Author Topic: Help with a henchman respawn script?  (Read 760 times)

Legacy_Mr. Versipellis

  • Full Member
  • ***
  • Posts: 236
  • Karma: +0/-0
Help with a henchman respawn script?
« on: July 03, 2012, 03:18:08 pm »


                I hate to beg but I've been puzzling over this for a good few days and I simply can't get it to work as I would like it to. This script is placed OnDeath for a certain henchman, tagged "erno". What I would like it to do is to have him sit there for thirty-odd seconds, then respawn, restore his health, say a random phrase taken from a list of four strings and then add himself back to the party. The script I have at the moment looks like this:

#include "nw_i0_generic"
#include "nw_i0_plot"
void main()
{
{
    object oMe = GetAssociate(ASSOCIATE_TYPE_HENCHMAN, GetMaster());
    if (oMe == OBJECT_SELF
        // * this is to prevent 'double hits' from stopping
        // * the henchmen from moving to the temple of tyr
        // * I.e., henchmen dies 'twice', once after leaving  your party
        || GetLocalInt(OBJECT_SELF, "NW_L_HEN_I_DIED") == TRUE)
       {       SetPlotFlag(oMe, TRUE);
       SetAssociateState(NW_ASC_IS_BUSY, TRUE);
       SetIsDestroyable(FALSE, TRUE, TRUE);
       SetLocalInt(OBJECT_SELF, "NW_L_HEN_I_DIED", TRUE);
        ClearAllActions();
        DelayCommand(0.5, ActionDoCommand(SetCommandable(TRUE)));
        DelayCommand(5.0, ActionDoCommand(SetAssociateState(NW_ASC_IS_BUSY, FALSE)));

        DelayCommand(5.1, SetPlotFlag(oMe, FALSE));

        SetCommandable(FALSE);       }}
  string sRevive;

  {    int iRandom = d4();
    switch(iRandom)
    {      case 1:
        sRevive = "1";
        break;
      case 2:
        sRevive = "2";
        break;
      case 3:
        sRevive = "3";
        break;
      case 4:
        sRevive = "4";
      break;
    }
  }
    SetLocalObject(OBJECT_SELF,"NW_L_FORMERMASTER", GetMaster());
    DelayCommand(0.1, RemoveEffects(OBJECT_SELF));
    DelayCommand(30.2, ApplyEffectToObject(DURATION_TYPE_PERMANENT, EffectResurrection(), OBJECT_SELF));
    DelayCommand(30.3, ApplyEffectToObject(DURATION_TYPE_PERMANENT, EffectHeal(GetMaxHitPoints(OBJECT_SELF)), OBJECT_SELF));
    DelayCommand(31.0, AssignCommand(OBJECT_SELF, ActionSpeakString(sRevive)));
    DelayCommand(35.1, SetIsDestroyable(TRUE, TRUE, TRUE));
    DelayCommand(35.1, SpeakString(sRevive));
    SetLocalInt(GetMaster(OBJECT_SELF), GetResRef(OBJECT_SELF) + "_dead", 1);

  object oMaster = GetLocalObject(OBJECT_SELF,"NW_L_FORMERMASTER");
  PrintString("Trying to join " + GetName(oMaster));
  PrintString("Distance " + FloatToString(GetDistanceBetween(oMaster, OBJECT_SELF)));

  if(
      (!(oMaster == OBJECT_INVALID)) &&
      (GetHenchman(oMaster) == OBJECT_INVALID) &&
      (GetDistanceBetween(oMaster, OBJECT_SELF) < 30.0) )  {
    PrintString("Joining");
    ClearAllActions();
    SetAssociateState(NW_ASC_IS_BUSY, FALSE);
    SetAssociateListenPatterns();
    SetLocalInt(OBJECT_SELF, "NW_COM_MODE_COMBAT", ASSOCIATE_COMMAND_ATTACKNEAREST);
    SetLocalInt(OBJECT_SELF, "NW_COM_MODE_MOVEMENT", ASSOCIATE_COMMAND_FOLLOWMASTER);
    SetAssociateState(NW_ASC_IS_BUSY, FALSE);
    AddHenchman(oMaster);
    SetLocalObject(OBJECT_SELF, "Master", GetPCSpeaker());
   }}

 

