2019-11-20 16:21:32 +00:00
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
/*
|
|
|
|
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
|
|
|
Copyright (C) 2019 sirlemonhead, Nuke.YKT
|
|
|
|
This file is part of PCExhumed.
|
|
|
|
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.
|
|
|
|
*/
|
|
|
|
//-------------------------------------------------------------------------
|
2019-11-22 23:11:37 +00:00
|
|
|
#include "ns.h"
|
2019-09-19 19:45:19 +00:00
|
|
|
#include "compat.h"
|
2019-09-20 17:04:02 +00:00
|
|
|
#include "build.h"
|
2019-09-19 19:45:19 +00:00
|
|
|
#include "exhumed.h"
|
2020-08-18 07:52:08 +00:00
|
|
|
#include "aistuff.h"
|
2019-09-19 19:45:19 +00:00
|
|
|
#include "player.h"
|
|
|
|
#include "sequence.h"
|
2019-09-20 17:04:02 +00:00
|
|
|
#include "menu.h"
|
|
|
|
#include "names.h"
|
|
|
|
#include "engine.h"
|
2020-01-02 18:56:57 +00:00
|
|
|
#include "c_bind.h"
|
2019-09-19 19:45:19 +00:00
|
|
|
#include "status.h"
|
2019-09-20 17:04:02 +00:00
|
|
|
#include "sound.h"
|
|
|
|
#include "names.h"
|
2019-11-24 09:03:19 +00:00
|
|
|
#include "ps_input.h"
|
2019-08-26 03:59:14 +00:00
|
|
|
#include "view.h"
|
2020-04-12 06:09:38 +00:00
|
|
|
#include "raze_sound.h"
|
2020-06-14 16:57:55 +00:00
|
|
|
#include "menu.h"
|
2020-01-05 09:48:44 +00:00
|
|
|
#include "v_2ddrawer.h"
|
2020-08-21 20:30:51 +00:00
|
|
|
#include "gamestate.h"
|
2020-08-21 20:40:09 +00:00
|
|
|
#include "statistics.h"
|
|
|
|
#include "v_draw.h"
|
2019-09-20 17:04:02 +00:00
|
|
|
#include <string>
|
2019-08-26 03:59:14 +00:00
|
|
|
|
|
|
|
#include <assert.h>
|
|
|
|
|
2019-11-22 23:11:37 +00:00
|
|
|
BEGIN_PS_NS
|
|
|
|
|
|
|
|
|
2019-10-29 21:28:14 +00:00
|
|
|
#define kSaveFileName "savgamea.sav"
|
2019-09-20 17:04:02 +00:00
|
|
|
#define kMaxSaveSlots 5
|
|
|
|
#define kMaxSaveSlotChars 25
|
2019-08-26 03:59:14 +00:00
|
|
|
|
|
|
|
GameStat GameStats;
|
|
|
|
|
|
|
|
short nCinemaSeen[30];
|
|
|
|
|
2019-11-18 22:15:48 +00:00
|
|
|
uint8_t energytile[66 * 66] = {0};
|
2019-08-26 03:59:14 +00:00
|
|
|
|
|
|
|
short SavePosition = -1;
|
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
uint8_t *cur;
|
|
|
|
uint8_t *dest;
|
2019-08-26 03:59:14 +00:00
|
|
|
|
|
|
|
|
2019-09-20 17:04:02 +00:00
|
|
|
unsigned int nRandom = 0x41C6167E;
|
|
|
|
int dword_9AB57 = 0x1F;
|
|
|
|
short word_9AB5B = 0;
|
2019-08-26 03:59:14 +00:00
|
|
|
|
|
|
|
int keytimer = 0;
|
|
|
|
|
|
|
|
|
2019-09-20 17:04:02 +00:00
|
|
|
void ClearCinemaSeen()
|
|
|
|
{
|
|
|
|
memset(nCinemaSeen, 0, sizeof(nCinemaSeen));
|
|
|
|
}
|
2019-08-26 03:59:14 +00:00
|
|
|
|
|
|
|
unsigned int menu_RandomBit2()
|
|
|
|
{
|
2019-08-31 07:47:15 +00:00
|
|
|
unsigned int result = nRandom & 1;
|
|
|
|
|
2020-08-22 20:40:22 +00:00
|
|
|
if (--dword_9AB57 > 0)
|
2019-08-31 07:47:15 +00:00
|
|
|
{
|
|
|
|
nRandom = (result << 31) | (nRandom >> 1);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
dword_9AB57 = 31;
|
|
|
|
nRandom ^= nRandom >> 4;
|
|
|
|
}
|
|
|
|
return result;
|
2019-08-26 03:59:14 +00:00
|
|
|
}
|
|
|
|
|
2019-09-20 17:04:02 +00:00
|
|
|
void InitEnergyTile()
|
|
|
|
{
|
|
|
|
memset(energytile, 96, sizeof(energytile));
|
|
|
|
}
|
2019-08-26 03:59:14 +00:00
|
|
|
|
|
|
|
void DoEnergyTile()
|
|
|
|
{
|
2019-08-31 07:47:15 +00:00
|
|
|
nButtonColor += nButtonColor < 0 ? 8 : 0;
|
|
|
|
|
2020-08-22 20:40:22 +00:00
|
|
|
auto energy1 = TileFiles.tileMakeWritable(kEnergy1);
|
|
|
|
auto energy2 = TileFiles.tileMakeWritable(kEnergy2);
|
|
|
|
uint8_t* ptr1 = energy1 + 1984;
|
|
|
|
uint8_t* ptr2 = energy2 + 2048;
|
2019-08-31 07:47:15 +00:00
|
|
|
|
|
|
|
short nColor = nButtonColor + 161;
|
|
|
|
|
|
|
|
int i, j;
|
|
|
|
|
|
|
|
for (i = 0; i < 32; i++)
|
|
|
|
{
|
|
|
|
memset(ptr1, nColor, 64);
|
|
|
|
memset(ptr2, nColor, 64);
|
|
|
|
|
|
|
|
ptr1 -= 64;
|
|
|
|
ptr2 += 64;
|
|
|
|
|
|
|
|
nColor++;
|
2019-11-20 16:21:32 +00:00
|
|
|
|
2019-09-20 17:04:02 +00:00
|
|
|
if (nColor >= 168) {
|
2019-08-31 07:47:15 +00:00
|
|
|
nColor = 160;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-22 16:12:19 +00:00
|
|
|
TileFiles.InvalidateTile(kEnergy1);
|
2019-11-05 06:15:21 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
if (nSmokeSparks)
|
|
|
|
{
|
2020-08-22 20:40:22 +00:00
|
|
|
uint8_t* c = &energytile[67]; // skip a line
|
|
|
|
uint8_t* ptrW = energy2;
|
2019-08-31 07:47:15 +00:00
|
|
|
|
|
|
|
for (i = 0; i < 64; i++)
|
|
|
|
{
|
|
|
|
for (j = 0; j < 64; j++)
|
|
|
|
{
|
2019-12-03 22:02:17 +00:00
|
|
|
uint8_t val = *c;
|
|
|
|
|
|
|
|
if (val != 96)
|
2019-08-31 07:47:15 +00:00
|
|
|
{
|
2019-12-03 22:02:17 +00:00
|
|
|
if (val > 158) {
|
|
|
|
*ptrW = val - 1;
|
2019-08-31 07:47:15 +00:00
|
|
|
}
|
2019-09-20 17:04:02 +00:00
|
|
|
else {
|
2019-12-03 22:02:17 +00:00
|
|
|
*ptrW = 96;
|
2019-08-31 07:47:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-09-20 17:04:02 +00:00
|
|
|
if (menu_RandomBit2()) {
|
2019-08-31 07:47:15 +00:00
|
|
|
*ptrW = *c;
|
|
|
|
}
|
2019-12-03 22:02:17 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
uint8_t al = *(c + 1);
|
|
|
|
uint8_t ah = *(c - 1);
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2019-12-03 22:02:17 +00:00
|
|
|
if (al <= ah) {
|
|
|
|
al = ah;
|
|
|
|
}
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2019-12-03 22:02:17 +00:00
|
|
|
uint8_t cl = al;
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2019-12-03 22:02:17 +00:00
|
|
|
al = *(c - 66);
|
|
|
|
if (cl <= al) {
|
|
|
|
cl = al;
|
|
|
|
}
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2019-12-03 22:02:17 +00:00
|
|
|
al = *(c + 66);
|
|
|
|
if (cl <= al) {
|
|
|
|
cl = al;
|
|
|
|
}
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2019-12-03 22:02:17 +00:00
|
|
|
al = *(c + 66);
|
|
|
|
if (cl <= al) {
|
|
|
|
cl = al;
|
|
|
|
}
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2019-12-03 22:02:17 +00:00
|
|
|
al = *(c + 66);
|
|
|
|
if (cl <= al) {
|
|
|
|
cl = al;
|
|
|
|
}
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2019-12-03 22:02:17 +00:00
|
|
|
al = *(c - 65);
|
|
|
|
if (cl <= al) {
|
|
|
|
cl = al;
|
|
|
|
}
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2019-12-03 22:02:17 +00:00
|
|
|
al = *(c - 67);
|
|
|
|
if (cl > al) {
|
|
|
|
al = cl;
|
|
|
|
}
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2019-12-03 22:02:17 +00:00
|
|
|
cl = al;
|
2019-11-18 22:15:48 +00:00
|
|
|
|
2019-12-03 22:02:17 +00:00
|
|
|
if (al <= 159) {
|
|
|
|
*ptrW = 96;
|
2019-08-31 07:47:15 +00:00
|
|
|
}
|
2019-12-03 22:02:17 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
if (!menu_RandomBit2()) {
|
|
|
|
cl--;
|
|
|
|
}
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2019-12-03 22:02:17 +00:00
|
|
|
*ptrW = cl;
|
|
|
|
}
|
2020-08-22 20:40:22 +00:00
|
|
|
}
|
2019-08-31 07:47:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
c++;
|
|
|
|
ptrW++;
|
|
|
|
}
|
|
|
|
|
|
|
|
c += 2;
|
|
|
|
}
|
|
|
|
|
2019-11-18 22:15:48 +00:00
|
|
|
c = &energytile[67];
|
2019-11-24 15:34:23 +00:00
|
|
|
ptrW = energy2;
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2019-12-03 22:02:17 +00:00
|
|
|
// copy back to energytile[]
|
2019-08-31 07:47:15 +00:00
|
|
|
for (i = 0; i < 64; i++)
|
|
|
|
{
|
|
|
|
memcpy(c, ptrW, 64);
|
|
|
|
c += 66;
|
|
|
|
ptrW += 64;
|
|
|
|
}
|
|
|
|
|
2019-11-24 15:34:23 +00:00
|
|
|
ptrW = energy2;
|
2019-11-20 16:21:32 +00:00
|
|
|
|
2019-12-03 22:02:17 +00:00
|
|
|
// kEnergy2 is 64 x 64
|
2019-08-31 07:47:15 +00:00
|
|
|
for (i = 0; i < 4096; i++)
|
|
|
|
{
|
2019-12-03 22:02:17 +00:00
|
|
|
if (ptrW[i] == 96) {
|
|
|
|
ptrW[i] = 255; // -1?
|
2019-08-31 07:47:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
word_9AB5B--;
|
|
|
|
if (word_9AB5B <= 0)
|
|
|
|
{
|
2020-08-22 20:40:22 +00:00
|
|
|
int randSize = (RandomSize(5) & 0x1F) + 16;
|
2019-08-31 07:47:15 +00:00
|
|
|
int randSize2 = (RandomSize(5) & 0x1F) + 16;
|
|
|
|
|
|
|
|
int val = randSize << 5;
|
|
|
|
val += randSize;
|
|
|
|
val *= 2;
|
|
|
|
val += randSize2;
|
|
|
|
|
2019-12-03 22:02:17 +00:00
|
|
|
assert(val < 4356);
|
|
|
|
|
2019-11-18 22:15:48 +00:00
|
|
|
energytile[val] = 175;
|
2019-09-20 17:04:02 +00:00
|
|
|
word_9AB5B = 1;
|
2019-08-31 07:47:15 +00:00
|
|
|
}
|
2020-08-22 16:12:19 +00:00
|
|
|
TileFiles.InvalidateTile(kEnergy2);
|
2019-08-31 07:47:15 +00:00
|
|
|
}
|
2019-08-26 03:59:14 +00:00
|
|
|
}
|
|
|
|
|
2020-08-22 20:40:22 +00:00
|
|
|
void menu_GameLoad2(FILE* fp, bool bIsDemo)
|
2019-08-26 03:59:14 +00:00
|
|
|
{
|
2020-08-22 08:03:21 +00:00
|
|
|
fread(&GameStats, sizeof(GameStats), 1, fp);
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
nPlayerWeapons[nLocalPlayer] = GameStats.nWeapons;
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
PlayerList[nLocalPlayer].nCurrentWeapon = GameStats.nCurrentWeapon;
|
2019-09-20 17:04:02 +00:00
|
|
|
nPlayerClip[nLocalPlayer] = GameStats.clip;
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
int nPistolBullets = PlayerList[nLocalPlayer].nAmmo[kWeaponPistol];
|
2019-09-20 17:04:02 +00:00
|
|
|
if (nPistolBullets >= 6) {
|
2019-08-31 07:47:15 +00:00
|
|
|
nPistolBullets = 6;
|
|
|
|
}
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
nPistolClip[nLocalPlayer] = nPistolBullets;
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
memcpy(&PlayerList[nLocalPlayer], &GameStats.player, sizeof(Player));
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2020-08-22 20:40:22 +00:00
|
|
|
nPlayerItem[nLocalPlayer] = GameStats.items;
|
2019-08-31 07:47:15 +00:00
|
|
|
nPlayerLives[nLocalPlayer] = GameStats.nLives;
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
SetPlayerItem(nLocalPlayer, nPlayerItem[nLocalPlayer]);
|
|
|
|
CheckClip(nLocalPlayer);
|
2019-08-26 03:59:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
short menu_GameLoad(int nSlot)
|
|
|
|
{
|
2019-08-31 07:47:15 +00:00
|
|
|
memset(&GameStats, 0, sizeof(GameStats));
|
2019-11-20 16:21:32 +00:00
|
|
|
|
2020-08-22 20:40:22 +00:00
|
|
|
FILE* fp = fopen(kSaveFileName, "rb");
|
2019-09-20 17:04:02 +00:00
|
|
|
if (fp == NULL) {
|
2019-08-31 07:47:15 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
fseek(fp, 125, SEEK_SET);
|
|
|
|
fseek(fp, nSlot * sizeof(GameStats), SEEK_CUR);
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
menu_GameLoad2(fp);
|
|
|
|
fclose(fp);
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
return GameStats.nMap;
|
2019-08-26 03:59:14 +00:00
|
|
|
}
|
|
|
|
|
2020-08-22 20:40:22 +00:00
|
|
|
void menu_GameSave2(FILE* fp)
|
2019-08-26 03:59:14 +00:00
|
|
|
{
|
2019-08-31 07:47:15 +00:00
|
|
|
memset(&GameStats, 0, sizeof(GameStats));
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-09-20 17:04:02 +00:00
|
|
|
GameStats.nMap = (uint8_t)levelnew;
|
|
|
|
GameStats.nWeapons = nPlayerWeapons[nLocalPlayer];
|
2019-08-31 07:47:15 +00:00
|
|
|
GameStats.nCurrentWeapon = PlayerList[nLocalPlayer].nCurrentWeapon;
|
2020-08-22 20:40:22 +00:00
|
|
|
GameStats.clip = nPlayerClip[nLocalPlayer];
|
|
|
|
GameStats.items = nPlayerItem[nLocalPlayer];
|
2019-09-20 17:04:02 +00:00
|
|
|
GameStats.nLives = nPlayerLives[nLocalPlayer];
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
memcpy(&GameStats.player, &PlayerList[nLocalPlayer], sizeof(GameStats.player));
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
fwrite(&GameStats, sizeof(GameStats), 1, fp);
|
2019-08-26 03:59:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void menu_GameSave(int nSaveSlot)
|
|
|
|
{
|
2019-09-20 17:04:02 +00:00
|
|
|
if (nSaveSlot < 0) {
|
2019-08-31 07:47:15 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-08-22 20:40:22 +00:00
|
|
|
FILE* fp = fopen(kSaveFileName, "rb+");
|
2019-08-31 07:47:15 +00:00
|
|
|
if (fp != NULL)
|
|
|
|
{
|
2019-09-20 17:04:02 +00:00
|
|
|
fseek(fp, 125, SEEK_SET); // skip save slot names
|
2019-08-31 07:47:15 +00:00
|
|
|
fseek(fp, sizeof(GameStat) * nSaveSlot, SEEK_CUR);
|
|
|
|
menu_GameSave2(fp);
|
|
|
|
fclose(fp);
|
|
|
|
}
|
2019-08-26 03:59:14 +00:00
|
|
|
}
|
|
|
|
|
2019-12-26 21:00:04 +00:00
|
|
|
static SavegameHelper sgh("menu",
|
|
|
|
SA(nCinemaSeen),
|
2019-12-27 09:52:40 +00:00
|
|
|
SA(energytile),
|
|
|
|
SV(nButtonColor),
|
|
|
|
SV(word_9AB5B),
|
2019-12-26 21:00:04 +00:00
|
|
|
nullptr);
|
|
|
|
|
2019-11-22 23:11:37 +00:00
|
|
|
END_PS_NS
|