mirror of
https://github.com/rwengine/openrw.git
synced 2024-09-15 15:02:34 +02:00
Merge pull request #446 from husho/respawn
[Ready] Respawn functionality
This commit is contained in:
commit
b77ca47fd4
@ -4,6 +4,7 @@
|
||||
|
||||
#include <glm/gtc/quaternion.hpp>
|
||||
|
||||
#include "engine/GameState.hpp"
|
||||
#include "engine/GameWorld.hpp"
|
||||
#include "objects/CharacterObject.hpp"
|
||||
#include "objects/GameObject.hpp"
|
||||
@ -12,7 +13,9 @@
|
||||
PlayerController::PlayerController()
|
||||
: CharacterController()
|
||||
, lastRotation(glm::vec3(0.f, 0.f, 0.f))
|
||||
, _enabled(true) {
|
||||
, missionRestartRequired(false)
|
||||
, _enabled(true)
|
||||
, restartState(Alive) {
|
||||
}
|
||||
|
||||
void PlayerController::setInputEnabled(bool enabled) {
|
||||
@ -58,12 +61,210 @@ void PlayerController::enterNearestVehicle() {
|
||||
}
|
||||
|
||||
if (nearest) {
|
||||
setNextActivity(std::make_unique<Activities::EnterVehicle>(nearest, 0));
|
||||
setNextActivity(
|
||||
std::make_unique<Activities::EnterVehicle>(nearest, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PlayerController::requestMissionRestart() {
|
||||
missionRestartRequired = true;
|
||||
}
|
||||
|
||||
bool PlayerController::isMissionRestartRequired() const {
|
||||
return missionRestartRequired;
|
||||
}
|
||||
|
||||
bool PlayerController::isWasted() const {
|
||||
return character->isDead();
|
||||
}
|
||||
|
||||
bool PlayerController::isBusted() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
void PlayerController::restart() {
|
||||
GameWorld* world = character->engine;
|
||||
GameState* state = character->engine->state;
|
||||
|
||||
glm::vec3 restartPosition;
|
||||
float restartHeading = 0.f;
|
||||
|
||||
if (state->overrideNextRestart) {
|
||||
restartPosition = glm::vec3(state->nextRestartLocation);
|
||||
restartHeading = state->nextRestartLocation.w;
|
||||
} else {
|
||||
GameState::RestartType type;
|
||||
|
||||
if (isBusted()) {
|
||||
type = GameState::RestartType::Police;
|
||||
}
|
||||
|
||||
if (isWasted()) {
|
||||
type = GameState::RestartType::Hospital;
|
||||
}
|
||||
|
||||
glm::vec4 closestRestart =
|
||||
state->getClosestRestart(type, character->getPosition());
|
||||
restartPosition = glm::vec3(closestRestart);
|
||||
restartHeading = closestRestart.w;
|
||||
}
|
||||
|
||||
if (isWasted()) {
|
||||
if (!state->playerInfo.singlePayerHealthcare) {
|
||||
if (state->playerInfo.money >= 1000) {
|
||||
state->playerInfo.money -= 1000;
|
||||
} else {
|
||||
state->playerInfo.money = 0;
|
||||
}
|
||||
} else {
|
||||
state->playerInfo.singlePayerHealthcare = false;
|
||||
}
|
||||
|
||||
state->gameStats.timesHospital++;
|
||||
}
|
||||
|
||||
if (isBusted()) {
|
||||
if (!state->playerInfo.thaneOfLibertyCity) {
|
||||
// @todo implement wanted system
|
||||
uint8_t wantedLevel = 0;
|
||||
uint32_t penalty = 0;
|
||||
|
||||
switch (wantedLevel) {
|
||||
case 0:
|
||||
penalty = 100;
|
||||
break;
|
||||
case 1:
|
||||
penalty = 100;
|
||||
break;
|
||||
case 2:
|
||||
penalty = 200;
|
||||
break;
|
||||
case 3:
|
||||
penalty = 400;
|
||||
break;
|
||||
case 4:
|
||||
penalty = 600;
|
||||
break;
|
||||
case 5:
|
||||
penalty = 900;
|
||||
break;
|
||||
case 6:
|
||||
penalty = 1500;
|
||||
break;
|
||||
}
|
||||
|
||||
if (state->playerInfo.money >= penalty) {
|
||||
state->playerInfo.money -= penalty;
|
||||
} else {
|
||||
state->playerInfo.money = 0;
|
||||
}
|
||||
} else {
|
||||
state->playerInfo.thaneOfLibertyCity = false;
|
||||
}
|
||||
|
||||
state->gameStats.timesBusted++;
|
||||
}
|
||||
|
||||
// Clean up mission restart
|
||||
missionRestartRequired = false;
|
||||
|
||||
// Clean up overrides
|
||||
state->hospitalIslandOverride = 0;
|
||||
state->policeIslandOverride = 0;
|
||||
|
||||
// Set position and heading for any restart
|
||||
character->setPosition(restartPosition);
|
||||
character->setHeading(restartHeading);
|
||||
|
||||
if (isWasted() || isBusted()) {
|
||||
// Advance 12 hours
|
||||
world->offsetGameTime(60 * 12);
|
||||
|
||||
character->getCurrentState().health = 100.f;
|
||||
// Reset dying state
|
||||
character->getCurrentState().isDying = false;
|
||||
character->getCurrentState().isDead = false;
|
||||
|
||||
// Remove weapons
|
||||
character->clearInventory();
|
||||
}
|
||||
}
|
||||
|
||||
void PlayerController::restartLogic() {
|
||||
GameWorld* world = character->engine;
|
||||
GameState* state = character->engine->state;
|
||||
|
||||
switch (restartState) {
|
||||
case Alive: {
|
||||
if (isWasted() || isBusted() || isMissionRestartRequired()) {
|
||||
state->fade(2000 / 1000.f, false);
|
||||
|
||||
restartState = FadingIn;
|
||||
}
|
||||
|
||||
if (isWasted()) {
|
||||
state->setFadeColour(glm::i32vec3(0xc8, 0xc8, 0xc8));
|
||||
|
||||
// Show "wasted" text
|
||||
const auto& gxtEntry = "DEAD";
|
||||
const auto& text = world->data->texts.text(gxtEntry);
|
||||
state->text.addText<ScreenTextType::Big>(
|
||||
ScreenTextEntry::makeBig(gxtEntry, text, 3, 4000));
|
||||
}
|
||||
|
||||
if (isBusted()) {
|
||||
state->setFadeColour(glm::i32vec3(0x00, 0x00, 0x00));
|
||||
|
||||
// Show "busted" text
|
||||
const auto& gxtEntry = "BUSTED";
|
||||
const auto& text = world->data->texts.text(gxtEntry);
|
||||
state->text.addText<ScreenTextType::Big>(
|
||||
ScreenTextEntry::makeBig(gxtEntry, text, 3, 5000));
|
||||
}
|
||||
|
||||
if (isMissionRestartRequired()) {
|
||||
state->setFadeColour(glm::i32vec3(0x00, 0x00, 0x00));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case FadingIn: {
|
||||
if (!state->isFading()) {
|
||||
restartState = Restarting;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case Restarting: {
|
||||
state->fade(4000 / 1000.f, true);
|
||||
|
||||
if (isWasted()) {
|
||||
state->setFadeColour(glm::i32vec3(0xc8, 0xc8, 0xc8));
|
||||
}
|
||||
|
||||
if (isBusted() || isMissionRestartRequired()) {
|
||||
state->setFadeColour(glm::i32vec3(0x00, 0x00, 0x00));
|
||||
}
|
||||
|
||||
restart();
|
||||
|
||||
restartState = FadingOut;
|
||||
|
||||
break;
|
||||
}
|
||||
case FadingOut: {
|
||||
if (!state->isFading()) {
|
||||
restartState = Alive;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PlayerController::update(float dt) {
|
||||
restartLogic();
|
||||
CharacterController::update(dt);
|
||||
}
|
||||
|
||||
|
@ -1,19 +1,33 @@
|
||||
#ifndef _RWENGINE_PLAYERCONTROLLER_HPP_
|
||||
#define _RWENGINE_PLAYERCONTROLLER_HPP_
|
||||
|
||||
#include <ai/CharacterController.hpp>
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/quaternion.hpp>
|
||||
#include <ai/CharacterController.hpp>
|
||||
|
||||
class PlayerController : public CharacterController {
|
||||
glm::quat cameraRotation{1.0f,0.0f,0.0f,0.0f};
|
||||
glm::quat cameraRotation{1.0f, 0.0f, 0.0f, 0.0f};
|
||||
|
||||
glm::vec3 direction{};
|
||||
|
||||
glm::quat lastRotation;
|
||||
|
||||
bool missionRestartRequired;
|
||||
|
||||
bool _enabled;
|
||||
|
||||
enum RestartState {
|
||||
Alive,
|
||||
FadingIn,
|
||||
Restarting,
|
||||
FadingOut,
|
||||
} restartState;
|
||||
|
||||
// handles player respawn logic
|
||||
void restartLogic();
|
||||
|
||||
void restart();
|
||||
|
||||
public:
|
||||
PlayerController();
|
||||
|
||||
@ -33,6 +47,14 @@ public:
|
||||
|
||||
void enterNearestVehicle();
|
||||
|
||||
void requestMissionRestart();
|
||||
|
||||
bool isMissionRestartRequired() const;
|
||||
|
||||
bool isWasted() const;
|
||||
// @todo not implemented yet
|
||||
bool isBusted() const;
|
||||
|
||||
void update(float dt) override;
|
||||
|
||||
glm::vec3 getTargetPosition() override;
|
||||
|
@ -99,7 +99,12 @@ GameState::GameState()
|
||||
, maxWantedLevel(0)
|
||||
, playerObject(0)
|
||||
, scriptOnMissionFlag(nullptr)
|
||||
, overrideNextRestart(false)
|
||||
, nextRestartLocation{}
|
||||
, hospitalRestarts{}
|
||||
, policeRestarts{}
|
||||
, hospitalIslandOverride(false)
|
||||
, policeIslandOverride(false)
|
||||
, fadeOut(true)
|
||||
, fadeStart(0.f)
|
||||
, fadeTime(0.f)
|
||||
@ -114,7 +119,7 @@ GameState::GameState()
|
||||
, cameraNear(0.1f)
|
||||
, cameraFixed(false)
|
||||
, cameraPosition{}
|
||||
, cameraRotation{1.0f,0.0f,0.0f,0.0f}
|
||||
, cameraRotation{1.0f, 0.0f, 0.0f, 0.0f}
|
||||
, cameraTarget(0)
|
||||
, importExportPortland(0)
|
||||
, importExportShoreside(0)
|
||||
@ -125,7 +130,7 @@ GameState::GameState()
|
||||
|
||||
int GameState::addRadarBlip(BlipData& blip) {
|
||||
int l = 0;
|
||||
for (const auto &radarBlip : radarBlips) {
|
||||
for (const auto& radarBlip : radarBlips) {
|
||||
if ((radarBlip.first) != l) {
|
||||
l = radarBlip.first - 1;
|
||||
} else {
|
||||
@ -145,3 +150,70 @@ void GameState::removeBlip(int blip) {
|
||||
radarBlips.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
void GameState::addHospitalRestart(const glm::vec4 location) {
|
||||
hospitalRestarts.push_back(location);
|
||||
}
|
||||
|
||||
void GameState::addPoliceRestart(const glm::vec4 location) {
|
||||
policeRestarts.push_back(location);
|
||||
}
|
||||
|
||||
void GameState::overrideRestart(const glm::vec4 location) {
|
||||
overrideNextRestart = true;
|
||||
nextRestartLocation = location;
|
||||
}
|
||||
|
||||
void GameState::cancelRestartOverride() {
|
||||
overrideNextRestart = false;
|
||||
}
|
||||
|
||||
const glm::vec4 GameState::getClosestRestart(
|
||||
RestartType type, const glm::vec3 playerPosition) const {
|
||||
float closest = 10000.f;
|
||||
glm::vec4 result;
|
||||
|
||||
ZoneData* playerZone = world->data->findZoneAt(playerPosition);
|
||||
|
||||
const std::vector<glm::vec4>* iter = nullptr;
|
||||
int islandOverride = 0;
|
||||
|
||||
if (type == Hospital) {
|
||||
iter = &hospitalRestarts;
|
||||
islandOverride = hospitalIslandOverride;
|
||||
} else if (type == Police) {
|
||||
iter = &policeRestarts;
|
||||
islandOverride = policeIslandOverride;
|
||||
}
|
||||
|
||||
for (auto& location : *iter) {
|
||||
glm::vec3 location3d(location);
|
||||
|
||||
ZoneData* restartZone = world->data->findZoneAt(location3d);
|
||||
|
||||
if ((playerZone->island == restartZone->island &&
|
||||
islandOverride != 0) ||
|
||||
islandOverride == 0) {
|
||||
if (glm::distance(location3d, playerPosition) < closest) {
|
||||
result = location;
|
||||
closest = glm::distance(location3d, playerPosition);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void GameState::fade(float time, bool f) {
|
||||
fadeTime = time;
|
||||
fadeOut = f;
|
||||
fadeStart = world->getGameTime();
|
||||
}
|
||||
|
||||
bool GameState::isFading() const {
|
||||
return world->getGameTime() < fadeStart + fadeTime;
|
||||
}
|
||||
|
||||
void GameState::setFadeColour(glm::i32vec3 colour) {
|
||||
fadeColour = colour;
|
||||
}
|
@ -2,8 +2,8 @@
|
||||
#define _RWENGINE_GAMESTATE_HPP_
|
||||
#include <bitset>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
@ -11,7 +11,9 @@
|
||||
|
||||
#include <data/GameTexts.hpp>
|
||||
#include <data/VehicleGenerator.hpp>
|
||||
#include <engine/GameData.hpp>
|
||||
#include <engine/GameInputState.hpp>
|
||||
#include <engine/GameWorld.hpp>
|
||||
#include <engine/ScreenText.hpp>
|
||||
#include <objects/ObjectTypes.hpp>
|
||||
|
||||
@ -191,7 +193,7 @@ struct BlipData {
|
||||
|
||||
uint16_t size = 3; // Only used if texture is empty
|
||||
|
||||
uint8_t brightness = 1; // Don't really know how it is used
|
||||
uint8_t brightness = 1; // Don't really know how it is used
|
||||
|
||||
enum DisplayMode { Hide = 0, MarkerOnly = 1, RadarOnly = 2, ShowBoth = 3 };
|
||||
|
||||
@ -323,8 +325,20 @@ public:
|
||||
/** Objects created by the current mission */
|
||||
std::vector<GameObject*> missionObjects;
|
||||
|
||||
bool overrideNextStart;
|
||||
bool overrideNextRestart;
|
||||
glm::vec4 nextRestartLocation;
|
||||
std::vector<glm::vec4> hospitalRestarts, policeRestarts;
|
||||
int hospitalIslandOverride, policeIslandOverride;
|
||||
|
||||
void addHospitalRestart(const glm::vec4 location);
|
||||
void addPoliceRestart(const glm::vec4 location);
|
||||
void overrideRestart(const glm::vec4 location);
|
||||
void cancelRestartOverride();
|
||||
|
||||
enum RestartType { Hospital, Police };
|
||||
|
||||
const glm::vec4 getClosestRestart(RestartType type,
|
||||
const glm::vec3 playerPosition) const;
|
||||
|
||||
bool fadeOut;
|
||||
float fadeStart;
|
||||
@ -332,6 +346,11 @@ public:
|
||||
bool fadeSound;
|
||||
glm::u16vec3 fadeColour;
|
||||
|
||||
// @todo fadeOut should be replaced with enum?
|
||||
void fade(float time, bool f);
|
||||
bool isFading() const;
|
||||
void setFadeColour(glm::i32vec3 colour);
|
||||
|
||||
std::string currentSplash;
|
||||
|
||||
bool skipCutscene;
|
||||
@ -393,7 +412,7 @@ public:
|
||||
*/
|
||||
ScriptMachine* script;
|
||||
|
||||
std::array<ScriptContactData, 16> scriptContacts = { };
|
||||
std::array<ScriptContactData, 16> scriptContacts = {};
|
||||
|
||||
GameState();
|
||||
|
||||
|
@ -148,6 +148,11 @@ glm::vec3 CharacterObject::updateMovementAnimation(float dt) {
|
||||
movementAnimation =
|
||||
animations->animation(AnimCycle::KnockOutShotFront0);
|
||||
repeat = false;
|
||||
if (currentAnim ==
|
||||
animations->animation(AnimCycle::KnockOutShotFront0) &&
|
||||
animator->isCompleted(AnimIndexMovement)) {
|
||||
SetDead();
|
||||
}
|
||||
} else if (jumped) {
|
||||
repeat = false;
|
||||
if (currentAnim == animations->animation(AnimCycle::JumpLaunch) &&
|
||||
@ -407,8 +412,26 @@ bool CharacterObject::isPlayer() const {
|
||||
return engine->state->playerObject == getGameObjectID();
|
||||
}
|
||||
|
||||
bool CharacterObject::isDying() const {
|
||||
return currentState.isDying;
|
||||
}
|
||||
|
||||
bool CharacterObject::isDead() const {
|
||||
return currentState.isDead;
|
||||
}
|
||||
|
||||
bool CharacterObject::isAlive() const {
|
||||
return currentState.health > 0.f;
|
||||
return !isDying() && !isDead();
|
||||
}
|
||||
|
||||
void CharacterObject::Die() {
|
||||
currentState.isDying = true;
|
||||
currentState.isDead = false;
|
||||
}
|
||||
|
||||
void CharacterObject::SetDead() {
|
||||
currentState.isDying = false;
|
||||
currentState.isDead = true;
|
||||
}
|
||||
|
||||
bool CharacterObject::enterVehicle(VehicleObject* vehicle, size_t seat) {
|
||||
@ -486,6 +509,9 @@ bool CharacterObject::takeDamage(const GameObject::DamageInfo& dmg) {
|
||||
if (dmgPoints > 0.f) {
|
||||
currentState.health = std::max(0.f, currentState.health - dmgPoints);
|
||||
}
|
||||
if (currentState.health <= 0.f) {
|
||||
Die();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -652,3 +678,9 @@ void CharacterObject::useItem(bool active, bool primary) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CharacterObject::clearInventory() {
|
||||
for (int slot = 0; slot < kMaxInventorySlots; ++slot) {
|
||||
removeFromInventory(slot);
|
||||
}
|
||||
}
|
@ -7,8 +7,8 @@
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
#include <glm/gtc/constants.hpp>
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/constants.hpp>
|
||||
|
||||
#include <rw/forward.hpp>
|
||||
|
||||
@ -37,6 +37,8 @@ struct CharacterWeaponSlot {
|
||||
struct CharacterState {
|
||||
float health = 100.f;
|
||||
float armour = 0.f;
|
||||
bool isDying = false;
|
||||
bool isDead = false;
|
||||
std::array<CharacterWeaponSlot, kMaxInventorySlots> weapons;
|
||||
uint16_t currentWeapon = 0;
|
||||
uint32_t lastFireTimeMS = 0;
|
||||
@ -129,7 +131,13 @@ public:
|
||||
|
||||
bool isPlayer() const;
|
||||
|
||||
bool isDying() const;
|
||||
bool isDead() const;
|
||||
bool isAlive() const;
|
||||
|
||||
void Die();
|
||||
void SetDead();
|
||||
|
||||
bool takeDamage(const DamageInfo& damage) override;
|
||||
|
||||
bool enterVehicle(VehicleObject* vehicle, size_t seat);
|
||||
@ -186,7 +194,8 @@ public:
|
||||
glm::vec3 getLookDirection() const {
|
||||
float theta = m_look.y - glm::half_pi<float>();
|
||||
return glm::vec3(std::sin(-m_look.x) * std::cos(theta),
|
||||
std::cos(-m_look.x) * std::cos(theta), std::sin(theta));
|
||||
std::cos(-m_look.x) * std::cos(theta),
|
||||
std::sin(theta));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -250,6 +259,8 @@ public:
|
||||
void useItem(bool active, bool primary = true);
|
||||
|
||||
void cycleInventory(bool up);
|
||||
|
||||
void clearInventory();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -3183,10 +3183,8 @@ void opcode_0114(const ScriptArguments& args, const ScriptCharacter character, c
|
||||
@arg player Player
|
||||
*/
|
||||
bool opcode_0117(const ScriptArguments& args, const ScriptPlayer player) {
|
||||
RW_UNIMPLEMENTED_OPCODE(0x0117);
|
||||
RW_UNUSED(player);
|
||||
RW_UNUSED(args);
|
||||
return false;
|
||||
return player->isWasted();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -3877,7 +3875,7 @@ void opcode_0168(const ScriptArguments& args, const ScriptBlip blip, const Scrip
|
||||
@arg colour Colour (0-255)
|
||||
*/
|
||||
void opcode_0169(const ScriptArguments& args, ScriptRGB colour) {
|
||||
args.getState()->fadeColour = colour;
|
||||
args.getState()->setFadeColour(colour);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -3888,9 +3886,7 @@ void opcode_0169(const ScriptArguments& args, ScriptRGB colour) {
|
||||
@arg scriptFade Boolean true/false
|
||||
*/
|
||||
void opcode_016a(const ScriptArguments& args, const ScriptInt time, const ScriptBoolean scriptFade) {
|
||||
args.getState()->fadeTime = time / 1000.f;
|
||||
args.getState()->fadeOut = scriptFade;
|
||||
args.getState()->fadeStart = args.getWorld()->getGameTime();
|
||||
args.getState()->fade(time / 1000.f, scriptFade);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -3902,8 +3898,7 @@ bool opcode_016b(const ScriptArguments& args) {
|
||||
if (args.getWorld()->state->skipCutscene) {
|
||||
return false;
|
||||
}
|
||||
return args.getWorld()->getGameTime() <
|
||||
args.getState()->fadeStart + args.getState()->fadeTime;
|
||||
return args.getState()->isFading();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -3913,11 +3908,9 @@ bool opcode_016b(const ScriptArguments& args) {
|
||||
@arg coord Coordinates
|
||||
@arg angle Angle
|
||||
*/
|
||||
void opcode_016c(const ScriptArguments& args, ScriptVec3 coord, const ScriptFloat angle) {
|
||||
RW_UNIMPLEMENTED_OPCODE(0x016c);
|
||||
RW_UNUSED(coord);
|
||||
RW_UNUSED(angle);
|
||||
RW_UNUSED(args);
|
||||
void opcode_016c(const ScriptArguments& args, ScriptVec3 coord, const ScriptFloat heading) {
|
||||
coord = script::getGround(args, coord);
|
||||
args.getState()->addHospitalRestart(glm::vec4(coord, heading));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -3927,11 +3920,9 @@ void opcode_016c(const ScriptArguments& args, ScriptVec3 coord, const ScriptFloa
|
||||
@arg coord Coordinates
|
||||
@arg angle Angle
|
||||
*/
|
||||
void opcode_016d(const ScriptArguments& args, ScriptVec3 coord, const ScriptFloat angle) {
|
||||
RW_UNIMPLEMENTED_OPCODE(0x016d);
|
||||
RW_UNUSED(coord);
|
||||
RW_UNUSED(angle);
|
||||
RW_UNUSED(args);
|
||||
void opcode_016d(const ScriptArguments& args, ScriptVec3 coord, const ScriptFloat heading) {
|
||||
coord = script::getGround(args, coord);
|
||||
args.getState()->addPoliceRestart(glm::vec4(coord, heading));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -3941,10 +3932,9 @@ void opcode_016d(const ScriptArguments& args, ScriptVec3 coord, const ScriptFloa
|
||||
@arg coord Coordinates
|
||||
@arg angle Angle
|
||||
*/
|
||||
void opcode_016e(const ScriptArguments& args, ScriptVec3 coord, const ScriptFloat angle) {
|
||||
args.getState()->overrideNextStart = true;
|
||||
/// @todo why is this a vec4
|
||||
args.getState()->nextRestartLocation = glm::vec4(coord, angle);
|
||||
void opcode_016e(const ScriptArguments& args, ScriptVec3 coord, const ScriptFloat heading) {
|
||||
coord = script::getGround(args, coord);
|
||||
args.getState()->overrideRestart(glm::vec4(coord, heading));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -5634,7 +5624,7 @@ void opcode_01f5(const ScriptArguments& args, const ScriptPlayer player, ScriptC
|
||||
opcode 01f6
|
||||
*/
|
||||
void opcode_01f6(const ScriptArguments& args) {
|
||||
args.getState()->overrideNextStart = false;
|
||||
args.getState()->cancelRestartOverride();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -6827,21 +6817,12 @@ void opcode_0254(const ScriptArguments& args) {
|
||||
@arg coord Coordinates
|
||||
@arg angle Angle
|
||||
*/
|
||||
void opcode_0255(const ScriptArguments& args, ScriptVec3 coord, const ScriptFloat angle) {
|
||||
auto object = args.getWorld()->pedestrianPool.find(args.getState()->playerObject);
|
||||
RW_CHECK(object != nullptr ,"No player found");
|
||||
auto player = static_cast<CharacterObject*>(object);
|
||||
|
||||
/// @todo Implment a proper force exit vehicle path
|
||||
auto cv = player->getCurrentVehicle();
|
||||
if ( cv != nullptr )
|
||||
{
|
||||
cv->setOccupant( player->getCurrentSeat(), nullptr );
|
||||
player->setCurrentVehicle(nullptr, 0);
|
||||
}
|
||||
|
||||
player->setPosition(coord + script::kSpawnOffset);
|
||||
player->setHeading(angle);
|
||||
void opcode_0255(const ScriptArguments& args, ScriptVec3 coord, const ScriptFloat heading) {
|
||||
coord = script::getGround(args, coord);
|
||||
args.getState()->overrideRestart(glm::vec4(coord, heading));
|
||||
// @todo Add support for multiple players
|
||||
PlayerController* player = args.getState()->world->players.at(0);
|
||||
player->requestMissionRestart();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -6851,10 +6832,8 @@ void opcode_0255(const ScriptArguments& args, ScriptVec3 coord, const ScriptFloa
|
||||
@arg player Player
|
||||
*/
|
||||
bool opcode_0256(const ScriptArguments& args, const ScriptPlayer player) {
|
||||
RW_UNIMPLEMENTED_OPCODE(0x0256);
|
||||
RW_UNUSED(player);
|
||||
RW_UNUSED(args);
|
||||
return player.get() != nullptr;
|
||||
return !player->isWasted() && !player->isBusted();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -12202,10 +12181,9 @@ void opcode_0412(const ScriptArguments& args, const ScriptVehicle vehicle, const
|
||||
@arg arg2 Boolean true/false
|
||||
*/
|
||||
void opcode_0413(const ScriptArguments& args, const ScriptPlayer player, const ScriptBoolean arg2) {
|
||||
RW_UNIMPLEMENTED_OPCODE(0x0413);
|
||||
// @todo support multiple players?
|
||||
RW_UNUSED(player);
|
||||
RW_UNUSED(arg2);
|
||||
RW_UNUSED(args);
|
||||
args.getState()->playerInfo.thaneOfLibertyCity = arg2;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -12216,10 +12194,9 @@ void opcode_0413(const ScriptArguments& args, const ScriptPlayer player, const S
|
||||
@arg arg2 Boolean true/false
|
||||
*/
|
||||
void opcode_0414(const ScriptArguments& args, const ScriptPlayer player, const ScriptBoolean arg2) {
|
||||
RW_UNIMPLEMENTED_OPCODE(0x0414);
|
||||
// @todo support multiple players?
|
||||
RW_UNUSED(player);
|
||||
RW_UNUSED(arg2);
|
||||
RW_UNUSED(args);
|
||||
args.getState()->playerInfo.singlePayerHealthcare = arg2;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -12338,9 +12315,7 @@ void opcode_041e(const ScriptArguments& args, const ScriptRadio arg1, const Scri
|
||||
@arg arg1
|
||||
*/
|
||||
void opcode_041f(const ScriptArguments& args, const ScriptLevel arg1) {
|
||||
RW_UNIMPLEMENTED_OPCODE(0x041f);
|
||||
RW_UNUSED(arg1);
|
||||
RW_UNUSED(args);
|
||||
args.getState()->hospitalIslandOverride = arg1;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -12350,9 +12325,7 @@ void opcode_041f(const ScriptArguments& args, const ScriptLevel arg1) {
|
||||
@arg arg1
|
||||
*/
|
||||
void opcode_0420(const ScriptArguments& args, const ScriptLevel arg1) {
|
||||
RW_UNIMPLEMENTED_OPCODE(0x0420);
|
||||
RW_UNUSED(arg1);
|
||||
RW_UNUSED(args);
|
||||
args.getState()->policeIslandOverride = arg1;
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user