- Made the "Zombie MOD" optional, so we can decide if we like to build an executable with/without the appearance of zombies

o See: builddefines.h: #define ENABLE_ZOMBIES (then you can turn on/off Zombies in the ingame option screen)
o Poison system is still in the code and not combined with the option "Zombie MOD"
o Gamers reported on the Bears Pit, that an executable compiled WITH the Zombies mod enabled makes the game unplayable slow in tactical screen after a few minutes in turn based/realtime



git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@5356 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
Wanne
2012-07-04 10:30:13 +00:00
parent e8027d6663
commit f40e7fb118
42 changed files with 2827 additions and 2479 deletions
+2
View File
@@ -1035,9 +1035,11 @@ void StartEnemyTaunt( SOLDIERTYPE *pCiv, INT8 iTauntType )
VIDEO_OVERLAY_DESC VideoOverlayDesc;
CHAR16 gzTauntQuote[ 320 ];
#ifdef ENABLE_ZOMBIES
// Flugente: zombies don't talk
if ( pCiv->IsZombie() )
return;
#endif
// if we have a different quote on, return, this one is not important
if ( gCivQuoteData.bActive )
+30 -25
View File
@@ -1926,13 +1926,8 @@ void InternalInitEDBTooltipRegion( OBJECTTYPE * gpItemDescObject, UINT32 guiCurr
}
}
if ( gGameSettings.fOptions[TOPTION_ZOMBIES] ) // Flugente Zombies
{
//////////////////// POISON PERCENTAGE
{
MSYS_EnableRegion( &gUDBFasthelpRegions[ iFirstDataRegion + 4 ] );
}
}
//////////////////// POISON PERCENTAGE
MSYS_EnableRegion( &gUDBFasthelpRegions[ iFirstDataRegion + 4 ] );
}
}
@@ -3864,10 +3859,11 @@ void InternalInitEDBTooltipRegion( OBJECTTYPE * gpItemDescObject, UINT32 guiCurr
}
}
}
//#ifdef ENABLE_ZOMBIES
// Flugente Zombies
if ( gGameSettings.fOptions[TOPTION_ZOMBIES] )
{
//if ( gGameSettings.fOptions[TOPTION_ZOMBIES] )
//{
if(!cnt) cnt += 2;
if (cnt >= sFirstLine && cnt < sLastLine)
@@ -3908,7 +3904,8 @@ void InternalInitEDBTooltipRegion( OBJECTTYPE * gpItemDescObject, UINT32 guiCurr
}
cnt++;
}
}
//}
//#endif
gubDescBoxTotalAdvLines = (UINT8)cnt;
}
@@ -4304,13 +4301,15 @@ void DrawAmmoStats( OBJECTTYPE * gpItemDescObject )
BltVideoObjectFromIndex( guiSAVEBUFFER, guiItemInfoAmmoIcon, 16, gItemDescGenRegions[3][0].sLeft+sOffsetX, gItemDescGenRegions[3][0].sTop+sOffsetY, VO_BLT_SRCTRANSPARENCY, NULL );
}
}
if ( gGameSettings.fOptions[TOPTION_ZOMBIES] ) // Flugente Zombies
{
//#ifdef ENABLE_ZOMBIES
//if ( gGameSettings.fOptions[TOPTION_ZOMBIES] ) // Flugente Zombies
//{
//////////////// POISON PERCENTAGE
{
//{
BltVideoObjectFromIndex( guiSAVEBUFFER, guiItemInfoWH40KIcon, 6, gItemDescGenRegions[4][0].sLeft+sOffsetX, gItemDescGenRegions[4][0].sTop+sOffsetY, VO_BLT_SRCTRANSPARENCY, NULL );
}
}
//}
//}
//#endif
DrawSecondaryStats( gpItemDescObject );
}
@@ -5198,9 +5197,10 @@ void DrawAdvancedStats( OBJECTTYPE * gpItemDescObject )
}
}
//#ifdef ENABLE_ZOMBIES
// Flugente Zombies
if ( gGameSettings.fOptions[TOPTION_ZOMBIES] )
{
// if ( gGameSettings.fOptions[TOPTION_ZOMBIES] )
// {
if(!cnt) cnt += 2;
++cnt; // for the new index-line
@@ -5215,7 +5215,8 @@ void DrawAdvancedStats( OBJECTTYPE * gpItemDescObject )
}
cnt++;
}
}
//}
//#endif
}
void DrawMiscStats( OBJECTTYPE * gpItemDescObject )
@@ -7597,8 +7598,9 @@ void DrawAmmoValues( OBJECTTYPE * gpItemDescObject, int shotsLeft )
mprintf( usX, usY, pStr );
}
if ( gGameSettings.fOptions[TOPTION_ZOMBIES] ) // Flugente Zombies
{
//#ifdef ENABLE_ZOMBIES
// if ( gGameSettings.fOptions[TOPTION_ZOMBIES] ) // Flugente Zombies
// {
///////////////////// POISON PERCENTAGE
// Set line to draw into
ubNumLine = 4;
@@ -7648,7 +7650,8 @@ void DrawAmmoValues( OBJECTTYPE * gpItemDescObject, int shotsLeft )
swprintf( pStr, L"%d", finalvalue );
FindFontCenterCoordinates( sLeft, sTop, sWidth, sHeight, pStr, BLOCKFONT2, &usX, &usY);
mprintf( usX, usY, pStr );
}
// }
//#endif
}
else if (gubDescBoxPage == 2)
{
@@ -11170,8 +11173,9 @@ void DrawAdvancedValues( OBJECTTYPE *gpItemDescObject )
}
// Flugente Zombies
if ( gGameSettings.fOptions[TOPTION_ZOMBIES] )
{
//#ifdef USE_ZOMBIES
// if ( gGameSettings.fOptions[TOPTION_ZOMBIES] )
//{
///////////////////////////////////////////////////// INDEXES
if(!cnt) cnt += 2;
@@ -11252,7 +11256,8 @@ void DrawAdvancedValues( OBJECTTYPE *gpItemDescObject )
}
cnt++;
}
}
//}
//#endif
}
void DrawMiscValues( OBJECTTYPE * gpItemDescObject )
+2
View File
@@ -2211,6 +2211,7 @@ void DrawSelectedUIAboveGuy( UINT16 usSoldierID )
}
}
#ifdef ENABLE_ZOMBIES
if ( pSoldier->IsZombie() )
{
swprintf(NameStr, pSoldier->name);
@@ -2225,6 +2226,7 @@ void DrawSelectedUIAboveGuy( UINT16 usSoldierID )
gprintfdirty( sX, sY, NameStr );
mprintf( sX, sY, NameStr );
}
#endif
//------------
}
}
+8
View File
@@ -847,9 +847,11 @@ void GenerateRandomEquipment( SOLDIERCREATE_STRUCT *pp, INT8 bSoldierClass, INT8
}
break;
#ifdef ENABLE_ZOMBIES
case SOLDIER_CLASS_ZOMBIE:
// zombies get no items at all...
break;
#endif
}
for ( i = 0; i < pp->Inv.size(); i++ )
@@ -1056,8 +1058,11 @@ void ChooseWeaponForSoldierCreateStruct( SOLDIERCREATE_STRUCT *pp, INT8 bWeaponC
bStatus += (INT8)(HighestPlayerProgressPercentage() / 10);
bStatus = (INT8)min( 100, bStatus );
break;
#ifdef ENABLE_ZOMBIES
case SOLDIER_CLASS_ZOMBIE:
bStatus = (INT8)(1); // if a zombie gets anything, it'll be broken
#endif
default:
bStatus = (INT8)(50 + Random( 51 ) );
break;
@@ -2111,8 +2116,11 @@ void ChooseFaceGearForSoldierCreateStruct( SOLDIERCREATE_STRUCT *pp )
break;
case SOLDIER_CLASS_ADMINISTRATOR:
case SOLDIER_CLASS_GREEN_MILITIA:
#ifdef ENABLE_ZOMBIES
case SOLDIER_CLASS_ZOMBIE:
#endif
break;
}
}
+4
View File
@@ -907,8 +907,12 @@ void HandleFirstHeliDropOfGame( )
{
// Say quote.....
SayQuoteFromAnyBodyInSector( QUOTE_ENEMY_PRESENCE );
// Start music
#ifdef ENABLE_ZOMBIES
UseCreatureMusic(HostileZombiesPresent());
#endif
SetMusicMode( MUSIC_TACTICAL_ENEMYPRESENT );
}
else
+50 -32
View File
@@ -6186,7 +6186,10 @@ void ExitCombatMode( )
// unused
//gfForceMusicToTense = TRUE;
#ifdef ENABLE_ZOMBIES
UseCreatureMusic(HostileZombiesPresent());
#endif
SetMusicMode( MUSIC_TACTICAL_ENEMYPRESENT );
BetweenTurnsVisibilityAdjustments();
@@ -6245,7 +6248,11 @@ void SetEnemyPresence( )
#endif
{
#ifdef ENABLE_ZOMBIES
UseCreatureMusic(HostileZombiesPresent());
#endif
SetMusicMode( MUSIC_TACTICAL_ENEMYPRESENT );
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("SetEnemyPresence: warnings = false"));
sniperwarning = FALSE;
@@ -6583,7 +6590,10 @@ BOOLEAN CheckForEndOfCombatMode( BOOLEAN fIncrementTurnsNotSeen )
// Begin tense music....
// unused
//gfForceMusicToTense = TRUE;
#ifdef ENABLE_ZOMBIES
UseCreatureMusic(HostileZombiesPresent());
#endif
SetMusicMode( MUSIC_TACTICAL_ENEMYPRESENT );
return( TRUE );
@@ -6682,8 +6692,10 @@ BOOLEAN CheckForEndOfBattle( BOOLEAN fAnEnemyRetreated )
return( FALSE );
}
#ifdef ENABLE_ZOMBIES
if ( HostileZombiesPresent() ) //Madd: got tired of the victory music playing right after the zombies arose
return FALSE;
#endif
// OK, this is to releave infinate looping...becasue we can kill guys in this function
if ( gfKillingGuysForLosingBattle )
@@ -7267,25 +7279,27 @@ UINT8 NumEnemyInSector( )
}
UINT8 NumZombiesInSector( )
{
SOLDIERTYPE *pTeamSoldier;
INT32 cnt = 0;
UINT8 ubNumZombies = 0;
for ( pTeamSoldier = Menptr, cnt = 0; cnt < TOTAL_SOLDIERS; ++pTeamSoldier, ++cnt )
#ifdef ENABLE_ZOMBIES
UINT8 NumZombiesInSector( )
{
if ( pTeamSoldier->bActive && pTeamSoldier->bInSector && pTeamSoldier->stats.bLife > 0 )
SOLDIERTYPE *pTeamSoldier;
INT32 cnt = 0;
UINT8 ubNumZombies = 0;
for ( pTeamSoldier = Menptr, cnt = 0; cnt < TOTAL_SOLDIERS; ++pTeamSoldier, ++cnt )
{
if ( pTeamSoldier->IsZombie() )
if ( pTeamSoldier->bActive && pTeamSoldier->bInSector && pTeamSoldier->stats.bLife > 0 )
{
++ubNumZombies;
if ( pTeamSoldier->IsZombie() )
{
++ubNumZombies;
}
}
}
}
return( ubNumZombies );
}
return( ubNumZombies );
}
#endif
UINT8 NumEnemyInSectorExceptCreatures()
{
@@ -7799,9 +7813,11 @@ void HandleSuppressionFire( UINT8 ubTargetedMerc, UINT8 ubCausedAttacker )
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("HandleSuppressionFire: loop = %d, numslots = %d ",uiLoop, guiNumMercSlots));
pSoldier = MercSlots[uiLoop];
#ifdef ENABLE_ZOMBIES
// Flugente: zombies do not receive any suppression at all!
if ( pSoldier != NULL && pSoldier->IsZombie() )
continue;
#endif
// Has this character received any Suppression Points since the last attack?
// HEADROCK: Suppression Points accumulate by bullets flying near the character. It includes
@@ -9286,28 +9302,30 @@ BOOLEAN HostileBloodcatsPresent( void )
return( FALSE );
}
BOOLEAN HostileZombiesPresent( void )
{
INT32 iLoop;
SOLDIERTYPE * pSoldier;
if ( gTacticalStatus.Team[ CREATURE_TEAM ].bTeamActive == FALSE )
#ifdef ENABLE_ZOMBIES
BOOLEAN HostileZombiesPresent( void )
{
INT32 iLoop;
SOLDIERTYPE * pSoldier;
if ( gTacticalStatus.Team[ CREATURE_TEAM ].bTeamActive == FALSE )
{
return( FALSE );
}
for ( iLoop = gTacticalStatus.Team[ CREATURE_TEAM ].bFirstID; iLoop <= gTacticalStatus.Team[ CREATURE_TEAM ].bLastID; iLoop++ )
{
pSoldier = MercPtrs[ iLoop ];
if ( pSoldier->bActive && pSoldier->bInSector && pSoldier->stats.bLife > 0 && pSoldier->IsZombie() )
{
return( TRUE );
}
}
return( FALSE );
}
for ( iLoop = gTacticalStatus.Team[ CREATURE_TEAM ].bFirstID; iLoop <= gTacticalStatus.Team[ CREATURE_TEAM ].bLastID; iLoop++ )
{
pSoldier = MercPtrs[ iLoop ];
if ( pSoldier->bActive && pSoldier->bInSector && pSoldier->stats.bLife > 0 && pSoldier->IsZombie() )
{
return( TRUE );
}
}
return( FALSE );
}
#endif
void HandleCreatureTenseQuote( )
{
+9 -3
View File
@@ -362,7 +362,10 @@ void DoPOWPathChecks( void );
BOOLEAN HostileCiviliansWithGunsPresent( void );
BOOLEAN HostileCiviliansPresent( void );
BOOLEAN HostileBloodcatsPresent( void );
BOOLEAN HostileZombiesPresent( void );
#ifdef ENABLE_ZOMBIES
BOOLEAN HostileZombiesPresent( void );
#endif
UINT8 NumPCsInSector( void );
@@ -396,6 +399,9 @@ BOOLEAN WillAirRaidBeStopped( INT16 sSectorX, INT16 sSectorY );
// HEADROCK HAM 3.5: Externalized for First Arrival enemy check
extern UINT8 NumEnemyInSector();
// Flugente
extern UINT8 NumZombiesInSector();
#ifdef ENABLE_ZOMBIES
// Flugente
extern UINT8 NumZombiesInSector();
#endif
#endif
+395 -383
View File
@@ -44,8 +44,7 @@
#include "qarray.h"
#include "Interface.h"
#include "Music Control.h"
#include "Campaign Types.h"
//#include "Queen Command.h"
#include "Campaign Types.h"
#include "text.h" // added by Flugente
#endif
@@ -584,9 +583,11 @@ INT32 AddRottingCorpse( ROTTING_CORPSE_DEFINITION *pCorpseDef )
pCorpse->pAniTile->uiUserData = iIndex;
pCorpse->iID = iIndex;
#ifdef ENABLE_ZOMBIES
// copy name of corpse definition...
memcpy( &(pCorpse->name), &(pCorpseDef->name), sizeof(CHAR16) * 10 );
pCorpse->name[9] = '\0';
#endif
pCorpse->fActivated = TRUE;
@@ -861,6 +862,7 @@ BOOLEAN TurnSoldierIntoCorpse( SOLDIERTYPE *pSoldier, BOOLEAN fRemoveMerc, BOOLE
Corpse.usFlags |= ROTTING_CORPSE_USE_SNOW_CAMO_PALETTE;
}
#ifdef ENABLE_ZOMBIES
// Flugente Zombies: Determine if a zombie can rise from this corpse
switch ( gGameExternalOptions.sZombieRiseBehaviour )
{
@@ -891,6 +893,7 @@ BOOLEAN TurnSoldierIntoCorpse( SOLDIERTYPE *pSoldier, BOOLEAN fRemoveMerc, BOOLE
// Flugente: copy name of soldier...
memcpy( &(Corpse.name), &(pSoldier->name), sizeof(CHAR16) * 10 );
Corpse.name[9] = '\0';
#endif
// Determine corpse type!
ubType = (UINT8)gubAnimSurfaceCorpseID[ pSoldier->ubBodyType][ pSoldier->usAnimState ];
@@ -2085,436 +2088,445 @@ UINT8 GetNearestRottingCorpseAIWarning( INT32 sGridNo )
return( ubHighestWarning );
}
// Flugente Zombies: resurrect zombies
void RaiseZombies( void )
{
if ( gGameSettings.fOptions[TOPTION_ZOMBIES] )
#ifdef ENABLE_ZOMBIES
// Flugente Zombies: resurrect zombies
void RaiseZombies( void )
{
// if gGameExternalOptions.fZombieSpawnWaves is true, zombies will spawn from all corpses (while there is still room for more), creating a wave of zombies. with lots of bodies lying around, this can be a lot.
// if GameExternalOptions.fZombieSpawnWaves is false, each zombie can spawn randomly, you will get zombies on msot turns, but they won't spawn a whole horde at once
if ( ( gGameExternalOptions.fZombieSpawnWaves && (INT8) ( Random( 100 ) ) > 100 - gGameExternalOptions.sZombieRiseWaveFrequency ) || !gGameExternalOptions.fZombieSpawnWaves )
if ( gGameSettings.fOptions[TOPTION_ZOMBIES] )
{
ROTTING_CORPSE * pCorpse;
BOOLEAN zombieshaverisen = FALSE;
SECTORINFO *pSector = &SectorInfo[ SECTOR( gWorldSectorX, gWorldSectorY ) ];
for ( INT32 cnt = giNumRottingCorpse - 1; cnt >= 0; --cnt )
// if gGameExternalOptions.fZombieSpawnWaves is true, zombies will spawn from all corpses (while there is still room for more), creating a wave of zombies. with lots of bodies lying around, this can be a lot.
// if GameExternalOptions.fZombieSpawnWaves is false, each zombie can spawn randomly, you will get zombies on msot turns, but they won't spawn a whole horde at once
if ( ( gGameExternalOptions.fZombieSpawnWaves && (INT8) ( Random( 100 ) ) > 100 - gGameExternalOptions.sZombieRiseWaveFrequency ) || !gGameExternalOptions.fZombieSpawnWaves )
{
if ( pSector->ubNumCreatures < gGameExternalOptions.ubGameMaximumNumberOfCreatures ) // ... if there is still room for more zombies (zombies count as creatures until a separate ZOMBIE_TEAM is implemented)...
ROTTING_CORPSE * pCorpse;
BOOLEAN zombieshaverisen = FALSE;
SECTORINFO *pSector = &SectorInfo[ SECTOR( gWorldSectorX, gWorldSectorY ) ];
for ( INT32 cnt = giNumRottingCorpse - 1; cnt >= 0; --cnt )
{
pCorpse = &(gRottingCorpse[ cnt ] );
// if zombies should spawn individually, roll for every corpse individually
if ( gGameExternalOptions.fZombieSpawnWaves || ( !gGameExternalOptions.fZombieSpawnWaves && (INT8) ( Random( 100 ) ) > 100 - gGameExternalOptions.sZombieRiseWaveFrequency ) )
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 ( pCorpse->fActivated && pCorpse->def.fHeadTaken == FALSE ) // ... if corpse is active, and still has a head ...
pCorpse = &(gRottingCorpse[ cnt ] );
// if zombies should spawn individually, roll for every corpse individually
if ( gGameExternalOptions.fZombieSpawnWaves || ( !gGameExternalOptions.fZombieSpawnWaves && (INT8) ( Random( 100 ) ) > 100 - gGameExternalOptions.sZombieRiseWaveFrequency ) )
{
if ( !(pCorpse->def.usFlags & ROTTING_CORPSE_NEVER_RISE_AGAIN) ) // ... if corpse is already that of a zombie, don't create zombie again ...
if ( pCorpse->fActivated && pCorpse->def.fHeadTaken == FALSE ) // ... if corpse is active, and still has a head ...
{
if ( !TileIsOutOfBounds(pCorpse->def.sGridNo) ) // ... if corpse is on existing coordinates ...
{
if ( WhoIsThere2( pCorpse->def.sGridNo, pCorpse->def.bLevel ) == NOBODY ) // ... if nobody else is on that position ...
{
UINT16 recanimstate = STANDING;
if ( !(pCorpse->def.usFlags & ROTTING_CORPSE_NEVER_RISE_AGAIN) ) // ... if corpse is already that of a zombie, don't create zombie again ...
{
if ( !TileIsOutOfBounds(pCorpse->def.sGridNo) ) // ... if corpse is on existing coordinates ...
{
if ( WhoIsThere2( pCorpse->def.sGridNo, pCorpse->def.bLevel ) == NOBODY ) // ... if nobody else is on that position ...
{
UINT16 recanimstate = STANDING;
if ( CorpseOkToSpawnZombie( pCorpse, &recanimstate ) ) // ... a zombie can be created from this corpse, in the corresponding animstate ...
{
zombieshaverisen = TRUE;
CreateZombiefromCorpse( pCorpse, recanimstate );
if ( CorpseOkToSpawnZombie( pCorpse, &recanimstate ) ) // ... a zombie can be created from this corpse, in the corresponding animstate ...
{
zombieshaverisen = TRUE;
CreateZombiefromCorpse( pCorpse, recanimstate );
//++pSector->ubNumZombies;
//++pSector->ubZombiesInBattle;
//++pSector->ubNumZombies;
//++pSector->ubZombiesInBattle;
RemoveCorpse( cnt );
RemoveCorpse( cnt );
}
}
}
}
}
}
}
else
{
// if there is no more room, we can skip this
break;
}
}
else
if ( zombieshaverisen )
{
// if there is no more room, we can skip this
break;
SetRenderFlags( RENDER_FLAG_FULL );
#ifdef JA2TESTVERSION
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_BETAVERSION, L"A wave of zombies is created");
#endif
// Play sound
PlayJA2SampleFromFile( "Sounds\\zombie1.wav", RATE_11025, HIGHVOLUME, 1, MIDDLEPAN );
UseCreatureMusic(TRUE); // Madd: music when zombies rise
SetMusicMode( MUSIC_TACTICAL_ENEMYPRESENT );
}
}
if ( zombieshaverisen )
{
SetRenderFlags( RENDER_FLAG_FULL );
#ifdef JA2TESTVERSION
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_BETAVERSION, L"A wave of zombies is created");
#endif
// Play sound
PlayJA2SampleFromFile( "Sounds\\zombie1.wav", RATE_11025, HIGHVOLUME, 1, MIDDLEPAN );
UseCreatureMusic(TRUE); // Madd: music when zombies rise
SetMusicMode( MUSIC_TACTICAL_ENEMYPRESENT );
}
}
}
}
// Flugente Zombies 1.0: create a zombie from a corpse
void CreateZombiefromCorpse( ROTTING_CORPSE * pCorpse, UINT16 usAnimState )
{
SOLDIERCREATE_STRUCT MercCreateStruct;
MercCreateStruct.ubProfile = NO_PROFILE;
MercCreateStruct.bTeam = CREATURE_TEAM; // should be ZOMBIE_TEAM, once that is properly implemented
MercCreateStruct.sInsertionGridNo = pCorpse->def.sGridNo;
MercCreateStruct.sSectorX = gWorldSectorX;
MercCreateStruct.sSectorY = gWorldSectorY;
MercCreateStruct.bSectorZ = gbWorldSectorZ;
MercCreateStruct.bBodyType = pCorpse->def.ubBodyType;
MercCreateStruct.ubDirection = pCorpse->def.ubDirection;
MercCreateStruct.fOnRoof = pCorpse->def.bLevel > 0 ? TRUE : FALSE;
// add important stats according to difficulty level
// bLife is actually lower than bLifeMax. Because zombies have poison absorption, they can and will heal themselves over time, thereby gaining more life if they are not put down fast
switch( gGameExternalOptions.sZombieDifficultyLevel )
// Flugente Zombies 1.0: create a zombie from a corpse
void CreateZombiefromCorpse( ROTTING_CORPSE * pCorpse, UINT16 usAnimState )
{
case 4:
MercCreateStruct.bLifeMax = (INT8)( 70 + Random( 30 ) );
MercCreateStruct.bLife = MercCreateStruct.bLifeMax - (INT8)(10 + Random(15));
MercCreateStruct.bAgility = (INT8)( 50 + Random( 10 ) );
MercCreateStruct.bDexterity = (INT8)( 60 + Random( 15 ) );
MercCreateStruct.bStrength = (INT8)( 80 + Random( 20 ) );
break;
SOLDIERCREATE_STRUCT MercCreateStruct;
MercCreateStruct.ubProfile = NO_PROFILE;
MercCreateStruct.bTeam = CREATURE_TEAM; // should be ZOMBIE_TEAM, once that is properly implemented
MercCreateStruct.sInsertionGridNo = pCorpse->def.sGridNo;
MercCreateStruct.sSectorX = gWorldSectorX;
MercCreateStruct.sSectorY = gWorldSectorY;
MercCreateStruct.bSectorZ = gbWorldSectorZ;
MercCreateStruct.bBodyType = pCorpse->def.ubBodyType;
MercCreateStruct.ubDirection = pCorpse->def.ubDirection;
MercCreateStruct.fOnRoof = pCorpse->def.bLevel > 0 ? TRUE : FALSE;
case 3:
MercCreateStruct.bLifeMax = (INT8)( 60 + Random( 20 ) );
MercCreateStruct.bLife = MercCreateStruct.bLifeMax - (INT8)(10 + Random(10));
MercCreateStruct.bAgility = (INT8)( 40 + Random( 10 ) );
MercCreateStruct.bDexterity = (INT8)( 45 + Random( 10 ) );
MercCreateStruct.bStrength = (INT8)( 60 + Random( 20 ) );
break;
case 2:
MercCreateStruct.bLifeMax = (INT8)( 45 + Random( 15 ) );
MercCreateStruct.bLife = MercCreateStruct.bLifeMax - (INT8)(5 + Random(10));
MercCreateStruct.bAgility = (INT8)( 30 + Random( 5 ) );
MercCreateStruct.bDexterity = (INT8)( 30 + Random( 10 ) );
MercCreateStruct.bStrength = (INT8)( 45 + Random( 20 ) );
break;
case 1:
default:
MercCreateStruct.bLifeMax = (INT8)( 35 + Random( 10 ) );
MercCreateStruct.bLife = MercCreateStruct.bLifeMax - (INT8)(5 + Random(5));
MercCreateStruct.bAgility = (INT8)( 15 + Random( 5 ) );
MercCreateStruct.bDexterity = (INT8)( 15 + Random( 5 ) );
MercCreateStruct.bStrength = (INT8)( 30 + Random( 20 ) );
break;
}
// FIX: something's wrong with the FATCIV-bodytype when dying... this is to ensure they die absolutely fast
//if ( MercCreateStruct.bBodyType == FATCIV )
//MercCreateStruct.bLifeMax = OKLIFE;
MercCreateStruct.bExpLevel = 1;
MercCreateStruct.bMarksmanship = 1;
MercCreateStruct.bMedical = 1;
MercCreateStruct.bMechanical = 1;
MercCreateStruct.bExplosive = 1;
MercCreateStruct.bLeadership = 1;
MercCreateStruct.bWisdom = 1;
MercCreateStruct.bMorale = 90;
MercCreateStruct.bAIMorale = MORALE_FEARLESS;
SET_PALETTEREP_ID ( MercCreateStruct.HeadPal, pCorpse->def.HeadPal );
SET_PALETTEREP_ID ( MercCreateStruct.PantsPal, pCorpse->def.PantsPal );
SET_PALETTEREP_ID ( MercCreateStruct.VestPal, pCorpse->def.VestPal );
SET_PALETTEREP_ID ( MercCreateStruct.SkinPal, pCorpse->def.SkinPal );
MercCreateStruct.fVisible = TRUE;
INT8 iNewIndex;
if ( TacticalCreateSoldier( &MercCreateStruct, (UINT8 *)&iNewIndex ) )
{
/* certain values have to be set afterwards - the alternative would be to edit each and every function that gets called from TacticalCreateSoldier() subsequently and
* make an exception for zombies every time...
*/
SOLDIERTYPE* pNewSoldier = MercPtrs[ (UINT8)iNewIndex ];
pNewSoldier->bActionPoints = 60;
pNewSoldier->bInitialActionPoints = 60;
pNewSoldier->sBreathRed = 0;
pNewSoldier->ubInsertionDirection = pCorpse->def.ubDirection;
//pNewSoldier->sHeightAdjustment = pCorpse->def.sHeightAdjustment;
pNewSoldier->sDesiredHeight = 3;
pNewSoldier->ubDesiredHeight = 3; // this forces pNewSoldier to rise up to crouching position
pNewSoldier->ubSoldierClass = SOLDIER_CLASS_ZOMBIE;
pNewSoldier->aiData.bOrders = SEEKENEMY;
pNewSoldier->aiData.bAttitude = AGGRESSIVE;
////////////// stuff for poisoning ///////////////////////////////////
// this is important - by declaring the gap between bLife and bLifeMax as bBleeding, the zombies will bleed (even more if they are damaged)
// all their lifepoints are also poisoned. Thereby all bleeding damage will be poisoned bleeding damage
// as they have bPoisonAbsorption of at least 200%, they will absorp this poison damage
// This leads to them GAINING life through bleeding
// They can thereby regain their health in battle (although not very fast)
pNewSoldier->bBleeding = pNewSoldier->stats.bLifeMax - pNewSoldier->stats.bLife;
pNewSoldier->bPoisonSum = pNewSoldier->stats.bLifeMax;
pNewSoldier->bPoisonLife = pNewSoldier->stats.bLife;
pNewSoldier->bPoisonBleeding = pNewSoldier->bPoisonSum - pNewSoldier->bPoisonLife;
// zombies get 200% poison absorption, but no resistance to it, as it would reduce their healing
pNewSoldier->bPoisonResistance = 0;
pNewSoldier->bPoisonAbsorption = 200 + Random(100);
//////////////////////////////////////////////////////////////////////
if ( !memcmp( pCorpse->name, TacticalStr[ CIV_TEAM_MINER_NAME ], sizeof(pCorpse->name) )
|| !memcmp( pCorpse->name, TacticalStr[ MILITIA_TEAM_MERC_NAME ], sizeof(pCorpse->name) )
|| !memcmp( pCorpse->name, TacticalStr[ CREATURE_TEAM_MERC_NAME ], sizeof(pCorpse->name) )
|| !memcmp( pCorpse->name, TacticalStr[ CIV_TEAM_MERC_NAME ], sizeof(pCorpse->name) )
|| !memcmp( pCorpse->name, TacticalStr[ ZOMBIE_TEAM_MERC_NAME ], sizeof(pCorpse->name) )
|| !memcmp( pCorpse->name, TacticalStr[ ENEMY_TEAM_MERC_NAME ], sizeof(pCorpse->name) ) )
{
swprintf( pNewSoldier->name, TacticalStr[ ZOMBIE_TEAM_MERC_NAME ] );
}
else
{
memcpy( &(pNewSoldier->name), &(pCorpse->name), sizeof(CHAR16) * 10 );
pNewSoldier->name[9] = '\0';
}
// add skills according to difficulty level
// add important stats according to difficulty level
// bLife is actually lower than bLifeMax. Because zombies have poison absorption, they can and will heal themselves over time, thereby gaining more life if they are not put down fast
switch( gGameExternalOptions.sZombieDifficultyLevel )
{
case 4:
if ( gGameOptions.fNewTraitSystem )
{
pNewSoldier->stats.ubSkillTraits[0] = MARTIAL_ARTS_NT;
pNewSoldier->stats.ubSkillTraits[1] = MARTIAL_ARTS_NT;
pNewSoldier->stats.ubSkillTraits[2] = ATHLETICS_NT;
}
else
{
pNewSoldier->stats.ubSkillTraits[0] = HANDTOHAND_OT;
pNewSoldier->stats.ubSkillTraits[1] = MARTIALARTS_OT;
}
MercCreateStruct.bLifeMax = (INT8)( 70 + Random( 30 ) );
MercCreateStruct.bLife = MercCreateStruct.bLifeMax - (INT8)(10 + Random(15));
MercCreateStruct.bAgility = (INT8)( 50 + Random( 10 ) );
MercCreateStruct.bDexterity = (INT8)( 60 + Random( 15 ) );
MercCreateStruct.bStrength = (INT8)( 80 + Random( 20 ) );
break;
case 3:
if ( gGameOptions.fNewTraitSystem )
{
pNewSoldier->stats.ubSkillTraits[0] = MARTIAL_ARTS_NT;
pNewSoldier->stats.ubSkillTraits[1] = ATHLETICS_NT;
pNewSoldier->stats.ubSkillTraits[2] = NO_SKILLTRAIT_NT;
}
else
{
pNewSoldier->stats.ubSkillTraits[0] = HANDTOHAND_OT;
pNewSoldier->stats.ubSkillTraits[1] = NO_SKILLTRAIT_OT;
}
MercCreateStruct.bLifeMax = (INT8)( 60 + Random( 20 ) );
MercCreateStruct.bLife = MercCreateStruct.bLifeMax - (INT8)(10 + Random(10));
MercCreateStruct.bAgility = (INT8)( 40 + Random( 10 ) );
MercCreateStruct.bDexterity = (INT8)( 45 + Random( 10 ) );
MercCreateStruct.bStrength = (INT8)( 60 + Random( 20 ) );
break;
case 2:
if ( gGameOptions.fNewTraitSystem )
{
pNewSoldier->stats.ubSkillTraits[0] = MARTIAL_ARTS_NT;
pNewSoldier->stats.ubSkillTraits[1] = NO_SKILLTRAIT_NT;
pNewSoldier->stats.ubSkillTraits[2] = NO_SKILLTRAIT_NT;
}
else
{
pNewSoldier->stats.ubSkillTraits[0] = NO_SKILLTRAIT_OT;
pNewSoldier->stats.ubSkillTraits[1] = NO_SKILLTRAIT_OT;
}
MercCreateStruct.bLifeMax = (INT8)( 45 + Random( 15 ) );
MercCreateStruct.bLife = MercCreateStruct.bLifeMax - (INT8)(5 + Random(10));
MercCreateStruct.bAgility = (INT8)( 30 + Random( 5 ) );
MercCreateStruct.bDexterity = (INT8)( 30 + Random( 10 ) );
MercCreateStruct.bStrength = (INT8)( 45 + Random( 20 ) );
break;
case 1:
default:
if ( gGameOptions.fNewTraitSystem )
{
pNewSoldier->stats.ubSkillTraits[0] = NO_SKILLTRAIT_NT;
pNewSoldier->stats.ubSkillTraits[1] = NO_SKILLTRAIT_NT;
pNewSoldier->stats.ubSkillTraits[2] = NO_SKILLTRAIT_NT;
}
else
{
pNewSoldier->stats.ubSkillTraits[0] = NO_SKILLTRAIT_OT;
pNewSoldier->stats.ubSkillTraits[1] = NO_SKILLTRAIT_OT;
}
MercCreateStruct.bLifeMax = (INT8)( 35 + Random( 10 ) );
MercCreateStruct.bLife = MercCreateStruct.bLifeMax - (INT8)(5 + Random(5));
MercCreateStruct.bAgility = (INT8)( 15 + Random( 5 ) );
MercCreateStruct.bDexterity = (INT8)( 15 + Random( 5 ) );
MercCreateStruct.bStrength = (INT8)( 30 + Random( 20 ) );
break;
}
AddSoldierToSectorNoCalculateDirectionUseAnimation( iNewIndex, usAnimState, 0 );
// If this corpse has camo, use palette from hvobject
if ( pCorpse->def.ubType == ROTTING_STAGE2 )
{
memcpy( pNewSoldier->p8BPPPalette, gpTileCache[ pCorpse->iCachedTileID ].pImagery->vo->pPaletteEntry, sizeof( pCorpse->p8BPPPalette ) * 256 );
}
else if ( pCorpse->def.usFlags & ROTTING_CORPSE_USE_CAMO_PALETTE )
{
pNewSoldier->bCamo = 60;
pNewSoldier->wornCamo = 60;
}
else if ( pCorpse->def.usFlags & ROTTING_CORPSE_USE_URBAN_CAMO_PALETTE )
{
pNewSoldier->urbanCamo = 60;
pNewSoldier->wornUrbanCamo = 60;
}
else if ( pCorpse->def.usFlags & ROTTING_CORPSE_USE_DESERT_CAMO_PALETTE )
{
pNewSoldier->desertCamo = 60;
pNewSoldier->wornDesertCamo = 60;
}
else if ( pCorpse->def.usFlags & ROTTING_CORPSE_USE_SNOW_CAMO_PALETTE )
{
pNewSoldier->snowCamo = 60;
pNewSoldier->wornSnowCamo = 60;
}
// FIX: something's wrong with the FATCIV-bodytype when dying... this is to ensure they die absolutely fast
//if ( MercCreateStruct.bBodyType == FATCIV )
//MercCreateStruct.bLifeMax = OKLIFE;
MercCreateStruct.bExpLevel = 1;
MercCreateStruct.bMarksmanship = 1;
MercCreateStruct.bMedical = 1;
MercCreateStruct.bMechanical = 1;
MercCreateStruct.bExplosive = 1;
MercCreateStruct.bLeadership = 1;
MercCreateStruct.bWisdom = 1;
MercCreateStruct.bMorale = 90;
MercCreateStruct.bAIMorale = MORALE_FEARLESS;
SET_PALETTEREP_ID ( MercCreateStruct.HeadPal, pCorpse->def.HeadPal );
SET_PALETTEREP_ID ( MercCreateStruct.PantsPal, pCorpse->def.PantsPal );
SET_PALETTEREP_ID ( MercCreateStruct.VestPal, pCorpse->def.VestPal );
SET_PALETTEREP_ID ( MercCreateStruct.SkinPal, pCorpse->def.SkinPal );
MercCreateStruct.fVisible = TRUE;
// Reload palettes....
if ( pNewSoldier->bInSector )
INT8 iNewIndex;
if ( TacticalCreateSoldier( &MercCreateStruct, (UINT8 *)&iNewIndex ) )
{
pNewSoldier->CreateSoldierPalettes( );
}
/* certain values have to be set afterwards - the alternative would be to edit each and every function that gets called from TacticalCreateSoldier() subsequently and
* make an exception for zombies every time...
*/
SOLDIERTYPE* pNewSoldier = MercPtrs[ (UINT8)iNewIndex ];
pNewSoldier->bActionPoints = 60;
pNewSoldier->bInitialActionPoints = 60;
pNewSoldier->sBreathRed = 0;
// Set a pending animation to change stance first...
//SendChangeSoldierStanceEvent( pNewSoldier, ANIM_CROUCH );
pNewSoldier->ubInsertionDirection = pCorpse->def.ubDirection;
// search for armour and equip if found
if ( gGameExternalOptions.fZombieRiseWithArmour )
{
BOOLEAN fHelmetFound = FALSE;
BOOLEAN fVestFound = FALSE;
BOOLEAN fPantsFound = FALSE;
//pNewSoldier->sHeightAdjustment = pCorpse->def.sHeightAdjustment;
pNewSoldier->sDesiredHeight = 3;
ITEM_POOL * pItemPool, * pItemPoolNext;
pNewSoldier->ubDesiredHeight = 3; // this forces pNewSoldier to rise up to crouching position
GetItemPool( pCorpse->def.sGridNo, &pItemPool, pCorpse->def.bLevel );
pNewSoldier->ubSoldierClass = SOLDIER_CLASS_ZOMBIE;
pNewSoldier->aiData.bOrders = SEEKENEMY;
pNewSoldier->aiData.bAttitude = AGGRESSIVE;
while( pItemPool && ( !fHelmetFound || !fVestFound ||!fPantsFound ) )
////////////// stuff for poisoning ///////////////////////////////////
// this is important - by declaring the gap between bLife and bLifeMax as bBleeding, the zombies will bleed (even more if they are damaged)
// all their lifepoints are also poisoned. Thereby all bleeding damage will be poisoned bleeding damage
// as they have bPoisonAbsorption of at least 200%, they will absorp this poison damage
// This leads to them GAINING life through bleeding
// They can thereby regain their health in battle (although not very fast)
pNewSoldier->bBleeding = pNewSoldier->stats.bLifeMax - pNewSoldier->stats.bLife;
pNewSoldier->bPoisonSum = pNewSoldier->stats.bLifeMax;
pNewSoldier->bPoisonLife = pNewSoldier->stats.bLife;
pNewSoldier->bPoisonBleeding = pNewSoldier->bPoisonSum - pNewSoldier->bPoisonLife;
// zombies get 200% poison absorption, but no resistance to it, as it would reduce their healing
pNewSoldier->bPoisonResistance = 0;
pNewSoldier->bPoisonAbsorption = 200 + Random(100);
//////////////////////////////////////////////////////////////////////
#ifdef ENABLE_ZOMBIES
if ( !memcmp( pCorpse->name, TacticalStr[ CIV_TEAM_MINER_NAME ], sizeof(pCorpse->name) )
|| !memcmp( pCorpse->name, TacticalStr[ MILITIA_TEAM_MERC_NAME ], sizeof(pCorpse->name) )
|| !memcmp( pCorpse->name, TacticalStr[ CREATURE_TEAM_MERC_NAME ], sizeof(pCorpse->name) )
|| !memcmp( pCorpse->name, TacticalStr[ CIV_TEAM_MERC_NAME ], sizeof(pCorpse->name) )
|| !memcmp( pCorpse->name, TacticalStr[ ZOMBIE_TEAM_MERC_NAME ], sizeof(pCorpse->name) )
|| !memcmp( pCorpse->name, TacticalStr[ ENEMY_TEAM_MERC_NAME ], sizeof(pCorpse->name) ) )
{
pItemPoolNext = pItemPool->pNext;
OBJECTTYPE* pObj = &(gWorldItems[ pItemPool->iItemIndex ].object);
if ( Item[ pObj->usItem ].usItemClass == IC_ARMOUR )
{
switch (Armour[Item[pObj->usItem].ubClassIndex].ubArmourClass)
{
case ARMOURCLASS_HELMET:
{
if( !fHelmetFound && AutoPlaceObject(pNewSoldier, pObj, FALSE))
{
// remove item from the ground
RemoveItemFromPool( pCorpse->def.sGridNo, pItemPool->iItemIndex, pCorpse->def.bLevel );
fHelmetFound = TRUE;
}
break;
}
case ARMOURCLASS_VEST:
{
if( !fVestFound && AutoPlaceObject(pNewSoldier, pObj, FALSE))
{
// remove item from the ground
RemoveItemFromPool( pCorpse->def.sGridNo, pItemPool->iItemIndex, pCorpse->def.bLevel );
fVestFound = TRUE;
}
break;
}
case ARMOURCLASS_LEGGINGS:
{
if( !fPantsFound && AutoPlaceObject(pNewSoldier, pObj, FALSE))
{
// remove item from the ground
RemoveItemFromPool( pCorpse->def.sGridNo, pItemPool->iItemIndex, pCorpse->def.bLevel );
fPantsFound = TRUE;
}
break;
}
default:
break;
}
}
pItemPool = pItemPoolNext;
swprintf( pNewSoldier->name, TacticalStr[ ZOMBIE_TEAM_MERC_NAME ] );
}
else
{
memcpy( &(pNewSoldier->name), &(pCorpse->name), sizeof(CHAR16) * 10 );
pNewSoldier->name[9] = '\0';
}
#else
memcpy( &(pNewSoldier->name), &(pCorpse->name), sizeof(CHAR16) * 10 );
pNewSoldier->name[9] = '\0';
#endif
// add skills according to difficulty level
switch( gGameExternalOptions.sZombieDifficultyLevel )
{
case 4:
if ( gGameOptions.fNewTraitSystem )
{
pNewSoldier->stats.ubSkillTraits[0] = MARTIAL_ARTS_NT;
pNewSoldier->stats.ubSkillTraits[1] = MARTIAL_ARTS_NT;
pNewSoldier->stats.ubSkillTraits[2] = ATHLETICS_NT;
}
else
{
pNewSoldier->stats.ubSkillTraits[0] = HANDTOHAND_OT;
pNewSoldier->stats.ubSkillTraits[1] = MARTIALARTS_OT;
}
break;
case 3:
if ( gGameOptions.fNewTraitSystem )
{
pNewSoldier->stats.ubSkillTraits[0] = MARTIAL_ARTS_NT;
pNewSoldier->stats.ubSkillTraits[1] = ATHLETICS_NT;
pNewSoldier->stats.ubSkillTraits[2] = NO_SKILLTRAIT_NT;
}
else
{
pNewSoldier->stats.ubSkillTraits[0] = HANDTOHAND_OT;
pNewSoldier->stats.ubSkillTraits[1] = NO_SKILLTRAIT_OT;
}
break;
case 2:
if ( gGameOptions.fNewTraitSystem )
{
pNewSoldier->stats.ubSkillTraits[0] = MARTIAL_ARTS_NT;
pNewSoldier->stats.ubSkillTraits[1] = NO_SKILLTRAIT_NT;
pNewSoldier->stats.ubSkillTraits[2] = NO_SKILLTRAIT_NT;
}
else
{
pNewSoldier->stats.ubSkillTraits[0] = NO_SKILLTRAIT_OT;
pNewSoldier->stats.ubSkillTraits[1] = NO_SKILLTRAIT_OT;
}
break;
case 1:
default:
if ( gGameOptions.fNewTraitSystem )
{
pNewSoldier->stats.ubSkillTraits[0] = NO_SKILLTRAIT_NT;
pNewSoldier->stats.ubSkillTraits[1] = NO_SKILLTRAIT_NT;
pNewSoldier->stats.ubSkillTraits[2] = NO_SKILLTRAIT_NT;
}
else
{
pNewSoldier->stats.ubSkillTraits[0] = NO_SKILLTRAIT_OT;
pNewSoldier->stats.ubSkillTraits[1] = NO_SKILLTRAIT_OT;
}
break;
}
AddSoldierToSectorNoCalculateDirectionUseAnimation( iNewIndex, usAnimState, 0 );
// If this corpse has camo, use palette from hvobject
if ( pCorpse->def.ubType == ROTTING_STAGE2 )
{
memcpy( pNewSoldier->p8BPPPalette, gpTileCache[ pCorpse->iCachedTileID ].pImagery->vo->pPaletteEntry, sizeof( pCorpse->p8BPPPalette ) * 256 );
}
else if ( pCorpse->def.usFlags & ROTTING_CORPSE_USE_CAMO_PALETTE )
{
pNewSoldier->bCamo = 60;
pNewSoldier->wornCamo = 60;
}
else if ( pCorpse->def.usFlags & ROTTING_CORPSE_USE_URBAN_CAMO_PALETTE )
{
pNewSoldier->urbanCamo = 60;
pNewSoldier->wornUrbanCamo = 60;
}
else if ( pCorpse->def.usFlags & ROTTING_CORPSE_USE_DESERT_CAMO_PALETTE )
{
pNewSoldier->desertCamo = 60;
pNewSoldier->wornDesertCamo = 60;
}
else if ( pCorpse->def.usFlags & ROTTING_CORPSE_USE_SNOW_CAMO_PALETTE )
{
pNewSoldier->snowCamo = 60;
pNewSoldier->wornSnowCamo = 60;
}
// Reload palettes....
if ( pNewSoldier->bInSector )
{
pNewSoldier->CreateSoldierPalettes( );
}
// Set a pending animation to change stance first...
//SendChangeSoldierStanceEvent( pNewSoldier, ANIM_CROUCH );
#ifdef ENABLE_ZOMBIES
// search for armour and equip if found
if ( gGameExternalOptions.fZombieRiseWithArmour )
{
BOOLEAN fHelmetFound = FALSE;
BOOLEAN fVestFound = FALSE;
BOOLEAN fPantsFound = FALSE;
ITEM_POOL * pItemPool, * pItemPoolNext;
GetItemPool( pCorpse->def.sGridNo, &pItemPool, pCorpse->def.bLevel );
while( pItemPool && ( !fHelmetFound || !fVestFound ||!fPantsFound ) )
{
pItemPoolNext = pItemPool->pNext;
OBJECTTYPE* pObj = &(gWorldItems[ pItemPool->iItemIndex ].object);
if ( Item[ pObj->usItem ].usItemClass == IC_ARMOUR )
{
switch (Armour[Item[pObj->usItem].ubClassIndex].ubArmourClass)
{
case ARMOURCLASS_HELMET:
{
if( !fHelmetFound && AutoPlaceObject(pNewSoldier, pObj, FALSE))
{
// remove item from the ground
RemoveItemFromPool( pCorpse->def.sGridNo, pItemPool->iItemIndex, pCorpse->def.bLevel );
fHelmetFound = TRUE;
}
break;
}
case ARMOURCLASS_VEST:
{
if( !fVestFound && AutoPlaceObject(pNewSoldier, pObj, FALSE))
{
// remove item from the ground
RemoveItemFromPool( pCorpse->def.sGridNo, pItemPool->iItemIndex, pCorpse->def.bLevel );
fVestFound = TRUE;
}
break;
}
case ARMOURCLASS_LEGGINGS:
{
if( !fPantsFound && AutoPlaceObject(pNewSoldier, pObj, FALSE))
{
// remove item from the ground
RemoveItemFromPool( pCorpse->def.sGridNo, pItemPool->iItemIndex, pCorpse->def.bLevel );
fPantsFound = TRUE;
}
break;
}
default:
break;
}
}
pItemPool = pItemPoolNext;
}
}
#endif
// Change to standing,unless we can getup with an animation
pNewSoldier->EVENT_InitNewSoldierAnim( STANDING, 0, TRUE );
pNewSoldier->BeginSoldierGetup( );
// So we can see them!
AllTeamsLookForAll(ALLOW_INTERRUPTS);
}
}
// Flugente Zombies: returns true if a zombie can be raised from this corpse, and returns the correct pAnimState for the new zombie
BOOLEAN CorpseOkToSpawnZombie( ROTTING_CORPSE * pCorpse, UINT16* pAnimState )
{
BOOLEAN canbezombie = FALSE;
*pAnimState = FALLBACKHIT_STOP;
switch ( pCorpse->def.ubType )
{
case SMERC_BCK:
case SMERC_DHD:
case SMERC_FALL:
case MMERC_BCK:
case MMERC_DHD:
case MMERC_FALL:
case FMERC_BCK:
case FMERC_DHD:
case FMERC_FALL:
case ROTTING_STAGE2:
canbezombie = TRUE;
*pAnimState = FALLBACKHIT_STOP;
break;
case SMERC_FWD:
case SMERC_PRN:
case SMERC_FALLF:
case MMERC_FWD:
case MMERC_PRN:
case MMERC_FALLF:
case FMERC_FWD:
case FMERC_PRN:
case FMERC_FALLF:
canbezombie = TRUE;
*pAnimState = FALLFORWARD_HITDEATH_STOP;
break;
case M_DEAD1:
canbezombie = TRUE;
*pAnimState = GENERIC_HIT_DEATH;
break;
case M_DEAD2:
canbezombie = TRUE;
*pAnimState = CIV_DIE2;
case H_DEAD1:
case K_DEAD1:
case FT_DEAD1:
case S_DEAD1:
case W_DEAD1:
case C_DEAD1:
case H_DEAD2:
case K_DEAD2:
case FT_DEAD2:
case S_DEAD2:
case W_DEAD2:
case C_DEAD2:
canbezombie = TRUE;
*pAnimState = STANDING;
default:
;
}
// Change to standing,unless we can getup with an animation
pNewSoldier->EVENT_InitNewSoldierAnim( STANDING, 0, TRUE );
pNewSoldier->BeginSoldierGetup( );
// So we can see them!
AllTeamsLookForAll(ALLOW_INTERRUPTS);
return( canbezombie );
}
}
// Flugente Zombies: returns true if a zombie can be raised from this corpse, and returns the correct pAnimState for the new zombie
BOOLEAN CorpseOkToSpawnZombie( ROTTING_CORPSE * pCorpse, UINT16* pAnimState )
{
BOOLEAN canbezombie = FALSE;
*pAnimState = FALLBACKHIT_STOP;
switch ( pCorpse->def.ubType )
{
case SMERC_BCK:
case SMERC_DHD:
case SMERC_FALL:
case MMERC_BCK:
case MMERC_DHD:
case MMERC_FALL:
case FMERC_BCK:
case FMERC_DHD:
case FMERC_FALL:
case ROTTING_STAGE2:
canbezombie = TRUE;
*pAnimState = FALLBACKHIT_STOP;
break;
case SMERC_FWD:
case SMERC_PRN:
case SMERC_FALLF:
case MMERC_FWD:
case MMERC_PRN:
case MMERC_FALLF:
case FMERC_FWD:
case FMERC_PRN:
case FMERC_FALLF:
canbezombie = TRUE;
*pAnimState = FALLFORWARD_HITDEATH_STOP;
break;
case M_DEAD1:
canbezombie = TRUE;
*pAnimState = GENERIC_HIT_DEATH;
break;
case M_DEAD2:
canbezombie = TRUE;
*pAnimState = CIV_DIE2;
case H_DEAD1:
case K_DEAD1:
case FT_DEAD1:
case S_DEAD1:
case W_DEAD1:
case C_DEAD1:
case H_DEAD2:
case K_DEAD2:
case FT_DEAD2:
case S_DEAD2:
case W_DEAD2:
case C_DEAD2:
canbezombie = TRUE;
*pAnimState = STANDING;
default:
;
}
return( canbezombie );
}
#endif
+16 -7
View File
@@ -84,7 +84,10 @@ enum RottingCorpseDefines
#define ROTTING_CORPSE_USE_URBAN_CAMO_PALETTE 0x100 //We use urban palette here....
#define ROTTING_CORPSE_USE_DESERT_CAMO_PALETTE 0x200 //We use desert palette here....
#define ROTTING_CORPSE_USE_SNOW_CAMO_PALETTE 0x400 //We use snow palette here....
#define ROTTING_CORPSE_NEVER_RISE_AGAIN 0x800 //a zombie cannot be created from this corpse (if not set, it'll eventually rise again )
#ifdef ENABLE_ZOMBIES
#define ROTTING_CORPSE_NEVER_RISE_AGAIN 0x800 //a zombie cannot be created from this corpse (if not set, it'll eventually rise again )
#endif
typedef struct
@@ -116,8 +119,10 @@ typedef struct
UINT8 ubFiller[ 12 ];
#ifdef ENABLE_ZOMBIES
// Flugente: added name so we can display individual name if corpse gets resurrected...
CHAR16 name[ 10 ];
#endif
} ROTTING_CORPSE_DEFINITION;
@@ -140,8 +145,10 @@ typedef struct
BOOLEAN fAttractCrowsOnlyWhenOnScreen;
INT32 iID;
#ifdef ENABLE_ZOMBIES
// Flugente: added name so we can display individual name if corpse gets resurrected...
CHAR16 name[ 10 ];
#endif
} ROTTING_CORPSE;
@@ -200,13 +207,15 @@ INT32 GetGridNoOfCorpseGivenProfileID( UINT8 ubProfileID );
void DecayRottingCorpseAIWarnings( void );
UINT8 GetNearestRottingCorpseAIWarning( INT32 sGridNo );
// Flugente: Raise zombies
void RaiseZombies( void );
#ifdef ENABLE_ZOMBIES
// Flugente: Raise zombies
void RaiseZombies( void );
// Flugente: create a zombie from a corpse
void CreateZombiefromCorpse( ROTTING_CORPSE * pCorpse, UINT16 usAnimState );
// Flugente: create a zombie from a corpse
void CreateZombiefromCorpse( ROTTING_CORPSE * pCorpse, UINT16 usAnimState );
// Flugente: returns true if a zombie can be raised from this corpse, and returns the correct pAnimState for the new zombie
BOOLEAN CorpseOkToSpawnZombie( ROTTING_CORPSE * pCorpse, UINT16* pAnimState );
// Flugente: returns true if a zombie can be raised from this corpse, and returns the correct pAnimState for the new zombie
BOOLEAN CorpseOkToSpawnZombie( ROTTING_CORPSE * pCorpse, UINT16* pAnimState );
#endif
#endif
+2
View File
@@ -3485,9 +3485,11 @@ BOOLEAN HandleSoldierDeath( SOLDIERTYPE *pSoldier , BOOLEAN *pfMadeCorpse )
case SOLDIER_CLASS_CREATURE :
gMercProfiles[ MercPtrs[ ubAttacker ]->ubProfile ].records.usKillsCreatures++;
break;
#ifdef ENABLE_ZOMBIES
case SOLDIER_CLASS_ZOMBIE :
gMercProfiles[ MercPtrs[ ubAttacker ]->ubProfile ].records.usKillsZombies++;
break;
#endif
default :
if ( CREATURE_OR_BLOODCAT( pSoldier ) )
gMercProfiles[ MercPtrs[ ubAttacker ]->ubProfile ].records.usKillsCreatures++;
+49 -7
View File
@@ -137,8 +137,10 @@ extern INT16 DirIncrementer[8];
#define MIN_SUBSEQUENT_SNDS_DELAY 2000
#include "connect.h"
extern void TeleportSelectedSoldier( void );
extern BOOLEAN AddSoldierToSectorNoCalculateDirectionUseAnimation( UINT8 ubID, UINT16 usAnimState, UINT16 usAnimCode );
#ifdef ENABLE_ZOMBIES
extern void TeleportSelectedSoldier( void );
extern BOOLEAN AddSoldierToSectorNoCalculateDirectionUseAnimation( UINT8 ubID, UINT16 usAnimState, UINT16 usAnimCode );
#endif
// Enumerate extended directions
@@ -1349,7 +1351,11 @@ MERCPROFILESTRUCT& MERCPROFILESTRUCT::operator=(const OLD_MERCPROFILESTRUCT_101&
this->records.usKillsAdmins = (src.usKills/4);
this->records.usKillsHostiles = 0;
this->records.usKillsCreatures = 0;
#ifdef ENABLE_ZOMBIES
this->records.usKillsZombies = 0;
#endif
this->records.usKillsTanks = 0;
this->records.usKillsOthers = 0;
this->records.usAssistsMercs = (src.usAssists*3/4);
@@ -8673,6 +8679,7 @@ void SOLDIERTYPE::BeginSoldierClimbUpRoof( void )
this->ubPendingDirection = bNewDirection;
//this->usPendingAnimation = CLIMBUPROOF;
#ifdef ENABLE_ZOMBIES
// Flugente: In case an animation is missing (zombies with bodytype of civilians), we TELEPORT instead
if ( IsAnimationValidForBodyType( this, CLIMBUPROOF ) == FALSE )
{
@@ -8682,6 +8689,9 @@ void SOLDIERTYPE::BeginSoldierClimbUpRoof( void )
}
else
this->EVENT_InitNewSoldierAnim( CLIMBUPROOF, 0 , FALSE );
#else
this->EVENT_InitNewSoldierAnim( CLIMBUPROOF, 0 , FALSE );
#endif
this->InternalReceivingSoldierCancelServices( FALSE );
this->InternalGivingSoldierCancelServices( FALSE );
@@ -9276,7 +9286,11 @@ UINT8 SOLDIERTYPE::SoldierTakeDamage( INT8 bHeight, INT16 sLifeDeduct, INT16 sPo
// ATE: Put some logic in here to allow enemies to die quicker.....
// Are we an enemy?
// zombies don't die suddenly, as they regenerate health by bloodloss and poison. You have to make sure they die!
#ifdef ENABLE_ZOMBIES
if ( this->bSide != gbPlayerNum && !this->aiData.bNeutral && this->ubProfile == NO_PROFILE && !this->IsZombie() )
#else
if ( this->bSide != gbPlayerNum && !this->aiData.bNeutral && this->ubProfile == NO_PROFILE)
#endif
{
// ATE: Give them a chance to fall down...
if ( this->stats.bLife > 0 && this->stats.bLife < ( OKLIFE - 1 ) )
@@ -9310,12 +9324,15 @@ UINT8 SOLDIERTYPE::SoldierTakeDamage( INT8 bHeight, INT16 sLifeDeduct, INT16 sPo
}
}
}
#ifdef ENABLE_ZOMBIES
else if ( this->IsZombie() && this->stats.bLife > 0 && this->stats.bLife < OKLIFE )
{
// a zombie doesn't automatically die, so he would normally stand up again after being hit.
// We don't want that, because he is dying, so we manually skip that animation
this->usPendingAnimation = NO_PENDING_ANIMATION;
}
#endif
if ( fShowDamage )
{
@@ -9988,6 +10005,7 @@ BOOLEAN SOLDIERTYPE::InternalDoMercBattleSound( UINT8 ubBattleSoundID, INT8 bSpe
}
}
}
#ifdef ENABLE_ZOMBIES
else if ( pSoldier->IsZombie() ) // Madd: add zombie sounds
{
if ( ubSoundID == BATTLE_SOUND_DIE1 )
@@ -10007,6 +10025,7 @@ BOOLEAN SOLDIERTYPE::InternalDoMercBattleSound( UINT8 ubBattleSoundID, INT8 bSpe
}
}
}
#endif
else
{
if ( ubSoundID == BATTLE_SOUND_DIE1 )
@@ -10265,6 +10284,7 @@ void SOLDIERTYPE::BeginSoldierClimbDownRoof( void )
this->ubPendingDirection = bNewDirection;
#ifdef ENABLE_ZOMBIES
// Flugente: In case an animation is missing (zombies with bodytype of civilians), we TELEPORT instead
if ( IsAnimationValidForBodyType( this, JUMPDOWNWALL ) == FALSE )
{
@@ -10274,6 +10294,9 @@ void SOLDIERTYPE::BeginSoldierClimbDownRoof( void )
}
else
this->EVENT_InitNewSoldierAnim( JUMPDOWNWALL, 0 , FALSE );
#else
this->EVENT_InitNewSoldierAnim( JUMPDOWNWALL, 0 , FALSE );
#endif
this->InternalReceivingSoldierCancelServices( FALSE );
this->InternalGivingSoldierCancelServices( FALSE );
@@ -11505,7 +11528,13 @@ void SOLDIERTYPE::EVENT_SoldierBeginPunchAttack( INT32 sGridNo, UINT8 ubDirectio
#if (defined JA2UB || defined JA113NODEMO)
if ( fMartialArtist && !Item[usItem].crowbar && this->ubBodyType == REGMALE)
#else
if ( fMartialArtist && !AreInMeanwhile( ) && !Item[usItem].crowbar && this->ubBodyType == REGMALE && !IsZombie() ) // SANDRO - added check for body type
#ifdef ENABLE_ZOMBIES
if ( fMartialArtist && !AreInMeanwhile( ) && !Item[usItem].crowbar && this->ubBodyType == REGMALE && !IsZombie() ) // SANDRO - added check for body type
#else
if ( fMartialArtist && !AreInMeanwhile( ) && !Item[usItem].crowbar && this->ubBodyType == REGMALE ) // SANDRO - added check for body type
#endif
#endif
{
// Are we in attack mode yet?
@@ -11520,6 +11549,7 @@ void SOLDIERTYPE::EVENT_SoldierBeginPunchAttack( INT32 sGridNo, UINT8 ubDirectio
}
else
{
#ifdef ENABLE_ZOMBIES
// Flugente: civilians can be zombies too, but they do not have a 'punch' animation. Simple fix: They 'attack' without animation...
// CHECK IF WE CAN DO THIS ANIMATION!
if ( this->IsZombie() && IsAnimationValidForBodyType( this, PUNCH ) == FALSE )
@@ -11589,6 +11619,7 @@ void SOLDIERTYPE::EVENT_SoldierBeginPunchAttack( INT32 sGridNo, UINT8 ubDirectio
}
else
{
#endif
// Look at stance of target
switch( gAnimControl[ pTSoldier->usAnimState ].ubEndHeight )
{
@@ -11649,7 +11680,10 @@ void SOLDIERTYPE::EVENT_SoldierBeginPunchAttack( INT32 sGridNo, UINT8 ubDirectio
}
}
break;
#ifdef ENABLE_ZOMBIES
}
#endif
}
}
@@ -13402,6 +13436,8 @@ INT32 SOLDIERTYPE::GetDamageResistance(BOOLEAN fAutoResolve, BOOLEAN fCalcBreath
resistance += gGameExternalOptions.sEnemyRegularDamageResistance;
else if (this->ubSoldierClass == SOLDIER_CLASS_ELITE && gGameExternalOptions.sEnemyEliteDamageResistance != 0)
resistance += gGameExternalOptions.sEnemyEliteDamageResistance;
#ifdef ENABLE_ZOMBIES
else if (IsZombie())
{
if ( fCalcBreathLoss )
@@ -13409,6 +13445,7 @@ INT32 SOLDIERTYPE::GetDamageResistance(BOOLEAN fAutoResolve, BOOLEAN fCalcBreath
else
resistance += gGameExternalOptions.sEnemyZombieDamageResistance;
}
#endif
}
//////////////////////////////////////////////////////////////////////////////////////
@@ -13463,10 +13500,13 @@ INT16 SOLDIERTYPE::GetSoldierCriticalDamageBonus( void )
return val;
}
BOOLEAN SOLDIERTYPE::IsZombie( void )
{
return( ubSoldierClass == SOLDIER_CLASS_ZOMBIE );
}
#ifdef ENABLE_ZOMBIES
BOOLEAN SOLDIERTYPE::IsZombie( void )
{
return( ubSoldierClass == SOLDIER_CLASS_ZOMBIE );
}
#endif
INT16 SOLDIERTYPE::GetPoisonResistance( void )
{
@@ -13497,9 +13537,11 @@ INT16 SOLDIERTYPE::GetPoisonDamagePercentage( void )
// Flugente: this percentage has to be between 0% and 100%
INT16 val = 0;
#ifdef ENABLE_ZOMBIES
// zombies poison damage percentage is externalised
if ( IsZombie() )
val += gGameExternalOptions.sZombiePoisonDamagePercentage;
#endif
if ( this->usAttackingWeapon )
{
+4
View File
@@ -310,7 +310,9 @@ enum
SOLDIER_CLASS_ELITE_MILITIA,
SOLDIER_CLASS_CREATURE,
SOLDIER_CLASS_MINER,
#ifdef ENABLE_ZOMBIES
SOLDIER_CLASS_ZOMBIE,
#endif
};
#define SOLDIER_CLASS_ENEMY( bSoldierClass ) ( ( bSoldierClass >= SOLDIER_CLASS_ADMINISTRATOR ) && ( bSoldierClass <= SOLDIER_CLASS_ARMY ) )
@@ -1358,8 +1360,10 @@ public:
INT16 GetSoldierCriticalDamageBonus( void ); // Flugente: determines critical damage bonus depending on class, skill, etc.
#ifdef ENABLE_ZOMBIES
// Flugente: Zombies
BOOLEAN IsZombie( void );
#endif
// Flugente: poison system
// These functions might one day be modified by traits etc. We'll keep that in these functions and not clutter the rest of the code
+53 -30
View File
@@ -1729,10 +1729,12 @@ BOOLEAN TacticalCopySoldierFromCreateStruct( SOLDIERTYPE *pSoldier, SOLDIERCREAT
{
swprintf( pSoldier->name, gzLateLocalizedString[ 36 ] );
}
#ifdef ENABLE_ZOMBIES
else if ( pSoldier->IsZombie() )
{
swprintf( pSoldier->name, TacticalStr[ ZOMBIE_TEAM_MERC_NAME ] );
}
#endif
else
{
swprintf( pSoldier->name, TacticalStr[ CREATURE_TEAM_MERC_NAME ] ); break;
@@ -2176,7 +2178,9 @@ void CreateDetailedPlacementGivenBasicPlacementInfo( SOLDIERCREATE_STRUCT *pp, B
switch( ubSoldierClass )
{
case SOLDIER_CLASS_ADMINISTRATOR:
#ifdef ENABLE_ZOMBIES
case SOLDIER_CLASS_ZOMBIE:
#endif
pp->bExpLevel = (INT8) 2 + bExpLevelModifier;
break;
case SOLDIER_CLASS_ARMY:
@@ -2294,7 +2298,11 @@ void CreateDetailedPlacementGivenBasicPlacementInfo( SOLDIERCREATE_STRUCT *pp, B
//If it is a detailed placement, don't do this yet, as detailed placements may have their
//own equipment.
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("CreateDetailedPlacementGivenBasicPlacementInfo: generate random equipment"));
#ifdef ENABLE_ZOMBIES
if( !bp->fDetailedPlacement && ubSoldierClass != SOLDIER_CLASS_NONE && ubSoldierClass != SOLDIER_CLASS_CREATURE && ubSoldierClass != SOLDIER_CLASS_MINER && ubSoldierClass != SOLDIER_CLASS_ZOMBIE )
#else
if( !bp->fDetailedPlacement && ubSoldierClass != SOLDIER_CLASS_NONE && ubSoldierClass != SOLDIER_CLASS_CREATURE && ubSoldierClass != SOLDIER_CLASS_MINER )
#endif
GenerateRandomEquipment( pp, ubSoldierClass, bp->bRelativeEquipmentLevel);
DecideToAssignSniperOrders(pp);
@@ -2462,7 +2470,12 @@ void CreateDetailedPlacementGivenStaticDetailedPlacementAndBasicPlacementInfo(
//{
// ReplaceExtendedGuns( pp, bp->ubSoldierClass );
//}
#ifdef ENABLE_ZOMBIES
if( bp->ubSoldierClass != SOLDIER_CLASS_NONE && bp->ubSoldierClass != SOLDIER_CLASS_CREATURE && bp->ubSoldierClass != SOLDIER_CLASS_MINER && bp->ubSoldierClass != SOLDIER_CLASS_ZOMBIE )
#else
if( bp->ubSoldierClass != SOLDIER_CLASS_NONE && bp->ubSoldierClass != SOLDIER_CLASS_CREATURE && bp->ubSoldierClass != SOLDIER_CLASS_MINER )
#endif
{
GenerateRandomEquipment( pp, bp->ubSoldierClass, bp->bRelativeEquipmentLevel);
DecideToAssignSniperOrders(pp);
@@ -2657,7 +2670,11 @@ 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.
#ifdef ENABLE_ZOMBIES
if( ubSoldierClass != SOLDIER_CLASS_CREATURE && ubSoldierClass != SOLDIER_CLASS_ZOMBIE )
#else
if( ubSoldierClass != SOLDIER_CLASS_CREATURE )
#endif
{ //use the enemy team
iStart = gTacticalStatus.Team[ ENEMY_TEAM ].bFirstID;
iEnd = gTacticalStatus.Team[ ENEMY_TEAM ].bLastID;
@@ -2799,39 +2816,41 @@ SOLDIERTYPE* TacticalCreateEliteEnemy()
return( pSoldier );
}
//USED BY STRATEGIC AI and AUTORESOLVE
SOLDIERTYPE* TacticalCreateZombie()
{
BASIC_SOLDIERCREATE_STRUCT bp;
SOLDIERCREATE_STRUCT pp;
UINT8 ubID;
SOLDIERTYPE * pSoldier;
if( guiCurrentScreen == AUTORESOLVE_SCREEN && !gfPersistantPBI )
#ifdef ENABLE_ZOMBIES
//USED BY STRATEGIC AI and AUTORESOLVE
SOLDIERTYPE* TacticalCreateZombie()
{
pSoldier = ReserveTacticalSoldierForAutoresolve( SOLDIER_CLASS_ZOMBIE );
if( pSoldier ) return pSoldier;
}
BASIC_SOLDIERCREATE_STRUCT bp;
SOLDIERCREATE_STRUCT pp;
UINT8 ubID;
SOLDIERTYPE * pSoldier;
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.bOrders = SEEKENEMY;
bp.bAttitude = AGGRESSIVE;
bp.bBodyType = -1;
bp.ubSoldierClass = SOLDIER_CLASS_ZOMBIE;
CreateDetailedPlacementGivenBasicPlacementInfo( &pp, &bp );
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 && !gfPersistantPBI )
{
pSoldier = ReserveTacticalSoldierForAutoresolve( SOLDIER_CLASS_ZOMBIE );
if( pSoldier ) return pSoldier;
}
return( pSoldier );
}
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.bOrders = SEEKENEMY;
bp.bAttitude = AGGRESSIVE;
bp.bBodyType = -1;
bp.ubSoldierClass = SOLDIER_CLASS_ZOMBIE;
CreateDetailedPlacementGivenBasicPlacementInfo( &pp, &bp );
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;
}
return( pSoldier );
}
#endif
SOLDIERTYPE* ReserveTacticalMilitiaSoldierForAutoresolve( UINT8 ubSoldierClass )
{
@@ -4236,8 +4255,10 @@ BOOLEAN AssignTraitsToSoldier( SOLDIERTYPE *pSoldier, SOLDIERCREATE_STRUCT *pCre
iChance = 10 + ubProgress/4; // 10-35% chance
else if( ubSolClass == SOLDIER_CLASS_ADMINISTRATOR || ubSolClass == SOLDIER_CLASS_GREEN_MILITIA )
iChance = ubProgress/4; // 0-25% chance
#ifdef ENABLE_ZOMBIES
else if (ubSolClass == SOLDIER_CLASS_ZOMBIE )
iChance = 100; // 100% chance
#endif
if( foundHtH ) // if found brass knuckless, increase the chance (doesn't happen often)
iChance += 35;
@@ -4281,8 +4302,10 @@ BOOLEAN AssignTraitsToSoldier( SOLDIERTYPE *pSoldier, SOLDIERCREATE_STRUCT *pCre
iChance = 25 + ubProgress*2/5; // 25-65% chance
else if( ubSolClass == SOLDIER_CLASS_ADMINISTRATOR || ubSolClass == SOLDIER_CLASS_GREEN_MILITIA )
iChance = 10 + ubProgress*2/5; // 10-50% chance
#ifdef ENABLE_ZOMBIES
else if (ubSolClass == SOLDIER_CLASS_ZOMBIE )
iChance = 100; // 100% chance
#endif
// modify the chance by preset ini setting
if( gGameExternalOptions.bAssignedTraitsRarity != 0 )
+3 -1
View File
@@ -420,7 +420,9 @@ SOLDIERTYPE* TacticalCreateSoldier( SOLDIERCREATE_STRUCT *pCreateStruct, UINT8 *
SOLDIERTYPE* TacticalCreateAdministrator();
SOLDIERTYPE* TacticalCreateEliteEnemy();
SOLDIERTYPE* TacticalCreateArmyTroop();
SOLDIERTYPE* TacticalCreateZombie(); // Flugente Zombies
#ifdef ENABLE_ZOMBIES
SOLDIERTYPE* TacticalCreateZombie(); // Flugente Zombies
#endif
SOLDIERTYPE* TacticalCreateMilitia( UINT8 ubMilitiaClass );
SOLDIERTYPE* TacticalCreateCreature( INT8 bCreatureBodyType );
+3
View File
@@ -275,11 +275,14 @@ void HandleTacticalEndTurn( )
// Flugente: Cool down all items not in a soldier's inventory
CoolDownWorldItems( FALSE );
#ifdef ENABLE_ZOMBIES
// Flugente: raise zombies if in gamescreen and option set
if ( guiCurrentScreen == GAME_SCREEN )
{
RaiseZombies();
}
#endif
}
+3
View File
@@ -464,11 +464,14 @@ void EndTurnEvents( void )
// Flugente: Cool down all items not in a soldier's inventory
CoolDownWorldItems( FALSE );
#ifdef ENABLE_ZOMBIES
// Flugente: raise zombies if in gamescreen and option set
if ( guiCurrentScreen == GAME_SCREEN )
{
RaiseZombies();
}
#endif
// decay AI warning values from corpses
DecayRottingCorpseAIWarnings();
+2
View File
@@ -8635,12 +8635,14 @@ INT32 BulletImpact( SOLDIERTYPE *pFirer, BULLET *pBullet, SOLDIERTYPE * pTarget,
INT8 bStatLoss = 0;
UINT8 ubAmmoType;
#ifdef ENABLE_ZOMBIES
if ( pTarget->IsZombie() && gGameExternalOptions.fZombieOnlyHeadshotsWork )
{
// if bullet does not hits anything other than the head, it doesn't do any damage
if ( ubHitLocation != AIM_SHOT_HEAD )
return 0;
}
#endif
// NOTE: reduction of bullet impact due to range and obstacles is handled
// in MoveBullet.
+4
View File
@@ -4764,7 +4764,11 @@ void DebugSoldierPage4( )
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;
#ifdef ENABLE_ZOMBIES
case SOLDIER_CLASS_ZOMBIE: gprintf( 320, LINE_HEIGHT * ubLine, L"(Zombie)" ); break;
#endif
default: break; //don't care (don't write anything)
}
ubLine++;