123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941 |
- #ifdef PRECOMPILEDHEADERS
- #include "Tactical All.h"
- #else
- #include <stdio.h>
- #include <string.h>
- #include "wcheck.h"
- #include "stdlib.h"
- #include "debug.h"
- #include "soldier control.h"
- #include "weapons.h"
- #include "handle items.h"
- #include "worlddef.h"
- #include "worldman.h"
- #include "rotting corpses.h"
- #include "tile cache.h"
- #include "isometric utils.h"
- #include "animation control.h"
- #include "utilities.h"
- #include "game clock.h"
- #include "soldier create.h"
- #include "renderworld.h"
- #include "soldier add.h"
- #include "strategicmap.h"
- #include "los.h"
- #include "opplist.h"
- #include "structure.h"
- #include "message.h"
- #include "sound control.h"
- #include "pathai.h"
- #include "Random.h"
- #include "dialogue control.h"
- #include "items.h"
- #include "smell.h"
- #include "World Items.h"
- #include "explosion control.h"
- #include "GameSettings.h"
- #endif
- #define CORPSE_WARNING_MAX 5
- #define CORPSE_WARNING_DIST 5
- #define CORPSE_INDEX_OFFSET 10000
- //#define DELAY_UNTIL_ROTTING ( 1 * NUM_SEC_IN_DAY )
- #define DELAY_UNTIL_ROTTING ( 1 * NUM_SEC_IN_DAY / 60 )
- #define DELAY_UNTIL_DONE_ROTTING ( 3 * NUM_SEC_IN_DAY / 60 )
- #define MAX_NUM_CROWS 6
- // From lighting
- extern SGPPaletteEntry gpLightColors[3];
- extern UINT16 gusShadeLevels[16][3];
- void MakeCorpseVisible( SOLDIERTYPE *pSoldier, ROTTING_CORPSE *pCorpse );
- // When adding a corpse, add struct data...
- CHAR8 zCorpseFilenames[ NUM_CORPSES ][70] =
- {
- "",
- "ANIMS\\CORPSES\\S_D_JFK.STI",
- "ANIMS\\CORPSES\\S_D_BCK.STI",
- "ANIMS\\CORPSES\\S_D_FWD.STI",
- "ANIMS\\CORPSES\\S_D_DHD.STI",
- "ANIMS\\CORPSES\\S_D_PRN.STI",
- "ANIMS\\CORPSES\\S_D_WTR.STI",
- "ANIMS\\CORPSES\\S_D_FALL.STI",
- "ANIMS\\CORPSES\\S_D_FALLF.STI",
- "ANIMS\\CORPSES\\M_D_JFK.STI",
- "ANIMS\\CORPSES\\M_D_BCK.STI",
- "ANIMS\\CORPSES\\M_D_FWD.STI",
- "ANIMS\\CORPSES\\M_D_DHD.STI",
- "ANIMS\\CORPSES\\M_D_PRN.STI",
- "ANIMS\\CORPSES\\S_D_WTR.STI",
- "ANIMS\\CORPSES\\M_D_FALL.STI",
- "ANIMS\\CORPSES\\M_D_FALLF.STI",
- "ANIMS\\CORPSES\\F_D_JFK.STI",
- "ANIMS\\CORPSES\\F_D_BCK.STI",
- "ANIMS\\CORPSES\\F_D_FWD.STI",
- "ANIMS\\CORPSES\\F_D_DHD.STI",
- "ANIMS\\CORPSES\\F_D_PRN.STI",
- "ANIMS\\CORPSES\\S_D_WTR.STI",
- "ANIMS\\CORPSES\\F_D_FALL.STI",
- "ANIMS\\CORPSES\\F_D_FALLF.STI",
- // Civs....
- "ANIMS\\CORPSES\\M_DEAD1.STI",
- "ANIMS\\CORPSES\\K_DEAD2.STI",
- "ANIMS\\CORPSES\\H_DEAD2.STI",
- "ANIMS\\CORPSES\\FT_DEAD1.STI",
- "ANIMS\\CORPSES\\S_DEAD1.STI",
- "ANIMS\\CORPSES\\W_DEAD1.STI",
- "ANIMS\\CORPSES\\CP_DEAD1.STI",
- "ANIMS\\CORPSES\\M_DEAD2.STI",
- "ANIMS\\CORPSES\\K_DEAD1.STI",
- "ANIMS\\CORPSES\\H_DEAD1.STI",
- "ANIMS\\CORPSES\\FT_DEAD2.STI",
- "ANIMS\\CORPSES\\S_DEAD2.STI",
- "ANIMS\\CORPSES\\W_DEAD2.STI",
- "ANIMS\\CORPSES\\CP_DEAD2.STI",
- "ANIMS\\CORPSES\\CT_DEAD.STI",
- "ANIMS\\CORPSES\\CW_DEAD1.STI",
- "ANIMS\\CORPSES\\MN_DEAD2.STI",
- "ANIMS\\CORPSES\\I_DEAD1.STI",
- "ANIMS\\CORPSES\\L_DEAD1.STI",
- "ANIMS\\CORPSES\\P_DECOMP2.STI",
- "ANIMS\\CORPSES\\TK_WREK.STI",
- "ANIMS\\CORPSES\\TK2_WREK.STI",
- "ANIMS\\CORPSES\\HM_WREK.STI",
- "ANIMS\\CORPSES\\IC_WREK.STI",
- "ANIMS\\CORPSES\\QN_DEAD.STI",
- "ANIMS\\CORPSES\\J_DEAD.STI",
- "ANIMS\\CORPSES\\S_BURNT.STI",
- "ANIMS\\CORPSES\\S_EXPLD.STI",
- };
- // When adding a corpse, add struct data...
- CHAR8 zNoBloodCorpseFilenames[ NUM_CORPSES ][70] =
- {
- "",
- "ANIMS\\CORPSES\\M_D_JFK_NB.STI",
- "ANIMS\\CORPSES\\S_D_BCK_NB.STI",
- "ANIMS\\CORPSES\\S_D_FWD_NB.STI",
- "ANIMS\\CORPSES\\S_D_DHD_NB.STI",
- "ANIMS\\CORPSES\\S_D_PRN_NB.STI",
- "ANIMS\\CORPSES\\S_D_WTR.STI",
- "ANIMS\\CORPSES\\S_D_FALL_NB.STI",
- "ANIMS\\CORPSES\\S_D_FALLF_NB.STI",
- "ANIMS\\CORPSES\\M_D_JFK_NB.STI",
- "ANIMS\\CORPSES\\M_D_BCK_NB.STI",
- "ANIMS\\CORPSES\\M_D_FWD_NB.STI",
- "ANIMS\\CORPSES\\M_D_DHD_NB.STI",
- "ANIMS\\CORPSES\\M_D_PRN_NB.STI",
- "ANIMS\\CORPSES\\S_D_WTR.STI",
- "ANIMS\\CORPSES\\M_D_FALL_NB.STI",
- "ANIMS\\CORPSES\\M_D_FALLF_NB.STI",
- "ANIMS\\CORPSES\\F_D_JFK_NB.STI",
- "ANIMS\\CORPSES\\F_D_BCK_NB.STI",
- "ANIMS\\CORPSES\\F_D_FWD_NB.STI",
- "ANIMS\\CORPSES\\F_D_DHD_NB.STI",
- "ANIMS\\CORPSES\\F_D_PRN_NB.STI",
- "ANIMS\\CORPSES\\S_D_WTR.STI",
- "ANIMS\\CORPSES\\F_D_FALL_NB.STI",
- "ANIMS\\CORPSES\\F_D_FALLF_NB.STI",
- // Civs....
- "ANIMS\\CORPSES\\M_DEAD1_NB.STI",
- "ANIMS\\CORPSES\\K_DEAD2_NB.STI",
- "ANIMS\\CORPSES\\H_DEAD2_NB.STI",
- "ANIMS\\CORPSES\\FT_DEAD1_NB.STI",
- "ANIMS\\CORPSES\\S_DEAD1_NB.STI",
- "ANIMS\\CORPSES\\W_DEAD1_NB.STI",
- "ANIMS\\CORPSES\\CP_DEAD1_NB.STI",
- "ANIMS\\CORPSES\\M_DEAD2_NB.STI",
- "ANIMS\\CORPSES\\K_DEAD1_NB.STI",
- "ANIMS\\CORPSES\\H_DEAD1_NB.STI",
- "ANIMS\\CORPSES\\FT_DEAD2_NB.STI",
- "ANIMS\\CORPSES\\S_DEAD2_NB.STI",
- "ANIMS\\CORPSES\\W_DEAD2_NB.STI",
- "ANIMS\\CORPSES\\CP_DEAD2_NB.STI",
- "ANIMS\\CORPSES\\CT_DEAD.STI",
- "ANIMS\\CORPSES\\CW_DEAD1.STI",
- "ANIMS\\CORPSES\\MN_DEAD2.STI",
- "ANIMS\\CORPSES\\I_DEAD1.STI",
- "ANIMS\\CORPSES\\L_DEAD1.STI",
- "ANIMS\\CORPSES\\P_DECOMP2.STI",
- "ANIMS\\CORPSES\\TK_WREK.STI",
- "ANIMS\\CORPSES\\TK2_WREK.STI",
- "ANIMS\\CORPSES\\HM_WREK.STI",
- "ANIMS\\CORPSES\\IC_WREK.STI",
- "ANIMS\\CORPSES\\QN_DEAD.STI",
- "ANIMS\\CORPSES\\J_DEAD.STI",
- "ANIMS\\CORPSES\\S_BURNT.STI",
- "ANIMS\\CORPSES\\S_EXPLD.STI",
- };
- UINT8 gb4DirectionsFrom8[8] =
- {
- 7, // NORTH
- 0, // NE
- 0, // E
- 0, // SE
- 1, // S
- 0, // SW,
- 2, // W,
- 0 // NW
- };
- UINT8 gb2DirectionsFrom8[8] =
- {
- 0, // NORTH
- 7, // NE
- 7, // E
- 7, // SE
- 0, // S
- 7, // SW,
- 7, // W,
- 7 // NW
- };
- BOOLEAN gbCorpseValidForDecapitation[ NUM_CORPSES ] =
- {
- 0,
- 0,
- 1,
- 1,
- 1,
- 1,
- 1,
- 1,
- 1,
- 0,
- 1,
- 1,
- 1,
- 1,
- 1,
- 1,
- 1,
- 0,
- 1,
- 1,
- 1,
- 1,
- 1,
- 1,
- 1,
- // Civs....
- 1,
- 1,
- 1,
- 1,
- 1,
- 1,
- 1,
- 1,
- 1,
- 1,
- 1,
- 1,
- 1,
- 1,
- 0,
- 0,
- 0,
- 0,
- 0,
- 1,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- };
- INT8 gDecapitatedCorpse[ NUM_CORPSES ] =
- {
- 0,
- SMERC_JFK,
- SMERC_JFK,
- SMERC_JFK,
- SMERC_JFK,
- SMERC_JFK,
- SMERC_JFK,
- SMERC_JFK,
- SMERC_JFK,
- MMERC_JFK,
- MMERC_JFK,
- MMERC_JFK,
- MMERC_JFK,
- MMERC_JFK,
- MMERC_JFK,
- MMERC_JFK,
- MMERC_JFK,
- FMERC_JFK,
- FMERC_JFK,
- FMERC_JFK,
- FMERC_JFK,
- FMERC_JFK,
- FMERC_JFK,
- FMERC_JFK,
- FMERC_JFK,
- // Civs....
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- };
- ROTTING_CORPSE gRottingCorpse[ MAX_ROTTING_CORPSES ];
- INT32 giNumRottingCorpse = 0;
- BOOLEAN CreateCorpsePalette( ROTTING_CORPSE *pCorpse );
- BOOLEAN CreateCorpseShadedPalette( ROTTING_CORPSE *pCorpse, UINT32 uiBase, SGPPaletteEntry *pShadePal);
- void ReduceAmmoDroppedByNonPlayerSoldiers( SOLDIERTYPE *pSoldier, INT32 iInvSlot );
- INT32 GetFreeRottingCorpse(void)
- {
- INT32 iCount;
- for(iCount=0; iCount < giNumRottingCorpse; iCount++)
- {
- if(( gRottingCorpse[iCount].fActivated == FALSE ) )
- return((INT32)iCount);
- }
- if(giNumRottingCorpse < MAX_ROTTING_CORPSES )
- return((INT32)giNumRottingCorpse++);
- return(-1);
- }
- void RecountRottingCorpses(void)
- {
- INT32 uiCount;
- if ( giNumRottingCorpse > 0 )
- {
- for(uiCount=giNumRottingCorpse-1; (uiCount >=0) ; uiCount--)
- {
- if( ( gRottingCorpse[uiCount].fActivated == FALSE ) )
- {
- giNumRottingCorpse=(UINT32)(uiCount+1);
- break;
- }
- }
- }
- }
- UINT16 GetCorpseStructIndex( ROTTING_CORPSE_DEFINITION *pCorpseDef, BOOLEAN fForImage )
- {
- INT8 bDirection;
- switch( pCorpseDef->ubType )
- {
- case QUEEN_MONSTER_DEAD:
- case BURNT_DEAD:
- case EXPLODE_DEAD:
- bDirection = 0;
- break;
- case ICECREAM_DEAD:
- case HUMMER_DEAD:
- // OK , these have 2 directions....
- bDirection = gb2DirectionsFrom8[ pCorpseDef->bDirection ];
- if ( fForImage )
- {
- bDirection = gOneCDirection[ bDirection ];
- }
- break;
- case SMERC_FALL:
- case SMERC_FALLF:
- case MMERC_FALL:
- case MMERC_FALLF:
- case FMERC_FALL:
- case FMERC_FALLF:
- // OK , these have 4 directions....
- bDirection = gb4DirectionsFrom8[ pCorpseDef->bDirection ];
- if ( fForImage )
- {
- bDirection = gOneCDirection[ bDirection ];
- }
- break;
- default:
-
- // Uses 8
- bDirection = pCorpseDef->bDirection;
- if ( fForImage )
- {
- bDirection = gOneCDirection[ bDirection ];
- }
- break;
- }
- return( bDirection );
- }
- INT32 AddRottingCorpse( ROTTING_CORPSE_DEFINITION *pCorpseDef )
- {
- INT32 iIndex;
- ROTTING_CORPSE *pCorpse;
- ANITILE_PARAMS AniParams;
- UINT8 ubLevelID;
- STRUCTURE_FILE_REF * pStructureFileRef = NULL;
- INT8 zFilename[150];
- DB_STRUCTURE_REF *pDBStructureRef;
- UINT8 ubLoop;
- INT16 sTileGridNo;
- DB_STRUCTURE_TILE ** ppTile;
- UINT16 usStructIndex;
- UINT32 uiDirectionUseFlag;
- if ( pCorpseDef->sGridNo == NOWHERE )
- {
- return( -1 );
- }
- if ( pCorpseDef->ubType == NO_CORPSE )
- {
- return( -1 );
- }
- if( ( iIndex = GetFreeRottingCorpse() )==(-1) )
- return(-1);
- pCorpse = &gRottingCorpse[ iIndex ];
- // Copy elements in
- memcpy( pCorpse, pCorpseDef, sizeof( ROTTING_CORPSE_DEFINITION ) );
- uiDirectionUseFlag = ANITILE_USE_DIRECTION_FOR_START_FRAME;
- // If we are a soecial type...
- switch( pCorpseDef->ubType )
- {
- case SMERC_FALL:
- case SMERC_FALLF:
- case MMERC_FALL:
- case MMERC_FALLF:
- case FMERC_FALL:
- case FMERC_FALLF:
- uiDirectionUseFlag = ANITILE_USE_4DIRECTION_FOR_START_FRAME;
- }
- if( !(gTacticalStatus.uiFlags & LOADING_SAVED_GAME ) )
- {
- // OK, AS WE ADD, CHECK FOR TOD AND DECAY APPROPRIATELY
- if ( ( ( GetWorldTotalMin( ) - pCorpse->def.uiTimeOfDeath ) > DELAY_UNTIL_ROTTING ) && ( pCorpse->def.ubType < ROTTING_STAGE2 ) )
- {
- if ( pCorpse->def.ubType <= FMERC_FALLF )
- {
- // Rott!
- pCorpse->def.ubType = ROTTING_STAGE2;
- }
- }
- // If time of death is a few days, now, don't add at all!
- if ( ( ( GetWorldTotalMin( ) - pCorpse->def.uiTimeOfDeath ) > DELAY_UNTIL_DONE_ROTTING ) )
- {
- return( -1 );
- }
- }
- // Check if on roof or not...
- if ( pCorpse->def.bLevel == 0 )
- {
- //ubLevelID = ANI_OBJECT_LEVEL;
- ubLevelID = ANI_STRUCT_LEVEL;
- }
- else
- {
- ubLevelID = ANI_ONROOF_LEVEL;
- }
- memset( &AniParams, 0, sizeof( ANITILE_PARAMS ) );
- AniParams.sGridNo = pCorpse->def.sGridNo;
- AniParams.ubLevelID = ubLevelID;
- AniParams.sDelay = (INT16)( 150 );
- AniParams.sStartFrame = 0;
- AniParams.uiFlags = ANITILE_CACHEDTILE | ANITILE_PAUSED | ANITILE_OPTIMIZEFORSLOWMOVING | ANITILE_ANIMATE_Z | ANITILE_ERASEITEMFROMSAVEBUFFFER | uiDirectionUseFlag;
- AniParams.sX = CenterX( pCorpse->def.sGridNo );
- AniParams.sY = CenterY( pCorpse->def.sGridNo );
- AniParams.sZ = (INT16)pCorpse->def.sHeightAdjustment;
- AniParams.uiUserData3 = pCorpse->def.bDirection;
-
- if ( !gGameSettings.fOptions[ TOPTION_BLOOD_N_GORE ] )
- {
- strcpy( AniParams.zCachedFile, zNoBloodCorpseFilenames[ pCorpse->def.ubType ] );
- }
- else
- {
- strcpy( AniParams.zCachedFile, zCorpseFilenames[ pCorpse->def.ubType ] );
- }
- pCorpse->pAniTile = CreateAnimationTile( &AniParams );
- if ( pCorpse->pAniTile == NULL )
- {
- pCorpse->fActivated = FALSE;
- return( -1 );
- }
- // Set flag and index values
- pCorpse->pAniTile->pLevelNode->uiFlags |= ( LEVELNODE_ROTTINGCORPSE );
- pCorpse->pAniTile->pLevelNode->ubShadeLevel = gpWorldLevelData[ pCorpse->def.sGridNo ].pLandHead->ubShadeLevel;
- pCorpse->pAniTile->pLevelNode->ubSumLights = gpWorldLevelData[ pCorpse->def.sGridNo ].pLandHead->ubSumLights;
- pCorpse->pAniTile->pLevelNode->ubMaxLights = gpWorldLevelData[ pCorpse->def.sGridNo ].pLandHead->ubMaxLights;
- pCorpse->pAniTile->pLevelNode->ubNaturalShadeLevel = gpWorldLevelData[ pCorpse->def.sGridNo ].pLandHead->ubNaturalShadeLevel;
- pCorpse->pAniTile->uiUserData = iIndex;
- pCorpse->iID = iIndex;
- pCorpse->fActivated = TRUE;
- if ( Random( 100 ) > 50 )
- {
- pCorpse->fAttractCrowsOnlyWhenOnScreen = TRUE;
- }
- else
- {
- pCorpse->fAttractCrowsOnlyWhenOnScreen = FALSE;
- }
- pCorpse->iCachedTileID = pCorpse->pAniTile->sCachedTileID;
- if ( pCorpse->iCachedTileID == -1 )
- {
- DeleteAniTile( pCorpse->pAniTile );
- pCorpse->fActivated = FALSE;
- return( -1 );
- }
- // Get palette and create palettes and do substitutions
- if ( !CreateCorpsePalette( pCorpse ) )
- {
- DeleteAniTile( pCorpse->pAniTile );
- pCorpse->fActivated = FALSE;
- return( -1 );
- }
- SetRenderFlags(RENDER_FLAG_FULL);
- if ( pCorpse->def.usFlags & ROTTING_CORPSE_VEHICLE )
- {
- pCorpse->pAniTile->uiFlags |= ( ANITILE_FORWARD | ANITILE_LOOPING );
- // Turn off pause...
- pCorpse->pAniTile->uiFlags &= (~ANITILE_PAUSED);
- }
- InvalidateWorldRedundency( );
- // OK, loop through gridnos for corpse and remove blood.....
- // Get root filename... this removes path and extension
- // USed to find struct data fo rthis corpse...
- GetRootName( zFilename, AniParams.zCachedFile );
- // Add structure data.....
- CheckForAndAddTileCacheStructInfo( pCorpse->pAniTile->pLevelNode, pCorpse->def.sGridNo, ( UINT16 ) ( pCorpse->iCachedTileID ), GetCorpseStructIndex( pCorpseDef, TRUE ) );
- pStructureFileRef = GetCachedTileStructureRefFromFilename( zFilename );
- if ( pStructureFileRef != NULL )
- {
- usStructIndex = GetCorpseStructIndex( pCorpseDef, TRUE );
- pDBStructureRef = &(pStructureFileRef->pDBStructureRef[ usStructIndex ] );
- for (ubLoop = 0; ubLoop < pDBStructureRef->pDBStructure->ubNumberOfTiles; ubLoop++)
- {
- ppTile = pDBStructureRef->ppTile;
- sTileGridNo = pCorpseDef->sGridNo + ppTile[ ubLoop ]->sPosRelToBase;
- //Remove blood
- RemoveBlood( sTileGridNo, pCorpseDef->bLevel );
- }
- }
- // OK, we're done!
- return( iIndex );
- }
- void FreeCorpsePalettes( ROTTING_CORPSE *pCorpse )
- {
- INT32 cnt;
- // Free palettes
- MemFree( pCorpse->p8BPPPalette );
- MemFree( pCorpse->p16BPPPalette );
- for ( cnt = 0; cnt < NUM_CORPSE_SHADES; cnt++ )
- {
- if ( pCorpse->pShades[ cnt ] != NULL )
- {
- MemFree( pCorpse->pShades[ cnt ] );
- pCorpse->pShades[ cnt ] = NULL;
- }
- }
- }
- void RemoveCorpses( )
- {
- INT32 iCount;
- for(iCount=0; iCount < giNumRottingCorpse; iCount++)
- {
- if( ( gRottingCorpse[iCount].fActivated ) )
- {
- RemoveCorpse( iCount );
- }
- }
- giNumRottingCorpse = 0;
- }
- void RemoveCorpse( INT32 iCorpseID )
- {
- // Remove!
- gRottingCorpse[ iCorpseID ].fActivated = FALSE;
- DeleteAniTile( gRottingCorpse[ iCorpseID ].pAniTile );
- FreeCorpsePalettes( &( gRottingCorpse[ iCorpseID ] ) );
- }
- BOOLEAN CreateCorpsePalette( ROTTING_CORPSE *pCorpse )
- {
- CHAR8 zColFilename[ 100 ];
- INT8 bBodyTypePalette;
- SGPPaletteEntry Temp8BPPPalette[ 256 ];
- pCorpse->p8BPPPalette = MemAlloc( sizeof( SGPPaletteEntry ) * 256 );
- CHECKF( pCorpse->p8BPPPalette != NULL );
- bBodyTypePalette = GetBodyTypePaletteSubstitutionCode( NULL, pCorpse->def.ubBodyType, zColFilename );
- // If this corpse has cammo,
- if ( pCorpse->def.ubType == ROTTING_STAGE2 )
- {
- bBodyTypePalette = 0;
- }
- else if ( pCorpse->def.usFlags & ROTTING_CORPSE_USE_CAMMO_PALETTE )
- {
- strcpy( zColFilename, "ANIMS\\camo.COL" );
- bBodyTypePalette = 1;
- }
- if ( bBodyTypePalette == -1 )
- {
- // Use palette from HVOBJECT, then use substitution for pants, etc
- memcpy( pCorpse->p8BPPPalette, gpTileCache[ pCorpse->iCachedTileID ].pImagery->vo->pPaletteEntry, sizeof( pCorpse->p8BPPPalette ) * 256 );
- // Substitute based on head, etc
- SetPaletteReplacement( pCorpse->p8BPPPalette, pCorpse->def.HeadPal );
- SetPaletteReplacement( pCorpse->p8BPPPalette, pCorpse->def.VestPal );
- SetPaletteReplacement( pCorpse->p8BPPPalette, pCorpse->def.PantsPal );
- SetPaletteReplacement( pCorpse->p8BPPPalette, pCorpse->def.SkinPal );
- }
- else if ( bBodyTypePalette == 0 )
- {
- // Use palette from hvobject
- memcpy( pCorpse->p8BPPPalette, gpTileCache[ pCorpse->iCachedTileID ].pImagery->vo->pPaletteEntry, sizeof( pCorpse->p8BPPPalette ) * 256 );
- }
- else
- {
- // Use col file
- if ( CreateSGPPaletteFromCOLFile( Temp8BPPPalette, zColFilename ) )
- {
- // Copy into palette
- memcpy( pCorpse->p8BPPPalette, Temp8BPPPalette, sizeof( pCorpse->p8BPPPalette ) * 256 );
- }
- else
- {
- // Use palette from hvobject
- memcpy( pCorpse->p8BPPPalette, gpTileCache[ pCorpse->iCachedTileID ].pImagery->vo->pPaletteEntry, sizeof( pCorpse->p8BPPPalette ) * 256 );
- }
- }
- // -- BUILD 16BPP Palette from this
- pCorpse->p16BPPPalette = Create16BPPPalette( pCorpse->p8BPPPalette );
- CreateCorpsePaletteTables( pCorpse );
- return( TRUE );
- }
- BOOLEAN TurnSoldierIntoCorpse( SOLDIERTYPE *pSoldier, BOOLEAN fRemoveMerc, BOOLEAN fCheckForLOS )
- {
- ROTTING_CORPSE_DEFINITION Corpse;
- UINT8 ubType;
- INT32 cnt;
- UINT16 usItemFlags = 0; //WORLD_ITEM_DONTRENDER;
- INT32 iCorpseID;
- INT8 bVisible = -1;
- OBJECTTYPE *pObj;
- UINT8 ubNumGoo;
- INT16 sNewGridNo;
- OBJECTTYPE ItemObject;
- if ( pSoldier->sGridNo == NOWHERE )
- {
- return( FALSE );
- }
- // ATE: Change to fix crash when item in hand
- if ( gpItemPointer != NULL && gpItemPointerSoldier == pSoldier )
- {
- CancelItemPointer( );
- }
- // Setup some values!
- memset( &Corpse, 0, sizeof( Corpse ) );
- Corpse.ubBodyType = pSoldier->ubBodyType;
- Corpse.sGridNo = pSoldier->sGridNo;
- Corpse.dXPos = pSoldier->dXPos;
- Corpse.dYPos = pSoldier->dYPos;
- Corpse.bLevel = pSoldier->bLevel;
- Corpse.ubProfile = pSoldier->ubProfile;
- if ( Corpse.bLevel > 0 )
- {
- Corpse.sHeightAdjustment = (INT16)( pSoldier->sHeightAdjustment - WALL_HEIGHT );
- }
- SET_PALETTEREP_ID ( Corpse.HeadPal, pSoldier->HeadPal );
- SET_PALETTEREP_ID ( Corpse.VestPal, pSoldier->VestPal );
- SET_PALETTEREP_ID ( Corpse.SkinPal, pSoldier->SkinPal );
- SET_PALETTEREP_ID ( Corpse.PantsPal, pSoldier->PantsPal );
- if ( pSoldier->bCamo != 0 )
- {
- Corpse.usFlags |= ROTTING_CORPSE_USE_CAMMO_PALETTE;
- }
-
- // Determine corpse type!
- ubType = (UINT8)gubAnimSurfaceCorpseID[ pSoldier->ubBodyType][ pSoldier->usAnimState ];
- Corpse.bDirection = pSoldier->bDirection;
- // If we are a vehicle.... only use 1 direction....
- if ( pSoldier->uiStatusFlags & SOLDIER_VEHICLE )
- {
- Corpse.usFlags |= ROTTING_CORPSE_VEHICLE;
- if ( pSoldier->ubBodyType != ICECREAMTRUCK && pSoldier->ubBodyType != HUMVEE )
- {
- Corpse.bDirection = 7;
- }
- else
- {
- Corpse.bDirection = gb2DirectionsFrom8[ Corpse.bDirection ];
- }
- }
- if ( ubType == QUEEN_MONSTER_DEAD || ubType == BURNT_DEAD || ubType == EXPLODE_DEAD )
- {
- Corpse.bDirection = 7;
- }
-
- // ATE: If bDirection, get opposite
- // if ( ubType == SMERC_FALLF || ubType == MMERC_FALLF || ubType == FMERC_FALLF )
- //{
- // Corpse.bDirection = gOppositeDirection[ Corpse.bDirection ];
- // }
- // Set time of death
- Corpse.uiTimeOfDeath = GetWorldTotalMin( );
- // If corpse is not valid. make items visible
- if ( ubType == NO_CORPSE && pSoldier->bTeam != gbPlayerNum )
- {
- usItemFlags &= (~WORLD_ITEM_DONTRENDER );
- }
- // ATE: If the queen is killed, she should
- // make items visible because it ruins end sequence....
- if ( pSoldier->ubProfile == QUEEN || pSoldier->bTeam == gbPlayerNum )
- {
- bVisible = 1;
- }
- // Not for a robot...
- if ( AM_A_ROBOT( pSoldier ) )
- {
- }
- else if ( ubType == QUEEN_MONSTER_DEAD )
- {
- gTacticalStatus.fLockItemLocators = FALSE;
- ubNumGoo = 6 - ( gGameOptions.ubDifficultyLevel - DIF_LEVEL_EASY );
- sNewGridNo = pSoldier->sGridNo + ( WORLD_COLS * 2 );
- for ( cnt = 0; cnt < ubNumGoo; cnt++ )
- {
- CreateItem( JAR_QUEEN_CREATURE_BLOOD, 100, &ItemObject );
- AddItemToPool( sNewGridNo, &ItemObject, bVisible , pSoldier->bLevel, usItemFlags, -1 );
- }
- }
- else
- {
- // OK, Place what objects this guy was carrying on the ground!
- for ( cnt = 0; cnt < NUM_INV_SLOTS; cnt++ )
- {
- pObj = &( pSoldier->inv[ cnt ] );
- if ( pObj->usItem != NOTHING )
- {
- // Check if it's supposed to be dropped
- if ( !( pObj->fFlags & OBJECT_UNDROPPABLE ) || pSoldier->bTeam == gbPlayerNum )
- {
- // and make sure that it really is a droppable item type
- if ( !(Item[ pObj->usItem ].fFlags & ITEM_DEFAULT_UNDROPPABLE) )
- {
- ReduceAmmoDroppedByNonPlayerSoldiers( pSoldier, cnt );
- AddItemToPool( pSoldier->sGridNo, pObj, bVisible , pSoldier->bLevel, usItemFlags, -1 );
- }
- }
- }
- }
- DropKeysInKeyRing( pSoldier, pSoldier->sGridNo, pSoldier->bLevel, bVisible, FALSE, 0, FALSE );
- }
- // Make team look for items
- AllSoldiersLookforItems( TRUE );
- //if we are to call TacticalRemoveSoldier after adding the corpse
- if( fRemoveMerc )
- {
- // If not a player, you can completely remove soldiertype
- // otherwise, just remove their graphic
- if ( pSoldier->bTeam != gbPlayerNum )
- {
- // Remove merc!
- // ATE: Remove merc slot first - will disappear if no corpse data found!
- TacticalRemoveSoldier( pSoldier->ubID );
- }
- else
- {
- RemoveSoldierFromGridNo( pSoldier );
- }
-
- if ( ubType == NO_CORPSE )
- {
- return( TRUE );
- }
- // Set type
- Corpse.ubType = ubType;
- // Add corpse!
- iCorpseID = AddRottingCorpse( &Corpse );
- }
- else
- {
- if ( ubType == NO_CORPSE )
- {
- return( TRUE );
- }
- // Set type
- Corpse.ubType = ubType;
- // Add corpse!
- iCorpseID = AddRottingCorpse( &Corpse );
- }
- // If this is our guy......make visible...
- //if ( pSoldier->bTeam == gbPlayerNum )
- {
- MakeCorpseVisible( pSoldier, &( gRottingCorpse[ iCorpseID ] ) );
- }
- return( TRUE );
- }
- INT16 FindNearestRottingCorpse( SOLDIERTYPE *pSoldier )
- {
- INT32 uiRange, uiLowestRange = 999999;
- INT16 sLowestGridNo = NOWHERE;
- INT32 cnt;
- ROTTING_CORPSE *pCorpse;
- // OK, loop through our current listing of bodies
- for ( cnt = 0; cnt < giNumRottingCorpse; cnt++ )
- {
- pCorpse = &(gRottingCorpse[ cnt ] );
- if ( pCorpse->fActivated )
- {
- // Check rotting state
- if ( pCorpse->def.ubType == ROTTING_STAGE2 )
- {
- uiRange = GetRangeInCellCoordsFromGridNoDiff( pSoldier->sGridNo, pCorpse->def.sGridNo );
- if ( uiRange < uiLowestRange )
- {
- sLowestGridNo = pCorpse->def.sGridNo;
- uiLowestRange = uiRange;
- }
- }
- }
- }
- return( sLowestGridNo );
- }
- void AddCrowToCorpse( ROTTING_CORPSE *pCorpse )
- {
- SOLDIERCREATE_STRUCT MercCreateStruct;
- INT8 bBodyType = CROW;
- UINT8 iNewIndex;
- INT16 sGridNo;
- UINT8 ubDirection;
- SOLDIERTYPE *pSoldier;
- UINT8 ubRoomNum;
- // No crows inside :(
- if ( InARoom( pCorpse->def.sGridNo, &ubRoomNum ) )
- {
- return;
- }
- // Put him flying over corpse pisition
- memset( &MercCreateStruct, 0, sizeof( MercCreateStruct ) );
- MercCreateStruct.ubProfile = NO_PROFILE;
- MercCreateStruct.sSectorX = gWorldSectorX;
- MercCreateStruct.sSectorY = gWorldSectorY;
- MercCreateStruct.bSectorZ = gbWorldSectorZ;
- MercCreateStruct.bBodyType = bBodyType;
- MercCreateStruct.bDirection = SOUTH;
- MercCreateStruct.bTeam = CIV_TEAM;
- MercCreateStruct.sInsertionGridNo = pCorpse->def.sGridNo;
- RandomizeNewSoldierStats( &MercCreateStruct );
- if ( TacticalCreateSoldier( &MercCreateStruct, &iNewIndex ) != NULL )
- {
- pSoldier = MercPtrs[ iNewIndex ];
- sGridNo = FindRandomGridNoFromSweetSpot( pSoldier, pCorpse->def.sGridNo, 2, &ubDirection );
-
- if ( sGridNo != NOWHERE )
- {
- pSoldier->ubStrategicInsertionCode = INSERTION_CODE_GRIDNO;
- pSoldier->usStrategicInsertionData = sGridNo;
- pSoldier->sInsertionGridNo = sGridNo;
- pSoldier->sDesiredHeight = 0;
- // Add to sector
- AddSoldierToSector( iNewIndex );
- // Change to fly animation
- //sGridNo = FindRandomGridNoFromSweetSpot( pSoldier, pCorpse->def.sGridNo, 5, &ubDirection );
- //pSoldier->usUIMovementMode = CROW_FLY;
- //EVENT_GetNewSoldierPath( pSoldier, sGridNo, pSoldier->usUIMovementMode );
- // Setup action data to point back to corpse....
- pSoldier->uiPendingActionData1 = pCorpse->iID;
- pSoldier->sPendingActionData2 = pCorpse->def.sGridNo;
- pCorpse->def.bNumServicingCrows++;
- }
- }
- }
- void HandleCrowLeave( SOLDIERTYPE *pSoldier )
- {
- ROTTING_CORPSE *pCorpse;
- // Check if this crow is still referencing the same corpse...
- pCorpse = &(gRottingCorpse[ pSoldier->uiPendingActionData1 ] );
-
- // Double check grindo...
- if ( pSoldier->sPendingActionData2 == pCorpse->def.sGridNo )
- {
- // We have a match
- // Adjust crow servicing count...
- pCorpse->def.bNumServicingCrows--;
- if ( pCorpse->def.bNumServicingCrows < 0 )
- {
- pCorpse->def.bNumServicingCrows = 0;
- }
- }
- }
- void HandleCrowFlyAway( SOLDIERTYPE *pSoldier )
- {
- UINT8 ubDirection;
- INT16 sGridNo;
- // Set desired height
- pSoldier->sDesiredHeight = 100;
- // Change to fly animation
- sGridNo = FindRandomGridNoFromSweetSpot( pSoldier, pSoldier->sGridNo, 5, &ubDirection );
- pSoldier->usUIMovementMode = CROW_FLY;
- SendGetNewSoldierPathEvent( pSoldier, sGridNo, pSoldier->usUIMovementMode );
- }
- void HandleRottingCorpses( )
- {
- ROTTING_CORPSE *pCorpse;
- INT8 bNumCrows = 0;
- UINT32 uiChosenCorpseID;
- // Don't allow crows here if flags not set
- if ( !gTacticalStatus.fGoodToAllowCrows )
- {
- return;
- }
- // ATE: If it's too late, don't!
- if( NightTime() )
- {
- return;
- }
- if ( gbWorldSectorZ > 0 )
- {
- return;
- }
- // ATE: Check for multiple crows.....
- // Couint how many we have now...
- {
- UINT8 bLoop;
- SOLDIERTYPE * pSoldier;
- for (bLoop=gTacticalStatus.Team[ CIV_TEAM ].bFirstID, pSoldier=MercPtrs[bLoop]; bLoop <= gTacticalStatus.Team[ CIV_TEAM ].bLastID; bLoop++, pSoldier++)
- {
- if (pSoldier->bActive && pSoldier->bInSector && (pSoldier->bLife >= OKLIFE) && !( pSoldier->uiStatusFlags & SOLDIER_GASSED ) )
- {
- if ( pSoldier->ubBodyType == CROW )
- {
- bNumCrows++;
- }
- }
- }
- }
- // Once population gets down to 0, we can add more again....
- if ( bNumCrows == 0 )
- {
- gTacticalStatus.fDontAddNewCrows = FALSE;
- }
- if ( gTacticalStatus.fDontAddNewCrows )
- {
- return;
- }
- if ( bNumCrows >= gTacticalStatus.ubNumCrowsPossible )
- {
- gTacticalStatus.fDontAddNewCrows = TRUE;
- return;
- }
- if ( gTacticalStatus.Team[ CREATURE_TEAM ].bTeamActive )
- {
- // don't add any crows while there are predators around
- return;
- }
- // Pick one to attact a crow...
- {
- uiChosenCorpseID = Random( giNumRottingCorpse );
- pCorpse = &(gRottingCorpse[ uiChosenCorpseID ] );
- if ( pCorpse->fActivated )
- {
- if ( !( pCorpse->def.usFlags & ROTTING_CORPSE_VEHICLE ) )
- {
- if ( pCorpse->def.ubType == ROTTING_STAGE2 )
- {
- if ( GridNoOnScreen( pCorpse->def.sGridNo ) )
- {
- return;
- }
- AddCrowToCorpse( pCorpse );
- AddCrowToCorpse( pCorpse );
- }
- }
- }
- }
- }
- void MakeCorpseVisible( SOLDIERTYPE *pSoldier, ROTTING_CORPSE *pCorpse )
- {
- pCorpse->def.bVisible = 1;
- SetRenderFlags( RENDER_FLAG_FULL );
- }
- void AllMercsOnTeamLookForCorpse( ROTTING_CORPSE *pCorpse, INT8 bTeam )
- {
- INT32 cnt;
- SOLDIERTYPE *pSoldier;
- INT16 sDistVisible;
- INT16 sGridNo;
- // If this cump is already visible, return
- if ( pCorpse->def.bVisible == 1 )
- {
- return;
- }
- if ( !pCorpse->fActivated )
- {
- return;
- }
- // IF IT'S THE SELECTED GUY, MAKE ANOTHER SELECTED!
- cnt = gTacticalStatus.Team[ bTeam ].bFirstID;
- sGridNo = pCorpse->def.sGridNo;
- // look for all mercs on the same team,
- for ( pSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ bTeam ].bLastID; cnt++,pSoldier++ )
- {
- // ATE: Ok, lets check for some basic things here!
- if ( pSoldier->bLife >= OKLIFE && pSoldier->sGridNo != NOWHERE && pSoldier->bActive && pSoldier->bInSector )
- {
- // is he close enough to see that gridno if he turns his head?
- sDistVisible = DistanceVisible( pSoldier, DIRECTION_IRRELEVANT, DIRECTION_IRRELEVANT, sGridNo, pCorpse->def.bLevel );
-
- if (PythSpacesAway( pSoldier->sGridNo, sGridNo ) <= sDistVisible )
- {
- // and we can trace a line of sight to his x,y coordinates?
- // (taking into account we are definitely aware of this guy now)
- if ( SoldierTo3DLocationLineOfSightTest( pSoldier, sGridNo, pCorpse->def.bLevel, 3, (UINT8) sDistVisible, TRUE ) )
- {
- MakeCorpseVisible( pSoldier, pCorpse );
- return;
- }
- }
- }
- }
- }
- void MercLooksForCorpses( SOLDIERTYPE *pSoldier )
- {
- INT32 cnt;
- INT16 sDistVisible;
- INT16 sGridNo;
- ROTTING_CORPSE *pCorpse;
- // Should we say disgust quote?
- if ( ( pSoldier->usQuoteSaidFlags & SOLDIER_QUOTE_SAID_ROTTINGCORPSE ) )
- {
- return;
- }
- if ( pSoldier->ubProfile == NO_PROFILE )
- {
- return;
- }
- if ( AM_AN_EPC( pSoldier ) )
- {
- return;
- }
- if ( QuoteExp_HeadShotOnly[ pSoldier->ubProfile ] == 1 )
- {
- return;
- }
- // Every so often... do a corpse quote...
- if ( Random( 400 ) <= 2 )
- {
- // Loop through all corpses....
- for ( cnt = 0; cnt < giNumRottingCorpse; cnt++ )
- {
- pCorpse = &(gRottingCorpse[ cnt ] );
- if ( !pCorpse->fActivated )
- {
- continue;
- }
- // Has this corpse rotted enough?
- if ( pCorpse->def.ubType == ROTTING_STAGE2 )
- {
- sGridNo = pCorpse->def.sGridNo;
- // is he close enough to see that gridno if he turns his head?
- sDistVisible = DistanceVisible( pSoldier, DIRECTION_IRRELEVANT, DIRECTION_IRRELEVANT, sGridNo, pCorpse->def.bLevel );
-
- if (PythSpacesAway( pSoldier->sGridNo, sGridNo ) <= sDistVisible )
- {
- // and we can trace a line of sight to his x,y coordinates?
- // (taking into account we are definitely aware of this guy now)
- if ( SoldierTo3DLocationLineOfSightTest( pSoldier, sGridNo, pCorpse->def.bLevel, 3, (UINT8) sDistVisible, TRUE ) )
- {
- TacticalCharacterDialogue( pSoldier, QUOTE_HEADSHOT );
- pSoldier->usQuoteSaidFlags |= SOLDIER_QUOTE_SAID_ROTTINGCORPSE;
- BeginMultiPurposeLocator( sGridNo, pCorpse->def.bLevel, FALSE );
- // Slide to...
- SlideToLocation( 0, sGridNo );
- return;
- }
- }
- }
- }
- }
- }
- void RebuildAllCorpseShadeTables( )
- {
- INT32 cnt;
- ROTTING_CORPSE *pCorpse;
- // Loop through all corpses....
- for ( cnt = 0; cnt < giNumRottingCorpse; cnt++ )
- {
- pCorpse = &(gRottingCorpse[ cnt ] );
- // If this cump is already visible, continue
- if ( pCorpse->def.bVisible == 1 )
- {
- continue;
- }
- if ( !pCorpse->fActivated )
- {
- continue;
- }
- // Rebuild shades....
- }
- }
- UINT16 CreateCorpsePaletteTables( ROTTING_CORPSE *pCorpse )
- {
- SGPPaletteEntry LightPal[256];
- UINT32 uiCount;
- // create the basic shade table
- for(uiCount=0; uiCount < 256; uiCount++)
- {
- // combine the rgb of the light color with the object's palette
- LightPal[uiCount].peRed=(UINT8)(__min((UINT16)pCorpse->p8BPPPalette[uiCount].peRed+(UINT16)gpLightColors[0].peRed, 255));
- LightPal[uiCount].peGreen=(UINT8)(__min((UINT16)pCorpse->p8BPPPalette[uiCount].peGreen+(UINT16)gpLightColors[0].peGreen, 255));
- LightPal[uiCount].peBlue=(UINT8)(__min((UINT16)pCorpse->p8BPPPalette[uiCount].peBlue+(UINT16)gpLightColors[0].peBlue, 255));
- }
- // build the shade tables
- CreateCorpseShadedPalette( pCorpse, 0, LightPal );
- // build neutral palette as well!
- // Set current shade table to neutral color
- return(TRUE);
- }
- BOOLEAN CreateCorpseShadedPalette( ROTTING_CORPSE *pCorpse, UINT32 uiBase, SGPPaletteEntry *pShadePal )
- {
- UINT32 uiCount;
- pCorpse->pShades[uiBase] = Create16BPPPaletteShaded( pShadePal, gusShadeLevels[0][0],
- gusShadeLevels[0][1],
- gusShadeLevels[0][2], TRUE);
-
- for(uiCount=1; uiCount < 16; uiCount++)
- {
- pCorpse->pShades[uiBase+uiCount]=Create16BPPPaletteShaded( pShadePal, gusShadeLevels[uiCount][0],
- gusShadeLevels[uiCount][1],
- gusShadeLevels[uiCount][2], FALSE);
- }
- return(TRUE);
- }
- ROTTING_CORPSE *FindCorpseBasedOnStructure( INT16 sGridNo, STRUCTURE *pStructure )
- {
- LEVELNODE *pLevelNode;
- ROTTING_CORPSE *pCorpse = NULL;
- pLevelNode = gpWorldLevelData[ sGridNo ].pStructHead;
- while( pLevelNode != NULL )
- {
- if (pLevelNode->pStructureData == pStructure )
- {
- break;
- }
- pLevelNode = pLevelNode->pNext;
- }
-
- if ( pLevelNode != NULL )
- {
- // Get our corpse....
- pCorpse = &( gRottingCorpse[ pLevelNode->pAniTile->uiUserData ] );
- }
- return( pCorpse );
- }
- void CorpseHit( INT16 sGridNo, UINT16 usStructureID )
- {
- #if 0
- STRUCTURE *pStructure, *pBaseStructure;
- ROTTING_CORPSE *pCorpse = NULL;
- INT16 sBaseGridNo;
-
- pStructure = FindStructureByID( sGridNo, usStructureID );
-
- // Get base....
- pBaseStructure = FindBaseStructure( pStructure );
- // Find base gridno...
- sBaseGridNo = pBaseStructure->sGridNo;
- // Get corpse ID.....
- pCorpse = FindCorpseBasedOnStructure( sBaseGridNo, pBaseStructure );
- if ( pCorpse == NULL )
- {
- #ifdef JA2TESTVERSION
- ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_TESTVERSION, L"Bullet hit corpse but corpse cannot be found at: %d", sBaseGridNo );
- #endif
- return;
- }
- // Twitch the bugger...
- #ifdef JA2BETAVERSION
- ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_TESTVERSION, L"Corpse hit" );
- #endif
- if ( GridNoOnScreen( sBaseGridNo ) )
- {
- // Twitch....
- // Set frame...
- SetAniTileFrame( pCorpse->pAniTile, 1 );
- // Go reverse...
- pCorpse->pAniTile->uiFlags |= ( ANITILE_BACKWARD | ANITILE_PAUSE_AFTER_LOOP );
- // Turn off pause...
- pCorpse->pAniTile->uiFlags &= (~ANITILE_PAUSED);
- }
- // PLay a sound....
- PlayJA2Sample( (UINT32)( BULLET_IMPACT_2 ), RATE_11025, SoundVolume( MIDVOLUME, sGridNo ), 1, SoundDir( sGridNo ) );
- #endif
- }
- void VaporizeCorpse( INT16 sGridNo, UINT16 usStructureID )
- {
- STRUCTURE *pStructure, *pBaseStructure;
- ROTTING_CORPSE *pCorpse = NULL;
- INT16 sBaseGridNo;
- ANITILE_PARAMS AniParams;
-
- pStructure = FindStructureByID( sGridNo, usStructureID );
-
- // Get base....
- pBaseStructure = FindBaseStructure( pStructure );
- // Find base gridno...
- sBaseGridNo = pBaseStructure->sGridNo;
- // Get corpse ID.....
- pCorpse = FindCorpseBasedOnStructure( sBaseGridNo, pBaseStructure );
- if ( pCorpse == NULL )
- {
- #ifdef JA2TESTVERSION
- ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_TESTVERSION, L"Vaporize corpse but corpse cannot be found at: %d", sBaseGridNo );
- #endif
- return;
- }
- if ( pCorpse->def.usFlags & ROTTING_CORPSE_VEHICLE )
- {
- return;
- }
- if ( GridNoOnScreen( sBaseGridNo ) )
- {
- // Add explosion
- memset( &AniParams, 0, sizeof( ANITILE_PARAMS ) );
- AniParams.sGridNo = sBaseGridNo;
- AniParams.ubLevelID = ANI_STRUCT_LEVEL;
- AniParams.sDelay = (INT16)( 80 );
- AniParams.sStartFrame = 0;
- AniParams.uiFlags = ANITILE_CACHEDTILE | ANITILE_FORWARD;
- AniParams.sX = CenterX( sBaseGridNo );
- AniParams.sY = CenterY( sBaseGridNo );
- AniParams.sZ = (INT16)pCorpse->def.sHeightAdjustment;
-
- strcpy( AniParams.zCachedFile, "TILECACHE\\GEN_BLOW.STI" );
- CreateAnimationTile( &AniParams );
- // Remove....
- RemoveCorpse( pCorpse->iID );
- SetRenderFlags( RENDER_FLAG_FULL );
-
- if ( pCorpse->def.bLevel == 0 )
- {
- // Set some blood......
- SpreadEffect( sBaseGridNo, (UINT8)( ( 2 ) ), 0, NOBODY, BLOOD_SPREAD_EFFECT, 0, -1 );
- }
- }
- // PLay a sound....
- PlayJA2Sample( (UINT32)( BODY_EXPLODE_1 ), RATE_11025, SoundVolume( HIGHVOLUME, sGridNo ), 1, SoundDir( sGridNo ) );
-
- }
- INT16 FindNearestAvailableGridNoForCorpse( ROTTING_CORPSE_DEFINITION *pDef, INT8 ubRadius )
- {
- INT16 sSweetGridNo;
- INT16 sTop, sBottom;
- INT16 sLeft, sRight;
- INT16 cnt1, cnt2, cnt3;
- INT16 sGridNo;
- INT32 uiRange, uiLowestRange = 999999;
- INT16 sLowestGridNo=0;
- INT32 leftmost;
- BOOLEAN fFound = FALSE;
- SOLDIERTYPE soldier;
- UINT8 ubSaveNPCAPBudget;
- UINT8 ubSaveNPCDistLimit;
- STRUCTURE_FILE_REF * pStructureFileRef = NULL;
- INT8 zFilename[150];
- UINT8 ubBestDirection=0;
- BOOLEAN fSetDirection = FALSE;
- cnt3 = 0;
- // Get root filename... this removes path and extension
- // USed to find struct data fo rthis corpse...
- GetRootName( zFilename, zCorpseFilenames[pDef->ubType ] );
- pStructureFileRef = GetCachedTileStructureRefFromFilename( zFilename );
- sSweetGridNo = pDef->sGridNo;
- //Save AI pathing vars. changing the distlimit restricts how
- //far away the pathing will consider.
- ubSaveNPCAPBudget = gubNPCAPBudget;
- ubSaveNPCDistLimit = gubNPCDistLimit;
- gubNPCAPBudget = 0;
- gubNPCDistLimit = ubRadius;
- //create dummy soldier, and use the pathing to determine which nearby slots are
- //reachable.
- memset( &soldier, 0, sizeof( SOLDIERTYPE ) );
- soldier.bTeam = 1;
- soldier.sGridNo = sSweetGridNo;
- sTop = ubRadius;
- sBottom = -ubRadius;
- sLeft = - ubRadius;
- sRight = ubRadius;
- //clear the mapelements of potential residue MAPELEMENT_REACHABLE flags
- //in the square region.
- for( cnt1 = sBottom; cnt1 <= sTop; cnt1++ )
- {
- for( cnt2 = sLeft; cnt2 <= sRight; cnt2++ )
- {
- sGridNo = sSweetGridNo + (WORLD_COLS * cnt1) + cnt2;
- if ( sGridNo >=0 && sGridNo < WORLD_MAX )
- {
- gpWorldLevelData[ sGridNo ].uiFlags &= (~MAPELEMENT_REACHABLE);
- }
- }
- }
- //Now, find out which of these gridnos are reachable
- //(use the fake soldier and the pathing settings)
- FindBestPath( &soldier, NOWHERE, 0, WALKING, COPYREACHABLE, 0 );
-
- uiLowestRange = 999999;
- for( cnt1 = sBottom; cnt1 <= sTop; cnt1++ )
- {
- leftmost = ( ( sSweetGridNo + ( WORLD_COLS * cnt1 ) )/ WORLD_COLS ) * WORLD_COLS;
- for( cnt2 = sLeft; cnt2 <= sRight; cnt2++ )
- {
- sGridNo = sSweetGridNo + ( WORLD_COLS * cnt1 ) + cnt2;
- if ( sGridNo >=0 && sGridNo < WORLD_MAX && sGridNo >= leftmost && sGridNo < ( leftmost + WORLD_COLS ) &&
- gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_REACHABLE )
- {
- // Go on sweet stop
- if ( NewOKDestination( &soldier, sGridNo, TRUE, soldier.bLevel ) )
- {
- BOOLEAN fDirectionFound = FALSE;
- BOOLEAN fCanSetDirection = FALSE;
- // Check each struct in each direction
- if ( pStructureFileRef == NULL )
- {
- fDirectionFound = TRUE;
- }
- else
- {
- for( cnt3 = 0; cnt3 < 8; cnt3++ )
- {
- if ( OkayToAddStructureToWorld( (INT16)sGridNo, pDef->bLevel, &(pStructureFileRef->pDBStructureRef[gOneCDirection[ cnt3 ]]), INVALID_STRUCTURE_ID ) )
- {
- fDirectionFound = TRUE;
- fCanSetDirection = TRUE;
- break;
- }
- }
- }
- if ( fDirectionFound )
- {
- uiRange = GetRangeInCellCoordsFromGridNoDiff( sSweetGridNo, sGridNo );
- if ( uiRange < uiLowestRange )
- {
- if ( fCanSetDirection )
- {
- ubBestDirection = (UINT8)cnt3;
- fSetDirection = TRUE;
- }
- sLowestGridNo = sGridNo;
- uiLowestRange = uiRange;
- fFound = TRUE;
- }
- }
- }
- }
- }
- }
- gubNPCAPBudget = ubSaveNPCAPBudget;
- gubNPCDistLimit = ubSaveNPCDistLimit;
- if ( fFound )
- {
- if ( fSetDirection )
- {
- pDef->bDirection = ubBestDirection;
- }
- return sLowestGridNo;
- }
- return NOWHERE;
- }
- BOOLEAN IsValidDecapitationCorpse( ROTTING_CORPSE *pCorpse )
- {
- if ( pCorpse->def.fHeadTaken )
- {
- return( FALSE );
- }
- return( gbCorpseValidForDecapitation[ pCorpse->def.ubType ] );
- }
- ROTTING_CORPSE *GetCorpseAtGridNo( INT16 sGridNo, INT8 bLevel )
- {
- STRUCTURE *pStructure, *pBaseStructure;
- INT16 sBaseGridNo;
- pStructure = FindStructure( sGridNo, STRUCTURE_CORPSE );
- if ( pStructure != NULL )
- {
- // Get base....
- pBaseStructure = FindBaseStructure( pStructure );
- // Find base gridno...
- sBaseGridNo = pBaseStructure->sGridNo;
- if ( pBaseStructure != NULL )
- {
- return( FindCorpseBasedOnStructure( sBaseGridNo, pBaseStructure ) );
- }
- }
- return( NULL );
- }
- void DecapitateCorpse( SOLDIERTYPE *pSoldier, INT16 sGridNo, INT8 bLevel )
- {
- OBJECTTYPE Object;
- ROTTING_CORPSE *pCorpse;
- ROTTING_CORPSE_DEFINITION CorpseDef;
- UINT16 usHeadIndex = HEAD_1;
- pCorpse = GetCorpseAtGridNo( sGridNo, bLevel );
- if ( pCorpse == NULL )
- {
- return;
- }
- if ( IsValidDecapitationCorpse( pCorpse ) )
- {
- // Decapitate.....
- // Copy corpse definition...
- memcpy( &CorpseDef, &(pCorpse->def), sizeof( ROTTING_CORPSE_DEFINITION ) );
- // Add new one...
- CorpseDef.ubType = gDecapitatedCorpse[ CorpseDef.ubType ];
- pCorpse->def.fHeadTaken = TRUE;
- if ( CorpseDef.ubType != 0 )
- {
- // Remove old one...
- RemoveCorpse( pCorpse->iID );
- AddRottingCorpse( &CorpseDef );
- }
- // Add head item.....
- // Pick the head based on profile type...
- switch( pCorpse->def.ubProfile )
- {
- case 83:
- usHeadIndex = HEAD_2;
- break;
- case 111:
- usHeadIndex = HEAD_3;
- break;
- case 64:
- usHeadIndex = HEAD_4;
- break;
- case 112:
- usHeadIndex = HEAD_5;
- break;
- case 82:
- usHeadIndex = HEAD_6;
- break;
- case 110:
- usHeadIndex = HEAD_7;
- break;
- }
- CreateItem( usHeadIndex, 100, &Object );
- AddItemToPool( sGridNo, &Object, INVISIBLE, 0, 0, 0 );
- // All teams lok for this...
- NotifySoldiersToLookforItems( );
- }
-
- }
- void GetBloodFromCorpse( SOLDIERTYPE *pSoldier )
- {
- ROTTING_CORPSE *pCorpse;
- INT8 bObjSlot;
- OBJECTTYPE Object;
- // OK, get corpse
- pCorpse = &( gRottingCorpse[ pSoldier->uiPendingActionData4 ] );
- bObjSlot = FindObj( pSoldier, JAR );
- // What kind of corpse ami I?
- switch( pCorpse->def.ubType )
- {
- case ADULTMONSTER_DEAD:
- case INFANTMONSTER_DEAD:
- // Can get creature blood....
- CreateItem( JAR_CREATURE_BLOOD, 100, &Object );
- break;
- case QUEEN_MONSTER_DEAD:
- CreateItem( JAR_QUEEN_CREATURE_BLOOD, 100, &Object );
- break;
- default:
- CreateItem( JAR_HUMAN_BLOOD, 100, &Object );
- break;
- }
- if ( bObjSlot != NO_SLOT )
- {
- SwapObjs( &(pSoldier->inv[ bObjSlot ] ), &Object );
- }
- }
- void ReduceAmmoDroppedByNonPlayerSoldiers( SOLDIERTYPE *pSoldier, INT32 iInvSlot )
- {
- OBJECTTYPE *pObj;
- Assert( pSoldier );
- Assert( ( iInvSlot >= 0 ) && ( iInvSlot < NUM_INV_SLOTS ) );
- pObj = &( pSoldier->inv[ iInvSlot ] );
- // if not a player soldier
- if ( pSoldier->bTeam != gbPlayerNum )
- {
- // if it's ammo
- if ( Item[ pObj->usItem ].usItemClass == IC_AMMO )
- {
- //don't drop all the clips, just a random # of them between 1 and how many there are
- pObj->ubNumberOfObjects = ( UINT8 ) ( 1 + Random( pObj->ubNumberOfObjects ) );
- // recalculate the weight
- pObj->ubWeight = CalculateObjectWeight( pObj );
- }
- }
- }
- void LookForAndMayCommentOnSeeingCorpse( SOLDIERTYPE *pSoldier, INT16 sGridNo, UINT8 ubLevel )
- {
- ROTTING_CORPSE *pCorpse;
- INT8 bToleranceThreshold = 0;
- INT32 cnt;
- SOLDIERTYPE *pTeamSoldier;
- if ( QuoteExp_HeadShotOnly[ pSoldier->ubProfile ] == 1 )
- {
- return;
- }
- pCorpse = GetCorpseAtGridNo( sGridNo, ubLevel );
- if ( pCorpse == NULL )
- {
- return;
- }
- if ( pCorpse->def.ubType != ROTTING_STAGE2 )
- {
- return;
- }
- // If servicing qrows, tolerance is now 1
- if ( pCorpse->def.bNumServicingCrows > 0 )
- {
- bToleranceThreshold++;
- }
- // Check tolerance
- if ( pSoldier->bCorpseQuoteTolerance <= bToleranceThreshold )
- {
- // Say quote...
- TacticalCharacterDialogue( pSoldier, QUOTE_HEADSHOT );
- BeginMultiPurposeLocator( sGridNo, ubLevel, FALSE );
- // Reset values....
- pSoldier->bCorpseQuoteTolerance = (INT8)( Random(3) + 1 );
- // 50% chance of adding 1 to other mercs....
- if ( Random( 2 ) == 1 )
- {
- // IF IT'S THE SELECTED GUY, MAKE ANOTHER SELECTED!
- cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
- // look for all mercs on the same team,
- for ( pTeamSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; cnt++,pTeamSoldier++ )
- {
- // ATE: Ok, lets check for some basic things here!
- if ( pTeamSoldier->bLife >= OKLIFE && pTeamSoldier->sGridNo != NOWHERE && pTeamSoldier->bActive && pTeamSoldier->bInSector )
- {
- pTeamSoldier->bCorpseQuoteTolerance++;
- }
- }
- }
- }
- }
- INT16 GetGridNoOfCorpseGivenProfileID( UINT8 ubProfileID )
- {
- INT32 cnt;
- ROTTING_CORPSE *pCorpse;
- // Loop through all corpses....
- for ( cnt = 0; cnt < giNumRottingCorpse; cnt++ )
- {
- pCorpse = &(gRottingCorpse[ cnt ] );
- if ( pCorpse->fActivated )
- {
- if ( pCorpse->def.ubProfile == ubProfileID )
- {
- return( pCorpse->def.sGridNo );
- }
- }
- }
- return( NOWHERE );
- }
- void DecayRottingCorpseAIWarnings( void )
- {
- INT32 cnt;
- ROTTING_CORPSE * pCorpse;
- for ( cnt = 0; cnt < giNumRottingCorpse; cnt++ )
- {
- pCorpse = &(gRottingCorpse[ cnt ] );
- if ( pCorpse->fActivated && pCorpse->def.ubAIWarningValue > 0 )
- {
- pCorpse->def.ubAIWarningValue--;
- }
- }
-
- }
- UINT8 GetNearestRottingCorpseAIWarning( INT16 sGridNo )
- {
- INT32 cnt;
- ROTTING_CORPSE * pCorpse;
- UINT8 ubHighestWarning = 0;
- for ( cnt = 0; cnt < giNumRottingCorpse; cnt++ )
- {
- pCorpse = &(gRottingCorpse[ cnt ] );
- if ( pCorpse->fActivated && pCorpse->def.ubAIWarningValue > 0 )
- {
- if ( PythSpacesAway( sGridNo, pCorpse->def.sGridNo ) <= CORPSE_WARNING_DIST )
- {
- if ( pCorpse->def.ubAIWarningValue > ubHighestWarning )
- {
- ubHighestWarning = pCorpse->def.ubAIWarningValue;
- }
- }
- }
- }
- return( ubHighestWarning );
- }
|