ref: a7ed30404bc98c13ac89721ab54e1d702d4e0b39
dir: /src/rt_playr.c/
/* Copyright (C) 1994-1995 Apogee Software, Ltd. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include <string.h> #include <stdlib.h> #include <stdio.h> #include <stdarg.h> #include "rt_def.h" #include "watcom.h" #include "rt_sound.h" #include "gmove.h" #include "states.h" #include "rt_sqrt.h" #include "rt_actor.h" #include "rt_main.h" #include "rt_playr.h" #include "isr.h" #include "rt_draw.h" #include "rt_ted.h" #include "rt_door.h" #include "rt_menu.h" #include "rt_view.h" #include "rt_com.h" #include "rt_in.h" #include "rt_util.h" #include "rt_game.h" #include "rt_rand.h" #include "z_zone.h" #include "engine.h" #include "_rt_play.h" #include "rt_cfg.h" #include "rt_floor.h" #include "develop.h" #include "rt_msg.h" #include "rt_debug.h" #include "sprites.h" #include "rt_net.h" #include "rt_dmand.h" #define FLYINGZMOM 350000 extern boolean usejump; specials CurrentSpecialsTimes = { 60*VBLCOUNTER, // god 60*VBLCOUNTER, // dog 20*VBLCOUNTER, // shrooms 20*VBLCOUNTER, // elasto 60*VBLCOUNTER, // asbestos vest 60*VBLCOUNTER, // bullet proof vest GASTICS, // gas mask 60*VBLCOUNTER, // mercury mode 300*VBLCOUNTER, // god respawn 60*VBLCOUNTER, // dog respawn 60*VBLCOUNTER, // shrooms respawn 60*VBLCOUNTER, // elasto respawn 60*VBLCOUNTER, // asbestos vest respawn 60*VBLCOUNTER, // bullet proof vest respawn 60*VBLCOUNTER, // gas mask respawn 60*VBLCOUNTER // mercury mode respawn }; int GRAVITY = NORMAL_GRAVITY; ROTTCHARS characters[5]= { {0x2100,0x4800,100,2,25}, // Taradino Cassatt {0x2200,0x5200,85,3,32}, // Thi Barrett {0x1f00,0x4000,150,3,20}, // Doug Wendt {0x2300,0x5500,70,2,33}, // Lorelei Ni {0x2000,0x4400,120,3,25} }; // Ian Paul Freeley static const int TD = MINACTORDIST+0x1000; static const int STRAFEAMOUNT = ((KEYBOARDNORMALTURNAMOUNT >> 10) + (KEYBOARDNORMALTURNAMOUNT >> 12)); static const int GODYZANGLE = -(9*FINEANGLES/360); static const int DOGYZANGLE = (4*FINEANGLES/360); static const int SHROOMYZANGLE = (15*FINEANGLES/360); static const int FALLINGYZANGLE = -(15*FINEANGLES/360); static const int NORMALYZANGLE = 0; /* ============================================================================= GLOBAL VARIABLES ============================================================================= */ int controlbuf[3]; int buttonbits; extern _2Dpoint LASTSOUND; // // player state info // statobj_t *DEADPLAYER[MAXDEAD]; int NUMDEAD; int lastpolltime; statobj_t *BulletHoles[MAXBULLETS]; int BulletHoleNum; objtype *PLAYER[MAXPLAYERS],*player; playertype PLAYERSTATE[MAXPLAYERS],*locplayerstate; gametype gamestate; boolean godmode = false; boolean missilecam=false; objtype * missobj=NULL; // Player control variables int KX = 0; int KY = 0; int MX = 0; int MY = 0; int JX = 0; int JY = 0; int CX = 0; int CY = 0; int VX = 0; int VY = 0; int leftmom = 0; int rightmom = 0; int lastmom = 0; int first = 1; int pausedstartedticcount; boolean RefreshPause = true; boolean buttonpoll[NUMBUTTONS]; int buttonscan[NUMBUTTONS] = {sc_Control, sc_Alt, sc_RShift, sc_Space, sc_PgUp,sc_PgDn,sc_Enter,sc_Delete, sc_Home,sc_End,sc_1,sc_2,sc_3,sc_4, sc_CapsLock, sc_F12, sc_Comma,sc_Period,sc_BackSpace,sc_A, sc_UpArrow, sc_RightArrow, sc_DownArrow, sc_LeftArrow, sc_Tab, sc_T, sc_Z }; int joyxmax = 0, joyymax = 0, joyxmin = 0, joyymin = 0; int buttonmouse[6] = {bt_attack, bt_strafe, di_north, bt_nobutton, bt_use, bt_nobutton }; int buttonjoy[8] = {bt_attack, bt_strafe, bt_run, bt_use, bt_nobutton, bt_nobutton, bt_nobutton, bt_nobutton }; williamdidthis FREE = {84,5,0,0,9,{{done,2,1},{done,2,2},{done,2,3}, {done,2,4},{done,2,5},{done,2,6},{done,2,7},{done,2,8}, {reset,2,9} } }; williamdidthis DOGSCRATCH = {128,5,0,0,4,{{done,2,8},{at_pulltrigger,2,9},{done,2,10}, {reset,2,11} } }; williamdidthis DOGLICK = {128,5,0,0,4,{{done,2,4},{done,2,5},{done,2,6}, {reset,2,7} } }; williamdidthis WEAPONS[MAXWEAPONS] = { {100,-1,10,0x2000l,3,{{at_pulltrigger,4,1},{done,4,2},{reset,4,0}}}, //single pistol { 100,-1,10,0x2000l,6,{{at_pulltrigger,2,1},{done,2,2},{done,2,3}, {at_pulltrigger,2,4},{done,2,5},{reset,2,3} } }, // double pistol {70,-1,10,0x2000l,2,{{at_pulltrigger,2,1},{reset,1,2}}}, //mp 40 {80,5,10,0x50000l,4,{{at_missileweapon,2,1},{done,2,2},{reset,2,3},{reset2,6,0}}}, //bazooka {80,5,10,0x10000l,4,{{at_missileweapon,2,1},{done,2,2},{reset,2,3},{reset2,6,0}}}, //firebomb {80,5,10,0x50000l,4,{{at_missileweapon,2,1},{done,2,2},{reset,2,3},{reset2,6,0}}}, //heatseeker {80,5,10,0x10000l,4,{{at_missileweapon,2,1},{done,2,2},{reset,2,3},{reset2,6,0}}}, //drunk {80,5,7,0x10000l,4,{{at_missileweapon,2,1},{done,2,2},{reset,2,2},{reset2,6,0}}}, // firewall { 125,5,7,0x10000l,7,{{done,3,1},{done,3,2},{done,3,3},{done,3,4}, {at_missileweapon,3,5},{done,3,6},{reset,3,7} } }, //GODHAND #if (SHAREWARE == 0) {80,5,7,0x10000l,4,{{at_missileweapon,2,1},{done,2,2},{reset,2,3},{reset2,6,0}}}, //split { 80,5,7,0x10000l,9,{{done,5,1},{done,5,2},{done,5,3},{done,5,4}, {at_missileweapon,10,5},{done,5,4},{done,5,3}, // kes {done,5,2},{reset,5,1} } }, { 200,5,7,0x10000l,6,{{done,1,1},{done,1,2},{at_pulltrigger,1,3},{at_pulltrigger,1,4}, {at_pulltrigger,1,5},{reset,1,6} } }, //BAT {128,5,7,0x10000l,3,{{done,2,1},{at_pulltrigger,2,2},{reset,2,3}}} #endif }; /* ============================================================================= LOCAL FUNCTION PROTOTYPES and VARIABLES ============================================================================= */ void CheckPlayerSpecials(objtype * ob); void CheckWeaponStates(objtype * ob); boolean CheckSprite (statobj_t*,int *); void T_Tag (objtype *ob); void T_Player (objtype *ob); void T_BatBlast(objtype*ob); void T_Attack (objtype *ob); void T_Free (objtype *ob); void T_DogUse (objtype *ob); void PlayerMove(objtype * ob); void Thrust (objtype * ob); void CheckWeaponChange (objtype * ob); void PlayerMissileAttack(objtype* ); void Cmd_Use(objtype*); //void ComError (char *error, ...); int FinddTopYZANGLELIMITvalue(objtype *ob); statetype s_free = {false,0,0,T_Free,0,&s_free}; statetype s_inelevator = {false,0,420,T_Player,0,&s_player}; #if (SHAREWARE == 0) statetype s_dogwait = {true,SERIALDOG_W11,50,T_Player,SF_DOGSTATE,&s_serialdog}; statetype s_doguse = {true,SERIALDOG_W11,140,T_DogUse,SF_DOGSTATE,&s_serialdog}; statetype s_doglick = {true,SERIALDOG_W11,0,T_DogLick,SF_DOGSTATE,&s_doglick}; #endif statetype s_tag = {false,CASSATT_S1,20,T_Tag,0,&s_player}; // // curent user input // static int turnheldtime; static int turnaround = 0; static int turnaroundtime; // // Double Click variables // static int DoubleClickTimer[ 3 ] = { 0 }; static byte DoubleClickCount[ 3 ] = { 0 }; static byte DoubleClickPressed[ 3 ] = { false }; static int JoyDblClickTimer[ 4 ] = { 0 }; static byte JoyDblClickCount[ 4 ] = { 0 }; static byte JoyDblClickPressed[ 4 ] = { false }; static int PlayerRecording=-1; static int nettics; void Move_Player_From_Exit_To_Start(objtype *ob); void CheckTagGame(objtype *actor1,objtype*actor2); void CheckFlying(objtype*ob,playertype *pstate); /* =============== = = LoadPlayer = =============== */ void LoadPlayer ( void ) { memset (locplayerstate->buttonstate, 0, sizeof(locplayerstate->buttonstate)); locplayerstate->anglefrac=player->angle<<ANGLEBITS; areabyplayer[player->areanumber]=true; ConnectAreas(); } int MaxHitpointsForCharacter(playertype*pstate) { if (BATTLEMODE && (gamestate.BattleOptions.HitPoints != bo_character_hitpoints)) { return( gamestate.BattleOptions.HitPoints ); } return characters[pstate->player].hitpoints; } void InitializeWeapons(playertype*pstate) { #if (SHAREWARE == 0) if (gamestate.SpawnEluder) { pstate->new_weapon = pstate->weapon = pstate->missileweapon = wp_dog; pstate->oldweapon = pstate->oldmissileweapon = wp_dog; pstate->bulletweapon = -1; pstate->HASBULLETWEAPON[wp_pistol] = 0; pstate->HASBULLETWEAPON[wp_twopistol] = 0; pstate->HASBULLETWEAPON[wp_mp40] = 0; } else #endif { if (gamestate.PlayerHasGun[pstate-&PLAYERSTATE[0]]) { pstate->new_weapon = pstate->weapon = pstate->oldweapon = pstate->bulletweapon = wp_pistol; pstate->HASBULLETWEAPON[wp_pistol] = 1; pstate->HASBULLETWEAPON[wp_twopistol] = 0; pstate->HASBULLETWEAPON[wp_mp40] = 0; pstate->missileweapon = pstate->oldmissileweapon = -1; } else { pstate->new_weapon = pstate->weapon = pstate->oldweapon = pstate->bulletweapon = -1; pstate->HASBULLETWEAPON[wp_pistol] = 0; pstate->HASBULLETWEAPON[wp_twopistol] = 0; pstate->HASBULLETWEAPON[wp_mp40] = 0; pstate->missileweapon = pstate->oldmissileweapon = -1; } } pstate->ammo = -1; } void ResetPlayerstate(playertype*pstate) { pstate->batblast = 0; pstate->poweruptime = pstate->protectiontime = 0; pstate->NETCAPTURED = 0; MISCVARS->NET_IN_FLIGHT = 0; pstate->weaponuptics = 0; pstate->weapondowntics = 0; if ((insetupgame==false) || NewGame) pstate->health = MaxHitpointsForCharacter(pstate); pstate->keys = 0; // Give players all the keys in battle game if ( BATTLEMODE ) { pstate->keys = 0x0f; } pstate->attackframe = pstate->attackcount = pstate->weaponframe = 0; if (gamestate.battlemode == battle_Tag) pstate->weaponheight = TAGHANDHEIGHT; else pstate->weaponheight = 0; pstate->heightoffset = pstate->oldheightoffset = 0; if (gamestate.SpawnEluder) pstate->playerheight = 40; else pstate->playerheight = characters[pstate->player].height; pstate->falling = false; memset (pstate->buttonstate, 0, sizeof(pstate->buttonstate)); SetPlayerHorizon(pstate,NORMALYZANGLE); } /* =============== = = SetupPlayerobj = =============== */ void SetupPlayerobj (int tilex, int tiley, int dir, objtype * ob) { playertype *pstate; M_LINKSTATE(ob,pstate); ob->obclass = playerobj; ob->tilex = tilex; ob->tiley = tiley; actorat[tilex][tiley] = ob; ob->areanumber = MAPSPOT(tilex,tiley,0)-AREATILE; MakeLastInArea(ob); ob->x = ((long)tilex<<TILESHIFT)+TILEGLOBAL/2; ob->y = ((long)tiley<<TILESHIFT)+TILEGLOBAL/2; ob->z = PlatformHeight(tilex,tiley); if ((ob->z == -10) || DiskAt(tilex,tiley)) ob->z = 0; ob->angle = (1-dir)*ANG90; ob->which = ACTOR; Fix(ob->angle); ob->yzangle = 0; ob->dir = angletodir[ob->angle]; ob->flags = (FL_SHOOTABLE|FL_ABP|FL_BLOCK|FL_COLORED); ob->drawx=ob->x; ob->drawy=ob->y; ob->hitpoints = pstate->health; pstate->anglefrac= (ob->angle<<ANGLEBITS); pstate->angle=0; areabyplayer[ob->areanumber]=true; if (ob == player) { playerdead=false; // local player dead flag } if (!gamestate.SpawnEluder) ob->shapeoffset = pstate->player*REMOTEOFFSET; memset (pstate->buttonstate, 0, sizeof(pstate->buttonstate)); if (SCREENEYE != NULL) { NewState(SCREENEYE,&s_megaremove); SCREENEYE = NULL; } } void SetShapeoffset(objtype*ob) { playertype *pstate; M_LINKSTATE(ob,pstate); ob->shapeoffset = pstate->player*REMOTEOFFSET; ob->flags |= FL_COLORED; ob->flags &= ~FL_DYING; } /* =============== = = RevivePlayerobj = =============== */ void RevivePlayerobj (int tilex, int tiley, int dir, objtype*ob) { playertype *pstate; statetype *tstate; M_LINKSTATE(ob,pstate); tstate = ob->state; RemoveFromArea(ob); TurnActorIntoSprite(ob); if ((LASTSTAT->z < nominalheight) && (!IsPlatform(LASTSTAT->tilex,LASTSTAT->tiley))) { SpawnParticles(ob,GUTS,10 + gamestate.difficulty); RemoveStatic(LASTSTAT); } else { if (DEADPLAYER[NUMDEAD]) RemoveStatic(DEADPLAYER[NUMDEAD]); DEADPLAYER[NUMDEAD] = LASTSTAT; LASTSTAT->linked_to = NUMDEAD; NUMDEAD = (NUMDEAD+1)&(MAXDEAD-1); } ob->state = tstate; SetupPlayerobj (tilex, tiley, dir, ob); ConnectAreas(); ResetPlayerstate(pstate); InitializeWeapons(pstate); SD_PlaySoundRTP(SD_PLAYERSPAWNSND,ob->x,ob->y); if (!gamestate.SpawnEluder) { ob->shapeoffset = 0; ob->flags &= ~FL_COLORED; ob->flags |= FL_DYING; NewState(ob,&s_respawn1); if (gamestate.battlemode == battle_Tag) { if (BATTLE_Team[ob->dirchoosetime] == BATTLE_It) { pstate->missileweapon = pstate->oldweapon = pstate->new_weapon = pstate->oldmissileweapon = pstate->weapon = wp_godhand; pstate->bulletweapon = -1; ob->flags |= FL_DESIGNATED; } else { pstate->weaponheight = 0; } } } #if (SHAREWARE == 0) else NewState(ob,&s_serialdog); #endif if (ob==player) DrawPlayScreen(false); ob->momentumx = ob->momentumy = ob->momentumz = 0; } /* =============== = = SpawnPlayerobj = =============== */ void SpawnPlayerobj (int tilex, int tiley, int dir, int playerindex) { GetNewActor(); MakeActive(new); // Set player number new->dirchoosetime = playerindex; // Save off if local player if (playerindex==consoleplayer) player=new; PLAYER[playerindex] = new; SetupPlayerobj (tilex, tiley, dir, new); if (!gamestate.SpawnEluder) NewState(new,&s_player); #if (SHAREWARE == 0) else NewState(new,&s_serialdog); #endif } /* =============== = = SetupBulletHoleLink = =============== */ void SetupBulletHoleLink (int num, statobj_t * item) { BulletHoles[num] = item; } /* =============== = = SpawnBulletHole = =============== */ void SpawnBulletHole (int x, int y, int z) { if (M_ISDOOR(x>>16,y>>16)) return; if (BulletHoles[MISCVARS->BulletHoleNum]) RemoveStatic(BulletHoles[MISCVARS->BulletHoleNum]); SpawnInertStatic(x,y,z,stat_bullethole); BulletHoles[MISCVARS->BulletHoleNum]=LASTSTAT; LASTSTAT->linked_to=MISCVARS->BulletHoleNum; MISCVARS->BulletHoleNum = (MISCVARS->BulletHoleNum+1)&(MAXBULLETS-1); } void SpawnGunSmoke(int x, int y, int z, int angle, int bullethole) { int chance; if ((x<=0) || (y<=0)) { SoftError("SpawnGunSmoke: xy below angle=%d\n",angle); return; } if ((bullethole!=0) && (z>=-32) && (z<=maxheight)) switch (bullethole) { case 1: SpawnBulletHole(x-BULLETHOLEOFFSET,y,z); break; case 2: SpawnBulletHole(x+BULLETHOLEOFFSET,y,z); break; case 3: SpawnBulletHole(x,y-BULLETHOLEOFFSET,z); break; case 4: SpawnBulletHole(x,y+BULLETHOLEOFFSET,z); break; case 5: SpawnBulletHole(x,y,z); break; default: Error("Invalid bullethole value\n"); break; } SpawnInertActor(x,y,z); NewState(new,&s_gunsmoke1); if (angle < ANGLES/4) { if ((angle < (3*ANGLES/16)) && (angle > (ANGLES/16))) chance = 128; else chance = 20; } else if (angle < ANGLES/2) { if ((angle < (7*ANGLES/16)) && (angle > (5*ANGLES/16))) chance = 128; else chance = 20; } else if (angle < 3*ANGLES/4) { if ((angle < (11*ANGLES/16)) && (angle > (9*ANGLES/16))) chance = 128; else chance = 20; } else { if ((angle < (15*ANGLES/16)) && (angle > (13*ANGLES/16))) chance = 128; else chance = 20; } if (RandomNumber("Wall ricochet check",0)<chance) { int rand; rand = RandomNumber("Spawn Ricochet Sound in SpawnGunSmoke",0); if (rand < 80) SD_PlaySoundRTP(SD_RICOCHET1SND,new->x,new->y); else if (rand < 160) SD_PlaySoundRTP(SD_RICOCHET2SND,new->x,new->y); else SD_PlaySoundRTP(SD_RICOCHET3SND,new->x,new->y); } } void SpawnBlood(objtype * ob, int angle) { SpawnInertActor(ob->x-(costable[angle]>>5), ob->y+(sintable[angle]>>5),ob->z); NewState(new,&s_bloodspurt1); if ((new->x<=0) || (new->y<=0)) Error("SpawnBlood: bad x,y obj->obclass=%d\n",ob->obclass); } void SpawnMetalSparks(objtype * ob, int angle) { int rand,dispx=0,dispy=0; if (ob->which == ACTOR) { dispx = ob->momentumx; dispy = ob->momentumy; } SpawnInertActor(ob->x-(costable[angle]>>3)+dispx, ob->y+(sintable[angle]>>3)+dispy,ob->z); if (GameRandomNumber("Spawn Metal Sparks",0)<128) NewState(new,&s_hitmetalactor1); else NewState(new,&s_hitmetalwall1); rand = RandomNumber("Spawn Ricochet Sound",0); if (rand < 80) SD_PlaySoundRTP(SD_RICOCHET1SND,new->x,new->y); else if (rand < 160) SD_PlaySoundRTP(SD_RICOCHET2SND,new->x,new->y); else SD_PlaySoundRTP(SD_RICOCHET3SND,new->x,new->y); if ((new->x<=0) || (new->y<=0)) Error("SpawnMetalSparks: bad x,y obj->obclass=%d\n",ob->obclass); } /* =============== = = UnTargetActor ( objtype * target ) = =============== */ void UnTargetActor ( objtype * target ) { int i; for (i=0; i<numplayers; i++) { if (PLAYERSTATE[i].guntarget==target) { PLAYERSTATE[i].guntarget=NULL; SetNormalHorizon(PLAYER[i]); } } } //============================================================= int GetWeaponForItem(int itemnumber) { switch (itemnumber) { case stat_twopistol: return wp_twopistol; case stat_mp40: return wp_mp40; case stat_bazooka: return wp_bazooka; case stat_heatseeker: return wp_heatseeker; case stat_drunkmissile: return wp_drunk; case stat_firebomb: return wp_firebomb; case stat_firewall: return wp_firewall; case stat_godmode: return wp_godhand; #if (SHAREWARE == 0) case stat_splitmissile: return wp_split; case stat_kes: return wp_kes; case stat_bat: return wp_bat; case stat_dogmode: return wp_dog; #endif } return 0; } int GetItemForWeapon(int weapon) { switch (weapon) { case wp_twopistol: return stat_twopistol; case wp_mp40: return stat_mp40; case wp_bazooka: return stat_bazooka; case wp_heatseeker: return stat_heatseeker; case wp_drunk: return stat_drunkmissile; case wp_firebomb: return stat_firebomb; case wp_firewall: return stat_firewall; case wp_godhand: return stat_godmode; #if (SHAREWARE == 0) case wp_split: return stat_splitmissile; case wp_kes: return stat_kes; case wp_bat: return stat_bat; case wp_dog: return stat_dogmode; #endif } return -1; } #define MF_SINGULAR 0x01 missile_stats PlayerMissileData[13] = { {0,0,0,0,0}, {0,0,0,0,0}, {0,0,0,0,0}, {&s_p_bazooka1,0x6000,p_bazookaobj,0x7000,MF_SINGULAR}, {&s_p_bazooka1,0x8000,p_heatseekobj,0x7000,MF_SINGULAR}, {&s_p_bazooka1,0x6000,p_drunkmissileobj,0x7000,0}, {&s_p_bazooka1,0x8000,p_firebombobj,0x7000,MF_SINGULAR}, {&s_p_grenade,0x4000,p_firewallobj,0x8000,0}, {&s_godfire1,0x3800,p_godballobj,0x8000,0}, {&s_p_bazooka1,0x8000,p_splitmissileobj,0x7000,MF_SINGULAR}, #if (SHAREWARE == 0) {&s_kessphere1,0xc000,p_kesobj,0x5000,MF_SINGULAR}, #else {0,0,0,0,0}, #endif {0,0,0,0,0}, {0,0,0,0,0} }; void MissileAutoTarget(objtype *ob,missile_stats *mdata) { int dx,dy,angle,mindist,currdist,magangle,saveangle, xydist,dz,yzangle,oldyzangle,saveyzangle; objtype *target,*temp; mindist = 0x7fffffff; target = NULL; for(temp = firstactive; temp; temp=temp->nextactive) { if (temp == ob) continue; if ((!(temp->flags & FL_SHOOTABLE)) || (temp->flags & FL_DYING)) continue; if (!CheckLine(ob,temp,SHOOT)) continue; dx = temp->x-ob->x; dy = ob->y-temp->y; dz = ob->z-temp->z; xydist = FindDistance(dx,dy); yzangle = atan2_appx(xydist,dz<<10); angle = atan2_appx(dx,dy); magangle = abs(ob->angle - angle); if (magangle > VANG180) magangle = ANGLES - magangle; if (magangle > ANGLESDIV8) continue; currdist = FindDistance(ob->x-temp->x,ob->y-temp->y); if (currdist < mindist) { mindist = currdist; target = temp; saveangle = angle; saveyzangle = yzangle; } } if (target) { oldyzangle = ob->yzangle; ob->yzangle = saveyzangle; SpawnMissile(ob,mdata->obclass,mdata->speed,saveangle, mdata->state,mdata->offset); ob->yzangle = oldyzangle; } else if (ob->flags&FL_GODMODE) { int saveangle; saveangle=ob->yzangle; ob->yzangle -= GODYZANGLE; Fix(ob->yzangle); SpawnMissile(ob,mdata->obclass,mdata->speed, ob->angle,mdata->state,mdata->offset); ob->yzangle=saveangle; } else SpawnMissile(ob,mdata->obclass,mdata->speed,ob->angle, mdata->state,mdata->offset); } void PlayerMissileAttack(objtype*ob) { playertype * pstate; missile_stats *newmissiledata; M_LINKSTATE(ob,pstate); MISCVARS->madenoise = true; newmissiledata = &PlayerMissileData[pstate->missileweapon]; // ready to annihilate this poor bastard if ((newmissiledata->obclass == p_godballobj) || (newmissiledata->obclass == p_kesobj)) MissileAutoTarget(ob,newmissiledata); else { //LT added: if autoAimMissileWeps is true (as well as autoAim), then missile weapons will be aimed similarly to bullet weapons if (autoAimMissileWeps && autoAim) AutoTargetHorizon(ob); SpawnMissile(ob,newmissiledata->obclass,newmissiledata->speed,ob->angle, newmissiledata->state,newmissiledata->offset); if (newmissiledata->obclass == p_drunkmissileobj) { int i; for(i=0; i<4; i++) { if (!MissileTryMove(new,new->x+new->momentumx,new->y+new->momentumy,new->z)) { new->x = new->drawx = ob->x + (costable[new->angle]>>3); new->y = new->drawy = ob->y - (sintable[new->angle]>>3); ob->momentumx = -FixedMul(0x5000l,costable[ob->angle]); ob->momentumy = FixedMul(0x5000l,sintable[ob->angle]); } SpawnMissile(ob,newmissiledata->obclass,newmissiledata->speed,ob->angle, newmissiledata->state,newmissiledata->offset); } } } if (newmissiledata->flags & MF_SINGULAR) PLAYER0MISSILE = new; SD_PlaySoundRTP(BAS[new->obclass].fire,ob->x,ob->y); // if (new->obclass == p_godballobj) // new->z += 10; new->dirchoosetime = 5; if (missilecam==true) missobj=new; if (!MissileTryMove(new,new->x+new->momentumx,new->y+new->momentumy,new->z)) { new->x = new->drawx = ob->x + (costable[new->angle]>>3); new->y = new->drawy = ob->y - (sintable[new->angle]>>3); ob->momentumx = -FixedMul(0x5000l,costable[ob->angle]); ob->momentumy = FixedMul(0x5000l,sintable[ob->angle]); } } //==================================================================== boolean InRange (objtype *p, objtype *victim, int distance) { int dx,dy; int angle; int magangle; if (victim->which==SPRITE) { dx = ((statobj_t *)victim)->x - p->x; dy = p->y - ((statobj_t *)victim)->y; } else { dx = victim->x - p->x; dy = p->y - victim->y; } angle = atan2_appx (dx,dy); magangle = abs(p->angle - angle); if (magangle > VANG180) magangle = ANGLES - magangle; if (magangle<(75-(distance>>16))) return true; else return false; } void DogAttack(objtype*ob) { objtype *temp; int dx,dy,dz; SD_PlaySoundRTP(SD_DOGMODEBITE1SND+(RandomNumber("DogAttack",0)>>7),ob->x,ob->y); for(temp=firstareaactor[ob->areanumber]; temp; temp=temp->nextinarea) { if (temp->obclass > b_heinrichobj) continue; if ((temp == ob) || (temp->obclass == roboguardobj)) continue; if ((!(temp->flags & FL_SHOOTABLE)) || (temp->flags & FL_DYING)) continue; if (temp->obclass == collectorobj) continue; dx = abs(temp->x - ob->x); if (dx > 0xc000) continue; dy = abs(temp->y - ob->y); if (dy > 0xc000) continue; dz = abs(temp->z - ob->z); if (dz > (0xc000>>10)) continue; DamageThing(temp,30); if (gamestate.violence == vl_excessive) SpawnParticles(temp,GUTS,15); Collision(temp,ob,-temp->momentumx,-temp->momentumy); if ((temp->obclass == playerobj) && (temp->flags & FL_DYING)) BATTLE_PlayerKilledPlayer(battle_kill_with_missile,ob->dirchoosetime,temp->dirchoosetime); return; } } void DogBlast(objtype*ob) { int txl,txh,tyl,tyh,radius = 0x70000,x,y,tile; objtype*temp; statobj_t*tstat; txl = ((ob->x - radius)>>TILESHIFT); tyl = ((ob->y - radius)>>TILESHIFT); txh = ((ob->x + radius)>>TILESHIFT); tyh = ((ob->y + radius)>>TILESHIFT); if (txl < 1) txl = 1; if (txh > MAPSIZE-1) txh = MAPSIZE-1; if (tyl < 1) tyl = 1; if (tyh > MAPSIZE-1) tyh = MAPSIZE-1; for(x=txl; x<=txh; x++) for(y=tyl; y<=tyh; y++) { temp = (objtype*)actorat[x][y]; if (temp && (temp->which == ACTOR) && (temp->flags & FL_SHOOTABLE) && (temp != ob) && (temp->obclass < roboguardobj) && (temp->flags & FL_ABP) ) { DamageThing(temp,100); if ((temp->hitpoints<=0) && (temp->obclass < roboguardobj)) { MISCVARS->supergibflag = true; temp->flags |= FL_HBM; } Collision(temp,ob,0,0); MISCVARS->supergibflag = false; if ((temp->obclass == playerobj) && (temp->flags & FL_DYING)) BATTLE_PlayerKilledPlayer(battle_kill_with_missile,ob->dirchoosetime,temp->dirchoosetime); } tile = tilemap[x][y]; if ((tile & 0x4000) && (tile & 0x8000)) { maskedwallobj_t * mw; mw=maskobjlist[tile&0x3ff]; if ((mw->flags & MW_SHOOTABLE) && (mw->flags & MW_ABP)) UpdateMaskedWall(tile&0x3ff); } tstat = sprites[x][y]; if (tstat && (tstat->flags & FL_SHOOTABLE) && (tstat->flags & FL_ABP)) DamageThing(tstat,50); } } /* void DogBlast(objtype*ob) { int txl,txh,tyl,tyh,radius = 0x70000,x,y,tile; objtype*temp; statobj_t*tstat; txl = ((ob->x - radius)>>TILESHIFT); tyl = ((ob->y - radius)>>TILESHIFT); txh = ((ob->x + radius)>>TILESHIFT); tyh = ((ob->y + radius)>>TILESHIFT); if (txl < 1) txl = 1; if (txh > MAPSIZE-1) txh = MAPSIZE-1; if (tyl < 1) tyl = 1; if (tyh > MAPSIZE-1) tyh = MAPSIZE-1; for(x=txl;x<=txh;x++) for(y=tyl;y<=tyh;y++) { temp = (objtype*)actorat[x][y]; if (temp && (temp->which == ACTOR) && (temp->flags & FL_SHOOTABLE) && (temp != ob) && (temp->obclass < roboguardobj)) { DamageThing(temp,100); if ((temp->hitpoints<=0) && (temp->obclass < roboguardobj)) { MISCVARS->supergibflag = true; temp->flags |= FL_HBM; } Collision(temp,ob,0,0); MISCVARS->supergibflag = false; if ((temp->obclass == playerobj) && (temp->flags & FL_DYING)) BATTLE_PlayerKilledPlayer(battle_kill_with_missile,ob->dirchoosetime,temp->dirchoosetime); } tile = tilemap[x][y]; if ((tile & 0x4000) && (tile & 0x8000)) { maskedwallobj_t * mw; mw=maskobjlist[tile&0x3ff]; if (mw->flags & MW_SHOOTABLE) UpdateMaskedWall(tile&0x3ff); } tstat = sprites[x][y]; if (tstat && (tstat->flags & FL_SHOOTABLE)) DamageThing(tstat,50); } } */ void BatBlast(objtype*ob) { int angle; playertype *pstate; M_LINKSTATE(ob,pstate); angle = ob->angle - ANGLES/8 + ((++pstate->batblast)*ANGLES/48); Fix(angle); #if (SHAREWARE == 0) SpawnMissile(ob,p_bazookaobj,0x6000,angle,&s_batblast1,0xa000); #endif } void BatAttack(objtype*ob) { objtype *temp,*temp2; objtype *grenadetarget; statobj_t*tstat; int dx,dy,dz,angle,momx,momy,op,magangle; int tilexlow,tilexhigh; int tileylow,tileyhigh; int radius =0x10000; int x,y; SD_PlaySoundRTP(SD_EXCALISWINGSND,ob->x,ob->y); for(temp=firstareaactor[ob->areanumber]; temp; temp=temp->nextinarea) { if (temp == ob) continue; if (temp->flags & FL_DYING) continue; if ((temp->obclass != grenadeobj) && (!((temp->obclass >= grenadeobj) && (temp->obclass <= p_godballobj))) && (!(temp->flags & FL_SHOOTABLE) || (temp->obclass >= roboguardobj)) ) continue; dx = abs(temp->x - ob->x); dy = abs(temp->y - ob->y); dz = abs(temp->z - ob->z); if ((dx > 0x10000) || (dy > 0x10000) || (dz > 20)) continue; magangle = abs(ob->angle - AngleBetween(ob,temp)); if (magangle > VANG180) magangle = ANGLES - magangle; if (magangle > ANGLES/8) continue; angle= ob->angle+ANGLES/16; Fix(angle); if ((temp->obclass >= grenadeobj) && (temp->obclass <= p_godballobj)) { temp->angle += ANGLES/2; Fix(temp->angle); temp->momentumx = temp->momentumy = temp->momentumz = 0; ParseMomentum(temp,temp->angle); temp->whatever = ob; temp->target = NULL; continue; } else if (temp->obclass != grenadeobj) { momx = FixedMul(0x3000l,costable[angle]); momy = -FixedMul(0x3000l,sintable[angle]); if (levelheight > 2) { op = FixedMul(GRAVITY,(maxheight-100)<<16) << 1; temp->momentumz = -FixedSqrtHP(op); } temp->flags |= FL_NOFRICTION; SD_PlaySoundRTP(SD_EXCALIHITSND,ob->x,ob->y); if ((gamestate.violence == vl_excessive) && (GameRandomNumber("Bat Gibs",0) < 150)) { temp->flags |= FL_HBM; DamageThing(temp,50); } else DamageThing(temp,10); if ((temp->flags & FL_HBM) && (temp->hitpoints > 0)) temp->flags &= ~FL_HBM; Collision(temp,ob,momx,momy); if ((temp->obclass == blitzguardobj) && (temp->state == &s_blitzplead7)) { temp->shapeoffset += deathshapeoffset[temp->obclass]; temp->flags |= FL_ALTERNATE; NewState(temp,&s_blitzdie3); temp->momentumx = temp->momentumy = 0; } } else // find target to hit grenade back at { int rand; rand = GameRandomNumber("bat/grenade target",0); if (rand < 80) { grenadetarget = (objtype*)(temp->whatever); // hit back at george GetMomenta(grenadetarget,ob,&(temp->momentumx),&(temp->momentumy),&(temp->momentumz),0x3000); } else if (rand < 160) // hit back at first eligible { for(temp2 = firstareaactor[ob->areanumber]; temp2; temp2 = temp2->nextinarea) { magangle = abs(ob->angle-AngleBetween(ob,temp2)); if (magangle > VANG180) magangle = ANGLES - magangle; if (magangle > ANGLES/8) continue; GetMomenta(temp2,ob,&(temp->momentumx),&(temp->momentumy),&(temp->momentumz),0x3000); break; } } else // hit wherever { ob->angle += (rand >> 1); Fix(ob->angle); ob->momentumx = ob->momentumy = 0; ParseMomentum(ob,ob->angle); } temp->temp1 = 0x70000; NewState(temp,&s_grenade1); } break; } for(tstat=firstactivestat; tstat; tstat=tstat->statnext) { if (!(tstat->flags & FL_SHOOTABLE)) continue; dx = abs(tstat->x - ob->x); dy = abs(tstat->y - ob->y); dz = abs(tstat->z - ob->z); if ((dx > 0xc000) || (dy > 0xc000) || (dz > 20)) continue; magangle = abs(ob->angle - AngleBetween(ob,(objtype*)tstat)); if (magangle > VANG180) magangle = ANGLES - magangle; if (magangle > ANGLES/8) continue; DamageThing(tstat,50); } tilexlow = (int)((ob->x-radius) >>TILESHIFT); tileylow = (int)((ob->y-radius) >>TILESHIFT); tilexhigh = (int)((ob->x+radius) >>TILESHIFT); tileyhigh = (int)((ob->y+radius) >>TILESHIFT); for (y=tileylow; y<=tileyhigh; y++) for (x=tilexlow; x<=tilexhigh; x++) { if ((tilemap[x][y]&0x8000) && (tilemap[x][y]&0x4000)) { maskedwallobj_t * mw; mw=maskobjlist[tilemap[x][y]&0x3ff]; if (mw->flags&MW_SHOOTABLE) UpdateMaskedWall(tilemap[x][y]&0x3ff); } } } void AutoTargetHorizon(objtype *ob) { int dx,dy,angle,mindist,magangle, xydist,dz; objtype *temp; playertype * pstate; M_LINKSTATE(ob,pstate); mindist = 0x7fffffff; for(temp = firstactive; temp; temp=temp->nextactive) { if (temp == ob) continue; if ((!(temp->flags & FL_SHOOTABLE)) || (temp->flags & FL_DYING)) continue; if (!CheckLine(ob,temp,SHOOT)) continue; dx = temp->x-ob->x; dy = ob->y-temp->y; dz = ob->z-temp->z;//-pstate->playerheight+32; xydist = FindDistance(dx,dy); if (abs(dz<<10)>xydist) continue; angle = atan2_appx(dx,dy); magangle = ob->angle - angle; Fix(magangle); if ( (magangle>=(ANGLESDIV8/4)) && (magangle<=(FINEANGLES-(ANGLESDIV8/4))) ) { continue; } if (xydist < mindist) { mindist = xydist; pstate->guntarget=temp; temp->flags |= FL_TARGET; pstate->targettime=oldpolltime+(VBLCOUNTER); } } } void GunAttack (objtype *ob) { playertype * pstate; int damage; M_LINKSTATE(ob,pstate); MISCVARS->madenoise = true; switch (pstate->weapon) { case wp_pistol: SD_PlaySoundRTP(SD_ATKPISTOLSND,ob->x,ob->y); damage=DMG_PISTOL; break; case wp_mp40: SD_PlaySoundRTP(SD_ATKMP40SND,ob->x,ob->y); damage=DMG_MP40; break; case wp_twopistol: SD_PlaySoundRTP(SD_ATKTWOPISTOLSND,ob->x,ob->y); damage=DMG_PISTOL; break; } if(autoAim) AutoTargetHorizon(ob); RayShoot (ob, damage, (characters[pstate->player].accuracy+gamestate.difficulty)<<3); } /* =============== = = Cmd_Fire = =============== */ void Cmd_Fire (objtype*ob) { playertype *pstate; M_LINKSTATE(ob,pstate); // pstate->buttonheld[bt_attack] = true; if (pstate->NETCAPTURED && (!pstate->HASKNIFE)) return; if (W_CHANGE(pstate)) return; pstate->attackframe = 0; if ((ob==player) && (pstate->weapon < wp_mp40) && (!pstate->NETCAPTURED)) gamestate.DODEMOCRATICBONUS1 = false; if (!pstate->NETCAPTURED) { if (pstate->weapon <= wp_mp40) NewState(ob,&s_pgunattack1); #if (SHAREWARE == 0) else if ((pstate->weapon == wp_bat) && (pstate->batblast >= BBTIME)) { pstate->batblast = 0; NewState(ob,&s_pbatblast); } else if (pstate->weapon == wp_dog) NewState(ob,&s_serialdogattack); #endif else NewState(ob,&s_pmissattack1); #if (SHAREWARE == 0) if ((pstate->weapon == wp_dog) && (!ob->momentumz)) ob->momentumz = -0x50000; #endif pstate->attackcount = WEAPONS[pstate->weapon].attackinfo[0].mtics; pstate->weaponframe = WEAPONS[pstate->weapon].attackinfo[0].frame; } else if (pstate->NETCAPTURED == 1) { NewState(player,&s_free); pstate->attackcount = FREE.attackinfo[0].mtics; pstate->weaponframe = FREE.attackinfo[0].frame; } } void PlayNoWaySound ( void ) { if (player->flags & FL_DOGMODE) SD_Play(SD_DOGMODEBITE2SND); else if ((locplayerstate->player == 1) || (locplayerstate->player == 3)) SD_Play(SD_PLAYERTBHURTSND); else SD_Play(SD_NOWAYSND); } /* =============== = = Cmd_Use = =============== */ boolean AreJumping = false;//bna added int oldzval; int donttilt=0; void Cmd_Use (objtype*ob) { int checkx,checky,doorn, /*newtilex,newtiley,oldtilex,oldtiley,*/elevnum, wallx,wally; // statobj_t* tempsprite=NULL; objtype* tempactor= NULL; doorobj_t* tempdoor=NULL; pwallobj_t* temppwall=NULL; wall_t* tempwall=NULL; int index; playertype * pstate; M_LINKSTATE(ob,pstate); #if (SHAREWARE == 0) if ((pstate->weapon == wp_dog) && (ob->state != &s_doguse) && (ob->state != &s_dogwait) && (!W_CHANGE(pstate)) ) { pstate->attackframe = 0; NewState(ob,&s_doguse); pstate->attackcount = DOGSCRATCH.attackinfo[0].mtics; pstate->weaponframe = DOGSCRATCH.attackinfo[0].frame; ob->momentumz = -0x40000; return; } else #endif if ((ob->flags & FL_DESIGNATED) && (BATTLEMODE) && (gamestate.battlemode == battle_Tag)) { NewState(ob,&s_tag); //return; } // // find which cardinal direction the player is facing // if (ob->angle < FINEANGLES/8 || ob->angle > 7*FINEANGLES/8) { checkx = ob->tilex + 1; checky = ob->tiley; ob->dir = east; wallx = (checkx << TILESHIFT); wally = (checky << TILESHIFT) + TILEGLOBAL/2; } else if (ob->angle < 3*FINEANGLES/8) { checkx = ob->tilex; checky = ob->tiley-1; ob->dir = north; wally = (checky << TILESHIFT) + TILEGLOBAL; wallx = (checkx << TILESHIFT) + TILEGLOBAL/2; } else if (ob->angle < 5*FINEANGLES/8) { checkx = ob->tilex - 1; checky = ob->tiley; ob->dir = west; wallx = (checkx << TILESHIFT) + TILEGLOBAL; wally = (checky << TILESHIFT) + TILEGLOBAL/2; } else { checkx = ob->tilex; checky = ob->tiley + 1; ob->dir = south; wally = (checky << TILESHIFT); wallx = (checkx << TILESHIFT) + TILEGLOBAL/2; } if (actorat[checkx][checky]) { tempdoor=(doorobj_t*)actorat[checkx][checky]; tempactor = (objtype*)actorat[checkx][checky]; tempwall = (wall_t*)actorat[checkx][checky]; } doorn = tilemap[checkx][checky] & ~0x2000; // if (sprites[checkx][checky]) // tempsprite = sprites[checkx][checky]; if (doorn == (elevatorstart + 6)) return; //bna ++ jumpmode //SetTextMode ( ); if (!BATTLEMODE) { //dont use jump in battle, spoils sync if (usejump == true) { if (pstate->buttonheld[bt_use]) { if ((AreJumping == false)&&(ob->z > 0)&&(doorn==0)) { oldzval = ob->z; ob->z -= 15; ob->momentumz += GRAVITY; AreJumping = true; donttilt=10; return; } AreJumping = false; return; } } } //bna if (pstate->buttonheld[bt_use]) return; if (doorn == (elevatorstart + 1)) { tilemap[checkx][checky]++; // flip switch if (MAPSPOT(ob->tilex,ob->tiley,1) == ALTELEVATORTILE); // playstate = ex_secretlevel; else if (ob==player) playstate = ex_completed; } else if (doorn == (elevatorstart + 5)) { elevnum = MAPSPOT(ob->tilex,ob->tiley,1) - 90; tempwall->flags |= FL_S_FLIPPED; OperateElevatorSwitch(ob,elevnum,checkx,checky); } else if (tempdoor && tempdoor->which==PWALL) { temppwall=(pwallobj_t *)tempdoor; OperatePushWall (temppwall->num,ob->dir, ob == player ); } else if ((doorn&0x8000) && (!(doorn&0x4000))) { doorobj_t* dptr = doorobjlist[doorn&0x3ff]; int dnum = doorn&0x3ff; int lock; OperateDoor (pstate->keys, dnum, (ob == player)); if (dptr->eindex != -1) { elevator_t*eptr; lock = dptr->lock; if ( lock && !( pstate->keys & ( 1 << ( lock - 1 ) ) ) ) { if (ob==player) { // locked switch (lock) { case 1: AddMessage("You need the \\EGOLD key",MSG_DOOR); break; case 2: AddMessage("You need the \\FSILVER key",MSG_DOOR); break; case 3: AddMessage("You need the \\8IRON key",MSG_DOOR); break; case 4: AddMessage("You need the \\AOSCURO key",MSG_DOOR); break; default: AddMessage("This door appears to be locked",MSG_DOOR); break; } SD_Play( SD_NOITEMSND ); } return; } eptr = &ELEVATOR[dptr->eindex]; if (((dnum == eptr->door1) && (eptr->state == ev_rad)) || ((dnum == eptr->door2) && (eptr->state == ev_ras)) ) if (ob == player) AddMessage("Elevator is on the way.",MSG_GAME); OperateElevatorDoor(dnum); } } else if ((tempactor) && (tempactor->which == ACTOR) && (tempactor->obclass == pillarobj) && DISTOK(ob->x,tempactor->x,TD) && DISTOK(ob->y,tempactor->y,TD) && (!(tempactor->flags & FL_DONE)) && (!MAPSPOT(tempactor->tilex,tempactor->tiley,2)) ) { if ((tempactor->dir == nodir) || (tempactor->dir == ob->dir)) { if (tempactor->dir == nodir) { tempactor->dir = ob->dir; ParseMomentum(tempactor,dirangle8[tempactor->dir]); } SD_PlaySoundRTP ( SD_PUSHWALLSND, tempactor->x, tempactor->y ); tempactor->flags |= FL_ACTIVE; tempactor->flags |= FL_FLIPPED; // MakeActive(tempactor); tempactor->whatever = ob; gamestate.secretcount++; } } else if ((tempwall) && (tempwall->which == WALL) && (tempwall->flags & FL_SWITCH) ) { tempwall->flags |= FL_S_FLIPPED; if ((tempwall->flags & FL_W_INVERTED) && DISTOK(ob->x,wallx,TD) && DISTOK(ob->y,wally,TD) && DISTOK(ob->z,0,32) ) { index = touchindices[checkx][checky]-1; if (!(tempwall->flags & FL_ON)) { maskobjlist[tilemap[checkx][checky]&0x3ff]->toptexture++; tempwall->flags |= FL_ON; TRIGGER[index] = 1; SD_PlaySoundRTP(SD_TOUCHPLATESND,ob->x,ob->y); if (ob==player) AddMessage("Switch turned on.",MSG_GAME); } else if (tempwall->flags & FL_REVERSIBLE) { maskobjlist[tilemap[checkx][checky]&0x3ff]->toptexture--; tempwall->flags &= ~FL_ON; TRIGGER[index] = 1; SD_PlaySoundRTP(SD_TOUCHPLATESND,ob->x,ob->y); if (ob==player) AddMessage("Switch turned off.",MSG_GAME); } } else if (DISTOK(ob->x,wallx,TD) && DISTOK(ob->y,wally,TD) && !(tempwall->flags & FL_W_INVERTED) ) { index = touchindices[checkx][checky]-1; if (!(tempwall->flags & FL_ON)) { tilemap[checkx][checky]++; tempwall->flags |= FL_ON; TRIGGER[index] = 1; SD_PlaySoundRTP(SD_TOUCHPLATESND,ob->x,ob->y); if (ob==player) AddMessage("Switch turned on.",MSG_GAME); } else if (tempwall->flags & FL_REVERSIBLE) { tilemap[checkx][checky]--; tempwall->flags &= ~FL_ON; TRIGGER[index] = 1; SD_PlaySoundRTP(SD_TOUCHPLATESND,ob->x,ob->y); if (ob==player) AddMessage("Switch turned off.",MSG_GAME); } } } else if ((tempwall) && (tempwall->which == WALL) && (ob==player)) { PlayNoWaySound(); //bna ++ jumpmode //SetTextMode ( ); if (!BATTLEMODE) { //dint use jump in battle, spoils sync if (usejump == true) { if (pstate->buttonheld[bt_use]) { if ((AreJumping == false)&&(ob->z > 0)&&(doorn==0)) { oldzval = ob->z; ob->z -= 15; ob->momentumz += GRAVITY; AreJumping = true; donttilt=10; return; } AreJumping = false; return; } } } //bna } // else // SD_PlaySoundRTP (SD_NOWAYSND,ob->x,ob->y); // pstate->buttonheld[bt_use] = true; } /* ============================================================================= USER CONTROL ============================================================================= */ //****************************************************************************** // // PollKeyboardButtons // //****************************************************************************** void PollKeyboardButtons (void) { int i; QueueLetterInput (); IN_UpdateKeyboard(); for (i = 0; i < NUMBUTTONS; i++) { if (Keystate[buttonscan[i]]) { buttonpoll[i] = true; } } } //****************************************************************************** // // PollMouseButtons // //****************************************************************************** extern boolean usemouselook; void PollMouseButtons (void) { int i; int buttons; int mask; int press; buttons = IN_GetMouseButtons(); mask = 1; for( i = 0; i < 3; i++, mask <<= 1 ) { press = buttons & mask; if ( press ) { //SetTextMode ( ); // if ( ( buttonmouse[ i ] != bt_nobutton ) && // ( DoubleClickCount[ i ] != 2 ) ) if ( buttonmouse[ i ] != bt_nobutton ) { buttonpoll[ buttonmouse[ i ] ] = true; //bna added if ((i == 1)&&(usemouselook == true)) { //if rightclick set horizon to 512 (normall) playertype * pstate; pstate=&PLAYERSTATE[consoleplayer]; pstate->horizon = 512; // SetNormalHorizon(PLAYER[0]); } //bna added } } // Check double-click if ( buttonmouse[ i + 3 ] != bt_nobutton ) { if ( press ) { // Was the button pressed last tic? if ( !DoubleClickPressed[ i ] ) { // Yes, take note of it DoubleClickPressed[ i ] = true; // Is this the first click, or a really late click? if ( ( DoubleClickCount[ i ] == 0 ) || ( GetTicCount() >= DoubleClickTimer[ i ] ) ) { // Yes, now wait for a second click DoubleClickTimer[ i ] = GetTicCount() + DoubleClickSpeed; //( tics << 5 ); DoubleClickCount[ i ] = 1; } else { // Second click buttonpoll[ buttonmouse[ i + 3 ] ] = true; DoubleClickTimer[ i ] = 0; DoubleClickCount[ i ] = 2; } } else { // After second click, button remains pressed // until user releases it if ( DoubleClickCount[ i ] == 2 ) { buttonpoll[ buttonmouse[ i + 3 ] ] = true; } } } else { if ( DoubleClickCount[ i ] == 2 ) { DoubleClickCount[ i ] = 0; } DoubleClickPressed[ i ] = false; } } } } //****************************************************************************** // // PollJoystickButtons // //****************************************************************************** void PollJoystickButtons ( void ) { int i; int buttons; int mask; int num; int press; buttons = IN_JoyButtons (); if ( joypadenabled ) { num = 4; mask = 1; } else { num = 2; if ( joystickport ) { mask = 4; } else { mask = 1; } } for( i = 0; i < num; i++, mask <<= 1 ) { press = buttons & mask; if ( press ) { // if ( ( buttonjoy[ i ] != bt_nobutton ) && // ( JoyDblClickCount[ i ] != 2 ) ) if ( buttonjoy[ i ] != bt_nobutton ) { buttonpoll[ buttonjoy[ i ] ] = true; } } // Check double-click if ( buttonjoy[ i + 4 ] != bt_nobutton ) { if ( press ) { // Was the button pressed last tic? if ( !JoyDblClickPressed[ i ] ) { // Yes, take note of it JoyDblClickPressed[ i ] = true; // Is this the first click, or a really late click? if ( ( JoyDblClickCount[ i ] == 0 ) || ( GetTicCount() >= JoyDblClickTimer[ i ] ) ) { // Yes, now wait for a second click JoyDblClickTimer[ i ] = GetTicCount() + DoubleClickSpeed; //( tics << 5 ); JoyDblClickCount[ i ] = 1; } else { // Second click buttonpoll[ buttonjoy[ i + 4 ] ] = true; JoyDblClickTimer[ i ] = 0; JoyDblClickCount[ i ] = 2; } } else { // After second click, button remains pressed // until user releases it if ( JoyDblClickCount[ i ] == 2 ) { buttonpoll[ buttonjoy[ i + 4 ] ] = true; } } } else { if ( JoyDblClickCount[ i ] == 2 ) { JoyDblClickCount[ i ] = 0; } JoyDblClickPressed[ i ] = false; } } } } //=========================================================================== //****************************************************************************** // // PollKeyboardMove // //****************************************************************************** void PollKeyboardMove ( void ) { if ( ( buttonpoll[ bt_turnaround ] ) && ( turnaround == 0 ) ) { turnaround = 1; turnaroundtime = 15 + tics; turnheldtime = 0; } if ( turnaround == 0 ) { if ( buttonpoll[ di_east ] ) { turnheldtime+=tics; if (turnheldtime>=TURBOTURNTIME) { KX = -KEYBOARDNORMALTURNAMOUNT; } else { KX = -KEYBOARDPREAMBLETURNAMOUNT; } } else if ( buttonpoll[ di_west ] ) { turnheldtime+=tics; if (turnheldtime>=TURBOTURNTIME) { KX = KEYBOARDNORMALTURNAMOUNT; } else { KX = KEYBOARDPREAMBLETURNAMOUNT; } } else { KX = 0; turnheldtime=0; } if ( (buttonpoll[bt_run]) && ( (turnheldtime>=TURBOTURNTIME) || (turnheldtime==0) ) ) KX = FixedMul(KX,TURBOTURNAMOUNT); } else { KX=TURNAROUNDSPEED; turnaroundtime-=tics; if (turnaroundtime<=0) { turnaround=0; KX=((turnaroundtime*TURNAROUNDSPEED)>>1); } } if ( buttonpoll[ di_north ] ) { KY = -BASEMOVE; } else if ( buttonpoll[ di_south ] ) { KY = BASEMOVE; } else KY = 0; if (buttonpoll[bt_run]) { KY <<= 1; } } //****************************************************************************** // // PollMouseMove // //****************************************************************************** //#define MOUSE_RY_SHIFT 12 //#define MOUSE_TZ_SHIFT 3 #define MOUSE_TZ_SENSITIVITY_SCALE 65535 #define MOUSE_RY_SENSITIVITY_SCALE 18725*2 //#define MOUSE_RY_INPUT_SCALE 6000 #define MOUSE_TZ_INPUT_SCALE 20 int mouse_ry_input_scale = 5000; int sensitivity_scalar[15] = { 0,1,2,3,4,5,6,8,11,13,15,18,12,13,14 }; //#define MOUSE_RY_SCALE 65535 //#define MOUSE_TZ_SCALE 65535 #define MAXMOUSETURN 7000000 /* use SDL mouse */ #define USESDLMOUSE 1 extern int inverse_mouse; double Y_MouseSpeed=70; void PollMouseMove (void) { int mousexmove, mouseymove; double Ys; //SetTextMode(); Ys=(Y_MouseSpeed/100); // // const long inverse_mouse = 1; //set to -1 to invert mouse // inverse_mouse def moved to RT_CFG.C #ifdef USESDLMOUSE INL_GetMouseDelta(&mousexmove, &mouseymove); #else PollMouse();//Uses DirectInput mouse in DInput.cpp mousexmove=MX; mouseymove=MY; #endif if (abs(mousexmove)>abs(mouseymove)) mouseymove/=2; else mousexmove/=2; MX = 0; MY = 0; if ((abs (mouseymove)) >= threshold) { // MY = MOUSE_TZ_INPUT_SCALE*mouseymove; MY *= inverse_mouse; if (usemouselook == true) { if (MY > 0) { playertype * pstate; pstate=&PLAYERSTATE[consoleplayer]; //if (pstate->horizon > 512){ pstate->horizon -= Ys * (2*sensitivity_scalar[mouseadjustment]); //} } else if (MY < 0) { playertype * pstate; pstate=&PLAYERSTATE[consoleplayer]; //SetTextMode ( ); pstate->horizon += Ys * (2*sensitivity_scalar[mouseadjustment]); //buttonpoll[ bt_horizonup ] = true; } MY = 0; } else { // MY += FixedMul(MY,mouseadjustment*MOUSE_TZ_SENSITIVITY_SCALE); if (abs(mouseymove)>200) { buttonpoll[bt_run]=true; // buttonpoll[ bt_lookup ] = true; } } } if ((abs (mousexmove)) >= threshold) { //MX = -MOUSE_RY_INPUT_SCALE*mousexmove; MX = -mouse_ry_input_scale*mousexmove; MX += FixedMul(MX,sensitivity_scalar[mouseadjustment]*MOUSE_RY_SENSITIVITY_SCALE); // if (abs(MX) > MAXMOUSETURN) // MX = MAXMOUSETURN*SGN(MX); if (usemouselook == true) { if (abs(mouseymove)>10) { buttonpoll[bt_run]=true; //buttonpoll[ bt_lookdown ] = true; } } } // if (MY > 0) // MX -= (MX/2); // MX=0; // MY=0; } //****************************************************************************** // // PollJoystickMove // //****************************************************************************** void PollJoystickMove (void) { int joyx,joyy; INL_GetJoyDelta (joystickport, &joyx, &joyy); if ( joypadenabled ) { if (joyx >= threshold) { buttonpoll[ di_east ] = true; } if (-joyx >= threshold) { buttonpoll[ di_west ] = true; } if ( joyy >= threshold ) { buttonpoll[ di_south ] = true; } if ( -joyy >= threshold ) { buttonpoll[ di_north ] = true; } } else { if ((abs (joyx)) >= threshold) { JX = ((-joyx)<<13)+((-joyx)<<11); turnheldtime += tics; } else JX = 0; if ((abs (joyy)) >= threshold) { JY = joyy<<4; } else JY = 0; if (buttonpoll[bt_run]) { JX <<= 1; JY <<= 1; } } } //****************************************************************************** // // PollMove () // //****************************************************************************** boolean aimbuttonpressed=false; extern boolean allowMovementWithMouseYAxis; void PollMove (void) { int angle; int x, y; x = KX + MX + JX + CX + VX; y = KY + MY + JY + CY + VY; if (buttonpoll[bt_aimbutton]) { if (y>0) { buttonpoll[bt_horizonup]=1; y=0; aimbuttonpressed=true; } else if (y<0) { buttonpoll[bt_horizondown]=1; y=0; aimbuttonpressed=true; } else if (aimbuttonpressed==false) { buttonpoll[bt_lookup]=1; buttonpoll[bt_lookdown]=1; } } else { aimbuttonpressed=false; } if (!allowMovementWithMouseYAxis) { y = KY + JY + CY + VY; } //kill any movement if (aimbuttonpressed) { y = 0; } if (player->flags & FL_FLEET) y += y>>1; if ((locplayerstate->NETCAPTURED == 1) && (!locplayerstate->HASKNIFE)) { if (first) { nettics = GetTicCount() + (VBLCOUNTER * 4); first = 0; } if (x > 0) { rightmom += NETMOM; if (lastmom!=0) controlbuf[2]=x<<1; lastmom=0; } else if (x < 0) { leftmom += NETMOM; if (lastmom!=1) controlbuf[2]=x<<1; lastmom=1; } else { rightmom -= (NETMOM >> 2); if (rightmom < 0) rightmom = 0; leftmom -= (NETMOM >> 2); if (leftmom < 0) leftmom = 0; } if ((GetTicCount() > nettics) && (rightmom > (NETMOM * 2)) && (leftmom > (NETMOM * 2))) { rightmom = 0; leftmom = 0; first = 1; lastmom^=1; locplayerstate->NETCAPTURED = 0; MISCVARS->NET_IN_FLIGHT = false; NewState(player, &s_player); locplayerstate->weaponuptics = WEAPONS[locplayerstate->weapon].screenheight/GMOVE; locplayerstate->weaponheight = locplayerstate->weaponuptics*GMOVE ; } } else if ((buttonpoll[bt_strafe]) && (turnaround==0)) { // strafing if (x < 0) { angle = (player->angle - FINEANGLES/4)&(FINEANGLES-1); x = (x>>10) + (x >> 11); controlbuf[0] = -(FixedMul (x, costable[angle])); controlbuf[1] = FixedMul (x, sintable[angle]); } else if (x > 0) { angle = (player->angle + FINEANGLES/4)&(FINEANGLES-1); x = (x>>10) + (x >> 11); controlbuf[0] = FixedMul (x, costable[angle]); controlbuf[1] = -(FixedMul (x, sintable[angle])); } if (y != 0) { controlbuf[0] += -(FixedMul (y, viewcos)); controlbuf[1] += (FixedMul (y, viewsin)); } } else { if (y != 0) { controlbuf[0] = -FixedMul (y, viewcos); controlbuf[1] = FixedMul (y, viewsin); } if (x != 0) controlbuf[2] = x; } if (buttonpoll[bt_strafeleft]) { angle = (player->angle - FINEANGLES/4)&(FINEANGLES-1); controlbuf[0] += -(FixedMul (STRAFEAMOUNT, costable[angle])); controlbuf[1] += FixedMul (STRAFEAMOUNT, sintable[angle]); } else if (buttonpoll[bt_straferight]) { angle = (player->angle + FINEANGLES/4)&(FINEANGLES-1); controlbuf[0] += -(FixedMul (STRAFEAMOUNT, costable[angle])); controlbuf[1] += FixedMul (STRAFEAMOUNT, sintable[angle]); } } //****************************************************************************** // // PollControls // // Gets user or demo input, call once each frame // // controlx set between -100 and 100 per tic // controly // //****************************************************************************** void PollControls (void) { int i; if (standalone==true) return; lastpolltime=controlupdatetime; memset (buttonpoll, 0, sizeof(buttonpoll)); controlbuf[0] = controlbuf[1] = controlbuf[2] = 0; //if (gamestate.autorun==1) //buttonpoll[bt_run] = true; // // get button states // PollKeyboardButtons (); if (gamestate.autorun == 1) { if (buttonpoll[bt_run]) { buttonpoll[bt_run] = false; } else { buttonpoll[bt_run] = true; } } if (mouseenabled) PollMouseButtons (); if (joystickenabled) PollJoystickButtons (); // // get movements // if (joystickenabled) PollJoystickMove (); else if (mouseenabled && MousePresent) PollMouseMove (); PollKeyboardMove (); PollMove (); buttonbits = 0; if (player->flags & FL_DYING) // Player has died { if ((playerdead==true) && ( buttonpoll[ bt_strafe ] || buttonpoll[ bt_attack ] || buttonpoll[ bt_use ] || ((gamestate.battlemode == battle_Hunter) && (BATTLE_Team[player->dirchoosetime] == BATTLE_It) ) ) ) { AddRespawnCommand(); } memset (buttonpoll, 0, sizeof(buttonpoll)); controlbuf[0] = controlbuf[1] = controlbuf[2] = 0; } if ((PausePressed==true) && (modemgame==false)) { PausePressed=false; if (GamePaused==true) AddPauseStateCommand(COM_UNPAUSE); else { AddPauseStateCommand(COM_PAUSE); } } if (Keyboard[sc_Insert] && Keyboard[sc_X]) { AddExitCommand(); } //bna section if (Keyboard[sc_5]) { // SetTextMode ( ); weaponscale += 1000; //testval++; } if (Keyboard[sc_6]) { // SetTextMode ( ); weaponscale -= 1000; // testval--; } //bna section end for (i = (NUMTXBUTTONS-1); i >= 0; i--) { buttonbits <<= 1; if (buttonpoll[i]) buttonbits |= 1; } UpdateClientControls(); } void ResetWeapons(objtype *ob) { playertype *pstate; M_LINKSTATE(ob,pstate); pstate->weapondowntics = WEAPONS[pstate->weapon].screenheight/GMOVE; pstate->new_weapon = pstate->oldweapon; pstate->missileweapon = pstate->oldmissileweapon; ob->shapeoffset = pstate->oldshapeoffset; pstate->attackframe = pstate->weaponframe = 0; if ((ob==player) && SHOW_BOTTOM_STATUS_BAR() ) DrawBarAmmo (false); } void SaveWeapons(objtype*ob) { playertype *pstate; if ((ob->flags&FL_DOGMODE) || (ob->flags&FL_GODMODE)) return; //pstate = (ob==player)?(&playerstate):(&remoteplayerstate); M_LINKSTATE(ob,pstate); pstate->weapondowntics = WEAPONS[pstate->weapon].screenheight/GMOVE; pstate->oldweapon = pstate->new_weapon; pstate->oldmissileweapon = pstate->missileweapon; pstate->oldshapeoffset = ob->shapeoffset; } /* void SaveWeapons(objtype*ob) {playertype *pstate; if ((ob->flags&FL_DOGMODE) || (ob->flags&FL_GODMODE)) return; //pstate = (ob==player)?(&playerstate):(&remoteplayerstate); M_LINKSTATE(ob,pstate); pstate->weapondowntics = WEAPONS[pstate->weapon].screenheight/GMOVE; pstate->oldweapon = pstate->weapon; pstate->oldmissileweapon = pstate->missileweapon; pstate->oldshapeoffset = ob->shapeoffset; } */ #define GiveProtection(flag,time,sound) \ { \ if ((ob->flags & flag) || (ob->flags & FL_GODMODE) || \ (ob->flags & FL_DOGMODE)) \ return; \ ob->flags &= ~(FL_BPV|FL_GASMASK|FL_AV); \ ob->flags |= flag; \ SD_PlaySoundRTP(sound,ob->x, ob->y); \ pstate->protectiontime = time; \ gamestate.supercount ++; \ } boolean GivePowerup(objtype *ob,int flag,int time,int sound) { playertype *pstate; if ((ob->flags & flag) || (ob->flags & FL_GODMODE) || (ob->flags & FL_DOGMODE) ) return false; M_LINKSTATE(ob,pstate); /* if (ob->flags & FL_DOGMODE) { ob->temp2 = DOGMODERISE; ResetWeapons(ob); if (ob->state->condition & SF_DOGSTATE) NewState(ob,&s_player); } else if (ob->flags & FL_GODMODE) { ob->temp2 = GODMODEFALL; ResetWeapons(ob); } */ ob->flags &= ~(FL_SHROOMS|FL_FLEET|FL_ELASTO|FL_GODMODE|FL_DOGMODE); ob->flags |= flag; pstate->poweruptime = time; pstate->soundtime = 0; SD_PlaySoundRTP(sound,ob->x, ob->y); gamestate.supercount ++; return true; } void GiveLifePoints(objtype *ob,int points) { SD_PlaySoundRTP(SD_GETBONUSSND,ob->x, ob->y); UpdateTriads (ob,points); if (ob==player) DrawTriads (false); } boolean GiveBulletWeapon(objtype *ob,int bulletweapon,statobj_t*check) { playertype *pstate; M_LINKSTATE(ob,pstate); if ((ob->flags & FL_DOGMODE) || (ob->flags & FL_GODMODE)) return false; if (!ARMED(ob->dirchoosetime)) return false; if (pstate->HASBULLETWEAPON[bulletweapon]) return false; GiveWeapon(ob,bulletweapon); if ( gamestate.BattleOptions.WeaponPersistence ) { LASTSTAT->z = check->z; } SD_PlaySoundRTP(SD_GETWEAPONSND,ob->x, ob->y); return true; } inline boolean DetermineAmmoPickup(playertype *pstate, statobj_t *check) { if ((GetWeaponForItem(check->itemnumber) == pstate->missileweapon) && (pstate->ammo < stats[check->itemnumber].ammo)) { return true; } else { return false; } } extern boolean enableAmmoPickups; boolean wasAmmoPickup = false; boolean GivePlayerMissileWeapon(objtype *ob, playertype *pstate, statobj_t *check) { if ((ob->flags & FL_DOGMODE) || (ob->flags & FL_GODMODE)) return false; if (!ARMED(ob->dirchoosetime)) return false; if ((GetWeaponForItem(check->itemnumber) == pstate->missileweapon) && (check->ammo == stats[check->itemnumber].ammo) && (pstate->ammo == stats[check->itemnumber].ammo) ) return false; else if ((GetWeaponForItem(check->itemnumber) == pstate->missileweapon) && (check->ammo == stats[check->itemnumber].ammo) && (pstate->ammo >= stats[check->itemnumber].ammo) ) return false; //LT added, this bit here handles ammo pickups if that option's enabled if (enableAmmoPickups && DetermineAmmoPickup(pstate, check)) { wasAmmoPickup = true; GivePlayerAmmo(ob, check, GetWeaponForItem(check->itemnumber)); if ((ob==player) && SHOW_BOTTOM_STATUS_BAR() ) DrawBarAmmo (false); SD_PlaySoundRTP(SD_GETWEAPONSND,ob->x, ob->y); return true; } else if ((GetWeaponForItem(check->itemnumber) == pstate->missileweapon) && (pstate->ammo >= check->ammo) && enableAmmoPickups) return false; SD_PlaySoundRTP(SD_GETWEAPONSND,ob->x, ob->y); GiveMissileWeapon(ob,GetWeaponForItem(check->itemnumber)); if (gamestate.BattleOptions.WeaponPersistence) LASTSTAT->z = check->z; gamestate.missilecount ++; if (BATTLEMODE && (gamestate.BattleOptions.Ammo != bo_normal_shots)) { if (gamestate.BattleOptions.Ammo == bo_one_shot) pstate->ammo = 1; else pstate->ammo = -1; } else pstate->ammo = check->ammo; if ((ob==player) && SHOW_BOTTOM_STATUS_BAR() ) DrawBarAmmo (false); return true; } #define LocalBonusMessage(string) \ { \ if (ob == player) \ AddMessage(string,MSG_BONUS); \ } #define LocalBonus1Message(string) \ { \ if (ob == player) \ AddMessage(string,MSG_BONUS1); \ } /* ================================= = = GetBonusTimeForItem = ================================= */ int GetBonusTimeForItem(int itemnumber) { specials *which; if ( BATTLEMODE ) { which = &gamestate.SpecialsTimes; } else { which = &CurrentSpecialsTimes; } switch(itemnumber) { case stat_godmode: return which->GodModeTime; case stat_dogmode: return which->DogModeTime; case stat_mushroom: return which->ShroomsModeTime; case stat_elastic: return which->ElastoModeTime; case stat_asbesto: return which->AsbestosVestTime; case stat_bulletproof: return which->BulletProofVestTime; case stat_gasmask: return which->GasMaskTime; case stat_fleetfeet: return which->MercuryModeTime; } return -1; } /* ================================= = = GetRespawnTimeForItem = ================================= */ int GetRespawnTimeForItem(int itemnumber) { switch(itemnumber) { case stat_godmode: return gamestate.SpecialsTimes.GodModeRespawnTime; case stat_dogmode: return gamestate.SpecialsTimes.DogModeRespawnTime; case stat_mushroom: return gamestate.SpecialsTimes.ShroomsModeRespawnTime; case stat_elastic: return gamestate.SpecialsTimes.ElastoModeRespawnTime; case stat_asbesto: return gamestate.SpecialsTimes.AsbestosVestRespawnTime; case stat_bulletproof: return gamestate.SpecialsTimes.BulletProofVestRespawnTime; case stat_gasmask: return gamestate.SpecialsTimes.GasMaskRespawnTime; case stat_fleetfeet: return gamestate.SpecialsTimes.MercuryModeRespawnTime; } return gamestate.BattleOptions.RespawnTime * VBLCOUNTER; } /* =================== = = GetBonus = =================== */ void GetBonus (objtype*ob,statobj_t *check) { int heal; playertype * pstate; boolean randompowerup; M_LINKSTATE(ob,pstate); randompowerup=false; randomlabel: switch (check->itemnumber) { case stat_knifestatue: SD_PlaySoundRTP(SD_GETKNIFESND,ob->x, ob->y); if (ob==player) locplayerstate->HASKNIFE = 1; SD_PlaySoundRTP(PlayerSnds[locplayerstate->player], ob->x, ob->y); LocalBonusMessage("You found a knife."); break; case stat_pedgoldkey: LocalBonusMessage("You found the \\EGold key."); goto keys; case stat_pedsilverkey: LocalBonusMessage("You got the \\FSilver key."); goto keys; case stat_pedironkey: LocalBonusMessage("You got the \\8Iron key."); goto keys; case stat_pedcrystalkey: LocalBonusMessage("You got the \\4Oscuro key."); keys: GiveKey (check->itemnumber - stat_pedgoldkey); SD_PlaySoundRTP (SD_GETKEYSND,ob->x, ob->y); break; case stat_monkmeal: if (pstate->health == MaxHitpointsForCharacter(pstate)) return; SD_PlaySoundRTP (SD_GETHEALTH1SND,ob->x, ob->y); LocalBonusMessage("You ate some Monk Meal."); HealPlayer (10,ob); gamestate.healthcount ++; break; case stat_monkcrystal1: if (pstate->health == MaxHitpointsForCharacter(pstate)) return; SD_PlaySoundRTP (SD_GETHEALTH2SND,ob->x, ob->y); LocalBonusMessage("You picked up a small Monk Crystal."); HealPlayer (10,ob); gamestate.healthcount ++; break; case stat_monkcrystal2: if (pstate->health == MaxHitpointsForCharacter(pstate)) return; SD_PlaySoundRTP (SD_GETHEALTH2SND,ob->x, ob->y); LocalBonusMessage("You picked up a large Monk Crystal."); HealPlayer (50,ob); gamestate.healthcount ++; break; case stat_priestporridge: if (pstate->health == MaxHitpointsForCharacter(pstate)) return; SD_PlaySoundRTP (SD_GETHEALTH1SND,ob->x, ob->y); if (check->flags & FL_ACTIVE) { HealPlayer (50,ob); LocalBonusMessage("You ate some Priest Porridge Hot."); } else { HealPlayer (20,ob); LocalBonusMessage("You ate some Priest Porridge."); } gamestate.healthcount ++; break; case stat_healingbasin: if (pstate->health == MaxHitpointsForCharacter(pstate)) return; SD_PlaySoundRTP (SD_GETHEALTH2SND,ob->x, ob->y); heal = 25 + (GameRandomNumber("GetBonus",0) >> 2); HealPlayer (heal,ob); LocalBonusMessage("You drank from the healing basin."); gamestate.healthcount ++; gamestate.democraticcount ++; break; case stat_oneup: if (abs(pstate->health - MaxHitpointsForCharacter(pstate)) < (MaxHitpointsForCharacter(pstate)>>2) ) { GiveLives(1); LocalBonusMessage("Extra Life!"); } else { HealPlayer(MaxHitpointsForCharacter(pstate),ob); LocalBonusMessage("Full Health!"); } SD_PlaySoundRTP(SD_GET1UPSND,ob->x, ob->y); break; case stat_threeup: if (abs(pstate->health - MaxHitpointsForCharacter(pstate)) < (MaxHitpointsForCharacter(pstate)>>2) ) { GiveLives(3); LocalBonusMessage("Three Extra Lives!"); } else { HealPlayer(MaxHitpointsForCharacter(pstate),ob); GiveLives(2); LocalBonusMessage("Full Health AND Two Extra Lives!"); } SD_PlaySoundRTP(SD_GET3UPSND,ob->x, ob->y); break; case stat_scotthead: // Give Apogee's phone number as points GivePoints( 2764331 ); LocalBonusMessage( "Whoa...Scott's Mystical Head!"); LocalBonus1Message( "You get 2,764,331 points!"); SD_PlaySoundRTP(SD_GETHEADSND,ob->x, ob->y); break; case stat_twopistol: if (GiveBulletWeapon(ob,wp_twopistol,check)==false) return; LocalBonusMessage("You got an extra pistol."); break; case stat_mp40: if (GiveBulletWeapon(ob,wp_mp40,check)==false) return; LocalBonusMessage("You picked up an MP40."); break; case stat_bazooka: if (GivePlayerMissileWeapon(ob,pstate,check)==false) return; if (wasAmmoPickup) { LocalBonusMessage("You bagged more Bazooka rounds!"); } else { LocalBonusMessage("You bagged a bazooka!"); } wasAmmoPickup = false; break; case stat_firebomb: if (GivePlayerMissileWeapon(ob,pstate,check)==false) return; if(wasAmmoPickup) { LocalBonusMessage("You got more Firebomb rounds!"); } else { LocalBonusMessage("You found a Firebomb!"); } wasAmmoPickup = false; break; case stat_heatseeker: if (GivePlayerMissileWeapon(ob,pstate,check)==false) return; if(wasAmmoPickup) { LocalBonusMessage("You got more Heatseeker rounds!"); } else { LocalBonusMessage("You have a Heat-seeker!"); } wasAmmoPickup = false; break; case stat_drunkmissile: if (GivePlayerMissileWeapon(ob,pstate,check)==false) return; if (wasAmmoPickup) { LocalBonusMessage("You recovered more Drunk missiles!"); } else { LocalBonusMessage("You recovered a Drunk Missile!"); } wasAmmoPickup = false; break; case stat_firewall: if (GivePlayerMissileWeapon(ob,pstate,check)==false) return; if(wasAmmoPickup) { LocalBonusMessage("You filched more FlameWalls!"); } else { LocalBonusMessage("You filched a FlameWall!"); } wasAmmoPickup = false; break; case stat_splitmissile: if (GivePlayerMissileWeapon(ob,pstate,check)==false) return; if (wasAmmoPickup) { LocalBonusMessage("You snagged more Split Missiles!"); } else { LocalBonusMessage("You snagged a Split Missile!"); } wasAmmoPickup = false; break; case stat_kes: if (GivePlayerMissileWeapon(ob,pstate,check)==false) return; if(wasAmmoPickup) { LocalBonusMessage("You got more Dark Staff rounds!"); } else { LocalBonusMessage("You wield the Dark Staff!"); } wasAmmoPickup = false; break; case stat_bat: if (GivePlayerMissileWeapon(ob,pstate,check)==false) return; if (wasAmmoPickup) { LocalBonusMessage("You got more bat blast rounds!"); } else { LocalBonusMessage("You picked up the Excalibat."); } wasAmmoPickup = false; break; case stat_lifeitem1: GiveLifePoints(ob,1); if (timelimitenabled) timelimit+=(VBLCOUNTER); break; case stat_lifeitem2: GiveLifePoints(ob,5); if (timelimitenabled) timelimit+=(2*VBLCOUNTER); break; case stat_lifeitem3: GiveLifePoints(ob,10); if (timelimitenabled) timelimit+=(5*VBLCOUNTER); break; case stat_lifeitem4: GiveLifePoints(ob,25); if (timelimitenabled) timelimit+=(10*VBLCOUNTER); break; case stat_random: switch (GameRandomNumber("GetBonus",0)>>6) { case 0: check->itemnumber=stat_godmode; break; case 1: check->itemnumber=stat_elastic; break; case 2: check->itemnumber=stat_dogmode; break; case 3: check->itemnumber=stat_mushroom; break; } randompowerup=true; LocalBonus1Message("Random powerup gives you . . ."); goto randomlabel; break; case stat_bulletproof: GiveProtection(FL_BPV, GetBonusTimeForItem(stat_bulletproof), SD_GETBVESTSND); LocalBonusMessage("Bulletproof Armor!"); goto drw; case stat_gasmask: GiveProtection(FL_GASMASK, GetBonusTimeForItem(stat_gasmask), SD_GETMASKSND); LocalBonusMessage("You put on a Gas Mask."); goto drw; case stat_asbesto: GiveProtection(FL_AV,GetBonusTimeForItem(stat_asbesto), SD_GETAVESTSND); LocalBonusMessage("Asbestos Armor! Oh so itchy!"); goto drw; case stat_elastic: if (GivePowerup(ob,FL_ELASTO,GetBonusTimeForItem(stat_elastic), SD_GETELASTSND) == false) return; LocalBonusMessage("Elasto Mode!"); ob->flags |= FL_NOFRICTION; goto drw; case stat_fleetfeet: if (GivePowerup(ob,FL_FLEET,GetBonusTimeForItem(stat_fleetfeet), SD_GETFLEETSND) == false) return; LocalBonus1Message("Mercury Mode!"); LocalBonusMessage("Press Look Up and Down to fly."); ob->flags &= ~FL_NOFRICTION; goto drw; case stat_mushroom: if (GivePowerup(ob,FL_SHROOMS,GetBonusTimeForItem(stat_mushroom), SD_GETSHROOMSSND) == false) return; LocalBonusMessage("Shrooms Mode!"); ob->flags &= ~FL_NOFRICTION; gamestate.democraticcount ++; goto drw; case stat_godmode: if (ob->flags & FL_GODMODE) return; if (!ARMED(ob->dirchoosetime)) return; ob->flags &= ~FL_NOFRICTION; if (ob->flags & FL_DOGMODE) { ob->temp2 = DOGMODERISE; ResetWeapons(ob); if (ob->state->condition & SF_DOGSTATE) NewState(ob,&s_player); } SaveWeapons(ob); SpawnNewObj(ob->tilex,ob->tiley,&s_flash1,inertobj); new->flags |= FL_ABP; new->x = new->drawx = ob->x; new->y = new->drawy = ob->y; MakeActive(new); new->z = ob->z; SetPlayerHorizon(pstate,GODYZANGLE); ob->flags &= ~(FL_GODMODE|FL_SHROOMS|FL_ELASTO|FL_FLEET|FL_DOGMODE); ob->flags |= FL_GODMODE; ob->temp2 = GODMODERISE; pstate->poweruptime = GetBonusTimeForItem(stat_godmode); pstate->soundtime = 0; GiveMissileWeapon(ob,wp_godhand); SD_PlaySoundRTP(SD_GETGODSND,ob->x, ob->y); gamestate.supercount ++; LocalBonusMessage("God Mode!"); goto drw; #if (SHAREWARE == 0) case stat_dogmode: if (ob->flags & FL_DOGMODE) return; if (!ARMED(ob->dirchoosetime)) return; ob->flags &= ~FL_NOFRICTION; if (ob->flags & FL_GODMODE) { ob->temp2 = GODMODEFALL; ResetWeapons(ob); } SaveWeapons(ob); ob->shapeoffset = 0; NewState(ob,&s_serialdog); SpawnNewObj(ob->tilex,ob->tiley,&s_flash1,inertobj); new->flags |= FL_ABP; new->x = new->drawx = ob->x; new->y = new->drawy = ob->y; MakeActive(new); new->z = ob->z; SetPlayerHorizon(pstate,DOGYZANGLE); ob->flags &= ~(FL_DOGMODE|FL_SHROOMS|FL_ELASTO|FL_FLEET|FL_GODMODE); ob->flags |= FL_DOGMODE; ob->temp2 = DOGMODEFALL; pstate->poweruptime = GetBonusTimeForItem(stat_dogmode); pstate->soundtime = 0; GiveMissileWeapon(ob,wp_dog); SD_PlaySoundRTP(SD_GETDOGSND,ob->x, ob->y); gamestate.supercount ++; LocalBonusMessage("Dog Mode!"); goto drw; #endif drw: if (ob==player) GM_DrawBonus (check->itemnumber); break; case stat_dipball1: case stat_dipball2: case stat_dipball3: SD_PlaySoundRTP(SD_GETBONUSSND,ob->x, ob->y); gamestate.dipballs++; LocalBonusMessage("You discovered a Developer Ball!"); break; case stat_collector: if (gamestate.battlemode==battle_CaptureTheTriad) { if (pstate->team == check->hitpoints) return; ob->flags |= FL_DESIGNATED; UpdateKills = true; LocalBonusMessage( "You picked up a triad! RUN!!!"); } else BATTLE_CheckGameStatus(battle_get_collector_item,ob->dirchoosetime); SD_PlaySoundRTP(SD_GETBONUSSND,ob->x, ob->y); break; #if (SHAREWARE == 0) case stat_mine: SpawnNewObj(check->tilex,check->tiley,&s_grexplosion1,inertobj); new->flags |= FL_ABP; new->whatever = check; new->temp2 = 100; MakeActive(new); SD_PlaySoundRTP(SD_EXPLODESND,check->x,check->y); break; #endif default: SD_PlaySoundRTP(SD_GETHEADSND,ob->x, ob->y); break; } //StartBonusFlash (); if (check->flags & FL_CHANGES) { switch (check->itemnumber) { case stat_pedgoldkey: case stat_pedsilverkey: case stat_pedironkey: case stat_pedcrystalkey: check->itemnumber = stat_emptypedestal; check->shapenum = stats[stat_emptypedestal].picnum; check->flags = stats[stat_emptypedestal].flags|FL_ABP; check->count = 0; check->numanims = 0; break; case stat_healingbasin: check->itemnumber = stat_emptybasin; check->shapenum = stats[stat_emptybasin].picnum; check->flags = stats[stat_emptybasin].flags|FL_ABP; check->count = 0; check->numanims = 0; break; /* case stat_tablebullets: check->itemnumber = stat_emptytable; check->shapenum = stats[stat_emptytable].picnum; check->flags = stats[stat_emptytable].flags|FL_ABP; break; case stat_statuewithpole: check->itemnumber = stat_armornopole; check->shapenum = stats[stat_armornopole].picnum; check->flags = stats[stat_armornopole].flags|FL_ABP; break; */ case stat_pit: check->shapenum ++; check->flags &= ~FL_CHANGES; check->flags &= ~FL_BONUS; break; case stat_knifestatue: check->itemnumber = stat_emptystatue; check->shapenum = stats[stat_emptystatue].picnum; check->flags = stats[stat_emptystatue].flags|FL_ABP; break; default: ; } } else { if (check == sprites[check->tilex][check->tiley]) { statobj_t *checkstat; checkstat = (statobj_t*)DiskAt(check->tilex,check->tiley); if (checkstat && (checkstat->which == SPRITE)) sprites[check->tilex][check->tiley] = checkstat; else sprites[check->tilex][check->tiley] = NULL; } if (randompowerup==true) check->itemnumber = stat_random; RemoveStatic(check); } } /* =================== = = DropWeapon = =================== */ void DropWeapon(objtype *ob) { playertype *pstate; int dtilex,dtiley; M_LINKSTATE(ob,pstate); if ((pstate->missileweapon == -1) || (pstate->missileweapon == wp_godhand) #if (SHAREWARE == 0) || (pstate->missileweapon == wp_dog) #endif ) return; pstate->weapondowntics = WEAPONS[pstate->weapon].screenheight/3; pstate->new_weapon = pstate->bulletweapon; dtilex = ob->tilex; dtiley = ob->tiley; FindEmptyTile(&dtilex, &dtiley); SpawnStatic(dtilex,dtiley,GetItemForWeapon(pstate->missileweapon),9); gamestate.missiletotal ++; LASTSTAT->ammo = pstate->ammo; LASTSTAT->flags |= FL_ABP; LASTSTAT->flags &= ~FL_RESPAWN; MakeStatActive(LASTSTAT); pstate->weaponx = ob->tilex; pstate->weapony = ob->tiley; pstate->ammo = -1; pstate->missileweapon = -1; if ((ob==player) && SHOW_BOTTOM_STATUS_BAR() ) DrawBarAmmo (false); } /* =================== = = Thrust = =================== */ void Thrust ( objtype * ob ) { statobj_t *tstat; int dx,dy,dz,rad,index,otherteam; objtype*temp; playertype * pstate; PlayerMove(ob); M_LINKSTATE(ob,pstate); if ((gamestate.battlemode == battle_CaptureTheTriad) && (ob->flags & FL_DESIGNATED) && (ob->tilex == TEAM[pstate->team].tilex) && (ob->tiley == TEAM[pstate->team].tiley)) { if (ob == player) SD_Play(PlayerSnds[locplayerstate->player]); if (BATTLE_CheckGameStatus(battle_captured_triad,ob->dirchoosetime)== battle_no_event) { ob->flags &= ~FL_DESIGNATED; UpdateKills = true; otherteam = (pstate->team ^ 1); SpawnStatic(TEAM[otherteam].tilex,TEAM[otherteam].tiley,stat_collector,9); LASTSTAT->flags |= FL_COLORED; LASTSTAT->hitpoints = otherteam; LASTSTAT->flags |= FL_ABP; MakeStatActive(LASTSTAT); } return; } if ((ob->tilex != pstate->weaponx) || (ob->tiley != pstate->weapony)) pstate->weaponx = pstate->weapony = 0; index = touchindices[ob->tilex][ob->tiley]; if (index && (abs(ob->z - nominalheight) < 5)) { if (!TRIGGER[index-1]) { #if (BNACRASHPREVENT == 1) if (touchplate[index-1] != 0) { // CRASH IN SHAREWARE 'ride em cowboy' BNA FIX //SetTextMode ( ); qwert // DONT ALLOW BAD touchplate ( == 0 ) see rt_door.c #endif if (touchplate[index-1]->complete) SD_PlaySoundRTP(SD_BADTOUCHSND,ob->x,ob->y); else { SD_PlaySoundRTP(SD_TOUCHPLATESND,ob->x,ob->y); if (ob == player) AddMessage("Touchplate triggered.",MSG_GAME); } #if (BNACRASHPREVENT == 1) } else { SD_PlaySoundRTP(SD_BADTOUCHSND,ob->x,ob->y); } // CRASH IN SHAREWARE 'ride em cowboy' BNA FIX #endif } TRIGGER[index-1] = 1; } tstat = sprites[ob->tilex][ob->tiley]; if (tstat) { dx = abs(ob->x - tstat->x); dy = abs(ob->y - tstat->y); dz = abs(ob->z - tstat->z); if ((dx < 0x8000) && (dy < 0x8000) && (dz<=35)) { #define OBJECT_IS_BONUS( tstat ) ( ( tstat )->flags & FL_BONUS ) #define PLAYER_IS_SWITCHING_WEAPONS( pstate ) ( W_CHANGE( pstate ) ) //#define IS_ATTACKING( ob ) ( ( ( ob )->state->think == T_Attack ) || ( ( ob )->state->think == T_BatBlast ) ) #define IS_WEAPON( tstat ) ( ( tstat )->flags & FL_WEAPON ) #define PLAYER_MAY_NOT_GET_WEAPON( pstate, ob ) ( PLAYER_IS_SWITCHING_WEAPONS( pstate ))// || IS_ATTACKING( ob ) ) #define OK_TO_PICK_UP( tstat, pstate, ob ) ( !( IS_WEAPON( tstat ) && PLAYER_MAY_NOT_GET_WEAPON( pstate, ob ) ) ) #define WHERE_PLAYER_DROPPED_WEAPON( ob, pstate ) ( ( ( ob )->tilex == ( pstate )->weaponx ) && ( ( ob )->tiley == ( pstate )->weapony ) ) if ( OBJECT_IS_BONUS( tstat ) && OK_TO_PICK_UP( tstat, pstate, ob ) && (!WHERE_PLAYER_DROPPED_WEAPON( ob, pstate )) ) { GetBonus(ob,tstat); if (PLAYER_IS_SWITCHING_WEAPONS( pstate )) { statetype *nstate; #if (SHAREWARE == 0) if (ob->state->condition & SF_DOGSTATE) nstate = &s_serialdog; else #endif nstate = &s_player; pstate->attackframe = pstate->weaponframe = pstate->batblast = 0; NewState(ob,nstate); } } else if ((tstat->itemnumber == stat_pit) && (ob->temp2 != PITFALL) && (!(ob->flags & FL_FLEET)) ) { ob->temp2 = PITFALL; ob->momentumx = ob->momentumy = 0; //ob->momentumz = 4; ob->momentumz = GRAVITY; if (ob->whatever == NULL) { ob->whatever = tstat; SD_PlaySoundRTP(SD_PITTRAPSND,ob->x,ob->y); tstat->shapenum = stats[tstat->itemnumber].picnum + 1; MakeStatInactive(tstat); //tstat->flags &= ~FL_ABP; } } else if ((tstat->itemnumber == stat_heatgrate) && (!(ob->flags & FL_DYING)) && (!(ob->flags & FL_AV)) ) { DamageThing(ob,1); Collision(ob,(objtype*)tstat,0,0); M_CheckPlayerKilled(ob); } } } //================ Check special player/actor links ====================== if (ob->whatever) { temp = (objtype*)(ob->whatever); dx = abs(ob->x - temp->x); dy = abs(ob->y - temp->y); dz = abs(ob->z - temp->z); if (ob->flags & FL_RIDING) rad = MINACTORDIST; else rad = 0x8000; if ((dx >rad) || (dy > rad) || (dz > 64)) { if ((temp->obclass == bladeobj) || (temp->obclass == diskobj)) { temp->whatever = NULL; ob->flags &= ~FL_RIDING; } else if (ob->temp2 == COLUMNCRUSH) ob->temp2 = RENORMALIZE; else if (ob->z < nominalheight) ob->momentumz = 40000; else if (temp->which == SPRITE) { tstat = (statobj_t*)(ob->whatever); MakeStatActive(tstat); SetNormalHorizon(ob); } ob->whatever = NULL; } } //========================================================================= if (BATTLEMODE && (MAPSPOT(ob->tilex,ob->tiley,1) == EXITTILE)) { Move_Player_From_Exit_To_Start(ob); return; } if (ob==player) { if (MAPSPOT(ob->tilex,ob->tiley,1) == EXITTILE) playstate=ex_completed; else if ( ( MAPSPOT( ob->tilex, ob->tiley, 2 ) & 0xff00 ) == 0xe400 ) playstate = ex_secretdone; else if (MAPSPOT(ob->tilex,ob->tiley,1) == SECRETEXITTILE) playstate=ex_secretlevel; } } void Move_Player_From_Exit_To_Start(objtype *ob) { int i = 0,oldarea,newarea; objtype *tplayer; int travelangle,dangle; playertype *pstate; M_LINKSTATE(ob,pstate); oldarea = ob->areanumber; newarea = AREANUMBER(FIRST.x,FIRST.y); if (oldarea != newarea) { RemoveFromArea(ob); ob->areanumber = newarea; MakeLastInArea(ob); } SetTilePosition(ob,FIRST.x,FIRST.y); ob->z = PlatformHeight(ob->tilex,ob->tiley); if ((ob->z == -10) || DiskAt(ob->tilex,ob->tiley)) ob->z = 0; ConnectAreas(); travelangle = atan2_appx(ob->momentumx,ob->momentumy); dangle = ob->angle - travelangle; ob->angle = (1-FIRST.dir)*ANG90 + dangle; Fix(ob->angle); ob->dir = angletodir[ob->angle]; pstate->anglefrac= (ob->angle<<ANGLEBITS); pstate->angle=0; for(i=0; i<numplayers; i++) { tplayer = PLAYER[i]; if (ob == tplayer) continue; if ( (tplayer->tilex == FIRST.x) && (tplayer->tiley == FIRST.y) && (!(tplayer->flags & FL_DYING)) ) { playertype *pstate; M_LINKSTATE(tplayer,pstate); pstate->health = tplayer->hitpoints = 0; tplayer->flags |= FL_HBM; Collision(tplayer,ob,0,0); BATTLE_PlayerKilledPlayer(battle_kill_by_crushing,ob->dirchoosetime,tplayer->dirchoosetime); \ } } } void PlayerSlideMove(objtype * ob) { int tryx, tryy, tryz; tryx = ob->x + ob->momentumx; tryy = ob->y + ob->momentumy; tryz = ob->z + (ob->momentumz >> 16); if (ActorTryMove(ob,ob->x,tryy,tryz)) { if (ob->momentumx>HITWALLSPEED) SD_PlaySoundRTP(SD_HITWALLSND,ob->x,ob->y); ob->momentumx=0; } else if (ActorTryMove(ob,tryx,ob->y,tryz)) { if (ob->momentumy>HITWALLSPEED) SD_PlaySoundRTP(SD_HITWALLSND,ob->x,ob->y); ob->momentumy=0; } else { if (FindDistance(ob->momentumx,ob->momentumy)>(HITWALLSPEED*3/2)) SD_PlaySoundRTP(SD_HITWALLSND,ob->x,ob->y); ob->momentumx=0; ob->momentumy=0; } } /* =================== = = SetNormalHorizon = =================== */ void SetNormalHorizon (objtype * ob) { playertype * pstate; M_LINKSTATE(ob,pstate); if (ob->flags&FL_DOGMODE) { SetPlayerHorizon(pstate,DOGYZANGLE); } else if (ob->flags&FL_GODMODE) { SetPlayerHorizon(pstate,GODYZANGLE); } else { SetPlayerHorizon(pstate,NORMALYZANGLE); } } /* =================== = = PlayerTiltHead = =================== */ extern int iG_playerTilt; extern double dTopYZANGLELIMIT; void PlayerTiltHead (objtype * ob) { playertype * pstate; int dyz=0; int yzangle; //bna++ jumpmode if ((donttilt > 0)) { donttilt--; return; } M_LINKSTATE(ob,pstate); yzangle=ob->yzangle+HORIZONYZOFFSET; Fix(yzangle); if ( (pstate->lastmomz!=ob->momentumz) && (ob->momentumz==0) && ( (!(ob->flags&FL_FLEET)) || ( (ob->flags&FL_FLEET) && (ob->z==nominalheight) ) ) ) SetNormalHorizon(ob); pstate->lastmomz=ob->momentumz; if (ob->flags&FL_SHROOMS) { ob->yzangle = FixedMulShift(SHROOMYZANGLE,sintable[(oldpolltime<<6)&(FINEANGLES-1)],16); Fix(ob->yzangle); return; } else if (pstate->guntarget) { int dx,dy,dz; int xydist; int yzangle; dx = ob->x - pstate->guntarget->x; dy = ob->y - pstate->guntarget->y; xydist = FindDistance(dx,dy)-0x8000; if (ob->z==pstate->guntarget->z) dz = 0; else { dz = (ob->z-pstate->guntarget->z)<<10; } yzangle = atan2_appx(xydist,dz); yzangle += HORIZONYZOFFSET; Fix(yzangle); SetPlayerHorizon(pstate,yzangle-HORIZONYZOFFSET); if (oldpolltime>pstate->targettime) { if (pstate->guntarget) pstate->guntarget->flags &= ~FL_TARGET; pstate->guntarget=NULL; SetNormalHorizon(ob); } } else { if (pstate->buttonstate[bt_horizonup]) { if (yzangle!=pstate->horizon) { SetPlayerHorizon(pstate,yzangle-HORIZONYZOFFSET); } else { SetPlayerHorizon(pstate,(pstate->horizon-HORIZONYZOFFSET+YZHORIZONSPEED)); } } else if (pstate->buttonstate[bt_horizondown]) { if (yzangle!=pstate->horizon) { SetPlayerHorizon(pstate,yzangle-HORIZONYZOFFSET); } else { SetPlayerHorizon(pstate,(pstate->horizon-HORIZONYZOFFSET-YZHORIZONSPEED)); } } if (pstate->buttonstate[bt_lookup]) { if (!(ob->flags & FL_FLEET)) { dyz=YZTILTSPEED; if (pstate->buttonstate[bt_lookdown]) { dyz=0; } SetNormalHorizon(ob); } } if (pstate->buttonstate[bt_lookdown]) { if (!(ob->flags & FL_FLEET)) { dyz=-YZTILTSPEED; if (pstate->buttonstate[bt_lookup]) { dyz=0; } SetNormalHorizon(ob); } } if (!(ob->flags&FL_DOGMODE) && !(ob->flags&FL_GODMODE) && !(ob->flags&FL_FLEET) && !(ob->flags&FL_RIDING) && (ob->momentumz > (GRAVITY<<1))//(ob->momentumz>0x1000) ) { SetPlayerHorizon(pstate,FALLINGYZANGLE); } } if ((yzangle!=pstate->horizon) && (dyz==0)) { int speed; speed=SNAPBACKSPEED; if (yzangle<pstate->horizon) yzangle+=speed; else yzangle-=speed; if ((abs(yzangle-pstate->horizon))<SNAPBACKSPEED) yzangle=pstate->horizon; } //SetTextMode(); if (yzangle != 512) { FinddTopYZANGLELIMITvalue(ob); } yzangle+=dyz; if (yzangle-HORIZONYZOFFSET>YZANGLELIMIT) yzangle=HORIZONYZOFFSET+YZANGLELIMIT; /* else if (yzangle-HORIZONYZOFFSET<-TopYZANGLELIMIT)//bnafix yzangle=HORIZONYZOFFSET-TopYZANGLELIMIT;//bnafix dTopYZANGLELIMIT*/ else if (yzangle-HORIZONYZOFFSET<-dTopYZANGLELIMIT)//bnafix yzangle=HORIZONYZOFFSET-dTopYZANGLELIMIT;//bnafix ob->yzangle=yzangle-HORIZONYZOFFSET; Fix(ob->yzangle); iG_playerTilt = ob->yzangle; } //---------------------------------------------------------------------- // bna added function // if a player is to close to wall, looking down max //,this func limit the dTopYZANGLELIMIT value when // facing a wall #define SMALLANGLE 90 //there is small angles where didnt work //so we check for them to = 90/2048 = aprox, 15 degrees int FinddTopYZANGLELIMITvalue(objtype *ob) { /* checkx = ob->tilex + 1; checky = ob->tiley + 1; if (actorat[checkx][checky]){ return 0; } return 1; checkx = ob->tilex ; checky = ob->tiley; // find which direction the player is facing //and check if it is a wall */ //use lowest down angle dTopYZANGLELIMIT = (26*FINEANGLES/360); if (ob->angle < 256 || ob->angle > 1792) { if ((tilemap[ob->tilex + 1][ob->tiley])!=0) { return 0; } //ob->dir = east; } else if (ob->angle < 768) { if ((tilemap[ob->tilex][ob->tiley-1])!=0) { return 0; } } else if (ob->angle < 1280) { if ((tilemap[ob->tilex-1][ob->tiley])!=0) { return 0; } } else { if ((tilemap[ob->tilex][ob->tiley+1])!=0) { return 0; } } //use middle down angle dTopYZANGLELIMIT = (42*FINEANGLES/360); if ((ob->angle > 768-SMALLANGLE)&&(ob->angle <= 768)) { if ((tilemap[ob->tilex -1][ob->tiley])!=0) { //ob->tiley-1 return 0; } } if ((ob->angle < 1280+SMALLANGLE)&&(ob->angle >= 1280)) { if ((tilemap[ob->tilex - 1][ob->tiley])!=0) { //ob->tiley+1 return 0; } } if ((ob->angle > 256)&&(ob->angle <= 256+SMALLANGLE)) { if ((tilemap[ob->tilex + 1][ob->tiley])!=0) { //ob->tiley-1 return 0; } } if ((ob->angle < 1792)&&(ob->angle >= 1792-SMALLANGLE)) { if ((tilemap[ob->tilex + 1][ob->tiley])!=0) { //ob->tiley+1 return 0; } } if ((ob->angle < 1280)&&(ob->angle >= 1280-SMALLANGLE)) { if ((tilemap[ob->tilex ][ob->tiley+1])!=0) { //ob->tilex-1 return 0; } } if ((ob->angle > 1792)&&(ob->angle <= 1792+SMALLANGLE)) { if ((tilemap[ob->tilex ][ob->tiley+1])!=0) { //ob->tiley+1 return 0; } } if ((ob->angle > 768)&&(ob->angle <= 768+SMALLANGLE)) { if ((tilemap[ob->tilex][ob->tiley-1])!=0) { //ob->tiley-1 return 0; } } if ((ob->angle < 256)&&(ob->angle >= 256-SMALLANGLE)) { if ((tilemap[ob->tilex][ob->tiley-1])!=0) { //ob->tiley-1 return 0; } } //use max down angle dTopYZANGLELIMIT = (90*FINEANGLES/360); return 1; } // bna added function end //---------------------------------------------------------------------- /* =================== = = UpdatePlayers = =================== QWERTYU */ void UpdatePlayers ( void ) { objtype * obj; // playertype * pstate; for (obj = FIRSTACTOR; obj->obclass==playerobj; obj = obj->next) { //ErrorDontQuit("obj->next = ",obj->next); #if (BNACRASHPREVENT == 1)//crashed here when oscuro and larves were all killed if (obj->next == 0) { return; } #endif obj->speed=FindDistance(obj->momentumx, obj->momentumy); // M_LINKSTATE(obj,pstate); // pstate->steptime-=obj->speed; // if (pstate->steptime<0) // { // while (pstate->steptime<0) // pstate->steptime+=PLAYERSTEPTIME; // pstate->stepwhich^=1; // SD_PlaySoundRTP(SD_WALK1SND+pstate->stepwhich,obj->x,obj->y); // } } } /* =================== = = PlayerMove = =================== */ void PlayerMove ( objtype * ob ) { playertype *pstate; M_LINKSTATE(ob,pstate); if (ob->flags & FL_FLEET) CheckFlying(ob,pstate); ActorMovement(ob); pstate->anglefrac = (pstate->anglefrac+pstate->angle)&((FINEANGLES<<ANGLEBITS)-1); ob->angle = (pstate->anglefrac >> ANGLEBITS); ob->dir = angletodir[ob->angle]; if (ob==player) UpdateLightLevel(player->areanumber); PlayerTiltHead(ob); if (IsWindow(ob->tilex,ob->tiley)) { if (!(ob->flags & FL_DYING)) { pstate->health = 0; pstate->falling=true; if ((ob->flags & FL_GODMODE) || (ob->flags & FL_DOGMODE) || (gamestate.battlemode == battle_Eluder) || (godmode==true)) { KillActor(ob); NewState(ob,&s_remotedie1); } else Collision(ob,(objtype*)NULL,0,0); ob->flags |= FL_DYING; M_CheckPlayerKilled(ob); } } } /* =============== = = T_Tag = =============== */ void T_Tag (objtype *ob) { playertype *pstate; CheckPlayerSpecials(ob); //CheckWeaponStates(ob); M_LINKSTATE(ob,pstate); Thrust(ob); if (ob->ticcount > 4) pstate->weaponheight -= GMOVE; else pstate->weaponheight += GMOVE; if ((ob->ticcount > 1) && (ob->ticcount < 8) && (!(ob->flags & FL_DIDTAG))) { int i,dx,dy,magangle; for(i=0; i<numplayers; i++) { if (PLAYER[i] == ob) continue; dx = abs(PLAYER[i]->x - ob->x); dy = abs(PLAYER[i]->y - ob->y); if ((dx > 0xc000) || (dy > 0xc000)) continue; magangle = abs(ob->angle - AngleBetween(ob,PLAYER[i])); if (magangle > VANG180) magangle = ANGLES - magangle; if (magangle > ANGLES/8) continue; CheckTagGame(ob,PLAYER[i]); break; } } //Commented out until we find if it's valid /* if (!ob->ticcount) {if ( pstate->buttonstate[bt_use] && !pstate->buttonheld[bt_use] ) pstate->buttonstate[bt_use] = false; if ( pstate->buttonstate[bt_attack] && !pstate->buttonheld[bt_attack]) pstate->buttonstate[bt_attack] = false; } */ } #if (SHAREWARE == 0) #define GET_RESETSTATE(ob,resetstate) \ { \ if (ob->state->condition & SF_DOGSTATE) \ resetstate = &s_serialdog; \ else \ resetstate = &s_player; \ } #else #define GET_RESETSTATE(ob,resetstate) \ { \ resetstate = &s_player; \ } #endif /* =============== = = T_Attack = =============== */ void T_Attack (objtype *ob) { attack_t *cur; playertype *pstate; statetype *resetstate; Thrust(ob); if (ob->flags & FL_DYING) return; resetstate = ob->state; CheckPlayerSpecials(ob); if (resetstate != ob->state) { return; } if ((ob->flags & FL_PAIN) && (!ob->ticcount)) ob->flags &= ~FL_PAIN; CheckWeaponStates(ob); M_LINKSTATE(ob,pstate); GET_RESETSTATE(ob,resetstate); if (ARMED(ob->dirchoosetime) //(gamestate.battlemode != battle_Tag) ) { if (pstate->weapondowntics == 1) // change to up; during change, up and down // are never zero at the same time { #if (SHAREWARE == 0) if (pstate->weapon == wp_kes) { pstate->weapondowntics = 0; pstate->weaponuptics = KESTICS/(2*GMOVE); } else #endif { pstate->weapondowntics = 0; pstate->weaponframe = pstate->attackframe = 0; if (pstate->NETCAPTURED == -1) { pstate->weaponuptics = FREE.screenheight/GMOVE; pstate->weaponheight = pstate->weaponuptics*GMOVE ; pstate->NETCAPTURED = 1; // return; } else if (pstate->NETCAPTURED == -2) { pstate->weaponuptics = WEAPONS[pstate->weapon].screenheight/GMOVE; pstate->weaponheight = pstate->weaponuptics*GMOVE ; pstate->NETCAPTURED = 0; //return; } else { pstate->weaponuptics = WEAPONS[pstate->new_weapon].screenheight/GMOVE; pstate->weapon = pstate->new_weapon; pstate->weaponheight = pstate->weaponuptics*GMOVE ; } } } } else if (gamestate.battlemode == battle_Hunter) { if (pstate->weapondowntics == 1) { pstate->weapondowntics = 0; pstate->weaponframe = pstate->attackframe = pstate->batblast = 0; pstate->weapon = pstate->new_weapon; NewState(ob,resetstate); return; } } #if (SHAREWARE==0) if ((pstate->buttonstate[bt_use]) && (pstate->weapon != wp_dog) ) #else if (pstate->buttonstate[bt_use]) #endif Cmd_Use (ob); if (pstate->attackframe >= WEAPONS[pstate->weapon].numattacks) Error("\n attackframe %d for weapon %d gt numattacks %d", pstate->attackframe,pstate->weapon, WEAPONS[pstate->weapon].numattacks ); cur = &(WEAPONS[pstate->weapon].attackinfo[pstate->attackframe]); if (! pstate->attackcount) { switch (cur->attack) { case reset: ob->flags &= ~FL_FULLLIGHT; if (pstate->ammo) { if (BATTLEMODE && (pstate->weapon == wp_firewall)) break; if (BATTLEMODE && (pstate->weapon == wp_firebomb)) break; if ((pstate->buttonstate[bt_attack]) && (pstate->weapon <= wp_firewall)) { if (pstate->weapon <= wp_mp40) { if (pstate->weapon == wp_twopistol) pstate->attackframe -= 6; else if (pstate->weapon == wp_pistol) pstate->attackframe -= 3; else if (pstate->weapon == wp_mp40) pstate->attackframe -= 2; if (ob->state == &s_pmissattack2) NewState(ob,&s_pmissattack1); else if (ob->state == &s_pgunattack2) NewState(ob,&s_pgunattack1); } } else { NewState(ob,resetstate); pstate->attackframe = pstate->weaponframe = 0; pstate->batblast = 0; return; } } else { NewState(ob,resetstate); pstate->attackframe = pstate->weaponframe = 0; pstate->new_weapon = pstate->bulletweapon; pstate->batblast = 0; pstate->ammo = -1; pstate->missileweapon = -1; pstate->weapondowntics = WEAPONS[pstate->weapon].screenheight/GMOVE; if ((ob==player) && SHOW_BOTTOM_STATUS_BAR() ) DrawBarAmmo (false); return; } break; case reset2: ob->flags &= ~FL_FULLLIGHT; if (pstate->buttonstate[bt_attack] && pstate->ammo) { pstate->attackframe -= 4; if (ob->state == &s_pmissattack2) NewState(ob,&s_pmissattack1); else if (ob->state == &s_pgunattack2) NewState(ob,&s_pgunattack1); } else { NewState(ob,resetstate); pstate->attackframe = pstate->weaponframe = 0; pstate->batblast = 0; return; } break; case at_pulltrigger: ob->flags |= FL_FULLLIGHT; #if (SHAREWARE == 0) if (pstate->batblast >= BBTIME) DogBlast(ob); else if (pstate->weapon == wp_dog) DogAttack(ob); else if (pstate->weapon == wp_bat) BatAttack (ob); else #endif GunAttack(ob); break; case at_missileweapon: if (!pstate->ammo) { pstate->attackframe = pstate->weaponframe = 0; pstate->batblast = 0; return; } ob->flags |= FL_FULLLIGHT; if (ob==player) SetIllumination(2); PlayerMissileAttack(ob); if (!(ob->flags & FL_GODMODE) && !godmode) { if (!BATTLEMODE || (gamestate.BattleOptions.Ammo != bo_infinite_shots)) pstate->ammo--; if ((ob==player) && SHOW_BOTTOM_STATUS_BAR() ) DrawBarAmmo (false); } #if (SHAREWARE == 0) if (pstate->weapon == wp_kes) pstate->weapondowntics = KESTICS/(2*GMOVE); #endif break; default: ; } pstate->attackframe++; cur = &(WEAPONS[pstate->weapon].attackinfo[pstate->attackframe]); pstate->weaponframe = cur->frame; pstate->attackcount = cur->mtics; } else pstate->attackcount --; } /* =============== = = T_BatBlast = =============== */ void T_BatBlast (objtype *ob) { attack_t *cur; playertype *pstate; Thrust(ob); CheckPlayerSpecials(ob); M_LINKSTATE(ob,pstate); //Commented out until we find if it's valid /* if (!ob->ticcount) {if ( pstate->buttonstate[bt_use] && !pstate->buttonheld[bt_use] ) pstate->buttonstate[bt_use] = false; if ( pstate->buttonstate[bt_attack] && !pstate->buttonheld[bt_attack]) pstate->buttonstate[bt_attack] = false; } */ // // change frame and fire // BatBlast(ob); if (pstate->attackframe >= WEAPONS[pstate->weapon].numattacks) Error("\n attackframe %d for weapon %d gt numattacks %d", pstate->attackframe,pstate->weapon, WEAPONS[pstate->weapon].numattacks ); cur = &(WEAPONS[pstate->weapon].attackinfo[pstate->attackframe]); if (! pstate->attackcount) { if (cur->attack == reset) { if (!(ob->flags & FL_GODMODE) && (!godmode)) { pstate->ammo --; if ((ob==player) && SHOW_BOTTOM_STATUS_BAR() ) DrawBarAmmo (false); } if (!pstate->ammo) { pstate->new_weapon = pstate->bulletweapon; pstate->ammo = -1; pstate->missileweapon = -1; pstate->weapondowntics = WEAPONS[pstate->weapon].screenheight/GMOVE; } NewState(ob,&s_player); pstate->attackframe = pstate->weaponframe = 0; pstate->batblast = 0; return; } pstate->attackframe++; pstate->weaponframe = WEAPONS[pstate->weapon].attackinfo[pstate->attackframe].frame; cur = &(WEAPONS[pstate->weapon].attackinfo[pstate->attackframe]); pstate->attackcount = cur->mtics; } else pstate->attackcount --; } void T_Free (objtype *ob) { attack_t *cur; if (!ob->ticcount) { //Commented out until we find if it's valid /* if ( locplayerstate->buttonstate[bt_use] && !locplayerstate->buttonheld[bt_use] ) locplayerstate->buttonstate[bt_use] = false; if ( locplayerstate->buttonstate[bt_attack] && !locplayerstate->buttonheld[bt_attack]) locplayerstate->buttonstate[bt_attack] = false; */ Thrust(ob); } CheckPlayerSpecials(ob); cur = &(FREE.attackinfo[locplayerstate->attackframe]); if (!locplayerstate->attackcount) { if ((locplayerstate->weaponframe > 3) && (locplayerstate->weaponframe < 8)) locplayerstate->NETCAPTURED ++; else if (locplayerstate->weaponframe == 8) { locplayerstate->NETCAPTURED = -2; MISCVARS->NET_IN_FLIGHT = false; NewState(ob,&s_player); locplayerstate->weapondowntics = FREE.screenheight/GMOVE; return; } locplayerstate->attackframe++; cur = &(FREE.attackinfo[locplayerstate->attackframe]); locplayerstate->weaponframe = cur->frame; locplayerstate->attackcount = cur->mtics; } else locplayerstate->attackcount --; } void Switch_Who_Is_It_For_Tag(objtype *actor1,objtype *actor2) { playertype *pstate; M_LINKSTATE(actor1,pstate); if (pstate->buttonstate[bt_use]) { playertype *pstate2; M_LINKSTATE(actor2,pstate2); pstate2->oldmissileweapon = pstate2->oldweapon = pstate2->new_weapon = pstate2->missileweapon = pstate2->weapon = wp_godhand; pstate2->weaponheight = 144; pstate2->weaponuptics = (144 - TAGHANDHEIGHT)/GMOVE; pstate2->weapondowntics = 0; actor1->flags |= FL_DIDTAG; actor2->flags |= FL_DESIGNATED; UpdateKills = true; actor1->flags &= ~FL_DESIGNATED; BATTLE_PlayerKilledPlayer(battle_player_tagged, actor1->dirchoosetime, actor2->dirchoosetime); } } void CheckTagGame(objtype *actor1,objtype*actor2) { //if ((actor1->obclass != playerobj) || (actor2->obclass != playerobj)) //return; if (!BATTLEMODE) return; if (gamestate.battlemode != battle_Tag) return; SD_PlaySoundRTP(SD_GETBONUSSND,actor1->x,actor1->y); if (actor1->flags & FL_DESIGNATED) Switch_Who_Is_It_For_Tag(actor1,actor2); else if (actor2->flags & FL_DESIGNATED) Switch_Who_Is_It_For_Tag(actor2,actor1); } /* ====================== = = CheckWeaponChange = = Keys 1-4 change weapons = ====================== */ void CheckWeaponChange (objtype * ob) { // int i; playertype * pstate; M_LINKSTATE(ob,pstate); //pstate = (ob == player)?(&playerstate):(&remoteplayerstate); if (W_CHANGE(pstate)) return; if (!ARMED(ob->dirchoosetime)) return; if ((ob->flags & FL_DOGMODE) || (ob->flags & FL_GODMODE)) return; #if (WEAPONCHEAT==1) if (godmode && Keyboard[sc_Insert]) { SD_Play(SD_SELECTWPNSND); // FOR DEBUG only /* if (pstate->buttonstate[bt_run]) { if (pstate->weapon == 0) pstate->new_weapon = wp_bat; else pstate->new_weapon --; } else {*/ if (pstate->weapon == MAXWEAPONS-1) pstate->new_weapon = 0; else pstate->new_weapon ++; //} if (pstate->new_weapon <= wp_mp40) { pstate->bulletweapon = pstate->new_weapon; pstate->HASBULLETWEAPON[pstate->new_weapon] = 1; } else pstate->missileweapon = pstate->new_weapon; pstate->ammo = stats[GetItemForWeapon(pstate->missileweapon)].ammo; if (pstate->ammo<1) pstate->ammo=5; StartWeaponChange; //pstate->weapondowntics = WEAPONS[pstate->weapon].screenheight/GMOVE; //if ((ob==player) && SHOW_BOTTOM_STATUS_BAR() ) // DrawBarAmmo (false); } else if (pstate->buttonstate[bt_swapweapon]) #else if (pstate->buttonstate[bt_swapweapon]) #endif { if ((pstate->weapon == pstate->bulletweapon) && (pstate->missileweapon != -1)) { pstate->new_weapon = pstate->missileweapon; StartWeaponChange; } else if (pstate->weapon != pstate->bulletweapon) { pstate->new_weapon = pstate->bulletweapon; StartWeaponChange; } } else if ((pstate->buttonstate[bt_dropweapon]) && (!gamestate.BattleOptions.WeaponPersistence)) { if (pstate->weapon==pstate->bulletweapon) { if ((ob==player) && (!(pstate->buttonheld[bt_dropweapon]))) PlayNoWaySound(); } else { if (sprites[ob->tilex][ob->tiley]) { if ((ob==player) && (!(pstate->buttonheld[bt_dropweapon]))) PlayNoWaySound(); } else { DropWeapon(ob); } } } if (pstate->buttonstate[bt_pistol]) { if (pstate->weapon != wp_pistol) { pstate->new_weapon = pstate->bulletweapon = wp_pistol; StartWeaponChange; } } else if (pstate->buttonstate[bt_dualpistol]) { if ((pstate->weapon != wp_twopistol) && pstate->HASBULLETWEAPON[wp_twopistol]) { pstate->new_weapon = pstate->bulletweapon = wp_twopistol; StartWeaponChange; } } else if (pstate->buttonstate[bt_mp40]) { if ((pstate->weapon != wp_mp40) && pstate->HASBULLETWEAPON[wp_mp40]) { pstate->new_weapon = pstate->bulletweapon = wp_mp40; StartWeaponChange; } } else if (pstate->buttonstate[bt_missileweapon]) { if ((pstate->weapon != pstate->missileweapon) && (pstate->missileweapon != -1)) { pstate->new_weapon = pstate->missileweapon; StartWeaponChange; } } } void SetWhoHaveWeapons(void) { playertype *pstate; objtype *ob; int i; for ( i = 0; i < numplayers; i++ ) { ob = PLAYER[ i ]; M_LINKSTATE( ob, pstate ); if ( ARMED( ob->dirchoosetime )) { if (pstate->weapon == -1) { if (( pstate->missileweapon != -1 ) && (pstate->ammo>0)) pstate->new_weapon = pstate->missileweapon; else { if ( pstate->bulletweapon == -1 ) { pstate->HASBULLETWEAPON[ wp_pistol ] = 1; pstate->bulletweapon = wp_pistol; } pstate->new_weapon = pstate->bulletweapon; pstate->ammo = -1; } pstate->weapon = pstate->new_weapon; pstate->weapondowntics = 0; pstate->weaponuptics = WEAPONS[pstate->new_weapon].screenheight/GMOVE; pstate->weaponheight = pstate->weaponuptics*GMOVE ; pstate->attackframe = pstate->weaponframe = pstate->batblast = 0; if (i == consoleplayer) DrawBarAmmo(false); } } else { if (ob->flags & FL_DOGMODE) { ob->temp2 = DOGMODERISE; pstate->oldweapon = -1; ResetWeapons(ob); if (ob->state->condition & SF_DOGSTATE) NewState(ob,&s_player); } else if (ob->flags & FL_GODMODE) { ob->temp2 = GODMODEFALL; pstate->oldweapon = -1; ResetWeapons(ob); } else { pstate->new_weapon = -1; StartWeaponChange; } pstate->attackframe = pstate->weaponframe = pstate->batblast = 0; } } } void CheckWeaponStates(objtype*ob) { playertype *pstate; M_LINKSTATE(ob,pstate); if (gamestate.battlemode == battle_Tag) { if (pstate->weapondowntics) { pstate->weaponheight += GMOVE; pstate->weapondowntics --; if (!pstate->weapondowntics) pstate->weapon = pstate->missileweapon = pstate->bulletweapon = pstate->new_weapon = pstate->oldweapon = pstate->oldmissileweapon = -1; } if (pstate->weaponuptics) { pstate->weaponheight -= GMOVE; pstate->weaponuptics --; } return; } if (pstate->weapondowntics) { pstate->weaponheight += GMOVE; #if (SHAREWARE == 0) if ((pstate->weapon == wp_kes) && pstate->attackframe) pstate->weaponheight += GMOVE; #endif pstate->weapondowntics --; } else if (pstate->weaponuptics) { pstate->weaponheight -= GMOVE; #if (SHAREWARE == 0) if ((pstate->weapon == wp_kes) && pstate->attackframe) pstate->weaponheight -= GMOVE; #endif pstate->weaponuptics --; } else if ((pstate->weapon == pstate->new_weapon) && (!pstate->NETCAPTURED)) pstate->weaponheight = 0; } /* ============================= = = CheckSpecialSounds = ============================= */ #define REGDOGSTATE(ob) \ ((ob->state == &s_serialdog) || (ob->state == &s_serialdog2) || \ (ob->state == &s_serialdog3) || (ob->state == &s_serialdog4) \ ) static int dyingvolume=255; void CheckSpecialSounds(objtype *ob, playertype *pstate) { int shift; if ((!BATTLEMODE) && (ob == player)) { if (pstate->health < MaxHitpointsForCharacter(locplayerstate)/5) { pstate->healthtime ++; if (pstate->healthtime > 2*VBLCOUNTER) { pstate->healthtime = 0; SD_PlayPitchedSound ( SD_PLAYERDYINGSND, dyingvolume, 0 ); if (dyingvolume>80) dyingvolume-=40; } } else { dyingvolume=255; } } if (((ob->flags & FL_GODMODE) || (ob->flags & FL_DOGMODE)) && (!W_CHANGE(pstate)) ) { pstate->soundtime++; if (pstate->soundtime > (2*VBLCOUNTER)) { int rand; rand = GameRandomNumber("player special sound",0); shift = (pstate->soundtime>>5); if ((rand << shift) > 3500) { int sound; pstate->soundtime = 0; rand = GameRandomNumber("player god scare",0); if (ob->flags & FL_GODMODE) { sound = SD_GODMODE1SND; if (rand < 160) sound++; if (rand < 80) sound ++; SD_PlaySoundRTP(sound,ob->x,ob->y); } #if (SHAREWARE == 0) else if ((!pstate->batblast) && (!ob->momentumz) && (REGDOGSTATE(ob)) ) { sound = SD_DOGMODEPANTSND; if (rand < 128) sound += 2; NewState(ob,&s_doglick); pstate->attackframe = pstate->weaponframe = pstate->batblast = 0; SD_PlaySoundRTP(sound,ob->x,ob->y); } #endif } } } else if (ob->flags & FL_GASMASK) { pstate->soundtime ++; if (pstate->soundtime > (3*VBLCOUNTER)) { pstate->soundtime = 0; SD_PlaySoundRTP(SD_GASMASKSND,ob->x,ob->y); } } else if (MISCVARS->GASON) { pstate->soundtime ++; if (pstate->soundtime > (2*VBLCOUNTER)) { int rand; rand = GameRandomNumber("player cough sound",0); shift = (pstate->soundtime>>5); if ((rand << shift) > 2000) { pstate->soundtime = 0; if ((pstate->player == 1) || (pstate->player == 3)) SD_PlaySoundRTP(SD_PLAYERCOUGHFSND,ob->x,ob->y); else SD_PlaySoundRTP(SD_PLAYERCOUGHMSND,ob->x,ob->y); } } } } /* static int dyingvolume=255; void CheckSpecialSounds(objtype *ob, playertype *pstate) { int shift; if ((!BATTLEMODE) && (ob == player)) { if (pstate->health < MaxHitpointsForCharacter(locplayerstate)/5) { pstate->healthtime ++; if (pstate->healthtime > 2*VBLCOUNTER) { pstate->healthtime = 0; SD_PlayPitchedSound ( SD_PLAYERDYINGSND, dyingvolume, 0 ); if (dyingvolume>80) dyingvolume-=40; } } else { dyingvolume=255; } } if (((ob->flags & FL_GODMODE) || (ob->flags & FL_DOGMODE)) && (!W_CHANGE(pstate)) ) { pstate->soundtime++; if (pstate->soundtime > (2*VBLCOUNTER)) { int rand; rand = GameRandomNumber("player special sound",0); shift = (pstate->soundtime>>5); if ((rand << shift) > 3500) { int sound; pstate->soundtime = 0; rand = GameRandomNumber("player god scare",0); if (ob->flags & FL_GODMODE) { sound = SD_GODMODE1SND; if (rand < 160) sound++; if (rand < 80) sound ++; SD_PlaySoundRTP(sound,ob->x,ob->y); } #if (SHAREWARE == 0) else if (!pstate->batblast) { sound = SD_DOGMODEPANTSND; if (rand < 128) sound += 2; NewState(ob,&s_doglick); pstate->attackframe = pstate->weaponframe = pstate->batblast = 0; SD_PlaySoundRTP(sound,ob->x,ob->y); } #endif } } } else if (ob->flags & FL_GASMASK) { pstate->soundtime ++; if (pstate->soundtime > (3*VBLCOUNTER)) { pstate->soundtime = 0; SD_PlaySoundRTP(SD_GASMASKSND,ob->x,ob->y); } } else if (MISCVARS->GASON) { pstate->soundtime ++; if (pstate->soundtime > (2*VBLCOUNTER)) { int rand; rand = GameRandomNumber("player cough sound",0); shift = (pstate->soundtime>>5); if ((rand << shift) > 2000) { pstate->soundtime = 0; if ((pstate->player == 1) || (pstate->player == 3)) SD_PlaySoundRTP(SD_PLAYERCOUGHFSND,ob->x,ob->y); else SD_PlaySoundRTP(SD_PLAYERCOUGHMSND,ob->x,ob->y); } } } } */ /* ============================= = = CheckProtectionsAndPowerups = ============================= */ void CheckProtectionsAndPowerups(objtype *ob, playertype *pstate) { if (pstate->poweruptime) { pstate->poweruptime --; if (pstate->poweruptime < 0) pstate->poweruptime = 0; if (ob==player) GM_UpdateBonus (pstate->poweruptime, true); } else { if (ob->flags & FL_ELASTO) { ob->flags &= ~FL_NOFRICTION; if (ob==player) GM_UpdateBonus (pstate->poweruptime, true); SD_PlaySoundRTP(SD_LOSEMODESND,ob->x, ob->y); } else if (ob->flags & FL_GODMODE) { ob->temp2 = GODMODEFALL; if ((pstate->player == 1) || (pstate->player == 3)) SD_PlaySoundRTP(SD_GODWOMANSND,ob->x, ob->y); else SD_PlaySoundRTP(SD_GODMANSND,ob->x, ob->y); ResetWeapons(ob); } else if (ob->flags & FL_DOGMODE) { int wall; wall = tilemap[ob->tilex][ob->tiley]; if ((wall & 0x4000) && (wall & 0x8000)) { maskedwallobj_t * mw; mw=maskobjlist[wall&0x3ff]; if (mw->flags&MW_NONDOGBLOCKING) return; } ob->temp2 = DOGMODERISE; if ((pstate->player == 1) || (pstate->player == 3)) SD_PlaySoundRTP(SD_DOGWOMANSND,ob->x, ob->y); else SD_PlaySoundRTP(SD_DOGMANSND,ob->x, ob->y); ResetWeapons(ob); if (ob->state->condition & SF_DOGSTATE) { NewState(ob,&s_player); pstate->attackframe = pstate->weaponframe = pstate->batblast = 0; } } else if (ob->flags & FL_SHROOMS) { ResetFocalWidth (); SD_PlaySoundRTP(SD_LOSEMODESND,ob->x, ob->y); } else if (ob->flags & FL_FLEET) SD_PlaySoundRTP(SD_LOSEMODESND,ob->x, ob->y); ob->flags &= ~(FL_SHROOMS|FL_ELASTO|FL_FLEET|FL_GODMODE|FL_DOGMODE); } if (pstate->protectiontime) { pstate->protectiontime --; if (pstate->protectiontime <= 0) { SD_PlaySoundRTP(SD_LOSEMODESND,ob->x, ob->y); pstate->protectiontime = 0; } if (ob==player) GM_UpdateBonus (pstate->protectiontime, false); } else ob->flags &= ~(FL_BPV|FL_AV|FL_GASMASK); } /* ============================= = = CheckFlying = ============================= */ void CheckFlying(objtype*ob,playertype *pstate) { if (pstate->buttonstate[bt_lookup]) { ob->momentumz = -FLYINGZMOM; } if (pstate->buttonstate[bt_lookdown]) { ob->momentumz = FLYINGZMOM; } /* if (!M_ISDOOR(((ob->x + costable[ob->angle])>>16), ((ob->y - sintable[ob->angle])>>16)) && (pstate->buttonstate[bt_use]) && (!pstate->buttonheld[bt_use]) ) { int op; int dist; dist=JETPACKTHRUST; if (ob->z-dist<-15) dist=ob->z+15; if (dist>0) { op = FixedMul(GRAVITY,(dist<<16)) << 1; ob->momentumz = -FixedSqrtHP(op); SD_PlaySoundRTP(SD_FLYINGSND,ob->x,ob->y); } } */ } /* ============================= = = CheckTemp2Codes = ============================= */ #define IN_AIR(ob) \ (!((ob->z == nominalheight) || \ (IsPlatform(ob->tilex,ob->tiley)) || \ (DiskAt(ob->tilex,ob->tiley)) \ ) \ ) \ void CheckTemp2Codes(objtype *ob,playertype *pstate) { int pitheight; int godheight; int height; int oldz; int destheightoffset; pitheight = maxheight - 8; height = ob->z + pstate->playerheight; godheight = ob->z + GODOFFSET; //SoftError("\nheightoffset: %d, temp2: %d",pstate->heightoffset,ob->temp2); if (!((ob->temp2 == PITFALL) || (ob->temp2 == PITRISE))) { oldz = ob->z; //SoftError("\n zmom %d, oldz %d, newz %d",ob->momentumz,oldz,ob->z); if (ob->flags & FL_FLEET) { if (IN_AIR(ob)) pstate->heightoffset = FixedMulShift(0x4000,sintable[(oldpolltime<<6)&2047],28); ob->z += ((ob->momentumz+0x8000)>>16); ob->momentumz = 0; } else { ob->z += (ob->momentumz>>16); ob->momentumz += GRAVITY; } if (ob->z >= nominalheight) { ob->z = nominalheight; ob->momentumz = 0; //if (platform == nominalheight) //{//ob->temp2 = 0; //ob->momentumz = 0; if ((oldz < nominalheight) && (!(ob->flags & FL_RIDING))) { SD_PlaySoundRTP(SD_PLAYERLANDSND,ob->x,ob->y); } if (!(ob->flags & FL_ELASTO)) ob->flags &= ~FL_NOFRICTION; // } } else if (height < 1) { ob->momentumz = 0; ob->z = 1-pstate->playerheight; } switch (ob->temp2) { case RENORMALIZE: pstate->heightoffset --; if (ob->flags & FL_DOGMODE) destheightoffset = DOGOFFSET-pstate->playerheight; else destheightoffset = 0; if (pstate->heightoffset <= destheightoffset) { ob->temp2 = 0; pstate->heightoffset = 0; } pstate->oldheightoffset = pstate->heightoffset; break; case COLUMNCRUSH: pstate->heightoffset += 4; if (pstate->heightoffset >= 30) pstate->heightoffset = 30; pstate->oldheightoffset = pstate->heightoffset; break; case GODMODERISE: pstate->heightoffset --; pstate->oldheightoffset = pstate->heightoffset; if ((height+pstate->heightoffset) <= godheight) { ob->temp2 = 0; pstate->poweruptime = POWERUPTICS; } break; case GODMODEFALL: pstate->heightoffset ++; pstate->oldheightoffset = pstate->heightoffset; SetPlayerHorizon(pstate,NORMALYZANGLE); if (pstate->heightoffset >= 0) { ob->temp2 = 0; ob->flags &= ~FL_GODMODE; SetNormalHorizon(ob); } break; case DOGMODERISE: pstate->heightoffset --; pstate->oldheightoffset = pstate->heightoffset; SetPlayerHorizon(pstate,NORMALYZANGLE); if (pstate->heightoffset <= 0) { ob->temp2 = 0; ob->flags &= ~FL_DOGMODE; SetNormalHorizon(ob); } break; case DOGMODEFALL: pstate->heightoffset ++; pstate->oldheightoffset = pstate->heightoffset; if (pstate->heightoffset >= (DOGOFFSET-pstate->playerheight)) { ob->temp2 = 0; pstate->poweruptime = POWERUPTICS; } break; case STEPUP: //Debug("\n\n heightoffset adjusted from %d to %d", // pstate->heightoffset,pstate->heightoffset - STEPADJUST); pstate->heightoffset -= STEPADJUST; if (pstate->heightoffset <= pstate->oldheightoffset) { ob->temp2 = 0; //Debug("\n done adjusting heightoffset"); pstate->heightoffset = pstate->oldheightoffset; } break; case STEPDOWN: pstate->heightoffset += STEPADJUST; if (pstate->heightoffset >= pstate->oldheightoffset) { ob->temp2 = 0; pstate->heightoffset = pstate->oldheightoffset; } break; case 0: if (!((ob->flags & FL_FLEET) || (ob->flags & FL_DOGMODE) || (ob->flags & FL_GODMODE) ) ) pstate->heightoffset = 0; break; } } else if (ob->temp2 == PITFALL) { if (ob->z != pitheight) { ob->z += (ob->momentumz>>16); ob->momentumz += GRAVITY; if (ob->z >= pitheight) { ob->z = pitheight; ob->momentumz = 0; if (!(ob->flags & FL_DYING)) { DamageThing(ob,10); Collision(ob,(objtype*)NULL,0,0); M_CheckPlayerKilled(ob); } } } else if (ob->momentumx || ob->momentumy) { ob->temp2 = PITRISE; ob->momentumz = -2; } } else if (ob->temp2 == PITRISE) { ob->z += ob->momentumz; if (ob->z <= nominalheight) { ob->z = nominalheight; ob->temp2 = 0; ob->momentumz = 0; if (pstate->heightoffset) ob->temp2 = RENORMALIZE; } } } /* ============================= = = CheckRemoteRecording = ============================= */ void CheckRemoteRecording(objtype *ob,playertype *pstate) { if (networkgame==true) { if ( (pstate->buttonstate[bt_recordsound]) && (!pstate->buttonheld[bt_recordsound]) ) { if (SD_RecordingActive()==false) { SD_SetRecordingActive (); PlayerRecording=ob->dirchoosetime; if (ob==player) { SD_StartRecordingSound(); UpdateClientControls(); } } } else if ( (pstate->buttonheld[bt_recordsound]) && (!pstate->buttonstate[bt_recordsound]) ) { if (SD_RecordingActive()==true) { if (ob->dirchoosetime==PlayerRecording) { if (ob==player) SD_StopRecordingSound(); SD_ClearRecordingActive(); PlayerRecording=-1; UpdateClientControls(); } } } } } /* ============================= = = CheckPlayerSpecials = ============================= */ void CheckPlayerSpecials(objtype * ob) { playertype * pstate; M_LINKSTATE(ob,pstate); // Check for recording of sound CheckRemoteRecording(ob,pstate); CheckTemp2Codes(ob,pstate); if (ob->flags & FL_DYING) return; CheckSpecialSounds(ob,pstate); CheckProtectionsAndPowerups(ob,pstate); } #if (SHAREWARE == 0) /* =============== = = T_DogUse = =============== */ void T_DogUse (objtype *ob) { attack_t *cur; playertype *pstate; statetype *oldstate; M_LINKSTATE(ob,pstate); Thrust(ob); oldstate = ob->state; CheckPlayerSpecials(ob); if (ob->state != oldstate) { return; } //Commented out until we find if it's valid /* if (!ob->ticcount) {if ( pstate->buttonstate[bt_use] && !pstate->buttonheld[bt_use] ) pstate->buttonstate[bt_use] = false; } */ if (pstate->attackframe >= DOGSCRATCH.numattacks) Error("\n attackframe %d for DOGSCRATCH gt numattacks %d", pstate->attackframe,DOGSCRATCH.numattacks ); cur = &(DOGSCRATCH.attackinfo[pstate->attackframe]); if (! pstate->attackcount) { switch (cur->attack) { case reset: { NewState(ob,&s_dogwait); pstate->attackframe = pstate->weaponframe = pstate->batblast = 0; return; } break; case at_pulltrigger: pstate->buttonheld[bt_use]=false; Cmd_Use(ob); break; default: break; } pstate->attackframe++; cur = &(DOGSCRATCH.attackinfo[pstate->attackframe]); pstate->weaponframe = cur->frame; pstate->attackcount = cur->mtics; } else pstate->attackcount --; } /* =============== = = T_DogLick = =============== */ void T_DogLick (objtype *ob) { attack_t *cur; playertype *pstate; statetype *oldstate; M_LINKSTATE(ob,pstate); Thrust(ob); oldstate = ob->state; CheckPlayerSpecials(ob); if (ob->state != oldstate) { return; } //Commented out until we find if it's valid /* if (!ob->ticcount) {if ( pstate->buttonstate[bt_use] && !pstate->buttonheld[bt_use] ) pstate->buttonstate[bt_use] = false; } */ if (pstate->attackframe >= DOGLICK.numattacks) Error("\n attackframe %d for DOGLICK gt numattacks %d", pstate->attackframe,DOGLICK.numattacks ); cur = &(DOGLICK.attackinfo[pstate->attackframe]); if (! pstate->attackcount) { if (cur->attack == reset) { NewState(ob,&s_serialdog); pstate->attackframe = pstate->weaponframe = 0; return; } pstate->attackframe++; cur = &(DOGLICK.attackinfo[pstate->attackframe]); pstate->weaponframe = cur->frame; pstate->attackcount = cur->mtics; } else pstate->attackcount --; // if ( playerstate.buttonstate[bt_attack] && (!playerstate.buttonheld[bt_attack]) && (!W_CHANGE)) // Cmd_Fire (ob); } #endif void T_DeadWait(objtype*ob) { playertype *pstate; M_LINKSTATE(ob,pstate); if ((ob->flags & FL_DESIGNATED) && (gamestate.battlemode == battle_CaptureTheTriad)) { int otherteam = (pstate->team ^ 1); ob->flags &= ~FL_DESIGNATED; UpdateKills = true; SpawnStatic(TEAM[otherteam].tilex,TEAM[otherteam].tiley,stat_collector,9); LASTSTAT->flags |= FL_COLORED; LASTSTAT->hitpoints = otherteam; LASTSTAT->flags |= FL_ABP; MakeStatActive(LASTSTAT); } //ob->momentumx=0; //ob->momentumy=0; if (pstate->heightoffset<36) { pstate->heightoffset++; pstate->oldheightoffset = pstate->heightoffset; } if (ob==player) { UpdateLightLevel(player->areanumber); if ((pstate->falling==true) || (ob->momentumz==0)) { if (BATTLEMODE) playerdead=true; else playstate = ex_died; } } /* if (BATTLEMODE) { objtype * killer=(objtype *)ob->target; dx = killer->x - ob->x; dy = ob->y - killer->y; if (dx && dy) ob->angle = atan2_appx (dx,dy); } */ //CheckPlayerSpecials(ob); } /* =============== = = T_Player = =============== */ void T_Player (objtype *ob) { playertype *pstate; statetype *oldstate; #if (SHAREWARE == 0) int eluder; #endif M_LINKSTATE(ob,pstate); #if (SHAREWARE == 0) eluder = ((pstate->weapon == wp_dog) && gamestate.SpawnEluder); #endif oldstate = ob->state; if (ob->flags&FL_DYING) { CheckPlayerSpecials(ob); PlayerMove(ob); if ( (pstate->falling==true) || ( (!ob->momentumx) && (!ob->momentumy) && (!ob->momentumz) && (!ob->state->tictime) ) ) { KillActor(ob); if (ob->state == &s_remoteguts12) NewState(ob,&s_gutwait); else NewState(ob,&s_deadwait); } return; } Thrust(ob); if (ob->flags & FL_DYING) return; oldstate = ob->state; CheckPlayerSpecials(ob); if (ob->state != oldstate) { if (ob->flags & FL_DYING) return; } if (!(ob->flags & FL_PAIN)) { if (!(ob->state->condition & SF_DOGSTATE)) { if ((ob->momentumx || ob->momentumy) && (ob->state->condition != SF_DOWN)) NewState(ob,&s_remotemove1); else if (NOMOM && (ob->state != &s_player)) NewState(ob,&s_player); } else if (NOMOM #if (SHAREWARE == 0) && (ob->state != &s_dogwait) #endif ) NewState(ob,ob->state); } else if (!ob->ticcount) { if (!(ob->state->condition & SF_DOGSTATE)) NewState(ob,&s_player); ob->flags &= ~FL_PAIN; } if (ob->flags & FL_DIDTAG) { ob->flags &= ~FL_DIDTAG; pstate->weapondowntics = (144 - TAGHANDHEIGHT)/GMOVE; } CheckWeaponStates(ob); if (ARMED(ob->dirchoosetime) //(gamestate.battlemode != battle_Tag) ) { if (pstate->weapondowntics == 1) // change to up; during change, up and down // are never zero at the same time { pstate->weapondowntics = 0; pstate->weaponframe = pstate->attackframe = 0; if (pstate->NETCAPTURED == -1) { pstate->weaponuptics = FREE.screenheight/GMOVE; pstate->weaponheight = pstate->weaponuptics*GMOVE ; pstate->NETCAPTURED = 1; // return; } else if (pstate->NETCAPTURED == -2) { pstate->weaponuptics = WEAPONS[pstate->weapon].screenheight/GMOVE; pstate->weaponheight = pstate->weaponuptics*GMOVE ; pstate->NETCAPTURED = 0; //return; } else { pstate->weaponuptics = WEAPONS[pstate->new_weapon].screenheight/GMOVE; pstate->weapon = pstate->new_weapon; pstate->weaponheight = pstate->weaponuptics*GMOVE ; } } else CheckWeaponChange (ob); } else if (gamestate.battlemode == battle_Hunter) { if (pstate->weapondowntics == 1) { pstate->weapondowntics = 0; pstate->weaponframe = pstate->attackframe = pstate->batblast = 0; pstate->weapon = pstate->new_weapon; } } // if ( pstate->buttonstate[bt_use] && (!W_CHANGE(pstate)) ) if ( pstate->buttonstate[bt_use] ) Cmd_Use (ob); if (W_CHANGE(pstate)) return; if ((!ARMED(ob->dirchoosetime)) #if (SHAREWARE == 0) && (pstate->weapon != wp_dog) #endif ) return; if (pstate->buttonstate[bt_attack]) { #if (SHAREWARE == 0) if (eluder) Cmd_Fire(ob); else if ((pstate->weapon == wp_bat) || (pstate->weapon == wp_dog) ) { int oldblast=pstate->batblast; pstate->batblast ++; if (pstate->weapon==wp_bat) { if (pstate->batblast == 20) SD_PlaySoundRTP(SD_EXCALIBUILDSND,ob->x,ob->y); } else { if ((pstate->batblast>>4)!=(oldblast>>4)) { int handle; handle=SD_PlaySoundRTP(SD_DOGMODEPREPBLASTSND,ob->x,ob->y); SD_SetSoundPitch(handle,-(BBTIME<<3)+(pstate->batblast<<3)); } } if (pstate->batblast < BBTIME) return; if (pstate->weapon == wp_bat) SD_PlaySoundRTP(SD_EXCALIBLASTSND,ob->x,ob->y); else SD_PlaySoundRTP(SD_DOGMODEBLASTSND,ob->x,ob->y); } if ((pstate->weapon != wp_split) || (!pstate->buttonheld[bt_attack])) #endif // if (!pstate->buttonheld[bt_attack]) //#endif { #if (SHAREWARE == 0) if (pstate->weapon == wp_kes) SD_PlaySoundRTP(SD_GRAVBUILDSND,ob->x,ob->y); #endif Cmd_Fire (ob); } } #if (SHAREWARE == 0) else if ( ((pstate->weapon == wp_bat) || ((pstate->weapon == wp_dog) && (!eluder)) ) && (pstate->buttonheld[bt_attack]) ) { if (pstate->weapon == wp_bat) SD_StopSound(SD_EXCALIBUILDSND); pstate->batblast = 0; Cmd_Fire(ob); } #endif }