1
0
mirror of https://github.com/ncblakely/GiantsTools synced 2024-12-22 15:27:22 +01:00

Update SDK for 1.5.1.103.

This commit is contained in:
Nick Blakely 2021-02-28 00:46:21 -08:00
parent 71b675f5cb
commit 6a455cb09c
10 changed files with 115 additions and 201 deletions

View File

@ -1,179 +0,0 @@
#include "AI/Public/Behaviors/DodgeBehavior.h"
#include "AI/Public/Components/Senses.h"
#include "AI/Public/Components/MoveEnactor.h"
#include "AI/Public/Components/PhysicsView.h"
#include "GameObject/Public/Core.h"
#include "Navigation/Public/Core.h"
#include "projectile.h"
namespace AI
{
using namespace beehive;
using namespace ECS;
using namespace GameObj;
using namespace Nav;
// TODO: Parameterize
const float DodgeStartTime = 5.0f;
const float DodgeSafeRadius = 10.0f;
static bool DodgeTargetValid(const std::optional<DodgeTarget>& target)
{
return target && !target->Projectile.expired();
}
static float GetTimeToImpact(const P3D& avoidLocation, const PhysicsView& projectilePhysics)
{
float timeToImpact = avoidLocation.Distance3D(projectilePhysics.Location) / projectilePhysics.Velocity.Length();
return timeToImpact;
}
static void AbortDodge(DodgeBehaviorState& state, BehaviorTreeContext& context)
{
state.DodgeTarget = std::nullopt;
context.ResetResumeIndex();
}
static std::optional<DodgeTarget> ChooseDodgeTarget(Entity* entity, Senses& senses, const PhysicsView& objectPhysics)
{
Object* aiObject = entity->GetComponent<ObjectRef>().GetObj();
std::sort(senses.KnownEnemyProjectiles.begin(), senses.KnownEnemyProjectiles.end(), [&objectPhysics](const auto& e1, const auto& e2)
{
const PhysicsView& entity1Physics = e1->GetComponent<PhysicsView>();
const PhysicsView& entity2Physics = e2->GetComponent<PhysicsView>();
return entity1Physics.Location.DistanceSquared3D(objectPhysics.Location) < entity2Physics.Location.DistanceSquared3D(objectPhysics.Location);
});
for (const auto& projectile : senses.KnownEnemyProjectiles)
{
Object* projectileObject = projectile->GetComponent<ObjectRef>().GetObj();
const PhysicsView& projectilePhysics = projectile->GetComponent<PhysicsView>();
ObjSpecProjectile* spec = ObjSpecProjectile::Cast(projectileObject);
if (!spec->ground_collision)
{
TRACE_BEHAVIOR("Projectile is not expected to collide with ground");
continue;
}
const PROJ_Def* def = PROJ_DefGet(spec->projectile_index);
float speed = projectileObject->velocity.Length();
float timeToImpact = GetTimeToImpact(spec->ground_collision_position, projectilePhysics);
if (timeToImpact > DodgeStartTime)
{
TRACE_BEHAVIOR("Projectile time to impact of {0} is above threshold", timeToImpact);
continue;
}
P3D aiProjectedLocation = aiObject->location + (aiObject->velocity * timeToImpact);
if (aiProjectedLocation.DistanceSquared3D(spec->ground_collision_position) < Squared(def->fardist))
{
return DodgeTarget{ projectile, def->fardist, spec->ground_collision_position };
}
}
return std::nullopt;
}
bool DodgeBehavior::ShouldStartDodge(Entity* entity, Object* object, BehaviorTreeContext& context)
{
if (!entity->HasComponent<Senses, PhysicsView>())
return false;
if (!World->navMesh)
return false;
auto& state = entity->GetComponent<DodgeBehaviorState>();
if (!DodgeTargetValid(state.DodgeTarget))
{
// Make sure invalid targets have been cleared out
state.DodgeTarget = std::nullopt;
}
else
{
// Already have dodge in progress
return false;
}
auto [senses, physicsView] = entity->GetComponent<Senses, PhysicsView>();
state.DodgeTarget = ChooseDodgeTarget(entity, senses, physicsView);
if (!state.DodgeTarget)
{
// No nearby threats
return false;
}
float angleToCenter = dirfcalcp3d(&state.DodgeTarget->AvoidLocation, &physicsView.Location);
float sa, ca;
calc_sincosd(dirfadjust(angleToCenter), &sa, &ca);
P3D wantLoc = state.DodgeTarget->AvoidLocation;
wantLoc.x += (state.DodgeTarget->ImpactRadius + DodgeSafeRadius) * ca;
wantLoc.y += (state.DodgeTarget->ImpactRadius + DodgeSafeRadius) * sa;
MoveGoalParams params;
params.Speed = MoveGoalSpeed::Fast;
std::shared_ptr<Path> path = PathUtil::GetPath(entity, World->navMesh.get(), physicsView.Location, wantLoc, &params);
if (!path)
{
TRACE_BEHAVIOR("Couldn't path away from projectile");
return false;
}
TRACE_BEHAVIOR("Dodging to location {0} {1} {2}, est. impact time {3}",
wantLoc.x,
wantLoc.y,
wantLoc.z,
GetTimeToImpact(state.DodgeTarget->AvoidLocation, state.DodgeTarget->Projectile.lock()->GetComponent<PhysicsView>()));
PathUtil::SetPath(entity, path);
context.SetChainingEnabled(false);
return true;
}
Status DodgeBehavior::MoveToDodgeLocation(Entity* entity, Object* object, BehaviorTreeContext& context)
{
auto& state = entity->GetComponent<DodgeBehaviorState>();
const auto& moveEnactor = entity->GetComponent<MoveEnactor>();
if (!DodgeTargetValid(state.DodgeTarget)
|| !moveEnactor.Path)
{
TRACE_BEHAVIOR("Dodge target no longer valid; canceling");
AbortDodge(state, context);
return Status::SUCCESS;
}
const auto& aiPhysics = entity->GetComponent<PhysicsView>();
float distanceFromImpactSq = state.DodgeTarget->AvoidLocation.DistanceSquared3D(aiPhysics.Location);
if (distanceFromImpactSq > Squared(state.DodgeTarget->ImpactRadius + DodgeSafeRadius))
{
// Got far enough away somehow, we can reset
TRACE_BEHAVIOR("AI is {0} units away from impact location with still active dodge behavior; canceling", sqrt(distanceFromImpactSq));
AbortDodge(state, context);
return Status::SUCCESS;
}
return Status::RUNNING;
}
InnerBehaviorTree DodgeBehavior::Build(ECS::Entity* entity)
{
assert(entity);
DodgeBehaviorState& state = entity->AddComponent<DodgeBehaviorState>();
return BehaviorTreeBuilder()
.sequence()
.leaf(CreateLeaf(entity, ShouldStartDodge))
.leaf(CreateLeaf(entity, MoveToDodgeLocation))
.end()
.build();
}
}

