mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2025-08-05 18:24:12 +00:00
Public release of the DLU server code!
Have fun!
This commit is contained in:
44
dGame/dBehaviors/AirMovementBehavior.cpp
Normal file
44
dGame/dBehaviors/AirMovementBehavior.cpp
Normal file
@@ -0,0 +1,44 @@
|
||||
#include "AirMovementBehavior.h"
|
||||
#include "BehaviorBranchContext.h"
|
||||
#include "BehaviorContext.h"
|
||||
#include "EntityManager.h"
|
||||
|
||||
void AirMovementBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch)
|
||||
{
|
||||
uint32_t handle;
|
||||
|
||||
bitStream->Read(handle);
|
||||
|
||||
context->RegisterSyncBehavior(handle, this, branch);
|
||||
}
|
||||
|
||||
void AirMovementBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch)
|
||||
{
|
||||
const auto handle = context->GetUniqueSkillId();
|
||||
|
||||
bitStream->Write(handle);
|
||||
}
|
||||
|
||||
void AirMovementBehavior::Sync(BehaviorContext* context, RakNet::BitStream* bit_stream, BehaviorBranchContext branch)
|
||||
{
|
||||
uint32_t behaviorId;
|
||||
|
||||
bit_stream->Read(behaviorId);
|
||||
|
||||
LWOOBJID target;
|
||||
|
||||
bit_stream->Read(target);
|
||||
|
||||
auto* behavior = CreateBehavior(behaviorId);
|
||||
|
||||
if (EntityManager::Instance()->GetEntity(target) != nullptr)
|
||||
{
|
||||
branch.target = target;
|
||||
}
|
||||
|
||||
behavior->Handle(context, bit_stream, branch);
|
||||
}
|
||||
|
||||
void AirMovementBehavior::Load()
|
||||
{
|
||||
}
|
23
dGame/dBehaviors/AirMovementBehavior.h
Normal file
23
dGame/dBehaviors/AirMovementBehavior.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
#include "Behavior.h"
|
||||
|
||||
class AirMovementBehavior final : public Behavior
|
||||
{
|
||||
public:
|
||||
|
||||
/*
|
||||
* Inherited
|
||||
*/
|
||||
|
||||
explicit AirMovementBehavior(const uint32_t behavior_id) : Behavior(behavior_id)
|
||||
{
|
||||
}
|
||||
|
||||
void Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) override;
|
||||
|
||||
void Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) override;
|
||||
|
||||
void Sync(BehaviorContext* context, RakNet::BitStream* bit_stream, BehaviorBranchContext branch) override;
|
||||
|
||||
void Load() override;
|
||||
};
|
35
dGame/dBehaviors/AndBehavior.cpp
Normal file
35
dGame/dBehaviors/AndBehavior.cpp
Normal file
@@ -0,0 +1,35 @@
|
||||
#include "AndBehavior.h"
|
||||
#include "BehaviorBranchContext.h"
|
||||
#include "Game.h"
|
||||
#include "dLogger.h"
|
||||
|
||||
void AndBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, const BehaviorBranchContext branch)
|
||||
{
|
||||
for (auto* behavior : this->m_behaviors)
|
||||
{
|
||||
behavior->Handle(context, bitStream, branch);
|
||||
}
|
||||
}
|
||||
|
||||
void AndBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, const BehaviorBranchContext branch)
|
||||
{
|
||||
for (auto* behavior : this->m_behaviors)
|
||||
{
|
||||
behavior->Calculate(context, bitStream, branch);
|
||||
}
|
||||
}
|
||||
|
||||
void AndBehavior::Load()
|
||||
{
|
||||
const auto parameters = GetParameterNames();
|
||||
|
||||
for (const auto& parameter : parameters)
|
||||
{
|
||||
if (parameter.first.rfind("behavior", 0) == 0)
|
||||
{
|
||||
auto* action = GetAction(parameter.second);
|
||||
|
||||
this->m_behaviors.push_back(action);
|
||||
}
|
||||
}
|
||||
}
|
24
dGame/dBehaviors/AndBehavior.h
Normal file
24
dGame/dBehaviors/AndBehavior.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "Behavior.h"
|
||||
|
||||
class AndBehavior final : public Behavior
|
||||
{
|
||||
public:
|
||||
std::vector<Behavior*> m_behaviors;
|
||||
|
||||
/*
|
||||
* Inherited
|
||||
*/
|
||||
explicit AndBehavior(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;
|
||||
};
|
52
dGame/dBehaviors/ApplyBuffBehavior.cpp
Normal file
52
dGame/dBehaviors/ApplyBuffBehavior.cpp
Normal file
@@ -0,0 +1,52 @@
|
||||
#include "ApplyBuffBehavior.h"
|
||||
#include "EntityManager.h"
|
||||
#include "BehaviorContext.h"
|
||||
#include "BehaviorBranchContext.h"
|
||||
#include "BuffComponent.h"
|
||||
|
||||
|
||||
void ApplyBuffBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch)
|
||||
{
|
||||
auto* entity = EntityManager::Instance()->GetEntity(branch.target == LWOOBJID_EMPTY ? context->originator : branch.target);
|
||||
|
||||
if (entity == nullptr) return;
|
||||
|
||||
auto* buffComponent = entity->GetComponent<BuffComponent>();
|
||||
|
||||
if (buffComponent == nullptr) return;
|
||||
|
||||
buffComponent->ApplyBuff(m_BuffId, m_Duration, context->originator, addImmunity, cancelOnDamaged, cancelOnDeath,
|
||||
cancelOnLogout, cancelonRemoveBuff, cancelOnUi, cancelOnUnequip, cancelOnZone);
|
||||
}
|
||||
|
||||
void ApplyBuffBehavior::UnCast(BehaviorContext* context, BehaviorBranchContext branch)
|
||||
{
|
||||
auto* entity = EntityManager::Instance()->GetEntity(branch.target);
|
||||
|
||||
if (entity == nullptr) return;
|
||||
|
||||
auto* buffComponent = entity->GetComponent<BuffComponent>();
|
||||
|
||||
if (buffComponent == nullptr) return;
|
||||
|
||||
buffComponent->RemoveBuff(m_BuffId);
|
||||
}
|
||||
|
||||
void ApplyBuffBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch)
|
||||
{
|
||||
Handle(context, bitStream, branch);
|
||||
}
|
||||
|
||||
void ApplyBuffBehavior::Load()
|
||||
{
|
||||
m_BuffId = GetInt("buff_id");
|
||||
m_Duration = GetFloat("duration_secs");
|
||||
addImmunity = GetBoolean("add_immunity");
|
||||
cancelOnDamaged = GetBoolean("cancel_on_damaged");
|
||||
cancelOnDeath = GetBoolean("cancel_on_death");
|
||||
cancelOnLogout = GetBoolean("cancel_on_logout");
|
||||
cancelonRemoveBuff = GetBoolean("cancel_on_remove_buff");
|
||||
cancelOnUi = GetBoolean("cancel_on_ui");
|
||||
cancelOnUnequip = GetBoolean("cancel_on_unequip");
|
||||
cancelOnZone = GetBoolean("cancel_on_zone");
|
||||
}
|
35
dGame/dBehaviors/ApplyBuffBehavior.h
Normal file
35
dGame/dBehaviors/ApplyBuffBehavior.h
Normal file
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "Behavior.h"
|
||||
|
||||
class ApplyBuffBehavior final : public Behavior
|
||||
{
|
||||
public:
|
||||
int32_t m_BuffId;
|
||||
float m_Duration;
|
||||
bool addImmunity;
|
||||
bool cancelOnDamaged;
|
||||
bool cancelOnDeath;
|
||||
bool cancelOnLogout;
|
||||
bool cancelonRemoveBuff;
|
||||
bool cancelOnUi;
|
||||
bool cancelOnUnequip;
|
||||
bool cancelOnZone;
|
||||
|
||||
/*
|
||||
* Inherited
|
||||
*/
|
||||
explicit ApplyBuffBehavior(const uint32_t behaviorId) : Behavior(behaviorId)
|
||||
{
|
||||
}
|
||||
|
||||
void Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) override;
|
||||
|
||||
void UnCast(BehaviorContext* context, BehaviorBranchContext branch) override;
|
||||
|
||||
void Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) override;
|
||||
|
||||
void Load() override;
|
||||
};
|
158
dGame/dBehaviors/AreaOfEffectBehavior.cpp
Normal file
158
dGame/dBehaviors/AreaOfEffectBehavior.cpp
Normal file
@@ -0,0 +1,158 @@
|
||||
#include "AreaOfEffectBehavior.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "EntityManager.h"
|
||||
#include "Game.h"
|
||||
#include "dLogger.h"
|
||||
#include "BehaviorBranchContext.h"
|
||||
#include "BehaviorContext.h"
|
||||
#include "RebuildComponent.h"
|
||||
#include "DestroyableComponent.h"
|
||||
|
||||
void AreaOfEffectBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch)
|
||||
{
|
||||
uint32_t targetCount;
|
||||
|
||||
bitStream->Read(targetCount);
|
||||
|
||||
if (targetCount > this->m_maxTargets)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<LWOOBJID> targets;
|
||||
|
||||
targets.reserve(targetCount);
|
||||
|
||||
for (auto i = 0u; i < targetCount; ++i)
|
||||
{
|
||||
LWOOBJID target;
|
||||
|
||||
bitStream->Read(target);
|
||||
|
||||
targets.push_back(target);
|
||||
}
|
||||
|
||||
for (auto target : targets)
|
||||
{
|
||||
branch.target = target;
|
||||
|
||||
this->m_action->Handle(context, bitStream, branch);
|
||||
}
|
||||
}
|
||||
|
||||
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)!\n", context->originator);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
auto reference = branch.isProjectile ? branch.referencePosition : self->GetPosition();
|
||||
|
||||
std::vector<Entity*> targets;
|
||||
|
||||
auto* presetTarget = EntityManager::Instance()->GetEntity(branch.target);
|
||||
|
||||
if (presetTarget != nullptr)
|
||||
{
|
||||
if (this->m_radius * this->m_radius >= Vector3::DistanceSquared(reference, presetTarget->GetPosition()))
|
||||
{
|
||||
targets.push_back(presetTarget);
|
||||
}
|
||||
}
|
||||
|
||||
int32_t includeFaction = m_includeFaction;
|
||||
|
||||
if (self->GetLOT() == 14466) // TODO: Fix edge case
|
||||
{
|
||||
includeFaction = 1;
|
||||
}
|
||||
|
||||
for (auto validTarget : context->GetValidTargets(m_ignoreFaction , includeFaction))
|
||||
{
|
||||
auto* entity = EntityManager::Instance()->GetEntity(validTarget);
|
||||
|
||||
if (entity == nullptr)
|
||||
{
|
||||
Game::logger->Log("TacArcBehavior", "Invalid target (%llu) for (%llu)!\n", validTarget, context->originator);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (std::find(targets.begin(), targets.end(), entity) != targets.end())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
auto* destroyableComponent = entity->GetComponent<DestroyableComponent>();
|
||||
|
||||
if (destroyableComponent == nullptr)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (destroyableComponent->HasFaction(m_ignoreFaction))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto distance = Vector3::DistanceSquared(reference, entity->GetPosition());
|
||||
|
||||
if (this->m_radius * this->m_radius >= distance && (this->m_maxTargets == 0 || targets.size() < this->m_maxTargets))
|
||||
{
|
||||
targets.push_back(entity);
|
||||
}
|
||||
}
|
||||
|
||||
std::sort(targets.begin(), targets.end(), [reference](Entity* a, Entity* b)
|
||||
{
|
||||
const auto aDistance = Vector3::DistanceSquared(a->GetPosition(), reference);
|
||||
const auto bDistance = Vector3::DistanceSquared(b->GetPosition(), reference);
|
||||
|
||||
return aDistance > bDistance;
|
||||
});
|
||||
|
||||
const uint32_t size = targets.size();
|
||||
|
||||
bitStream->Write(size);
|
||||
|
||||
if (size == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
context->foundTarget = true;
|
||||
|
||||
for (auto* target : targets)
|
||||
{
|
||||
bitStream->Write(target->GetObjectID());
|
||||
|
||||
PlayFx(u"cast", context->originator, target->GetObjectID());
|
||||
}
|
||||
|
||||
for (auto* target : targets)
|
||||
{
|
||||
branch.target = target->GetObjectID();
|
||||
|
||||
this->m_action->Calculate(context, bitStream, branch);
|
||||
}
|
||||
}
|
||||
|
||||
void AreaOfEffectBehavior::Load()
|
||||
{
|
||||
this->m_action = GetAction("action");
|
||||
|
||||
this->m_radius = GetFloat("radius");
|
||||
|
||||
this->m_maxTargets = GetInt("max targets");
|
||||
|
||||
this->m_ignoreFaction = GetInt("ignore_faction");
|
||||
|
||||
this->m_includeFaction = GetInt("include_faction");
|
||||
}
|
29
dGame/dBehaviors/AreaOfEffectBehavior.h
Normal file
29
dGame/dBehaviors/AreaOfEffectBehavior.h
Normal file
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
#include "Behavior.h"
|
||||
|
||||
class AreaOfEffectBehavior final : public Behavior
|
||||
{
|
||||
public:
|
||||
Behavior* m_action;
|
||||
|
||||
uint32_t m_maxTargets;
|
||||
|
||||
float m_radius;
|
||||
|
||||
int32_t m_ignoreFaction;
|
||||
|
||||
int32_t m_includeFaction;
|
||||
|
||||
/*
|
||||
* Inherited
|
||||
*/
|
||||
explicit AreaOfEffectBehavior(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;
|
||||
};
|
61
dGame/dBehaviors/AttackDelayBehavior.cpp
Normal file
61
dGame/dBehaviors/AttackDelayBehavior.cpp
Normal file
@@ -0,0 +1,61 @@
|
||||
#include "AttackDelayBehavior.h"
|
||||
#include "BehaviorBranchContext.h"
|
||||
#include "BehaviorContext.h"
|
||||
#include "Game.h"
|
||||
#include "dLogger.h"
|
||||
|
||||
void AttackDelayBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, const BehaviorBranchContext branch)
|
||||
{
|
||||
uint32_t handle;
|
||||
|
||||
bitStream->Read(handle);
|
||||
|
||||
for (auto i = 0u; i < this->m_numIntervals; ++i)
|
||||
{
|
||||
context->RegisterSyncBehavior(handle, this, branch);
|
||||
}
|
||||
}
|
||||
|
||||
void AttackDelayBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, const BehaviorBranchContext branch)
|
||||
{
|
||||
const auto handle = context->GetUniqueSkillId();
|
||||
|
||||
bitStream->Write(handle);
|
||||
|
||||
context->foundTarget = true;
|
||||
|
||||
for (auto i = 0u; i < this->m_numIntervals; ++i)
|
||||
{
|
||||
const auto multiple = static_cast<float>(i + 1);
|
||||
|
||||
context->SyncCalculation(handle, this->m_delay * multiple, this, branch, m_ignoreInterrupts);
|
||||
}
|
||||
}
|
||||
|
||||
void AttackDelayBehavior::Sync(BehaviorContext* context, RakNet::BitStream* bitStream, const BehaviorBranchContext branch)
|
||||
{
|
||||
this->m_action->Handle(context, bitStream, branch);
|
||||
}
|
||||
|
||||
void AttackDelayBehavior::SyncCalculation(BehaviorContext* context, RakNet::BitStream* bitStream, const BehaviorBranchContext branch)
|
||||
{
|
||||
PlayFx(u"cast", context->originator);
|
||||
|
||||
this->m_action->Calculate(context, bitStream, branch);
|
||||
}
|
||||
|
||||
void AttackDelayBehavior::Load()
|
||||
{
|
||||
this->m_numIntervals = GetInt("num_intervals");
|
||||
|
||||
this->m_action = GetAction("action");
|
||||
|
||||
this->m_delay = GetFloat("delay");
|
||||
|
||||
this->m_ignoreInterrupts = GetBoolean("ignore_interrupts");
|
||||
|
||||
if (this->m_numIntervals == 0)
|
||||
{
|
||||
this->m_numIntervals = 1;
|
||||
}
|
||||
}
|
32
dGame/dBehaviors/AttackDelayBehavior.h
Normal file
32
dGame/dBehaviors/AttackDelayBehavior.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
#include "Behavior.h"
|
||||
|
||||
class AttackDelayBehavior final : public Behavior
|
||||
{
|
||||
public:
|
||||
Behavior* m_action;
|
||||
|
||||
float m_delay;
|
||||
|
||||
uint32_t m_numIntervals;
|
||||
|
||||
bool m_ignoreInterrupts;
|
||||
|
||||
/*
|
||||
* Inherited
|
||||
*/
|
||||
|
||||
explicit AttackDelayBehavior(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 Sync(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) override;
|
||||
|
||||
void SyncCalculation(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) override;
|
||||
|
||||
void Load() override;
|
||||
};
|
150
dGame/dBehaviors/BasicAttackBehavior.cpp
Normal file
150
dGame/dBehaviors/BasicAttackBehavior.cpp
Normal file
@@ -0,0 +1,150 @@
|
||||
#include "BasicAttackBehavior.h"
|
||||
#include "BehaviorBranchContext.h"
|
||||
#include "Game.h"
|
||||
#include "dLogger.h"
|
||||
#include "EntityManager.h"
|
||||
#include "DestroyableComponent.h"
|
||||
#include "BehaviorContext.h"
|
||||
|
||||
|
||||
void BasicAttackBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
|
||||
if (context->unmanaged) {
|
||||
auto* entity = EntityManager::Instance()->GetEntity(branch.target);
|
||||
|
||||
auto* destroyableComponent = entity->GetComponent<DestroyableComponent>();
|
||||
if (destroyableComponent != nullptr) {
|
||||
PlayFx(u"onhit", entity->GetObjectID());
|
||||
destroyableComponent->Damage(this->m_maxDamage, context->originator);
|
||||
}
|
||||
|
||||
this->m_onSuccess->Handle(context, bitStream, branch);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
bitStream->AlignReadToByteBoundary();
|
||||
|
||||
uint16_t allocatedBits;
|
||||
bitStream->Read(allocatedBits);
|
||||
|
||||
const auto baseAddress = bitStream->GetReadOffset();
|
||||
if (bitStream->ReadBit()) { // Blocked
|
||||
return;
|
||||
}
|
||||
|
||||
if (bitStream->ReadBit()) { // Immune
|
||||
return;
|
||||
}
|
||||
|
||||
if (bitStream->ReadBit()) { // Success
|
||||
uint32_t unknown;
|
||||
bitStream->Read(unknown);
|
||||
|
||||
uint32_t damageDealt;
|
||||
bitStream->Read(damageDealt);
|
||||
|
||||
// A value that's too large may be a cheating attempt, so we set it to MIN too
|
||||
if (damageDealt > this->m_maxDamage || damageDealt < this->m_minDamage) {
|
||||
damageDealt = this->m_minDamage;
|
||||
}
|
||||
|
||||
auto* entity = EntityManager::Instance()->GetEntity(branch.target);
|
||||
bool died;
|
||||
bitStream->Read(died);
|
||||
|
||||
if (entity != nullptr) {
|
||||
auto* destroyableComponent = entity->GetComponent<DestroyableComponent>();
|
||||
if (destroyableComponent != nullptr) {
|
||||
PlayFx(u"onhit", entity->GetObjectID());
|
||||
destroyableComponent->Damage(damageDealt, context->originator);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t successState;
|
||||
bitStream->Read(successState);
|
||||
|
||||
switch (successState) {
|
||||
case 1:
|
||||
this->m_onSuccess->Handle(context, bitStream, branch);
|
||||
break;
|
||||
default:
|
||||
Game::logger->Log("BasicAttackBehavior", "Unknown success state (%i)!\n", successState);
|
||||
break;
|
||||
}
|
||||
|
||||
bitStream->SetReadOffset(baseAddress + allocatedBits);
|
||||
}
|
||||
|
||||
void BasicAttackBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
|
||||
auto* self = EntityManager::Instance()->GetEntity(context->originator);
|
||||
if (self == nullptr) {
|
||||
Game::logger->Log("BasicAttackBehavior", "Invalid self entity (%llu)!\n", context->originator);
|
||||
return;
|
||||
}
|
||||
|
||||
bitStream->AlignWriteToByteBoundary();
|
||||
|
||||
const auto allocatedAddress = bitStream->GetWriteOffset();
|
||||
|
||||
bitStream->Write(uint16_t(0));
|
||||
|
||||
const auto startAddress = bitStream->GetWriteOffset();
|
||||
|
||||
bitStream->Write0(); // Blocked
|
||||
bitStream->Write0(); // Immune
|
||||
bitStream->Write1(); // Success
|
||||
|
||||
if (true) {
|
||||
uint32_t unknown3 = 0;
|
||||
bitStream->Write(unknown3);
|
||||
|
||||
auto damage = this->m_minDamage;
|
||||
auto* entity = EntityManager::Instance()->GetEntity(branch.target);
|
||||
|
||||
if (entity == nullptr) {
|
||||
damage = 0;
|
||||
bitStream->Write(damage);
|
||||
bitStream->Write(false);
|
||||
} else {
|
||||
bitStream->Write(damage);
|
||||
bitStream->Write(true);
|
||||
|
||||
auto* destroyableComponent = entity->GetComponent<DestroyableComponent>();
|
||||
if (damage != 0 && destroyableComponent != nullptr) {
|
||||
PlayFx(u"onhit", entity->GetObjectID(), 1);
|
||||
destroyableComponent->Damage(damage, context->originator, false);
|
||||
context->ScheduleUpdate(branch.target);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t successState = 1;
|
||||
bitStream->Write(successState);
|
||||
|
||||
switch (successState) {
|
||||
case 1:
|
||||
this->m_onSuccess->Calculate(context, bitStream, branch);
|
||||
break;
|
||||
default:
|
||||
Game::logger->Log("BasicAttackBehavior", "Unknown success state (%i)!\n", successState);
|
||||
break;
|
||||
}
|
||||
|
||||
const auto endAddress = bitStream->GetWriteOffset();
|
||||
const uint16_t allocate = endAddress - startAddress + 1;
|
||||
|
||||
bitStream->SetWriteOffset(allocatedAddress);
|
||||
bitStream->Write(allocate);
|
||||
bitStream->SetWriteOffset(startAddress + allocate);
|
||||
}
|
||||
|
||||
void BasicAttackBehavior::Load() {
|
||||
this->m_minDamage = GetInt("min damage");
|
||||
if (this->m_minDamage == 0) this->m_minDamage = 1;
|
||||
|
||||
this->m_maxDamage = GetInt("max damage");
|
||||
if (this->m_maxDamage == 0) this->m_maxDamage = 1;
|
||||
|
||||
this->m_onSuccess = GetAction("on_success");
|
||||
}
|
22
dGame/dBehaviors/BasicAttackBehavior.h
Normal file
22
dGame/dBehaviors/BasicAttackBehavior.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
#include "Behavior.h"
|
||||
|
||||
class BasicAttackBehavior final : public Behavior
|
||||
{
|
||||
public:
|
||||
uint32_t m_minDamage;
|
||||
|
||||
uint32_t m_maxDamage;
|
||||
|
||||
Behavior* m_onSuccess;
|
||||
|
||||
explicit BasicAttackBehavior(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;
|
||||
};
|
547
dGame/dBehaviors/Behavior.cpp
Normal file
547
dGame/dBehaviors/Behavior.cpp
Normal file
@@ -0,0 +1,547 @@
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
|
||||
#include "Behavior.h"
|
||||
#include "CDActivitiesTable.h"
|
||||
#include "Game.h"
|
||||
#include "dLogger.h"
|
||||
#include "BehaviorTemplates.h"
|
||||
#include "BehaviorBranchContext.h"
|
||||
|
||||
/*
|
||||
* Behavior includes
|
||||
*/
|
||||
#include "AirMovementBehavior.h"
|
||||
#include "EmptyBehavior.h"
|
||||
#include "MovementSwitchBehavior.h"
|
||||
#include "AndBehavior.h"
|
||||
#include "AreaOfEffectBehavior.h"
|
||||
#include "DurationBehavior.h"
|
||||
#include "TacArcBehavior.h"
|
||||
#include "AttackDelayBehavior.h"
|
||||
#include "BasicAttackBehavior.h"
|
||||
#include "ChainBehavior.h"
|
||||
#include "ChargeUpBehavior.h"
|
||||
#include "GameMessages.h"
|
||||
#include "HealBehavior.h"
|
||||
#include "ImaginationBehavior.h"
|
||||
#include "KnockbackBehavior.h"
|
||||
#include "NpcCombatSkillBehavior.h"
|
||||
#include "StartBehavior.h"
|
||||
#include "StunBehavior.h"
|
||||
#include "ProjectileAttackBehavior.h"
|
||||
#include "RepairBehavior.h"
|
||||
#include "SwitchBehavior.h"
|
||||
#include "SwitchMultipleBehavior.h"
|
||||
#include "TargetCasterBehavior.h"
|
||||
#include "VerifyBehavior.h"
|
||||
#include "BuffBehavior.h"
|
||||
#include "TauntBehavior.h"
|
||||
#include "SkillCastFailedBehavior.h"
|
||||
#include "SpawnBehavior.h"
|
||||
#include "ForceMovementBehavior.h"
|
||||
#include "ImmunityBehavior.h"
|
||||
#include "InterruptBehavior.h"
|
||||
#include "PlayEffectBehavior.h"
|
||||
#include "DamageAbsorptionBehavior.h"
|
||||
#include "BlockBehavior.h"
|
||||
#include "ClearTargetBehavior.h"
|
||||
#include "PullToPointBehavior.h"
|
||||
#include "EndBehavior.h"
|
||||
#include "ChangeOrientationBehavior.h"
|
||||
#include "OverTimeBehavior.h"
|
||||
#include "ApplyBuffBehavior.h"
|
||||
#include "CarBoostBehavior.h"
|
||||
#include "SkillEventBehavior.h"
|
||||
#include "SpeedBehavior.h"
|
||||
#include "DamageReductionBehavior.h"
|
||||
|
||||
//CDClient includes
|
||||
#include "CDBehaviorParameterTable.h"
|
||||
#include "CDClientDatabase.h"
|
||||
#include "CDClientManager.h"
|
||||
|
||||
//Other includes
|
||||
#include "EntityManager.h"
|
||||
#include "RenderComponent.h"
|
||||
#include "DestroyableComponent.h"
|
||||
|
||||
std::map<uint32_t, Behavior*> Behavior::Cache = {};
|
||||
CDBehaviorParameterTable* Behavior::BehaviorParameterTable = nullptr;
|
||||
|
||||
Behavior* Behavior::GetBehavior(const uint32_t behaviorId)
|
||||
{
|
||||
if (BehaviorParameterTable == nullptr)
|
||||
{
|
||||
BehaviorParameterTable = CDClientManager::Instance()->GetTable<CDBehaviorParameterTable>("BehaviorParameter");
|
||||
}
|
||||
|
||||
const auto pair = Cache.find(behaviorId);
|
||||
|
||||
if (pair == Cache.end())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return static_cast<Behavior*>(pair->second);
|
||||
}
|
||||
|
||||
Behavior* Behavior::CreateBehavior(const uint32_t behaviorId)
|
||||
{
|
||||
auto* cached = GetBehavior(behaviorId);
|
||||
|
||||
if (cached != nullptr)
|
||||
{
|
||||
return cached;
|
||||
}
|
||||
|
||||
if (behaviorId == 0)
|
||||
{
|
||||
return new EmptyBehavior(0);
|
||||
}
|
||||
|
||||
const auto templateId = GetBehaviorTemplate(behaviorId);
|
||||
|
||||
Behavior* behavior = nullptr;
|
||||
|
||||
switch (templateId)
|
||||
{
|
||||
case BehaviorTemplates::BEHAVIOR_EMPTY: break;
|
||||
case BehaviorTemplates::BEHAVIOR_BASIC_ATTACK:
|
||||
behavior = new BasicAttackBehavior(behaviorId);
|
||||
break;
|
||||
case BehaviorTemplates::BEHAVIOR_TAC_ARC:
|
||||
behavior = new TacArcBehavior(behaviorId);
|
||||
break;
|
||||
case BehaviorTemplates::BEHAVIOR_AND:
|
||||
behavior = new AndBehavior(behaviorId);
|
||||
break;
|
||||
case BehaviorTemplates::BEHAVIOR_PROJECTILE_ATTACK:
|
||||
behavior = new ProjectileAttackBehavior(behaviorId);
|
||||
break;
|
||||
case BehaviorTemplates::BEHAVIOR_HEAL:
|
||||
behavior = new HealBehavior(behaviorId);
|
||||
break;
|
||||
case BehaviorTemplates::BEHAVIOR_MOVEMENT_SWITCH:
|
||||
behavior = new MovementSwitchBehavior(behaviorId);
|
||||
break;
|
||||
case BehaviorTemplates::BEHAVIOR_AREA_OF_EFFECT:
|
||||
behavior = new AreaOfEffectBehavior(behaviorId);
|
||||
break;
|
||||
case BehaviorTemplates::BEHAVIOR_PLAY_EFFECT:
|
||||
behavior = new PlayEffectBehavior(behaviorId);
|
||||
break;
|
||||
case BehaviorTemplates::BEHAVIOR_IMMUNITY:
|
||||
behavior = new ImmunityBehavior(behaviorId);
|
||||
break;
|
||||
case BehaviorTemplates::BEHAVIOR_DAMAGE_BUFF: break;
|
||||
case BehaviorTemplates::BEHAVIOR_DAMAGE_ABSORBTION:
|
||||
behavior = new DamageAbsorptionBehavior(behaviorId);
|
||||
break;
|
||||
case BehaviorTemplates::BEHAVIOR_OVER_TIME:
|
||||
behavior = new OverTimeBehavior(behaviorId);
|
||||
break;
|
||||
case BehaviorTemplates::BEHAVIOR_IMAGINATION:
|
||||
behavior = new ImaginationBehavior(behaviorId);
|
||||
break;
|
||||
case BehaviorTemplates::BEHAVIOR_TARGET_CASTER:
|
||||
behavior = new TargetCasterBehavior(behaviorId);
|
||||
break;
|
||||
case BehaviorTemplates::BEHAVIOR_STUN:
|
||||
behavior = new StunBehavior(behaviorId);
|
||||
break;
|
||||
case BehaviorTemplates::BEHAVIOR_DURATION:
|
||||
behavior = new DurationBehavior(behaviorId);
|
||||
break;
|
||||
case BehaviorTemplates::BEHAVIOR_KNOCKBACK:
|
||||
behavior = new KnockbackBehavior(behaviorId);
|
||||
break;
|
||||
case BehaviorTemplates::BEHAVIOR_ATTACK_DELAY:
|
||||
behavior = new AttackDelayBehavior(behaviorId);
|
||||
break;
|
||||
case BehaviorTemplates::BEHAVIOR_CAR_BOOST:
|
||||
behavior = new CarBoostBehavior(behaviorId);
|
||||
break;
|
||||
case BehaviorTemplates::BEHAVIOR_FALL_SPEED: break;
|
||||
case BehaviorTemplates::BEHAVIOR_SHIELD: break;
|
||||
case BehaviorTemplates::BEHAVIOR_REPAIR_ARMOR:
|
||||
behavior = new RepairBehavior(behaviorId);
|
||||
break;
|
||||
case BehaviorTemplates::BEHAVIOR_SPEED:
|
||||
behavior = new SpeedBehavior(behaviorId);
|
||||
break;
|
||||
case BehaviorTemplates::BEHAVIOR_DARK_INSPIRATION: break;
|
||||
case BehaviorTemplates::BEHAVIOR_LOOT_BUFF: break;
|
||||
case BehaviorTemplates::BEHAVIOR_VENTURE_VISION: break;
|
||||
case BehaviorTemplates::BEHAVIOR_SPAWN_OBJECT:
|
||||
behavior = new SpawnBehavior(behaviorId);
|
||||
break;
|
||||
case BehaviorTemplates::BEHAVIOR_LAY_BRICK: break;
|
||||
case BehaviorTemplates::BEHAVIOR_SWITCH:
|
||||
behavior = new SwitchBehavior(behaviorId);
|
||||
break;
|
||||
case BehaviorTemplates::BEHAVIOR_BUFF:
|
||||
behavior = new BuffBehavior(behaviorId);
|
||||
break;
|
||||
case BehaviorTemplates::BEHAVIOR_JETPACK: break;
|
||||
case BehaviorTemplates::BEHAVIOR_SKILL_EVENT:
|
||||
behavior = new SkillEventBehavior(behaviorId);
|
||||
break;
|
||||
case BehaviorTemplates::BEHAVIOR_CONSUME_ITEM: break;
|
||||
case BehaviorTemplates::BEHAVIOR_SKILL_CAST_FAILED:
|
||||
behavior = new SkillCastFailedBehavior(behaviorId);
|
||||
break;
|
||||
case BehaviorTemplates::BEHAVIOR_IMITATION_SKUNK_STINK: break;
|
||||
case BehaviorTemplates::BEHAVIOR_CHANGE_IDLE_FLAGS: break;
|
||||
case BehaviorTemplates::BEHAVIOR_APPLY_BUFF:
|
||||
behavior = new ApplyBuffBehavior(behaviorId);
|
||||
break;
|
||||
case BehaviorTemplates::BEHAVIOR_CHAIN:
|
||||
behavior = new ChainBehavior(behaviorId);
|
||||
break;
|
||||
case BehaviorTemplates::BEHAVIOR_CHANGE_ORIENTATION:
|
||||
behavior = new ChangeOrientationBehavior(behaviorId);
|
||||
break;
|
||||
case BehaviorTemplates::BEHAVIOR_FORCE_MOVEMENT:
|
||||
behavior = new ForceMovementBehavior(behaviorId);
|
||||
break;
|
||||
case BehaviorTemplates::BEHAVIOR_INTERRUPT:
|
||||
behavior = new InterruptBehavior(behaviorId);
|
||||
break;
|
||||
case BehaviorTemplates::BEHAVIOR_ALTER_COOLDOWN: break;
|
||||
case BehaviorTemplates::BEHAVIOR_CHARGE_UP:
|
||||
behavior = new ChargeUpBehavior(behaviorId);
|
||||
break;
|
||||
case BehaviorTemplates::BEHAVIOR_SWITCH_MULTIPLE:
|
||||
behavior = new SwitchMultipleBehavior(behaviorId);
|
||||
break;
|
||||
case BehaviorTemplates::BEHAVIOR_START:
|
||||
behavior = new StartBehavior(behaviorId);
|
||||
break;
|
||||
case BehaviorTemplates::BEHAVIOR_END:
|
||||
behavior = new EndBehavior(behaviorId);
|
||||
break;
|
||||
case BehaviorTemplates::BEHAVIOR_ALTER_CHAIN_DELAY: break;
|
||||
case BehaviorTemplates::BEHAVIOR_CAMERA: break;
|
||||
case BehaviorTemplates::BEHAVIOR_REMOVE_BUFF: break;
|
||||
case BehaviorTemplates::BEHAVIOR_GRAB: break;
|
||||
case BehaviorTemplates::BEHAVIOR_MODULAR_BUILD: break;
|
||||
case BehaviorTemplates::BEHAVIOR_NPC_COMBAT_SKILL:
|
||||
behavior = new NpcCombatSkillBehavior(behaviorId);
|
||||
break;
|
||||
case BehaviorTemplates::BEHAVIOR_BLOCK:
|
||||
behavior = new BlockBehavior(behaviorId);
|
||||
break;
|
||||
case BehaviorTemplates::BEHAVIOR_VERIFY:
|
||||
behavior = new VerifyBehavior(behaviorId);
|
||||
break;
|
||||
case BehaviorTemplates::BEHAVIOR_TAUNT:
|
||||
behavior = new TauntBehavior(behaviorId);
|
||||
break;
|
||||
case BehaviorTemplates::BEHAVIOR_AIR_MOVEMENT:
|
||||
behavior = new AirMovementBehavior(behaviorId);
|
||||
break;
|
||||
case BehaviorTemplates::BEHAVIOR_SPAWN_QUICKBUILD:
|
||||
behavior = new SpawnBehavior(behaviorId);
|
||||
break;
|
||||
case BehaviorTemplates::BEHAVIOR_PULL_TO_POINT:
|
||||
behavior = new PullToPointBehavior(behaviorId);
|
||||
break;
|
||||
case BehaviorTemplates::BEHAVIOR_PROPERTY_ROTATE: break;
|
||||
case BehaviorTemplates::BEHAVIOR_DAMAGE_REDUCTION:
|
||||
behavior = new DamageReductionBehavior(behaviorId);
|
||||
break;
|
||||
case BehaviorTemplates::BEHAVIOR_PROPERTY_TELEPORT: break;
|
||||
case BehaviorTemplates::BEHAVIOR_PROPERTY_CLEAR_TARGET:
|
||||
behavior = new ClearTargetBehavior(behaviorId);
|
||||
break;
|
||||
case BehaviorTemplates::BEHAVIOR_TAKE_PICTURE: break;
|
||||
case BehaviorTemplates::BEHAVIOR_MOUNT: break;
|
||||
case BehaviorTemplates::BEHAVIOR_SKILL_SET: break;
|
||||
default:
|
||||
//Game::logger->Log("Behavior", "Failed to load behavior with invalid template id (%i)!\n", templateId);
|
||||
break;
|
||||
}
|
||||
|
||||
if (behavior == nullptr)
|
||||
{
|
||||
//Game::logger->Log("Behavior", "Failed to load unimplemented template id (%i)!\n", templateId);
|
||||
|
||||
behavior = new EmptyBehavior(behaviorId);
|
||||
}
|
||||
|
||||
behavior->Load();
|
||||
|
||||
return behavior;
|
||||
}
|
||||
|
||||
BehaviorTemplates Behavior::GetBehaviorTemplate(const uint32_t behaviorId)
|
||||
{
|
||||
std::stringstream query;
|
||||
|
||||
query << "SELECT templateID FROM BehaviorTemplate WHERE behaviorID = " << std::to_string(behaviorId);
|
||||
|
||||
auto result = CDClientDatabase::ExecuteQuery(query.str());
|
||||
|
||||
// Make sure we do not proceed if we are trying to load an invalid behavior
|
||||
if (result.eof())
|
||||
{
|
||||
if (behaviorId != 0)
|
||||
{
|
||||
Game::logger->Log("Behavior::GetBehaviorTemplate", "Failed to load behavior template with id (%i)!\n", behaviorId);
|
||||
}
|
||||
|
||||
return BehaviorTemplates::BEHAVIOR_EMPTY;
|
||||
}
|
||||
|
||||
const auto id = static_cast<BehaviorTemplates>(result.getIntField(0));
|
||||
|
||||
result.finalize();
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
// For use with enemies, to display the correct damage animations on the players
|
||||
void Behavior::PlayFx(std::u16string type, const LWOOBJID target, const LWOOBJID secondary)
|
||||
{
|
||||
auto* targetEntity = EntityManager::Instance()->GetEntity(target);
|
||||
|
||||
if (targetEntity == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const auto effectId = this->m_effectId;
|
||||
|
||||
if (effectId == 0)
|
||||
{
|
||||
GameMessages::SendPlayFXEffect(targetEntity, -1, type, "", secondary, 1, 1, true);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
auto* renderComponent = targetEntity->GetComponent<RenderComponent>();
|
||||
|
||||
const auto typeString = GeneralUtils::UTF16ToWTF8(type);
|
||||
|
||||
if (m_effectNames == nullptr)
|
||||
{
|
||||
m_effectNames = new std::unordered_map<std::string, std::string>();
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto pair = m_effectNames->find(typeString);
|
||||
|
||||
if (type.empty())
|
||||
{
|
||||
type = GeneralUtils::ASCIIToUTF16(*m_effectType);
|
||||
}
|
||||
|
||||
if (pair != m_effectNames->end())
|
||||
{
|
||||
if (renderComponent == nullptr)
|
||||
{
|
||||
GameMessages::SendPlayFXEffect(targetEntity, effectId, type, pair->second, secondary, 1, 1, true);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
renderComponent->PlayEffect(effectId, type, pair->second, secondary);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
std::stringstream query;
|
||||
|
||||
if (!type.empty())
|
||||
{
|
||||
query << "SELECT effectName FROM BehaviorEffect WHERE effectType = '" << typeString << "' AND effectID = " << std::to_string(effectId) << ";";
|
||||
}
|
||||
else
|
||||
{
|
||||
query << "SELECT effectName, effectType FROM BehaviorEffect WHERE effectID = " << std::to_string(effectId) << ";";
|
||||
}
|
||||
|
||||
auto result = CDClientDatabase::ExecuteQuery(query.str());
|
||||
|
||||
if (result.eof() || result.fieldIsNull(0))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const auto name = std::string(result.getStringField(0));
|
||||
|
||||
if (type.empty())
|
||||
{
|
||||
const auto typeResult = result.getStringField(1);
|
||||
|
||||
type = GeneralUtils::ASCIIToUTF16(typeResult);
|
||||
|
||||
m_effectType = new std::string(typeResult);
|
||||
}
|
||||
|
||||
result.finalize();
|
||||
|
||||
m_effectNames->insert_or_assign(typeString, name);
|
||||
|
||||
if (renderComponent == nullptr)
|
||||
{
|
||||
GameMessages::SendPlayFXEffect(targetEntity, effectId, type, name, secondary, 1, 1, true);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
renderComponent->PlayEffect(effectId, type, name, secondary);
|
||||
}
|
||||
|
||||
Behavior::Behavior(const uint32_t behaviorId)
|
||||
{
|
||||
this->m_behaviorId = behaviorId;
|
||||
|
||||
// Add to cache
|
||||
Cache.insert_or_assign(behaviorId, this);
|
||||
|
||||
if (behaviorId == 0) {
|
||||
this->m_effectId = 0;
|
||||
this->m_effectHandle = nullptr;
|
||||
this->m_templateId = BehaviorTemplates::BEHAVIOR_EMPTY;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get standard info
|
||||
*/
|
||||
|
||||
std::stringstream query;
|
||||
|
||||
query << "SELECT templateID, effectID, effectHandle FROM BehaviorTemplate WHERE behaviorID = " << std::to_string(behaviorId);
|
||||
|
||||
auto result = CDClientDatabase::ExecuteQuery(query.str());
|
||||
|
||||
// Make sure we do not proceed if we are trying to load an invalid behavior
|
||||
if (result.eof())
|
||||
{
|
||||
Game::logger->Log("Behavior", "Failed to load behavior with id (%i)!\n", behaviorId);
|
||||
|
||||
this->m_effectId = 0;
|
||||
this->m_effectHandle = nullptr;
|
||||
this->m_templateId = BehaviorTemplates::BEHAVIOR_EMPTY;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
this->m_templateId = static_cast<BehaviorTemplates>(result.getIntField(0));
|
||||
|
||||
this->m_effectId = result.getIntField(1);
|
||||
|
||||
if (!result.fieldIsNull(2))
|
||||
{
|
||||
const std::string effectHandle = result.getStringField(2);
|
||||
if (effectHandle == "")
|
||||
{
|
||||
this->m_effectHandle = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->m_effectHandle = new std::string(effectHandle);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this->m_effectHandle = nullptr;
|
||||
}
|
||||
|
||||
result.finalize();
|
||||
}
|
||||
|
||||
|
||||
float Behavior::GetFloat(const std::string& name) const
|
||||
{
|
||||
return BehaviorParameterTable->GetEntry(this->m_behaviorId, name);
|
||||
}
|
||||
|
||||
|
||||
bool Behavior::GetBoolean(const std::string& name) const
|
||||
{
|
||||
return GetFloat(name) > 0;
|
||||
}
|
||||
|
||||
|
||||
int32_t Behavior::GetInt(const std::string& name) const
|
||||
{
|
||||
return static_cast<int32_t>(GetFloat(name));
|
||||
}
|
||||
|
||||
|
||||
Behavior* Behavior::GetAction(const std::string& name) const
|
||||
{
|
||||
const auto id = GetInt(name);
|
||||
|
||||
return CreateBehavior(id);
|
||||
}
|
||||
|
||||
Behavior* Behavior::GetAction(float value) const
|
||||
{
|
||||
return CreateBehavior(static_cast<int32_t>(value));
|
||||
}
|
||||
|
||||
std::map<std::string, float> Behavior::GetParameterNames() const
|
||||
{
|
||||
std::map<std::string, float> parameters;
|
||||
|
||||
std::stringstream query;
|
||||
|
||||
query << "SELECT parameterID, value FROM BehaviorParameter WHERE behaviorID = " << std::to_string(this->m_behaviorId);
|
||||
|
||||
auto tableData = CDClientDatabase::ExecuteQuery(query.str());
|
||||
|
||||
while (!tableData.eof())
|
||||
{
|
||||
parameters.insert_or_assign(tableData.getStringField(0, ""), tableData.getFloatField(1, 0));
|
||||
|
||||
tableData.nextRow();
|
||||
}
|
||||
|
||||
tableData.finalize();
|
||||
|
||||
return parameters;
|
||||
}
|
||||
|
||||
void Behavior::Load()
|
||||
{
|
||||
}
|
||||
|
||||
void Behavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch)
|
||||
{
|
||||
}
|
||||
|
||||
void Behavior::Sync(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch)
|
||||
{
|
||||
}
|
||||
|
||||
void Behavior::UnCast(BehaviorContext* context, BehaviorBranchContext branch)
|
||||
{
|
||||
}
|
||||
|
||||
void Behavior::Timer(BehaviorContext* context, BehaviorBranchContext branch, LWOOBJID second)
|
||||
{
|
||||
}
|
||||
|
||||
void Behavior::End(BehaviorContext* context, BehaviorBranchContext branch, LWOOBJID second)
|
||||
{
|
||||
}
|
||||
|
||||
void Behavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch)
|
||||
{
|
||||
}
|
||||
|
||||
void Behavior::SyncCalculation(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch)
|
||||
{
|
||||
}
|
||||
|
||||
Behavior::~Behavior()
|
||||
{
|
||||
delete m_effectNames;
|
||||
delete m_effectType;
|
||||
delete m_effectHandle;
|
||||
}
|
92
dGame/dBehaviors/Behavior.h
Normal file
92
dGame/dBehaviors/Behavior.h
Normal file
@@ -0,0 +1,92 @@
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "BitStream.h"
|
||||
#include "BehaviorTemplates.h"
|
||||
#include "dCommonVars.h"
|
||||
|
||||
struct BehaviorContext;
|
||||
struct BehaviorBranchContext;
|
||||
class CDBehaviorParameterTable;
|
||||
|
||||
class Behavior
|
||||
{
|
||||
public:
|
||||
/*
|
||||
* Static
|
||||
*/
|
||||
static std::map<uint32_t, Behavior*> Cache;
|
||||
static CDBehaviorParameterTable* BehaviorParameterTable;
|
||||
|
||||
static Behavior* GetBehavior(uint32_t behaviorId);
|
||||
|
||||
static Behavior* CreateBehavior(uint32_t behaviorId);
|
||||
|
||||
static BehaviorTemplates GetBehaviorTemplate(uint32_t behaviorId);
|
||||
|
||||
/*
|
||||
* Utilities
|
||||
*/
|
||||
|
||||
void PlayFx(std::u16string type, LWOOBJID target, LWOOBJID secondary = LWOOBJID_EMPTY);
|
||||
|
||||
/*
|
||||
* Members
|
||||
*/
|
||||
|
||||
uint32_t m_behaviorId;
|
||||
BehaviorTemplates m_templateId;
|
||||
uint32_t m_effectId;
|
||||
std::string* m_effectHandle = nullptr;
|
||||
std::unordered_map<std::string, std::string>* m_effectNames = nullptr;
|
||||
std::string* m_effectType = nullptr;
|
||||
|
||||
/*
|
||||
* Behavior parameters
|
||||
*/
|
||||
|
||||
float GetFloat(const std::string& name) const;
|
||||
|
||||
bool GetBoolean(const std::string& name) const;
|
||||
|
||||
int32_t GetInt(const std::string& name) const;
|
||||
|
||||
Behavior* GetAction(const std::string& name) const;
|
||||
|
||||
Behavior* GetAction(float value) const;
|
||||
|
||||
std::map<std::string, float> GetParameterNames() const;
|
||||
|
||||
/*
|
||||
* Virtual
|
||||
*/
|
||||
|
||||
virtual void Load();
|
||||
|
||||
// Player side
|
||||
virtual void Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch);
|
||||
|
||||
virtual void Sync(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch);
|
||||
|
||||
virtual void UnCast(BehaviorContext* context, BehaviorBranchContext branch);
|
||||
|
||||
virtual void Timer(BehaviorContext* context, BehaviorBranchContext branch, LWOOBJID second);
|
||||
|
||||
virtual void End(BehaviorContext* context, BehaviorBranchContext branch, LWOOBJID second);
|
||||
|
||||
// Npc side
|
||||
virtual void Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch);
|
||||
|
||||
virtual void SyncCalculation(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch);
|
||||
|
||||
/*
|
||||
* Creations/destruction
|
||||
*/
|
||||
|
||||
explicit Behavior(uint32_t behaviorId);
|
||||
virtual ~Behavior();
|
||||
};
|
15
dGame/dBehaviors/BehaviorBranchContext.cpp
Normal file
15
dGame/dBehaviors/BehaviorBranchContext.cpp
Normal file
@@ -0,0 +1,15 @@
|
||||
#include "BehaviorBranchContext.h"
|
||||
|
||||
|
||||
BehaviorBranchContext::BehaviorBranchContext()
|
||||
{
|
||||
this->isProjectile = false;
|
||||
}
|
||||
|
||||
BehaviorBranchContext::BehaviorBranchContext(const LWOOBJID target, const float duration, const NiPoint3& referencePosition)
|
||||
{
|
||||
this->target = target;
|
||||
this->duration = duration;
|
||||
this->referencePosition = referencePosition;
|
||||
this->isProjectile = false;
|
||||
}
|
21
dGame/dBehaviors/BehaviorBranchContext.h
Normal file
21
dGame/dBehaviors/BehaviorBranchContext.h
Normal file
@@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include "dCommonVars.h"
|
||||
#include "NiPoint3.h"
|
||||
|
||||
struct BehaviorBranchContext
|
||||
{
|
||||
LWOOBJID target = LWOOBJID_EMPTY;
|
||||
|
||||
float duration = 0;
|
||||
|
||||
NiPoint3 referencePosition = {};
|
||||
|
||||
bool isProjectile = false;
|
||||
|
||||
uint32_t start = 0;
|
||||
|
||||
BehaviorBranchContext();
|
||||
|
||||
BehaviorBranchContext(LWOOBJID target, float duration = 0, const NiPoint3& referencePosition = NiPoint3(0, 0, 0));
|
||||
};
|
400
dGame/dBehaviors/BehaviorContext.cpp
Normal file
400
dGame/dBehaviors/BehaviorContext.cpp
Normal file
@@ -0,0 +1,400 @@
|
||||
#include "BehaviorContext.h"
|
||||
#include "Behavior.h"
|
||||
#include "BehaviorBranchContext.h"
|
||||
#include "EntityManager.h"
|
||||
#include "SkillComponent.h"
|
||||
#include "Game.h"
|
||||
#include "dLogger.h"
|
||||
#include "dServer.h"
|
||||
#include "PacketUtils.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
|
||||
#include "DestroyableComponent.h"
|
||||
#include "PhantomPhysicsComponent.h"
|
||||
#include "RebuildComponent.h"
|
||||
|
||||
BehaviorSyncEntry::BehaviorSyncEntry()
|
||||
{
|
||||
}
|
||||
|
||||
BehaviorTimerEntry::BehaviorTimerEntry()
|
||||
{
|
||||
}
|
||||
|
||||
BehaviorEndEntry::BehaviorEndEntry()
|
||||
{
|
||||
}
|
||||
|
||||
uint32_t BehaviorContext::GetUniqueSkillId() const
|
||||
{
|
||||
auto* entity = EntityManager::Instance()->GetEntity(this->originator);
|
||||
|
||||
if (entity == nullptr)
|
||||
{
|
||||
Game::logger->Log("BehaviorContext", "Invalid entity for (%llu)!\n", this->originator);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto* component = entity->GetComponent<SkillComponent>();
|
||||
|
||||
if (component == nullptr)
|
||||
{
|
||||
Game::logger->Log("BehaviorContext", "No skill component attached to (%llu)!\n", this->originator);;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return component->GetUniqueSkillId();
|
||||
}
|
||||
|
||||
|
||||
void BehaviorContext::RegisterSyncBehavior(const uint32_t syncId, Behavior* behavior, const BehaviorBranchContext& branchContext)
|
||||
{
|
||||
auto entry = BehaviorSyncEntry();
|
||||
|
||||
entry.handle = syncId;
|
||||
entry.behavior = behavior;
|
||||
entry.branchContext = branchContext;
|
||||
|
||||
this->syncEntries.push_back(entry);
|
||||
}
|
||||
|
||||
void BehaviorContext::RegisterTimerBehavior(Behavior* behavior, const BehaviorBranchContext& branchContext, const LWOOBJID second)
|
||||
{
|
||||
BehaviorTimerEntry entry
|
||||
;
|
||||
entry.time = branchContext.duration;
|
||||
entry.behavior = behavior;
|
||||
entry.branchContext = branchContext;
|
||||
entry.second = second;
|
||||
|
||||
this->timerEntries.push_back(entry);
|
||||
}
|
||||
|
||||
void BehaviorContext::RegisterEndBehavior(Behavior* behavior, const BehaviorBranchContext& branchContext, const LWOOBJID second)
|
||||
{
|
||||
BehaviorEndEntry entry;
|
||||
|
||||
entry.behavior = behavior;
|
||||
entry.branchContext = branchContext;
|
||||
entry.second = second;
|
||||
entry.start = branchContext.start;
|
||||
|
||||
this->endEntries.push_back(entry);
|
||||
}
|
||||
|
||||
void BehaviorContext::ScheduleUpdate(const LWOOBJID id)
|
||||
{
|
||||
if (std::find(this->scheduledUpdates.begin(), this->scheduledUpdates.end(), id) != this->scheduledUpdates.end())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this->scheduledUpdates.push_back(id);
|
||||
}
|
||||
|
||||
void BehaviorContext::ExecuteUpdates()
|
||||
{
|
||||
for (const auto& id : this->scheduledUpdates)
|
||||
{
|
||||
auto* entity = EntityManager::Instance()->GetEntity(id);
|
||||
|
||||
if (entity == nullptr) continue;
|
||||
|
||||
EntityManager::Instance()->SerializeEntity(entity);
|
||||
}
|
||||
|
||||
this->scheduledUpdates.clear();
|
||||
}
|
||||
|
||||
void BehaviorContext::SyncBehavior(const uint32_t syncId, RakNet::BitStream* bitStream)
|
||||
{
|
||||
BehaviorSyncEntry entry;
|
||||
auto found = false;
|
||||
|
||||
/*
|
||||
* There may be more than one of each handle
|
||||
*/
|
||||
for (auto i = 0u; i < this->syncEntries.size(); ++i)
|
||||
{
|
||||
const auto syncEntry = this->syncEntries.at(i);
|
||||
|
||||
if (syncEntry.handle == syncId)
|
||||
{
|
||||
found = true;
|
||||
entry = syncEntry;
|
||||
|
||||
this->syncEntries.erase(this->syncEntries.begin() + i);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
Game::logger->Log("BehaviorContext", "Failed to find behavior sync entry with sync id (%i)!\n", syncId);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
auto* behavior = entry.behavior;
|
||||
const auto branch = entry.branchContext;
|
||||
|
||||
if (behavior == nullptr)
|
||||
{
|
||||
Game::logger->Log("BehaviorContext", "Invalid behavior for sync id (%i)!\n", syncId);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
behavior->Sync(this, bitStream, branch);
|
||||
}
|
||||
|
||||
|
||||
void BehaviorContext::Update(const float deltaTime)
|
||||
{
|
||||
for (auto i = 0u; i < this->timerEntries.size(); ++i)
|
||||
{
|
||||
auto entry = this->timerEntries.at(i);
|
||||
|
||||
if (entry.time > 0)
|
||||
{
|
||||
entry.time -= deltaTime;
|
||||
|
||||
this->timerEntries[i] = entry;
|
||||
}
|
||||
|
||||
if (entry.time > 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
entry.behavior->Timer(this, entry.branchContext, entry.second);
|
||||
}
|
||||
|
||||
std::vector<BehaviorTimerEntry> valid;
|
||||
|
||||
for (const auto& entry : this->timerEntries)
|
||||
{
|
||||
if (entry.time <= 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
valid.push_back(entry);
|
||||
}
|
||||
|
||||
this->timerEntries = valid;
|
||||
}
|
||||
|
||||
|
||||
void BehaviorContext::SyncCalculation(const uint32_t syncId, const float time, Behavior* behavior, const BehaviorBranchContext& branch, const bool ignoreInterrupts)
|
||||
{
|
||||
BehaviorSyncEntry entry;
|
||||
|
||||
entry.behavior = behavior;
|
||||
entry.time = time;
|
||||
entry.branchContext = branch;
|
||||
entry.handle = syncId;
|
||||
entry.ignoreInterrupts = ignoreInterrupts;
|
||||
|
||||
this->syncEntries.push_back(entry);
|
||||
}
|
||||
|
||||
void BehaviorContext::InvokeEnd(const uint32_t id)
|
||||
{
|
||||
std::vector<BehaviorEndEntry> entries;
|
||||
|
||||
for (const auto& entry : this->endEntries)
|
||||
{
|
||||
if (entry.start == id)
|
||||
{
|
||||
entry.behavior->End(this, entry.branchContext, entry.second);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
entries.push_back(entry);
|
||||
}
|
||||
|
||||
this->endEntries = entries;
|
||||
}
|
||||
|
||||
bool BehaviorContext::CalculateUpdate(const float deltaTime)
|
||||
{
|
||||
auto any = false;
|
||||
|
||||
for (auto i = 0u; i < this->syncEntries.size(); ++i)
|
||||
{
|
||||
auto entry = this->syncEntries.at(i);
|
||||
|
||||
if (entry.time > 0)
|
||||
{
|
||||
entry.time -= deltaTime;
|
||||
|
||||
this->syncEntries[i] = entry;
|
||||
}
|
||||
|
||||
if (entry.time > 0)
|
||||
{
|
||||
any = true;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Echo sync
|
||||
GameMessages::EchoSyncSkill echo;
|
||||
|
||||
echo.bDone = true;
|
||||
echo.uiBehaviorHandle = entry.handle;
|
||||
echo.uiSkillHandle = this->skillUId;
|
||||
|
||||
auto* bitStream = new RakNet::BitStream();
|
||||
|
||||
// Calculate sync
|
||||
entry.behavior->SyncCalculation(this, bitStream, entry.branchContext);
|
||||
|
||||
if (!clientInitalized)
|
||||
{
|
||||
echo.sBitStream.assign((char*) bitStream->GetData(), bitStream->GetNumberOfBytesUsed());
|
||||
|
||||
// Write message
|
||||
RakNet::BitStream message;
|
||||
|
||||
PacketUtils::WriteHeader(message, CLIENT, MSG_CLIENT_GAME_MSG);
|
||||
message.Write(this->originator);
|
||||
echo.Serialize(&message);
|
||||
|
||||
Game::server->Send(&message, UNASSIGNED_SYSTEM_ADDRESS, true);
|
||||
}
|
||||
|
||||
ExecuteUpdates();
|
||||
|
||||
delete bitStream;
|
||||
}
|
||||
|
||||
std::vector<BehaviorSyncEntry> valid;
|
||||
|
||||
for (const auto& entry : this->syncEntries)
|
||||
{
|
||||
if (entry.time <= 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
valid.push_back(entry);
|
||||
}
|
||||
|
||||
this->syncEntries = valid;
|
||||
|
||||
return any;
|
||||
}
|
||||
|
||||
void BehaviorContext::Interrupt()
|
||||
{
|
||||
std::vector<BehaviorSyncEntry> keptSync {};
|
||||
|
||||
for (const auto& entry : this->syncEntries)
|
||||
{
|
||||
if (!entry.ignoreInterrupts) continue;
|
||||
|
||||
keptSync.push_back(entry);
|
||||
}
|
||||
|
||||
this->syncEntries = keptSync;
|
||||
}
|
||||
|
||||
void BehaviorContext::Reset()
|
||||
{
|
||||
for (const auto& entry : this->timerEntries)
|
||||
{
|
||||
entry.behavior->Timer(this, entry.branchContext, entry.second);
|
||||
}
|
||||
|
||||
for (const auto& entry : this->endEntries)
|
||||
{
|
||||
entry.behavior->End(this, entry.branchContext, entry.second);
|
||||
}
|
||||
|
||||
this->endEntries.clear();
|
||||
this->timerEntries.clear();
|
||||
this->syncEntries.clear();
|
||||
this->scheduledUpdates.clear();
|
||||
}
|
||||
|
||||
std::vector<LWOOBJID> BehaviorContext::GetValidTargets(int32_t ignoreFaction, int32_t includeFaction) const
|
||||
{
|
||||
auto* entity = EntityManager::Instance()->GetEntity(this->caster);
|
||||
|
||||
std::vector<LWOOBJID> targets;
|
||||
|
||||
if (entity == nullptr)
|
||||
{
|
||||
Game::logger->Log("BehaviorContext", "Invalid entity for (%llu)!\n", this->originator);
|
||||
|
||||
return targets;
|
||||
}
|
||||
|
||||
if (!ignoreFaction && !includeFaction)
|
||||
{
|
||||
for (auto entry : entity->GetTargetsInPhantom())
|
||||
{
|
||||
auto* instance = EntityManager::Instance()->GetEntity(entry);
|
||||
|
||||
if (instance == nullptr)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
targets.push_back(entry);
|
||||
}
|
||||
}
|
||||
|
||||
if (ignoreFaction || includeFaction || (!entity->HasComponent(COMPONENT_TYPE_PHANTOM_PHYSICS) && !entity->HasComponent(COMPONENT_TYPE_CONTROLLABLE_PHYSICS) && targets.empty()))
|
||||
{
|
||||
DestroyableComponent* destroyableComponent;
|
||||
if (!entity->TryGetComponent(COMPONENT_TYPE_DESTROYABLE, destroyableComponent))
|
||||
{
|
||||
return targets;
|
||||
}
|
||||
|
||||
auto entities = EntityManager::Instance()->GetEntitiesByComponent(COMPONENT_TYPE_CONTROLLABLE_PHYSICS);
|
||||
|
||||
for (auto* candidate : entities)
|
||||
{
|
||||
const auto id = candidate->GetObjectID();
|
||||
|
||||
if (destroyableComponent->CheckValidity(id, ignoreFaction || includeFaction))
|
||||
{
|
||||
targets.push_back(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return targets;
|
||||
}
|
||||
|
||||
|
||||
BehaviorContext::BehaviorContext(const LWOOBJID originator, const bool calculation)
|
||||
{
|
||||
this->originator = originator;
|
||||
this->syncEntries = {};
|
||||
this->timerEntries = {};
|
||||
|
||||
if (calculation)
|
||||
{
|
||||
this->skillUId = GetUniqueSkillId();
|
||||
}
|
||||
else
|
||||
{
|
||||
this->skillUId = 0;
|
||||
}
|
||||
}
|
||||
|
||||
BehaviorContext::~BehaviorContext()
|
||||
{
|
||||
Reset();
|
||||
}
|
110
dGame/dBehaviors/BehaviorContext.h
Normal file
110
dGame/dBehaviors/BehaviorContext.h
Normal file
@@ -0,0 +1,110 @@
|
||||
#pragma once
|
||||
|
||||
#include "RakPeerInterface.h"
|
||||
#include "dCommonVars.h"
|
||||
#include "BehaviorBranchContext.h"
|
||||
#include "GameMessages.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
class Behavior;
|
||||
|
||||
struct BehaviorSyncEntry
|
||||
{
|
||||
uint32_t handle = 0;
|
||||
|
||||
float time = 0;
|
||||
|
||||
bool ignoreInterrupts = false;
|
||||
|
||||
Behavior* behavior = nullptr;
|
||||
|
||||
BehaviorBranchContext branchContext;
|
||||
|
||||
BehaviorSyncEntry();
|
||||
};
|
||||
|
||||
struct BehaviorTimerEntry
|
||||
{
|
||||
float time = 0;
|
||||
|
||||
Behavior* behavior = nullptr;
|
||||
|
||||
BehaviorBranchContext branchContext;
|
||||
|
||||
LWOOBJID second = LWOOBJID_EMPTY;
|
||||
|
||||
BehaviorTimerEntry();
|
||||
};
|
||||
|
||||
struct BehaviorEndEntry
|
||||
{
|
||||
Behavior* behavior = nullptr;
|
||||
|
||||
uint32_t start = 0;
|
||||
|
||||
BehaviorBranchContext branchContext;
|
||||
|
||||
LWOOBJID second = LWOOBJID_EMPTY;
|
||||
|
||||
BehaviorEndEntry();
|
||||
};
|
||||
|
||||
struct BehaviorContext
|
||||
{
|
||||
LWOOBJID originator = LWOOBJID_EMPTY;
|
||||
|
||||
bool foundTarget = false;
|
||||
|
||||
float skillTime = 0;
|
||||
|
||||
uint32_t skillUId = 0;
|
||||
|
||||
bool failed = false;
|
||||
|
||||
bool clientInitalized = false;
|
||||
|
||||
std::vector<BehaviorSyncEntry> syncEntries;
|
||||
|
||||
std::vector<BehaviorTimerEntry> timerEntries;
|
||||
|
||||
std::vector<BehaviorEndEntry> endEntries;
|
||||
|
||||
std::vector<LWOOBJID> scheduledUpdates;
|
||||
|
||||
bool unmanaged = false;
|
||||
|
||||
LWOOBJID caster = LWOOBJID_EMPTY;
|
||||
|
||||
uint32_t GetUniqueSkillId() const;
|
||||
|
||||
void RegisterSyncBehavior(uint32_t syncId, Behavior* behavior, const BehaviorBranchContext& branchContext);
|
||||
|
||||
void RegisterTimerBehavior(Behavior* behavior, const BehaviorBranchContext& branchContext, LWOOBJID second = LWOOBJID_EMPTY);
|
||||
|
||||
void RegisterEndBehavior(Behavior* behavior, const BehaviorBranchContext& branchContext, LWOOBJID second = LWOOBJID_EMPTY);
|
||||
|
||||
void ScheduleUpdate(LWOOBJID id);
|
||||
|
||||
void ExecuteUpdates();
|
||||
|
||||
void SyncBehavior(uint32_t syncId, RakNet::BitStream* bitStream);
|
||||
|
||||
void Update(float deltaTime);
|
||||
|
||||
void SyncCalculation(uint32_t syncId, float time, Behavior* behavior, const BehaviorBranchContext& branch, bool ignoreInterrupts = false);
|
||||
|
||||
void InvokeEnd(uint32_t id);
|
||||
|
||||
bool CalculateUpdate(float deltaTime);
|
||||
|
||||
void Interrupt();
|
||||
|
||||
void Reset();
|
||||
|
||||
std::vector<LWOOBJID> GetValidTargets(int32_t ignoreFaction = 0, int32_t includeFaction = 0) const;
|
||||
|
||||
explicit BehaviorContext(LWOOBJID originator, bool calculation = false);
|
||||
|
||||
~BehaviorContext();
|
||||
};
|
11
dGame/dBehaviors/BehaviorSlot.h
Normal file
11
dGame/dBehaviors/BehaviorSlot.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
enum class BehaviorSlot
|
||||
{
|
||||
Invalid = -1,
|
||||
Primary,
|
||||
Offhand,
|
||||
Neck,
|
||||
Head,
|
||||
Consumable
|
||||
};
|
1
dGame/dBehaviors/BehaviorTemplates.cpp
Normal file
1
dGame/dBehaviors/BehaviorTemplates.cpp
Normal file
@@ -0,0 +1 @@
|
||||
#include "BehaviorTemplates.h"
|
70
dGame/dBehaviors/BehaviorTemplates.h
Normal file
70
dGame/dBehaviors/BehaviorTemplates.h
Normal file
@@ -0,0 +1,70 @@
|
||||
#pragma once
|
||||
|
||||
enum class BehaviorTemplates : unsigned int {
|
||||
BEHAVIOR_EMPTY, // Not a real behavior, indicates invalid behaviors
|
||||
BEHAVIOR_BASIC_ATTACK,
|
||||
BEHAVIOR_TAC_ARC,
|
||||
BEHAVIOR_AND,
|
||||
BEHAVIOR_PROJECTILE_ATTACK,
|
||||
BEHAVIOR_HEAL,
|
||||
BEHAVIOR_MOVEMENT_SWITCH,
|
||||
BEHAVIOR_AREA_OF_EFFECT,
|
||||
BEHAVIOR_PLAY_EFFECT,
|
||||
BEHAVIOR_IMMUNITY,
|
||||
BEHAVIOR_DAMAGE_BUFF,
|
||||
BEHAVIOR_DAMAGE_ABSORBTION,
|
||||
BEHAVIOR_OVER_TIME,
|
||||
BEHAVIOR_IMAGINATION,
|
||||
BEHAVIOR_TARGET_CASTER,
|
||||
BEHAVIOR_STUN,
|
||||
BEHAVIOR_DURATION,
|
||||
BEHAVIOR_KNOCKBACK,
|
||||
BEHAVIOR_ATTACK_DELAY,
|
||||
BEHAVIOR_CAR_BOOST,
|
||||
BEHAVIOR_FALL_SPEED,
|
||||
BEHAVIOR_SHIELD,
|
||||
BEHAVIOR_REPAIR_ARMOR,
|
||||
BEHAVIOR_SPEED,
|
||||
BEHAVIOR_DARK_INSPIRATION,
|
||||
BEHAVIOR_LOOT_BUFF,
|
||||
BEHAVIOR_VENTURE_VISION,
|
||||
BEHAVIOR_SPAWN_OBJECT,
|
||||
BEHAVIOR_LAY_BRICK,
|
||||
BEHAVIOR_SWITCH,
|
||||
BEHAVIOR_BUFF,
|
||||
BEHAVIOR_JETPACK,
|
||||
BEHAVIOR_SKILL_EVENT,
|
||||
BEHAVIOR_CONSUME_ITEM,
|
||||
BEHAVIOR_SKILL_CAST_FAILED,
|
||||
BEHAVIOR_IMITATION_SKUNK_STINK,
|
||||
BEHAVIOR_CHANGE_IDLE_FLAGS,
|
||||
BEHAVIOR_APPLY_BUFF,
|
||||
BEHAVIOR_CHAIN,
|
||||
BEHAVIOR_CHANGE_ORIENTATION,
|
||||
BEHAVIOR_FORCE_MOVEMENT,
|
||||
BEHAVIOR_INTERRUPT,
|
||||
BEHAVIOR_ALTER_COOLDOWN,
|
||||
BEHAVIOR_CHARGE_UP,
|
||||
BEHAVIOR_SWITCH_MULTIPLE,
|
||||
BEHAVIOR_START,
|
||||
BEHAVIOR_END,
|
||||
BEHAVIOR_ALTER_CHAIN_DELAY,
|
||||
BEHAVIOR_CAMERA,
|
||||
BEHAVIOR_REMOVE_BUFF,
|
||||
BEHAVIOR_GRAB,
|
||||
BEHAVIOR_MODULAR_BUILD,
|
||||
BEHAVIOR_NPC_COMBAT_SKILL,
|
||||
BEHAVIOR_BLOCK,
|
||||
BEHAVIOR_VERIFY,
|
||||
BEHAVIOR_TAUNT,
|
||||
BEHAVIOR_AIR_MOVEMENT,
|
||||
BEHAVIOR_SPAWN_QUICKBUILD,
|
||||
BEHAVIOR_PULL_TO_POINT,
|
||||
BEHAVIOR_PROPERTY_ROTATE,
|
||||
BEHAVIOR_DAMAGE_REDUCTION,
|
||||
BEHAVIOR_PROPERTY_TELEPORT,
|
||||
BEHAVIOR_PROPERTY_CLEAR_TARGET,
|
||||
BEHAVIOR_TAKE_PICTURE,
|
||||
BEHAVIOR_MOUNT,
|
||||
BEHAVIOR_SKILL_SET
|
||||
};
|
85
dGame/dBehaviors/BlockBehavior.cpp
Normal file
85
dGame/dBehaviors/BlockBehavior.cpp
Normal file
@@ -0,0 +1,85 @@
|
||||
#include "BlockBehavior.h"
|
||||
|
||||
#include "BehaviorContext.h"
|
||||
#include "BehaviorBranchContext.h"
|
||||
#include "EntityManager.h"
|
||||
#include "Game.h"
|
||||
#include "dLogger.h"
|
||||
#include "DestroyableComponent.h"
|
||||
|
||||
void BlockBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch)
|
||||
{
|
||||
const auto target = context->originator;
|
||||
|
||||
auto* entity = EntityManager::Instance()->GetEntity(target);
|
||||
|
||||
if (entity == nullptr)
|
||||
{
|
||||
Game::logger->Log("DamageAbsorptionBehavior", "Failed to find target (%llu)!\n", branch.target);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
auto* destroyableComponent = entity->GetComponent<DestroyableComponent>();
|
||||
|
||||
if (destroyableComponent == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
destroyableComponent->SetAttacksToBlock(this->m_numAttacksCanBlock);
|
||||
|
||||
if (branch.start > 0)
|
||||
{
|
||||
context->RegisterEndBehavior(this, branch);
|
||||
}
|
||||
else if (branch.duration > 0)
|
||||
{
|
||||
context->RegisterTimerBehavior(this, branch);
|
||||
}
|
||||
}
|
||||
|
||||
void BlockBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch)
|
||||
{
|
||||
Handle(context, bitStream, branch);
|
||||
}
|
||||
|
||||
void BlockBehavior::UnCast(BehaviorContext* context, BehaviorBranchContext branch)
|
||||
{
|
||||
const auto target = context->originator;
|
||||
|
||||
auto* entity = EntityManager::Instance()->GetEntity(target);
|
||||
|
||||
if (entity == nullptr)
|
||||
{
|
||||
Game::logger->Log("DamageAbsorptionBehavior", "Failed to find target (%llu)!\n", branch.target);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
auto* destroyableComponent = entity->GetComponent<DestroyableComponent>();
|
||||
|
||||
destroyableComponent->SetAttacksToBlock(this->m_numAttacksCanBlock);
|
||||
|
||||
if (destroyableComponent == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
destroyableComponent->SetAttacksToBlock(0);
|
||||
}
|
||||
|
||||
void BlockBehavior::Timer(BehaviorContext* context, BehaviorBranchContext branch, LWOOBJID second)
|
||||
{
|
||||
UnCast(context, branch);
|
||||
}
|
||||
|
||||
void BlockBehavior::End(BehaviorContext* context, BehaviorBranchContext branch, LWOOBJID second)
|
||||
{
|
||||
UnCast(context, branch);
|
||||
}
|
||||
|
||||
void BlockBehavior::Load()
|
||||
{
|
||||
this->m_numAttacksCanBlock = GetInt("num_attacks_can_block");
|
||||
}
|
28
dGame/dBehaviors/BlockBehavior.h
Normal file
28
dGame/dBehaviors/BlockBehavior.h
Normal file
@@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
#include "Behavior.h"
|
||||
|
||||
class BlockBehavior final : public Behavior
|
||||
{
|
||||
public:
|
||||
int32_t m_numAttacksCanBlock;
|
||||
|
||||
/*
|
||||
* Inherited
|
||||
*/
|
||||
|
||||
explicit BlockBehavior(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 UnCast(BehaviorContext* context, BehaviorBranchContext branch) override;
|
||||
|
||||
void Timer(BehaviorContext* context, BehaviorBranchContext branch, LWOOBJID second) override;
|
||||
|
||||
void End(BehaviorContext* context, BehaviorBranchContext branch, LWOOBJID second) override;
|
||||
|
||||
void Load() override;
|
||||
};
|
97
dGame/dBehaviors/BuffBehavior.cpp
Normal file
97
dGame/dBehaviors/BuffBehavior.cpp
Normal file
@@ -0,0 +1,97 @@
|
||||
#include "BuffBehavior.h"
|
||||
|
||||
#include "BehaviorContext.h"
|
||||
#include "BehaviorBranchContext.h"
|
||||
#include "EntityManager.h"
|
||||
#include "Game.h"
|
||||
#include "dLogger.h"
|
||||
#include "DestroyableComponent.h"
|
||||
|
||||
void BuffBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch)
|
||||
{
|
||||
const auto target = branch.target != LWOOBJID_EMPTY ? branch.target : context->originator;
|
||||
|
||||
auto* entity = EntityManager::Instance()->GetEntity(target);
|
||||
|
||||
if (entity == nullptr)
|
||||
{
|
||||
Game::logger->Log("BuffBehavior", "Invalid target (%llu)!\n", target);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
auto* component = entity->GetComponent<DestroyableComponent>();
|
||||
|
||||
if (component == nullptr)
|
||||
{
|
||||
Game::logger->Log("BuffBehavior", "Invalid target, no destroyable component (%llu)!\n", target);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
component->SetMaxHealth(component->GetMaxHealth() + this->m_health);
|
||||
component->SetMaxArmor(component->GetMaxArmor() + this->m_armor);
|
||||
component->SetMaxImagination(component->GetMaxImagination() + this->m_imagination);
|
||||
|
||||
EntityManager::Instance()->SerializeEntity(entity);
|
||||
|
||||
if (!context->unmanaged)
|
||||
{
|
||||
if (branch.duration > 0)
|
||||
{
|
||||
context->RegisterTimerBehavior(this, branch);
|
||||
}
|
||||
else if (branch.start > 0)
|
||||
{
|
||||
context->RegisterEndBehavior(this, branch);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BuffBehavior::UnCast(BehaviorContext* context, BehaviorBranchContext branch)
|
||||
{
|
||||
const auto target = branch.target != LWOOBJID_EMPTY ? branch.target : context->originator;
|
||||
|
||||
auto* entity = EntityManager::Instance()->GetEntity(target);
|
||||
|
||||
if (entity == nullptr)
|
||||
{
|
||||
Game::logger->Log("BuffBehavior", "Invalid target (%llu)!\n", target);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
auto* component = entity->GetComponent<DestroyableComponent>();
|
||||
|
||||
if (component == nullptr)
|
||||
{
|
||||
Game::logger->Log("BuffBehavior", "Invalid target, no destroyable component (%llu)!\n", target);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
component->SetMaxHealth(component->GetMaxHealth() - this->m_health);
|
||||
component->SetMaxArmor(component->GetMaxArmor() - this->m_armor);
|
||||
component->SetMaxImagination(component->GetMaxImagination() - this->m_imagination);
|
||||
|
||||
EntityManager::Instance()->SerializeEntity(entity);
|
||||
}
|
||||
|
||||
void BuffBehavior::Timer(BehaviorContext* context, const BehaviorBranchContext branch, LWOOBJID second)
|
||||
{
|
||||
UnCast(context, branch);
|
||||
}
|
||||
|
||||
void BuffBehavior::End(BehaviorContext* context, const BehaviorBranchContext branch, LWOOBJID second)
|
||||
{
|
||||
UnCast(context, branch);
|
||||
}
|
||||
|
||||
void BuffBehavior::Load()
|
||||
{
|
||||
this->m_health = GetInt("life");
|
||||
|
||||
this->m_armor = GetInt("armor");
|
||||
|
||||
this->m_imagination = GetInt("imag");
|
||||
}
|
29
dGame/dBehaviors/BuffBehavior.h
Normal file
29
dGame/dBehaviors/BuffBehavior.h
Normal file
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
#include "Behavior.h"
|
||||
|
||||
class BuffBehavior final : public Behavior
|
||||
{
|
||||
public:
|
||||
uint32_t m_health;
|
||||
|
||||
uint32_t m_armor;
|
||||
|
||||
uint32_t m_imagination;
|
||||
|
||||
/*
|
||||
* Inherited
|
||||
*/
|
||||
explicit BuffBehavior(const uint32_t behaviorId) : Behavior(behaviorId)
|
||||
{
|
||||
}
|
||||
|
||||
void Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) override;
|
||||
|
||||
void UnCast(BehaviorContext* context, BehaviorBranchContext branch) override;
|
||||
|
||||
void Timer(BehaviorContext* context, BehaviorBranchContext branch, LWOOBJID second) override;
|
||||
|
||||
void End(BehaviorContext* context, BehaviorBranchContext branch, LWOOBJID second) override;
|
||||
|
||||
void Load() override;
|
||||
};
|
51
dGame/dBehaviors/CarBoostBehavior.cpp
Normal file
51
dGame/dBehaviors/CarBoostBehavior.cpp
Normal file
@@ -0,0 +1,51 @@
|
||||
#include "CarBoostBehavior.h"
|
||||
#include "BehaviorBranchContext.h"
|
||||
#include "GameMessages.h"
|
||||
#include "EntityManager.h"
|
||||
#include "BehaviorContext.h"
|
||||
#include "CharacterComponent.h"
|
||||
#include "Game.h"
|
||||
#include "dLogger.h"
|
||||
#include "PossessableComponent.h"
|
||||
|
||||
void CarBoostBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch)
|
||||
{
|
||||
GameMessages::SendVehicleAddPassiveBoostAction(branch.target, UNASSIGNED_SYSTEM_ADDRESS);
|
||||
|
||||
auto* entity = EntityManager::Instance()->GetEntity(context->originator);
|
||||
|
||||
if (entity == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Game::logger->Log("Car boost", "Activating car boost!\n");
|
||||
|
||||
auto* possessableComponent = entity->GetComponent<PossessableComponent>();
|
||||
if (possessableComponent != nullptr) {
|
||||
|
||||
auto* possessor = EntityManager::Instance()->GetEntity(possessableComponent->GetPossessor());
|
||||
if (possessor != nullptr) {
|
||||
|
||||
auto* characterComponent = possessor->GetComponent<CharacterComponent>();
|
||||
if (characterComponent != nullptr) {
|
||||
Game::logger->Log("Car boost", "Tracking car boost!\n");
|
||||
characterComponent->UpdatePlayerStatistic(RacingCarBoostsActivated);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
m_Action->Handle(context, bitStream, branch);
|
||||
|
||||
entity->AddCallbackTimer(m_Time, [entity] () {
|
||||
GameMessages::SendVehicleRemovePassiveBoostAction(entity->GetObjectID(), UNASSIGNED_SYSTEM_ADDRESS);
|
||||
});
|
||||
}
|
||||
|
||||
void CarBoostBehavior::Load()
|
||||
{
|
||||
m_Action = GetAction("action");
|
||||
|
||||
m_Time = GetFloat("time");
|
||||
}
|
24
dGame/dBehaviors/CarBoostBehavior.h
Normal file
24
dGame/dBehaviors/CarBoostBehavior.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include "Behavior.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
class CarBoostBehavior final : public Behavior
|
||||
{
|
||||
public:
|
||||
Behavior* m_Action;
|
||||
float m_Time;
|
||||
|
||||
/*
|
||||
* Inherited
|
||||
*/
|
||||
|
||||
explicit CarBoostBehavior(const uint32_t behaviorId) : Behavior(behaviorId)
|
||||
{
|
||||
}
|
||||
|
||||
void Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) override;
|
||||
|
||||
void Load() override;
|
||||
};
|
40
dGame/dBehaviors/ChainBehavior.cpp
Normal file
40
dGame/dBehaviors/ChainBehavior.cpp
Normal file
@@ -0,0 +1,40 @@
|
||||
#include "ChainBehavior.h"
|
||||
#include "BehaviorBranchContext.h"
|
||||
#include "Game.h"
|
||||
#include "dLogger.h"
|
||||
|
||||
void ChainBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, const BehaviorBranchContext branch)
|
||||
{
|
||||
uint32_t chain_index;
|
||||
|
||||
bitStream->Read(chain_index);
|
||||
|
||||
chain_index--;
|
||||
|
||||
if (chain_index < this->m_behaviors.size())
|
||||
{
|
||||
this->m_behaviors.at(chain_index)->Handle(context, bitStream, branch);
|
||||
}
|
||||
}
|
||||
|
||||
void ChainBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, const BehaviorBranchContext branch)
|
||||
{
|
||||
bitStream->Write(1);
|
||||
|
||||
this->m_behaviors.at(0)->Calculate(context, bitStream, branch);
|
||||
}
|
||||
|
||||
void ChainBehavior::Load()
|
||||
{
|
||||
const auto parameters = GetParameterNames();
|
||||
|
||||
for (const auto& parameter : parameters)
|
||||
{
|
||||
if (parameter.first.rfind("behavior", 0) == 0)
|
||||
{
|
||||
auto* action = GetAction(parameter.second);
|
||||
|
||||
this->m_behaviors.push_back(action);
|
||||
}
|
||||
}
|
||||
}
|
25
dGame/dBehaviors/ChainBehavior.h
Normal file
25
dGame/dBehaviors/ChainBehavior.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include "Behavior.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
class ChainBehavior final : public Behavior
|
||||
{
|
||||
public:
|
||||
std::vector<Behavior*> m_behaviors;
|
||||
|
||||
/*
|
||||
* Inherited
|
||||
*/
|
||||
|
||||
explicit ChainBehavior(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;
|
||||
};
|
50
dGame/dBehaviors/ChangeOrientationBehavior.cpp
Normal file
50
dGame/dBehaviors/ChangeOrientationBehavior.cpp
Normal file
@@ -0,0 +1,50 @@
|
||||
#include "ChangeOrientationBehavior.h"
|
||||
#include "BehaviorBranchContext.h"
|
||||
#include "BehaviorContext.h"
|
||||
#include "EntityManager.h"
|
||||
#include "BaseCombatAIComponent.h"
|
||||
|
||||
void ChangeOrientationBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch)
|
||||
{
|
||||
}
|
||||
|
||||
void ChangeOrientationBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch)
|
||||
{
|
||||
if (!m_ToTarget) return; // TODO: Add the other arguments to this behavior
|
||||
|
||||
auto* self = EntityManager::Instance()->GetEntity(context->originator);
|
||||
auto* other = EntityManager::Instance()->GetEntity(branch.target);
|
||||
|
||||
if (self == nullptr || other == nullptr) return;
|
||||
|
||||
const auto source = self->GetPosition();
|
||||
const auto destination = self->GetPosition();
|
||||
|
||||
if (m_OrientCaster)
|
||||
{
|
||||
auto* baseCombatAIComponent = self->GetComponent<BaseCombatAIComponent>();
|
||||
|
||||
/*if (baseCombatAIComponent != nullptr)
|
||||
{
|
||||
baseCombatAIComponent->LookAt(destination);
|
||||
}
|
||||
else*/
|
||||
{
|
||||
self->SetRotation(NiQuaternion::LookAt(source, destination));
|
||||
}
|
||||
|
||||
EntityManager::Instance()->SerializeEntity(self);
|
||||
}
|
||||
else
|
||||
{
|
||||
other->SetRotation(NiQuaternion::LookAt(destination, source));
|
||||
|
||||
EntityManager::Instance()->SerializeEntity(other);
|
||||
}
|
||||
}
|
||||
|
||||
void ChangeOrientationBehavior::Load()
|
||||
{
|
||||
m_OrientCaster = GetBoolean("orient_caster");
|
||||
m_ToTarget = GetBoolean("to_target");
|
||||
}
|
26
dGame/dBehaviors/ChangeOrientationBehavior.h
Normal file
26
dGame/dBehaviors/ChangeOrientationBehavior.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include "Behavior.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
class ChangeOrientationBehavior final : public Behavior
|
||||
{
|
||||
public:
|
||||
bool m_OrientCaster;
|
||||
bool m_ToTarget;
|
||||
|
||||
/*
|
||||
* Inherited
|
||||
*/
|
||||
|
||||
explicit ChangeOrientationBehavior(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;
|
||||
};
|
27
dGame/dBehaviors/ChargeUpBehavior.cpp
Normal file
27
dGame/dBehaviors/ChargeUpBehavior.cpp
Normal file
@@ -0,0 +1,27 @@
|
||||
#include "ChargeUpBehavior.h"
|
||||
#include "BehaviorBranchContext.h"
|
||||
#include "BehaviorContext.h"
|
||||
#include "dLogger.h"
|
||||
|
||||
void ChargeUpBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, const BehaviorBranchContext branch)
|
||||
{
|
||||
uint32_t handle;
|
||||
|
||||
bitStream->Read(handle);
|
||||
|
||||
context->RegisterSyncBehavior(handle, this, branch);
|
||||
}
|
||||
|
||||
void ChargeUpBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch)
|
||||
{
|
||||
}
|
||||
|
||||
void ChargeUpBehavior::Sync(BehaviorContext* context, RakNet::BitStream* bitStream, const BehaviorBranchContext branch)
|
||||
{
|
||||
this->m_action->Handle(context, bitStream, branch);
|
||||
}
|
||||
|
||||
void ChargeUpBehavior::Load()
|
||||
{
|
||||
this->m_action = GetAction("action");
|
||||
}
|
24
dGame/dBehaviors/ChargeUpBehavior.h
Normal file
24
dGame/dBehaviors/ChargeUpBehavior.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
#include "Behavior.h"
|
||||
|
||||
class ChargeUpBehavior final : public Behavior
|
||||
{
|
||||
public:
|
||||
Behavior* m_action;
|
||||
|
||||
/*
|
||||
* Inherited
|
||||
*/
|
||||
|
||||
explicit ChargeUpBehavior(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 Sync(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) override;
|
||||
|
||||
void Load() override;
|
||||
};
|
25
dGame/dBehaviors/ClearTargetBehavior.cpp
Normal file
25
dGame/dBehaviors/ClearTargetBehavior.cpp
Normal file
@@ -0,0 +1,25 @@
|
||||
#include "ClearTargetBehavior.h"
|
||||
#include "BehaviorBranchContext.h"
|
||||
#include "BehaviorContext.h"
|
||||
|
||||
|
||||
void ClearTargetBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch)
|
||||
{
|
||||
branch.target = LWOOBJID_EMPTY;
|
||||
|
||||
this->m_action->Handle(context, bitStream, branch);
|
||||
}
|
||||
|
||||
void ClearTargetBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch)
|
||||
{
|
||||
branch.target = LWOOBJID_EMPTY;
|
||||
|
||||
this->m_action->Calculate(context, bitStream, branch);
|
||||
}
|
||||
|
||||
void ClearTargetBehavior::Load()
|
||||
{
|
||||
this->m_action = GetAction("action");
|
||||
|
||||
this->m_clearIfCaster = GetBoolean("clear_if_caster");
|
||||
}
|
23
dGame/dBehaviors/ClearTargetBehavior.h
Normal file
23
dGame/dBehaviors/ClearTargetBehavior.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
#include "Behavior.h"
|
||||
|
||||
class ClearTargetBehavior final : public Behavior
|
||||
{
|
||||
public:
|
||||
Behavior* m_action;
|
||||
|
||||
bool m_clearIfCaster;
|
||||
|
||||
/*
|
||||
* Inherited
|
||||
*/
|
||||
explicit ClearTargetBehavior(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;
|
||||
};
|
68
dGame/dBehaviors/DamageAbsorptionBehavior.cpp
Normal file
68
dGame/dBehaviors/DamageAbsorptionBehavior.cpp
Normal file
@@ -0,0 +1,68 @@
|
||||
#include "DamageAbsorptionBehavior.h"
|
||||
|
||||
#include "BehaviorBranchContext.h"
|
||||
#include "BehaviorContext.h"
|
||||
#include "EntityManager.h"
|
||||
#include "Game.h"
|
||||
#include "dLogger.h"
|
||||
#include "DestroyableComponent.h"
|
||||
|
||||
void DamageAbsorptionBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, const BehaviorBranchContext branch)
|
||||
{
|
||||
auto* target = EntityManager::Instance()->GetEntity(branch.target);
|
||||
|
||||
if (target == nullptr)
|
||||
{
|
||||
Game::logger->Log("DamageAbsorptionBehavior", "Failed to find target (%llu)!\n", branch.target);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
auto* destroyable = target->GetComponent<DestroyableComponent>();
|
||||
|
||||
if (destroyable == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
destroyable->SetDamageToAbsorb(static_cast<uint32_t>(destroyable->GetDamageToAbsorb()) + this->m_absorbAmount);
|
||||
|
||||
destroyable->SetIsShielded(true);
|
||||
|
||||
context->RegisterTimerBehavior(this, branch, target->GetObjectID());
|
||||
}
|
||||
|
||||
void DamageAbsorptionBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch)
|
||||
{
|
||||
Handle(context, bitStream, branch);
|
||||
}
|
||||
|
||||
void DamageAbsorptionBehavior::Timer(BehaviorContext* context, BehaviorBranchContext branch, const LWOOBJID second)
|
||||
{
|
||||
auto* target = EntityManager::Instance()->GetEntity(second);
|
||||
|
||||
if (target == nullptr)
|
||||
{
|
||||
Game::logger->Log("DamageAbsorptionBehavior", "Failed to find target (%llu)!\n", second);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
auto* destroyable = target->GetComponent<DestroyableComponent>();
|
||||
|
||||
if (destroyable == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const auto present = static_cast<uint32_t>(destroyable->GetDamageToAbsorb());
|
||||
|
||||
const auto toRemove = std::min(present, this->m_absorbAmount);
|
||||
|
||||
destroyable->SetDamageToAbsorb(present - toRemove);
|
||||
}
|
||||
|
||||
void DamageAbsorptionBehavior::Load()
|
||||
{
|
||||
this->m_absorbAmount = GetInt("absorb_amount");
|
||||
}
|
24
dGame/dBehaviors/DamageAbsorptionBehavior.h
Normal file
24
dGame/dBehaviors/DamageAbsorptionBehavior.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
#include "Behavior.h"
|
||||
|
||||
class DamageAbsorptionBehavior final : public Behavior
|
||||
{
|
||||
public:
|
||||
uint32_t m_absorbAmount;
|
||||
|
||||
/*
|
||||
* Inherited
|
||||
*/
|
||||
|
||||
explicit DamageAbsorptionBehavior(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 Timer(BehaviorContext* context, BehaviorBranchContext branch, LWOOBJID second) override;
|
||||
|
||||
void Load() override;
|
||||
};
|
62
dGame/dBehaviors/DamageReductionBehavior.cpp
Normal file
62
dGame/dBehaviors/DamageReductionBehavior.cpp
Normal file
@@ -0,0 +1,62 @@
|
||||
#include "DamageReductionBehavior.h"
|
||||
|
||||
#include "BehaviorBranchContext.h"
|
||||
#include "BehaviorContext.h"
|
||||
#include "EntityManager.h"
|
||||
#include "Game.h"
|
||||
#include "dLogger.h"
|
||||
#include "DestroyableComponent.h"
|
||||
|
||||
void DamageReductionBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, const BehaviorBranchContext branch)
|
||||
{
|
||||
auto* target = EntityManager::Instance()->GetEntity(branch.target);
|
||||
|
||||
if (target == nullptr)
|
||||
{
|
||||
Game::logger->Log("DamageReductionBehavior", "Failed to find target (%llu)!\n", branch.target);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
auto* destroyable = target->GetComponent<DestroyableComponent>();
|
||||
|
||||
if (destroyable == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
destroyable->SetDamageReduction(m_ReductionAmount);
|
||||
|
||||
context->RegisterTimerBehavior(this, branch, target->GetObjectID());
|
||||
}
|
||||
|
||||
void DamageReductionBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch)
|
||||
{
|
||||
Handle(context, bitStream, branch);
|
||||
}
|
||||
|
||||
void DamageReductionBehavior::Timer(BehaviorContext* context, BehaviorBranchContext branch, const LWOOBJID second)
|
||||
{
|
||||
auto* target = EntityManager::Instance()->GetEntity(second);
|
||||
|
||||
if (target == nullptr)
|
||||
{
|
||||
Game::logger->Log("DamageReductionBehavior", "Failed to find target (%llu)!\n", second);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
auto* destroyable = target->GetComponent<DestroyableComponent>();
|
||||
|
||||
if (destroyable == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
destroyable->SetDamageReduction(0);
|
||||
}
|
||||
|
||||
void DamageReductionBehavior::Load()
|
||||
{
|
||||
this->m_ReductionAmount = GetInt("reduction_amount");
|
||||
}
|
24
dGame/dBehaviors/DamageReductionBehavior.h
Normal file
24
dGame/dBehaviors/DamageReductionBehavior.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
#include "Behavior.h"
|
||||
|
||||
class DamageReductionBehavior final : public Behavior
|
||||
{
|
||||
public:
|
||||
uint32_t m_ReductionAmount;
|
||||
|
||||
/*
|
||||
* Inherited
|
||||
*/
|
||||
|
||||
explicit DamageReductionBehavior(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 Timer(BehaviorContext* context, BehaviorBranchContext branch, LWOOBJID second) override;
|
||||
|
||||
void Load() override;
|
||||
};
|
24
dGame/dBehaviors/DurationBehavior.cpp
Normal file
24
dGame/dBehaviors/DurationBehavior.cpp
Normal file
@@ -0,0 +1,24 @@
|
||||
#include "DurationBehavior.h"
|
||||
#include "BehaviorBranchContext.h"
|
||||
#include "BehaviorContext.h"
|
||||
|
||||
void DurationBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch)
|
||||
{
|
||||
branch.duration = this->m_duration;
|
||||
|
||||
this->m_action->Handle(context, bitStream, branch);
|
||||
}
|
||||
|
||||
void DurationBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch)
|
||||
{
|
||||
branch.duration = this->m_duration;
|
||||
|
||||
this->m_action->Calculate(context, bitStream, branch);
|
||||
}
|
||||
|
||||
void DurationBehavior::Load()
|
||||
{
|
||||
this->m_duration = GetFloat("duration");
|
||||
|
||||
this->m_action = GetAction("action");
|
||||
}
|
22
dGame/dBehaviors/DurationBehavior.h
Normal file
22
dGame/dBehaviors/DurationBehavior.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
#include "Behavior.h"
|
||||
|
||||
class DurationBehavior final : public Behavior
|
||||
{
|
||||
public:
|
||||
float m_duration;
|
||||
|
||||
Behavior* m_action;
|
||||
|
||||
explicit DurationBehavior(const uint32_t behavior_id) : Behavior(behavior_id)
|
||||
{
|
||||
}
|
||||
|
||||
void Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) override;
|
||||
|
||||
void Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) override;
|
||||
|
||||
void Load() override;
|
||||
private:
|
||||
float m_Timer = 0.0f;
|
||||
};
|
2
dGame/dBehaviors/EmptyBehavior.cpp
Normal file
2
dGame/dBehaviors/EmptyBehavior.cpp
Normal file
@@ -0,0 +1,2 @@
|
||||
#include "EmptyBehavior.h"
|
||||
|
11
dGame/dBehaviors/EmptyBehavior.h
Normal file
11
dGame/dBehaviors/EmptyBehavior.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include "Behavior.h"
|
||||
|
||||
class EmptyBehavior final : public Behavior
|
||||
{
|
||||
public:
|
||||
explicit EmptyBehavior(const uint32_t behavior_id) : Behavior(behavior_id)
|
||||
{
|
||||
}
|
||||
};
|
19
dGame/dBehaviors/EndBehavior.cpp
Normal file
19
dGame/dBehaviors/EndBehavior.cpp
Normal file
@@ -0,0 +1,19 @@
|
||||
#include "EndBehavior.h"
|
||||
|
||||
#include "BehaviorContext.h"
|
||||
#include "BehaviorBranchContext.h"
|
||||
|
||||
void EndBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch)
|
||||
{
|
||||
context->InvokeEnd(this->m_startBehavior);
|
||||
}
|
||||
|
||||
void EndBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch)
|
||||
{
|
||||
context->InvokeEnd(this->m_startBehavior);
|
||||
}
|
||||
|
||||
void EndBehavior::Load()
|
||||
{
|
||||
this->m_startBehavior = GetInt("start_action");
|
||||
}
|
22
dGame/dBehaviors/EndBehavior.h
Normal file
22
dGame/dBehaviors/EndBehavior.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
#include "Behavior.h"
|
||||
|
||||
class EndBehavior final : public Behavior
|
||||
{
|
||||
public:
|
||||
uint32_t m_startBehavior;
|
||||
|
||||
/*
|
||||
* Inherited
|
||||
*/
|
||||
|
||||
explicit EndBehavior(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;
|
||||
};
|
44
dGame/dBehaviors/ForceMovementBehavior.cpp
Normal file
44
dGame/dBehaviors/ForceMovementBehavior.cpp
Normal file
@@ -0,0 +1,44 @@
|
||||
#include "ForceMovementBehavior.h"
|
||||
|
||||
#include "BehaviorBranchContext.h"
|
||||
#include "BehaviorContext.h"
|
||||
|
||||
void ForceMovementBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, const BehaviorBranchContext branch)
|
||||
{
|
||||
if (this->m_hitAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY && this->m_hitEnemyAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY && this->m_hitFactionAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t handle;
|
||||
|
||||
bitStream->Read(handle);
|
||||
|
||||
context->RegisterSyncBehavior(handle, this, branch);
|
||||
}
|
||||
|
||||
void ForceMovementBehavior::Sync(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch)
|
||||
{
|
||||
uint32_t next;
|
||||
|
||||
bitStream->Read(next);
|
||||
|
||||
LWOOBJID target;
|
||||
|
||||
bitStream->Read(target);
|
||||
|
||||
auto* behavior = CreateBehavior(next);
|
||||
|
||||
branch.target = target;
|
||||
|
||||
behavior->Handle(context, bitStream, branch);
|
||||
}
|
||||
|
||||
void ForceMovementBehavior::Load()
|
||||
{
|
||||
this->m_hitAction = GetAction("hit_action");
|
||||
|
||||
this->m_hitEnemyAction = GetAction("hit_action_enemy");
|
||||
|
||||
this->m_hitFactionAction = GetAction("hit_action_faction");
|
||||
}
|
27
dGame/dBehaviors/ForceMovementBehavior.h
Normal file
27
dGame/dBehaviors/ForceMovementBehavior.h
Normal file
@@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
#include "Behavior.h"
|
||||
|
||||
class ForceMovementBehavior final : public Behavior
|
||||
{
|
||||
public:
|
||||
Behavior* m_hitAction;
|
||||
|
||||
Behavior* m_hitEnemyAction;
|
||||
|
||||
Behavior* m_hitFactionAction;
|
||||
|
||||
/*
|
||||
* Inherited
|
||||
*/
|
||||
|
||||
explicit ForceMovementBehavior(const uint32_t behaviorId) : Behavior(behaviorId)
|
||||
{
|
||||
}
|
||||
|
||||
void Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) override;
|
||||
|
||||
void Sync(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) override;
|
||||
|
||||
void Load() override;
|
||||
|
||||
};
|
42
dGame/dBehaviors/HealBehavior.cpp
Normal file
42
dGame/dBehaviors/HealBehavior.cpp
Normal file
@@ -0,0 +1,42 @@
|
||||
#include "HealBehavior.h"
|
||||
#include "BehaviorBranchContext.h"
|
||||
#include "Game.h"
|
||||
#include "dLogger.h"
|
||||
#include "EntityManager.h"
|
||||
#include "DestroyableComponent.h"
|
||||
|
||||
|
||||
void HealBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bit_stream, const BehaviorBranchContext branch)
|
||||
{
|
||||
auto* entity = EntityManager::Instance()->GetEntity(branch.target);
|
||||
|
||||
if (entity == nullptr)
|
||||
{
|
||||
Game::logger->Log("HealBehavior", "Failed to find entity for (%llu)!\n", branch.target);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
auto* destroyable = static_cast<DestroyableComponent*>(entity->GetComponent(COMPONENT_TYPE_DESTROYABLE));
|
||||
|
||||
if (destroyable == nullptr)
|
||||
{
|
||||
Game::logger->Log("HealBehavior", "Failed to find destroyable component for %(llu)!\n", branch.target);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
destroyable->Heal(this->m_health);
|
||||
}
|
||||
|
||||
|
||||
void HealBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bit_stream, const BehaviorBranchContext branch)
|
||||
{
|
||||
Handle(context, bit_stream, branch);
|
||||
}
|
||||
|
||||
|
||||
void HealBehavior::Load()
|
||||
{
|
||||
this->m_health = GetInt("health");
|
||||
}
|
22
dGame/dBehaviors/HealBehavior.h
Normal file
22
dGame/dBehaviors/HealBehavior.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
#include "Behavior.h"
|
||||
|
||||
class HealBehavior final : public Behavior
|
||||
{
|
||||
public:
|
||||
uint32_t m_health;
|
||||
|
||||
/*
|
||||
* Inherited
|
||||
*/
|
||||
|
||||
explicit HealBehavior(const uint32_t behavior_id) : Behavior(behavior_id)
|
||||
{
|
||||
}
|
||||
|
||||
void Handle(BehaviorContext* context, RakNet::BitStream* bit_stream, BehaviorBranchContext branch) override;
|
||||
|
||||
void Calculate(BehaviorContext* context, RakNet::BitStream* bit_stream, BehaviorBranchContext branch) override;
|
||||
|
||||
void Load() override;
|
||||
};
|
37
dGame/dBehaviors/ImaginationBehavior.cpp
Normal file
37
dGame/dBehaviors/ImaginationBehavior.cpp
Normal file
@@ -0,0 +1,37 @@
|
||||
#include "ImaginationBehavior.h"
|
||||
#include "BehaviorBranchContext.h"
|
||||
#include "DestroyableComponent.h"
|
||||
#include "dpWorld.h"
|
||||
#include "EntityManager.h"
|
||||
#include "dLogger.h"
|
||||
|
||||
|
||||
void ImaginationBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bit_stream, const BehaviorBranchContext branch)
|
||||
{
|
||||
auto* entity = EntityManager::Instance()->GetEntity(branch.target);
|
||||
|
||||
if (entity == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto* destroyable = entity->GetComponent<DestroyableComponent>();
|
||||
|
||||
if (destroyable == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
destroyable->Imagine(this->m_imagination);
|
||||
|
||||
}
|
||||
|
||||
void ImaginationBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bit_stream, const BehaviorBranchContext branch)
|
||||
{
|
||||
Handle(context, bit_stream, branch);
|
||||
}
|
||||
|
||||
void ImaginationBehavior::Load()
|
||||
{
|
||||
this->m_imagination = GetInt("imagination");
|
||||
}
|
22
dGame/dBehaviors/ImaginationBehavior.h
Normal file
22
dGame/dBehaviors/ImaginationBehavior.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
#include "Behavior.h"
|
||||
|
||||
class ImaginationBehavior final : public Behavior
|
||||
{
|
||||
public:
|
||||
int32_t m_imagination;
|
||||
|
||||
/*
|
||||
* Inherited
|
||||
*/
|
||||
|
||||
explicit ImaginationBehavior(const uint32_t behavior_id) : Behavior(behavior_id)
|
||||
{
|
||||
}
|
||||
|
||||
void Handle(BehaviorContext* context, RakNet::BitStream* bit_stream, BehaviorBranchContext branch) override;
|
||||
|
||||
void Calculate(BehaviorContext* context, RakNet::BitStream* bit_stream, BehaviorBranchContext branch) override;
|
||||
|
||||
void Load() override;
|
||||
};
|
67
dGame/dBehaviors/ImmunityBehavior.cpp
Normal file
67
dGame/dBehaviors/ImmunityBehavior.cpp
Normal file
@@ -0,0 +1,67 @@
|
||||
#include "ImmunityBehavior.h"
|
||||
|
||||
#include "BehaviorBranchContext.h"
|
||||
#include "BehaviorContext.h"
|
||||
#include "EntityManager.h"
|
||||
#include "Game.h"
|
||||
#include "dLogger.h"
|
||||
#include "DestroyableComponent.h"
|
||||
|
||||
void ImmunityBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, const BehaviorBranchContext branch)
|
||||
{
|
||||
auto* target = EntityManager::Instance()->GetEntity(branch.target);
|
||||
|
||||
if (target == nullptr)
|
||||
{
|
||||
Game::logger->Log("DamageAbsorptionBehavior", "Failed to find target (%llu)!\n", branch.target);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
auto* destroyable = static_cast<DestroyableComponent*>(target->GetComponent(COMPONENT_TYPE_DESTROYABLE));
|
||||
|
||||
if (destroyable == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this->m_immuneBasicAttack)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
destroyable->PushImmunity();
|
||||
|
||||
context->RegisterTimerBehavior(this, branch, target->GetObjectID());
|
||||
}
|
||||
|
||||
void ImmunityBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch)
|
||||
{
|
||||
Handle(context, bitStream, branch);
|
||||
}
|
||||
|
||||
void ImmunityBehavior::Timer(BehaviorContext* context, BehaviorBranchContext branch, const LWOOBJID second)
|
||||
{
|
||||
auto* target = EntityManager::Instance()->GetEntity(second);
|
||||
|
||||
if (target == nullptr)
|
||||
{
|
||||
Game::logger->Log("DamageAbsorptionBehavior", "Failed to find target (%llu)!\n", second);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
auto* destroyable = static_cast<DestroyableComponent*>(target->GetComponent(COMPONENT_TYPE_DESTROYABLE));
|
||||
|
||||
if (destroyable == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
destroyable->PopImmunity();
|
||||
}
|
||||
|
||||
void ImmunityBehavior::Load()
|
||||
{
|
||||
this->m_immuneBasicAttack = GetBoolean("immune_basic_attack");
|
||||
}
|
24
dGame/dBehaviors/ImmunityBehavior.h
Normal file
24
dGame/dBehaviors/ImmunityBehavior.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
#include "Behavior.h"
|
||||
|
||||
class ImmunityBehavior final : public Behavior
|
||||
{
|
||||
public:
|
||||
uint32_t m_immuneBasicAttack;
|
||||
|
||||
/*
|
||||
* Inherited
|
||||
*/
|
||||
|
||||
explicit ImmunityBehavior(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 Timer(BehaviorContext* context, BehaviorBranchContext branch, LWOOBJID second) override;
|
||||
|
||||
void Load() override;
|
||||
};
|
84
dGame/dBehaviors/InterruptBehavior.cpp
Normal file
84
dGame/dBehaviors/InterruptBehavior.cpp
Normal file
@@ -0,0 +1,84 @@
|
||||
#include "InterruptBehavior.h"
|
||||
#include "BehaviorBranchContext.h"
|
||||
#include "BehaviorContext.h"
|
||||
#include "Game.h"
|
||||
#include "dLogger.h"
|
||||
#include "EntityManager.h"
|
||||
#include "SkillComponent.h"
|
||||
|
||||
|
||||
void InterruptBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch)
|
||||
{
|
||||
if (branch.target != context->originator)
|
||||
{
|
||||
bool unknown = false;
|
||||
|
||||
bitStream->Read(unknown);
|
||||
|
||||
if (unknown) return;
|
||||
}
|
||||
|
||||
if (!this->m_interruptBlock)
|
||||
{
|
||||
bool unknown = false;
|
||||
|
||||
bitStream->Read(unknown);
|
||||
|
||||
if (unknown) return;
|
||||
}
|
||||
|
||||
if (this->m_target) // Guess...
|
||||
{
|
||||
bool unknown = false;
|
||||
|
||||
bitStream->Read(unknown);
|
||||
}
|
||||
|
||||
if (branch.target == context->originator) return;
|
||||
|
||||
auto* target = EntityManager::Instance()->GetEntity(branch.target);
|
||||
|
||||
if (target == nullptr) return;
|
||||
|
||||
auto* skillComponent = target->GetComponent<SkillComponent>();
|
||||
|
||||
if (skillComponent == nullptr) return;
|
||||
|
||||
skillComponent->Interrupt();
|
||||
}
|
||||
|
||||
|
||||
void InterruptBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch)
|
||||
{
|
||||
if (branch.target != context->originator)
|
||||
{
|
||||
bitStream->Write(false);
|
||||
}
|
||||
|
||||
if (!this->m_interruptBlock)
|
||||
{
|
||||
bitStream->Write(false);
|
||||
}
|
||||
|
||||
bitStream->Write(false);
|
||||
|
||||
if (branch.target == context->originator) return;
|
||||
|
||||
auto* target = EntityManager::Instance()->GetEntity(branch.target);
|
||||
|
||||
if (target == nullptr) return;
|
||||
|
||||
auto* skillComponent = target->GetComponent<SkillComponent>();
|
||||
|
||||
if (skillComponent == nullptr) return;
|
||||
|
||||
skillComponent->Interrupt();
|
||||
}
|
||||
|
||||
|
||||
void InterruptBehavior::Load()
|
||||
{
|
||||
this->m_target = GetBoolean("target");
|
||||
|
||||
this->m_interruptBlock = GetBoolean("interrupt_block");
|
||||
}
|
24
dGame/dBehaviors/InterruptBehavior.h
Normal file
24
dGame/dBehaviors/InterruptBehavior.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
#include "Behavior.h"
|
||||
|
||||
class InterruptBehavior final : public Behavior
|
||||
{
|
||||
public:
|
||||
bool m_target;
|
||||
|
||||
bool m_interruptBlock;
|
||||
|
||||
/*
|
||||
* Inherited
|
||||
*/
|
||||
|
||||
explicit InterruptBehavior(const uint32_t behavior_id) : Behavior(behavior_id)
|
||||
{
|
||||
}
|
||||
|
||||
void Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) override;
|
||||
|
||||
void Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) override;
|
||||
|
||||
void Load() override;
|
||||
};
|
42
dGame/dBehaviors/KnockbackBehavior.cpp
Normal file
42
dGame/dBehaviors/KnockbackBehavior.cpp
Normal file
@@ -0,0 +1,42 @@
|
||||
#define _USE_MATH_DEFINES
|
||||
#include <cmath>
|
||||
#include "KnockbackBehavior.h"
|
||||
#include "BehaviorBranchContext.h"
|
||||
#include "BehaviorContext.h"
|
||||
#include "EntityManager.h"
|
||||
#include "GameMessages.h"
|
||||
#include "DestroyableComponent.h"
|
||||
|
||||
void KnockbackBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch)
|
||||
{
|
||||
bool unknown;
|
||||
|
||||
bitStream->Read(unknown);
|
||||
}
|
||||
|
||||
void KnockbackBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch)
|
||||
{
|
||||
bool blocked = false;
|
||||
|
||||
auto* target = EntityManager::Instance()->GetEntity(branch.target);
|
||||
|
||||
if (target != nullptr)
|
||||
{
|
||||
auto* destroyableComponent = target->GetComponent<DestroyableComponent>();
|
||||
|
||||
if (destroyableComponent != nullptr)
|
||||
{
|
||||
blocked = destroyableComponent->IsKnockbackImmune();
|
||||
}
|
||||
}
|
||||
|
||||
bitStream->Write(blocked);
|
||||
}
|
||||
|
||||
void KnockbackBehavior::Load()
|
||||
{
|
||||
this->m_strength = GetInt("strength");
|
||||
this->m_angle = GetInt("angle");
|
||||
this->m_relative = GetBoolean("relative");
|
||||
this->m_time = GetInt("time_ms");
|
||||
}
|
26
dGame/dBehaviors/KnockbackBehavior.h
Normal file
26
dGame/dBehaviors/KnockbackBehavior.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
#include "Behavior.h"
|
||||
|
||||
class KnockbackBehavior final : public Behavior
|
||||
{
|
||||
public:
|
||||
/*
|
||||
* Inherited
|
||||
*/
|
||||
|
||||
uint32_t m_strength;
|
||||
uint32_t m_angle;
|
||||
bool m_relative;
|
||||
uint32_t m_time;
|
||||
|
||||
|
||||
explicit KnockbackBehavior(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;
|
||||
};
|
62
dGame/dBehaviors/MovementSwitchBehavior.cpp
Normal file
62
dGame/dBehaviors/MovementSwitchBehavior.cpp
Normal file
@@ -0,0 +1,62 @@
|
||||
#include "MovementSwitchBehavior.h"
|
||||
#include "BehaviorBranchContext.h"
|
||||
#include "Game.h"
|
||||
#include "dLogger.h"
|
||||
|
||||
void MovementSwitchBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, const BehaviorBranchContext branch)
|
||||
{
|
||||
if (this->m_groundAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY &&
|
||||
this->m_jumpAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY &&
|
||||
this->m_fallingAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY &&
|
||||
this->m_doubleJumpAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY &&
|
||||
this->m_airAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY &&
|
||||
this->m_jetpackAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t movementType;
|
||||
|
||||
bitStream->Read(movementType);
|
||||
|
||||
switch (movementType)
|
||||
{
|
||||
case 1:
|
||||
this->m_groundAction->Handle(context, bitStream, branch);
|
||||
break;
|
||||
case 2:
|
||||
this->m_jumpAction->Handle(context, bitStream, branch);
|
||||
break;
|
||||
case 3:
|
||||
this->m_fallingAction->Handle(context, bitStream, branch);
|
||||
break;
|
||||
case 4:
|
||||
this->m_doubleJumpAction->Handle(context, bitStream, branch);
|
||||
break;
|
||||
case 5:
|
||||
this->m_airAction->Handle(context, bitStream, branch);
|
||||
break;
|
||||
case 6:
|
||||
this->m_jetpackAction->Handle(context, bitStream, branch);
|
||||
break;
|
||||
default:
|
||||
Game::logger->Log("MovementSwitchBehavior", "Invalid movement behavior type (%i)!\n", movementType);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void MovementSwitchBehavior::Load()
|
||||
{
|
||||
this->m_airAction = GetAction("air_action");
|
||||
|
||||
this->m_doubleJumpAction = GetAction("double_jump_action");
|
||||
|
||||
this->m_fallingAction = GetAction("falling_action");
|
||||
|
||||
this->m_groundAction = GetAction("ground_action");
|
||||
|
||||
this->m_jetpackAction = GetAction("jetpack_action");
|
||||
|
||||
this->m_jumpAction = GetAction("jump_action");
|
||||
}
|
||||
|
32
dGame/dBehaviors/MovementSwitchBehavior.h
Normal file
32
dGame/dBehaviors/MovementSwitchBehavior.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
#include "Behavior.h"
|
||||
|
||||
class MovementSwitchBehavior final : public Behavior
|
||||
{
|
||||
public:
|
||||
/*
|
||||
* Members
|
||||
*/
|
||||
Behavior* m_airAction;
|
||||
|
||||
Behavior* m_doubleJumpAction;
|
||||
|
||||
Behavior* m_fallingAction;
|
||||
|
||||
Behavior* m_groundAction;
|
||||
|
||||
Behavior* m_jetpackAction;
|
||||
|
||||
Behavior* m_jumpAction;
|
||||
|
||||
/*
|
||||
* Inherited
|
||||
*/
|
||||
explicit MovementSwitchBehavior(const uint32_t behavior_id) : Behavior(behavior_id)
|
||||
{
|
||||
}
|
||||
|
||||
void Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) override;
|
||||
|
||||
void Load() override;
|
||||
};
|
31
dGame/dBehaviors/NpcCombatSkillBehavior.cpp
Normal file
31
dGame/dBehaviors/NpcCombatSkillBehavior.cpp
Normal file
@@ -0,0 +1,31 @@
|
||||
#include "NpcCombatSkillBehavior.h"
|
||||
#include "BehaviorBranchContext.h"
|
||||
#include "BehaviorContext.h"
|
||||
|
||||
|
||||
void NpcCombatSkillBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bit_stream, BehaviorBranchContext branch)
|
||||
{
|
||||
context->skillTime = this->m_npcSkillTime;
|
||||
|
||||
for (auto* behavior : this->m_behaviors)
|
||||
{
|
||||
behavior->Calculate(context, bit_stream, branch);
|
||||
}
|
||||
}
|
||||
|
||||
void NpcCombatSkillBehavior::Load()
|
||||
{
|
||||
this->m_npcSkillTime = GetFloat("npc skill time");
|
||||
|
||||
const auto parameters = GetParameterNames();
|
||||
|
||||
for (const auto& parameter : parameters)
|
||||
{
|
||||
if (parameter.first.rfind("behavior", 0) == 0)
|
||||
{
|
||||
auto* action = GetAction(parameter.second);
|
||||
|
||||
this->m_behaviors.push_back(action);
|
||||
}
|
||||
}
|
||||
}
|
22
dGame/dBehaviors/NpcCombatSkillBehavior.h
Normal file
22
dGame/dBehaviors/NpcCombatSkillBehavior.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
#include "Behavior.h"
|
||||
|
||||
class NpcCombatSkillBehavior final : public Behavior
|
||||
{
|
||||
public:
|
||||
std::vector<Behavior*> m_behaviors;
|
||||
|
||||
float m_npcSkillTime;
|
||||
|
||||
/*
|
||||
* Inherited
|
||||
*/
|
||||
|
||||
explicit NpcCombatSkillBehavior(const uint32_t behavior_id) : Behavior(behavior_id)
|
||||
{
|
||||
}
|
||||
|
||||
void Calculate(BehaviorContext* context, RakNet::BitStream* bit_stream, BehaviorBranchContext branch) override;
|
||||
|
||||
void Load() override;
|
||||
};
|
80
dGame/dBehaviors/OverTimeBehavior.cpp
Normal file
80
dGame/dBehaviors/OverTimeBehavior.cpp
Normal file
@@ -0,0 +1,80 @@
|
||||
#include "OverTimeBehavior.h"
|
||||
#include "BehaviorBranchContext.h"
|
||||
#include "BehaviorContext.h"
|
||||
#include "Game.h"
|
||||
#include "dLogger.h"
|
||||
#include "EntityManager.h"
|
||||
#include "SkillComponent.h"
|
||||
#include "DestroyableComponent.h"
|
||||
|
||||
/**
|
||||
* The OverTime behavior is very inconsistent in how it appears in the skill tree vs. how it should behave.
|
||||
*
|
||||
* Items like "Doc in a Box" use an overtime behavior which you would expect have health & armor regen, but is only fallowed by a stun.
|
||||
*
|
||||
* Due to this inconsistency, we have to implement a special case for some items.
|
||||
*/
|
||||
|
||||
void OverTimeBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch)
|
||||
{
|
||||
const auto originator = context->originator;
|
||||
|
||||
auto* entity = EntityManager::Instance()->GetEntity(originator);
|
||||
|
||||
if (entity == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < m_NumIntervals; i++)
|
||||
{
|
||||
entity->AddCallbackTimer((i + 1) * m_Delay, [originator, branch, this]() {
|
||||
auto* entity = EntityManager::Instance()->GetEntity(originator);
|
||||
|
||||
if (entity == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto* skillComponent = entity->GetComponent<SkillComponent>();
|
||||
|
||||
if (skillComponent == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
skillComponent->CalculateBehavior(0, m_Action->m_behaviorId, branch.target, true, true);
|
||||
|
||||
auto* destroyableComponent = entity->GetComponent<DestroyableComponent>();
|
||||
|
||||
if (destroyableComponent == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Special cases for inconsistent behavior.
|
||||
*/
|
||||
|
||||
switch (m_behaviorId)
|
||||
{
|
||||
case 26253: // "Doc in a Box", heal up to 6 health and regen up to 18 armor.
|
||||
destroyableComponent->Heal(1);
|
||||
destroyableComponent->Repair(3);
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void OverTimeBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void OverTimeBehavior::Load()
|
||||
{
|
||||
m_Action = GetAction("action");
|
||||
m_Delay = GetFloat("delay");
|
||||
m_NumIntervals = GetInt("num_intervals");
|
||||
}
|
24
dGame/dBehaviors/OverTimeBehavior.h
Normal file
24
dGame/dBehaviors/OverTimeBehavior.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
#include "Behavior.h"
|
||||
|
||||
class OverTimeBehavior final : public Behavior
|
||||
{
|
||||
public:
|
||||
Behavior* m_Action;
|
||||
float m_Delay;
|
||||
int32_t m_NumIntervals;
|
||||
|
||||
/*
|
||||
* Inherited
|
||||
*/
|
||||
|
||||
explicit OverTimeBehavior(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;
|
||||
};
|
26
dGame/dBehaviors/PlayEffectBehavior.cpp
Normal file
26
dGame/dBehaviors/PlayEffectBehavior.cpp
Normal file
@@ -0,0 +1,26 @@
|
||||
#include "PlayEffectBehavior.h"
|
||||
|
||||
#include "BehaviorContext.h"
|
||||
#include "BehaviorBranchContext.h"
|
||||
|
||||
void PlayEffectBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch)
|
||||
{
|
||||
// On managed behaviors this is handled by the client
|
||||
if (!context->unmanaged)
|
||||
return;
|
||||
|
||||
const auto& target = branch.target == LWOOBJID_EMPTY ? context->originator : branch.target;
|
||||
|
||||
PlayFx(u"", target);
|
||||
}
|
||||
|
||||
void PlayEffectBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch)
|
||||
{
|
||||
const auto& target = branch.target == LWOOBJID_EMPTY ? context->originator : branch.target;
|
||||
|
||||
//PlayFx(u"", target);
|
||||
}
|
||||
|
||||
void PlayEffectBehavior::Load()
|
||||
{
|
||||
}
|
19
dGame/dBehaviors/PlayEffectBehavior.h
Normal file
19
dGame/dBehaviors/PlayEffectBehavior.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
#include "Behavior.h"
|
||||
|
||||
class PlayEffectBehavior final : public Behavior
|
||||
{
|
||||
public:
|
||||
/*
|
||||
* Inherited
|
||||
*/
|
||||
explicit PlayEffectBehavior(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;
|
||||
};
|
166
dGame/dBehaviors/ProjectileAttackBehavior.cpp
Normal file
166
dGame/dBehaviors/ProjectileAttackBehavior.cpp
Normal file
@@ -0,0 +1,166 @@
|
||||
#include "ProjectileAttackBehavior.h"
|
||||
#include "BehaviorBranchContext.h"
|
||||
#include "BehaviorContext.h"
|
||||
#include "EntityManager.h"
|
||||
#include "Game.h"
|
||||
#include "dLogger.h"
|
||||
#include "SkillComponent.h"
|
||||
#include "../dWorldServer/ObjectIDManager.h"
|
||||
|
||||
void ProjectileAttackBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch)
|
||||
{
|
||||
LWOOBJID target;
|
||||
|
||||
bitStream->Read(target);
|
||||
|
||||
auto* entity = EntityManager::Instance()->GetEntity(context->originator);
|
||||
|
||||
if (entity == nullptr)
|
||||
{
|
||||
Game::logger->Log("ProjectileAttackBehavior", "Failed to find originator (%llu)!\n", context->originator);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
auto* skillComponent = entity->GetComponent<SkillComponent>();
|
||||
|
||||
if (skillComponent == nullptr)
|
||||
{
|
||||
Game::logger->Log("ProjectileAttackBehavior", "Failed to find skill component for (%llu)!\n", -context->originator);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_useMouseposit)
|
||||
{
|
||||
NiPoint3 targetPosition = NiPoint3::ZERO;
|
||||
bitStream->Read(targetPosition);
|
||||
}
|
||||
|
||||
auto* targetEntity = EntityManager::Instance()->GetEntity(target);
|
||||
|
||||
for (auto i = 0u; i < this->m_projectileCount; ++i)
|
||||
{
|
||||
LWOOBJID projectileId;
|
||||
|
||||
bitStream->Read(projectileId);
|
||||
|
||||
branch.target = target;
|
||||
branch.isProjectile = true;
|
||||
branch.referencePosition = targetEntity == nullptr ? entity->GetPosition() : targetEntity->GetPosition();
|
||||
|
||||
skillComponent->RegisterPlayerProjectile(projectileId, context, branch, this->m_lot);
|
||||
}
|
||||
}
|
||||
|
||||
void ProjectileAttackBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch)
|
||||
{
|
||||
bitStream->Write(branch.target);
|
||||
|
||||
auto* entity = EntityManager::Instance()->GetEntity(context->originator);
|
||||
|
||||
if (entity == nullptr)
|
||||
{
|
||||
Game::logger->Log("ProjectileAttackBehavior", "Failed to find originator (%llu)!\n", context->originator);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
auto* skillComponent = entity->GetComponent<SkillComponent>();
|
||||
|
||||
if (skillComponent == nullptr)
|
||||
{
|
||||
Game::logger->Log("ProjectileAttackBehavior", "Failed to find skill component for (%llu)!\n", context->originator);
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
auto* other = EntityManager::Instance()->GetEntity(branch.target);
|
||||
|
||||
if (other == nullptr)
|
||||
{
|
||||
Game::logger->Log("ProjectileAttackBehavior", "Invalid projectile target (%llu)!\n", branch.target);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const auto position = entity->GetPosition() + this->m_offset;
|
||||
|
||||
const auto distance = Vector3::Distance(position, other->GetPosition());
|
||||
|
||||
const auto time = distance / this->m_projectileSpeed;
|
||||
|
||||
const auto rotation = NiQuaternion::LookAtUnlocked(position, other->GetPosition());
|
||||
|
||||
const auto targetPosition = other->GetPosition();
|
||||
|
||||
//entity->SetRotation(rotation);
|
||||
|
||||
const auto angleDelta = this->m_spreadAngle;
|
||||
const auto angleStep = angleDelta / this->m_projectileCount;
|
||||
|
||||
auto angle = -angleStep;
|
||||
|
||||
const auto maxTime = this->m_maxDistance / this->m_projectileSpeed;
|
||||
|
||||
for (auto i = 0u; i < this->m_projectileCount; ++i)
|
||||
{
|
||||
auto id = static_cast<LWOOBJID>(ObjectIDManager::Instance()->GenerateObjectID());
|
||||
|
||||
id = GeneralUtils::SetBit(id, OBJECT_BIT_CLIENT);
|
||||
|
||||
bitStream->Write(id);
|
||||
|
||||
auto eulerAngles = rotation.GetEulerAngles();
|
||||
|
||||
eulerAngles.y += angle * (3.14 / 180);
|
||||
|
||||
const auto angledRotation = NiQuaternion::FromEulerAngles(eulerAngles);
|
||||
|
||||
const auto direction = angledRotation.GetForwardVector();
|
||||
|
||||
const auto destination = position + direction * distance;
|
||||
|
||||
branch.isProjectile = true;
|
||||
branch.referencePosition = destination;
|
||||
|
||||
skillComponent->RegisterCalculatedProjectile(id, context, branch, this->m_lot, maxTime, position, direction * this->m_projectileSpeed, this->m_trackTarget, this->m_trackRadius);
|
||||
|
||||
// No idea how to calculate this properly
|
||||
if (this->m_projectileCount == 2)
|
||||
{
|
||||
angle += angleDelta;
|
||||
}
|
||||
else if (this->m_projectileCount == 3)
|
||||
{
|
||||
angle += angleStep;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ProjectileAttackBehavior::Load()
|
||||
{
|
||||
this->m_lot = GetInt("LOT_ID");
|
||||
|
||||
this->m_projectileCount = GetInt("spread_count");
|
||||
|
||||
if (this->m_projectileCount == 0)
|
||||
{
|
||||
this->m_projectileCount = 1;
|
||||
}
|
||||
|
||||
this->m_maxDistance = GetFloat("max_distance");
|
||||
|
||||
this->m_projectileSpeed = GetFloat("projectile_speed");
|
||||
|
||||
this->m_spreadAngle = GetFloat("spread_angle");
|
||||
|
||||
this->m_offset = { GetFloat("offset_x"), GetFloat("offset_y"), GetFloat("offset_z") };
|
||||
|
||||
this->m_trackTarget = GetBoolean("track_target");
|
||||
|
||||
this->m_trackRadius = GetFloat("track_radius");
|
||||
|
||||
this->m_useMouseposit = GetBoolean("use_mouseposit");
|
||||
}
|
39
dGame/dBehaviors/ProjectileAttackBehavior.h
Normal file
39
dGame/dBehaviors/ProjectileAttackBehavior.h
Normal file
@@ -0,0 +1,39 @@
|
||||
#pragma once
|
||||
#include "Behavior.h"
|
||||
#include "NiPoint3.h"
|
||||
|
||||
class ProjectileAttackBehavior final : public Behavior
|
||||
{
|
||||
public:
|
||||
LOT m_lot;
|
||||
|
||||
uint32_t m_projectileCount;
|
||||
|
||||
float m_projectileSpeed;
|
||||
|
||||
float m_maxDistance;
|
||||
|
||||
float m_spreadAngle;
|
||||
|
||||
NiPoint3 m_offset;
|
||||
|
||||
bool m_trackTarget;
|
||||
|
||||
float m_trackRadius;
|
||||
|
||||
bool m_useMouseposit;
|
||||
|
||||
/*
|
||||
* Inherited
|
||||
*/
|
||||
|
||||
explicit ProjectileAttackBehavior(const uint32_t behavior_id) : Behavior(behavior_id)
|
||||
{
|
||||
}
|
||||
|
||||
void Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) override;
|
||||
|
||||
void Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) override;
|
||||
|
||||
void Load() override;
|
||||
};
|
38
dGame/dBehaviors/PullToPointBehavior.cpp
Normal file
38
dGame/dBehaviors/PullToPointBehavior.cpp
Normal file
@@ -0,0 +1,38 @@
|
||||
#include "PullToPointBehavior.h"
|
||||
|
||||
#include "BehaviorContext.h"
|
||||
#include "BehaviorBranchContext.h"
|
||||
#include "EntityManager.h"
|
||||
#include "MovementAIComponent.h"
|
||||
|
||||
void PullToPointBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch)
|
||||
{
|
||||
auto* entity = EntityManager::Instance()->GetEntity(context->originator);
|
||||
|
||||
auto* target = EntityManager::Instance()->GetEntity(branch.target);
|
||||
|
||||
if (entity == nullptr || target == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto* movement = target->GetComponent<MovementAIComponent>();
|
||||
|
||||
if (movement == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const auto position = branch.isProjectile ? branch.referencePosition : entity->GetPosition();
|
||||
|
||||
movement->PullToPoint(position);
|
||||
}
|
||||
|
||||
void PullToPointBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch)
|
||||
{
|
||||
Handle(context, bitStream, branch);
|
||||
}
|
||||
|
||||
void PullToPointBehavior::Load()
|
||||
{
|
||||
}
|
21
dGame/dBehaviors/PullToPointBehavior.h
Normal file
21
dGame/dBehaviors/PullToPointBehavior.h
Normal file
@@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
#include "Behavior.h"
|
||||
|
||||
class PullToPointBehavior final : public Behavior
|
||||
{
|
||||
public:
|
||||
|
||||
/*
|
||||
* Inherited
|
||||
*/
|
||||
|
||||
explicit PullToPointBehavior(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;
|
||||
};
|
40
dGame/dBehaviors/RepairBehavior.cpp
Normal file
40
dGame/dBehaviors/RepairBehavior.cpp
Normal file
@@ -0,0 +1,40 @@
|
||||
#include "RepairBehavior.h"
|
||||
#include "BehaviorBranchContext.h"
|
||||
#include "DestroyableComponent.h"
|
||||
#include "dpWorld.h"
|
||||
#include "EntityManager.h"
|
||||
#include "dLogger.h"
|
||||
#include "Game.h"
|
||||
|
||||
void RepairBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bit_stream, const BehaviorBranchContext branch)
|
||||
{
|
||||
auto* entity = EntityManager::Instance()->GetEntity(branch.target);
|
||||
|
||||
if (entity == nullptr)
|
||||
{
|
||||
Game::logger->Log("RepairBehavior", "Failed to find entity for (%llu)!\n", branch.target);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
auto* destroyable = static_cast<DestroyableComponent*>(entity->GetComponent(COMPONENT_TYPE_DESTROYABLE));
|
||||
|
||||
if (destroyable == nullptr)
|
||||
{
|
||||
Game::logger->Log("RepairBehavior", "Failed to find destroyable component for %(llu)!\n", branch.target);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
destroyable->Repair(this->m_armor);
|
||||
}
|
||||
|
||||
void RepairBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bit_stream, const BehaviorBranchContext branch)
|
||||
{
|
||||
Handle(context, bit_stream, branch);
|
||||
}
|
||||
|
||||
void RepairBehavior::Load()
|
||||
{
|
||||
this->m_armor = GetInt("armor");
|
||||
}
|
22
dGame/dBehaviors/RepairBehavior.h
Normal file
22
dGame/dBehaviors/RepairBehavior.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
#include "Behavior.h"
|
||||
|
||||
class RepairBehavior final : public Behavior
|
||||
{
|
||||
public:
|
||||
uint32_t m_armor;
|
||||
|
||||
/*
|
||||
* Inherited
|
||||
*/
|
||||
|
||||
explicit RepairBehavior(const uint32_t behavior_id) : Behavior(behavior_id)
|
||||
{
|
||||
}
|
||||
|
||||
void Handle(BehaviorContext* context, RakNet::BitStream* bit_stream, BehaviorBranchContext branch) override;
|
||||
|
||||
void Calculate(BehaviorContext* context, RakNet::BitStream* bit_stream, BehaviorBranchContext branch) override;
|
||||
|
||||
void Load() override;
|
||||
};
|
18
dGame/dBehaviors/SkillCastFailedBehavior.cpp
Normal file
18
dGame/dBehaviors/SkillCastFailedBehavior.cpp
Normal file
@@ -0,0 +1,18 @@
|
||||
#include "SkillCastFailedBehavior.h"
|
||||
|
||||
#include "BehaviorContext.h"
|
||||
#include "BehaviorBranchContext.h"
|
||||
|
||||
void SkillCastFailedBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch)
|
||||
{
|
||||
context->failed = true;
|
||||
}
|
||||
|
||||
void SkillCastFailedBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch)
|
||||
{
|
||||
context->failed = true;
|
||||
}
|
||||
|
||||
void SkillCastFailedBehavior::Load()
|
||||
{
|
||||
}
|
20
dGame/dBehaviors/SkillCastFailedBehavior.h
Normal file
20
dGame/dBehaviors/SkillCastFailedBehavior.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
#include "Behavior.h"
|
||||
|
||||
class SkillCastFailedBehavior final : public Behavior
|
||||
{
|
||||
public:
|
||||
|
||||
/*
|
||||
* Inherited
|
||||
*/
|
||||
explicit SkillCastFailedBehavior(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;
|
||||
};
|
28
dGame/dBehaviors/SkillEventBehavior.cpp
Normal file
28
dGame/dBehaviors/SkillEventBehavior.cpp
Normal file
@@ -0,0 +1,28 @@
|
||||
#include "SkillEventBehavior.h"
|
||||
#include "BehaviorBranchContext.h"
|
||||
#include "BehaviorContext.h"
|
||||
#include "EntityManager.h"
|
||||
#include "CppScripts.h"
|
||||
|
||||
void SkillEventBehavior::Handle(BehaviorContext *context, RakNet::BitStream *bitStream, BehaviorBranchContext branch) {
|
||||
auto* target = EntityManager::Instance()->GetEntity(branch.target);
|
||||
auto* caster = EntityManager::Instance()->GetEntity(context->originator);
|
||||
|
||||
if (caster != nullptr && target != nullptr && this->m_effectHandle != nullptr && !this->m_effectHandle->empty()) {
|
||||
for (CppScripts::Script* script : CppScripts::GetEntityScripts(target)) {
|
||||
script->OnSkillEventFired(target, caster, *this->m_effectHandle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SkillEventBehavior::Calculate(BehaviorContext *context, RakNet::BitStream *bitStream, BehaviorBranchContext branch) {
|
||||
auto* target = EntityManager::Instance()->GetEntity(branch.target);
|
||||
auto* caster = EntityManager::Instance()->GetEntity(context->originator);
|
||||
|
||||
if (caster != nullptr && target != nullptr && this->m_effectHandle != nullptr && !this->m_effectHandle->empty()) {
|
||||
for (CppScripts::Script* script : CppScripts::GetEntityScripts(target)) {
|
||||
script->OnSkillEventFired(target, caster, *this->m_effectHandle);
|
||||
}
|
||||
}
|
||||
}
|
15
dGame/dBehaviors/SkillEventBehavior.h
Normal file
15
dGame/dBehaviors/SkillEventBehavior.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
#include "Behavior.h"
|
||||
|
||||
/**
|
||||
* Behavior that casts explicit events on its target
|
||||
*/
|
||||
class SkillEventBehavior final : public Behavior {
|
||||
public:
|
||||
explicit SkillEventBehavior(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;
|
||||
};
|
||||
|
120
dGame/dBehaviors/SpawnBehavior.cpp
Normal file
120
dGame/dBehaviors/SpawnBehavior.cpp
Normal file
@@ -0,0 +1,120 @@
|
||||
#include "SpawnBehavior.h"
|
||||
|
||||
#include "BehaviorContext.h"
|
||||
#include "BehaviorBranchContext.h"
|
||||
#include "EntityManager.h"
|
||||
#include "Game.h"
|
||||
#include "dLogger.h"
|
||||
#include "DestroyableComponent.h"
|
||||
#include "RebuildComponent.h"
|
||||
|
||||
void SpawnBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch)
|
||||
{
|
||||
auto* origin = EntityManager::Instance()->GetEntity(context->originator);
|
||||
|
||||
if (origin == nullptr)
|
||||
{
|
||||
Game::logger->Log("SpawnBehavior", "Failed to find self entity (%llu)!\n", context->originator);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (branch.isProjectile)
|
||||
{
|
||||
auto* target = EntityManager::Instance()->GetEntity(branch.target);
|
||||
|
||||
if (target != nullptr)
|
||||
{
|
||||
origin = target;
|
||||
}
|
||||
}
|
||||
|
||||
EntityInfo info;
|
||||
info.lot = this->m_lot;
|
||||
info.pos = origin->GetPosition();
|
||||
info.rot = origin->GetRotation();
|
||||
info.scale = 1;
|
||||
info.spawner = nullptr;
|
||||
info.spawnerID = context->originator;
|
||||
info.spawnerNodeID = 0;
|
||||
info.pos = info.pos + (info.rot.GetForwardVector() * m_Distance);
|
||||
|
||||
auto* entity = EntityManager::Instance()->CreateEntity(
|
||||
info,
|
||||
nullptr,
|
||||
EntityManager::Instance()->GetEntity(context->originator)
|
||||
);
|
||||
|
||||
if (entity == nullptr)
|
||||
{
|
||||
Game::logger->Log("SpawnBehavior", "Failed to spawn entity (%i)!\n", this->m_lot);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
entity->SetOwnerOverride(context->originator);
|
||||
|
||||
// Unset the flag to reposition the player, this makes it harder to glitch out of the map
|
||||
auto* rebuildComponent = entity->GetComponent<RebuildComponent>();
|
||||
|
||||
if (rebuildComponent != nullptr)
|
||||
{
|
||||
rebuildComponent->SetRepositionPlayer(false);
|
||||
}
|
||||
|
||||
EntityManager::Instance()->ConstructEntity(entity);
|
||||
|
||||
if (branch.duration > 0)
|
||||
{
|
||||
context->RegisterTimerBehavior(this, branch, entity->GetObjectID());
|
||||
}
|
||||
|
||||
if (branch.start != 0)
|
||||
{
|
||||
context->RegisterEndBehavior(this, branch, entity->GetObjectID());
|
||||
}
|
||||
|
||||
entity->AddCallbackTimer(60, [entity] () {
|
||||
entity->Smash();
|
||||
});
|
||||
}
|
||||
|
||||
void SpawnBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch)
|
||||
{
|
||||
Handle(context, bitStream, branch);
|
||||
}
|
||||
|
||||
void SpawnBehavior::Timer(BehaviorContext* context, const BehaviorBranchContext branch, const LWOOBJID second)
|
||||
{
|
||||
auto* entity = EntityManager::Instance()->GetEntity(second);
|
||||
|
||||
if (entity == nullptr)
|
||||
{
|
||||
Game::logger->Log("SpawnBehavior", "Failed to find spawned entity (%llu)!\n", second);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
auto* destroyable = static_cast<DestroyableComponent*>(entity->GetComponent(COMPONENT_TYPE_DESTROYABLE));
|
||||
|
||||
if (destroyable == nullptr)
|
||||
{
|
||||
entity->Smash(context->originator);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
destroyable->Smash(second);
|
||||
}
|
||||
|
||||
void SpawnBehavior::End(BehaviorContext* context, const BehaviorBranchContext branch, const LWOOBJID second)
|
||||
{
|
||||
Timer(context, branch, second);
|
||||
}
|
||||
|
||||
|
||||
void SpawnBehavior::Load()
|
||||
{
|
||||
this->m_lot = GetInt("LOT_ID");
|
||||
this->m_Distance = GetFloat("distance");
|
||||
}
|
26
dGame/dBehaviors/SpawnBehavior.h
Normal file
26
dGame/dBehaviors/SpawnBehavior.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
#include "Behavior.h"
|
||||
|
||||
class SpawnBehavior final : public Behavior
|
||||
{
|
||||
public:
|
||||
LOT m_lot;
|
||||
float m_Distance;
|
||||
|
||||
/*
|
||||
* Inherited
|
||||
*/
|
||||
explicit SpawnBehavior(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 Timer(BehaviorContext* context, BehaviorBranchContext branch, LWOOBJID second) override;
|
||||
|
||||
void End(BehaviorContext* context, BehaviorBranchContext branch, LWOOBJID second) override;
|
||||
|
||||
void Load() override;
|
||||
};
|
13
dGame/dBehaviors/SpawnQuickbuildBehavior.cpp
Normal file
13
dGame/dBehaviors/SpawnQuickbuildBehavior.cpp
Normal file
@@ -0,0 +1,13 @@
|
||||
#include "SpawnQuickbuildBehavior.h"
|
||||
|
||||
#include "BehaviorBranchContext.h"
|
||||
#include "BehaviorContext.h"
|
||||
|
||||
void SpawnQuickbuildBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch)
|
||||
{
|
||||
}
|
||||
|
||||
void SpawnQuickbuildBehavior::Load()
|
||||
{
|
||||
}
|
||||
|
18
dGame/dBehaviors/SpawnQuickbuildBehavior.h
Normal file
18
dGame/dBehaviors/SpawnQuickbuildBehavior.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
#include "Behavior.h"
|
||||
|
||||
class SpawnQuickbuildBehavior final : public Behavior
|
||||
{
|
||||
public:
|
||||
|
||||
/*
|
||||
* Inherited
|
||||
*/
|
||||
explicit SpawnQuickbuildBehavior(const uint32_t behaviorId) : Behavior(behaviorId)
|
||||
{
|
||||
}
|
||||
|
||||
void Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) override;
|
||||
|
||||
void Load() override;
|
||||
};
|
106
dGame/dBehaviors/SpeedBehavior.cpp
Normal file
106
dGame/dBehaviors/SpeedBehavior.cpp
Normal file
@@ -0,0 +1,106 @@
|
||||
#include "SpeedBehavior.h"
|
||||
|
||||
#include "ControllablePhysicsComponent.h"
|
||||
#include "BehaviorContext.h"
|
||||
#include "BehaviorBranchContext.h"
|
||||
#include "dLogger.h"
|
||||
|
||||
|
||||
void SpeedBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch)
|
||||
{
|
||||
if (m_AffectsCaster)
|
||||
{
|
||||
branch.target = context->caster;
|
||||
}
|
||||
|
||||
auto* target = EntityManager::Instance()->GetEntity(branch.target);
|
||||
|
||||
if (target == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto* controllablePhysicsComponent = target->GetComponent<ControllablePhysicsComponent>();
|
||||
|
||||
if (controllablePhysicsComponent == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const auto current = controllablePhysicsComponent->GetSpeedMultiplier();
|
||||
|
||||
controllablePhysicsComponent->SetSpeedMultiplier(current + ((m_RunSpeed - 500.0f) / 500.0f));
|
||||
|
||||
EntityManager::Instance()->SerializeEntity(target);
|
||||
|
||||
if (branch.duration > 0.0f)
|
||||
{
|
||||
context->RegisterTimerBehavior(this, branch);
|
||||
}
|
||||
else if (branch.start > 0)
|
||||
{
|
||||
controllablePhysicsComponent->SetIgnoreMultipliers(true);
|
||||
|
||||
context->RegisterEndBehavior(this, branch);
|
||||
}
|
||||
}
|
||||
|
||||
void SpeedBehavior::Timer(BehaviorContext* context, BehaviorBranchContext branch, LWOOBJID second)
|
||||
{
|
||||
auto* target = EntityManager::Instance()->GetEntity(branch.target);
|
||||
|
||||
if (target == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto* controllablePhysicsComponent = target->GetComponent<ControllablePhysicsComponent>();
|
||||
|
||||
if (controllablePhysicsComponent == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const auto current = controllablePhysicsComponent->GetSpeedMultiplier();
|
||||
|
||||
controllablePhysicsComponent->SetSpeedMultiplier(current - ((m_RunSpeed - 500.0f) / 500.0f));
|
||||
|
||||
EntityManager::Instance()->SerializeEntity(target);
|
||||
}
|
||||
|
||||
void SpeedBehavior::End(BehaviorContext* context, BehaviorBranchContext branch, LWOOBJID second)
|
||||
{
|
||||
auto* target = EntityManager::Instance()->GetEntity(branch.target);
|
||||
|
||||
if (target == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto* controllablePhysicsComponent = target->GetComponent<ControllablePhysicsComponent>();
|
||||
|
||||
if (controllablePhysicsComponent == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const auto current = controllablePhysicsComponent->GetSpeedMultiplier();
|
||||
|
||||
controllablePhysicsComponent->SetIgnoreMultipliers(false);
|
||||
|
||||
controllablePhysicsComponent->SetSpeedMultiplier(current - ((m_RunSpeed - 500.0f) / 500.0f));
|
||||
|
||||
EntityManager::Instance()->SerializeEntity(target);
|
||||
}
|
||||
|
||||
void SpeedBehavior::Load()
|
||||
{
|
||||
m_RunSpeed = GetFloat("run_speed");
|
||||
|
||||
if (m_RunSpeed < 500.0f)
|
||||
{
|
||||
m_RunSpeed = 500.0f;
|
||||
}
|
||||
|
||||
m_AffectsCaster = GetBoolean("affects_caster");
|
||||
}
|
27
dGame/dBehaviors/SpeedBehavior.h
Normal file
27
dGame/dBehaviors/SpeedBehavior.h
Normal file
@@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
#include "Behavior.h"
|
||||
|
||||
class SpeedBehavior final : public Behavior
|
||||
{
|
||||
public:
|
||||
|
||||
/*
|
||||
* Inherited
|
||||
*/
|
||||
explicit SpeedBehavior(const uint32_t behaviorId) : Behavior(behaviorId)
|
||||
{
|
||||
}
|
||||
|
||||
void Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) override;
|
||||
|
||||
void Timer(BehaviorContext* context, BehaviorBranchContext branch, LWOOBJID second) override;
|
||||
|
||||
void End(BehaviorContext* context, BehaviorBranchContext branch, LWOOBJID second) override;
|
||||
|
||||
void Load() override;
|
||||
|
||||
private:
|
||||
float m_RunSpeed;
|
||||
|
||||
bool m_AffectsCaster;
|
||||
};
|
21
dGame/dBehaviors/StartBehavior.cpp
Normal file
21
dGame/dBehaviors/StartBehavior.cpp
Normal file
@@ -0,0 +1,21 @@
|
||||
#include "StartBehavior.h"
|
||||
#include "BehaviorBranchContext.h"
|
||||
|
||||
void StartBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bit_stream, BehaviorBranchContext branch)
|
||||
{
|
||||
branch.start = this->m_behaviorId;
|
||||
|
||||
this->m_action->Handle(context, bit_stream, branch);
|
||||
}
|
||||
|
||||
void StartBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bit_stream, BehaviorBranchContext branch)
|
||||
{
|
||||
branch.start = this->m_behaviorId;
|
||||
|
||||
this->m_action->Calculate(context, bit_stream, branch);
|
||||
}
|
||||
|
||||
void StartBehavior::Load()
|
||||
{
|
||||
this->m_action = GetAction("action");
|
||||
}
|
22
dGame/dBehaviors/StartBehavior.h
Normal file
22
dGame/dBehaviors/StartBehavior.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
#include "Behavior.h"
|
||||
|
||||
class StartBehavior final : public Behavior
|
||||
{
|
||||
public:
|
||||
Behavior* m_action;
|
||||
|
||||
/*
|
||||
* Inherited
|
||||
*/
|
||||
|
||||
explicit StartBehavior(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;
|
||||
};
|
113
dGame/dBehaviors/StunBehavior.cpp
Normal file
113
dGame/dBehaviors/StunBehavior.cpp
Normal file
@@ -0,0 +1,113 @@
|
||||
#include "StunBehavior.h"
|
||||
|
||||
#include "BaseCombatAIComponent.h"
|
||||
#include "BehaviorBranchContext.h"
|
||||
#include "BehaviorContext.h"
|
||||
#include "EntityManager.h"
|
||||
#include "Game.h"
|
||||
#include "dLogger.h"
|
||||
#include "DestroyableComponent.h"
|
||||
|
||||
|
||||
void StunBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, const BehaviorBranchContext branch)
|
||||
{
|
||||
if (this->m_stunCaster || branch.target == context->originator) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool blocked;
|
||||
bitStream->Read(blocked);
|
||||
|
||||
auto* target = EntityManager::Instance()->GetEntity(branch.target);
|
||||
|
||||
if (target == nullptr)
|
||||
{
|
||||
Game::logger->Log("StunBehavior", "Failed to find target (%llu)!\n", branch.target);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* If our target is an enemy we can go ahead and stun it.
|
||||
*/
|
||||
|
||||
auto* combatAiComponent = static_cast<BaseCombatAIComponent*>(target->GetComponent(COMPONENT_TYPE_BASE_COMBAT_AI));
|
||||
|
||||
if (combatAiComponent == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
combatAiComponent->Stun(branch.duration);
|
||||
}
|
||||
|
||||
void StunBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, const BehaviorBranchContext branch)
|
||||
{
|
||||
if (this->m_stunCaster || branch.target == context->originator)
|
||||
{
|
||||
auto* self = EntityManager::Instance()->GetEntity(context->originator);
|
||||
|
||||
if (self == nullptr)
|
||||
{
|
||||
Game::logger->Log("StunBehavior", "Invalid self entity (%llu)!\n", context->originator);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* See if we can stun ourselves
|
||||
*/
|
||||
|
||||
auto* combatAiComponent = static_cast<BaseCombatAIComponent*>(self->GetComponent(COMPONENT_TYPE_BASE_COMBAT_AI));
|
||||
|
||||
if (combatAiComponent == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
combatAiComponent->Stun(branch.duration);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
bool blocked = false;
|
||||
|
||||
auto* target = EntityManager::Instance()->GetEntity(branch.target);
|
||||
|
||||
if (target != nullptr)
|
||||
{
|
||||
auto* destroyableComponent = target->GetComponent<DestroyableComponent>();
|
||||
|
||||
if (destroyableComponent != nullptr)
|
||||
{
|
||||
blocked = destroyableComponent->IsKnockbackImmune();
|
||||
}
|
||||
}
|
||||
|
||||
bitStream->Write(blocked);
|
||||
|
||||
if (target == nullptr)
|
||||
{
|
||||
Game::logger->Log("StunBehavior", "Failed to find target (%llu)!\n", branch.target);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* If our target is an enemy we can go ahead and stun it.
|
||||
*/
|
||||
|
||||
auto* combatAiComponent = static_cast<BaseCombatAIComponent*>(target->GetComponent(COMPONENT_TYPE_BASE_COMBAT_AI));
|
||||
|
||||
if (combatAiComponent == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
combatAiComponent->Stun(branch.duration);
|
||||
}
|
||||
|
||||
void StunBehavior::Load()
|
||||
{
|
||||
this->m_stunCaster = GetBoolean("stun_caster");
|
||||
}
|
21
dGame/dBehaviors/StunBehavior.h
Normal file
21
dGame/dBehaviors/StunBehavior.h
Normal file
@@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
#include "Behavior.h"
|
||||
|
||||
class StunBehavior final : public Behavior
|
||||
{
|
||||
public:
|
||||
bool m_stunCaster;
|
||||
|
||||
/*
|
||||
* Inherited
|
||||
*/
|
||||
explicit StunBehavior(const uint32_t behavior_id) : Behavior(behavior_id)
|
||||
{
|
||||
}
|
||||
|
||||
void Handle(BehaviorContext* context, RakNet::BitStream* bit_stream, BehaviorBranchContext branch) override;
|
||||
|
||||
void Calculate(BehaviorContext* context, RakNet::BitStream* bit_stream, BehaviorBranchContext branch) override;
|
||||
|
||||
void Load() override;
|
||||
};
|
88
dGame/dBehaviors/SwitchBehavior.cpp
Normal file
88
dGame/dBehaviors/SwitchBehavior.cpp
Normal file
@@ -0,0 +1,88 @@
|
||||
#include "SwitchBehavior.h"
|
||||
#include "BehaviorBranchContext.h"
|
||||
#include "EntityManager.h"
|
||||
#include "dLogger.h"
|
||||
#include "DestroyableComponent.h"
|
||||
#include "BehaviorContext.h"
|
||||
#include "BuffComponent.h"
|
||||
|
||||
void SwitchBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, const BehaviorBranchContext branch)
|
||||
{
|
||||
auto state = true;
|
||||
|
||||
if (this->m_imagination > 0 || !this->m_isEnemyFaction)
|
||||
{
|
||||
bitStream->Read(state);
|
||||
}
|
||||
|
||||
auto* entity = EntityManager::Instance()->GetEntity(context->originator);
|
||||
|
||||
if (entity == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto* destroyableComponent = entity->GetComponent<DestroyableComponent>();
|
||||
|
||||
if (destroyableComponent == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Game::logger->Log("SwitchBehavior", "[%i] State: (%d), imagination: (%i) / (%f)\n", entity->GetLOT(), state, destroyableComponent->GetImagination(), destroyableComponent->GetMaxImagination());
|
||||
|
||||
if (state || (entity->GetLOT() == 8092 && destroyableComponent->GetImagination() >= m_imagination))
|
||||
{
|
||||
this->m_actionTrue->Handle(context, bitStream, branch);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->m_actionFalse->Handle(context, bitStream, branch);
|
||||
}
|
||||
}
|
||||
|
||||
void SwitchBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch)
|
||||
{
|
||||
auto state = true;
|
||||
|
||||
if (this->m_imagination > 0 || !this->m_isEnemyFaction)
|
||||
{
|
||||
auto* entity = EntityManager::Instance()->GetEntity(branch.target);
|
||||
|
||||
state = entity != nullptr;
|
||||
|
||||
if (state && m_targetHasBuff != 0)
|
||||
{
|
||||
auto* buffComponent = entity->GetComponent<BuffComponent>();
|
||||
|
||||
if (buffComponent != nullptr && !buffComponent->HasBuff(m_targetHasBuff))
|
||||
{
|
||||
state = false;
|
||||
}
|
||||
}
|
||||
|
||||
bitStream->Write(state);
|
||||
}
|
||||
|
||||
if (state)
|
||||
{
|
||||
this->m_actionTrue->Calculate(context, bitStream, branch);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->m_actionFalse->Calculate(context, bitStream, branch);
|
||||
}
|
||||
}
|
||||
|
||||
void SwitchBehavior::Load()
|
||||
{
|
||||
this->m_actionTrue = GetAction("action_true");
|
||||
|
||||
this->m_actionFalse = GetAction("action_false");
|
||||
|
||||
this->m_imagination = GetInt("imagination");
|
||||
|
||||
this->m_isEnemyFaction = GetBoolean("isEnemyFaction");
|
||||
|
||||
this->m_targetHasBuff = GetInt("target_has_buff");
|
||||
}
|
30
dGame/dBehaviors/SwitchBehavior.h
Normal file
30
dGame/dBehaviors/SwitchBehavior.h
Normal file
@@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
#include "Behavior.h"
|
||||
|
||||
class SwitchBehavior final : public Behavior
|
||||
{
|
||||
public:
|
||||
Behavior* m_actionTrue;
|
||||
|
||||
Behavior* m_actionFalse;
|
||||
|
||||
uint32_t m_imagination;
|
||||
|
||||
bool m_isEnemyFaction;
|
||||
|
||||
int32_t m_targetHasBuff;
|
||||
|
||||
/*
|
||||
* Inherited
|
||||
*/
|
||||
|
||||
explicit SwitchBehavior(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;
|
||||
};
|
63
dGame/dBehaviors/SwitchMultipleBehavior.cpp
Normal file
63
dGame/dBehaviors/SwitchMultipleBehavior.cpp
Normal file
@@ -0,0 +1,63 @@
|
||||
#include "SwitchMultipleBehavior.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include "BehaviorBranchContext.h"
|
||||
#include "CDActivitiesTable.h"
|
||||
#include "Game.h"
|
||||
#include "dLogger.h"
|
||||
#include "EntityManager.h"
|
||||
|
||||
|
||||
void SwitchMultipleBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bit_stream, BehaviorBranchContext branch)
|
||||
{
|
||||
float value;
|
||||
|
||||
bit_stream->Read(value);
|
||||
|
||||
uint32_t trigger = 0;
|
||||
|
||||
for (unsigned int i = 0; i < this->m_behaviors.size(); i++) {
|
||||
|
||||
const double data = this->m_behaviors.at(i).first;
|
||||
|
||||
if (value <= data) {
|
||||
|
||||
trigger = i;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
auto* behavior = this->m_behaviors.at(trigger).second;
|
||||
|
||||
behavior->Handle(context, bit_stream, branch);
|
||||
}
|
||||
|
||||
void SwitchMultipleBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bit_stream, BehaviorBranchContext branch)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
void SwitchMultipleBehavior::Load()
|
||||
{
|
||||
const auto b = std::to_string(this->m_behaviorId);
|
||||
std::stringstream query;
|
||||
query << "SELECT replace(bP1.parameterID, 'behavior ', '') as key, bP1.value as behavior, "
|
||||
<< "(select bP2.value FROM BehaviorParameter bP2 WHERE bP2.behaviorID = " << b << " AND bP2.parameterID LIKE 'value %' "
|
||||
<< "AND replace(bP1.parameterID, 'behavior ', '') = replace(bP2.parameterID, 'value ', '')) as value "
|
||||
<< "FROM BehaviorParameter bP1 WHERE bP1.behaviorID = " << b << " AND bP1.parameterID LIKE 'behavior %'";
|
||||
auto result = CDClientDatabase::ExecuteQuery(query.str());
|
||||
|
||||
while (!result.eof()) {
|
||||
const auto behavior_id = static_cast<uint32_t>(result.getFloatField(1));
|
||||
|
||||
auto* behavior = CreateBehavior(behavior_id);
|
||||
|
||||
auto value = result.getFloatField(2);
|
||||
|
||||
this->m_behaviors.emplace_back(value, behavior);
|
||||
|
||||
result.nextRow();
|
||||
}
|
||||
}
|
24
dGame/dBehaviors/SwitchMultipleBehavior.h
Normal file
24
dGame/dBehaviors/SwitchMultipleBehavior.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
#include "Behavior.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
class SwitchMultipleBehavior final : public Behavior
|
||||
{
|
||||
public:
|
||||
std::vector<std::pair<float, Behavior*>> m_behaviors;
|
||||
|
||||
/*
|
||||
* Inherited
|
||||
*/
|
||||
|
||||
explicit SwitchMultipleBehavior(const uint32_t behavior_id) : Behavior(behavior_id)
|
||||
{
|
||||
}
|
||||
|
||||
void Handle(BehaviorContext* context, RakNet::BitStream* bit_stream, BehaviorBranchContext branch) override;
|
||||
|
||||
void Calculate(BehaviorContext* context, RakNet::BitStream* bit_stream, BehaviorBranchContext branch) override;
|
||||
|
||||
void Load() override;
|
||||
};
|
288
dGame/dBehaviors/TacArcBehavior.cpp
Normal file
288
dGame/dBehaviors/TacArcBehavior.cpp
Normal file
@@ -0,0 +1,288 @@
|
||||
#include "TacArcBehavior.h"
|
||||
#include "BehaviorBranchContext.h"
|
||||
#include "Game.h"
|
||||
#include "dLogger.h"
|
||||
#include "Entity.h"
|
||||
#include "BehaviorContext.h"
|
||||
#include "BaseCombatAIComponent.h"
|
||||
#include "EntityManager.h"
|
||||
#include "RebuildComponent.h"
|
||||
#include "DestroyableComponent.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
void TacArcBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch)
|
||||
{
|
||||
if (this->m_targetEnemy && this->m_usePickedTarget && branch.target > 0)
|
||||
{
|
||||
this->m_action->Handle(context, bitStream, branch);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
bool hit = false;
|
||||
|
||||
bitStream->Read(hit);
|
||||
|
||||
if (this->m_checkEnv)
|
||||
{
|
||||
bool blocked = false;
|
||||
|
||||
bitStream->Read(blocked);
|
||||
|
||||
if (blocked)
|
||||
{
|
||||
this->m_blockedAction->Handle(context, bitStream, branch);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (hit)
|
||||
{
|
||||
uint32_t count = 0;
|
||||
|
||||
bitStream->Read(count);
|
||||
|
||||
if (count > m_maxTargets && m_maxTargets > 0)
|
||||
{
|
||||
count = m_maxTargets;
|
||||
}
|
||||
|
||||
std::vector<LWOOBJID> targets;
|
||||
|
||||
for (auto i = 0u; i < count; ++i)
|
||||
{
|
||||
LWOOBJID id;
|
||||
|
||||
bitStream->Read(id);
|
||||
|
||||
targets.push_back(id);
|
||||
}
|
||||
|
||||
for (auto target : targets)
|
||||
{
|
||||
branch.target = target;
|
||||
|
||||
this->m_action->Handle(context, bitStream, branch);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this->m_missAction->Handle(context, bitStream, branch);
|
||||
}
|
||||
}
|
||||
|
||||
void TacArcBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch)
|
||||
{
|
||||
auto* self = EntityManager::Instance()->GetEntity(context->originator);
|
||||
if (self == nullptr) {
|
||||
Game::logger->Log("TacArcBehavior", "Invalid self for (%llu)!\n", context->originator);
|
||||
return;
|
||||
}
|
||||
|
||||
const auto* destroyableComponent = self->GetComponent<DestroyableComponent>();
|
||||
|
||||
if ((this->m_usePickedTarget || context->clientInitalized) && branch.target > 0) {
|
||||
const auto* target = EntityManager::Instance()->GetEntity(branch.target);
|
||||
|
||||
if (target == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// If the game is specific about who to target, check that
|
||||
if (destroyableComponent == nullptr || ((!m_targetFriend && !m_targetEnemy
|
||||
|| m_targetFriend && destroyableComponent->IsFriend(target)
|
||||
|| m_targetEnemy && destroyableComponent->IsEnemy(target)))) {
|
||||
this->m_action->Calculate(context, bitStream, branch);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
auto* combatAi = self->GetComponent<BaseCombatAIComponent>();
|
||||
|
||||
const auto casterPosition = self->GetPosition();
|
||||
|
||||
auto reference = self->GetPosition(); //+ m_offset;
|
||||
|
||||
std::vector<Entity*> targets;
|
||||
|
||||
std::vector<LWOOBJID> validTargets;
|
||||
|
||||
if (combatAi != nullptr)
|
||||
{
|
||||
if (combatAi->GetTarget() != LWOOBJID_EMPTY)
|
||||
{
|
||||
validTargets.push_back(combatAi->GetTarget());
|
||||
}
|
||||
}
|
||||
|
||||
// Find all valid targets, based on whether we target enemies or friends
|
||||
for (const auto& contextTarget : context->GetValidTargets()) {
|
||||
if (destroyableComponent != nullptr) {
|
||||
const auto* targetEntity = EntityManager::Instance()->GetEntity(contextTarget);
|
||||
|
||||
if (m_targetEnemy && destroyableComponent->IsEnemy(targetEntity)
|
||||
|| m_targetFriend && destroyableComponent->IsFriend(targetEntity)) {
|
||||
validTargets.push_back(contextTarget);
|
||||
}
|
||||
} else {
|
||||
validTargets.push_back(contextTarget);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto validTarget : validTargets)
|
||||
{
|
||||
if (targets.size() >= this->m_maxTargets)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
auto* entity = EntityManager::Instance()->GetEntity(validTarget);
|
||||
|
||||
if (entity == nullptr)
|
||||
{
|
||||
Game::logger->Log("TacArcBehavior", "Invalid target (%llu) for (%llu)!\n", validTarget, context->originator);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (std::find(targets.begin(), targets.end(), entity) != targets.end())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (entity->GetIsDead()) continue;
|
||||
|
||||
const auto otherPosition = entity->GetPosition();
|
||||
|
||||
const auto heightDifference = std::abs(otherPosition.y - casterPosition.y);
|
||||
|
||||
/*if (otherPosition.y > reference.y && heightDifference > this->m_upperBound || otherPosition.y < reference.y && heightDifference > this->m_lowerBound)
|
||||
{
|
||||
continue;
|
||||
}*/
|
||||
|
||||
const auto forward = self->GetRotation().GetForwardVector();
|
||||
|
||||
// forward is a normalized vector of where the caster is facing.
|
||||
// otherPosition is the position of the target.
|
||||
// reference is the position of the caster.
|
||||
// If we cast a ray forward from the caster, does it come within m_farWidth of the target?
|
||||
|
||||
const auto distance = Vector3::Distance(reference, otherPosition);
|
||||
|
||||
if (m_method == 2)
|
||||
{
|
||||
NiPoint3 rayPoint = casterPosition + forward * distance;
|
||||
|
||||
if (m_farWidth > 0 && Vector3::DistanceSquared(rayPoint, otherPosition) > this->m_farWidth * this->m_farWidth)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
auto normalized = (reference - otherPosition) / distance;
|
||||
|
||||
const float degreeAngle = std::abs(Vector3::Angle(forward, normalized) * (180 / 3.14) - 180);
|
||||
|
||||
if (distance >= this->m_minDistance && this->m_maxDistance >= distance && degreeAngle <= 2 * this->m_angle)
|
||||
{
|
||||
targets.push_back(entity);
|
||||
}
|
||||
}
|
||||
|
||||
std::sort(targets.begin(), targets.end(), [reference](Entity* a, Entity* b)
|
||||
{
|
||||
const auto aDistance = Vector3::DistanceSquared(reference, a->GetPosition());
|
||||
const auto bDistance = Vector3::DistanceSquared(reference, b->GetPosition());
|
||||
|
||||
return aDistance > bDistance;
|
||||
});
|
||||
|
||||
const auto hit = !targets.empty();
|
||||
|
||||
bitStream->Write(hit);
|
||||
|
||||
if (this->m_checkEnv)
|
||||
{
|
||||
const auto blocked = false; // TODO
|
||||
|
||||
bitStream->Write(blocked);
|
||||
}
|
||||
|
||||
if (hit)
|
||||
{
|
||||
if (combatAi != nullptr)
|
||||
{
|
||||
combatAi->LookAt(targets[0]->GetPosition());
|
||||
}
|
||||
|
||||
context->foundTarget = true; // We want to continue with this behavior
|
||||
|
||||
const auto count = static_cast<uint32_t>(targets.size());
|
||||
|
||||
bitStream->Write(count);
|
||||
|
||||
for (auto* target : targets)
|
||||
{
|
||||
bitStream->Write(target->GetObjectID());
|
||||
}
|
||||
|
||||
for (auto* target : targets)
|
||||
{
|
||||
branch.target = target->GetObjectID();
|
||||
|
||||
this->m_action->Calculate(context, bitStream, branch);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this->m_missAction->Calculate(context, bitStream, branch);
|
||||
}
|
||||
}
|
||||
|
||||
void TacArcBehavior::Load()
|
||||
{
|
||||
this->m_usePickedTarget = GetBoolean("use_picked_target");
|
||||
|
||||
this->m_action = GetAction("action");
|
||||
|
||||
this->m_missAction = GetAction("miss action");
|
||||
|
||||
this->m_checkEnv = GetBoolean("check_env");
|
||||
|
||||
this->m_blockedAction = GetAction("blocked action");
|
||||
|
||||
this->m_minDistance = GetFloat("min range");
|
||||
|
||||
this->m_maxDistance = GetFloat("max range");
|
||||
|
||||
this->m_maxTargets = GetInt("max targets");
|
||||
|
||||
this->m_targetEnemy = GetBoolean("target_enemy");
|
||||
|
||||
this->m_targetFriend = GetBoolean("target_friend");
|
||||
|
||||
this->m_targetTeam = GetBoolean("target_team");
|
||||
|
||||
this->m_angle = GetFloat("angle");
|
||||
|
||||
this->m_upperBound = GetFloat("upper_bound");
|
||||
|
||||
this->m_lowerBound = GetFloat("lower_bound");
|
||||
|
||||
this->m_farHeight = GetFloat("far_height");
|
||||
|
||||
this->m_farWidth = GetFloat("far_width");
|
||||
|
||||
this->m_method = GetInt("method");
|
||||
|
||||
this->m_offset = {
|
||||
GetFloat("offset_x"),
|
||||
GetFloat("offset_y"),
|
||||
GetFloat("offset_z")
|
||||
};
|
||||
}
|
58
dGame/dBehaviors/TacArcBehavior.h
Normal file
58
dGame/dBehaviors/TacArcBehavior.h
Normal file
@@ -0,0 +1,58 @@
|
||||
#pragma once
|
||||
#include "Behavior.h"
|
||||
#include "dCommonVars.h"
|
||||
#include "NiPoint3.h"
|
||||
|
||||
class TacArcBehavior final : public Behavior
|
||||
{
|
||||
public:
|
||||
bool m_usePickedTarget;
|
||||
|
||||
Behavior* m_action;
|
||||
|
||||
bool m_checkEnv;
|
||||
|
||||
Behavior* m_missAction;
|
||||
|
||||
Behavior* m_blockedAction;
|
||||
|
||||
float m_minDistance;
|
||||
|
||||
float m_maxDistance;
|
||||
|
||||
uint32_t m_maxTargets;
|
||||
|
||||
bool m_targetEnemy;
|
||||
|
||||
bool m_targetFriend;
|
||||
|
||||
bool m_targetTeam;
|
||||
|
||||
float m_angle;
|
||||
|
||||
float m_upperBound;
|
||||
|
||||
float m_lowerBound;
|
||||
|
||||
float m_farHeight;
|
||||
|
||||
float m_farWidth;
|
||||
|
||||
uint32_t m_method;
|
||||
|
||||
NiPoint3 m_offset;
|
||||
|
||||
/*
|
||||
* Inherited
|
||||
*/
|
||||
|
||||
explicit TacArcBehavior(const uint32_t behavior_id) : Behavior(behavior_id)
|
||||
{
|
||||
}
|
||||
|
||||
void Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) override;
|
||||
|
||||
void Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) override;
|
||||
|
||||
void Load() override;
|
||||
};
|
29
dGame/dBehaviors/TargetCasterBehavior.cpp
Normal file
29
dGame/dBehaviors/TargetCasterBehavior.cpp
Normal file
@@ -0,0 +1,29 @@
|
||||
#include "TargetCasterBehavior.h"
|
||||
#include "BehaviorBranchContext.h"
|
||||
#include "BehaviorContext.h"
|
||||
|
||||
|
||||
void TargetCasterBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bit_stream, BehaviorBranchContext branch)
|
||||
{
|
||||
branch.target = context->caster;
|
||||
|
||||
this->m_action->Handle(context, bit_stream, branch);
|
||||
}
|
||||
|
||||
void TargetCasterBehavior::UnCast(BehaviorContext* context, BehaviorBranchContext branch)
|
||||
{
|
||||
this->m_action->UnCast(context, branch);
|
||||
}
|
||||
|
||||
void TargetCasterBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bit_stream, BehaviorBranchContext branch)
|
||||
{
|
||||
branch.target = context->caster;
|
||||
|
||||
this->m_action->Calculate(context, bit_stream, branch);
|
||||
}
|
||||
|
||||
void TargetCasterBehavior::Load()
|
||||
{
|
||||
this->m_action = GetAction("action");
|
||||
}
|
||||
|
24
dGame/dBehaviors/TargetCasterBehavior.h
Normal file
24
dGame/dBehaviors/TargetCasterBehavior.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
#include "Behavior.h"
|
||||
|
||||
class TargetCasterBehavior final : public Behavior
|
||||
{
|
||||
public:
|
||||
Behavior* m_action;
|
||||
|
||||
/*
|
||||
* Inherited
|
||||
*/
|
||||
|
||||
explicit TargetCasterBehavior(const uint32_t behavior_id) : Behavior(behavior_id)
|
||||
{
|
||||
}
|
||||
|
||||
void Handle(BehaviorContext* context, RakNet::BitStream* bit_stream, BehaviorBranchContext branch) override;
|
||||
|
||||
void UnCast(BehaviorContext* context, BehaviorBranchContext branch) override;
|
||||
|
||||
void Calculate(BehaviorContext* context, RakNet::BitStream* bit_stream, BehaviorBranchContext branch) override;
|
||||
|
||||
void Load() override;
|
||||
};
|
51
dGame/dBehaviors/TauntBehavior.cpp
Normal file
51
dGame/dBehaviors/TauntBehavior.cpp
Normal file
@@ -0,0 +1,51 @@
|
||||
#include "TauntBehavior.h"
|
||||
#include "BehaviorBranchContext.h"
|
||||
#include "BehaviorContext.h"
|
||||
#include "BaseCombatAIComponent.h"
|
||||
#include "EntityManager.h"
|
||||
#include "dLogger.h"
|
||||
|
||||
|
||||
void TauntBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch)
|
||||
{
|
||||
auto* target = EntityManager::Instance()->GetEntity(branch.target);
|
||||
|
||||
if (target == nullptr)
|
||||
{
|
||||
Game::logger->Log("TauntBehavior", "Failed to find target (%llu)!\n", branch.target);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
auto* combatComponent = target->GetComponent<BaseCombatAIComponent>();
|
||||
|
||||
if (combatComponent != nullptr)
|
||||
{
|
||||
combatComponent->Taunt(context->originator, m_threatToAdd);
|
||||
}
|
||||
}
|
||||
|
||||
void TauntBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch)
|
||||
{
|
||||
auto* target = EntityManager::Instance()->GetEntity(branch.target);
|
||||
|
||||
if (target == nullptr)
|
||||
{
|
||||
Game::logger->Log("TauntBehavior", "Failed to find target (%llu)!\n", branch.target);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
auto* combatComponent = target->GetComponent<BaseCombatAIComponent>();
|
||||
|
||||
if (combatComponent != nullptr)
|
||||
{
|
||||
combatComponent->Taunt(context->originator, m_threatToAdd);
|
||||
}
|
||||
}
|
||||
|
||||
void TauntBehavior::Load()
|
||||
{
|
||||
this->m_threatToAdd = GetFloat("threat to add");
|
||||
}
|
||||
|
23
dGame/dBehaviors/TauntBehavior.h
Normal file
23
dGame/dBehaviors/TauntBehavior.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include "Behavior.h"
|
||||
|
||||
class TauntBehavior final : public Behavior
|
||||
{
|
||||
public:
|
||||
float m_threatToAdd;
|
||||
|
||||
/*
|
||||
* Inherited
|
||||
*/
|
||||
|
||||
explicit TauntBehavior(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;
|
||||
};
|
72
dGame/dBehaviors/VerifyBehavior.cpp
Normal file
72
dGame/dBehaviors/VerifyBehavior.cpp
Normal file
@@ -0,0 +1,72 @@
|
||||
#include "VerifyBehavior.h"
|
||||
#include "BehaviorBranchContext.h"
|
||||
#include "EntityManager.h"
|
||||
#include "NiPoint3.h"
|
||||
#include "BehaviorContext.h"
|
||||
#include "Game.h"
|
||||
#include "dLogger.h"
|
||||
|
||||
|
||||
void VerifyBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch)
|
||||
{
|
||||
auto* entity = EntityManager::Instance()->GetEntity(branch.target);
|
||||
|
||||
auto success = true;
|
||||
|
||||
if (entity == nullptr)
|
||||
{
|
||||
success = false;
|
||||
}
|
||||
else if (this->m_rangeCheck)
|
||||
{
|
||||
auto* self = EntityManager::Instance()->GetEntity(context->originator);
|
||||
|
||||
if (self == nullptr)
|
||||
{
|
||||
Game::logger->Log("VerifyBehavior", "Invalid self for (%llu)", context->originator);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const auto distance = Vector3::DistanceSquared(self->GetPosition(), entity->GetPosition());
|
||||
|
||||
if (distance > this->m_range * this->m_range)
|
||||
{
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
else if (this->m_blockCheck)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
if (branch.target != LWOOBJID_EMPTY && branch.target != context->originator)
|
||||
{
|
||||
bitStream->Write(success);
|
||||
|
||||
if (success)
|
||||
{
|
||||
bitStream->Write<uint32_t>(1);
|
||||
bitStream->Write0();
|
||||
bitStream->Write0();
|
||||
}
|
||||
}
|
||||
|
||||
if (!success)
|
||||
{
|
||||
branch.target = LWOOBJID_EMPTY;
|
||||
}
|
||||
|
||||
m_action->Calculate(context, bitStream, branch);
|
||||
}
|
||||
|
||||
void VerifyBehavior::Load()
|
||||
{
|
||||
this->m_rangeCheck = GetBoolean("check_range");
|
||||
|
||||
this->m_blockCheck = GetBoolean("check blocking");
|
||||
|
||||
this->m_action = GetAction("action");
|
||||
|
||||
this->m_range = GetFloat("range");
|
||||
}
|
26
dGame/dBehaviors/VerifyBehavior.h
Normal file
26
dGame/dBehaviors/VerifyBehavior.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
#include "Behavior.h"
|
||||
|
||||
class VerifyBehavior final : public Behavior
|
||||
{
|
||||
public:
|
||||
bool m_rangeCheck;
|
||||
|
||||
bool m_blockCheck;
|
||||
|
||||
float m_range;
|
||||
|
||||
Behavior* m_action;
|
||||
|
||||
/*
|
||||
* Inherited
|
||||
*/
|
||||
|
||||
explicit VerifyBehavior(const uint32_t behaviorId) : Behavior(behaviorId)
|
||||
{
|
||||
}
|
||||
|
||||
void Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) override;
|
||||
|
||||
void Load() override;
|
||||
};
|
Reference in New Issue
Block a user