It is succesfully resurrecting him and stripping him of effects after the set time, but then he always says the fourth line and does not add himself back to the party. What am I doing wrong here?

Edit: Formatting
               
               

               


                     Modifié par Mr. Versipellis, 03 juillet 2012 - 03:28 .
                     
                  


            

Legacy_GhostOfGod

  • Hero Member
  • *****
  • Posts: 1490
  • Karma: +0/-0
Help with a henchman respawn script?
« Reply #1 on: July 04, 2012, 01:06:28 am »


               Well you did have a few extra curly brackets in there I took out. I edited it a bit mor for readability.


#include "nw_i0_generic"
#include "nw_i0_plot"
void main()
{
    object oMe = GetAssociate(ASSOCIATE_TYPE_HENCHMAN, GetMaster());
    if (oMe == OBJECT_SELF
        // * this is to prevent 'double hits' from stopping
        // * the henchmen from moving to the temple of tyr
        // * I.e., henchmen dies 'twice', once after leaving  your party
        || GetLocalInt(OBJECT_SELF, "NW_L_HEN_I_DIED") == TRUE)
    {
        SetPlotFlag(oMe, TRUE);
        SetAssociateState(NW_ASC_IS_BUSY, TRUE);
        SetIsDestroyable(FALSE, TRUE, TRUE);
        SetLocalInt(OBJECT_SELF, "NW_L_HEN_I_DIED", TRUE);
        ClearAllActions();
        DelayCommand(0.5, ActionDoCommand(SetCommandable(TRUE)));
        DelayCommand(5.0, ActionDoCommand(SetAssociateState(NW_ASC_IS_BUSY, FALSE)));
        DelayCommand(5.1, SetPlotFlag(oMe, FALSE));
        SetCommandable(FALSE);
    }

    string sRevive;
    int iRandom = d4();
    switch(iRandom)
    {
        case 1: sRevive = "1"; break;
        case 2: sRevive = "2"; break;
        case 3: sRevive = "3"; break;
        case 4: sRevive = "4"; break;
    }

    SetLocalObject(OBJECT_SELF,"NW_L_FORMERMASTER", GetMaster());
    DelayCommand(0.1, RemoveEffects(OBJECT_SELF));
    DelayCommand(30.2, ApplyEffectToObject(DURATION_TYPE_PERMANENT, EffectResurrection(), OBJECT_SELF));
    DelayCommand(30.3, ApplyEffectToObject(DURATION_TYPE_PERMANENT, EffectHeal(GetMaxHitPoints(OBJECT_SELF)), OBJECT_SELF));
    DelayCommand(31.0, AssignCommand(OBJECT_SELF, ActionSpeakString(sRevive)));
    DelayCommand(35.1, SetIsDestroyable(TRUE, TRUE, TRUE));
    DelayCommand(35.1, SpeakString(sRevive));
    SetLocalInt(GetMaster(OBJECT_SELF), GetResRef(OBJECT_SELF) + "_dead", 1);

    object oMaster = GetLocalObject(OBJECT_SELF,"NW_L_FORMERMASTER");
    PrintString("Trying to join " + GetName(oMaster));
    PrintString("Distance " + FloatToString(GetDistanceBetween(oMaster, OBJECT_SELF)));

    if((!(oMaster == OBJECT_INVALID)) &&
       (GetHenchman(oMaster) == OBJECT_INVALID) &&
       (GetDistanceBetween(oMaster, OBJECT_SELF) < 30.0))
    {
        PrintString("Joining");
        ClearAllActions();
        SetAssociateState(NW_ASC_IS_BUSY, FALSE);
        SetAssociateListenPatterns();
        SetLocalInt(OBJECT_SELF, "NW_COM_MODE_COMBAT", ASSOCIATE_COMMAND_ATTACKNEAREST);
        SetLocalInt(OBJECT_SELF, "NW_COM_MODE_MOVEMENT", ASSOCIATE_COMMAND_FOLLOWMASTER);
        SetAssociateState(NW_ASC_IS_BUSY, FALSE);
        AddHenchman(oMaster);
        SetLocalObject(OBJECT_SELF, "Master", GetPCSpeaker());
    }
}


There are a couple other things that make this confusing to read and hard to figure out what you want to check exactly. Like this:

(!(oMaster == OBJECT_INVALID))

Would just be the same as this:

oMaster != OBJECT_INVALID

So this section the way you have it:

if((!(oMaster == OBJECT_INVALID)) &&

       (GetHenchman(oMaster) == OBJECT_INVALID) &&

       (GetDistanceBetween(oMaster, OBJECT_SELF) < 30.0))

Would be the same as:

if (oMaster != OBJECT_INVALID &&

    GetHenchman(oMaster) == OBJECT_INVALID &&

    GetDistanceBetween(oMaster, OBJECT_SELF) < 30.0)
               
               

               
            

Legacy_Mr. Versipellis

  • Full Member
  • ***
  • Posts: 236
  • Karma: +0/-0
Help with a henchman respawn script?
« Reply #2 on: July 04, 2012, 12:20:31 pm »


               

GhostOfGod wrote...

Well you did have a few extra curly brackets in there I took out. I edited it a bit mor for readability.


#include "nw_i0_generic"
#include "nw_i0_plot"
void main()
{
    object oMe = GetAssociate(ASSOCIATE_TYPE_HENCHMAN, GetMaster());
    if (oMe == OBJECT_SELF
        // * this is to prevent 'double hits' from stopping
        // * the henchmen from moving to the temple of tyr
        // * I.e., henchmen dies 'twice', once after leaving  your party
        || GetLocalInt(OBJECT_SELF, "NW_L_HEN_I_DIED") == TRUE)
    {
        SetPlotFlag(oMe, TRUE);
        SetAssociateState(NW_ASC_IS_BUSY, TRUE);
        SetIsDestroyable(FALSE, TRUE, TRUE);
        SetLocalInt(OBJECT_SELF, "NW_L_HEN_I_DIED", TRUE);
        ClearAllActions();
        DelayCommand(0.5, ActionDoCommand(SetCommandable(TRUE)));
        DelayCommand(5.0, ActionDoCommand(SetAssociateState(NW_ASC_IS_BUSY, FALSE)));
        DelayCommand(5.1, SetPlotFlag(oMe, FALSE));
        SetCommandable(FALSE);
    }

    string sRevive;
    int iRandom = d4();
    switch(iRandom)
    {
        case 1: sRevive = "1"; break;
        case 2: sRevive = "2"; break;
        case 3: sRevive = "3"; break;
        case 4: sRevive = "4"; break;
    }

    SetLocalObject(OBJECT_SELF,"NW_L_FORMERMASTER", GetMaster());
    DelayCommand(0.1, RemoveEffects(OBJECT_SELF));
    DelayCommand(30.2, ApplyEffectToObject(DURATION_TYPE_PERMANENT, EffectResurrection(), OBJECT_SELF));
    DelayCommand(30.3, ApplyEffectToObject(DURATION_TYPE_PERMANENT, EffectHeal(GetMaxHitPoints(OBJECT_SELF)), OBJECT_SELF));
    DelayCommand(31.0, AssignCommand(OBJECT_SELF, ActionSpeakString(sRevive)));
    DelayCommand(35.1, SetIsDestroyable(TRUE, TRUE, TRUE));
    DelayCommand(35.1, SpeakString(sRevive));
    SetLocalInt(GetMaster(OBJECT_SELF), GetResRef(OBJECT_SELF) + "_dead", 1);

    object oMaster = GetLocalObject(OBJECT_SELF,"NW_L_FORMERMASTER");
    PrintString("Trying to join " + GetName(oMaster));
    PrintString("Distance " + FloatToString(GetDistanceBetween(oMaster, OBJECT_SELF)));

    if((!(oMaster == OBJECT_INVALID)) &&
       (GetHenchman(oMaster) == OBJECT_INVALID) &&
       (GetDistanceBetween(oMaster, OBJECT_SELF) < 30.0))
    {
        PrintString("Joining");
        ClearAllActions();
        SetAssociateState(NW_ASC_IS_BUSY, FALSE);
        SetAssociateListenPatterns();
        SetLocalInt(OBJECT_SELF, "NW_COM_MODE_COMBAT", ASSOCIATE_COMMAND_ATTACKNEAREST);
        SetLocalInt(OBJECT_SELF, "NW_COM_MODE_MOVEMENT", ASSOCIATE_COMMAND_FOLLOWMASTER);
        SetAssociateState(NW_ASC_IS_BUSY, FALSE);
        AddHenchman(oMaster);
        SetLocalObject(OBJECT_SELF, "Master", GetPCSpeaker());
    }
}


