cfh85 Posted August 11, 2012 Share Posted August 11, 2012 can it be done? I don't want to put the script into the activator (compatibility). OnMagicEffectHit is for use on the target and I don't think it's specific enough to work for only 1 spell. Any ideas on this? Link to comment Share on other sites More sharing options...
Lanceor Posted August 11, 2012 Share Posted August 11, 2012 So you want a script to run when an activator is hit by a specific spell? OnMagicEffectHit is the only reliable easy way to detect a hit by a certain type of spell. If compatibility is a concern, you could swap out a custom activator that looks identical to the existing one. If it needs to be a specific spell, that would be much harder. Just pulling ideas out of the air... you could place a trigger zone around the player to capture the reference of any missiles coming from the player. Once the activator is hit, it uses GetActionRef to determine whether it's the same reference as what the player cast. GetProjectile is another function worth investigating. Link to comment Share on other sites More sharing options...
cfh85 Posted August 11, 2012 Author Share Posted August 11, 2012 Okay. Full story. I'm TRYING to create a spell to replace dark welkynd stones with a PC friendly one for a limited amount of time. I'll probably have to end up putting the script on the stones. Though, even then I only want it to respond to a specific spell, not effect. Link to comment Share on other sites More sharing options...
DrakeTheDragon Posted August 12, 2012 Share Posted August 12, 2012 (edited) Sounds to me like a scripted effect spell with the exchange taking place in the spell script itself could do the trick here. Though I admit scripting the exchange will be the hard part. The spell script will have to check if it's running on such a dark welkynd stone or not.One such way could be using GetBaseObject and then comparing the returned value with the EditorIDs of the traps you're intending to replace.E.g.:if GetBaseObject == ARTrapEvilStone01Or you could use GetIsID for the same comparing purpose.E.g.:if GetIsID ARTrapEvilStone01As there are already 9 different generic and 1 quest-related (though this one shoots only on a quest NPC and seems to be of no relevance to your idea here) "types" of those traps in the Vanilla game alone, and only The Nine know how many custom ones in mods, it will be difficult to catch them all, but I think you can catch "most" of them via the NIF file used for their model instead, by using CompareModelPath for example.if CompareModelPath "ARTrapEvilStone01"And you would already catch all of the above... though you as well catch ones not intended to be caught with this solution.Still not caught would be those with a custom model used for the same purpose, but I think now we're getting too far away from your original intention anyways. I had a short look into their scripts and it seems they're either "triggered" by something else (a trigger plate maybe or an invisible trigger zone) (ARTrapEvilStone01, ARTrapEvilStone02, ARTrapEvilStoneFAST01), or they're the kind that shoots on its own while the player is in range (ARTrapEvilStoneAUTOFIRE01, ...02, ARTrapEvilStoneAUTOFIREFAR01, ...02). They only react to the player (hardcoded target). And they're all firing through means of their object scripts. In retrospect only the last 4 seem to be relevant and the way of identification through EditorIDs seems to be very feasible. I for one wouldn't mess with their scripts to turn them inactive, although this would be a feasible attempt as well. The most simple approach to get rid of them "temporarily" would be to "move them away" or "disable" them and place a placeholder at their place.This could all be handled in one single spell script... if all works out as intended that is. begin ScriptEffectStart ;the identification part: if (GetIsID ARTrapEvilStoneAUTOFIRE01) || (GetIsID ARTrapEvilStoneAUTOFIRE02) || (GetIsID ARTrapEvilStoneAUTOFIREFAR01) || (GetIsID ARTrapEvilStoneAUTOFIREFAR02) disable ; will disappear and should no longer be able to react on player or shoot at player endif end begin ScriptEffectFinish enable ; should reappear after time runs out and also be able to react on player and shoot at player again automatically end If we're lucky, everything will work fine already and the running out of the spell will turn everything back to normal.But it could be calling "disable" on the object will also disable the continuation of this spell or its script execution. In this case we'll have to put the disable and enable part into the object script of the replacing object we put in its place as well as an actual timer counting down. I'd say try this attempt first and come back telling if it works or not. In case it really won't work that way at all due to the repercussions of "disable", I could go more into detail on what to do otherwise. You can use MoveTo to put something else into the trap's place without risking savegame bloat from PlaceAtMe, but then it will only work for a fix number of traps at once, as you'll need to have a fix number of replacements with "persistent reference id" ready from inside a holding cell or something. And you'll need some scripted trickery taking care of which of them to take and when not to act at all due to no more replacements being available at this time... and all such things. ... ref self ... set self to GetSelf ; now we have a reference to the target to work with other than the default reference automatically used in spell scripts ... TemporaryReplacementStone01.MoveTo self ; move replacement 01 from holding cell to target disable ; disable target ... TemporaryReplacementStone01.MoveTo HoldingCellID ; move rep. 01 back to holding cell when time is up ... "TemporaryReplacementStone01" and so on have to be "persistent reference id"s for replacement objects you placed into the holding cell with EditorID "HoldingCellID". In case MoveTo doesn't lead to the replacements being placed at exactly the same location, use GetPos and SetPos, for X, Y and Z respectively, and appropriate "float" variables, to store the location of "self" and set the replacement's location exactly after using MoveTo to get the replacements at least into the same cell and nearby. In case the disable-enable-based approach above doesn't work out, you could try using following approach instead. ... short active float timer float pos ref target ref self ... begin GameMode if active == 1 && timer > 0 set timer to timer - GetSecondsPassed elseif active == 1 && target != 0 set active to 0 set self to GetSelf target.MoveTo self set pos to self.GetPos X target.SetPos X pos set pos to self.GetPos Y target.SetPos Y pos set pos to self.GetPos Z target.SetPos Z pos target.enable self.disable self.MoveTo HoldingCellID set target to 0 endif end And do following when "moving away" the traps inside the spell script: ... set self to GetSelf ; obtain a usable reference to the spell target TemporaryReplacementStone01.MoveTo self ; get the replacement at least into the same cell and nearby set pos to GetPos X TemporaryReplacementStone01.SetPos X pos set pos to GetPos Y TemporaryReplacementStone01.SetPos Y pos set pos to GetPos Z TemporaryReplacementStone01.SetPos Z pos ; get position absolutely exact TemporaryReplacementStone01.enable disable MoveTo HoldingCellID set TemporaryReplacementStone01.target to self ; at least if replacement is an Activator, too, this should work, set target variable of rep to target set TemporaryReplacementStone01.timer to 10 ; set countdown of 10 seconds over in the script of rep. set TemporaryReplacementStone01.active to 1 ; initiate ... Make sure all variables are properly defined inside the spell script ("self" of type "ref", "pos" of type "float"). Phew, that ought to have given some pointers. I hope it'll all work, as I can't test it at the moment. Edited August 12, 2012 by DrakeTheDragon Link to comment Share on other sites More sharing options...
cfh85 Posted August 12, 2012 Author Share Posted August 12, 2012 (edited) what I already tried is this Scriptname CFHDarkWelkyndDefenceScript ref Target Float Defended Begin ScripteffectStart Set Target to GetSelf If (Target == ARTrapEvilStone01) || (Target == ARTrapEvilStone02) || (Target == ARTrapEvilStoneAUTOFIRE01) || (Target == ARTrapEvilStoneAUTOFIRE02) || (Target == ARTrapEvilStoneAUTOFIREFAR01) || (Target == ARTrapEvilStoneAUTOFIREFAR02) || (Target == ARTrapEvilStoneAUTOFIRETest) || (Target == ARTrapEvilStoneFast01) CFHARTrapEvilStonePCDefenceRef.MoveTo Target CFHARTrapEvilStonePCDefenceRef.Enable Target.Disable Set Defended to 1 EndIf End Begin ScriptEffectFinish If Defended == 1 CFHARTrapEvilStonePCDefenceRef.Disable Target.Enable Set Defended to 0 EndIf End but it doesn't do anything. It seems as if it's not recognising the activator as a target. :wallbash: just realised I didn't remove the script from my replacement stone. Just tried it and still doesn't work. I'm going to try using GetIsID now. Will reply soon Edit.just tried Scriptname CFHDarkWelkyndDefenceScript ref Target Float Defended Begin ScripteffectStart Set Target to GetSelf If (Target.GetIsID ARTrapEvilStone01) || (Target.GetIsID ARTrapEvilStone02) || (Target.GetIsID ARTrapEvilStoneAUTOFIRE01) || (Target.GetIsID ARTrapEvilStoneAUTOFIRE02) || (Target.GetIsID ARTrapEvilStoneAUTOFIREFAR01) || (Target.GetIsID ARTrapEvilStoneAUTOFIREFAR02) || (Target.GetIsID ARTrapEvilStoneAUTOFIRETest) || (Target.GetIsID ARTrapEvilStoneFast01) CFHARTrapEvilStonePCDefenceRef.MoveTo Target CFHARTrapEvilStonePCDefenceRef.Enable Target.Disable Set Defended to 1 EndIf End Begin ScriptEffectFinish If Defended == 1 CFHARTrapEvilStonePCDefenceRef.Disable Target.Enable Set Defended to 0 EndIf End still no luck. I've set the spell duration to 3000 and removed the script from my replacement stone.It just seems to not want to recognise the dark welkynd stone as a target Edited August 12, 2012 by cfh85 Link to comment Share on other sites More sharing options...
DrakeTheDragon Posted August 12, 2012 Share Posted August 12, 2012 (edited) I added a lot to my post after you posted this, as I wasn't told you posted something already by then. For some reason "Target" seems to be reserved, as the script highlighter in my browser highlights it. Either try "target" instead, as ObScript is case-sensitive in some regards, or a totally different variable name even. "==" on something obtained in a spell script via "GetSelf" in this case will not work, as you're now comparing apples with bananas, an actual "reference" with a BaseObject's EditorID. Try using "GetIsID" without a reference, exactly like I used it. In a spell script it could be troublesome to use "GetSelf" where it's not necessary. But most important of all, let's first check if spells even work on activators. Use this simple script in your spell to find out: begin ScriptEffectStart MessageBox "Hit something!" end Then cast this onto random things and see if it does pop up at all. Edited August 12, 2012 by DrakeTheDragon Link to comment Share on other sites More sharing options...
cfh85 Posted August 12, 2012 Author Share Posted August 12, 2012 (edited) I tried using the messagebox. Works on doors & containers but not activators.I'm wondering if there is a function to call an array of all the objects in a cell. If I can find one then I can just (I think) check if they're dark welkynd stones, check their distance from the PC and replace all the stones within distance. I'll post back once I've had a good look. Also, thanks for the help. So far I've foundGetCrosshairRef - may work but will on would within activate distance. This would make the spell very short range. Not the end of the world if it works. That's all I can find under get. I'm going to have a look at some mods that auto harvest ingredients. I'm sure there is some way to find what items are in a cell GetFirstRef and GetNextRef . Scans all the references in the cell when used together. Using the code 18, so GetFirstRef 18, will only return activators. I'll try this as soon as I feel awake enough to write the rest of the code Edited August 12, 2012 by cfh85 Link to comment Share on other sites More sharing options...
cfh85 Posted August 16, 2012 Author Share Posted August 16, 2012 :biggrin: Got it to work. It works by scanning all activators in the cell and checking for Dark Welkynd Stones. Because you can not actually target the stones it has to remove all stones from the current cell (otherwise it might not remove the one your after) but it has a limit. I've put 5 replacers in game, so I can only disable 5 at a time.Some changes are needed though.1 problem may arise from multiple casts before the first has finished. I had considered using a quest or global to prevent this however, I'm going to try using getincell on #1 stone replacer. If it's not in the storage cell then it'll prevent a second spell from running.1 other upgrade would be to use comparemodelpath and another to set x,y,z positions. - Thanks DrakeTheDragon for the pointersAlso, disable may not of been the way to go, as the scripts still run. I don't know if that means they could still cast or not, but I figured it's best to be safe. I'm hoping to have a trial mod released very soon to test it out anyway, my current script Scriptname CFHSpellDarkWelkyndDefenceScript Ref TempRef Ref Disabled1Ref Ref Disabled2Ref Ref Disabled3Ref Ref Disabled4Ref Ref Disabled5Ref Short Counter Short DisabledCount Begin ScripteffectStart Set DisabledCount to 0 Set Counter to (GetNumRefs 18 0) Set TempRef to (GetFirstRef 18 0) While Counter > 0 Let Counter -= 1 If (TempRef.GetIsID ARTrapEvilStone01) || (TempRef.GetIsID ARTrapEvilStone02) || (TempRef.GetIsID ARTrapEvilStoneAUTOFIRE01) || (TempRef.GetIsID ARTrapEvilStoneAUTOFIRE02) || (TempRef.GetIsID ARTrapEvilStoneAUTOFIREFAR01) || (TempRef.GetIsID ARTrapEvilStoneAUTOFIREFAR02) || (TempRef.GetIsID ARTrapEvilStoneAUTOFIRETest) || (TempRef.GetIsID ARTrapEvilStoneFast01) If DisabledCount == 0 CFHARTrapEvilStonePCDefence1Ref.MoveTo TempRef Set Disabled1Ref to TempRef Disabled1Ref.MoveTo CFHDarkWelkyndStorageRef Set DisabledCount to 1 ElseIf DisabledCount == 1 CFHARTrapEvilStonePCDefence2Ref.MoveTo TempRef Set Disabled2Ref to TempRef Disabled2Ref.MoveTo CFHDarkWelkyndStorageRef Set DisabledCount to 2 ElseIf DisabledCount == 2 CFHARTrapEvilStonePCDefence3Ref.MoveTo TempRef Set Disabled3Ref to TempRef Disabled3Ref.MoveTo CFHDarkWelkyndStorageRef Set DisabledCount to 3 ElseIf DisabledCount == 3 CFHARTrapEvilStonePCDefence4Ref.MoveTo TempRef Set Disabled4Ref to TempRef Disabled4Ref.MoveTo CFHDarkWelkyndStorageRef Set DisabledCount to 4 ElseIf DisabledCount == 4 CFHARTrapEvilStonePCDefence5Ref.MoveTo TempRef Set Disabled5Ref to TempRef Disabled5Ref.MoveTo CFHDarkWelkyndStorageRef Set DisabledCount to 5 EndIf EndIf Set TempRef to GetNextRef Loop If DisabledCount > 0 Message "DarkStones Disabled" EndIf End Begin ScriptEffectFinish If DisabledCount == 0 Return EndIf If DisabledCount >=1 Disabled1Ref.MoveTo CFHARTrapEvilStonePCDefence1Ref CFHARTrapEvilStonePCDefence1Ref.MoveTo CFHDarkWelkyndStorageRef EndIf If DisabledCount >=2 Disabled2Ref.MoveTo CFHARTrapEvilStonePCDefence2Ref CFHARTrapEvilStonePCDefence2Ref.MoveTo CFHDarkWelkyndStorageRef EndIf If DisabledCount >=3 Disabled3Ref.MoveTo CFHARTrapEvilStonePCDefence3Ref CFHARTrapEvilStonePCDefence3Ref.MoveTo CFHDarkWelkyndStorageRef EndIf If DisabledCount >=4 Disabled4Ref.MoveTo CFHARTrapEvilStonePCDefence4Ref CFHARTrapEvilStonePCDefence4Ref.MoveTo CFHDarkWelkyndStorageRef EndIf If DisabledCount >=5 Disabled5Ref.MoveTo CFHARTrapEvilStonePCDefence5Ref CFHARTrapEvilStonePCDefence5Ref.MoveTo CFHDarkWelkyndStorageRef EndIf End Link to comment Share on other sites More sharing options...
cfh85 Posted August 16, 2012 Author Share Posted August 16, 2012 okay. My plan to prevent it from being cast twice didn't work.I can either just settle for posting a warning or put it as a scroll spell, and re add a scroll to inventory on scripteffectfinish... probably another way.It didn't seem to cause a problem when I cast it twice, although that was in my teshinghall with only 1 darkstone. Perhaps it's not an issues - I don't know how scripted spells work. I suspect that as the script is attached to a spell, assigned to a player that it doesn't act as a separate instance of the script each time I cast it, to prevent spell stacking. Also, I couldn't get comparemodel path to work Link to comment Share on other sites More sharing options...
DrakeTheDragon Posted August 16, 2012 Share Posted August 16, 2012 Every time a Scripted Effect spell is cast a new instance of the script is created and run. They don't know each other and can't access each other's variables. All variables start at uninitialized value every time a spell is cast. What I was concerned of in regards to a limited number of spells active at the same time was the number of the replacement stones "only". As you're only having fixed number, 5 stones, trying to swap out 6 stones the first placeholder will vanish when the last stone gets exchanged, as it will be moved to the last stone's position. You can only have 5 replacement stones in place at once, so one of the dark stones will be missing its replacement. But this was only for when it was still a spell to exchange a single dark stone only. Now that it loops through all dark stones in range storing "DisabledCount" in the spell script where it's at "0" again for every new spell you cast, maybe a more "global" storage method should be considered. As it is right now, there will be dark stones without replacements in place when the number of stones replaced (in sum over all spells running at the same time) exceeds 5. Where is the spell cast at now anyways? If it's now On-Self, I think you're good to go, as I've never seen a single spell being in effect twice or more times on an actor so far. There could be an internal prevention in place here already. What's the issue with CompareModelPath? Can you show me some lines of the scripts? Link to comment Share on other sites More sharing options...
Recommended Posts