Author Topic: Custom Structs and functions  (Read 574 times)

Legacy_henesua

  • Hero Member
  • *****
  • Posts: 6519
  • Karma: +0/-0
Custom Structs and functions
« on: July 15, 2011, 04:12:04 am »


               I am creating a custom struct so as to return it from various functions. 

Is this the right way to set up the function declaration for a function that returns the entire struct?

//establish struct
struct NPC
{
      int foo1;
      int foo2;
};

// define function
struct NPC GetCreatureData(object oCreature);

correct?
               
               

               


                     Modifié par henesua, 15 juillet 2011 - 03:14 .
                     
                  


            

Legacy_FunkySwerve

  • Hero Member
  • *****
  • Posts: 2325
  • Karma: +0/-0
Custom Structs and functions
« Reply #1 on: July 15, 2011, 04:30:01 am »


               Yup. Then, when used in another function,

struct NPC somename = GetCreatureData(oSomeCritter);
int nSomeInt = somename.foo1;

Just think of 'struct NPC' as being the same as another datatype, like 'int' or 'string' - just one that you defined yourself.

Funky
               
               

               
            

Legacy_henesua

  • Hero Member
  • *****
  • Posts: 6519
  • Karma: +0/-0
Custom Structs and functions
« Reply #2 on: July 15, 2011, 06:25:34 am »


               Thanks. I got thrown off course when I tried

NPC GetCreatureData(object oCreature);

and it threw me errors. so I added struct as well at the beginning as an experiment.. but wanted confirmation that this was copacetic.
               
               

               
            

Legacy_CID-78

  • Sr. Member
  • ****
  • Posts: 261
  • Karma: +0/-0
Custom Structs and functions
« Reply #3 on: July 15, 2011, 07:12:19 am »


               you are still lacking the function declaration, you only have the prototype.

also there was some issues with passing in structs in the NWN/NWN2 compiler, if it doesn't work try a external compiler.

but i think it was when i tried nested structs. don't really recall.
               
               

               
            

Legacy_Xardex

  • Sr. Member
  • ****
  • Posts: 414
  • Karma: +0/-0
Custom Structs and functions
« Reply #4 on: July 15, 2011, 11:10:32 am »


               I found this useful: http://nwn.wikia.com...ction_to_struct

Though, really, I have never had any real use for structs.
               
               

               
            

Legacy_henesua

  • Hero Member
  • *****
  • Posts: 6519
  • Karma: +0/-0
Custom Structs and functions
« Reply #5 on: July 15, 2011, 03:53:51 pm »


               Considering NWN's limitations with variables/data, I find STRUCTS useful. The code above was just a dummy so as to focus on what I wanted to understand.

I doubt this is of interest to many but I'll share what i am doing with STRUCTS. Rather than just use NESS to handle my spawns, I decided to write my own spawning code. With STRUCTS I can track the state of the creatures I am spawning. In the mod I am writing, I have a creature which spawns and despawns a few times, and I wanted to track their hitpoints in a data object as well as control whether or not they would spawn (eg. no spawning if they are dead). This is for a single player mod. i'm sure there are better ways to do this, but I like to roll my own code so as to get better at this.


// STRUCTS
struct NPC
{
    // these are used for unique individuals
    int bUnique;         // TRUE = NPC is an individual
    int nHP;             // track hitpoints
    object oSelf;        // object identifier

    // these are used by both individuals and populations
    object oData;
    int nDeaths;         // track deaths
    int nLives;          // maximum deaths. 0 == unlimited.
    int nSpawned;        // track spawns. count of how many currently spawned.

    // these are used by populations
    int nSpawn_limit;    // maximum spawns at once in the area. 0 == untracked.
};

// SUB FUNCTIONS ---------------------------------------------------------------

void SpawnCreature(string sRef, location lSpawn);

struct NPC GetCreatureData(object oCreature);

int InitializeCreature(struct NPC Creature);

void SpawnCreature(string sRef, location lSpawn)
{
    object oCreature    = CreateObject(OBJECT_TYPE_CREATURE, sRef, lSpawn, TRUE, sRef);
    struct NPC Creature   = GetCreatureData(oCreature); // load data from data object
    if(GetIsObjectValid(Creature.oData) && !InitializeCreature(Creature))
        DestroyObject(oCreature);
}

