mirror of
https://github.com/DrBeef/Raze.git
synced 2024-11-15 08:52:00 +00:00
- scriptified Exhumed's 2D content (minus the programmatic textures.)
This commit is contained in:
parent
5b54e9c1ad
commit
4069a5096a
27 changed files with 1522 additions and 1257 deletions
|
@ -550,7 +550,21 @@ DEFINE_ACTION_FUNCTION_NATIVE(FStringStruct, ToDouble, StringToDbl)
|
|||
ACTION_RETURN_FLOAT(self->ToDouble());
|
||||
}
|
||||
|
||||
static void StringSplit(FString *self, TArray<FString> *tokens, const FString &delimiter, int keepEmpty)
|
||||
static void StringSubst(FString *self, const FString &substr, const FString& replc)
|
||||
{
|
||||
self->Substitute(substr, replc);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION_NATIVE(FStringStruct, Substitute, StringSubst)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(FString);
|
||||
PARAM_STRING(substr);
|
||||
PARAM_STRING(replc);
|
||||
StringSubst(self, substr, replc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void StringSplit(FString* self, TArray<FString>* tokens, const FString& delimiter, int keepEmpty)
|
||||
{
|
||||
self->Split(*tokens, delimiter, static_cast<FString::EmptyTokenType>(keepEmpty));
|
||||
}
|
||||
|
|
|
@ -881,6 +881,13 @@ DEFINE_ACTION_FUNCTION(FKeyBindings, GetAllKeysForCommand)
|
|||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(FKeyBindings, GetBinding)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(FKeyBindings);
|
||||
PARAM_INT(key);
|
||||
ACTION_RETURN_STRING(self->GetBinding(key));
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(FKeyBindings, UnbindACommand)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(FKeyBindings);
|
||||
|
@ -928,6 +935,7 @@ DEFINE_GLOBAL_NAMED(mus_playing, musplaying);
|
|||
DEFINE_FIELD_X(MusPlayingInfo, MusPlayingInfo, name);
|
||||
DEFINE_FIELD_X(MusPlayingInfo, MusPlayingInfo, baseorder);
|
||||
DEFINE_FIELD_X(MusPlayingInfo, MusPlayingInfo, loop);
|
||||
DEFINE_FIELD_X(MusPlayingInfo, MusPlayingInfo, handle);
|
||||
|
||||
DEFINE_GLOBAL_NAMED(PClass::AllClasses, AllClasses)
|
||||
DEFINE_GLOBAL(Bindings)
|
||||
|
|
|
@ -69,11 +69,11 @@ constexpr double BAngToDegree = 360. / 2048.;
|
|||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
inline int32_t bsin(const int ang, const int8_t shift = 0)
|
||||
inline int bsin(const int ang, const int shift = 0)
|
||||
{
|
||||
return shift < 0 ? sintable[ang & 2047] >> abs(shift) : sintable[ang & 2047] << shift;
|
||||
}
|
||||
inline double bsinf(const double ang, const int8_t shift = 0)
|
||||
inline double bsinf(const double ang, const int shift = 0)
|
||||
{
|
||||
return g_sin(ang * BAngRadian) * (shift >= -SINSHIFT ? uint64_t(1) << (SINSHIFT + shift) : 1. / (uint64_t(1) << abs(SINSHIFT + shift)));
|
||||
}
|
||||
|
@ -85,11 +85,11 @@ inline double bsinf(const double ang, const int8_t shift = 0)
|
|||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
inline int32_t bcos(const int ang, const int8_t shift = 0)
|
||||
inline int bcos(const int ang, const int shift = 0)
|
||||
{
|
||||
return shift < 0 ? sintable[(ang + 512) & 2047] >> abs(shift) : sintable[(ang + 512) & 2047] << shift;
|
||||
}
|
||||
inline double bcosf(const double ang, const int8_t shift = 0)
|
||||
inline double bcosf(const double ang, const int shift = 0)
|
||||
{
|
||||
return g_cos(ang * BAngRadian) * (shift >= -SINSHIFT ? uint64_t(1) << (SINSHIFT + shift) : 1. / (uint64_t(1) << abs(SINSHIFT + shift)));
|
||||
}
|
||||
|
|
|
@ -555,7 +555,7 @@ int GameMain()
|
|||
I_ShowFatalError(err.what());
|
||||
r = -1;
|
||||
}
|
||||
DeleteScreenJob();
|
||||
//DeleteScreenJob();
|
||||
DeinitMenus();
|
||||
if (StatusBar) StatusBar->Destroy();
|
||||
StatusBar = nullptr;
|
||||
|
@ -1479,6 +1479,22 @@ DEFINE_ACTION_FUNCTION(_Raze, PlayerName)
|
|||
ACTION_RETURN_STRING(unsigned(index) >= MAXPLAYERS ? "" : PlayerName(index));
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION_NATIVE(_Raze, bsin, bsin)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_INT(v);
|
||||
PARAM_INT(shift);
|
||||
ACTION_RETURN_INT(bsin(v, shift));
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION_NATIVE(_Raze, bcos, bcos)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_INT(v);
|
||||
PARAM_INT(shift);
|
||||
ACTION_RETURN_INT(bcos(v, shift));
|
||||
}
|
||||
|
||||
extern bool demoplayback;
|
||||
DEFINE_GLOBAL(multiplayer)
|
||||
DEFINE_GLOBAL(netgame)
|
||||
|
|
|
@ -136,7 +136,9 @@ bool newGameStarted;
|
|||
void NewGame(MapRecord* map, int skill, bool ns = false)
|
||||
{
|
||||
newGameStarted = true;
|
||||
ShowIntermission(nullptr, map, nullptr, [=](bool) { gi->NewGame(map, skill, ns); });
|
||||
ShowIntermission(nullptr, map, nullptr, [=](bool) {
|
||||
gi->NewGame(map, skill, ns);
|
||||
});
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
@ -148,15 +148,18 @@ void CallCreateMapFunction(const char* qname, DObject* runner, MapRecord* map)
|
|||
//
|
||||
//=============================================================================
|
||||
|
||||
void CallCreateSummaryFunction(const char* qname, DObject* runner, MapRecord* map, SummaryInfo* info)
|
||||
void CallCreateSummaryFunction(const char* qname, DObject* runner, MapRecord* map, SummaryInfo* info, MapRecord* map2)
|
||||
{
|
||||
auto func = LookupFunction(qname);
|
||||
if (func->Proto->ArgumentTypes.Size() != 3) I_Error("Bad map-cutscene function %s. Must receive precisely three arguments.", qname);
|
||||
if (func->Proto->ArgumentTypes[0] != runnerclasstype && func->Proto->ArgumentTypes[1] != maprecordtype && func->Proto->ArgumentTypes[2] != summaryinfotype)
|
||||
I_Error("Bad cutscene function %s. Must receive ScreenJobRunner, MapRecord and SummaryInfo reference.", qname);
|
||||
summaryinfo = *info; // must be copied to a persistent location.
|
||||
VMValue val[3] = { runner, map, &summaryinfo };
|
||||
VMCall(func, val, 3, nullptr, 0);
|
||||
auto s = func->Proto->ArgumentTypes.Size();
|
||||
auto at = func->Proto->ArgumentTypes.Data();
|
||||
if (s != 3 && s != 4) I_Error("Bad map-cutscene function %s. Must receive precisely three or four arguments.", qname);
|
||||
if (at[0] != runnerclasstype && at[1] != maprecordtype && at[2] != summaryinfotype && (s == 3 || at[3] == maprecordtype))
|
||||
I_Error("Bad cutscene function %s. Must receive ScreenJobRunner, MapRecord and SummaryInfo reference,", qname);
|
||||
if (info) summaryinfo = *info; // must be copied to a persistent location.
|
||||
else summaryinfo = {};
|
||||
VMValue val[] = { runner, map, &summaryinfo, map2 };
|
||||
VMCall(func, val, s, nullptr, 0);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
@ -480,8 +483,9 @@ void ShowIntermission(MapRecord* fromMap, MapRecord* toMap, SummaryInfo* info, C
|
|||
globalCutscenes.DefaultMapOutro.Create(runner, fromMap, !!toMap);
|
||||
}
|
||||
|
||||
CallCreateSummaryFunction(globalCutscenes.SummaryScreen, runner, fromMap, info);
|
||||
}
|
||||
if (fromMap || (g_gameType & GAMEFLAG_PSEXHUMED))
|
||||
CallCreateSummaryFunction(globalCutscenes.SummaryScreen, runner, fromMap, info, toMap);
|
||||
|
||||
if (toMap)
|
||||
{
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -90,12 +90,6 @@ END_PS_NS
|
|||
|
||||
using namespace Exhumed;
|
||||
|
||||
DEFINE_ACTION_FUNCTION(_ListMenuItemExhumedPlasma, Draw)
|
||||
{
|
||||
menu_DoPlasma();
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(_ListMenuItemExhumedLogo, Draw)
|
||||
{
|
||||
auto nLogoTile = GameLogo();
|
||||
|
|
|
@ -244,6 +244,15 @@ double calc_smoothratio()
|
|||
return I_GetTimeFrac() * MaxSmoothRatio;
|
||||
}
|
||||
|
||||
void DoGameOverScene(bool finallevel)
|
||||
{
|
||||
// todo: make these customizable later.
|
||||
StartCutscene(finallevel ? "ExhumedCutscenes.BuildCinemaLose" : "ExhumedCutscenes.BuildGameoverScene", 0, [](bool)
|
||||
{
|
||||
gameaction = ga_mainmenu;
|
||||
});
|
||||
}
|
||||
|
||||
void GameMove(void)
|
||||
{
|
||||
FixPalette();
|
||||
|
@ -646,7 +655,6 @@ void SerializeState(FSerializer& arc)
|
|||
("bsnakecam", bSnakeCam)
|
||||
("slipmode", bSlipMode)
|
||||
("PlayClock", PlayClock)
|
||||
("cinemaseen", nCinemaSeen)
|
||||
("spiritsprite", nSpiritSprite)
|
||||
.EndObject();
|
||||
}
|
||||
|
|
|
@ -81,7 +81,7 @@ void DoSpiritHead();
|
|||
|
||||
void CheckKeys2();
|
||||
void GameTicker();
|
||||
void InitLevel(int);
|
||||
void InitLevel(MapRecord*);
|
||||
void InitNewGame();
|
||||
|
||||
int showmap(short nLevel, short nLevelNew, short nLevelBest);
|
||||
|
@ -124,7 +124,6 @@ extern short nCurBodyNum;
|
|||
extern short nBodyTotal;
|
||||
|
||||
extern short bSnakeCam;
|
||||
extern uint8_t nCinemaSeen;
|
||||
|
||||
extern short nButtonColor;
|
||||
|
||||
|
@ -152,11 +151,6 @@ extern short bDoFlashes;
|
|||
|
||||
extern int bVanilla;
|
||||
|
||||
inline int PublisherLogo()
|
||||
{
|
||||
return (g_gameType & GAMEFLAG_EXHUMED) ? kTileBMGLogo : kTilePIELogo;
|
||||
}
|
||||
|
||||
inline int GameLogo()
|
||||
{
|
||||
return (g_gameType & GAMEFLAG_EXHUMED) ? kExhumedLogo : kPowerslaveLogo;
|
||||
|
@ -198,6 +192,7 @@ public:
|
|||
void DisplayText();
|
||||
bool AdvanceCinemaText(double clock);
|
||||
void SetPalette(int pal) { currentCinemaPalette = pal; }
|
||||
void Create(const FString& text, int pal);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -49,13 +49,12 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|||
#include "automap.h"
|
||||
#include "raze_music.h"
|
||||
#include "v_draw.h"
|
||||
#include "vm.h"
|
||||
|
||||
BEGIN_PS_NS
|
||||
|
||||
short nBestLevel;
|
||||
|
||||
extern uint8_t nCinemaSeen;
|
||||
|
||||
void RunCinemaScene(int num);
|
||||
void GameMove(void);
|
||||
void DrawClock();
|
||||
|
@ -116,33 +115,87 @@ void GameInterface::DrawBackground()
|
|||
|
||||
void GameInterface::NextLevel(MapRecord *map, int skill)
|
||||
{
|
||||
InitLevel(map->levelNumber);
|
||||
InitLevel(map);
|
||||
|
||||
if (map->levelNumber > nBestLevel)
|
||||
if (map->levelNumber >= nBestLevel)
|
||||
{
|
||||
nBestLevel = selectedlevelnew;
|
||||
nBestLevel = map->levelNumber - 1;
|
||||
}
|
||||
|
||||
if (map->levelNumber == 11) nCinemaSeen |= 2;
|
||||
STAT_NewLevel(currentLevel->labelName);
|
||||
|
||||
}
|
||||
|
||||
void Intermission(MapRecord* from_map, MapRecord* to_map);
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void GameInterface::NewGame(MapRecord *map, int skill, bool frommenu)
|
||||
{
|
||||
// start a new game on the given level
|
||||
InitNewGame();
|
||||
if (map->levelNumber == 1) STAT_StartNewGame("Exhumed", 1);
|
||||
Intermission(nullptr, map);
|
||||
InitLevel(map);
|
||||
gameaction = ga_level;
|
||||
}
|
||||
|
||||
void GameInterface::LevelCompleted(MapRecord *map, int skill)
|
||||
int selectedlevelnew;
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DMapScreen, SetNextLevel)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_INT(v);
|
||||
selectedlevelnew = v;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void GameInterface::LevelCompleted(MapRecord *to_map, int skill)
|
||||
{
|
||||
Mus_Stop();
|
||||
if (currentLevel->levelNumber == 0) gameaction = ga_mainmenu;
|
||||
Intermission(currentLevel, map);
|
||||
if (currentLevel->levelNumber == 0)
|
||||
{
|
||||
gameaction = ga_mainmenu;
|
||||
return;
|
||||
}
|
||||
|
||||
StopAllSounds();
|
||||
bCamera = false;
|
||||
automapMode = am_off;
|
||||
|
||||
STAT_Update(to_map == nullptr);
|
||||
if (to_map)
|
||||
{
|
||||
if (to_map->levelNumber > nBestLevel) nBestLevel = to_map->levelNumber - 1;
|
||||
|
||||
if (to_map->levelNumber == 20) nPlayerLives[0] = 0;
|
||||
if (to_map->levelNumber == 0) // skip all intermission stuff when going to the training map.
|
||||
{
|
||||
gameaction = ga_nextlevel;
|
||||
return;
|
||||
}
|
||||
}
|
||||
SummaryInfo info{};
|
||||
info.kills = nCreaturesKilled;
|
||||
info.maxkills = nCreaturesTotal;
|
||||
info.supersecrets = nBestLevel;
|
||||
info.time = PlayClock * GameTicRate / 120;
|
||||
selectedlevelnew = to_map->levelNumber;
|
||||
ShowIntermission(currentLevel, to_map, &info, [=](bool)
|
||||
{
|
||||
if (!to_map) gameaction = ga_startup; // this was the end of the game
|
||||
else
|
||||
{
|
||||
if (to_map->levelNumber != selectedlevelnew)
|
||||
{
|
||||
// User can switch destination on the scrolling map.
|
||||
g_nextmap = FindMapByLevelNum(selectedlevelnew);
|
||||
STAT_Cancel();
|
||||
}
|
||||
gameaction = ga_nextlevel;
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
|
|
@ -66,9 +66,9 @@ uint8_t bIsVersion6 = true;
|
|||
|
||||
|
||||
|
||||
uint8_t LoadLevel(int nMap)
|
||||
uint8_t LoadLevel(MapRecord* map)
|
||||
{
|
||||
if (nMap == kMap20)
|
||||
if (map->levelNumber == kMap20)
|
||||
{
|
||||
lCountDown = 81000;
|
||||
nAlarmTicks = 30;
|
||||
|
@ -116,12 +116,12 @@ uint8_t LoadLevel(int nMap)
|
|||
InitItems();
|
||||
InitInput();
|
||||
|
||||
if (nMap == kMap20) {
|
||||
if (map->levelNumber == kMap20) {
|
||||
InitEnergyTile();
|
||||
}
|
||||
}
|
||||
|
||||
if (nMap > 15)
|
||||
if (map->levelNumber > 15)
|
||||
{
|
||||
nSwitchSound = 35;
|
||||
nStoneSound = 23;
|
||||
|
@ -136,10 +136,6 @@ uint8_t LoadLevel(int nMap)
|
|||
nStopSound = 66;
|
||||
}
|
||||
|
||||
if (nMap < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
vec3_t startPos;
|
||||
engineLoadBoard(currentLevel->fileName, 0, &startPos, &inita, &initsect);
|
||||
initx = startPos.x;
|
||||
|
@ -172,12 +168,12 @@ uint8_t LoadLevel(int nMap)
|
|||
return true;
|
||||
}
|
||||
|
||||
void InitLevel(int level) // todo: use a map record
|
||||
void InitLevel(MapRecord* map)
|
||||
{
|
||||
StopCD();
|
||||
currentLevel = FindMapByLevelNum(level);
|
||||
if (!LoadLevel(level)) {
|
||||
I_Error("Can't load level %d...\n", level);
|
||||
currentLevel = map;
|
||||
if (!LoadLevel(map)) {
|
||||
I_Error("Cannot load %s...\n", map->fileName.GetChars());
|
||||
}
|
||||
|
||||
for (int i = 0; i < nTotalPlayers; i++)
|
||||
|
@ -200,7 +196,7 @@ void InitLevel(int level) // todo: use a map record
|
|||
|
||||
RefreshStatus();
|
||||
|
||||
int nTrack = level;
|
||||
int nTrack = map->levelNumber;
|
||||
if (nTrack != 0) nTrack--;
|
||||
|
||||
playCDtrack((nTrack % 8) + 11, true);
|
||||
|
@ -210,7 +206,6 @@ void InitLevel(int level) // todo: use a map record
|
|||
void InitNewGame()
|
||||
{
|
||||
bCamera = false;
|
||||
nCinemaSeen = 0;
|
||||
PlayerCount = 0;
|
||||
|
||||
for (int i = 0; i < nTotalPlayers; i++)
|
||||
|
|
|
@ -43,8 +43,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|||
BEGIN_PS_NS
|
||||
|
||||
|
||||
uint8_t nCinemaSeen;
|
||||
|
||||
uint8_t energytile[66 * 66] = {0};
|
||||
|
||||
uint8_t *cur;
|
||||
|
|
|
@ -28,6 +28,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|||
#include "s_music.h"
|
||||
#include "screenjob.h"
|
||||
#include "v_draw.h"
|
||||
#include "vm.h"
|
||||
|
||||
BEGIN_PS_NS
|
||||
|
||||
|
@ -63,9 +64,34 @@ class LMFPlayer
|
|||
AudioData audio{};
|
||||
AnimTextures animtex;
|
||||
|
||||
FileReader fp;
|
||||
|
||||
int nFrame = 0;
|
||||
|
||||
uint64_t nextclock = 0;
|
||||
|
||||
public:
|
||||
|
||||
LMFPlayer(const char *filename)
|
||||
{
|
||||
fp = fileSystem.OpenFileReader(filename);
|
||||
Open(fp);
|
||||
}
|
||||
|
||||
bool Frame(uint64_t clock)
|
||||
{
|
||||
if (clock >= nextclock)
|
||||
{
|
||||
nextclock += 100'000'000;
|
||||
if (ReadFrame(fp) == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int ReadFrame(FileReader& fp)
|
||||
{
|
||||
nFrame++;
|
||||
|
@ -188,107 +214,56 @@ public:
|
|||
S_StopCustomStream(stream);
|
||||
}
|
||||
|
||||
AnimTextures& animTex()
|
||||
FTextureID GetTexture()
|
||||
{
|
||||
return animtex;
|
||||
return animtex.GetFrameID();
|
||||
}
|
||||
};
|
||||
|
||||
#if 0
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
class DLmfPlayer : public DSkippableScreenJob
|
||||
int IdentifyLMF(const FString* fn)
|
||||
{
|
||||
LMFPlayer decoder;
|
||||
double angle = 1536;
|
||||
double z = 0;
|
||||
uint64_t nextclock = 0, lastclock = 0;
|
||||
FileReader fp;
|
||||
|
||||
public:
|
||||
|
||||
DLmfPlayer(FileReader& fr)
|
||||
{
|
||||
decoder.Open(fr);
|
||||
lastclock = 0;
|
||||
nextclock = 0;
|
||||
fp = std::move(fr);
|
||||
pausable = false;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void Draw(double smoothratio) override
|
||||
{
|
||||
uint64_t clock = (ticks + smoothratio) * 1'000'000'000. / GameTicRate;
|
||||
if (clock >= nextclock)
|
||||
{
|
||||
nextclock += 100'000'000;
|
||||
if (decoder.ReadFrame(fp) == 0)
|
||||
{
|
||||
state = finished;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
double duration = (clock - lastclock) * double(120. / 8'000'000'000);
|
||||
if (z < 65536) { // Zoom - normal zoom is 65536.
|
||||
z += 2048 * duration;
|
||||
}
|
||||
if (z > 65536) z = 65536;
|
||||
if (angle != 0) {
|
||||
angle += 16. * duration;
|
||||
if (angle >= 2048) {
|
||||
angle = 0;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
twod->ClearScreen();
|
||||
DrawTexture(twod, decoder.animTex().GetFrame(), 160, 100, DTA_FullscreenScale, FSMode_Fit320x200,
|
||||
DTA_CenterOffset, true, DTA_FlipY, true, DTA_ScaleX, z / 65536., DTA_ScaleY, z / 65536., DTA_Rotate, (-angle - 512) * BAngToDegree, TAG_DONE);
|
||||
}
|
||||
|
||||
lastclock = clock;
|
||||
}
|
||||
|
||||
void OnDestroy() override
|
||||
{
|
||||
decoder.Close();
|
||||
fp.Close();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
DScreenJob* PlayMovie(const char* fileName)
|
||||
{
|
||||
// clear keys
|
||||
|
||||
auto fp = fileSystem.OpenFileReader(fileName);
|
||||
if (!fp.isOpen())
|
||||
{
|
||||
return Create<DBlackScreen>(1);
|
||||
}
|
||||
auto fp = fileSystem.OpenFileReader(*fn);
|
||||
if (!fp.isOpen()) return false;
|
||||
char buffer[4];
|
||||
fp.Read(buffer, 4);
|
||||
if (memcmp(buffer, "LMF ", 4))
|
||||
{
|
||||
fp.Close();
|
||||
// Allpw replacement with more modern formats.
|
||||
return PlayVideo(fileName);
|
||||
}
|
||||
fp.Seek(0, FileReader::SeekSet);
|
||||
return Create<DLmfPlayer>(fp);
|
||||
return (0 == memcmp(buffer, "LMF ", 4));
|
||||
}
|
||||
#endif
|
||||
|
||||
DEFINE_ACTION_FUNCTION(_LMFDecoder, Create)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_STRING(fn);
|
||||
ACTION_RETURN_POINTER(new LMFPlayer(fn));
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION_NATIVE(_LMFDecoder, Identify, IdentifyLMF)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_STRING(fn);
|
||||
ACTION_RETURN_BOOL(IdentifyLMF(&fn));
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(_LMFDecoder, Frame)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(LMFPlayer);
|
||||
PARAM_FLOAT(clock);
|
||||
ACTION_RETURN_BOOL(self->Frame(uint64_t(clock)));
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(_LMFDecoder, GetTexture)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(LMFPlayer);
|
||||
ACTION_RETURN_INT(self->GetTexture().GetIndex());
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(_LMFDecoder, Close)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(LMFPlayer);
|
||||
self->Close();
|
||||
delete self;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
END_PS_NS
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
x(SkullJaw, 3437)
|
||||
x(PowerslaveLogo, 3442)
|
||||
x(MenuNewGameTile, 3460)
|
||||
x(MenuLoadGameTile, 3461)
|
||||
|
@ -6,6 +7,7 @@ x(MenuSoundFxTile, 3466)
|
|||
x(MenuCursorTile, 3468)
|
||||
x(MenuBlank, 3469)
|
||||
x(SkullHead, 3582)
|
||||
x(SkullJaw2, 3583)
|
||||
x(ExhumedLogo, 3592)
|
||||
x(Energy1, 3604)
|
||||
x(Energy2, 3605)
|
||||
|
@ -27,4 +29,100 @@ x(ClockSymbol15, 3620)
|
|||
x(ClockSymbol16, 3621)
|
||||
x(TileLoboLaptop, 3623)
|
||||
x(TileBMGLogo, 3368)
|
||||
x(LobotomyLogo, 3348)
|
||||
x(TilePIELogo, 3349)
|
||||
x(Gameover, 3591)
|
||||
|
||||
x(MapPlaque1_01, 3376)
|
||||
x(MapPlaque1_02, 3378)
|
||||
x(MapPlaque1_03, 3380)
|
||||
x(MapPlaque1_04, 3382)
|
||||
x(MapPlaque1_05, 3384)
|
||||
x(MapPlaque1_06, 3371)
|
||||
x(MapPlaque1_07, 3387)
|
||||
x(MapPlaque1_08, 3389)
|
||||
x(MapPlaque1_09, 3391)
|
||||
x(MapPlaque1_10, 3409)
|
||||
x(MapPlaque1_11, 3393)
|
||||
x(MapPlaque1_12, 3395)
|
||||
x(MapPlaque1_13, 3397)
|
||||
x(MapPlaque1_14, 3399)
|
||||
x(MapPlaque1_15, 3401)
|
||||
x(MapPlaque1_16, 3403)
|
||||
x(MapPlaque1_17, 3405)
|
||||
x(MapPlaque1_18, 3407)
|
||||
x(MapPlaque1_19, 3412)
|
||||
x(MapPlaque1_20, 3415)
|
||||
|
||||
x(MapPlaque2_01, 3377)
|
||||
x(MapPlaque2_02, 3379)
|
||||
x(MapPlaque2_03, 3381)
|
||||
x(MapPlaque2_04, 3383)
|
||||
x(MapPlaque2_05, 3385)
|
||||
x(MapPlaque2_06, 3386)
|
||||
x(MapPlaque2_07, 3388)
|
||||
x(MapPlaque2_08, 3390)
|
||||
x(MapPlaque2_09, 3392)
|
||||
x(MapPlaque2_10, 3410)
|
||||
x(MapPlaque2_11, 3394)
|
||||
x(MapPlaque2_12, 3396)
|
||||
x(MapPlaque2_13, 3398)
|
||||
x(MapPlaque2_14, 3400)
|
||||
x(MapPlaque2_15, 3402)
|
||||
x(MapPlaque2_16, 3404)
|
||||
x(MapPlaque2_17, 3406)
|
||||
x(MapPlaque2_18, 3408)
|
||||
x(MapPlaque2_19, 3413)
|
||||
x(MapPlaque2_20, 3416)
|
||||
|
||||
x(MapPlaqueText_01, 3411)
|
||||
x(MapPlaqueText_02, 3414)
|
||||
x(MapPlaqueText_03, 3417)
|
||||
x(MapPlaqueText_04, 3420)
|
||||
x(MapPlaqueText_05, 3423)
|
||||
x(MapPlaqueText_06, 3426)
|
||||
x(MapPlaqueText_07, 3429)
|
||||
x(MapPlaqueText_08, 3432)
|
||||
x(MapPlaqueText_09, 3435)
|
||||
x(MapPlaqueText_10, 3418)
|
||||
x(MapPlaqueText_11, 3438)
|
||||
x(MapPlaqueText_12, 3441)
|
||||
x(MapPlaqueText_13, 3444)
|
||||
x(MapPlaqueText_14, 3447)
|
||||
x(MapPlaqueText_15, 3450)
|
||||
x(MapPlaqueText_16, 3453)
|
||||
x(MapPlaqueText_17, 3456)
|
||||
x(MapPlaqueText_18, 3459)
|
||||
x(MapPlaqueText_19, 3419)
|
||||
x(MapPlaqueText_20, 3421)
|
||||
|
||||
x(MapFire_11, 3484)
|
||||
x(MapFire_12, 3485)
|
||||
x(MapFire_13, 3486)
|
||||
x(MapFire_14, 3487)
|
||||
x(MapFire_21, 3488)
|
||||
x(MapFire_22, 3489)
|
||||
x(MapFire_23, 3490)
|
||||
x(MapFire_24, 3491)
|
||||
x(MapFire_31, 3492)
|
||||
x(MapFire_32, 3493)
|
||||
x(MapFire_33, 3494)
|
||||
x(MapFire_34, 3495)
|
||||
|
||||
x(MapBG01, 3353)
|
||||
x(MapBG02, 3354)
|
||||
x(MapBG03, 3355)
|
||||
x(MapBG04, 3356)
|
||||
x(MapBG05, 3357)
|
||||
x(MapBG06, 3358)
|
||||
x(MapBG07, 3359)
|
||||
x(MapBG08, 3360)
|
||||
x(MapBG09, 3361)
|
||||
x(MapBG10, 3362)
|
||||
|
||||
x(TileCinema5, 3449)
|
||||
x(TileCinema10, 3451)
|
||||
x(TileCinema11, 3454)
|
||||
x(TileCinema15, 3446)
|
||||
x(TileCinemaLose, 3445)
|
||||
x(TileCinema20, 3448)
|
||||
|
|
|
@ -29,136 +29,10 @@ kTileStatusBar = 657,
|
|||
kTile985 = 985,
|
||||
kTile986 = 986,
|
||||
kTile3000 = 3000,
|
||||
kTile3117 = 3117,
|
||||
kQueenChunk = 3117,
|
||||
kTile3126 = 3126,
|
||||
kTile3353 = 3353,
|
||||
kTile3370 = 3370,
|
||||
kTile3371 = 3371,
|
||||
kTile3372 = 3372,
|
||||
kTile3373 = 3373,
|
||||
kTile3374 = 3374,
|
||||
kTile3375 = 3375,
|
||||
kTile3376 = 3376,
|
||||
kTile3377 = 3377,
|
||||
kTile3378 = 3378,
|
||||
kTile3379 = 3379,
|
||||
kTile3380 = 3380,
|
||||
kTile3381 = 3381,
|
||||
kTile3382 = 3382,
|
||||
kTile3383 = 3383,
|
||||
kTile3384 = 3384,
|
||||
kTile3385 = 3385,
|
||||
kTile3386 = 3386,
|
||||
kTile3387 = 3387,
|
||||
kTile3388 = 3388,
|
||||
kTile3389 = 3389,
|
||||
kTile3390 = 3390,
|
||||
kTile3391 = 3391,
|
||||
kTile3392 = 3392,
|
||||
kTile3393 = 3393,
|
||||
kTile3394 = 3394,
|
||||
kTile3395 = 3395,
|
||||
kTile3396 = 3396,
|
||||
kTile3397 = 3397,
|
||||
kTile3398 = 3398,
|
||||
kTile3399 = 3399,
|
||||
kTile3400 = 3400,
|
||||
kTile3401 = 3401,
|
||||
kTile3402 = 3402,
|
||||
kTile3403 = 3403,
|
||||
kTile3404 = 3404,
|
||||
kTile3405 = 3405,
|
||||
kTile3406 = 3406,
|
||||
kTile3407 = 3407,
|
||||
kTile3408 = 3408,
|
||||
kTile3409 = 3409,
|
||||
kTile3410 = 3410,
|
||||
kTile3411 = 3411,
|
||||
kTile3412 = 3412,
|
||||
kTile3413 = 3413,
|
||||
kTile3414 = 3414,
|
||||
kTile3415 = 3415,
|
||||
kTile3416 = 3416,
|
||||
kTile3417 = 3417,
|
||||
kTile3418 = 3418,
|
||||
kTile3419 = 3419,
|
||||
kTile3420 = 3420,
|
||||
kTile3421 = 3421,
|
||||
kTile3422 = 3422,
|
||||
kTile3423 = 3423,
|
||||
kTile3424 = 3424,
|
||||
kTile3425 = 3425,
|
||||
kTile3426 = 3426,
|
||||
kTile3427 = 3427,
|
||||
kTile3428 = 3428,
|
||||
kTile3429 = 3429,
|
||||
kTile3430 = 3430,
|
||||
kTile3431 = 3431,
|
||||
kTile3432 = 3432,
|
||||
kTile3433 = 3433,
|
||||
kTile3434 = 3434,
|
||||
kTile3435 = 3435,
|
||||
kTile3436 = 3436,
|
||||
kSkullJaw = 3437,
|
||||
kTile3438 = 3438,
|
||||
kTile3439 = 3439,
|
||||
kTile3440 = 3440,
|
||||
kTile3441 = 3441,
|
||||
kTile3443 = 3443,
|
||||
kTile3444 = 3444,
|
||||
kTile3445 = 3445,
|
||||
kTile3446 = 3446,
|
||||
kTile3447 = 3447,
|
||||
kTile3448 = 3448,
|
||||
kTile3449 = 3449,
|
||||
kTile3450 = 3450,
|
||||
kTile3451 = 3451,
|
||||
kTile3452 = 3452,
|
||||
kTile3453 = 3453,
|
||||
kTile3454 = 3454,
|
||||
kTile3455 = 3455,
|
||||
kTile3456 = 3456,
|
||||
kTile3457 = 3457,
|
||||
kTile3458 = 3458,
|
||||
kTile3459 = 3459,
|
||||
kTile3462 = 3462,
|
||||
kTile3463 = 3463,
|
||||
kTile3464 = 3464,
|
||||
kTile3467 = 3467,
|
||||
kTile3470 = 3470,
|
||||
kTile3471 = 3471,
|
||||
kTile3472 = 3472,
|
||||
kTile3473 = 3473,
|
||||
kTile3474 = 3474,
|
||||
kTile3475 = 3475,
|
||||
kTile3476 = 3476,
|
||||
kTile3477 = 3477,
|
||||
kTile3478 = 3478,
|
||||
kTile3479 = 3479,
|
||||
kTile3480 = 3480,
|
||||
kTile3481 = 3481,
|
||||
kTile3482 = 3482,
|
||||
kTile3483 = 3483,
|
||||
kTile3484 = 3484,
|
||||
kTile3485 = 3485,
|
||||
kTile3486 = 3486,
|
||||
kTile3487 = 3487,
|
||||
kTile3488 = 3488,
|
||||
kTile3489 = 3489,
|
||||
kTile3490 = 3490,
|
||||
kTile3491 = 3491,
|
||||
kTile3492 = 3492,
|
||||
kTile3493 = 3493,
|
||||
kTile3494 = 3494,
|
||||
kTile3495 = 3495,
|
||||
kTile3496 = 3496,
|
||||
kTile3497 = 3497,
|
||||
kTile3498 = 3498,
|
||||
kTile3499 = 3499,
|
||||
kTile3512 = 3512,
|
||||
kTile3571 = 3571,
|
||||
kTile3583 = 3583,
|
||||
kTile3591 = 3591,
|
||||
kTile3593 = 3593,
|
||||
kTile3603 = 3603,
|
||||
kTile4092 = 4092,
|
||||
|
|
|
@ -1445,7 +1445,7 @@ void FuncQueen(int a, int nDamage, int nRun)
|
|||
{
|
||||
short nChunkSprite = BuildCreatureChunk(nSprite, seq_GetSeqPicnum(kSeqQueen, 57, 0)) & 0xFFFF;
|
||||
|
||||
sprite[nChunkSprite].picnum = kTile3117 + (i % 3);
|
||||
sprite[nChunkSprite].picnum = kQueenChunk + (i % 3);
|
||||
sprite[nChunkSprite].xrepeat = 100;
|
||||
sprite[nChunkSprite].yrepeat = 100;
|
||||
}
|
||||
|
|
|
@ -800,4 +800,35 @@ void PlayGameOverSound(void)
|
|||
PlayLocalSound(StaticSound[kSoundJonLaugh2], 0, false, CHANF_UI);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(_Exhumed, PlayLocalSound)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_INT(snd);
|
||||
PARAM_INT(pitch);
|
||||
PARAM_BOOL(unatt);
|
||||
PARAM_INT(flags);
|
||||
PlayLocalSound(StaticSound[snd], pitch, unatt, EChanFlags::FromInt(flags));
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION_NATIVE(_Exhumed, StopLocalSound, StopLocalSound)
|
||||
{
|
||||
StopLocalSound();
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(_Exhumed, LocalSoundPlaying)
|
||||
{
|
||||
ACTION_RETURN_BOOL(soundEngine->IsSourcePlayingSomething(SOURCE_None, nullptr, CHAN_AUTO, -1));
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(_Exhumed, PlayCDTrack)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_INT(track);
|
||||
PARAM_BOOL(loop);
|
||||
playCDtrack(track, loop);
|
||||
return 0;
|
||||
}
|
||||
|
||||
END_PS_NS
|
||||
|
|
71
wadsrc/static/filter/exhumed/engine/engine.def
Normal file
71
wadsrc/static/filter/exhumed/engine/engine.def
Normal file
|
@ -0,0 +1,71 @@
|
|||
// Cutscene definitions for Duke
|
||||
|
||||
definecutscene intro
|
||||
{
|
||||
function ExhumedCutscenes.BuildIntro
|
||||
}
|
||||
|
||||
definecutscene map lev5
|
||||
{
|
||||
intro
|
||||
{
|
||||
function ExhumedCutscenes.BuildCinemaBefore5
|
||||
}
|
||||
}
|
||||
|
||||
definecutscene map lev10
|
||||
{
|
||||
outro
|
||||
{
|
||||
function ExhumedCutscenes.BuildCinemaAfter10
|
||||
}
|
||||
}
|
||||
|
||||
definecutscene map lev11
|
||||
{
|
||||
intro
|
||||
{
|
||||
function ExhumedCutscenes.BuildCinemaBefore11
|
||||
}
|
||||
}
|
||||
|
||||
definecutscene map lev15
|
||||
{
|
||||
outro
|
||||
{
|
||||
function ExhumedCutscenes.BuildCinemaAfter15
|
||||
}
|
||||
}
|
||||
|
||||
definecutscene map lev20
|
||||
{
|
||||
intro
|
||||
{
|
||||
function ExhumedCutscenes.BuildCinemaBefore20
|
||||
}
|
||||
outro
|
||||
{
|
||||
function ExhumedCutscenes.BuildCinemaAfter20
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
definecutscene gameover
|
||||
{
|
||||
function ExhumedCutscenes.BuildGameoverScene
|
||||
}
|
||||
|
||||
definecutscene lose
|
||||
{
|
||||
function ExhumedCutscenes.BuildCinemaLose
|
||||
}
|
||||
|
||||
definecutscene loading
|
||||
{
|
||||
function DukeCutscenes.BuildLoading
|
||||
}
|
||||
*/
|
||||
|
||||
definecutscene summary ExhumedCutscenes.BuildMap
|
||||
//definecutscene mpsummary DukeCutscenes.BuildMPSummary
|
||||
|
|
@ -39,4 +39,6 @@ version "4.3"
|
|||
#include "zscript/games/sw/swgame.zs"
|
||||
#include "zscript/games/sw/ui/menu.zs"
|
||||
#include "zscript/games/sw/ui/screens.zs"
|
||||
#include "zscript/games/exhumed/exhumedgame.zs"
|
||||
#include "zscript/games/exhumed/ui/menu.zs"
|
||||
#include "zscript/games/exhumed/ui/screens.zs"
|
||||
|
|
|
@ -187,6 +187,8 @@ struct MusPlayingInfo native
|
|||
native String name;
|
||||
native int baseorder;
|
||||
native bool loop;
|
||||
native voidptr handle;
|
||||
|
||||
};
|
||||
|
||||
struct TexMan
|
||||
|
@ -662,6 +664,7 @@ struct StringStruct native
|
|||
native void DeleteLastCharacter();
|
||||
native int CodePointCount() const;
|
||||
native int, int GetNextCodePoint(int position) const;
|
||||
native void Substitute(String str, String replace);
|
||||
}
|
||||
|
||||
struct Translation version("2.4")
|
||||
|
|
|
@ -120,6 +120,21 @@ struct InputEvent native play version("2.4")
|
|||
Key_F12 = 0x58, // DIK_F12
|
||||
Key_Grave = 0x29, // DIK_GRAVE
|
||||
|
||||
KEY_kpad_1 = 0x4f,
|
||||
KEY_kpad_2 = 0x50,
|
||||
KEY_kpad_3 = 0x51,
|
||||
KEY_kpad_4 = 0x4b,
|
||||
KEY_kpad_5 = 0x4c,
|
||||
KEY_kpad_6 = 0x4d,
|
||||
KEY_kpad_7 = 0x47,
|
||||
KEY_kpad_8 = 0x48,
|
||||
KEY_kpad_9 = 0x49,
|
||||
KEY_kpad_0 = 0x52,
|
||||
KEY_kpad_Minus = 0x4a,
|
||||
KEY_kpad_Plus = 0x4e,
|
||||
KEY_kpad_Period = 0x53,
|
||||
|
||||
|
||||
Key_Backspace = 0x0e, // DIK_BACK
|
||||
|
||||
Key_Equals = 0x0d, // DIK_EQUALS
|
||||
|
|
|
@ -40,6 +40,7 @@ struct KeyBindings native version("2.4")
|
|||
|
||||
native int, int GetKeysForCommand(String cmd);
|
||||
native void GetAllKeysForCommand(out array<int> list, String cmd);
|
||||
native String GetBinding(int key);
|
||||
|
||||
native void SetBind(int key, String cmd);
|
||||
native void UnbindACommand (String str);
|
||||
|
|
104
wadsrc/static/zscript/games/exhumed/exhumedgame.zs
Normal file
104
wadsrc/static/zscript/games/exhumed/exhumedgame.zs
Normal file
|
@ -0,0 +1,104 @@
|
|||
|
||||
|
||||
struct Exhumed native
|
||||
{
|
||||
native static void PlayLocalSound(int snd, int pitch, bool b, int chanf);
|
||||
native static void StopLocalSound();
|
||||
native static bool LocalSoundPlaying();
|
||||
native static void playCDTrack(int track, bool looped);
|
||||
native static void DrawPlasma();
|
||||
|
||||
|
||||
static void DrawAbs(String img, int x, int y, int shade = 0)
|
||||
{
|
||||
Screen.DrawTexture(TexMan.CheckForTexture(img, TexMan.Type_Any), false, x, y, DTA_FullscreenScale, FSMode_Fit320x200, DTA_TopLeft, true, DTA_Color, Raze.shadeToLight(shade));
|
||||
}
|
||||
|
||||
static void DRawRel(String img, int x, int y, int shade = 0)
|
||||
{
|
||||
let tex = TexMan.CheckForTexture(img, TexMan.Type_Any);
|
||||
if (!tex.IsValid()) return;
|
||||
let size = TexMan.GetScaledSize(tex);
|
||||
let offs = TexMan.GetScaledOffset(tex);
|
||||
// The integer truncation here is important. Old Build versions were bugged here.
|
||||
x -= (int(size.x) >> 1) + int(offs.x);
|
||||
y -= (int(size.y) >> 1) + int(offs.y);
|
||||
Screen.DrawTexture(tex, false, x, y, DTA_FullscreenScale, FSMode_Fit320x200, DTA_TopLeft, true, DTA_Color, Raze.shadeToLight(shade));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct ExhumedSnd native
|
||||
{
|
||||
enum ESounds
|
||||
{
|
||||
kSound0 = 0,
|
||||
kSound1,
|
||||
kSound2,
|
||||
kSound3,
|
||||
kSound4,
|
||||
kSound5,
|
||||
kSound6,
|
||||
kSound7,
|
||||
kSound8,
|
||||
kSound9,
|
||||
kSoundItemSpecial,
|
||||
kSound11,
|
||||
kSoundTorchOn,
|
||||
kSound13,
|
||||
kSound14,
|
||||
kSound15,
|
||||
kSound16,
|
||||
kSound17,
|
||||
kSound18,
|
||||
kSound19,
|
||||
kSound20,
|
||||
kSound21,
|
||||
kSound22,
|
||||
kSound23,
|
||||
kSound24,
|
||||
kSound25,
|
||||
kSound26,
|
||||
kSound27,
|
||||
kSoundJonLaugh2,
|
||||
kSound29,
|
||||
kSound30,
|
||||
kSound31,
|
||||
kSound32,
|
||||
kSound33,
|
||||
kSound34,
|
||||
kSound35,
|
||||
kSound36,
|
||||
kSound38 = 38,
|
||||
kSound39,
|
||||
kSound40,
|
||||
kSound41,
|
||||
kSound42,
|
||||
kSound43,
|
||||
kSound47 = 47,
|
||||
kSound48 = 48,
|
||||
kSoundQTail = 50,
|
||||
kSound52 = 52,
|
||||
kSoundTauntStart = 53,
|
||||
kSoundJonFDie = 60,
|
||||
kSound61,
|
||||
kSound62,
|
||||
kSound63,
|
||||
kSound64,
|
||||
kSound65,
|
||||
kSound66,
|
||||
kSoundMana1,
|
||||
kSoundMana2,
|
||||
kSoundAmmoPickup,
|
||||
kSound70,
|
||||
kSound71,
|
||||
kSound72,
|
||||
kSoundAlarm,
|
||||
kSound74,
|
||||
kSound75,
|
||||
kSound76,
|
||||
kSound77,
|
||||
kSound78,
|
||||
kSound79,
|
||||
}
|
||||
}
|
|
@ -50,7 +50,10 @@ class ListMenuItemExhumedPlasma : ListMenuItem
|
|||
Super.Init(0, 0);
|
||||
}
|
||||
|
||||
native override void Draw(bool selected, ListMenuDescriptor desc);
|
||||
override void Draw(bool selected, ListMenuDescriptor desc)
|
||||
{
|
||||
Exhumed.DrawPlasma();
|
||||
}
|
||||
}
|
||||
|
||||
class ListMenuItemExhumedLogo : ListMenuItem
|
||||
|
|
927
wadsrc/static/zscript/games/exhumed/ui/screens.zs
Normal file
927
wadsrc/static/zscript/games/exhumed/ui/screens.zs
Normal file
|
@ -0,0 +1,927 @@
|
|||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||
Copyright (C) 2019 sirlemonhead, Nuke.YKT
|
||||
Copyright (C) 2020-2021 Christoph Oelckers
|
||||
This file is part of Raze.
|
||||
PCExhumed is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
struct LMFDecoder native
|
||||
{
|
||||
static native bool Identify(String fn);
|
||||
static native LMFDecoder Create(String fn);
|
||||
native bool Frame(double clock);
|
||||
native TextureID GetTexture();
|
||||
native void Close();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
class LmfPlayer : SkippableScreenJob
|
||||
{
|
||||
LMFDecoder decoder;
|
||||
double nextclock;
|
||||
String fn;
|
||||
|
||||
ScreenJob Init(String filename)
|
||||
{
|
||||
fn = filename;
|
||||
return self;
|
||||
}
|
||||
|
||||
override void Start()
|
||||
{
|
||||
decoder = LMFDecoder.Create(fn);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
override void Draw(double smoothratio)
|
||||
{
|
||||
double clock = (ticks + smoothratio) * 1000000000. / GameTicRate;
|
||||
if (clock >= nextclock)
|
||||
{
|
||||
if (decoder.Frame(clock))
|
||||
{
|
||||
jobstate = finished;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
double duration = clock * (120. / 8000000000.);
|
||||
double z = 2048 * duration;
|
||||
if (z > 65536) z = 65536;
|
||||
|
||||
double angle = 1536. + 16. * duration;
|
||||
if (angle >= 2048.) angle = 0.;
|
||||
|
||||
Screen.DrawTexture(decoder.getTexture(), false, 160, 100, DTA_FullscreenScale, FSMode_Fit320x200,
|
||||
DTA_CenterOffset, true, DTA_FlipY, true, DTA_ScaleX, z / 65536., DTA_ScaleY, z / 65536., DTA_Rotate, (-angle - 512) * (360. / 2048.));
|
||||
}
|
||||
|
||||
override void OnDestroy()
|
||||
{
|
||||
decoder.Close();
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
class LobotomyScreen : ImageScreen
|
||||
{
|
||||
ScreenJob Init(String texname, int fade)
|
||||
{
|
||||
Super.InitNamed(texname, fade);
|
||||
return self;
|
||||
}
|
||||
|
||||
override void OnSkip()
|
||||
{
|
||||
Exhumed.StopLocalSound();
|
||||
}
|
||||
|
||||
override void Start()
|
||||
{
|
||||
Exhumed.PlayLocalSound(ExhumedSnd.kSoundJonLaugh2, 7000, false, CHANF_UI);
|
||||
}
|
||||
|
||||
override void OnTick()
|
||||
{
|
||||
Super.OnTick();
|
||||
if (jobstate == finished) Exhumed.StopLocalSound();
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
||||
class MainTitle : SkippableScreenJob
|
||||
{
|
||||
String a, b;
|
||||
int mystate;
|
||||
int duration;
|
||||
int var_4;
|
||||
int esi;
|
||||
int nCount;
|
||||
int starttime;
|
||||
static const short skullDurations[] = { 6, 25, 43, 50, 68, 78, 101, 111, 134, 158, 173, 230, 600 };
|
||||
|
||||
ScreenJob Init()
|
||||
{
|
||||
Super.Init(fadein);
|
||||
a = StringTable.Localize("$TXT_EX_COPYRIGHT1");
|
||||
b = StringTable.Localize("$TXT_EX_COPYRIGHT2");
|
||||
duration = skullDurations[0];
|
||||
esi = 130;
|
||||
return self;
|
||||
}
|
||||
|
||||
override void Start()
|
||||
{
|
||||
Exhumed.PlayLocalSound(59, 0, true, CHANF_UI);
|
||||
Exhumed.playCDtrack(19, true);
|
||||
}
|
||||
|
||||
override void OnTick()
|
||||
{
|
||||
int ticker = ticks * 120 / GameTicRate;
|
||||
if (ticks > 1 && mystate == 0 && !Exhumed.LocalSoundPlaying())
|
||||
{
|
||||
if (random(0, 15))
|
||||
Exhumed.PlayLocalSound(ExhumedSnd.kSoundJonLaugh2, 0, false, CHANF_UI);
|
||||
else
|
||||
Exhumed.PlayLocalSound(61, 0, false, CHANF_UI);
|
||||
mystate = 1;
|
||||
starttime = ticker;
|
||||
}
|
||||
if (mystate == 1)
|
||||
{
|
||||
if (ticker > duration)
|
||||
{
|
||||
nCount++;
|
||||
if (nCount > 12)
|
||||
{
|
||||
jobstate = finished;
|
||||
return;
|
||||
}
|
||||
duration = starttime + skullDurations[nCount];
|
||||
var_4 = var_4 == 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override void Draw(double sr)
|
||||
{
|
||||
Exhumed.DrawPlasma();
|
||||
Exhumed.DrawRel("SkullHead", 160, 100);
|
||||
if (mystate == 0)
|
||||
{
|
||||
Exhumed.DrawRel("SkullJaw", 161, 130);
|
||||
}
|
||||
else
|
||||
{
|
||||
int nStringWidth = SmallFont.StringWidth(a);
|
||||
Screen.DrawText(SmallFont, Font.CR_UNTRANSLATED, 160 - nStringWidth / 2, 200 - 24, a, DTA_FullscreenScale, FSMode_Fit320x200);
|
||||
nStringWidth = SmallFont.StringWidth(b);
|
||||
Screen.DrawText(SmallFont, Font.CR_UNTRANSLATED, 160 - nStringWidth / 2, 200 - 16, b, DTA_FullscreenScale, FSMode_Fit320x200);
|
||||
|
||||
|
||||
String nTile = "SkullJaw";
|
||||
|
||||
if (var_4)
|
||||
{
|
||||
if (esi >= 135) nTile = "SkullJaw2";
|
||||
else esi += 5;
|
||||
}
|
||||
else if (esi <= 130) esi = 130;
|
||||
else esi -= 2;
|
||||
|
||||
int y;
|
||||
|
||||
if (nTile == "SkullJaw2")
|
||||
{
|
||||
y = 131;
|
||||
}
|
||||
else
|
||||
{
|
||||
y = esi;
|
||||
if (y > 135) y = 135;
|
||||
}
|
||||
|
||||
Exhumed.DrawRel(nTile, 161, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
class MapScreen : ScreenJob
|
||||
{
|
||||
static const int MapLevelOffsets[] = { 0, 50, 10, 20, 0, 45, -20, 20, 5, 0, -10, 10, 30, -20, 0, 20, 0, 0, 0, 0 };
|
||||
static const int MapPlaqueX[] = { 100, 230, 180, 10, 210, 10, 10, 140, 30, 200, 145, 80, 15, 220, 190, 20, 220, 20, 200, 20 };
|
||||
static const int MapPlaqueY[] = { 170, 10, 125, 95, 160, 110, 50, 0, 20, 150, 170, 80, 0, 35, 40, 130, 160, 10, 10, 10 };
|
||||
static const int MapPlaqueTextX[] = { 18, 18, 18, 18, 18, 18, 18, 18, 18, 20, 18, 18, 18, 18, 18, 19, 18, 18, 18, 19 };
|
||||
static const int MapPlaqueTextY[] = { 6, 6, 6, 6, 6, 6, 6, 6, 6, 4, 6, 6, 5, 6, 6, 6, 6, 6, 5, 4 };
|
||||
|
||||
static const int FireTilesX[] = { 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1 };
|
||||
static const int FireTilesY[] = { 3, 0, 3, 0, 0, 0, 1, 1, 2, 0, 2, 0 };
|
||||
|
||||
static const int MapLevelFires[] = {
|
||||
3, 0, 107, 95 , 1, 58, 140 , 2, 28, 38 ,
|
||||
3, 2, 240, 0 , 0, 237, 32 , 1, 200, 30 ,
|
||||
2, 2, 250, 57 , 0, 250, 43 , 2, 200, 70 ,
|
||||
2, 1, 82, 59 , 2, 84, 16 , 0, 10, 95 ,
|
||||
2, 2, 237, 50 , 1, 215, 42 , 1, 210, 50 ,
|
||||
3, 0, 40, 7 , 1, 75, 6 , 2, 100, 10 ,
|
||||
3, 0, 58, 61 , 1, 85, 80 , 2, 111, 63 ,
|
||||
3, 0, 260, 65 , 1, 228, 0 , 2, 259, 15 ,
|
||||
2, 0, 81, 38 , 2, 58, 38 , 2, 30, 20 ,
|
||||
3, 0, 259, 49 , 1, 248, 76 , 2, 290, 65 ,
|
||||
3, 2, 227, 66 , 0, 224, 98 , 1, 277, 30 ,
|
||||
2, 0, 100, 10 , 2, 48, 76 , 2, 80, 80 ,
|
||||
3, 0, 17, 2 , 1, 29, 49 , 2, 53, 28 ,
|
||||
3, 0, 266, 42 , 1, 283, 99 , 2, 243, 108 ,
|
||||
2, 0, 238, 19 , 2, 240, 92 , 2, 190, 40 ,
|
||||
2, 0, 27, 0 , 1, 70, 40 , 0, 20, 130 ,
|
||||
3, 0, 275, 65 , 1, 235, 8 , 2, 274, 6 ,
|
||||
3, 0, 75, 45 , 1, 152, 105 , 2, 24, 68 ,
|
||||
3, 0, 290, 25 , 1, 225, 63 , 2, 260, 110 ,
|
||||
0, 1, 20, 10 , 1, 20, 10 , 1, 20, 10
|
||||
};
|
||||
|
||||
const FIRE_SIZE = 10;
|
||||
const FIRE_TYPE = 1;
|
||||
const FIRE_XOFS = 2;
|
||||
const FIRE_YOFS = 3;
|
||||
const FIRE_ELEMENT_SIZE = 3;
|
||||
|
||||
int x;
|
||||
int delta;
|
||||
int nIdleSeconds;
|
||||
|
||||
int curYPos, destYPos;
|
||||
int nLevel, nLevelNew, nLevelBest;
|
||||
|
||||
native static void SetNextLevel(int num);
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
ScreenJob Init(int oldlevel, int newlevel, int maxlevel)
|
||||
{
|
||||
Super.Init(fadein|fadeout);
|
||||
nLevel = oldlevel - 1;
|
||||
nLevelNew = newlevel - 1;
|
||||
nLevelBest = min(maxlevel, 19) - 1;
|
||||
curYPos = MapLevelOffsets[nLevel] + (200 * (nLevel / 2));
|
||||
destYPos = MapLevelOffsets[nLevelNew] + (200 * (nLevelNew / 2));
|
||||
if (curYPos < destYPos) delta = 2;
|
||||
else if (curYPos > destYPos) delta = -2;
|
||||
// Trim smoke in widescreen
|
||||
/*
|
||||
vec2_t mapwinxy1 = windowxy1, mapwinxy2 = windowxy2;
|
||||
int32_t width = mapwinxy2.x - mapwinxy1.x + 1, height = mapwinxy2.y - mapwinxy1.y + 1;
|
||||
if (3 * width > 4 * height)
|
||||
{
|
||||
mapwinxy1.x += (width - 4 * height / 3) / 2;
|
||||
mapwinxy2.x -= (width - 4 * height / 3) / 2;
|
||||
}
|
||||
*/
|
||||
return self;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
override bool OnEvent(InputEvent ev)
|
||||
{
|
||||
if (ev.type == InputEvent.Type_KeyDown)
|
||||
{
|
||||
int key = ev.KeyScan;
|
||||
let binding = Bindings.GetBinding(key);
|
||||
if (key == InputEvent.KEY_UPARROW || key == InputEvent.KEY_PAD_DPAD_UP || key == InputEvent.Key_kpad_8 || binding ~== "+move_forward")
|
||||
{
|
||||
if (curYPos == destYPos && nLevelNew <= nLevelBest)
|
||||
{
|
||||
nLevelNew++;
|
||||
SetNextLevel(nLevelNew + 1);
|
||||
destYPos = MapLevelOffsets[nLevelNew] + (200 * (nLevelNew / 2));
|
||||
|
||||
if (curYPos <= destYPos) delta = 2;
|
||||
else delta = -2;
|
||||
nIdleSeconds = 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (key == InputEvent.KEY_DOWNARROW || key == InputEvent.KEY_PAD_DPAD_DOWN || key == InputEvent.Key_kpad_2 || binding ~== "+move_backward")
|
||||
{
|
||||
if (curYPos == destYPos && nLevelNew > 0)
|
||||
{
|
||||
nLevelNew--;
|
||||
SetNextLevel(nLevelNew + 1);
|
||||
destYPos = MapLevelOffsets[nLevelNew] + (200 * (nLevelNew / 2));
|
||||
|
||||
if (curYPos <= destYPos) delta = 2;
|
||||
else delta = -2;
|
||||
nIdleSeconds = 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (!Raze.specialKeyEvent(ev)) jobstate = skipped;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
override void OnTick()
|
||||
{
|
||||
if (curYPos != destYPos)
|
||||
{
|
||||
// scroll the map every couple of ms
|
||||
curYPos += delta;
|
||||
|
||||
if ((curYPos > destYPos && delta > 0) || (curYPos < destYPos && delta < 0))
|
||||
curYPos = destYPos;
|
||||
|
||||
nIdleSeconds = 0;
|
||||
}
|
||||
else nIdleSeconds++;
|
||||
if (nIdleSeconds > 300) jobstate = finished;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
override void Draw(double smoothratio)
|
||||
{
|
||||
int currentclock = int((ticks + smoothratio) * 120 / GameTicRate);
|
||||
|
||||
int tileY = curYPos;
|
||||
|
||||
// Draw the background screens
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
let tex = String.Format("MapBG%02d", i+1);
|
||||
Exhumed.DrawAbs(tex, x, tileY);
|
||||
tileY -= 200;
|
||||
}
|
||||
|
||||
// for each level - drawing the 'level completed' on-fire smoke markers
|
||||
for (int i = 0; i < 20; i++)
|
||||
{
|
||||
int screenY = (i >> 1) * -200;
|
||||
|
||||
if (nLevelBest >= i) // check if the player has finished this level
|
||||
{
|
||||
for (int j = 0; j < MapLevelFires[i * FIRE_SIZE]; j++)
|
||||
{
|
||||
int nFireFrame = ((currentclock >> 4) & 3);
|
||||
int elem = i * FIRE_SIZE + FIRE_ELEMENT_SIZE * j;
|
||||
int nFireType = MapLevelFires[elem + FIRE_TYPE];
|
||||
int x = MapLevelFires[elem + FIRE_XOFS];
|
||||
int y = MapLevelFires[elem + FIRE_YOFS];
|
||||
|
||||
String nTile = String.Format("MAPFIRE_%d%d", nFireType+1, nFireFrame+1);
|
||||
int smokeX = x + FireTilesX[nFireType*3 + nFireFrame];
|
||||
int smokeY = y + FireTilesY[nFireType*3 + nFireFrame] + curYPos + screenY;
|
||||
|
||||
// Use rotatesprite to trim smoke in widescreen
|
||||
Exhumed.DrawAbs(nTile, smokeX, smokeY);
|
||||
// Todo: mask out the sides of the screen if the background is not widescreen.
|
||||
}
|
||||
}
|
||||
|
||||
int t = (((currentclock & 16) >> 4));
|
||||
|
||||
String nTile = String.Format("MapPlaque%d_%02d", t+1, i+1);
|
||||
|
||||
int nameX = mapPlaqueX[i];
|
||||
int nameY = mapPlaqueY[i] + curYPos + screenY;
|
||||
|
||||
// Draw level name plaque
|
||||
Exhumed.DrawAbs(nTile, nameX, nameY);
|
||||
|
||||
int shade = 96;
|
||||
|
||||
if (nLevelNew == i)
|
||||
{
|
||||
shade = (Raze.bsin(16 * currentclock) + 31) >> 8;
|
||||
}
|
||||
else if (nLevelBest >= i)
|
||||
{
|
||||
shade = 31;
|
||||
}
|
||||
|
||||
int textY = nameY + MapPlaqueTextY[i];
|
||||
int textX = nameX + MapPlaqueTextX[i];
|
||||
nTile = String.Format("MapPlaqueText_%02d", i+1);
|
||||
|
||||
// draw the text, alternating between red and black
|
||||
Exhumed.DrawAbs(nTile, textX, textY, shade);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
class TextOverlay
|
||||
{
|
||||
int nHeight;
|
||||
double nCrawlY;
|
||||
int palette;
|
||||
BrokenLines screentext;
|
||||
|
||||
void Init(String text, int pal)
|
||||
{
|
||||
screentext = SmallFont.BreakLines(StringTable.Localize(text), 320);
|
||||
nCrawlY = 199;
|
||||
nHeight = screentext.Count() * 10;
|
||||
palette = pal;
|
||||
}
|
||||
|
||||
void DisplayText()
|
||||
{
|
||||
if (nHeight + nCrawlY > 0)
|
||||
{
|
||||
double y = nCrawlY;
|
||||
for (int i = 0; i < screentext.Count() && y <= 199; i++)
|
||||
{
|
||||
if (y >= -10)
|
||||
{
|
||||
int x = 160 - screenText.StringWidth(i)/2;
|
||||
Screen.DrawText(SmallFont, Font.CR_UNDEFINED, x, y, screentext.StringAt(i), DTA_FullscreenScale, FSMode_Fit320x200, DTA_TranslationIndex, palette);
|
||||
}
|
||||
y += 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool AdvanceCinemaText(double clock)
|
||||
{
|
||||
if (nHeight + nCrawlY > 0 || musplaying.handle)
|
||||
{
|
||||
nCrawlY = 199 - clock / 15.;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// cinema (this has been stripped off all game logic that was still in here)
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
class Cinema : SkippableScreenJob
|
||||
{
|
||||
TextOverlay textov;
|
||||
TextureID cinematile;
|
||||
int currentCinemaPalette;
|
||||
int cdtrack;
|
||||
int palette;
|
||||
bool done;
|
||||
|
||||
ScreenJob Init(String bgTexture, String text, int pal, int cdtrk)
|
||||
{
|
||||
Super.Init(fadein|fadeout);
|
||||
cinematile = TexMan.CheckForTexture(bgTexture, TexMan.Type_Any);
|
||||
textov = new("TextOverlay");
|
||||
palette = Translation.MakeID(Translation_BasePalette, pal);
|
||||
textov.Init(text, palette);
|
||||
cdtrack = cdtrk;
|
||||
return self;
|
||||
}
|
||||
|
||||
override void Start()
|
||||
{
|
||||
Raze.StopAllSounds();
|
||||
if (cdtrack != -1)
|
||||
{
|
||||
Exhumed.playCDtrack(cdtrack, false);
|
||||
}
|
||||
}
|
||||
|
||||
override void OnTick()
|
||||
{
|
||||
if (done) jobstate = finished;
|
||||
}
|
||||
|
||||
override void Draw(double smoothratio)
|
||||
{
|
||||
Screen.DrawTexture(cinematile, false, 0, 0, DTA_FullscreenEx, FSMode_ScaleToFit43, DTA_TranslationIndex, palette);
|
||||
textov.DisplayText();
|
||||
done = textov.AdvanceCinemaText((ticks + smoothratio) * (120. / GameTicRate));
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
class LastLevelCinema : ScreenJob
|
||||
{
|
||||
int var_24;
|
||||
int var_28;
|
||||
|
||||
int ebp;
|
||||
int phase;
|
||||
int nextclock;
|
||||
uint nStringTypeOn, nCharTypeOn;
|
||||
int screencnt;
|
||||
bool skiprequest;
|
||||
|
||||
BrokenLines screentext;
|
||||
Font printFont;
|
||||
TextureID tex;
|
||||
|
||||
ScreenJob Init()
|
||||
{
|
||||
Super.Init(fadein | fadeout);
|
||||
var_24 = 16;
|
||||
var_28 = 12;
|
||||
nextclock = 4;
|
||||
let p = StringTable.Localize("REQUIRED_CHARACTERS", false);
|
||||
if (p == "REQUIRED_CHARACTERS") printFont = SmallFont2;
|
||||
else printFont = ConFont;
|
||||
return self;
|
||||
}
|
||||
|
||||
native static TextureID DoStatic(int a, int b);
|
||||
native static TextureID UndoStatic();
|
||||
|
||||
void Phase1()
|
||||
{
|
||||
if (var_24 >= 116)
|
||||
{
|
||||
if (var_28 < 192)
|
||||
var_28 += 20;
|
||||
}
|
||||
else
|
||||
{
|
||||
var_24 += 20;
|
||||
}
|
||||
|
||||
tex = DoStatic(var_28, var_24);
|
||||
}
|
||||
|
||||
bool InitPhase2()
|
||||
{
|
||||
let label = StringTable.Localize(String.Format("$TXT_EX_LASTLEVEL%d", screencnt + 1));
|
||||
screentext = printFont.BreakLines(label, 320);
|
||||
if (screentext.Count() == 0) return false;
|
||||
|
||||
nStringTypeOn = 0;
|
||||
nCharTypeOn = 0;
|
||||
|
||||
ebp = screentext.Count() * 4; // half height of the entire text
|
||||
ebp = 81 - ebp; // offset from the screen's center.
|
||||
tex = UndoStatic();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Phase3()
|
||||
{
|
||||
tex = DoStatic(var_28, var_24);
|
||||
|
||||
if (var_28 > 20)
|
||||
{
|
||||
var_28 -= 20;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (var_24 > 20)
|
||||
{
|
||||
var_24 -= 20;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void DisplayPhase2()
|
||||
{
|
||||
int yy = ebp;
|
||||
|
||||
// for international content, use the generic 8x8 font. The original one is too small for expansion.
|
||||
if (printFont == ConFont)
|
||||
{
|
||||
yy *= 2;
|
||||
for (int i = 0; i < nStringTypeOn; i++, yy += 10) Screen.DrawText(ConFont, Font.CR_GREEN, 140, yy, screentext.StringAt(i), DTA_FullscreenScale, FSMode_Fit640x400);
|
||||
Screen.DrawText(ConFont, Font.CR_GREEN, 140, yy, screentext.StringAt(nStringTypeOn), DTA_FullscreenScale, FSMode_Fit640x400, DTA_TextLen, nCharTypeOn);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < nStringTypeOn; i++, yy += 8) Screen.DrawText(SmallFont2, Font.CR_UNTRANSLATED, 70, yy, screentext.StringAt(i), DTA_FullscreenScale, FSMode_Fit320x200);
|
||||
Screen.DrawText(SmallFont2, Font.CR_UNTRANSLATED, 70, yy, screentext.StringAt(nStringTypeOn), DTA_FullscreenScale, FSMode_Fit320x200, DTA_TextLen, nCharTypeOn);
|
||||
}
|
||||
}
|
||||
|
||||
override bool OnEvent(InputEvent ev)
|
||||
{
|
||||
if (ev.type == InputEvent.Type_KeyDown && !Raze.specialKeyEvent(ev)) skiprequest = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
override void Start()
|
||||
{
|
||||
Exhumed.PlayLocalSound(ExhumedSnd.kSound75, 0, false, CHANF_UI);
|
||||
phase = 1;
|
||||
}
|
||||
|
||||
override void OnTick()
|
||||
{
|
||||
switch (phase)
|
||||
{
|
||||
case 1:
|
||||
Phase1();
|
||||
if (skiprequest || ticks >= nextclock)
|
||||
{
|
||||
InitPhase2();
|
||||
phase = 2;
|
||||
skiprequest = false;
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
{
|
||||
let text = screenText.StringAt(nStringTypeOn);
|
||||
int chr;
|
||||
[chr,nCharTypeOn] = text.GetNextCodePoint(nCharTypeOn);
|
||||
|
||||
if (chr == 0)
|
||||
{
|
||||
nCharTypeOn = 0;
|
||||
nStringTypeOn++;
|
||||
if (nStringTypeOn >= screentext.Count())
|
||||
{
|
||||
nextclock = (GameTicRate * (screentext.Count() + 2)) + ticks;
|
||||
phase = 3;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
nCharTypeOn++;
|
||||
if (chr != 32) Exhumed.PlayLocalSound(ExhumedSnd.kSound71, 0, false, CHANF_UI);
|
||||
}
|
||||
|
||||
if (skiprequest)
|
||||
{
|
||||
nextclock = (GameTicRate * (screentext.Count() + 2)) + ticks;
|
||||
phase = 4;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
if (ticks >= nextclock || skiprequest)
|
||||
{
|
||||
Exhumed.PlayLocalSound(ExhumedSnd.kSound75, 0, false, CHANF_UI);
|
||||
phase = 4;
|
||||
nextclock = ticks + 60;
|
||||
skiprequest = false;
|
||||
}
|
||||
|
||||
case 4:
|
||||
if (ticks >= nextclock)
|
||||
{
|
||||
skiprequest |= !Phase3();
|
||||
}
|
||||
if (skiprequest)
|
||||
{
|
||||
// Go to the next text page.
|
||||
if (screencnt != 2)
|
||||
{
|
||||
screencnt++;
|
||||
nextclock = ticks + 60;
|
||||
skiprequest = 0;
|
||||
phase = 1;
|
||||
}
|
||||
else jobstate = finished;
|
||||
}
|
||||
|
||||
if (skiprequest)
|
||||
{
|
||||
jobstate = finished;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override void Draw(double sm)
|
||||
{
|
||||
Screen.DrawTexture(tex, false, 0, 0, DTA_FullscreenEx, FSMode_ScaleToFit43);
|
||||
if (phase == 2 || phase == 3) DisplayPhase2();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Credits roll
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
class ExCredits : ScreenJob
|
||||
{
|
||||
Array<String> credits;
|
||||
Array<String> pagelines;
|
||||
int page;
|
||||
int pagetime;
|
||||
bool skiprequest;
|
||||
|
||||
ScreenJob Init()
|
||||
{
|
||||
Super.Init();
|
||||
String text;
|
||||
int lump = Wads.CheckNumForFullName("credits.txt");
|
||||
if (lump > -1) text = Wads.ReadLump(lump);
|
||||
text.Substitute("\r", "");
|
||||
text.Split(credits, "\n\n");
|
||||
return self;
|
||||
}
|
||||
|
||||
override bool OnEvent(InputEvent ev)
|
||||
{
|
||||
if (ev.type == InputEvent.Type_KeyDown && !Raze.specialKeyEvent(ev)) skiprequest = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
override void Start()
|
||||
{
|
||||
if (credits.Size() == 0)
|
||||
{
|
||||
jobstate = finished;
|
||||
return;
|
||||
}
|
||||
Exhumed.playCDtrack(19, false);
|
||||
pagetime = 0;
|
||||
page = -1;
|
||||
}
|
||||
|
||||
override void OnTick()
|
||||
{
|
||||
if (ticks >= pagetime || skiprequest)
|
||||
{
|
||||
page++;
|
||||
if (page < credits.Size())
|
||||
credits[page].Split(pagelines, "\n");
|
||||
else
|
||||
{
|
||||
if (skiprequest || !musplaying.handle)
|
||||
{
|
||||
jobstate = finished;
|
||||
return;
|
||||
}
|
||||
pagelines.Clear();
|
||||
}
|
||||
pagetime = ticks + 60; //
|
||||
}
|
||||
}
|
||||
|
||||
override void Draw(double smoothratio)
|
||||
{
|
||||
int y = 100 - ((10 * (pagelines.Size() - 1)) / 2);
|
||||
|
||||
for (int i = 0; i < pagelines.Size(); i++)
|
||||
{
|
||||
int ptime = clamp((pagetime - ticks - smoothratio) * 1000 / GameTicRate, 0, 2000); // in milliseconds
|
||||
int light;
|
||||
|
||||
if (ptime < 255) light = ptime;
|
||||
else if (ptime > 2000 - 255) light = 2000 - ptime;
|
||||
else light = 255;
|
||||
|
||||
let colr = Color(light, light, light);
|
||||
|
||||
int nStringWidth = SmallFont.StringWidth(pagelines[i]);
|
||||
Screen.DrawText(SmallFont, Font.CR_UNTRANSLATED, 160 - nStringWidth / 2, y, pagelines[i], DTA_FullscreenScale, FSMode_Fit320x200, DTA_Color, colr);
|
||||
y += 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ExhumedCutscenes
|
||||
{
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
static void BuildIntro(ScreenJobRunner runner)
|
||||
{
|
||||
let logo = (gameinfo.gameType & GAMEFLAG_EXHUMED) ? "TileBMGLogo" : "TilePIELogo";
|
||||
runner.Append(ImageScreen.CreateNamed(logo, ScreenJob.fadein | ScreenJob.fadeout));
|
||||
runner.Append(new("LobotomyScreen").Init("LobotomyLogo", ScreenJob.fadein | ScreenJob.fadeout));
|
||||
if (LMFDecoder.Identify("book.mov")) runner.Append(new("LMFPlayer").Init("book.mov"));
|
||||
else runner.Append(MoviePlayerJob.Create("book.mov", 0));
|
||||
runner.Append(new("MainTitle").Init());
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
static void BuildMap(ScreenJobRunner runner, MapRecord frommap, SummaryInfo info, MapRecord tomap)
|
||||
{
|
||||
// This is only defined for the regular levels.
|
||||
int frommapnum = frommap == null? 1 : frommap.levelNumber;
|
||||
if (fromMapnum < 1 || fromMapNum > 20 || tomap == null || tomap.levelNumber < 1 || tomap.levelNumber > 20) return;
|
||||
|
||||
// hijack the super secret info in the summary info to convey the max. map because we won't need that field for its real purpose.
|
||||
runner.Append(new("MapScreen").Init(fromMapNum, toMap.levelNumber, info.supersecrets));
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// This removes all the insanity the original setup had with these.
|
||||
// Simplicity rules!
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
static void BuildCinemaBefore5(ScreenJobRunner runner)
|
||||
{
|
||||
runner.Append(new("Cinema").Init("TileCinema5", "$TXT_EX_CINEMA2", 3, 2));
|
||||
}
|
||||
|
||||
static void BuildCinemaAfter10(ScreenJobRunner runner)
|
||||
{
|
||||
runner.Append(new("Cinema").Init("TileCinema10", "$TXT_EX_CINEMA4", 5, 3));
|
||||
}
|
||||
|
||||
static void BuildCinemaBefore11(ScreenJobRunner runner)
|
||||
{
|
||||
runner.Append(new("Cinema").Init("TileCinema11", "$TXT_EX_CINEMA3", 1, 4));
|
||||
}
|
||||
|
||||
static void BuildCinemaAfter15(ScreenJobRunner runner)
|
||||
{
|
||||
runner.Append(new("Cinema").Init("TileCinema15", "$TXT_EX_CINEMA6", 7, 6));
|
||||
}
|
||||
|
||||
static void BuildCinemaBefore20(ScreenJobRunner runner)
|
||||
{
|
||||
runner.Append(new("LastLevelCinema").Init());
|
||||
}
|
||||
|
||||
static void BuildCinemaAfter20(ScreenJobRunner runner)
|
||||
{
|
||||
runner.Append(new("Cinema").Init("TileCinema20", "$TXT_EX_CINEMA8", 6, 8));
|
||||
runner.Append(new("ExCredits").Init());
|
||||
}
|
||||
|
||||
static void BuildCinemaLose(ScreenJobRunner runner)
|
||||
{
|
||||
runner.Append(new("Cinema").Init("TileCinemaLose", "$TXT_EX_CINEMA7", 4, 7));
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// player died
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void BuildGameOverScene(ScreenJobRunner runner, MapRecord map)
|
||||
{
|
||||
Raze.StopMusic();
|
||||
Exhumed.PlayLocalSound(ExhumedSnd.kSoundJonLaugh2, 0, false, CHANF_UI);
|
||||
runner.Append(ImageScreen.CreateNamed("Gameover", ScreenJob.fadein | ScreenJob.fadeout, 0x7fffffff, Translation.MakeID(Translation_BasePalette, 16)));
|
||||
}
|
||||
|
||||
}
|
|
@ -111,6 +111,8 @@ struct Raze
|
|||
native static bool MusicEnabled();
|
||||
native static String PlayerName(int i);
|
||||
native static double GetTimeFrac();
|
||||
native static int bsin(int angle, int shift = 0);
|
||||
native static int bcos(int angle, int shift = 0);
|
||||
|
||||
static bool specialKeyEvent(InputEvent ev)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue