Skip to content

Commit

Permalink
fix: queued effects
Browse files Browse the repository at this point in the history
  • Loading branch information
RobbeBryssinck committed Mar 8, 2022
1 parent bae848b commit 96d835e
Show file tree
Hide file tree
Showing 7 changed files with 56 additions and 42 deletions.
19 changes: 14 additions & 5 deletions Code/client/Games/Skyrim/Effects/ActiveEffect.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,22 @@ struct ActiveEffect

static ActiveEffect* Instantiate(Actor* apCaster, MagicItem* apSpell, EffectItem* apEffect);

uint8_t pad8[0x48];
uint8_t pad8[0x38];
MagicItem* pSpell;
void* pEffect;
MagicTarget* pTarget;
uint8_t pad58[0x20];
float effectValue;
uint8_t pad_007C[4];
TESBoundObject* pSource;
void* pHitEffects;
MagicItem* pDisplacementSpell;
float fElapsedSeconds;
float fDuration;
float fMagnitude;
uint32_t uiFlags;
uint32_t eConditionStatus;
uint16_t usUniqueID;
MagicSystem::CastingSource eCastingSource;
};
static_assert(sizeof(ActiveEffect) == 0x80);
static_assert(sizeof(ActiveEffect) == 0x90);

namespace ActiveEffectFactory
{
Expand Down
1 change: 0 additions & 1 deletion Code/client/Games/Skyrim/Effects/ValueModifierEffect.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ struct ValueModifierEffect : public ActiveEffect
virtual void sub_1F();
virtual void ApplyActorEffect(Actor* actor, float effectValue, unsigned int unk1);

char pad_0080[16];
uint32_t actorValueIndex;
char pad_0094[4];
};
Expand Down
2 changes: 1 addition & 1 deletion Code/client/Games/Skyrim/Misc/InventoryEntry.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ struct ExtraDataList;
struct InventoryEntry
{
TESBoundObject* pObject;
GameList<ExtraDataList*>* pExtraLists;
GameList<ExtraDataList>* pExtraLists;
int32_t count;
};
2 changes: 1 addition & 1 deletion Code/client/Games/Skyrim/Misc/MiddleProcess.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ struct MiddleProcess
uint8_t pad0[0xB8];
float direction; // B8
uint8_t padBC[0x1A0 - 0xBC];
GameList<ActiveEffect*>* ActiveEffects;
GameList<ActiveEffect>* ActiveEffects;
uint8_t pad1A8[0x220 - 0x1A8];
InventoryEntry* leftEquippedObject;
uint8_t pad228[0x260 - 0x228];
Expand Down
17 changes: 17 additions & 0 deletions Code/client/Services/Debug/Views/FormDebugView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
#include <Forms/TESWorldSpace.h>

#include <Services/TestService.h>
#include <AI/AIProcess.h>
#include <Misc/MiddleProcess.h>
#include <Effects/ActiveEffect.h>

void TestService::DrawFormDebugView()
{
Expand All @@ -30,5 +33,19 @@ void TestService::DrawFormDebugView()
{
ImGui::InputScalar("Memory address", ImGuiDataType_U64, (void*)&pActor, 0, 0, "%" PRIx64,
ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_ReadOnly);

for (ActiveEffect* pEffect : *pActor->currentProcess->middleProcess->ActiveEffects)
{
if (!pEffect)
continue;

if (!ImGui::CollapsingHeader(pEffect->pSpell->fullName.value, ImGuiTreeNodeFlags_DefaultOpen))
continue;

ImGui::InputFloat("Elapsed seconds", &pEffect->fElapsedSeconds, 0, 0, "%.1f", ImGuiInputTextFlags_ReadOnly);
ImGui::InputFloat("Duration", &pEffect->fDuration, 0, 0, "%.1f", ImGuiInputTextFlags_ReadOnly);
ImGui::InputFloat("Magnitude", &pEffect->fMagnitude, 0, 0, "%.1f", ImGuiInputTextFlags_ReadOnly);
ImGui::InputInt("Flags", (int*)&pEffect->uiFlags, 0, 0, ImGuiInputTextFlags_ReadOnly);
}
}
}
54 changes: 21 additions & 33 deletions Code/client/Services/Generic/MagicService.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@

#include <Messages/SpellCastRequest.h>
#include <Messages/InterruptCastRequest.h>
#include <Messages/AddTargetRequest.h>

#include <Messages/NotifySpellCast.h>
#include <Messages/NotifyInterruptCast.h>
Expand Down Expand Up @@ -39,8 +38,6 @@ MagicService::MagicService(World& aWorld, entt::dispatcher& aDispatcher, Transpo
pEventList->activeEffectApplyRemove.RegisterSink(this);
}

// TODO: might be easier to just check the list of effects in OnUpdate() for each actor, and send that back and forth

