lesi123 Posted November 9, 2016 Share Posted November 9, 2016 (edited) I'm in the process of remaking a mod that applies a debuff to an actor when the player hits them with a certain weapon type. I'm doing this through dynamically attaching scripts to actors near the player and have followed the guide here: https://www.creationkit.com/index.php?title=Dynamically_Attaching_Scripts Everything is working okay except the Death Dispel code. To check who has the script attached, I selected a Hit Shader on the magic effect and ticked FX Persist. When I placed the Death Dispel code on the script, however, it didn't seem like the magic effect got dispelled when they died since the Hit Shader was still active on the corpses. When I unticked the No Death Dispel box on the magic effect, the Hit Shader disappeared on death. However the wiki states unticking this box can cause errors and it's best to remove the magic effect via the script instead. Death Dispel code: Event OnEffectStart(Actor akTarget, Actor akCaster) ; Any Initialization/Setup code here ; Go to our Alive state GoToState("alive") EndEvent State alive Event OnBeginState() RegisterForSingleUpdate(0.25) EndEvent Event OnUpdate() ; Regular code here RegisterForSingleUpdate(0.25) EndEvent Event OnDying(Actor akKiller) ; Any additional cleanup code here UnregisterForUpdate() GoToState("dead") EndEvent EndState State dead ; Nothing needed here EndState When I saw the Hit Shader persist on the actor, I attempted to use the .Dispel() function under the OnDying event but I receive the error "Dispel is not a function or does not exist" even though the script extends ActiveMagicEffect. Another issue I could foresee after long playthroughs with this scripts attaching to any actor around the player is it will continuously be applied to more and more actors unless the actors die (once I can find out how the Death Dispel code is supposed to work). Is there a way to remove a magic effect with an attached script from an actor based on distance from the player? GetDistance seems to only work with objects and not actors. Basically the goal is to get the script removed from actors that die or obtain a certain distance from the player to prevent bloat. Any help would be greatly appreciated! Here's the script: Scriptname BTDMonitorScript extends activemagiceffect ;PROPERTIES Actor Property PlayerRef Auto Keyword Property WeapTypeBow Auto Spell Property BTDSpellBleedDmgBOW Auto Spell Property BTDSpellBleedExtrasBOW Auto MagicEffect Property BTDMonitorEffect Auto GlobalVariable Property BTDGlobalBleedDurBOW Auto Event OnEffectStart(Actor akTarget, Actor akCaster) ; Any Initialization/Setup code here ; Go to our Alive state GoToState("alive") EndEvent State alive Event OnBeginState() RegisterForSingleUpdate(0.25) EndEvent Event OnUpdate() ; Regular code here RegisterForSingleUpdate(0.25) EndEvent Event OnDying(Actor akKiller) ; Any additional cleanup code here BTDMonitorEffect.Dispel() ;will not compile with this line UnregisterForUpdate() GoToState("dead") EndEvent EndState State dead ; Nothing needed here EndState Event OnHit(ObjectReference akAggressor, Form akSource, Projectile akProjectile, bool abPowerAttack, bool abSneakAttack, bool abBashAttack, bool abHitBlocked) if ((akAggressor == PlayerRef) && (akSource as Weapon) && (abHitBlocked != true)) if ((akSource.HasKeyword(WeapTypeBow)) && BTDGlobalBleedDurBOW.GetValue() != 0)) if ((Utility.RandomInt() >= 75) && (PlayerRef.GetActorValue("Marksman") < 30)) if BTDGlobalBleedDurBOW.GetValue() == 1 BTDSpellBleedDmgBOW.cast(PlayerRef) BTDSpellBleedExtrasBOW.cast(PlayerRef) endif endif endif endif EndEvent Edited November 9, 2016 by lesi123 Link to comment Share on other sites More sharing options...
FrankFamily Posted November 9, 2016 Share Posted November 9, 2016 Just a thought, are you sure the effect isn't persisting BECAUSE OF the fx persist flag? as that would be a false positive. I haven't used the fx persist flag much so can't really tell. It could be posible that spells naturally dispel on death without doing anything since there is a "No Death Dispel" flag. GetDistance should work with actors too, they are object references in the end, and the wiki example uses the player. EDIT: the wiki says this: FX Persist: If checked, the visual effect on the target persists for the entire duration of the Effect. Otherwise, it only plays once.No Death Dispel: If checked, the effect persists even if the target dies. Link to comment Share on other sites More sharing options...
thesniperdevil Posted November 9, 2016 Share Posted November 9, 2016 I take it you can't assign the target enemy to a quest alias? that way you can do all your jiggery pokery to the quest alias, and simply clear the alias when the target dies? ..I think (its been a while since I did this sorta stuff and I've forgotten a lot) Link to comment Share on other sites More sharing options...
lesi123 Posted November 10, 2016 Author Share Posted November 10, 2016 It could be posible that spells naturally dispel on death without doing anything since there is a "No Death Dispel" flag. You're correct, if I untick the No Death Dispel flag, then the FX stops playing when the actor dies and I assume it's because the magic effect (and it's attached script) has been dispelled. However, the wiki says it's best to dispel the effect from within the script itself since unticking the No Death Dispel can cause this error: "Unable to call X - no native object bound to the script object, or object is of incorrect type"This error appears when native function X, which is non-global, is called on an object variable which does not point at an actual object in game. This usually happens in ActiveMagicEffect scripts which can have their effect deleted out from under them, or when calling certain functions on objects in containers. I just have no idea how to make the magic effect dispel itself on the dead actor since .Dispel() won't work. As for the distance thing, I may have been looking for a problem that's not really there since it wouldn't make sense for a script to run on something that's not even loaded for the player. Link to comment Share on other sites More sharing options...
lofgren Posted November 10, 2016 Share Posted November 10, 2016 (edited) The tutorial you linked to appears to have been edited by some true luminaries of Papyrus scripting. Nevertheless, I feel remiss if I don't mention that it contradicts my own direct experiences, which makes me skeptical of some of its suggestions. In the case of death dispel, I have actually found it to be best to UNcheck "No death dispel," and then put any necessary cleanup functions in the OnEffectFinish block, which fires when the actor dies and the effect is dispelled. Another point of difference is that I find it preferable to put the script effect in the actual effect applied by the cloak, rather than having the cloak effect apply an ability. that way the script effect is removed automatically when the player leaves the vicinity, eliminating some risk of bloat. In cases where it is better to have the cloak effect apply a secondary tracking effect, I would use the cast() function to apply timered effect that lasts 5 minutes or so rather than use a constant effect. That way, worst case scenario, the effect is removed after 5 minutes, which again helps minimize bloat (at the cost of some negligible amount of extra script processing). Edited November 10, 2016 by lofgren Link to comment Share on other sites More sharing options...
lesi123 Posted November 10, 2016 Author Share Posted November 10, 2016 (edited) It seems the wiki is also saying that using the OnEffectFinish event has the same issue as unchecking the No Death Dispel box on a magic effect carrying a script (http://www.creationkit.com/fallout4/index.php?title=OnEffectFinish_-_ActiveMagicEffect). There's even various reports of OnDeath events being inconsistent and the general consensus is to use OnDying instead; I can only assume to give the game and papyrus that tiny extra bit of time to actually execute whatever is in the OnDying event block. However, I did find that a simple self.dispel() in the OnDying event block removes the effect and the attached script from any NPCs affected with it. I did toy around with attaching the script to the Cloak Effect or the Applying Effect but I kept running into issues with Casting Type and Delivery not matching up with the spells. Making them match up then caused the magic effect to not apply and thus no script got added to the NPCs. It's been rough relearning this stuff. Thank you guys for your all your help. I'm sure I'll have more questions down the road as I continue to improve on this damn thing. EDIT: Well, I'm dumb. I forgot to adjust the Applying Spell duration from 0. I removed the Applying Script from the Applying Effect and just placed my Monitor Script on it instead, then changed the Applying Spell duration to 5 minutes. Now it truly acts like a bubble! I also made sure to have the target conditions on the Applying Effect to not apply it to already dead actors or actors that already have the Applying Effect on them. Edited November 10, 2016 by lesi123 Link to comment Share on other sites More sharing options...
FrankFamily Posted November 10, 2016 Share Posted November 10, 2016 You probably figured it out already but just in case, the exact reason why the original dispel line did not compile is because you run it on a magic effect when its an activemagiceffect function, that is, the specific instance not the form, similar to an object reference. Self is an activemagiceffect so it works. Link to comment Share on other sites More sharing options...
lofgren Posted November 10, 2016 Share Posted November 10, 2016 The errors reported on the OnEffectFinish page aren't really relevant to your script, since the only thing you are doing in the clean up function is unregistering for an update, which is done automatically by the game when it dispels the effect anyway. Link to comment Share on other sites More sharing options...
Recommended Posts