1
0
mirror of https://github.com/rwengine/openrw.git synced 2024-09-03 17:19:46 +02:00

Implement script timer (#500)

Added script timer
This commit is contained in:
husho 2018-06-12 21:05:50 +03:00 committed by darkf
parent 85785b04e0
commit 23072a5e99
4 changed files with 90 additions and 24 deletions

View File

@ -18,6 +18,8 @@
#include <engine/ScreenText.hpp>
#include <objects/ObjectTypes.hpp>
#include <script/ScriptTypes.hpp>
class GameWorld;
class GameObject;
class ScriptMachine;
@ -330,7 +332,7 @@ public:
* @brief Stores a pointer to script global that stores the on-mission
* state.
*/
int32_t* scriptOnMissionFlag;
ScriptInt* scriptOnMissionFlag;
/** Objects created by the current mission */
std::vector<GameObject*> missionObjects;
@ -386,6 +388,12 @@ public:
*/
std::vector<TextDisplayData> texts;
/**
* Script timer
*/
ScriptInt* scriptTimerVariable = nullptr;
bool scriptTimerPaused = false;
/** The camera near value currently set by the script */
float cameraNear;
bool cameraFixed;

View File

@ -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;
}
/**
@ -10413,10 +10410,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;
}
/**

View File

@ -1,9 +1,9 @@
#include "DrawUI.hpp"
#include <ai/PlayerController.hpp>
#include <engine/GameState.hpp>
#include <objects/CharacterObject.hpp>
#include <data/WeaponData.hpp>
#include <engine/GameData.hpp>
#include <engine/GameState.hpp>
#include <objects/CharacterObject.hpp>
#include <render/GameRenderer.hpp>
#include <glm/gtc/constants.hpp>
@ -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<float>();
@ -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);
}
}

View File

@ -485,6 +485,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);
@ -506,6 +507,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<int>(world->effects.size()); ++i) {
VisualFX* effect = world->effects[i];