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: TacArc #1037

Closed
wants to merge 36 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 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
2cd4e6e
tacarc re-write WIP
aronwk-aaron Mar 30, 2023
6775ec7
doenvcheck
aronwk-aaron Mar 30, 2023
cf2e9c6
change type
aronwk-aaron Mar 30, 2023
f2514f0
miss
aronwk-aaron Mar 30, 2023
95be52d
WIP
aronwk-aaron Mar 30, 2023
7e229d1
re-write tac arc handle
aronwk-aaron Mar 30, 2023
b3155ea
le wopps
aronwk-aaron Mar 31, 2023
c40e226
fix indent
aronwk-aaron Mar 31, 2023
892d5d3
Re-work filter targets to be 100% live accurate
aronwk-aaron Mar 31, 2023
1a43887
Merge branch 'make-filterTarget-better' into re-write-tacarc
aronwk-aaron Mar 31, 2023
5107369
Work on getentities in tacarc
aronwk-aaron Apr 1, 2023
d6bf2e0
remove debuging longs and remove oopsie
aronwk-aaron Apr 1, 2023
3f8e7f1
Merge branch 'make-filterTarget-better' into re-write-tacarc
aronwk-aaron Apr 1, 2023
4988015
address feedback
aronwk-aaron Apr 1, 2023
3baaeeb
Merge branch 'make-filterTarget-better' into re-write-tacarc
aronwk-aaron Apr 1, 2023
68abb74
make log more useful
aronwk-aaron Apr 1, 2023
1d5534b
Merge branch 'make-filterTarget-better' into re-write-tacarc
aronwk-aaron Apr 1, 2023
cba8ac3
updates
aronwk-aaron Apr 1, 2023
753b667
WIP
aronwk-aaron Apr 1, 2023
859c109
use dcommon pi
aronwk-aaron Apr 1, 2023
83d05f1
make filter more flat
aronwk-aaron Apr 3, 2023
6313728
whitespace
aronwk-aaron Apr 5, 2023
b098139
Merge branch 'make-filterTarget-better' into re-write-tacarc
aronwk-aaron Apr 5, 2023
8626ea4
Merge branch 'main' into re-write-tacarc
aronwk-aaron Apr 5, 2023
98ff0d2
correct tacarc handle
aronwk-aaron Apr 5, 2023
bf63bc9
remove write
aronwk-aaron Apr 5, 2023
d331702
Merge branch 'main' into make-filterTarget-better
aronwk-aaron Apr 5, 2023
ec4c76d
Merge branch 'make-filterTarget-better' into re-write-tacarc
aronwk-aaron Apr 5, 2023
6d55bcf
Fix reading tac arc in
aronwk-aaron Apr 7, 2023
33bbb48
Add some more checks to filter targets
aronwk-aaron Apr 7, 2023
7c93ec4
Merge branch 'make-filterTarget-better' into re-write-tacarc
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
3459f70
merge from upstream
aronwk-aaron May 13, 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
5 changes: 5 additions & 0 deletions dCommon/NiPoint3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,11 @@ NiPoint3 NiPoint3::operator*(float fScalar) const {
return NiPoint3(this->x * fScalar, this->y * fScalar, this->z * fScalar);
}

//! Operator for scalar multiplication of a vector
NiPoint3 NiPoint3::operator*=(float fScalar) const {
return NiPoint3(this->x * fScalar, this->y * fScalar, this->z * fScalar);
}

