More efficient way to script [clandestine] chemistry into AGS

Started by ty3194, Wed 25/07/2012 09:47:20

Previous topic - Next topic

ty3194

I spent several hours making this half-finished system in order to perform chemistry (albeit a novice form) but am now wondering if there is a simpler, less redundant and time-consuming method... Here is my code:

Code: AGS
// CHEMISTRY



// DXM EXTRACTION



//USES iNH3 ON iRobo IF POSSIBLE
function iNH3_UseInv(){
if (player.ActiveInventory == iRobo){ 
Display ("You basify 30mL of cough syrup with 30mL of ammonia.");
  player.InventoryQuantity[iNH3.ID] -= 30;
  player.InventoryQuantity[iRobo.ID] -= 30;
  player.AddInventory(iSyr_Amm);
  player.InventoryQuantity[iSyr_Amm.ID] += 59;
  }  
}


 //USES iRobo ON iNH3 IF POSSIBLE
function iRobo_UseInv(){
if (player.ActiveInventory == iNH3) {
Display ("You basify 30mL of cough syrup with 30mL of ammonia.");
  player.InventoryQuantity[iNH3.ID] -= 30;
  player.InventoryQuantity[iRobo.ID] -= 30;
  player.AddInventory(iSyr_Amm);
  player.InventoryQuantity[iSyr_Amm.ID] += 59;
  }  
}


// INSPECTS iRobo+iNH3 FLASK
function iSyr_Amm_Look(){
Display ("A flask filled with %dmL of ammonia and cough syrup", player.InventoryQuantity[iSyr_Amm.ID]);
}


// ADD 5mL OF iNaphtha TO FLASK OF 30mL iRobo+iNH3 IN POSSIBLE
function iNaphtha_UseInv() 
{
if (player.InventoryQuantity[iSyr_Amm.ID] > 0){
Display ("You add 5mL of naphtha to 30ml of the ammonia/syrup");
  player.InventoryQuantity[iNaphtha.ID] -= 5;
  player.InventoryQuantity[iSyr_Amm.ID] -= 30;
  player.AddInventory(iSyr_Amm_Nap);
  player.InventoryQuantity[iSyr_Amm_Nap.ID] += 34;
}
else{
  if (player.InventoryQuantity[iSyr_Amm.ID] < 1){
    player.LoseInventory (iSyr_Amm);
    }
  }
}


// ADD 5mL OF iNaphtha TO FLASK OF 30mL iRobo+iNH3 IF POSSIBLE
function iSyr_Amm_UseInv()
{
if (player.InventoryQuantity[iSyr_Amm.ID] > 0){
Display ("You add 5mL of naphtha to 30ml of the ammonia/syrup");
  player.InventoryQuantity[iNaphtha.ID] -= 5;
  player.InventoryQuantity[iSyr_Amm.ID] -= 30;
  player.AddInventory(iSyr_Amm_Nap);
  player.InventoryQuantity[iSyr_Amm_Nap.ID] += 34;
}
else{
  if (player.InventoryQuantity[iSyr_Amm.ID] < 1){
    player.LoseInventory (iSyr_Amm);
    }
  }
}


// INSPECTS iRobo+iNH3+iNaphtha FLASK
function iSyr_Amm_Nap_Look()
{
 Display ("A flask filled with an %dmL of an immiscible mixture of ammonia/ cough syrup and naphtha at 30mL:5mL", player.InventoryQuantity[iSyr_Amm_Nap.ID]);
}


Khris

Maybe if you came up with a generic way to handle combinations of chemicals, which is possible. You'd need to store possible combinations in a struct array (i.e. database table) and check if the attempted combinations matches any.

Regarding your code though: Add/LoseInventory do nothing other than in/decrease InventoryQuantity by one. So there's no need to add, then increase by 59, just add 60; and "if quantity < 1 loseinventory" is completely redundant.

