- New feature: zombies can now spawn from corpses, if you specify that option in the preferences screen (by Flugente)

o if set to off, no zombies will spawn. This can also be changed in mid-game
o for more information on how this works and how to set it up, see http://www.bears-pit.com/board/ubbthreads.php/topics/295746/Zombies_WH40K_and_more.html#Post295746
o with the tag <PoisonPercentage>, you can now poison guns or ammo. This is the percentage of damage dealt that will be poisonous (see zombie thread for an explanation)
o The zombie option can only be enabled in a single player game

o AI fix: to prevent the endless clock problem, the AI now ends the turn if the same actor calls the decision routine over 100 times in a single turn.

git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@5313 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
Wanne
2012-05-29 22:49:17 +00:00
parent 744ce2ee9c
commit c90f4bce47
73 changed files with 4481 additions and 609 deletions
+4
View File
@@ -792,6 +792,10 @@ void ChangeBaseSoldierStats( SOLDIERTYPE *pSoldier )
pSoldier->bBleeding = 0;
pSoldier->bBreath = 100;
pSoldier->bPoisonSum = 0;
pSoldier->bPoisonLife = 0;
pSoldier->bPoisonBleeding = 0;
pSoldier->stats.bMarksmanship = (UINT8)(sBaseStat[sCurBaseDiff] + (UINT16)(Random(BASE_STAT_DEVIATION * 2)-BASE_STAT_DEVIATION));
pSoldier->stats.bMedical = (UINT8)(sBaseStat[sCurBaseDiff] + (UINT16)(Random(BASE_STAT_DEVIATION * 2)-BASE_STAT_DEVIATION));
pSoldier->stats.bMechanical = (UINT8)(sBaseStat[sCurBaseDiff] + (UINT16)(Random(BASE_STAT_DEVIATION * 2)-BASE_STAT_DEVIATION));
+20 -10
View File
@@ -241,7 +241,7 @@ BOOLEAN LoadGameSettings()
if (!IsHiSpeedClockMode())
gGameSettings.fOptions[TOPTION_AUTO_FAST_FORWARD_MODE] = FALSE;
//gGameOptions.fWeaponOverheating = iniReader.ReadBoolean("JA2 Game Settings","TOPTION_WEAPON_OVERHEATING" , FALSE ); // Flugente FTW 1: Weapon Overheating
gGameSettings.fOptions[TOPTION_ZOMBIES] = iniReader.ReadBoolean("JA2 Game Settings","TOPTION_ZOMBIES" , FALSE );
gGameSettings.fOptions[NUM_ALL_GAME_OPTIONS] = iniReader.ReadBoolean("JA2 Game Settings","NUM_ALL_GAME_OPTIONS" , FALSE );
@@ -341,8 +341,6 @@ BOOLEAN SaveGameSettings()
settings << "; UINT8 fOptions[ NUM_ALL_GAME_OPTIONS ]; // Toggle Options (Speech, Subtitles, Show Tree Tops, etc.. )" << endl;
settings << "; UINT32 uiMeanwhileScenesSeenFlags; // Bit Vector describing seen 'mean whiles..'" << endl;
settings << "; BOOLEAN fHideHelpInAllScreens; // Controls Help \"do not show help again\" checkbox" << endl;
//settings << "; UINT8 ubSizeOfDisplayCover; // The number of grids the player designates thru [Delete + ( = or - )]" << endl;
//settings << "; UINT8 ubSizeOfLOS; // The number of grids the player designates thru [End + ( = or - )]" << endl;
settings << "; } GAME_SETTINGS" << endl;
settings << ";" << endl;
settings << ";******************************************************************************************************************************" << endl;
@@ -355,8 +353,6 @@ BOOLEAN SaveGameSettings()
settings << "ubSpeechVolume = " << (int)gGameSettings.ubSpeechVolume << endl;
settings << "uiMeanwhileScenesSeenFlags = " << gGameSettings.uiMeanwhileScenesSeenFlags << endl;
settings << "fHideHelpInAllScreens = " << (gGameSettings.fHideHelpInAllScreens ? "TRUE" : "FALSE" ) << endl;
//settings << "ubSizeOfDisplayCover = " << (int)gGameSettings.ubSizeOfDisplayCover << endl;
//settings << "ubSizeOfLOS = " << (int)gGameSettings.ubSizeOfLOS << endl;
settings << "TOPTION_SPEECH = " << (gGameSettings.fOptions[TOPTION_SPEECH] ? "TRUE" : "FALSE" ) << endl;
settings << "TOPTION_MUTE_CONFIRMATIONS = " << (gGameSettings.fOptions[TOPTION_MUTE_CONFIRMATIONS] ? "TRUE" : "FALSE" ) << endl;
settings << "TOPTION_SUBTITLES = " << (gGameSettings.fOptions[TOPTION_SUBTITLES] ? "TRUE" : "FALSE" ) << endl;
@@ -391,20 +387,18 @@ BOOLEAN SaveGameSettings()
settings << "TOPTION_ALLOW_SOLDIER_TOOLTIPS = " << (gGameSettings.fOptions[TOPTION_ALLOW_SOLDIER_TOOLTIPS] ? "TRUE" : "FALSE" ) << endl;
settings << "TOPTION_USE_AUTO_SAVE = " << (gGameSettings.fOptions[TOPTION_USE_AUTO_SAVE] ? "TRUE" : "FALSE" ) << endl;
settings << "TOPTION_SILENT_SKYRIDER = " << (gGameSettings.fOptions[TOPTION_SILENT_SKYRIDER] ? "TRUE" : "FALSE" ) << endl;
//settings << "TOPTION_LOW_CPU_USAGE = " << (gGameSettings.fOptions[TOPTION_LOW_CPU_USAGE] ? "TRUE" : "FALSE" ) << endl;
settings << "TOPTION_ENHANCED_DESC_BOX = " << (gGameSettings.fOptions[TOPTION_ENHANCED_DESC_BOX] ? "TRUE" : "FALSE" ) << endl;
settings << "TOPTION_TOGGLE_TURN_MODE = " << (gGameSettings.fOptions[TOPTION_TOGGLE_TURN_MODE] ? "TRUE" : "FALSE" ) << endl;
settings << "TOPTION_STAT_PROGRESS_BARS = " << (gGameSettings.fOptions[TOPTION_STAT_PROGRESS_BARS] ? "TRUE" : "FALSE" ) << endl; // HEADROCK HAM 3.6: Progress Bars
settings << "TOPTION_ALT_MAP_COLOR = " << (gGameSettings.fOptions[TOPTION_ALT_MAP_COLOR] ? "TRUE" : "FALSE" ) << endl; // HEADROCK HAM 4: Alt Map Colors
settings << "TOPTION_ALTERNATE_BULLET_GRAPHICS = " << (gGameSettings.fOptions[TOPTION_ALTERNATE_BULLET_GRAPHICS] ? "TRUE" : "FALSE" ) << endl;
//settings << "TOPTION_USE_NCTH = " << (gGameSettings.fOptions[TOPTION_USE_NCTH] ? "TRUE" : "FALSE" ) << endl;
settings << "TOPTION_SHOW_MERC_RANKS = " << (gGameSettings.fOptions[TOPTION_SHOW_MERC_RANKS] ? "TRUE" : "FALSE" ) << endl;
settings << "TOPTION_SHOW_TACTICAL_FACE_GEAR = " << (gGameSettings.fOptions[TOPTION_SHOW_TACTICAL_FACE_GEAR] ? "TRUE" : "FALSE" ) << endl;
settings << "TOPTION_SHOW_TACTICAL_FACE_ICONS = " << (gGameSettings.fOptions[TOPTION_SHOW_TACTICAL_FACE_ICONS] ? "TRUE" : "FALSE" ) << endl;
settings << "TOPTION_DISABLE_CURSOR_SWAP = " << (gGameSettings.fOptions[TOPTION_DISABLE_CURSOR_SWAP] ? "TRUE" : "FALSE" ) << endl;
settings << "TOPTION_QUIET_TRAINING = " << (gGameSettings.fOptions[TOPTION_QUIET_TRAINING] ? "TRUE" : "FALSE" ) << endl;
settings << "TOPTION_AUTO_FAST_FORWARD_MODE = " << (gGameSettings.fOptions[TOPTION_AUTO_FAST_FORWARD_MODE] ? "TRUE" : "FALSE" ) << endl;
//settings << "TOPTION_WEAPON_OVERHEATING = " << (gGameOptions.fWeaponOverheating ? "TRUE" : "FALSE" ) << endl; // Flugente FTW 1: Weapon Overheating
settings << "TOPTION_ZOMBIES = " << (gGameSettings.fOptions[TOPTION_ZOMBIES] ? "TRUE" : "FALSE" ) << endl;
settings << "TOPTION_CHEAT_MODE_OPTIONS_HEADER = " << (gGameSettings.fOptions[TOPTION_CHEAT_MODE_OPTIONS_HEADER] ? "TRUE" : "FALSE" ) << endl;
settings << "TOPTION_FORCE_BOBBY_RAY_SHIPMENTS = " << (gGameSettings.fOptions[TOPTION_FORCE_BOBBY_RAY_SHIPMENTS] ? "TRUE" : "FALSE" ) << endl;
settings << "TOPTION_CHEAT_MODE_OPTIONS_END = " << (gGameSettings.fOptions[TOPTION_CHEAT_MODE_OPTIONS_END] ? "TRUE" : "FALSE" ) << endl;
@@ -530,9 +524,8 @@ void InitGameSettings()
gGameSettings.fOptions[ TOPTION_DISABLE_CURSOR_SWAP ] = FALSE;
gGameSettings.fOptions[ TOPTION_QUIET_TRAINING ] = FALSE;
gGameSettings.fOptions[ TOPTION_AUTO_FAST_FORWARD_MODE ] = FALSE;
gGameSettings.fOptions[ TOPTION_ZOMBIES ] = FALSE; // Flugente Zombies 1.0
// Flugente FTW 1: Weapon Overheating
//gGameSettings.fOptions[ TOPTION_WEAPON_OVERHEATING ] = TRUE;
// arynn: Cheat/Debug Menu
gGameSettings.fOptions[ TOPTION_CHEAT_MODE_OPTIONS_HEADER ] = FALSE;
@@ -547,6 +540,8 @@ void InitGameSettings()
gGameSettings.fOptions[ TOPTION_RENDER_MOUSE_REGIONS ] = FALSE; // an example of a DEBUG build option
gGameSettings.fOptions[ TOPTION_DEBUG_MODE_OPTIONS_END ] = FALSE; // an example options screen options divider (pure text)
// enum control options (not real options but included here for the sake of complete control of values)
//gGameSettings.ubSizeOfDisplayCover = 16;
@@ -1331,6 +1326,21 @@ void LoadGameExternalOptions()
gGameExternalOptions.iCooldownModificatorLonelyBarrel = iniReader.ReadFloat ("Tactical Weapon Overheating Settings","OVERHEATING_COOLDOWN_MODIFICATOR_LONELYBARREL", 1.15f, 1.0f, 10.0f);
gGameExternalOptions.fSetZeroUponNewSector = iniReader.ReadBoolean("Tactical Weapon Overheating Settings","OVERHEATING_SET_ZERO_UPON_NEW_SECTOR",TRUE);
//################# Tactical Zombie Settings ##################
gGameExternalOptions.sZombieRiseBehaviour = iniReader.ReadInteger("Tactical Zombie Settings", "ZOMBIE_RISE_BEHAVIOUR", 0, 0, 3);
gGameExternalOptions.fZombieSpawnWaves = iniReader.ReadInteger("Tactical Zombie Settings", "ZOMBIE_SPAWN_WAVES", FALSE);
gGameExternalOptions.sZombieRiseWaveFrequency = iniReader.ReadInteger("Tactical Zombie Settings", "ZOMBIE_RISE_WAVE_FREQUENCY", 30, 0, 100);
gGameExternalOptions.fZombieCanClimb = iniReader.ReadBoolean("Tactical Zombie Settings", "ZOMBIE_CAN_CLIMB", TRUE);
gGameExternalOptions.fZombieExplodingCivs = iniReader.ReadBoolean("Tactical Zombie Settings", "ZOMBIE_EXPLODING_CIVS", FALSE);
gGameExternalOptions.sEnemyZombieDamageResistance = iniReader.ReadInteger("Tactical Zombie Settings", "ZOMBIE_DAMAGE_RESISTANCE", 0, -50, 95);
gGameExternalOptions.fZombieOnlyHeadshotsWork = iniReader.ReadBoolean("Tactical Zombie Settings", "ZOMBIE_ONLY_HEADSHOTS_WORK", FALSE);
gGameExternalOptions.sZombieDifficultyLevel = iniReader.ReadInteger("Tactical Zombie Settings", "ZOMBIE_DIFFICULTY_LEVEL", 2, 1, 4);
//################# Tactical Poison Settings ##################
gGameExternalOptions.ubPoisonBaseMedicalSkillToCure = iniReader.ReadInteger("Tactical Poison Settings", "POISON_BASE_MEDICAL_SKILL_TO_CURE", 50, 1, 100);
gGameExternalOptions.sZombiePoisonDamagePercentage = iniReader.ReadInteger("Tactical Poison Settings", "ZOMBIE_POISON_DAMAGE_PERCENTAGE", 50, 0, 100);
gGameExternalOptions.sPoisonInfectionDamageMultiplier = iniReader.ReadFloat("Tactical Poison Settings", "POISON_INFECTION_DAMAGE_MULTIPLIER", 4.0, 1.0, 10.0);
//################# Strategic Gamestart Settings ##################
//Lalien: Game starting time
+17 -4
View File
@@ -89,9 +89,7 @@ enum
TOPTION_DISABLE_CURSOR_SWAP, // Disable cursor swapping every second between talk and quick exchange
TOPTION_QUIET_TRAINING, //Madd: mercs don't say gained experience quote while training
TOPTION_AUTO_FAST_FORWARD_MODE, // automatically fast forward through AI turns
// Flugente FTW 1: Weapon Overheating
//TOPTION_WEAPON_OVERHEATING, // allow Overheating of weapons
TOPTION_ZOMBIES, // Flugente Zombies 1.0: allow zombies
// arynn: Debug/Cheat
TOPTION_CHEAT_MODE_OPTIONS_HEADER,
@@ -107,7 +105,7 @@ enum
TOPTION_RETAIN_DEBUG_OPTIONS_IN_RELEASE, // allow debug options that were set in debug.exe to continue in a rel.exe (debugging release can be beneficial)
TOPTION_DEBUG_MODE_RENDER_OPTIONS_GROUP, // an example option that will show/hide other options
TOPTION_RENDER_MOUSE_REGIONS, // an example of a DEBUG build option
TOPTION_DEBUG_MODE_OPTIONS_END, // an example options screen options divider (pure text)
TOPTION_DEBUG_MODE_OPTIONS_END, // an example options screen options divider (pure text)
// this is THE LAST option that exists (intended for debugging the options screen, doesnt do anything, except exist)
TOPTION_LAST_OPTION,
@@ -365,6 +363,21 @@ typedef struct
//Video settings
BOOLEAN gfVSync;
// Flugente: zombie settings
INT8 sZombieRiseBehaviour;
BOOLEAN fZombieSpawnWaves;
INT8 sZombieRiseWaveFrequency;
BOOLEAN fZombieCanClimb;
BOOLEAN fZombieExplodingCivs;
INT8 sEnemyZombieDamageResistance;
BOOLEAN fZombieOnlyHeadshotsWork;
INT8 sZombieDifficultyLevel;
// Flugente: poison settings
INT32 ubPoisonBaseMedicalSkillToCure;
INT16 sZombiePoisonDamagePercentage;
FLOAT sPoisonInfectionDamageMultiplier;
//Animation settings
FLOAT giPlayerTurnSpeedUpFactor;
FLOAT giEnemyTurnSpeedUpFactor;
+2 -1
View File
@@ -20,8 +20,9 @@ extern CHAR16 zTrackingNumber[16];
//
// Keeps track of the saved game version. Increment the saved game version whenever
// you will invalidate the saved game file
#define SAVE_GAME_VERSION 131 //125 //124 //114 //113 //112 //111 //110 //109 //108 //107 //106 //105 //104 //103 //102 //101 //100 // 99
#define SAVE_GAME_VERSION 132 //131 //125 //124 //114 //113 //112 //111 //110 //109 //108 //107 //106 //105 //104 //103 //102 //101 //100 // 99
#define ZOMBIE_CHANGES 132 // Included some changes for Zombies
#define JA25_UB_INTEGRATION 131 // Before this, the JA25 Unfinished Business code was not integrated (see "Builddefines.h" JA2UB)
#define IMPROVED_INTERRUPT_SYSTEM 130
#define ENCYCLOPEDIA_SAVEGAME_CHANGE 129 // Added encyclopedia
+10 -2
View File
@@ -4959,7 +4959,7 @@ void DisplayDepartedCharStats(INT32 iId, INT32 iSlot, INT32 iState)
case 14:
// kills
mprintf((INT16)(pPersonnelScreenPoints[20].x+(iSlot*TEXT_BOX_WIDTH)),(pPersonnelScreenPoints[20].y - 12),pPersonnelScreenStrings[PRSNL_TXT_KILLS]);
swprintf(sString, L"%d",(gMercProfiles[iId].records.usKillsElites + gMercProfiles[iId].records.usKillsRegulars + gMercProfiles[iId].records.usKillsAdmins + gMercProfiles[iId].records.usKillsHostiles + gMercProfiles[iId].records.usKillsCreatures + gMercProfiles[iId].records.usKillsTanks + gMercProfiles[iId].records.usKillsOthers));
swprintf(sString, L"%d",(gMercProfiles[iId].records.usKillsElites + gMercProfiles[iId].records.usKillsRegulars + gMercProfiles[iId].records.usKillsAdmins + gMercProfiles[iId].records.usKillsHostiles + gMercProfiles[iId].records.usKillsCreatures + gMercProfiles[iId].records.usKillsZombies + gMercProfiles[iId].records.usKillsTanks + gMercProfiles[iId].records.usKillsOthers));
FindFontRightCoordinates((INT16)(pPersonnelScreenPoints[20].x+(iSlot*TEXT_BOX_WIDTH)),0,TEXT_BOX_WIDTH-20,0,sString, PERS_FONT, &sX, &sY);
mprintf(sX,(pPersonnelScreenPoints[20].y - 12),sString);
@@ -6824,7 +6824,7 @@ DEF:3/19/99:
case 14:
// kills
mprintf((INT16)(pPersonnelScreenPoints[20].x+(iSlot*TEXT_BOX_WIDTH)),(pPersonnelScreenPoints[20].y - 12),pPersonnelScreenStrings[PRSNL_TXT_KILLS]);
swprintf(sString, L"%d",(gMercProfiles[Menptr[iId].ubProfile].records.usKillsElites + gMercProfiles[Menptr[iId].ubProfile].records.usKillsRegulars + gMercProfiles[Menptr[iId].ubProfile].records.usKillsAdmins + gMercProfiles[Menptr[iId].ubProfile].records.usKillsHostiles + gMercProfiles[Menptr[iId].ubProfile].records.usKillsCreatures + gMercProfiles[Menptr[iId].ubProfile].records.usKillsTanks + gMercProfiles[Menptr[iId].ubProfile].records.usKillsOthers));
swprintf(sString, L"%d",(gMercProfiles[Menptr[iId].ubProfile].records.usKillsElites + gMercProfiles[Menptr[iId].ubProfile].records.usKillsRegulars + gMercProfiles[Menptr[iId].ubProfile].records.usKillsAdmins + gMercProfiles[Menptr[iId].ubProfile].records.usKillsHostiles + gMercProfiles[Menptr[iId].ubProfile].records.usKillsCreatures + gMercProfiles[Menptr[iId].ubProfile].records.usKillsZombies + gMercProfiles[Menptr[iId].ubProfile].records.usKillsTanks + gMercProfiles[Menptr[iId].ubProfile].records.usKillsOthers));
FindFontRightCoordinates((INT16)(pPersonnelScreenPoints[20].x+(iSlot*TEXT_BOX_WIDTH)),0,TEXT_BOX_WIDTH-20,0,sString, PERS_FONT, &sX, &sY);
mprintf(sX,(pPersonnelScreenPoints[20].y - 12),sString);
@@ -8235,6 +8235,14 @@ void AssignPersonnelKillsHelpText( INT32 IMercId )
swprintf(atStr, pPersonnelRecordsHelpTexts[ 6 ], gMercProfiles[Menptr[IMercId].ubProfile].records.usKillsOthers );
wcscat( apStr, atStr );
}
if (gGameSettings.fOptions[TOPTION_ZOMBIES] )
{
if (gMercProfiles[Menptr[IMercId].ubProfile].records.usKillsZombies > 0 || fShowRecordsIfZero)
{
swprintf(atStr, pPersonnelRecordsHelpTexts[ 46 ], gMercProfiles[Menptr[IMercId].ubProfile].records.usKillsZombies );
wcscat( apStr, atStr );
}
}
// Set region help text
SetRegionFastHelpText( &(gSkillTraitHelpTextRegion[7]), apStr );
+2 -2
View File
@@ -3570,7 +3570,7 @@ void recieveEXPLOSIONDAMAGE (RPCParameters *rpcParameters)
// can use DishOutGasDamage() as it is dependant on the local state of the gas cloud which is not always in sync
// but we have the definite results of damage on a merc, so :
pSoldier->SoldierTakeDamage( ANIM_STAND, exp->sWoundAmt, exp->sBreathAmt, TAKE_DAMAGE_GAS, NOBODY, NOWHERE, 0, TRUE );
pSoldier->SoldierTakeDamage( ANIM_STAND, exp->sWoundAmt, 0, exp->sBreathAmt, TAKE_DAMAGE_GAS, NOBODY, NOWHERE, 0, TRUE );
}
else if (exp->ubDamageFunc == 2)
{
@@ -4405,7 +4405,7 @@ void recieveDISCONNECT(RPCParameters* rpcParameters)
if ( !pTeamSoldier->aiData.bNeutral && (pTeamSoldier->bTeam == iNetbTeam ) )
{
// KIll......
pTeamSoldier->SoldierTakeDamage( ANIM_CROUCH, pTeamSoldier->stats.bLife, 100, TAKE_DAMAGE_BLOODLOSS, NOBODY, NOWHERE, 0, TRUE );
pTeamSoldier->SoldierTakeDamage( ANIM_CROUCH, pTeamSoldier->stats.bLife, 0, 100, TAKE_DAMAGE_BLOODLOSS, NOBODY, NOWHERE, 0, TRUE );
}
}
}
Binary file not shown.
+9
View File
@@ -1972,6 +1972,12 @@ BOOLEAN SOLDIERTYPE::Load(HWFILE hFile)
numBytesRead = ReadFieldByField(hFile, &this->wornSnowCamo, sizeof(wornSnowCamo), sizeof(INT8), numBytesRead);
numBytesRead = ReadFieldByField(hFile, &this->sFacilityTypeOperated, sizeof(sFacilityTypeOperated), sizeof(INT16), numBytesRead);
numBytesRead = ReadFieldByField(hFile, &this->bScopeMode, sizeof(bScopeMode), sizeof(INT8), numBytesRead);
numBytesRead = ReadFieldByField(hFile, &this->bPoisonBleeding, sizeof(bPoisonBleeding), sizeof(INT8), numBytesRead);
numBytesRead = ReadFieldByField(hFile, &this->bPoisonLife, sizeof(bPoisonLife), sizeof(INT8), numBytesRead);
numBytesRead = ReadFieldByField(hFile, &this->bPoisonSum, sizeof(bPoisonSum), sizeof(INT8), numBytesRead);
numBytesRead = ReadFieldByField(hFile, &this->bPoisonResistance, sizeof(bPoisonResistance), sizeof(INT16), numBytesRead);
numBytesRead = ReadFieldByField(hFile, &this->bPoisonAbsorption, sizeof(bPoisonAbsorption), sizeof(INT16), numBytesRead);
#ifdef JA2UB
numBytesRead = ReadFieldByField(hFile, &this->fIgnoreGetupFromCollapseCheck, sizeof(fIgnoreGetupFromCollapseCheck), sizeof(BOOLEAN), numBytesRead);
numBytesRead = ReadFieldByField(hFile, &this->GetupFromJA25StartCounter, sizeof(GetupFromJA25StartCounter), sizeof(TIMECOUNTER), numBytesRead);
@@ -2181,6 +2187,9 @@ BOOLEAN SOLDIERTYPE::Load(HWFILE hFile)
buffer = 28;
}
numBytesRead += buffer;
INT32 sizestruct = sizeof(STRUCT_Statistics);
if(numBytesRead != sizeof(STRUCT_Statistics))
return(FALSE);
// if ( !FileRead( hFile, &this->stats, sizeof(STRUCT_Statistics), &uiNumBytesRead ) )
+219 -17
View File
@@ -571,6 +571,8 @@ static BOOLEAN IsGunJammed(const OBJECTTYPE* pObj);
/// Collect items that need repairing and add them to the repair queue
static void CollectRepairableItems(const SOLDIERTYPE* pSoldier, RepairQueue& itemsToFix);
extern BOOLEAN HandleSoldierDeath( SOLDIERTYPE *pSoldier , BOOLEAN *pfMadeCorpse );
void InitSectorsWithSoldiersList( void )
{
// init list of sectors
@@ -1121,6 +1123,11 @@ BOOLEAN CanCharacterPatient( SOLDIERTYPE *pSoldier )
if ( pSoldier->ubCriticalStatDamage[i] > 0 )
return ( TRUE );
}
// Flugente: check if poisoned
if ( pSoldier->bPoisonSum > 0 )
return( TRUE );
// if we don't have damaged stat, look if we need healing
if ( pSoldier->stats.bLife == pSoldier->stats.bLifeMax )
return( FALSE );
@@ -2669,8 +2676,8 @@ void UpdatePatientsWhoAreDoneHealing( void )
// active soldier?
if( pTeamSoldier->bActive )
{
// patient who doesn't need healing
if( ( pTeamSoldier->bAssignment == PATIENT ) &&( pTeamSoldier->stats.bLife == pTeamSoldier->stats.bLifeMax ) )
// patient who doesn't need healing or curing
if( ( pTeamSoldier->bAssignment == PATIENT ) &&( pTeamSoldier->stats.bLife == pTeamSoldier->stats.bLifeMax ) && ( pTeamSoldier->bPoisonSum == 0 ) )
{
// SANDRO - added check if we can help to heal lost stats to this one
for (UINT8 cnt = 0; cnt < NUM_DAMAGABLE_STATS; cnt++)
@@ -2937,8 +2944,21 @@ BOOLEAN CanSoldierBeHealedByDoctor( SOLDIERTYPE *pSoldier, SOLDIERTYPE *pDoctor,
// if we have no damaged stat and don't need healing
if (!fHealDamagedStat && (pSoldier->stats.bLife == pSoldier->stats.bLifeMax) )
{
// cannot be healed
return( FALSE );
// if we are poisoned
if ( pSoldier->bPoisonSum )
{
// if using the new trait system, Doctor skill is needed
if ( gGameOptions.fNewTraitSystem && ( NUM_SKILL_TRAITS( pDoctor, DOCTOR_NT ) == 0 ) )
{
// we may have the medical stats, but we lack the skills!
return( FALSE );
}
}
else // if we are not poisoned
{
// cannot be healed
return( FALSE );
}
}
return( TRUE );
@@ -2954,6 +2974,12 @@ UINT8 GetMinHealingSkillNeeded( SOLDIERTYPE *pPatient )
// less than ok life, return skill needed
return( gGameExternalOptions.ubBaseMedicalSkillToDealWithEmergency + ( gGameExternalOptions.ubMultiplierForDifferenceInLifeValueForEmergency * ( OKLIFE - pPatient->stats.bLife ) ) );
}
// if at full life, only poison needs to be removed
else if ( pPatient->stats.bLife == pPatient->stats.bLifeMax && pPatient->bPoisonSum > 0 )
{
// skill to remove poison needed
return( gGameExternalOptions.ubPoisonBaseMedicalSkillToCure );
}
else
{
// only need some skill
@@ -2967,16 +2993,19 @@ UINT16 HealPatient( SOLDIERTYPE *pPatient, SOLDIERTYPE * pDoctor, UINT16 usHundr
//////////////////////////////////////////////////////////////////////////////
// SANDRO - this whole procedure was heavily changed
////////////////////////////////////////////////////
UINT16 usHealingPtsLeft;
UINT16 usHealingPtsLeft = 0;
UINT16 usTotalHundredthsUsed = 0;
INT16 sPointsToUse = 0;
INT8 bPointsHealed = 0;
INT8 bMedFactor;
INT8 bMedFactor = 1; // basic medical factor
BOOLEAN fWillRepiarStats = FALSE;
BOOLEAN fWillHealLife = TRUE;
BOOLEAN fWillHealLife = TRUE;
UINT16 usTotalMedPoints = 0;
UINT16 ubReturnDamagedStatRate = 0;
// usPointsLeftToCurePoison will measure how much Hundreths will be left to cure poison
INT16 usPointsLeftToCurePoison = usHundredthsHealed;
// Look how much life do we need to heal
sPointsToUse = ( pPatient->stats.bLifeMax - pPatient->stats.bLife );
if ( sPointsToUse <= 0 )
@@ -3008,7 +3037,6 @@ UINT16 HealPatient( SOLDIERTYPE *pPatient, SOLDIERTYPE * pDoctor, UINT16 usHundr
sPointsToUse = ( INT8 )usHealingPtsLeft;
}
bMedFactor = 1; // basic medical factor
// if we will heal life and stats at the same time, increases the medical cost
if (fWillRepiarStats && fWillHealLife)
{
@@ -3071,6 +3099,10 @@ UINT16 HealPatient( SOLDIERTYPE *pPatient, SOLDIERTYPE * pDoctor, UINT16 usHundr
}
}
// we have to remember what will be left over to cure poison
//usPointsLeftToCurePoison = min(usHundredthsHealed, usPointsLeftToCurePoison - usTotalHundredthsUsed);
//usPointsLeftToCurePoison = max(usPointsLeftToCurePoison, 0); // do not go below zero
// if we are actually here to heal life
if ( fWillHealLife )
{
@@ -3084,6 +3116,16 @@ UINT16 HealPatient( SOLDIERTYPE *pPatient, SOLDIERTYPE * pDoctor, UINT16 usHundr
pPatient->sFractLife %= 100;
pPatient->stats.bLife = min( pPatient->stats.bLifeMax, (pPatient->stats.bLife + bPointsHealed));
// potentially increase bPoisonLife: as life points are healed, unhealed poinson points become healed poison points
if ( pPatient->bPoisonSum > 0 )
{
// check if there are unhealed poison points
if ( pPatient->bPoisonLife < pPatient->bPoisonSum )
{
pPatient->bPoisonLife = min( pPatient->bPoisonSum, (pPatient->bPoisonLife + bPointsHealed));
}
}
}
else if (((pPatient->sFractLife / gGameExternalOptions.ubPointCostPerHealthBelowOkLife) >= 100) && (pPatient->stats.bLife < OKLIFE))
{
@@ -3091,6 +3133,16 @@ UINT16 HealPatient( SOLDIERTYPE *pPatient, SOLDIERTYPE * pDoctor, UINT16 usHundr
pPatient->sFractLife %= 100;
pPatient->stats.bLife = min( pPatient->stats.bLifeMax, (pPatient->stats.bLife + bPointsHealed));
// potentially increase bPoisonLife: as life points are healed, unhealed poinson points become healed poison points
if ( pPatient->bPoisonSum > 0 )
{
// check if there are unhealed poison points
if ( pPatient->bPoisonLife < pPatient->bPoisonSum )
{
pPatient->bPoisonLife = min( pPatient->bPoisonSum, (pPatient->bPoisonLife + bPointsHealed));
}
}
}
// when being healed normally, reduce insta-healable HPs value
@@ -3113,6 +3165,65 @@ UINT16 HealPatient( SOLDIERTYPE *pPatient, SOLDIERTYPE * pDoctor, UINT16 usHundr
}
}
// As curing poison happens only when there is no more life to heal ortats to repair, we don't have to edit the above function - we simply cure afterwards
// Look how much poison needs to be cured. Conversion of fresh life points to poison points has already taken place
if ( pPatient->bPoisonSum > 0 || pPatient->sFractLife < 0 )
{
if ( fWillHealLife || fWillRepiarStats )
usPointsLeftToCurePoison = max(0, usPointsLeftToCurePoison - usHundredthsHealed);
if ( usPointsLeftToCurePoison > 0 )
{
INT8 usPoisontoCure = pPatient->bPoisonSum;
if ( (INT8) (usPointsLeftToCurePoison/100) < usPoisontoCure )
usPoisontoCure = (INT8) (usPointsLeftToCurePoison/100);
// calculate how much total points we have in all medical bags
UINT16 usTotalMedPointsLeft = TotalMedicalKitPoints(pDoctor);
if ( usTotalMedPointsLeft > 0 )
{
UINT16 usTotalHundredthsUsedToCurePoison = 0;
// if having enough, no problem
if (usTotalMedPointsLeft >= (usPoisontoCure * bMedFactor))
{
usTotalHundredthsUsedToCurePoison = usPoisontoCure * 100;
usTotalMedPointsLeft = (usPoisontoCure * bMedFactor);
}
else
{
// only heal what we have
usTotalHundredthsUsedToCurePoison = (usTotalMedPointsLeft * 100 / bMedFactor) ;
}
pPatient->sFractLife += usTotalHundredthsUsedToCurePoison;
// modify usHundredthsHealed?
//usHundredthsHealed += usTotalHundredthsUsedToCurePoison;
if (pPatient->sFractLife >= 100)
{
// convert fractions into full points
INT8 bPoisonPointsHealed = (pPatient->sFractLife / 100);
pPatient->sFractLife %= 100;
pPatient->bPoisonSum = max( 0, (pPatient->bPoisonSum - bPoisonPointsHealed));
pPatient->bPoisonLife = max( 0, (pPatient->bPoisonLife - bPoisonPointsHealed));
}
// Finally use all kit points (we are sure, we have that much)
if (UseTotalMedicalKitPoints( pDoctor, usTotalMedPointsLeft ) == FALSE )
{
// throw message if this went wrong for feedback on debugging
#ifdef JA2TESTVERSION
ScreenMsg( FONT_MCOLOR_RED, MSG_TESTVERSION, L"Warning! UseTotalKitPOints returned false, not all points were probably used." );
#endif
}
}
}
}
return ( usHundredthsHealed );
}
@@ -3176,13 +3287,23 @@ void HealHospitalPatient( SOLDIERTYPE *pPatient, UINT16 usHealingPtsLeft )
// if he needs more than we have, reduce to that
if( bPointsToUse > usHealingPtsLeft )
{
bPointsToUse = ( INT8 )usHealingPtsLeft;
bPointsToUse = ( INT8 )usHealingPtsLeft;
}
usHealingPtsLeft -= bPointsToUse;
// heal person the amount / POINT_COST_PER_HEALTH_BELOW_OKLIFE
pPatient->stats.bLife += ( bPointsToUse / gGameExternalOptions.ubPointCostPerHealthBelowOkLife );
// potentially increase bPoisonLife: as life points are healed, unhealed poinson points become healed poison points
if ( pPatient->bPoisonSum > 0 )
{
// check if there are unhealed poison points
if ( pPatient->bPoisonLife < pPatient->bPoisonSum )
{
pPatient->bPoisonLife = min( pPatient->bPoisonSum, (pPatient->bPoisonLife + ( bPointsToUse / gGameExternalOptions.ubPointCostPerHealthBelowOkLife ) ) );
}
}
// SANDRO - doctor trait - when being healed normally, reduce insta-healable HPs value
if ( gGameOptions.fNewTraitSystem && pPatient->iHealableInjury > 0 )
@@ -3209,6 +3330,16 @@ void HealHospitalPatient( SOLDIERTYPE *pPatient, UINT16 usHealingPtsLeft )
// heal person the amount
pPatient->stats.bLife += bPointsToUse;
// potentially increase bPoisonLife: as life points are healed, unhealed poinson points become healed poison points
if ( pPatient->bPoisonSum > 0 )
{
// check if there are unhealed poison points
if ( pPatient->bPoisonLife < pPatient->bPoisonSum )
{
pPatient->bPoisonLife = min( pPatient->bPoisonSum, (pPatient->bPoisonLife + bPointsToUse) );
}
}
// SANDRO - doctor trait - when being healed normally, reduce insta-healable HPs value
if ( gGameOptions.fNewTraitSystem && pPatient->iHealableInjury > 0 )
@@ -3219,8 +3350,21 @@ void HealHospitalPatient( SOLDIERTYPE *pPatient, UINT16 usHealingPtsLeft )
}
}
// if this patient is fully healed
if ( pPatient->stats.bLife == pPatient->stats.bLifeMax )
// are here still points left to cure poison?
if ( usHealingPtsLeft > 0 )
{
UINT16 usPoisonToCure = pPatient->bPoisonSum;
if ( usPoisonToCure > usHealingPtsLeft )
usPoisonToCure = usHealingPtsLeft;
usHealingPtsLeft -= usPoisonToCure;
pPatient->bPoisonSum = max( 0, (pPatient->bPoisonSum - usPoisonToCure));
}
// if this patient is fully healed and cured
if ( pPatient->stats.bLife == pPatient->stats.bLifeMax && pPatient->bPoisonSum == 0 )
{
AssignmentDone( pPatient, TRUE, TRUE );
}
@@ -4550,7 +4694,7 @@ INT16 GetBonusTrainingPtsDueToInstructor( SOLDIERTYPE *pInstructor, SOLDIERTYPE
switch( bTrainStat )
{
case( STRENGTH ):
bTrainerEffSkill = EffectiveStrength ( pInstructor );
bTrainerEffSkill = (INT8)EffectiveStrength ( pInstructor );
bTrainerNatSkill = pInstructor->stats.bStrength;
break;
case( DEXTERITY ):
@@ -5428,6 +5572,7 @@ void HandleNaturalHealing( void )
void HandleHealingByNaturalCauses( SOLDIERTYPE *pSoldier )
{
UINT32 uiPercentHealth = 0;
UINT32 uiPercentPoison = 0;
INT8 bActivityLevelDivisor = 0;
UINT16 usFacilityModifier = 100;
UINT8 ubAssignmentType = 0;
@@ -5446,7 +5591,7 @@ void HandleHealingByNaturalCauses( SOLDIERTYPE *pSoldier )
}
// lost any pts?
if( pSoldier->stats.bLife == pSoldier->stats.bLifeMax )
if( pSoldier->stats.bLife == pSoldier->stats.bLifeMax && pSoldier->bPoisonLife == 0 )
{
return;
}
@@ -5498,6 +5643,9 @@ void HandleHealingByNaturalCauses( SOLDIERTYPE *pSoldier )
// what percentage of health is he down to
uiPercentHealth = ( pSoldier->stats.bLife * 100 ) / pSoldier->stats.bLifeMax;
// how much is he poisoned?
uiPercentPoison = ( pSoldier->bPoisonSum * 100 ) / pSoldier->stats.bLifeMax;
// SANDRO - experimental - increase health regenariton of soldiers when doctors are around
if ( gGameOptions.fNewTraitSystem )
{
@@ -5539,6 +5687,11 @@ void HandleHealingByNaturalCauses( SOLDIERTYPE *pSoldier )
pSoldier->sFractLife += ( INT16 ) ((( uiPercentHealth / bActivityLevelDivisor ) * usFacilityModifier) / 100 );
}
// Flugente: reduce gained life because of poison
// poison resistance reduces poison damage
// a high activity level (stress) increases poisoning
pSoldier->sFractLife -= ( INT16 ) ( (uiPercentPoison * (100 - pSoldier->GetPoisonResistance())/100) * gGameExternalOptions.sPoisonInfectionDamageMultiplier * ((99 + bActivityLevelDivisor)/100) );
// now update the real life values
UpDateSoldierLife( pSoldier );
@@ -5549,12 +5702,45 @@ void HandleHealingByNaturalCauses( SOLDIERTYPE *pSoldier )
void UpDateSoldierLife( SOLDIERTYPE *pSoldier )
{
// update soldier life, make sure we don't go out of bounds
pSoldier->stats.bLife += pSoldier->sFractLife / 100;
INT8 sAddedLife = pSoldier->sFractLife/100;
// if sAddedLife, it must be poison damage
if ( sAddedLife < 0 )
{
// it is hereby possible to heal yourself through poison, if you have high absorption ( > 100%)
INT8 sPoisonAbsorped = - (INT8) ( sAddedLife * (pSoldier->GetPoisonAbsorption()/100) );
sAddedLife += sPoisonAbsorped;
// if we're not fully poisoned, we are now poisoned a bit more, even if we won life thanks to absorption
if ( pSoldier->bPoisonSum < pSoldier->stats.bLifeMax )
{
pSoldier->bPoisonSum += abs(sAddedLife);
}
}
INT8 oldlife = pSoldier->stats.bLife;
pSoldier->stats.bLife += sAddedLife;
// if we fall below OKLIFE (can only be because of poison), we start bleeding again...
if ( pSoldier->stats.bLife < OKLIFE && oldlife >= OKLIFE && sAddedLife < 0 )
{
/*pSoldier->stats.bLife = 0;
BOOLEAN fMadeCorpse;
HandleSoldierDeath( pSoldier, &fMadeCorpse );*/
pSoldier->bBleeding = pSoldier->stats.bLifeMax - pSoldier->stats.bLife;
pSoldier->bPoisonBleeding = pSoldier->bPoisonSum - pSoldier->bPoisonLife;
/*pSoldier->bPoisonSum = 0;
pSoldier->bPoisonLife = 0;
pSoldier->bPoisonBleeding = 0;*/
}
// SANDRO - when being healed normally, reduce insta-healable HPs value
if ( gGameOptions.fNewTraitSystem && pSoldier->iHealableInjury > 0 )
{
pSoldier->iHealableInjury -= pSoldier->sFractLife;
pSoldier->iHealableInjury -= sAddedLife * 100;
if (pSoldier->iHealableInjury < 0)
pSoldier->iHealableInjury = 0;
@@ -5568,7 +5754,11 @@ void UpDateSoldierLife( SOLDIERTYPE *pSoldier )
{
// reduce
pSoldier->stats.bLife = pSoldier->stats.bLifeMax;
pSoldier->sFractLife = 0;
// only set sFractLife to be 0 if > 0, saving possible poison damage
if ( pSoldier->sFractLife > 0 )
pSoldier->sFractLife = 0;
pSoldier->iHealableInjury = 0; // check added by SANDRO
}
return;
@@ -8107,7 +8297,9 @@ void BeginRemoveMercFromContract( SOLDIERTYPE *pSoldier )
// WANNE: Nothing to do here, when we want to dismiss the robot
BOOLEAN fAmIaRobot = AM_A_ROBOT( pSoldier );
if (!fAmIaRobot)
// Flugente: If merc is unconscious, just fire him anyway (if talking stuff is called, this leads to a geme lock)
if (!fAmIaRobot && pSoldier->stats.bLife > CONSCIOUSNESS )
{
if( ( pSoldier->ubWhatKindOfMercAmI == MERC_TYPE__MERC ) || ( pSoldier->ubWhatKindOfMercAmI == MERC_TYPE__NPC ) )
{
@@ -10938,6 +11130,7 @@ void SetSoldierAssignment( SOLDIERTYPE *pSoldier, INT8 bAssignment, INT32 iParam
pSoldier->bOldAssignment = pSoldier->bAssignment;
pSoldier->bBleeding = 0;
pSoldier->bPoisonBleeding = 0;
// set dirty flag
fTeamPanelDirty = TRUE;
@@ -12219,6 +12412,7 @@ void BandageBleedingDyingPatientsBeingTreated( )
// stop bleeding automatically
pSoldier->bBleeding = 0;
pSoldier->bPoisonBleeding = 0;
if ( pSoldier->stats.bLife < OKLIFE )
{
@@ -12227,7 +12421,14 @@ void BandageBleedingDyingPatientsBeingTreated( )
{
pSoldier->iHealableInjury -= ((OKLIFE - pSoldier->stats.bLife) * 100);
}
// convert poison points to poison life points
INT8 oldlife = pSoldier->stats.bLife;
pSoldier->stats.bLife = OKLIFE;
INT8 lifegained = OKLIFE - oldlife;
pSoldier->bPoisonLife = min(pSoldier->bPoisonSum, pSoldier->bPoisonLife + lifegained);
}
}
else // assigned to DOCTOR/PATIENT
@@ -16417,3 +16618,4 @@ void HaveMercSayWhyHeWontLeave( SOLDIERTYPE *pSoldier )
}
}
#endif
+63 -5
View File
@@ -729,6 +729,9 @@ void RefreshMerc( SOLDIERTYPE *pSoldier )
{
pSoldier->stats.bLife = pSoldier->stats.bLifeMax;
pSoldier->bBleeding = 0;
pSoldier->bPoisonSum = 0;
pSoldier->bPoisonLife = 0;
pSoldier->bPoisonBleeding = 0;
pSoldier->iHealableInjury = 0; // added by SANDRO
pSoldier->bBreath = pSoldier->bBreathMax = 100;
pSoldier->sBreathRed = 0;
@@ -1189,14 +1192,43 @@ void RenderSoldierCellBars( SOLDIERCELL *pCell )
iStartY = pCell->yp + 29 - 25*pCell->pSoldier->stats.bLifeMax/100;
ColorFillVideoSurfaceArea( FRAME_BUFFER, pCell->xp+37, iStartY, pCell->xp+38, pCell->yp+29, Get16BPPColor( FROMRGB( 107, 107, 57 ) ) );
ColorFillVideoSurfaceArea( FRAME_BUFFER, pCell->xp+38, iStartY, pCell->xp+39, pCell->yp+29, Get16BPPColor( FROMRGB( 222, 181, 115 ) ) );
// poisoned bleeding in purple
if ( pCell->pSoldier->bPoisonBleeding )
{
iStartY = pCell->yp + 29 - 25*(pCell->pSoldier->stats.bLifeMax - pCell->pSoldier->bBleeding + pCell->pSoldier->bPoisonBleeding)/100;
ColorFillVideoSurfaceArea( FRAME_BUFFER, pCell->xp+37, iStartY, pCell->xp+38, pCell->yp+29, Get16BPPColor( FROMRGB( 107, 57, 107 ) ) );
ColorFillVideoSurfaceArea( FRAME_BUFFER, pCell->xp+38, iStartY, pCell->xp+39, pCell->yp+29, Get16BPPColor( FROMRGB( 222, 115, 181 ) ) );
}
//pink one for bandaged.
iStartY += 25*pCell->pSoldier->bBleeding/100;
iStartY = pCell->yp + 29 - 25*(pCell->pSoldier->stats.bLifeMax - pCell->pSoldier->bBleeding)/100;
ColorFillVideoSurfaceArea( FRAME_BUFFER, pCell->xp+37, iStartY, pCell->xp+38, pCell->yp+29, Get16BPPColor( FROMRGB( 156, 57, 57 ) ) );
ColorFillVideoSurfaceArea( FRAME_BUFFER, pCell->xp+38, iStartY, pCell->xp+39, pCell->yp+29, Get16BPPColor( FROMRGB( 222, 132, 132 ) ) );
// get amount of poisoned bandage
INT8 bPoisonBandage = pCell->pSoldier->bPoisonSum - pCell->pSoldier->bPoisonBleeding - pCell->pSoldier->bPoisonLife;
if ( bPoisonBandage )
{
// poisoned bandage in bright green
iStartY = pCell->yp + 29 - 25*(pCell->pSoldier->stats.bLife + bPoisonBandage)/100;
ColorFillVideoSurfaceArea( FRAME_BUFFER, pCell->xp+37, iStartY, pCell->xp+38, pCell->yp+29, Get16BPPColor( FROMRGB( 57, 156, 57 ) ) );
ColorFillVideoSurfaceArea( FRAME_BUFFER, pCell->xp+38, iStartY, pCell->xp+39, pCell->yp+29, Get16BPPColor( FROMRGB( 132, 222, 132 ) ) );
}
//red one for actual health
iStartY = pCell->yp + 29 - 25*pCell->pSoldier->stats.bLife/100;
ColorFillVideoSurfaceArea( FRAME_BUFFER, pCell->xp+37, iStartY, pCell->xp+38, pCell->yp+29, Get16BPPColor( FROMRGB( 107, 8, 8 ) ) );
ColorFillVideoSurfaceArea( FRAME_BUFFER, pCell->xp+38, iStartY, pCell->xp+39, pCell->yp+29, Get16BPPColor( FROMRGB( 206, 0, 0 ) ) );
// poisoned life
if ( pCell->pSoldier->bPoisonLife )
{
iStartY = pCell->yp + 29 - 25*pCell->pSoldier->bPoisonLife/100;
ColorFillVideoSurfaceArea( FRAME_BUFFER, pCell->xp+37, iStartY, pCell->xp+38, pCell->yp+29, Get16BPPColor( FROMRGB( 8, 107, 8 ) ) );
ColorFillVideoSurfaceArea( FRAME_BUFFER, pCell->xp+38, iStartY, pCell->xp+39, pCell->yp+29, Get16BPPColor( FROMRGB( 0, 206, 0 ) ) );
}
//BREATH BAR
iStartY = pCell->yp + 29 - 25*pCell->pSoldier->bBreathMax/100;
ColorFillVideoSurfaceArea( FRAME_BUFFER, pCell->xp+41, iStartY, pCell->xp+42, pCell->yp+29, Get16BPPColor( FROMRGB( 8, 8, 132 ) ) );
@@ -1519,6 +1551,11 @@ UINT32 VirtualSoldierDressWound( SOLDIERTYPE *pSoldier, SOLDIERTYPE *pVictim, OB
pVictim->stats.bLife = OKLIFE;
// reduce bleeding by the same number of life points healed up
pVictim->bBleeding -= bBelowOKlife;
// Flugente: increase bPoisonLife, decrease bPoisonBleeding
pVictim->bPoisonLife = min(pVictim->bPoisonSum, pVictim->bPoisonLife + bBelowOKlife);
pVictim->bPoisonBleeding = max(0, pVictim->bPoisonBleeding - bBelowOKlife);
// use up appropriate # of actual healing points
bPtsLeft -= (2 * bBelowOKlife);
}
@@ -1533,12 +1570,20 @@ UINT32 VirtualSoldierDressWound( SOLDIERTYPE *pSoldier, SOLDIERTYPE *pVictim, OB
}
pVictim->stats.bLife += ( bPtsLeft / 2);
pVictim->bBleeding -= ( bPtsLeft / 2);
// Flugente: increase bPoisonLife, decrease bPoisonBleeding
pVictim->bPoisonLife = min(pVictim->bPoisonSum, pVictim->bPoisonLife + ( bPtsLeft / 2));
pVictim->bPoisonBleeding = max(0, pVictim->bPoisonBleeding - ( bPtsLeft / 2));
bPtsLeft = bPtsLeft % 2; // if ptsLeft was odd, ptsLeft = 1
}
// this should never happen any more, but make sure bleeding not negative
if (pVictim->bBleeding < 0)
{
pVictim->bBleeding = 0;
pVictim->bPoisonBleeding = 0;
}
// if this healing brought the patient out of the worst of it, cancel dying
if (pVictim->stats.bLife >= OKLIFE )
@@ -1612,22 +1657,27 @@ UINT32 VirtualSoldierDressWound( SOLDIERTYPE *pSoldier, SOLDIERTYPE *pVictim, OB
if ((pVictim->stats.bLife + (iLifeReturned / 100)) <= pVictim->stats.bLifeMax)
{
pVictim->stats.bLife += (iLifeReturned/100);
pVictim->bPoisonLife = min(pVictim->bPoisonSum, pVictim->bPoisonLife + (iLifeReturned/100));
if (pVictim->bBleeding >= (iLifeReturned/100))
{
pVictim->bBleeding -= (iLifeReturned/100);
pVictim->bPoisonBleeding = max(0, pVictim->bPoisonBleeding - (iLifeReturned/100));
uiMedcost += (iLifeReturned / 200); // add medkit points cost for unbandaged part
}
else
{
pVictim->bBleeding = 0;
pVictim->bPoisonBleeding = 0;
uiMedcost += max( 0, (((iLifeReturned/100) - pVictim->bBleeding) / 2)); // add medkit points cost for unbandaged part
}
}
else // this shouldn't even happen, but we still want to have it here for sure
{
pVictim->stats.bLife = pVictim->stats.bLifeMax;
pVictim->bPoisonLife = pVictim->bPoisonSum;
pVictim->iHealableInjury = 0;
pVictim->bBleeding = 0;
pVictim->bPoisonBleeding = 0;
}
// Reduce max breath based on life returned
if ( (pVictim->bBreathMax - (((iLifeReturned/100) * gSkillTraitValues.usDOSurgeryMaxBreathLoss )/ 100)) <= BREATHMAX_ABSOLUTE_MINIMUM )
@@ -1654,10 +1704,12 @@ UINT32 VirtualSoldierDressWound( SOLDIERTYPE *pSoldier, SOLDIERTYPE *pVictim, OB
{
bPtsLeft -= pVictim->bBleeding;
pVictim->bBleeding = 0;
pVictim->bPoisonBleeding = 0;
}
else // bandage what we can
{
pVictim->bBleeding -= bPtsLeft;
pVictim->bPoisonBleeding = max(0, pVictim->bPoisonBleeding - bPtsLeft);
bPtsLeft = 0;
}
}
@@ -4541,13 +4593,16 @@ void AttackTarget( SOLDIERCELL *pAttacker, SOLDIERCELL *pTarget )
case SOLDIER_CLASS_CREATURE :
gMercProfiles[ pAttacker->pSoldier->ubProfile ].records.usKillsCreatures++;
break;
case SOLDIER_CLASS_ZOMBIE :
gMercProfiles[ pAttacker->pSoldier->ubProfile ].records.usKillsZombies++;
break;
default :
if ( CREATURE_OR_BLOODCAT( pTarget->pSoldier ) )
gMercProfiles[ pAttacker->pSoldier->ubProfile ].records.usKillsCreatures++;
else if ( TANK( pTarget->pSoldier ) ) // we hardly can kill a tank in autoresolve, but well.. who knows..
gMercProfiles[ pAttacker->pSoldier->ubProfile ].records.usKillsTanks++;
else if ( pTarget->pSoldier->bTeam == CIV_TEAM && !pTarget->pSoldier->aiData.bNeutral && pTarget->pSoldier->bSide != gbPlayerNum )
gMercProfiles[ pAttacker->pSoldier->ubProfile ].records.usKillsHostiles++;
else if ( TANK( pTarget->pSoldier ) ) // we hardly can kill a tank in autoresolve, but well.. who knows..
gMercProfiles[ pAttacker->pSoldier->ubProfile ].records.usKillsTanks++;
else if ( pTarget->pSoldier->bTeam == CIV_TEAM && !pTarget->pSoldier->aiData.bNeutral && pTarget->pSoldier->bSide != gbPlayerNum )
gMercProfiles[ pAttacker->pSoldier->ubProfile ].records.usKillsHostiles++;
else
gMercProfiles[ pAttacker->pSoldier->ubProfile ].records.usKillsOthers++;
break;
@@ -4729,6 +4784,9 @@ void TargetHitCallback( SOLDIERCELL *pTarget, INT32 index )
case SOLDIER_CLASS_CREATURE :
gMercProfiles[ pKiller->pSoldier->ubProfile ].records.usKillsCreatures++;
break;
case SOLDIER_CLASS_ZOMBIE :
gMercProfiles[ pKiller->pSoldier->ubProfile ].records.usKillsZombies++;
break;
default :
if ( CREATURE_OR_BLOODCAT( pTarget->pSoldier ) )
gMercProfiles[ pKiller->pSoldier->ubProfile ].records.usKillsCreatures++;
+1 -1
View File
@@ -1722,7 +1722,7 @@ void HandleRisksForSoldierFacilityAssignment( SOLDIERTYPE *pSoldier, UINT8 ubFac
if (Result < 0)
{
// Soldier is suffering direct unbandaged injury.
pSoldier->SoldierTakeDamage( 0, abs(Result), abs(Result), TAKE_DAMAGE_BLOODLOSS, NOBODY, NOWHERE, 0, FALSE );
pSoldier->SoldierTakeDamage( 0, abs(Result), 0, abs(Result), TAKE_DAMAGE_BLOODLOSS, NOBODY, NOWHERE, 0, FALSE );
fBadResult = TRUE;
// SANDRO - add to merc records - facility accidents counter
+44 -5
View File
@@ -1972,10 +1972,23 @@ void UpdateCharRegionHelpText( void )
{
// person (health/energy/morale)
GetMoraleString( pSoldier, pMoraleStr );
swprintf( sString, L"%s: %d/%d, %s: %d/%d, %s: %s",
pMapScreenStatusStrings[ 0 ], pSoldier->stats.bLife, pSoldier->stats.bLifeMax,
pMapScreenStatusStrings[ 1 ], pSoldier->bBreath, pSoldier->bBreathMax,
pMapScreenStatusStrings[ 2 ], pMoraleStr );
if ( pSoldier->bPoisonSum )
{
INT8 bPoisonBandaged = pSoldier->bPoisonSum - pSoldier->bPoisonBleeding - pSoldier->bPoisonLife;
swprintf( sString, L"%s: %d/%d, %s: %d/%d/%d - %d, %s: %d/%d, %s: %s",
pMapScreenStatusStrings[ 0 ], pSoldier->stats.bLife, pSoldier->stats.bLifeMax,
pMapScreenStatusStrings[ 5 ], pSoldier->bPoisonBleeding, bPoisonBandaged, pSoldier->bPoisonLife, pSoldier->bPoisonSum,
pMapScreenStatusStrings[ 1 ], pSoldier->bBreath, pSoldier->bBreathMax,
pMapScreenStatusStrings[ 2 ], pMoraleStr );
}
else
{
swprintf( sString, L"%s: %d/%d, %s: %d/%d, %s: %s",
pMapScreenStatusStrings[ 0 ], pSoldier->stats.bLife, pSoldier->stats.bLifeMax,
pMapScreenStatusStrings[ 1 ], pSoldier->bBreath, pSoldier->bBreathMax,
pMapScreenStatusStrings[ 2 ], pMoraleStr );
}
}
}
else
@@ -5358,16 +5371,42 @@ void RenderSoldierSmallFaceForUpdatePanel( INT32 iIndex, INT32 iX, INT32 iY )
ColorFillVideoSurfaceArea( guiSAVEBUFFER, iX+36, iStartY, iX+37, iY+29, Get16BPPColor( FROMRGB( 107, 107, 57 ) ) );
ColorFillVideoSurfaceArea( guiSAVEBUFFER, iX+37, iStartY, iX+38, iY+29, Get16BPPColor( FROMRGB( 222, 181, 115 ) ) );
if ( pSoldier->bPoisonBleeding )
{
// poisoned bleeding in purple
iStartY = iY + 29 - 27*(pSoldier->stats.bLifeMax - pSoldier->bBleeding + pSoldier->bPoisonBleeding)/100;
ColorFillVideoSurfaceArea( guiSAVEBUFFER, iX+36, iStartY, iX+37, iY+29, Get16BPPColor( FROMRGB( 107, 57, 107 ) ) );
ColorFillVideoSurfaceArea( guiSAVEBUFFER, iX+37, iStartY, iX+38, iY+29, Get16BPPColor( FROMRGB( 222, 115, 181 ) ) );
}
//pink one for bandaged.
iStartY += 27*pSoldier->bBleeding/100;
iStartY = iY + 29 - 27*(pSoldier->stats.bLifeMax - pSoldier->bBleeding)/100;
ColorFillVideoSurfaceArea( guiSAVEBUFFER, iX+36, iStartY, iX+37, iY+29, Get16BPPColor( FROMRGB( 156, 57, 57 ) ) );
ColorFillVideoSurfaceArea( guiSAVEBUFFER, iX+37, iStartY, iX+38, iY+29, Get16BPPColor( FROMRGB( 222, 132, 132 ) ) );
// get amount of poisoned bandage
INT8 bPoisonBandage = pSoldier->bPoisonSum - pSoldier->bPoisonBleeding - pSoldier->bPoisonLife;
if ( bPoisonBandage )
{
// poisoned bandage in bright green
iStartY = iY + 29 - 27*(pSoldier->stats.bLife + bPoisonBandage)/100;
ColorFillVideoSurfaceArea( guiSAVEBUFFER, iX+36, iStartY, iX+37, iY+29, Get16BPPColor( FROMRGB( 57, 156, 57 ) ) );
ColorFillVideoSurfaceArea( guiSAVEBUFFER, iX+37, iStartY, iX+38, iY+29, Get16BPPColor( FROMRGB( 132, 222, 132 ) ) );
}
//red one for actual health
iStartY = iY + 29 - 27*pSoldier->stats.bLife/100;
ColorFillVideoSurfaceArea( guiSAVEBUFFER, iX+36, iStartY, iX+37, iY+29, Get16BPPColor( FROMRGB( 107, 8, 8 ) ) );
ColorFillVideoSurfaceArea( guiSAVEBUFFER, iX+37, iStartY, iX+38, iY+29, Get16BPPColor( FROMRGB( 206, 0, 0 ) ) );
// poisoned life
if ( pSoldier->bPoisonLife )
{
iStartY = iY + 29 - 27*pSoldier->bPoisonLife/100;
ColorFillVideoSurfaceArea( guiSAVEBUFFER, iX+36, iStartY, iX+37, iY+29, Get16BPPColor( FROMRGB( 8, 107, 8 ) ) );
ColorFillVideoSurfaceArea( guiSAVEBUFFER, iX+37, iStartY, iX+38, iY+29, Get16BPPColor( FROMRGB( 0, 206, 0 ) ) );
}
//BREATH BAR
iStartY = iY + 29 - 27*pSoldier->bBreathMax/100;
ColorFillVideoSurfaceArea( guiSAVEBUFFER, iX+39, iStartY, iX+40, iY+29, Get16BPPColor( FROMRGB( 8, 8, 132 ) ) );
+4
View File
@@ -496,6 +496,10 @@ BOOLEAN WillMercRenew( SOLDIERTYPE *pSoldier, BOOLEAN fSayQuote )
if( pSoldier->ubWhatKindOfMercAmI != MERC_TYPE__AIM_MERC )
return( FALSE );
// Flugente: an unconscious merc can't say 'yes' to a contract renewal
if ( pSoldier->stats.bLife < CONSCIOUSNESS )
return( FALSE );
// does the merc have another contract already lined up?
if( pSoldier->flags.fSignedAnotherContract )
{
+10
View File
@@ -2174,6 +2174,7 @@ void EnemyCapturesPlayerSoldier( SOLDIERTYPE *pSoldier )
//Bandaging him would prevent him from dying (due to low HP)
pSoldier->bBleeding = 0;
pSoldier->bPoisonBleeding = 0;
// wake him up
if ( pSoldier->flags.fMercAsleep )
@@ -2183,6 +2184,7 @@ void EnemyCapturesPlayerSoldier( SOLDIERTYPE *pSoldier )
}
//Set his life to 50% + or - 10 HP.
INT8 oldlife = pSoldier->stats.bLife;
pSoldier->stats.bLife = pSoldier->stats.bLifeMax / 2;
if ( pSoldier->stats.bLife <= 35 )
{
@@ -2192,6 +2194,14 @@ void EnemyCapturesPlayerSoldier( SOLDIERTYPE *pSoldier )
{
pSoldier->stats.bLife += (INT8)(10 - Random( 21 ) );
}
// adjust poison points
INT8 lifechanged = oldlife - pSoldier->stats.bLife;
if ( lifechanged < 0 )
pSoldier->bPoisonLife -= lifechanged;
else if ( lifechanged > 0)
pSoldier->bPoisonLife = max(pSoldier->bPoisonSum, pSoldier->bPoisonLife + lifechanged);
// SANDRO - make the lost life insta-healable
pSoldier->iHealableInjury = ((pSoldier->stats.bLifeMax - pSoldier->stats.bLife) * 100);
+27 -1
View File
@@ -1305,16 +1305,42 @@ BOOLEAN RenderSoldierSmallFaceForAutoBandagePanel( INT32 iIndex, INT16 sCurrentX
ColorFillVideoSurfaceArea( FRAME_BUFFER, sCurrentXPosition+36, iStartY, sCurrentXPosition+37, sCurrentYPosition+29, Get16BPPColor( FROMRGB( 107, 107, 57 ) ) );
ColorFillVideoSurfaceArea( FRAME_BUFFER, sCurrentXPosition+37, iStartY, sCurrentXPosition+38, sCurrentYPosition+29, Get16BPPColor( FROMRGB( 222, 181, 115 ) ) );
// poisoned bleeding in purple
if ( pSoldier->bPoisonBleeding )
{
iStartY = sCurrentYPosition + 29 - 27*(pSoldier->stats.bLifeMax - pSoldier->bBleeding + pSoldier->bPoisonBleeding)/100;
ColorFillVideoSurfaceArea( FRAME_BUFFER, sCurrentXPosition+36, iStartY, sCurrentXPosition+37, sCurrentYPosition+29, Get16BPPColor( FROMRGB( 107, 57, 107 ) ) );
ColorFillVideoSurfaceArea( FRAME_BUFFER, sCurrentXPosition+37, iStartY, sCurrentXPosition+38, sCurrentYPosition+29, Get16BPPColor( FROMRGB( 222, 115, 181 ) ) );
}
//pink one for bandaged.
iStartY += 27*pSoldier->bBleeding/100;
iStartY = sCurrentYPosition + 29 - 27*(pSoldier->stats.bLifeMax - pSoldier->bBleeding)/100;
ColorFillVideoSurfaceArea( FRAME_BUFFER, sCurrentXPosition+36, iStartY, sCurrentXPosition+37, sCurrentYPosition+29, Get16BPPColor( FROMRGB( 156, 57, 57 ) ) );
ColorFillVideoSurfaceArea( FRAME_BUFFER, sCurrentXPosition+37, iStartY, sCurrentXPosition+38, sCurrentYPosition+29, Get16BPPColor( FROMRGB( 222, 132, 132 ) ) );
// get amount of poisoned bandage
INT8 bPoisonBandage = pSoldier->bPoisonSum - pSoldier->bPoisonBleeding - pSoldier->bPoisonLife;
if ( bPoisonBandage )
{
// poisoned bandage in bright green
iStartY = sCurrentYPosition + 29 - 27*(pSoldier->stats.bLife + bPoisonBandage)/100;
ColorFillVideoSurfaceArea( FRAME_BUFFER, sCurrentXPosition+36, iStartY, sCurrentXPosition+37, sCurrentYPosition+29, Get16BPPColor( FROMRGB( 57, 156, 57 ) ) );
ColorFillVideoSurfaceArea( FRAME_BUFFER, sCurrentXPosition+37, iStartY, sCurrentXPosition+38, sCurrentYPosition+29, Get16BPPColor( FROMRGB( 132, 222, 132 ) ) );
}
//red one for actual health
iStartY = sCurrentYPosition + 29 - 27*pSoldier->stats.bLife/100;
ColorFillVideoSurfaceArea( FRAME_BUFFER, sCurrentXPosition+36, iStartY, sCurrentXPosition+37, sCurrentYPosition+29, Get16BPPColor( FROMRGB( 107, 8, 8 ) ) );
ColorFillVideoSurfaceArea( FRAME_BUFFER, sCurrentXPosition+37, iStartY, sCurrentXPosition+38, sCurrentYPosition+29, Get16BPPColor( FROMRGB( 206, 0, 0 ) ) );
// poisoned life
if ( pSoldier->bPoisonLife )
{
iStartY = sCurrentYPosition + 29 - 27*pSoldier->bPoisonLife/100;
ColorFillVideoSurfaceArea( FRAME_BUFFER, sCurrentXPosition+36, iStartY, sCurrentXPosition+37, sCurrentYPosition+29, Get16BPPColor( FROMRGB( 8, 107, 8 ) ) );
ColorFillVideoSurfaceArea( FRAME_BUFFER, sCurrentXPosition+37, iStartY, sCurrentXPosition+38, sCurrentYPosition+29, Get16BPPColor( FROMRGB( 0, 206, 0 ) ) );
}
//BREATH BAR
iStartY = sCurrentYPosition + 29 - 27*pSoldier->bBreathMax/100;
ColorFillVideoSurfaceArea( FRAME_BUFFER, sCurrentXPosition+39, iStartY, sCurrentXPosition+40, sCurrentYPosition+29, Get16BPPColor( FROMRGB( 8, 8, 132 ) ) );
+4
View File
@@ -1035,6 +1035,10 @@ void StartEnemyTaunt( SOLDIERTYPE *pCiv, INT8 iTauntType )
VIDEO_OVERLAY_DESC VideoOverlayDesc;
CHAR16 gzTauntQuote[ 320 ];
// Flugente: zombies don't talk
if ( pCiv->IsZombie() )
return;
// if we have a different quote on, return, this one is not important
if ( gCivQuoteData.bActive )
{
+4 -1
View File
@@ -334,8 +334,9 @@ void HandleEndTurnDrugAdjustments( SOLDIERTYPE *pSoldier )
// bBandaged = BANDAGED( pSoldier );
// increase life
pSoldier->bPoisonLife = max(pSoldier->bPoisonSum, pSoldier->bPoisonLife + pSoldier->stats.bLife - __min( pSoldier->stats.bLife + LIFE_GAIN_PER_REGEN_POINT, pSoldier->stats.bLifeMax ) );
pSoldier->stats.bLife = __min( pSoldier->stats.bLife + LIFE_GAIN_PER_REGEN_POINT, pSoldier->stats.bLifeMax );
//SANDRO - Insta-healable injury reduction
if( pSoldier->iHealableInjury > 0 )
{
@@ -345,12 +346,14 @@ void HandleEndTurnDrugAdjustments( SOLDIERTYPE *pSoldier )
if ( pSoldier->stats.bLife == pSoldier->stats.bLifeMax )
{
pSoldier->bBleeding = 0;
pSoldier->bPoisonBleeding = 0;
pSoldier->iHealableInjury = 0;
}
else if ( pSoldier->bBleeding + pSoldier->stats.bLife > pSoldier->stats.bLifeMax )
{
// got to reduce amount of bleeding
pSoldier->bBleeding = (pSoldier->stats.bLifeMax - pSoldier->stats.bLife);
pSoldier->bPoisonBleeding = min(pSoldier->bPoisonBleeding, (pSoldier->stats.bLifeMax - pSoldier->stats.bLife));
}
// decrement counter
+1 -1
View File
@@ -4575,7 +4575,7 @@ void SetOffBoobyTrapInMapScreen( SOLDIERTYPE *pSoldier, OBJECTTYPE *pObject )
}
// injure the inventory character
pSoldier->SoldierTakeDamage( 0, ubPtsDmg, ubPtsDmg, TAKE_DAMAGE_EXPLOSION, NOBODY, NOWHERE, 0, TRUE );
pSoldier->SoldierTakeDamage( 0, ubPtsDmg, 0, ubPtsDmg, TAKE_DAMAGE_EXPLOSION, NOBODY, NOWHERE, 0, TRUE );
// play the sound
PlayJA2Sample( EXPLOSION_1, RATE_11025, BTNVOLUME, 1, MIDDLEPAN );
+14 -4
View File
@@ -760,13 +760,23 @@ void RenderTopmostTacticalInterface( )
SetFontForeground( FONT_MCOLOR_WHITE );
bool showDamage = true;
if (gGameExternalOptions.ubEnemyHitCount > 0 && pSoldier->bTeam == ENEMY_TEAM || pSoldier->bTeam == CREATURE_TEAM)
if (gGameExternalOptions.ubEnemyHitCount > 0 && ( pSoldier->bTeam == ENEMY_TEAM || pSoldier->bTeam == CREATURE_TEAM) )
showDamage = false;
if (showDamage)
{
gprintfdirty( sDamageX, sDamageY, L"-%d", pSoldier->sDamage );
mprintf( sDamageX, sDamageY, L"-%d", pSoldier->sDamage );
{
if ( pSoldier->sDamage >= 0 )
{
gprintfdirty( sDamageX, sDamageY, L"-%d", pSoldier->sDamage );
mprintf( sDamageX, sDamageY, L"-%d", pSoldier->sDamage );
}
else // Flugente: it is possible that someone might regain negative damage as zombies can regenerate health through bleeding
{
SetFontForeground( FONT_MCOLOR_LTGREEN );
gprintfdirty( sDamageX, sDamageY, L"+%d", -pSoldier->sDamage );
mprintf( sDamageX, sDamageY, L"+%d", -pSoldier->sDamage );
SetFontForeground( FONT_MCOLOR_WHITE );
}
}
else
{
+4
View File
@@ -2268,6 +2268,7 @@ void HandleNPCDoAction( UINT8 ubTargetNPC, UINT16 usActionCode, UINT8 ubQuoteNum
DeleteTalkingMenu();
SetSoldierNeutral( pSoldier );
pSoldier->bBleeding = 0; // make sure he doesn't bleed now...
pSoldier->bPoisonBleeding = 0;
RecalculateOppCntsDueToBecomingNeutral( pSoldier );
if ( gTacticalStatus.uiFlags & INCOMBAT )
{
@@ -4445,6 +4446,9 @@ UINT32 CalcPatientMedicalCost( SOLDIERTYPE * pSoldier )
uiCost += ( 25 * ( OKLIFE - pSoldier->stats.bLife ) );
}
// charge additional $13 for every poison point that has to be cured
uiCost += 13 * pSoldier->bPoisonSum;
// also charge $2 for each point of bleeding that must be stopped
if ( pSoldier->bBleeding > 0 )
{
+164 -236
View File
@@ -95,6 +95,8 @@ UINT32 guiItemInfoArmorIcon;
UINT32 guiItemInfoSecondaryIcon;
// HEADROCK HAM 4: This replaces "Misc" icons.
UINT32 guiItemInfoAdvancedIcon;
// Flugente: added icons for WH40K
UINT32 guiItemInfoWH40KIcon;
// HEADROCK HAM 4: New tooltip regions for UDB replace the old regions.
#define NUM_UDB_FASTHELP_REGIONS 102
@@ -1376,6 +1378,10 @@ BOOLEAN InternalInitEnhancedDescBox()
strcpy( VObjectDesc.ImageFile, "INTERFACE\\ItemInfoAdvancedIcons.STI" );
CHECKF( AddVideoObject( &VObjectDesc, &guiItemInfoAdvancedIcon ) );
// Flugente: added icons for WH40K
VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE;
strcpy( VObjectDesc.ImageFile, "INTERFACE\\ItemInfoWH40KIcons.STI" );
CHECKF( AddVideoObject( &VObjectDesc, &guiItemInfoWH40KIcon ) );
}
return (TRUE);
@@ -1879,7 +1885,7 @@ void InternalInitEDBTooltipRegion( OBJECTTYPE * gpItemDescObject, UINT32 guiCurr
CHAR16 pStr[1000];
///////////////// PRIMARY DATA - ICONS
for (cnt = 0; cnt < 4; cnt++)
for (cnt = 0; cnt < 5; cnt++)
{
MSYS_DefineRegion( &gUDBFasthelpRegions[ iRegionsCreated ],
(INT16)(gItemDescGenRegions[cnt][0].sLeft),
@@ -1919,6 +1925,14 @@ void InternalInitEDBTooltipRegion( OBJECTTYPE * gpItemDescObject, UINT32 guiCurr
MSYS_EnableRegion( &gUDBFasthelpRegions[ iFirstDataRegion + 3 ] );
}
}
if ( gGameSettings.fOptions[TOPTION_ZOMBIES] ) // Flugente Zombies
{
//////////////////// POISON PERCENTAGE
{
MSYS_EnableRegion( &gUDBFasthelpRegions[ iFirstDataRegion + 4 ] );
}
}
}
}
@@ -3850,6 +3864,51 @@ void InternalInitEDBTooltipRegion( OBJECTTYPE * gpItemDescObject, UINT32 guiCurr
}
}
}
// Flugente Zombies
if ( gGameSettings.fOptions[TOPTION_ZOMBIES] )
{
if(!cnt) cnt += 2;
if (cnt >= sFirstLine && cnt < sLastLine)
{
SetRegionFastHelpText( &(gUDBFasthelpRegions[ iFirstDataRegion + (cnt-sFirstLine) ]), gzUDBGenIndexTooltipText[ 0 ] );
MSYS_EnableRegion( &gUDBFasthelpRegions[ iFirstDataRegion + (cnt-sFirstLine) ] );
iRegionsCreated++;
for (cnt2 = 1; cnt2 < 4; cnt2++)
{
MSYS_DefineRegion( &gUDBFasthelpRegions[ iRegionsCreated ],
(INT16)(gItemDescAdvIndexRegions[cnt-sFirstLine][cnt2].sLeft),
(INT16)(gItemDescAdvIndexRegions[cnt-sFirstLine][cnt2].sTop),
(INT16)(gItemDescAdvIndexRegions[cnt-sFirstLine][cnt2].sRight),
(INT16)(gItemDescAdvIndexRegions[cnt-sFirstLine][cnt2].sBottom),
MSYS_PRIORITY_HIGHEST, MSYS_NO_CURSOR, MSYS_NO_CALLBACK, ItemDescCallback );
MSYS_AddRegion( &gUDBFasthelpRegions[ iFirstDataRegion + (cnt-sFirstLine) + cnt2]);
SetRegionFastHelpText( &(gUDBFasthelpRegions[ iFirstDataRegion + (cnt-sFirstLine) + cnt2]), gzUDBGenIndexTooltipText[ cnt2 ] );
SetRegionHelpEndCallback( &(gUDBFasthelpRegions[ iFirstDataRegion + (cnt-sFirstLine) + cnt2]), HelpTextDoneCallback );
MSYS_EnableRegion( &gUDBFasthelpRegions[ iFirstDataRegion + (cnt-sFirstLine) + cnt2] );
iRegionsCreated++;
}
}
++cnt;
///////////////////// poison percentage
// only draw if item is poisoned in any way
if ( Item[gpItemDescObject->usItem].bPoisonPercentage != 0 || (Item[gpItemDescObject->usItem].usItemClass == IC_GUN && AmmoTypes[Magazine[ Item[ gpItemDescObject->usItem ].ubClassIndex].ubAmmoType].poisonPercentage != 0 ) )
{
if (cnt >= sFirstLine && cnt < sLastLine)
{
swprintf( pStr, L"%s%s", szUDBAdvStatsTooltipText[ 56 ], szUDBAdvStatsExplanationsTooltipText[ 56 ]);
SetRegionFastHelpText( &(gUDBFasthelpRegions[ iFirstDataRegion + (cnt-sFirstLine) ]), pStr );
MSYS_EnableRegion( &gUDBFasthelpRegions[ iFirstDataRegion + (cnt-sFirstLine) ] );
}
cnt++;
}
}
gubDescBoxTotalAdvLines = (UINT8)cnt;
}
@@ -3866,6 +3925,7 @@ void DeleteEnhancedDescBox( UINT32 guiCurrentItemDescriptionScreen )
// HEADROCK HAM 4: Delete new icons
DeleteVideoObjectFromIndex( guiItemInfoSecondaryIcon );
DeleteVideoObjectFromIndex( guiItemInfoAdvancedIcon );
DeleteVideoObjectFromIndex( guiItemInfoWH40KIcon );
if ( UsingEDBSystem() > 0 )
{
@@ -4244,6 +4304,13 @@ 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
{
//////////////// POISON PERCENTAGE
{
BltVideoObjectFromIndex( guiSAVEBUFFER, guiItemInfoWH40KIcon, 6, gItemDescGenRegions[4][0].sLeft+sOffsetX, gItemDescGenRegions[4][0].sTop+sOffsetY, VO_BLT_SRCTRANSPARENCY, NULL );
}
}
DrawSecondaryStats( gpItemDescObject );
}
@@ -5130,6 +5197,25 @@ void DrawAdvancedStats( OBJECTTYPE * gpItemDescObject )
}
}
}
// Flugente Zombies
if ( gGameSettings.fOptions[TOPTION_ZOMBIES] )
{
if(!cnt) cnt += 2;
++cnt; // for the new index-line
///////////////////// poison percentage
// only draw if item is poisoned in any way
if ( Item[gpItemDescObject->usItem].bPoisonPercentage != 0 || (Item[gpItemDescObject->usItem].usItemClass == IC_GUN && AmmoTypes[Magazine[ Item[ gpItemDescObject->usItem ].ubClassIndex].ubAmmoType].poisonPercentage != 0 ) )
{
if (cnt >= sFirstLine && cnt < sLastLine)
{
BltVideoObjectFromIndex( guiSAVEBUFFER, guiItemInfoWH40KIcon, 6, gItemDescAdvRegions[cnt-sFirstLine][0].sLeft + sOffsetX, gItemDescAdvRegions[cnt-sFirstLine][0].sTop + sOffsetY, VO_BLT_SRCTRANSPARENCY, NULL );
}
cnt++;
}
}
}
void DrawMiscStats( OBJECTTYPE * gpItemDescObject )
@@ -7246,7 +7332,6 @@ void DrawWeaponValues( OBJECTTYPE * gpItemDescObject )
FindFontCenterCoordinates( sLeft, sTop, sWidth, sHeight, pStr, BLOCKFONT2, &usX, &usY);
mprintf( usX, usY, pStr );
}
}
if (gubDescBoxPage == 2)
{
@@ -7511,6 +7596,59 @@ void DrawAmmoValues( OBJECTTYPE * gpItemDescObject, int shotsLeft )
FindFontCenterCoordinates( sLeft, sTop, sWidth, sHeight, pStr, BLOCKFONT2, &usX, &usY);
mprintf( usX, usY, pStr );
}
if ( gGameSettings.fOptions[TOPTION_ZOMBIES] ) // Flugente Zombies
{
///////////////////// POISON PERCENTAGE
// Set line to draw into
ubNumLine = 4;
// Set Y coordinates
sTop = gItemDescGenRegions[ubNumLine][1].sTop;
sHeight = gItemDescGenRegions[ubNumLine][1].sBottom - sTop;
// base modificator
INT16 basevalue = AmmoTypes[Magazine[ Item[ gpItemDescObject->usItem ].ubClassIndex].ubAmmoType].poisonPercentage;
INT16 modificator = 0; // Does not exist (yet?)
INT16 finalvalue = basevalue - modificator;
// Print base value
SetFontForeground( 5 );
sLeft = gItemDescGenRegions[ubNumLine][1].sLeft;
sWidth = gItemDescGenRegions[ubNumLine][1].sRight - sLeft;
swprintf( pStr, L"%d", basevalue );
FindFontCenterCoordinates( sLeft, sTop, sWidth, sHeight, pStr, BLOCKFONT2, &usX, &usY);
mprintf( usX, usY, pStr );
// modifier
SetFontForeground( 5 );
if ( modificator > 0 )
{
SetFontForeground( ITEMDESC_FONTPOSITIVE );
swprintf( pStr, L"%d", modificator );
}
else if ( modificator < 0 )
{
SetFontForeground( ITEMDESC_FONTNEGATIVE );
swprintf( pStr, L"%d", modificator );
}
else
{
swprintf( pStr, L"--" );
}
sLeft = gItemDescGenRegions[ubNumLine][2].sLeft;
sWidth = gItemDescGenRegions[ubNumLine][2].sRight - sLeft;
FindFontCenterCoordinates( sLeft, sTop, sWidth, sHeight, pStr, BLOCKFONT2, &usX, &usY);
mprintf( usX, usY, pStr );
// Print final value
SetFontForeground( FONT_MCOLOR_WHITE );
sLeft = gItemDescGenRegions[ubNumLine][3].sLeft;
sWidth = gItemDescGenRegions[ubNumLine][3].sRight - sLeft;
swprintf( pStr, L"%d", finalvalue );
FindFontCenterCoordinates( sLeft, sTop, sWidth, sHeight, pStr, BLOCKFONT2, &usX, &usY);
mprintf( usX, usY, pStr );
}
}
else if (gubDescBoxPage == 2)
{
@@ -10660,47 +10798,6 @@ void DrawAdvancedValues( OBJECTTYPE *gpItemDescObject )
}
cnt++;
}
///////////////////// MAX COUNTER FORCE
iFloatModifier[0] = CalcCounterForceMax( gpItemDescSoldier, gpItemDescObject, ANIM_STAND );
iFloatModifier[1] = CalcCounterForceMax( gpItemDescSoldier, gpItemDescObject, ANIM_CROUCH );
iFloatModifier[2] = CalcCounterForceMax( gpItemDescSoldier, gpItemDescObject, ANIM_PRONE );
if ((iFloatModifier[0] != 0 || iFloatModifier[1] != 0 || iFloatModifier[2] != 0) && UsingNewCTHSystem() == true && Item[gpItemDescObject->usItem].usItemClass == IC_GUN )
{
if (cnt >= sFirstLine && cnt < sLastLine)
{
// Set Y coordinates
sTop = gItemDescAdvRegions[cnt-sFirstLine][1].sTop;
sHeight = gItemDescAdvRegions[cnt-sFirstLine][1].sBottom - sTop;
// Print Values
for (UINT8 cnt2 = 0; cnt2 < 3; cnt2++)
{
SetFontForeground( 5 );
sLeft = gItemDescAdvRegions[cnt-sFirstLine][cnt2+1].sLeft;
sWidth = gItemDescAdvRegions[cnt-sFirstLine][cnt2+1].sRight - sLeft;
if (iFloatModifier[cnt2] > 0)
{
SetFontForeground( ITEMDESC_FONTPOSITIVE );
swprintf( pStr, L"%3.1f", iFloatModifier[cnt2] );
FindFontCenterCoordinates( sLeft, sTop, sWidth, sHeight, pStr, BLOCKFONT2, &usX, &usY);
}
else if (iFloatModifier[cnt2] < 0)
{
SetFontForeground( ITEMDESC_FONTNEGATIVE );
swprintf( pStr, L"%3.1f", iFloatModifier[cnt2] );
FindFontCenterCoordinates( sLeft, sTop, sWidth, sHeight, pStr, BLOCKFONT2, &usX, &usY);
}
else
{
swprintf( pStr, L"--" );
FindFontCenterCoordinates( sLeft, sTop, sWidth, sHeight, pStr, BLOCKFONT2, &usX, &usY);
}
mprintf( usX, usY, pStr );
}
}
cnt++;
}
// HEADROCK HAM 5: Counter-Force Frequency has been removed from the game in favour of a more realistic system.
/*
@@ -10783,7 +10880,7 @@ void DrawAdvancedValues( OBJECTTYPE *gpItemDescObject )
sTop = gItemDescAdvRegions[cnt-sFirstLine][1].sTop;
sHeight = gItemDescAdvRegions[cnt-sFirstLine][1].sBottom - sTop;
iFloatModifier[0] = Weapon[ Item[gpItemDescObject->usItem].ubClassIndex].usOverheatingSingleShotTemperature;
iFloatModifier[0] = Weapon[ gpItemDescObject->usItem ].usOverheatingSingleShotTemperature;
iFloatModifier[1] = GetSingleShotTemperature( gpItemDescObject ) - iFloatModifier[0];
iFloatModifier[2] = GetSingleShotTemperature( gpItemDescObject );
@@ -10890,7 +10987,7 @@ void DrawAdvancedValues( OBJECTTYPE *gpItemDescObject )
sTop = gItemDescAdvRegions[cnt-sFirstLine][1].sTop;
sHeight = gItemDescAdvRegions[cnt-sFirstLine][1].sBottom - sTop;
iFloatModifier[0] = Weapon[ Item[gpItemDescObject->usItem].ubClassIndex].usOverheatingJamThreshold;
iFloatModifier[0] = Weapon[ gpItemDescObject->usItem ].usOverheatingJamThreshold;
iFloatModifier[1] = GetOverheatJamThreshold(gpItemDescObject) - iFloatModifier[0];
iFloatModifier[2] = GetOverheatJamThreshold(gpItemDescObject);
@@ -10943,7 +11040,7 @@ void DrawAdvancedValues( OBJECTTYPE *gpItemDescObject )
sTop = gItemDescAdvRegions[cnt-sFirstLine][1].sTop;
sHeight = gItemDescAdvRegions[cnt-sFirstLine][1].sBottom - sTop;
iFloatModifier[0] = Weapon[ Item[gpItemDescObject->usItem].ubClassIndex].usOverheatingDamageThreshold;
iFloatModifier[0] = Weapon[ gpItemDescObject->usItem ].usOverheatingDamageThreshold;
iFloatModifier[1] = GetOverheatDamageThreshold(gpItemDescObject) - iFloatModifier[0];
iFloatModifier[2] = GetOverheatDamageThreshold(gpItemDescObject);
@@ -11070,11 +11167,14 @@ void DrawAdvancedValues( OBJECTTYPE *gpItemDescObject )
}
cnt++;
}
}
// Flugente Zombies
if ( gGameSettings.fOptions[TOPTION_ZOMBIES] )
{
///////////////////////////////////////////////////// INDEXES
if(!cnt) cnt += 2;
// various overheating modificators
if ( ( Item[gpItemDescObject->usItem].overheatTemperatureModificator != 0.0 ) || ( Item[gpItemDescObject->usItem].overheatCooldownModificator != 0.0 ) || ( Item[gpItemDescObject->usItem].overheatJamThresholdModificator != 0.0 ) || ( Item[gpItemDescObject->usItem].overheatDamageThresholdModificator != 0.0 ) )
{
///////////////////////////////////////////////////// INDEXES
if (cnt >= sFirstLine && cnt < sLastLine)
{
SetFontForeground( FONT_MCOLOR_WHITE );
@@ -11099,31 +11199,32 @@ void DrawAdvancedValues( OBJECTTYPE *gpItemDescObject )
}
++cnt;
///////////////////// TEMPERATURE MODIFICATOR
iFloatModifier[0] = Item[gpItemDescObject->usItem].overheatTemperatureModificator;
iFloatModifier[1] = 0.0; // doesn't exist (yet?)
iFloatModifier[2] = iFloatModifier[0];
///////////////////// poison percentage
iModifier[0] = Item[gpItemDescObject->usItem].bPoisonPercentage;
if ( iFloatModifier[0] != 0 )
UINT8 ammotype = (*gpItemDescObject)[0]->data.gun.ubGunAmmoType; // ... get type of ammunition used ...
iModifier[1] = AmmoTypes[ammotype].poisonPercentage;
iModifier[2] = iModifier[0] + iModifier[1];
// only draw if item is poisoned in any way
if ( iModifier[0] != 0 || iModifier[1] != 0 || iModifier[2] != 0 )
{
if (cnt >= sFirstLine && cnt < sLastLine)
{
// Set Y coordinates
sTop = gItemDescAdvRegions[cnt-sFirstLine][1].sTop;
sHeight = gItemDescAdvRegions[cnt-sFirstLine][1].sBottom - sTop;
// Print Values
for (UINT8 cnt2 = 0; cnt2 < 3; cnt2++)
{
SetFontForeground( 5 );
SetRGBFontForeground( 0, 255, 0 );
sLeft = gItemDescAdvRegions[cnt-sFirstLine][cnt2+1].sLeft;
sWidth = gItemDescAdvRegions[cnt-sFirstLine][cnt2+1].sRight - sLeft;
if (iFloatModifier[cnt2] > 0)
if (iModifier[cnt2] > 0)
{
if ( cnt2 == 1 )
SetFontForeground( ITEMDESC_FONTNEGATIVE );
swprintf( pStr, L"%4.2f", iFloatModifier[cnt2] );
swprintf( pStr, L"%d", iModifier[cnt2] );
FindFontCenterCoordinates( sLeft, sTop, sWidth, sHeight, pStr, BLOCKFONT2, &usX, &usY);
#ifdef CHINESE
wcscat( pStr, ChineseSpecString1 );
@@ -11133,10 +11234,7 @@ void DrawAdvancedValues( OBJECTTYPE *gpItemDescObject )
}
else if (iFloatModifier[cnt2] < 0)
{
if ( cnt2 == 1 )
SetFontForeground( ITEMDESC_FONTPOSITIVE );
swprintf( pStr, L"%4.2f", iFloatModifier[cnt2] );
swprintf( pStr, L"%d", iModifier[cnt2] );
FindFontCenterCoordinates( sLeft, sTop, sWidth, sHeight, pStr, BLOCKFONT2, &usX, &usY);
#ifdef CHINESE
wcscat( pStr, ChineseSpecString1 );
@@ -11154,176 +11252,6 @@ void DrawAdvancedValues( OBJECTTYPE *gpItemDescObject )
}
cnt++;
}
///////////////////// COOLDOWN FACTOR MODIFICATOR
iFloatModifier[0] = Item[gpItemDescObject->usItem].overheatCooldownModificator;
iFloatModifier[1] = 0.0; // doesn't exist (yet?)
iFloatModifier[2] = iFloatModifier[0];
if ( iFloatModifier[0] != 0 )
{
if (cnt >= sFirstLine && cnt < sLastLine)
{
// Set Y coordinates
sTop = gItemDescAdvRegions[cnt-sFirstLine][1].sTop;
sHeight = gItemDescAdvRegions[cnt-sFirstLine][1].sBottom - sTop;
// Print Values
for (UINT8 cnt2 = 0; cnt2 < 3; cnt2++)
{
SetFontForeground( 5 );
sLeft = gItemDescAdvRegions[cnt-sFirstLine][cnt2+1].sLeft;
sWidth = gItemDescAdvRegions[cnt-sFirstLine][cnt2+1].sRight - sLeft;
if (iFloatModifier[cnt2] > 0)
{
if ( cnt2 == 1 )
SetFontForeground( ITEMDESC_FONTPOSITIVE );
swprintf( pStr, L"%4.2f", iFloatModifier[cnt2] );
FindFontCenterCoordinates( sLeft, sTop, sWidth, sHeight, pStr, BLOCKFONT2, &usX, &usY);
#ifdef CHINESE
wcscat( pStr, ChineseSpecString1 );
#else
wcscat( pStr, L"%" );
#endif
}
else if (iFloatModifier[cnt2] < 0)
{
if ( cnt2 == 1 )
SetFontForeground( ITEMDESC_FONTNEGATIVE );
swprintf( pStr, L"%4.2f", iFloatModifier[cnt2] );
FindFontCenterCoordinates( sLeft, sTop, sWidth, sHeight, pStr, BLOCKFONT2, &usX, &usY);
#ifdef CHINESE
wcscat( pStr, ChineseSpecString1 );
#else
wcscat( pStr, L"%" );
#endif
}
else
{
swprintf( pStr, L"--" );
FindFontCenterCoordinates( sLeft, sTop, sWidth, sHeight, pStr, BLOCKFONT2, &usX, &usY);
}
mprintf( usX, usY, pStr );
}
}
cnt++;
}
///////////////////// JAM THRESHOLD FACTOR MODIFICATOR
iFloatModifier[0] = Item[gpItemDescObject->usItem].overheatJamThresholdModificator;
iFloatModifier[1] = 0.0; // doesn't exist (yet?)
iFloatModifier[2] = iFloatModifier[0];
if ( iFloatModifier[0] != 0 )
{
if (cnt >= sFirstLine && cnt < sLastLine)
{
// Set Y coordinates
sTop = gItemDescAdvRegions[cnt-sFirstLine][1].sTop;
sHeight = gItemDescAdvRegions[cnt-sFirstLine][1].sBottom - sTop;
// Print Values
for (UINT8 cnt2 = 0; cnt2 < 3; cnt2++)
{
SetFontForeground( 5 );
sLeft = gItemDescAdvRegions[cnt-sFirstLine][cnt2+1].sLeft;
sWidth = gItemDescAdvRegions[cnt-sFirstLine][cnt2+1].sRight - sLeft;
if (iFloatModifier[cnt2] > 0)
{
if ( cnt2 == 1 )
SetFontForeground( ITEMDESC_FONTNEGATIVE );
swprintf( pStr, L"%4.2f", iFloatModifier[cnt2] );
FindFontCenterCoordinates( sLeft, sTop, sWidth, sHeight, pStr, BLOCKFONT2, &usX, &usY);
#ifdef CHINESE
wcscat( pStr, ChineseSpecString1 );
#else
wcscat( pStr, L"%" );
#endif
}
else if (iFloatModifier[cnt2] < 0)
{
if ( cnt2 == 1 )
SetFontForeground( ITEMDESC_FONTPOSITIVE );
swprintf( pStr, L"%4.2f", iFloatModifier[cnt2] );
FindFontCenterCoordinates( sLeft, sTop, sWidth, sHeight, pStr, BLOCKFONT2, &usX, &usY);
#ifdef CHINESE
wcscat( pStr, ChineseSpecString1 );
#else
wcscat( pStr, L"%" );
#endif
}
else
{
swprintf( pStr, L"--" );
FindFontCenterCoordinates( sLeft, sTop, sWidth, sHeight, pStr, BLOCKFONT2, &usX, &usY);
}
mprintf( usX, usY, pStr );
}
}
cnt++;
}
///////////////////// DAMAGE THRESHOLD MODIFICATOR
iFloatModifier[0] = Item[gpItemDescObject->usItem].overheatDamageThresholdModificator;
iFloatModifier[1] = 0.0; // doesn't exist (yet?)
iFloatModifier[2] = iFloatModifier[0];
if ( iFloatModifier[0] != 0 )
{
if (cnt >= sFirstLine && cnt < sLastLine)
{
// Set Y coordinates
sTop = gItemDescAdvRegions[cnt-sFirstLine][1].sTop;
sHeight = gItemDescAdvRegions[cnt-sFirstLine][1].sBottom - sTop;
// Print Values
for (UINT8 cnt2 = 0; cnt2 < 3; cnt2++)
{
SetFontForeground( 5 );
sLeft = gItemDescAdvRegions[cnt-sFirstLine][cnt2+1].sLeft;
sWidth = gItemDescAdvRegions[cnt-sFirstLine][cnt2+1].sRight - sLeft;
if (iFloatModifier[cnt2] > 0)
{
if ( cnt2 == 1 )
SetFontForeground( ITEMDESC_FONTNEGATIVE );
swprintf( pStr, L"%4.2f", iFloatModifier[cnt2] );
FindFontCenterCoordinates( sLeft, sTop, sWidth, sHeight, pStr, BLOCKFONT2, &usX, &usY);
#ifdef CHINESE
wcscat( pStr, ChineseSpecString1 );
#else
wcscat( pStr, L"%" );
#endif
}
else if (iFloatModifier[cnt2] < 0)
{
if ( cnt2 == 1 )
SetFontForeground( ITEMDESC_FONTPOSITIVE );
swprintf( pStr, L"%4.2f", iFloatModifier[cnt2] );
FindFontCenterCoordinates( sLeft, sTop, sWidth, sHeight, pStr, BLOCKFONT2, &usX, &usY);
#ifdef CHINESE
wcscat( pStr, ChineseSpecString1 );
#else
wcscat( pStr, L"%" );
#endif
}
else
{
swprintf( pStr, L"--" );
FindFontCenterCoordinates( sLeft, sTop, sWidth, sHeight, pStr, BLOCKFONT2, &usX, &usY);
}
mprintf( usX, usY, pStr );
}
}
cnt++;
}
}
}
}
+27 -9
View File
@@ -2928,8 +2928,17 @@ void RenderSMPanel( BOOLEAN *pfDirty )
else
{
GetMoraleString( gpSMCurrentMerc, pMoraleStr );
swprintf( pStr, TacticalStr[ MERC_VITAL_STATS_POPUPTEXT ], gpSMCurrentMerc->stats.bLife, gpSMCurrentMerc->stats.bLifeMax, gpSMCurrentMerc->bBreath, gpSMCurrentMerc->bBreathMax, pMoraleStr );
// Flugente: added a display for poison, only show text if actualy poisoned
if ( gpSMCurrentMerc->bPoisonSum > 0 )
{
swprintf( pStr, TacticalStr[ MERC_VITAL_STATS_WITH_POISON_POPUPTEXT ], gpSMCurrentMerc->stats.bLife, gpSMCurrentMerc->stats.bLifeMax, gpSMCurrentMerc->bPoisonSum, gpSMCurrentMerc->stats.bLifeMax, gpSMCurrentMerc->bBreath, gpSMCurrentMerc->bBreathMax, pMoraleStr );
}
else
{
swprintf( pStr, TacticalStr[ MERC_VITAL_STATS_POPUPTEXT ], gpSMCurrentMerc->stats.bLife, gpSMCurrentMerc->stats.bLifeMax, gpSMCurrentMerc->bBreath, gpSMCurrentMerc->bBreathMax, pMoraleStr );
}
SetRegionFastHelpText( &(gSM_SELMERCBarsRegion), pStr );
}
}
else
@@ -5442,16 +5451,25 @@ void RenderTEAMPanel( BOOLEAN fDirty )
}
else
{
GetMoraleString( pSoldier, pMoraleStr );
swprintf( pStr, TacticalStr[ MERC_VITAL_STATS_POPUPTEXT ], pSoldier->stats.bLife, pSoldier->stats.bLifeMax, pSoldier->bBreath, pSoldier->bBreathMax, pMoraleStr );
SetRegionFastHelpText( &(gTEAM_BarsRegions[ cnt ]), pStr );
GetMoraleString( pSoldier, pMoraleStr );
// Flugente: added a display for poison, only show text if actually poisoned
if ( pSoldier->bPoisonSum > 0 )
{
swprintf( pStr, TacticalStr[ MERC_VITAL_STATS_WITH_POISON_POPUPTEXT ], pSoldier->stats.bLife, pSoldier->stats.bLifeMax, pSoldier->bPoisonSum, pSoldier->stats.bLifeMax, pSoldier->bBreath, pSoldier->bBreathMax, pMoraleStr );
}
else
{
swprintf( pStr, TacticalStr[ MERC_VITAL_STATS_POPUPTEXT ], pSoldier->stats.bLife, pSoldier->stats.bLifeMax, pSoldier->bBreath, pSoldier->bBreathMax, pMoraleStr );
}
SetRegionFastHelpText( &(gTEAM_BarsRegions[ cnt ]), pStr );
}
}
else
{
SetRegionFastHelpText( &(gTEAM_BarsRegions[ cnt ]), L"" );
}
}
else
{
SetRegionFastHelpText( &(gTEAM_BarsRegions[ cnt ]), L"" );
}
}
if ( !( pSoldier->flags.uiStatusFlags & SOLDIER_DEAD ) )
{
+83 -18
View File
@@ -24,22 +24,30 @@
#endif
#define LIFE_BAR_SHADOW FROMRGB( 108, 12, 12 )
#define LIFE_BAR FROMRGB( 200, 0, 0 )
#define LIFE_BAR FROMRGB( 200, 0, 0 )
#define BANDAGE_BAR_SHADOW FROMRGB( 156, 60, 60 )
#define BANDAGE_BAR FROMRGB( 222, 132, 132 )
#define BANDAGE_BAR FROMRGB( 222, 132, 132 )
#define BLEEDING_BAR_SHADOW FROMRGB( 128, 128, 60 )
#define BLEEDING_BAR FROMRGB( 240, 240, 20 )
#define CURR_BREATH_BAR_SHADOW FROMRGB( 8, 12, 118 ) // the MAX max breatth, always at 100%
#define CURR_BREATH_BAR FROMRGB( 8, 12, 160 )
#define CURR_MAX_BREATH FROMRGB( 0, 0, 0 ) // the current max breath, black
#define CURR_MAX_BREATH_SHADOW FROMRGB( 0, 0, 0 )
#define MORALE_BAR_SHADOW FROMRGB( 8, 112, 12 )
#define MORALE_BAR FROMRGB( 8, 180, 12 )
#define BREATH_BAR_SHADOW FROMRGB( 60, 108, 108 ) // the lt blue current breath
#define BREATH_BAR FROMRGB( 113, 178, 218 )
#define BLEEDING_BAR FROMRGB( 240, 240, 20 )
#define POISON_LIFE_BAR_SHADOW FROMRGB( 12, 108, 12 )
#define POISON_LIFE_BAR FROMRGB( 0, 200, 0 )
#define POISON_BANDAGE_BAR_SHADOW FROMRGB( 80, 186, 80 )
#define POISON_BANDAGE_BAR FROMRGB( 152, 252, 152 )
#define POISON_BLEEDING_BAR_SHADOW FROMRGB( 128, 60, 128 )
#define POISON_BLEEDING_BAR FROMRGB( 240, 20, 240 )
#define CURR_BREATH_BAR_SHADOW FROMRGB( 8, 12, 118 ) // the MAX max breatth, always at 100%
#define CURR_BREATH_BAR FROMRGB( 8, 12, 160 )
#define CURR_MAX_BREATH FROMRGB( 0, 0, 0 ) // the current max breath, black
#define CURR_MAX_BREATH_SHADOW FROMRGB( 0, 0, 0 )
#define MORALE_BAR_SHADOW FROMRGB( 8, 112, 12 )
#define MORALE_BAR FROMRGB( 8, 180, 12 )
#define BREATH_BAR_SHADOW FROMRGB( 60, 108, 108 ) // the lt blue current breath
#define BREATH_BAR FROMRGB( 113, 178, 218 )
#define BREATH_BAR_SHAD_BACK FROMRGB( 1,1,1 )
#define FACE_WIDTH 48
#define FACE_HEIGHT 43
#define FACE_WIDTH 48
#define FACE_HEIGHT 43
// backgrounds for breath max background
@@ -162,12 +170,15 @@ void DrawLifeUIBarEx( SOLDIERTYPE *pSoldier, INT16 sXPos, INT16 sYPos, INT16 sWi
pDestBuf = LockVideoSurface( uiBuffer, &uiDestPitchBYTES );
SetClippingRegionAndImageWidth( uiDestPitchBYTES, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT );
dStart = sYPos;
dEnd = 0;
// FIRST DO MAX LIFE
dPercentage = (FLOAT)pSoldier->stats.bLife / (FLOAT)100;
FLOAT dstart1 = dStart - dEnd;
dStart = (FLOAT)( dStart - dEnd );
dEnd = dPercentage * sHeight;
dStart = sYPos;
usLineColor = Get16BPPColor( LIFE_BAR_SHADOW );
RectangleDraw( TRUE, sXPos, (INT32)dStart, sXPos, (INT32)( dStart - dEnd ) , usLineColor, pDestBuf );
@@ -177,15 +188,33 @@ void DrawLifeUIBarEx( SOLDIERTYPE *pSoldier, INT16 sXPos, INT16 sYPos, INT16 sWi
usLineColor = Get16BPPColor( LIFE_BAR_SHADOW );
RectangleDraw( TRUE, sXPos+ 2, (INT32)dStart, sXPos + 2, (INT32)( dStart - dEnd ), usLineColor, pDestBuf );
// NOW DO BANDAGE
// poisoned life first
if ( pSoldier->bPoisonLife )
{
dPercentage = (FLOAT)pSoldier->bPoisonLife / (FLOAT)100;
FLOAT dpoisonStart = (FLOAT)( dstart1 );
FLOAT dpoisonEnd = dPercentage * sHeight;
usLineColor = Get16BPPColor( POISON_LIFE_BAR_SHADOW );
RectangleDraw( TRUE, sXPos, (INT32)dpoisonStart, sXPos, (INT32)( dpoisonStart - dpoisonEnd ) , usLineColor, pDestBuf );
usLineColor = Get16BPPColor( POISON_LIFE_BAR );
RectangleDraw( TRUE, sXPos+ 1, (INT32)dpoisonStart, sXPos + 1, (INT32)( dpoisonStart - dpoisonEnd ), usLineColor, pDestBuf );
usLineColor = Get16BPPColor( POISON_LIFE_BAR_SHADOW );
RectangleDraw( TRUE, sXPos+ 2, (INT32)dpoisonStart, sXPos + 2, (INT32)( dpoisonStart - dpoisonEnd ), usLineColor, pDestBuf );
}
// NOW DO BANDAGE
// Calculate bandage
FLOAT dstart2 = dStart - dEnd;
bBandage = pSoldier->stats.bLifeMax - pSoldier->stats.bLife - pSoldier->bBleeding;
if ( bBandage )
{
dPercentage = (FLOAT)bBandage / (FLOAT)100;
dStart = (FLOAT)( sYPos - dEnd );
dStart = (FLOAT)( dStart - dEnd );
dEnd = ( dPercentage * sHeight );
usLineColor = Get16BPPColor( BANDAGE_BAR_SHADOW );
@@ -198,7 +227,26 @@ void DrawLifeUIBarEx( SOLDIERTYPE *pSoldier, INT16 sXPos, INT16 sYPos, INT16 sWi
RectangleDraw( TRUE, sXPos+ 2, (INT32)dStart, sXPos + 2, (INT32)( dStart - dEnd ), usLineColor, pDestBuf );
}
// get amount of poisoned bandage
INT8 bPoisonBandage = pSoldier->bPoisonSum - pSoldier->bPoisonBleeding - pSoldier->bPoisonLife;
if ( bPoisonBandage )
{
dPercentage = (FLOAT)bPoisonBandage / (FLOAT)100;
FLOAT dpoisonStart = (FLOAT)( dstart2 );
FLOAT dpoisonEnd = dPercentage * sHeight;
usLineColor = Get16BPPColor( POISON_BANDAGE_BAR_SHADOW );
RectangleDraw( TRUE, sXPos, (INT32)dpoisonStart, sXPos, (INT32)( dpoisonStart - dpoisonEnd ) , usLineColor, pDestBuf );
usLineColor = Get16BPPColor( POISON_BANDAGE_BAR );
RectangleDraw( TRUE, sXPos+ 1, (INT32)dpoisonStart, sXPos + 1, (INT32)( dpoisonStart - dpoisonEnd ), usLineColor, pDestBuf );
usLineColor = Get16BPPColor( POISON_BANDAGE_BAR_SHADOW );
RectangleDraw( TRUE, sXPos+ 2, (INT32)dpoisonStart, sXPos + 2, (INT32)( dpoisonStart - dpoisonEnd ), usLineColor, pDestBuf );
}
// NOW DO BLEEDING
FLOAT dstart3 = dStart - dEnd;
if ( pSoldier->bBleeding )
{
dPercentage = (FLOAT)pSoldier->bBleeding / (FLOAT)100;
@@ -215,6 +263,23 @@ void DrawLifeUIBarEx( SOLDIERTYPE *pSoldier, INT16 sXPos, INT16 sYPos, INT16 sWi
RectangleDraw( TRUE, sXPos+ 2, (INT32)dStart, sXPos + 2, (INT32)( dStart - dEnd ), usLineColor, pDestBuf );
}
// poisoned bleeding
if ( pSoldier->bPoisonBleeding )
{
dPercentage = (FLOAT)pSoldier->bPoisonBleeding / (FLOAT)100;
FLOAT dpoisonStart = (FLOAT)( dstart3 );
FLOAT dpoisonEnd = dPercentage * sHeight;
usLineColor = Get16BPPColor( POISON_BLEEDING_BAR_SHADOW );
RectangleDraw( TRUE, sXPos, (INT32)dpoisonStart, sXPos, (INT32)( dpoisonStart - dpoisonEnd ) , usLineColor, pDestBuf );
usLineColor = Get16BPPColor( POISON_BLEEDING_BAR );
RectangleDraw( TRUE, sXPos+ 1, (INT32)dpoisonStart, sXPos + 1, (INT32)( dpoisonStart - dpoisonEnd ), usLineColor, pDestBuf );
usLineColor = Get16BPPColor( POISON_BLEEDING_BAR_SHADOW );
RectangleDraw( TRUE, sXPos+ 2, (INT32)dpoisonStart, sXPos + 2, (INT32)( dpoisonStart - dpoisonEnd ), usLineColor, pDestBuf );
}
UnLockVideoSurface( uiBuffer );
}
+69
View File
@@ -2210,6 +2210,21 @@ void DrawSelectedUIAboveGuy( UINT16 usSoldierID )
}
}
}
if ( pSoldier->IsZombie() )
{
swprintf(NameStr, pSoldier->name);
// Display name
SetFont( TINYFONT1 );
SetFontBackground( FONT_MCOLOR_BLACK );
SetFontForeground( FONT_MCOLOR_WHITE );
//legion2
FindFontCenterCoordinates( sXPos, (INT16)( sYPos -10 ), (INT16)(80 ), 1, NameStr, TINYFONT1, &sX, &sY );
gprintfdirty( sX, sY, NameStr );
mprintf( sX, sY, NameStr );
}
//------------
}
}
@@ -3162,6 +3177,7 @@ void DrawBarsInUIBox( SOLDIERTYPE *pSoldier , INT16 sXPos, INT16 sYPos, INT16 sW
UINT8 *pDestBuf;
UINT16 usLineColor;
INT8 bBandage;
INT8 bPoisonBandage;
// Draw breath points
@@ -3174,6 +3190,8 @@ void DrawBarsInUIBox( SOLDIERTYPE *pSoldier , INT16 sXPos, INT16 sYPos, INT16 sW
// get amt bandaged
bBandage = pSoldier->stats.bLifeMax - pSoldier->stats.bLife - pSoldier->bBleeding;
// get amount of poisoned bandage
bPoisonBandage = pSoldier->bPoisonSum - pSoldier->bPoisonBleeding - pSoldier->bPoisonLife;
// NOW DO BLEEDING
@@ -3194,6 +3212,23 @@ void DrawBarsInUIBox( SOLDIERTYPE *pSoldier , INT16 sXPos, INT16 sYPos, INT16 sW
}
}
// poisoned bleeding
if ( pSoldier->bPoisonBleeding )
{
dPercentage = (FLOAT)( pSoldier->stats.bLifeMax - pSoldier->bBleeding + pSoldier->bPoisonBleeding )/ (FLOAT)100;
dWidth = dPercentage * sWidth;
if(gbPixelDepth==16)
{
usLineColor = Get16BPPColor( FROMRGB( 240, 20, 240 ) );
RectangleDraw( TRUE, sXPos + 3, sYPos + 1, (INT32)( sXPos + dWidth + 3 ), sYPos + 1, usLineColor, pDestBuf );
}
else if(gbPixelDepth==8)
{
// DB Need to change this to a color from the 8-bit standard palette
usLineColor = COLOR_GREEN;
RectangleDraw8( TRUE, sXPos + 3, sYPos + 1, (INT32)( sXPos + dWidth + 3 ), sYPos + 1, usLineColor, pDestBuf );
}
}
if( bBandage )
{
@@ -3212,6 +3247,23 @@ void DrawBarsInUIBox( SOLDIERTYPE *pSoldier , INT16 sXPos, INT16 sYPos, INT16 sW
}
}
// poisoned bandage
if ( bPoisonBandage )
{
dPercentage = (FLOAT)( pSoldier->stats.bLife + bPoisonBandage )/ (FLOAT)100;
dWidth = dPercentage * sWidth;
if(gbPixelDepth==16)
{
usLineColor = Get16BPPColor( FROMRGB( 132, 222, 132 ) );
RectangleDraw( TRUE, sXPos + 3, sYPos + 1, (INT32)( sXPos + dWidth + 3 ), sYPos + 1, usLineColor, pDestBuf );
}
else if(gbPixelDepth==8)
{
// DB Need to change this to a color from the 8-bit standard palette
usLineColor = COLOR_GREEN;
RectangleDraw8( TRUE, sXPos + 3, sYPos + 1, (INT32)( sXPos + dWidth + 3 ), sYPos + 1, usLineColor, pDestBuf );
}
}
dPercentage = (FLOAT)pSoldier->stats.bLife / (FLOAT)100;
dWidth = dPercentage * sWidth;
@@ -3227,6 +3279,23 @@ void DrawBarsInUIBox( SOLDIERTYPE *pSoldier , INT16 sXPos, INT16 sYPos, INT16 sW
RectangleDraw8( TRUE, sXPos + 3, sYPos + 1, (INT32)( sXPos + dWidth + 3 ), sYPos + 1, usLineColor, pDestBuf );
}
// poisoned life
if ( pSoldier->bPoisonLife )
{
dPercentage = (FLOAT)( pSoldier->bPoisonLife )/ (FLOAT)100;
dWidth = dPercentage * sWidth;
if(gbPixelDepth==16)
{
usLineColor = Get16BPPColor( FROMRGB( 0, 200, 0 ) );
RectangleDraw( TRUE, sXPos + 3, sYPos + 1, (INT32)( sXPos + dWidth + 3 ), sYPos + 1, usLineColor, pDestBuf );
}
else if(gbPixelDepth==8)
{
// DB Need to change this to a color from the 8-bit standard palette
usLineColor = COLOR_GREEN;
RectangleDraw8( TRUE, sXPos + 3, sYPos + 1, (INT32)( sXPos + dWidth + 3 ), sYPos + 1, usLineColor, pDestBuf );
}
}
dPercentage = (FLOAT)( pSoldier->bBreathMax ) / (FLOAT)100;
+7
View File
@@ -846,6 +846,10 @@ void GenerateRandomEquipment( SOLDIERCREATE_STRUCT *pp, INT8 bSoldierClass, INT8
}
}
break;
case SOLDIER_CLASS_ZOMBIE:
// zombies get no items at all...
break;
}
for ( i = 0; i < pp->Inv.size(); i++ )
@@ -1052,6 +1056,8 @@ void ChooseWeaponForSoldierCreateStruct( SOLDIERCREATE_STRUCT *pp, INT8 bWeaponC
bStatus += (INT8)(HighestPlayerProgressPercentage() / 10);
bStatus = (INT8)min( 100, bStatus );
break;
case SOLDIER_CLASS_ZOMBIE:
bStatus = (INT8)(1); // if a zombie gets anything, it'll be broken
default:
bStatus = (INT8)(50 + Random( 51 ) );
break;
@@ -2105,6 +2111,7 @@ void ChooseFaceGearForSoldierCreateStruct( SOLDIERCREATE_STRUCT *pp )
break;
case SOLDIER_CLASS_ADMINISTRATOR:
case SOLDIER_CLASS_GREEN_MILITIA:
case SOLDIER_CLASS_ZOMBIE:
break;
}
}
+6
View File
@@ -219,6 +219,9 @@ typedef enum
#define GS_CARTRIDGE_IN_CHAMBER 0x01
#define GS_WEAPON_BEING_RELOADED 0x02
// Flugente: define for maximum temperature
#define OVERHEATING_MAX_TEMPERATURE 60000.0
//forward declaration
class OBJECTTYPE;
class SOLDIERTYPE;
@@ -956,6 +959,9 @@ typedef struct
BOOLEAN blockironsight; // if a gun or any attachment have this property, the iron sight won't be usable (if there is at least one other usable sight)
// Flugente poison system
INT16 bPoisonPercentage;
} INVTYPE;
// CHRISL: Added new structures to handle LBE gear and the two new XML files that will be needed to deal
+51 -8
View File
@@ -3042,7 +3042,7 @@ UINT32 CalculateCarriedWeight( SOLDIERTYPE * pSoldier )
UINT32 uiTotalWeight = 0;
UINT32 uiPercent;
UINT8 ubLoop;
UINT8 ubStrengthForCarrying;
UINT16 ubStrengthForCarrying;
//Pulmu: Changes for dynamic ammo weight
for( ubLoop = 0; ubLoop < pSoldier->inv.size(); ubLoop++)
@@ -7418,7 +7418,7 @@ BOOLEAN CreateGun( UINT16 usItem, INT16 bStatus, OBJECTTYPE * pObj )
pStackedObject->data.ubImprintID = NO_PROFILE;
// Flugente FTW 1: temperature on creation is 0
pStackedObject->data.bTemperature = 0.0;
pStackedObject->data.bTemperature = 0.0f;
if (Weapon[ usItem ].ubWeaponClass == MONSTERCLASS)
{
@@ -7533,6 +7533,7 @@ BOOLEAN CreateItem( UINT16 usItem, INT16 bStatus, OBJECTTYPE * pObj )
{
(*pObj)[0]->data.objectStatus = bStatus;
}
//ADB ubWeight has been removed, see comments in OBJECTTYPE
//pObj->ubWeight = CalculateObjectWeight( pObj );
fRet = TRUE;
@@ -9189,6 +9190,41 @@ void ActivateXRayDevice( SOLDIERTYPE * pSoldier )
pSoldier->uiXRayActivatedTime = GetWorldTotalSeconds();
}
void TurnOnXRayEffects( SOLDIERTYPE * pSoldier )
{
SOLDIERTYPE * pSoldier2;
UINT32 uiSlot;
// first, scan through all mercs and turn off xrayed flag for anyone
// previously xrayed by this guy
for ( uiSlot = 0; uiSlot < guiNumMercSlots; ++uiSlot )
{
pSoldier2 = MercSlots[ uiSlot ];
if ( pSoldier2 )
{
if ( (pSoldier2->ubMiscSoldierFlags & SOLDIER_MISC_XRAYED) && (pSoldier2->aiData.ubXRayedBy == pSoldier->ubID) )
{
pSoldier2->ubMiscSoldierFlags &= (~SOLDIER_MISC_XRAYED);
pSoldier2->aiData.ubXRayedBy = NOBODY;
}
}
}
// now turn on xray for anyone within range
for ( uiSlot = 0; uiSlot < guiNumMercSlots; ++uiSlot )
{
pSoldier2 = MercSlots[ uiSlot ];
if ( pSoldier2 )
{
if ( pSoldier2->bTeam != pSoldier->bTeam && PythSpacesAway( pSoldier->sGridNo, pSoldier2->sGridNo ) < XRAY_RANGE )
{
pSoldier2->ubMiscSoldierFlags |= SOLDIER_MISC_XRAYED;
pSoldier2->aiData.ubXRayedBy = pSoldier->ubID;
}
}
}
pSoldier->uiXRayActivatedTime = GetWorldTotalSeconds();
}
void TurnOffXRayEffects( SOLDIERTYPE * pSoldier )
{
SOLDIERTYPE * pSoldier2;
@@ -9453,13 +9489,17 @@ INT16 GetGearAPBonus( SOLDIERTYPE * pSoldier )
{
INT16 bonus=0;
for (int j = HELMETPOS; j <= HEAD2POS; j++)
for (int j = HELMETPOS; j <= HEAD2POS; ++j)
{
if (pSoldier->inv[j].exists() == true) {
bonus += Item[pSoldier->inv[j].usItem].APBonus;
if (pSoldier->inv[j].exists() == true)
{
OBJECTTYPE* pObj = &pSoldier->inv[j];
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter) {
if(iter->exists()){
attachmentList::iterator iterend = (*pObj)[0]->attachments.begin();
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != iterend; ++iter)
{
if(iter->exists())
{
bonus += Item[iter->usItem].APBonus;
}
}
@@ -11020,7 +11060,9 @@ BOOLEAN HasThermalOptics( SOLDIERTYPE * pSoldier )
if (!IsWeapon(pSoldier->inv[i].usItem) || (IsWeapon(pSoldier->inv[i].usItem) && usingGunScope == true) )
{
if (Item[pSoldier->inv[i].usItem].thermaloptics)
{
return TRUE;
}
}
}
}
@@ -13414,6 +13456,8 @@ BOOLEAN HasAttachmentOfClass( OBJECTTYPE * pObj, UINT32 aFlag )
return( FALSE );
}
extern void HandleSight(SOLDIERTYPE *pSoldier, UINT8 ubSightFlags);
///////////////////////////////////////////////////////////////////////////////////////////////////
// HEADROCK HAM 5: Item Transformation.
// Item Transformation is a new way to interact with items. Where Merges combine two items into one, a Transformation
@@ -13816,4 +13860,3 @@ UINT64 GetAvailableAttachmentPoint (OBJECTTYPE * pObject, UINT8 subObject)
return point;
}
+2 -4
View File
@@ -225,6 +225,7 @@ void CheckEquipmentForFragileItemDamage( SOLDIERTYPE *pSoldier, INT32 iDamage );
#define XRAY_TIME 5
extern void ActivateXRayDevice( SOLDIERTYPE * pSoldier );
extern void TurnOnXRayEffects( SOLDIERTYPE * pSoldier );
extern void TurnOffXRayEffects( SOLDIERTYPE * pSoldier );
OBJECTTYPE* FindLaunchableAttachment( OBJECTTYPE * pObj, UINT16 usWeapon );
UINT16 FindLegalGrenade(UINT16 usItem);
@@ -448,7 +449,7 @@ BOOLEAN UseTotalMedicalKitPoints( SOLDIERTYPE * pSoldier, UINT16 usPointsToConsu
FLOAT GetItemCooldownFactor( OBJECTTYPE * pObj );
void GetScopeLists( OBJECTTYPE * pObj, std::map<INT8, OBJECTTYPE*>& arScopeMap );
// check if item belongs to a specific attachemnt class
// check if item belongs to a specific attachment class
BOOLEAN IsAttachmentClass( UINT16 usItem, UINT32 aFlag );
BOOLEAN HasAttachmentOfClass( OBJECTTYPE * pObj, UINT32 aFlag );
@@ -459,6 +460,3 @@ bool IsAttachmentPointAvailable( UINT64 point, UINT32 attachmentID, BOOLEAN only
UINT64 GetAvailableAttachmentPoint ( OBJECTTYPE * pObject, UINT8 subObject );
#endif
+2 -2
View File
@@ -702,7 +702,7 @@ void HandleDoorTrap( SOLDIERTYPE * pSoldier, DOOR * pDoor )
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("!!!!!!! Trap gone off %d", gTacticalStatus.ubAttackBusyCount) );
DebugAttackBusy( "!!!!!!! Trap gone off\n" );
pSoldier->SoldierTakeDamage( 0, (UINT16) (10 + PreRandom( 10 )), (UINT16) ((3 + PreRandom( 3 ) * 1000)), TAKE_DAMAGE_ELECTRICITY, NOBODY, pDoor->sGridNo, 0, TRUE );
pSoldier->SoldierTakeDamage( 0, (UINT16) (10 + PreRandom( 10 )), 0, (UINT16) ((3 + PreRandom( 3 ) * 1000)), TAKE_DAMAGE_ELECTRICITY, NOBODY, pDoor->sGridNo, 0, TRUE );
break;
case SUPER_ELECTRIC:
@@ -717,7 +717,7 @@ void HandleDoorTrap( SOLDIERTYPE * pSoldier, DOOR * pDoor )
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("!!!!!!! Trap gone off %d", gTacticalStatus.ubAttackBusyCount) );
DebugAttackBusy( "!!!!!!! Trap gone off\n" );
pSoldier->SoldierTakeDamage( 0, (UINT16) (20 + PreRandom( 20 )), (UINT16) ((6 + PreRandom( 6 ) * 1000)), TAKE_DAMAGE_ELECTRICITY, NOBODY, pDoor->sGridNo, 0, TRUE );
pSoldier->SoldierTakeDamage( 0, (UINT16) (20 + PreRandom( 20 )), 0, (UINT16) ((6 + PreRandom( 6 ) * 1000)), TAKE_DAMAGE_ELECTRICITY, NOBODY, pDoor->sGridNo, 0, TRUE );
break;
+1
View File
@@ -48,6 +48,7 @@
#include "WorldDat.h"
// HEADROCK HAM 3.6: This must be included, for testing whether Bloodcats and Enemies can see one another.
#include "Campaign Types.h"
#include "soldier tile.h" // added by Flugente
//forward declarations of common classes to eliminate includes
class OBJECTTYPE;
-16
View File
@@ -109,20 +109,6 @@ extern SOLDIERTYPE *pTMilitiaSoldier;
extern BOOLEAN SoldierCanAffordNewStance( SOLDIERTYPE *pSoldier, UINT8 ubDesiredStance );
void ResetMilitia()
{
UINT8 ubNumGreen = 0;
@@ -2370,5 +2356,3 @@ void MilitiaControlMenuBtnCallBack( MOUSE_REGION * pRegion, INT32 iReason )
// return;
//}
+9 -1
View File
@@ -88,6 +88,8 @@ MoraleEvent gbMoraleEvent[NUM_MORALE_EVENTS] =
{ TACTICAL_MORALE_EVENT, -1}, // MORALE_PSYCHO_UNABLE_TO_PSYCHO,
{ STRATEGIC_MORALE_EVENT, +1}, // MORALE_PACIFIST_GAIN_NONCOMBAT,
{ TACTICAL_MORALE_EVENT, +1}, // MORALE_MALICIOUS_HIT,
// added by SANDRO
{ TACTICAL_MORALE_EVENT, -1}, //MORALE_KHORNATE_RANGED_COMBAT,
};
BOOLEAN gfSomeoneSaidMoraleQuote = FALSE;
@@ -523,7 +525,7 @@ void UpdateSoldierMorale( SOLDIERTYPE * pSoldier, INT8 bMoraleEvent )
}
}
}
else if ( bMoraleMod != MORALE_PSYCHO_UNABLE_TO_PSYCHO)
else if ( bMoraleMod != MORALE_PSYCHO_UNABLE_TO_PSYCHO && bMoraleMod != MORALE_KHORNATE_RANGED_COMBAT)
{
switch( pProfile->bAttitude )
{
@@ -909,6 +911,12 @@ void HandleMoraleEvent( SOLDIERTYPE *pSoldier, INT8 bMoraleEvent, INT16 sMapX, I
HandleMoraleEventForSoldier( pSoldier, bMoraleEvent );
break;
// added by Flugente
case MORALE_KHORNATE_RANGED_COMBAT:
Assert( pSoldier );
HandleMoraleEventForSoldier( pSoldier, bMoraleEvent );
break;
default:
// debug message
ScreenMsg( MSG_FONT_RED, MSG_BETAVERSION, L"Invalid morale event type = %d. AM/CC-1", bMoraleEvent );
+3
View File
@@ -49,6 +49,9 @@ typedef enum
MORALE_PSYCHO_UNABLE_TO_PSYCHO,
MORALE_PACIFIST_GAIN_NONCOMBAT,
MORALE_MALICIOUS_HIT,
// added by Flugente
MORALE_KHORNATE_RANGED_COMBAT,
NUM_MORALE_EVENTS
} MoraleEventNames;
+30 -4
View File
@@ -6975,10 +6975,12 @@ BOOLEAN CheckForEndOfBattle( BOOLEAN fAnEnemyRetreated )
if (pTeamSoldier->iHealableInjury < 0)
pTeamSoldier->iHealableInjury = 0;
pTeamSoldier->bPoisonLife = min(pTeamSoldier->bPoisonSum, pTeamSoldier->bPoisonLife + OKLIFE - pTeamSoldier->stats.bLife);
pTeamSoldier->stats.bLife = OKLIFE;
}
pTeamSoldier->bBleeding = 0; // let's think, the autobandage was done for the militia too
pTeamSoldier->bPoisonBleeding = 0;
}
}
gTacticalStatus.Team[ MILITIA_TEAM ].bAwareOfOpposition = FALSE;
@@ -7255,6 +7257,26 @@ UINT8 NumEnemyInSector( )
}
UINT8 NumZombiesInSector( )
{
SOLDIERTYPE *pTeamSoldier;
INT32 cnt = 0;
UINT8 ubNumZombies = 0;
for ( pTeamSoldier = Menptr, cnt = 0; cnt < TOTAL_SOLDIERS; ++pTeamSoldier, ++cnt )
{
if ( pTeamSoldier->bActive && pTeamSoldier->bInSector && pTeamSoldier->stats.bLife > 0 )
{
if ( pTeamSoldier->IsZombie() )
{
++ubNumZombies;
}
}
}
return( ubNumZombies );
}
UINT8 NumEnemyInSectorExceptCreatures()
{
SOLDIERTYPE *pTeamSoldier;
@@ -7582,13 +7604,13 @@ BOOLEAN KillIncompacitatedEnemyInSector( )
// KIll......
// SANDRO - if the soldier is bleeding out, consider this damage as done by the last attacker
if ( pTeamSoldier->ubAttackerID != NOBODY )
pTeamSoldier->SoldierTakeDamage( ANIM_CROUCH, pTeamSoldier->stats.bLife, 100, TAKE_DAMAGE_BLOODLOSS, pTeamSoldier->ubAttackerID, NOWHERE, 0, TRUE );
pTeamSoldier->SoldierTakeDamage( ANIM_CROUCH, pTeamSoldier->stats.bLife, 0, 100, TAKE_DAMAGE_BLOODLOSS, pTeamSoldier->ubAttackerID, NOWHERE, 0, TRUE );
else if ( pTeamSoldier->ubPreviousAttackerID != NOBODY )
pTeamSoldier->SoldierTakeDamage( ANIM_CROUCH, pTeamSoldier->stats.bLife, 100, TAKE_DAMAGE_BLOODLOSS, pTeamSoldier->ubPreviousAttackerID, NOWHERE, 0, TRUE );
pTeamSoldier->SoldierTakeDamage( ANIM_CROUCH, pTeamSoldier->stats.bLife, 0, 100, TAKE_DAMAGE_BLOODLOSS, pTeamSoldier->ubPreviousAttackerID, NOWHERE, 0, TRUE );
else if ( pTeamSoldier->ubNextToPreviousAttackerID != NOBODY )
pTeamSoldier->SoldierTakeDamage( ANIM_CROUCH, pTeamSoldier->stats.bLife, 100, TAKE_DAMAGE_BLOODLOSS, pTeamSoldier->ubNextToPreviousAttackerID, NOWHERE, 0, TRUE );
pTeamSoldier->SoldierTakeDamage( ANIM_CROUCH, pTeamSoldier->stats.bLife, 0, 100, TAKE_DAMAGE_BLOODLOSS, pTeamSoldier->ubNextToPreviousAttackerID, NOWHERE, 0, TRUE );
else
pTeamSoldier->SoldierTakeDamage( ANIM_CROUCH, pTeamSoldier->stats.bLife, 100, TAKE_DAMAGE_BLOODLOSS, NOBODY, NOWHERE, 0, TRUE );
pTeamSoldier->SoldierTakeDamage( ANIM_CROUCH, pTeamSoldier->stats.bLife, 0, 100, TAKE_DAMAGE_BLOODLOSS, NOBODY, NOWHERE, 0, TRUE );
fReturnVal = TRUE;
}
@@ -7767,6 +7789,10 @@ void HandleSuppressionFire( UINT8 ubTargetedMerc, UINT8 ubCausedAttacker )
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("HandleSuppressionFire: loop = %d, numslots = %d ",uiLoop, guiNumMercSlots));
pSoldier = MercSlots[uiLoop];
// Flugente: zombies do not receive any suppression at all!
if ( pSoldier != NULL && pSoldier->IsZombie() )
continue;
// Has this character received any Suppression Points since the last attack?
// HEADROCK: Suppression Points accumulate by bullets flying near the character. It includes
// friendly fire at a certain distance. As of HAM 3.2, it also happens with nearby explosions.
+3
View File
@@ -393,4 +393,7 @@ BOOLEAN WillAirRaidBeStopped( INT16 sSectorX, INT16 sSectorY );
// HEADROCK HAM 3.5: Externalized for First Arrival enemy check
extern UINT8 NumEnemyInSector();
// Flugente
extern UINT8 NumZombiesInSector();
#endif
+398
View File
@@ -43,6 +43,9 @@
#include "strategic.h"
#include "qarray.h"
#include "Interface.h"
#include "Campaign Types.h"
//#include "Queen Command.h"
#endif
#include "Animation Control.h"
@@ -580,6 +583,10 @@ INT32 AddRottingCorpse( ROTTING_CORPSE_DEFINITION *pCorpseDef )
pCorpse->pAniTile->uiUserData = iIndex;
pCorpse->iID = iIndex;
// copy name of corpse definition...
memcpy( &(pCorpse->name), &(pCorpseDef->name), sizeof(CHAR16) * 10 );
pCorpse->name[9] = '\0';
pCorpse->fActivated = TRUE;
if ( Random( 100 ) > 50 )
@@ -853,6 +860,36 @@ BOOLEAN TurnSoldierIntoCorpse( SOLDIERTYPE *pSoldier, BOOLEAN fRemoveMerc, BOOLE
Corpse.usFlags |= ROTTING_CORPSE_USE_SNOW_CAMO_PALETTE;
}
// Flugente Zombies: Determine if a zombie can rise from this corpse
switch ( gGameExternalOptions.sZombieRiseBehaviour )
{
case 3:
// a zombie might rise again
if ( pSoldier->IsZombie() && Random( 2 ) > 0 )
Corpse.usFlags |= ROTTING_CORPSE_NEVER_RISE_AGAIN;
break;
case 2:
// death tosses a coin...
if ( Random( 2 ) > 0 )
Corpse.usFlags |= ROTTING_CORPSE_NEVER_RISE_AGAIN;
break;
case 1:
// no flag, the dead shall rise for eternity!
break;
case 0:
default:
// a killed zombie won't rise again
if ( pSoldier->IsZombie() )
Corpse.usFlags |= ROTTING_CORPSE_NEVER_RISE_AGAIN;
break;
}
// Flugente: copy name of soldier...
memcpy( &(Corpse.name), &(pSoldier->name), sizeof(CHAR16) * 10 );
Corpse.name[9] = '\0';
// Determine corpse type!
ubType = (UINT8)gubAnimSurfaceCorpseID[ pSoldier->ubBodyType][ pSoldier->usAnimState ];
@@ -2046,3 +2083,364 @@ UINT8 GetNearestRottingCorpseAIWarning( INT32 sGridNo )
return( ubHighestWarning );
}
// Flugente Zombies: resurrect zombies
void RaiseZombies( void )
{
if ( gGameSettings.fOptions[TOPTION_ZOMBIES] )
{
// 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 )
{
ROTTING_CORPSE * pCorpse;
BOOLEAN zombieshaverisen = FALSE;
SECTORINFO *pSector = &SectorInfo[ SECTOR( gWorldSectorX, gWorldSectorY ) ];
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)...
{
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->fActivated && pCorpse->def.fHeadTaken == FALSE ) // ... if corpse is active, and still has a head ...
{
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 );
//++pSector->ubNumZombies;
//++pSector->ubZombiesInBattle;
RemoveCorpse( cnt );
}
}
}
}
}
}
}
else
{
// if there is no more room, we can skip this
break;
}
}
if ( zombieshaverisen )
{
#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 );
}
}
}
}
// 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 )
{
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;
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;
// do not generate a new palette, thereby using the old palette of the corpse
MercCreateStruct.fNoGenNewPalette = TRUE;
INT8 iNewIndex;
if ( TacticalCreateSoldier( &MercCreateStruct, (UINT8 *)&iNewIndex ) )
{
/* certain values have to be set afterwards - the alternative 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);
//////////////////////////////////////////////////////////////////////
memcpy( &(pNewSoldier->name), &(pCorpse->name), sizeof(CHAR16) * 10 );
pNewSoldier->name[9] = '\0';
// 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 );
// 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:
;
}
return( canbezombie );
}
+38 -21
View File
@@ -26,14 +26,14 @@ enum RottingCorpseDefines
MMERC_FALL,
MMERC_FALLF,
FMERC_JFK,
FMERC_BCK,
FMERC_FWD,
FMERC_JFK, // head has exploded
FMERC_BCK, // body lying backward
FMERC_FWD, // body lying forward
FMERC_DHD,
FMERC_PRN,
FMERC_WTR,
FMERC_FALL,
FMERC_FALLF,
FMERC_PRN, // body lying on the belly while looking forward, one leg to the side
FMERC_WTR, // body lying in water
FMERC_FALL, // body lying backward, fallen from roof
FMERC_FALLF, // body lying forward, fallen from roof
// CIVS
M_DEAD1,
@@ -73,17 +73,19 @@ enum RottingCorpseDefines
#define ROTTING_CORPSE_FIND_SWEETSPOT_FROM_GRIDNO 0x001 //Find the closest spot to the given gridno
#define ROTTING_CORPSE_FIND_SWEETSPOT_FROM_GRIDNO 0x001 //Find the closest spot to the given gridno
#define ROTTING_CORPSE_USE_NORTH_ENTRY_POINT 0x002 //Find the spot closest to the north entry grid
#define ROTTING_CORPSE_USE_SOUTH_ENTRY_POINT 0x004 //Find the spot closest to the south entry grid
#define ROTTING_CORPSE_USE_EAST_ENTRY_POINT 0x008 //Find the spot closest to the east entry grid
#define ROTTING_CORPSE_USE_WEST_ENTRY_POINT 0x010 //Find the spot closest to the west entry grid
#define ROTTING_CORPSE_USE_CAMO_PALETTE 0x020 //We use cammo palette here....
#define ROTTING_CORPSE_VEHICLE 0x040 //Vehicle Corpse
#define ROTTING_CORPSE_USE_STEALTH_PALETTE 0x080 //We use stealth palette here....
#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_VEHICLE 0x040 //Vehicle Corpse
#define ROTTING_CORPSE_USE_STEALTH_PALETTE 0x080 //We use stealth palette here....
#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 )
typedef struct
{
@@ -94,26 +96,29 @@ typedef struct
FLOAT dYPos;
INT16 sHeightAdjustment;
PaletteRepID HeadPal; // Palette reps
PaletteRepID PantsPal;
PaletteRepID VestPal;
PaletteRepID SkinPal;
PaletteRepID HeadPal; // Palette reps
PaletteRepID PantsPal;
PaletteRepID VestPal;
PaletteRepID SkinPal;
UINT8 ubDirection;
UINT32 uiTimeOfDeath;
UINT32 uiTimeOfDeath;
UINT16 usFlags;
UINT16 usFlags;
INT8 bLevel;
INT8 bVisible;
INT8 bNumServicingCrows;
UINT8 ubProfile;
BOOLEAN fHeadTaken;
UINT8 ubAIWarningValue;
BOOLEAN fHeadTaken;
UINT8 ubAIWarningValue;
UINT8 ubFiller[ 12 ];
// Flugente: added name so we can display individual name if corpse gets resurrected...
CHAR16 name[ 10 ];
} ROTTING_CORPSE_DEFINITION;
@@ -135,6 +140,9 @@ typedef struct
BOOLEAN fAttractCrowsOnlyWhenOnScreen;
INT32 iID;
// Flugente: added name so we can display individual name if corpse gets resurrected...
CHAR16 name[ 10 ];
} ROTTING_CORPSE;
@@ -192,4 +200,13 @@ INT32 GetGridNoOfCorpseGivenProfileID( UINT8 ubProfileID );
void DecayRottingCorpseAIWarnings( void );
UINT8 GetNearestRottingCorpseAIWarning( INT32 sGridNo );
// Flugente: Raise zombies
void RaiseZombies( void );
// 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 );
#endif
+14 -6
View File
@@ -18,7 +18,7 @@
#include "Soldier Control.h"
#endif
INT8 EffectiveStrength( SOLDIERTYPE * pSoldier )
INT8 EffectiveStrength( SOLDIERTYPE *pSoldier)
{
INT8 bBandaged;
INT32 iEffStrength;
@@ -29,9 +29,9 @@ INT8 EffectiveStrength( SOLDIERTYPE * pSoldier )
bBandaged = pSoldier->stats.bLifeMax - pSoldier->stats.bLife - pSoldier->bBleeding;
if (pSoldier->stats.bStrength > 0)
{
iEffStrength = pSoldier->stats.bStrength / 2;
iEffStrength += (pSoldier->stats.bStrength / 2) * (pSoldier->stats.bLife + bBandaged / 2) / (pSoldier->stats.bLifeMax);
{
iEffStrength = ( pSoldier->stats.bStrength )/ 2;
iEffStrength += ( (pSoldier->stats.bStrength ) / 2) * (pSoldier->stats.bLife + bBandaged / 2) / (pSoldier->stats.bLifeMax);
}
else
{
@@ -164,7 +164,7 @@ INT8 EffectiveExpLevel( SOLDIERTYPE * pSoldier )
iEffExpLevel -= 1;
}
}
if (iEffExpLevel > 10)
{
// can't go over 10 - SANDRO
@@ -476,7 +476,7 @@ INT32 SkillCheck( SOLDIERTYPE * pSoldier, INT8 bReason, INT8 bChanceMod )
case OPEN_WITH_CROWBAR:
// Add for crowbar...
iSkill = EffectiveStrength( pSoldier ) + 20;
fForceDamnSound = TRUE;
fForceDamnSound = TRUE;
break;
case SMASH_DOOR_CHECK:
@@ -546,6 +546,14 @@ INT32 SkillCheck( SOLDIERTYPE * pSoldier, INT8 bReason, INT8 bChanceMod )
iSkill /= 2;
}
}
break;
case ATTACH_POWER_PACK: // added by Flugente
// technicians can attach it, other people can'
if ( HAS_SKILL_TRAIT( pSoldier, TECHNICIAN_NT ))
iSkill = 100;
else
iSkill = 0;
break;
default:
iSkill = 0;
+1
View File
@@ -41,6 +41,7 @@ enum SkillChecks
ATTACHING_SPECIAL_ITEM_CHECK,
ATTACHING_SPECIAL_ELECTRONIC_ITEM_CHECK,
DISARM_ELECTRONIC_TRAP_CHECK,
ATTACH_POWER_PACK, // Flugente: attach a power pack to power armor
} ;
+3
View File
@@ -3485,6 +3485,9 @@ BOOLEAN HandleSoldierDeath( SOLDIERTYPE *pSoldier , BOOLEAN *pfMadeCorpse )
case SOLDIER_CLASS_CREATURE :
gMercProfiles[ MercPtrs[ ubAttacker ]->ubProfile ].records.usKillsCreatures++;
break;
case SOLDIER_CLASS_ZOMBIE :
gMercProfiles[ MercPtrs[ ubAttacker ]->ubProfile ].records.usKillsZombies++;
break;
default :
if ( CREATURE_OR_BLOODCAT( pSoldier ) )
gMercProfiles[ MercPtrs[ ubAttacker ]->ubProfile ].records.usKillsCreatures++;
+427 -138
View File
@@ -110,6 +110,8 @@
#include "Dialogue Control.h"
#include "IMP Skill Trait.h" // added by Flugente
//forward declarations of common classes to eliminate includes
class OBJECTTYPE;
class SOLDIERTYPE;
@@ -135,6 +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 );
// Enumerate extended directions
enum
{
@@ -996,6 +1002,12 @@ SOLDIERTYPE& SOLDIERTYPE::operator=(const OLDSOLDIERTYPE_101& src)
this->wornSnowCamo = src.wornSnowCamo;
this->bScopeMode = USE_BEST_SCOPE;
this->bPoisonBleeding = 0;
this->bPoisonLife = 0;
this->bPoisonSum = 0;
this->bPoisonResistance = 0;
this->bPoisonAbsorption = 0;
}
return *this;
}
@@ -1337,6 +1349,7 @@ MERCPROFILESTRUCT& MERCPROFILESTRUCT::operator=(const OLD_MERCPROFILESTRUCT_101&
this->records.usKillsAdmins = (src.usKills/4);
this->records.usKillsHostiles = 0;
this->records.usKillsCreatures = 0;
this->records.usKillsZombies = 0;
this->records.usKillsTanks = 0;
this->records.usKillsOthers = 0;
this->records.usAssistsMercs = (src.usAssists*3/4);
@@ -1476,7 +1489,7 @@ MERCPROFILESTRUCT& MERCPROFILESTRUCT::operator=(const OLD_MERCPROFILESTRUCT_101&
this->iMercMercContractLength = src.iMercMercContractLength;//Used for MERC mercs, specifies how many days the merc has gone since last page
this->uiTotalCostToDate = src.uiTotalCostToDate;// The total amount of money that has been paid to the merc for their salary
this->uiTotalCostToDate = src.uiTotalCostToDate;// The total amount of money that has been paid to the merc for their salary
}
return *this;
}
@@ -1669,7 +1682,7 @@ void HandleSystemNewAISituation( SOLDIERTYPE *pSoldier, BOOLEAN fResetABC );
UINT16 *CreateEnemyGlow16BPPPalette( SGPPaletteEntry *pPalette, UINT32 rscale, UINT32 gscale, BOOLEAN fAdjustGreen );
UINT16 *CreateEnemyGreyGlow16BPPPalette( SGPPaletteEntry *pPalette, UINT32 rscale, UINT32 gscale, BOOLEAN fAdjustGreen );
void SoldierBleed( SOLDIERTYPE *pSoldier, BOOLEAN fBandagedBleed );
void SoldierBleed( SOLDIERTYPE *pSoldier, BOOLEAN fBandagedBleed, BOOLEAN fAllowPoisoning );
INT32 CheckBleeding( SOLDIERTYPE *pSoldier );
void EVENT_InternalSetSoldierDesiredDirection( SOLDIERTYPE *pSoldier, UINT8 ubNewDirection, BOOLEAN fInitalMove, UINT16 usAnimState );
@@ -5409,7 +5422,7 @@ void SOLDIERTYPE::EVENT_SoldierGotHit( UINT16 usWeaponIndex, INT16 sDamage, INT1
HandleMoraleEvent( this, MORALE_TOOK_LOTS_OF_DAMAGE, this->sSectorX, this->sSectorY, this->bSectorZ );
}
}
// SWITCH IN TYPE OF WEAPON
if ( ubSpecial == FIRE_WEAPON_TOSSED_OBJECT_SPECIAL )
{
@@ -5652,12 +5665,14 @@ void SOLDIERTYPE::EVENT_SoldierGotHit( UINT16 usWeaponIndex, INT16 sDamage, INT1
// OK, If we are a vehicle.... damage vehicle...( people inside... )
if ( this->flags.uiStatusFlags & SOLDIER_VEHICLE )
{
this->SoldierTakeDamage( ANIM_CROUCH, sDamage, sBreathLoss, ubReason, this->ubAttackerID, NOWHERE, FALSE, TRUE );
this->SoldierTakeDamage( ANIM_CROUCH, sDamage, 0, sBreathLoss, ubReason, this->ubAttackerID, NOWHERE, FALSE, TRUE );
return;
}
INT16 poisondamage = (INT16) ( sDamage * MercPtrs[ubAttackerID]->GetPoisonDamagePercentage() / 100 );
// DEDUCT LIFE
ubCombinedLoss = this->SoldierTakeDamage( ANIM_CROUCH, sDamage, sBreathLoss, ubReason, this->ubAttackerID, NOWHERE, FALSE, TRUE );
ubCombinedLoss = this->SoldierTakeDamage( ANIM_CROUCH, sDamage, poisondamage, sBreathLoss, ubReason, this->ubAttackerID, NOWHERE, FALSE, TRUE );
// ATE: OK, Let's check our ASSIGNMENT state,
// If anything other than on a squad or guard, make them guard....
@@ -7053,10 +7068,6 @@ void SOLDIERTYPE::EVENT_BeginMercTurn( BOOLEAN fFromRealTime, INT32 iRealTimeCou
{
HandleEndTurnDrugAdjustments( this );
}
else
{
HandleEndTurnDrugAdjustments( this );
}
// ATE: Don't bleed if in AUTO BANDAGE!
if ( !gTacticalStatus.fAutoBandageMode )
@@ -8657,7 +8668,16 @@ void SOLDIERTYPE::BeginSoldierClimbUpRoof( void )
this->ubPendingDirection = bNewDirection;
//this->usPendingAnimation = CLIMBUPROOF;
this->EVENT_InitNewSoldierAnim( CLIMBUPROOF, 0 , FALSE );
// Flugente: In case an animation is missing (zombies with bodytype of civilians), we TELEPORT instead
if ( IsAnimationValidForBodyType( this, CLIMBUPROOF ) == FALSE )
{
SetSoldierHeight( 50.0 );
TeleportSoldier( this, this->sTempNewGridNo, TRUE );
EndAIGuysTurn( this);
}
else
this->EVENT_InitNewSoldierAnim( CLIMBUPROOF, 0 , FALSE );
this->InternalReceivingSoldierCancelServices( FALSE );
this->InternalGivingSoldierCancelServices( FALSE );
@@ -8810,7 +8830,7 @@ void SOLDIERTYPE::BeginSoldierClimbWallUp( void )
UINT32 SleepDartSuccumbChance( SOLDIERTYPE * pSoldier )
{
UINT32 uiChance;
INT8 bEffectiveStrength;
INT16 bEffectiveStrength;
// figure out base chance of succumbing,
bEffectiveStrength = EffectiveStrength( pSoldier );
@@ -9006,12 +9026,12 @@ void HandleTakeDamageDeath( SOLDIERTYPE *pSoldier, UINT8 bOldLife, UINT8 ubReaso
}
UINT8 SOLDIERTYPE::SoldierTakeDamage( INT8 bHeight, INT16 sLifeDeduct, INT16 sBreathLoss, UINT8 ubReason, UINT8 ubAttacker, INT32 sSourceGrid, INT16 sSubsequent, BOOLEAN fShowDamage )
UINT8 SOLDIERTYPE::SoldierTakeDamage( INT8 bHeight, INT16 sLifeDeduct, INT16 sPoisonAdd, INT16 sBreathLoss, UINT8 ubReason, UINT8 ubAttacker, INT32 sSourceGrid, INT16 sSubsequent, BOOLEAN fShowDamage )
{
#ifdef JA2BETAVERSION
if (is_networked) {
CHAR tmpMPDbgString[512];
sprintf(tmpMPDbgString,"SoldierTakeDamage ( bHeight : %i , sLifeDeduct : %i , sBreathLoss : %i , ubReason : %i , ubAttacker : %i , sSourceGrid : %i , sSubsequent : %i , fShowDamage : %i )\n", bHeight , sLifeDeduct , sBreathLoss , ubReason , ubAttacker , sSourceGrid , sSubsequent , fShowDamage );
sprintf(tmpMPDbgString,"SoldierTakeDamage ( bHeight : %i , sLifeDeduct : %i , sPoisonAdd : %i , sBreathLoss : %i , ubReason : %i , ubAttacker : %i , sSourceGrid : %i , sSubsequent : %i , fShowDamage : %i )\n", bHeight , sLifeDeduct , sPoisonAdd, sBreathLoss , ubReason , ubAttacker , sSourceGrid , sSubsequent , fShowDamage );
MPDebugMsg(tmpMPDbgString);
}
#endif
@@ -9025,6 +9045,11 @@ UINT8 SOLDIERTYPE::SoldierTakeDamage( INT8 bHeight, INT16 sLifeDeduct, INT16 sBr
this->ubLastDamageReason = ubReason;
// check: poison damage cannot be higher than damage
sPoisonAdd = min(sPoisonAdd, sLifeDeduct);
// reduce poison damage by poison resistance
sPoisonAdd = (INT16)(sPoisonAdd * (100 - this->GetPoisonResistance())/100);
// CJC Jan 21 99: add check to see if we are hurting an enemy in an enemy-controlled
// sector; if so, this is a sign of player activity
@@ -9059,6 +9084,11 @@ UINT8 SOLDIERTYPE::SoldierTakeDamage( INT8 bHeight, INT16 sLifeDeduct, INT16 sBr
// Deduct life!, Show damage if we want!
bOldLife = this->stats.bLife;
// we need this to relation to decide how to redistribute poison points
FLOAT dpoisonliferelation = 1.0;
if ( bOldLife > 0 )
dpoisonliferelation = (FLOAT)(this->bPoisonLife / bOldLife);
// OK, If we are a vehicle.... damage vehicle...( people inside... )
if ( this->flags.uiStatusFlags & SOLDIER_VEHICLE )
{
@@ -9182,11 +9212,41 @@ UINT8 SOLDIERTYPE::SoldierTakeDamage( INT8 bHeight, INT16 sLifeDeduct, INT16 sBr
if (sLifeDeduct > this->stats.bLife)
{
this->stats.bLife = 0;
this->bPoisonSum = 0;
this->bPoisonLife = 0;
this->bPoisonBleeding = 0;
}
else
{
// we might have poison absorption
INT16 sLifeGainAbsorption = (INT16) ((sPoisonAdd * this->GetPoisonAbsorption())/100);
// life reduction gets reduced itself by life gained through absorption
sLifeDeduct -= sLifeGainAbsorption;
// poison points however get increased by absorped life points (poison was absorbed, not resisted)
INT16 poisongained = sPoisonAdd + sLifeGainAbsorption;
// Decrease Health
this->stats.bLife -= sLifeDeduct;
// life may increase by poison absorption, so make sure it doesn't rise too much
this->stats.bLife = min(this->stats.bLife, this->stats.bLifeMax);
// increase poisoning
this->bPoisonSum = min(this->stats.bLifeMax, this->bPoisonSum + poisongained);
// increase poison life if we gained life through absorption
if ( sLifeGainAbsorption > 0 )
this->bPoisonLife = min(this->bPoisonSum, this->bPoisonLife + sLifeGainAbsorption);
// if no life was lost, also add sPoisonAdd to bPoisonLife
if ( sLifeDeduct <= 0 )
this->bPoisonLife = min(this->bPoisonSum, this->bPoisonLife + sPoisonAdd);
else
// we reduce bPoisonLife according to old percentage of poison life to life
this->bPoisonLife -= (INT8) (dpoisonliferelation * sLifeDeduct);
}
/////////////////////////////////////////////////////////////////////////////////////////////////
@@ -9211,7 +9271,8 @@ UINT8 SOLDIERTYPE::SoldierTakeDamage( INT8 bHeight, INT16 sLifeDeduct, INT16 sBr
// ATE: Put some logic in here to allow enemies to die quicker.....
// Are we an enemy?
if ( this->bSide != gbPlayerNum && !this->aiData.bNeutral && this->ubProfile == NO_PROFILE )
// zombies don't die suddenly, as they regenerate health by bloodloss and poison. You have to make sure they die!
if ( this->bSide != gbPlayerNum && !this->aiData.bNeutral && this->ubProfile == NO_PROFILE && !this->IsZombie() )
{
// ATE: Give them a chance to fall down...
if ( this->stats.bLife > 0 && this->stats.bLife < ( OKLIFE - 1 ) )
@@ -9219,11 +9280,15 @@ UINT8 SOLDIERTYPE::SoldierTakeDamage( INT8 bHeight, INT16 sLifeDeduct, INT16 sBr
// Are we taking damage from bleeding?
if ( ubReason == TAKE_DAMAGE_BLOODLOSS )
{
// Fifty-fifty chance to die now!
// Fifty-fifty chance to die now!
if ( Random( 3 ) == 0 || gTacticalStatus.Team[ this->bTeam ].bMenInSector == 1 )
{
// Kill!
this->stats.bLife = 0;
this->bPoisonSum = 0;
this->bPoisonLife = 0;
this->bPoisonBleeding = 0;
}
}
else
@@ -9233,10 +9298,20 @@ UINT8 SOLDIERTYPE::SoldierTakeDamage( INT8 bHeight, INT16 sLifeDeduct, INT16 sBr
{
// Kill!
this->stats.bLife = 0;
this->bPoisonSum = 0;
this->bPoisonLife = 0;
this->bPoisonBleeding = 0;
}
}
}
}
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;
}
if ( fShowDamage )
{
@@ -9247,6 +9322,10 @@ UINT8 SOLDIERTYPE::SoldierTakeDamage( INT8 bHeight, INT16 sLifeDeduct, INT16 sBr
if ( this->stats.bLife < 0 )
{
this->stats.bLife = 0;
this->bPoisonSum = 0;
this->bPoisonLife = 0;
this->bPoisonBleeding = 0;
}
@@ -9267,11 +9346,29 @@ UINT8 SOLDIERTYPE::SoldierTakeDamage( INT8 bHeight, INT16 sLifeDeduct, INT16 sBr
{
// HTH does 1 pt bleeding per hit
this->bBleeding = this->bBleeding + 1;
// add poison point according to poison/life relation
this->bPoisonBleeding += (INT8) (dpoisonliferelation );
}
}
else
{
this->bBleeding = this->stats.bLifeMax - ( this->stats.bLife + bBandage );
// if we would actually bleed _less_ after applying the damage received (poison absorption), we reduce bleeding only if the new bBandage would be zero
// by this, we can continue bleeding, and eventually bleeding
// the normal behaviour is unchanged, as this case can't happen without poison absorption
if ( sLifeDeduct < 0 )
{
INT8 oldBleeding = this->bBleeding;
this->bBleeding = min(this->bBleeding, this->stats.bLifeMax - this->stats.bLife );
this->bPoisonBleeding = max(0, this->bPoisonBleeding - (oldBleeding - this->bBleeding));
}
else
{
this->bBleeding = this->stats.bLifeMax - ( this->stats.bLife + bBandage );
// we increase bPoisonLife according to old percentage of poison life to life
this->bPoisonBleeding += (INT8) (dpoisonliferelation * sLifeDeduct);
}
}
}
@@ -10089,7 +10186,7 @@ BOOLEAN SOLDIERTYPE::CheckSoldierHitRoof( void )
//this->EVENT_InitNewSoldierAnim( FALLFORWARD_ROOF, 0 , FALSE );
// Deduct hitpoints/breath for falling!
this->SoldierTakeDamage( ANIM_CROUCH, 100, 5000, TAKE_DAMAGE_FALLROOF, NOBODY, NOWHERE, 0, TRUE );
this->SoldierTakeDamage( ANIM_CROUCH, 100, 0, 5000, TAKE_DAMAGE_FALLROOF, NOBODY, NOWHERE, 0, TRUE );
fReturnVal = TRUE;
@@ -10104,7 +10201,7 @@ BOOLEAN SOLDIERTYPE::CheckSoldierHitRoof( void )
this->usPendingAnimation = FALLOFF;
// Deduct hitpoints/breath for falling!
this->SoldierTakeDamage( ANIM_CROUCH, 100, 5000, TAKE_DAMAGE_FALLROOF, NOBODY, NOWHERE, 0, TRUE );
this->SoldierTakeDamage( ANIM_CROUCH, 100, 0, 5000, TAKE_DAMAGE_FALLROOF, NOBODY, NOWHERE, 0, TRUE );
fReturnVal = TRUE;
}
@@ -10139,15 +10236,21 @@ void SOLDIERTYPE::BeginSoldierClimbDownRoof( void )
SetUIBusy( this->ubID );
}
this->sTempNewGridNo = NewGridNo( this->sGridNo, (UINT16)DirectionInc(bNewDirection ) );
bNewDirection = gTwoCDirection[ bNewDirection ];
this->ubPendingDirection = bNewDirection;
this->EVENT_InitNewSoldierAnim( JUMPDOWNWALL, 0 , FALSE );
// Flugente: In case an animation is missing (zombies with bodytype of civilians), we TELEPORT instead
if ( IsAnimationValidForBodyType( this, JUMPDOWNWALL ) == FALSE )
{
SetSoldierHeight( 0.0 );
TeleportSoldier( this, this->sTempNewGridNo, TRUE );
EndAIGuysTurn( this);
}
else
this->EVENT_InitNewSoldierAnim( JUMPDOWNWALL, 0 , FALSE );
this->InternalReceivingSoldierCancelServices( FALSE );
this->InternalGivingSoldierCancelServices( FALSE );
@@ -10952,6 +11055,9 @@ void SOLDIERTYPE::ReviveSoldier( void )
this->stats.bLife = this->stats.bLifeMax;
this->bBleeding = 0;
this->bPoisonBleeding = 0;
this->bPoisonLife = 0;
this->bPoisonSum = 0;
this->iHealableInjury = 0; // added by SANDRO
this->ubDesiredHeight = ANIM_STAND;
@@ -11376,7 +11482,7 @@ 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 ) // SANDRO - added check for body type
if ( fMartialArtist && !AreInMeanwhile( ) && !Item[usItem].crowbar && this->ubBodyType == REGMALE && !IsZombie() ) // SANDRO - added check for body type
#endif
{
// Are we in attack mode yet?
@@ -11391,66 +11497,136 @@ void SOLDIERTYPE::EVENT_SoldierBeginPunchAttack( INT32 sGridNo, UINT8 ubDirectio
}
else
{
// Look at stance of target
switch( gAnimControl[ pTSoldier->usAnimState ].ubEndHeight )
// 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 )
{
case ANIM_STAND:
case ANIM_CROUCH:
if ( !Item[usItem].crowbar )
if ( gGameExternalOptions.fZombieExplodingCivs )
{
this->EVENT_InitNewSoldierAnim( PUNCH, 0 , FALSE );
// Solution 1: zombie explodes, killing himself and eventually also killing his target
// Lower hitpoints, to ensure we will die in explosion (otherwise there might be multiple explosions or zombies not dying correctly...)
if ( stats.bLife > 2 )
stats.bLife = 2;
// Explosion of a Jar of RDX Crystals
IgniteExplosion( this->ubID, this->sX, this->sY, (INT16) (gpWorldLevelData[this->sGridNo].sHeight), this->sGridNo, 136, this->pathing.bLevel );
}
else
{
this->EVENT_InitNewSoldierAnim( CROWBAR_ATTACK, 0 , FALSE );
}
// CHECK IF HE CAN SEE US, IF SO CHANGE DIR
if ( pTSoldier->aiData.bOppList[ this->ubID ] == 0 && pTSoldier->bTeam != this->bTeam )
{
// Get direction to target
// IF WE ARE AN ANIMAL, CAR, MONSTER, DONT'T TURN
if ( !( pTSoldier->flags.uiStatusFlags & ( SOLDIER_MONSTER | SOLDIER_ANIMAL | SOLDIER_VEHICLE ) ) )
// Solution 2: Crude simulation of a 'melee' attack (this is a rig-up, a better solution needs to be found).
// do we 'hit'?
if ( Random(100) > 30 )
{
// OK, stop merc....
pTSoldier->EVENT_StopMerc( pTSoldier->sGridNo, pTSoldier->ubDirection );
// Play sound
PlayJA2SampleFromFile( "Sounds\\zombie_swish1.wav", RATE_11025, HIGHVOLUME, 1, MIDDLEPAN );
if ( pTSoldier->bTeam != gbPlayerNum )
INT8 oldlife = pTSoldier->stats.bLife;
INT16 damage = (INT16)(5 + Random(20));
if ( pTSoldier->stats.bLife - damage < 0 )
damage = oldlife;
// We've got a problem if we kill someone outright ithout him collapsing properly...
// FIX: We'll adjust our damage, so if we'd kill someone without collapsing first, we lower our damage, to let him collapse
// After all, this whole thing's a rig up, so there shouldn't be a problem with that
if ( oldlife >= OKLIFE && oldlife <= damage )
damage -= (INT16)((5 + Random(5)));
INT16 breathdamage = (INT16)(500 + Random(1500));
if ( pTSoldier->bBreath - breathdamage < 0 )
breathdamage = pTSoldier->bBreath;
INT16 poisondamage = (INT16) ( sDamage * this->GetPoisonDamagePercentage() / 100 );
// zombies do ~50% poison damage
pTSoldier->SoldierTakeDamage( 0, damage, poisondamage, breathdamage, TAKE_DAMAGE_HANDTOHAND, this->ubID, pTSoldier->sGridNo, 0, TRUE );
if ( pTSoldier->stats.bLife == 0 )
{
CancelAIAction( pTSoldier, TRUE );
// FINISH HIM!
HandleTakeDamageDeath( pTSoldier, oldlife, TAKE_DAMAGE_BLOODLOSS );
}
else if ( pTSoldier->stats.bLife < OKLIFE && !pTSoldier->bCollapsed )
{
// let the target collapse...
SoldierCollapse(pTSoldier);
}
ubTDirection = (UINT8)GetDirectionFromGridNo( this->sGridNo, pTSoldier );
SendSoldierSetDesiredDirectionEvent( pTSoldier, ubTDirection );
}
}
break;
case ANIM_PRONE:
// CHECK OUR STANCE
// ATE: Added this for CIV body types 'cause of elliot
if ( !IS_MERC_BODY_TYPE( this ) )
{
this->EVENT_InitNewSoldierAnim( PUNCH, 0 , FALSE );
}
else
{
if ( gAnimControl[ this->usAnimState ].ubEndHeight != ANIM_CROUCH )
{
// SET DESIRED STANCE AND SET PENDING ANIMATION
SendChangeSoldierStanceEvent( this, ANIM_CROUCH );
this->usPendingAnimation = PUNCH_LOW;
}
else
{
// USE crouched one
// NEED TO CHANGE STANCE IF NOT CROUCHD!
this->EVENT_InitNewSoldierAnim( PUNCH_LOW, 0 , FALSE );
// Play sound
PlayJA2SampleFromFile( "Sounds\\zombie_swish2.wav", RATE_11025, HIGHVOLUME, 1, MIDDLEPAN );
}
// zombie is done doing harm...
EndAIGuysTurn( this);
}
// ensure that we are running on our way to the next enemy
this->EVENT_InitNewSoldierAnim( RUNNING, 0 , FALSE );
}
else
{
// Look at stance of target
switch( gAnimControl[ pTSoldier->usAnimState ].ubEndHeight )
{
case ANIM_STAND:
case ANIM_CROUCH:
if ( !Item[usItem].crowbar )
{
this->EVENT_InitNewSoldierAnim( PUNCH, 0 , FALSE );
}
else
{
this->EVENT_InitNewSoldierAnim( CROWBAR_ATTACK, 0 , FALSE );
}
// CHECK IF HE CAN SEE US, IF SO CHANGE DIR
if ( pTSoldier->aiData.bOppList[ this->ubID ] == 0 && pTSoldier->bTeam != this->bTeam )
{
// Get direction to target
// IF WE ARE AN ANIMAL, CAR, MONSTER, DONT'T TURN
if ( !( pTSoldier->flags.uiStatusFlags & ( SOLDIER_MONSTER | SOLDIER_ANIMAL | SOLDIER_VEHICLE ) ) )
{
// OK, stop merc....
pTSoldier->EVENT_StopMerc( pTSoldier->sGridNo, pTSoldier->ubDirection );
if ( pTSoldier->bTeam != gbPlayerNum )
{
CancelAIAction( pTSoldier, TRUE );
}
ubTDirection = (UINT8)GetDirectionFromGridNo( this->sGridNo, pTSoldier );
SendSoldierSetDesiredDirectionEvent( pTSoldier, ubTDirection );
}
}
break;
case ANIM_PRONE:
// CHECK OUR STANCE
// ATE: Added this for CIV body types 'cause of elliot
if ( !IS_MERC_BODY_TYPE( this ) )
{
this->EVENT_InitNewSoldierAnim( PUNCH, 0 , FALSE );
}
else
{
if ( gAnimControl[ this->usAnimState ].ubEndHeight != ANIM_CROUCH )
{
// SET DESIRED STANCE AND SET PENDING ANIMATION
SendChangeSoldierStanceEvent( this, ANIM_CROUCH );
this->usPendingAnimation = PUNCH_LOW;
}
else
{
// USE crouched one
// NEED TO CHANGE STANCE IF NOT CROUCHD!
this->EVENT_InitNewSoldierAnim( PUNCH_LOW, 0 , FALSE );
}
}
break;
}
break;
}
}
@@ -11682,7 +11858,7 @@ void SOLDIERTYPE::EVENT_SoldierEnterVehicle( INT32 sGridNo, UINT8 ubDirection )
UINT32 SOLDIERTYPE::SoldierDressWound( SOLDIERTYPE *pVictim, INT16 sKitPts, INT16 sStatus )
{
UINT32 uiDressSkill, uiPossible, uiActual, uiMedcost, uiDeficiency, uiAvailAPs, uiUsedAPs;
UINT8 ubBelowOKlife, ubPtsLeft = 0;
UINT8 ubBelowOKlife = 0, ubPtsLeft = 0;
BOOLEAN fRanOut = FALSE;
BOOLEAN fOnSurgery = FALSE;
INT8 bInitialBleeding;
@@ -11860,6 +12036,10 @@ UINT32 SOLDIERTYPE::SoldierDressWound( SOLDIERTYPE *pVictim, INT16 sKitPts, INT1
// use up appropriate # of actual healing points
ubPtsLeft -= (2 * ubBelowOKlife);
// raise bPoisonLife, reduce bPoisonBleeding
pVictim->bPoisonLife = min(pVictim->bPoisonLife + ubBelowOKlife, pVictim->bPoisonSum);
pVictim->bPoisonBleeding = max(0, pVictim->bPoisonBleeding - ubBelowOKlife);
}
else
{
@@ -11875,12 +12055,17 @@ UINT32 SOLDIERTYPE::SoldierDressWound( SOLDIERTYPE *pVictim, INT16 sKitPts, INT1
pVictim->bBleeding -= ( ubPtsLeft / 2);
ubPtsLeft = ubPtsLeft % 2; // if ptsLeft was odd, ptsLeft = 1
// raise bPoisonLife, reduce bPoisonBleeding
pVictim->bPoisonLife = min(pVictim->bPoisonLife + ( ubPtsLeft / 2), pVictim->bPoisonSum);
pVictim->bPoisonBleeding = max(0, pVictim->bPoisonBleeding - ( ubPtsLeft / 2));
}
// this should never happen any more, but make sure bleeding not negative
if (pVictim->bBleeding < 0)
{
pVictim->bBleeding = 0;
pVictim->bPoisonBleeding = 0;
}
// if this healing brought the patient out of the worst of it, cancel dying
@@ -11970,11 +12155,13 @@ UINT32 SOLDIERTYPE::SoldierDressWound( SOLDIERTYPE *pVictim, INT16 sKitPts, INT1
if (pVictim->bBleeding >= (usLifeReturned/100))
{
pVictim->bBleeding -= (usLifeReturned/100);
pVictim->bPoisonBleeding = max(0, pVictim->bPoisonBleeding - (usLifeReturned/100) );
uiMedcost += (usLifeReturned / 200); // add medkit points cost for unbandaged part
}
else
{
pVictim->bBleeding = 0;
pVictim->bPoisonBleeding = 0;
uiMedcost += max( 0, (((usLifeReturned/100) - pVictim->bBleeding) / 2)); // add medkit points cost for unbandaged part
}
}
@@ -11983,6 +12170,7 @@ UINT32 SOLDIERTYPE::SoldierDressWound( SOLDIERTYPE *pVictim, INT16 sKitPts, INT1
pVictim->stats.bLife = pVictim->stats.bLifeMax;
pVictim->iHealableInjury = 0;
pVictim->bBleeding = 0;
pVictim->bPoisonBleeding = 0;
}
// Reduce max breath based on life returned
if ( (pVictim->bBreathMax - (((usLifeReturned/100) * gSkillTraitValues.usDOSurgeryMaxBreathLoss )/ 100)) <= BREATHMAX_ABSOLUTE_MINIMUM )
@@ -12010,10 +12198,12 @@ UINT32 SOLDIERTYPE::SoldierDressWound( SOLDIERTYPE *pVictim, INT16 sKitPts, INT1
{
ubPtsLeft -= pVictim->bBleeding;
pVictim->bBleeding = 0;
pVictim->bPoisonBleeding = 0;
}
else // bandage what we can
{
pVictim->bBleeding -= ubPtsLeft;
pVictim->bPoisonBleeding = max(0, pVictim->bPoisonBleeding - ubPtsLeft);
ubPtsLeft = 0;
}
@@ -13189,6 +13379,8 @@ INT32 SOLDIERTYPE::GetDamageResistance(BOOLEAN fAutoResolve, BOOLEAN fCalcBreath
resistance += gGameExternalOptions.sEnemyRegularDamageResistance;
else if (this->ubSoldierClass == SOLDIER_CLASS_ELITE && gGameExternalOptions.sEnemyEliteDamageResistance != 0)
resistance += gGameExternalOptions.sEnemyEliteDamageResistance;
else if (IsZombie())
resistance += gGameExternalOptions.sEnemyZombieDamageResistance;
}
//////////////////////////////////////////////////////////////////////////////////////
@@ -13236,6 +13428,74 @@ INT32 SOLDIERTYPE::GetDamageResistance(BOOLEAN fAutoResolve, BOOLEAN fCalcBreath
return( resistance );
}
INT16 SOLDIERTYPE::GetSoldierCriticalDamageBonus( void )
{
INT16 val = 0;
return val;
}
BOOLEAN SOLDIERTYPE::IsZombie( void )
{
return( ubSoldierClass == SOLDIER_CLASS_ZOMBIE );
}
INT16 SOLDIERTYPE::GetPoisonResistance( void )
{
// Flugente: resistance can per definition only be between -100 and 100 (at least that's my definition)
INT16 val = bPoisonResistance;
// without WH40K, there are no modifiers
val = max(-100, val);
val = min(100, val);
return( val );
}
INT16 SOLDIERTYPE::GetPoisonAbsorption( void )
{
// Flugente: absorption can per definition only be >= 0 (at least that's my definition)
INT16 val = bPoisonAbsorption;
val = max(0, val);
return( val );
}
INT16 SOLDIERTYPE::GetPoisonDamagePercentage( void )
{
// Flugente: this percentage has to be between 0% and 100%
INT16 val = 0;
// zombies poison damage percentage is externalised
if ( IsZombie() )
val += gGameExternalOptions.sZombiePoisonDamagePercentage;
if ( this->usAttackingWeapon )
{
val += Item[this->usAttackingWeapon].bPoisonPercentage;
if ( Item[this->usAttackingWeapon].usItemClass == IC_GUN )
{
// check for modificators (attachments, poisoned ammunition)
// check for poisoned ammunition
UINT8 ammotype = this->inv[ this->ubAttackingHand ][0]->data.gun.ubGunAmmoType;
val += AmmoTypes[ammotype].poisonPercentage;
// check for attachments with a bonus to poison (currently, none exist)
}
}
val = max(0, val);
val = min(100, val);
return( val );
}
INT32 CheckBleeding( SOLDIERTYPE *pSoldier )
{
INT8 bBandaged; //,savedOurTurn;
@@ -13244,94 +13504,116 @@ INT32 CheckBleeding( SOLDIERTYPE *pSoldier )
if ( pSoldier->stats.bLife != 0 )
{
// if merc is hurt beyond the minimum required to bleed, or he's dying
if ( ( pSoldier->bBleeding > MIN_BLEEDING_THRESHOLD) || pSoldier->stats.bLife < OKLIFE )
// Flugente: also allow bleeding if we would regenerate health through it, which happens when we have enough absorption and are poisoned enough (only guaranteed if fully poisoned)
if ( ( ( pSoldier->bBleeding > MIN_BLEEDING_THRESHOLD) || pSoldier->stats.bLife < OKLIFE ) || ( pSoldier->bPoisonSum == pSoldier->stats.bLifeMax && pSoldier->GetPoisonAbsorption() >= 200 ) )
{
// if he's NOT in the process of being bandaged or DOCTORed
if ( ( pSoldier->ubServiceCount == 0 ) && ( AnyDoctorWhoCanHealThisPatient( pSoldier, HEALABLE_EVER ) == NULL ) )
{
// may drop blood whether or not any bleeding takes place this turn
if ( pSoldier->bTilesMoved < 1 )
{
iBlood = ( ( pSoldier->bBleeding - MIN_BLEEDING_THRESHOLD ) / BLOODDIVISOR ); // + pSoldier->dying;
if ( iBlood > MAXBLOODQUANTITY )
{
iBlood = MAXBLOODQUANTITY;
}
}
{
iBlood = ( ( pSoldier->bBleeding - MIN_BLEEDING_THRESHOLD ) / BLOODDIVISOR ); // + pSoldier->dying;
if ( iBlood > MAXBLOODQUANTITY )
{
iBlood = MAXBLOODQUANTITY;
}
}
else
{
iBlood = NOBLOOD;
}
{
iBlood = NOBLOOD;
}
// Are we in a different mode?
if ( !(gTacticalStatus.uiFlags & TURNBASED ) || !(gTacticalStatus.uiFlags & INCOMBAT ) )
{
pSoldier->dNextBleed -= (FLOAT)RT_NEXT_BLEED_MODIFIER;
}
{
pSoldier->dNextBleed -= (FLOAT)RT_NEXT_BLEED_MODIFIER;
}
else
{
// Do a single step descrease
pSoldier->dNextBleed--;
}
{
// Do a single step descrease
pSoldier->dNextBleed--;
}
// if it's time to lose some blood
if ( pSoldier->dNextBleed <= 0)
{
// first, calculate if soldier is bandaged
bBandaged = pSoldier->stats.bLifeMax - pSoldier->bBleeding - pSoldier->stats.bLife;
{
// first, calculate if soldier is bandaged
bBandaged = pSoldier->stats.bLifeMax - pSoldier->bBleeding - pSoldier->stats.bLife;
// as long as he's bandaged and not "dying"
if ( bBandaged && pSoldier->stats.bLife >= OKLIFE )
{
// just bleeding through existing bandages
pSoldier->bBleeding++;
SoldierBleed( pSoldier, TRUE );
}
else // soldier is either not bandaged at all or is dying
{
if ( pSoldier->stats.bLife < OKLIFE ) // if he's dying
// as long as he's bandaged and not "dying"
if ( bBandaged && pSoldier->stats.bLife >= OKLIFE )
{
// if he's conscious, and he hasn't already, say his "dying quote"
if ( ( pSoldier->stats.bLife >= CONSCIOUSNESS ) && !pSoldier->flags.fDyingComment )
// just bleeding through existing bandages
pSoldier->bBleeding++;
SoldierBleed( pSoldier, TRUE, TRUE );
}
else // soldier is either not bandaged at all or is dying
{
if ( pSoldier->stats.bLife < OKLIFE ) // if he's dying
{
TacticalCharacterDialogue( pSoldier, QUOTE_SERIOUSLY_WOUNDED );
// if he's conscious, and he hasn't already, say his "dying quote"
if ( ( pSoldier->stats.bLife >= CONSCIOUSNESS ) && !pSoldier->flags.fDyingComment )
{
TacticalCharacterDialogue( pSoldier, QUOTE_SERIOUSLY_WOUNDED );
pSoldier->flags.fDyingComment = TRUE;
}
pSoldier->flags.fDyingComment = TRUE;
}
// can't permit lifemax to ever bleed beneath OKLIFE, or that
// soldier might as well be dead!
if (pSoldier->stats.bLifeMax >= OKLIFE)
{
// bleeding while "dying" costs a PERMANENT point of life each time!
pSoldier->stats.bLifeMax--;
pSoldier->bBleeding--;
if ( pSoldier->iHealableInjury >= 100) // added check for insta-healable injury - SANDRO
pSoldier->iHealableInjury -= 100;
}
}
}
// can't permit lifemax to ever bleed beneath OKLIFE, or that
// soldier might as well be dead!
if (pSoldier->stats.bLifeMax >= OKLIFE)
{
// Flugente: reduce PERMANENT points of life only if through 'normal' bleeding, not by poisoning
// problem is that this function applies every bleeding cycle, while loosing points through natural restoration (too much poison in body) only happens every hour.
// so one might lose 1pt of life through poisoning at 8:00, and then lose 30 points of life PERMANTENLY in the following hour without dying
// We bypass this by only allowing PERMANTENT lifeloss if really bleeding
if ( pSoldier->bBleeding )
{
// bleeding while "dying" costs a PERMANENT point of life each time!
pSoldier->stats.bLifeMax--;
pSoldier->bBleeding = max(0, pSoldier->bBleeding - 1);
// either way, a point of life (health) is lost because of bleeding
// This will also update the life bar
// the lost point might be poisoned
pSoldier->bPoisonSum = max(0, pSoldier->bPoisonSum - 1);
SoldierBleed( pSoldier, FALSE );
// also adjust poisoned bleeding
pSoldier->bPoisonBleeding = max(0, pSoldier->bPoisonBleeding - 1);
if ( pSoldier->iHealableInjury >= 100) // added check for insta-healable injury - SANDRO
pSoldier->iHealableInjury -= 100;
}
}
}
}
// either way, a point of life (health) is lost because of bleeding
// Flugente: not true anymore! We might be fully bandaged, not bleeding, but still receive poison damage that will lower our life. So check if we're bleeding!
if ( pSoldier->bBleeding )
{
// This will also update the life bar
SoldierBleed( pSoldier, FALSE, TRUE );
}
else
{
// just to update everything, like going unconscious or dying
pSoldier->SoldierTakeDamage( ANIM_CROUCH, 0, 0, 0, TAKE_DAMAGE_BLOODLOSS, NOBODY, NOWHERE, 0, TRUE );
}
// if he's not dying (which includes him saying the dying quote just
// now), and he hasn't warned us that he's bleeding yet, he does so
// Also, not if they are being bandaged....
if ( ( pSoldier->stats.bLife >= OKLIFE ) && !pSoldier->flags.fDyingComment && !pSoldier->flags.fWarnedAboutBleeding && !gTacticalStatus.fAutoBandageMode && pSoldier->ubServiceCount == 0 )
{
// if he's not dying (which includes him saying the dying quote just
// now), and he hasn't warned us that he's bleeding yet, he does so
// Also, not if they are being bandaged....
if ( ( pSoldier->stats.bLife >= OKLIFE ) && !pSoldier->flags.fDyingComment && !pSoldier->flags.fWarnedAboutBleeding && !gTacticalStatus.fAutoBandageMode && pSoldier->ubServiceCount == 0 )
{
TacticalCharacterDialogue( pSoldier, QUOTE_STARTING_TO_BLEED );
// "starting to bleed" quote
pSoldier->flags.fWarnedAboutBleeding = TRUE;
}
pSoldier->dNextBleed = CalcSoldierNextBleed( pSoldier );
}
pSoldier->dNextBleed = CalcSoldierNextBleed( pSoldier );
}
}
}
@@ -13340,10 +13622,8 @@ INT32 CheckBleeding( SOLDIERTYPE *pSoldier )
}
void SoldierBleed( SOLDIERTYPE *pSoldier, BOOLEAN fBandagedBleed )
void SoldierBleed( SOLDIERTYPE *pSoldier, BOOLEAN fBandagedBleed, BOOLEAN fAllowPoisoning )
{
INT8 bOldLife;
// OK, here make some stuff happen for bleeding
// A banaged bleed does not show damage taken , just through existing bandages
@@ -13360,21 +13640,30 @@ void SoldierBleed( SOLDIERTYPE *pSoldier, BOOLEAN fBandagedBleed )
SetInfoChar( pSoldier->ubID );
}
}
// if poisoning is allowed, if we are poisoned and we can be sure that we are really bleeding (safety reasons), there is a chance that the poisoning spreads
// this simply means that the new Bleeding point will also be a poisoned bleeding point
INT16 poisondamage = 0;
if ( fAllowPoisoning && pSoldier->bPoisonSum > 0 && pSoldier->bBleeding )
{
INT8 bleedingpercentagepoison = (INT8) (100 * pSoldier->bPoisonSum / pSoldier->stats.bLifeMax);
bOldLife = pSoldier->stats.bLife;
if ( (INT8) Random(100) < bleedingpercentagepoison )
poisondamage = 1;
}
// If we are already dead, don't show damage!
if ( !fBandagedBleed )
{
// SANDRO - if the soldier is bleeding out, consider this damage as done by the last attacker
if ( pSoldier->ubAttackerID != NOBODY )
pSoldier->SoldierTakeDamage( ANIM_CROUCH, 1, 100, TAKE_DAMAGE_BLOODLOSS, pSoldier->ubAttackerID, NOWHERE, 0, TRUE );
pSoldier->SoldierTakeDamage( ANIM_CROUCH, 1, poisondamage, 100, TAKE_DAMAGE_BLOODLOSS, pSoldier->ubAttackerID, NOWHERE, 0, TRUE );
else if ( pSoldier->ubPreviousAttackerID != NOBODY )
pSoldier->SoldierTakeDamage( ANIM_CROUCH, 1, 100, TAKE_DAMAGE_BLOODLOSS, pSoldier->ubPreviousAttackerID, NOWHERE, 0, TRUE );
pSoldier->SoldierTakeDamage( ANIM_CROUCH, 1, poisondamage, 100, TAKE_DAMAGE_BLOODLOSS, pSoldier->ubPreviousAttackerID, NOWHERE, 0, TRUE );
else if ( pSoldier->ubNextToPreviousAttackerID != NOBODY )
pSoldier->SoldierTakeDamage( ANIM_CROUCH, 1, 100, TAKE_DAMAGE_BLOODLOSS, pSoldier->ubNextToPreviousAttackerID, NOWHERE, 0, TRUE );
pSoldier->SoldierTakeDamage( ANIM_CROUCH, 1, poisondamage, 100, TAKE_DAMAGE_BLOODLOSS, pSoldier->ubNextToPreviousAttackerID, NOWHERE, 0, TRUE );
else
pSoldier->SoldierTakeDamage( ANIM_CROUCH, 1, 100, TAKE_DAMAGE_BLOODLOSS, NOBODY, NOWHERE, 0, TRUE );
pSoldier->SoldierTakeDamage( ANIM_CROUCH, 1, poisondamage, 100, TAKE_DAMAGE_BLOODLOSS, NOBODY, NOWHERE, 0, TRUE );
}
}
+32 -5
View File
@@ -309,6 +309,7 @@ enum
SOLDIER_CLASS_ELITE_MILITIA,
SOLDIER_CLASS_CREATURE,
SOLDIER_CLASS_MINER,
SOLDIER_CLASS_ZOMBIE,
};
#define SOLDIER_CLASS_ENEMY( bSoldierClass ) ( ( bSoldierClass >= SOLDIER_CLASS_ADMINISTRATOR ) && ( bSoldierClass <= SOLDIER_CLASS_ARMY ) )
@@ -1143,6 +1144,21 @@ public:
// I don't know if this is a good idea at all...
//INT16 filler;
// Flugente: Is this the correct position?
INT8 bScopeMode;
///////////////////////////////////////////////////////
// Flugente Zombies: Added variables for the poison system
INT8 bPoisonBleeding; // The number of bleeding points that are also poison points
//INT8 bPoisonBandaged; // The number of bandaged lifepoints that are also poison points
INT8 bPoisonLife; // The number of Lifepoints that are also poison points
INT8 bPoisonSum; // The sum of poison points;
INT16 bPoisonResistance; // poison resistance reduces the amount of poison damage received. It is applied before poison absorption
INT16 bPoisonAbsorption; // for x points of poison damage received, you gain x * (bPoisonAbsorption / 100) poison life points
///////////////////////////////////////////////////////
#ifdef JA2UB
//ja25
BOOLEAN fIgnoreGetupFromCollapseCheck;
@@ -1151,10 +1167,7 @@ public:
UINT8 ubPercentDamageInflictedByTeam[NUM_ASSIST_SLOTS]; //The percent of damage inflicted by the player team. Each element corresponds to the Soldier ID. Each element contains the percent damage inflicted by that merc
#endif
// Flugente: Is this the correct position?
INT8 bScopeMode;
char endOfPOD; // marker for end of POD (plain old data)
// Note: Place all non-POD items at the end (after endOfPOD)
@@ -1229,7 +1242,8 @@ public:
void ChangeSoldierStance( UINT8 ubDesiredStance );
void StopSoldier( void );
void ReviveSoldier( void );
UINT8 SoldierTakeDamage( INT8 bHeight, INT16 sLifeDeduct, INT16 sBreathDeduct, UINT8 ubReason, UINT8 ubAttacker, INT32 sSourceGrid, INT16 sSubsequent, BOOLEAN fShowDamage );
// Flugente: added poison damage, which should be smaller or equal than sLifeDeduct
UINT8 SoldierTakeDamage( INT8 bHeight, INT16 sLifeDeduct, INT16 sPoisonAdd, INT16 sBreathDeduct, UINT8 ubReason, UINT8 ubAttacker, INT32 sSourceGrid, INT16 sSubsequent, BOOLEAN fShowDamage );
// Palette functions for soldiers
@@ -1330,6 +1344,19 @@ public:
// returns damage resistance in percent
INT32 GetDamageResistance( BOOLEAN fAutoResolve = FALSE, BOOLEAN fCalcBreathLoss = FALSE);
INT16 GetSoldierCriticalDamageBonus( void ); // Flugente: determines critical damage bonus depending on class, skill, etc.
// Flugente: Zombies
BOOLEAN IsZombie( void );
// 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
INT16 GetPoisonResistance( void );
INT16 GetPoisonAbsorption( void );
// returns the poison percentage of the damage we will be doing with the weapon currently in our hand
INT16 GetPoisonDamagePercentage( void );
//////////////////////////////////////////////////////////////////////////////
}; // SOLDIERTYPE;
#define SIZEOF_SOLDIERTYPE_POD offsetof( SOLDIERTYPE, endOfPOD )
+51 -5
View File
@@ -341,6 +341,7 @@ SOLDIERCREATE_STRUCT::SOLDIERCREATE_STRUCT() {
SOLDIERCREATE_STRUCT::SOLDIERCREATE_STRUCT(const SOLDIERCREATE_STRUCT& src) {
memcpy(this, &src, SIZEOF_SOLDIERCREATE_STRUCT_POD);
this->Inv = src.Inv;
this->fNoGenNewPalette = src.fNoGenNewPalette;
}
// Assignment operator
@@ -349,6 +350,7 @@ SOLDIERCREATE_STRUCT& SOLDIERCREATE_STRUCT::operator=(const SOLDIERCREATE_STRUCT
if (this != &src) {
memcpy(this, &src, SIZEOF_SOLDIERCREATE_STRUCT_POD);
this->Inv = src.Inv;
this->fNoGenNewPalette = src.fNoGenNewPalette;
}
return *this;
}
@@ -1727,6 +1729,10 @@ BOOLEAN TacticalCopySoldierFromCreateStruct( SOLDIERTYPE *pSoldier, SOLDIERCREAT
{
swprintf( pSoldier->name, gzLateLocalizedString[ 36 ] );
}
else if ( pSoldier->IsZombie() )
{
swprintf( pSoldier->name, TacticalStr[ ZOMBIE_TEAM_MERC_NAME ] );
}
else
{
swprintf( pSoldier->name, TacticalStr[ CREATURE_TEAM_MERC_NAME ] ); break;
@@ -1735,7 +1741,8 @@ BOOLEAN TacticalCopySoldierFromCreateStruct( SOLDIERTYPE *pSoldier, SOLDIERCREAT
}
//Generate colors for soldier based on the body type.
GeneratePaletteForSoldier( pSoldier, pCreateStruct->ubSoldierClass );
if ( !pCreateStruct->fNoGenNewPalette )
GeneratePaletteForSoldier( pSoldier, pCreateStruct->ubSoldierClass );
// Copy item info over
pSoldier->inv = pCreateStruct->Inv;
@@ -2170,6 +2177,7 @@ void CreateDetailedPlacementGivenBasicPlacementInfo( SOLDIERCREATE_STRUCT *pp, B
switch( ubSoldierClass )
{
case SOLDIER_CLASS_ADMINISTRATOR:
case SOLDIER_CLASS_ZOMBIE:
pp->bExpLevel = (INT8) 2 + bExpLevelModifier;
break;
case SOLDIER_CLASS_ARMY:
@@ -2287,7 +2295,7 @@ 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"));
if( !bp->fDetailedPlacement && ubSoldierClass != SOLDIER_CLASS_NONE && ubSoldierClass != SOLDIER_CLASS_CREATURE && ubSoldierClass != SOLDIER_CLASS_MINER )
if( !bp->fDetailedPlacement && ubSoldierClass != SOLDIER_CLASS_NONE && ubSoldierClass != SOLDIER_CLASS_CREATURE && ubSoldierClass != SOLDIER_CLASS_MINER && ubSoldierClass != SOLDIER_CLASS_ZOMBIE )
GenerateRandomEquipment( pp, ubSoldierClass, bp->bRelativeEquipmentLevel);
DecideToAssignSniperOrders(pp);
@@ -2455,7 +2463,7 @@ void CreateDetailedPlacementGivenStaticDetailedPlacementAndBasicPlacementInfo(
//{
// ReplaceExtendedGuns( pp, bp->ubSoldierClass );
//}
if( bp->ubSoldierClass != SOLDIER_CLASS_NONE && bp->ubSoldierClass != SOLDIER_CLASS_CREATURE && bp->ubSoldierClass != SOLDIER_CLASS_MINER )
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);
DecideToAssignSniperOrders(pp);
@@ -2650,7 +2658,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 )
if( ubSoldierClass != SOLDIER_CLASS_CREATURE && ubSoldierClass != SOLDIER_CLASS_ZOMBIE )
{ //use the enemy team
iStart = gTacticalStatus.Team[ ENEMY_TEAM ].bFirstID;
iEnd = gTacticalStatus.Team[ ENEMY_TEAM ].bLastID;
@@ -2660,7 +2668,7 @@ SOLDIERTYPE* ReserveTacticalSoldierForAutoresolve( UINT8 ubSoldierClass )
iStart = gTacticalStatus.Team[ CREATURE_TEAM ].bFirstID;
iEnd = gTacticalStatus.Team[ CREATURE_TEAM ].bLastID;
}
for( i = iStart; i <= iEnd; i++ )
for( i = iStart; i <= iEnd; ++i )
{
if( MercPtrs[ i ]->bActive && MercPtrs[ i ]->bInSector && MercPtrs[ i ]->stats.bLife && !TileIsOutOfBounds(MercPtrs[ i ]->sGridNo))
{
@@ -2792,6 +2800,40 @@ 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 )
{
pSoldier = ReserveTacticalSoldierForAutoresolve( SOLDIER_CLASS_ZOMBIE );
if( 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 );
}
SOLDIERTYPE* ReserveTacticalMilitiaSoldierForAutoresolve( UINT8 ubSoldierClass )
{
INT32 i, iStart, iEnd;
@@ -4195,6 +4237,8 @@ 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
else if (ubSolClass == SOLDIER_CLASS_ZOMBIE )
iChance = 100; // 100% chance
if( foundHtH ) // if found brass knuckless, increase the chance (doesn't happen often)
iChance += 35;
@@ -4238,6 +4282,8 @@ 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
else if (ubSolClass == SOLDIER_CLASS_ZOMBIE )
iChance = 100; // 100% chance
// modify the chance by preset ini setting
if( gGameExternalOptions.bAssignedTraitsRarity != 0 )
+4
View File
@@ -305,6 +305,9 @@ public:
INT8 bUseGivenVehicleID;
BOOLEAN fHasKeys;
// Flugente: do not generate new palette for soldier (for soldiers that are created from existing soldiers/corpses, like doppelgangers and zombies)
BOOLEAN fNoGenNewPalette;
//
// New and OO stuff goes after here. Above this point any changes will goof up reading from files.
//
@@ -420,6 +423,7 @@ SOLDIERTYPE* TacticalCreateSoldier( SOLDIERCREATE_STRUCT *pCreateStruct, UINT8 *
SOLDIERTYPE* TacticalCreateAdministrator();
SOLDIERTYPE* TacticalCreateEliteEnemy();
SOLDIERTYPE* TacticalCreateArmyTroop();
SOLDIERTYPE* TacticalCreateZombie(); // Flugente Zombies
SOLDIERTYPE* TacticalCreateMilitia( UINT8 ubMilitiaClass );
SOLDIERTYPE* TacticalCreateCreature( INT8 bCreatureBodyType );
+1
View File
@@ -2106,6 +2106,7 @@ SOLDIERTYPE * SwapLarrysProfiles( SOLDIERTYPE * pSoldier )
pNewProfile->records.usKillsRegulars = gMercProfiles[ ubSrcProfile ].records.usKillsRegulars;
pNewProfile->records.usKillsAdmins = gMercProfiles[ ubSrcProfile ].records.usKillsAdmins;
pNewProfile->records.usKillsCreatures = gMercProfiles[ ubSrcProfile ].records.usKillsCreatures;
pNewProfile->records.usKillsZombies = gMercProfiles[ ubSrcProfile ].records.usKillsZombies;
pNewProfile->records.usKillsTanks = gMercProfiles[ ubSrcProfile ].records.usKillsTanks;
pNewProfile->records.usKillsOthers = gMercProfiles[ ubSrcProfile ].records.usKillsOthers;
pNewProfile->records.usAssistsMercs = gMercProfiles[ ubSrcProfile ].records.usAssistsMercs;
+5
View File
@@ -273,6 +273,11 @@ void HandleTacticalEndTurn( )
// Flugente FTW 1: Cool down all items not in a soldier's inventory
CoolDownWorldItems( FALSE );
// Flugente: raise zombies if in gamescreen and option set
if ( guiCurrentScreen == GAME_SCREEN )
{
RaiseZombies();
}
}
+4
View File
@@ -120,6 +120,9 @@
#include "connect.h"
#include "fresh_header.h"
#include "IMP Skill Trait.h" // added by Flugente
//forward declarations of common classes to eliminate includes
class OBJECTTYPE;
class SOLDIERTYPE;
@@ -4316,6 +4319,7 @@ void GetKeyboardInput( UINT32 *puiNewEvent )
// Get life back
pSoldier->stats.bLife = pSoldier->stats.bLifeMax;
pSoldier->bBleeding = 0;
pSoldier->bPoisonBleeding = 0;
// SANDRO - erase insta-healable injury
pSoldier->iHealableInjury = 0;
+2 -2
View File
@@ -1330,7 +1330,7 @@ BOOLEAN InjurePersonInVehicle( INT32 iId, SOLDIERTYPE *pSoldier, UINT8 ubPointsO
}
// otherwise hurt them
pSoldier->SoldierTakeDamage( 0, ubPointsOfDmg, ubPointsOfDmg, TAKE_DAMAGE_GUNFIRE, NOBODY, NOWHERE, 0, TRUE );
pSoldier->SoldierTakeDamage( 0, ubPointsOfDmg, 0, ubPointsOfDmg, TAKE_DAMAGE_GUNFIRE, NOBODY, NOWHERE, 0, TRUE );
pSoldier->HandleSoldierTakeDamageFeedback( );
@@ -1359,7 +1359,7 @@ BOOLEAN KillPersonInVehicle( INT32 iId, SOLDIERTYPE *pSoldier )
}
// otherwise hurt them
pSoldier->SoldierTakeDamage( 0, 100, 100, TAKE_DAMAGE_BLOODLOSS, NOBODY, NOWHERE, 0, TRUE );
pSoldier->SoldierTakeDamage( 0, 100, 0, 100, TAKE_DAMAGE_BLOODLOSS, NOBODY, NOWHERE, 0, TRUE );
return( TRUE );
}
+64 -13
View File
@@ -334,9 +334,6 @@ bool gbForceWeaponNotReady = false;
bool gbForceWeaponReady = false;
// Flugente: define for maximum temperature
#define OVERHEATING_MAX_TEMPERATURE 60000.0
enum
{
WEAPON_ELEMENT_NONE = 0,
@@ -1328,6 +1325,22 @@ BOOLEAN OKFireWeapon( SOLDIERTYPE *pSoldier )
}
// Flugente FTW 1: Get percentage: temperature/damagethreshold
FLOAT GetGunOverheatDamagePercentage( FLOAT usTemperature, UINT16 usIndx )
{
FLOAT damagethreshold = Weapon[Item[ usIndx ].ubClassIndex].usOverheatingDamageThreshold;
return usTemperature/ damagethreshold ;
}
// Flugente FTW 1: Get percentage: temperature/jamthreshold
FLOAT GetGunOverheatJamPercentage( FLOAT usTemperature, UINT16 usIndx )
{
FLOAT jamthreshold = Weapon[Item[ usIndx ].ubClassIndex].usOverheatingJamThreshold;
return usTemperature/ jamthreshold ;
}
BOOLEAN FireWeapon( SOLDIERTYPE *pSoldier , INT32 sTargetGridNo )
{
// ignore passed in target gridno for now
@@ -5187,6 +5200,7 @@ UINT32 CalcNewChanceToHitGun(SOLDIERTYPE *pSoldier, INT32 sGridNo, INT16 ubAimTi
// AGILITY OR EXPERIENCE
FLOAT iTempPenalty = (FLOAT)__max((pTarget->stats.bExpLevel*10), pTarget->stats.bAgility);
iBaseModifier += (iTempPenalty * gGameCTHConstants.BASE_AGILE_TARGET) / 100;
}
@@ -6235,19 +6249,19 @@ UINT32 CalcChanceToHitGun(SOLDIERTYPE *pSoldier, INT32 sGridNo, INT16 ubAimTime,
if ( TANK( pSoldier ) && iRange < MIN_TANK_RANGE )
{
// 13% penalty per tile closer than min range
iChance -= 13 * ( ( MIN_TANK_RANGE - iRange ) / CELL_X_SIZE );
iChance -= (INT32)(13 * ( ( MIN_TANK_RANGE - iRange ) / CELL_X_SIZE ));
}
else
{
// at anything other than point-blank range
if (iRange > POINT_BLANK_RANGE + 10 * (AIM_PENALTY_TARGET_CROUCHED / 3) )
{
iChance -= AIM_PENALTY_TARGET_CROUCHED;
iChance -= (INT32)(AIM_PENALTY_TARGET_CROUCHED);
}
else if (iRange > POINT_BLANK_RANGE)
{
// at close range give same bonus as prone, up to maximum of AIM_PENALTY_TARGET_CROUCHED
iChance -= 3 * ((iRange - POINT_BLANK_RANGE) / CELL_X_SIZE); // penalty -3%/tile
iChance -= (INT32)(3 * ((iRange - POINT_BLANK_RANGE) / CELL_X_SIZE)); // penalty -3%/tile
}
}
break;
@@ -6255,7 +6269,7 @@ UINT32 CalcChanceToHitGun(SOLDIERTYPE *pSoldier, INT32 sGridNo, INT16 ubAimTime,
if ( TANK( pSoldier ) && iRange < MIN_TANK_RANGE )
{
// 25% penalty per tile closer than min range
iChance -= 25 * ( ( MIN_TANK_RANGE - iRange ) / CELL_X_SIZE );
iChance -= (INT32)(25 * ( ( MIN_TANK_RANGE - iRange ) / CELL_X_SIZE ) * iPenalty);
}
else
{
@@ -6286,7 +6300,7 @@ UINT32 CalcChanceToHitGun(SOLDIERTYPE *pSoldier, INT32 sGridNo, INT16 ubAimTime,
// e.g. 30% to aim at head at range 1, only 10% at range 3
// or 20% to aim at torso at range 1, no penalty at range 3
// NB torso aim position is 2, so (5-aimpos) is 3, for legs it's 2, for head 4
iChance -= (5 - ubAdjAimPos - iRange / CELL_X_SIZE) * 10;
iChance -= (INT32)((5 - ubAdjAimPos - iRange / CELL_X_SIZE) * 10 * iPenalty);
}
break;
default:
@@ -8421,7 +8435,7 @@ INT32 CalcBodyImpactReduction( UINT8 ubAmmoType, UINT8 ubHitLocation )
return( iReduction );
}
INT32 ArmourProtection( SOLDIERTYPE * pTarget, UINT16 ubArmourType, INT16 * pbStatus, INT32 iImpact, UINT8 ubAmmoType, BOOLEAN *plateHit )
INT32 ArmourProtection( SOLDIERTYPE * pTarget, UINT16 ubArmourType, INT16 * pbStatus, INT32 iImpact, UINT8 ubAmmoType, BOOLEAN *plateHit)
{
INT32 iProtection, iAppliedProtection, iFailure, iCoverage;
@@ -8498,7 +8512,7 @@ INT32 ArmourProtection( SOLDIERTYPE * pTarget, UINT16 ubArmourType, INT16 * pbSt
else if ( AmmoTypes[ubAmmoType].ignoreArmour )
{
// knives and darts damage armour but are not stopped by kevlar
if (Armour[ ubArmourType ].ubArmourClass == ARMOURCLASS_VEST || Armour[ ubArmourType ].ubArmourClass == ARMOURCLASS_LEGGINGS)
if ( Armour[ ubArmourType ].ubArmourClass == ARMOURCLASS_VEST || Armour[ ubArmourType ].ubArmourClass == ARMOURCLASS_LEGGINGS )
{
iProtection = 0;
}
@@ -8624,6 +8638,13 @@ INT32 BulletImpact( SOLDIERTYPE *pFirer, BULLET *pBullet, SOLDIERTYPE * pTarget,
INT8 bStatLoss = 0;
UINT8 ubAmmoType;
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;
}
// NOTE: reduction of bullet impact due to range and obstacles is handled
// in MoveBullet.
@@ -8769,7 +8790,7 @@ INT32 BulletImpact( SOLDIERTYPE *pFirer, BULLET *pBullet, SOLDIERTYPE * pTarget,
AdjustImpactByHitLocation( iImpact, ubHitLocation, &iImpact, &iImpactForCrits );
switch( ubHitLocation )
{
case AIM_SHOT_HEAD:
@@ -9346,7 +9367,22 @@ INT32 HTHImpact( SOLDIERTYPE * pSoldier, SOLDIERTYPE * pTarget, INT32 iHitBy, BO
if (pTarget->aiData.bOppList[ pSoldier->ubID ] == NOT_HEARD_OR_SEEN && !CREATURE_OR_BLOODCAT( pTarget ) )
{
iImpact = (INT32)((iImpact * 140 / 100) + 0.5); // 30% incresed damage on suprising attacks
}
}
}
// Flugente: power armour reduces damage taken
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
@@ -9369,6 +9405,21 @@ INT32 HTHImpact( SOLDIERTYPE * pSoldier, SOLDIERTYPE * pTarget, INT32 iHitBy, BO
iImpact = (INT32)(iImpact * 125 / 100); // 40% incresed damage to lying characters
}
}
// Flugente: power armour reduces damage taken
INT8 iSlot = VESTPOS;
switch( pSoldier->bAimShotLocation )
{
case AIM_SHOT_HEAD:
iSlot = HELMETPOS;
break;
case AIM_SHOT_LEGS:
iSlot = LEGPOS;
break;
default:
iSlot = VESTPOS;
break;
}
}
// bonus damage for aggressive characters
@@ -9501,7 +9552,7 @@ UINT32 CalcChanceHTH( SOLDIERTYPE * pAttacker,SOLDIERTYPE *pDefender, INT16 ubAi
// We need to be agile and dexterous
iAttRating = ( 2 * EffectiveDexterity( pAttacker ) + // coordination, accuracy *
2 * EffectiveAgility( pAttacker ) + // speed & reflexes
pAttacker->stats.bStrength + // physical strength
pAttacker->stats.bStrength + // physical strength
(10 * EffectiveExpLevel( pAttacker ) ) ); // experience, knowledge
}
else
+3
View File
@@ -211,6 +211,7 @@ typedef struct
INT16 lockBustingPower;
BOOLEAN tracerEffect;
FLOAT temperatureModificator; // Flugente FTW 1.1: modificator for weapon temperature
INT16 poisonPercentage; // Flugente FTW 1.1: modificator for weapon temperature
//zilpin: pellet spread patterns externalized in XML
INT32 spreadPattern;
@@ -428,6 +429,8 @@ extern void GetTargetWorldPositions( SOLDIERTYPE *pSoldier, INT32 sTargetGridNo,
extern BOOLEAN OKFireWeapon( SOLDIERTYPE *pSoldier );
extern BOOLEAN CheckForGunJam( SOLDIERTYPE * pSoldier );
extern FLOAT GetGunOverheatDamagePercentage( FLOAT usTemperature, UINT16 usIndx ); // Flugente FTW 1: Get percentage: temperature/damagethreshold
extern FLOAT GetGunOverheatJamPercentage( FLOAT usTemperature, UINT16 usIndx ); // Flugente FTW 1: Get percentage: temperature/jamthreshold
extern INT32 CalcMaxTossRange( SOLDIERTYPE * pSoldier, UINT16 usItem, BOOLEAN fArmed );
extern UINT32 CalcThrownChanceToHit(SOLDIERTYPE *pSoldier, INT32 sGridNo, INT16 ubAimTime, UINT8 ubAimPos );
+4 -4
View File
@@ -844,7 +844,7 @@ void CoolDownWorldItems( BOOLEAN fSetZero )
{
for(INT16 i = 0; i < pObj->ubNumberOfObjects; ++i) // ... there might be multiple items here (item stack), so for each one ...
{
FLOAT newguntemperature = 0.0;
FLOAT newguntemperature = 0.0f;
if ( !fSetZero && gGameExternalOptions.fSetZeroUponNewSector )
{
@@ -855,7 +855,7 @@ void CoolDownWorldItems( BOOLEAN fSetZero )
if ( Item[gWorldItems[ uiCount ].object.usItem].barrel == TRUE ) // ... a barrel lying around cools down a bit faster ...
cooldownfactor *= gGameExternalOptions.iCooldownModificatorLonelyBarrel;
newguntemperature = max(0.0, guntemperature - cooldownfactor); // ... calculate new temperature ...
newguntemperature = max(0.0f, guntemperature - cooldownfactor); // ... calculate new temperature ...
}
(*pObj)[i]->data.bTemperature = newguntemperature; // ... set new temperature
@@ -869,7 +869,7 @@ void CoolDownWorldItems( BOOLEAN fSetZero )
{
if ( iter->exists() && Item[ iter->usItem ].usItemClass & (IC_GUN|IC_LAUNCHER) )
{
FLOAT newtemperature = 0.0;
FLOAT newtemperature = 0.0f;
if ( !fSetZero && gGameExternalOptions.fSetZeroUponNewSector )
{
@@ -877,7 +877,7 @@ void CoolDownWorldItems( BOOLEAN fSetZero )
FLOAT cooldownfactor = GetItemCooldownFactor( &(*iter) ); // ... get cooldown factor ...
newtemperature = max(0.0, temperature - cooldownfactor); // ... calculate new temperature ...
newtemperature = max(0.0f, temperature - cooldownfactor); // ... calculate new temperature ...
}
(*iter)[i]->data.bTemperature = newtemperature; // ... set new temperature
+12 -1
View File
@@ -79,7 +79,8 @@ ammotypeStartElementHandle(void *userData, const XML_Char *name, const XML_Char
strcmp(name, "acidic") == 0 ||
strcmp(name, "tracerEffect") == 0 ||
strcmp(name, "monsterSpit") == 0 ||
strcmp(name, "temperatureModificator") == 0 ))
strcmp(name, "temperatureModificator") == 0 ||
strcmp(name, "PoisonPercentage") == 0 ))
{
pData->curElement = ELEMENT_PROPERTY;
@@ -282,6 +283,15 @@ ammotypeEndElementHandle(void *userData, const XML_Char *name)
pData->curElement = ELEMENT;
pData->curAmmoType.temperatureModificator = (FLOAT) atof(pData->szCharData);
}
else if(strcmp(name, "PoisonPercentage") == 0)
{
pData->curElement = ELEMENT;
pData->curAmmoType.poisonPercentage = (INT16) atol(pData->szCharData);
// check: poisonPercentage must be between 0 and 100, fit bad values
pData->curAmmoType.poisonPercentage = max(0, pData->curAmmoType.poisonPercentage);
pData->curAmmoType.poisonPercentage = min(100, pData->curAmmoType.poisonPercentage);
}
pData->maxReadDepth--;
}
@@ -404,6 +414,7 @@ BOOLEAN WriteAmmoTypeStats()
FilePrintf(hFile,"\t\t<lockBustingPower>%d</lockBustingPower>\r\n", AmmoTypes[cnt].lockBustingPower );
FilePrintf(hFile,"\t\t<tracerEffect>%d</tracerEffect>\r\n", AmmoTypes[cnt].tracerEffect );
FilePrintf(hFile,"\t\t<temperatureModificator>%4.2f</temperatureModificator>\r\n", AmmoTypes[cnt].temperatureModificator );
FilePrintf(hFile,"\t\t<PoisonPercentage>%d</PoisonPercentage>\r\n", AmmoTypes[cnt].poisonPercentage );
FilePrintf(hFile,"\t</AMMOTYPE>\r\n");
+1
View File
@@ -4764,6 +4764,7 @@ 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;
case SOLDIER_CLASS_ZOMBIE: gprintf( 320, LINE_HEIGHT * ubLine, L"(Zombie)" ); break;
default: break; //don't care (don't write anything)
}
ubLine++;
+1
View File
@@ -262,6 +262,7 @@ public:
UINT16 usKillsAdmins;
UINT16 usKillsHostiles;
UINT16 usKillsCreatures;
UINT16 usKillsZombies;
UINT16 usKillsTanks;
UINT16 usKillsOthers;
+8
View File
@@ -171,6 +171,14 @@ INT32 ClosestSeenOpponent(SOLDIERTYPE *pSoldier, INT32 * psGridNo, INT8 * pbLeve
void CreatureCall( SOLDIERTYPE * pCaller );
INT8 CreatureDecideAction( SOLDIERTYPE * pCreature );
void CreatureDecideAlertStatus( SOLDIERTYPE *pCreature );
// Flugente: Zombie AI
INT8 ZombieDecideAction( SOLDIERTYPE * pZombie );
void ZombieDecideAlertStatus( SOLDIERTYPE *pZombie );
// a variant of ClosestSeenOpponent(...), that allows zombies
INT32 ClosestSeenOpponentforZombie(SOLDIERTYPE *pSoldier, INT32 * psGridNo, INT8 * pbLevel);
INT8 CrowDecideAction( SOLDIERTYPE * pSoldier );
void DecideAlertStatus( SOLDIERTYPE *pSoldier );
INT8 DecideAutoBandage( SOLDIERTYPE * pSoldier );
+31 -1
View File
@@ -1616,7 +1616,32 @@ fprintf(NetDebugFile,"\tNPC %d, dtctLvl %d, marking mine at gridno %d, gridCost
void TurnBasedHandleNPCAI(SOLDIERTYPE *pSoldier)
{
// added by Flugente: static pointers, used to break out of an endless circles (currently only used for zombie AI)
static SOLDIERTYPE* pLastDecisionSoldier = NULL;
static INT16 lastdecisioncount = 0;
// simple solution to prevent an endless clock: remember the last soldier that decided an action. If its the same one, increase the counter.
// if counter is high enough, end this guy's turn
if ( pSoldier == pLastDecisionSoldier )
{
// we will only end our turn this way if this function was called over 100 times with same soldier without ending a turn.
// so many actions in a single turn smell of an endless clock.
// If we end a turn normally, the counter will be set back to 0, so this wont be a problem if you have a single soldier left for multiple turns
if ( lastdecisioncount >= 100 )
{
// zombie is done doing harm...
EndAIGuysTurn( pSoldier);
lastdecisioncount = 0;
return ;
}
else
++lastdecisioncount;
}
else
{
pLastDecisionSoldier = pSoldier;
lastdecisioncount = 0;
}
/*
if (Status.gamePaused)
@@ -1905,7 +1930,11 @@ void TurnBasedHandleNPCAI(SOLDIERTYPE *pSoldier)
{
if (!(gTacticalStatus.uiFlags & ENGAGED_IN_CONV))
{
if (CREATURE_OR_BLOODCAT( pSoldier ))
if ( pSoldier->IsZombie() )
{
pSoldier->aiData.bAction = ZombieDecideAction(pSoldier);
}
else if (CREATURE_OR_BLOODCAT( pSoldier ))
{
pSoldier->aiData.bAction = CreatureDecideAction( pSoldier );
}
@@ -1971,6 +2000,7 @@ void TurnBasedHandleNPCAI(SOLDIERTYPE *pSoldier)
{
// turn based... abort this guy's turn
EndAIGuysTurn( pSoldier );
lastdecisioncount = 0;
}
}
else
+98
View File
@@ -1295,6 +1295,100 @@ INT32 ClosestSeenOpponent(SOLDIERTYPE *pSoldier, INT32 * psGridNo, INT8 * pbLeve
}
// special variant with a minor twist for the zombie AI
INT32 ClosestSeenOpponentforZombie(SOLDIERTYPE *pSoldier, INT32 * psGridNo, INT8 * pbLevel)
{
INT32 sGridNo, sClosestOpponent = NOWHERE;
UINT32 uiLoop;
INT32 iRange, iClosestRange = 1500;
INT8 *pbPersOL;
INT8 bLevel, bClosestLevel;
SOLDIERTYPE * pOpp;
bClosestLevel = -1;
// look through this man's personal & public opplists for opponents known
for (uiLoop = 0; uiLoop < guiNumMercSlots; uiLoop++)
{
pOpp = MercSlots[ uiLoop ];
// if this merc is inactive, at base, on assignment, or dead
if (!pOpp)
{
continue; // next merc
}
// if this merc is neutral/on same side, he's not an opponent
if ( CONSIDERED_NEUTRAL( pSoldier, pOpp ) || (pSoldier->bSide == pOpp->bSide))
{
continue; // next merc
}
// Special stuff for Carmen the bounty hunter
if (pSoldier->aiData.bAttitude == ATTACKSLAYONLY && pOpp->ubProfile != 64)
{
continue; // next opponent
}
pbPersOL = pSoldier->aiData.bOppList + pOpp->ubID;
// if this opponent is not seen personally
if (*pbPersOL != SEEN_CURRENTLY)
{
continue; // next merc
}
// since we're dealing with seen people, use exact gridnos
sGridNo = pOpp->sGridNo;
bLevel = pOpp->pathing.bLevel;
// if we are standing at that gridno(!, obviously our info is old...)
if (sGridNo == pSoldier->sGridNo)
{
continue; // next merc
}
// special: allow zombies to also find opponents on a roof
// otherwise they have will never decide to climb a roof while they are seeing an enemy
// this function is used only for turning towards closest opponent or changing stance
// as such, if they AI is in a building,
// we should ignore people who are on the roof of the same building as the AI
if ( !pSoldier->IsZombie() && (bLevel != pSoldier->pathing.bLevel) && SameBuilding( pSoldier->sGridNo, sGridNo ) )
{
continue;
}
// I hope this will be good enough; otherwise we need a fractional/world-units-based 2D distance function
//sRange = PythSpacesAway( pSoldier->sGridNo, sGridNo);
iRange = GetRangeInCellCoordsFromGridNoDiff( pSoldier->sGridNo, sGridNo );
if (iRange < iClosestRange)
{
iClosestRange = iRange;
sClosestOpponent = sGridNo;
bClosestLevel = bLevel;
}
}
#ifdef DEBUGDECISIONS
if (!TileIsOutOfBounds(sClosestOpponent))
{
AINumMessage("CLOSEST OPPONENT is at gridno ",sClosestOpponent);
}
#endif
if (psGridNo)
{
*psGridNo = sClosestOpponent;
}
if (pbLevel)
{
*pbLevel = bClosestLevel;
}
return( sClosestOpponent );
}
INT32 ClosestPC( SOLDIERTYPE *pSoldier, INT32 * psDistance )
{
// used by NPCs... find the closest PC
@@ -2487,6 +2581,10 @@ UINT8 SoldierDifficultyLevel( SOLDIERTYPE * pSoldier )
bDifficulty = 4;
break;
case SOLDIER_CLASS_ZOMBIE:
bDifficulty = bDifficultyBase;
break;
default:
if (pSoldier->bTeam == CREATURE_TEAM)
{
+1
View File
@@ -1757,3 +1757,4 @@ INT8 CrowDecideAction( SOLDIERTYPE * pSoldier )
return( AI_ACTION_NONE );
}
}
File diff suppressed because it is too large Load Diff
+8
View File
@@ -27,6 +27,10 @@ INT8 RTPlayerDecideAction( SOLDIERTYPE * pSoldier )
{
bAction = DecideAutoBandage( pSoldier );
}
else if ( pSoldier->IsZombie() )
{
bAction = ZombieDecideAction( pSoldier );
}
else
{
bAction = DecideAction( pSoldier );
@@ -47,6 +51,10 @@ INT8 RTDecideAction(SOLDIERTYPE *pSoldier)
{
return( CreatureDecideAction( pSoldier ) );
}
else if ( pSoldier->IsZombie() )
{
return( ZombieDecideAction( pSoldier ) );
}
else if (pSoldier->ubBodyType == CROW)
{
return( CrowDecideAction( pSoldier ) );
+13 -52
View File
@@ -1577,21 +1577,10 @@ BOOLEAN DamageSoldierFromBlast( UINT8 ubPerson, UINT8 ubOwner, INT32 sBombGridNo
// Bodybuilding damage resistance
if ( gGameOptions.fNewTraitSystem && HAS_SKILL_TRAIT( pSoldier, BODYBUILDING_NT ) )
sNewWoundAmt = max( 1, (INT16)(sNewWoundAmt * (100 - gSkillTraitValues.ubBBDamageResistance) / 100));
// Damage resistance for Militia
if (pSoldier->ubSoldierClass == SOLDIER_CLASS_GREEN_MILITIA && gGameExternalOptions.bGreenMilitiaDamageResistance != 0)
sNewWoundAmt -= ((sNewWoundAmt * gGameExternalOptions.bGreenMilitiaDamageResistance) /100);
else if (pSoldier->ubSoldierClass == SOLDIER_CLASS_REG_MILITIA && gGameExternalOptions.bRegularMilitiaDamageResistance != 0)
sNewWoundAmt -= ((sNewWoundAmt * gGameExternalOptions.bRegularMilitiaDamageResistance) /100);
else if (pSoldier->ubSoldierClass == SOLDIER_CLASS_ELITE_MILITIA && gGameExternalOptions.bVeteranMilitiaDamageResistance != 0)
sNewWoundAmt -= ((sNewWoundAmt * gGameExternalOptions.bVeteranMilitiaDamageResistance) /100);
// bonus for enemy too
else if (pSoldier->ubSoldierClass == SOLDIER_CLASS_ADMINISTRATOR && gGameExternalOptions.sEnemyAdminDamageResistance != 0)
sNewWoundAmt -= ((sNewWoundAmt * gGameExternalOptions.sEnemyAdminDamageResistance) /100);
else if (pSoldier->ubSoldierClass == SOLDIER_CLASS_ARMY && gGameExternalOptions.sEnemyRegularDamageResistance != 0)
sNewWoundAmt -= ((sNewWoundAmt * gGameExternalOptions.sEnemyRegularDamageResistance) /100);
else if (pSoldier->ubSoldierClass == SOLDIER_CLASS_ELITE && gGameExternalOptions.sEnemyEliteDamageResistance != 0)
sNewWoundAmt -= ((sNewWoundAmt * gGameExternalOptions.sEnemyEliteDamageResistance) /100);
// Flugente: moved the damage calculation into a separate function
if ( pSoldier->GetDamageResistance(FALSE, FALSE) > 0 )
sNewWoundAmt -= ((sNewWoundAmt * pSoldier->GetDamageResistance(FALSE, FALSE)) /100);
// we can loose stats due to being hit by the blast
else if ( gGameOptions.fNewTraitSystem && Explosive[Item[usItem].ubClassIndex].ubType == EXPLOSV_NORMAL &&
@@ -1790,41 +1779,12 @@ BOOLEAN DamageSoldierFromBlast( UINT8 ubPerson, UINT8 ubOwner, INT32 sBombGridNo
sNewWoundAmt = max(1, sNewWoundAmt);
}
//////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////
// SANDRO - option to make special NPCs stronger - damage resistance
if (gGameExternalOptions.usSpecialNPCStronger > 0)
{
switch( pSoldier->ubProfile )
{
case CARMEN:
case QUEEN:
case JOE:
case ANNIE:
case CHRIS:
case KINGPIN:
case TIFFANY:
case T_REX:
case DRUGGIST:
case GENERAL:
case JACK:
case OLAF:
case RAY:
case OLGA:
case TYRONE:
case MIKE:
sNewWoundAmt -= (sNewWoundAmt * gGameExternalOptions.usSpecialNPCStronger / 200);
sNewWoundAmt = max( 1, sNewWoundAmt);
break;
}
}
// SANDRO - new merc records - times wounded (blasted by explosion)
if ( ( sNewWoundAmt > 1 || sBreathAmt > 1000 ) && pSoldier->ubProfile != NO_PROFILE )
gMercProfiles[ pSoldier->ubProfile ].records.usTimesWoundedBlasted++;
////////////////////////////////////////////////////////////////////////////////////
// Lesh: flashbang does affect on soldier or not - check it
if ( (Item[usItem].usItemClass & IC_EXPLOSV) && fFlashbang )
{
@@ -1918,7 +1878,8 @@ BOOLEAN DishOutGasDamage( SOLDIERTYPE * pSoldier, EXPLOSIVETYPE * pExplosive, IN
{
if ( pExplosive->ubType == EXPLOSV_TEARGAS )
{
if ( AM_A_ROBOT( pSoldier ) )
// zombies and robots are unaffected by tear gas
if ( AM_A_ROBOT( pSoldier ) || pSoldier->IsZombie() )
{
return( fRecompileMovementCosts );
}
@@ -1932,7 +1893,8 @@ BOOLEAN DishOutGasDamage( SOLDIERTYPE * pSoldier, EXPLOSIVETYPE * pExplosive, IN
}
else if ( pExplosive->ubType == EXPLOSV_MUSTGAS )
{
if ( AM_A_ROBOT( pSoldier ) )
// zombies and robots are unaffected by mustard gas
if ( AM_A_ROBOT( pSoldier ) || pSoldier->IsZombie() )
{
return( fRecompileMovementCosts );
}
@@ -2030,9 +1992,8 @@ BOOLEAN DishOutGasDamage( SOLDIERTYPE * pSoldier, EXPLOSIVETYPE * pExplosive, IN
case EXPLOSV_TEARGAS:
pSoldier->flags.fHitByGasFlags |= HIT_BY_TEARGAS;
break;
case EXPLOSV_MUSTGAS:
case EXPLOSV_MUSTGAS:
pSoldier->flags.fHitByGasFlags |= HIT_BY_MUSTARDGAS;
break;
case EXPLOSV_BURNABLEGAS:
pSoldier->flags.fHitByGasFlags |= HIT_BY_BURNABLEGAS;
break;
@@ -2046,7 +2007,7 @@ BOOLEAN DishOutGasDamage( SOLDIERTYPE * pSoldier, EXPLOSIVETYPE * pExplosive, IN
//ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"ExpControl pSoldier->flags.fHitByGasFlags: %d", pSoldier->flags.fHitByGasFlags );
// a gas effect, take damage directly...
pSoldier->SoldierTakeDamage( ANIM_STAND, sWoundAmt, sBreathAmt, TAKE_DAMAGE_GAS, NOBODY, NOWHERE, 0, TRUE );
pSoldier->SoldierTakeDamage( ANIM_STAND, sWoundAmt, 0, sBreathAmt, TAKE_DAMAGE_GAS, NOBODY, NOWHERE, 0, TRUE );
if (is_networked && is_client)
{
@@ -2480,7 +2441,7 @@ BOOLEAN ExpAffect( INT32 sBombGridNo, INT32 sGridNo, UINT32 uiDist, UINT16 usIte
break;
}
// a gas effect, take damage directly...
pSoldier->SoldierTakeDamage( ANIM_STAND, sWoundAmt, sBreathAmt, TAKE_DAMAGE_GAS, NOBODY, NOWHERE, 0, TRUE );
pSoldier->SoldierTakeDamage( ANIM_STAND, sWoundAmt, 0, sBreathAmt, TAKE_DAMAGE_GAS, NOBODY, NOWHERE, 0, TRUE );
if ( pSoldier->stats.bLife >= CONSCIOUSNESS )
{
pSoldier->DoMercBattleSound( (INT8)( BATTLE_SOUND_HIT1 + Random( 2 ) ) );
+30 -1
View File
@@ -683,14 +683,43 @@ void RenderTacticalPlacementGUI()
iStartY = yp + 29 - 27*pSoldier->stats.bLifeMax/100;
ColorFillVideoSurfaceArea( FRAME_BUFFER, xp+36, iStartY, xp+37, yp+29, Get16BPPColor( FROMRGB( 107, 107, 57 ) ) );
ColorFillVideoSurfaceArea( FRAME_BUFFER, xp+37, iStartY, xp+38, yp+29, Get16BPPColor( FROMRGB( 222, 181, 115 ) ) );
// poisoned bleeding in purple
if ( pSoldier->bPoisonBleeding )
{
iStartY = yp + 29 - 27*(pSoldier->stats.bLifeMax - pSoldier->bBleeding + pSoldier->bPoisonBleeding)/100;
ColorFillVideoSurfaceArea( FRAME_BUFFER, xp+36, iStartY, xp+37, yp+29, Get16BPPColor( FROMRGB( 107, 57, 107 ) ) );
ColorFillVideoSurfaceArea( FRAME_BUFFER, xp+37, iStartY, xp+38, yp+29, Get16BPPColor( FROMRGB( 222, 115, 181 ) ) );
}
//pink one for bandaged.
iStartY += 27*pSoldier->bBleeding/100;
iStartY = yp + 29 - 27*(pSoldier->stats.bLifeMax - pSoldier->bBleeding)/100;
ColorFillVideoSurfaceArea( FRAME_BUFFER, xp+36, iStartY, xp+37, yp+29, Get16BPPColor( FROMRGB( 156, 57, 57 ) ) );
ColorFillVideoSurfaceArea( FRAME_BUFFER, xp+37, iStartY, xp+38, yp+29, Get16BPPColor( FROMRGB( 222, 132, 132 ) ) );
// get amount of poisoned bandage
INT8 bPoisonBandage = pSoldier->bPoisonSum - pSoldier->bPoisonBleeding - pSoldier->bPoisonLife;
if ( bPoisonBandage )
{
// poisoned bandage in bright green
iStartY = yp + 29 - 27*(pSoldier->stats.bLife + bPoisonBandage)/100;
ColorFillVideoSurfaceArea( FRAME_BUFFER, xp+36, iStartY, xp+37, yp+29, Get16BPPColor( FROMRGB( 57, 156, 57 ) ) );
ColorFillVideoSurfaceArea( FRAME_BUFFER, xp+37, iStartY, xp+38, yp+29, Get16BPPColor( FROMRGB( 132, 222, 132 ) ) );
}
//red one for actual health
iStartY = yp + 29 - 27*pSoldier->stats.bLife/100;
ColorFillVideoSurfaceArea( FRAME_BUFFER, xp+36, iStartY, xp+37, yp+29, Get16BPPColor( FROMRGB( 107, 8, 8 ) ) );
ColorFillVideoSurfaceArea( FRAME_BUFFER, xp+37, iStartY, xp+38, yp+29, Get16BPPColor( FROMRGB( 206, 0, 0 ) ) );
// poisoned life
if ( pSoldier->bPoisonLife )
{
iStartY = yp + 29 - 27*pSoldier->bPoisonLife/100;
ColorFillVideoSurfaceArea( FRAME_BUFFER, xp+36, iStartY, xp+37, yp+29, Get16BPPColor( FROMRGB( 8, 107, 8 ) ) );
ColorFillVideoSurfaceArea( FRAME_BUFFER, xp+37, iStartY, xp+38, yp+29, Get16BPPColor( FROMRGB( 0, 206, 0 ) ) );
}
//BREATH BAR
iStartY = yp + 29 - 27*pSoldier->bBreathMax/100;
ColorFillVideoSurfaceArea( FRAME_BUFFER, xp+39, iStartY, xp+40, yp+29, Get16BPPColor( FROMRGB( 8, 8, 132 ) ) );
+7 -4
View File
@@ -632,14 +632,14 @@ extern STR16 szUDBGenWeaponsStatsTooltipText[ 23 ];
extern STR16 szUDBGenWeaponsStatsExplanationsTooltipText[ 23 ];
extern STR16 szUDBGenArmorStatsTooltipText[ 3 ];
extern STR16 szUDBGenArmorStatsExplanationsTooltipText[ 3 ];
extern STR16 szUDBGenAmmoStatsTooltipText[ 4 ]; // Flugente Overheating Weapons: 3->4
extern STR16 szUDBGenAmmoStatsExplanationsTooltipText[ 4 ];
extern STR16 szUDBGenAmmoStatsTooltipText[ 5 ]; // Flugente Overheating: 3->4 poison: 4->5
extern STR16 szUDBGenAmmoStatsExplanationsTooltipText[ 5 ]; // Flugente Overheating: 3->4 poison: 4->5
extern STR16 szUDBGenExplosiveStatsTooltipText[ 22 ];
extern STR16 szUDBGenExplosiveStatsExplanationsTooltipText[ 22 ];
extern STR16 szUDBGenSecondaryStatsTooltipText[ 26 ];
extern STR16 szUDBGenSecondaryStatsExplanationsTooltipText[ 26 ];
extern STR16 szUDBAdvStatsTooltipText[ 56 ]; // Flugente Overheating Weapons: 48->56
extern STR16 szUDBAdvStatsExplanationsTooltipText[ 56 ]; // Flugente Overheating Weapons: 48->56
extern STR16 szUDBAdvStatsTooltipText[ 57 ]; // Flugente Overheating Weapons: 48->56 poison: 56->57
extern STR16 szUDBAdvStatsExplanationsTooltipText[ 57 ]; // Flugente Overheating Weapons: 48->56 poison: 56->57
extern STR16 szUDBAdvStatsExplanationsTooltipTextForWeapons[ 52 ]; // Flugente Overheating Weapons: 48->52
// Headrock: End Externs
@@ -752,6 +752,7 @@ enum
CREATURE_TEAM_MERC_NAME,
MILITIA_TEAM_MERC_NAME,
CIV_TEAM_MERC_NAME,
ZOMBIE_TEAM_MERC_NAME,
//The text for the 'exiting sector' gui
EXIT_GUI_TITLE_STR,
@@ -808,6 +809,8 @@ enum
CHOOSE_REMOTE_DETONATE_AND_REMOTE_DEFUSE_FREQUENCY_STR,
CHOOSE_DETONATE_AND_REMOTE_DEFUSE_FREQUENCY_STR,
CHOOSE_TRIPWIRE_NETWORK,
MERC_VITAL_STATS_WITH_POISON_POPUPTEXT,
TEXT_NUM_TACTICAL_STR
};
+11
View File
@@ -265,6 +265,8 @@ itemStartElementHandle(void *userData, const XML_Char *name, const XML_Char **at
strcmp(name, "Directional") == 0 ||
strcmp(name, "DrugType") == 0 ||
strcmp(name, "BlockIronSight") == 0 ||
// Flugente: poison system
strcmp(name, "PoisonPercentage") == 0 ||
strcmp(name, "fFlags") == 0 ))
{
@@ -1331,6 +1333,12 @@ itemEndElementHandle(void *userData, const XML_Char *name)
pData->curElement = ELEMENT;
pData->curItem.blockironsight = (BOOLEAN) atol(pData->szCharData);
}
// Flugente poison system
else if(strcmp(name, "PoisonPercentage") == 0)
{
pData->curElement = ELEMENT;
pData->curItem.bPoisonPercentage = (INT16) atol(pData->szCharData);
}
pData->maxReadDepth--;
@@ -1947,6 +1955,9 @@ BOOLEAN WriteItemStats()
FilePrintf(hFile,"\t\t<BlockIronSight>%d</BlockIronSight>\r\n", Item[cnt].blockironsight );
// Flugente poison system
FilePrintf(hFile,"\t\t<PoisonPercentage>%d</PoisonPercentage>\r\n", Item[cnt].bPoisonPercentage );
FilePrintf(hFile,"\t</ITEM>\r\n");
}
FilePrintf(hFile,"</ITEMLIST>\r\n");
+14 -1
View File
@@ -2070,6 +2070,8 @@ STR16 pPersonnelRecordsHelpTexts[] =
L"弱点:",
L"态度:", // WANNE: For old traits display instead of "Character:"!
L"Zombies: %d\n", // TODO.Translate
};
@@ -2865,6 +2867,7 @@ CHAR16 TacticalStr[][ MED_STRING_LENGTH ] =
L"异形",
L"民兵",
L"平民",
L"ZOMBIE", // TODO.Translate
L"离开分区",
L"确定",
L"取消",
@@ -2920,6 +2923,9 @@ CHAR16 TacticalStr[][ MED_STRING_LENGTH ] =
L"Set detonation frequency (1 - 4) and defusing frequency (A - D):",
L"Set detonation time in turns (1 - 4) and defusing frequency (A - D):",
L"Select tripwire hierarchy (1 - 4) and network (A - D):",
// added by Flugente to display health and poisoning // TODO.Translate
L"Health: %d/%d\n Poison: %d/%d\nEnergy: %d/%d\nMorale: %s",
};
//Varying helptext explains (for the "Go to Sector/Map" checkbox) what will happen given different circumstances in the "exiting sector" interface.
@@ -3473,6 +3479,7 @@ STR16 pMapScreenStatusStrings[] =
L"士气",
L"状态", // the condition of the current vehicle (its "health")
L"油量", // the fuel level of the current vehicle (its "energy")
L"Posion", // TODO.Translate
};
@@ -5102,8 +5109,9 @@ STR16 zOptionsToggleText[] =
L"显示脸部装备图",
L"显示脸部装备图标",
L"禁止光标切换", // Disable Cursor Swap
L"Quiet Training", // Madd: mercs don't say quotes while training // TODO.Translate
L"Quiet Training", // Madd: mercs don't say quotes while training // TODO.Translate
L"自动加速敌军回合", // Automatic fast forward through AI turns
L"Allow Zombies", // TODO.Translate
//L"武器过热",
L"--作弊模式选项--", // TOPTION_CHEAT_MODE_OPTIONS_HEADER,
L"强制 Bobby Ray 送货", // force all pending Bobby Ray shipments
@@ -5213,6 +5221,7 @@ STR16 zOptionsScreenHelpText[] =
L"打开时,在交换位置和其它动作时光标不切换。键入 |x 可以快速切换。",
L"When ON, mercs will not report progress during training.", //TODO.Translate
L"打开时,敌军回合将被大幅加速。",
L"When ON, zombies will span. Be aware!", // allow zombies // TODO.Translate
//L"打开时,武器连续射击时温度逐渐升高引起过热。",
L"(text not rendered)TOPTION_CHEAT_MODE_OPTIONS_HEADER",
L"强制 Bobby Ray 出货",
@@ -6924,6 +6933,7 @@ STR16 szUDBGenAmmoStatsTooltipText[]=
L"|翻|搅|力||开|花|弹|",
L"|爆|炸|力||炸|子|儿|",
L"|过|热|修|正",
L"|P|o|i|s|o|n |P|e|r|c|e|n|t|a|g|e", // TODO.Translate
};
STR16 szUDBGenAmmoStatsExplanationsTooltipText[]=
@@ -6932,6 +6942,7 @@ STR16 szUDBGenAmmoStatsExplanationsTooltipText[]=
L"\n \n该值决定子弹打穿护甲击中身体时的伤害力\n加成。\n \n该值大于1时,子弹在穿过护甲后会增加伤害。\n \n当该值小于1时,子弹穿过护甲后会减少伤害。\n \n该数值越高越好。",
L"\n \n该值是子弹在击中目标前已经造成的潜在伤害的倍率。\n \n大于1的数值可以增加伤害,\n反之则减少伤害。\n \n该数值越高越好。",
L"\n \n子弹温度系数。\n \n该数值越低越好。",
L"\n \nDetermines what percentage of a\nbullet's damage will be poisonous.", // TODO.Translate
};
STR16 szUDBGenExplosiveStatsTooltipText[]=
@@ -7108,6 +7119,7 @@ STR16 szUDBAdvStatsTooltipText[]=
L"|冷|却|参|数",
L"|卡|壳|阈|值",
L"|损|坏|阈|值",
L"|P|o|i|s|o|n |P|e|r|c|e|n|t|a|g|e", // TODO.Translate
};
// Alternate tooltip text for weapon Advanced Stats. Just different wording, nothing spectacular.
@@ -7169,6 +7181,7 @@ STR16 szUDBAdvStatsExplanationsTooltipText[]=
L"\n \n武器的冷却系数数增加了(百分比)。\n \n该数值越高越好。",
L"\n \n武器的卡壳阈值增加了(百分比)。\n \n该数值越高越好。",
L"\n \n武器的损坏阈值增加了(百分比)。\n \n该数值越高越好。",
L"\n \nThis is the percentage of damage dealt\nby this item that will be poisonous.\n\nUsefulness depends on wether enemy\nhas poison resistance or absorption.", // TODO.Translate
};
STR16 szUDBAdvStatsExplanationsTooltipTextForWeapons[]=
+13
View File
@@ -2066,6 +2066,8 @@ STR16 pPersonnelRecordsHelpTexts[] =
L"Weakness:",
L"Attitudes:", // WANNE: For old traits display instead of "Character:"!
L"Zombies: %d\n", // TODO.Translate
};
@@ -2862,6 +2864,7 @@ CHAR16 TacticalStr[][ MED_STRING_LENGTH ] =
L"CREPITUS", // L"CREPITUS",
L"MILITIE", // L"MILITIA",
L"BURGER", // L"CIVILIAN",
L"ZOMBIE", // TODO.Translate
L"Verlaten Sector", // L"Exiting Sector",
L"OK",
L"Stoppen", // L"Cancel",
@@ -2917,6 +2920,9 @@ CHAR16 TacticalStr[][ MED_STRING_LENGTH ] =
L"Set detonation frequency (1 - 4) and defusing frequency (A - D):",
L"Set detonation time in turns (1 - 4) and defusing frequency (A - D):",
L"Select tripwire hierarchy (1 - 4) and network (A - D):",
// added by Flugente to display health and poisoning // TODO.Translate
L"Health: %d/%d\n Poison: %d/%d\nEnergy: %d/%d\nMorale: %s",
};
//Varying helptext explains (for the "Go to Sector/Map" checkbox) what will happen given different circumstances in the "exiting sector" interface.
@@ -3469,6 +3475,7 @@ STR16 pMapScreenStatusStrings[] =
L"Moraal",
L"Conditie", // the condition of the current vehicle (its "health")
L"Brandstof", // the fuel level of the current vehicle (its "energy")
L"Posion", // TODO.Translate
};
@@ -5103,6 +5110,7 @@ STR16 zOptionsToggleText[] =
L"Uit te schakelen Cursor Swap", // Disable Cursor Swap
L"Quiet Training", // Madd: mercs don't say quotes while training // TODO.Translate
L"Auto Fast Forward AI Turns", // Automatic fast forward through AI turns // TODO.Translate
L"Allow Zombies", // TODO.Translate
//L"Weapons Overheating", // TODO.Translate
L"--Cheat Mode Options--", // TOPTION_CHEAT_MODE_OPTIONS_HEADER,
L"Force Bobby Ray shipments", // force all pending Bobby Ray shipments
@@ -5212,6 +5220,7 @@ STR16 zOptionsScreenHelpText[] =
L"Wanneer ingeschakeld, zal de cursor niet te schakelen tussen uitwisseling positie en andere acties. Druk op |x om snelle uitwisseling te starten.",
L"When ON, mercs will not report progress during training.", //TODO.Translate
L"When ON, AI turns will be much faster.", // TODO.Translate
L"When ON, zombies will span. Be aware!", // allow zombies // TODO.Translate
//L"When ON, weapons can be overheated when firing.", // TODO.Translate
L"(text not rendered)TOPTION_CHEAT_MODE_OPTIONS_HEADER",
L"Force all pending Bobby Ray shipments",
@@ -6919,6 +6928,7 @@ STR16 szUDBGenAmmoStatsTooltipText[]=
L"|B|u|l|l|e|t |T|u|m|b|l|e",
L"|P|r|e|-|I|m|p|a|c|t |E|x|p|l|o|s|i|o|n",
L"|T|e|m|p|e|r|a|t|u|r|e |M|o|d|i|f|i|c|a|t|i|o|n", // TODO.Translate
L"|P|o|i|s|o|n |P|e|r|c|e|n|t|a|g|e", // TODO.Translate
};
STR16 szUDBGenAmmoStatsExplanationsTooltipText[]=
@@ -6927,6 +6937,7 @@ STR16 szUDBGenAmmoStatsExplanationsTooltipText[]=
L"\n \nDetermines a proportional increase of damage\npotential once the bullet gets through the\ntarget's armor and hits the bodypart behind it.\n \nWhen above 1.0, the bullet's damage\nincreases after penetrating the armor.\n \nWhen below 1.0, the bullet's damage\npotential decreases after passing through armor.\n \nHigher is better.",
L"\n \nA multiplier to the bullet's damage potential\nthat is applied immediately before hitting the\ntarget.\n \nValues above 1.0 indicate an increase in damage,\nvalues below 1.0 indicate a decrease.\n \nHigher is better.",
L"\n \nAdditional heat generated by this ammunition.\n \nLower is better.", // TODO.Translate
L"\n \nDetermines what percentage of a\nbullet's damage will be poisonous.", // TODO.Translate
};
STR16 szUDBGenExplosiveStatsTooltipText[]=
@@ -7103,6 +7114,7 @@ STR16 szUDBAdvStatsTooltipText[]=
L"|C|o|o|l|d|o|w|n |M|o|d|i|f|i|e|r",
L"|J|a|m |T|h|r|e|s|h|o|l|d |M|o|d|i|f|i|e|r",
L"|D|a|m|a|g|e |T|h|r|e|s|h|o|l|d |M|o|d|i|f|i|e|r",
L"|P|o|i|s|o|n |P|e|r|c|e|n|t|a|g|e", // TODO.Translate
};
// Alternate tooltip text for weapon Advanced Stats. Just different wording, nothing spectacular.
@@ -7164,6 +7176,7 @@ STR16 szUDBAdvStatsExplanationsTooltipText[]=
L"\n \nA gun's cooldown factor is\nincreased by this percentage.\n \nHigher is better.",
L"\n \nA gun's jam threshold is\nincreased by this percentage.\n \nHigher is better.",
L"\n \nA gun's damage threshold is\nincreased by this percentage.\n \nHigher is better.",
L"\n \nThis is the percentage of damage dealt\nby this item that will be poisonous.\n\nUsefulness depends on wether enemy\nhas poison resistance or absorption.", // TODO.Translate
};
STR16 szUDBAdvStatsExplanationsTooltipTextForWeapons[]=
+15 -3
View File
@@ -2070,6 +2070,8 @@ STR16 pPersonnelRecordsHelpTexts[] =
L"Weakness:",
L"Attitudes:", // WANNE: For old traits display instead of "Character:"!
L"Zombies: %d\n", // Flugente Zombies
};
@@ -2865,6 +2867,7 @@ CHAR16 TacticalStr[][ MED_STRING_LENGTH ] =
L"CREPITUS",
L"MILITIA",
L"CIVILIAN",
L"ZOMBIE",
L"Exiting Sector",
L"OK",
L"Cancel",
@@ -2920,6 +2923,9 @@ CHAR16 TacticalStr[][ MED_STRING_LENGTH ] =
L"Set detonation frequency (1 - 4) and defusing frequency (A - D):",
L"Set detonation time in turns (1 - 4) and defusing frequency (A - D):",
L"Select tripwire hierarchy (1 - 4) and network (A - D):",
// added by Flugente to display health and poisoning
L"Health: %d/%d\n Poison: %d/%d\nEnergy: %d/%d\nMorale: %s",
};
//Varying helptext explains (for the "Go to Sector/Map" checkbox) what will happen given different circumstances in the "exiting sector" interface.
@@ -3471,6 +3477,7 @@ STR16 pMapScreenStatusStrings[] =
L"Morale",
L"Condition", // the condition of the current vehicle (its "health")
L"Fuel", // the fuel level of the current vehicle (its "energy")
L"Poison", // for display of poisoning
};
@@ -5102,6 +5109,7 @@ STR16 zOptionsToggleText[] =
L"Disable Cursor Swap", // Disable Cursor Swap
L"Quiet Training", // Madd: mercs don't say quotes while training
L"Auto Fast Forward AI Turns", // Automatic fast forward through AI turns
L"Allow Zombies", // Flugente Zombies 1.0
//L"Weapons Overheating", // TODO.Translate
L"--Cheat Mode Options--", // TOPTION_CHEAT_MODE_OPTIONS_HEADER,
L"Force Bobby Ray shipments", // force all pending Bobby Ray shipments
@@ -5113,7 +5121,7 @@ STR16 zOptionsToggleText[] =
L"Debug Options in other builds", // allow debugging in release or mapeditor
L"DEBUG Render Option group", // an example option that will show/hide other options
L"Render Mouse Regions", // an example of a DEBUG build option
L"-----------------", // an example options screen options divider (pure text)
L"-----------------", // an example options screen options divider (pure text)
// this is THE LAST option that exists (debug the options screen, doesnt do anything, except exist)
L"THE_LAST_OPTION",
@@ -5211,6 +5219,7 @@ STR16 zOptionsScreenHelpText[] =
L"When ON, the cursor will not toggle between exchange position and other actions. Press |x to initiate quick exchange.",
L"When ON, mercs will not report progress during training.",
L"When ON, AI turns will be much faster.",
L"When ON, zombies will span. Be aware!", // allow zombies
//L"When ON, weapons can be overheated when firing.", // TODO.Translate
L"(text not rendered)TOPTION_CHEAT_MODE_OPTIONS_HEADER",
L"Force all pending Bobby Ray shipments",
@@ -5222,8 +5231,7 @@ STR16 zOptionsScreenHelpText[] =
L"Allows debug options in release or mapeditor builds", // allow debugging in release or mapeditor
L"Toggle to display debugging render options", // an example option that will show/hide other options
L"Attempts to display slash-rects around mouse regions", // an example of a DEBUG build option
L"(text not rendered)TOPTION_DEBUG_MODE_OPTIONS_END", // an example options screen options divider (pure text)
L"(text not rendered)TOPTION_DEBUG_MODE_OPTIONS_END", // an example options screen options divider (pure text)
// this is THE LAST option that exists (debug the options screen, doesnt do anything, except exist)
L"TOPTION_LAST_OPTION",
@@ -6911,6 +6919,7 @@ STR16 szUDBGenAmmoStatsTooltipText[]=
L"|B|u|l|l|e|t |T|u|m|b|l|e",
L"|P|r|e|-|I|m|p|a|c|t |E|x|p|l|o|s|i|o|n",
L"|T|e|m|p|e|r|a|t|u|r|e |M|o|d|i|f|i|c|a|t|i|o|n",
L"|P|o|i|s|o|n |P|e|r|c|e|n|t|a|g|e",
};
STR16 szUDBGenAmmoStatsExplanationsTooltipText[]=
@@ -6919,6 +6928,7 @@ STR16 szUDBGenAmmoStatsExplanationsTooltipText[]=
L"\n \nDetermines a proportional increase of damage\npotential once the bullet gets through the\ntarget's armor and hits the bodypart behind it.\n \nWhen above 1.0, the bullet's damage\nincreases after penetrating the armor.\n \nWhen below 1.0, the bullet's damage\npotential decreases after passing through armor.\n \nHigher is better.",
L"\n \nA multiplier to the bullet's damage potential\nthat is applied immediately before hitting the\ntarget.\n \nValues above 1.0 indicate an increase in damage,\nvalues below 1.0 indicate a decrease.\n \nHigher is better.",
L"\n \nAdditional heat generated by this ammunition.\n \nLower is better.",
L"\n \nDetermines what percentage of a\nbullet's damage will be poisonous.",
};
STR16 szUDBGenExplosiveStatsTooltipText[]=
@@ -7096,6 +7106,7 @@ STR16 szUDBAdvStatsTooltipText[]=
L"|C|o|o|l|d|o|w|n |M|o|d|i|f|i|e|r",
L"|J|a|m |T|h|r|e|s|h|o|l|d |M|o|d|i|f|i|e|r",
L"|D|a|m|a|g|e |T|h|r|e|s|h|o|l|d |M|o|d|i|f|i|e|r",
L"|P|o|i|s|o|n |P|e|r|c|e|n|t|a|g|e",
};
// Alternate tooltip text for weapon Advanced Stats. Just different wording, nothing spectacular.
@@ -7157,6 +7168,7 @@ STR16 szUDBAdvStatsExplanationsTooltipText[]=
L"\n \nA gun's cooldown factor is\nincreased by this percentage.\n \nHigher is better.",
L"\n \nA gun's jam threshold is\nincreased by this percentage.\n \nHigher is better.",
L"\n \nA gun's damage threshold is\nincreased by this percentage.\n \nHigher is better.",
L"\n \nThis is the percentage of damage dealt\nby this item that will be poisonous.\n\nUsefulness depends on wether enemy\nhas poison resistance or absorption.",
};
STR16 szUDBAdvStatsExplanationsTooltipTextForWeapons[]=
+13
View File
@@ -2069,6 +2069,8 @@ STR16 pPersonnelRecordsHelpTexts[] =
L"Faiblesse :",
L"Attitudes :", // WANNE: For old traits display instead of "Character:"!
L"Zombies: %d\n", // TODO.Translate
};
@@ -2864,6 +2866,7 @@ CHAR16 TacticalStr[][ MED_STRING_LENGTH ] =
L"CREPITUS",
L"Milice",
L"CIVIL",
L"ZOMBIE", // TODO.Translate
L"Quitter Secteur",
L"OK",
L"Annuler",
@@ -2919,6 +2922,9 @@ CHAR16 TacticalStr[][ MED_STRING_LENGTH ] =
L"Set detonation frequency (1 - 4) and defusing frequency (A - D):",
L"Set detonation time in turns (1 - 4) and defusing frequency (A - D):",
L"Select tripwire hierarchy (1 - 4) and network (A - D):",
// added by Flugente to display health and poisoning // TODO.Translate
L"Health: %d/%d\n Poison: %d/%d\nEnergy: %d/%d\nMorale: %s",
};
//Varying helptext explains (for the "Go to Sector/Map" checkbox) what will happen given different circumstances in the "exiting sector" interface.
@@ -3473,6 +3479,7 @@ STR16 pMapScreenStatusStrings[] =
L"Moral",
L"Etat", // the condition of the current vehicle (its "Santé")
L"Carburant", // the fuel level of the current vehicle (its "energy")
L"Posion", // TODO.Translate
};
@@ -5093,6 +5100,7 @@ STR16 zOptionsToggleText[] =
L"Désactiver échange curseur", // Disable Cursor Swap
L"Quiet Training", // Madd: mercs don't say quotes while training // TODO.Translate
L"Auto Fast Forward AI Turns", // Automatic fast forward through AI turns // TODO.Translate
L"Allow Zombies", // Flugente Zombies 1.0
//L"Weapons Overheating", // TODO.Translate
L"--Cheat Mode Options--", // TOPTION_CHEAT_MODE_OPTIONS_HEADER,
L"Forcer envois Bobby Ray", // force all pending Bobby Ray shipments
@@ -5202,6 +5210,7 @@ STR16 zOptionsScreenHelpText[] =
L"Si activé, le curseur ne basculera pas entre changer de position et une autre action. Appuyez sur |x pour initier un échange rapide.",
L"When ON, mercs will not report progress during training.",
L"When ON, AI turns will be much faster.", // TODO.Translate
L"When ON, zombies will span. Be aware!", // allow zombies // TODO.Translate
//L"When ON, weapons can be overheated when firing.", // TODO.Translate
L"(text not rendered)TOPTION_CHEAT_MODE_OPTIONS_HEADER",
L"Forcer tous les envois en attente de Bobby Ray",
@@ -6894,6 +6903,7 @@ STR16 szUDBGenAmmoStatsTooltipText[]=
L"|C|u|l|b|u|t|e |d|e |b|a|l|l|e",
L"|P|r|e|-|I|m|p|a|c|t |E|x|p|l|o|s|i|o|n",
L"|T|e|m|p|e|r|a|t|u|r|e |M|o|d|i|f|i|c|a|t|i|o|n", // TODO.Translate
L"|P|o|i|s|o|n |P|e|r|c|e|n|t|a|g|e", // TODO.Translate
};
STR16 szUDBGenAmmoStatsExplanationsTooltipText[]=
@@ -6902,6 +6912,7 @@ STR16 szUDBGenAmmoStatsExplanationsTooltipText[]=
L"\n \nDétermine le potentiel de la balle à faire des dégâts\nsur le corps après avoir traversée l'armure.\n \nAvec une valeur supérieure à 1.0, la balle fera de lourds dégâts\naprès pénétration\nAvec une valeur inférieure à 1.0, la balle fera des dégâts moindre\naprès pénétration.\n \nValeur élevée recommandée.",
L"\n \nMultiplicateur de potentiel de dégâts juste avant\nl'impact de la balle.\n \nAvec une valeur supérieure à 1.0, la balle fera de lourds dégâts\nUne valeur inférieure à 1.0 fera des dégâts moindre.\n \nValeur élevée recommandée.",
L"\n \nAdditional heat generated by this ammunition.\n \nLower is better.", // TODO.Translate
L"\n \nDetermines what percentage of a\nbullet's damage will be poisonous.", // TODO.Translate
};
STR16 szUDBGenExplosiveStatsTooltipText[]=
@@ -7078,6 +7089,7 @@ STR16 szUDBAdvStatsTooltipText[]=
L"|C|o|o|l|d|o|w|n |M|o|d|i|f|i|e|r",
L"|J|a|m |T|h|r|e|s|h|o|l|d |M|o|d|i|f|i|e|r",
L"|D|a|m|a|g|e |T|h|r|e|s|h|o|l|d |M|o|d|i|f|i|e|r",
L"|P|o|i|s|o|n |P|e|r|c|e|n|t|a|g|e", // TODO.Translate
};
// Alternate tooltip text for weapon Advanced Stats. Just different wording, nothing spectacular.
@@ -7139,6 +7151,7 @@ STR16 szUDBAdvStatsExplanationsTooltipText[]=
L"\n \nA gun's cooldown factor is\nincreased by this percentage.\n \nHigher is better.",
L"\n \nA gun's jam threshold is\nincreased by this percentage.\n \nHigher is better.",
L"\n \nA gun's damage threshold is\nincreased by this percentage.\n \nHigher is better.",
L"\n \nThis is the percentage of damage dealt\nby this item that will be poisonous.\n\nUsefulness depends on wether enemy\nhas poison resistance or absorption.", // TODO.Translate
};
STR16 szUDBAdvStatsExplanationsTooltipTextForWeapons[]=
+12
View File
@@ -2080,6 +2080,8 @@ STR16 pPersonnelRecordsHelpTexts[] =
L"Schwächen:",
L"Persönlichkeit:", // WANNE: For old traits display instead of "Character:"!
L"Zombies: %d\n", // TODO.Translate
};
@@ -2866,6 +2868,7 @@ CHAR16 TacticalStr[][ MED_STRING_LENGTH ] =
L"MONSTER",
L"MILIZ",
L"ZIVILIST",
L"ZOMBIE", // TODO.Translate
L"Sektor verlassen",
L"OK",
L"Abbruch",
@@ -2923,6 +2926,9 @@ CHAR16 TacticalStr[][ MED_STRING_LENGTH ] =
L"Detonations-Frequenz (1 - 4) und die Entschärfungs-Frequenz (A - D):",
L"Detonations-Zeit (in Züge) (1 - 4) und die Entschärfungs-Frequenz (A - D):",
L"Stolperdraht-Hierarchie (1 - 4) und das Netzwerk (A - D):",
// added by Flugente to display health and poisoning // TODO.Translate
L"Health: %d/%d\n Poison: %d/%d\nEnergy: %d/%d\nMorale: %s",
};
//Varying helptext explains (for the "Go to Sector/Map" checkbox) what will happen given different circumstances in the "exiting sector" interface.
@@ -3440,6 +3446,7 @@ STR16 pMapScreenStatusStrings[] =
L"Moral",
L"Zustand", // the condition of the current vehicle (its "health")
L"Tank", // the fuel level of the current vehicle (its "energy")
L"Posion", // TODO.Translate
};
STR16 pMapScreenPrevNextCharButtonHelpText[] =
@@ -4951,6 +4958,7 @@ STR16 zOptionsToggleText[] =
L"Cursor-Wechsel deaktivieren", // Disable Cursor Swap
L"Stummes Trainieren", // Madd: mercs don't say quotes while training
L"Autom. schnelle Gegner-Züge", // Automatic fast forward through AI turns
L"Allow Zombies", // Flugente Zombies 1.0
//L"Waffen können überhitzen",
L"--Cheat Mode Options--", // TOPTION_CHEAT_MODE_OPTIONS_HEADER,
L"Erzwinge BR Lieferung", // force all pending Bobby Ray shipments
@@ -6739,6 +6747,7 @@ STR16 szUDBGenAmmoStatsTooltipText[]=
L"|K|u|g|e|l|s|t|u|r|z",
L"|E|x|p|l|o|s|i|o|n |v|o|r |E|i|n|s|c|h|l|a|g",
L"|T|e|m|p|e|r|a|t|u|r |M|o|d|i|f|i|k|a|t|o|r",
L"|P|o|i|s|o|n |P|e|r|c|e|n|t|a|g|e", // TODO.Translate
};
STR16 szUDBGenAmmoStatsExplanationsTooltipText[]=
@@ -6747,6 +6756,7 @@ STR16 szUDBGenAmmoStatsExplanationsTooltipText[]=
L"\n \nBestimmt eine verhältnismäßige Zunahme des Schadenspotentials,\nsobald die Kugel die Rüstung des Ziels\ndurchbricht und den Körper dahinter trifft.\n \nWerte über 1.0 erhöhen, Werte unter 1.0 reduzieren das Schadenspotential\nder durchbrochenen Kugel.\n \nHöher ist besser.",
L"\n \nEin Multiplikator zum Schadenspotential der Kugel,\nder vor dem Treffen des Zieles angewandt wird.\n \nWerte über 1.0 erhöhen, Werte unter 1.0 reduzieren den Schaden.\n \nHöher ist besser.",
L"\n \nProzentuale zusätzliche Hitze\ndurch diese Munitionsart.\n \nNiedriger ist besser.",
L"\n \nDetermines what percentage of a\nbullet's damage will be poisonous.", // TODO.Translate
};
STR16 szUDBGenExplosiveStatsTooltipText[]=
@@ -6923,6 +6933,7 @@ STR16 szUDBAdvStatsTooltipText[]=
L"|M|o|d|i|f|i|k|a|t|o|r|-|A|b|k|ü|h|l|f|a|k|t|o|r",
L"|M|o|d|i|f|i|k|a|t|o|r|-|L|a|d|e|h|e|m|m|u|n|g|s|s|c|h|r|a|n|k|e",
L"|M|o|d|i|f|i|k|a|t|o|r|-|H|i|t|z|e|s|c|h|a|d|e|n|s|s|c|h|r|a|n|k|e",
L"|P|o|i|s|o|n |P|e|r|c|e|n|t|a|g|e", // TODO.Translate
};
// Alternate tooltip text for weapon Advanced Stats. Just different wording, nothing spectacular.
@@ -6984,6 +6995,7 @@ STR16 szUDBAdvStatsExplanationsTooltipText[]=
L"\n \nAbkühlung wird um diesen Prozentsatz erhöht.\n \nHöher ist besser.",
L"\n \nLadehemmungsschranke wird um diesen Prozentsatz erhöht.\n \nHöher ist besser.",
L"\n \nHitzeschadensschranke wird um diesen Prozentsatz erhöht.\n \nHöher is besser.",
L"\n \nThis is the percentage of damage dealt\nby this item that will be poisonous.\n\nUsefulness depends on wether enemy\nhas poison resistance or absorption.", // TODO.Translate
};
STR16 szUDBAdvStatsExplanationsTooltipTextForWeapons[]=
+13
View File
@@ -2062,6 +2062,8 @@ STR16 pPersonnelRecordsHelpTexts[] =
L"Weakness:",
L"Attitudes:", // WANNE: For old traits display instead of "Character:"!
L"Zombies: %d\n", // TODO.Translate
};
@@ -2857,6 +2859,7 @@ CHAR16 TacticalStr[][ MED_STRING_LENGTH ] =
L"CREPITUS",
L"ESERCITO",
L"CIVILE",
L"ZOMBIE", // TODO.Translate
L"Settore di uscita",
L"OK",
L"Annulla",
@@ -2912,6 +2915,9 @@ CHAR16 TacticalStr[][ MED_STRING_LENGTH ] =
L"Set detonation frequency (1 - 4) and defusing frequency (A - D):",
L"Set detonation time in turns (1 - 4) and defusing frequency (A - D):",
L"Select tripwire hierarchy (1 - 4) and network (A - D):",
// added by Flugente to display health and poisoning // TODO.Translate
L"Health: %d/%d\n Poison: %d/%d\nEnergy: %d/%d\nMorale: %s",
};
//Varying helptext explains (for the "Go to Sector/Map" checkbox) what will happen given different circumstances in the "exiting sector" interface.
@@ -3464,6 +3470,7 @@ STR16 pMapScreenStatusStrings[] =
L"Morale",
L"Condizione", // the condition of the current vehicle (its "health")
L"Carburante", // the fuel level of the current vehicle (its "energy")
L"Posion", // TODO.Translate
};
@@ -5088,6 +5095,7 @@ STR16 zOptionsToggleText[] =
L"Disabilita Swap Cursore", // Disable Cursor Swap
L"Quiet Training", // Madd: mercs don't say quotes while training // TODO.Translate
L"Auto Fast Forward AI Turns", // Automatic fast forward through AI turns // TODO.Translate
L"Allow Zombies", // Flugente Zombies 1.0
//L"Weapons Overheating", // TODO.Translate
L"--Cheat Mode Options--", // TOPTION_CHEAT_MODE_OPTIONS_HEADER,
L"Force Bobby Ray shipments", // force all pending Bobby Ray shipments
@@ -5197,6 +5205,7 @@ STR16 zOptionsScreenHelpText[] =
L"Se attivato, il cursore non si alternerà tra la posizione di scambio e altre azioni. Premere |x per avviare lo scambio rapido.",
L"When ON, mercs will not report progress during training.",
L"When ON, AI turns will be much faster.", // TODO.Translate
L"When ON, zombies will span. Be aware!", // allow zombies // TODO.Translate
//L"When ON, weapons can be overheated when firing.", // TODO.Translate
L"(text not rendered)TOPTION_CHEAT_MODE_OPTIONS_HEADER",
L"Force all pending Bobby Ray shipments",
@@ -6907,6 +6916,7 @@ STR16 szUDBGenAmmoStatsTooltipText[]=
L"|B|u|l|l|e|t |T|u|m|b|l|e",
L"|P|r|e|-|I|m|p|a|c|t |E|x|p|l|o|s|i|o|n",
L"|T|e|m|p|e|r|a|t|u|r|e |M|o|d|i|f|i|c|a|t|i|o|n", // TODO.Translate
L"|P|o|i|s|o|n |P|e|r|c|e|n|t|a|g|e", // TODO.Translate
};
STR16 szUDBGenAmmoStatsExplanationsTooltipText[]=
@@ -6915,6 +6925,7 @@ STR16 szUDBGenAmmoStatsExplanationsTooltipText[]=
L"\n \nDetermines a proportional increase of damage\npotential once the bullet gets through the\ntarget's armor and hits the bodypart behind it.\n \nWhen above 1.0, the bullet's damage\nincreases after penetrating the armor.\n \nWhen below 1.0, the bullet's damage\npotential decreases after passing through armor.\n \nHigher is better.",
L"\n \nA multiplier to the bullet's damage potential\nthat is applied immediately before hitting the\ntarget.\n \nValues above 1.0 indicate an increase in damage,\nvalues below 1.0 indicate a decrease.\n \nHigher is better.",
L"\n \nAdditional heat generated by this ammunition.\n \nLower is better.", // TODO.Translate
L"\n \nDetermines what percentage of a\nbullet's damage will be poisonous.", // TODO.Translate
};
STR16 szUDBGenExplosiveStatsTooltipText[]=
@@ -7091,6 +7102,7 @@ STR16 szUDBAdvStatsTooltipText[]=
L"|C|o|o|l|d|o|w|n |M|o|d|i|f|i|e|r",
L"|J|a|m |T|h|r|e|s|h|o|l|d |M|o|d|i|f|i|e|r",
L"|D|a|m|a|g|e |T|h|r|e|s|h|o|l|d |M|o|d|i|f|i|e|r",
L"|P|o|i|s|o|n |P|e|r|c|e|n|t|a|g|e", // TODO.Translate
};
// Alternate tooltip text for weapon Advanced Stats. Just different wording, nothing spectacular.
@@ -7152,6 +7164,7 @@ STR16 szUDBAdvStatsExplanationsTooltipText[]=
L"\n \nA gun's cooldown factor is\nincreased by this percentage.\n \nHigher is better.",
L"\n \nA gun's jam threshold is\nincreased by this percentage.\n \nHigher is better.",
L"\n \nA gun's damage threshold is\nincreased by this percentage.\n \nHigher is better.",
L"\n \nThis is the percentage of damage dealt\nby this item that will be poisonous.\n\nUsefulness depends on wether enemy\nhas poison resistance or absorption.", // TODO.Translate
};
STR16 szUDBAdvStatsExplanationsTooltipTextForWeapons[]=
+13
View File
@@ -2077,6 +2077,8 @@ STR16 pPersonnelRecordsHelpTexts[] =
L"NiepełnosprawnoŚć:",
L"Attitudes:", // WANNE: For old traits display instead of "Character:"!
L"Zombies: %d\n", // TODO.Translate
};
@@ -2872,6 +2874,7 @@ CHAR16 TacticalStr[][ MED_STRING_LENGTH ] =
L"STWÓR",
L"SAMOOBRONA",
L"CYWIL",
L"ZOMBIE", // TODO.Translate
L"WyjŚcie z sektora",
L"OK",
L"Anuluj",
@@ -2927,6 +2930,9 @@ CHAR16 TacticalStr[][ MED_STRING_LENGTH ] =
L"Set detonation frequency (1 - 4) and defusing frequency (A - D):",
L"Set detonation time in turns (1 - 4) and defusing frequency (A - D):",
L"Select tripwire hierarchy (1 - 4) and network (A - D):",
// added by Flugente to display health and poisoning // TODO.Translate
L"Health: %d/%d\n Poison: %d/%d\nEnergy: %d/%d\nMorale: %s",
};
//Varying helptext explains (for the "Go to Sector/Map" checkbox) what will happen given different circumstances in the "exiting sector" interface.
@@ -3480,6 +3486,7 @@ STR16 pMapScreenStatusStrings[] =
L"Morale",
L"Stan", // the condition of the current vehicle (its "health")
L"Paliwo", // the fuel level of the current vehicle (its "energy")
L"Posion", // TODO.Translate
};
@@ -5100,6 +5107,7 @@ STR16 zOptionsToggleText[] =
L"Disable Cursor Swap", // Disable Cursor Swap // TODO.Translate
L"Quiet Training", // Madd: mercs don't say quotes while training // TODO.Translate
L"Auto Fast Forward AI Turns", // Automatic fast forward through AI turns // TODO.Translate
L"Allow Zombies", // Flugente Zombies 1.0
//L"Weapons Overheating", // TODO.Translate
L"--Cheat Mode Options--", // TOPTION_CHEAT_MODE_OPTIONS_HEADER,
L"Force Bobby Ray shipments", // force all pending Bobby Ray shipments
@@ -5209,6 +5217,7 @@ STR16 zOptionsScreenHelpText[] =
L"When ON, the cursor will not toggle between exchange position and other actions. Press |x to initiate quick exchange.", // TODO.Translate
L"When ON, mercs will not report progress during training.",
L"When ON, AI turns will be much faster.", // TODO.Translate
L"When ON, zombies will span. Be aware!", // allow zombies // TODO.Translate
//L"When ON, weapons can be overheated when firing.", // TODO.Translate
L"(text not rendered)TOPTION_CHEAT_MODE_OPTIONS_HEADER",
L"WymuŚ wszystkie oczekiwane dostawy od Bobby Ray's.",
@@ -6917,6 +6926,7 @@ STR16 szUDBGenAmmoStatsTooltipText[]=
L"|B|u|l|l|e|t |T|u|m|b|l|e",
L"|P|r|e|-|I|m|p|a|c|t |E|x|p|l|o|s|i|o|n",
L"|T|e|m|p|e|r|a|t|u|r|e |M|o|d|i|f|i|c|a|t|i|o|n", // TODO.Translate
L"|P|o|i|s|o|n |P|e|r|c|e|n|t|a|g|e", // TODO.Translate
};
STR16 szUDBGenAmmoStatsExplanationsTooltipText[]=
@@ -6925,6 +6935,7 @@ STR16 szUDBGenAmmoStatsExplanationsTooltipText[]=
L"\n \nDetermines a proportional increase of damage\npotential once the bullet gets through the\ntarget's armor and hits the bodypart behind it.\n \nWhen above 1.0, the bullet's damage\nincreases after penetrating the armor.\n \nWhen below 1.0, the bullet's damage\npotential decreases after passing through armor.\n \nHigher is better.",
L"\n \nA multiplier to the bullet's damage potential\nthat is applied immediately before hitting the\ntarget.\n \nValues above 1.0 indicate an increase in damage,\nvalues below 1.0 indicate a decrease.\n \nHigher is better.",
L"\n \nAdditional heat generated by this ammunition.\n \nLower is better.", // TODO.Translate
L"\n \nDetermines what percentage of a\nbullet's damage will be poisonous.", // TODO.Translate
};
STR16 szUDBGenExplosiveStatsTooltipText[]=
@@ -7101,6 +7112,7 @@ STR16 szUDBAdvStatsTooltipText[]=
L"|C|o|o|l|d|o|w|n |M|o|d|i|f|i|e|r",
L"|J|a|m |T|h|r|e|s|h|o|l|d |M|o|d|i|f|i|e|r",
L"|D|a|m|a|g|e |T|h|r|e|s|h|o|l|d |M|o|d|i|f|i|e|r",
L"|P|o|i|s|o|n |P|e|r|c|e|n|t|a|g|e", // TODO.Translate
};
// Alternate tooltip text for weapon Advanced Stats. Just different wording, nothing spectacular.
@@ -7162,6 +7174,7 @@ STR16 szUDBAdvStatsExplanationsTooltipText[]=
L"\n \nA gun's cooldown factor is\nincreased by this percentage.\n \nHigher is better.",
L"\n \nA gun's jam threshold is\nincreased by this percentage.\n \nHigher is better.",
L"\n \nA gun's damage threshold is\nincreased by this percentage.\n \nHigher is better.",
L"\n \nThis is the percentage of damage dealt\nby this item that will be poisonous.\n\nUsefulness depends on wether enemy\nhas poison resistance or absorption.", // TODO.Translate
};
STR16 szUDBAdvStatsExplanationsTooltipTextForWeapons[]=
+13
View File
@@ -2070,6 +2070,8 @@ STR16 pPersonnelRecordsHelpTexts[] =
L"Недостаток:",
L"По жизни:", //Attitudes For old traits display instead of "Character:"!
L"Zombies: %d\n", // TODO.Translate
};
@@ -2865,6 +2867,7 @@ CHAR16 TacticalStr[][ MED_STRING_LENGTH ] =
L"РЕПТИОН",
L"ОПОЛЧЕНЕЦ",
L"ЖИТЕЛЬ",
L"ZOMBIE", // TODO.Translate
L"Выход из сектора",
L"ДА",
L"ОТМЕНА",
@@ -2920,6 +2923,9 @@ CHAR16 TacticalStr[][ MED_STRING_LENGTH ] =
L"Set detonation frequency (1 - 4) and defusing frequency (A - D):",
L"Set detonation time in turns (1 - 4) and defusing frequency (A - D):",
L"Select tripwire hierarchy (1 - 4) and network (A - D):",
// added by Flugente to display health and poisoning // TODO.Translate
L"Health: %d/%d\n Poison: %d/%d\nEnergy: %d/%d\nMorale: %s",
};
//Varying helptext explains (for the "Go to Sector/Map" checkbox) what will happen given different circumstances in the "exiting sector" interface.
@@ -3473,6 +3479,7 @@ STR16 pMapScreenStatusStrings[] =
L"Боевой дух",
L"Состояние", // the condition of the current vehicle (its "health")
L"Бензин", // the fuel level of the current vehicle (its "energy")
L"Posion", // TODO.Translate
};
@@ -5083,6 +5090,7 @@ STR16 zOptionsToggleText[] =
L"Disable Cursor Swap", // Disable Cursor Swap // TODO.Translate
L"Quiet Training", // Madd: mercs don't say quotes while training // TODO.Translate
L"Auto Fast Forward AI Turns", // Automatic fast forward through AI turns // TODO.Translate
L"Allow Zombies", // Flugente Zombies 1.0
//L"Weapons Overheating", // TODO.Translate
L"--Читерские настройки--", // TOPTION_CHEAT_MODE_OPTIONS_HEADER,
L"Ускорить доставку Бобби Рэя", // force all pending Bobby Ray shipments
@@ -5192,6 +5200,7 @@ STR16 zOptionsScreenHelpText[] =
L"When ON, the cursor will not toggle between exchange position and other actions. Press |x to initiate quick exchange.", // TODO.Translate
L"When ON, mercs will not report progress during training.",
L"When ON, AI turns will be much faster.", // TODO.Translate
L"When ON, zombies will span. Be aware!", // allow zombies // TODO.Translate
//L"When ON, weapons can be overheated when firing.", // TODO.Translate
L"(text not rendered)TOPTION_CHEAT_MODE_OPTIONS_HEADER",
L"Выберите этот пункт чтобы груз Бобби Рэя прибыл немедленно.",
@@ -6885,6 +6894,7 @@ STR16 szUDBGenAmmoStatsTooltipText[]=
L"|П|а|д|е|н|и|е |п|а|т|р|о|н|ы",
L"|П|р|е|д|в|а|р|и|т|е|л|ь|н|о|е |в|л|и|я|н|и|е |в|з|р|ы|в|а",
L"|T|e|m|p|e|r|a|t|u|r|e |M|o|d|i|f|i|c|a|t|i|o|n", // TODO.Translate
L"|P|o|i|s|o|n |P|e|r|c|e|n|t|a|g|e", // TODO.Translate
};
STR16 szUDBGenAmmoStatsExplanationsTooltipText[]=
@@ -6893,6 +6903,7 @@ STR16 szUDBGenAmmoStatsExplanationsTooltipText[]=
L"\n \nDetermines a proportional increase of damage\npotential once the bullet gets through the\ntarget's armor and hits the bodypart behind it.\n \nWhen above 1.0, the bullet's damage\nincreases after penetrating the armor.\n \nWhen below 1.0, the bullet's damage\npotential decreases after passing through armor.\n \nHigher is better.",
L"\n \nA multiplier to the bullet's damage potential\nthat is applied immediately before hitting the\ntarget.\n \nValues above 1.0 indicate an increase in damage,\nvalues below 1.0 indicate a decrease.\n \nHigher is better.",
L"\n \nAdditional heat generated by this ammunition.\n \nLower is better.", // TODO.Translate
L"\n \nDetermines what percentage of a\nbullet's damage will be poisonous.", // TODO.Translate
};
STR16 szUDBGenExplosiveStatsTooltipText[]=
@@ -7069,6 +7080,7 @@ STR16 szUDBAdvStatsTooltipText[]=
L"|C|o|o|l|d|o|w|n |M|o|d|i|f|i|e|r",
L"|J|a|m |T|h|r|e|s|h|o|l|d |M|o|d|i|f|i|e|r",
L"|D|a|m|a|g|e |T|h|r|e|s|h|o|l|d |M|o|d|i|f|i|e|r",
L"|P|o|i|s|o|n |P|e|r|c|e|n|t|a|g|e", // TODO.Translate
};
// Alternate tooltip text for weapon Advanced Stats. Just different wording, nothing spectacular.
@@ -7130,6 +7142,7 @@ STR16 szUDBAdvStatsExplanationsTooltipText[]=
L"\n \nA gun's cooldown factor is\nincreased by this percentage.\n \nHigher is better.",
L"\n \nA gun's jam threshold is\nincreased by this percentage.\n \nHigher is better.",
L"\n \nA gun's damage threshold is\nincreased by this percentage.\n \nHigher is better.",
L"\n \nThis is the percentage of damage dealt\nby this item that will be poisonous.\n\nUsefulness depends on wether enemy\nhas poison resistance or absorption.", // TODO.Translate
};
STR16 szUDBAdvStatsExplanationsTooltipTextForWeapons[]=
+13
View File
@@ -2070,6 +2070,8 @@ STR16 pPersonnelRecordsHelpTexts[] =
L"Weakness:",
L"Attitudes:", // WANNE: For old traits display instead of "Character:"!
L"Zombies: %d\n", // TODO.Translate
};
@@ -2866,6 +2868,7 @@ CHAR16 TacticalStr[][ MED_STRING_LENGTH ] =
L"CREPITUS",
L"MILITIA",
L"CIVILIAN",
L"ZOMBIE", // TODO.Translate
L"Exiting Sector",
L"OK",
L"Cancel",
@@ -2921,6 +2924,9 @@ CHAR16 TacticalStr[][ MED_STRING_LENGTH ] =
L"Set detonation frequency (1 - 4) and defusing frequency (A - D):",
L"Set detonation time in turns (1 - 4) and defusing frequency (A - D):",
L"Select tripwire hierarchy (1 - 4) and network (A - D):",
// added by Flugente to display health and poisoning // TODO.Translate
L"Health: %d/%d\n Poison: %d/%d\nEnergy: %d/%d\nMorale: %s",
};
//Varying helptext explains (for the "Go to Sector/Map" checkbox) what will happen given different circumstances in the "exiting sector" interface.
@@ -3474,6 +3480,7 @@ STR16 pMapScreenStatusStrings[] =
L"Morale",
L"Condition", // the condition of the current vehicle (its "health")
L"Fuel", // the fuel level of the current vehicle (its "energy")
L"Posion", // TODO.Translate
};
@@ -5104,6 +5111,7 @@ STR16 zOptionsToggleText[] =
L"Disable Cursor Swap", // Disable Cursor Swap
L"Quiet Training", // Madd: mercs don't say quotes while training // TODO.Translate
L"Auto Fast Forward AI Turns", // Automatic fast forward through AI turns // TODO.Translate
L"Allow Zombies", // Flugente Zombies 1.0
//L"Weapons Overheating", // TODO.Translate
L"--Cheat Mode Options--", // TOPTION_CHEAT_MODE_OPTIONS_HEADER,
L"Force Bobby Ray shipments", // force all pending Bobby Ray shipments
@@ -5213,6 +5221,7 @@ STR16 zOptionsScreenHelpText[] =
L"When ON, the cursor will not toggle between exchange position and other actions. Press |x to initiate quick exchange.",
L"When ON, mercs will not report progress during training.",
L"When ON, AI turns will be much faster.", // TODO.Translate
L"When ON, zombies will span. Be aware!", // allow zombies // TODO.Translate
//L"When ON, weapons can be overheated when firing.", // TODO.Translate
L"(text not rendered)TOPTION_CHEAT_MODE_OPTIONS_HEADER",
L"Force all pending Bobby Ray shipments",
@@ -6922,6 +6931,7 @@ STR16 szUDBGenAmmoStatsTooltipText[]=
L"|B|u|l|l|e|t |T|u|m|b|l|e",
L"|P|r|e|-|I|m|p|a|c|t |E|x|p|l|o|s|i|o|n",
L"|T|e|m|p|e|r|a|t|u|r|e |M|o|d|i|f|i|c|a|t|i|o|n", // TODO.Translate
L"|P|o|i|s|o|n |P|e|r|c|e|n|t|a|g|e", // TODO.Translate
};
STR16 szUDBGenAmmoStatsExplanationsTooltipText[]=
@@ -6930,6 +6940,7 @@ STR16 szUDBGenAmmoStatsExplanationsTooltipText[]=
L"\n \nDetermines a proportional increase of damage\npotential once the bullet gets through the\ntarget's armor and hits the bodypart behind it.\n \nWhen above 1.0, the bullet's damage\nincreases after penetrating the armor.\n \nWhen below 1.0, the bullet's damage\npotential decreases after passing through armor.\n \nHigher is better.",
L"\n \nA multiplier to the bullet's damage potential\nthat is applied immediately before hitting the\ntarget.\n \nValues above 1.0 indicate an increase in damage,\nvalues below 1.0 indicate a decrease.\n \nHigher is better.",
L"\n \nAdditional heat generated by this ammunition.\n \nLower is better.", // TODO.Translate
L"\n \nDetermines what percentage of a\nbullet's damage will be poisonous.", // TODO.Translate
};
STR16 szUDBGenExplosiveStatsTooltipText[]=
@@ -7106,6 +7117,7 @@ STR16 szUDBAdvStatsTooltipText[]=
L"|C|o|o|l|d|o|w|n |M|o|d|i|f|i|e|r",
L"|J|a|m |T|h|r|e|s|h|o|l|d |M|o|d|i|f|i|e|r",
L"|D|a|m|a|g|e |T|h|r|e|s|h|o|l|d |M|o|d|i|f|i|e|r",
L"|P|o|i|s|o|n |P|e|r|c|e|n|t|a|g|e", // TODO.Translate
};
// Alternate tooltip text for weapon Advanced Stats. Just different wording, nothing spectacular.
@@ -7167,6 +7179,7 @@ STR16 szUDBAdvStatsExplanationsTooltipText[]=
L"\n \nA gun's cooldown factor is\nincreased by this percentage.\n \nHigher is better.",
L"\n \nA gun's jam threshold is\nincreased by this percentage.\n \nHigher is better.",
L"\n \nA gun's damage threshold is\nincreased by this percentage.\n \nHigher is better.",
L"\n \nThis is the percentage of damage dealt\nby this item that will be poisonous.\n\nUsefulness depends on wether enemy\nhas poison resistance or absorption.", // TODO.Translate
};
STR16 szUDBAdvStatsExplanationsTooltipTextForWeapons[]=