mirror of
https://github.com/1dot13/source.git
synced 2026-07-22 13:40:22 +02:00
New feature: riot shields protect against damage from some directions.
For more info, see http://thepit.ja-galaxy-forum.com/index.php?t=msg&th=23452&start=0& git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@8434 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
@@ -3148,6 +3148,9 @@ void LoadItemSettings()
|
||||
gItemSettings.fDamageBreathModifierExplosive = iniReader.ReadFloat ("Explosives Settings","DAMAGE_BREATH_EXPLOSIVE_MODIFIER", 1.0f, 0.1f, 5.0f);
|
||||
gItemSettings.fDamageHealthMoveModifierExplosive = iniReader.ReadFloat ("Explosives Settings","DAMAGE_HEALTH_MOVE_EXPLOSIVE_MODIFIER", 0.1f, 0.0f, 1.0f);
|
||||
gItemSettings.fDamageBreathMoveModifierExplosive = iniReader.ReadFloat ("Explosives Settings","DAMAGE_BREATH_MOVE_EXPLOSIVE_MODIFIER", 0.1f, 0.0f, 1.0f);
|
||||
|
||||
// ------------ MISC MODIFIERS --------------
|
||||
gItemSettings.fShieldMovementAPCostModifier = iniReader.ReadFloat ("Misc Settings", "SHIELD_MOVEMENT_APCOST_MODIFIER", 1.7f, 1.0f, 10.0f );
|
||||
}
|
||||
|
||||
INT16 DynamicAdjustAPConstants(INT16 iniReadValue, INT16 iniDefaultValue, BOOLEAN reverse)
|
||||
|
||||
@@ -2376,6 +2376,10 @@ typedef struct
|
||||
FLOAT fDamageHealthMoveModifierExplosive; // applies when character moves through gas cloud without a gas mask
|
||||
FLOAT fDamageBreathMoveModifierExplosive; // applies when character moves through gas cloud without a gas mask
|
||||
|
||||
// ------------ MISC MODIFIERS --------------
|
||||
// Flugente
|
||||
FLOAT fShieldMovementAPCostModifier; // movement AP costs are multiplied with this while a shield is equipped
|
||||
|
||||
}ITEM_SETTINGS;
|
||||
|
||||
extern MOD_SETTINGS gModSettings;
|
||||
|
||||
+9
-9
@@ -15,9 +15,9 @@
|
||||
#ifdef JA2EDITOR
|
||||
|
||||
#ifdef JA2UB
|
||||
CHAR16 zVersionLabel[256] = { L"Unfinished Business - Map Editor v1.13.8405 (Development Build)" };
|
||||
CHAR16 zVersionLabel[256] = { L"Unfinished Business - Map Editor v1.13.8434 (Development Build)" };
|
||||
#else
|
||||
CHAR16 zVersionLabel[256] = { L"Map Editor v1.13.8405 (Development Build)" };
|
||||
CHAR16 zVersionLabel[256] = { L"Map Editor v1.13.8434 (Development Build)" };
|
||||
#endif
|
||||
|
||||
// ------------------------------
|
||||
@@ -27,11 +27,11 @@
|
||||
|
||||
//DEBUG BUILD VERSION
|
||||
#ifdef JA2UB
|
||||
CHAR16 zVersionLabel[256] = { L"Debug: Unfinished Business - v1.13.8405 (Development Build)" };
|
||||
CHAR16 zVersionLabel[256] = { L"Debug: Unfinished Business - v1.13.8434 (Development Build)" };
|
||||
#elif defined (JA113DEMO)
|
||||
CHAR16 zVersionLabel[256] = { L"Debug: JA2 Demo - v1.13.8405 (Development Build)" };
|
||||
CHAR16 zVersionLabel[256] = { L"Debug: JA2 Demo - v1.13.8434 (Development Build)" };
|
||||
#else
|
||||
CHAR16 zVersionLabel[256] = { L"Debug: v1.13.8405 (Development Build)" };
|
||||
CHAR16 zVersionLabel[256] = { L"Debug: v1.13.8434 (Development Build)" };
|
||||
#endif
|
||||
|
||||
#elif defined CRIPPLED_VERSION
|
||||
@@ -46,16 +46,16 @@
|
||||
|
||||
//RELEASE BUILD VERSION
|
||||
#ifdef JA2UB
|
||||
CHAR16 zVersionLabel[256] = { L"Release Unfinished Business - v1.13.8405 (Development Build)" };
|
||||
CHAR16 zVersionLabel[256] = { L"Release Unfinished Business - v1.13.8434 (Development Build)" };
|
||||
#elif defined (JA113DEMO)
|
||||
CHAR16 zVersionLabel[256] = { L"Release JA2 Demo - v1.13.8405 (Development Build)" };
|
||||
CHAR16 zVersionLabel[256] = { L"Release JA2 Demo - v1.13.8434 (Development Build)" };
|
||||
#else
|
||||
CHAR16 zVersionLabel[256] = { L"Release v1.13.8405 (Development Build)" };
|
||||
CHAR16 zVersionLabel[256] = { L"Release v1.13.8434 (Development Build)" };
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
CHAR8 czVersionNumber[16] = { "Build 17.06.12" }; //YY.MM.DD
|
||||
CHAR8 czVersionNumber[16] = { "Build 17.07.29" }; //YY.MM.DD
|
||||
CHAR16 zTrackingNumber[16] = { L"Z" };
|
||||
|
||||
// SAVE_GAME_VERSION is defined in header, change it there
|
||||
|
||||
@@ -2714,6 +2714,15 @@ void InternalInitEDBTooltipRegion( OBJECTTYPE * gpItemDescObject, UINT32 guiCurr
|
||||
cnt++;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////// SHIELD
|
||||
if ( Item[gpItemDescObject->usItem].usRiotShieldStrength > 0 )
|
||||
{
|
||||
swprintf( pStr, L"%s%s", szUDBGenSecondaryStatsTooltipText[40], szUDBGenSecondaryStatsExplanationsTooltipText[40] );
|
||||
SetRegionFastHelpText( &(gUDBFasthelpRegions[iFirstDataRegion + cnt]), pStr );
|
||||
MSYS_EnableRegion( &gUDBFasthelpRegions[iFirstDataRegion + cnt] );
|
||||
++cnt;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
@@ -6255,6 +6264,14 @@ void DrawSecondaryStats( OBJECTTYPE * gpItemDescObject )
|
||||
++cnt;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////// SHIELD
|
||||
if ( (Item[gpItemDescObject->usItem].usRiotShieldStrength > 0 && !fComparisonMode) ||
|
||||
(fComparisonMode && Item[gpComparedItemDescObject->usItem].usRiotShieldStrength > 0) )
|
||||
{
|
||||
BltVideoObjectFromIndex( guiSAVEBUFFER, guiItemInfoSecondaryIcon, 38, gItemDescGenSecondaryRegions[cnt].sLeft + sOffsetX, gItemDescGenSecondaryRegions[cnt].sTop + sOffsetY, VO_BLT_SRCTRANSPARENCY, NULL );
|
||||
++cnt;
|
||||
}
|
||||
}
|
||||
|
||||
void DrawPropertyValueInColour( INT16 iValue, UINT8 ubNumLine, UINT8 ubNumRegion, BOOLEAN fComparisonMode, BOOLEAN fModifier, BOOLEAN fHigherBetter, UINT16 uiOverwriteColour = 0, BOOLEAN fPercentSign = FALSE )
|
||||
|
||||
@@ -2571,6 +2571,105 @@ return( iImpact );
|
||||
}
|
||||
*/
|
||||
|
||||
// Flugente: riot shields
|
||||
void DamageRiotShield( SOLDIERTYPE* pSoldier, INT32& rsDamage, INT32& rsSecondaryDamage )
|
||||
{
|
||||
if ( !pSoldier )
|
||||
return;
|
||||
|
||||
OBJECTTYPE* pObj = pSoldier->GetEquippedRiotShield( );
|
||||
if ( pObj && rsDamage > 0 && Item[pObj->usItem].usRiotShieldStrength > 0 )
|
||||
{
|
||||
INT32 damage_original = rsDamage;
|
||||
|
||||
UINT16 shieldstrength = Item[pObj->usItem].usRiotShieldStrength;
|
||||
|
||||
UINT16 damagetoshield = 2 * damage_original / shieldstrength;
|
||||
|
||||
pSoldier->RiotShieldTakeDamage( damagetoshield );
|
||||
|
||||
INT32 damage_new = max( 0, min( damage_original, ((100.0f - shieldstrength) / 100.0f) * (damage_original - shieldstrength) ) );
|
||||
|
||||
if ( rsSecondaryDamage > 0 )
|
||||
rsSecondaryDamage = max( 0, rsSecondaryDamage * damage_new / damage_original );
|
||||
|
||||
rsDamage = damage_new;
|
||||
}
|
||||
}
|
||||
|
||||
// Flugente: handle bullet impact on riot shield. Returns true if bullet should be removed
|
||||
BOOLEAN DamageRiotShield_Bullet( SOLDIERTYPE* pSoldier, BULLET* pBullet )
|
||||
{
|
||||
UINT16 ubAmmoType = 0;
|
||||
|
||||
SOLDIERTYPE * pFirer = NULL;
|
||||
if ( pBullet->ubFirerID != NOBODY )
|
||||
pFirer = pBullet->pFirer;
|
||||
|
||||
// HEADROCK HAM 5: Fragments read attacking weapon from explosive, not from firer. Theoretically,
|
||||
// all bullets should read this value...
|
||||
UINT16 usAttackingWeapon = 0;
|
||||
if ( pBullet->ubFirerID == NOBODY || pBullet->fFragment )
|
||||
{
|
||||
usAttackingWeapon = pBullet->fromItem;
|
||||
}
|
||||
else
|
||||
{
|
||||
usAttackingWeapon = pFirer->usAttackingWeapon;
|
||||
}
|
||||
|
||||
if ( pBullet->usFlags & BULLET_FLAG_KNIFE )
|
||||
{
|
||||
UINT16 usItem = (Item[pBullet->fromItem].bloodieditem>0 ? Item[pBullet->fromItem].bloodieditem : pBullet->fromItem);
|
||||
UINT16 usItemStatus = (pBullet->ubItemStatus>1 ? pBullet->ubItemStatus - Random( 2 ) : pBullet->ubItemStatus);
|
||||
|
||||
// Add item
|
||||
CreateItem( usItem, usItemStatus, &gTempObject );
|
||||
AddItemToPool( pSoldier->sGridNo, &gTempObject, -1, pSoldier->pathing.bLevel, 0, 0 );
|
||||
|
||||
// Make team look for items
|
||||
NotifySoldiersToLookforItems( );
|
||||
|
||||
// Flugente: if this guy has the disease, or the blade was already infected, the new one will be too
|
||||
if ( pSoldier->sDiseasePoints[0] > 0 || pBullet->usFlags & BULLET_FLAG_INFECTED )
|
||||
(*&gTempObject)[0]->data.sObjectFlag |= INFECTED;
|
||||
|
||||
ubAmmoType = AMMO_KNIFE;
|
||||
|
||||
// as we've already stopped the bullet, get out of here
|
||||
return TRUE;
|
||||
}
|
||||
else if ( pBullet->fFragment )
|
||||
{
|
||||
// Read ammo type from the explosive data.
|
||||
ubAmmoType = Explosive[Item[usAttackingWeapon].ubClassIndex].ubFragType;
|
||||
}
|
||||
else
|
||||
{
|
||||
ubAmmoType = AMMO_REGULAR;
|
||||
|
||||
if ( pFirer )
|
||||
ubAmmoType = pFirer->inv[pFirer->ubAttackingHand][0]->data.gun.ubGunAmmoType;
|
||||
}
|
||||
|
||||
INT32 impact_original = max(0, pBullet->iImpact - pBullet->iImpactReduction);
|
||||
|
||||
FLOAT damagepercentage = (FLOAT)((FLOAT)AmmoTypes[ubAmmoType].armourImpactReductionDivisor / (FLOAT)max( 1, AmmoTypes[ubAmmoType].armourImpactReductionMultiplier ));
|
||||
|
||||
damagepercentage *= 1.0f + max( AmmoTypes[ubAmmoType].dDamageModifierArmouredVehicle, AmmoTypes[ubAmmoType].dDamageModifierTank );
|
||||
|
||||
INT32 impact_new = impact_original * damagepercentage;
|
||||
|
||||
INT32 tmp = 0;
|
||||
DamageRiotShield( pSoldier, impact_new, tmp );
|
||||
|
||||
INT32 impactreduction = impact_original - impact_new / damagepercentage;
|
||||
|
||||
pBullet->iImpactReduction += impactreduction;
|
||||
|
||||
return (pBullet->iImpact <= pBullet->iImpactReduction);
|
||||
}
|
||||
|
||||
BOOLEAN BulletHitMerc( BULLET * pBullet, STRUCTURE * pStructure, BOOLEAN fIntended )
|
||||
{
|
||||
INT32 iImpact, iDamage;
|
||||
@@ -6365,6 +6464,8 @@ void MoveBullet( INT32 iBullet )
|
||||
FIXEDPT qWindowBottomHeight;
|
||||
FIXEDPT qWindowTopHeight;
|
||||
|
||||
UINT16 lastriotshieldholder = NOBODY; // added by Flugente
|
||||
|
||||
pBullet = GetBulletPtr( iBullet );
|
||||
|
||||
// CHECK MIN TIME ELAPSED
|
||||
@@ -6913,6 +7014,33 @@ void MoveBullet( INT32 iBullet )
|
||||
pStructure = gpLocalStructure[iStructureLoop];
|
||||
if (pStructure && pStructure->sCubeOffset == sDesiredLevel)
|
||||
{
|
||||
// Flugente: a riot shield would cover the entire front of a tile. We thus cannot check whether the person would be hit, as the bullet might miss a soldier
|
||||
// Instead, we check whether the structure is indeed a person, whether that person has a riot shield equipped, and whether that shield faces the bullet before it would hit the soldier
|
||||
// the same bullet cannot hit a shield multiple times
|
||||
if ( lastriotshieldholder != pStructure->usStructureID && pStructure->fFlags & STRUCTURE_PERSON )
|
||||
{
|
||||
SOLDIERTYPE* pTarget = MercPtrs[pStructure->usStructureID];
|
||||
|
||||
lastriotshieldholder = pStructure->usStructureID;
|
||||
|
||||
// check for riot shield contact
|
||||
if ( pTarget && pTarget->IsRiotShieldEquipped( ) )
|
||||
{
|
||||
UINT8 bulletdir_inverse = GetDirectionToGridNoFromGridNo( pTarget->sGridNo, pBullet->sOrigGridNo );
|
||||
|
||||
// check whether the opposite direction of the bullet is the direction the soldier looks, or adjacant to that. That would mean the shield is between bullet and soldier
|
||||
if ( bulletdir_inverse == pTarget->ubDirection || bulletdir_inverse == gOneCCDirection[pTarget->ubDirection] || bulletdir_inverse == gOneCDirection[pTarget->ubDirection] )
|
||||
{
|
||||
if ( DamageRiotShield_Bullet( pTarget, pBullet ) )
|
||||
{
|
||||
RemoveBullet( pBullet->iBullet );
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (((*(pStructure->pShape))[pBullet->bLOSIndexX][pBullet->bLOSIndexY] & AtHeight[iCurrCubesAboveLevelZ]) > 0)
|
||||
{
|
||||
if (pStructure->fFlags & STRUCTURE_PERSON)
|
||||
@@ -7103,6 +7231,32 @@ void MoveBullet( INT32 iBullet )
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Flugente: a riot shield would cover the entire front of a tile. We thus cannot check whether the person would be hit, as the bullet might miss a soldier
|
||||
// Instead, we check whether the structure is indeed a person, whether that person has a riot shield equipped, and whether that shield faces the bullet before it would hit the soldier
|
||||
if ( lastriotshieldholder != pStructure->usStructureID && pStructure->fFlags & STRUCTURE_PERSON )
|
||||
{
|
||||
SOLDIERTYPE* pTarget = MercPtrs[pStructure->usStructureID];
|
||||
|
||||
lastriotshieldholder = pStructure->usStructureID;
|
||||
|
||||
// check for riot shield contact
|
||||
if ( pTarget && pTarget->IsRiotShieldEquipped( ) )
|
||||
{
|
||||
UINT8 bulletdir = GetDirectionToGridNoFromGridNo( pBullet->sOrigGridNo, pTarget->sGridNo );
|
||||
|
||||
// check whether the direction of the bullet is the direction the soldier looks, or adjacant to that. That would mean the shield is hit after the and soldier
|
||||
if ( bulletdir == pTarget->ubDirection || bulletdir == gOneCCDirection[pTarget->ubDirection] || bulletdir == gOneCDirection[pTarget->ubDirection] )
|
||||
{
|
||||
if ( DamageRiotShield_Bullet( pTarget, pBullet ) )
|
||||
{
|
||||
RemoveBullet( pBullet->iBullet );
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -248,4 +248,7 @@ void CalcRecoilOffset( SOLDIERTYPE *pShooter, FLOAT *dMuzzleOffsetX, FLOAT *dMuz
|
||||
// HEADROCK HAM 5: New function, completely replaces the Counter Force Frequency check.
|
||||
FLOAT CalcCounterForceChange( SOLDIERTYPE * pShooter, UINT32 uiCounterForceAccuracy, FLOAT dCounterForceMax, FLOAT dMuzzleOffset, FLOAT bRecoil, FLOAT dPrevCounterForce, UINT32 uiIntendedBullets );
|
||||
|
||||
// Flugente: riot shields
|
||||
void DamageRiotShield( SOLDIERTYPE* pSoldier, INT32& rsDamage, INT32& rsSecondaryDamage );
|
||||
|
||||
#endif
|
||||
@@ -1404,6 +1404,12 @@ INT16 AStarPathfinder::CalcAP(int const terrainCost, UINT8 const direction)
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Flugente: riot shields lower movement speed
|
||||
if ( pSoldier->IsRiotShieldEquipped( ) )
|
||||
{
|
||||
movementAPCost *= gItemSettings.fShieldMovementAPCostModifier;
|
||||
}
|
||||
|
||||
if (terrainCost == TRAVELCOST_FENCE)
|
||||
{
|
||||
switch( movementModeToUseForAPs )
|
||||
@@ -3629,6 +3635,12 @@ if(!GridNoOnVisibleWorldTile(iDestination))
|
||||
if ( TERRAIN_IS_HIGH_WATER( gpWorldLevelData[ newLoc ].ubTerrainID ) )
|
||||
ubAPCost = (ubAPCost * (100 + s->GetBackgroundValue(BG_SWIMMING))) / 100;
|
||||
|
||||
// Flugente: riot shields lower movement speed
|
||||
if ( s->IsRiotShieldEquipped( ) )
|
||||
{
|
||||
ubAPCost *= gItemSettings.fShieldMovementAPCostModifier;
|
||||
}
|
||||
|
||||
// SANDRO - moved backpack check to here
|
||||
// Moa: backpack penalty
|
||||
//if((UsingNewInventorySystem() == true) && FindBackpackOnSoldier( s ) != ITEM_NOT_FOUND )
|
||||
@@ -4699,6 +4711,13 @@ INT32 PlotPath( SOLDIERTYPE *pSold, INT32 sDestGridNo, INT8 bCopyRoute, INT8 bPl
|
||||
sMovementAPsCost += APBPConstants[AP_STEALTH_MODIFIER];
|
||||
}
|
||||
}
|
||||
|
||||
// Flugente: riot shields lower movement speed
|
||||
if ( pSold->IsRiotShieldEquipped( ) )
|
||||
{
|
||||
sMovementAPsCost *= gItemSettings.fShieldMovementAPCostModifier;
|
||||
}
|
||||
|
||||
// Check for backpack
|
||||
//if((UsingNewInventorySystem() == true) && FindBackpackOnSoldier( pSold ) != ITEM_NOT_FOUND )
|
||||
// sMovementAPsCost += APBPConstants[AP_MODIFIER_PACK];
|
||||
@@ -4747,11 +4766,13 @@ INT32 PlotPath( SOLDIERTYPE *pSold, INT32 sDestGridNo, INT8 bCopyRoute, INT8 bPl
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// SANDRO - This part was modified "a bit"
|
||||
sMovementAPsCost = sTileCost;
|
||||
|
||||
// Check for reverse mode
|
||||
if ( pSold->bReverse || bReverse )
|
||||
{
|
||||
sMovementAPsCost += APBPConstants[AP_REVERSE_MODIFIER];
|
||||
}
|
||||
|
||||
// STOMP traits - Athletics trait decreases movement cost
|
||||
if ( gGameOptions.fNewTraitSystem && HAS_SKILL_TRAIT( pSold, ATHLETICS_NT ))
|
||||
{
|
||||
@@ -4818,6 +4839,16 @@ INT32 PlotPath( SOLDIERTYPE *pSold, INT32 sDestGridNo, INT8 bCopyRoute, INT8 bPl
|
||||
sPointsRun += APBPConstants[AP_STEALTH_MODIFIER];
|
||||
}
|
||||
}
|
||||
|
||||
// Flugente: riot shields lower movement speed
|
||||
if ( pSold->IsRiotShieldEquipped( ) )
|
||||
{
|
||||
sPointsWalk *= gItemSettings.fShieldMovementAPCostModifier;
|
||||
sPointsCrawl *= gItemSettings.fShieldMovementAPCostModifier;
|
||||
sPointsSwat *= gItemSettings.fShieldMovementAPCostModifier;
|
||||
sPointsRun *= gItemSettings.fShieldMovementAPCostModifier;
|
||||
}
|
||||
|
||||
// Check for backpack
|
||||
//if((UsingNewInventorySystem() == true) && FindBackpackOnSoldier( pSold ) != ITEM_NOT_FOUND )
|
||||
//{
|
||||
|
||||
+24
-5
@@ -474,6 +474,12 @@ INT16 ActionPointCost( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bDir, UINT16 u
|
||||
sPoints = max(1, (INT16)((sPoints * (100 - gSkillTraitValues.ubATAPsMovementReduction) / 100) + 0.5));
|
||||
}
|
||||
|
||||
// Flugente: riot shields lower movement speed
|
||||
if ( pSoldier->IsRiotShieldEquipped( ) )
|
||||
{
|
||||
sPoints *= gItemSettings.fShieldMovementAPCostModifier;
|
||||
}
|
||||
|
||||
// Flugente: scuba fins reduce movement cost in water, but increase cost on land
|
||||
if ( pSoldier->inv[LEGPOS].exists() && HasItemFlag( pSoldier->inv[LEGPOS].usItem, SCUBA_FINS ) )
|
||||
{
|
||||
@@ -715,6 +721,13 @@ INT16 EstimateActionPointCost( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bDir,
|
||||
{
|
||||
sPoints = max(1, (INT16)((sPoints * (100 - gSkillTraitValues.ubATAPsMovementReduction) / 100) + 0.5));
|
||||
}
|
||||
|
||||
// Flugente: riot shields lower movement speed
|
||||
if ( pSoldier->IsRiotShieldEquipped( ) )
|
||||
{
|
||||
sPoints *= gItemSettings.fShieldMovementAPCostModifier;
|
||||
}
|
||||
|
||||
// Check if doors if not player's merc (they have to open them manually)
|
||||
if ( sSwitchValue == TRAVELCOST_DOOR && pSoldier->bTeam != gbPlayerNum )
|
||||
{
|
||||
@@ -4209,17 +4222,23 @@ INT16 GetAPsProne( SOLDIERTYPE *pSoldier, BOOLEAN fBackpackCheck )
|
||||
// SANDRO - Added feature to calculate start run cost (for Athletics trait)
|
||||
INT16 GetAPsStartRun( SOLDIERTYPE *pSoldier )
|
||||
{
|
||||
INT16 val = APBPConstants[AP_START_RUN_COST];
|
||||
|
||||
// Flugente: riot shields lower movement speed
|
||||
if ( pSoldier->IsRiotShieldEquipped( ) )
|
||||
val *= gItemSettings.fShieldMovementAPCostModifier;
|
||||
|
||||
// Athletics trait
|
||||
if ( HAS_SKILL_TRAIT( pSoldier, ATHLETICS_NT ) && gGameOptions.fNewTraitSystem )
|
||||
return( max( 1, (INT16)((APBPConstants[AP_START_RUN_COST] * (100 - gSkillTraitValues.ubATAPsMovementReduction)/100) + 0.5 )) );
|
||||
else
|
||||
return( APBPConstants[AP_START_RUN_COST] );
|
||||
if( HAS_SKILL_TRAIT( pSoldier, ATHLETICS_NT ) && gGameOptions.fNewTraitSystem )
|
||||
val = max( 1, (INT16)((val * (100 - gSkillTraitValues.ubATAPsMovementReduction) / 100) + 0.5) );
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
// SANDRO - Added feature to calculate APs for handling doors (for Ambidextrous trait)
|
||||
INT16 GetAPsToOpenDoor( SOLDIERTYPE *pSoldier )
|
||||
{
|
||||
if( gGameOptions.fNewTraitSystem && HAS_SKILL_TRAIT( pSoldier, AMBIDEXTROUS_NT ) )
|
||||
if ( gGameOptions.fNewTraitSystem && HAS_SKILL_TRAIT( pSoldier, AMBIDEXTROUS_NT ) )
|
||||
return( max( 1, (INT16)((APBPConstants[AP_OPEN_DOOR] * (100 - gSkillTraitValues.ubAMHandleDoorsAPsReduction)/100) + 0.5 )) );
|
||||
else
|
||||
return( APBPConstants[AP_OPEN_DOOR] );
|
||||
|
||||
@@ -1510,7 +1510,8 @@ BOOLEAN AdjustToNextAnimationFrame( SOLDIERTYPE *pSoldier )
|
||||
|
||||
// ONLY DO THIS IF CERTAIN CONDITIONS ARISE!
|
||||
// For one, only do for mercs!
|
||||
if ( pSoldier->ubBodyType <= REGFEMALE )
|
||||
// Flugente: don't do this while equipping a shield, as this renders them almost useless
|
||||
if ( pSoldier->ubBodyType <= REGFEMALE && !pSoldier->IsRiotShieldEquipped( ) )
|
||||
{
|
||||
// Secondly, don't if we are going to collapse
|
||||
if ( pSoldier->stats.bLife >= OKLIFE && pSoldier->bBreath > 0 && pSoldier->pathing.bLevel == 0 )
|
||||
|
||||
@@ -8917,7 +8917,7 @@ void CalculateSoldierAniSpeed( SOLDIERTYPE *pSoldier, SOLDIERTYPE *pStatsSoldier
|
||||
|
||||
pSoldier->sAniDelay = (INT16)uiTerrainDelay;
|
||||
|
||||
// If a moving animation and w/re on drugs, increase speed....
|
||||
// If a moving animation and we're on drugs, increase speed....
|
||||
if ( gAnimControl[pSoldier->usAnimState].uiFlags & ANIM_MOVING )
|
||||
{
|
||||
if ( pSoldier->newdrugs.size[DRUG_EFFECT_AP] )
|
||||
@@ -8949,6 +8949,7 @@ void CalculateSoldierAniSpeed( SOLDIERTYPE *pSoldier, SOLDIERTYPE *pStatsSoldier
|
||||
pSoldier->sAniDelay = (INT16)(pSoldier->sAniDelay * 2);
|
||||
}
|
||||
}
|
||||
|
||||
// SANDRO - STOMP traits - bonus to movement speed for Athletics
|
||||
if ( gGameOptions.fNewTraitSystem && (gAnimControl[pSoldier->usAnimState].uiFlags & ANIM_MOVING) )
|
||||
{
|
||||
@@ -8958,6 +8959,12 @@ void CalculateSoldierAniSpeed( SOLDIERTYPE *pSoldier, SOLDIERTYPE *pStatsSoldier
|
||||
}
|
||||
}
|
||||
|
||||
// Flugente: riot shields lower movement speed
|
||||
if ( pSoldier->IsRiotShieldEquipped( ) )
|
||||
{
|
||||
pSoldier->sAniDelay = gItemSettings.fShieldMovementAPCostModifier * pSoldier->sAniDelay;
|
||||
}
|
||||
|
||||
//pSoldier->sAniDelay = pSoldier->sAniDelay * ( 1 * gTacticalStatus.bRealtimeSpeed / 2 );
|
||||
}
|
||||
|
||||
@@ -9900,6 +9907,33 @@ UINT8 SOLDIERTYPE::SoldierTakeDamage( INT8 bHeight, INT16 sLifeDeduct, INT16 sBr
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Flugente: do we have a riot shield equipped?
|
||||
if ( this->IsRiotShieldEquipped( ) )
|
||||
{
|
||||
// if we have equipped a riot shield and are being attacked in melee, ignore damage from some directions
|
||||
if ( ubReason == TAKE_DAMAGE_BLADE || ubReason == TAKE_DAMAGE_HANDTOHAND || ubReason == TAKE_DAMAGE_TENTACLES )
|
||||
{
|
||||
if ( ubAttacker != NOBODY && MercPtrs[ubAttacker] )
|
||||
{
|
||||
UINT8 attackdir_inverse = GetDirectionToGridNoFromGridNo( this->sGridNo, MercPtrs[ubAttacker]->sGridNo );
|
||||
|
||||
// if the shield faces the direction of the attacker, we block the attack
|
||||
if ( attackdir_inverse == this->ubDirection || attackdir_inverse == gOneCCDirection[this->ubDirection] || attackdir_inverse == gOneCDirection[this->ubDirection] )
|
||||
{
|
||||
// damaging even a wooden shield is hard. For that reason we lower the initial damage.
|
||||
INT32 damage = sLifeDeduct / 3;
|
||||
INT32 breathdamage = sBreathLoss;
|
||||
DamageRiotShield( this, damage, breathdamage );
|
||||
|
||||
sLifeDeduct = damage;
|
||||
sBreathLoss = breathdamage;
|
||||
|
||||
PlayJA2Sample( (UINT32)(S_WOOD_IMPACT1 + Random(3)), RATE_11025, SoundVolume( MIDVOLUME, this->sGridNo ), 1, SoundDir( this->sGridNo ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Deduct life!, Show damage if we want!
|
||||
bOldLife = this->stats.bLife;
|
||||
@@ -17360,7 +17394,7 @@ BOOLEAN SOLDIERTYPE::UseSkill( UINT8 iSkill, INT32 usMapPos, UINT8 ID )
|
||||
case SKILLS_RADIO_JAM:
|
||||
return JamCommunications( );
|
||||
break;
|
||||
|
||||
|
||||
case SKILLS_RADIO_SCAN_FOR_JAM:
|
||||
return ScanForJam( );
|
||||
break;
|
||||
@@ -19244,6 +19278,79 @@ UINT16 SOLDIERTYPE::GetInteractiveActionSkill( INT32 sGridNo, UINT8 usLevel, UIN
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Flugente: riot shields
|
||||
OBJECTTYPE* SOLDIERTYPE::GetEquippedRiotShield()
|
||||
{
|
||||
OBJECTTYPE* pObj = NULL;
|
||||
|
||||
if ( this->inv[HANDPOS].exists( ) && Item[this->inv[HANDPOS].usItem].usRiotShieldStrength > 0 )
|
||||
pObj = &(this->inv[HANDPOS]);
|
||||
|
||||
if ( this->inv[SECONDHANDPOS].exists( ) && Item[this->inv[SECONDHANDPOS].usItem].usRiotShieldStrength > 0 )
|
||||
pObj = &(this->inv[SECONDHANDPOS]);
|
||||
|
||||
return pObj;
|
||||
}
|
||||
|
||||
|
||||
BOOLEAN SOLDIERTYPE::IsRiotShieldEquipped()
|
||||
{
|
||||
// shield is not erect if prone
|
||||
if ( gAnimControl[this->usAnimState].ubEndHeight == ANIM_PRONE )
|
||||
return FALSE;
|
||||
|
||||
// no shield while swimming
|
||||
if ( TERRAIN_IS_HIGH_WATER(this->sGridNo) )
|
||||
return FALSE;
|
||||
|
||||
return (GetEquippedRiotShield() != NULL);
|
||||
}
|
||||
|
||||
void SOLDIERTYPE::DestroyEquippedRiotShield( )
|
||||
{
|
||||
// create graphic (destroyed shield item?)
|
||||
OBJECTTYPE* pObj = GetEquippedRiotShield( );
|
||||
|
||||
if ( pObj )
|
||||
{
|
||||
if ( Item[pObj->usItem].usBuddyItem )
|
||||
{
|
||||
CreateItem( Item[pObj->usItem].usBuddyItem, 100, pObj );
|
||||
|
||||
// Flugente: why would we keep a piece of scrap in our hands in the first place? just drop it to the ground
|
||||
AddItemToPool( this->sGridNo, pObj, 1, this->pathing.bLevel, 0, -1 );
|
||||
|
||||
NotifySoldiersToLookforItems( );
|
||||
}
|
||||
|
||||
// Delete object
|
||||
DeleteObj( pObj );
|
||||
}
|
||||
|
||||
// dirty interface panel
|
||||
DirtyMercPanelInterface( this, DIRTYLEVEL2 );
|
||||
|
||||
this->DoMercBattleSound( BATTLE_SOUND_CURSE1 );
|
||||
}
|
||||
|
||||
void SOLDIERTYPE::RiotShieldTakeDamage( INT32 sDamage )
|
||||
{
|
||||
OBJECTTYPE* pObj = GetEquippedRiotShield();
|
||||
|
||||
if ( pObj )
|
||||
{
|
||||
PlayJA2Sample( (UINT32)(S_METAL_IMPACT1 + +Random( 3 )), RATE_11025, SoundVolume( MIDVOLUME, this->sGridNo ), 1, SoundDir( this->sGridNo ) );
|
||||
|
||||
(*pObj)[0]->data.objectStatus -= sDamage;
|
||||
|
||||
// if shield should have been destroyed, do so
|
||||
if ( (*pObj)[0]->data.objectStatus < 1 )
|
||||
{
|
||||
DestroyEquippedRiotShield( );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
INT32 CheckBleeding( SOLDIERTYPE *pSoldier )
|
||||
{
|
||||
INT8 bBandaged; //,savedOurTurn;
|
||||
|
||||
@@ -1943,6 +1943,12 @@ public:
|
||||
|
||||
// Flugente: interactive actions
|
||||
UINT16 GetInteractiveActionSkill( INT32 sGridNo, UINT8 usLevel, UINT16 usType );
|
||||
|
||||
// Flugente: riot shields
|
||||
OBJECTTYPE* GetEquippedRiotShield();
|
||||
BOOLEAN IsRiotShieldEquipped();
|
||||
void DestroyEquippedRiotShield();
|
||||
void RiotShieldTakeDamage(INT32 sDamage);
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}; // SOLDIERTYPE;
|
||||
|
||||
@@ -1571,6 +1571,28 @@ BOOLEAN DamageSoldierFromBlast( UINT8 ubPerson, UINT8 ubOwner, INT32 sBombGridNo
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
// Flugente: do we have a riot shield equipped?
|
||||
if ( pSoldier->IsRiotShieldEquipped( ) )
|
||||
{
|
||||
UINT8 attackdir_inverse = GetDirectionToGridNoFromGridNo( pSoldier->sGridNo, sBombGridNo );
|
||||
|
||||
// if the shield faces the direction of the attack, block it
|
||||
if ( attackdir_inverse == pSoldier->ubDirection || attackdir_inverse == gOneCCDirection[pSoldier->ubDirection] || attackdir_inverse == gOneCDirection[pSoldier->ubDirection] )
|
||||
{
|
||||
INT32 damage = sWoundAmt;
|
||||
INT32 breathdamage = sBreathAmt;
|
||||
DamageRiotShield( pSoldier, damage, breathdamage );
|
||||
|
||||
sWoundAmt = damage;
|
||||
sBreathAmt = breathdamage;
|
||||
|
||||
if ( sWoundAmt == 0 && sBreathAmt == 0 )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Lesh: if flashbang
|
||||
// check if soldier is outdoor and situated farther that half explosion radius and not underground
|
||||
usHalfExplosionRadius = Explosive[Item[usItem].ubClassIndex].ubRadius / 2;
|
||||
@@ -4238,6 +4260,9 @@ void HandleExplosionQueue( void )
|
||||
}
|
||||
}
|
||||
|
||||
// Flugente: riot shields
|
||||
extern void ShowRiotShield( SOLDIERTYPE* pSoldier );
|
||||
|
||||
// Flugente: show warnings around armed timebombs both in map and inventories
|
||||
void HandleExplosionWarningAnimations( )
|
||||
{
|
||||
@@ -4315,6 +4340,25 @@ void HandleExplosionWarningAnimations( )
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// show riot shields
|
||||
SOLDIERTYPE* pSoldier;
|
||||
UINT16 cnt = gTacticalStatus.Team[0].bFirstID;
|
||||
for ( pSoldier = MercPtrs[cnt]; cnt <= gTacticalStatus.Team[CIV_TEAM].bLastID; ++cnt, pSoldier++ )
|
||||
{
|
||||
if ( pSoldier && pSoldier->bActive && pSoldier->bInSector )
|
||||
{
|
||||
if ( (pSoldier->ubDirection == EAST ||
|
||||
pSoldier->ubDirection == SOUTHEAST ||
|
||||
pSoldier->ubDirection == SOUTH ||
|
||||
pSoldier->ubDirection == SOUTHWEST ||
|
||||
pSoldier->ubDirection == NORTHEAST)
|
||||
&& pSoldier->IsRiotShieldEquipped( ) )
|
||||
{
|
||||
ShowRiotShield( pSoldier );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DecayBombTimers( void )
|
||||
|
||||
@@ -53,6 +53,11 @@
|
||||
#include "Render Z.h"
|
||||
///////////////////////////
|
||||
|
||||
#include "Utilities.h"
|
||||
|
||||
UINT32 guiShieldGraphic = 0;
|
||||
BOOLEAN fShieldGraphicInit = FALSE;
|
||||
|
||||
extern CHAR8 gDebugStr[128];
|
||||
extern BOOLEAN fLandLayerDirty = TRUE;
|
||||
|
||||
@@ -603,6 +608,50 @@ void DeleteFromWorld( UINT16 usTileIndex, UINT32 uiRenderTiles, UINT16 usIndex )
|
||||
void RenderHighlight( INT16 sMouseX_M, INT16 sMouseY_M, INT16 sStartPointX_M, INT16 sStartPointY_M, INT16 sStartPointX_S, INT16 sStartPointY_S, INT16 sEndXS, INT16 sEndYS );
|
||||
BOOLEAN CheckRenderCenter( INT16 sNewCenterX, INT16 sNewCenterY );
|
||||
|
||||
// Flugente: display a riot shield
|
||||
void ShowRiotShield( SOLDIERTYPE* pSoldier )
|
||||
{
|
||||
if (pSoldier)
|
||||
{
|
||||
if (!fShieldGraphicInit)
|
||||
{
|
||||
VOBJECT_DESC VObjectDesc;
|
||||
|
||||
// Flugente: enemy role symbols
|
||||
VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE;
|
||||
FilenameForBPP("Tilecache\\riotshield.sti", VObjectDesc.ImageFile);
|
||||
if (!AddVideoObject(&VObjectDesc, &guiShieldGraphic))
|
||||
AssertMsg(0, "Missing Tilecache\\riotshield.sti");
|
||||
|
||||
fShieldGraphicInit = TRUE;
|
||||
}
|
||||
|
||||
// Get screen pos of gridno......
|
||||
INT16 sScreenX, sScreenY;
|
||||
GetGridNoScreenXY(pSoldier->sGridNo, &sScreenX, &sScreenY);
|
||||
|
||||
// redraw background to stop weird graphic remnants remaining
|
||||
// but don*t do so while scrolling, because that looks weird
|
||||
if ( !gfScrollPending && !gfScrollInertia)
|
||||
{
|
||||
INT32 iBack = RegisterBackgroundRect(BGND_FLAG_SINGLE, NULL, sScreenX - 50, sScreenY - 60, sScreenX + 50, sScreenY + 35);
|
||||
|
||||
if (iBack != -1)
|
||||
{
|
||||
SetBackgroundRectFilled(iBack);
|
||||
}
|
||||
}
|
||||
|
||||
UINT16 offset = 0;
|
||||
OBJECTTYPE* pObj = pSoldier->GetEquippedRiotShield();
|
||||
|
||||
if (pObj)
|
||||
offset = Item[pObj->usItem].usRiotShieldGraphic;
|
||||
|
||||
BltVideoObjectFromIndex( FRAME_BUFFER, guiShieldGraphic, offset * 8 + pSoldier->ubDirection, sScreenX - 20, sScreenY - 60, VO_BLT_TRANSSHADOW, NULL );
|
||||
}
|
||||
}
|
||||
|
||||
BOOLEAN RevealWalls(INT16 sX, INT16 sY, INT16 sRadius)
|
||||
{
|
||||
LEVELNODE *pStruct;
|
||||
@@ -1837,6 +1886,16 @@ void RenderTiles(UINT32 uiFlags, INT32 iStartPointX_M, INT32 iStartPointY_M, INT
|
||||
usImageIndex = pSoldier->CryoAniFrame( );
|
||||
}
|
||||
|
||||
// Flugente: riot shields
|
||||
if ( pSoldier &&
|
||||
(pSoldier->ubDirection == NORTH ||
|
||||
pSoldier->ubDirection == NORTHWEST ||
|
||||
pSoldier->ubDirection == WEST)
|
||||
&& pSoldier->IsRiotShieldEquipped( ) )
|
||||
{
|
||||
ShowRiotShield( pSoldier );
|
||||
}
|
||||
|
||||
uiDirtyFlags=BGND_FLAG_SINGLE|BGND_FLAG_ANIMATED| BGND_FLAG_MERC;
|
||||
break;
|
||||
}
|
||||
|
||||
+17
-2
@@ -291,7 +291,9 @@ itemStartElementHandle(void *userData, const XML_Char *name, const XML_Char **at
|
||||
strcmp(name, "cigarette" ) == 0 ||
|
||||
strcmp(name, "usPortionSize" ) == 0 ||
|
||||
strcmp(name, "diseaseprotectionface" ) == 0 ||
|
||||
strcmp(name, "diseaseprotectionhand" ) == 0))
|
||||
strcmp(name, "diseaseprotectionhand" ) == 0||
|
||||
strcmp(name, "usRiotShieldStrength" ) == 0 ||
|
||||
strcmp(name, "usRiotShieldGraphic" ) == 0))
|
||||
{
|
||||
pData->curElement = ELEMENT_PROPERTY;
|
||||
//DebugMsg(TOPIC_JA2, DBG_LEVEL_3, String("itemStartElementHandle: going into element, name = %s",name) );
|
||||
@@ -1499,6 +1501,16 @@ itemEndElementHandle(void *userData, const XML_Char *name)
|
||||
if ( val )
|
||||
pData->curItem.usItemFlag |= DISEASEPROTECTION_2;
|
||||
}
|
||||
else if ( strcmp( name, "usRiotShieldStrength" ) == 0 )
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
pData->curItem.usRiotShieldStrength = min( 100, (UINT16)atol( pData->szCharData ) );
|
||||
}
|
||||
else if ( strcmp( name, "usRiotShieldGraphic" ) == 0 )
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
pData->curItem.usRiotShieldGraphic = (UINT16)atol( pData->szCharData );
|
||||
}
|
||||
|
||||
--pData->maxReadDepth;
|
||||
}
|
||||
@@ -2128,7 +2140,7 @@ BOOLEAN WriteItemStats()
|
||||
FilePrintf(hFile,"\t\t<usSpotting>%d</usSpotting>\r\n", Item[cnt].usSpotting );
|
||||
FilePrintf(hFile,"\t\t<sBackpackWeightModifier>%d</sBackpackWeightModifier>\r\n", Item[cnt].sBackpackWeightModifier);
|
||||
FilePrintf(hFile,"\t\t<fAllowClimbing>%d</fAllowClimbing>\r\n", Item[cnt].fAllowClimbing);
|
||||
FilePrintf(hFile, "\t\t<cigarette>%d</cigarette>\r\n", Item[cnt].cigarette );
|
||||
FilePrintf(hFile,"\t\t<cigarette>%d</cigarette>\r\n", Item[cnt].cigarette );
|
||||
FilePrintf(hFile,"\t\t<usPortionSize>%d</usPortionSize>\r\n", Item[cnt].usPortionSize );
|
||||
|
||||
if ( Item[cnt].usItemFlag & DISEASEPROTECTION_1 )
|
||||
@@ -2136,6 +2148,9 @@ BOOLEAN WriteItemStats()
|
||||
if ( Item[cnt].usItemFlag & DISEASEPROTECTION_2 )
|
||||
FilePrintf( hFile, "\t\t<diseaseprotectionhand>%d</diseaseprotectionhand>\r\n", 1 );
|
||||
|
||||
FilePrintf(hFile,"\t\t<usRiotShieldStrength>%d</usRiotShieldStrength>\r\n", Item[cnt].usRiotShieldStrength );
|
||||
FilePrintf(hFile,"\t\t<usRiotShieldGraphic>%d</usRiotShieldGraphic>\r\n", Item[cnt].usRiotShieldGraphic );
|
||||
|
||||
FilePrintf(hFile,"\t</ITEM>\r\n");
|
||||
}
|
||||
FilePrintf(hFile,"</ITEMLIST>\r\n");
|
||||
|
||||
@@ -8388,6 +8388,7 @@ STR16 szUDBGenSecondaryStatsTooltipText[]=
|
||||
L"|反|器|材|弹|药", //L"|A|n|t|i|-|M|a|t|e|r|i|a|l |A|m|m|o",
|
||||
L"|面|部|防|护", //L"|F|a|c|e |P|r|o|t|e|c|t|i|o|n",
|
||||
L"|感|染|防|护", //L"|I|n|f|e|c|t|i|o|n |P|r|o|t|e|c|t|i|o|n", // 39
|
||||
L"|S|h|i|e|l|d", // TODO.Translate
|
||||
};
|
||||
|
||||
STR16 szUDBGenSecondaryStatsExplanationsTooltipText[]=
|
||||
@@ -8432,6 +8433,7 @@ STR16 szUDBGenSecondaryStatsExplanationsTooltipText[]=
|
||||
L"\n \n这种弹药可以破坏发光的墙\n或者其他不同种类的物品。", //L"\n \nThis ammo can destroy light walls\nand various other objects.",
|
||||
L"\n \n如果你脸上带了这个,这就将降低\n传播给其他人的几率。", //L"\n \nIf worn on your face, this will lower\nthe chance to be infected by other people.",
|
||||
L"\n \n如果保存在物品栏\n降低\n传染给其他人的几率。", //L"\n \nIf kept in your inventory, this will\nlower\nthe chance to be infected by other people.",
|
||||
L"\n \nIf equipped in a hand, this will block incoming damage.", // TODO.Translate
|
||||
};
|
||||
|
||||
STR16 szUDBAdvStatsTooltipText[]=
|
||||
|
||||
@@ -8405,6 +8405,7 @@ STR16 szUDBGenSecondaryStatsTooltipText[]=
|
||||
L"|A|n|t|i|-|M|a|t|e|r|i|a|l |A|m|m|o", // TODO.Translate
|
||||
L"|F|a|c|e |P|r|o|t|e|c|t|i|o|n",
|
||||
L"|I|n|f|e|c|t|i|o|n |P|r|o|t|e|c|t|i|o|n", // 39
|
||||
L"|S|h|i|e|l|d", // TODO.Translate
|
||||
};
|
||||
|
||||
STR16 szUDBGenSecondaryStatsExplanationsTooltipText[]=
|
||||
@@ -8449,6 +8450,7 @@ STR16 szUDBGenSecondaryStatsExplanationsTooltipText[]=
|
||||
L"\n \nThis ammo can destroy light walls\nand various other objects.", // TODO.Translate
|
||||
L"\n \nIf worn on your face, this will lower\nthe chance to be infected by other people.",
|
||||
L"\n \nIf kept in your inventory, this will\nlower\nthe chance to be infected by other people.",
|
||||
L"\n \nIf equipped in a hand, this will block incoming damage.", // TODO.Translate
|
||||
};
|
||||
|
||||
STR16 szUDBAdvStatsTooltipText[]=
|
||||
|
||||
@@ -8386,6 +8386,7 @@ STR16 szUDBGenSecondaryStatsTooltipText[]=
|
||||
L"|A|n|t|i|-|M|a|t|e|r|i|e|l |A|m|m|o",
|
||||
L"|F|a|c|e |P|r|o|t|e|c|t|i|o|n",
|
||||
L"|I|n|f|e|c|t|i|o|n |P|r|o|t|e|c|t|i|o|n", // 39
|
||||
L"|S|h|i|e|l|d",
|
||||
};
|
||||
|
||||
STR16 szUDBGenSecondaryStatsExplanationsTooltipText[]=
|
||||
@@ -8430,6 +8431,7 @@ STR16 szUDBGenSecondaryStatsExplanationsTooltipText[]=
|
||||
L"\n \nThis ammo can destroy light walls\nand various other objects.",
|
||||
L"\n \nIf worn on your face, this will lower\nthe chance to be infected by other people.",
|
||||
L"\n \nIf kept in your inventory, this will\nlower\nthe chance to be infected by other people.",
|
||||
L"\n \nIf equipped in a hand, this will block incoming damage.",
|
||||
};
|
||||
|
||||
STR16 szUDBAdvStatsTooltipText[]=
|
||||
|
||||
@@ -8392,6 +8392,7 @@ STR16 szUDBGenSecondaryStatsTooltipText[]=
|
||||
L"|A|n|t|i|-|M|a|t|e|r|i|a|l |A|m|m|o", // TODO.Translate
|
||||
L"|F|a|c|e |P|r|o|t|e|c|t|i|o|n",
|
||||
L"|I|n|f|e|c|t|i|o|n |P|r|o|t|e|c|t|i|o|n", // 39
|
||||
L"|S|h|i|e|l|d", // TODO.Translate
|
||||
};
|
||||
|
||||
STR16 szUDBGenSecondaryStatsExplanationsTooltipText[]=
|
||||
@@ -8436,6 +8437,7 @@ STR16 szUDBGenSecondaryStatsExplanationsTooltipText[]=
|
||||
L"\n \nThis ammo can destroy light walls\nand various other objects.", // TODO.Translate
|
||||
L"\n \nIf worn on your face, this will lower\nthe chance to be infected by other people.",
|
||||
L"\n \nIf kept in your inventory, this will\nlower\nthe chance to be infected by other people.",
|
||||
L"\n \nIf equipped in a hand, this will block incoming damage.", // TODO.Translate
|
||||
};
|
||||
|
||||
STR16 szUDBAdvStatsTooltipText[]=
|
||||
|
||||
@@ -8221,6 +8221,7 @@ STR16 szUDBGenSecondaryStatsTooltipText[]=
|
||||
L"|A|n|t|i|-|M|a|t|e|r|i|a|l |A|m|m|o", // TODO.Translate
|
||||
L"|F|a|c|e |P|r|o|t|e|c|t|i|o|n",
|
||||
L"|I|n|f|e|c|t|i|o|n |P|r|o|t|e|c|t|i|o|n", // 39
|
||||
L"|S|h|i|e|l|d", // TODO.Translate
|
||||
};
|
||||
|
||||
STR16 szUDBGenSecondaryStatsExplanationsTooltipText[]=
|
||||
@@ -8265,6 +8266,7 @@ STR16 szUDBGenSecondaryStatsExplanationsTooltipText[]=
|
||||
L"\n \nThis ammo can destroy light walls\nand various other objects.", // TODO.Translate
|
||||
L"\n \nIf worn on your face, this will lower\nthe chance to be infected by other people.",
|
||||
L"\n \nIf kept in your inventory, this will\nlower\nthe chance to be infected by other people.",
|
||||
L"\n \nIf equipped in a hand, this will block incoming damage.", // TODO.Translate
|
||||
};
|
||||
|
||||
STR16 szUDBAdvStatsTooltipText[]=
|
||||
|
||||
@@ -8395,6 +8395,7 @@ STR16 szUDBGenSecondaryStatsTooltipText[]=
|
||||
L"|A|n|t|i|-|M|a|t|e|r|i|a|l |A|m|m|o", // TODO.Translate
|
||||
L"|F|a|c|e |P|r|o|t|e|c|t|i|o|n",
|
||||
L"|I|n|f|e|c|t|i|o|n |P|r|o|t|e|c|t|i|o|n", // 39
|
||||
L"|S|h|i|e|l|d", // TODO.Translate
|
||||
};
|
||||
|
||||
STR16 szUDBGenSecondaryStatsExplanationsTooltipText[]=
|
||||
@@ -8439,6 +8440,7 @@ STR16 szUDBGenSecondaryStatsExplanationsTooltipText[]=
|
||||
L"\n \nThis ammo can destroy light walls\nand various other objects.", // TODO.Translate
|
||||
L"\n \nIf worn on your face, this will lower\nthe chance to be infected by other people.",
|
||||
L"\n \nIf kept in your inventory, this will\nlower\nthe chance to be infected by other people.",
|
||||
L"\n \nIf equipped in a hand, this will block incoming damage.", // TODO.Translate
|
||||
};
|
||||
|
||||
STR16 szUDBAdvStatsTooltipText[]=
|
||||
|
||||
@@ -8407,6 +8407,7 @@ STR16 szUDBGenSecondaryStatsTooltipText[]=
|
||||
L"|A|n|t|i|-|M|a|t|e|r|i|a|l |A|m|m|o", // TODO.Translate
|
||||
L"|F|a|c|e |P|r|o|t|e|c|t|i|o|n",
|
||||
L"|I|n|f|e|c|t|i|o|n |P|r|o|t|e|c|t|i|o|n", // 39
|
||||
L"|S|h|i|e|l|d", // TODO.Translate
|
||||
};
|
||||
|
||||
STR16 szUDBGenSecondaryStatsExplanationsTooltipText[]=
|
||||
@@ -8451,6 +8452,7 @@ STR16 szUDBGenSecondaryStatsExplanationsTooltipText[]=
|
||||
L"\n \nThis ammo can destroy light walls\nand various other objects.", // TODO.Translate
|
||||
L"\n \nIf worn on your face, this will lower\nthe chance to be infected by other people.",
|
||||
L"\n \nIf kept in your inventory, this will\nlower\nthe chance to be infected by other people.",
|
||||
L"\n \nIf equipped in a hand, this will block incoming damage.", // TODO.Translate
|
||||
};
|
||||
|
||||
STR16 szUDBAdvStatsTooltipText[]=
|
||||
|
||||
@@ -8390,6 +8390,7 @@ STR16 szUDBGenSecondaryStatsTooltipText[]=
|
||||
L"|С|н|а|р|я|д |п|р|о|т|и|в |б|р|о|н|и",
|
||||
L"|З|а|щ|и|т|а |д|л|я |л|и|ц|а",
|
||||
L"|И|н|ф|е|к|ц|и|о|н|н|а|я |з|а|щ|и|т|а", // 39
|
||||
L"|S|h|i|e|l|d", // TODO.Translate
|
||||
};
|
||||
|
||||
STR16 szUDBGenSecondaryStatsExplanationsTooltipText[]=
|
||||
@@ -8434,6 +8435,7 @@ STR16 szUDBGenSecondaryStatsExplanationsTooltipText[]=
|
||||
L"\n \nЭтот боеприпас может уничтожать тонкие стены\nи некоторые другие объекты.",
|
||||
L"\n \nЕсли одето на лицо, понижает шанс\nзаражения от других людей.",
|
||||
L"\n \nЕсли хранить в своём кармане,\nпонижается шанс заражения\n от других людей.",
|
||||
L"\n \nIf equipped in a hand, this will block incoming damage.", // TODO.Translate
|
||||
};
|
||||
|
||||
STR16 szUDBAdvStatsTooltipText[]=
|
||||
|
||||
Reference in New Issue
Block a user