[MODULE] Crafting 0.1 - Craft items in a second inventory window

Started by Khris, Wed 29/08/2012 17:58:59

Previous topic - Next topic

Khris

This module handles moving multiple inventory items to a secondary inventory window and combining them into a new item.

In order to use it:
1. Get the module here: DOWNLOAD  (DEMO VIDEO)

2. Import it into AGS by right clicking the Script node in the Project tree, selecting "Import script..." and choosing the file.

3. Add an InvWindow to a GUI in a way that the player can click it with an active InventoryItem as mouse cursor, then in its properties, name it something sensible like "InvCrafting". The easiest way to accomplish this is by adding it to the existing inventory GUI (gInventory).
Now add a dummy character to the game (or use an existing NPC) and set its ID as the InvWindow's CharacterID. (Don't use the player character!)

4. Add two buttons to a GUI. One is supposed to try and combine the selected items, the other is supposed to clear the selection. The buttons should have proper names, choose something like "btnCraft" and "btnCraftClear" or similar.

5. Create the click handler functions for the two buttons, either by double-clicking them or via their event pane.

6. In Globalscript.asc, find the two handler functions and link them to the module so the whole thing looks similar to this:
Code: ags
function btnCraftClear_OnClick(GUIControl *control, MouseButton button) {
  if (button == eMouseLeft) Crafting.Clear(false);   // <- false is crucial here
}

function btnCraft_OnClick(GUIControl *control, MouseButton button) {
  if (button == eMouseLeft) Crafting.Craft();
}

The latter one can of course contain additional code, for instance if the player is currently unable to craft items, the game could provide a message instead. Calling Crafting.Craft(); attempts to craft an item in the pool, regardless of other circumstances.

The following steps are all about adding commands to the game_start() function in GlobalScript.asc.

7. Some more preparation for the module is necessary; tell the module the names of the InvWindow, Craft and Clear Button:
Code: ags
  Crafting.SetGUIElements(InvCrafting, btnCraft, btnCraftClear);

(The buttons are disabled automatically if the crafting window is empty.)

8. Optionally, you can
a) allow the selection of multiple instances of the same item. Say building a box takes five pieces of wood, among other things. In order to not confuse the player, you should activate the following option in that case: General settings -> Inventory -> Display multiple icons for multiple items
Code: ags
  Crafting.SetMultipleAllowed(true);

b) change the default messages.
They are "You successfully craft a %s." and "You fail to craft anything."
Just call
Code: ags
  Crafting.SetMessages("success message here, include item name using %s", "failure message here");


9. Now the most important part: adding item recipes.
Start by adding the resulting InventoryItem:
Code: ags
  int box = Crafting.AddItem(iBox);

The function returns an index number that's used by the module to identify items. I've chosen this route because there might be multiple recipes producing the same item. (Store the returned integer in a global variable in order to be able to change or deactivate the recipe later in the game.*)
Using the value returned by the function, you can now add parts. Optionally, state the number of required parts, if it is greater than one:
Code: ags
  Crafting.AddPart(box, iGlue);
  Crafting.AddPart(box, iWood, 5);
  Crafting.AddPart(box, iHandle);

You can use that function to change the recipe later in the game, just call it with a different number as third parameter or 0 to remove the ingredient from the list of requirements altogether.

*To remove an item from the pool of possible items, use this function:
Code: ags
  Crafting.SetItem(box, null);

This will effectively remove the possibility to create the box from the game. You can of course also use this to change the resulting item; simply pass it to the function as second parameter.

Note: The player can move single items back to the main inventory by right-clicking them.

You can also check the requirement for an item in-game. If debug mode is activated, type !, then enter the number of the item. (The module's number, starting at 0, not AGS's inventory ID!)

ProTip: If you have lots of recipes, your game_start might get crowded. To avoid this:
Spoiler
Create a function above game_start containing all the crafting setup commands and call it in game_start, like this:
Code: ags
void prepare_crafting() {
  Crafting.SetGUIElements(InvCraft, btnCraft, btnCraftClear);
  Crafting.SetMultipleAllowed(true);

  int box = Crafting.AddItem(iBox);
  Crafting.AddPart(box, iGlue);
  Crafting.AddPart(box, iWood, 5);
  Crafting.AddPart(box, iHandle);
  ...
}

function game_start() {
  ...
  ...
  prepare_crafting();
}
[close]
I'd be grateful if people tested this and provided some feedback. This is pretty much a beta-version, so use at your own risk ;-D
The module can be altered freely, credit is welcome but not required.

Also, here's a short video demonstrating the module: http://www.youtube.com/watch?v=K4-ScC_nyhg

steptoe

It's not over until the fat lady sings..

Ghost

Sounds very interesting, I will surely try it out. The video is a nice touch by the way!

cRonald

