Manage combat music with a quest, removed _00E_CombatSoundtrackScript from 800+ objects

This commit is contained in:
Eddoursul 2024-01-15 02:47:42 +01:00
parent e15bec3672
commit fbbf0bd7f7
11 changed files with 114 additions and 53 deletions

Binary file not shown.

BIN
SKSE/Plugins/EnderalSE.dll (Stored with Git LFS)

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -12,6 +12,7 @@ void EventListener::Install()
//RE::ScriptEventSourceHolder::GetSingleton()->AddEventSink<RE::TESContainerChangedEvent>(EventListener::GetSingleton()); //RE::ScriptEventSourceHolder::GetSingleton()->AddEventSink<RE::TESContainerChangedEvent>(EventListener::GetSingleton());
RE::UI::GetSingleton()->AddEventSink<RE::MenuOpenCloseEvent>(EventListener::GetSingleton()); RE::UI::GetSingleton()->AddEventSink<RE::MenuOpenCloseEvent>(EventListener::GetSingleton());
SKSE::GetModCallbackEventSource()->AddEventSink(EventListener::GetSingleton()); SKSE::GetModCallbackEventSource()->AddEventSink(EventListener::GetSingleton());
RE::ScriptEventSourceHolder::GetSingleton()->GetEventSource<RE::TESCombatEvent>()->AddEventSink(EventListener::GetSingleton());
} }
auto EventListener::ProcessEvent( auto EventListener::ProcessEvent(
@ -75,3 +76,26 @@ auto EventListener::ProcessEvent(
return RE::BSEventNotifyControl::kContinue; return RE::BSEventNotifyControl::kContinue;
} }
auto EventListener::ProcessEvent(
const RE::TESCombatEvent* a_event,
RE::BSTEventSource<RE::TESCombatEvent>* a_eventSource)
-> RE::BSEventNotifyControl
{
if (!a_event) {
return RE::BSEventNotifyControl::kContinue;
}
RE::Actor* sourceActor = a_event->actor ? a_event->actor->As<RE::Actor>() : nullptr;
if (!sourceActor) {
return RE::BSEventNotifyControl::kContinue;
}
RE::Actor* targetActor = a_event->targetActor ? a_event->targetActor->As<RE::Actor>() : nullptr;
SKSE::ModCallbackEvent modEvent{ "Enderal_CombatStateChanged", targetActor && targetActor->IsPlayerRef() ? "1" : "", a_event->newState.underlying(), sourceActor };
SKSE::GetModCallbackEventSource()->SendEvent(&modEvent);
return RE::BSEventNotifyControl::kContinue;
}

View File

@ -9,7 +9,8 @@ class EventListener :
public RE::BSTEventSink<SKSE::ModCallbackEvent>, public RE::BSTEventSink<SKSE::ModCallbackEvent>,
public RE::BSTEventSink<RE::TESContainerChangedEvent>, public RE::BSTEventSink<RE::TESContainerChangedEvent>,
public RE::BSTEventSink<RE::MenuOpenCloseEvent>, public RE::BSTEventSink<RE::MenuOpenCloseEvent>,
public RE::BSTEventSink<RE::TESActivateEvent> public RE::BSTEventSink<RE::TESActivateEvent>,
public RE::BSTEventSink<RE::TESCombatEvent>
{ {
public: public:
~EventListener() = default; ~EventListener() = default;
@ -26,7 +27,6 @@ public:
RE::BSTEventSource<RE::TESContainerChangedEvent>* a_eventSource) RE::BSTEventSource<RE::TESContainerChangedEvent>* a_eventSource)
-> RE::BSEventNotifyControl override; -> RE::BSEventNotifyControl override;
auto ProcessEvent( auto ProcessEvent(
const RE::MenuOpenCloseEvent* a_event, const RE::MenuOpenCloseEvent* a_event,
RE::BSTEventSource<RE::MenuOpenCloseEvent>* a_eventSource) RE::BSTEventSource<RE::MenuOpenCloseEvent>* a_eventSource)
@ -42,6 +42,11 @@ public:
RE::BSTEventSource<RE::TESActivateEvent>* a_eventSource) RE::BSTEventSource<RE::TESActivateEvent>* a_eventSource)
-> RE::BSEventNotifyControl override; -> RE::BSEventNotifyControl override;
auto ProcessEvent(
const RE::TESCombatEvent* a_event,
RE::BSTEventSource<RE::TESCombatEvent>* a_eventSource)
-> RE::BSEventNotifyControl override;
private: private:
EventListener() = default; EventListener() = default;
}; };