void MagicService::OnUpdate(const UpdateEvent& acEvent) noexcept
{
#if TP_SKYRIM64
Expand All @@ -58,7 +55,7 @@ void MagicService::OnUpdate(const UpdateEvent& acEvent) noexcept

Vector<uint32_t> markedForRemoval;

for (auto [formId, spellId] : m_queuedEffects)
for (auto [formId, request] : m_queuedEffects)
{
auto view = m_world.view<FormIdComponent>();
const auto it = std::find_if(std::begin(view), std::end(view), [id = formId, view](auto entity) {
Expand All @@ -70,20 +67,12 @@ void MagicService::OnUpdate(const UpdateEvent& acEvent) noexcept

entt::entity entity = *it;

AddTargetRequest request;

std::optional<uint32_t> serverIdRes = Utils::GetServerId(entity);
if (!serverIdRes.has_value())
continue;

request.TargetId = serverIdRes.value();

if (!m_world.GetModSystem().GetServerModId(spellId, request.SpellId.ModId, request.SpellId.BaseId))
{
spdlog::error("{s}: Could not find spell with form {:X}", __FUNCTION__, spellId);
continue;
}

m_transport.Send(request);

markedForRemoval.push_back(formId);
Expand Down Expand Up @@ -205,7 +194,7 @@ void MagicService::OnNotifySpellCast(const NotifySpellCast& acMessage) const noe
TESForm* pSpellForm = TESForm::GetById(cSpellFormId);
if (!pSpellForm)
{
spdlog::error("Cannot find spell form.");
spdlog::error("Cannot find spell form, id: {:X}.", cSpellFormId);
return;
}
else
Expand Down Expand Up @@ -321,6 +310,22 @@ void MagicService::OnAddTargetEvent(const AddTargetEvent& acEvent) noexcept
if (!m_transport.IsConnected())
return;

AddTargetRequest request;

if (!m_world.GetModSystem().GetServerModId(acEvent.SpellID, request.SpellId.ModId, request.SpellId.BaseId))
{
spdlog::error("{s}: Could not find spell with form {:X}", __FUNCTION__, acEvent.SpellID);
return;
}

if (!m_world.GetModSystem().GetServerModId(acEvent.EffectID, request.EffectId.ModId, request.EffectId.BaseId))
{
spdlog::error("{s}: Could not find effect with form {:X}", __FUNCTION__, acEvent.EffectID);
return;
}

request.Magnitude = acEvent.Magnitude;

auto view = m_world.view<FormIdComponent>();
const auto it = std::find_if(std::begin(view), std::end(view), [id = acEvent.TargetID, view](auto entity) {
return view.get<FormIdComponent>(entity).Id == id;
Expand All @@ -329,34 +334,17 @@ void MagicService::OnAddTargetEvent(const AddTargetEvent& acEvent) noexcept
if (it == std::end(view))
{
spdlog::warn("Target not found for magic add target, form id: {:X}", acEvent.TargetID);
m_queuedEffects[acEvent.TargetID] = acEvent.SpellID;
m_queuedEffects[acEvent.TargetID] = request;
return;
}

entt::entity entity = *it;

AddTargetRequest request;

std::optional<uint32_t> serverIdRes = Utils::GetServerId(entity);
if (!serverIdRes.has_value())
return;

request.TargetId = serverIdRes.value();

if (!m_world.GetModSystem().GetServerModId(acEvent.SpellID, request.SpellId.ModId, request.SpellId.BaseId))
{
spdlog::error("{s}: Could not find spell with form {:X}", __FUNCTION__, acEvent.SpellID);
return;
}

if (!m_world.GetModSystem().GetServerModId(acEvent.EffectID, request.EffectId.ModId, request.EffectId.BaseId))
{
spdlog::error("{s}: Could not find effect with form {:X}", __FUNCTION__, acEvent.EffectID);
return;
}

request.Magnitude = acEvent.Magnitude;

m_transport.Send(request);
#endif
}
Expand Down Expand Up @@ -388,7 +376,7 @@ void MagicService::OnNotifyAddTarget(const NotifyAddTarget& acMessage) const noe
const uint32_t cEffectId = World::Get().GetModSystem().GetGameId(acMessage.EffectId);
if (cEffectId == 0)
{
spdlog::error("{}: failed to retrieve spell id, GameId base: {:X}, mod: {:X}", __FUNCTION__,
spdlog::error("{}: failed to retrieve effect id, GameId base: {:X}, mod: {:X}", __FUNCTION__,
acMessage.EffectId.BaseId, acMessage.EffectId.ModId);
return;
}
Expand All @@ -406,7 +394,7 @@ void MagicService::OnNotifyAddTarget(const NotifyAddTarget& acMessage) const noe

if (!pEffect)
{
spdlog::error("{}: Failed to retrieve spell by id {:X}", __FUNCTION__, cEffectId);
spdlog::error("{}: Failed to retrieve effect by id {:X}", __FUNCTION__, cEffectId);
return;
}

Expand Down
3 changes: 2 additions & 1 deletion Code/client/Services/MagicService.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include <Games/Events.h>
#include <Events/EventDispatcher.h>
#include <Messages/AddTargetRequest.h>

struct World;
struct TransportService;
Expand Down Expand Up @@ -41,7 +42,7 @@ struct MagicService : BSTEventSink<TESMagicEffectApplyEvent>, BSTEventSink<TESAc
entt::dispatcher& m_dispatcher;
TransportService& m_transport;

Map<uint32_t, uint32_t> m_queuedEffects;
Map<uint32_t, AddTargetRequest> m_queuedEffects;

entt::scoped_connection m_updateConnection;
entt::scoped_connection m_spellCastEventConnection;
Expand Down

0 comments on commit 96d835e

Please sign in to comment.