There are a couple other things that make this confusing to read and hard to figure out what you want to check exactly. Like this:

(!(oMaster == OBJECT_INVALID))

Would just be the same as this:

oMaster != OBJECT_INVALID

So this section the way you have it:

if((!(oMaster == OBJECT_INVALID)) &&

       (GetHenchman(oMaster) == OBJECT_INVALID) &&

       (GetDistanceBetween(oMaster, OBJECT_SELF) < 30.0))

Would be the same as:

if (oMaster != OBJECT_INVALID &&

    GetHenchman(oMaster) == OBJECT_INVALID &&

    GetDistanceBetween(oMaster, OBJECT_SELF) < 30.0)




Thanks for that - I really do need to be more careful with my programming! Does this give you any clue of what the problem with the actual code is?
               
               

               
            

Legacy_Failed.Bard

  • Hero Member
  • *****
  • Posts: 1409
  • Karma: +0/-0
Help with a henchman respawn script?
« Reply #3 on: July 04, 2012, 01:31:04 pm »


               

ClearAllActions();
       DelayCommand(0.5, ActionDoCommand(SetCommandable(TRUE)));
       DelayCommand(5.0, ActionDoCommand(SetAssociateState(NW_ASC_IS_BUSY, FALSE)));
       DelayCommand(5.1, SetPlotFlag(oMe, FALSE));
       SetCommandable(FALSE);

Can a dead PC/NPC quoue actions?  Also, with the delays on them, even if they can, then they'd be assigned after the NPC has been set to non-commandable anyways.
               
               

               
            

Legacy_Mr. Versipellis

  • Full Member
  • ***
  • Posts: 236
  • Karma: +0/-0
Help with a henchman respawn script?
« Reply #4 on: July 04, 2012, 01:54:22 pm »


               

Failed.Bard wrote...

ClearAllActions();
       DelayCommand(0.5, ActionDoCommand(SetCommandable(TRUE)));
       DelayCommand(5.0, ActionDoCommand(SetAssociateState(NW_ASC_IS_BUSY, FALSE)));
       DelayCommand(5.1, SetPlotFlag(oMe, FALSE));
       SetCommandable(FALSE);

Can a dead PC/NPC quoue actions?  Also, with the delays on them, even if they can, then they'd be assigned after the NPC has been set to non-commandable anyways.

I believe that I've seen other people do it in the same way, but my memory may well be at fault. Do you know of another, more effective way to delay actions like these? That would make sense, considering that the only actions that aren't running are the "DoCommand" ones.
               
               

               
            

Legacy_GhostOfGod

  • Hero Member
  • *****
  • Posts: 1490
  • Karma: +0/-0
Help with a henchman respawn script?
« Reply #5 on: July 04, 2012, 02:01:51 pm »


               You could assign commands to the 'area' of the dead henchmen.

Also something else I noticed on your last line:

SetLocalObject(OBJECT_SELF, "Master", GetPCSpeaker());

If this is an OnDeath script I'm not sure what object, if any, will be returned using the GetPCSpeaker function. That is usually meant for conversations. So this might be causing a problem as well.
               
               

               


                     Modifié par GhostOfGod, 04 juillet 2012 - 01:05 .
                     
                  


            

Legacy_Mr. Versipellis

  • Full Member
  • ***
  • Posts: 236
  • Karma: +0/-0
Help with a henchman respawn script?
« Reply #6 on: July 04, 2012, 04:01:02 pm »


               

GhostOfGod wrote...

You could assign commands to the 'area' of the dead henchmen.

And how would I go about doing that? Would that solve the problem? As it stands, I'm using a slightly tweaked script that does everything except add the henchman back to the party; instead, the player has to speak to them, which is a bit of a problem since they can easily be forgotten, which affects the story.
               
               

               
            

Legacy_GhostOfGod

  • Hero Member
  • *****
  • Posts: 1490
  • Karma: +0/-0
Help with a henchman respawn script?
« Reply #7 on: July 04, 2012, 08:01:31 pm »


               Are you seeing your PrintString "Joining"?
               
               

               


                     Modifié par GhostOfGod, 04 juillet 2012 - 07:02 .
                     
                  


            

Legacy_Mr. Versipellis

  • Full Member
  • ***
  • Posts: 236
  • Karma: +0/-0
Help with a henchman respawn script?
« Reply #8 on: July 04, 2012, 10:04:09 pm »


               

GhostOfGod wrote...

Are you seeing your PrintString "Joining"?

No - that's exactly the reason I stuck it in there; I figured that as soon as I saw that, the rest of the code must be working since it's all in one block. If you like, I could put together an ERF with the script and henchman in question in it?
               
               

               
            

Legacy_GhostOfGod

  • Hero Member
  • *****
  • Posts: 1490
  • Karma: +0/-0
Help with a henchman respawn script?
« Reply #9 on: July 04, 2012, 11:54:35 pm »


               Ok then you are not getting past your "if". So lets break this down:

if (oMaster != OBJECT_INVALID &&

    GetHenchman(oMaster) == OBJECT_INVALID &&

    GetDistanceBetween(oMaster, OBJECT_SELF) < 30.0)


What this is saying is;

If oMaster exists (which is an object that has been set on the henchman) AND oMaster does NOT have any henchmen AND the distance to oMaster is less than 30.0, then do stuff.

So one of these things is not happening. It is most likely this line:

object oMaster = GetLocalObject(OBJECT_SELF,"NW_L_FORMERMASTER");

Somewhere in some other script there should be a SetLocalObject line that makes sure this gets set.

You could add a couple lines under the above mentioned line that will let you know if oMaster exists.
Something kinda like so:

object oMaster = GetLocalObject(OBJECT_SELF,"NW_L_FORMERMASTER");
if (!GetIsObjectValid(oMaster))
{
    SendMessageToPC(GetFirstPC(), "oMaster not found");
}

Hopefully this will at least get you pointed in the right direction.
               
               

               


                     Modifié par GhostOfGod, 04 juillet 2012 - 10:55 .
                     
                  


            

Legacy_meaglyn

  • Hero Member
  • *****
  • Posts: 1451
  • Karma: +0/-0
Help with a henchman respawn script?
« Reply #10 on: July 05, 2012, 01:46:26 pm »


               I think the logic of that "if" looks iffy (so to speak '<img'>

As GhostofGod said it's based on the master which is set earlier in the script from this:

SetLocalObject(OBJECT_SELF,"NW_L_FORMERMASTER", GetMaster());

and then retrieved with this:

object oMaster = GetLocalObject(OBJECT_SELF,"NW_L_FORMERMASTER");

So if you take out the variable what the if is saying is

if (GetMaster() != OBJECT_INVALID
  && GetHenchmen(GetMaster()) == OBJECT_INVALID)
  && GetDistanceBetween(oMaster, OBJECT_SELF) < 30.0)

