GamerRick Posted April 2, 2023 Share Posted April 2, 2023 (edited) I would like to display the size of the soul when I (the PC) cast any soultrap spell. Here is the only thing I can think of: Create an event for the spellcast: Begin GameMode if GetGameRestarted PlayerRef.SetEventHandler "OnSpellCast", FnOnSpellCast endif EndIn the function, display the soul size of the target: scn FnOnSpellCast ref refActor ref refSpell short iSoulSize Begin Function { refActor, refSpell } if MagicItemHasEffect STRP, refSpell set refActor to player.GetCrosshairRef if refActor if refActor.IsActor set iSoulSize to GetActorSoulLevel refActor if iSoulSize == 5 Message "Target soul level is GRAND" 4 else if refActor.GetLevel >= 18 Message "Target soul level is GRAND" 4 elseif refActor.GetLevel >= 13 Message "Target soul level is GREATER" 4 elseif refActor.GetLevel >= 7 Message "Target soul level is COMMON" 4 elseif refActor.GetLevel >= 2 Message "Target soul level is LESSER" 4 else Message "Target soul level is PETTY" 4 endif endif else Message "Target is not an Actor" 4 endif else Message "No Target Detected" 4 endif return endif end This technique misses a lot, and displays "No Target Detected". It seems to be hit or miss even if it seems like I had the crosshair on the target. Is where Is there any other way to get a ref of the target? Edited April 2, 2023 by GamerRick Link to comment Share on other sites More sharing options...
qwertyasdfgh Posted April 3, 2023 Share Posted April 3, 2023 GetCrosshairRef only returns the target within activation distance. You can dynamically change the related game setting to make it return far away target, but for what you want to do it would be much easier to use OnMagicEffectHit event handler instead. Link to comment Share on other sites More sharing options...
GamerRick Posted April 3, 2023 Author Share Posted April 3, 2023 GetCrosshairRef only returns the target within activation distance. You can dynamically change the related game setting to make it return far away target, but for what you want to do it would be much easier to use OnMagicEffectHit event handler instead.Thanks! Link to comment Share on other sites More sharing options...
RomanR Posted April 3, 2023 Share Posted April 3, 2023 (edited) And if you find it usefull, I present here a function which returns 0 or 1 if target of spell was hit by particular effect and a player is responsible: scn RomRFnHitByPlayer ; this script returns 0 or 1 if a target was hit by particular effect made by player ref target ;target of a spell,enchant etc. ref caster ref m_item int index int size int effect_code string_var m_effect ;effect code in a form of string, for example "SEFF" string_var m_effect_active short result ;variable for return array_var effects begin function { target, m_effect } set result to 0 let size := ar_Size effects if size == -1 let effects := ar_Construct array let size := ar_Size effects endif if target != 0 && sv_Length m_effect == 4 ; fill up a field let effects := target.GetActiveEffectCodes let size := ar_Size effects if size > 0 ; active effects exist? set index to 0 while index < size ;scan let effect_code := effects[index] ;convert code to string first let m_effect_active := GetMagicEffectCharsC effect_code if eval (m_effect == m_effect_active) ;found requested effect code let m_item := target.GetNthActiveEffectMagicItem index ;what enchant, spell etc. if m_item != 0 let caster := target.GetNthActiveEffectCaster index ;who is responsible? if caster == player ;it is a player set result to 1 break endif endif endif set index to index + 1 loop endif endif SetFunctionValue result if size > 0 ar_Resize effects 0 endif let effects := ar_Null sv_Destruct m_effect m_effect_active end Function is used like this: scn SomeScript ... ref actor short result ... begin ScriptEffectStart ;for example spell ... set actor to GetSelf ; someone was hit by script spell effect cast by player let result := Call RomRFnHitByPlayer actor "SEFF" if result != 0 ;yes ... endif ... end Edited April 3, 2023 by RomanR Link to comment Share on other sites More sharing options...
GamerRick Posted April 3, 2023 Author Share Posted April 3, 2023 (edited) Wait a sec.... If I use OnMagicEffectHit, I can make sure to not run if I am the target, but how would I know if another NPC cast the spell at another NPC or creature? I only want it to run when I (the playerRef) am the caster. Thanks. I can't get it to work at all: This won't compile without an error saying it will treat "object" as a script SetEventHandler "OnMagicEffectHit" FnOnSoulTrap object::"STRP"These compile, but obviously I don't want it to only work when I am the target or not filter for only STRP commands. SetEventHandler "OnMagicEffectHit" RFFnOnSoulTrap or SetEventHandler "OnMagicEffectHit" RFFnOnSoulTrap ref::PlayerRef object::"STRP" Edited April 3, 2023 by GamerRick Link to comment Share on other sites More sharing options...
RomanR Posted April 4, 2023 Share Posted April 4, 2023 (edited) I think you can safely use GetSelf command. For example as I used for "OnMagicEffectApply" event.(borrowed setting a handler from my Counter Effect framework): ... ; setting an event set restart to 0 if GetGameRestarted set restart to 1 endif if restart let good := SetEventHandler "OnMagicApply" ShowSoulLevelScript if good == 0 Message "Counter Effect Mod: Creation of event handler failed." endif set restart to 0 endif ... And then for your case it can look like this: scn ShowSoulLevelScript ref magic_item ref caster ref target short hit (another variables for showing soul level) begin function { magic_item, caster } if magic_item != 0 set target to GetSelf if target != 0 && target != player ;valid target, but no player if target.IsActor != 0 ;want NPC or creature let hit := Call RomRFnHitByPlayer target "STRP" ;using function posted before if hit != 0 (your commands for showing soul level here) endif endif endif endif end Edited April 4, 2023 by RomanR Link to comment Share on other sites More sharing options...
RomanR Posted April 4, 2023 Share Posted April 4, 2023 (edited) Seems editor won't let add lines after a code box, so I would only add that for me using OnMagicApply event can be a best solution. But for OnMagicEffectHit filtering a target is easier. scn RFFnOnSoulTrap ref target int effect_code string_var ascii_code begin function { target, effect_code } if target != 0 if target.IsActor != 0 && target != player let ascii_code := GetMagicEffectCharsC effect_code if eval (ascii_code == "STRP") .... endif endif endif sv_Destruct ascii_code end Edited April 4, 2023 by RomanR Link to comment Share on other sites More sharing options...
GamerRick Posted April 4, 2023 Author Share Posted April 4, 2023 (edited) The last thing I tried last night is this: let iResult := SetEventHandler "OnMagicEffectHit" RFFnOnSoulTrap PrintC"RFLightSpellQuestScript - SetEventHandler result = %g" iResultEven without any filters on it, it just won't call my function when I cast a STRP spell on a creature. Nothing happens. So, I have given up for now. Also, according to your script, I could have just done a GetSelf to get the target of the spell??? I find it hard to believe that would work from within a custom function. However, if it does work, wouldn't it also work if my event were OnSpellCast? "OnMagicApply" is a function for Skyrim. EDIT: I finally got this to work. Gotta use COMMAS to separate the variables in the command in spite of what the OBSE docs say.I tried the GetSelf command and it crashes the script. The quest script (note how using object::PlayerRef changes it to look for the player to cast the spell, whereas ref::PlayerRef looks for the player to be the target of the spell): let iResult := SetEventHandler "OnMagicEffectHit" RFFnOnSoulTrap, object::PlayerRef, object::"STRP"The function (same as before) EDIT: Just remembered that I also had to change the 2nd parameter of the function to a long instead of a string_var. scn RFFnOnSoulTrap ref rTarget long lEffect short iSoulSize begin Function { rTarget, lEffect } PrintC"RFFnOnSoulTrap called on %n" rTarget if rTarget.GetIsReference player return endif if rTarget.IsActor set iSoulSize to GetActorSoulLevel rTarget if iSoulSize == 5 Message "Target soul level is GRAND" 4 Message "Target soul level is GRAND" 4 PrintC "Target soul level is GRAND" else if rTarget.GetLevel >= 18 Message "Target soul level is GRAND" 4 Message "Target soul level is GRAND" 4 PrintC "Target soul level is GRAND" elseif rTarget.GetLevel >= 13 Message "Target soul level is GREATER" 4 Message "Target soul level is GREATER" 4 PrintC "Target soul level is GREATER" elseif rTarget.GetLevel >= 7 Message "Target soul level is COMMON" 4 Message "Target soul level is COMMON" 4 PrintC "Target soul level is COMMON" elseif rTarget.GetLevel >= 2 Message "Target soul level is LESSER" 4 Message "Target soul level is LESSER" 4 PrintC "Target soul level is LESSER" else Message "Target soul level is PETTY" 4 Message "Target soul level is PETTY" 4 PrintC "Target soul level is PETTY" endif endif else Message "Target is not an Actor" 4 Message "Target is not an Actor" 4 endif endThe downside is that if I don't have a soulgem that is big enough for the target, I no longer get the usual message about it. Edited April 4, 2023 by GamerRick Link to comment Share on other sites More sharing options...
RomanR Posted April 4, 2023 Share Posted April 4, 2023 (edited) As function is also an object type script, GetSelf returns the object which runs onto. So in the case of events it's no wonder that for "OnMagicApply" you get a target this way. In fact you will get all you need: a magic item (spell, power, enchanment) which caused it, caster and target. You just need a check if this spell has particular effect. I presented a function if target has active effect on it, but as I'm looking, the MagicItemHasEffect should be enough to use in the end. scn ShowSoulLevelScript ;function for "OnMagicApply" event ref magic_item ref caster ref target short hit (another variables for showing soul level) begin function { magic_item, caster } if magic_item != 0 set target to GetSelf if target != 0 && target != player ;valid target, but no player if target.IsActor != 0 ;want NPC or creature let hit := MagicItemHasEffect "STRP" magic_item ;I am not sure about quotes if hit != 0 && caster == player (your commands for showing soul level here) endif endif endif endif end With OnMagicEffectHit, GetSelf should return target too, but as it's already filled in variable by event, you don't need it. With OnSpellCast you don't need it too and if you use it, it will return a caster. Regarding events - is return value from SetEventHandler non zero? How do you know that your function wasn't called? It often helps adding print commads for showing used variables while running a script to view if script is at least doing something. Edit: As I see your new post - no, OnMagicApply isn't only for Skyrim. See the OBSE command docs Event Handlers part and you will see this type of event in the table. It's almost at the end, right under OnMagicCast. But as I see SetEventCommand - doesn't it set the event only for player as a target? Edited April 4, 2023 by RomanR Link to comment Share on other sites More sharing options...
GamerRick Posted April 4, 2023 Author Share Posted April 4, 2023 I tried GetSelf and it crashes the script. Link to comment Share on other sites More sharing options...
Recommended Posts