I have some problem. I start new game, choose "Default Game" template, complete steps 1-8, add to inventory 2 items, and run the game.

When i open inventory window, it look like this:
Spoiler
[close]

When i try to drag and drop any item from the inventory to the crafting inventory, an error comes out:
Spoiler
[close]

Can you help me? What i did wrong?
Sorry for my bad english.

Khris

Yeah, sorry, I forgot to mention a pretty crucial step: the InvWindow has to be assigned to a different character, either some NPC or a dummy character that isn't used for anything else; the InvWindow can't also reflect the player's possessions since the two inventories need to be separate.
I've also added this to the instructions (step 3).

cRonald

 Thanks! Now all works perfect.
But i have another newbie question. If i want to add one more resulting InventoryItem to the same recipe. For example: item1+item2+item3 = item1, item4 and  item5.
What is the right way to do it?
Sorry for my bad english.

Khris

Good point, I haven't thought about producing more than one item.
For now, if either item 4 or 5 can't be obtained by any other means, you can add this to your GlobalScript.asc:
Code: ags
void on_event (EventType event, int data) {
  if (event == eEventAddInventory && data == iItem4.ID) {
    player.AddInventory(iItem1);
    player.AddInventory(iItem5);
  }
}


This is just a workaround; I'll amend the module soon.

Ghost

It would be very convenient to have a "recipe book" button (or maybe a listbox that holds all recipes the player knows about), with the option to click on a recipe and have the item crafted. May sound like overkill, but I think it would make a pretty neat extra feature :)

Khris

I was thinking about implementing something like that while writing the module, but it would have rendered about 70% of the module obsolete.
It really comes down to game design, I guess.
If the player gathers lots and lots of ingredients and recipes, and has to craft certain items frequently, this system is pretty uncomfortable and tedious. It's more of an "solve an item combination puzzle" thing than to be used in an RPG.

Slasher

Yeah,

it's like the old mixing bowl scenario you used to get in games where you needed to put in a few ingredients and mix to make a solution needed for a puzzle. This worked fine. However, too many can become tedious to say the least, especially if they had to be in an order.

Ghost suggested having a "recipe book" button, that seems a good idea if you have many items.

Putting the player in 'total control' of his actions is all well and good, but if this mixing of items is throughout the game then it could become dull and laborious. I think that 4 items is enough at any 1 time and 1 - 3 times in the game is ok.

Remember Tomb Raider, putting a couple of items togther to make a key?

If you have to find say 6 items to build an object and you have all 6 then making the object with a 'build' button is, I feel, very satisfying. Using Khris' module to put the objects into another pane and then building automatically is definitely a bonus and I'm sure it would delight the player having succeeded that task.

Mind you, if the player has this, that and the other then show this inv and delete the others could do the job at the moment.

I would like to see how Khris develops this module.

Thumbs up

(nod)


cRonald

Quote from: Khris on Thu 30/08/2012 17:24:37
I'll amend the module soon.
I'm looking forward to. Because workaround not fit for my game.

About recipe book. It`s a good idea, but i think not necessary. If I understand correctly, recipe book required in games, when player needs to repeat one recipe over and over. Playing in that kind of games, i think, will be boring.
Sorry for my bad english.

Dualnames

Wonderful module, people seem to be gracing its usefulness so far. Please do consider adding your module here, http://www.adventuregamestudio.co.uk/wiki/?title=Module_IndexCategory
Worked on Strangeland, Primordia, Hob's Barrow, The Cat Lady, Mage's Initiation, Until I Have You, Downfall, Hunie Pop, and every game in the Wadjet Eye Games catalogue (porting)

Construed

Wow Khris, This is just absolutely awesome! Thank you so very much!

I used it to create a potion crafting table where you can make a dispel potion to transform a man who was cursed to be a cactus and will use it to make many more potions, I will also likely use it for crafting various other objects and materials :D

Works perfectly!
I felt sorry for myself because I had no shoes.
Then I met the man with no feet.

Ewery1


Construed

Hey Khris,
I'm trying to make a recepie where you can mix 3 "hpot" to make an "elixer" and it keeps throwing me errors, I'm sure I had a grammatical error here.

Code: ags

 int elixer = Crafting.AddItem(elixer);
 Crafting.AddPart(elixer, hpot, 3);
I felt sorry for myself because I had no shoes.
Then I met the man with no feet.

Khris

I assume that "elixer" is the inventory item, right? (Shouldn't that be "iElixir"?)

You can't use it as handler integer, too, you need a separate variable:

Code: ags
  int elix = Crafting.AddItem(elixer);
  Crafting.AddPart(elix, hpot, 3);


The AddItem function accepts an inventory item but returns an internal index number. That's what you need to pass to AddPart.

Construed

I felt sorry for myself because I had no shoes.
Then I met the man with no feet.

SMF spam blocked by CleanTalk