diff --git a/dCommon/dEnums/dMessageIdentifiers.h b/dCommon/dEnums/dMessageIdentifiers.h index 7dc08711..5f7e9128 100644 --- a/dCommon/dEnums/dMessageIdentifiers.h +++ b/dCommon/dEnums/dMessageIdentifiers.h @@ -537,6 +537,7 @@ enum GAME_MSG : unsigned short { GAME_MSG_REMOVE_RUN_SPEED_MODIFIER = 1506, GAME_MSG_UPDATE_PROPERTY_PERFORMANCE_COST = 1547, GAME_MSG_PROPERTY_ENTRANCE_BEGIN = 1553, + GAME_MSG_REMOVE_BUFF = 1648, GAME_MSG_REQUEST_MOVE_ITEM_BETWEEN_INVENTORY_TYPES = 1666, GAME_MSG_RESPONSE_MOVE_ITEM_BETWEEN_INVENTORY_TYPES = 1667, GAME_MSG_PLAYER_SET_CAMERA_CYCLING_MODE = 1676, diff --git a/dGame/dBehaviors/Behavior.cpp b/dGame/dBehaviors/Behavior.cpp index 046df117..d0d6192b 100644 --- a/dGame/dBehaviors/Behavior.cpp +++ b/dGame/dBehaviors/Behavior.cpp @@ -42,6 +42,7 @@ #include "SkillCastFailedBehavior.h" #include "SpawnBehavior.h" #include "ForceMovementBehavior.h" +#include "RemoveBuffBehavior.h" #include "ImmunityBehavior.h" #include "InterruptBehavior.h" #include "PlayEffectBehavior.h" @@ -226,7 +227,9 @@ Behavior* Behavior::CreateBehavior(const uint32_t behaviorId) { break; case BehaviorTemplates::BEHAVIOR_ALTER_CHAIN_DELAY: break; case BehaviorTemplates::BEHAVIOR_CAMERA: break; - case BehaviorTemplates::BEHAVIOR_REMOVE_BUFF: break; + case BehaviorTemplates::BEHAVIOR_REMOVE_BUFF: + behavior = new RemoveBuffBehavior(behaviorId); + break; case BehaviorTemplates::BEHAVIOR_GRAB: break; case BehaviorTemplates::BEHAVIOR_MODULAR_BUILD: break; case BehaviorTemplates::BEHAVIOR_NPC_COMBAT_SKILL: diff --git a/dGame/dBehaviors/CMakeLists.txt b/dGame/dBehaviors/CMakeLists.txt index fe8e89b8..297c389b 100644 --- a/dGame/dBehaviors/CMakeLists.txt +++ b/dGame/dBehaviors/CMakeLists.txt @@ -34,6 +34,7 @@ set(DGAME_DBEHAVIORS_SOURCES "AirMovementBehavior.cpp" "PlayEffectBehavior.cpp" "ProjectileAttackBehavior.cpp" "PullToPointBehavior.cpp" + "RemoveBuffBehavior.cpp" "RepairBehavior.cpp" "SkillCastFailedBehavior.cpp" "SkillEventBehavior.cpp" diff --git a/dGame/dBehaviors/RemoveBuffBehavior.cpp b/dGame/dBehaviors/RemoveBuffBehavior.cpp new file mode 100644 index 00000000..be3066ac --- /dev/null +++ b/dGame/dBehaviors/RemoveBuffBehavior.cpp @@ -0,0 +1,21 @@ +#include "RemoveBuffBehavior.h" + +#include "BehaviorBranchContext.h" +#include "BehaviorContext.h" +#include "EntityManager.h" +#include "BuffComponent.h" + +void RemoveBuffBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) { + auto* entity = EntityManager::Instance()->GetEntity(context->caster); + if (!entity) return; + + auto* buffComponent = entity->GetComponent(); + if (!buffComponent) return; + + buffComponent->RemoveBuff(m_BuffId, false, m_RemoveImmunity); +} + +void RemoveBuffBehavior::Load() { + this->m_RemoveImmunity = GetBoolean("remove_immunity"); + this->m_BuffId = GetInt("buff_id"); +} diff --git a/dGame/dBehaviors/RemoveBuffBehavior.h b/dGame/dBehaviors/RemoveBuffBehavior.h new file mode 100644 index 00000000..f2d8547b --- /dev/null +++ b/dGame/dBehaviors/RemoveBuffBehavior.h @@ -0,0 +1,22 @@ +#pragma once +#include "Behavior.h" + +class RemoveBuffBehavior final : public Behavior +{ +public: + + /* + * Inherited + */ + + explicit RemoveBuffBehavior(const uint32_t behaviorId) : Behavior(behaviorId) { + } + + void Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) override; + + void Load() override; + +private: + bool m_RemoveImmunity; + uint32_t m_BuffId; +}; diff --git a/dGame/dComponents/BuffComponent.cpp b/dGame/dComponents/BuffComponent.cpp index ecb10017..af20fc00 100644 --- a/dGame/dComponents/BuffComponent.cpp +++ b/dGame/dComponents/BuffComponent.cpp @@ -123,13 +123,15 @@ void BuffComponent::ApplyBuff(const int32_t id, const float duration, const LWOO m_Buffs.emplace(id, buff); } -void BuffComponent::RemoveBuff(int32_t id) { +void BuffComponent::RemoveBuff(int32_t id, bool fromUnEquip, bool removeImmunity) { const auto& iter = m_Buffs.find(id); if (iter == m_Buffs.end()) { return; } + GameMessages::SendRemoveBuff(m_Parent, fromUnEquip, removeImmunity, id); + m_Buffs.erase(iter); RemoveBuffEffect(id); diff --git a/dGame/dComponents/BuffComponent.h b/dGame/dComponents/BuffComponent.h index aa669b13..7f7c6b0f 100644 --- a/dGame/dComponents/BuffComponent.h +++ b/dGame/dComponents/BuffComponent.h @@ -78,8 +78,9 @@ public: /** * Removes a buff from the parent entity, reversing its effects * @param id the id of the buff to remove + * @param removeImmunity whether or not to remove immunity on removing the buff */ - void RemoveBuff(int32_t id); + void RemoveBuff(int32_t id, bool fromUnEquip = false, bool removeImmunity = false); /** * Returns whether or not the entity has a buff identified by `id` diff --git a/dGame/dComponents/InventoryComponent.cpp b/dGame/dComponents/InventoryComponent.cpp index 12b6792e..9f53cfa3 100644 --- a/dGame/dComponents/InventoryComponent.cpp +++ b/dGame/dComponents/InventoryComponent.cpp @@ -986,6 +986,7 @@ void InventoryComponent::ApplyBuff(Item* item) const { } } +// TODO Something needs to send the remove buff GameMessage as well when it is unequipping items that would remove buffs. void InventoryComponent::RemoveBuff(Item* item) const { const auto buffs = FindBuffs(item, false); diff --git a/dGame/dGameMessages/GameMessages.cpp b/dGame/dGameMessages/GameMessages.cpp index 025c26b3..896dfa0c 100644 --- a/dGame/dGameMessages/GameMessages.cpp +++ b/dGame/dGameMessages/GameMessages.cpp @@ -3476,6 +3476,20 @@ void GameMessages::SendPlayEmote(LWOOBJID objectId, int32_t emoteID, LWOOBJID ta SEND_PACKET; } +void GameMessages::SendRemoveBuff(Entity* entity, bool fromUnEquip, bool removeImmunity, uint32_t buffId) { + CBITSTREAM; + CMSGHEADER; + + bitStream.Write(entity->GetObjectID()); + bitStream.Write(GAME_MSG::GAME_MSG_REMOVE_BUFF); + + bitStream.Write(false); // bFromRemoveBehavior but setting this to true makes the GM not do anything on the client? + bitStream.Write(fromUnEquip); + bitStream.Write(removeImmunity); + bitStream.Write(buffId); + + SEND_PACKET_BROADCAST; +} void GameMessages::SendBouncerActiveStatus(LWOOBJID objectId, bool bActive, const SystemAddress& sysAddr) { CBITSTREAM; diff --git a/dGame/dGameMessages/GameMessages.h b/dGame/dGameMessages/GameMessages.h index 31bdebb3..3594a86a 100644 --- a/dGame/dGameMessages/GameMessages.h +++ b/dGame/dGameMessages/GameMessages.h @@ -566,6 +566,8 @@ namespace GameMessages { void HandleReportBug(RakNet::BitStream* inStream, Entity* entity); + void SendRemoveBuff(Entity* entity, bool fromUnEquip, bool removeImmunity, uint32_t buffId); + /* Message to synchronize a skill cast */ class EchoSyncSkill { static const GAME_MSG MsgID = GAME_MSG_ECHO_SYNC_SKILL;