Jump to content

[LE] How to properly script a custom conditional system which will be used by a quest script?


Recommended Posts

Too many scripts, its very hard to to follow you and find out what you want to reach with this. But now back to the base scripts:

 

qlBerserk_ArmorScript

 

Scriptname qlBerserk_ArmorScript extends ObjectReference
; https://forums.nexusmods.com/index.php?/topic/7301906-how-to-properly-script-a-custom-conditional-system-which-will-be-used-by-a-quest-script/
; is attached to an armor, which controls the spell "BerserkerArmorBeastChange"

;"This script is to add the spell which trigger the transformation to the player. I need to give a bit more explanations about this.
; So, the mod i'm trying to make is a transformation feature which is casted by a spell. The transformation has chance to make the player "losing control".
; The spell to transform is added to the player when he/she is wearing a certain armor.
; This script (ie. SCRBerserkArmorCheckIfSet) checks if the player has worn the armor properly, then add the spell.
; In addition, this script also contains additional features such as initialising the loose control script (ie. Berserk_Loose_Control_Script) and
; giving chance to transform when getting hit." (qwertypol012)

  Quest PROPERTY myQuest auto    ; the special quest "Berserk_Quest_Loose_Control"
  Actor player                    ; for OnHit()

;*******************************************************************************
;* Scheme which summarizes all of above explanations:
;*
;* Player wears the Armor            =>  Transformation Spell added to Player
;* Player cast Transformation Spell  =>  Player enter a Transformation state  =>  Armor unequipped from Player, Armor2 equipped to Player
;*
;* Transformation state:
;*  1. Normal     =>  casted after duration3 end
;*  2. Dangerous  => casted when duration3 still run
;*
;* When Player is in Transformation state /and/ if Player is in combat  =>  has chance to Lose Control
;*
;* If Lose Control is not triggered  =>  Transformation state continues until its duration1 end
;* If Lose Control is triggered      =>  Armor2 unequipped from Player, Armor equpped to Player, control taken from Player,
;*                                       Player replaced by NPC Replacer until its duration2 end
;*
;* After duration1 end  =>  Armor2 uneqipped from Player, Armor equipped to Player, Negative Effects casted to Player until its duration3 end
;* After duration2 end  =>  NPC Replacer disabled, give control back to Player, Negative Effects casted to Player until its duration3 end
;*
;* If duration3 still run  &  Player cast Transformation Spell  =>  Player enter Dangerous Transformation
;*
;* After duration3 end  &  Player cast Transformation Spell  =>  Player enter Normal Transformation
;*
;* When Player is in Dangerous Transformation  &  Player getting hit  =>  Severe Damage spell casted to Player
;********************************************************************************************************************************************


; -- EVENTs -- 1 + "Waiting" + "Action"

EVENT OnContainerChanged(ObjectReference akNewContainer, ObjectReference akOldContainer)
; received when this object enters, exits, or changes containers

IF (akNewContainer == Game.GetPlayer() as ObjectReference)
ELSE
    gotoState("")                ; ### STATE ###
    RETURN    ; - STOP -    not into players inventory
ENDIF
;---------------------
    gotoState("Waiting")        ; ### STATE ###
    IF (myQuest) && !myQuest.IsRunning()
        myQuest.Start()
    ENDIF
ENDEVENT


;====================================
state Waiting    ; for player only
;============
EVENT OnEquipped(Actor akActor)
    IF ( myQuest )
    ELSE
        Debug.Trace("qlBerserk: OnEquipped(1) - quest property is missing!")
        RETURN    ; - STOP -
    ENDIF
    ;---------------------
    IF myQuest.IsRunning()
    ELSE
        Debug.Trace("qlBerserk: OnEquipped(2) - quest is not running!")
        RETURN    ; - STOP -
    ENDIF
    ;---------------------
    IF (myQuest as qlBerserk_QuestScript)
    ELSE
        Debug.Trace("qlBerserk: OnEquipped(3) - quest script 'qlBerserk_QuestScript' not found!")
        RETURN    ; - STOP -
    ENDIF
    ;---------------------
    player = akActor
    gotoState("Action")            ; ### STATE ###
    (myQuest as qlBerserk_QuestScript).myF_Init(akActor, TRUE)
ENDEVENT
;=======
endState


;====================================
state Action    ; for player only
;===========
EVENT OnUnequipped(Actor akActor)
    IF (myQuest as qlBerserk_QuestScript)
    ELSE
        RETURN    ; - STOP -
    ENDIF
    ;---------------------
    gotoState("Waiting")        ; ### STATE ###
    player = None
    (myQuest as qlBerserk_QuestScript).myF_Init(akActor, False)
ENDEVENT

EVENT OnHit(ObjectReference akAggressor, Form akSource, Projectile akProj, Bool b1, Bool b2, Bool b3, Bool b4)
    IF player.IsInCombat()
    ELSE
        RETURN    ; - STOP -    not in combat mode (or player is <None>)
    ENDIF
    ;---------------------
    IF player.IsDead()
        RETURN    ; - STOP -    just dead
    ENDIF
    ;---------------------
    IF (myQuest as qlBerserk_QuestScript)
    ELSE
        RETURN    ; - STOP -
    ENDIF
    ;---------------------
    (myQuest as qlBerserk_QuestScript).myF_TryToCast(player, akAggressor)    ; BerserkerArmorBeastChange.Cast(player)
ENDEVENT
;=======
endState

 

 

 

qlBerserk_EffectScript

 

Scriptname qlBerserk_EffectScript extends ActiveMagicEffect
; https://forums.nexusmods.com/index.php?/topic/7301906-how-to-properly-script-a-custom-conditional-system-which-will-be-used-by-a-quest-script/
; "This script is for warning spell which will be casted when the player is about to lose control."

  GlobalVariable PROPERTY Berserk_Comp_Dawnguard auto        ; DLC1 has been loaded, GetValue() = 1.0
  GlobalVariable PROPERTY Berserk_Config_Sounds  auto

  MagicEffect PROPERTY Berserk_Effect_Warningspell auto        ; effect that this script should be attached

; switch to something more suitable, such as heartbeat sound
  Sound PROPERTY UIHealthHeartbeatALPSD auto
  Sound PROPERTY UIHealthHeartbeatBLPSD auto

  ImageSpaceModifier PROPERTY DA10HauntingISMDFadeIn auto
  ImageSpaceModifier PROPERTY DA10HauntingISMDLoop   auto
  ImageSpaceModifier PROPERTY WerewolfWarningImod    auto
  ImageSpaceModifier     DLC1AurielsEclipseImod01

  Bool bReady


; -- EVENTs -- 2 + "Running"

EVENT OnEffectStart(Actor akTarget, Actor akCaster)
IF (akTarget == Game.GetPlayer())
ELSE
    self.Dispel()                                            ; akTarget.DispelSpell(Berserk_Spell_Warningspell)
    RETURN    ; - STOP -    target is not the player
ENDIF
;---------------------
    bReady = TRUE
    gotoState("Running")            ; ### STATE ###
    RegisterForSingleUpdate(5.0)                            ; wait 5 seconds, before triggering update event                        
ENDEVENT


EVENT OnEffectFinish(Actor akTarget, Actor akCaster)
    myF_Remove()
ENDEVENT


;==========================================
State Running
;============
EVENT OnUpdate()
    IF ( !DLC1AurielsEclipseImod01 )
        myF_SetImod01()
    ENDIF

IF myF_IsEffectGone(DA10HauntingISMDFadeIn, 12.0)    ; wait three times inside (maximum)
    RETURN    ; - STOP -
ENDIF
;---------------------
IF myF_IsEffectGone(DA10HauntingISMDLoop, 16.0)        ; wait four times inside (maximum)
    RETURN    ; - STOP -
ENDIF
;---------------------
    RegisterForSingleUpdate(3.0)                            ; trigger event again in 3 seconds
ENDEVENT
;=======
endState


; -- FUNCTIONs -- 4

;-----------------------
FUNCTION myF_SetImod01()
;-----------------------
    DLC1AurielsEclipseImod01 = WerewolfWarningImod

; *** Dawnguard DLC
    IF (Berserk_Comp_Dawnguard.GetValue() == 1)
        form fm = Game.GetFormFromFile(0x02003DCD, "Dawnguard.esm")
        IF (fm as ImageSpaceModifier)
            DLC1AurielsEclipseImod01 = fm as ImageSpaceModifier
        ELSE
            Debug.Trace("Error: Cannot find Dawnguard imod 'DLC1AurielsEclipseImod01'!")
        ENDIF
    ENDIF
; *** End of Dawnguard DLC
ENDFUNCTION


;--------------------------------------------------------------
Bool FUNCTION myF_IsEffectGone(ImageSpaceModifier ISM, Float f)
;--------------------------------------------------------------
    ISM.Remove()                ; probably this is needed here!!
    ISM.ApplyCrossFade(f)
;;;    magicEffect ME = self as MagicEffect        ; <-- THIS IS NOT POSSIBLE !!!

int i = (f / 4.0) as Int        ; loop counter
    WHILE (i > 0) && Game.GetPlayer().HasMagicEffect(Berserk_Effect_Warningspell)
        myF_Play()
        Utility.Wait(4.0)
        i = i - 1
    ENDWHILE

IF Game.GetPlayer().HasMagicEffect(Berserk_Effect_Warningspell)
    Return False        ; ***
ENDIF
;---------
    myF_Remove()
    Return TRUE            ; *T*
ENDFUNCTION


;--------------------
FUNCTION myF_Remove()
;--------------------
IF ( !bReady )
    RETURN    ; - STOP - imods already removed
ENDIF
;---------------------
    bReady = False
    gotoState("")                    ; ### STATE ###

    DA10HauntingISMDFadeIn.Remove()
    DA10HauntingISMDLoop.Remove()
    IF ( DLC1AurielsEclipseImod01 )
        DLC1AurielsEclipseImod01.Remove()
    ENDIF
ENDFUNCTION


;------------------
FUNCTION myF_Play()
;------------------
IF ( DLC1AurielsEclipseImod01 )
    DLC1AurielsEclipseImod01.Remove()
    DLC1AurielsEclipseImod01.Apply()
ENDIF

    objectReference playerRef = Game.GetPlayer() as ObjectReference

    Game.ShakeCamera(afStrength = 1, afDuration = 2)
    UIHealthHeartbeatBLPSD.Play(playerRef)

IF (Berserk_Config_Sounds.GetValue() == 1) && (Utility.RandomInt(1, 4) == 1)    ; RandomGrowlSound 25% chance
    int i = UIHealthHeartbeatALPSD.Play(playerRef)                                ; i = SoundID1
    IF (i > 0)
        Sound.SetInstanceVolume(i, 0.5)
    ENDIF
ENDIF
ENDFUNCTION

 

 

 

;Scriptname Berserk_RefAlias_Playerreplacement_Script extends ReferenceAlias
;Scriptname qlBerserk_PlayerAliasScript extends ReferenceAlias

qlBerserk_ReplacementAliasScript

 