It seems to me that if GetMaster() returns a valid object then a GetHenchman() call on that
master really must also be returning a valid object. So this second clause will never be true.

I don't know when in the death process a henchman gets removed from the his/her master.

As GhostofGod said it could also be the master is INVALID already. It won't be from the
object oMaster = GetLocalObject(OBJECT_SELF,"NW_L_FORMERMASTER") line
but from the actual GetMaster() call.
               
               

               
            

Legacy_Mr. Versipellis

  • Full Member
  • ***
  • Posts: 236
  • Karma: +0/-0
Help with a henchman respawn script?
« Reply #11 on: July 05, 2012, 06:15:56 pm »


               Thanks guys, I got it sorted. I basically had to "trim the fat" out of the script and make sure that all the "if" conditions were doing what they were supposed to - I must admit, I took parts of this script from an ERF template so I didn't really know what I was doing. I really do appreciate the help!
Just one question, though: how do you think this design will work in terms of gameplay? The script is working without a hitch, but would you like the henchman system to work this way if you were playing the module? And can you forsee any problems with the design? I'm going for a Dragon Age/Neverwinter Nights 2 system, but I'm not quite sure how that'll work out in the Aurora engine.
               
               

               
            

Legacy_Lightfoot8

  • Hero Member
  • *****
  • Posts: 4797
  • Karma: +0/-0
Help with a henchman respawn script?
« Reply #12 on: July 05, 2012, 09:28:50 pm »


               Can you post your current version of the script.
               
               

               
            

Legacy_Mr. Versipellis

  • Full Member
  • ***
  • Posts: 236
  • Karma: +0/-0
Help with a henchman respawn script?
« Reply #13 on: July 06, 2012, 10:36:10 am »


               

Lightfoot8 wrote...

Can you post your current version of the script.


#include "nw_i0_generic"
#include "nw_i0_plot"
void main()

