Aller au contenu

Photo

DelayCommand


  • Veuillez vous connecter pour répondre
18 réponses à ce sujet

#1
Julian Gellert

Julian Gellert
  • Members
  • 18 messages
 I have this script...

---------------------------------------------------------------------------------------
#include "f_encounter_tables"

void respawn()
{
//Debug
SendMessageToPC(GetFirstPC(), "Delayed part fired!");
if (GetTag(OBJECT_SELF) != "SPAWN_POINT")
{
location lPoint = GetLocation(OBJECT_SELF);
string sTable = GetLocalString(OBJECT_SELF, "ENCOUNTER_TABLE");
string sTemplate = RollEncounterTable(sTable);
string sNo = IntToString(GetLocalInt(OBJECT_SELF, "ID_NUMBER"));
CreateObject(OBJECT_TYPE_CREATURE, sTemplate, lPoint, TRUE, sNo);
}
}

void main()
{
//Debug
string sTag = GetTag(OBJECT_SELF);
SendMessageToPC(GetFirstPC(), "Script successfully fired from " + sTag);
float fDelay = 12.0f;
DelayCommand(fDelay, respawn());
}
---------------------------------------------------------------------------------------

Which doesn't work.

However, if I remove the delay...

---------------------------------------------------------------------------------------
void main()
{
respawn();
}
---------------------------------------------------------------------------------------

Then it does work.

I've written dozens of delay scripts on this module alone, but I can't figure this out and currently have a headache, so... Help...?

I should also mention that this script is executed on a waypoint (another script causes it to fire, "executescript")

Modifié par Julian Gellert, 17 juin 2011 - 07:23 .


#2
Guest_Chaos Wielder_*

Guest_Chaos Wielder_*
  • Guests
I'm not sure why the specific code wouldn't work, but I wonder if you could just delay the ExecuteScript call?

#3
M. Rieder

M. Rieder
  • Members
  • 2 530 messages
Does it compile with the delay? Some functions don't play well with delaycommand().

#4
Julian Gellert

Julian Gellert
  • Members
  • 18 messages
It compiles... I can't delay the executescript, because it's on a creature that dies and decays... Otherwise I'd have all functions in the original script, no problem.

I did executescript to move it on something that sticks around, then delay it.

Modifié par Julian Gellert, 17 juin 2011 - 08:08 .


#5
MasterChanger

MasterChanger
  • Members
  • 686 messages
DelayCommand/AssignCommand is a tricky thing, to be sure. Since the "action" variable type can't actually be used to declare/define a variable, it's hard to know what kind of function can be passed as a command (other than that it should be a "void" function).

There was a recent discussion of this issue started by M. Rieder. Though that was geared towards delaying animations, looking over what Pain and Skywing have to say is useful.

One of the examples of DelayCommand being used for something like this by OEI is the Creeping Doom script. In NWN2, this went from being implemented as an AOE to a more brute-force method of using DelayCommand to make it apply every round. On the one hand, not using a true AOE has problems, but it does mean that the swarms stay on the target rather than staying confined to a particular area.

At any rate, the usage there is similar to what you've done, so I can't see what your respawn() function shouldn't be delayed properly. Are you not even getting the "Delayed part fired! message? Setting up such a test message would have been my first suggestion.

#6
Julian Gellert

Julian Gellert
  • Members
  • 18 messages
Exactly, I'm not getting it. I get the first message properly but nothing after the delay.

#7
MasterChanger

MasterChanger
  • Members
  • 686 messages

Julian Gellert wrote...

Exactly, I'm not getting it. I get the first message properly but nothing after the delay.


Ah, interesting to see that the problem's downstream. You could set up some more feedback to make sure your strings get defined correctly.

I'd also recommend OBJECT_SELF into the respawn function rather than re-determining it there. It's not that I think there's a specific problem with how you've got it set up, but I know some people (Pain especially, IIRC) recommend storing OBJECT_SELF in an object variable if you're going to be using it in widely-separated places. With a delay, particularly, I suspect this could become more of an issue.

#8
Julian Gellert

Julian Gellert
  • Members
  • 18 messages
 You mean like so?

void respawn(object oTarget)
{
//Debug
SendMessageToPC(GetFirstPC(), "f_wp_reset_encounter delay script fired!");
if (GetTag(oTarget) != "SPAWN_POINT")
{
//Debug
SendMessageToPC(GetFirstPC(), "f_wp_reset_encounter CreateObject script fired!");
location lPoint = GetLocation(oTarget);
string sTable = GetLocalString(oTarget, "ENCOUNTER_TABLE");
string sTemplate = RollEncounterTable(sTable);
string sNo = IntToString(GetLocalInt(oTarget, "ID_NUMBER"));
CreateObject(OBJECT_TYPE_CREATURE, sTemplate, lPoint, TRUE, sNo);
}
}

Still not working... Hmm... what kind of feedback messages could I have, if even the message on the first line doesn't work?

Modifié par Julian Gellert, 17 juin 2011 - 10:32 .