Scriptname qlBerserk_ReplacementAliasScript extends ReferenceAlias
; https://forums.nexusmods.com/index.php?/topic/7301906-how-to-properly-script-a-custom-conditional-system-which-will-be-used-by-a-quest-script/
; This script is a ref alias for the player replacement when he/she is losing control and being replaced by the NPC replacer.

  qlBerserk_QuestScript ps


; -- EVENTs -- 5 + "Busy"

EVENT OnInit()
    ps = self.GetOwningQuest() as qlBerserk_QuestScript
ENDEVENT


EVENT OnDetachedFromCell()
    myF_Action(0)
ENDEVENT


EVENT OnDying(Actor akKiller)
    myF_Action(1, akKiller)
ENDEVENT


;Event OnHit(ObjectReference akAggressor, Form akSource, Projectile akProjectile, bool abPowerAttack, bool abSneakAttack, bool abBashAttack, bool abHitBlocked)
EVENT OnHit(ObjectReference akAggressor, Form akSource, Projectile akProj, Bool b1, Bool b2, Bool b3, Bool b4)
;;;    gotoState("Busy")                ; ### STATE ###
    Utility.Wait(0.1)
    myF_Action(2)
;;;    gotoState("")                    ; ### STATE ###
ENDEVENT


EVENT OnObjectEquipped(Form akBaseObject, ObjectReference akReference)
IF (akBaseObject as Ammo)
    myF_Ammo(akBaseObject, TRUE)
ENDIF
ENDEVENT


EVENT OnObjectUnEquipped(Form akBaseObject, ObjectReference akReference)
IF (akBaseObject as Ammo)
    myF_Ammo(akBaseObject, False)
ENDIF
ENDEVENT


;;====================================
;state Busy
;;=========
;EVENT OnHit(ObjectReference akAggressor, Form akSource, Projectile akProj, Bool b1, Bool b2, Bool b3, Bool b4)
;ENDEVENT
;;=======
;endState


; -- FUNCTIONs -- 2

;----------------------------------------------
FUNCTION myF_Ammo(Form akBaseObject, Bool bAdd)
;----------------------------------------------
IF ( ps )
ELSE
    Debug.Trace(" myF_Ammo(" +bAdd+ ") - Error:  quest = " + self.GetOwningQuest() + ", script = " +ps)
    RETURN    ; - STOP -
ENDIF
;=====================
    formList fmL = ps.WornAmmoList

IF ( fmL )
ELSE
    Debug.Trace(" myF_Ammo(" +bAdd+ ") - Error: formlist for worn ammo is missing!")
    RETURN    ; - STOP -
ENDIF
;---------------------
    IF ( bAdd )
        fmL.AddForm(akBaseObject)            ; gets filled as ammo is equipped by the player
    ELSE
        fmL.RemoveAddedForm(akBaseObject)    ; gets removed as ammo is unequipped by the player
    ENDIF
ENDFUNCTION


;------------------------------------------
FUNCTION myF_Action(Int i, Actor aRef=None)
;------------------------------------------
IF ( ps )
ELSE
    Debug.Trace(" myF_Action(" +i+ ") - Error:  quest = " + self.GetOwningQuest() + ", script = " +ps)
    RETURN    ; - STOP -
ENDIF
;=====================
IF (i == 0)
    ps.update_player_pos()
    RETURN    ; - STOP -    detached
ENDIF
;---------------------
IF (i == 1)
    ps.player_replacement_was_killed(self.GetActorReference(), aRef)
    RETURN    ; - STOP -    dying
ENDIF
;---------------------
IF (i == 2)
    ps.update_player_health()
;;;    RETURN    ; - STOP -    hit
ENDIF
ENDFUNCTION

 

 

 

; Scriptname qlMEBerserkerTransformScript extends ActiveMagicEffect

; Scriptname qlMEBerserkerTransformDangerScript extends ActiveMagicEffect

; Scriptname qlMENegativeEffectsScript extends ActiveMagicEffect

qlBerserk_TransformFinishScript

 

Scriptname qlBerserk_TransformFinishScript extends ActiveMagicEffect
{set active flag into globalVar for effects 'BerserkerArmorBeastT' and 'BerserkerArmorBeastTDanger'}
; https://forums.nexusmods.com/index.php?/topic/7285811-how-to-script-2-magic-effects-with-different-conditions-and-they-nullify-each-other/

; Its a replacement for next scripts:
;    qlMEBerserkerTransformScript         ; 1.0
;    qlMEBerserkerTransformDangerScript   ; 1.0
;    qlMENegativeEffectsScript            ; 0.0

  GlobalVariable PROPERTY MEValueDefiner auto    ; its value defines what MEs are active
  Float PROPERTY EffectValue = 1.0       auto    ; [default=1.0], can be different for each effect that script will be attached
  {set to 0.0 for former used script qlMENegativeEffectsScript}


; -- EVENTs --

EVENT OnEffectStart(Actor akTarget, Actor akCaster)
    Debug.Trace(" OnEffectStart() - akTarget = " +akTarget+ ", akCaster = " +akCaster+ "  " +self)        ; debugging only
ENDEVENT


EVENT OnEffectFinish(Actor akTarget, Actor akCaster)
    MEValueDefiner.SetValue(EffectValue)        ; set the value to activate damage attributes and debuffs
ENDEVENT

 

 

 

qlBerserk_TransformScript

 

Scriptname qlBerserk_TransformScript extends ActiveMagicEffect
{Berserker Armor transformation}
; https://forums.nexusmods.com/index.php?/topic/7301906-how-to-properly-script-a-custom-conditional-system-which-will-be-used-by-a-quest-script/  

  Spell PROPERTY BerserkerArmorBeastChange auto
  Spell PROPERTY BerserkerArmorRevertForm  auto

  Idle         PROPERTY IdleVampireLordTransformation auto
  Explosion    PROPERTY FXVampChangeExplosion         auto
  EffectShader PROPERTY Deintegrate                   auto      ; desintegration

  Armor PROPERTY ArmorBerserkSHelmet      auto        ; head
  Armor PROPERTY ArmorBerserkWHelmet      auto

  Armor PROPERTY ArmorBerserkerCuirass    auto        ; body
  Armor PROPERTY ArmorBerserkerWCuirass   auto
  Armor PROPERTY ArmorBerserkerWCuirass2  auto

  Armor PROPERTY ArmorBerserkerGauntlets  auto        ; hands
  Armor PROPERTY ArmorBerserkerGauntlets2 auto

  Armor PROPERTY ArmorBerserkerBoots      auto        ; legs
  Armor PROPERTY ArmorBerserkerWBoots     auto
  Armor PROPERTY ArmorBerserkerWBoots2    auto

  Actor PROPERTY PlayerEquipmentBrsk auto

  Bool bRemoveGhost
 ;Bool abIsGhost


; -- EVENTs -- 3

EVENT OnEffectStart(Actor akTarget, Actor akCaster)
IF (akTarget == Game.GetPlayer())
ELSE
    self.Dispel()
    RETURN    ; - STOP - /0    failsafe, player is not the target
ENDIF
;---------------------
IF akTarget.IsEquipped(ArmorBerserkerCuirass) && akTarget.IsEquipped(ArmorBerserkerBoots)
ELSE                ; edited by ReDragon 2019/02/04
    self.Dispel()
    RETURN    ; - STOP - /1    failsafe, player does not have any berserker armor
ENDIF
;---------------------
    IF akTarget.IsGhost()
        bRemoveGhost = False    ; x = 0 as Bool
    ELSE
       bRemoveGhost  = TRUE        ; x = 1 as Bool
       akTarget.GetActorBase().SetInvulnerable()
       akTarget.SetGhost()
    ENDIF

;    if abIsGhost == false
;       akTarget.SetGhost()
;    endif

    RegisterForAnimationEvent(akTarget as ObjectReference, "SetRace")
    akTarget.PlayIdle(IdleVampireLordTransformation)
    akTarget.RestoreActorValue("health", 5000)

    Utility.Wait(10.0)

    TransformIfNecessary(akTarget)
    MakeForm(akTarget)
ENDEVENT


EVENT OnEffectFinish(Actor akTarget, Actor akCaster)
    RevertForm(akTarget)
ENDEVENT


EVENT OnAnimationEvent(ObjectReference akSource, string asEventName)
;;    Debug.Trace("VAMPIRE: Getting anim event -- " + akSource + " " + asEventName)

IF (asEventName == "SetRace")
    TransformIfNecessary(akSource as Actor)
ENDIF
ENDEVENT


; -- FUNCTIONs -- 3

;------------------------------------------
FUNCTION TransformIfNecessary(Actor player)
;------------------------------------------
IF ( player )
ELSE
    RETURN    ; - STOP -    invalid parameter
ENDIF
;---------------------
    UnRegisterForAnimationEvent(player as ObjectReference, "SetRace")
    player.PlaceAtMe(FXVampChangeExplosion)                ; place explosion now

    IF ( bRemoveGhost )
        player.GetActorBase().SetInvulnerable(False)
        player.SetGhost(False)
    ENDIF

;    if abIsGhost == true
;        akTarget.SetGhost(false)    ;it is possible that actor will lose ghost status even if his status is ghost by default
;    endif
ENDFUNCTION


;------------------------------
FUNCTION MakeForm(Actor player)  ; outsourced code from OnEffectStart()
;------------------------------
IF ( player )
ELSE
    RETURN    ; - STOP -    invalid parameter
ENDIF
;---------------------
;   if (akTarget.GetWornForm(0x00000008) != none)
;        Debug.Messagebox("Gauntlets are equipped")
;   else
;       Debug.MessageBox("Gauntlets are not equipped or something is wrong")
;   endif

    form fm

;    check if gauntlets are being worn or not, then add and equip them to the dummy if they are
    fm = player.GetWornForm(0x00000008)        ; Gauntlets
    IF (fm as Armor)
        PlayerEquipmentBrsk.AddItem(fm, absilent=true)
        PlayerEquipmentBrsk.EquipItem(fm, true, true)
;          Debug.MessageBox(Gauntlets)
    ENDIF

;    check if a full head helmet is being worn or not, then add and equip it to the dummy if it is
    fm = player.GetWornForm(0x00000003)        ; HeadHair
    IF (fm as Armor)
        PlayerEquipmentBrsk.AddItem(fm, absilent=true)
        PlayerEquipmentBrsk.EquipItem(fm, true, true)
;   else
;          Debug.MessageBox("You have nothing equipped on HeadHair")
    ENDIF

;    check if a head only helmet is being worn or not, then add and equip it to the dummy if it is
    fm = player.GetWornForm(0x00000001)        ; Head
    IF (fm as Armor)
        PlayerEquipmentBrsk.AddItem(fm, absilent=true)
        PlayerEquipmentBrsk.EquipItem(fm, true, true)
    ENDIF

;    check if a hair only helmet is being worn or not, then add and equip it to the dummy if it is
    fm = player.GetWornForm(0x00000002)        ; Hair
    IF (fm as Armor)
        PlayerEquipmentBrsk.AddItem(fm, absilent=true)
        PlayerEquipmentBrsk.EquipItem(fm, true, true)
    ENDIF