{

//Define the former master
object oMaster = GetNearestPC();
//Define the henchman
object oMe = GetAssociate(ASSOCIATE_TYPE_HENCHMAN, GetMaster());

//Set the HCH erno_dead variable, just in case the script goes wrong.
//This means that you see a special bit of dialogue when you speak to the hench post-death, but only if something goes wrong, i.e. the PC moves areas
SetLocalInt(GetMaster(OBJECT_SELF), GetResRef(OBJECT_SELF) + "erno_dead", 1);



//Double-hit thing to stop the body from getting destroyed or anything
if (oMe == OBJECT_SELF
|| GetLocalInt(OBJECT_SELF, "NW_L_HEN_I_DIED") == TRUE)
    {
        SetPlotFlag(oMe, TRUE);
        SetAssociateState(NW_ASC_IS_BUSY, TRUE);
        SetIsDestroyable(FALSE, TRUE, TRUE);
        SetLocalInt(OBJECT_SELF, "NW_L_HEN_I_DIED", TRUE);
        ClearAllActions();
        DelayCommand(0.5, ActionDoCommand(SetCommandable(TRUE)));
        DelayCommand(5.0, ActionDoCommand(SetAssociateState(NW_ASC_IS_BUSY, FALSE)));
        DelayCommand(5.1, SetPlotFlag(oMe, FALSE));
        SetCommandable(FALSE);
    }
//Choose a random dialogue string
string sRevive;
int iRandom = d4();
switch(iRandom)
    {
    case 1: sRevive = "Better luck next time, eh?"; break;
    case 2: sRevive = "Thank all the Gods that we pulled through that..."; break;
    case 3: sRevive = "That was... unpleasant, to say the least."; break;
    case 4: sRevive = "Oh my... how long was I out for?"; break;
    case 5: sRevive = "Well, there's one for the journal."; break;
    case 6: sRevive = "Argh, I can barely feel my legs!"; break;
    case 7: sRevive = "That was strangely invigorating!"; break;
    case 8: sRevive = "For the love of all things holy, let's be more careful next time!"; break;
    }

//Resurrect and remove effects, then add back the henchman
DelayCommand(0.1, RemoveEffects(OBJECT_SELF));
DelayCommand(30.0, ApplyEffectToObject(DURATION_TYPE_PERMANENT, EffectResurrection(), OBJECT_SELF));
DelayCommand(30.25, ApplyEffectToObject(DURATION_TYPE_PERMANENT, EffectHeal(GetMaxHitPoints(OBJECT_SELF)), OBJECT_SELF));
DelayCommand(30.75, SetIsDestroyable(TRUE, TRUE, TRUE));
DelayCommand(31.0, SpeakString(sRevive));
DelayCommand(31.5, AddHenchman(oMaster, oMe));

//Re-set the variable to get rid of annoying dialogueif the henchie has successfully re-joined
DelayCommand(32.0, SetLocalInt(GetMaster(OBJECT_SELF), GetResRef(OBJECT_SELF) + "erno_dead", 0));

//Set up the proper conditions for henchman as defined by the X2 script
SetAssociateState(NW_ASC_IS_BUSY, FALSE);
SetAssociateListenPatterns();
SetLocalInt(OBJECT_SELF, "NW_COM_MODE_COMBAT", ASSOCIATE_COMMAND_ATTACKNEAREST);
SetLocalInt(OBJECT_SELF, "NW_COM_MODE_MOVEMENT", ASSOCIATE_COMMAND_FOLLOWMASTER);
SetAssociateState(NW_ASC_IS_BUSY, FALSE);
SetLocalObject(OBJECT_SELF, "Master", GetNearestPC());

}

 
               
               

               


                     Modifié par Mr. Versipellis, 06 juillet 2012 - 09:38 .
                     
                  


            

Legacy_Lightfoot8

  • Hero Member
  • *****
  • Posts: 4797
  • Karma: +0/-0
Help with a henchman respawn script?
« Reply #14 on: July 08, 2012, 08:00:40 am »


               

Mr. Versipellis wrote...

http://pastebin.com/CpmY4F7R#


Your script still looks problematic to me.  The problems start with how you are defining oMaster and oMe at the begining of the script ( lines 6-9 ).  Both of them as written have a chance of returning the wrong object.  oMaster should be defined as a local that is set up at the time the henchman is added to the party.   oMe should be simply OBJECT_SELF


for oMaster you can use the wrapper function set up in X0_I0_HENCHMAN.

ie
object oMaster = GetLastMaster();
object oMe = OBJECT_SELF;

At that point if oMaster does not return the correct object, make sure that you have the SetLastMaster function in the script that adds the henchman to the party.


line 13:  SetLocalInt(GetMaster(OBJECT_SELF), GetResRef(OBJECT_SELF) + "erno_dead", 1);
Makes no since to me as being  set up on the master instead of the henchman.  We even have the problem here that if the henchman has already been removed from the party GetMaster is going to return an invalid object.  assuming that the other scripts are done correctly for the var being set on the PC, just use oMaster instead of GetMaster() ie:

 SetLocalInt(oMaster, GetResRef(OBJECT_SELF) + "erno_dead", 1);


lines: 17 through 30: 
This section does nothing close to the comments say it is doing.   None of the actions have a chance to fire, the Henchman being dead will not even que up actions.  even if the action que was active, The ActionDoCommands would get added to the que, however  the Action que is already locked when they fire and try to add the actions they contain to the action que.    ActionDoCommand is normally used to add commands to the Action que in this maner, NOT OTHER ACTIONS.

The SetDestroyable function in this section is way to late.  If the Henchman is not already set to be non destroyable, it will do no good to try and set it now. the henchman is already well on his way to being destroyed.   This is another function that you will want to make sure is set when the henchman is added to the party. 

