Jump to content

[LE] OnHit event won't detect incoming hits from multiple enemies?


Recommended Posts

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
endEvent

The 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 by qwertypol012
Link to comment
Share on other sites

; 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 by ReDragon2013
Link to comment
Share on other sites

 

; 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

The 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 by qwertypol012
Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...