Author Topic: Scripting Isn't a Spectator Sport  (Read 901 times)

Legacy_One Thousand Talons Mao Ra

  • Jr. Member
  • **
  • Posts: 66
  • Karma: +0/-0
Scripting Isn't a Spectator Sport
« on: November 13, 2010, 01:06:03 am »


               Alright folks. I'm at my wit's end. I've been working on these two scripts for a month. It's a nightmare!

Here's what I'm trying to create. It's gonna sound complex, but it ain't. I have a colosseum, and I wanna spawn random gladiator battles between three schools to watch whenever a player is in the area. I based spawning the fights off of the area's heartbeat event, and ending the fights on the actual gladiator's death event. Spawning the fight works great, but it only spawns one fight, and stops. I need someone to comb through this and show me why this fails.

Here's the area heartbeat script (all the random fights are the same right now, ignore that. I wanna create that after the system works)...


//Put this script in Area OnHeartbeat event
#include "nw_i0_2q4luskan"
void main()
{
object oTarget;
oTarget = GetArea(OBJECT_SELF);
if (GetLocalInt(oTarget, "Spectate Colosseum Go")== 0)
   return;
if (GetLocalInt(oTarget, "Gladiators In Game")>= 1)
   return;

oTarget = GetObjectByTag("NorthGameGate");
SetLocked(oTarget, FALSE);
AssignCommand(oTarget, ActionOpenDoor(oTarget));
DelayCommand(10.0, AssignCommand(oTarget, ActionCloseDoor(oTarget)));
DelayCommand(11.0, SetLocked(oTarget, TRUE));
oTarget = GetObjectByTag("SouthGameGate");
SetLocked(oTarget, FALSE);
AssignCommand(oTarget, ActionOpenDoor(oTarget));
DelayCommand(10.0, AssignCommand(oTarget, ActionCloseDoor(oTarget)));
DelayCommand(11.0, SetLocked(oTarget, TRUE));
location lTarget;
  switch( Random( 4 ))
  { case 0: SetLocalInt(OBJECT_SELF, "Gladiators In Game", 4);
            oTarget = GetWaypointByTag("NorthColosseumSpawn");
            lTarget = GetLocation(oTarget);
            CreateObject(OBJECT_TYPE_CREATURE, "carpathian", lTarget);
            DelayCommand(2.0, CreateObjectVoid(OBJECT_TYPE_CREATURE, "carpathian", lTarget));
            oTarget = GetWaypointByTag("SouthColosseumSpawn");
            lTarget = GetLocation(oTarget);
            CreateObject(OBJECT_TYPE_CREATURE, "sacrentian", lTarget);
            DelayCommand(2.0, CreateObjectVoid(OBJECT_TYPE_CREATURE, "sacrentian", lTarget));
            break;
    case 1: SetLocalInt(OBJECT_SELF, "Gladiators In Game", 4);
            oTarget = GetWaypointByTag("NorthColosseumSpawn");
            lTarget = GetLocation(oTarget);
            CreateObject(OBJECT_TYPE_CREATURE, "carpathian", lTarget);
            DelayCommand(2.0, CreateObjectVoid(OBJECT_TYPE_CREATURE, "carpathian", lTarget));
            oTarget = GetWaypointByTag("SouthColosseumSpawn");
            lTarget = GetLocation(oTarget);
            CreateObject(OBJECT_TYPE_CREATURE, "sacrentian", lTarget);
            DelayCommand(2.0, CreateObjectVoid(OBJECT_TYPE_CREATURE, "sacrentian", lTarget));
            break;
    case 2: SetLocalInt(OBJECT_SELF, "Gladiators In Game", 4);
            oTarget = GetWaypointByTag("NorthColosseumSpawn");
            lTarget = GetLocation(oTarget);
            CreateObject(OBJECT_TYPE_CREATURE, "carpathian", lTarget);
            DelayCommand(2.0, CreateObjectVoid(OBJECT_TYPE_CREATURE, "carpathian", lTarget));
            oTarget = GetWaypointByTag("SouthColosseumSpawn");
            lTarget = GetLocation(oTarget);
            CreateObject(OBJECT_TYPE_CREATURE, "sacrentian", lTarget);
            DelayCommand(2.0, CreateObjectVoid(OBJECT_TYPE_CREATURE, "sacrentian", lTarget));
            break;
    case 3: SetLocalInt(OBJECT_SELF, "Gladiators In Game", 4);
            location lTarget;
            oTarget = GetWaypointByTag("NorthColosseumSpawn");
            lTarget = GetLocation(oTarget);
            CreateObject(OBJECT_TYPE_CREATURE, "carpathian", lTarget);
            DelayCommand(2.0, CreateObjectVoid(OBJECT_TYPE_CREATURE, "carpathian", lTarget));
            oTarget = GetWaypointByTag("SouthColosseumSpawn");
            lTarget = GetLocation(oTarget);
            CreateObject(OBJECT_TYPE_CREATURE, "sacrentian", lTarget);
            DelayCommand(2.0, CreateObjectVoid(OBJECT_TYPE_CREATURE, "sacrentian", lTarget));
            break;
  }
}

