Use TESHitEvent to track unlock spell hits

This commit is contained in:
Eddoursul 2024-01-15 05:01:05 +01:00
parent 3c1725cbcb
commit a43aa14bef
11 changed files with 110 additions and 177 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.

Binary file not shown.

Binary file not shown.

View File

@ -13,6 +13,7 @@ void EventListener::Install()
RE::UI::GetSingleton()->AddEventSink<RE::MenuOpenCloseEvent>(EventListener::GetSingleton());
SKSE::GetModCallbackEventSource()->AddEventSink(EventListener::GetSingleton());
RE::ScriptEventSourceHolder::GetSingleton()->GetEventSource<RE::TESCombatEvent>()->AddEventSink(EventListener::GetSingleton());
RE::ScriptEventSourceHolder::GetSingleton()->GetEventSource<RE::TESHitEvent>()->AddEventSink(EventListener::GetSingleton());
}
auto EventListener::ProcessEvent(
@ -99,3 +100,34 @@ auto EventListener::ProcessEvent(
return RE::BSEventNotifyControl::kContinue;
}
auto EventListener::ProcessEvent(
const RE::TESHitEvent* a_event,
RE::BSTEventSource<RE::TESHitEvent>* a_eventSource)
-> RE::BSEventNotifyControl
{
if (!a_event || !a_event->cause || a_event->cause->formID != 0x14) {
return RE::BSEventNotifyControl::kContinue;
}
RE::FormID spellFormID = a_event->projectile ? a_event->projectile : a_event->source;
RE::TESObjectREFR* containerRef = a_event->target ? a_event->target->As<RE::TESObjectREFR>() : nullptr;
if (!containerRef || !spellFormID) {
return RE::BSEventNotifyControl::kContinue;
}
RE::TESBoundObject* baseObject = containerRef->GetBaseObject();
if (baseObject && (baseObject->Is(RE::FormType::Container) || baseObject->Is(RE::FormType::Door)) && containerRef->IsLocked()) {
auto* dataHandler = RE::TESDataHandler::GetSingleton();
const RE::BGSListForm* formList = dataHandler ? dataHandler->LookupForm<RE::BGSListForm>(0x44EE4, "Skyrim.esm") : nullptr;
if (formList && formList->HasForm(spellFormID)) {
SKSE::ModCallbackEvent modEvent{ "Enderal_UnlockSpellHit", "", spellFormID, containerRef };
SKSE::GetModCallbackEventSource()->SendEvent(&modEvent);
}
}
return RE::BSEventNotifyControl::kContinue;
}

View File

@ -10,7 +10,8 @@ class EventListener :
public RE::BSTEventSink<RE::TESContainerChangedEvent>,
public RE::BSTEventSink<RE::MenuOpenCloseEvent>,
public RE::BSTEventSink<RE::TESActivateEvent>,
public RE::BSTEventSink<RE::TESCombatEvent>
public RE::BSTEventSink<RE::TESCombatEvent>,
public RE::BSTEventSink<RE::TESHitEvent>
{
public:
~EventListener() = default;
@ -47,6 +48,11 @@ public:
RE::BSTEventSource<RE::TESCombatEvent>* a_eventSource)
-> RE::BSEventNotifyControl override;
auto ProcessEvent(
const RE::TESHitEvent* a_event,
RE::BSTEventSource<RE::TESHitEvent>* a_eventSource)
-> RE::BSEventNotifyControl override;
private:
EventListener() = default;
};

View File