;   if PlayerEquipmentBrsk.IsEquipped(Gauntlets)
;          Debug.MessageBox(PlayerEquipmentBrsk + "has equipped" +  Gauntlets)
;   else
;          Debug.MessageBox(PlayerEquipmentBrsk + "could not equip" + Gauntlets)
;   endif

; This was to check if the NPC was equipping the stuff or not...
;    PlayerEquipmentBrsk.Moveto(Game.GetPlayer())

    player.EquipItem(ArmorBerserkerWBoots2,    true, true)
    player.EquipItem(ArmorBerserkerWCuirass2,  true, true)
    player.EquipItem(ArmorBerserkerGauntlets2, true, true)
    player.EquipItem(ArmorBerserkWHelmet,      true, true)

    player.AddSpell(BerserkerArmorRevertForm)
    player.RemoveSpell(BerserkerArmorBeastChange)
ENDFUNCTION


;--------------------------------
FUNCTION RevertForm(Actor player)
;--------------------------------
IF ( player )
ELSE
    RETURN    ; - STOP -    invalid parameter
ENDIF
;---------------------
    Deintegrate.Play(player)                            ; *** effectShader
    Utility.Wait(2.0)

    player.UnEquipItem(ArmorBerserkerWBoots2,    false, true)
    player.UnEquipItem(ArmorBerserkerWCuirass2,  false, true)
    player.UnEquipItem(ArmorBerserkerGauntlets2, false, true)
    player.UnEquipItem(ArmorBerserkWHelmet,      false, true)

    player.EquipItem(ArmorBerserkerCuirass,      false, true)
    player.EquipItem(ArmorBerserkerBoots,        false, true)

    form fm

;check if gauntlets are being worn or not
    fm = PlayerEquipmentBrsk.GetWornForm(0x00000008)    ; Gaunlets
    IF (fm as Armor)
        player.EquipItem(fm, false, true)
    ENDIF

;check if a full head helmet is being worn or not
    fm = PlayerEquipmentBrsk.GetWornForm(0x00000003)    ; HeadHair
    IF (fm as Armor)
        player.EquipItem(fm, false, true)
    ENDIF

;check if a head only helmet is being worn or not
    fm = PlayerEquipmentBrsk.GetWornForm(0x00000001)    ; Head
    IF (fm as Armor)
        player.EquipItem(fm, false, true)
    ENDIF

;check if a hair only helmet is being worn or not
    fm = PlayerEquipmentBrsk.GetWornForm(0x00000002)    ; Hair
    IF (fm as Armor)
        player.EquipItem(fm, false, true)
    ENDIF

    PlayerEquipmentBrsk.RemoveAllItems()        ; Dangerous !!!

;Checking if it did remove them again
;   PlayerEquipmentBrsk.MoveTo(Game.GetPlayer())

    player.AddSpell(BerserkerArmorBeastChange)
    player.EquipSpell(BerserkerArmorBeastChange, 2)

    Deintegrate.Stop(player)                            ; ***
    player.RemoveSpell(BerserkerArmorRevertForm)

    player.RemoveItem(ArmorBerserkSHelmet,      abSilent=true)
    player.RemoveItem(ArmorBerserkWHelmet,      abSilent=true)

    player.RemoveItem(ArmorBerserkerWCuirass,   abSilent=true)
    player.RemoveItem(ArmorBerserkerWCuirass2,  abSilent=true)

    player.RemoveItem(ArmorBerserkerGauntlets,  abSilent=true)
    player.RemoveItem(ArmorBerserkerGauntlets2, abSilent=true)

    player.RemoveItem(ArmorBerserkerWBoots,     abSilent=true)
    player.RemoveItem(ArmorBerserkerWBoots2,    abSilent=true)
ENDFUNCTION

 

 

Edited by ReDragon2013
Link to comment
Share on other sites

And now the quest script, but you have it already changed. I tried my best to understand the script and functionality.

 

qlBerserk_QuestScript

 

Scriptname qlBerserk_QuestScript extends Quest Conditional
; https://forums.nexusmods.com/index.php?/topic/7301906-how-to-properly-script-a-custom-conditional-system-which-will-be-used-by-a-quest-script/

; Based on MTE_Quest_Loose_Control_Script from Moonlight Tales Essentials Overhauled (MTEO) by ubuntufreakdragon,
; most credits go to him for providing a robust base script for lose control functionality

; Huge credits go to ReDragon2013 (Nexusmods member) for helping me A LOT in editing and opimizing the script!
; That guy is really amazing :D
; ---------------------------------------------------------------------------------------------------------------

; qwertypol012 wrote: "I'll post my WIP script here so that people will get a better idea on what i'm working on..
; ..still currently trying to make Transform Condition System."


;vanilla
  GlobalVariable PROPERTY GameDaysPassed auto
  GlobalVariable PROPERTY TimeScale      auto

  Perk PROPERTY AllowShoutingPerk auto                        ;*ql
  Idle PROPERTY BleedOutStart     auto                        ;*ql
  Idle PROPERTY BleedOutStop      auto                        ;*ql

  Static   PROPERTY DwePlatMid01              auto            ; to place a marker and moveto
  Location PROPERTY WhiterunJorrvaskrLocation auto            ;++ moved from armor script (ReDragon)

  ImageSpaceModifier PROPERTY FadeToBlackImod     auto
  ImageSpaceModifier PROPERTY FadeToBlackHoldImod auto
  ImageSpaceModifier PROPERTY FadeToBlackBackImod auto
  ImageSpaceModifier PROPERTY IllusionBlueMassiveImod auto

;others
  ReferenceAlias PROPERTY BerserkerAlias auto
  GlobalVariable PROPERTY MEValueDefiner auto                ;*ql added, its value defines which MGEF is currently active

  MagicEffect PROPERTY BerserkArmorBeastT       auto        ;*ql
  MagicEffect PROPERTY BerserkArmorBeastTDanger auto        ;*ql

;;;  SCRBerserkArmorB Property BerserkArmorBeastT       auto    ; ??
;;;  SCRBerserkArmorB Property BerserkArmorBeastTDanger auto    ; ??

  Perk  PROPERTY Berserk_NPC_FallDmg              auto        ;*ql
  Spell PROPERTY Berserk_Spell_Warningspell       auto        ; similar with MTE, but only take visual effects without sound effects, or switch sound effects into something more fitting
  Spell PROPERTY BerserkerArmorBeastChange          auto        ;++ moved from armor script (ReDragon)
  Spell PROPERTY BerserkerLostControlAfterEffects auto         ;*ql spell to trigger debuff effects after lost control effect finished

  Armor PROPERTY ArmorBerserkWHelmet      auto                ;*ql head
  Armor PROPERTY ArmorBerserkerWCuirass2  auto                ;*ql body
  Armor PROPERTY ArmorBerserkerGauntlets2 auto                ;*ql arms
  Armor PROPERTY ArmorBerserkerWBoots2    auto                ;*ql legs

;++moved all 3 globalVars from armor script (ReDragon)
  GlobalVariable PROPERTY HealthThreshold_AutoT auto
  GlobalVariable PROPERTY TargetLvlMult_AutoT   auto
  GlobalVariable PROPERTY RandomChance_AutoT    auto

;loose control timings
  GlobalVariable PROPERTY Berserk_Config_LooseControlBaseTimeMin     auto
  GlobalVariable PROPERTY Berserk_Config_LooseControlBaseTimeMax     auto
  GlobalVariable PROPERTY Berserk_Config_LooseControlCooldownTimeMin auto
  GlobalVariable PROPERTY Berserk_Config_LooseControlCooldownTimeMax auto

;loose control values
  GlobalVariable PROPERTY Berserk_Config_LooseControlBaseChance  auto
  GlobalVariable PROPERTY Berserk_Config_LooseControlBaseWeight  auto
  GlobalVariable PROPERTY Berserk_Config_LooseControlMoralWeight auto    ; [default value = 1], make sure it's counted correctly in the MCM
 ;GlobalVariable PROPERTY Berserk_Config_LooseControlKillWeight  auto    ;*ql obsolete
  GlobalVariable PROPERTY Berserk_Config_LooseControlDeathtype   auto
  GlobalVariable PROPERTY Berserk_Config_Moral_Warningtime       auto    ;*ql added

 ;GlobalVariable PROPERTY Berserk_Config_LooseControlMoral       auto    ;*ql replaced by next variable
  GlobalVariable PROPERTY Berserk_LooseControlMoral_Enable       auto    ; on/off toggle for lost control based on moral

;moral score
 ;GlobalVariable PROPERTY Berserk_Config_MoralScorebase          auto    ; OBSOLETE, not used anymore
 ;GlobalVariable PROPERTY Berserk_Config_Killscoremodifier       auto    ;*ql removed
  GlobalVariable PROPERTY Berserk_Config_MoralScoremax           auto
  GlobalVariable PROPERTY Berserk_Config_MoralScoretimemultmax   auto

;moral status
  GlobalVariable PROPERTY Berserk_Moral_Transformed auto

;global storage
  GlobalVariable PROPERTY Berserk_Moral_Config_GSWerewolf     auto        ;default 10
  GlobalVariable PROPERTY Berserk_Moral_Config_GSNeckBit      auto        ;default 8
  GlobalVariable PROPERTY Berserk_Moral_Config_GSBribe        auto        ;default 1
  GlobalVariable PROPERTY Berserk_Moral_Config_GSIntimidation auto        ;default 4
  GlobalVariable PROPERTY Berserk_Moral_Config_GSTGQuest      auto        ;default 5
  GlobalVariable PROPERTY Berserk_Moral_Config_GSDBQuest      auto        ;default 10
  GlobalVariable PROPERTY Berserk_Moral_Config_GSDaedricQuest auto        ;default 100
  GlobalVariable PROPERTY Berserk_Moral_Config_GSPeopleKill   auto        ;default 2
  GlobalVariable PROPERTY Berserk_Moral_Config_GSAnimalKill   auto        ;default 2
  GlobalVariable PROPERTY Berserk_Moral_Config_GSUndeadKill   auto        ;default -2
  GlobalVariable PROPERTY Berserk_Moral_Config_GSDaedraKill   auto        ;default -4
  GlobalVariable PROPERTY Berserk_Moral_Config_GSBunnyKill    auto        ;default 1
  GlobalVariable PROPERTY Berserk_Moral_Config_GSDragonSoul   auto        ;default -2
  GlobalVariable PROPERTY Berserk_Moral_Config_GSShoutLearn   auto        ;default -4
  GlobalVariable PROPERTY Berserk_Moral_Config_GSShoutMaster  auto        ;default -10
  GlobalVariable PROPERTY Berserk_Moral_Config_GSTotalBounty  auto        ;default 80
  GlobalVariable PROPERTY Berserk_Moral_Config_GSItemPickpocket auto    ;default 1
  GlobalVariable PROPERTY Berserk_Moral_Config_GSTimeJail     auto        ;default 4
  GlobalVariable PROPERTY Berserk_Moral_Config_GSJailEscape   auto        ;default 10
  GlobalVariable PROPERTY Berserk_Moral_Config_GSItemSteal    auto        ;default 1
  GlobalVariable PROPERTY Berserk_Moral_Config_GSAssault      auto        ;default 60
  GlobalVariable PROPERTY Berserk_Moral_Config_GSMurder       auto        ;default 80
  GlobalVariable PROPERTY Berserk_Moral_Config_GSHorseSteal   auto        ;default 4
  GlobalVariable PROPERTY Berserk_Moral_Config_GSTrespass     auto        ;default 2