struct NPC GetCreatureData(object oCreature)
{
    struct NPC Creature;
    object oData            = GetObjectByTag("data_"+GetTag(oCreature));

    Creature.oSelf          = oCreature;
    Creature.oData          = oData;

    if (!GetIsObjectValid(oData))
    {
        if(DEBUG) SpeakString("data object not found", TALKVOLUME_SHOUT);
        return Creature;
    }

    Creature.bUnique        = GetLocalInt(oData,"bUnique");
    Creature.nHP            = GetLocalInt(oData,"nHP");
    Creature.nDeaths        = GetLocalInt(oData,"nDeaths");
    Creature.nLives         = GetLocalInt(oData,"nLives");
    Creature.nSpawned       = GetLocalInt(oData,"nSpawned");
    Creature.nSpawn_limit   = GetLocalInt(oData,"nSpawn_limit");

    return Creature;
}

int InitializeCreature(struct NPC Creature)
{
    if ( Creature.bUnique )
    {
        if (Creature.nDeaths == 0 && Creature.nSpawned == 0)
        {
            int nMaxHP = GetMaxHitPoints(Creature.oSelf);
            if ( Creature.nHP > 0 && Creature.nHP < nMaxHP )
            {
                int nDamage = nMaxHP - Creature.nHP;
                ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDamage(nDamage), Creature.oSelf);
            }
            SetLocalInt(Creature.oData, "nSpawned", ++Creature.nSpawned);
            return TRUE;
        }

        return FALSE; // creature is dead or already spawned
    }
    else if(
            (Creature.nDeaths < Creature.nLives || Creature.nLives == 0)
                &&
            (Creature.nSpawned < Creature.nSpawn_limit || Creature.nSpawn_limit == 0)
           )
    {
        if(Creature.nSpawn_limit != 0) // we are tracking spawns
            SetLocalInt(Creature.oData, "nSpawned", ++Creature.nSpawned);
        return TRUE;
    }

    return FALSE; // population is exhausted
}


pastebin: http://pastebin.com/MJT7XfiC
               
               

               


                     Modifié par henesua, 15 juillet 2011 - 03:01 .
                     
                  


            

Legacy_CID-78

  • Sr. Member
  • ****
  • Posts: 261
  • Karma: +0/-0
Custom Structs and functions
« Reply #6 on: July 15, 2011, 08:17:30 pm »


               don't see any problem with your code or your approach to a spawning system. it's a simple respawn system with a limited population.
               
               

               
            

Legacy_henesua

  • Hero Member
  • *****
  • Posts: 6519
  • Karma: +0/-0
Custom Structs and functions
« Reply #7 on: July 16, 2011, 12:39:33 am »


               Here's an actual working version of the code ripped from my master include. The previous version was not complete, inadequately documented, and didn't create a data object if one was missing.


// STRUCTS ---------------------------------------------------------------------

// used in a custom spawn system which associates a data object with the creature
struct NPC
{
    // these are used for unique individuals
    int bUnique;         // TRUE = NPC is an individual
    int nHP;             // track hitpoints
    object oSelf;        // object_self identifier

    // these are used by both individuals and populations
    object oData;        // identifies the data object
    int nDeaths;         // track deaths
    int nSpawned;        // track spawns. count of how many currently spawned.

    // these are used by populations
    int nLives;          // maximum deaths. 0 == unlimited.
    int nSpawn_limit;    // maximum spawns at once in the area. 0 == untracked.
};

// FUNCTION DECLARATIONS -------------------------------------------------------

// utility funcs ---------------------------------------------------------------

// Spawns a creature associated with data object. See: Struct NPC - [FILE: aa_inc_master]
void SpawnCreature(string sRef, location lSpawn, int bAppear = FALSE, string sTag = "");
// Called by SpawnCreature  - [FILE: aa_inc_master]
// returns data stored on an object associated with a creature. See: Struct NPC
struct NPC GetCreatureData(object oCreature);
// Called by SpawnCreature  - [FILE: aa_inc_master]
// creates a data object (as waypoint) associated with a creature.
// if creature's tag != resref, assume creature is unique individual
// sets up NPC struct and returns. See: Struct NPC
struct NPC CreateObjectCreatureData(object oCreature);
// Called by SpawnCreature  - [FILE: aa_inc_master]
// Returns TRUE if creature spawn should continue. FALSE if conditions not met. See: Struct NPC
int InitializeCreature(struct NPC Creature);

