Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: re-write AOE, add FilterTargets, Update TacArc Reading #1035

Merged
merged 24 commits into from
Oct 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
fdeb2e6
Re-write AOE behavior for new filter targets
aronwk-aaron Mar 30, 2023
8a64d2b
Get all entities by detroyable
aronwk-aaron Mar 30, 2023
892d5d3
Re-work filter targets to be 100% live accurate
aronwk-aaron Mar 31, 2023
d6bf2e0
remove debuging longs and remove oopsie
aronwk-aaron Apr 1, 2023
4988015
address feedback
aronwk-aaron Apr 1, 2023
68abb74
make log more useful
aronwk-aaron Apr 1, 2023
83d05f1
make filter more flat
aronwk-aaron Apr 3, 2023
d331702
Merge branch 'main' into make-filterTarget-better
aronwk-aaron Apr 5, 2023
33bbb48
Add some more checks to filter targets
aronwk-aaron Apr 7, 2023
644e169
Merge branch 'main' into make-filterTarget-better
aronwk-aaron May 13, 2023
9a401cc
fix typing
aronwk-aaron May 13, 2023
35a1747
Add filter target to TacArc and update filter target
aronwk-aaron May 14, 2023
98787c8
fix double declaration
aronwk-aaron May 14, 2023
910c18e
Some debugging logs
aronwk-aaron May 14, 2023
319b406
Update TacArc reading
aronwk-aaron May 15, 2023
3fdcd8f
make log clearer
aronwk-aaron May 15, 2023
269ce14
logs
EmosewaMC May 16, 2023
5917404
Update TacArcBehavior.cpp
EmosewaMC May 16, 2023
e0327c6
banana
EmosewaMC May 16, 2023
2053676
Merge branch 'main' into make-filterTarget-better
aronwk-aaron Aug 23, 2023
4f16f1e
fix max targets
aronwk-aaron Aug 23, 2023
678eece
remove extreanous parenthesesuuesdsds
aronwk-aaron Aug 23, 2023
8273ac5
make behavior slot use a real type
aronwk-aaron Oct 9, 2023
b93bb75
Merge branch 'main' into make-filterTarget-better
aronwk-aaron Oct 9, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions dGame/EntityManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,16 @@ std::vector<Entity*> EntityManager::GetEntitiesByLOT(const LOT& lot) const {
return entities;
}

std::vector<Entity*> EntityManager::GetEntitiesByProximity(NiPoint3 reference, float radius) const{
std::vector<Entity*> entities = {};
if (radius > 1000.0f) return entities;
for (const auto& entity : m_Entities) {
if (NiPoint3::Distance(reference, entity.second->GetPosition()) <= radius) entities.push_back(entity.second);
}
return entities;
}


Entity* EntityManager::GetZoneControlEntity() const {
return m_ZoneControlEntity;
}
Expand Down
1 change: 1 addition & 0 deletions dGame/EntityManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class EntityManager {
std::vector<Entity*> GetEntitiesInGroup(const std::string& group);
std::vector<Entity*> GetEntitiesByComponent(eReplicaComponentType componentType) const;
std::vector<Entity*> GetEntitiesByLOT(const LOT& lot) const;
std::vector<Entity*> GetEntitiesByProximity(NiPoint3 reference, float radius) const;
Entity* GetZoneControlEntity() const;

// Get spawn point entity by spawn name
Expand Down
166 changes: 73 additions & 93 deletions dGame/dBehaviors/AreaOfEffectBehavior.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,134 +20,114 @@ void AreaOfEffectBehavior::Handle(BehaviorContext* context, RakNet::BitStream* b
return;
}

if (this->m_useTargetPosition && branch.target == LWOOBJID_EMPTY) return;

if (targetCount == 0){
PlayFx(u"miss", context->originator);
aronwk-aaron marked this conversation as resolved.
Show resolved Hide resolved
return;
}

if (targetCount > this->m_maxTargets) {
Game::logger->Log("AreaOfEffectBehavior", "Serialized size is greater than max targets! Size: %i, Max: %i", targetCount, this->m_maxTargets);
return;
}

std::vector<LWOOBJID> targets;
auto caster = context->caster;
if (this->m_useTargetAsCaster) context->caster = branch.target;

std::vector<LWOOBJID> targets;
targets.reserve(targetCount);

for (auto i = 0u; i < targetCount; ++i) {
LWOOBJID target{};

if (!bitStream->Read(target)) {
Game::logger->Log("AreaOfEffectBehavior", "failed to read in target %i from bitStream, aborting target Handle!", i);
return;
};

targets.push_back(target);
}

for (auto target : targets) {
branch.target = target;

this->m_action->Handle(context, bitStream, branch);
}
context->caster = caster;
PlayFx(u"cast", context->originator);
}

void AreaOfEffectBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
auto* self = Game::entityManager->GetEntity(context->caster);
if (self == nullptr) {
Game::logger->Log("AreaOfEffectBehavior", "Invalid self for (%llu)!", context->originator);

return;
auto* caster = Game::entityManager->GetEntity(context->caster);
if (!caster) return;

// determine the position we are casting the AOE from
auto reference = branch.isProjectile ? branch.referencePosition : caster->GetPosition();
if (this->m_useTargetPosition) {
if (branch.target == LWOOBJID_EMPTY) return;
auto branchTarget = Game::entityManager->GetEntity(branch.target);
if (branchTarget) reference = branchTarget->GetPosition();
}

auto reference = branch.isProjectile ? branch.referencePosition : self->GetPosition();

std::vector<Entity*> targets;
reference += this->m_offset;

auto* presetTarget = Game::entityManager->GetEntity(branch.target);
std::vector<Entity*> targets {};
targets = Game::entityManager->GetEntitiesByProximity(reference, this->m_radius);
context->FilterTargets(targets, this->m_ignoreFactionList, this->m_includeFactionList, this->m_targetSelf, this->m_targetEnemy, this->m_targetFriend, this->m_targetTeam);

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;
}

