123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293 |
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include "actor.h"
- #include "ai.h"
- #include "db.h"
- #include "debug4g.h"
- #include "dude.h"
- #include "engine.h"
- #include "error.h"
- #include "eventq.h"
- #include "gameutil.h"
- #include "globals.h"
- #include "misc.h"
- #include "multi.h"
- #include "names.h"
- #include "options.h"
- #include "player.h"
- #include "screen.h"
- #include "sectorfx.h"
- #include "seq.h"
- #include "tile.h"
- #include "trig.h"
- #include "triggers.h"
- #include "view.h"
- #include "warp.h"
- #include "weapon.h"
- #include "aizomba.h" // currently required for lackeys
- #include "sfx.h"
- #include "sound.h" // can be removed once sfx complete
- #define kLookMax 60
- #define kHorizUpMax 120
- #define kHorizDownMax 180
- // this should probably go into the posture table too
- #define kClimbSpeed 160
- #define kPowerUpTime (kTimerRate * 30)
- #define kMaxPowerUpTime ((kTimerRate * 60) * 60)
- PLAYER gPlayer[kMaxPlayers];
- PLAYER *gMe = NULL;
- PLAYER *gView = NULL;
- INPUT gPlayerInput[kMaxPlayers];
- /*******************************************************************************
- Notes on the posture table:
- Acceleration units are units per clock tick. If the timer rate is changed,
- these values will need to change as well.
- *******************************************************************************/
- POSTURE gPosture[] =
- {
- // player posture
- {
- 10, // frontAccel 25,
- 5, // sideAccel 30,
- 5, // backAccel 20,
- 350, // frontSpeed[0] 350,
- 800, // frontSpeed[1] 700,
- 300, // sideSpeed[0] 300,
- 500, // sideSpeed[1] 500,
- 250, // backSpeed[0] 250,
- 500, // backSpeed[1] 500,
- 100, // pace[0]
- 140, // pace[1]
- 3, // bobV
- 2, // bobH
- 4, // swayV
- 10, // swayH
- },
- // beast posture ******** THESE ALL NEED TO LOOK LIKE ABOVE (TO DO!) **********
- {
- 20, // frontAccel 20,
- 40, // sideAccel 40,
- 24, // backAccel 24,
- 500, // frontSpeed[0] 500,
- 1000, // frontSpeed[1] 1000,
- 400, // sideSpeed[0] 400,
- 800, // sideSpeed[1] 800,
- 300, // backSpeed[0] 300,
- 600, // backSpeed[1] 600,
- 100, // pace[0]
- 80, // pace[1]
- 12, // bobV
- 4, // bobH
- 8, // swayV
- 16, // swayH
- },
- };
- AMMOINFO gAmmoInfo[kAmmoMax] =
- {
- // max, vectorType
- { kTimerRate*40, kVectorNone }, // kAmmoSprayCan
- { 24, kVectorNone }, // kAmmoTNTStick
- { 8, kVectorNone }, // kAmmoTNTProximity
- { 8, kVectorNone }, // kAmmoTNTRemote
- { 50, kVectorShell }, // kAmmoShell
- { 500, kVectorBullet }, // kAmmoBullet
- { 500, kVectorBulletAP }, // kAmmoBulletAP
- { 24, kVectorNone }, // kAmmoFlare
- { 24, kVectorNone }, // kAmmoFlareSB
- { 10, kVectorNone }, // kAmmoVoodoo
- { 24, kVectorNone }, // kAmmoSpear
- { 24, kVectorNone }, // kAmmoSpearXP
- };
- #if 0
- enum POWERUP {
- kPupFeatherFall = 0,
- kPupJumpBoots,
- kPupInvisible,
- kPupInvulnerable,
- kPupJumpBoots,
- kPupRavenFlight,
- kPupGunsAkimbo,
- kPupDivingSuit,
- kPupGasMask,
- kPupClone,
- kPupCrystalBall,
- kPupDecoy,
- kPupDoppleganger,
- kPupReflectiveShots,
- kPupRoseGlasses,
- kPupShadowCloak,
- kPupShroomRage,
- kPupShroomDelirium,
- kPupShroomGrow,
- kPupShroomShrink,
- kPupDeathMask,
- kPupAsbestosArmor,
- kMaxPowerUps
- };
- enum POWERUPFLAGS {
- kPowerPermanent = 0x0001,
- kPowerUnique = 0x0002,
- };
- #endif
- struct POWERUPINFO {
- short picnum;
- long zoom;
- BOOL isUnique;
- int addPower;
- int maxPower;
- };
- POWERUPINFO gPowerUpInfo[ kMaxPowerUps ] =
- {
- {-1, 0, TRUE, 1, 1}, // kItemKey1
- {-1, 0, TRUE, 1, 1}, // kItemKey2
- {-1, 0, TRUE, 1, 1}, // kItemKey3
- {-1, 0, TRUE, 1, 1}, // kItemKey4
- {-1, 0, TRUE, 1, 1}, // kItemKey5
- {-1, 0, TRUE, 1, 1}, // kItemKey6
- {-1, 0, TRUE, 1, 1}, // kItemKey7
- {-1, 0, FALSE, 10, 100}, // kItemDoctorBag INVENTORY
- {-1, 0, FALSE, 5, 100}, // kItemMedPouch
- {-1, 0, FALSE, 20, 100}, // kItemLifeEssence
- {-1, 0, FALSE, 100, 200}, // kItemLifeSeed
- {-1, 0, FALSE, 2, 200}, // kItemPotion1
- {kAnmFeather, 0, FALSE, kPowerUpTime, kMaxPowerUpTime}, // kItemFeatherFall INVENTORY
- {-1, 0, FALSE, kPowerUpTime, kMaxPowerUpTime}, // kItemLtdInvisibility
- {-1, 0, FALSE, kPowerUpTime, kMaxPowerUpTime}, // kItemInvulnerability
- {kPicJumpBoots, 0, FALSE, kPowerUpTime, kMaxPowerUpTime}, // kItemJumpBoots INVENTORY
- {kPicRavenFlight, 0, FALSE, kPowerUpTime, kMaxPowerUpTime}, // kItemRavenFlight INVENTORY
- {-1, 0, FALSE, kPowerUpTime, kMaxPowerUpTime}, // kItemGunsAkimbo
- {-1, 0, FALSE, kPowerUpTime, kMaxPowerUpTime}, // kItemDivingSuit INVENTORY
- {-1, 0, FALSE, kPowerUpTime, kMaxPowerUpTime}, // kItemGasMask INVENTORY or CUT
- {-1, 0, FALSE, kPowerUpTime, kMaxPowerUpTime}, // kItemClone
- {-1, 0, FALSE, kPowerUpTime, kMaxPowerUpTime}, // kItemCrystalBall INVENTORY
- {-1, 0, FALSE, kPowerUpTime, kMaxPowerUpTime}, // kItemDecoy INVENTORY
- {kAnmDoppleganger, 0, FALSE, kPowerUpTime, kMaxPowerUpTime}, // kItemDoppleganger
- {kAnmReflectShots, 0, FALSE, kPowerUpTime, kMaxPowerUpTime}, // kItemReflectiveShots
- {-1, 0, FALSE, kPowerUpTime, kMaxPowerUpTime}, // kItemRoseGlasses INVENTORY
- {-1, 0, FALSE, kPowerUpTime, kMaxPowerUpTime}, // kItemShadowCloak
- {-1, 0, FALSE, kPowerUpTime, kMaxPowerUpTime}, // kItemShroomRage
- {-1, 0, FALSE, kPowerUpTime/4, kMaxPowerUpTime}, // kItemShroomDelirium
- {-1, 0, FALSE, kPowerUpTime, kMaxPowerUpTime}, // kItemShroomGrow
- {-1, 0, FALSE, kPowerUpTime, kMaxPowerUpTime}, // kItemShroomShrink
- {-1, 0, FALSE, kPowerUpTime, kMaxPowerUpTime}, // kItemDeathMask INVENTORY
- {-1, 0, FALSE, kPowerUpTime, kMaxPowerUpTime}, // kItemWineGoblet
- {-1, 0, FALSE, kPowerUpTime, kMaxPowerUpTime}, // kItemWineBottle
- {-1, 0, FALSE, kPowerUpTime, kMaxPowerUpTime}, // kItemSkullGrail
- {-1, 0, FALSE, kPowerUpTime, kMaxPowerUpTime}, // kItemSilverGrail
- {-1, 0, FALSE, kPowerUpTime, kMaxPowerUpTime}, // kItemTome
- {-1, 0, FALSE, kPowerUpTime, kMaxPowerUpTime}, // kItemBlackChest
- {-1, 0, FALSE, kPowerUpTime, kMaxPowerUpTime}, // kItemWoodenChest
- {-1, 0, FALSE, kPowerUpTime, kMaxPowerUpTime}, // kItemAsbestosArmor INVENTORY
- };
- int powerupCheck( PLAYER *pPlayer, int nPowerUp )
- {
- dassert( pPlayer != NULL );
- dassert( nPowerUp >= 0 && nPowerUp < kMaxPowerUps );
- return pPlayer->powerUpTimer[nPowerUp];
- }
- void powerupDraw( PLAYER *pView )
- {
- for (int nPowerUp = kItemMax - kItemBase - 1; nPowerUp >= 0; nPowerUp--)
- {
- int nPowerRemaining = powerupCheck( pView, nPowerUp );
- if ( nPowerRemaining )
- {
- POWERUPINFO *pInfo = &gPowerUpInfo[ nPowerUp ];
- switch( nPowerUp + kItemBase ) // switch off of actual type
- {
- case kItemFeatherFall:
- case kItemLtdInvisibility:
- case kItemInvulnerability:
- case kItemJumpBoots:
- case kItemRavenFlight:
- case kItemGunsAkimbo:
- case kItemDivingSuit:
- case kItemGasMask:
- case kItemClone:
- case kItemCrystalBall:
- case kItemDecoy:
- case kItemDoppleganger:
- case kItemReflectiveShots:
- case kItemRoseGlasses:
- case kItemShadowCloak:
- case kItemShroomRage:
- case kItemShroomDelirium:
- case kItemShroomGrow:
- case kItemShroomShrink:
- case kItemDeathMask:
- case kItemWineGoblet:
- case kItemWineBottle:
- case kItemSkullGrail:
- case kItemSilverGrail:
- case kItemTome:
- case kItemBlackChest:
- case kItemWoodenChest:
- case kItemAsbestosArmor:
- {
- int nFlags = kRotateNormal;
- if ( nPowerRemaining < (kTimerRate * 8) && ( gGameClock & 32 ) )
- nFlags |= kRotateTranslucent;
- short nTile = pInfo->picnum;
- if (nTile >= 0)
- {
- nTile += animateoffs(nTile, 0);
- rotatesprite(xdim<<15, ydim<<15, pInfo->zoom, 0, nTile, -128, kPLUNormal,
- (char)nFlags, gViewX0, gViewY0, gViewX1, gViewY1);
- }
- }
- break;
- default:
- break;
- }
- }
- }
- }
- BOOL powerupActivate( PLAYER *pPlayer, int nPowerUp )
- {
- // char buffer[80];
- // skip the power-up if it is unique and already activated
- if ( powerupCheck( pPlayer, nPowerUp ) > 0 && gPowerUpInfo[nPowerUp].isUnique )
- return FALSE;
- pPlayer->powerUpTimer[nPowerUp] = ClipHigh( pPlayer->powerUpTimer[nPowerUp] +
- gPowerUpInfo[nPowerUp].addPower, gPowerUpInfo[nPowerUp].maxPower );
- DUDEINFO *pDudeInfo = &dudeInfo[pPlayer->sprite->type - kDudeBase];
- switch( nPowerUp + kItemBase ) // switch off of actual type
- {
- case kItemFeatherFall:
- case kItemJumpBoots:
- pDudeInfo->damageShift[ kDamageFall ] += kNoDamage;
- break;
- case kItemInvulnerability:
- {
- for ( int i = 0; i < kDamageMax; i++ )
- pDudeInfo->damageShift[ i ] += kNoDamage;
- break;
- }
- case kItemDivingSuit:
- pDudeInfo->damageShift[ kDamageDrown ] += kNoDamage;
- break;
- case kItemGasMask:
- pDudeInfo->damageShift[ kDamageGas ] += kNoDamage;
- break;
- case kItemAsbestosArmor:
- pDudeInfo->damageShift[ kDamageBurn ] += kNoDamage;
- break;
- default:
- break;
- }
- SPRITE *pSprite = pPlayer->sprite;
- sfxCreate3DSound(pSprite->x, pSprite->y, pSprite->z, kSfxPlayPowerUp);
- // sprintf( buffer, "Activating %s for %i",
- // gItemText[ nPowerUp ], pPlayer->powerUpTimer[nPowerUp] );
- // viewSetMessage(buffer);
- return TRUE;
- }
- void powerupDeactivate( PLAYER *pPlayer, int nPowerUp )
- {
- DUDEINFO *pDudeInfo = &dudeInfo[pPlayer->sprite->type - kDudeBase];
- switch( nPowerUp + kItemBase ) // switch off of actual type
- {
- case kItemFeatherFall:
- case kItemJumpBoots:
- pDudeInfo->damageShift[ kDamageFall ] -= kNoDamage;
- break;
- case kItemInvulnerability:
- {
- for ( int i = 0; i < kDamageMax; i++ )
- pDudeInfo->damageShift[ i ] -= kNoDamage;
- break;
- }
- case kItemDivingSuit:
- pDudeInfo->damageShift[ kDamageDrown ] -= kNoDamage;
- break;
- case kItemGasMask:
- pDudeInfo->damageShift[ kDamageGas ] -= kNoDamage;
- break;
- case kItemAsbestosArmor:
- pDudeInfo->damageShift[ kDamageBurn ] -= kNoDamage;
- break;
- default:
- break;
- }
- pPlayer->powerUpTimer[ nPowerUp ] = 0;
- }
- void powerupProcess( PLAYER *pPlayer )
- {
- for (int nPowerUp = kItemMax - kItemBase - 1; nPowerUp >= 0; nPowerUp--)
- {
- if ( pPlayer->powerUpTimer[nPowerUp] )
- {
- pPlayer->powerUpTimer[nPowerUp] = ClipLow(pPlayer->powerUpTimer[nPowerUp] - kFrameTicks, 0);
- if ( !powerupCheck( pPlayer, nPowerUp ) )
- powerupDeactivate( pPlayer, nPowerUp );
- }
- }
- }
- void powerupClear( PLAYER *pPlayer )
- {
- for (int nPowerUp = kItemMax - kItemBase - 1; nPowerUp >= 0; nPowerUp--)
- {
- pPlayer->powerUpTimer[nPowerUp] = 0;
- }
- }
- void powerupInit( void )
- {
- for (int nPowerUp = kItemMax - kItemBase - 1; nPowerUp >= 0; nPowerUp--)
- {
- POWERUPINFO *pInfo = &gPowerUpInfo[ nPowerUp ];
- dassert( pInfo->picnum < kMaxTiles );
- if ( pInfo->picnum >= 0 )
- {
- int maxSize = 0;
- PICANM *pAnm = &picanm[ pInfo->picnum ];
- int nFrame = (pAnm->type != 0) ? pAnm->frames : 0;
- for (; nFrame >= 0; nFrame-- )
- {
- if (pAnm->type == 3) // special case for backward anims
- {
- maxSize = tilesizx[ pInfo->picnum - nFrame ];
- if ( maxSize < tilesizy[ pInfo->picnum - nFrame ] )
- maxSize = tilesizy[ pInfo->picnum - nFrame ];
- }
- else
- {
- maxSize = tilesizx[ pInfo->picnum + nFrame ];
- if ( maxSize < tilesizy[ pInfo->picnum + nFrame ] )
- maxSize = tilesizy[ pInfo->picnum + nFrame ];
- }
- }
- dassert( maxSize > 0 );
- pInfo->zoom = ( 24 /*kPowerUpFrameSize*/ << 16 ) / maxSize;
- }
- }
- }
- void playerSetRace( PLAYER *pPlayer, int nLifeMode, int nType )
- {
- dassert( nLifeMode >= kModeHuman && nLifeMode <= kModeBeast );
- int dudeIndex = nType - kDudeBase;
- pPlayer->lifemode = nLifeMode;
- dudeInfo[dudeIndex] = gPlayerTemplate[ nLifeMode ];
- }
- void playerSetGodMode( PLAYER *pPlayer, BOOL nMode )
- {
- DUDEINFO *pDudeInfo = &dudeInfo[pPlayer->sprite->type - kDudeBase];
- if ( nMode )
- {
- for ( int i = 0; i < kDamageMax; i++ )
- pDudeInfo->damageShift[i] += kNoDamage;
- }
- else
- {
- for ( int i = 0; i < kDamageMax; i++ )
- pDudeInfo->damageShift[i] -= kNoDamage;
- }
- pPlayer->godMode = nMode;
- pPlayer->xsprite->health = pDudeInfo->startHealth << 4;
- }
- void playerReset( PLAYER *pPlayer, INPUT *pInput, int type )
- {
- dprintf("Resetting player %d\n", type - kDudePlayer1);
- // get the normal player starting position, else if in bloodbath mode,
- // randomly pick one of kMaxPlayers starting positions
- ZONE *pZone;
- if (gNetMode == kNetModeOff || gNetMode == kNetModeCoop)
- pZone = &gStartZone[ type - kDudePlayer1 ];
- else
- pZone = &gStartZone[ Random(numplayers)];
- if ( pPlayer->sprite != NULL )
- {
- // ADD: make the dead body a non-player type
- }
- int nSprite = actSpawnSprite( pZone->sector, pZone->x, pZone->y, pZone->z, kStatDude, TRUE );
- SPRITE *pSprite = &sprite[nSprite];
- dassert(pSprite->extra > 0 && pSprite->extra < kMaxXSprites);
- XSPRITE *pXSprite = &xsprite[pSprite->extra];
- int dudeIndex = type - kDudeBase;
- playerSetRace( pPlayer, kModeHuman, type );
- seqSpawn(dudeInfo[dudeIndex].seqStartID + kSeqDudeIdle, SS_SPRITE, pSprite->extra);
- // make the player's own sprite visible
- if ( pPlayer == gMe )
- SetBitString(show2dsprite, nSprite);
- // raise the player up off the floor
- int zTop, zBot;
- GetSpriteExtents(pSprite, &zTop, &zBot);
- pSprite->z -= zBot - pSprite->z;
- pPlayer->sprite = pSprite;
- pPlayer->nSprite = nSprite;
- pPlayer->xsprite = pXSprite;
- pSprite->ang = pZone->angle;
- pSprite->type = (short)type;
- pSprite->clipdist = dudeInfo[dudeIndex].clipdist;
- pSprite->flags = kAttrMove | kAttrGravity | kAttrFalling;
- pXSprite->health = dudeInfo[dudeIndex].startHealth << 4;
- pXSprite->moveState = kMoveWalk;
- pXSprite->burnTime = 0;
- pXSprite->burnSource = -1;
- pPlayer->eyeAboveZ = dudeInfo[dudeIndex].eyeHeight * pSprite->yrepeat << 2;
- pPlayer->weaponAboveZ = pPlayer->eyeAboveZ / 2;
- pPlayer->bloodlust = 0;
- pPlayer->impactPE = 0;
- pPlayer->impactPhase = 0;
- pPlayer->standSpeed = 0;
- pPlayer->compression = 0;
- pPlayer->viewOffZ = 0;
- pPlayer->weapOffZ = 0;
- pPlayer->viewOffdZ = 0;
- pPlayer->weapOffdZ = 0;
- pPlayer->horiz = 0;
- pPlayer->look = 0;
- pPlayer->slope = 0;
- pPlayer->fraggerID = -1;
- pPlayer->airTime = 0;
- pPlayer->bloodTime = 0;
- pPlayer->gooTime = 0;
- pPlayer->wetTime = 0;
- pPlayer->godMode = FALSE;
- pPlayer->relAim.dx = 1 << 14;
- pPlayer->relAim.dy = 0;
- pPlayer->relAim.dz = 0;
- pPlayer->aimSprite = -1;
- for (int i = 0; i < 8; i++)
- pPlayer->hasKey[i] = 0;
- pPlayer->weapon = kWeaponNone;
- pPlayer->deathTime = 0;
- pSprite->xvel = 0;
- pSprite->yvel = 0;
- pSprite->zvel = 0;
- pInput->forward = 0;
- pInput->strafe = 0;
- pInput->turn = 0;
- pInput->syncFlags.byte = 0;
- pInput->buttonFlags.byte = 0;
- pInput->keyFlags.byte = 0;
- pInput->newWeapon = kWeaponPitchfork;
- scrDacAbsEffect(0, 0, 0);
- for (i = 0; i < kWeaponMax; i++)
- {
- pPlayer->hasWeapon[i] = gInfiniteAmmo;
- pPlayer->weaponMode[i] = 0;
- }
- pPlayer->hasWeapon[kWeaponPitchfork] = TRUE;
- for (i = 0; i < kAmmoMax; i++)
- {
- pPlayer->ammoCount[i] = gInfiniteAmmo ? gAmmoInfo[i].max : 0;
- }
- pPlayer->weaponTimer = 0; // idle
- pPlayer->weaponState = 0;
- pPlayer->pWeaponQAV = NULL;
- for (i = 0; i < kMaxPowerUps; i++)
- pPlayer->powerUpTimer[i] = 0;
- for (i = 0; i < kMaxLackeys; i++)
- pPlayer->nLackeySprites[i] = -1;
- }
- void playerInit( int nPlayer )
- {
- PLAYER *pPlayer = &gPlayer[nPlayer];
- dprintf("Initializing player %d\n", nPlayer);
- pPlayer->sprite = NULL;
- pPlayer->teamID = nPlayer;
- pPlayer->fragCount = 0;
- memset(pPlayer->fragInfo, 0, sizeof(pPlayer->fragInfo));
- playerReset(pPlayer, &gPlayerInput[nPlayer], kDudePlayer1 + nPlayer);
- }
- static int CheckTouchSprite( SPRITE *pSprite )
- {
- int i, next;
- int dx, dy, dz;
- for (i = headspritestat[kStatItem]; i >= 0; i = next)
- {
- next = nextspritestat[i];
- dx = qabs(pSprite->x - sprite[i].x) >> 4;
- if (dx < kTouchXYDist)
- {
- dy = qabs(pSprite->y - sprite[i].y) >> 4;
- if (dy < kTouchXYDist)
- {
- int zTop, zBot;
- GetSpriteExtents(pSprite, &zTop, &zBot);
- dz = 0;
- if ( sprite[i].z < zTop )
- dz = (zTop - sprite[i].z) >> 8;
- else if ( sprite[i].z > zBot )
- dz = (sprite[i].z - zBot) >> 8;
- if (dz < kTouchZDist)
- {
- if (qdist(dx, dy) < kTouchXYDist)
- {
- int zTop, zBot;
- GetSpriteExtents(&sprite[i], &zTop, &zBot);
- if (
- // center
- cansee(pSprite->x, pSprite->y, pSprite->z, pSprite->sectnum,
- sprite[i].x, sprite[i].y, sprite[i].z, sprite[i].sectnum) ||
- // top
- cansee(pSprite->x, pSprite->y, pSprite->z, pSprite->sectnum,
- sprite[i].x, sprite[i].y, zTop, sprite[i].sectnum) ||
- // bottom
- cansee(pSprite->x, pSprite->y, pSprite->z, pSprite->sectnum,
- sprite[i].x, sprite[i].y, zBot, sprite[i].sectnum)
- )
- return i;
- }
- }
- }
- }
- }
- return -1;
- }
- static BOOL PickupItem( PLAYER *pPlayer, int nSprite, int nItemType )
- {
- SPRITE *pSprite = pPlayer->sprite;
- XSPRITE *pXSprite = pPlayer->xsprite;
- int nPowerUp = nItemType - kItemBase;
- switch( nItemType )
- {
- case kItemKey1:
- case kItemKey2:
- case kItemKey3:
- case kItemKey4:
- case kItemKey5:
- case kItemKey6:
- case kItemKey7:
- if ( pPlayer->hasKey[nItemType - kItemKey1 + 1] )
- return FALSE;
- pPlayer->hasKey[nItemType - kItemKey1 + 1] = sprite[nSprite].picnum;
- break;
- case kItemDoctorBag:
- case kItemPotion1:
- case kItemMedPouch:
- case kItemLifeEssence:
- case kItemLifeSeed:
- if ( !actHealDude(pXSprite, gPowerUpInfo[nPowerUp].addPower, gPowerUpInfo[nPowerUp].maxPower) )
- return FALSE;
- break;
- default:
- if ( !powerupActivate( pPlayer, nPowerUp ) )
- return FALSE;
- break;
- }
- sfxCreate3DSound(pSprite->x, pSprite->y, pSprite->z, kSfxPlayItemUp);
- return TRUE;
- }
- static BOOL PickupAmmo( PLAYER *pPlayer, int /*nSprite*/, int nAmmoItemType )
- {
- AMMOITEMDATA *pAmmoData = &gAmmoItemData[nAmmoItemType - kAmmoItemBase];
- int nAmmoType = pAmmoData->ammoType;
- if ( pPlayer->ammoCount[nAmmoType] >= gAmmoInfo[nAmmoType].max )
- return FALSE;
- pPlayer->ammoCount[nAmmoType] = ClipHigh(
- pPlayer->ammoCount[nAmmoType] + pAmmoData->count, gAmmoInfo[nAmmoType].max );
- // set the hasWeapon flags for weapons which are ammo
- if ( pAmmoData->weaponType != kWeaponNone )
- pPlayer->hasWeapon[pAmmoData->weaponType] = TRUE;
- SPRITE *pSprite = pPlayer->sprite;
- sfxCreate3DSound(pSprite->x, pSprite->y, pSprite->z, kSfxPlayItemUp);
- return TRUE;
- }
- static BOOL PickupWeapon( PLAYER *pPlayer, int nSprite, int nWeaponItem )
- {
- WEAPONITEMDATA *pWeaponData = &gWeaponItemData[nWeaponItem - kWeaponItemBase];
- int nWeapon = pWeaponData->weaponType;
- int nAmmo = pWeaponData->ammoType;
- // add weapon to player inventory
- if ( !pPlayer->hasWeapon[nWeapon] )
- {
- pPlayer->hasWeapon[nWeapon] = TRUE;
- if ( nAmmo != kAmmoNone )
- {
- // add preloaded ammo
- pPlayer->ammoCount[nAmmo] = ClipHigh(
- pPlayer->ammoCount[nAmmo] + pWeaponData->count, gAmmoInfo[nAmmo].max );
- }
- SPRITE *pSprite = pPlayer->sprite;
- // sfxCreate3DSound(pSprite->x, pSprite->y, pSprite->z, kSfxWeaponUp);
- return TRUE;
- }
- if ( nAmmo == kAmmoNone )
- return FALSE;
- if ( pPlayer->ammoCount[nAmmo] >= gAmmoInfo[nAmmo].max )
- return FALSE;
- BOOL isPermanent = FALSE;
- if ( sprite[nSprite].extra > 0)
- {
- XSPRITE *pXItem = &xsprite[sprite[nSprite].extra];
- if ( pXItem->respawn == kRespawnPermanent )
- isPermanent = TRUE;
- }
- if ( !isPermanent )
- {
- // add preloaded ammo
- pPlayer->ammoCount[nAmmo] = ClipHigh(
- pPlayer->ammoCount[nAmmo] + pWeaponData->count, gAmmoInfo[nAmmo].max );
- SPRITE *pSprite = pPlayer->sprite;
- // sfxCreate3DSound(pSprite->x, pSprite->y, pSprite->z, kSfxWeaponUp);
- return TRUE;
- }
- return FALSE;
- }
- static void PickUp( PLAYER *pPlayer )
- {
- int x, y, z;
- SPRITE *pSprite = pPlayer->sprite;
- XSPRITE *pXSprite = pPlayer->xsprite;
- char buffer[80];
- x = pSprite->x;
- y = pSprite->y;
- z = pSprite->z;
- int nSprite = CheckTouchSprite(pSprite);
- if (nSprite >= 0)
- {
- BOOL bPickedUp = FALSE;
- int nType = sprite[nSprite].type;
- if (nType >= kItemBase && nType <= kItemMax)
- {
- bPickedUp = PickupItem( pPlayer, nSprite, nType );
- sprintf(buffer, "Picked up %s", gItemText[ nType - kItemBase ] );
- }
- else if (nType >= kAmmoItemBase && nType < kAmmoItemMax) {
- bPickedUp = PickupAmmo( pPlayer, nSprite, nType );
- sprintf(buffer, "Picked up %s", gAmmoText[ nType - kAmmoItemBase ] );
- }
- else if (nType >= kWeaponItemBase && nType < kWeaponItemMax)
- {
- bPickedUp = PickupWeapon( pPlayer, nSprite, nType );
- sprintf(buffer, "Picked up %s", gWeaponText[ nType - kWeaponItemBase ] );
- }
- if (bPickedUp)
- {
- if ( sprite[nSprite].extra > 0)
- {
- XSPRITE *pXItem = &xsprite[sprite[nSprite].extra];
- if ( pXItem->triggerPickup )
- trTriggerSprite(nSprite, pXItem, kCommandSpritePickup);
- }
- if ( !actCheckRespawn( nSprite ) )
- actPostSprite( nSprite, kStatFree );
- if (pPlayer == gMe)
- {
- viewSetMessage(buffer);
- scrDacRelEffect(16, 16, -16);
- }
- }
- }
- }
- static int ActionScan( PLAYER *pPlayer, int *nIndex, int *nXIndex)
- {
- SPRITE *pSprite = pPlayer->sprite;
- HITINFO hitInfo;
- *nIndex = 0;
- *nXIndex = 0;
- int dx = Cos(pSprite->ang) >> 16;
- int dy = Sin(pSprite->ang) >> 16;
- int dz = pPlayer->slope;
- int hitType = HitScan(pSprite, pSprite->z - pPlayer->eyeAboveZ, dx, dy, dz, &hitInfo);
- int hitDist = qdist(pSprite->x - hitInfo.hitx, pSprite->y - hitInfo.hity) >> 4;
- if ( hitDist < kPushXYDist )
- {
- switch ( hitType )
- {
- case SS_SPRITE:
- *nIndex = hitInfo.hitsprite;
- *nXIndex = sprite[*nIndex].extra;
- if (*nXIndex > 0 && xsprite[*nXIndex].triggerPush )
- return SS_SPRITE;
- if ( sprite[*nIndex].statnum == kStatDude )
- {
- SPRITE *pDude = &sprite[*nIndex];
- XSPRITE *pXDude = &xsprite[*nXIndex];
- dprintf("DUDE %d: ang=%d, goalAng=%d\n", *nIndex, pDude->ang, pXDude->goalAng);
- }
- break;
- case SS_MASKED:
- case SS_WALL:
- *nIndex = hitInfo.hitwall;
- *nXIndex = wall[*nIndex].extra;
- if (*nXIndex > 0 && xwall[*nXIndex].triggerPush )
- return SS_WALL;
- if ( wall[*nIndex].nextsector >= 0)
- {
- *nIndex = wall[*nIndex].nextsector;
- *nXIndex = sector[*nIndex].extra;
- if (*nXIndex > 0 && xsector[*nXIndex].triggerWPush )
- return SS_SECTOR;
- }
- break;
- case SS_FLOOR:
- case SS_CEILING:
- *nIndex = hitInfo.hitsect;
- *nXIndex = sector[*nIndex].extra;
- if (*nXIndex > 0 && xsector[*nXIndex].triggerPush )
- return SS_SECTOR;
- break;
- }
- if ( pPlayer == gMe )
- sfxStart3DSound(pPlayer->sprite->extra, kSfxPlayHunt, 0x1000); // push grunt
- }
- *nIndex = pSprite->sectnum;
- *nXIndex = sector[*nIndex].extra;
- if (*nXIndex > 0 && xsector[*nXIndex].triggerPush )
- return SS_SECTOR;
- return -1;
- }
- static void ProcessInput( PLAYER *pPlayer, INPUT *pInput )
- {
- long vel, svel, sin, cos;
- POSTURE *cp = &gPosture[pPlayer->lifemode];
- SPRITE *pSprite = pPlayer->sprite;
- XSPRITE *pXSprite = pPlayer->xsprite;
- pPlayer->run = FALSE;
- BOOL run;
- WeaponProcess(pPlayer, pInput);
- // quick hack for death
- if (pXSprite->health == 0)
- {
- if ( pPlayer->deathTime == 0 )
- {
- // pXSprite->avel = (pXSprite->avel + BiRandom(40)) & kAngleMask;
- }
- pPlayer->deathTime += kFrameTicks;
- pPlayer->horiz = mulscale16((1 << 15) - (Cos(ClipHigh(pPlayer->deathTime << 3, kAngle180)) >> 15), kHorizUpMax);
- pXSprite->moveState = kMoveDead;
- pPlayer->compression = mulscale16((1 << 15) - (Cos(ClipHigh(pPlayer->deathTime << 3, kAngle90)) >> 15), pPlayer->eyeAboveZ);
- if (pPlayer->weapon)
- pInput->newWeapon = pPlayer->weapon; // force weapon down
- if (pInput->keyFlags.action)
- {
- playerReset(pPlayer, pInput, pPlayer->sprite->type);
- pInput->keyFlags.action = 0;
- }
- return; // Don't allow the player to do anything else if dead
- }
- sin = Sin(pSprite->ang);
- cos = Cos(pSprite->ang);
- // find vel and svel relative to current angle
- vel = dmulscale30(pSprite->xvel, cos, pSprite->yvel, sin);
- svel = dmulscale30(pSprite->xvel, sin, -pSprite->yvel, cos);
- /*
- // ground deceleration
- switch ( pXSprite->moveState )
- {
- case kMoveFall:
- case kMoveSwim:
- break;
- default:
- if (vel > 0)
- vel = ClipLow(vel - pInput->ticks * cp->decel, 0);
- else if (vel < 0)
- vel = ClipHigh(vel + pInput->ticks * cp->decel, 0);
- if (svel > 0)
- svel = ClipLow(svel - pInput->ticks * cp->sideDecel, 0);
- else if (svel < 0)
- svel = ClipHigh(svel + pInput->ticks * cp->sideDecel, 0);
- break;
- }
- */
- // acceleration
- switch ( pXSprite->moveState )
- {
- case kMoveWalk:
- case kMoveStand:
- case kMoveLand:
- case kMoveSwim:
- if ( pInput->forward > 0 )
- {
- run = pInput->forward > pInput->ticks;
- pPlayer->run |= run;
- if ( vel < cp->frontSpeed[run] );
- vel = ClipHigh(vel + cp->frontAccel * pInput->forward + kGroundFriction * kFrameTicks, cp->frontSpeed[run]);
- }
- else if ( pInput->forward < 0 )
- {
- run = pInput->forward < -pInput->ticks;
- pPlayer->run |= run;
- if ( vel > -cp->backSpeed[run] );
- vel = ClipLow(vel + cp->backAccel * pInput->forward - kGroundFriction * kFrameTicks, -cp->backSpeed[run]);
- }
- if ( pInput->strafe > 0 )
- {
- run = pInput->strafe > pInput->ticks;
- pPlayer->run |= run;
- if ( svel < cp->sideSpeed[run] );
- svel = ClipHigh(svel + cp->sideAccel * pInput->strafe + kGroundFriction * kFrameTicks, cp->sideSpeed[run]);
- }
- else if ( pInput->strafe < 0 )
- {
- run = pInput->strafe < -pInput->ticks;
- pPlayer->run |= run;
- if ( svel > -cp->sideSpeed[run] );
- svel = ClipLow(svel + cp->sideAccel * pInput->strafe - kGroundFriction * kFrameTicks, -cp->sideSpeed[run]);
- }
- break;
- }
- // turn player
- if (pInput->turn != 0)
- pSprite->ang = (short)((pSprite->ang + (pInput->turn * kFrameTicks >> 4)) & kAngleMask);
- // reconstruct x and y velocities
- pSprite->xvel = (short)dmulscale30(vel, cos, svel, sin);
- pSprite->yvel = (short)dmulscale30(vel, sin, -svel, cos);
- // action key
- if (pInput->keyFlags.action)
- {
- int nIndex, nXIndex;
- int keyId;
- switch ( ActionScan(pPlayer, &nIndex, &nXIndex) )
- {
- case SS_SECTOR:
- {
- XSECTOR *pXSector = &xsector[nXIndex];
- keyId = pXSector->key;
- dprintf("Key %d required\n", keyId);
- if ( pXSector->locked && pPlayer == gMe )
- viewSetMessage("It's locked");
- if ( keyId == 0 || pPlayer->hasKey[keyId] )
- trTriggerSector(nIndex, pXSector, kCommandSpritePush);
- else
- if (pPlayer == gMe)
- {
- viewSetMessage("That requires a key.");
- }
- break;
- }
- case SS_WALL:
- {
- XWALL *pXWall = &xwall[nXIndex];
- keyId = pXWall->key;
- dprintf("Key %d required\n", keyId);
- if ( pXWall->locked && pPlayer == gMe )
- viewSetMessage("It's locked");
- if ( keyId == 0 || pPlayer->hasKey[keyId] )
- trTriggerWall(nIndex, pXWall, kCommandWallPush);
- else
- if (pPlayer == gMe)
- {
- viewSetMessage("That requires a key.");
- }
- break;
- }
- case SS_SPRITE:
- {
- XSPRITE *pXSprite = &xsprite[nXIndex];
- keyId = pXSprite->key;
- dprintf("Key %d required\n", keyId);
- if ( pXSprite->locked && pPlayer == gMe )
- viewSetMessage("It's locked");
- if ( keyId == 0 || pPlayer->hasKey[keyId] )
- trTriggerSprite(nIndex, pXSprite, kCommandSpritePush);
- else
- if (pPlayer == gMe)
- {
- viewSetMessage("That requires a key.");
- }
- break;
- }
- }
- // non-repeating, so clear flag
- pInput->keyFlags.action = 0;
- }
- if ( pInput->keyFlags.lookcenter && !pInput->buttonFlags.lookup && !pInput->buttonFlags.lookdown )
- {
- if ( pPlayer->look < 0 )
- pPlayer->look = ClipHigh(pPlayer->look + kFrameTicks, 0);
- if ( pPlayer->look > 0 )
- pPlayer->look = ClipLow(pPlayer->look - kFrameTicks, 0);
- if ( pPlayer->look == 0 )
- pInput->keyFlags.lookcenter = 0;
- }
- else
- {
- if ( pInput->buttonFlags.lookup )
- pPlayer->look = ClipHigh(pPlayer->look + kFrameTicks, kLookMax);
- if ( pInput->buttonFlags.lookdown )
- pPlayer->look = ClipLow(pPlayer->look - kFrameTicks, -kLookMax);
- }
- if ( pPlayer->look > 0 )
- pPlayer->horiz = mulscale30(kHorizUpMax, Sin(pPlayer->look * (kAngle90 / kLookMax)));
- else if ( pPlayer->look < 0 )
- pPlayer->horiz = mulscale30(kHorizDownMax, Sin(pPlayer->look * (kAngle90 / kLookMax)));
- else
- pPlayer->horiz = 0;
- pPlayer->slope = -pPlayer->horiz << 7;
- PickUp(pPlayer);
- }
- void playerMove( PLAYER *pPlayer, INPUT *pInput )
- {
- int nSprite = pPlayer->nSprite;
- SPRITE *pSprite = pPlayer->sprite;
- int nXSprite = pSprite->extra;
- XSPRITE *pXSprite = pPlayer->xsprite;
- short nSector;
- int nXSector;
- XSECTOR *pXSector = NULL;
- POSTURE *cp = &gPosture[pPlayer->lifemode];
- nSector = pSprite->sectnum;
- if ( (nXSector = sector[nSector].extra) > 0 )
- pXSector = &xsector[nXSector];
- int moveDist = qdist(pSprite->xvel, pSprite->yvel);
- ProcessInput(pPlayer, pInput);
- if ( pXSprite->health == 0 )
- return;
- int dudeIndex = kDudePlayer1 - kDudeBase;
- if ( moveDist == 0 )
- seqSpawn(dudeInfo[dudeIndex].seqStartID + kSeqDudeIdle, SS_SPRITE, nXSprite);
- else
- seqSpawn(dudeInfo[dudeIndex].seqStartID + kSeqCultistWalk, SS_SPRITE, nXSprite); // hack to make player walk
- if ( gSpriteHit[nXSprite].floorHit == 0 )
- pXSprite->moveState = kMoveFall;
- else
- pXSprite->moveState = kMoveWalk;
- /*
- switch (pXSprite->moveState)
- {
- case kMoveFall:
- pPlayer->impactPE = pSprite->zvel * gSpring;
- pXSprite->moveState = kMoveLand;
- pSprite->zvel = 0;
- pPlayer->impactPhase = 0;
- pPlayer->standSpeed = kAngle90 / ClipLow(fallDamage << 2, 8);
- pPlayer->standSpeed = ClipLow(pPlayer->standSpeed, 2);
- // fall through to Move Land
- case kMoveLand:
- pPlayer->impactPhase = ClipHigh(pPlayer->impactPhase + dt * gSpringPhaseInc, kAngle90);
- pPlayer->compression = mulscale30(pPlayer->impactPE, Sin(pPlayer->impactPhase));
- // pSprite->zvel = mulscale30(pPlayer->impactPE, Cos(pPlayer->impactPhase));
- if (pPlayer->impactPhase == kAngle90)
- {
- pXSprite->moveState = kMoveStand;
- pPlayer->impactPhase = 0;
- pSprite->zvel = 0;
- }
- break;
- case kMoveStand:
- pPlayer->impactPhase = ClipHigh(pPlayer->impactPhase + dt * pPlayer->standSpeed, kAngle90);
- pPlayer->compression = mulscale30(pPlayer->impactPE, (1 << 30) - Sin(pPlayer->impactPhase));
- if (pPlayer->impactPhase == kAngle90)
- {
- pXSprite->moveState = kMoveWalk;
- pSprite->zvel = 0;
- pPlayer->impactPE = 0;
- }
- // fall through
- case kMoveWalk:
- if ( zBot > loz )
- {
- pPlayer->compression += zBot - loz;
- pSprite->z += loz - zBot;
- pPlayer->impactPhase = 0;
- pXSprite->moveState = kMoveStand;
- pPlayer->standSpeed = 8;
- pPlayer->impactPE = pPlayer->compression;
- }
- }
- */
- if ( pInput->buttonFlags.jump && gSpriteHit[nXSprite].floorHit != 0 )
- {
- sfxStart3DSound(nXSprite, kSfxPlayJump, 0x1000);
- pSprite->zvel = -400;
- }
- if (pSprite->sectnum < 0 || pSprite->sectnum >= numsectors)
- {
- dprintf("How did you get in the wrong sector (%d)?\n", pSprite->sectnum);
- }
- if (pXSector && (pXSector->underwater || (pXSector->depth == kDepthSwim && pSprite->z >= sector[nSector].floorz)))
- pXSprite->moveState = kMoveSwim;
- // bobbing and swaying code
- // this controls the decay on bobbing
- int xamp, yamp;
- pPlayer->bobAmp = ClipLow(pPlayer->bobAmp - 8 * kFrameTicks, 0);
- moveDist >>= 2;
- if ( gViewBobbing )
- {
- // this bobbing code should be moved somewhere else, VIEW maybe?
- switch ( pPlayer->xsprite->moveState )
- {
- case kMoveWalk:
- pPlayer->bobPhase = (pPlayer->bobPhase + kFrameTicks * cp->pace[pPlayer->run] * kAngle360 / 120 / kTimerRate) & kAngleMask;
- pPlayer->swayPhase = (pPlayer->swayPhase + kFrameTicks * cp->pace[pPlayer->run] / 2 * kAngle360 / 120 / kTimerRate) & kAngleMask;
- if ( pPlayer->run )
- {
- if (pPlayer->bobAmp < 512)
- pPlayer->bobAmp = ClipHigh(pPlayer->bobAmp + moveDist, 512);
- }
- else
- {
- if (pPlayer->bobAmp < 384)
- pPlayer->bobAmp = ClipHigh(pPlayer->bobAmp + moveDist, 384);
- }
- xamp = yamp = pPlayer->bobAmp;
- break;
- case kMoveSwim:
- pPlayer->bobPhase = (pPlayer->bobPhase + kFrameTicks * kAngle360 / kTimerRate / 2) & kAngleMask;
- pPlayer->swayPhase = (pPlayer->swayPhase + kFrameTicks * kAngle360 / kTimerRate / 2) & kAngleMask;
- yamp = 64;
- xamp = 0;
- break;
- default:
- xamp = yamp = pPlayer->bobAmp;
- }
- pPlayer->bobHeight = mulscale30(cp->bobV * yamp, Sin(pPlayer->bobPhase * 2));
- pPlayer->bobWidth = mulscale30(cp->bobH * xamp, Sin(pPlayer->bobPhase - kAngle45));
- pPlayer->swayHeight = mulscale30(cp->swayV * yamp, Sin(pPlayer->swayPhase * 2));
- pPlayer->swayWidth = mulscale30(cp->swayH * xamp, Sin(pPlayer->swayPhase - kAngle60));
- }
- }
- void playerFireMissile( PLAYER *pPlayer, long dx, long dy, long dz, int missileType )
- {
- actFireMissile(pPlayer->nSprite, pPlayer->sprite->z - pPlayer->weaponAboveZ,
- dx, dy, dz, missileType);
- }
- int playerFireThing( PLAYER *pPlayer, int relSlope, int thingType, int velocity )
- {
- dassert( thingType >= kThingBase && thingType < kThingMax );
- SPRITE *pSprite = pPlayer->sprite;
- return actFireThing( pPlayer->nSprite, pSprite->z - pPlayer->weaponAboveZ,
- pPlayer->slope + relSlope, thingType, velocity );
- }
- void playerDamageSprite( PLAYER *pPlayer, int nSource, int nDamage )
- {
- // if (pPlayer == gMe)
- if ( pPlayer == gView )
- scrDacRelEffect((nDamage>>4)*2, (-nDamage>>4)*3, (-nDamage>>4)*3);
- if ( nDamage > 0 )
- sfxStart3DSound(pPlayer->sprite->extra, kSfxPlayPain, 0x1000);
- // source can be targeted by lackeys?
- if (IsDudeSprite( nSource ))
- {
- for (int i=0; i<kMaxLackeys; i++)
- {
- int nLackey = pPlayer->nLackeySprites[i];
- if (nLackey >= 0 && nLackey != nSource)
- aiAlertLackey( pPlayer, nLackey, nSource, nDamage );
- }
- }
- }
- BOOL playerAddLackey( PLAYER *pPlayer, int nLackey )
- {
- for (int i=0; i<kMaxLackeys; i++)
- if (pPlayer->nLackeySprites[i] == nLackey)
- {
- //dprintf("lackey already in list\n");
- return FALSE;
- }
- for (i=0; i<kMaxLackeys; i++)
- if (pPlayer->nLackeySprites[i] == -1)
- {
- //dprintf("adding lackey %i: %i\n",i,nLackey);
- pPlayer->nLackeySprites[i] = nLackey;
- sprite[nLackey].owner = (short)pPlayer->nSprite;
- break;
- }
- return (i < kMaxLackeys) ? TRUE : FALSE;
- }
- void playerDeleteLackey( PLAYER *pPlayer, int nLackey )
- {
- for (int i=0; i<kMaxLackeys; i++)
- if (pPlayer->nLackeySprites[i] == nLackey)
- {
- pPlayer->nLackeySprites[i] = -1;
- sprite[nLackey].owner = -1;
- break;
- }
- }
|