TombEngine/TR5Main/Scripting/GameFlowScript.cpp

366 lines
9 KiB
C++
Raw Normal View History

2020-12-21 13:16:29 -03:00
#include "framework.h"
#include "GameFlowScript.h"
#include "items.h"
#include "box.h"
#include "lot.h"
#include "sound.h"
#include "savegame.h"
#include "draw.h"
#include "AudioTracks.h"
#include <Objects/objectslist.h>
#include <Game/newinv2.h>
2020-12-21 13:16:29 -03:00
using std::string;
using std::vector;
extern vector<AudioTrack> g_AudioTracks;
GameFlow::GameFlow(sol::state* lua) : LuaHandler{ lua }
2020-12-21 13:16:29 -03:00
{
//Hardcode in English - old strings for now; will be removed shortly
LanguageScript* lang = new LanguageScript("English");
Strings.push_back(lang);
2020-12-21 13:16:29 -03:00
// Settings type
m_lua->new_usertype<GameScriptSettings>("GameScriptSettings",
"screenWidth", &GameScriptSettings::ScreenWidth,
"screenHeight", &GameScriptSettings::ScreenHeight,
"windowTitle", &GameScriptSettings::WindowTitle,
"enableDynamicShadows", &GameScriptSettings::EnableDynamicShadows,
"windowed", &GameScriptSettings::Windowed,
"enableWaterCaustics", &GameScriptSettings::EnableWaterCaustics,
"drawingDistance", &GameScriptSettings::DrawingDistance,
"showRendererSteps", &GameScriptSettings::ShowRendererSteps,
"showDebugInfo", &GameScriptSettings::ShowDebugInfo
);
// Layer type
m_lua->new_usertype<GameScriptSkyLayer>("SkyLayer",
sol::constructors<GameScriptSkyLayer(byte, byte, byte, short)>(),
"r", &GameScriptSkyLayer::R,
"g", &GameScriptSkyLayer::G,
"b", &GameScriptSkyLayer::B,
"speed", &GameScriptSkyLayer::CloudSpeed
);
// Mirror type
m_lua->new_usertype<GameScriptMirror>("Mirror",
sol::constructors<GameScriptMirror(short, int, int, int, int)>(),
"room", &GameScriptMirror::Room,
"startX", &GameScriptMirror::StartX,
"endX", &GameScriptMirror::EndX,
"startZ", &GameScriptMirror::StartZ,
"endZ", &GameScriptMirror::EndZ
);
// Fog type
m_lua->new_usertype<GameScriptFog>("Fog",
sol::constructors<GameScriptFog(byte, byte, byte)>(),
"r", &GameScriptFog::R,
"g", &GameScriptFog::G,
"b", &GameScriptFog::B
);
// Inventory object type
m_lua->new_usertype<GameScriptInventoryObject>("InventoryObject",
sol::constructors<GameScriptInventoryObject(std::string, short, float, float, float, float, float, short, int, __int64)>(),
"name", &GameScriptInventoryObject::name,
"yOffset", &GameScriptInventoryObject::yOffset,
"scale", &GameScriptInventoryObject::scale,
"xRot", &GameScriptInventoryObject::xRot,
"yRot", &GameScriptInventoryObject::yRot,
"zRot", &GameScriptInventoryObject::zRot,
"rotationFlags", &GameScriptInventoryObject::rotationFlags,
"meshBits", &GameScriptInventoryObject::meshBits,
"operation", &GameScriptInventoryObject::operation
);
2020-12-21 13:16:29 -03:00
// Level type
m_lua->new_usertype<GameScriptLevel>("Level",
2020-12-21 13:16:29 -03:00
sol::constructors<GameScriptLevel()>(),
"name", &GameScriptLevel::NameStringKey,
2020-12-21 13:16:29 -03:00
"script", &GameScriptLevel::ScriptFileName,
"fileName", &GameScriptLevel::FileName,
"loadScreen", &GameScriptLevel::LoadScreenFileName,
"soundTrack", &GameScriptLevel::Soundtrack,
"layer1", &GameScriptLevel::Layer1,
"layer2", &GameScriptLevel::Layer2,
"fog", &GameScriptLevel::Fog,
"horizon", &GameScriptLevel::Horizon,
"colAddHorizon", &GameScriptLevel::ColAddHorizon,
"storm", &GameScriptLevel::Storm,
"background", &GameScriptLevel::Background,
"weather", &GameScriptLevel::Weather,
2020-12-21 13:16:29 -03:00
"laraType", &GameScriptLevel::LaraType,
"rumble", &GameScriptLevel::Rumble,
"resetHub", &GameScriptLevel::ResetHub,
"mirror", &GameScriptLevel::Mirror,
"objects", &GameScriptLevel::InventoryObjects
);
2020-12-21 13:16:29 -03:00
(*m_lua)["GameFlow"] = std::ref(*this);
2020-12-21 13:16:29 -03:00
m_lua->new_usertype<GameFlow>("_GameFlow",
sol::no_constructor,
"AddLevel", &GameFlow::AddLevel,
"WriteDefaults", &GameFlow::WriteDefaults,
"AddTracks", &GameFlow::AddTracks,
"SetStrings", &GameFlow::SetStrings,
"SetLanguageNames", &GameFlow::SetLanguageNames
);
2020-12-21 13:16:29 -03:00
}
GameFlow::~GameFlow()
2020-12-21 13:16:29 -03:00
{
for (auto& lev : Levels)
2020-12-21 13:16:29 -03:00
{
delete lev;
2020-12-21 13:16:29 -03:00
}
for (auto& lang : Strings)
2020-12-21 13:16:29 -03:00
{
delete lang;
2020-12-21 13:16:29 -03:00
}
}
void GameFlow::SetLanguageNames(sol::as_table_t<std::vector<std::string>> && src)
2020-12-21 13:16:29 -03:00
{
m_languageNames = std::move(src);
2020-12-21 13:16:29 -03:00
}
void GameFlow::SetStrings(sol::nested<std::unordered_map<std::string, std::vector<std::string>>> && src)
2020-12-21 13:16:29 -03:00
{
m_translationsMap = std::move(src);
2020-12-21 13:16:29 -03:00
}
//hardcoded for now
void GameFlow::WriteDefaults()
2020-12-21 13:16:29 -03:00
{
Intro = "SCREENS\\MAIN.PNG";
EnableLoadSave = true;
PlayAnyLevel = true;
FlyCheat = true;
DebugMode = false;
LevelFarView = 0;
2020-12-21 13:16:29 -03:00
}
void GameFlow::AddLevel(GameScriptLevel const& level)
2020-12-21 13:16:29 -03:00
{
Levels.push_back(new GameScriptLevel{ level });
2020-12-21 13:16:29 -03:00
}
void GameFlow::AddTracks() {
for (auto str : kAudioTracks) {
AudioTrack track;
track.Name = str;
track.Mask = 0;
g_AudioTracks.push_back(track);
}
2020-12-21 13:16:29 -03:00
}
bool __cdecl LoadScript()
2020-12-21 13:16:29 -03:00
{
g_GameFlow->CurrentStrings = g_GameFlow->Strings[0];
2020-12-21 13:16:29 -03:00
return true;
}
bool GameFlow::LoadGameFlowScript()
2020-12-21 13:16:29 -03:00
{
// Load the enums file
std::string err;
if (!ExecuteScript("Scripts/Enums.lua", err)) {
std::cout << err << "\n";
}
// Load the new script file
if (!ExecuteScript("Scripts/Gameflow.lua", err)) {
std::cout << err << "\n";
}
// Hardcode English for now - this will be changed
// to something like "Strings.lua" once that system
// through
if (!ExecuteScript("Scripts/Strings.lua", err)) {
std::cout << err << "\n";
}
2020-12-21 13:16:29 -03:00
return true;
}
char* GameFlow::GetString(const char* id)
2020-12-21 13:16:29 -03:00
{
if (m_translationsMap.find(id) == m_translationsMap.end())
return "String not found";
else
return (char*)(m_translationsMap.at(string(id)).at(0).c_str());
2020-12-21 13:16:29 -03:00
}
GameScriptSettings* GameFlow::GetSettings()
{
return &m_settings;
}
GameScriptLevel* GameFlow::GetLevel(int id)
{
return Levels[id];
}
void GameFlow::SetHorizon(bool horizon, bool colAddHorizon)
{
DrawHorizon = horizon;
ColAddHorizon = colAddHorizon;
}
void GameFlow::SetLayer1(byte r, byte g, byte b, short speed)
{
SkyColor1.r = r;
SkyColor1.g = g;
SkyColor1.b = b;
SkyVelocity1 = speed;
SkyColorLayer1.x = r / 255.0f;
SkyColorLayer1.y = g / 255.0f;
SkyColorLayer1.z = b / 255.0f;
SkySpeedLayer1 = speed;
}
void GameFlow::SetLayer2(byte r, byte g, byte b, short speed)
{
SkyColor2.r = r;
SkyColor2.g = g;
SkyColor2.b = b;
SkyVelocity2 = speed;
SkyColorLayer2.x = r / 255.0f;
SkyColorLayer2.y = g / 255.0f;
SkyColorLayer2.z = b / 255.0f;
SkySpeedLayer2 = speed;
}
void GameFlow::SetFog(byte r, byte g, byte b, short startDistance, short endDistance)
{
FogColor.x = r / 255.0f;
FogColor.y = g / 255.0f;
FogColor.z = b / 255.0f;
FogInDistance = startDistance;
FogOutDistance = endDistance;
}
int GameFlow::GetNumLevels()
{
return Levels.size();
}
bool GameFlow::DoGameflow()
{
// We start with the title level
CurrentLevel = 0;
SelectedLevelForNewGame = 0;
SelectedSaveGame = 0;
SaveGameHeader header;
// We loop indefinitely, looking for return values of DoTitle or DoLevel
bool loadFromSavegame = false;
while (true)
{
// First we need to fill some legacy variables in PCTomb5.exe
GameScriptLevel* level = Levels[CurrentLevel];
2020-12-21 13:16:29 -03:00
CurrentAtmosphere = level->Soundtrack;
if (level->Horizon)
{
SkyColor1.r = level->Layer1.R;
SkyColor1.g = level->Layer1.G;
SkyColor1.b = level->Layer1.B;
SkyVelocity1 = level->Layer1.CloudSpeed;
SkyColor2.r = level->Layer2.R;
SkyColor2.g = level->Layer2.G;
SkyColor2.b = level->Layer2.B;
SkyVelocity2 = level->Layer2.CloudSpeed;
}
if (level->Storm)
{
SkyStormColor[0] = level->Layer1.R;
SkyStormColor[1] = level->Layer1.G;
SkyStormColor[2] = level->Layer1.B;
SkyStormColor2[0] = level->Layer1.R;
SkyStormColor2[1] = level->Layer1.G;
SkyStormColor2[2] = level->Layer1.B;
}
GAME_STATUS status;
if (CurrentLevel == 0)
{
status = DoTitle(0);
}
else
{
// Prepare inventory objects table
for (int i = 0; i < level->InventoryObjects.size(); i++)
{
GameScriptInventoryObject* obj = &level->InventoryObjects[i];
if (obj->slot >= 0 && obj->slot < INVENTORY_TABLE_SIZE)
{
INVOBJ* invObj = &inventry_objects_list[obj->slot];
invObj->objname = obj->name.c_str();
invObj->scale1 = obj->scale;
invObj->yoff = obj->yOffset;
invObj->xrot = obj->xRot;
invObj->zrot = obj->zRot;
invObj->meshbits = obj->meshBits;
invObj->opts = obj->operation;
invObj->rot_flags = obj->rotationFlags;
}
}
2020-12-21 13:16:29 -03:00
status = DoLevel(CurrentLevel, CurrentAtmosphere, loadFromSavegame);
loadFromSavegame = false;
}
switch (status)
{
case GAME_STATUS_EXIT_GAME:
return true;
case GAME_STATUS_EXIT_TO_TITLE:
CurrentLevel = 0;
break;
case GAME_STATUS_NEW_GAME:
CurrentLevel = (SelectedLevelForNewGame != 0 ? SelectedLevelForNewGame : 1);
SelectedLevelForNewGame = 0;
InitialiseGame = true;
break;
case GAME_STATUS_LOAD_GAME:
// Load the header of the savegame for getting the level to load
char fileName[255];
ZeroMemory(fileName, 255);
sprintf(fileName, "savegame.%d", SelectedSaveGame);
SaveGame::LoadHeader(fileName, &header);
// Load level
CurrentLevel = header.Level;
loadFromSavegame = true;
break;
case GAME_STATUS_LEVEL_COMPLETED:
if (LevelComplete == Levels.size())
{
// TODO: final credits
}
else
CurrentLevel++;
break;
}
}
return true;
}
GameFlow* g_GameFlow;