// Gets all of the valid targets, passing in if should target enemies and friends
for (auto validTarget : context->GetValidTargets(m_ignoreFaction, includeFaction, m_TargetSelf == 1, m_targetEnemy == 1, m_targetFriend == 1)) {
auto* entity = Game::entityManager->GetEntity(validTarget);

if (entity == nullptr) {
Game::logger->Log("AreaOfEffectBehavior", "Invalid target (%llu) for (%llu)!", validTarget, context->originator);

continue;
}

if (std::find(targets.begin(), targets.end(), entity) != targets.end()) {
continue;
// sort by distance
std::sort(targets.begin(), targets.end(), [reference](Entity* a, Entity* b) {
const auto aDistance = NiPoint3::Distance(a->GetPosition(), reference);
const auto bDistance = NiPoint3::Distance(b->GetPosition(), reference);
return aDistance < bDistance;
}
);

auto* destroyableComponent = entity->GetComponent<DestroyableComponent>();
// resize if we have more than max targets allows
if (targets.size() > this->m_maxTargets) targets.resize(this->m_maxTargets);

if (destroyableComponent == nullptr) {
continue;
}
bitStream->Write<uint32_t>(targets.size());

if (destroyableComponent->HasFaction(m_ignoreFaction)) {
continue;
if (targets.size() == 0) {
PlayFx(u"miss", context->originator);
return;
} else {
context->foundTarget = true;
// write all the targets to the bitstream
for (auto* target : targets) {
bitStream->Write(target->GetObjectID());
}

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);
// then cast all the actions
for (auto* target : targets) {
branch.target = target->GetObjectID();
this->m_action->Calculate(context, bitStream, branch);
}
}

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);
PlayFx(u"cast", context->originator);
}
}

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");

this->m_TargetSelf = GetInt("target_self");

this->m_targetEnemy = GetInt("target_enemy");

this->m_targetFriend = GetInt("target_friend");
this->m_action = GetAction("action"); // required
this->m_radius = GetFloat("radius", 0.0f); // required
this->m_maxTargets = GetInt("max targets", 100);
if (this->m_maxTargets == 0) this->m_maxTargets = 100;
this->m_useTargetPosition = GetBoolean("use_target_position", false);
this->m_useTargetAsCaster = GetBoolean("use_target_as_caster", false);
this->m_offset = NiPoint3(
GetFloat("offset_x", 0.0f),
GetFloat("offset_y", 0.0f),
GetFloat("offset_z", 0.0f)
);

// params after this are needed for filter targets
const auto parameters = GetParameterNames();
for (const auto& parameter : parameters) {
if (parameter.first.rfind("include_faction", 0) == 0) {
this->m_includeFactionList.push_front(parameter.second);
} else if (parameter.first.rfind("ignore_faction", 0) == 0) {
this->m_ignoreFactionList.push_front(parameter.second);
}
}
this->m_targetSelf = GetBoolean("target_self", false);
this->m_targetEnemy = GetBoolean("target_enemy", false);
this->m_targetFriend = GetBoolean("target_friend", false);
this->m_targetTeam = GetBoolean("target_team", false);
}
40 changes: 16 additions & 24 deletions dGame/dBehaviors/AreaOfEffectBehavior.h
Original file line number Diff line number Diff line change
@@ -1,34 +1,26 @@
#pragma once
#include "Behavior.h"
#include <forward_list>

class AreaOfEffectBehavior final : public Behavior
{
public:
Behavior* m_action;

uint32_t m_maxTargets;

float m_radius;

int32_t m_ignoreFaction;

int32_t m_includeFaction;

int32_t m_TargetSelf;

int32_t m_targetEnemy;

int32_t m_targetFriend;

/*
* Inherited
*/
explicit AreaOfEffectBehavior(const uint32_t behaviorId) : Behavior(behaviorId) {
}

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;
private:
Behavior* m_action;
uint32_t m_maxTargets;
float m_radius;
bool m_useTargetPosition;
aronwk-aaron marked this conversation as resolved.
Show resolved Hide resolved
bool m_useTargetAsCaster;
NiPoint3 m_offset;

std::forward_list<int32_t> m_ignoreFactionList {};
std::forward_list<int32_t> m_includeFactionList {};
bool m_targetSelf;
bool m_targetEnemy;
bool m_targetFriend;
bool m_targetTeam;
};
2 changes: 1 addition & 1 deletion dGame/dBehaviors/Behavior.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ Behavior* Behavior::CreateBehavior(const uint32_t behaviorId) {
case BehaviorTemplates::BEHAVIOR_SPEED:
behavior = new SpeedBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_DARK_INSPIRATION:
case BehaviorTemplates::BEHAVIOR_DARK_INSPIRATION:
behavior = new DarkInspirationBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_LOOT_BUFF:
Expand Down
Loading