Also, while you're checking player.ActiveInventory in the first function, you stop doing it in the other ones. You need to check the quantity in addition to which item was used, not instead of.

ty3194

Quote from: Khris on Wed 25/07/2012 11:00:36
"You'd need to store possible combinations in a struct array (i.e. database table)"

Thanks for the tip.

Quote from: Khris on Wed 25/07/2012 11:00:36
"Regarding your code though: Add/LoseInventory do nothing other than in/decrease InventoryQuantity by one. So there's no need to add, then increase by 59, just add 60; and "if quantity < 1 loseinventory" is completely redundant.

At first I was using both "player.AddInventory(iItem)" and "player.InventoryQuantity[iItem] += 59" because I was having problems with the item appearing in inventory, but I later found that to be caused by a lack of "UpdateInventory()" afterwards.

And I was using "if quantity < 1 loseinventory" because without it problems would occur with using items with zero quantity, but it was later concluded to be a result of using "if (player.InventoryQuantity[iItem.ID] > 0)" instead of "if (player.ActiveInventory == iItem)" and was promptly fixed.

Quote from: Khris on Wed 25/07/2012 11:00:36
Also, while you're checking player.ActiveInventory in the first function, you stop doing it in the other ones. You need to check the quantity in addition to which item was used, not instead of.

Could you expand on this?


EDIT: I'm having trouble figuring how to incorporate my chemistry scripts into a struct array. The dynamic help is vague.. perhaps this is a start but what would it afford me:
Code: AGS
// at top of script
Chem chems[300];
// inside script function
chems[0].damage = 10;
chems[0].price = $3;
chems[0].name = "960mL Ammonia";
chems[1].damage = 20;
chems[1].price = $5;
chems[1].name = "300mL Naphtha";


Also, is there a way to use this script array to avoid creating several different inventory items during chemistry, as each game can only contain 300 items and they will surely fill fast if not.

geork

Quote
QuoteAlso, while you're checking player.ActiveInventory in the first function, you stop doing it in the other ones. You need to check the quantity in addition to which item was used, not instead of.

Could you expand on this?
As in: in some of your functions you are checking what the players active inventory is, but in some of them you are not. It's probably best to check this in all combining objects functions.

QuoteAlso, is there a way to use this script array to avoid creating several different inventory items during chemistry, as each game can only contain 300 items and they will surely fill fast if not.

Yes, absolutely, and this is where structs can come in handy. Instead of having 30 inventory items for a single chemical, have one, and attach the amount of the chemical onto a variable. So for example, instead of:
Code: AGS
player.InventoryQuantity[iItem] += 60;
UpdateInventory();
 
have:
Code: AGS
player.AddInventory(iItem);
chems[iItem.ID].quantity += 60; // Have the chems ID match the item ID, it makes everything super simple

You can always check whether the quantity becomes 0, in which case the player should lose that inventory item.

As a general rule (probably a general rule, anyway) - if you have lots of repeated code you can usually stick that into your own function and call it with specific parameters. as far as I can see, every time you lose two chemicals and gain one, with a message, so you could write a function:
Code: AGS
function MixChems(InventoryItem *item1, InventoryItem *item2, InventoryItem *product){
  int ProductAmount = chems[item1.ID].quantity + chems[item2.ID]; //so you get how much chemical is made
  chems[item1.ID].quantity = 0;
  player.LoseInventory(item1);
  chems[item2.ID].quantity = 0;
  player.LoseInventory(item2);
  if(chems[produce.ID].quantity == 0) player.AddInventory(produce); // in case the player already has it
  chems[produce.ID].quantity += ProductAmount;
}
//other code
function iNH3_UseInv(){
  if (player.ActiveInventory == iRobo){
  Display ("You basify 30mL of cough syrup with 30mL of ammonia.");
  MixChems(iNH3, iRobo, iSyr_Amm); //Call the function
 }
}  //etc. etc.

You'll find that creating functions like these should save you a lot of time