//! Operator for scalar division of a vector
NiPoint3 NiPoint3::operator/(float fScalar) const {
float retX = this->x != 0 ? this->x / fScalar : 0;
Expand Down
3 changes: 3 additions & 0 deletions dCommon/NiPoint3.h
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,9 @@ class NiPoint3 {
//! Operator for scalar division of a vector
NiPoint3 operator/(float fScalar) const;

//! Operator for scalar multiplication of a vector
NiPoint3 operator*=(float fScalar) const;


// MARK: Helper Functions

Expand Down
17 changes: 17 additions & 0 deletions dCommon/dEnums/eTacArcMethod.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#pragma once

#ifndef __ETACARCMETHOD__H__
#define __ETACARCMETHOD__H__

#include <cstdint>

enum class eTacArcMethod : uint32_t {
INVALID = 0,
CONE_AND_PIE_SLICE,
FRUSTUM
};

#endif //!__ETACARCMETHOD__H__



2 changes: 1 addition & 1 deletion dDatabase/Tables/CDDestructibleComponentTable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ CDDestructibleComponentTable::CDDestructibleComponentTable(void) {
entry.armor = tableData.getFloatField("armor", -1.0f);
entry.death_behavior = tableData.getIntField("death_behavior", -1);
entry.isnpc = tableData.getIntField("isnpc", -1) == 1 ? true : false;
entry.attack_priority = tableData.getIntField("attack_priority", -1);
entry.attack_priority = tableData.getIntField("attack_priority", 1);
entry.isSmashable = tableData.getIntField("isSmashable", -1) == 1 ? true : false;
entry.difficultyLevel = tableData.getIntField("difficultyLevel", -1);

Expand Down
2 changes: 1 addition & 1 deletion dDatabase/Tables/CDDestructibleComponentTable.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ struct CDDestructibleComponent {
float armor; //!< The amount of armor of the object
unsigned int death_behavior; //!< The behavior ID of the death behavior
bool isnpc; //!< Whether or not the object is an NPC
unsigned int attack_priority; //!< ???
unsigned int attack_priority; //!< The Priority of attack
bool isSmashable; //!< Whether or not the object is smashable
int difficultyLevel; //!< ???
};
Expand Down
7 changes: 4 additions & 3 deletions dGame/Entity.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -407,17 +407,18 @@ void Entity::Initialize() {
}

if (destCompData.size() > 0) {
comp->AddFaction(destCompData[0].faction);
std::stringstream ss(destCompData[0].factionList);
comp->AddFaction(destCompData.at(0).faction);
std::stringstream ss(destCompData.at(0).factionList);
std::string token;

while (std::getline(ss, token, ',')) {
if (std::stoi(token) == destCompData[0].faction) continue;
if (std::stoi(token) == destCompData.at(0).faction) continue;

if (token != "") {
comp->AddFaction(std::stoi(token));
}
}
comp->SetAttackPriority(destCompData.at(0).attack_priority);
}

m_Components.insert(std::make_pair(eReplicaComponentType::DESTROYABLE, comp));
Expand Down
35 changes: 35 additions & 0 deletions dGame/EntityManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
#include "eObjectBits.h"
#include "eGameMasterLevel.h"
#include "eReplicaComponentType.h"
#include "TacArcInfo.h"
#include "eTacArcMethod.h"
#include "eReplicaPacketType.h"

EntityManager* EntityManager::m_Address = nullptr;
Expand Down Expand Up @@ -303,6 +305,39 @@ 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;
}

void EntityManager::GetEntitiesInsideTacArc(TacArcInfo& tacArcInfo){
if (tacArcInfo.method == eTacArcMethod::CONE_AND_PIE_SLICE || tacArcInfo.method == eTacArcMethod::INVALID) {
GetEntitiesInsideConeAndPieSliceTacArc(tacArcInfo);
} else if (tacArcInfo.method == eTacArcMethod::FRUSTUM) {
GetEntitiesInsideFrustumTacArc(tacArcInfo);
}
return;
}

void EntityManager::GetEntitiesInsideConeAndPieSliceTacArc(TacArcInfo& tacArcInfo){
float max_range = tacArcInfo.maxRange;
if (tacArcInfo.bGetHeight){
auto heightAbsMax = std::max(abs(tacArcInfo.heightUpperBound),abs(tacArcInfo.heightLowerBound));
max_range = std::max(max_range, heightAbsMax);
}
// PeGameWorld::GetObjectsInArea replacement
tacArcInfo.targets = GetEntitiesByProximity(tacArcInfo.position, max_range);

}

void EntityManager::GetEntitiesInsideFrustumTacArc(TacArcInfo& tacArcInfo){

}

Entity* EntityManager::GetZoneControlEntity() const {
return m_ZoneControlEntity;
}
Expand Down
6 changes: 6 additions & 0 deletions dGame/EntityManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ class User;
enum class eReplicaComponentType : uint32_t;

struct SystemAddress;
struct TacArcInfo;

class EntityManager {
public:
Expand All @@ -38,6 +39,11 @@ 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;
void GetEntitiesInsideTacArc(TacArcInfo& tacArcInfo);
void GetEntitiesInsideConeAndPieSliceTacArc(TacArcInfo& tacArcInfo);
void GetEntitiesInsideFrustumTacArc(TacArcInfo& tacArcInfo);

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);
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 = EntityManager::Instance()->GetEntity(context->caster);
if (self == nullptr) {
Game::logger->Log("AreaOfEffectBehavior", "Invalid self for (%llu)!", context->originator);

return;
auto* caster = EntityManager::Instance()->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 = EntityManager::Instance()->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 = EntityManager::Instance()->GetEntity(branch.target);
std::vector<Entity*> targets {};
targets = EntityManager::Instance()->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 = EntityManager::Instance()->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);
}
Loading