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

Various opcodes (#499)

Various opcodes
This commit is contained in:
husho 2018-06-18 07:23:20 +03:00 committed by darkf
parent 1574ebb83c
commit 81781a53ed
7 changed files with 107 additions and 92 deletions

View File

@ -128,7 +128,7 @@ void PlayerController::restart() {
if (!state->playerInfo.thaneOfLibertyCity) { if (!state->playerInfo.thaneOfLibertyCity) {
// @todo implement wanted system // @todo implement wanted system
uint8_t wantedLevel = 0; uint8_t wantedLevel = 0;
uint32_t penalty = 0; int32_t penalty = 0;
switch (wantedLevel) { switch (wantedLevel) {
case 0: case 0:

View File

@ -76,12 +76,12 @@ struct BasicState {
/** Block 16 player info */ /** Block 16 player info */
struct PlayerInfo { struct PlayerInfo {
uint32_t money; int32_t money;
uint8_t unknown1; uint8_t unknown1;
uint32_t unknown2; uint32_t unknown2;
uint16_t unknown3; uint16_t unknown3;
float unknown4; float unknown4;
uint32_t displayedMoney; int32_t displayedMoney;
uint32_t hiddenPackagesCollected; uint32_t hiddenPackagesCollected;
uint32_t hiddenPackageCount; uint32_t hiddenPackageCount;
uint8_t neverTired; uint8_t neverTired;

View File

@ -519,8 +519,13 @@ void VehicleObject::tickPhysics(float dt) {
} }
bool VehicleObject::isFlipped() const { bool VehicleObject::isFlipped() const {
auto up = getRotation() * glm::vec3(0.f, 0.f, 1.f); auto forward = getRotation() * glm::vec3(0.f, 0.f, 1.f);
return up.z <= -0.1f; return forward.z <= -0.97f;
}
bool VehicleObject::isUpright() const {
auto forward = getRotation() * glm::vec3(0.f, 0.f, 1.f);
return forward.z >= 0.f;
} }
float VehicleObject::getVelocity() const { float VehicleObject::getVelocity() const {

View File

@ -128,6 +128,8 @@ public:
bool isFlipped() const; bool isFlipped() const;
bool isUpright() const;
float getVelocity() const; float getVelocity() const;
void ejectAll(); void ejectAll();

View File

@ -22,7 +22,13 @@ void ScriptMachine::executeThread(SCMThread& t, int msPassed) {
t.programCounter = t.calls[t.stackDepth]; t.programCounter = t.calls[t.stackDepth];
} }
} }
// There is 02a1 opcode that is used only during "Kingdom Come", which
// basically acts like a wait command, but waiting time can be skipped
// by pressing 'X'? PS2 button
if (t.allowWaitSkip && getState()->input[0].pressed(GameInputState::Jump)) {
t.wakeCounter = 0;
t.allowWaitSkip = false;
}
if (t.wakeCounter > 0) { if (t.wakeCounter > 0) {
t.wakeCounter = std::max(t.wakeCounter - msPassed, 0); t.wakeCounter = std::max(t.wakeCounter - msPassed, 0);
} }
@ -211,6 +217,7 @@ void ScriptMachine::startThread(SCMThread::pc_t start, bool mission) {
t.stackDepth = 0; t.stackDepth = 0;
t.deathOrArrestCheck = true; t.deathOrArrestCheck = true;
t.wastedOrBusted = false; t.wastedOrBusted = false;
t.allowWaitSkip = false;
_activeThreads.push_back(t); _activeThreads.push_back(t);
} }

View File

@ -5,12 +5,12 @@
#include <cstdint> #include <cstdint>
#include <iomanip> #include <iomanip>
#include <list> #include <list>
#include <random>
#include <sstream> #include <sstream>
#include <string> #include <string>
#include <type_traits>
#include <utility> #include <utility>
#include <vector> #include <vector>
#include <random>
#include <type_traits>
#include <script/ScriptTypes.hpp> #include <script/ScriptTypes.hpp>
@ -27,7 +27,6 @@ class SCMFile;
#define SCM_VARIABLE_SIZE 4 #define SCM_VARIABLE_SIZE 4
#define SCM_STACK_DEPTH 4 #define SCM_STACK_DEPTH 4
struct SCMException { struct SCMException {
virtual ~SCMException() = default; virtual ~SCMException() = default;
@ -42,7 +41,9 @@ struct IllegalInstruction : SCMException {
template <class String> template <class String>
IllegalInstruction(SCMOpcode _opcode, unsigned int _offset, IllegalInstruction(SCMOpcode _opcode, unsigned int _offset,
String&& _thread) String&& _thread)
: opcode(_opcode), offset(_offset), thread(std::forward<String>(_thread)) { : opcode(_opcode)
, offset(_offset)
, thread(std::forward<String>(_thread)) {
} }
std::string what() const override { std::string what() const override {
@ -100,6 +101,8 @@ struct SCMThread {
bool deathOrArrestCheck; bool deathOrArrestCheck;
bool wastedOrBusted; bool wastedOrBusted;
bool allowWaitSkip;
}; };
/** /**
@ -160,17 +163,18 @@ public:
debugFlag = flag; debugFlag = flag;
} }
template<typename T> template <typename T>
typename std::enable_if<std::is_integral<T>::value, T>::type typename std::enable_if<std::is_integral<T>::value, T>::type
getRandomNumber(T min, T max) { getRandomNumber(T min, T max) {
std::uniform_int_distribution<> dist(min, max); std::uniform_int_distribution<> dist(min, max);
return dist(randomNumberGen); return dist(randomNumberGen);
} }
template<typename T> template <typename T>
typename std::enable_if<std::is_floating_point<T>::value, T>::type typename std::enable_if<std::is_floating_point<T>::value, T>::type
getRandomNumber(T min, T max) { getRandomNumber(T min, T max) {
std::uniform_real_distribution<> dist(static_cast<double>(min), static_cast<double>(max)); std::uniform_real_distribution<> dist(static_cast<double>(min),
static_cast<double>(max));
return dist(randomNumberGen); return dist(randomNumberGen);
} }

View File

@ -3013,10 +3013,8 @@ void opcode_0108(const ScriptArguments& args, const ScriptObject object) {
@arg money @arg money
*/ */
void opcode_0109(const ScriptArguments& args, const ScriptPlayer player, const ScriptInt money) { void opcode_0109(const ScriptArguments& args, const ScriptPlayer player, const ScriptInt money) {
RW_UNIMPLEMENTED_OPCODE(0x0109);
RW_UNUSED(player); RW_UNUSED(player);
RW_UNUSED(money); args.getState()->playerInfo.money += money;
RW_UNUSED(args);
} }
/** /**
@ -3027,11 +3025,8 @@ void opcode_0109(const ScriptArguments& args, const ScriptPlayer player, const S
@arg money @arg money
*/ */
bool opcode_010a(const ScriptArguments& args, const ScriptPlayer player, const ScriptInt money) { bool opcode_010a(const ScriptArguments& args, const ScriptPlayer player, const ScriptInt money) {
RW_UNIMPLEMENTED_OPCODE(0x010a);
RW_UNUSED(player); RW_UNUSED(player);
RW_UNUSED(money); return args.getState()->playerInfo.money > money;
RW_UNUSED(args);
return false;
} }
/** /**
@ -3042,10 +3037,8 @@ bool opcode_010a(const ScriptArguments& args, const ScriptPlayer player, const S
@arg money @arg money
*/ */
void opcode_010b(const ScriptArguments& args, const ScriptPlayer player, ScriptInt& money) { void opcode_010b(const ScriptArguments& args, const ScriptPlayer player, ScriptInt& money) {
RW_UNIMPLEMENTED_OPCODE(0x010b);
RW_UNUSED(player); RW_UNUSED(player);
RW_UNUSED(args); money = args.getState()->playerInfo.money;
money = 0;
} }
/** /**
@ -3570,14 +3563,16 @@ void opcode_0156(const ScriptArguments& args, const ScriptString arg1, const Scr
opcode 0157 opcode 0157
@arg player Player @arg player Player
@arg cameraModeID Camera mode ID @arg cameraModeID Camera mode ID
@arg arg3 @arg cameraChangeModeID
*/ */
void opcode_0157(const ScriptArguments& args, const ScriptPlayer player, const ScriptCamMode cameraModeID, const ScriptChangeCamMode arg3) { void opcode_0157(const ScriptArguments& args, const ScriptPlayer player,
RW_UNIMPLEMENTED_OPCODE(0x0157); const ScriptCamMode cameraModeID,
RW_UNUSED(player); const ScriptChangeCamMode cameraChangeModeID) {
args.getWorld()->state->cameraTarget =
player->getCharacter()->getGameObjectID();
RW_UNUSED(cameraModeID); RW_UNUSED(cameraModeID);
RW_UNUSED(arg3); RW_UNUSED(cameraChangeModeID);
RW_UNUSED(args);
} }
/** /**
@ -3586,14 +3581,16 @@ void opcode_0157(const ScriptArguments& args, const ScriptPlayer player, const S
opcode 0158 opcode 0158
@arg vehicle Car/vehicle @arg vehicle Car/vehicle
@arg cameraModeID Camera mode ID @arg cameraModeID Camera mode ID
@arg arg3 @arg cameraChangeModeID
*/ */
void opcode_0158(const ScriptArguments& args, const ScriptVehicle vehicle, const ScriptCamMode cameraModeID, const ScriptChangeCamMode arg3) { void opcode_0158(const ScriptArguments& args, const ScriptVehicle vehicle,
RW_UNIMPLEMENTED_OPCODE(0x0158); const ScriptCamMode cameraModeID,
RW_UNUSED(vehicle); const ScriptChangeCamMode cameraChangeModeID) {
if (vehicle) {
args.getWorld()->state->cameraTarget = vehicle->getGameObjectID();
}
RW_UNUSED(cameraModeID); RW_UNUSED(cameraModeID);
RW_UNUSED(arg3); RW_UNUSED(cameraChangeModeID);
RW_UNUSED(args);
} }
/** /**
@ -3602,14 +3599,16 @@ void opcode_0158(const ScriptArguments& args, const ScriptVehicle vehicle, const
opcode 0159 opcode 0159
@arg character Character/ped @arg character Character/ped
@arg cameraModeID Camera mode ID @arg cameraModeID Camera mode ID
@arg arg3 @arg cameraChangeModeID
*/ */
void opcode_0159(const ScriptArguments& args, const ScriptCharacter character, const ScriptCamMode cameraModeID, const ScriptChangeCamMode arg3) { void opcode_0159(const ScriptArguments& args, const ScriptCharacter character,
const ScriptCamMode cameraModeID,
const ScriptChangeCamMode cameraChangeModeID) {
if (character) { if (character) {
args.getWorld()->state->cameraTarget = character->getGameObjectID(); args.getWorld()->state->cameraTarget = character->getGameObjectID();
} }
RW_UNUSED(cameraModeID); RW_UNUSED(cameraModeID);
RW_UNUSED(arg3); RW_UNUSED(cameraChangeModeID);
} }
/** /**
@ -3666,12 +3665,10 @@ void opcode_015c(const ScriptArguments& args, const ScriptString areaName, const
@brief set_time_scale %1d% @brief set_time_scale %1d%
opcode 015d opcode 015d
@arg arg1 @arg scale
*/ */
void opcode_015d(const ScriptArguments& args, const ScriptFloat arg1) { void opcode_015d(const ScriptArguments& args, const ScriptFloat scale) {
RW_UNIMPLEMENTED_OPCODE(0x015d); args.getState()->basic.timeScale = scale;
RW_UNUSED(arg1);
RW_UNUSED(args);
} }
/** /**
@ -4073,16 +4070,15 @@ bool opcode_0179(const ScriptArguments& args, const ScriptCharacter character, c
@brief set_player %1d% weapon %2d% ammo_to %3d% @brief set_player %1d% weapon %2d% ammo_to %3d%
opcode 017a opcode 017a
@arg player @arg player
@arg arg2 @arg weaponID Weapon ID
@arg arg3 @arg arg3
*/ */
void opcode_017a(const ScriptArguments& args, const ScriptPlayer player, const ScriptWeaponType arg2, const ScriptInt arg3) { void opcode_017a(const ScriptArguments& args, const ScriptPlayer player,
RW_UNIMPLEMENTED_OPCODE(0x017a); const ScriptWeaponType weaponID, const ScriptInt ammo) {
RW_UNUSED(player);
RW_UNUSED(arg2);
RW_UNUSED(arg3);
RW_UNUSED(args); RW_UNUSED(args);
player->getCharacter()->getCurrentState().weapons[weaponID].bulletsTotal =
ammo;
} }
/** /**
@ -4909,18 +4905,21 @@ void opcode_01bd(const ScriptArguments& args, ScriptInt& time) {
@brief set_actor %1d% to_look_at_spot %2d% %3d% %4d% @brief set_actor %1d% to_look_at_spot %2d% %3d% %4d%
opcode 01be opcode 01be
@arg character @arg character
@arg arg2 @arg arg2
@arg arg3 @arg arg3
@arg arg4 @arg arg4
*/ */
void opcode_01be(const ScriptArguments& args, const ScriptCharacter character, const ScriptFloat arg2, const ScriptFloat arg3, const ScriptFloat arg4) { void opcode_01be(const ScriptArguments& args, const ScriptCharacter character,
RW_UNIMPLEMENTED_OPCODE(0x01be); const ScriptVec3 coord) {
RW_UNUSED(character);
RW_UNUSED(arg2);
RW_UNUSED(arg3);
RW_UNUSED(arg4);
RW_UNUSED(args); RW_UNUSED(args);
GameObject* object = character;
if (character->getCurrentVehicle()) {
object = character->getCurrentVehicle();
}
const auto& pos = object->getPosition() - coord;
object->setHeading(
glm::degrees(glm::atan(pos.x, pos.y) + glm::half_pi<float>()));
} }
/** /**
@ -5923,10 +5922,8 @@ void opcode_020c(const ScriptArguments& args, ScriptVec3 coord, const ScriptExpl
@arg vehicle Car/vehicle @arg vehicle Car/vehicle
*/ */
bool opcode_020d(const ScriptArguments& args, const ScriptVehicle vehicle) { bool opcode_020d(const ScriptArguments& args, const ScriptVehicle vehicle) {
RW_UNIMPLEMENTED_OPCODE(0x020d);
RW_UNUSED(vehicle);
RW_UNUSED(args); RW_UNUSED(args);
return false; return vehicle->isUpright();
} }
/** /**
@ -5937,10 +5934,10 @@ bool opcode_020d(const ScriptArguments& args, const ScriptVehicle vehicle) {
@arg character1 @arg character1
*/ */
void opcode_020e(const ScriptArguments& args, const ScriptCharacter character0, const ScriptCharacter character1) { void opcode_020e(const ScriptArguments& args, const ScriptCharacter character0, const ScriptCharacter character1) {
RW_UNIMPLEMENTED_OPCODE(0x020e);
RW_UNUSED(character0);
RW_UNUSED(character1);
RW_UNUSED(args); RW_UNUSED(args);
const auto& pos = character1->getPosition();
character0->setHeading(
glm::degrees(glm::atan(pos.x, pos.y) + glm::half_pi<float>()));
} }
/** /**
@ -5951,10 +5948,10 @@ void opcode_020e(const ScriptArguments& args, const ScriptCharacter character0,
@arg player @arg player
*/ */
void opcode_020f(const ScriptArguments& args, const ScriptCharacter character, const ScriptPlayer player) { void opcode_020f(const ScriptArguments& args, const ScriptCharacter character, const ScriptPlayer player) {
RW_UNIMPLEMENTED_OPCODE(0x020f);
RW_UNUSED(character);
RW_UNUSED(player);
RW_UNUSED(args); RW_UNUSED(args);
const auto& pos = player->getCharacter()->getPosition();
character->setHeading(
glm::degrees(glm::atan(pos.x, pos.y) + glm::half_pi<float>()));
} }
/** /**
@ -5965,10 +5962,10 @@ void opcode_020f(const ScriptArguments& args, const ScriptCharacter character, c
@arg character Character/ped @arg character Character/ped
*/ */
void opcode_0210(const ScriptArguments& args, const ScriptPlayer player, const ScriptCharacter character) { void opcode_0210(const ScriptArguments& args, const ScriptPlayer player, const ScriptCharacter character) {
RW_UNIMPLEMENTED_OPCODE(0x0210);
RW_UNUSED(player);
RW_UNUSED(character);
RW_UNUSED(args); RW_UNUSED(args);
const auto& pos = character->getPosition();
player->getCharacter()->setHeading(
glm::degrees(glm::atan(pos.x, pos.y) + glm::half_pi<float>()));
} }
/** /**
@ -6889,17 +6886,18 @@ bool opcode_02a0(const ScriptArguments& args, const ScriptCharacter character) {
} }
/** /**
@brief @brief skippable_wait
opcode 02a1 opcode 02a1
@arg arg1 @arg time
@arg arg2 @arg waitSkip
*/ */
void opcode_02a1(const ScriptArguments& args, const ScriptInt arg1, const ScriptInt arg2) { void opcode_02a1(const ScriptArguments& args, const ScriptInt time, const ScriptBoolean waitSkip) {
RW_UNIMPLEMENTED_OPCODE(0x02a1); RW_CHECK(time >= 0, "negative wait time is not supported");
RW_UNUSED(arg1); auto thread = args.getThread();
RW_UNUSED(arg2); // Scripts use wait 0 to yield
RW_UNUSED(args); thread->wakeCounter = time > 0 ? time : -1;
thread->allowWaitSkip = waitSkip;
} }
/** /**
@ -9594,11 +9592,11 @@ void opcode_0361(const ScriptArguments& args, const ScriptGarage garage) {
@arg character Character/ped @arg character Character/ped
@arg coord Coordinates @arg coord Coordinates
*/ */
void opcode_0362(const ScriptArguments& args, const ScriptCharacter character, ScriptVec3 coord) { void opcode_0362(const ScriptArguments& args, const ScriptCharacter character,
RW_UNIMPLEMENTED_OPCODE(0x0362); ScriptVec3 coord) {
RW_UNUSED(character);
RW_UNUSED(coord);
RW_UNUSED(args); RW_UNUSED(args);
character->setCurrentVehicle(nullptr, 0);
character->setPosition(coord);
} }
/** /**
@ -10593,11 +10591,11 @@ void opcode_039e(const ScriptArguments& args, const ScriptCharacter character, c
@arg vehicle Car/vehicle @arg vehicle Car/vehicle
@arg coord Coordinates @arg coord Coordinates
*/ */
void opcode_039f(const ScriptArguments& args, const ScriptVehicle vehicle, ScriptVec2 coord) { void opcode_039f(const ScriptArguments& args, const ScriptVehicle vehicle,
RW_UNIMPLEMENTED_OPCODE(0x039f); ScriptVec2 coord) {
RW_UNUSED(vehicle);
RW_UNUSED(coord);
RW_UNUSED(args); RW_UNUSED(args);
vehicle->setHeading(
glm::degrees(glm::atan(coord.x, coord.y) + glm::half_pi<float>()));
} }
/** /**
@ -10909,9 +10907,8 @@ void opcode_03b7(const ScriptArguments& args, const ScriptBoolean arg1) {
@arg player @arg player
*/ */
void opcode_03b8(const ScriptArguments& args, const ScriptPlayer player) { void opcode_03b8(const ScriptArguments& args, const ScriptPlayer player) {
RW_UNIMPLEMENTED_OPCODE(0x03b8);
RW_UNUSED(player);
RW_UNUSED(args); RW_UNUSED(args);
player->getCharacter()->clearInventory();
} }
/** /**