1
0
mirror of https://github.com/rwengine/openrw.git synced 2024-11-07 11:22:45 +01:00

clang-format files in rwengine/src/ai

This commit is contained in:
Daniel Evans 2016-09-09 21:13:18 +01:00
parent 9aa3af6703
commit d5e853d23f
11 changed files with 1018 additions and 1051 deletions

View File

@ -1,18 +1,17 @@
#include "ai/AIGraph.hpp"
#include <objects/GameObject.hpp>
#include <ai/AIGraphNode.hpp>
#include <glm/gtx/norm.hpp>
#include <iostream>
#include <objects/GameObject.hpp>
AIGraph::~AIGraph()
{
AIGraph::~AIGraph() {
for (auto n : nodes) {
delete n;
}
}
void AIGraph::createPathNodes(const glm::vec3& position, const glm::quat& rotation, PathData& path)
{
void AIGraph::createPathNodes(const glm::vec3& position,
const glm::quat& rotation, PathData& path) {
size_t startIndex = nodes.size();
std::vector<AIGraphNode*> pathNodes;
pathNodes.reserve(path.nodes.size());
@ -36,7 +35,9 @@ void AIGraph::createPathNodes(const glm::vec3& position, const glm::quat& rotati
if (ainode == nullptr) {
ainode = new AIGraphNode;
ainode->type = (path.type == PathData::PATH_PED ? AIGraphNode::Pedestrian : AIGraphNode::Vehicle);
ainode->type =
(path.type == PathData::PATH_PED ? AIGraphNode::Pedestrian
: AIGraphNode::Vehicle);
ainode->nextIndex = node.next >= 0 ? startIndex + node.next : -1;
ainode->flags = AIGraphNode::None;
ainode->size = node.size;
@ -49,17 +50,20 @@ void AIGraph::createPathNodes(const glm::vec3& position, const glm::quat& rotati
pathNodes.push_back(ainode);
nodes.push_back(ainode);
if( ainode->external )
{
if (ainode->external) {
externalNodes.push_back(ainode);
// Determine which grid cell this node falls into
float lowerCoord = -(WORLD_GRID_SIZE) / 2.f;
auto gridrel = glm::vec2(ainode->position) - glm::vec2(lowerCoord, lowerCoord);
auto gridcoord = glm::floor(gridrel / glm::vec2(WORLD_CELL_SIZE));
if( gridcoord.x < 0 || gridcoord.y < 0 || gridcoord.x >= WORLD_GRID_WIDTH || gridcoord.y >= WORLD_GRID_WIDTH )
{
std::cout << "Warning: Node outside of grid at coord " << gridcoord.x << " " << gridcoord.y << std::endl;
auto gridrel = glm::vec2(ainode->position) -
glm::vec2(lowerCoord, lowerCoord);
auto gridcoord =
glm::floor(gridrel / glm::vec2(WORLD_CELL_SIZE));
if (gridcoord.x < 0 || gridcoord.y < 0 ||
gridcoord.x >= WORLD_GRID_WIDTH ||
gridcoord.y >= WORLD_GRID_WIDTH) {
std::cout << "Warning: Node outside of grid at coord "
<< gridcoord.x << " " << gridcoord.y << std::endl;
}
auto index = (gridcoord.x * WORLD_GRID_WIDTH) + gridcoord.y;
gridNodes[index].push_back(ainode);
@ -68,7 +72,8 @@ void AIGraph::createPathNodes(const glm::vec3& position, const glm::quat& rotati
}
for (size_t pn = 0; pn < path.nodes.size(); ++pn) {
if(path.nodes[pn].next >= 0 && (unsigned) path.nodes[pn].next < pathNodes.size()) {
if (path.nodes[pn].next >= 0 &&
(unsigned)path.nodes[pn].next < pathNodes.size()) {
auto node = pathNodes[pn];
auto next = pathNodes[path.nodes[pn].next];
@ -78,14 +83,15 @@ void AIGraph::createPathNodes(const glm::vec3& position, const glm::quat& rotati
}
}
glm::ivec2 worldToGrid(const glm::vec2& world)
{
glm::ivec2 worldToGrid(const glm::vec2& world) {
static const float lowerCoord = -(WORLD_GRID_SIZE) / 2.f;
return glm::ivec2((world - glm::vec2(lowerCoord)) / glm::vec2(WORLD_CELL_SIZE));
return glm::ivec2((world - glm::vec2(lowerCoord)) /
glm::vec2(WORLD_CELL_SIZE));
}
void AIGraph::gatherExternalNodesNear(const glm::vec3& center, const float radius, std::vector< AIGraphNode* >& nodes)
{
void AIGraph::gatherExternalNodesNear(const glm::vec3& center,
const float radius,
std::vector<AIGraphNode*>& nodes) {
// the bounds end up covering more than might fit
auto planecoords = glm::vec2(center);
auto minWorld = planecoords - glm::vec2(radius);
@ -93,24 +99,18 @@ void AIGraph::gatherExternalNodesNear(const glm::vec3& center, const float radiu
auto minGrid = worldToGrid(minWorld);
auto maxGrid = worldToGrid(maxWorld);
for( int x = minGrid.x; x <= maxGrid.x; ++x )
{
for( int y = minGrid.y; y <= maxGrid.y; ++y )
{
for (int x = minGrid.x; x <= maxGrid.x; ++x) {
for (int y = minGrid.y; y <= maxGrid.y; ++y) {
int i = (x * WORLD_GRID_WIDTH) + y;
if( i < 0 || i >= (int)gridNodes.size() )
{
if (i < 0 || i >= (int)gridNodes.size()) {
continue;
}
auto& external = gridNodes[i];
for ( AIGraphNode* node : external )
{
if ( glm::distance2( center, node->position ) < radius*radius )
{
for (AIGraphNode* node : external) {
if (glm::distance2(center, node->position) < radius * radius) {
nodes.push_back(node);
}
}
}
}
}

View File

@ -1,18 +1,16 @@
#pragma once
#ifndef _AIGRAPH_HPP_
#define _AIGRAPH_HPP_
#include <vector>
#include <glm/gtc/quaternion.hpp>
#include <data/PathData.hpp>
#include <array>
#include <data/PathData.hpp>
#include <glm/gtc/quaternion.hpp>
#include <rw/types.hpp>
#include <vector>
struct AIGraphNode;
class AIGraph
{
class AIGraph {
public:
~AIGraph();
std::vector<AIGraphNode*> nodes;
@ -29,9 +27,11 @@ public:
*/
std::array<std::vector<AIGraphNode*>, WORLD_GRID_CELLS> gridNodes;
void createPathNodes(const glm::vec3& position, const glm::quat& rotation, PathData& path);
void createPathNodes(const glm::vec3& position, const glm::quat& rotation,
PathData& path);
void gatherExternalNodesNear(const glm::vec3& center, const float radius, std::vector<AIGraphNode*>& nodes);
void gatherExternalNodesNear(const glm::vec3& center, const float radius,
std::vector<AIGraphNode*>& nodes);
};
#endif

View File

@ -1,20 +1,17 @@
#pragma once
#ifndef _AIGRAPHNODE_HPP_
#define _AIGRAPHNODE_HPP_
#include <glm/glm.hpp>
#include <cstdint>
#include <glm/glm.hpp>
#include <vector>
struct AIGraphNode
{
enum NodeType {
Vehicle,
Pedestrian
};
struct AIGraphNode {
enum NodeType { Vehicle, Pedestrian };
enum {
None = 0,
CrossesRoad = 1 /// No documentation for other flags yet, but this is mentioned.
CrossesRoad =
1 /// No documentation for other flags yet, but this is mentioned.
};
NodeType type;

View File

@ -1,7 +1,7 @@
#include <btBulletDynamicsCommon.h>
#include <ai/CharacterController.hpp>
#include <objects/CharacterObject.hpp>
#include <objects/VehicleObject.hpp>
#include <btBulletDynamicsCommon.h>
#include <data/Model.hpp>
#include <engine/Animator.hpp>
@ -17,13 +17,11 @@ CharacterController::CharacterController(CharacterObject* character)
, m_closeDoorTimer(0.f)
, currentGoal(None)
, leader(nullptr)
, targetNode(nullptr)
{
, targetNode(nullptr) {
character->controller = this;
}
bool CharacterController::updateActivity()
{
bool CharacterController::updateActivity() {
if (_currentActivity && character->isAlive()) {
return _currentActivity->update(character, this);
}
@ -31,52 +29,46 @@ bool CharacterController::updateActivity()
return false;
}
void CharacterController::setActivity(CharacterController::Activity* activity)
{
void CharacterController::setActivity(CharacterController::Activity *activity) {
if (_currentActivity) delete _currentActivity;
_currentActivity = activity;
}
void CharacterController::skipActivity()
{
// Some activities can't be cancelled, such as the final phase of entering a vehicle
void CharacterController::skipActivity() {
// Some activities can't be cancelled, such as the final phase of entering a
// vehicle
// or jumping.
if (getCurrentActivity() != nullptr &&
getCurrentActivity()->canSkip(character, this))
setActivity(nullptr);
}
void CharacterController::setNextActivity(CharacterController::Activity* activity)
{
void CharacterController::setNextActivity(
CharacterController::Activity *activity) {
if (_currentActivity == nullptr) {
setActivity(activity);
_nextActivity = nullptr;
}
else {
} else {
if (_nextActivity) delete _nextActivity;
_nextActivity = activity;
}
}
bool CharacterController::isCurrentActivity(const std::string& activity) const
{
bool CharacterController::isCurrentActivity(const std::string &activity) const {
if (getCurrentActivity() == nullptr) return false;
return getCurrentActivity()->name() == activity;
}
void CharacterController::update(float dt)
{
void CharacterController::update(float dt) {
if (character->getCurrentVehicle()) {
// Nevermind, the player is in a vehicle.
auto &d = character->getMovement();
if( character->getCurrentSeat() == 0 )
{
if (character->getCurrentSeat() == 0) {
character->getCurrentVehicle()->setSteeringAngle(d.y);
if( std::abs(d.x) > 0.01f )
{
if (std::abs(d.x) > 0.01f) {
character->getCurrentVehicle()->setHandbraking(false);
}
character->getCurrentVehicle()->setThrottle(d.x);
@ -90,18 +82,16 @@ void CharacterController::update(float dt)
if (entryDoor && entryDoor->constraint) {
if (glm::length(d) <= 0.1f) {
if (m_closeDoorTimer >= kCloseDoorIdleTime) {
character->getCurrentVehicle()->setPartTarget(entryDoor, true, entryDoor->closedAngle);
character->getCurrentVehicle()->setPartTarget(
entryDoor, true, entryDoor->closedAngle);
}
m_closeDoorTimer += dt;
}
else {
} else {
m_closeDoorTimer = 0.f;
}
}
}
}
else
{
} else {
m_closeDoorTimer = 0.f;
}
@ -118,29 +108,24 @@ void CharacterController::update(float dt)
}
}
CharacterObject *CharacterController::getCharacter() const
{
CharacterObject *CharacterController::getCharacter() const {
return character;
}
void CharacterController::setMoveDirection(const glm::vec3 &movement)
{
void CharacterController::setMoveDirection(const glm::vec3 &movement) {
character->setMovement(movement);
}
void CharacterController::setLookDirection(const glm::vec2 &look)
{
void CharacterController::setLookDirection(const glm::vec2 &look) {
character->setLook(look);
}
void CharacterController::setRunning(bool run)
{
void CharacterController::setRunning(bool run) {
character->setRunning(run);
}
bool Activities::GoTo::update(CharacterObject *character, CharacterController *controller)
{
bool Activities::GoTo::update(CharacterObject *character,
CharacterController *controller) {
/* TODO: Use the ai nodes to navigate to the position */
auto cpos = character->getPosition();
glm::vec3 targetDirection = target - cpos;
@ -153,7 +138,8 @@ bool Activities::GoTo::update(CharacterObject *character, CharacterController *c
return true;
}
float hdg = atan2(targetDirection.y, targetDirection.x) - glm::half_pi<float>();
float hdg =
atan2(targetDirection.y, targetDirection.x) - glm::half_pi<float>();
character->setHeading(glm::degrees(hdg));
controller->setMoveDirection({1.f, 0.f, 0.f});
@ -162,18 +148,15 @@ bool Activities::GoTo::update(CharacterObject *character, CharacterController *c
return false;
}
bool Activities::Jump::update(CharacterObject* character, CharacterController* controller)
{
bool Activities::Jump::update(CharacterObject *character,
CharacterController *controller) {
RW_UNUSED(controller);
if (character->physCharacter == nullptr) return true;
if( !jumped )
{
if (!jumped) {
character->jump();
jumped = true;
}
else
{
} else {
if (character->physCharacter->canJump()) {
return true;
}
@ -182,14 +165,14 @@ bool Activities::Jump::update(CharacterObject* character, CharacterController* c
return false;
}
bool Activities::EnterVehicle::canSkip(CharacterObject *character, CharacterController *) const
{
bool Activities::EnterVehicle::canSkip(CharacterObject *character,
CharacterController *) const {
// If we're already inside the vehicle, it can't helped.
return character->getCurrentVehicle() == nullptr;
}
bool Activities::EnterVehicle::update(CharacterObject *character, CharacterController *controller)
{
bool Activities::EnterVehicle::update(CharacterObject *character,
CharacterController *controller) {
constexpr float kSprintToEnterDistance = 5.f;
constexpr float kGiveUpDistance = 100.f;
@ -201,16 +184,13 @@ bool Activities::EnterVehicle::update(CharacterObject *character, CharacterContr
return true;
}
if( seat == ANY_SEAT )
{
if (seat == ANY_SEAT) {
// Determine which seat to take.
float nearest = std::numeric_limits<float>::max();
for(unsigned int s = 1; s < vehicle->info->seats.size(); ++s)
{
for (unsigned int s = 1; s < vehicle->info->seats.size(); ++s) {
auto entry = vehicle->getSeatEntryPositionWorld(s);
float dist = glm::distance(entry, character->getPosition());
if( dist < nearest )
{
if (dist < nearest) {
seat = s;
nearest = dist;
}
@ -225,15 +205,16 @@ bool Activities::EnterVehicle::update(CharacterObject *character, CharacterContr
auto anm_enter = character->animations.car_getin_lhs;
auto anm_pullout = character->animations.car_pullout_lhs;
if ( entryPosLocal.x > 0.f )
{
if (entryPosLocal.x > 0.f) {
anm_open = character->animations.car_open_rhs;
anm_enter = character->animations.car_getin_rhs;
anm_pullout = character->animations.car_pullout_rhs;
}
// If there's someone in this seat already, we may have to ask them to leave.
auto currentOccupant= static_cast<CharacterObject*>(vehicle->getOccupant(seat));
// If there's someone in this seat already, we may have to ask them to
// leave.
auto currentOccupant =
static_cast<CharacterObject *>(vehicle->getOccupant(seat));
bool tryToEnter = false;
@ -241,29 +222,27 @@ bool Activities::EnterVehicle::update(CharacterObject *character, CharacterContr
if (character->animator->getAnimation(AnimIndexAction) == anm_open) {
if (character->animator->isCompleted(AnimIndexAction)) {
tryToEnter = true;
}
else if( entryDoor && character->animator->getAnimationTime(AnimIndexAction) >= 0.5f )
{
} else if (entryDoor &&
character->animator->getAnimationTime(AnimIndexAction) >=
0.5f) {
vehicle->setPartTarget(entryDoor, true, entryDoor->openAngle);
}
else {
} else {
// character->setPosition(vehicle->getSeatEntryPosition(seat));
character->rotation = vehicle->getRotation();
}
}
else if (character->animator->getAnimation(AnimIndexAction) == anm_pullout) {
} else if (character->animator->getAnimation(AnimIndexAction) ==
anm_pullout) {
if (character->animator->isCompleted(AnimIndexAction)) {
tryToEnter = true;
}
}
else if( character->animator->getAnimation(AnimIndexAction) == anm_enter ) {
} else if (character->animator->getAnimation(AnimIndexAction) ==
anm_enter) {
if (character->animator->isCompleted(AnimIndexAction)) {
// VehicleGetIn is over, finish activity
return true;
}
}
}
else {
} else {
glm::vec3 targetDirection = entryPos - character->getPosition();
targetDirection.z = 0.f;
@ -278,35 +257,34 @@ bool Activities::EnterVehicle::update(CharacterObject *character, CharacterContr
glm::degrees(glm::roll(vehicle->getRotation())));
// Determine if the door open animation should be skipped.
if( entryDoor == nullptr || (entryDoor->constraint != nullptr && glm::abs(entryDoor->constraint->getHingeAngle()) >= 0.6f ) )
{
if (entryDoor == nullptr ||
(entryDoor->constraint != nullptr &&
glm::abs(entryDoor->constraint->getHingeAngle()) >= 0.6f)) {
tryToEnter = true;
}
else
{
} else {
character->playActivityAnimation(anm_open, false, true);
}
}
else if (targetDistance > kGiveUpDistance) {
} else if (targetDistance > kGiveUpDistance) {
return true;
}
else {
} else {
if (targetDistance > kSprintToEnterDistance) {
character->controller->setRunning(true);
}
character->setHeading(
glm::degrees(atan2(targetDirection.y, targetDirection.x) - glm::half_pi<float>()));
glm::degrees(atan2(targetDirection.y, targetDirection.x) -
glm::half_pi<float>()));
character->controller->setMoveDirection({1.f, 0.f, 0.f});
}
}
if (tryToEnter) {
if (currentOccupant != nullptr && currentOccupant != character) {
// Play the pullout animation and tell the other character to get out.
// Play the pullout animation and tell the other character to get
// out.
character->playActivityAnimation(anm_pullout, false, true);
currentOccupant->controller->setNextActivity(new Activities::ExitVehicle(true));
}
else {
currentOccupant->controller->setNextActivity(
new Activities::ExitVehicle(true));
} else {
character->playActivityAnimation(anm_enter, false, true);
character->enterVehicle(vehicle, seat);
}
@ -314,9 +292,8 @@ bool Activities::EnterVehicle::update(CharacterObject *character, CharacterContr
return false;
}
bool Activities::ExitVehicle::update(CharacterObject *character, CharacterController *controller)
{
bool Activities::ExitVehicle::update(CharacterObject *character,
CharacterController *controller) {
RW_UNUSED(controller);
if (jacked) {
@ -328,8 +305,7 @@ bool Activities::ExitVehicle::update(CharacterObject *character, CharacterContro
if (character->animator->isCompleted(AnimIndexAction)) {
return true;
}
}
else {
} else {
if (character->getCurrentVehicle() == nullptr) return true;
auto vehicle = character->getCurrentVehicle();
@ -346,8 +322,7 @@ bool Activities::ExitVehicle::update(CharacterObject *character, CharacterContro
if (exitPosLocal.x > 0.f) {
character->playActivityAnimation(anm_jacked_rhs, false, true);
}
else {
} else {
character->playActivityAnimation(anm_jacked_lhs, false, true);
}
// No need to open the door, it should already be open.
@ -365,8 +340,7 @@ bool Activities::ExitVehicle::update(CharacterObject *character, CharacterContro
auto anm_exit = character->animations.car_getout_lhs;
if( exitPosLocal.x > 0.f )
{
if (exitPosLocal.x > 0.f) {
anm_exit = character->animations.car_getout_rhs;
}
@ -380,10 +354,8 @@ bool Activities::ExitVehicle::update(CharacterObject *character, CharacterContro
bool isDriver = vehicle->isOccupantDriver(character->getCurrentSeat());
// If the vehicle is going too fast, slow down
if (isDriver)
{
if (!vehicle->canOccupantExit())
{
if (isDriver) {
if (!vehicle->canOccupantExit()) {
vehicle->setBraking(1.f);
return false;
}
@ -391,12 +363,10 @@ bool Activities::ExitVehicle::update(CharacterObject *character, CharacterContro
if (character->animator->getAnimation(AnimIndexAction) == anm_exit) {
if (character->animator->isCompleted(AnimIndexAction)) {
character->enterVehicle(nullptr, seat);
character->setPosition(exitPos);
if (isDriver)
{
if (isDriver) {
// Apply the handbrake
vehicle->setHandbraking(true);
vehicle->setThrottle(0.f);
@ -404,11 +374,9 @@ bool Activities::ExitVehicle::update(CharacterObject *character, CharacterContro
return true;
}
}
else {
} else {
character->playActivityAnimation(anm_exit, false, true);
if( door )
{
if (door) {
vehicle->setPartTarget(door, true, door->openAngle);
}
}
@ -416,11 +384,11 @@ bool Activities::ExitVehicle::update(CharacterObject *character, CharacterContro
return false;
}
#include <engine/GameWorld.hpp>
#include <engine/GameData.hpp>
#include <data/Model.hpp>
bool Activities::ShootWeapon::update(CharacterObject *character, CharacterController *controller)
{
#include <engine/GameData.hpp>
#include <engine/GameWorld.hpp>
bool Activities::ShootWeapon::update(CharacterObject *character,
CharacterController *controller) {
RW_UNUSED(controller);
auto &wepdata = _item->getWeaponData();
@ -429,22 +397,27 @@ bool Activities::ShootWeapon::update(CharacterObject *character, CharacterContro
// Thrown projectiles have lob / throw.
// Update player direction
character->setRotation(glm::angleAxis(character->getLook().x, glm::vec3{0.f, 0.f, 1.f}));
character->setRotation(
glm::angleAxis(character->getLook().x, glm::vec3{0.f, 0.f, 1.f}));
RW_CHECK(wepdata->inventorySlot < maxInventorySlots, "Inventory slot out of bounds");
auto& itemState = character->getCurrentState().weapons[wepdata->inventorySlot];
RW_CHECK(wepdata->inventorySlot < maxInventorySlots,
"Inventory slot out of bounds");
auto &itemState =
character->getCurrentState().weapons[wepdata->inventorySlot];
if (itemState.bulletsClip == 0 && itemState.bulletsTotal > 0) {
itemState.bulletsClip += std::min(int(itemState.bulletsTotal), wepdata->clipSize);
itemState.bulletsClip +=
std::min(int(itemState.bulletsTotal), wepdata->clipSize);
itemState.bulletsTotal -= itemState.bulletsClip;
}
bool hasammo = itemState.bulletsClip > 0;
if (wepdata->fireType == WeaponData::INSTANT_HIT) {
if (_item->isFiring(character) && hasammo) {
auto shootanim = character->engine->data->animations[wepdata->animation1];
auto shootanim =
character->engine->data->animations[wepdata->animation1];
if (shootanim) {
if( character->animator->getAnimation(AnimIndexAction) != shootanim ) {
if (character->animator->getAnimation(AnimIndexAction) !=
shootanim) {
character->playActivityAnimation(shootanim, false, false);
}
@ -452,7 +425,8 @@ bool Activities::ShootWeapon::update(CharacterObject *character, CharacterContro
auto loopend = wepdata->animLoopEnd / 100.f;
auto firetime = wepdata->animFirePoint / 100.f;
auto currID = character->animator->getAnimationTime(AnimIndexAction);
auto currID =
character->animator->getAnimationTime(AnimIndexAction);
if (currID >= firetime && !_fired) {
itemState.bulletsClip--;
@ -460,12 +434,12 @@ bool Activities::ShootWeapon::update(CharacterObject *character, CharacterContro
_fired = true;
}
if (currID > loopend) {
character->animator->setAnimationTime( AnimIndexAction, loopstart );
character->animator->setAnimationTime(AnimIndexAction,
loopstart);
_fired = false;
}
}
}
else {
} else {
if (character->animator->isCompleted(AnimIndexAction)) {
return true;
}
@ -473,17 +447,20 @@ bool Activities::ShootWeapon::update(CharacterObject *character, CharacterContro
}
/// @todo Use Thrown flag instead of project (RPG isn't thrown eg.)
else if (wepdata->fireType == WeaponData::PROJECTILE && hasammo) {
auto shootanim = character->engine->data->animations[wepdata->animation1];
auto throwanim = character->engine->data->animations[wepdata->animation2];
auto shootanim =
character->engine->data->animations[wepdata->animation1];
auto throwanim =
character->engine->data->animations[wepdata->animation2];
if (character->animator->getAnimation(AnimIndexAction) == shootanim) {
if (character->animator->isCompleted(AnimIndexAction)) {
character->playActivityAnimation(throwanim, false, false);
}
}
else if( character->animator->getAnimation(AnimIndexAction) == throwanim ) {
} else if (character->animator->getAnimation(AnimIndexAction) ==
throwanim) {
auto firetime = wepdata->animCrouchFirePoint / 100.f;
auto currID = character->animator->getAnimationTime(AnimIndexAction);
auto currID =
character->animator->getAnimationTime(AnimIndexAction);
if (currID >= firetime && !_fired) {
itemState.bulletsClip--;
@ -493,21 +470,17 @@ bool Activities::ShootWeapon::update(CharacterObject *character, CharacterContro
if (character->animator->isCompleted(AnimIndexAction)) {
return true;
}
}
else {
} else {
character->playActivityAnimation(throwanim, false, true);
}
}
else if( wepdata->fireType == WeaponData::MELEE ) {
RW_CHECK(wepdata->fireType != WeaponData::MELEE, "Melee attacks not implemented");
} else if (wepdata->fireType == WeaponData::MELEE) {
RW_CHECK(wepdata->fireType != WeaponData::MELEE,
"Melee attacks not implemented");
return true;
}
else
{
} else {
RW_ERROR("Unrecognized fireType: " << wepdata->fireType);
return true;
}
return false;
}

View File

@ -11,18 +11,17 @@ class VehicleObject;
/**
* @class CharacterController
* Character Controller Interface, translates high-level behaviours into low level actions.
* Character Controller Interface, translates high-level behaviours into low
* level actions.
*/
class CharacterController
{
class CharacterController {
public:
/**
* @brief The Activity struct interface
*/
struct Activity {
virtual ~Activity() {}
virtual ~Activity() {
}
virtual std::string name() const = 0;
@ -30,16 +29,18 @@ public:
* @brief canSkip
* @return true if the activity can be skipped.
*/
virtual bool canSkip(CharacterObject*, CharacterController*) const { return false; }
virtual bool canSkip(CharacterObject*, CharacterController*) const {
return false;
}
virtual bool update(CharacterObject* character, CharacterController* controller) = 0;
virtual bool update(CharacterObject* character,
CharacterController* controller) = 0;
};
/**
* Available AI goals.
*/
enum Goal
{
enum Goal {
/**
* No goal, will idle or execute external Activities.
*/
@ -55,7 +56,6 @@ public:
};
protected:
/**
* The character being controlled.
*/
@ -75,14 +75,18 @@ protected:
AIGraphNode* targetNode;
public:
CharacterController(CharacterObject* character);
virtual ~CharacterController() { }
virtual ~CharacterController() {
}
Activity* getCurrentActivity() const { return _currentActivity; }
Activity* getCurrentActivity() const {
return _currentActivity;
}
Activity* getNextActivity() const { return _nextActivity; }
Activity* getNextActivity() const {
return _nextActivity;
}
/**
* @brief skipActivity Cancel the current activity immediatley, if possible.
@ -122,16 +126,26 @@ public:
void setRunning(bool run);
void setGoal(Goal goal) { currentGoal = goal; }
Goal getGoal() const { return currentGoal; }
void setGoal(Goal goal) {
currentGoal = goal;
}
Goal getGoal() const {
return currentGoal;
}
void setTargetCharacter(CharacterObject* c) { leader = c; }
CharacterObject* getTargetCharacter() const { return leader; }
void setTargetCharacter(CharacterObject* c) {
leader = c;
}
CharacterObject* getTargetCharacter() const {
return leader;
}
};
#define DECL_ACTIVITY(activity_name) \
static constexpr auto ActivityName = #activity_name; \
std::string name() const { return ActivityName; }
std::string name() const { \
return ActivityName; \
}
// TODO: Refactor this with an ugly macro to reduce code dup.
class WeaponItem;
@ -149,20 +163,23 @@ namespace Activities {
bool sprint;
GoTo(const glm::vec3& target, bool _sprint = false)
: target( target ), sprint(_sprint) {}
: target(target), sprint(_sprint) {
}
bool update(CharacterObject* character, CharacterController* controller);
bool canSkip(CharacterObject *, CharacterController *) const { return true; }
bool canSkip(CharacterObject*, CharacterController*) const {
return true;
}
};
struct Jump : public CharacterController::Activity
{
struct Jump : public CharacterController::Activity {
DECL_ACTIVITY(Jump)
bool jumped;
Jump() : jumped(false) {}
Jump() : jumped(false) {
}
bool update(CharacterObject* character, CharacterController* controller);
};
@ -180,9 +197,11 @@ namespace Activities {
bool entering;
EnterVehicle(VehicleObject* vehicle, int seat = 0)
: vehicle( vehicle ), seat( seat ), entering(false) {}
: vehicle(vehicle), seat(seat), entering(false) {
}
bool canSkip(CharacterObject* character, CharacterController*) const override;
bool canSkip(CharacterObject* character,
CharacterController*) const override;
bool update(CharacterObject* character, CharacterController* controller);
};
@ -192,9 +211,8 @@ namespace Activities {
const bool jacked;
ExitVehicle(bool jacked_ = false)
: jacked(jacked_)
{}
ExitVehicle(bool jacked_ = false) : jacked(jacked_) {
}
bool update(CharacterObject* character, CharacterController* controller);
};
@ -205,8 +223,8 @@ namespace Activities {
WeaponItem* _item;
bool _fired;
ShootWeapon( WeaponItem* item )
: _item(item), _fired(false) {}
ShootWeapon(WeaponItem* item) : _item(item), _fired(false) {
}
bool update(CharacterObject* character, CharacterController* controller);
};

View File

@ -1,12 +1,12 @@
#include <ai/DefaultAIController.hpp>
#include <objects/CharacterObject.hpp>
#include <engine/GameWorld.hpp>
#include <objects/CharacterObject.hpp>
glm::vec3 DefaultAIController::getTargetPosition()
{
glm::vec3 DefaultAIController::getTargetPosition() {
/*if(targetNode) {
if(lastNode && character->getCurrentVehicle()) {
auto nDir = glm::normalize(targetNode->position - lastNode->position);
auto nDir = glm::normalize(targetNode->position -
lastNode->position);
auto right = glm::cross(nDir, glm::vec3(0.f, 0.f, 1.f));
return targetNode->position + right * 2.2f;
}
@ -17,84 +17,71 @@ glm::vec3 DefaultAIController::getTargetPosition()
const float followRadius = 5.f;
void DefaultAIController::update(float dt)
{
switch(currentGoal)
{
case FollowLeader:
{
void DefaultAIController::update(float dt) {
switch (currentGoal) {
case FollowLeader: {
if (!leader) break;
if( getCharacter()->getCurrentVehicle() )
{
if( leader->getCurrentVehicle() != getCharacter()->getCurrentVehicle() )
{
if (getCharacter()->getCurrentVehicle()) {
if (leader->getCurrentVehicle() !=
getCharacter()->getCurrentVehicle()) {
skipActivity();
setNextActivity(new Activities::ExitVehicle);
}
// else we're already in the right spot.
}
else
{
if( leader->getCurrentVehicle() )
{
setNextActivity(new Activities::EnterVehicle(leader->getCurrentVehicle(), 1));
}
else
{
glm::vec3 dir = leader->getPosition() - getCharacter()->getPosition();
if( glm::length(dir) > followRadius )
{
if( glm::distance(gotoPos, leader->getPosition()) > followRadius )
{
gotoPos = leader->getPosition() + ( glm::normalize(-dir) * followRadius * 0.7f );
} else {
if (leader->getCurrentVehicle()) {
setNextActivity(new Activities::EnterVehicle(
leader->getCurrentVehicle(), 1));
} else {
glm::vec3 dir =
leader->getPosition() - getCharacter()->getPosition();
if (glm::length(dir) > followRadius) {
if (glm::distance(gotoPos, leader->getPosition()) >
followRadius) {
gotoPos =
leader->getPosition() +
(glm::normalize(-dir) * followRadius * 0.7f);
skipActivity();
setNextActivity(new Activities::GoTo(gotoPos));
}
}
}
}
}
break;
case TrafficWander:
{
if( targetNode )
{
auto targetDistance = glm::vec2(character->getPosition() - targetNode->position);
if( glm::length(targetDistance) <= 0.1f )
{
} break;
case TrafficWander: {
if (targetNode) {
auto targetDistance =
glm::vec2(character->getPosition() - targetNode->position);
if (glm::length(targetDistance) <= 0.1f) {
// Assign the next target node
auto lastTarget = targetNode;
std::random_device rd;
std::default_random_engine re(rd());
std::uniform_int_distribution<> d(0, lastTarget->connections.size()-1);
std::uniform_int_distribution<> d(
0, lastTarget->connections.size() - 1);
targetNode = lastTarget->connections.at(d(re));
setNextActivity(new Activities::GoTo(targetNode->position));
}
else if ( getCurrentActivity() == nullptr )
{
} else if (getCurrentActivity() == nullptr) {
setNextActivity(new Activities::GoTo(targetNode->position));
}
}
else
{
} else {
// We need to pick an initial node
auto& graph = getCharacter()->engine->aigraph;
AIGraphNode* node = nullptr;
float mindist = std::numeric_limits<float>::max();
for( auto n : graph.nodes )
{
float d = glm::distance( n->position, getCharacter()->getPosition() );
if( d < mindist )
{
for (auto n : graph.nodes) {
float d = glm::distance(n->position,
getCharacter()->getPosition());
if (d < mindist) {
node = n;
mindist = d;
}
}
targetNode = node;
}
}
} break;
default:
break;
default: break;
}
CharacterController::update(dt);

View File

@ -5,13 +5,13 @@
#include <random>
struct AIGraphNode;
class DefaultAIController : public CharacterController
{
class DefaultAIController : public CharacterController {
glm::vec3 gotoPos;
public:
public:
DefaultAIController(CharacterObject* character)
: CharacterController(character) {}
: CharacterController(character) {
}
glm::vec3 getTargetPosition();

View File

@ -1,55 +1,52 @@
#include <ai/PlayerController.hpp>
#include <objects/CharacterObject.hpp>
#include <objects/VehicleObject.hpp>
#include <engine/Animator.hpp>
#include <engine/GameWorld.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <engine/Animator.hpp>
#include <objects/CharacterObject.hpp>
#include <objects/VehicleObject.hpp>
PlayerController::PlayerController(CharacterObject* character)
: CharacterController(character), lastRotation(glm::vec3(0.f, 0.f, 0.f)), _enabled(true)
{
: CharacterController(character)
, lastRotation(glm::vec3(0.f, 0.f, 0.f))
, _enabled(true) {
}
void PlayerController::setInputEnabled(bool enabled)
{
void PlayerController::setInputEnabled(bool enabled) {
_enabled = enabled;
}
bool PlayerController::isInputEnabled() const
{
bool PlayerController::isInputEnabled() const {
return _enabled;
}
void PlayerController::updateCameraDirection(const glm::quat& rot)
{
void PlayerController::updateCameraDirection(const glm::quat& rot) {
cameraRotation = rot;
}
void PlayerController::updateMovementDirection(const glm::vec3& dir, const glm::vec3 &rawdirection)
{
void PlayerController::updateMovementDirection(const glm::vec3& dir,
const glm::vec3& rawdirection) {
if (_currentActivity == nullptr) {
direction = dir;
setMoveDirection(rawdirection);
}
}
void PlayerController::exitVehicle()
{
void PlayerController::exitVehicle() {
if (character->getCurrentVehicle()) {
setNextActivity(new Activities::ExitVehicle());
}
}
void PlayerController::enterNearestVehicle()
{
void PlayerController::enterNearestVehicle() {
if (!character->getCurrentVehicle()) {
auto world = character->engine;
VehicleObject* nearest = nullptr; float d = 10.f;
VehicleObject* nearest = nullptr;
float d = 10.f;
for (auto& p : world->vehiclePool.objects) {
auto object = p.second;
float vd = glm::length( character->getPosition() - object->getPosition());
float vd =
glm::length(character->getPosition() - object->getPosition());
if (vd < d) {
d = vd;
nearest = static_cast<VehicleObject*>(object);
@ -62,20 +59,16 @@ void PlayerController::enterNearestVehicle()
}
}
void PlayerController::update(float dt)
{
void PlayerController::update(float dt) {
CharacterController::update(dt);
}
glm::vec3 PlayerController::getTargetPosition()
{
glm::vec3 PlayerController::getTargetPosition() {
return direction;
}
void PlayerController::jump()
{
void PlayerController::jump() {
if (!character->isInWater()) {
setNextActivity(new Activities::Jump());
}
}

View File

@ -3,8 +3,7 @@
#define _PLAYERCONTROLLER_HPP_
#include <ai/CharacterController.hpp>
class PlayerController : public CharacterController
{
class PlayerController : public CharacterController {
glm::quat cameraRotation;
glm::vec3 direction;
@ -14,7 +13,6 @@ class PlayerController : public CharacterController
bool _enabled;
public:
PlayerController(CharacterObject* character);
/**
@ -26,7 +24,8 @@ public:
void updateCameraDirection(const glm::quat& rot);
void updateMovementDirection(const glm::vec3& pos, const glm::vec3& rawdirection);
void updateMovementDirection(const glm::vec3& pos,
const glm::vec3& rawdirection);
void exitVehicle();
@ -41,7 +40,9 @@ public:
/**
* returns 0 (only one player supported)
*/
int getScriptObjectID() const { return 0; }
int getScriptObjectID() const {
return 0;
}
};
#endif

View File

@ -1,29 +1,31 @@
#include "ai/TrafficDirector.hpp"
#include <ai/AIGraphNode.hpp>
#include <ai/CharacterController.hpp>
#include <engine/GameWorld.hpp>
#include <core/Logger.hpp>
#include <engine/GameState.hpp>
#include <objects/GameObject.hpp>
#include <engine/GameWorld.hpp>
#include <objects/CharacterObject.hpp>
#include <objects/GameObject.hpp>
#include <objects/VehicleObject.hpp>
#include <render/ViewCamera.hpp>
#include <core/Logger.hpp>
#include <glm/gtx/string_cast.hpp>
#include <glm/gtx/norm.hpp>
#include <glm/gtx/string_cast.hpp>
#ifdef RW_WINDOWS
#include <rw_mingw.hpp>
#endif
TrafficDirector::TrafficDirector(AIGraph* g, GameWorld* w)
: graph( g ), world( w ), pedDensity(1.f), carDensity(1.f),
maximumPedestrians(20), maximumCars(10)
{
: graph(g)
, world(w)
, pedDensity(1.f)
, carDensity(1.f)
, maximumPedestrians(20)
, maximumCars(10) {
}
std::vector< AIGraphNode* > TrafficDirector::findAvailableNodes(AIGraphNode::NodeType type, const ViewCamera& camera, float radius)
{
std::vector<AIGraphNode*> TrafficDirector::findAvailableNodes(
AIGraphNode::NodeType type, const ViewCamera& camera, float radius) {
std::vector<AIGraphNode*> available;
available.reserve(20);
@ -33,28 +35,31 @@ std::vector< AIGraphNode* > TrafficDirector::findAvailableNodes(AIGraphNode::Nod
float minDist = (10.f / density) * (10.f / density);
float halfRadius2 = std::pow(radius / 2.f, 2.f);
// Check if any of the nearby nodes are blocked by a pedestrian standing on it
// Check if any of the nearby nodes are blocked by a pedestrian standing on
// it
// or because it's inside the view frustum
for (auto it = available.begin(); it != available.end();) {
bool blocked = false;
float dist2 = glm::distance2(camera.position, (*it)->position);
for (auto& obj : world->pedestrianPool.objects) {
if (glm::distance2( (*it)->position, obj.second->getPosition() ) <= minDist) {
if (glm::distance2((*it)->position, obj.second->getPosition()) <=
minDist) {
blocked = true;
break;
}
}
// Check that we're not going to spawn something right where the player is looking
if (dist2 <= halfRadius2 && camera.frustum.intersects((*it)->position, 1.f)) {
// Check that we're not going to spawn something right where the player
// is looking
if (dist2 <= halfRadius2 &&
camera.frustum.intersects((*it)->position, 1.f)) {
blocked = true;
}
if (blocked) {
it = available.erase(it);
}
else {
} else {
it++;
}
}
@ -62,10 +67,8 @@ std::vector< AIGraphNode* > TrafficDirector::findAvailableNodes(AIGraphNode::Nod
return available;
}
void TrafficDirector::setDensity(AIGraphNode::NodeType type, float density)
{
switch ( type )
{
void TrafficDirector::setDensity(AIGraphNode::NodeType type, float density) {
switch (type) {
case AIGraphNode::Vehicle:
carDensity = density;
break;
@ -75,9 +78,10 @@ void TrafficDirector::setDensity(AIGraphNode::NodeType type, float density)
}
}
std::vector<GameObject*> TrafficDirector::populateNearby(const ViewCamera& camera, float radius, int maxSpawn)
{
int availablePeds = maximumPedestrians - world->pedestrianPool.objects.size();
std::vector<GameObject*> TrafficDirector::populateNearby(
const ViewCamera& camera, float radius, int maxSpawn) {
int availablePeds =
maximumPedestrians - world->pedestrianPool.objects.size();
std::vector<GameObject*> created;
@ -117,8 +121,7 @@ std::vector<GameObject*> TrafficDirector::populateNearby(const ViewCamera& camer
auto type = AIGraphNode::Pedestrian;
auto available = findAvailableNodes(type, camera, radius);
if( availablePeds <= 0 )
{
if (availablePeds <= 0) {
// We have already reached the limit of spawned traffic
return {};
}
@ -132,28 +135,24 @@ std::vector<GameObject*> TrafficDirector::populateNearby(const ViewCamera& camer
int counter = availablePeds;
// maxSpawn can be -1 for "as many as possible"
if( maxSpawn > -1 )
{
if (maxSpawn > -1) {
counter = std::min(availablePeds, maxSpawn);
}
for ( AIGraphNode* spawn : available )
{
if( spawn->type != AIGraphNode::Pedestrian )
{
for (AIGraphNode* spawn : available) {
if (spawn->type != AIGraphNode::Pedestrian) {
continue;
}
if ( counter > -1 )
{
if ( counter == 0 )
{
if (counter > -1) {
if (counter == 0) {
break;
}
counter--;
}
// Spawn a pedestrian from the available pool
auto ped = world->createPedestrian(validPeds[d(re)], spawn->position + glm::vec3( 0.f, 0.f, 1.f ) );
auto ped = world->createPedestrian(
validPeds[d(re)], spawn->position + glm::vec3(0.f, 0.f, 1.f));
ped->setLifetime(GameObject::TrafficLifetime);
ped->controller->setGoal(CharacterController::TrafficWander);
created.push_back(ped);
@ -164,9 +163,7 @@ std::vector<GameObject*> TrafficDirector::populateNearby(const ViewCamera& camer
return created;
}
void TrafficDirector::setPopulationLimits(int maxPeds, int maxCars)
{
void TrafficDirector::setPopulationLimits(int maxPeds, int maxCars) {
maximumPedestrians = maxPeds;
maximumCars = maxCars;
}

View File

@ -11,13 +11,13 @@ class GameObject;
class GameWorld;
class ViewCamera;
class TrafficDirector
{
class TrafficDirector {
public:
TrafficDirector(AIGraph* graph, GameWorld* world);
std::vector< AIGraphNode* > findAvailableNodes(AIGraphNode::NodeType type, const ViewCamera& camera, float radius);
std::vector<AIGraphNode*> findAvailableNodes(AIGraphNode::NodeType type,
const ViewCamera& camera,
float radius);
void setDensity(AIGraphNode::NodeType type, float density);
@ -27,7 +27,8 @@ public:
* @param radius the maximum distance to spawn in
* @param max The maximum number of traffic to create.
*/
std::vector<GameObject*> populateNearby( const ViewCamera& camera, float radius, int maxSpawn = -1 );
std::vector<GameObject*> populateNearby(const ViewCamera& camera,
float radius, int maxSpawn = -1);
/**
* Sets the maximum number of pedestrians and cars in the traffic system