To get this section to do what it looks like it is tring to do simply changing it to 

 
if (GetDidDie()) return;
else SetDidDie();

GetDidDie and SetDidDie are wrapper functions around the NW_L_HEN_I_DIED var in  X0_I0_HENCHMAN. 


Line 33: 
Change it to a d8 since you have added more options.

Line 48 & 49: should be  DURATION_TYPE_INSTANT

Line55:  should only be ran if a valid connection to oMaster has been made This means that lines 46 - 63 should be removed to there own functoin for better control.   this will also allow us to make checks to see if combat is still going on before raising the henchman. 


With the above adjustments you end up with something like this. 

#include "nw_i0_generic"
#include "nw_i0_plot"
#include "X0_I0_HENCHMAN"

void ResHenchman(object oPC,string sLiner = "", object oHenchman =OBJECT_SELF)
{
   if ( GetIsInCombat (oPC) || !GetIsObjectValid(oPC))
   {
     DelayCommand(30.0,ResHenchman(oPC,sLiner,oHenchman));
     return;
   }


  ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectResurrection(), oHenchman);
  ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectHeal(GetMaxHitPoints(oHenchman)), oHenchman);
  //DelayCommand(30.75, SetIsDestroyable(TRUE, TRUE, TRUE));
  DelayCommand(1.0, SpeakString(sLiner));
  SetDidDie(FALSE);

  if (GetArea(oPC) == GetArea(oHenchman))
  {
    DelayCommand(1.5, AddHenchman(oPC, oHenchman));

    //Re-set the variable to get rid of annoying dialogueif the henchie has successfully re-joined
    DeleteLocalInt(oPC, GetResRef(oHenchman) + "erno_dead");

    //Set up the proper conditions for henchman as defined by the X2 script
    SetAssociateState(NW_ASC_IS_BUSY, FALSE,oHenchman);
    //SetAssociateListenPatterns();
    SetLocalInt(oHenchman, "NW_COM_MODE_COMBAT", ASSOCIATE_COMMAND_ATTACKNEAREST);
    SetLocalInt(oHenchman, "NW_COM_MODE_MOVEMENT", ASSOCIATE_COMMAND_FOLLOWMASTER);
    SetAssociateState(NW_ASC_IS_BUSY, FALSE,oHenchman);
  }
}
void main()
{
  //Define the former master
  object oMaster=GetLastMaster();
  //Define the henchman
  object oMe =OBJECT_SELF;

  //Set the HCH erno_dead variable, just in case the script goes wrong.
  //This means that you see a special bit of dialogue when you speak to the hench post-death, but only if something goes wrong, i.e. the PC moves areas
  SetLocalInt(oMaster, GetResRef(OBJECT_SELF) + "erno_dead", 1);


  //Double-hit thing to stop the body from getting destroyed or anything
  if (GetDidDie()) return;
  else SetDidDie();

  //Choose a random dialogue string
  string sRevive;
  int iRandom = d8();
  switch(iRandom)
  {
    case 1: sRevive = "Better luck next time, eh?"; break;
    case 2: sRevive = "Thank all the Gods that we pulled through that..."; break;
    case 3: sRevive = "That was... unpleasant, to say the least."; break;
    case 4: sRevive = "Oh my... how long was I out for?"; break;
    case 5: sRevive = "Well, there's one for the journal."; break;
    case 6: sRevive = "Argh, I can barely feel my legs!"; break;
    case 7: sRevive = "That was strangely invigorating!"; break;
    case 8: sRevive = "For the love of all things holy, let's be more careful next time!"; break;
  }
 
//Resurrect and remove effects, then add back the henchman
  DelayCommand(0.1, RemoveEffects(OBJECT_SELF));
  DelayCommand( 30.0,ResHenchman(oMaster,sRevive) );
}
 

  
 
EDIT:  Forgot to reset his death flag.   Done.
               
               

               


                     Modifié par Lightfoot8, 08 juillet 2012 - 01:43 .