;bounty stage
  GlobalVariable PROPERTY Berserk_Moral_Config_BountyStage1   auto        ;default 1000
  GlobalVariable PROPERTY Berserk_Moral_Config_BountyStage2   auto        ;default 2000
  GlobalVariable PROPERTY Berserk_Moral_Config_BountyStage3   auto        ;default 3000
  GlobalVariable PROPERTY Berserk_Moral_Config_BountyStage4   auto        ;default 4000
  GlobalVariable PROPERTY Berserk_Moral_Config_BountyStage5   auto        ;default 5000
  GlobalVariable PROPERTY Berserk_Moral_Config_BountyStage6   auto        ;default 6000
  GlobalVariable PROPERTY Berserk_Moral_Config_BountyStage7   auto        ;default 7000
  GlobalVariable PROPERTY Berserk_Moral_Config_BountyStage8   auto        ;default 8000
  GlobalVariable PROPERTY Berserk_Moral_Config_BountyStage9   auto        ;default 9000
  GlobalVariable PROPERTY Berserk_Moral_Config_BountyStage10  auto        ;default 10000


 ;ActorBase[] PROPERTY Berserk_Player_Loose_Controls_Array auto         ; array to store actorbases as follow (not using array for now)
;; male
  ActorBase PROPERTY Berserk_Player_Loose_Controls_Unarmed_M    auto    ; 0
  ActorBase PROPERTY Berserk_Player_Loose_Controls_Melee_M      auto    ; 1
  ActorBase PROPERTY Berserk_Player_Loose_Controls_Ranger_M     auto    ; 2
  ActorBase PROPERTY Berserk_Player_Loose_Controls_Mage_M       auto    ; 3
  ActorBase PROPERTY Berserk_Player_Loose_Controls_Spellsword_M auto    ; 4
;; female
  ActorBase PROPERTY Berserk_Player_Loose_Controls_Unarmed_F    auto    ; 5
  ActorBase PROPERTY Berserk_Player_Loose_Controls_Melee_F      auto    ; 6
  ActorBase PROPERTY Berserk_Player_Loose_Controls_Ranger_F     auto    ; 7
  ActorBase PROPERTY Berserk_Player_Loose_Controls_Mage_F       auto    ; 8
  ActorBase PROPERTY Berserk_Player_Loose_Controls_Spellsword_F auto    ; 9

;-----------------------------------------------------------------
  Bool PROPERTY player_has_control        = TRUE  auto Conditional
  Bool PROPERTY player_is_loosing_control = False auto Conditional
;-----------------------------------------------------------------

  FormList PROPERTY Berserk_List_secure_caves auto
  Formlist PROPERTY WornAmmoList              auto Hidden    ; starts out empty

 ;Float killscorebuffresettime     = 0.0    ;*ql removed
  Float Invisibility_originalvalue = 0.0

 ;Int killscore     = 0        ;*ql removed
 ;Int killscorebuff = 0        ;*ql removed

;;;  Int MoralMax                ;*ql added, as a max value for MoralScore, default is 500
  Int MoralScore            ;*ql added, contains accumulated points from all used game statistics

  Bool LC_system_active          = False
  Bool singlerun_updating_health = False    ; just to block updatespam, required If placed in an OnHit
  Bool singlerun_updating_pos    = False    ; just to block updatespam.

  Actor BerserkerRef
  ObjectReference PlatRef

; playerAlias script
    ; ps.update_player_pos()
    ; ps.player_replacement_was_killed(self.GetActorReference(), aRef)
    ; ps.update_player_health()


;----------------------------------------------------------------
FUNCTION myF_TryToCast(Actor player, ObjectReference akAggressor)  ; external called by "qlBerserk_ArmorScript" only
;----------------------------------------------------------------
IF (akAggressor as Actor)
ELSE
    RETURN    ; - STOP - /0    no actor, no cast
ENDIF
;---------------------
IF (player.GetActorValuePercentage("Health") > HealthThreshold_AutoT.GetValue())
    RETURN    ; - STOP - /1    player health is good enough
ENDIF
;---------------------
    float f = Utility.RandomFloat(1.0, 100.0)

IF (f > RandomChance_AutoT.GetValue())
    RETURN    ; - STOP - /2    no luck this time
ENDIF
;---------------------
IF (player.GetCurrentLocation() == WhiterunJorrvaskrLocation)
    RETURN    ; - STOP - /3    special location detected
ENDIF
;---------------------
    actor aRef = player.GetCombatTarget()
    Debug.Trace(" myF_TryToCast() - akAggressor = " +akAggressor as Actor+ ", combatTarget = " +aRef)        ; debugging only

IF ((akAggressor as Actor).GetLevel() < (player.GetLevel() * TargetLvlMult_AutoT.GetValue() as Int))
    RETURN    ; - STOP - /4    player level is too high
ENDIF
;---------------------
    BerserkerArmorBeastChange.Cast(player)
ENDFUNCTION


;------------------------------------------
FUNCTION myF_Init(Actor player, Bool bInit)  ; external called by "qlBerserk_ArmorScript" only
;------------------------------------------
IF ( !bInit )
    player.RemoveSpell(BerserkerArmorBeastChange)
    RETURN    ; - STOP -    armor unequipped
ENDIF
;---------------------
    player.AddSpell(BerserkerArmorBeastChange)
    player.EquipSpell(BerserkerArmorBeastChange, 2)
    Initialise()
ENDFUNCTION


;--------------------
FUNCTION Initialise()  ; the LC system until, Force_control_to_player() is called
;--------------------
; setting up some time until, the loose control check runs first

;If (Berserk_LooseControlMoral_Enable.GetValueInt() == 1)    ; currently checked in mainloop
;    return
;EndIf

;;;    KillScore = 0        ;*ql
;   MoralScore=0        ;no more set as an assignment variable, no need to be initialized,
                        ;because it seems that game stats can be tracked & accumulated without using assignment

    LC_system_active = TRUE
    RegisterForSingleUpdateGameTime( Utility.RandomFloat(0.25, 0.5) )    ; run first check after a quarter to a half hour
ENDFUNCTION


; -- EVENTs -- 2

EVENT OnUpdate()
IF ( player_has_control )
    RETURN    ; - STOP -    player has its control back
ENDIF
;---------------------  player lost control
    update_player_pos()            ; opdate Player position to loaded cells
    Utility.Wait(0.1)            ; to let the new cell load if any

    update_player_health()      ; run after update pos, as unloaded NPCs have well unknown health values.
    RegisterForSingleUpdate(2.9)
ENDEVENT


EVENT OnUpdateGameTime()      ; only running while lose control transformations controlled by moral counting running the main rolls
IF ( LC_system_active )
ELSE
    RETURN    ; - STOP - /0    system not active
ENDIF
;---------------------
IF (Berserk_LooseControlMoral_Enable.GetValue() as Bool) && myF_IsBerserkerArmor(False) && (player_has_control) && (!player_is_loosing_control)
    Moral_counting()            ; applies both in & out of combat
    IF myF_IsBerserkerArmor(TRUE)
        Loose_Control_Roll()    ; loose control roll only applies in combat
    ENDIF
    RETURN    ; - STOP - /1
ENDIF
;---------------------
IF (player_is_loosing_control) && myF_IsBerserkerArmor(TRUE)      ;make sure to only call this once transformation is complete
    myF_Dispel()
    Trigger_control_loss()
    RETURN    ; - STOP - /2   looses control
ENDIF
;---------------------
IF ( player_has_control )
    RETURN    ; - STOP - /3    player has its control back
ENDIF
;---------------------
    update_player_pos()

    ;Gaincontrol()                ;*ql replaced this by next function
;;;    TransformBack()                ; removed by ReDragon
    Force_control_to_player()
    Berserk_Moral_Transformed.SetValue(0)

IF ( LC_system_active )
    myF_RegisterForWaitTime(Berserk_Config_LooseControlCooldownTimeMin, Berserk_Config_LooseControlCooldownTimeMax, False)
ENDIF
ENDEVENT


;-----------------------------------------------
Bool FUNCTION myF_IsBerserkerArmor(Bool bCombat)  ; internal helper, see OnUpdateGameTime()
;-----------------------------------------------
    actor player = Game.GetPlayer()

IF (bCombat) && !player.IsInCombat()
    Return False
ENDIF
;---------
IF player.HasSpell(BerserkerArmorBeastChange)
    Return TRUE
ENDIF
;---------
IF player.HasMagicEffect(BerserkArmorBeastT)
    Return TRUE
ENDIF
;---------
IF player.HasMagicEffect(BerserkArmorBeastTDanger)
    Return TRUE
ENDIF
;---------
    Return False    ; either 1 of 3 requirements not fulfilled
ENDFUNCTION


;;------------------------------------
;Int FUNCTION myF_TestBerserkerArmor()  ; other approach to give back what is happen with Berserker armor
;;------------------------------------
;    actor player = Game.GetPlayer()
;    int i
;
;IF player.HasSpell(BerserkerArmorBeastChange)
;    i = 1
;ENDIF
;
;IF player.HasMagicEffect(BerserkArmorBeastT)
;    i = i + 10
;ENDIF
;
;IF player.HasMagicEffect(BerserkArmorBeastTDanger)
;    i = i + 20
;ENDIF
;
;    RETURN i    ; 0,1, 10,11, 20,21, 30,31
;ENDFUNCTION


;--------------------
FUNCTION myF_Dispel()  ; internal helper
;--------------------
    player_is_loosing_control = False
    Game.GetPlayer().DispelSpell(Berserk_Spell_Warningspell)
ENDFUNCTION


;---------------------------------
FUNCTION Force_control_to_player()
;---------------------------------
    UnRegisterForUpdateGameTime()
    LC_system_active = False
    myF_Dispel()

    Gaincontrol()            ; Remove any used Imagespace Modifier
;;;    KillScore = 0        ;*ql
;   MoralScore=0        ;no more set as an assignment variable, no need to be reset, because it seems that game stats can be tracked & accumulated without using assignment
ENDFUNCTION


;;-----------------------
;FUNCTION TransformBack()  ;*ql added this function
;;-----------------------
;   Force_control_to_player()
;   ;UnregisterForUpdateGameTime()    ; already included in Force_control_to_player()
;   Berserk_Moral_Transformed.SetValue(0)
;ENDFUNCTION


; -- FUNCTIONs -- (3) + (3) + 3 + 2 + 9 + 6

;------------------------------------------------------
Float FUNCTION RealTimeSecondsToGameTimeHours(Float fs)  ; convert "Real Time Seconds" to "Game Time Hours"
;------------------------------------------------------
   float f = (TimeScale.GetValue() * fs) / 3600.0                                ; f = scaledSeconds, fs = realTime
   RETURN f
