mirror of
https://github.com/rwengine/openrw.git
synced 2024-11-07 03:12:36 +01:00
Add AI Goal system, FollowLeader goal.
+ Add support for setting leader, e.g. Misty follows you during "Luigi's Girls".
This commit is contained in:
parent
0c84873be2
commit
3f40ba0e18
@ -28,6 +28,21 @@ public:
|
||||
virtual bool update(CharacterObject* character, CharacterController* controller) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Available AI goals.
|
||||
*/
|
||||
enum Goal
|
||||
{
|
||||
/**
|
||||
* No goal, will idle or execute external Activities.
|
||||
*/
|
||||
None,
|
||||
/**
|
||||
* Keep close to leader character
|
||||
*/
|
||||
FollowLeader
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
@ -45,6 +60,10 @@ protected:
|
||||
|
||||
bool running;
|
||||
|
||||
// Goal related variables
|
||||
Goal currentGoal;
|
||||
CharacterObject* leader;
|
||||
|
||||
public:
|
||||
|
||||
CharacterController(CharacterObject* character);
|
||||
@ -90,6 +109,12 @@ public:
|
||||
void setRawMovement(const glm::vec3& movement);
|
||||
|
||||
void setRunning(bool run);
|
||||
|
||||
void setGoal(Goal goal) { currentGoal = goal; }
|
||||
Goal getGoal() const { return currentGoal; }
|
||||
|
||||
void setTargetCharacter(CharacterObject* c) { leader = c; }
|
||||
CharacterObject* getTargetCharacter() const { return leader; }
|
||||
};
|
||||
|
||||
#define DECL_ACTIVITY( activity_name ) \
|
||||
|
@ -7,12 +7,15 @@
|
||||
struct AIGraphNode;
|
||||
class DefaultAIController : public CharacterController
|
||||
{
|
||||
glm::vec3 gotoPos;
|
||||
public:
|
||||
|
||||
DefaultAIController(CharacterObject* character)
|
||||
: CharacterController(character) {}
|
||||
|
||||
glm::vec3 getTargetPosition();
|
||||
|
||||
virtual void update(float dt);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -24,7 +24,8 @@ void CharacterController::setActivity(CharacterController::Activity* activity)
|
||||
}
|
||||
|
||||
CharacterController::CharacterController(CharacterObject* character)
|
||||
: character(character), _currentActivity(nullptr), _nextActivity(nullptr), running(false)
|
||||
: character(character), _currentActivity(nullptr), _nextActivity(nullptr), running(false),
|
||||
currentGoal(None), leader(nullptr)
|
||||
{
|
||||
character->controller = this;
|
||||
}
|
||||
@ -128,6 +129,9 @@ void CharacterController::update(float dt)
|
||||
}
|
||||
}
|
||||
|
||||
// Reset raw movement between activity updates.
|
||||
setRawMovement(glm::vec3());
|
||||
|
||||
if( updateActivity() ) {
|
||||
if( _currentActivity ) {
|
||||
delete _currentActivity;
|
||||
|
@ -14,3 +14,49 @@ glm::vec3 DefaultAIController::getTargetPosition()
|
||||
}*/
|
||||
return glm::vec3();
|
||||
}
|
||||
|
||||
const float followRadius = 5.f;
|
||||
|
||||
void DefaultAIController::update(float dt)
|
||||
{
|
||||
switch(currentGoal)
|
||||
{
|
||||
case FollowLeader:
|
||||
{
|
||||
if( ! leader ) break;
|
||||
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 );
|
||||
skipActivity();
|
||||
setNextActivity(new Activities::GoTo(gotoPos));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
CharacterController::update(dt);
|
||||
}
|
||||
|
@ -81,7 +81,7 @@ void CharacterObject::createActor(const glm::vec3& size)
|
||||
physShape = new btCapsuleShapeZ(size.x, size.z);
|
||||
physObject->setCollisionShape(physShape);
|
||||
physObject->setCollisionFlags(btCollisionObject::CF_KINEMATIC_OBJECT);
|
||||
physCharacter = new btKinematicCharacterController(physObject, physShape, 0.2f, 2);
|
||||
physCharacter = new btKinematicCharacterController(physObject, physShape, 0.1f, 2);
|
||||
physCharacter->setVelocityForTimeInterval(btVector3(1.f, 1.f, 0.f), 1.f);
|
||||
physCharacter->setGravity(engine->dynamicsWorld->getGravity().length());
|
||||
physCharacter->setJumpSpeed(5.f);
|
||||
|
@ -572,6 +572,15 @@ void game_character_exit_vehicle(const ScriptArguments& args)
|
||||
}
|
||||
}
|
||||
|
||||
void game_character_follow_character(const ScriptArguments& args)
|
||||
{
|
||||
auto controller = (CharacterController*)(*args[0].handle);
|
||||
auto leader = (CharacterController*)(*args[1].handle);
|
||||
|
||||
controller->setGoal(CharacterController::FollowLeader);
|
||||
controller->setTargetCharacter(leader->getCharacter());
|
||||
}
|
||||
|
||||
void game_navigate_on_foot(const ScriptArguments& args)
|
||||
{
|
||||
auto controller = (CharacterController*)(*args[0].handle);
|
||||
@ -867,7 +876,7 @@ ObjectModule::ObjectModule()
|
||||
bindFunction(0x01D4, game_enter_as_passenger, 2, "Character Enter Vehicle as Passenger" );
|
||||
bindFunction(0x01D3, game_character_exit_vehicle, 2, "Character Exit Vehicle" );
|
||||
|
||||
bindUnimplemented( 0x01DF, game_character_follow_character, 2, "Make Character Follow Character" );
|
||||
bindFunction(0x01DF, game_character_follow_character, 2, "Make Character Follow Character");
|
||||
|
||||
bindFunction(0x01F3, game_vehicle_in_air, 1, "Is Vehicle In Air" );
|
||||
bindFunction(0x01F4, game_vehicle_flipped, 1, "Is Car Flipped" );
|
||||
|
@ -78,6 +78,14 @@ DebugState::DebugState(RWGame* game, const glm::vec3& vp, const glm::quat& vd)
|
||||
m->addEntry(Menu::lambda("Jump to Hospital", [=] {
|
||||
jumpCharacter(game, game->getWorld()->state.player, glm::vec3(1123.77, -569.15, 100.0));
|
||||
}, entryHeight));
|
||||
m->addEntry(Menu::lambda("Add Follower", [=] {
|
||||
auto spawnPos = game->getWorld()->state.player->getCharacter()->getPosition();
|
||||
spawnPos += game->getWorld()->state.player->getCharacter()->getRotation() * glm::vec3(-1.f, 0.f, 0.f);
|
||||
auto follower = game->getWorld()->createPedestrian(12, spawnPos);
|
||||
jumpCharacter(game, follower->controller, spawnPos);
|
||||
follower->controller->setGoal(CharacterController::FollowLeader);
|
||||
follower->controller->setTargetCharacter(game->getWorld()->state.player->getCharacter());
|
||||
}, entryHeight));
|
||||
|
||||
this->enterMenu(m);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user