New feature: food system requires mercs to eat and drink in order to survive

- food and water levels are lowered every hour, eat food to survive
- not doing so leads to various penalties and ultimately death
- added food items for that purpose. Food can degrade over time. Rotten food poisons.
- Mercs automatically consume food if hungry/thirsty and food is in their inventories
- for more info, see http://www.bears-pit.com/board/ubbthreads.php/topics/307396/Re_Mercs_need_food_and_water_t.html#Post307396
- this feature requires new STI files from the GameDir trunk.

- added a bunch of filler variable to the soldier type, so hopefully savegame compatibility can be maintained easier in the future.

WARNING: This will break savegame compatibility

git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@5411 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
Flugente
2012-07-21 16:41:04 +00:00
parent b95d001812
commit f6bf6bf4aa
54 changed files with 2660 additions and 144 deletions
+190 -2
View File
@@ -158,6 +158,10 @@
#define GIO_OVERHEATING_SETTING_Y GIO_DROPALL_SETTING_Y + CHECK_Y_OFFSET + CORRECTION_Y_OFFSET
#define GIO_OVERHEATING_SETTING_WIDTH CHECK_WIDTH
#define GIO_FOODSYSTEM_SETTING_X SECOND_COLUMN_X + CHECK_X_OFFSET
#define GIO_FOODSYSTEM_SETTING_Y GIO_OVERHEATING_SETTING_Y + CHECK_Y_OFFSET + CORRECTION_Y_OFFSET
#define GIO_FOODSYSTEM_SETTING_WIDTH CHECK_WIDTH
/*********************************
THIRD COLUMN
**********************************/
@@ -581,6 +585,7 @@ UINT8 GetCurrentInventoryAPButtonSetting();
UINT8 GetCurrentNCTHButtonSetting();
UINT8 GetCurrentIISButtonSetting();
UINT8 GetCurrentOverheatingButtonSetting();
UINT8 GetCurrentFoodSystemButtonSetting();
void DoneFadeOutForExitGameInitOptionScreen( void );
void DoneFadeInForExitGameInitOptionScreen( void );
@@ -694,6 +699,7 @@ UINT32 GameInitOptionsScreenInit( void )
gGameOptions.fUseNCTH = FALSE;
gGameOptions.fImprovedInterruptSystem = FALSE;
gGameOptions.fWeaponOverheating = FALSE;
gGameOptions.fFoodSystem = FALSE;
gGameOptions.fAirStrikes = FALSE;
gGameOptions.fTurnTimeLimit = FALSE;
@@ -1285,7 +1291,36 @@ BOOLEAN EnterGIOScreen()
if( gGameOptions.fWeaponOverheating )
ButtonList[ guiOverheatingOptionToggles[ GIO_BUTTON_ON ] ]->uiFlags |= BUTTON_CLICKED_ON;
else
ButtonList[ guiOverheatingOptionToggles[ GIO_BUTTON_OFF ] ]->uiFlags |= BUTTON_CLICKED_ON;
ButtonList[ guiOverheatingOptionToggles[ GIO_BUTTON_OFF ] ]->uiFlags |= BUTTON_CLICKED_ON;
///////////////////////////////////////////////////////////////////////////////////////////////////////
// FOOD SYSTEM ON/OFF SETTING
guiFoodSystemOptionTogglesImage[ GIO_BUTTON_OFF ] = UseLoadedButtonImage( guiTraitsOptionTogglesImage[ GIO_TRAITS_OLD ], -1,1,-1,3,-1 );
guiFoodSystemOptionToggles[ GIO_BUTTON_OFF ] = CreateIconAndTextButton( guiFoodSystemOptionTogglesImage[ GIO_BUTTON_OFF ], gzGIOScreenText[ GIO_DROPALL_OFF_TEXT ], GIO_TOGGLE_TEXT_FONT,
GIO_TOGGLE_TEXT_COLOR, NO_SHADOW,
GIO_TOGGLE_TEXT_COLOR, NO_SHADOW,
TEXT_CJUSTIFIED,
(GIO_FOODSYSTEM_SETTING_X), (GIO_FOODSYSTEM_SETTING_Y + 10), BUTTON_TOGGLE, MSYS_PRIORITY_HIGH,
DEFAULT_MOVE_CALLBACK, BtnGIOFoodSystemOffCallback);
guiFoodSystemOptionTogglesImage[ GIO_BUTTON_ON ] = UseLoadedButtonImage( guiTraitsOptionTogglesImage[ GIO_TRAITS_OLD ], -1,1,-1,3,-1 );
guiFoodSystemOptionToggles[ GIO_BUTTON_ON ] = CreateIconAndTextButton( guiFoodSystemOptionTogglesImage[ GIO_BUTTON_ON ], gzGIOScreenText[ GIO_DROPALL_ON_TEXT ], GIO_TOGGLE_TEXT_FONT,
GIO_TOGGLE_TEXT_COLOR, NO_SHADOW,
GIO_TOGGLE_TEXT_COLOR, NO_SHADOW,
TEXT_CJUSTIFIED,
(GIO_FOODSYSTEM_SETTING_X + 74), (GIO_FOODSYSTEM_SETTING_Y + 10), BUTTON_TOGGLE, MSYS_PRIORITY_HIGH,
DEFAULT_MOVE_CALLBACK, BtnGIOFoodSystemOnCallback );
SpecifyButtonSoundScheme( guiFoodSystemOptionToggles[ GIO_BUTTON_OFF ], BUTTON_SOUND_SCHEME_BIGSWITCH3 );
SpecifyButtonSoundScheme( guiFoodSystemOptionToggles[ GIO_BUTTON_ON ], BUTTON_SOUND_SCHEME_BIGSWITCH3 );
MSYS_SetBtnUserData(guiFoodSystemOptionToggles[ GIO_BUTTON_OFF ],0, 0 );
MSYS_SetBtnUserData(guiFoodSystemOptionToggles[ GIO_BUTTON_ON ],0, 1 );
if( gGameOptions.fFoodSystem )
ButtonList[ guiFoodSystemOptionToggles[ GIO_BUTTON_ON ] ]->uiFlags |= BUTTON_CLICKED_ON;
else
ButtonList[ guiFoodSystemOptionToggles[ GIO_BUTTON_OFF ] ]->uiFlags |= BUTTON_CLICKED_ON;
///////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -2257,6 +2292,37 @@ void BtnGIOOverheatingOnCallback(GUI_BUTTON *btn,INT32 reason)
}
}
void BtnGIOFoodSystemOffCallback(GUI_BUTTON *btn,INT32 reason)
{
if (!(btn->uiFlags & BUTTON_ENABLED))
return;
if( reason & MSYS_CALLBACK_REASON_LBUTTON_DWN )
{
RestoreExternBackgroundRect( (GIO_FOODSYSTEM_SETTING_X), (GIO_FOODSYSTEM_SETTING_Y + 10), 230, 40 );
ButtonList[ guiFoodSystemOptionToggles[ GIO_BUTTON_ON ] ]->uiFlags &= ~BUTTON_CLICKED_ON;
btn->uiFlags|=(BUTTON_CLICKED_ON);
PlayButtonSound( guiFoodSystemOptionToggles[ GIO_BUTTON_OFF ], BUTTON_SOUND_CLICKED_ON );
}
}
void BtnGIOFoodSystemOnCallback(GUI_BUTTON *btn,INT32 reason)
{
if (!(btn->uiFlags & BUTTON_ENABLED))
return;
if( reason & MSYS_CALLBACK_REASON_LBUTTON_DWN )
{
RestoreExternBackgroundRect( (GIO_FOODSYSTEM_SETTING_X), (GIO_FOODSYSTEM_SETTING_Y + 10), 230, 40 );
ButtonList[ guiFoodSystemOptionToggles[ GIO_BUTTON_OFF ] ]->uiFlags &= ~BUTTON_CLICKED_ON;
btn->uiFlags|=(BUTTON_CLICKED_ON);
PlayButtonSound( guiFoodSystemOptionToggles[ GIO_BUTTON_ON ], BUTTON_SOUND_CLICKED_ON );
}
}
BOOLEAN ExitGIOScreen()
{
UINT16 cnt;
@@ -2393,6 +2459,13 @@ BOOLEAN ExitGIOScreen()
UnloadButtonImage( guiOverheatingOptionTogglesImage[ cnt ] );
}
// Destroy Food System Cost setting buttons
for( cnt=0; cnt<GIO_NUM_ONOFF_BUTTONS; cnt++)
{
RemoveButton( guiFoodSystemOptionToggles[ cnt ] );
UnloadButtonImage( guiFoodSystemptionTogglesImage[ cnt ] );
}
gfGIOButtonsAllocated = FALSE;
//If we are starting the game stop playing the music
@@ -2568,6 +2641,8 @@ BOOLEAN RenderGIOScreen()
DisplayWrappedString( (GIO_IIS_SETTING_X - 6), (UINT16)(GIO_IIS_SETTING_Y-GIO_GAP_BN_SETTINGS + GIO_TITLE_DISTANCE), GIO_IIS_SETTING_WIDTH + 14, 2, GIO_TOGGLE_TEXT_FONT, GIO_TOGGLE_TEXT_COLOR, gzGIOScreenText[ GIO_IIS_TITLE_TEXT ], FONT_MCOLOR_BLACK, FALSE, CENTER_JUSTIFIED );
//Display the Weapon Overheating Settings Title Text
DisplayWrappedString( (GIO_OVERHEATING_SETTING_X - 6), (UINT16)(GIO_OVERHEATING_SETTING_Y-GIO_GAP_BN_SETTINGS + GIO_TITLE_DISTANCE), GIO_OVERHEATING_SETTING_WIDTH + 14, 2, GIO_TOGGLE_TEXT_FONT, GIO_TOGGLE_TEXT_COLOR, gzGIOScreenText[ GIO_OVERHEATING_TITLE_TEXT ], FONT_MCOLOR_BLACK, FALSE, CENTER_JUSTIFIED );
//Display the Food System Settings Title Text
DisplayWrappedString( (GIO_FOODSYSTEM_SETTING_X - 6), (UINT16)(GIO_FOODSYSTEM_SETTING_Y-GIO_GAP_BN_SETTINGS + GIO_TITLE_DISTANCE), GIO_FOODSYSTEM_SETTING_WIDTH + 14, 2, GIO_TOGGLE_TEXT_FONT, GIO_TOGGLE_TEXT_COLOR, gzGIOScreenText[ GIO_FOODSYSTEM_TITLE_TEXT ], FONT_MCOLOR_BLACK, FALSE, CENTER_JUSTIFIED );
return( TRUE );
}
@@ -2822,6 +2897,20 @@ UINT8 GetCurrentOverheatingButtonSetting()
return( 0 );
}
UINT8 GetCurrentFoodSystemButtonSetting()
{
UINT8 cnt;
for( cnt=0; cnt<GIO_NUM_ONOFF_BUTTONS; cnt++)
{
if( ButtonList[ guiFoodSystemOptionToggles[ cnt ] ]->uiFlags & BUTTON_CLICKED_ON )
{
return( cnt );
}
}
return( 0 );
}
void DoneFadeOutForExitGameInitOptionScreen( void )
{
// loop through and get the status of all the buttons
@@ -2891,6 +2980,7 @@ void DoneFadeOutForExitGameInitOptionScreen( void )
gGameOptions.fUseNCTH = GetCurrentNCTHButtonSetting();
gGameOptions.fImprovedInterruptSystem = GetCurrentIISButtonSetting();
gGameOptions.fWeaponOverheating = GetCurrentOverheatingButtonSetting();
gGameOptions.fFoodSystem = GetCurrentFoodSystemButtonSetting();
gubGIOExitScreen = INIT_SCREEN;
@@ -3123,6 +3213,10 @@ void RenderGIOSmallSelectionFrame(INT16 sX, INT16 sY)
#define GIO_OVERHEATING_SETTING_Y GIO_DROPALL_SETTING_Y + CHECK_Y_OFFSET + CORRECTION_Y_OFFSET
#define GIO_OVERHEATING_SETTING_WIDTH CHECK_WIDTH
#define GIO_FOODSYSTEM_SETTING_X SECOND_COLUMN_X + CHECK_X_OFFSET
#define GIO_FOODSYSTEM_SETTING_Y GIO_OVERHEATING_SETTING_Y + CHECK_Y_OFFSET + CORRECTION_Y_OFFSET
#define GIO_FOODSYSTEM_SETTING_WIDTH CHECK_WIDTH
/*********************************
THIRD COLUMN
**********************************/
@@ -3176,6 +3270,7 @@ void RenderGIOSmallSelectionFrame(INT16 sX, INT16 sY)
#define JA2SP_USE_NCTH "USE_NCTH"
#define JA2SP_USE_IIS "IMPROVED_INTERRUPT_SYSTEM"
#define JA2SP_OVERHEATING "WEAPON_OVERHEATING"
#define JA2SP_FOODSYSTEM "FOOD_SYSTEM"
//Difficulty settings
@@ -3414,6 +3509,13 @@ UINT32 guiOverheatingOptionToggles[ GIO_NUM_ONOFF_BUTTONS ];
void BtnGIOOverheatingOffCallback(GUI_BUTTON *btn,INT32 reason);
void BtnGIOOverheatingOnCallback(GUI_BUTTON *btn,INT32 reason);
// Food System
UINT32 guiFoodSystemOptionTogglesImage[ GIO_NUM_ONOFF_BUTTONS ];
UINT32 guiFoodSystemOptionToggles[ GIO_NUM_ONOFF_BUTTONS ];
void BtnGIOFoodSystemOffCallback(GUI_BUTTON *btn,INT32 reason);
void BtnGIOFoodSystemOnCallback(GUI_BUTTON *btn,INT32 reason);
UINT32 guiTimedTurnToggles[ GIO_NUM_TIMED_TURN_OPTIONS ];
void BtnTimedTurnsTogglesCallback(GUI_BUTTON *btn,INT32 reason);
@@ -3444,6 +3546,7 @@ UINT8 GetCurrentInventoryAPButtonSetting();
UINT8 GetCurrentNCTHButtonSetting();
UINT8 GetCurrentIISButtonSetting();
UINT8 GetCurrentOverheatingButtonSetting();
UINT8 GetCurrentFoodSystemButtonSetting();
void DoneFadeOutForExitGameInitOptionScreen( void );
void DoneFadeInForExitGameInitOptionScreen( void );
@@ -3550,6 +3653,7 @@ UINT32 GameInitOptionsScreenInit( void )
gGameOptions.fUseNCTH = (BOOLEAN)props.getIntProperty(JA2SP_INI_INITIAL_SECTION, JA2SP_USE_NCTH, 0);
gGameOptions.fImprovedInterruptSystem = (BOOLEAN)props.getIntProperty(JA2SP_INI_INITIAL_SECTION, JA2SP_USE_IIS, 0);
gGameOptions.fWeaponOverheating = (BOOLEAN)props.getIntProperty(JA2SP_INI_INITIAL_SECTION, JA2SP_OVERHEATING, 0);
gGameOptions.fFoodSystem = (BOOLEAN)props.getIntProperty(JA2SP_INI_INITIAL_SECTION, JA2SP_FOODSYSTEM, 0);
// Air strikes
gGameOptions.fAirStrikes = FALSE;
@@ -4140,7 +4244,36 @@ BOOLEAN EnterGIOScreen()
if( gGameOptions.fWeaponOverheating )
ButtonList[ guiOverheatingOptionToggles[ GIO_BUTTON_ON ] ]->uiFlags |= BUTTON_CLICKED_ON;
else
ButtonList[ guiOverheatingOptionToggles[ GIO_BUTTON_OFF ] ]->uiFlags |= BUTTON_CLICKED_ON;
ButtonList[ guiOverheatingOptionToggles[ GIO_BUTTON_OFF ] ]->uiFlags |= BUTTON_CLICKED_ON;
///////////////////////////////////////////////////////////////////////////////////////////////////////
// FOOD SYSTEM ON/OFF SETTING
guiFoodSystemOptionTogglesImage[ GIO_BUTTON_OFF ] = UseLoadedButtonImage( guiTraitsOptionTogglesImage[ GIO_TRAITS_OLD ], -1,1,-1,3,-1 );
guiFoodSystemOptionToggles[ GIO_BUTTON_OFF ] = CreateIconAndTextButton( guiFoodSystemOptionTogglesImage[ GIO_BUTTON_OFF ], gzGIOScreenText[ GIO_DROPALL_OFF_TEXT ], GIO_TOGGLE_TEXT_FONT,
GIO_TOGGLE_TEXT_COLOR, NO_SHADOW,
GIO_TOGGLE_TEXT_COLOR, NO_SHADOW,
TEXT_CJUSTIFIED,
(GIO_FOODSYSTEM_SETTING_X), (GIO_FOODSYSTEM_SETTING_Y + 10), BUTTON_TOGGLE, MSYS_PRIORITY_HIGH,
DEFAULT_MOVE_CALLBACK, BtnGIOFoodSystemOffCallback);
guiFoodSystemOptionTogglesImage[ GIO_BUTTON_ON ] = UseLoadedButtonImage( guiTraitsOptionTogglesImage[ GIO_TRAITS_OLD ], -1,1,-1,3,-1 );
guiFoodSystemOptionToggles[ GIO_BUTTON_ON ] = CreateIconAndTextButton( guiFoodSystemOptionTogglesImage[ GIO_BUTTON_ON ], gzGIOScreenText[ GIO_DROPALL_ON_TEXT ], GIO_TOGGLE_TEXT_FONT,
GIO_TOGGLE_TEXT_COLOR, NO_SHADOW,
GIO_TOGGLE_TEXT_COLOR, NO_SHADOW,
TEXT_CJUSTIFIED,
(GIO_FOODSYSTEM_SETTING_X + 74), (GIO_FOODSYSTEM_SETTING_Y + 10), BUTTON_TOGGLE, MSYS_PRIORITY_HIGH,
DEFAULT_MOVE_CALLBACK, BtnGIOFoodSystemOnCallback );
SpecifyButtonSoundScheme( guiFoodSystemOptionToggles[ GIO_BUTTON_OFF ], BUTTON_SOUND_SCHEME_BIGSWITCH3 );
SpecifyButtonSoundScheme( guiFoodSystemOptionToggles[ GIO_BUTTON_ON ], BUTTON_SOUND_SCHEME_BIGSWITCH3 );
MSYS_SetBtnUserData(guiFoodSystemOptionToggles[ GIO_BUTTON_OFF ],0, 0 );
MSYS_SetBtnUserData(guiFoodSystemOptionToggles[ GIO_BUTTON_ON ],0, 1 );
if( gGameOptions.fFoodSystem )
ButtonList[ guiFoodSystemOptionToggles[ GIO_BUTTON_ON ] ]->uiFlags |= BUTTON_CLICKED_ON;
else
ButtonList[ guiFoodSystemOptionToggles[ GIO_BUTTON_OFF ] ]->uiFlags |= BUTTON_CLICKED_ON;
///////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -5079,6 +5212,37 @@ void BtnGIOOverheatingOnCallback(GUI_BUTTON *btn,INT32 reason)
}
}
void BtnGIOFoodSystemOffCallback(GUI_BUTTON *btn,INT32 reason)
{
if (!(btn->uiFlags & BUTTON_ENABLED))
return;
if( reason & MSYS_CALLBACK_REASON_LBUTTON_DWN )
{
RestoreExternBackgroundRect( (GIO_FOODSYSTEM_SETTING_X), (GIO_FOODSYSTEM_SETTING_Y + 10), 230, 40 );
ButtonList[ guiFoodSystemOptionToggles[ GIO_BUTTON_ON ] ]->uiFlags &= ~BUTTON_CLICKED_ON;
btn->uiFlags|=(BUTTON_CLICKED_ON);
PlayButtonSound( guiFoodSystemOptionToggles[ GIO_BUTTON_OFF ], BUTTON_SOUND_CLICKED_ON );
}
}
void BtnGIOFoodSystemOnCallback(GUI_BUTTON *btn,INT32 reason)
{
if (!(btn->uiFlags & BUTTON_ENABLED))
return;
if( reason & MSYS_CALLBACK_REASON_LBUTTON_DWN )
{
RestoreExternBackgroundRect( (GIO_FOODSYSTEM_SETTING_X), (GIO_FOODSYSTEM_SETTING_Y + 10), 230, 40 );
ButtonList[ guiFoodSystemOptionToggles[ GIO_BUTTON_OFF ] ]->uiFlags &= ~BUTTON_CLICKED_ON;
btn->uiFlags|=(BUTTON_CLICKED_ON);
PlayButtonSound( guiFoodSystemOptionToggles[ GIO_BUTTON_ON ], BUTTON_SOUND_CLICKED_ON );
}
}
BOOLEAN ExitGIOScreen()
{
UINT16 cnt;
@@ -5215,6 +5379,13 @@ BOOLEAN ExitGIOScreen()
UnloadButtonImage( guiOverheatingOptionTogglesImage[ cnt ] );
}
// Destroy Food System Cost setting buttons
for( cnt=0; cnt<GIO_NUM_ONOFF_BUTTONS; cnt++)
{
RemoveButton( guiFoodSystemOptionToggles[ cnt ] );
UnloadButtonImage( guiFoodSystemOptionTogglesImage[ cnt ] );
}
gfGIOButtonsAllocated = FALSE;
//If we are starting the game stop playing the music
@@ -5390,6 +5561,8 @@ BOOLEAN RenderGIOScreen()
DisplayWrappedString( (GIO_IIS_SETTING_X - 6), (UINT16)(GIO_IIS_SETTING_Y-GIO_GAP_BN_SETTINGS + GIO_TITLE_DISTANCE), GIO_IIS_SETTING_WIDTH + 14, 2, GIO_TOGGLE_TEXT_FONT, GIO_TOGGLE_TEXT_COLOR, gzGIOScreenText[ GIO_IIS_TITLE_TEXT ], FONT_MCOLOR_BLACK, FALSE, CENTER_JUSTIFIED );
//Display the Weapon Overheating Settings Title Text
DisplayWrappedString( (GIO_OVERHEATING_SETTING_X - 6), (UINT16)(GIO_OVERHEATING_SETTING_Y-GIO_GAP_BN_SETTINGS + GIO_TITLE_DISTANCE), GIO_OVERHEATING_SETTING_WIDTH + 14, 2, GIO_TOGGLE_TEXT_FONT, GIO_TOGGLE_TEXT_COLOR, gzGIOScreenText[ GIO_OVERHEATING_TITLE_TEXT ], FONT_MCOLOR_BLACK, FALSE, CENTER_JUSTIFIED );
//Display the Food System Settings Title Text
DisplayWrappedString( (GIO_FOODSYSTEM_SETTING_X - 6), (UINT16)(GIO_FOODSYSTEM_SETTING_Y-GIO_GAP_BN_SETTINGS + GIO_TITLE_DISTANCE), GIO_FOODSYSTEM_SETTING_WIDTH + 14, 2, GIO_TOGGLE_TEXT_FONT, GIO_TOGGLE_TEXT_COLOR, gzGIOScreenText[ GIO_FOODSYSTEM_TITLE_TEXT ], FONT_MCOLOR_BLACK, FALSE, CENTER_JUSTIFIED );
return( TRUE );
@@ -5631,6 +5804,20 @@ UINT8 GetCurrentOverheatingButtonSetting()
return( 0 );
}
UINT8 GetCurrentFoodSystemButtonSetting()
{
UINT8 cnt;
for( cnt=0; cnt<GIO_NUM_ONOFF_BUTTONS; cnt++)
{
if( ButtonList[ guiFoodSystemOptionToggles[ cnt ] ]->uiFlags & BUTTON_CLICKED_ON )
{
return( cnt );
}
}
return( 0 );
}
void DoneFadeOutForExitGameInitOptionScreen( void )
{
// loop through and get the status of all the buttons
@@ -5690,6 +5877,7 @@ void DoneFadeOutForExitGameInitOptionScreen( void )
gGameOptions.fUseNCTH = GetCurrentNCTHButtonSetting();
gGameOptions.fImprovedInterruptSystem = GetCurrentIISButtonSetting();
gGameOptions.fWeaponOverheating = GetCurrentOverheatingButtonSetting();
gGameOptions.fFoodSystem = GetCurrentFoodSystemButtonSetting();
// gubGIOExitScreen = INIT_SCREEN;
+16
View File
@@ -616,6 +616,7 @@ void InitGameOptions()
gGameOptions.fUseNCTH = FALSE;
gGameOptions.fImprovedInterruptSystem = TRUE;
gGameOptions.fWeaponOverheating = TRUE;
gGameOptions.fFoodSystem = FALSE;
//CHRISL: override default inventory mode when in low res
if(IsNIVModeValid(true) == FALSE)
@@ -1379,12 +1380,26 @@ void LoadGameExternalOptions()
//################# Tactical Poison Settings ##################
gGameExternalOptions.ubPoisonBaseMedicalSkillToCure = iniReader.ReadInteger("Tactical Poison Settings", "POISON_BASE_MEDICAL_SKILL_TO_CURE", 50, 1, 100);
gGameExternalOptions.sPoisonMedicalPtsToCureMultiplicator = iniReader.ReadFloat("Tactical Poison Settings", "POISON_MEDICAL_POINTS_TO_CURE_MULTIPLICATOR", 0.5, 0.1, 10.0);
gGameExternalOptions.sZombiePoisonDamagePercentage = iniReader.ReadInteger("Tactical Poison Settings", "ZOMBIE_POISON_DAMAGE_PERCENTAGE", 50, 0, 100);
gGameExternalOptions.sPoisonInfectionDamageMultiplier = iniReader.ReadFloat("Tactical Poison Settings", "POISON_INFECTION_DAMAGE_MULTIPLIER", 4.0, 1.0, 10.0);
//################# Tactical Fortification Settings ##################
gGameExternalOptions.fFortificationAllowInHostileSector = iniReader.ReadBoolean("Tactical Fortification Settings", "FORTIFICATION_ALLOW_IN_HOSTILE_SECTOR", FALSE);
//################# Tactical Food Settings ##################
gGameExternalOptions.usFoodDigestionHourlyBaseFood = iniReader.ReadInteger("Tactical Food Settings", "FOOD_DIGESTION_HOURLY_BASE_FOOD", 20, 0, 250);
gGameExternalOptions.usFoodDigestionHourlyBaseDrink = iniReader.ReadInteger("Tactical Food Settings", "FOOD_DIGESTION_HOURLY_BASE_DRINK", 130, 0, 250);
gGameExternalOptions.sFoodDigestionSleep = iniReader.ReadFloat("Tactical Food Settings", "FOOD_DIGESTION_SLEEP", 0.6, 0.0, 10.0);
gGameExternalOptions.sFoodDigestionTravelVehicle = iniReader.ReadFloat("Tactical Food Settings", "FOOD_DIGESTION_TRAVEL_VEHICLE", 0.8, 0.0, 10.0);
gGameExternalOptions.sFoodDigestionTravel = iniReader.ReadFloat("Tactical Food Settings", "FOOD_DIGESTION_TRAVEL", 1.5, 0.0, 10.0);
gGameExternalOptions.sFoodDigestionAssignment = iniReader.ReadFloat("Tactical Food Settings", "FOOD_DIGESTION_ASSIGNMENT", 0.9, 0.0, 10.0);
gGameExternalOptions.sFoodDigestionOnDuty = iniReader.ReadFloat("Tactical Food Settings", "FOOD_DIGESTION_ONDUTY", 1.0, 0.0, 10.0);
gGameExternalOptions.sFoodDigestionCombat = iniReader.ReadFloat("Tactical Food Settings", "FOOD_DIGESTION_COMBAT", 2.0, 0.0, 10.0);
gGameExternalOptions.fFoodDecayInSectors = iniReader.ReadBoolean("Tactical Food Settings", "FOOD_DECAY_IN_SECTORS", TRUE);
gGameExternalOptions.sFoodDecayModificator = iniReader.ReadFloat("Tactical Food Settings", "FOOD_DECAY_MODIFICATOR", 1.0, 0.1, 10.0);
//################# Strategic Gamestart Settings ##################
//Lalien: Game starting time
@@ -2356,6 +2371,7 @@ void LoadGameAPBPConstants()
APBPConstants[AP_JUMPOFFWALL] = DynamicAdjustAPConstants(iniReader.ReadInteger("APConstants","AP_JUMPWALL",24),24);
APBPConstants[AP_FORTIFICATION] = DynamicAdjustAPConstants(iniReader.ReadInteger("APConstants","AP_FORTIFICATION",80),80);
APBPConstants[AP_EAT] = DynamicAdjustAPConstants(iniReader.ReadInteger("APConstants","AP_EAT",80),80);
SetupMaxActionPointsAnimation();
#undef ReadInteger
+16 -1
View File
@@ -234,9 +234,10 @@ typedef struct
BOOLEAN fUseNCTH; // ubFiller: From 499 to 498
BOOLEAN fImprovedInterruptSystem; // ubFiller: From 498 to 497
BOOLEAN fWeaponOverheating; // ubFiller: From 497 to 496
BOOLEAN fFoodSystem; // ubFiler: From 496 to 495
// WANNE: Decrease this filler by 1, for each new UINT8 / BOOLEAN variable, so we can maintain savegame compatibility!!
UINT8 ubFiller[496];
UINT8 ubFiller[495];
} GAME_OPTIONS;
@@ -387,12 +388,26 @@ typedef struct
// Flugente: poison settings
INT32 ubPoisonBaseMedicalSkillToCure;
FLOAT sPoisonMedicalPtsToCureMultiplicator;
INT16 sZombiePoisonDamagePercentage;
FLOAT sPoisonInfectionDamageMultiplier;
// Flugente: fortification settings
BOOLEAN fFortificationAllowInHostileSector;
// Flugente: food settings
UINT16 usFoodDigestionHourlyBaseFood;
UINT16 usFoodDigestionHourlyBaseDrink;
FLOAT sFoodDigestionSleep;
FLOAT sFoodDigestionTravelVehicle;
FLOAT sFoodDigestionTravel;
FLOAT sFoodDigestionAssignment;
FLOAT sFoodDigestionOnDuty;
FLOAT sFoodDigestionCombat;
BOOLEAN fFoodDecayInSectors;
FLOAT sFoodDecayModificator;
//Animation settings
FLOAT giPlayerTurnSpeedUpFactor;
FLOAT giEnemyTurnSpeedUpFactor;
+2 -1
View File
@@ -20,8 +20,9 @@ extern CHAR16 zTrackingNumber[16];
//
// Keeps track of the saved game version. Increment the saved game version whenever
// you will invalidate the saved game file
#define SAVE_GAME_VERSION 132 //131 //125 //124 //114 //113 //112 //111 //110 //109 //108 //107 //106 //105 //104 //103 //102 //101 //100 // 99
#define SAVE_GAME_VERSION 133 // 132 //131 //125 //124 //114 //113 //112 //111 //110 //109 //108 //107 //106 //105 //104 //103 //102 //101 //100 // 99
#define FOOD_CHANGES 133 // changes for food system
#define ZOMBIE_CHANGES 132 // Included some changes for Zombies
#define JA25_UB_INTEGRATION 131 // Before this, the JA25 Unfinished Business code was not integrated (see "Builddefines.h" JA2UB)
#define IMPROVED_INTERRUPT_SYSTEM 130
+4
View File
@@ -380,6 +380,10 @@ BOOLEAN LoadExternalGameplayData(STR directoryName)
strcat(fileName, DRUGSFILENAME);
SGP_THROW_IFFALSE(ReadInDrugsStats(fileName),DRUGSFILENAME);
strcpy(fileName, directoryName);
strcat(fileName, FOODFILENAME);
SGP_THROW_IFFALSE(ReadInFoodStats(fileName),FOODFILENAME);
strcpy(fileName, directoryName);
strcat(fileName, ARMOURSFILENAME);
SGP_THROW_IFFALSE(ReadInArmourStats(fileName),ARMOURSFILENAME);
+1
View File
@@ -198,6 +198,7 @@ BP_JUMPWALL,
AP_JUMPWALL,
AP_JUMPOFFWALL,
AP_FORTIFICATION,
AP_EAT,
TOTAL_APBP_VALUES
};
#endif
+3
View File
@@ -2482,6 +2482,8 @@ void recieveSETTINGS (RPCParameters *rpcParameters) //recive settings from serve
gGameOptions.fUseNCTH = FALSE;
gGameOptions.fImprovedInterruptSystem = FALSE;
gGameOptions.fWeaponOverheating = FALSE;
gGameOptions.fFoodSystem = FALSE;
// Server forces us to play with new Inventory, but NIV is not allowed on the client,
// because of wrong resolution or other stuff
@@ -2703,6 +2705,7 @@ void reapplySETTINGS()
gGameOptions.fUseNCTH = FALSE;
gGameOptions.fImprovedInterruptSystem = FALSE;
gGameOptions.fWeaponOverheating = FALSE;
gGameOptions.fFoodSystem = FALSE;
// WANNE - MP: We have to re-initialize the correct interface
if((UsingNewInventorySystem() == true) && IsNIVModeValid(true))
+41
View File
@@ -1984,6 +1984,47 @@ BOOLEAN SOLDIERTYPE::Load(HWFILE hFile)
numBytesRead = ReadFieldByField(hFile, &this->bExtraWisdom, sizeof(bExtraWisdom), sizeof(INT16), numBytesRead);
numBytesRead = ReadFieldByField(hFile, &this->bExtraExpLevel, sizeof(bExtraExpLevel), sizeof(INT8), numBytesRead);
numBytesRead = ReadFieldByField(hFile, &this->bSoldierFlagMask, sizeof(bSoldierFlagMask), sizeof(INT32), numBytesRead);
if ( guiCurrentSaveGameVersion >= FOOD_CHANGES )
{
numBytesRead = ReadFieldByField(hFile, &this->bFoodLevel, sizeof(bFoodLevel), sizeof(INT32), numBytesRead);
numBytesRead = ReadFieldByField(hFile, &this->bDrinkLevel, sizeof(bDrinkLevel), sizeof(INT32), numBytesRead);
numBytesRead = ReadFieldByField(hFile, &this->usStarveDamageHealth, sizeof(usStarveDamageHealth), sizeof(UINT8), numBytesRead);
numBytesRead = ReadFieldByField(hFile, &this->usStarveDamageStrength, sizeof(usStarveDamageStrength), sizeof(UINT8), numBytesRead);
numBytesRead = ReadFieldByField(hFile, &this->ubFiller, sizeof(ubFiller), sizeof(UINT8), numBytesRead);
}
else
{
//CHRISL: We have to make sure we add a buffer to account for the lack of ubInterruptCounter and that buffer needs to be a full DWORD in size
buffer = 0;
for(int i = 0; i < sizeof(bFoodLevel); ++i)
buffer++;
while((buffer%4) > 0)
buffer++;
for(int i = 0; i < sizeof(bDrinkLevel); ++i)
buffer++;
while((buffer%4) > 0)
buffer++;
for(int i = 0; i < sizeof(usStarveDamageHealth); ++i)
buffer++;
while((buffer%4) > 0)
buffer++;
for(int i = 0; i < sizeof(usStarveDamageStrength); ++i)
buffer++;
while((buffer%4) > 0)
buffer++;
for(int i = 0; i < sizeof(ubFiller); ++i)
buffer++;
while((buffer%4) > 0)
buffer++;
numBytesRead += buffer;
}
#ifdef JA2UB
numBytesRead = ReadFieldByField(hFile, &this->fIgnoreGetupFromCollapseCheck, sizeof(fIgnoreGetupFromCollapseCheck), sizeof(BOOLEAN), numBytesRead);
+72 -18
View File
@@ -63,6 +63,7 @@
// added by SANDRO
#include "AIInternals.h"
#include "Morale.h"
#include "Food.h"
#endif
#include <vector>
#include <queue>
@@ -354,7 +355,7 @@ void UpdatePatientsWhoAreDoneHealing( void );
UINT8 GetMinHealingSkillNeeded( SOLDIERTYPE *pPatient );
// heal patient, given doctor and total healing pts available to doctor at this time
UINT16 HealPatient( SOLDIERTYPE *pPatient, SOLDIERTYPE * pDoctor, UINT16 usHundredthsHealed );
UINT16 HealPatient( SOLDIERTYPE *pPatient, SOLDIERTYPE * pDoctor, UINT16 usHealAmount );
// can item be repaired?
BOOLEAN IsItemRepairable( UINT16 usItem, INT16 bStatus );
@@ -1118,10 +1119,17 @@ BOOLEAN CanCharacterPatient( SOLDIERTYPE *pSoldier )
}
// SANDRO - added check if having damaged stat
for ( UINT8 i = 0; i < NUM_DAMAGABLE_STATS; i++)
for ( UINT8 i = 0; i < NUM_DAMAGABLE_STATS; ++i)
{
if ( pSoldier->ubCriticalStatDamage[i] > 0 )
return ( TRUE );
// Flugente: stats can also be damaged
if ( !gGameOptions.fFoodSystem || ( gGameOptions.fFoodSystem && pSoldier->bFoodLevel > FoodMoraleMods[FOOD_NORMAL].bThreshold && pSoldier->bDrinkLevel > FoodMoraleMods[FOOD_NORMAL].bThreshold ) )
{
if ( pSoldier->usStarveDamageHealth > 0 || pSoldier->usStarveDamageStrength > 0 )
return ( TRUE );
}
}
// Flugente: check if poisoned
@@ -2451,6 +2459,10 @@ UINT16 CalculateHealingPointsForDoctor(SOLDIERTYPE *pDoctor, UINT16 *pusMaxPts,
// adjust for fatigue
ReducePointsForFatigue( pDoctor, &usHealPts );
// Flugente: our food situation influences our effectiveness
if ( gGameOptions.fFoodSystem )
ReducePointsForHunger( pDoctor, &usHealPts );
// count how much medical supplies we have
usKitPts = 100 * TotalMedicalKitPoints( pDoctor );
@@ -2537,6 +2549,9 @@ UINT8 CalculateRepairPointsForRepairman(SOLDIERTYPE *pSoldier, UINT16 *pusMaxPts
// adjust for fatigue
ReducePointsForFatigue( pSoldier, &usRepairPts );
// Flugente: our food situation influences our effectiveness
if ( gGameOptions.fFoodSystem )
ReducePointsForHunger( pSoldier, &usRepairPts );
// figure out what shape his "equipment" is in ("coming" in JA3: Viagra - improves the "shape" your "equipment" is in)
usKitPts = ToolKitPoints( pSoldier );
@@ -2680,10 +2695,17 @@ void UpdatePatientsWhoAreDoneHealing( void )
if( ( pTeamSoldier->bAssignment == PATIENT ) &&( pTeamSoldier->stats.bLife == pTeamSoldier->stats.bLifeMax ) && ( pTeamSoldier->bPoisonSum == 0 ) )
{
// SANDRO - added check if we can help to heal lost stats to this one
for (UINT8 cnt = 0; cnt < NUM_DAMAGABLE_STATS; cnt++)
for (UINT8 cnt = 0; cnt < NUM_DAMAGABLE_STATS; ++cnt)
{
if (pTeamSoldier->ubCriticalStatDamage[cnt] > 0 )
fHasDamagedStat = TRUE;
// Flugente: stats can also be damaged
if ( !gGameOptions.fFoodSystem || ( gGameOptions.fFoodSystem && pSoldier->bFoodLevel > FoodMoraleMods[FOOD_NORMAL].bThreshold && pSoldier->bDrinkLevel > FoodMoraleMods[FOOD_NORMAL].bThreshold ) )
{
if ( pSoldier->usStarveDamageHealth > 0 || pSoldier->usStarveDamageStrength > 0 )
fHasDamagedStat = TRUE;
}
}
if (!fHasDamagedStat )// || !DoctorIsPresent( pTeamSoldier, TRUE ))
AssignmentDone( pTeamSoldier, TRUE, TRUE );
@@ -2988,13 +3010,14 @@ UINT8 GetMinHealingSkillNeeded( SOLDIERTYPE *pPatient )
}
UINT16 HealPatient( SOLDIERTYPE *pPatient, SOLDIERTYPE * pDoctor, UINT16 usHundredthsHealed )
UINT16 HealPatient( SOLDIERTYPE *pPatient, SOLDIERTYPE * pDoctor, UINT16 usHealAmount )
{
//////////////////////////////////////////////////////////////////////////////
// SANDRO - this whole procedure was heavily changed
////////////////////////////////////////////////////
UINT16 usHealingPtsLeft = 0;
UINT16 usTotalHundredthsUsed = 0;
UINT16 usHundredthsHealed = 0;
INT16 sPointsToUse = 0;
INT8 bPointsHealed = 0;
INT8 bMedFactor = 1; // basic medical factor
@@ -3004,7 +3027,7 @@ UINT16 HealPatient( SOLDIERTYPE *pPatient, SOLDIERTYPE * pDoctor, UINT16 usHundr
UINT16 ubReturnDamagedStatRate = 0;
// usPointsLeftToCurePoison will measure how much Hundreths will be left to cure poison
INT16 usPointsLeftToCurePoison = usHundredthsHealed;
INT16 usPointsLeftToCurePoison = usHealAmount;
// Look how much life do we need to heal
sPointsToUse = ( pPatient->stats.bLifeMax - pPatient->stats.bLife );
@@ -3029,7 +3052,7 @@ UINT16 HealPatient( SOLDIERTYPE *pPatient, SOLDIERTYPE * pDoctor, UINT16 usHundr
if ( sPointsToUse > 0 && ( fWillHealLife || fWillRepiarStats ))
{
// here is our maximum, we can heal this time
usHealingPtsLeft = max( 1, ((pPatient->sFractLife + usHundredthsHealed) / 100));
usHealingPtsLeft = max( 1, ((pPatient->sFractLife + usHealAmount) / 100));
// if guy is hurt more than points we have...heal only what we have
if( sPointsToUse > usHealingPtsLeft )
@@ -3075,12 +3098,19 @@ UINT16 HealPatient( SOLDIERTYPE *pPatient, SOLDIERTYPE * pDoctor, UINT16 usHundr
{
pPatient->sFractLife += usTotalHundredthsUsed;
fWillHealLife = FALSE;
usHundredthsHealed = usTotalHundredthsUsed;
}
// if we would heal more than we need
else if ( !fWillRepiarStats && (pPatient->stats.bLifeMax < pPatient->stats.bLife + bPointsHealed) )
{
usHundredthsHealed = max( 1, (usHundredthsHealed - usTotalHundredthsUsed));
usHundredthsHealed = max( 1, (usHealAmount - usTotalHundredthsUsed));
}
else
{
usHundredthsHealed = usHealAmount;
}
usHealAmount = max(0, usHealAmount - usHundredthsHealed);
}
// repair our stats here!!
@@ -3098,11 +3128,7 @@ UINT16 HealPatient( SOLDIERTYPE *pPatient, SOLDIERTYPE * pDoctor, UINT16 usHundr
usTotalHundredthsUsed -= ((usTotalHundredthsUsed * gSkillTraitValues.ubDOHealingPenaltyIfAlsoStatRepair ) / 100);
}
}
// we have to remember what will be left over to cure poison
//usPointsLeftToCurePoison = min(usHundredthsHealed, usPointsLeftToCurePoison - usTotalHundredthsUsed);
//usPointsLeftToCurePoison = max(usPointsLeftToCurePoison, 0); // do not go below zero
// if we are actually here to heal life
if ( fWillHealLife )
{
@@ -3170,7 +3196,7 @@ UINT16 HealPatient( SOLDIERTYPE *pPatient, SOLDIERTYPE * pDoctor, UINT16 usHundr
if ( pPatient->bPoisonSum > 0 || pPatient->sFractLife < 0 )
{
if ( fWillHealLife || fWillRepiarStats )
usPointsLeftToCurePoison = max(0, usPointsLeftToCurePoison - usHundredthsHealed);
usPointsLeftToCurePoison = max(0, usPointsLeftToCurePoison - usHealAmount);
if ( usPointsLeftToCurePoison > 0 )
{
@@ -3186,10 +3212,11 @@ UINT16 HealPatient( SOLDIERTYPE *pPatient, SOLDIERTYPE * pDoctor, UINT16 usHundr
{
UINT16 usTotalHundredthsUsedToCurePoison = 0;
// if having enough, no problem
if (usTotalMedPointsLeft >= (usPoisontoCure * bMedFactor))
// gGameExternalOptions.sPoisonMedicalPtsToCureMultiplicator alters the amount needed for curing poison
if (usTotalMedPointsLeft >= ( (UINT16)(gGameExternalOptions.sPoisonMedicalPtsToCureMultiplicator * usPoisontoCure * bMedFactor)))
{
usTotalHundredthsUsedToCurePoison = usPoisontoCure * 100;
usTotalMedPointsLeft = (usPoisontoCure * bMedFactor);
usTotalMedPointsLeft = ( (UINT16)(gGameExternalOptions.sPoisonMedicalPtsToCureMultiplicator * usPoisontoCure * bMedFactor));
}
else
{
@@ -3198,9 +3225,7 @@ UINT16 HealPatient( SOLDIERTYPE *pPatient, SOLDIERTYPE * pDoctor, UINT16 usHundr
}
pPatient->sFractLife += usTotalHundredthsUsedToCurePoison;
// modify usHundredthsHealed?
//usHundredthsHealed += usTotalHundredthsUsedToCurePoison;
usHundredthsHealed += (UINT16)(usTotalHundredthsUsedToCurePoison * gGameExternalOptions.sPoisonMedicalPtsToCureMultiplicator);
if (pPatient->sFractLife >= 100)
{
@@ -4884,6 +4909,11 @@ INT16 GetBonusTrainingPtsDueToInstructor( SOLDIERTYPE *pInstructor, SOLDIERTYPE
// adjust for instructor fatigue
UINT32 uiTrainingPts = (UINT32) sTrainingPts;
ReducePointsForFatigue( pInstructor, &uiTrainingPts );
// Flugente: our food situation influences our effectiveness
if ( gGameOptions.fFoodSystem )
ReducePointsForHunger( pInstructor, &uiTrainingPts );
sTrainingPts = (INT16)uiTrainingPts;
return( sTrainingPts );
@@ -4998,6 +5028,11 @@ INT16 GetSoldierTrainingPts( SOLDIERTYPE *pSoldier, INT8 bTrainStat, UINT16 *pus
// adjust for fatigue
UINT32 uiTrainingPts = (UINT32) sTrainingPts;
ReducePointsForFatigue( pSoldier, &uiTrainingPts );
// Flugente: our food situation influences our effectiveness
if ( gGameOptions.fFoodSystem )
ReducePointsForHunger( pSoldier, &uiTrainingPts );
sTrainingPts = (INT16)uiTrainingPts;
return( sTrainingPts );
@@ -5116,6 +5151,11 @@ INT16 GetSoldierStudentPts( SOLDIERTYPE *pSoldier, INT8 bTrainStat, UINT16 *pusM
// adjust for fatigue
UINT32 uiTrainingPts = (UINT32) sTrainingPts;
ReducePointsForFatigue( pSoldier, &uiTrainingPts );
// Flugente: our food situation influences our effectiveness
if ( gGameOptions.fFoodSystem )
ReducePointsForHunger( pSoldier, &uiTrainingPts );
sTrainingPts = (INT16)uiTrainingPts;
@@ -5386,6 +5426,11 @@ INT16 GetTownTrainPtsForCharacter( SOLDIERTYPE *pTrainer, UINT16 *pusMaxPts )
// adjust for fatigue of trainer
UINT32 uiTrainingPts = (UINT32) sTotalTrainingPts;
ReducePointsForFatigue( pTrainer, &uiTrainingPts );
// Flugente: our food situation influences our effectiveness
if ( gGameOptions.fFoodSystem )
ReducePointsForHunger( pTrainer, &uiTrainingPts );
sTotalTrainingPts = (INT16)uiTrainingPts;
@@ -13160,6 +13205,10 @@ UINT8 CalcSoldierNeedForSleep( SOLDIERTYPE *pSoldier )
ubNeedForSleep -= NUM_SKILL_TRAITS( pSoldier, MARTIALARTS_OT );
}
// Flugente: ubNeedForSleep can now be influenced by our food situation
if ( gGameOptions.fFoodSystem )
FoodNeedForSleepModifiy(pSoldier, &ubNeedForSleep);
return( ubNeedForSleep );
}
@@ -16088,6 +16137,9 @@ void FacilityAssignmentMenuBtnCallback ( MOUSE_REGION * pRegion, INT32 iReason )
case FAC_STAFF:
ChangeSoldiersAssignment( pSoldier, FACILITY_STAFF );
break;
case FAC_FOOD:
ChangeSoldiersAssignment( pSoldier, FACILITY_EAT );
break;
case FAC_REST:
ChangeSoldiersAssignment( pSoldier, FACILITY_REST );
break;
@@ -16227,6 +16279,8 @@ void FacilityAssignmentMenuBtnCallback ( MOUSE_REGION * pRegion, INT32 iReason )
}
// Flugente: I guess this piece of code is here to get a group Id for the soldier, which must not be there for movement specifically. Just my understanding, in case anybody else coming here wonders
// why we get movement related stuff when we were jsut ordered to stay in a facility
AssignMercToAMovementGroup( pSoldier );
MakeSoldiersTacticalAnimationReflectAssignment( pSoldier );
+2 -1
View File
@@ -62,12 +62,13 @@ enum
TRAIN_TEAMMATE,
TRAIN_BY_OTHER,
FACILITY_STAFF, // HEADROCK HAM 3.6: Operating a facility for strategic gain.
FACILITY_EAT, // added by Flugente
FACILITY_REST, // HEADROCK HAM 3.6: Facility equivalent of resting (no assignment)
ASSIGNMENT_DEAD,
ASSIGNMENT_UNCONCIOUS, // unused
ASSIGNMENT_POW,
ASSIGNMENT_HOSPITAL,
ASSIGNMENT_EMPTY,
ASSIGNMENT_EMPTY,
NUM_ASSIGNMENTS,
};
+3 -1
View File
@@ -148,6 +148,7 @@ enum
// Enumerate the different assignments that a facility can emulate.
FAC_AMBIENT = 0,
FAC_STAFF,
FAC_FOOD,
FAC_REST,
FAC_REPAIR_ITEMS,
FAC_REPAIR_VEHICLE,
@@ -180,7 +181,7 @@ enum
FAC_TRAINER_MEDICAL,
FAC_TRAINER_MECHANICAL,
FAC_TRAINER_LEADERSHIP,
FAC_TRAINER_EXPLOSIVES,
FAC_TRAINER_EXPLOSIVES,
NUM_FACILITY_ASSIGNMENTS,
};
@@ -247,6 +248,7 @@ typedef struct FACILITYASSIGNMENTTYPE
INT16 sSkyriderCostModifier; // Flat modifier for Skyrider's Cost Per Tile
UINT16 usMineIncomeModifier; // Percentage income adjustment
BOOLEAN fOnlyLocalMineAffected; // Determines whether income modifier applies to local mine only, or all mines.
INT16 sCantinaFoodModifier; // how many food points do we get when spending time in a cantina?
UINT8 ubMinimumStrength; // Minimum STR Requirement to begin this assignment
UINT8 ubMinimumHealth; // Minimum HLT Requirement to begin this assignment
+9
View File
@@ -141,6 +141,12 @@ INT16 GetFacilityModifier( UINT8 ubModifierType, UINT8 ubFacilityType, UINT8 ubA
sAssignmentModifier = 100 + ((sAssignmentModifier-100) + (sAmbientModifier-100));
return (sAssignmentModifier);
case FACILITY_CANTINA_MOD:
sAssignmentModifier = gFacilityTypes[ubFacilityType].AssignmentData[ubAssignmentType].sCantinaFoodModifier;
sAmbientModifier = gFacilityTypes[ubFacilityType].AssignmentData[0].sCantinaFoodModifier;
sAssignmentModifier = 100 + ((sAssignmentModifier-100) + (sAmbientModifier-100));
return (sAssignmentModifier);
default:
return (0);
}
@@ -894,6 +900,9 @@ INT8 GetSoldierFacilityAssignmentIndex( SOLDIERTYPE *pSoldier )
case FACILITY_STAFF:
bAssignmentIndex = FAC_STAFF;
break;
case FACILITY_EAT:
bAssignmentIndex = FAC_FOOD;
break;
case FACILITY_REST:
bAssignmentIndex = FAC_REST;
break;
+2
View File
@@ -46,6 +46,8 @@ enum
FACILITY_MINE_INCOME_MOD,
FACILITY_SKYRIDER_COST_MOD,
FACILITY_CANTINA_MOD
};
// HEADROCK HAM 3.6: Different enemy detection and counting levels
+5
View File
@@ -31,6 +31,7 @@
#include "Text.h"
// HEADROCK HAM 3.5: Add facility code for hourly update of detection levels
#include "Facilities.h"
#include "Food.h" // added by Flugente
void HourlyQuestUpdate( void );
void HourlyLarryUpdate( void );
@@ -65,6 +66,10 @@ CHAR16 zString[128];
// hourly update of town loyalty
HandleTownLoyalty();
// Flugente: food update
if ( gGameOptions.fFoodSystem )
HourlyFoodUpdate();
// hourly update of team assignments
UpdateAssignments();
@@ -41,6 +41,7 @@
#include "SaveLoadGame.h"//dnl ch51 081009
#include "Map Information.h"//dnl ch51 091009
#include "Interface Items.h"
#include "Food.h" // added by Flugente
//forward declarations of common classes to eliminate includes
class OBJECTTYPE;
@@ -290,6 +291,8 @@ INT32 MapScreenSectorInventoryCompare( const void *pNum1, const void *pNum2);
void SortSectorInventory( std::vector<WORLDITEM>& pInventory, UINT32 uiSizeOfArray );
BOOLEAN CanPlayerUseSectorInventory( SOLDIERTYPE *pSelectedSoldier );
void BuildStashForSelectedSectorAndDecayFood( INT16 sMapX, INT16 sMapY, INT16 sMapZ ); // Flugente: for food decay
extern void MAPEndItemPointer( );
extern BOOLEAN GetCurrentBattleSectorXYZAndReturnTRUEIfThereIsABattle( INT16 *psSectorX, INT16 *psSectorY, INT16 *psSectorZ );
extern BOOLEAN MAPInternalInitItemDescriptionBox( OBJECTTYPE *pObject, UINT8 ubStatusIndex, SOLDIERTYPE *pSoldier );
@@ -5019,4 +5022,53 @@ void HandleSetFilterButtons()
{
ButtonList[guiMapInvenFilterButton[ 8 ]]->uiFlags &=~ (BUTTON_CLICKED_ON);
}
}
void BuildStashForSelectedSectorAndDecayFood( INT16 sMapX, INT16 sMapY, INT16 sMapZ )
{
UINT32 uiTotalNumberOfRealItems = 0;
WORLDITEM * pTotalSectorList = NULL;
// #ifdef _DEBUG
BOOLEAN fReturn = TRUE;
// #endif
// now load these items into memory, based on fact if sector is in fact loaded
if( ( sMapX == gWorldSectorX )&&( gWorldSectorY == sMapY ) &&(gbWorldSectorZ == sMapZ ) )
{
fReturn = GetNumberOfWorldItemsFromTempItemFile( sMapX, sMapY, ( INT8 )( sMapZ ), &( uiTotalNumberOfRealItems ), FALSE );
Assert( fReturn );
if ( !uiTotalNumberOfRealItems )
return;
pTotalSectorList = gWorldItems;
}
else
{
// not loaded, load
// get total number, visable and invisible
fReturn = GetNumberOfWorldItemsFromTempItemFile( sMapX, sMapY, ( INT8 )( sMapZ ), &( uiTotalNumberOfRealItems ), FALSE );
Assert( fReturn );
if( uiTotalNumberOfRealItems > 0 )
{
// allocate space for the list
pTotalSectorList = new WORLDITEM[ uiTotalNumberOfRealItems ];
if ( !uiTotalNumberOfRealItems )
return;
// now load into mem
LoadWorldItemsFromTempItemFile( sMapX, sMapY, ( INT8 ) ( sMapZ ), pTotalSectorList );
}
}
//Check to see if any of the items in the list have a gridno of NOWHERE and the entry point flag NOT set
//CheckGridNoOfItemsInMapScreenMapInventory();
SectorFoodDecay( pTotalSectorList, uiTotalNumberOfRealItems );
//Save the Items to the the file
SaveWorldItemsToTempItemFile( sMapX, sMapY, (INT8)sMapZ, uiTotalNumberOfRealItems, pTotalSectorList );
}
+38 -11
View File
@@ -53,6 +53,7 @@
#include "Air Raid.h"
#include "Queen Command.h"
#include "Render Fun.h"
#include "Food.h"
#endif
#include "connect.h"
@@ -1973,21 +1974,47 @@ void UpdateCharRegionHelpText( void )
// person (health/energy/morale)
GetMoraleString( pSoldier, pMoraleStr );
if ( pSoldier->bPoisonSum )
if ( gGameOptions.fFoodSystem )
{
INT8 bPoisonBandaged = pSoldier->bPoisonSum - pSoldier->bPoisonBleeding - pSoldier->bPoisonLife;
swprintf( sString, L"%s: %d/%d, %s: %d/%d/%d - %d, %s: %d/%d, %s: %s",
pMapScreenStatusStrings[ 0 ], pSoldier->stats.bLife, pSoldier->stats.bLifeMax,
pMapScreenStatusStrings[ 5 ], pSoldier->bPoisonBleeding, bPoisonBandaged, pSoldier->bPoisonLife, pSoldier->bPoisonSum,
pMapScreenStatusStrings[ 1 ], pSoldier->bBreath, pSoldier->bBreathMax,
pMapScreenStatusStrings[ 2 ], pMoraleStr );
if ( pSoldier->bPoisonSum )
{
INT8 bPoisonBandaged = pSoldier->bPoisonSum - pSoldier->bPoisonBleeding - pSoldier->bPoisonLife;
swprintf( sString, L"%s: %d/%d, %s: %d/%d/%d - %d, %s: %d/%d, %s: %s, %s: %d%s, %s: %d%s",
pMapScreenStatusStrings[ 0 ], pSoldier->stats.bLife, pSoldier->stats.bLifeMax,
pMapScreenStatusStrings[ 5 ], pSoldier->bPoisonBleeding, bPoisonBandaged, pSoldier->bPoisonLife, pSoldier->bPoisonSum,
pMapScreenStatusStrings[ 1 ], pSoldier->bBreath, pSoldier->bBreathMax,
pMapScreenStatusStrings[ 2 ], pMoraleStr,
pMapScreenStatusStrings[ 6 ], (INT32)(100*pSoldier->bDrinkLevel/FOOD_MAX), L"%",
pMapScreenStatusStrings[ 7 ], (INT32)(100*pSoldier->bFoodLevel/FOOD_MAX), L"%" );
}
else
{
swprintf( sString, L"%s: %d/%d, %s: %d/%d, %s: %s, %s: %d%s, %s: %d%s",
pMapScreenStatusStrings[ 0 ], pSoldier->stats.bLife, pSoldier->stats.bLifeMax,
pMapScreenStatusStrings[ 1 ], pSoldier->bBreath, pSoldier->bBreathMax,
pMapScreenStatusStrings[ 2 ], pMoraleStr,
pMapScreenStatusStrings[ 6 ], (INT32)(100*pSoldier->bDrinkLevel/FOOD_MAX), L"%",
pMapScreenStatusStrings[ 7 ], (INT32)(100*pSoldier->bFoodLevel/FOOD_MAX), L"%" );
}
}
else
{
swprintf( sString, L"%s: %d/%d, %s: %d/%d, %s: %s",
pMapScreenStatusStrings[ 0 ], pSoldier->stats.bLife, pSoldier->stats.bLifeMax,
pMapScreenStatusStrings[ 1 ], pSoldier->bBreath, pSoldier->bBreathMax,
pMapScreenStatusStrings[ 2 ], pMoraleStr );
if ( pSoldier->bPoisonSum )
{
INT8 bPoisonBandaged = pSoldier->bPoisonSum - pSoldier->bPoisonBleeding - pSoldier->bPoisonLife;
swprintf( sString, L"%s: %d/%d, %s: %d/%d/%d - %d, %s: %d/%d, %s: %s",
pMapScreenStatusStrings[ 0 ], pSoldier->stats.bLife, pSoldier->stats.bLifeMax,
pMapScreenStatusStrings[ 5 ], pSoldier->bPoisonBleeding, bPoisonBandaged, pSoldier->bPoisonLife, pSoldier->bPoisonSum,
pMapScreenStatusStrings[ 1 ], pSoldier->bBreath, pSoldier->bBreathMax,
pMapScreenStatusStrings[ 2 ], pMoraleStr );
}
else
{
swprintf( sString, L"%s: %d/%d, %s: %d/%d, %s: %s",
pMapScreenStatusStrings[ 0 ], pSoldier->stats.bLife, pSoldier->stats.bLifeMax,
pMapScreenStatusStrings[ 1 ], pSoldier->bBreath, pSoldier->bBreathMax,
pMapScreenStatusStrings[ 2 ], pMoraleStr );
}
}
}
}
+20 -2
View File
@@ -98,6 +98,8 @@ void InitAssignmentDataArray( facilitytypeParseData *pData )
pData->curAssignmentData.usMineIncomeModifier = 100;
pData->curAssignmentData.fOnlyLocalMineAffected = 0;
pData->curAssignmentData.sCantinaFoodModifier = 100;
pData->curAssignmentData.ubMaximumBreath = 100;
pData->curAssignmentData.ubMaximumMorale = 100;
@@ -217,7 +219,8 @@ facilitytypeStartElementHandle(void *userData, const XML_Char *name, const XML_C
strcmp(name, "fCountEnemiesInCities") == 0 ||
strcmp(name, "sSkyriderCostModifier") == 0 ||
strcmp(name, "usMineIncomeModifier") == 0 ||
strcmp(name, "fOnlyLocalMineAffected") == 0 ))
strcmp(name, "fOnlyLocalMineAffected") == 0 ||
strcmp(name, "sCantinaFoodModifier") == 0 ))
{
pData->curElement = FACILITYTYPE_ASSIGNMENT_ELEMENT;
@@ -449,6 +452,8 @@ facilitytypeEndElementHandle(void *userData, const XML_Char *name)
gFacilityTypes[pData->curIndex].AssignmentData[cnt].usMineIncomeModifier = pData->curFacilityTypeData.AssignmentData[cnt].usMineIncomeModifier;
gFacilityTypes[pData->curIndex].AssignmentData[cnt].fOnlyLocalMineAffected = pData->curFacilityTypeData.AssignmentData[cnt].fOnlyLocalMineAffected;
gFacilityTypes[pData->curIndex].AssignmentData[cnt].sCantinaFoodModifier = pData->curFacilityTypeData.AssignmentData[cnt].sCantinaFoodModifier;
// Conditions
gFacilityTypes[pData->curIndex].AssignmentData[cnt].ubMinimumStrength = pData->curFacilityTypeData.AssignmentData[cnt].ubMinimumStrength;
gFacilityTypes[pData->curIndex].AssignmentData[cnt].ubMinimumAgility = pData->curFacilityTypeData.AssignmentData[cnt].ubMinimumAgility;
@@ -587,6 +592,8 @@ facilitytypeEndElementHandle(void *userData, const XML_Char *name)
pData->curFacilityTypeData.AssignmentData[pData->curAssignmentType].usMineIncomeModifier = pData->curAssignmentData.usMineIncomeModifier;
pData->curFacilityTypeData.AssignmentData[pData->curAssignmentType].fOnlyLocalMineAffected = pData->curAssignmentData.fOnlyLocalMineAffected;
pData->curFacilityTypeData.AssignmentData[pData->curAssignmentType].sCantinaFoodModifier = pData->curAssignmentData.sCantinaFoodModifier;
pData->curFacilityTypeData.AssignmentData[pData->curAssignmentType].ubMaximumBreath = pData->curAssignmentData.ubMaximumBreath;
pData->curFacilityTypeData.AssignmentData[pData->curAssignmentType].ubMaximumMorale = pData->curAssignmentData.ubMaximumMorale;
@@ -648,6 +655,11 @@ facilitytypeEndElementHandle(void *userData, const XML_Char *name)
//pData->curAssignmentType = (INT16) atol(pData->szCharData);
pData->curAssignmentType = FAC_STAFF;
}
else if (strcmp(pData->szCharData, "FACILITY_EAT") == 0)
{
//pData->curAssignmentType = (INT16) atol(pData->szCharData);
pData->curAssignmentType = FAC_FOOD;
}
else if (strcmp(pData->szCharData, "REST") == 0)
{
//pData->curAssignmentType = (INT16) atol(pData->szCharData);
@@ -811,7 +823,7 @@ facilitytypeEndElementHandle(void *userData, const XML_Char *name)
{
//pData->curAssignmentType = (INT16) atol(pData->szCharData);
pData->curAssignmentType = FAC_STUDENT_EXPLOSIVES;
}
}
else
{
CHAR16 sErrorString[256];
@@ -930,6 +942,12 @@ facilitytypeEndElementHandle(void *userData, const XML_Char *name)
pData->curAssignmentData.fOnlyLocalMineAffected = (BOOLEAN) atol(pData->szCharData);
}
else if(strcmp(name, "sCantinaFoodModifier") == 0 )
{
pData->curElement = FACILITYTYPE_ASSIGNMENT;
pData->curAssignmentData.sCantinaFoodModifier = (UINT16) atol(pData->szCharData);
}
//////////////////////////////////////////////
// Conditions for assignment
+26 -1
View File
@@ -19,6 +19,9 @@
// Four different sector names, used at different times.
extern CHAR16 gzSectorNames[256][4][MAX_SECTOR_NAME_LENGTH];
// Flugente: To determine wether a sector has water in it.
extern UINT8 gSectorWaterType[256][4];
// moved to lua
//extern CHAR16 gzSectorUndergroundNames1[256][4][MAX_SECTOR_NAME_LENGTH];
//extern CHAR16 gzSectorUndergroundNames2[256][4][MAX_SECTOR_NAME_LENGTH];
@@ -42,6 +45,7 @@ typedef struct
CHAR16 szCurDetailedUnexploredName[MAX_SECTOR_NAME_LENGTH];
CHAR16 szCurExploredName[MAX_SECTOR_NAME_LENGTH];
CHAR16 szCurDetailedExploredName[MAX_SECTOR_NAME_LENGTH];
UINT8 sWaterType;
UINT32 currentDepth;
UINT32 maxReadDepth;
} SectorNameParseData;
@@ -66,6 +70,10 @@ SectorNameStartElementHandle(void *userData, const XML_Char *name, const char **
// Initiate Array by setting first character to 0.
for (UINT16 x = 0; x < 256; x++)
{
gSectorWaterType[x][0] = 0;
gSectorWaterType[x][1] = 0;
gSectorWaterType[x][2] = 0;
gSectorWaterType[x][3] = 0;
if (Sector_Level == 0 )
{
@@ -112,7 +120,8 @@ SectorNameStartElementHandle(void *userData, const XML_Char *name, const char **
strcmp(name, "szUnexploredName") == 0 ||
strcmp(name, "szDetailedUnexploredName") == 0 ||
strcmp(name, "szExploredName") == 0 ||
strcmp(name, "szDetailedExploredName") == 0 ))
strcmp(name, "szDetailedExploredName") == 0 ||
strcmp(name, "sWaterType") == 0 ))
{
pData->curElement = SECTORNAME_ELEMENT;
@@ -164,6 +173,11 @@ SectorNameEndElementHandle(void *userData, const XML_Char *name)
wcscpy(gzSectorNames[ubSectorId][1], pData->szCurDetailedUnexploredName);
wcscpy(gzSectorNames[ubSectorId][2], pData->szCurExploredName);
wcscpy(gzSectorNames[ubSectorId][3], pData->szCurDetailedExploredName);
gSectorWaterType[ubSectorId][0] = pData->sWaterType;
gSectorWaterType[ubSectorId][1] = pData->sWaterType;
gSectorWaterType[ubSectorId][2] = pData->sWaterType;
gSectorWaterType[ubSectorId][3] = pData->sWaterType;
}
// moved to lua
//else if (Sector_Level == 1 )
@@ -196,6 +210,11 @@ SectorNameEndElementHandle(void *userData, const XML_Char *name)
wcscpy(gzSectorNames[ubSectorId][1], pData->szCurDetailedUnexploredName);
wcscpy(gzSectorNames[ubSectorId][2], pData->szCurExploredName);
wcscpy(gzSectorNames[ubSectorId][3], pData->szCurDetailedExploredName);
gSectorWaterType[ubSectorId][0] = pData->sWaterType;
gSectorWaterType[ubSectorId][1] = pData->sWaterType;
gSectorWaterType[ubSectorId][2] = pData->sWaterType;
gSectorWaterType[ubSectorId][3] = pData->sWaterType;
}
// moved to lua
//else if (Sector_Level == 1 )
@@ -268,6 +287,12 @@ SectorNameEndElementHandle(void *userData, const XML_Char *name)
pData->szCurDetailedExploredName[sizeof(pData->szCurDetailedExploredName)/sizeof(pData->szCurDetailedExploredName[0]) - 1] = '\0';
}
else if(strcmp(name, "sWaterType") == 0)
{
pData->curElement = SECTORNAME_ELEMENT_SECTOR;
pData->sWaterType = (UINT8) atol(pData->szCharData);
}
pData->maxReadDepth--;
}
+1 -1
View File
@@ -2361,7 +2361,7 @@ void DrawCharStats( INT16 sCharNum )
swprintf( sString, L"%d", pSoldier->stats.bStrength);
// SANDRO - if damaged stat we could regain, show in red until repaired
if( gGameOptions.fNewTraitSystem && ( pSoldier->ubCriticalStatDamage[DAMAGED_STAT_STRENGTH] > 0 ))
if ( ( gGameOptions.fNewTraitSystem && ( pSoldier->ubCriticalStatDamage[DAMAGED_STAT_STRENGTH] > 0 )) || (gGameOptions.fFoodSystem && pSoldier->usStarveDamageStrength > 0) )
{
SetFontForeground( FONT_RED );
}
+13 -1
View File
@@ -673,8 +673,20 @@ void ChangeStat( MERCPROFILESTRUCT *pProfile, SOLDIERTYPE *pSoldier, UINT8 ubSta
// SANDRO - reduce damaged stat if this stat was increased normally
if ( fChangeTypeIncrease && (bDamagedStatToRaise != -1) )
{
INT16 ptstolower = sPtsChanged;
UINT8 oldctrpts = pSoldier->ubCriticalStatDamage[ bDamagedStatToRaise ];
if (pSoldier->ubCriticalStatDamage[ bDamagedStatToRaise ] > 0)
pSoldier->ubCriticalStatDamage[ bDamagedStatToRaise ] = max( 0, (pSoldier->ubCriticalStatDamage[ bDamagedStatToRaise ] - sPtsChanged));
{
pSoldier->ubCriticalStatDamage[ bDamagedStatToRaise ] = max( 0, (pSoldier->ubCriticalStatDamage[ bDamagedStatToRaise ] - ptstolower));
ptstolower -= oldctrpts - pSoldier->ubCriticalStatDamage[ bDamagedStatToRaise ];
}
if ( bDamagedStatToRaise == DAMAGED_STAT_STRENGTH && pSoldier->usStarveDamageStrength > 0 )
pSoldier->usStarveDamageStrength = max(0, pSoldier->usStarveDamageStrength - ptstolower);
else if ( bDamagedStatToRaise == DAMAGED_STAT_HEALTH && pSoldier->usStarveDamageHealth > 0 )
pSoldier->usStarveDamageHealth = max(0, pSoldier->usStarveDamageHealth - ptstolower);
}
// if it's a level gain, or sometimes for other stats
+26 -11
View File
@@ -66,6 +66,14 @@ BOOLEAN ApplyDrugs( SOLDIERTYPE *pSoldier, OBJECTTYPE *pObject )
gMercProfiles[ LARRY_DRUNK ].bNPCData = 0;
}
BOOLEAN consumeitem = TRUE;
// if item is also a food iem, don't use it up here, it will be consumed in ApplyFood, which will be called afterwards
UINT32 foodtype = Item[pObject->usItem].foodtype;
// if not a food item, nothing to see here
if ( foodtype > 0 )
consumeitem = FALSE;
// set flag: we are on drugs
pSoldier->bSoldierFlagMask |= SOLDIER_DRUGGED;
@@ -209,23 +217,30 @@ BOOLEAN ApplyDrugs( SOLDIERTYPE *pSoldier, OBJECTTYPE *pObject )
pSoldier->bRegenBoostersUsedToday++;
}
// ATE: use kit points...
if ( usItem == ALCOHOL )
UseKitPoints( pObject, 10, pSoldier );
else if ( usItem == WINE )
UseKitPoints( pObject, 20, pSoldier );
else if ( usItem == BEER )
UseKitPoints( pObject, 100, pSoldier );
else
// increase drug counter if not alcoholic drug
if ( usItem != ALCOHOL && usItem != WINE && usItem != BEER )
{
// remove object
pObject->RemoveObjectsFromStack(1);
if ( gMercProfiles[ pSoldier->ubProfile ].ubNumTimesDrugUseInLifetime != 255 )
{
gMercProfiles[ pSoldier->ubProfile ].ubNumTimesDrugUseInLifetime++;
}
}
// ATE: use kit points...
if ( consumeitem )
{
if ( usItem == ALCOHOL )
UseKitPoints( pObject, 10, pSoldier );
else if ( usItem == WINE )
UseKitPoints( pObject, 20, pSoldier );
else if ( usItem == BEER )
UseKitPoints( pObject, 100, pSoldier );
else
{
// remove object
pObject->RemoveObjectsFromStack(1);
}
}
if ( (ubDrugType & DRUG_ALCOHOL) != 0 )
{
+16
View File
@@ -40,6 +40,7 @@
// HEADROCK HAM 3.2: Added two includes so that a function can read values of the Gun Range/hospital location
#include "Campaign Types.h"
#include "Strategic Event Handler.h"
#include "Food.h" // added by Flugente
#endif
// Defines
@@ -2286,6 +2287,21 @@ void HandleRenderFaceAdjustments( FACETYPE *pFace, BOOLEAN fDisplayBuffer, BOOLE
bNumRightIcons++;
}
// Flugente: food system - symbols used if hungry or thirsty
if ( gGameOptions.fFoodSystem )
{
if ( MercPtrs[ pFace->ubSoldierID ]->bDrinkLevel < FoodMoraleMods[FOOD_MERC_START_CONSUME].bThreshold )
{
DoRightIcon( uiRenderBuffer, pFace, sFaceX, sFaceY, bNumRightIcons, 19 );
bNumRightIcons++;
}
if ( MercPtrs[ pFace->ubSoldierID ]->bFoodLevel < FoodMoraleMods[FOOD_MERC_START_CONSUME].bThreshold )
{
DoRightIcon( uiRenderBuffer, pFace, sFaceX, sFaceY, bNumRightIcons, 20 );
bNumRightIcons++;
}
}
switch( pSoldier->bAssignment )
{
+964
View File
@@ -0,0 +1,964 @@
#ifdef PRECOMPILEDHEADERS
#include "Tactical All.h"
#else
#include "sgp.h"
#include "soldier profile.h"
#include "Food.h"
#include "items.h"
#include "morale.h"
#include "points.h"
#include "message.h"
#include "GameSettings.h" // SANDRO - had to add this, dammit!
#include "Random.h"
#include "Text.h"
#include "Interface.h"
#include "Dialogue Control.h"
#include "Sound Control.h"
#include "Assignments.h"
#include "Overhead.h"
#include "worldman.h"
#include "Isometric Utils.h"
#include "Campaign Types.h"
#include "Drugs And Alcohol.h"
#include "environment.h"
//#include "Game Clock.h"
#include "WorldDat.h"
#include "Facilities.h"
#endif
//forward declarations of common classes to eliminate includes
class OBJECTTYPE;
class SOLDIERTYPE;
extern MoraleEvent gbMoraleEvent[NUM_MORALE_EVENTS];
UINT8 gSectorWaterType[256][4];
//extern BOOLEAN HandleSoldierDeath( SOLDIERTYPE *pSoldier , BOOLEAN *pfMadeCorpse );
//extern BOOLEAN TacticalRemoveSoldier( UINT16 usSoldierIndex );
extern BOOLEAN GetSectorFlagStatus( INT16 sMapX, INT16 sMapY, UINT8 bMapZ, UINT32 uiFlagToSet );
extern void BuildStashForSelectedSectorAndDecayFood( INT16 sMapX, INT16 sMapY, INT16 sMapZ );
FoodMoraleMod FoodMoraleMods[NUM_FOOD_MORALE_TYPES] =
{
{ 100000, -10, -3, - -75, -75, 2}, // FOOD_STUFFED
{ 5000, -5, -2, -5, -5, 0}, // FOOD_EXTREMELY_FULL
{ 2500, 2, -1, -1, 0, 0}, // FOOD_FULL
{ 1000, 5, 0, 0, 0, 0}, // FOOD_SLIGHTLY_FULL
{ 0, 0, 0, 0, 0, 0}, // FOOD_NORMAL
{ -1000, 0, 0, 0, 0, 0}, // FOOD_LOW
{ -2500, -2, 0, 0, 0, 0}, // FOOD_EVEN_LOWER
{ -5000, -10, -1, -10, -10, 5}, // FOOD_VERY_LOW
{ -7500, -20, -2, -25, -25, 25}, // FOOD_DANGER
{ -8750, -30, -2, -50, -50, 75}, // FOOD_DESPERATE
{ -10000, -50, -3, -80, -75, 100}, // FOOD_STARVING
};
BOOLEAN ApplyFood( SOLDIERTYPE *pSoldier, OBJECTTYPE *pObject )
{
// how did this even happen?
if ( !pSoldier || !pObject || !(pObject->exists() ) || (*pObject)[0]->data.objectStatus < 1 )
return( FALSE);
UINT32 foodtype = Item[pObject->usItem].foodtype;
// if not a food item, nothing to see here
if ( foodtype == 0 || foodtype > FOOD_TYPE_MAX )
return( FALSE);
// workaround: canteens with 1% status are treated as 'empty'. They cannot be consumed, but refilled
if ( Item[pObject->usItem].canteen == TRUE && (*pObject)[0]->data.objectStatus == 1 )
return( FALSE);
// do we eat or drink this stuff?
UINT8 type = AP_EAT;
if ( Food[foodtype].bDrinkPoints > Food[foodtype].bFoodPoints )
type = AP_DRINK;
// return if we don't have enough APs
if (!EnoughPoints( pSoldier, APBPConstants[type], 0, TRUE ) )
{
return( FALSE );
}
// check if we are willing to eat this: if we're filled, the merc refuses
if ( ( ( Food[foodtype].bFoodPoints > 0 && pSoldier->bFoodLevel > FoodMoraleMods[FOOD_EXTREMELY_FULL].bThreshold ) || Food[foodtype].bFoodPoints <= 0 ) && ( ( Food[foodtype].bDrinkPoints > 0 && pSoldier->bDrinkLevel > FoodMoraleMods[FOOD_EXTREMELY_FULL].bThreshold ) || Food[foodtype].bDrinkPoints <= 0 ) )
{
// Say quote!
TacticalCharacterDialogue( pSoldier, 61 );
return( FALSE);
}
// we have to determine wether the food is rotten, that might influence its condition and poison us
FLOAT foodcondition = (*pObject)[0]->data.bTemperature / OVERHEATING_MAX_TEMPERATURE;
FLOAT conditionmodifier = 0.5f * (1.0f + sqrt(foodcondition));
FLOAT percentualsize = min(Food[foodtype].ubPortionSize, (*pObject)[0]->data.objectStatus) / 100.0f;
INT32 foodpts = (INT32) (Food[foodtype].bFoodPoints * percentualsize * conditionmodifier );
INT32 drinkpts = (INT32) (Food[foodtype].bDrinkPoints * percentualsize * conditionmodifier );
// food in bad condition is harmful!
if ( foodcondition < FOOD_BAD_THRESHOLD )
{
// determine the max nutritional value
INT32 maxpts = max(Food[foodtype].bFoodPoints, Food[foodtype].bDrinkPoints);
// divide by 100 (poison sum is in [0, 99]
// multiply with FOOD_BAD_THRESHOLD for more reasonable values
INT8 poisonadd = (INT8)(0.01 * maxpts * (1.0 - foodcondition) * FOOD_BAD_THRESHOLD );
pSoldier->AddPoison(poisonadd);
}
// eat it!
pSoldier->bFoodLevel = min(pSoldier->bFoodLevel + foodpts, FOOD_MAX);
pSoldier->bFoodLevel = max(pSoldier->bFoodLevel, FOOD_MIN);
pSoldier->bDrinkLevel = min(pSoldier->bDrinkLevel + drinkpts, DRINK_MAX);
pSoldier->bDrinkLevel = max(pSoldier->bDrinkLevel, DRINK_MIN);
/////////////////// MORALE //////////////////////
INT8 moralemod = Food[foodtype].bMoraleMod;
if ( moralemod > 0 )
// morale is lower if food is rotten, can even become negative
moralemod = (INT8) ( moralemod * (FOOD_BAD_THRESHOLD_INVERSE*foodcondition - 1.0f) );
else
// if we hate the food anyway, give even lower morale if its rotten
moralemod = (INT8) ( moralemod * (2.0f - foodcondition) );
if ( moralemod > 0 )
{
while ( moralemod > 0 && moralemod >= gbMoraleEvent[MORALE_GOOD_FOOD].bChange )
{
HandleMoraleEvent( pSoldier, MORALE_GOOD_FOOD, pSoldier->sSectorX, pSoldier->sSectorY, pSoldier->bSectorZ );
moralemod -= gbMoraleEvent[MORALE_GOOD_FOOD].bChange;
}
while ( moralemod > 0 && moralemod >= gbMoraleEvent[MORALE_FOOD].bChange )
{
HandleMoraleEvent( pSoldier, MORALE_FOOD, pSoldier->sSectorX, pSoldier->sSectorY, pSoldier->bSectorZ );
moralemod -= gbMoraleEvent[MORALE_FOOD].bChange;
}
}
else if ( moralemod < 0 )
{
while ( moralemod < 0 && moralemod <= gbMoraleEvent[MORALE_LOATHSOME_FOOD].bChange )
{
HandleMoraleEvent( pSoldier, MORALE_LOATHSOME_FOOD, pSoldier->sSectorX, pSoldier->sSectorY, pSoldier->bSectorZ );
moralemod -= gbMoraleEvent[MORALE_LOATHSOME_FOOD].bChange;
}
while ( moralemod < 0 && moralemod <= gbMoraleEvent[MORALE_BAD_FOOD].bChange )
{
HandleMoraleEvent( pSoldier, MORALE_BAD_FOOD, pSoldier->sSectorX, pSoldier->sSectorY, pSoldier->bSectorZ );
moralemod -= gbMoraleEvent[MORALE_BAD_FOOD].bChange;
}
}
/////////////////// MORALE //////////////////////
// notification
if ( type == AP_EAT )
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"%s ate %s", pSoldier->name, Item[pObject->usItem].szItemName );
else
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"%s drank %s", pSoldier->name, Item[pObject->usItem].szItemName );
// now remove a portion of the food item (or the whole item altogether)
UINT16 ptsconsumed = UseKitPoints( pObject, Food[foodtype].ubPortionSize, pSoldier );
INT32 sBPAdjustment = 0;
// if the food is more of a drink, we also restore breath points
if ( Food[foodtype].bDrinkPoints > Food[foodtype].bFoodPoints )
{
//UINT16 ptsconsumed = Food[foodtype].ubPortionSize - ptsleft;
INT16 usTotalKitPoints = TotalPoints( pObject );
INT16 sPointsToUse = __min( ptsconsumed, usTotalKitPoints );
sBPAdjustment = 2 * sPointsToUse * -(100 - pSoldier->bBreath);
}
DeductPoints( pSoldier, APBPConstants[type], sBPAdjustment );
// let it be known that we are eating
if ( pSoldier->bTeam == gbPlayerNum )
{
if ( type == AP_EAT )
{
// Play sound
PlayJA2SampleFromFile( "Sounds\\eat1.wav", RATE_11025, HIGHVOLUME, 1, MIDDLEPAN );
}
else
{
if ( gMercProfiles[ pSoldier->ubProfile ].bSex == MALE )
{
PlayJA2Sample( DRINK_CANTEEN_MALE, RATE_11025, MIDVOLUME, 1, MIDDLEPAN );
}
else
{
PlayJA2Sample( DRINK_CANTEEN_FEMALE, RATE_11025, MIDVOLUME, 1, MIDDLEPAN );
}
}
}
return( TRUE );
}
UINT8 GetFoodSituation( SOLDIERTYPE *pSoldier )
{
UINT8 foodsituation = FOOD_NORMAL;
if ( !pSoldier )
return( foodsituation );
// The lowest value determines how bad we feel
INT32 missamount = min( pSoldier->bFoodLevel, pSoldier->bDrinkLevel);
// old code
/*INT32 missamount = 0;
if ( pSoldier->bFoodLevel < 0 )
missamount += pSoldier->bFoodLevel;
if ( pSoldier->bDrinkLevel < 0 )
missamount += (INT32)(FOOD_MORALE_DRINK_TO_FOOD_RATIO * pSoldier->bDrinkLevel);*/
for ( UINT8 i = FOOD_STUFFED; i < NUM_FOOD_MORALE_TYPES; ++i )
{
if ( missamount < FoodMoraleMods[i].bThreshold )
foodsituation = i;
else
break;
}
return( foodsituation );
}
void FoodMaxMoraleModifiy( SOLDIERTYPE *pSoldier, UINT8* pubMaxMorale )
{
if ( !pSoldier )
return;
UINT8 foodsituation = GetFoodSituation( pSoldier );
INT8 mod = FoodMoraleMods[foodsituation].bMoraleModifier;
if ( (*pubMaxMorale) + mod > 0 )
(*pubMaxMorale) += mod;
else
(*pubMaxMorale) = 0;
}
void FoodNeedForSleepModifiy( SOLDIERTYPE *pSoldier, UINT8* pubNeedForSleep )
{
if ( !pSoldier )
return;
UINT8 foodsituation = GetFoodSituation( pSoldier );
(*pubNeedForSleep) += max(1, (INT16)((*pubNeedForSleep) - FoodMoraleMods[foodsituation].bSleepModifier));
}
void ReducePointsForHunger( SOLDIERTYPE *pSoldier, UINT32 *pusPoints )
{
UINT8 foodsituation = GetFoodSituation( pSoldier );
INT8 mod = FoodMoraleMods[foodsituation].bAssignmentEfficiencyModifier;
*pusPoints = (UINT32)((*pusPoints) * (100 - mod)/100);
}
void ReduceBPRegenForHunger( SOLDIERTYPE *pSoldier, INT32 *psPoints )
{
UINT8 foodsituation = GetFoodSituation( pSoldier );
INT8 mod = FoodMoraleMods[foodsituation].bBreathRegenModifier;
*psPoints = (INT32)((*psPoints) * (100 - mod)/100);
}
void HourlyFoodSituationUpdate( SOLDIERTYPE *pSoldier )
{
if ( !pSoldier )
return;
// determine our current activity level
FLOAT activitymodifier = gGameExternalOptions.sFoodDigestionOnDuty;
if ( pSoldier->flags.fMercAsleep == TRUE )
activitymodifier = gGameExternalOptions.sFoodDigestionSleep;
else if ( !pSoldier->bInSector )
{
if( pSoldier->bAssignment == VEHICLE )
activitymodifier = gGameExternalOptions.sFoodDigestionTravelVehicle;
else
activitymodifier = gGameExternalOptions.sFoodDigestionTravel;
}
else if ( pSoldier->bAssignment > DOCTOR )
activitymodifier = gGameExternalOptions.sFoodDigestionAssignment;
else if ( (gTacticalStatus.uiFlags & INCOMBAT) )
activitymodifier = gGameExternalOptions.sFoodDigestionCombat;
// for some odd reason, the time isn't even needed here, so we just use 0 :-)
INT8 sectortemperaturemod = SectorTemperature( 0, pSoldier->sSectorX, pSoldier->sSectorY, pSoldier->bSectorZ );
// if we are heat intolerant, increase modifier
if ( sectortemperaturemod > 0 && (gMercProfiles[ pSoldier->ubProfile ].bDisability == HEAT_INTOLERANT || MercUnderTheInfluence(pSoldier, DRUG_TYPE_HEATINTOLERANT) ) )
++sectortemperaturemod;
FLOAT temperaturemodifier = (FLOAT)(3 + sectortemperaturemod)/3;
// due to digestion, reduce our food and drink levels
pSoldier->bFoodLevel = max(pSoldier->bFoodLevel - (INT32) (activitymodifier * gGameExternalOptions.usFoodDigestionHourlyBaseFood), FOOD_MIN);
pSoldier->bDrinkLevel = max(pSoldier->bDrinkLevel - (INT32) (activitymodifier * temperaturemodifier * gGameExternalOptions.usFoodDigestionHourlyBaseDrink), DRINK_MIN);
// there is a chance that we take damage to our health and strength stats if we are starving (or insanely obese :-) )
UINT8 foodsituation = GetFoodSituation( pSoldier );
UINT8 statdamagechance = FoodMoraleMods[foodsituation].ubStatDamageChance;
if ( statdamagechance > 0 )
{
// these reductions can be healed, but only if we are in a sufficient food situation again
// damage strength
if ( Random(100) < statdamagechance )
{
UINT8 numberofreduces = 1;
// if starving, we lose stats a LOT faster
if ( foodsituation == FOOD_STARVING )
numberofreduces += Random(2);
INT8 oldval = pSoldier->stats.bStrength;
pSoldier->stats.bStrength = max(1, pSoldier->stats.bStrength - numberofreduces);
pSoldier->usStarveDamageStrength += oldval - pSoldier->stats.bStrength;
// Update Profile
gMercProfiles[ pSoldier->ubProfile ].bStrength = pSoldier->stats.bStrength;
gMercProfiles[ pSoldier->ubProfile ].records.usTimesStatDamaged++;
// make stat RED for a while...
pSoldier->timeChanges.uiChangeStrengthTime = GetJA2Clock();
pSoldier->usValueGoneUp &= ~( STRENGTH_INCREASE );
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"%s's strength was damaged due to lack of nutrition!", pSoldier->name );
}
// damage health
if ( Random(100) < statdamagechance )
{
UINT8 numberofreduces = 1;
// if starving, we lose stats a LOT faster
if ( foodsituation == FOOD_STARVING )
numberofreduces += 1 + 2 * Random(4);
INT8 oldlife = pSoldier->stats.bLife;
pSoldier->stats.bLifeMax = max(2, pSoldier->stats.bLifeMax - numberofreduces);
pSoldier->stats.bLife = min(pSoldier->stats.bLife, pSoldier->stats.bLifeMax);
pSoldier->bBleeding = min(pSoldier->bBleeding, pSoldier->stats.bLifeMax);
// adjust poison values
pSoldier->bPoisonSum = min(pSoldier->bPoisonSum, pSoldier->stats.bLifeMax);
pSoldier->bPoisonLife = min(pSoldier->bPoisonLife, pSoldier->bPoisonSum);
pSoldier->bPoisonBleeding = min(pSoldier->bPoisonBleeding, pSoldier->bBleeding);
pSoldier->usStarveDamageHealth += oldlife - pSoldier->stats.bLifeMax;
// Update Profile
gMercProfiles[ pSoldier->ubProfile ].bLifeMax = pSoldier->stats.bLifeMax;
gMercProfiles[ pSoldier->ubProfile ].records.usTimesStatDamaged++;
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"%s's health was damaged due to lack of nutrition!", pSoldier->name );
// if we fall below OKLIFE, we start bleeding...
// Reason for this is that
if ( pSoldier->stats.bLife < OKLIFE )
{
// handling a soldiers death doesn't work somehow - let them bleed to death instead
/*BOOLEAN fMadeCorpse;
HandleSoldierDeath( pSoldier, &fMadeCorpse );
//remove the merc from the tactical
TacticalRemoveSoldier( pSoldier->ubID );*/
pSoldier->bBleeding = max(1, pSoldier->stats.bLife - 1);
pSoldier->stats.bLife = 1;
// Update Profile
gMercProfiles[ pSoldier->ubProfile ].bLifeMax = pSoldier->stats.bLifeMax;
pSoldier->usStarveDamageHealth += oldlife - pSoldier->stats.bLifeMax;
return;
}
// make stat RED for a while...
pSoldier->timeChanges.uiChangeStrengthTime = GetJA2Clock();
pSoldier->usValueGoneUp &= ~( HEALTH_INCREASE );
}
}
}
void HourlyFoodAutoDigestion( SOLDIERTYPE *pSoldier )
{
if ( !pSoldier )
return;
// don't eat if not necessary ( note that if the play decides to eat manually, he can achieve better results. This is intended to award micro-management)
if ( pSoldier->bFoodLevel > FoodMoraleMods[FOOD_MERC_START_CONSUME].bThreshold && pSoldier->bDrinkLevel > FoodMoraleMods[FOOD_MERC_START_CONSUME].bThreshold )
return;
// if were a prisoner, we can't feed ourself, and the player can't do that either. Instead the army provides food (not much and of bad quality)
if (pSoldier->bAssignment == ASSIGNMENT_POW)
{
INT16 powwater = gGameExternalOptions.usFoodDigestionHourlyBaseDrink * FOOD_POW_MULTIPLICATOR;
INT16 powfoodadd = powwater * gGameExternalOptions.usFoodDigestionHourlyBaseFood / gGameExternalOptions.usFoodDigestionHourlyBaseDrink;
// if we're thirsty or hungry, and this is nutritious, consume it
if ( pSoldier->bDrinkLevel < FoodMoraleMods[FOOD_VERY_LOW].bThreshold )
{
pSoldier->bDrinkLevel = min(pSoldier->bDrinkLevel + powwater, DRINK_MAX);
pSoldier->bDrinkLevel = max(pSoldier->bDrinkLevel, DRINK_MIN);
}
if ( pSoldier->bFoodLevel < FoodMoraleMods[FOOD_VERY_LOW].bThreshold )
{
pSoldier->bFoodLevel = min(pSoldier->bFoodLevel + powfoodadd, FOOD_MAX);
pSoldier->bFoodLevel = max(pSoldier->bFoodLevel, FOOD_MIN);
}
}
else
{
// no eating if not able to!
if ( pSoldier->flags.fMercAsleep == TRUE || pSoldier->stats.bLife < OKLIFE )
return;
// In certain facilities, we can also eat
for (UINT16 cnt = 0; cnt < NUM_FACILITY_TYPES; ++cnt)
{
// Is this facility here?
if (gFacilityLocations[SECTOR(pSoldier->sSectorX, pSoldier->sSectorY)][cnt].fFacilityHere)
{
// Does it allow training militia?
if (gFacilityTypes[cnt].AssignmentData[FAC_FOOD].sCantinaFoodModifier > 0)
{
if (cnt == (UINT16)pSoldier->sFacilityTypeOperated && // Soldier is operating this facility
GetSoldierFacilityAssignmentIndex( pSoldier ) != -1)
{
INT16 cantinafoodadd = gFacilityTypes[cnt].AssignmentData[FAC_FOOD].sCantinaFoodModifier;
INT16 cantinawater = cantinafoodadd * FOOD_FACILITY_WATER_FACTOR;
// if we're thirsty or hungry, and this is nutritious, consume it. When in a cantina, we are willing to eat a bit more
if ( pSoldier->bDrinkLevel < FoodMoraleMods[FOOD_MERC_STOP_FACILITY].bThreshold )
{
pSoldier->bDrinkLevel = min(pSoldier->bDrinkLevel + cantinawater, DRINK_MAX);
pSoldier->bDrinkLevel = max(pSoldier->bDrinkLevel, DRINK_MIN);
}
if ( pSoldier->bFoodLevel < FoodMoraleMods[FOOD_MERC_STOP_FACILITY].bThreshold )
{
pSoldier->bFoodLevel = min(pSoldier->bFoodLevel + cantinafoodadd, FOOD_MAX);
pSoldier->bFoodLevel = max(pSoldier->bFoodLevel, FOOD_MIN);
}
}
}
}
}
// search for food in our inventory
INT8 invsize = (INT8)pSoldier->inv.size(); // remember inventorysize, so we don't call size() repeatedly
// on the first loop, we omit food in bad condition, and refillable canteens and canned food
for ( INT8 bLoop = 0; bLoop < invsize; ++bLoop) // ... for all items in our inventory ...
{
// ... if Item exists and is food ...
if (pSoldier->inv[bLoop].exists() == true && Item[pSoldier->inv[bLoop].usItem].foodtype > 0 )
{
OBJECTTYPE * pObj = &(pSoldier->inv[bLoop]); // ... get pointer for this item ...
if ( pObj != NULL ) // ... if pointer is not obviously useless ...
{
UINT32 foodtype = Item[pObj->usItem].foodtype;
// omit non-degrading food (save it for later!)
if ( Food[foodtype].usDecayRate <= 0.0f )
continue;
// omit bad food (we don't like that and will eat it only if we have to)
FLOAT foodcondition = (*pObj)[0]->data.bTemperature / OVERHEATING_MAX_TEMPERATURE;
if ( foodcondition < FOOD_BAD_THRESHOLD )
continue;
if ( Item[pObj->usItem].canteen == TRUE )
continue;
// if we're thirsty or hungry, and this is nutritious, consume it
if ( ( pSoldier->bDrinkLevel < FoodMoraleMods[FOOD_MERC_START_CONSUME].bThreshold && Food[foodtype].bDrinkPoints > 0 ) || ( pSoldier->bFoodLevel < FoodMoraleMods[FOOD_MERC_START_CONSUME].bThreshold && Food[foodtype].bFoodPoints > 0 ) )
{
while ( (*pObj)[0]->data.objectStatus > 1 )
{
ApplyFood( pSoldier, pObj );
// if we're full, finish
if ( pSoldier->bFoodLevel > FoodMoraleMods[FOOD_MERC_START_CONSUME].bThreshold && pSoldier->bDrinkLevel > FoodMoraleMods[FOOD_MERC_START_CONSUME].bThreshold )
return;
}
}
}
}
}
// second loop: consume anything to feed
for ( INT8 bLoop = 0; bLoop < invsize; ++bLoop) // ... for all items in our inventory ...
{
// ... if Item exists and is food ...
if (pSoldier->inv[bLoop].exists() == true && Item[pSoldier->inv[bLoop].usItem].foodtype > 0 )
{
OBJECTTYPE * pObj = &(pSoldier->inv[bLoop]); // ... get pointer for this item ...
if ( pObj != NULL ) // ... if pointer is not obviously useless ...
{
UINT32 foodtype = Item[pObj->usItem].foodtype;
// if we're thirsty or hungry, and this is nutritious, consume it
if ( ( pSoldier->bDrinkLevel < FoodMoraleMods[FOOD_MERC_START_CONSUME].bThreshold && Food[foodtype].bDrinkPoints > 0 ) || ( pSoldier->bFoodLevel < FoodMoraleMods[FOOD_MERC_START_CONSUME].bThreshold && Food[foodtype].bFoodPoints > 0 ) )
{
while ( (*pObj)[0]->data.objectStatus > 1 )
{
ApplyFood( pSoldier, pObj );
// if we're full, finish
if ( pSoldier->bFoodLevel > FoodMoraleMods[FOOD_MERC_START_CONSUME].bThreshold && pSoldier->bDrinkLevel > FoodMoraleMods[FOOD_MERC_START_CONSUME].bThreshold )
return;
}
}
}
}
}
}
}
void HourlyFoodUpdate( void )
{
INT8 bMercID, bLastTeamID;
SOLDIERTYPE * pSoldier = NULL;
bMercID = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
bLastTeamID = gTacticalStatus.Team[ gbPlayerNum ].bLastID;
// loop through all mercs to calculate their morale
for ( pSoldier = MercPtrs[ bMercID ]; bMercID <= bLastTeamID; ++bMercID, ++pSoldier)
{
//if the merc is active, and in Arulco
if ( pSoldier && pSoldier->bActive && pSoldier->ubProfile != NO_PROFILE && !(pSoldier->bAssignment == IN_TRANSIT || pSoldier->bAssignment == ASSIGNMENT_DEAD ) )
{
// digestion
HourlyFoodSituationUpdate( pSoldier );
// if hungry, eat something automatically from the inventory
HourlyFoodAutoDigestion( pSoldier );
}
}
// decay food everywhere
HourlyFoodDecay();
}
UINT8 GetWaterQuality(INT16 asMapX, INT16 asMapY, INT8 asMapZ)
{
UINT8 waterquality = WATER_NONE;
// for now, we assume that only sectors on the surface have access to water
UINT8 ubSectorId = SECTOR(asMapX, asMapY);
if (asMapZ == 0 && ubSectorId >= 0 && ubSectorId < 256 )
{
waterquality = gSectorWaterType[ubSectorId][asMapZ];
}
return waterquality;
}
// a function that tries to fill up all canteens in this sector
void SectorFillCanteens( void )
{
// no functionality if not in tactical or in combat, or nobody is here
if ( guiCurrentScreen != GAME_SCREEN || (gTacticalStatus.uiFlags & INCOMBAT) || gusSelectedSoldier == NOBODY )
return;
// determine if there are any patches of water in this sector.
// If so, fill up all refillable water containers (= canteens) (there is no way to check if this is actually fresh water, we just assume it is)
// If not, see if there is a water drum, and fill up the canteens from that one
UINT8 waterquality = GetWaterQuality(gWorldSectorX, gWorldSectorY, gbWorldSectorZ);
if ( waterquality == WATER_DRINKABLE || waterquality == WATER_POISONOUS )
{
// the temperature of the water in this sector (temperature reflects the quality)
FLOAT addtemperature = OVERHEATING_MAX_TEMPERATURE;
// if the water in this sector is poisoned, we add a different temperature - resulting in worsening of the item's decay status
if ( waterquality == WATER_POISONOUS )
addtemperature = 0.0f;
// first step: fill all canteens in inventories
INT8 bMercID, bLastTeamID;
SOLDIERTYPE * pSoldier = NULL;
bMercID = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
bLastTeamID = gTacticalStatus.Team[ gbPlayerNum ].bLastID;
// loop through all mercs
for ( pSoldier = MercPtrs[ bMercID ]; bMercID <= bLastTeamID; bMercID++, pSoldier++)
{
//if the merc is in this sector
if ( pSoldier->bActive && pSoldier->ubProfile != NO_PROFILE && pSoldier->bInSector && ( pSoldier->sSectorX == gWorldSectorX ) && ( pSoldier->sSectorY == gWorldSectorY ) && ( pSoldier->bSectorZ == gbWorldSectorZ) )
{
INT8 invsize = (INT8)pSoldier->inv.size(); // remember inventorysize, so we don't call size() repeatedly
for ( INT8 bLoop = 0; bLoop < invsize; ++bLoop) // ... for all items in our inventory ...
{
// ... if Item exists and is canteen (that can have drink points) ...
if (pSoldier->inv[bLoop].exists() == true && Item[pSoldier->inv[bLoop].usItem].canteen && Food[Item[pSoldier->inv[bLoop].usItem].foodtype].bDrinkPoints > 0)
{
OBJECTTYPE* pObj = &(pSoldier->inv[bLoop]); // ... get pointer for this item ...
if ( pObj != NULL ) // ... if pointer is not obviously useless ...
{
for(INT16 i = 0; i < pObj->ubNumberOfObjects; ++i) // ... there might be multiple items here (item stack), so for each one ...
{
UINT16 status = (*pObj)[i]->data.objectStatus;
UINT16 statusmmissing = max(0, 100 - status);
FLOAT temperature = (*pObj)[i]->data.bTemperature;
(*pObj)[i]->data.objectStatus = 100; // refill canteen
(*pObj)[i]->data.bTemperature = (status * temperature + statusmmissing * addtemperature)/100;
}
}
}
}
}
}
// second step: fill canteens in sector
for( UINT32 uiCount = 0; uiCount < guiNumWorldItems; ++uiCount ) // ... for all items in the world ...
{
if( gWorldItems[ uiCount ].fExists ) // ... if item exists ...
{
// ... if Item exists and is a canteen (only those are refillable) ...
if ( Item[gWorldItems[ uiCount ].object.usItem].canteen && Food[Item[gWorldItems[ uiCount ].object.usItem].foodtype].bDrinkPoints > 0)
{
OBJECTTYPE* pObj = &(gWorldItems[ uiCount ].object); // ... get pointer for this item ...
if ( pObj != NULL ) // ... if pointer is not obviously useless ...
{
for(INT16 i = 0; i < pObj->ubNumberOfObjects; ++i) // ... there might be multiple items here (item stack), so for each one ...
{
UINT16 status = (*pObj)[i]->data.objectStatus;
UINT16 statusmmissing = max(0, 100 - status);
FLOAT temperature = (*pObj)[i]->data.bTemperature;
(*pObj)[i]->data.objectStatus = 100; // refill canteen
(*pObj)[i]->data.bTemperature = (status * temperature + statusmmissing * addtemperature)/100;
}
}
}
}
}
}
else
{
OBJECTTYPE* pWaterDrum = GetUsableWaterDrumInSector();
if ( !pWaterDrum || !(pWaterDrum->exists()) )
return;
INT32 drumsize = Food[Item[pWaterDrum->usItem].foodtype].bDrinkPoints;
// first step: fill all canteens in inventories
INT8 bMercID, bLastTeamID;
SOLDIERTYPE * pSoldier = NULL;
bMercID = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
bLastTeamID = gTacticalStatus.Team[ gbPlayerNum ].bLastID;
// loop through all mercs
for ( pSoldier = MercPtrs[ bMercID ]; bMercID <= bLastTeamID; bMercID++, pSoldier++)
{
//if the merc is in this sector
if ( pSoldier->bActive && pSoldier->ubProfile != NO_PROFILE && pSoldier->bInSector && ( pSoldier->sSectorX == gWorldSectorX ) && ( pSoldier->sSectorY == gWorldSectorY ) && ( pSoldier->bSectorZ == gbWorldSectorZ) )
{
INT8 invsize = (INT8)pSoldier->inv.size(); // remember inventorysize, so we don't call size() repeatedly
for ( INT8 bLoop = 0; bLoop < invsize; ++bLoop) // ... for all items in our inventory ...
{
// ... if Item exists and is canteen and is NOT a water drum...
if (pSoldier->inv[bLoop].exists() == true && Item[pSoldier->inv[bLoop].usItem].canteen && (Food[Item[pSoldier->inv[bLoop].usItem].foodtype].bDrinkPoints > 0) && !HasItemFlag(pSoldier->inv[bLoop].usItem, (WATER_DRUM)))
{
OBJECTTYPE* pObj = &(pSoldier->inv[bLoop]); // ... get pointer for this item ...
if ( pObj != NULL && pObj->exists() ) // ... if pointer is not obviously useless ...
{
INT32 canteensize = Food[Item[pObj->usItem].foodtype].bDrinkPoints;
for(INT16 i = 0; i < pObj->ubNumberOfObjects; ++i) // ... there might be multiple items here (item stack), so for each one ...
{
if ( (*pObj)[i]->data.objectStatus < 100 ) // ... and status is > 1 (1 means that it is empty, but still usable)
{
INT32 ptsneeded = (INT32)((100 - (*pObj)[i]->data.objectStatus) * canteensize / 100);
INT32 ptsinwaterdrum = (INT32)(((*pWaterDrum)[i]->data.objectStatus - 1) * drumsize / 100); // -1 because 1% is the status of an empty water drum
if ( ptsneeded < ptsinwaterdrum )
{
(*pObj)[i]->data.objectStatus = 100;
(*pWaterDrum)[i]->data.objectStatus = max(1, (INT16)((100 * ( ptsinwaterdrum - ptsneeded )) / drumsize) );
}
else
{
(*pObj)[i]->data.objectStatus += (INT16)((100 * ptsinwaterdrum) / canteensize);
(*pWaterDrum)[i]->data.objectStatus = 1;
}
(*pObj)[i]->data.bTemperature = ((*pObj)[i]->data.bTemperature + (*pWaterDrum)[0]->data.bTemperature) / 2; // water now has mixed freshness
if ( (*pWaterDrum)[0]->data.objectStatus == 1 )
{
// get a new water drum!
pWaterDrum = GetUsableWaterDrumInSector();
if ( !pWaterDrum || !(pWaterDrum->exists()) )
return;
drumsize = Food[Item[pWaterDrum->usItem].foodtype].bDrinkPoints;
}
}
}
}
}
}
}
}
// second step: fill canteens in sector
for( UINT32 uiCount = 0; uiCount < guiNumWorldItems; ++uiCount ) // ... for all items in the world ...
{
if( gWorldItems[ uiCount ].fExists ) // ... if item exists ...
{
// ... if Item exists and is a canteen (only those are refillable) ...
if ( Item[gWorldItems[ uiCount ].object.usItem].canteen )
{
OBJECTTYPE* pObj = &(gWorldItems[ uiCount ].object); // ... get pointer for this item ...
if ( pObj != NULL && pObj->exists() ) // ... if pointer is not obviously useless ...
{
if ( (Food[pObj->usItem].bDrinkPoints > 0) && !HasItemFlag(pObj->usItem, (WATER_DRUM)) ) // ... if item is NOT a water drum...
{
INT32 canteensize = Food[Item[pObj->usItem].foodtype].bDrinkPoints;
for(INT16 i = 0; i < pObj->ubNumberOfObjects; ++i) // ... there might be multiple items here (item stack), so for each one ...
{
if ( (*pObj)[i]->data.objectStatus < 100 ) // ... and status is > 1 (1 means that it is empty, but still usable)
{
INT32 ptsneeded = (INT32)((100 - (*pObj)[i]->data.objectStatus) * canteensize / 100);
INT32 ptsinwaterdrum = (INT32)(((*pWaterDrum)[i]->data.objectStatus - 1) * drumsize / 100); // -1 because 1% is the status of an empty water drum
if ( ptsneeded < ptsinwaterdrum )
{
(*pObj)[i]->data.objectStatus = 100;
(*pWaterDrum)[i]->data.objectStatus = max(1, (INT16)((100 * ( ptsinwaterdrum - ptsneeded )) / drumsize) );
}
else
{
(*pObj)[i]->data.objectStatus += (INT16)((100 * ptsinwaterdrum) / canteensize);
(*pWaterDrum)[i]->data.objectStatus = 1;
}
(*pObj)[0]->data.bTemperature = ((*pObj)[0]->data.bTemperature + (*pWaterDrum)[0]->data.bTemperature) / 2; // water now has mixed freshness
if ( (*pWaterDrum)[i]->data.objectStatus == 1 )
{
// get a new water drum!
pWaterDrum = GetUsableWaterDrumInSector();
if ( !pWaterDrum || !(pWaterDrum->exists()) )
return;
drumsize = Food[Item[pWaterDrum->usItem].foodtype].bDrinkPoints;
}
}
}
}
}
}
}
}
}
}
OBJECTTYPE* GetUsableWaterDrumInSector( void )
{
for( UINT32 uiCount = 0; uiCount < guiNumWorldItems; ++uiCount ) // ... for all items in the world ...
{
if( gWorldItems[ uiCount ].fExists ) // ... if item exists ...
{
// ... if Item exists and is a canteen (only those are refillable) ...
if ( Item[gWorldItems[ uiCount ].object.usItem].canteen )
{
OBJECTTYPE* pObj = &(gWorldItems[ uiCount ].object); // ... get pointer for this item ...
if ( pObj != NULL && pObj->exists() ) // ... if pointer is not obviously useless ...
{
if ( HasItemFlag(pObj->usItem, (WATER_DRUM)) ) // ... if item is a water drum...
{
for(INT16 i = 0; i < pObj->ubNumberOfObjects; ++i) // ... there might be multiple items here (item stack), so for each one ...
{
if ( (*pObj)[i]->data.objectStatus > 1 ) // ... and status is > 1 (1 means that it is empty, but still usable)
{
return( pObj );
}
}
}
}
}
}
}
return( NULL );
}
void HourlyFoodDecay( void )
{
// decay food in all inventories
UINT32 cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
for ( SOLDIERTYPE* pSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; cnt++, pSoldier++)
{
if ( pSoldier && pSoldier->bActive )
{
pSoldier->SoldierInventoryFoodDecay();
}
}
if ( gGameExternalOptions.fFoodDecayInSectors )
{
INT16 currentSectorX = gWorldSectorX;
INT16 currentSectorY = gWorldSectorY;
INT8 currentSectorZ = gbWorldSectorZ;
// decay food in all visited sectors
for ( INT16 sbMapX = 1; sbMapX < MAP_WORLD_X - 1; ++sbMapX )
{
for ( INT16 sbMapY = 1; sbMapY < MAP_WORLD_Y - 1; ++sbMapY )
{
for ( UINT8 ubMapZ = 0; ubMapZ < 4; ++ubMapZ )
{
// only if sector has already been visisted
if( GetSectorFlagStatus( sbMapX, sbMapY, ubMapZ, SF_ALREADY_VISITED ) == TRUE )
{
BuildStashForSelectedSectorAndDecayFood(sbMapX, sbMapY, (INT16)ubMapZ);
}
}
}
}
}
}
void SectorFoodDecay( WORLDITEM* pWorldItem, UINT32 size )
{
// one hour has 60 minutes, with 12 5-second-intervals (cooldown values are based on 5-second values)
FLOAT decaymod = 12*60*gGameExternalOptions.sFoodDecayModificator;
for( UINT32 uiCount = 0; uiCount < size; ++uiCount ) // ... for all items in the world ...
{
if( pWorldItem[ uiCount ].fExists ) // ... if item exists ...
{
if ( Item[pWorldItem[ uiCount ].object.usItem].foodtype > 0 ) // ... if is food...
{
OBJECTTYPE* pObj = &(pWorldItem[ uiCount ].object); // ... get pointer for this item ...
if ( pObj != NULL ) // ... if pointer is not obviously useless ...
{
if ( Food[Item[pObj->usItem].foodtype].usDecayRate > 0.0f ) // ... if the food can decay...
{
for(INT16 i = 0; i < pObj->ubNumberOfObjects; ++i) // ... there might be multiple items here (item stack), so for each one ...
{
(*pObj)[i]->data.bTemperature = max(0.0f, (*pObj)[i]->data.bTemperature - decaymod * Food[Item[pObj->usItem].foodtype].usDecayRate); // set new temperature
}
}
}
}
}
}
}
// commented out, as we now look for an xml value. Might be relevant in the future, though
/*BOOLEAN DrinkableWaterInSector(INT16 asMapX, INT16 asMapY, INT8 asMapZ)
{
// static variables allow us to remember the result of the last time this function was called - this way, only one call per sector is required
static INT16 sMapX = 0;
static INT16 sMapY = 0;
static INT8 sMapZ = 0;
static BOOLEAN drinkablewaterfound = FALSE;
if ( asMapX != sMapX || asMapY != sMapY || asMapZ != sMapZ )
{
drinkablewaterfound = FALSE;
for( INT32 sGridNo = 0; sGridNo < MAX_MAP_POS; ++sGridNo )
{
if ( Water(sGridNo) || IsKitchenFurnitureWaterSource(sGridNo) )
{
drinkablewaterfound = TRUE;
break;
}
}
UINT8 ubSectorId = SECTOR(asMapX, asMapY);
if (ubSectorId >= 0 && ubSectorId < 256 && gSectorWaterType[ubSectorId][asMapZ] == WATER_DRINKABLE )
{
drinkablewaterfound = TRUE;
}
sMapX = asMapX;
sMapY = asMapY;
sMapZ = asMapZ;
}
return drinkablewaterfound;
}*/
// commented out, as we now look for an xml value. Might be relevant in the future, though
/*// determine wether there is a kitechen furniture here (we assume its a sink, so it'll have water)
BOOLEAN IsKitchenFurnitureWaterSource( INT32 sGridNo )
{
STRUCTURE* pStruct = FindStructure(sGridNo, STRUCTURE_GENERIC);
if ( pStruct != NULL )
{
// Get LEVELNODE for struct and remove!
LEVELNODE* pNode = FindLevelNodeBasedOnStructure( pStruct->sGridNo, pStruct );
if ( pNode )
{
UINT32 uiTileType = 0;
if ( GetTileType( pNode->usIndex, &uiTileType ) )
{
UINT16 usIndex = pNode->usIndex;
// Check if we are a sandbag
if ( ( _strnicmp( gTilesets[ giCurrentTilesetID ].TileSurfaceFilenames[ uiTileType ], "furn_6.sti", 10) == 0 ) ||
( _strnicmp( gTilesets[ giCurrentTilesetID ].TileSurfaceFilenames[ uiTileType ], "old_furn.sti", 12) == 0 ) ||
( _strnicmp( gTilesets[ giCurrentTilesetID ].TileSurfaceFilenames[ uiTileType ], "furnmix.sti", 11) == 0 ) ||
( _strnicmp( gTilesets[ giCurrentTilesetID ].TileSurfaceFilenames[ uiTileType ], "furn_mix.sti", 12) == 0 ) )
{
return TRUE;
}
}
}
}
return FALSE;
}*/
+106
View File
@@ -0,0 +1,106 @@
#ifndef __FOOD_H
#define __FOOD_H
#include "soldier control.h"
#define FOOD_BAD_THRESHOLD 0.5f // must be > 0 !!!!!
#define FOOD_BAD_THRESHOLD_INVERSE 1.0f/FOOD_BAD_THRESHOLD
#define FOOD_MIN - 20000
#define FOOD_MAX 10000
#define DRINK_MIN - 20000
#define DRINK_MAX 10000
#define FOOD_MORALE_DRINK_TO_FOOD_RATIO 1.0f
#define FOOD_FACILITY_WATER_FACTOR 3.0f
#define FOOD_POW_MULTIPLICATOR 1.2f // multiplicator to the water we get when POWs (so many times our water digestion rate, so we will barely survive)
typedef enum
{
FOOD_STUFFED,
FOOD_EXTREMELY_FULL,
FOOD_FULL,
FOOD_SLIGHTLY_FULL,
FOOD_NORMAL,
FOOD_LOW,
FOOD_EVEN_LOWER,
FOOD_VERY_LOW,
FOOD_DANGER,
FOOD_DESPERATE,
FOOD_STARVING,
NUM_FOOD_MORALE_TYPES
} FoodMoraleModType;
#define FOOD_MERC_START_CONSUME FOOD_EVEN_LOWER
#define FOOD_MERC_STOP_FACILITY FOOD_FULL
typedef struct
{
INT32 bThreshold;
INT8 bMoraleModifier; // absolute modifier to max morale
INT8 bSleepModifier; // absolute modifier
INT8 bBreathRegenModifier; // percentage modifier
INT8 bAssignmentEfficiencyModifier; // percentage modifier
UINT8 ubStatDamageChance; // percentual chance to receive damage to life and strength
} FoodMoraleMod;
extern FoodMoraleMod FoodMoraleMods[NUM_FOOD_MORALE_TYPES];
extern UINT8 gbPlayerNum;
typedef struct
{
UINT16 uiIndex;
CHAR16 szName[80]; // name of this food
INT32 bFoodPoints; // points that will be added to our drink level
INT32 bDrinkPoints; // points that will be added to our drink level
UINT16 ubPortionSize; // how much is 'eaten' as a portion (percentage)
INT8 bMoraleMod; // morale modificator for eating this
FLOAT usDecayRate; // rate at which food decays
} FOODTYPE;
//GLOBALS
extern FOODTYPE Food[FOOD_TYPE_MAX];
// for determining the type of water source a sector has
typedef enum
{
WATER_NONE, // no water at all
WATER_DRINKABLE, // drinkable water (rivers, water supply from houses)
WATER_SALTWATER, // salt water, can't drink that (until something special for this gets implemented)
WATER_POISONOUS // there is water, but it is poisoned (swamps and polluted sectors)
} FoodSectorWaterSupply;
BOOLEAN ApplyFood( SOLDIERTYPE *pSoldier, OBJECTTYPE *pObject );
UINT8 GetFoodSituation( SOLDIERTYPE *pSoldier );
void FoodMaxMoraleModifiy( SOLDIERTYPE *pSoldier, UINT8* pubMaxMorale );
void FoodNeedForSleepModifiy( SOLDIERTYPE *pSoldier, UINT8* pubNeedForSleep );
void ReducePointsForHunger( SOLDIERTYPE *pSoldier, UINT32 *pusPoints );
void ReduceBPRegenForHunger( SOLDIERTYPE *pSoldier, INT32 *psPoints );
void HourlyFoodSituationUpdate( SOLDIERTYPE *pSoldier );
void HourlyFoodAutoDigestion( SOLDIERTYPE *pSoldier );
void HourlyFoodUpdate( void );
UINT8 GetWaterQuality(INT16 asMapX, INT16 asMapY, INT8 asMapZ);
// a function that tries to fill up all canteens in this sector
void SectorFillCanteens( void );
OBJECTTYPE* GetUsableWaterDrumInSector( void );
void HourlyFoodDecay( void );
// Decay the food in a sector, performed every hour
void SectorFoodDecay( WORLDITEM* pWorldItem, UINT32 size );
// checks wether there is any drinkable water source in this sector. Atm every water found is taken as 'drinkable'
//BOOLEAN DrinkableWaterInSector(INT16 asMapX, INT16 asMapY, INT8 asMapZ);
// determine wether there is a kitechen furniture here (we assume its a sink, so it'll have water)
//BOOLEAN IsKitchenFurnitureWaterSource( INT32 sGridNo );
#endif
+39
View File
@@ -73,6 +73,7 @@
#include "opplist.h"
#include "los.h"
#include "Map Screen Interface Map.h"
#include "Food.h" // added by Flugente
#endif
//forward declarations of common classes to eliminate includes
@@ -2462,6 +2463,27 @@ void InternalInitEDBTooltipRegion( OBJECTTYPE * gpItemDescObject, UINT32 guiCurr
MSYS_EnableRegion( &gUDBFasthelpRegions[ iFirstDataRegion + cnt ] );
cnt++;
}
//////////////////// drinkable WATER
UINT32 foodtype = Item[gpItemDescObject->usItem].foodtype;
if ( foodtype > 0 )
{
if ( Food[foodtype].bDrinkPoints > 0 )
{
swprintf( pStr, L"%s%s", szUDBGenSecondaryStatsTooltipText[ 26 ], szUDBGenSecondaryStatsExplanationsTooltipText[ 26 ]);
SetRegionFastHelpText( &(gUDBFasthelpRegions[ iFirstDataRegion + cnt ]), pStr );
MSYS_EnableRegion( &gUDBFasthelpRegions[ iFirstDataRegion + cnt ] );
cnt++;
}
if ( Food[foodtype].bFoodPoints > 0 )
{
swprintf( pStr, L"%s%s", szUDBGenSecondaryStatsTooltipText[ 27 ], szUDBGenSecondaryStatsExplanationsTooltipText[ 27 ]);
SetRegionFastHelpText( &(gUDBFasthelpRegions[ iFirstDataRegion + cnt ]), pStr );
MSYS_EnableRegion( &gUDBFasthelpRegions[ iFirstDataRegion + cnt ] );
cnt++;
}
}
}
//////////////////////////////////////////////////////
@@ -5453,6 +5475,23 @@ void DrawSecondaryStats( OBJECTTYPE * gpItemDescObject )
BltVideoObjectFromIndex( guiSAVEBUFFER, guiItemInfoSecondaryIcon, 24, gItemDescGenSecondaryRegions[cnt].sLeft+sOffsetX, gItemDescGenSecondaryRegions[cnt].sTop+sOffsetY, VO_BLT_SRCTRANSPARENCY, NULL );
cnt++;
}
//////////////////// drinkable WATER
UINT32 foodtype = Item[gpItemDescObject->usItem].foodtype;
if ( foodtype > 0 )
{
if ( Food[foodtype].bDrinkPoints > 0 )
{
BltVideoObjectFromIndex( guiSAVEBUFFER, guiItemInfoSecondaryIcon, 26, gItemDescGenSecondaryRegions[cnt].sLeft+sOffsetX, gItemDescGenSecondaryRegions[cnt].sTop+sOffsetY, VO_BLT_SRCTRANSPARENCY, NULL );
cnt++;
}
if ( Food[foodtype].bFoodPoints > 0 )
{
BltVideoObjectFromIndex( guiSAVEBUFFER, guiItemInfoSecondaryIcon, 27, gItemDescGenSecondaryRegions[cnt].sLeft+sOffsetX, gItemDescGenSecondaryRegions[cnt].sTop+sOffsetY, VO_BLT_SRCTRANSPARENCY, NULL );
cnt++;
}
}
}
void DrawWeaponValues( OBJECTTYPE * gpItemDescObject )
+69
View File
@@ -84,6 +84,7 @@
#include "SkillCheck.h" // added by Flugente
#include "random.h" // added by Flugente
#include "Explosion Control.h" // added by Flugente
#include "Food.h" // added by Flugente
#endif
#ifdef JA2UB
@@ -3803,6 +3804,23 @@ void INVRenderItem( UINT32 uiBuffer, SOLDIERTYPE * pSoldier, OBJECTTYPE *pObjec
DrawItemUIBarEx( pObjShown, DRAW_ITEM_TEMPERATURE, sX, sY + sHeight-1, ITEMDESC_ITEM_STATUS_WIDTH, sHeight-1, colour, colour, TRUE, guiSAVEBUFFER );
}
// Flugente: display condition of food if it can decay
if ( gGameOptions.fFoodSystem == TRUE && Item[pObject->usItem].foodtype > 0 )
{
if ( OVERHEATING_MAX_TEMPERATURE > 0 )
{
FLOAT condition = (*pObject)[0]->data.bTemperature / OVERHEATING_MAX_TEMPERATURE;
UINT32 red = (UINT32) ( 127 );
UINT32 green = (UINT32) ( 54 + 201 * ( min(1.0f, condition ) ) );
UINT32 blue = 0;
UINT16 colour = Get16BPPColor( FROMRGB( red, green, blue ) );
DrawItemUIBarEx( pObject, DRAW_ITEM_TEMPERATURE, sX, sY + sHeight-1, ITEMDESC_ITEM_STATUS_WIDTH, sHeight-1, colour, colour, TRUE, guiSAVEBUFFER);
}
}
// display symbol if we are leaning our weapon on something
// display only if eapon resting is allowed, display is allowed, item is a gun/launcher, we are a person, we hold the gun in our hand, and we are resting the gun
if ( gGameExternalOptions.fWeaponResting && gGameExternalOptions.fDisplayWeaponRestingIndicator && pItem->usItemClass & (IC_GUN | IC_LAUNCHER) && pSoldier && &(pSoldier->inv[pSoldier->ubAttackingHand]) == pObject && pSoldier->IsWeaponMounted() )
@@ -6677,6 +6695,57 @@ void RenderItemDescriptionBox( )
mprintf( usX, usY, pStr );
}
// Flugente: display condition of food if it can decay
else if ( gGameOptions.fFoodSystem == TRUE && Item[gpItemDescObject->usItem].foodtype > 0 )
{
if ( OVERHEATING_MAX_TEMPERATURE > 0 )
{
FLOAT condition = (*gpItemDescObject)[0]->data.bTemperature / OVERHEATING_MAX_TEMPERATURE;
UINT32 red = (UINT32) ( 127 );
UINT32 green = (UINT32) ( 54 + 201 * ( min(1.0f, condition ) ) );
UINT32 blue = 0;
UINT8 FoodStringNum = 6;
if ( condition > 0.84f )
FoodStringNum = 1;
else if ( condition > 0.66f )
FoodStringNum = 2;
else if ( condition > 0.5f )
FoodStringNum = 3;
else if ( condition > 0.33f )
FoodStringNum = 4;
else if ( condition > 0.16f )
FoodStringNum = 5;
// UDB system displays a string with colored condition text.
int regionindex = 7;
SetFontForeground( ForegroundColor );
swprintf( pStr, L"%s", gFoodDesc[0] ); // "Temperature is "
mprintf( gItemDescTextRegions[regionindex].sLeft, gItemDescTextRegions[regionindex].sTop, pStr );
// Record length
INT16 indent = StringPixLength( gFoodDesc[0], ITEMDESC_FONT );
swprintf( pStr, L"%s", gFoodDesc[FoodStringNum] );
SetRGBFontForeground( red, green, blue );
mprintf( gItemDescTextRegions[regionindex].sLeft+indent+2, gItemDescTextRegions[regionindex].sTop, pStr );
// Record length
indent += StringPixLength( gFoodDesc[FoodStringNum], ITEMDESC_FONT );
SetFontForeground( ForegroundColor );
swprintf( pStr, L"%s", gFoodDesc[7] ); // "."
mprintf( gItemDescTextRegions[regionindex].sLeft + indent + 2, gItemDescTextRegions[regionindex].sTop, pStr );
// to get the text to the left side...
swprintf( pStr, L"");
FindFontRightCoordinates( gItemDescTextRegions[regionindex].sLeft, gItemDescTextRegions[regionindex].sTop, gItemDescTextRegions[regionindex].sRight - gItemDescTextRegions[regionindex].sLeft ,gItemDescTextRegions[regionindex].sBottom - gItemDescTextRegions[regionindex].sTop ,pStr, BLOCKFONT2, &usX, &usY);
mprintf( usX, usY, pStr );
}
}
// UDB system displays a string with colored condition text.
SetFontForeground( ForegroundColor );
+59 -12
View File
@@ -74,6 +74,7 @@
#include "Boxing.h"
// HEADROCK HAM 3.6: This is required for Stat Progress Bars
#include "Campaign.h"
#include "Food.h" // added by Flugente
#endif
//legion by Jazz
@@ -2767,7 +2768,7 @@ void RenderSMPanel( BOOLEAN *pfDirty )
FindFontRightCoordinates(SM_DEX_X, SM_DEX_Y ,SM_STATS_WIDTH ,SM_STATS_HEIGHT ,sString, BLOCKFONT2, &usX, &usY);
mprintf( usX, usY , sString );
UpdateStatColor( gpSMCurrentMerc->timeChanges.uiChangeStrengthTime, ( BOOLEAN )( gpSMCurrentMerc->usValueGoneUp & STRENGTH_INCREASE?TRUE: FALSE ), ( BOOLEAN ) ( ( gGameOptions.fNewTraitSystem && ( gpSMCurrentMerc->ubCriticalStatDamage[DAMAGED_STAT_STRENGTH] > 0 )) ? TRUE : FALSE), MercUnderTheInfluence(gpSMCurrentMerc, DRUG_TYPE_STRENGTH)); // SANDRO
UpdateStatColor( gpSMCurrentMerc->timeChanges.uiChangeStrengthTime, ( BOOLEAN )( gpSMCurrentMerc->usValueGoneUp & STRENGTH_INCREASE?TRUE: FALSE ), ( BOOLEAN ) ( (( gGameOptions.fNewTraitSystem && ( gpSMCurrentMerc->ubCriticalStatDamage[DAMAGED_STAT_STRENGTH] > 0 )) || (gGameOptions.fFoodSystem && gpSMCurrentMerc->usStarveDamageStrength > 0) ) ? TRUE : FALSE), MercUnderTheInfluence(gpSMCurrentMerc, DRUG_TYPE_STRENGTH)); // SANDRO
swprintf( sString, L"%2d", gpSMCurrentMerc->stats.bStrength + gpSMCurrentMerc->bExtraStrength );
FindFontRightCoordinates(SM_STR_X, SM_STR_Y ,SM_STATS_WIDTH ,SM_STATS_HEIGHT ,sString, BLOCKFONT2, &usX, &usY);
@@ -2928,14 +2929,30 @@ void RenderSMPanel( BOOLEAN *pfDirty )
else
{
GetMoraleString( gpSMCurrentMerc, pMoraleStr );
// Flugente: added a display for poison, only show text if actualy poisoned
if ( gpSMCurrentMerc->bPoisonSum > 0 )
// Flugente: food info if food system is active
if ( gGameOptions.fFoodSystem )
{
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 );
// Flugente: added a display for poison, only show text if actually poisoned
if ( gpSMCurrentMerc->bPoisonSum > 0 )
{
swprintf( pStr, TacticalStr[ MERC_VITAL_STATS_WITH_POISON_AND_FOOD_POPUPTEXT ], gpSMCurrentMerc->stats.bLife, gpSMCurrentMerc->stats.bLifeMax, gpSMCurrentMerc->bPoisonSum, gpSMCurrentMerc->stats.bLifeMax, gpSMCurrentMerc->bBreath, gpSMCurrentMerc->bBreathMax, pMoraleStr, (INT32)(100*gpSMCurrentMerc->bDrinkLevel/FOOD_MAX), L"%", (INT32)(100*gpSMCurrentMerc->bFoodLevel/FOOD_MAX), L"%" );
}
else
{
swprintf( pStr, TacticalStr[ MERC_VITAL_STATS_WITH_FOOD_POPUPTEXT ], gpSMCurrentMerc->stats.bLife, gpSMCurrentMerc->stats.bLifeMax, gpSMCurrentMerc->bBreath, gpSMCurrentMerc->bBreathMax, pMoraleStr, (INT32)(100*gpSMCurrentMerc->bDrinkLevel/FOOD_MAX), L"%", (INT32)(100*gpSMCurrentMerc->bFoodLevel/FOOD_MAX), L"%" );
}
}
else
{
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 actually 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 );
@@ -3264,8 +3281,8 @@ void SMInvClickCamoCallback( MOUSE_REGION * pRegion, INT32 iReason )
// Say OK acknowledge....
gpSMCurrentMerc->DoMercBattleSound( BATTLE_SOUND_COOL1 );
}
}
else if ( ApplyCanteen( gpSMCurrentMerc, gpItemPointer, &fGoodAPs ) )
}
else if ( !gGameOptions.fFoodSystem && ApplyCanteen( gpSMCurrentMerc, gpItemPointer, &fGoodAPs ) )
{
// Dirty
if ( fGoodAPs )
@@ -3298,7 +3315,7 @@ void SMInvClickCamoCallback( MOUSE_REGION * pRegion, INT32 iReason )
gpSMCurrentMerc->DoMercBattleSound( BATTLE_SOUND_COOL1 );
}
}
else if ( ApplyDrugs( gpSMCurrentMerc, gpItemPointer ) )
else if ( gGameOptions.fFoodSystem && ApplyDrugs( gpSMCurrentMerc, gpItemPointer ) )
{
// Dirty
fInterfacePanelDirty = DIRTYLEVEL2;
@@ -3325,6 +3342,21 @@ void SMInvClickCamoCallback( MOUSE_REGION * pRegion, INT32 iReason )
gpSMCurrentMerc->DoMercBattleSound( BATTLE_SOUND_COOL1 );
}
else if ( ApplyFood( gpSMCurrentMerc, gpItemPointer ) )
{
// Dirty
fInterfacePanelDirty = DIRTYLEVEL2;
// Check if it's the same now!
if ( gpItemPointer->exists() == false )
{
gbCompatibleApplyItem = FALSE;
EndItemPointer( );
}
// Say OK acknowledge....
gpSMCurrentMerc->DoMercBattleSound( BATTLE_SOUND_COOL1 );
}
else
{
// Send message
@@ -5475,14 +5507,29 @@ void RenderTEAMPanel( BOOLEAN fDirty )
{
GetMoraleString( pSoldier, pMoraleStr );
// Flugente: added a display for poison, only show text if actually poisoned
if ( pSoldier->bPoisonSum > 0 )
if ( gGameOptions.fFoodSystem )
{
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 );
// Flugente: added a display for poison, only show text if actually poisoned
if ( pSoldier->bPoisonSum > 0 )
{
swprintf( pStr, TacticalStr[ MERC_VITAL_STATS_WITH_POISON_AND_FOOD_POPUPTEXT ], pSoldier->stats.bLife, pSoldier->stats.bLifeMax, pSoldier->bPoisonSum, pSoldier->stats.bLifeMax, pSoldier->bBreath, pSoldier->bBreathMax, pMoraleStr, (INT32)(100*pSoldier->bDrinkLevel/FOOD_MAX), L"%", (INT32)(100*pSoldier->bFoodLevel/FOOD_MAX), L"%" );
}
else
{
swprintf( pStr, TacticalStr[ MERC_VITAL_STATS_WITH_FOOD_POPUPTEXT ], pSoldier->stats.bLife, pSoldier->stats.bLifeMax, pSoldier->bBreath, pSoldier->bBreathMax, pMoraleStr, (INT32)(100*pSoldier->bDrinkLevel/FOOD_MAX), L"%", (INT32)(100*pSoldier->bFoodLevel/FOOD_MAX), L"%" );
}
}
else
{
swprintf( pStr, TacticalStr[ MERC_VITAL_STATS_POPUPTEXT ], pSoldier->stats.bLife, pSoldier->stats.bLifeMax, pSoldier->bBreath, pSoldier->bBreathMax, 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 );
}
+14 -6
View File
@@ -496,14 +496,22 @@ void DrawItemUIBarEx( OBJECTTYPE *pObject, UINT8 ubStatus, INT16 sXPos, INT16 sY
// Flugente FTW 1.2
if ( ubStatus == DRAW_ITEM_TEMPERATURE )
{
sValue = (INT16) (100 * GetGunOverheatJamPercentage( pObject) );
// the food item bar always has full size
if ( gGameOptions.fFoodSystem == TRUE && Item[pObject->usItem].foodtype > 0 )
{
sValue = 100;
}
else
{
sValue = (INT16) (100 * GetGunOverheatJamPercentage( pObject) );
// if temperature is 0 or below, do not display anything
if ( sValue < 1)
return;
// if temperature is 0 or below, do not display anything
if ( sValue < 1)
return;
// cut off temperature at 100%, otherwise the bar will be out of its box
sValue = min(sValue, 100);
// cut off temperature at 100%, otherwise the bar will be out of its box
sValue = min(sValue, 100);
}
}
// ATE: Subtract 1 to exagerate bad status
+8 -5
View File
@@ -221,7 +221,7 @@ typedef enum
#define GS_WEAPON_BEING_RELOADED 0x02
// Flugente: define for maximum temperature
#define OVERHEATING_MAX_TEMPERATURE 60000.0
#define OVERHEATING_MAX_TEMPERATURE 60000.0f
//forward declaration
class OBJECTTYPE;
@@ -717,10 +717,10 @@ extern OBJECTTYPE gTempObject;
#define SHOVEL 0x00000004 //4
#define CONCERTINA 0x00000008 //8
/*#define WH40K_POWER_ARMOR 0x00000010 //16
#define WH40K_POWER_PACK 0x00000020 //32
#define WH40K_JUMPPACK 0x00000040 //64
#define WH40K_DISPLACER 0x00000080 //128
#define WATER_DRUM 0x00000010 //16 // water drums allow to refill canteens in the sector they are in
#define MEAT_BLOODCAT 0x00000020 //32 // retrieve this by gutting a bloodcat
#define COW_MEAT 0x00000040 //64 // retrieve this by gutting a cow
/*#define WH40K_DISPLACER 0x00000080 //128
#define WH40K_ROSARIUS 0x00000100 //256
#define WH40K_SEAL 0x00000200 //512
@@ -1009,6 +1009,9 @@ typedef struct
UINT32 usItemFlag; // bitflags to store various item properties (better than introducing 32 BOOLEAN values). If I only had thought of this earlier....
// Flugente: food type
UINT32 foodtype;
} INVTYPE;
// CHRISL: Added new structures to handle LBE gear and the two new XML files that will be needed to deal
+16
View File
@@ -60,6 +60,7 @@
#include "popup_definition.h"
#include "drugs and alcohol.h"
#include "Food.h"
#endif
#ifdef JA2UB
@@ -1255,6 +1256,8 @@ std::map<UINT8,popupDef> LBEPocketPopup;
DRUGTYPE Drug[DRUG_TYPE_MAX];
FOODTYPE Food[FOOD_TYPE_MAX];
BOOLEAN ItemIsLegal( UINT16 usItemIndex, BOOLEAN fIgnoreCoolness )
{
if ( Item[usItemIndex].ubCoolness == 0 && !fIgnoreCoolness )
@@ -7117,6 +7120,13 @@ UINT16 UseKitPoints( OBJECTTYPE * pObj, UINT16 usPoints, SOLDIERTYPE *pSoldier )
(*pObj)[bLoop]->data.objectStatus -= (INT8)(usPoints * (max( 0, (100 - Item[pObj->usItem].percentstatusdrainreduction) ) )/100);
return( usOriginalPoints );
}
// Flugente: we no longer destroy canteens upon emtptying them - as we can now refill them
else if ( Item[pObj->usItem].canteen == TRUE )
{
// consume this kit totally
usPoints -= (((*pObj)[bLoop]->data.objectStatus - 1) / (max( 0, (100 - Item[pObj->usItem].percentstatusdrainreduction))) /100);
(*pObj)[bLoop]->data.objectStatus = 1;
}
else
{
// consume this kit totally
@@ -7597,6 +7607,12 @@ BOOLEAN CreateItem( UINT16 usItem, INT16 bStatus, OBJECTTYPE * pObj )
(*pObj)[0]->data.objectStatus = bStatus;
}
// Flugente: the temperature variable determines the quality of the food, begin with being fresh
if ( Item[usItem].foodtype > 0 )
{
(*pObj)[0]->data.bTemperature = OVERHEATING_MAX_TEMPERATURE;
}
//ADB ubWeight has been removed, see comments in OBJECTTYPE
//pObj->ubWeight = CalculateObjectWeight( pObj );
fRet = TRUE;
+15 -4
View File
@@ -26,6 +26,7 @@
// addedd by SANDRO
#include "GameSettings.h"
#include "Isometric Utils.h"
#include "Food.h"
#endif
#include "connect.h"
@@ -88,8 +89,11 @@ 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,
// added by Flugente
{ TACTICAL_MORALE_EVENT, 1}, //MORALE_FOOD,
{ TACTICAL_MORALE_EVENT, 5}, //MORALE_GOOD_FOOD,
{ TACTICAL_MORALE_EVENT, -1}, //MORALE_BAD_FOOD,
{ TACTICAL_MORALE_EVENT, -5}, //MORALE_LOATHSOME_FOOD,
};
BOOLEAN gfSomeoneSaidMoraleQuote = FALSE;
@@ -349,6 +353,10 @@ void RefreshSoldierMorale( SOLDIERTYPE * pSoldier )
}
}
// Flugente: ubMaxMorale can now be influenced by our food situation
if ( gGameOptions.fFoodSystem )
FoodMaxMoraleModifiy(pSoldier, &ubMaxMorale);
if (ubMaxMorale > 0 && iActualMorale > ubMaxMorale)
{
// Normalize to Max Morale
@@ -525,7 +533,7 @@ void UpdateSoldierMorale( SOLDIERTYPE * pSoldier, INT8 bMoraleEvent )
}
}
}
else if ( bMoraleMod != MORALE_PSYCHO_UNABLE_TO_PSYCHO && bMoraleMod != MORALE_KHORNATE_RANGED_COMBAT)
else if ( bMoraleMod != MORALE_PSYCHO_UNABLE_TO_PSYCHO )
{
switch( pProfile->bAttitude )
{
@@ -912,7 +920,10 @@ void HandleMoraleEvent( SOLDIERTYPE *pSoldier, INT8 bMoraleEvent, INT16 sMapX, I
break;
// added by Flugente
case MORALE_KHORNATE_RANGED_COMBAT:
case MORALE_FOOD:
case MORALE_GOOD_FOOD:
case MORALE_BAD_FOOD:
case MORALE_LOATHSOME_FOOD:
Assert( pSoldier );
HandleMoraleEventForSoldier( pSoldier, bMoraleEvent );
break;
+5 -1
View File
@@ -51,7 +51,11 @@ typedef enum
MORALE_MALICIOUS_HIT,
// added by Flugente
MORALE_KHORNATE_RANGED_COMBAT,
MORALE_FOOD,
MORALE_GOOD_FOOD,
MORALE_BAD_FOOD,
MORALE_LOATHSOME_FOOD,
NUM_MORALE_EVENTS
} MoraleEventNames;
+6
View File
@@ -36,6 +36,7 @@
#include "Soldier Control.h" // added by SANDRO
#include "opplist.h" // added by SANDRO
#include "lighting.h" // added by SANDRO
#include "Food.h" // added by Flugente
#endif
#include "connect.h"
//rain
@@ -795,6 +796,11 @@ void DeductPoints( SOLDIERTYPE *pSoldier, INT16 sAPCost, INT32 iBPCost, UINT8 ub
// NB: iBPCost > 0 - breath loss, iBPCost < 0 - breath gain
if (iBPCost)
{
// Flugente: if we GAIN breath points, adjust them - if we are hungry, we get fewer points back
// Flugente: ubMaxMorale can now be influenced by our food situation
if ( iBPCost < 0 && gGameOptions.fFoodSystem )
ReduceBPRegenForHunger(pSoldier, &iBPCost);
if (is_networked)
{
// Adjust breath changes due to spending or regaining of energy
+44 -25
View File
@@ -275,8 +275,8 @@ BOOLEAN gbCorpseValidForDecapitation[ NUM_CORPSES ] =
1,
1,
1,
0,
0,
1, // Bloodcat - changed to 1 to allow gutting
1, // Cow - changed to 1 to allow gutting
0,
0,
0,
@@ -1760,9 +1760,9 @@ INT32 FindNearestAvailableGridNoForCorpse( ROTTING_CORPSE_DEFINITION *pDef, INT8
BOOLEAN IsValidDecapitationCorpse( ROTTING_CORPSE *pCorpse )
{
if ( pCorpse->def.fHeadTaken )
if ( (pCorpse->def.usFlags & ROTTING_CORPSE_GUTTED) )
{
return( FALSE );
return( FALSE );
}
return( gbCorpseValidForDecapitation[ pCorpse->def.ubType ] );
@@ -1799,6 +1799,8 @@ void DecapitateCorpse( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel )
ROTTING_CORPSE *pCorpse;
ROTTING_CORPSE_DEFINITION CorpseDef;
UINT16 usHeadIndex = HEAD_1;
static UINT16 usBloodCatMeatIndex = 1566;
static UINT16 usCowMeatIndex = 1565;
pCorpse = GetCorpseAtGridNo( sGridNo, bLevel );
@@ -1814,10 +1816,27 @@ void DecapitateCorpse( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel )
// Copy corpse definition...
memcpy( &CorpseDef, &(pCorpse->def), sizeof( ROTTING_CORPSE_DEFINITION ) );
// Flugente: if the corpse is of a cow or a bloodcat, we don't take its head, we simply gut it and give meat instead of a head
if ( CorpseDef.ubType == BLOODCAT_DEAD || CorpseDef.ubType == COW_DEAD )
{
pCorpse->def.usFlags |= (ROTTING_CORPSE_HEAD_TAKEN|ROTTING_CORPSE_GUTTED);
if ( CorpseDef.ubType == BLOODCAT_DEAD )
{
if ( HasItemFlag(usBloodCatMeatIndex, MEAT_BLOODCAT) || GetFirstItemWithFlag(&usBloodCatMeatIndex, MEAT_BLOODCAT) )
usHeadIndex = usBloodCatMeatIndex;
}
else
{
if ( HasItemFlag(usCowMeatIndex, COW_MEAT) || GetFirstItemWithFlag(&usCowMeatIndex, COW_MEAT) )
usHeadIndex = usCowMeatIndex;
}
}
// Add new one...
CorpseDef.ubType = gDecapitatedCorpse[ CorpseDef.ubType ];
pCorpse->def.fHeadTaken = TRUE;
pCorpse->def.usFlags |= (ROTTING_CORPSE_HEAD_TAKEN|ROTTING_CORPSE_GUTTED);
if ( CorpseDef.ubType != 0 )
{
@@ -1858,11 +1877,14 @@ void DecapitateCorpse( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel )
}
CreateItem( usHeadIndex, 100, &gTempObject );
AddItemToPool( sGridNo, &gTempObject, INVISIBLE, 0, 0, 0 );
if ( usHeadIndex > 0 )
{
CreateItem( usHeadIndex, 100, &gTempObject );
AddItemToPool( sGridNo, &gTempObject, INVISIBLE, 0, 0, 0 );
// All teams lok for this...
NotifySoldiersToLookforItems( );
// All teams lok for this...
NotifySoldiersToLookforItems( );
}
}
}
@@ -2112,26 +2134,23 @@ UINT8 GetNearestRottingCorpseAIWarning( INT32 sGridNo )
// 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->fActivated && !(pCorpse->def.usFlags & (ROTTING_CORPSE_HEAD_TAKEN|ROTTING_CORPSE_NEVER_RISE_AGAIN) ) ) // ... if corpse is active, and still has a head and can rise again...
{
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 ( !TileIsOutOfBounds(pCorpse->def.sGridNo) ) // ... if corpse is on existing coordinates ...
{
if ( WhoIsThere2( pCorpse->def.sGridNo, pCorpse->def.bLevel ) == NOBODY ) // ... if nobody else is on that position ...
{
UINT16 recanimstate = STANDING;
if ( CorpseOkToSpawnZombie( pCorpse, &recanimstate ) ) // ... a zombie can be created from this corpse, in the corresponding animstate ...
{
zombieshaverisen = TRUE;
CreateZombiefromCorpse( pCorpse, recanimstate );
if ( CorpseOkToSpawnZombie( pCorpse, &recanimstate ) ) // ... a zombie can be created from this corpse, in the corresponding animstate ...
{
zombieshaverisen = TRUE;
CreateZombiefromCorpse( pCorpse, recanimstate );
//++pSector->ubNumZombies;
//++pSector->ubZombiesInBattle;
//++pSector->ubNumZombies;
//++pSector->ubZombiesInBattle;
RemoveCorpse( cnt );
}
RemoveCorpse( cnt );
}
}
}
+17 -14
View File
@@ -73,22 +73,25 @@ enum RottingCorpseDefines
#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_FIND_SWEETSPOT_FROM_GRIDNO 0x00000001 //Find the closest spot to the given gridno
#define ROTTING_CORPSE_USE_NORTH_ENTRY_POINT 0x00000002 //Find the spot closest to the north entry grid
#define ROTTING_CORPSE_USE_SOUTH_ENTRY_POINT 0x00000004 //Find the spot closest to the south entry grid
#define ROTTING_CORPSE_USE_EAST_ENTRY_POINT 0x00000008 //Find the spot closest to the east entry grid
#define ROTTING_CORPSE_USE_WEST_ENTRY_POINT 0x00000010 //Find the spot closest to the west entry grid
#define ROTTING_CORPSE_USE_CAMO_PALETTE 0x00000020 //We use cammo palette here....
#define ROTTING_CORPSE_VEHICLE 0x00000040 //Vehicle Corpse
#define ROTTING_CORPSE_USE_STEALTH_PALETTE 0x00000080 //We use stealth palette here....
#define ROTTING_CORPSE_USE_URBAN_CAMO_PALETTE 0x00000100 //We use urban palette here....
#define ROTTING_CORPSE_USE_DESERT_CAMO_PALETTE 0x00000200 //We use desert palette here....
#define ROTTING_CORPSE_USE_SNOW_CAMO_PALETTE 0x00000400 //We use snow palette here....
#ifdef ENABLE_ZOMBIES
#define ROTTING_CORPSE_NEVER_RISE_AGAIN 0x800 //a zombie cannot be created from this corpse (if not set, it'll eventually rise again )
#define ROTTING_CORPSE_NEVER_RISE_AGAIN 0x00000800 //a zombie cannot be created from this corpse (if not set, it'll eventually rise again )
#endif
// Flugente: corpses can now be gutted after they have been decapitated. Atm there is no corpse that can be both gutted and decapitated (to be done later)
#define ROTTING_CORPSE_HEAD_TAKEN 0x00001000 // head has been taken off
#define ROTTING_CORPSE_GUTTED 0x00001000 // corpse has been gutted
typedef struct
{
@@ -107,7 +110,7 @@ typedef struct
UINT8 ubDirection;
UINT32 uiTimeOfDeath;
UINT16 usFlags;
UINT32 usFlags;
INT8 bLevel;
@@ -117,7 +120,7 @@ typedef struct
BOOLEAN fHeadTaken;
UINT8 ubAIWarningValue;
UINT8 ubFiller[ 12 ];
UINT8 ubFiller[ 10 ]; // Flugente: 12 -> 10, because usFlags was cahnged from UINT16 to UINT32
#ifdef ENABLE_ZOMBIES
// Flugente: added name so we can display individual name if corpse gets resurrected...
+2
View File
@@ -18,6 +18,8 @@
#include "Soldier Control.h"
#endif
extern void ReducePointsForHunger( SOLDIERTYPE *pSoldier, UINT32 *pusPoints );
INT16 EffectiveStrength( SOLDIERTYPE *pSoldier, BOOLEAN fTrainer )
{
INT8 bBandaged;
+158 -3
View File
@@ -111,6 +111,7 @@
#include "Dialogue Control.h"
#include "IMP Skill Trait.h" // added by Flugente
#include "Food.h" // added by Flugente
//forward declarations of common classes to eliminate includes
class OBJECTTYPE;
@@ -1010,6 +1011,11 @@ SOLDIERTYPE& SOLDIERTYPE::operator=(const OLDSOLDIERTYPE_101& src)
this->bPoisonSum = 0;
this->bPoisonResistance = 0;
this->bPoisonAbsorption = 0;
this->bFoodLevel = 0;
this->bDrinkLevel = 0;
this->usStarveDamageHealth = 0;
this->usStarveDamageStrength = 0;
}
return *this;
}
@@ -13256,7 +13262,7 @@ void SOLDIERTYPE::SoldierInventoryCoolDown(void)
FLOAT cooldownfactor = GetItemCooldownFactor(pObj); // ... get cooldown factor ...
FLOAT newtemperature = max((FLOAT)0.0, temperature - cooldownfactor); // ... calculate new temperature ...
FLOAT newtemperature = max(0.0f, temperature - cooldownfactor); // ... calculate new temperature ...
(*pObj)[i]->data.bTemperature = newtemperature; // ... set new temperature
#if 0//def JA2TESTVERSION
@@ -13272,7 +13278,7 @@ void SOLDIERTYPE::SoldierInventoryCoolDown(void)
FLOAT cooldownfactor = GetItemCooldownFactor( &(*iter) ); // ... get cooldown factor ...
FLOAT newtemperature = max((FLOAT)0.0, temperature - cooldownfactor); // ... calculate new temperature ...
FLOAT newtemperature = max(0.0f, temperature - cooldownfactor); // ... calculate new temperature ...
(*iter)[i]->data.bTemperature = newtemperature; // ... set new temperature
#if 0//def JA2TESTVERSION
@@ -13289,7 +13295,7 @@ void SOLDIERTYPE::SoldierInventoryCoolDown(void)
}
}
// Flugente: determine if we can rest our weapon on something. This can only happen when STANDING/CROUCHED. As a result, we get superior handling modifiers (we apply the PRONE modfiers)
// Flugente: determine if we can rest our weapon on something. This ca6n only happen when STANDING/CROUCHED. As a result, we get superior handling modifiers (we apply the PRONE modfiers)
BOOLEAN SOLDIERTYPE::IsWeaponMounted( void )
{
BOOLEAN applybipod = FALSE;
@@ -13568,6 +13574,27 @@ INT16 SOLDIERTYPE::GetPoisonDamagePercentage( void )
return( val );
}
// add poison
void SOLDIERTYPE::AddPoison( INT8 sPoisonAmount )
{
if ( sPoisonAmount < 1 )
return;
INT8 oldpoisonsum = this->bPoisonSum;
this->bPoisonSum = min(this->bPoisonSum + sPoisonAmount, this->stats.bLifeMax);
// recalc really added poison
sPoisonAmount = max(0, this->bPoisonSum - oldpoisonsum);
INT8 oldpoisonlife = this->bPoisonLife;
this->bPoisonLife = min(this->bPoisonLife + sPoisonAmount, this->bPoisonSum);
INT8 poisontolife = max(0, this->bPoisonLife - oldpoisonlife);
INT8 oldpoisonbleed = this->bPoisonBleeding;
this->bPoisonBleeding = min(this->bPoisonBleeding + (sPoisonAmount - poisontolife), this->bPoisonSum);
}
// reset the extra stat variables
void SOLDIERTYPE::ResetExtraStats()
{
@@ -13642,6 +13669,33 @@ void SOLDIERTYPE::InventoryExplosion( void )
}
}
// Flugente: Food decay in inventory (once an hour)
void SOLDIERTYPE::SoldierInventoryFoodDecay(void)
{
if ( !gGameOptions.fFoodSystem )
return;
// one hour has 60 minutes, with 12 5-second-intervals (cooldown values are based on 5-second values)
FLOAT decaymod = 12*60*gGameExternalOptions.sFoodDecayModificator;
INT8 invsize = (INT8)this->inv.size(); // remember inventorysize, so we don't call size() repeatedly
for ( INT8 bLoop = 0; bLoop < invsize; ++bLoop) // ... for all items in our inventory ...
{
if ( Item[this->inv[bLoop].usItem].foodtype > 0 ) // food decays
{
OBJECTTYPE * pObj = &(this->inv[bLoop]); // ... get pointer for this item ...
if ( pObj != NULL ) // ... if pointer is not obviously useless ...
{
for(INT16 i = 0; i < pObj->ubNumberOfObjects; ++i) // ... there might be multiple items here (item stack), so for each one ...
{
(*pObj)[i]->data.bTemperature = max(0.0f, (*pObj)[i]->data.bTemperature - decaymod * Food[Item[pObj->usItem].foodtype].usDecayRate); // set new temperature
}
}
}
}
}
INT32 CheckBleeding( SOLDIERTYPE *pSoldier )
{
@@ -15742,6 +15796,11 @@ UINT16 NumberOfDamagedStats( SOLDIERTYPE * pSoldier )
if (pSoldier->ubCriticalStatDamage[cnt] > 0 )
ubTotalStatsDamaged += pSoldier->ubCriticalStatDamage[cnt];
}
// Flugente: stats can also be damaged
ubTotalStatsDamaged += pSoldier->usStarveDamageHealth;
ubTotalStatsDamaged += pSoldier->usStarveDamageStrength;
return( ubTotalStatsDamaged );
}
@@ -15874,6 +15933,102 @@ UINT8 RegainDamagedStats( SOLDIERTYPE * pSoldier, UINT16 usAmountRegainedHundred
}
}
// Flugente: Third, heal damage from starvation if possible
if ( !gGameOptions.fFoodSystem || ( gGameOptions.fFoodSystem && ubAmountRegained > 0 && pSoldier->bFoodLevel > FoodMoraleMods[FOOD_NORMAL].bThreshold && pSoldier->bDrinkLevel > FoodMoraleMods[FOOD_NORMAL].bThreshold ) )
{
// if we have a damaged stat here
if (pSoldier->usStarveDamageHealth > 0 )
{
if (ubAmountRegained >= pSoldier->usStarveDamageHealth)
{
// if the amount we can return is bigger than what we need, keep the rest, for other stats
usStatIncreasement = pSoldier->usStarveDamageHealth;
ubAmountRegained = max(0,(ubAmountRegained - usStatIncreasement));
pSoldier->usStarveDamageHealth = 0;
}
else
{
// if not having full amount, heal what we can
usStatIncreasement = ubAmountRegained;
ubAmountRegained = 0;
pSoldier->usStarveDamageHealth = max( 0, (pSoldier->usStarveDamageHealth - usStatIncreasement));
}
// so we can start regaining the stats
if ( usStatIncreasement > 0 )
{
bStatsReturned += usStatIncreasement; // keep value for feedback
sStat = sStatGainStrings[0]; // set string
pSoldier->stats.bLifeMax += usStatIncreasement;
pSoldier->stats.bLife += usStatIncreasement;
pSoldier->iHealableInjury -= (usStatIncreasement * 100); // don't forget the healable injury
if (pSoldier->iHealableInjury < 0)
pSoldier->iHealableInjury = 0;
if (pSoldier->stats.bLifeMax >= 100 || pSoldier->stats.bLife >= 100 ) // repair if going too far
{
pSoldier->stats.bLifeMax = 100;
pSoldier->stats.bLife = 100;
pSoldier->iHealableInjury = 0;
pSoldier->usStarveDamageHealth = 0;
}
gMercProfiles[ pSoldier->ubProfile ].bLifeMax = pSoldier->stats.bLifeMax; // update profile
// Throw a message if healed anything
if ( gSkillTraitValues.fDORepStShouldThrowMessage )
{
if ( usStatIncreasement == 1 )
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, New113Message[MSG113_REGAINED_ONE_POINTS_OF_STAT], pSoldier->name, sStat );
else
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, New113Message[MSG113_REGAINED_X_POINTS_OF_STATS], pSoldier->name, usStatIncreasement, sStat );
}
}
}
// if we have a damaged stat here
if (pSoldier->usStarveDamageStrength > 0 )
{
if (ubAmountRegained >= pSoldier->usStarveDamageStrength)
{
// if the amount we can return is bigger than what we need, keep the rest, for other stats
usStatIncreasement = pSoldier->usStarveDamageStrength;
ubAmountRegained = max(0,(ubAmountRegained - usStatIncreasement));
pSoldier->usStarveDamageStrength = 0;
}
else
{
// if not having full amount, heal what we can
usStatIncreasement = ubAmountRegained;
ubAmountRegained = 0;
pSoldier->usStarveDamageStrength = max( 0, (pSoldier->usStarveDamageStrength - usStatIncreasement));
}
// so we can start regaining the stats
if ( usStatIncreasement > 0 )
{
bStatsReturned += usStatIncreasement; // keep value for feedback
sStat = sStatGainStrings[9]; // set string
pSoldier->stats.bStrength += usStatIncreasement;
if (pSoldier->stats.bStrength >= 100 ) // repair if going too far
{
pSoldier->stats.bStrength = 100;
pSoldier->usStarveDamageStrength = 0;
}
gMercProfiles[ pSoldier->ubProfile ].bStrength = pSoldier->stats.bStrength; // update profile
// Throw a message if healed anything
if ( gSkillTraitValues.fDORepStShouldThrowMessage )
{
if ( usStatIncreasement == 1 )
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, New113Message[MSG113_REGAINED_ONE_POINTS_OF_STAT], pSoldier->name, sStat );
else
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, New113Message[MSG113_REGAINED_X_POINTS_OF_STATS], pSoldier->name, usStatIncreasement, sStat );
}
}
}
}
// Done, return what we healed
return( bStatsReturned );
}
+16
View File
@@ -21,6 +21,7 @@
#define PTR_PRONE (gAnimControl[ pSoldier->usAnimState ].ubHeight == ANIM_PRONE)
#define DRUG_TYPE_MAX 32
#define FOOD_TYPE_MAX 128
// TEMP VALUES FOR NAMES
#define MAXCIVLASTNAMES 30
@@ -1213,6 +1214,15 @@ public:
INT32 bSoldierFlagMask; // for various soldier-related flags (Illusion, Kill streak, etc.). Easier than adding 32 bool variables
// Flugente: food system
INT32 bFoodLevel; // current level of food saturation
INT32 bDrinkLevel; // current level of drink saturation
UINT8 usStarveDamageHealth; // damage to health due to starvation. Can be cured by surgery, but only if nutrition level is high enough again
UINT8 usStarveDamageStrength; // damage to strength due to starvation. Can be cured by surgery, but only if nutrition level is high enough again
// Flugente: Decrease this filler by 1 for each new UINT8 / BOOLEAN variable, so we can maintain savegame compatibility!!
UINT8 ubFiller[20];
#ifdef JA2UB
//ja25
@@ -1415,11 +1425,17 @@ public:
// returns the poison percentage of the damage we will be doing with the weapon currently in our hand
INT16 GetPoisonDamagePercentage( void );
// add poison
void AddPoison( INT8 sPoisonAmount );
// reset the extra stat variables
void ResetExtraStats();
// Flugente: inventory bombs can ignite while in mapscreen. Workaround: Damage items and health
void InventoryExplosion( void );
// Flugente: Food decay in inventory
void SoldierInventoryFoodDecay( void );
//////////////////////////////////////////////////////////////////////////////
}; // SOLDIERTYPE;
+16 -1
View File
@@ -122,6 +122,7 @@
#include "IMP Skill Trait.h" // added by Flugente
#include "Food.h" // added by Flugente
//forward declarations of common classes to eliminate includes
class OBJECTTYPE;
@@ -4456,11 +4457,25 @@ void GetKeyboardInput( UINT32 *puiNewEvent )
case '.':
if ( fCtrl )
{
SectorFillCanteens();
}
else if ( fAlt )
{
/*
// Flugente: spawn items while debugging
if ( gusSelectedSoldier != NOBODY )
{
static UINT16 usitem = 1560;
static INT16 status = 100;
static FLOAT temperature = 50000.0;
OBJECTTYPE newobj;
CreateItem( usitem, status, &newobj );
(newobj)[0]->data.bTemperature = temperature;
AddItemToPool( MercPtrs[ gusSelectedSoldier ]->sGridNo, &newobj, 1, 0, 0, -1 );
}*/
}
else
{
+3 -3
View File
@@ -11285,7 +11285,7 @@ void GunIncreaseHeat( OBJECTTYPE *pObj )
FLOAT singleshottemperature = GetSingleShotTemperature( pObj ); // ... get temperature rise ...
FLOAT newguntemperature = min(guntemperature + singleshottemperature, (FLOAT)(OVERHEATING_MAX_TEMPERATURE) ); // ... calculate new temperature ...
FLOAT newguntemperature = min(guntemperature + singleshottemperature, OVERHEATING_MAX_TEMPERATURE ); // ... calculate new temperature ...
(*pObj)[0]->data.bTemperature = newguntemperature; // ... apply new temperature
@@ -11353,7 +11353,7 @@ FLOAT GetGunOverheatJamPercentage( OBJECTTYPE * pObj )
FLOAT GetOverheatJamThreshold( OBJECTTYPE *pObj )
{
FLOAT jamthreshold = (FLOAT) (OVERHEATING_MAX_TEMPERATURE / 4.0);
FLOAT jamthreshold = OVERHEATING_MAX_TEMPERATURE / 4.0f;
if ( Item[pObj->usItem].usItemClass & (IC_GUN|IC_LAUNCHER) )
{
@@ -11379,7 +11379,7 @@ FLOAT GetOverheatJamThreshold( OBJECTTYPE *pObj )
FLOAT GetOverheatDamageThreshold( OBJECTTYPE *pObj )
{
FLOAT damagethreshold = (FLOAT) (OVERHEATING_MAX_TEMPERATURE / 4.0);
FLOAT damagethreshold = OVERHEATING_MAX_TEMPERATURE / 4.0f;
if ( Item[pObj->usItem].usItemClass & (IC_GUN|IC_LAUNCHER) )
{
+13
View File
@@ -28,6 +28,7 @@
#include "Quests.h"
#include "Soldier Profile.h"
#include "message.h"
#include "Food.h" // added by Flugente
#include "connect.h"
#endif
@@ -895,6 +896,18 @@ void CoolDownWorldItems( BOOLEAN fSetZero )
}
}
}
else if ( Item[gWorldItems[ uiCount ].object.usItem].foodtype > 0 ) // food decays
{
OBJECTTYPE* pObj = &(gWorldItems[ uiCount ].object); // ... get pointer for this item ...
if ( pObj != NULL ) // ... if pointer is not obviously useless ...
{
for(INT16 i = 0; i < pObj->ubNumberOfObjects; ++i) // ... there might be multiple items here (item stack), so for each one ...
{
(*pObj)[i]->data.bTemperature = max(0.0f, (*pObj)[i]->data.bTemperature - Food[Item[pObj->usItem].foodtype].usDecayRate); // set new temperature
}
}
}
}
}
}
+5
View File
@@ -66,6 +66,7 @@ typedef PARSE_STAGE;
#define ARMOURSFILENAME "Armours.xml"
#define EXPLOSIVESFILENAME "Explosives.xml"
#define DRUGSFILENAME "Drugs.xml"
#define FOODFILENAME "Food.xml"
#define AMMOFILENAME "AmmoStrings.xml"
#define AMMOTYPESFILENAME "AmmoTypes.xml"
#define INCOMPATIBLEATTACHMENTSFILENAME "IncompatibleAttachments.xml"
@@ -301,6 +302,10 @@ extern BOOLEAN WriteExplosiveStats();
extern BOOLEAN ReadInDrugsStats(STR fileName);
extern BOOLEAN WriteDrugsStats();
// Flugente: food
extern BOOLEAN ReadInFoodStats(STR fileName);
extern BOOLEAN WriteFoodStats();
extern BOOLEAN ReadInAmmoStats(STR fileName);
extern BOOLEAN WriteAmmoStats();
+245
View File
@@ -0,0 +1,245 @@
#ifdef PRECOMPILEDHEADERS
#include "Tactical All.h"
#else
#include "sgp.h"
#include "overhead.h"
#include "Food.h"
#include "Debug Control.h"
#include "expat.h"
#include "XML.h"
#endif
struct
{
PARSE_STAGE curElement;
CHAR8 szCharData[MAX_CHAR_DATA_LENGTH+1];
FOODTYPE curFood;
FOODTYPE * curArray;
UINT32 maxArraySize;
UINT32 currentDepth;
UINT32 maxReadDepth;
}
typedef foodParseData;
static void XMLCALL
foodStartElementHandle(void *userData, const XML_Char *name, const XML_Char **atts)
{
foodParseData * pData = (foodParseData *)userData;
if(pData->currentDepth <= pData->maxReadDepth) //are we reading this element?
{
if(strcmp(name, "FOODSLIST") == 0 && pData->curElement == ELEMENT_NONE)
{
pData->curElement = ELEMENT_LIST;
memset(pData->curArray,0,sizeof(FOODTYPE)*pData->maxArraySize);
pData->maxReadDepth++; //we are not skipping this element
}
else if(strcmp(name, "FOOD") == 0 && pData->curElement == ELEMENT_LIST)
{
pData->curElement = ELEMENT;
memset(&pData->curFood,0,sizeof(FOODTYPE));
pData->maxReadDepth++; //we are not skipping this element
}
else if(pData->curElement == ELEMENT &&
(strcmp(name, "uiIndex") == 0 ||
strcmp(name, "szName") == 0 ||
strcmp(name, "bFoodPoints") == 0 ||
strcmp(name, "bDrinkPoints") == 0 ||
strcmp(name, "ubPortionSize") == 0 ||
strcmp(name, "bMoraleMod") == 0 ||
strcmp(name, "usDecayRate") == 0 ))
{
pData->curElement = ELEMENT_PROPERTY;
pData->maxReadDepth++; //we are not skipping this element
}
pData->szCharData[0] = '\0';
}
pData->currentDepth++;
}
static void XMLCALL
foodCharacterDataHandle(void *userData, const XML_Char *str, int len)
{
foodParseData * pData = (foodParseData *)userData;
if( (pData->currentDepth <= pData->maxReadDepth) &&
(strlen(pData->szCharData) < MAX_CHAR_DATA_LENGTH)
){
strncat(pData->szCharData,str,__min((unsigned int)len,MAX_CHAR_DATA_LENGTH-strlen(pData->szCharData)));
}
}
static void XMLCALL
foodEndElementHandle(void *userData, const XML_Char *name)
{
foodParseData * pData = (foodParseData *)userData;
if(pData->currentDepth <= pData->maxReadDepth) //we're at the end of an element that we've been reading
{
if(strcmp(name, "FOODSLIST") == 0)
{
pData->curElement = ELEMENT_NONE;
}
else if(strcmp(name, "FOOD") == 0)
{
pData->curElement = ELEMENT_LIST;
// we do NOT want to read the first entry -> move stuff by 1
if(pData->curFood.uiIndex < pData->maxArraySize)
{
pData->curArray[pData->curFood.uiIndex] = pData->curFood; //write the food into the table
}
}
else if(strcmp(name, "uiIndex") == 0)
{
pData->curElement = ELEMENT;
pData->curFood.uiIndex = (UINT16) atol(pData->szCharData);
}
else if(strcmp(name, "szName") == 0)
{
pData->curElement = ELEMENT;
// not needed, but it's there for informational purposes
}
else if(strcmp(name, "bFoodPoints") == 0)
{
pData->curElement = ELEMENT;
pData->curFood.bFoodPoints = (INT32) atol(pData->szCharData);
}
else if(strcmp(name, "bDrinkPoints") == 0)
{
pData->curElement = ELEMENT;
pData->curFood.bDrinkPoints = (INT32) atol(pData->szCharData);
}
else if(strcmp(name, "ubPortionSize") == 0)
{
pData->curElement = ELEMENT;
pData->curFood.ubPortionSize = (UINT16) atol(pData->szCharData);
}
else if(strcmp(name, "bMoraleMod") == 0)
{
pData->curElement = ELEMENT;
pData->curFood.bMoraleMod = (UINT8) atol(pData->szCharData);
}
else if(strcmp(name, "usDecayRate") == 0)
{
pData->curElement = ELEMENT;
pData->curFood.usDecayRate = (FLOAT) atof(pData->szCharData);
}
pData->maxReadDepth--;
}
pData->currentDepth--;
}
BOOLEAN ReadInFoodStats(STR fileName)
{
HWFILE hFile;
UINT32 uiBytesRead;
UINT32 uiFSize;
CHAR8 * lpcBuffer;
XML_Parser parser = XML_ParserCreate(NULL);
foodParseData pData;
DebugMsg(TOPIC_JA2, DBG_LEVEL_3, "Loading Food.xml" );
// Open foods file
hFile = FileOpen( fileName, FILE_ACCESS_READ, FALSE );
if ( !hFile )
return( FALSE );
uiFSize = FileGetSize(hFile);
lpcBuffer = (CHAR8 *) MemAlloc(uiFSize+1);
//Read in block
if ( !FileRead( hFile, lpcBuffer, uiFSize, &uiBytesRead ) )
{
MemFree(lpcBuffer);
return( FALSE );
}
lpcBuffer[uiFSize] = 0; //add a null terminator
FileClose( hFile );
XML_SetElementHandler(parser, foodStartElementHandle, foodEndElementHandle);
XML_SetCharacterDataHandler(parser, foodCharacterDataHandle);
memset(&pData,0,sizeof(pData));
pData.curArray = Food;
pData.maxArraySize = FOOD_TYPE_MAX;
XML_SetUserData(parser, &pData);
if(!XML_Parse(parser, lpcBuffer, uiFSize, TRUE))
{
CHAR8 errorBuf[511];
sprintf(errorBuf, "XML Parser Error in Food.xml: %s at line %d", XML_ErrorString(XML_GetErrorCode(parser)), XML_GetCurrentLineNumber(parser));
LiveMessage(errorBuf);
MemFree(lpcBuffer);
return FALSE;
}
MemFree(lpcBuffer);
XML_ParserFree(parser);
return( TRUE );
}
BOOLEAN WriteFoodStats()
{
//DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"writefoodsstats");
HWFILE hFile;
//Debug code; make sure that what we got from the file is the same as what's there
// Open a new file
hFile = FileOpen( "TABLEDATA\\Food out.xml", FILE_ACCESS_WRITE | FILE_CREATE_ALWAYS, FALSE );
if ( !hFile )
return( FALSE );
{
UINT32 cnt;
FilePrintf(hFile,"<FOODSLIST>\r\n");
for(cnt = 0; cnt < MAXITEMS; ++cnt)
{
FilePrintf(hFile,"\t<FOOD>\r\n");
FilePrintf(hFile,"\t\t<uiIndex>%d</uiIndex>\r\n", cnt );
FilePrintf(hFile,"\t\t<bFoodPoints>%d</bFoodPoints>\r\n", Food[cnt].bFoodPoints );
FilePrintf(hFile,"\t\t<bDrinkPoints>%d</bDrinkPoints>\r\n", Food[cnt].bDrinkPoints );
FilePrintf(hFile,"\t\t<ubPortionSize>%d</ubPortionSize>\r\n", Food[cnt].ubPortionSize );
FilePrintf(hFile,"\t\t<bMoraleMod>%d</bMoraleMod>\r\n", Food[cnt].bMoraleMod );
FilePrintf(hFile,"\t\t<usDecayRate>%4.2f</usDecayRate>\r\n", Food[cnt].usDecayRate );
FilePrintf(hFile,"\t</FOOD>\r\n");
}
FilePrintf(hFile,"</FOODSLIST>\r\n");
}
FileClose( hFile );
return( TRUE );
}
+9 -3
View File
@@ -612,9 +612,12 @@ extern STR16 gzItemDescGenIndexes[ 4 ];
// HEADROCK HAM 4: Added list of condition strings
extern STR16 gConditionDesc[ 9 ];
// Flugente FTW1: Added list of temperature descriptions
// Flugente: Added list of temperature descriptions
extern STR16 gTemperatureDesc[ 11 ];
// Flugente: Added list of food condition descriptions
extern STR16 gFoodDesc[ 8 ];
extern CHAR16 gMoneyStatsDesc[][ 14 ];
// HEADROCK: Altered value to 16 //WarmSteel - And I need 17.
extern CHAR16 gWeaponStatsDesc[][ 17 ];
@@ -636,8 +639,8 @@ extern STR16 szUDBGenAmmoStatsTooltipText[ 5 ]; // Flugente Overheating: 3
extern STR16 szUDBGenAmmoStatsExplanationsTooltipText[ 5 ]; // Flugente Overheating: 3->4 poison: 4->5
extern STR16 szUDBGenExplosiveStatsTooltipText[ 22 ];
extern STR16 szUDBGenExplosiveStatsExplanationsTooltipText[ 22 ];
extern STR16 szUDBGenSecondaryStatsTooltipText[ 26 ];
extern STR16 szUDBGenSecondaryStatsExplanationsTooltipText[ 26 ];
extern STR16 szUDBGenSecondaryStatsTooltipText[ 28 ]; // Flugente Food System: 26 -> 28
extern STR16 szUDBGenSecondaryStatsExplanationsTooltipText[ 28 ]; // Flugente Food System: 26 -> 28
extern STR16 szUDBAdvStatsTooltipText[ 57 ]; // Flugente Overheating Weapons: 48->56 poison: 56->57
extern STR16 szUDBAdvStatsExplanationsTooltipText[ 57 ]; // Flugente Overheating Weapons: 48->56 poison: 56->57
extern STR16 szUDBAdvStatsExplanationsTooltipTextForWeapons[ 52 ]; // Flugente Overheating Weapons: 48->52
@@ -811,6 +814,8 @@ enum
CHOOSE_TRIPWIRE_NETWORK,
MERC_VITAL_STATS_WITH_POISON_POPUPTEXT,
MERC_VITAL_STATS_WITH_FOOD_POPUPTEXT,
MERC_VITAL_STATS_WITH_POISON_AND_FOOD_POPUPTEXT,
TEXT_NUM_TACTICAL_STR
};
@@ -1785,6 +1790,7 @@ enum
GIO_NCTH_TITLE_TEXT,
GIO_IIS_TITLE_TEXT,
GIO_OVERHEATING_TITLE_TEXT,
GIO_FOODSYSTEM_TITLE_TEXT,
GIO_BR_QUANTITY_TEXT,
////////////////////////////////////
+8
View File
@@ -267,6 +267,7 @@ itemStartElementHandle(void *userData, const XML_Char *name, const XML_Char **at
strcmp(name, "BlockIronSight") == 0 ||
strcmp(name, "PoisonPercentage") == 0 ||
strcmp(name, "ItemFlag") == 0 ||
strcmp(name, "FoodType") == 0 ||
strcmp(name, "fFlags") == 0 ))
{
@@ -1343,6 +1344,11 @@ itemEndElementHandle(void *userData, const XML_Char *name)
pData->curElement = ELEMENT;
pData->curItem.usItemFlag = (UINT32) atol(pData->szCharData);
}
else if(strcmp(name, "FoodType") == 0)
{
pData->curElement = ELEMENT;
pData->curItem.foodtype = (UINT32) atol(pData->szCharData);
}
pData->maxReadDepth--;
@@ -1960,6 +1966,8 @@ BOOLEAN WriteItemStats()
FilePrintf(hFile,"\t\t<BlockIronSight>%d</BlockIronSight>\r\n", Item[cnt].blockironsight );
FilePrintf(hFile,"\t\t<ItemFlag>%d</ItemFlag>\r\n", Item[cnt].usItemFlag );
FilePrintf(hFile,"\t\t<FoodType>%d</FoodType>\r\n", Item[cnt].foodtype );
// Flugente poison system
FilePrintf(hFile,"\t\t<PoisonPercentage>%d</PoisonPercentage>\r\n", Item[cnt].bPoisonPercentage );
+29 -1
View File
@@ -1638,6 +1638,7 @@ STR16 pAssignmentStrings[] =
L"教练", // training a teammate
L"学员", // being trained by someone else
L"工作", // L"Staff", // operating a strategic facility //ham3.6
L"Eat", // eating at a facility (cantina etc.) // TODO. Translate
L"休息", //L"Rest",// Resting at a facility //ham3.6
L"死亡", // dead
L"无力中", // abbreviation for incapacitated
@@ -1722,6 +1723,7 @@ STR16 pPersonnelAssignmentStrings[] =
L"教练",
L"学员",
L"设施职员",
L"Eat", // eating at a facility (cantina etc.) // TODO. Translate
L"在设施里休养",
L"休息",
L"无力中",
@@ -2926,6 +2928,10 @@ CHAR16 TacticalStr[][ MED_STRING_LENGTH ] =
// added by Flugente to display health and poisoning // TODO.Translate
L"Health: %d/%d\n Poison: %d/%d\nEnergy: %d/%d\nMorale: %s",
// added by Flugente to display food status
L"Health: %d/%d\nEnergy: %d/%d\nMorale: %s\nWater: %d%s\nFood: %d%s",
L"Health: %d/%d\n Poison: %d/%d\nEnergy: %d/%d\nMorale: %s\nWater: %d%s\nFood: %d%s",
};
//Varying helptext explains (for the "Go to Sector/Map" checkbox) what will happen given different circumstances in the "exiting sector" interface.
@@ -3480,6 +3486,8 @@ STR16 pMapScreenStatusStrings[] =
L"状态", // the condition of the current vehicle (its "health")
L"油量", // the fuel level of the current vehicle (its "energy")
L"Posion", // TODO.Translate
L"Water", // drink level
L"Food", // food level
};
@@ -5337,6 +5345,7 @@ STR16 gzGIOScreenText[] =
L"新命中率系统(NCTH", //L"New Chance to Hit System",
L"改进的中断系统(IIS", //L"Improved Interrupt System",
L"武器过热", //L"Weapon Overheating",
L"Food System",//TODO.Translate
L"Bobby Ray Quantity",//TODO.Translate
};
@@ -6663,6 +6672,7 @@ STR16 gzFacilityAssignmentStrings[]=
{
L"环境",
L"工作人员",
L"Eat",// TODO. Translate
L"休息",
L"修理物品",
L"修理%s", // Vehicle name inserted here
@@ -7041,6 +7051,8 @@ STR16 szUDBGenSecondaryStatsTooltipText[]=
L"|急|救|包",
L"|医|药|箱",
L"|破|锁|炸|弹",
L"|D|r|i|n|k",// TODO. Translate
L"|M|e|a|l",
};
STR16 szUDBGenSecondaryStatsExplanationsTooltipText[]=
@@ -7071,6 +7083,8 @@ STR16 szUDBGenSecondaryStatsExplanationsTooltipText[]=
L"\n \n这一战场的基础急救包提供了基本的医疗用品。\n \n可以被用来包扎受伤的角色以止血。\n \n如需要回复生命,使用名副其实的医药箱,并辅以大量的休息。",
L"\n \n这是名副其实的医药箱,可以用于外科手术或其他复杂的治疗。\n \n安排佣兵进行医疗工作时,该佣兵必须持有医\n药箱。",
L"\n \n该物品能够用于爆破锁具。\n \n使用它需要爆破技能以避免过早引爆。\n \n使用炸药是一个相对简单的破锁手段,但是会\n发出很大噪音,并且对于大部分佣兵来说过于\n危险。",
L"\n \nThis item will still your thirst\nif you drink it.",// TODO. Translate
L"\n \nThis item will still your hunger\nif you eat it.",
};
STR16 szUDBAdvStatsTooltipText[]=
@@ -7286,7 +7300,7 @@ STR16 gzMapInventoryFilterOptions[] =
L"Hide all",
};
// Flugente FTW 1: Temperature-based text similar to HAM 4's condition-based text.
// Flugente: Temperature-based text similar to HAM 4's condition-based text.
STR16 gTemperatureDesc[] =
{
L"当前温度为: ",
@@ -7302,6 +7316,20 @@ STR16 gTemperatureDesc[] =
L"."
};
// TODO.Translate
// Flugente: food condition texts
STR16 gFoodDesc[] =
{
L"Food is ",
L"fresh",
L"good",
L"ok",
L"stale",
L"shabby",
L"rotting",
L"."
};
CHAR16* ranks[] =
{ L"", //ExpLevel 0
L"列兵 ", //L"Pvt. ", //ExpLevel 1
+28 -1
View File
@@ -1634,6 +1634,7 @@ STR16 pAssignmentStrings[] =
L"Trainer", // training a teammate
L"Student", // being trained by someone else
L"Staff", // operating a strategic facility // TODO.Translate
L"Eat", // eating at a facility (cantina etc.) // TODO. Translate
L"Rest", // Resting at a facility // TODO.Translate
L"Dood", // dead
L"Uitgesc.", // abbreviation for incapacitated
@@ -1718,6 +1719,7 @@ STR16 pPersonnelAssignmentStrings[] =
L"Trainer", // training a teammate
L"Student", // being trained by someone else
L"Facility Staff", // TODO.Translate
L"Eat", // eating at a facility (cantina etc.) // TODO. Translate
L"Resting at Facility", // TODO.Translate
L"Dood", // dead
L"Uitgesc.", // abbreviation for incapacitated
@@ -2923,6 +2925,10 @@ CHAR16 TacticalStr[][ MED_STRING_LENGTH ] =
// added by Flugente to display health and poisoning // TODO.Translate
L"Health: %d/%d\n Poison: %d/%d\nEnergy: %d/%d\nMorale: %s",
// added by Flugente to display food status
L"Health: %d/%d\nEnergy: %d/%d\nMorale: %s\nWater: %d%s\nFood: %d%s",
L"Health: %d/%d\n Poison: %d/%d\nEnergy: %d/%d\nMorale: %s\nWater: %d%s\nFood: %d%s",
};
//Varying helptext explains (for the "Go to Sector/Map" checkbox) what will happen given different circumstances in the "exiting sector" interface.
@@ -3476,6 +3482,8 @@ STR16 pMapScreenStatusStrings[] =
L"Conditie", // the condition of the current vehicle (its "health")
L"Brandstof", // the fuel level of the current vehicle (its "energy")
L"Posion", // TODO.Translate
L"Water", // drink level
L"Food", // food level
};
@@ -5339,6 +5347,7 @@ STR16 gzGIOScreenText[] =
L"New Chance to Hit System",
L"Improved Interrupt System",
L"Weapon Overheating",
L"Food System",//TODO.Translate
L"Bobby Ray Quantity",//TODO.Translate
};
@@ -6658,6 +6667,7 @@ STR16 gzFacilityAssignmentStrings[]=
{
L"AMBIENT",
L"Staff",
L"Eat",// TODO. Translate
L"Rest",
L"Repair Items",
L"Repair %s", // Vehicle name inserted here
@@ -7036,6 +7046,8 @@ STR16 szUDBGenSecondaryStatsTooltipText[]=
L"|F|i|r|s|t |A|i|d |K|i|t",
L"|M|e|d|i|c|a|l |K|i|t",
L"|L|o|c|k |B|o|m|b",
L"|D|r|i|n|k",// TODO. Translate
L"|M|e|a|l",
};
STR16 szUDBGenSecondaryStatsExplanationsTooltipText[]=
@@ -7066,6 +7078,8 @@ STR16 szUDBGenSecondaryStatsExplanationsTooltipText[]=
L"\n \nThis is a basic field medical kit, containing\nitems required to provide basic medical aid.\n \nIt can be used to bandage wounded characters\nand prevent bleeding.\n \nFor actual healing, use a proper Medical Kit\nand/or plenty of rest.",
L"\n \nThis is a proper medical kit, which can\nbe used in surgery and other serious medicinal\npurposes.\n \nMedical Kits are always required when setting\na character to Doctoring duty.",
L"\n \nThis item can be used to blast open locked\ndoors and containers.\n \nExplosives skill is required to avoid\npremature detonation.\n \nBlowing locks is a relatively easy way of quickly\ngetting through locked doors. However,\nit is very loud, and dangerous to most characters.",
L"\n \nThis item will still your thirst\nif you drink it.",// TODO. Translate
L"\n \nThis item will still your hunger\nif you eat it.",
};
STR16 szUDBAdvStatsTooltipText[]=
@@ -7281,7 +7295,7 @@ STR16 gzMapInventoryFilterOptions[] =
L"Hide all",
};
// Flugente FTW 1: Temperature-based text similar to HAM 4's condition-based text.
// Flugente: Temperature-based text similar to HAM 4's condition-based text.
STR16 gTemperatureDesc[] = // TODO.Translate
{
L"Temperature is ",
@@ -7297,6 +7311,19 @@ STR16 gTemperatureDesc[] = // TODO.Translate
L"."
};
// TODO.Translate
// Flugente: food condition texts
STR16 gFoodDesc[] =
{
L"Food is ",
L"fresh",
L"good",
L"ok",
L"stale",
L"shabby",
L"rotting",
L"."
};
// TODO.Translate
CHAR16* ranks[] =
+30 -3
View File
@@ -1638,12 +1638,13 @@ STR16 pAssignmentStrings[] =
L"Trainer", // training a teammate
L"Student", // being trained by someone else
L"Staff", // operating a strategic facility
L"Eat", // eating at a facility (cantina etc.)
L"Rest", // Resting at a facility
L"Dead", // dead
L"Incap.", // abbreviation for incapacitated
L"POW", // Prisoner of war - captured
L"Hospital", // patient in a hospital
L"Empty", // Vehicle is empty
L"Hospital", // patient in a hospital
L"Empty", // Vehicle is empty
};
@@ -1722,6 +1723,7 @@ STR16 pPersonnelAssignmentStrings[] =
L"Trainer",
L"Student",
L"Facility Staff", // Missing
L"Eat", // eating at a facility (cantina etc.)
L"Resting at Facility", // Missing
L"Dead",
L"Incap.",
@@ -2926,6 +2928,10 @@ CHAR16 TacticalStr[][ MED_STRING_LENGTH ] =
// added by Flugente to display health and poisoning
L"Health: %d/%d\n Poison: %d/%d\nEnergy: %d/%d\nMorale: %s",
// added by Flugente to display food status
L"Health: %d/%d\nEnergy: %d/%d\nMorale: %s\nWater: %d%s\nFood: %d%s",
L"Health: %d/%d\n Poison: %d/%d\nEnergy: %d/%d\nMorale: %s\nWater: %d%s\nFood: %d%s",
};
//Varying helptext explains (for the "Go to Sector/Map" checkbox) what will happen given different circumstances in the "exiting sector" interface.
@@ -3478,6 +3484,8 @@ STR16 pMapScreenStatusStrings[] =
L"Condition", // the condition of the current vehicle (its "health")
L"Fuel", // the fuel level of the current vehicle (its "energy")
L"Poison", // for display of poisoning
L"Water", // drink level
L"Food", // food level
};
@@ -5335,6 +5343,7 @@ STR16 gzGIOScreenText[] =
L"New Chance to Hit System",
L"Improved Interrupt System",
L"Weapon Overheating",
L"Food System",
L"Bobby Ray Quantity",
};
@@ -6649,6 +6658,7 @@ STR16 gzFacilityAssignmentStrings[]=
{
L"AMBIENT",
L"Staff",
L"Eat",
L"Rest",
L"Repair Items",
L"Repair %s", // Vehicle name inserted here
@@ -7028,6 +7038,8 @@ STR16 szUDBGenSecondaryStatsTooltipText[]=
L"|F|i|r|s|t |A|i|d |K|i|t",
L"|M|e|d|i|c|a|l |K|i|t",
L"|L|o|c|k |B|o|m|b",
L"|D|r|i|n|k",
L"|M|e|a|l",
};
STR16 szUDBGenSecondaryStatsExplanationsTooltipText[]=
@@ -7058,6 +7070,8 @@ STR16 szUDBGenSecondaryStatsExplanationsTooltipText[]=
L"\n \nThis is a basic field medical kit, containing\nitems required to provide basic medical aid.\n \nIt can be used to bandage wounded characters\nand prevent bleeding.\n \nFor actual healing, use a proper Medical Kit\nand/or plenty of rest.",
L"\n \nThis is a proper medical kit, which can\nbe used in surgery and other serious medicinal\npurposes.\n \nMedical Kits are always required when setting\na character to Doctoring duty.",
L"\n \nThis item can be used to blast open locked\ndoors and containers.\n \nExplosives skill is required to avoid\npremature detonation.\n \nBlowing locks is a relatively easy way of quickly\ngetting through locked doors. However,\nit is very loud, and dangerous to most characters.",
L"\n \nThis item will still your thirst\nif you drink it.",
L"\n \nThis item will still your hunger\nif you eat it.",
};
STR16 szUDBAdvStatsTooltipText[]=
@@ -7272,7 +7286,7 @@ STR16 gzMapInventoryFilterOptions[] =
L"Hide all",
};
// Flugente FTW 1: Temperature-based text similar to HAM 4's condition-based text.
// Flugente: Temperature-based text similar to HAM 4's condition-based text.
STR16 gTemperatureDesc[] =
{
L"Temperature is ",
@@ -7288,6 +7302,19 @@ STR16 gTemperatureDesc[] =
L"."
};
// Flugente: food condition texts
STR16 gFoodDesc[] =
{
L"Food is ",
L"fresh",
L"good",
L"ok",
L"stale",
L"shabby",
L"rotting",
L"."
};
CHAR16* ranks[] =
{ L"", //ExpLevel 0
L"Pvt. ", //ExpLevel 1
+30 -2
View File
@@ -1637,6 +1637,7 @@ STR16 pAssignmentStrings[] =
L"Entraîneur", // training a teammate
L"Elève", // being trained by someone else
L"Exploitation", // operating a strategic facility
L"Eat", // eating at a facility (cantina etc.) // TODO. Translate
L"Repos", // Resting at a facility
L"Mort(e)", // dead
L"Incap.", // abbreviation for incapacitated
@@ -1721,6 +1722,7 @@ STR16 pPersonnelAssignmentStrings[] =
L"Entraîneur",
L"Elève",
L"Exploitation infras.",
L"Eat", // eating at a facility (cantina etc.) // TODO. Translate
L"Repos infras.",
L"Mort(e)",
L"Incap.",
@@ -2925,6 +2927,10 @@ CHAR16 TacticalStr[][ MED_STRING_LENGTH ] =
// added by Flugente to display health and poisoning // TODO.Translate
L"Health: %d/%d\n Poison: %d/%d\nEnergy: %d/%d\nMorale: %s",
// added by Flugente to display food status
L"Health: %d/%d\nEnergy: %d/%d\nMorale: %s\nWater: %d%s\nFood: %d%s",
L"Health: %d/%d\n Poison: %d/%d\nEnergy: %d/%d\nMorale: %s\nWater: %d%s\nFood: %d%s",
};
//Varying helptext explains (for the "Go to Sector/Map" checkbox) what will happen given different circumstances in the "exiting sector" interface.
@@ -3479,7 +3485,9 @@ STR16 pMapScreenStatusStrings[] =
L"Moral",
L"Etat", // the condition of the current vehicle (its "Santé")
L"Carburant", // the fuel level of the current vehicle (its "energy")
L"Posion", // TODO.Translate
L"Poison", // TODO.Translate
L"Water", // drink level
L"Food", // food level
};
@@ -5327,6 +5335,7 @@ STR16 gzGIOScreenText[] =
L"New Chance to Hit System",
L"Improved Interrupt System",
L"Weapon Overheating",
L"Food System",//TODO.Translate
L"Quantité de Bobby Ray",//TODO.Translate
};
@@ -6635,6 +6644,7 @@ STR16 gzFacilityAssignmentStrings[]=
{
L"AMBIENT",
L"Equipe",
L"Eat",// TODO. Translate
L"Reste",
L"Réparer les objets",
L"Réparer %s", // Vehicle name inserted here
@@ -7011,6 +7021,8 @@ STR16 szUDBGenSecondaryStatsTooltipText[]=
L"|T|r|o|u|s|s|e |d|e |1|e|r |s|o|i|n|s",
L"|T|r|o|u|s|s|e |d|e |s|o|i|n|s",
L"|B|o|m|b|e |p|o|u|r |s|e|r|r|u|r|e |d|e |p|o|r|t|e",
L"|D|r|i|n|k",// TODO. Translate
L"|M|e|a|l",
};
STR16 szUDBGenSecondaryStatsExplanationsTooltipText[]=
@@ -7041,6 +7053,8 @@ STR16 szUDBGenSecondaryStatsExplanationsTooltipText[]=
L"\n \nIl s'agit d'un kit médical basic, contenant les ustensibles\nrequis pour faire une intervention médicale basic.\n \nIl peut être utilisé pour soigner un mercenaire blessé et\nempêcher le saignement.\n \nPour une guérison optimale, utlisez une véritable trousse\nde soins et/ou beaucoup de repos.",
L"\n \nIl s'agit d'un kit médicale complet, qui peut être utilisé\npour une opération chirurgicale ou autre cas sérieux.\n \nUne trousse de soins est toujours nécessaire lorsque vous\nêtes en mission de Docteur.",
L"\n \nCet objet peut être utilisé pour faire sauter les portes\nou containeurs vérouillés.\n \nDes compétences en explosion sont nécessaire pour éviter\nune explosion prématurée.\n \nExploser les serrures est relativement facile et rapide\nà faire. Cependant, c'est très bruyant et dangereux pour\nla plupart des mercernaires.",
L"\n \nThis item will still your thirst\nif you drink it.",// TODO. Translate
L"\n \nThis item will still your hunger\nif you eat it.",
};
STR16 szUDBAdvStatsTooltipText[]=
@@ -7256,7 +7270,7 @@ STR16 gzMapInventoryFilterOptions[] =
L"Hide all",
};
// Flugente FTW 1: Temperature-based text similar to HAM 4's condition-based text.
// Flugente: Temperature-based text similar to HAM 4's condition-based text.
STR16 gTemperatureDesc[] = // TODO.Translate
{
L"Temperature is ",
@@ -7272,6 +7286,20 @@ STR16 gTemperatureDesc[] = // TODO.Translate
L"."
};
// TODO.Translate
// Flugente: food condition texts
STR16 gFoodDesc[] =
{
L"Food is ",
L"fresh",
L"good",
L"ok",
L"stale",
L"shabby",
L"rotting",
L"."
};
// TODO.Translate
CHAR16* ranks[] =
{ L"", //ExpLevel 0
+28 -1
View File
@@ -1647,6 +1647,7 @@ STR16 pAssignmentStrings[] =
L"Trainer", // training a teammate
L"Rekrut", // being trained by someone else
L"Betrieb", // operating a strategic facility
L"Essen", // eating at a facility (cantina etc.)
L"Pause", // Resting at a facility
L"Tot", // dead
L"Koma", // abbreviation for incapacitated //LOOTF - "Unfähig" klingt schlimm. Geändert auf Koma. Vorschläge?
@@ -1727,6 +1728,7 @@ STR16 pPersonnelAssignmentStrings[] =
L"Trainer",
L"Rekrut",
L"Betriebspersonal",
L"Essen", // eating at a facility (cantina etc.)
L"Betriebspause",
L"Tot",
L"Koma", //LOOTF - s.o.
@@ -2929,6 +2931,10 @@ CHAR16 TacticalStr[][ MED_STRING_LENGTH ] =
// added by Flugente to display health and poisoning
L"Gesundheit: %d/%d\n Gift: %d/%d\Ausdauer: %d/%d\Moral: %s",
// added by Flugente to display food status
L"Gesundheit: %d/%d\Ausdauer: %d/%d\Moral: %s\nWasser: %d%s\nEssen: %d%s",
L"Gesundheit: %d/%d\n Gift: %d/%d\Ausdauer: %d/%d\Moral: %s\nWasser: %d%s\nEssen: %d%s",
};
//Varying helptext explains (for the "Go to Sector/Map" checkbox) what will happen given different circumstances in the "exiting sector" interface.
@@ -3447,6 +3453,8 @@ STR16 pMapScreenStatusStrings[] =
L"Zustand", // the condition of the current vehicle (its "health")
L"Tank", // the fuel level of the current vehicle (its "energy")
L"Gift",
L"Wasser", // drink level
L"Essen", // food level
};
STR16 pMapScreenPrevNextCharButtonHelpText[] =
@@ -5182,6 +5190,7 @@ STR16 gzGIOScreenText[] =
L"Neues Zielsystem",
L"Verbesserte Unterbrechungen",
L"Waffen-Überhitzung",
L"Nahrungssystem",
L"Bobby Ray Auswahl",
};
@@ -6478,6 +6487,7 @@ STR16 gzFacilityAssignmentStrings[]=
L"UMGEBUNG",
L"Betrieb",
L"Essen",
L"Pause",
L"Repariere Gegenstände",
L"Repariere %s",
@@ -6856,6 +6866,8 @@ STR16 szUDBGenSecondaryStatsTooltipText[]=
L"|E|r|s|t|e|-|H|i|l|f|e|-|K|a|s|t|e|n",
L"|A|r|z|t|t|a|s|c|h|e",
L"|T|ü|r|s|p|r|e|n|g|s|a|t|z",
L"|W|a|s|s|e|r",
L"|N|a|h|r|u|n|g",
};
STR16 szUDBGenSecondaryStatsExplanationsTooltipText[]=
@@ -6886,6 +6898,8 @@ STR16 szUDBGenSecondaryStatsExplanationsTooltipText[]=
L"\n \nDas ist ein Erste-Hilfe-Kasten der\nGegenstände enthält die einfache medizinische Hilfe bieten.\n \nEr kann dazu benutzt werden verwundetet Personen zu bandagieren\nund Blutungen zu stoppen.\n \nFür richtige Heilung, benutze eine Arzttasche\nund/oder reichlich Ruhe.",
L"\n \nDas ist eine Arzttasche, die für\nOperationen und andere gravierende medizinische\nZwecke genutzt werden kann.\n \nEine Arzttasche wird dazu benötigt\neinem Söldner die Aufgabe Doktor zu geben.",
L"\n \nDieser Gegenstand kann dazu benutzt werden verschlossene\nTüren/Behälter zu sprengen.\n \nExplosionsfertigkeit ist erforderlich um\nvorzeitige Detonationen zu vermeiden.\n \nSchlösser zu sprengen ist der einfache Weg um schnell\ndurch verschlossene Türen/Behälter zu kommen. Wie auch immer,\nes ist Laut und für die meisten Personen gefährlich.",
L"\n \nMan kann das trinken.",
L"\n \nMan kann das essen.",
};
STR16 szUDBAdvStatsTooltipText[]=
@@ -7100,7 +7114,7 @@ STR16 gzMapInventoryFilterOptions[] =
L"Alle ausblenden",
};
// Flugente FTW 1: Temperature-based text similar to HAM 4's condition-based text.
// Flugente: Temperature-based text similar to HAM 4's condition-based text.
STR16 gTemperatureDesc[] =
{
L"Temperatur ist ",
@@ -7116,6 +7130,19 @@ STR16 gTemperatureDesc[] =
L"."
};
// Flugente: food condition texts
STR16 gFoodDesc[] =
{
L"Nahrung ist ",
L"frisch",
L"gut",
L"in Ordnung",
L"alt",
L"ranzig",
L"verdorben",
L"."
};
CHAR16* ranks[] =
{ L"", //ExpLevel 0
L"Rekr. ", //ExpLevel 1
+30 -2
View File
@@ -1630,6 +1630,7 @@ STR16 pAssignmentStrings[] =
L"Istrutt.", // training a teammate
L"Studente", // being trained by someone else
L"Staff", // operating a strategic facility // TODO.Translate
L"Eat", // eating at a facility (cantina etc.) // TODO. Translate
L"Rest", // Resting at a facility // TODO.Translate
L"Morto", // dead
L"Incap.", // abbreviation for incapacitated
@@ -1714,6 +1715,7 @@ STR16 pPersonnelAssignmentStrings[] =
L"Allenatore",
L"Studente",
L"Facility Staff", // TODO.Translate
L"Eat", // eating at a facility (cantina etc.) // TODO. Translate
L"Resting at Facility", // TODO.Translate
L"Morto",
L"Incap.",
@@ -2918,6 +2920,10 @@ CHAR16 TacticalStr[][ MED_STRING_LENGTH ] =
// added by Flugente to display health and poisoning // TODO.Translate
L"Health: %d/%d\n Poison: %d/%d\nEnergy: %d/%d\nMorale: %s",
// added by Flugente to display food status
L"Health: %d/%d\nEnergy: %d/%d\nMorale: %s\nWater: %d%s\nFood: %d%s",
L"Health: %d/%d\n Poison: %d/%d\nEnergy: %d/%d\nMorale: %s\nWater: %d%s\nFood: %d%s",
};
//Varying helptext explains (for the "Go to Sector/Map" checkbox) what will happen given different circumstances in the "exiting sector" interface.
@@ -3470,7 +3476,9 @@ STR16 pMapScreenStatusStrings[] =
L"Morale",
L"Condizione", // the condition of the current vehicle (its "health")
L"Carburante", // the fuel level of the current vehicle (its "energy")
L"Posion", // TODO.Translate
L"Poison", // TODO.Translate
L"Water", // drink level
L"Food", // food level
};
@@ -5325,6 +5333,7 @@ STR16 gzGIOScreenText[] =
L"New Chance to Hit System",
L"Improved Interrupt System",
L"Weapon Overheating",
L"Food System",//TODO.Translate
L"Bobby Ray Quantity", //TODO.Translate
};
@@ -6646,6 +6655,7 @@ STR16 gzFacilityAssignmentStrings[]=
{
L"AMBIENT",
L"Staff",
L"Eat",// TODO. Translate
L"Rest",
L"Repair Items",
L"Repair %s", // Vehicle name inserted here
@@ -7024,6 +7034,8 @@ STR16 szUDBGenSecondaryStatsTooltipText[]=
L"|F|i|r|s|t |A|i|d |K|i|t",
L"|M|e|d|i|c|a|l |K|i|t",
L"|L|o|c|k |B|o|m|b",
L"|D|r|i|n|k",// TODO. Translate
L"|M|e|a|l",
};
STR16 szUDBGenSecondaryStatsExplanationsTooltipText[]=
@@ -7054,6 +7066,8 @@ STR16 szUDBGenSecondaryStatsExplanationsTooltipText[]=
L"\n \nThis is a basic field medical kit, containing\nitems required to provide basic medical aid.\n \nIt can be used to bandage wounded characters\nand prevent bleeding.\n \nFor actual healing, use a proper Medical Kit\nand/or plenty of rest.",
L"\n \nThis is a proper medical kit, which can\nbe used in surgery and other serious medicinal\npurposes.\n \nMedical Kits are always required when setting\na character to Doctoring duty.",
L"\n \nThis item can be used to blast open locked\ndoors and containers.\n \nExplosives skill is required to avoid\npremature detonation.\n \nBlowing locks is a relatively easy way of quickly\ngetting through locked doors. However,\nit is very loud, and dangerous to most characters.",
L"\n \nThis item will still your thirst\nif you drink it.",// TODO. Translate
L"\n \nThis item will still your hunger\nif you eat it.",
};
STR16 szUDBAdvStatsTooltipText[]=
@@ -7269,7 +7283,7 @@ STR16 gzMapInventoryFilterOptions[] =
L"Hide all",
};
// Flugente FTW 1: Temperature-based text similar to HAM 4's condition-based text.
// Flugente: Temperature-based text similar to HAM 4's condition-based text.
STR16 gTemperatureDesc[] = // TODO.Translate
{
L"Temperature is ",
@@ -7285,6 +7299,20 @@ STR16 gTemperatureDesc[] = // TODO.Translate
L"."
};
// TODO.Translate
// Flugente: food condition texts
STR16 gFoodDesc[] =
{
L"Food is ",
L"fresh",
L"good",
L"ok",
L"stale",
L"shabby",
L"rotting",
L"."
};
// TODO.Translate
CHAR16* ranks[] =
{ L"", //ExpLevel 0
+30 -2
View File
@@ -1645,6 +1645,7 @@ STR16 pAssignmentStrings[] =
L"Instruk.", // training a teammate
L"Uczeń", // being trained by someone else
L"Staff", // operating a strategic facility // TODO.Translate
L"Eat", // eating at a facility (cantina etc.) // TODO. Translate
L"Rest", // Resting at a facility // TODO.Translate
L"Nie żyje", // dead
L"Obezwł.", // abbreviation for incapacitated
@@ -1729,6 +1730,7 @@ STR16 pPersonnelAssignmentStrings[] =
L"Instruktor",
L"Uczeń",
L"Facility Staff", // TODO.Translate
L"Eat", // eating at a facility (cantina etc.) // TODO. Translate
L"Resting at Facility", // TODO.Translate
L"Nie żyje",
L"Obezwładniony",
@@ -2933,6 +2935,10 @@ CHAR16 TacticalStr[][ MED_STRING_LENGTH ] =
// added by Flugente to display health and poisoning // TODO.Translate
L"Health: %d/%d\n Poison: %d/%d\nEnergy: %d/%d\nMorale: %s",
// added by Flugente to display food status
L"Health: %d/%d\nEnergy: %d/%d\nMorale: %s\nWater: %d%s\nFood: %d%s",
L"Health: %d/%d\n Poison: %d/%d\nEnergy: %d/%d\nMorale: %s\nWater: %d%s\nFood: %d%s",
};
//Varying helptext explains (for the "Go to Sector/Map" checkbox) what will happen given different circumstances in the "exiting sector" interface.
@@ -3486,7 +3492,9 @@ STR16 pMapScreenStatusStrings[] =
L"Morale",
L"Stan", // the condition of the current vehicle (its "health")
L"Paliwo", // the fuel level of the current vehicle (its "energy")
L"Posion", // TODO.Translate
L"Poison", // TODO.Translate
L"Water", // drink level
L"Food", // food level
};
@@ -5334,6 +5342,7 @@ STR16 gzGIOScreenText[] =
L"New Chance to Hit System",
L"Improved Interrupt System",
L"Weapon Overheating",
L"Food System",//TODO.Translate
L"Bobby Ray Quantity", //TODO.Translate
};
@@ -6656,6 +6665,7 @@ STR16 gzFacilityAssignmentStrings[]=
{
L"AMBIENT",
L"Staff",
L"Eat",// TODO. Translate
L"Odpoczywa"
L"Naprawa ekwipunku",
L"Naprawa %s",
@@ -7034,6 +7044,8 @@ STR16 szUDBGenSecondaryStatsTooltipText[]=
L"|F|i|r|s|t |A|i|d |K|i|t",
L"|M|e|d|i|c|a|l |K|i|t",
L"|L|o|c|k |B|o|m|b",
L"|D|r|i|n|k",// TODO. Translate
L"|M|e|a|l",
};
STR16 szUDBGenSecondaryStatsExplanationsTooltipText[]=
@@ -7064,6 +7076,8 @@ STR16 szUDBGenSecondaryStatsExplanationsTooltipText[]=
L"\n \nThis is a basic field medical kit, containing\nitems required to provide basic medical aid.\n \nIt can be used to bandage wounded characters\nand prevent bleeding.\n \nFor actual healing, use a proper Medical Kit\nand/or plenty of rest.",
L"\n \nThis is a proper medical kit, which can\nbe used in surgery and other serious medicinal\npurposes.\n \nMedical Kits are always required when setting\na character to Doctoring duty.",
L"\n \nThis item can be used to blast open locked\ndoors and containers.\n \nExplosives skill is required to avoid\npremature detonation.\n \nBlowing locks is a relatively easy way of quickly\ngetting through locked doors. However,\nit is very loud, and dangerous to most characters.",
L"\n \nThis item will still your thirst\nif you drink it.",// TODO. Translate
L"\n \nThis item will still your hunger\nif you eat it.",
};
STR16 szUDBAdvStatsTooltipText[]=
@@ -7279,7 +7293,7 @@ STR16 gzMapInventoryFilterOptions[] =
L"Hide all",
};
// Flugente FTW 1: Temperature-based text similar to HAM 4's condition-based text.
// Flugente: Temperature-based text similar to HAM 4's condition-based text.
STR16 gTemperatureDesc[] = // TODO.Translate
{
L"Temperature is ",
@@ -7295,6 +7309,20 @@ STR16 gTemperatureDesc[] = // TODO.Translate
L"."
};
// TODO.Translate
// Flugente: food condition texts
STR16 gFoodDesc[] =
{
L"Food is ",
L"fresh",
L"good",
L"ok",
L"stale",
L"shabby",
L"rotting",
L"."
};
// TODO.Translate
CHAR16* ranks[] =
{ L"", //ExpLevel 0
+30 -2
View File
@@ -1638,6 +1638,7 @@ STR16 pAssignmentStrings[] =
L"Тренер", // training a teammate
L"Ученик", // being trained by someone else
L"Штат", // operating a strategic facility //Staff
L"Eat", // eating at a facility (cantina etc.) // TODO. Translate
L"Отдых", // Resting at a facility //Rest
L"Мертв", // dead
L"Недеесп.", // abbreviation for incapacitated
@@ -1722,6 +1723,7 @@ STR16 pPersonnelAssignmentStrings[] =
L"Тренер",
L"Ученик",
L"Работает с населением", //Facility Staff
L"Eat", // eating at a facility (cantina etc.) // TODO. Translate
L"Отдыхает", //Resting at Facility
L"Мертв",
L"Недеесп.",
@@ -2926,6 +2928,10 @@ CHAR16 TacticalStr[][ MED_STRING_LENGTH ] =
// added by Flugente to display health and poisoning // TODO.Translate
L"Health: %d/%d\n Poison: %d/%d\nEnergy: %d/%d\nMorale: %s",
// added by Flugente to display food status
L"Health: %d/%d\nEnergy: %d/%d\nMorale: %s\nWater: %d%s\nFood: %d%s",
L"Health: %d/%d\n Poison: %d/%d\nEnergy: %d/%d\nMorale: %s\nWater: %d%s\nFood: %d%s",
};
//Varying helptext explains (for the "Go to Sector/Map" checkbox) what will happen given different circumstances in the "exiting sector" interface.
@@ -3479,7 +3485,9 @@ STR16 pMapScreenStatusStrings[] =
L"Боевой дух",
L"Состояние", // the condition of the current vehicle (its "health")
L"Бензин", // the fuel level of the current vehicle (its "energy")
L"Posion", // TODO.Translate
L"Poison", // TODO.Translate
L"Water", // drink level
L"Food", // food level
};
@@ -5318,6 +5326,7 @@ STR16 gzGIOScreenText[] =
L"New Chance to Hit System",
L"Improved Interrupt System",
L"Weapon Overheating",
L"Food System",//TODO.Translate
L"Bobby Ray Quantity",
};
@@ -6625,6 +6634,7 @@ STR16 gzFacilityAssignmentStrings[]=
{
L"AMBIENT",
L"Штат", //Staff
L"Eat",// TODO. Translate
L"Отдых",
L"Ремонт вещей",
L"Ремонт %s", // Vehicle name inserted here
@@ -7002,6 +7012,8 @@ STR16 szUDBGenSecondaryStatsTooltipText[]=
L"|А|п|т|е|ч к|а |п|е|р|в|о|й |п|о|м|о|щ|и",
L"|М|е|д|и|ц|и|нс|к|и|й |н|а|б|о|р",
L"|Б|о|м|б|а |д|л|я |з|а|м|к|о|в",
L"|D|r|i|n|k",// TODO. Translate
L"|M|e|a|l",
};
STR16 szUDBGenSecondaryStatsExplanationsTooltipText[]=
@@ -7032,6 +7044,8 @@ STR16 szUDBGenSecondaryStatsExplanationsTooltipText[]=
L"\n \nThis is a basic field medical kit, containing\nitems required to provide basic medical aid.\n \nIt can be used to bandage wounded characters\nand prevent bleeding.\n \nFor actual healing, use a proper Medical Kit\nand/or plenty of rest.",
L"\n \nThis is a proper medical kit, which can\nbe used in surgery and other serious medicinal\npurposes.\n \nMedical Kits are always required when setting\na character to Doctoring duty.",
L"\n \nThis item can be used to blast open locked\ndoors and containers.\n \nExplosives skill is required to avoid\npremature detonation.\n \nBlowing locks is a relatively easy way of quickly\ngetting through locked doors. However,\nit is very loud, and dangerous to most characters.",
L"\n \nThis item will still your thirst\nif you drink it.",// TODO. Translate
L"\n \nThis item will still your hunger\nif you eat it.",
};
STR16 szUDBAdvStatsTooltipText[]=
@@ -7247,7 +7261,7 @@ STR16 gzMapInventoryFilterOptions[] =
L"Hide all",
};
// Flugente FTW 1: Temperature-based text similar to HAM 4's condition-based text.
// Flugente: Temperature-based text similar to HAM 4's condition-based text.
STR16 gTemperatureDesc[] = // TODO.Translate
{
L"Temperature is ",
@@ -7263,6 +7277,20 @@ STR16 gTemperatureDesc[] = // TODO.Translate
L"."
};
// TODO.Translate
// Flugente: food condition texts
STR16 gFoodDesc[] =
{
L"Food is ",
L"fresh",
L"good",
L"ok",
L"stale",
L"shabby",
L"rotting",
L"."
};
// TODO.Translate
CHAR16* ranks[] =
{ L"", //ExpLevel 0
+30 -2
View File
@@ -1638,6 +1638,7 @@ STR16 pAssignmentStrings[] =
L"Trainer", // training a teammate
L"Student", // being trained by someone else
L"Staff", // operating a strategic facility // TODO.Translate
L"Eat", // eating at a facility (cantina etc.) // TODO. Translate
L"Rest", // Resting at a facility // TODO.Translate
L"Dead", // dead
L"Incap.", // abbreviation for incapacitated
@@ -1722,6 +1723,7 @@ STR16 pPersonnelAssignmentStrings[] =
L"Trainer",
L"Student",
L"Facility Staff", // TODO.Translate
L"Eat", // eating at a facility (cantina etc.) // TODO. Translate
L"Resting at Facility", // TODO.Translate
L"Dead",
L"Incap.",
@@ -2927,6 +2929,10 @@ CHAR16 TacticalStr[][ MED_STRING_LENGTH ] =
// added by Flugente to display health and poisoning // TODO.Translate
L"Health: %d/%d\n Poison: %d/%d\nEnergy: %d/%d\nMorale: %s",
// added by Flugente to display food status
L"Health: %d/%d\nEnergy: %d/%d\nMorale: %s\nWater: %d%s\nFood: %d%s",
L"Health: %d/%d\n Poison: %d/%d\nEnergy: %d/%d\nMorale: %s\nWater: %d%s\nFood: %d%s",
};
//Varying helptext explains (for the "Go to Sector/Map" checkbox) what will happen given different circumstances in the "exiting sector" interface.
@@ -3480,7 +3486,9 @@ STR16 pMapScreenStatusStrings[] =
L"Morale",
L"Condition", // the condition of the current vehicle (its "health")
L"Fuel", // the fuel level of the current vehicle (its "energy")
L"Posion", // TODO.Translate
L"Poison", // TODO.Translate
L"Water", // drink level
L"Food", // food level
};
@@ -5341,6 +5349,7 @@ STR16 gzGIOScreenText[] =
L"New Chance to Hit System",
L"Improved Interrupt System",
L"Weapon Overheating",
L"Food System",//TODO.Translate
L"Bobby Ray Quantity",
};
@@ -6661,6 +6670,7 @@ STR16 gzFacilityAssignmentStrings[]=
{
L"AMBIENT",
L"Staff",
L"Eat",// TODO. Translate
L"Rest",
L"Repair Items",
L"Repair %s", // Vehicle name inserted here
@@ -7039,6 +7049,8 @@ STR16 szUDBGenSecondaryStatsTooltipText[]=
L"|F|i|r|s|t |A|i|d |K|i|t",
L"|M|e|d|i|c|a|l |K|i|t",
L"|L|o|c|k |B|o|m|b",
L"|D|r|i|n|k",// TODO. Translate
L"|M|e|a|l",
};
STR16 szUDBGenSecondaryStatsExplanationsTooltipText[]=
@@ -7069,6 +7081,8 @@ STR16 szUDBGenSecondaryStatsExplanationsTooltipText[]=
L"\n \nThis is a basic field medical kit, containing\nitems required to provide basic medical aid.\n \nIt can be used to bandage wounded characters\nand prevent bleeding.\n \nFor actual healing, use a proper Medical Kit\nand/or plenty of rest.",
L"\n \nThis is a proper medical kit, which can\nbe used in surgery and other serious medicinal\npurposes.\n \nMedical Kits are always required when setting\na character to Doctoring duty.",
L"\n \nThis item can be used to blast open locked\ndoors and containers.\n \nExplosives skill is required to avoid\npremature detonation.\n \nBlowing locks is a relatively easy way of quickly\ngetting through locked doors. However,\nit is very loud, and dangerous to most characters.",
L"\n \nThis item will still your thirst\nif you drink it.",// TODO. Translate
L"\n \nThis item will still your hunger\nif you eat it.",
};
STR16 szUDBAdvStatsTooltipText[]=
@@ -7284,7 +7298,7 @@ STR16 gzMapInventoryFilterOptions[] =
L"Hide all",
};
// Flugente FTW 1: Temperature-based text similar to HAM 4's condition-based text.
// Flugente: Temperature-based text similar to HAM 4's condition-based text.
STR16 gTemperatureDesc[] = // TODO.Translate
{
L"Temperature is ",
@@ -7300,6 +7314,20 @@ STR16 gTemperatureDesc[] = // TODO.Translate
L"."
};
// TODO.Translate
// Flugente: food condition texts
STR16 gFoodDesc[] =
{
L"Food is ",
L"fresh",
L"good",
L"ok",
L"stale",
L"shabby",
L"rotting",
L"."
};
// TODO.Translate
CHAR16* ranks[] =
{ L"", //ExpLevel 0