Dark122490 Posted July 11, 2010 Share Posted July 11, 2010 Hi, I'm trying to write a script that will cause a spell to be cast (using CastImmediateOnSelf) with the reference as an Actor that has passed a distance threshold stated by the command "GetDistance". I've looked around and saw something called "GetActionRef" but it seems to only work with Trigger Boxes such as those used in quests. I want the player to "be" the trigger box in that when an NPC steps within 30 game units of the player, a spell is cast on the actor. So far I've only built up something like this from the Construction Wiki for Oblivion (the GECK wiki didn't have specific examples): scnSpellProximityScript Ref Actor Begin OnTriggerEnter set Actor to GetActionRef if player.Getdistance Actor < 30 Actor.castimmediateonself Myspell endifend I placed this object script on a random misc item that I later get in game, however it didn't function. I'm just not sure about the OnTriggerEnter beginner... Anyone experimented with this before? Link to comment Share on other sites More sharing options...
Cipscis Posted July 11, 2010 Share Posted July 11, 2010 OnTriggerEnter won't work in this case. If you want to use an OnTriggerEnter block, then you'd need to have it attached to a trigger box which you move along with the player via script, in which case you wouldn't need to call GetDistance. I don't know it moving a triggerbox along with the player via script would cause any issues, but I'd probably go with a reference walking loop instead. In order to prevent any performance issues caused by calling GetDistance multiple times per frame, I'd recommend using a quest script with a script processing delay. Something like 0.5 should work fine - with the script running twice per second. Try something like this:ref rCurrentRef Begin GameMode set rCurrentRef to GetFirstRef 200 0 0 ; Actors Label 10 if rCurrentRef if rCurrentRef.IsSpellTarget MySpell elseif rCurrentRef.GetDistance player < 30 rCurrentRef.CastImmediateOnSelf MySpell endif set rCurrentRef to Pencil01 ; Prevent "apple" bug set rCurrentRef to GetNextRef Goto 10 endif End P.S. Please use "code" tags when posting scripts. It maintains indentation and forces them to use a fixed width font, making them much easier to read. Cipscis Link to comment Share on other sites More sharing options...
Dark122490 Posted July 11, 2010 Author Share Posted July 11, 2010 OnTriggerEnter won't work in this case. If you want to use an OnTriggerEnter block, then you'd need to have it attached to a trigger box which you move along with the player via script, in which case you wouldn't need to call GetDistance. I don't know it moving a triggerbox along with the player via script would cause any issues, but I'd probably go with a reference walking loop instead. In order to prevent any performance issues caused by calling GetDistance multiple times per frame, I'd recommend using a quest script with a script processing delay. Something like 0.5 should work fine - with the script running twice per second. Try something like this:ref rCurrentRef Begin GameMode set rCurrentRef to GetFirstRef 200 0 0 ; Actors Label 10 if rCurrentRef if rCurrentRef.IsSpellTarget MySpell elseif rCurrentRef.GetDistance player < 30 rCurrentRef.CastImmediateOnSelf MySpell endif set rCurrentRef to Pencil01 ; Prevent "apple" bug set rCurrentRef to GetNextRef Goto 10 endif End P.S. Please use "code" tags when posting scripts. It maintains indentation and forces them to use a fixed width font, making them much easier to read. Cipscis I'm unsure about some parts of your example script, here is my take: ref rCurrentRef Begin GameMode set rCurrentRef to GetFirstRef 200 0 0 ; Actors Label 10 if rCurrentRef if rCurrentRef.IsSpellTarget MySpell == 0 && rCurrentRef.GetDistance player < 30 rCurrentRef.CastImmediateOnSelf MySpell endif set rCurrentRef to Pencil01 ; Prevent "apple" bug set rCurrentRef to GetNextRef Goto 10 endif End I looked up all the commands you used (didn't realize GetFirstRef was a FOSE command) and noticed something about IsSpellTarget. Shouldn't there be an integer value for that? Since 1 means the actor has the spell and 0 meaning it doesn't? So I would want to specify that the spell would only be cast if the target is not already under the effects of that spell. Furthermore, I don't understand your use of elseif in line 10 of your script. Would it not make more sense for both conditions to be met before casting the spell? That way it ensures the actor did not already have the spell on it and that the distance is within 30 game units. But besides all that, I still can't seem to implement this in game. I placed the script on a quest and made the script processing delay at 0.5. I clicked the "Start Game Enabled" radio button but it doesn't seem to do a thing. Do I need to add a stage to the quest? I thought quest scripts begin running when "Start Game Enabled" is...well enabled. Also just out of curiosity, what is the "apple" bug? Link to comment Share on other sites More sharing options...
Dyadya_Fedor Posted July 11, 2010 Share Posted July 11, 2010 Just use Player.PlaceAtMe ExplosionWithEnchantment (Area - 30, no magnitude, etc). Link to comment Share on other sites More sharing options...
Cipscis Posted July 11, 2010 Share Posted July 11, 2010 No, don't use PlaceAtMe explosions. That method has similar results to a reference walking loop, but is horrendously inefficient in comparison. Conditional statements work by checking if the condition supplied to them evaluates to 0 or not. If the condition evaluates to 0, then the code inside the conditional statement does not run, otherwise it does run. This means that using "== 1" on conditions that evaluate to boolean values (i.e. 1 or 0) do nothing except make the script less efficient. For example:if IsSpellTarget MySpell == 1IsSpellTarget can evaluate to 1 or 0, so once it has been called you can imagine the line looking like one of these two lines:if 1 == 1 if 0 == 1The "is equal to" operator is then evaluated. This operator returns 1 if both operands are equal, and 0 if they are not, which means that it will not change boolean values in a meaningful way when the second operand is 1 ("1 == 1" returns 1, and "0 == 1" returns 0). The following two lines are equivalent, but the first is more efficient:if IsSpellTarget MySpell if IsSpellTarget MySpell == 1"else" and "elseif" statements have a special extra condition - "and all previously checked conditions in the current block of conditional statements were false (i.e. evaluated to 0)". This means that the following three pieces of code will work in the same way: if rCurrentRef.IsSpellTarget MySpell elseif rCurrentRef.GetDistance player < 30 rCurrentRef.CastImmediateOnSelf MySpell endif if rCurrentRef.IsSpellTarget MySpell == 0 if rCurrentRef.GetDistance player < 30 rCurrentRef.CastImmediateOnSelf MySpell endif endif if rCurrentRef.IsSpellTarget MySpell == 0 && rCurrentRef.GetDistance player < 30 rCurrentRef.CastImmediateOnSelf MySpell endif In the first two examples, GetDistance will only be called if the IsSpellTarget condition has been evaluated in the intended way, whereas in the third example it will always be called. The first example is also slightly more efficient than the second because it doesn't need to use "== 0" to "invert" the condition - this is done implicitly by using an "elseif" statement. The "apple bug" is a bug in GetNextRef, where it will not always update correctly, which can be fixed by setting it to an arbitrary value before calling GetNextRef. It originated in Oblivion, and is called the "apple bug" because it was named after its solution:set rCurrentRef to AppleIn Fallout 3, I've always used "Pencil01" as my arbitrary value, but I give it the same name so that anyone familiar with it from Oblivion will know what I'm talking about. You don't need to add a stage to your quest or anything like that to get it working, although I don't know why it isn't working at the moment. Try adding some DebugPrint lines to your script to make sure that it's actually running (use SetDebugMode in the console to activate these statements). Cipscis Link to comment Share on other sites More sharing options...
Dyadya_Fedor Posted July 12, 2010 Share Posted July 12, 2010 No, don't use PlaceAtMe explosions. That method has similar results to a reference walking loop, but is horrendously inefficient in comparison. Good to know. If I someday decide to use FOSE, I will keep this in mind. Link to comment Share on other sites More sharing options...
Dark122490 Posted July 12, 2010 Author Share Posted July 12, 2010 Edited: Nevermind. Link to comment Share on other sites More sharing options...
Recommended Posts