Skip to content

Commit

Permalink
[Ready] Payphones (#498)
Browse files Browse the repository at this point in the history
Payphones
  • Loading branch information
husho authored and darkf committed Jun 18, 2018
1 parent 81781a5 commit 6d04746
Show file tree
Hide file tree
Showing 15 changed files with 474 additions and 106 deletions.
2 changes: 2 additions & 0 deletions rwengine/CMakeLists.txt
Expand Up @@ -63,6 +63,8 @@ set(RWENGINE_SOURCES
src/engine/GameWorld.hpp
src/engine/GarageController.cpp
src/engine/GarageController.hpp
src/engine/Payphone.cpp
src/engine/Payphone.hpp
src/engine/SaveGame.cpp
src/engine/SaveGame.hpp
src/engine/ScreenText.cpp
Expand Down
42 changes: 41 additions & 1 deletion rwengine/src/ai/PlayerController.cpp
Expand Up @@ -4,18 +4,22 @@

#include <glm/gtc/quaternion.hpp>

#include "engine/Animator.hpp"
#include "engine/GameState.hpp"
#include "engine/GameWorld.hpp"
#include "objects/CharacterObject.hpp"
#include "objects/GameObject.hpp"
#include "objects/VehicleObject.hpp"

class Animator;

PlayerController::PlayerController()
: CharacterController()
, lastRotation(glm::vec3(0.f, 0.f, 0.f))
, missionRestartRequired(false)
, _enabled(true)
, restartState(Alive) {
, restartState(Alive)
, payphoneState(Left) {
}

void PlayerController::setInputEnabled(bool enabled) {
Expand Down Expand Up @@ -275,6 +279,42 @@ void PlayerController::restartLogic() {
}
}

void PlayerController::pickUpPayphone() {
payphoneState = PayphoneState::PickingUp;

character->animator->playAnimation(
AnimIndexMovement, character->animations->animation(AnimCycle::PhoneIn),
1.f, false);
}

void PlayerController::hangUpPayphone() {
payphoneState = PayphoneState::HangingUp;

character->animator->playAnimation(
AnimIndexMovement,
character->animations->animation(AnimCycle::PhoneOut), 1.f, false);
}

void PlayerController::talkOnPayphone() {
payphoneState = PayphoneState::Talking;
}

void PlayerController::leavePayphone() {
payphoneState = Left;
}

bool PlayerController::isPickingUpPayphone() const {
return payphoneState == PayphoneState::PickingUp;
}

bool PlayerController::isHangingUpPayphone() const {
return payphoneState == PayphoneState::HangingUp;
}

bool PlayerController::isTalkingOnPayphone() const {
return payphoneState == PayphoneState::Talking;
}

void PlayerController::update(float dt) {
restartLogic();

Expand Down
24 changes: 24 additions & 0 deletions rwengine/src/ai/PlayerController.hpp
Expand Up @@ -6,6 +6,7 @@
#include <glm/gtc/quaternion.hpp>

class PlayerController : public CharacterController {
private:
glm::quat cameraRotation{1.0f, 0.0f, 0.0f, 0.0f};

glm::vec3 direction{};
Expand All @@ -26,6 +27,13 @@ class PlayerController : public CharacterController {
FadingIn,
} restartState;

enum PayphoneState {
Left,
Talking,
PickingUp,
HangingUp,
} payphoneState;

// handles player respawn logic
void restartLogic();

Expand Down Expand Up @@ -58,6 +66,22 @@ class PlayerController : public CharacterController {
// @todo not implemented yet
bool isBusted() const;

// Play payphone pick up anim
void pickUpPayphone();
// Play payphone hang up anim
void hangUpPayphone();
// Play talking on payphone anim
void talkOnPayphone();
// Reset any payphone anim
void leavePayphone();

// Is payphone pick up anim playing
bool isPickingUpPayphone() const;
// Is payphone hang up anim playing
bool isHangingUpPayphone() const;
// Is talking on payphone anim playing
bool isTalkingOnPayphone() const;

void update(float dt) override;

glm::vec3 getTargetPosition() override;
Expand Down
8 changes: 7 additions & 1 deletion rwengine/src/engine/GameWorld.cpp
Expand Up @@ -459,6 +459,12 @@ GarageInfo* GameWorld::createGarage(const glm::vec3 coord0,
return info;
}

Payphone* GameWorld::createPayphone(const glm::vec2 coord) {
int id = payphones.size();
payphones.emplace_back(make_unique<Payphone>(this, id, coord));
return payphones.back().get();
}

void GameWorld::ObjectPool::insert(GameObject* object) {
if (object->getGameObjectID() == 0) {
// Find the lowest free GameObjectID.
Expand Down Expand Up @@ -1031,4 +1037,4 @@ PlayerController* GameWorld::getPlayer() {
return static_cast<PlayerController*>(controller);
}
return nullptr;
}
}
9 changes: 9 additions & 0 deletions rwengine/src/engine/GameWorld.hpp
Expand Up @@ -18,6 +18,7 @@
#include <audio/SoundManager.hpp>

#include <engine/GarageController.hpp>
#include <engine/Payphone.hpp>
#include <objects/ObjectTypes.hpp>

#include <render/VisualFX.hpp>
Expand All @@ -35,6 +36,7 @@ struct btDbvtBroadphase;

class GameState;
class GarageController;
class Payphone;

class PlayerController;
class Logger;
Expand Down Expand Up @@ -151,6 +153,11 @@ class GameWorld {
GarageInfo* createGarage(const glm::vec3 coord0, const glm::vec3 coord1,
const int type);

/**
* Creates a payphone
*/
Payphone* createPayphone(const glm::vec2 coord);

/**
* Destroys an existing Object
*/
Expand Down Expand Up @@ -266,6 +273,8 @@ class GameWorld {

std::vector<std::unique_ptr<GarageController>> garageControllers;

std::vector<std::unique_ptr<Payphone>> payphones;

/**
* @brief getBlipTarget
* @param blip
Expand Down
127 changes: 127 additions & 0 deletions rwengine/src/engine/Payphone.cpp
@@ -0,0 +1,127 @@
#include "engine/Payphone.hpp"

#include <rw/defines.hpp>

#include "ai/PlayerController.hpp"

#include "engine/GameState.hpp"
#include "engine/GameWorld.hpp"

#include "objects/CharacterObject.hpp"
#include "objects/GameObject.hpp"
#include "objects/InstanceObject.hpp"

Payphone::Payphone(GameWorld* engine_, const int id_, const glm::vec2 coord)
: engine(engine_), id(id_) {
// Find payphone object, original game does this differently
for (const auto& p : engine->instancePool.objects) {
auto o = p.second;
if (!o->getModel()) {
continue;
}
if (o->getModelInfo<BaseModelInfo>()->name != "phonebooth1") {
continue;
}
if (glm::distance(coord, glm::vec2(o->getPosition())) < 2.f) {
object = static_cast<InstanceObject*>(o);
break;
}
}

message.clear();

if (object) {
position = object->getPosition();
}
}

void Payphone::enable() {
state = State::Ringing;
}

void Payphone::disable() {
state = State::Idle;
}

bool Payphone::isTalking() const {
return state == State::Talking;
}

void Payphone::setMessageAndStartRinging(const std::string& m) {
state = State::Ringing;
message = m;
}

void Payphone::tick(float dt) {
RW_UNUSED(dt);

switch (state) {
case State::Idle: {
break;
}

case State::Ringing: {
if (glm::distance(
position,
engine->getPlayer()->getCharacter()->getPosition()) < 1.f) {
state = State::PickingUp;

engine->getPlayer()->pickUpPayphone();

engine->state->isCinematic = true;
engine->getPlayer()->prepareForCutscene();

engine->getPlayer()->getCharacter()->setHeading(glm::degrees(
glm::atan(position.x, position.y) + glm::half_pi<float>()));
}

// @todo Do wiggle animation

break;
}

case State::PickingUp: {
if (!engine->getPlayer()->isPickingUpPayphone()) {
state = State::Talking;

if (!message.empty()) {
const auto& text =
ScreenText::format(engine->data->texts.text(message));

engine->state->text.clear<ScreenTextType::HighPriority>();
engine->state->text.addText<ScreenTextType::HighPriority>(
ScreenTextEntry::makeHighPriority(message, text, 3000));

message.clear();
}

callTimer = engine->getGameTime() + 3.f;
}

break;
}

case State::Talking: {
if (callTimer <= engine->getGameTime()) {
state = State::HangingUp;

engine->getPlayer()->hangUpPayphone();
}

break;
}

case State::HangingUp: {
if (!engine->getPlayer()->isHangingUpPayphone()) {
state = State::Idle;

engine->state->isCinematic = false;
engine->getPlayer()->freeFromCutscene();
}

break;
}

default: { break; }
}
}
49 changes: 49 additions & 0 deletions rwengine/src/engine/Payphone.hpp
@@ -0,0 +1,49 @@
#ifndef _RWENGINE_PAYPHONE_HPP_
#define _RWENGINE_PAYPHONE_HPP_

#include <glm/glm.hpp>
#include <string>

class PlayerController;

class GameWorld;
class GameState;

class GameObject;
class InstanceObject;
class CharacterObject;

class Payphone {
private:
InstanceObject* object;
glm::vec3 position;
GameWorld* engine;
float callTimer = 0.f;
std::string message;

public:
enum class State { Idle, Ringing, PickingUp, Talking, HangingUp };

State state = State::Idle;

int id;

int getScriptObjectID() const {
return id;
}

Payphone(GameWorld* engine_, const int id_, const glm::vec2 coord);
~Payphone() = default;

// Makes a payphone ring
void enable();
// Disables ringing
void disable();
// Is currently used by player
bool isTalking() const;
// Sets a message and makes a payphone ring
void setMessageAndStartRinging(const std::string& m);
void tick(float dt);
};

#endif

0 comments on commit 6d04746

Please sign in to comment.