0,0 → 1,1500 |
// WL_AGENT.C |
|
#include "wl_def.h" |
#pragma hdrstop |
|
/* |
============================================================================= |
|
LOCAL CONSTANTS |
|
============================================================================= |
*/ |
|
#define MAXMOUSETURN 10 |
|
|
#define MOVESCALE 150l |
#define BACKMOVESCALE 100l |
#define ANGLESCALE 20 |
|
/* |
============================================================================= |
|
GLOBAL VARIABLES |
|
============================================================================= |
*/ |
|
|
|
// |
// player state info |
// |
int32_t thrustspeed; |
|
word plux,pluy; // player coordinates scaled to unsigned |
|
short anglefrac; |
|
objtype *LastAttacker; |
|
/* |
============================================================================= |
|
LOCAL VARIABLES |
|
============================================================================= |
*/ |
|
|
void T_Player (objtype *ob); |
void T_Attack (objtype *ob); |
|
statetype s_player = {false,0,0,(statefunc) T_Player,NULL,NULL}; |
statetype s_attack = {false,0,0,(statefunc) T_Attack,NULL,NULL}; |
|
struct atkinf |
{ |
int8_t tics,attack,frame; // attack is 1 for gun, 2 for knife |
} attackinfo[4][14] = |
{ |
{ {6,0,1},{6,2,2},{6,0,3},{6,-1,4} }, |
{ {6,0,1},{6,1,2},{6,0,3},{6,-1,4} }, |
{ {6,0,1},{6,1,2},{6,3,3},{6,-1,4} }, |
{ {6,0,1},{6,1,2},{6,4,3},{6,-1,4} }, |
}; |
|
//=========================================================================== |
|
//---------- |
|
void Attack (void); |
void Use (void); |
void Search (objtype *ob); |
void SelectWeapon (void); |
void SelectItem (void); |
|
//---------- |
|
boolean TryMove (objtype *ob); |
void T_Player (objtype *ob); |
|
void ClipMove (objtype *ob, int32_t xmove, int32_t ymove); |
|
/* |
============================================================================= |
|
CONTROL STUFF |
|
============================================================================= |
*/ |
|
/* |
====================== |
= |
= CheckWeaponChange |
= |
= Keys 1-4 change weapons |
= |
====================== |
*/ |
|
void CheckWeaponChange (void) |
{ |
int newWeapon = -1; |
|
if (!gamestate.ammo) // must use knife with no ammo |
return; |
|
#ifdef _arch_dreamcast |
int joyx, joyy; |
IN_GetJoyFineDelta (&joyx, &joyy); |
if(joyx < -64) |
buttonstate[bt_prevweapon] = true; |
else if(joyx > 64) |
buttonstate[bt_nextweapon] = true; |
#endif |
|
if(buttonstate[bt_nextweapon] && !buttonheld[bt_nextweapon]) |
{ |
newWeapon = gamestate.weapon + 1; |
if(newWeapon > gamestate.bestweapon) newWeapon = 0; |
} |
else if(buttonstate[bt_prevweapon] && !buttonheld[bt_prevweapon]) |
{ |
newWeapon = gamestate.weapon - 1; |
if(newWeapon < 0) newWeapon = gamestate.bestweapon; |
} |
else |
{ |
for(int i = wp_knife; i <= gamestate.bestweapon; i++) |
{ |
if (buttonstate[bt_readyknife + i - wp_knife]) |
{ |
newWeapon = i; |
break; |
} |
} |
} |
|
if(newWeapon != -1) |
{ |
gamestate.weapon = gamestate.chosenweapon = (weapontype) newWeapon; |
DrawWeapon(); |
} |
} |
|
|
/* |
======================= |
= |
= ControlMovement |
= |
= Takes controlx,controly, and buttonstate[bt_strafe] |
= |
= Changes the player's angle and position |
= |
= There is an angle hack because when going 70 fps, the roundoff becomes |
= significant |
= |
======================= |
*/ |
|
void ControlMovement (objtype *ob) |
{ |
int32_t oldx,oldy; |
int angle; |
int angleunits; |
|
thrustspeed = 0; |
|
oldx = player->x; |
oldy = player->y; |
|
if(buttonstate[bt_strafeleft]) |
{ |
angle = ob->angle + ANGLES/4; |
if(angle >= ANGLES) |
angle -= ANGLES; |
if(buttonstate[bt_run]) |
Thrust(angle, RUNMOVE * MOVESCALE * tics); |
else |
Thrust(angle, BASEMOVE * MOVESCALE * tics); |
} |
|
if(buttonstate[bt_straferight]) |
{ |
angle = ob->angle - ANGLES/4; |
if(angle < 0) |
angle += ANGLES; |
if(buttonstate[bt_run]) |
Thrust(angle, RUNMOVE * MOVESCALE * tics ); |
else |
Thrust(angle, BASEMOVE * MOVESCALE * tics); |
} |
|
// |
// side to side move |
// |
if (buttonstate[bt_strafe]) |
{ |
// |
// strafing |
// |
// |
if (controlx > 0) |
{ |
angle = ob->angle - ANGLES/4; |
if (angle < 0) |
angle += ANGLES; |
Thrust (angle,controlx*MOVESCALE); // move to left |
} |
else if (controlx < 0) |
{ |
angle = ob->angle + ANGLES/4; |
if (angle >= ANGLES) |
angle -= ANGLES; |
Thrust (angle,-controlx*MOVESCALE); // move to right |
} |
} |
else |
{ |
// |
// not strafing |
// |
anglefrac += controlx; |
angleunits = anglefrac/ANGLESCALE; |
anglefrac -= angleunits*ANGLESCALE; |
ob->angle -= angleunits; |
|
if (ob->angle >= ANGLES) |
ob->angle -= ANGLES; |
if (ob->angle < 0) |
ob->angle += ANGLES; |
|
} |
|
// |
// forward/backwards move |
// |
if (controly < 0) |
{ |
Thrust (ob->angle,-controly*MOVESCALE); // move forwards |
} |
else if (controly > 0) |
{ |
angle = ob->angle + ANGLES/2; |
if (angle >= ANGLES) |
angle -= ANGLES; |
Thrust (angle,controly*BACKMOVESCALE); // move backwards |
} |
|
if (gamestate.victoryflag) // watching the BJ actor |
return; |
} |
|
/* |
============================================================================= |
|
STATUS WINDOW STUFF |
|
============================================================================= |
*/ |
|
|
/* |
================== |
= |
= StatusDrawPic |
= |
================== |
*/ |
|
void StatusDrawPic (unsigned x, unsigned y, unsigned picnum) |
{ |
LatchDrawPicScaledCoord ((screenWidth-scaleFactor*320)/16 + scaleFactor*x, |
screenHeight-scaleFactor*(STATUSLINES-y),picnum); |
} |
|
void StatusDrawFace(unsigned picnum) |
{ |
StatusDrawPic(17, 4, picnum); |
|
#ifdef _arch_dreamcast |
DC_StatusDrawLCD(picnum); |
#endif |
} |
|
|
/* |
================== |
= |
= DrawFace |
= |
================== |
*/ |
|
void DrawFace (void) |
{ |
if(viewsize == 21 && ingame) return; |
if (SD_SoundPlaying() == GETGATLINGSND) |
StatusDrawFace(GOTGATLINGPIC); |
else if (gamestate.health) |
{ |
#ifdef SPEAR |
if (godmode) |
StatusDrawFace(GODMODEFACE1PIC+gamestate.faceframe); |
else |
#endif |
StatusDrawFace(FACE1APIC+3*((100-gamestate.health)/16)+gamestate.faceframe); |
} |
else |
{ |
#ifndef SPEAR |
if (LastAttacker && LastAttacker->obclass == needleobj) |
StatusDrawFace(MUTANTBJPIC); |
else |
#endif |
StatusDrawFace(FACE8APIC); |
} |
} |
|
/* |
=============== |
= |
= UpdateFace |
= |
= Calls draw face if time to change |
= |
=============== |
*/ |
|
int facecount = 0; |
int facetimes = 0; |
|
void UpdateFace (void) |
{ |
// don't make demo depend on sound playback |
if(demoplayback || demorecord) |
{ |
if(facetimes > 0) |
{ |
facetimes--; |
return; |
} |
} |
else if(SD_SoundPlaying() == GETGATLINGSND) |
return; |
|
facecount += tics; |
if (facecount > US_RndT()) |
{ |
gamestate.faceframe = (US_RndT()>>6); |
if (gamestate.faceframe==3) |
gamestate.faceframe = 1; |
|
facecount = 0; |
DrawFace (); |
} |
} |
|
|
|
/* |
=============== |
= |
= LatchNumber |
= |
= right justifies and pads with blanks |
= |
=============== |
*/ |
|
static void LatchNumber (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) |
{ |
StatusDrawPic (x,y,N_BLANKPIC); |
x++; |
width--; |
} |
|
c = length <= width ? 0 : length-width; |
|
while (c<length) |
{ |
StatusDrawPic (x,y,str[c]-'0'+ N_0PIC); |
x++; |
c++; |
} |
} |
|
|
/* |
=============== |
= |
= DrawHealth |
= |
=============== |
*/ |
|
void DrawHealth (void) |
{ |
if(viewsize == 21 && ingame) return; |
LatchNumber (21,16,3,gamestate.health); |
} |
|
|
/* |
=============== |
= |
= TakeDamage |
= |
=============== |
*/ |
|
void TakeDamage (int points,objtype *attacker) |
{ |
LastAttacker = attacker; |
|
if (gamestate.victoryflag) |
return; |
if (gamestate.difficulty==gd_baby) |
points>>=2; |
|
if (!godmode) |
gamestate.health -= points; |
|
if (gamestate.health<=0) |
{ |
gamestate.health = 0; |
playstate = ex_died; |
killerobj = attacker; |
} |
|
if (godmode != 2) |
StartDamageFlash (points); |
|
DrawHealth (); |
DrawFace (); |
|
// |
// MAKE BJ'S EYES BUG IF MAJOR DAMAGE! |
// |
#ifdef SPEAR |
if (points > 30 && gamestate.health!=0 && !godmode && viewsize != 21) |
{ |
StatusDrawFace(BJOUCHPIC); |
facecount = 0; |
} |
#endif |
} |
|
/* |
=============== |
= |
= HealSelf |
= |
=============== |
*/ |
|
void HealSelf (int points) |
{ |
gamestate.health += points; |
if (gamestate.health>100) |
gamestate.health = 100; |
|
DrawHealth (); |
DrawFace (); |
} |
|
|
//=========================================================================== |
|
|
/* |
=============== |
= |
= DrawLevel |
= |
=============== |
*/ |
|
void DrawLevel (void) |
{ |
if(viewsize == 21 && ingame) return; |
#ifdef SPEAR |
if (gamestate.mapon == 20) |
LatchNumber (2,16,2,18); |
else |
#endif |
LatchNumber (2,16,2,gamestate.mapon+1); |
} |
|
//=========================================================================== |
|
|
/* |
=============== |
= |
= DrawLives |
= |
=============== |
*/ |
|
void DrawLives (void) |
{ |
if(viewsize == 21 && ingame) return; |
LatchNumber (14,16,1,gamestate.lives); |
} |
|
|
/* |
=============== |
= |
= GiveExtraMan |
= |
=============== |
*/ |
|
void GiveExtraMan (void) |
{ |
if (gamestate.lives<9) |
gamestate.lives++; |
DrawLives (); |
SD_PlaySound (BONUS1UPSND); |
} |
|
//=========================================================================== |
|
/* |
=============== |
= |
= DrawScore |
= |
=============== |
*/ |
|
void DrawScore (void) |
{ |
if(viewsize == 21 && ingame) return; |
LatchNumber (6,16,6,gamestate.score); |
} |
|
/* |
=============== |
= |
= GivePoints |
= |
=============== |
*/ |
|
void GivePoints (int32_t points) |
{ |
gamestate.score += points; |
while (gamestate.score >= gamestate.nextextra) |
{ |
gamestate.nextextra += EXTRAPOINTS; |
GiveExtraMan (); |
} |
DrawScore (); |
} |
|
//=========================================================================== |
|
/* |
================== |
= |
= DrawWeapon |
= |
================== |
*/ |
|
void DrawWeapon (void) |
{ |
if(viewsize == 21 && ingame) return; |
StatusDrawPic (32,8,KNIFEPIC+gamestate.weapon); |
} |
|
|
/* |
================== |
= |
= DrawKeys |
= |
================== |
*/ |
|
void DrawKeys (void) |
{ |
if(viewsize == 21 && ingame) return; |
if (gamestate.keys & 1) |
StatusDrawPic (30,4,GOLDKEYPIC); |
else |
StatusDrawPic (30,4,NOKEYPIC); |
|
if (gamestate.keys & 2) |
StatusDrawPic (30,20,SILVERKEYPIC); |
else |
StatusDrawPic (30,20,NOKEYPIC); |
} |
|
/* |
================== |
= |
= GiveWeapon |
= |
================== |
*/ |
|
void GiveWeapon (int weapon) |
{ |
GiveAmmo (6); |
|
if (gamestate.bestweapon<weapon) |
gamestate.bestweapon = gamestate.weapon |
= gamestate.chosenweapon = (weapontype) weapon; |
|
DrawWeapon (); |
} |
|
//=========================================================================== |
|
/* |
=============== |
= |
= DrawAmmo |
= |
=============== |
*/ |
|
void DrawAmmo (void) |
{ |
if(viewsize == 21 && ingame) return; |
LatchNumber (27,16,2,gamestate.ammo); |
} |
|
/* |
=============== |
= |
= GiveAmmo |
= |
=============== |
*/ |
|
void GiveAmmo (int ammo) |
{ |
if (!gamestate.ammo) // knife was out |
{ |
if (!gamestate.attackframe) |
{ |
gamestate.weapon = gamestate.chosenweapon; |
DrawWeapon (); |
} |
} |
gamestate.ammo += ammo; |
if (gamestate.ammo > 99) |
gamestate.ammo = 99; |
DrawAmmo (); |
} |
|
//=========================================================================== |
|
/* |
================== |
= |
= GiveKey |
= |
================== |
*/ |
|
void GiveKey (int key) |
{ |
gamestate.keys |= (1<<key); |
DrawKeys (); |
} |
|
|
|
/* |
============================================================================= |
|
MOVEMENT |
|
============================================================================= |
*/ |
|
|
/* |
=================== |
= |
= GetBonus |
= |
=================== |
*/ |
void GetBonus (statobj_t *check) |
{ |
switch (check->itemnumber) |
{ |
case bo_firstaid: |
if (gamestate.health == 100) |
return; |
|
SD_PlaySound (HEALTH2SND); |
HealSelf (25); |
break; |
|
case bo_key1: |
case bo_key2: |
case bo_key3: |
case bo_key4: |
GiveKey (check->itemnumber - bo_key1); |
SD_PlaySound (GETKEYSND); |
break; |
|
case bo_cross: |
SD_PlaySound (BONUS1SND); |
GivePoints (100); |
gamestate.treasurecount++; |
break; |
case bo_chalice: |
SD_PlaySound (BONUS2SND); |
GivePoints (500); |
gamestate.treasurecount++; |
break; |
case bo_bible: |
SD_PlaySound (BONUS3SND); |
GivePoints (1000); |
gamestate.treasurecount++; |
break; |
case bo_crown: |
SD_PlaySound (BONUS4SND); |
GivePoints (5000); |
gamestate.treasurecount++; |
break; |
|
case bo_clip: |
if (gamestate.ammo == 99) |
return; |
|
SD_PlaySound (GETAMMOSND); |
GiveAmmo (8); |
break; |
case bo_clip2: |
if (gamestate.ammo == 99) |
return; |
|
SD_PlaySound (GETAMMOSND); |
GiveAmmo (4); |
break; |
|
#ifdef SPEAR |
case bo_25clip: |
if (gamestate.ammo == 99) |
return; |
|
SD_PlaySound (GETAMMOBOXSND); |
GiveAmmo (25); |
break; |
#endif |
|
case bo_machinegun: |
SD_PlaySound (GETMACHINESND); |
GiveWeapon (wp_machinegun); |
break; |
case bo_chaingun: |
SD_PlaySound (GETGATLINGSND); |
facetimes = 38; |
GiveWeapon (wp_chaingun); |
|
if(viewsize != 21) |
StatusDrawFace (GOTGATLINGPIC); |
facecount = 0; |
break; |
|
case bo_fullheal: |
SD_PlaySound (BONUS1UPSND); |
HealSelf (99); |
GiveAmmo (25); |
GiveExtraMan (); |
gamestate.treasurecount++; |
break; |
|
case bo_food: |
if (gamestate.health == 100) |
return; |
|
SD_PlaySound (HEALTH1SND); |
HealSelf (10); |
break; |
|
case bo_alpo: |
if (gamestate.health == 100) |
return; |
|
SD_PlaySound (HEALTH1SND); |
HealSelf (4); |
break; |
|
case bo_gibs: |
if (gamestate.health >10) |
return; |
|
SD_PlaySound (SLURPIESND); |
HealSelf (1); |
break; |
|
#ifdef SPEAR |
case bo_spear: |
spearflag = true; |
spearx = player->x; |
speary = player->y; |
spearangle = player->angle; |
playstate = ex_completed; |
#endif |
} |
|
StartBonusFlash (); |
check->shapenum = -1; // remove from list |
} |
|
/* |
=================== |
= |
= TryMove |
= |
= returns true if move ok |
= debug: use pointers to optimize |
=================== |
*/ |
|
boolean TryMove (objtype *ob) |
{ |
int xl,yl,xh,yh,x,y; |
objtype *check; |
int32_t deltax,deltay; |
|
xl = (ob->x-PLAYERSIZE) >>TILESHIFT; |
yl = (ob->y-PLAYERSIZE) >>TILESHIFT; |
|
xh = (ob->x+PLAYERSIZE) >>TILESHIFT; |
yh = (ob->y+PLAYERSIZE) >>TILESHIFT; |
|
#define PUSHWALLMINDIST PLAYERSIZE |
|
// |
// check for solid walls |
// |
for (y=yl;y<=yh;y++) |
{ |
for (x=xl;x<=xh;x++) |
{ |
check = actorat[x][y]; |
if (check && !ISPOINTER(check)) |
{ |
if(tilemap[x][y]==64 && x==pwallx && y==pwally) // back of moving pushwall? |
{ |
switch(pwalldir) |
{ |
case di_north: |
if(ob->y-PUSHWALLMINDIST<=(pwally<<TILESHIFT)+((63-pwallpos)<<10)) |
return false; |
break; |
case di_west: |
if(ob->x-PUSHWALLMINDIST<=(pwallx<<TILESHIFT)+((63-pwallpos)<<10)) |
return false; |
break; |
case di_east: |
if(ob->x+PUSHWALLMINDIST>=(pwallx<<TILESHIFT)+(pwallpos<<10)) |
return false; |
break; |
case di_south: |
if(ob->y+PUSHWALLMINDIST>=(pwally<<TILESHIFT)+(pwallpos<<10)) |
return false; |
break; |
} |
} |
else return false; |
} |
} |
} |
|
// |
// check for actors |
// |
if (yl>0) |
yl--; |
if (yh<MAPSIZE-1) |
yh++; |
if (xl>0) |
xl--; |
if (xh<MAPSIZE-1) |
xh++; |
|
for (y=yl;y<=yh;y++) |
{ |
for (x=xl;x<=xh;x++) |
{ |
check = actorat[x][y]; |
if (ISPOINTER(check) && check != player && (check->flags & FL_SHOOTABLE) ) |
{ |
deltax = ob->x - check->x; |
if (deltax < -MINACTORDIST || deltax > MINACTORDIST) |
continue; |
deltay = ob->y - check->y; |
if (deltay < -MINACTORDIST || deltay > MINACTORDIST) |
continue; |
|
return false; |
} |
} |
} |
|
return true; |
} |
|
|
/* |
=================== |
= |
= ClipMove |
= |
=================== |
*/ |
|
void ClipMove (objtype *ob, int32_t xmove, int32_t ymove) |
{ |
int32_t basex,basey; |
|
basex = ob->x; |
basey = ob->y; |
|
ob->x = basex+xmove; |
ob->y = basey+ymove; |
if (TryMove (ob)) |
return; |
|
#ifndef REMDEBUG |
if (noclip && ob->x > 2*TILEGLOBAL && ob->y > 2*TILEGLOBAL |
&& ob->x < (((int32_t)(mapwidth-1))<<TILESHIFT) |
&& ob->y < (((int32_t)(mapheight-1))<<TILESHIFT) ) |
return; // walk through walls |
#endif |
|
if (!SD_SoundPlaying()) |
SD_PlaySound (HITWALLSND); |
|
ob->x = basex+xmove; |
ob->y = basey; |
if (TryMove (ob)) |
return; |
|
ob->x = basex; |
ob->y = basey+ymove; |
if (TryMove (ob)) |
return; |
|
ob->x = basex; |
ob->y = basey; |
} |
|
//========================================================================== |
|
/* |
=================== |
= |
= VictoryTile |
= |
=================== |
*/ |
|
void VictoryTile (void) |
{ |
#ifndef SPEAR |
SpawnBJVictory (); |
#endif |
|
gamestate.victoryflag = true; |
} |
|
/* |
=================== |
= |
= Thrust |
= |
=================== |
*/ |
|
// For player movement in demos exactly as in the original Wolf3D v1.4 source code |
static fixed FixedByFracOrig(fixed a, fixed b) |
{ |
int sign = 0; |
if(b == 65536) b = 65535; |
else if(b == -65536) b = 65535, sign = 1; |
else if(b < 0) b = (-b), sign = 1; |
|
if(a < 0) |
{ |
a = -a; |
sign = !sign; |
} |
fixed res = (fixed)(((int64_t) a * b) >> 16); |
if(sign) |
res = -res; |
return res; |
} |
|
void Thrust (int angle, int32_t speed) |
{ |
int32_t xmove,ymove; |
unsigned offset; |
|
|
// |
// ZERO FUNNY COUNTER IF MOVED! |
// |
#ifdef SPEAR |
if (speed) |
funnyticount = 0; |
#endif |
|
thrustspeed += speed; |
// |
// moving bounds speed |
// |
if (speed >= MINDIST*2) |
speed = MINDIST*2-1; |
|
xmove = DEMOCHOOSE_ORIG_SDL( |
FixedByFracOrig(speed, costable[angle]), |
FixedMul(speed,costable[angle])); |
ymove = DEMOCHOOSE_ORIG_SDL( |
-FixedByFracOrig(speed, sintable[angle]), |
-FixedMul(speed,sintable[angle])); |
|
ClipMove(player,xmove,ymove); |
|
player->tilex = (short)(player->x >> TILESHIFT); // scale to tile values |
player->tiley = (short)(player->y >> TILESHIFT); |
|
offset = (player->tiley<<mapshift)+player->tilex; |
player->areanumber = *(mapsegs[0] + offset) -AREATILE; |
|
if (*(mapsegs[1] + offset) == EXITTILE) |
VictoryTile (); |
} |
|
|
/* |
============================================================================= |
|
ACTIONS |
|
============================================================================= |
*/ |
|
|
/* |
=============== |
= |
= Cmd_Fire |
= |
=============== |
*/ |
|
void Cmd_Fire (void) |
{ |
buttonheld[bt_attack] = true; |
|
gamestate.weaponframe = 0; |
|
player->state = &s_attack; |
|
gamestate.attackframe = 0; |
gamestate.attackcount = |
attackinfo[gamestate.weapon][gamestate.attackframe].tics; |
gamestate.weaponframe = |
attackinfo[gamestate.weapon][gamestate.attackframe].frame; |
} |
|
//=========================================================================== |
|
/* |
=============== |
= |
= Cmd_Use |
= |
=============== |
*/ |
|
void Cmd_Use (void) |
{ |
int checkx,checky,doornum,dir; |
boolean elevatorok; |
|
// |
// find which cardinal direction the player is facing |
// |
if (player->angle < ANGLES/8 || player->angle > 7*ANGLES/8) |
{ |
checkx = player->tilex + 1; |
checky = player->tiley; |
dir = di_east; |
elevatorok = true; |
} |
else if (player->angle < 3*ANGLES/8) |
{ |
checkx = player->tilex; |
checky = player->tiley-1; |
dir = di_north; |
elevatorok = false; |
} |
else if (player->angle < 5*ANGLES/8) |
{ |
checkx = player->tilex - 1; |
checky = player->tiley; |
dir = di_west; |
elevatorok = true; |
} |
else |
{ |
checkx = player->tilex; |
checky = player->tiley + 1; |
dir = di_south; |
elevatorok = false; |
} |
|
doornum = tilemap[checkx][checky]; |
if (*(mapsegs[1]+(checky<<mapshift)+checkx) == PUSHABLETILE) |
{ |
// |
// pushable wall |
// |
|
PushWall (checkx,checky,dir); |
return; |
} |
if (!buttonheld[bt_use] && doornum == ELEVATORTILE && elevatorok) |
{ |
// |
// use elevator |
// |
buttonheld[bt_use] = true; |
|
tilemap[checkx][checky]++; // flip switch |
if (*(mapsegs[0]+(player->tiley<<mapshift)+player->tilex) == ALTELEVATORTILE) |
playstate = ex_secretlevel; |
else |
playstate = ex_completed; |
SD_PlaySound (LEVELDONESND); |
SD_WaitSoundDone(); |
} |
else if (!buttonheld[bt_use] && doornum & 0x80) |
{ |
buttonheld[bt_use] = true; |
OperateDoor (doornum & ~0x80); |
} |
else |
SD_PlaySound (DONOTHINGSND); |
} |
|
/* |
============================================================================= |
|
PLAYER CONTROL |
|
============================================================================= |
*/ |
|
|
|
/* |
=============== |
= |
= SpawnPlayer |
= |
=============== |
*/ |
|
void SpawnPlayer (int tilex, int tiley, int dir) |
{ |
player->obclass = playerobj; |
player->active = ac_yes; |
player->tilex = tilex; |
player->tiley = tiley; |
player->areanumber = (byte) *(mapsegs[0]+(player->tiley<<mapshift)+player->tilex); |
player->x = ((int32_t)tilex<<TILESHIFT)+TILEGLOBAL/2; |
player->y = ((int32_t)tiley<<TILESHIFT)+TILEGLOBAL/2; |
player->state = &s_player; |
player->angle = (1-dir)*90; |
if (player->angle<0) |
player->angle += ANGLES; |
player->flags = FL_NEVERMARK; |
Thrust (0,0); // set some variables |
|
InitAreas (); |
} |
|
|
//=========================================================================== |
|
/* |
=============== |
= |
= T_KnifeAttack |
= |
= Update player hands, and try to do damage when the proper frame is reached |
= |
=============== |
*/ |
|
void KnifeAttack (objtype *ob) |
{ |
objtype *check,*closest; |
int32_t dist; |
|
SD_PlaySound (ATKKNIFESND); |
// actually fire |
dist = 0x7fffffff; |
closest = NULL; |
for (check=ob->next; check; check=check->next) |
{ |
if ( (check->flags & FL_SHOOTABLE) && (check->flags & FL_VISABLE) |
&& abs(check->viewx-centerx) < shootdelta) |
{ |
if (check->transx < dist) |
{ |
dist = check->transx; |
closest = check; |
} |
} |
} |
|
if (!closest || dist > 0x18000l) |
{ |
// missed |
return; |
} |
|
// hit something |
DamageActor (closest,US_RndT() >> 4); |
} |
|
|
|
void GunAttack (objtype *ob) |
{ |
objtype *check,*closest,*oldclosest; |
int damage; |
int dx,dy,dist; |
int32_t viewdist; |
|
switch (gamestate.weapon) |
{ |
case wp_pistol: |
SD_PlaySound (ATKPISTOLSND); |
break; |
case wp_machinegun: |
SD_PlaySound (ATKMACHINEGUNSND); |
break; |
case wp_chaingun: |
SD_PlaySound (ATKGATLINGSND); |
break; |
} |
|
madenoise = true; |
|
// |
// find potential targets |
// |
viewdist = 0x7fffffffl; |
closest = NULL; |
|
while (1) |
{ |
oldclosest = closest; |
|
for (check=ob->next ; check ; check=check->next) |
{ |
if ((check->flags & FL_SHOOTABLE) && (check->flags & FL_VISABLE) |
&& abs(check->viewx-centerx) < shootdelta) |
{ |
if (check->transx < viewdist) |
{ |
viewdist = check->transx; |
closest = check; |
} |
} |
} |
|
if (closest == oldclosest) |
return; // no more targets, all missed |
|
// |
// trace a line from player to enemey |
// |
if (CheckLine(closest)) |
break; |
} |
|
// |
// hit something |
// |
dx = ABS(closest->tilex - player->tilex); |
dy = ABS(closest->tiley - player->tiley); |
dist = dx>dy ? dx:dy; |
if (dist<2) |
damage = US_RndT() / 4; |
else if (dist<4) |
damage = US_RndT() / 6; |
else |
{ |
if ( (US_RndT() / 12) < dist) // missed |
return; |
damage = US_RndT() / 6; |
} |
DamageActor (closest,damage); |
} |
|
//=========================================================================== |
|
/* |
=============== |
= |
= VictorySpin |
= |
=============== |
*/ |
|
void VictorySpin (void) |
{ |
int32_t desty; |
|
if (player->angle > 270) |
{ |
player->angle -= (short)(tics * 3); |
if (player->angle < 270) |
player->angle = 270; |
} |
else if (player->angle < 270) |
{ |
player->angle += (short)(tics * 3); |
if (player->angle > 270) |
player->angle = 270; |
} |
|
desty = (((int32_t)player->tiley-5)<<TILESHIFT)-0x3000; |
|
if (player->y > desty) |
{ |
player->y -= tics*4096; |
if (player->y < desty) |
player->y = desty; |
} |
} |
|
|
//=========================================================================== |
|
/* |
=============== |
= |
= T_Attack |
= |
=============== |
*/ |
|
void T_Attack (objtype *ob) |
{ |
struct atkinf *cur; |
|
UpdateFace (); |
|
if (gamestate.victoryflag) // watching the BJ actor |
{ |
VictorySpin (); |
return; |
} |
|
if ( buttonstate[bt_use] && !buttonheld[bt_use] ) |
buttonstate[bt_use] = false; |
|
if ( buttonstate[bt_attack] && !buttonheld[bt_attack]) |
buttonstate[bt_attack] = false; |
|
ControlMovement (ob); |
if (gamestate.victoryflag) // watching the BJ actor |
return; |
|
plux = (word) (player->x >> UNSIGNEDSHIFT); // scale to fit in unsigned |
pluy = (word) (player->y >> UNSIGNEDSHIFT); |
player->tilex = (short)(player->x >> TILESHIFT); // scale to tile values |
player->tiley = (short)(player->y >> TILESHIFT); |
|
// |
// change frame and fire |
// |
gamestate.attackcount -= (short) tics; |
while (gamestate.attackcount <= 0) |
{ |
cur = &attackinfo[gamestate.weapon][gamestate.attackframe]; |
switch (cur->attack) |
{ |
case -1: |
ob->state = &s_player; |
if (!gamestate.ammo) |
{ |
gamestate.weapon = wp_knife; |
DrawWeapon (); |
} |
else |
{ |
if (gamestate.weapon != gamestate.chosenweapon) |
{ |
gamestate.weapon = gamestate.chosenweapon; |
DrawWeapon (); |
} |
} |
gamestate.attackframe = gamestate.weaponframe = 0; |
return; |
|
case 4: |
if (!gamestate.ammo) |
break; |
if (buttonstate[bt_attack]) |
gamestate.attackframe -= 2; |
case 1: |
if (!gamestate.ammo) |
{ // can only happen with chain gun |
gamestate.attackframe++; |
break; |
} |
GunAttack (ob); |
if (!ammocheat) |
gamestate.ammo--; |
DrawAmmo (); |
break; |
|
case 2: |
KnifeAttack (ob); |
break; |
|
case 3: |
if (gamestate.ammo && buttonstate[bt_attack]) |
gamestate.attackframe -= 2; |
break; |
} |
|
gamestate.attackcount += cur->tics; |
gamestate.attackframe++; |
gamestate.weaponframe = |
attackinfo[gamestate.weapon][gamestate.attackframe].frame; |
} |
} |
|
|
|
//=========================================================================== |
|
/* |
=============== |
= |
= T_Player |
= |
=============== |
*/ |
|
void T_Player (objtype *ob) |
{ |
if (gamestate.victoryflag) // watching the BJ actor |
{ |
VictorySpin (); |
return; |
} |
|
UpdateFace (); |
CheckWeaponChange (); |
|
if ( buttonstate[bt_use] ) |
Cmd_Use (); |
|
if ( buttonstate[bt_attack] && !buttonheld[bt_attack]) |
Cmd_Fire (); |
|
ControlMovement (ob); |
if (gamestate.victoryflag) // watching the BJ actor |
return; |
|
plux = (word) (player->x >> UNSIGNEDSHIFT); // scale to fit in unsigned |
pluy = (word) (player->y >> UNSIGNEDSHIFT); |
player->tilex = (short)(player->x >> TILESHIFT); // scale to tile values |
player->tiley = (short)(player->y >> TILESHIFT); |
} |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |