123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154 |
- #ifdef PRECOMPILEDHEADERS
- #include "Tactical All.h"
- #else
- #include "sgp.h"
- #include "worlddef.h"
- #include "points.h"
- #include "overhead.h"
- #include "Font control.h"
- #include "interface.h"
- #include "Isometric utils.h"
- #include "pathai.h"
- #include "interface.h"
- #include "message.h"
- #include "Animation Control.h"
- #include "Weapons.h"
- #include "structure wrap.h"
- #include "dialogue control.h"
- #include "items.h"
- #include "rt time defines.h"
- #include "ai.h"
- #include "handle ui.h"
- #include "text.h"
- #include "SkillCheck.h"
- #include "wcheck.h"
- #include "Soldier Profile.h"
- #endif
- extern BOOLEAN IsValidSecondHandShot( SOLDIERTYPE *pSoldier );
- INT16 GetBreathPerAP( SOLDIERTYPE *pSoldier, UINT16 usAnimState );
- INT16 TerrainActionPoints( SOLDIERTYPE *pSoldier, INT16 sGridno, INT8 bDir, INT8 bLevel )
- {
- INT16 sAPCost = 0;
- INT16 sSwitchValue;
- BOOLEAN fHiddenStructVisible; // Used for hidden struct visiblity
- if ( pSoldier->bStealthMode )
- sAPCost += AP_STEALTH_MODIFIER;
-
- if ( pSoldier->bReverse || gUIUseReverse )
- sAPCost += AP_REVERSE_MODIFIER;
- //if (GridCost[gridno] == NPCMINECOST)
- // switchValue = BackupGridCost[gridno];
- //else
- sSwitchValue = gubWorldMovementCosts[sGridno][bDir][ bLevel ];
- // Check reality vs what the player knows....
- if ( pSoldier->bTeam == gbPlayerNum )
- {
- // Is this obstcale a hidden tile that has not been revealed yet?
- if( DoesGridnoContainHiddenStruct( (UINT16)sGridno, &fHiddenStructVisible ) )
- {
- // Are we not visible, if so use terrain costs!
- if ( !fHiddenStructVisible )
- {
- // Set cost of terrain!
- sSwitchValue = gTileTypeMovementCost[ gpWorldLevelData[ sGridno ].ubTerrainID ];
- }
- }
- }
- if ( sSwitchValue == TRAVELCOST_NOT_STANDING )
- {
- // use the cost of the terrain!
- sSwitchValue = gTileTypeMovementCost[ gpWorldLevelData[ sGridno ].ubTerrainID ];
- }
- else if (IS_TRAVELCOST_DOOR( sSwitchValue ))
- {
- sSwitchValue = DoorTravelCost( pSoldier, sGridno, (UINT8) sSwitchValue, (BOOLEAN) (pSoldier->bTeam == gbPlayerNum), NULL );
- }
- if (sSwitchValue >= TRAVELCOST_BLOCKED && sSwitchValue != TRAVELCOST_DOOR )
- {
- return(100); // Cost too much to be considered!
- }
-
- switch( sSwitchValue )
- {
- case TRAVELCOST_DIRTROAD :
- case TRAVELCOST_FLAT : sAPCost += AP_MOVEMENT_FLAT;
- break;
- //case TRAVELCOST_BUMPY :
- case TRAVELCOST_GRASS : sAPCost += AP_MOVEMENT_GRASS;
- break;
- case TRAVELCOST_THICK : sAPCost += AP_MOVEMENT_BUSH;
- break;
- case TRAVELCOST_DEBRIS : sAPCost += AP_MOVEMENT_RUBBLE;
- break;
- case TRAVELCOST_SHORE : sAPCost += AP_MOVEMENT_SHORE; // wading shallow water
- break;
- case TRAVELCOST_KNEEDEEP : sAPCost += AP_MOVEMENT_LAKE; // wading waist/chest deep - very slow
- break;
-
- case TRAVELCOST_DEEPWATER: sAPCost += AP_MOVEMENT_OCEAN; // can swim, so it's faster than wading
- break;
- /*
- case TRAVELCOST_VEINEND :
- case TRAVELCOST_VEINMID : sAPCost += AP_MOVEMENT_FLAT;
- break;
- */
- case TRAVELCOST_DOOR : sAPCost += AP_MOVEMENT_FLAT;
- break;
- // cost for jumping a fence REPLACES all other AP costs!
- case TRAVELCOST_FENCE : return( AP_JUMPFENCE );
- case TRAVELCOST_NONE : return( 0 );
- default:
- DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("Calc AP: Unrecongnized MP type %d in %d, direction %d", sSwitchValue, sGridno, bDir ) );
- break;
- }
- if (bDir & 1)
- {
- sAPCost = (sAPCost * 14) / 10;
- }
- return(sAPCost);
- }
- INT16 BreathPointAdjustmentForCarriedWeight( SOLDIERTYPE * pSoldier )
- {
- UINT32 uiCarriedPercent;
- UINT32 uiPercentCost;
- uiCarriedPercent = CalculateCarriedWeight( pSoldier );
- if (uiCarriedPercent < 101)
- {
- // normal BP costs
- uiPercentCost = 100;
- }
- else
- {
- if (uiCarriedPercent < 151)
- {
- // between 101 and 150% of max carried weight, extra BP cost
- // of 1% per % above 100... so at 150%, we pay 150%
- uiPercentCost = 100 + (uiCarriedPercent - 100) * 3;
- }
- else if (uiCarriedPercent < 201)
- {
- // between 151 and 200% of max carried weight, extra BP cost
- // of 2% per % above 150... so at 200%, we pay 250%
- uiPercentCost = 100 + (uiCarriedPercent - 100) * 3 + (uiCarriedPercent - 150);
- }
- else
- {
- // over 200%, extra BP cost of 3% per % above 200
- uiPercentCost = 100 + (uiCarriedPercent - 100) * 3 + (uiCarriedPercent - 150) + (uiCarriedPercent - 200);
- // so at 250% weight, we pay 400% breath!
- }
- }
- return( (INT16) uiPercentCost );
- }
- INT16 TerrainBreathPoints(SOLDIERTYPE * pSoldier, INT16 sGridno,INT8 bDir, UINT16 usMovementMode)
- {
- INT32 iPoints=0;
- UINT8 ubMovementCost;
-
- ubMovementCost = gubWorldMovementCosts[sGridno][bDir][0];
- switch( ubMovementCost )
- {
- case TRAVELCOST_DIRTROAD :
- case TRAVELCOST_FLAT : iPoints = BP_MOVEMENT_FLAT; break;
- //case TRAVELCOST_BUMPY :
- case TRAVELCOST_GRASS : iPoints = BP_MOVEMENT_GRASS; break;
- case TRAVELCOST_THICK : iPoints = BP_MOVEMENT_BUSH; break;
- case TRAVELCOST_DEBRIS : iPoints = BP_MOVEMENT_RUBBLE; break;
- case TRAVELCOST_SHORE : iPoints = BP_MOVEMENT_SHORE; break; // wading shallow water
- case TRAVELCOST_KNEEDEEP : iPoints = BP_MOVEMENT_LAKE; break; // wading waist/chest deep - very slow
- case TRAVELCOST_DEEPWATER : iPoints = BP_MOVEMENT_OCEAN; break; // can swim, so it's faster than wading
- // case TRAVELCOST_VEINEND :
- // case TRAVELCOST_VEINMID : iPoints = BP_MOVEMENT_FLAT; break;
- default:
- if ( IS_TRAVELCOST_DOOR( ubMovementCost ) )
- {
- iPoints = BP_MOVEMENT_FLAT;
- break;
- }
- /*
- #ifdef TESTVERSION
- NumMessage("ERROR: TerrainBreathPoints: Unrecognized grid cost = ",
- GridCost[gridno]);
- #endif
- */
- return(0);
- }
- iPoints = iPoints * BreathPointAdjustmentForCarriedWeight( pSoldier ) / 100;
- // ATE - MAKE MOVEMENT ALWAYS WALK IF IN WATER
- if ( gpWorldLevelData[ sGridno ].ubTerrainID == DEEP_WATER || gpWorldLevelData[ sGridno ].ubTerrainID == MED_WATER || gpWorldLevelData[ sGridno ].ubTerrainID == LOW_WATER )
- {
- usMovementMode = WALKING;
- }
- // so, then we must modify it for other movement styles and accumulate
- switch(usMovementMode)
- {
- case RUNNING:
- case ADULTMONSTER_WALKING:
- case BLOODCAT_RUN:
-
- iPoints *= BP_RUN_ENERGYCOSTFACTOR; break;
- case SIDE_STEP:
- case WALK_BACKWARDS:
- case BLOODCAT_WALK_BACKWARDS:
- case MONSTER_WALK_BACKWARDS:
- case WALKING : iPoints *= BP_WALK_ENERGYCOSTFACTOR; break;
- case START_SWAT:
- case SWATTING:
- case SWAT_BACKWARDS:
- iPoints *= BP_SWAT_ENERGYCOSTFACTOR; break;
- case CRAWLING: iPoints *= BP_CRAWL_ENERGYCOSTFACTOR; break;
- }
- // ATE: Adjust these by realtime movement
- if (!(gTacticalStatus.uiFlags & TURNBASED) || !(gTacticalStatus.uiFlags & INCOMBAT ) )
- {
- // ATE: ADJUST FOR RT - MAKE BREATH GO A LITTLE FASTER!
- iPoints = (INT32)( iPoints * TB_BREATH_DEDUCT_MODIFIER );
- }
- return( (INT16) iPoints);
- }
- INT16 ActionPointCost( SOLDIERTYPE *pSoldier, INT16 sGridNo, INT8 bDir, UINT16 usMovementMode )
- {
- INT16 sTileCost, sPoints, sSwitchValue;
- sPoints = 0;
- // get the tile cost for that tile based on WALKING
- sTileCost = TerrainActionPoints( pSoldier, sGridNo, bDir, pSoldier->bLevel );
- // Get switch value...
- sSwitchValue = gubWorldMovementCosts[ sGridNo ][ bDir ][ pSoldier->bLevel ];
- // Tile cost should not be reduced based on movement mode...
- if ( sSwitchValue == TRAVELCOST_FENCE )
- {
- return( sTileCost );
- }
- // ATE - MAKE MOVEMENT ALWAYS WALK IF IN WATER
- if ( gpWorldLevelData[ sGridNo ].ubTerrainID == DEEP_WATER || gpWorldLevelData[ sGridNo ].ubTerrainID == MED_WATER || gpWorldLevelData[ sGridNo ].ubTerrainID == LOW_WATER )
- {
- usMovementMode = WALKING;
- }
- // so, then we must modify it for other movement styles and accumulate
- if (sTileCost > 0)
- {
- switch(usMovementMode)
- {
- case RUNNING:
- case ADULTMONSTER_WALKING:
- case BLOODCAT_RUN:
- sPoints = (INT16)(DOUBLE)( (sTileCost / RUNDIVISOR) ); break;
- case CROW_FLY:
- case SIDE_STEP:
- case WALK_BACKWARDS:
- case ROBOT_WALK:
- case BLOODCAT_WALK_BACKWARDS:
- case MONSTER_WALK_BACKWARDS:
- case LARVAE_WALK:
- case WALKING : sPoints = (sTileCost + WALKCOST); break;
- case START_SWAT:
- case SWAT_BACKWARDS:
- case SWATTING: sPoints = (sTileCost + SWATCOST); break;
- case CRAWLING: sPoints = (sTileCost + CRAWLCOST); break;
- default:
- // Invalid movement mode
- DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("Invalid movement mode %d used in ActionPointCost", usMovementMode ) );
- sPoints = 1;
- }
- }
- if (sSwitchValue == TRAVELCOST_NOT_STANDING)
- {
- switch(usMovementMode)
- {
- case RUNNING:
- case WALKING :
- case LARVAE_WALK:
- case SIDE_STEP:
- case WALK_BACKWARDS:
- // charge crouch APs for ducking head!
- sPoints += AP_CROUCH;
- break;
- default:
- break;
- }
- }
- return( sPoints );
- }
- INT16 EstimateActionPointCost( SOLDIERTYPE *pSoldier, INT16 sGridNo, INT8 bDir, UINT16 usMovementMode, INT8 bPathIndex, INT8 bPathLength )
- {
- // This action point cost code includes the penalty for having to change
- // stance after jumping a fence IF our path continues...
- INT16 sTileCost, sPoints, sSwitchValue;
- sPoints = 0;
- // get the tile cost for that tile based on WALKING
- sTileCost = TerrainActionPoints( pSoldier, sGridNo, bDir, pSoldier->bLevel );
- // so, then we must modify it for other movement styles and accumulate
- if (sTileCost > 0)
- {
- switch(usMovementMode)
- {
- case RUNNING:
- case ADULTMONSTER_WALKING:
- case BLOODCAT_RUN:
- sPoints = (INT16)(DOUBLE)( (sTileCost / RUNDIVISOR) ); break;
- case CROW_FLY:
- case SIDE_STEP:
- case ROBOT_WALK:
- case WALK_BACKWARDS:
- case BLOODCAT_WALK_BACKWARDS:
- case MONSTER_WALK_BACKWARDS:
- case LARVAE_WALK:
- case WALKING : sPoints = (sTileCost + WALKCOST); break;
- case START_SWAT:
- case SWAT_BACKWARDS:
- case SWATTING: sPoints = (sTileCost + SWATCOST); break;
- case CRAWLING: sPoints = (sTileCost + CRAWLCOST); break;
- default:
- // Invalid movement mode
- DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("Invalid movement mode %d used in ActionPointCost", usMovementMode ) );
- sPoints = 1;
- }
- }
- // Get switch value...
- sSwitchValue = gubWorldMovementCosts[ sGridNo ][ bDir ][ pSoldier->bLevel ];
- // ATE: If we have a 'special cost, like jump fence...
- if ( sSwitchValue == TRAVELCOST_FENCE )
- {
- // If we are changeing stance ( either before or after getting there....
- // We need to reflect that...
- switch(usMovementMode)
- {
- case SIDE_STEP:
- case WALK_BACKWARDS:
- case RUNNING:
- case WALKING :
- // Add here cost to go from crouch to stand AFTER fence hop....
- // Since it's AFTER.. make sure we will be moving after jump...
- if ( ( bPathIndex + 2 ) < bPathLength )
- {
- sPoints += AP_CROUCH;
- }
- break;
- case SWATTING:
- case START_SWAT:
- case SWAT_BACKWARDS:
- // Add cost to stand once there BEFORE....
- sPoints += AP_CROUCH;
- break;
- case CRAWLING:
- // Can't do it here.....
- break;
- }
- }
- else if (sSwitchValue == TRAVELCOST_NOT_STANDING)
- {
- switch(usMovementMode)
- {
- case RUNNING:
- case WALKING :
- case SIDE_STEP:
- case WALK_BACKWARDS:
- // charge crouch APs for ducking head!
- sPoints += AP_CROUCH;
- break;
- default:
- break;
- }
- }
- return( sPoints );
- }
-
- BOOLEAN EnoughPoints( SOLDIERTYPE *pSoldier, INT16 sAPCost, INT16 sBPCost, BOOLEAN fDisplayMsg )
- {
- INT16 sNewAP = 0;
- // If this guy is on a special move... don't care about APS, OR BPSs!
- if ( pSoldier->ubWaitActionToDo )
- {
- return( TRUE );
- }
- if ( pSoldier->ubQuoteActionID >=QUOTE_ACTION_ID_TRAVERSE_EAST && pSoldier->ubQuoteActionID <= QUOTE_ACTION_ID_TRAVERSE_NORTH )
- {
- // AI guy on special move off map
- return( TRUE );
- }
- // IN realtime.. only care about BPs
- if ( ( gTacticalStatus.uiFlags & REALTIME ) || !(gTacticalStatus.uiFlags & INCOMBAT ) )
- {
- sAPCost = 0;
- }
- #ifdef NETWORKED
- if( !IsTheSolderUnderMyControl( pSoldier->ubID) )
- {
- return( TRUE );
- }
- #endif
- // Get New points
- sNewAP = pSoldier->bActionPoints - sAPCost;
- // If we cannot deduct points, return FALSE
- if ( sNewAP < 0 )
- {
- // Display message if it's our own guy
- if ( pSoldier->bTeam == gbPlayerNum && fDisplayMsg )
- {
- ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_UI_FEEDBACK, TacticalStr[ NOT_ENOUGH_APS_STR ] );
- }
- return( FALSE );
- }
- return( TRUE );
- }
- void DeductPoints( SOLDIERTYPE *pSoldier, INT16 sAPCost, INT16 sBPCost )
- {
- INT16 sNewAP = 0, sNewBP = 0;
- INT8 bNewBreath;
- // in real time, there IS no AP cost, (only breath cost)
- if (!(gTacticalStatus.uiFlags & TURNBASED) || !(gTacticalStatus.uiFlags & INCOMBAT ) )
- {
- sAPCost = 0;
- }
- // Get New points
- sNewAP = pSoldier->bActionPoints - sAPCost;
- // If this is the first time with no action points, set UI flag
- if ( sNewAP <= 0 && pSoldier->bActionPoints > 0 )
- {
- pSoldier->fUIFirstTimeNOAP = TRUE;
- fInterfacePanelDirty = TRUE;
- }
- // If we cannot deduct points, return FALSE
- if ( sNewAP < 0 )
- {
- sNewAP = 0;
- }
- pSoldier->bActionPoints = (INT8)sNewAP;
- DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("Deduct Points (%d at %d) %d %d", pSoldier->ubID, pSoldier->sGridNo, sAPCost, sBPCost ) );
- if ( AM_A_ROBOT( pSoldier ) )
- {
- // zap all breath costs for robot
- sBPCost = 0;
- }
- // is there a BREATH deduction/transaction to be made? (REMEMBER: could be a GAIN!)
- if (sBPCost)
- {
- // Adjust breath changes due to spending or regaining of energy
- sBPCost = AdjustBreathPts(pSoldier,sBPCost);
- sBPCost *= -1;
- pSoldier->sBreathRed -= sBPCost;
- // CJC: moved check for high breathred to below so that negative breath can be detected
- // cap breathred
- if ( pSoldier->sBreathRed < 0 )
- {
- pSoldier->sBreathRed = 0;
- }
- if ( pSoldier->sBreathRed > 10000 )
- {
- pSoldier->sBreathRed = 10000;
- }
- // Get new breath
- bNewBreath = (UINT8)( pSoldier->bBreathMax - ( (FLOAT)pSoldier->sBreathRed / (FLOAT)100 ) );
- if ( bNewBreath > 100 )
- {
- bNewBreath = 100;
- }
- if ( bNewBreath < 00 )
- {
- // Take off 1 AP per 5 breath... rem adding a negative subtracts
- pSoldier->bActionPoints += (bNewBreath / 5);
- if ( pSoldier->bActionPoints < 0 )
- {
- pSoldier->bActionPoints = 0;
- }
- bNewBreath = 0;
- }
- if( bNewBreath > pSoldier->bBreathMax )
- {
- bNewBreath = pSoldier->bBreathMax;
- }
- pSoldier->bBreath = bNewBreath;
- }
- // UPDATE BAR
- DirtyMercPanelInterface( pSoldier, DIRTYLEVEL1 );
- }
- INT16 AdjustBreathPts(SOLDIERTYPE *pSold, INT16 sBPCost)
- {
- INT16 sBreathFactor = 100;
- UINT8 ubBandaged;
- //NumMessage("BEFORE adjustments, BREATH PTS = ",breathPts);
- // in real time, there IS no AP cost, (only breath cost)
- /*
- if (!(gTacticalStatus.uiFlags & TURNBASED) || !(gTacticalStatus.uiFlags & INCOMBAT ) )
- {
- // ATE: ADJUST FOR RT - MAKE BREATH GO A LITTLE FASTER!
- sBPCost *= TB_BREATH_DEDUCT_MODIFIER;
- }
- */
- // adjust breath factor for current breath deficiency
- sBreathFactor += (100 - pSold->bBreath);
- // adjust breath factor for current life deficiency (but add 1/2 bandaging)
- ubBandaged = pSold->bLifeMax - pSold->bLife - pSold->bBleeding;
- //sBreathFactor += (pSold->bLifeMax - (pSold->bLife + (ubBandaged / 2)));
- sBreathFactor += 100 * (pSold->bLifeMax - (pSold->bLife + (ubBandaged / 2))) / pSold->bLifeMax;
- if ( pSold->bStrength > 80 )
- {
- // give % reduction to breath costs for high strength mercs
- sBreathFactor -= (pSold->bStrength - 80) / 2;
- }
-
- /* THIS IS OLD JAGGED ALLIANCE STUFF (left for possible future reference)
- // apply penalty due to high temperature, heat, and hot Metaviran sun
- // if INDOORS, in DEEP WATER, or possessing HEAT TOLERANCE trait
- if ((ptr->terrtype == FLOORTYPE) || (ptr->terr >= OCEAN21) ||
- (ptr->trait == HEAT_TOLERANT))
- breathFactor += (Status.heatFactor / 5); // 20% of normal heat penalty
- else
- breathFactor += Status.heatFactor; // not used to this!
- */
- // if a non-swimmer type is thrashing around in deep water
- if ( (pSold->ubProfile != NO_PROFILE ) && (gMercProfiles[ pSold->ubProfile ].bPersonalityTrait == NONSWIMMER) )
- {
- if ( pSold->usAnimState == DEEP_WATER_TRED || pSold->usAnimState == DEEP_WATER_SWIM)
- {
- sBreathFactor *= 5; // lose breath 5 times faster in deep water!
- }
- }
- if ( sBreathFactor == 0 )
- {
- sBPCost = 0;
- }
- else if (sBPCost > 0) // breath DECREASE
- // increase breath COST by breathFactor
- sBPCost = ((sBPCost * sBreathFactor) / 100);
- else // breath INCREASE
- // decrease breath GAIN by breathFactor
- sBPCost = ((sBPCost * 100) / sBreathFactor);
-
- return(sBPCost);
- }
- void UnusedAPsToBreath(SOLDIERTYPE *pSold)
- {
- INT16 sUnusedAPs, sBreathPerAP = 0, sBreathChange, sRTBreathMod;
- BOOLEAN fAnimTypeFound = FALSE;
- // Note to Andrew (or whomever else it may concern):
- // This function deals with BETWEEN TURN breath/energy gains. The basic concept is:
- //
- // - look at LAST (current) animation of merc to see what he's now doing
- // - look at how many AP remain unspent (indicating duration of time doing that anim)
- //
- // figure out how much breath/energy (if any) he should recover. Obviously if a merc
- // is STANDING BREATHING and hasn't spent any AP then it means he *stood around* for
- // the entire duration of one turn (which, instead of spending energy, REGAINS energy)
- // COMMENTED OUT FOR NOW SINCE MOST OF THE ANIMATION DEFINES DO NOT MATCH
- // If we are not in turn-based combat...
- if ( pSold->uiStatusFlags & SOLDIER_VEHICLE )
- {
- return;
- }
- if ( !( gTacticalStatus.uiFlags & TURNBASED ) || !(gTacticalStatus.uiFlags & INCOMBAT ) )
- {
- // ALRIGHT, GIVE A FULL AMOUNT BACK, UNLES MODIFIED BY WHAT ACTIONS WE WERE DOING
- sBreathPerAP = GetBreathPerAP( pSold, pSold->usAnimState );
- // adjust for carried weight
- sBreathPerAP = sBreathPerAP * 100 / BreathPointAdjustmentForCarriedWeight( pSold );
- // If this value is -ve, we have a gain, else we have a loos which we should not really do
- // We just want to limit this to no gain if we were doing stuff...
- sBreathChange = 3 * sBreathPerAP;
-
- // Adjust for on drugs
- HandleBPEffectDueToDrugs( pSold, &sBreathChange );
- if ( sBreathChange > 0 )
- {
- sBreathChange = 0;
- }
- else
- {
- // We have a gain, now limit this depending on what we were doing...
- // OK for RT, look at how many tiles we have moved, our last move anim
- if ( pSold->ubTilesMovedPerRTBreathUpdate > 0 )
- {
- // How long have we done this for?
- // And what anim were we doing?
- sBreathPerAP = GetBreathPerAP( pSold, pSold->usLastMovementAnimPerRTBreathUpdate );
- sRTBreathMod = sBreathPerAP * pSold->ubTilesMovedPerRTBreathUpdate;
-
- // Deduct some if we were exerting ourselves
- // We add here because to gain breath, sBreathChange needs to be -ve
- if ( sRTBreathMod > 0 )
- {
- sBreathChange += sRTBreathMod;
- }
- if ( sBreathChange < 0 )
- {
- sBreathChange = 0;
- }
- }
- }
- // Divide by a number to adjust that in realtimer we do not want to recover as
- // as fast as the TB values do
- sBreathChange *= TB_BREATH_RECOVER_MODIFIER;
- // adjust breath only, don't touch action points!
- DeductPoints(pSold,0,(INT16)sBreathChange );
- // Reset value for RT breath update
- pSold->ubTilesMovedPerRTBreathUpdate = 0;
- }
- else
- {
- // if merc has any APs left unused this turn (that aren't carrying over)
- if (pSold->bActionPoints > MAX_AP_CARRIED)
- {
- sUnusedAPs = pSold->bActionPoints - MAX_AP_CARRIED;
- sBreathPerAP = GetBreathPerAP( pSold, pSold->usAnimState );
- if (sBreathPerAP < 0)
- {
- // can't gain any breath when we've just been gassed, OR
- // if standing in tear gas without a gas mask on
- if ( pSold->uiStatusFlags & SOLDIER_GASSED )
- {
- return; // can't breathe here, so get no breath back!
- }
- }
- // adjust for carried weight
- sBreathPerAP = sBreathPerAP * 100 / BreathPointAdjustmentForCarriedWeight( pSold );
-
- sBreathChange = (AP_MAXIMUM - sUnusedAPs) * sBreathPerAP;
- }
- else
- {
- sBreathChange = 0;
- }
- // Adjust for on drugs
- HandleBPEffectDueToDrugs( pSold, &sBreathChange );
- // adjust breath only, don't touch action points!
- DeductPoints(pSold,0,(INT16)sBreathChange );
- }
- }
- INT16 GetBreathPerAP( SOLDIERTYPE *pSoldier, UINT16 usAnimState )
- {
- INT16 sBreathPerAP = 0;
- BOOLEAN fAnimTypeFound = FALSE;
- if ( gAnimControl[ usAnimState ].uiFlags & ANIM_VARIABLE_EFFORT )
- {
- // Default effort
- sBreathPerAP = BP_PER_AP_MIN_EFFORT;
- // OK, check if we are in water and are waling/standing
- if ( MercInWater( pSoldier ) )
- {
- switch( usAnimState )
- {
- case STANDING:
- sBreathPerAP = BP_PER_AP_LT_EFFORT;
- break;
- case WALKING:
- sBreathPerAP = BP_PER_AP_MOD_EFFORT;
- break;
- }
- }
- else
- {
- switch( usAnimState )
- {
- case STANDING:
- sBreathPerAP = BP_PER_AP_NO_EFFORT;
- break;
- case WALKING:
- sBreathPerAP = BP_PER_AP_LT_EFFORT;
- break;
- }
- }
- fAnimTypeFound = TRUE;
- }
- if ( gAnimControl[ usAnimState ].uiFlags & ANIM_NO_EFFORT )
- {
- sBreathPerAP = BP_PER_AP_NO_EFFORT;
- fAnimTypeFound = TRUE;
- }
- if ( gAnimControl[ usAnimState ].uiFlags & ANIM_MIN_EFFORT )
- {
- sBreathPerAP = BP_PER_AP_MIN_EFFORT;
- fAnimTypeFound = TRUE;
- }
- if ( gAnimControl[ usAnimState ].uiFlags & ANIM_LIGHT_EFFORT )
- {
- sBreathPerAP = BP_PER_AP_LT_EFFORT;
- fAnimTypeFound = TRUE;
- }
- if ( gAnimControl[ usAnimState ].uiFlags & ANIM_MODERATE_EFFORT )
- {
- sBreathPerAP = BP_PER_AP_MOD_EFFORT;
- fAnimTypeFound = TRUE;
- }
- if ( !fAnimTypeFound )
- {
- DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("Unknown end-of-turn breath anim: %s", gAnimControl[ usAnimState ].zAnimStr ) );
- }
- return( sBreathPerAP );
- }
- //UINT8 CalcAPsToBurst( INT8 bBaseActionPoints, UINT16 usItem )
- UINT8 CalcAPsToBurst( INT8 bBaseActionPoints, OBJECTTYPE * pObj )
- {
- // base APs is what you'd get from CalcActionPoints();
- if (pObj->usItem == G11)
- {
- return( 1 );
- }
- else
- {
- // NB round UP, so 21-25 APs pay full
- INT8 bAttachPos;
- bAttachPos = FindAttachment( pObj, SPRING_AND_BOLT_UPGRADE );
- if ( bAttachPos != -1 )
- {
- return( (__max( 3, (AP_BURST * bBaseActionPoints + (AP_MAXIMUM - 1) ) / AP_MAXIMUM ) * 100) / (100 + pObj->bAttachStatus[ bAttachPos ] / 5) );
- }
- else
- {
- return( __max( 3, (AP_BURST * bBaseActionPoints + (AP_MAXIMUM - 1) ) / AP_MAXIMUM ) );
- }
- }
- }
- UINT8 CalcTotalAPsToAttack( SOLDIERTYPE *pSoldier, INT16 sGridNo, UINT8 ubAddTurningCost, INT8 bAimTime )
- {
- UINT16 sAPCost = 0;
- UINT16 usItemNum;
- INT16 sActionGridNo;
- UINT8 ubDirection;
- INT16 sAdjustedGridNo;
- UINT32 uiItemClass;
-
- // LOOK IN BUDDY'S HAND TO DETERMINE WHAT TO DO HERE
- usItemNum = pSoldier->inv[HANDPOS].usItem;
- uiItemClass = Item[ usItemNum ].usItemClass;
- if ( uiItemClass == IC_GUN || uiItemClass == IC_LAUNCHER || uiItemClass == IC_TENTACLES || uiItemClass == IC_THROWING_KNIFE )
- {
- sAPCost = MinAPsToAttack( pSoldier, sGridNo, ubAddTurningCost );
- if ( pSoldier->bDoBurst )
- {
- sAPCost += CalcAPsToBurst( CalcActionPoints( pSoldier ), &(pSoldier->inv[HANDPOS]) );
- }
- else
- {
- sAPCost += bAimTime;
- }
- }
- //ATE: HERE, need to calculate APs!
- if ( uiItemClass & IC_EXPLOSV )
- {
- sAPCost = MinAPsToAttack( pSoldier, sGridNo, ubAddTurningCost );
- sAPCost = 5;
- }
- if ( uiItemClass == IC_PUNCH || ( uiItemClass == IC_BLADE && uiItemClass != IC_THROWING_KNIFE ) )
- {
- // IF we are at this gridno, calc min APs but if not, calc cost to goto this lication
- if ( pSoldier->sGridNo != sGridNo )
- {
- // OK, in order to avoid path calculations here all the time... save and check if it's changed!
- if ( pSoldier->sWalkToAttackGridNo == sGridNo )
- {
- sAdjustedGridNo = sGridNo;
- sAPCost += (UINT8)( pSoldier->sWalkToAttackWalkToCost );
- }
- else
- {
- //INT32 cnt;
- //INT16 sSpot;
- UINT8 ubGuyThere;
- INT16 sGotLocation = NOWHERE;
- BOOLEAN fGotAdjacent = FALSE;
- SOLDIERTYPE *pTarget;
- ubGuyThere = WhoIsThere2( sGridNo, pSoldier->bLevel );
- if ( ubGuyThere != NOBODY )
- {
- pTarget = MercPtrs[ ubGuyThere ];
- if ( pSoldier->ubBodyType == BLOODCAT )
- {
- sGotLocation = FindNextToAdjacentGridEx( pSoldier, sGridNo, &ubDirection, &sAdjustedGridNo, TRUE, FALSE );
- if ( sGotLocation == -1 )
- {
- sGotLocation = NOWHERE;
- }
- }
- else
- {
- sGotLocation = FindAdjacentPunchTarget( pSoldier, pTarget, &sAdjustedGridNo, &ubDirection );
- }
- }
- if ( sGotLocation == NOWHERE && pSoldier->ubBodyType != BLOODCAT )
- {
- sActionGridNo = FindAdjacentGridEx( pSoldier, sGridNo, &ubDirection, &sAdjustedGridNo, TRUE, FALSE );
- if ( sActionGridNo == -1 )
- {
- sGotLocation = NOWHERE;
- }
- else
- {
- sGotLocation = sActionGridNo;
- }
- fGotAdjacent = TRUE;
- }
- if ( sGotLocation != NOWHERE )
- {
- if (pSoldier->sGridNo == sGotLocation || !fGotAdjacent )
- {
- pSoldier->sWalkToAttackWalkToCost = 0;
- }
- else
- {
- // Save for next time...
- pSoldier->sWalkToAttackWalkToCost = PlotPath( pSoldier, sGotLocation, NO_COPYROUTE, NO_PLOT, TEMPORARY, (UINT16)pSoldier->usUIMovementMode, NOT_STEALTH, FORWARD, pSoldier->bActionPoints );
- if (pSoldier->sWalkToAttackWalkToCost == 0)
- {
- return( 99 );
- }
- }
- }
- else
- {
- return( 0 );
- }
- sAPCost += pSoldier->sWalkToAttackWalkToCost;
- }
- // Save old location!
- pSoldier->sWalkToAttackGridNo = sGridNo;
- // Add points to attack
- sAPCost += MinAPsToAttack( pSoldier, sAdjustedGridNo, ubAddTurningCost );
- }
- else
- {
- // Add points to attack
- // Use our gridno
- sAPCost += MinAPsToAttack( pSoldier, sGridNo, ubAddTurningCost );
- }
- // Add aim time...
- sAPCost += bAimTime;
- }
- return( (INT8)sAPCost );
- }
- UINT8 MinAPsToAttack(SOLDIERTYPE *pSoldier, INT16 sGridno, UINT8 ubAddTurningCost)
- {
- UINT16 sAPCost = 0;
- UINT32 uiItemClass;
- if ( pSoldier->bWeaponMode == WM_ATTACHED )
- {
- INT8 bAttachSlot;
- // look for an attached grenade launcher
- bAttachSlot = FindAttachment( &(pSoldier->inv[ HANDPOS ]), UNDER_GLAUNCHER );
- if ( bAttachSlot == NO_SLOT )
- {
- // default to hand
- // LOOK IN BUDDY'S HAND TO DETERMINE WHAT TO DO HERE
- uiItemClass = Item[ pSoldier->inv[HANDPOS].usItem ].usItemClass;
- }
- else
- {
- uiItemClass = Item[ UNDER_GLAUNCHER ].usItemClass;
- }
- }
- else
- {
- // LOOK IN BUDDY'S HAND TO DETERMINE WHAT TO DO HERE
- uiItemClass = Item[ pSoldier->inv[HANDPOS].usItem ].usItemClass;
- }
-
- if ( uiItemClass == IC_BLADE || uiItemClass == IC_GUN || uiItemClass == IC_LAUNCHER || uiItemClass == IC_TENTACLES || uiItemClass == IC_THROWING_KNIFE )
- {
- sAPCost = MinAPsToShootOrStab( pSoldier, sGridno, ubAddTurningCost );
- }
- else if ( uiItemClass & ( IC_GRENADE | IC_THROWN ) )
- {
- sAPCost = MinAPsToThrow( pSoldier, sGridno, ubAddTurningCost );
- }
- else if ( uiItemClass == IC_PUNCH )
- {
- sAPCost = MinAPsToPunch( pSoldier, sGridno, ubAddTurningCost );
- }
-
- return( (UINT8)sAPCost );
- }
- INT8 CalcAimSkill( SOLDIERTYPE * pSoldier, UINT16 usWeapon )
- {
- INT8 bAimSkill;
- if ( Item[ usWeapon ].usItemClass == IC_GUN || Item[ usWeapon ].usItemClass == IC_LAUNCHER )
- {
- // GUNS: modify aiming cost by shooter's MARKSMANSHIP
- bAimSkill = EffectiveMarksmanship( pSoldier );
- }
- else
- // for now use this for all other weapons
- //if ( Item[ usInHand ].usItemClass == IC_BLADE )
- {
- // KNIVES: modify aiming cost by avg of attacker's DEXTERITY & AGILITY
- bAimSkill = ( EffectiveDexterity( pSoldier ) + EffectiveAgility( pSoldier ) ) / 2;
- //return( 4 );
- }
- return( bAimSkill );
- }
- UINT8 BaseAPsToShootOrStab( INT8 bAPs, INT8 bAimSkill, OBJECTTYPE * pObj )
- {
- INT16 sTop, sBottom;
- INT8 bAttachPos;
- // Calculate default top & bottom of the magic "aiming" formula!
- // get this man's maximum possible action points (ignoring carryovers)
- // the 2 times is here only to allow rounding off using integer math later
- sTop = 2 * bAPs;//CalcActionPoints( pSoldier );
- // Shots per turn rating is for max. aimSkill(100), drops down to 1/2 at = 0
- // DIVIDE BY 4 AT THE END HERE BECAUSE THE SHOTS PER TURN IS NOW QUADRUPLED!
- // NB need to define shots per turn for ALL Weapons then.
- sBottom = ( ( 50 + (bAimSkill / 2) ) * Weapon[ pObj->usItem ].ubShotsPer4Turns ) / 4;
- bAttachPos = FindAttachment( pObj, SPRING_AND_BOLT_UPGRADE );
- if ( bAttachPos != -1 )
- {
- sBottom = (sBottom * (100 + pObj->bAttachStatus[ bAttachPos ] / 5) ) / 100;
- }
- // add minimum aiming time to the overall minimum AP_cost
- // This here ROUNDS UP fractions of 0.5 or higher using integer math
- // This works because 'top' is 2x what it really should be throughout
- return( ( ( ( 100 * sTop ) / sBottom ) + 1) / 2);
- }
- void GetAPChargeForShootOrStabWRTGunRaises( SOLDIERTYPE *pSoldier, INT16 sGridNo, UINT8 ubAddTurningCost, BOOLEAN *pfChargeTurning, BOOLEAN *pfChargeRaise )
- {
- UINT8 ubDirection;
- UINT32 uiMercFlags;
- UINT16 usTargID;
- BOOLEAN fAddingTurningCost = FALSE;
- BOOLEAN fAddingRaiseGunCost = FALSE;
-
- if ( sGridNo != NOWHERE )
- {
- // OK, get a direction and see if we need to turn...
- if (ubAddTurningCost)
- {
- // Given a gridno here, check if we are on a guy - if so - get his gridno
- if ( FindSoldier( sGridNo, &usTargID, &uiMercFlags, FIND_SOLDIER_GRIDNO ) )
- {
- sGridNo = MercPtrs[ usTargID ]->sGridNo;
- }
- ubDirection = (UINT8)GetDirectionFromGridNo( sGridNo, pSoldier );
- // Is it the same as he's facing?
- if ( ubDirection != pSoldier->bDirection )
- {
- fAddingTurningCost = TRUE;
- }
- }
- }
- else
- {
- if (ubAddTurningCost)
- {
- // Assume we need to add cost!
- fAddingTurningCost = TRUE;
- }
- }
- if ( Item[ pSoldier->inv[ HANDPOS ].usItem ].usItemClass == IC_THROWING_KNIFE )
- {
- }
- else
- {
- // Do we need to ready weapon?
- if ( !( gAnimControl[ pSoldier->usAnimState ].uiFlags &( ANIM_FIREREADY | ANIM_FIRE ) ) )
- {
- fAddingRaiseGunCost = TRUE;
- }
- }
- (*pfChargeTurning) = fAddingTurningCost;
- (*pfChargeRaise ) = fAddingRaiseGunCost;
- }
- UINT8 MinAPsToShootOrStab(SOLDIERTYPE *pSoldier, INT16 sGridNo, UINT8 ubAddTurningCost)
- {
- UINT32 uiMercFlags;
- UINT16 usTargID;
- INT8 bFullAPs;
- INT8 bAimSkill;
- UINT8 bAPCost = AP_MIN_AIM_ATTACK;
- BOOLEAN fAddingTurningCost = FALSE;
- BOOLEAN fAddingRaiseGunCost = FALSE;
- UINT16 usItem;
- if ( pSoldier->bWeaponMode == WM_ATTACHED )
- {
- usItem = UNDER_GLAUNCHER;
- }
- else
- {
- usItem = pSoldier->inv[ HANDPOS ].usItem;
- }
- GetAPChargeForShootOrStabWRTGunRaises( pSoldier, sGridNo, ubAddTurningCost, &fAddingTurningCost, &fAddingRaiseGunCost );
- if ( Item[ usItem ].usItemClass == IC_THROWING_KNIFE )
- {
- // Do we need to stand up?
- bAPCost += GetAPsToChangeStance( pSoldier, ANIM_STAND );
- }
- // ATE: Look at stance...
- if ( gAnimControl[ pSoldier->usAnimState ].ubHeight == ANIM_STAND )
- {
- // Don't charge turning if gun-ready...
- if ( fAddingRaiseGunCost )
- {
- fAddingTurningCost = FALSE;
- }
- }
- else
- {
- // Just charge turning costs...
- if ( fAddingTurningCost )
- {
- fAddingRaiseGunCost = FALSE;
- }
- }
- if ( AM_A_ROBOT( pSoldier ) )
- {
- fAddingRaiseGunCost = FALSE;
- }
- if ( fAddingTurningCost )
- {
- if ( Item[ usItem ].usItemClass == IC_THROWING_KNIFE )
- {
- bAPCost += 1;
- }
- else
- {
- bAPCost += GetAPsToLook( pSoldier );
- }
- }
- if ( fAddingRaiseGunCost )
- {
- bAPCost += GetAPsToReadyWeapon( pSoldier, pSoldier->usAnimState );
- pSoldier->fDontChargeReadyAPs = FALSE;
- }
- if ( sGridNo != NOWHERE )
- {
- // Given a gridno here, check if we are on a guy - if so - get his gridno
- if ( FindSoldier( sGridNo, &usTargID, &uiMercFlags, FIND_SOLDIER_GRIDNO ) )
- {
- sGridNo = MercPtrs[ usTargID ]->sGridNo;
- }
- }
- // if attacking a new target (or if the specific target is uncertain)
- if ( ( sGridNo != pSoldier->sLastTarget ) && usItem != ROCKET_LAUNCHER )
- {
- bAPCost += AP_CHANGE_TARGET;
- }
- bFullAPs = CalcActionPoints( pSoldier );
- // aim skill is the same whether we are using 1 or 2 guns
- bAimSkill = CalcAimSkill( pSoldier, usItem );
- if ( pSoldier->bWeaponMode == WM_ATTACHED )
- {
- INT8 bAttachSlot;
- OBJECTTYPE GrenadeLauncher;
- // look for an attached grenade launcher
- bAttachSlot = FindAttachment( &(pSoldier->inv[ HANDPOS ]), UNDER_GLAUNCHER );
- // create temporary grenade launcher and use that
- if ( bAttachSlot != NO_SLOT )
- {
- CreateItem( UNDER_GLAUNCHER, pSoldier->inv[ HANDPOS ].bAttachStatus[ bAttachSlot ], &GrenadeLauncher );
- }
- else
- {
- // fake it, use a 100 status...
- CreateItem( UNDER_GLAUNCHER, 100, &GrenadeLauncher );
- }
- bAPCost += BaseAPsToShootOrStab( bFullAPs, bAimSkill, &GrenadeLauncher );
-
- }
- else if ( IsValidSecondHandShot( pSoldier ) )
- {
- // charge the maximum of the two
- bAPCost += __max(
- BaseAPsToShootOrStab( bFullAPs, bAimSkill, &(pSoldier->inv[HANDPOS]) ),
- BaseAPsToShootOrStab( bFullAPs, bAimSkill, &(pSoldier->inv[SECONDHANDPOS]) ) );
- }
- else
- {
- bAPCost += BaseAPsToShootOrStab( bFullAPs, bAimSkill, &(pSoldier->inv[HANDPOS]) );
- }
- // the minimum AP cost of ANY shot can NEVER be more than merc's maximum APs!
- if ( bAPCost > bFullAPs )
- bAPCost = bFullAPs;
- // this SHOULD be impossible, but nevertheless...
- if ( bAPCost < 1 )
- bAPCost = 1;
- if ( pSoldier->inv[HANDPOS].usItem == ROCKET_LAUNCHER )
- {
- bAPCost += GetAPsToChangeStance( pSoldier, ANIM_STAND );
- }
- return ( bAPCost );
- }
- UINT8 MinAPsToPunch(SOLDIERTYPE *pSoldier, INT16 sGridNo, UINT8 ubAddTurningCost)
- {
- UINT8 bAPCost = 0;
- UINT16 usTargID;
- UINT8 ubDirection;
- // bAimSkill = ( pSoldier->bDexterity + pSoldier->bAgility) / 2;
- if ( sGridNo != NOWHERE )
- {
- usTargID = WhoIsThere2( sGridNo, pSoldier->bTargetLevel );
- // Given a gridno here, check if we are on a guy - if so - get his gridno
- if ( usTargID != NOBODY )
- {
- sGridNo = MercPtrs[ usTargID ]->sGridNo;
- // Check if target is prone, if so, calc cost...
- if ( gAnimControl[ MercPtrs[ usTargID ]->usAnimState ].ubEndHeight == ANIM_PRONE )
- {
- bAPCost += GetAPsToChangeStance( pSoldier, ANIM_CROUCH );
- }
- else
- {
- if ( pSoldier->sGridNo == sGridNo )
- {
- bAPCost += GetAPsToChangeStance( pSoldier, ANIM_STAND );
- }
- }
- }
- if (ubAddTurningCost)
- {
- if ( pSoldier->sGridNo == sGridNo )
- {
- // ATE: Use standing turn cost....
- ubDirection = (UINT8)GetDirectionFromGridNo( sGridNo, pSoldier );
- // Is it the same as he's facing?
- if ( ubDirection != pSoldier->bDirection )
- {
- bAPCost += AP_LOOK_STANDING;
- }
- }
- }
- }
- bAPCost += 4;
- return ( bAPCost );
- }
- INT8 MinPtsToMove(SOLDIERTYPE *pSoldier)
- {
- // look around all 8 directions and return lowest terrain cost
- INT32 cnt;
- INT16 sLowest=127;
- INT16 sGridno,sCost;
- if ( TANK( pSoldier ) )
- {
- return( (INT8)sLowest);
- }
- for (cnt=0; cnt <= 7; cnt++)
- {
- sGridno = NewGridNo(pSoldier->sGridNo,DirectionInc((INT16) cnt));
- if (sGridno != pSoldier->sGridNo)
- {
- if ( (sCost=ActionPointCost( pSoldier, sGridno, (UINT8)cnt , pSoldier->usUIMovementMode ) ) < sLowest )
- {
- sLowest = sCost;
- }
- }
- }
- return( (INT8)sLowest);
- }
- INT8 PtsToMoveDirection(SOLDIERTYPE *pSoldier, INT8 bDirection )
- {
- INT16 sGridno,sCost;
- INT8 bOverTerrainType;
- UINT16 usMoveModeToUse;
- sGridno = NewGridNo( pSoldier->sGridNo, DirectionInc((INT16) bDirection ) );
- usMoveModeToUse = pSoldier->usUIMovementMode;
- // ATE: Check if the new place is watter and we were tying to run....
- bOverTerrainType = GetTerrainType( sGridno );
- if ( bOverTerrainType == MED_WATER || bOverTerrainType == DEEP_WATER || bOverTerrainType == LOW_WATER )
- {
- usMoveModeToUse = WALKING;
- }
- sCost = ActionPointCost( pSoldier, sGridno, bDirection , usMoveModeToUse );
- if ( gubWorldMovementCosts[ sGridno ][ bDirection ][ pSoldier->bLevel ] != TRAVELCOST_FENCE )
- {
- if ( usMoveModeToUse == RUNNING && pSoldier->usAnimState != RUNNING )
- {
- sCost += AP_START_RUN_COST;
- }
- }
-
- return( (INT8)sCost );
- }
- INT8 MinAPsToStartMovement( SOLDIERTYPE * pSoldier, UINT16 usMovementMode )
- {
- INT8 bAPs = 0;
- switch( usMovementMode )
- {
- case RUNNING:
- case WALKING:
- if (gAnimControl[ pSoldier->usAnimState ].ubEndHeight == ANIM_PRONE)
- {
- bAPs += AP_CROUCH + AP_PRONE;
- }
- else if (gAnimControl[ pSoldier->usAnimState ].ubEndHeight == ANIM_CROUCH)
- {
- bAPs += AP_CROUCH;
- }
- break;
- case SWATTING:
- if (gAnimControl[ pSoldier->usAnimState ].ubEndHeight == ANIM_PRONE)
- {
- bAPs += AP_PRONE;
- }
- else if (gAnimControl[ pSoldier->usAnimState ].ubEndHeight == ANIM_STAND)
- {
- bAPs += AP_CROUCH;
- }
- break;
- case CRAWLING:
- if (gAnimControl[ pSoldier->usAnimState ].ubEndHeight == ANIM_STAND)
- {
- bAPs += AP_CROUCH + AP_PRONE;
- }
- else if (gAnimControl[ pSoldier->usAnimState ].ubEndHeight == ANIM_CROUCH)
- {
- bAPs += AP_CROUCH;
- }
- break;
- default:
- break;
- }
- if (usMovementMode == RUNNING && pSoldier->usAnimState != RUNNING )
- {
- bAPs += AP_START_RUN_COST;
- }
- return( bAPs );
- }
- BOOLEAN EnoughAmmo( SOLDIERTYPE *pSoldier, BOOLEAN fDisplay, INT8 bInvPos )
- {
- if ( pSoldier->inv[ bInvPos ].usItem != NOTHING )
- {
- if ( pSoldier->bWeaponMode == WM_ATTACHED )
- {
- return( TRUE );
- }
- else
- {
- if ( pSoldier->inv[ bInvPos ].usItem == ROCKET_LAUNCHER )
- {
- // hack... they turn empty afterwards anyways
- return( TRUE );
- }
- if (Item[ pSoldier->inv[ bInvPos ].usItem ].usItemClass == IC_LAUNCHER || pSoldier->inv[ bInvPos ].usItem == TANK_CANNON )
- {
- if ( FindAttachmentByClass( &(pSoldier->inv[ bInvPos ]), IC_GRENADE ) != ITEM_NOT_FOUND )
- {
- return( TRUE );
- }
- // ATE: Did an else if here...
- if ( FindAttachmentByClass( &(pSoldier->inv[ bInvPos ]), IC_BOMB ) != ITEM_NOT_FOUND )
- {
- return( TRUE );
- }
- if ( fDisplay )
- {
- TacticalCharacterDialogue( pSoldier, QUOTE_OUT_OF_AMMO );
- }
- return( FALSE );
- }
- else if (Item[ pSoldier->inv[ bInvPos ].usItem ].usItemClass == IC_GUN)
- {
- if ( pSoldier->inv[ bInvPos ].ubGunShotsLeft == 0 )
- {
- if ( fDisplay )
- {
- TacticalCharacterDialogue( pSoldier, QUOTE_OUT_OF_AMMO );
- }
- return( FALSE );
- }
- }
- }
- return( TRUE );
- }
- return( FALSE );
- }
- void DeductAmmo( SOLDIERTYPE *pSoldier, INT8 bInvPos )
- {
- OBJECTTYPE * pObj;
- // tanks never run out of MG ammo!
- // unlimited cannon ammo is handled in AI
- if ( TANK( pSoldier ) && pSoldier->inv[bInvPos].usItem != TANK_CANNON )
- {
- return;
- }
- pObj = &(pSoldier->inv[ bInvPos ]);
- if ( pObj->usItem != NOTHING )
- {
- if ( pObj->usItem == TANK_CANNON )
- {
- }
- else if ( Item[ pObj->usItem ].usItemClass == IC_GUN && pObj->usItem != TANK_CANNON )
- {
- if ( pSoldier->usAttackingWeapon == pObj->usItem)
- {
- // OK, let's see, don't overrun...
- if ( pObj->ubGunShotsLeft != 0 )
- {
- pObj->ubGunShotsLeft--;
- }
- }
- else
- {
- // firing an attachment?
- }
- }
- else if ( Item[ pObj->usItem ].usItemClass == IC_LAUNCHER || pObj->usItem == TANK_CANNON )
- {
- INT8 bAttachPos;
- bAttachPos = FindAttachmentByClass( pObj, IC_GRENADE );
- if (bAttachPos == ITEM_NOT_FOUND )
- {
- bAttachPos = FindAttachmentByClass( pObj, IC_BOMB );
- }
-
- if (bAttachPos != ITEM_NOT_FOUND)
- {
- RemoveAttachment( pObj, bAttachPos, NULL );
- }
- }
- // Dirty Bars
- DirtyMercPanelInterface( pSoldier, DIRTYLEVEL1 );
- }
- }
- UINT16 GetAPsToPickupItem( SOLDIERTYPE *pSoldier, UINT16 usMapPos )
- {
- ITEM_POOL *pItemPool;
- UINT16 sAPCost = 0;
- INT16 sActionGridNo;
- // Check if we are over an item pool
- if ( GetItemPool( usMapPos, &pItemPool, pSoldier->bLevel ) )
- {
- // If we are in the same tile, just return pickup cost
- sActionGridNo = AdjustGridNoForItemPlacement( pSoldier, usMapPos );
- if ( pSoldier->sGridNo != sActionGridNo )
- {
- sAPCost = PlotPath( pSoldier, sActionGridNo, NO_COPYROUTE, NO_PLOT, TEMPORARY, (UINT16)pSoldier->usUIMovementMode, NOT_STEALTH, FORWARD, pSoldier->bActionPoints );
-
- // If point cost is zero, return 0
- if ( sAPCost != 0 )
- {
- // ADD APS TO PICKUP
- sAPCost += AP_PICKUP_ITEM;
- }
- }
- else
- {
- sAPCost += AP_PICKUP_ITEM;
- }
- }
- return( sAPCost );
- }
- UINT16 GetAPsToGiveItem( SOLDIERTYPE *pSoldier, UINT16 usMapPos )
- {
- UINT16 sAPCost = 0;
- sAPCost = PlotPath( pSoldier, usMapPos, NO_COPYROUTE, NO_PLOT, TEMPORARY, (UINT16)pSoldier->usUIMovementMode, NOT_STEALTH, FORWARD, pSoldier->bActionPoints );
- // If point cost is zero, return 0
- if ( sAPCost != 0 || pSoldier->sGridNo == usMapPos )
- {
- // ADD APS TO PICKUP
- sAPCost += AP_GIVE_ITEM;
- }
- return( sAPCost );
- }
- INT8 GetAPsToReloadGunWithAmmo( OBJECTTYPE * pGun, OBJECTTYPE * pAmmo )
- {
- if (Item[ pGun->usItem ].usItemClass == IC_LAUNCHER)
- {
- // always standard AP cost
- return( AP_RELOAD_GUN );
- }
- if ( Weapon[pGun->usItem].ubMagSize == Magazine[Item[pAmmo->usItem].ubClassIndex].ubMagSize )
- {
- // normal situation
- return( AP_RELOAD_GUN );
- }
- else
- {
- // trying to reload with wrong size of magazine
- return( AP_RELOAD_GUN + AP_RELOAD_GUN );
- }
- }
- INT8 GetAPsToAutoReload( SOLDIERTYPE * pSoldier )
- {
- OBJECTTYPE * pObj;
- INT8 bSlot, bSlot2, bExcludeSlot;
- INT8 bAPCost = 0, bAPCost2 = 0;;
- CHECKF( pSoldier );
- pObj = &(pSoldier->inv[HANDPOS]);
- if (Item[pObj->usItem].usItemClass == IC_GUN || Item[pObj->usItem].usItemClass == IC_LAUNCHER)
- {
- bSlot = FindAmmoToReload( pSoldier, HANDPOS, NO_SLOT );
- if (bSlot != NO_SLOT)
- {
- // we would reload using this ammo!
- bAPCost += GetAPsToReloadGunWithAmmo( pObj, &(pSoldier->inv[bSlot] ) );
- }
- if ( IsValidSecondHandShotForReloadingPurposes( pSoldier ) )
- {
- pObj = &(pSoldier->inv[SECONDHANDPOS]);
- bExcludeSlot = NO_SLOT;
- bSlot2 = NO_SLOT;
- // if the ammo for the first gun is the same we have to do special checks
- if ( ValidAmmoType( pObj->usItem, pSoldier->inv[ bSlot ].usItem ) )
- {
- if ( pSoldier->inv[ bSlot ].ubNumberOfObjects == 1 )
- {
- // we must not consider this slot for reloading!
- bExcludeSlot = bSlot;
- }
- else
- {
- // we can reload the 2nd gun from the same pocket!
- bSlot2 = bSlot;
- }
- }
-
- if (bSlot2 == NO_SLOT)
- {
- bSlot2 = FindAmmoToReload( pSoldier, SECONDHANDPOS, bExcludeSlot );
- }
- if (bSlot2 != NO_SLOT)
- {
- // we would reload using this ammo!
- bAPCost2 = GetAPsToReloadGunWithAmmo( pObj, &(pSoldier->inv[bSlot2] ) );
- if ( EnoughPoints( pSoldier, (INT16) (bAPCost + bAPCost2), 0, FALSE ) )
- {
- // we can afford to reload both guns; otherwise display just for 1 gun
- bAPCost += bAPCost2;
- }
- }
- }
- }
- return( bAPCost );
- }
- UINT16 GetAPsToReloadRobot( SOLDIERTYPE *pSoldier, SOLDIERTYPE *pRobot )
- {
- UINT16 sAPCost = 0;
- INT16 sActionGridNo;
- UINT8 ubDirection;
- INT16 sAdjustedGridNo;
- sActionGridNo = FindAdjacentGridEx( pSoldier, pRobot->sGridNo, &ubDirection, &sAdjustedGridNo, TRUE, FALSE );
- sAPCost = PlotPath( pSoldier, sActionGridNo, NO_COPYROUTE, NO_PLOT, TEMPORARY, (UINT16)pSoldier->usUIMovementMode, NOT_STEALTH, FORWARD, pSoldier->bActionPoints );
- // If point cost is zero, return 0
- if ( sAPCost != 0 || sActionGridNo == pSoldier->sGridNo )
- {
- // ADD APS TO RELOAD
- sAPCost += 4;
- }
- return( sAPCost );
- }
- UINT16 GetAPsToChangeStance( SOLDIERTYPE *pSoldier, INT8 bDesiredHeight )
- {
- UINT16 sAPCost = 0;
- INT8 bCurrentHeight;
- bCurrentHeight = gAnimControl[ pSoldier->usAnimState ].ubEndHeight;
- if ( bCurrentHeight == bDesiredHeight )
- {
- sAPCost = 0;
- }
- if ( bCurrentHeight == ANIM_STAND && bDesiredHeight == ANIM_PRONE )
- {
- sAPCost = AP_CROUCH + AP_PRONE;
- }
- if ( bCurrentHeight == ANIM_STAND && bDesiredHeight == ANIM_CROUCH )
- {
- sAPCost = AP_CROUCH;
- }
- if ( bCurrentHeight == ANIM_CROUCH && bDesiredHeight == ANIM_PRONE )
- {
- sAPCost = AP_PRONE;
- }
- if ( bCurrentHeight == ANIM_CROUCH && bDesiredHeight == ANIM_STAND )
- {
- sAPCost = AP_CROUCH;
- }
- if ( bCurrentHeight == ANIM_PRONE && bDesiredHeight == ANIM_STAND )
- {
- sAPCost = AP_PRONE + AP_CROUCH;
- }
- if ( bCurrentHeight == ANIM_PRONE && bDesiredHeight == ANIM_CROUCH )
- {
- sAPCost = AP_PRONE;
- }
- return( sAPCost );
- }
- UINT16 GetBPsToChangeStance( SOLDIERTYPE *pSoldier, INT8 bDesiredHeight )
- {
- UINT16 sBPCost = 0;
- INT8 bCurrentHeight;
- bCurrentHeight = gAnimControl[ pSoldier->usAnimState ].ubEndHeight;
- if ( bCurrentHeight == bDesiredHeight )
- {
- sBPCost = 0;
- }
- if ( bCurrentHeight == ANIM_STAND && bDesiredHeight == ANIM_PRONE )
- {
- sBPCost = BP_CROUCH + BP_PRONE;
- }
- if ( bCurrentHeight == ANIM_STAND && bDesiredHeight == ANIM_CROUCH )
- {
- sBPCost = BP_CROUCH;
- }
- if ( bCurrentHeight == ANIM_CROUCH && bDesiredHeight == ANIM_PRONE )
- {
- sBPCost = BP_PRONE;
- }
- if ( bCurrentHeight == ANIM_CROUCH && bDesiredHeight == ANIM_STAND )
- {
- sBPCost = BP_CROUCH;
- }
- if ( bCurrentHeight == ANIM_PRONE && bDesiredHeight == ANIM_STAND )
- {
- sBPCost = BP_PRONE + BP_CROUCH;
- }
- if ( bCurrentHeight == ANIM_PRONE && bDesiredHeight == ANIM_CROUCH )
- {
- sBPCost = BP_PRONE;
- }
- return( sBPCost );
- }
- UINT16 GetAPsToLook( SOLDIERTYPE *pSoldier )
- {
- // Set # of APs
- switch( gAnimControl[ pSoldier->usAnimState ].ubEndHeight )
- {
- // Now change to appropriate animation
- case ANIM_STAND:
- return( AP_LOOK_STANDING );
- break;
- case ANIM_CROUCH:
- return( AP_LOOK_CROUCHED );
- break;
- case ANIM_PRONE:
- // AP_PRONE is the AP cost to go to or from the prone stance. To turn while prone, your merc has to get up to
- // crouched, turn, and then go back down. Hence you go up (AP_PRONE), turn (AP_LOOK_PRONE) and down (AP_PRONE).
- return( AP_LOOK_PRONE + AP_PRONE + AP_PRONE );
- break;
- // no other values should be possible
- default:
- Assert( FALSE );
- return(0);
- break;
- }
- }
- BOOLEAN CheckForMercContMove( SOLDIERTYPE *pSoldier )
- {
- INT16 sAPCost;
- INT16 sGridNo;
- if ( !( gTacticalStatus.uiFlags & INCOMBAT ) )
- {
- return( FALSE );
- }
- if ( gpItemPointer != NULL )
- {
- return( FALSE );
- }
- if( pSoldier->bLife >= OKLIFE )
- {
- if( pSoldier->sGridNo != pSoldier->sFinalDestination || pSoldier->bGoodContPath )
- {
- // OK< check if we are the selected guy!
- if ( pSoldier->ubID == gusSelectedSoldier )
- {
- if (SoldierOnScreen( pSoldier->ubID ) )
- {
- sGridNo = pSoldier->sFinalDestination;
- if ( pSoldier->bGoodContPath )
- {
- sGridNo = pSoldier->sContPathLocation;
- }
- // Do a check if we can afford move here!
- // get a path to dest...
- if ( FindBestPath( pSoldier, sGridNo, pSoldier->bLevel, pSoldier->usUIMovementMode, NO_COPYROUTE, 0 ) )
- {
- sAPCost = PtsToMoveDirection( pSoldier, (UINT8)guiPathingData[ 0 ] );
- if ( EnoughPoints( pSoldier, sAPCost, 0 , FALSE ) )
- {
- return( TRUE );
- }
- }
- else
- {
- return( FALSE );
- }
- }
- }
- }
- }
- return( FALSE );
- }
- INT16 GetAPsToReadyWeapon( SOLDIERTYPE *pSoldier, UINT16 usAnimState )
- {
- UINT16 usItem;
- // If this is a dwel pistol anim
- // ATE: What was I thinking, hooking into animations like this....
- //if ( usAnimState == READY_DUAL_STAND || usAnimState == READY_DUAL_CROUCH )
- //{
- //return( AP_READY_DUAL );
- //}
- if ( IsValidSecondHandShot( pSoldier ) )
- {
- return( AP_READY_DUAL );
- }
- // OK, now check type of weapon
- usItem = pSoldier->inv[ HANDPOS ].usItem;
- if ( usItem == NOTHING )
- {
- return( 0 );
- }
- else
- {
- // CHECK FOR RIFLE
- if ( Item[ usItem ].usItemClass == IC_GUN )
- {
- return( Weapon[ usItem ].ubReadyTime );
- }
- }
- return( 0 );
- }
- INT8 GetAPsToClimbRoof( SOLDIERTYPE *pSoldier, BOOLEAN fClimbDown )
- {
- if ( !fClimbDown )
- {
- // OK, add aps to goto stand stance...
- return( (INT8)( AP_CLIMBROOF + GetAPsToChangeStance( pSoldier, ANIM_STAND ) ) );
- }
- else
- {
- // Add aps to goto crouch
- return( (INT8)( AP_CLIMBOFFROOF + GetAPsToChangeStance( pSoldier, ANIM_CROUCH ) ) );
- }
- }
- INT16 GetBPsToClimbRoof( SOLDIERTYPE *pSoldier, BOOLEAN fClimbDown )
- {
- if ( !fClimbDown )
- {
- return( BP_CLIMBROOF );
- }
- else
- {
- return( BP_CLIMBOFFROOF );
- }
- }
- INT8 GetAPsToCutFence( SOLDIERTYPE *pSoldier )
- {
- // OK, it's normally just cost, but add some if different stance...
- return( GetAPsToChangeStance( pSoldier, ANIM_CROUCH ) + AP_USEWIRECUTTERS );
- }
- INT8 GetAPsToBeginFirstAid( SOLDIERTYPE *pSoldier )
- {
- // OK, it's normally just cost, but add some if different stance...
- return( GetAPsToChangeStance( pSoldier, ANIM_CROUCH ) + AP_START_FIRST_AID );
- }
- INT8 GetAPsToBeginRepair( SOLDIERTYPE *pSoldier )
- {
- // OK, it's normally just cost, but add some if different stance...
- return( GetAPsToChangeStance( pSoldier, ANIM_CROUCH ) + AP_START_REPAIR );
- }
- INT8 GetAPsToRefuelVehicle( SOLDIERTYPE *pSoldier )
- {
- // OK, it's normally just cost, but add some if different stance...
- return( GetAPsToChangeStance( pSoldier, ANIM_CROUCH ) + AP_REFUEL_VEHICLE );
- }
- #define TOSSES_PER_10TURNS 18 // max # of grenades tossable in 10 turns
- #define AP_MIN_AIM_ATTACK 0 // minimum permitted extra aiming
- #define AP_MAX_AIM_ATTACK 4 // maximum permitted extra aiming
- INT16 MinAPsToThrow( SOLDIERTYPE *pSoldier, INT16 sGridNo, UINT8 ubAddTurningCost )
- {
- INT32 iTop, iBottom;
- INT32 iFullAPs;
- INT32 iAPCost = AP_MIN_AIM_ATTACK;
- UINT16 usInHand;
- UINT16 usTargID;
- UINT32 uiMercFlags;
- UINT8 ubDirection;
- // make sure the guy's actually got a throwable item in his hand!
- usInHand = pSoldier->inv[ HANDPOS ].usItem;
- if ( ( !Item[ usInHand ].usItemClass & IC_GRENADE ) )
- {
- #ifdef JA2TESTVERSION
- ScreenMsg( MSG_FONT_YELLOW, MSG_DEBUG, L"MinAPsToThrow - Called when in-hand item is %s", usInHand );
- #endif
- return(0);
- }
- if ( sGridNo != NOWHERE )
- {
- // Given a gridno here, check if we are on a guy - if so - get his gridno
- if ( FindSoldier( sGridNo, &usTargID, &uiMercFlags, FIND_SOLDIER_GRIDNO ) )
- {
- sGridNo = MercPtrs[ usTargID ]->sGridNo;
- }
- // OK, get a direction and see if we need to turn...
- if (ubAddTurningCost)
- {
- ubDirection = (UINT8)GetDirectionFromGridNo( sGridNo, pSoldier );
- // Is it the same as he's facing?
- if ( ubDirection != pSoldier->bDirection )
- {
- //iAPCost += GetAPsToLook( pSoldier );
- }
- }
- }
- else
- {
- // Assume we need to add cost!
- //iAPCost += GetAPsToLook( pSoldier );
- }
- // if attacking a new target (or if the specific target is uncertain)
- if ( ( sGridNo != pSoldier->sLastTarget ) )
- {
- iAPCost += AP_CHANGE_TARGET;
- }
- iAPCost += GetAPsToChangeStance( pSoldier, ANIM_STAND );
- // Calculate default top & bottom of the magic "aiming" formula)
- // get this man's maximum possible action points (ignoring carryovers)
- iFullAPs = CalcActionPoints( pSoldier );
- // the 2 times is here only to around rounding off using integer math later
- iTop = 2 * iFullAPs;
- // if it's anything but a mortar
- // if ( usInHand != MORTAR)
- // tosses per turn is for max dexterity, drops down to 1/2 at dexterity = 0
- // bottom = (TOSSES_PER_10TURNS * (50 + (ptr->dexterity / 2)) / 10);
- //else
- iBottom = ( TOSSES_PER_10TURNS * (50 + ( pSoldier->bDexterity / 2 ) ) / 10 );
- // add minimum aiming time to the overall minimum AP_cost
- // This here ROUNDS UP fractions of 0.5 or higher using integer math
- // This works because 'top' is 2x what it really should be throughout
- iAPCost += ( ( ( 100 * iTop ) / iBottom) + 1) / 2;
- // the minimum AP cost of ANY throw can NEVER be more than merc has APs!
- if ( iAPCost > iFullAPs )
- iAPCost = iFullAPs;
- // this SHOULD be impossible, but nevertheless...
- if ( iAPCost < 1 )
- iAPCost = 1;
- return ( (INT16)iAPCost );
- }
- UINT16 GetAPsToDropBomb( SOLDIERTYPE *pSoldier )
- {
- return( AP_DROP_BOMB );
- }
- UINT16 GetTotalAPsToDropBomb( SOLDIERTYPE *pSoldier, INT16 sGridNo )
- {
- INT16 sAPs = 0;
- sAPs = PlotPath( pSoldier, sGridNo, NO_COPYROUTE, NO_PLOT, TEMPORARY, (UINT16)pSoldier->usUIMovementMode, NOT_STEALTH, FORWARD, pSoldier->bActionPoints );
- if ( sAPs > 0 )
- {
- sAPs += AP_DROP_BOMB;
- }
- return( sAPs );
- }
- UINT16 GetAPsToUseRemote( SOLDIERTYPE *pSoldier )
- {
- return( AP_USE_REMOTE );
- }
- INT8 GetAPsToStealItem( SOLDIERTYPE *pSoldier, INT16 usMapPos )
- {
- UINT16 sAPCost = 0;
- sAPCost = PlotPath( pSoldier, usMapPos, NO_COPYROUTE, NO_PLOT, TEMPORARY, (UINT16)pSoldier->usUIMovementMode, NOT_STEALTH, FORWARD, pSoldier->bActionPoints );
- // ADD APS TO PICKUP
- sAPCost += AP_STEAL_ITEM;
- // CJC August 13 2002: added cost to stand into equation
- if (!(PTR_STANDING))
- {
- sAPCost += GetAPsToChangeStance( pSoldier, ANIM_STAND );
- }
- return( (INT8)sAPCost );
- }
- INT8 GetBPsToStealItem( SOLDIERTYPE *pSoldier )
- {
- return( BP_STEAL_ITEM );
- }
- INT8 GetAPsToUseJar( SOLDIERTYPE *pSoldier, INT16 usMapPos )
- {
- UINT16 sAPCost = 0;
- sAPCost = PlotPath( pSoldier, usMapPos, NO_COPYROUTE, NO_PLOT, TEMPORARY, (UINT16)pSoldier->usUIMovementMode, NOT_STEALTH, FORWARD, pSoldier->bActionPoints );
- // If point cost is zero, return 0
- if ( sAPCost != 0 )
- {
- // ADD APS TO PICKUP
- sAPCost += AP_TAKE_BLOOD;
- }
- return( (INT8)sAPCost );
- }
- INT8 GetAPsToUseCan( SOLDIERTYPE *pSoldier, INT16 usMapPos )
- {
- UINT16 sAPCost = 0;
- sAPCost = PlotPath( pSoldier, usMapPos, NO_COPYROUTE, NO_PLOT, TEMPORARY, (UINT16)pSoldier->usUIMovementMode, NOT_STEALTH, FORWARD, pSoldier->bActionPoints );
- // If point cost is zero, return 0
- if ( sAPCost != 0 )
- {
- // ADD APS TO PICKUP
- sAPCost += AP_ATTACH_CAN;
- }
- return( (INT8)sAPCost );
- }
- INT8 GetAPsToJumpOver( SOLDIERTYPE *pSoldier )
- {
- return( GetAPsToChangeStance( pSoldier, ANIM_STAND ) + AP_JUMP_OVER );
- }
|