ENDFUNCTION
 
 
;-----------------------------------------------------
Float FUNCTION RealTimeSecondsToGameTimeDays(Float fs)  ; convert "Real Time Seconds" To "Game Time Days"
;-----------------------------------------------------
   float f = RealTimeSecondsToGameTimeHours(fs)                                    ; f = scaledSeconds, fs = realTime
   RETURN (f / 24.0)
ENDFUNCTION


;-------------------------------------------------------------------------------------
FUNCTION myF_RegisterForWaitTime(GlobalVariable gMin, GlobalVariable gMax, Bool bMoral)  ; internal helper
;-------------------------------------------------------------------------------------
    float fMin = gMin.GetValue()
    float fMax = gMax.GetValue()
    float f
    
    IF (fMin > fMax)      ; failsafe for random next
        f    = fMax
        fMax = fMin
        fMin = f
    ENDIF

     f = Utility.RandomFloat(RealTimeSecondsToGameTimeHours(fMin), RealTimeSecondsToGameTimeHours(fMax))

;;;    IF ( bKill )
    IF ( bMoral )
;;;        int iMax = Berserk_Config_Killscoretimemultmax.GetValueInt() * 100                            ; iMax = Maxmult
;;;        int i  = ((iMax - 100) * KillScore / Berserk_Config_Killscoremax.GetValueInt()) + 100        ; i = KillMult

        int iMax = Berserk_Config_MoralScoretimemultmax.GetValueInt() * 100                         ; iMax = Maxmult
        int i  = ((iMax - 100) * MoralScore / Berserk_Config_MoralScoremax.GetValueInt()) + 100     ; i = MoralMult

        IF (i > iMax)
            i = iMax
        ENDIF
        f = (i as Float * f) / 100        ; lowest is 20 ingame minutes highest is 160 ingame minutes, this sounds fair
    ENDIF

    RegisterForSingleUpdateGameTime(f)
ENDFUNCTION


;##################### Skyrim runs each Script only once at a time, internal calls and edits will not break this
;### ThreadControl #############################################################################################
;##################### read/write to script's own vars is atomic

  Int mutex_control_status_turn   = 0
  Int mutex_control_status_number = 0

;--------------------
FUNCTION mutex_Wait()  ; mutex_control_status_wait()
;--------------------
  int i = mutex_control_status_number                                            ; i = local_number
  mutex_control_status_number+= 1            ; increased again and again !!!

  WHILE (i != mutex_control_status_turn)
    Utility.Wait(0.1)
  ENDWHILE
ENDFUNCTION

;-------------------
FUNCTION mutex_Add()  ; mutex_control_status_signal()
;-------------------
  mutex_control_status_turn+= 1                ; increased again and again !!!
ENDFUNCTION


;##############
;### Player #############################################################################################
;############## 9

;---------------------
FUNCTION Gaincontrol()  ; Player Gain Control
;---------------------
;;    debug.messagebox("controlgain is started")
;;    debug.messagebox(player_has_control)

    mutex_Wait()                ; THREADsafe ON

IF ( player_has_control )
    mutex_Add()
    RETURN    ; - STOP -    we can only gain controls once
ENDIF
;---------------------
    UnRegisterForUpdate()

; ==
    actor player = Game.GetPlayer()
    player.StopTranslation()            ; just to be sure
    player.MoveTo(BerserkerRef)
    player.SetAngle(0.0, 0.0, 0.0)

    ;Debug.SetGodMode(False)
    Game.SetCameraTarget(player)
    player.SetActorValue("Invisibility", Invisibility_originalvalue)
    player.SetAlpha(1.0)

; ==
    PlatRef.DisableNoWait()
    PlatRef.Delete()
    PlatRef = None

; ==
;;;    int i = Berserk_Config_LooseControlDeathtype.GetValueInt()                    ; i = deathtype
;;;    IF (i == 0)
        player.SetGhost(False)
;;;    ENDIF

    myF_AdjustHealth(player, BerserkerRef.GetActorValue("health"))

; ==
    Game.SetPlayerAiDriven(False)
    player_has_control = TRUE

; ==
    BerserkerAlias.Clear()        
    BerserkerRef.DisableNoWait()
    BerserkerRef.Delete()
    BerserkerRef = None
;  (MTE_Quest_Follower_System as MTE_Quest_Follower_System_Script).Update_LC_playerreplacement(None)  ;leftover code from MTEO for follower system, not needed here

;;    debug.messagebox("controlgain is done")
    mutex_Add()                    ; THREADsafe OFF
; ==
    IllusionBlueMassiveImod.Apply()

; *** ql added
    player.PlayIdle(BleedOutStart)
    Utility.Wait(1.5)
    player.PlayIdle(BleedOutStop)
    MEValueDefiner.SetValue(1)                        ;set the value to activate damage attributes and debuffs
    BerserkerLostControlAfterEffects.Cast(player)
    Initialise()
; ***
ENDFUNCTION


;----------------------------------------------------------------------
FUNCTION player_replacement_was_killed(Actor targetRef, Actor akKiller)  ; external called by Alias script, without Control
;----------------------------------------------------------------------
;;    debug.messagebox(player_has_control)
;;    debug.messagebox(BerserkerRef)
;;    debug.messagebox(targetRef)            ; the_killed_replacement

IF ( !BerserkerRef )
    RETURN    ; - STOP -    just ignore it, None should not die
ENDIF
;---------------------
IF (targetRef == BerserkerRef)
ELSE
    RETURN    ; - STOP -   targetRef != BerserkerRef; just ignore it, its the wrong replacement, maybe an older one not deleted yet,
ENDIF                    ; or something spawned by an external script, at least this should never become True
;---------------------
    mutex_Wait()                ; THREADsafe ON

IF ( player_has_control )
    mutex_Add()
    RETURN    ; - STOP -    just ignore it, the player has the controls
ENDIF
;---------------------
    UnRegisterForUpdate()

; ==
    actor player = Game.GetPlayer()
    player.StopTranslation()            ; just to be sure
    player.MoveTo(BerserkerRef)
    player.SetAngle(0.0, 0.0, 0.0)

    ;Debug.SetGodMode(False)
    Game.SetCameraTarget(player)
    player.SetActorValue("Invisibility", Invisibility_originalvalue)
    player.SetAlpha(1.0)

; ==
    PlatRef.DisableNoWait()
    PlatRef.Delete()
    PlatRef = None

; ==
    int i = Berserk_Config_LooseControlDeathtype.GetValueInt()                    ; i = deathtype
    IF (i == 0)
        player.SetGhost(False)
        player.Kill(akKiller)
    ENDIF

; ==
    Game.SetPlayerAiDriven(False)
    player_has_control = TRUE

; ==
    BerserkerAlias.Clear()        
    BerserkerRef.DisableNoWait()
    BerserkerRef.Delete()
    BerserkerRef = None
;  (MTE_Quest_Follower_System as MTE_Quest_Follower_System_Script).Update_LC_playerreplacement(None)  ;leftover code from MTEO for follower system, not needed here

    mutex_Add()                    ; THREADsafe OFF
; ==
    IF (i == 1)
        wake_up_in_cave(player)
    ENDIF
ENDFUNCTION


;-------------------------------------
FUNCTION wake_up_in_cave(Actor player)
;-------------------------------------
  ;Debug.SendAnimationEvent(player, "BreviMoonlightTalesRestS1")

;Todo some eye candy anim
    FadeToBlackImod.Apply()                               ; >> 1
    Utility.Wait(2.1)
    FadeToBlackImod.PopTo(FadeToBlackHoldImod)            ; -> 2

    myF_MoveToSecurePlace(player)
    myF_AdjustHealth(player, 50.0)    ; heal you up to 50 health

    Utility.Wait(0.5)
    player.SetGhost(False)
    player = None

    FadeToBlackHoldImod.PopTo(FadeToBlackBackImod)        ; -> 3
    Utility.Wait(3.0)

    FadeToBlackBackImod.Remove()                        ; << 3
    FadeToBlackHoldImod.Remove()                        ; << 2
    FadeToBlackImod.Remove()                            ; << 1

; *** ql added
    MEValueDefiner.SetValue(1)        ;set the value to activate damage attributes and debuffs
    BerserkerLostControlAfterEffects.Cast(player)
; ***
ENDFUNCTION


;-------------------------------------------
FUNCTION myF_MoveToSecurePlace(Actor player)  ; internal helper
;-------------------------------------------
    int i = Utility.RandomInt(0, Berserk_List_secure_caves.GetSize() - 1)
    formlist myList = Berserk_List_secure_caves.GetAt(i) as Formlist    ; get a random formlist entry from a formlist
    objectReference oRef                                                ; oRef = TargetMarker

    IF ( myList )
        oRef = myList.GetAt(0) as ObjectReference       ; get the Berserkermarker which is the first object in the cavedata
;;    ELSE
;;        Debug.Trace(" Formlist not found! " +self)
    ENDIF

    IF ( oRef )
        player.MoveTo(oRef)                                ; move player to target marker
        player.SetAngle(0.0, 0.0, 0.0)                    ; adjust angles
;;    ELSE
;;        Debug.Trace(" BersekerMarker is invalid! " +self)
    ENDIF
ENDFUNCTION


;-----------------------------------------------
FUNCTION myF_AdjustHealth(Actor player, Float f)  ; internal helper
;-----------------------------------------------                
    f = player.GetActorValue("health") - f

IF (f > 0)
    player.DamageActorValue("health", f)
    RETURN    ; - STOP -
ENDIF
;---------------------
IF (f == 0)
    RETURN    ; - STOP -    just in case
ENDIF
;---------------------
    player.RestoreActorValue("health", -f)
ENDFUNCTION


;------------------------------
FUNCTION update_player_health() ; So the player can monitor his body's health.
;------------------------------
IF ( singlerun_updating_health )
    RETURN    ; - STOP -
ENDIF
;---------------------
    singlerun_updating_health = TRUE
    mutex_Wait()

IF ( player_has_control )
    mutex_Add()
    RETURN    ; - STOP -    just ignore it, the player has the controls
ENDIF
;--------------------- update health while Control is Lost
    myF_AdjustHealth(Game.GetPlayer(), BerserkerRef.GetActorValue("health"))
    mutex_Add()

    singlerun_updating_health = False
ENDFUNCTION


;---------------------------
FUNCTION update_player_pos()  ; So the player can monitor his body even If it's running away. :)
;---------------------------
IF ( singlerun_updating_pos )
    RETURN    ; - STOP -    
ENDIF
;---------------------
    singlerun_updating_pos = TRUE
    mutex_Wait()

IF ( player_has_control )
    mutex_Add()
    RETURN    ; - STOP -    just ignore it, the player has the controls
ENDIF
;--------------------- update Position while Control is Lost
    myF_Update()
    mutex_Add()

    singlerun_updating_pos = False
ENDFUNCTION


;--------------------
FUNCTION myF_Update()  ; internal helper, >>> The code of this function should be a bit more optimized <<<
;--------------------
; Cell.size == 4096 < 10000/sqrt(2) so cell would differ, too.
; Rasikko asked what does it mean? No idea..

    actor player  = Game.GetPlayer()
    worldSpace ws = player.GetWorldSpace()
    bool bOK
    cell c

    IF ( BerserkerRef )
        c = BerserkerRef.GetParentCell()
        bOK = (!c) || (c != player.GetParentCell())
    ELSE
        bOK = False
    ENDIF

IF (ws) && (ws == BerserkerRef.GetWorldSpace()) && (player.GetDistance(BerserkerRef as ObjectReference) < 10000)
    IF (bOK) || (player.GetDistance(BerserkerRef) > 500)
        myF_Translate(BerserkerRef, 2000.0, False)
    ENDIF
    RETURN    ; - STOP -    we are in the same worldspace wuhu, using translate to.
ENDIF
;---------------------
IF (ws) || (bOK)
    ; Berserker left actual cell, moving Player.
    ; either we are inside an interior cell or in diffent worldspaces, using moveto

    player.StopTranslation()        ; just to be sure

    IF ( PlatRef )
        PlatRef.DisableNoWait()
        PlatRef.Delete()
        PlatRef = None
    ENDIF

    player.MoveTo(BerserkerRef)
    PlatRef = player.PlaceAtMe(DwePlatMid01, 1, TRUE, TRUE)        ; place a new plate

    myF_Translate(player, 1000.0, TRUE)
    PlatRef.EnableNoWait()
ENDIF
ENDFUNCTION


;---------------------------------------------------------
FUNCTION myF_Translate(Actor aRef, Float fSpeed, Bool bOK)  ; internal helper to shrink parent function stack size
;---------------------------------------------------------
; speed shouldn't be too big or Skyrim could crash because of loading to much Cells in short time,
; 2000 was ok for Flyable Dragon Races 3 so I will use it.
; Berserker has left loaded space or got too far away from the Player, moving Player.

    float fx = aRef.GetPositionX()
    float fy = aRef.GetPositionY()
    float fz = aRef.GetPositionZ() + 3300.0

    float aX = aRef.GetAngleX()
    float aY = aRef.GetAngleY()
    float aZ = aRef.GetAngleZ()

IF ( bOK )                                        ; player up into the sky
    PlatRef.SetPosition(fx, fy, fz - 300.0)
    PlatRef.SetAngle(0.0, 0.0, 0.0)
    aRef.TranslateTo(fx,fy,fz, aX,aY,aZ, fSpeed)        ; 1000

ELSE                                            ; berserker up into the sky
    aRef.TranslateTo(fx,fy,fz, aX,aY,aZ, fSpeed)        ; 2000
    PlatRef.SetPosition(fx, fy, fz - 300.0)
    PlatRef.SetAngle(0.0, 0.0, 0.0)
ENDIF
ENDFUNCTION


;;-----------------------------------------
;FUNCTION player_has_killed(Bool bHumanoid)  ; OBSOLETE, has killed on something
;;-----------------------------------------
;    float f = GameDaysPassed.GetValue()
;
;    IF (killscorebuffResetTime < f)
;        killscorebuff = 0
;    ENDIF
;
;    killscorebuffResetTime = f + RTS_ToGameTimeDays(45.0)
;
;    IF ( bHumanoid )                                                            ; bHumanoid =  was_humanoid
;        KillScore    += Berserk_Config_Killscorebase.GetValueInt() + killscorebuff
;        killscorebuff+= Berserk_Config_Killscoremodifier.GetValueInt()
;    ENDIF
;ENDFUNCTION


;###############
;### Control #############################################################################################
;############### 6

;----------------------------
;FUNCTION Loose_Control_Roll()
FUNCTION Moral_counting()
;------------------------
    int[] a = new Int[24]        ; query stats storage

    int i
; https://www.creationkit.com/index.php?title=QueryStat_-_Game

    i =  Game.QueryStat("Werewolf Transformations")
    a[0] = i * Berserk_Moral_Config_GSWerewolf.GetValueInt()         ; int WerewolfTransforms

     i = Game.QueryStat("Necks Bitten")
    a[1] = i * Berserk_Moral_Config_GSNeckBit.GetValueInt()          ; int NecksBitten

     i = Game.QueryStat("Bribes")
    a[2] = i * Berserk_Moral_Config_GSBribe.GetValueInt()            ; int Bribes

     i = Game.QueryStat("Intimidations")
    a[3] = i * Berserk_Moral_Config_GSIntimidation.GetValueInt()     ; int Intimidations

     i = Game.QueryStat("Thieves' Guild Quests Completed")
    a[4] = i * Berserk_Moral_Config_GSTGQuest.GetValueInt()          ; int TGQuests

     i = Game.QueryStat("The Dark Brotherhood Quests Completed")
    a[5] = i * Berserk_Moral_Config_GSDBQuest.GetValueInt()          ; int DBQuests

     i = Game.QueryStat("Daedric Quests Completed")
    a[6] = i * Berserk_Moral_Config_GSDaedricQuest.GetValueInt()     ; int DaedricQuests

     i = Game.QueryStat("Dragon Souls Collected")
    a[7] = -i * Berserk_Moral_Config_GSDragonSoul.GetValueInt()       ; int DragonSouls, has minus value

     i = Game.QueryStat("Shouts Learned")
    a[8] = -i * Berserk_Moral_Config_GSShoutLearn.GetValueInt()       ; int ShoutsLearned, has minus value

     i = Game.QueryStat("Shouts Mastered")
    a[9] = -i * Berserk_Moral_Config_GSShoutMaster.GetValueInt()      ; int ShoutsMastered, has minus value

     i = Game.QueryStat("People Killed")
    a[10] = i * Berserk_Moral_Config_GSPeopleKill.GetValueInt()      ; int PeopleKilled

     i = Game.QueryStat("Animals Killed")
    a[11] = i * Berserk_Moral_Config_GSAnimalKill.GetValueInt()      ; int AnimalsKilled

     i = Game.QueryStat("Undead Killed")
    a[12] = -i * Berserk_Moral_Config_GSUndeadKill.GetValueInt()      ; int UndeadKilled, has minus value

     i = Game.QueryStat("Daedra Killed")
    a[13] = -i * Berserk_Moral_Config_GSDaedraKill.GetValueInt()      ; int DaedraKilled, has minus value

     i = Game.QueryStat("Bunnies Slaughtered")
    a[14] = i * Berserk_Moral_Config_GSBunnyKill.GetValueInt()       ; int BunniesKilled

     i = Game.QueryStat("Items Pickpocketed")
    a[15] = i * Berserk_Moral_Config_GSItemPickpocket.GetValueInt()  ; int ItemsPickpocketed

     i = Game.QueryStat("Times Jailed")
    a[16] = i * Berserk_Moral_Config_GSTimeJail.GetValueInt()        ; int TimesJailed

     i = Game.QueryStat("Jail Escapes")
    a[17] = i * Berserk_Moral_Config_GSJailEscape.GetValueInt()      ; int JailEscapes

     i = Game.QueryStat("Items Stolen")
    a[18] = i * Berserk_Moral_Config_GSItemSteal.GetValueInt()       ; int ItemsStolen

     i = Game.QueryStat("Assaults")
    a[19] = i * Berserk_Moral_Config_GSAssault.GetValueInt()         ; int Assaults

     i = Game.QueryStat("Murders")
    a[20] = i * Berserk_Moral_Config_GSMurder.GetValueInt()          ; int Murders

     i = Game.QueryStat("Horses Stolen")
    a[21] = i * Berserk_Moral_Config_GSHorseSteal.GetValueInt()      ; int HorsesStolen

     i = Game.QueryStat("Trespasses")
    a[22] = i * Berserk_Moral_Config_GSTrespass.GetValueInt()        ; int Tresspasses

;--------
     i = Game.QueryStat("Total Lifetime Bounty")
    float f = Berserk_Moral_Config_GSTotalBounty.GetValue()          ; f = BountyMoralMultiplier

    IF     (i < Berserk_Moral_Config_BountyStage1.GetValueInt())
        f = 1.0        ; no multiplier

    ELSEIF (i < Berserk_Moral_Config_BountyStage2.GetValueInt())
        ; keep it

    ELSEIF (i < Berserk_Moral_Config_BountyStage3.GetValueInt())
        f *= 2

    ELSEIF (i < Berserk_Moral_Config_BountyStage4.GetValueInt())
        f *= 3

    ELSEIF (i < Berserk_Moral_Config_BountyStage5.GetValueInt())
        f *= 4

    ELSEIF (i < Berserk_Moral_Config_BountyStage6.GetValueInt())
        f *= 5

    ELSEIF (i < Berserk_Moral_Config_BountyStage7.GetValueInt())
        f *= 6

    ELSEIF (i < Berserk_Moral_Config_BountyStage8.GetValueInt())
        f *= 7

    ELSEIF (i < Berserk_Moral_Config_BountyStage9.GetValueInt())
        f *= 8

    ELSEIF (i < Berserk_Moral_Config_BountyStage10.GetValueInt())
        f *= 9

;;;    ELSEIF (i >= Berserk_Moral_Config_BountyStage10.GetValueInt())
    ELSE
        f *= 10
    ENDIF

    a[23] = i * (f as Int)        ; ### Total Bounty ###

;--------
;;;    float MoralityIncrements    ; contains accumulated points from all used game statistics
;*; float MoralScore            ;*ql, contains accumulated points from all used game statistics

    i = 0
    WHILE (i < a.Length)
        MoralScore += a[i]
        i = i + 1
    ENDWHILE

;;;    Loose_Control_Roll()        ; *ql, removed code here, see next function

; *** ql
    i = Berserk_Config_MoralScoremax.GetValueInt()        ; max default is 500
    IF  (MoralScore >= i)
         MoralScore = i            ; set to max value of MoralScore
    ENDIF
; ***
ENDFUNCTION


;----------------------------
FUNCTION Loose_Control_Roll()
;----------------------------
IF myF_NoControl()
    player_is_loosing_control = TRUE

    IF ( LC_system_active )
        float f = Utility.RandomFloat(RealTimeSecondsToGameTimeHours(30), RealTimeSecondsToGameTimeHours(60))
        RegisterForSingleUpdateGameTime(f)
    ENDIF

    IF (Berserk_Config_Moral_Warningtime.GetValue() == 1)
        Berserk_Spell_Warningspell.Cast(Game.GetPlayer())    ; apply a short visual warning
    ENDIF

    RETURN    ; - STOP -
ENDIF
;---------------------
    IF ( LC_system_active )
        myF_RegisterForWaitTime(Berserk_Config_LooseControlCooldownTimeMin, Berserk_Config_LooseControlCooldownTimeMax, False)
    ENDIF

; *** ql
;;;    KillScore = KillScore * 9 / 10            ; see  also Trigger_control_loss()
;    MoralScore = MoralScore * 9 / 10
; ***
ENDFUNCTION


;--------------------------------------------
;Bool FUNCTION myF_NoControl(Float MoralScore)  ; internal helper
Bool FUNCTION myF_NoControl()
;----------------------------
    float r = Utility.RandomInt(1, 100) as Float

;;;    Float chance=(BaseWeight*Berserk_loose_control_base_chance + MoralWeight*Berserk_moral_chance)/(BaseWeight+MoralWeight)
;    -------------------------------------------------------------------------------------------------------------------------

    int iB = Berserk_Config_LooseControlBaseWeight.GetValueInt()            ; iB = BaseWeight
    int iM = Berserk_Config_LooseControlMoralWeight.GetValueInt()           ; iM = MoralWeight

    IF (iB == 0) && (iM == 0)  
        iB = 1                        ; **
    ENDIF

    float f = (iB as Float) * Berserk_Config_LooseControlBaseChance.GetValue()
;--------
    float fMC = Berserk_Config_MoralScoremax.GetValue()        ; as a max value for MoralScore, default is 500
    fMC = MoralScore / fMC * 100.0                               ; Berserk_moral_chance
    IF (fMC >= 100)
       fMC = 100
    ENDIF
    f = f + (iM as Float) * fMC            ; fMC = MoralChance
;--------
    f = f / (iB + iM) as Float        ; ** we don't want to divide by 0 here
;--------
    RETURN (r <= f)        ; RandomChance <= chance
ENDFUNCTION


;------------------------------
FUNCTION Trigger_control_loss()  ; Actually Trigger Control Loss
;------------------------------
    Loosecontrol()

    IF ( LC_system_active )
        myF_RegisterForWaitTime(Berserk_Config_LooseControlBaseTimeMin, Berserk_Config_LooseControlBaseTimeMax, TRUE)
    ENDIF        

; *** ql
;;;    KillScore = KillScore * 9 / 10
; ***
ENDFUNCTION


;----------------------
FUNCTION Loosecontrol()
;----------------------
;;    debug.messagebox("loosing Controls")
    mutex_Wait()

IF ( !player_has_control )        ; we can only loose controls once
    mutex_Add()
    RETURN    ; - STOP -
ENDIF
;---------------------
    actor player = Game.GetPlayer()

    IF player.IsSprinting()
        Debug.SendAnimationEvent(player, "SprintStop")
    ENDIF
    ;utility.wait(5);waits not necessarary, as we don't run it directly while transforming, like the original mod

    Game.ForceThirdPerson()            ; just to be sure
    Game.SetPlayerAiDriven(TRUE)    ; I don't want to disable the health bar as disableplayercontrols does.
    ;Game.disableplayercontrols(abLooking=False)    
    ;Debug.SetGodMode(True)
    player.SetGhost()

    BerserkerRef = myF_PlaceBerserker(player)        ; ###

    float fx = player.GetPositionX()
    float fy = player.GetPositionY()
    float fz = player.GetPositionZ()

    BerserkerRef.SetPosition(fx, fy, fz)
    BerserkerRef.Enable()

    Invisibility_originalvalue = player.GetBaseActorValue("Invisibility")
    player.SetActorValue("Invisibility", 100)
    player.SetAlpha(0.0)
    Utility.Wait(0.2)        ; wait a small bit so spells can apply to the replacement

; *** ql added
    IF player.HasMagicEffect(BerserkArmorBeastT)
;###       (BerserkArmorBeastT as SCRBerserkArmorB).RevertForm(player)

    ELSEIF player.HasMagicEffect(BerserkArmorBeastTDanger)
;###       (BerserkArmorBeastTDanger as SCRBerserkArmorB).RevertForm(player)
    ENDIF

    utility.wait(0.1)        ;wait a small bit so revert form can be finished completely

    IF (MEValueDefiner.GetValue() == 1)        ;get the value for activation of damage attributes and debuffs
       MEValueDefiner.SetValue(0)            ;set the value to deactivate damage attributes and debuffs
    ENDIF

    copy_player_stats_to_replacement()                ; ###  *** not added ***
    copy_player_gears_to_replacement(player)

    BerserkerRef.EquipItem(ArmorBerserkerWBoots2,    true, true)
    BerserkerRef.EquipItem(ArmorBerserkerWCuirass2,  true, true)
    BerserkerRef.EquipItem(ArmorBerserkerGauntlets2, true, true)
    BerserkerRef.EquipItem(ArmorBerserkWHelmet,      true, true)

    BerserkerRef.AddPerk(AllowShoutingPerk)
    BerserkerRef.AddPerk(Berserk_NPC_FallDmg)
; ***

    BerserkerAlias.Clear()
    BerserkerAlias.ForceRefTo(BerserkerRef)        ; to attach scripts to the berserker
;    (MTE_Quest_Follower_System as MTE_Quest_Follower_System_Script).Update_LC_playerreplacement(BerserkerRef)  ;leftover code from MTEO for follower system, not needed here

;For some reason SetAngle() doesnt work for X angle so I'll use TranslateTo to set this angle
    float aX = player.GetAngleX()
    float aY = player.GetAngleY()
    float aZ = player.GetAngleZ()

    fx = player.GetPositionX()
    fy = player.GetPositionY()
    fz = player.GetPositionZ()

    BerserkerRef.TranslateTo(fx,fy,fz, aX,aY,aZ, 300.0)    

    Game.SetCameraTarget(BerserkerRef)    ; MUST be runned on an enabled Object
    Game.ForceFirstPerson()             ; toggle to first person. Force the game to update the camera when we..
    Utility.Wait(0.1)
    Game.ForceThirdPerson()             ; force third person

    IF ( PlatRef )
        PlatRef.Delete()
        PlatRef = None
    ENDIF

    PlatRef = player.PlaceAtMe(DwePlatMid01, 1, TRUE, TRUE)
    PlatRef.SetPosition(fx, fy, fz + 3000.0)
    PlatRef.SetAngle(0.0, 0.0, 0.0)
    PlatRef.Enable()

    aX = player.GetAngleX()
    aY = player.GetAngleY()
    aZ = player.GetAngleZ()

    player.TranslateTo(fx, fy, fz + 3300.0, aX, aY, aZ, 1000.0, 0.0)

    player_has_control = False
    RegisterForSingleUpdate(3.0)

;    utility.wait(5.0)    ; just don't forget to overwrite still active translations (which is quiet unlikly ) in Gaincontrol()
;;    debug.messagebox("loosing Controls done")

    mutex_Add()

; *** ql added
    Berserk_Moral_Transformed.SetValue(1)
; ***
ENDFUNCTION


;----------------------------------------------
Actor FUNCTION myF_PlaceBerserker(Actor player)  ; internal helper (non array version)
;----------------------------------------------
    bool bFemale = (player.GetActorBase().GetSex() == 1)
    int        i = player.GetEquippedItemType(1)        ; right hand
    actorBase AB

;-----------------------
IF (i == 0) || (i == 11)        ; unarmed /or/ torch
    IF (i == 11)
        weapon w = player.GetEquippedWeapon(False)            ; torch in right hand by default
        player.UnEquipItem(w as Form, False, TRUE)            ; unequip it firstly
    ENDIF
    IF ( bFemale )
                    AB = Berserk_Player_Loose_Controls_Unarmed_F        ; 0        
    ELSE
                    AB = Berserk_Player_Loose_Controls_Unarmed_M
    ENDIF
;---------------------------
ELSEIF (i == 7) || (i == 12)
    IF ( bFemale )
                    AB = Berserk_Player_Loose_Controls_Ranger_F         ; 7, 12    
    ELSE
                    AB = Berserk_Player_Loose_Controls_Ranger_M
    ENDIF
;--------------
ELSEIF (i == 8)
    IF ( bFemale )
                    AB = Berserk_Player_Loose_Controls_Spellsword_F     ; 8  staff    
    ELSE
                    AB = Berserk_Player_Loose_Controls_Spellsword_M
    ENDIF
;--------------
ELSEIF (i == 9)
    IF ( bFemale )
                    AB = Berserk_Player_Loose_Controls_Mage_F           ; 9  spell    
    ELSE
                    AB = Berserk_Player_Loose_Controls_Mage_M
    ENDIF
;--------------------------
ELSEIF (i >= 1) && (i <= 6)
    i = player.GetEquippedItemType(0)                    ; left hand
    IF (i == 8) || (i == 9)
        IF ( bFemale )
                    AB = Berserk_Player_Loose_Controls_Spellsword_F     ;
        ELSE
                    AB = Berserk_Player_Loose_Controls_Spellsword_M
        ENDIF
    ELSE
        IF ( bFemale )
                    AB = Berserk_Player_Loose_Controls_Melee_F          ; 1, 2, 3, 4, 5, 6
        ELSE
                    AB = Berserk_Player_Loose_Controls_Melee_M
        ENDIF
    ENDIF
ENDIF

IF ( !AB )
    RETURN None
ENDIF
;---------
    RETURN player.PlaceAtMe(AB, 1, abForcePersist=True, abInitiallyDisabled=True) as Actor
ENDFUNCTION

;;----------------------------------------------
;Actor FUNCTION myF_PlaceBerserker(Actor player)  ; internal helper (array version) ; not used for now, i prefer the non array version
;;----------------------------------------------
;    int i = player.GetEquippedItemType(1)            ; right hand
;    int n = -1

;    IF     (i == 0)
;                                    n = 0        ; Berserk_Player_Loose_Controls_Unarmed_M       0 -- 5  Berserk_Player_Loose_Controls_Unarmed_F
;    ELSEIF (i == 8)
;                                    n = 4        ; Berserk_Player_Loose_Controls_Spellsword_M    4 -- 9 Berserk_Player_Loose_Controls_Spellsword_F
;    ELSEIF (i == 9)
;                                    n = 3        ; Berserk_Player_Loose_Controls_Mage_M          3 -- 8 Berserk_Player_Loose_Controls_Mage_F
;    ELSEIF (i == 7) || (i == 12)
;                                    n = 2        ; Berserk_Player_Loose_Controls_Ranger_M        2 -- 7  Berserk_Player_Loose_Controls_Ranger_F
;    ELSEIF (i >= 1) && (i <= 6)
;        i = player.GetEquippedItemType(0)            ; left hand
;        IF (i == 8) || (i == 9)
;                                    n = 4        ; Berserk_Player_Loose_Controls_Spellsword_M    4 -- 9 Berserk_Player_Loose_Controls_Spellsword_F
;        ELSE
;                                    n = 1        ; Berserk_Player_Loose_Controls_Melee_M         1 -- 6  Berserk_Player_Loose_Controls_Melee_F
;        ENDIF
;    ENDIF

;IF (n < 0)
;    RETURN None        ; What is about Torch?
;ENDIF
;;---------
;    IF (player.GetActorBase().GetSex() == 1)
;        n = n + 6            ; female actorbase position
;    ENDIF

;    RETURN player.PlaceAtMe(Berserk_Player_Loose_Controls_Array[n], 1, abForcePersist=True, abInitiallyDisabled=True) as Actor
;ENDFUNCTION


;------------------------------------------
FUNCTION copy_player_stats_to_replacement()  ; internal helper, copy Player stats to Loose Control replacement
;------------------------------------------
IF ( !BerserkerRef )
    RETURN    ; - STOP -