Of course, in the area's on enter and on exit I have...

//Put this script in Area OnEnter event
void main()
{
object oTarget;
oTarget = GetArea(OBJECT_SELF);
SetLocalInt(oTarget, "Spectate Colosseum Go", 1);
}

And...

//Put this script in Area OnExit event
void main()
{
object oTarget;
oTarget = GetArea(OBJECT_SELF);
SetLocalInt(oTarget, "Spectate Colosseum Go", 0);
}

In the gladiator's on spawn I added ActionMoveToObject(GetObjectByTag("ArenaCenter")); so they move together and the hostile factions scrap. This works fine. I may change this to a walkwaypoints later. All gladiator's currently share the same tag.

This is where my real problems are, I suspect. The gladiators' on death script...

// Gladiator's OnDeath script by Robert Donald Paiser
void main()
{
ExecuteScript("nw_c2_default7", OBJECT_SELF);

object oArea;
oArea = GetArea(GetNearestObjectByTag("ArenaCenter"));
int nInt;
nInt = GetLocalInt(oArea, "Gladiators In Game");
nInt -= -1;
SetLocalInt(oArea, "Gladiators In Game", nInt);
object oKiller;
object oSpectater;
object oSgate;
oSgate = GetObjectByTag("SouthGameGate");
oKiller = GetLastKiller();
int iSpectaters = 1;
while (iSpectaters <= 15)
    {
    iSpectaters++;
        oSpectater = GetNearestCreature(CREATURE_TYPE_IS_ALIVE, 4, oKiller);
        if (GetIsEnemy(oSpectater, oKiller))
        return;
    SetLocked(oSgate, FALSE);
    AssignCommand(oSgate, ActionOpenDoor(oSgate));
    DelayCommand(20.0, AssignCommand(oSgate, ActionCloseDoor(oSgate)));
    DelayCommand(20.0, SetLocked(oSgate, TRUE));
    AssignCommand(oKiller, ClearAllActions());
    AssignCommand(oKiller, ActionMoveToObject(GetObjectByTag("SouthGameExit")));
    AssignCommand(oKiller, ActionJumpToObject(GetObjectByTag("BigExit")));
    DelayCommand(30.0, SetLocalInt(oArea, "Gladiators In Game", 0));
    }
}

Right now, only one gladiator actually leaves the arena after the fight. I understand why, and that I will probably require another loop to fix it, but I wanna make this first loop work first. The gates never close and, as I said, only one fight spawns in.

Secondary questions...
Is there a way, while within a loop, to kick out of the entire script similar to the way 'return' does outside of the loop?
In the 'GetNearestCreature', the second criteria is aparently mandatory but what in the Nine Hells does it mean? I don't understand it. I threw ''4'' in there just to make it compile.

               
               

               
            

Legacy__Knightmare_

  • Full Member
  • ***
  • Posts: 191
  • Karma: +0/-0
Scripting Isn't a Spectator Sport
« Reply #1 on: November 13, 2010, 01:59:06 am »


               

