From 7e91fe351df23ff14418ceac1c247e6834421af2 Mon Sep 17 00:00:00 2001 From: husho Date: Sun, 3 Jun 2018 13:48:01 +0300 Subject: [PATCH 1/2] Added script timer --- rwengine/src/engine/GameState.hpp | 6 ++ .../src/script/modules/GTA3ModuleImpl.inl | 21 +++--- rwgame/DrawUI.cpp | 66 ++++++++++++++++--- rwgame/RWGame.cpp | 20 +++++- 4 files changed, 88 insertions(+), 25 deletions(-) diff --git a/rwengine/src/engine/GameState.hpp b/rwengine/src/engine/GameState.hpp index da530d2e3..474ff4eb2 100644 --- a/rwengine/src/engine/GameState.hpp +++ b/rwengine/src/engine/GameState.hpp @@ -386,6 +386,12 @@ class GameState { */ std::vector texts; + /** + * Script timer + */ + int32_t* scriptTimerVariable = nullptr; + bool scriptTimerPaused = false; + /** The camera near value currently set by the script */ float cameraNear; bool cameraFixed; diff --git a/rwengine/src/script/modules/GTA3ModuleImpl.inl b/rwengine/src/script/modules/GTA3ModuleImpl.inl index dd356b0a8..d6770d1b0 100644 --- a/rwengine/src/script/modules/GTA3ModuleImpl.inl +++ b/rwengine/src/script/modules/GTA3ModuleImpl.inl @@ -3456,12 +3456,10 @@ void opcode_014d(const ScriptArguments& args, const ScriptString arg1, const Scr @brief start_timer_at %1d% opcode 014e - @arg arg1G Global timer storage + @arg timer */ -void opcode_014e(const ScriptArguments& args, ScriptInt& arg1G) { - RW_UNIMPLEMENTED_OPCODE(0x014e); - RW_UNUSED(arg1G); - RW_UNUSED(args); +void opcode_014e(const ScriptArguments& args, ScriptInt& timer) { + args.getState()->scriptTimerVariable = &timer; } /** @@ -3470,10 +3468,9 @@ void opcode_014e(const ScriptArguments& args, ScriptInt& arg1G) { opcode 014f @arg arg1G Global timer storage */ -void opcode_014f(const ScriptArguments& args, ScriptInt& arg1G) { - RW_UNIMPLEMENTED_OPCODE(0x014f); - RW_UNUSED(arg1G); - RW_UNUSED(args); +void opcode_014f(const ScriptArguments& args, ScriptInt& unused) { + RW_UNUSED(unused); + args.getState()->scriptTimerVariable = nullptr; } /** @@ -10416,10 +10413,8 @@ void opcode_0395(const ScriptArguments& args, ScriptVec3 coord, const ScriptFloa opcode 0396 @arg arg1 Boolean true/false */ -void opcode_0396(const ScriptArguments& args, const ScriptBoolean arg1) { - RW_UNIMPLEMENTED_OPCODE(0x0396); - RW_UNUSED(arg1); - RW_UNUSED(args); +void opcode_0396(const ScriptArguments& args, const ScriptBoolean paused) { + args.getState()->scriptTimerPaused = paused; } /** diff --git a/rwgame/DrawUI.cpp b/rwgame/DrawUI.cpp index 11e48eda2..21bb70d48 100644 --- a/rwgame/DrawUI.cpp +++ b/rwgame/DrawUI.cpp @@ -1,9 +1,9 @@ #include "DrawUI.hpp" #include -#include -#include #include #include +#include +#include #include #include @@ -12,11 +12,16 @@ constexpr size_t ui_textSize = 25; constexpr size_t ui_textHeight = 22; +constexpr size_t ui_elementMargin = 3; constexpr size_t ui_outerMargin = 20; constexpr size_t ui_infoMargin = 10; constexpr size_t ui_weaponSize = 64; constexpr size_t ui_ammoSize = 14; constexpr size_t ui_ammoHeight = 16; +constexpr size_t ui_wantedLevelHeight = + ui_outerMargin + ui_weaponSize + ui_elementMargin; +constexpr size_t ui_scriptTimerHeight = + ui_wantedLevelHeight + ui_textHeight + ui_elementMargin; constexpr size_t ui_armourOffset = ui_textSize * 3; constexpr size_t ui_maxWantedLevel = 6; constexpr size_t ui_lowHealth = 9; @@ -24,17 +29,49 @@ const glm::u8vec3 ui_timeColour(196, 165, 119); const glm::u8vec3 ui_moneyColour(89, 113, 147); const glm::u8vec3 ui_healthColour(187, 102, 47); const glm::u8vec3 ui_armourColour(123, 136, 93); +const glm::u8vec3 ui_scriptTimerColour(186, 101, 50); const glm::u8vec3 ui_shadowColour(0, 0, 0); constexpr float ui_mapSize = 150.f; constexpr float ui_worldSizeMin = 200.f; constexpr float ui_worldSizeMax = 300.f; +void drawScriptTimer(GameWorld* world, GameRenderer* render) { + if (world->state->scriptTimerVariable) { + float scriptTimerTextX = + render->getRenderer()->getViewport().x - ui_outerMargin; + float scriptTimerTextY = ui_scriptTimerHeight; + + TextRenderer::TextInfo ti; + ti.font = 1; + ti.size = ui_textSize; + ti.align = TextRenderer::TextInfo::Right; + + { + int32_t seconds = *world->state->scriptTimerVariable / 1000; + std::stringstream ss; + ss << std::setw(2) << std::setfill('0') << seconds / 60 + << std::setw(0) << ":" << std::setw(2) << seconds % 60; + + ti.text = GameStringUtil::fromString(ss.str()); + } + + ti.baseColour = ui_shadowColour; + ti.screenPosition = + glm::vec2(scriptTimerTextX + 1.f, scriptTimerTextY + 1.f); + render->text.renderText(ti); + + ti.baseColour = ui_scriptTimerColour; + ti.screenPosition = glm::vec2(scriptTimerTextX, scriptTimerTextY); + render->text.renderText(ti); + } +} + void drawMap(ViewCamera& currentView, PlayerController* player, GameWorld* world, GameRenderer* render) { MapRenderer::MapInfo map; - if (world->state->hudFlash != HudFlash::FlashRadar - || std::fmod(world->getGameTime(), 0.5f) >= .25f) { + if (world->state->hudFlash != HudFlash::FlashRadar || + std::fmod(world->getGameTime(), 0.5f) >= .25f) { glm::quat camRot = currentView.rotation; map.rotation = glm::roll(camRot) - glm::half_pi(); @@ -67,7 +104,7 @@ void drawPlayerInfo(PlayerController* player, GameWorld* world, (ui_outerMargin + ui_weaponSize); float iconY = ui_outerMargin; float wantedX = render->getRenderer()->getViewport().x - (ui_outerMargin); - float wantedY = ui_outerMargin + ui_weaponSize + 3.f; + float wantedY = ui_wantedLevelHeight; TextRenderer::TextInfo ti; ti.font = 1; @@ -81,12 +118,14 @@ void drawPlayerInfo(PlayerController* player, GameWorld* world, ti.text = GameStringUtil::fromString(ss.str()); } + ti.baseColour = ui_shadowColour; ti.screenPosition = glm::vec2(infoTextX + 1.f, infoTextY + 1.f); render->text.renderText(ti); ti.baseColour = ui_timeColour; ti.screenPosition = glm::vec2(infoTextX, infoTextY); + render->text.renderText(ti); infoTextY += ui_textHeight; @@ -98,25 +137,30 @@ void drawPlayerInfo(PlayerController* player, GameWorld* world, ti.text = GameSymbols::Money + GameStringUtil::fromString(ss.str()); } + ti.baseColour = ui_shadowColour; ti.screenPosition = glm::vec2(infoTextX + 1.f, infoTextY + 1.f); render->text.renderText(ti); ti.baseColour = ui_moneyColour; + ti.screenPosition = glm::vec2(infoTextX, infoTextY); render->text.renderText(ti); infoTextY += ui_textHeight; - if ((world->state->hudFlash != HudFlash::FlashHealth - && player->getCharacter()->getCurrentState().health > ui_lowHealth) - || std::fmod(world->getGameTime(), 0.5f) >= .25f) { // UI: Blinking health indicator if health is low + if ((world->state->hudFlash != HudFlash::FlashHealth && + player->getCharacter()->getCurrentState().health > ui_lowHealth) || + std::fmod(world->getGameTime(), 0.5f) >= + .25f) { // UI: Blinking health indicator if health is low std::stringstream ss; ss << std::setw(3) << std::setfill('0') << (int)player->getCharacter()->getCurrentState().health; ti.text = GameSymbols::Heart + GameStringUtil::fromString(ss.str()); + ti.baseColour = ui_shadowColour; ti.screenPosition = glm::vec2(infoTextX + 1.f, infoTextY + 1.f); + render->text.renderText(ti); ti.baseColour = ui_healthColour; @@ -129,6 +173,7 @@ void drawPlayerInfo(PlayerController* player, GameWorld* world, ss << std::setw(3) << std::setfill('0') << (int)player->getCharacter()->getCurrentState().armour; ti.text = GameSymbols::Armour + GameStringUtil::fromString(ss.str()); + ti.baseColour = ui_shadowColour; ti.screenPosition = glm::vec2(infoTextX + 1.f - ui_armourOffset, infoTextY + 1.f); @@ -201,8 +246,8 @@ void drawPlayerInfo(PlayerController* player, GameWorld* world, // The clip is actually there, but it holds just one shot/charge displayBulletsTotal += slotInfo.bulletsClip; - ti.text = GameStringUtil::fromString( - std::to_string(displayBulletsTotal)); + ti.text = + GameStringUtil::fromString(std::to_string(displayBulletsTotal)); } else { // Limit the maximal displayed length for the total bullet count if (slotInfo.bulletsTotal > 9999) { @@ -229,6 +274,7 @@ void drawHUD(ViewCamera& currentView, PlayerController* player, if (player && player->getCharacter()) { drawMap(currentView, player, world, render); drawPlayerInfo(player, world, render); + drawScriptTimer(world, render); } } diff --git a/rwgame/RWGame.cpp b/rwgame/RWGame.cpp index c3d3c9b3c..7d9292818 100644 --- a/rwgame/RWGame.cpp +++ b/rwgame/RWGame.cpp @@ -491,6 +491,7 @@ void RWGame::tick(float dt) { State* currState = StateManager::get().states.back().get(); static float clockAccumulator = 0.f; + static float scriptTimerAccumulator = 0.f; if (currState->shouldWorldUpdate()) { world->chase.update(dt); @@ -512,6 +513,22 @@ void RWGame::tick(float dt) { clockAccumulator -= 1.f; } + if (state.scriptTimerVariable && !state.scriptTimerPaused) { + scriptTimerAccumulator += dt; + while (scriptTimerAccumulator >= 1.f) { + (*state.scriptTimerVariable) -= 1000; + if (*state.scriptTimerVariable <= 0) { + (*state.scriptTimerVariable) = 0; + state.scriptTimerVariable = nullptr; + } + // 11 seconds + if (*state.scriptTimerVariable <= 11000) { + // @todo beep + } + scriptTimerAccumulator -= 1.f; + } + } + // Clean up old VisualFX for (int i = 0; i < static_cast(world->effects.size()); ++i) { VisualFX* effect = world->effects[i]; @@ -615,8 +632,7 @@ void RWGame::render(float alpha, float time) { } RW_PROFILE_END(); - if (!world->isPaused()) - drawOnScreenText(world.get(), &renderer); + if (!world->isPaused()) drawOnScreenText(world.get(), &renderer); } void RWGame::renderDebugStats(float time) { From d598cfe0971b55c043c6cb8847de5b3c33677625 Mon Sep 17 00:00:00 2001 From: husho Date: Fri, 8 Jun 2018 17:06:58 +0300 Subject: [PATCH 2/2] Use ScriptInt --- rwengine/src/engine/GameState.hpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/rwengine/src/engine/GameState.hpp b/rwengine/src/engine/GameState.hpp index 474ff4eb2..0bb03b811 100644 --- a/rwengine/src/engine/GameState.hpp +++ b/rwengine/src/engine/GameState.hpp @@ -18,6 +18,8 @@ #include #include +#include