ENDIF
;---------------------
string[] a = new string[11]                ; a = primevalues + secvalues
    a[0] = "Health"
    a[1] = "Stamina"
    a[2] = "Magicka"
    a[3] = "UnarmedDamage"
    a[4] = "DamageResist"
    a[5] = "DiseaseResist"
    a[6] = "PoisonResist"
    a[7] = "FireResist"
    a[8] = "ElectricResist"
    a[9] = "FrostResist"
    a[10]= "MagicResist"

    actor player = Game.GetPlayer()
    float f                                ; f = pval

int i = 0
    WHILE (i < 3) && (BerserkerRef)
        f = player.GetBaseActorValue(a[i])            ; get player base actor value
        BerserkerRef.SetActorValue(a[i], f)

        float fc = player.GetActorValue(a[i])
        player.RestoreActorValue(a[i], 100000)        ; to get the modified maxValue

        f = player.GetActorValue(a[i])                ; get current player max actor value
        player.DamageActorValue(a[i], f - fc)
        BerserkerRef.RestoreActorValue(a[i], 100000)
;        ------------
        float fw = BerserkerRef.GetActorValue(a[i])
        BerserkerRef.ModActorValue(a[i], f - fw)
        BerserkerRef.RestoreActorValue(a[i], 100000)

        fw = BerserkerRef.GetActorValue(a[i])
        BerserkerRef.DamageActorValue(a[i], fw - fc)

        i = i + 1
    ENDWHILE

    WHILE (i < a.Length) && (BerserkerRef)
        f = player.GetActorValue(a[i])               ; get current player actor value
        BerserkerRef.ForceActorValue(a[i], f)        ; force that to the berseker
        i = i + 1
    ENDWHILE
ENDFUNCTION


;--------------------------------------
Form FUNCTION GetWornAmmo(Actor player)     ;*ql, internal helper "copy player gears"
;--------------------------------------
; https://www.creationkit.com/index.php?title=IsEquipped_-_Actor

int i = 0
    WHILE (i < WornAmmoList.GetSize())
        form fm = WornAmmoList.GetAt(i)
        IF player.IsEquipped(fm)
            RETURN fm        ; got what we need
        ENDIF
;        ----------
        i = i + 1
    ENDWHILE
    RETURN None                ; nothing found
ENDFUNCTION


;------------------------------
FUNCTION myF_BerserkerAE(Int i)
;------------------------------
    form fm
    fm = player.GetWornForm(i)                            ; SKSE required !!
    IF (fm as Armor)
        BerserkerRef.AddItem(fm, absilent=true)
        BerserkerRef.EquipItemEx(fm, TRUE, TRUE)        ; SKSE required !!
;;        Debug.MessageBox("...")
    ENDIF
ENDFUNCTION


;------------------------------------------------------
FUNCTION copy_player_gears_to_replacement(Actor player)  ;*ql, copy Player gears to Loose Control replacement
;------------------------------------------------------
IF ( !BerserkerRef )
    RETURN    ; - STOP -    fail earlier
ENDIF
;---------------------
    form fm
    weapon w
    spell sp
    shout sh

; https://www.creationkit.com/index.php?title=GetWornForm_-_Actor
; https://www.creationkit.com/index.php?title=EquipItemEx_-_Actor

    myF_BerserkerAE(0x00000200)
    myF_BerserkerAE(0x00000020)
    myF_BerserkerAE(0x00000040)
;;;
;;###    fm = player.GetWornForm(0x00000200)                ; Shield
;    IF (fm as Armor)
;        BerserkerRef.AddItem(fm, absilent=true)
;;###        BerserkerRef.EquipItemEx(fm, TRUE, TRUE)
;;;        Debug.MessageBox("...")
;    ENDIF
;
;;###    fm = player.GetWornForm(0x00000020)                ; Amulet
;    IF (fm  as Armor)
;        BerserkerRef.AddItem(fm, absilent=TRUE)
;;###        BerserkerRef.EquipItemEx(fm, False, TRUE)
;    ENDIF
;
;;###    fm = player.GetWornForm(0x00000040)                ; Ring
;    IF (fm as Armor)
;        BerserkerRef.AddItem(fm, absilent=TRUE)
;;###        BerserkerRef.EquipItemEx(fm, False, TRUE)
;    ENDIF
;;;

    w = player.GetEquippedWeapon(False)                ; right hand
    IF ( w )
        BerserkerRef.AddItem(w as Form, absilent=TRUE)
        BerserkerRef.EquipItemEx(w as Form, TRUE, TRUE)        ; SKSE version does not lose weapon enchantement.
;##        BerserkerRef.EquipItem(w as Form, TRUE, TRUE)
;;        Debug.MessageBox("...")
    ENDIF

    w = player.GetEquippedWeapon(TRUE)                ; left hand
    IF ( w )
        BerserkerRef.AddItem(w as Form, absilent=TRUE)
        BerserkerRef.EquipItemEx(w as Form, TRUE, TRUE)        ; SKSE version does not lose weapon enchantement.
;##        BerserkerRef.EquipItem(w as Form, TRUE, TRUE)
;;        Debug.MessageBox("...")
    ENDIF

    fm = GetWornAmmo(player)                    ; fm = WornAmmo

IF ( !BerserkerRef )
    RETURN    ; - STOP -    fail earlier
ENDIF
;---------------------
    IF ( fm )                                     ; WornAmmo is valid ammo
;;;        int i = player.GetItemCount(fm)
        BerserkerRef.AddItem(fm, 100, absilent=true); could get count of ammo on player or just give a fixed ammount
        BerserkerRef.EquipItem(fm, TRUE, TRUE)        ; that should last the duration of the berserker status
    ENDIF
;--------
    sp = player.GetEquippedSpell(0)                    ; left hand spell
    IF ( sp )
        BerserkerRef.AddSpell(sp)
        BerserkerRef.EquipSpell(sp, 0)
;;        Debug.MessageBox("...")
    ENDIF

    sp = player.GetEquippedSpell(1)                    ; right hand spell
    IF ( sp )
        BerserkerRef.AddSpell(sp)
        BerserkerRef.EquipSpell(sp, 1)
;;        Debug.MessageBox("...")
    ENDIF

    sp = player.GetEquippedSpell(2)                    ; other Spell, (3 is instant)
    IF ( sp )
        BerserkerRef.AddSpell(sp)
        BerserkerRef.EquipSpell(sp, 2)
;;        Debug.MessageBox("...")
    ENDIF

    sh = player.GetEquippedShout()                    ; pre selected shout
    IF ( sh )
        BerserkerRef.AddShout(sh)
        BerserkerRef.EquipShout(sh)
;;        Debug.MessageBox("...")
    ENDIF
ENDFUNCTION

 

 

Link to comment
Share on other sites

Thanks a lot! :smile:

 

Btw i need to ask to confirm several things.

1. It seems that you merged qlBerserk_PlayerAliasScript into qlBerserk_ReplacementAliasScript. But i couldn't find the function from qlBerserk_PlayerAliasScript inside qlBerserk_ReplacementAliasScript. So, where did it go? I couldn't find any function about adding severe damage spell into the player in other scrips either.

Edit: I think i can simply add it to your new merged script. Yeah, that should work.

 

2. You merged those 3 smaller other scripts into qlBerserk_TransformFinishScript, then where should it attached to?

Previously, they were attached to 3 different magic effects, but now it's merged into a single script, and the last magic effect has different global value than the previous 2 magic effects. How to make it work?

Edit: Nvm. Just a trivial issue. I should be able to fix it now.

 

3. A question regarding this code from qlBerserk_TransformScript:

IF akTarget.IsEquipped(ArmorBerserkerCuirass) && akTarget.IsEquipped(ArmorBerserkerBoots)
    self.Dispel()
    RETURN    ; - STOP - /1    failsafe, player is not the target
ENDIF 

How do it check if the player is not the target? All i can understand is that it checks whether the target is wearing both armors and if so, then dispel the spell. I'm not sure that's what we want, if that's really the case.

 

4. A question regarding these codes from qlBerserk_QuestScript (under Loosecontrol() function):

; *** ql added
    IF player.HasMagicEffect(BerserkArmorBeastT)
;###       (BerserkArmorBeastT as SCRBerserkArmorB).RevertForm(player)

    ELSEIF player.HasMagicEffect(BerserkArmorBeastTDanger)
;###       (BerserkArmorBeastTDanger as SCRBerserkArmorB).RevertForm(player)
    ENDIF 

Note: "SCRBerserkArmorB" has been renamed into "qlBerserk_TransformScript", ie. transformation script

Why did you comment it out? Is there something wrong or have them already done by other codes?

I added these codes to make the player revert back from transformed state if he/she's losing control. Did i do something wrong in this part?

Edited by qwertypol012
Link to comment
Share on other sites

Answers:

 

1) It seems that you merged qlBerserk_PlayerAliasScript into qlBerserk_ReplacementAliasScript.

No, no .. I renamed this script back (to go along with name convention) because it is not really a PlayerAlias script.

 

2) you merged 3 smaller scripts into qlBerserk_TransformFinishScript

Cannot see any problem here, you have two properties "MEValueDefiner" and "EffectValue", which can be prefilled by CK as you need.

 

3) about qlBerserk_TransformScript I forgot an "ELSE" here, you asked: "How do it check if the player is not the target?"

EVENT OnEffectStart(Actor akTarget, Actor akCaster)
IF (akTarget == Game.GetPlayer())
ELSE
    self.Dispel()
    RETURN    ; - STOP - /0    failsafe, player is not the target
ENDIF
;--------------------- from here down to endevent: akTarget == Game.GetPlayer()
IF akTarget.IsEquipped(ArmorBerserkerCuirass) && akTarget.IsEquipped(ArmorBerserkerBoots)
ELSE               ; forgotten last time !!!
    self.Dispel()
    RETURN    ; - STOP - /1    failsafe, player does not have equipped berserker armor
ENDIF
;---------------------

4. regarding qlBerserk_QuestScript (under Loosecontrol() function):

Note: "SCRBerserkArmorB" has been renamed into "qlBerserk_TransformScript", ie. transformation script

Why did you comment it out? Is there something wrong or have them already done by other codes?

I added these codes to make the player revert back from transformed state if he/she's losing control. Did i do something wrong in this part?

 

As I wrote at the begin of my preview posting, too many scripts and its not so easy to follow, next should be done here.

; *** ql added
IF player.HasMagicEffect(BerserkArmorBeastT)
;### (BerserkArmorBeastT as SCRBerserkArmorB).RevertForm(player)
       (BerserkArmorBeastT as qlBerserk_TransformScript).RevertForm(player)

ELSEIF player.HasMagicEffect(BerserkArmorBeastTDanger)
;### (BerserkArmorBeastTDanger as SCRBerserkArmorB).RevertForm(player)
      (BerserkArmorBeastTDanger as qlBerserk_TransformScript).RevertForm(player)
ENDIF 
Edited by ReDragon2013
Link to comment
Share on other sites

  • Recently Browsing   0 members

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