audiogarden21 Posted January 2, 2021 Author Share Posted January 2, 2021 Will you be requiring SKSE for this mod? Yes. Unless something changes in the future. I'm actually roughly halfway done with my mod but then I came across this anomaly and it all came to a screeching halt until I sort this mess out. The 'OnHit()' event will always fire more than once if the object that hit it has an enchantment. Definitely aware of this fact. xD I believe that the first "OnHit" event with an enchanted weapon will always be the weapon itself and then the rests of the events are the 'Enchantments'. Actually, it's always the weapon itself as far as the game is concerned however the enchant is what triggers it in cases where it's the enchant hitting the target. For instance, before when I ran "Debug.Trace("Weapon ID: "+akSource)" it returns: [01/02/2021 - 01:22:35AM] Weapon ID: [WEAPON < (00028DE8)>]- switched to enchanted mace [01/02/2021 - 01:22:35AM] Weapon ID: [WEAPON < (00028DE8)>] Which as you can see returns the weapon on both hits. In this case it's a Daedric Mace of Fire. I may have to try installing Oldrim and testing that just to see if it functions the same way... :wallbash: While I'm not one for celebrating most holidays or events of that nature, happy New Year to you nonetheless. :D Oh, and I already "fixed" it using dylbill's suggestion without the need for states. It's above your post if you want to look. It's pretty simple. Does anyone else have a potential fix or know why things aren't what they should be??! Inquiring mind/s(?) would like to know! Link to comment Share on other sites More sharing options...
RichWebster Posted January 2, 2021 Share Posted January 2, 2021 What about (akSource as Enchantment) Does this detect if it was an enchantment in the OnHit? Link to comment Share on other sites More sharing options...
maxarturo Posted January 2, 2021 Share Posted January 2, 2021 I was just sharing some data, and although dylbill's suggestion works, in my case i don't need to obtain anything from the weapon or from the hitting actor, just to fire the ability of the hitted actor. PS: 'State' are the most faster, powerful and reliable tool that the game engine and papyrus has. Link to comment Share on other sites More sharing options...
ReDragon2013 Posted January 2, 2021 Share Posted January 2, 2021 (edited) audiogarden21 wrote: " While attempting to set up an "OnHit" event and filter out enchantment hits"As RichWebster already posted next type cast is what you are looking for. (akSource as Enchantment)from here edited: https://www.creationkit.com/index.php?title=GetEquippedWeapon_-_Actor ; next three lines are the same for right hand weapon, because "abLeftHand" is False by predefined default.. (akAggressor as Actor).GetEquippedWeapon() (akAggressor as Actor).GetEquippedWeapon(False) (akAggressor as Actor).GetEquippedWeapon(0) ; type cast from int to bool; next two lines have the same result for left hand weapon (akAggressor as Actor).GetEquippedWeapon(TRUE) (akAggressor as Actor).GetEquippedWeapon(1) ; type cast from int to booljust a sample: How to use OnHit() event! EVENT OnHit(ObjectReference akAggressor, Form akSource, Projectile akProj, Bool b1, Bool b2, Bool b3, Bool b4) ; b1 = abPowerAttack ; b2 = abSneakAttack ; b3 = abBashAttack ; b4 = abHitBlocked IF ( b4 ) ; (b4 == TRUE) RETURN ; - STOP - hit from aggressor was blocked by script owner (self, if is not an ActiveMagicEffect script) ENDIF ;--------------------- ;IF ( akProj ) ; Debug.Trace("ranged Weapon: " + (akAggressor as Actor).GetEquippedWeapon()) ; RETURN ; - STOP - hit was made by range weapon like bow or crossbow ;ENDIF ;--------------------- IF (akSource as Spell) RETURN ; - STOP - hit comes from magic (not potion) ENDIF ;--------------------- ;IF (akSource as Enchantment) ; "It does not work as audiogarden21 researched" !!! ; RETURN ; - STOP - Do not try to use this if statement to get weapon hit by enchantment. ;ENDIF ;--------------------- IF (akSource as Weapon) ; if weapon is enchanted, code inside will be executed at least twice (one for normal weapon + n-more for each magic effect on weapon) gotoState("Busy") ; ### STATE ### myF_Action(akAggressor, akSource) gotoState("") ; ### STATE ### ENDIF ENDEVENT ;======================== state Busy ; block hit events for a very short time ;========= EVENT OnHit(ObjectReference akAggressor, Form akSource, Projectile akProj, Bool b1, Bool b2, Bool b3, Bool b4) ENDEVENT ;======= endState ; -- FUNCTION -- ;-------------------------------------------------------------- FUNCTION myF_Action(ObjectReference akAggressor, Form akSource) ;-------------------------------------------------------------- actor aRef = akAggressor as Actor IF ( aRef ) Debug.Trace("rightHand Weapon: " + aRef.GetEquippedWeapon(False)) ; abLeftHand [default=False] Debug.Trace(" leftHand Weapon: " + aRef.GetEquippedWeapon(TRUE)) ENDIF ENDFUNCTION This post has been edited by ReDragon to remove some mistakes I made earlier. Edited January 3, 2021 by ReDragon2013 Link to comment Share on other sites More sharing options...
audiogarden21 Posted January 2, 2021 Author Share Posted January 2, 2021 What about (akSource as Enchantment) Does this detect if it was an enchantment in the OnHit? It does not. Papyrus cannot detect whether it was an enchant in any way using the information provided in the wiki. If you try to cast it as Enchantment it returns None. I was just sharing some data, and although dylbill's suggestion works, in my case i don't need to obtain anything from the weapon or from the hitting actor, just to fire the ability of the hitted actor. PS: 'State' are the most faster, powerful and reliable tool that the game engine and papyrus has. Fair enough. Forgive me if I came off as ungrateful for your input. =) audiogarden21 wrote: " While attempting to set up an "OnHit" event and filter out enchantment hits"As RichWebster already posted next type cast is what you are looking for. (akSource as Enchantment); next two lines are the same for left hand weapon, because "abLeftHand" is False by predefined default.. https://www.creationkit.com/index.php?title=GetEquippedWeapon_-_Actor (akAggressor as Actor).GetEquippedWeapon() (akAggressor as Actor).GetEquippedWeapon(False); next two lines have the same result for right hand weapon, except second line do a type cast from int to bool before execution (akAggressor as Actor).GetEquippedWeapon(TRUE) (akAggressor as Actor).GetEquippedWeapon(1)just a sample: How to use OnHit() event! EVENT OnHit(ObjectReference akAggressor, Form akSource, Projectile akProj, Bool b1, Bool b2, Bool b3, Bool b4) ; b1 = abPowerAttack ; b2 = abSneakAttack ; b3 = abBashAttack ; b4 = abHitBlocked IF ( b4 ) ; (b4 == TRUE) RETURN ; - STOP - hit from aggressor was blocked by script owner (self, if is not an ActiveMagicEffect script) ENDIF ;--------------------- ;IF ( akProj ) ; Debug.Trace("ranged Weapon: " + (akAggressor as Actor).GetEquippedWeapon()) ; RETURN ; - STOP - hit was made by range weapon like bow or crossbow ;ENDIF ;--------------------- IF (akSource as Weapon) RETURN ; - STOP - hit comes from weapon (no magic) ENDIF ;--------------------- IF (akSource as Enchantment) gotoState("Busy") ; ### STATE ### myF_Action(akAggressor, akSource) gotoState("") ; ### STATE ### ENDIF ENDEVENT ;======================== state Busy ; block hit events for a very short time ;========= EVENT OnHit(ObjectReference akAggressor, Form akSource, Projectile akProj, Bool b1, Bool b2, Bool b3, Bool b4) ENDEVENT ;======= endState ; -- FUNCTION -- ;-------------------------------------------------------------- FUNCTION myF_Action(ObjectReference akAggressor, Form akSource) ;-------------------------------------------------------------- actor aRef = akAggressor as Actor IF ( aRef ) Debug.Trace("rightHand Weapon: " + aRef.GetEquippedWeapon(TRUE)) Debug.Trace(" leftHand Weapon: " + aRef.GetEquippedWeapon(False)) ENDIF ENDFUNCTION Sorry to tell ya bud but that code does absolutely nothing as evidenced by the papyrus log. [01/02/2021 - 09:51:22AM] Papyrus log opened (PC) [01/02/2021 - 09:51:22AM] Update budget: 1.200000ms (Extra tasklet budget: 1.200000ms, Load screen budget: 500.000000ms) [01/02/2021 - 09:51:22AM] Memory page: 128 (min) 512 (max) 153600 (max total) [01/02/2021 - 09:51:29AM] VM is freezing... [01/02/2021 - 09:51:29AM] VM is frozen [01/02/2021 - 09:51:29AM] Reverting game... [01/02/2021 - 09:51:34AM] Loading game... [01/02/2021 - 09:51:35AM] VM is thawing... [01/02/2021 - 09:51:35AM] InitWidgetLoader() The reason being is two fold. A) you're stopping it from running "IF (akSource as Enchantment)" before it can even get to that bit of code because every hit is treated as a weapon hit regardless if it's a weapon or an enchant, period. B) as I've stated before, you cannot cast it as anything other than a weapon. If you cast it "as Enchantment" it returns "None" and always "None". You also had the hands backward. Right hand is 0 and left hand is 1, but I digress. After you correct the code, here is what you get: Code EVENT OnHit(ObjectReference akAggressor, Form akSource, Projectile akProj, Bool b1, Bool b2, Bool b3, Bool b4) ; b1 = abPowerAttack ; b2 = abSneakAttack ; b3 = abBashAttack ; b4 = abHitBlocked IF ( b4 ) ; (b4 == TRUE) RETURN ; - STOP - hit from aggressor was blocked by script owner (self, if is not an ActiveMagicEffect script) ENDIF ;--------------------- ;IF ( akProj ) ; Debug.Trace("ranged Weapon: " + (akAggressor as Actor).GetEquippedWeapon()) ; RETURN ; - STOP - hit was made by range weapon like bow or crossbow ;ENDIF ;--------------------- ;IF (akSource as Weapon) COMMENTED OUT BECAUSE IT WILL IMMEDIATELY KILL THE EVENT ; RETURN ; - STOP - hit comes from weapon (no magic) ;ENDIF ;--------------------- IF (akSource as Weapon) CANNOT CAST AS ENCHANTMENT, RETURNS NONE gotoState("Busy") ; ### STATE ### myF_Action(akAggressor, akSource) gotoState("") ; ### STATE ### ENDIF ENDEVENT ;======================== state Busy ; block hit events for a very short time ;========= EVENT OnHit(ObjectReference akAggressor, Form akSource, Projectile akProj, Bool b1, Bool b2, Bool b3, Bool b4) ENDEVENT ;======= endState ; -- FUNCTION -- ;-------------------------------------------------------------- FUNCTION myF_Action(ObjectReference akAggressor, Form akSource) ;-------------------------------------------------------------- actor aRef = akAggressor as Actor IF ( aRef ) Debug.Trace("rightHand Weapon: " + aRef.GetEquippedWeapon(0)) Debug.Trace("leftHand Weapon: " + aRef.GetEquippedWeapon(1)) ENDIF ENDFUNCTION Log [01/02/2021 - 09:59:39AM] Papyrus log opened (PC) [01/02/2021 - 09:59:39AM] Update budget: 1.200000ms (Extra tasklet budget: 1.200000ms, Load screen budget: 500.000000ms) [01/02/2021 - 09:59:39AM] Memory page: 128 (min) 512 (max) 153600 (max total) [01/02/2021 - 09:59:45AM] VM is freezing... [01/02/2021 - 09:59:45AM] VM is frozen [01/02/2021 - 09:59:45AM] Reverting game... [01/02/2021 - 09:59:51AM] Loading game... [01/02/2021 - 09:59:51AM] VM is thawing... [01/02/2021 - 09:59:51AM] InitWidgetLoader() [01/02/2021 - 10:00:04AM] rightHand Weapon: [WEAPON < (00013982)>]-unenchanted weapon [01/02/2021 - 10:00:04AM] leftHand Weapon: None [01/02/2021 - 10:00:15AM] rightHand Weapon: [WEAPON < (00013982)>]- [01/02/2021 - 10:00:15AM] leftHand Weapon: None [01/02/2021 - 10:00:17AM] rightHand Weapon: [WEAPON < (00013982)>]- [01/02/2021 - 10:00:17AM] leftHand Weapon: None [01/02/2021 - 10:00:18AM] rightHand Weapon: [WEAPON < (00013982)>]- [01/02/2021 - 10:00:18AM] leftHand Weapon: None [01/02/2021 - 10:00:25AM] rightHand Weapon: [WEAPON < (00028DE8)>]-enchanted weapon [01/02/2021 - 10:00:25AM] leftHand Weapon: None [01/02/2021 - 10:00:25AM] rightHand Weapon: [WEAPON < (00028DE8)>] [01/02/2021 - 10:00:25AM] leftHand Weapon: None [01/02/2021 - 10:00:29AM] rightHand Weapon: [WEAPON < (00028DE8)>]- [01/02/2021 - 10:00:29AM] leftHand Weapon: None [01/02/2021 - 10:00:29AM] rightHand Weapon: [WEAPON < (00028DE8)>] [01/02/2021 - 10:00:29AM] leftHand Weapon: None [01/02/2021 - 10:00:33AM] rightHand Weapon: [WEAPON < (00028DE8)>]- [01/02/2021 - 10:00:33AM] leftHand Weapon: None [01/02/2021 - 10:00:35AM] rightHand Weapon: [WEAPON < (00028DE8)>]- [01/02/2021 - 10:00:35AM] leftHand Weapon: None [01/02/2021 - 10:00:35AM] rightHand Weapon: [WEAPON < (00028DE8)>] [01/02/2021 - 10:00:35AM] leftHand Weapon: None As you can see by the time stamps for the dashed sections, your code does precisely what I said it would do, which is run the event twice every hit with an enchanted weapon though with a slight anomaly at 10:00:33AM. I've noticed occasionally it does not run double but I'd say 90% of the time it does. I've said it before guys. I've run the casting every which way and tested everything I could think of under the sun for the past two days straight and you cannot detect an enchantment specifically or filter out enchantment hits like the wiki states. Or at least, it won't let me... Link to comment Share on other sites More sharing options...
RichWebster Posted January 2, 2021 Share Posted January 2, 2021 Can you explain what it is you're doing and how you're doing it? We might be able to come up with something if we know the requirements. Set the scene for us. Link to comment Share on other sites More sharing options...
maxarturo Posted January 2, 2021 Share Posted January 2, 2021 As RichWebster said... Link to comment Share on other sites More sharing options...
audiogarden21 Posted January 2, 2021 Author Share Posted January 2, 2021 Can you explain what it is you're doing and how you're doing it? We might be able to come up with something if we know the requirements. Set the scene for us. What I'm trying to do with my mod is irrelevant at this point (which is also moot because the time check workaround provided by dylbill works). All I'm trying to do right now is figure out why Papyrus cannot distinguish between enchantments like the wiki states. This is the only thing I'm trying to get working: Event OnHit(ObjectReference akAggressor, Form akSource, Projectile akProjectile, bool abPowerAttack, bool abSneakAttack, bool abBashAttack, bool abHitBlocked) Weapon RightHandSword = (akAggressor as Actor).GetEquippedWeapon(0); this gets the sword that the enemy had in their right hand and stores it as an object variable If ((akSource as Weapon) == RightHandSword) ;do code stuff EndIf EndEvent Which, as the wiki states, should allow you to detect a hit from the weapon and filter out all enchantment hits, so that the code only runs once, when the weapon in the attacker's right hand is the same as what hit us and not something else like an enchantment. Currently, what it actually does is run the code twice if the weapon has an enchant so it posts "weapon hit", then immediately runs the event again for the "enchantment hit" which is counted as the weapon itself. It hits not once but twice, once per "hit" from both the "weapon hit" and the "enchantment hit", regardless of any efforts to filter out the enchant. Essentially the wiki is wrong from my testing. The code above is directly from the wiki (minus some fixes like a missing EndIf and a cast of akAggressor to Actor otherwise Papyrus complains) for the purposes of filtering enchantment hits and it doesn't work. You could say I'm trying to understand the distinction between what the wiki tells me, and what is actually happening in practical terms. The two are out of sync. I'm not just doing this for me at this point. I'm running myself through the ringers for everyone's sake at this point in the event that they want to do something similar, assuming it's out of sync for everyone else and I'm not just an idiot. xD For the record, here is what the wiki states: To avoid the hits from enchantments running the code block one must compare the akSource to the actual reference that hit the actor/object. For instance, say we have a weapon with 2 enchantments called "Fire/Ice Sword." When hit with this sword the hit registers as 3 separate hits, but you have code such as:Event OnHit(ObjectReference akAggressor, Form akSource, Projectile akProjectile, bool abPowerAttack, bool abSneakAttack, \bool abBashAttack, bool abHitBlocked) if(akSource as Weapon)Variable1 -= 100EndEventThis would actually subtract 300 from Variable1 since the event was called 3 times simultaneously, even though the akSource has been cast as a weapon papyrus counts the hit from the enchantments as "weapons" too so the enchantments are reference as (akSource as Weapon) as well. So the solution is to be more explicit.Event OnHit(ObjectReference akAggressor, Form akSource, Projectile akProjectile, bool abPowerAttack, bool abSneakAttack, \bool abBashAttack, bool abHitBlocked) Form RightHandSword = akAggressor.GetEquippedWeapon(0); this gets the sword that the enemy had in their right hand and stores it as an object variable if((akSource as weapon) == RightHandSword ;do code stuff EndEventThis will still call the event 3 times, but the code will only fire once when (akSource as weapon) == RightHandSword1st hit: Sword: (akSource as weapon) == RightHandSword - fires code2nd hit: Enchant1: (akSource as weapon) == SomeEnchant1 - nothing happens3rd hit: Enchant2: (akSource as weapon) == SomeEnchant2 - nothing happensIf you had the exact same script but only want the code to run when the actor/object that has the script with the OnHit Event is hit with a certain enchantment, regardless of the sword then: Enchantment Property ''TheEnchantment'' Auto Event OnHit(ObjectReference akAggressor, Form akSource, Projectile akProjectile, bool abPowerAttack, bool abSneakAttack, \bool abBashAttack, bool abHitBlocked) if((akSource as weapon) == ''TheEnchantment'' ;do code stuff EndEventWith this code the Actor/Object with the OnHitEvent script could be hit by 5 different weapons but the onhit event will only fire when the weapon has TheEnchantment and it will only fire once. None of it actually works in Skyrim SE. Link to comment Share on other sites More sharing options...
RichWebster Posted January 2, 2021 Share Posted January 2, 2021 That particular contribution was added in 2016. https://www.creationkit.com/index.php?title=OnHit_-_ObjectReference&diff=46226&oldid=45330 I'll do some quick tests myself tomorrow, to verify on my side, and remove it from the wiki if it's actually false. Link to comment Share on other sites More sharing options...
audiogarden21 Posted January 2, 2021 Author Share Posted January 2, 2021 That particular contribution was added in 2016. https://www.creationkit.com/index.php?title=OnHit_-_ObjectReference&diff=46226&oldid=45330 I'll do some quick tests myself tomorrow, to verify on my side, and remove it from the wiki if it's actually false. I see that. I forgot to check how old that contribution was. In any case, I appreciate you taking the time to check on your end to see if it behaves the same for you as it does for me. That's largely what I'm looking for. One thing to note; it might still work for Oldrim so you might just want to notate that the information is false for SE only if that turns out to be the case. Unless someone knows some behind the scenes magic trickery for SE that the rest of us don't, then the time check from dylbill seems to be the simplest solution and can be found on the front page, post #5 for anyone interested. By all means, if anyone else would like to chime in with their own findings, I'm all ears. EDIT You also cannot run the bottom half of that wiki quote I posted that mentions checking for a specific enchantment i.e. "if((akSource as weapon) == ''TheEnchantment''" I'm not sure why he or she added those apostrophes but in any case, Papyrus complains telling you that you cannot compare a weapon to an enchantment, and as stated previously if you try to cast akSource as Enchantment then it will return None. Link to comment Share on other sites More sharing options...
Recommended Posts