************************************************************

* Merged Source Code from Development Trunk: Revision 4063 *
************************************************************
- Source Code is merged from: https://81.169.133.124/source/ja2/branches/Wanne/JA2%201.13%20MP
- This will be the Source for the Beta 2011 Test

git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@4064 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
Wanne
2011-01-18 09:11:09 +00:00
parent 44e1646410
commit 91087ca8c0
469 changed files with 118108 additions and 24678 deletions
+11
View File
@@ -236,3 +236,14 @@ INT8 FindDirectionForClimbing( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel
INT16 AssessTacticalSituation( INT8 bSide );
BOOLEAN TeamSeesOpponent( INT8 bSide, SOLDIERTYPE * pOpponent );
INT32 CalcStraightThreatValue( SOLDIERTYPE *pEnemy );
// SANDRO - added following functions
BOOLEAN DoctorIsPresent( SOLDIERTYPE * pPatient, BOOLEAN fOnDoctorAssignmentCheck );
BOOLEAN AIDetermineStealingWeaponAttempt( SOLDIERTYPE * pSoldier, SOLDIERTYPE * ubOpponent );
// HEADROCK HAM 4: Calculate average recoil offset for a shot.
FLOAT AICalcRecoilForShot( SOLDIERTYPE *pSoldier, OBJECTTYPE *pWeapon, UINT8 ubShotNum);
// HEADROCK HAM 4: Calculate average recoil offset for a shot.
FLOAT AICalcRecoilForShot( SOLDIERTYPE *pSoldier, OBJECTTYPE *pWeapon, UINT8 ubShotNum);
+93 -3
View File
@@ -55,6 +55,7 @@
#include "Queen Command.h"
#include "cheats.h"
#include "points.h"
#include "Soldier Functions.h" // added by SANDRO
#endif
#include "connect.h"
@@ -2043,6 +2044,23 @@ void AIDecideRadioAnimation( SOLDIERTYPE *pSoldier )
}
}
UINT32 GetTankCannonIndex()
{
UINT32 tankCannonIndex = 0;
for (UINT32 i = 0; i < MAXITEMS; i++)
{
if (Item[i].cannon)
{
tankCannonIndex = Item[i].uiIndex;
break;
}
}
return tankCannonIndex;
}
INT8 ExecuteAction(SOLDIERTYPE *pSoldier)
{
@@ -2056,8 +2074,29 @@ INT8 ExecuteAction(SOLDIERTYPE *pSoldier)
// reset this field, too
pSoldier->aiData.bLastAttackHit = FALSE;
// WANNE.TANK: Choose cannon or rocket
UINT16 usHandItem = pSoldier->inv[HANDPOS].usItem;
if (TANK(pSoldier))
{
// No cannon selected to fire
if (!Item[pSoldier->inv[HANDPOS].usItem].cannon)
{
// 50 % chance, that the tank fires with the explosive cannon
UINT32 fireWithCannon = GetRndNum(2);
if (fireWithCannon)
{
UINT32 tankCannonIndex = GetTankCannonIndex();
if (tankCannonIndex > 0)
{
usHandItem = tankCannonIndex;
}
}
}
}
UINT16 usSoldierIndex; // added by SANDRO
#ifdef TESTAICONTROL
if (gfTurnBasedAI || gTacticalStatus.fAutoBandageMode)
{
@@ -2065,7 +2104,7 @@ INT8 ExecuteAction(SOLDIERTYPE *pSoldier)
}
#endif
DebugAI( String( "%d does %s (a.d. %d) at time %ld", pSoldier->ubID, gzActionStr[pSoldier->aiData.bAction], pSoldier->aiData.usActionData, GetJA2Clock() ) );
DebugAI( String( "%d does %s (a.d. %d) at time %lu", pSoldier->ubID, gzActionStr[pSoldier->aiData.bAction], pSoldier->aiData.usActionData, GetJA2Clock() ) );
// 0verhaul: The decideaction stage does so many path plots and overrides that
// relying on a stored path from there is a bad idea.
@@ -2183,7 +2222,17 @@ INT8 ExecuteAction(SOLDIERTYPE *pSoldier)
case AI_ACTION_LEAVE_WATER_GAS: // seek nearest spot of ungassed land
case AI_ACTION_SEEK_NOISE: // seek most important noise heard
case AI_ACTION_RUN_AWAY: // run away from nearby opponent(s)
// SANDRO - ENEMY TAUNTS
if (gGameSettings.fOptions[TOPTION_ALLOW_TAUNTS] == TRUE && pSoldier->bTeam == ENEMY_TEAM && SOLDIER_CLASS_ENEMY( pSoldier->ubSoldierClass ) && pSoldier->bVisible != -1 )
{
if ( Random( 5 ) == 0 )
{
if (pSoldier->aiData.bAction == AI_ACTION_SEEK_NOISE )
StartEnemyTaunt( pSoldier, TAUNT_SEEK_NOISE );
else if (pSoldier->aiData.bAction == AI_ACTION_RUN_AWAY )
StartEnemyTaunt( pSoldier, TAUNT_RUN_AWAY );
}
}
case AI_ACTION_APPROACH_MERC: // walk up to someone to talk
case AI_ACTION_TRACK: // track by ground scent
case AI_ACTION_EAT: // monster approaching corpse
@@ -2400,8 +2449,28 @@ INT8 ExecuteAction(SOLDIERTYPE *pSoldier)
// ATE: Make sure it's a person :)
if ( IS_MERC_BODY_TYPE( pSoldier ) && pSoldier->ubProfile == NO_PROFILE )
{
// SANDRO - SOLDIER TAUNTS
if (gGameSettings.fOptions[TOPTION_ALLOW_TAUNTS] == TRUE && pSoldier->bTeam == ENEMY_TEAM && SOLDIER_CLASS_ENEMY( pSoldier->ubSoldierClass ) )
{
if ( Random( 8 ) == 0 )
{
if (Item[pSoldier->inv[HANDPOS].usItem].usItemClass == IC_GUN )
StartEnemyTaunt( pSoldier, TAUNT_FIRE_GUN );
else if (Item[pSoldier->inv[HANDPOS].usItem].grenadelauncher || Item[pSoldier->inv[HANDPOS].usItem].mortar || Item[pSoldier->inv[HANDPOS].usItem].rocketlauncher )
StartEnemyTaunt( pSoldier, TAUNT_FIRE_LAUNCHER );
else if (pSoldier->aiData.bAction == AI_ACTION_TOSS_PROJECTILE && Item[pSoldier->inv[HANDPOS].usItem].usItemClass == IC_THROWN && !Item[pSoldier->inv[HANDPOS].usItem].flare )
StartEnemyTaunt( pSoldier, TAUNT_THROW );
else if (pSoldier->aiData.bAction == AI_ACTION_KNIFE_MOVE )
{
if (Item[pSoldier->inv[HANDPOS].usItem].usItemClass == IC_BLADE )
StartEnemyTaunt( pSoldier, TAUNT_CHARGE_KNIFE );
//else if (Item[pSoldier->inv[HANDPOS].usItem].usItemClass == IC_PUNCH )
// StartEnemyTaunt( pSoldier, TAUNT_CHARGE_HTH );
}
}
}
// CC, ATE here - I put in some TEMP randomness...
if ( Random( 50 ) == 0 )
else if ( Random( 50 ) == 0 )
{
StartCivQuote( pSoldier );
}
@@ -2489,6 +2558,15 @@ INT8 ExecuteAction(SOLDIERTYPE *pSoldier)
{
HandleInitialRedAlert(pSoldier->bTeam, TRUE);
}
// SANDRO - ENEMY TAUNTS
if (gGameSettings.fOptions[TOPTION_ALLOW_TAUNTS] == TRUE && pSoldier->bTeam == ENEMY_TEAM && SOLDIER_CLASS_ENEMY( pSoldier->ubSoldierClass ) && pSoldier->bVisible != -1 )
{
if ( Random( 4 ) == 0 )
{
StartEnemyTaunt( pSoldier, TAUNT_ALERT );
}
}
//ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_BETAVERSION, L"Debug: AI radios your position!" );
// DROP THROUGH HERE!
case AI_ACTION_YELLOW_ALERT: // tell friends opponent(s) heard
@@ -2679,6 +2757,18 @@ INT8 ExecuteAction(SOLDIERTYPE *pSoldier)
// start the offer of surrender!
StartCivQuote( pSoldier );
break;
/////////////////////////////////////////////////////////////
// SANDRO - added a possibility for enemies to try to steal your gun
case AI_ACTION_STEAL_MOVE: // preparing to steal opponents weapon
pSoldier->aiData.ubPendingAction = NO_PENDING_ACTION;
pSoldier->usUIMovementMode = DetermineMovementMode( pSoldier, AI_ACTION_KNIFE_MOVE );
usSoldierIndex = WhoIsThere2( pSoldier->aiData.usActionData, pSoldier->bTargetLevel);
if ( usSoldierIndex != NOBODY )
MercStealFromMerc( pSoldier, MercPtrs[usSoldierIndex] );
break;
/////////////////////////////////////////////////////////////
default:
#ifdef BETAVERSION
+29 -15
View File
@@ -23,8 +23,14 @@
#include "environment.h"
#include "lighting.h"
#include "Soldier Create.h"
#include "SkillCheck.h" // added by SANDRO
#endif
//////////////////////////////////////////////////////////////////////////////
// SANDRO - In this file, all APBPConstants[AP_CROUCH] and APBPConstants[AP_PRONE] were changed to GetAPsCrouch() and GetAPsProne()
// On the bottom here, there are these functions made
//////////////////////////////////////////////////////////////////////
//
// CJC's DG->JA2 conversion notes
//
@@ -151,9 +157,9 @@ UINT8 StanceChange( SOLDIERTYPE * pSoldier, INT16 ubAttackAPCost )
if (PTR_STANDING)
{
if (pSoldier->bActionPoints - ubAttackAPCost >= APBPConstants[AP_CROUCH])
if (pSoldier->bActionPoints - ubAttackAPCost >= GetAPsCrouch(pSoldier, TRUE))
{
if ( (pSoldier->bActionPoints - ubAttackAPCost >= APBPConstants[AP_CROUCH] + APBPConstants[AP_PRONE]) && IsValidStance( pSoldier, ANIM_PRONE ) && ConsiderProne( pSoldier ) )
if ( (pSoldier->bActionPoints - ubAttackAPCost >= GetAPsCrouch(pSoldier, TRUE) + GetAPsProne(pSoldier, TRUE)) && IsValidStance( pSoldier, ANIM_PRONE ) && ConsiderProne( pSoldier ) )
{
return( ANIM_PRONE );
}
@@ -165,7 +171,7 @@ UINT8 StanceChange( SOLDIERTYPE * pSoldier, INT16 ubAttackAPCost )
}
else if (PTR_CROUCHED)
{
if ( (pSoldier->bActionPoints - ubAttackAPCost >= APBPConstants[AP_PRONE]) && IsValidStance( pSoldier, ANIM_PRONE ) && ConsiderProne( pSoldier ) )
if ( (pSoldier->bActionPoints - ubAttackAPCost >= GetAPsProne(pSoldier, TRUE)) && IsValidStance( pSoldier, ANIM_PRONE ) && ConsiderProne( pSoldier ) )
{
return( ANIM_PRONE );
}
@@ -192,7 +198,7 @@ UINT8 ShootingStanceChange( SOLDIERTYPE * pSoldier, ATTACKTYPE * pAttack, INT8 b
uiCurrChanceOfDamage = 0;
bAPsAfterAttack = pSoldier->bActionPoints - MinAPsToAttack( pSoldier, pAttack->sTarget, ADDTURNCOST, 1);
if (bAPsAfterAttack < APBPConstants[AP_CROUCH])
if (bAPsAfterAttack < GetAPsCrouch(pSoldier, TRUE))
{
return( 0 );
}
@@ -220,7 +226,7 @@ UINT8 ShootingStanceChange( SOLDIERTYPE * pSoldier, ATTACKTYPE * pAttack, INT8 b
for (bLoop = 0; bLoop < 3; bLoop++)
{
bStanceDiff = abs( bLoop - bStanceNum );
if (bStanceDiff == 2 && bAPsAfterAttack < APBPConstants[AP_CROUCH] + APBPConstants[AP_PRONE])
if (bStanceDiff == 2 && bAPsAfterAttack < GetAPsCrouch(pSoldier, TRUE) + GetAPsProne(pSoldier, TRUE))
{
// can't consider this!
continue;
@@ -487,7 +493,7 @@ BOOLEAN IsActionAffordable(SOLDIERTYPE *pSoldier)
break;
case AI_ACTION_PICKUP_ITEM: // grab things lying on the ground
bMinPointsNeeded = __max( MinPtsToMove( pSoldier ), APBPConstants[AP_PICKUP_ITEM] );
bMinPointsNeeded = __max( MinPtsToMove( pSoldier ), GetBasicAPsToPickupItem( pSoldier ) ); // SANDRO
break;
case AI_ACTION_OPEN_OR_CLOSE_DOOR:
@@ -497,7 +503,7 @@ BOOLEAN IsActionAffordable(SOLDIERTYPE *pSoldier)
break;
case AI_ACTION_DROP_ITEM:
bMinPointsNeeded = APBPConstants[AP_PICKUP_ITEM];
bMinPointsNeeded = GetBasicAPsToPickupItem( pSoldier ); // SANDRO
break;
case AI_ACTION_FIRE_GUN: // shoot at nearby opponent
@@ -534,7 +540,7 @@ BOOLEAN IsActionAffordable(SOLDIERTYPE *pSoldier)
break;
case AI_ACTION_CHANGE_STANCE: // crouch
bMinPointsNeeded = APBPConstants[AP_CROUCH];
bMinPointsNeeded = GetAPsCrouch(pSoldier, TRUE);
break;
case AI_ACTION_GIVE_AID: // help injured/dying friend
@@ -542,16 +548,17 @@ BOOLEAN IsActionAffordable(SOLDIERTYPE *pSoldier)
break;
case AI_ACTION_CLIMB_ROOF:
// SANDRO - improved this a bit
if (pSoldier->pathing.bLevel == 0)
{
if( PTR_CROUCHED ) bAPForStandUp = 2;
if( PTR_PRONE ) bAPForStandUp = 4;
bMinPointsNeeded = APBPConstants[AP_CLIMBROOF] + bAPForStandUp + bAPToLookAtWall;
if( PTR_CROUCHED ) bAPForStandUp = (INT8)(GetAPsCrouch(pSoldier, TRUE));
if( PTR_PRONE ) bAPForStandUp = GetAPsCrouch(pSoldier, TRUE) + GetAPsProne(pSoldier, TRUE);
bMinPointsNeeded = GetAPsToClimbRoof( pSoldier, FALSE ) + bAPForStandUp + bAPToLookAtWall;
}
else
{
if( !PTR_CROUCHED ) bAPForStandUp = 2;
bMinPointsNeeded = APBPConstants[AP_CLIMBOFFROOF] + bAPForStandUp + bAPToLookAtWall;
if( !PTR_CROUCHED ) bAPForStandUp = (INT8)(GetAPsCrouch(pSoldier, TRUE));
bMinPointsNeeded = GetAPsToClimbRoof( pSoldier, TRUE ) + bAPForStandUp + bAPToLookAtWall;
}
break;
@@ -564,6 +571,10 @@ BOOLEAN IsActionAffordable(SOLDIERTYPE *pSoldier)
bMinPointsNeeded = 0;
break;
case AI_ACTION_STEAL_MOVE: // added by SANDRO
//bMinPointsNeeded = GetAPsToStealItem( pSoldier, NULL, pSoldier->aiData.usActionData );;
break;
default:
#ifdef BETAVERSION
//NumMessage("AffordableAction - Illegal action type = ",pSoldier->aiData.bAction);
@@ -2084,6 +2095,9 @@ INT8 CalcMorale(SOLDIERTYPE *pSoldier)
(pSoldier->aiData.bAttitude == BRAVESOLO || pSoldier->aiData.bAttitude == BRAVEAID))
bMoraleCategory = MORALE_WORRIED;
// SANDRO - on Insane difficulty enemy morale cannot go below worried
if (bMoraleCategory == MORALE_HOPELESS && gGameOptions.ubDifficultyLevel == DIF_LEVEL_INSANE )
bMoraleCategory = MORALE_WORRIED;
#ifdef DEBUGDECISIONS
STR tempstr;
@@ -2128,7 +2142,7 @@ INT32 CalcManThreatValue( SOLDIERTYPE *pEnemy, INT32 sMyGrid, UINT8 ubReduceForC
else
{
// ADD twice the man's level (2-20)
iThreatValue += pEnemy->stats.bExpLevel;
iThreatValue += EffectiveExpLevel(pEnemy); // SANDRO - find precise effective exp level
// ADD man's total action points (10-35)
iThreatValue += pEnemy->CalcActionPoints();
@@ -2725,7 +2739,7 @@ INT32 CalcStraightThreatValue( SOLDIERTYPE *pEnemy )
else
{
// ADD twice the man's level (2-20)
iThreatValue += pEnemy->stats.bExpLevel;
iThreatValue += EffectiveExpLevel(pEnemy); // SANDRO - find precise effective exp level
// ADD man's total action points (10-35)
iThreatValue += pEnemy->CalcActionPoints();
+326 -32
View File
@@ -21,6 +21,7 @@
#include "environment.h"
#include "lighting.h"
#include "Sound Control.h"
#include "message.h"
#endif
extern INT16 DirIncrementer[8];
@@ -115,6 +116,36 @@ void LoadWeaponIfNeeded(SOLDIERTYPE *pSoldier)
}
}
// FROM SB JA2005
void ResetWeaponMode( SOLDIERTYPE * pSoldier )
{
// ATE: Don't do this if in a fire amimation.....
if ( gAnimControl[ pSoldier->usAnimState ].uiFlags & ANIM_FIRE )
{
return;
}
pSoldier->bWeaponMode = WM_NORMAL;
//<DR>
pSoldier->aiData.bShownAimTime = REFINE_AIM_1;
//!pSoldier->aiData.ubBurstAP = 0; //SB reset long burst length
//^^^^òàêîãî ñâîéñòâà íåò, äîáàâëÿòü â ñîëæåð êîíòðîë.õ
// gfDisplayFullCountRing = FALSE;
// gfDisplayFullCountRingBurst = FALSE;
//</DR>
// pSoldier->bDoBurst = Weapon[Item[pSoldier->inv[HANDPOS].usItem].ubClassIndex].mode[WM_NORMAL].usROF > 0;
// DirtyMercPanelInterface( pSoldier, DIRTYLEVEL2 );
// gfUIForceReExamineCursorData = TRUE;
// gfShowBurstLength = Weapon[Item[pSoldier->inv[HANDPOS].usItem].ubClassIndex].mode[pSoldier->bWeaponMode].usROF > 0;
// gfShowBurstLength = Weapon[Item[pSoldier->inv[HANDPOS].usItem].ubClassIndex].mode[pSoldier->bWeaponMode].ubBullets > 1;
}
//</SB>
void CalcBestShot(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestShot, BOOLEAN shootUnseen)
{
UINT32 uiLoop;
@@ -254,9 +285,7 @@ void CalcBestShot(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestShot, BOOLEAN shootUns
if ( TANK( pSoldier ) )
{
// HEADROCK HAM 3.6: Calculation must take into account APBP constants and other aiming modifications!
INT8 bAPsLeft = pSoldier->bActionPoints - ubMinAPcost;
ubMaxPossibleAimTime = CalcAimingLevelsAvailableWithAP( pSoldier, pOpponent->sGridNo, bAPsLeft );
ubMaxPossibleAimTime = pSoldier->bActionPoints - ubMinAPcost;
// always burst
if ( ubMaxPossibleAimTime < ubBurstAPs )
@@ -291,11 +320,7 @@ void CalcBestShot(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestShot, BOOLEAN shootUns
//sprintf(tempstr,"Vs. %s, at AimTime %d, ubChanceToHit = %d",ExtMen[pOpponent->ubID].name,ubAimTime,ubChanceToHit);
//PopMessage(tempstr);
// HEADROCK HAM 3.6: Actual aiming time is no longer 1AP per level... Failure to take this into account
// may yield skewed results in favour of high-aim targets.
INT16 sActualAimTime = CalcAPCostForAiming( pSoldier, pOpponent->sGridNo, (INT8)ubAimTime );
iHitRate = (pSoldier->bActionPoints * ubChanceToHit) / (ubRawAPCost + sActualAimTime);
iHitRate = (pSoldier->bActionPoints * ubChanceToHit) / (ubRawAPCost + ubAimTime);
//NumMessage("hitRate = ",iHitRate);
// if aiming for this amount of time produces a better hit rate
@@ -501,7 +526,7 @@ void CalcBestThrow(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow)
if ( EXPLOSIVE_GUN( usInHand ) )
{
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"explosive gun");
iTossRange = Weapon[ usInHand ].usRange / CELL_X_SIZE;
iTossRange = GetModifiedGunRange(usInHand) / CELL_X_SIZE;
}
else
{
@@ -1068,7 +1093,8 @@ void CalcBestThrow(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow)
}
// calculate the maximum possible aiming time
ubMaxPossibleAimTime = min(AllowedAimingLevels(pSoldier),pSoldier->bActionPoints - ubMinAPcost);
// HEADROCK HAM 4: Required for new Aiming Level Limits function
ubMaxPossibleAimTime = min( AllowedAimingLevels(pSoldier, sGridNo), pSoldier->bActionPoints - ubMinAPcost);
DebugMsg(TOPIC_JA2 , DBG_LEVEL_3 , String("Max Possible Aim Time = %d",ubMaxPossibleAimTime ));
// calc next attack's minimum AP cost (excludes readying & turning)
@@ -1282,7 +1308,8 @@ void CalcBestStab(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestStab, BOOLEAN fBladeAt
iBestHitRate = 0; // reset best hit rate to minimum
// calculate the maximum possible aiming time
ubMaxPossibleAimTime = min(AllowedAimingLevels(pSoldier),pSoldier->bActionPoints - ubMinAPCost);
// HEADROCK HAM 4: Required for new Aiming Level Limits function
ubMaxPossibleAimTime = min(AllowedAimingLevels(pSoldier, pOpponent->sGridNo),pSoldier->bActionPoints - ubMinAPCost);
//NumMessage("Max Possible Aim Time = ",ubMaxPossibleAimTime);
// consider the various aiming times
@@ -1433,8 +1460,9 @@ void CalcTentacleAttack(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestStab )
if (pSoldier->pathing.bLevel != pOpponent->pathing.bLevel)
continue; // next merc
UINT16 usRange = GetModifiedGunRange(CREATURE_QUEEN_TENTACLES);
// if this opponent is outside the range of our tentacles
if ( GetRangeInCellCoordsFromGridNoDiff( pSoldier->sGridNo, pOpponent->sGridNo ) > Weapon[ CREATURE_QUEEN_TENTACLES].usRange )
if ( GetRangeInCellCoordsFromGridNoDiff( pSoldier->sGridNo, pOpponent->sGridNo ) > usRange )
{
continue; // next merc
}
@@ -1609,10 +1637,16 @@ INT32 EstimateShotDamage(SOLDIERTYPE *pSoldier, SOLDIERTYPE *pOpponent, INT16 ub
// calculate distance to target, obtain his gun's maximum range rating
iRange = GetRangeInCellCoordsFromGridNoDiff( pSoldier->sGridNo, pOpponent->sGridNo );
iMaxRange = Weapon[usItem].usRange;
// SANDRO - added specific range calculation
if ( Item[ usItem ].usItemClass & IC_GUN )
iMaxRange = GunRange( pObj, pSoldier );
else
iMaxRange = GetModifiedGunRange(usItem);
// bullet loses speed and penetrating power, 50% loss per maximum range
iPowerLost = ((50 * iRange) / iMaxRange);
// SANDRO - you know, 50% is a lot, it often leads to negative damage values in the end
// while there is no true effect of this in game !!! Made it 25%!
iPowerLost = ((25 * iRange) / iMaxRange);
// up to 50% extra impact for making particularly accurate successful shots
ubBonus = ubChanceToHit / 4; // /4 is really /2 and /2 again
@@ -1641,7 +1675,7 @@ INT32 EstimateShotDamage(SOLDIERTYPE *pSoldier, SOLDIERTYPE *pOpponent, INT16 ub
// check for ceramic plates; these do affect monster spit
for (attachmentList::iterator iter = pOpponent->inv[VESTPOS][0]->attachments.begin(); iter != pOpponent->inv[VESTPOS][0]->attachments.end(); ++iter) {
if (Item[iter->usItem].usItemClass == IC_ARMOUR && (*iter)[0]->data.objectStatus > 0 )
if (Item[iter->usItem].usItemClass == IC_ARMOUR && (*iter)[0]->data.objectStatus > 0 && iter->exists() )
{
iTorsoProt += (INT32) Armour[Item[iter->usItem].ubClassIndex].ubProtection *
(INT32) (*iter)[0]->data.objectStatus / 100;
@@ -1745,7 +1779,7 @@ INT32 EstimateThrowDamage( SOLDIERTYPE *pSoldier, UINT8 ubItemPos, SOLDIERTYPE *
else if ( Item[pSoldier->inv[ ubItemPos ].usItem].rocketlauncher || Item[pSoldier->inv[ ubItemPos ].usItem].grenadelauncher || Item[pSoldier->inv[ ubItemPos ].usItem].mortar )
{
OBJECTTYPE* pAttachment = FindLaunchableAttachment(&pSoldier->inv[ ubItemPos ],pSoldier->inv[ ubItemPos ].usItem ) ;
if ( pAttachment )
if ( pAttachment->exists() )
ubExplosiveIndex = Item[pAttachment->usItem].ubClassIndex;
else
return 0;
@@ -1843,21 +1877,44 @@ INT32 EstimateStabDamage( SOLDIERTYPE *pSoldier, SOLDIERTYPE *pOpponent,
}
else
{
// NB martial artists don't get a bonus for using brass knuckles!
if (pSoldier->usAttackingWeapon && !( HAS_SKILL_TRAIT( pSoldier, MARTIALARTS ) ) )
// this all was a little changed for enhanced close combat system - SANDRO
if ( gGameExternalOptions.fEnhancedCloseCombatSystem )
{
iImpact = GetDamage(&pSoldier->inv[HANDPOS]);
iImpact = EffectiveStrength( pSoldier ) / 5; // 0 to 20 for strength, adjusted by damage taken
if ( pSoldier->usAttackingWeapon )
{
iImpact += GetDamage(&pSoldier->inv[HANDPOS]);
}
else
{
// base HTH damage
iImpact += 4; // Slightly reduced for we can now attack to head for bigger damage - SANDRO
// Add melee damage multiplier to bare HtH attacks as well - SANDRO
// actually I make the influence a little lesser, because to the blades and so,
// only the item impact is multiplied, not the level and strength bonus, but here it does
iImpact += iImpact * gGameExternalOptions.iMeleeDamageModifier / 120;
}
}
else
{
// base HTH damage
iImpact = 5;
// NB martial artists don't get a bonus for using brass knuckles!
if (pSoldier->usAttackingWeapon && !( HAS_SKILL_TRAIT( pSoldier, MARTIALARTS_OT ) ) )
{
iImpact = GetDamage(&pSoldier->inv[HANDPOS]);
}
else
{
// base HTH damage
iImpact = 5;
}
iImpact += EffectiveStrength( pSoldier ) / 5; // 0 to 20 for strength, adjusted by damage taken
}
iImpact += EffectiveStrength( pSoldier ) / 5; // 0 to 20 for strength, adjusted by damage taken
}
iImpact += (pSoldier->stats.bExpLevel / 2); // 0 to 4 for level
iImpact += (EffectiveExpLevel( pSoldier ) / 2); // 0 to 4 for level // SANDRO - added effective level calc
iFluke = 0;
iBonus = ubChanceToHit / 4; // up to 50% extra impact for accurate attacks
@@ -1867,17 +1924,81 @@ INT32 EstimateStabDamage( SOLDIERTYPE *pSoldier, SOLDIERTYPE *pOpponent,
if (!fBladeAttack)
{
// add bonuses for hand-to-hand and martial arts
if ( HAS_SKILL_TRAIT( pSoldier, MARTIALARTS ) )
// Check for new traits - SANDRO
if ( gGameOptions.fNewTraitSystem )
{
iImpact = iImpact * (100 + gbSkillTraitBonus[MARTIALARTS] * NUM_SKILL_TRAITS( pSoldier, MARTIALARTS ) ) / 100;
if (!pSoldier->usAttackingWeapon || Item[pSoldier->inv[HANDPOS].usItem].brassknuckles)
{
// add bonuses for martial arts
if ( HAS_SKILL_TRAIT( pSoldier, MARTIAL_ARTS_NT ) )
{
// also add breath damage bonus into consideration
iImpact = (INT32)((iImpact * ( 100 + (gSkillTraitValues.ubMABonusDamageHandToHand + gSkillTraitValues.ubMABonusBreathDamageHandToHand) * NUM_SKILL_TRAITS( pSoldier, MARTIAL_ARTS_NT ) ) / 100) + 0.5);
// The Spinning kicks or aimed punch bonus - SANDRO
//if (pSoldier->usAnimState == NINJA_SPINKICK || (pSoldier->aiData.bAimTime > 0))
//{
// iImpact += (iImpact * gSkillTraitValues.usMAAimedPunchDamageBonus * NUM_SKILL_TRAITS( pSoldier, MARTIAL_ARTS_NT ) ) / 100; // +75% damage per trait
//}
}
}
else
{
// +30% damage of blunt weapons for melee character
if (HAS_SKILL_TRAIT( pSoldier, MELEE_NT ))
{
iImpact = (INT32)((iImpact * (100 + gSkillTraitValues.ubMEDamageBonusBlunt)/100) + 0.5);
//if (pSoldier->aiData.bAimTime > 0)
//{
// iImpact += (iImpact * (100 + gSkillTraitValues.usMEAimedMeleeAttackDamageBonus) / 100); // 50% incresed damage if focused melee attack
//}
}
}
}
if ( HAS_SKILL_TRAIT( pSoldier, HANDTOHAND ) )
else
{
iImpact = iImpact * (100 + gbSkillTraitBonus[HANDTOHAND] * NUM_SKILL_TRAITS( pSoldier, HANDTOHAND ) ) / 100;
if ( HAS_SKILL_TRAIT( pSoldier, MARTIALARTS_OT ) )
{
iImpact = (INT32)((iImpact * (100 + gbSkillTraitBonus[MARTIALARTS_OT] * NUM_SKILL_TRAITS( pSoldier, MARTIALARTS_OT ) ) / 100) + 0.5);
}
if ( HAS_SKILL_TRAIT( pSoldier, HANDTOHAND_OT ) )
{
iImpact = (INT32)((iImpact * (100 + gbSkillTraitBonus[HANDTOHAND_OT] * NUM_SKILL_TRAITS( pSoldier, HANDTOHAND_OT ) ) / 100) + 0.5);
}
}
// SANDRO - Enhanced Close Combat System - aiming at body parts makes difference
if (gGameExternalOptions.fEnhancedCloseCombatSystem && (gAnimControl[ pOpponent->usAnimState ].ubEndHeight == ANIM_PRONE))
{
iImpact = (INT32)(iImpact * 150 / 100); // 50% incresed damage to lying characters
}
// Here, if we're doing a bare-fisted attack,
// we want to pay attention just to wounds inflicted
iImpact = iImpact / PUNCH_REAL_DAMAGE_PORTION;
// SANDRO - No, we may consider the breath damage as asort of "real" damage too, so only reduce it by half
iImpact = iImpact / 2;
//iImpact = iImpact / PUNCH_REAL_DAMAGE_PORTION;
}
// SANDRO - damage bonus to melee trait
else
{
if ( HAS_SKILL_TRAIT( pSoldier, MELEE_NT ) && (gGameOptions.fNewTraitSystem) )
{
iImpact += (iImpact * (100 + gSkillTraitValues.ubMEDamageBonusBlades ) / 100); // +30% damage
//if (pSoldier->aiData.bAimTime > 0)
//{
// iImpact += (iImpact * ( 100 + gSkillTraitValues.usMEAimedMeleeAttackDamageBonus ) / 100); // 50% incresed damage if focused melee attack
//}
}
// SANDRO - Enhanced Close Combat System
if (gGameExternalOptions.fEnhancedCloseCombatSystem)
{
if (gAnimControl[ pOpponent->usAnimState ].ubEndHeight == ANIM_PRONE)
{
iImpact = (INT32)(iImpact * 140 / 100); // 40% incresed damage to lying characters
}
}
}
if (iImpact < 1)
@@ -1914,7 +2035,24 @@ INT8 TryToReload( SOLDIERTYPE * pSoldier )
{
(*pObj)[0]->data.gun.ubGunState |= GS_CARTRIDGE_IN_CHAMBER;
DeductPoints(pSoldier, Weapon[Item[(pObj)->usItem].ubClassIndex].APsToReloadManually, 0);
////////////////////////////////////////////////////////////////////////////////////////////////////////
// STOMP traits - SANDRO
if ( gGameOptions.fNewTraitSystem )
{
// Sniper trait makes chambering a round faster
if (( Weapon[Item[(pObj)->usItem].ubClassIndex].ubWeaponType == GUN_SN_RIFLE || Weapon[Item[(pObj)->usItem].ubClassIndex].ubWeaponType == GUN_RIFLE ) && HAS_SKILL_TRAIT( pSoldier, SNIPER_NT ))
DeductPoints(pSoldier, (INT16)(((Weapon[Item[(pObj)->usItem].ubClassIndex].APsToReloadManually * (100 - gSkillTraitValues.ubSNChamberRoundAPsReduction * NUM_SKILL_TRAITS( pSoldier, SNIPER_NT )))/100) + 0.5), 0);
// Ranger trait makes pumping shotguns faster
else if (( Weapon[Item[(pObj)->usItem].ubClassIndex].ubWeaponType == GUN_SHOTGUN ) && HAS_SKILL_TRAIT( pSoldier, RANGER_NT ))
DeductPoints(pSoldier, (INT16)(((Weapon[Item[(pObj)->usItem].ubClassIndex].APsToReloadManually * (100 - gSkillTraitValues.ubRAPumpShotgunsAPsReduction * NUM_SKILL_TRAITS( pSoldier, RANGER_NT )))/100) + 0.5), 0);
else
DeductPoints(pSoldier, Weapon[Item[(pObj)->usItem].ubClassIndex].APsToReloadManually, 0);
}
else
{
DeductPoints(pSoldier, Weapon[Item[(pObj)->usItem].ubClassIndex].APsToReloadManually, 0);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
PlayJA2Sample( Weapon[ Item[pObj->usItem].ubClassIndex ].ManualReloadSound, RATE_11025, SoundVolume( HIGHVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ) );
@@ -1942,7 +2080,24 @@ INT8 TryToReload( SOLDIERTYPE * pSoldier )
{
(*pObj2)[0]->data.gun.ubGunState |= GS_CARTRIDGE_IN_CHAMBER;
DeductPoints(pSoldier, Weapon[Item[(pObj2)->usItem].ubClassIndex].APsToReloadManually, 0);
////////////////////////////////////////////////////////////////////////////////////////////////////////
// STOMP traits - SANDRO (well, I don't know any one-handed sniper rifle, but what the hell...)
if ( gGameOptions.fNewTraitSystem )
{
// Sniper trait makes chambering a round faster
if (( Weapon[Item[(pObj2)->usItem].ubClassIndex].ubWeaponType == GUN_SN_RIFLE || Weapon[Item[(pObj2)->usItem].ubClassIndex].ubWeaponType == GUN_RIFLE ) && HAS_SKILL_TRAIT( pSoldier, SNIPER_NT ))
DeductPoints(pSoldier, (INT16)(((Weapon[Item[(pObj2)->usItem].ubClassIndex].APsToReloadManually * (100 - gSkillTraitValues.ubSNChamberRoundAPsReduction * NUM_SKILL_TRAITS( pSoldier, SNIPER_NT )))/100) + 0.5), 0);
// Ranger trait makes pumping shotguns faster
else if (( Weapon[Item[(pObj2)->usItem].ubClassIndex].ubWeaponType == GUN_SHOTGUN ) && HAS_SKILL_TRAIT( pSoldier, RANGER_NT ))
DeductPoints(pSoldier, (INT16)(((Weapon[Item[(pObj2)->usItem].ubClassIndex].APsToReloadManually * (100 - gSkillTraitValues.ubRAPumpShotgunsAPsReduction * NUM_SKILL_TRAITS( pSoldier, RANGER_NT )))/100) + 0.5), 0);
else
DeductPoints(pSoldier, Weapon[Item[(pObj2)->usItem].ubClassIndex].APsToReloadManually, 0);
}
else
{
DeductPoints(pSoldier, Weapon[Item[(pObj2)->usItem].ubClassIndex].APsToReloadManually, 0);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
PlayJA2Sample( Weapon[ Item[pObj2->usItem].ubClassIndex ].ManualReloadSound, RATE_11025, SoundVolume( HIGHVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ) );
@@ -2492,10 +2647,10 @@ void CheckIfShotPossible(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestShot, BOOLEAN s
// (suppressionFire && IsGunAutofireCapable(&pSoldier->inv[pBestShot->bWeaponIn] ) && GetMagSize(pObj) > 30 && (*pObj)[0]->data.gun.ubGunShotsLeft > 20 ))
BOOLEAN fEnableAISuppression = FALSE;
if ( gGameExternalOptions.fIncreaseAISuppressionFire && ((!suppressionFire && ( (IsScoped(pObj) && GunRange(pObj) > MaxNormalDistanceVisible() ) || pSoldier->aiData.bOrders == SNIPER ) ) ||
if ( gGameExternalOptions.fIncreaseAISuppressionFire && ((!suppressionFire && ( (IsScoped(pObj) && GunRange(pObj, pSoldier) > MaxNormalDistanceVisible() ) || pSoldier->aiData.bOrders == SNIPER ) ) || // SANDRO - added argument to GunRange()
(suppressionFire && IsGunAutofireCapable(&pSoldier->inv[pBestShot->bWeaponIn]))) )
fEnableAISuppression = TRUE;
else if ( !gGameExternalOptions.fIncreaseAISuppressionFire && ( (!suppressionFire && ( (IsScoped(pObj) && GunRange(pObj) > MaxNormalDistanceVisible() ) || pSoldier->aiData.bOrders == SNIPER ) ) ||
else if ( !gGameExternalOptions.fIncreaseAISuppressionFire && ( (!suppressionFire && ( (IsScoped(pObj) && GunRange(pObj, pSoldier) > MaxNormalDistanceVisible() ) || pSoldier->aiData.bOrders == SNIPER ) ) || // SANDRO - added argument
(suppressionFire && IsGunAutofireCapable(&pSoldier->inv[pBestShot->bWeaponIn] ) && GetMagSize(pObj) > 30 && (*pObj)[0]->data.gun.ubGunShotsLeft > 20 )))
fEnableAISuppression = TRUE;
@@ -2523,3 +2678,142 @@ void CheckIfShotPossible(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestShot, BOOLEAN s
}
}
}
// SANDRO - function to determine if we should try to steal the enemy gun
BOOLEAN AIDetermineStealingWeaponAttempt( SOLDIERTYPE * pSoldier, SOLDIERTYPE * pOpponent )
{
INT16 sChance = 0;
UINT32 uiSuccessChance = 0;
if( pOpponent == NULL )
{
return( FALSE );
}
if( pOpponent->bTeam != gbPlayerNum )
{
return( FALSE );
}
if( pOpponent->bCollapsed || pOpponent->bBreathCollapsed )
{
return( FALSE );
}
pSoldier->usUIMovementMode = RUNNING;
if( pSoldier->bActionPoints < GetAPsToStealItem( pSoldier, NULL, pOpponent->sGridNo ) )
{
return( FALSE );
}
if( (pOpponent->inv[HANDPOS].exists() != true) )
{
return( FALSE );
}
if ( !(Item[pOpponent->inv[HANDPOS].usItem].usItemClass & IC_WEAPON) )
{
UINT16 dfgvdfv = Item[pOpponent->inv[HANDPOS].usItem].usItemClass;
return( FALSE );
}
uiSuccessChance = CalcChanceToSteal(pSoldier, pOpponent, 0);
if ( uiSuccessChance >= 100 )
{
sChance = 90;
}
else if ( uiSuccessChance >= 85 )
{
sChance = 75;
}
else if ( uiSuccessChance >= 70 )
{
sChance = 60;
}
else if ( uiSuccessChance >= 50 )
{
sChance = 40;
}
else if ( uiSuccessChance >= 25 )
{
sChance = 15;
}
else
{
return( FALSE );
}
if( gGameOptions.fNewTraitSystem )
{
if( !HAS_SKILL_TRAIT( pSoldier, MARTIAL_ARTS_NT ) )
{
return( FALSE );
}
else if( NUM_SKILL_TRAITS( pSoldier, MARTIAL_ARTS_NT ) > 1 )
{
sChance += 50;
}
}
else
{
if( !HAS_SKILL_TRAIT( pSoldier, MARTIALARTS_OT ) && !HAS_SKILL_TRAIT( pSoldier, HANDTOHAND_OT ) )
{
return( FALSE );
}
else if(( NUM_SKILL_TRAITS( pSoldier, MARTIALARTS_OT ) > 1 ) || ( NUM_SKILL_TRAITS( pSoldier, HANDTOHAND_OT ) > 1 ))
{
sChance += 25;
}
}
if( pSoldier->stats.bLife < pSoldier->stats.bLifeMax )
{
sChance -= (pSoldier->stats.bLifeMax - pSoldier->stats.bLife);
}
if( pSoldier->bBreath < pSoldier->bBreathMax )
{
sChance -= ((pSoldier->bBreathMax - pSoldier->bBreath) / 2);
}
if( pOpponent->stats.bLife < pOpponent->stats.bLifeMax )
{
sChance += (pOpponent->stats.bLifeMax - pOpponent->stats.bLife);
}
if( pOpponent->bBreath < pOpponent->bBreathMax )
{
sChance += ((pOpponent->bBreathMax - pOpponent->bBreath) / 2);
}
if( pSoldier->bActionPoints > (GetAPsToStealItem( pSoldier, NULL, pOpponent->sGridNo ) + (2 * ApsToPunch( pSoldier ))) )
{
sChance += 35;
}
else if ( pSoldier->bActionPoints > (GetAPsToStealItem( pSoldier, NULL, pOpponent->sGridNo ) + ApsToPunch( pSoldier )) )
{
sChance += 20;
}
else
{
sChance -= 10;
}
if( Chance( sChance ) )
{
return( TRUE );
}
else
{
return( FALSE );
}
}
// HEADROCK HAM 4: This is required for the AI to be able to assess the length of autofire volleys using the new
// recoil system.
FLOAT AICalcRecoilForShot( SOLDIERTYPE *pSoldier, OBJECTTYPE *pWeapon, UINT8 ubShotNum)
{
INT8 bRecoilX = 0;
INT8 bRecoilY = 0;
GetRecoil( pWeapon, &bRecoilX, &bRecoilY, ubShotNum );
// Return average shooter's ability to control this gun.
// HEADROCK HAM 4: TODO: Incorporate items that alter max counter-force.
FLOAT AverageRecoil = __max(0, ((FLOAT)sqrt( (FLOAT)(bRecoilX * bRecoilX) + (FLOAT)(bRecoilY * bRecoilY) ) - (gGameCTHConstants.RECOIL_MAX_COUNTER_FORCE * 0.7f) ) );
return AverageRecoil;
}
+324 -94
View File
@@ -36,6 +36,11 @@
#include "connect.h"
#include "Text.h"
//////////////////////////////////////////////////////////////////////////////
// SANDRO - In this file, all APBPConstants[AP_CROUCH] and APBPConstants[AP_PRONE] were changed to GetAPsCrouch() and GetAPsProne()
// On the bottom here, there are these functions made
//////////////////////////////////////////////////////////////////////
extern BOOLEAN gfHiddenInterrupt;
extern BOOLEAN gfUseAlternateQueenPosition;
@@ -845,9 +850,36 @@ INT8 DecideActionGreen(SOLDIERTYPE *pSoldier)
}
//ddd{
if(gGameExternalOptions.bNewTacticalAIBehavior
&& !( (gTacticalStatus.uiFlags & TURNBASED) && (gTacticalStatus.uiFlags & INCOMBAT) )
&& pSoldier->bTeam == ENEMY_TEAM)
{
INT32 cnt;
ROTTING_CORPSE * pCorpse;
for ( cnt = 0; cnt < giNumRottingCorpse; cnt++ )
{
pCorpse = &(gRottingCorpse[ cnt ] );
if ( pCorpse->fActivated && pCorpse->def.ubAIWarningValue > 0 )
if ( PythSpacesAway( pSoldier->sGridNo, pCorpse->def.sGridNo ) <= 5 )//ïðèäåëàòü ñðàâíåíèå ïåðåìåííî äàëüíîñòè âèäåíèÿ (smaxvid ?)
{
//ïðîâåðèòü, íàõîäèòñÿ ëè òðóï â ïîëå çðåíèÿ äðàíèêà.ìåíòà?
//CHRISL: Shouldn't we be using the corpse's bLevel? Otherwise a soldier inside a building can see a corpse on the roof of that building
//if ( SoldierTo3DLocationLineOfSightTest( pSoldier, pCorpse->def.sGridNo, pSoldier->pathing.bLevel, 3, TRUE, CALC_FROM_WANTED_DIR ) )
if ( SoldierTo3DLocationLineOfSightTest( pSoldier, pCorpse->def.sGridNo, pCorpse->def.bLevel, 3, TRUE, CALC_FROM_WANTED_DIR ) )
{
ScreenMsg( MSG_FONT_YELLOW, MSG_INTERFACE, L"Warning: enemy corpse found!!!" );
//pCorpse->def.ubAIWarningValue=0;
gRottingCorpse[ cnt ].def.ubAIWarningValue=0;
return( AI_ACTION_RED_ALERT );
}
}
}
}
//ddd}
////////////////////////////////////////////////////////////////////////////
// POINT PATROL: move towards next point unless getting a bit winded
@@ -2204,7 +2236,10 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier, UINT8 ubUnconsciousOK)
if (BestThrow.ubPossible)
{
// if firing mortar make sure we have room
if ( Item[pSoldier->inv[ BestThrow.bWeaponIn ].usItem].mortar )
//if ( Item[pSoldier->inv[ BestThrow.bWeaponIn ].usItem].mortar ) //comm by ddd
if (Item[pSoldier->inv[ BestThrow.bWeaponIn ].usItem].mortar
|| Item[pSoldier->inv[ BestThrow.bWeaponIn ].usItem].grenadelauncher
|| Item[pSoldier->inv[ BestThrow.bWeaponIn ].usItem].flare )
{
ubOpponentDir = GetDirectionFromGridNo( BestThrow.sTarget, pSoldier );
@@ -2311,7 +2346,7 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier, UINT8 ubUnconsciousOK)
OBJECTTYPE * gun = &pSoldier->inv[BestShot.bWeaponIn];
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,String("decideactionred: men in sector %d, ubspotters called by %d, nobody %d",gTacticalStatus.Team[pSoldier->bTeam].bMenInSector,gTacticalStatus.ubSpottersCalledForBy,NOBODY ));
//if ( ( ( IsScoped(gun) && GunRange(gun) > pSoldier->GetMaxDistanceVisible(BestShot.sTarget, BestShot.bTargetLevel) ) || pSoldier->aiData.bOrders == SNIPER ) &&
if ( ( ( IsScoped(gun) && GunRange(gun) > MaxNormalDistanceVisible() ) || pSoldier->aiData.bOrders == SNIPER ) &&
if ( ( ( IsScoped(gun) && GunRange(gun, pSoldier) > MaxNormalDistanceVisible() ) || pSoldier->aiData.bOrders == SNIPER ) && // SANDRO - added argument
(gTacticalStatus.Team[pSoldier->bTeam].bMenInSector > 1) &&
(gTacticalStatus.ubSpottersCalledForBy == NOBODY))
@@ -2360,17 +2395,30 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier, UINT8 ubUnconsciousOK)
pSoldier->aiData.usActionData = BestShot.sTarget;
//pSoldier->aiData.bAimTime = BestShot.ubAimTime;
INT16 ubBurstAPs = 0;
FLOAT dTotalRecoil = 0;
pSoldier->bDoAutofire = 0;
do
{
pSoldier->bDoAutofire++;
ubBurstAPs = CalcAPsToAutofire( pSoldier->CalcActionPoints(), &(pSoldier->inv[BestShot.bWeaponIn]), pSoldier->bDoAutofire );
if(UsingNewCTHSystem() == true){
do
{
INT8 bRecoilX = 0;
INT8 bRecoilY = 0;
pSoldier->bDoAutofire++;
dTotalRecoil += AICalcRecoilForShot( pSoldier, &(pSoldier->inv[BestShot.bWeaponIn]), pSoldier->bDoAutofire );
ubBurstAPs = CalcAPsToAutofire( pSoldier->CalcActionPoints(), &(pSoldier->inv[BestShot.bWeaponIn]), pSoldier->bDoAutofire );
}
while( pSoldier->bActionPoints >= BestShot.ubAPCost + ubBurstAPs && pSoldier->inv[ pSoldier->ubAttackingHand ][0]->data.gun.ubGunShotsLeft >= pSoldier->bDoAutofire
&& dTotalRecoil <= 10.0f );
} else {
do
{
pSoldier->bDoAutofire++;
ubBurstAPs = CalcAPsToAutofire( pSoldier->CalcActionPoints(), &(pSoldier->inv[BestShot.bWeaponIn]), pSoldier->bDoAutofire );
}
while( pSoldier->bActionPoints >= BestShot.ubAPCost + ubBurstAPs &&
pSoldier->inv[ pSoldier->ubAttackingHand ][0]->data.gun.ubGunShotsLeft >= pSoldier->bDoAutofire &&
GetAutoPenalty(&pSoldier->inv[ pSoldier->ubAttackingHand ], gAnimControl[ pSoldier->usAnimState ].ubEndHeight == ANIM_PRONE)*pSoldier->bDoAutofire <= 80 );
}
while( pSoldier->bActionPoints >= BestShot.ubAPCost + ubBurstAPs &&
pSoldier->inv[ pSoldier->ubAttackingHand ][0]->data.gun.ubGunShotsLeft >= pSoldier->bDoAutofire &&
GetAutoPenalty(&pSoldier->inv[ pSoldier->ubAttackingHand ], gAnimControl[ pSoldier->usAnimState ].ubEndHeight == ANIM_PRONE)*pSoldier->bDoAutofire <= 80 );
pSoldier->bDoAutofire--;
@@ -2385,7 +2433,8 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier, UINT8 ubUnconsciousOK)
pSoldier->bDoBurst = 1;
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, New113Message[ MSG113_SUPPRESSIONFIRE ] );
Menptr[BestShot.ubOpponent].ubSuppressionPoints += pSoldier->bDoAutofire;
// HEADROCK HAM 4: This is the stupidest thing ever.
// Menptr[BestShot.ubOpponent].ubSuppressionPoints += pSoldier->bDoAutofire;
Menptr[BestShot.ubOpponent].ubSuppressorID = pSoldier->ubID;
return( AI_ACTION_FIRE_GUN );
}
@@ -2463,6 +2512,11 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier, UINT8 ubUnconsciousOK)
////////////////////////////////////////////////////////////////////////////
if ( ubCanMove && InLightAtNight( pSoldier->sGridNo, pSoldier->pathing.bLevel ) && pSoldier->aiData.bOrders != STATIONARY )
{
//ddd ÷òîáû óáåãàëè, êîãäà ïîäñâåòÿò ôàëüøâåéåðîì íî÷üþ
if(gGameExternalOptions.bNewTacticalAIBehavior)
pSoldier->aiData.bAction = AI_ACTION_LEAVE_WATER_GAS;
//ddd
pSoldier->aiData.usActionData = FindNearbyDarkerSpot( pSoldier );
if (!TileIsOutOfBounds(pSoldier->aiData.usActionData))
{
@@ -2687,12 +2741,12 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier, UINT8 ubUnconsciousOK)
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"decideactionred: stop flanking");
if (PythSpacesAway ( pSoldier->sGridNo, tempGridNo ) > MIN_FLANK_DIST_RED * 2 )
{
pSoldier->aiData.usActionData = InternalGoAsFarAsPossibleTowards(pSoldier,tempGridNo,APBPConstants[AP_PRONE],AI_ACTION_SEEK_OPPONENT,0);
pSoldier->aiData.usActionData = InternalGoAsFarAsPossibleTowards(pSoldier,tempGridNo,GetAPsProne( pSoldier, TRUE),AI_ACTION_SEEK_OPPONENT,0);
if ( LocationToLocationLineOfSightTest( pSoldier->aiData.usActionData, pSoldier->pathing.bLevel, tempGridNo, pSoldier->pathing.bLevel, TRUE) )
{
// reserve APs for a possible crouch plus a shot
pSoldier->aiData.usActionData = InternalGoAsFarAsPossibleTowards(pSoldier, tempGridNo, (INT8) (MinAPsToAttack( pSoldier, tempGridNo, ADDTURNCOST) + APBPConstants[AP_CROUCH]), AI_ACTION_SEEK_OPPONENT, FLAG_CAUTIOUS );
pSoldier->aiData.usActionData = InternalGoAsFarAsPossibleTowards(pSoldier, tempGridNo, (INT8) (MinAPsToAttack( pSoldier, tempGridNo, ADDTURNCOST) + GetAPsCrouch( pSoldier, TRUE)), AI_ACTION_SEEK_OPPONENT, FLAG_CAUTIOUS );
if (!TileIsOutOfBounds(pSoldier->aiData.usActionData))
{
@@ -2815,7 +2869,7 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier, UINT8 ubUnconsciousOK)
//////////////////////////////////////////////////////////////////////
// try to move towards him
pSoldier->aiData.usActionData = InternalGoAsFarAsPossibleTowards(pSoldier,sClosestDisturbance,APBPConstants[AP_CROUCH],AI_ACTION_SEEK_OPPONENT,0);
pSoldier->aiData.usActionData = InternalGoAsFarAsPossibleTowards(pSoldier,sClosestDisturbance,GetAPsCrouch( pSoldier, TRUE),AI_ACTION_SEEK_OPPONENT,0);
if (!TileIsOutOfBounds(pSoldier->aiData.usActionData))
{
@@ -2917,12 +2971,12 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier, UINT8 ubUnconsciousOK)
if (TileIsOutOfBounds(pSoldier->aiData.usActionData) || pSoldier->numFlanks >= MAX_FLANKS_RED )
{
pSoldier->aiData.usActionData = InternalGoAsFarAsPossibleTowards(pSoldier,sClosestDisturbance,APBPConstants[AP_CROUCH], AI_ACTION_SEEK_OPPONENT,0);
pSoldier->aiData.usActionData = InternalGoAsFarAsPossibleTowards(pSoldier,sClosestDisturbance,GetAPsCrouch( pSoldier, TRUE), AI_ACTION_SEEK_OPPONENT,0);
//pSoldier->numFlanks = 0;
if ( PythSpacesAway( pSoldier->aiData.usActionData, sClosestDisturbance ) < 5 || LocationToLocationLineOfSightTest( pSoldier->aiData.usActionData, pSoldier->pathing.bLevel, sClosestDisturbance, pSoldier->pathing.bLevel, TRUE ) )
{
// reserve APs for a possible crouch plus a shot
pSoldier->aiData.usActionData = InternalGoAsFarAsPossibleTowards(pSoldier, sClosestDisturbance, (INT8) (MinAPsToAttack( pSoldier, sClosestDisturbance, ADDTURNCOST) + APBPConstants[AP_CROUCH]), AI_ACTION_SEEK_OPPONENT, FLAG_CAUTIOUS );
pSoldier->aiData.usActionData = InternalGoAsFarAsPossibleTowards(pSoldier, sClosestDisturbance, (INT8) (MinAPsToAttack( pSoldier, sClosestDisturbance, ADDTURNCOST) + GetAPsCrouch( pSoldier, TRUE)), AI_ACTION_SEEK_OPPONENT, FLAG_CAUTIOUS );
if (!TileIsOutOfBounds(pSoldier->aiData.usActionData))
{
@@ -2960,7 +3014,7 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier, UINT8 ubUnconsciousOK)
if ( PythSpacesAway( pSoldier->aiData.usActionData, sClosestDisturbance ) < 5 || LocationToLocationLineOfSightTest( pSoldier->aiData.usActionData, pSoldier->pathing.bLevel, sClosestDisturbance, pSoldier->pathing.bLevel, TRUE ) )
{
// reserve APs for a possible crouch plus a shot
pSoldier->aiData.usActionData = InternalGoAsFarAsPossibleTowards(pSoldier, sClosestDisturbance, (INT8) (MinAPsToAttack( pSoldier, sClosestDisturbance, ADDTURNCOST) + APBPConstants[AP_CROUCH]), AI_ACTION_SEEK_OPPONENT, FLAG_CAUTIOUS );
pSoldier->aiData.usActionData = InternalGoAsFarAsPossibleTowards(pSoldier, sClosestDisturbance, (INT8) (MinAPsToAttack( pSoldier, sClosestDisturbance, ADDTURNCOST) + GetAPsCrouch( pSoldier, TRUE)), AI_ACTION_SEEK_OPPONENT, FLAG_CAUTIOUS );
if (!TileIsOutOfBounds(pSoldier->aiData.usActionData))
{
@@ -3058,7 +3112,7 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier, UINT8 ubUnconsciousOK)
//////////////////////////////////////////////////////////////////////
// GO DIRECTLY TOWARDS CLOSEST FRIEND UNDER FIRE OR WHO LAST RADIOED
//////////////////////////////////////////////////////////////////////
pSoldier->aiData.usActionData = InternalGoAsFarAsPossibleTowards(pSoldier,sClosestFriend,APBPConstants[AP_CROUCH], AI_ACTION_SEEK_OPPONENT,0);
pSoldier->aiData.usActionData = InternalGoAsFarAsPossibleTowards(pSoldier,sClosestFriend,GetAPsCrouch( pSoldier, TRUE), AI_ACTION_SEEK_OPPONENT,0);
if (!TileIsOutOfBounds(pSoldier->aiData.usActionData))
{
@@ -3148,7 +3202,7 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier, UINT8 ubUnconsciousOK)
{
// either moving significantly closer or into very close range
// ensure will we have enough APs for a possible crouch plus a shot
if ( InternalGoAsFarAsPossibleTowards( pSoldier, pSoldier->aiData.usActionData, (INT8) (MinAPsToAttack( pSoldier, sClosestOpponent, ADDTURNCOST) + APBPConstants[AP_CROUCH]), AI_ACTION_TAKE_COVER, 0 ) == pSoldier->aiData.usActionData )
if ( InternalGoAsFarAsPossibleTowards( pSoldier, pSoldier->aiData.usActionData, (INT8) (MinAPsToAttack( pSoldier, sClosestOpponent, ADDTURNCOST) + GetAPsCrouch( pSoldier, TRUE)), AI_ACTION_TAKE_COVER, 0 ) == pSoldier->aiData.usActionData )
{
return(AI_ACTION_TAKE_COVER);
}
@@ -3425,7 +3479,7 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier, UINT8 ubUnconsciousOK)
if ( pSoldier->bBleeding > MIN_BLEEDING_THRESHOLD )
{
// reduce bleeding by 1 point per AP (in RT, APs will get recalculated so it's okay)
pSoldier->bBleeding = __max( 0, pSoldier->bBleeding - pSoldier->bActionPoints );
pSoldier->bBleeding = __max( 0, pSoldier->bBleeding - (pSoldier->bActionPoints/2) );
return( AI_ACTION_NONE ); // will end-turn/wait depending on whether we're in TB or realtime
}
#ifdef RECORDNET
@@ -3936,7 +3990,9 @@ INT16 ubMinAPCost;
{
// look around for a worthy target (which sets BestShot.ubPossible)
BOOLEAN shootUnseen = FALSE;
if (gGameOptions.ubDifficultyLevel > DIF_LEVEL_MEDIUM )
///ddd
//if (gGameOptions.ubDifficultyLevel > DIF_LEVEL_MEDIUM ) //comm by ddd
if (gGameOptions.ubDifficultyLevel > DIF_LEVEL_MEDIUM || gGameExternalOptions.bNewTacticalAIBehavior)
shootUnseen = TRUE;
CalcBestShot(pSoldier,&BestShot,shootUnseen);
@@ -4125,6 +4181,107 @@ INT16 ubMinAPCost;
RearrangePocket(pSoldier,HANDPOS,bWeaponIn,TEMPORARILY);
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
// SANDRO - even if we don't have any blade, calculate how much damage we could do unarmed
else if ( !TANK( pSoldier) )
{
bWeaponIn = FindAIUsableObjClass( pSoldier, IC_PUNCH );
if (bWeaponIn == NO_SLOT) // if no punch-type weapon found, just calculate it with empty hands
{
bWeaponIn = FindEmptySlotWithin( pSoldier, HANDPOS, NUM_INV_SLOTS );
}
if (bWeaponIn != NO_SLOT)
{
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"try to punch");
BestStab.bWeaponIn = bWeaponIn;
// if it's in his holster, swap it into his hand temporarily
if (bWeaponIn != HANDPOS)
{
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"decideactionblack: about to rearrange pocket before punch check");
RearrangePocket(pSoldier,HANDPOS,bWeaponIn,TEMPORARILY);
}
// get the minimum cost to attack with punch
ubMinAPCost = MinAPsToAttack(pSoldier,pSoldier->sLastTarget,DONTADDTURNCOST);
// if we can afford the minimum AP cost to punch
if (pSoldier->bActionPoints >= ubMinAPCost)
{
// then look around for a worthy target (which sets BestStab.ubPossible)
CalcBestStab(pSoldier,&BestStab, FALSE);
if (BestStab.ubPossible)
{
// if we have not enough APs to deal at least two or three punches,
// reduce the attack value as one punch ain't much
if( gGameOptions.fNewTraitSystem )
{
// if we are not specialized, reduce the attack attractiveness generaly
if ( !HAS_SKILL_TRAIT( pSoldier, MARTIAL_ARTS_NT ) )
{
BestStab.iAttackValue /= 4;
// if too far and not having APs for at least 3 hits no way to attack
if (((CalcTotalAPsToAttack( pSoldier,BestStab.sTarget,ADDTURNCOST, 0 ) + (2 * (ApsToPunch( pSoldier )))) > pSoldier->bActionPoints) && !(PythSpacesAway(pSoldier->sGridNo, BestStab.sTarget) <= 1) )
{
BestStab.ubPossible = 0;
BestStab.iAttackValue = 0;
}
}
else
{
if (PythSpacesAway(pSoldier->sGridNo, BestStab.sTarget) <= 1)
{
BestStab.iAttackValue = (BestStab.iAttackValue * 2);
}
// if too far and not having APs for at least 2 hits
else if (((CalcTotalAPsToAttack( pSoldier,BestStab.sTarget,ADDTURNCOST, 0 ) + ApsToPunch( pSoldier )) > pSoldier->bActionPoints) && !(PythSpacesAway(pSoldier->sGridNo, BestStab.sTarget) <= 1))
{
BestStab.iAttackValue /= 3;
}
}
}
else
{
if ( !HAS_SKILL_TRAIT( pSoldier, MARTIALARTS_OT ) && !HAS_SKILL_TRAIT( pSoldier, HANDTOHAND_OT ) )
{
// if we are not specialized, reduce the attack attractiveness generaly
BestStab.iAttackValue /= 4;
// if too far and not having APs for at least 3 hits
if (((CalcTotalAPsToAttack( pSoldier,BestStab.sTarget,ADDTURNCOST, 0 ) + (2 * (ApsToPunch( pSoldier )))) > pSoldier->bActionPoints) && !(PythSpacesAway(pSoldier->sGridNo, BestStab.sTarget <= 1)) )
{
BestStab.ubPossible = 0;
BestStab.iAttackValue = 0;
}
}
else
{
BestStab.iAttackValue = ((BestStab.iAttackValue * 3)/2);
if (PythSpacesAway(pSoldier->sGridNo, BestStab.sTarget) <= 1)
{
BestStab.iAttackValue = ((BestStab.iAttackValue * 3)/2);
}
// if too far and not having APs for at least 2 hits
else if (((CalcTotalAPsToAttack( pSoldier,BestStab.sTarget,ADDTURNCOST, 0 ) + ApsToPunch( pSoldier )) > pSoldier->bActionPoints) && !(PythSpacesAway(pSoldier->sGridNo, BestStab.sTarget <= 1)) )
{
BestStab.iAttackValue /= 3;
}
}
}
// now we KNOW FOR SURE that we will do something (stab, at least)
NPCDoesAct(pSoldier);
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"NPC decided to punch");
}
}
// if it was in his holster, swap it back into his holster for now
if (bWeaponIn != HANDPOS)
{
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"about to rearrange pocket after punch check");
RearrangePocket(pSoldier,HANDPOS,bWeaponIn,TEMPORARILY);
}
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
// CHOOSE THE BEST TYPE OF ATTACK OUT OF THOSE FOUND TO BE POSSIBLE
@@ -4148,11 +4305,27 @@ INT16 ubMinAPCost;
ubBestAttackAction = AI_ACTION_THROW_KNIFE;
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"best action = throw knife");
}
else
else if ( Item[ pSoldier->inv[BestStab.bWeaponIn].usItem ].usItemClass & IC_BLADE ) // SANDRO - check specifically for blade attack
{
ubBestAttackAction = AI_ACTION_KNIFE_MOVE;
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"best action = move to stab");
}
////////////////////////////////////////////////////////////////////////////////////
// SANDRO - added a chance to try to steal merc's gun from hands
else
{
if (AIDetermineStealingWeaponAttempt( pSoldier, MercPtrs[BestStab.ubOpponent] ) == TRUE)
{
ubBestAttackAction = AI_ACTION_STEAL_MOVE;
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"best action = move to steal weapon");
}
else
{
ubBestAttackAction = AI_ACTION_KNIFE_MOVE;
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"best action = move to punch");
}
}
////////////////////////////////////////////////////////////////////////////////////
}
if (BestThrow.ubPossible && ((BestThrow.iAttackValue > BestAttack.iAttackValue) || (ubBestAttackAction == AI_ACTION_NONE)))
{
@@ -4223,6 +4396,10 @@ INT16 ubMinAPCost;
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"DecideActionBlack: best attack = stab with a knife");
memcpy(&BestAttack,&BestStab,sizeof(BestAttack));
break;
case AI_ACTION_STEAL_MOVE: // added by SANDRO
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"DecideActionBlack: best attack = try to steal weapon");
memcpy(&BestAttack,&BestStab,sizeof(BestAttack));
break;
default:
// set to empty
@@ -4233,12 +4410,14 @@ INT16 ubMinAPCost;
}
// NB a desire of 4 or more is only achievable by brave/aggressive guys with high morale
UINT16 usRange = GetModifiedGunRange(pSoldier->inv[ BestAttack.bWeaponIn ].usItem);
if ( (pSoldier->bActionPoints == pSoldier->bInitialActionPoints) &&
(ubBestAttackAction == AI_ACTION_FIRE_GUN) &&
(pSoldier->aiData.bShock == 0) &&
(pSoldier->stats.bLife >= pSoldier->stats.bLifeMax / 2) &&
(BestAttack.ubChanceToReallyHit < 30) &&
(PythSpacesAway( pSoldier->sGridNo, BestAttack.sTarget ) > Weapon[ pSoldier->inv[ BestAttack.bWeaponIn ].usItem ].usRange / CELL_X_SIZE ) &&
(PythSpacesAway( pSoldier->sGridNo, BestAttack.sTarget ) > usRange / CELL_X_SIZE ) &&
(RangeChangeDesire( pSoldier ) >= 4) )
{
// okay, really got to wonder about this... could taking cover be an option?
@@ -4383,7 +4562,7 @@ INT16 ubMinAPCost;
if (ubBestAttackAction == AI_ACTION_FIRE_GUN)
{
// Do we need to change stance? NB We'll have to ready our gun again
if ( !TANK( pSoldier ) && ( pSoldier->bActionPoints >= BestAttack.ubAPCost + APBPConstants[AP_CROUCH] + MinAPsToAttack( pSoldier, BestAttack.sTarget, ADDTURNCOST, 1 ) ) )
if ( !TANK( pSoldier ) && ( pSoldier->bActionPoints >= BestAttack.ubAPCost + GetAPsCrouch( pSoldier, TRUE) + MinAPsToAttack( pSoldier, BestAttack.sTarget, ADDTURNCOST, 1 ) ) )
{
// since the AI considers shooting chance from standing primarily, if we are not
// standing we should always consider a stance change
@@ -4484,13 +4663,13 @@ INT16 ubMinAPCost;
iChance = (25 / max((BestAttack.ubAimTime + 1),1));
switch (pSoldier->aiData.bAttitude)
{
case DEFENSIVE: iChance += -5; break;
case BRAVESOLO: iChance += 5; break;
case BRAVEAID: iChance += 5; break;
case CUNNINGSOLO: iChance += 0; break;
case CUNNINGAID: iChance += 0; break;
case AGGRESSIVE: iChance += 10; break;
case ATTACKSLAYONLY:iChance += 30; break;
case DEFENSIVE: iChance += -5; break;
case BRAVESOLO: iChance += 5; break;
case BRAVEAID: iChance += 5; break;
case CUNNINGSOLO: iChance += 0; break;
case CUNNINGAID: iChance += 0; break;
case AGGRESSIVE: iChance += 10; break;
case ATTACKSLAYONLY:iChance += 30; break;
}
// HEADROCK HAM B2.6: Allows control over increased enemy burstfire.
@@ -4510,10 +4689,10 @@ INT16 ubMinAPCost;
iChance += 5 * ( 15 - PythSpacesAway( pSoldier->sGridNo, BestAttack.sTarget ) );
}
}
// HEADROCK HAM 3.6: due to the "else", this part of the formula is NEVER hit. Removing.
//else if (PythSpacesAway( pSoldier->sGridNo, BestAttack.sTarget ) < 10 && gGameOptions.ubDifficultyLevel > DIF_LEVEL_EASY )
if (PythSpacesAway( pSoldier->sGridNo, BestAttack.sTarget ) < 10 && gGameOptions.ubDifficultyLevel > DIF_LEVEL_EASY )
{
iChance += 100;
}
@@ -4535,20 +4714,33 @@ INT16 ubMinAPCost;
if (IsGunAutofireCapable( &pSoldier->inv[BestAttack.bWeaponIn] ) &&
!(Menptr[BestShot.ubOpponent].stats.bLife < OKLIFE) && // don't burst at downed targets
(( pSoldier->inv[BestAttack.bWeaponIn][0]->data.gun.ubGunShotsLeft > 1 &&
BestAttack.ubAimTime != BURSTING ) || Weapon[pSoldier->inv[BestAttack.bWeaponIn].usItem].NoSemiAuto) )
!pSoldier->bDoBurst ) || Weapon[pSoldier->inv[BestAttack.bWeaponIn].usItem].NoSemiAuto) )
{
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"DecideActionBlack: ENOUGH APs TO AUTOFIRE, RANDOM CHANCE OF DOING SO");
FLOAT dTotalRecoil = 0.0f;
pSoldier->bDoAutofire = 0;
do
{
pSoldier->bDoAutofire++;
ubBurstAPs = CalcAPsToAutofire( pSoldier->CalcActionPoints(), &(pSoldier->inv[BestAttack.bWeaponIn]), pSoldier->bDoAutofire );
if(UsingNewCTHSystem() == true){
do
{
INT8 bRecoilX = 0;
INT8 bRecoilY = 0;
pSoldier->bDoAutofire++;
dTotalRecoil += AICalcRecoilForShot( pSoldier, &(pSoldier->inv[BestShot.bWeaponIn]), pSoldier->bDoAutofire );
ubBurstAPs = CalcAPsToAutofire( pSoldier->CalcActionPoints(), &(pSoldier->inv[BestShot.bWeaponIn]), pSoldier->bDoAutofire );
}
while( pSoldier->bActionPoints >= BestShot.ubAPCost + ubBurstAPs + sActualAimTime && pSoldier->inv[ pSoldier->ubAttackingHand ][0]->data.gun.ubGunShotsLeft >= pSoldier->bDoAutofire
&& dTotalRecoil <= 10.0f );
} else {
do
{
pSoldier->bDoAutofire++;
ubBurstAPs = CalcAPsToAutofire( pSoldier->CalcActionPoints(), &(pSoldier->inv[BestAttack.bWeaponIn]), pSoldier->bDoAutofire );
}
while( pSoldier->bActionPoints >= BestAttack.ubAPCost + ubBurstAPs &&
pSoldier->inv[ pSoldier->ubAttackingHand ][0]->data.gun.ubGunShotsLeft >= pSoldier->bDoAutofire &&
GetAutoPenalty(&pSoldier->inv[ BestAttack.bWeaponIn ], gAnimControl[ pSoldier->usAnimState ].ubEndHeight == ANIM_PRONE)*pSoldier->bDoAutofire <= 80);
}
while( pSoldier->bActionPoints >= BestAttack.ubAPCost + ubBurstAPs &&
pSoldier->inv[ pSoldier->ubAttackingHand ][0]->data.gun.ubGunShotsLeft >= pSoldier->bDoAutofire &&
GetAutoPenalty(&pSoldier->inv[ BestAttack.bWeaponIn ], gAnimControl[ pSoldier->usAnimState ].ubEndHeight == ANIM_PRONE)*pSoldier->bDoAutofire <= 80);
pSoldier->bDoAutofire--;
if (pSoldier->bDoAutofire > 0)
@@ -4606,20 +4798,24 @@ INT16 ubMinAPCost;
if ((INT32) PreRandom( 100 ) < iChance || Weapon[pSoldier->inv[BestAttack.bWeaponIn].usItem].NoSemiAuto)
{
BestAttack.ubAimTime = AUTOFIRING + pSoldier->bDoAutofire;
BestAttack.ubAPCost = BestAttack.ubAPCost + CalcAPsToAutofire( pSoldier->CalcActionPoints(), &(pSoldier->inv[BestAttack.bWeaponIn]), pSoldier->bDoAutofire );
pSoldier->aiData.bAimTime = BestAttack.ubAimTime ;
pSoldier->bDoBurst = 1;
BestAttack.ubAPCost = BestAttack.ubAPCost + CalcAPsToAutofire( pSoldier->CalcActionPoints(), &(pSoldier->inv[BestAttack.bWeaponIn]), pSoldier->bDoAutofire ) + sActualAimTime;
}
else
{
pSoldier->bDoAutofire = 0;
pSoldier->bDoBurst = 0;
}
}
}
else
{
// HEADROCK HAM 3.6: No no no! This line removes all aiming from a potentially deadly single-shot! Commenting out.
//pSoldier->aiData.bAimTime = 0;
pSoldier->aiData.bAimTime = BestAttack.ubAimTime;
pSoldier->bDoBurst = 0;
pSoldier->bDoAutofire = 0;
// not enough aps - do somthing else
}
}
if (!pSoldier->bDoBurst)
{
pSoldier->aiData.bAimTime = BestAttack.ubAimTime;
pSoldier->bDoBurst = 0;
pSoldier->bDoAutofire = 0;
}
//////////////////////////////////////////////////////////////////////////
@@ -4629,6 +4825,10 @@ INT16 ubMinAPCost;
// HEADROCK HAM 4: No longer necessary to do here. The conditions above already handle this, specifically
// WITHOUT messing with the BestAttack.ubAimTime variable, since that can apply now even when bursting
// or autofiring!!
/*
if (BestAttack.ubAimTime == BURSTING)
{
pSoldier->aiData.bAimTime = 0;
@@ -4642,7 +4842,7 @@ INT16 ubMinAPCost;
pSoldier->bDoAutofire = BestAttack.ubAimTime-AUTOFIRING;
BestAttack.ubAimTime = AUTOFIRING;
}
}*/
/*
else // defaults already set
@@ -4669,6 +4869,32 @@ INT16 ubMinAPCost;
}
}
// SANDRO - chance to make aimed punch/stab for martial arts/melee
else if (ubBestAttackAction == AI_ACTION_KNIFE_MOVE && gGameOptions.fNewTraitSystem)
{
pSoldier->aiData.bAimTime = 0;
if (Item[pSoldier->inv[BestAttack.bWeaponIn].usItem].usItemClass == IC_PUNCH)
{
if (HAS_SKILL_TRAIT( pSoldier, MARTIAL_ARTS_NT))
{
if( PreRandom( (gGameExternalOptions.fEnhancedCloseCombatSystem ? 2 : 0) + 2 * NUM_SKILL_TRAITS( pSoldier, MARTIAL_ARTS_NT) ) > 2 )
{
pSoldier->aiData.bAimTime = (gGameExternalOptions.fEnhancedCloseCombatSystem ? gSkillTraitValues.ubModifierForAPsAddedOnAimedPunches : 6);
}
}
}
else
{
if (HAS_SKILL_TRAIT( pSoldier, MELEE_NT))
{
if( PreRandom( gGameExternalOptions.fEnhancedCloseCombatSystem ? 3 : 1 ) > 0 )
{
pSoldier->aiData.bAimTime = (gGameExternalOptions.fEnhancedCloseCombatSystem ? gSkillTraitValues.ubModifierForAPsAddedOnAimedBladedAttackes : 6);
}
}
}
}
//////////////////////////////////////////////////////////////////////////
// OTHERWISE, JUST GO AHEAD & ATTACK!
@@ -4889,59 +5115,63 @@ INT16 ubMinAPCost;
// if not in water and not already crouched, try to crouch down first
if (!gfTurnBasedAI || GetAPsToChangeStance( pSoldier, ANIM_CROUCH ) <= pSoldier->bActionPoints)
{
if ( !fCivilian && !gfHiddenInterrupt && IsValidStance( pSoldier, ANIM_CROUCH ) )
if ( !fCivilian && !gfHiddenInterrupt && IsValidStance( pSoldier, ANIM_CROUCH ) && ubBestAttackAction != AI_ACTION_KNIFE_MOVE && ubBestAttackAction != AI_ACTION_KNIFE_STAB && ubBestAttackAction != AI_ACTION_STEAL_MOVE) // SANDRO - if knife attack don't crouch
{
pSoldier->aiData.usActionData = StanceChange( pSoldier, BestAttack.ubAPCost );
if (pSoldier->aiData.usActionData != 0)
// determine the location of the known closest opponent
// (don't care if he's conscious, don't care if he's reachable at all)
sClosestOpponent = ClosestSeenOpponent(pSoldier, NULL, NULL);
// SANDRO - don't crouch if in close combat distance (we got penalties that way)
if (PythSpacesAway(pSoldier->sGridNo, sClosestOpponent) > 1 )
{
if (pSoldier->aiData.usActionData == ANIM_PRONE)
pSoldier->aiData.usActionData = StanceChange( pSoldier, BestAttack.ubAPCost );
if (pSoldier->aiData.usActionData != 0)
{
// we might want to turn before lying down!
if ( (!gfTurnBasedAI || GetAPsToLook( pSoldier ) <= pSoldier->bActionPoints - GetAPsToChangeStance( pSoldier, (INT8) pSoldier->aiData.usActionData )) &&
(((pSoldier->aiData.bAIMorale > MORALE_HOPELESS) || ubCanMove) && !AimingGun(pSoldier)) )
if (pSoldier->aiData.usActionData == ANIM_PRONE)
{
// determine the location of the known closest opponent
// (don't care if he's conscious, don't care if he's reachable at all)
sClosestOpponent = ClosestSeenOpponent(pSoldier, NULL, NULL);
// if we have a closest seen opponent
if (!TileIsOutOfBounds(sClosestOpponent))
// we might want to turn before lying down!
if ( (!gfTurnBasedAI || GetAPsToLook( pSoldier ) <= pSoldier->bActionPoints - GetAPsToChangeStance( pSoldier, (INT8) pSoldier->aiData.usActionData )) &&
(((pSoldier->aiData.bAIMorale > MORALE_HOPELESS) || ubCanMove) && !AimingGun(pSoldier)) )
{
bDirection = atan8(CenterX(pSoldier->sGridNo),CenterY(pSoldier->sGridNo),CenterX(sClosestOpponent),CenterY(sClosestOpponent));
// if we're not facing towards him
if (pSoldier->ubDirection != bDirection)
// if we have a closest seen opponent
if (!TileIsOutOfBounds(sClosestOpponent))
{
if ( pSoldier->InternalIsValidStance( bDirection, (INT8) pSoldier->aiData.usActionData) )
bDirection = atan8(CenterX(pSoldier->sGridNo),CenterY(pSoldier->sGridNo),CenterX(sClosestOpponent),CenterY(sClosestOpponent));
// if we're not facing towards him
if (pSoldier->ubDirection != bDirection)
{
// change direction, THEN change stance!
pSoldier->aiData.bNextAction = AI_ACTION_CHANGE_STANCE;
pSoldier->aiData.usNextActionData = pSoldier->aiData.usActionData;
pSoldier->aiData.usActionData = bDirection;
if ( pSoldier->InternalIsValidStance( bDirection, (INT8) pSoldier->aiData.usActionData) )
{
// change direction, THEN change stance!
pSoldier->aiData.bNextAction = AI_ACTION_CHANGE_STANCE;
pSoldier->aiData.usNextActionData = pSoldier->aiData.usActionData;
pSoldier->aiData.usActionData = bDirection;
#ifdef DEBUGDECISIONS
sprintf(tempstr,"%s - TURNS to face CLOSEST OPPONENT in direction %d",pSoldier->name,pSoldier->aiData.usActionData);
AIPopMessage(tempstr);
sprintf(tempstr,"%s - TURNS to face CLOSEST OPPONENT in direction %d",pSoldier->name,pSoldier->aiData.usActionData);
AIPopMessage(tempstr);
#endif
return(AI_ACTION_CHANGE_FACING);
}
else if ( (pSoldier->aiData.usActionData == ANIM_PRONE) && (pSoldier->InternalIsValidStance( bDirection, ANIM_CROUCH) ) )
{
// we shouldn't go prone, since we can't turn to shoot
pSoldier->aiData.usActionData = ANIM_CROUCH;
pSoldier->aiData.bNextAction = AI_ACTION_END_TURN;
return( AI_ACTION_CHANGE_STANCE );
return(AI_ACTION_CHANGE_FACING);
}
else if ( (pSoldier->aiData.usActionData == ANIM_PRONE) && (pSoldier->InternalIsValidStance( bDirection, ANIM_CROUCH) ) )
{
// we shouldn't go prone, since we can't turn to shoot
pSoldier->aiData.usActionData = ANIM_CROUCH;
pSoldier->aiData.bNextAction = AI_ACTION_END_TURN;
return( AI_ACTION_CHANGE_STANCE );
}
}
// else we are facing in the right direction
}
// else we are facing in the right direction
// else we don't know any enemies
}
// else we don't know any enemies
}
// we don't want to turn
// we don't want to turn
}
pSoldier->aiData.bNextAction = AI_ACTION_END_TURN;
return( AI_ACTION_CHANGE_STANCE );
}
pSoldier->aiData.bNextAction = AI_ACTION_END_TURN;
return( AI_ACTION_CHANGE_STANCE );
}
}
}
+21 -10
View File
@@ -33,6 +33,12 @@
#include "PathAIDebug.h"
////////////////////////////////////////////////////////////////////////////////////////////////////////
// SANDRO - all "APBPConstants[AP_CROUCH]" and "APBPConstants[AP_PRONE]" here
// were changed to GetAPsCrouch() and GetAPsProne()
// - also all "APBPConstants[AP_PICKUP_ITEM]" were replaced by GetBasicAPsToPickupItem()
////////////////////////////////////////////////////////////////////////////////////////////////////////
INT16 * gsCoverValue = NULL;
#ifdef _DEBUG
@@ -128,13 +134,13 @@ INT8 CalcWorstCTGTForPosition( SOLDIERTYPE * pSoldier, UINT8 ubOppID, INT32 sOpp
switch (bCubeLevel)
{
case 1:
if (iMyAPsLeft < APBPConstants[AP_CROUCH] + APBPConstants[AP_PRONE])
if (iMyAPsLeft < GetAPsCrouch(pSoldier,TRUE) + GetAPsProne(pSoldier,TRUE))
{
continue;
}
break;
case 2:
if (iMyAPsLeft < APBPConstants[AP_CROUCH])
if (iMyAPsLeft < GetAPsCrouch(pSoldier,TRUE))
{
continue;
}
@@ -168,13 +174,13 @@ INT8 CalcAverageCTGTForPosition( SOLDIERTYPE * pSoldier, UINT8 ubOppID, INT32 sO
switch (bCubeLevel)
{
case 1:
if (iMyAPsLeft < APBPConstants[AP_CROUCH] + APBPConstants[AP_PRONE])
if (iMyAPsLeft < GetAPsCrouch(pSoldier,TRUE) + GetAPsProne(pSoldier,TRUE))
{
continue;
}
break;
case 2:
if (iMyAPsLeft < APBPConstants[AP_CROUCH])
if (iMyAPsLeft < GetAPsCrouch(pSoldier,TRUE))
{
continue;
}
@@ -430,7 +436,7 @@ INT32 CalcCoverValue(SOLDIERTYPE *pMe, INT32 sMyGridNo, INT32 iMyThreat, INT32 i
{
// if I CAN'T crouch when I get there, that makes it significantly less
// appealing a spot (how much depends on range), so that's a penalty to me
if (iMyAPsLeft < APBPConstants[AP_CROUCH])
if (iMyAPsLeft < GetAPsCrouch(pMe,TRUE))
// subtract another 1 % penalty for NOT being able to crouch per tile
// the farther away we are, the bigger a difference crouching will make!
iMyPosValue -= ((iMyPosValue * (AIM_PENALTY_TARGET_CROUCHED + (iRange / CELL_X_SIZE))) / 100);
@@ -1662,7 +1668,7 @@ INT8 SearchForItems( SOLDIERTYPE * pSoldier, INT8 bReason, UINT16 usItem )
return AI_ACTION_NONE;
}
if (pSoldier->bActionPoints < APBPConstants[AP_PICKUP_ITEM])
if (pSoldier->bActionPoints < GetBasicAPsToPickupItem( pSoldier ))
{
return( AI_ACTION_NONE );
}
@@ -1719,7 +1725,7 @@ INT8 SearchForItems( SOLDIERTYPE * pSoldier, INT8 bReason, UINT16 usItem )
// set an AP limit too, to our APs less the cost of picking up an item
// and less the cost of dropping an item since we might need to do that
gubNPCAPBudget = pSoldier->bActionPoints - APBPConstants[AP_PICKUP_ITEM];
gubNPCAPBudget = pSoldier->bActionPoints - GetBasicAPsToPickupItem( pSoldier );
// reset the "reachable" flags in the region we're looking at
for (sYOffset = -sMaxUp; sYOffset <= sMaxDown; sYOffset++)
@@ -1922,7 +1928,12 @@ INT8 SearchForItems( SOLDIERTYPE * pSoldier, INT8 bReason, UINT16 usItem )
// WANNE: Fix a vanilla bug: When an enemy soldier is looking for items and finds a non-helmet/vest/leggings piece of armour it was incorrectly considered for pickup.
// Fixed by Tron (Stracciatella): Revision: 5719
// break;
continue;
// continue; <- silversurfer: bad idea, this causes the game to hang
// to make sure that the item isn't considered set iTempValue to zero and get out
{
iTempValue = 0;
break;
}
}
}
else
@@ -1959,7 +1970,7 @@ INT8 SearchForItems( SOLDIERTYPE * pSoldier, INT8 bReason, UINT16 usItem )
//if (pSoldier->inv[HANDPOS].exists() == true && PlaceInAnyPocket(pSoldier, &pSoldier->inv[HANDPOS], false) == false)
if (FindBetterSpotForItem( pSoldier, HANDPOS ) == FALSE)
{
if (pSoldier->bActionPoints < APBPConstants[AP_PICKUP_ITEM] + APBPConstants[AP_PICKUP_ITEM])
if (pSoldier->bActionPoints < GetBasicAPsToPickupItem( pSoldier ) + GetBasicAPsToPickupItem( pSoldier ))
{
return( AI_ACTION_NONE );
}
@@ -1968,7 +1979,7 @@ INT8 SearchForItems( SOLDIERTYPE * pSoldier, INT8 bReason, UINT16 usItem )
// destroy this item!
DebugAI( String( "%d decides he must drop %S first so destroys it", pSoldier->ubID, ItemNames[ pSoldier->inv[HANDPOS].usItem ] ) );
DeleteObj( &(pSoldier->inv[HANDPOS]) );
DeductPoints( pSoldier, APBPConstants[AP_PICKUP_ITEM], 0 );
DeductPoints( pSoldier, GetBasicAPsToPickupItem( pSoldier ), 0 );
}
else
{
+47
View File
@@ -15,6 +15,9 @@
#include "Buildings.h"
#include "worldman.h"
#include "Assignments.h"
// added by SANDRO
#include "Soldier Profile.h"
#include "GameSettings.h"
#endif
//forward declarations of common classes to eliminate includes
@@ -465,3 +468,47 @@ INT8 DecideAutoBandage( SOLDIERTYPE * pSoldier )
// do nothing
return( AI_ACTION_NONE );
}
// SANDRO - added a function
BOOLEAN DoctorIsPresent( SOLDIERTYPE * pPatient, BOOLEAN fOnDoctorAssignmentCheck )
{
SOLDIERTYPE * pMedic = NULL;
UINT8 cnt;
INT8 bSlot;
BOOLEAN fDoctorHasBeenFound = FALSE;
cnt = gTacticalStatus.Team[ OUR_TEAM ].bFirstID;
for ( pMedic = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ OUR_TEAM ].bLastID; cnt++,pMedic++)
{
if ( !(pMedic->bActive) || !(pMedic->bInSector) || ( pMedic->flags.uiStatusFlags & SOLDIER_VEHICLE ) || (pMedic->bAssignment == VEHICLE ) )
{
// is nowhere around!
continue; // NEXT!!!
}
if ( pPatient->ubID == pMedic->ubID )
{
// cannot make surgery on self!
continue; // NEXT!!!
}
if ( fOnDoctorAssignmentCheck && pMedic->bAssignment != DOCTOR )
{
// not on the right assignment!
continue; // NEXT!!!
}
bSlot = FindMedKit( pMedic );
if (bSlot == NO_SLOT)
{
// no medical kit!
continue; // NEXT!!!
}
if (pMedic->stats.bLife > OKLIFE && !(pMedic->bCollapsed) && pMedic->stats.bMedical > 0 && (NUM_SKILL_TRAITS( pMedic, DOCTOR_NT ) >= gSkillTraitValues.ubDONumberTraitsNeededForSurgery))
{
fDoctorHasBeenFound = TRUE;
}
}
return( fDoctorHasBeenFound );
}
+2 -2
View File
@@ -7,7 +7,7 @@
#include "overhead.h"
#include "worldman.h"
#include "pathai.h"
#include "points.h"
//#include "points.h"
#include "message.h"
#include "Smell.h"
#include "mapscreen.h"
@@ -720,7 +720,7 @@ INT32 InternalGoAsFarAsPossibleTowards(SOLDIERTYPE *pSoldier, INT32 sDesGrid, IN
if (pSoldier->usUIMovementMode == RUNNING)
{
sAPCost += APBPConstants[AP_START_RUN_COST];
sAPCost += GetAPsStartRun( pSoldier ); // changed by SANDRO
}
}
+160 -24
View File
@@ -47,15 +47,21 @@
#include "Scheduling.h"
#include "Tactical Save.h"
#include "Campaign Types.h"
#include "GameSettings.h" // added by SANDRO
#include "Soldier Profile.h"
#endif
#include "Soldier Profile.h"
//forward declarations of common classes to eliminate includes
class OBJECTTYPE;
class SOLDIERTYPE;
// WANNE - BMP: DONE!
//SB: new .npc format
#define NPCEX_SIGNATURE 0x00070000
#define _MAKEFOURCC(ch0, ch1, ch2, ch3) \
((UINT32)(UINT8)(ch0) | ((UINT32)(UINT8)(ch1) << 8) | \
((UINT32)(UINT8)(ch2) << 16) | ((UINT32)(UINT8)(ch3) << 24 ))
#define NPCEX_SIGNATURE _MAKEFOURCC('B','1','1','3')
#define NUM_CIVQUOTE_SECTORS 20
#define MINERS_CIV_QUOTE_INDEX 16
@@ -143,7 +149,9 @@ NPCQuoteInfo * LoadQuoteFile( UINT8 ubNPC )
// use a copy of Herve's data file instead!
sprintf( zFileName, "NPCData\\%03d.npc", HERVE );
}
else if ( ubNPC < FIRST_RPC || ubNPC >= GASTON || (ubNPC < FIRST_NPC && gMercProfiles[ ubNPC ].ubMiscFlags & PROFILE_MISC_FLAG_RECRUITED ) )
//else if ( ubNPC < FIRST_RPC || ubNPC >= GASTON || (ubNPC < FIRST_NPC && gMercProfiles[ ubNPC ].ubMiscFlags & PROFILE_MISC_FLAG_RECRUITED ) )
//new profiles by Jazz
else if ( gProfilesIMP[ubNPC].ProfilId == ubNPC || gProfilesAIM[ubNPC].ProfilId == ubNPC || gProfilesMERC[ubNPC].ProfilId == ubNPC || ( gProfilesRPC[ubNPC].ProfilId == ubNPC && gMercProfiles[ ubNPC ].ubMiscFlags & PROFILE_MISC_FLAG_RECRUITED ) )
{
sprintf( zFileName, "NPCData\\000.npc", ubNPC );
}
@@ -257,7 +265,7 @@ NPCQuoteInfo& NPCQuoteInfo::operator=(const _old_NPCQuoteInfo& src)
ubLastDay = src.ubLastDay;
ubApproachRequired = src.ubApproachRequired;
ubOpinionRequired = src.ubOpinionRequired;
ubUnused = 0;
usUnused = 0;
ubQuoteNum = src.ubQuoteNum;
ubNumQuotes = src.ubNumQuotes;
ubStartQuest = src.ubStartQuest;
@@ -305,7 +313,9 @@ BOOLEAN EnsureQuoteFileLoaded( UINT8 ubNPC )
fLoadFile = TRUE;
}
if ( ubNPC >= FIRST_RPC && ubNPC < FIRST_NPC )
// if ( ubNPC >= FIRST_RPC && ubNPC < FIRST_NPC )
//new profiles by Jazz
if ( ( gProfilesRPC[ubNPC].ProfilId == ubNPC ) )
{
if (gMercProfiles[ ubNPC ].ubMiscFlags & PROFILE_MISC_FLAG_RECRUITED)
{
@@ -415,20 +425,31 @@ BOOLEAN RefreshNPCScriptRecord( UINT8 ubNPC, UINT8 ubRecord )
{
// we have some work to do...
// loop through all PCs, and refresh their copy of this record
for ( ubLoop = 0; ubLoop < FIRST_RPC; ubLoop++ ) // need more finesse here
//for ( ubLoop = 0; ubLoop < FIRST_RPC; ubLoop++ ) // need more finesse here
//new profiles by Jazz
for ( ubLoop = 0; ubLoop < NUM_PROFILES; ubLoop++ ) // need more finesse here
{
//new profiles by Jazz
if ( gProfilesIMP[ubLoop].ProfilId == ubLoop || gProfilesAIM[ubLoop].ProfilId == ubLoop || gProfilesMERC[ubLoop].ProfilId == ubLoop )
RefreshNPCScriptRecord( ubLoop, ubRecord );
}
for ( ubLoop = GASTON; ubLoop < NUM_PROFILES; ubLoop++ ) // need more finesse here
{
RefreshNPCScriptRecord( ubLoop, ubRecord );
}
for ( ubLoop = FIRST_RPC; ubLoop < FIRST_NPC; ubLoop++ )
//for ( ubLoop = GASTON; ubLoop < NUM_PROFILES; ubLoop++ ) // need more finesse here
//{
// RefreshNPCScriptRecord( ubLoop, ubRecord );
//}
//new profiles by Jazz
//for ( ubLoop = FIRST_RPC; ubLoop < FIRST_NPC; ubLoop++ )
for ( ubLoop = 0; ubLoop < NUM_PROFILES; ubLoop++ )
{
if ( gProfilesRPC[ubLoop].ProfilId == ubLoop )
{
if ( gMercProfiles[ ubNPC ].ubMiscFlags & PROFILE_MISC_FLAG_RECRUITED && gpBackupNPCQuoteInfoArray[ ubNPC ] != NULL )
{
RefreshNPCScriptRecord( ubLoop, ubRecord );
}
}
}
return( TRUE );
}
@@ -462,21 +483,87 @@ NPCQuoteInfo * LoadCivQuoteFile( UINT8 ubIndex )
NPCQuoteInfo * pFileData;
UINT32 uiBytesRead;
UINT32 uiFileSize;
DWORD uiSignature = 0; // SB // WANNE - BMP: DONE!
if ( ubIndex == MINERS_CIV_QUOTE_INDEX )
{
sprintf( zFileName, "NPCData\\miners.npc" );
}
else
{
sprintf( zFileName, "NPCData\\%c%d.npc", 'A' + ( gsCivQuoteSector[ ubIndex ][ 1 ] - 1 ), gsCivQuoteSector[ ubIndex ][ 0 ] );
}
if ( ubIndex == MINERS_CIV_QUOTE_INDEX )
{
sprintf( zFileName, "NPCData\\miners.npc" );
}
else
{
sprintf( zFileName, "NPCData\\%c%d.npc", 'A' + ( gsCivQuoteSector[ ubIndex ][ 1 ] - 1 ), gsCivQuoteSector[ ubIndex ][ 0 ] );
}
CHECKN( FileExists( zFileName ) );
hFile = FileOpen( zFileName, FILE_ACCESS_READ, FALSE );
CHECKN( hFile );
// -----------------------------------------------------------
// WANNE: This fixes the bug, that NPCs do not give hints
// Problem was, the missing conversion from old to new NPC structure!
if (!FileRead( hFile, &uiSignature, sizeof(uiSignature), &uiBytesRead ) || uiBytesRead != sizeof(uiSignature) )
return NULL;
if(uiSignature == NPCEX_SIGNATURE)//new fmt
{
uiFileSize = sizeof( NPCQuoteInfo ) * NUM_NPC_QUOTE_RECORDS;
pFileData = (NPCQuoteInfo *)MemAlloc( uiFileSize );
if (pFileData)
{
if (!FileRead( hFile, pFileData, uiFileSize, &uiBytesRead ) || uiBytesRead != uiFileSize )
{
MemFree( pFileData );
pFileData = NULL;
}
}
FileClose( hFile );
}
else //old fmt - make conversion
{
int iRecord;
_old_NPCQuoteInfo * pFileData_old_;
uiFileSize = sizeof( _old_NPCQuoteInfo ) * NUM_NPC_QUOTE_RECORDS;
pFileData_old_ = ( _old_NPCQuoteInfo * )MemAlloc( uiFileSize );
FileSeek(hFile, 0, FILE_SEEK_FROM_START);
if (pFileData_old_)
{
if (!FileRead( hFile, pFileData_old_, uiFileSize, &uiBytesRead ) || uiBytesRead != uiFileSize )
{
MemFree( pFileData_old_ );
pFileData_old_ = NULL;
}
}
FileClose( hFile );
//check for Russian script & make a runtime conversion of it to International
if( *(DWORD*)pFileData_old_ == 0x00350039 )
{
//just offset records 4 bytes backward
_old_NPCQuoteInfo * pEnglishScript = ( _old_NPCQuoteInfo * )MemAlloc( uiFileSize );
memcpy( pEnglishScript, ((char*)pFileData_old_)+4, uiFileSize-4 );
MemFree( pFileData_old_ );
pFileData_old_ = pEnglishScript;
}
// Now it's time for conversion
uiFileSize = sizeof(NPCQuoteInfo) * NUM_NPC_QUOTE_RECORDS;
pFileData = (NPCQuoteInfo*)MemAlloc(uiFileSize);
for(iRecord=0; iRecord<NUM_NPC_QUOTE_RECORDS; iRecord++)
pFileData[iRecord] = pFileData_old_[iRecord];//dnl ch46 021009
MemFree(pFileData_old_);
}
// -----------------------------------------------------------
//
//</SB> new script format
return( pFileData );
// -----------------------------------------------------------
// WANNE: This is old vanilla JA2 code without conversion of NPC data to new format used for Big Maps project
/*
uiFileSize = sizeof( NPCQuoteInfo ) * NUM_NPC_QUOTE_RECORDS;
pFileData = (NPCQuoteInfo *)MemAlloc( uiFileSize );
if (pFileData)
@@ -491,6 +578,8 @@ NPCQuoteInfo * LoadCivQuoteFile( UINT8 ubIndex )
FileClose( hFile );
return( pFileData );
// -----------------------------------------------------------
*/
}
@@ -578,8 +667,12 @@ BOOLEAN ReloadAllQuoteFiles( void )
{
UINT8 ubProfile, ubLoop;
for ( ubProfile = FIRST_RPC; ubProfile < GASTON; ubProfile++ )
//for ( ubProfile = FIRST_RPC; ubProfile < GASTON; ubProfile++ )
//new profiles by Jazz
for ( ubProfile = 0; ubProfile < NUM_PROFILES; ubProfile++ )
{
if ( gProfilesRPC[ubProfile].ProfilId == ubProfile || gProfilesNPC[ubProfile].ProfilId == ubProfile )
{
// zap backup if any
if ( gpBackupNPCQuoteInfoArray[ ubProfile ] != NULL )
{
@@ -587,6 +680,7 @@ BOOLEAN ReloadAllQuoteFiles( void )
gpBackupNPCQuoteInfoArray[ ubProfile ] = NULL;
}
ReloadQuoteFileIfLoaded( ubProfile );
}
}
// reload all civ quote files
for ( ubLoop = 0; ubLoop < NUM_CIVQUOTE_SECTORS; ubLoop++ )
@@ -642,6 +736,12 @@ INT32 CalcThreateningEffectiveness( UINT8 ubMerc )
iDeadliness = -30;
}
// SANDRO - bonus for threatening for assertive people
if ( gGameOptions.fNewTraitSystem && gMercProfiles[pSoldier->ubProfile].bCharacterTrait == CHAR_TRAIT_ASSERTIVE )
{
iDeadliness += 50;
}
return( (EffectiveLeadership( pSoldier ) + iStrength + iDeadliness) / 3 ); //Trail minor bug fix.
}
@@ -661,6 +761,15 @@ UINT8 CalcDesireToTalk( UINT8 ubNPC, UINT8 ubMerc, INT8 bApproach )
iPersonalVal += pNPCProfile->bMercOpinion[ubMerc];
}
// SANDRO - bonus for communication with people for assertive people
if ( gGameOptions.fNewTraitSystem && bApproach != APPROACH_THREATEN)
{
if ( pMercProfile->bCharacterTrait == CHAR_TRAIT_ASSERTIVE )
iPersonalVal += 50;
else if ( pMercProfile->bCharacterTrait == CHAR_TRAIT_MALICIOUS )
iPersonalVal -= 50;
}
// ARM: NOTE - for towns which don't use loyalty (San Mona, Estoni, Tixa, Orta )
// loyalty will always remain 0 (this was OKed by Ian)
iTownVal = gTownLoyalty[ pNPCProfile->bTown ].ubRating;
@@ -1215,7 +1324,9 @@ UINT8 NPCConsiderReceivingItemFromMerc( UINT8 ubNPC, UINT8 ubMerc, OBJECTTYPE *
}
break;
default:
if ( usItemToConsider == MONEY && (ubNPC == SKYRIDER || (ubNPC >= FIRST_RPC && ubNPC < FIRST_NPC) ) )
//if ( usItemToConsider == MONEY && (ubNPC == SKYRIDER || (ubNPC >= FIRST_RPC && ubNPC < FIRST_NPC) ) )
//new profiles by Jazz
if ( usItemToConsider == MONEY && (ubNPC == SKYRIDER || ( gProfilesRPC[ubNPC].ProfilId == ubNPC ) ) )
{
if ( gMercProfiles[ ubNPC ].iBalance < 0 && pNPCQuoteInfo->sActionData != NPC_ACTION_DONT_ACCEPT_ITEM )
{
@@ -1603,14 +1714,23 @@ void ResetOncePerConvoRecordsForNPC( UINT8 ubNPC )
void ResetOncePerConvoRecordsForAllNPCsInLoadedSector( void )
{
UINT8 ubLoop;
UINT8 IDnpc;
if ( gWorldSectorX == 0 || gWorldSectorY == 0 )
{
return;
}
for ( ubLoop = FIRST_RPC; ubLoop < GASTON; ubLoop++ )
//for ( ubLoop = FIRST_RPC; ubLoop < GASTON; ubLoop++ )
//new profiles by Jazz
for ( IDnpc = 0; IDnpc < NUM_PROFILES; IDnpc++ )
{
if ( gProfilesRPC[IDnpc].ProfilId == IDnpc || gProfilesNPC[IDnpc].ProfilId == IDnpc)
{
ubLoop = IDnpc;
if ( gMercProfiles[ ubLoop ].sSectorX == gWorldSectorX &&
gMercProfiles[ ubLoop ].sSectorY == gWorldSectorY &&
gMercProfiles[ ubLoop ].bSectorZ == gbWorldSectorZ &&
@@ -1618,6 +1738,9 @@ void ResetOncePerConvoRecordsForAllNPCsInLoadedSector( void )
{
ResetOncePerConvoRecordsForNPC( ubLoop );
}
}
}
}
@@ -1695,7 +1818,15 @@ void Converse( UINT8 ubNPC, UINT8 ubMerc, INT8 bApproach, UINT32 uiApproachData
}
return;
}
pNPCQuoteInfoArray = gpNPCQuoteInfoArray[ubNPC];
//Legion jazz
if (zHiddenNames[ubNPC].Hidden == TRUE)
{
zHiddenNames[ubNPC].Hidden = FALSE;
}
pProfile = &(gMercProfiles[ubNPC]);
switch( bApproach )
@@ -1849,7 +1980,7 @@ void Converse( UINT8 ubNPC, UINT8 ubMerc, INT8 bApproach, UINT32 uiApproachData
break;
case TRIGGER_NPC:
// if triggering, pass in the approach data as the record to consider
DebugMsg( TOPIC_JA2, DBG_LEVEL_0, String( "Handling trigger %S/%d at %ld", gMercProfiles[ ubNPC ].zNickname, (UINT8)uiApproachData, GetJA2Clock() ) );
DebugMsg( TOPIC_JA2, DBG_LEVEL_0, String( "Handling trigger %S/%d at %lu", gMercProfiles[ ubNPC ].zNickname, (UINT8)uiApproachData, GetJA2Clock() ) );
NPCConsiderTalking( ubNPC, ubMerc, bApproach, (UINT8)uiApproachData, pNPCQuoteInfoArray, &pQuotePtr, &ubRecordNum );
break;
default:
@@ -2242,6 +2373,11 @@ void Converse( UINT8 ubNPC, UINT8 ubMerc, INT8 bApproach, UINT32 uiApproachData
case APPROACH_DECLARATION_OF_HOSTILITY:
case APPROACH_INITIAL_QUOTE:
case APPROACH_GIVINGITEM:
// SANDRO - new records - NPCs discovered
if ( pProfile->ubLastDateSpokenTo == 0 && FindSoldierByProfileID( ubMerc, TRUE ) != NULL )
{
gMercProfiles[ubMerc].records.usNPCsDiscovered++;
}
pProfile->ubLastDateSpokenTo = (UINT8) GetWorldDay();
break;
default:
+7 -3
View File
@@ -90,8 +90,6 @@ public:
// conditions
INT16 sRequiredItem; // item NPC must have to say quote
INT32 sRequiredGridNo; // location for NPC req'd to say quote
UINT16 usFactMustBeTrue; // ...before saying quote
UINT16 usFactMustBeFalse; // ...before saying quote
UINT8 ubQuest; // quest must be current to say quote
@@ -99,7 +97,6 @@ public:
UINT8 ubLastDay; // last day quote can be said
UINT8 ubApproachRequired; // must use this approach to generate quote
UINT8 ubOpinionRequired; // opinion needed for this quote
UINT8 ubUnused;
// quote to say (if any)
UINT8 ubQuoteNum; // this is the quote to say
@@ -110,10 +107,17 @@ public:
UINT8 ubEndQuest;
UINT8 ubTriggerNPC;
UINT8 ubTriggerNPCRec;
UINT8 ubFiller;
UINT16 usSetFactTrue;
UINT16 usGiftItem; // item NPC gives to merc after saying quote
UINT16 usUnused;
INT16 sActionData; // special action value
INT32 sRequiredGridNo; // location for NPC req'd to say quote
INT32 usGoToGridNo;
UINT16 usSourceDialogueLevel; // reserved for future use
UINT16 usDestDialogueLevel; // reserved for future use
public:
NPCQuoteInfo& operator=(const _old_NPCQuoteInfo& src);
};
+431
View File
@@ -0,0 +1,431 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8,00"
Name="TacticalAI"
ProjectGUID="{27A49DAF-3F5A-4FF2-B943-9559F0B63032}"
RootNamespace="TacticalAI"
Keyword="Win32Proj"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="..\lib\VS2005\$(ConfigurationName)"
IntermediateDirectory="..\build\VS2005\$(ProjectName)_$(ConfigurationName)"
ConfigurationType="4"
InheritedPropertySheets="..\ja2.vsprops;..\ja2_Debug.vsprops"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/D &quot;_CRT_SECURE_NO_DEPRECATE&quot;"
Optimization="0"
AdditionalIncludeDirectories=""
PreprocessorDefinitions="WIN32;_DEBUG;_LIB;"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
RuntimeTypeInfo="true"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="4"
DisableSpecificWarnings="4100"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="..\lib\VS2005\$(ConfigurationName)"
IntermediateDirectory="..\build\VS2005\$(ProjectName)_$(ConfigurationName)"
ConfigurationType="4"
InheritedPropertySheets="..\ja2.vsprops"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/D &quot;_CRT_SECURE_NO_DEPRECATE&quot;"
AdditionalIncludeDirectories=""
PreprocessorDefinitions="WIN32;NDEBUG;_LIB;"
RuntimeLibrary="0"
RuntimeTypeInfo="true"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="MapEditor|Win32"
OutputDirectory="..\lib\VS2005\$(ConfigurationName)"
IntermediateDirectory="..\build\VS2005\$(ProjectName)_$(ConfigurationName)"
ConfigurationType="4"
InheritedPropertySheets="..\ja2.vsprops;..\ja2_Editor.vsprops"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/D &quot;_CRT_SECURE_NO_DEPRECATE&quot;"
AdditionalIncludeDirectories=""
PreprocessorDefinitions="WIN32;NDEBUG;_LIB;"
RuntimeLibrary="0"
RuntimeTypeInfo="true"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="MapEditorD|Win32"
OutputDirectory="..\lib\VS2005\$(ConfigurationName)"
IntermediateDirectory="..\build\VS2005\$(ProjectName)_$(ConfigurationName)"
ConfigurationType="4"
InheritedPropertySheets="..\ja2.vsprops;..\ja2_Editor.vsprops"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/D &quot;_CRT_SECURE_NO_DEPRECATE&quot;"
Optimization="0"
AdditionalIncludeDirectories=""
PreprocessorDefinitions="WIN32;_DEBUG;_LIB;"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
RuntimeTypeInfo="true"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="4"
DisableSpecificWarnings="4100"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release_WithDebugInfo|Win32"
OutputDirectory="..\lib\VS2005\$(ConfigurationName)"
IntermediateDirectory="..\build\VS2005\$(ProjectName)_$(ConfigurationName)"
ConfigurationType="4"
InheritedPropertySheets="..\ja2.vsprops"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/D &quot;_CRT_SECURE_NO_DEPRECATE&quot;"
Optimization="0"
AdditionalIncludeDirectories=""
PreprocessorDefinitions="WIN32;NDEBUG;_LIB;"
RuntimeLibrary="0"
RuntimeTypeInfo="true"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath=".\AI All.h"
>
</File>
<File
RelativePath=".\ai.h"
>
</File>
<File
RelativePath=".\AIInternals.h"
>
</File>
<File
RelativePath=".\AIList.h"
>
</File>
<File
RelativePath=".\NPC.h"
>
</File>
<File
RelativePath=".\QuestDebug.h"
>
</File>
</Filter>
<Filter
Name="Source Files"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath=".\AIList.cpp"
>
</File>
<File
RelativePath=".\AIMain.cpp"
>
</File>
<File
RelativePath=".\AIUtils.cpp"
>
</File>
<File
RelativePath=".\Attacks.cpp"
>
</File>
<File
RelativePath=".\CreatureDecideAction.cpp"
>
</File>
<File
RelativePath=".\DecideAction.cpp"
>
</File>
<File
RelativePath=".\FindLocations.cpp"
>
</File>
<File
RelativePath=".\Knowledge.cpp"
>
</File>
<File
RelativePath=".\Medical.cpp"
>
</File>
<File
RelativePath=".\Movement.cpp"
>
</File>
<File
RelativePath=".\NPC.cpp"
>
</File>
<File
RelativePath=".\PanicButtons.cpp"
>
</File>
<File
RelativePath=".\QuestDebug.cpp"
>
</File>
<File
RelativePath=".\Realtime.cpp"
>
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>
+5 -5
View File
@@ -21,7 +21,7 @@
OutputDirectory="..\lib\VS2008\$(ConfigurationName)"
IntermediateDirectory="..\build\VS2008\$(ProjectName)_$(ConfigurationName)"
ConfigurationType="4"
InheritedPropertySheets="..\ja2_VS2008.vsprops;..\ja2_VS2008Debug.vsprops"
InheritedPropertySheets="..\ja2.vsprops;..\ja2_Debug.vsprops"
CharacterSet="0"
>
<Tool
@@ -83,7 +83,7 @@
OutputDirectory="..\lib\VS2008\$(ConfigurationName)"
IntermediateDirectory="..\build\VS2008\$(ProjectName)_$(ConfigurationName)"
ConfigurationType="4"
InheritedPropertySheets="..\ja2_VS2008.vsprops"
InheritedPropertySheets="..\ja2.vsprops"
CharacterSet="0"
WholeProgramOptimization="0"
>
@@ -147,7 +147,7 @@
OutputDirectory="..\lib\VS2008\$(ConfigurationName)"
IntermediateDirectory="..\build\VS2008\$(ProjectName)_$(ConfigurationName)"
ConfigurationType="4"
InheritedPropertySheets="..\ja2_VS2008.vsprops;..\ja2_VS2008Editor.vsprops"
InheritedPropertySheets="..\ja2.vsprops;..\ja2_Editor.vsprops"
CharacterSet="0"
WholeProgramOptimization="0"
>
@@ -211,7 +211,7 @@
OutputDirectory="..\lib\VS2008\$(ConfigurationName)"
IntermediateDirectory="..\build\VS2008\$(ProjectName)_$(ConfigurationName)"
ConfigurationType="4"
InheritedPropertySheets="..\ja2_VS2008.vsprops;..\ja2_VS2008Editor.vsprops"
InheritedPropertySheets="..\ja2.vsprops;..\ja2_Editor.vsprops"
CharacterSet="0"
>
<Tool
@@ -273,7 +273,7 @@
OutputDirectory="..\lib\VS2008\$(ConfigurationName)"
IntermediateDirectory="..\build\VS2008\$(ProjectName)_$(ConfigurationName)"
ConfigurationType="4"
InheritedPropertySheets="..\ja2_VS2008.vsprops"
InheritedPropertySheets="..\ja2.vsprops"
CharacterSet="0"
WholeProgramOptimization="0"
>
+233
View File
@@ -0,0 +1,233 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="MapEditorD|Win32">
<Configuration>MapEditorD</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="MapEditor|Win32">
<Configuration>MapEditor</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Relese_WithDebugInfo|Win32">
<Configuration>Relese_WithDebugInfo</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClInclude Include="AI All.h" />
<ClInclude Include="ai.h" />
<ClInclude Include="AIInternals.h" />
<ClInclude Include="AIList.h" />
<ClInclude Include="NPC.h" />
<ClInclude Include="QuestDebug.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="AIList.cpp" />
<ClCompile Include="AIMain.cpp" />
<ClCompile Include="AIUtils.cpp" />
<ClCompile Include="Attacks.cpp" />
<ClCompile Include="CreatureDecideAction.cpp" />
<ClCompile Include="DecideAction.cpp" />
<ClCompile Include="FindLocations.cpp" />
<ClCompile Include="Knowledge.cpp" />
<ClCompile Include="Medical.cpp" />
<ClCompile Include="Movement.cpp" />
<ClCompile Include="NPC.cpp" />
<ClCompile Include="PanicButtons.cpp" />
<ClCompile Include="QuestDebug.cpp" />
<ClCompile Include="Realtime.cpp" />
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{B369A125-E62E-46AE-9285-58003D688301}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>TacticalAI</RootNamespace>
<ProjectName>TacticalAI</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>NotSet</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='MapEditorD|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>NotSet</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>false</WholeProgramOptimization>
<CharacterSet>NotSet</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='MapEditor|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>false</WholeProgramOptimization>
<CharacterSet>NotSet</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Relese_WithDebugInfo|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>false</WholeProgramOptimization>
<CharacterSet>NotSet</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\ja2.props" />
<Import Project="..\ja2_Debug.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='MapEditorD|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\ja2.props" />
<Import Project="..\ja2_Debug.props" />
<Import Project="..\ja2_Editor.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\ja2.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='MapEditor|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\ja2.props" />
<Import Project="..\ja2_Editor.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Relese_WithDebugInfo|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\ja2.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<OutDir>..\lib\VS2010\$(Configuration)\</OutDir>
<IntDir>..\build\VS2010\$(ProjectName)_$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='MapEditorD|Win32'">
<OutDir>..\lib\VS2010\$(Configuration)\</OutDir>
<IntDir>..\build\VS2010\$(ProjectName)_$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<IntDir>..\build\VS2010\$(ProjectName)_$(Configuration)\</IntDir>
<OutDir>..\lib\VS2010\$(Configuration)\</OutDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='MapEditor|Win32'">
<IntDir>..\build\VS2010\$(ProjectName)_$(Configuration)\</IntDir>
<OutDir>..\lib\VS2010\$(Configuration)\</OutDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Relese_WithDebugInfo|Win32'">
<IntDir>..\build\VS2010\$(ProjectName)_$(Configuration)\</IntDir>
<OutDir>..\lib\VS2010\$(Configuration)\</OutDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<PrecompiledHeaderFile>
</PrecompiledHeaderFile>
<PrecompiledHeaderOutputFile>
</PrecompiledHeaderOutputFile>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='MapEditorD|Win32'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<PrecompiledHeaderFile>
</PrecompiledHeaderFile>
<PrecompiledHeaderOutputFile>
</PrecompiledHeaderOutputFile>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeaderFile>
</PrecompiledHeaderFile>
<PrecompiledHeaderOutputFile>
</PrecompiledHeaderOutputFile>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='MapEditor|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeaderFile>
</PrecompiledHeaderFile>
<PrecompiledHeaderOutputFile>
</PrecompiledHeaderOutputFile>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Relese_WithDebugInfo|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<Optimization>Disabled</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeaderFile>
</PrecompiledHeaderFile>
<PrecompiledHeaderOutputFile>
</PrecompiledHeaderOutputFile>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
@@ -0,0 +1,75 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Header Files">
<UniqueIdentifier>{2552d0a1-b3ed-43af-a06c-d0737ce6a63f}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files">
<UniqueIdentifier>{0f98d0d9-dbab-4dc2-8aa6-ee517a6ceab6}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="AI All.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ai.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="AIInternals.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="AIList.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="NPC.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="QuestDebug.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="AIList.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="AIMain.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="AIUtils.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Attacks.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="CreatureDecideAction.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="DecideAction.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="FindLocations.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Knowledge.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Medical.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Movement.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="NPC.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="PanicButtons.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="QuestDebug.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Realtime.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>
+1
View File
@@ -97,6 +97,7 @@ typedef enum
AI_ACTION_TRAVERSE_DOWN, // move down a level
AI_ACTION_OFFER_SURRENDER, // offer surrender to the player
AI_ACTION_RAISE_GUN,
AI_ACTION_STEAL_MOVE, // added by SANDRO
} ActionType;