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-08-26 03:59:14 +00:00
|
|
|
#include "engine.h"
|
|
|
|
#include "player.h"
|
|
|
|
#include "anims.h"
|
|
|
|
#include "status.h"
|
|
|
|
#include "exhumed.h"
|
|
|
|
#include "sequence.h"
|
|
|
|
#include "init.h"
|
|
|
|
#include "names.h"
|
|
|
|
#include "items.h"
|
|
|
|
#include "view.h"
|
|
|
|
#include "trigdat.h"
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdarg.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include "typedefs.h"
|
|
|
|
|
2019-11-22 23:11:37 +00:00
|
|
|
BEGIN_PS_NS
|
|
|
|
|
2019-08-26 03:59:14 +00:00
|
|
|
short nMaskY;
|
|
|
|
static short nAnimsFree = 0;
|
|
|
|
|
2019-08-31 16:05:11 +00:00
|
|
|
short statusmask[MAXXDIM];
|
2019-08-26 03:59:14 +00:00
|
|
|
|
|
|
|
short message_timer = 0;
|
|
|
|
char message_text[80];
|
|
|
|
int magicperline;
|
|
|
|
int airperline;
|
|
|
|
int healthperline;
|
|
|
|
int nAirFrames;
|
|
|
|
int nCounter;
|
|
|
|
int nCounterDest;
|
|
|
|
|
|
|
|
short nStatusSeqOffset;
|
|
|
|
short nItemFrames;
|
|
|
|
|
|
|
|
int laststatusx;
|
|
|
|
int laststatusy;
|
|
|
|
|
2019-08-31 09:08:38 +00:00
|
|
|
int16_t nItemSeq;
|
2019-08-26 03:59:14 +00:00
|
|
|
short nDigit[3];
|
|
|
|
|
|
|
|
short nMagicFrames;
|
|
|
|
short nHealthLevel;
|
|
|
|
short nItemFrame;
|
|
|
|
short nMeterRange;
|
|
|
|
short nMagicLevel;
|
|
|
|
short nHealthFrame;
|
|
|
|
short nMagicFrame;
|
|
|
|
|
|
|
|
short statusx;
|
|
|
|
short statusy;
|
|
|
|
short nHealthFrames;
|
|
|
|
|
|
|
|
short airframe;
|
|
|
|
|
2019-08-31 09:08:38 +00:00
|
|
|
int16_t nFirstAnim;
|
|
|
|
int16_t nLastAnim;
|
2019-08-26 03:59:14 +00:00
|
|
|
short nItemAltSeq;
|
|
|
|
|
|
|
|
short airpages = 0;
|
|
|
|
|
|
|
|
short ammodelay = 3;
|
|
|
|
|
|
|
|
short nCounterBullet = -1;
|
|
|
|
|
|
|
|
|
|
|
|
// 8 bytes
|
|
|
|
struct statusAnim
|
|
|
|
{
|
2019-10-28 19:45:35 +00:00
|
|
|
int16_t s1;
|
|
|
|
int16_t s2;
|
|
|
|
// int16_t nPage;
|
|
|
|
int8_t nPrevAnim;
|
|
|
|
int8_t nNextAnim;
|
2019-08-26 03:59:14 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
#define kMaxStatusAnims 50
|
|
|
|
|
|
|
|
statusAnim StatusAnim[kMaxStatusAnims];
|
2019-08-31 07:47:15 +00:00
|
|
|
uint8_t StatusAnimsFree[kMaxStatusAnims];
|
2019-10-28 19:45:35 +00:00
|
|
|
uint8_t StatusAnimFlags[kMaxStatusAnims];
|
2019-08-26 03:59:14 +00:00
|
|
|
|
|
|
|
short nItemSeqOffset[] = {91, 72, 76, 79, 68, 87, 83};
|
|
|
|
|
|
|
|
short word_9AD54[kMaxPlayers] = {0, 0, 0, 0, 0, 0, 0, 0};
|
|
|
|
int dword_9AD64[kMaxPlayers] = {0, 0, 0, 0, 0, 0, 0, 0};
|
|
|
|
|
|
|
|
void SetCounterDigits();
|
|
|
|
void SetItemSeq();
|
|
|
|
void SetItemSeq2(int nSeqOffset);
|
2019-10-28 19:45:35 +00:00
|
|
|
void DestroyStatusAnim(short nAnim);
|
2019-08-26 03:59:14 +00:00
|
|
|
|
|
|
|
|
|
|
|
int BuildStatusAnim(int val, int nFlags)
|
|
|
|
{
|
2019-10-28 19:45:35 +00:00
|
|
|
// destroy this anim if it already exists
|
|
|
|
for (int i = nFirstAnim; i >= 0; i = StatusAnim[i].nPrevAnim)
|
|
|
|
{
|
|
|
|
if (StatusAnim[i].s1 == val) {
|
|
|
|
DestroyStatusAnim(i);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
if (nAnimsFree <= 0) {
|
|
|
|
return -1;
|
|
|
|
}
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
nAnimsFree--;
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
uint8_t nStatusAnim = StatusAnimsFree[nAnimsFree];
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-10-28 19:45:35 +00:00
|
|
|
StatusAnim[nStatusAnim].nPrevAnim = -1;
|
|
|
|
StatusAnim[nStatusAnim].nNextAnim = nLastAnim;
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
if (nLastAnim < 0) {
|
|
|
|
nFirstAnim = nStatusAnim;
|
|
|
|
}
|
|
|
|
else {
|
2019-10-28 19:45:35 +00:00
|
|
|
StatusAnim[nLastAnim].nPrevAnim = nStatusAnim;
|
2019-08-31 07:47:15 +00:00
|
|
|
}
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
nLastAnim = nStatusAnim;
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
StatusAnim[nStatusAnim].s1 = val;
|
|
|
|
StatusAnim[nStatusAnim].s2 = 0;
|
|
|
|
StatusAnimFlags[nStatusAnim] = nFlags;
|
|
|
|
return nStatusAnim;
|
2019-08-26 03:59:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void RefreshStatus()
|
|
|
|
{
|
2019-08-31 07:47:15 +00:00
|
|
|
short nLives = nPlayerLives[nLocalPlayer];
|
|
|
|
if (nLives < 0 || nLives > kMaxPlayerLives) {
|
2019-11-24 09:03:19 +00:00
|
|
|
I_Error("illegal value for nPlayerLives #%d\n", nLocalPlayer);
|
2019-08-31 07:47:15 +00:00
|
|
|
}
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
// draws the red dots that indicate the lives amount
|
2019-10-28 19:45:35 +00:00
|
|
|
BuildStatusAnim(145 + (2 * nLives), 0);
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 09:08:38 +00:00
|
|
|
uint16_t nKeys = PlayerList[nLocalPlayer].keys;
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
int val = 37;
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
for (int i = 0; i < 4; i++)
|
|
|
|
{
|
|
|
|
if (nKeys & 0x1000) {
|
|
|
|
BuildStatusAnim(val, 0);
|
|
|
|
}
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
nKeys >>= 1;
|
|
|
|
val += 2;
|
|
|
|
}
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
SetPlayerItem(nLocalPlayer, nPlayerItem[nLocalPlayer]);
|
|
|
|
SetHealthFrame(0);
|
|
|
|
SetMagicFrame();
|
|
|
|
SetAirFrame();
|
2019-08-26 03:59:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void InitStatus()
|
|
|
|
{
|
2019-08-31 07:47:15 +00:00
|
|
|
nStatusSeqOffset = SeqOffsets[kSeqStatus];
|
|
|
|
nHealthFrames = SeqSize[nStatusSeqOffset + 1];
|
|
|
|
int nPicNum = seq_GetSeqPicnum(kSeqStatus, 1, 0);
|
|
|
|
nMagicFrames = SeqSize[nStatusSeqOffset + 129];
|
|
|
|
nHealthFrame = 0;
|
|
|
|
nMagicFrame = 0;
|
|
|
|
nHealthLevel = 0;
|
|
|
|
nMagicLevel = 0;
|
|
|
|
nMeterRange = tilesiz[nPicNum].y;
|
|
|
|
magicperline = 1000 / nMeterRange;
|
|
|
|
healthperline = 800 / nMeterRange;
|
|
|
|
nAirFrames = SeqSize[nStatusSeqOffset + 133];
|
|
|
|
airperline = 100 / nAirFrames;
|
|
|
|
nCounter = 0;
|
|
|
|
nCounterDest = 0;
|
|
|
|
|
|
|
|
memset(nDigit, 0, sizeof(nDigit));
|
|
|
|
|
|
|
|
SetCounter(0);
|
|
|
|
SetHealthFrame(0);
|
|
|
|
SetMagicFrame();
|
|
|
|
|
|
|
|
for (int i = 0; i < kMaxStatusAnims; i++) {
|
|
|
|
StatusAnimsFree[i] = i;
|
|
|
|
}
|
|
|
|
|
|
|
|
nLastAnim = -1;
|
|
|
|
nFirstAnim = -1;
|
|
|
|
nItemSeq = -1;
|
|
|
|
nAnimsFree = kMaxStatusAnims;
|
|
|
|
statusx = xdim - 320;
|
|
|
|
textpages = 0;
|
|
|
|
message_timer = 0;
|
|
|
|
statusy = ydim - 200;
|
2019-08-26 03:59:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MoveStatusAnims()
|
|
|
|
{
|
2019-10-28 19:45:35 +00:00
|
|
|
for (int i = nFirstAnim; i >= 0; i = StatusAnim[i].nPrevAnim)
|
2019-08-31 07:47:15 +00:00
|
|
|
{
|
|
|
|
seq_MoveSequence(-1, nStatusSeqOffset + StatusAnim[i].s1, StatusAnim[i].s2);
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
StatusAnim[i].s2++;
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
short nSize = SeqSize[nStatusSeqOffset + StatusAnim[i].s1];
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
if (StatusAnim[i].s2 >= nSize)
|
|
|
|
{
|
|
|
|
if (StatusAnimFlags[i] & 0x10) {
|
|
|
|
StatusAnim[i].s2 = 0;
|
|
|
|
}
|
|
|
|
else {
|
2019-10-28 19:45:35 +00:00
|
|
|
StatusAnim[i].s2 = nSize - 1; // restart it
|
2019-08-31 07:47:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-08-26 03:59:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void DestroyStatusAnim(short nAnim)
|
|
|
|
{
|
2019-10-28 19:45:35 +00:00
|
|
|
int8_t nPrev = StatusAnim[nAnim].nPrevAnim;
|
|
|
|
int8_t nNext = StatusAnim[nAnim].nNextAnim;
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-10-28 19:45:35 +00:00
|
|
|
if (nNext >= 0) {
|
|
|
|
StatusAnim[nNext].nPrevAnim = nPrev;
|
2019-08-31 07:47:15 +00:00
|
|
|
}
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-10-28 19:45:35 +00:00
|
|
|
if (nPrev >= 0) {
|
|
|
|
StatusAnim[nPrev].nNextAnim = nNext;
|
2019-08-31 07:47:15 +00:00
|
|
|
}
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
if (nAnim == nFirstAnim) {
|
2019-10-28 19:45:35 +00:00
|
|
|
nFirstAnim = nPrev;
|
2019-08-31 07:47:15 +00:00
|
|
|
}
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
if (nAnim == nLastAnim) {
|
2019-10-28 19:45:35 +00:00
|
|
|
nLastAnim = nNext;
|
2019-08-31 07:47:15 +00:00
|
|
|
}
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
StatusAnimsFree[nAnimsFree] = (uint8_t)nAnim;
|
|
|
|
nAnimsFree++;
|
2019-08-26 03:59:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void DrawStatusAnims()
|
|
|
|
{
|
2019-10-28 19:45:35 +00:00
|
|
|
for (int i = nFirstAnim; i >= 0; i = StatusAnim[i].nPrevAnim)
|
2019-08-31 07:47:15 +00:00
|
|
|
{
|
2019-10-28 19:45:35 +00:00
|
|
|
int nSequence = nStatusSeqOffset + StatusAnim[i].s1;
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2020-01-21 18:14:53 +00:00
|
|
|
//seq_DrawStatusSequence(nSequence, StatusAnim[i].s2, 0);
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-10-28 19:45:35 +00:00
|
|
|
/*
|
2019-08-31 07:47:15 +00:00
|
|
|
if (StatusAnim[nAnim].s2 >= (SeqSize[nSequence] - 1))
|
|
|
|
{
|
|
|
|
if (!(StatusAnimFlags[nAnim] & 0x10))
|
|
|
|
{
|
|
|
|
StatusAnim[nAnim].nPage--;
|
|
|
|
if (StatusAnim[nAnim].nPage <= 0) {
|
|
|
|
DestroyStatusAnim(nAnim);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-10-28 19:45:35 +00:00
|
|
|
*/
|
2019-08-31 07:47:15 +00:00
|
|
|
}
|
2019-08-26 03:59:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void SetMagicFrame()
|
|
|
|
{
|
2019-08-31 07:47:15 +00:00
|
|
|
nMagicLevel = (1000 - PlayerList[nLocalPlayer].nMagic) / magicperline;
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
if (nMagicLevel >= nMeterRange) {
|
|
|
|
nMagicLevel = nMeterRange - 1;
|
|
|
|
}
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
if (nMagicLevel < 0) {
|
|
|
|
nMagicLevel = 0;
|
|
|
|
}
|
2019-11-20 16:21:32 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
SetItemSeq();
|
2019-08-26 03:59:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void SetHealthFrame(short nVal)
|
|
|
|
{
|
2019-08-31 07:47:15 +00:00
|
|
|
nHealthLevel = (800 - PlayerList[nLocalPlayer].nHealth) / healthperline;
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
if (nHealthLevel >= nMeterRange ) {
|
|
|
|
nHealthLevel = nMeterRange - 1;
|
|
|
|
}
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
if (nHealthLevel < 0) {
|
|
|
|
nHealthLevel = 0;
|
|
|
|
}
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
if (nVal < 0) {
|
|
|
|
BuildStatusAnim(4, 0);
|
|
|
|
}
|
2019-08-26 03:59:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void SetAirFrame()
|
|
|
|
{
|
2019-08-31 07:47:15 +00:00
|
|
|
airframe = PlayerList[nLocalPlayer].nAir / airperline;
|
|
|
|
|
2019-10-29 15:17:43 +00:00
|
|
|
if (airframe >= nAirFrames)
|
2019-08-31 07:47:15 +00:00
|
|
|
{
|
2019-10-29 15:17:43 +00:00
|
|
|
airframe = nAirFrames - 1;
|
2019-08-31 07:47:15 +00:00
|
|
|
}
|
2019-10-29 15:17:43 +00:00
|
|
|
else if (airframe < 0)
|
2019-08-31 07:47:15 +00:00
|
|
|
{
|
2019-10-29 15:17:43 +00:00
|
|
|
airframe = 0;
|
2019-08-31 07:47:15 +00:00
|
|
|
}
|
2019-08-26 03:59:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void SetCounter(short nVal)
|
|
|
|
{
|
2019-08-31 07:47:15 +00:00
|
|
|
if (nVal <= 999)
|
|
|
|
{
|
|
|
|
if (nVal < 0) {
|
|
|
|
nVal = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
nVal = 999;
|
|
|
|
}
|
|
|
|
|
|
|
|
nCounterDest = nVal;
|
2019-08-26 03:59:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void SetCounterImmediate(short nVal)
|
|
|
|
{
|
2019-08-31 07:47:15 +00:00
|
|
|
SetCounter(nVal);
|
|
|
|
nCounter = nCounterDest;
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
SetCounterDigits();
|
2019-08-26 03:59:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void SetCounterDigits()
|
|
|
|
{
|
2019-08-31 07:47:15 +00:00
|
|
|
nDigit[2] = 3 * (nCounter / 100 % 10);
|
|
|
|
nDigit[1] = 3 * (nCounter / 10 % 10);
|
|
|
|
nDigit[0] = 3 * (nCounter % 10);
|
2019-08-26 03:59:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void SetItemSeq()
|
|
|
|
{
|
2019-08-31 07:47:15 +00:00
|
|
|
short nItem = nPlayerItem[nLocalPlayer];
|
|
|
|
if (nItem < 0)
|
|
|
|
{
|
|
|
|
nItemSeq = -1;
|
|
|
|
return;
|
|
|
|
}
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
short nOffset = nItemSeqOffset[nItem];
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
SetItemSeq2(nOffset);
|
2019-08-26 03:59:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void SetItemSeq2(int nSeqOffset)
|
|
|
|
{
|
2019-08-31 07:47:15 +00:00
|
|
|
short nItem = nPlayerItem[nLocalPlayer];
|
|
|
|
|
|
|
|
if (nItemMagic[nItem] <= PlayerList[nLocalPlayer].nMagic) {
|
|
|
|
nItemAltSeq = 0;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
nItemAltSeq = 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
nItemFrame = 0;
|
|
|
|
nItemSeq = nSeqOffset + nItemAltSeq;
|
|
|
|
nItemFrames = SeqSize[nItemSeq + nStatusSeqOffset];
|
2019-08-26 03:59:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void SetPlayerItem(short nPlayer, short nItem)
|
|
|
|
{
|
2019-08-31 07:47:15 +00:00
|
|
|
nPlayerItem[nPlayer] = nItem;
|
|
|
|
|
|
|
|
if (nPlayer == nLocalPlayer)
|
|
|
|
{
|
|
|
|
SetItemSeq();
|
|
|
|
if (nItem >= 0) {
|
2019-10-28 19:45:35 +00:00
|
|
|
BuildStatusAnim(156 + (2 * PlayerList[nLocalPlayer].items[nItem]), 0);
|
2019-08-31 07:47:15 +00:00
|
|
|
}
|
|
|
|
}
|
2019-08-26 03:59:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void SetNextItem(int nPlayer)
|
|
|
|
{
|
2019-08-31 07:47:15 +00:00
|
|
|
short nItem = nPlayerItem[nPlayer];
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
int i;
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
for (i = 6; i > 0; i--)
|
|
|
|
{
|
|
|
|
nItem++;
|
|
|
|
if (nItem == 6)
|
|
|
|
nItem = 0;
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
if (PlayerList[nPlayer].items[nItem] != 0)
|
|
|
|
break;
|
|
|
|
}
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
if (i > 0) {
|
|
|
|
SetPlayerItem(nPlayer, nItem);
|
|
|
|
}
|
2019-08-26 03:59:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void SetPrevItem(int nPlayer)
|
|
|
|
{
|
2019-08-31 07:47:15 +00:00
|
|
|
if (nPlayerItem[nPlayer] == -1)
|
|
|
|
return;
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
int nItem = nPlayerItem[nPlayer];
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
int i;
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
for (i = 6; i > 0; i--)
|
|
|
|
{
|
|
|
|
nItem--;
|
|
|
|
if (nItem < 0)
|
|
|
|
nItem = 5;
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
if (PlayerList[nPlayer].items[nItem] != 0)
|
|
|
|
break;
|
|
|
|
}
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
if (i > 0) {
|
|
|
|
SetPlayerItem(nPlayer, nItem);
|
|
|
|
}
|
2019-08-26 03:59:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MoveStatus()
|
|
|
|
{
|
2019-08-31 07:47:15 +00:00
|
|
|
if (nItemSeq >= 0)
|
|
|
|
{
|
|
|
|
nItemFrame++;
|
|
|
|
|
|
|
|
if (nItemFrame >= nItemFrames)
|
|
|
|
{
|
|
|
|
if (nItemSeq == 67) {
|
|
|
|
SetItemSeq();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
nItemSeq -= nItemAltSeq;
|
|
|
|
|
|
|
|
if (nItemAltSeq || totalmoves & 0x1F)
|
|
|
|
{
|
|
|
|
if (nItemSeq < 2) {
|
|
|
|
nItemAltSeq = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
nItemAltSeq = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
nItemFrame = 0;
|
|
|
|
nItemSeq += nItemAltSeq;
|
|
|
|
nItemFrames = SeqSize[nStatusSeqOffset + nItemSeq];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (message_timer)
|
|
|
|
{
|
|
|
|
message_timer -= 4;
|
|
|
|
if (message_timer <= 0)
|
|
|
|
{
|
2019-10-29 14:17:15 +00:00
|
|
|
if (screensize > 0) {
|
2019-08-31 07:47:15 +00:00
|
|
|
textpages = numpages;
|
|
|
|
}
|
|
|
|
|
|
|
|
message_timer = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
MoveStatusAnims();
|
|
|
|
|
|
|
|
if (nCounter == nCounterDest)
|
|
|
|
{
|
|
|
|
nCounter = nCounterDest;
|
|
|
|
ammodelay = 3;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ammodelay--;
|
|
|
|
if (ammodelay > 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int eax = nCounterDest - nCounter;
|
|
|
|
|
|
|
|
if (eax <= 0)
|
|
|
|
{
|
|
|
|
if (eax >= -30)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < 3; i++)
|
|
|
|
{
|
|
|
|
nDigit[i]--;
|
|
|
|
|
|
|
|
if (nDigit[i] < 0)
|
|
|
|
{
|
|
|
|
nDigit[i] += 30;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (nDigit[i] < 27) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
nCounter += (nCounterDest - nCounter) >> 1;
|
|
|
|
SetCounterDigits();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (eax <= 30)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < 3; i++)
|
|
|
|
{
|
|
|
|
nDigit[i]++;
|
|
|
|
|
|
|
|
if (nDigit[i] <= 27) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (nDigit[i] >= 30) {
|
|
|
|
nDigit[i] -= 30;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
nCounter += (nCounterDest - nCounter) >> 1;
|
|
|
|
SetCounterDigits();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2019-11-20 16:21:32 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
if (!(nDigit[0] % 3)) {
|
|
|
|
nCounter = nDigit[0] / 3 + 100 * (nDigit[2] / 3) + 10 * (nDigit[1] / 3);
|
|
|
|
}
|
|
|
|
|
|
|
|
eax = nCounterDest - nCounter;
|
|
|
|
if (eax < 0) {
|
|
|
|
eax = -eax;
|
|
|
|
}
|
|
|
|
|
|
|
|
ammodelay = 4 - (eax >> 1);
|
|
|
|
if (ammodelay < 1) {
|
|
|
|
ammodelay = 1;
|
|
|
|
}
|
2019-08-26 03:59:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void UnMaskStatus()
|
|
|
|
{
|
2019-08-31 16:05:11 +00:00
|
|
|
#if 0
|
2019-08-31 07:47:15 +00:00
|
|
|
for (int i = 0; i < xdim; i++) {
|
|
|
|
startdmost[i] = ydim;
|
|
|
|
}
|
2019-08-31 16:05:11 +00:00
|
|
|
#endif
|
2019-08-26 03:59:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MaskStatus()
|
|
|
|
{
|
2019-08-31 16:05:11 +00:00
|
|
|
#if 0
|
2019-08-31 07:47:15 +00:00
|
|
|
for (int i = 0; i < xdim; i++)
|
|
|
|
{
|
|
|
|
short bx = startdmost[i];
|
|
|
|
short cx = statusmask[i];
|
|
|
|
|
|
|
|
if (bx > cx) {
|
|
|
|
startdmost[i] = cx;
|
|
|
|
}
|
|
|
|
}
|
2019-08-31 16:05:11 +00:00
|
|
|
#endif
|
2019-08-26 03:59:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void LoadStatus()
|
|
|
|
{
|
2019-08-31 16:05:11 +00:00
|
|
|
#if 0
|
2019-08-31 07:47:15 +00:00
|
|
|
int i;
|
|
|
|
short nSize;
|
|
|
|
short tmp;
|
|
|
|
short buffer[1024];
|
2019-08-26 03:59:14 +00:00
|
|
|
// memset(buffer, 0, sizeof(buffer)); // bjd - added by me
|
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
for (i = 0; i < xdim; i++) {
|
|
|
|
statusmask[i] = ydim;
|
|
|
|
}
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
nMaskY = ydim;
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
int hStatus = kopen4load("status.msk", 1);
|
|
|
|
if (!hStatus) {
|
|
|
|
return;
|
|
|
|
}
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
kread(hStatus, &nSize, sizeof(nSize));
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
int nCount = nSize >> 1;
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
kread(hStatus, &tmp, sizeof(tmp));
|
|
|
|
kread(hStatus, buffer, nSize);
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
kclose(hStatus);
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
short *pStatusMask = statusmask;
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
for (i = 0; i < nCount; i++)
|
|
|
|
{
|
|
|
|
int v8 = ydim - ((ydim * buffer[i]) / 200);
|
|
|
|
*pStatusMask++ = ydim - v8;
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
if (bHiRes) {
|
|
|
|
*pStatusMask++ = ydim - v8;
|
|
|
|
}
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
if (ydim - v8 < nMaskY) {
|
|
|
|
nMaskY = ydim - v8;
|
|
|
|
}
|
|
|
|
}
|
2019-08-31 16:05:11 +00:00
|
|
|
#endif
|
2019-08-26 03:59:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void StatusMessage(int messageTime, const char *fmt, ...)
|
|
|
|
{
|
2019-08-31 07:47:15 +00:00
|
|
|
message_timer = messageTime;
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
va_list args;
|
2019-08-26 03:59:14 +00:00
|
|
|
va_start(args, fmt);
|
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
vsprintf(message_text, fmt, args);
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-10-29 14:17:15 +00:00
|
|
|
if (screensize > 0) {
|
2019-08-31 07:47:15 +00:00
|
|
|
textpages = numpages;
|
|
|
|
}
|
2019-08-26 03:59:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void DrawStatus()
|
|
|
|
{
|
2019-08-31 07:47:15 +00:00
|
|
|
char numberBuf[10] = {0};
|
|
|
|
char stringBuf[20] = {0};
|
|
|
|
char coordBuf[50] = {0}; // not sure of the size for this?
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
if (!bFullScreen && nNetTime)
|
|
|
|
{
|
|
|
|
// bjd - commenting out this check seems to fix the black status bar at 320x200 resolution
|
2019-08-26 03:59:14 +00:00
|
|
|
// if (bHiRes) {
|
2019-08-31 07:47:15 +00:00
|
|
|
NoClip();
|
2019-08-26 03:59:14 +00:00
|
|
|
// }
|
|
|
|
|
2019-08-31 16:05:11 +00:00
|
|
|
// draw the main bar itself
|
|
|
|
seq_DrawStatusSequence(nStatusSeqOffset, 0, 0);
|
2019-08-31 07:47:15 +00:00
|
|
|
|
|
|
|
seq_DrawStatusSequence(nStatusSeqOffset + 128, 0, 0);
|
|
|
|
seq_DrawStatusSequence(nStatusSeqOffset + 127, 0, 0);
|
|
|
|
seq_DrawStatusSequence(nStatusSeqOffset + 1, nHealthFrame, nHealthLevel);
|
|
|
|
seq_DrawStatusSequence(nStatusSeqOffset + 129, nMagicFrame, nMagicLevel);
|
|
|
|
|
|
|
|
nHealthFrame++;
|
|
|
|
if (nHealthFrame >= nHealthFrames) {
|
|
|
|
nHealthFrame = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
nMagicFrame++;
|
|
|
|
if (nMagicFrame >= nMagicFrames) {
|
|
|
|
nMagicFrame = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
seq_DrawStatusSequence(nStatusSeqOffset + 125, 0, 0); // draw ankh on health pool
|
|
|
|
seq_DrawStatusSequence(nStatusSeqOffset + 130, 0, 0); // draw health pool frame (top)
|
|
|
|
seq_DrawStatusSequence(nStatusSeqOffset + 131, 0, 0); // magic pool frame (bottom)
|
|
|
|
|
|
|
|
if (nItemSeq >= 0) {
|
|
|
|
seq_DrawStatusSequence(nItemSeq + nStatusSeqOffset, nItemFrame, 0);
|
|
|
|
}
|
|
|
|
|
2019-10-28 19:45:35 +00:00
|
|
|
// draws health level dots, animates breathing lungs and other things
|
2019-08-31 07:47:15 +00:00
|
|
|
DrawStatusAnims();
|
|
|
|
|
2019-10-28 19:45:35 +00:00
|
|
|
// draw the blue air level meter when underwater (but not responsible for animating the breathing lungs otherwise)
|
2019-08-31 07:47:15 +00:00
|
|
|
if (airpages)
|
|
|
|
{
|
|
|
|
seq_DrawStatusSequence(nStatusSeqOffset + 133, airframe, 0);
|
2019-10-29 15:17:43 +00:00
|
|
|
// airpages--;
|
2019-08-31 07:47:15 +00:00
|
|
|
}
|
|
|
|
|
2019-10-28 19:45:35 +00:00
|
|
|
// draw compass
|
2019-08-31 07:47:15 +00:00
|
|
|
seq_DrawStatusSequence(nStatusSeqOffset + 35, ((inita + 128) & kAngleMask) >> 8, 0);
|
|
|
|
|
|
|
|
if (bCoordinates)
|
|
|
|
{
|
2019-11-13 20:06:48 +00:00
|
|
|
sprintf(numberBuf, "%i", lastfps);
|
|
|
|
// char *cFPS = itoa(lastfps, numberBuf, 10);
|
|
|
|
printext(xdim - 20, nViewTop, numberBuf, kTile159, -1);
|
2019-08-31 07:47:15 +00:00
|
|
|
}
|
|
|
|
|
2019-10-28 19:45:35 +00:00
|
|
|
// draw ammo count
|
2019-08-31 16:05:11 +00:00
|
|
|
seq_DrawStatusSequence(nStatusSeqOffset + 44, nDigit[2], 0);
|
|
|
|
seq_DrawStatusSequence(nStatusSeqOffset + 45, nDigit[1], 0);
|
|
|
|
seq_DrawStatusSequence(nStatusSeqOffset + 46, nDigit[0], 0);
|
2019-08-31 07:47:15 +00:00
|
|
|
|
|
|
|
// bjd - commenting out this check seems to fix the black status bar at 320x200 resolution
|
2019-08-26 03:59:14 +00:00
|
|
|
// if (bHiRes) {
|
2019-08-31 07:47:15 +00:00
|
|
|
Clip();
|
2019-08-26 03:59:14 +00:00
|
|
|
// }
|
2019-08-31 07:47:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (nNetPlayerCount)
|
|
|
|
{
|
|
|
|
NoClip();
|
|
|
|
|
|
|
|
int shade;
|
|
|
|
|
2019-09-06 05:18:12 +00:00
|
|
|
if ((int)totalclock / kTimerTicks & 1) {
|
2019-08-31 07:47:15 +00:00
|
|
|
shade = -100;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
shade = 127;
|
|
|
|
}
|
|
|
|
|
|
|
|
int nTile = kTile3593;
|
|
|
|
|
|
|
|
int x = 320 / (nTotalPlayers + 1);
|
|
|
|
|
|
|
|
for (int i = 0; i < nTotalPlayers; i++)
|
|
|
|
{
|
|
|
|
int nScore = nPlayerScore[i];
|
|
|
|
if (word_9AD54[i] == nScore)
|
|
|
|
{
|
|
|
|
int v9 = dword_9AD64[i];
|
2019-09-06 05:18:12 +00:00
|
|
|
if (v9 && v9 <= (int)totalclock) {
|
2019-08-31 07:47:15 +00:00
|
|
|
dword_9AD64[i] = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
word_9AD54[i] = nScore;
|
2019-09-06 05:18:12 +00:00
|
|
|
dword_9AD64[i] = (int)totalclock + 30;
|
2019-08-31 07:47:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
overwritesprite(x, 7, nTile, 0, 3, kPalNormal);
|
|
|
|
|
|
|
|
if (i != nLocalPlayer) {
|
|
|
|
shade = -100;
|
|
|
|
}
|
|
|
|
|
|
|
|
sprintf(stringBuf, "%d", nPlayerScore[i]);
|
|
|
|
int nStringLen = MyGetStringWidth(stringBuf);
|
|
|
|
|
|
|
|
myprintext(x - (nStringLen / 2), 4, stringBuf, shade);
|
|
|
|
|
|
|
|
x *= 2;
|
|
|
|
nTile++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (nNetTime >= 0)
|
|
|
|
{
|
|
|
|
int y = nViewTop;
|
|
|
|
|
|
|
|
if (nNetTime)
|
|
|
|
{
|
|
|
|
int v12 = (nNetTime + 29) / 30 % 60;
|
|
|
|
int v13 = (nNetTime + 29) / 1800;
|
|
|
|
nNetTime += 29;
|
|
|
|
|
|
|
|
sprintf(stringBuf, "%d.%02d", v13, v12);
|
|
|
|
|
|
|
|
if (bHiRes) {
|
|
|
|
y = nViewTop / 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (nViewTop <= 0) {
|
|
|
|
y += 20;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
y += 15;
|
|
|
|
}
|
|
|
|
|
|
|
|
nNetTime -= 29;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
y = 100;
|
|
|
|
strcpy(stringBuf, "GAME OVER");
|
|
|
|
}
|
|
|
|
|
|
|
|
int nLenString = MyGetStringWidth(stringBuf);
|
|
|
|
myprintext((320 - nLenString) / 2, y, stringBuf, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
Clip();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bCoordinates)
|
|
|
|
{
|
|
|
|
int nSprite = PlayerList[nLocalPlayer].nSprite;
|
|
|
|
|
|
|
|
int x = (nViewLeft + nViewRight) / 2;
|
|
|
|
|
2019-11-24 15:34:23 +00:00
|
|
|
snprintf(coordBuf, 50, "X %d", (int)sprite[nSprite].x.cast());
|
2019-08-31 07:47:15 +00:00
|
|
|
printext(x, nViewTop + 1, coordBuf, kTile159, 255);
|
|
|
|
|
2019-11-24 15:34:23 +00:00
|
|
|
snprintf(coordBuf, 50, "Y %d", sprite[nSprite].y.cast());
|
2019-08-31 07:47:15 +00:00
|
|
|
printext(x, nViewTop + 10, coordBuf, kTile159, 255);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bHolly)
|
|
|
|
{
|
2019-11-24 15:34:23 +00:00
|
|
|
snprintf(message_text, 80, "HOLLY: %s", sHollyStr);
|
2019-08-31 07:47:15 +00:00
|
|
|
printext(0, 0, message_text, kTile159, 255);
|
|
|
|
}
|
|
|
|
else if (nSnakeCam < 0)
|
|
|
|
{
|
|
|
|
if (message_timer) {
|
|
|
|
printext(0, 0, message_text, kTile159, 255);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
printext(0, 0, "S E R P E N T C A M", kTile159, 255);
|
|
|
|
}
|
2019-08-26 03:59:14 +00:00
|
|
|
}
|
2019-11-22 23:11:37 +00:00
|
|
|
|
2019-12-26 21:00:04 +00:00
|
|
|
// I'm not sure this really needs to be saved.
|
|
|
|
static SavegameHelper sgh("status",
|
|
|
|
SV(nMaskY),
|
|
|
|
SV(nAnimsFree),
|
|
|
|
SV(message_timer),
|
|
|
|
SV(magicperline),
|
|
|
|
SV(airperline),
|
|
|
|
SV(healthperline),
|
|
|
|
SV(nAirFrames),
|
|
|
|
SV(nCounter),
|
|
|
|
SV(nCounterDest),
|
|
|
|
SV(nStatusSeqOffset),
|
|
|
|
SV(nItemFrames),
|
|
|
|
SV(laststatusx),
|
|
|
|
SV(laststatusy),
|
|
|
|
SV(nItemSeq),
|
|
|
|
SV(nMagicFrames),
|
|
|
|
SV(nHealthLevel),
|
|
|
|
SV(nItemFrame),
|
|
|
|
SV(nMeterRange),
|
|
|
|
SV(nMagicLevel),
|
|
|
|
SV(nHealthFrame),
|
|
|
|
SV(nMagicFrame),
|
|
|
|
SV(statusx),
|
|
|
|
SV(statusy),
|
|
|
|
SV(nHealthFrames),
|
|
|
|
SV(airframe),
|
|
|
|
SV(nFirstAnim),
|
|
|
|
SV(nLastAnim),
|
|
|
|
SV(nItemAltSeq),
|
|
|
|
SV(airpages),
|
|
|
|
SV(ammodelay),
|
|
|
|
SV(nCounterBullet),
|
|
|
|
SA(statusmask),
|
|
|
|
SA(message_text),
|
|
|
|
SA(nDigit),
|
|
|
|
SA(StatusAnim),
|
|
|
|
SA(StatusAnimsFree),
|
|
|
|
SA(StatusAnimFlags),
|
|
|
|
SA(nItemSeqOffset),
|
|
|
|
SA(word_9AD54),
|
|
|
|
SA(dword_9AD64),
|
|
|
|
nullptr);
|
|
|
|
|
|
|
|
|
2019-11-22 23:11:37 +00:00
|
|
|
END_PS_NS
|