Skip to content

Commit

Permalink
fix: implement enemy clear threat script (#1678)
Browse files Browse the repository at this point in the history
* brother

* use some better logic
  • Loading branch information
EmosewaMC authored Dec 16, 2024
1 parent 53242ad commit 0f8c5b4
Show file tree
Hide file tree
Showing 20 changed files with 197 additions and 64 deletions.
34 changes: 26 additions & 8 deletions dGame/Entity.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@
#include "CDSkillBehaviorTable.h"
#include "CDZoneTableTable.h"

#include <ranges>

Observable<Entity*, const PositionUpdate&> Entity::OnPlayerPositionUpdate;

Entity::Entity(const LWOOBJID& objectID, EntityInfo info, User* parentUser, Entity* parentEntity) {
Expand Down Expand Up @@ -286,8 +288,9 @@ void Entity::Initialize() {
AddComponent<PropertyEntranceComponent>(propertyEntranceComponentID);
}

if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::CONTROLLABLE_PHYSICS) > 0) {
auto* controllablePhysics = AddComponent<ControllablePhysicsComponent>();
const int32_t controllablePhysicsComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::CONTROLLABLE_PHYSICS);
if (controllablePhysicsComponentID > 0) {
auto* controllablePhysics = AddComponent<ControllablePhysicsComponent>(controllablePhysicsComponentID);

if (m_Character) {
controllablePhysics->LoadFromXml(m_Character->GetXMLDoc());
Expand Down Expand Up @@ -330,16 +333,19 @@ void Entity::Initialize() {
AddComponent<SimplePhysicsComponent>(simplePhysicsComponentID);
}

if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::RIGID_BODY_PHANTOM_PHYSICS) > 0) {
AddComponent<RigidbodyPhantomPhysicsComponent>();
const int32_t rigidBodyPhantomPhysicsComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::RIGID_BODY_PHANTOM_PHYSICS);
if (rigidBodyPhantomPhysicsComponentID > 0) {
AddComponent<RigidbodyPhantomPhysicsComponent>(rigidBodyPhantomPhysicsComponentID);
}

if (markedAsPhantom || compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::PHANTOM_PHYSICS) > 0) {
AddComponent<PhantomPhysicsComponent>()->SetPhysicsEffectActive(false);
const int32_t phantomPhysicsComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::PHANTOM_PHYSICS);
if (markedAsPhantom || phantomPhysicsComponentID > 0) {
AddComponent<PhantomPhysicsComponent>(phantomPhysicsComponentID)->SetPhysicsEffectActive(false);
}

if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::HAVOK_VEHICLE_PHYSICS) > 0) {
auto* havokVehiclePhysicsComponent = AddComponent<HavokVehiclePhysicsComponent>();
const int32_t havokVehiclePhysicsComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::HAVOK_VEHICLE_PHYSICS);
if (havokVehiclePhysicsComponentID > 0) {
auto* havokVehiclePhysicsComponent = AddComponent<HavokVehiclePhysicsComponent>(havokVehiclePhysicsComponentID);
havokVehiclePhysicsComponent->SetPosition(m_DefaultPosition);
havokVehiclePhysicsComponent->SetRotation(m_DefaultRotation);
}
Expand Down Expand Up @@ -2161,7 +2167,19 @@ void Entity::SetRespawnPos(const NiPoint3& position) {
auto* characterComponent = GetComponent<CharacterComponent>();
if (characterComponent) characterComponent->SetRespawnPos(position);
}

void Entity::SetRespawnRot(const NiQuaternion& rotation) {
auto* characterComponent = GetComponent<CharacterComponent>();
if (characterComponent) characterComponent->SetRespawnRot(rotation);
}

