Merge branch 'master' of github.com:1dot13/source

This commit is contained in:
zwwooooo
2023-09-10 22:03:41 +08:00
116 changed files with 3522 additions and 1434 deletions
+18 -5
View File
@@ -190,22 +190,35 @@ jobs:
mkdir dist/
mv artifacts/*_release/* dist/
- name: Delete Latest
if: startsWith(github.ref, 'refs/tags/v') == false
- name: Delete Latest Release and Tag
if: github.ref == 'refs/heads/master'
uses: dev-drprasad/delete-tag-and-release@v1.0
with:
delete_release: true
tag_name: "latest"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Checkout Repo
if: github.ref == 'refs/heads/master'
uses: actions/checkout@v3
with:
path: source
fetch-depth: 1
sparse-checkout: 'README.md'
- name: Create Latest Tag
if: github.ref == 'refs/heads/master'
working-directory: source
run: |
git tag -d latest || true
git tag latest
git push origin latest
- id: release_latest
name: Release Latest
if: startsWith(github.ref, 'refs/tags/v') == false
if: github.ref == 'refs/heads/master'
uses: ncipollo/release-action@v1
with:
allowUpdates: false
artifactErrorsFailBuild: true
artifacts: dist/*
draft: false
generateReleaseNotes: true
makeLatest: true
name: "Latest (unstable)"
+1
View File
@@ -8,3 +8,4 @@
/out/
/CMakeSettings.json
/CMakeUserPresets.json
/lib/
+6
View File
@@ -9,6 +9,12 @@ set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
option(ADDRESS_SANITIZER OFF)
if(ADDRESS_SANITIZER)
message(STATUS "AddressSanitizer ENABLED for non-Release builds")
add_compile_options($<IF:$<OR:$<CONFIG:Debug>,$<CONFIG:RelWithDebInfo>>,-fsanitize=address,>)
endif()
# whether we are using MSBuild as a generator
set(usingMsBuild $<STREQUAL:${CMAKE_VS_PLATFORM_NAME},Win32>)
+1 -1
View File
@@ -1517,7 +1517,7 @@ void HandleHighLightedText(BOOLEAN fHighLight)
bLastRegion = -1;
}
if (bHighLight != -1)
if (bHighLight != -1 && toggle_box_array[bHighLight] != -1)
{
if (bHighLight < OPT_FIRST_COLUMN_TOGGLE_CUT_OFF)
{
+2 -2
View File
@@ -4153,7 +4153,7 @@ void BtnGIOSquadSizeSelectionRightCallback( GUI_BUTTON *btn,INT32 reason )
if( reason & MSYS_CALLBACK_REASON_LBUTTON_REPEAT )
{
UINT8 maxSquadSize = GIO_SQUAD_SIZE_10;
if (iResolution >= _800x600 && iResolution < _1024x768)
if (iResolution >= _800x600 && iResolution < _1280x720)
maxSquadSize = GIO_SQUAD_SIZE_8;
if ( iCurrentSquadSize < maxSquadSize )
@@ -4173,7 +4173,7 @@ void BtnGIOSquadSizeSelectionRightCallback( GUI_BUTTON *btn,INT32 reason )
btn->uiFlags|=(BUTTON_CLICKED_ON);
UINT8 maxSquadSize = GIO_SQUAD_SIZE_10;
if (iResolution >= _800x600 && iResolution < _1024x768)
if (iResolution >= _800x600 && iResolution < _1280x720)
maxSquadSize = GIO_SQUAD_SIZE_8;
if ( iCurrentSquadSize < maxSquadSize )
+23 -6
View File
@@ -248,6 +248,7 @@ void UpdateFeatureFlags()
gGameExternalOptions.gfAllowSnow = gGameSettings.fFeatures[FF_ALLOW_SNOW];
gGameExternalOptions.fMiniEventsEnabled = gGameSettings.fFeatures[FF_MINI_EVENTS];
gGameExternalOptions.fRebelCommandEnabled = gGameSettings.fFeatures[FF_REBEL_COMMAND];
gGameExternalOptions.fStrategicTransportGroupsEnabled = gGameSettings.fFeatures[FF_STRATEGIC_TRANSPORT_GROUPS];
}
else
{
@@ -497,6 +498,7 @@ BOOLEAN LoadFeatureFlags()
gGameSettings.fFeatures[FF_ALLOW_SNOW] = iniReader.ReadBoolean("JA2 Feature Flags", "FF_ALLOW_SNOW", TRUE, FALSE);
gGameSettings.fFeatures[FF_MINI_EVENTS] = iniReader.ReadBoolean("JA2 Feature Flags", "FF_MINI_EVENTS", FALSE, FALSE);
gGameSettings.fFeatures[FF_REBEL_COMMAND] = iniReader.ReadBoolean("JA2 Feature Flags", "FF_REBEL_COMMAND", FALSE, FALSE);
gGameSettings.fFeatures[FF_STRATEGIC_TRANSPORT_GROUPS] = iniReader.ReadBoolean("JA2 Feature Flags", "FF_STRATEGIC_TRANSPORT_GROUPS", FALSE, FALSE);
}
}
catch(vfs::Exception)
@@ -725,6 +727,7 @@ BOOLEAN SaveFeatureFlags()
settings << "FF_ALLOW_SNOW = " << (gGameSettings.fFeatures[FF_ALLOW_SNOW] ? "TRUE" : "FALSE") << endl;
settings << "FF_MINI_EVENTS = " << (gGameSettings.fFeatures[FF_MINI_EVENTS] ? "TRUE" : "FALSE") << endl;
settings << "FF_REBEL_COMMAND = " << (gGameSettings.fFeatures[FF_REBEL_COMMAND] ? "TRUE" : "FALSE") << endl;
settings << "FF_STRATEGIC_TRANSPORT_GROUPS = " << (gGameSettings.fFeatures[FF_STRATEGIC_TRANSPORT_GROUPS] ? "TRUE" : "FALSE") << endl;
try
{
@@ -1076,6 +1079,9 @@ void LoadGameExternalOptions()
gGameExternalOptions.ubMercRandomExpRange = iniReader.ReadInteger("Recruitment Settings", "MERCS_RANDOM_EXP_RANGE", 1, 0, 4);
gGameExternalOptions.fMercRandomStartSalary = iniReader.ReadBoolean("Recruitment Settings", "MERCS_RANDOM_START_SALARY", FALSE);
gGameExternalOptions.ubMercRandomStartSalaryPercentMod = iniReader.ReadInteger("Recruitment Settings", "MERCS_RANDOM_START_SALARY_PERCENTAGE_MAX_MODIFIER", 30, 0, 100);
gGameExternalOptions.fMercGrowthModifiersEnabled = iniReader.ReadBoolean("Recruitment Settings", "MERCS_GROWTH_MODIFIERS_ENABLED", FALSE);
gGameExternalOptions.fMercRandomGrowthModifiers = iniReader.ReadBoolean("Recruitment Settings", "MERCS_RANDOM_GROWTH_MODIFIERS", FALSE);
gGameExternalOptions.iMercRandomGrowthModifiersRange = iniReader.ReadInteger("Recruitment Settings", "MERCS_RANDOM_GROWTH_MODIFIERS_RANGE", 5, -50, 50);
//################# Financial Settings #################
@@ -1144,7 +1150,9 @@ void LoadGameExternalOptions()
giTimerIntervals[ NEXTSCROLL ] = (INT16)(giTimerIntervals[ NEXTSCROLL ] / gGameExternalOptions.fScrollSpeedFactor);
gGameExternalOptions.gfUseExternalLoadscreens = iniReader.ReadBoolean("Graphics Settings","USE_EXTERNALIZED_LOADSCREENS", FALSE);
gGameExternalOptions.ubLoadscreenStretchMode = iniReader.ReadInteger("Graphics Settings", "LOADSCREEN_STRETCH_MODE", 0, 0, 2);
if (!is_networked)
gGameExternalOptions.gfUseLoadScreenHints = iniReader.ReadBoolean("Graphics Settings","USE_LOADSCREENHINTS", TRUE);
else
@@ -1425,6 +1433,11 @@ void LoadGameExternalOptions()
gGameExternalOptions.usLeadershipSubpointsToImprove = iniReader.ReadInteger("Tactical Difficulty Settings","LEADERSHIP_SUBPOINTS_TO_IMPROVE", 25, 1, 1000 );
gGameExternalOptions.usLevelSubpointsToImprove = iniReader.ReadInteger("Tactical Difficulty Settings","LEVEL_SUBPOINTS_TO_IMPROVE", 350, 1, 6500);
// rftr: optionally slow stat growth at 80+ and 90+. this gives more value to mercs with high base stats
gGameExternalOptions.ubMaxGrowthChanceAt80 = iniReader.ReadInteger("Tactical Difficulty Settings", "MAX_GROWTH_CHANCE_AT_80", 100, 1, 100);
gGameExternalOptions.ubMaxGrowthChanceAt90 = iniReader.ReadInteger("Tactical Difficulty Settings", "MAX_GROWTH_CHANCE_AT_90", 100, 1, 100);
// Alternate algorithm for choosing equipment level. Mostly disregards soldier's class and puts less emphasis on distance from Sector P3.
// SANDRO - moved into the game
//gGameExternalOptions.fSlowProgressForEnemyItemsChoice = iniReader.ReadBoolean("Tactical Difficulty Settings", "SLOW_PROGRESS_FOR_ENEMY_ITEMS_CHOICE", TRUE);
@@ -2161,6 +2174,10 @@ void LoadGameExternalOptions()
gGameExternalOptions.fAlternativeHelicopterFuelSystem = iniReader.ReadBoolean("Strategic Gameplay Settings","ALTERNATIVE_HELICOPTER_FUEL_SYSTEM", TRUE);
gGameExternalOptions.fHelicopterPassengersCanGetHit = iniReader.ReadBoolean("Strategic Gameplay Settings","HELICOPTER_PASSENGERS_CAN_GET_HIT", TRUE);
gGameExternalOptions.fStrategicTransportGroupsDebug = iniReader.ReadBoolean("Strategic Gameplay Settings", "STRATEGIC_TRANSPORT_GROUPS_DEBUG", FALSE, FALSE);
gGameExternalOptions.fStrategicTransportGroupsEnabled = iniReader.ReadBoolean("Strategic Gameplay Settings", "STRATEGIC_TRANSPORT_GROUPS_ENABLED", FALSE);
gGameExternalOptions.iMaxSimultaneousTransportGroups = iniReader.ReadInteger("Strategic Gameplay Settings", "MAX_SIMULTANEOUS_STRATEGIC_TRANSPORT_GROUPS", 5, 1, 10);
//################# Morale Settings ##################
gGameExternalOptions.sMoraleModAppearance = iniReader.ReadInteger("Morale Settings","MORALE_MOD_APPEARANCE", 1, 0, 5);
gGameExternalOptions.sMoraleModRefinement = iniReader.ReadInteger("Morale Settings","MORALE_MOD_REFINEMENT", 2, 0, 5);
@@ -2468,8 +2485,6 @@ void LoadGameExternalOptions()
gGameExternalOptions.ubTeachBonusToTrain = iniReader.ReadInteger("Strategic Assignment Settings","TEACHER_TRAIT_BONUS_TO_TRAINING_EFFICIENCY",30, 0, 100);
gGameExternalOptions.ubMinSkillToTeach = iniReader.ReadInteger("Strategic Assignment Settings","MIN_SKILL_REQUIRED_TO_TEACH_OTHER",25, 0, 100);
gGameExternalOptions.bDisableEvolution = iniReader.ReadBoolean("Strategic Assignment Settings", "DISABLE_EVOLUTION", TRUE );
// HEADROCK HAM B2.8: New Trainer Relations: 2 = Trainees will go to sleep when their trainer goes to sleep. 3 = Trainer will go to sleep if all trainees are asleep. 1 = Both. 0 = Neither.
gGameExternalOptions.ubSmartTrainingSleep = iniReader.ReadInteger("Strategic Assignment Settings","SYNCHRONIZED_SLEEPING_HOURS_WHEN_TRAINING_TOGETHER", 0, 0, 3);
@@ -2772,6 +2787,9 @@ void LoadSkillTraitsExternalSettings()
gSkillTraitValues.ubTHBladesSilentCriticalHitChance = iniReader.ReadInteger("Throwing","TH_BLADES_SILENT_CRITICAL_HIT_CHANCE", 20, 0, 100);
gSkillTraitValues.ubTHBladesCriticalHitMultiplierBonus = iniReader.ReadInteger("Throwing","SILENT_CRITICAL_HIT_MULTIPLIER_BONUS", 1, 0, 50);
gSkillTraitValues.ubTHBladesAimClicksAdded = iniReader.ReadInteger("Throwing","POSSIBLE_AIM_CLICK_ADDED_TH_KNIVES", 1, 0, 5);
gSkillTraitValues.ubTHAPsNeededToThrowGrenadesReduction = iniReader.ReadInteger("Throwing","APS_NEEDED_TO_THROW_GRENADES_REDUCTION", 25, 0, 90);
gSkillTraitValues.ubTHMaxRangeToThrowGrenades = iniReader.ReadInteger("Throwing","MAX_RANGE_TO_THROW_GRENADES", 20, 0, 250);
gSkillTraitValues.ubTHCtHWhenThrowingGrenades = iniReader.ReadInteger("Throwing","CTH_WHEN_THROWING_GRENADES", 30, 0, 100);
// NIGHT OPS
gSkillTraitValues.ubNOeSightRangeBonusInDark = iniReader.ReadInteger("Night Ops","SIGHT_RANGE_BONUS_IN_DARK", 1, 0, 100);
@@ -2798,9 +2816,6 @@ void LoadSkillTraitsExternalSettings()
gSkillTraitValues.usBBIncreasedNeededDamageToFallDown = iniReader.ReadInteger("Bodybuilding","INCREASE_DAMAGE_NEEDED_TO_FALL_DOWN_IF_HIT_TO_LEGS", 100, 0, 500);
// DEMOLITIONS
gSkillTraitValues.ubDEAPsNeededToThrowGrenadesReduction = iniReader.ReadInteger("Demolitions","APS_NEEDED_TO_THROW_GRENADES_REDUCTION", 25, 0, 90);
gSkillTraitValues.ubDEMaxRangeToThrowGrenades = iniReader.ReadInteger("Demolitions","MAX_RANGE_TO_THROW_GRENADES", 20, 0, 250);
gSkillTraitValues.ubDECtHWhenThrowingGrenades = iniReader.ReadInteger("Demolitions","CTH_WHEN_THROWING_GRENADES", 30, 0, 100);
gSkillTraitValues.ubDEDamageOfBombsAndMines = iniReader.ReadInteger("Demolitions","DAMAGE_OF_PLACED_BOMBS_AND_MINES", 25, 0, 250);
gSkillTraitValues.ubDEAttachDetonatorCheckBonus = iniReader.ReadInteger("Demolitions","ATTACH_DETONATOR_CHECK_BONUS", 50, 0, 250);
gSkillTraitValues.ubDEPlantAndRemoveBombCheckBonus = iniReader.ReadInteger("Demolitions","PLANT_AND_REMOVE_BOMBS_AND_MINES_BONUS", 50, 0, 250);
@@ -4187,6 +4202,8 @@ void LoadRebelCommandSettings()
gRebelCommandSettings.iDisruptAsdDuration_Bonus_Nightops = iniReader.ReadInteger("Rebel Command Settings", "DISRUPT_ASD_DURATION_BONUS_NIGHTOPS", 48, 0, 255);
gRebelCommandSettings.iDisruptAsdDuration_Bonus_Technician = iniReader.ReadInteger("Rebel Command Settings", "DISRUPT_ASD_DURATION_BONUS_TECHNICIAN", 48, 0, 255);
gRebelCommandSettings.iForgeTransportOrdersSuccessChance = iniReader.ReadInteger("Rebel Command Settings", "FORGE_TRANSPORT_ORDERS_SUCCESS_CHANCE", 50, 0, 100);
gRebelCommandSettings.iGetEnemyMovementTargetsSuccessChance = iniReader.ReadInteger("Rebel Command Settings", "STRATEGIC_INTEL_SUCCESS_CHANCE", 50, 0, 100);
gRebelCommandSettings.iGetEnemyMovementTargetsDuration = iniReader.ReadInteger("Rebel Command Settings", "STRATEGIC_INTEL_DURATION", 72, 0, 255);
gRebelCommandSettings.iGetEnemyMovementTargetsDuration_Bonus_Covert = iniReader.ReadInteger("Rebel Command Settings", "STRATEGIC_INTEL_DURATION_BONUS_COVERT", 48, 0, 255);
+19 -6
View File
@@ -181,6 +181,7 @@ enum
FF_ALLOW_SNOW,
FF_MINI_EVENTS,
FF_REBEL_COMMAND,
FF_STRATEGIC_TRANSPORT_GROUPS,
NUM_FEATURE_FLAGS,
};
@@ -780,6 +781,7 @@ typedef struct
INT32 ubEnemiesItemDrop;
BOOLEAN gfUseExternalLoadscreens;
UINT32 ubLoadscreenStretchMode; // added by anv
BOOLEAN gfUseLoadScreenHints; // added by Flugente
UINT32 ubAdditionalDelayUntilLoadScreenDisposal; // added by WANNE to have time to read the load screen hints
@@ -815,9 +817,6 @@ typedef struct
INT32 ubRpcBonusToTrainMilitia;
INT32 ubMinSkillToTeach;
// Flugente: disable evolution setting in MercProfiles.xml
BOOLEAN bDisableEvolution;
INT32 ubLowActivityLevel;
INT32 ubMediumActivityLevel;
INT32 ubHighActivityLevel;
@@ -1148,6 +1147,10 @@ typedef struct
UINT16 usLeadershipSubpointsToImprove;
UINT16 usLevelSubpointsToImprove;
// rftr: optionally slow stat growth at 80+ and 90+. this gives more value to mercs with high base stats
UINT8 ubMaxGrowthChanceAt80;
UINT8 ubMaxGrowthChanceAt90;
// HEADROCK HAM B2.7: When turned on, this will give a CTH approximation instead of an exact value, on CTH Bars and "F" key feedback.
BOOLEAN fApproximateCTH;
@@ -1435,6 +1438,10 @@ typedef struct
UINT8 ubMercRandomStartSalaryPercentMod;
BOOLEAN fMercGrowthModifiersEnabled;
BOOLEAN fMercRandomGrowthModifiers;
INT16 iMercRandomGrowthModifiersRange;
BOOLEAN fBobbyRayFastShipments;
BOOLEAN fGridExitInTurnBased;
@@ -1602,6 +1609,10 @@ typedef struct
BOOLEAN fAlternativeHelicopterFuelSystem;
BOOLEAN fHelicopterPassengersCanGetHit;
BOOLEAN fStrategicTransportGroupsDebug;
BOOLEAN fStrategicTransportGroupsEnabled;
INT8 iMaxSimultaneousTransportGroups;
UINT16 usHelicopterHoverCostOnGreenTile;
UINT16 usHelicopterHoverCostOnRedTile;
@@ -1878,6 +1889,8 @@ typedef struct
UINT8 iDisruptAsdDuration_Bonus_Nightops;
UINT8 iDisruptAsdDuration_Bonus_Technician;
INT8 iForgeTransportOrdersSuccessChance;
INT8 iGetEnemyMovementTargetsSuccessChance;
UINT8 iGetEnemyMovementTargetsDuration;
UINT8 iGetEnemyMovementTargetsDuration_Bonus_Covert;
@@ -2165,6 +2178,9 @@ typedef struct
UINT8 ubTHBladesSilentCriticalHitChance;
UINT8 ubTHBladesCriticalHitMultiplierBonus;
UINT8 ubTHBladesAimClicksAdded;
UINT8 ubTHAPsNeededToThrowGrenadesReduction;
UINT8 ubTHMaxRangeToThrowGrenades;
UINT8 ubTHCtHWhenThrowingGrenades;
// NIGHT OPS
UINT8 ubNOeSightRangeBonusInDark;
@@ -2191,9 +2207,6 @@ typedef struct
UINT16 usBBIncreasedNeededDamageToFallDown;
// DEMOLITIONS
UINT8 ubDEAPsNeededToThrowGrenadesReduction;
UINT8 ubDEMaxRangeToThrowGrenades;
UINT8 ubDECtHWhenThrowingGrenades;
UINT8 ubDEDamageOfBombsAndMines;
UINT8 ubDEAttachDetonatorCheckBonus;
UINT8 ubDEPlantAndRemoveBombCheckBonus;
+2 -1
View File
@@ -23,6 +23,7 @@ extern CHAR16 zBuildInformation[256];
// Keeps track of the saved game version. Increment the saved game version whenever
// you will invalidate the saved game file
#define GROWTH_MODIFIERS 184
#define REBELCOMMAND 183
#define DRAGSTRUCTURE 182 // Flugente: we can drag structures behind us
#define DISABILITYFLAGMASK 181 // Flugente: disabilities get a flagmask
@@ -104,7 +105,7 @@ extern CHAR16 zBuildInformation[256];
#define AP100_SAVEGAME_DATATYPE_CHANGE 105 // Before this, we didn't have the 100AP structure changes
#define NIV_SAVEGAME_DATATYPE_CHANGE 102 // Before this, we used the old structure system
#define SAVE_GAME_VERSION REBELCOMMAND
#define SAVE_GAME_VERSION GROWTH_MODIFIERS
//#define RUSSIANGOLD
#ifdef __cplusplus
+68 -87
View File
@@ -362,6 +362,29 @@ void GetHelpTextForItemInLaptop( STR16 pzStr, UINT16 usItemNumber );
void HandleBobbyRGunsKeyBoardInput();
void HandleBobbyRayMouseWheel(void);
// Appends source STR16 to target STR16 using decorators ("\n" and "...").
// Returns TRUE if everything fits target, FALSE otherwise.
static BOOLEAN DecorateAppendString(STR16 target, size_t targetCapacity, STR16 source, UINT32 frontDecoratorsCnt = 1)
{
const CHAR16 DECORATOR0[] = L"\n";
const CHAR16 DECORATOR1[] = L"\n...";
BOOLEAN result = FALSE;
size_t decoratorLen = wcslen(DECORATOR0) * frontDecoratorsCnt;
if (wcslen(target) + decoratorLen + wcslen(source) + 1 < targetCapacity)
{
for (UINT32 i = 0; i < frontDecoratorsCnt; i++)
wcscat(target, DECORATOR0);
wcscat(target, source);
result = TRUE;
}
else if (wcslen(target) + wcslen(DECORATOR1) + 1 < targetCapacity)
{
wcscat(target, DECORATOR1);
} // otherwise don't even touch the target
return result;
}
void GameInitBobbyRGuns()
{
guiTempCurrentMode=0;
@@ -4088,7 +4111,8 @@ void HandleBobbyRayMouseWheel(void)
}
void GetHelpTextForItemInLaptop( STR16 pzStr, UINT16 usItemNumber )
{
{
const size_t ATTACHMENTS_STRBUF_SIZE = 3800;
CHAR16 zItemName[ SIZE_ITEM_NAME ];
UINT8 ubItemCount=0;
@@ -4115,12 +4139,9 @@ void GetHelpTextForItemInLaptop( STR16 pzStr, UINT16 usItemNumber )
// HEADROCK HAM 3: Variables for "Possible Attachment List"
BOOLEAN fAttachmentsFound = FALSE;
// Contains entire string of attachment names
CHAR16 attachStr[3900];
// Contains current attachment string
CHAR16 attachStr2[100];
CHAR16 attachStr[ATTACHMENTS_STRBUF_SIZE];
// Contains temporary attachment list before added to string constant from text.h
CHAR16 attachStr3[3900];
UINT16 usAttachment;
CHAR16 attachStr3[ATTACHMENTS_STRBUF_SIZE];
CreateItem(usItemNumber, 100, &pObject);
INT16 ubAttackAPs = BaseAPsToShootOrStab( APBPConstants[DEFAULT_APS], APBPConstants[DEFAULT_AIMSKILL], &pObject, NULL );
@@ -4146,109 +4167,69 @@ void GetHelpTextForItemInLaptop( STR16 pzStr, UINT16 usItemNumber )
else
wcscat( apStr, L" / -" );
// HEADROCK HAM 3: Empty these strings first, to avoid crashes. Please keep this here.
swprintf( attachStr, L"" );
swprintf( attachStr2, L"" );
swprintf( attachStr3, L"" );
attachStr[0] = 0;
attachStr3[0] = 0;
// HEADROCK HAM 3: Generate list of possible attachments to a gun (Guns only!)
if (gGameExternalOptions.fBobbyRayTooltipsShowAttachments)
{
UINT16 iLoop = 0;
// Check entire attachment list
while( 1 )
if (UsingNewAttachmentSystem())
{
//Madd: Common Attachment Framework
//TODO: Note that the items in this list will be duplicated if they are present in both the CAF and the old attachment method
//need to refactor this to work more like the NAS attachment slots method
usAttachment = 0;
if ( IsAttachmentPointAvailable(Item[usItemNumber].uiIndex, iLoop) )
{
usAttachment = iLoop;
// If the attachment is not hidden
if (usAttachment > 0 && !Item[ usAttachment ].hiddenaddon && !Item[ usAttachment ].hiddenattachment)
{
if (wcslen( attachStr3 ) + wcslen(Item[usAttachment].szItemName) > 3800)
{
// End list early to avoid stack overflow
wcscat( attachStr3, L"\n..." );
break;
}
else
{// Add the attachment's name to the list.
fAttachmentsFound = TRUE;
swprintf( attachStr2, L"\n%s", Item[ usAttachment ].szItemName );
wcscat( attachStr3, attachStr2);
}
}
}
// Is the weapon we're checking the same as the one we're tooltipping?
usAttachment = 0;
if (Attachment[iLoop][1] == Item[usItemNumber].uiIndex)
std::pair<std::multimap<UINT16, AttachmentStruct>::iterator, std::multimap<UINT16, AttachmentStruct>::iterator> range;
std::multimap<UINT16, AttachmentStruct>::iterator it;
range = AttachmentBackmap.equal_range(Item[usItemNumber].uiIndex);
for (it = range.first; it != range.second; it++)
{
usAttachment = Attachment[iLoop][0];
}
// If the attachment is not hidden
if (usAttachment > 0 && !Item[ usAttachment ].hiddenaddon && !Item[ usAttachment ].hiddenattachment)
{
if (wcslen( attachStr3 ) + wcslen(Item[usAttachment].szItemName) > 3800)
UINT16 attachmentId = it->second.attachmentIndex;
if (!Item[attachmentId].hiddenaddon && !Item[attachmentId].hiddenattachment && ItemIsLegal(attachmentId, TRUE))
{
// End list early to avoid stack overflow
wcscat( attachStr3, L"\n..." );
break;
}
else
{// Add the attachment's name to the list.
fAttachmentsFound = TRUE;
swprintf( attachStr2, L"\n%s", Item[ usAttachment ].szItemName );
wcscat( attachStr3, attachStr2);
if (DecorateAppendString(attachStr3, ATTACHMENTS_STRBUF_SIZE, Item[attachmentId].szItemName) == FALSE)
break;
}
}
iLoop++;
if (Attachment[iLoop][0] == 0 && Item[iLoop].usItemClass == 0)
{
// Reached end of list
break;
}
}
else // old attachment system
{
for (UINT32 itemId = 1; itemId < gMAXITEMS_READ; itemId++)
{
// If the attachment is not hidden and attachable to the gun (usItemNumber)
if (!Item[itemId].hiddenaddon && !Item[itemId].hiddenattachment &&
ItemIsLegal(itemId, TRUE) && IsAttachmentPointAvailable(Item[usItemNumber].uiIndex, itemId))
{
fAttachmentsFound = TRUE;
if (DecorateAppendString(attachStr3, ATTACHMENTS_STRBUF_SIZE, Item[itemId].szItemName) == FALSE)
break;
}
}
}
if (fAttachmentsFound)
{
// Add extra empty line and attachment list title
swprintf( attachStr, L"\n \n%s", gWeaponStatsDesc[ 14 ] );
wcscat( attachStr, attachStr3 );
DecorateAppendString(attachStr, ATTACHMENTS_STRBUF_SIZE, gWeaponStatsDesc[14], 2); // 2 new lines and "Attachments:" title
DecorateAppendString(attachStr, ATTACHMENTS_STRBUF_SIZE, attachStr3, 0); // no new line, list of attachments (starts with new line)
}
}
//Sum up default attachments.
BOOLEAN fFoundDefault = FALSE;
swprintf( attachStr2, L"" );
swprintf( attachStr3, L"" );
for(UINT8 cnt = 0; cnt < MAX_DEFAULT_ATTACHMENTS; cnt++){
if(Item[usItemNumber].defaultattachments[cnt] != 0){
if (wcslen( attachStr ) + wcslen(attachStr3) + wcslen(Item[ Item[usItemNumber].defaultattachments[cnt] ].szItemName) > 3800)
{
// End list early to avoid stack overflow
wcscat( attachStr3, L"\n..." );
attachStr3[0] = 0;
for (UINT8 cnt = 0; cnt < MAX_DEFAULT_ATTACHMENTS; cnt++)
{
if (Item[usItemNumber].defaultattachments[cnt] != 0)
{
if (DecorateAppendString(attachStr3, ATTACHMENTS_STRBUF_SIZE, Item[Item[usItemNumber].defaultattachments[cnt]].szItemName) == FALSE)
break;
}
fFoundDefault = TRUE;
swprintf( attachStr2, L"\n%s", Item[ Item[usItemNumber].defaultattachments[cnt] ].szItemName );
wcscat( attachStr3, attachStr2 );
} else {
//If we found an empty entry, we can assume the rest will be empty too.
break;
}
else // If we found an empty entry, we can assume the rest will be empty too.
break;
}
if(fFoundDefault){
//Found at least one default attachment, write it to the attachment string.
CHAR16 defaultStr[50];
swprintf( defaultStr, L"\n \n%s", gWeaponStatsDesc[ 17 ] );
wcscat( attachStr, defaultStr );
wcscat( attachStr, attachStr3 );
if (fFoundDefault)
{
DecorateAppendString(attachStr, ATTACHMENTS_STRBUF_SIZE, gWeaponStatsDesc[17], 2); // 2 new lines and "Default:" title
DecorateAppendString(attachStr, ATTACHMENTS_STRBUF_SIZE, attachStr3, 0); // no new line, list of attachments (starts with new line)
}
// HEADROCK HAM 3: Added last string (attachStr), for display of the possible attachment list.
+5 -3
View File
@@ -15,6 +15,8 @@
#include "CharProfile.h"
#include "soldier profile type.h"
#include "IMP Compile Character.h"
#include "IMP Disability Trait.h"
#include "IMP Character Trait.h"
#include "GameSettings.h"
#include "Interface.h"
@@ -671,7 +673,7 @@ BOOLEAN IsBackGroundAllowed( UINT16 ubNumber )
return FALSE;
}
switch ( iPersonality )
switch ( iChosenDisabilityTrait() )
{
case HEAT_INTOLERANT:
if ( zBackground[ ubNumber ].value[BG_DESERT] > 0 )
@@ -707,7 +709,7 @@ BOOLEAN IsBackGroundAllowed( UINT16 ubNumber )
break;
}
switch ( iAttitude )
switch ( iChosenCharacterTrait() )
{
case CHAR_TRAIT_SOCIABLE:
if ( zBackground[ ubNumber ].uiFlags & BACKGROUND_XENOPHOBIC )
@@ -807,4 +809,4 @@ void BtnIMPBackgroundPreviousCallback(GUI_BUTTON *btn,INT32 reason)
usBackground = 0;
}
}
}
}
+18 -1
View File
@@ -539,6 +539,23 @@ BOOLEAN CPostalService::DeliverShipment(UINT16 usShipmentID)
SetFactFalse( FACT_PABLOS_STOLE_FROM_LATEST_SHIPMENT );
}
// set fact according to shipment size (item count, not weight)
if (usNumberOfItems - uiStolenCount <= 5)
{
SetFactFalse(FACT_MEDIUM_SIZED_SHIPMENT_WAITING);
SetFactFalse(FACT_LARGE_SIZED_SHIPMENT_WAITING);
}
else if (usNumberOfItems - uiStolenCount <= 15)
{
SetFactTrue(FACT_MEDIUM_SIZED_SHIPMENT_WAITING);
SetFactFalse(FACT_LARGE_SIZED_SHIPMENT_WAITING);
}
else
{
SetFactFalse(FACT_MEDIUM_SIZED_SHIPMENT_WAITING);
SetFactTrue(FACT_LARGE_SIZED_SHIPMENT_WAITING);
}
SetFactFalse( FACT_PLAYER_FOUND_ITEMS_MISSING );
SetFactFalse( FACT_LARGE_SIZED_OLD_SHIPMENT_WAITING );
@@ -1146,4 +1163,4 @@ RefToDestinationStruct CPostalService::_GetDestination(UINT16 usDestinationID)
}
return DESTINATION(dli);
}
}
+1
View File
@@ -1259,6 +1259,7 @@ void ProcessHistoryTransactionString(STR16 pString, HistoryUnitPtr pHistory)
case HISTORY_SLAY_MYSTERIOUSLY_LEFT:
case HISTORY_WALDO:
case HISTORY_HELICOPTER_REPAIR_STARTED:
case HISTORY_INTERCEPTED_TRANSPORT_GROUP:
//swprintf( pString, pHistoryStrings[ pHistory->ubCode ], pHistory->ubSecondCode );
swprintf( pString, HistoryName[ pHistory->ubCode ].sHistory, pHistory->ubSecondCode );
break;
+1
View File
@@ -113,6 +113,7 @@ enum{
HISTORY_MERC_KILLED_CHARACTER,
HISTORY_WALDO,
HISTORY_HELICOPTER_REPAIR_STARTED,
HISTORY_INTERCEPTED_TRANSPORT_GROUP,
TEXT_NUM_HISTORY
};
+204 -30
View File
@@ -2170,7 +2170,7 @@ void DisplayCharPersonality(INT32 iId, INT32 iSlot)
for ( int i = APPROACH_FRIENDLY; i <= APPROACH_RECRUIT; ++i )
{
mprintf( (INT16)(pPersonnelScreenPoints[loc].x + (iSlot*TEXT_BOX_WIDTH)), (pPersonnelScreenPoints[loc].y + 15), szLaptopStatText[7 + i] );
mprintf( (INT16)(pPersonnelScreenPoints[loc].x + (iSlot*TEXT_BOX_WIDTH)), (pPersonnelScreenPoints[loc].y + 15), szLaptopStatText[LAPTOP_STAT_TEXT_FRIENDLY_APPROACH-1 + i] ); // APPROACH_FRIENDLY is 1 so fix the offset
CHAR16 sStr[200];
swprintf( sStr, L"" );
@@ -2180,7 +2180,7 @@ void DisplayCharPersonality(INT32 iId, INT32 iSlot)
swprintf( sStr, L"%d", val );
FindFontRightCoordinates( (INT16)(pPersonnelScreenPoints[loc].x + (iSlot*TEXT_BOX_WIDTH)), 0, TEXT_BOX_WIDTH - 20, 0, sStr, PERS_FONT, &sX, &sY );
FindFontRightCoordinates( (INT16)(pPersonnelScreenPoints[loc].x + (iSlot*TEXT_BOX_WIDTH)), 0, TEXT_BOX_WIDTH, 0, sStr, PERS_FONT, &sX, &sY );
mprintf( sX, (pPersonnelScreenPoints[loc].y + 15), sStr );
// Add specific region for fast help window
@@ -2205,10 +2205,10 @@ void DisplayCharPersonality(INT32 iId, INT32 iSlot)
if ( (gMercProfiles[pSoldier->ubProfile].ubMiscFlags3 & PROFILE_MISC_FLAG3_GOODGUY) )
{
CHAR16 sStr1[200];
swprintf( sStr1, szLaptopStatText[6] );
swprintf( sStr1, szLaptopStatText[LAPTOP_STAT_TEXT_GOOD_GUY] );
CHAR16 sStr2[200];
swprintf( sStr2, szLaptopStatText[7], pSoldier->GetName( ) );
swprintf( sStr2, szLaptopStatText[LAPTOP_STAT_TEXT_REFUSES_TO_ATTACK_NON_HOSTILES], pSoldier->GetName( ) );
sX = pPersonnelScreenPoints[loc].x + (iSlot*TEXT_BOX_WIDTH);
@@ -2233,15 +2233,189 @@ void DisplayCharPersonality(INT32 iId, INT32 iSlot)
++region;
}
if ( !gGameExternalOptions.bDisableEvolution )
if (gGameExternalOptions.fMercGrowthModifiersEnabled)
{
CHAR16 sStr2[200];
swprintf( sStr2, szLaptopStatText[12 + gMercProfiles[pSoldier->ubProfile].bEvolution], pSoldier->GetName() );
if (gMercProfiles[pSoldier->ubProfile].fRegresses)
{
CHAR16 sStr2[200];
swprintf(sStr2, szLaptopStatText[LAPTOP_STAT_TEXT_MERC_REGRESSES]);
mprintf( (INT16)( pPersonnelScreenPoints[loc].x + ( iSlot*TEXT_BOX_WIDTH ) ), ( pPersonnelScreenPoints[loc].y + 15 ), sStr2 );
mprintf((INT16)(pPersonnelScreenPoints[loc].x + (iSlot * TEXT_BOX_WIDTH)), (pPersonnelScreenPoints[loc].y + 15), sStr2);
++loc;
++region;
++loc;
++region;
}
else
{
const int THRESHOLD_FAST = -3; // this value and below: "fast"
const int THRESHOLD_SLOW = 3; // this value and above: "slow"
int yOffset = 15;
CHAR16 statTxt[200];
// health
{
swprintf(statTxt, szLaptopStatText[LAPTOP_STAT_TEXT_HEALTH_SPEED]);
mprintf((INT16)(pPersonnelScreenPoints[loc].x + (iSlot * TEXT_BOX_WIDTH)), (pPersonnelScreenPoints[loc].y + yOffset), statTxt);
if (gMercProfiles[pSoldier->ubProfile].bGrowthModifierLife <= THRESHOLD_FAST)
swprintf(statTxt, L"%s", szLaptopStatText[LAPTOP_STAT_TEXT_FAST]);
else if (gMercProfiles[pSoldier->ubProfile].bGrowthModifierLife >= THRESHOLD_SLOW)
swprintf(statTxt, L"%s", szLaptopStatText[LAPTOP_STAT_TEXT_SLOW]);
else
swprintf(statTxt, L"%s", szLaptopStatText[LAPTOP_STAT_TEXT_AVERAGE]);
FindFontRightCoordinates((INT16)(pPersonnelScreenPoints[loc].x + (iSlot * TEXT_BOX_WIDTH)), 0, TEXT_BOX_WIDTH, 0, statTxt, PERS_FONT, &sX, &sY);
mprintf(sX, (pPersonnelScreenPoints[loc].y + yOffset), statTxt);
yOffset += 10;
}
// strength
{
swprintf(statTxt, szLaptopStatText[LAPTOP_STAT_TEXT_STRENGTH_SPEED]);
mprintf((INT16)(pPersonnelScreenPoints[loc].x + (iSlot * TEXT_BOX_WIDTH)), (pPersonnelScreenPoints[loc].y + yOffset), statTxt);
if (gMercProfiles[pSoldier->ubProfile].bGrowthModifierStrength <= THRESHOLD_FAST)
swprintf(statTxt, L"%s", szLaptopStatText[LAPTOP_STAT_TEXT_FAST]);
else if (gMercProfiles[pSoldier->ubProfile].bGrowthModifierStrength >= THRESHOLD_SLOW)
swprintf(statTxt, L"%s", szLaptopStatText[LAPTOP_STAT_TEXT_SLOW]);
else
swprintf(statTxt, L"%s", szLaptopStatText[LAPTOP_STAT_TEXT_AVERAGE]);
FindFontRightCoordinates((INT16)(pPersonnelScreenPoints[loc].x + (iSlot * TEXT_BOX_WIDTH)), 0, TEXT_BOX_WIDTH, 0, statTxt, PERS_FONT, &sX, &sY);
mprintf(sX, (pPersonnelScreenPoints[loc].y + yOffset), statTxt);
yOffset += 10;
}
// agility
{
swprintf(statTxt, szLaptopStatText[LAPTOP_STAT_TEXT_AGILITY_SPEED]);
mprintf((INT16)(pPersonnelScreenPoints[loc].x + (iSlot * TEXT_BOX_WIDTH)), (pPersonnelScreenPoints[loc].y + yOffset), statTxt);
if (gMercProfiles[pSoldier->ubProfile].bGrowthModifierAgility <= THRESHOLD_FAST)
swprintf(statTxt, L"%s", szLaptopStatText[LAPTOP_STAT_TEXT_FAST]);
else if (gMercProfiles[pSoldier->ubProfile].bGrowthModifierAgility >= THRESHOLD_SLOW)
swprintf(statTxt, L"%s", szLaptopStatText[LAPTOP_STAT_TEXT_SLOW]);
else
swprintf(statTxt, L"%s", szLaptopStatText[LAPTOP_STAT_TEXT_AVERAGE]);
FindFontRightCoordinates((INT16)(pPersonnelScreenPoints[loc].x + (iSlot * TEXT_BOX_WIDTH)), 0, TEXT_BOX_WIDTH, 0, statTxt, PERS_FONT, &sX, &sY);
mprintf(sX, (pPersonnelScreenPoints[loc].y + yOffset), statTxt);
yOffset += 10;
}
// dexterity
{
swprintf(statTxt, szLaptopStatText[LAPTOP_STAT_TEXT_DEXTERITY_SPEED]);
mprintf((INT16)(pPersonnelScreenPoints[loc].x + (iSlot * TEXT_BOX_WIDTH)), (pPersonnelScreenPoints[loc].y + yOffset), statTxt);
if (gMercProfiles[pSoldier->ubProfile].bGrowthModifierDexterity <= THRESHOLD_FAST)
swprintf(statTxt, L"%s", szLaptopStatText[LAPTOP_STAT_TEXT_FAST]);
else if (gMercProfiles[pSoldier->ubProfile].bGrowthModifierDexterity >= THRESHOLD_SLOW)
swprintf(statTxt, L"%s", szLaptopStatText[LAPTOP_STAT_TEXT_SLOW]);
else
swprintf(statTxt, L"%s", szLaptopStatText[LAPTOP_STAT_TEXT_AVERAGE]);
FindFontRightCoordinates((INT16)(pPersonnelScreenPoints[loc].x + (iSlot * TEXT_BOX_WIDTH)), 0, TEXT_BOX_WIDTH, 0, statTxt, PERS_FONT, &sX, &sY);
mprintf(sX, (pPersonnelScreenPoints[loc].y + yOffset), statTxt);
yOffset += 10;
}
// wisdom
{
swprintf(statTxt, szLaptopStatText[LAPTOP_STAT_TEXT_WISDOM_SPEED]);
mprintf((INT16)(pPersonnelScreenPoints[loc].x + (iSlot * TEXT_BOX_WIDTH)), (pPersonnelScreenPoints[loc].y + yOffset), statTxt);
if (gMercProfiles[pSoldier->ubProfile].bGrowthModifierWisdom <= THRESHOLD_FAST)
swprintf(statTxt, L"%s", szLaptopStatText[LAPTOP_STAT_TEXT_FAST]);
else if (gMercProfiles[pSoldier->ubProfile].bGrowthModifierWisdom >= THRESHOLD_SLOW)
swprintf(statTxt, L"%s", szLaptopStatText[LAPTOP_STAT_TEXT_SLOW]);
else
swprintf(statTxt, L"%s", szLaptopStatText[LAPTOP_STAT_TEXT_AVERAGE]);
FindFontRightCoordinates((INT16)(pPersonnelScreenPoints[loc].x + (iSlot * TEXT_BOX_WIDTH)), 0, TEXT_BOX_WIDTH, 0, statTxt, PERS_FONT, &sX, &sY);
mprintf(sX, (pPersonnelScreenPoints[loc].y + yOffset), statTxt);
yOffset += 10;
}
// marksmanship
{
swprintf(statTxt, szLaptopStatText[LAPTOP_STAT_TEXT_MARKSMANSHIP_SPEED]);
mprintf((INT16)(pPersonnelScreenPoints[loc].x + (iSlot * TEXT_BOX_WIDTH)), (pPersonnelScreenPoints[loc].y + yOffset), statTxt);
if (gMercProfiles[pSoldier->ubProfile].bGrowthModifierMarksmanship <= THRESHOLD_FAST)
swprintf(statTxt, L"%s", szLaptopStatText[LAPTOP_STAT_TEXT_FAST]);
else if (gMercProfiles[pSoldier->ubProfile].bGrowthModifierMarksmanship >= THRESHOLD_SLOW)
swprintf(statTxt, L"%s", szLaptopStatText[LAPTOP_STAT_TEXT_SLOW]);
else
swprintf(statTxt, L"%s", szLaptopStatText[LAPTOP_STAT_TEXT_AVERAGE]);
FindFontRightCoordinates((INT16)(pPersonnelScreenPoints[loc].x + (iSlot * TEXT_BOX_WIDTH)), 0, TEXT_BOX_WIDTH, 0, statTxt, PERS_FONT, &sX, &sY);
mprintf(sX, (pPersonnelScreenPoints[loc].y + yOffset), statTxt);
yOffset += 10;
}
// explosives
{
swprintf(statTxt, szLaptopStatText[LAPTOP_STAT_TEXT_EXPLOSIVES_SPEED]);
mprintf((INT16)(pPersonnelScreenPoints[loc].x + (iSlot * TEXT_BOX_WIDTH)), (pPersonnelScreenPoints[loc].y + yOffset), statTxt);
if (gMercProfiles[pSoldier->ubProfile].bGrowthModifierExplosive <= THRESHOLD_FAST)
swprintf(statTxt, L"%s", szLaptopStatText[LAPTOP_STAT_TEXT_FAST]);
else if (gMercProfiles[pSoldier->ubProfile].bGrowthModifierExplosive >= THRESHOLD_SLOW)
swprintf(statTxt, L"%s", szLaptopStatText[LAPTOP_STAT_TEXT_SLOW]);
else
swprintf(statTxt, L"%s", szLaptopStatText[LAPTOP_STAT_TEXT_AVERAGE]);
FindFontRightCoordinates((INT16)(pPersonnelScreenPoints[loc].x + (iSlot * TEXT_BOX_WIDTH)), 0, TEXT_BOX_WIDTH, 0, statTxt, PERS_FONT, &sX, &sY);
mprintf(sX, (pPersonnelScreenPoints[loc].y + yOffset), statTxt);
yOffset += 10;
}
// leadership
{
swprintf(statTxt, szLaptopStatText[LAPTOP_STAT_TEXT_LEADERSHIP_SPEED]);
mprintf((INT16)(pPersonnelScreenPoints[loc].x + (iSlot * TEXT_BOX_WIDTH)), (pPersonnelScreenPoints[loc].y + yOffset), statTxt);
if (gMercProfiles[pSoldier->ubProfile].bGrowthModifierLeadership <= THRESHOLD_FAST)
swprintf(statTxt, L"%s", szLaptopStatText[LAPTOP_STAT_TEXT_FAST]);
else if (gMercProfiles[pSoldier->ubProfile].bGrowthModifierLeadership >= THRESHOLD_SLOW)
swprintf(statTxt, L"%s", szLaptopStatText[LAPTOP_STAT_TEXT_SLOW]);
else
swprintf(statTxt, L"%s", szLaptopStatText[LAPTOP_STAT_TEXT_AVERAGE]);
FindFontRightCoordinates((INT16)(pPersonnelScreenPoints[loc].x + (iSlot * TEXT_BOX_WIDTH)), 0, TEXT_BOX_WIDTH, 0, statTxt, PERS_FONT, &sX, &sY);
mprintf(sX, (pPersonnelScreenPoints[loc].y + yOffset), statTxt);
yOffset += 10;
}
// medical
{
swprintf(statTxt, szLaptopStatText[LAPTOP_STAT_TEXT_MEDICAL_SPEED]);
mprintf((INT16)(pPersonnelScreenPoints[loc].x + (iSlot * TEXT_BOX_WIDTH)), (pPersonnelScreenPoints[loc].y + yOffset), statTxt);
if (gMercProfiles[pSoldier->ubProfile].bGrowthModifierMedical <= THRESHOLD_FAST)
swprintf(statTxt, L"%s", szLaptopStatText[LAPTOP_STAT_TEXT_FAST]);
else if (gMercProfiles[pSoldier->ubProfile].bGrowthModifierMedical >= THRESHOLD_SLOW)
swprintf(statTxt, L"%s", szLaptopStatText[LAPTOP_STAT_TEXT_SLOW]);
else
swprintf(statTxt, L"%s", szLaptopStatText[LAPTOP_STAT_TEXT_AVERAGE]);
FindFontRightCoordinates((INT16)(pPersonnelScreenPoints[loc].x + (iSlot * TEXT_BOX_WIDTH)), 0, TEXT_BOX_WIDTH, 0, statTxt, PERS_FONT, &sX, &sY);
mprintf(sX, (pPersonnelScreenPoints[loc].y + yOffset), statTxt);
yOffset += 10;
}
// mechanical
{
swprintf(statTxt, szLaptopStatText[LAPTOP_STAT_TEXT_MECHANICAL_SPEED]);
mprintf((INT16)(pPersonnelScreenPoints[loc].x + (iSlot * TEXT_BOX_WIDTH)), (pPersonnelScreenPoints[loc].y + yOffset), statTxt);
if (gMercProfiles[pSoldier->ubProfile].bGrowthModifierMechanical <= THRESHOLD_FAST)
swprintf(statTxt, L"%s", szLaptopStatText[LAPTOP_STAT_TEXT_FAST]);
else if (gMercProfiles[pSoldier->ubProfile].bGrowthModifierMechanical >= THRESHOLD_SLOW)
swprintf(statTxt, L"%s", szLaptopStatText[LAPTOP_STAT_TEXT_SLOW]);
else
swprintf(statTxt, L"%s", szLaptopStatText[LAPTOP_STAT_TEXT_AVERAGE]);
FindFontRightCoordinates((INT16)(pPersonnelScreenPoints[loc].x + (iSlot * TEXT_BOX_WIDTH)), 0, TEXT_BOX_WIDTH, 0, statTxt, PERS_FONT, &sX, &sY);
mprintf(sX, (pPersonnelScreenPoints[loc].y + yOffset), statTxt);
yOffset += 10;
}
// exp level
{
swprintf(statTxt, szLaptopStatText[LAPTOP_STAT_TEXT_EXPERIENCE_SPEED]);
mprintf((INT16)(pPersonnelScreenPoints[loc].x + (iSlot * TEXT_BOX_WIDTH)), (pPersonnelScreenPoints[loc].y + yOffset), statTxt);
if (gMercProfiles[pSoldier->ubProfile].bGrowthModifierExpLevel <= THRESHOLD_FAST)
swprintf(statTxt, L"%s", szLaptopStatText[LAPTOP_STAT_TEXT_FAST]);
else if (gMercProfiles[pSoldier->ubProfile].bGrowthModifierExpLevel >= THRESHOLD_SLOW)
swprintf(statTxt, L"%s", szLaptopStatText[LAPTOP_STAT_TEXT_SLOW]);
else
swprintf(statTxt, L"%s", szLaptopStatText[LAPTOP_STAT_TEXT_AVERAGE]);
FindFontRightCoordinates((INT16)(pPersonnelScreenPoints[loc].x + (iSlot * TEXT_BOX_WIDTH)), 0, TEXT_BOX_WIDTH, 0, statTxt, PERS_FONT, &sX, &sY);
mprintf(sX, (pPersonnelScreenPoints[loc].y + yOffset), statTxt);
}
}
}
}
@@ -7991,6 +8165,21 @@ void AssignPersonnelSkillTraitHelpText( UINT8 ubTraitNumber, BOOLEAN fExpertLeve
wcscat( apStr, atStr );
}
if( gSkillTraitValues.ubTHAPsNeededToThrowGrenadesReduction != 0 )
{
swprintf( atStr, gzIMPMinorTraitsHelpTextsThrowing[10], gSkillTraitValues.ubTHAPsNeededToThrowGrenadesReduction, sSpecialCharacters[0]);
wcscat( apStr, atStr );
}
if( gSkillTraitValues.ubTHMaxRangeToThrowGrenades != 0 )
{
swprintf( atStr, gzIMPMinorTraitsHelpTextsThrowing[11], gSkillTraitValues.ubTHMaxRangeToThrowGrenades, sSpecialCharacters[0]);
wcscat( apStr, atStr );
}
if( gSkillTraitValues.ubTHCtHWhenThrowingGrenades != 0 )
{
swprintf( atStr, gzIMPMinorTraitsHelpTextsThrowing[12], gSkillTraitValues.ubTHCtHWhenThrowingGrenades, sSpecialCharacters[0]);
wcscat( apStr, atStr );
}
break;
}
case NIGHT_OPS_NT:
@@ -8096,44 +8285,29 @@ void AssignPersonnelSkillTraitHelpText( UINT8 ubTraitNumber, BOOLEAN fExpertLeve
case DEMOLITIONS_NT:
{
swprintf( apStr, L"" );
if( gSkillTraitValues.ubDEAPsNeededToThrowGrenadesReduction != 0 )
{
swprintf( atStr, gzIMPMinorTraitsHelpTextsDemolitions[0], gSkillTraitValues.ubDEAPsNeededToThrowGrenadesReduction, sSpecialCharacters[0]);
wcscat( apStr, atStr );
}
if( gSkillTraitValues.ubDEMaxRangeToThrowGrenades != 0 )
{
swprintf( atStr, gzIMPMinorTraitsHelpTextsDemolitions[1], gSkillTraitValues.ubDEMaxRangeToThrowGrenades, sSpecialCharacters[0]);
wcscat( apStr, atStr );
}
if( gSkillTraitValues.ubDECtHWhenThrowingGrenades != 0 )
{
swprintf( atStr, gzIMPMinorTraitsHelpTextsDemolitions[2], gSkillTraitValues.ubDECtHWhenThrowingGrenades, sSpecialCharacters[0]);
wcscat( apStr, atStr );
}
if( gSkillTraitValues.ubDEDamageOfBombsAndMines != 0 )
{
swprintf( atStr, gzIMPMinorTraitsHelpTextsDemolitions[3], gSkillTraitValues.ubDEDamageOfBombsAndMines, sSpecialCharacters[0]);
swprintf( atStr, gzIMPMinorTraitsHelpTextsDemolitions[0], gSkillTraitValues.ubDEDamageOfBombsAndMines, sSpecialCharacters[0]);
wcscat( apStr, atStr );
}
if( gSkillTraitValues.ubDEAttachDetonatorCheckBonus != 0 )
{
swprintf( atStr, gzIMPMinorTraitsHelpTextsDemolitions[4], gSkillTraitValues.ubDEAttachDetonatorCheckBonus, sSpecialCharacters[0]);
swprintf( atStr, gzIMPMinorTraitsHelpTextsDemolitions[1], gSkillTraitValues.ubDEAttachDetonatorCheckBonus, sSpecialCharacters[0]);
wcscat( apStr, atStr );
}
if( gSkillTraitValues.ubDEPlantAndRemoveBombCheckBonus != 0 )
{
swprintf( atStr, gzIMPMinorTraitsHelpTextsDemolitions[5], gSkillTraitValues.ubDEPlantAndRemoveBombCheckBonus, sSpecialCharacters[0]);
swprintf( atStr, gzIMPMinorTraitsHelpTextsDemolitions[2], gSkillTraitValues.ubDEPlantAndRemoveBombCheckBonus, sSpecialCharacters[0]);
wcscat( apStr, atStr );
}
if( gSkillTraitValues.ubDEPlacedBombLevelBonus != 0 )
{
swprintf( atStr, gzIMPMinorTraitsHelpTextsDemolitions[6], gSkillTraitValues.ubDEPlacedBombLevelBonus);
swprintf( atStr, gzIMPMinorTraitsHelpTextsDemolitions[3], gSkillTraitValues.ubDEPlacedBombLevelBonus);
wcscat( apStr, atStr );
}
if( gSkillTraitValues.ubDEShapedChargeDamageMultiplier != 0 )
{
swprintf( atStr, gzIMPMinorTraitsHelpTextsDemolitions[7], gSkillTraitValues.ubDEShapedChargeDamageMultiplier);
swprintf( atStr, gzIMPMinorTraitsHelpTextsDemolitions[4], gSkillTraitValues.ubDEShapedChargeDamageMultiplier);
wcscat( apStr, atStr );
}
break;
+94 -33
View File
@@ -23,6 +23,7 @@ extern BOOLEAN gfSchedulesHosed;
#include "Ja25 Strategic Ai.h"
#endif
UINT8 gubLastLoadingScreenID = LOADINGSCREEN_NOTHING;
FLOAT fLoadingScreenAspectRatio;
//BOOLEAN bShowSmallImage = FALSE;
SECTOR_LOADSCREENS gSectorLoadscreens[MAX_SECTOR_LOADSCREENS];
@@ -343,6 +344,62 @@ static void BuildLoadscreenFilename(std::string& dst, const char* path, int reso
dst.append(".sti");
}
std::string GetResolutionSuffix(SCREEN_RESOLUTION resolution)
{
switch (resolution)
{
case _960x540: return "_960x540";
case _800x600: return "_800x600";
case _1024x600: return "_1024x600";
case _1280x720: return "_1280x720";
case _1024x768: return "_1024x768";
case _1280x768: return "_1280x768";
case _1360x768: return "_1360x768";
case _1366x768: return "_1366x768";
case _1280x800: return "_1280x800";
case _1440x900: return "_1440x900";
case _1600x900: return "_1600x900";
case _1280x960: return "_1280x960";
case _1440x960: return "_1440x960";
case _1770x1000: return "_1770x1000";
case _1280x1024: return "_1280x1024";
case _1360x1024: return "_1360x1024";
case _1600x1024: return "_1600x1024";
case _1440x1050: return "_1440x1050";
case _1680x1050: return "_1680x1050";
case _1920x1080: return "_1920x1080";
case _1600x1200: return "_1600x1200";
case _1920x1200: return "_1920x1200";
case _2560x1440: return "_2560x1440";
case _2560x1600: return "_2560x1600";
default: return "";
}
}
std::string FindBestFittingLoadscreenFilename(const std::string& baseName, SCREEN_RESOLUTION resolution)
{
for (SCREEN_RESOLUTION res = resolution; res <= _2560x1600; res = (SCREEN_RESOLUTION)(res + 1))
{
std::string fileName = baseName + GetResolutionSuffix(res);
if (FileExists((CHAR8*)((fileName + ".png").c_str())))
{
return fileName + ".png";
}
if (FileExists((CHAR8*)((fileName + ".sti").c_str())))
{
return fileName + ".sti";
}
}
if (FileExists((CHAR8*)((baseName + ".png").c_str())))
{
return baseName + ".png";
}
return baseName + ".sti";
}
//sets up the loadscreen with specified ID, and draws it to the FRAME_BUFFER,
//and refreshing the screen with it.
void DisplayLoadScreenWithID( UINT8 ubLoadScreenID )
@@ -420,27 +477,8 @@ void DisplayLoadScreenWithID( UINT8 ubLoadScreenID )
}
}
std::string strImage;
BuildLoadscreenFilename(strImage, imagePath.c_str(), 0, imageFormat.c_str());
strImage.copy(vs_desc.ImageFile, sizeof(vs_desc.ImageFile)-1);
if ( !FileExists(vs_desc.ImageFile) )
{
std::string strImage;
BuildLoadscreenFilename(strImage, imagePath.c_str(), 0, "png");
strImage.copy(vs_desc.ImageFile, sizeof(vs_desc.ImageFile) - 1);
if (!FileExists(vs_desc.ImageFile))
{
std::string strImage("LOADSCREENS\\");
BuildLoadscreenFilename(strImage, LoadScreenNames[1], 0, imageFormat.c_str());
strImage.copy(vs_desc.ImageFile, sizeof(vs_desc.ImageFile) - 1);
}
}
std::string strImage = FindBestFittingLoadscreenFilename(imagePath, (SCREEN_RESOLUTION)iResolution);
strImage.copy(vs_desc.ImageFile, sizeof(vs_desc.ImageFile) - 1);
}
else
{
@@ -475,18 +513,41 @@ void DisplayLoadScreenWithID( UINT8 ubLoadScreenID )
//Blit the background image
GetVideoSurface(&hVSurface, uiLoadScreen);
// Stretch the background image
SrcRect.iLeft = 0;
SrcRect.iTop = 0;
SrcRect.iRight = hVSurface->usWidth;
SrcRect.iBottom = hVSurface->usHeight;
DstRect.iLeft = 0;
DstRect.iTop = 0;
DstRect.iRight = SCREEN_WIDTH;
DstRect.iBottom = SCREEN_HEIGHT;
fLoadingScreenAspectRatio = (FLOAT)hVSurface->usWidth / (FLOAT)hVSurface->usHeight;
FLOAT fScreenAspectRatio = (FLOAT)SCREEN_WIDTH / (FLOAT)SCREEN_HEIGHT;
if (gGameExternalOptions.ubLoadscreenStretchMode == 1 ||
(gGameExternalOptions.ubLoadscreenStretchMode == 2 && fLoadingScreenAspectRatio > fScreenAspectRatio))
{
// match height, preserve aspect ratio
INT32 iCalculatedWidth = (INT32)(SCREEN_HEIGHT * fLoadingScreenAspectRatio + 0.5f);
SrcRect.iLeft = 0;
SrcRect.iTop = 0;
SrcRect.iRight = hVSurface->usWidth;
SrcRect.iBottom = hVSurface->usHeight;
DstRect.iLeft = (SCREEN_WIDTH - iCalculatedWidth) / 2;
DstRect.iTop = 0;
DstRect.iRight = SCREEN_WIDTH - ((SCREEN_WIDTH - iCalculatedWidth) / 2);
DstRect.iBottom = SCREEN_HEIGHT;
}
else
{
// vanilla (stretch to fit)
// Stretch the background image
SrcRect.iLeft = 0;
SrcRect.iTop = 0;
SrcRect.iRight = hVSurface->usWidth;
SrcRect.iBottom = hVSurface->usHeight;
DstRect.iLeft = 0;
DstRect.iTop = 0;
DstRect.iRight = SCREEN_WIDTH;
DstRect.iBottom = SCREEN_HEIGHT;
}
BltStretchVideoSurface( FRAME_BUFFER, uiLoadScreen, 0, 0, 0, &SrcRect, &DstRect );
DeleteVideoSurfaceFromIndex( uiLoadScreen );
+2
View File
@@ -84,6 +84,8 @@ enum
//For use by the game loader, before it can possibly know the situation.
extern UINT8 gubLastLoadingScreenID;
extern FLOAT fLoadingScreenAspectRatio;
//returns the UINT8 ID for the specified sector.
UINT8 GetLoadScreenID( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ );
+3
View File
@@ -855,6 +855,9 @@ void RenderMainMenu()
DrawTextToScreen( L"BLOCKFONTNARROW: ÄÀÁÂÇËÈÉÊÏÖÒÓÔÜÙÚÛäàáâçëèéêïöòóôüùúûÌÎìî"/*gzCopyrightText[ 0 ]*/, 0, 445, 640, BLOCKFONTNARROW, FONT_MCOLOR_WHITE, FONT_MCOLOR_BLACK, FALSE, LEFT_JUSTIFIED );
DrawTextToScreen( L"FONT14HUMANIST: ÄÀÁÂÇËÈÉÊÏÖÒÓÔÜÙÚÛäàáâçëèéêïöòóôüùúûÌÎìî"/*gzCopyrightText[ 0 ]*/, 0, 465, 640, FONT14HUMANIST, FONT_MCOLOR_WHITE, FONT_MCOLOR_BLACK, FALSE, LEFT_JUSTIFIED );
#else
CHAR16 text[128];
swprintf(text, L"%s: %s %S %s", pMessageStrings[ MSG_VERSION ], zProductLabel, czVersionString, zBuildInformation );
DrawTextToScreen( text, 10, 10, SCREEN_WIDTH, TINYFONT1, FONT_MCOLOR_WHITE, FONT_MCOLOR_BLACK, FALSE, LEFT_JUSTIFIED );
DrawTextToScreen( gzCopyrightText[ 0 ], 0, SCREEN_HEIGHT - 20, SCREEN_WIDTH, FONT10ARIAL, FONT_MCOLOR_WHITE, FONT_MCOLOR_BLACK, FALSE, CENTER_JUSTIFIED );
#endif
+130 -11
View File
@@ -1294,7 +1294,16 @@ BOOLEAN MERCPROFILESTRUCT::Load(HWFILE hFile, bool forceLoadOldVersion, bool for
numBytesRead = ReadFieldByField( hFile, &this->bSex, sizeof(this->bSex), sizeof(INT8), numBytesRead);
numBytesRead = ReadFieldByField( hFile, &this->bArmourAttractiveness, sizeof(this->bArmourAttractiveness), sizeof(INT8), numBytesRead);
numBytesRead = ReadFieldByField( hFile, &this->ubMiscFlags2, sizeof(this->ubMiscFlags2), sizeof(UINT8), numBytesRead);
numBytesRead = ReadFieldByField( hFile, &this->bEvolution, sizeof(this->bEvolution), sizeof(INT8), numBytesRead);
if (guiCurrentSaveGameVersion < GROWTH_MODIFIERS)
{
numBytesRead = ReadFieldByField( hFile, &this->fRegresses, sizeof(this->fRegresses), sizeof(INT8), numBytesRead);
// convert old evolution to regresses boolean
this->fRegresses = this->fRegresses == 2 ? TRUE : FALSE; // 2 == CharacterEvolution::DEVOLVES
}
else
{
numBytesRead = ReadFieldByField( hFile, &this->fRegresses, sizeof(this->fRegresses), sizeof(INT8), numBytesRead);
}
numBytesRead = ReadFieldByField( hFile, &this->ubMiscFlags, sizeof(this->ubMiscFlags), sizeof(UINT8), numBytesRead);
numBytesRead = ReadFieldByField( hFile, &this->bSexist, sizeof(this->bSexist), sizeof(UINT8), numBytesRead);
numBytesRead = ReadFieldByField( hFile, &this->bLearnToHate, sizeof(this->bLearnToHate), sizeof(UINT8), numBytesRead);
@@ -1637,6 +1646,70 @@ BOOLEAN MERCPROFILESTRUCT::Load(HWFILE hFile, bool forceLoadOldVersion, bool for
return( FALSE );
}
}
// rftr: growth modifiers
if (guiCurrentSaveGameVersion >= GROWTH_MODIFIERS)
{
if (!FileRead(hFile, &this->bGrowthModifierLife, sizeof(INT8), &uiNumBytesRead))
{
return(FALSE);
}
if ( !FileRead( hFile, &this->bGrowthModifierStrength, sizeof(INT8), &uiNumBytesRead) )
{
return( FALSE );
}
if ( !FileRead( hFile, &this->bGrowthModifierAgility, sizeof(INT8), &uiNumBytesRead) )
{
return( FALSE );
}
if ( !FileRead( hFile, &this->bGrowthModifierDexterity, sizeof(INT8), &uiNumBytesRead) )
{
return( FALSE );
}
if ( !FileRead( hFile, &this->bGrowthModifierWisdom, sizeof(INT8), &uiNumBytesRead) )
{
return( FALSE );
}
if ( !FileRead( hFile, &this->bGrowthModifierMarksmanship, sizeof(INT8), &uiNumBytesRead) )
{
return( FALSE );
}
if ( !FileRead( hFile, &this->bGrowthModifierExplosive, sizeof(INT8), &uiNumBytesRead) )
{
return( FALSE );
}
if ( !FileRead( hFile, &this->bGrowthModifierLeadership, sizeof(INT8), &uiNumBytesRead) )
{
return( FALSE );
}
if ( !FileRead( hFile, &this->bGrowthModifierMedical, sizeof(INT8), &uiNumBytesRead) )
{
return( FALSE );
}
if ( !FileRead( hFile, &this->bGrowthModifierMechanical, sizeof(INT8), &uiNumBytesRead) )
{
return( FALSE );
}
if ( !FileRead( hFile, &this->bGrowthModifierExpLevel, sizeof(INT8), &uiNumBytesRead) )
{
return( FALSE );
}
}
else
{
// zero out growth modifiers for upgrading savegames
this->bGrowthModifierLife = 0;
this->bGrowthModifierStrength = 0;
this->bGrowthModifierAgility = 0;
this->bGrowthModifierDexterity = 0;
this->bGrowthModifierWisdom = 0;
this->bGrowthModifierMarksmanship = 0;
this->bGrowthModifierExplosive = 0;
this->bGrowthModifierLeadership = 0;
this->bGrowthModifierMedical = 0;
this->bGrowthModifierMechanical = 0;
this->bGrowthModifierExpLevel = 0;
}
}
if ( this->uiProfileChecksum != this->GetChecksum() )
@@ -1753,6 +1826,52 @@ BOOLEAN MERCPROFILESTRUCT::Save(HWFILE hFile)
{
return( FALSE );
}
// rftr: growth modifiers
if (!FileWrite(hFile, &this->bGrowthModifierLife, sizeof(INT8), &uiNumBytesWritten))
{
return(FALSE);
}
if ( !FileWrite( hFile, &this->bGrowthModifierStrength, sizeof(INT8), &uiNumBytesWritten) )
{
return( FALSE );
}
if ( !FileWrite( hFile, &this->bGrowthModifierAgility, sizeof(INT8), &uiNumBytesWritten) )
{
return( FALSE );
}
if ( !FileWrite( hFile, &this->bGrowthModifierDexterity, sizeof(INT8), &uiNumBytesWritten) )
{
return( FALSE );
}
if ( !FileWrite( hFile, &this->bGrowthModifierWisdom, sizeof(INT8), &uiNumBytesWritten) )
{
return( FALSE );
}
if ( !FileWrite( hFile, &this->bGrowthModifierMarksmanship, sizeof(INT8), &uiNumBytesWritten) )
{
return( FALSE );
}
if ( !FileWrite( hFile, &this->bGrowthModifierExplosive, sizeof(INT8), &uiNumBytesWritten) )
{
return( FALSE );
}
if ( !FileWrite( hFile, &this->bGrowthModifierLeadership, sizeof(INT8), &uiNumBytesWritten) )
{
return( FALSE );
}
if ( !FileWrite( hFile, &this->bGrowthModifierMedical, sizeof(INT8), &uiNumBytesWritten) )
{
return( FALSE );
}
if ( !FileWrite( hFile, &this->bGrowthModifierMechanical, sizeof(INT8), &uiNumBytesWritten) )
{
return( FALSE );
}
if ( !FileWrite( hFile, &this->bGrowthModifierExpLevel, sizeof(INT8), &uiNumBytesWritten) )
{
return( FALSE );
}
return TRUE;
}
@@ -4926,7 +5045,7 @@ BOOLEAN LoadSavedGame( int ubSavedGameID )
}
if ((gGameOptions.ubSquadSize == 8 && iResolution < _800x600) ||
(gGameOptions.ubSquadSize == 10 && iResolution < _1024x768))
(gGameOptions.ubSquadSize == 10 && iResolution < _1280x720))
{
FileClose( hFile );
return(FALSE);
@@ -6694,15 +6813,6 @@ BOOLEAN LoadSavedGame( int ubSavedGameID )
//Reset the Ai Timer clock
giRTAILastUpdateTime = 0;
//if we are in tactical
if( guiScreenToGotoAfterLoadingSavedGame == GAME_SCREEN )
{
//Initialize the current panel
InitializeCurrentPanel( );
SelectSoldier( gusSelectedSoldier, FALSE, TRUE );
}
uiRelEndPerc += 1;
SetRelativeStartAndEndPercentage( 0, uiRelStartPerc, uiRelEndPerc, L"Final Checks..." );
RenderProgressBar( 0, 100 );
@@ -6831,6 +6941,15 @@ BOOLEAN LoadSavedGame( int ubSavedGameID )
RemoveLoadingScreenProgressBar();
//if we are in tactical
if (guiScreenToGotoAfterLoadingSavedGame == GAME_SCREEN)
{
//Initialize the current panel
InitializeCurrentPanel();
SelectSoldier(gusSelectedSoldier, FALSE, TRUE);
}
// sevenfm: reset sound map
ResetSoundMap();
+1 -1
View File
@@ -2512,7 +2512,7 @@ void DoneFadeOutForSaveLoadScreen( void )
NextLoopCheckForEnoughFreeHardDriveSpace();
}
else if ((gGameOptions.ubSquadSize == 8 && iResolution < _800x600) ||
(gGameOptions.ubSquadSize == 10 && iResolution < _1024x768))
(gGameOptions.ubSquadSize == 10 && iResolution < _1280x720))
{
DoSaveLoadMessageBox( MSG_BOX_BASIC_STYLE, zSaveLoadText[SLG_SQUAD_SIZE_RES_ERROR], SAVE_LOAD_SCREEN, MSG_BOX_FLAG_OK, FailedLoadingGameCallBack );
NextLoopCheckForEnoughFreeHardDriveSpace();
+1
View File
@@ -4,6 +4,7 @@ int iResolution; // INI file
int iPlayIntro;
int iDisableMouseScrolling;
int iUseWinFonts;
float fTooltipScaleFactor;
/* WANNE, Sgt.Kolja
* INI file (Windowed or Fullscreen)
* REPLACE all defines WINDOWED_MODE with this variable
+5
View File
@@ -43,6 +43,9 @@
#endif
#include "GameSettings.h"
#include "SaveLoadGame.h"
#include "Font.h"
#include "GameVersion.h"
#include "Text.h"
#include "debug_util.h"
@@ -408,6 +411,8 @@ void _FailMessage(const char* message, unsigned lineNum, const char * functionNa
sgp::dumpStackTrace(message);
mprintf( 10, 10, L"%s: %s %S %s", pMessageStrings[ MSG_VERSION ], zProductLabel, czVersionString, zBuildInformation );
std::stringstream basicInformation;
basicInformation << "Assertion Failure [Line " << lineNum;
if (functionName) {
+1 -1
View File
@@ -721,7 +721,7 @@ UINT16 GetFontHeight(INT32 FontNum)
MapFont = WinFontMap[FontNum];
if (FontNum != -1)
{
return (GetWinFontHeight(L"A", MapFont));
return (GetWinFontHeight(MapFont));
}
}
return((UINT16)GetHeight(FontObjs[FontNum], 0));
+51 -60
View File
@@ -26,11 +26,6 @@
#include <vfs/Tools/vfs_property_container.h>
INT32 FindFreeWinFont( void );
BOOLEAN gfEnumSucceed = FALSE;
#ifdef CHINESE
#define DEC_INTERNAL_LEADING
#endif
// Private struct not to be exported
// to other modules
@@ -41,15 +36,14 @@ typedef struct
COLORVAL ForeColor;
COLORVAL BackColor;
UINT8 Height;
UINT8 Width[0x80];
#ifdef DEC_INTERNAL_LEADING
UINT8 InternalLeading;
#ifdef CHINESE
UINT8 Width[0x80];
#endif
} HWINFONT;
LOGFONT gLogFont;
LONG gWinFontAdjust;
HWINFONT WinFonts[WIN_LASTFONT];
HWINFONT WinFonts[WIN_LASTFONT + 2]; // extra space for the tooltip fonts
INT32 WinFontMap[MAX_WINFONTMAP];
@@ -80,6 +74,9 @@ struct {
{"HugeFont", {-19, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY, VARIABLE_PITCH | FF_DONTCARE, "ja2font3"}, FROMRGB(0, 255, 0)}
};
INT32 TOOLTIP_IFONT = -1;
INT32 TOOLTIP_IFONT_BOLD = -1;
void Convert16BitStringTo8Bit( CHAR8 *dst, CHAR16 *src )
{
//hope 'dst' is big enough
@@ -288,6 +285,31 @@ void ShutdownWinFonts( )
{DeleteWinFont(i);}
}
void InitTooltipFonts()
{
LOGFONT logFont = { -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE,
DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY, VARIABLE_PITCH | FF_DONTCARE,
"Arial"
};
logFont.lfHeight = logFont.lfHeight * fTooltipScaleFactor;
LOGFONT boldTooltipLogFont = logFont;
boldTooltipLogFont.lfWeight = FW_BOLD;
TOOLTIP_IFONT = CreateWinFont(logFont);
TOOLTIP_IFONT_BOLD = CreateWinFont(boldTooltipLogFont);
COLORVAL regularColor = FROMRGB(201, 197, 143);
COLORVAL boldColor = FROMRGB(223, 176, 1);
SetWinFontForeColor(TOOLTIP_IFONT, &regularColor);
SetWinFontForeColor(TOOLTIP_IFONT_BOLD, &boldColor);
}
void ShutdownTooltipFonts()
{
ShutdownWinFonts();
}
INT32 FindFreeWinFont( void )
{
INT32 iCount;
@@ -306,7 +328,7 @@ INT32 FindFreeWinFont( void )
HWINFONT *GetWinFont( INT32 iFont )
{
if ( iFont == -1 || iFont >=WIN_LASTFONT)
if (iFont == -1 || iFont >= sizeof(WinFonts) )
{
return( NULL );
}
@@ -347,8 +369,10 @@ INT32 CreateWinFont( LOGFONT &logfont )
WinFonts[ iFont ].hFont = hFont;
HDC hdc = GetDC(NULL);
SelectObject(hdc, hFont);
#ifdef CHINESE
SIZE RectSize;
SelectObject(hdc, hFont );
wchar_t str[2]=L"\1";
for (int i = 1; i<0x80; i++)
{
@@ -359,12 +383,12 @@ INT32 CreateWinFont( LOGFONT &logfont )
str[0] = L'';
GetTextExtentPoint32W( hdc, str, 1, &RectSize );
WinFonts[iFont].Width[0] = (UINT8)RectSize.cx;
#endif
TEXTMETRIC tm;
GetTextMetrics(hdc, &tm);
WinFonts[ iFont ].Height = (UINT8)tm.tmAscent;
#ifdef DEC_INTERNAL_LEADING
WinFonts[ iFont ].InternalLeading = (UINT8)tm.tmInternalLeading;
#endif
ReleaseDC(NULL, hdc);
return( iFont );
@@ -444,12 +468,10 @@ void PrintWinFont( UINT32 uiDestBuf, INT32 iFont, INT32 x, INT32 y, STR16 pFontS
SetBkMode(hdc, TRANSPARENT);
SetTextAlign(hdc, TA_TOP|TA_LEFT);
#ifdef DEC_INTERNAL_LEADING
if (y - pWinFont->InternalLeading >=0)
{
y -= pWinFont->InternalLeading;
}
#endif
TextOutW( hdc, x, y, string, len );
IDirectDrawSurface2_ReleaseDC( pDDSurface, hdc );
@@ -458,17 +480,10 @@ void PrintWinFont( UINT32 uiDestBuf, INT32 iFont, INT32 x, INT32 y, STR16 pFontS
INT16 WinFontStringPixLength( STR16 string2, INT32 iFont )
{
HWINFONT *pWinFont;
#ifndef CHINESE
HDC hdc;
SIZE RectSize;
#endif
HWINFONT *pWinFont;
pWinFont = GetWinFont( iFont );
if ( pWinFont == NULL )
{
return( 0 );
}
if (pWinFont == NULL) return(0);
#ifdef CHINESE
wchar_t *p=string2;
@@ -486,7 +501,9 @@ INT16 WinFontStringPixLength( STR16 string2, INT32 iFont )
}
return size;
#else
hdc = GetDC(NULL);
SIZE RectSize;
HDC hdc = GetDC(NULL);
SelectObject(hdc, pWinFont->hFont );
GetTextExtentPoint32W( hdc, string2, lstrlenW(string2), &RectSize );
ReleaseDC(NULL, hdc);
@@ -496,44 +513,18 @@ INT16 WinFontStringPixLength( STR16 string2, INT32 iFont )
}
INT16 GetWinFontHeight( STR16 string2, INT32 iFont )
INT16 GetWinFontHeight(INT32 iFont)
{
HWINFONT *pWinFont;
// HDC hdc;
// SIZE RectSize;
HWINFONT* pWinFont;
pWinFont = GetWinFont( iFont );
pWinFont = GetWinFont(iFont);
if ( pWinFont == NULL )
{
return( 0 );
}
else
{
if (pWinFont == NULL) return(0);
#ifdef CHINESE //zwwooooo: Correct tactical interface font height to fixed Chinese characters smearing bug
if (iFont==WIN_TINYFONT1 || iFont==WIN_SMALLFONT1 || iFont==WIN_14POINTARIAL) return pWinFont->Height+2;
if (iFont == WinFontMap[TINYFONT1] || iFont == WinFontMap[SMALLFONT1] || iFont == WinFontMap[WIN_14POINTARIAL])
{
return pWinFont->Height + 2;
}
#endif
return pWinFont->Height;
}
/*
hdc = GetDC(NULL);
SelectObject(hdc, pWinFont->hFont );
GetTextExtentPoint32W( hdc, string2, lstrlenW(string2), &RectSize );
ReleaseDC(NULL, hdc);
return( (INT16)RectSize.cy );*/
}
UINT32 WinFont_mprintf( INT32 iFont, INT32 x, INT32 y, STR16 pFontString, ...)
{
va_list argptr;
CHAR16 string[512];
va_start(argptr, pFontString); // Set up variable argument pointer
vswprintf(string, pFontString, argptr); // process gprintf string (get output str)
va_end(argptr);
PrintWinFont( FontDestBuffer, iFont, x, y, string );
return( 1 );
return pWinFont->Height;
}
+6 -2
View File
@@ -5,6 +5,9 @@
void InitWinFonts( );
void ShutdownWinFonts( );
void InitTooltipFonts();
void ShutdownTooltipFonts();
INT32 CreateWinFont( LOGFONT &logfont );
void DeleteWinFont( INT32 iFont );
@@ -14,8 +17,7 @@ void SetWinFontForeColor( INT32 iFont, COLORVAL *pColor );
void PrintWinFont( UINT32 uiDestBuf, INT32 iFont, INT32 x, INT32 y, STR16 pFontString, ...);
INT16 WinFontStringPixLength( STR16 string, INT32 iFont );
INT16 GetWinFontHeight( STR16 string, INT32 iFont );
UINT32 WinFont_mprintf( INT32 iFont, INT32 x, INT32 y, STR16 pFontString, ...);
INT16 GetWinFontHeight( INT32 iFont );
//if you cahnge this enum, you must change FontInfo struct in WinFont.cpp too.
enum {
@@ -43,5 +45,7 @@ WIN_LASTFONT
};
#define MAX_WINFONTMAP 25
extern INT32 WinFontMap[MAX_WINFONTMAP];
extern INT32 TOOLTIP_IFONT;
extern INT32 TOOLTIP_IFONT_BOLD;
#endif
+146 -83
View File
@@ -56,6 +56,7 @@ extern void ReleaseAnchorMode(); //private function used here (implemented in Bu
INT16 GetNumberOfLinesInHeight( const STR16 pStringA );
INT16 GetWidthOfString( const STR16 pStringA );
void DisplayHelpTokenizedString( const STR16 pStringA, INT16 sX, INT16 sY );
bool isTooltipScalingEnabled();
@@ -1361,32 +1362,31 @@ void SetRegionFastHelpText( MOUSE_REGION *region, const STR16 szText )
//region->FastHelpTimer = gsFastHelpDelay;
}
INT16 GetNumberOfLinesInHeight( const STR16 pStringA )
bool isTooltipScalingEnabled() {
return fTooltipScaleFactor > 1;
}
UINT16 GetScaledFontHeight()
{
STR16 pToken;
INT16 sCounter = 0;
CHAR16 pString[ 4096 ];
return isTooltipScalingEnabled()
? GetWinFontHeight(TOOLTIP_IFONT)
: GetFontHeight(FONT10ARIAL);
}
wcscpy( pString, pStringA );
// this function returns the number of lines the input string has
// that can be renderered within the screen height
INT16 GetNumberOfLinesInHeight(const STR16 inputString) {
INT32 fontHeight = GetScaledFontHeight();
// tokenize
pToken = wcstok( pString, L"\n" );
while( pToken != NULL )
{
// WANNE: Fix by Headrock
if ( (sCounter+1) * (GetFontHeight(FONT10ARIAL)+1) > (SCREEN_HEIGHT - 10) )
{
break;
}
pToken = wcstok( NULL, L"\n" );
sCounter++;
/*pToken = wcstok( NULL, L"\n" );
sCounter++;*/
INT32 count = 1;
INT32 stringLength = (INT32)wcslen(inputString);
for (int i = 0; i < stringLength && count * (fontHeight + 1) < (SCREEN_HEIGHT - 10); i++) {
if (inputString[i] == '\n' && i + 1 < stringLength) {
count++;
}
}
return( sCounter );
return(count);
}
@@ -1398,17 +1398,14 @@ INT16 GetNumberOfLinesInHeight( const STR16 pStringA )
//
void DisplayFastHelp( MOUSE_REGION *region )
{
UINT16 usFillColor;
INT32 iX,iY,iW,iH;
if ( region->uiFlags & MSYS_FASTHELP )
{
usFillColor = Get16BPPColor(FROMRGB(250, 240, 188));
iW = (INT32)GetWidthOfString(region->FastHelpText) + 10 * fTooltipScaleFactor;
iH = (INT32)(GetNumberOfLinesInHeight(region->FastHelpText) * (GetScaledFontHeight() + 1) + 8 * fTooltipScaleFactor);
iW = (INT32)GetWidthOfString( region->FastHelpText ) + 10;
iH = (INT32)( GetNumberOfLinesInHeight( region->FastHelpText ) * (GetFontHeight(FONT10ARIAL)+1) + 8 );
iX = (INT32)region->RegionTopLeftX + 10;
iX = (INT32)region->RegionTopLeftX + 10 * fTooltipScaleFactor;
if (iX < 0)
iX = 0;
@@ -1424,7 +1421,7 @@ void DisplayFastHelp( MOUSE_REGION *region )
iY = 0;
if ( (iY + iH) >= SCREEN_HEIGHT )
iY = (SCREEN_HEIGHT - iH - 15);
iY = (SCREEN_HEIGHT - iH - 10);
if ( !(region->uiFlags & MSYS_GOT_BACKGROUND) )
{
@@ -1445,83 +1442,149 @@ void DisplayFastHelp( MOUSE_REGION *region )
ShadowVideoSurfaceRect( FRAME_BUFFER, iX + 2, iY + 2, iX + iW - 3, iY + iH - 3 );
ShadowVideoSurfaceRect( FRAME_BUFFER, iX + 2, iY + 2, iX + iW - 3, iY + iH - 3 );
SetFont( FONT10ARIAL );
SetFontShadow( FONT_NEARBLACK );
DisplayHelpTokenizedString( region->FastHelpText ,( INT16 )( iX + 5 ), ( INT16 )( iY + 5 ) );
DisplayHelpTokenizedString(
region->FastHelpText,
(INT16)(iX + (isTooltipScalingEnabled() ? 5 * fTooltipScaleFactor : 5)),
(INT16)(iY + (isTooltipScalingEnabled() ? 4 * fTooltipScaleFactor : 5))
);
InvalidateRegion( iX, iY, (iX + iW) , (iY + iH) );
}
}
}
INT16 GetWidthOfString( const STR16 pStringA )
INT16 GetWidthOfString(const STR16 inputString)
{
CHAR16 pString[ 4096 ];
STR16 pToken;
INT16 sWidth = 0;
wcscpy( pString, pStringA );
INT16 width = 0;
CHAR16 stringBuffer[256] = L"";
INT32 bufferIndex = 0;
bool isBold = false;
// tokenize
pToken = wcstok( pString, L"\n" );
INT32 iFontHeight = GetScaledFontHeight();
while( pToken != NULL )
{
if( sWidth < StringPixLength( pToken, FONT10ARIAL ) )
{
sWidth = StringPixLength( pToken, FONT10ARIAL );
INT16 lineWidth = 0;
INT32 lineCounter = 0;
INT32 stringLength = (INT32)wcslen(inputString);
for (int i = 0; i < stringLength; i++) {
if (inputString[i] == '\n') {
// if the lines don't fit the screen the last line is ...
if ((lineCounter + 2) * (iFontHeight + 1) > (SCREEN_HEIGHT - 10)) {
lineWidth = isTooltipScalingEnabled()
? WinFontStringPixLength(L"...", TOOLTIP_IFONT)
: StringPixLength(L"...", FONT10ARIAL);
if (width < lineWidth) {
width = lineWidth;
}
break;
}
lineWidth = 0;
lineCounter++;
}
else if (inputString[i] == '|') {
isBold = true;
}
else {
stringBuffer[bufferIndex++] = inputString[i];
pToken = wcstok( NULL, L"\n" );
// look ahead to see if we need to flush the string buffer
if (i + 1 >= stringLength
|| inputString[i + 1] == '\n'
|| (isBold && inputString[i + 1] != '|')
|| (!isBold && inputString[i + 1] == '|')) {
// set string ending character
stringBuffer[bufferIndex] = '\0';
if (isTooltipScalingEnabled()) {
INT32 iFont = isBold ? TOOLTIP_IFONT_BOLD : TOOLTIP_IFONT;
lineWidth += WinFontStringPixLength(stringBuffer, iFont);
}
else {
INT32 iFont = isBold ? FONT10ARIALBOLD : FONT10ARIAL;
SetFont(iFont);
lineWidth += StringPixLength(stringBuffer, iFont);
}
bufferIndex = 0;
isBold = false;
if (i + 1 >= stringLength || inputString[i + 1] == '\n') {
if (width < lineWidth) {
width = lineWidth;
}
}
}
}
}
return( sWidth );
return width;
}
void DisplayHelpTokenizedString( const STR16 pStringA, INT16 sX, INT16 sY )
void DisplayHelpTokenizedString(const STR16 inputString, INT16 sX, INT16 sY)
{
STR16 pToken;
INT32 iCounter = 0, i;
UINT32 uiCursorXPos;
CHAR16 pString[ 4096 ];
INT32 iLength;
SetFontShadow(FONT_NEARBLACK);
wcscpy( pString, pStringA );
INT32 fontHeight = GetScaledFontHeight();
// tokenize
pToken = wcstok( pString, L"\n" );
CHAR16 stringBuffer[256] = L"";
INT32 bufferIndex = 0;
bool isBold = false;
while( pToken != NULL )
{
// WANNE: Fix by Headrock
if ( (iCounter+2) * (GetFontHeight(FONT10ARIAL)+1) > (SCREEN_HEIGHT - 10) )
{
mprintf( sX, sY + iCounter * (GetFontHeight(FONT10ARIAL)+1), L"..." );
break;
}
iLength = (INT32)wcslen( pToken );
INT16 xDelta = 0;
//iLength = (INT32)wcslen( pToken );
for( i = 0; i < iLength; i++ )
{
uiCursorXPos = StringPixLengthArgFastHelp( FONT10ARIAL, FONT10ARIALBOLD, i, pToken );
if( pToken[ i ] == '|' )
{
i++;
SetFont( FONT10ARIALBOLD );
SetFontForeground( 146 );
INT32 lineCounter = 0;
INT32 stringLength = (INT32)wcslen(inputString);
for (int i = 0; i < stringLength; i++) {
if (inputString[i] == '\n') {
// if the lines don't fit the screen the last line is ...
if ((lineCounter + 2) * (fontHeight + 1) > (SCREEN_HEIGHT - 10)) {
if (isTooltipScalingEnabled()) {
PrintWinFont(FontDestBuffer, TOOLTIP_IFONT, sX, sY + lineCounter * (fontHeight + 1), L"...");
}
else {
SetFont(FONT10ARIAL);
mprintf(sX, sY + lineCounter * (fontHeight + 1), L"...");
}
break;
}
xDelta = 0;
lineCounter++;
}
else if (inputString[i] == '|') {
isBold = true;
}
else {
stringBuffer[bufferIndex++] = inputString[i];
// look ahead to see if we need to flush the string buffer
if (i + 1 >= stringLength
|| inputString[i + 1] == '\n'
|| (isBold && inputString[i + 1] != '|')
|| (!isBold && inputString[i + 1] == '|')) {
// set string ending character
stringBuffer[bufferIndex] = '\0';
if (isTooltipScalingEnabled()) {
// the font color is set on font initialization
INT32 iFont = isBold ? TOOLTIP_IFONT_BOLD : TOOLTIP_IFONT;
PrintWinFont(FontDestBuffer, iFont, sX + xDelta, sY + lineCounter * (fontHeight + 1), L"%s", stringBuffer);
xDelta += WinFontStringPixLength(stringBuffer, iFont);
}
else {
INT32 iFont = isBold ? FONT10ARIALBOLD : FONT10ARIAL;
SetFont(iFont);
SetFontForeground(isBold ? 146 : FONT_BEIGE);
mprintf(sX + xDelta, sY + lineCounter * (fontHeight + 1), L"%s", stringBuffer);
xDelta += StringPixLength(stringBuffer, iFont);
}
bufferIndex = 0;
isBold = false;
}
else
{
SetFont( FONT10ARIAL );
SetFontForeground( FONT_BEIGE );
}
mprintf( sX + uiCursorXPos, sY + iCounter * (GetFontHeight(FONT10ARIAL)+1), L"%c", pToken[ i ] );
}
pToken = wcstok( NULL, L"\n" );
iCounter++;
}
SetFontDestBuffer( FRAME_BUFFER, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, FALSE );
SetFontDestBuffer(FRAME_BUFFER, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, FALSE);
}
void RenderFastHelp()
@@ -1819,4 +1882,4 @@ MOUSE_REGION *get_next_entry_in_MSYS_RegList(MOUSE_REGION *current_region)
void ResetWheelState( MOUSE_REGION *region )
{
region->WheelState = 0;
}
}
+4
View File
@@ -1329,6 +1329,8 @@ void GetRuntimeSettings( )
// WANNE: Should we play the intro?
iPlayIntro = (int) GetPrivateProfileInt( "Ja2 Settings","PLAY_INTRO", iPlayIntro, INIFile );
iUseWinFonts = (int) GetPrivateProfileInt( "Ja2 Settings","USE_WINFONTS", iUseWinFonts, INIFile,);
fTooltipScaleFactor = ((int)GetPrivateProfileInt("Ja2 Settings", "TOOLTIP_SCALE_FACTOR", 100, INIFile, )) / 100;
if (fTooltipScaleFactor < 1) fTooltipScaleFactor = 1;
// haydent: mouse scrolling
iDisableMouseScrolling = (int) GetPrivateProfileInt( "Ja2 Settings","DISABLE_MOUSE_SCROLLING", iDisableMouseScrolling, INIFile );
@@ -1371,6 +1373,8 @@ void GetRuntimeSettings( )
iPlayIntro = (int)oProps.getIntProperty("Ja2 Settings","PLAY_INTRO", iPlayIntro);
iUseWinFonts= (int)oProps.getIntProperty("Ja2 Settings","USE_WINFONTS", iUseWinFonts);
fTooltipScaleFactor = ((float)oProps.getFloatProperty("Ja2 Settings", "TOOLTIP_SCALE_FACTOR", 100)) / 100;
if (fTooltipScaleFactor < 1) fTooltipScaleFactor = 1;
// haydent: mouse scrolling
iDisableMouseScrolling = (int)oProps.getIntProperty("Ja2 Settings","DISABLE_MOUSE_SCROLLING", iDisableMouseScrolling);
+5 -4
View File
@@ -633,6 +633,7 @@ DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Autoresolve1");
switch( GetEnemyEncounterCode() )
{
case ENEMY_ENCOUNTER_CODE:
case TRANSPORT_INTERCEPT_CODE:
gpAR->ubPlayerDefenceAdvantage = 21; //Skewed to the player's advantage for convenience purposes.
break;
case ENEMY_INVASION_CODE:
@@ -680,7 +681,7 @@ UINT32 AutoResolveScreenHandle()
SGPRect ClipRect;
gpAR->fEnteringAutoResolve = FALSE;
//Take the framebuffer, shade it, and save it to the SAVEBUFFER.
ClipRect.iLeft = 0 + xResOffset;
ClipRect.iLeft = 0;
ClipRect.iTop = 0;
/*ClipRect.iRight = 640;
ClipRect.iBottom = 480;*/
@@ -691,7 +692,7 @@ UINT32 AutoResolveScreenHandle()
Blt16BPPBufferShadowRect( (UINT16*)pDestBuf, uiDestPitchBYTES, &ClipRect );
UnLockVideoSurface( FRAME_BUFFER );
//BlitBufferToBuffer( FRAME_BUFFER, guiSAVEBUFFER, 0, 0, 640, 480 );
BlitBufferToBuffer( FRAME_BUFFER, guiSAVEBUFFER, 0 + xResOffset, 0, SCREEN_WIDTH, SCREEN_HEIGHT );
BlitBufferToBuffer( FRAME_BUFFER, guiSAVEBUFFER, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT );
KillPreBattleInterface();
CalculateAutoResolveInfo();
CalculateSoldierCells( FALSE );
@@ -1745,6 +1746,7 @@ void RenderAutoResolve()
swprintf( str, gpStrategicString[STR_AR_ATTACK_HEADER] );
break;
case ENEMY_ENCOUNTER_CODE:
case TRANSPORT_INTERCEPT_CODE:
swprintf( str, gpStrategicString[STR_AR_ENCOUNTER_HEADER] );
break;
case ENEMY_INVASION_CODE:
@@ -6058,6 +6060,5 @@ BOOLEAN IndividualMilitiaInUse_AutoResolve( UINT32 aMilitiaId )
}
}
}
return FALSE;
}
}
+1
View File
@@ -47,6 +47,7 @@ set(StrategicSrc
"${CMAKE_CURRENT_SOURCE_DIR}/Strategic Status.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/Strategic Town Loyalty.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/strategic town reputation.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/Strategic Transport Groups.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/Strategic Turns.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/strategic.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/strategicmap.cpp"
+6
View File
@@ -48,6 +48,7 @@
#include "LuaInitNPCs.h" // added by Flugente
#include "MiniEvents.h"
#include "Rebel Command.h"
#include "interface Dialogue.h"
#include "connect.h"
@@ -668,6 +669,11 @@ BOOLEAN ExecuteStrategicEvent( STRATEGICEVENT *pEvent )
case EVENT_REBELCOMMAND:
RebelCommand::HandleStrategicEvent(pEvent->uiParam);
break;
case EVENT_RETURN_TRANSPORT_GROUP:
// for this action, we only care about the groupid, which is in the event param
ExecuteStrategicAIAction(NPC_ACTION_RETURN_TRANSPORT_GROUP, 0, 0, pEvent->uiParam);
break;
}
gfPreventDeletionOfAnyEvent = fOrigPreventFlag;
return TRUE;
+4 -1
View File
@@ -154,6 +154,9 @@ enum
EVENT_REBELCOMMAND,
EVENT_RETURN_TRANSPORT_GROUP,
EVENT_TRANSPORT_GROUP_DEFEATED,
NUMBER_OF_EVENT_TYPES_PLUS_ONE,
NUMBER_OF_EVENT_TYPES = NUMBER_OF_EVENT_TYPES_PLUS_ONE - 1
};
@@ -217,4 +220,4 @@ void DeleteAllStrategicEvents();
// Flugente: return vector of all events of type ubCallbackID with time and param
std::vector< std::pair<UINT32, UINT32> > GetAllStrategicEventsOfType( UINT8 ubCallbackID );
#endif
#endif
+1
View File
@@ -137,6 +137,7 @@ CHAR16 gEventName[NUMBER_OF_EVENT_TYPES_PLUS_ONE][40]={
L"ArmyFinishTraining",
L"MiniEvent",
L"ARC_Event",
L"ReturnTransportGroup",
};
#endif
+2 -2
View File
@@ -340,7 +340,7 @@ void RenderMapScreenInterfaceBottom( BOOLEAN fForceMapscreenFullRender )
// HEADROCK HAM 3.6: OK, let's always render this panel, as long as the team inventory screen isn't open.
// sevenfm: improved r8524 fix to work with 1280x720 resolution
//if (fMapScreenBottomDirty || ((!fShowInventoryFlag || iResolution > _1024x600) && fForceMapscreenFullRender))
if ((!fShowInventoryFlag || iResolution > _1280x720) && (fMapScreenBottomDirty || fForceMapscreenFullRender))
if ( (!fShowInventoryFlag || iResolution > _1024x600) && (fMapScreenBottomDirty || fForceMapscreenFullRender))
{
// get and blt panel
GetVideoObject(&hHandle, guiMAPBOTTOMPANEL );
@@ -1936,7 +1936,7 @@ BOOLEAN AllowedToExitFromMapscreenTo( INT8 bExitToWhere )
}
// battle about to occur?
if( ( fDisableDueToBattleRoster ) || ( fDisableMapInterfaceDueToBattle ) )
if( ( fDisableDueToBattleRoster ) || ( fDisableMapInterfaceDueToBattle ) || ( gfPreBattleInterfaceActive ))
{
return( FALSE );
}
+28 -1
View File
@@ -46,6 +46,7 @@
#include "LuaInitNPCs.h" // added by Flugente
#include "Game Event Hook.h" // added by Flugente
#include "Rebel Command.h"
#include "Strategic Transport Groups.h"
#include "Quests.h"
#include "connect.h"
@@ -841,6 +842,8 @@ void fillMapColoursForVisitedSectors(INT32(&colorMap)[ MAXIMUM_VALID_Y_COORDINAT
}
}
FillMapColoursForTransportGroups(colorMap);
if (RebelCommand::ShowEnemyMovementTargets())
{
const auto targetColor = MAP_SHADE_LT_RED;
@@ -1789,11 +1792,16 @@ void InitializeMilitiaPopup(void)
const UINT16 xVal = 330 + xResOffset;
const UINT16 yVal = 25 + yResOffset;
if (isWidescreenUI() || iResolution >= _1024x768)
if (iResolution >= _1024x768)
{
MAP_MILITIA_BOX_POS_X = xVal + 190;
MAP_MILITIA_BOX_POS_Y = yVal + 285;
}
else if (isWidescreenUI())
{
MAP_MILITIA_BOX_POS_X = xVal + 190;
MAP_MILITIA_BOX_POS_Y = yVal + 116;
}
else if (iResolution >= _800x600)
{
MAP_MILITIA_BOX_POS_X = xVal + 77;
@@ -8584,6 +8592,25 @@ void DetermineMapIntelData( INT32 asSectorZ )
}
}
// transport groups
std::map<UINT8, TransportGroupSectorInfo> map = GetTransportGroupSectorInfo();
for (const auto iter : map)
{
CHAR16 str[128];
switch (iter.second)
{
case TransportGroupSectorInfo::TransportGroupSectorInfo_LocatedGroup:
swprintf( str, gpStrategicString[STR_PB_TRANSPORT_GROUP]);
break;
case TransportGroupSectorInfo::TransportGroupSectorInfo_LocatedDestination:
swprintf( str, gpStrategicString[STR_PB_TRANSPORT_GROUP_EN_ROUTE]);
break;
}
AddIntelAndQuestMapDataForSector( SECTORX(iter.first), SECTORY(iter.first), MAP_SHADE_LT_YELLOW, -1, str, L"" );
}
// uncovered terrorists we know of
for ( int cnt = 0; cnt < 6; ++cnt )
{
+34 -87
View File
@@ -2959,85 +2959,6 @@ void DisplayUserDefineHelpTextRegions( FASTHELPREGION *pRegion )
extern void DisplayHelpTokenizedString( const STR16 pStringA, INT16 sX, INT16 sY );
extern INT16 GetNumberOfLinesInHeight( const STR16 pStringA );
extern INT16 GetWidthOfString( const STR16 pStringA );
void DisplaySoldierToolTip( FASTHELPREGION *pRegion )
{
UINT16 usFillColor;
INT32 iX,iY,iW,iH;
UINT8 *pDestBuf;
UINT32 uiDestPitchBYTES;
// grab the color for the background region
usFillColor = Get16BPPColor(FROMRGB(250, 240, 188));
iX = pRegion->iX;
iY = pRegion->iY;
// get the width and height of the string
//iW = (INT32)( pRegion->iW ) + 14;
iW = (INT32)GetWidthOfString( pRegion->FastHelpText ) + 10;
//iH = IanWrappedStringHeight( ( UINT16 )iX, ( UINT16 )iY, ( UINT16 )( pRegion->iW ), 0, FONT10ARIAL, FONT_BLACK, pRegion->FastHelpText, FONT_BLACK, TRUE, 0 );
iH = (INT32)( GetNumberOfLinesInHeight( pRegion->FastHelpText ) * (GetFontHeight(FONT10ARIAL)+1) + 8 );
// tack on the outer border
iH += 14;
// gone not far enough?
if ( iX < 0 )
iX = 0;
// gone too far
if ( ( pRegion->iX + iW ) >= SCREEN_WIDTH )
iX = (SCREEN_WIDTH - iW - 4);
// what about the y value?
iY = (INT32)pRegion->iY - ( iH * 3 / 4);
// not far enough
if (iY < 0)
iY = 0;
// too far
if ( (iY + iH) >= SCREEN_HEIGHT )
iY = (SCREEN_HEIGHT - iH - 15);
pDestBuf = LockVideoSurface( FRAME_BUFFER, &uiDestPitchBYTES );
SetClippingRegionAndImageWidth( uiDestPitchBYTES, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT );
RectangleDraw( TRUE, iX + 1, iY + 1, iX + iW - 1, iY + iH - 1, Get16BPPColor( FROMRGB( 65, 57, 15 ) ), pDestBuf );
RectangleDraw( TRUE, iX, iY, iX + iW - 2, iY + iH - 2, Get16BPPColor( FROMRGB( 227, 198, 88 ) ), pDestBuf );
UnLockVideoSurface( FRAME_BUFFER );
ShadowVideoSurfaceRect( FRAME_BUFFER, iX + 2, iY + 2, iX + iW - 3, iY + iH - 3 );
ShadowVideoSurfaceRect( FRAME_BUFFER, iX + 2, iY + 2, iX + iW - 3, iY + iH - 3 );
// fillt he video surface areas
//ColorFillVideoSurfaceArea(FRAME_BUFFER, iX, iY, (iX + iW), (iY + iH), 0);
//ColorFillVideoSurfaceArea(FRAME_BUFFER, (iX + 1), (iY + 1), (iX + iW - 1), (iY + iH - 1), usFillColor);
SetFont( FONT10ARIAL );
SetFontForeground( FONT_BEIGE );
//iH = ( INT32 )DisplayWrappedString( ( INT16 )( iX + 10 ), ( INT16 )( iY + 6 ), ( INT16 )pRegion->iW, 0, FONT10ARIAL, FONT_BEIGE, pRegion->FastHelpText, FONT_NEARBLACK, TRUE, 0 );
DisplayHelpTokenizedString( pRegion->FastHelpText ,( INT16 )( iX + 5 ), ( INT16 )( iY + 5 ) );
iHeightOfInitFastHelpText = iH + 20;
InvalidateRegion( iX, iY, (iX + iW) , (iY + iH + 20 ) );
}
void DisplayFastHelpForInitialTripInToMapScreen( FASTHELPREGION *pRegion )
{
if( gTacticalStatus.fDidGameJustStart )
@@ -4661,6 +4582,28 @@ void HandleSettingTheSelectedListOfMercs( void )
INT8 pbErrorNumber = -1;
pSoldier = MercPtrs[gCharactersList[GetSelectedDestChar()].usSolID];
INT8 bSquadValue = pSoldier->bAssignment;
if (bSquadValue == VEHICLE)
{
for (INT8 bCounter = 0; bCounter < NUMBER_OF_SQUADS; ++bCounter)
{
if (Squad[bCounter][0] != NULL && IsVehicle(Squad[bCounter][0]) &&
Squad[bCounter][0]->bVehicleID == pSoldier->iVehicleId)
{
bSquadValue = bCounter;
break;
}
}
}
if (bSquadValue >= NUMBER_OF_SQUADS)
{
if (pbErrorNumber != -1)
{
ReportMapScreenMovementError(pbErrorNumber);
}
SetSelectedDestChar(-1);
giDestHighLine = -1;
return;
}
// find number of characters in particular squad.
for (INT8 bCounter = 0; bCounter < NUMBER_OF_SOLDIERS_PER_SQUAD; ++bCounter)
@@ -4772,17 +4715,21 @@ INT8 FindSquadThatSoldierCanJoin( SOLDIERTYPE *pSoldier )
// run through the list of squads
for( bCounter = 0; bCounter < NUMBER_OF_SQUADS; bCounter++ )
{
// is this squad in this sector
if( IsThisSquadInThisSector( pSoldier->sSectorX, pSoldier->sSectorY, pSoldier->bSectorZ, bCounter ) )
// anv: don't automatically put people in vehicle squads
if (Squad[bCounter][0] == NULL || !IsVehicle(Squad[bCounter][0]))
{
// does it have room?
if( IsThisSquadFull( bCounter ) == FALSE )
// is this squad in this sector
if (IsThisSquadInThisSector(pSoldier->sSectorX, pSoldier->sSectorY, pSoldier->bSectorZ, bCounter))
{
// is it doing the same thing as the soldier is (staying or going) ?
if( IsSquadSelectedForMovement( bCounter ) == IsSoldierSelectedForMovement( pSoldier ) )
// does it have room?
if (IsThisSquadFull(bCounter) == FALSE)
{
// go ourselves a match, then
return( bCounter );
// is it doing the same thing as the soldier is (staying or going) ?
if (IsSquadSelectedForMovement(bCounter) == IsSoldierSelectedForMovement(pSoldier))
{
// go ourselves a match, then
return(bCounter);
}
}
}
}
+230 -132
View File
@@ -47,6 +47,8 @@
#include "CampaignStats.h" // added by Flugente
#include "militiasquads.h" // added by Flugente
#include "SkillCheck.h" // added by Flugente
#include "Strategic Transport Groups.h"
#include "Utilities.h"
#ifdef JA2UB
#include "ub_config.h"
@@ -98,13 +100,23 @@ enum //GraphicIDs for the panel
#define ROW_HEIGHT 10
//The start of the black space
#define TOP_Y 113
#define TOP_Y_TEXT_BUFFER 1
//The end of the black space
//#define BOTTOM_Y (349+(OUR_TEAM_SIZE_NO_VEHICLE-18)*ROW_HEIGHT)
#define BOTTOM_Y 349
#define BOTTOM_HEIGHT 8
//The internal height of the uninvolved panel
#define INTERNAL_HEIGHT 27
//The actual height of the uninvolved panel
#define ACTUAL_HEIGHT 24
#define UNINVOLVED_RELEVANT_HEIGHT 28
#define UNINVOLVED_OFFSET_HEIGHT 7
#define PREBATTLE_INTERFACE_WIDTH 261
INT32 iPrebattleInterfaceHeight = 360;
UINT16 xOffset;
UINT16 yOffset;
UINT16 blanketStartX;
UINT16 blanketStartY;
INT16 bListOffset = 0;
UINT16 ubDesiredListHeight = 0;
UINT16 ubAllowedListHeight = 0;
BOOLEAN gfDisplayPotentialRetreatPaths = FALSE;
UINT16 gusRetreatButtonLeft, gusRetreatButtonTop, gusRetreatButtonRight, gusRetreatButtonBottom;
@@ -299,6 +311,8 @@ void InitPreBattleInterface( GROUP *pBattleGroup, BOOLEAN fPersistantPBI )
gAmbushRadiusModifier = 0.0f;
bListOffset = 0;
// ARM: Feb01/98 - Cancel out of mapscreen movement plotting if PBI subscreen is coming up
if ( ( GetSelectedDestChar() != -1) || fPlotForHelicopter || fPlotForMilitia )
{
@@ -438,7 +452,7 @@ void InitPreBattleInterface( GROUP *pBattleGroup, BOOLEAN fPersistantPBI )
}
else if ( pBattleGroup && pBattleGroup->usGroupTeam != OUR_TEAM && NumNonPlayerTeamMembersInSector( pBattleGroup->ubSectorX, pBattleGroup->ubSectorY, MILITIA_TEAM ) > 0 )
{
SetEnemyEncounterCode( ENEMY_ENCOUNTER_CODE );
SetEnemyEncounterCode( pBattleGroup->usGroupTeam == ENEMY_TEAM && pBattleGroup->pEnemyGroup->ubIntention == TRANSPORT ? TRANSPORT_INTERCEPT_CODE : ENEMY_ENCOUNTER_CODE );
}
else if( GetEnemyEncounterCode() == ENTERING_ENEMY_SECTOR_CODE ||
GetEnemyEncounterCode() == ENEMY_ENCOUNTER_CODE ||
@@ -452,7 +466,8 @@ void InitPreBattleInterface( GROUP *pBattleGroup, BOOLEAN fPersistantPBI )
GetEnemyEncounterCode() == CONCEALINSERTION_CODE ||
GetEnemyEncounterCode() == BLOODCAT_ATTACK_CODE ||
GetEnemyEncounterCode() == ZOMBIE_ATTACK_CODE ||
GetEnemyEncounterCode() == BANDIT_ATTACK_CODE )
GetEnemyEncounterCode() == BANDIT_ATTACK_CODE ||
GetEnemyEncounterCode() == TRANSPORT_INTERCEPT_CODE )
{
//use same code
SetExplicitEnemyEncounterCode( GetEnemyEncounterCode() );
@@ -479,32 +494,69 @@ void InitPreBattleInterface( GROUP *pBattleGroup, BOOLEAN fPersistantPBI )
fMapScreenBottomDirty = TRUE;
ChangeSelectedMapSector( gubPBSectorX, gubPBSectorY, gubPBSectorZ );
// Headrock: Added FALSE argument, We might need TRUE but not sure. Will need to initiate battle :)
RenderMapScreenInterfaceBottom( FALSE );
if( !fShowTeamFlag )
{
ToggleShowTeamsMode();
}
//Define the blanket region to cover all of the other regions used underneath the panel.
MSYS_DefineRegion( &PBInterfaceBlanket, 0 + xResOffset, 0 + yResOffset, 261 + xResOffset, 359 + yResOffset, MSYS_PRIORITY_HIGHEST - 5, 0, 0, 0 );
//Create the panel
VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE;
GetMLGFilename( VObjectDesc.ImageFile, MLG_PREBATTLEPANEL );
// anv: prebattle interface per vertical resolution
if (isWidescreenUI())
{
GetMLGFilename(VObjectDesc.ImageFile, MLG_PREBATTLEPANEL_1280x720);
iPrebattleInterfaceHeight = 600;
xOffset = xResOffset + 15;
yOffset = 0;
blanketStartX = 0;
blanketStartY = 0;
}
else if (iResolution >= _640x480 && iResolution < _800x600)
{
GetMLGFilename(VObjectDesc.ImageFile, MLG_PREBATTLEPANEL);
iPrebattleInterfaceHeight = 360;
xOffset = xResOffset;
yOffset = yResOffset;
blanketStartX = yOffset;
blanketStartY = yOffset;
}
else if (iResolution < _1024x768)
{
GetMLGFilename(VObjectDesc.ImageFile, MLG_PREBATTLEPANEL_800x600);
iPrebattleInterfaceHeight = 478;
xOffset = xResOffset;
yOffset = yResOffset;
blanketStartX = yOffset;
blanketStartY = yOffset;
}
else
{
GetMLGFilename(VObjectDesc.ImageFile, MLG_PREBATTLEPANEL_1024x768);
iPrebattleInterfaceHeight = 647;
xOffset = xResOffset;
yOffset = yResOffset;
blanketStartX = yOffset;
blanketStartY = yOffset;
}
ubAllowedListHeight = iPrebattleInterfaceHeight - TOP_Y - BOTTOM_HEIGHT;
if( !AddVideoObject( &VObjectDesc, &uiInterfaceImages ) )
AssertMsg( 0, "Failed to load interface\\PreBattlePanel.sti" );
//Define the blanket region to cover all of the other regions used underneath the panel.
MSYS_DefineRegion( &PBInterfaceBlanket, blanketStartX, blanketStartY, PREBATTLE_INTERFACE_WIDTH + xOffset, iPrebattleInterfaceHeight + yOffset, MSYS_PRIORITY_HIGHEST, 0, 0, 0 );
//Create the 3 buttons
iPBButtonImage[0] = LoadButtonImage( "INTERFACE\\PreBattleButton.sti", -1, 0, -1, 1, -1 );
if( iPBButtonImage[ 0 ] == -1 )
AssertMsg( 0, "Failed to load interface\\PreBattleButton.sti" );
iPBButtonImage[1] = UseLoadedButtonImage( iPBButtonImage[ 0 ], -1, 0, -1, 1, -1 );
iPBButtonImage[2] = UseLoadedButtonImage( iPBButtonImage[ 0 ], -1, 0, -1, 1, -1 );
iPBButton[0] = QuickCreateButton( iPBButtonImage[0], 27 + xResOffset, 54 + yResOffset, BUTTON_NO_TOGGLE, MSYS_PRIORITY_HIGHEST - 2, DEFAULT_MOVE_CALLBACK, AutoResolveBattleCallback );
iPBButton[1] = QuickCreateButton( iPBButtonImage[1], 98 + xResOffset, 54 + yResOffset, BUTTON_NO_TOGGLE, MSYS_PRIORITY_HIGHEST - 2, DEFAULT_MOVE_CALLBACK, GoToSectorCallback );
iPBButton[2] = QuickCreateButton( iPBButtonImage[2], 169 + xResOffset, 54 + yResOffset, BUTTON_NO_TOGGLE, MSYS_PRIORITY_HIGHEST - 2, DEFAULT_MOVE_CALLBACK, RetreatMercsCallback );
iPBButton[0] = QuickCreateButton( iPBButtonImage[0], 27 + xOffset, 54 + yOffset, BUTTON_NO_TOGGLE, MSYS_PRIORITY_HIGHEST, DEFAULT_MOVE_CALLBACK, AutoResolveBattleCallback );
iPBButton[1] = QuickCreateButton( iPBButtonImage[1], 98 + xOffset, 54 + yOffset, BUTTON_NO_TOGGLE, MSYS_PRIORITY_HIGHEST, DEFAULT_MOVE_CALLBACK, GoToSectorCallback );
iPBButton[2] = QuickCreateButton( iPBButtonImage[2], 169 + xOffset, 54 + yOffset, BUTTON_NO_TOGGLE, MSYS_PRIORITY_HIGHEST, DEFAULT_MOVE_CALLBACK, RetreatMercsCallback );
SpecifyGeneralButtonTextAttributes( iPBButton[0], gpStrategicString[ STR_PB_AUTORESOLVE_BTN ], BLOCKFONT, FONT_BEIGE, 141 );
SpecifyGeneralButtonTextAttributes( iPBButton[1], gpStrategicString[ STR_PB_GOTOSECTOR_BTN ], BLOCKFONT, FONT_BEIGE, 141 );
@@ -679,8 +731,24 @@ void InitPreBattleInterface( GROUP *pBattleGroup, BOOLEAN fPersistantPBI )
{
SetEnemyEncounterCode( ENEMY_ENCOUNTER_CODE );
GROUP* pGroup = gpGroupList;
BOOLEAN encounteredTransportGroup = FALSE;
while (pGroup)
{
if (pGroup->usGroupTeam == ENEMY_TEAM && pGroup->pEnemyGroup->ubIntention == TRANSPORT && pGroup->ubSectorX == gpBattleGroup->ubSectorX && pGroup->ubSectorY == gpBattleGroup->ubSectorY && pGroup->ubSectorZ == gpBattleGroup->ubSectorZ)
{
encounteredTransportGroup = TRUE;
break;
}
pGroup = pGroup->next;
}
if (encounteredTransportGroup)
{
SetEnemyEncounterCode( TRANSPORT_INTERCEPT_CODE );
}
// Flugente: no ambushes on an airdrop
if ( !fAirDrop )
else if ( !fAirDrop )
{
//Don't consider ambushes until the player has reached 25% (normal) progress
if( gfHighPotentialForAmbush )
@@ -798,7 +866,9 @@ void InitPreBattleInterface( GROUP *pBattleGroup, BOOLEAN fPersistantPBI )
}
else
{ //Are enemies invading a town, or just encountered the player.
if( GetTownIdForSector( gubPBSectorX, gubPBSectorY ) )
if (pBattleGroup && pBattleGroup->usGroupTeam == ENEMY_TEAM && pBattleGroup->pEnemyGroup->ubIntention == TRANSPORT)
SetEnemyEncounterCode( TRANSPORT_INTERCEPT_CODE );
else if( GetTownIdForSector( gubPBSectorX, gubPBSectorY ) )
SetEnemyEncounterCode( ENEMY_INVASION_CODE );
//SAM sites not in towns will also be considered to be important
else if( pSector->uiFlags & SF_SAM_SITE )
@@ -866,7 +936,7 @@ void InitPreBattleInterface( GROUP *pBattleGroup, BOOLEAN fPersistantPBI )
}
HideButton( giMapContractButton );
if( GetEnemyEncounterCode() == ENEMY_ENCOUNTER_CODE )
if( GetEnemyEncounterCode() == ENEMY_ENCOUNTER_CODE || GetEnemyEncounterCode() == TRANSPORT_INTERCEPT_CODE )
{ //we know how many enemies are here, so until we leave the sector, we will continue to display the value.
//the flag will get cleared when time advances after the fEnemyInSector flag is clear.
@@ -955,6 +1025,7 @@ void InitPreBattleInterface( GROUP *pBattleGroup, BOOLEAN fPersistantPBI )
{
case CREATURE_ATTACK_CODE:
case ENEMY_ENCOUNTER_CODE:
case TRANSPORT_INTERCEPT_CODE:
case ENEMY_INVASION_CODE:
case ENEMY_INVASION_AIRDROP_CODE:
case BLOODCAT_ATTACK_CODE:
@@ -1029,7 +1100,7 @@ void DoTransitionFromMapscreenToPreBattleInterface()
INT32 iPercentage, iFactor;
UINT32 uiTimeRange;
INT16 sStartLeft, sEndLeft, sStartTop, sEndTop;
INT32 iLeft, iTop, iWidth, iHeight;
INT32 iLeft, iTop, iWidth;
BOOLEAN fEnterAutoResolveMode = FALSE;
if( !gfExtraBuffer )
@@ -1037,12 +1108,11 @@ void DoTransitionFromMapscreenToPreBattleInterface()
PauseTime( FALSE );
PBIRect.iLeft = 0 + xResOffset;
PBIRect.iTop = 0 + yResOffset;
PBIRect.iRight = 261 + xResOffset;
PBIRect.iBottom = 359 + yResOffset;
iWidth = 261;
iHeight = 359;
PBIRect.iLeft = 0 + xOffset;
PBIRect.iTop = 0 + yOffset;
PBIRect.iRight = PREBATTLE_INTERFACE_WIDTH + xOffset;
PBIRect.iBottom = iPrebattleInterfaceHeight + yOffset;
iWidth = PREBATTLE_INTERFACE_WIDTH;
uiTimeRange = 1000;
iPercentage = 0;
@@ -1051,8 +1121,8 @@ void DoTransitionFromMapscreenToPreBattleInterface()
GetScreenXYFromMapXY( gubPBSectorX, gubPBSectorY, &sStartLeft, &sStartTop );
sStartLeft += UI_MAP.GridSize.iX / 2;
sStartTop += UI_MAP.GridSize.iY / 2;
sEndLeft = 131 + xResOffset;
sEndTop = 180 + yResOffset;
sEndLeft = PBIRect.iLeft;
sEndTop = PBIRect.iTop;
//save the mapscreen buffer
BlitBufferToBuffer( FRAME_BUFFER, guiEXTRABUFFER, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT );
@@ -1074,17 +1144,23 @@ void DoTransitionFromMapscreenToPreBattleInterface()
gfEnterAutoResolveMode = TRUE;
}
BlitBufferToBuffer( guiSAVEBUFFER, FRAME_BUFFER, 27 + xResOffset, 54 + yResOffset, 209, 32 );
BlitBufferToBuffer( guiSAVEBUFFER, FRAME_BUFFER, 27 + xOffset, 54 + yOffset, 209, 32 );
RenderButtons();
BlitBufferToBuffer( FRAME_BUFFER, guiSAVEBUFFER, 27 + xResOffset, 54 + yResOffset, 209, 32 );
BlitBufferToBuffer( FRAME_BUFFER, guiSAVEBUFFER, 27 + xOffset, 54 + yOffset, 209, 32 );
gfRenderPBInterface = TRUE;
//hide the prebattle interface
BlitBufferToBuffer( guiEXTRABUFFER, FRAME_BUFFER, 0 + xResOffset, 0 + yResOffset, 261 + xResOffset, 359 + yResOffset );
BlitBufferToBuffer( guiEXTRABUFFER, FRAME_BUFFER, 0 + xOffset, 0 + yOffset, PREBATTLE_INTERFACE_WIDTH + xOffset, iPrebattleInterfaceHeight + yOffset );
PlayJA2SampleFromFile( "SOUNDS\\Laptop power up (8-11).wav", RATE_11025, HIGHVOLUME, 1, MIDDLEPAN );
InvalidateScreen();
RefreshScreen( NULL );
SGPRect PrevRect;
PrevRect.iLeft = sStartLeft;
PrevRect.iRight = sStartLeft + 1;
PrevRect.iTop = sStartTop;
PrevRect.iBottom = sStartTop + 1;
while( iPercentage < 100 )
{
uiCurrTime = GetJA2Clock();
@@ -1096,19 +1172,12 @@ void DoTransitionFromMapscreenToPreBattleInterface()
if( iPercentage < 50 )
iPercentage = (UINT32)(iPercentage + iPercentage * iFactor * 0.01 + 0.5);
else
iPercentage = (UINT32)(iPercentage + (100-iPercentage) * iFactor * 0.01 + 0.05);
iPercentage = (UINT32)(iPercentage + (100 - iPercentage) * iFactor * 0.01 + 0.05);
//Calculate the center point.
iLeft = sStartLeft - (sStartLeft-sEndLeft+1) * iPercentage / 100;
if( sStartTop > sEndTop )
iTop = sStartTop - (sStartTop-sEndTop+1) * iPercentage / 100;
else
iTop = sStartTop + (sEndTop-sStartTop+1) * iPercentage / 100;
DstRect.iLeft = iLeft - iWidth * iPercentage / 200;
DstRect.iLeft = sStartLeft + (sEndLeft - sStartLeft) * iPercentage / 100;
DstRect.iRight = DstRect.iLeft + max( iWidth * iPercentage / 100, 1 );
DstRect.iTop = iTop - iHeight * iPercentage / 200;
DstRect.iBottom = DstRect.iTop + max( iHeight * iPercentage / 100, 1 );
DstRect.iTop = sStartTop + (sEndTop - sStartTop) * iPercentage / 100;
DstRect.iBottom = DstRect.iTop + max(iPrebattleInterfaceHeight * iPercentage / 100, 1);
BltStretchVideoSurface( FRAME_BUFFER, guiSAVEBUFFER, 0, 0, 0, &PBIRect, &DstRect );
@@ -1116,14 +1185,35 @@ void DoTransitionFromMapscreenToPreBattleInterface()
RefreshScreen( NULL );
//Restore the previous rect.
BlitBufferToBuffer( guiEXTRABUFFER, FRAME_BUFFER, (UINT16)DstRect.iLeft, (UINT16)DstRect.iTop,
(UINT16)(DstRect.iRight-DstRect.iLeft+1), (UINT16)(DstRect.iBottom-DstRect.iTop+1) );
BlitBufferToBuffer(guiEXTRABUFFER, FRAME_BUFFER, (UINT16)PrevRect.iLeft, (UINT16)PrevRect.iTop,
(UINT16)PrevRect.iRight, (UINT16)PrevRect.iBottom);
PrevRect.iLeft = DstRect.iLeft;
PrevRect.iRight = DstRect.iRight;
PrevRect.iTop = DstRect.iTop;
PrevRect.iBottom = DstRect.iBottom;
}
BlitBufferToBuffer( FRAME_BUFFER, guiSAVEBUFFER, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT );
gfZoomDone = TRUE;
}
void ScrollPreBattleInterface( BOOLEAN fUp )
{
if ( ubDesiredListHeight <= ubAllowedListHeight )
return;
if ( fUp )
{
bListOffset = max( 0, bListOffset - ubAllowedListHeight );
}
else
{
bListOffset = min( bListOffset + ubAllowedListHeight, ubDesiredListHeight - ubAllowedListHeight );
}
gfRenderPBInterface = TRUE;
}
void KillPreBattleInterface()
{
if( !gfPreBattleInterfaceActive )
@@ -1163,7 +1253,7 @@ void KillPreBattleInterface()
//Enable the options button when the auto resolve screen comes up
EnableDisAbleMapScreenOptionsButton( TRUE );
ColorFillVideoSurfaceArea( guiSAVEBUFFER, 0, 0, 261 + xResOffset, 359 + yResOffset, 0 );
ColorFillVideoSurfaceArea( guiSAVEBUFFER, 0, 0, PREBATTLE_INTERFACE_WIDTH + xOffset, iPrebattleInterfaceHeight + yOffset, 0 );
EnableTeamInfoPanels();
if( ButtonList[ giMapContractButton ] )
@@ -1213,6 +1303,7 @@ void RenderPBHeader( INT32 *piX, INT32 *piWidth)
swprintf( str, gpStrategicString[ STR_PB_ENEMYINVASION_HEADER ] );
break;
case ENEMY_ENCOUNTER_CODE:
case TRANSPORT_INTERCEPT_CODE:
swprintf( str, gpStrategicString[ STR_PB_ENEMYENCOUNTER_HEADER ] );
break;
case ENEMY_AMBUSH_CODE:
@@ -1255,8 +1346,8 @@ void RenderPBHeader( INT32 *piX, INT32 *piWidth)
}
width = StringPixLength( str, FONT10ARIALBOLD );
x = 130 - width / 2;
mprintf( x + xResOffset, 4 + yResOffset, str );
InvalidateRegion( 0, 0, 231 + xResOffset, 12 + yResOffset );
mprintf( x + xOffset, 4 + yOffset, str );
InvalidateRegion( 0, 0, 231 + xOffset, 12 + yOffset );
*piX = x;
*piWidth = width;
}
@@ -1271,10 +1362,15 @@ void RenderPreBattleInterface()
UINT8 ubHPPercent, ubBPPercent;
BOOLEAN fMouseInRetreatButtonArea;
UINT8 ubJunk;
SGPRect ClipRect;
UINT16 ubDesiredParticipantsListHeight = 0;
UINT16 ubDesiredUninvolvedListHeight = 0;
UINT16 ubUninvolvedStartY = 0;
//PLAYERGROUP *pPlayer;
// Make the background black!
//ColorFillVideoSurfaceArea( guiSAVEBUFFER, 0, 0, 261 + xResOffset, SCREEN_HEIGHT - 120, 0 );
//ColorFillVideoSurfaceArea( guiSAVEBUFFER, 0, 0, 261 + xOffset, SCREEN_HEIGHT - 120, 0 );
//This code determines if the cursor is inside the rectangle consisting of the
//retreat button. If it is inside, then we set up the variables so that the retreat
@@ -1315,33 +1411,21 @@ void RenderPreBattleInterface()
gfRenderPBInterface = FALSE;
GetVideoObject( &hVObject, uiInterfaceImages );
//main panel
BltVideoObject( guiSAVEBUFFER, hVObject, MAINPANEL, xResOffset, yResOffset, VO_BLT_SRCTRANSPARENCY, NULL );
BltVideoObject( guiSAVEBUFFER, hVObject, MAINPANEL, xOffset, yOffset, VO_BLT_SRCTRANSPARENCY, NULL );
//main title
RenderPBHeader( &x, &width );
//now draw the title bars up to the text.
for( i = x - 12; i > 20; i -= 10 )
{
BltVideoObject( guiSAVEBUFFER, hVObject, TITLE_BAR_PIECE, i + xResOffset, 6 + yResOffset, VO_BLT_SRCTRANSPARENCY, NULL );
BltVideoObject( guiSAVEBUFFER, hVObject, TITLE_BAR_PIECE, i + xOffset, 6 + yOffset, VO_BLT_SRCTRANSPARENCY, NULL );
}
for( i = x + width + 2; i < 231; i += 10 )
{
BltVideoObject( guiSAVEBUFFER, hVObject, TITLE_BAR_PIECE, i + xResOffset, 6 + yResOffset, VO_BLT_SRCTRANSPARENCY, NULL );
BltVideoObject( guiSAVEBUFFER, hVObject, TITLE_BAR_PIECE, i + xOffset, 6 + yOffset, VO_BLT_SRCTRANSPARENCY, NULL );
}
BltVideoObject(guiSAVEBUFFER, hVObject, BOTTOM_LINE, 0 + xResOffset, BOTTOM_Y + yResOffset, VO_BLT_SRCTRANSPARENCY, NULL);
BltVideoObject(guiSAVEBUFFER, hVObject, BOTTOM_LINE, 0 + xResOffset, BOTTOM_Y + yResOffset + 10, VO_BLT_SRCTRANSPARENCY, NULL);
BltVideoObject(guiSAVEBUFFER, hVObject, BOTTOM_LINE, 0 + xResOffset, BOTTOM_Y + yResOffset + 20, VO_BLT_SRCTRANSPARENCY, NULL);
BltVideoObject(guiSAVEBUFFER, hVObject, BOTTOM_LINE, 0 + xResOffset, BOTTOM_Y + yResOffset + 30, VO_BLT_SRCTRANSPARENCY, NULL);
//Draw the bottom edges
for (i = 0; i < max(guiNumUninvolved, 1); i++)
{
y = BOTTOM_Y + ROW_HEIGHT * (i + 1) + 30;
BltVideoObject(guiSAVEBUFFER, hVObject, BOTTOM_LINE, 0 + xResOffset, y + yResOffset, VO_BLT_SRCTRANSPARENCY, NULL);
}
BltVideoObject(guiSAVEBUFFER, hVObject, UNINVOLVED_HEADER, 8 + xResOffset, BOTTOM_Y + yResOffset, VO_BLT_SRCTRANSPARENCY, NULL);
BltVideoObject(guiSAVEBUFFER, hVObject, BOTTOM_END, 0 + xResOffset, BOTTOM_Y + yResOffset + 35 + ROW_HEIGHT * max(guiNumUninvolved, 1), VO_BLT_SRCTRANSPARENCY, NULL);
// header
SetFont( BLOCKFONT );
SetFontForeground( FONT_BEIGE );
swprintf( str, gpStrategicString[ STR_PB_LOCATION ] );
@@ -1351,7 +1435,7 @@ void RenderPreBattleInterface()
SetFont( BLOCKFONTNARROW );
width = StringPixLength( str, BLOCKFONTNARROW );
}
mprintf( 65 - width + xResOffset , 17 + yResOffset, str );
mprintf( 65 - width + xOffset , 17 + yOffset, str );
SetFont( BLOCKFONT );
if( GetEnemyEncounterCode() == CREATURE_ATTACK_CODE )
@@ -1383,7 +1467,7 @@ void RenderPreBattleInterface()
SetFont( BLOCKFONTNARROW );
width = StringPixLength( str, BLOCKFONTNARROW );
}
mprintf( 54 + xResOffset - width , 38 + yResOffset, str );
mprintf( 54 + xOffset - width , 38 + yOffset, str );
SetFont( BLOCKFONT );
swprintf( str, gpStrategicString[ STR_PB_MERCS ] );
@@ -1393,7 +1477,7 @@ void RenderPreBattleInterface()
SetFont( BLOCKFONTNARROW );
width = StringPixLength( str, BLOCKFONTNARROW );
}
mprintf( 139 + xResOffset - width , 38 + yResOffset, str );
mprintf( 139 + xOffset - width , 38 + yOffset, str );
SetFont( BLOCKFONT );
swprintf( str, gpStrategicString[ STR_PB_MILITIA ] );
@@ -1403,29 +1487,53 @@ void RenderPreBattleInterface()
SetFont( BLOCKFONTNARROW );
width = StringPixLength( str, BLOCKFONTNARROW );
}
mprintf( 224 + xResOffset - width , 38 + yResOffset, str );
mprintf( 224 + xOffset - width , 38 + yOffset, str );
//Draw the bottom columns
for( i = 0; i < (INT32)max( guiNumUninvolved, 1 ); i++ )
ubDesiredParticipantsListHeight = guiNumInvolved * ROW_HEIGHT;
ubDesiredUninvolvedListHeight = UNINVOLVED_RELEVANT_HEIGHT + max(guiNumUninvolved, 1) * ROW_HEIGHT;
ubDesiredListHeight = ubDesiredParticipantsListHeight + ubDesiredUninvolvedListHeight;
if (ubDesiredListHeight >= ubAllowedListHeight)
{
y = BOTTOM_Y + ROW_HEIGHT * (i+1) + 1 + ACTUAL_HEIGHT;
BltVideoObject( guiSAVEBUFFER, hVObject, BOTTOM_COLUMN, 161 + xResOffset, y + yResOffset, VO_BLT_SRCTRANSPARENCY, NULL );
ubUninvolvedStartY = ubDesiredParticipantsListHeight;
}
else
{
ubUninvolvedStartY = ubAllowedListHeight - ubDesiredUninvolvedListHeight;
}
// WDS - make number of mercenaries, etc. be configurable
for( i = 0; i < (INT32)(25/*3+ OUR_TEAM_SIZE_NO_VEHICLE - max( guiNumUninvolved, 1 )*/); i++ )
ClipRect.iLeft = xOffset;
ClipRect.iTop = yOffset + TOP_Y;
ClipRect.iRight = xOffset + PREBATTLE_INTERFACE_WIDTH;
ClipRect.iBottom = yOffset + TOP_Y + ubAllowedListHeight;// + TOP_Y_BUFFER;
SetClippingRect(&ClipRect);
// Draw the top columns
// Draw from the top to uninvolved header
for ( y = TOP_Y - bListOffset; y < TOP_Y - bListOffset + ubUninvolvedStartY; y += ROW_HEIGHT )
{
y = TOP_Y + ROW_HEIGHT * i;
BltVideoObject( guiSAVEBUFFER, hVObject, TOP_COLUMN, 186 + xResOffset, y + yResOffset, VO_BLT_SRCTRANSPARENCY, NULL );
BltVideoObject(guiSAVEBUFFER, hVObject, TOP_COLUMN, 186 + xOffset, y + yOffset, VO_BLT_CLIP | VO_BLT_SRCTRANSPARENCY, NULL);
}
// Draw extra empty participants rows to close off bottom of the content area
for ( y = TOP_Y - bListOffset + ubUninvolvedStartY + ROW_HEIGHT; y < TOP_Y - bListOffset + ubUninvolvedStartY + ubDesiredUninvolvedListHeight; y += ROW_HEIGHT )
{
BltVideoObject(guiSAVEBUFFER, hVObject, BOTTOM_COLUMN, 161 + xOffset, y + yOffset, VO_BLT_CLIP | VO_BLT_SRCTRANSPARENCY, NULL);
}
// Draw uninvolved header
BltVideoObject( guiSAVEBUFFER, hVObject, UNINVOLVED_HEADER, 8 + xOffset, yOffset + TOP_Y + ubUninvolvedStartY - UNINVOLVED_OFFSET_HEIGHT - bListOffset, VO_BLT_CLIP | VO_BLT_SRCTRANSPARENCY, NULL );
RestoreClipRegionToFullScreen();
//location
SetFont( FONT10ARIAL );
SetFontForeground( FONT_YELLOW );
SetFontShadow( FONT_NEARBLACK );
GetSectorIDString( gubPBSectorX, gubPBSectorY, gubPBSectorZ, pSectorName, TRUE );
mprintf( 70 + xResOffset, 17 + yResOffset, L"%s %s", gpStrategicString[ STR_PB_SECTOR ], pSectorName );
mprintf( 70 + xOffset, 17 + yOffset, L"%s %s", gpStrategicString[STR_PB_SECTOR], pSectorName );
//enemy
SetFont( FONT14ARIAL );
@@ -1450,58 +1558,55 @@ void RenderPreBattleInterface()
}
x = 57 + (27 - StringPixLength( str, FONT14ARIAL )) / 2;
y = 36;
mprintf( x + xResOffset, y + yResOffset, str );
mprintf( x + xOffset, y + yOffset, str );
//player
swprintf( str, L"%d", guiNumInvolved );
x = 142 + (27 - StringPixLength( str, FONT14ARIAL )) / 2;
mprintf( x + xResOffset, y + yResOffset, str );
mprintf( x + xOffset, y + yOffset, str );
//militia
swprintf( str, L"%d", NumNonPlayerTeamMembersInSector( gubPBSectorX, gubPBSectorY, MILITIA_TEAM ) );
x = 227 + (27 - StringPixLength( str, FONT14ARIAL )) / 2;
mprintf( x + xResOffset, y + yResOffset, str );
mprintf( x + xOffset, y + yOffset, str );
SetFontShadow( FONT_NEARBLACK );
SetFont( BLOCKFONT2 );
SetFontForeground( FONT_YELLOW );
SetFontDestBuffer( guiSAVEBUFFER, xOffset, yOffset + TOP_Y,
xOffset + PREBATTLE_INTERFACE_WIDTH, yOffset + TOP_Y + ubAllowedListHeight, FALSE );
//print out the participants of the battle.
// | NAME | ASSIGN | COND | HP | BP |
line = 0;
y = TOP_Y + 1;
for( i = gTacticalStatus.Team[ OUR_TEAM ].bFirstID; i <= gTacticalStatus.Team[ OUR_TEAM ].bLastID; i++ )
y = TOP_Y + TOP_Y_TEXT_BUFFER - bListOffset;
for( i = gTacticalStatus.Team[OUR_TEAM].bFirstID; i <= gTacticalStatus.Team[OUR_TEAM].bLastID; i++)
{
if( MercPtrs[ i ]->bActive && MercPtrs[ i ]->stats.bLife && !(MercPtrs[ i ]->flags.uiStatusFlags & SOLDIER_VEHICLE) )
if( MercPtrs[i]->bActive && MercPtrs[i]->stats.bLife && !(MercPtrs[i]->flags.uiStatusFlags & SOLDIER_VEHICLE) )
{
if ( PlayerMercInvolvedInThisCombat( MercPtrs[ i ] ) )
{ //involved
if( line == giHilitedInvolved )
SetFontForeground( FONT_WHITE );
else
SetFontForeground( FONT_YELLOW );
if( PlayerMercInvolvedInThisCombat( MercPtrs[ i ] ) )
{
//NAME
wcscpy( str, MercPtrs[ i ]->name );
x = 17 + (52-StringPixLength( str, BLOCKFONT2)) / 2;
mprintf( x + xResOffset , y + yResOffset, str );
x = 17 + (52 - StringPixLength(str, BLOCKFONT2)) / 2;
mprintf( x + xOffset, y + yOffset, str );
//ASSIGN
GetMapscreenMercAssignmentString( MercPtrs[ i ], str );
x = 72 + (54-StringPixLength( str, BLOCKFONT2)) / 2;
mprintf( x + xResOffset, y + yResOffset, str );
x = 72 + (54 - StringPixLength(str, BLOCKFONT2)) / 2;
mprintf( x + xOffset, y + yOffset, str );
//COND
GetSoldierConditionInfo( MercPtrs[ i ], str, &ubHPPercent, &ubBPPercent );
x = 129 + (58-StringPixLength( str, BLOCKFONT2)) / 2;
mprintf( x + xResOffset, y + yResOffset, str );
x = 129 + (58 - StringPixLength(str, BLOCKFONT2)) / 2;
mprintf( x + xOffset, y + yOffset, str );
//HP
swprintf( str, L"%d%%", ubHPPercent );
x = 189 + (25-StringPixLength( str, BLOCKFONT2)) / 2;
x = 189 + (25 - StringPixLength(str, BLOCKFONT2)) / 2;
wcscat( str, sSpecialCharacters[0] );
mprintf( x + xResOffset, y + yResOffset, str );
mprintf( x + xOffset, y + yOffset, str );
//BP
swprintf( str, L"%d%%", ubBPPercent );
x = 217 + (25-StringPixLength( str, BLOCKFONT2)) / 2;
wcscat( str, sSpecialCharacters[0] );
mprintf( x + xResOffset, y + yResOffset, str );
line++;
mprintf( x + xOffset, y + yOffset, str );
y += ROW_HEIGHT;
}
}
@@ -1511,51 +1616,44 @@ void RenderPreBattleInterface()
// | NAME | ASSIGN | LOC | DEST | DEP |
if( !guiNumUninvolved )
{
SetFontForeground( FONT_YELLOW );
wcscpy( str, gpStrategicString[ STR_PB_NONE ] );
x = 17 + (52-StringPixLength( str, BLOCKFONT2)) / 2;
y = BOTTOM_Y + ROW_HEIGHT + 2 + ACTUAL_HEIGHT;
mprintf( x + xResOffset, y + yResOffset, str );
x = 17 + (52 - StringPixLength( str, BLOCKFONT2)) / 2;
mprintf( x + xOffset, yOffset + TOP_Y + TOP_Y_TEXT_BUFFER + ubUninvolvedStartY + UNINVOLVED_RELEVANT_HEIGHT - bListOffset, str );
}
else
{
pGroup = gpGroupList;
y = BOTTOM_Y + ROW_HEIGHT + 2 + ACTUAL_HEIGHT;
for( i = gTacticalStatus.Team[ OUR_TEAM ].bFirstID; i <= gTacticalStatus.Team[ OUR_TEAM ].bLastID; i++ )
y = TOP_Y + TOP_Y_TEXT_BUFFER + ubUninvolvedStartY + UNINVOLVED_RELEVANT_HEIGHT - bListOffset;
for( i = gTacticalStatus.Team[OUR_TEAM].bFirstID; i <= gTacticalStatus.Team[OUR_TEAM].bLastID; i++ )
{
if( MercPtrs[ i ]->bActive && MercPtrs[ i ]->stats.bLife && !(MercPtrs[ i ]->flags.uiStatusFlags & SOLDIER_VEHICLE) )
{
if ( !PlayerMercInvolvedInThisCombat( MercPtrs[ i ] ) )
if( !PlayerMercInvolvedInThisCombat(MercPtrs[ i ]) )
{
// uninvolved
if( line == giHilitedUninvolved )
SetFontForeground( FONT_WHITE );
else
SetFontForeground( FONT_YELLOW );
//NAME
wcscpy( str, MercPtrs[ i ]->name );
x = 17 + (52-StringPixLength( str, BLOCKFONT2)) / 2;
mprintf( x + xResOffset, y + yResOffset, str );
x = 17 + (52 - StringPixLength(str, BLOCKFONT2)) / 2;
mprintf( x + xOffset, y + yOffset, str );
//ASSIGN
GetMapscreenMercAssignmentString( MercPtrs[ i ], str );
x = 72 + (54-StringPixLength( str, BLOCKFONT2)) / 2;
mprintf( x + xResOffset, y + yResOffset, str );
x = 72 + (54 - StringPixLength(str, BLOCKFONT2)) / 2;
mprintf( x + xOffset, y + yOffset, str );
//LOC
GetMapscreenMercLocationString( MercPtrs[ i ], str );
x = 128 + (33-StringPixLength( str, BLOCKFONT2)) / 2;
mprintf( x + xResOffset, y + yResOffset, str );
x = 128 + (33 - StringPixLength(str, BLOCKFONT2)) / 2;
mprintf( x + xOffset, y + yOffset, str );
//DEST
GetMapscreenMercDestinationString( MercPtrs[ i ], str );
if( wcslen( str ) > 0 )
if (wcslen(str) > 0)
{
x = 164 + (41-StringPixLength( str, BLOCKFONT2)) / 2;
mprintf( x + xResOffset, y + yResOffset, str );
x = 164 + (41 - StringPixLength(str, BLOCKFONT2)) / 2;
mprintf( x + xOffset, y + yOffset, str );
}
//DEP
GetMapscreenMercDepartureString( MercPtrs[ i ], str, &ubJunk );
x = 208 + (34-StringPixLength( str, BLOCKFONT2)) / 2;
mprintf( x + xResOffset, y + yResOffset, str );
line++;
x = 208 + (34 - StringPixLength(str, BLOCKFONT2)) / 2;
mprintf(x + xOffset, y + yOffset, str);
y += ROW_HEIGHT;
}
}
@@ -1565,12 +1663,7 @@ void RenderPreBattleInterface()
// mark any and ALL pop up boxes as altered
MarkAllBoxesAsAltered( );
if(!gfZoomDone)
RestoreExternBackgroundRect( 0 + xResOffset, 0 + yResOffset, 261 + xResOffset, 359 + yResOffset );
else if(!guiNumUninvolved)
RestoreExternBackgroundRect( 0 + xResOffset, 0 + yResOffset, 261 + xResOffset, 389 + yResOffset );
else
RestoreExternBackgroundRect( 0 + xResOffset, 0 + yResOffset, 261 + xResOffset, y + yResOffset );
RestoreExternBackgroundRect( 0 + xOffset, 0 + yOffset, PREBATTLE_INTERFACE_WIDTH, iPrebattleInterfaceHeight );
// restore font destinanation buffer to the frame buffer
SetFontDestBuffer( FRAME_BUFFER, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, FALSE );
@@ -1580,7 +1673,7 @@ void RenderPreBattleInterface()
RenderPBHeader( &x, &width ); //the text is important enough to blink.
}
//InvalidateRegion( 0, 0, 261, 359 );
InvalidateRegion( 0, 0, PREBATTLE_INTERFACE_WIDTH, iPrebattleInterfaceHeight );
if( gfEnterAutoResolveMode )
{
gfEnterAutoResolveMode = FALSE;
@@ -1589,7 +1682,6 @@ void RenderPreBattleInterface()
}
gfIgnoreAllInput = FALSE;
}
void AutoResolveBattleCallback( GUI_BUTTON *btn, INT32 reason )
@@ -2520,6 +2612,10 @@ void LogBattleResults( UINT8 ubVictoryCode)
break;
case CONCEALINSERTION_CODE:
break;
case TRANSPORT_INTERCEPT_CODE:
AddHistoryToPlayersLog( HISTORY_INTERCEPTED_TRANSPORT_GROUP, 0, GetWorldTotalMin(), sSectorX, sSectorY );
NotifyTransportGroupDefeated();
break;
}
// Flugente: campaign stats
@@ -2534,6 +2630,7 @@ void LogBattleResults( UINT8 ubVictoryCode)
AddHistoryToPlayersLog( HISTORY_LOSTTOWNSECTOR, 0, GetWorldTotalMin(), sSectorX, sSectorY );
break;
case ENEMY_ENCOUNTER_CODE:
case TRANSPORT_INTERCEPT_CODE:
AddHistoryToPlayersLog( HISTORY_LOSTBATTLE, 0, GetWorldTotalMin(), sSectorX, sSectorY );
break;
case ENEMY_AMBUSH_CODE:
@@ -2567,6 +2664,7 @@ void LogBattleResults( UINT8 ubVictoryCode)
gCurrentIncident.usIncidentFlags |= INCIDENT_ATTACK_ENEMY;
break;
case ENEMY_ENCOUNTER_CODE:
case TRANSPORT_INTERCEPT_CODE:
case ENTERING_ENEMY_SECTOR_CODE:
case CREATURE_ATTACK_CODE:
case ENTERING_BLOODCAT_LAIR_CODE:
+4 -1
View File
@@ -7,6 +7,7 @@
void InitPreBattleInterface( GROUP *pBattleGroup, BOOLEAN fPersistantPBI );
void KillPreBattleInterface();
void RenderPreBattleInterface();
void ScrollPreBattleInterface( BOOLEAN fUp );
extern BOOLEAN gfPreBattleInterfaceActive;
extern BOOLEAN gfDisplayPotentialRetreatPaths;
@@ -47,6 +48,8 @@ enum
BLOODCAT_ATTACK_CODE, // Flugente: like CREATURE_ATTACK_CODE, but with cats
ZOMBIE_ATTACK_CODE, // Flugente: like CREATURE_ATTACK_CODE, but with zombies
BANDIT_ATTACK_CODE, // Flugente: like CREATURE_ATTACK_CODE, but with bandits
TRANSPORT_INTERCEPT_CODE, // rftr: like ENEMY_ENCOUNTER_CODE
};
extern BOOLEAN gfAutoAmbush;
@@ -112,4 +115,4 @@ enum
};
void LogBattleResults( UINT8 ubVictoryCode);
#endif
#endif
+54 -3
View File
@@ -42,6 +42,7 @@
#include "CampaignStats.h" // added by Flugente
#include "ASD.h" // added by Flugente
#include "Interface Panels.h"
#include "Strategic Transport Groups.h"
#ifdef JA2BETAVERSION
extern BOOLEAN gfClearCreatureQuest;
@@ -98,7 +99,6 @@ void HandleBloodCatDeaths( SECTORINFO *pSector );
extern void Ensure_RepairedGarrisonGroup( GARRISON_GROUP **ppGarrison, INT32 *pGarraySize );
void ValidateEnemiesHaveWeapons()
{
#ifdef JA2BETAVERSION
@@ -613,6 +613,9 @@ BOOLEAN PrepareEnemyForSectorBattle()
gfPendingNonPlayerTeam[ENEMY_TEAM] = FALSE;
// rftr: clear cached transport groups
ClearTransportGroupMap();
if( gbWorldSectorZ > 0 )
return PrepareEnemyForUndergroundBattle();
@@ -640,9 +643,9 @@ BOOLEAN PrepareEnemyForSectorBattle()
for( unsigned ubIndex = 0; ubIndex < ubDirNumber; ++ubIndex )
{
while ( NumMobileEnemiesInSector( SECTORX( pusMoveDir[ubIndex][0] ), SECTORY( pusMoveDir[ubIndex][0] ) ) && GetNonPlayerGroupInSector( SECTORX( pusMoveDir[ubIndex][0] ), SECTORY( pusMoveDir[ubIndex][0] ), ENEMY_TEAM ) )
while ( NumMobileEnemiesInSector( SECTORX( pusMoveDir[ubIndex][0] ), SECTORY( pusMoveDir[ubIndex][0] ) ) && GetNonPlayerGroupInSectorForReinforcement( SECTORX( pusMoveDir[ubIndex][0] ), SECTORY( pusMoveDir[ubIndex][0] ), ENEMY_TEAM ) )
{
pGroup = GetNonPlayerGroupInSector( SECTORX( pusMoveDir[ubIndex][0] ), SECTORY( pusMoveDir[ubIndex][0] ), ENEMY_TEAM );
pGroup = GetNonPlayerGroupInSectorForReinforcement( SECTORX( pusMoveDir[ubIndex][0] ), SECTORY( pusMoveDir[ubIndex][0] ), ENEMY_TEAM );
pGroup->ubPrevX = pGroup->ubSectorX;
pGroup->ubPrevY = pGroup->ubSectorY;
@@ -669,10 +672,23 @@ BOOLEAN PrepareEnemyForSectorBattle()
HandleArrivalOfReinforcements( pGroup );
}
// for transport groups, track how many enemies of each type we're adding so we can update drops for them
if (pGroup->usGroupTeam == ENEMY_TEAM && pGroup->pEnemyGroup->ubIntention == TRANSPORT && pGroup->ubSectorX == gWorldSectorX && pGroup->ubSectorY == gWorldSectorY && !gbWorldSectorZ)
{
AddToTransportGroupMap(pGroup->ubGroupID, SOLDIER_CLASS_ADMINISTRATOR, pGroup->pEnemyGroup->ubNumAdmins);
AddToTransportGroupMap(pGroup->ubGroupID, SOLDIER_CLASS_ARMY, pGroup->pEnemyGroup->ubNumTroops);
AddToTransportGroupMap(pGroup->ubGroupID, SOLDIER_CLASS_ELITE, pGroup->pEnemyGroup->ubNumElites);
AddToTransportGroupMap(pGroup->ubGroupID, SOLDIER_CLASS_ROBOT, pGroup->pEnemyGroup->ubNumRobots);
AddToTransportGroupMap(pGroup->ubGroupID, SOLDIER_CLASS_JEEP, pGroup->pEnemyGroup->ubNumJeeps);
AddToTransportGroupMap(pGroup->ubGroupID, SOLDIER_CLASS_TANK, pGroup->pEnemyGroup->ubNumTanks);
}
pGroup = pGroup->next;
}
}
UpdateTransportGroupInventory();
ValidateEnemiesHaveWeapons();
UnPauseGame();
return ( ( BOOLEAN) ( gpBattleGroup->ubGroupSize > 0 ) );
@@ -852,6 +868,7 @@ BOOLEAN PrepareEnemyForSectorBattle()
if ( pGroup->usGroupTeam == ENEMY_TEAM && !pGroup->fVehicle &&
pGroup->ubSectorX == gWorldSectorX && pGroup->ubSectorY == gWorldSectorY && !gbWorldSectorZ )
{ //Process enemy group in sector.
const BOOLEAN isTransportGroup = pGroup->pEnemyGroup->ubIntention == TRANSPORT;
if( sNumSlots > 0 )
{
AssertGE(pGroup->pEnemyGroup->ubNumAdmins, pGroup->pEnemyGroup->ubAdminsInBattle);
@@ -865,6 +882,9 @@ BOOLEAN PrepareEnemyForSectorBattle()
}
pGroup->pEnemyGroup->ubAdminsInBattle += ubNumAdmins;
ubTotalAdmins += ubNumAdmins;
if (isTransportGroup)
AddToTransportGroupMap(pGroup->ubGroupID, SOLDIER_CLASS_ADMINISTRATOR, ubNumAdmins);
}
if( sNumSlots > 0 )
{ //Add regular army forces.
@@ -879,6 +899,9 @@ BOOLEAN PrepareEnemyForSectorBattle()
}
pGroup->pEnemyGroup->ubTroopsInBattle += ubNumTroops;
ubTotalTroops += ubNumTroops;
if (isTransportGroup)
AddToTransportGroupMap(pGroup->ubGroupID, SOLDIER_CLASS_ARMY, ubNumTroops);
}
if( sNumSlots > 0 )
{ //Add elite troops
@@ -893,6 +916,9 @@ BOOLEAN PrepareEnemyForSectorBattle()
}
pGroup->pEnemyGroup->ubElitesInBattle += ubNumElites;
ubTotalElites += ubNumElites;
if (isTransportGroup)
AddToTransportGroupMap(pGroup->ubGroupID, SOLDIER_CLASS_ELITE, ubNumElites);
}
if( sNumSlots > 0 )
{ //Add robots
@@ -907,6 +933,9 @@ BOOLEAN PrepareEnemyForSectorBattle()
}
pGroup->pEnemyGroup->ubRobotsInBattle += ubNumRobots;
ubTotalRobots += ubNumRobots;
if (isTransportGroup)
AddToTransportGroupMap(pGroup->ubGroupID, SOLDIER_CLASS_ROBOT, ubNumRobots);
}
if( sNumSlots > 0 )
{ //Add tanks
@@ -921,6 +950,9 @@ BOOLEAN PrepareEnemyForSectorBattle()
}
pGroup->pEnemyGroup->ubTanksInBattle += ubNumTanks;
ubTotalTanks += ubNumTanks;
if (isTransportGroup)
AddToTransportGroupMap(pGroup->ubGroupID, SOLDIER_CLASS_TANK, ubNumTanks);
}
if ( sNumSlots > 0 )
{
@@ -936,6 +968,9 @@ BOOLEAN PrepareEnemyForSectorBattle()
}
pGroup->pEnemyGroup->ubJeepsInBattle += ubNumJeeps;
ubTotalJeeps += ubNumJeeps;
if (isTransportGroup)
AddToTransportGroupMap(pGroup->ubGroupID, SOLDIER_CLASS_JEEP, ubNumJeeps);
}
//NOTE:
//no provisions for profile troop leader or retreat groups yet.
@@ -976,6 +1011,7 @@ BOOLEAN PrepareEnemyForSectorBattle()
unsigned firstSlot = gTacticalStatus.Team[ ENEMY_TEAM ].bFirstID;
unsigned lastSlot = gTacticalStatus.Team[ ENEMY_TEAM ].bLastID;
unsigned slotsAvailable = lastSlot-firstSlot+1;
while( pGroup && sNumSlots > 0 )
{
if ( pGroup->usGroupTeam != OUR_TEAM && !pGroup->fVehicle &&
@@ -1088,6 +1124,7 @@ BOOLEAN PrepareEnemyForSectorBattle()
}
break;
}
}
// Flugente: instead of just crashing the game without any explanation to the user, ignore this issue if it still exists.
@@ -1103,6 +1140,8 @@ BOOLEAN PrepareEnemyForSectorBattle()
pGroup = pGroup->next;
}
UpdateTransportGroupInventory();
ValidateEnemiesHaveWeapons();
UnPauseGame();
@@ -2145,6 +2184,16 @@ void AddEnemiesToBattle( GROUP *pGroup, UINT8 ubStrategicInsertionCode, UINT8 ub
UINT8 ubTotalSoldiers;
UINT8 bDesiredDirection=0;
// while transport groups can't normally reinforce, this covers the case where a transport group enters a sector (via normal movement)
// where a battle is in progress.
if (pGroup && pGroup->pEnemyGroup->ubIntention == TRANSPORT)
{
AddToTransportGroupMap(pGroup->ubGroupID, SOLDIER_CLASS_ADMINISTRATOR, ubNumAdmins);
AddToTransportGroupMap(pGroup->ubGroupID, SOLDIER_CLASS_ARMY, ubNumTroops);
AddToTransportGroupMap(pGroup->ubGroupID, SOLDIER_CLASS_ELITE, ubNumElites);
AddToTransportGroupMap(pGroup->ubGroupID, SOLDIER_CLASS_JEEP, ubNumJeeps);
}
switch( ubStrategicInsertionCode )
{
case INSERTION_CODE_NORTH: bDesiredDirection = SOUTHEAST; break;
@@ -3594,3 +3643,5 @@ void CorrectTurncoatCount( INT16 sSectorX, INT16 sSectorY )
pGroup = pGroup->next;
}
}
+59 -6
View File
@@ -41,8 +41,10 @@ How to add a new admin action:
- if effect applies outside of towns, add help text range band as appropriate to SetupAdminActionBox
How to add a new mission:
- add to the RebelCommandAgentMissions enum in the header
- add strings to text files (szRebelCommandAgentMissionsText)
- add strings to text files (szRebelCommandText (trait bonuses), szRebelCommandAgentMissionsText (title/description))
- add to the RebelCommandText and RebelCommandAgentMissions enums in the header
- add to the RebelCommandAgentMissionsText enums in the cpp
- add mission variables to GameSettings
- add values to MissionHelpers::missionInfo table in SetupInfo()
- add to valid check in HandleStrategicEvent() (allows advance from first event/prepare to second event/active effect)
- add to SetupMissionAgentBox() (mission description and merc bonus text)
@@ -91,6 +93,7 @@ Points of interest:
#include "Strategic Mines.h"
#include "Strategic Movement.h"
#include "Strategic Town Loyalty.h"
#include "Strategic Transport Groups.h"
#include "Structure Wrap.h"
#include "Tactical Save.h"
#include "Text.h"
@@ -405,6 +408,7 @@ enum RebelCommandAgentMissionsText // keep this synced with szRebelCommandAgentM
{
MISSION_TEXT(DEEP_DEPLOYMENT)
MISSION_TEXT(DISRUPT_ASD)
MISSION_TEXT(FORGE_TRANSPORT_ORDERS)
MISSION_TEXT(GET_ENEMY_MOVEMENT_TARGETS)
MISSION_TEXT(IMPROVE_LOCAL_SHOPS)
MISSION_TEXT(REDUCE_STRATEGIC_DECISION_SPEED)
@@ -2221,6 +2225,7 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index)
{
case RCAM_DEEP_DEPLOYMENT: swprintf(sText, szRebelCommandAgentMissionsText[RCAMT_DEEP_DEPLOYMENT_TITLE]); break;
case RCAM_DISRUPT_ASD: swprintf(sText, szRebelCommandAgentMissionsText[RCAMT_DISRUPT_ASD_TITLE]); break;
case RCAM_FORGE_TRANSPORT_ORDERS: swprintf(sText, szRebelCommandAgentMissionsText[RCAMT_FORGE_TRANSPORT_ORDERS_TITLE]); break;
case RCAM_GET_ENEMY_MOVEMENT_TARGETS: swprintf(sText, szRebelCommandAgentMissionsText[RCAMT_GET_ENEMY_MOVEMENT_TARGETS_TITLE]); break;
case RCAM_IMPROVE_LOCAL_SHOPS: swprintf(sText, szRebelCommandAgentMissionsText[RCAMT_IMPROVE_LOCAL_SHOPS_TITLE]); break;
case RCAM_REDUCE_STRATEGIC_DECISION_SPEED: swprintf(sText, szRebelCommandAgentMissionsText[RCAMT_REDUCE_STRATEGIC_DECISION_SPEED_TITLE]); break;
@@ -2241,6 +2246,7 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index)
{
case RCAM_DEEP_DEPLOYMENT: missionDurationBase = gRebelCommandSettings.iDeepDeploymentDuration; break;
case RCAM_DISRUPT_ASD: missionDurationBase = gRebelCommandSettings.iDisruptAsdDuration; break;
case RCAM_FORGE_TRANSPORT_ORDERS: missionDurationBase = 1; break; // instant effect
case RCAM_GET_ENEMY_MOVEMENT_TARGETS: missionDurationBase = gRebelCommandSettings.iGetEnemyMovementTargetsDuration; break;
case RCAM_IMPROVE_LOCAL_SHOPS: missionDurationBase = gRebelCommandSettings.iImproveLocalShopsDuration; break;
case RCAM_REDUCE_STRATEGIC_DECISION_SPEED: missionDurationBase = gRebelCommandSettings.iReduceStrategicDecisionSpeedDuration; break;
@@ -2264,6 +2270,7 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index)
{
case RCAM_DEEP_DEPLOYMENT: missionSuccessChanceBase = gRebelCommandSettings.iDeepDeploymentSuccessChance; break;
case RCAM_DISRUPT_ASD: missionSuccessChanceBase = gRebelCommandSettings.iDisruptAsdSuccessChance; break;
case RCAM_FORGE_TRANSPORT_ORDERS: missionSuccessChanceBase = gRebelCommandSettings.iForgeTransportOrdersSuccessChance; break;
case RCAM_GET_ENEMY_MOVEMENT_TARGETS: missionSuccessChanceBase = gRebelCommandSettings.iGetEnemyMovementTargetsSuccessChance; break;
case RCAM_IMPROVE_LOCAL_SHOPS: missionSuccessChanceBase = gRebelCommandSettings.iImproveLocalShopsSuccessChance; break;
case RCAM_REDUCE_STRATEGIC_DECISION_SPEED: missionSuccessChanceBase = gRebelCommandSettings.iReduceStrategicDecisionSpeedSuccessChance; break;
@@ -2284,6 +2291,7 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index)
{
case RCAM_DEEP_DEPLOYMENT: swprintf(sText, szRebelCommandAgentMissionsText[RCAMT_DEEP_DEPLOYMENT_DESC]); break;
case RCAM_DISRUPT_ASD: swprintf(sText, szRebelCommandAgentMissionsText[RCAMT_DISRUPT_ASD_DESC]); break;
case RCAM_FORGE_TRANSPORT_ORDERS: swprintf(sText, szRebelCommandAgentMissionsText[RCAMT_FORGE_TRANSPORT_ORDERS_DESC]); break;
case RCAM_GET_ENEMY_MOVEMENT_TARGETS: swprintf(sText, szRebelCommandAgentMissionsText[RCAMT_GET_ENEMY_MOVEMENT_TARGETS_DESC]); break;
case RCAM_IMPROVE_LOCAL_SHOPS: swprintf(sText, szRebelCommandAgentMissionsText[RCAMT_IMPROVE_LOCAL_SHOPS_DESC]); break;
case RCAM_REDUCE_STRATEGIC_DECISION_SPEED: swprintf(sText, szRebelCommandAgentMissionsText[RCAMT_REDUCE_STRATEGIC_DECISION_SPEED_DESC]); break;
@@ -2454,6 +2462,12 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index)
}
}
case RCAM_FORGE_TRANSPORT_ORDERS:
{
// no special modifiers. included for completeness.
}
break;
case RCAM_GET_ENEMY_MOVEMENT_TARGETS:
{
// no special modifiers. included for completeness.
@@ -2610,7 +2624,13 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index)
swprintf(sText, szRebelCommandText[RCT_MISSION_CANT_START_CONTRACT_EXPIRING]);
}
}
else if (agentIndex[index] == mercs.size() && rebelCommandSaveInfo.availableMissions[index] == RCAM_SEND_SUPPLIES_TO_TOWN)
else if (agentIndex[index] == mercs.size() &&
(
rebelCommandSaveInfo.availableMissions[index] == RCAM_SEND_SUPPLIES_TO_TOWN ||
rebelCommandSaveInfo.availableMissions[index] == RCAM_FORGE_TRANSPORT_ORDERS
)
)
{
canStartMission = FALSE;
swprintf(sText, szRebelCommandText[RCT_MISSION_CANT_USE_REBEL_AGENT]);
@@ -2847,6 +2867,14 @@ void PrepareMission(INT8 index)
}
break;
case RCAM_FORGE_TRANSPORT_ORDERS:
{
missionTitle = RCAMT_FORGE_TRANSPORT_ORDERS_TITLE;
missionSuccessChance = gRebelCommandSettings.iForgeTransportOrdersSuccessChance;
missionDuration = 12;
}
break;
case RCAM_GET_ENEMY_MOVEMENT_TARGETS:
{
missionTitle = RCAMT_GET_ENEMY_MOVEMENT_TARGETS_TITLE;
@@ -3897,6 +3925,7 @@ void DailyUpdate()
{
if (i == RCAM_SOLDIER_BOUNTIES_KINGPIN && !(CheckFact(FACT_KINGPIN_INTRODUCED_SELF, 0) == TRUE && CheckFact(FACT_KINGPIN_DEAD, 0) == FALSE && CheckFact(FACT_KINGPIN_IS_ENEMY, 0) == FALSE && CurrentPlayerProgressPercentage() >= 30)) continue;
else if (i == RCAM_DISRUPT_ASD && gGameExternalOptions.fASDActive == FALSE) continue;
else if (i == RCAM_FORGE_TRANSPORT_ORDERS && gGameExternalOptions.fStrategicTransportGroupsEnabled == FALSE) continue;
validMissions.insert(static_cast<RebelCommandAgentMissions>(i));
}
@@ -4299,6 +4328,16 @@ void SetupInfo()
{0, 0, 0, 0},
{0, MissionHelpers::DISRUPT_ASD_STEAL_FUEL, MissionHelpers::DISRUPT_ASD_DESTROY_RESERVES, 0}
});
//RCAM_FORGE_TRANSPORT_ORDERS
MissionHelpers::missionInfo.push_back(
{
{COVERT_NT },
{-1},
{0},
{0.f},
{0},
{0}
});
//RCAM_GET_ENEMY_MOVEMENT_TARGETS
MissionHelpers::missionInfo.push_back(
{
@@ -4390,7 +4429,8 @@ void SetupInfo()
&& (gGameOptions.ubGameStyle == STYLE_SCIFI || !Item[i].scifi))
{
// coolness runs from 1-10, so apply offset
ItemIdCache::ammo[Item[i].ubCoolness-1].push_back(i);
const UINT8 coolness = min(max(1, Item[i].ubCoolness), 10);
ItemIdCache::ammo[coolness-1].push_back(i);
}
}
}
@@ -4902,6 +4942,7 @@ void HandleStrategicEvent(const UINT32 eventParam)
{
case RCAM_DEEP_DEPLOYMENT:
case RCAM_DISRUPT_ASD:
case RCAM_FORGE_TRANSPORT_ORDERS:
case RCAM_GET_ENEMY_MOVEMENT_TARGETS:
case RCAM_IMPROVE_LOCAL_SHOPS:
case RCAM_REDUCE_STRATEGIC_DECISION_SPEED:
@@ -4926,7 +4967,15 @@ void HandleStrategicEvent(const UINT32 eventParam)
if (validMission)
{
const UINT32 activatedMissionParam = SerialiseMissionSecondEvent(evt1.sentGenericRebelAgent, evt1.mercProfileId, mission, extraBits);
AddStrategicEvent(EVENT_REBELCOMMAND, GetWorldTotalMin() + 60 * evt1.missionDurationInHours, activatedMissionParam);
if (mission == RCAM_FORGE_TRANSPORT_ORDERS)
{
// don't send a follow-up event for instant-result missions
}
else
{
AddStrategicEvent(EVENT_REBELCOMMAND, GetWorldTotalMin() + 60 * evt1.missionDurationInHours, activatedMissionParam);
missionMap.insert(std::make_pair(mission, activatedMissionParam));
}
if (!evt1.sentGenericRebelAgent)
{
@@ -4935,6 +4984,11 @@ void HandleStrategicEvent(const UINT32 eventParam)
SOLDIERTYPE* pSoldier = MercPtrs[i];
if (pSoldier->ubProfile == evt1.mercProfileId)
{
if (mission == RCAM_FORGE_TRANSPORT_ORDERS)
{
ForceDeployTransportGroup(SECTOR(pSoldier->sSectorX, pSoldier->sSectorY));
}
// mission successful! give some experience pts
StatChange(pSoldier, LDRAMT, 20, FROM_SUCCESS);
StatChange(pSoldier, WISDOMAMT, 15, FROM_SUCCESS);
@@ -4943,7 +4997,6 @@ void HandleStrategicEvent(const UINT32 eventParam)
}
}
missionMap.insert(std::make_pair(mission, activatedMissionParam));
swprintf(msgBoxText, szRebelCommandText[RCT_MISSION_SUCCESS], szRebelCommandAgentMissionsText[evt1.missionId * 2]);
swprintf(screenMsgText, szRebelCommandText[RCT_MISSION_SUCCESS], szRebelCommandAgentMissionsText[evt1.missionId * 2]);
ScreenMsg(FONT_MCOLOR_LTGREEN, MSG_INTERFACE, screenMsgText);
+1
View File
@@ -78,6 +78,7 @@ enum RebelCommandAgentMissions
RCAM_NONE = -1,
RCAM_DEEP_DEPLOYMENT = 0,
RCAM_DISRUPT_ASD, // only available if ASD enabled
RCAM_FORGE_TRANSPORT_ORDERS,
RCAM_GET_ENEMY_MOVEMENT_TARGETS, // aka Strategic Intel
RCAM_IMPROVE_LOCAL_SHOPS,
RCAM_REDUCE_STRATEGIC_DECISION_SPEED, // aka Slower Strategic Decisions
+3 -3
View File
@@ -246,13 +246,13 @@ BOOLEAN ARMoveBestMilitiaManFromAdjacentSector(INT16 sMapX, INT16 sMapY)
return TRUE;
}
GROUP* GetNonPlayerGroupInSector( INT16 sMapX, INT16 sMapY, UINT8 usTeam )
GROUP* GetNonPlayerGroupInSectorForReinforcement( INT16 sMapX, INT16 sMapY, UINT8 usTeam )
{
GROUP *curr;
curr = gpGroupList;
while( curr )
{
if ( curr->ubSectorX == sMapX && curr->ubSectorY == sMapY && curr->usGroupTeam == usTeam && curr->ubGroupID )
if ( curr->ubSectorX == sMapX && curr->ubSectorY == sMapY && curr->usGroupTeam == usTeam && curr->ubGroupID && (curr->usGroupTeam != ENEMY_TEAM || curr->pEnemyGroup->ubIntention != TRANSPORT) )
return curr;
curr = curr->next;
}
@@ -280,7 +280,7 @@ UINT8 DoReinforcementAsPendingNonPlayer( INT16 sMapX, INT16 sMapY, UINT8 usTeam
for( ubIndex = 0; ubIndex < ubDirNumber; ++ubIndex )
{
while ( (pGroup = GetNonPlayerGroupInSector( SECTORX( pusMoveDir[ubIndex][0] ), SECTORY( pusMoveDir[ubIndex][0] ), usTeam )) != NULL )
while ( (pGroup = GetNonPlayerGroupInSectorForReinforcement( SECTORX( pusMoveDir[ubIndex][0] ), SECTORY( pusMoveDir[ubIndex][0] ), usTeam )) != NULL )
{
pGroup->ubPrevX = pGroup->ubSectorX;
pGroup->ubPrevY = pGroup->ubSectorY;
+1 -1
View File
@@ -12,6 +12,6 @@ UINT8 NumEnemiesInFiveSectors( INT16 sMapX, INT16 sMapY );
//For Tactical
UINT8 DoReinforcementAsPendingNonPlayer( INT16 sMapX, INT16 sMapY, UINT8 usTeam );
void AddPossiblePendingMilitiaToBattle();
GROUP* GetNonPlayerGroupInSector( INT16 sMapX, INT16 sMapY, UINT8 usTeam );
GROUP* GetNonPlayerGroupInSectorForReinforcement( INT16 sMapX, INT16 sMapY, UINT8 usTeam );
#endif
+102 -73
View File
@@ -33,6 +33,9 @@
#include "interface dialogue.h"
#include "ASD.h" // added by Flugente
#include "Rebel Command.h"
#include "Game Event Hook.h"
#include "Strategic Town Loyalty.h"
#include "Strategic Transport Groups.h"
#include "GameInitOptionsScreen.h"
@@ -488,7 +491,6 @@ extern INT16 sWorldSectorLocationOfFirstBattle;
void ReassignAIGroup( GROUP **pGroup );
void TransferGroupToPool( GROUP **pGroup );
void SendGroupToPool( GROUP **pGroup );
//Simply orders all garrisons to take troops from the patrol groups and send the closest troops from them. Any garrison,
//whom there request isn't fulfilled (due to lack of troops), will recieve their reinforcements from the queen (P3).
@@ -2418,6 +2420,11 @@ DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Strategic5");
}
}
}
else if (pGroup->pEnemyGroup->ubIntention == TRANSPORT)
{
ProcessTransportGroupReachedDestination(pGroup);
return TRUE;
}
else
{ //This is a floating group at his final destination...
if( pGroup->pEnemyGroup->ubIntention != STAGING && pGroup->pEnemyGroup->ubIntention != REINFORCEMENTS )
@@ -3458,7 +3465,7 @@ void EvaluateQueenSituation()
dEnemyGeneralsSpeedupFactor *= RebelCommand::GetStrategicDecisionSpeedModifier();
uiOffset += dEnemyGeneralsSpeedupFactor * (zDiffSetting[gGameOptions.ubDifficultyLevel].iBaseDelayInMinutesBetweenEvaluations + Random( zDiffSetting[gGameOptions.ubDifficultyLevel].iEvaluationDelayVariance ));
// Check/update reinforcements pool if old behavior is enabled
if ( !gfUnlimitedTroops && zDiffSetting[gGameOptions.ubDifficultyLevel].iQueenPoolIncrementDaysPerDifficultyLevel == 0 )
{
@@ -3488,88 +3495,88 @@ void EvaluateQueenSituation()
// Gradually promote any remaining admins into troops
UpgradeAdminsToTroops();
if( ( giRequestPoints <= 0 ) || ( ( giReinforcementPoints <= 0 ) && ( giReinforcementPool <= 0 ) ) )
{ //we either have no reinforcements or request for reinforcements.
return;
}
// consider deploying a transport group
ExecuteStrategicAIAction( NPC_ACTION_DEPLOY_TRANSPORT_GROUP, 0, 0 );
// anv: only consider garrisons and patrols that can be reinforced
// otherwise unreinforcable groups will stall the rest, effectively breaking entire system
Ensure_RepairedGarrisonGroup( &gGarrisonGroup, &giGarrisonArraySize ); /* added NULL fix, 2007-03-03, Sgt. Kolja */
for( i = 0; i < giGarrisonArraySize; i++ )
// we either have reinforcements or a request for reinforcements
if (giRequestPoints > 0 && (giReinforcementPoints > 0 || giReinforcementPool > 0))
{
RecalculateGarrisonWeight( i );
iWeight = gGarrisonGroup[ i ].bWeight;
if( iWeight > 0 )
// anv: only consider garrisons and patrols that can be reinforced
// otherwise unreinforcable groups will stall the rest, effectively breaking entire system
Ensure_RepairedGarrisonGroup( &gGarrisonGroup, &giGarrisonArraySize ); /* added NULL fix, 2007-03-03, Sgt. Kolja */
for( i = 0; i < giGarrisonArraySize; i++ )
{
if( !gGarrisonGroup[ i ].ubPendingGroupID &&
EnemyPermittedToAttackSector( NULL, gGarrisonGroup[ i ].ubSectorID ) &&
GarrisonRequestingMinimumReinforcements( i ) )
RecalculateGarrisonWeight( i );
iWeight = gGarrisonGroup[ i ].bWeight;
if( iWeight > 0 )
{
if( ReinforcementsApproved( i, &usDefencePoints ) )
if( !gGarrisonGroup[ i ].ubPendingGroupID &&
EnemyPermittedToAttackSector( NULL, gGarrisonGroup[ i ].ubSectorID ) &&
GarrisonRequestingMinimumReinforcements( i ) )
{
iApplicableGarrisonIds[iApplicableGarrisons] = i;
iApplicableGarrisons++;
iApplicableRequestPoints += gGarrisonGroup[ i ].bWeight;
if( ReinforcementsApproved( i, &usDefencePoints ) )
{
iApplicableGarrisonIds[iApplicableGarrisons] = i;
iApplicableGarrisons++;
iApplicableRequestPoints += gGarrisonGroup[ i ].bWeight;
}
}
}
}
}
for( i = 0; i < giPatrolArraySize; i++ )
{
RecalculatePatrolWeight( i );
iWeight = gPatrolGroup[ i ].bWeight;
if( iWeight > 0 )
for( i = 0; i < giPatrolArraySize; i++ )
{
if( !gPatrolGroup[ i ].ubPendingGroupID && PatrolRequestingMinimumReinforcements( i ) )
RecalculatePatrolWeight( i );
iWeight = gPatrolGroup[ i ].bWeight;
if( iWeight > 0 )
{
iApplicablePatrolIds[iApplicablePatrols] = i;
iApplicablePatrols++;
iApplicableRequestPoints += gPatrolGroup[ i ].bWeight;
if( !gPatrolGroup[ i ].ubPendingGroupID && PatrolRequestingMinimumReinforcements( i ) )
{
iApplicablePatrolIds[iApplicablePatrols] = i;
iApplicablePatrols++;
iApplicableRequestPoints += gPatrolGroup[ i ].bWeight;
}
}
}
}
if( !iApplicableRequestPoints )
{
return;
}
//now randomly choose who gets the reinforcements.
// giRequestPoints is the combined sum of all the individual weights of all garrisons and patrols requesting reinforcements
//iRandom = Random( giRequestPoints );
iRandom = Random( iApplicableRequestPoints );
iOrigRequestPoints = giRequestPoints; // debug only!
//go through garrisons first
for( i = 0; i < iApplicableGarrisons; i++ )
{
iSumOfAllWeights += iWeight; // debug only!
iWeight = gGarrisonGroup[ iApplicableGarrisonIds[i] ].bWeight;
if( iRandom < iWeight )
if( iApplicableRequestPoints )
{
//This is the group that gets the reinforcements!
if ( SendReinforcementsForGarrison( iApplicableGarrisonIds[i] , usDefencePoints, NULL ) )
return;
}
iRandom -= iWeight;
}
//now randomly choose who gets the reinforcements.
// giRequestPoints is the combined sum of all the individual weights of all garrisons and patrols requesting reinforcements
//iRandom = Random( giRequestPoints );
iRandom = Random( iApplicableRequestPoints );
//go through the patrol groups
for( i = 0; i < iApplicablePatrols; i++ )
{
iSumOfAllWeights += iWeight; // debug only!
iWeight = gPatrolGroup[ iApplicablePatrolIds[i] ].bWeight;
if( iRandom < iWeight )
{
//This is the group that gets the reinforcements!
if ( SendReinforcementsForPatrol( iApplicablePatrolIds[i], NULL ) )
return;
iOrigRequestPoints = giRequestPoints; // debug only!
//go through garrisons first
for( i = 0; i < iApplicableGarrisons; i++ )
{
iSumOfAllWeights += iWeight; // debug only!
iWeight = gGarrisonGroup[ iApplicableGarrisonIds[i] ].bWeight;
if( iRandom < iWeight )
{
//This is the group that gets the reinforcements!
if ( SendReinforcementsForGarrison( iApplicableGarrisonIds[i] , usDefencePoints, NULL ) )
return;
}
iRandom -= iWeight;
}
//go through the patrol groups
for( i = 0; i < iApplicablePatrols; i++ )
{
iSumOfAllWeights += iWeight; // debug only!
iWeight = gPatrolGroup[ iApplicablePatrolIds[i] ].bWeight;
if( iRandom < iWeight )
{
//This is the group that gets the reinforcements!
if ( SendReinforcementsForPatrol( iApplicablePatrolIds[i], NULL ) )
return;
}
iRandom -= iWeight;
}
}
iRandom -= iWeight;
}
ValidateWeights( 27 );
@@ -5125,7 +5132,7 @@ void ExecuteStrategicAIAction( UINT16 usActionCode, INT16 sSectorX, INT16 sSecto
if ( ubNumSoldiers )
{
InitializeGroup(GROUP_TYPE_ATTACK, ubNumSoldiers, grouptroops[0], groupelites[0], grouprobots[0], groupjeeps[0], grouptanks[0], Random(10) < difficultyMod);
totalusedsoldiers += grouptroops[0] + groupelites[0] + grouprobots[0], grouptanks[0] + groupjeeps[0];
totalusedsoldiers += grouptroops[0] + groupelites[0] + grouprobots[0] + grouptanks[0] + groupjeeps[0];
}
pGroup = CreateNewEnemyGroupDepartingFromSector( SECTOR( gModSettings.ubSAISpawnSectorX, gModSettings.ubSAISpawnSectorY ), 0, grouptroops[0], groupelites[0], grouprobots[0], grouptanks[0], groupjeeps[0] );
@@ -5386,6 +5393,14 @@ void ExecuteStrategicAIAction( UINT16 usActionCode, INT16 sSectorX, INT16 sSecto
gubNumAwareBattles = zDiffSetting[gGameOptions.ubDifficultyLevel].iNumAwareBattles;
break;
case NPC_ACTION_DEPLOY_TRANSPORT_GROUP:
DeployTransportGroup();
break;
case NPC_ACTION_RETURN_TRANSPORT_GROUP:
ReturnTransportGroup(option1);
break;
default:
ScreenMsg( FONT_RED, MSG_DEBUG, L"QueenAI failed to handle action code %d.", usActionCode );
break;
@@ -6403,8 +6418,14 @@ void UpgradeAdminsToTroops()
// if there are any admins currently in this group
if ( pGroup->pEnemyGroup->ubNumAdmins > 0 )
{
// skip transport groups
if (pGroup->pEnemyGroup->ubIntention == TRANSPORT)
{
pGroup = pGroup->next;
continue;
}
// if it's a patrol group
if ( pGroup->pEnemyGroup->ubIntention == PATROL )
else if ( pGroup->pEnemyGroup->ubIntention == PATROL )
{
sPatrolIndex = FindPatrolGroupIndexForGroupID( pGroup->ubGroupID );
Assert( sPatrolIndex != -1 );
@@ -6508,9 +6529,17 @@ INT16 FindGarrisonIndexForGroupIDPending( UINT8 ubGroupID )
void TransferGroupToPool( GROUP **pGroup )
{
//Madd: unlimited reinforcements?
if ( !gfUnlimitedTroops )
giReinforcementPool += (*pGroup)->ubGroupSize;
if ((*pGroup)->usGroupTeam == ENEMY_TEAM)
{
//Madd: unlimited reinforcements?
if ( !gfUnlimitedTroops )
giReinforcementPool += (*pGroup)->ubGroupSize;
AddStrategicAIResources(ASD_ROBOT, (*pGroup)->pEnemyGroup->ubNumRobots);
AddStrategicAIResources(ASD_JEEP, (*pGroup)->pEnemyGroup->ubNumJeeps);
AddStrategicAIResources(ASD_TANK, (*pGroup)->pEnemyGroup->ubNumTanks);
}
RemovePGroup( *pGroup );
*pGroup = NULL;
+3 -1
View File
@@ -38,6 +38,7 @@ BOOLEAN StrategicAILookForAdjacentGroups( GROUP *pGroup );
void RemoveGroupFromStrategicAILists( UINT8 ubGroupID );
void RecalculateSectorWeight( UINT8 ubSectorID );
void RecalculateGroupWeight( GROUP *pGroup );
void SendGroupToPool( GROUP **pGroup );
BOOLEAN OkayForEnemyToMoveThroughSector( UINT8 ubSectorID );
BOOLEAN EnemyPermittedToAttackSector( GROUP **pGroup, UINT8 ubSectorID );
@@ -78,7 +79,8 @@ BOOLEAN PermittedToFillPatrolGroup( INT32 iPatrolID );
enum GROUP_TYPE
{
GROUP_TYPE_ATTACK,
GROUP_TYPE_PATROL
GROUP_TYPE_PATROL,
GROUP_TYPE_TRANSPORT
};
void ASDInitializePatrolGroup(GROUP *pGroup);
+69 -57
View File
@@ -50,6 +50,7 @@
#include "Creature Spreading.h" // added by Flugente
#include "MilitiaIndividual.h" // added by Flugente
#include "Rebel Command.h"
#include "Strategic Transport Groups.h"
#include "MilitiaSquads.h"
#include "Vehicles.h"
@@ -1891,47 +1892,48 @@ void GroupArrivedAtSector( UINT8 ubGroupID, BOOLEAN fCheckForBattle, BOOLEAN fNe
fExceptionQueue = TRUE;
}
}
//First check if the group arriving is going to queue another battle. //KM : Aug 11, 1999 -- Patch fix: Added additional checks to prevent a 2nd battle in the case
//NOTE: We can't have more than one battle ongoing at a time. //where the player is involved in a potential battle with bloodcats/civilians
if( fExceptionQueue || (fCheckForBattle && (gTacticalStatus.fEnemyInSector || HostileCiviliansPresent() || HostileBloodcatsPresent()) &&
FindMovementGroupInSector( (UINT8)gWorldSectorX, (UINT8)gWorldSectorY, OUR_TEAM ) &&
(pGroup->ubNextX != gWorldSectorX || pGroup->ubNextY != gWorldSectorY || gbWorldSectorZ > 0 ) && NumHostilesInSector(pGroup->ubNextX, pGroup->ubNextY, pGroup->ubSectorZ) > 0)
#ifdef JA2UB
//Ja25: NO meanwhiles
#else
// if this group arrival would cause a simultaneous combat, then delay it!
// we can't have more that one battle at a time.
if( fExceptionQueue
|| ((fCheckForBattle && (gTacticalStatus.fEnemyInSector || HostileCiviliansPresent() || HostileBloodcatsPresent())) // if there is an active battle
&& (pGroup->ubNextX != gWorldSectorX || pGroup->ubNextY != gWorldSectorY || gbWorldSectorZ > 0)) // and the group is arriving at a different sector
#ifndef JA2UB
|| AreInMeanwhile()
#endif
#endif
)
{
//QUEUE BATTLE!
//Delay arrival by a random value ranging from 3-5 minutes, so it doesn't get the player
//too suspicious after it happens to him a few times, which, by the way, is a rare occurrence.
#ifdef JA2UB
/*Ja25: No meanwhiles*/
#else
if( AreInMeanwhile() )
if (((pGroup->usGroupTeam == OUR_TEAM || pGroup->usGroupTeam == MILITIA_TEAM) && NumHostilesInSector(pGroup->ubNextX, pGroup->ubNextY, pGroup->ubSectorZ) > 0) // if a friendly movement group will arrive at an enemy sector
|| (pGroup->usGroupTeam == ENEMY_TEAM && (NumPlayerTeamMembersInSector(pGroup->ubNextX, pGroup->ubNextY, pGroup->ubSectorZ) + NumNonPlayerTeamMembersInSector(pGroup->ubNextX, pGroup->ubNextY, MILITIA_TEAM) > 0))) // or an enemy movement group will arrive at a friendly sector
{
pGroup->uiArrivalTime ++; //tack on only 1 minute if we are in a meanwhile scene. This effectively
//prevents any battle from occurring while inside a meanwhile scene.
}
else
#endif
{
pGroup->uiArrivalTime += Random(3) + 3;
}
if( !AddStrategicEvent( EVENT_GROUP_ARRIVAL, pGroup->uiArrivalTime, pGroup->ubGroupID ) )
AssertMsg( 0, "Failed to add movement event." );
if ( pGroup->usGroupTeam == OUR_TEAM )
{
if( pGroup->uiArrivalTime - ABOUT_TO_ARRIVE_DELAY > GetWorldTotalMin( ) )
//QUEUE BATTLE!
//Delay arrival by a random value ranging from 3-5 minutes, so it doesn't get the player
//too suspicious after it happens to him a few times, which, by the way, is a rare occurrence.
#ifndef JA2UB
if( AreInMeanwhile() )
{
AddStrategicEvent( EVENT_GROUP_ABOUT_TO_ARRIVE, pGroup->uiArrivalTime - ABOUT_TO_ARRIVE_DELAY, pGroup->ubGroupID );
pGroup->uiArrivalTime ++; //tack on only 1 minute if we are in a meanwhile scene. This effectively
//prevents any battle from occurring while inside a meanwhile scene.
}
else
#endif
{
pGroup->uiArrivalTime += Random(3) + 3;
}
}
return;
if( !AddStrategicEvent( EVENT_GROUP_ARRIVAL, pGroup->uiArrivalTime, pGroup->ubGroupID ) )
AssertMsg( 0, "Failed to add movement event." );
if ( pGroup->usGroupTeam == OUR_TEAM )
{
if( pGroup->uiArrivalTime - ABOUT_TO_ARRIVE_DELAY > GetWorldTotalMin( ) )
{
AddStrategicEvent( EVENT_GROUP_ABOUT_TO_ARRIVE, pGroup->uiArrivalTime - ABOUT_TO_ARRIVE_DELAY, pGroup->ubGroupID );
}
}
return;
}
}
//Update the position of the group
@@ -1949,33 +1951,33 @@ void GroupArrivedAtSector( UINT8 ubGroupID, BOOLEAN fCheckForBattle, BOOLEAN fNe
SectorInfo[SECTOR( pGroup->ubSectorX, pGroup->ubSectorY )].bLastKnownEnemies = NumNonPlayerTeamMembersInSector( pGroup->ubSectorX, pGroup->ubSectorY, ENEMY_TEAM );
}
// award life 'experience' for travelling, based on travel time!
if ( !pGroup->fVehicle )
// Flugente: do not award experience gain if we never left
if (!fNeverLeft)
{
// Flugente: do not award experience gain if we never left
if ( !fNeverLeft )
// award life 'experience' for travelling, based on travel time!
if (!pGroup->fVehicle)
{
// gotta be walking to get tougher
AwardExperienceForTravelling( pGroup );
AwardExperienceForTravelling(pGroup);
}
}
else if( !IsGroupTheHelicopterGroup( pGroup ) )
{
SOLDIERTYPE *pSoldier;
INT32 iVehicleID;
iVehicleID = GivenMvtGroupIdFindVehicleId( pGroup->ubGroupID );
AssertMsg( iVehicleID != -1, "GroupArrival for vehicle group. Invalid iVehicleID. " );
pSoldier = GetSoldierStructureForVehicle( iVehicleID );
AssertMsg( pSoldier, "GroupArrival for vehicle group. Invalid soldier pointer." );
SpendVehicleFuel( pSoldier, (INT16)(pGroup->uiTraverseTime*6) );
if( !VehicleFuelRemaining( pSoldier ) )
else if (!IsGroupTheHelicopterGroup(pGroup))
{
ReportVehicleOutOfGas( iVehicleID, pGroup->ubSectorX, pGroup->ubSectorY );
//Nuke the group's path, so they don't continue moving.
ClearMercPathsAndWaypointsForAllInGroup( pGroup );
SOLDIERTYPE* pSoldier;
INT32 iVehicleID;
iVehicleID = GivenMvtGroupIdFindVehicleId(pGroup->ubGroupID);
AssertMsg(iVehicleID != -1, "GroupArrival for vehicle group. Invalid iVehicleID. ");
pSoldier = GetSoldierStructureForVehicle(iVehicleID);
AssertMsg(pSoldier, "GroupArrival for vehicle group. Invalid soldier pointer.");
SpendVehicleFuel(pSoldier, (INT16)(pGroup->uiTraverseTime * 6));
if (!VehicleFuelRemaining(pSoldier))
{
ReportVehicleOutOfGas(iVehicleID, pGroup->ubSectorX, pGroup->ubSectorY);
//Nuke the group's path, so they don't continue moving.
ClearMercPathsAndWaypointsForAllInGroup(pGroup);
}
}
}
}
@@ -3635,7 +3637,10 @@ INT32 GetSectorMvtTimeForGroup( UINT8 ubSector, UINT8 ubDirection, GROUP *pGroup
dEnemyGeneralsSpeedupFactor = max( 0.75f, dEnemyGeneralsSpeedupFactor - gStrategicStatus.usVIPsLeft * gGameExternalOptions.fEnemyGeneralStrategicMovementSpeedBonus );
}
iBestTraverseTime = dEnemyGeneralsSpeedupFactor * iBestTraverseTime;
// rftr: transport groups move slower than normal
const FLOAT transportSpeedFactor = pGroup->pEnemyGroup->ubIntention == TRANSPORT ? 2.0f : 1.0f;
iBestTraverseTime = dEnemyGeneralsSpeedupFactor * transportSpeedFactor * iBestTraverseTime;
iBestTraverseTime = iBestTraverseTime * (100 + RebelCommand::GetHarriersSpeedPenalty(ubSector)) / 100;
}
@@ -3816,6 +3821,13 @@ void HandleArrivalOfReinforcements( GROUP *pGroup )
ResetMortarsOnTeamCount();
ResetNumSquadleadersInArmyGroup(); // added by SANDRO
AddPossiblePendingEnemiesToBattle();
if (pGroup->pEnemyGroup->ubIntention == TRANSPORT)
{
// normally, transport groups can't reinforce, but this can be hit normally if a battle is occuring in a sector
// where a transport group is moving into.
UpdateTransportGroupInventory();
}
}
else if ( pGroup->usGroupTeam == MILITIA_TEAM )
{
+4
View File
@@ -15,6 +15,7 @@ enum //enemy intentions,
PATROL, //enemy is moving around determining safe areas.
REINFORCEMENTS, //enemy group has intentions to fortify position at final destination.
ASSAULT, //enemy is ready to fight anything they encounter.
TRANSPORT, //rftr: enemy is carrying out non-combat tasks, but still has an escort
NUM_ENEMY_INTENTIONS
};
@@ -109,6 +110,9 @@ typedef struct ENEMYGROUP
#define GROUPFLAG_KNOWN_DIRECTION 0x00000080
#define GROUPFLAG_KNOWN_NUMBER 0x00000100
// rftr: strategic transport group direction flag
#define GROUPFLAG_TRANSPORT_ENROUTE 0x00000200
typedef struct GROUP
{
BOOLEAN fDebugGroup; //for testing purposes -- handled differently in certain cases.
File diff suppressed because it is too large Load Diff
+31
View File
@@ -0,0 +1,31 @@
#ifndef _STRATEGIC_TRANSPORT_GROUPS_H
#define _STRATEGIC_TRANSPORT_GROUPS_H
#include "Campaign Types.h"
#include "Types.h"
#include <map>
enum TransportGroupSectorInfo
{
TransportGroupSectorInfo_LocatedGroup = 0,
TransportGroupSectorInfo_LocatedDestination,
};
struct GROUP;
BOOLEAN DeployTransportGroup();
BOOLEAN ForceDeployTransportGroup(UINT8 sectorId);
BOOLEAN ReturnTransportGroup(INT32 groupId);
void FillMapColoursForTransportGroups(INT32(&colorMap)[MAXIMUM_VALID_Y_COORDINATE][MAXIMUM_VALID_X_COORDINATE]);
void ProcessTransportGroupReachedDestination(GROUP* pGroup);
void UpdateTransportGroupInventory();
const std::map<UINT8, TransportGroupSectorInfo> GetTransportGroupSectorInfo();
void AddToTransportGroupMap(UINT8 groupId, int soldierClass, UINT8 amount);
void ClearTransportGroupMap();
void NotifyTransportGroupDefeated();
#endif
+38 -20
View File
@@ -3372,7 +3372,7 @@ void DisplayCharacterInfo( void )
const auto x = UI_CHARPANEL.Attr.AGL.iX;
const auto y = UI_CHARPANEL.Attr.AGL.iY;
ubBarWidth = (STAT_WIDTH * (gMercProfiles[ pSoldier->ubProfile ].sAgilityGain+1)) / SubpointsPerPoint(AGILAMT,0);
ubBarWidth = (STAT_WIDTH * (gMercProfiles[ pSoldier->ubProfile ].sAgilityGain+1)) / SubpointsPerPoint(AGILAMT, &gMercProfiles[pSoldier->ubProfile]);
ubBarWidth = __max(0, __min(ubBarWidth, STAT_WIDTH));
ClipRect.iTop = (y-1);
ClipRect.iBottom = (y-1) + STAT_HEIGHT;
@@ -3387,7 +3387,7 @@ void DisplayCharacterInfo( void )
const auto x = UI_CHARPANEL.Attr.DEX.iX;
const auto y = UI_CHARPANEL.Attr.DEX.iY;
ubBarWidth = (STAT_WIDTH * (gMercProfiles[ pSoldier->ubProfile ].sDexterityGain+1)) / SubpointsPerPoint(DEXTAMT,0);
ubBarWidth = (STAT_WIDTH * (gMercProfiles[ pSoldier->ubProfile ].sDexterityGain+1)) / SubpointsPerPoint(DEXTAMT, &gMercProfiles[pSoldier->ubProfile]);
ubBarWidth = __max(0, __min(ubBarWidth, STAT_WIDTH));
ClipRect.iTop = (y-1);
ClipRect.iBottom = (y-1) + STAT_HEIGHT;
@@ -3402,7 +3402,7 @@ void DisplayCharacterInfo( void )
const auto x = UI_CHARPANEL.Attr.STR.iX;
const auto y = UI_CHARPANEL.Attr.STR.iY;
ubBarWidth = (STAT_WIDTH * (gMercProfiles[ pSoldier->ubProfile ].sStrengthGain+1)) / SubpointsPerPoint(STRAMT,0);
ubBarWidth = (STAT_WIDTH * (gMercProfiles[ pSoldier->ubProfile ].sStrengthGain+1)) / SubpointsPerPoint(STRAMT, &gMercProfiles[pSoldier->ubProfile]);
ubBarWidth = __max(0, __min(ubBarWidth, STAT_WIDTH));
ClipRect.iTop = (y-1);
ClipRect.iBottom = (y-1) + STAT_HEIGHT;
@@ -3417,7 +3417,7 @@ void DisplayCharacterInfo( void )
const auto x = UI_CHARPANEL.Attr.WIS.iX;
const auto y = UI_CHARPANEL.Attr.WIS.iY;
ubBarWidth = (STAT_WIDTH * (gMercProfiles[ pSoldier->ubProfile ].sWisdomGain+1)) / SubpointsPerPoint(WISDOMAMT,0);
ubBarWidth = (STAT_WIDTH * (gMercProfiles[ pSoldier->ubProfile ].sWisdomGain+1)) / SubpointsPerPoint(WISDOMAMT, &gMercProfiles[pSoldier->ubProfile]);
ubBarWidth = __max(0, __min(ubBarWidth, STAT_WIDTH));
ClipRect.iTop = (y-1);
ClipRect.iBottom = (y-1) + STAT_HEIGHT;
@@ -3432,7 +3432,7 @@ void DisplayCharacterInfo( void )
const auto x = UI_CHARPANEL.Attr.MRK.iX;
const auto y = UI_CHARPANEL.Attr.MRK.iY;
ubBarWidth = (STAT_WIDTH * (gMercProfiles[ pSoldier->ubProfile ].sMarksmanshipGain+1)) / SubpointsPerPoint(MARKAMT,0);
ubBarWidth = (STAT_WIDTH * (gMercProfiles[ pSoldier->ubProfile ].sMarksmanshipGain+1)) / SubpointsPerPoint(MARKAMT, &gMercProfiles[pSoldier->ubProfile]);
ubBarWidth = __max(0, __min(ubBarWidth, STAT_WIDTH));
ClipRect.iTop = (y-1);
ClipRect.iBottom = (y-1) + STAT_HEIGHT;
@@ -3447,7 +3447,7 @@ void DisplayCharacterInfo( void )
const auto x = UI_CHARPANEL.Attr.LDR.iX;
const auto y = UI_CHARPANEL.Attr.LDR.iY;
ubBarWidth = (STAT_WIDTH * (gMercProfiles[ pSoldier->ubProfile ].sLeadershipGain+1)) / SubpointsPerPoint(LDRAMT,0);
ubBarWidth = (STAT_WIDTH * (gMercProfiles[ pSoldier->ubProfile ].sLeadershipGain+1)) / SubpointsPerPoint(LDRAMT, &gMercProfiles[pSoldier->ubProfile]);
ubBarWidth = __max(0, __min(ubBarWidth, STAT_WIDTH));
ClipRect.iTop = (y-1);
ClipRect.iBottom = (y-1) + STAT_HEIGHT;
@@ -3462,7 +3462,7 @@ void DisplayCharacterInfo( void )
const auto x = UI_CHARPANEL.Attr.MEC.iX;
const auto y = UI_CHARPANEL.Attr.MEC.iY;
ubBarWidth = (STAT_WIDTH * (gMercProfiles[ pSoldier->ubProfile ].sMechanicGain+1)) / SubpointsPerPoint(MECHANAMT,0);
ubBarWidth = (STAT_WIDTH * (gMercProfiles[ pSoldier->ubProfile ].sMechanicGain+1)) / SubpointsPerPoint(MECHANAMT, &gMercProfiles[pSoldier->ubProfile]);
ubBarWidth = __max(0, __min(ubBarWidth, STAT_WIDTH));
ClipRect.iTop = (y-1);
ClipRect.iBottom = (y-1) + STAT_HEIGHT;
@@ -3477,7 +3477,7 @@ void DisplayCharacterInfo( void )
const auto x = UI_CHARPANEL.Attr.EXP.iX;
const auto y = UI_CHARPANEL.Attr.EXP.iY;
ubBarWidth = (STAT_WIDTH * (gMercProfiles[ pSoldier->ubProfile ].sExplosivesGain+1)) / SubpointsPerPoint(EXPLODEAMT,0);
ubBarWidth = (STAT_WIDTH * (gMercProfiles[ pSoldier->ubProfile ].sExplosivesGain+1)) / SubpointsPerPoint(EXPLODEAMT, &gMercProfiles[pSoldier->ubProfile]);
ubBarWidth = __max(0, __min(ubBarWidth, STAT_WIDTH));
ClipRect.iTop = (y-1);
ClipRect.iBottom = (y-1) + STAT_HEIGHT;
@@ -3492,7 +3492,7 @@ void DisplayCharacterInfo( void )
const auto x = UI_CHARPANEL.Attr.MED.iX;
const auto y = UI_CHARPANEL.Attr.MED.iY;
ubBarWidth = (STAT_WIDTH * (gMercProfiles[ pSoldier->ubProfile ].sMedicalGain+1)) / SubpointsPerPoint(MEDICALAMT,0);
ubBarWidth = (STAT_WIDTH * (gMercProfiles[ pSoldier->ubProfile ].sMedicalGain+1)) / SubpointsPerPoint(MEDICALAMT, &gMercProfiles[pSoldier->ubProfile]);
ubBarWidth = __max(0, __min(ubBarWidth, STAT_WIDTH));
ClipRect.iTop = (y-1);
ClipRect.iBottom = (y-1) + STAT_HEIGHT;
@@ -3507,7 +3507,7 @@ void DisplayCharacterInfo( void )
const auto x = UI_CHARPANEL.Attr.LVL.iX;
const auto y = UI_CHARPANEL.Attr.LVL.iY;
ubBarWidth = (STAT_WIDTH * (gMercProfiles[ pSoldier->ubProfile ].sExpLevelGain+1)) / SubpointsPerPoint(EXPERAMT, pSoldier->stats.bExpLevel);
ubBarWidth = (STAT_WIDTH * (gMercProfiles[ pSoldier->ubProfile ].sExpLevelGain+1)) / SubpointsPerPoint(EXPERAMT, &gMercProfiles[pSoldier->ubProfile]);
ubBarWidth = __max(0, __min(ubBarWidth, STAT_WIDTH));
ClipRect.iTop = (y-1);
ClipRect.iBottom = (y-1) + STAT_HEIGHT;
@@ -5708,7 +5708,7 @@ UINT32 MapScreenHandle(void)
HandleCharBarRender( );
}
if( (fShowInventoryFlag && !isWidescreenUI()) || fDisableDueToBattleRoster )
if( ( fShowInventoryFlag || fDisableDueToBattleRoster ) && !isWidescreenUI() )
{
for( iCounter = 0; iCounter < MAX_SORT_METHODS; iCounter++ )
{
@@ -5824,9 +5824,6 @@ UINT32 MapScreenHandle(void)
HandleContractRenewalSequence( );
// handle dialog
HandleDialogue( );
// handle display of inventory pop up
// HEADROCK HAM 3.5: Externalize!
HandleDisplayOfItemPopUpForSector( gGameExternalOptions.ubDefaultArrivalSectorX, gGameExternalOptions.ubDefaultArrivalSectorY, startingZ );
@@ -6065,6 +6062,8 @@ UINT32 MapScreenHandle(void)
//InvalidateRegion( 0,0, 640, 480);
EndFrameBufferRender( );
// handle dialog
HandleDialogue();
// if not going anywhere else
if ( guiPendingScreen == NO_PENDING_SCREEN )
@@ -7225,14 +7224,29 @@ void GetMapKeyboardInput( UINT32 *puiNewEvent )
break;
case PGUP:
// WANNE: Jump to first merc in list
fResetMapCoords = TRUE;
GoToFirstCharacterInList( );
if (gfPreBattleInterfaceActive)
{
ScrollPreBattleInterface(TRUE);
}
else
{
// WANNE: Jump to first merc in list
fResetMapCoords = TRUE;
GoToFirstCharacterInList();
}
break;
case PGDN:
// WANNE: Jump to last merc in list
fResetMapCoords = TRUE;
GoToLastCharacterInList( );
if (gfPreBattleInterfaceActive)
{
ScrollPreBattleInterface(FALSE);
}
else
{
// WANNE: Jump to last merc in list
fResetMapCoords = TRUE;
GoToLastCharacterInList();
}
break;
case SHIFT_PGUP:
@@ -10927,6 +10941,10 @@ void BlitBackgroundToSaveBuffer( void )
ForceButtonUnDirty( giMapContractButton );
ForceButtonUnDirty( giCharInfoButton[ 0 ] );
ForceButtonUnDirty( giCharInfoButton[ 1 ] );
if (isWidescreenUI())
{
ForceButtonUnDirty(giMapInvDoneButton);
}
RenderPreBattleInterface();
}
+9 -4
View File
@@ -493,15 +493,20 @@ void DailyCheckOnItemQuantities()
if ( itemsAreOnOrder.count( usItemIndex ) == 0 )
{
ubMaxSupply = GetDealersMaxItemAmount( ubArmsDealer, usItemIndex );
UINT16 halfSupply = (UINT16)(ubMaxSupply / 2);
UINT16 itemsInStock = 0;
if ( numTotalItems.count(usItemIndex) > 0 )
{
itemsInStock = numTotalItems[usItemIndex];
}
//if the qty on hand is half the desired amount or fewer
if(numTotalItems.count(usItemIndex) == 1 && numTotalItems[ usItemIndex ] <= (INT32)( ubMaxSupply / 2 ) )
if( itemsInStock <= halfSupply )
{
//determine if the item can be restocked (assume new, use items aren't checked for until the stuff arrives)
if (ItemTransactionOccurs( ubArmsDealer, usItemIndex, DEALER_BUYING, FALSE ))
{
// figure out how many items to reorder (items are reordered an entire batch at a time)
ubNumItems = HowManyItemsToReorder( ubMaxSupply, numTotalItems[ usItemIndex ] );
ubNumItems = HowManyItemsToReorder( ubMaxSupply, itemsInStock);
#ifdef JA2UB
//if the dealer is betty, and we are to ADD the stuff instantly
if( ubArmsDealer == ARMS_DEALER_BETTY && fInstallyHaveItemsAppear &&
@@ -1120,7 +1125,7 @@ UINT32 GetArmsDealerItemTypeFromItemNumber( UINT16 usItem )
return( 0 );
break;
default:
AssertMsg( FALSE, String( "GetArmsDealerItemTypeFromItemNumber(), invalid class %d for item %d. DF 0.", Item[ usItem ].usItemClass, usItem ) );
AssertMsg( FALSE, String( "GetArmsDealerItemTypeFromItemNumber(), invalid class %d for item %d. gMAXITEMS_READ = %d.", Item[ usItem ].usItemClass, usItem, gMAXITEMS_READ ) );
break;
}
return( 0 );
+39 -35
View File
@@ -167,25 +167,14 @@ void ProcessStatChange(MERCPROFILESTRUCT *pProfile, UINT8 ubStat, UINT16 usNumCh
INT8 bCurrentRating;
UINT16 *psStatGainPtr;
BOOLEAN fAffectedByWisdom = TRUE;
INT8 evolution = NORMAL_EVOLUTION;
Assert(pProfile != NULL);
if ( !gGameExternalOptions.bDisableEvolution )
evolution = pProfile->bEvolution;
if ( evolution == NO_EVOLUTION )
return; // No change possible, quit right away
// if this is a Reverse-Evolving merc who attempting to train
if ( ( ubReason == FROM_TRAINING ) && ( evolution == DEVOLVE ) )
return; // he doesn't get any benefit, but isn't penalized either
if (usNumChances == 0)
return;
usSubpointsPerPoint = SubpointsPerPoint(ubStat, pProfile->bExpLevel);
usSubpointsPerLevel = SubpointsPerPoint(EXPERAMT, pProfile->bExpLevel);
usSubpointsPerPoint = SubpointsPerPoint(ubStat, pProfile);
usSubpointsPerLevel = SubpointsPerPoint(EXPERAMT, pProfile);
switch (ubStat)
{
@@ -255,7 +244,6 @@ void ProcessStatChange(MERCPROFILESTRUCT *pProfile, UINT8 ubStat, UINT16 usNumCh
return;
}
if (ubReason == FROM_TRAINING)
{
// training always affected by wisdom
@@ -271,7 +259,7 @@ void ProcessStatChange(MERCPROFILESTRUCT *pProfile, UINT8 ubStat, UINT16 usNumCh
// loop once for each chance to improve
for (uiCnt = 0; uiCnt < usNumChances; ++uiCnt)
{
if ( evolution != DEVOLVE) // Evolves!
if (pProfile->fRegresses == FALSE) // Evolves!
{
// if this is improving from a failure, and a successful roll would give us enough to go up a point
if ((ubReason == FROM_FAILURE) && ((*psStatGainPtr + 1) >= usSubpointsPerPoint))
@@ -302,16 +290,18 @@ void ProcessStatChange(MERCPROFILESTRUCT *pProfile, UINT8 ubStat, UINT16 usNumCh
// if there IS a usChance, adjust it for high or low wisdom (50 is avg)
if (usChance > 0 && fAffectedByWisdom)
{
usChance += (usChance * (pProfile->bWisdom + (pProfile->sWisdomGain / SubpointsPerPoint(WISDOMAMT, pProfile->bExpLevel)) - 50)) / 100;
usChance += (usChance * (pProfile->bWisdom + (pProfile->sWisdomGain / SubpointsPerPoint(WISDOMAMT, pProfile)) - 50)) / 100;
}
/*
// if the stat is Marksmanship, and the guy is a hopeless shot
if ((ubStat == MARKAMT) && (pProfile->bSpecialTrait == HOPELESS_SHOT))
// rftr: reduced growth rates at 80+ and 90+ (to make mercs with higher base stats more valuable)
if (bCurrentRating >= 90)
{
usChance /= 5; // MUCH slower to improve, divide usChance by 5
usChance = min(min(gGameExternalOptions.ubMaxGrowthChanceAt80, gGameExternalOptions.ubMaxGrowthChanceAt90), usChance);
}
else if (bCurrentRating >= 80)
{
usChance = min(gGameExternalOptions.ubMaxGrowthChanceAt80, usChance);
}
*/
// SANDRO - penalty for primitive people, they get lesser chance to gain point for certain skills
if ( gGameOptions.fNewTraitSystem && (usChance > 10) && (ubStat != EXPERAMT) && (pProfile->bCharacterTrait == CHAR_TRAIT_PRIMITIVE) )
@@ -328,14 +318,6 @@ void ProcessStatChange(MERCPROFILESTRUCT *pProfile, UINT8 ubStat, UINT16 usNumCh
}
}
// Buggler: more evolution rate choices
if ( evolution == THREEQUARTER_EVOLUTION)
usChance = max(1, usChance * 0.75);
else if ( evolution == HALF_EVOLUTION)
usChance = max(1, usChance * 0.5);
else if ( evolution == ONEQUARTER_EVOLUTION)
usChance = max(1, usChance * 0.25);
// maximum possible usChance is 99%
if (usChance > 99)
{
@@ -403,7 +385,7 @@ void ProcessStatChange(MERCPROFILESTRUCT *pProfile, UINT8 ubStat, UINT16 usNumCh
// if there IS a usChance, adjust it for high or low wisdom (50 is avg)
if (usChance > 0 && fAffectedByWisdom)
{
usChance -= (usChance * (pProfile->bWisdom + (pProfile->sWisdomGain / SubpointsPerPoint(WISDOMAMT, pProfile->bExpLevel)) - 50)) / 100;
usChance -= (usChance * (pProfile->bWisdom + (pProfile->sWisdomGain / SubpointsPerPoint(WISDOMAMT, pProfile)) - 50)) / 100;
}
// if there's ANY usChance, minimum usChance is 1% regardless of wisdom
@@ -487,7 +469,7 @@ void ChangeStat( MERCPROFILESTRUCT *pProfile, SOLDIERTYPE *pSoldier, UINT8 ubSta
UINT16 usSubpointsPerPoint;
INT8 bDamagedStatToRaise = -1; // added by SANDRO
usSubpointsPerPoint = SubpointsPerPoint(ubStat, pProfile->bExpLevel );
usSubpointsPerPoint = SubpointsPerPoint(ubStat, pProfile );
// build ptrs to appropriate profiletype stat fields
switch( ubStat )
@@ -913,7 +895,7 @@ void ProcessUpdateStats( MERCPROFILESTRUCT *pProfile, SOLDIERTYPE *pSoldier, UIN
// set default min & max, subpoints/pt.
bMinStatValue = 1;
bMaxStatValue = MAX_STAT_VALUE;
usSubpointsPerPoint = SubpointsPerPoint(ubStat, pProfile->bExpLevel);
usSubpointsPerPoint = SubpointsPerPoint(ubStat, pProfile);
// build ptrs to appropriate profiletype stat fields
switch( ubStat )
@@ -1156,7 +1138,7 @@ UINT32 RoundOffSalary(UINT32 uiSalary)
}
UINT16 SubpointsPerPoint(UINT8 ubStat, INT8 bExpLevel)
UINT16 SubpointsPerPoint(UINT8 ubStat, MERCPROFILESTRUCT* pProfile)
{
UINT16 usSubpointsPerPoint;
@@ -1177,40 +1159,62 @@ UINT16 SubpointsPerPoint(UINT8 ubStat, INT8 bExpLevel)
// Attributes
case HEALTHAMT:
usSubpointsPerPoint = HEALTH_SUBPOINTS_TO_IMPROVE;
if (gGameExternalOptions.fMercGrowthModifiersEnabled) usSubpointsPerPoint += pProfile->bGrowthModifierLife;
usSubpointsPerPoint = max(usSubpointsPerPoint, HEALTH_SUBPOINTS_TO_IMPROVE/2);
break;
case AGILAMT:
usSubpointsPerPoint = AGILITY_SUBPOINTS_TO_IMPROVE;
if (gGameExternalOptions.fMercGrowthModifiersEnabled) usSubpointsPerPoint += pProfile->bGrowthModifierAgility;
usSubpointsPerPoint = max(usSubpointsPerPoint, AGILITY_SUBPOINTS_TO_IMPROVE/2);
break;
case DEXTAMT:
usSubpointsPerPoint = DEXTERITY_SUBPOINTS_TO_IMPROVE;
if (gGameExternalOptions.fMercGrowthModifiersEnabled) usSubpointsPerPoint += pProfile->bGrowthModifierDexterity;
usSubpointsPerPoint = max(usSubpointsPerPoint, DEXTERITY_SUBPOINTS_TO_IMPROVE/2);
break;
case WISDOMAMT:
usSubpointsPerPoint = WISDOM_SUBPOINTS_TO_IMPROVE;
if (gGameExternalOptions.fMercGrowthModifiersEnabled) usSubpointsPerPoint += pProfile->bGrowthModifierWisdom;
usSubpointsPerPoint = max(usSubpointsPerPoint, WISDOM_SUBPOINTS_TO_IMPROVE/2);
break;
case STRAMT:
usSubpointsPerPoint = STRENGTH_SUBPOINTS_TO_IMPROVE;
if (gGameExternalOptions.fMercGrowthModifiersEnabled) usSubpointsPerPoint += pProfile->bGrowthModifierStrength;
usSubpointsPerPoint = max(usSubpointsPerPoint, STRENGTH_SUBPOINTS_TO_IMPROVE/2);
break;
// Skills
case MEDICALAMT:
usSubpointsPerPoint = MEDICAL_SUBPOINTS_TO_IMPROVE;
if (gGameExternalOptions.fMercGrowthModifiersEnabled) usSubpointsPerPoint += pProfile->bGrowthModifierMedical;
usSubpointsPerPoint = max(usSubpointsPerPoint, MEDICAL_SUBPOINTS_TO_IMPROVE/2);
break;
case EXPLODEAMT:
usSubpointsPerPoint = EXPLOSIVES_SUBPOINTS_TO_IMPROVE;
if (gGameExternalOptions.fMercGrowthModifiersEnabled) usSubpointsPerPoint += pProfile->bGrowthModifierExplosive;
usSubpointsPerPoint = max(usSubpointsPerPoint, EXPLOSIVES_SUBPOINTS_TO_IMPROVE/2);
break;
case MECHANAMT:
usSubpointsPerPoint = MECHANICAL_SUBPOINTS_TO_IMPROVE;
if (gGameExternalOptions.fMercGrowthModifiersEnabled) usSubpointsPerPoint += pProfile->bGrowthModifierMechanical;
usSubpointsPerPoint = max(usSubpointsPerPoint, MECHANICAL_SUBPOINTS_TO_IMPROVE/2);
break;
case MARKAMT:
usSubpointsPerPoint = MARKSMANSHIP_SUBPOINTS_TO_IMPROVE;
if (gGameExternalOptions.fMercGrowthModifiersEnabled) usSubpointsPerPoint += pProfile->bGrowthModifierMarksmanship;
usSubpointsPerPoint = max(usSubpointsPerPoint, MARKSMANSHIP_SUBPOINTS_TO_IMPROVE/2);
break;
case LDRAMT:
usSubpointsPerPoint = LEADERSHIP_SUBPOINTS_TO_IMPROVE;
if (gGameExternalOptions.fMercGrowthModifiersEnabled) usSubpointsPerPoint += pProfile->bGrowthModifierLeadership;
usSubpointsPerPoint = max(usSubpointsPerPoint, LEADERSHIP_SUBPOINTS_TO_IMPROVE/2);
break;
// Experience
case EXPERAMT:
usSubpointsPerPoint = LEVEL_SUBPOINTS_TO_IMPROVE * bExpLevel;
usSubpointsPerPoint = LEVEL_SUBPOINTS_TO_IMPROVE * pProfile->bExpLevel;
if (gGameExternalOptions.fMercGrowthModifiersEnabled) usSubpointsPerPoint += pProfile->bGrowthModifierExpLevel;
usSubpointsPerPoint = max(usSubpointsPerPoint, LEVEL_SUBPOINTS_TO_IMPROVE * pProfile->bExpLevel / 2);
break;
default:
@@ -1787,7 +1791,7 @@ void TestDumpStatChanges(void)
// print days served
fprintf(FDump, "%3d ", pProfile->usTotalDaysServed);
// print evolution type
fprintf(FDump, "%c ", cEvolutionChars[ pProfile->bEvolution ]);
fprintf(FDump, "%c ", cEvolutionChars[ pProfile->fRegresses ]);
// now print all non-zero stats
for( ubStat = FIRST_CHANGEABLE_STAT; ubStat <= LAST_CHANGEABLE_STAT; ubStat++ )
+2 -2
View File
@@ -73,7 +73,7 @@ void ProcessUpdateStats( MERCPROFILESTRUCT *pProfile, SOLDIERTYPE *pSoldier, UIN
UINT32 CalcNewSalary(UINT32 uiOldSalary, BOOLEAN fIncrease, UINT32 uiMaxLimit, UINT32 uiIncreaseCap);
UINT32 RoundOffSalary(UINT32 uiSalary);
UINT16 SubpointsPerPoint(UINT8 ubStat, INT8 bExpLevel);
UINT16 SubpointsPerPoint(UINT8 ubStat, MERCPROFILESTRUCT* pProfile);
void HandleUnhiredMercImprovement( MERCPROFILESTRUCT *pProfile );
void HandleUnhiredMercDeaths( INT32 iProfileID );
@@ -92,4 +92,4 @@ void BuildStatChangeString( STR16 wString, STR16 wName, BOOLEAN fIncrease, INT16
void MERCMercWentUpALevelSendEmail( UINT8 ubMercMercIdValue );
#endif
#endif
+2 -2
View File
@@ -1823,8 +1823,8 @@ void CalculateWeapondata()
pObjUsed = pObjPlatform;
}
gunrange = GunRange( pObjUsed, pSoldier ) / 10;
laserrange = GetBestLaserRange( pObjPlatform ) / 10;
gunrange = GunRange( pObjUsed, pSoldier ) / CELL_X_SIZE;
laserrange = GetBestLaserRange( pObjPlatform ) / CELL_X_SIZE;
if ( Item[pObjUsed->usItem].usItemClass & IC_LAUNCHER )
{
+2 -2
View File
@@ -1467,8 +1467,8 @@ void GetXYForRightIconPlacement_FaceGera( FACETYPE *pFace, UINT16 ubIndex, INT16
usHeight = pTrav->usHeight;
usWidth = pTrav->usWidth;
sX = sFaceX + ( usWidth * bNumIcons ) + 1;
sY = sFaceY + pFace->usFaceHeight - usHeight - 1;
sX = sFaceX + ( usWidth * bNumIcons );
sY = sFaceY + pFace->usFaceHeight - usHeight;
*psX = sX;
*psY = sY;
+9 -1
View File
@@ -279,7 +279,8 @@ INT32 HandleItem( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel, UINT16 usHa
{
pTargetSoldier = MercPtrs[ usSoldierIndex ];
if ( fFromUI )
// anv: don't try to heal interactive spots
if (fFromUI && Item[usHandItem].usItemClass != IC_MEDKIT)
{
INT32 sInteractiveGridNo;
@@ -325,6 +326,13 @@ INT32 HandleItem( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel, UINT16 usHa
{
if (pTargetSoldier->bTeam == gbPlayerNum || pTargetSoldier->aiData.bNeutral)
{
// anv: don't try to attack yourself, it will only cause deadlock
if (pSoldier == pTargetSoldier)
{
TacticalCharacterDialogue(pSoldier, QUOTE_REFUSING_ORDER);
return(ITEM_HANDLE_REFUSAL);
}
// nice mercs won't shoot other nice guys or neutral civilians
if ((gMercProfiles[pSoldier->ubProfile].ubMiscFlags3 & PROFILE_MISC_FLAG3_GOODGUY) &&
((pTargetSoldier->ubProfile == NO_PROFILE && pTargetSoldier->aiData.bNeutral && pTargetSoldier->ubBodyType != CROW) ||
+1
View File
@@ -3590,6 +3590,7 @@ void HandleNPCDoAction( UINT8 ubTargetNPC, UINT16 usActionCode, UINT8 ubQuoteNum
case NPC_ACTION_SEND_SOLDIERS_TO_BALIME:
case NPC_ACTION_GLOBAL_OFFENSIVE_1:
case NPC_ACTION_GLOBAL_OFFENSIVE_2:
case NPC_ACTION_DEPLOY_TRANSPORT_GROUP:
break;
case NPC_ACTION_TRIGGER_QUEEN_BY_SAM_SITES_CONTROLLED:
+38 -30
View File
@@ -1621,8 +1621,8 @@ void InternalInitEDBTooltipRegion( OBJECTTYPE * gpItemDescObject, UINT32 guiCurr
/////////////////// PROJECTION FACTOR / NCTH BEST LASER RANGE
// with the reworked NCTH code and the laser performance factor we will display BestLaserRange instead of ProjectionFactor but we still need the mouse region
if (UsingNewCTHSystem() && ( GetProjectionFactor( gpItemDescObject ) > 1.0 || GetBestLaserRange( gpItemDescObject ) > 0
&& (gGameCTHConstants.LASER_PERFORMANCE_BONUS_HIP + gGameCTHConstants.LASER_PERFORMANCE_BONUS_IRON + gGameCTHConstants.LASER_PERFORMANCE_BONUS_SCOPE != 0) ) )
if (UsingNewCTHSystem() && ( GetProjectionFactor( gpItemDescObject ) > 1.0 || (GetBestLaserRange(gpItemDescObject) / CELL_X_SIZE > 0
&& (gGameCTHConstants.LASER_PERFORMANCE_BONUS_HIP + gGameCTHConstants.LASER_PERFORMANCE_BONUS_IRON + gGameCTHConstants.LASER_PERFORMANCE_BONUS_SCOPE != 0)) ) )
{
ubRegionOffset = 6;
MSYS_EnableRegion( &gUDBFasthelpRegions[ iFirstDataRegion + ubRegionOffset ] );
@@ -1637,7 +1637,7 @@ void InternalInitEDBTooltipRegion( OBJECTTYPE * gpItemDescObject, UINT32 guiCurr
}
/////////////////// OCTH BEST LASER RANGE
if (!UsingNewCTHSystem() && (Item[gpItemDescObject->usItem].bestlaserrange > 0 || GetAverageBestLaserRange( gpItemDescObject ) > 0 ) )
if ( UsingNewCTHSystem() == false && (GetAverageBestLaserRange(gpItemDescObject) / CELL_X_SIZE) > 0 )
{
ubRegionOffset = 7;
MSYS_EnableRegion( &gUDBFasthelpRegions[ iFirstDataRegion + ubRegionOffset ] );
@@ -2881,10 +2881,10 @@ void InternalInitEDBTooltipRegion( OBJECTTYPE * gpItemDescObject, UINT32 guiCurr
///////////////////// ACCURACY MODIFIER
if (GetAccuracyModifier( gpItemDescObject ) != 0 )
{
if (cnt >= sFirstLine && cnt < sLastLine)
{
if( UsingNewCTHSystem() == true )
if (UsingNewCTHSystem() == true)
{
if (cnt >= sFirstLine && cnt < sLastLine)
{
if (Item[ gpItemDescObject->usItem ].usItemClass & (IC_WEAPON|IC_PUNCH))
{
swprintf( pStr, L"%s%s", szUDBAdvStatsTooltipText[ 0 ], szUDBAdvStatsExplanationsTooltipTextForWeapons[ 0 ]);
@@ -3262,9 +3262,9 @@ void InternalInitEDBTooltipRegion( OBJECTTYPE * gpItemDescObject, UINT32 guiCurr
///////////////////// PROJECTION FACTOR / BEST LASER RANGE
// with the reworked NCTH code and the laser performance factor we will display BestLaserRange instead of ProjectionFactor
if ( ( UsingNewCTHSystem() && GetBestLaserRange( gpItemDescObject ) > 0
if ( ( UsingNewCTHSystem() && (GetBestLaserRange(gpItemDescObject) / CELL_X_SIZE) > 0
&& (gGameCTHConstants.LASER_PERFORMANCE_BONUS_HIP + gGameCTHConstants.LASER_PERFORMANCE_BONUS_IRON + gGameCTHConstants.LASER_PERFORMANCE_BONUS_SCOPE != 0) )
|| ( !UsingNewCTHSystem() && GetBestLaserRange( gpItemDescObject ) > 0 ) )
|| ( !UsingNewCTHSystem() && (GetBestLaserRange(gpItemDescObject) / CELL_X_SIZE) > 0 ) )
{
if (cnt >= sFirstLine && cnt < sLastLine)
{
@@ -4441,10 +4441,12 @@ void DrawWeaponStats( OBJECTTYPE * gpItemDescObject )
//////////////////// PROJECTION FACTOR / NCTH BEST LASER RANGE
// with the reworked NCTH code and the laser performance factor we will display BestLaserRange instead of ProjectionFactor but we use the same icon
if ( (UsingNewCTHSystem() && ( GetProjectionFactor( gpItemDescObject ) > 1.0 || ( GetBestLaserRange( gpItemDescObject ) > 0
INT16 itemLaserRangeTiles = GetBestLaserRange(gpItemDescObject) / CELL_X_SIZE;
INT16 comparedLaserRangeTiles = fComparisonMode ? GetBestLaserRange(gpComparedItemDescObject) / CELL_X_SIZE : 0;
if ( (UsingNewCTHSystem() && ( GetProjectionFactor( gpItemDescObject ) > 1.0 || ( itemLaserRangeTiles > 0
&& (gGameCTHConstants.LASER_PERFORMANCE_BONUS_HIP + gGameCTHConstants.LASER_PERFORMANCE_BONUS_IRON + gGameCTHConstants.LASER_PERFORMANCE_BONUS_SCOPE != 0) ) ) ) ||
( fComparisonMode && UsingNewCTHSystem() && ( (GetProjectionFactor( gpItemDescObject ) > 1.0 || GetProjectionFactor( gpComparedItemDescObject ) > 1.0) ||
( GetBestLaserRange( gpComparedItemDescObject ) > 0
( comparedLaserRangeTiles > 0
&& (gGameCTHConstants.LASER_PERFORMANCE_BONUS_HIP + gGameCTHConstants.LASER_PERFORMANCE_BONUS_IRON + gGameCTHConstants.LASER_PERFORMANCE_BONUS_SCOPE != 0) ) ) ) )
{
ubNumLine = 6;
@@ -4462,8 +4464,8 @@ void DrawWeaponStats( OBJECTTYPE * gpItemDescObject )
}
//////////////////// OCTH BEST LASER RANGE
if ( !UsingNewCTHSystem() && ( GetBestLaserRange( gpItemDescObject ) ||
( fComparisonMode && GetBestLaserRange( gpComparedItemDescObject ) ) ) )
if ( UsingNewCTHSystem() == false &&
(itemLaserRangeTiles != 0 || (fComparisonMode && comparedLaserRangeTiles != 0)) )
{
ubNumLine = 7;
BltVideoObjectFromIndex( guiSAVEBUFFER, guiItemInfoWeaponIcon, 14, gItemDescGenRegions[ubNumLine][0].sLeft+sOffsetX, gItemDescGenRegions[ubNumLine][0].sTop+sOffsetY, VO_BLT_SRCTRANSPARENCY, NULL );
@@ -5354,11 +5356,13 @@ void DrawAdvancedStats( OBJECTTYPE * gpItemDescObject )
///////////////////// PROJECTION FACTOR / BEST LASER RANGE
// with the reworked NCTH code and the laser performance factor we will display BestLaserRange instead of ProjectionFactor but we use the same icon
if ( ( UsingNewCTHSystem() && ( GetProjectionFactor( gpItemDescObject ) > 1.0 || ( GetBestLaserRange( gpItemDescObject ) > 0
INT16 itemLaserRangeTiles = GetBestLaserRange(gpItemDescObject) / CELL_X_SIZE;
INT16 comparedLaserRangeTiles = fComparisonMode ? GetBestLaserRange(gpComparedItemDescObject) / CELL_X_SIZE : 0;
if ( ( UsingNewCTHSystem() && ( GetProjectionFactor( gpItemDescObject ) > 1.0 || ( itemLaserRangeTiles > 0
&& (gGameCTHConstants.LASER_PERFORMANCE_BONUS_HIP + gGameCTHConstants.LASER_PERFORMANCE_BONUS_IRON + gGameCTHConstants.LASER_PERFORMANCE_BONUS_SCOPE != 0) ) ) ||
( fComparisonMode && ( GetProjectionFactor( gpComparedItemDescObject ) > 1.0 || ( GetBestLaserRange( gpComparedItemDescObject ) > 0
( fComparisonMode && ( GetProjectionFactor( gpComparedItemDescObject ) > 1.0 || ( comparedLaserRangeTiles > 0
&& (gGameCTHConstants.LASER_PERFORMANCE_BONUS_HIP + gGameCTHConstants.LASER_PERFORMANCE_BONUS_IRON + gGameCTHConstants.LASER_PERFORMANCE_BONUS_SCOPE != 0) ) ) ) ) ||
( !UsingNewCTHSystem() && ( GetBestLaserRange( gpItemDescObject ) > 0 || ( fComparisonMode && GetBestLaserRange( gpComparedItemDescObject ) > 0 ) ) ) )
( !UsingNewCTHSystem() && ( itemLaserRangeTiles > 0 || ( fComparisonMode && comparedLaserRangeTiles > 0 ) ) ) )
{
if (cnt >= sFirstLine && cnt < sLastLine)
{
@@ -7545,9 +7549,11 @@ void DrawWeaponValues( OBJECTTYPE * gpItemDescObject )
///////////////// (LASER) PROJECTION FACTOR
// with the reworked NCTH code and the laser performance factor we will display BestLaserRange instead of ProjectionFactor
INT16 itemLaserRangeTiles = GetBestLaserRange(gpItemDescObject) / CELL_X_SIZE;
INT16 comparedLaserRangeTiles = fComparisonMode ? GetBestLaserRange(gpComparedItemDescObject) / CELL_X_SIZE : 0;
if (UsingNewCTHSystem() == true &&
( (Item[gpItemDescObject->usItem].projectionfactor > 1.0 || GetProjectionFactor( gpItemDescObject ) > 1.0) ||
( GetBestLaserRange( gpItemDescObject ) > 0
( itemLaserRangeTiles > 0
&& (gGameCTHConstants.LASER_PERFORMANCE_BONUS_HIP + gGameCTHConstants.LASER_PERFORMANCE_BONUS_IRON + gGameCTHConstants.LASER_PERFORMANCE_BONUS_SCOPE != 0) ) ) )
{
// Set line to draw into
@@ -7558,13 +7564,13 @@ void DrawWeaponValues( OBJECTTYPE * gpItemDescObject )
FLOAT iFinalProjectionValue = 0;
BOOLEAN bNewCode = FALSE;
if ( GetBestLaserRange( gpItemDescObject ) > 0
&& (gGameCTHConstants.LASER_PERFORMANCE_BONUS_HIP + gGameCTHConstants.LASER_PERFORMANCE_BONUS_IRON + gGameCTHConstants.LASER_PERFORMANCE_BONUS_SCOPE != 0) )
if ( itemLaserRangeTiles > 0 &&
(gGameCTHConstants.LASER_PERFORMANCE_BONUS_HIP + gGameCTHConstants.LASER_PERFORMANCE_BONUS_IRON + gGameCTHConstants.LASER_PERFORMANCE_BONUS_SCOPE != 0) )
{
// Get base laser range
iProjectionValue = __max(0, Item[ gpItemDescObject->usItem ].bestlaserrange * gItemSettings.fBestLaserRangeModifier / CELL_X_SIZE);
// Get best laser range
iProjectionModifier = ((FLOAT)GetBestLaserRange( gpItemDescObject ) / CELL_X_SIZE);
iProjectionModifier = (FLOAT)itemLaserRangeTiles;
// Get final laser range
iFinalProjectionValue = __max( iProjectionValue, iProjectionModifier );
bNewCode = TRUE;
@@ -7622,7 +7628,7 @@ void DrawWeaponValues( OBJECTTYPE * gpItemDescObject )
// Get base laser range
iComparedProjectionValue = __max(0, Item[ gpComparedItemDescObject->usItem ].bestlaserrange * gItemSettings.fBestLaserRangeModifier / CELL_X_SIZE);
// Get best laser range
iComparedProjectionModifier = ((FLOAT)GetBestLaserRange( gpComparedItemDescObject ) / CELL_X_SIZE);
iComparedProjectionModifier = (FLOAT)comparedLaserRangeTiles;
// Get final laser range
iComparedFinalProjectionValue = __max( iComparedProjectionValue, iComparedProjectionModifier );
}
@@ -7645,7 +7651,7 @@ void DrawWeaponValues( OBJECTTYPE * gpItemDescObject )
}
else if( fComparisonMode && UsingNewCTHSystem() == true &&
( (Item[gpComparedItemDescObject->usItem].projectionfactor > 1.0 || GetProjectionFactor( gpComparedItemDescObject ) > 1.0) ||
( GetBestLaserRange( gpItemDescObject ) > 0
( itemLaserRangeTiles > 0
&& (gGameCTHConstants.LASER_PERFORMANCE_BONUS_HIP + gGameCTHConstants.LASER_PERFORMANCE_BONUS_IRON + gGameCTHConstants.LASER_PERFORMANCE_BONUS_SCOPE != 0) ) ) )
{
ubNumLine = 6;
@@ -7655,13 +7661,13 @@ void DrawWeaponValues( OBJECTTYPE * gpItemDescObject )
FLOAT iFinalProjectionValue = 0;
BOOLEAN bNewCode = FALSE;
if ( GetBestLaserRange( gpComparedItemDescObject ) > 0
if ( comparedLaserRangeTiles > 0
&& (gGameCTHConstants.LASER_PERFORMANCE_BONUS_HIP + gGameCTHConstants.LASER_PERFORMANCE_BONUS_IRON + gGameCTHConstants.LASER_PERFORMANCE_BONUS_SCOPE != 0) )
{
// Get base laser range
iProjectionValue = __max(0, Item[ gpComparedItemDescObject->usItem ].bestlaserrange * gItemSettings.fBestLaserRangeModifier / CELL_X_SIZE);
// Get best laser range
iProjectionModifier = ((FLOAT)GetBestLaserRange( gpComparedItemDescObject ) / CELL_X_SIZE);
iProjectionModifier = (FLOAT)comparedLaserRangeTiles;
// Get final laser range
iFinalProjectionValue = __max( iProjectionValue, iProjectionModifier );
bNewCode = TRUE;
@@ -7765,7 +7771,7 @@ void DrawWeaponValues( OBJECTTYPE * gpItemDescObject )
}
///////////////// OCTH BEST LASER RANGE
if ( !UsingNewCTHSystem() && GetBestLaserRange( gpItemDescObject ) > 0 )
if ( !UsingNewCTHSystem() && itemLaserRangeTiles > 0 )
{
// Set line to draw into
ubNumLine = 7;
@@ -7802,7 +7808,7 @@ void DrawWeaponValues( OBJECTTYPE * gpItemDescObject )
DrawPropertyValueInColour( iComparedFinalBestLaserRangeValue - iFinalBestLaserRangeValue, ubNumLine, 3, fComparisonMode, FALSE, TRUE );
}
}
else if( !UsingNewCTHSystem() && ( fComparisonMode && GetBestLaserRange( gpComparedItemDescObject ) > 0 ) )
else if( !UsingNewCTHSystem() && ( fComparisonMode && comparedLaserRangeTiles > 0 ) )
{
// Set line to draw into
ubNumLine = 7;
@@ -11379,14 +11385,16 @@ void DrawAdvancedValues( OBJECTTYPE *gpItemDescObject )
cnt++;
}
BOOLEAN bNewCode = FALSE;
///////////////////// PROJECTION FACTOR / BEST LASER RANGE
// with the reworked NCTH code and the laser performance factor we will display BestLaserRange instead of ProjectionFactor
if ( ( UsingNewCTHSystem() && ( GetBestLaserRange( gpItemDescObject ) > 0 || ( fComparisonMode && GetBestLaserRange( gpComparedItemDescObject ) > 0
BOOLEAN bNewCode = FALSE;
INT16 itemLaserRangeTiles = GetBestLaserRange(gpItemDescObject) / CELL_X_SIZE;
INT16 comparedLaserRangeTiles = fComparisonMode ? GetBestLaserRange(gpComparedItemDescObject) / CELL_X_SIZE : 0;
if ( ( UsingNewCTHSystem() && (itemLaserRangeTiles > 0 || ( fComparisonMode && comparedLaserRangeTiles > 0
&& (gGameCTHConstants.LASER_PERFORMANCE_BONUS_HIP + gGameCTHConstants.LASER_PERFORMANCE_BONUS_IRON + gGameCTHConstants.LASER_PERFORMANCE_BONUS_SCOPE != 0) ) ) )
|| ( !UsingNewCTHSystem() && ( GetBestLaserRange( gpItemDescObject ) > 0 || ( fComparisonMode && GetBestLaserRange( gpComparedItemDescObject ) > 0 ) ) ) )
|| ( !UsingNewCTHSystem() && (itemLaserRangeTiles > 0 || ( fComparisonMode && comparedLaserRangeTiles > 0 ) ) ) )
{
iFloatModifier[0] = ((FLOAT)GetBestLaserRange( gpItemDescObject ) / CELL_X_SIZE);
iFloatModifier[0] = (FLOAT)itemLaserRangeTiles;
bNewCode = TRUE;
}
else
@@ -11397,7 +11405,7 @@ void DrawAdvancedValues( OBJECTTYPE *gpItemDescObject )
if( fComparisonMode )
{
if ( bNewCode )
iComparedFloatModifier[0] = ((FLOAT)GetBestLaserRange( gpComparedItemDescObject ) / CELL_X_SIZE);
iComparedFloatModifier[0] = (FLOAT)comparedLaserRangeTiles;
else
iComparedFloatModifier[0] = GetProjectionFactor( gpComparedItemDescObject );
iComparedFloatModifier[1] = iComparedFloatModifier[0];
+37 -34
View File
@@ -2913,20 +2913,16 @@ void HandleAnyMercInSquadHasCompatibleStuff( UINT8 ubSquad, OBJECTTYPE *pObject,
BOOLEAN IsMutuallyValidAttachmentOrLaunchable(UINT16 usAttItem, UINT16 usItem)//dnl ch76 091113
{
UINT32 uiLoop = 0;
while ( Attachment[uiLoop][0] )
for (UINT32 uiLoop = 0; uiLoop < gMAXATTACHMENTS_READ; uiLoop++)
{
if(Attachment[uiLoop][0] == usAttItem && Attachment[uiLoop][1] == usItem || Attachment[uiLoop][0] == usItem && Attachment[uiLoop][1] == usAttItem )
if (Attachment[uiLoop].attachmentIndex == usAttItem && Attachment[uiLoop].itemIndex == usItem || Attachment[uiLoop].attachmentIndex == usItem && Attachment[uiLoop].itemIndex == usAttItem)
return(TRUE);
++uiLoop;
}
uiLoop = 0;
while ( Launchable[uiLoop][0] )
for (UINT32 uiLoop = 0; uiLoop < gMAXLAUNCHABLES_READ; uiLoop++)
{
if ( Launchable[uiLoop][0] == usAttItem && Launchable[uiLoop][1] == usItem || Launchable[uiLoop][0] == usItem && Launchable[uiLoop][1] == usAttItem )
return(TRUE);
++uiLoop;
}
return(FALSE);
@@ -5765,12 +5761,8 @@ void UpdateAttachmentTooltips(OBJECTTYPE *pObject, UINT8 ubStatusIndex)
}
// sevenfm: check launchables
for (UINT16 usLoop = 0; usLoop < MAXITEMS + 1; usLoop++)
for (UINT16 usLoop = 0; usLoop < gMAXLAUNCHABLES_READ; usLoop++)
{
// check that reached end of valid launchables
if (Launchable[usLoop][0] == 0)
break;
usAttachment = 0;
if (Launchable[usLoop][1] == pObject->usItem && AttachmentSlots[usLoopSlotID].nasAttachmentClass & Item[Launchable[usLoop][0]].nasAttachmentClass)
{
@@ -5801,17 +5793,14 @@ void UpdateAttachmentTooltips(OBJECTTYPE *pObject, UINT8 ubStatusIndex)
}
// check all attachments
for (UINT16 usLoop = 0; usLoop < MAXATTACHMENTS; usLoop++)
//TODO: should be optimized using AttachmentBackmap and/or possibly FindAttachmentRange()
for (UINT32 uiLoop = 0; uiLoop < gMAXATTACHMENTS_READ; uiLoop++)
{
// check that reached end of valid attachments
if (Attachment[usLoop][0] == 0)
break;
usAttachment = 0;
if (Attachment[usLoop][1] == pObject->usItem && AttachmentSlots[usLoopSlotID].nasAttachmentClass & Item[Attachment[usLoop][0]].nasAttachmentClass)
if (Attachment[uiLoop].itemIndex == pObject->usItem && AttachmentSlots[usLoopSlotID].nasAttachmentClass & Item[Attachment[uiLoop].attachmentIndex].nasAttachmentClass)
{
//search primary item attachments.xml
usAttachment = Attachment[usLoop][0];
usAttachment = Attachment[uiLoop].attachmentIndex;
}
else
{
@@ -5820,8 +5809,11 @@ void UpdateAttachmentTooltips(OBJECTTYPE *pObject, UINT8 ubStatusIndex)
UINT16* p = cnt ? &attachedList.front() : NULL;
while (cnt)
{
if (Attachment[usLoop][1] == *p && AttachmentSlots[usLoopSlotID].nasAttachmentClass & Item[Attachment[usLoop][0]].nasAttachmentClass)
usAttachment = Attachment[usLoop][0];
if (Attachment[uiLoop].itemIndex == *p && AttachmentSlots[usLoopSlotID].nasAttachmentClass & Item[Attachment[uiLoop].attachmentIndex].nasAttachmentClass)
{
usAttachment = Attachment[uiLoop].attachmentIndex;
break;
}
cnt--, p++;
}
@@ -12648,28 +12640,39 @@ void GetHelpTextForItem( STR16 pzStr, OBJECTTYPE *pObject, SOLDIERTYPE *pSoldier
// Add attachment string....
CHAR16 attachString[ 300 ];
CHAR16 tempString[ 120 ];
memset(attachString,0,sizeof(attachString));
for (attachmentList::iterator iter = (*pObject)[subObject]->attachments.begin(); iter != (*pObject)[subObject]->attachments.end(); ++iter) {
if(iter->exists()){
//Break off if it's too long.
if(wcslen(attachString)>270){
wcscat( attachString, L"\n...." );
break;
}
for (attachmentList::iterator iter = (*pObject)[subObject]->attachments.begin(); iter != (*pObject)[subObject]->attachments.end(); ++iter)
{
if(iter->exists())
{
memset(tempString, 0, sizeof(tempString));
iNumAttachments++;
if ( iNumAttachments == 1 )
if (iNumAttachments == 1)
{
swprintf( attachString, L"\n \n%s:\n", Message[ STR_ATTACHMENTS ] );
swprintf(tempString, L"\n \n%s:\n", Message[STR_ATTACHMENTS]);
}
else
{
wcscat( attachString, L"\n" );
swprintf(tempString, L"\n");
}
wcscat(tempString, ItemNames[iter->usItem]);
wcscat( attachString, ItemNames[ iter->usItem ] );
auto attachStringLength = wcslen(attachString);
auto tempStringLength = wcslen(tempString);
auto totalLength = attachStringLength + tempStringLength;
// Break off if the string to be added does not fit.
// attachStringLength[300] - L"\n...." -> 294
if (totalLength > 294)
{
wcscat(attachString, L"\n....");
break;
}
else
{
wcscat(attachString, tempString);
}
}
}
+22 -12
View File
@@ -2598,7 +2598,7 @@ void RenderSMPanel( BOOLEAN *pfDirty )
// AGI
if (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sAgilityGain)
{
ubBarWidth = (SM_STATS_WIDTH * (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sAgilityGain+1)) / SubpointsPerPoint(AGILAMT,0);
ubBarWidth = (SM_STATS_WIDTH * (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sAgilityGain+1)) / SubpointsPerPoint(AGILAMT, &gMercProfiles[gpSMCurrentMerc->ubProfile]);
ubBarWidth = __max(0, __min(ubBarWidth, SM_STATS_WIDTH));
ClipRect.iTop = (SM_AGI_Y-1);
ClipRect.iBottom = (SM_AGI_Y-1) + SM_STATS_HEIGHT;
@@ -2610,7 +2610,7 @@ void RenderSMPanel( BOOLEAN *pfDirty )
// DEX
if (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sDexterityGain)
{
ubBarWidth = (SM_STATS_WIDTH * (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sDexterityGain+1)) / SubpointsPerPoint(DEXTAMT,0);
ubBarWidth = (SM_STATS_WIDTH * (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sDexterityGain+1)) / SubpointsPerPoint(DEXTAMT, &gMercProfiles[gpSMCurrentMerc->ubProfile]);
ubBarWidth = __max(0, __min(ubBarWidth, SM_STATS_WIDTH));
ClipRect.iTop = (SM_DEX_Y-1);
ClipRect.iBottom = (SM_DEX_Y-1) + SM_STATS_HEIGHT;
@@ -2622,7 +2622,7 @@ void RenderSMPanel( BOOLEAN *pfDirty )
// STR
if (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sStrengthGain)
{
ubBarWidth = (SM_STATS_WIDTH * (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sStrengthGain+1)) / SubpointsPerPoint(STRAMT,0);
ubBarWidth = (SM_STATS_WIDTH * (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sStrengthGain+1)) / SubpointsPerPoint(STRAMT, &gMercProfiles[gpSMCurrentMerc->ubProfile]);
ubBarWidth = __max(0, __min(ubBarWidth, SM_STATS_WIDTH));
ClipRect.iTop = (SM_STR_Y-1);
ClipRect.iBottom = (SM_STR_Y-1) + SM_STATS_HEIGHT;
@@ -2634,7 +2634,7 @@ void RenderSMPanel( BOOLEAN *pfDirty )
// WIS
if (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sWisdomGain)
{
ubBarWidth = (SM_STATS_WIDTH * (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sWisdomGain+1)) / SubpointsPerPoint(WISDOMAMT,0);
ubBarWidth = (SM_STATS_WIDTH * (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sWisdomGain+1)) / SubpointsPerPoint(WISDOMAMT, &gMercProfiles[gpSMCurrentMerc->ubProfile]);
ubBarWidth = __max(0, __min(ubBarWidth, SM_STATS_WIDTH));
ClipRect.iTop = (SM_WIS_Y-1);
ClipRect.iBottom = (SM_WIS_Y-1) + SM_STATS_HEIGHT;
@@ -2646,7 +2646,7 @@ void RenderSMPanel( BOOLEAN *pfDirty )
// MRK
if (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sMarksmanshipGain)
{
ubBarWidth = (SM_STATS_WIDTH * (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sMarksmanshipGain+1)) / SubpointsPerPoint(MARKAMT,0);
ubBarWidth = (SM_STATS_WIDTH * (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sMarksmanshipGain+1)) / SubpointsPerPoint(MARKAMT, &gMercProfiles[gpSMCurrentMerc->ubProfile]);
ubBarWidth = __max(0, __min(ubBarWidth, SM_STATS_WIDTH));
ClipRect.iTop = (SM_MRKM_Y-1);
ClipRect.iBottom = (SM_MRKM_Y-1) + SM_STATS_HEIGHT;
@@ -2658,7 +2658,7 @@ void RenderSMPanel( BOOLEAN *pfDirty )
// LDR
if (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sLeadershipGain)
{
ubBarWidth = (SM_STATS_WIDTH * (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sLeadershipGain+1)) / SubpointsPerPoint(LDRAMT,0);
ubBarWidth = (SM_STATS_WIDTH * (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sLeadershipGain+1)) / SubpointsPerPoint(LDRAMT, &gMercProfiles[gpSMCurrentMerc->ubProfile]);
ubBarWidth = __max(0, __min(ubBarWidth, SM_STATS_WIDTH));
ClipRect.iTop = (SM_CHAR_Y-1);
ClipRect.iBottom = (SM_CHAR_Y-1) + SM_STATS_HEIGHT;
@@ -2670,7 +2670,7 @@ void RenderSMPanel( BOOLEAN *pfDirty )
// MECH
if (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sMechanicGain)
{
ubBarWidth = (SM_STATS_WIDTH * (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sMechanicGain+1)) / SubpointsPerPoint(MECHANAMT,0);
ubBarWidth = (SM_STATS_WIDTH * (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sMechanicGain+1)) / SubpointsPerPoint(MECHANAMT, &gMercProfiles[gpSMCurrentMerc->ubProfile]);
ubBarWidth = __max(0, __min(ubBarWidth, SM_STATS_WIDTH));
ClipRect.iTop = (SM_MECH_Y-1);
ClipRect.iBottom = (SM_MECH_Y-1) + SM_STATS_HEIGHT;
@@ -2682,7 +2682,7 @@ void RenderSMPanel( BOOLEAN *pfDirty )
// EXPLO
if (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sExplosivesGain)
{
ubBarWidth = (SM_STATS_WIDTH * (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sExplosivesGain+1)) / SubpointsPerPoint(EXPLODEAMT,0);
ubBarWidth = (SM_STATS_WIDTH * (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sExplosivesGain+1)) / SubpointsPerPoint(EXPLODEAMT, &gMercProfiles[gpSMCurrentMerc->ubProfile]);
ubBarWidth = __max(0, __min(ubBarWidth, SM_STATS_WIDTH));
ClipRect.iTop = (SM_EXPL_Y-1);
ClipRect.iBottom = (SM_EXPL_Y-1) + SM_STATS_HEIGHT;
@@ -2694,7 +2694,7 @@ void RenderSMPanel( BOOLEAN *pfDirty )
// MED
if (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sMedicalGain)
{
ubBarWidth = (SM_STATS_WIDTH * (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sMedicalGain+1)) / SubpointsPerPoint(MEDICALAMT,0);
ubBarWidth = (SM_STATS_WIDTH * (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sMedicalGain+1)) / SubpointsPerPoint(MEDICALAMT, &gMercProfiles[gpSMCurrentMerc->ubProfile]);
ubBarWidth = __max(0, __min(ubBarWidth, SM_STATS_WIDTH));
ClipRect.iTop = (SM_MED_Y-1);
ClipRect.iBottom = (SM_MED_Y-1) + SM_STATS_HEIGHT;
@@ -2706,7 +2706,7 @@ void RenderSMPanel( BOOLEAN *pfDirty )
// EXPLEVEL
if (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sExpLevelGain)
{
ubBarWidth = (SM_STATS_WIDTH * (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sExpLevelGain+1)) / SubpointsPerPoint(EXPERAMT, gpSMCurrentMerc->stats.bExpLevel);
ubBarWidth = (SM_STATS_WIDTH * (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sExpLevelGain+1)) / SubpointsPerPoint(EXPERAMT, &gMercProfiles[gpSMCurrentMerc->ubProfile]);
ubBarWidth = __max(0, __min(ubBarWidth, SM_STATS_WIDTH));
ClipRect.iTop = (SM_EXPLVL_Y-1);
ClipRect.iBottom = (SM_EXPLVL_Y-1) + SM_STATS_HEIGHT;
@@ -5199,7 +5199,7 @@ BOOLEAN InitializeTEAMPanel( )
if (iResolution >= _640x480 && iResolution < _800x600)
FilenameForBPP("INTERFACE\\bottom_bar.sti", VObjectDesc.ImageFile);
else if (iResolution < _1024x768)
else if (iResolution < _1280x720)
{
if (gGameOptions.ubSquadSize > 6)
{
@@ -5240,6 +5240,16 @@ BOOLEAN InitializeTEAMPanel( )
memset( gfTEAM_HandInvDispText, 0, sizeof( gfTEAM_HandInvDispText ) );
// Offset button coordinates to correct positions if squadsize is 10
if (iResolution == _1280x720)
{
UINT16 offset = 223;
TM_ENDTURN_X = xResOffset + (xResSize - 131) + offset;
TM_ROSTERMODE_X = xResOffset + (xResSize - 131) + offset;
TM_DISK_X = xResOffset + (xResSize - 131) + offset;
INTERFACE_CLOCK_TM_X = xResOffset + (xResSize - 86) + offset;
LOCATION_NAME_TM_X = xResOffset + (xResSize - 92) + offset;
}
// Create buttons
CHECKF( CreateTEAMPanelButtons( ) );
@@ -5358,7 +5368,7 @@ BOOLEAN ShutdownTEAMPanel( )
if( fRenderRadarScreen == FALSE )
{
// start rendering radar region again,
fRenderRadarScreen = TRUE;
fRenderRadarScreen = TRUE;
// remove squad panel
CreateDestroyMouseRegionsForSquadList( );
+27 -1
View File
@@ -1220,6 +1220,10 @@ typedef struct
BOOLEAN fProvidesRobotLaserBonus;
//shadooow: bitflag controlling what system needs to be in play for item to appear
UINT8 usLimitedToSystem;
// rftr: the progress bounds that allow a transport group to drop an item
INT8 iTransportGroupMinProgress;
INT8 iTransportGroupMaxProgress;
} INVTYPE;
@@ -1720,9 +1724,30 @@ typedef enum
MAXITEMS = 16001
} ITEMDEFINE;
struct AttachmentStruct
{
UINT16 attachmentIndex;
UINT16 itemIndex;
UINT16 APCost;
UINT16 NASOnly;
bool operator<(const AttachmentStruct& a) const
{
bool result = false;
if (attachmentIndex < a.attachmentIndex)
result = true;
else if (attachmentIndex == a.attachmentIndex)
result = itemIndex < a.itemIndex;
return result;
}
};
// Flugente: in order not to loop over MAXITEMS items if we only have a few thousand, remember the actual number of items in the xml
extern UINT32 gMAXITEMS_READ;
extern UINT32 gMAXAMMOTYPES_READ;
extern UINT32 gMAXATTACHMENTS_READ;
extern UINT32 gMAXLAUNCHABLES_READ;
/* CHRISL: Arrays to track ic group information. These allow us to determine which LBE slots control which pockets and
what LBE class the pockets are.*/
@@ -1777,7 +1802,8 @@ const INT16 icDefault[NUM_INV_SLOTS] = {
#define MAXATTACHMENTS 60000
extern INVTYPE Item[MAXITEMS];
extern UINT16 Attachment[MAXATTACHMENTS][4];
extern AttachmentStruct Attachment[MAXATTACHMENTS];
extern std::multimap<UINT16, AttachmentStruct> AttachmentBackmap;
//WarmSteel - Here we have some definitions for NAS
typedef struct
+93 -63
View File
@@ -566,7 +566,8 @@ AttachmentInfoStruct AttachmentInfo[MAXITEMS+1];// =
AttachmentSlotStruct AttachmentSlots[MAXITEMS+1];
ItemReplacementStruct ItemReplacement[MAXATTACHMENTS];
UINT16 Attachment[MAXATTACHMENTS][4];// =
AttachmentStruct Attachment[MAXATTACHMENTS];// =
std::multimap<UINT16, AttachmentStruct> AttachmentBackmap; // key is itemId
//{
// {SILENCER, GLOCK_17},
// {SILENCER, GLOCK_18},
@@ -2253,7 +2254,6 @@ INT32 GetAttachmentInfoIndex( UINT16 usItem )
//Determine if it is possible to add this attachment to the item.
BOOLEAN ValidAttachment( UINT16 usAttachment, UINT16 usItem, UINT8 * pubAPCost )
{
INT32 iLoop = 0;
if (pubAPCost) {
*pubAPCost = (UINT8)APBPConstants[AP_RELOAD_GUN]; //default value
}
@@ -2269,40 +2269,26 @@ BOOLEAN ValidAttachment( UINT16 usAttachment, UINT16 usItem, UINT8 * pubAPCost )
*pubAPCost = Item[usAttachment].ubAttachToPointAPCost;
return TRUE;
}
// look for the section of the array pertaining to this attachment...
while( 1 )
{
if (Attachment[iLoop][0] == usAttachment)
{
break;
}
++iLoop;
if (Attachment[iLoop][0] == 0)
{
// the proposed item cannot be attached to anything!
return( FALSE );
}
}
UINT32 startIndex = 0, endIndex = 0;
if (FindAttachmentRange(usAttachment, &startIndex, &endIndex) == FALSE)
return FALSE;
// now look through this section for the item in question
while( 1 )
for (UINT32 iLoop = startIndex; iLoop <= endIndex; iLoop++)
{
if (Attachment[iLoop][1] == usItem)
if (Attachment[iLoop].itemIndex == usItem)
{
if ( UsingNewAttachmentSystem( ) || Attachment[iLoop][3] != 1 )
if ( UsingNewAttachmentSystem( ) || Attachment[iLoop].NASOnly != 1 )
{
if (pubAPCost)
*pubAPCost = (UINT8)Attachment[iLoop][2]; //Madd: get ap cost of attaching items :)
break;
*pubAPCost = (UINT8)Attachment[iLoop].APCost; //Madd: get ap cost of attaching items :)
}
}
++iLoop;
if (Attachment[iLoop][0] != usAttachment)
{
// the proposed item cannot be attached to the item in question
return( FALSE );
return TRUE;
}
}
return( TRUE );
return FALSE;
}
BOOLEAN ValidAttachment( UINT16 usAttachment, OBJECTTYPE * pObj, UINT8 * pubAPCost, UINT8 subObject, std::vector<UINT16> usAttachmentSlotIndexVector)
@@ -5677,40 +5663,40 @@ BOOLEAN OBJECTTYPE::AttachObjectNAS( SOLDIERTYPE * pSoldier, OBJECTTYPE * pAttac
UINT64 SetAttachmentSlotsFlag(OBJECTTYPE* pObj)
{
UINT64 uiSlotFlag = 0;
UINT32 uiLoop = 0;
UINT32 fItem;
if (pObj->exists() == false)
return 0;
UINT64 point = GetAvailableAttachmentPoint(pObj, 0);
while (uiLoop < gMAXITEMS_READ && Item[uiLoop].usItemClass != 0 ||
uiLoop < MAXATTACHMENTS && Attachment[uiLoop][0] != 0 ||
uiLoop < MAXITEMS + 1 && Launchable[uiLoop][0] != 0)
if (UsingNewAttachmentSystem())
{
if (uiLoop > 0 && uiLoop < gMAXITEMS_READ && IsAttachmentPointAvailable(point, uiLoop, TRUE))
std::pair<std::multimap<UINT16, AttachmentStruct>::iterator, std::multimap<UINT16, AttachmentStruct>::iterator> range;
std::multimap<UINT16, AttachmentStruct>::iterator it;
range = AttachmentBackmap.equal_range(pObj->usItem);
for (it = range.first; it != range.second; it++)
{
fItem = uiLoop;
if (fItem && ItemIsLegal(fItem, TRUE))
uiSlotFlag |= Item[fItem].nasAttachmentClass;
UINT16 attachmentId = it->second.attachmentIndex;
if (ItemIsLegal(attachmentId, TRUE))
uiSlotFlag |= Item[attachmentId].nasAttachmentClass;
}
if (uiLoop < MAXATTACHMENTS && Attachment[uiLoop][1] == pObj->usItem)
for (UINT32 i = 0; i < gMAXLAUNCHABLES_READ; i++)
{
fItem = Attachment[uiLoop][0];
if (fItem && ItemIsLegal(fItem, TRUE))
uiSlotFlag |= Item[fItem].nasAttachmentClass;
if (Launchable[i][1] == pObj->usItem)
{
UINT16 attachmentId = Launchable[i][0];
if (ItemIsLegal(attachmentId, TRUE))
uiSlotFlag |= Item[attachmentId].nasAttachmentClass;
}
}
if (uiLoop < MAXITEMS + 1 && Launchable[uiLoop][1] == pObj->usItem)
}
else
{
UINT64 point = GetAvailableAttachmentPoint(pObj, 0);
for (UINT32 itemId = 1; itemId < gMAXITEMS_READ; itemId++)
{
fItem = Launchable[uiLoop][0];
if (fItem && ItemIsLegal(fItem, TRUE))
uiSlotFlag |= Item[fItem].nasAttachmentClass;
if (ItemIsLegal(itemId, TRUE) && IsAttachmentPointAvailable(point, itemId, TRUE))
uiSlotFlag |= Item[itemId].nasAttachmentClass;
}
uiLoop++;
}
return uiSlotFlag;
@@ -14078,29 +14064,29 @@ INT16 GetFlatToHitBonus( OBJECTTYPE * pObj )
// HEADROCK: Function to get average of all "best laser range" attributes from weapon and attachments
INT16 GetAverageBestLaserRange( OBJECTTYPE * pObj )
{
INT16 bonus=0;
FLOAT bonus = 0.0;
INT16 numModifiers=0;
if (Item[pObj->usItem].bestlaserrange > 0)
{
numModifiers++;
bonus += Item[pObj->usItem].bestlaserrange;
bonus += (FLOAT) Item[pObj->usItem].bestlaserrange;
}
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter)
{
if (Item[iter->usItem].bestlaserrange > 0 && iter->exists())
{
numModifiers++;
bonus += Item[iter->usItem].bestlaserrange;
bonus += (FLOAT) Item[iter->usItem].bestlaserrange;
}
}
if (numModifiers>0)
if (numModifiers > 1)
{
bonus = bonus / numModifiers;
}
return( bonus * gItemSettings.fBestLaserRangeModifier );
return (INT16)(bonus * gItemSettings.fBestLaserRangeModifier);
}
// get the best laser range from the weapon and attachments
@@ -14120,7 +14106,7 @@ INT16 GetBestLaserRange( OBJECTTYPE * pObj )
}
}
return( range * gItemSettings.fBestLaserRangeModifier );
return (INT16) ((FLOAT)range * gItemSettings.fBestLaserRangeModifier);
}
// HEADROCK: This function determines the bipod bonii of the gun or its attachments
@@ -15642,14 +15628,9 @@ BOOLEAN GetItemFromRandomItem( UINT16 usRandomItem, UINT16* pusNewItem )
// as it is also possible to reference to other random items, we also have to check for them
// clear the random item arrays and reset the counters
for ( int i = 0; i < RANDOM_ITEM_MAX_NUMBER; ++i)
randomitemarray[i] = 0;
for ( int i = 0; i < RANDOM_TABOO_MAX; ++i)
{
randomitemtabooarray[i] = 0;
randomitemclasstabooarray[i] = 0;
}
memset(randomitemarray, 0, sizeof(randomitemarray));
memset(randomitemtabooarray, 0, sizeof(randomitemtabooarray));
memset(randomitemclasstabooarray, 0, sizeof(randomitemclasstabooarray));
itemcnt = 0;
rdtaboocnt = 0;
@@ -16033,3 +16014,52 @@ UINT16 GetLaunchableOfExplosionType(UINT16 launcher, UINT8 explosionType)
}
return NOTHING;
}
BOOLEAN FindAttachmentRange(UINT16 usAttachment, UINT32* pStartIndex, UINT32* pEndIndex)
{
BOOLEAN result = FALSE;
INT32 leftMargin = 0;
INT32 rightMargin = (INT32)gMAXATTACHMENTS_READ - 1;
INT32 middle = 0;
// use binary search to locate the group of elements for given attachment item Id (usAttachment)
while (leftMargin <= rightMargin)
{
middle = leftMargin + (rightMargin - leftMargin) / 2;
if (Attachment[middle].attachmentIndex == usAttachment)
{
result = TRUE;
break;
}
else if (Attachment[middle].attachmentIndex < usAttachment)
leftMargin = middle + 1;
else
rightMargin = middle - 1;
}
if (result)
{
// now middle is an index somewhere within the group, seek for beginning and ending of the group
if (pStartIndex)
{
*pStartIndex = (UINT32)middle;
for (INT32 i = middle - 1; i >= leftMargin; i--)
if (Attachment[i].attachmentIndex == usAttachment)
*pStartIndex = (UINT32)i;
else
break;
}
if (pEndIndex)
{
*pEndIndex = (UINT32)middle;
for (INT32 i = middle + 1; i <= rightMargin; i++)
if (Attachment[i].attachmentIndex == usAttachment)
*pEndIndex = (UINT32)i;
else
break;
}
}
return result;
}
+1
View File
@@ -568,6 +568,7 @@ INT32 GetPercentRangeBonus( OBJECTTYPE * pObj );
UINT8 GetInventorySleepModifier( SOLDIERTYPE *pSoldier );
void AttachDefaultAttachments(OBJECTTYPE *pObj, BOOLEAN fAllDefaultAttachments=TRUE);//dnl ch75 261013
BOOLEAN FindAttachmentRange(UINT16 usAttachment, UINT32* pStartIndex, UINT32* pEndIndex);
// Flugente: is this object useable by militia?
BOOLEAN ObjectIsMilitiaRelevant( OBJECTTYPE *pObj );
+1 -1
View File
@@ -3018,7 +3018,7 @@ BOOLEAN BulletHitMerc( BULLET * pBullet, STRUCTURE * pStructure, BOOLEAN fIntend
// Determine damage, checking guy's armour, etc
sRange = GetRangeInCellCoordsFromGridNoDiff( pBullet->sOrigGridNo, pTarget->sGridNo );
if ( gTacticalStatus.uiFlags & GODMODE && pBullet->ubFirerID != NOBODY && !(pFirer->flags.uiStatusFlags & SOLDIER_PC))
if ( gTacticalStatus.uiFlags & GODMODE && pTarget->bTeam == OUR_TEAM && pBullet->ubFirerID != NOBODY && !(pFirer->flags.uiStatusFlags & SOLDIER_PC))
{
// in god mode, and firer is computer controlled
iImpact = 0;
-1
View File
@@ -76,7 +76,6 @@ private:
SOLDIERTYPE* pSoldier;
INT8 onRooftop;//aka ubLevel, not sure if this bool is logically reversed yet
bool fNonFenceJumper;
bool fNonSwimmer;
bool fPathingForPlayer;
bool fPathAroundPeople;
+6 -266
View File
@@ -454,6 +454,11 @@ UINT32 guiFailedPathChecks = 0;
UINT32 guiUnsuccessfulPathChecks = 0;
#endif
static auto canJumpFences(SOLDIERTYPE* pSoldier) -> bool {
return IS_MERC_BODY_TYPE(pSoldier) && pSoldier->CanClimbWithCurrentBackpack();
}
//ADB the extra cover feature is supposed to pick a path of the same distance as one calculated with the feature off,
//but a safer path, usually farther away from an enemy or following behind some cover.
//however it has not been tested and it may need some work, I haven't touched it in a while
@@ -638,7 +643,6 @@ int AStarPathfinder::GetPath(SOLDIERTYPE *s ,
fTurnBased = ( (gTacticalStatus.uiFlags & TURNBASED) && (gTacticalStatus.uiFlags & INCOMBAT) );
fPathingForPlayer = ( (pSoldier->bTeam == gbPlayerNum) && (!gTacticalStatus.fAutoBandageMode) && !(pSoldier->flags.uiStatusFlags & SOLDIER_PCUNDERAICONTROL) );
fNonFenceJumper = !( IS_MERC_BODY_TYPE( pSoldier ) );
fNonSwimmer = !( IS_MERC_BODY_TYPE( pSoldier ) );
fPathAroundPeople = ( (fFlags & PATH_THROUGH_PEOPLE) == 0 );
fCloseGoodEnough = ( (fFlags & PATH_CLOSE_GOOD_ENOUGH) != 0);
@@ -1454,268 +1458,6 @@ INT16 AStarPathfinder::CalcAP(int const terrainCost, UINT8 const direction)
return movementAPCost;
}
int AStarPathfinder::CalcG(int* pPrevCost)
{
//how much is admission to the next tile
if ( gfPathAroundObstacles == false)
{
return TRAVELCOST_FLAT;
}
int nextCost = gubWorldMovementCosts[ CurrentNode ][ direction ][ onRooftop ];
*pPrevCost = nextCost;
//if we are holding down shift and finding a direct path, count non obstacles as flat terrain
if (gfPlotDirectPath && nextCost < NOPASS && nextCost != 0)
{
return TRAVELCOST_FLAT;
}
//performance: if nextCost is low then do not do many many if == checks
if ( nextCost >= TRAVELCOST_FENCE )
{
//ATE: Check for differences from reality
// Is next cost an obstcale
if ( nextCost == TRAVELCOST_HIDDENOBSTACLE )
{
if ( fPathingForPlayer )
{
// Is this obstacle a hidden tile that has not been revealed yet?
BOOLEAN fHiddenStructVisible;
if( DoesGridNoContainHiddenStruct( CurrentNode, &fHiddenStructVisible ) )
{
// Are we not visible, if so use terrain costs!
if ( !fHiddenStructVisible )
{
// Set cost of terrain!
nextCost = gTileTypeMovementCost[ gpWorldLevelData[ CurrentNode ].ubTerrainID ];
}
}
}
}
else if ( nextCost == TRAVELCOST_NOT_STANDING )
{
// for path plotting purposes, use the terrain value
nextCost = gTileTypeMovementCost[ gpWorldLevelData[ CurrentNode ].ubTerrainID ];
}
else if ( nextCost == TRAVELCOST_EXITGRID )
{
if (gfPlotPathToExitGrid)
{
// replace with terrain cost so that we can plot path, otherwise is obstacle
nextCost = gTileTypeMovementCost[ gpWorldLevelData[ CurrentNode ].ubTerrainID ];
}
}
//ddd: window. { check 2 conditions: 1. if next tile is a window and we will have to hump through it
//2. if current tile is a window and we should jump through the window to reach another tile
else if ( nextCost == TRAVELCOST_JUMPABLEWINDOW
|| nextCost == TRAVELCOST_JUMPABLEWINDOW_N
|| nextCost == TRAVELCOST_JUMPABLEWINDOW_W)
{
// don't let anyone path diagonally through doors!
if (IsDiagonal(direction) == true)
{
return -1;
}
nextCost = gTileTypeMovementCost[ gpWorldLevelData[ CurrentNode ].ubTerrainID ];//?
}
//ddd: window }
else if ( nextCost == TRAVELCOST_FENCE && fNonFenceJumper )
{
return -1;
}
else if ( IS_TRAVELCOST_DOOR( nextCost ) )
{
// don't let anyone path diagonally through doors!
if (IsDiagonal(direction) == true)
{
return -1;
}
INT32 iDoorGridNo = CurrentNode;
bool fDoorIsObstacleIfClosed = FALSE;
bool fDoorIsOpen = false;
switch( nextCost )
{
case TRAVELCOST_DOOR_CLOSED_HERE:
fDoorIsObstacleIfClosed = TRUE;
iDoorGridNo = CurrentNode;
break;
case TRAVELCOST_DOOR_CLOSED_N:
fDoorIsObstacleIfClosed = TRUE;
iDoorGridNo = CurrentNode + dirDelta[ NORTH ];
break;
case TRAVELCOST_DOOR_CLOSED_W:
fDoorIsObstacleIfClosed = TRUE;
iDoorGridNo = CurrentNode + dirDelta[ WEST ];
break;
case TRAVELCOST_DOOR_OPEN_HERE:
iDoorGridNo = CurrentNode;
break;
case TRAVELCOST_DOOR_OPEN_N:
iDoorGridNo = CurrentNode + dirDelta[ NORTH ];
break;
case TRAVELCOST_DOOR_OPEN_NE:
iDoorGridNo = CurrentNode + dirDelta[ NORTHEAST ];
break;
case TRAVELCOST_DOOR_OPEN_E:
iDoorGridNo = CurrentNode + dirDelta[ EAST ];
break;
case TRAVELCOST_DOOR_OPEN_SE:
iDoorGridNo = CurrentNode + dirDelta[ SOUTHEAST ];
break;
case TRAVELCOST_DOOR_OPEN_S:
iDoorGridNo = CurrentNode + dirDelta[ SOUTH ];
break;
case TRAVELCOST_DOOR_OPEN_SW:
iDoorGridNo = CurrentNode + dirDelta[ SOUTHWEST ];
break;
case TRAVELCOST_DOOR_OPEN_W:
iDoorGridNo = CurrentNode + dirDelta[ WEST ];
break;
case TRAVELCOST_DOOR_OPEN_NW:
iDoorGridNo = CurrentNode + dirDelta[ NORTHWEST ];
break;
case TRAVELCOST_DOOR_OPEN_N_N:
iDoorGridNo = CurrentNode + dirDelta[ NORTH ] + dirDelta[ NORTH ];
break;
case TRAVELCOST_DOOR_OPEN_NW_N:
iDoorGridNo = CurrentNode + dirDelta[ NORTHWEST ] + dirDelta[ NORTH ];
break;
case TRAVELCOST_DOOR_OPEN_NE_N:
iDoorGridNo = CurrentNode + dirDelta[ NORTHEAST ] + dirDelta[ NORTH ];
break;
case TRAVELCOST_DOOR_OPEN_W_W:
iDoorGridNo = CurrentNode + dirDelta[ WEST ] + dirDelta[ WEST ];
break;
case TRAVELCOST_DOOR_OPEN_SW_W:
iDoorGridNo = CurrentNode + dirDelta[ SOUTHWEST ] + dirDelta[ WEST ];
break;
case TRAVELCOST_DOOR_OPEN_NW_W:
iDoorGridNo = CurrentNode + dirDelta[ NORTHWEST ] + dirDelta[ WEST ];
break;
default:
break;
}
if ( fPathingForPlayer && gpWorldLevelData[ iDoorGridNo ].ubExtFlags[0] & MAPELEMENT_EXT_DOOR_STATUS_PRESENT )
{
// check door status
DOOR_STATUS* pDoorStatus = GetDoorStatus( iDoorGridNo );
if (pDoorStatus)
{
fDoorIsOpen = (pDoorStatus->ubFlags & DOOR_PERCEIVED_OPEN) != 0;
}
else
{
// door destroyed?
nextCost = gTileTypeMovementCost[ gpWorldLevelData[ CurrentNode ].ubTerrainID ];
}
}
else
{
// check door structure
STRUCTURE* pDoorStructure = FindStructure( iDoorGridNo, STRUCTURE_ANYDOOR );
if (pDoorStructure)
{
fDoorIsOpen = (pDoorStructure->fFlags & STRUCTURE_OPEN) != 0;
}
else
{
// door destroyed?
nextCost = gTileTypeMovementCost[ gpWorldLevelData[ CurrentNode ].ubTerrainID ];
}
}
// now determine movement cost... if it hasn't been changed already
if ( IS_TRAVELCOST_DOOR( nextCost ) )
{
if (fDoorIsOpen)
{
if (fDoorIsObstacleIfClosed)
{
nextCost = gTileTypeMovementCost[ gpWorldLevelData[ CurrentNode ].ubTerrainID ];
}
else
{
nextCost = TRAVELCOST_OBSTACLE;
}
}
else
{
if (fDoorIsObstacleIfClosed)
{
// door is closed and this should be an obstacle, EXCEPT if we are calculating
// a path for an enemy or NPC with keys
if ( fPathingForPlayer || ( pSoldier && (pSoldier->flags.uiStatusFlags & (SOLDIER_MONSTER | SOLDIER_ANIMAL) ) ) )
{
nextCost = TRAVELCOST_OBSTACLE;
}
else
{
// have to check if door is locked and NPC does not have keys!
// This function has an inaccurate name. It is actually checking if the door has LOCK info.
DOOR* pDoor = FindDoorInfoAtGridNo( iDoorGridNo );
if (pDoor)
{
if (!pDoor->fLocked || pSoldier->flags.bHasKeys)
{
// add to AP cost
//if (maxAPBudget)
{
fGoingThroughDoor = TRUE;
}
nextCost = gTileTypeMovementCost[ gpWorldLevelData[ CurrentNode ].ubTerrainID ];
}
else
{
nextCost = TRAVELCOST_OBSTACLE;
}
}
else
{
// The door is closed, so we still have to open it
fGoingThroughDoor = TRUE;
nextCost = gTileTypeMovementCost[ gpWorldLevelData[ CurrentNode ].ubTerrainID ];
}
}
}
else
{
nextCost = gTileTypeMovementCost[ gpWorldLevelData[ CurrentNode ].ubTerrainID ];
}
}
}
}
else if ( fNonSwimmer && ISWATER( gpWorldLevelData[ CurrentNode ].ubTerrainID))
{
// creatures and animals can't go in water
nextCost = TRAVELCOST_OBSTACLE;
}
}
// Apr. '96 - moved up be ahead of AP_Budget stuff
if ( nextCost >= NOPASS ) // || ( nextCost == TRAVELCOST_DOOR ) )
{
return -1;
}
// make water cost attractive for water to water paths
// Why? If a path through water gets you there sooner, you shouldn't need
// artificial inflation to figure that out. And if not, then get out of the water!
//if (bWaterToWater && ISWATER(nextCost) )
//{
// nextCost = EASYWATERCOST;
//}
return nextCost;
}//end CalcG
int AStarPathfinder::CalcH()
{
if ( fCopyReachable )
@@ -2506,7 +2248,6 @@ INT32 FindBestPath(SOLDIERTYPE *s , INT32 sDestination, INT8 bLevel, INT16 usMov
DOOR * pDoor;
STRUCTURE * pDoorStructure;
BOOLEAN fDoorIsOpen = FALSE;
BOOLEAN fNonFenceJumper;
BOOLEAN fNonSwimmer;
BOOLEAN fPathAroundPeople;
BOOLEAN fConsiderPersonAtDestAsObstacle;
@@ -2578,7 +2319,6 @@ if(!GridNoOnVisibleWorldTile(iDestination))
fTurnBased = ( (gTacticalStatus.uiFlags & TURNBASED) && (gTacticalStatus.uiFlags & INCOMBAT) );
fPathingForPlayer = ( (s->bTeam == gbPlayerNum) && (!gTacticalStatus.fAutoBandageMode) && !(s->flags.uiStatusFlags & SOLDIER_PCUNDERAICONTROL) );
fNonFenceJumper = !( IS_MERC_BODY_TYPE( s ) ) || (!s->CanClimbWithCurrentBackpack());//Moa: added backpack check
// Flugente: nonswimmers are those who are not mercs and not boats
fNonSwimmer = !(IS_MERC_BODY_TYPE( s ) );
@@ -3192,7 +2932,7 @@ if(!GridNoOnVisibleWorldTile(iDestination))
nextCost = gTileTypeMovementCost[ gpWorldLevelData[ newLoc ].ubTerrainID ];
}
}
else if ( nextCost == TRAVELCOST_FENCE && fNonFenceJumper )
else if ( nextCost == TRAVELCOST_FENCE && !canJumpFences(s))
{
goto NEXTDIR;
}
+2 -2
View File
@@ -3640,11 +3640,11 @@ INT16 MinAPsToThrow( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT8 ubAddTurningCos
iAPCost += ( ( ( 100 * iTop ) / iBottom) + 1) / 2;
// SANDRO - STOMP traits - reduce APs needed to throw grenades if having Demolitions skill
if( HAS_SKILL_TRAIT( pSoldier, DEMOLITIONS_NT ) && gGameOptions.fNewTraitSystem )
if( HAS_SKILL_TRAIT( pSoldier, THROWING_NT ) && gGameOptions.fNewTraitSystem )
{
if ( grenadAPreductionpossible )
{
iAPCost = max( 1, (INT32)(iAPCost * (100 - gSkillTraitValues.ubDEAPsNeededToThrowGrenadesReduction) / 100));
iAPCost = max( 1, (INT32)(iAPCost * (100 - gSkillTraitValues.ubTHAPsNeededToThrowGrenadesReduction) / 100));
}
}
+3 -1
View File
@@ -2469,7 +2469,9 @@ void ReduceAmmoDroppedByNonPlayerSoldiers( SOLDIERTYPE *pSoldier, INT32 iInvSlot
OBJECTTYPE *pObj = &( pSoldier->inv[ iInvSlot ] );
// if it's ammo
if ( Item[ pObj->usItem ].usItemClass == IC_AMMO )
if ( Item[ pObj->usItem ].usItemClass == IC_AMMO
&& Magazine[Item[pObj->usItem].ubClassIndex].ubMagType != AMMO_BOX
&& Magazine[Item[pObj->usItem].ubClassIndex].ubMagType != AMMO_CRATE)
{
//don't drop all the clips, just a random # of them between 1 and how many there are
pObj->ubNumberOfObjects = ( UINT8 ) ( 1 + Random( pObj->ubNumberOfObjects ) );
+21 -1
View File
@@ -1339,7 +1339,7 @@ MERCPROFILESTRUCT& MERCPROFILESTRUCT::operator=(const OLD_MERCPROFILESTRUCT_101&
this->bSex = src.bSex;
this->bArmourAttractiveness = src.bArmourAttractiveness;
this->ubMiscFlags2 = src.ubMiscFlags2;
this->bEvolution = src.bEvolution;
this->fRegresses = src.bEvolution == 2; // formerly, 2 == CharacterEvolution::DEVOLVES
this->ubMiscFlags = src.ubMiscFlags;
this->bSexist = src.bSexist;
this->bLearnToHate = src.bLearnToHate;
@@ -10700,6 +10700,22 @@ UINT8 SOLDIERTYPE::SoldierTakeDamage( INT8 bHeight, INT16 sLifeDeduct, INT16 sBr
return(ubCombinedLoss);
}
void SOLDIERTYPE::SoldierTakeDelayedDamage(INT8 bHeight, INT16 sLifeDeduct, INT16 sBreathLoss, UINT8 ubReason, UINT8 ubAttacker, INT32 sSourceGrid, INT16 sSubsequent, BOOLEAN fShowDamage)
{
delayedDamageFunction = [this, bHeight, sLifeDeduct, sBreathLoss, ubReason, ubAttacker, sSourceGrid, sSubsequent, fShowDamage]()
{
this->SoldierTakeDamage(bHeight, sLifeDeduct, sBreathLoss, ubReason, ubAttacker, sSourceGrid, sSubsequent, fShowDamage);
};
}
void SOLDIERTYPE::ResolveDelayedDamage()
{
if (delayedDamageFunction)
{
delayedDamageFunction();
delayedDamageFunction = nullptr;
}
}
extern BOOLEAN IsMercSayingDialogue( UINT8 ubProfileID );
@@ -11499,6 +11515,8 @@ void SOLDIERTYPE::MoveMerc( FLOAT dMovementChange, FLOAT dAngle, BOOLEAN fCheckR
// OK, set new position
this->EVENT_InternalSetSoldierPosition( dXPos, dYPos, FALSE, FALSE, FALSE );
this->ResolveDelayedDamage();
// Flugente: drag people
if ( currentlydragging )
{
@@ -26234,4 +26252,6 @@ void SOLDIERTYPE::InitializeExtraData(void)
this->ubQuickItemSlot = 0;
this->usGrenadeItem = 0;
this->delayedDamageFunction = nullptr;
}
+8
View File
@@ -20,6 +20,7 @@
#include <iterator>
#include "GameSettings.h" // added by Flugente
#include "Disease.h" // added by Flugente
#include <functional>
#define PTR_CIVILIAN (pSoldier->bTeam == CIV_TEAM)
#define PTR_CROUCHED (gAnimControl[ pSoldier->usAnimState ].ubHeight == ANIM_CROUCH)
@@ -1656,6 +1657,10 @@ public:
UINT8 ubQuickItemSlot;
UINT16 usGrenadeItem;
// anv: resolve damage with delay, e.g. damage applied mid movement that would cause issues with world data if applied immediately
std::function<void()> delayedDamageFunction;
public:
// CREATION FUNCTIONS
BOOLEAN DeleteSoldier( void );
@@ -1719,6 +1724,9 @@ public:
void ReviveSoldier( void );
UINT8 SoldierTakeDamage( INT8 bHeight, INT16 sLifeDeduct, INT16 sBreathDeduct, UINT8 ubReason, UINT8 ubAttacker, INT32 sSourceGrid, INT16 sSubsequent, BOOLEAN fShowDamage );
// anv: resolve damage with delay, e.g. damage applied mid movement that would cause issues with world data if applied immediately
void SoldierTakeDelayedDamage(INT8 bHeight, INT16 sLifeDeduct, INT16 sBreathDeduct, UINT8 ubReason, UINT8 ubAttacker, INT32 sSourceGrid, INT16 sSubsequent, BOOLEAN fShowDamage);
void ResolveDelayedDamage();
// Palette functions for soldiers
BOOLEAN CreateSoldierPalettes( void );
+1 -1
View File
@@ -1849,7 +1849,7 @@ void AddSoldierInitListMilitia( UINT8 ubNumGreen, UINT8 ubNumRegs, UINT8 ubNumEl
else
Assert(0);
curr->pBasicPlacement->bTeam = MILITIA_TEAM;
curr->pBasicPlacement->bOrders = STATIONARY;
curr->pBasicPlacement->bOrders = ONGUARD;
curr->pBasicPlacement->bAttitude = (INT8) Random( MAXATTITUDES );
// silversurfer: Replace body type. Militia tanks are not allowed.
+46 -1
View File
@@ -98,6 +98,7 @@ extern UINT8 gubItemDroppableFlag[NUM_INV_SLOTS];
//Random Stats
RANDOM_STATS_VALUES gRandomStatsValue[NUM_PROFILES];
void RandomStats();
void RandomGrowthModifiers();
void RandomStartSalary();
//Jenilee
@@ -459,6 +460,35 @@ void RandomStats()
ExitRandomMercs(); }
}
void RandomGrowthModifiers()
{
UINT32 cnt;
MERCPROFILESTRUCT * pProfile;
BOOLEAN useBellCurve = TRUE;
if (gGameExternalOptions.fMercRandomGrowthModifiers == TRUE)
{
for (cnt = 0; cnt < NUM_PROFILES; cnt++)
{
pProfile = &(gMercProfiles[cnt]);
// cap minimum growth modifier to negative half subpoints. this is effectively double speed using default values (subpoints = 50)
// cap maximum growth modifier to 30000. this would make a merc take 600x as long to level up a stat using default values
pProfile->bGrowthModifierExpLevel = RandomAbsoluteRange( pProfile->bGrowthModifierExpLevel, -gGameExternalOptions.usLevelSubpointsToImprove/2, 30000, gGameExternalOptions.iMercRandomGrowthModifiersRange, useBellCurve );
pProfile->bGrowthModifierLife = RandomAbsoluteRange( pProfile->bGrowthModifierLife, -gGameExternalOptions.usHealthSubpointsToImprove/2, 30000, gGameExternalOptions.iMercRandomGrowthModifiersRange, useBellCurve );
pProfile->bGrowthModifierAgility = RandomAbsoluteRange( pProfile->bGrowthModifierAgility, -gGameExternalOptions.usAgilitySubpointsToImprove/2, 30000, gGameExternalOptions.iMercRandomGrowthModifiersRange, useBellCurve );
pProfile->bGrowthModifierDexterity = RandomAbsoluteRange( pProfile->bGrowthModifierDexterity, -gGameExternalOptions.usDexteritySubpointsToImprove/2, 30000, gGameExternalOptions.iMercRandomGrowthModifiersRange, useBellCurve );
pProfile->bGrowthModifierStrength = RandomAbsoluteRange( pProfile->bGrowthModifierStrength, -gGameExternalOptions.usStrengthSubpointsToImprove/2, 30000, gGameExternalOptions.iMercRandomGrowthModifiersRange, useBellCurve );
pProfile->bGrowthModifierLeadership = RandomAbsoluteRange( pProfile->bGrowthModifierLeadership, -gGameExternalOptions.usLeadershipSubpointsToImprove/2, 30000, gGameExternalOptions.iMercRandomGrowthModifiersRange, useBellCurve );
pProfile->bGrowthModifierWisdom = RandomAbsoluteRange( pProfile->bGrowthModifierWisdom, -gGameExternalOptions.usWisdomSubpointsToImprove/2, 30000, gGameExternalOptions.iMercRandomGrowthModifiersRange, useBellCurve );
pProfile->bGrowthModifierMarksmanship = RandomAbsoluteRange( pProfile->bGrowthModifierMarksmanship, -gGameExternalOptions.usMarksmanshipSubpointsToImprove/2, 30000, gGameExternalOptions.iMercRandomGrowthModifiersRange, useBellCurve );
pProfile->bGrowthModifierMechanical = RandomAbsoluteRange( pProfile->bGrowthModifierMechanical, -gGameExternalOptions.usMechanicalSubpointsToImprove/2, 30000, gGameExternalOptions.iMercRandomGrowthModifiersRange, useBellCurve );
pProfile->bGrowthModifierExplosive = RandomAbsoluteRange( pProfile->bGrowthModifierExplosive, -gGameExternalOptions.usExplosivesSubpointsToImprove/2, 30000, gGameExternalOptions.iMercRandomGrowthModifiersRange, useBellCurve );
pProfile->bGrowthModifierMedical = RandomAbsoluteRange( pProfile->bGrowthModifierMedical, -gGameExternalOptions.usMedicalSubpointsToImprove/2, 30000, gGameExternalOptions.iMercRandomGrowthModifiersRange, useBellCurve );
}
}
}
void RandomStartSalary()
{
UINT32 cnt;
@@ -996,6 +1026,8 @@ for( int i = 0; i < NUM_PROFILES; i++ )
// ---------------
RandomStats (); //random stats by Jazz
RandomGrowthModifiers();
// Buggler: random starting salary
RandomStartSalary ();
@@ -2522,7 +2554,7 @@ void OverwriteMercProfileWithXMLData( UINT32 uiLoop )
gMercProfiles[ uiLoop ].bMechanical = tempProfiles[ uiLoop ].bMechanical ;
gMercProfiles[ uiLoop ].bExpLevel = tempProfiles[ uiLoop ].bExpLevel ;
gMercProfiles[ uiLoop ].bEvolution = tempProfiles[ uiLoop ].bEvolution ;
gMercProfiles[uiLoop].fRegresses = tempProfiles[ uiLoop ].fRegresses;
//////////////////////////////////////////////////////////////////////////////////////
// SANDRO - Check old/new traits and repair possible errors
if (gGameOptions.fNewTraitSystem)
@@ -2637,6 +2669,19 @@ void OverwriteMercProfileWithXMLData( UINT32 uiLoop )
gMercProfiles[ uiLoop ].usVoiceIndex = tempProfiles[uiLoop].usVoiceIndex;
gMercProfiles[ uiLoop ].Type = tempProfiles[uiLoop].Type;
gMercProfiles[uiLoop].fRegresses = tempProfiles[uiLoop].fRegresses;
gMercProfiles[uiLoop].bGrowthModifierLife = tempProfiles[uiLoop].bGrowthModifierLife;
gMercProfiles[uiLoop].bGrowthModifierStrength = tempProfiles[uiLoop].bGrowthModifierStrength;
gMercProfiles[uiLoop].bGrowthModifierAgility = tempProfiles[uiLoop].bGrowthModifierAgility;
gMercProfiles[uiLoop].bGrowthModifierDexterity = tempProfiles[uiLoop].bGrowthModifierDexterity;
gMercProfiles[uiLoop].bGrowthModifierWisdom = tempProfiles[uiLoop].bGrowthModifierWisdom;
gMercProfiles[uiLoop].bGrowthModifierMarksmanship = tempProfiles[uiLoop].bGrowthModifierMarksmanship;
gMercProfiles[uiLoop].bGrowthModifierExplosive = tempProfiles[uiLoop].bGrowthModifierExplosive;
gMercProfiles[uiLoop].bGrowthModifierLeadership = tempProfiles[uiLoop].bGrowthModifierLeadership;
gMercProfiles[uiLoop].bGrowthModifierMedical = tempProfiles[uiLoop].bGrowthModifierMedical;
gMercProfiles[uiLoop].bGrowthModifierMechanical = tempProfiles[uiLoop].bGrowthModifierMechanical;
gMercProfiles[uiLoop].bGrowthModifierExpLevel = tempProfiles[uiLoop].bGrowthModifierExpLevel;
gProfileType[uiLoop] = gMercProfiles[uiLoop].Type;
switch ( tempProfiles[uiLoop].Type )
+12 -1
View File
@@ -314,7 +314,18 @@ typedef struct
INT8 bExpLevel;
INT8 bEvolution;
BOOLEAN fRegresses;
INT16 bGrowthModifierLife;
INT16 bGrowthModifierStrength;
INT16 bGrowthModifierAgility;
INT16 bGrowthModifierDexterity;
INT16 bGrowthModifierWisdom;
INT16 bGrowthModifierMarksmanship;
INT16 bGrowthModifierExplosive;
INT16 bGrowthModifierLeadership;
INT16 bGrowthModifierMedical;
INT16 bGrowthModifierMechanical;
INT16 bGrowthModifierExpLevel;
// changed by SANDRO
INT8 bOldSkillTrait;
INT8 bOldSkillTrait2;
+21 -24
View File
@@ -743,6 +743,7 @@ void DrawMouseTooltip()
UINT32 uiDestPitchBYTES;
static INT32 iX, iY, iW, iH;
extern bool isTooltipScalingEnabled();
extern INT16 GetWidthOfString(const STR16);
extern INT16 GetNumberOfLinesInHeight(const STR16);
extern void DisplayHelpTokenizedString(const STR16,INT16,INT16);
@@ -752,29 +753,23 @@ void DrawMouseTooltip()
extern void DisplayTooltipString( const STR16 pStringA, INT16 sX, INT16 sY );
extern void j_log(PTR,...);
UINT16 fontHeight = isTooltipScalingEnabled()
? GetWinFontHeight(TOOLTIP_IFONT)
: GetFontHeight(FONT10ARIAL);
iX = mouseTT.iX;iY = mouseTT.iY;
iW = (INT32)GetWidthOfString( mouseTT.FastHelpText ) + 10;
iH = (INT32)( GetNumberOfLinesInHeight( mouseTT.FastHelpText ) * (GetFontHeight(FONT10ARIAL)+1) + 8 );
iW = (INT32)(GetWidthOfString(mouseTT.FastHelpText) + 10 * fTooltipScaleFactor);
iH = (INT32)(GetNumberOfLinesInHeight(mouseTT.FastHelpText) * (fontHeight + 1) + 8 * fTooltipScaleFactor);
if(1)//draw at cursor
{
iY -= (iH / 2);
if (gusMouseXPos > (SCREEN_WIDTH / 2))
iX = gusMouseXPos - iW - 24;
else
iX = gusMouseXPos + 24;
//if (gusMouseYPos > (SCREEN_HEIGHT / 2))
// iY -= 32;
if (iY <= 0) iY += 32;
}
iY -= (iH / 2);
if (gusMouseXPos > (SCREEN_WIDTH / 2))
iX = gusMouseXPos - iW - 24;
else
{ //draw in panel
//502,485 658,596 160*110 580,540
iX = 580 - (iW / 2);
iY = 540 - (iH/2);
if (iY + iH > SCREEN_HEIGHT) iY = SCREEN_HEIGHT - iH - 3 ;
}
iX = gusMouseXPos + 24;
//if (gusMouseYPos > (SCREEN_HEIGHT / 2))
// iY -= 32;
if (iY <= 0) iY += 32;
pDestBuf = LockVideoSurface( FRAME_BUFFER, &uiDestPitchBYTES );
SetClippingRegionAndImageWidth( uiDestPitchBYTES, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT );
@@ -784,10 +779,12 @@ void DrawMouseTooltip()
ShadowVideoSurfaceRect( FRAME_BUFFER, iX + 2, iY + 2, iX + iW - 3, iY + iH - 3 );
ShadowVideoSurfaceRect( FRAME_BUFFER, iX + 2, iY + 2, iX + iW - 3, iY + iH - 3 );
SetFont( FONT10ARIAL );
SetFontShadow( FONT_NEARBLACK );
DisplayHelpTokenizedString( mouseTT.FastHelpText ,( INT16 )( iX + 5 ), ( INT16 )( iY + 5 ) );
DisplayHelpTokenizedString(
mouseTT.FastHelpText,
(INT16)(iX + (isTooltipScalingEnabled() ? 5 * fTooltipScaleFactor : 5)),
(INT16)(iY + (isTooltipScalingEnabled() ? 4 * fTooltipScaleFactor : 5))
);
InvalidateRegion( iX, iY, (iX + iW) , (iY + iH) );
//InvalidateScreen();
}
}
+14 -1
View File
@@ -1700,7 +1700,20 @@ void CheckSquadMovementGroups( void )
for (INT8 iSoldier = 0; iSoldier < NUMBER_OF_SOLDIERS_PER_SQUAD; iSoldier++) {
if (Squad[iSquad][iSoldier] != NULL)
{
Squad[iSquad][iSoldier]->ubGroupID = pGroup->ubGroupID;
if (IsVehicle(Squad[iSquad][iSoldier]))
{
INT32 iCounter = 0;
for (iCounter = 0; iCounter < ubNumberOfVehicles; iCounter++)
{
if (pVehicleList[iCounter].ubProfileID == Squad[iSquad][iSoldier]->ubProfile)
break;
}
Squad[iSquad][iSoldier]->ubGroupID = pVehicleList[iCounter].ubMovementGroup;
}
else
{
Squad[iSquad][iSoldier]->ubGroupID = pGroup->ubGroupID;
}
}
}
}
+7 -8
View File
@@ -7479,8 +7479,8 @@ UINT32 CalcChanceToHitGun(SOLDIERTYPE *pSoldier, INT32 sGridNo, INT16 ubAimTime,
}
else
{
INT16 moda = GetToHitBonus(pInHand, iRange, bLightLevel, stance && iRange > MIN_PRONE_RANGE);
INT16 modb = GetToHitBonus(pInHand, iRange, bLightLevel, gAnimControl[pSoldier->usAnimState].ubEndHeight && iRange > MIN_PRONE_RANGE);
INT16 moda = GetToHitBonus(pInHand, iRange, bLightLevel, stance == ANIM_PRONE && iRange > MIN_PRONE_RANGE);
INT16 modb = GetToHitBonus(pInHand, iRange, bLightLevel, gAnimControl[pSoldier->usAnimState].ubEndHeight == ANIM_PRONE && iRange > MIN_PRONE_RANGE);
iChance += (INT32)((gGameExternalOptions.ubProneModifierPercentage * moda + (100 - gGameExternalOptions.ubProneModifierPercentage) * modb) / 100);
}
@@ -10175,10 +10175,10 @@ INT32 CalcMaxTossRange( SOLDIERTYPE * pSoldier, UINT16 usItem, BOOLEAN fArmed, O
iRange += ((iRange * gSkillTraitValues.ubTHBladesMaxRange ) / 100);
}
// sevenfm: add range only for hand grenades and not launched grenades
else if ( (Item[ usItem ].usItemClass == IC_GRENADE) && Item[usItem].ubCursor == TOSSCURS && (HAS_SKILL_TRAIT( pSoldier, DEMOLITIONS_NT )) )
else if ( (Item[ usItem ].usItemClass == IC_GRENADE) && Item[usItem].ubCursor == TOSSCURS && HAS_SKILL_TRAIT( pSoldier, THROWING_NT ) )
{
// better max range due to expertise
iRange += ((iRange * gSkillTraitValues.ubDEMaxRangeToThrowGrenades) / 100);
iRange += ((iRange * gSkillTraitValues.ubTHMaxRangeToThrowGrenades) / 100);
}
}
else
@@ -10260,9 +10260,8 @@ UINT32 CalcThrownChanceToHit(SOLDIERTYPE *pSoldier, INT32 sGridNo, INT16 ubAimTi
else
{
iChance += gSkillTraitValues.bCtHModifierThrowingGrenades; // -10% for untrained mercs
if ( HAS_SKILL_TRAIT( pSoldier, DEMOLITIONS_NT ) )
iChance += gSkillTraitValues.ubDECtHWhenThrowingGrenades; // +30% chance
if ( HAS_SKILL_TRAIT( pSoldier, THROWING_NT ) )
iChance += gSkillTraitValues.ubTHCtHWhenThrowingGrenades;
}
}
else
@@ -12196,4 +12195,4 @@ BOOLEAN ArtilleryStrike( UINT16 usItem, UINT8 ubOwnerID, UINT32 usStartingGridNo
//REAL_OBJECT* pObject = &( ObjectSlots[ iID ] );
return TRUE;
}
}
+2 -2
View File
@@ -157,8 +157,8 @@ typedef PARSE_STAGE;
#define ALTSECTORSFILENAME "Map\\AltSectors.xml"
#define SAMSITESFILENAME "Map\\SamSites.xml"
#define HELISITESFILENAME "Map\\HeliSites.xml"
#define EXTRAITEMSFILENAME "Map\\A9_0_ExtraItems" // ".xml" will be added @runtime
#define EXTRAITEMSFILENAME2 "Map\\A11_0_ExtraItems" // ".xml" will be added @runtime
#define EXTRAITEMSFILENAME "Map\\ExtraItems\\A9_0_ExtraItems" // ".xml" will be added @runtime
#define EXTRAITEMSFILENAME2 "Map\\ExtraItems\\A11_0_ExtraItems" // ".xml" will be added @runtime
#define SHIPPINGDESTINATIONSFILENAME "Map\\ShippingDestinations.xml"
#define DELIVERYMETHODSFILENAME "Map\\DeliveryMethods.xml"
#define DELIVERYMETHODSFILENAME "Map\\DeliveryMethods.xml"
+31 -10
View File
@@ -20,6 +20,8 @@ struct
}
typedef attachmentParseData;
UINT32 gMAXATTACHMENTS_READ = 0;
static void XMLCALL
attachmentStartElementHandle(void *userData, const XML_Char *name, const XML_Char **atts)
{
@@ -93,9 +95,9 @@ attachmentEndElementHandle(void *userData, const XML_Char *name)
if(pData->curIndex < pData->maxArraySize)
{
//DebugMsg(TOPIC_JA2, DBG_LEVEL_3,"AttachmentStartElementHandle: writing attachment to array");
Attachment[pData->curIndex][0] = pData->curAttachment[0]; //write the attachment into the table
Attachment[pData->curIndex][1] = pData->curAttachment[1];
Attachment[pData->curIndex][2] = pData->curAttachment[2];
Attachment[pData->curIndex].attachmentIndex = pData->curAttachment[0]; //write the attachment into the table
Attachment[pData->curIndex].itemIndex = pData->curAttachment[1];
Attachment[pData->curIndex].APCost = pData->curAttachment[2];
}
}
else if(strcmp(name, "attachmentIndex") == 0)
@@ -127,7 +129,25 @@ attachmentEndElementHandle(void *userData, const XML_Char *name)
}
static void MapAttachments()
{
std::list<AttachmentStruct> stdList;
std::list<AttachmentStruct>::iterator it;
UINT32 i = 0;
for (i = 0; i < gMAXATTACHMENTS_READ; i++)
{
stdList.push_back(Attachment[i]);
AttachmentBackmap.insert(std::make_pair(Attachment[i].itemIndex, Attachment[i]));
}
stdList.sort();
for (it = stdList.begin(), i = 0; it != stdList.end(); it++, i++)
{
Attachment[i] = *it;
}
}
BOOLEAN ReadInAttachmentStats(STR fileName)
{
@@ -171,7 +191,6 @@ BOOLEAN ReadInAttachmentStats(STR fileName)
XML_SetUserData(parser, &pData);
if(!XML_Parse(parser, lpcBuffer, uiFSize, TRUE))
{
CHAR8 errorBuf[511];
@@ -183,13 +202,15 @@ BOOLEAN ReadInAttachmentStats(STR fileName)
return FALSE;
}
gMAXATTACHMENTS_READ = pData.curIndex + 1;
MapAttachments();
MemFree(lpcBuffer);
XML_ParserFree(parser);
return( TRUE );
}
BOOLEAN WriteAttachmentStats()
{
HWFILE hFile;
@@ -208,10 +229,10 @@ BOOLEAN WriteAttachmentStats()
{
FilePrintf(hFile,"\t<ATTACHMENT>\r\n");
FilePrintf(hFile,"\t\t<attachmentIndex>%d</attachmentIndex>\r\n", Attachment[cnt][0]);
FilePrintf(hFile,"\t\t<itemIndex>%d</itemIndex>\r\n", Attachment[cnt][1]);
FilePrintf(hFile,"\t\t<APCost>%d</APCost>\r\n", Attachment[cnt][2]);
FilePrintf(hFile,"\t\t<NASOnly>%d</NASOnly>\r\n", Attachment[cnt][3]);
FilePrintf(hFile,"\t\t<attachmentIndex>%d</attachmentIndex>\r\n", Attachment[cnt].attachmentIndex);
FilePrintf(hFile,"\t\t<itemIndex>%d</itemIndex>\r\n", Attachment[cnt].itemIndex);
FilePrintf(hFile,"\t\t<APCost>%d</APCost>\r\n", Attachment[cnt].APCost);
FilePrintf(hFile,"\t\t<NASOnly>%d</NASOnly>\r\n", Attachment[cnt].NASOnly);
FilePrintf(hFile,"\t</ATTACHMENT>\r\n");
}
+4 -2
View File
@@ -19,6 +19,8 @@ struct
}
typedef launchableParseData;
UINT32 gMAXLAUNCHABLES_READ = 0;
static void XMLCALL
launchableStartElementHandle(void *userData, const XML_Char *name, const XML_Char **atts)
{
@@ -168,9 +170,9 @@ BOOLEAN ReadInLaunchableStats(STR fileName)
return FALSE;
}
gMAXLAUNCHABLES_READ = pData.curIndex + 1;
MemFree(lpcBuffer);
XML_ParserFree(parser);
return( TRUE );
+88 -6
View File
@@ -101,7 +101,19 @@ profileStartElementHandle(void *userData, const XML_Char *name, const XML_Char *
strcmp(name, "bMedical") == 0 ||
strcmp(name, "bMechanical") == 0 ||
strcmp(name, "bExpLevel") == 0 ||
strcmp(name, "bEvolution") == 0 ||
strcmp(name, "fRegresses") == 0 ||
// rftr: growth rates are intended to replace the <bEvolution> tag, letting each stat have its own growth modifier
strcmp(name, "bGrowthModifierLife") == 0 ||
strcmp(name, "bGrowthModifierStrength") == 0 ||
strcmp(name, "bGrowthModifierAgility") == 0 ||
strcmp(name, "bGrowthModifierDexterity") == 0 ||
strcmp(name, "bGrowthModifierWisdom") == 0 ||
strcmp(name, "bGrowthModifierMarksmanship") == 0 ||
strcmp(name, "bGrowthModifierExplosive") == 0 ||
strcmp(name, "bGrowthModifierLeadership") == 0 ||
strcmp(name, "bGrowthModifierMedical") == 0 ||
strcmp(name, "bGrowthModifierMechanical") == 0 ||
strcmp(name, "bGrowthModifierExpLevel") == 0 ||
// added by SANDRO
strcmp(name, "bOldSkillTrait") == 0 ||
strcmp(name, "bOldSkillTrait2") == 0 ||
@@ -280,7 +292,18 @@ profileEndElementHandle(void *userData, const XML_Char *name)
tempProfiles[pData->curIndex].bMechanical = pData->curProfile.bMechanical;
tempProfiles[pData->curIndex].bExpLevel = pData->curProfile.bExpLevel;
tempProfiles[pData->curIndex].bEvolution = pData->curProfile.bEvolution;
tempProfiles[pData->curIndex].fRegresses = pData->curProfile.fRegresses;
tempProfiles[pData->curIndex].bGrowthModifierLife = pData->curProfile.bGrowthModifierLife;
tempProfiles[pData->curIndex].bGrowthModifierStrength = pData->curProfile.bGrowthModifierStrength;
tempProfiles[pData->curIndex].bGrowthModifierAgility = pData->curProfile.bGrowthModifierAgility;
tempProfiles[pData->curIndex].bGrowthModifierDexterity = pData->curProfile.bGrowthModifierDexterity;
tempProfiles[pData->curIndex].bGrowthModifierWisdom = pData->curProfile.bGrowthModifierWisdom;
tempProfiles[pData->curIndex].bGrowthModifierMarksmanship = pData->curProfile.bGrowthModifierMarksmanship;
tempProfiles[pData->curIndex].bGrowthModifierExplosive = pData->curProfile.bGrowthModifierExplosive;
tempProfiles[pData->curIndex].bGrowthModifierLeadership = pData->curProfile.bGrowthModifierLeadership;
tempProfiles[pData->curIndex].bGrowthModifierMedical = pData->curProfile.bGrowthModifierMedical;
tempProfiles[pData->curIndex].bGrowthModifierMechanical = pData->curProfile.bGrowthModifierMechanical;
tempProfiles[pData->curIndex].bGrowthModifierExpLevel = pData->curProfile.bGrowthModifierExpLevel;
// added by SANDRO
tempProfiles[pData->curIndex].bOldSkillTrait = pData->curProfile.bOldSkillTrait;
tempProfiles[pData->curIndex].bOldSkillTrait2 = pData->curProfile.bOldSkillTrait2;
@@ -586,11 +609,70 @@ profileEndElementHandle(void *userData, const XML_Char *name)
pData->curElement = ELEMENT;
pData->curProfile.bExpLevel = (UINT32) strtoul(pData->szCharData, NULL, 0);
}
else if(strcmp(name, "bEvolution") == 0)
else if(strcmp(name, "fRegresses") == 0)
{
pData->curElement = ELEMENT;
pData->curProfile.bEvolution = (UINT32) strtoul(pData->szCharData, NULL, 0);
pData->curProfile.fRegresses = (BOOLEAN) strtoul(pData->szCharData, NULL, 0);
}
else if (strncmp(name, "bGrowthModifier", 11) == 0) // doing this to avoid C1061
{
if (strcmp(name, "bGrowthModifierLife") == 0)
{
pData->curElement = ELEMENT;
pData->curProfile.bGrowthModifierLife = (UINT32)strtoul(pData->szCharData, NULL, 0);
}
else if(strcmp(name, "bGrowthModifierStrength") == 0)
{
pData->curElement = ELEMENT;
pData->curProfile.bGrowthModifierStrength = (UINT32)strtoul(pData->szCharData, NULL, 0);
}
else if(strcmp(name, "bGrowthModifierAgility") == 0)
{
pData->curElement = ELEMENT;
pData->curProfile.bGrowthModifierAgility = (UINT32)strtoul(pData->szCharData, NULL, 0);
}
else if(strcmp(name, "bGrowthModifierDexterity") == 0)
{
pData->curElement = ELEMENT;
pData->curProfile.bGrowthModifierDexterity = (UINT32)strtoul(pData->szCharData, NULL, 0);
}
else if(strcmp(name, "bGrowthModifierWisdom") == 0)
{
pData->curElement = ELEMENT;
pData->curProfile.bGrowthModifierWisdom = (UINT32)strtoul(pData->szCharData, NULL, 0);
}
else if(strcmp(name, "bGrowthModifierMarksmanship") == 0)
{
pData->curElement = ELEMENT;
pData->curProfile.bGrowthModifierMarksmanship = (UINT32)strtoul(pData->szCharData, NULL, 0);
}
else if(strcmp(name, "bGrowthModifierExplosive") == 0)
{
pData->curElement = ELEMENT;
pData->curProfile.bGrowthModifierExplosive = (UINT32)strtoul(pData->szCharData, NULL, 0);
}
else if(strcmp(name, "bGrowthModifierLeadership") == 0)
{
pData->curElement = ELEMENT;
pData->curProfile.bGrowthModifierLeadership = (UINT32)strtoul(pData->szCharData, NULL, 0);
}
else if(strcmp(name, "bGrowthModifierMedical") == 0)
{
pData->curElement = ELEMENT;
pData->curProfile.bGrowthModifierMedical = (UINT32)strtoul(pData->szCharData, NULL, 0);
}
else if(strcmp(name, "bGrowthModifierMechanical") == 0)
{
pData->curElement = ELEMENT;
pData->curProfile.bGrowthModifierMechanical = (UINT32)strtoul(pData->szCharData, NULL, 0);
}
else if(strcmp(name, "bGrowthModifierExpLevel") == 0)
{
pData->curElement = ELEMENT;
pData->curProfile.bGrowthModifierExpLevel = (UINT32)strtoul(pData->szCharData, NULL, 0);
}
}
////////////////////////////////////////////////////////////////////////////
// SANDRO was here - messed this a bit
@@ -1600,7 +1682,7 @@ BOOLEAN WriteMercProfiles()
FilePrintf(hFile,"\t\t<bMedical>%d</bMedical>\r\n", gMercProfiles[ cnt ].bMedical);
FilePrintf(hFile,"\t\t<bMechanical>%d</bMechanical>\r\n", gMercProfiles[ cnt ].bMechanical);
FilePrintf(hFile,"\t\t<bExpLevel>%d</bExpLevel>\r\n", gMercProfiles[ cnt ].bExpLevel);
FilePrintf(hFile,"\t\t<bEvolution>%d</bEvolution>\r\n", gMercProfiles[ cnt ].bEvolution);
FilePrintf(hFile,"\t\t<fRegresses>%d</fRegresses>\r\n", gMercProfiles[ cnt ].fRegresses);
////////////////////////////////////////////////////////////////////////////////////////////
// SANDRO - old/new traits
if (gGameOptions.fNewTraitSystem)
+4
View File
@@ -387,6 +387,10 @@ enum
NPC_ACTION_GLOBAL_OFFENSIVE_1,
NPC_ACTION_GLOBAL_OFFENSIVE_2,
// rftr: transport groups
NPC_ACTION_DEPLOY_TRANSPORT_GROUP,
NPC_ACTION_RETURN_TRANSPORT_GROUP,
NPC_ACTION_RECRUIT_PROFILE_TO_EPC = 700,
NPC_ACTION_UNRECRUIT_EPC = 701,
+15 -13
View File
@@ -402,18 +402,7 @@ typedef enum
NUM_SEXIST
} SexistLevels;
// training defines for evolution, no stat increase, stat decrease( de-evolve )
typedef enum
{
NORMAL_EVOLUTION =0,
NO_EVOLUTION,
DEVOLVE,
THREEQUARTER_EVOLUTION,
HALF_EVOLUTION,
ONEQUARTER_EVOLUTION,
} CharacterEvolution;
// rftr: removed the CharacterEvolution enum as it was replaced by growth modifiers
#define BUDDY_MERC( prof, bud ) ((prof)->bBuddy[0] == (bud) || (prof)->bBuddy[1] == (bud) || (prof)->bBuddy[2] == (bud) || (prof)->bBuddy[3] == (bud) || (prof)->bBuddy[4] == (bud) || ( (prof)->bLearnToLike == (bud) && (prof)->bLearnToLikeCount == 0 ) )
#define HATED_MERC( prof, hat ) ((prof)->bHated[0] == (hat) || (prof)->bHated[1] == (hat) || (prof)->bHated[2] == (hat) || (prof)->bHated[3] == (hat) || (prof)->bHated[4] == (hat) || ( (prof)->bLearnToHate == (hat) && (prof)->bLearnToHateCount == 0 ) )
@@ -789,7 +778,7 @@ public:
INT8 bSex;
INT8 bArmourAttractiveness;
UINT8 ubMiscFlags2;
INT8 bEvolution;
BOOLEAN fRegresses;
UINT8 ubMiscFlags;
UINT8 bSexist;
UINT8 bLearnToHate;
@@ -1009,6 +998,19 @@ public:
// Flugente: type of profile
UINT32 Type;
// rftr: growth modifiers - ignored if fRegresses is TRUE
INT16 bGrowthModifierLife;
INT16 bGrowthModifierStrength;
INT16 bGrowthModifierAgility;
INT16 bGrowthModifierDexterity;
INT16 bGrowthModifierWisdom;
INT16 bGrowthModifierMarksmanship;
INT16 bGrowthModifierExplosive;
INT16 bGrowthModifierLeadership;
INT16 bGrowthModifierMedical;
INT16 bGrowthModifierMechanical;
INT16 bGrowthModifierExpLevel;
}; // MERCPROFILESTRUCT;
// WANNE - BMP: DONE!
+1 -2
View File
@@ -174,7 +174,6 @@ extern THREATTYPE Threat[MAXMERCS];
extern int ThreatPercent[10];
extern UINT8 SkipCoverCheck;
extern INT8 GameOption[MAXGAMEOPTIONS];
extern UINT32 guiThreatCnt;
typedef enum
{
@@ -322,4 +321,4 @@ BOOLEAN GetBestAoEGridNo(SOLDIERTYPE *pSoldier, INT32* pGridNo, INT16 aRadius, U
BOOLEAN GetFarthestOpponent(SOLDIERTYPE *pSoldier, UINT8* puID, INT16 sRange);
// are there more allies than friends in adjacent sectors?
BOOLEAN MoreFriendsThanEnemiesinNearbysectors(UINT8 ausTeam, INT16 aX, INT16 aY, INT8 aZ);
BOOLEAN MoreFriendsThanEnemiesinNearbysectors(UINT8 ausTeam, INT16 aX, INT16 aY, INT8 aZ);
-1
View File
@@ -1430,7 +1430,6 @@ void ActionDone(SOLDIERTYPE *pSoldier)
UINT8 SkipCoverCheck = FALSE;
THREATTYPE Threat[MAXMERCS];
UINT32 guiThreatCnt = 0;
// threat percentage is based on the certainty of opponent knowledge:
// opplist value: -4 -3 -2 -1 SEEN 1 2 3 4 5
+21 -19
View File
@@ -5938,7 +5938,7 @@ INT32 RandomizeOpponentLocation(INT32 sSpot, SOLDIERTYPE *pOpponent, INT16 sMaxD
}
// first call PrepareThreatlist to make threat list
UINT8 ClosestKnownThreatID(SOLDIERTYPE *pSoldier)
UINT8 ClosestKnownThreatID(SOLDIERTYPE *pSoldier, UINT32 uiThreatCnt)
{
CHECKF(pSoldier);
@@ -5948,7 +5948,7 @@ UINT8 ClosestKnownThreatID(SOLDIERTYPE *pSoldier)
UINT8 ubClosestOpponentID = NOBODY;
// use global defined threat list
for (uiLoop = 0; uiLoop < guiThreatCnt; uiLoop++)
for (uiLoop = 0; uiLoop < uiThreatCnt; uiLoop++)
{
// if for some reason we have incorrect location
if (TileIsOutOfBounds(Threat[uiLoop].sGridNo))
@@ -5968,7 +5968,7 @@ UINT8 ClosestKnownThreatID(SOLDIERTYPE *pSoldier)
}
// first call PrepareThreatlist to make threat list
UINT8 ClosestSeenThreatID(SOLDIERTYPE *pSoldier, UINT8 ubMax)
UINT8 ClosestSeenThreatID(SOLDIERTYPE *pSoldier, UINT32 uiThreatCnt, UINT8 ubMax)
{
CHECKF(pSoldier);
@@ -5978,7 +5978,7 @@ UINT8 ClosestSeenThreatID(SOLDIERTYPE *pSoldier, UINT8 ubMax)
UINT8 ubClosestOpponentID = NOBODY;
// use global defined threat list
for (uiLoop = 0; uiLoop < guiThreatCnt; uiLoop++)
for (uiLoop = 0; uiLoop < uiThreatCnt; uiLoop++)
{
// if for some reason we have incorrect location
if (TileIsOutOfBounds(Threat[uiLoop].sGridNo))
@@ -6001,7 +6001,7 @@ UINT8 ClosestSeenThreatID(SOLDIERTYPE *pSoldier, UINT8 ubMax)
return(ubClosestOpponentID);
}
void PrepareThreatlist(SOLDIERTYPE *pSoldier)
UINT32 PrepareThreatlist(SOLDIERTYPE *pSoldier)
{
SOLDIERTYPE *pOpponent;
INT32 iThreatRange, iClosestThreatRange = 1500;
@@ -6014,10 +6014,10 @@ void PrepareThreatlist(SOLDIERTYPE *pSoldier)
INT32 iThreatCertainty;
INT32 iMaxThreatRange = MAX_THREAT_RANGE + AI_PATHCOST_RADIUS;
guiThreatCnt = 0;
UINT32 uiThreatCnt = 0;
if (!pSoldier)
return;
return 0;
// look through all opponents for those we know of
for (uiLoop = 0; uiLoop < guiNumMercSlots; uiLoop++)
@@ -6065,35 +6065,37 @@ void PrepareThreatlist(SOLDIERTYPE *pSoldier)
}
// remember this opponent as a current threat, but DON'T REDUCE FOR COVER!
Threat[guiThreatCnt].iValue = CalcManThreatValue(pOpponent, pSoldier->sGridNo, FALSE, pSoldier);
Threat[uiThreatCnt].iValue = CalcManThreatValue(pOpponent, pSoldier->sGridNo, FALSE, pSoldier);
// if the opponent is no threat at all for some reason
if (Threat[guiThreatCnt].iValue == -999)
if (Threat[uiThreatCnt].iValue == -999)
{
continue; // check next opponent
}
Threat[guiThreatCnt].pOpponent = pOpponent;
Threat[guiThreatCnt].sGridNo = sThreatLoc;
Threat[guiThreatCnt].iCertainty = iThreatCertainty;
Threat[guiThreatCnt].iOrigRange = iThreatRange;
Threat[uiThreatCnt].pOpponent = pOpponent;
Threat[uiThreatCnt].sGridNo = sThreatLoc;
Threat[uiThreatCnt].iCertainty = iThreatCertainty;
Threat[uiThreatCnt].iOrigRange = iThreatRange;
// calculate how many APs he will have at the start of the next turn
Threat[guiThreatCnt].iAPs = pOpponent->CalcActionPoints();
Threat[uiThreatCnt].iAPs = pOpponent->CalcActionPoints();
// sevenfm: more information
Threat[guiThreatCnt].bLevel = bThreatLevel;
Threat[guiThreatCnt].bKnowledge = bKnowledge;
Threat[guiThreatCnt].bPersonalKnowledge = bPersonalKnowledge;
Threat[guiThreatCnt].bPublicKnowledge = bPublicKnowledge;
Threat[uiThreatCnt].bLevel = bThreatLevel;
Threat[uiThreatCnt].bKnowledge = bKnowledge;
Threat[uiThreatCnt].bPersonalKnowledge = bPersonalKnowledge;
Threat[uiThreatCnt].bPublicKnowledge = bPublicKnowledge;
if (iThreatRange < iClosestThreatRange)
{
iClosestThreatRange = iThreatRange;
}
guiThreatCnt++;
uiThreatCnt++;
}
return uiThreatCnt;
}
UINT8 CountPublicKnownEnemies(SOLDIERTYPE *pSoldier, INT32 sGridNo, INT16 sDistance)
+8 -3
View File
@@ -3308,6 +3308,10 @@ BOOLEAN AIDetermineStealingWeaponAttempt( SOLDIERTYPE * pSoldier, SOLDIERTYPE *
UINT16 dfgvdfv = Item[pOpponent->inv[HANDPOS].usItem].usItemClass;
return( FALSE );
}
if (HasAttachmentOfClass(&(pOpponent->inv[HANDPOS]), AC_SLING))
{
return FALSE;
}
uiSuccessChance = CalcChanceToSteal(pSoldier, pOpponent, 0);
if ( uiSuccessChance >= 100 )
@@ -3755,6 +3759,7 @@ void CheckTossSelfSmoke(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow)
{
INT16 ubMinAPcost;
INT8 bGrenadeIn = NO_SLOT;
UINT32 uiThreatCnt = 0;
// initialize
pBestThrow->ubPossible = FALSE;
@@ -3771,7 +3776,7 @@ void CheckTossSelfSmoke(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow)
bGrenadeIn = FindThrowableGrenade(pSoldier, EXPLOSV_SMOKE);
// prepare threat list for ClosestSeenThreatID(), ClosestKnownThreatID()
PrepareThreatlist(pSoldier);
uiThreatCnt = PrepareThreatlist(pSoldier);
if (bGrenadeIn != NO_SLOT)
{
@@ -3812,7 +3817,7 @@ void CheckTossSelfSmoke(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow)
if (TileIsOutOfBounds(sTargetSpot))
{
ubClosestThreatID = ClosestSeenThreatID(pSoldier, SEEN_LAST_TURN);
ubClosestThreatID = ClosestSeenThreatID(pSoldier, uiThreatCnt, SEEN_LAST_TURN);
if (ubClosestThreatID != NOBODY &&
MercPtrs[ubClosestThreatID] &&
@@ -3826,7 +3831,7 @@ void CheckTossSelfSmoke(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow)
if (TileIsOutOfBounds(sTargetSpot))
{
ubClosestThreatID = ClosestKnownThreatID(pSoldier);
ubClosestThreatID = ClosestKnownThreatID(pSoldier, uiThreatCnt);
if (ubClosestThreatID != NOBODY &&
MercPtrs[ubClosestThreatID] &&
+1 -1
View File
@@ -753,7 +753,7 @@ INT32 FindBestNearbyCover(SOLDIERTYPE *pSoldier, INT32 morale, INT32 *piPercentB
iMyThreatValue = CalcManThreatValue(pSoldier, NOWHERE, FALSE, pSoldier);
// prepare threat list from known enemies
PrepareThreatlist(pSoldier);
uiThreatCnt = PrepareThreatlist(pSoldier);
// if no known opponents were found to threaten us, can't worry about cover
if (!uiThreatCnt)
+6 -6
View File
@@ -808,7 +808,7 @@ INT32 GetEffectiveApproachValue( UINT8 usProfile, UINT8 usApproach, CHAR16* apSt
if ( apStr )
{
swprintf( atStr, szLaptopStatText[0], threateneffectiveness );
swprintf( atStr, szLaptopStatText[LAPTOP_STAT_TEXT_THREATEN_EFFECTIVENESS], threateneffectiveness );
wcscat( apStr, atStr );
}
@@ -818,7 +818,7 @@ INT32 GetEffectiveApproachValue( UINT8 usProfile, UINT8 usApproach, CHAR16* apSt
{
if ( apStr )
{
swprintf( atStr, szLaptopStatText[1], gMercProfiles[usProfile].bLeadership );
swprintf( atStr, szLaptopStatText[LAPTOP_STAT_TEXT_LEADERSHIP], gMercProfiles[usProfile].bLeadership );
wcscat( apStr, atStr );
}
@@ -829,7 +829,7 @@ INT32 GetEffectiveApproachValue( UINT8 usProfile, UINT8 usApproach, CHAR16* apSt
if ( apStr )
{
swprintf( atStr, szLaptopStatText[2], approachfactor );
swprintf( atStr, szLaptopStatText[LAPTOP_STAT_TEXT_APPROACH_MODIFIER], approachfactor );
wcscat( apStr, atStr );
}
@@ -855,7 +855,7 @@ INT32 GetEffectiveApproachValue( UINT8 usProfile, UINT8 usApproach, CHAR16* apSt
if ( apStr )
{
swprintf( atStr, szLaptopStatText[3], bgmodifier );
swprintf( atStr, szLaptopStatText[LAPTOP_STAT_TEXT_BACKGROUND_MODIFIER], bgmodifier );
wcscat( apStr, atStr );
}
@@ -868,7 +868,7 @@ INT32 GetEffectiveApproachValue( UINT8 usProfile, UINT8 usApproach, CHAR16* apSt
swprintf( atStr, L" \n" );
wcscat( apStr, atStr );
swprintf( atStr, szLaptopStatText[4] );
swprintf( atStr, szLaptopStatText[LAPTOP_STAT_TEXT_ASSERTIVE] );
wcscat( apStr, atStr );
}
else if ( DoesMercHavePersonality( pSoldier, CHAR_TRAIT_MALICIOUS ) )
@@ -876,7 +876,7 @@ INT32 GetEffectiveApproachValue( UINT8 usProfile, UINT8 usApproach, CHAR16* apSt
swprintf( atStr, L" \n" );
wcscat( apStr, atStr );
swprintf( atStr, szLaptopStatText[5] );
swprintf( atStr, szLaptopStatText[LAPTOP_STAT_TEXT_MALICIOUS] );
wcscat( apStr, atStr );
}
}
+3 -3
View File
@@ -314,9 +314,9 @@ BOOLEAN AICheckFriendsNoContact( SOLDIERTYPE *pSoldier );
BOOLEAN AICheckIsFlanking( SOLDIERTYPE *pSoldier );
INT8 CalcMoraleNew(SOLDIERTYPE *pSoldier);
void PrepareThreatlist(SOLDIERTYPE *pSoldier);
UINT8 ClosestSeenThreatID(SOLDIERTYPE *pSoldier, UINT8 ubMax = SEEN_CURRENTLY); // first call PrepareThreatlist to make threat list
UINT8 ClosestKnownThreatID(SOLDIERTYPE *pSoldier); // first call PrepareThreatlist to make threat list
UINT32 PrepareThreatlist(SOLDIERTYPE *pSoldier);
UINT8 ClosestSeenThreatID(SOLDIERTYPE *pSoldier, UINT32 uiThreatCnt, UINT8 ubMax = SEEN_CURRENTLY); // first call PrepareThreatlist to make threat list
UINT8 ClosestKnownThreatID(SOLDIERTYPE *pSoldier, UINT32 uiThreatCnt); // first call PrepareThreatlist to make threat list
BOOLEAN ProneSightCoverAtSpot(SOLDIERTYPE *pSoldier, INT32 sSpot, BOOLEAN fUnlimited);
BOOLEAN SightCoverAtSpot(SOLDIERTYPE *pSoldier, INT32 sSpot, BOOLEAN fUnlimited);
+14 -8
View File
@@ -82,14 +82,16 @@ void InitRadarScreenCoords( )
{
RADAR_WINDOW_STRAT_X = UI_BOTTOM_X + 1182;
RADAR_WINDOW_STRAT_Y = UI_BOTTOM_Y + 9;
RADAR_WINDOW_TM_X = xResOffset + (xResSize - 97) + 223;
RADAR_WINDOW_SM_X = xResOffset + (xResSize - 97);
}
else
{
RADAR_WINDOW_STRAT_X = xResOffset + (xResSize - 97);
RADAR_WINDOW_STRAT_Y = (SCREEN_HEIGHT - 107);
RADAR_WINDOW_TM_X = xResOffset + (xResSize - 97);
RADAR_WINDOW_SM_X = xResOffset + (xResSize - 97);
}
RADAR_WINDOW_TM_X = xResOffset + (xResSize - 97);
RADAR_WINDOW_SM_X = xResOffset + (xResSize - 97);
RADAR_WINDOW_TM_Y = (INTERFACE_START_Y + 13);
RADAR_WINDOW_SM_Y = ((UsingNewInventorySystem() == false)) ? (INV_INTERFACE_START_Y + 33) : (INV_INTERFACE_START_Y + 116);
@@ -435,8 +437,8 @@ void RenderRadarScreen( )
sWidth = ( RADAR_WINDOW_WIDTH );
sHeight = ( RADAR_WINDOW_HEIGHT );
sX = RADAR_WINDOW_TM_X;
sY = gsRadarY;
sX = gsRadarX;
sY = gsRadarY;
sRadarTLX = (INT16)( ( sTopLeftWorldX * gdScaleX ) - sRadarCX + sX + ( sWidth /2 ) );
@@ -601,7 +603,7 @@ void RenderRadarScreen( )
}
// Add starting relative to interface
sXSoldRadar += RADAR_WINDOW_TM_X;
sXSoldRadar += gsRadarX;
sYSoldRadar += gsRadarY;
if(gbPixelDepth==16)
@@ -767,9 +769,13 @@ BOOLEAN CreateDestroyMouseRegionsForSquadList( void )
CHECKF(AddVideoObject(&VObjectDesc, &uiHandle));
GetVideoObject(&hHandle, uiHandle);
BltVideoObject( guiSAVEBUFFER , hHandle, 0,(xResOffset + xResSize - 102 - 1), gsVIEWPORT_END_Y, VO_BLT_SRCTRANSPARENCY,NULL );
RestoreExternBackgroundRect ((xResOffset + xResSize - 102 - 1), gsVIEWPORT_END_Y, 102,( INT16 ) ( SCREEN_HEIGHT - gsVIEWPORT_END_Y ) );
INT32 xCoord = (xResOffset + xResSize - 102 - 1);
if (isWidescreenUI())
{
xCoord += 224;
}
BltVideoObject( guiSAVEBUFFER, hHandle, 0, xCoord, gsVIEWPORT_END_Y, VO_BLT_SRCTRANSPARENCY,NULL );
RestoreExternBackgroundRect(xCoord, gsVIEWPORT_END_Y, 102,( INT16 ) ( SCREEN_HEIGHT - gsVIEWPORT_END_Y ) );
for( sCounter = 0; sCounter < NUMBER_OF_SQUADS; sCounter++ )
{
+6
View File
@@ -1009,6 +1009,12 @@ BOOLEAN UpdateVideoOverlay( VIDEO_OVERLAY_DESC *pTopmostDesc, UINT32 iBlitterInd
}
}
if ( uiFlags & VOVERLAY_DESC_FONT )
{
gVideoOverlays[iBlitterIndex].uiFontID = pTopmostDesc->uiFontID;
gVideoOverlays[iBlitterIndex].ubFontBack = pTopmostDesc->ubFontBack;
gVideoOverlays[iBlitterIndex].ubFontFore = pTopmostDesc->ubFontFore;
}
if ( uiFlags & VOVERLAY_DESC_DISABLED )
{
+2 -1
View File
@@ -15,9 +15,10 @@
#define VOVERLAY_STARTDISABLED 0x00000002
#define VOVERLAY_DESC_TEXT 0x00001000
#define VOVERLAY_DESC_TEXT 0x00001000
#define VOVERLAY_DESC_DISABLED 0x00002000
#define VOVERLAY_DESC_POSITION 0x00004000
#define VOVERLAY_DESC_FONT 0x00008000
// STRUCTURES
+2 -2
View File
@@ -1914,10 +1914,10 @@ INT8 DamageStructure( STRUCTURE * pStructure, UINT8 ubDamage, UINT8 ubReason, IN
//Since the structure is being damaged, set the map element that a structure is damaged
gpWorldLevelData[ tmpgridno ].uiFlags |= MAPELEMENT_STRUCTURE_DAMAGED;
// handle structure revenge - damage to vehicle
// handle structure revenge - damage to vehicle - to be resolved after movement
if ( ubOwner != NOBODY && MercPtrs[ubOwner] && !ARMED_VEHICLE( MercPtrs[ubOwner] ) )
{
MercPtrs[ ubOwner ]->SoldierTakeDamage( 0, Random(max(0,(ubBaseArmour-10)/5))+max(0,(ubBaseArmour-10)/5), 0, TAKE_DAMAGE_STRUCTURE_EXPLOSION, NOBODY, MercPtrs[ ubOwner ]->sGridNo, 0, TRUE );
MercPtrs[ubOwner]->SoldierTakeDelayedDamage(0, Random(max(0,(ubBaseArmour-10)/5)) + max(0,(ubBaseArmour-10)/5), 0, TAKE_DAMAGE_STRUCTURE_EXPLOSION, NOBODY, MercPtrs[ ubOwner ]->sGridNo, 0, TRUE);
}
// recompile = TRUE means that we destroyed something
+40 -17
View File
@@ -14,6 +14,7 @@
#include "WordWrap.h"
#include "Message.h"
#include "Text.h"
#include "Loading Screen.h"
double rStart, rEnd;
double rActual;
@@ -63,10 +64,31 @@ void CreateLoadingScreenProgressBar(BOOLEAN resetLoadScreenHint)
// CreateProgressBar(0, 259 + ((SCREEN_WIDTH - 1024) / 2), 683 + ((SCREEN_HEIGHT - 768) / 2), 767 + ((SCREEN_WIDTH - 1024) / 2), 708 + ((SCREEN_HEIGHT - 768) / 2));
// }
//}
CreateProgressBar(0, SCREEN_WIDTH*162/640, SCREEN_HEIGHT*427/480, SCREEN_WIDTH*480/640, SCREEN_HEIGHT*443/480);
FLOAT fScreenAspectRatio = (FLOAT)SCREEN_WIDTH / (FLOAT)SCREEN_HEIGHT;
if (gGameExternalOptions.ubLoadscreenStretchMode == 1 ||
(gGameExternalOptions.ubLoadscreenStretchMode == 2 && fLoadingScreenAspectRatio > fScreenAspectRatio))
{
// match height, preserve aspect ratioernalOptions.ubLoadscreenStretchMode == 2 && fLoadingScreenAspectRatio > fScreenAspectRatio))
INT32 iCalculatedWidth = (INT32)(SCREEN_HEIGHT * fLoadingScreenAspectRatio + 0.5f);
UINT16 usLeft = (UINT16)((SCREEN_WIDTH - iCalculatedWidth) / 2 + (iCalculatedWidth * 162.0f / 640.0f) + 0.5f);
UINT16 usTop = (UINT16)((SCREEN_HEIGHT * 427.0f / 480.0f) + 0.5f);
UINT16 usRight = (UINT16)((SCREEN_WIDTH - iCalculatedWidth) / 2 + (iCalculatedWidth * 478.0f / 640.0f) + 0.5f);
UINT16 usBottom = (UINT16)((SCREEN_HEIGHT * 443.0f / 480.0f) + 0.5f);
CreateProgressBar(0, usLeft, usTop, usRight, usBottom);
}
else
{
UINT16 usLeft = (UINT16)((SCREEN_WIDTH * 162.0f / 640.0f) + 0.5f);
UINT16 usTop = (UINT16)((SCREEN_HEIGHT * 427.0f / 480.0f) + 0.5f);
UINT16 usRight = (UINT16)((SCREEN_WIDTH * 478.0f / 640.0f) + 0.5f);
UINT16 usBottom = (UINT16)((SCREEN_HEIGHT * 443.0f / 480.0f) + 0.5f);
CreateProgressBar(0, usLeft, usTop, usRight, usBottom);
}
SetProgressBarUseBorder(0, FALSE );
}
@@ -334,6 +356,8 @@ void SetRelativeStartAndEndPercentage( UINT8 ubID, UINT16 uiRelStartPerc, UINT16
pCurr->rStart = (double)uiRelStartPerc*0.01f;
pCurr->rEnd = (double)uiRelEndPerc*0.01f;
UINT8 yTextOffset = (UINT8)(3.0f * SCREEN_HEIGHT / 480.0f + 0.5f);
//Render the entire panel now, as it doesn't need update during the normal rendering
if( pCurr->fPanel )
{
@@ -352,7 +376,7 @@ void SetRelativeStartAndEndPercentage( UINT8 ubID, UINT16 uiRelStartPerc, UINT16
usStartX = pCurr->usPanelLeft + // left position
(pCurr->usPanelRight - pCurr->usPanelLeft)/2 - // + half width
StringPixLength( pCurr->swzTitle, pCurr->usTitleFont ) / 2; // - half string width
usStartY = pCurr->usPanelTop + 3;
usStartY = pCurr->usPanelTop + yTextOffset;
SetFont( pCurr->usTitleFont );
SetFontForeground( pCurr->ubTitleFontForeColor );
SetFontShadow( pCurr->ubTitleFontShadowColor );
@@ -370,21 +394,21 @@ void SetRelativeStartAndEndPercentage( UINT8 ubID, UINT16 uiRelStartPerc, UINT16
{
UINT16 usFontHeight = GetFontHeight( pCurr->usMsgFont );
RestoreExternBackgroundRect( pCurr->usBarLeft, pCurr->usBarBottom, (INT16)(pCurr->usBarRight-pCurr->usBarLeft), (INT16)(usFontHeight + 3) );
RestoreExternBackgroundRect( pCurr->usBarLeft, pCurr->usBarBottom, (INT16)(pCurr->usBarRight-pCurr->usBarLeft), (INT16)(usFontHeight + yTextOffset) );
}
SetFont( pCurr->usMsgFont );
SetFontForeground( pCurr->ubMsgFontForeColor );
SetFontShadow( pCurr->ubMsgFontShadowColor );
SetFontBackground( 0 );
mprintf( pCurr->usBarLeft, pCurr->usBarBottom + 3, str );
mprintf( pCurr->usBarLeft, pCurr->usBarBottom + yTextOffset, str );
}
}
// Flugente: loadscreen hints
if (gGameExternalOptions.gfUseLoadScreenHints && usCurrentLoadScreenHint )
{
ShowLoadScreenHintInLoadScreen(pCurr->usBarBottom + 3 - 100);
ShowLoadScreenHintInLoadScreen(pCurr->usBarBottom + yTextOffset - 100);
}
}
@@ -408,25 +432,24 @@ void RenderProgressBar( UINT8 ubID, UINT32 uiPercentage )
if( pCurr )
{
rActual = pCurr->rStart+(pCurr->rEnd-pCurr->rStart)*uiPercentage*0.01;
rActual = pCurr->rStart + (pCurr->rEnd - pCurr->rStart) * uiPercentage * 0.01;
if( fabs(rActual - pCurr->rLastActual) < 0.01 )
pCurr->rLastActual = (DOUBLE)((INT32)(std::round(rActual * 100)) * 0.01);
end = (INT32)(pCurr->usBarLeft + std::round(rActual * (pCurr->usBarRight - pCurr->usBarLeft)));
if (end < pCurr->usBarLeft)
{
return;
end = pCurr->usBarLeft;
}
pCurr->rLastActual = ( DOUBLE )( ( INT32)( rActual * 100 ) * 0.01 );
end = (INT32)(pCurr->usBarLeft+2.0+rActual*(pCurr->usBarRight-pCurr->usBarLeft-4));
if( end < pCurr->usBarLeft+2 || end > pCurr->usBarRight-2 )
else if (end > pCurr->usBarRight)
{
return;
end = pCurr->usBarRight;
}
if( !pCurr->fDrawBorder )
{
ColorFillVideoSurfaceArea( pCurr->uiFrameBuffer, //FRAME_BUFFER,
pCurr->usBarLeft, pCurr->usBarTop, end, pCurr->usBarBottom,
Get16BPPColor(FROMRGB( pCurr->ubColorFillRed, pCurr->ubColorFillGreen, pCurr->ubColorFillBlue )) );
Get16BPPColor(FROMRGB(pCurr->ubColorFillRed, pCurr->ubColorFillGreen, pCurr->ubColorFillBlue)));
//if( pCurr->usBarRight > gusLeftmostShaded )
//{
// ShadowVideoSurfaceRect( FRAME_BUFFER, gusLeftmostShaded+1, pCurr->usBarTop, end, pCurr->usBarBottom );
@@ -493,7 +516,7 @@ void SetProgressBarTextDisplayFlag( UINT8 ubID, BOOLEAN fDisplayText, BOOLEAN fU
//if we are to use the save buffer, blit the portion of the screen to the save buffer
if( fSaveScreenToFrameBuffer )
{
UINT16 usFontHeight = GetFontHeight( pCurr->usMsgFont )+3;
UINT16 usFontHeight = GetFontHeight(pCurr->usMsgFont) + (UINT8)(3.0f * SCREEN_HEIGHT / 480.f + 0.5f);
//blit everything to the save buffer ( cause the save buffer can bleed through )
BlitBufferToBuffer(guiRENDERBUFFER, guiSAVEBUFFER, pCurr->usBarLeft, pCurr->usBarBottom, (UINT16)(pCurr->usBarRight-pCurr->usBarLeft), usFontHeight );
+2
View File
@@ -231,6 +231,7 @@ BOOLEAN InitializeFonts( )
if ( iUseWinFonts ) {
InitWinFonts( );
}
InitTooltipFonts();
return( TRUE );
}
@@ -261,6 +262,7 @@ void ShutdownFonts( )
if ( iUseWinFonts ) {
ShutdownWinFonts();
}
ShutdownTooltipFonts();
}
// Set shades for fonts
+36
View File
@@ -76,6 +76,15 @@ BOOLEAN GetMLGFilename( SGPFILENAME filename, UINT16 usMLGGraphicID )
case MLG_PREBATTLEPANEL:
sprintf( filename, "INTERFACE\\PreBattlePanel.sti" );
return TRUE;
case MLG_PREBATTLEPANEL_800x600:
sprintf(filename, "INTERFACE\\PreBattlePanel_800x600.sti");
return TRUE;
case MLG_PREBATTLEPANEL_1024x768:
sprintf(filename, "INTERFACE\\PreBattlePanel_1024x768.sti");
return TRUE;
case MLG_PREBATTLEPANEL_1280x720:
sprintf(filename, "INTERFACE\\PreBattlePanel_1280x720.sti");
return TRUE;
case MLG_SMALLTITLE:
sprintf( filename, "LAPTOP\\SmallTitle.sti" );
return TRUE;
@@ -203,6 +212,15 @@ BOOLEAN GetMLGFilename( SGPFILENAME filename, UINT16 usMLGGraphicID )
case MLG_PREBATTLEPANEL:
sprintf( filename, "GERMAN\\PreBattlePanel_german.sti" );
return TRUE;
case MLG_PREBATTLEPANEL_800x600:
sprintf(filename, "GERMAN\\PreBattlePanel_800x600_german.sti");
return TRUE;
case MLG_PREBATTLEPANEL_1024x768:
sprintf(filename, "GERMAN\\PreBattlePanel_1024x768_german.sti");
return TRUE;
case MLG_PREBATTLEPANEL_1280x720:
sprintf(filename, "GERMAN\\PreBattlePanel_1280x720_german.sti");
return TRUE;
case MLG_SMALLTITLE:
sprintf( filename, "GERMAN\\SmallTitle_german.sti" );
return TRUE;
@@ -368,6 +386,15 @@ BOOLEAN GetMLGFilename( SGPFILENAME filename, UINT16 usMLGGraphicID )
case MLG_PREBATTLEPANEL:
sprintf( filename, "%s\\PreBattlePanel_%s.sti", zLanguage, zLanguage );
break;
case MLG_PREBATTLEPANEL_800x600:
sprintf(filename, "%s\\PreBattlePanel_800x600_%s.sti", zLanguage, zLanguage);
break;
case MLG_PREBATTLEPANEL_1024x768:
sprintf(filename, "%s\\PreBattlePanel_1024x768_%s.sti", zLanguage, zLanguage);
break;
case MLG_PREBATTLEPANEL_1280x720:
sprintf(filename, "%s\\PreBattlePanel_1280x720_%s.sti", zLanguage, zLanguage);
break;
case MLG_SMALLTITLE:
sprintf( filename, "%s\\SmallTitle_%s.sti", zLanguage, zLanguage );
break;
@@ -492,6 +519,15 @@ BOOLEAN GetMLGFilename( SGPFILENAME filename, UINT16 usMLGGraphicID )
case MLG_PREBATTLEPANEL:
sprintf( filename, "INTERFACE\\PreBattlePanel.sti" );
return TRUE;
case MLG_PREBATTLEPANEL_800x600:
sprintf(filename, "INTERFACE\\PreBattlePanel_800x600.sti");
return TRUE;
case MLG_PREBATTLEPANEL_1024x768:
sprintf(filename, "INTERFACE\\PreBattlePanel_1024x768.sti");
return TRUE;
case MLG_PREBATTLEPANEL_1280x720:
sprintf(filename, "INTERFACE\\PreBattlePanel_1280x720.sti");
return TRUE;
case MLG_SMALLTITLE:
sprintf( filename, "LAPTOP\\SmallTitle.sti" );
return TRUE;
+3
View File
@@ -26,6 +26,9 @@ enum
MLG_OPTIONHEADER, //OptionScreenAddOns
MLG_ORDERGRID,
MLG_PREBATTLEPANEL,
MLG_PREBATTLEPANEL_800x600,
MLG_PREBATTLEPANEL_1024x768,
MLG_PREBATTLEPANEL_1280x720,
MLG_SECTORINVENTORY,
MLG_SMALLFLORISTSYMBOL, //SmallSymbol
MLG_SMALLTITLE,
+32
View File
@@ -1912,6 +1912,8 @@ enum
STR_PB_ZOMBIE,
STR_PB_BANDIT,
STR_PB_BANDIT_KILLCIVS_IN_SECTOR,
STR_PB_TRANSPORT_GROUP,
STR_PB_TRANSPORT_GROUP_EN_ROUTE,
TEXT_NUM_STRATEGIC_TEXT
};
@@ -3082,6 +3084,36 @@ extern STR16 szSMilitiaResourceText[];
extern STR16 szInteractiveActionText[];
extern STR16 szLaptopStatText[];
enum
{
LAPTOP_STAT_TEXT_THREATEN_EFFECTIVENESS,
LAPTOP_STAT_TEXT_LEADERSHIP,
LAPTOP_STAT_TEXT_APPROACH_MODIFIER,
LAPTOP_STAT_TEXT_BACKGROUND_MODIFIER,
LAPTOP_STAT_TEXT_ASSERTIVE,
LAPTOP_STAT_TEXT_MALICIOUS,
LAPTOP_STAT_TEXT_GOOD_GUY,
LAPTOP_STAT_TEXT_REFUSES_TO_ATTACK_NON_HOSTILES,
LAPTOP_STAT_TEXT_FRIENDLY_APPROACH,
LAPTOP_STAT_TEXT_DIRECT_APPROACH,
LAPTOP_STAT_TEXT_THREATEN_APPROACH,
LAPTOP_STAT_TEXT_RECRUIT_APPROACH,
LAPTOP_STAT_TEXT_MERC_REGRESSES,
LAPTOP_STAT_TEXT_FAST,
LAPTOP_STAT_TEXT_AVERAGE,
LAPTOP_STAT_TEXT_SLOW,
LAPTOP_STAT_TEXT_HEALTH_SPEED,
LAPTOP_STAT_TEXT_STRENGTH_SPEED,
LAPTOP_STAT_TEXT_AGILITY_SPEED,
LAPTOP_STAT_TEXT_DEXTERITY_SPEED,
LAPTOP_STAT_TEXT_WISDOM_SPEED,
LAPTOP_STAT_TEXT_MARKSMANSHIP_SPEED,
LAPTOP_STAT_TEXT_EXPLOSIVES_SPEED,
LAPTOP_STAT_TEXT_LEADERSHIP_SPEED,
LAPTOP_STAT_TEXT_MEDICAL_SPEED,
LAPTOP_STAT_TEXT_MECHANICAL_SPEED,
LAPTOP_STAT_TEXT_EXPERIENCE_SPEED,
};
// Flugente: gear templates
extern STR16 szGearTemplateText[];
+23 -8
View File
@@ -307,7 +307,9 @@ itemStartElementHandle(void *userData, const XML_Char *name, const XML_Char **at
strcmp(name, "ProvidesRobotNightVision") == 0 ||
strcmp(name, "ProvidesRobotLaserBonus") == 0 ||
strcmp(name, "FoodSystemExclusive") == 0 ||
strcmp(name, "DiseaseSystemExclusive") == 0
strcmp(name, "DiseaseSystemExclusive") == 0 ||
strcmp(name, "TransportGroupMinProgress") == 0 ||
strcmp(name, "TransportGroupMaxProgress") == 0
)
{
pData->curElement = ELEMENT_PROPERTY;
@@ -1505,26 +1507,36 @@ itemEndElementHandle(void *userData, const XML_Char *name)
}
else if (strcmp(name, "ProvidesRobotNightVision") == 0)
{
pData->curElement == ELEMENT;
pData->curElement = ELEMENT;
pData->curItem.fProvidesRobotNightVision = (BOOLEAN)atol(pData->szCharData);
}
else if (strcmp(name, "ProvidesRobotLaserBonus") == 0)
{
pData->curElement == ELEMENT;
pData->curElement = ELEMENT;
pData->curItem.fProvidesRobotLaserBonus = (BOOLEAN)atol(pData->szCharData);
}
else if (strcmp(name, "FoodSystemExclusive") == 0)
{
pData->curElement == ELEMENT;
pData->curElement = ELEMENT;
if (atol(pData->szCharData))
pData->curItem.usLimitedToSystem|= FOOD_SYSTEM_FLAG;
}
else if (strcmp(name, "DiseaseSystemExclusive") == 0)
{
pData->curElement == ELEMENT;
pData->curElement = ELEMENT;
if (atol(pData->szCharData))
pData->curItem.usLimitedToSystem|= DISEASE_SYSTEM_FLAG;
}
else if (strcmp(name, "TransportGroupMinProgress") == 0)
{
pData->curElement = ELEMENT;
pData->curItem.iTransportGroupMinProgress = (INT8)atoi(pData->szCharData);
}
else if (strcmp(name, "TransportGroupMaxProgress") == 0)
{
pData->curElement = ELEMENT;
pData->curItem.iTransportGroupMaxProgress = (INT8)atoi(pData->szCharData);
}
--pData->maxReadDepth;
}
@@ -1588,9 +1600,12 @@ BOOLEAN ReadInItemStats(STR fileName, BOOLEAN localizedVersion )
MemFree(lpcBuffer);
return FALSE;
}
// item read was x -> x+1 items
++gMAXITEMS_READ;
if (localizedTextOnly == false)
{
// item read was x -> x+1 items
++gMAXITEMS_READ;
}
MemFree(lpcBuffer);
+22 -7
View File
@@ -3568,6 +3568,8 @@ STR16 gpStrategicString[] =
L"僵尸", //L"Zombie",
L"土匪", //L"Bandit",
L"土匪杀死了%d名平民,在%s分区。", //注:这里的%d和%s不可以随意放前面或后面,一定要按英文顺序,不然会出错。(%d和%s 在中文中不能反过来。) L"Bandits attack and kill %d civilians in sector %s.",
L"Transport group",
L"Transport group en route",
};
STR16 gpGameClockString[] =
@@ -6262,6 +6264,7 @@ STR16 z113FeaturesToggleText[] =
L"天气功能:暴风雪", //L"Weather: Snow",
L"随机事件功能", //L"Mini Events",
L"反抗军司令部功能", //L"Arulco Rebel Command",
L"Strategic Transport Groups",
};
STR16 z113FeaturesHelpText[] =
@@ -6309,6 +6312,7 @@ STR16 z113FeaturesHelpText[] =
L"|天|气|功|能||暴|风|雪\n \n覆盖 [Tactical Weather Settings] ALLOW_SNOW\n \n暴风雪降低了能见度。\n \n配置选项:\nSNOW_EVENTS_PER_DAY\nSNOW_CHANCE_PER_DAY\nSNOW_MIN_LENGTH_IN_MINUTES\nSNOW_MAX_LENGTH_IN_MINUTES\nWEAPON_RELIABILITY_REDUCTION_SNOW\nBREATH_GAIN_REDUCTION_SNOW\nVISUAL_DISTANCE_DECREASE_SNOW\nHEARING_REDUCTION_SNOW\n \n", //L"|W|e|a|t|h|e|r|: |S|n|o|w\nOverrides [Tactical Weather Settings] ALLOW_SNOW\n \nSnowstorms decrease visibility.\n \nConfigurable Options:\nSNOW_EVENTS_PER_DAY\nSNOW_CHANCE_PER_DAY\nSNOW_MIN_LENGTH_IN_MINUTES\nSNOW_MAX_LENGTH_IN_MINUTES\nWEAPON_RELIABILITY_REDUCTION_SNOW\nBREATH_GAIN_REDUCTION_SNOW\nVISUAL_DISTANCE_DECREASE_SNOW\nHEARING_REDUCTION_SNOW",
L"|随|机|事|件|功|能\n \n覆盖 [Mini Events Settings] MINI_EVENTS_ENABLED\n \n可能发生一些随机互动事件。\n \n配置选项:\nMINI_EVENTS_MIN_HOURS_BETWEEN_EVENTS\nMINI_EVENTS_MAX_HOURS_BETWEEN_EVENTS\n \n详细信息请查看MiniEvents.lua。\n \n", //L"|M|i|n|i |E|v|e|n|t|s\nOverrides [Mini Events Settings] MINI_EVENTS_ENABLED\n \nRandom events can occur.\n \nConfigurable Options:\nMINI_EVENTS_MIN_HOURS_BETWEEN_EVENTS\nMINI_EVENTS_MAX_HOURS_BETWEEN_EVENTS\n \nSee MiniEvents.lua for more details.",
L"|反|抗|军|司|令|部|功|能\n \n覆盖 [Rebel Command Settings] REBEL_COMMAND_ENABLED\n \n允许你升级占领的城镇,控制反抗军在战略层面上运作。\n \n详细的内容设定请查看RebelCommand_Settings.ini。\n \n", //L"|A|R|C\nOverrides [Rebel Command Settings] REBEL_COMMAND_ENABLED\n \nCommand the rebel movement at the strategic level, and upgrade captured towns.\n \nFor tweakable values, see RebelCommand_Settings.ini.",
L"|S|t|r|a|t|e|g|i|c |T|r|a|n|s|p|o|r|t |G|r|o|u|p|s\nOverrides [Strategic Gameplay Settings] STRATEGIC_TRANSPORT_GROUPS_ENABLED\n \nTransport groups carry valuable equipment across the map.\n \nConfigurable Options:\nMAX_SIMULTANEOUS_STRATEGIC_TRANSPORT_GROUPS",
};
STR16 z113FeaturesPanelText[] =
@@ -6356,6 +6360,7 @@ STR16 z113FeaturesPanelText[] =
L"启用暴风雪功能。在暴风雪中,更难被看到,武器退化更快,呼吸也更困难。", //L"Toggle snow. In a snowstorm, it is harder to see, weapons degrade faster, and it is a little harder to regain breath.",
L"在游戏过程中,可能会弹出简短的事件。您可以从两个选项中选择一个,这可能会产生积极或消极的影响。事件可以影响各种各样的事情,但主要是你的佣兵。", //L"During the course of a campaign, brief events can pop up. You can select one of two responses, which may have positive and/or negative effects. Events can affect a wide variety of things, but mostly your mercs.",
L"在完成反抗军食物运送任务后,你可以访问他们的(A.R.C)指挥部网站。在这里你可以设定反抗军的政策,也可以为占领区单独设置地方政策。这将带来丰厚的奖励。作为代价,城镇的民忠会上升得更慢,所以你需要更加努力地让当地人信任你。", //L"After completing the food delivery quest for the rebels, they will grant you access to their command website (A.R.C.). You can set the rebels' country-wide directive there, and capturing towns allows you to enact policies in that region that provide powerful bonuses. This comes at a price - town loyalty will rise slower, so you will need to work harder to have the locals trust you.",
L"The enemy sends groups across the map. If you can find and intercept them, they will probably have valuable gear. However, depending on your difficulty, each group that completes its transport mission provides the AI with strategic resources. Best experienced with Arulco Strategic Division enabled.",
};
@@ -11650,13 +11655,21 @@ STR16 szLaptopStatText[] =
L"威胁对话", //L"Threaten approach",
L"招募对话", //L"Recruit approach",
L"%s正以正常速度学习。", //L"%s learns with normal speed.",
L"%s根本没有在学习。", //L"%s does not learn at all.",
L"%s遗忘了技能。", //L"%s unlearns his skills.",
L"%s正以3/4的速度学习。", //L"%s learns with 3/4 speed.",
L"%s正以1/2的速度学习。", //L"%s learns with 1/2 speed.",
L"%s正以1/4的速度学习。", //L"%s learns with 1/4 speed.",
L"Stats will regress.",
L"Fast",
L"Average",
L"Slow",
L"Health growth",
L"Strength growth",
L"Agility growth",
L"Dexterity growth",
L"Wisdom growth",
L"Marksmanship growth",
L"Explosives growth",
L"Leadership growth",
L"Medical growth",
L"Mechanical growth",
L"Experience growth",
};
STR16 szGearTemplateText[] =
@@ -12098,6 +12111,8 @@ STR16 szRebelCommandAgentMissionsText[] =
L"协同行动,悄悄地抵进敌军,但是要小心:这可能会让你部署在劣势区域。当进攻敌军部队时,部署区会更大。", //L"Coordinate efforts to find ways to sneak up on the enemy, but be careful: it's equally possible to put yourself in a disadvantaged deployment area. When attacking enemy forces, the deployment area is much larger.",
L"扰乱ASD", //L"Disrupt ASD",
L"破坏Arulco特种部门(ASD)的日常行动。临时阻止ASD部署更多的机械化单位,并且大幅度降低他们的每日收入。", //L"Wreak havoc on the day-to-day operations of the Arulco Special Division. Temporarily prevent the ASD from deploying additional mechanised units, and drastically reduce their daily income.",
L"Forge Transport Orders",
L"Create a bogus supply request. An enemy transport group will be ordered to rendezvous at this agent's location.",
L"战略情报", //L"Strategic Intel",
L"侦听敌人,发现敌军的攻击目标。当在战略地图上观察队伍时,敌军优先进攻的目标区域会被标红。", //L"Intercept plans and discover where enemies intend to strike. When viewing teams on the strategic map, sectors prioritised by the enemy will be marked in red.",
L"强化本地商店", //L"Improve Local Shops",
+22 -7
View File
@@ -3568,6 +3568,8 @@ STR16 gpStrategicString[] =
L"Zombie",
L"Bandit",
L"Bandits attack and kill %d civilians in sector %s.",
L"Transport group",
L"Transport group en route",
};
STR16 gpGameClockString[] =
@@ -6265,6 +6267,7 @@ STR16 z113FeaturesToggleText[] =
L"Weather: Snow",
L"Mini Events",
L"Arulco Rebel Command",
L"Strategic Transport Groups",
};
STR16 z113FeaturesHelpText[] =
@@ -6312,6 +6315,7 @@ STR16 z113FeaturesHelpText[] =
L"|W|e|a|t|h|e|r|: |S|n|o|w\nOverrides [Tactical Weather Settings] ALLOW_SNOW\n \nSnowstorms decrease visibility.\n \nConfigurable Options:\nSNOW_EVENTS_PER_DAY\nSNOW_CHANCE_PER_DAY\nSNOW_MIN_LENGTH_IN_MINUTES\nSNOW_MAX_LENGTH_IN_MINUTES\nWEAPON_RELIABILITY_REDUCTION_SNOW\nBREATH_GAIN_REDUCTION_SNOW\nVISUAL_DISTANCE_DECREASE_SNOW\nHEARING_REDUCTION_SNOW",
L"|M|i|n|i |E|v|e|n|t|s\nOverrides [Mini Events Settings] MINI_EVENTS_ENABLED\n \nRandom events can occur.\n \nConfigurable Options:\nMINI_EVENTS_MIN_HOURS_BETWEEN_EVENTS\nMINI_EVENTS_MAX_HOURS_BETWEEN_EVENTS\n \nSee MiniEvents.lua for more details.",
L"|A|R|C\nOverrides [Rebel Command Settings] REBEL_COMMAND_ENABLED\n \nCommand the rebel movement at the strategic level, and upgrade captured towns.\n \nFor tweakable values, see RebelCommand_Settings.ini.",
L"|S|t|r|a|t|e|g|i|c |T|r|a|n|s|p|o|r|t |G|r|o|u|p|s\nOverrides [Strategic Gameplay Settings] STRATEGIC_TRANSPORT_GROUPS_ENABLED\n \nTransport groups carry valuable equipment across the map.\n \nConfigurable Options:\nMAX_SIMULTANEOUS_STRATEGIC_TRANSPORT_GROUPS",
};
STR16 z113FeaturesPanelText[] =
@@ -6359,6 +6363,7 @@ STR16 z113FeaturesPanelText[] =
L"Toggle snow. In a snowstorm, it is harder to see, weapons degrade faster, and it is a little harder to regain breath.",
L"During the course of a campaign, brief events can pop up. You can select one of two responses, which may have positive and/or negative effects. Events can affect a wide variety of things, but mostly your mercs.",
L"After completing the food delivery quest for the rebels, they will grant you access to their command website (A.R.C.). You can set the rebels' country-wide directive there, and capturing towns allows you to enact policies in that region that provide powerful bonuses. This comes at a price - town loyalty will rise slower, so you will need to work harder to have the locals trust you.",
L"The enemy sends groups across the map. If you can find and intercept them, they will probably have valuable gear. However, depending on your difficulty, each group that completes its transport mission provides the AI with strategic resources. Best experienced with Arulco Strategic Division enabled.",
};
@@ -11659,13 +11664,21 @@ STR16 szLaptopStatText[] = // TODO.Translate
L"Threaten approach",
L"Recruit approach",
L"%s learns with normal speed.", // TODO.Translate
L"%s does not learn at all.",
L"%s unlearns his skills.",
L"%s learns with 3/4 speed.",
L"%s learns with 1/2 speed.",
L"%s learns with 1/4 speed.",
L"Stats will regress.",
L"Fast",
L"Average",
L"Slow",
L"Health growth",
L"Strength growth",
L"Agility growth",
L"Dexterity growth",
L"Wisdom growth",
L"Marksmanship growth",
L"Explosives growth",
L"Leadership growth",
L"Medical growth",
L"Mechanical growth",
L"Experience growth",
};
STR16 szGearTemplateText[] = // TODO.Translate
@@ -12108,6 +12121,8 @@ STR16 szRebelCommandAgentMissionsText[] =
L"Coordinate efforts to find ways to sneak up on the enemy, but be careful: it's equally possible to put yourself in a disadvantaged deployment area. When attacking enemy forces, the deployment area is much larger.",
L"Disrupt ASD",
L"Wreak havoc on the day-to-day operations of the Arulco Special Division. Temporarily prevent the ASD from deploying additional mechanised units, and drastically reduce their daily income.",
L"Forge Transport Orders",
L"Create a bogus supply request. An enemy transport group will be ordered to rendezvous at this agent's location.",
L"Strategic Intel",
L"Intercept plans and discover where enemies intend to strike. When viewing teams on the strategic map, sectors prioritised by the enemy will be marked in red.",
L"Improve Local Shops",
+22 -7
View File
@@ -3568,6 +3568,8 @@ STR16 gpStrategicString[] =
L"Zombie",
L"Bandit",
L"Bandits attack and kill %d civilians in sector %s.",
L"Transport group",
L"Transport group en route",
};
STR16 gpGameClockString[] =
@@ -6262,6 +6264,7 @@ STR16 z113FeaturesToggleText[] =
L"Weather: Snow",
L"Mini Events",
L"Arulco Rebel Command",
L"Strategic Transport Groups",
};
STR16 z113FeaturesHelpText[] =
@@ -6309,6 +6312,7 @@ STR16 z113FeaturesHelpText[] =
L"|W|e|a|t|h|e|r|: |S|n|o|w\nOverrides [Tactical Weather Settings] ALLOW_SNOW\n \nSnowstorms decrease visibility.\n \nConfigurable Options:\nSNOW_EVENTS_PER_DAY\nSNOW_CHANCE_PER_DAY\nSNOW_MIN_LENGTH_IN_MINUTES\nSNOW_MAX_LENGTH_IN_MINUTES\nWEAPON_RELIABILITY_REDUCTION_SNOW\nBREATH_GAIN_REDUCTION_SNOW\nVISUAL_DISTANCE_DECREASE_SNOW\nHEARING_REDUCTION_SNOW",
L"|M|i|n|i |E|v|e|n|t|s\nOverrides [Mini Events Settings] MINI_EVENTS_ENABLED\n \nRandom events can occur.\n \nConfigurable Options:\nMINI_EVENTS_MIN_HOURS_BETWEEN_EVENTS\nMINI_EVENTS_MAX_HOURS_BETWEEN_EVENTS\n \nSee MiniEvents.lua for more details.",
L"|A|R|C\nOverrides [Rebel Command Settings] REBEL_COMMAND_ENABLED\n \nCommand the rebel movement at the strategic level, and upgrade captured towns.\n \nFor tweakable values, see RebelCommand_Settings.ini.",
L"|S|t|r|a|t|e|g|i|c |T|r|a|n|s|p|o|r|t |G|r|o|u|p|s\nOverrides [Strategic Gameplay Settings] STRATEGIC_TRANSPORT_GROUPS_ENABLED\n \nTransport groups carry valuable equipment across the map.\n \nConfigurable Options:\nMAX_SIMULTANEOUS_STRATEGIC_TRANSPORT_GROUPS",
};
STR16 z113FeaturesPanelText[] =
@@ -6356,6 +6360,7 @@ STR16 z113FeaturesPanelText[] =
L"Toggle snow. In a snowstorm, it is harder to see, weapons degrade faster, and it is a little harder to regain breath.",
L"During the course of a campaign, brief events can pop up. You can select one of two responses, which may have positive and/or negative effects. Events can affect a wide variety of things, but mostly your mercs.",
L"After completing the food delivery quest for the rebels, they will grant you access to their command website (A.R.C.). You can set the rebels' country-wide directive there, and capturing towns allows you to enact policies in that region that provide powerful bonuses. This comes at a price - town loyalty will rise slower, so you will need to work harder to have the locals trust you.",
L"The enemy sends groups across the map. If you can find and intercept them, they will probably have valuable gear. However, depending on your difficulty, each group that completes its transport mission provides the AI with strategic resources. Best experienced with Arulco Strategic Division enabled.",
};
@@ -11650,13 +11655,21 @@ STR16 szLaptopStatText[] =
L"Threaten approach",
L"Recruit approach",
L"%s learns with normal speed.",
L"%s does not learn at all.",
L"%s unlearns his skills.",
L"%s learns with 3/4 speed.",
L"%s learns with 1/2 speed.",
L"%s learns with 1/4 speed.",
L"Stats will regress.",
L"Fast",
L"Average",
L"Slow",
L"Health growth",
L"Strength growth",
L"Agility growth",
L"Dexterity growth",
L"Wisdom growth",
L"Marksmanship growth",
L"Explosives growth",
L"Leadership growth",
L"Medical growth",
L"Mechanical growth",
L"Experience growth",
};
STR16 szGearTemplateText[] =
@@ -12098,6 +12111,8 @@ STR16 szRebelCommandAgentMissionsText[] =
L"Coordinate efforts to find ways to sneak up on the enemy, but be careful: it's equally possible to put yourself in a disadvantaged deployment area. When attacking enemy forces, the deployment area is much larger.",
L"Disrupt ASD",
L"Wreak havoc on the day-to-day operations of the Arulco Special Division. Temporarily prevent the ASD from deploying additional mechanised units, and drastically reduce their daily income.",
L"Forge Transport Orders",
L"Create a bogus supply request. An enemy transport group will be ordered to rendezvous at this agent's location.",
L"Strategic Intel",
L"Intercept plans and discover where enemies intend to strike. When viewing teams on the strategic map, sectors prioritised by the enemy will be marked in red.",
L"Improve Local Shops",

Some files were not shown because too many files have changed in this diff Show More