One Thousand Talons Mao Ra wrote...

Right now, only one gladiator actually leaves the arena after the fight. I understand why, and that I will probably require another loop to fix it, but I wanna make this first loop work first. The gates never close and, as I said, only one fight spawns in.


I think your problem might be with this line in the OnDeath:

nInt -= -1;

Subtracting a negative value is the same as adding a positive value. 1 - (-1) = 2

In your HB script, you have it set to return out if the value is greater than or equal to 1. Change the -1 to a positive 1 and see what happens.

Also, you might want to move the ExecuteScript to the end of your script. Firing off the default script may cause it to do some actions or whatever that you did not intend or interfere with the rest of your script. Do what you need to do first, then have it execute the default.

Secondary questions...
Is there a way, while within a loop, to kick out of the entire script similar to the way 'return' does outside of the loop?


You can use a return inside a loop in the same manner you can use it outside a loop. You did this in your line:

if (GetIsEnemy(oSpectater, oKiller))
        return;

This might be why the gates are not closing, etc. It could be that the script is detecting that oSpectater and oKiller are enemies and ending the script (firing off the return).


In the 'GetNearestCreature', the second criteria is aparently mandatory but what in the Nine Hells does it mean? I don't understand it. I threw ''4'' in there just to make it compile.

It references which nearest creature to the target. So, as written, you have it set to look for the 4th nearest creature to oKiller.
               
               

               


                     Modifié par _Knightmare_, 13 novembre 2010 - 02:34 .
                     
                  


            

Legacy_One Thousand Talons Mao Ra

  • Jr. Member
  • **
  • Posts: 66
  • Karma: +0/-0
Scripting Isn't a Spectator Sport
« Reply #2 on: November 13, 2010, 04:55:08 am »


               Awesome. Thank you for actually reading through that mess. Ok...

_Knightmare_ wrote...

I think your problem might be with this line in the OnDeath:

nInt -= -1;

Subtracting a negative value is the same as adding a positive value. 1 - (-1) = 2


Fixed the double negative.

In your HB script, you have it set to return out if the value is greater than or equal to 1. Change the -1 to a positive 1 and see what happens.


This shouldn't matter, actually, because I set the variable to 0 in the on death script if the gladiator find no enemies. Or I would, if this would fire right.

Also, you might want to move the ExecuteScript to the end of your script. Firing off the default script may cause it to do some actions or whatever that you did not intend or interfere with the rest of your script. Do what you need to do first, then have it execute the default.


If I do that, it cuts the player out of any experience rewards for kills during the battle.

Secondary questions...
Is there a way, while within a loop, to kick out of the entire script similar to the way 'return' does outside of the loop?


You can use a return inside a loop in the same manner you can use it outside a loop. You did this in your line:

if (GetIsEnemy(oSpectater, oKiller))
        return;

This might be why the gates are not closing, etc. It could be that the script is detecting that oSpectater and oKiller are enemies and ending the script (firing off the return).


It is quite sloppy. I want it to end the script until the last hostile faction member is killed, at which point it will find no enemy and the script should run all the way through.

I made an improved version, because my 'GetNearestCreature' was picking people in the audience. So here it is...

// Gladiator's OnDeath script by Robert Donald Paiser
void main()
{
ExecuteScript("nw_c2_default7", OBJECT_SELF);

object oArea;
oArea = GetArea(GetNearestObjectByTag("ArenaCenter"));
int nInt;
nInt = GetLocalInt(oArea, "Gladiators In Game");
nInt -= 1;
SetLocalInt(oArea, "Gladiators In Game", nInt);
object oKiller;
object oSpectater;
object oSgate;
oSgate = GetObjectByTag("SouthGameGate");
oKiller = GetLastKiller();
int iSpectaters = 1;
while (iSpectaters <= 15)
    {
    iSpectaters++;
        oSpectater = GetNearestObjectByTag("Gladiator", oKiller, 1);
        if (GetIsEnemy(oSpectater, oKiller))
        return;
    }
SetLocked(oSgate, FALSE);
AssignCommand(oSgate, ActionOpenDoor(oSgate));
DelayCommand(20.0, AssignCommand(oSgate, ActionCloseDoor(oSgate)));
DelayCommand(20.0, SetLocked(oSgate, TRUE));
AssignCommand(oKiller, ClearAllActions());
AssignCommand(oKiller, ActionMoveToObject(GetObjectByTag("SouthGameExit")));
AssignCommand(oKiller, ActionJumpToObject(GetObjectByTag("BigExit")));
DelayCommand(30.0, SetLocalInt(oArea, "Gladiators In Game", 0));
}

