#include #include #include #include #include #include #include #include #include #include #include #include ActorValueService::ActorValueService(World& aWorld, entt::dispatcher& aDispatcher) noexcept : m_world(aWorld) { m_updateHealthConnection = aDispatcher.sink>().connect<&ActorValueService::OnActorValueChanges>(this); m_updateMaxValueConnection = aDispatcher.sink>().connect<&ActorValueService::OnActorMaxValueChanges>(this); m_updateDeltaHealthConnection = aDispatcher.sink>().connect<&ActorValueService::OnHealthChangeBroadcast>(this); m_deathStateConnection = aDispatcher.sink>().connect<&ActorValueService::OnDeathStateChange>(this); } void ActorValueService::OnActorValueChanges(const PacketEvent& acMessage) const noexcept { auto& message = acMessage.Packet; auto actorValuesView = m_world.view(); auto it = actorValuesView.find(static_cast(message.Id)); if (it != actorValuesView.end()) { auto& actorValuesComponent = actorValuesView.get(*it); for (auto& [id, value] : message.Values) { actorValuesComponent.CurrentActorValues.ActorValuesList[id] = value; } } NotifyActorValueChanges notify; notify.Id = acMessage.Packet.Id; notify.Values = acMessage.Packet.Values; const entt::entity cEntity = static_cast(message.Id); if (!GameServer::Get()->SendToPlayersInRange(notify, cEntity, acMessage.pPlayer)) spdlog::error("{}: SendToPlayersInRange failed", __FUNCTION__); } void ActorValueService::OnActorMaxValueChanges(const PacketEvent& acMessage) const noexcept { auto& message = acMessage.Packet; auto actorValuesView = m_world.view(); auto it = actorValuesView.find(static_cast(message.Id)); if (it != actorValuesView.end()) { auto& actorValuesComponent = actorValuesView.get(*it); for (auto& [id, value] : message.Values) { actorValuesComponent.CurrentActorValues.ActorMaxValuesList[id] = value; } } NotifyActorMaxValueChanges notify; notify.Id = message.Id; notify.Values = message.Values; const entt::entity cEntity = static_cast(message.Id); if (!GameServer::Get()->SendToPlayersInRange(notify, cEntity, acMessage.pPlayer)) spdlog::error("{}: SendToPlayersInRange failed", __FUNCTION__); } void ActorValueService::OnHealthChangeBroadcast(const PacketEvent& acMessage) const noexcept { auto& message = acMessage.Packet; // TODO(cosideci): should server side health not be updated? auto actorValuesView = m_world.view(); auto it = actorValuesView.find(static_cast(message.Id)); if (it != actorValuesView.end()) { auto& actorValuesComponent = actorValuesView.get(*it); auto currentHealth = actorValuesComponent.CurrentActorValues.ActorValuesList[24]; actorValuesComponent.CurrentActorValues.ActorValuesList[24] = currentHealth - message.DeltaHealth; } NotifyHealthChangeBroadcast notify; notify.Id = message.Id; notify.DeltaHealth = message.DeltaHealth; const entt::entity cEntity = static_cast(message.Id); if (!GameServer::Get()->SendToPlayersInRange(notify, cEntity, acMessage.pPlayer)) spdlog::error("{}: SendToPlayersInRange failed", __FUNCTION__); } void ActorValueService::OnDeathStateChange(const PacketEvent& acMessage) const noexcept { auto& message = acMessage.Packet; auto characterView = m_world.view(); const auto it = characterView.find(static_cast(message.Id)); if (it != characterView.end()) { auto& characterComponent = characterView.get(*it); characterComponent.SetDead(message.IsDead); spdlog::debug("Updating death state {:x}:{}", message.Id, message.IsDead); } NotifyDeathStateChange notify; notify.Id = message.Id; notify.IsDead = message.IsDead; const entt::entity cEntity = static_cast(message.Id); if (!GameServer::Get()->SendToPlayersInRange(notify, cEntity, acMessage.pPlayer)) spdlog::error("{}: SendToPlayersInRange failed", __FUNCTION__); }