0,0 → 1,1604 |
// WL_GAME.C |
|
#include <math.h> |
#include "wl_def.h" |
//#include <SDL_mixer.h> |
#pragma hdrstop |
|
#ifdef MYPROFILE |
#include <TIME.H> |
#endif |
|
|
/* |
============================================================================= |
|
LOCAL CONSTANTS |
|
============================================================================= |
*/ |
|
|
/* |
============================================================================= |
|
GLOBAL VARIABLES |
|
============================================================================= |
*/ |
|
boolean ingame,fizzlein; |
gametype gamestate; |
byte bordercol=VIEWCOLOR; // color of the Change View/Ingame border |
|
#ifdef SPEAR |
int32_t spearx,speary; |
unsigned spearangle; |
boolean spearflag; |
#endif |
|
#ifdef USE_FEATUREFLAGS |
int ffDataTopLeft, ffDataTopRight, ffDataBottomLeft, ffDataBottomRight; |
#endif |
|
// |
// ELEVATOR BACK MAPS - REMEMBER (-1)!! |
// |
int ElevatorBackTo[]={1,1,7,3,5,3}; |
|
void SetupGameLevel (void); |
void DrawPlayScreen (void); |
void LoadLatchMem (void); |
void GameLoop (void); |
|
/* |
============================================================================= |
|
LOCAL VARIABLES |
|
============================================================================= |
*/ |
|
|
|
//=========================================================================== |
//=========================================================================== |
|
|
/* |
========================== |
= |
= SetSoundLoc - Given the location of an object (in terms of global |
= coordinates, held in globalsoundx and globalsoundy), munges the values |
= for an approximate distance from the left and right ear, and puts |
= those values into leftchannel and rightchannel. |
= |
= JAB |
= |
========================== |
*/ |
|
int leftchannel, rightchannel; |
#define ATABLEMAX 15 |
byte righttable[ATABLEMAX][ATABLEMAX * 2] = { |
{ 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 6, 0, 0, 0, 0, 0, 1, 3, 5, 8, 8, 8, 8, 8, 8, 8, 8}, |
{ 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 6, 4, 0, 0, 0, 0, 0, 2, 4, 6, 8, 8, 8, 8, 8, 8, 8, 8}, |
{ 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 4, 1, 0, 0, 0, 1, 2, 4, 6, 8, 8, 8, 8, 8, 8, 8, 8}, |
{ 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 6, 5, 4, 2, 1, 0, 1, 2, 3, 5, 7, 8, 8, 8, 8, 8, 8, 8, 8}, |
{ 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 6, 5, 4, 3, 2, 2, 3, 3, 5, 6, 8, 8, 8, 8, 8, 8, 8, 8, 8}, |
{ 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 6, 6, 5, 4, 4, 4, 4, 5, 6, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8}, |
{ 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 6, 6, 5, 5, 5, 6, 6, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}, |
{ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 6, 6, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}, |
{ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}, |
{ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}, |
{ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}, |
{ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}, |
{ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}, |
{ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}, |
{ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8} |
}; |
byte lefttable[ATABLEMAX][ATABLEMAX * 2] = { |
{ 8, 8, 8, 8, 8, 8, 8, 8, 5, 3, 1, 0, 0, 0, 0, 0, 6, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8}, |
{ 8, 8, 8, 8, 8, 8, 8, 8, 6, 4, 2, 0, 0, 0, 0, 0, 4, 6, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8}, |
{ 8, 8, 8, 8, 8, 8, 8, 8, 6, 4, 2, 1, 0, 0, 0, 1, 4, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8}, |
{ 8, 8, 8, 8, 8, 8, 8, 8, 7, 5, 3, 2, 1, 0, 1, 2, 4, 5, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8}, |
{ 8, 8, 8, 8, 8, 8, 8, 8, 8, 6, 5, 3, 3, 2, 2, 3, 4, 5, 6, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8}, |
{ 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 6, 5, 4, 4, 4, 4, 5, 6, 6, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8}, |
{ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 6, 6, 5, 5, 5, 6, 6, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8}, |
{ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 6, 6, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}, |
{ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}, |
{ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}, |
{ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}, |
{ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}, |
{ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}, |
{ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}, |
{ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8} |
}; |
|
void |
SetSoundLoc(fixed gx,fixed gy) |
{ |
fixed xt,yt; |
int x,y; |
|
// |
// translate point to view centered coordinates |
// |
gx -= viewx; |
gy -= viewy; |
|
// |
// calculate newx |
// |
xt = FixedMul(gx,viewcos); |
yt = FixedMul(gy,viewsin); |
x = (xt - yt) >> TILESHIFT; |
|
// |
// calculate newy |
// |
xt = FixedMul(gx,viewsin); |
yt = FixedMul(gy,viewcos); |
y = (yt + xt) >> TILESHIFT; |
|
if (y >= ATABLEMAX) |
y = ATABLEMAX - 1; |
else if (y <= -ATABLEMAX) |
y = -ATABLEMAX; |
if (x < 0) |
x = -x; |
if (x >= ATABLEMAX) |
x = ATABLEMAX - 1; |
leftchannel = lefttable[x][y + ATABLEMAX]; |
rightchannel = righttable[x][y + ATABLEMAX]; |
|
#if 0 |
CenterWindow(8,1); |
US_PrintSigned(leftchannel); |
US_Print(","); |
US_PrintSigned(rightchannel); |
VW_UpdateScreen(); |
#endif |
} |
|
/* |
========================== |
= |
= SetSoundLocGlobal - Sets up globalsoundx & globalsoundy and then calls |
= UpdateSoundLoc() to transform that into relative channel volumes. Those |
= values are then passed to the Sound Manager so that they'll be used for |
= the next sound played (if possible). |
= |
= JAB |
= |
========================== |
*/ |
void PlaySoundLocGlobal(word s,fixed gx,fixed gy) |
{ |
SetSoundLoc(gx, gy); |
SD_PositionSound(leftchannel, rightchannel); |
|
int channel = SD_PlaySound((soundnames) s); |
if(channel) |
{ |
/* channelSoundPos[channel - 1].globalsoundx = gx; |
channelSoundPos[channel - 1].globalsoundy = gy; |
channelSoundPos[channel - 1].valid = 1;*/ |
} |
} |
|
void UpdateSoundLoc(void) |
{ |
/* if (SoundPositioned) |
{ |
SetSoundLoc(globalsoundx,globalsoundy); |
SD_SetPosition(leftchannel,rightchannel); |
}*/ |
/* |
for(int i = 0; i < MIX_CHANNELS; i++) |
{ |
if(channelSoundPos[i].valid) |
{ |
SetSoundLoc(channelSoundPos[i].globalsoundx, |
channelSoundPos[i].globalsoundy); |
SD_SetPosition(i, leftchannel, rightchannel); |
} |
}*/ |
} |
|
/* |
** JAB End |
*/ |
|
/* |
========================== |
= |
= ScanInfoPlane |
= |
= Spawn all actors and mark down special places |
= |
========================== |
*/ |
|
static void ScanInfoPlane(void) |
{ |
unsigned x,y; |
int tile; |
word *start; |
|
start = mapsegs[1]; |
for (y=0;y<mapheight;y++) |
{ |
for (x=0;x<mapwidth;x++) |
{ |
tile = *start++; |
if (!tile) |
continue; |
|
switch (tile) |
{ |
case 19: |
case 20: |
case 21: |
case 22: |
SpawnPlayer(x,y,NORTH+tile-19); |
break; |
|
case 23: |
case 24: |
case 25: |
case 26: |
case 27: |
case 28: |
case 29: |
case 30: |
|
case 31: |
case 32: |
case 33: |
case 34: |
case 35: |
case 36: |
case 37: |
case 38: |
|
case 39: |
case 40: |
case 41: |
case 42: |
case 43: |
case 44: |
case 45: |
case 46: |
|
case 47: |
case 48: |
case 49: |
case 50: |
case 51: |
case 52: |
case 53: |
case 54: |
|
case 55: |
case 56: |
case 57: |
case 58: |
case 59: |
case 60: |
case 61: |
case 62: |
|
case 63: |
case 64: |
case 65: |
case 66: |
case 67: |
case 68: |
case 69: |
case 70: |
case 71: |
case 72: |
#ifdef SPEAR |
case 73: // TRUCK AND SPEAR! |
case 74: |
#elif defined(USE_DIR3DSPR) // just for the example |
case 73: |
#endif |
SpawnStatic(x,y,tile-23); |
break; |
|
// |
// P wall |
// |
case 98: |
if (!loadedgame) |
gamestate.secrettotal++; |
break; |
|
// |
// guard |
// |
case 180: |
case 181: |
case 182: |
case 183: |
if (gamestate.difficulty<gd_hard) |
break; |
tile -= 36; |
case 144: |
case 145: |
case 146: |
case 147: |
if (gamestate.difficulty<gd_medium) |
break; |
tile -= 36; |
case 108: |
case 109: |
case 110: |
case 111: |
SpawnStand(en_guard,x,y,tile-108); |
break; |
|
|
case 184: |
case 185: |
case 186: |
case 187: |
if (gamestate.difficulty<gd_hard) |
break; |
tile -= 36; |
case 148: |
case 149: |
case 150: |
case 151: |
if (gamestate.difficulty<gd_medium) |
break; |
tile -= 36; |
case 112: |
case 113: |
case 114: |
case 115: |
SpawnPatrol(en_guard,x,y,tile-112); |
break; |
|
case 124: |
SpawnDeadGuard (x,y); |
break; |
// |
// officer |
// |
case 188: |
case 189: |
case 190: |
case 191: |
if (gamestate.difficulty<gd_hard) |
break; |
tile -= 36; |
case 152: |
case 153: |
case 154: |
case 155: |
if (gamestate.difficulty<gd_medium) |
break; |
tile -= 36; |
case 116: |
case 117: |
case 118: |
case 119: |
SpawnStand(en_officer,x,y,tile-116); |
break; |
|
|
case 192: |
case 193: |
case 194: |
case 195: |
if (gamestate.difficulty<gd_hard) |
break; |
tile -= 36; |
case 156: |
case 157: |
case 158: |
case 159: |
if (gamestate.difficulty<gd_medium) |
break; |
tile -= 36; |
case 120: |
case 121: |
case 122: |
case 123: |
SpawnPatrol(en_officer,x,y,tile-120); |
break; |
|
|
// |
// ss |
// |
case 198: |
case 199: |
case 200: |
case 201: |
if (gamestate.difficulty<gd_hard) |
break; |
tile -= 36; |
case 162: |
case 163: |
case 164: |
case 165: |
if (gamestate.difficulty<gd_medium) |
break; |
tile -= 36; |
case 126: |
case 127: |
case 128: |
case 129: |
SpawnStand(en_ss,x,y,tile-126); |
break; |
|
|
case 202: |
case 203: |
case 204: |
case 205: |
if (gamestate.difficulty<gd_hard) |
break; |
tile -= 36; |
case 166: |
case 167: |
case 168: |
case 169: |
if (gamestate.difficulty<gd_medium) |
break; |
tile -= 36; |
case 130: |
case 131: |
case 132: |
case 133: |
SpawnPatrol(en_ss,x,y,tile-130); |
break; |
|
// |
// dogs |
// |
case 206: |
case 207: |
case 208: |
case 209: |
if (gamestate.difficulty<gd_hard) |
break; |
tile -= 36; |
case 170: |
case 171: |
case 172: |
case 173: |
if (gamestate.difficulty<gd_medium) |
break; |
tile -= 36; |
case 134: |
case 135: |
case 136: |
case 137: |
SpawnStand(en_dog,x,y,tile-134); |
break; |
|
|
case 210: |
case 211: |
case 212: |
case 213: |
if (gamestate.difficulty<gd_hard) |
break; |
tile -= 36; |
case 174: |
case 175: |
case 176: |
case 177: |
if (gamestate.difficulty<gd_medium) |
break; |
tile -= 36; |
case 138: |
case 139: |
case 140: |
case 141: |
SpawnPatrol(en_dog,x,y,tile-138); |
break; |
|
// |
// boss |
// |
#ifndef SPEAR |
case 214: |
SpawnBoss (x,y); |
break; |
case 197: |
SpawnGretel (x,y); |
break; |
case 215: |
SpawnGift (x,y); |
break; |
case 179: |
SpawnFat (x,y); |
break; |
case 196: |
SpawnSchabbs (x,y); |
break; |
case 160: |
SpawnFakeHitler (x,y); |
break; |
case 178: |
SpawnHitler (x,y); |
break; |
#else |
case 106: |
SpawnSpectre (x,y); |
break; |
case 107: |
SpawnAngel (x,y); |
break; |
case 125: |
SpawnTrans (x,y); |
break; |
case 142: |
SpawnUber (x,y); |
break; |
case 143: |
SpawnWill (x,y); |
break; |
case 161: |
SpawnDeath (x,y); |
break; |
|
#endif |
|
// |
// mutants |
// |
case 252: |
case 253: |
case 254: |
case 255: |
if (gamestate.difficulty<gd_hard) |
break; |
tile -= 18; |
case 234: |
case 235: |
case 236: |
case 237: |
if (gamestate.difficulty<gd_medium) |
break; |
tile -= 18; |
case 216: |
case 217: |
case 218: |
case 219: |
SpawnStand(en_mutant,x,y,tile-216); |
break; |
|
case 256: |
case 257: |
case 258: |
case 259: |
if (gamestate.difficulty<gd_hard) |
break; |
tile -= 18; |
case 238: |
case 239: |
case 240: |
case 241: |
if (gamestate.difficulty<gd_medium) |
break; |
tile -= 18; |
case 220: |
case 221: |
case 222: |
case 223: |
SpawnPatrol(en_mutant,x,y,tile-220); |
break; |
|
// |
// ghosts |
// |
#ifndef SPEAR |
case 224: |
SpawnGhosts (en_blinky,x,y); |
break; |
case 225: |
SpawnGhosts (en_clyde,x,y); |
break; |
case 226: |
SpawnGhosts (en_pinky,x,y); |
break; |
case 227: |
SpawnGhosts (en_inky,x,y); |
break; |
#endif |
} |
} |
} |
} |
|
//========================================================================== |
|
/* |
================== |
= |
= SetupGameLevel |
= |
================== |
*/ |
|
void SetupGameLevel (void) |
{ |
int x,y; |
word *map; |
word tile; |
|
|
if (!loadedgame) |
{ |
gamestate.TimeCount |
= gamestate.secrettotal |
= gamestate.killtotal |
= gamestate.treasuretotal |
= gamestate.secretcount |
= gamestate.killcount |
= gamestate.treasurecount |
= pwallstate = pwallpos = facetimes = 0; |
LastAttacker = NULL; |
killerobj = NULL; |
} |
|
if (demoplayback || demorecord) |
US_InitRndT (false); |
else |
US_InitRndT (true); |
|
// |
// load the level |
// |
CA_CacheMap (gamestate.mapon+10*gamestate.episode); |
mapon-=gamestate.episode*10; |
|
#ifdef USE_FEATUREFLAGS |
// Temporary definition to make things clearer |
#define MXX MAPSIZE - 1 |
|
// Read feature flags data from map corners and overwrite corners with adjacent tiles |
ffDataTopLeft = MAPSPOT(0, 0, 0); MAPSPOT(0, 0, 0) = MAPSPOT(1, 0, 0); |
ffDataTopRight = MAPSPOT(MXX, 0, 0); MAPSPOT(MXX, 0, 0) = MAPSPOT(MXX, 1, 0); |
ffDataBottomRight = MAPSPOT(MXX, MXX, 0); MAPSPOT(MXX, MXX, 0) = MAPSPOT(MXX - 1, MXX, 0); |
ffDataBottomLeft = MAPSPOT(0, MXX, 0); MAPSPOT(0, MXX, 0) = MAPSPOT(0, MXX - 1, 0); |
|
#undef MXX |
#endif |
|
// |
// copy the wall data to a data segment array |
// |
memset (tilemap,0,sizeof(tilemap)); |
memset (actorat,0,sizeof(actorat)); |
map = mapsegs[0]; |
for (y=0;y<mapheight;y++) |
{ |
for (x=0;x<mapwidth;x++) |
{ |
tile = *map++; |
if (tile<AREATILE) |
{ |
// solid wall |
tilemap[x][y] = (byte) tile; |
actorat[x][y] = (objtype *)(uintptr_t) tile; |
} |
else |
{ |
// area floor |
tilemap[x][y] = 0; |
actorat[x][y] = 0; |
} |
} |
} |
|
// |
// spawn doors |
// |
InitActorList (); // start spawning things with a clean slate |
InitDoorList (); |
InitStaticList (); |
|
map = mapsegs[0]; |
for (y=0;y<mapheight;y++) |
{ |
for (x=0;x<mapwidth;x++) |
{ |
tile = *map++; |
if (tile >= 90 && tile <= 101) |
{ |
// door |
switch (tile) |
{ |
case 90: |
case 92: |
case 94: |
case 96: |
case 98: |
case 100: |
SpawnDoor (x,y,1,(tile-90)/2); |
break; |
case 91: |
case 93: |
case 95: |
case 97: |
case 99: |
case 101: |
SpawnDoor (x,y,0,(tile-91)/2); |
break; |
} |
} |
} |
} |
|
// |
// spawn actors |
// |
ScanInfoPlane (); |
|
|
// |
// take out the ambush markers |
// |
map = mapsegs[0]; |
for (y=0;y<mapheight;y++) |
{ |
for (x=0;x<mapwidth;x++) |
{ |
tile = *map++; |
if (tile == AMBUSHTILE) |
{ |
tilemap[x][y] = 0; |
if ( (unsigned)(uintptr_t)actorat[x][y] == AMBUSHTILE) |
actorat[x][y] = NULL; |
|
if (*map >= AREATILE) |
tile = *map; |
if (*(map-1-mapwidth) >= AREATILE) |
tile = *(map-1-mapwidth); |
if (*(map-1+mapwidth) >= AREATILE) |
tile = *(map-1+mapwidth); |
if ( *(map-2) >= AREATILE) |
tile = *(map-2); |
|
*(map-1) = tile; |
} |
} |
} |
|
|
// |
// have the caching manager load and purge stuff to make sure all marks |
// are in memory |
// |
CA_LoadAllSounds (); |
} |
|
|
//========================================================================== |
|
|
/* |
=================== |
= |
= DrawPlayBorderSides |
= |
= To fix window overwrites |
= |
=================== |
*/ |
void DrawPlayBorderSides(void) |
{ |
if(viewsize == 21) return; |
|
const int sw = screenWidth; |
const int sh = screenHeight; |
const int vw = viewwidth; |
const int vh = viewheight; |
const int px = scaleFactor; // size of one "pixel" |
|
const int h = sh - px * STATUSLINES; |
const int xl = sw / 2 - vw / 2; |
const int yl = (h - vh) / 2; |
|
if(xl != 0) |
{ |
VWB_BarScaledCoord(0, 0, xl - px, h, bordercol); // left side |
VWB_BarScaledCoord(xl + vw + px, 0, xl - px * 2, h, bordercol); // right side |
} |
|
if(yl != 0) |
{ |
VWB_BarScaledCoord(0, 0, sw, yl - px, bordercol); // upper side |
VWB_BarScaledCoord(0, yl + vh + px, sw, yl - px, bordercol); // lower side |
} |
|
if(xl != 0) |
{ |
// Paint game view border lines |
VWB_BarScaledCoord(xl - px, yl - px, vw + px, px, 0); // upper border |
VWB_BarScaledCoord(xl, yl + vh, vw + px, px, bordercol - 2); // lower border |
VWB_BarScaledCoord(xl - px, yl - px, px, vh + px, 0); // left border |
VWB_BarScaledCoord(xl + vw, yl - px, px, vh + px * 2, bordercol - 2); // right border |
VWB_BarScaledCoord(xl - px, yl + vh, px, px, bordercol - 3); // lower left highlight |
} |
else |
{ |
// Just paint a lower border line |
VWB_BarScaledCoord(0, yl+vh, vw, px, bordercol-2); // lower border |
} |
} |
|
|
/* |
=================== |
= |
= DrawStatusBorder |
= |
=================== |
*/ |
|
void DrawStatusBorder (byte color) |
{ |
int statusborderw = (screenWidth-scaleFactor*320)/2; |
|
VWB_BarScaledCoord (0,0,screenWidth,screenHeight-scaleFactor*(STATUSLINES-3),color); |
VWB_BarScaledCoord (0,screenHeight-scaleFactor*(STATUSLINES-3), |
statusborderw+scaleFactor*8,scaleFactor*(STATUSLINES-4),color); |
VWB_BarScaledCoord (0,screenHeight-scaleFactor*2,screenWidth,scaleFactor*2,color); |
VWB_BarScaledCoord (screenWidth-statusborderw-scaleFactor*8, screenHeight-scaleFactor*(STATUSLINES-3), |
statusborderw+scaleFactor*8,scaleFactor*(STATUSLINES-4),color); |
|
VWB_BarScaledCoord (statusborderw+scaleFactor*9, screenHeight-scaleFactor*3, |
scaleFactor*97, scaleFactor*1, color-1); |
VWB_BarScaledCoord (statusborderw+scaleFactor*106, screenHeight-scaleFactor*3, |
scaleFactor*161, scaleFactor*1, color-2); |
VWB_BarScaledCoord (statusborderw+scaleFactor*267, screenHeight-scaleFactor*3, |
scaleFactor*44, scaleFactor*1, color-3); |
VWB_BarScaledCoord (screenWidth-statusborderw-scaleFactor*9, screenHeight-scaleFactor*(STATUSLINES-4), |
scaleFactor*1, scaleFactor*20, color-2); |
VWB_BarScaledCoord (screenWidth-statusborderw-scaleFactor*9, screenHeight-scaleFactor*(STATUSLINES/2-4), |
scaleFactor*1, scaleFactor*14, color-3); |
} |
|
|
/* |
=================== |
= |
= DrawPlayBorder |
= |
=================== |
*/ |
|
void DrawPlayBorder (void) |
{ |
const int px = scaleFactor; // size of one "pixel" |
|
if (bordercol != VIEWCOLOR) |
DrawStatusBorder(bordercol); |
else |
{ |
const int statusborderw = (screenWidth-px*320)/2; |
VWB_BarScaledCoord (0, screenHeight-px*STATUSLINES, |
statusborderw+px*8, px*STATUSLINES, bordercol); |
VWB_BarScaledCoord (screenWidth-statusborderw-px*8, screenHeight-px*STATUSLINES, |
statusborderw+px*8, px*STATUSLINES, bordercol); |
} |
|
if((unsigned) viewheight == screenHeight) return; |
|
VWB_BarScaledCoord (0,0,screenWidth,screenHeight-px*STATUSLINES,bordercol); |
|
const int xl = screenWidth/2-viewwidth/2; |
const int yl = (screenHeight-px*STATUSLINES-viewheight)/2; |
VWB_BarScaledCoord (xl,yl,viewwidth,viewheight,0); |
|
if(xl != 0) |
{ |
// Paint game view border lines |
VWB_BarScaledCoord(xl-px, yl-px, viewwidth+px, px, 0); // upper border |
VWB_BarScaledCoord(xl, yl+viewheight, viewwidth+px, px, bordercol-2); // lower border |
VWB_BarScaledCoord(xl-px, yl-px, px, viewheight+px, 0); // left border |
VWB_BarScaledCoord(xl+viewwidth, yl-px, px, viewheight+2*px, bordercol-2); // right border |
VWB_BarScaledCoord(xl-px, yl+viewheight, px, px, bordercol-3); // lower left highlight |
} |
else |
{ |
// Just paint a lower border line |
VWB_BarScaledCoord(0, yl+viewheight, viewwidth, px, bordercol-2); // lower border |
} |
} |
|
|
/* |
=================== |
= |
= DrawPlayScreen |
= |
=================== |
*/ |
|
void DrawPlayScreen (void) |
{ |
VWB_DrawPicScaledCoord ((screenWidth-scaleFactor*320)/2,screenHeight-scaleFactor*STATUSLINES,STATUSBARPIC); |
DrawPlayBorder (); |
|
DrawFace (); |
DrawHealth (); |
DrawLives (); |
DrawLevel (); |
DrawAmmo (); |
DrawKeys (); |
DrawWeapon (); |
DrawScore (); |
} |
|
// Uses LatchDrawPic instead of StatusDrawPic |
void LatchNumberHERE (int x, int y, unsigned width, int32_t number) |
{ |
unsigned length,c; |
char str[20]; |
|
ltoa (number,str,10); |
|
length = (unsigned) strlen (str); |
|
while (length<width) |
{ |
LatchDrawPic (x,y,N_BLANKPIC); |
x++; |
width--; |
} |
|
c = length <= width ? 0 : length-width; |
|
while (c<length) |
{ |
LatchDrawPic (x,y,str[c]-'0'+ N_0PIC); |
x++; |
c++; |
} |
} |
|
void ShowActStatus() |
{ |
// Draw status bar without borders |
byte *source = grsegs[STATUSBARPIC]; |
int picnum = STATUSBARPIC - STARTPICS; |
int width = pictable[picnum].width; |
int height = pictable[picnum].height; |
int destx = (screenWidth-scaleFactor*320)/2 + 9 * scaleFactor; |
int desty = screenHeight - (height - 4) * scaleFactor; |
VL_MemToScreenScaledCoord(source, width, height, 9, 4, destx, desty, width - 18, height - 7); |
|
ingame = false; |
DrawFace (); |
DrawHealth (); |
DrawLives (); |
DrawLevel (); |
DrawAmmo (); |
DrawKeys (); |
DrawWeapon (); |
DrawScore (); |
ingame = true; |
} |
|
|
//========================================================================== |
|
/* |
================== |
= |
= StartDemoRecord |
= |
================== |
*/ |
|
char demoname[13] = "DEMO?."; |
|
#ifndef REMDEBUG |
#define MAXDEMOSIZE 8192 |
|
void StartDemoRecord (int levelnumber) |
{ |
demobuffer=malloc(MAXDEMOSIZE); |
CHECKMALLOCRESULT(demobuffer); |
demoptr = (int8_t *) demobuffer; |
lastdemoptr = demoptr+MAXDEMOSIZE; |
|
*demoptr = levelnumber; |
demoptr += 4; // leave space for length |
demorecord = true; |
} |
|
|
/* |
================== |
= |
= FinishDemoRecord |
= |
================== |
*/ |
|
void FinishDemoRecord (void) |
{ |
int32_t length,level; |
|
demorecord = false; |
|
length = (int32_t) (demoptr - (int8_t *)demobuffer); |
|
demoptr = ((int8_t *)demobuffer)+1; |
demoptr[0] = (int8_t) length; |
demoptr[1] = (int8_t) (length >> 8); |
demoptr[2] = 0; |
|
VW_FadeIn(); |
CenterWindow(24,3); |
PrintY+=6; |
fontnumber=0; |
SETFONTCOLOR(0,15); |
US_Print(" Demo number (0-9): "); |
VW_UpdateScreen(); |
|
if (US_LineInput (px,py,str,NULL,true,1,0)) |
{ |
level = atoi (str); |
if (level>=0 && level<=9) |
{ |
demoname[4] = (char)('0'+level); |
CA_WriteFile (demoname,demobuffer,length); |
} |
} |
|
free(demobuffer); |
} |
|
//========================================================================== |
|
/* |
================== |
= |
= RecordDemo |
= |
= Fades the screen out, then starts a demo. Exits with the screen faded |
= |
================== |
*/ |
|
void RecordDemo (void) |
{ |
int level,esc,maps; |
|
CenterWindow(26,3); |
PrintY+=6; |
CA_CacheGrChunk(STARTFONT); |
fontnumber=0; |
SETFONTCOLOR(0,15); |
#ifndef SPEAR |
#ifdef UPLOAD |
US_Print(" Demo which level(1-10): "); maps = 10; |
#else |
US_Print(" Demo which level(1-60): "); maps = 60; |
#endif |
#else |
US_Print(" Demo which level(1-21): "); maps = 21; |
#endif |
VW_UpdateScreen(); |
VW_FadeIn (); |
esc = !US_LineInput (px,py,str,NULL,true,2,0); |
if (esc) |
return; |
|
level = atoi (str); |
level--; |
|
if (level >= maps || level < 0) |
return; |
|
VW_FadeOut (); |
|
#ifndef SPEAR |
NewGame (gd_hard,level/10); |
gamestate.mapon = level%10; |
#else |
NewGame (gd_hard,0); |
gamestate.mapon = level; |
#endif |
|
StartDemoRecord (level); |
|
DrawPlayScreen (); |
VW_FadeIn (); |
|
startgame = false; |
demorecord = true; |
|
SetupGameLevel (); |
StartMusic (); |
|
if(usedoublebuffering) VH_UpdateScreen(); |
fizzlein = true; |
|
PlayLoop (); |
|
demoplayback = false; |
|
StopMusic (); |
VW_FadeOut (); |
ClearMemory (); |
|
FinishDemoRecord (); |
} |
#else |
void FinishDemoRecord (void) {return;} |
void RecordDemo (void) {return;} |
#endif |
|
|
|
//========================================================================== |
|
/* |
================== |
= |
= PlayDemo |
= |
= Fades the screen out, then starts a demo. Exits with the screen unfaded |
= |
================== |
*/ |
|
void PlayDemo (int demonumber) |
{ |
int length; |
#ifdef DEMOSEXTERN |
// debug: load chunk |
#ifndef SPEARDEMO |
int dems[4]={T_DEMO0,T_DEMO1,T_DEMO2,T_DEMO3}; |
#else |
int dems[1]={T_DEMO0}; |
#endif |
|
CA_CacheGrChunk(dems[demonumber]); |
demoptr = (int8_t *) grsegs[dems[demonumber]]; |
#else |
demoname[4] = '0'+demonumber; |
CA_LoadFile (demoname,&demobuffer); |
demoptr = (int8_t *)demobuffer; |
#endif |
|
NewGame (1,0); |
gamestate.mapon = *demoptr++; |
gamestate.difficulty = gd_hard; |
length = READWORD(*(uint8_t **)&demoptr); |
// TODO: Seems like the original demo format supports 16 MB demos |
// But T_DEM00 and T_DEM01 of Wolf have a 0xd8 as third length size... |
demoptr++; |
lastdemoptr = demoptr-4+length; |
|
VW_FadeOut (); |
|
SETFONTCOLOR(0,15); |
DrawPlayScreen (); |
|
startgame = false; |
demoplayback = true; |
|
SetupGameLevel (); |
StartMusic (); |
|
PlayLoop (); |
|
#ifdef DEMOSEXTERN |
UNCACHEGRCHUNK(dems[demonumber]); |
#else |
MM_FreePtr (&demobuffer); |
#endif |
|
demoplayback = false; |
|
StopMusic (); |
ClearMemory (); |
} |
|
//========================================================================== |
|
/* |
================== |
= |
= Died |
= |
================== |
*/ |
|
#define DEATHROTATE 2 |
|
void Died (void) |
{ |
float fangle; |
int32_t dx,dy; |
int iangle,curangle,clockwise,counter,change; |
|
if (screenfaded) |
{ |
ThreeDRefresh (); |
VW_FadeIn (); |
} |
|
gamestate.weapon = (weapontype) -1; // take away weapon |
SD_PlaySound (PLAYERDEATHSND); |
|
// |
// swing around to face attacker |
// |
if(killerobj) |
{ |
dx = killerobj->x - player->x; |
dy = player->y - killerobj->y; |
|
fangle = (float) atan2((float) dy, (float) dx); // returns -pi to pi |
if (fangle<0) |
fangle = (float) (M_PI*2+fangle); |
|
iangle = (int) (fangle/(M_PI*2)*ANGLES); |
} |
else |
{ |
iangle = player->angle + ANGLES / 2; |
if(iangle >= ANGLES) iangle -= ANGLES; |
} |
|
if (player->angle > iangle) |
{ |
counter = player->angle - iangle; |
clockwise = ANGLES-player->angle + iangle; |
} |
else |
{ |
clockwise = iangle - player->angle; |
counter = player->angle + ANGLES-iangle; |
} |
|
curangle = player->angle; |
|
if (clockwise<counter) |
{ |
// |
// rotate clockwise |
// |
if (curangle>iangle) |
curangle -= ANGLES; |
do |
{ |
change = tics*DEATHROTATE; |
if (curangle + change > iangle) |
change = iangle-curangle; |
|
curangle += change; |
player->angle += change; |
if (player->angle >= ANGLES) |
player->angle -= ANGLES; |
|
ThreeDRefresh (); |
CalcTics (); |
} while (curangle != iangle); |
} |
else |
{ |
// |
// rotate counterclockwise |
// |
if (curangle<iangle) |
curangle += ANGLES; |
do |
{ |
change = -(int)tics*DEATHROTATE; |
if (curangle + change < iangle) |
change = iangle-curangle; |
|
curangle += change; |
player->angle += change; |
if (player->angle < 0) |
player->angle += ANGLES; |
|
ThreeDRefresh (); |
CalcTics (); |
} while (curangle != iangle); |
} |
|
// |
// fade to red |
// |
FinishPaletteShifts (); |
|
if(usedoublebuffering) VH_UpdateScreen(); |
|
VL_BarScaledCoord (viewscreenx,viewscreeny,viewwidth,viewheight,4); |
|
IN_ClearKeysDown (); |
|
FizzleFade(screenBuffer,viewscreenx,viewscreeny,viewwidth,viewheight,70,false); |
|
IN_UserInput(100); |
SD_WaitSoundDone (); |
ClearMemory(); |
|
gamestate.lives--; |
|
if (gamestate.lives > -1) |
{ |
gamestate.health = 100; |
gamestate.weapon = gamestate.bestweapon |
= gamestate.chosenweapon = wp_pistol; |
gamestate.ammo = STARTAMMO; |
gamestate.keys = 0; |
pwallstate = pwallpos = 0; |
gamestate.attackframe = gamestate.attackcount = |
gamestate.weaponframe = 0; |
|
if(viewsize != 21) |
{ |
DrawKeys (); |
DrawWeapon (); |
DrawAmmo (); |
DrawHealth (); |
DrawFace (); |
DrawLives (); |
} |
} |
} |
|
//========================================================================== |
|
/* |
=================== |
= |
= GameLoop |
= |
=================== |
*/ |
|
void GameLoop (void) |
{ |
boolean died; |
#ifdef MYPROFILE |
clock_t start,end; |
#endif |
|
restartgame: |
ClearMemory (); |
SETFONTCOLOR(0,15); |
VW_FadeOut(); |
DrawPlayScreen (); |
died = false; |
do |
{ |
if (!loadedgame) |
gamestate.score = gamestate.oldscore; |
if(!died || viewsize != 21) DrawScore(); |
|
startgame = false; |
if (!loadedgame) |
SetupGameLevel (); |
|
#ifdef SPEAR |
if (gamestate.mapon == 20) // give them the key allways |
{ |
gamestate.keys |= 1; |
DrawKeys (); |
} |
#endif |
|
ingame = true; |
if(loadedgame) |
{ |
ContinueMusic(lastgamemusicoffset); |
loadedgame = false; |
} |
else StartMusic (); |
|
if (!died) |
PreloadGraphics (); // TODO: Let this do something useful! |
else |
{ |
died = false; |
fizzlein = true; |
} |
|
DrawLevel (); |
|
#ifdef SPEAR |
startplayloop: |
#endif |
PlayLoop (); |
|
#ifdef SPEAR |
if (spearflag) |
{ |
SD_StopSound(); |
SD_PlaySound(GETSPEARSND); |
if (DigiMode != sds_Off) |
{ |
Delay(150); |
} |
else |
SD_WaitSoundDone(); |
|
ClearMemory (); |
gamestate.oldscore = gamestate.score; |
gamestate.mapon = 20; |
SetupGameLevel (); |
StartMusic (); |
player->x = spearx; |
player->y = speary; |
player->angle = (short)spearangle; |
spearflag = false; |
Thrust (0,0); |
goto startplayloop; |
} |
#endif |
|
StopMusic (); |
ingame = false; |
|
if (demorecord && playstate != ex_warped) |
FinishDemoRecord (); |
|
if (startgame || loadedgame) |
goto restartgame; |
|
switch (playstate) |
{ |
case ex_completed: |
case ex_secretlevel: |
if(viewsize == 21) DrawPlayScreen(); |
gamestate.keys = 0; |
DrawKeys (); |
VW_FadeOut (); |
|
ClearMemory (); |
|
LevelCompleted (); // do the intermission |
if(viewsize == 21) DrawPlayScreen(); |
|
#ifdef SPEARDEMO |
if (gamestate.mapon == 1) |
{ |
died = true; // don't "get psyched!" |
|
VW_FadeOut (); |
|
ClearMemory (); |
|
CheckHighScore (gamestate.score,gamestate.mapon+1); |
#ifndef JAPAN |
strcpy(MainMenu[viewscores].string,STR_VS); |
#endif |
MainMenu[viewscores].routine = CP_ViewScores; |
return; |
} |
#endif |
|
#ifdef JAPDEMO |
if (gamestate.mapon == 3) |
{ |
died = true; // don't "get psyched!" |
|
VW_FadeOut (); |
|
ClearMemory (); |
|
CheckHighScore (gamestate.score,gamestate.mapon+1); |
#ifndef JAPAN |
strcpy(MainMenu[viewscores].string,STR_VS); |
#endif |
MainMenu[viewscores].routine = CP_ViewScores; |
return; |
} |
#endif |
|
gamestate.oldscore = gamestate.score; |
|
#ifndef SPEAR |
// |
// COMING BACK FROM SECRET LEVEL |
// |
if (gamestate.mapon == 9) |
gamestate.mapon = ElevatorBackTo[gamestate.episode]; // back from secret |
else |
// |
// GOING TO SECRET LEVEL |
// |
if (playstate == ex_secretlevel) |
gamestate.mapon = 9; |
#else |
|
#define FROMSECRET1 3 |
#define FROMSECRET2 11 |
|
// |
// GOING TO SECRET LEVEL |
// |
if (playstate == ex_secretlevel) |
switch(gamestate.mapon) |
{ |
case FROMSECRET1: gamestate.mapon = 18; break; |
case FROMSECRET2: gamestate.mapon = 19; break; |
} |
else |
// |
// COMING BACK FROM SECRET LEVEL |
// |
if (gamestate.mapon == 18 || gamestate.mapon == 19) |
switch(gamestate.mapon) |
{ |
case 18: gamestate.mapon = FROMSECRET1+1; break; |
case 19: gamestate.mapon = FROMSECRET2+1; break; |
} |
#endif |
else |
// |
// GOING TO NEXT LEVEL |
// |
gamestate.mapon++; |
break; |
|
case ex_died: |
Died (); |
died = true; // don't "get psyched!" |
|
if (gamestate.lives > -1) |
break; // more lives left |
|
VW_FadeOut (); |
if(screenHeight % 200 != 0) |
VL_ClearScreen(0); |
|
#ifdef _arch_dreamcast |
DC_StatusClearLCD(); |
#endif |
|
ClearMemory (); |
|
CheckHighScore (gamestate.score,gamestate.mapon+1); |
#ifndef JAPAN |
strcpy(MainMenu[viewscores].string,STR_VS); |
#endif |
MainMenu[viewscores].routine = CP_ViewScores; |
return; |
|
case ex_victorious: |
if(viewsize == 21) DrawPlayScreen(); |
#ifndef SPEAR |
VW_FadeOut (); |
#else |
VL_FadeOut (0,255,0,17,17,300); |
#endif |
ClearMemory (); |
|
Victory (); |
|
ClearMemory (); |
|
CheckHighScore (gamestate.score,gamestate.mapon+1); |
#ifndef JAPAN |
strcpy(MainMenu[viewscores].string,STR_VS); |
#endif |
MainMenu[viewscores].routine = CP_ViewScores; |
return; |
|
default: |
if(viewsize == 21) DrawPlayScreen(); |
ClearMemory (); |
break; |
} |
} while (1); |
} |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |