diff --git a/CombatMusicControl update.esp b/CombatMusicControl update.esp new file mode 100644 index 00000000..79012708 Binary files /dev/null and b/CombatMusicControl update.esp differ diff --git a/SKSE/Plugins/EnderalSE.dll b/SKSE/Plugins/EnderalSE.dll index 77d83cb7..d339a69d 100644 --- a/SKSE/Plugins/EnderalSE.dll +++ b/SKSE/Plugins/EnderalSE.dll @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7c3f64719f244c37e335b2029182b51bea05957a1636d1dedf7bf5a854403de6 -size 751616 +oid sha256:ca655e941a261df2f688427ef906c5bdd91cf3ce1d55cc262638fc15b4c582bb +size 757248 diff --git a/scripts/_00E_CombatMusicControl.pex b/scripts/_00E_CombatMusicControl.pex index 6bdafae2..d4fab48c 100644 Binary files a/scripts/_00E_CombatMusicControl.pex and b/scripts/_00E_CombatMusicControl.pex differ diff --git a/scripts/_00e_combatsoundtrackscript.pex b/scripts/_00e_combatsoundtrackscript.pex deleted file mode 100644 index 36da9b9c..00000000 Binary files a/scripts/_00e_combatsoundtrackscript.pex and /dev/null differ diff --git a/scripts/enderalfunctions.pex b/scripts/enderalfunctions.pex index 289e1f89..89990827 100644 Binary files a/scripts/enderalfunctions.pex and b/scripts/enderalfunctions.pex differ diff --git a/source/Enderal DLL/src/EventListener.cpp b/source/Enderal DLL/src/EventListener.cpp index f2fe11ee..4c672076 100644 --- a/source/Enderal DLL/src/EventListener.cpp +++ b/source/Enderal DLL/src/EventListener.cpp @@ -12,6 +12,7 @@ void EventListener::Install() //RE::ScriptEventSourceHolder::GetSingleton()->AddEventSink(EventListener::GetSingleton()); RE::UI::GetSingleton()->AddEventSink(EventListener::GetSingleton()); SKSE::GetModCallbackEventSource()->AddEventSink(EventListener::GetSingleton()); + RE::ScriptEventSourceHolder::GetSingleton()->GetEventSource()->AddEventSink(EventListener::GetSingleton()); } auto EventListener::ProcessEvent( @@ -75,3 +76,26 @@ auto EventListener::ProcessEvent( return RE::BSEventNotifyControl::kContinue; } + +auto EventListener::ProcessEvent( + const RE::TESCombatEvent* a_event, + RE::BSTEventSource* a_eventSource) + -> RE::BSEventNotifyControl +{ + if (!a_event) { + return RE::BSEventNotifyControl::kContinue; + } + + RE::Actor* sourceActor = a_event->actor ? a_event->actor->As() : nullptr; + + if (!sourceActor) { + return RE::BSEventNotifyControl::kContinue; + } + + RE::Actor* targetActor = a_event->targetActor ? a_event->targetActor->As() : nullptr; + + SKSE::ModCallbackEvent modEvent{ "Enderal_CombatStateChanged", targetActor && targetActor->IsPlayerRef() ? "1" : "", a_event->newState.underlying(), sourceActor }; + SKSE::GetModCallbackEventSource()->SendEvent(&modEvent); + + return RE::BSEventNotifyControl::kContinue; +} diff --git a/source/Enderal DLL/src/EventListener.h b/source/Enderal DLL/src/EventListener.h index 3edd03bb..be09e7ee 100644 --- a/source/Enderal DLL/src/EventListener.h +++ b/source/Enderal DLL/src/EventListener.h @@ -9,7 +9,8 @@ class EventListener : public RE::BSTEventSink, public RE::BSTEventSink, public RE::BSTEventSink, - public RE::BSTEventSink + public RE::BSTEventSink, + public RE::BSTEventSink { public: ~EventListener() = default; @@ -26,7 +27,6 @@ public: RE::BSTEventSource* a_eventSource) -> RE::BSEventNotifyControl override; - auto ProcessEvent( const RE::MenuOpenCloseEvent* a_event, RE::BSTEventSource* a_eventSource) @@ -42,6 +42,11 @@ public: RE::BSTEventSource* a_eventSource) -> RE::BSEventNotifyControl override; + auto ProcessEvent( + const RE::TESCombatEvent* a_event, + RE::BSTEventSource* a_eventSource) + -> RE::BSEventNotifyControl override; + private: EventListener() = default; }; \ No newline at end of file diff --git a/source/Enderal DLL/src/PapyrusFunctions.h b/source/Enderal DLL/src/PapyrusFunctions.h index 5797a4d5..c769242c 100644 --- a/source/Enderal DLL/src/PapyrusFunctions.h +++ b/source/Enderal DLL/src/PapyrusFunctions.h @@ -103,6 +103,25 @@ namespace Papyrus::PapyrusFunctions return ComputeNeededExpPoints(CurrentLevel, Slope, Mult, fExpAcc, fExpAcc_Level20, fExpAcc_Level30, fExpAcc_Level40); } + bool IsInRegion(RE::StaticFunctionTag*, RE::TESForm* playerRegion) + { + auto* parentCell = RE::PlayerCharacter::GetSingleton()->parentCell; + + if (!parentCell) { + return false; + } + + auto regions = parentCell->GetRegionList(false); + + for (auto it = regions->begin(); it != regions->end(); it++) { + if ((*it)->formID == playerRegion->formID) { + return true; + } + } + + return false; + } + inline void Bind(VM& a_vm) { BIND(CreatePotion); @@ -123,5 +142,7 @@ namespace Papyrus::PapyrusFunctions logger::info("{}", "Registered EnableDialogueQuitting"sv); BIND(ComputeNeededExp); logger::info("{}", "Registered ComputeNeededExp"sv); + BIND(IsInRegion); + logger::info("{}", "Registered IsInRegion"sv); } } diff --git a/source/scripts/_00E_CombatMusicControl.psc b/source/scripts/_00E_CombatMusicControl.psc index 7972993d..dff46ca3 100644 --- a/source/scripts/_00E_CombatMusicControl.psc +++ b/source/scripts/_00E_CombatMusicControl.psc @@ -17,6 +17,8 @@ Event OnInit() EndEvent Function InitCombatMusic() + RegisterForModEvent("Enderal_CombatStateChanged", "OnCombatStateChange") + If ActiveCombatMusics.Length == 0 ActiveCombatMusics = _NewMusicArray() EndIf @@ -30,6 +32,41 @@ Function InitCombatMusic() EndIf EndFunction +Event OnCombatStateChange(string eventName, string bTargetIsPlayer, float fCombatState, Form sender) + if bTargetIsPlayer ; start combat or searching + if fCombatState as int == 1 ; combat + ; start music + Actor sourceActor = sender as Actor + Int encounterLevel = sourceActor.GetLevel() + + If encounterLevel >= 20 || (encounterLevel >= PlayerLevel.GetValue() - 15) || HasKeyword(ActorTypeBoss) + MusicType combatMusic + if _00E_ActorsCombatMusicEpic.HasForm(sourceActor.GetActorBase()) + combatMusic = _00E_Music_Combat_Epic + elseif EnderalFunctions.IsInRegion(Wueste) + combatMusic = _00E_Music_Combat_Exotic + else + combatMusic = _00E_Music_Combat_Regular + endif + + if StartCombatMusic(combatMusic) + RegisterForSingleUpdate(5.0) + EndIf + EndIf + elseif ! PlayerRef.IsInCombat() + if GetState() == "" + GoToState("CombatMusicTracking") + endif + RegisterForSingleUpdate(2.0) + endif + elseif ! PlayerRef.IsInCombat() + if GetState() == "" + GoToState("CombatMusicTracking") + endif + RegisterForSingleUpdate(2.0) + endif +endEvent + Bool Function StartCombatMusic(MusicType newMusic) ; Debug.Trace(self + ", StartCombatMusic, newMusic = " + newMusic) @@ -95,11 +132,9 @@ State CombatMusicTracking Event OnUpdate() - ; Debug.Trace("_00E_PlayerFunctions, OnUpdate") - RegisterForSingleUpdate(3.5) - If (Game.GetForm(0x14) as Actor).IsInCombat() || CombatMusicLockLevel > COMBAT_MUSIC_LOCK_NONE + If CombatMusicLockLevel > COMBAT_MUSIC_LOCK_NONE || PlayerRef.IsInCombat() Return EndIf @@ -170,4 +205,17 @@ Function RemoveCombatSoundtracks() EndFunction +Keyword Property ActorTypeBoss Auto + +GlobalVariable Property PlayerLevel Auto + +MusicType Property _00E_Music_Combat_Regular Auto +MusicType Property _00E_Music_Combat_Exotic Auto +MusicType Property _00E_Music_Combat_Epic Auto + FormList Property _00E_MUS_AllCombatSoundtracks Auto +FormList Property _00E_ActorsCombatMusicEpic Auto + +Form Property Wueste Auto ; Powder Desert + +Actor Property PlayerRef Auto diff --git a/source/scripts/_00e_combatsoundtrackscript.psc b/source/scripts/_00e_combatsoundtrackscript.psc deleted file mode 100644 index 4842a383..00000000 --- a/source/scripts/_00e_combatsoundtrackscript.psc +++ /dev/null @@ -1,38 +0,0 @@ -Scriptname _00E_CombatSoundtrackScript extends Actor - -Event OnUpdate() - Actor player = Game.GetForm(0x14) as Actor - If player.IsInCombat() - RegisterForSingleUpdate(2.0) - ElseIf Triggered - Triggered = False - _00E_PlayerFunctions.GetCombatMusicControl().StopCombatMusic() - EndIf -EndEvent - -Event OnCombatStateChanged(Actor akTarget, int aeCombatState) - If !_00E_Music_Combat_Regular - Debug.Trace(self + ": _00E_Music_Combat_Regular property is empty") - Return - EndIf - - If aeCombatState == 1 - Actor player = Game.GetForm(0x14) as Actor - If akTarget == player - Int encounterLevel = GetLevel() - If encounterLevel >= 20 || (encounterLevel >= (PlayerLevel.GetValue() - 15)) || HasKeyword(ActorTypeBoss) ; Frage ab ob Gegnerstufe über Spielerstufe oder Boss ist, wenn ja spiele Combatmusic - If Triggered == False ; player.IsInCombat() && - Triggered = _00E_PlayerFunctions.GetCombatMusicControl().StartCombatMusic(_00E_Music_Combat_Regular) - If Triggered - RegisterForSingleUpdate(5.0) - EndIf - EndIf - EndIf - EndIf - EndIf -EndEvent - -MusicType Property _00E_Music_Combat_Regular Auto -GlobalVariable Property PlayerLevel Auto -Keyword Property ActorTypeBoss Auto -Bool Triggered = False diff --git a/source/scripts/enderalfunctions.psc b/source/scripts/enderalfunctions.psc index e10a564c..f1ba4c5e 100644 --- a/source/scripts/enderalfunctions.psc +++ b/source/scripts/enderalfunctions.psc @@ -12,25 +12,26 @@ Actor[] function GetPlayerFollowers() native global ; Gets the player hash used to uniquely identify the player's save profile. ; RETURN - Returns the player hash as an 8-digit string. -String Function GetPlayerHash() Global Native +String Function GetPlayerHash() native global ; Converts the given string to it's hexadecimal equivalent. Preserves case. ; a_string - The string to convert to hexadecimal. ; RETURN - Returns the hexadecimal equivalent of the passed string. -String Function StringToHex(String a_string) Global Native +String Function StringToHex(String a_string) native global -float function ComputeNeededExp(int CurrentLevel, float Slope, float Mult, float fExpAcc = 1.0, float fExpAcc_Level20 = 1.2, float fExpAcc_Level30 = 1.5, float fExpAcc_Level40 = 2.0) global native +float function ComputeNeededExp(int CurrentLevel, float Slope, float Mult, float fExpAcc = 1.0, float fExpAcc_Level20 = 1.2, float fExpAcc_Level30 = 1.5, float fExpAcc_Level40 = 2.0) native global ; Disables the TAB Key during dialogue. Resets automatically upon dialogue exit via Goodbye. -Function DisableDialogueQuitting() Global Native -Function EnableDialogueQuitting() Global Native +Function DisableDialogueQuitting() native global +Function EnableDialogueQuitting() native global + +bool function IsInRegion(Form region) native global bool function IsDLLLoaded() global - int iVer = SKSE.GetPluginVersion("EnderalSE") - return iVer > 0 + return SKSE.GetPluginVersion("EnderalSE") > 0 endfunction -String Function GetPlayerClassNameGlobal() Global +String Function GetPlayerClassNameGlobal() global {Called by EnderalSE.dll} Quest AffinityQuest = Game.GetFormFromFile(0x1597B, "Enderal - Forgotten Stories.esm") as Quest return (AffinityQuest.GetAlias(0) as _00E_AffinityControl).GetPlayerClassName()