mirror of
https://github.com/1dot13/source.git
synced 2026-08-19 14:20:30 +02:00
- 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:
@@ -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 ) ) );
|
||||
|
||||
@@ -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 )
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 );
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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
@@ -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++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 ) )
|
||||
{
|
||||
|
||||
@@ -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 );
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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 );
|
||||
|
||||
@@ -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
@@ -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.
|
||||
|
||||
@@ -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
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
@@ -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
@@ -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 );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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 )
|
||||
|
||||
@@ -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 )
|
||||
|
||||
@@ -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 );
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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 );
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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++;
|
||||
|
||||
@@ -262,6 +262,7 @@ public:
|
||||
UINT16 usKillsAdmins;
|
||||
UINT16 usKillsHostiles;
|
||||
UINT16 usKillsCreatures;
|
||||
UINT16 usKillsZombies;
|
||||
UINT16 usKillsTanks;
|
||||
UINT16 usKillsOthers;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user