New feature: environment hazards pose danger to soldiers in certain sectors - first use are snakes that attack anybody in water sources in swamps.

Requires GameDir >= r2327.

git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@8266 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
Flugente
2016-07-03 21:26:45 +00:00
parent 762fb79c09
commit ce6e63831d
28 changed files with 294 additions and 27 deletions
+6 -1
View File
@@ -1685,7 +1685,11 @@ void LoadGameExternalOptions()
gGameExternalOptions.dHearingReduction[WEATHER_FORECAST_THUNDERSHOWERS] = iniReader.ReadDouble( "Tactical Weather Settings", "HEARING_REDUCTION_THUNDERSTORM", 0.8f, 0.0f, 1.0f );
gGameExternalOptions.dHearingReduction[WEATHER_FORECAST_SANDSTORM] = iniReader.ReadDouble( "Tactical Weather Settings", "HEARING_REDUCTION_SANDSTORM", 0.6f, 0.0f, 1.0f );
gGameExternalOptions.dHearingReduction[WEATHER_FORECAST_SNOW] = iniReader.ReadDouble( "Tactical Weather Settings", "HEARING_REDUCTION_SNOW", 0.1f, 0.0f, 1.0f );
//################# Environment Hazard Settings ##################
// Flugente: this controls what dangers we face in different sectors
gGameExternalOptions.gfAllowSnakes = iniReader.ReadBoolean( "Environment Hazard Settings", "ALLOW_SNAKES", TRUE );
//################# Tactical Weapon Overheating Settings ##################
// Flugente: These settings control the behavior of Weapon Overheating, its severity, and its display.
gGameExternalOptions.fWeaponOverheating = iniReader.ReadBoolean("Tactical Weapon Overheating Settings","OVERHEATING",FALSE);
@@ -2634,6 +2638,7 @@ void LoadSkillTraitsExternalSettings()
gSkillTraitValues.usSVDiseaseResistance = iniReader.ReadInteger( "Survival", "DISEASE_RESISTANCE", 10, 0, 100 );
gSkillTraitValues.sSVFoodConsumption = iniReader.ReadInteger( "Survival", "FOOD_CONSUMPTION", -20, -100, 100 );
gSkillTraitValues.sSVDrinkConsumption = iniReader.ReadInteger( "Survival", "DRINK_CONSUMPTION", -10, -100, 100 );
gSkillTraitValues.usSVSnakeDefense = iniReader.ReadInteger( "Survival", "SNAKE_EVADE_BONUS", 10, 0, 50 );
}
//DBrot: Grids
+5
View File
@@ -592,6 +592,10 @@ typedef struct
FLOAT dVisDistDecrease[WEATHER_FORECAST_MAX];
FLOAT dHearingReduction[WEATHER_FORECAST_MAX];
// Flugente: this controls what dangers we face in different sectors
// Snakes can attack mercs in water
BOOLEAN gfAllowSnakes;
// WDS - Progress settings
UINT32 ubGameProgressPortionKills;
UINT32 ubGameProgressPortionControl;
@@ -1902,6 +1906,7 @@ typedef struct
UINT8 usSVDiseaseResistance;
INT8 sSVFoodConsumption; // alters food consumption rate
INT8 sSVDrinkConsumption;
UINT8 usSVSnakeDefense; // increases chance to evade a snake attack
} SKILL_TRAIT_VALUES;
// HEADROCK HAM 4: Constants used as coefficients by the various parts of the new CTH system.
+9
View File
@@ -8337,6 +8337,15 @@ void AssignPersonnelSkillTraitHelpText( UINT8 ubTraitNumber, BOOLEAN fExpertLeve
}
}
if ( gGameExternalOptions.gfAllowSnakes )
{
if ( gSkillTraitValues.usSVSnakeDefense > 0 )
{
swprintf( atStr, gzIMPMajorTraitsHelpTextsSurvival[9], gSkillTraitValues.usSVSnakeDefense );
wcscat( apStr, atStr );
}
}
break;
}
case NO_SKILLTRAIT_NT:
+14 -2
View File
@@ -96,7 +96,8 @@ SectorNameStartElementHandle(void *userData, const XML_Char *name, const char **
strcmp(name, "usCivilianPopulation" ) == 0 ||
strcmp(name, "rainchance" ) == 0 ||
strcmp(name, "sandstormchance") == 0 ||
strcmp(name, "snowchance" ) == 0 ))
strcmp(name, "snowchance" ) == 0 ||
strcmp(name, "snakechance" ) == 0 ))
{
pData->curElement = ELEMENT_PROPERTY;
@@ -212,7 +213,12 @@ SectorNameEndElementHandle(void *userData, const XML_Char *name)
SectorExternalData[ubSectorId][1].snowchance = 0;
SectorExternalData[ubSectorId][2].snowchance = 0;
SectorExternalData[ubSectorId][3].snowchance = 0;
SectorExternalData[ubSectorId][0].snakechance = pData->sectordata.snakechance;
SectorExternalData[ubSectorId][1].snakechance = 0;
SectorExternalData[ubSectorId][2].snakechance = 0;
SectorExternalData[ubSectorId][3].snakechance = 0;
if ( !prisonroomvector.empty( ) )
{
std::vector<UINT16>::iterator itend = prisonroomvector.end( );
@@ -234,6 +240,7 @@ SectorNameEndElementHandle(void *userData, const XML_Char *name)
pData->sectordata.rainchance = 0;
pData->sectordata.sandstormchance = 0;
pData->sectordata.snowchance = 0;
pData->sectordata.snakechance = 0;
}
else
{
@@ -343,6 +350,11 @@ SectorNameEndElementHandle(void *userData, const XML_Char *name)
pData->curElement = ELEMENT;
pData->sectordata.snowchance = min( 100, (UINT8)atoi( pData->szCharData ) );
}
else if ( strcmp( name, "snakechance" ) == 0 )
{
pData->curElement = ELEMENT;
pData->sectordata.snakechance = min( 100, (UINT8)atoi( pData->szCharData ) );
}
pData->maxReadDepth--;
}
+3
View File
@@ -508,6 +508,9 @@ typedef struct
UINT8 rainchance; // chance that it rains in this sector
UINT8 sandstormchance; // chance that a sandstorm happens in this sector
UINT8 snowchance; // chance that it snows in this sector
UINT8 snakechance; // if positive, snakes can attack in water, the higher the number, the more often it happens
} SECTOR_EXT_DATA;
// get dirt increase for object with attachments, fConsiderAmmo: with ammo
+39
View File
@@ -10089,6 +10089,9 @@ UINT8 SOLDIERTYPE::SoldierTakeDamage( INT8 bHeight, INT16 sLifeDeduct, INT16 sBr
if ( ubAttacker != NOBODY && MercPtrs[ubAttacker] && CREATURE_OR_BLOODCAT( MercPtrs[ubAttacker] ) )
HandlePossibleInfection( this, MercPtrs[ubAttacker], INFECTION_TYPE_WOUND_ANIMAL );
if ( ubReason == TAKE_DAMAGE_TENTACLES )
HandlePossibleInfection( this, NULL, INFECTION_TYPE_WOUND_ANIMAL );
if ( ubReason == TAKE_DAMAGE_GUNFIRE && sLifeDeduct > 20 )
HandlePossibleInfection( this, NULL, INFECTION_TYPE_WOUND_GUNSHOT );
else if ( ubReason == TAKE_DAMAGE_BLADE || ubReason == TAKE_DAMAGE_HANDTOHAND
@@ -19133,6 +19136,42 @@ BOOLEAN SOLDIERTYPE::SelfDetonate( )
return FALSE;
}
// Flugente: chance to defeat a water snake instead of being hit by it
UINT8 SOLDIERTYPE::GetWaterSnakeDefenseChance()
{
// base evasion chance is 5%
INT16 val = 5;
if ( gGameOptions.fNewTraitSystem )
val += gSkillTraitValues.usSVSnakeDefense * NUM_SKILL_TRAITS( this, SURVIVAL_NT );
// bonus if we have a knife, extra if it is in our hands
INT8 invsize = (INT8)inv.size( ); // remember inventorysize, so we don't call size() repeatedly
for ( INT8 bLoop = 0; bLoop < invsize; ++bLoop )
{
if ( inv[bLoop].exists( ) )
{
OBJECTTYPE* pObj = &(inv[bLoop]);
if ( pObj && (*pObj)[0]->data.objectStatus >= USABLE && Item[pObj->usItem].usItemClass == IC_BLADE )
{
if ( bLoop == HANDPOS || bLoop == SECONDHANDPOS )
val += 25;
else
val += 15;
break;
}
}
}
// chance is lowered if we are in deep water
if ( TERRAIN_IS_DEEP_WATER( this->bOverTerrainType ) )
val = max(0, val - 10);
return (UINT8)(val);
}
INT32 CheckBleeding( SOLDIERTYPE *pSoldier )
{
INT8 bBandaged; //,savedOurTurn;
+3
View File
@@ -1932,6 +1932,9 @@ public:
// Flugente: do we have a specific item in our inventory?
BOOLEAN HasItem( UINT16 usItem );
BOOLEAN SelfDetonate(); // AI-only: blow up explosive in own inventory. Do NOT, repeat, NOT use this with mercs!
// Flugente: chance to defeat a water snake instead of being hit by it
UINT8 GetWaterSnakeDefenseChance( );
//////////////////////////////////////////////////////////////////////////////
}; // SOLDIERTYPE;
+2
View File
@@ -176,6 +176,8 @@ void HandleTacticalEndTurn( )
// decay AI warning values from corpses
DecayRottingCorpseAIWarnings();
HandleEnvironmentHazard( );
if(gGameExternalOptions.gfAllowReinforcements)//dnl ch68 100913
{
if ( gTacticalStatus.Team[ENEMY_TEAM].bTeamActive || gfPendingNonPlayerTeam[ENEMY_TEAM] ||
+2
View File
@@ -486,6 +486,8 @@ void EndTurnEvents( void )
// decay AI warning values from corpses
DecayRottingCorpseAIWarnings();
HandleEnvironmentHazard( );
#ifdef JA2UB
//Ja25 UB
+126
View File
@@ -22,11 +22,19 @@
#include "Random.h"
#include "strategicmap.h"
#include "GameSettings.h"
#include "Points.h" // added by Flugente
#include "Campaign.h" // added by Flugente
#include "Isometric Utils.h" // added by Flugente
#include "Strategic Movement.h" // added by Flugente
#include "tiledef.h" // added by Flugente
#include "worldman.h" // added by Flugente
#endif
#include "Text.h"
#include "connect.h"
extern SECTOR_EXT_DATA SectorExternalData[256][4];
//effects whether or not time of day effects the lighting. Underground
//maps have an ambient light level that is saved in the map, and doesn't change.
BOOLEAN gfBasement = FALSE;
@@ -1088,3 +1096,121 @@ INT8 SectorTemperature( UINT32 uiTime, INT16 sSectorX, INT16 sSectorY, INT8 bSec
return( gubGlobalTemperature );
}
}
// Flugente: fun with snakes
void AddSnakeAmim( INT32 sGridno, UINT8 usDirection )
{
if ( !TileIsOutOfBounds( sGridno ) )
{
ANITILE_PARAMS AniParams;
memset( &AniParams, 0, sizeof(ANITILE_PARAMS) );
AniParams.sGridNo = sGridno;
AniParams.ubLevelID = ANI_OBJECT_LEVEL;
AniParams.sDelay = 100;
AniParams.sStartFrame = 0;
AniParams.uiFlags = ANITILE_CACHEDTILE | ANITILE_FORWARD | ANITILE_USE_DIRECTION_FOR_START_FRAME;//| ANITILE_LOOPING;
AniParams.sX = CenterX( sGridno );
AniParams.sY = CenterY( sGridno );
AniParams.sZ = 0;
strcpy( AniParams.zCachedFile, "TILECACHE\\WATERSNAKE_MOVE.sti" );
AniParams.uiUserData3 = gOneCCDirection[usDirection];
CreateAnimationTile( &AniParams );
}
}
// Flugente: the environment can interact with soldiers
void HandleEnvironmentHazard( )
{
UINT8 sector = (UINT8)SECTOR( gWorldSectorX, gWorldSectorY );
UINT8 ubTraverseType = SectorInfo[sector].ubTraversability[THROUGH_STRATEGIC_MOVE];
if ( gGameExternalOptions.gfAllowSnakes && !gbWorldSectorZ && Chance( SectorExternalData[sector][0].snakechance ) )
{
// there can be up to 3 attacks at the same time
int actionstodo = 3;
BOOLEAN soundplayed = FALSE;
SOLDIERTYPE *pSoldier = NULL;
UINT32 uiCnt = 0;
for ( uiCnt = 0, pSoldier = MercPtrs[uiCnt]; uiCnt < TOTAL_SOLDIERS; ++uiCnt, ++pSoldier )
{
if ( pSoldier->bActive && !pSoldier->bSectorZ && pSoldier->sSectorX == gWorldSectorX && pSoldier->sSectorY == gWorldSectorY && pSoldier->stats.bLife > 0 )
{
if ( TERRAIN_IS_WATER( pSoldier->bOverTerrainType ) && pSoldier->pathing.bLevel <= 0 )
{
// there is a chance to be attacked, it is increased if we have open wounds
UINT16 chancetobeattacked = 20 + pSoldier->bBleeding + 20 * TERRAIN_IS_DEEP_WATER( pSoldier->bOverTerrainType );
if ( Chance( chancetobeattacked ) )
{
// there is a chance we defeat the snake and do not take damage, but get a bit of exp
if ( Chance( pSoldier->GetWaterSnakeDefenseChance( ) ) )
{
StatChange( pSoldier, EXPERAMT, 10, FROM_SUCCESS );
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szSnakeText[0], pSoldier->GetName( ) );
}
// otherwise, the snake damages us
else
{
INT16 damage = 10 + Random( 11 );
pSoldier->SoldierTakeDamage( 0, damage, damage * 100, TAKE_DAMAGE_TENTACLES, NOBODY, pSoldier->sGridNo, 0, TRUE );
// if this is a swamp, handle possible extra infection
if ( ubTraverseType == SWAMP || ubTraverseType == SWAMP_ROAD )
{
HandlePossibleInfection( pSoldier, NULL, INFECTION_TYPE_SWAMP );
}
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szSnakeText[1], pSoldier->GetName( ) );
}
// in any case, play animation and lose APs
DeductPoints( pSoldier, 20, 200, DISABLED_INTERRUPT );
AddSnakeAmim( pSoldier->sGridNo, Random( NUM_WORLD_DIRECTIONS ) );
if ( !soundplayed )
{
PlayJA2SampleFromFile( Chance( 50 ) ? "Sounds\\WATERSNAKE_ATTACK_01.WAV" : "Sounds\\WATERSNAKE_ATTACK_02.WAV", RATE_11025, SoundVolume( HIGHVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ) );
soundplayed = TRUE;
}
--actionstodo;
}
if ( actionstodo <= 0 )
break;
}
}
}
// if there are actions left, just have the snakes travel ominously in random locations
int cnt = 0;
while ( actionstodo > 0 && cnt < 1000 )
{
INT32 sGridNo = RandomGridNo( );
if ( TERRAIN_IS_WATER( GetTerrainType( sGridNo ) ) )
{
AddSnakeAmim( sGridNo, Random( NUM_WORLD_DIRECTIONS ) );
--actionstodo;
}
++cnt;
}
if ( !actionstodo && !soundplayed )
{
PlayJA2SampleFromFile( Chance( 50 ) ? "Sounds\\WATERSNAKE_MOVE_01.WAV" : "Sounds\\WATERSNAKE_MOVE_02.WAV", RATE_11025, LOWVOLUME, 1, MIDDLEPAN );
}
}
}
+2
View File
@@ -83,5 +83,7 @@ INT8 SectorTemperature( UINT32 uiTime, INT16 sSectorX, INT16 sSectorY, INT8 bSec
void UpdateTemperature( UINT8 ubTemperatureCode );
// Flugente: the environment can interact with soldiers
void HandleEnvironmentHazard( );
#endif
+3
View File
@@ -2971,6 +2971,9 @@ extern STR16 szNonProfileMerchantText[];
// Flugente: externalised weather
extern STR16 szWeatherTypeText[];
// Flugente: snakes
extern STR16 szSnakeText[];
#define TACTICAL_INVENTORY_DIALOG_NUM 16
#define TACTICAL_COVER_DIALOG_NUM 16
+6
View File
@@ -11137,6 +11137,12 @@ STR16 szWeatherTypeText[] = // TODO.Translate
L"snow",
};
STR16 szSnakeText[] =
{
L"%s evaded a snake attack!",
L"%s was attacked by a snake!",
};
// WANNE: Some Chinese specific strings that needs to be in unicode!
STR16 ChineseSpecString1 = L"%"; //defined in _ChineseText.cpp as this file is already unicode
STR16 ChineseSpecString2 = L"*%3d%%%"; //defined in _ChineseText.cpp as this file is already unicode
+6
View File
@@ -11154,4 +11154,10 @@ STR16 szWeatherTypeText[] = // TODO.Translate
L"snow",
};
STR16 szSnakeText[] =
{
L"%s evaded a snake attack!",
L"%s was attacked by a snake!",
};
#endif //DUTCH
+6
View File
@@ -11137,4 +11137,10 @@ STR16 szWeatherTypeText[] =
L"snow",
};
STR16 szSnakeText[] =
{
L"%s evaded a snake attack!",
L"%s was attacked by a snake!",
};
#endif //ENGLISH
+6
View File
@@ -11136,4 +11136,10 @@ STR16 szWeatherTypeText[] = // TODO.Translate
L"snow",
};
STR16 szSnakeText[] =
{
L"%s evaded a snake attack!",
L"%s was attacked by a snake!",
};
#endif //FRENCH
+6
View File
@@ -10966,4 +10966,10 @@ STR16 szWeatherTypeText[] = // TODO.Translate
L"snow",
};
STR16 szSnakeText[] =
{
L"%s evaded a snake attack!",
L"%s was attacked by a snake!",
};
#endif //GERMAN
+6
View File
@@ -11145,4 +11145,10 @@ STR16 szWeatherTypeText[] = // TODO.Translate
L"snow",
};
STR16 szSnakeText[] =
{
L"%s evaded a snake attack!",
L"%s was attacked by a snake!",
};
#endif //ITALIAN
+4 -3
View File
@@ -395,9 +395,10 @@ STR16 gzIMPMajorTraitsHelpTextsSurvival[] =
L"迷彩涂装退色的速度 -%d%s\n",// L"-%d%s worn out speed of camouflage by water or time\n",
L"Can spot tracks up to %d tiles away\n", //L"Can spot tracks up to %d tiles away\n",
L" %s%d%% 疾病抗性\n",//L" %s%d%% disease resistance\n",
L" %s%d%% 食物消耗\n",//L" %s%d%% food consumption\n",
L" %s%d%% 水消耗\n",//L" %s%d%% water consumption\n",
L"%s%d%% 疾病抗性\n",//L" %s%d%% disease resistance\n",
L"%s%d%% 食物消耗\n",//L" %s%d%% food consumption\n",
L"%s%d%% 水消耗\n",//L" %s%d%% water consumption\n",
L"+%d%% snake evasion\n", // TODO.Translate
};
STR16 gzIMPMinorTraitsHelpTextsNone[]=
+4 -3
View File
@@ -396,9 +396,10 @@ STR16 gzIMPMajorTraitsHelpTextsSurvival[] = // TODO.Translate
L"-%d%s worn out speed of camouflage by water or time\n",
L"Can spot tracks up to %d tiles away\n",
L" %s%d%% disease resistance\n",
L" %s%d%% food consumption\n",
L" %s%d%% water consumption\n",
L"%s%d%% disease resistance\n",
L"%s%d%% food consumption\n",
L"%s%d%% water consumption\n",
L"+%d%% snake evasion\n", // TODO.Translate
};
STR16 gzIMPMinorTraitsHelpTextsNone[]=
+4 -3
View File
@@ -397,9 +397,10 @@ STR16 gzIMPMajorTraitsHelpTextsSurvival[] =
L"-%d%s worn out speed of camouflage by water or time\n",
L"Can spot tracks up to %d tiles away\n",
L" %s%d%% disease resistance\n",
L" %s%d%% food consumption\n",
L" %s%d%% water consumption\n",
L"%s%d%% disease resistance\n",
L"%s%d%% food consumption\n",
L"%s%d%% water consumption\n",
L"+%d%% snake evasion\n",
};
STR16 gzIMPMinorTraitsHelpTextsNone[]=
+4 -3
View File
@@ -395,9 +395,10 @@ STR16 gzIMPMajorTraitsHelpTextsSurvival[] = // TODO.Translate
L"-%d%s de l'usure du camouflage due au temps ou à l'eau\n",
L"Can spot tracks up to %d tiles away\n", // TODO.Translate
L" %s%d%% disease resistance\n",
L" %s%d%% food consumption\n",
L" %s%d%% water consumption\n",
L"%s%d%% disease resistance\n",
L"%s%d%% food consumption\n",
L"%s%d%% water consumption\n",
L"+%d%% snake evasion\n", // TODO.Translate
};
STR16 gzIMPMinorTraitsHelpTextsNone[]=
+4 -3
View File
@@ -398,9 +398,10 @@ STR16 gzIMPMajorTraitsHelpTextsSurvival[] =
L"-%d%s Abnutzung von Tarnfarbe durch Wasser oder Zeit\n",
L"Kann Spuren bis zu %d Felder weit erkennen\n",
L" %s%d%% disease resistance\n", //TODO.Translate
L" %s%d%% food consumption\n",
L" %s%d%% water consumption\n",
L"%s%d%% disease resistance\n", //TODO.Translate
L"%s%d%% food consumption\n",
L"%s%d%% water consumption\n",
L"+%d%% snake evasion\n", // TODO.Translate
};
STR16 gzIMPMinorTraitsHelpTextsNone[]=
+4 -3
View File
@@ -394,9 +394,10 @@ STR16 gzIMPMajorTraitsHelpTextsSurvival[] = // TODO.Translate
L"-%d%s worn out speed of camouflage by water or time\n",
L"Can spot tracks up to %d tiles away\n",
L" %s%d%% disease resistance\n",
L" %s%d%% food consumption\n",
L" %s%d%% water consumption\n",
L"%s%d%% disease resistance\n",
L"%s%d%% food consumption\n",
L"%s%d%% water consumption\n",
L"+%d%% snake evasion\n", // TODO.Translate
};
STR16 gzIMPMinorTraitsHelpTextsNone[]=
+4 -3
View File
@@ -396,9 +396,10 @@ STR16 gzIMPMajorTraitsHelpTextsSurvival[] = // TODO.Translate
L"-%d%s worn out speed of camouflage by water or time\n",
L"Can spot tracks up to %d tiles away\n",
L" %s%d%% disease resistance\n",
L" %s%d%% food consumption\n",
L" %s%d%% water consumption\n",
L"%s%d%% disease resistance\n",
L"%s%d%% food consumption\n",
L"%s%d%% water consumption\n",
L"+%d%% snake evasion\n", // TODO.Translate
};
STR16 gzIMPMinorTraitsHelpTextsNone[]=
+4 -3
View File
@@ -397,9 +397,10 @@ STR16 gzIMPMajorTraitsHelpTextsSurvival[] =
L"-%d%s к износу камуфляжного покрытия из-за воды и времени\n",
L"Может заметить следы за %d метров\n",
L" %s%d%% к сопротивляемости заболеваниям\n",
L" %s%d%% к потреблению еды\n",
L" %s%d%% к потреблению воды\n",
L"%s%d%% к сопротивляемости заболеваниям\n",
L"%s%d%% к потреблению еды\n",
L"%s%d%% к потреблению воды\n",
L"+%d%% snake evasion\n", // TODO.Translate
};
STR16 gzIMPMinorTraitsHelpTextsNone[]=
+6
View File
@@ -11158,4 +11158,10 @@ STR16 szWeatherTypeText[] = // TODO.Translate
L"snow",
};
STR16 szSnakeText[] =
{
L"%s evaded a snake attack!",
L"%s was attacked by a snake!",
};
#endif //POLISH
+6
View File
@@ -11137,4 +11137,10 @@ STR16 szWeatherTypeText[] = // TODO.Translate
L"snow",
};
STR16 szSnakeText[] =
{
L"%s evaded a snake attack!",
L"%s was attacked by a snake!",
};
#endif //RUSSIAN