qwertypol012 Posted June 11, 2020 Share Posted June 11, 2020 (edited) I have an issue with OnHit event. I want to have a spell which is casted whenever the player is getting hit by a hostile actor while wearing a specific armor. It has several conditions as checks in order for the spell to be successfully casted. At first, i tried to make a script attached to the armor, then equip the armor to my player character. Whenever the armor is getting hit, it checks for several conditions, and run the function to cast the spell if these conditions are passed. Here's the code: Scriptname qlBerserk_ArmorTransformedScript extends ObjectReference GlobalVariable Property Berserk_Immoral_Transformed Auto Quest Property mainQuest Auto Actor Player Event OnContainerChanged(ObjectReference akNewContainer, ObjectReference akOldContainer) If (akNewContainer == Game.GetPlayer() as ObjectReference) Player = akNewContainer as Actor else Player = None Return endIf endEvent Event OnEquipped(Actor akActor) ; OnEquipped will not fire if the item is equipped through the console or papyrus calls If ( mainQuest ) else Debug.Notification("qlBerserk_ArmorTransformed: OnEquipped(1) - quest property is missing!") Return endIf If mainQuest.IsRunning() else Debug.Notification("qlBerserk_ArmorTransformed: OnEquipped(2) - quest is not running!") Return endIf If (mainQuest as qlBerserk_QuestScript) else Debug.Notification("qlBerserk_ArmorTransformed: OnEquipped(3) - quest script 'qlBerserk_QuestScript' not found!") Return endIf Player = akActor endEvent Event OnHit(ObjectReference akAggressor, Form akSource, Projectile akProj, Bool b1, Bool b2, Bool b3, Bool b4) If Player.IsInCombat() else Debug.Notification("Armor Transformed: player is not in combat") ; will be removed later Return ; not in combat (or player is <None>) endIf If Player.IsDead() Debug.Notification("Armor Transformed: player is dead") ; will be removed later Return ; dead endIf If (akAggressor as Actor).IsHostileToActor(player) else Debug.Notification("Armor: attacker is not hostile") ; will be removed later Return ; not hostile (ie. friendly fire or something like that) endIf If (Berserk_Immoral_Transformed.GetValue() as Int == 1) Debug.Notification("Armor Transformed: player is losing control already") ; will be removed later Return ; is losing control already endIf If (mainQuest as qlBerserk_QuestScript) else Debug.Notification("Armor Transformed: 'qlBerserk_QuestScript' not found") ; will be removed later Return endIf (mainQuest as qlBerserk_QuestScript).TryToCast(Player) endEvent Event OnUnequipped(Actor akActor) Player = None endEventThe code for the quest script: Scriptname qlBerserk_QuestScript extends Quest Conditional Quest Property DGIntimidateQuest Auto FormList Property PlayerCombatTargetList Auto GlobalVariable Property Berserk_Config_MoralScoremax Auto GlobalVariable Property HealthThreshold_AutoT Auto GlobalVariable Property IsImmoral Auto GlobalVariable Property MEValueDefiner Auto GlobalVariable Property RandomChance_AutoT Auto Spell Property BerserkArmorBeastChange Auto Spell Property BerserkPlayerScanEnemyAutoT Auto Int MoralScore ; Other events and functions Function TryToCast(Actor player) Debug.Notification("The armor is trying to transform") BerserkPlayerScanEnemyAutoT.Cast(player) Utility.Wait(0.5) ; wait a little bit for Enemy Scan effect to finish adding all valid actors If (MEValueDefiner.GetValue() == 1.0) Debug.Notification("Transformation failed: your body is too weak to transform again") Return ; still in "cooldown" after reverting form, to avoid being forced into dangerous transformation endIf If DGIntimidateQuest.IsRunning() Debug.Notification("Transformation failed: you're in a brawl") Return ; brawling quest is running endIf If (PlayerCombatTargetList.GetSize() > 0) PlayerCombatTargetList.Revert() else Debug.Notification("Transformation failed: enemy is not strong enough") Return endIf If (player.GetActorValuePercentage("Health") > (HealthThreshold_AutoT.GetValue()/100.0)) Debug.Notification("Transformation failed: Health is not in danger") Return ; player health is good enough endIf float f = Utility.RandomInt(1, 100) as Float If (f > RandomChance_AutoT.GetValue()) If (IsImmoral.GetValue() as Int == 0) ;(MoralScore < Berserk_Config_MoralScoremax.GetValue() as Int) Debug.Notification("Transformation failed: Immorality is below the limit") Return ; no luck this time, or MoralScore still below limit endIf endIf Debug.Notification("The armor is transforming") BerserkArmorBeastChange.Cast(player) endFunction But it didn't work. No matter how many times my character got hit, the spell didn't get casted at all. And as shown in the script code for the armor, if the conditions fail then surely the notifications will be shown to infom why it fails. But no notification shown when i get hit multiple times by hostile actors while the spell didn't get casted. It's as if the OnHit event cannot recognize incoming attacks from actors, because i got a notification when i got with by traps (not actors). Because attaching the script to the armor seemed to fail, i then tried to add the code into a Player Alias script instead. The script is as follows: Scriptname qlBerserk_PlayerAliasScript extends ReferenceAlias Quest Property mainQuest Auto GlobalVariable Property Berserk_Immoral_Transformed Auto GlobalVariable Property Berserk_Transform Auto Actor player (defined in other function & event which is not shown below) ; Other events and functions Event OnHit(ObjectReference akAggressor, Form akSource, Projectile akProjectile, Bool abPowerAttack, Bool abSneakAttack, Bool abBashAttack, Bool abHitBlocked) If player.IsInCombat() else Debug.Notification("PlayerAlias: player is not in combat") ; will be removed later Return ; not in combat mode (or player is <None>) endIf If player.IsDead() Debug.Notification("PlayerAlias: player is dead") ; will be removed later Return ; just dead endIf If (akAggressor as Actor).IsHostileToActor(player) else Debug.Notification("PlayerAlias: attacker is not hostile") ; will be removed later Return ; not hostile (ie. friendly fire or something like that) endIf If (mainQuest as qlBerserk_QuestScript) else Debug.Notification("PlayerAlias: 'qlBerserk_QuestScript' not found") ; will be removed later Return endIf If (Berserk_Transform.GetValue() as Int == 1) || (Berserk_Immoral_Transformed.GetValue() as Int == 1) Debug.Notification("PlayerAlias - Armor: player is transformed or losing control already") ; will be removed later Return ; is transformed or is losing control already else Debug.Notification("PlayerAlias - Armor: running TryToCast") ; will be removed later (mainQuest as qlBerserk_QuestScript).TryToCast(player) endIf endEvent The quest script is the same with the previous one. Yet, still, it didn't work. My character got hit multiple times by hostile actors, and not a single notification shown and the function didn't seem to fire. So, is there anyone know why did my OnHit event here fail to detect incoming hits from hostile actors? What's exactly wrong here? Edited June 11, 2020 by qwertypol012 Link to comment Share on other sites More sharing options...
IsharaMeradin Posted June 12, 2020 Share Posted June 12, 2020 Q: Did you fill the properties with the correct data?Q: Are you testing on a new game or save that has not seen the mod in question? Link to comment Share on other sites More sharing options...
qwertypol012 Posted June 12, 2020 Author Share Posted June 12, 2020 I did. All properties were filled in my testing. And of course in a new game. Link to comment Share on other sites More sharing options...
ReDragon2013 Posted June 13, 2020 Share Posted June 13, 2020 (edited) ; variable Actor player ; has to be filled by event code within the script EVENT OnInit() player = Game.GetPlayer() ENDEVENT; property Actor PROPERTY player auto ; has to be pre-defined by Creation Kit Edited June 13, 2020 by ReDragon2013 Link to comment Share on other sites More sharing options...
qwertypol012 Posted June 14, 2020 Author Share Posted June 14, 2020 (edited) ; variable Actor player ; has to be filled by event code within the script EVENT OnInit() player = Game.GetPlayer() ENDEVENT; property Actor PROPERTY player auto ; has to be pre-defined by Creation KitThe player variable has actually been filled in other recent event or function. I didn't write full functions for the player alias script, but there is an initialization function which fills the player variable by Game.GetPlayer(), which is run on game start from the owning quest script of the player alias script. As for the armor script, the player variable should be filled in OnContainerChanged event ie. when the armor is entering player's inventory. I tried to avoid using property as long as possible to lessen the script load. Edited June 14, 2020 by qwertypol012 Link to comment Share on other sites More sharing options...
Recommended Posts