@ -1,77 +0,0 @@
Scriptname _00E_ClosedChestAlias extends ReferenceAlias
Int Property LOCK_LEVEL_NOVICE = 1 AutoReadOnly
Int Property LOCK_LEVEL_APPRENTICE = 25 AutoReadOnly
Int Property LOCK_LEVEL_ADEPT = 50 AutoReadOnly
Int Property LOCK_LEVEL_EXPERT = 75 AutoReadOnly
Int Property LOCK_LEVEL_MASTER = 254 AutoReadOnly
Event OnHit(ObjectReference akAggressor, Form akSource, Projectile akProjectile, bool abPowerAttack, bool abSneakAttack, bool abBashAttack, bool abHitBlocked)
ObjectReference hitRef = GetReference()
If akAggressor != PlayerREF || hitRef.IsLocked() == False
Return
EndIf
Int projectileLevel = 0
If akProjectile == _00E_UnlockProjectile_Novice
projectileLevel = LOCK_LEVEL_NOVICE
ElseIf akProjectile == _00E_UnlockProjectile_Apprentice
projectileLevel = LOCK_LEVEL_APPRENTICE
ElseIf akProjectile == _00E_UnlockProjectile_Adept
projectileLevel = LOCK_LEVEL_ADEPT
ElseIf akProjectile == _00E_UnlockProjectile_Expert
projectileLevel = LOCK_LEVEL_EXPERT
ElseIf akProjectile == _00E_UnlockProjectile_Master
projectileLevel = LOCK_LEVEL_MASTER
ElseIf akSource
Formlist unlockSpells = _00E_ChestAndDoorUnlockScript_UnlockSpells
If unlockSpells.HasForm(akSource)
If akSource == unlockSpells.GetAt(0) as Explosion
projectileLevel = LOCK_LEVEL_APPRENTICE
ElseIf akSource == unlockSpells.GetAt(1) as Explosion
projectileLevel = LOCK_LEVEL_ADEPT
ElseIf akSource == unlockSpells.GetAt(2) as Explosion
projectileLevel = LOCK_LEVEL_EXPERT
ElseIf akSource == unlockSpells.GetAt(3) as Explosion
projectileLevel = LOCK_LEVEL_MASTER
EndIf
EndIf
EndIf
If projectileLevel > 0
Int lockLevel = hitRef.GetLockLevel()
If lockLevel > LOCK_LEVEL_MASTER
_00E_sDoorLocked.Show()
WPNTG06ControlStaffShootFailM.Play(hitRef)
ElseIf projectileLevel >= lockLevel
; Unlock
hitRef.Lock(False)
_00E_UILockpickingUnlockM.Play(hitRef)
_00E_Ability_Antimagic_FXSShader.Play(hitRef)
hitRef.PlaceAtMe(_00E_UnlockLockExplosion, 1)
EndIf
EndIf
EndEvent
Projectile Property _00E_UnlockProjectile_Novice Auto
Projectile Property _00E_UnlockProjectile_Apprentice Auto
Projectile Property _00E_UnlockProjectile_Adept Auto
Projectile Property _00E_UnlockProjectile_Expert Auto
Projectile Property _00E_UnlockProjectile_Master Auto
Message Property _00E_sDoorLocked Auto
Sound Property _00E_UILockpickingUnlockM Auto
Sound Property WPNTG06ControlStaffShootFailM Auto
EffectShader Property _00E_Ability_Antimagic_FXSShader Auto
Explosion Property _00E_UnlockLockExplosion Auto
FormList Property _00E_UnlockScrolls Auto
FormList Property _00E_ChestAndDoorUnlockScript_UnlockSpells Auto
Actor Property PlayerREF Auto

View File

@ -1,97 +0,0 @@
Scriptname _00E_ScrollUnlockAlias extends ReferenceAlias Hidden
event OnPlayerLoadGame()
if UnlockScrollEquipped()
GotoState("Equipped")
endif
endevent
Event OnObjectEquipped(Form akBaseObject, ObjectReference akReference)
if akBaseObject as Scroll && _00E_UnlockScrolls.HasForm(akBaseObject)
GotoState("Equipped")
endif
endEvent
bool function UnlockScrollEquipped()
Actor PlayerREF = GetReference() as Actor
if PlayerREF.IsEquipped(_00E_UnlockScrolls)
return true
endif
Form leftHand = PlayerREF.GetEquippedObject(0)
return leftHand && _00E_UnlockScrolls.HasForm(leftHand)
endfunction
Event OnUpdate()
if UnlockScrollAliases.IsStopped()
if ! UnlockScrollAliases.Start()
RegisterForSingleUpdate(0.1)
endif
elseif UnlockScrollAliases.IsStopping()
RegisterForSingleUpdate(0.01)
elseif UnlockScrollAliases.IsStarting()
RegisterForSingleUpdate(0.01)
endif
EndEvent
state Equipped
event OnPlayerLoadGame()
if ! UnlockScrollEquipped()
GotoState("")
endif
endevent
event OnBeginState()
ObjectReference actorRef = GetReference()
RegisterForAnimationEvent(actorRef, "BeginCastRight")
RegisterForAnimationEvent(actorRef, "BeginCastLeft")
endevent
event OnEndState()
ObjectReference actorRef = GetReference()
UnregisterForAnimationEvent(actorRef, "BeginCastRight")
UnregisterForAnimationEvent(actorRef, "BeginCastLeft")
endevent
Event OnUpdate()
if UnlockScrollAliases.IsStopped()
if ! UnlockScrollAliases.Start()
RegisterForSingleUpdate(0.1)
endif
elseif UnlockScrollAliases.IsStopping()
RegisterForSingleUpdate(0.01)
elseif UnlockScrollAliases.IsStarting()
RegisterForSingleUpdate(0.01)
endif
EndEvent
Event OnObjectEquipped(Form akBaseObject, ObjectReference akReference)
; do nothing
endEvent
Event OnObjectUnequipped(Form akBaseObject, ObjectReference akReference)
if ! UnlockScrollEquipped()
GotoState("")
endif
endEvent
Event OnAnimationEvent(ObjectReference akSource, string asEventName)
ObjectReference crosshairRef = Game.GetCurrentCrosshairRef()
if crosshairRef
Form baseObject = crosshairRef.GetBaseObject()
if baseObject as Container || baseObject as Door
ScrollTarget.ForceRefTo(crosshairRef)
UnlockScrollAliases.Stop()
return
endif
endif
UnlockScrollAliases.Stop()
RegisterForSingleUpdate(0.01)
ScrollTarget.Clear()
endEvent
endstate
Quest Property UnlockScrollAliases Auto
FormList Property _00E_UnlockScrolls Auto
ReferenceAlias Property ScrollTarget Auto