View File

@ -0,0 +1,7 @@
#pragma once
enum class EventListenerResult
{
Continue,
Cancel
};

View File

@ -3,11 +3,13 @@
#include <functional>
#include <guiddef.h>
#include "EventListenerResult.h"
template<typename TEventType, typename TEvent>
struct IEventSource
{
virtual ~IEventSource() = default;
virtual GUID Listen(TEventType event, std::function<void(const TEvent&)> function) noexcept = 0;
virtual GUID Listen(TEventType event, std::function<EventListenerResult(const TEvent&)> function) noexcept = 0;
virtual void Unlisten(TEventType event, GUID uuid) noexcept = 0;
};

View File

@ -7,9 +7,6 @@
enum class NetPlayerState;
enum class GameTeam;
// {770DEBD3-165D-4340-829D-5262F473FBE3}
inline const GUID IID_ITextLookupService = { 0x770debd3, 0x165d, 0x4340, 0x82, 0x9d, 0x52, 0x62, 0xf4, 0x73, 0xfb, 0xe3 };
/// <summary>
/// Service providing localization of text placeholders and friendly-name mappings of common enums.
/// </summary>

View File

@ -46,6 +46,7 @@ struct ChatMessageEvent : GameServerEvent
tstring_view message{};
PlayerIndex senderIndex{};
ChatFlag flags{};
};
struct WorldLoadedEvent : GameServerEvent

View File

@ -8,9 +8,6 @@
#include "GameServerEvents.h"
#include "NetCommon.h"
// {B2D67EE7-8063-488F-B3B9-E7DA675CB752}
inline const GUID IID_IGameServer = { 0xb2d67ee7, 0x8063, 0x488f, 0xb3, 0xb9, 0xe7, 0xda, 0x67, 0x5c, 0xb7, 0x52 };
/// <summary>
/// Defines an API for communicating with the game server.
/// </summary>
@ -31,15 +28,24 @@ DEFINE_SERVICE_MULTI("{B2D67EE7-8063-488F-B3B9-E7DA675CB752}", IGameServer, IEve
/// Bans the player at the specified index.
/// </summary>
/// <param name="index">The player index.</param>
/// <returns></returns>
virtual void BanPlayer(int index) = 0;
/// <summary>
/// Removes the IP address from the ban list.
/// </summary>
/// <param name="index">The IP address.</param>
virtual void UnbanPlayer(const IPAddress & ipAddress) = 0;
/// <summary>
/// Gets the IP addresses that are currently banned.
/// </summary>
virtual const std::vector<IPAddress> GetBans() const = 0;
/// <summary>
/// Kicks the player at the specified index.
/// </summary>
/// <param name="index">The player index.</param>
/// <param name="reason">The reason for kicking the player.</param>
/// <returns></returns>
virtual void KickPlayer(int index, KickReason reason) = 0;
/// <summary>
@ -72,6 +78,4 @@ DEFINE_SERVICE_MULTI("{B2D67EE7-8063-488F-B3B9-E7DA675CB752}", IGameServer, IEve
/// </summary>
/// <param name="gameDetails">The game details.</param>
virtual void ChangeGameDetails(const NetGameDetails& gameDetails) = 0;
};
struct DECLSPEC_UUID("{B2D67EE7-8063-488F-B3B9-E7DA675CB752}") IGameServer;
};