int32_t Entity::GetCollisionGroup() const {
for (const auto* component : m_Components | std::views::values) {
auto* compToCheck = dynamic_cast<const PhysicsComponent*>(component);
if (compToCheck) {
return compToCheck->GetCollisionGroup();
}
}

return 0;
}
5 changes: 5 additions & 0 deletions dGame/Entity.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,11 @@ class Entity {

const SystemAddress& GetSystemAddress() const;

// Returns the collision group for this entity.
// Because the collision group is stored on a base component, this will look for a physics component
// then return the collision group from that.
int32_t GetCollisionGroup() const;

/**
* Setters
*/
Expand Down
105 changes: 69 additions & 36 deletions dGame/dComponents/BaseCombatAIComponent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "DestroyableComponent.h"

#include <algorithm>
#include <ranges>
#include <sstream>
#include <vector>

Expand All @@ -27,7 +28,7 @@
#include "CDPhysicsComponentTable.h"
#include "dNavMesh.h"

BaseCombatAIComponent::BaseCombatAIComponent(Entity* parent, const uint32_t id): Component(parent) {
BaseCombatAIComponent::BaseCombatAIComponent(Entity* parent, const uint32_t id) : Component(parent) {
m_Target = LWOOBJID_EMPTY;
m_DirtyStateOrTarget = true;
m_State = AiState::spawn;
Expand All @@ -37,6 +38,7 @@ BaseCombatAIComponent::BaseCombatAIComponent(Entity* parent, const uint32_t id):
m_Disabled = false;
m_SkillEntries = {};
m_SoftTimer = 5.0f;
m_ForcedTetherTime = 0.0f;

//Grab the aggro information from BaseCombatAI:
auto componentQuery = CDClientDatabase::CreatePreppedStmt(
Expand Down Expand Up @@ -170,6 +172,17 @@ void BaseCombatAIComponent::Update(const float deltaTime) {
GameMessages::SendStopFXEffect(m_Parent, true, "tether");
m_TetherEffectActive = false;
}
m_ForcedTetherTime -= deltaTime;
if (m_ForcedTetherTime >= 0) return;
}

for (auto entry = m_RemovedThreatList.begin(); entry != m_RemovedThreatList.end();) {
entry->second -= deltaTime;
if (entry->second <= 0.0f) {
entry = m_RemovedThreatList.erase(entry);
} else {
++entry;
}
}

if (m_SoftTimer <= 0.0f) {
Expand Down Expand Up @@ -287,40 +300,7 @@ void BaseCombatAIComponent::CalculateCombat(const float deltaTime) {
}

if (!m_TetherEffectActive && m_OutOfCombat && (m_OutOfCombatTime -= deltaTime) <= 0) {
auto* destroyableComponent = m_Parent->GetComponent<DestroyableComponent>();

if (destroyableComponent != nullptr && destroyableComponent->HasFaction(4)) {
auto serilizationRequired = false;

if (destroyableComponent->GetHealth() != destroyableComponent->GetMaxHealth()) {
destroyableComponent->SetHealth(destroyableComponent->GetMaxHealth());

serilizationRequired = true;
}

if (destroyableComponent->GetArmor() != destroyableComponent->GetMaxArmor()) {
destroyableComponent->SetArmor(destroyableComponent->GetMaxArmor());

serilizationRequired = true;
}

if (serilizationRequired) {
Game::entityManager->SerializeEntity(m_Parent);
}

GameMessages::SendPlayFXEffect(m_Parent->GetObjectID(), 6270, u"tether", "tether");

m_TetherEffectActive = true;

m_TetherTime = 3.0f;
}

// Speed towards start position
if (m_MovementAI != nullptr) {
m_MovementAI->SetHaltDistance(0);
m_MovementAI->SetMaxSpeed(m_PursuitSpeed);
m_MovementAI->SetDestination(m_StartPosition);
}
TetherLogic();

m_OutOfCombat = false;
m_OutOfCombatTime = 0.0f;
Expand Down Expand Up @@ -499,7 +479,7 @@ std::vector<LWOOBJID> BaseCombatAIComponent::GetTargetWithinAggroRange() const {

const auto distance = Vector3::DistanceSquared(m_Parent->GetPosition(), other->GetPosition());

if (distance > m_AggroRadius * m_AggroRadius) continue;
if (distance > m_AggroRadius * m_AggroRadius || m_RemovedThreatList.contains(id)) continue;

targets.push_back(id);
}
Expand Down Expand Up @@ -626,6 +606,7 @@ const NiPoint3& BaseCombatAIComponent::GetStartPosition() const {

void BaseCombatAIComponent::ClearThreat() {
m_ThreatEntries.clear();
m_Target = LWOOBJID_EMPTY;

m_DirtyThreat = true;
}
Expand Down Expand Up @@ -806,3 +787,55 @@ void BaseCombatAIComponent::Wake() {
m_dpEntity->SetSleeping(false);
m_dpEntityEnemy->SetSleeping(false);
}

void BaseCombatAIComponent::TetherLogic() {
auto* destroyableComponent = m_Parent->GetComponent<DestroyableComponent>();

if (destroyableComponent != nullptr && destroyableComponent->HasFaction(4)) {
auto serilizationRequired = false;

if (destroyableComponent->GetHealth() != destroyableComponent->GetMaxHealth()) {
destroyableComponent->SetHealth(destroyableComponent->GetMaxHealth());

serilizationRequired = true;
}

if (destroyableComponent->GetArmor() != destroyableComponent->GetMaxArmor()) {
destroyableComponent->SetArmor(destroyableComponent->GetMaxArmor());

serilizationRequired = true;
}

if (serilizationRequired) {
Game::entityManager->SerializeEntity(m_Parent);
}

GameMessages::SendPlayFXEffect(m_Parent->GetObjectID(), 6270, u"tether", "tether");

m_TetherEffectActive = true;

m_TetherTime = 3.0f;
}

// Speed towards start position
if (m_MovementAI != nullptr) {
m_MovementAI->SetHaltDistance(0);
m_MovementAI->SetMaxSpeed(m_PursuitSpeed);
m_MovementAI->SetDestination(m_StartPosition);
}
}

void BaseCombatAIComponent::ForceTether() {
SetTarget(LWOOBJID_EMPTY);
m_ThreatEntries.clear();
TetherLogic();
m_ForcedTetherTime = m_TetherTime;

SetAiState(AiState::aggro);
}

void BaseCombatAIComponent::IgnoreThreat(const LWOOBJID threat, const float value) {
m_RemovedThreatList[threat] = value;
SetThreat(threat, 0.0f);
m_Target = LWOOBJID_EMPTY;
}
16 changes: 16 additions & 0 deletions dGame/dComponents/BaseCombatAIComponent.h
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,16 @@ class BaseCombatAIComponent final : public Component {
*/
void Wake();

// Force this entity to tether and ignore all other actions
void ForceTether();

// heals the entity to full health and armor
// and tethers them to their spawn point
void TetherLogic();

// Ignore a threat for a certain amount of time
void IgnoreThreat(const LWOOBJID target, const float time);

private:
/**
* Returns the current target or the target that currently is the largest threat to this entity
Expand Down Expand Up @@ -382,6 +392,12 @@ class BaseCombatAIComponent final : public Component {
*/
bool m_DirtyStateOrTarget = false;

// The amount of time the entity will be forced to tether for
float m_ForcedTetherTime = 0.0f;

// The amount of time a removed threat will be ignored for.
std::map<LWOOBJID, float> m_RemovedThreatList;

/**
* Whether the current entity is a mech enemy, needed as mechs tether radius works differently
* @return whether this entity is a mech
Expand Down
2 changes: 1 addition & 1 deletion dGame/dComponents/ControllablePhysicsComponent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
#include "LevelProgressionComponent.h"
#include "eStateChangeType.h"

ControllablePhysicsComponent::ControllablePhysicsComponent(Entity* entity) : PhysicsComponent(entity) {
ControllablePhysicsComponent::ControllablePhysicsComponent(Entity* entity, int32_t componentId) : PhysicsComponent(entity, componentId) {
m_Velocity = {};
m_AngularVelocity = {};
m_InJetpackMode = false;
Expand Down
2 changes: 1 addition & 1 deletion dGame/dComponents/ControllablePhysicsComponent.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class ControllablePhysicsComponent : public PhysicsComponent {
public:
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::CONTROLLABLE_PHYSICS;

ControllablePhysicsComponent(Entity* entity);
ControllablePhysicsComponent(Entity* entity, int32_t componentId);
~ControllablePhysicsComponent() override;

void Update(float deltaTime) override;
Expand Down
2 changes: 1 addition & 1 deletion dGame/dComponents/HavokVehiclePhysicsComponent.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#include "HavokVehiclePhysicsComponent.h"
#include "EntityManager.h"

HavokVehiclePhysicsComponent::HavokVehiclePhysicsComponent(Entity* parent) : PhysicsComponent(parent) {
HavokVehiclePhysicsComponent::HavokVehiclePhysicsComponent(Entity* parent, int32_t componentId) : PhysicsComponent(parent, componentId) {
m_Velocity = NiPoint3Constant::ZERO;
m_AngularVelocity = NiPoint3Constant::ZERO;
m_IsOnGround = true;
Expand Down
2 changes: 1 addition & 1 deletion dGame/dComponents/HavokVehiclePhysicsComponent.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class HavokVehiclePhysicsComponent : public PhysicsComponent {
public:
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::HAVOK_VEHICLE_PHYSICS;

HavokVehiclePhysicsComponent(Entity* parentEntity);
HavokVehiclePhysicsComponent(Entity* parentEntity, int32_t componentId);

void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;

Expand Down
2 changes: 1 addition & 1 deletion dGame/dComponents/PhantomPhysicsComponent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
#include "dpShapeBox.h"
#include "dpShapeSphere.h"

PhantomPhysicsComponent::PhantomPhysicsComponent(Entity* parent) : PhysicsComponent(parent) {
PhantomPhysicsComponent::PhantomPhysicsComponent(Entity* parent, int32_t componentId) : PhysicsComponent(parent, componentId) {
m_Position = m_Parent->GetDefaultPosition();
m_Rotation = m_Parent->GetDefaultRotation();
m_Scale = m_Parent->GetDefaultScale();
Expand Down
2 changes: 1 addition & 1 deletion dGame/dComponents/PhantomPhysicsComponent.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class PhantomPhysicsComponent final : public PhysicsComponent {
public:
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::PHANTOM_PHYSICS;

PhantomPhysicsComponent(Entity* parent);
PhantomPhysicsComponent(Entity* parent, int32_t componentId);
~PhantomPhysicsComponent() override;
void Update(float deltaTime) override;
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;
Expand Down
13 changes: 12 additions & 1 deletion dGame/dComponents/PhysicsComponent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,21 @@

#include "EntityInfo.h"

PhysicsComponent::PhysicsComponent(Entity* parent) : Component(parent) {
PhysicsComponent::PhysicsComponent(Entity* parent, int32_t componentId) : Component(parent) {
m_Position = NiPoint3Constant::ZERO;
m_Rotation = NiQuaternionConstant::IDENTITY;
m_DirtyPosition = false;

CDPhysicsComponentTable* physicsComponentTable = CDClientManager::GetTable<CDPhysicsComponentTable>();

if (physicsComponentTable) {
auto* info = physicsComponentTable->GetByID(componentId);
if (info) {
m_CollisionGroup = info->collisionGroup;
}
}

if (m_Parent->HasVar(u"CollisionGroupID")) m_CollisionGroup = m_Parent->GetVar<int32_t>(u"CollisionGroupID");
}

void PhysicsComponent::Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) {
Expand Down
7 changes: 6 additions & 1 deletion dGame/dComponents/PhysicsComponent.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class dpEntity;

class PhysicsComponent : public Component {
public:
PhysicsComponent(Entity* parent);
PhysicsComponent(Entity* parent, int32_t componentId);
virtual ~PhysicsComponent() = default;

void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;
Expand All @@ -25,6 +25,9 @@ class PhysicsComponent : public Component {

const NiQuaternion& GetRotation() const { return m_Rotation; }
virtual void SetRotation(const NiQuaternion& rot) { if (m_Rotation == rot) return; m_Rotation = rot; m_DirtyPosition = true; }

int32_t GetCollisionGroup() const noexcept { return m_CollisionGroup; }
void SetCollisionGroup(int32_t group) noexcept { m_CollisionGroup = group; }
protected:
dpEntity* CreatePhysicsEntity(eReplicaComponentType type);

Expand All @@ -37,6 +40,8 @@ class PhysicsComponent : public Component {
NiQuaternion m_Rotation;

bool m_DirtyPosition;

int32_t m_CollisionGroup{};
};

#endif //!__PHYSICSCOMPONENT__H__
2 changes: 1 addition & 1 deletion dGame/dComponents/RigidbodyPhantomPhysicsComponent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
#include "dpShapeSphere.h"
#include"EntityInfo.h"

RigidbodyPhantomPhysicsComponent::RigidbodyPhantomPhysicsComponent(Entity* parent) : PhysicsComponent(parent) {
RigidbodyPhantomPhysicsComponent::RigidbodyPhantomPhysicsComponent(Entity* parent, int32_t componentId) : PhysicsComponent(parent, componentId) {
m_Position = m_Parent->GetDefaultPosition();
m_Rotation = m_Parent->GetDefaultRotation();
m_Scale = m_Parent->GetDefaultScale();
Expand Down
2 changes: 1 addition & 1 deletion dGame/dComponents/RigidbodyPhantomPhysicsComponent.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class RigidbodyPhantomPhysicsComponent : public PhysicsComponent {
public:
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::RIGID_BODY_PHANTOM_PHYSICS;

RigidbodyPhantomPhysicsComponent(Entity* parent);
RigidbodyPhantomPhysicsComponent(Entity* parent, int32_t componentId);

void Update(const float deltaTime) override;

Expand Down
2 changes: 1 addition & 1 deletion dGame/dComponents/SimplePhysicsComponent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

#include "Entity.h"

SimplePhysicsComponent::SimplePhysicsComponent(Entity* parent, uint32_t componentID) : PhysicsComponent(parent) {
SimplePhysicsComponent::SimplePhysicsComponent(Entity* parent, int32_t componentID) : PhysicsComponent(parent, componentID) {
m_Position = m_Parent->GetDefaultPosition();
m_Rotation = m_Parent->GetDefaultRotation();

Expand Down
Loading

0 comments on commit 0f8c5b4

Please sign in to comment.