Adventure Game Studio

AGS Support => Beginners' Technical Questions => Topic started by: wynni2 on Thu 09/03/2017 14:29:26

Title: simple question about changing values in custom structs
Post by: wynni2 on Thu 09/03/2017 14:29:26
Sorry for a such a basic question, but I'm clearly missing something.  I have an array of the struct Cstat, which contains some character stats for my game.  For simplicity's sake, I'll focus on "int aggression." 

I have a command to return aggression, which works fine:

Code (ags) Select

int Aggression(this Character*) {
return Cstat[this.ID].aggression;
}

if (this.Aggression() > 10) this.Attack();


If I want to increase the character's aggression level I know how to use the script o-name:

Code (ags) Select

Cstat[this.ID].aggression ++;


What I don't understand is how / if I can write a custom function allowing me to do this:

Code (ags) Select

this.Aggression ++;


I assume I have to use a method within the struct, but I'm a novice coder and the wiki/manual aren't 100% clear on implementing methods within structs. 

I'm using AGS v 3.3, BTW.

Thanks.
Title: Re: simple question about changing values in custom structs
Post by: dayowlron on Thu 09/03/2017 16:34:14
I am not sure if you can do extender functions on structures.

I can tell you if you can, just wondering what is the name of the structure?
I see the occurrence is named Cstat. Lets say the struction is Cstatstruct then from a programming standpoint the code would look something like this:

function IncreaseAggression(this Cstatstruct*) {
    this.aggression ++;
}

The you would call it like this

  IncreaseAggression(Cstat[x]);
Title: Re: simple question about changing values in custom structs
Post by: Khris on Thu 09/03/2017 17:21:34
It all comes down to what the this is referring to. It looks as if you're lumping together custom structs and extender functions, at least in your question.

First of all, you cannot add variables to built-in structs like Character, only functions (at least afaik, unless it was added very recently)

The common workaround is a pair called getter and setter:

int getAggression(this Character*) {
  return Cstat[this.ID].aggression;
}

void setAggression(this Character*, int val) {
  Cstat[this.ID].aggression = val;
}


So increasing the aggression by one in another extender function would look like this:
  Cstat[this.ID].setAggression(Cstat[this.ID].getAggression() + 1);

You could also use this:
void changeAggressionBy(this Character*, int val) {
  Cstat[this.ID].aggression += val;
}


That way you can shorten it to   Cstat[this.ID].changeAggressionBy(1); // add 1and pass negative values to lower it.


All of this is still pretty ugly, but you can simply use a completely different approach: use a custom struct with functions, and store the AGS character in it:

struct Person {
  int aggression;
  int hunger;
  ...
  Character *ac;
  import void DoStuff();
};


Now you can simply do this:

Person person[50];

// this instead of extender functions
void Person::DoStuff() {
  if (this.aggression < 10) this.aggression++;
  ...
}

// to actually call an AGS command on the character, simply use the pointer stored in the instance:
function x() {
  person[1].ac = cEgo;
  person[1].aggression++;
  // now we want the AGS character:
  person[1].ac.Walk(150, 100);
}
Title: Re: simple question about changing values in custom structs
Post by: Crimson Wizard on Thu 09/03/2017 18:44:45
I think I'll mention, as a potential alternative for certain cases, that since 3.4.0 you can change custom property values at runtime, which allows to use them as "extender variables".

You need to create Property Schema in your game first, by opening, e.g., character for editing and clicking on "Properties" property, and then on "Edit schema..." button. There you create any number of properties you want your game objects have.
The main limitation here is that these properties may only be integer, bool or string. Another thing is that you cannot group these properties, but have just one big list of them.

Later in game you use these properties as:
Code (ags) Select

int num = cMyCharacter.GetProperty("SomeCustomNumber");
cMyCharacter.SetTextProperty("HowShouldIBeCalled", "George");