Hope that helps!

ty3194

Quote from: geork on Sat 28/07/2012 21:53:05
As in: in some of your functions you are checking what the players active inventory is, but in some of them you are not. It's probably best to check this in all combining objects functions.

Thanks, now I understand, I made them all into player.ActiveInventory == #

Quote from: geork on Sat 28/07/2012 21:53:05
Yes, absolutely, and this is where structs can come in handy. Instead of having 30 inventory items for a single chemical, have one, and attach the amount of the chemical onto a variable. So for example, instead of:
Code: AGS
player.InventoryQuantity[iItem] += 60;
UpdateInventory();
 
have:
Code: AGS
player.AddInventory(iItem);
chems[iItem.ID].quantity += 60; // Have the chems ID match the item ID, it makes everything super simple

You can always check whether the quantity becomes 0, in which case the player should lose that inventory item.

This helps in a way but doesn't really help how I needed because you are still using "player.AddInventory(iItem);" and the game can only have a total of 300 iItems. I'm talking about a way one could avoid several items for each different stage of a reaction such as iRobo (cough syrup), iSyr_Amm (syrup and ammonia), iSyr_Amm_Nap (syrup, ammonia, and naphtha), etc...

And for that code, how would that help? Wouldn't I have to call that for every step of the extraction since it discusses mixing 2 specific chems with each other to make a 3rd? And would I still have to use it twice so that you can use both items to start the reaction as in:

Code: AGS

//USES iNH3 ON iRobo IF POSSIBLE
function iNH3_UseInv(){
if (player.ActiveInventory == iRobo){


AND

Code: AGS

//USES iRobo ON iNH3 IF POSSIBLE
function iRobo_UseInv(){
if (player.ActiveInventory == iNH3) {

Khris

Sorry for the late reply.
When I said "use a struct array", what I meant wasn't to store the individual chemicals but the possible reactions:
Code: ags
struct ChemReaction {
  InventoryItem*a, b;
  int amount_a, amount_b;
  InventoryItem*result;
  int amount_result;
};


Now when two inventory items are combined, the game iterates through the struct data to find a possible match.

geork

Sorry for the late reply, I hope I'm still in time!

QuoteThis helps in a way but doesn't really help how I needed because you are still using "player.AddInventory(iItem);" and the game can only have a total of 300 iItems. I'm talking about a way one could avoid several items for each different stage of a reaction such as iRobo (cough syrup), iSyr_Amm (syrup and ammonia), iSyr_Amm_Nap (syrup, ammonia, and naphtha), etc...

Oops, sorry, I misunderstood that :S Not that I can see: But there are ways to circumnavigate this problem. The easiest I can see is, instead of having 1 item per chemical, is to have maybe 10 items called iChemical1, iChemical2 etc. etc. and then assign they're names, properties, quanties and so on via either item properties or structs (personally I prefer structs, as you may have noticed :P) for each game. So in game 1, iChemical1 would by Robo, iChemical2 would be NH3 or whatever you assign to them. This way you can have potentially limitless number of chemicals.
This approach needs something along the lines of Khris' code to function however. Although instead of checking InventoryItems, you'd instead check Chemical Names (Strings).

QuoteAnd for that code, how would that help? Wouldn't I have to call that for every step of the extraction since it discusses mixing 2 specific chems with each other to make a 3rd? And would I still have to use it twice so that you can use both items to start the reaction

@(Anyone) is it possible to use an unhandled_event(5,3) function (i.e use inventory on another) and still know both items involved?
Otherwise: I can see no way of minimizing on that, you'll have to use both functions. Or you could find another way around. For example you could make a GUI which displays the inventory items you click on with a "combine" button - that way you only have one function to put everything in (the one that's linked to the button)

I hope that helps! Tell me if I should be clearer (Sometimes things make sense in my head but not on paper, as it were... :S apologies in advance)

SMF spam blocked by CleanTalk