View File

@ -103,6 +103,25 @@ namespace Papyrus::PapyrusFunctions
return ComputeNeededExpPoints(CurrentLevel, Slope, Mult, fExpAcc, fExpAcc_Level20, fExpAcc_Level30, fExpAcc_Level40); 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) inline void Bind(VM& a_vm)
{ {
BIND(CreatePotion); BIND(CreatePotion);
@ -123,5 +142,7 @@ namespace Papyrus::PapyrusFunctions
logger::info("{}", "Registered EnableDialogueQuitting"sv); logger::info("{}", "Registered EnableDialogueQuitting"sv);
BIND(ComputeNeededExp); BIND(ComputeNeededExp);
logger::info("{}", "Registered ComputeNeededExp"sv); logger::info("{}", "Registered ComputeNeededExp"sv);
BIND(IsInRegion);
logger::info("{}", "Registered IsInRegion"sv);
} }
} }

View File

@ -17,6 +17,8 @@ Event OnInit()
EndEvent EndEvent
Function InitCombatMusic() Function InitCombatMusic()
RegisterForModEvent("Enderal_CombatStateChanged", "OnCombatStateChange")
If ActiveCombatMusics.Length == 0 If ActiveCombatMusics.Length == 0
ActiveCombatMusics = _NewMusicArray() ActiveCombatMusics = _NewMusicArray()
EndIf EndIf
@ -30,6 +32,41 @@ Function InitCombatMusic()
EndIf EndIf
EndFunction 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) Bool Function StartCombatMusic(MusicType newMusic)
; Debug.Trace(self + ", StartCombatMusic, newMusic = " + newMusic) ; Debug.Trace(self + ", StartCombatMusic, newMusic = " + newMusic)
@ -95,11 +132,9 @@ State CombatMusicTracking
Event OnUpdate() Event OnUpdate()
; Debug.Trace("_00E_PlayerFunctions, OnUpdate")
RegisterForSingleUpdate(3.5) RegisterForSingleUpdate(3.5)
If (Game.GetForm(0x14) as Actor).IsInCombat() || CombatMusicLockLevel > COMBAT_MUSIC_LOCK_NONE If CombatMusicLockLevel > COMBAT_MUSIC_LOCK_NONE || PlayerRef.IsInCombat()
Return Return
EndIf EndIf
@ -170,4 +205,17 @@ Function RemoveCombatSoundtracks()
EndFunction 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_MUS_AllCombatSoundtracks Auto
FormList Property _00E_ActorsCombatMusicEpic Auto
Form Property Wueste Auto ; Powder Desert
Actor Property PlayerRef Auto

View File

@ -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

View File

@ -12,25 +12,26 @@ Actor[] function GetPlayerFollowers() native global
; Gets the player hash used to uniquely identify the player's save profile. ; Gets the player hash used to uniquely identify the player's save profile.
; RETURN - Returns the player hash as an 8-digit string. ; 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. ; Converts the given string to it's hexadecimal equivalent. Preserves case.
; a_string - The string to convert to hexadecimal. ; a_string - The string to convert to hexadecimal.
; RETURN - Returns the hexadecimal equivalent of the passed string. ; 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. ; Disables the TAB Key during dialogue. Resets automatically upon dialogue exit via Goodbye.
Function DisableDialogueQuitting() Global Native Function DisableDialogueQuitting() native global
Function EnableDialogueQuitting() Global Native Function EnableDialogueQuitting() native global
bool function IsInRegion(Form region) native global
bool function IsDLLLoaded() global bool function IsDLLLoaded() global
int iVer = SKSE.GetPluginVersion("EnderalSE") return SKSE.GetPluginVersion("EnderalSE") > 0
return iVer > 0
endfunction endfunction
String Function GetPlayerClassNameGlobal() Global String Function GetPlayerClassNameGlobal() global
{Called by EnderalSE.dll} {Called by EnderalSE.dll}
Quest AffinityQuest = Game.GetFormFromFile(0x1597B, "Enderal - Forgotten Stories.esm") as Quest Quest AffinityQuest = Game.GetFormFromFile(0x1597B, "Enderal - Forgotten Stories.esm") as Quest
return (AffinityQuest.GetAlias(0) as _00E_AffinityControl).GetPlayerClassName() return (AffinityQuest.GetAlias(0) as _00E_AffinityControl).GetPlayerClassName()