2022-08-06 03:01:59 +00:00
|
|
|
#include "ProjectileAttackBehavior.h"
|
2021-12-05 17:54:36 +00:00
|
|
|
#include "BehaviorBranchContext.h"
|
|
|
|
#include "BehaviorContext.h"
|
|
|
|
#include "EntityManager.h"
|
|
|
|
#include "Game.h"
|
2023-10-21 23:31:55 +00:00
|
|
|
#include "Logger.h"
|
2021-12-05 17:54:36 +00:00
|
|
|
#include "SkillComponent.h"
|
2024-01-05 12:31:22 +00:00
|
|
|
#include "ObjectIDManager.h"
|
2023-04-25 18:17:40 +00:00
|
|
|
#include "eObjectBits.h"
|
2021-12-05 17:54:36 +00:00
|
|
|
|
2024-02-27 07:25:44 +00:00
|
|
|
void ProjectileAttackBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bitStream, BehaviorBranchContext branch) {
|
2022-12-16 21:23:02 +00:00
|
|
|
LWOOBJID target{};
|
2021-12-05 17:54:36 +00:00
|
|
|
|
2024-02-27 07:25:44 +00:00
|
|
|
if (!bitStream.Read(target)) {
|
2024-03-08 21:44:02 +00:00
|
|
|
Log::Warn("Unable to read target from bitStream, aborting Handle! {:d}", bitStream.GetNumberOfUnreadBits());
|
2022-12-16 21:23:02 +00:00
|
|
|
return;
|
|
|
|
};
|
2022-07-25 02:26:51 +00:00
|
|
|
|
2023-07-15 20:56:33 +00:00
|
|
|
auto* entity = Game::entityManager->GetEntity(context->originator);
|
2021-12-05 17:54:36 +00:00
|
|
|
|
2022-07-28 13:39:57 +00:00
|
|
|
if (entity == nullptr) {
|
2024-03-08 21:44:02 +00:00
|
|
|
Log::Warn("Failed to find originator ({:d})!", context->originator);
|
2021-12-05 17:54:36 +00:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto* skillComponent = entity->GetComponent<SkillComponent>();
|
|
|
|
|
2022-07-28 13:39:57 +00:00
|
|
|
if (skillComponent == nullptr) {
|
2024-03-08 21:44:02 +00:00
|
|
|
Log::Warn("Failed to find skill component for ({:d})!", -context->originator);
|
2021-12-05 17:54:36 +00:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-12-21 08:26:17 +00:00
|
|
|
if (m_useMouseposit && !branch.isSync) {
|
2024-01-29 07:53:12 +00:00
|
|
|
NiPoint3 targetPosition = NiPoint3Constant::ZERO;
|
2024-02-27 07:25:44 +00:00
|
|
|
if (!bitStream.Read(targetPosition)) {
|
2024-03-08 21:44:02 +00:00
|
|
|
Log::Warn("Unable to read targetPosition from bitStream, aborting Handle! {:d}", bitStream.GetNumberOfUnreadBits());
|
2022-12-16 21:23:02 +00:00
|
|
|
return;
|
|
|
|
};
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
|
2023-07-15 20:56:33 +00:00
|
|
|
auto* targetEntity = Game::entityManager->GetEntity(target);
|
2021-12-05 17:54:36 +00:00
|
|
|
|
2022-07-28 13:39:57 +00:00
|
|
|
for (auto i = 0u; i < this->m_projectileCount; ++i) {
|
2022-12-16 21:23:02 +00:00
|
|
|
LWOOBJID projectileId{};
|
2021-12-05 17:54:36 +00:00
|
|
|
|
2024-02-27 07:25:44 +00:00
|
|
|
if (!bitStream.Read(projectileId)) {
|
2024-03-08 21:44:02 +00:00
|
|
|
Log::Warn("Unable to read projectileId from bitStream, aborting Handle! {:d}", bitStream.GetNumberOfUnreadBits());
|
2022-12-16 21:23:02 +00:00
|
|
|
return;
|
|
|
|
};
|
2022-07-25 02:26:51 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
branch.target = target;
|
|
|
|
branch.isProjectile = true;
|
|
|
|
branch.referencePosition = targetEntity == nullptr ? entity->GetPosition() : targetEntity->GetPosition();
|
|
|
|
|
|
|
|
skillComponent->RegisterPlayerProjectile(projectileId, context, branch, this->m_lot);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-27 07:25:44 +00:00
|
|
|
void ProjectileAttackBehavior::Calculate(BehaviorContext* context, RakNet::BitStream& bitStream, BehaviorBranchContext branch) {
|
|
|
|
bitStream.Write(branch.target);
|
2021-12-05 17:54:36 +00:00
|
|
|
|
2023-07-15 20:56:33 +00:00
|
|
|
auto* entity = Game::entityManager->GetEntity(context->originator);
|
2021-12-05 17:54:36 +00:00
|
|
|
|
2022-07-28 13:39:57 +00:00
|
|
|
if (entity == nullptr) {
|
2023-10-21 23:31:55 +00:00
|
|
|
LOG("Failed to find originator (%llu)!", context->originator);
|
2021-12-05 17:54:36 +00:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto* skillComponent = entity->GetComponent<SkillComponent>();
|
|
|
|
|
2022-07-28 13:39:57 +00:00
|
|
|
if (skillComponent == nullptr) {
|
2023-10-21 23:31:55 +00:00
|
|
|
LOG("Failed to find skill component for (%llu)!", context->originator);
|
2021-12-05 17:54:36 +00:00
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2023-07-15 20:56:33 +00:00
|
|
|
auto* other = Game::entityManager->GetEntity(branch.target);
|
2021-12-05 17:54:36 +00:00
|
|
|
|
2022-07-28 13:39:57 +00:00
|
|
|
if (other == nullptr) {
|
2023-10-21 23:31:55 +00:00
|
|
|
LOG("Invalid projectile target (%llu)!", branch.target);
|
2022-07-25 02:26:51 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
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;
|
|
|
|
|
2022-07-28 13:39:57 +00:00
|
|
|
for (auto i = 0u; i < this->m_projectileCount; ++i) {
|
2024-01-05 12:31:22 +00:00
|
|
|
auto id = static_cast<LWOOBJID>(ObjectIDManager::GenerateObjectID());
|
2021-12-05 17:54:36 +00:00
|
|
|
|
2023-04-25 18:17:40 +00:00
|
|
|
GeneralUtils::SetBit(id, eObjectBits::SPAWNED);
|
2021-12-05 17:54:36 +00:00
|
|
|
|
2024-02-27 07:25:44 +00:00
|
|
|
bitStream.Write(id);
|
2021-12-05 17:54:36 +00:00
|
|
|
|
|
|
|
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
|
2022-07-28 13:39:57 +00:00
|
|
|
if (this->m_projectileCount == 2) {
|
2021-12-05 17:54:36 +00:00
|
|
|
angle += angleDelta;
|
2022-07-28 13:39:57 +00:00
|
|
|
} else if (this->m_projectileCount == 3) {
|
2021-12-05 17:54:36 +00:00
|
|
|
angle += angleStep;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-07-28 13:39:57 +00:00
|
|
|
void ProjectileAttackBehavior::Load() {
|
2021-12-05 17:54:36 +00:00
|
|
|
this->m_lot = GetInt("LOT_ID");
|
|
|
|
|
|
|
|
this->m_projectileCount = GetInt("spread_count");
|
|
|
|
|
2022-07-28 13:39:57 +00:00
|
|
|
if (this->m_projectileCount == 0) {
|
2021-12-05 17:54:36 +00:00
|
|
|
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");
|
2022-12-19 20:52:00 +00:00
|
|
|
|
|
|
|
this->m_ProjectileType = GetInt("projectile_type");
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|