However, nothing fires outside my loop. Therefore, the check for enemies must be so quick that it detects the dead guy. I'm open for suggestions here! ':pinched:'

In the 'GetNearestCreature', the second criteria is aparently mandatory but what in the Nine Hells does it mean? I don't understand it. I threw ''4'' in there just to make it compile.It references which nearest creature to the target.


So, as written, you have it set to look for the 4th nearest creature to oKiller.


Excellent. I see now! ':wizard:'
               
               

               
            

Legacy_Lightfoot8

  • Hero Member
  • *****
  • Posts: 4797
  • Karma: +0/-0
Scripting Isn't a Spectator Sport
« Reply #3 on: November 13, 2010, 05:44:42 am »


               

One Thousand Talons Mao Ra wrote...

Alright folks. I'm at my wit's end. I've been working on these two scripts for a month. It's a nightmare!

//Put this script in Area OnHeartbeat event
#include "nw_i0_2q4luskan"
void main()
{
object oTarget;
oTarget = GetArea(OBJECT_SELF);
if (GetLocalInt(oTarget, "Spectate Colosseum Go")== 0)
   return;
...

Ok, So if "Spectate Colosseum Go" is equal to 0 nothing happens. 

 
Of course, in the area's on enter and on exit I have...


//Put this script in Area OnExit event
void main()
{
object oTarget;
oTarget = GetArea(OBJECT_SELF);
SetLocalInt(oTarget, "Spectate Colosseum Go", 0);
}

The OnExit script here is fired every time anything leaves the area.  This includes when a gladiator is killed.
You should to put in a check to make sure it only fires when a PC leaves the Area. If multiplayer a check to make sure there are no PC in the area would be better.
 //Put this script in Area OnEnter event

void main()
{
object oTarget;
oTarget = GetArea(OBJECT_SELF);
SetLocalInt(oTarget, "Spectate Colosseum Go", 1);
}

Again you need a check to make sure it is a PC entering the area.  This event will also fire when you create your gladiators into the area.  Not a problem unless your PC has left the area during the creation delay.


EDIT:  Sorry,  Im wrong on the OnExit firing for NPC death. 
EDIT2: limited the strike through to only the line in error instead of the whole post.  OnExit does not fire for dead NPC's
               
               

               


                     Modifié par Lightfoot8, 13 novembre 2010 - 08:55 .
                     
                  


            

Legacy_Lightfoot8

  • Hero Member
  • *****
  • Posts: 4797
  • Karma: +0/-0
Scripting Isn't a Spectator Sport
« Reply #4 on: November 13, 2010, 07:01:53 am »


               

One Thousand Talons Mao Ra wrote...


Secondary questions...
Is there a way, while within a loop, to kick out of the entire script similar to the way 'return' does outside of the loop?
In the 'GetNearestCreature', the second criteria is aparently mandatory but what in the Nine Hells does it mean? I don't understand it. I threw ''4'' in there just to make it compile.



break Statement
               
               

               
            

Legacy__Knightmare_

  • Full Member
  • ***
  • Posts: 191
  • Karma: +0/-0
Scripting Isn't a Spectator Sport
« Reply #5 on: November 13, 2010, 02:00:20 pm »


               

It is quite sloppy. I want it to end the script until the last hostile faction member is killed, at which point it will find no enemy and the script should run all the way through.


Try looking at all objects in a Shape instead of counting and looking for the nearest creatures. But for this to work, you need to know how big your arena floor is and not have it include the Spectator areas.

Example (you would need to edit the 10.0f to an appropriate size of arena):

location lLoc = GetLocation(GetNearestObjectByTag("ArenaCenter"));
object oEnemy = GetFirstObjectInShape(SHAPE_CUBE, 10.0f, lLoc, FALSE, OBJECT_TYPE_CREATURE);
while(GetIsObjectValid(oEnemy))
{
// If the found creature is not dead (or dying), not a PC and is an enemy of oKiller then end script
if((!GetIsDead(oEnemy, TRUE)) && (!GetIsPC(oEnemy)) && (GetIsEnemy(oEnemy, oKiller))) return;

oEnemy = GetNextObjectInShape(SHAPE_CUBE, 10.0f, lLoc, FALSE, OBJECT_TYPE_CREATURE);
}

My reasoning here is that it may be possible that the NearestObject might be not hostile to oKiller while at the same time all actual enemies are dead. So instead of checking the closest creature, we search through all the creatures in a given shape (CUBE) of a given size (20 meters per side, the 10.0f above is one half the length of a cube side).

If you have NPC spectators, then you might want to create a custom faction (and add them all to it) that is neutral to both sides of the arena fight so that they are not detected as enemies by either side.

However, nothing fires outside my loop. Therefore, the check for enemies must be so quick that it detects the dead guy. I'm open for suggestions here! ':pinched:'


In my example above, I have it excluding any dead or dying NPCs in the search. For the rest, put in a couple debug type FloatText strings after your loop (or anywhere else you may have a question of if it is firing or not):

object oPC = GetFirstPC(FALSE); // Debug - this should be the players currently controlled character (in SP anyway)
FloatingTextStringOnCreature("All enemies are dead, rest of script firing.", oPC); // Debug

SetLocked(oSgate, FALSE);
AssignCommand(oSgate, ActionOpenDoor(oSgate));
// Rest of script

Also, Lightfoot8 has some valid comments (if you can see/read them with the strikethroughs lol). 'Image
               
               

               
            

Legacy_One Thousand Talons Mao Ra

  • Jr. Member
  • **
  • Posts: 66
  • Karma: +0/-0
Scripting Isn't a Spectator Sport
« Reply #6 on: November 14, 2010, 02:53:51 am »


               Thanks, you two.



Lightfoot, I see your point with the need for a PC query in the enter and exit area scripts. I added one. Except that I do want this multi-player, so how would I have it search the area for a PC and return out if it finds one?



My loop now looks like this...



object oKiller;

object oSpectater;

oKiller = GetLastKiller();

int iSpectaters = 1;

while (iSpectaters <= 15)

   {

   iSpectaters++;

       oSpectater = GetNearestObjectByTag("Gladiator", oKiller, 1);

       if (!GetIsDead(oSpectater) && GetIsEnemy(oSpectater, oKiller))

         return;

   }



It seems to hit and miss about 80/20, and none of the DelayCommand functions fire when it hits, only the normal ones. It's slightly insane. Why would only the DelayCommand functions fail? I checked the tag references a million times.



Nightmare, I already do have the NPCs in the stands as a different faction. I made a faction for each of the 3 gladiator schools which are neutral toward the commoner faction. (Commoners are neutral toward them, too.)
               
               

               
            

Legacy_One Thousand Talons Mao Ra

  • Jr. Member
  • **
  • Posts: 66
  • Karma: +0/-0
Scripting Isn't a Spectator Sport
« Reply #7 on: November 14, 2010, 11:47:04 am »


               Progress! The DelayCommands weren't firing because the script owner, the dead gladiator wasn't around any more for the DelayCommand to run off of. So I changed my delays to...

AssignCommand(GetModule(), DelayCommand(20.0, AssignCommand(oSgate, ActionCloseDoor(oSgate))));
AssignCommand(GetModule(), DelayCommand(20.0, SetLocked(oSgate, TRUE)));
AssignCommand(GetModule(), DelayCommand(30.0, SetLocalInt(oArea, "Gladiators In Game", 0)));

Now they fire.

And now I have to determine why my loop doesn't always return when it should, because my arena filled right up with angry gladiators! ':lol:' I suppose my loop -

while (iSpectaters <= 10)
    {
    iSpectaters++;
        oSpectater = GetNearestObjectByTag("Gladiator", oKiller, 1);
        if (!GetIsDead(oSpectater) && GetIsEnemy(oSpectater, oKiller))
          return;
    }

- could be detecting dead allies and not returning. ':blush:'
I'm gonna have to reinvent this whole situation, aren't I? I gotta sleep. '-_-'
               
               

               
            

Legacy__Knightmare_

  • Full Member
  • ***
  • Posts: 191
  • Karma: +0/-0
Scripting Isn't a Spectator Sport
« Reply #8 on: November 14, 2010, 01:21:27 pm »


               Try adding the TRUE into the GetIsDead function:



(!GetIsDead(oSpectater, TRUE)



The TRUE tells it to ignore dying NPCs along with the truely dead ones. I believe it defaults to FALSE.
               
               

               
            

Legacy_One Thousand Talons Mao Ra

  • Jr. Member
  • **
  • Posts: 66
  • Karma: +0/-0
Scripting Isn't a Spectator Sport
« Reply #9 on: November 15, 2010, 03:15:05 am »


               

_Knightmare_ wrote...
Try adding the TRUE into the GetIsDead function:

(!GetIsDead(oSpectater, TRUE)

The TRUE tells it to ignore dying NPCs along with the truely dead ones. I believe it defaults to FALSE.


It wouldn't compile unless I dropped the TRUE.

Every time the nearest creature happens to be a friendly gladiator, the script doesn't return out and runs through. So this won't work.

I just tried a -

if (GetIsInCombat(oKiller))
   return;

- but it happens too fast. I wish you could pause a script for X seconds.
               
               

               


                     Modifié par One Thousand Talons Mao Ra, 15 novembre 2010 - 03:15 .
                     
                  


            

Legacy_Lightfoot8

  • Hero Member
  • *****
  • Posts: 4797
  • Karma: +0/-0
Scripting Isn't a Spectator Sport
« Reply #10 on: November 15, 2010, 03:35:19 am »


               Anytime you have a return control is going to return to the calling code. If the return is in a function called from the main body of your script, control will be returned back to the main body of your script. If the return is in the main body of your script control will be returned back to what ever script/code called your script.  

If you are looking to just get out of the loop in your code and not exit the entire script, you need to use the break Statement not the return statment.  
               
               

               


                     Modifié par Lightfoot8, 15 novembre 2010 - 03:37 .
                     
                  


            

Legacy__Knightmare_

  • Full Member
  • ***
  • Posts: 191
  • Karma: +0/-0
Scripting Isn't a Spectator Sport
« Reply #11 on: November 15, 2010, 01:33:10 pm »


               Sorry about that. The added TRUE is a difference between the NWN1 and NWN2 versions of that function. My bad, should have checked.

You seem to know exactly how many times you want the loop to fire itself since you keep setting it to search as long as iSpectaters <= 10 (or 15 previously). For situations where you know specifically how many times you want the loop to... well loop, then a "for" loop might be more appropriate than a "while" loop:

object oSpectater;
object oKiller = GetLastKiller();

int iSpectaters;

for (iSpectaters = 1; iSpectaters < 11; iSpectaters ++)
{
oSpectater = GetNearestObjectByTag("Gladiator", oKiller, iSpectaters);

if (!GetIsDead(oSpectater) && GetIsEnemy(oSpectater, oKiller)) return;
}

The above will loop 10 times, each time adding 1 to the current value of iSpectaters. I then have that same value inserted in the GetNearestObjectByTag function so during the first loop it will search for the first nearest creature and check then against you "if" conditional. If the "if" fails to return/exit the script then it adds 1 to iSpectaters (for a value of 2 now) and now checks the 2nd closest creature. If the condtional fails, it changes value to 3, checks the 3rd closest, etc. This pattern will continue until iSpectaters has a value of 11 and exits the loop there (so we have previously checked the 10 closest creatures). There is a short section in my tutorial (linked in sig below) if you want some more info on "for loops."

However, a totally unrelated way of doing this whole thing is:

- When an NPC fighter spawns in (so their OnSpawn event) have them find the current value of some integer (which is saved on something that can't die or be destroyed) and add 1 to it. For example:

int nTeam1 = GetLocalInt(oArea, "Fight_Group_1");
int nTeam1 += 1;
SetLocalInt(oArea, "Fight_Group_1", nTeam1);

Then in the OnDeath of those NPCs, remove one from that stored integer:

int nTeam1 = GetLocalInt(oArea, "Fight_Group_1");
int nTeam1 -= 1;
SetLocalInt(oArea, "Fight_Group_1", nTeam1 );

In that same OnDeath, after changing the variable, then check to see if the saved integer now equals 0 (or is less than 1), if it does, do the rest of your script:

if(nTeam1 < 1)
{
// Rest of script with doors and such here
}

As you have 3 teams fighting at the same time your "if" coditional above will be a bit more complicated but not by much.

As opposed to your original version, this is still tracking ints, but just doing it by "fighting team" rather than tracking all the possible fighters from the different teams totalled together. Of course the drawback is that you are tracking 3 different integers (one per fighting team), but that is fairly easy to do.

@ Lightfoot The question was how to get out of the script entirely, not just break the loop:


Is there a way, while within a loop, to kick out of the entire script similar to the way 'return' does outside of the loop?

However, your point is valid for the situation you are meaning to describe. 'Image
               
               

               


                     Modifié par _Knightmare_, 15 novembre 2010 - 01:35 .
                     
                  


            

Legacy_One Thousand Talons Mao Ra

  • Jr. Member
  • **
  • Posts: 66
  • Karma: +0/-0
Scripting Isn't a Spectator Sport
« Reply #12 on: November 15, 2010, 08:07:03 pm »


               

_Knightmare_ wrote...
You seem to know exactly how many times you want the loop to fire itself since you keep setting it to search as long as iSpectaters <= 10 (or 15 previously). For situations where you know specifically how many times you want the loop to... well loop, then a "for" loop might be more appropriate than a "while" loop:
There is a short section in my tutorial (linked in sig below) if you want some more info on "for loops."


I actually just kept changing it because I was undecided. I figure there probably will never be more than 10 people standing after a fight. Also, it still leaves us with the problem of the GetNearest grabing living allies and firing the rest of the script. I like your second idea better! I was originally considering something like it, actually...

However, a totally unrelated way of doing this whole thing is:

- When an NPC fighter spawns in (so their OnSpawn event) have them find the current value of some integer (which is saved on something that can't die or be destroyed) and add 1 to it. For example:

int nTeam1 = GetLocalInt(oArea, "Fight_Group_1");
int nTeam1 += 1;
SetLocalInt(oArea, "Fight_Group_1", nTeam1);

Then in the OnDeath of those NPCs, remove one from that stored integer:

int nTeam1 = GetLocalInt(oArea, "Fight_Group_1");
int nTeam1 -= 1;
SetLocalInt(oArea, "Fight_Group_1", nTeam1 );

In that same OnDeath, after changing the variable, then check to see if the saved integer now equals 0 (or is less than 1), if it does, do the rest of your script:

if(nTeam1 < 1)
{
// Rest of script with doors and such here
}


I had read, however, that the on death event doesn't fire very reliably. Didn't wanna mess with variables over much if that is the case. Is this untrue?
               
               

               
            

Legacy_One Thousand Talons Mao Ra

  • Jr. Member
  • **
  • Posts: 66
  • Karma: +0/-0
Scripting Isn't a Spectator Sport
« Reply #13 on: November 15, 2010, 09:38:19 pm »


               Oh, I'll be checking out that loop tutorial as well. Thanks!
               
               

               
            

Legacy_One Thousand Talons Mao Ra

  • Jr. Member
  • **
  • Posts: 66
  • Karma: +0/-0
Scripting Isn't a Spectator Sport
« Reply #14 on: November 15, 2010, 10:42:04 pm »


               The following script, if you're interested, almost worked it but gets wonky after a few fights...

I changed the gladiators tags to match their schools and added variables to them.

// Gladiator's OnDeath script by Robert Donald Paiser
void main()
{
ExecuteScript("nw_c2_default7", OBJECT_SELF);

object oKiller;
oKiller = GetLastKiller();
object oThreat;
if (GetLocalInt(oKiller, "Carpathian")== 1)
    {
    oThreat = GetNearestObjectByTag("Sacrentian", oKiller, 2);
    if (GetIsObjectValid(oThreat))
        return;
    oThreat = GetNearestObjectByTag("Darkheart", oKiller, 2);
    if (GetIsObjectValid(oThreat))
        return;
    }
if (GetLocalInt(oKiller, "Sacrentian")== 1)
    {
    oThreat = GetNearestObjectByTag("Carpathian", oKiller, 2);
    if (GetIsObjectValid(oThreat) && !GetIsDead(oThreat))
        return;
    oThreat = GetNearestObjectByTag("Darkheart", oKiller, 2);
    if (GetIsObjectValid(oThreat) && !GetIsDead(oThreat))
        return;
    }
if (GetLocalInt(oKiller, "Darkheart")== 1)
    {
    oThreat = GetNearestObjectByTag("Carpathian", oKiller, 2);
    if (GetIsObjectValid(oThreat) && !GetIsDead(oThreat))
        return;
    oThreat = GetNearestObjectByTag("Sacrentian", oKiller, 2);
    if (GetIsObjectValid(oThreat) && !GetIsDead(oThreat))
        return;
    }
object oSgate;
oSgate = GetObjectByTag("SouthGameGate");
SetLocked(oSgate, FALSE);
AssignCommand(oSgate, ActionOpenDoor(oSgate));
object oVictor;
if (GetLocalInt(oKiller, "Carpathian")== 1)
    {
    int iVictors = 1;
    while (iVictors <= 10)
        {
        oVictor = GetNearestObjectByTag("Carpathian", oKiller, 1);
        AssignCommand(oVictor, ClearAllActions());
        AssignCommand(oVictor, ActionMoveToObject(GetObjectByTag("SouthGameExit")));
        AssignCommand(oVictor, ActionJumpToObject(GetObjectByTag("BigExit")));
          iVictors++;
        }
    }
if (GetLocalInt(oKiller, "Sacrentian")== 1)
    {
    int iVictors = 1;
    while (iVictors <= 10)
        {
        oVictor = GetNearestObjectByTag("Sacrentian", oKiller, 1);
        AssignCommand(oVictor, ClearAllActions());
        AssignCommand(oVictor, ActionMoveToObject(GetObjectByTag("SouthGameExit")));
        AssignCommand(oVictor, ActionJumpToObject(GetObjectByTag("BigExit")));
          iVictors++;
        }
    }
if (GetLocalInt(oKiller, "Darkheart")== 1)
    {
    int iVictors = 1;
    while (iVictors <= 10)
        {
        oVictor = GetNearestObjectByTag("Darkheart", oKiller, 1);
        AssignCommand(oVictor, ClearAllActions());
        AssignCommand(oVictor, ActionMoveToObject(GetObjectByTag("SouthGameExit")));
        AssignCommand(oVictor, ActionJumpToObject(GetObjectByTag("BigExit")));
          iVictors++;
        }
    }
AssignCommand(GetModule(), DelayCommand(20.0, AssignCommand(oSgate, ActionCloseDoor(oSgate))));
AssignCommand(GetModule(), DelayCommand(20.0, SetLocked(oSgate, TRUE)));
AssignCommand(oKiller, ClearAllActions());
AssignCommand(oKiller, ActionMoveToObject(GetObjectByTag("SouthGameExit")));
AssignCommand(oKiller, ActionJumpToObject(GetObjectByTag("BigExit")));
object oArea;
oArea = GetArea(GetNearestObjectByTag("ArenaCenter"));
AssignCommand(GetModule(), DelayCommand(30.0, SetLocalInt(oArea, "Gladiators In Game", 0)));
}