void SpawnCreature(string sRef, location lSpawn, int bAppear = FALSE, string sTag = "")
{
    object oCreature    = CreateObject(OBJECT_TYPE_CREATURE, sRef, lSpawn, bAppear, sTag);
    struct NPC Creature   = GetCreatureData(oCreature); // load data from data object
    if(!GetIsObjectValid(Creature.oData))
    {
        WriteTimestampedLogEntry("SpawnCreature() - "+GetTag(oCreature)+": data object was NOT FOUND"); // Logging
        Creature = CreateObjectCreatureData(oCreature);
    }
    else if (!InitializeCreature(Creature))
        DestroyObject(oCreature);
}

struct NPC GetCreatureData(object oCreature)
{
    struct NPC Creature;
    object oData            = GetObjectByTag("data_"+GetTag(oCreature));

    Creature.oSelf          = oCreature;
    Creature.oData          = oData;

    if (!GetIsObjectValid(oData))
        return Creature;

    Creature.bUnique        = GetLocalInt(oData,"bUnique");
    Creature.nHP            = GetLocalInt(oData,"nHP");
    Creature.nDeaths        = GetLocalInt(oData,"nDeaths");
    Creature.nLives         = GetLocalInt(oData,"nLives");
    Creature.nSpawned       = GetLocalInt(oData,"nSpawned");
    Creature.nSpawn_limit   = GetLocalInt(oData,"nSpawn_limit");

    return Creature;
}

struct NPC CreateObjectCreatureData(object oCreature)
{
    struct NPC Creature;
    string sTag = GetTag(oCreature);
    string sRef = GetResRef(oCreature);

    WriteTimestampedLogEntry("CreateObjectCreatureData() - "+sTag); // logging

    string sDataRef = "";

    object oData = CreateObject(OBJECT_TYPE_WAYPOINT, sDataRef, GetLocation(oCreature), FALSE, "data_"+sTag);

    if (sTag != sRef) // assume creature is unique
    {
        Creature.bUnique = TRUE;
        SetLocalInt(oData, "bUnique", Creature.bUnique);
        Creature.nHP = GetMaxHitPoints(oCreature);
        SetLocalInt(oData, "nHP", Creature.nHP);
    }

    Creature.oSelf = oCreature;
    SetLocalObject(oData, "oSelf", oCreature);
    Creature.oData = oData;
    SetLocalObject(oCreature, "oData", oData);

    return Creature;
}

int InitializeCreature(struct NPC Creature)
{
    if ( Creature.bUnique )
    {
        if (Creature.nDeaths == 0 && Creature.nSpawned == 0)
        {
            int nMaxHP = GetMaxHitPoints(Creature.oSelf);
            if ( Creature.nHP > 0 && Creature.nHP < nMaxHP )
            {
                int nDamage = nMaxHP - Creature.nHP;
                ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDamage(nDamage), Creature.oSelf);
            }
            SetLocalInt(Creature.oData, "nSpawned", ++Creature.nSpawned);
            return TRUE;
        }

        return FALSE; // creature is dead or already spawned
    }
    else if(
            (Creature.nDeaths < Creature.nLives || Creature.nLives == 0)
                &&
            (Creature.nSpawned < Creature.nSpawn_limit || Creature.nSpawn_limit == 0)
           )
    {
        if(Creature.nSpawn_limit != 0) // we are tracking spawns
            SetLocalInt(Creature.oData, "nSpawned", ++Creature.nSpawned);
        return TRUE;
    }

    return FALSE; // population is exhausted
}

               
               

               
            

Legacy_henesua

  • Hero Member
  • *****
  • Posts: 6519
  • Karma: +0/-0
Custom Structs and functions
« Reply #8 on: July 18, 2011, 04:08:36 am »


                Improved version on the vault:
http://nwvault.ign.c....Detail&id=3821