#9
M. Rieder

M. Rieder
  • Members
  • 2 530 messages
If you can't get the delay to work, you can create it, then script it hidden for 12 seconds. That way it would look like it spawns 12 seconds later.

#10
Julian Gellert

Julian Gellert
  • Members
  • 18 messages
That sounds painfully inefficient for a respawning monster deal :)

But it looks like this script hates delays. I wrote this line:

DelayCommand(fDelay, SendMessageToPC(GetFirstPC(), "See, I can do a delay!"));

And that doesn't work either.

#11
Lugaid of the Red Stripes

Lugaid of the Red Stripes
  • Members
  • 955 messages
Might be a problem with the waypoint object, try running it on an i-point instead.

#12
Julian Gellert

Julian Gellert
  • Members
  • 18 messages
Well I'll be able to sleep after all, I also thought it might be a problem with the object, since the script is sound, and some googling found other scripts that do it just fine...

I passed the executescript to the Area, as well as a variable so that it gets the correct waypoint. It seems to work! More testing tomorrow to find out what happens to this variable if multiple creatures die in quick succession (though I'm guessing it should be fine because it's set instantly?)

#13
SkywingvL

SkywingvL
  • Members
  • 351 messages
If an object is destroyed, any pending DelayCommands or AssignCommands attached to the object are canceled. Perhaps (given that you call this script "respawn") this is what is happening in this particular case. Sometimes this is what you want; sometimes it isn't.

If so, a workaround would be to queue the continuation against an object that you know will not go away. For example:

AssignCommand( GetModule( ), DelayCommand( fDelay, respawn( ) ) );

#14
painofdungeoneternal

painofdungeoneternal
  • Members
  • 1 799 messages
need to pass everything into the respawn function, so it knows what it is going to respawn. OBJECT_SELF actually can change depending on what things are assigned to.

Delayed commands need to have all objects they need, and anything dependent on the original script type - ie if you delay a command inside a spell script and try to get the spell class, and they cast another spell from a different class that value changes. What will happen is really complicated, and by putting it all in as parameters up front while more work, makes how it works being a lot less complicated.

#15
SkywingvL

SkywingvL
  • Members
  • 351 messages

painofdungeoneternal wrote...

need to pass everything into the respawn function, so it knows what it is going to respawn. OBJECT_SELF actually can change depending on what things are assigned to.

Delayed commands need to have all objects they need, and anything dependent on the original script type - ie if you delay a command inside a spell script and try to get the spell class, and they cast another spell from a different class that value changes. What will happen is really complicated, and by putting it all in as parameters up front while more work, makes how it works being a lot less complicated.


OBJECT_SELF is the object that the DelayCommand continatuation is attached to.  This is the callers OBJECT_SELF unless the caller changes it via ExecuteScript or AssignCommand.

#16
Shallina

Shallina
  • Members
  • 1 011 messages
The solution is to run the script on an object that doesn't decay.

You "wrap" your action on a script, and you run a executescript on an object that doesn't decay (the module or the area or the player for exemple).

#17
Julian Gellert

Julian Gellert
  • Members
  • 18 messages
 Exactly, it was running on a waypoint. And I know it was running on the proper waypoint because it sent me a message with its tag.

This was how I did it before, to avoid monster decay:

object oTarget = GetWaypointByTag( "SPAWN_POINT_" + sNo );
ExecuteScript("f_wp_reset_enc", oTarget);


The script fired, and on the right waypoint, but any delays in it were ignored.

This is how I am doing it now:

SetLocalInt(GetArea(OBJECT_SELF), "LAST_KILLED", StringToInt(sNo));
ExecuteScript("f_wp_area_enc", GetArea(OBJECT_SELF));


And it works perfectly.

I was afraid that if multiple creatures die quickly, the LAST_KILLED int would break, but it doesn't... Probably because it's used before the delay on the area script.

string sNo = IntToString(GetLocalInt(OBJECT_SELF, "LAST_KILLED"));
string sTag = "SPAWN_POINT_" + sNo;
object oTarget = GetWaypointByTag(sTag);
DelayCommand(fDelay, respawn(oTarget));


void respawn(object oTarget) creates a creature on the right waypoint.

Modifié par Julian Gellert, 18 juin 2011 - 08:02 .


#18
SkywingvL

SkywingvL
  • Members
  • 351 messages

Shallina wrote...

The solution is to run the script on an object that doesn't decay.

You "wrap" your action on a script, and you run a executescript on an object that doesn't decay (the module or the area or the player for exemple).


You can also use AssignCommand to 'change' OBJECT_SELF this way, without having to go through the trouble of ExecuteScript, BTW.

#19
The Fred

The Fred
  • Members
  • 2 516 messages
Don't you get some funny behaviour with effect creators, though? I seem to remember that if you have someone deal damage, say, through AssignCommand, it's still considered to be the script-executor's fault in terms of making people go hostile. I'm not sure if this was specific to NWN1, though, and it's a bit of a niche issue.