qwertypol012 Posted January 10, 2019 Share Posted January 10, 2019 Hello there, thanks for taking a look at my help request here :smile: I'm currently trying to make a script which contains a custom conditional system which will be used by a particular quest script. The quest script is about a transformation feature which transform the player into something, and that transformation effect is triggered when some conditions are met. Those conditions are contained inside something i called "custom conditional system" above. To make things clearer and easy to read, i'll try to arrange it better here. TransformationTransform the player into "lost control" stateLost control state replaces the player with a set of prepared NPCs which will be choosen depend on what weapons the player currently wield before being transformedThe replacer NPC is driven by an AI to attack and kill everything near itThe transformation effect has a calculated duration which is calculated from something called "killcount". Killcount checks how many kills the replacer NPC made after being transformed. The more it kills, the longer the duration.Trigger for this whole transformation effect depends on calculations contained in the Transform Condition SystemTransform Condition SystemHas something i call "Condition meter" which has ranged values from 0 to 1000Condition meter 1000 means 100% chance for the transformation effect to happen. Condition meter 0 means 0% chance to transform.Condition meter will be filled or be emptied based on some game statistics' values. Some game statistics increase the condition meter, but some others reduce the meter.Each game statistic is given a base value to add or subtract the condition meter.Whenever the player do something which contribute to a particular game statistic, the base value of that game statistic will be contributed into the condition meter (either add it or subtract it).The amount of condition meter will then determine the chance for the player to transform into lost control state.I already have the base script for Transformation, but still currently trying to make Transform Condition System. I'm not sure whether it has to be written into its own script or can be included within Transformation script. If it has to be made separately, then do i need to add "extends Quest Conditional" or simply "extends Quest" (i'm still confused on the usage of Conditional keyword in scriptname line). Also, do i need to extends the script into Quest script or instead into some other script? It will also be cool if someone would help me to write the base for Transform Condition System script :teehee: I'm still new to papyrus scripting, so any guides will be appreciated. Thanks in advance :smile: Link to comment Share on other sites More sharing options...
qwertypol012 Posted January 13, 2019 Author Share Posted January 13, 2019 It turns out that i have managed to solve most of them. There are still some works need to be done though, such as 1) making sure that Transformation only works when the player wears specific armor AND only in combat with health below xx% (configurable), 2) making codes to copy player's weapons into the replacer NPC's inventory, 3) adding "area fear effect" around the replacer NPC so that any innocent/weak NPCs will run away instead of trying to fight the replacer NPC. So, i'll still accept any helps for these areas. Oh, i also want to notify that the scripts i'm using are based on Moonlight Tales Essentials Overhauled (MTEO) by ubuntufreakdragon. He gave me permission to use his scrips as long as i credited him. So all credits go to him since he has done most of the work :smile:What i did was simply replacing his "Lunar Transformation" system with Transform Condition System (in which i renamed it into Morality System), replacing "feed" mechanism into "kill" mechanism (since the replacer NPCs are humanoids, not werewolves), replacing all instances about werewolf NPC replacer into my NPC replacer (named "Berserker"), removing any codes related to skin changer/updater, renaming properties and variables to suit my needs, and some minor things i couldn't remember. I also decided to give a name to Transformation mechanism with Lost Control (just like what MTEO uses). I'll post my WIP script here so that people will get a better idea on what i'm working on (a bit long, but can't be helped lol)Transformation (a.k.a. Lost Control) script (contains Morality System which is now built in into it): Scriptname Berserk_Loose_Control_Script extends Quest Conditional ; -- PROPERTIES -- Quest Property Berserk_Quest_Morality Auto ;as a factor for loose control roll, referenced for morality, name can be changed to suit better GlobalVariable Property TimeScale Auto GlobalVariable Property GameDaysPassed Auto GlobalVariable Property Berserk_Config_LooseControlMoral Auto ;a bool which check whether moral transform which lead to lost control is on or off, configurable via MCM GlobalVariable Property Berserk_Config_LooseControlBaseChance Auto GlobalVariable Property Berserk_Config_LooseControlBaseWeight Auto GlobalVariable Property Berserk_Config_LooseControlMoralWeight Auto ;default is 1, make sure it's counted correctly in the MCM GlobalVariable Property Berserk_Config_LooseControlKillWeight Auto GlobalVariable Property Berserk_Config_Moralitymax Auto GlobalVariable Property Berserk_Config_Killscorebase Auto GlobalVariable Property Berserk_Config_Killscoremodifier Auto GlobalVariable Property Berserk_Config_Killscoremax Auto GlobalVariable Property Berserk_Config_Killscoretimemultmax Auto GlobalVariable Property Berserk_Config_LooseControlBaseTimeMin Auto GlobalVariable Property Berserk_Config_LooseControlBaseTimeMax Auto GlobalVariable Property Berserk_Config_LooseControlCooldownTimeMin Auto GlobalVariable Property Berserk_Config_LooseControlCooldownTimeMax Auto 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 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 GlobalVariable Property Berserk_Config_LooseControlDeathtype Auto FormList Property Berserk_List_secure_caves Auto Spell Property Berserk_Spell_Warningspell Auto ;similar with MTE, but only take visual effects without sound effects Static Property DwePlatMid01 auto ReferenceAlias Property BerserkerAlias auto ActorBase Property Berserk_Player_Loose_Controls_1H_M auto ActorBase Property Berserk_Player_Loose_Controls_2H_M auto ActorBase Property Berserk_Player_Loose_Controls_Ranger_M auto ActorBase Property Berserk_Player_Loose_Controls_Spellsword_M auto ActorBase Property Berserk_Player_Loose_Controls_Mage_M auto ActorBase Property Berserk_Player_Loose_Controls_Unarmed_M auto ActorBase Property Berserk_Player_Loose_Controls_1H_F auto ActorBase Property Berserk_Player_Loose_Controls_2H_F auto ActorBase Property Berserk_Player_Loose_Controls_Ranger_F auto ActorBase Property Berserk_Player_Loose_Controls_Spellsword_F auto ActorBase Property Berserk_Player_Loose_Controls_Mage_F auto ActorBase Property Berserk_Player_Loose_Controls_Unarmed_F auto ImageSpaceModifier Property IllusionBlueMassiveImod Auto ImageSpaceModifier Property FadeToBlackImod Auto ImageSpaceModifier Property FadeToBlackHoldImod Auto ImageSpaceModifier Property FadeToBlackBackImod Auto Bool Property player_has_control=True auto conditional Bool Property player_is_loosing_control=False auto conditional ; -- VARIABLEs -- Actor BerserkerRef ObjectReference PlatRef Int killscore = 0 Int killscorebuff = 0 Float killscorebuffresettime = 0.0 Bool LC_system_active = False Float Invisibility_originalvalue = 0.0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;Threadsafety ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Int mutex_control_status_turn =0 Int mutex_control_status_number =0 Function mutex_control_status_wait() ;atomic as read/write to script's own vars is atomic, Skyrim runs each Script only once at a time, and internal calls and edits won't break this run Int local_number=mutex_control_status_number mutex_control_status_number+=1 while mutex_control_status_turn != local_number utility.wait(0.1) endwhile ;endatomic EndFunction Function mutex_control_status_signal() ;atomic as read/write to script's own vars is atomic, Skyrim runs each Script only once at a time, and internal calls and edits won't break this run mutex_control_status_turn+=1 ;endatomic EndFunction ; -- EVENTs -- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;On Update Game Time, only running while moraltransformations runnin the main rolls ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Event OnUpdateGameTime() ObjectReference PlayerRef = Game.GetPlayer() If !LC_system_active return EndIf ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;Loose Control check ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; If (Berserk_Config_LooseControlMoral.GetValue() as int == 1 && player_has_control && !player_is_loosing_control) Loose_Control_Roll() ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;Loose Control ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ElseIf player_is_loosing_control ;&& !PlayerRef.HasMagicEffect(Berserk_Effect_MoralTransformation);make sure to only call this once transformation is complete Trigger_control_loss() player_is_loosing_control = False PlayerRef.dispelspell(Berserk_Spell_Warningspell) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;Gain Control back ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ElseIf !player_has_control update_player_pos () Gaincontrol() If LC_system_active Float Min = Berserk_Config_LooseControlCooldownTimeMin.GetValue() Float Max = Berserk_Config_LooseControlCooldownTimeMax.GetValue() If Min >= Max Max = Min EndIf RegisterForSingleUpdateGameTime(utility.randomFloat(RealTimeSecondsToGameTimeHours(Min),RealTimeSecondsToGameTimeHours(Max))) EndIf EndIf EndEvent ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;On Update, only running while control is actually lost ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Event OnUpdate() If player_has_control return Endif ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;Update Playerpos to load cells ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; update_player_pos () utility.wait(0.1) ;to let the new cell load if any ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;Monitor Health ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; update_player_health ();run after update pos, as unloaded NPC's have well unknown health values. RegisterForSingleUpdate(2.9) EndEvent ; -- FUNCTIONs -- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;Function: Player got killed without Control ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Function player_replacement_was_killed(Actor the_killed_replacement, Actor akKiller) ObjectReference PlayerRef = Game.GetPlayer() mutex_control_status_wait() ;debug.messagebox(player_has_control) ;debug.messagebox(BerserkerRef) ;debug.messagebox(the_killed_replacement) If player_has_control ;just ignore it, the player has the controls mutex_control_status_signal() ;mutex.signal() return EndIf If the_killed_replacement != BerserkerRef ;just ignore it, its the wrong replacement, maybe an older one not deleted yet, or something spawned by an external script, at least this should never become True mutex_control_status_signal() ;mutex.signal() return EndIf If BerserkerRef == None ;just ignore it, None should not die mutex_control_status_signal() ;mutex.signal() return EndIf PlayerRef.stoptranslation();just to be sure PlayerRef.moveto(BerserkerRef) ;PlayerRef.SetPosition(BerserkerRef.X, BerserkerRef.Y, BerserkerRef.Z) PlatRef.DisableNoWait() PlatRef.Delete() PlatRef = none Game.SetCameraTarget(PlayerRef) ;Debug.SetGodMode(False) PlayerRef.SetActorValue("Invisibility",Invisibility_originalvalue) PlayerRef.SetAlpha(1) Int deathtype = Berserk_Config_LooseControlDeathtype.GetValue() as int If deathtype == 0 PlayerRef.setghost(False) PlayerRef.kill(akKiller) Endif BerserkerAlias.Clear() ; (MTE_Quest_Follower_System as MTE_Quest_Follower_System_Script).Update_LC_playerreplacement(None) BerserkerRef.DisableNoWait() BerserkerRef.Delete() BerserkerRef=none game.setplayeraidriven(False) player_has_control = True UnRegisterForUpdate() mutex_control_status_signal() ;mutex.signal() If deathtype == 1 wake_up_in_cave() Endif EndFunction Function wake_up_in_cave() ObjectReference PlayerRef = Game.GetPlayer() ;Todo some eye candy anim FadeToBlackImod.Apply() ;Debug.SendAnimationEvent(PlayerREF, "BreviMoonlightTalesRestS1") Utility.Wait(2.1) FadeToBlackImod.PopTo(FadeToBlackHoldImod) Int Target = utility.randomint(0,Berserk_List_secure_caves.getsize() - 1) Formlist Targetlocation = Berserk_List_secure_caves.getat(Target) as Formlist Objectreference TargetMarker = Targetlocation.getat(0) as Objectreference ;get the Berserkermarker which is the first object in the cavedata PlayerRef.moveto(TargetMarker) Float whealth= 50.0 ;heal you up to 50 health Float phealth= PlayerRef.GetActorValue("health") Float diff = phealth-whealth If diff > 0 PlayerRef.damageactorvalue("health",diff) ElseIf diff < 0 PlayerRef.restoreactorvalue("health",-diff) EndIf Utility.Wait(0.5) PlayerRef.setghost(False) FadeToBlackHoldImod.PopTo(FadeToBlackBackImod) Utility.Wait(3) FadeToBlackImod.Remove() FadeToBlackHoldImod.Remove() FadeToBlackBackImod.Remove() Endfunction ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;Function Player has killed on something: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Function player_has_killed(Bool was_humanoid) If killscorebuffresettime < GameDaysPassed.GetValue() killscorebuff = 0 EndIf killscorebuffresettime = GameDaysPassed.GetValue()+RealTimeSecondsToGameTimeDays(45.0) If was_humanoid KillScore +=Berserk_Config_Killscorebase.GetValue() as int+killscorebuff killscorebuff+=Berserk_Config_Killscoremodifier.GetValue() as int EndIf EndFunction ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;Function: Player update Health while Control is Lost ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Bool singlerun_updating_health=False ;just to block updatespam, required If placed in an OnHit Function update_player_health() ;So the player can monitor his body's health. ObjectReference PlayerRef = Game.GetPlayer() If singlerun_updating_health return EndIf singlerun_updating_health=True mutex_control_status_wait() If player_has_control ;just ignore it, the player has the controls mutex_control_status_signal() ;mutex.signal() return EndIf Float whealth= BerserkerRef.GetActorValue("health") Float phealth= PlayerRef.GetActorValue("health") Float diff = phealth-whealth If diff > 0 PlayerRef.damageactorvalue("health",diff) ElseIf diff < 0 PlayerRef.restoreactorvalue("health",-diff) EndIf mutex_control_status_signal() ;mutex.signal() singlerun_updating_health=False EndFunction ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;Function: Player update Position while Control is Lost ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Bool singlerun_updating_pos=False ;just to block updatespam. Function update_player_pos ();So the player can monitor his body even If it's running away. :) ObjectReference PlayerRef = Game.GetPlayer() If singlerun_updating_pos return EndIf singlerun_updating_pos=True mutex_control_status_wait() If player_has_control ;just ignore it, the player has the controls mutex_control_status_signal() ;mutex.signal() return EndIf If PlayerRef.GetWorldSpace() == BerserkerRef.GetWorldSpace() && PlayerRef.GetWorldSpace() != None && PlayerRef.GetDistance(BerserkerRef) < 10000 ;Cell.size == 4096 < 10000/sqrt(2) so cell would differ, too. ;we are in the same worldspace wuhu, using translate to. If BerserkerRef.GetParentCell() == None || BerserkerRef.GetParentCell() != PlayerRef.GetParentCell() || PlayerRef.GetDistance(BerserkerRef) > 500 ;Berserker leftloaded space or got to far away from the Player, moving Player. PlayerRef.TranslateTo(BerserkerRef.X, BerserkerRef.Y, BerserkerRef.Z + 3300, BerserkerRef.GetAngleX(), BerserkerRef.GetAngleY(), BerserkerRef.GetAngleZ(), 2000, 0);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. PlatRef.SetPosition(BerserkerRef.X, BerserkerRef.Y, BerserkerRef.Z + 3000) PlatRef.SetAngle(0, 0, 0) EndIf Else If PlayerRef.GetWorldSpace() != None || BerserkerRef.GetParentCell() == None || BerserkerRef.GetParentCell() != PlayerRef.GetParentCell() ;Berserker left actual cell, moving Player. ;either we are inside an iterior cell or in diffent worldspaces, using moveto PlayerRef.stoptranslation();just to be sure PlayerRef.moveto(BerserkerRef) PlatRef.disable() PlatRef.delete() PlatRef = PlayerRef.PlaceAtMe(DwePlatMid01, 1, True, True) PlatRef.SetPosition(PlayerRef.X, PlayerRef.Y, PlayerRef.Z + 3000) PlatRef.SetAngle(0, 0, 0) PlatRef.Enable() PlayerRef.TranslateTo(PlayerRef.X, PlayerRef.Y, PlayerRef.Z + 3300, PlayerRef.GetAngleX(), PlayerRef.GetAngleY(), PlayerRef.GetAngleZ(), 1000, 0) EndIf EndIf mutex_control_status_signal() ;mutex.signal() singlerun_updating_pos=False EndFunction ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;Function: Initialise LCsystem until Force_control_to_player() is called ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Function Initialise() ;If (Berserk_Config_LooseControlMoral.GetValue() as int == 1);currently checked in mainloop ; return ;EndIf KillScore=0 LC_system_active = True ;setting up some time untill, the loose controll check runs first RegisterForSingleUpdateGameTime(utility.randomfloat(0.25,0.5));run first check after a quater to a half ighour EndFunction ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;Function: Force Control to Player ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Function Force_control_to_player() ObjectReference PlayerRef = Game.GetPlayer() player_is_loosing_control=False LC_system_active = False UnregisterForUpdateGameTime() player_is_loosing_control=False PlayerRef.dispelspell(Berserk_Spell_Warningspell) ;Remove any used Imagespace Modifier Gaincontrol() KillScore=0 EndFunction ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;Function Loose Control Roll: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Function Loose_Control_Roll() ObjectReference PlayerRef = Game.GetPlayer() ObjectReference Stat = Game.QueryStat(string asStat) Float MoralityMeter ; as a max value for MoralityIncrements, default is 500 Float MoralityIncrements ; contains points accumulated from all used game statistics Int WerewolfTransforms Int NecksBitten Int Bribes Int Intimidations Int TGQuests Int DBQuests Int DaedricQuests Int PeopleKilled Int AnimalsKilled Int UndeadKilled Int DaedraKilled Int BunniesKilled Int DragonSouls Int ShoutsLearned Int ShoutsMastered Int TotalBounty Int ItemsPickpocketed Int TimesJailed Int JailEscapes Int ItemsStolen Int Assaults Int Murders Int HorsesStolen Int Tresspasses Int BountyMoralMultiplier Int KillChance=0; Int MoralityMeter = Berserk_Config_Moralitymax.GetValue() as int Int RandomChance = Utility.RandomInt(1, 100) Int Berserk_loose_control_base_chance = Berserk_Config_LooseControlBaseChance.GetValue() as int Float Berserk_moral_chance = (MoralityIncrements.GetValue() as int / MoralityMeter.GetValue() as int) * 100 ;--------------------- MoralityIncrements = WerewolfTransforms.GetValue() as int + NecksBitten.GetValue() as int + Bribes.GetValue() as int + Intimidations.GetValue() as int + TGQuests.GetValue() as int + DBQuests.GetValue() as int + DaedricQuests.GetValue() as int + PeopleKilled.GetValue() as int + AnimalsKilled.GetValue() as int + UndeadKilled.GetValue() as int + DaedraKilled.GetValue() as int + BunniesKilled.GetValue() as int + DragonSouls.GetValue() as int + ShoutsLearned.GetValue() as int + ShoutsMastered.GetValue() as int + TotalBounty.GetValue() as int + ItemsPickpocketed.GetValue() as int + TimesJailed.GetValue() as int + JailEscapes.GetValue() as int + ItemsStolen.GetValue() as int + Assaults.GetValue() as int + Murders.GetValue() as int + HorsesStolen.GetValue() as int + Tresspasses.GetValue() as int WerewolfTransforms = (Stat("Werewolf Transformations").GetValue() as int) * Berserk_Moral_Config_GSWerewolf.GetValue() as int NecksBitten = (Stat("Necks Bitten").GetValue() as int) * Berserk_Moral_Config_GSNeckBit.GetValue() as int Bribes = (Stat("Bribes").GetValue() as int) * Berserk_Moral_Config_GSBribe.GetValue() as int Intimidations = (Stat("Intimidations").GetValue() as int) * Berserk_Moral_Config_GSIntimidation.GetValue() as int TGQuests = (Stat("Thieves' Guild Quests Completed").GetValue() as int) * Berserk_Moral_Config_GSTGQuest.GetValue() as int DBQuests = (Stat("The Dark Brotherhood Quests Completed").GetValue() as int) * Berserk_Moral_Config_GSDBQuest.GetValue() as int DaedricQuests = (Stat("Daedric Quests Completed").GetValue() as int) * Berserk_Moral_Config_GSDaedricQuest.GetValue() as int PeopleKilled = (Stat("People Killed").GetValue() as int) * Berserk_Moral_Config_GSPeopleKill.GetValue() as int AnimalsKilled = (Stat("Animals Killed").GetValue() as int) * Berserk_Moral_Config_GSAnimalKill.GetValue() as int UndeadKilled = (Stat("Undead Killed").GetValue() as int) * Berserk_Moral_Config_GSUndeadKill.GetValue() as int DaedraKilled = (Stat("Daedra Killed").GetValue() as int) * Berserk_Moral_Config_GSDaedraKill.GetValue() as int BunniesKilled = (Stat("Bunnies Slaughtered").GetValue() as int) * Berserk_Moral_Config_GSBunnyKill.GetValue() as int DragonSouls = (Stat("Dragon Souls Collected").GetValue() as int) * Berserk_Moral_Config_GSDragonSoul.GetValue() as int ShoutsLearned = (Stat("Shouts Learned").GetValue() as int) * Berserk_Moral_Config_GSShoutLearn.GetValue() as int ShoutsMastered = (Stat("Shouts Mastered").GetValue() as int) * Berserk_Moral_Config_GSShoutMaster.GetValue() as int TotalBounty = (Stat("Total Lifetime Bounty").GetValue() as int) * BountyMoralMultiplier.GetValue() as int ItemsPickpocketed = (Stat("Items Pickpocketed").GetValue() as int) * Berserk_Moral_Config_GSItemPickpocket.GetValue() as int TimesJailed = (Stat("Times Jailed").GetValue() as int) * Berserk_Moral_Config_GSTimeJail.GetValue() as int JailEscapes = (Stat("Jail Escapes").GetValue() as int) * Berserk_Moral_Config_GSJailEscape.GetValue() as int ItemsStolen = (Stat("Items Stolen").GetValue() as int) * Berserk_Moral_Config_GSItemSteal.GetValue() as int Assaults = (Stat("Assaults").GetValue() as int) * Berserk_Moral_Config_GSAssault.GetValue() as int Murders = (Stat("Murders").GetValue() as int) * Berserk_Moral_Config_GSMurder.GetValue() as int HorsesStolen = (Stat("Horses Stolen").GetValue() as int) * Berserk_Moral_Config_GSHorseSteal.GetValue() as int Tresspasses = (Stat("Trespasses").GetValue() as int) * Berserk_Config_Moral_GSTrespass.GetValue() as int ;--------------------- If (Stat("Total Lifetime Bounty").GetValue() as int >= Berserk_Moral_Config_BountyStage1.GetValue() as int) && (Stat("Total Lifetime Bounty").GetValue() as int < Berserk_Moral_Config_BountyStage2.GetValue() as int) BountyMoralMultiplier = Berserk_Moral_Config_GSTotalBounty.GetValue() as int ElseIf (Stat("Total Lifetime Bounty").GetValue() as int >= Berserk_Moral_Config_BountyStage2.GetValue() as int) && (Stat("Total Lifetime Bounty").GetValue() as int < Berserk_Moral_Config_BountyStage3.GetValue() as int) BountyMoralMultiplier = 2 * Berserk_Moral_Config_GSTotalBounty.GetValue() as int ElseIf (Stat("Total Lifetime Bounty").GetValue() as int >= Berserk_Moral_Config_BountyStage3.GetValue() as int) && (Stat("Total Lifetime Bounty").GetValue() as int < Berserk_Moral_Config_BountyStage4.GetValue() as int) BountyMoralMultiplier = 3 * Berserk_Moral_Config_GSTotalBounty.GetValue() as int ElseIf (Stat("Total Lifetime Bounty").GetValue() as int >= Berserk_Moral_Config_BountyStage4.GetValue() as int) && (Stat("Total Lifetime Bounty").GetValue() as int < Berserk_Moral_Config_BountyStage5.GetValue() as int) BountyMoralMultiplier = 4 * Berserk_Moral_Config_GSTotalBounty.GetValue() as int ElseIf (Stat("Total Lifetime Bounty").GetValue() as int >= Berserk_Moral_Config_BountyStage5.GetValue() as int) && (Stat("Total Lifetime Bounty").GetValue() as int < Berserk_Moral_Config_BountyStage6.GetValue() as int) BountyMoralMultiplier = 5 * Berserk_Moral_Config_GSTotalBounty.GetValue() as int ElseIf (Stat("Total Lifetime Bounty").GetValue() as int >= Berserk_Moral_Config_BountyStage6.GetValue() as int) && (Stat("Total Lifetime Bounty").GetValue() as int < Berserk_Moral_Config_BountyStage7.GetValue() as int) BountyMoralMultiplier = 6 * Berserk_Moral_Config_GSTotalBounty.GetValue() as int ElseIf (Stat("Total Lifetime Bounty").GetValue() as int >= Berserk_Moral_Config_BountyStage7.GetValue() as int) && (Stat("Total Lifetime Bounty").GetValue() as int < Berserk_Moral_Config_BountyStage8.GetValue() as int) BountyMoralMultiplier = 7 * Berserk_Moral_Config_GSTotalBounty.GetValue() as int ElseIf (Stat("Total Lifetime Bounty").GetValue() as int >= Berserk_Moral_Config_BountyStage8.GetValue() as int) && (Stat("Total Lifetime Bounty").GetValue() as int < Berserk_Moral_Config_BountyStage9.GetValue() as int) BountyMoralMultiplier = 8 * Berserk_Moral_Config_GSTotalBounty.GetValue() as int ElseIf (Stat("Total Lifetime Bounty").GetValue() as int >= Berserk_Moral_Config_BountyStage9.GetValue() as int) && (Stat("Total Lifetime Bounty").GetValue() as int < Berserk_Moral_Config_BountyStage10.GetValue() as int) BountyMoralMultiplier = 9 * Berserk_Moral_Config_GSTotalBounty.GetValue() as int ElseIf (Stat("Total Lifetime Bounty").GetValue() as int >= Berserk_Moral_Config_BountyStage10.GetValue() as int) BountyMoralMultiplier = 10 * Berserk_Moral_Config_GSTotalBounty.GetValue() as int EndIF ;---consider to move these into MCM script to avoid cluttering this script If Berserk_Moral_Config_BountyStage1.GetValue() as int > Berserk_Moral_Config_BountyStage2.GetValue() as int Berserk_Moral_Config_BountyStage1.GetValue() as int = Berserk_Moral_Config_BountyStage2.GetValue() as int ElseIF Berserk_Moral_Config_BountyStage2.GetValue() as int > Berserk_Moral_Config_BountyStage3.GetValue() as int Berserk_Moral_Config_BountyStage2.GetValue() as int = Berserk_Moral_Config_BountyStage3.GetValue() as int ElseIF Berserk_Moral_Config_BountyStage3.GetValue() as int > Berserk_Moral_Config_BountyStage4.GetValue() as int Berserk_Moral_Config_BountyStage3.GetValue() as int = Berserk_Moral_Config_BountyStage4.GetValue() as int ElseIF Berserk_Moral_Config_BountyStage4.GetValue() as int > Berserk_Moral_Config_BountyStage5.GetValue() as int Berserk_Moral_Config_BountyStage4.GetValue() as int = Berserk_Moral_Config_BountyStage5.GetValue() as int ElseIF Berserk_Moral_Config_BountyStage5.GetValue() as int > Berserk_Moral_Config_BountyStage6.GetValue() as int Berserk_Moral_Config_BountyStage5.GetValue() as int = Berserk_Moral_Config_BountyStage6.GetValue() as int ElseIF Berserk_Moral_Config_BountyStage6.GetValue() as int > Berserk_Moral_Config_BountyStage7.GetValue() as int Berserk_Moral_Config_BountyStage6.GetValue() as int = Berserk_Moral_Config_BountyStage7.GetValue() as int ElseIF Berserk_Moral_Config_BountyStage7.GetValue() as int > Berserk_Moral_Config_BountyStage8.GetValue() as int Berserk_Moral_Config_BountyStage7.GetValue() as int = Berserk_Moral_Config_BountyStage8.GetValue() as int ElseIF Berserk_Moral_Config_BountyStage8.GetValue() as int > Berserk_Moral_Config_BountyStage9.GetValue() as int Berserk_Moral_Config_BountyStage8.GetValue() as int = Berserk_Moral_Config_BountyStage9.GetValue() as int ElseIF Berserk_Moral_Config_BountyStage9.GetValue() as int > Berserk_Moral_Config_BountyStage10.GetValue() as int Berserk_Moral_Config_BountyStage9.GetValue() as int = Berserk_Moral_Config_BountyStage10.GetValue() as int EndIf ;---Debugging to check whether Stat object reference is working properly or not If Stat("People Killed").GetValue() as int == 5 Debug.Notification("You killed 5 people already, added to People Killed game stat") EndIF If Stat("People Killed").GetValue() as int == 10 Debug.Notification("You killed 10 people already, added to People Killed game stat") EndIF If Stat("People Killed").GetValue() as int == 15 Debug.Notification("You killed 15 people already, added to People Killed game stat") EndIF If Stat("Animals Killed").GetValue() as int == 5 Debug.Notification("You killed 5 animals already, added to Animals Killed game stat") EndIF If Stat("Animals Killed").GetValue() as int == 10 Debug.Notification("You killed 10 animals already, added to Animals Killed game stat") EndIF If Stat("Animals Killed").GetValue() as int == 15 Debug.Notification("You killed 15 animals already, added to Animals Killed game stat") EndIF ;---End of debugging KillChance=(KillScore*100)/Berserk_Config_Killscoremax.GetValue() as int If KillChance >= 100 KillChance = 100 EndIF Int BaseWeight=Berserk_Config_LooseControlBaseWeight.GetValue() as int Int MoralWeight=Berserk_Config_LooseControlMoralWeight.GetValue() as int Int KillWeight=Berserk_Config_LooseControlKillWeight.GetValue() as int If BaseWeight == 0 && MoralWeight == 0 && KillWeight == 0 ;we don't want to divide by 0 in the next calculation BaseWeight = 1 EndIf Float chance=(BaseWeight*Berserk_loose_control_base_chance + MoralWeight*Berserk_moral_chance + KillWeight*KillChance)/(BaseWeight+MoralWeight+KillWeight) If RandomChance<=chance player_is_loosing_control=True If LC_system_active RegisterForSingleUpdateGameTime(utility.randomFloat(RealTimeSecondsToGameTimeHours(30),RealTimeSecondsToGameTimeHours(60))) EndIf ;apply a short visual warning Berserk_Spell_Warningspell.cast(PlayerRef) Else If LC_system_active Float Min = Berserk_Config_LooseControlCooldownTimeMin.GetValue() Float Max = Berserk_Config_LooseControlCooldownTimeMax.GetValue() If Min >= Max Max = Min EndIf RegisterForSingleUpdateGameTime(utility.randomFloat(RealTimeSecondsToGameTimeHours(Min),RealTimeSecondsToGameTimeHours(Max))) EndIf KillScore=(KillScore*9)/10 EndIf EndFunction ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;Function Actually Trigger Control Loss: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Function Trigger_control_loss() ObjectReference PlayerRef = Game.GetPlayer() Int Maxmult = (Berserk_Config_Killscoretimemultmax.GetValue() * 100.0) as Int Int KillMult = 100 + (KillScore * (Maxmult - 100)) / Berserk_Config_Killscoremax.GetValue() as int If KillMult > Maxmult KillMult = Maxmult EndIf PlayerRef.dispelspell(Berserk_Spell_Warningspell) Loosecontrol() If LC_system_active Float Min = Berserk_Config_LooseControlBaseTimeMin.GetValue() Float Max = Berserk_Config_LooseControlBaseTimeMax.GetValue() If Min >= Max Max = Min EndIf RegisterForSingleUpdateGameTime(((KillMult as Float)*utility.randomFloat(RealTimeSecondsToGameTimeHours(Min),RealTimeSecondsToGameTimeHours(Max)))/100);lowest is 20 ingame minutes highest is 160 ingame minutes, this sounds fair EndIf KillScore=(KillScore*9)/10 EndFunction ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;Function: Player Loose Control ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Function Loosecontrol() ObjectReference PlayerRef = Game.GetPlayer() mutex_control_status_wait() ;debug.messagebox("loosing Controls") If !player_has_control ;we can only loose controls once mutex_control_status_signal() ;mutex.signal() return EndIf If (PlayerRef.IsSprinting()) Debug.SendAnimationEvent(PlayerRef, "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() ;I don't want to disable the health bar as disableplayercontrols does. ;game.disableplayercontrols(abLooking=False) ;Debug.SetGodMode(True) PlayerRef.setghost() If (PlayerRef.GetActorBase().GetSex() == 1 && PlayerRef.GetEquippedItemType(1) == 1) || (PlayerRef.GetActorBase().GetSex() == 1 && PlayerRef.GetEquippedItemType(1) == 2) || (PlayerRef.GetActorBase().GetSex() == 1 && PlayerRef.GetEquippedItemType(1) == 3) || (PlayerRef.GetActorBase().GetSex() == 1 && PlayerRef.GetEquippedItemType(1) == 4) BerserkerRef = PlayerRef.PlaceAtMe(Berserk_Player_Loose_Controls_1H_F, 1, abForcePersist=True, abInitiallyDisabled = True) as actor ElseIf (PlayerRef.GetActorBase().GetSex() == 1 && PlayerRef.GetEquippedItemType(1) == 5) || (PlayerRef.GetActorBase().GetSex() == 1 && PlayerRef.GetEquippedItemType(1) == 6) BerserkerRef = PlayerRef.PlaceAtMe(Berserk_Player_Loose_Controls_2H_F, 1, abForcePersist=True, abInitiallyDisabled = True) as actor ElseIf (PlayerRef.GetActorBase().GetSex() == 1 && PlayerRef.GetEquippedItemType(1) == 7) || (PlayerRef.GetActorBase().GetSex() == 1 && PlayerRef.GetEquippedItemType(1) == 12) BerserkerRef = PlayerRef.PlaceAtMe(Berserk_Player_Loose_Controls_Ranger_F, 1, abForcePersist=True, abInitiallyDisabled = True) as actor ElseIf (PlayerRef.GetActorBase().GetSex() == 1 && PlayerRef.GetEquippedItemType(1) == 1 && (PlayerRef.GetEquippedItemType(0) == 9 || PlayerRef.GetEquippedItemType(0) == 8)) || (PlayerRef.GetActorBase().GetSex() == 1 && PlayerRef.GetEquippedItemType(1) == 2 && (PlayerRef.GetEquippedItemType(0) == 9 || PlayerRef.GetEquippedItemType(0) == 8)) || (PlayerRef.GetActorBase().GetSex() == 1 && PlayerRef.GetEquippedItemType(1) == 3 && (PlayerRef.GetEquippedItemType(0) == 9 || PlayerRef.GetEquippedItemType(0) == 8)) || (PlayerRef.GetActorBase().GetSex() == 1 && PlayerRef.GetEquippedItemType(1) == 4 && (PlayerRef.GetEquippedItemType(0) == 9 || PlayerRef.GetEquippedItemType(0) == 8)) || (PlayerRef.GetActorBase().GetSex() == 1 && PlayerRef.GetEquippedItemType(1) == 8) BerserkerRef = PlayerRef.PlaceAtMe(Berserk_Player_Loose_Controls_Spellsword_F, 1, abForcePersist=True, abInitiallyDisabled = True) as actor ElseIf (PlayerRef.GetActorBase().GetSex() == 1 && PlayerRef.GetEquippedItemType(1) == 9) BerserkerRef = PlayerRef.PlaceAtMe(Berserk_Player_Loose_Controls_Mage_F, 1, abForcePersist=True, abInitiallyDisabled = True) as actor ElseIf (PlayerRef.GetActorBase().GetSex() == 1 && PlayerRef.GetEquippedItemType(1) == 0) BerserkerRef = PlayerRef.PlaceAtMe(Berserk_Player_Loose_Controls_Unarmed_F, 1, abForcePersist=True, abInitiallyDisabled = True) as actor ElseIf (PlayerRef.GetActorBase().GetSex() == 0 && PlayerRef.GetEquippedItemType(1) == 1) || (PlayerRef.GetActorBase().GetSex() == 0 && PlayerRef.GetEquippedItemType(1) == 2) || (PlayerRef.GetActorBase().GetSex() == 0 && PlayerRef.GetEquippedItemType(1) == 3) || (PlayerRef.GetActorBase().GetSex() == 0 && PlayerRef.GetEquippedItemType(1) == 4) BerserkerRef = PlayerRef.PlaceAtMe(Berserk_Player_Loose_Controls_1H_M, 1, abForcePersist=True, abInitiallyDisabled = True) as actor ElseIf (PlayerRef.GetActorBase().GetSex() == 0 && PlayerRef.GetEquippedItemType(1) == 5) || (PlayerRef.GetActorBase().GetSex() == 0 && PlayerRef.GetEquippedItemType(1) == 6) BerserkerRef = PlayerRef.PlaceAtMe(Berserk_Player_Loose_Controls_2H_M, 1, abForcePersist=True, abInitiallyDisabled = True) as actor ElseIf (PlayerRef.GetActorBase().GetSex() == 0 && PlayerRef.GetEquippedItemType(1) == 7) || (PlayerRef.GetActorBase().GetSex() == 0 && PlayerRef.GetEquippedItemType(1) == 12) BerserkerRef = PlayerRef.PlaceAtMe(Berserk_Player_Loose_Controls_Ranger_M, 1, abForcePersist=True, abInitiallyDisabled = True) as actor ElseIf (PlayerRef.GetActorBase().GetSex() == 0 && PlayerRef.GetEquippedItemType(1) == 1 && (PlayerRef.GetEquippedItemType(0) == 9 || PlayerRef.GetEquippedItemType(0) == 8)) || (PlayerRef.GetActorBase().GetSex() == 0 && PlayerRef.GetEquippedItemType(1) == 2 && (PlayerRef.GetEquippedItemType(0) == 9 || PlayerRef.GetEquippedItemType(0) == 8)) || (PlayerRef.GetActorBase().GetSex() == 0 && PlayerRef.GetEquippedItemType(1) == 3 && (PlayerRef.GetEquippedItemType(0) == 9 || PlayerRef.GetEquippedItemType(0) == 8)) || (PlayerRef.GetActorBase().GetSex() == 0 && PlayerRef.GetEquippedItemType(1) == 4 && (PlayerRef.GetEquippedItemType(0) == 9 || PlayerRef.GetEquippedItemType(0) == 8)) || (PlayerRef.GetActorBase().GetSex() == 0 && PlayerRef.GetEquippedItemType(1) == 8) BerserkerRef = PlayerRef.PlaceAtMe(Berserk_Player_Loose_Controls_Spellsword_M, 1, abForcePersist=True, abInitiallyDisabled = True) as actor ElseIf (PlayerRef.GetActorBase().GetSex() == 0 && PlayerRef.GetEquippedItemType(1) == 9) BerserkerRef = PlayerRef.PlaceAtMe(Berserk_Player_Loose_Controls_Mage_M, 1, abForcePersist=True, abInitiallyDisabled = True) as actor ElseIf (PlayerRef.GetActorBase().GetSex() == 0 && PlayerRef.GetEquippedItemType(1) == 0) BerserkerRef = PlayerRef.PlaceAtMe(Berserk_Player_Loose_Controls_Unarmed_M, 1, abForcePersist=True, abInitiallyDisabled = True) as actor EndIf BerserkerRef.SetPosition(PlayerRef.X, PlayerRef.Y, PlayerRef.Z) BerserkerRef.enable() Invisibility_originalvalue = PlayerRef.GetBaseActorValue("Invisibility") PlayerRef.SetActorValue("Invisibility",100) PlayerRef.SetAlpha(0) utility.wait(0.1);wait a small bit so spells can apply to the replacement utility.wait(0.1);wait a small bit so spells can apply to the replacement copy_player_stats_to_replacement () ; copy_player_faction_to_replacement () ;BerserkerRef.addspell(Berserk_Ability_Replacement_Helthreg_buff) 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) BerserkerRef.TranslateTo(PlayerRef.X, PLayerRef.Y, PlayerRef.Z, PlayerRef.GetAngleX(), PlayerRef.GetAngleY(), PlayerRef.GetAngleZ(), 300, 0) ;For some reason SetAngle() doesnt work for X angle so I'll use TranslateTo to set this angle 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 PlatRef = PlayerRef.PlaceAtMe(DwePlatMid01, 1, True, True) PlatRef.SetPosition(PlayerRef.X, PlayerRef.Y, PlayerRef.Z + 3000) PlatRef.SetAngle(0, 0, 0) PlatRef.Enable() PlayerRef.TranslateTo(PlayerRef.X, PlayerRef.Y, PlayerRef.Z + 3300, PlayerRef.GetAngleX(), PlayerRef.GetAngleY(), PlayerRef.GetAngleZ(), 1000, 0) player_has_control=False RegisterForSingleUpdate(3.0) ;utility.wait(5);just don't forget to overwrite still active translations (which is quiet unlikly ) in Gaincontrol() ;debug.messagebox("loosing Controls done") mutex_control_status_signal() ;mutex.signal() Endfunction ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;Function: Player Gain Control ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Function Gaincontrol() ObjectReference PlayerRef = Game.GetPlayer() ;atomic as read/write to script's own vars is atomic mutex_control_status_wait() ;endatomic ;debug.messagebox("controlgain is started") ;debug.messagebox(player_has_control) If player_has_control ;we can only gain controls once mutex_control_status_signal() ;mutex.signal() return EndIf PlayerRef.stoptranslation();just to be sure PlayerRef.moveto(BerserkerRef) ;PlayerRef.SetPosition(BerserkerRef.X, BerserkerRef.Y, BerserkerRef.Z) ;PlayerRef.TranslateTo(BerserkerRef.X, BerserkerRef.Y, BerserkerRef.Z, BerserkerRef.GetAngleX(), BerserkerRef.GetAngleY(), BerserkerRef.GetAngleZ(), 300, 0) ;For some reason SetAngle() doesnt work for X angle so I'll use TranslateTo to set this angle Float whealth= BerserkerRef.GetActorValue("health") Float phealth= PlayerRef.GetActorValue("health") Float diff = phealth-whealth If diff > 0 PlayerRef.damageactorvalue("health",diff) ElseIf diff < 0 PlayerRef.restoreactorvalue("health",-diff) EndIf Game.SetCameraTarget(PlayerRef) BerserkerRef.DisableNoWait() PlayerRef.SetActorValue("Invisibility",Invisibility_originalvalue) PlayerRef.SetAlpha(1) PlayerRef.setghost(False) ;Debug.SetGodMode(False) game.setplayeraidriven(False) ;game.EnablePlayerControls() BerserkerAlias.Clear() ; (MTE_Quest_Follower_System as MTE_Quest_Follower_System_Script).Update_LC_playerreplacement(None) BerserkerRef.Delete() BerserkerRef=none PlatRef.Disable() PlatRef.Delete() PlatRef=none player_has_control=True UnRegisterForUpdate() ;debug.messagebox("controlgain is done") mutex_control_status_signal() ;mutex.signal() IllusionBlueMassiveImod.apply() Endfunction ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;Function: Copy Player stats to Loose Control replacement ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; function copy_player_stats_to_replacement () ObjectReference PlayerRef = Game.GetPlayer() If BerserkerRef == NONE return EndIf Float pval Float pcval Float wval string[] primevalues= new string[3] primevalues[0]="Health" primevalues[1]="Stamina" primevalues[2]="Magicka" string valname Int i=0 while i<primevalues.length valname=primevalues[i] pval=PlayerRef.GetBaseActorValue(valname) BerserkerRef.setactorvalue(valname,pval) pcval=PlayerRef.GetActorValue(valname) PlayerRef.restoreactorvalue(valname,100000);to get the modIfied maxval pval=PlayerRef.GetActorValue(valname) PlayerRef.damageactorvalue(valname,pval-pcval) BerserkerRef.restoreactorvalue(valname,100000) wval=BerserkerRef.GetActorValue(valname) BerserkerRef.modactorvalue(valname,(pval-wval)) BerserkerRef.restoreactorvalue(valname,100000) wval=BerserkerRef.GetActorValue(valname) BerserkerRef.damageactorvalue(valname,wval-pcval) i+=1 endwhile string[] secvalues= new string[8] secvalues[0]="UnarmedDamage" secvalues[1]="DamageResist" secvalues[2]="DiseaseResist" secvalues[3]="PoisonResist" secvalues[4]="FireResist" secvalues[5]="ElectricResist" secvalues[6]="FrostResist" secvalues[7]="MagicResist" i=0 while i<secvalues.length valname=secvalues[i] pval=PlayerRef.GetActorValue(valname) BerserkerRef.forceactorvalue(valname,pval) i+=1 endwhile endfunction ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;Function: Copy Player Faction to Loose Control replacement ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;function copy_player_faction_to_replacement () ; ObjectReference PlayerRef = Game.GetPlayer() ; If MTE_Config_WolfAlly.GetValue() as int == 1 && !WerewolfRef.IsInFaction(MT_WolfAllyFaction) ; WerewolfRef.AddtoFaction(MT_WolfAllyFaction) ; MT_WolfAllyFaction.SetAlly(WolfFaction) ; EndIf ; BerserkerRef.AddItem(Berserk_Armor_Updater,1) ; utility.wait(0.1) ; BerserkerRef.EquipItem(Berserk_Armor_Updater, true) ; If PlayerREF.IsInFaction(MT_WerewolfFaction) && MT_Player_TherianthropeType.GetValue() as int == 1 && !WerewolfRef.IsInFaction(MT_WerewolfFaction) ; WerewolfRef.AddtoFaction(MT_WerewolfFaction) ; WerewolfRef.AddItem(MT_Item_NPC, MT_Player_WerewolfSkin.GetValue() as int, True) ; (MT_Quest_SkinFramework as MT_Quest_SkinFrameworkScript).NPCWerewolfSkin(WerewolfRef) ; EndIf ; If MTE_Config_WolfAlly.GetValue() as int == 1 && PlayerREF.IsInFaction(MT_WerewolfFaction) && MT_Player_TherianthropeType.GetValue() as int == 1 && !WerewolfRef.IsInFaction(MT_WolfAllyFaction) ; WerewolfRef.AddtoFaction(MT_WolfAllyFaction) ; MT_WolfAllyFaction.SetAlly(WolfFaction) ; EndIf ; If PlayerREF.IsInFaction(MT_WerebearFaction) && MT_Player_TherianthropeType.GetValue() as int == 2 && !WerewolfRef.IsInFaction(MT_WerebearFaction) ; WerewolfRef.AddtoFaction(MT_WerebearFaction) ; WerewolfRef.AddItem(MT_Item_NPC, MT_Player_WerebearSkin.GetValue() as int, True) ; (MT_Quest_SkinFramework as MT_Quest_SkinFrameworkScript).NPCWerebearSkin(WerewolfRef) ; EndIf ; If MTE_Config_WolfAlly.GetValue() as int == 1 && PlayerREF.IsInFaction(MT_WerebearFaction) && MT_Player_TherianthropeType.GetValue() as int == 2 && !WerewolfRef.IsInFaction(MT_BearAllyFaction) ; WerewolfRef.AddtoFaction(MT_BearAllyFaction) ; MT_BearAllyFaction.SetAlly(BearFaction) ; EndIf ;EndFunction ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;Function: Update Replacement Skin ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;Function Update_Replacement_Skin() ; mutex_control_status_wait() ; If player_has_control ; mutex_control_status_signal() ; return ; EndIf ; BerserkerRef.UnEquipItem(Berserk_Armor_Updater, true) ; utility.wait(0.1) ; BerserkerRef.EquipItem(Berserk_Armor_Updater, true) ; mutex_control_status_signal() ;EndFunction ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;Function: Real Time Seconds To Game Time Hours ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Float Function RealTimeSecondsToGameTimeHours(float realtime) Float scaledSeconds = realtime * TimeScale.Value Return scaledSeconds / (60 * 60) EndFunction ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;Function: Real Time Seconds To Game Time Days ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Float Function RealTimeSecondsToGameTimeDays(float realtime) Float scaledSeconds = realtime * TimeScale.Value Return scaledSeconds / (60 * 60 * 24) EndFunction Link to comment Share on other sites More sharing options...
ReDragon2013 Posted January 22, 2019 Share Posted January 22, 2019 You wrote: "I'll post my WIP script here so that people will get a better idea on what i'm working on" My advice use smaller papyrus projects to understand the basics of this language. Find your own coding style.Use this website as lexicon: http://www.creationkit.com/index.php?title=Category:Scripting Berserk_Loose_Control_Script Scriptname Berserk_Loose_Control_Script 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/ ; 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. ; I'm not sure whether it has to be written into its own script or can be included within Transformation script." ; scripts i'm using are based on Moonlight Tales Essentials Overhauled (MTEO) by ubuntufreakdragon" ; -- PROPERTIES -- Quest PROPERTY Berserk_Quest_Morality auto ; as a factor for loose control roll, referenced for morality, name can be changed to suit better Spell PROPERTY Berserk_Spell_Warningspell auto ; similar with MTE, but only take visual effects without sound effects Static PROPERTY DwePlatMid01 auto ImageSpaceModifier PROPERTY IllusionBlueMassiveImod auto ImageSpaceModifier PROPERTY FadeToBlackImod auto ImageSpaceModifier PROPERTY FadeToBlackHoldImod auto ImageSpaceModifier PROPERTY FadeToBlackBackImod auto ; vanilla GlobalVariable PROPERTY GameDaysPassed auto GlobalVariable PROPERTY TimeScale 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_Config_MoralityMax auto 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 ; loose control values GlobalVariable PROPERTY Berserk_Config_LooseControlMoral auto ; a bool, which check whether moral transform which lead to lost control is on or off, configurable via MCM GlobalVariable PROPERTY Berserk_Config_LooseControlBaseChance auto GlobalVariable PROPERTY Berserk_Config_LooseControlBaseWeight auto GlobalVariable PROPERTY Berserk_Config_LooseControlMoralWeight auto ; default=1, make sure it's counted correctly in the MCM GlobalVariable PROPERTY Berserk_Config_LooseControlKillWeight auto GlobalVariable PROPERTY Berserk_Config_LooseControlDeathtype 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 ; kill score GlobalVariable PROPERTY Berserk_Config_Killscorebase auto GlobalVariable PROPERTY Berserk_Config_Killscoremodifier auto GlobalVariable PROPERTY Berserk_Config_Killscoremax auto GlobalVariable PROPERTY Berserk_Config_Killscoretimemultmax auto ActorBase[] PROPERTY Berserk_Player_Loose_Controls_Array auto ; array to store actorbases as follow ;; male ; ActorBase PROPERTY Berserk_Player_Loose_Controls_Unarmed_M auto ; 0 ; ActorBase PROPERTY Berserk_Player_Loose_Controls_1H_M auto ; 1 ; ActorBase PROPERTY Berserk_Player_Loose_Controls_2H_M auto ; 2 ; ActorBase PROPERTY Berserk_Player_Loose_Controls_Ranger_M auto ; 3 ; ActorBase PROPERTY Berserk_Player_Loose_Controls_Mage_M auto ; 4 ; ActorBase PROPERTY Berserk_Player_Loose_Controls_Spellsword_M auto ; 5 ; ;; female ; ActorBase PROPERTY Berserk_Player_Loose_Controls_Unarmed_F auto ; 6 ; ActorBase PROPERTY Berserk_Player_Loose_Controls_1H_F auto ; 7 ; ActorBase PROPERTY Berserk_Player_Loose_Controls_2H_F auto ; 8 ; ActorBase PROPERTY Berserk_Player_Loose_Controls_Ranger_F auto ; 9 ; ActorBase PROPERTY Berserk_Player_Loose_Controls_Mage_F auto ; 10 ; ActorBase PROPERTY Berserk_Player_Loose_Controls_Spellsword_F auto ; 11 FormList PROPERTY Berserk_List_secure_caves auto ReferenceAlias PROPERTY BerserkerAlias auto Bool PROPERTY player_has_control = TRUE auto Conditional Bool PROPERTY player_is_loosing_control = False auto Conditional Float killscorebuffresettime = 0.0 Float Invisibility_originalvalue = 0.0 Int killscore = 0 Int killscorebuff = 0 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 ;-------------------- 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_Config_LooseControlMoral.GetValue() as int == 1) ; currently checked in mainloop ; return ;EndIf KillScore = 0 LC_system_active = TRUE RegisterForSingleUpdateGameTime( Utility.RandomFloat(0.25, 0.5) ) ; run first check after a quater to a half hour ENDFUNCTION ;--------------------------------- FUNCTION Force_control_to_player() ;--------------------------------- UnRegisterForUpdateGameTime() LC_system_active = False myF_Dispel() Gaincontrol() ; Remove any used Imagespace Modifier KillScore = 0 ENDFUNCTION ;-------------------- FUNCTION myF_Dispel() ; internal helper ;-------------------- player_is_loosing_control = False Game.GetPlayer().DispelSpell(Berserk_Spell_Warningspell) ENDFUNCTION ; -- EVENTs -- 2 EVENT OnUpdate() IF ( player_has_control ) RETURN ; - STOP - ENDIF ;--------------------- ; control is actually lost update_player_pos() ; Update Playerpos to load cells Utility.Wait(0.1) ; to let the new cell load if any update_player_health() ; run after update pos, as unloaded NPC's have well unknown health values. RegisterForSingleUpdate(2.9) ENDEVENT EVENT OnUpdateGameTime() ; only running while moraltransformations running the main rolls IF ( LC_system_active ) ELSE RETURN ; - STOP - /0 system not active ENDIF ;--------------------- IF (Berserk_Config_LooseControlMoral.GetValueInt() == 1) && (player_has_control) && (!player_is_loosing_control) Loose_Control_Roll() RETURN ; - STOP - /1 Loose Control check ENDIF ;--------------------- IF ( player_is_loosing_control ) ;&& !PlayerRef.HasMagicEffect(Berserk_Effect_MoralTransformation) ;make sure to only call this once transformation is complete myF_Dispel() Trigger_control_loss() RETURN ; - STOP - /2 loose control ENDIF ;--------------------- IF ( player_has_control ) RETURN ; - STOP - /3 has control back ENDIF ;--------------------- update_player_pos() Gaincontrol() IF ( LC_system_active ) myF_RegisterForWaitTime(Berserk_Config_LooseControlCooldownTimeMin, Berserk_Config_LooseControlCooldownTimeMax, False) ENDIF ENDEVENT ; -- FUNCTIONs -- (3) + 3 + 2 + 10 + 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 RTS_ToGameTimeDays(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 bKill) ; internal helper ;------------------------------------------------------------------------------------- float fMin = gMin.GetValue() float fMax = gMax.GetValue() float f IF (fMin > fMax) ; failsafe for random f = fMax fMax = fMin fMin = f ENDIF f = Utility.RandomFloat(RealTimeSecondsToGameTimeHours(fMin), RealTimeSecondsToGameTimeHours(fMax)) IF ( bKill ) int iMax = Berserk_Config_Killscoretimemultmax.GetValueInt() * 100 ; iMax = Maxmult int i = ((iMax - 100) * KillScore / Berserk_Config_Killscoremax.GetValueInt()) + 100 ; i = KillMult 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 ############################################################################################# ;############## 10 ;----------------------------------------- FUNCTION player_has_killed(Bool bHumanoid) ; 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 ;--------------------- 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) mutex_Add() ; THREADsafe OFF ; == IllusionBlueMassiveImod.Apply() ENDFUNCTION ;---------------------------------------------------------------------- FUNCTION player_replacement_was_killed(Actor targetRef, Actor akKiller) ; 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 - 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) 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) FadeToBlackImod.Remove() ; << 1 FadeToBlackHoldImod.Remove() ; << 2 FadeToBlackBackImod.Remove() ; << 3 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 objectReference oRef 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) player.SetAngle(0.0, 0.0, 0.0) ;; 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 ;-------------------- ; Cell.size == 4096 < 10000/sqrt(2) so cell would differ, too. 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 iterior 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 ;--------------------------------------------------------- ; 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 ) 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 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 ;############### ;### Control ############################################################################################# ;############### 6 ;---------------------------- FUNCTION Loose_Control_Roll() ;---------------------------- 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 i = Game.QueryStat("Shouts Learned") a[8] = i * Berserk_Moral_Config_GSShoutLearn.GetValueInt() ; int ShoutsLearned i = Game.QueryStat("Shouts Mastered") a[9] = i * Berserk_Moral_Config_GSShoutMaster.GetValueInt() ; int ShoutsMastered 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 i = Game.QueryStat("Daedra Killed") a[13] = i * Berserk_Moral_Config_GSDaedraKill.GetValueInt() ; int DaedraKilled 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 i = 0 WHILE (i < a.Length) MoralityIncrements += a[i] as Float i = i + 1 ENDWHILE IF myF_NoControl(MoralityIncrements) player_is_loosing_control = TRUE IF ( LC_system_active ) f = Utility.RandomFloat(RealTimeSecondsToGameTimeHours(30), RealTimeSecondsToGameTimeHours(60)) RegisterForSingleUpdateGameTime(f) ENDIF Berserk_Spell_Warningspell.Cast(Game.GetPlayer()) ; apply a short visual warning RETURN ; - STOP - ENDIF ;--------------------- IF ( LC_system_active ) myF_RegisterForWaitTime(Berserk_Config_LooseControlCooldownTimeMin, Berserk_Config_LooseControlCooldownTimeMax, False) ENDIF KillScore = KillScore * 9 / 10 ; see also Trigger_control_loss() ENDFUNCTION ;---------------------------------------------------- Bool FUNCTION myF_NoControl(Float MoralityIncrements) ; internal helper ;---------------------------------------------------- float r = Utility.RandomInt(1, 100) as Float ;;; Float chance=(BaseWeight*Berserk_loose_control_base_chance + MoralWeight*Berserk_moral_chance + KillWeight*KillChance)/(BaseWeight+MoralWeight+KillWeight) ; ---------------------------------------------------------------------------------------------------------------------------------------------------------- int iB = Berserk_Config_LooseControlBaseWeight.GetValueInt() ; iB = BaseWeight int iM = Berserk_Config_LooseControlMoralWeight.GetValueInt() ; iM = MoralWeight int iK = Berserk_Config_LooseControlKillWeight.GetValueInt() ; iK = KillWeight IF (iB == 0) && (iM == 0) && (iK == 0) iB = 1 ; ** ENDIF float f = (iB as Float) * Berserk_Config_LooseControlBaseChance.GetValue() ;-------- float MoralityMeter = Berserk_Config_Moralitymax.GetValue() ; as a max value for MoralityIncrements, default is 500 f = f + (iM as Float) * MoralityIncrements / MoralityMeter * 100.0 ; Berserk_moral_chance ;-------- int KillChance = (KillScore * 100) / Berserk_Config_Killscoremax.GetValueInt() IF (KillChance >= 100) KillChance = 100 ENDIF f = f + (iK * KillChance) as Float ;-------- f = f / (iB + iM + iK) 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 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 copy_player_stats_to_replacement() ; ### 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) ;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() 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 ( bFemale ) ; IF (i == 0) ; AB = Berserk_Player_Loose_Controls_Unarmed_F ; 0 ; ELSEIF (i == 5) || (i == 6) ; AB = Berserk_Player_Loose_Controls_2H_F ; 5, 6 ; ELSEIF (i == 8) ; AB = Berserk_Player_Loose_Controls_Spellsword_F ; 8 staff ; ELSEIF (i == 9) ; AB = Berserk_Player_Loose_Controls_Mage_F ; 9 spell ; ELSEIF (i == 7) || (i == 12) ; AB = Berserk_Player_Loose_Controls_Ranger_F ; 7, 12 ; ELSEIF (i >= 1) && (i <= 4) ; i = player.GetEquippedItemType(0) ; left hand ; IF (i == 8) || (i == 9) ; AB = Berserk_Player_Loose_Controls_Spellsword_F ; ; ELSE ; AB = Berserk_Player_Loose_Controls_1H_F ; 1, 2, 3, 4 ; ENDIF ; ENDIF ;ELSE ; IF (i == 0) ; AB = Berserk_Player_Loose_Controls_Unarmed_M ; ELSEIF (i == 5) || (i == 6) ; AB = Berserk_Player_Loose_Controls_2H_M ; ELSEIF (i == 8) ; AB = Berserk_Player_Loose_Controls_Spellsword_M ; ELSEIF (i == 9) ; AB = Berserk_Player_Loose_Controls_Mage_M ; ELSEIF (i == 7) || (i == 12) ; AB = Berserk_Player_Loose_Controls_Ranger_M ; ELSEIF (i >= 1) && (i <= 4) ; i = player.GetEquippedItemType(0) ; left hand ; IF (i == 8) || (i == 9) ; AB = Berserk_Player_Loose_Controls_Spellsword_M ; ELSE ; AB = Berserk_Player_Loose_Controls_1H_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) ;---------------------------------------------- int i = player.GetEquippedItemType(1) ; right hand int n = -1 IF (i == 0) n = 0 ; Berserk_Player_Loose_Controls_Unarmed_M 0 -- 6 Berserk_Player_Loose_Controls_Unarmed_F ELSEIF (i == 5) || (i == 6) n = 2 ; Berserk_Player_Loose_Controls_2H_M 2 -- 8 Berserk_Player_Loose_Controls_2H_F ELSEIF (i == 8) n = 5 ; Berserk_Player_Loose_Controls_Spellsword_M 5 -- 11 Berserk_Player_Loose_Controls_Spellsword_F ELSEIF (i == 9) n = 4 ; Berserk_Player_Loose_Controls_Mage_M 4 -- 10 Berserk_Player_Loose_Controls_Mage_F ELSEIF (i == 7) || (i == 12) n = 3 ; Berserk_Player_Loose_Controls_Ranger_M 3 -- 9 Berserk_Player_Loose_Controls_Ranger_F ELSEIF (i >= 1) && (i <= 4) i = player.GetEquippedItemType(0) ; left hand IF (i == 8) || (i == 9) n = 5 ; Berserk_Player_Loose_Controls_Spellsword_M 5 -- 11 Berserk_Player_Loose_Controls_Spellsword_F ELSE n = 1 ; Berserk_Player_Loose_Controls_1H_M 1 -- 7 Berserk_Player_Loose_Controls_1H_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) 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) 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 Link to comment Share on other sites More sharing options...
qwertypol012 Posted January 22, 2019 Author Share Posted January 22, 2019 (edited) You wrote: "I'll post my WIP script here so that people will get a better idea on what i'm working on" My advice use smaller papyrus projects to understand the basics of this language. Find your own coding style.Use this website as lexicon: http://www.creationkit.com/index.php?title=Category:Scripting Berserk_Loose_Control_Script Scriptname Berserk_Loose_Control_Script 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/ ; 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. ; I'm not sure whether it has to be written into its own script or can be included within Transformation script." ; scripts i'm using are based on Moonlight Tales Essentials Overhauled (MTEO) by ubuntufreakdragon" ; -- PROPERTIES -- Quest PROPERTY Berserk_Quest_Morality auto ; as a factor for loose control roll, referenced for morality, name can be changed to suit better Spell PROPERTY Berserk_Spell_Warningspell auto ; similar with MTE, but only take visual effects without sound effects Static PROPERTY DwePlatMid01 auto ImageSpaceModifier PROPERTY IllusionBlueMassiveImod auto ImageSpaceModifier PROPERTY FadeToBlackImod auto ImageSpaceModifier PROPERTY FadeToBlackHoldImod auto ImageSpaceModifier PROPERTY FadeToBlackBackImod auto ; vanilla GlobalVariable PROPERTY GameDaysPassed auto GlobalVariable PROPERTY TimeScale 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_Config_MoralityMax auto 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 ; loose control values GlobalVariable PROPERTY Berserk_Config_LooseControlMoral auto ; a bool, which check whether moral transform which lead to lost control is on or off, configurable via MCM GlobalVariable PROPERTY Berserk_Config_LooseControlBaseChance auto GlobalVariable PROPERTY Berserk_Config_LooseControlBaseWeight auto GlobalVariable PROPERTY Berserk_Config_LooseControlMoralWeight auto ; default=1, make sure it's counted correctly in the MCM GlobalVariable PROPERTY Berserk_Config_LooseControlKillWeight auto GlobalVariable PROPERTY Berserk_Config_LooseControlDeathtype 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 ; kill score GlobalVariable PROPERTY Berserk_Config_Killscorebase auto GlobalVariable PROPERTY Berserk_Config_Killscoremodifier auto GlobalVariable PROPERTY Berserk_Config_Killscoremax auto GlobalVariable PROPERTY Berserk_Config_Killscoretimemultmax auto ActorBase[] PROPERTY Berserk_Player_Loose_Controls_Array auto ; array to store actorbases as follow ;; male ; ActorBase PROPERTY Berserk_Player_Loose_Controls_Unarmed_M auto ; 0 ; ActorBase PROPERTY Berserk_Player_Loose_Controls_1H_M auto ; 1 ; ActorBase PROPERTY Berserk_Player_Loose_Controls_2H_M auto ; 2 ; ActorBase PROPERTY Berserk_Player_Loose_Controls_Ranger_M auto ; 3 ; ActorBase PROPERTY Berserk_Player_Loose_Controls_Mage_M auto ; 4 ; ActorBase PROPERTY Berserk_Player_Loose_Controls_Spellsword_M auto ; 5 ; ;; female ; ActorBase PROPERTY Berserk_Player_Loose_Controls_Unarmed_F auto ; 6 ; ActorBase PROPERTY Berserk_Player_Loose_Controls_1H_F auto ; 7 ; ActorBase PROPERTY Berserk_Player_Loose_Controls_2H_F auto ; 8 ; ActorBase PROPERTY Berserk_Player_Loose_Controls_Ranger_F auto ; 9 ; ActorBase PROPERTY Berserk_Player_Loose_Controls_Mage_F auto ; 10 ; ActorBase PROPERTY Berserk_Player_Loose_Controls_Spellsword_F auto ; 11 FormList PROPERTY Berserk_List_secure_caves auto ReferenceAlias PROPERTY BerserkerAlias auto Bool PROPERTY player_has_control = TRUE auto Conditional Bool PROPERTY player_is_loosing_control = False auto Conditional Float killscorebuffresettime = 0.0 Float Invisibility_originalvalue = 0.0 Int killscore = 0 Int killscorebuff = 0 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 ;-------------------- 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_Config_LooseControlMoral.GetValue() as int == 1) ; currently checked in mainloop ; return ;EndIf KillScore = 0 LC_system_active = TRUE RegisterForSingleUpdateGameTime( Utility.RandomFloat(0.25, 0.5) ) ; run first check after a quater to a half hour ENDFUNCTION ;--------------------------------- FUNCTION Force_control_to_player() ;--------------------------------- UnRegisterForUpdateGameTime() LC_system_active = False myF_Dispel() Gaincontrol() ; Remove any used Imagespace Modifier KillScore = 0 ENDFUNCTION ;-------------------- FUNCTION myF_Dispel() ; internal helper ;-------------------- player_is_loosing_control = False Game.GetPlayer().DispelSpell(Berserk_Spell_Warningspell) ENDFUNCTION ; -- EVENTs -- 2 EVENT OnUpdate() IF ( player_has_control ) RETURN ; - STOP - ENDIF ;--------------------- ; control is actually lost update_player_pos() ; Update Playerpos to load cells Utility.Wait(0.1) ; to let the new cell load if any update_player_health() ; run after update pos, as unloaded NPC's have well unknown health values. RegisterForSingleUpdate(2.9) ENDEVENT EVENT OnUpdateGameTime() ; only running while moraltransformations running the main rolls IF ( LC_system_active ) ELSE RETURN ; - STOP - /0 system not active ENDIF ;--------------------- IF (Berserk_Config_LooseControlMoral.GetValueInt() == 1) && (player_has_control) && (!player_is_loosing_control) Loose_Control_Roll() RETURN ; - STOP - /1 Loose Control check ENDIF ;--------------------- IF ( player_is_loosing_control ) ;&& !PlayerRef.HasMagicEffect(Berserk_Effect_MoralTransformation) ;make sure to only call this once transformation is complete myF_Dispel() Trigger_control_loss() RETURN ; - STOP - /2 loose control ENDIF ;--------------------- IF ( player_has_control ) RETURN ; - STOP - /3 has control back ENDIF ;--------------------- update_player_pos() Gaincontrol() IF ( LC_system_active ) myF_RegisterForWaitTime(Berserk_Config_LooseControlCooldownTimeMin, Berserk_Config_LooseControlCooldownTimeMax, False) ENDIF ENDEVENT ; -- FUNCTIONs -- (3) + 3 + 2 + 10 + 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 RTS_ToGameTimeDays(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 bKill) ; internal helper ;------------------------------------------------------------------------------------- float fMin = gMin.GetValue() float fMax = gMax.GetValue() float f IF (fMin > fMax) ; failsafe for random f = fMax fMax = fMin fMin = f ENDIF f = Utility.RandomFloat(RealTimeSecondsToGameTimeHours(fMin), RealTimeSecondsToGameTimeHours(fMax)) IF ( bKill ) int iMax = Berserk_Config_Killscoretimemultmax.GetValueInt() * 100 ; iMax = Maxmult int i = ((iMax - 100) * KillScore / Berserk_Config_Killscoremax.GetValueInt()) + 100 ; i = KillMult 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 ############################################################################################# ;############## 10 ;----------------------------------------- FUNCTION player_has_killed(Bool bHumanoid) ; 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 ;--------------------- 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) mutex_Add() ; THREADsafe OFF ; == IllusionBlueMassiveImod.Apply() ENDFUNCTION ;---------------------------------------------------------------------- FUNCTION player_replacement_was_killed(Actor targetRef, Actor akKiller) ; 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 - 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) 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) FadeToBlackImod.Remove() ; << 1 FadeToBlackHoldImod.Remove() ; << 2 FadeToBlackBackImod.Remove() ; << 3 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 objectReference oRef 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) player.SetAngle(0.0, 0.0, 0.0) ;; 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 ;-------------------- ; Cell.size == 4096 < 10000/sqrt(2) so cell would differ, too. 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 iterior 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 ;--------------------------------------------------------- ; 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 ) 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 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 ;############### ;### Control ############################################################################################# ;############### 6 ;---------------------------- FUNCTION Loose_Control_Roll() ;---------------------------- 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 i = Game.QueryStat("Shouts Learned") a[8] = i * Berserk_Moral_Config_GSShoutLearn.GetValueInt() ; int ShoutsLearned i = Game.QueryStat("Shouts Mastered") a[9] = i * Berserk_Moral_Config_GSShoutMaster.GetValueInt() ; int ShoutsMastered 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 i = Game.QueryStat("Daedra Killed") a[13] = i * Berserk_Moral_Config_GSDaedraKill.GetValueInt() ; int DaedraKilled 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 i = 0 WHILE (i < a.Length) MoralityIncrements += a[i] as Float i = i + 1 ENDWHILE IF myF_NoControl(MoralityIncrements) player_is_loosing_control = TRUE IF ( LC_system_active ) f = Utility.RandomFloat(RealTimeSecondsToGameTimeHours(30), RealTimeSecondsToGameTimeHours(60)) RegisterForSingleUpdateGameTime(f) ENDIF Berserk_Spell_Warningspell.Cast(Game.GetPlayer()) ; apply a short visual warning RETURN ; - STOP - ENDIF ;--------------------- IF ( LC_system_active ) myF_RegisterForWaitTime(Berserk_Config_LooseControlCooldownTimeMin, Berserk_Config_LooseControlCooldownTimeMax, False) ENDIF KillScore = KillScore * 9 / 10 ; see also Trigger_control_loss() ENDFUNCTION ;---------------------------------------------------- Bool FUNCTION myF_NoControl(Float MoralityIncrements) ; internal helper ;---------------------------------------------------- float r = Utility.RandomInt(1, 100) as Float ;;; Float chance=(BaseWeight*Berserk_loose_control_base_chance + MoralWeight*Berserk_moral_chance + KillWeight*KillChance)/(BaseWeight+MoralWeight+KillWeight) ; ---------------------------------------------------------------------------------------------------------------------------------------------------------- int iB = Berserk_Config_LooseControlBaseWeight.GetValueInt() ; iB = BaseWeight int iM = Berserk_Config_LooseControlMoralWeight.GetValueInt() ; iM = MoralWeight int iK = Berserk_Config_LooseControlKillWeight.GetValueInt() ; iK = KillWeight IF (iB == 0) && (iM == 0) && (iK == 0) iB = 1 ; ** ENDIF float f = (iB as Float) * Berserk_Config_LooseControlBaseChance.GetValue() ;-------- float MoralityMeter = Berserk_Config_Moralitymax.GetValue() ; as a max value for MoralityIncrements, default is 500 f = f + (iM as Float) * MoralityIncrements / MoralityMeter * 100.0 ; Berserk_moral_chance ;-------- int KillChance = (KillScore * 100) / Berserk_Config_Killscoremax.GetValueInt() IF (KillChance >= 100) KillChance = 100 ENDIF f = f + (iK * KillChance) as Float ;-------- f = f / (iB + iM + iK) 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 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 copy_player_stats_to_replacement() ; ### 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) ;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() 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 ( bFemale ) ; IF (i == 0) ; AB = Berserk_Player_Loose_Controls_Unarmed_F ; 0 ; ELSEIF (i == 5) || (i == 6) ; AB = Berserk_Player_Loose_Controls_2H_F ; 5, 6 ; ELSEIF (i == 8) ; AB = Berserk_Player_Loose_Controls_Spellsword_F ; 8 staff ; ELSEIF (i == 9) ; AB = Berserk_Player_Loose_Controls_Mage_F ; 9 spell ; ELSEIF (i == 7) || (i == 12) ; AB = Berserk_Player_Loose_Controls_Ranger_F ; 7, 12 ; ELSEIF (i >= 1) && (i <= 4) ; i = player.GetEquippedItemType(0) ; left hand ; IF (i == 8) || (i == 9) ; AB = Berserk_Player_Loose_Controls_Spellsword_F ; ; ELSE ; AB = Berserk_Player_Loose_Controls_1H_F ; 1, 2, 3, 4 ; ENDIF ; ENDIF ;ELSE ; IF (i == 0) ; AB = Berserk_Player_Loose_Controls_Unarmed_M ; ELSEIF (i == 5) || (i == 6) ; AB = Berserk_Player_Loose_Controls_2H_M ; ELSEIF (i == 8) ; AB = Berserk_Player_Loose_Controls_Spellsword_M ; ELSEIF (i == 9) ; AB = Berserk_Player_Loose_Controls_Mage_M ; ELSEIF (i == 7) || (i == 12) ; AB = Berserk_Player_Loose_Controls_Ranger_M ; ELSEIF (i >= 1) && (i <= 4) ; i = player.GetEquippedItemType(0) ; left hand ; IF (i == 8) || (i == 9) ; AB = Berserk_Player_Loose_Controls_Spellsword_M ; ELSE ; AB = Berserk_Player_Loose_Controls_1H_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) ;---------------------------------------------- int i = player.GetEquippedItemType(1) ; right hand int n = -1 IF (i == 0) n = 0 ; Berserk_Player_Loose_Controls_Unarmed_M 0 -- 6 Berserk_Player_Loose_Controls_Unarmed_F ELSEIF (i == 5) || (i == 6) n = 2 ; Berserk_Player_Loose_Controls_2H_M 2 -- 8 Berserk_Player_Loose_Controls_2H_F ELSEIF (i == 8) n = 5 ; Berserk_Player_Loose_Controls_Spellsword_M 5 -- 11 Berserk_Player_Loose_Controls_Spellsword_F ELSEIF (i == 9) n = 4 ; Berserk_Player_Loose_Controls_Mage_M 4 -- 10 Berserk_Player_Loose_Controls_Mage_F ELSEIF (i == 7) || (i == 12) n = 3 ; Berserk_Player_Loose_Controls_Ranger_M 3 -- 9 Berserk_Player_Loose_Controls_Ranger_F ELSEIF (i >= 1) && (i <= 4) i = player.GetEquippedItemType(0) ; left hand IF (i == 8) || (i == 9) n = 5 ; Berserk_Player_Loose_Controls_Spellsword_M 5 -- 11 Berserk_Player_Loose_Controls_Spellsword_F ELSE n = 1 ; Berserk_Player_Loose_Controls_1H_M 1 -- 7 Berserk_Player_Loose_Controls_1H_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) 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) 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 Thanks for coming here too, ReDragon2013! :laugh: Yes, one really shoud to start from smaller projects first before delving further into the depths of papyrus scripting. But unfortunately, the features i realy want to have in my mod requires such kind of advanced codes, so i have no other choices other than get my hands dirty with such complex papyrus scripting. Fortunately, ubuntufreakdragon made a mod which works just exactly what i need, and he gave me permission to use his scripts as long as i credit him. So that helped me a lot with a robust base script for a feature i want in my mod, and i need to edit and tweak it further (also removing unnecessary codes) in order to get the result i really want. The script i posted here was an "old" version since it has been edited and updated further, although it's not finished yet (i'm still in progress on finishing it). That said, thanks for your edited script and i'll try to elaborate it. If i have some problems or questions regarding it, then sorry if i'll bother you again for asking about it (i'll most likely try to post the new version of the script so that you and other people can take a look at it and see if there's anything need to be corrected or improved). Big thanks to you anyway! I'll surely put your name in the credits for the mod once it's released. :smile: Edit: Just did a quick glance on your edited script, and i find that you've added some significant improvements i could never think of. I could learn a thing or two from this. But now i need to take a rest since my body is atching all over, wanting to go to bed earlier. :laugh: Edited January 23, 2019 by qwertypol012 Link to comment Share on other sites More sharing options...
qwertypol012 Posted January 27, 2019 Author Share Posted January 27, 2019 (edited) Alright, so i have somehow -more or less- finished the scripts, except MCM script which i'm still working on to finish. Here i'll post the scripts, hopefully you can take a look and check if there's something wrong or need improvement. There are several scripts. Some of them are linked each other, ie. some functions from a script are called by other scripts. I'll post the scripts with the name on it. 1. Berserk_Loose_Control_Script.This is the main script which governs lose control mechanism. Scriptname Berserk_Loose_Control_Script extends Quest Conditional ;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 ; -- PROPERTIES -- Perk Property Berserk_NPC_FallDmg Auto Spell Property BerserkerLostControlAfterEffects Auto ;spell to trigger debuff effects after lost control effect finished 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 Static Property DwePlatMid01 auto ;other script references Armor Property ArmorBerserkerWBoots2 Auto Armor Property ArmorBerserkerWCuirass2 Auto Armor Property ArmorBerserkerGauntlets2 Auto Armor Property ArmorBerserkWHelmet Auto GlobalVariable Property MEValueDefiner Auto ;its value defines what MEs are active Spell Property BerserkerArmorBeastChange Auto MagicEffect Property BerserkArmorBeastT Auto MagicEffect Property BerserkArmorBeastTDanger Auto SCRBerserkArmorB Property BerserkArmorBeastT Auto SCRBerserkArmorB Property BerserkArmorBeastTDanger Auto Formlist Property WornAmmoList Auto ImageSpaceModifier Property IllusionBlueMassiveImod Auto ImageSpaceModifier Property FadeToBlackImod Auto ImageSpaceModifier Property FadeToBlackHoldImod Auto ImageSpaceModifier Property FadeToBlackBackImod Auto ;vanilla Idle Property BleedOutStart Auto Idle Property BleedOutStop Auto GlobalVariable Property GameDaysPassed Auto GlobalVariable Property TimeScale Auto Perk Property AllowShoutingPerk 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 ;loose control values GlobalVariable Property Berserk_Config_Moral_Warningtime Auto GlobalVariable Property Berserk_LooseControlMoral_Enable Auto ;on/off toggle for lost control based on moral GlobalVariable Property Berserk_Config_LooseControlBaseChance Auto GlobalVariable Property Berserk_Config_LooseControlBaseWeight Auto GlobalVariable Property Berserk_Config_LooseControlMoralWeight Auto ;default is 1, make sure it's counted correctly in the MCM GlobalVariable Property Berserk_Config_LooseControlDeathtype 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 ;moral score ;GlobalVariable Property Berserk_Config_MoralScorebase Auto ;not used anymore GlobalVariable Property Berserk_Config_MoralScoremax Auto GlobalVariable Property Berserk_Config_MoralScoretimemultmax Auto ;moral status GlobalVariable Property Berserk_Moral_Transformed Auto ;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 FormList Property Berserk_List_secure_caves Auto ReferenceAlias Property BerserkerAlias auto Bool Property player_has_control = True auto conditional Bool Property player_is_loosing_control = False auto conditional Float Invisibility_originalvalue = 0.0 Int MoralMax ; as a max value for MoralScore, default is 500 Int MoralScore ; 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 ;-------------------- 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 MoralScore = 0 LC_system_active = TRUE RegisterForSingleUpdateGameTime( Utility.RandomFloat(0.25, 0.5) ) ; run first check after a quarter to a half hour ENDFUNCTION ;--------------------------------- FUNCTION Force_control_to_player() ;--------------------------------- UnRegisterForUpdateGameTime() LC_system_active = False myF_Dispel() Gaincontrol() ; Remove any used Imagespace Modifier MoralScore = 0 ENDFUNCTION ;-------------------- FUNCTION myF_Dispel() ; internal helper ;-------------------- player_is_loosing_control = False Game.GetPlayer().DispelSpell(Berserk_Spell_Warningspell) ENDFUNCTION ;------------------------- FUNCTION TransformBack() ;------------------------- Force_control_to_player() ;UnregisterForUpdateGameTime() ; already included in Force_control_to_player() Berserk_Moral_Transformed.SetValue(0) ENDFUNCTION ; -- EVENTs -- EVENT OnUpdate() IF ( player_has_control ) RETURN ; - STOP - ENDIF ;--------------------- ; control is actually lost update_player_pos() ; Update Playerpos to load 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 actor player = Game.GetPlayer() IF ( LC_system_active ) IF ( player.HasSpell(BerserkerArmorBeastChange) ) || ( player.HasMagicEffect(BerserkArmorBeastT) ) || ( player.HasMagicEffect(BerserkArmorBeastTDanger) ) ELSE RETURN ; - STOP - /0 either 1 of 3 requirements not fulfilled ENDIF ELSE RETURN ; - STOP - /1 system not active ENDIF ;--------------------- IF (Berserk_LooseControlMoral_Enable.GetValueInt() == 1) && (player_has_control) && (!player_is_loosing_control) IF ( player.HasSpell(BerserkerArmorBeastChange) ) || ( player.HasMagicEffect(BerserkArmorBeastT) ) || ( player.HasMagicEffect(BerserkArmorBeastTDanger) ) Moral_counting() RETURN ; - STOP - /2 Moral counting, applies both in & out of combat ELSEIF ( (player.IsInCombat() == True) && player.HasSpell(BerserkerArmorBeastChange) ) || ( (player.IsInCombat() == True) && player.HasMagicEffect(BerserkArmorBeastT) ) || ( (player.IsInCombat() == True) && player.HasMagicEffect(BerserkArmorBeastTDanger) ) Moral_counting() Loose_Control_Roll() RETURN ; - STOP - /3 Moral counting & Loose Control check, loose control roll only applies in combat ENDIF ENDIF ;--------------------- IF ( player_is_loosing_control ) && ( player.IsInCombat() == True ) ;&& !player.HasMagicEffect(Berserk_Effect_MoralTransformation) ;make sure to only call this once transformation is complete IF ( player.HasSpell(BerserkerArmorBeastChange) ) || ( player.HasMagicEffect(BerserkArmorBeastT) ) || ( player.HasMagicEffect(BerserkArmorBeastTDanger) ) myF_Dispel() Trigger_control_loss() RETURN ; - STOP - /4 loose control ELSE RETURN ; - STOP - /5 ENDIF ENDIF ;--------------------- IF ( player_has_control ) RETURN ; - STOP - /6 has control back ENDIF ;--------------------- update_player_pos() TransformBack() ;Gaincontrol() IF ( LC_system_active ) myF_RegisterForWaitTime(Berserk_Config_LooseControlCooldownTimeMin, Berserk_Config_LooseControlCooldownTimeMax, False) ENDIF ENDEVENT ; -- FUNCTIONs -- (3) + 3 + 2 + 10 + 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 f = fMax fMax = fMin fMin = f ENDIF f = Utility.RandomFloat(RealTimeSecondsToGameTimeHours(fMin), RealTimeSecondsToGameTimeHours(fMax)) IF ( bMoral ) 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 ############################################################################################# ;############## 10 ;--------------------- 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() 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) ; 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) FadeToBlackImod.Remove() ; << 1 FadeToBlackHoldImod.Remove() ; << 2 FadeToBlackBackImod.Remove() ; << 3 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 objectReference oRef 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) player.SetAngle(0.0, 0.0, 0.0) ;; 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 ;-------------------- ; Cell.size == 4096 < 10000/sqrt(2) so cell would differ, too. 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 ;--------------------------------------------------------- ; 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 ) 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 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 ;############### ;### Control ############################################################################################# ;############### 6 ;---------------------------- 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 MoralScore ; contains accumulated points from all used game statistics i = 0 WHILE (i < a.Length) MoralScore += a[i] as Float i = i + 1 ENDWHILE float MoralMax = Berserk_Config_MoralScoremax.GetValue() ; as a max value for MoralScore, default is 500 IF (MoralScore >= MoralMax) MoralScore = MoralMax ENDIF ENDFUNCTION ;------------------------------- FUNCTION Loose_Control_Roll() ;------------------------------- IF myF_NoControl(MoralScore) player_is_loosing_control = TRUE IF ( LC_system_active ) f = Utility.RandomFloat(RealTimeSecondsToGameTimeHours(30), RealTimeSecondsToGameTimeHours(60)) RegisterForSingleUpdateGameTime(f) ENDIF IF ( Berserk_Config_Moral_Warningtime.GetValueInt() == 1 ) Berserk_Spell_Warningspell.Cast(Game.GetPlayer()) ; apply a short visual warning RETURN ; - STOP - ENDIF ENDIF ;--------------------- IF ( LC_system_active ) myF_RegisterForWaitTime(Berserk_Config_LooseControlCooldownTimeMin, Berserk_Config_LooseControlCooldownTimeMax, False) ENDIF ; MoralScore = MoralScore * 9 / 10 ; see also Trigger_control_loss() ENDFUNCTION ;---------------------------------------------------- Bool FUNCTION myF_NoControl(Float MoralScore) ; internal helper ;---------------------------------------------------- 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 MoralMax = Berserk_Config_MoralScoremax.GetValue() ; as a max value for MoralScore, default is 500 float MoralChance = MoralScore / MoralMax * 100.0 ; Berserk_moral_chance IF (MoralChance >= 100) MoralChance = 100 ENDIF f = f + (iM as Float) * 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 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 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.GetValueInt() == 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() ; ### copy_player_gears_to_replacement() 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() 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 ( bFemale ) IF (i == 0) AB = Berserk_Player_Loose_Controls_Unarmed_F ; 0 ELSEIF (i == 11) Weapon j = player.GetEquippedWeapon() as Weapon player.UnEquipItem(j, False, True) AB = Berserk_Player_Loose_Controls_Unarmed_F ; 11 torch, unequip then return to unarmed ELSEIF (i == 8) AB = Berserk_Player_Loose_Controls_Spellsword_F ; 8 staff ELSEIF (i == 9) AB = Berserk_Player_Loose_Controls_Mage_F ; 9 spell ELSEIF (i == 7) || (i == 12) AB = Berserk_Player_Loose_Controls_Ranger_F ; 7, 12 ELSEIF (i >= 1) && (i <= 6) i = player.GetEquippedItemType(0) ; left hand IF (i == 8) || (i == 9) AB = Berserk_Player_Loose_Controls_Spellsword_F ; ELSE AB = Berserk_Player_Loose_Controls_Melee_F ; 1, 2, 3, 4, 5, 6 ENDIF ENDIF ELSE IF (i == 0) AB = Berserk_Player_Loose_Controls_Unarmed_M ELSEIF (i == 11) Weapon j = player.GetEquippedWeapon() as Weapon player.UnEquipItem(j, False, True) AB = Berserk_Player_Loose_Controls_Unarmed_M ELSEIF (i == 8) AB = Berserk_Player_Loose_Controls_Spellsword_M ELSEIF (i == 9) AB = Berserk_Player_Loose_Controls_Mage_M ELSEIF (i == 7) || (i == 12) AB = Berserk_Player_Loose_Controls_Ranger_M ELSEIF (i >= 1) && (i <= 6) i = player.GetEquippedItemType(0) ; left hand IF (i == 8) || (i == 9) AB = Berserk_Player_Loose_Controls_Spellsword_M 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) 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) 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(Formlist AmmoList) ; ammo list for copy player gears function ;--------------------------------------------- Form Entry = NONE Int index = 0 WHILE index < AmmoList.GetSize() Entry = AmmoList.GetAt(Index) IF Entry.IsEquipped() index = AmmoList.GetSize() ; got what we need stop loop ELSE Entry = NONE ; erase stored entry as we do not need it ENDIF index += 1 ENDWHILE RETURN Entry ENDFUNCTION ;--------------------------------------------- FUNCTION copy_player_gears_to_replacement() ; copy Player gears to Loose Control replacement ;--------------------------------------------- actor player = Game.GetPlayer() Form WornAmmo = GetWornAmmo(WornAmmoList) IF ( !BerserkerRef ) RETURN ; - STOP - ENDIF IF (player.GetWornForm(0x00000200) != None) Armor Shield = player.GetWornForm(0x00000200) as Armor BerserkerRef.AddItem(Shield, absilent=true) BerserkerRef.EquipItem(Shield, true, true) ; Debug.MessageBox("...") ENDIF IF (player.GetWornForm(0x00000020) != None) Armor Amulet = player.GetWornForm(0x00000020) as Armor BerserkerRef.AddItem(Amulet, absilent=true) BerserkerRef.EquipItem(Amulet, false, true) ; Debug.MessageBox("...") ENDIF IF (player.GetWornForm(0x00000040) != None) Armor Ring = player.GetWornForm(0x00000040) as Armor BerserkerRef.AddItem(Ring, absilent=true) BerserkerRef.EquipItem(Ring, false, true) ; Debug.MessageBox("...") ENDIF IF (player.GetEquippedWeapon() != None) Weapon RWeapon = player.GetEquippedWeapon() as Weapon BerserkerRef.AddItem(RWeapon, absilent=true) BerserkerRef.EquipItem(RWeapon, true, true) ; Debug.MessageBox("...") ENDIF IF (player.GetEquippedWeapon(true) != None) Weapon LWeapon = player.GetEquippedWeapon(true) as Weapon BerserkerRef.AddItem(LWeapon, absilent=true) BerserkerRef.EquipItem(LWeapon, true, true) ; Debug.MessageBox("...") ENDIF IF WornAmmo ;valid ammo BerserkerRef.AddItem(WornAmmo, 100, absilent=true) ;could get count of ammo on player or just give a fixed ammount that should last the duration of the berserker status BerserkerRef.EquipItem(WornAmmo, true, true) ENDIF IF (player.GetEquippedSpell(0) != None) Spell LSpell = player.GetEquippedSpell(0) as Spell BerserkerRef.AddSpell(LSpell) BerserkerRef.EquipSpell(LSpell, 0) ; Debug.MessageBox("...") ENDIF IF (player.GetEquippedSpell(1) != None) Spell RSpell = player.GetEquippedSpell(1) as Spell BerserkerRef.AddSpell(RSpell) BerserkerRef.EquipSpell(RSpell, 1) ; Debug.MessageBox("...") ENDIF IF (player.GetEquippedSpell(2) != None) Spell OSpell = player.GetEquippedSpell(2) as Spell BerserkerRef.AddSpell(OSpell) BerserkerRef.EquipSpell(OSpell, 2) ; Debug.MessageBox("...") ENDIF IF (player.GetEquippedShout() != None) Shout Shouts = player.GetEquippedShout() as Shout BerserkerRef.AddShout(Shouts) BerserkerRef.EquipShout(Shouts) ; Debug.MessageBox("...") ENDIF ENDFUNCTION 2. SCRBerserkArmorCheckIfSet.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. Scriptname SCRBerserkArmorCheckIfSet extends ObjectReference Quest Property Berserk_Quest_Loose_Control Auto Spell Property BerserkerArmorBeastChange Auto GlobalVariable Property TargetLvlMult_AutoT Auto GlobalVariable Property HealthThreshold_AutoT Auto GlobalVariable Property RandomChance_AutoT Auto Bool LC_system_active = False Actor Player Event OnInit() Player = Game.GetPlayer() EndEvent Event OnEquipped(Actor akActor) akActor.AddSpell(BerserkerArmorBeastChange) akActor.EquipSpell(BerserkerArmorBeastChange, 2) (Berserk_Quest_Loose_Control as Berserk_Loose_Control_Script).Initialise() EndEvent Event OnHit(ObjectReference akAggressor, Form akSource, Projectile akProjectile, bool abPowerAttack, bool abSneakAttack, bool abBashAttack, bool abHitBlocked) If (Player.IsInCombat() == True) && (Player.GetActorValuePercentage("Health") <= HealthThreshold_AutoT.GetValue()) && (Player.GetCombatTarget().GetLevel() >= (TargetLvlMult_AutoT.GetValue() * Player.GetLevel())) && (Player.GetCurrentLocation() != WhiterunJorrvaskrLocation) && (Player.IsDead() == False) && (Utility.RandomFloat(1.0, 100.0) <= RandomChance_AutoT.GetValue()) BerserkerArmorBeastChange.Cast(Player) Else Return EndIf EndEvent Event OnUnequipped(Actor akActor) akActor.RemoveSpell(BerserkerArmorBeastChange) If (Berserk_Quest_Loose_Control as Berserk_Loose_Control_Script) LC_system_active = False EndIf EndEvent 3. Berserk_RefAlias_Playerreplacement_ScriptThis script is a ref alias for the player replacement when he/she's losing control and being replaced by the NPC replacer. Scriptname Berserk_RefAlias_Playerreplacement_Script extends ReferenceAlias Actor Property PlayerRef auto Quest Property Berserk_Quest_Loose_Control auto Formlist Property WornAmmoList Auto ;this list starts out empty, gets filled as ammo is equipped by the player ;must be placed in ref alias script for lost control script Event OnObjectEquipped(Form akBaseObject, ObjectReference akReference) If akBaseObject as Ammo WornAmmoList.AddForm(akBaseObject) EndIf EndEvent Event OnDying(Actor akKiller) (Berserk_Quest_Loose_Control as Berserk_Loose_Control_Script).player_replacement_was_killed((self.GetReference()) as actor, akKiller) EndEvent Event OnHit(ObjectReference akAggressor, Form akSource, Projectile akProjectile, bool abPowerAttack, bool abSneakAttack, bool abBashAttack, bool abHitBlocked) utility.wait(0.1) (Berserk_Quest_Loose_Control as Berserk_Loose_Control_Script).update_player_health() EndEvent Event OnDetachedFromCell() (Berserk_Quest_Loose_Control as Berserk_Loose_Control_Script).update_player_pos() EndEvent 4. Berserk_Effect_Warningspell_ScriptThis script is for warning spell which will be casted when the player is about to lose control. Scriptname Berserk_Effect_Warningspell_Script extends ActiveMagicEffect Actor Property PlayerREF Auto ;GlobalVariable Property Berserk_Config_LC_Warning Auto ;already covered by Berserk_Config_Moral_Warningtime exists in lose control script & MCM script GlobalVariable Property Berserk_Comp_Dawnguard Auto GlobalVariable Property Berserk_Config_Sounds Auto Sound Property UIHealthHeartbeatALPSD Auto ;switch to something more suitable, such as heartbeat sound Sound Property UIHealthHeartbeatBLPSD Auto ;switch to something more suitable, such as heartbeat sound Spell Property Berserk_Spell_Warningspell Auto MagicEffect Property Berserk_Effect_Warningspell Auto ImageSpaceModifier Property DA10HauntingISMDFadeIn Auto ImageSpaceModifier Property DA10HauntingISMDLoop Auto ImageSpaceModifier DLC1AurielsEclipseImod01 ImageSpaceModifier Property WerewolfWarningImod Auto ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;Events ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Event OnInit() Actor TargetLock = GetTargetActor() If (TargetLock == None) TargetLock.dispelspell(Berserk_Spell_Warningspell) Return ElseIF (TargetLock == PlayerREF) RegisterForSingleUpdate(5) Else TargetLock.dispelspell(Berserk_Spell_Warningspell) Return EndIf EndEvent ;State Running Event OnUpdate() ;Dawnguard DLC If Berserk_Comp_Dawnguard.GetValueInt() == 1 DLC1AurielsEclipseImod01 = Game.GetFormFromFile(0x02003DCD, "Dawnguard.esm") as ImageSpaceModifier Else DLC1AurielsEclipseImod01 = WerewolfWarningImod EndIf ;End of Dawnguard DLC DA10HauntingISMDFadeIn.ApplyCrossFade(12.0) Sounds() If !PlayerREF.HasMagicEffect(Berserk_Effect_Warningspell) Remove_Imods() Return EndIf Sounds() If !PlayerREF.HasMagicEffect(Berserk_Effect_Warningspell) Remove_Imods() Return EndIf Sounds() If !PlayerREF.HasMagicEffect(Berserk_Effect_Warningspell) Remove_Imods() Return EndIf DA10HauntingISMDLoop.ApplyCrossFade(16.0) Sounds() If !PlayerREF.HasMagicEffect(Berserk_Effect_Warningspell) Remove_Imods() Return EndIf Sounds() If !PlayerREF.HasMagicEffect(Berserk_Effect_Warningspell) Remove_Imods() Return EndIf Sounds() If !PlayerREF.HasMagicEffect(Berserk_Effect_Warningspell) Remove_Imods() Return EndIf Sounds() If !PlayerREF.HasMagicEffect(Berserk_Effect_Warningspell) Remove_Imods() Return EndIf RegisterForSingleUpdate(3) EndEvent Event OnEffectFinish(Actor akTarget, Actor akCaster) Remove_Imods() EndEvent ;EndState ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;Functions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Function Sounds() If !PlayerREF.HasMagicEffect(Berserk_Effect_Warningspell) Return EndIf Int RandomGrowlSound = Utility.RandomInt(1, 4) DLC1AurielsEclipseImod01.Remove() DLC1AurielsEclipseImod01.Apply() Game.ShakeCamera(afStrength = 1, afDuration = 2) UIHealthHeartbeatBLPSD.Play(PlayerREF) If RandomGrowlSound == 1 && Berserk_Config_Sounds.GetValueInt() == 1 Int SoundID1 = UIHealthHeartbeatALPSD.Play(PlayerREF) Sound.SetInstanceVolume(SoundID1, 0.5) EndIf Utility.Wait(4) EndFunction Function Remove_Imods() DA10HauntingISMDFadeIn.Remove() DA10HauntingISMDLoop.Remove() DLC1AurielsEclipseImod01.Remove() Utility.Wait(5) DA10HauntingISMDFadeIn.Remove() DA10HauntingISMDLoop.Remove() DLC1AurielsEclipseImod01.Remove() EndFunction I still have additional script to add kill skill gain feature, but it's still on the plan so i can't upload it yet. Currently, i'm still wondering whether i have put function Initialise() and TransformBack() from Berserk_Loose_Control_Script properly. Initialise() acts as an "Start" button for lose control system,and TransformBack() acts as "Stop" button.I really hope that you can check on these and give me feedbacks or corrections if necessary. Thanks in advance. :smile: Edited January 27, 2019 by qwertypol012 Link to comment Share on other sites More sharing options...
Evangela Posted January 27, 2019 Share Posted January 27, 2019 I wondering what this is supposed to mean: Cell.size == 4096 < 10000/sqrt(2) Link to comment Share on other sites More sharing options...
ReDragon2013 Posted January 28, 2019 Share Posted January 28, 2019 (edited) At first let us make clear the dependencies and scripting order. (1) SCRBerserkArmorCheckIfSet, renamed asqlBerserk_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" ; -- EVENTs -- 1 + "Waiting" 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 - 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 ;--------------------- (myQuest as qlBerserk_QuestScript).myF_Init(akActor, TRUE) ENDEVENT EVENT OnUnequipped(Actor akActor) IF (myQuest as qlBerserk_QuestScript) ELSE RETURN ; - STOP - ENDIF ;--------------------- (myQuest as qlBerserk_QuestScript).myF_Init(akActor, False) ENDEVENT ;======= endState As you can see I removed some code to make it more clean. I wonder if the OnHit() event would be triggered for this armor script. (2) Berserk_Effect_Warningspell_Script, renamed asqlBerserk_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 max. three times inside RETURN ; - STOP - ENDIF ;--------------------- IF myF_IsEffectGone(DA10HauntingISMDLoop, 16.0) ; wait max. four times inside 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.ApplyCrossFade(f) int i = (f / 4.0) as Int ; i 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 - ENDIF ;--------------------- bReady = False gotoState("") ; ### STATE ### DA10HauntingISMDFadeIn.Remove() DA10HauntingISMDLoop.Remove() IF ( DLC1AurielsEclipseImod01 ) DLC1AurielsEclipseImod01.Remove() ENDIF ENDFUNCTION ;------------------ FUNCTION myF_Play() ;------------------ DLC1AurielsEclipseImod01.Remove() DLC1AurielsEclipseImod01.Apply() 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 I remove the OnInit() event and added instead the OnEffectStart() event, which is much more useful to take for ActiveMagicEffect scripts. (3) Berserk_RefAlias_Playerreplacement_Script, renamed as How much is this script used and for what RefAliases?qlBerserk_PlayerAliasScript Scriptname qlBerserk_PlayerAliasScript 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. GlobalVariable PROPERTY TargetLvlMult_AutoT auto GlobalVariable PROPERTY HealthThreshold_AutoT auto GlobalVariable PROPERTY RandomChance_AutoT auto Location PROPERTY WhiterunJorrvaskrLocation auto Quest myQuest ;Formlist PROPERTY WornAmmoList auto ; must be placed here for lost control script, starts out empty ; -- EVENTs -- 5 + "Busy" EVENT OnInit() myQuest = self.GetOwningQuest() ENDEVENT EVENT OnDetachedFromCell() ; no idea whether this will be triggered within a playerAlias script !! IF (myQuest as qlBerserk_QuestScript) ELSE RETURN ; - STOP - ENDIF ;--------------------- (myQuest as qlBerserk_QuestScript).update_player_pos() ENDEVENT EVENT OnDying(Actor akKiller) IF (myQuest as qlBerserk_QuestScript) ELSE RETURN ; - STOP - ENDIF ;--------------------- (myQuest as qlBerserk_QuestScript).player_replacement_was_killed(self.GetActorReference(), akKiller) ENDEVENT EVENT OnHit(ObjectReference akAggressor, Form akSource, Projectile akProj, Bool b1, Bool b2, Bool b3, Bool b4) actor player = self.GetActorReference() IF !player.IsInCombat() || player.IsDead() RETURN ; - STOP - player is not in combat /or/ just dead ENDIF ;--------------------- IF (player.GetActorValuePercentage("Health") <= HealthThreshold_AutoT.GetValue()) RETURN ; - STOP - ENDIF ;--------------------- myF_Action(akAggressor, player) gotoState("Busy") ; ### STATE ### (myQuest as qlBerserk_QuestScript).update_player_health() gotoState("") ; ### STATE ### ENDEVENT ;EVENT OnObjectEquipped(Form akBaseObject, ObjectReference akReference) ;IF (akBaseObject as Ammo) ; WornAmmoList.AddForm(akBaseObject) ; gets filled as ammo is equipped by the player ;ENDIF ;ENDEVENT ;==================================== state Busy ; with hit action ;========= ;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) ENDEVENT ;======= endState ; -- FUNCTION -- ;------------------------------------------------------------- FUNCTION myF_Action(ObjectReference akAggressor, Actor player) ; internal helper ;------------------------------------------------------------- IF (player.GetCurrentLocation() == WhiterunJorrvaskrLocation) RETURN ; - STOP - player is in special location, brawl possible ENDIF ;--------------------- IF (akAggressor as Actor) ELSE RETURN ; - STOP - player was hit by non-actor, could be happens ENDIF ;--------------------- IF ((akAggressor as Actor).GetLevel() < player.GetLevel() * TargetLvlMult_AutoT.GetValueInt()) RETURN ; - STOP - player level is higher then aggressor level ENDIF ;--------------------- IF (Utility.RandomInt(1, 100) > RandomChance_AutoT.GetValueInt()) RETURN ; - STOP - out of chance to cast spell ENDIF ;--------------------- BerserkerArmorBeastChange.Cast(player) Utility.Wait(0.1) ENDFUNCTION This is the right place for the OnHit() event code from armor script above. I cannot see any sense to use OnObjectEquipped() here. (4) Berserk_Loose_Control_Script, renamed asqlBerserk_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 ;------------------------------------------ FUNCTION myF_Init(Actor player, Bool bInit) ; external called by "qlBerserk_ArmorScript" only ;------------------------------------------ IF ( bInit ) player.AddSpell(BerserkerArmorBeastChange) player.EquipSpell(BerserkerArmorBeastChange, 2) ;;; BerserkerArmorBeastChange.Cast(akActor) ; maybe CAST would be better here Initialise() ELSE player.RemoveSpell(BerserkerArmorBeastChange) ENDIF 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 ; 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 ; .. cut here This quest script only with two functions, I believe there is still some work to make code inside more understandable. Some code of this is truly strange for me. Edited January 28, 2019 by ReDragon2013 Link to comment Share on other sites More sharing options...
qwertypol012 Posted January 29, 2019 Author Share Posted January 29, 2019 (edited) Well, i need to elaborate it (ie. your edited scripts) at first (that's a lot of new logics and conditions :sweat:, but that's good if it improve the scripts :laugh: ) ... I couldn't imagine such simple-looking scripts from me could become something more complex-looking :pinch: Anyway, you renamed the scripts with "qlxxxx". What does "ql" refer to btw? I also have some feedbacks to what you wrote above: 1. You asked: "How much is this script used and for what RefAliases?" and "I cannot see any sense to use OnObjectEquipped()". Berserk_RefAlias_Playerreplacement_Script or qlBerserk_PlayerAliasScript is only used for 1) calling function "player_replacement_was_killed" ie. if the player was killed during losing control, 2) updating the player health when the npc replacer is getting hit, 3) updating the player pos when the npc replacer goes too far (or enter a new cell i guess), 4) and to check if the player is equipping any ammo. Ammo equpping check is used by Berserk_Loose_Control_Script or qlBerserk_QuestScript for the function "copy_player_gears_to_replacement()", which is if the player is equipping any ammo then it will be added to the npc replacer when lose control is triggered. So yeah, that function is needed, and it's put in the ref alias script to check if the player is equipping any ammo. 2. You wrote: "This is the right place for the OnHit() event code from armor script above." I'm not sure if you've understood it correctly, but i just want to clarify that OnHit() in SCRBerserkArmorCheckIfSet is actually different with OnHit() in Berserk_RefAlias_Playerreplacement_Script. As the name of each script suggests, the first one is for the player, and the second one is for the NPC replacer. In other words, OnHit() in SCRBerserkArmorCheckIfSet runs when the player is getting hit (means that he/she is not losing control), while OnHit() in Berserk_RefAlias_Playerreplacement_Script runs when the NPC replacer (not the player) is getting hit (means that the player is losing control and hence is replaced by the NPC replacer) and then update the player's health based on the damage done to the NPC replacer. So i think we need 2 OnHit() events in separate scripts, right? 3. You wrote: "EVENT OnDetachedFromCell() ; no idea whether this will be triggered within a playerAlias script" This is the original event from the player replacement ref alias script of MTEO by ubuntufreakdragon, and it does seem to work for some reason. Though i also do have no clue about this anyway. But do note that the function "update_player_pos()" called by this event is also called within Berserk_Loose_Control_Script or qlBerserk_QuestScript by OnUpdate() and OnUpdateGameTime() events. So i guess those two also contribute to make it work. 4. You wrote: "Some code of this is truly strange for me." Which one do you mean? I do have an additional question: In the last edit, in Berserk_Loose_Control_Script, i tweaked MoralScore variable under Initialise() and Force_control_to_player() to set it into 0. So it's: MoralScore = 0 Is this necessary? I just want to restore it to zero so that it will be filled again when the lose control roll is running again. Edited January 29, 2019 by qwertypol012 Link to comment Share on other sites More sharing options...
ReDragon2013 Posted January 30, 2019 Share Posted January 30, 2019 ql is refering to your nickname "qwertypol012", keep in mind every script is stored in the same script folder.In case two moders use the same script name in their mods, only the script from last loaded mod (esp-file) will be used ingame. That would be a problem. You added "int MoralScore" as global script variable, not a good idea. Why? It is used as local function variable "float MoralScore", which makes really confusing. About hit event your are right, this can be triggered also in ObjectReference scripts.I need some time to update the scripts according to your explanation. You wrote: "Berserk_RefAlias_Playerreplacement_Script or qlBerserk_PlayerAliasScript is only used for .."My question was, how many RefAliases may have attached this script? Link to comment Share on other sites More sharing options...
qwertypol012 Posted January 30, 2019 Author Share Posted January 30, 2019 (edited) "In case two moders use the same script name in their mods, only the script from last loaded mod (esp-file) will be used ingame. That would be a problem."I see. You got a point. That nickname will really help. "You added "int MoralScore" as global script variable, not a good idea. Why? It is used as local function variable "float MoralScore", which makes really confusing."Uh, right. But it's actually remnants from your edited script of Berserk_Loose_Control_Script. You put "Int KillScore" as script variable, then put "float KillScore" as local function variable, then i renamed it to "MoralScore" and removed some math calculations from it, making it more simple since now it's purely calculated based on game stats, hence no need for additional values except from the used game stats and related variables.So, should it be a script variable or local function variable? But it's used by at least 2 functions, so will it work without it's set as script variable? "My question was, how many RefAliases may have attached this script?"I'm not sure if i understand your question properly, but i can only say that the player replacement ref alias script is only meant for the npc replacer. If it doesn't bother you, mind to explain to me a bit about RefAliases? I think i'll make some mistakes if i don't understand about RefAliases properly (i tried to read the article in creation kit website but it's a bit complicated, a bit unfathomable for me). Btw, i actually has a player ref alias script which currently only serves as a mean to give severe damage to the player when he's "overtransform". Here's the script: Scriptname Berserk_PlayerAliasScript extends ReferenceAlias {must be set as ref alias script for a quest script other than lost control script} Actor Property PlayerRef Auto MagicEffect Property BerserkArmorBeastTDanger Auto Spell Property BerserkerSelfRepairDangerous Auto Event OnHit(ObjectReference akAggressor, Form akSource, Projectile akProjectile, bool abPowerAttack, bool abSneakAttack, bool abBashAttack, bool abHitBlocked) If (PlayerRef.HasMagicEffect(BerserkArmorBeastTDanger)) BerserkerSelfRepairDangerous.Cast(PlayerRef) Else Return EndIf EndEvent This also needs more explanations. In addition to everything i have written above (regarding the mod i'm trying to make), there are actually 2 kinds of transformation magic effect. The first one is normal transformation, and the second one is a dangerous transformation. Both are casted from a single spell (let's call it Transformation Spell), but with different conditions so that only one of them will be triggered whenever the spell is casted. As i have said earlier (or so i think), the transformations leave after effects which will be triggered whenever the transformation ends. They are negative effects from some magic effects which are casted from a spell. If you noticed in the loose control script (Berserk_Loose_Control_Script), there's "BerserkerLostControlAfterEffects" spell. This is the spell to cast these negative effects (let's call it "After-effects Spell"). These negative effects have durations and will wear off once the durations end. If the player cast the Transformation Spell after these negative effects end, then the player will be transformed normally (normal transformation). If the player cast the Transformation Spell while the negative effects still active, then the player will go into the dangerous transformation. Basically, the dangerous transformation is only a more severe version of normal transformation. A notable feature from dangerous transformation is that the player will get additional damage when he's hit. To make it work, i had to make a script which does just this, and that's the script i posted above. Actually, i'm still not sure where should i attach this script. The only thing i know is that it's different from the player replacement alias, so maybe i need to put it in a different quest script? But no clue if it can actually be simplified or included in any existing scripts. Additonal notes:To make things clearer (if it's still unclear), the lose control feature only runs when the player is in combat (i already set the condition in the lose control script). On top of that, there are also 3 additional conditions, and either 1 of them must be filled in order for lose control to run: 1) player has Transformation Spell (in other words, the player is wearing the armor, ie. the spell is added via the armor), 2) player is under normal transformation, or 3) player is under dangerous transformation.What i really want to achieve from this is that, the lose control feature should work in ANY conditions (but only in combat), as long as the player is wearing the armor or he/she is being transformed. Note that when the player is being transformed, he/she will not wear the armor (it will be force-unequipped because the player will be force-equipped with other gears which replace the armor), so i need to put both transformation conditions on top of wearing the armor (a.k.a has the spell) condition. TLDR, here's a basic simulation/scheme which summarizes all of above explanations: Player wears the Armor => Transformation Spell added to PlayerPlayer cast Transformation Spell => Player enter a Transformation state => Armor unequipped from Player, Armor2 equipped to Player Transformation state:1. Normal => casted after duration3 end2. Dangerous => casted when duration3 still run When Player is in Transformation state & if Player is in combat => has chance to Lose Control If Lose Control is not triggered => Transformation state continues until its duration1 endIf 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 endAfter 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 TransformationAfter 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 I'll also post any additional scripts related to these functionalities (just in case if they're necessary):1. qlBerserk_TransformScriptThis is the script for Transformation Spell. Attached to both Normal Transformation and Dangerous Transformation magic effects. Scriptname qlBerserk_TransformScript extends ActiveMagicEffect {Berserker Armor transformation} Actor Property PlayerRef Auto Actor Property PlayerEquipmentBrsk Auto Armor Property ArmorBerserkerCuirass Auto Armor Property ArmorBerserkerBoots Auto Armor Property ArmorBerserkerWCuirass Auto Armor Property ArmorBerserkerWBoots Auto Armor Property ArmorBerserkerGauntlets Auto Armor Property ArmorBerserkSHelmet Auto Armor Property ArmorBerserkerWCuirass2 Auto Armor Property ArmorBerserkerWBoots2 Auto Armor Property ArmorBerserkerGauntlets2 Auto Armor Property ArmorBerserkWHelmet Auto EffectShader Property Deintegrate Auto Explosion Property FXVampChangeExplosion Auto Idle Property IdleVampireLordTransformation Auto SPELL Property BerserkerArmorBeastChange Auto SPELL Property BerserkerArmorRevertForm Auto bool bRemoveGhost ;bool abIsGhost Event OnEffectStart(Actor akTarget, Actor akCaster) ; Actor Player = Game.GetPlayer() if PlayerRef.IsEquipped(ArmorBerserkerCuirass) && PlayerRef.IsEquipped(ArmorBerserkerBoots) if akTarget.IsGhost() bRemoveGhost = 0 else bRemoveGhost = 1 akTarget.GetActorBase().SetInvulnerable() akTarget.SetGhost() endif ; if abIsGhost == false ; akTarget.SetGhost() ; endif RegisterForAnimationEvent(akTarget, "SetRace") akTarget.PlayIdle(IdleVampireLordTransformation) akTarget.RestoreActorValue("health", 5000) Utility.Wait(10) TransformIfNecessary(akTarget) ; if (akTarget.GetWornForm(0x00000008) != none) ; Debug.Messagebox("Gauntlets are equipped") ; else ; Debug.MessageBox("Gauntlets are not equipped or something is wrong") ; endif ; check if gauntlets are being worn or not, then add and equip them to the dummy if they are if (akTarget.GetWornForm(0x00000008) != None) Armor Gauntlets = aktarget.GetWornForm(0x00000008) as Armor PlayerEquipmentBrsk.AddItem(Gauntlets, absilent=true) PlayerEquipmentBrsk.EquipItem(Gauntlets, 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 if (akTarget.GetWornForm(0x00000003) != None) Armor HeadHair = aktarget.GetWornForm(0x00000003) as Armor PlayerEquipmentBrsk.AddItem(HeadHair, absilent=true) PlayerEquipmentBrsk.EquipItem(HeadHair, 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 if (akTarget.GetWornForm(0x00000001) != None) Armor Head = aktarget.GetWornForm(0x00000001) as Armor PlayerEquipmentBrsk.AddItem(Head, absilent=true) PlayerEquipmentBrsk.EquipItem(Head, 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 if (akTarget.GetWornForm(0x00000002) != None) Armor Hair = aktarget.GetWornForm(0x00000002) as Armor PlayerEquipmentBrsk.AddItem(Hair, absilent=true) PlayerEquipmentBrsk.EquipItem(Hair, 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()) akTarget.EquipItem(ArmorBerserkerWBoots2, true, true) akTarget.EquipItem(ArmorBerserkerWCuirass2, true, true) akTarget.EquipItem(ArmorBerserkerGauntlets2, true, true) akTarget.EquipItem(ArmorBerserkWHelmet, true, true) aktarget.AddSpell(BerserkerArmorRevertForm) aktarget.RemoveSpell(BerserkerArmorBeastChange) else Dispel() endif EndEvent Event OnAnimationEvent(ObjectReference akSource, string asEventName) ; Debug.Trace("VAMPIRE: Getting anim event -- " + akSource + " " + asEventName) if (asEventName == "SetRace") TransformIfNecessary(akSource as Actor) endif EndEvent Function TransformIfNecessary(Actor akTarget) if (akTarget == None) return endif UnRegisterForAnimationEvent(akTarget, "SetRace") akTarget.placeatme(FXVampChangeExplosion) if bRemoveGhost = 1 akTarget.GetActorBase().SetInvulnerable(false) akTarget.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 Event OnEffectFinish(Actor akTarget, Actor akCaster) RevertForm(PlayerRef) EndEvent Function RevertForm(Actor akTarget) Deintegrate.Play(akTarget) utility.wait(2.0) akTarget.UnEquipItem(ArmorBerserkerWBoots2, false, true) akTarget.UnEquipItem(ArmorBerserkerWCuirass2, false, true) akTarget.UnEquipItem(ArmorBerserkerGauntlets2, false, true) akTarget.UnEquipItem(ArmorBerserkWHelmet, false, true) akTarget.EquipItem(ArmorBerserkerCuirass, false, true) akTarget.EquipItem(ArmorBerserkerBoots, false, true) ;check if gauntlets are being worn or not if (PlayerEquipmentBrsk.GetWornForm(0x00000008) != None) Armor Gauntlets = PlayerEquipmentBrsk.GetWornForm(0x00000008) as Armor akTarget.EquipItem(Gauntlets, false, true) endif ;check if a full head helmet is being worn or not if (PlayerEquipmentBrsk.GetWornForm(0x00000003) != None) Armor HeadHair = PlayerEquipmentBrsk.GetWornForm(0x00000003) as Armor akTarget.EquipItem(HeadHair, false, true) endif ;check if a head only helmet is being worn or not if (PlayerEquipmentBrsk.GetWornForm(0x00000001) != None) Armor Head = PlayerEquipmentBrsk.GetWornForm(0x00000001) as Armor akTarget.EquipItem(Head, false, true) endif ;check if a hair only helmet is being worn or not if (PlayerEquipmentBrsk.GetWornForm(0x00000002) != None) Armor Hair = PlayerEquipmentBrsk.GetWornForm(0x00000002) as Armor akTarget.EquipItem(Hair, false, true) endif PlayerEquipmentBrsk.RemoveAllItems() ;Checking if it did remove them again ; PlayerEquipmentBrsk.MoveTo(Game.GetPlayer()) aktarget.AddSpell(BerserkerArmorBeastChange) aktarget.EquipSpell(BerserkerArmorBeastChange, 2) Deintegrate.Stop(akTarget) aktarget.RemoveSpell(BerserkerArmorRevertForm) akTarget.RemoveItem(ArmorBerserkerWBoots, abSilent=true) akTarget.RemoveItem(ArmorBerserkerWBoots2, abSilent=true) akTarget.RemoveItem(ArmorBerserkerWCuirass, abSilent=true) akTarget.RemoveItem(ArmorBerserkerWCuirass2, abSilent=true) akTarget.RemoveItem(ArmorBerserkerGauntlets, abSilent=true) akTarget.RemoveItem(ArmorBerserkerGauntlets2, abSilent=true) akTarget.RemoveItem(ArmorBerserkSHelmet, abSilent=true) akTarget.RemoveItem(ArmorBerserkWHelmet, abSilent=true) EndFunction 2. qlBerserk_RevertFormScriptThis is the script to revert form. It's attached to a magic effect which will be triggered from Revert Form Spell. This spell is added after Player entered a Transformation state (see qlBerserk_TransformScript). This script calls RevertForm function from qlBerserk_TransformScript. It also force control Player when he/she is Losing Control. Scriptname qlBerserk_RevertFormScript extends ActiveMagicEffect {Berserker Armor revert form} Quest Property Berserk_Quest Auto MagicEffect Property BerserkArmorBeastT Auto MagicEffect Property BerserkArmorBeastTDanger Auto qlBerserk_TransformScript Property BerserkArmorBeastT Auto qlBerserk_TransformScript Property BerserkArmorBeastTDanger Auto GlobalVariable Property Berserk_Moral_Transformed Auto Event OnEffectStart(Actor akTarget, Actor akCaster) Actor Player = Game.GetPlayer() If Player.HasMagicEffect(BerserkArmorBeastT) (BerserkArmorBeastT as qlBerserk_TransformScript).RevertForm(Player) ElseIF Player.HasMagicEffect(BerserkArmorBeastTDanger) (BerserkArmorBeastTDanger as qlBerserk_TransformScript).RevertForm(Player) ElseIf Berserk_Moral_Transformed.GetValueInt() == 1 (Berserk_Quest as qlBerserk_QuestScript).TransformBack() Else Return EndIf EndEvent 3. Other scripts which manage transformation conditions and related stuff: qlMETransformManagerScript(attached to the main transformation magic effect which will trigger either Normal or Dangerous transformation) Scriptname qlMETransformManagerScript extends ActiveMagicEffect {defines global values for Berserker Armor transformation magic effects to correctly run under their own conditions} ; https://forums.nexusmods.com/index.php?/topic/7285811-how-to-script-2-magic-effects-with-different-conditions-and-they-nullify-each-other/ ; List of all Magic Effects need to be managed: ; BerserkerArmorBeastT (main transformation, nullify below) METransform 1 ; BerserkerArmorBeastTDanger (secondary transformation, nullify above) METransform 2 ; BerserkerDamageHealRate (casted after BerserkerArmorBeastT worn off) MEValueDefiner 1 ; BerserkerDamageMagickaRate (casted after BerserkerArmorBeastT worn off) MEValueDefiner 1 ; BerserkerDamageStaminaRate (casted after BerserkerArmorBeastT worn off) MEValueDefiner 1 ; BerserkerDamageHealth (casted after BerserkerArmorBeastT worn off) MEValueDefiner 1 ; BerserkerDamageMagicka (casted after BerserkerArmorBeastT worn off) MEValueDefiner 1 ; BerserkerDamageStamina (casted after BerserkerArmorBeastT worn off) MEValueDefiner 1 ; BerserkerDebuffLongTerm1 (casted after BerserkerArmorBeastT worn off) MEValueDefiner 1 ; BerserkerDebuffLongTerm2 (casted after BerserkerArmorBeastT worn off) MEValueDefiner 1 ; BerserkerDamageHealthDanger (casted when BerserkerArmorBeastTDanger is active) ; BerserkerDebuffLongTerm1b (casted after BerserkerArmorBeastT worn off) MEValueDefiner 1 ; BerserkerDebuffLongTerm2b (casted after BerserkerArmorBeastT worn off) MEValueDefiner 1 ; -- PROPERTIES -- GlobalVariable Property MEValueDefiner Auto ;its value defines what MEs are active GlobalVariable Property METransform Auto ;to check which one of normal transformation and dangerous transformation is active ; -- EVENTs -- EVENT OnEffectStart(Actor akTarget, Actor akCaster) METransformCheck() ENDEVENT ;EVENT OnEffectFinish(Actor akTarget, Actor akCaster) ; METransform.SetValue(0) ;player is no more transformed ;ENDEVENT ; -- FUNCTIONs -- ;----------------------- FUNCTION METransformCheck() ;----------------------- IF MEValueDefiner.GetValueInt() == 0 METransform.SetValue(1) ;player is transformed normally ENDIF IF MEValueDefiner.GetValueInt() == 1 METransform.SetValue(2) ;player is transformed dangerously ENDIF ENDFUNCTION qlMEBerserkerTransformScript(attached to Normal Transformation magic effect) Scriptname qlMEBerserkerTransformScript extends ActiveMagicEffect {defines global value for Magic Effect BerserkerArmorBeastT to active} ; https://forums.nexusmods.com/index.php?/topic/7285811-how-to-script-2-magic-effects-with-different-conditions-and-they-nullify-each-other/ ; -- PROPERTIES -- GlobalVariable Property METransform Auto ;to check which one of normal transformation and dangerous transformation is active GlobalVariable Property MEValueDefiner Auto ;its value defines what MEs are active ; -- EVENTs -- ;EVENT OnEffectStart(Actor akTarget, Actor akCaster) ;IF METransform.GetValueInt() != 1 ; METransform.SetValue(1) ;player is transformed normally ;ENDIF ;ENDEVENT EVENT OnEffectFinish(Actor akTarget, Actor akCaster) MEValueDefiner.SetValue(1) ;set the value to activate damage attributes and debuffs ENDEVENT qlMEBerserkerTransformDangerScript(attached to Dangerous Transformation magic effect) Scriptname qlMEBerserkerTransformDangerScript extends ActiveMagicEffect {defines global value for Magic Effect BerserkerArmorBeastTDanger to active} ; https://forums.nexusmods.com/index.php?/topic/7285811-how-to-script-2-magic-effects-with-different-conditions-and-they-nullify-each-other/ ; -- PROPERTIES -- GlobalVariable Property METransform Auto ;to check which one of normal transformation and dangerous transformation is active GlobalVariable Property MEValueDefiner Auto ;its value defines what MEs are active ; -- EVENTs -- ;EVENT OnEffectStart(Actor akTarget, Actor akCaster) ;IF METransform.GetValueInt() != 2 ; METransform.SetValue(2) ;player is transformed dangerously ;ENDIF ;ENDEVENT EVENT OnEffectFinish(Actor akTarget, Actor akCaster) MEValueDefiner.SetValue(1) ;set the value to activate damage attributes and debuffs ENDEVENT qlMENegativeEffectsScript(attached to a Negative Effect magic effect) Scriptname qlMENegativeEffectsScript extends ActiveMagicEffect {defines global value for all negative magic effects to active} ; https://forums.nexusmods.com/index.php?/topic/7285811-how-to-script-2-magic-effects-with-different-conditions-and-they-nullify-each-other/ ; -- PROPERTIES -- GlobalVariable Property METransform Auto ;to check which one of normal transformation and dangerous transformation is active GlobalVariable Property MEValueDefiner Auto ;its value defines what MEs are active ; -- EVENTs -- ;EVENT OnEffectStart(Actor akTarget, Actor akCaster) ;IF MEValueDefiner.GetValueInt() != 1 ; MEValueDefiner.SetValue(1) ;set the value to activate damage attributes and debuffs ;ENDIF ;ENDEVENT EVENT OnEffectFinish(Actor akTarget, Actor akCaster) MEValueDefiner.SetValue(0) ;set the value to deactivate damage attributes and debuffs ENDEVENT Edited January 30, 2019 by qwertypol012 Link to comment Share on other sites More sharing options...
Recommended Posts