View File

@ -7,9 +7,6 @@
typedef std::future<std::vector<ServerInfoResponse>> ServerInfoFuture;
// {EE129A81-0A86-49C4-8D23-A771A7350952}
inline const GUID IID_IGiantsApiClient = { 0xee129a81, 0xa86, 0x49c4, 0x8d, 0x23, 0xa7, 0x71, 0xa7, 0x35, 0x9, 0x52 };
DEFINE_SERVICE("{EE129A81-0A86-49C4-8D23-A771A7350952}", IGiantsApiClient)
{
virtual ~IGiantsApiClient() = default;
@ -17,6 +14,4 @@ DEFINE_SERVICE("{EE129A81-0A86-49C4-8D23-A771A7350952}", IGiantsApiClient)
virtual void DeleteServerInformationAsync(tstring_view gameName, int hostPort) = 0;
virtual ServerInfoFuture GetServerInformationAsync() = 0;
virtual void PostServerInformationAsync(const nlohmann::json& requestBody) = 0;
};
struct DECLSPEC_UUID("{EE129A81-0A86-49C4-8D23-A771A7350952}") IGiantsApiClient;
};

View File

@ -0,0 +1,82 @@
#pragma once
#include <sstream>
class IPAddress
{
public:
int operator[](int index) const
{
if (index < countof(m_octets) && index > 0)
{
return m_octets[index];
}
throw std::invalid_argument("Invalid octet index.");
}
bool operator==(const IPAddress& right) const
{
return (m_octets[0] == right.m_octets[0] &&
m_octets[1] == right.m_octets[1] &&
m_octets[2] == right.m_octets[2] &&
m_octets[3] == right.m_octets[3]);
}
bool operator!= (const IPAddress& right) const
{
return !operator==(right);
}
bool operator<(const IPAddress& right) const
{
return ToInt() < right.ToInt();
}
bool operator>(const IPAddress& right) const
{
return right.operator<(*this);
}
static IPAddress FromString(const tstring_view str)
{
IPAddress ipAddress;
char octetBuff[4]{};
std::string tmp(str);
std::istringstream iss(tmp);
int octetsRead = 0;
while (true)
{
iss.getline(octetBuff, sizeof(octetBuff), '.');
if (iss.gcount() <= 0)
break;
int octet = atoi(octetBuff);
if (octet > 255 || octet < 0)
{
throw std::invalid_argument(fmt::format("Octet '{0}' is invalid.", octet));
}
ipAddress.m_octets[octetsRead] = octet;
octetsRead++;
}
return ipAddress;
}
std::string ToString() const
{
return fmt::sprintf("%d.%d.%d.%d", m_octets[0], m_octets[1], m_octets[2], m_octets[3]);
}
uint ToInt() const
{
return ((m_octets[0] << 24) + (m_octets[1] << 16) + (m_octets[2] << 8) + m_octets[3]);
}
protected:
int m_octets[4]{};
};

View File

@ -2,6 +2,8 @@
#include <string>
#include "IPAddress.h"
typedef int PlayerIndex;
typedef int PlayerTeamIndex;
@ -81,13 +83,14 @@ enum class GameTeam
struct PlayerInfo
{
PlayerIndex index = 0;
std::string name;
tstring name;
float score = 0;
float deaths = 0;
int ping = 0;
PlayerTeamIndex team = 0;
bool host = false;
NetPlayerState state = NetPlayerState::None;
IPAddress ipAddress;
};
struct NetGameSettings
@ -105,6 +108,7 @@ struct NetGameSettings
bool vimpsDisabled = false;
bool weaponAvailabilityModified = false;
int worldId = 0;
tstring sessionName;
};
struct NetGameDetails
@ -112,7 +116,7 @@ struct NetGameDetails
// User-adjustable settings for the current game.
NetGameSettings settings;
std::string worldName;
std::string teamTypeName;
std::string gameTypeName;
tstring worldName;
tstring teamTypeName;
tstring gameTypeName;
};

View File

@ -28,6 +28,7 @@ ServerDialog::~ServerDialog()
pGameServer->Unlisten(GameServerEventType::PlayerConnected, m_playerConnectedEventHandle);
pGameServer->Unlisten(GameServerEventType::PlayerDisconnected, m_playerDisconnectedEventHandle);
pGameServer->Unlisten(GameServerEventType::ChatMessage, m_playerChatMessageHandle);
pGameServer->Unlisten(GameServerEventType::WorldLoaded, m_worldLoadedHandle);
}
catch (...)
{