New feature: bloodcat/zombie/bandit raids on player-controlled sectors

For more info, see http://thepit.ja-galaxy-forum.com/index.php?t=msg&th=23711&goto=353154&#msg_353154

Requires GameDir >= r2420

git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@8554 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
Flugente
2018-04-15 14:42:01 +00:00
parent 1ea69989ed
commit 80674249cc
52 changed files with 1628 additions and 479 deletions
+6
View File
@@ -316,6 +316,11 @@ INT8 GetCivType( SOLDIERTYPE *pCiv )
return( CIV_TYPE_ENEMY );
}
if ( pCiv->bTeam == CREATURE_TEAM && pCiv->ubSoldierClass == SOLDIER_CLASS_BANDIT )
{
return( CIV_TYPE_ENEMY );
}
if ( pCiv->bTeam != CIV_TEAM && pCiv->bTeam != MILITIA_TEAM )
{
return( CIV_TYPE_NA );
@@ -1627,6 +1632,7 @@ void StartEnemyTaunt( SOLDIERTYPE *pCiv, TAUNTTYPE iTauntType, SOLDIERTYPE *pTar
switch( pCiv->ubSoldierClass )
{
case SOLDIER_CLASS_ADMINISTRATOR:
case SOLDIER_CLASS_BANDIT:
if( !(zTaunt[ i ].uiFlags2 & TAUNT_C_ADMIN) )
continue;
if( (zTaunt[ i ].value[TAUNT_PROFILE_ADMIN] != -1 ) && !(zTaunt[ i ].value[TAUNT_PROFILE_ADMIN] == pCiv->usSoldierProfile ) )
+5 -4
View File
@@ -333,10 +333,11 @@ void GenerateRandomEquipment( SOLDIERCREATE_STRUCT *pp, INT8 bSoldierClass, INT8
// handled differently than for enemies.
case SOLDIER_CLASS_ADMINISTRATOR:
case SOLDIER_CLASS_GREEN_MILITIA:
case SOLDIER_CLASS_BANDIT:
bRating = BAD_ADMINISTRATOR_EQUIPMENT_RATING + bEquipmentModifier;
// Equipment quality modifier
if ( bSoldierClass == SOLDIER_CLASS_ADMINISTRATOR )
if ( bSoldierClass == SOLDIER_CLASS_ADMINISTRATOR || bSoldierClass == SOLDIER_CLASS_BANDIT )
{
if ( gGameExternalOptions.sEnemyAdminEquipmentQualityModifier != 0 )
bRating += gGameExternalOptions.sEnemyAdminEquipmentQualityModifier;
@@ -360,7 +361,7 @@ void GenerateRandomEquipment( SOLDIERCREATE_STRUCT *pp, INT8 bSoldierClass, INT8
bHelmetClass = bRating;
// no leggings
if ( bSoldierClass == SOLDIER_CLASS_ADMINISTRATOR )
if ( bSoldierClass == SOLDIER_CLASS_ADMINISTRATOR || bSoldierClass == SOLDIER_CLASS_BANDIT )
{
if ( Chance( 30 ) )
bKnifeClass = bRating;
@@ -919,6 +920,7 @@ void ChooseWeaponForSoldierCreateStruct( SOLDIERCREATE_STRUCT *pp, INT8 bWeaponC
case SOLDIER_CLASS_ARMY:
case SOLDIER_CLASS_GREEN_MILITIA:
case SOLDIER_CLASS_REG_MILITIA:
case SOLDIER_CLASS_BANDIT:
//Admins/Troops: 60-75% + 1% every 4% progress
bStatus = (INT8)(60 + Random( 16 ));
bStatus += (INT8)(HighestPlayerProgressPercentage() / 4);
@@ -1987,13 +1989,12 @@ void ChooseFaceGearForSoldierCreateStruct( SOLDIERCREATE_STRUCT *pp )
case SOLDIER_CLASS_ADMINISTRATOR:
case SOLDIER_CLASS_GREEN_MILITIA:
case SOLDIER_CLASS_ZOMBIE:
case SOLDIER_CLASS_BANDIT:
break;
}
}
void ChooseKitsForSoldierCreateStruct( SOLDIERCREATE_STRUCT *pp, INT8 bKitClass )
{
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"ChooseKitsForSoldierCreateStruct");
+6
View File
@@ -494,6 +494,10 @@ OBJECTTYPE* GetExternalFeedingObject(SOLDIERTYPE* pSoldier, OBJECTTYPE * pObject
BOOLEAN DeductBulletViaExternalFeeding(SOLDIERTYPE* pSoldier, OBJECTTYPE * pObject);
#define SECTORFLAG_RAIDPOSSIBLE_BLOODCAT 0x00000001 // bloodcats can attack this sector
#define SECTORFLAG_RAIDPOSSIBLE_ZOMBIE 0x00000002 // zombies can attack this sector
#define SECTORFLAG_RAIDPOSSIBLE_BANDIT 0x00000004 // bandits can attack this sector
// Flugente: additional xml data for sectors
typedef struct
{
@@ -515,6 +519,8 @@ typedef struct
UINT8 maxworkers; // maximum number of workers in this sector;
UINT32 usSectorFlagMask; // various flags
} SECTOR_EXT_DATA;
// get dirt increase for object with attachments, fConsiderAmmo: with ammo
+28 -34
View File
@@ -6856,7 +6856,8 @@ void RemoveCapturedEnemiesFromSectorInfo( INT16 sMapX, INT16 sMapY, INT8 bMapZ )
{
switch ( pTeamSoldier->ubSoldierClass )
{
case SOLDIER_CLASS_ADMINISTRATOR: ++sNumPrisoner[PRISONER_ADMIN]; break;
case SOLDIER_CLASS_ADMINISTRATOR:
case SOLDIER_CLASS_BANDIT: ++sNumPrisoner[PRISONER_ADMIN]; break;
case SOLDIER_CLASS_ARMY: ++sNumPrisoner[PRISONER_REGULAR]; break;
case SOLDIER_CLASS_ELITE: ++sNumPrisoner[PRISONER_ELITE]; break;
default:
@@ -6865,7 +6866,11 @@ void RemoveCapturedEnemiesFromSectorInfo( INT16 sMapX, INT16 sMapY, INT8 bMapZ )
break;
}
}
else //if ( pTeamSoldier->bTeam == CIV_TEAM )
else if ( pTeamSoldier->bTeam == CREATURE_TEAM && pTeamSoldier->ubSoldierClass == SOLDIER_CLASS_BANDIT )
{
++sNumPrisoner[PRISONER_ADMIN];
}
else
{
++sNumPrisoner[PRISONER_CIVILIAN];
}
@@ -10508,9 +10513,9 @@ void PrisonerSurrenderMessageBoxCallBack( UINT8 ubExitValue )
// We justify this storywise by these soldiers being very determined leaders who don't allow surrender categorically.
BOOLEAN fNoSurrender = FALSE;
// enemy team
// enemy team and creature team (bandits can be captured)
firstid = gTacticalStatus.Team[ ENEMY_TEAM ].bFirstID;
lastid = gTacticalStatus.Team[ ENEMY_TEAM ].bLastID;
lastid = gTacticalStatus.Team[CREATURE_TEAM].bLastID;
for ( uiCnt = firstid, pSoldier = MercPtrs[ uiCnt ]; uiCnt <= lastid; ++uiCnt, ++pSoldier)
{
if( pSoldier->bActive && ( pSoldier->sSectorX == gWorldSectorX ) && ( pSoldier->sSectorY == gWorldSectorY ) && ( pSoldier->bSectorZ == gbWorldSectorZ) )
@@ -10558,7 +10563,7 @@ void PrisonerSurrenderMessageBoxCallBack( UINT8 ubExitValue )
{
// it is enough to simply set all soldiers to captured
firstid = gTacticalStatus.Team[ ENEMY_TEAM ].bFirstID;
lastid = gTacticalStatus.Team[ ENEMY_TEAM ].bLastID;
lastid = gTacticalStatus.Team[ CIV_TEAM ].bLastID;
for ( uiCnt = firstid, pSoldier = MercPtrs[ uiCnt ]; uiCnt <= lastid; ++uiCnt, ++pSoldier)
{
if( pSoldier->bActive && ( pSoldier->sSectorX == gWorldSectorX ) && ( pSoldier->sSectorY == gWorldSectorY ) && ( pSoldier->bSectorZ == gbWorldSectorZ) )
@@ -10577,28 +10582,7 @@ void PrisonerSurrenderMessageBoxCallBack( UINT8 ubExitValue )
}
}
}
firstid = gTacticalStatus.Team[CIV_TEAM].bFirstID;
lastid = gTacticalStatus.Team[CIV_TEAM].bLastID;
for ( uiCnt = firstid, pSoldier = MercPtrs[uiCnt]; uiCnt <= lastid; ++uiCnt, ++pSoldier )
{
if ( pSoldier->bActive && (pSoldier->sSectorX == gWorldSectorX) && (pSoldier->sSectorY == gWorldSectorY) && (pSoldier->bSectorZ == gbWorldSectorZ) )
{
// can this guy be captured?
if ( !pSoldier->CanBeCaptured() )
continue;
// only if not dying
if ( pSoldier->stats.bLife >= OKLIFE )
{
pSoldier->usSoldierFlagMask |= SOLDIER_POW;
// Remove as target
RemoveManAsTarget( pSoldier );
}
}
}
// dynamic opinion: a merc caused the remaining enemies to give up
if ( gusSelectedSoldier != NOBODY )
HandleDynamicOpinionChange( MercPtrs[gusSelectedSoldier], OPINIONEVENT_BATTLE_TOOK_PRISONER, TRUE, TRUE );
@@ -10626,6 +10610,14 @@ void PrisonerSurrenderMessageBoxCallBack( UINT8 ubExitValue )
// we offered to surrender OURSELVES TO the enemy
else if ( ubExitValue == 2 )
{
// we cannot surrender to bandits, talk instead
if ( MercPtrs[prisonerdialoguetargetID]->bTeam != CREATURE_TEAM )
{
// normal dialog
StartCivQuote( MercPtrs[prisonerdialoguetargetID] );
return;
}
if ( !gGameExternalOptions.fPlayerCanAsktoSurrender )
{
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szPrisonerTextStr[ SRT_PRISONER_INI_SETTING_OFF ] );
@@ -10763,14 +10755,16 @@ void HandleSurrenderOffer( SOLDIERTYPE* pSoldier )
// open a dialogue box and see wether we really want to offer this, or just talk
wcscpy( gzUserDefinedButton[0], TacticalStr[ PRISONER_DEMAND_SURRENDER_STR ] );
wcscpy( gzUserDefinedButton[1], TacticalStr[ PRISONER_OFFER_SURRENDER_STR ] );
SOLDIERTYPE* pTargetSoldier = NULL;
if ( GetSoldier( &pTargetSoldier, prisonerdialoguetargetID ) &&
pTargetSoldier->bTeam == ENEMY_TEAM &&
pTargetSoldier->ubProfile == NO_PROFILE &&
pTargetSoldier->aiData.bAlertStatus < STATUS_RED &&
!pTargetSoldier->RecognizeAsCombatant( gusSelectedSoldier ) )
if ( pSoldier->bTeam != CREATURE_TEAM )
wcscpy( gzUserDefinedButton[1], TacticalStr[ PRISONER_OFFER_SURRENDER_STR ] );
else
wcscpy( gzUserDefinedButton[1], TacticalStr[PRISONER_TALK_STR] );
if ( pSoldier->bTeam == ENEMY_TEAM &&
pSoldier->ubProfile == NO_PROFILE &&
pSoldier->aiData.bAlertStatus < STATUS_RED &&
!pSoldier->RecognizeAsCombatant( gusSelectedSoldier ) )
{
wcscpy( gzUserDefinedButton[2], TacticalStr[PRISONER_DISTRACT_STR] );
}
+26 -5
View File
@@ -47,6 +47,8 @@
#include "Campaign Types.h"
#include "text.h" // added by Flugente
#include "Vehicles.h" // added by silversurfer
#include "ai.h" // added by Flugente
#include "PreBattle Interface.h" // added by Flugente
#endif
#include "Animation Control.h"
@@ -2632,7 +2634,7 @@ void RaiseZombies( void )
for ( INT32 cnt = giNumRottingCorpse - 1; cnt >= 0; --cnt )
{
if ( pSector->ubNumCreatures < gGameExternalOptions.ubGameMaximumNumberOfCreatures ) // ... if there is still room for more zombies (zombies count as creatures until a separate ZOMBIE_TEAM is implemented)...
if ( pSector && pSector->ubNumCreatures < gGameExternalOptions.ubGameMaximumNumberOfCreatures ) // ... if there is still room for more zombies (zombies count as creatures until a separate ZOMBIE_TEAM is implemented)...
{
pCorpse = &(gRottingCorpse[ cnt ] );
@@ -2652,8 +2654,8 @@ void RaiseZombies( void )
zombieshaverisen = TRUE;
CreateZombiefromCorpse( pCorpse, recanimstate );
//++pSector->ubNumZombies;
//++pSector->ubZombiesInBattle;
pSector->ubNumCreatures++;
pSector->ubCreaturesInBattle++;
RemoveCorpse( cnt );
}
@@ -2680,13 +2682,32 @@ void RaiseZombies( void )
PlayJA2SampleFromFile( "Sounds\\zombie1.wav", RATE_11025, HIGHVOLUME, 1, MIDDLEPAN );
UseCreatureMusic(TRUE); // Madd: music when zombies rise
#ifdef NEWMUSIC
#ifdef NEWMUSIC
GlobalSoundID = MusicSoundValues[ SECTOR( gWorldSectorX, gWorldSectorY ) ].SoundTacticalTensor[gbWorldSectorZ];
if ( MusicSoundValues[ SECTOR( gWorldSectorX, gWorldSectorY ) ].SoundTacticalTensor[gbWorldSectorZ] != -1 )
SetMusicModeID( MUSIC_TACTICAL_ENEMYPRESENT, MusicSoundValues[ SECTOR( gWorldSectorX, gWorldSectorY ) ].SoundTacticalTensor[gbWorldSectorZ] );
else
#endif
#endif
SetMusicMode( MUSIC_TACTICAL_ENEMYPRESENT );
// alert the creatures
HandleInitialRedAlert( CREATURE_TEAM, FALSE );
// we need this so that the battle is properly recognized in strategic
{
//Set up the location as well as turning on the blit flag.
gubPBSectorX = (UINT8)gWorldSectorX;
gubPBSectorY = (UINT8)gWorldSectorY;
gubPBSectorZ = (UINT8)gbWorldSectorZ;
gfBlitBattleSectorLocator = TRUE;
}
if ( GetEnemyEncounterCode() == NO_ENCOUNTER_CODE )
SetEnemyEncounterCode( ZOMBIE_ATTACK_CODE );
// idea... potentially scrap this part and use a simplified form of void CreatureAttackTown_OtherCreatures(...) ?
//gubSectorIDOfCreatureAttack = SECTOR( gWorldSectorX, gWorldSectorY );
}
}
}
+13
View File
@@ -64,6 +64,8 @@
#include "CampaignStats.h" // added by Flugente
#include "DynamicDialogue.h" // added by Flugente
#include "MilitiaIndividual.h" // added by Flugente
#include "Town Militia.h" // added by Flugente
#include "PreBattle Interface.h" // added by Flugente
#endif
// anv: for enemy taunts
@@ -3945,6 +3947,9 @@ BOOLEAN HandleSoldierDeath( SOLDIERTYPE *pSoldier , BOOLEAN *pfMadeCorpse )
case SOLDIER_CLASS_ZOMBIE :
gMercProfiles[ MercPtrs[ ubAttacker ]->ubProfile ].records.usKillsZombies++;
break;
case SOLDIER_CLASS_BANDIT:
gMercProfiles[MercPtrs[ubAttacker]->ubProfile].records.usKillsOthers++;
break;
default :
if ( CREATURE_OR_BLOODCAT( pSoldier ) )
gMercProfiles[ MercPtrs[ ubAttacker ]->ubProfile ].records.usKillsCreatures++;
@@ -4049,6 +4054,14 @@ BOOLEAN HandleSoldierDeath( SOLDIERTYPE *pSoldier , BOOLEAN *pfMadeCorpse )
// Flugente: campaign stats
gCurrentIncident.AddStat( pSoldier, CAMPAIGNHISTORY_TYPE_KILL );
// Flugente: for raids, we need to keep track of killed forces
if ( GetEnemyEncounterCode() == BLOODCAT_ATTACK_CODE ||
GetEnemyEncounterCode() == ZOMBIE_ATTACK_CODE ||
GetEnemyEncounterCode() == BANDIT_ATTACK_CODE )
{
AddRaidPersonnel( -( pSoldier->ubBodyType == BLOODCAT ), -( pSoldier->ubSoldierClass == SOLDIER_CLASS_ZOMBIE ), -( pSoldier->ubSoldierClass == SOLDIER_CLASS_BANDIT ) );
}
// Flugente: individual militia
MILITIA militia;
if ( GetMilitia( pSoldier->usIndividualMilitiaID, &militia ) && !(militia.flagmask & MILITIAFLAG_DEAD) )
+6 -2
View File
@@ -14723,7 +14723,7 @@ INT32 SOLDIERTYPE::GetDamageResistance( BOOLEAN fAutoResolve, BOOLEAN fCalcBreat
else if ( this->ubSoldierClass == SOLDIER_CLASS_ELITE_MILITIA && gGameExternalOptions.bVeteranMilitiaDamageResistance != 0 )
resistance += (INT32)(gGameExternalOptions.bVeteranMilitiaDamageResistance / breathmodifiermilitia);
// bonus for enemy too
else if ( this->ubSoldierClass == SOLDIER_CLASS_ADMINISTRATOR && gGameExternalOptions.sEnemyAdminDamageResistance != 0 )
else if ( (this->ubSoldierClass == SOLDIER_CLASS_ADMINISTRATOR || this->ubSoldierClass == SOLDIER_CLASS_BANDIT ) && gGameExternalOptions.sEnemyAdminDamageResistance != 0 )
resistance += gGameExternalOptions.sEnemyAdminDamageResistance;
else if ( this->ubSoldierClass == SOLDIER_CLASS_ARMY && gGameExternalOptions.sEnemyRegularDamageResistance != 0 )
resistance += gGameExternalOptions.sEnemyRegularDamageResistance;
@@ -16211,7 +16211,7 @@ UINT32 SOLDIERTYPE::GetSurrenderStrength( )
// adjust for type of soldier
if ( this->ubSoldierClass == SOLDIER_CLASS_ELITE || this->ubSoldierClass == SOLDIER_CLASS_ELITE_MILITIA )
value *= 1.5f;
else if ( this->ubSoldierClass == SOLDIER_CLASS_ADMINISTRATOR || this->ubSoldierClass == SOLDIER_CLASS_GREEN_MILITIA )
else if ( this->ubSoldierClass == SOLDIER_CLASS_ADMINISTRATOR || this->ubSoldierClass == SOLDIER_CLASS_GREEN_MILITIA || this->ubSoldierClass == SOLDIER_CLASS_BANDIT )
value *= 0.75f;
// tanks won't surrender that easy
@@ -16267,6 +16267,10 @@ BOOLEAN SOLDIERTYPE::CanBeCaptured( )
if ( this->bTeam == ENEMY_TEAM )
return TRUE;
// bandits can be captured
if ( this->bTeam == CREATURE_TEAM && this->ubSoldierClass == SOLDIER_CLASS_BANDIT )
return TRUE;
// civilians can be captured if their faction can, and if they are hostile
if ( this->bTeam == CIV_TEAM && zCivGroupName[this->ubCivilianGroup].fCanBeCaptured )
{
+1
View File
@@ -331,6 +331,7 @@ enum
SOLDIER_CLASS_ZOMBIE,
SOLDIER_CLASS_TANK,
SOLDIER_CLASS_JEEP,
SOLDIER_CLASS_BANDIT,
SOLDIER_CLASS_MAX,
};
+156 -93
View File
@@ -1799,7 +1799,7 @@ BOOLEAN TacticalCopySoldierFromCreateStruct( SOLDIERTYPE *pSoldier, SOLDIERCREAT
//////////////////////////////////////////////////////////////////////////////////////////////////
// Added by SANDRO - the enemy/militia has a decent chance to have some traits
if ( gGameExternalOptions.fAssignTraitsToEnemy && SOLDIER_CLASS_ENEMY( pSoldier->ubSoldierClass ) )
if ( gGameExternalOptions.fAssignTraitsToEnemy && (SOLDIER_CLASS_ENEMY( pSoldier->ubSoldierClass ) || pSoldier->ubSoldierClass == SOLDIER_CLASS_BANDIT) )
AssignTraitsToSoldier( pSoldier, pCreateStruct );
if ( gGameExternalOptions.fAssignTraitsToMilitia && SOLDIER_CLASS_MILITIA( pSoldier->ubSoldierClass ) )
AssignTraitsToSoldier( pSoldier, pCreateStruct );
@@ -2010,7 +2010,7 @@ BOOLEAN TacticalCopySoldierFromCreateStruct( SOLDIERTYPE *pSoldier, SOLDIERCREAT
}
break;
case CREATURE_TEAM:
if( pSoldier->ubBodyType == BLOODCAT )
if ( pSoldier->ubBodyType == BLOODCAT )
{
swprintf( pSoldier->name, gzLateLocalizedString[ 36 ] );
}
@@ -2018,9 +2018,13 @@ BOOLEAN TacticalCopySoldierFromCreateStruct( SOLDIERTYPE *pSoldier, SOLDIERCREAT
{
swprintf( pSoldier->name, TacticalStr[ ZOMBIE_TEAM_MERC_NAME ] );
}
else if ( pSoldier->ubBodyType >= ADULTFEMALEMONSTER && pSoldier->ubBodyType <= QUEENMONSTER )
{
swprintf( pSoldier->name, TacticalStr[CREATURE_TEAM_MERC_NAME] ); break;
}
else
{
swprintf( pSoldier->name, TacticalStr[ CREATURE_TEAM_MERC_NAME ] ); break;
swprintf( pSoldier->name, gpStrategicString[STR_PB_BANDIT] ); break;
}
break;
}
@@ -2296,7 +2300,6 @@ INT8 CalcDifficultyModifier( UINT8 ubSoldierClass )
return(bDiffModifier);
}
//When the editor modifies the soldier's relative attribute level,
//this function is called to update that information.
//Used to generate a detailed placement from a basic placement. This assumes that the detailed placement
@@ -2397,8 +2400,7 @@ void CreateDetailedPlacementGivenBasicPlacementInfo( SOLDIERCREATE_STRUCT *pp, B
pp->bOrders = bp->bOrders;
pp->bAttitude = bp->bAttitude;
pp->ubDirection = bp->ubDirection;
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("CreateDetailedPlacementGivenBasicPlacementInfo: determine soldier's class"));
// determine this soldier's soldier class
if( bp->bTeam == CREATURE_TEAM )
@@ -2411,8 +2413,7 @@ void CreateDetailedPlacementGivenBasicPlacementInfo( SOLDIERCREATE_STRUCT *pp, B
}
ubDiffFactor = CalcDifficultyModifier( ubSoldierClass );
// experience level is modified by game difficulty, player's progress, & proximity to Queen's Palace, etc.
// This formula gives the following results:
// DIFFICULTY FACTOR EXP. LEVEL MODIFIER LEVEL OF AVG REGULAR TROOP
@@ -2457,6 +2458,19 @@ void CreateDetailedPlacementGivenBasicPlacementInfo( SOLDIERCREATE_STRUCT *pp, B
break;
}
UINT8 DiffLevel;
if ( gGameOptions.ubDifficultyLevel == DIF_LEVEL_EASY )
DiffLevel = 1;
else if ( gGameOptions.ubDifficultyLevel == DIF_LEVEL_MEDIUM )
DiffLevel = 2;
else if ( gGameOptions.ubDifficultyLevel == DIF_LEVEL_HARD )
DiffLevel = 3;
else if ( gGameOptions.ubDifficultyLevel == DIF_LEVEL_INSANE )
DiffLevel = 4;
else
{
DiffLevel = 1 + Random ( 4 );
}
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("CreateDetailedPlacementGivenBasicPlacementInfo: set level based on soldier class"));
//Set the experience level based on the soldier class and exp level modifier or relative attribute level
@@ -2464,6 +2478,7 @@ void CreateDetailedPlacementGivenBasicPlacementInfo( SOLDIERCREATE_STRUCT *pp, B
{
case SOLDIER_CLASS_ADMINISTRATOR:
case SOLDIER_CLASS_ZOMBIE:
case SOLDIER_CLASS_BANDIT:
pp->bExpLevel = (INT8) 2 + bExpLevelModifier;
break;
case SOLDIER_CLASS_ARMY:
@@ -2512,23 +2527,7 @@ void CreateDetailedPlacementGivenBasicPlacementInfo( SOLDIERCREATE_STRUCT *pp, B
UINT8 PlacementType = gBloodcatPlacements[ SECTOR(gWorldSectorX, gWorldSectorY) ][0].PlacementType;
if( PlacementType == BLOODCAT_PLACEMENT_LAIR )
{
UINT8 DiffLevel;
if( gGameOptions.ubDifficultyLevel == DIF_LEVEL_EASY )
DiffLevel = 1;
else if( gGameOptions.ubDifficultyLevel == DIF_LEVEL_MEDIUM )
DiffLevel = 2;
else if( gGameOptions.ubDifficultyLevel == DIF_LEVEL_HARD )
DiffLevel = 3;
else if( gGameOptions.ubDifficultyLevel == DIF_LEVEL_INSANE )
DiffLevel = 4;
else
{
DiffLevel = Random (4);
if (DiffLevel == 0) DiffLevel = 1;
}
pp->bExpLevel += DiffLevel;
//pp->bExpLevel += gGameOptions.ubDifficultyLevel;
}
break;
}
@@ -2546,8 +2545,8 @@ void CreateDetailedPlacementGivenBasicPlacementInfo( SOLDIERCREATE_STRUCT *pp, B
}
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("CreateDetailedPlacementGivenBasicPlacementInfo: set exp. level"));
pp->bExpLevel = max( gGameOptions.ubDifficultyLevel, pp->bExpLevel ); //minimum exp. level of 1 -- madd->= dif level
pp->bExpLevel = max( DiffLevel, pp->bExpLevel ); //minimum exp. level of 1 -- madd->= dif level
if ( gGameOptions.ubDifficultyLevel == DIF_LEVEL_INSANE )
pp->bExpLevel = max( 6, pp->bExpLevel ); //minimum exp. level of 6 in insane - madd
@@ -2555,23 +2554,7 @@ void CreateDetailedPlacementGivenBasicPlacementInfo( SOLDIERCREATE_STRUCT *pp, B
ubStatsLevel = pp->bExpLevel + bStatsModifier;
UINT8 DiffLevel;
if( gGameOptions.ubDifficultyLevel == DIF_LEVEL_EASY )
DiffLevel = 1;
else if( gGameOptions.ubDifficultyLevel == DIF_LEVEL_MEDIUM )
DiffLevel = 2;
else if( gGameOptions.ubDifficultyLevel == DIF_LEVEL_HARD )
DiffLevel = 3;
else if( gGameOptions.ubDifficultyLevel == DIF_LEVEL_INSANE )
DiffLevel = 4;
else
{
DiffLevel = Random (4);
if (DiffLevel == 0) DiffLevel = 1;
}
ubStatsLevel = max( DiffLevel, ubStatsLevel ); //minimum stats level of 0 -- madd->= dif level
//ubStatsLevel = max( gGameOptions.ubDifficultyLevel, ubStatsLevel ); //minimum stats level of 0 -- madd->= dif level
ubStatsLevel = max( DiffLevel, ubStatsLevel ); //minimum stats level of 0 -- madd->= dif level
if ( gGameOptions.ubDifficultyLevel == DIF_LEVEL_INSANE )
ubStatsLevel = max( 6, ubStatsLevel ); //minimum stats level of 6 in insane
@@ -2618,7 +2601,11 @@ void CreateDetailedPlacementGivenBasicPlacementInfo( SOLDIERCREATE_STRUCT *pp, B
//own equipment.
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("CreateDetailedPlacementGivenBasicPlacementInfo: generate random equipment"));
if( !bp->fDetailedPlacement && ubSoldierClass != SOLDIER_CLASS_NONE && ubSoldierClass != SOLDIER_CLASS_CREATURE && ubSoldierClass != SOLDIER_CLASS_MINER && ubSoldierClass != SOLDIER_CLASS_ZOMBIE )
if( !bp->fDetailedPlacement &&
ubSoldierClass != SOLDIER_CLASS_NONE &&
ubSoldierClass != SOLDIER_CLASS_CREATURE &&
ubSoldierClass != SOLDIER_CLASS_MINER &&
ubSoldierClass != SOLDIER_CLASS_ZOMBIE )
{
GenerateRandomEquipment( pp, ubSoldierClass, bp->bRelativeEquipmentLevel);
@@ -2800,7 +2787,10 @@ void CreateDetailedPlacementGivenStaticDetailedPlacementAndBasicPlacementInfo(
// ReplaceExtendedGuns( pp, bp->ubSoldierClass );
//}
if( bp->ubSoldierClass != SOLDIER_CLASS_NONE && bp->ubSoldierClass != SOLDIER_CLASS_CREATURE && bp->ubSoldierClass != SOLDIER_CLASS_MINER && bp->ubSoldierClass != SOLDIER_CLASS_ZOMBIE )
if( bp->ubSoldierClass != SOLDIER_CLASS_NONE &&
bp->ubSoldierClass != SOLDIER_CLASS_CREATURE &&
bp->ubSoldierClass != SOLDIER_CLASS_MINER &&
bp->ubSoldierClass != SOLDIER_CLASS_ZOMBIE )
{
GenerateRandomEquipment( pp, bp->ubSoldierClass, bp->bRelativeEquipmentLevel);
@@ -2841,6 +2831,7 @@ void UpdateSoldierWithStaticDetailedInformation( SOLDIERTYPE *s, SOLDIERCREATE_S
case SOLDIER_CLASS_ADMINISTRATOR:
case SOLDIER_CLASS_ARMY:
case SOLDIER_CLASS_ELITE:
case SOLDIER_CLASS_BANDIT:
GeneratePaletteForSoldier( s, spp->ubSoldierClass, spp->bTeam );
break;
}
@@ -3003,7 +2994,7 @@ SOLDIERTYPE* ReserveTacticalSoldierForAutoresolve( UINT8 ubSoldierClass )
//returns the pointer to that soldier. This is used when copying the exact status of
//all remaining enemy troops (or creatures) to finish the battle in autoresolve. To
//signify that the troop has already been reserved, we simply set their gridno to NOWHERE.
if( ubSoldierClass != SOLDIER_CLASS_CREATURE && ubSoldierClass != SOLDIER_CLASS_ZOMBIE )
if( ubSoldierClass != SOLDIER_CLASS_CREATURE && ubSoldierClass != SOLDIER_CLASS_ZOMBIE && ubSoldierClass != SOLDIER_CLASS_BANDIT )
{
//use the enemy team
iStart = gTacticalStatus.Team[ ENEMY_TEAM ].bFirstID;
@@ -3244,12 +3235,16 @@ SOLDIERTYPE* TacticalCreateZombie()
memset( &bp, 0, sizeof( BASIC_SOLDIERCREATE_STRUCT ) );
RandomizeRelativeLevel( &( bp.bRelativeAttributeLevel ), SOLDIER_CLASS_ZOMBIE );
RandomizeRelativeLevel( &( bp.bRelativeEquipmentLevel ), SOLDIER_CLASS_ZOMBIE );
bp.bTeam = CREATURE_TEAM;//ZOMBIE_TEAM;
bp.bTeam = CREATURE_TEAM;
bp.bOrders = SEEKENEMY;
bp.bAttitude = AGGRESSIVE;
bp.ubBodyType = -1;
bp.ubBodyType = Random( ADULTFEMALEMONSTER );
bp.ubSoldierClass = SOLDIER_CLASS_ZOMBIE;
CreateDetailedPlacementGivenBasicPlacementInfo( &pp, &bp );
// need to properly set this here
pp.ubSoldierClass = SOLDIER_CLASS_ZOMBIE;
pSoldier = TacticalCreateSoldier( &pp, &ubID );
if ( pSoldier )
{
@@ -3398,10 +3393,13 @@ SOLDIERTYPE* TacticalCreateArmedCivilian( UINT8 usSoldierClass )
pSoldier->aiData.sNoiseGridno = (CENTRAL_GRIDNO + (Random( CENTRAL_RADIUS * 2 + 1 ) - CENTRAL_RADIUS) + (Random( CENTRAL_RADIUS * 2 + 1 ) - CENTRAL_RADIUS) * WORLD_COLS);
pSoldier->aiData.ubNoiseVolume = MAX_MISC_NOISE_DURATION;
// random clothes
SetClothes( pSoldier, Random( NUMSHIRTS ), Random( NUMPANTS ) );
if ( guiCurrentScreen != AUTORESOLVE_SCREEN )
{
// random clothes
SetClothes( pSoldier, Random( NUMSHIRTS ), Random( NUMPANTS ) );
pSoldier->CreateSoldierPalettes( );
pSoldier->CreateSoldierPalettes();
}
}
return(pSoldier);
@@ -3481,25 +3479,28 @@ SOLDIERTYPE* TacticalCreateCivilian( INT32 sGridNo, UINT8 usCivilianGroup, INT8
pSoldier->aiData.bOrders = ONGUARD;
}
// make him wear administrator uniform
UINT16 usPaletteAnimSurface = LoadSoldierAnimationSurface( pSoldier, pSoldier->usAnimState );
if ( usPaletteAnimSurface != INVALID_ANIMATION_SURFACE )
if ( guiCurrentScreen != AUTORESOLVE_SCREEN )
{
SetClothes( pSoldier, aVest, aPants, aHair, aSkin );
// make him wear administrator uniform
UINT16 usPaletteAnimSurface = LoadSoldierAnimationSurface( pSoldier, pSoldier->usAnimState );
// Use palette from HVOBJECT, then use substitution for pants, etc
memcpy( pSoldier->p8BPPPalette, gAnimSurfaceDatabase[usPaletteAnimSurface].hVideoObject->pPaletteEntry, sizeof(pSoldier->p8BPPPalette) * 256 );
if ( usPaletteAnimSurface != INVALID_ANIMATION_SURFACE )
{
SetClothes( pSoldier, aVest, aPants, aHair, aSkin );
SetPaletteReplacement( pSoldier->p8BPPPalette, pSoldier->HeadPal );
SetPaletteReplacement( pSoldier->p8BPPPalette, pSoldier->VestPal );
SetPaletteReplacement( pSoldier->p8BPPPalette, pSoldier->PantsPal );
SetPaletteReplacement( pSoldier->p8BPPPalette, pSoldier->SkinPal );
// Use palette from HVOBJECT, then use substitution for pants, etc
memcpy( pSoldier->p8BPPPalette, gAnimSurfaceDatabase[usPaletteAnimSurface].hVideoObject->pPaletteEntry, sizeof( pSoldier->p8BPPPalette ) * 256 );
pSoldier->CreateSoldierPalettes( );
SetPaletteReplacement( pSoldier->p8BPPPalette, pSoldier->HeadPal );
SetPaletteReplacement( pSoldier->p8BPPPalette, pSoldier->VestPal );
SetPaletteReplacement( pSoldier->p8BPPPalette, pSoldier->PantsPal );
SetPaletteReplacement( pSoldier->p8BPPPalette, pSoldier->SkinPal );
// Dirty
fInterfacePanelDirty = DIRTYLEVEL2;
pSoldier->CreateSoldierPalettes();
// Dirty
fInterfacePanelDirty = DIRTYLEVEL2;
}
}
}
@@ -3572,6 +3573,65 @@ SOLDIERTYPE* TacticalCreateEnemyAssassin(UINT8 disguisetype)
return( pSoldier );
}
SOLDIERTYPE* TacticalCreateBandit()
{
BASIC_SOLDIERCREATE_STRUCT bp;
SOLDIERCREATE_STRUCT pp;
UINT8 ubID;
SOLDIERTYPE * pSoldier;
if ( guiCurrentScreen == AUTORESOLVE_SCREEN && !gfPersistantPBI )
{
pSoldier = ReserveTacticalSoldierForAutoresolve( SOLDIER_CLASS_BANDIT );
if ( pSoldier ) return pSoldier;
}
memset( &bp, 0, sizeof( BASIC_SOLDIERCREATE_STRUCT ) );
RandomizeRelativeLevel( &( bp.bRelativeAttributeLevel ), SOLDIER_CLASS_ADMINISTRATOR );
RandomizeRelativeLevel( &( bp.bRelativeEquipmentLevel ), SOLDIER_CLASS_ADMINISTRATOR );
bp.bTeam = ENEMY_TEAM; // set wrong team here, otherwise no bodytype/equipment will be set
bp.bOrders = SEEKENEMY;
bp.bAttitude = (INT8)Random( MAXATTITUDES );
bp.ubBodyType = -1;
bp.ubSoldierClass = SOLDIER_CLASS_ADMINISTRATOR;
CreateDetailedPlacementGivenBasicPlacementInfo( &pp, &bp );
// need to properly set this here
pp.bTeam = CREATURE_TEAM;
pp.ubSoldierClass = SOLDIER_CLASS_BANDIT;
pSoldier = TacticalCreateSoldier( &pp, &ubID );
if ( pSoldier )
{
// send soldier to centre of map, roughly
pSoldier->aiData.sNoiseGridno = ( CENTRAL_GRIDNO + ( Random( CENTRAL_RADIUS * 2 + 1 ) - CENTRAL_RADIUS ) + ( Random( CENTRAL_RADIUS * 2 + 1 ) - CENTRAL_RADIUS ) * WORLD_COLS );
pSoldier->aiData.ubNoiseVolume = MAX_MISC_NOISE_DURATION;
if ( guiCurrentScreen != AUTORESOLVE_SCREEN )
{
UINT16 usPaletteAnimSurface = LoadSoldierAnimationSurface( pSoldier, pSoldier->usAnimState );
if ( usPaletteAnimSurface != INVALID_ANIMATION_SURFACE )
{
// random clothes
SetClothes( pSoldier, Random( NUMSHIRTS ), Random( NUMPANTS ) );
// Use palette from HVOBJECT, then use substitution for pants, etc
memcpy( pSoldier->p8BPPPalette, gAnimSurfaceDatabase[usPaletteAnimSurface].hVideoObject->pPaletteEntry, sizeof( pSoldier->p8BPPPalette ) * 256 );
SetPaletteReplacement( pSoldier->p8BPPPalette, pSoldier->HeadPal );
SetPaletteReplacement( pSoldier->p8BPPPalette, pSoldier->VestPal );
SetPaletteReplacement( pSoldier->p8BPPPalette, pSoldier->PantsPal );
SetPaletteReplacement( pSoldier->p8BPPPalette, pSoldier->SkinPal );
pSoldier->CreateSoldierPalettes();
}
}
}
return( pSoldier );
}
void CreateAssassin(UINT8 disguisetype)
{
SOLDIERTYPE* pSoldier = TacticalCreateEnemyAssassin( disguisetype );
@@ -3742,26 +3802,29 @@ void CreatePrisonerOfWar()
swprintf( pSoldier->name, TacticalStr[ POW_TEAM_MERC_NAME ] );
// make him wear 'prisoner garb' (just what Shank and Dynamo are wearing)
UINT16 usPaletteAnimSurface = LoadSoldierAnimationSurface( pSoldier, pSoldier->usAnimState );
if ( usPaletteAnimSurface != INVALID_ANIMATION_SURFACE )
if ( guiCurrentScreen != AUTORESOLVE_SCREEN )
{
SET_PALETTEREP_ID( pSoldier->VestPal, "greyVEST" );
SET_PALETTEREP_ID( pSoldier->PantsPal, "BLACKPANTS" );
// make him wear 'prisoner garb' (just what Shank and Dynamo are wearing)
UINT16 usPaletteAnimSurface = LoadSoldierAnimationSurface( pSoldier, pSoldier->usAnimState );
// Use palette from HVOBJECT, then use substitution for pants, etc
memcpy( pSoldier->p8BPPPalette, gAnimSurfaceDatabase[usPaletteAnimSurface].hVideoObject->pPaletteEntry, sizeof(pSoldier->p8BPPPalette) * 256 );
if ( usPaletteAnimSurface != INVALID_ANIMATION_SURFACE )
{
SET_PALETTEREP_ID( pSoldier->VestPal, "greyVEST" );
SET_PALETTEREP_ID( pSoldier->PantsPal, "BLACKPANTS" );
SetPaletteReplacement( pSoldier->p8BPPPalette, pSoldier->HeadPal );
SetPaletteReplacement( pSoldier->p8BPPPalette, pSoldier->VestPal );
SetPaletteReplacement( pSoldier->p8BPPPalette, pSoldier->PantsPal );
SetPaletteReplacement( pSoldier->p8BPPPalette, pSoldier->SkinPal );
// Use palette from HVOBJECT, then use substitution for pants, etc
memcpy( pSoldier->p8BPPPalette, gAnimSurfaceDatabase[usPaletteAnimSurface].hVideoObject->pPaletteEntry, sizeof( pSoldier->p8BPPPalette ) * 256 );
pSoldier->CreateSoldierPalettes( );
SetPaletteReplacement( pSoldier->p8BPPPalette, pSoldier->HeadPal );
SetPaletteReplacement( pSoldier->p8BPPPalette, pSoldier->VestPal );
SetPaletteReplacement( pSoldier->p8BPPPalette, pSoldier->PantsPal );
SetPaletteReplacement( pSoldier->p8BPPPalette, pSoldier->SkinPal );
// Dirty
fInterfacePanelDirty = DIRTYLEVEL2;
pSoldier->CreateSoldierPalettes();
// Dirty
fInterfacePanelDirty = DIRTYLEVEL2;
}
}
// So we can see them!
@@ -4696,7 +4759,7 @@ BOOLEAN AssignTraitsToSoldier( SOLDIERTYPE *pSoldier, SOLDIERCREATE_STRUCT *pCre
// 30-80%
iChance = 30 + ubProgress / 2;
}
else if ( ubSolClass == SOLDIER_CLASS_ADMINISTRATOR || ubSolClass == SOLDIER_CLASS_GREEN_MILITIA )
else if ( ubSolClass == SOLDIER_CLASS_ADMINISTRATOR || ubSolClass == SOLDIER_CLASS_GREEN_MILITIA || ubSolClass == SOLDIER_CLASS_BANDIT )
{
// 15-65%
iChance = 15 + ubProgress / 2;
@@ -4757,7 +4820,7 @@ BOOLEAN AssignTraitsToSoldier( SOLDIERTYPE *pSoldier, SOLDIERCREATE_STRUCT *pCre
// 30-80%
iChance = 30 + ubProgress / 2;
}
else if ( ubSolClass == SOLDIER_CLASS_ADMINISTRATOR || ubSolClass == SOLDIER_CLASS_GREEN_MILITIA )
else if ( ubSolClass == SOLDIER_CLASS_ADMINISTRATOR || ubSolClass == SOLDIER_CLASS_GREEN_MILITIA || ubSolClass == SOLDIER_CLASS_BANDIT )
{
// 15-65%
iChance = 15 + ubProgress / 2;
@@ -4819,7 +4882,7 @@ BOOLEAN AssignTraitsToSoldier( SOLDIERTYPE *pSoldier, SOLDIERCREATE_STRUCT *pCre
// 25-75%
iChance = 25 + ubProgress / 2;
}
else if ( ubSolClass == SOLDIER_CLASS_ADMINISTRATOR || ubSolClass == SOLDIER_CLASS_GREEN_MILITIA )
else if ( ubSolClass == SOLDIER_CLASS_ADMINISTRATOR || ubSolClass == SOLDIER_CLASS_GREEN_MILITIA || ubSolClass == SOLDIER_CLASS_BANDIT )
{
// 10-60%
iChance = 10 + ubProgress / 2;
@@ -4888,7 +4951,7 @@ BOOLEAN AssignTraitsToSoldier( SOLDIERTYPE *pSoldier, SOLDIERCREATE_STRUCT *pCre
// 25-75%
iChance = 25 + ubProgress / 2;
}
else if ( ubSolClass == SOLDIER_CLASS_ADMINISTRATOR || ubSolClass == SOLDIER_CLASS_GREEN_MILITIA )
else if ( ubSolClass == SOLDIER_CLASS_ADMINISTRATOR || ubSolClass == SOLDIER_CLASS_GREEN_MILITIA || ubSolClass == SOLDIER_CLASS_BANDIT )
{
// 10-60%
iChance = 10 + ubProgress / 2;
@@ -4993,7 +5056,7 @@ BOOLEAN AssignTraitsToSoldier( SOLDIERTYPE *pSoldier, SOLDIERCREATE_STRUCT *pCre
// 25-75%
iChance = 25 + ubProgress / 2;
}
else if ( ubSolClass == SOLDIER_CLASS_ADMINISTRATOR || ubSolClass == SOLDIER_CLASS_GREEN_MILITIA )
else if ( ubSolClass == SOLDIER_CLASS_ADMINISTRATOR || ubSolClass == SOLDIER_CLASS_GREEN_MILITIA || ubSolClass == SOLDIER_CLASS_BANDIT )
{
// 10-60%
iChance = 10 + ubProgress / 2;
@@ -5177,7 +5240,7 @@ BOOLEAN AssignTraitsToSoldier( SOLDIERTYPE *pSoldier, SOLDIERCREATE_STRUCT *pCre
iChance = 45 + ubProgress / 2; // 45-95% chance
else if ( ubSolClass == SOLDIER_CLASS_ARMY || ubSolClass == SOLDIER_CLASS_REG_MILITIA )
iChance = 30 + ubProgress / 2; // 30-80% chance
else if ( ubSolClass == SOLDIER_CLASS_ADMINISTRATOR || ubSolClass == SOLDIER_CLASS_GREEN_MILITIA )
else if ( ubSolClass == SOLDIER_CLASS_ADMINISTRATOR || ubSolClass == SOLDIER_CLASS_GREEN_MILITIA || ubSolClass == SOLDIER_CLASS_BANDIT )
iChance = 15 + ubProgress / 2; // 15-65% chance
// adust the chance by the type of heavy weapon
@@ -5239,7 +5302,7 @@ BOOLEAN AssignTraitsToSoldier( SOLDIERTYPE *pSoldier, SOLDIERCREATE_STRUCT *pCre
iChance = 20 + ubProgress / 4; // 20-45% chance
else if ( ubSolClass == SOLDIER_CLASS_ARMY || ubSolClass == SOLDIER_CLASS_REG_MILITIA )
iChance = 10 + ubProgress / 4; // 10-35% chance
else if ( ubSolClass == SOLDIER_CLASS_ADMINISTRATOR || ubSolClass == SOLDIER_CLASS_GREEN_MILITIA )
else if ( ubSolClass == SOLDIER_CLASS_ADMINISTRATOR || ubSolClass == SOLDIER_CLASS_GREEN_MILITIA || ubSolClass == SOLDIER_CLASS_BANDIT )
iChance = ubProgress / 4; // 0-25% chance
else if ( ubSolClass == SOLDIER_CLASS_ZOMBIE )
iChance = 100; // 100% chance
@@ -5284,7 +5347,7 @@ BOOLEAN AssignTraitsToSoldier( SOLDIERTYPE *pSoldier, SOLDIERCREATE_STRUCT *pCre
iChance = 40 + ubProgress * 2 / 5; // 40-80% chance
else if ( ubSolClass == SOLDIER_CLASS_ARMY || ubSolClass == SOLDIER_CLASS_REG_MILITIA )
iChance = 25 + ubProgress * 2 / 5; // 25-65% chance
else if ( ubSolClass == SOLDIER_CLASS_ADMINISTRATOR || ubSolClass == SOLDIER_CLASS_GREEN_MILITIA )
else if ( ubSolClass == SOLDIER_CLASS_ADMINISTRATOR || ubSolClass == SOLDIER_CLASS_GREEN_MILITIA || ubSolClass == SOLDIER_CLASS_BANDIT )
iChance = 10 + ubProgress * 2 / 5; // 10-50% chance
else if ( ubSolClass == SOLDIER_CLASS_ZOMBIE )
iChance = 100; // 100% chance
@@ -5348,7 +5411,7 @@ BOOLEAN AssignTraitsToSoldier( SOLDIERTYPE *pSoldier, SOLDIERCREATE_STRUCT *pCre
iChance = 30 + ubProgress / 3 + 30; // 60-92% chance
else if ( ubSolClass == SOLDIER_CLASS_ARMY || ubSolClass == SOLDIER_CLASS_REG_MILITIA )
iChance = 15 + ubProgress / 3 + 25; // 40-73% chance
else if ( ubSolClass == SOLDIER_CLASS_ADMINISTRATOR || ubSolClass == SOLDIER_CLASS_GREEN_MILITIA )
else if ( ubSolClass == SOLDIER_CLASS_ADMINISTRATOR || ubSolClass == SOLDIER_CLASS_GREEN_MILITIA || ubSolClass == SOLDIER_CLASS_BANDIT )
iChance = ubProgress / 3 + 20; // 20-53% chance
// modify the chance by preset ini setting
@@ -5411,7 +5474,7 @@ BOOLEAN AssignTraitsToSoldier( SOLDIERTYPE *pSoldier, SOLDIERCREATE_STRUCT *pCre
iChance = 20 + ubProgress / 3; // 20-53% chance
else if ( ubSolClass == SOLDIER_CLASS_ARMY || ubSolClass == SOLDIER_CLASS_REG_MILITIA )
iChance = 10 + ubProgress / 3; // 10-43% chance
else if ( ubSolClass == SOLDIER_CLASS_ADMINISTRATOR || ubSolClass == SOLDIER_CLASS_GREEN_MILITIA )
else if ( ubSolClass == SOLDIER_CLASS_ADMINISTRATOR || ubSolClass == SOLDIER_CLASS_GREEN_MILITIA || ubSolClass == SOLDIER_CLASS_BANDIT )
iChance = ubProgress / 3; // 0-33% chance
// modify the chance by preset ini setting
@@ -5451,7 +5514,7 @@ BOOLEAN AssignTraitsToSoldier( SOLDIERTYPE *pSoldier, SOLDIERCREATE_STRUCT *pCre
iChance = 50 + ubProgress * 2 / 5; // 50-90% chance
else if ( ubSolClass == SOLDIER_CLASS_ARMY || ubSolClass == SOLDIER_CLASS_REG_MILITIA )
iChance = 35 + ubProgress * 2 / 5; // 35-75% chance
else if ( ubSolClass == SOLDIER_CLASS_ADMINISTRATOR || ubSolClass == SOLDIER_CLASS_GREEN_MILITIA )
else if ( ubSolClass == SOLDIER_CLASS_ADMINISTRATOR || ubSolClass == SOLDIER_CLASS_GREEN_MILITIA || ubSolClass == SOLDIER_CLASS_BANDIT )
iChance = 15 + ubProgress * 2 / 5; // 15-55% chance
// modify the chance by preset ini setting
@@ -5514,7 +5577,7 @@ BOOLEAN AssignTraitsToSoldier( SOLDIERTYPE *pSoldier, SOLDIERCREATE_STRUCT *pCre
iChance = 40 + ubProgress * 2 / 5; // 40-80% chance
else if ( ubSolClass == SOLDIER_CLASS_ARMY || ubSolClass == SOLDIER_CLASS_REG_MILITIA )
iChance = 25 + ubProgress * 2 / 5; // 25-65% chance
else if ( ubSolClass == SOLDIER_CLASS_ADMINISTRATOR || ubSolClass == SOLDIER_CLASS_GREEN_MILITIA )
else if ( ubSolClass == SOLDIER_CLASS_ADMINISTRATOR || ubSolClass == SOLDIER_CLASS_GREEN_MILITIA || ubSolClass == SOLDIER_CLASS_BANDIT )
iChance = 10 + ubProgress * 2 / 5; // 10-50% chance
// modify the chance by preset ini setting
@@ -5556,7 +5619,7 @@ BOOLEAN AssignTraitsToSoldier( SOLDIERTYPE *pSoldier, SOLDIERCREATE_STRUCT *pCre
iChance = 10 + ubProgress / 4; // 10-35% chance
else if ( ubSolClass == SOLDIER_CLASS_ARMY || ubSolClass == SOLDIER_CLASS_REG_MILITIA )
iChance = ubProgress / 5; // 0-20% chance
else if ( ubSolClass == SOLDIER_CLASS_ADMINISTRATOR || ubSolClass == SOLDIER_CLASS_GREEN_MILITIA )
else if ( ubSolClass == SOLDIER_CLASS_ADMINISTRATOR || ubSolClass == SOLDIER_CLASS_GREEN_MILITIA || ubSolClass == SOLDIER_CLASS_BANDIT )
iChance = 0; // 0% chance
// modify the chance by preset ini setting
@@ -5598,7 +5661,7 @@ BOOLEAN AssignTraitsToSoldier( SOLDIERTYPE *pSoldier, SOLDIERCREATE_STRUCT *pCre
iChance = 30 + ubProgress / 2; // 30-90% chance
else if ( ubSolClass == SOLDIER_CLASS_ARMY || ubSolClass == SOLDIER_CLASS_REG_MILITIA )
iChance = 10 + ubProgress / 2; // 10-60% chance
else if ( ubSolClass == SOLDIER_CLASS_ADMINISTRATOR || ubSolClass == SOLDIER_CLASS_GREEN_MILITIA )
else if ( ubSolClass == SOLDIER_CLASS_ADMINISTRATOR || ubSolClass == SOLDIER_CLASS_GREEN_MILITIA || ubSolClass == SOLDIER_CLASS_BANDIT )
iChance = ubProgress / 3; // 0-33% chance
// modify the chance by preset ini setting
+3
View File
@@ -481,6 +481,9 @@ SOLDIERTYPE* TacticalCreateCivilian( INT32 sGridNo, UINT8 usCivilianGroup, INT8
// Flugente: assassins are elite soldiers of the civ team that go hostile on a certain event, otherwise they just blend in
SOLDIERTYPE* TacticalCreateEnemyAssassin(UINT8 disguisetype);
SOLDIERTYPE* TacticalCreateBandit();
void CreateAssassin(UINT8 disguisetype);
// create a prisoner (in a prison cell) in the current sector
+130 -2
View File
@@ -59,6 +59,8 @@
#include "PreBattle Interface.h" // added by Flugente
#include "LuaInitNPCs.h" // added by Flugente
#include "Soldier macros.h" // added by Flugente
#include "Creature Spreading.h" // added by Flugente
BOOLEAN gfOriginalList = TRUE;
@@ -1105,6 +1107,7 @@ void AddSoldierInitListEnemyDefenceSoldiers( UINT8 ubTotalAdmin, UINT8 ubTotalTr
ubEliteBSlots++;
break;
case SOLDIER_CLASS_ADMINISTRATOR:
case SOLDIER_CLASS_BANDIT:
if( curr->pBasicPlacement->fPriorityExistance && curr->pDetailedPlacement )
ubAdminPDSlots++;
else if( curr->pBasicPlacement->fPriorityExistance )
@@ -1163,6 +1166,7 @@ void AddSoldierInitListEnemyDefenceSoldiers( UINT8 ubTotalAdmin, UINT8 ubTotalTr
switch( ubCurrClass )
{
case SOLDIER_CLASS_ADMINISTRATOR:
case SOLDIER_CLASS_BANDIT:
pCurrSlots = &ubAdminPDSlots;
pCurrTotal = &ubTotalAdmin;
break;
@@ -1229,6 +1233,7 @@ void AddSoldierInitListEnemyDefenceSoldiers( UINT8 ubTotalAdmin, UINT8 ubTotalTr
switch( ubCurrClass )
{
case SOLDIER_CLASS_ADMINISTRATOR:
case SOLDIER_CLASS_BANDIT:
pCurrSlots = &ubAdminPSlots;
pCurrTotal = &ubTotalAdmin;
break;
@@ -1285,6 +1290,7 @@ void AddSoldierInitListEnemyDefenceSoldiers( UINT8 ubTotalAdmin, UINT8 ubTotalTr
switch( ubCurrClass )
{
case SOLDIER_CLASS_ADMINISTRATOR:
case SOLDIER_CLASS_BANDIT:
pCurrSlots = &ubAdminDSlots;
pCurrTotal = &ubTotalAdmin;
break;
@@ -1389,12 +1395,13 @@ void AddSoldierInitListEnemyDefenceSoldiers( UINT8 ubTotalAdmin, UINT8 ubTotalTr
//ADD REMAINING PLACEMENTS WITH BASIC PLACEMENT INFORMATION
//we now have the numbers of available slots for each soldier class, so loop through three times
//and randomly choose some (or all) of the matching slots to fill. This is done randomly.
for( ubCurrClass = SOLDIER_CLASS_ADMINISTRATOR; ubCurrClass <= SOLDIER_CLASS_ARMY; ubCurrClass++ )
for( ubCurrClass = SOLDIER_CLASS_ADMINISTRATOR; ubCurrClass <= SOLDIER_CLASS_ARMY; ++ubCurrClass )
{
//First, prepare the counters.
switch( ubCurrClass )
{
case SOLDIER_CLASS_ADMINISTRATOR:
case SOLDIER_CLASS_BANDIT:
pCurrSlots = &ubAdminBSlots;
pCurrTotal = &ubTotalAdmin;
break;
@@ -1672,7 +1679,8 @@ void AddSoldierInitListMilitia( UINT8 ubNumGreen, UINT8 ubNumRegs, UINT8 ubNumEl
switch( curr->pBasicPlacement->ubSoldierClass )
{
case SOLDIER_CLASS_ELITE: ubEliteSlots++; break;
case SOLDIER_CLASS_ADMINISTRATOR: ubGreenSlots++; break;
case SOLDIER_CLASS_ADMINISTRATOR:
case SOLDIER_CLASS_BANDIT: ubGreenSlots++; break;
case SOLDIER_CLASS_ARMY: ubRegSlots++; break;
}
}
@@ -1693,6 +1701,7 @@ void AddSoldierInitListMilitia( UINT8 ubNumGreen, UINT8 ubNumRegs, UINT8 ubNumEl
switch( reorder[i] )
{
case SOLDIER_CLASS_ADMINISTRATOR:
case SOLDIER_CLASS_BANDIT:
pCurrSlots = &ubGreenSlots;
pCurrTotal = &ubNumGreen;
break;
@@ -1721,6 +1730,7 @@ void AddSoldierInitListMilitia( UINT8 ubNumGreen, UINT8 ubNumRegs, UINT8 ubNumEl
switch( reorder[i] )
{
case SOLDIER_CLASS_ADMINISTRATOR:
case SOLDIER_CLASS_BANDIT:
curr->pBasicPlacement->ubSoldierClass = SOLDIER_CLASS_GREEN_MILITIA;
break;
case SOLDIER_CLASS_ARMY:
@@ -2059,7 +2069,125 @@ void AddSoldierInitListCreatures( BOOLEAN fQueen, UINT8 ubNumLarvae, UINT8 ubNum
}
}
void AddSoldierInitListOtherCreatures( UINT8 usNum )
{
SOLDIERINITNODE *curr;
INT32 iRandom;
UINT8 ubFreeSlots;
BOOLEAN fDoPlacement;
UINT8 ubNumCreatures = usNum;
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String( "AddSoldierInitListBloodcats" ) );
SortSoldierInitList();
//First fill up only the priority existance slots (as long as the availability and bodytypes match)
curr = gSoldierInitHead;
while ( curr && curr->pBasicPlacement->fPriorityExistance && ubNumCreatures )
{
fDoPlacement = TRUE;
if ( curr->pBasicPlacement->bTeam == CREATURE_TEAM )
{
//Matching team, now check the soldier class...
switch ( guCreatureAttackType )
{
case CREATURE_ATTACK_TYPE_ZOMBIE:
if ( curr->pBasicPlacement->ubBodyType > REGFEMALE )
fDoPlacement = FALSE;
break;
case CREATURE_ATTACK_TYPE_BANDIT:
if ( curr->pBasicPlacement->ubBodyType > REGFEMALE )
fDoPlacement = FALSE;
break;
case CREATURE_ATTACK_TYPE_BLOODCAT:
if ( curr->pBasicPlacement->ubBodyType != BLOODCAT )
fDoPlacement = FALSE;
break;
}
break;
if ( fDoPlacement )
{
if ( AddPlacementToWorld( curr ) )
{
--ubNumCreatures;
}
else
return;
}
}
curr = curr->next;
}
if ( !ubNumCreatures )
return;
//Count how many free creature slots are left.
curr = gSoldierInitHead;
ubFreeSlots = 0;
while ( curr )
{
if ( !curr->pSoldier && curr->pBasicPlacement->bTeam == CREATURE_TEAM )
++ubFreeSlots;
curr = curr->next;
}
//Now, if we still have creatures to place, do so completely randomly, overriding priority
//placements, etc.
curr = gSoldierInitHead;
while ( curr && ubFreeSlots && ubNumCreatures )
{
if ( !curr->pSoldier && curr->pBasicPlacement->bTeam == CREATURE_TEAM )
{
//Randomly determine if we will use this slot; the more available slots in proportion to
//the number of enemies, the lower the chance of accepting the slot.
if ( ubFreeSlots <= ubNumCreatures || Random( ubFreeSlots ) < ubNumCreatures )
{
switch ( guCreatureAttackType )
{
case CREATURE_ATTACK_TYPE_ZOMBIE:
curr->pBasicPlacement->ubBodyType = Random( ADULTFEMALEMONSTER );
break;
case CREATURE_ATTACK_TYPE_BANDIT:
curr->pBasicPlacement->ubBodyType = Random( ADULTFEMALEMONSTER );
break;
case CREATURE_ATTACK_TYPE_BLOODCAT:
curr->pBasicPlacement->ubBodyType = BLOODCAT;
break;
}
break;
if ( curr->pDetailedPlacement )
{
//delete the detailed placement information.
MemFree( curr->pDetailedPlacement );
curr->pDetailedPlacement = NULL;
curr->pBasicPlacement->fDetailedPlacement = FALSE;
}
if ( AddPlacementToWorld( curr ) )
{
--ubNumCreatures;
}
else
{
return;
}
}
--ubFreeSlots;
//With the decrementing of the slot vars in this manner, the chances increase so that all slots
//will be full by the time the end of the list comes up.
}
curr = curr->next;
}
}
SOLDIERINITNODE* FindSoldierInitNodeWithProfileID( UINT16 usProfile );
SOLDIERINITNODE* FindSoldierInitNodeWithProfileID( UINT16 usProfile )
+1
View File
@@ -44,6 +44,7 @@ void AddSoldierInitListEnemyDefenceSoldiers( UINT8 ubTotalAdmin, UINT8 ubTotalTr
void AddSoldierInitListCreatures( BOOLEAN fQueen, UINT8 ubNumLarvae, UINT8 ubNumInfants,
UINT8 ubNumYoungMales, UINT8 ubNumYoungFemales, UINT8 ubNumAdultMales,
UINT8 ubNumAdultFemales );
void AddSoldierInitListOtherCreatures( UINT8 usNum );
void AddSoldierInitListMilitia( UINT8 ubNumGreen, UINT8 ubNumReg, UINT8 ubNumElites );
void AddSoldierInitListMilitiaOnEdge( UINT8 ubStrategicInsertionCode, UINT8 ubNumGreen, UINT8 ubNumReg, UINT8 ubNumElites );
+24 -49
View File
@@ -6477,7 +6477,7 @@ UINT32 CalcChanceToHitGun(SOLDIERTYPE *pSoldier, INT32 sGridNo, INT16 ubAimTime,
else if (pSoldier->ubSoldierClass == SOLDIER_CLASS_ELITE_MILITIA && gGameExternalOptions.sVeteranMilitiaCtHBonusPercent != 0)
iChance += ((iChance * gGameExternalOptions.sVeteranMilitiaCtHBonusPercent) /100);
// bonus for enemy
else if (pSoldier->ubSoldierClass == SOLDIER_CLASS_ADMINISTRATOR && gGameExternalOptions.sEnemyAdminCtHBonusPercent != 0)
else if ( (pSoldier->ubSoldierClass == SOLDIER_CLASS_ADMINISTRATOR || pSoldier->ubSoldierClass == SOLDIER_CLASS_BANDIT) && gGameExternalOptions.sEnemyAdminCtHBonusPercent != 0)
iChance += ((iChance * gGameExternalOptions.sEnemyAdminCtHBonusPercent) /100);
else if (pSoldier->ubSoldierClass == SOLDIER_CLASS_ARMY && gGameExternalOptions.sEnemyRegularCtHBonusPercent != 0)
iChance += ((iChance * gGameExternalOptions.sEnemyRegularCtHBonusPercent) /100);
@@ -9069,6 +9069,8 @@ INT32 HTHImpact( SOLDIERTYPE * pSoldier, SOLDIERTYPE * pTarget, INT32 iHitBy, BO
INT32 iImpact, iFluke, iBonus;
BOOLEAN autoresolve = IsAutoResolveActive();
// Flugente: check for underbarrel weapons and use that object if necessary (think of bayonets)
OBJECTTYPE* pObj = pSoldier->GetUsedWeapon( &(pSoldier->inv[HANDPOS]) );
@@ -9158,9 +9160,10 @@ INT32 HTHImpact( SOLDIERTYPE * pSoldier, SOLDIERTYPE * pTarget, INT32 iHitBy, BO
if ( HAS_SKILL_TRAIT( pSoldier, MARTIAL_ARTS_NT ) )
{
iBonus += ( gSkillTraitValues.ubMABonusDamageHandToHand * NUM_SKILL_TRAITS( pSoldier, MARTIAL_ARTS_NT ) );
}
}
// add bonus for focused punch
if (pSoldier->usAnimState == NINJA_SPINKICK || pSoldier->usAnimState == FOCUSED_PUNCH || pSoldier->usAnimState == FOCUSED_HTH_KICK )
if ( !autoresolve && (pSoldier->usAnimState == NINJA_SPINKICK || pSoldier->usAnimState == FOCUSED_PUNCH || pSoldier->usAnimState == FOCUSED_HTH_KICK) )
{
iBonus += 50;
@@ -9180,7 +9183,8 @@ INT32 HTHImpact( SOLDIERTYPE * pSoldier, SOLDIERTYPE * pTarget, INT32 iHitBy, BO
iBonus += ( gSkillTraitValues.ubMABonusDamageHandToHand * NUM_SKILL_TRAITS( pSoldier, MARTIAL_ARTS_NT ) );
// The Spinning kicks or aimed punch bonus - SANDRO
if (pSoldier->usAnimState == NINJA_SPINKICK || (pSoldier->aiData.bAimTime >= (gGameExternalOptions.fEnhancedCloseCombatSystem ? gSkillTraitValues.ubModifierForAPsAddedOnAimedPunches : 6)))
if ( !autoresolve &&
(pSoldier->usAnimState == NINJA_SPINKICK || (pSoldier->aiData.bAimTime >= (gGameExternalOptions.fEnhancedCloseCombatSystem ? gSkillTraitValues.ubModifierForAPsAddedOnAimedPunches : 6)) ))
{
//iImpact = (INT32)((iImpact * (100 + gSkillTraitValues.usMAAimedPunchDamageBonus * NUM_SKILL_TRAITS( pSoldier, MARTIAL_ARTS_NT ) ) / 100) + 0.5); // +75% damage per trait
iBonus += ( (gSkillTraitValues.ubMABonusDamageHandToHand + 25 )* NUM_SKILL_TRAITS( pSoldier, MARTIAL_ARTS_NT ) );
@@ -9196,28 +9200,31 @@ INT32 HTHImpact( SOLDIERTYPE * pSoldier, SOLDIERTYPE * pTarget, INT32 iHitBy, BO
iBonus += gSkillTraitValues.ubMEDamageBonusBlunt;
// bonus for aimed attack
if ( pSoldier->aiData.bAimTime >= (gGameExternalOptions.fEnhancedCloseCombatSystem ? gSkillTraitValues.ubModifierForAPsAddedOnAimedBladedAttackes : 6) )
if ( !autoresolve && pSoldier->aiData.bAimTime >= (gGameExternalOptions.fEnhancedCloseCombatSystem ? gSkillTraitValues.ubModifierForAPsAddedOnAimedBladedAttackes : 6) )
{
iBonus += gSkillTraitValues.usMEAimedMeleeAttackDamageBonus; // incresed damage if focused melee attack
iBonus += gSkillTraitValues.usMEAimedMeleeAttackDamageBonus; // incresed damage if focused melee attack
}
}
}
}
else // original code
{
if ( gGameExternalOptions.fEnhancedCloseCombatSystem && (pSoldier->usAnimState == NINJA_SPINKICK || pSoldier->usAnimState == FOCUSED_PUNCH || pSoldier->usAnimState == FOCUSED_HTH_KICK ))
if ( !autoresolve && gGameExternalOptions.fEnhancedCloseCombatSystem && (pSoldier->usAnimState == NINJA_SPINKICK || pSoldier->usAnimState == FOCUSED_PUNCH || pSoldier->usAnimState == FOCUSED_HTH_KICK ))
{
iBonus += 50;
}
// add bonuses for hand-to-hand and martial arts
if ( HAS_SKILL_TRAIT( pSoldier, MARTIALARTS_OT ) )
{
iBonus += gbSkillTraitBonus[MARTIALARTS_OT] * NUM_SKILL_TRAITS( pSoldier, MARTIALARTS_OT );
if (pSoldier->usAnimState == NINJA_SPINKICK)
if ( !autoresolve && pSoldier->usAnimState == NINJA_SPINKICK)
{
iBonus += 100;
}
}
if ( HAS_SKILL_TRAIT( pSoldier, HANDTOHAND_OT ) )
{
// SPECIAL - give TRIPLE bonus for damage for hand-to-hand trait
@@ -9227,7 +9234,7 @@ INT32 HTHImpact( SOLDIERTYPE * pSoldier, SOLDIERTYPE * pTarget, INT32 iHitBy, BO
}
// Enhanced Close Combat System - aiming at body parts makes difference
if (gGameExternalOptions.fEnhancedCloseCombatSystem)
if ( !autoresolve && gGameExternalOptions.fEnhancedCloseCombatSystem)
{
if ( pSoldier->bAimShotLocation == AIM_SHOT_HEAD )
{
@@ -9251,22 +9258,6 @@ INT32 HTHImpact( SOLDIERTYPE * pSoldier, SOLDIERTYPE * pTarget, INT32 iHitBy, BO
iBonus += 50; // 50% incresed damage on suprising attacks
}
}
// Flugente: power armour reduces damage taken
// SANDRO - huh?!
/*INT8 iSlot = VESTPOS;
switch( pSoldier->bAimShotLocation )
{
case AIM_SHOT_HEAD:
iSlot = HELMETPOS;
break;
case AIM_SHOT_LEGS:
iSlot = LEGPOS;
break;
default:
iSlot = VESTPOS;
break;
}*/
}
// DAMAGE BONUS TO KNIFE ATTACK WITH MELEE SKILL
else
@@ -9277,42 +9268,27 @@ INT32 HTHImpact( SOLDIERTYPE * pSoldier, SOLDIERTYPE * pTarget, INT32 iHitBy, BO
iBonus += gSkillTraitValues.ubMEDamageBonusBlades; // +30% damage
// if this attack happens directly after running, the attack is slightly more powerful due to extra force
if (pSoldier->usSoldierFlagMask2 & SOLDIER_BAYONET_RUNBONUS)
if ( !autoresolve && pSoldier->usSoldierFlagMask2 & SOLDIER_BAYONET_RUNBONUS)
iBonus += 20;
}
else if ( HAS_SKILL_TRAIT( pSoldier, MELEE_NT ) && ( gGameOptions.fNewTraitSystem ))
{
iBonus += gSkillTraitValues.ubMEDamageBonusBlades; // +30% damage
if (pSoldier->usAnimState == FOCUSED_STAB)
if ( !autoresolve && pSoldier->usAnimState == FOCUSED_STAB)
{
iBonus += gSkillTraitValues.usMEAimedMeleeAttackDamageBonus; // 50% increased damage if focused melee attack
}
}
// Enhanced Close Combat System
if (gGameExternalOptions.fEnhancedCloseCombatSystem)
if ( !autoresolve && gGameExternalOptions.fEnhancedCloseCombatSystem)
{
if (gAnimControl[ pTarget->usAnimState ].ubEndHeight == ANIM_PRONE)
{
iBonus += 30; // incresed damage to lying characters
}
}
// Flugente: power armour reduces damage taken
// SANDRO - huh?!
/*INT8 iSlot = VESTPOS;
switch( pSoldier->bAimShotLocation )
{
case AIM_SHOT_HEAD:
iSlot = HELMETPOS;
break;
case AIM_SHOT_LEGS:
iSlot = LEGPOS;
break;
default:
iSlot = VESTPOS;
break;
}*/
}
// remove flag, regardless of whether it was used
@@ -9326,7 +9302,7 @@ INT32 HTHImpact( SOLDIERTYPE * pSoldier, SOLDIERTYPE * pTarget, INT32 iHitBy, BO
// Flugente: if we are using a garotte, there is a chance that we score an instakill
// our level in covert ops and wether the target is aware of us has a huge impact
if ( pObj && HasItemFlag(pObj->usItem, GAROTTE) )
if ( !autoresolve && pObj && HasItemFlag(pObj->usItem, GAROTTE) )
{
INT32 instakillchance = 0;
INT32 resistchance = 20;
@@ -9356,7 +9332,6 @@ INT32 HTHImpact( SOLDIERTYPE * pSoldier, SOLDIERTYPE * pTarget, INT32 iHitBy, BO
iImpact = (iImpact * (100 + iBonus) + 50) / 100; // round it properly
// Flugente: moved the damage calculation into a separate function
BOOLEAN autoresolve = IsAutoResolveActive();
iImpact = max( 1, (INT32)(iImpact * (100 - pTarget->GetDamageResistance(autoresolve, FALSE)) / 100 ) );
// Flugente: if the target is a zombie, any melee attack, regardless of hit location, will set the headshot flag. Thus any zombie killed in melee will stay dead (if you play with that option)
@@ -10068,7 +10043,7 @@ UINT32 CalcChanceHTH( SOLDIERTYPE * pAttacker,SOLDIERTYPE *pDefender, INT16 ubAi
else if (pAttacker->ubSoldierClass == SOLDIER_CLASS_ELITE_MILITIA && gGameExternalOptions.sVeteranMilitiaCtHBonusPercent != 0)
iChance += ((iChance * gGameExternalOptions.sVeteranMilitiaCtHBonusPercent) /100);
// bonus for enemy
else if (pAttacker->ubSoldierClass == SOLDIER_CLASS_ADMINISTRATOR && gGameExternalOptions.sEnemyAdminCtHBonusPercent != 0)
else if ( ( pAttacker->ubSoldierClass == SOLDIER_CLASS_ADMINISTRATOR || pAttacker->ubSoldierClass == SOLDIER_CLASS_BANDIT ) && gGameExternalOptions.sEnemyAdminCtHBonusPercent != 0)
iChance += ((iChance * gGameExternalOptions.sEnemyAdminCtHBonusPercent) /100);
else if (pAttacker->ubSoldierClass == SOLDIER_CLASS_ARMY && gGameExternalOptions.sEnemyRegularCtHBonusPercent != 0)
iChance += ((iChance * gGameExternalOptions.sEnemyRegularCtHBonusPercent) /100);
@@ -10746,7 +10721,7 @@ UINT32 CalcThrownChanceToHit(SOLDIERTYPE *pSoldier, INT32 sGridNo, INT16 ubAimTi
else if (pSoldier->ubSoldierClass == SOLDIER_CLASS_ELITE_MILITIA && gGameExternalOptions.sVeteranMilitiaCtHBonusPercent != 0)
iChance += ((iChance * gGameExternalOptions.sVeteranMilitiaCtHBonusPercent) /100);
// bonus for enemy
else if (pSoldier->ubSoldierClass == SOLDIER_CLASS_ADMINISTRATOR && gGameExternalOptions.sEnemyAdminCtHBonusPercent != 0)
else if ( ( pSoldier->ubSoldierClass == SOLDIER_CLASS_ADMINISTRATOR || pSoldier->ubSoldierClass == SOLDIER_CLASS_BANDIT ) && gGameExternalOptions.sEnemyAdminCtHBonusPercent != 0)
iChance += ((iChance * gGameExternalOptions.sEnemyAdminCtHBonusPercent) /100);
else if (pSoldier->ubSoldierClass == SOLDIER_CLASS_ARMY && gGameExternalOptions.sEnemyRegularCtHBonusPercent != 0)
iChance += ((iChance * gGameExternalOptions.sEnemyRegularCtHBonusPercent) /100);
@@ -11801,7 +11776,7 @@ FLOAT CalcNewChanceToHitBaseSpecialBonus(SOLDIERTYPE *pSoldier)
else if (pSoldier->ubSoldierClass == SOLDIER_CLASS_ELITE_MILITIA && gGameExternalOptions.sVeteranMilitiaCtHBonusPercent != 0)
fBaseModifier += gGameExternalOptions.sVeteranMilitiaCtHBonusPercent;
// bonus for enemy
else if (pSoldier->ubSoldierClass == SOLDIER_CLASS_ADMINISTRATOR && gGameExternalOptions.sEnemyAdminCtHBonusPercent != 0)
else if ( ( pSoldier->ubSoldierClass == SOLDIER_CLASS_ADMINISTRATOR || pSoldier->ubSoldierClass == SOLDIER_CLASS_BANDIT ) && gGameExternalOptions.sEnemyAdminCtHBonusPercent != 0)
fBaseModifier += gGameExternalOptions.sEnemyAdminCtHBonusPercent;
else if (pSoldier->ubSoldierClass == SOLDIER_CLASS_ARMY && gGameExternalOptions.sEnemyRegularCtHBonusPercent != 0)
fBaseModifier += gGameExternalOptions.sEnemyRegularCtHBonusPercent;
+15 -14
View File
@@ -4870,18 +4870,19 @@ void DebugSoldierPage4( )
switch( pSoldier->ubSoldierClass )
{
case SOLDIER_CLASS_ADMINISTRATOR: gprintf( 320, LINE_HEIGHT * ubLine, L"(Administrator)" ); break;
case SOLDIER_CLASS_ELITE: gprintf( 320, LINE_HEIGHT * ubLine, L"(Army Elite)" ); break;
case SOLDIER_CLASS_ARMY: gprintf( 320, LINE_HEIGHT * ubLine, L"(Army Troop)" ); break;
case SOLDIER_CLASS_CREATURE: gprintf( 320, LINE_HEIGHT * ubLine, L"(Creature)" ); break;
case SOLDIER_CLASS_ELITE: gprintf( 320, LINE_HEIGHT * ubLine, L"(Army Elite)" ); break;
case SOLDIER_CLASS_ARMY: gprintf( 320, LINE_HEIGHT * ubLine, L"(Army Troop)" ); break;
case SOLDIER_CLASS_CREATURE: gprintf( 320, LINE_HEIGHT * ubLine, L"(Creature)" ); break;
case SOLDIER_CLASS_GREEN_MILITIA: gprintf( 320, LINE_HEIGHT * ubLine, L"(Green Militia)" ); break;
case SOLDIER_CLASS_REG_MILITIA: gprintf( 320, LINE_HEIGHT * ubLine, L"(Reg Militia)" ); break;
case SOLDIER_CLASS_ELITE_MILITIA: gprintf( 320, LINE_HEIGHT * ubLine, L"(Elite Militia)" ); break;
case SOLDIER_CLASS_MINER: gprintf( 320, LINE_HEIGHT * ubLine, L"(Miner)" ); break;
case SOLDIER_CLASS_ZOMBIE: gprintf( 320, LINE_HEIGHT * ubLine, L"(Zombie)" ); break;
case SOLDIER_CLASS_MINER: gprintf( 320, LINE_HEIGHT * ubLine, L"(Miner)" ); break;
case SOLDIER_CLASS_ZOMBIE: gprintf( 320, LINE_HEIGHT * ubLine, L"(Zombie)" ); break;
case SOLDIER_CLASS_BANDIT: gprintf( 320, LINE_HEIGHT * ubLine, L"(Bandit)" ); break;
default: break; //don't care (don't write anything)
}
ubLine++;
++ubLine;
if( pSoldier->bTeam != OUR_TEAM )
{
@@ -7785,19 +7786,19 @@ void MakeBloodcatsHostile( void )
iLoop = gTacticalStatus.Team[ CREATURE_TEAM ].bFirstID;
for (pSoldier = MercPtrs[iLoop]; iLoop <= gTacticalStatus.Team[ CREATURE_TEAM ].bLastID; iLoop++,pSoldier++ )
for (pSoldier = MercPtrs[iLoop]; iLoop <= gTacticalStatus.Team[ CREATURE_TEAM ].bLastID; ++iLoop, ++pSoldier )
{
if ( pSoldier->ubBodyType == BLOODCAT && pSoldier->bActive && pSoldier->bInSector && pSoldier->stats.bLife > 0 )
{
SetSoldierNonNeutral( pSoldier );
RecalculateOppCntsDueToNoLongerNeutral( pSoldier );
if ( ( gTacticalStatus.uiFlags & INCOMBAT ) )
{
CheckForPotentialAddToBattleIncrement( pSoldier );
}
SetSoldierNonNeutral( pSoldier );
RecalculateOppCntsDueToNoLongerNeutral( pSoldier );
if ( ( gTacticalStatus.uiFlags & INCOMBAT ) )
{
CheckForPotentialAddToBattleIncrement( pSoldier );
}
}
}
}
BOOLEAN SoldierHasLimitedVision(SOLDIERTYPE * pSoldier)