diff --git a/dGame/dBehaviors/AreaOfEffectBehavior.cpp b/dGame/dBehaviors/AreaOfEffectBehavior.cpp index ca3bdf93..dedede2a 100644 --- a/dGame/dBehaviors/AreaOfEffectBehavior.cpp +++ b/dGame/dBehaviors/AreaOfEffectBehavior.cpp @@ -48,9 +48,8 @@ void AreaOfEffectBehavior::Handle(BehaviorContext* context, RakNet::BitStream* b void AreaOfEffectBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) { auto* self = EntityManager::Instance()->GetEntity(context->caster); - if (self == nullptr) { - Game::logger->Log("TacArcBehavior", "Invalid self for (%llu)!", context->originator); + Game::logger->Log("AreaOfEffectBehavior", "Invalid self for (%llu)!", context->originator); return; } @@ -79,7 +78,7 @@ void AreaOfEffectBehavior::Calculate(BehaviorContext* context, RakNet::BitStream auto* entity = EntityManager::Instance()->GetEntity(validTarget); if (entity == nullptr) { - Game::logger->Log("TacArcBehavior", "Invalid target (%llu) for (%llu)!", validTarget, context->originator); + Game::logger->Log("AreaOfEffectBehavior", "Invalid target (%llu) for (%llu)!", validTarget, context->originator); continue; } diff --git a/dGame/dBehaviors/Behavior.cpp b/dGame/dBehaviors/Behavior.cpp index cd9304d3..568780d0 100644 --- a/dGame/dBehaviors/Behavior.cpp +++ b/dGame/dBehaviors/Behavior.cpp @@ -61,6 +61,7 @@ #include "DamageReductionBehavior.h" #include "JetPackBehavior.h" #include "ChangeIdleFlagsBehavior.h" +#include "DarkInspirationBehavior.h" //CDClient includes #include "CDBehaviorParameterTable.h" @@ -169,7 +170,9 @@ Behavior* Behavior::CreateBehavior(const uint32_t behaviorId) { case BehaviorTemplates::BEHAVIOR_SPEED: behavior = new SpeedBehavior(behaviorId); break; - case BehaviorTemplates::BEHAVIOR_DARK_INSPIRATION: break; + case BehaviorTemplates::BEHAVIOR_DARK_INSPIRATION: + behavior = new DarkInspirationBehavior(behaviorId); + break; case BehaviorTemplates::BEHAVIOR_LOOT_BUFF: behavior = new LootBuffBehavior(behaviorId); break; diff --git a/dGame/dBehaviors/CMakeLists.txt b/dGame/dBehaviors/CMakeLists.txt index 40ac0a9c..e274872d 100644 --- a/dGame/dBehaviors/CMakeLists.txt +++ b/dGame/dBehaviors/CMakeLists.txt @@ -18,6 +18,7 @@ set(DGAME_DBEHAVIORS_SOURCES "AirMovementBehavior.cpp" "ClearTargetBehavior.cpp" "DamageAbsorptionBehavior.cpp" "DamageReductionBehavior.cpp" + "DarkInspirationBehavior.cpp" "DurationBehavior.cpp" "EmptyBehavior.cpp" "EndBehavior.cpp" diff --git a/dGame/dBehaviors/DarkInspirationBehavior.cpp b/dGame/dBehaviors/DarkInspirationBehavior.cpp new file mode 100644 index 00000000..ea80cbba --- /dev/null +++ b/dGame/dBehaviors/DarkInspirationBehavior.cpp @@ -0,0 +1,52 @@ +#include "DarkInspirationBehavior.h" + +#include "BehaviorBranchContext.h" +#include "Entity.h" +#include "DestroyableComponent.h" +#include "EntityManager.h" +#include "BehaviorContext.h" + +void DarkInspirationBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, const BehaviorBranchContext branch) { + auto* target = EntityManager::Instance()->GetEntity(branch.target); + + if (target == nullptr) { + Game::logger->LogDebug("DarkInspirationBehavior", "Failed to find target (%llu)!", branch.target); + return; + } + + auto* destroyableComponent = target->GetComponent(); + + if (destroyableComponent == nullptr) { + return; + } + + if (destroyableComponent->HasFaction(m_FactionList)) { + this->m_ActionIfFactionMatches->Handle(context, bitStream, branch); + } +} + +void DarkInspirationBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) { + auto* target = EntityManager::Instance()->GetEntity(branch.target); + + if (target == nullptr) { + Game::logger->LogDebug("DarkInspirationBehavior", "Failed to find target (%llu)!", branch.target); + + return; + } + + auto* destroyableComponent = target->GetComponent(); + + if (destroyableComponent == nullptr) { + return; + } + + if (destroyableComponent->HasFaction(m_FactionList)) { + this->m_ActionIfFactionMatches->Calculate(context, bitStream, branch); + } +} + +void DarkInspirationBehavior::Load() { + this->m_ActionIfFactionMatches = GetAction("action"); + + this->m_FactionList = GetInt("faction_list"); +} diff --git a/dGame/dBehaviors/DarkInspirationBehavior.h b/dGame/dBehaviors/DarkInspirationBehavior.h new file mode 100644 index 00000000..f8298742 --- /dev/null +++ b/dGame/dBehaviors/DarkInspirationBehavior.h @@ -0,0 +1,22 @@ +#pragma once +#include "Behavior.h" + +class DarkInspirationBehavior final : public Behavior +{ +public: + /* + * Inherited + */ + + explicit DarkInspirationBehavior(const uint32_t behaviorId) : Behavior(behaviorId) { + } + + void Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) override; + + void Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) override; + + void Load() override; +private: + Behavior* m_ActionIfFactionMatches; + uint32_t m_FactionList; +}; diff --git a/dGame/dComponents/BuffComponent.cpp b/dGame/dComponents/BuffComponent.cpp index d8d7428d..974d0bd2 100644 --- a/dGame/dComponents/BuffComponent.cpp +++ b/dGame/dComponents/BuffComponent.cpp @@ -170,17 +170,10 @@ void BuffComponent::ApplyBuffEffect(int32_t id) { destroyable->SetMaxImagination(destroyable->GetMaxImagination() + maxImagination); } else if (parameter.name == "speed") { - const auto speed = parameter.value; - auto* controllablePhysicsComponent = this->GetParent()->GetComponent(); - - if (controllablePhysicsComponent == nullptr) return; - - const auto current = controllablePhysicsComponent->GetSpeedMultiplier(); - - controllablePhysicsComponent->SetSpeedMultiplier(current + ((speed - 500.0f) / 500.0f)); - - EntityManager::Instance()->SerializeEntity(this->GetParent()); + if (!controllablePhysicsComponent) return; + const auto speed = parameter.value; + controllablePhysicsComponent->AddSpeedboost(speed); } } } @@ -213,17 +206,10 @@ void BuffComponent::RemoveBuffEffect(int32_t id) { destroyable->SetMaxImagination(destroyable->GetMaxImagination() - maxImagination); } else if (parameter.name == "speed") { - const auto speed = parameter.value; - auto* controllablePhysicsComponent = this->GetParent()->GetComponent(); - - if (controllablePhysicsComponent == nullptr) return; - - const auto current = controllablePhysicsComponent->GetSpeedMultiplier(); - - controllablePhysicsComponent->SetSpeedMultiplier(current - ((speed - 500.0f) / 500.0f)); - - EntityManager::Instance()->SerializeEntity(this->GetParent()); + if (!controllablePhysicsComponent) return; + const auto speed = parameter.value; + controllablePhysicsComponent->RemoveSpeedboost(speed); } } } diff --git a/dGame/dComponents/DestroyableComponent.cpp b/dGame/dComponents/DestroyableComponent.cpp index 6902917f..d832ef93 100644 --- a/dGame/dComponents/DestroyableComponent.cpp +++ b/dGame/dComponents/DestroyableComponent.cpp @@ -694,7 +694,7 @@ void DestroyableComponent::Smash(const LWOOBJID source, const eKillType killType auto* inventoryComponent = owner->GetComponent(); if (inventoryComponent != nullptr && isEnemy) { - inventoryComponent->TriggerPassiveAbility(PassiveAbilityTrigger::EnemySmashed); + inventoryComponent->TriggerPassiveAbility(PassiveAbilityTrigger::EnemySmashed, m_Parent); } auto* missions = owner->GetComponent(); diff --git a/dGame/dComponents/InventoryComponent.cpp b/dGame/dComponents/InventoryComponent.cpp index eeb6afa7..6247f32d 100644 --- a/dGame/dComponents/InventoryComponent.cpp +++ b/dGame/dComponents/InventoryComponent.cpp @@ -1196,9 +1196,9 @@ void InventoryComponent::RemoveItemSkills(const LOT lot) { } } -void InventoryComponent::TriggerPassiveAbility(PassiveAbilityTrigger trigger) { +void InventoryComponent::TriggerPassiveAbility(PassiveAbilityTrigger trigger, Entity* target) { for (auto* set : m_Itemsets) { - set->TriggerPassiveAbility(trigger); + set->TriggerPassiveAbility(trigger, target); } } diff --git a/dGame/dComponents/InventoryComponent.h b/dGame/dComponents/InventoryComponent.h index 44636d95..f63a8d70 100644 --- a/dGame/dComponents/InventoryComponent.h +++ b/dGame/dComponents/InventoryComponent.h @@ -283,7 +283,7 @@ public: * Triggers one of the passive abilities from the equipped item set * @param trigger the trigger to fire */ - void TriggerPassiveAbility(PassiveAbilityTrigger trigger); + void TriggerPassiveAbility(PassiveAbilityTrigger trigger, Entity* target = nullptr); /** * Returns if the entity has any of the passed passive abilities equipped diff --git a/dGame/dGameMessages/GameMessages.cpp b/dGame/dGameMessages/GameMessages.cpp index c3b86647..37aeb093 100644 --- a/dGame/dGameMessages/GameMessages.cpp +++ b/dGame/dGameMessages/GameMessages.cpp @@ -4728,13 +4728,13 @@ void GameMessages::HandleSellToVendor(RakNet::BitStream* inStream, Entity* entit float sellScalar = vend->GetSellScalar(); if (Inventory::IsValidItem(itemComp.currencyLOT)) { - const auto altCurrency = (itemComp.altCurrencyCost * sellScalar) * count; + const auto altCurrency = static_cast(itemComp.altCurrencyCost * sellScalar) * count; inv->AddItem(itemComp.currencyLOT, std::floor(altCurrency), eLootSourceType::LOOT_SOURCE_VENDOR); // Return alt currencies like faction tokens. } //inv->RemoveItem(count, -1, iObjID); inv->MoveItemToInventory(item, eInventoryType::VENDOR_BUYBACK, count, true, false, true); - character->SetCoins(std::floor(character->GetCoins() + ((itemComp.baseValue * sellScalar) * count)), eLootSourceType::LOOT_SOURCE_VENDOR); + character->SetCoins(std::floor(character->GetCoins() + (static_cast(itemComp.baseValue * sellScalar) * count)), eLootSourceType::LOOT_SOURCE_VENDOR); //EntityManager::Instance()->SerializeEntity(player); // so inventory updates GameMessages::SendVendorTransactionResult(entity, sysAddr); } @@ -5763,11 +5763,7 @@ void GameMessages::HandleUseNonEquipmentItem(RakNet::BitStream* inStream, Entity auto* item = inv->FindItemById(itemConsumed); - if (item == nullptr) { - return; - } - - item->UseNonEquip(); + if (item) item->UseNonEquip(item); } void GameMessages::HandleMatchRequest(RakNet::BitStream* inStream, Entity* entity) { diff --git a/dGame/dInventory/Item.cpp b/dGame/dInventory/Item.cpp index 778d8237..a3d4cfc0 100644 --- a/dGame/dInventory/Item.cpp +++ b/dGame/dInventory/Item.cpp @@ -262,7 +262,7 @@ bool Item::Consume() { return success; } -void Item::UseNonEquip() { +void Item::UseNonEquip(Item* item) { LOT thisLot = this->GetLot(); if (!GetInventory()) { Game::logger->LogDebug("Item", "item %i has no inventory??", this->GetLot()); @@ -292,45 +292,49 @@ void Item::UseNonEquip() { } // This precondition response is taken care of in SpawnPet(). } else { - auto* compRegistryTable = CDClientManager::Instance()->GetTable("ComponentsRegistry"); - const auto packageComponentId = compRegistryTable->GetByIDAndType(lot, COMPONENT_TYPE_PACKAGE); + bool success = false; + auto inventory = item->GetInventory(); + if (inventory && inventory->GetType() == eInventoryType::ITEMS) { + auto* compRegistryTable = CDClientManager::Instance()->GetTable("ComponentsRegistry"); + const auto packageComponentId = compRegistryTable->GetByIDAndType(lot, COMPONENT_TYPE_PACKAGE); - if (packageComponentId == 0) return; + if (packageComponentId == 0) return; - auto* packCompTable = CDClientManager::Instance()->GetTable("PackageComponent"); - auto packages = packCompTable->Query([=](const CDPackageComponent entry) {return entry.id == static_cast(packageComponentId); }); + auto* packCompTable = CDClientManager::Instance()->GetTable("PackageComponent"); + auto packages = packCompTable->Query([=](const CDPackageComponent entry) {return entry.id == static_cast(packageComponentId); }); - auto success = !packages.empty(); - if (success) { - if (this->GetPreconditionExpression()->Check(playerInventoryComponent->GetParent())) { - auto* entityParent = playerInventoryComponent->GetParent(); - // Roll the loot for all the packages then see if it all fits. If it fits, give it to the player, otherwise don't. - std::unordered_map rolledLoot{}; - for (auto& pack : packages) { - auto thisPackage = LootGenerator::Instance().RollLootMatrix(entityParent, pack.LootMatrixIndex); - for (auto& loot : thisPackage) { - // If we already rolled this lot, add it to the existing one, otherwise create a new entry. - auto existingLoot = rolledLoot.find(loot.first); - if (existingLoot == rolledLoot.end()) { - rolledLoot.insert(loot); - } else { - existingLoot->second += loot.second; + auto success = !packages.empty(); + if (success) { + if (this->GetPreconditionExpression()->Check(playerInventoryComponent->GetParent())) { + auto* entityParent = playerInventoryComponent->GetParent(); + // Roll the loot for all the packages then see if it all fits. If it fits, give it to the player, otherwise don't. + std::unordered_map rolledLoot{}; + for (auto& pack : packages) { + auto thisPackage = LootGenerator::Instance().RollLootMatrix(entityParent, pack.LootMatrixIndex); + for (auto& loot : thisPackage) { + // If we already rolled this lot, add it to the existing one, otherwise create a new entry. + auto existingLoot = rolledLoot.find(loot.first); + if (existingLoot == rolledLoot.end()) { + rolledLoot.insert(loot); + } else { + existingLoot->second += loot.second; + } } } - } - if (playerInventoryComponent->HasSpaceForLoot(rolledLoot)) { - LootGenerator::Instance().GiveLoot(playerInventoryComponent->GetParent(), rolledLoot, eLootSourceType::LOOT_SOURCE_CONSUMPTION); - playerInventoryComponent->RemoveItem(lot, 1); + if (playerInventoryComponent->HasSpaceForLoot(rolledLoot)) { + LootGenerator::Instance().GiveLoot(playerInventoryComponent->GetParent(), rolledLoot, eLootSourceType::LOOT_SOURCE_CONSUMPTION); + item->SetCount(item->GetCount() - 1); + } else { + success = false; + } } else { + GameMessages::SendUseItemRequirementsResponse( + playerInventoryComponent->GetParent()->GetObjectID(), + playerInventoryComponent->GetParent()->GetSystemAddress(), + UseItemResponse::FailedPrecondition + ); success = false; } - } else { - GameMessages::SendUseItemRequirementsResponse( - playerInventoryComponent->GetParent()->GetObjectID(), - playerInventoryComponent->GetParent()->GetSystemAddress(), - UseItemResponse::FailedPrecondition - ); - success = false; } } Game::logger->LogDebug("Item", "Player %llu %s used item %i", playerEntity->GetObjectID(), success ? "successfully" : "unsuccessfully", thisLot); diff --git a/dGame/dInventory/Item.h b/dGame/dInventory/Item.h index bb8316d7..6993a0ba 100644 --- a/dGame/dInventory/Item.h +++ b/dGame/dInventory/Item.h @@ -195,7 +195,7 @@ public: /** * Uses this item if its non equip, essentially an interface for the linked GM */ - void UseNonEquip(); + void UseNonEquip(Item* item); /** * Disassembles the part LOTs of this item back into the inventory, if it has any diff --git a/dGame/dInventory/ItemSet.cpp b/dGame/dInventory/ItemSet.cpp index 5063139e..1c67f6d6 100644 --- a/dGame/dInventory/ItemSet.cpp +++ b/dGame/dInventory/ItemSet.cpp @@ -180,9 +180,9 @@ void ItemSet::Update(float deltaTime) { } } -void ItemSet::TriggerPassiveAbility(PassiveAbilityTrigger trigger) { +void ItemSet::TriggerPassiveAbility(PassiveAbilityTrigger trigger, Entity* target) { for (auto& passiveAbility : m_PassiveAbilities) { - passiveAbility.Trigger(trigger); + passiveAbility.Trigger(trigger, target); } } diff --git a/dGame/dInventory/ItemSet.h b/dGame/dInventory/ItemSet.h index 7c713f03..d167cfaa 100644 --- a/dGame/dInventory/ItemSet.h +++ b/dGame/dInventory/ItemSet.h @@ -52,7 +52,7 @@ public: * Triggers all the passive abilities in this item set that match this trigger * @param trigger the trigger to use to trigger passive abilities */ - void TriggerPassiveAbility(PassiveAbilityTrigger trigger); + void TriggerPassiveAbility(PassiveAbilityTrigger trigger, Entity* target = nullptr); /** * Returns the skills that can be equipped for a specified amount of equipped items diff --git a/dGame/dInventory/ItemSetPassiveAbility.cpp b/dGame/dInventory/ItemSetPassiveAbility.cpp index d90f6e4e..83db4405 100644 --- a/dGame/dInventory/ItemSetPassiveAbility.cpp +++ b/dGame/dInventory/ItemSetPassiveAbility.cpp @@ -16,12 +16,12 @@ ItemSetPassiveAbility::ItemSetPassiveAbility(PassiveAbilityTrigger trigger, Enti ItemSetPassiveAbility::~ItemSetPassiveAbility() { } -void ItemSetPassiveAbility::Trigger(PassiveAbilityTrigger trigger) { +void ItemSetPassiveAbility::Trigger(PassiveAbilityTrigger trigger, Entity* target) { if (m_Trigger != trigger || m_Cooldown > 0.0f) { return; } - Activate(); + Activate(target); } void ItemSetPassiveAbility::Update(float deltaTime) { @@ -30,9 +30,9 @@ void ItemSetPassiveAbility::Update(float deltaTime) { } } -void ItemSetPassiveAbility::Activate() { +void ItemSetPassiveAbility::Activate(Entity* target) { if (m_Trigger == PassiveAbilityTrigger::EnemySmashed) { - OnEnemySmshed(); + OnEnemySmshed(target); return; } @@ -195,7 +195,7 @@ std::vector ItemSetPassiveAbility::FindAbilities(uint32_t return abilities; } -void ItemSetPassiveAbility::OnEnemySmshed() { +void ItemSetPassiveAbility::OnEnemySmshed(Entity* target) { auto* destroyableComponent = m_Parent->GetComponent(); auto* skillComponent = m_Parent->GetComponent(); @@ -293,8 +293,8 @@ void ItemSetPassiveAbility::OnEnemySmshed() { break; } case ItemSetPassiveAbilityID::ShinobiRank3: { - if (equippedCount < 4) return; - destroyableComponent->Imagine(3); + if (equippedCount < 4 || !target) return; + skillComponent->CalculateBehavior(695, 11399, target->GetObjectID()); break; } diff --git a/dGame/dInventory/ItemSetPassiveAbility.h b/dGame/dInventory/ItemSetPassiveAbility.h index ff945df2..8735e695 100644 --- a/dGame/dInventory/ItemSetPassiveAbility.h +++ b/dGame/dInventory/ItemSetPassiveAbility.h @@ -30,12 +30,12 @@ public: * Attempts to trigger a passive ability for this item set, if this is the wrong trigger this is a no-op * @param trigger the trigger to attempt to fire */ - void Trigger(PassiveAbilityTrigger trigger); + void Trigger(PassiveAbilityTrigger trigger, Entity* target = nullptr); /** * Activates the passive ability */ - void Activate(); + void Activate(Entity* target = nullptr); /** * Finds all the passive abilities associated with a certain item set @@ -47,7 +47,7 @@ public: static std::vector FindAbilities(uint32_t itemSetID, Entity* parent, ItemSet* itemSet); private: - void OnEnemySmshed(); + void OnEnemySmshed(Entity* target = nullptr); /** * The means of triggering this ability diff --git a/dScripts/ai/PROPERTY/PropertyFXDamage.cpp b/dScripts/ai/PROPERTY/PropertyFXDamage.cpp index d12cc9e1..56079384 100644 --- a/dScripts/ai/PROPERTY/PropertyFXDamage.cpp +++ b/dScripts/ai/PROPERTY/PropertyFXDamage.cpp @@ -12,7 +12,7 @@ void PropertyFXDamage::OnCollisionPhantom(Entity* self, Entity* target) { if (skills != nullptr && targetStats != nullptr) { auto targetFactions = targetStats->GetFactionIDs(); if (std::find(targetFactions.begin(), targetFactions.end(), 1) != targetFactions.end()) { - skills->CalculateBehavior(11386, 692, target->GetObjectID()); + skills->CalculateBehavior(692, 11386, target->GetObjectID()); } } }