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"
|
2021-06-16 15:05:10 +01:00
|
|
|
#include "AudioTracks.h"
|
2021-06-23 05:58:24 +02:00
|
|
|
#include <Objects/objectslist.h>
|
|
|
|
#include <Game/newinv2.h>
|
2021-06-16 15:05:10 +01:00
|
|
|
|
2021-07-13 22:29:47 -05:00
|
|
|
#ifndef _DEBUG
|
|
|
|
#include <iostream>
|
|
|
|
#endif
|
|
|
|
|
2020-12-21 13:16:29 -03:00
|
|
|
using std::string;
|
|
|
|
using std::vector;
|
2021-06-26 07:36:54 +02:00
|
|
|
using std::unordered_map;
|
2020-12-21 13:16:29 -03:00
|
|
|
|
2021-06-26 07:36:54 +02:00
|
|
|
extern unordered_map<string, AudioTrack> g_AudioTracks;
|
2020-12-21 13:16:29 -03:00
|
|
|
|
2021-06-16 15:05:10 +01:00
|
|
|
GameFlow::GameFlow(sol::state* lua) : LuaHandler{ lua }
|
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
|
|
|
|
);
|
|
|
|
|
2021-06-23 05:58:24 +02:00
|
|
|
// 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
|
|
|
|
);
|
2021-06-16 15:05:10 +01:00
|
|
|
|
2021-06-26 07:36:54 +02:00
|
|
|
// Audio track type
|
|
|
|
m_lua->new_usertype<GameScriptAudioTrack>("AudioTrack",
|
|
|
|
sol::constructors<GameScriptAudioTrack(std::string, bool)>(),
|
|
|
|
"trackName", &GameScriptAudioTrack::trackName,
|
|
|
|
"looped", &GameScriptAudioTrack::looped
|
|
|
|
);
|
|
|
|
|
2020-12-21 13:16:29 -03:00
|
|
|
// Level type
|
2021-06-16 15:05:10 +01:00
|
|
|
m_lua->new_usertype<GameScriptLevel>("Level",
|
2020-12-21 13:16:29 -03:00
|
|
|
sol::constructors<GameScriptLevel()>(),
|
2021-06-19 07:20:04 +02:00
|
|
|
"name", &GameScriptLevel::NameStringKey,
|
2020-12-21 13:16:29 -03:00
|
|
|
"script", &GameScriptLevel::ScriptFileName,
|
|
|
|
"fileName", &GameScriptLevel::FileName,
|
|
|
|
"loadScreen", &GameScriptLevel::LoadScreenFileName,
|
2021-06-26 07:36:54 +02:00
|
|
|
"ambientTrack", &GameScriptLevel::AmbientTrack,
|
2020-12-21 13:16:29 -03:00
|
|
|
"layer1", &GameScriptLevel::Layer1,
|
|
|
|
"layer2", &GameScriptLevel::Layer2,
|
|
|
|
"fog", &GameScriptLevel::Fog,
|
|
|
|
"horizon", &GameScriptLevel::Horizon,
|
|
|
|
"colAddHorizon", &GameScriptLevel::ColAddHorizon,
|
|
|
|
"storm", &GameScriptLevel::Storm,
|
|
|
|
"background", &GameScriptLevel::Background,
|
2021-06-16 15:05:10 +01:00
|
|
|
"weather", &GameScriptLevel::Weather,
|
2020-12-21 13:16:29 -03:00
|
|
|
"laraType", &GameScriptLevel::LaraType,
|
|
|
|
"rumble", &GameScriptLevel::Rumble,
|
|
|
|
"resetHub", &GameScriptLevel::ResetHub,
|
2021-06-23 05:58:24 +02:00
|
|
|
"mirror", &GameScriptLevel::Mirror,
|
|
|
|
"objects", &GameScriptLevel::InventoryObjects
|
2021-06-16 15:05:10 +01:00
|
|
|
);
|
2020-12-21 13:16:29 -03:00
|
|
|
|
2021-06-16 15:05:10 +01:00
|
|
|
(*m_lua)["GameFlow"] = std::ref(*this);
|
2020-12-21 13:16:29 -03:00
|
|
|
|
2021-06-16 15:05:10 +01:00
|
|
|
m_lua->new_usertype<GameFlow>("_GameFlow",
|
|
|
|
sol::no_constructor,
|
|
|
|
"AddLevel", &GameFlow::AddLevel,
|
|
|
|
"WriteDefaults", &GameFlow::WriteDefaults,
|
2021-06-26 07:36:54 +02:00
|
|
|
"SetAudioTracks", &GameFlow::SetAudioTracks,
|
2021-06-16 15:05:10 +01:00
|
|
|
"SetStrings", &GameFlow::SetStrings,
|
|
|
|
"SetLanguageNames", &GameFlow::SetLanguageNames
|
|
|
|
);
|
2020-12-21 13:16:29 -03:00
|
|
|
}
|
|
|
|
|
2021-06-16 15:05:10 +01:00
|
|
|
GameFlow::~GameFlow()
|
2020-12-21 13:16:29 -03:00
|
|
|
{
|
2021-06-16 15:05:10 +01:00
|
|
|
for (auto& lev : Levels)
|
2020-12-21 13:16:29 -03:00
|
|
|
{
|
2021-06-16 15:05:10 +01:00
|
|
|
delete lev;
|
2020-12-21 13:16:29 -03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-16 15:05:10 +01:00
|
|
|
void GameFlow::SetLanguageNames(sol::as_table_t<std::vector<std::string>> && src)
|
2020-12-21 13:16:29 -03:00
|
|
|
{
|
2021-06-16 15:05:10 +01:00
|
|
|
m_languageNames = std::move(src);
|
2020-12-21 13:16:29 -03:00
|
|
|
}
|
|
|
|
|
2021-06-16 15:05:10 +01:00
|
|
|
void GameFlow::SetStrings(sol::nested<std::unordered_map<std::string, std::vector<std::string>>> && src)
|
2020-12-21 13:16:29 -03:00
|
|
|
{
|
2021-06-16 15:05:10 +01:00
|
|
|
m_translationsMap = std::move(src);
|
2020-12-21 13:16:29 -03:00
|
|
|
}
|
|
|
|
|
2021-06-16 15:05:10 +01:00
|
|
|
//hardcoded for now
|
|
|
|
void GameFlow::WriteDefaults()
|
2020-12-21 13:16:29 -03:00
|
|
|
{
|
2021-06-16 15:05:10 +01:00
|
|
|
Intro = "SCREENS\\MAIN.PNG";
|
|
|
|
EnableLoadSave = true;
|
|
|
|
PlayAnyLevel = true;
|
|
|
|
FlyCheat = true;
|
|
|
|
DebugMode = false;
|
|
|
|
LevelFarView = 0;
|
2020-12-21 13:16:29 -03:00
|
|
|
}
|
|
|
|
|
2021-06-16 15:05:10 +01:00
|
|
|
void GameFlow::AddLevel(GameScriptLevel const& level)
|
2020-12-21 13:16:29 -03:00
|
|
|
{
|
2021-06-16 15:05:10 +01:00
|
|
|
Levels.push_back(new GameScriptLevel{ level });
|
2020-12-21 13:16:29 -03:00
|
|
|
}
|
|
|
|
|
2021-06-26 07:36:54 +02:00
|
|
|
void GameFlow::SetAudioTracks(sol::as_table_t<std::vector<GameScriptAudioTrack>>&& src)
|
|
|
|
{
|
|
|
|
std::vector<GameScriptAudioTrack> tracks = std::move(src);
|
|
|
|
for (auto t : tracks) {
|
2021-06-16 15:05:10 +01:00
|
|
|
AudioTrack track;
|
2021-06-26 07:36:54 +02:00
|
|
|
track.Name = t.trackName;
|
2021-06-16 15:05:10 +01:00
|
|
|
track.Mask = 0;
|
2021-06-26 07:36:54 +02:00
|
|
|
track.looped = t.looped;
|
|
|
|
g_AudioTracks.insert_or_assign(track.Name, track);
|
2021-06-16 15:05:10 +01:00
|
|
|
}
|
2020-12-21 13:16:29 -03:00
|
|
|
}
|
|
|
|
|
2021-06-16 15:05:10 +01:00
|
|
|
bool GameFlow::LoadGameFlowScript()
|
2020-12-21 13:16:29 -03:00
|
|
|
{
|
2021-06-23 05:58:24 +02:00
|
|
|
// Load the enums file
|
2021-06-16 15:05:10 +01:00
|
|
|
std::string err;
|
2021-06-23 05:58:24 +02:00
|
|
|
if (!ExecuteScript("Scripts/Enums.lua", err)) {
|
|
|
|
std::cout << err << "\n";
|
|
|
|
}
|
|
|
|
|
2021-06-26 07:36:54 +02:00
|
|
|
// Load the new audio tracks file
|
|
|
|
if (!ExecuteScript("Scripts/Tracks.lua", err)) {
|
|
|
|
std::cout << err << "\n";
|
|
|
|
}
|
|
|
|
|
2021-06-23 05:58:24 +02:00
|
|
|
// Load the new script file
|
2021-06-16 15:05:10 +01:00
|
|
|
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
|
2021-06-20 06:33:44 +02:00
|
|
|
if (!ExecuteScript("Scripts/Strings.lua", err)) {
|
2021-06-16 15:05:10 +01:00
|
|
|
std::cout << err << "\n";
|
|
|
|
}
|
2020-12-21 13:16:29 -03:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2021-07-23 21:48:49 +01:00
|
|
|
char const * GameFlow::GetString(const char* id)
|
2020-12-21 13:16:29 -03:00
|
|
|
{
|
2021-06-20 06:33:44 +02: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];
|
2021-06-23 05:58:24 +02:00
|
|
|
|
2021-06-26 07:36:54 +02:00
|
|
|
CurrentAtmosphere = level->AmbientTrack;
|
2020-12-21 13:16:29 -03:00
|
|
|
|
|
|
|
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
|
|
|
|
{
|
2021-06-23 05:58:24 +02:00
|
|
|
// 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;
|
|
|
|
}
|
|
|
|
|
2018-09-22 23:54:36 +02:00
|
|
|
GameFlow* g_GameFlow;
|