View File

@ -0,0 +1,69 @@
Scriptname _00E_UnlockSpellAlias extends ReferenceAlias
Int Property LOCK_LEVEL_NOVICE = 1 AutoReadOnly
Int Property LOCK_LEVEL_APPRENTICE = 25 AutoReadOnly
Int Property LOCK_LEVEL_ADEPT = 50 AutoReadOnly
Int Property LOCK_LEVEL_EXPERT = 75 AutoReadOnly
Int Property LOCK_LEVEL_MASTER = 254 AutoReadOnly
event OnInit()
RegisterForModEvent("Enderal_UnlockSpellHit", "OnUnlockSpell")
endevent
event OnPlayerLoadGame()
RegisterForModEvent("Enderal_UnlockSpellHit", "OnUnlockSpell")
endevent
Event OnUnlockSpell(string eventName, string strArg, float fSpellFormID, Form containerForm)
ObjectReference rContainer = containerForm as ObjectReference
Form rSpell = Game.GetForm(fSpellFormID as int)
Int projectileLevel = 0
If rSpell == _00E_UnlockProjectile_Novice
projectileLevel = LOCK_LEVEL_NOVICE
ElseIf rSpell == _00E_UnlockProjectile_Apprentice || rSpell == _25E_UnlockLockExplosion_Apprentice
projectileLevel = LOCK_LEVEL_APPRENTICE
ElseIf rSpell == _00E_UnlockProjectile_Adept || rSpell == _50E_UnlockLockExplosion_Adept
projectileLevel = LOCK_LEVEL_ADEPT
ElseIf rSpell == _00E_UnlockProjectile_Expert || rSpell == _75E_UnlockLockExplosion_Expert
projectileLevel = LOCK_LEVEL_EXPERT
ElseIf rSpell == _00E_UnlockProjectile_Master || rSpell == _100E_UnlockLockExplosion_Master
projectileLevel = LOCK_LEVEL_MASTER
else
return
endif
Int lockLevel = rContainer.GetLockLevel()
If lockLevel > LOCK_LEVEL_MASTER
_00E_sDoorLocked.Show()
WPNTG06ControlStaffShootFailM.Play(rContainer)
ElseIf projectileLevel >= lockLevel
; Unlock
rContainer.Lock(False)
_00E_UILockpickingUnlockM.Play(rContainer)
_00E_Ability_Antimagic_FXSShader.Play(rContainer)
rContainer.PlaceAtMe(_00E_UnlockLockExplosion, 1)
EndIf
endevent
Projectile Property _00E_UnlockProjectile_Novice Auto
Projectile Property _00E_UnlockProjectile_Apprentice Auto
Projectile Property _00E_UnlockProjectile_Adept Auto
Projectile Property _00E_UnlockProjectile_Expert Auto
Projectile Property _00E_UnlockProjectile_Master Auto
Explosion Property _00E_UnlockLockExplosion Auto
Explosion Property _100E_UnlockLockExplosion_Master Auto
Explosion Property _25E_UnlockLockExplosion_Apprentice Auto
Explosion Property _50E_UnlockLockExplosion_Adept Auto
Explosion Property _75E_UnlockLockExplosion_Expert Auto
Message Property _00E_sDoorLocked Auto
Sound Property WPNTG06ControlStaffShootFailM Auto
Sound Property _00E_UILockpickingUnlockM Auto
EffectShader Property _00E_Ability_Antimagic_FXSShader Auto