Hello Holowanians!
This is for K1.
I am attempting to spawn an NPC into a module using the script injection method. I have successfully spawned the NPC, and utilizing UserDefinedEvents I have the NPC engaging the NPC upon perception.
What I would like is for this particular NPC to be *invisible* until the PC is "perceived". At that point, I want to apply the effect of uncloaking to the NPC to make her visible, and then initiate the dialog. I imagine that I simply need to add a couple lines in my script that fires on perception, before the command that fires the dialog. What those lines might be...
Anyone know how to accomplish this? My inclination is to look at the scripts for the hidden Mandalorians in the Shadowlands, or the Trandoshans on Yavin Station. Just wondered if anyone around had some insight or, a short-cut?
EDIT: Here is the current code that is being used by the NPC's UserDefinedEvent script field in it's .utc.
// qgg this is nwn script for the onperception field of the
creature user defined events
// the on perception has to be uncommented on the creatures
onspawn scripts, default is k_def_percept01.nss found in
scripts.bif (thanks tk102!!!)
// script modified and adapted from the work of Darth333, tk102,
Doc Valentine and David Gaider
void main()
{
int nEvent = GetUserDefinedEventNumber();
// if the OnPerception event was fired
if (nEvent == 1002) // OnPerception event
{
object oPC=GetFirstPC();
object oSpeaker=GetObjectByTag("qg_sithstalker");
ActionDoCommand(SetFacingPoint(GetPosition(oPC)));
AssignCommand(oSpeaker,ActionMoveToObject(oPC));
AssignCommand(oSpeaker,ActionStartConversation(oPC ,"sithstalking"));
}
}
This code is fine, works, just doesn't do all that I would like...
It occurs to me now that perhaps what I need is to not alter this script, rather that I need to have a scripted sequence play out when the PC makes it to this trigger point.
Hmmm... I am not sure how to express better what I am trying to do, so I am sorry that I cannot ask better questions at this time. I will continue to study...
Thanks in advance :)
EDIT #3
Merged from later post I deleted, a few funnies (to me at least, and I know others have seen these and probably mentioned them here before)...
Well, as I continue to part learn/part confuse myself, I thought I would share with you the things I enjoyed most from nwscript. These are potentially useful, but I like them for the desperate humor of the devs... I did manage to find many helpful ideas, so perhaps I will update this previous post with a better question or maybe even a solution... until then, I present to you the humor of BioWare's nwscript.nss
int PLOT_O_DOOM = 0;
int PLOT_O_SCARY_STUFF = 1;
int PLOT_O_BIG_MONSTERS = 2;
// 159: Choke the bugger...
effect EffectChoke( );
// 471: Make the creature horified. BOO!
effect EffectHorrified( );
// 599: a bunch of Is functions for your pleasure
// 771. YavinHackCloseDoor
// This is an incredibly hacky function to allow the doors to be properly
// closed on Yavin without running into the problems we've had. It is too
// late in development to fix it correctly, so thus we do this. Life is
// hard. You'll get over it
If the script you're doing should fire when the player reaches a certain point, then it's better to use a trigger for that.. I believe there's a tutorial on triggers on this site.
Now as for the functions, to remove the invisibility, you're gonna have to run one effect on the NPC (the one that does the transition visual effects and sound), then remove one that should run immediately when the creature is spawned (ie via the OnSpawn script - it's the effect that makes the NPC actually invisible).
ApplyEffectToObject(1, EffectVisualEffect(8001), oNPC);
DelayCommand(??, RemoveEffectByID(oNPC, 8000));
The problem now is that the RemoveEffectByID() function is only available in TSL, so in K1 you will have to make a while statement and use GetFirstEffect() and GetNextEffect() to cycle through the effects that are running on the NPC, then use GetEffect(Sub)Type() to identify the right effect and remove it (via RemoveEffect() ...).
If you need help with anything else, ask.
If the script you're doing should fire when the player reaches a certain point, then it's better to use a trigger for that.. I believe there's a tutorial on triggers on this site.Yeah, there are a few ways to skin this cat, and I had been trying to simply keep it an override affair. I may use a trigger just for simplicities sake, but I am not sure at this point.... The invisible placeable seemed like a good idea as it would perform like a trigger, but yes it is more complicated. But yeah, there are trigger examples and tut's here, I've been reading them for a week as I have been working out how to best accomplish this little deal.
Now as for the functions, to remove the invisibility, you're gonna have to run one effect on the NPC (the one that does the transition visual effects and sound), then remove one that should run immediately when the creature is spawned (ie via the OnSpawn script - it's the effect that makes the NPC actually invisible).
ApplyEffectToObject(1, EffectVisualEffect(8001), oNPC);
DelayCommand(??, RemoveEffectByID(oNPC, 8000));
The problem now is that the RemoveEffectByID() function is only available in TSL, so in K1 you will have to make a while statement and use GetFirstEffect() and GetNextEffect() to cycle through the effects that are running on the NPC, then use GetEffect(Sub)Type() to identify the right effect and remove it (via RemoveEffect() ...).
If you need help with anything else, ask.
^^^ Ok. Let me see if I am following you correctly.
It makes sense that I would have to first make the NPC invisible before actually uncloaking her - you can't uncloak if you ain't cloaked! So, I could add the "ApplyEffectToObject" line in the OnSpawn for the NPC, and this would make the NPC invisible?
If that is the case, I think we are making headway. I already have a working UserDefined script based on perception, so the scripting to "uncloak" the NPC could be added there.
I am not 100% sure I follow you on having to isolate the Effect that is applied on the NPC. Don't we know what it is... why do we need code to look up what it is? I have made a little while loop trying to show myself what you are thinking, and I kinda see what you are getting at, just not sure why.
Regardless, thank you for the Effect script! Hopefully you will follow my questions... :)
EDIT: Currently looking through visualeffects.2da and animations.2da... I am going to try and make a few things work, and we shall see where we get. There is in visualeffects.2da line 2001 - invisibility, which I would not have found if not for your post, bead-v! Also, there is force whirlwind.... there are many instances of forcewhirlwind, I wonder which one I am looking for...
Also, do I need to remove the old effect? Wouldn't the second script applying the new effect override the old effect? I will test this, but it seems like that should be the case, which almost certainly means it wont.
Ok.... here is where I am at currently.
I have tried to make the NPC invisible by applying the visual effect of invisibility (2001) and stealth field (8002), which currently are being applied to the NPC in the area's OnEnter script.
The UserDefined script, where the NPC perceives the PC and uncloaks, is working well enough... I would like to add a little delay to the action, and I have tried to do that a couple ways, but I think I am misunderstanding the parameters I should be entering to the function call.
Here is the current UserDefined script:
// qgg - this is for the UserDefinedEvent, on Perception
void main()
{
int nEvent = GetUserDefinedEventNumber();
if (nEvent == 1002) // OnPerception event
{
object oPC=GetFirstPC();
object oSpeaker=GetObjectByTag("qg_sithstalker");
ActionDoCommand(SetFacingPoint(GetPosition(oPC)));
EnableVideoEffect(8001);
// a delay of some sort here would be nice!
ApplyEffectToObject(1, EffectVisualEffect(8001), oSpeaker);
AssignCommand(oSpeaker,ActionMoveToObject(oPC));
DisableVideoEffect();
AssignCommand(oSpeaker,ActionStartConversation(oPC ,"sithstalking"));
}
}
So, the scene plays out alright with the exception of the invisibility, and I want to embellish the scene with some combat animations. As far as that goes, I was not sure which animation in the animations.2da corresponded to a force user "casting" the force. Is it one of the "castout" entries?
Ideally, I want the NPC to cast a Whirlwind or a Choke on the PC, and then release the PC, leaving the PC in a stupor, looking slunched, and then the convo begins, with the PC remaining in the stupor-state until the last line of the dialog. It would play out similar to the dialog with the Crazed Sith Master in korriban when he has you and, I think, Mekel?
Anyway, wanted to post where I was at, hopefully someone has a suggestion or idea. Thanks!
The invisible placeable seemed like a good idea as it would perform like a trigger, but yes it is more complicated.
I'm not sure there's an OnPercieved event for placeables, you should check to make sure. Another possibility would be to make a script that would check your location and if you aren't at the right location it runs the script again.. But I think setting a trigger is the most simple solution. At least for me.
So, I could add the "ApplyEffectToObject" line in the OnSpawn for the NPC, and this would make the NPC invisible?
Correct you are.
I am not 100% sure I follow you on having to isolate the Effect that is applied on the NPC. Don't we know what it is... why do we need code to look up what it is? I have made a little while loop trying to show myself what you are thinking, and I kinda see what you are getting at, just not sure why.
It's because of the RemoveEffect() function. You need to specify the exact effect that should be removed. Now in your case there will be at least two effects running when you remove it (the uncloaking effect and the invisibility effect). In TSL you'd just enter the right ID and it would get you exactly that effect. In k1 that function doesn't exist, so you have to find another way to determine which effect is which.
You'd first get the GetFirstEffect(), then check whether it's the invisibility effect. If not, you'll use GetNextEffect() to get the next effect (dooh), and check whether that is the right one. If so, you'll save it into an effect variable (for example eEffectVar), then later use the RemoveEffect(oNPC, eEffectVar) to remove the right effect.
There is in visualeffects.2da line 2001 - invisibility, which I would not have found if not for your post, bead-v! Also, there is force whirlwind.... there are many instances of forcewhirlwind, I wonder which one I am looking for...
Don't know how 2001 works, I only really know about 8000/1. As for the whirlwinds, try one and see if it's right, if not try the next one. =)
Also, do I need to remove the old effect? Wouldn't the second script applying the new effect override the old effect?
No, you can have multiple effects running on an object.
I would like to add a little delay to the action, and I have tried to do that a couple ways, but I think I am misunderstanding the parameters I should be entering to the function call.
Do:
DelayCommand(float fDelay, ACTION());
For example:
DelayCommand(0.5, EnableVideoEffect(8001)); //This is a 0.5 second delay
As far as that goes, I was not sure which animation in the animations.2da corresponded to a force user "casting" the force. Is it one of the "castout" entries?
I would recommend using the animation from nwscript.nss. The force casting animation number is 121.
deally, I want the NPC to cast a Whirlwind or a Choke on the PC, and then release the PC, leaving the PC in a stupor, looking slunched, and then the convo begins, with the PC remaining in the stupor-state until the last line of the dialog. It would play out similar to the dialog with the Crazed Sith Master in korriban when he has you and, I think, Mekel?
All the animations you need are in nwscript.nss, you can use those.
It's because of the RemoveEffect() function. You need to specify the exact effect that should be removed. Now in your case there will be at least two effects running when you remove it (the uncloaking effect and the invisibility effect)... In k1 that function doesn't exist, so you have to find another way to determine which effect is which.
You'd first get the GetFirstEffect(), then check whether it's the invisibility effect. If not, you'll use GetNextEffect() to get the next effect (dooh), and check whether that is the right one. If so, you'll save it into an effect variable (for example eEffectVar), then later use the RemoveEffect(oNPC, eEffectVar) to remove the right effect.Ok. I thought this was the reasoning for the while loop, but I needed a little clarification, and a reminder that I needed to make a variable (eEffectVar). How do I declare that? Like this: int eEffectVar?
I also did not know about the reality of potential applied multiple effects... Good stuff!
Don't know how 2001 works, I only really know about 8000/1. As for the whirlwinds, try one and see if it's right, if not try the next one. =)Right... I think that I have the right footing now to fool around... I will make a bunch of animation scripts, see how things play out in a test vehicle.
Do:
DelayCommand(float fDelay, ACTION());
For example:
DelayCommand(0.5, EnableVideoEffect(8001)); //This is a 0.5 second delay
Excellent! This was exactly the case where I did not understand how to correctly pass the parameter for the "float fDelay". I was missing that it was simply a float value!! Thanks again!
I would recommend using the animation from nwscript.nss. The force casting animation number is 121.I think that is one of the castout anim's I was looking at, but I will double check. I was looking directly at animation .2da, I should have referred to the listing of them in nwscript.
All the animations you need are in nwscript.nss, you can use those.Yeah... I was not sure which were which in some cases, but I think I can go from here for the time being. If I have a related question in this area, I will bring it back!
Thank you for taking the time, bead-v :D
Ok. I thought this was the reasoning for the while loop, but I needed a little clarification, and a reminder that I needed to make a variable (eEffectVar). How do I declare that?
Nope, like this:
effect eEffectVar;
I think that is one of the castout anim's I was looking at, but I will double check. I was looking directly at animation .2da, I should have referred to the listing of them in nwscript.
It's possible they overlap, but generally the numbers in the 2da aren't the same as in the nwscript.nss. But if you ever want to use an animation from animations.2da, unlike the animation numbers from nwscript, these animation need to be used like this: 10XXX, where XXX is the number in animations.2da. If you wanted animation 3 from the 2da, you'd use 10003, if you wanted 252, you'd use 10252, and so on..
And you're welcome, I'm happy to help..
I have further questions, I think, since you are willing :)
For now, the easy one... where are you getting the value 121 from in nwscript? Is that from TSL? I find no instance of an effect in nwscript or in any corresponding .2da for "121" and using the "Find" option in the KTool text editor, looking for "121" in nwscript for k1, only turned up a female disguise and a script function for time conversion??
EDIT: Also, the invisibility VFX is listed in both the nwscript and the .2da, same reference number, so I feel like it should work.... if I can work things out!
Is that from TSL?
...... yes ..... Sorry, I'm so very used to the fact that I always have to go the TSL folder to check things out that I simply forgot it wasn't for TSL this time. Sorry, it looks like you will have to use the 2da animation. Try to find a name that suggests that could be it, and try it in the game.
As for the invisibility VFX, try it and you'll see if it works. =P
...... yes ..... Sorry, I'm so very used to the fact that I always have to go the TSL folder to check things out that I simply forgot it wasn't for TSL this time. Sorry, it looks like you will have to use the 2da animation. Try to find a name that suggests that could be it, and try it in the game.Ok, good... thought I was going crazy there for a bit, and I searched through every .2da in the game looking for a 121 that seemed likely!
Regarding the script, I have now a rough script that will not compile - I am sure that it is mostly regarding incorrectly defined variables, incorrectly passed params in the functions, and possibly a bad algorithm (although that shouldn't stop compilation, just proper function :p ). Here is my current code, and there are some commented sections I will, ahem, comment on, following the code...
// * qg_stalkpercp.nss
// * Jan 06 2011
// * First novel script... will explode upon compilation
// * This is for the UserDefinedEvent, on Perception
void main()
{
int nEvent = GetUserDefinedEventNumber();
effect eInvis = EffectVisualEffect(2001);
effect eCloaked = EffectVisualEffect(8001);
if (nEvent == 1002) // OnPerception event
{
object oPC=GetFirstPC();
object oStalker=GetObjectByTag("qg_sithstalker");
ActionDoCommand(SetFacingPoint(GetPosition(oPC)));
ApplyEffectToObject(1, EffectVisualEffect(8001), oStalker, 2.0f);
int iFX = 0;
effect eCheckFX = GetFirstEffect(oStalker);
while (iFX <2)
{
while (GetisEffectValid(eCheckFX)
{
if (eCheckFX == eInvis) // set in qg_stalkonspawn
{
RemoveEffect(oStalker,eCheckFX);
AssignCommand(oStalker,ActionMoveToObject(oPC));
iFX = 1;
}
else
{
eCheckFX = GetNextEffect(oStalker);
}
if (iFX == 1)
{
if (eCheckFX == eCloaked)
{
DelayCommand(1.0, RemoveEffect(oStalker,eCheckFX);
void ActionCastFakeSpellAtObject(9, oPC, 1);
iFX = 2;
}
else
{
eCheckFX = GetNextEffect(oStalker);
}
}
}
}
AssignCommand(oPC, ActionPlayAnimation(ANIMATION_LOOPING_CHOKE));
// should be persistent with convo, would prefer punch drunk stupor on PC, oh well
// could also be (ANIMATION_LOOPING_LISTEN_INJURED)
// ApplyEffectToObject(2, EffectVisualEffect(1004), oPC, 10.0f);
// * i imagine i could just kill the effect with a basic while loop in the script that fires
// at conversation end, qg_stalkattack... the injection anim from the
// dlg default, then the end of the woozy PC effect, then combat begins */
AssignCommand(oStalker,ActionStartConversation(oPC ,"sithstalking",CONVERSATION_TYPE_CINEMATIC));
}
}
The structure of the "while" seems sound, although the nested if's inside are far from elegant.
I don't think you would have steered me this way for no reason, so I guess I remain a little confused. Hopefully though, you can help me with where I am going wrong.
When I attempt to compile, the main complaints are the variables iFX and eCheckFX... I have tried eCheckFX as an int and as an effect, no joy either way. Also, the else's come up as compiler errors, so I wonder if it is bad logical structure, or just brackets placed incorrectly... hopefully just the latter!
As for the invisibility VFX, try it and you'll see if it works. =PYou are so right! I need to drop this big script for a minute and just make some animation test scripts to insert, see what happens. Laziness, procrastination, stubbornness, singlemindedness... all of these are my enemies right now, seemingly contradictory qualities, but I have them all simultaneously right now. I guess this is modding :lol:
EDIT: Changed the code in the post to reflect the most recent, failed, iteration
EDIT2: Newer code posted, only have errors with brackets and semi-colon, as far as syntax is concerned. whether the code is doing what i want is a whole 'nuther story!!!
EDIT3: New code below. Thanks to bead-v for all the help so far, we are now quite close I believe, and I will explain what I learned when it is all over :devsmoke:
// * qg_stalkpercp.nss
// * Jan 06 2011
// * First novel script... will explode upon compilation
// * This is for the UserDefinedEvent, on Perception
void main()
{
int nEvent = GetUserDefinedEventNumber();
effect eInvis = EffectVisualEffect(2001);
effect eCloaked = EffectVisualEffect(8001);
if (nEvent == 1002) // OnPerception event
{
object oPC=GetFirstPC();
object oStalker=GetObjectByTag("qg_sithstalker");
ActionDoCommand(SetFacingPoint(GetPosition(oPC)));
ApplyEffectToObject(1, EffectVisualEffect(8001), oStalker, 2.0f);
effect eCheckFX = GetFirstEffect(oStalker);
While (GetisEffectValid(eCheckFX)
{
if (eCheckFX == eInvis) // set in qg_stalkonspawn
{
RemoveEffect(oStalker,eCheckFX);
}
else
{
eCheckFX = GetNextEffect(oStalker);
}
AssignCommand(oStalker,ActionMoveToObject(oPC));
ActionCastFakeSpellAtObject(9, oPC, 1);
AssignCommand(oPC, ActionPlayAnimation(ANIMATION_LOOPING_CHOKE));
// should be persistent with convo, would prefer punch drunk stupor on PC, oh well
// could also be (ANIMATION_LOOPING_LISTEN_INJURED)
// ApplyEffectToObject(2, EffectVisualEffect(1004), oPC, 10.0f);
// * i imagine i could just kill the effect with a basic while loop in the script that fires
// at conversation end, qg_stalkattack... the injection anim from the
// dlg default, then the end of the woozy PC effect, then combat begins */
AssignCommand(oStalker,ActionStartConversation(oPC ,"sithstalking",CONVERSATION_TYPE_CINEMATIC));
}
}
I have a working script! Needs some tweaking now, but I will share the working code with you, and edit the post later to explain a little what I learned. Not sure if it will be helpful for anyone down the road, but I sure learned alot.
I give a big THANK YOU to bead-v especially and Varsity Puppet for taking their time to chat with me on this and show me where I was nutty, dead wrong, and occasionally on the right path :)
// * qg_stalkpercp.nss
// * Jan 06 2011
// * This is for the UserDefinedEvent, on Perception
void main()
{
int nEvent = GetUserDefinedEventNumber();
effect eInvis = EffectVisualEffect(2001);
effect eCloaked = EffectVisualEffect(8001);
if (nEvent == 1002) // OnPerception event
{
object oPC=GetFirstPC();
object oStalker=GetObjectByTag("qg_sithstalker");
ActionDoCommand(SetFacingPoint(GetPosition(oPC)));
ApplyEffectToObject(1, eCloaked, oStalker, 2.0);
effect eCheckFX = GetFirstEffect(oStalker);
while (GetIsEffectValid(eCheckFX))
{
if (eCheckFX == eInvis) // set in qg_stalkonspawn
{
RemoveEffect(oStalker,eCheckFX);
eCheckFX = GetNextEffect(oStalker);
}
}
AssignCommand(oStalker,ActionMoveToObject(oPC));
ActionCastFakeSpellAtObject(9, oPC, 1);
AssignCommand(oPC, ActionPlayAnimation(ANIMATION_LOOPING_CHOKE, 1.0, 12.0));
// would prefer punch drunk stupor on PC, could also be (ANIMATION_LOOPING_LISTEN_INJURED)
// ApplyEffectToObject(2, EffectVisualEffect(1004), oPC, 10.0);
DelayCommand(5.0, AssignCommand(oStalker,ActionStartConversation(oPC ,"sithstalking",CONVERSATION_TYPE_CINEMATIC)));
}
}
For those that are curious, this script is supporting the upcoming update release to Force Fashion for K1, and will be introducing a cool new armor j7 has made for us! You can see the armor in his "tinkerings" thread, it is the Sith Stalker! of course :p
For those that are curious, this script is supporting the upcoming update release to Force Fashion for K1, and will be introducing a cool new armor j7 has made for us! You can see the armor in his "tinkerings" thread, it is the Sith Stalker! of course
If you had told me that, I would have made the script for you! I love that Sith Stalker! =P
Lol, you still need to put the "eCheckFX = GetNextEffect(oStalker);" out of the if to make it perfect, but it seems the first effect is the effect you need anyway, so there's no real need. Good job!
If you had told me that, I would have made the script for you! I love that Sith Stalker! =P
It is a great skin! I am glad I kept it secret this long though, or I would have learned much less :)
Lol, you still need to put the "eCheckFX = GetNextEffect(oStalker);" out of the if to make it perfect, but it seems the first effect is the effect you need anyway, so there's no real need.
No, I think there is a need, actually... logically you are correct (doy) and I think it also is affecting things, although I will need to test things a bit more to be sure where my hiccups are.
Basically, 2001 invisibility does not work, regardless. I either need a new way to do invisibility, or I need to simplify the whole thing and just use a trigger to spawn this nasty gal.
Good job!Hehe... not done yet! The script shown here does everything we want for the most part, yet does it with awful timing :lol: I have tried to add some delays to things, and I think that has stopped the .dlg from firing.
No, I think there is a need, actually... logically you are correct (doy) and I think it also is affecting things, although I will need to test things a bit more to be sure where my hiccups are.
Basically, it works for your case because the effect you need to remove is the first one on the object, but the same thing might not work for a different effect, or on a different object.
Basically, 2001 invisibility does not work, regardless. I either need a new way to do invisibility, or I need to simplify the whole thing and just use a trigger to spawn this nasty gal.
Just use the 8000 VFX. Apply it to the stalker when he is spawned and take it off when the PC is perceived (with the while loop).
Hehe... not done yet! The script shown here does everything we want for the most part, yet does it with awful timing :lol: I have tried to add some delays to things, and I think that has stopped the .dlg from firing.
You need to set a delay for firing the dlg too.. As for the timing, just keep trying until it works, there's no way around it unfortunately..
I believe there's a much easier way to cloak an NPC than what you're trying here:
AssignCommand(oObject, ActionUseSkill(2, oAtton, 0, GetItemInSlot(10, oObject)));
That tells the NPC to use their stealth skill (2, as noted in NWScript) with their belt item (10, also noted in NWScript). Now, if the NPC doesn't have a belt item, it might be possible to specify a feat or Force power as well. Or if that fails, and you really, really don't want a stealth belt to be on their remains, you could attach a script to remove the item from them upon death. The item might not even be necessary, though. You'll just have to fiddle around with that aspect.
As far as I can remember I used this once ages ago in K2, and it worked perfectly - though I used it in conjunction with Visual Effect 8001 for the decloak effect.
^^^ JCarter, this is interesting in light of the difficulties I am having now with my script. I would still like to do things *this way* just as a proof-of-concept (to myself), but if I cannot make it work, I will have to go the route you have laid. This is for K1 though...
At bead-v, and anyone else interested:
Well, there have been a few interesting developments since last I updated things.
First of all, applying effect 8000 does indeed create "DISTORTION"/invisibility. I have done this in the area OnEnter, applying the Effect to oStalker with a duration of permanent. According to our forum, nwscript and many other resources, this effect will not be removed until it is forceably removed via RemoveEffect. Thus the need for the while loop that has been discussed in this thread.
I am not sure if the problem is in the OnEnter script and how I am applying the effect, or if the perception script I am using is simply not doing it's job, despite compiling and working in other ways, as the scripted events following the loop play out fine now. Previously, the dialog would not start at all, so something has changed to the positive.
So, once again, let me post some code.
First, the OnEnter script:
// qg - this is either for the trigger or the on-enter, TBD
void main()
{
effect eInvis = EffectVisualEffect(8000);
if (!GetIsObjectValid(GetObjectByTag("qg_sithstalker")))
{
CreateObject(OBJECT_TYPE_CREATURE, "qg_sithstalker", Location(Vector(76.90,84.12,0.00), 0.0));
object oStalker=GetObjectByTag("qg_sithstalker");
ApplyEffectToObject(2, eInvis, oStalker);
}
ExecuteScript("qg_pnd_1b_area", OBJECT_SELF);
}This script has been changed a few times, most recently I had to add a duration to the ApplyEffect line, as it refused to compile otherwise (although it had compiled without it several times before this.... ?? ) The duration type is PERMANENT, which is still supposed to be removable with RemoveEffect. I could change this to a TEMPORARY, but I have no idea how long to float it out, as events that occur before the confrontation may take longer/shorter - I can't have the Stalker stripping the cloak off and just hang out visible for the PC to find.
Here is the latest version of the perception script - it is the evolution of the script posted here several times before.
// * qg_stalkpercp.nss
// * Jan 06 2011
// /* This is for the UserDefinedEvent slot, or can be broken up from here
// into several smaller dialog slot scripts */
void main()
{
int nEvent = GetUserDefinedEventNumber();
effect eUncloak = EffectVisualEffect(8001); // is VFX_DUR_CLOAK_REMOVAL, says DUR is actually FNF
effect eInvis = EffectVisualEffect(8000);
if (nEvent == 1002) // OnPerception
{
object oPC=GetFirstPC();
object oStalker=GetObjectByTag("qg_sithstalker");
effect eCheckFX = GetFirstEffect(oStalker);
while (GetIsEffectValid(eCheckFX))
{
if (eCheckFX == eInvis) // was eInvis
{
RemoveEffect(oStalker,eCheckFX);
}
eCheckFX = GetNextEffect(oStalker);
}
ActionDoCommand(SetFacingPoint(GetPosition(oPC)));
ApplyEffectToObject(0, eUncloak, oStalker);
AssignCommand(oStalker, ActionMoveToObject(oPC));
ActionCastFakeSpellAtObject(9, oPC);
AssignCommand(oPC, ActionPlayAnimation(116, 1.0)); // Chokes the PC
AssignCommand(oStalker,ActionStartConversation(oPC ,"sithstalking",CONVERSATION_TYPE_CINEMATIC));
}
}
So.... the while loop does not do it's job right now, yet is not an infinite loop either, as it does kick out and let things continue. So, anyone understand why the Effect is not being removed? Is it the duration that I have set in the OnEnter? Is the while loop flawed? My thought is that the way I am looking for eInvis might be flawed - that I need to use a more specific function to narrow things.... but I am grasping at straws, really. Logically, the script seems sound, so I think it must be the permanence of the applied Effect - hmmmm........................ yuck.
This is for K1 though...
It shouldn't matter, they share the same code in this respect.
As for your looping problem... only thing I can think of would be to try temporary... since there's no way to set the duration in the effect string, I'd guess that means it's designed to stay on until it's turned off (unlike, for example, a knockdown effect).
...there's no way to set the duration in the effect string, I'd guess that means it's designed to stay on until it's turned off (unlike, for example, a knockdown effect).There is a way to set the duration, it is just a guess though and not perfect, as the PC would have a chance to do, well, whatever a PC does sometimes.
There are the 3 duration types, instant (used for fire/forget animations like 8001) temporary and permanent. These are, in integers: 0,1 and 2, respectively.
So, if I want a temporary effect, I must set the duration of the temporary effect, which is done by a float value in the last parameter of the ApplyEffect command. If I try to make it temporary, ie: value 1, then I must set a duration or it will not compile. The duration is the x factor.... which more and more leads to doing this whole deal with a trigger instead. However, we are very close to this thing, it is not far from working methinks, so I want to understand what is failing and why. That way, I learn, become a better scripter, and can improve my own work and better help that of others!
As for the mention of K1, I wasn't sure if the same functions were all available, with the same passable params as in your script, in TSL. If it is as you say, cool! It will be useful at some point, I am sure :D
This is what worked for me in TSL:
DelayCommand(0.8, ApplyEffectToObject(3, EffectVisualEffect(8000), oNPC, -1.0));
Don't ask me why, because I don't know.. Just keep trying, it shouldn't take you a lot of time to try all the options...
As for the perception script, you should really add some delays to the second part, just so everything doesn't happen at once, so you'll be able to at least tell what's going on, ie. what's working and what isn't...
This is what worked for me in TSL:
DelayCommand(0.8, ApplyEffectToObject(3, EffectVisualEffect(8000), oNPC, -1.0));
Don't ask me why, because I don't know.. Just keep trying, it shouldn't take you a lot of time to try all the options...Duration 3, -1.0 for the time of duration.... wow. I wouldn't have thought.... is that a "custom" duration... I feel all of sudden like I know waaaaaaay less than I thought :|
Thanks though, I will see how that goes!
As for the perception script, you should really add some delays to the second part, just so everything doesn't happen at once, so you'll be able to at least tell what's going on, ie. what's working and what isn't...
I need to add the delays back in... At a certain point, I wasn't sure what was breaking the scene and so one by one I removed anything extraneous to troubleshoot the issue. I could have done this by commenting out pieces of code, but instead I just saved a dozen versions of the script, and only posted the one that was in the current state.
I will try and catch up with you bead-v, I am a little confused!
Oh, so you can set the duration. Yeah, see, that's -1 then. -1 means to keep it on until something else is triggered... this applies for other things as well, like animations. Sorry, I wasn't thinking clearly before, 'twas late and I was in the middle of scripting myself... it rots your brain, it does.
The OnEnter was changed to reflect (3, , , -1.0) as the duration.... just occurs to me that I will try the duration type as 1 as it was before... maybe the -1 is enough. Cross fingers... nope. No invisibility at all in that case. :(
// * qg_stalkpercp.nss
// * Jan 06 2011
// /* This is for the UserDefinedEvent slot, or can be broken up from here
// into several smaller dialog slot scripts */
void main()
{
int nEvent = GetUserDefinedEventNumber(); // OnPerception
effect eUncloak = EffectVisualEffect(8001); // VFX_DUR_CLOAK_REMOVAL, says DUR is FNF
effect eInvis = EffectVisualEffect(8000); // VFX_DUR_DISTORTION
if (nEvent == 1002)
{
object oPC=GetFirstPC();
object oStalker=GetObjectByTag("qg_sithstalker");
effect eCurrent = GetFirstEffect(oStalker);
while (GetIsEffectValid(eCurrent))
{
if (GetEffectType(eCurrent) == 8000) // testing without eInvis, does not like _DIST...
{
RemoveEffect(oStalker,eCurrent);
}
eCurrent = GetNextEffect(oStalker);
}
ActionDoCommand(SetFacingPoint(GetPosition(oPC)));
DelayCommand(1.5, ApplyEffectToObject(0, eUncloak, oStalker));
DelayCommand(1.0, AssignCommand(oStalker, ActionMoveToObject(oPC)));
DelayCommand(6.0, ActionCastFakeSpellAtObject(9, oPC));
DelayCommand(8.0, AssignCommand(oPC, ActionPlayAnimation(ANIMATION_LOOPING_CHOKE, -1.0)));
DelayCommand(9.5, AssignCommand(oStalker,ActionStartConversation(oPC ,"sithstalking",CONVERSATION_TYPE_CINEMATIC)));
}
}
Ok, here is the good news - cinematics play out as they should: the scene is timing out well enough that I can say it seems "directed", and just needs some fine tuning. The order of events is correct, in any case. The dialog fires as it should, the animations are all working.
But... the inability to remove the effect persists. It is at this point, boggling to me, in that I have literally used David Gaider's script to do this thing, and though compiling like mine, it does nothing.
The problem must be either in how the duration is being set in the OnEnter, or that the while loop is not catching the effect....
I am going to try and decompile some of the k_pkas_mand* files and if so, I will hopefully figure out how BioWare has done this... it could be that it is only possible to achieve this specific cinematic decloaking, that it must be done by a trigger where the creature is spawned in with the 8001 effect only.
Well... little steps...
I tried to ask this last night, but LF was down... anyway...
Have you tried applying an invalid effect after 8000 is in place? Theoretically if 8000's duration is negative, it should go away once any effect is applied. I'd suggest you do this (in addition to trying to remove the effect, if that fails) outside the while branch, and if it works, test it inside the while branch... if it doesn't work, then your problem's clear.
Well, I am currently trying several different things, including the recommendations of VP and bead-v to ClearAllEffects, as well as trying to re-apply the effect before removing it. Putting in an INVALID effect is an interesting idea as well. On that note, I have been doing homework, and have an enlightening piece from the lexicon. GetEffectType is definitely being used incorrectly by yours truly, as well as most scripters, IIUC.
GetEffectType: Description
Returns the effect type (EFFECT_TYPE_*) of the effect being examined.
Return EFFECT_INVALIDEFFECT if effect is invalid.
Following the link, these are the EFFECT_TYPE's: LINK (
http://www.nwnlexicon.com/compiled/constant.effect_type.html)
I think that when I use GetEffectType(eCurrent), the value it returns is EFFECT_TYPE_VISUALEFFECT, which is defined in the lexicon as
An effect constructed with EffectVisualEffect.This is the case, as I did apply the effect using EffectVisualEffect. This is another thing to consider... having I been screwing myself by using that as the effect, rather than just specifying the effect I want in the constant, ie: effect eInvis = VFX_DUR_DISTORTION; This, I think, is another thing I have been doing wrong, possibly overcomplicating things... I have been applying an effect to the object effect visual effect VFX_..., rather than just the effect itself. EDIT: No, this is wrong... I was doing the application of effects correctly. Still, the studying continues...
:)
:headbump
So, I am going to guess that the flaw is in the first conditional, as it has always been -
but I cannot be sure yet.