Author SHA1 Message Date
Asdow 9353bf27a1 Revert "Make new kit selection respect TonsOfGuns & Scifi tags"
This reverts commit 69904ee003.
2026-06-19 21:58:41 +03:00
Asdow ef51b578c3 Discard items based on gamestyle 2026-06-19 21:58:27 +03:00
Asdow 69904ee003 Make new kit selection respect TonsOfGuns & Scifi tags 2026-06-19 10:10:48 +03:00
db29feed11 Don't strip robot's installed components on mapscreen drop-all
The mapscreen "drop everything" hotkey (Shift+W) looped over every
inventory slot from HELMETPOS to NUM_INV_SLOTS and dumped each one.
Madlab's robot stores its installed gear in those same slots - ammo (14),
targeting (15), chassis/armour (16) and utility (17). Dropping these left
the robot defenceless, and the player cannot re-install the components
through normal inventory, so the loss was permanent.

Skip the robot's component slots in the drop loop; only its general cargo
slot (ROBOT_INVENTORY_SLOT) may still be emptied. Regular mercs are
unaffected.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 23:06:33 +03:00
Asdow 1fc5f939bf Use new RandomGridNoUnloadedSector() for autoresolve
* Load required mapinfo for checking suitable gridnos
* Modify SOLDIERTYPE::DropSectorEquipment( ) to take an external gridno when placing items into an unloaded sector
2026-06-15 22:01:07 +03:00
Asdow 9e0105caec Add function for choosing random gridno in an unloaded sector 2026-06-15 22:01:07 +03:00
Asdow 0cc7fb4e39 Add function for loading world height data 2026-06-15 22:01:07 +03:00
Asdow db15679ec1 Add missing Iter->Exists() checks 2026-06-12 15:52:24 +03:00
Asdow 6a8a22aba2 Move iter->exists() check to first 2026-06-12 15:52:24 +03:00
Asdow 9b654ff3f1 Fix typo 2026-06-12 15:51:03 +03:00
Asdow a67f4b8a8f Formatting 2026-06-12 15:51:03 +03:00
Asdow 673dea01af Use correct sector for Chitzena 2026-06-12 15:51:03 +03:00
Marco Antonio J. Costaandmajcosta b44b6cebb8 Revert PR544
"Corpses are not properly shown even if within mercs' vision due to the check only
running intermittently since we're not constantly running the reveal roofs and items
function. In addition, mercs such as Raven who have the quoteexpheadshotonly set to true,
will NEVER reveal any corpses"

Revert "Remove extra line"

This reverts commit 1e1eb88864.

Revert "Move visibility check after already included pCorpse check"

This reverts commit 72e586a378.

Revert "Make 3rd party corpses invisible till they in fov"

This reverts commit 07dbf9c848.
2026-06-02 19:17:31 -03:00
Asdow 8bc3dbd0aa Prevent RebelCommand::DailyUpdate() from running twice when loading autosave 2026-06-02 23:59:30 +03:00
Marco Antonio J. Costaandmajcosta b4176bb2d9 Fix/drag unconscious softlock
Same logic but cleaned up version of https://github.com/1dot13/source/pull/602 which Tais contributed with Claude Code's help

Most calls to SOLDIERTYPE::IsDragging() aren't supposed to have a side effect of cancelling a drag, being simple queries.
Changing the default to reflect that is right move.

Assisted-by: Claude:
2026-06-01 21:45:55 -03:00
Asdow 8b3e417872 Guard against illegal array access
Hovering mouse over an option long enough that the popup text appears and scrolling to last page with mouse wheel would run into assertion error in gprintfdirty()  Assert(pFontString!=NULL); if the option was one of the last ones that didn't have a text box in the last option page.
2026-05-28 17:44:21 +03:00
AsdowandClaude Opus 4.7 b949189881 Fix palette resolution
The LayerProp palette lookup was gated on the *filter* attribute instead
of the *palette* attribute -- the filter checks from the line above were
copy-pasted verbatim. As a result, any LayerProp with an empty filter but
a real palette never resolved its palette table: paletteTable stayed NULL
and the layer fell back to the merc's shade table.

The most visible victim is the heli fast-rope arrival layer
(filter="" palette="hats"): rendered with the merc palette, the rope's
pixel indices (45-81, 166-172) hit the merc's unreplaced orange/red glow
ramp instead of the rope's own tan/green, painting orange specks along the
rope. Testing the palette attribute restores the intended "hats" palette
and the correct rope colours; it also fixes any other empty-filter layers.

Co-Authored-By: Claude Opus 4.7
2026-05-28 16:33:48 +03:00
JuqiandAsdow cc19490898 update Chinese translations 2026-05-25 08:37:30 +03:00
GreysaandAsdow 9fac0a8ecd Tidy up code 2026-05-23 21:22:28 +03:00
GreysaandAsdow 346e5c6293 fix for issue #580 2026-05-23 21:22:28 +03:00
GreysaandAsdow 0bea84374e fixed some screenmsg strings not changed 2026-05-23 21:22:28 +03:00
GreysaandAsdow 3d589bd78e A little code cleanup and moved debug reload to shift + alt + r 2026-05-23 21:22:28 +03:00
GreysaandAsdow e1c8bee1d1 Message strings added to language files. 2026-05-23 21:22:28 +03:00
GreysaandAsdow ead2932316 Added dual wielding unjamming, tidied up reload and unjam code a little 2026-05-23 21:22:28 +03:00
GreysaandAsdow bb55299ff6 Basic implementaion of unjamming on reload hotkey.
TODO:
text strings
check dual wielding
2026-05-23 21:22:28 +03:00
JuqiandAsdow 2d4f62a5b6 Correct two errors in the Chinese translation 2026-05-13 16:02:28 +03:00
Asdow 03a7b017b6 Change mouse cursor if attachment attempt fails 2026-05-06 23:23:07 +03:00
Asdow edf8f2f086 Fix crash when failing an attachment via item desc popup callback 2026-05-06 23:23:07 +03:00
Asdow 78ed49c73d Remove corpse structure from world when removing corpse
Fixes not being able to take all corpses from one tile, if multiple corpses were stacked on top of each other. With the structure not deleted, the  GetCorpseAtGridNo would not find an existing corpse anymore.
2026-05-06 11:28:11 +03:00
Asdow 5697acabb3 Take most recent corpse from tile
Fixes crash when taking a corpse on roof when multiple corpses are stacked on one tile.
2026-05-06 11:28:11 +03:00
Asdow 09197e421c Add a function for finding last matching structure 2026-05-06 11:28:11 +03:00
JuqiandAsdow 46afd90fdc Add Chinese translation 2026-05-04 12:10:10 +03:00
JuqiandAsdow 80ba0a05d7 Revert "Add Chinese translation"
This reverts commit e7d436d9fa.
2026-05-04 12:10:10 +03:00
JuqiandAsdow aab34bff20 Add Chinese translation 2026-05-04 12:10:10 +03:00
JuqiandAsdow ef325c1cde (Chinese) Add support for line breaks in ITEMS.XML
Added detection of the NEWLINE_CHAR character "±" to enable line breaks not only when text exceeds display width, but also upon encountering NEWLINE_CHAR.
Note: This character has been conventionally adopted in the Chinese community as a line break marker within XML item descriptions. The modification affects Chinese text display only.
2026-05-02 09:39:03 +03:00
Asdow 99a4ff1527 Guard against invalid value 2026-05-02 09:31:09 +03:00
Marco Antonio J. Costaandmajcosta f2d1b09fc6 add comment to CMakeLists.txt
save people a trip to learn.microsoft.com
2026-04-08 15:25:48 -03:00
Marco Antonio J. CostaandAsdow 31970291bd make preprocessor definitions consistent in every single lib
SGP did not seem to make any use of compilationFlags or debugFlags when
translating from msbuild to cmake, but there could be a thrice removed
transitive include I've missed.

there's a small probability this fixes some obscure UB or one-definition rule
violation that's causing the mystery crashes people have reported
2026-04-08 21:06:34 +03:00
GreysaandGitHub 0a758179c2 Advanced repairs skill check (#581)
* Add technician level skill check for advanced repair

* changed readability
2026-03-17 10:35:29 +01:00
noooooo4499andAsdow 481e95d42d Avoid breaking compatibility with gamedirs with old HourlyUpdate scripts
They are mapped to the right variable now
2026-02-25 10:47:47 +02:00
Asdow 8f178a59ab Add filename to error text for pngloader 2026-02-23 18:23:08 +02:00
Asdow a6d96f5f31 Remove compiler warnings 2026-02-21 21:00:38 +02:00
Asdow 67f41d4de6 Remove superfluous variable 2026-02-21 21:00:38 +02:00
Asdow 1d53b92731 Add const keyword 2026-02-21 21:00:38 +02:00
Asdow 42b2cbc7f5 add const keyword 2026-02-21 21:00:38 +02:00
Asdow 04ace5df24 add const keyword 2026-02-21 21:00:38 +02:00
Asdow 323944757d Improve DisplayCover() performance
* Replaced gCoverViewArea[2000][2000][2] with std::vector that is adjusted to the actual viewport size. Size difference for example in 720p resolution is 8 000 000 vs 3969 elements
* FPS improved in merc view mode 6-8 frames and in enemy view mode 10-20 frames
2026-02-21 21:00:38 +02:00
noooooo4499andAsdow 7d5a1c2e9e Remove useless lua gameclock variables, add lua externalized function to heal boxers
- These gameclock variables were not updated properly so it created a discrepancy between it and the proper gameclock variables, and it was causing issues with the lua hourly update script

- Function that heals boxers after they finish resting
2026-02-12 10:24:47 +02:00
noooooo4499andAsdow dc107f5044 Fix Darren sometimes never giving fights if the boxers's IDs aren't assigned 2026-02-07 12:03:03 +02:00
53 changed files with 1389 additions and 893 deletions
+2 -2
View File
@@ -27,7 +27,7 @@ if(ADDRESS_SANITIZER)
endif()
if(MSVC)
add_compile_options("/wd4838")
add_compile_options("/wd4838") # silence implicit narrowing conversion warnings
endif()
# whether we are using MSBuild as a generator
@@ -163,5 +163,5 @@ foreach(app IN LISTS ApplicationTargets)
# for SGP only
target_link_libraries(${app}_sgp PRIVATE "ddraw.lib" "${PROJECT_SOURCE_DIR}/fmodvc.lib")
target_link_libraries(${app}_sgp PRIVATE libpng)
target_compile_definitions(${app}_sgp PRIVATE NO_ZLIB_COMPRESSION)
target_compile_definitions(${app}_sgp PRIVATE ${compilationFlags} ${debugFlags} NO_ZLIB_COMPRESSION)
endforeach()
+1
View File
@@ -2749,6 +2749,7 @@ void LoadSkillTraitsExternalSettings()
gSkillTraitValues.ubTERepairRobotPenaltyReduction = iniReader.ReadInteger("Technician","REPAIR_SPEED_ROBOT_PENALTY_REDUCTION", 30, 0, 100);
if (gSkillTraitValues.ubTETraitsNumToRepairRobot == 2) {gSkillTraitValues.ubTERepairRobotPenaltyReduction /= 2; }
gSkillTraitValues.fTETraitsCanRestoreItemThreshold = iniReader.ReadBoolean( "Technician", "MERCS_CAN_DO_ADVANCED_REPAIRS", FALSE );
gSkillTraitValues.ubTechLevelNeededForAdvancedRepair = iniReader.ReadInteger("Technician", "TECH_LEVEL_NEEDED_FOR_ADVANCED_REPAIR", 2, 1, 2);
// DOCTOR
gSkillTraitValues.ubDONumberTraitsNeededForSurgery = iniReader.ReadInteger("Doctor","NUMBER_OF_TRAITS_NEEDED_FOR_SURGERY", 1, 0, 2);
+1
View File
@@ -2145,6 +2145,7 @@ typedef struct
UINT8 ubTERepairRobotPenaltyReduction;
UINT8 ubTETraitsNumToRepairRobot;
BOOLEAN fTETraitsCanRestoreItemThreshold;
UINT8 ubTechLevelNeededForAdvancedRepair; // if we have a high enough technician level, we can repair items above the normal threshold (1 for technician, 2 for engineer)
// DOCTOR
UINT8 ubDONumberTraitsNeededForSurgery;
+1 -1
View File
@@ -1822,7 +1822,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 )
{
+26
View File
@@ -1560,6 +1560,8 @@ BOOLEAN DisplayMercsInventory(UINT8 ubMercID)
CHAR16 gzItemName[ 5000 ];
UINT8 ubItemCount=0;
UINT8 ubColumnCount=0;
const bool realisticGameStyle = gGameOptions.ubGameStyle != STYLE_SCIFI;
const bool reducedGuns = gGameOptions.fGunNut == false;
//if the mercs inventory has already been purchased, dont display the inventory
if ( (gMercProfiles[ ubMercID ].ubMiscFlags & PROFILE_MISC_FLAG_ALREADY_USED_ITEMS) && !gGameExternalOptions.fGearKitsAlwaysAvailable )
@@ -1583,6 +1585,18 @@ BOOLEAN DisplayMercsInventory(UINT8 ubMercID)
{
usItem = gMercProfiles[ubMercID].inv[ i ];
if (realisticGameStyle && ItemIsOnlyInScifi(usItem))
{
gMercProfiles[ubMercID].inv[i] = 0;
continue;
}
if (reducedGuns && ItemIsOnlyInTonsOfGuns(usItem))
{
gMercProfiles[ubMercID].inv[i] = 0;
continue;
}
//if its a valid item AND we are only displaying less then 8 items
if( usItem && ubItemCount < WEAPONBOX_TOTAL_ITEMS )
{
@@ -1662,6 +1676,18 @@ BOOLEAN DisplayMercsInventory(UINT8 ubMercID)
{
usItem = gMercProfiles[ubMercID].inv[ i ];
if (realisticGameStyle && ItemIsOnlyInScifi(usItem))
{
gMercProfiles[ubMercID].inv[i] = 0;
continue;
}
if (reducedGuns && ItemIsOnlyInTonsOfGuns(usItem))
{
gMercProfiles[ubMercID].inv[i] = 0;
continue;
}
//if its a valid item AND we are only displaying less then 8 items
if( usItem && ubItemCount < WEAPONBOX_NUMBER )
{
+9 -4
View File
@@ -4948,7 +4948,7 @@ static void CollectRepairableItems(SOLDIERTYPE* pRepairSoldier, SOLDIERTYPE* pSo
// Check for attachments (are there stackable items that can take attachments though?)
UINT8 attachmentIndex = 0;
for (attachmentList::const_iterator iter = (*pObj)[stackIndex]->attachments.begin(); iter != (*pObj)[stackIndex]->attachments.end(); ++iter, ++attachmentIndex) {
if (IsItemRepairable(pRepairSoldier, iter->usItem, (*iter)[attachmentIndex]->data.objectStatus, (*iter)[attachmentIndex]->data.sRepairThreshold )) {
if ( iter->exists() && IsItemRepairable(pRepairSoldier, iter->usItem, (*iter)[attachmentIndex]->data.objectStatus, (*iter)[attachmentIndex]->data.sRepairThreshold )) {
// Send the main item, not the attachment
RepairItem item(pObj, pSoldier, (INVENTORY_SLOT) pocketIndex);
itemsToFix.push(item);
@@ -5081,7 +5081,7 @@ OBJECTTYPE* FindRepairableItemInSpecificPocket(SOLDIERTYPE * pSoldier, OBJECTTYP
// have to check for attachments after...
for (attachmentList::iterator iter = (*pObj)[subObject]->attachments.begin(); iter != (*pObj)[subObject]->attachments.end(); ++iter) {
// if it's repairable and NEEDS repairing
if ( IsItemRepairable( pSoldier, iter->usItem, (*iter)[subObject]->data.objectStatus, (*iter)[subObject]->data.sRepairThreshold ) && iter->exists() ) {
if ( iter->exists() && IsItemRepairable( pSoldier, iter->usItem, (*iter)[subObject]->data.objectStatus, (*iter)[subObject]->data.sRepairThreshold ) ) {
return( &(*iter) );
}
}
@@ -5171,8 +5171,12 @@ BOOLEAN RepairObject( SOLDIERTYPE * pSoldier, SOLDIERTYPE * pOwner, OBJECTTYPE *
INT16 threshold = 100;
if ( gGameExternalOptions.fAdvRepairSystem && (Item[pObj->usItem].usItemClass & (IC_WEAPON|IC_ARMOUR)) )
{
if ( !gSkillTraitValues.fTETraitsCanRestoreItemThreshold || !HAS_SKILL_TRAIT( pSoldier, TECHNICIAN_NT ) )
if (gSkillTraitValues.fTETraitsCanRestoreItemThreshold && NUM_SKILL_TRAITS(pSoldier, TECHNICIAN_NT) >= gSkillTraitValues.ubTechLevelNeededForAdvancedRepair) // Greysa: added skill check for advanced repair. If we have a high enough technician level, we can repair items above the normal threshold (1 for technician, 2 for engineer)
{
threshold = 100;
}
else
{
threshold = (*pObj)[ubLoop]->data.sRepairThreshold;
}
}
@@ -11085,7 +11089,8 @@ void DetermineWhichAssignmentMenusCanBeShown( void )
CreateDestroyMouseRegionForFacilityMenu();
CreateDestroyMouseRegionsForFacilityAssignmentMenu();
if( ( ( gCharactersList[ bSelectedInfoChar ].usSolID->stats.bLife == 0 )||( gCharactersList[bSelectedInfoChar].usSolID->bAssignment == ASSIGNMENT_POW ) ) && ( (guiTacticalInterfaceFlags & INTERFACE_MAPSCREEN ) ) )
const auto selectedCharacter = gCharactersList[bSelectedInfoChar].usSolID;
if( selectedCharacter < NOBODY && ( (selectedCharacter->stats.bLife == 0 )||(selectedCharacter->bAssignment == ASSIGNMENT_POW ) ) && ( (guiTacticalInterfaceFlags & INTERFACE_MAPSCREEN ) ) )
{
// show basic assignment menu
ShowBox( ghRemoveMercAssignBox );
+13 -5
View File
@@ -2481,6 +2481,12 @@ DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Autoresolve2");
DeleteVideoObjectFromIndex( gpAR->iIndent );
DeleteVideoSurfaceFromIndex( gpAR->iInterfaceBuffer );
// Load necessary mapinfo to place corpses
CHAR8 bFilename[50];
INT32 worldRows, worldCols;
GetMapFileName(gpAR->ubSectorX, gpAR->ubSectorY, 0, bFilename, TRUE, TRUE);
LoadWorldInfoForAutoResolve(bFilename, worldRows, worldCols);
if( fDeleteForGood )
{ //Delete the soldier instances -- done when we are completely finished.
@@ -2519,7 +2525,7 @@ DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Autoresolve2");
RemoveCharacterFromSquads( gpMercs[ i ].pSoldier );
ChangeSoldiersAssignment( gpMercs[ i ].pSoldier, ASSIGNMENT_DEAD );
AddDeadSoldierToUnLoadedSector( gpAR->ubSectorX, gpAR->ubSectorY, 0, gpMercs[ i ].pSoldier, RandomGridNo(), ADD_DEAD_SOLDIER_TO_SWEETSPOT );
AddDeadSoldierToUnLoadedSector( gpAR->ubSectorX, gpAR->ubSectorY, 0, gpMercs[ i ].pSoldier, RandomGridNoUnloadedSector(worldRows, worldCols), ADD_DEAD_SOLDIER_TO_SWEETSPOT );
}
else if( gpAR->ubBattleStatus == BATTLE_SURRENDERED || gpAR->ubBattleStatus == BATTLE_CAPTURED )
{
@@ -2624,7 +2630,8 @@ DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Autoresolve2");
}
// Flugente: drop sector equipment
gpCivs[ i ].pSoldier->DropSectorEquipment();
const auto gridno = RandomGridNoUnloadedSector(worldRows, worldCols);
gpCivs[ i ].pSoldier->DropSectorEquipment(gridno);
if( fDeleteForGood && gpCivs[ i ].pSoldier->stats.bLife < OKLIFE/2 )
{
@@ -2649,7 +2656,7 @@ DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Autoresolve2");
UpdateMilitia( militia );
}
AddDeadSoldierToUnLoadedSector( gpAR->ubSectorX, gpAR->ubSectorY, 0, gpCivs[ i ].pSoldier, RandomGridNo(), ADD_DEAD_SOLDIER_TO_SWEETSPOT );
AddDeadSoldierToUnLoadedSector( gpAR->ubSectorX, gpAR->ubSectorY, 0, gpCivs[ i ].pSoldier, gridno, ADD_DEAD_SOLDIER_TO_SWEETSPOT );
StrategicRemoveMilitiaFromSector( gpCivs[ i ].pSoldier->sSectorX, gpCivs[ i ].pSoldier->sSectorY, ubCurrentRank, 1 );
if( ProcessLoyalty() )
@@ -2681,7 +2688,8 @@ DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Autoresolve2");
TrackEnemiesKilled( ENEMY_KILLED_IN_AUTO_RESOLVE, gpEnemies[ i ].pSoldier->ubSoldierClass ); //add casualty to some statistic
if( ProcessLoyalty() )HandleGlobalLoyaltyEvent( GLOBAL_LOYALTY_ENEMY_KILLED, gpAR->ubSectorX, gpAR->ubSectorY, 0 );
ProcessQueenCmdImplicationsOfDeath( gpEnemies[ i ].pSoldier );
AddDeadSoldierToUnLoadedSector( gpAR->ubSectorX, gpAR->ubSectorY, 0, gpEnemies[ i ].pSoldier, RandomGridNo(), ADD_DEAD_SOLDIER_TO_SWEETSPOT );
const auto gridno = RandomGridNoUnloadedSector(worldRows, worldCols);
AddDeadSoldierToUnLoadedSector( gpAR->ubSectorX, gpAR->ubSectorY, 0, gpEnemies[ i ].pSoldier, gridno, ADD_DEAD_SOLDIER_TO_SWEETSPOT);
}
}
}
@@ -6007,7 +6015,7 @@ void AutoResolveMilitiaDropAndPromote()
}
// Flugente: drop sector equipment
gpCivs[i].pSoldier->DropSectorEquipment( );
gpCivs[i].pSoldier->DropSectorEquipment( NOWHERE );
if ( gpCivs[i].pSoldier->stats.bLife < OKLIFE / 2 )
{
-4
View File
@@ -249,10 +249,6 @@ void AdvanceClock( UINT8 ubWarpCode )
guiDay = ( guiGameClock / NUM_SEC_IN_DAY );
guiHour = ( guiGameClock - ( guiDay * NUM_SEC_IN_DAY ) ) / NUM_SEC_IN_HOUR;
guiMin = ( guiGameClock - ( ( guiDay * NUM_SEC_IN_DAY ) + ( guiHour * NUM_SEC_IN_HOUR ) ) ) / NUM_SEC_IN_MIN;
uiHourLua = guiHour;
uiDayLua = guiDay;
uiMinLua = guiMin;
swprintf( WORLDTIMESTR, L"%s %d, %02d:%02d", gpGameClockString[ STR_GAMECLOCK_DAY_NAME ], guiDay, guiHour, guiMin );
+4 -1
View File
@@ -158,7 +158,6 @@ CHAR16 zString[128];
HourlyDrugUpdate();
RebelCommand::HourlyUpdate();
// WANNE: This check should avoid the resaving of a loaded auto-save game, when entering tactical
BOOLEAN doAutoSave = TRUE;
@@ -169,6 +168,10 @@ CHAR16 zString[128];
if (doAutoSave)
{
// We're also using the doAutoSave check to prevent RebelCommand::DailyUpdate() from running a second time when loading an autosave at 00:00
RebelCommand::HourlyUpdate();
if ( AutoSaveToSlot[1] == FALSE && AutoSaveToSlot[2] == FALSE && AutoSaveToSlot[3] == FALSE && AutoSaveToSlot[4] == FALSE )
AutoSaveToSlot[0] = TRUE;
+23 -3
View File
@@ -859,6 +859,7 @@ static int l_PlayerTeamFull(lua_State* L);
static int l_ProfilesStrategicInsertionData(lua_State* L);
static int l_HealBoxers(lua_State* L);
static int l_ResetBoxers(lua_State* L);
static int l_AddVolunteers(lua_State* L);
@@ -912,9 +913,6 @@ static int l_SetIntelAndQuestMapDataForSector(lua_State* L);
using namespace std;
UINT16 idProfil;
UINT32 uiHourLua;
UINT32 uiDayLua;
UINT32 uiMinLua;
UINT16 PROFILLUA_sSectorX;
UINT16 PROFILLUA_sSectorY;
@@ -1189,6 +1187,7 @@ static void IniFunction(lua_State* L, BOOLEAN bQuests)
lua_register(L, "TacticalCharacterDialogueWithSpecialEvent", l_TacticalCharacterDialogueWithSpecialEvent);
lua_register(L, "SetSalary", l_MercSalary);
lua_register(L, "SetProfileStrategicInsertionData", l_ProfilesStrategicInsertionData);
lua_register(L, "HealBoxers", l_HealBoxers);
//Get merc
lua_register(L, "GetDirection", l_GetDirection); //new
@@ -9315,6 +9314,27 @@ static int l_ResetBoxers(lua_State* L)
return 0;
}
// heal boxers back to max health in case the player stays in sector while the boxers are resting
static int l_HealBoxers(lua_State* L)
{
for (UINT8 i = 0; i < NUM_BOXERS; ++i)
{
// Get breath back
gubBoxerID[i]->bBreath = gubBoxerID[i]->bBreathMax;
gubBoxerID[i]->sBreathRed = 0;
// Get life back
gubBoxerID[i]->stats.bLife = gubBoxerID[i]->stats.bLifeMax;
gubBoxerID[i]->bBleeding = 0;
// erase insta-healable injury
gubBoxerID[i]->iHealableInjury = 0;
DebugQuestInfo(String("Lua: healed gubBoxerID[%d] %d back to full health", i, gubBoxerID[i]));
}
return 0;
}
//Set character to sector Y
static int l_SetCharacterSectorY(lua_State* L)
{
-3
View File
@@ -26,9 +26,6 @@ typedef struct
extern ACTION_ITEM_VALUES ActionItemsValues[500];
extern UINT32 uiHourLua;
extern UINT32 uiDayLua;
extern UINT32 uiMinLua;
extern UINT16 PROFILLUA_sSectorX;
extern UINT16 PROFILLUA_sSectorY;
extern UINT8 PROFILLUA_bSectorZ;
+10 -9
View File
@@ -510,15 +510,6 @@ void IniGlobalGameSetting(lua_State *L)
lua_pushinteger(L, gubBoxingMatchesWon);
lua_setglobal(L, "gubBoxingMatchesWon");
lua_pushinteger(L, uiHourLua);
lua_setglobal(L, "cHour");
lua_pushinteger(L, uiDayLua);
lua_setglobal(L, "cDay");
lua_pushinteger(L, uiMinLua);
lua_setglobal(L, "cMin");
lua_pushinteger(L, gbPlayerNum);
lua_setglobal(L, "gbPlayerNum");
@@ -590,6 +581,16 @@ void IniGlobalGameSetting(lua_State *L)
lua_pushinteger(L, guiMin);
lua_setglobal(L, "guiMin");
lua_pushinteger(L, guiDay);
lua_setglobal(L, "cDay");
lua_pushinteger(L, guiHour);
lua_setglobal(L, "cHour");
lua_pushinteger(L, guiMin);
lua_setglobal(L, "cMin");
lua_pushinteger(L, guiCurrentScreen);
lua_setglobal(L, "guiCurrentScreen");
+3 -3
View File
@@ -4881,14 +4881,14 @@ void ExecuteStrategicAIAction( UINT16 usActionCode, INT16 sSectorX, INT16 sSecto
}
// depending on which cities the player currently holds, we send out attack on multiple cities. We try to make these attacks occur simultaneously, so the player will have to fend off
// multiple gigantic attacks on different cities. Ideally, the attacks will be timed so well that the player cannot use a sqaud in both battles, even with use of the helicopter
// multiple gigantic attacks on different cities. Ideally, the attacks will be timed so well that the player cannot use a squad in both battles, even with use of the helicopter
// we first have to check which cities we have to attack. For that, we simply check wether there are troops in the target sector. If not, we will attack here
BOOLEAN fAttack_Grumm = !(SectorInfo[ SEC_H3 ].ubNumTroops > 0);
BOOLEAN fAttack_Cambria = !(SectorInfo[ SEC_H8 ].ubNumTroops > 0);
BOOLEAN fCambriaSAMOccupied = !(SectorInfo[ SEC_I8 ].ubNumTroops > 0);
BOOLEAN fAttack_Alma = !(SectorInfo[ SEC_I13 ].ubNumTroops > 0);
BOOLEAN fAttack_Alma = !(SectorInfo[ SEC_I13 ].ubNumTroops > 0);
BOOLEAN fAttack_Balime = !(SectorInfo[ SEC_L11 ].ubNumTroops > 0);
BOOLEAN fAttack_Chitzena = !(SectorInfo[ SEC_L11 ].ubNumTroops > 0);
BOOLEAN fAttack_Chitzena = !(SectorInfo[ SEC_B2 ].ubNumTroops > 0);
ubNumSoldiers = (UINT8)( gubMinEnemyGroupSize + difficultyMod * 3);
+6
View File
@@ -8472,6 +8472,12 @@ void GetMapKeyboardInput( UINT32 *puiNewEvent )
if ( HandleNailsVestFetish( pSoldier, i, NOTHING ) )
continue;
// tais: never strip Madlab's robot of its installed components (ammo,
// targeting, chassis/armour, utility) - the player can't re-install them
// and the robot would be left defenceless. Only its cargo slot may be emptied.
if ( AM_A_ROBOT( pSoldier ) && i != ROBOT_INVENTORY_SLOT )
continue;
AutoPlaceObjectInInventoryStash(&pSoldier->inv[i], pSoldier->sGridNo, pSoldier->pathing.bLevel);
DeleteObj(&pSoldier->inv[i]);
}
+3 -3
View File
@@ -1423,7 +1423,7 @@ void AddObjectToArmsDealerInventory( UINT8 ubArmsDealer, OBJECTTYPE *pObject )
for (attachmentList::iterator iter = seperateObject[0]->attachments.begin(); iter != seperateObject[0]->attachments.end();) {
// ARM: Note: this is only used for selling, not repairs, so attachmentes are seperated when sold to a dealer
// If the attachment is detachable
if (! (Item[ iter->usItem ].inseparable ) && iter->exists())
if (! (iter->exists() && Item[ iter->usItem ].inseparable))
{
// add this particular attachment (they can't be imprinted, or themselves have attachments!)
AddObjectToArmsDealerInventory( ubArmsDealer, &(*iter) );
@@ -1931,7 +1931,7 @@ UINT32 CalculateObjectItemRepairTime( UINT8 ubArmsDealer, OBJECTTYPE *pItemObjec
// add time to repair any attachments on it
for (attachmentList::iterator iter = (*pItemObject)[x]->attachments.begin(); iter != (*pItemObject)[x]->attachments.end(); ++iter) {
// if damaged and repairable
if ( ( (*iter)[x]->data.objectStatus < 100 ) && CanDealerRepairItem( ubArmsDealer, iter->usItem ) && iter->exists())
if ( iter->exists() && ( (*iter)[x]->data.objectStatus < 100 ) && CanDealerRepairItem( ubArmsDealer, iter->usItem ) )
{
//uiRepairTime += CalculateSimpleItemRepairTime( ubArmsDealer, iter->usItem, (*iter)[x]->data.objectStatus );
uiRepairTime += CalculateObjectItemRepairTime( ubArmsDealer, &(*iter) );
@@ -1988,7 +1988,7 @@ UINT32 CalculateObjectItemRepairCost( UINT8 ubArmsDealer, OBJECTTYPE *pItemObjec
// add cost of repairing any attachments on it
for (attachmentList::iterator iter = (*pItemObject)[x]->attachments.begin(); iter != (*pItemObject)[x]->attachments.end(); ++iter) {
// if damaged and repairable
if ( ( (*iter)[x]->data.objectStatus < 100 ) && CanDealerRepairItem( ubArmsDealer, iter->usItem ) && iter->exists())
if ( iter->exists() && ( (*iter)[x]->data.objectStatus < 100 ) && CanDealerRepairItem( ubArmsDealer, iter->usItem ) )
{
uiRepairCost += CalculateObjectItemRepairCost( ubArmsDealer, &(*iter));
}
+5 -2
View File
@@ -453,11 +453,14 @@ BOOLEAN BoxerAvailable( void )
return( FALSE );
}
// NOTE THIS IS NOW BROKEN BECAUSE NPC.C ASSUMES THAT BOXERSAVAILABLE < 3 IS A
// SEQUEL FIGHT. Maybe we could check Kingpin's location instead!
UINT8 BoxersAvailable( void )
{
UINT8 ubCount = 0;
// Should also run CheckOnBoxers to make sure boxer IDs are set for this function similarly to BoxerAvailable
if (CheckOnBoxers() == FALSE)
{
return(ubCount);
}
for (UINT8 ubLoop = 0; ubLoop < NUM_BOXERS; ++ubLoop)
{
+412 -556
View File
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -10073,7 +10073,7 @@ void DrawArmorValues( OBJECTTYPE * gpItemDescObject )
UINT16 iFinalProtectionValue = iProtectionValue;
for (attachmentList::iterator iter = (*gpItemDescObject)[0]->attachments.begin(); iter != (*gpItemDescObject)[0]->attachments.end(); ++iter)
{
if (Item[ iter->usItem ].usItemClass == IC_ARMOUR)
if ( iter->exists() && Item[ iter->usItem ].usItemClass == IC_ARMOUR)
{
iFinalProtectionValue += Armour[Item[iter->usItem].ubClassIndex].ubProtection;
}
@@ -10099,7 +10099,7 @@ void DrawArmorValues( OBJECTTYPE * gpItemDescObject )
UINT16 iComparedFinalProtectionValue = iComparedProtectionValue;
for (attachmentList::iterator iter = (*gpComparedItemDescObject)[0]->attachments.begin(); iter != (*gpComparedItemDescObject)[0]->attachments.end(); ++iter)
{
if (Item[ iter->usItem ].usItemClass == IC_ARMOUR)
if ( iter->exists() && Item[ iter->usItem ].usItemClass == IC_ARMOUR)
{
iComparedFinalProtectionValue += Armour[Item[iter->usItem].ubClassIndex].ubProtection;
}
+22 -4
View File
@@ -643,13 +643,29 @@ void popupCallbackItem(INT16 itemId){
i++;p++;
}
OBJECTTYPE pObjTmp;
static OBJECTTYPE pObjTmp;
pObjTmp.initialize();
if( bestStack->RemoveObjectAtIndex(leastDamagedIndex, &pObjTmp) ){
gpItemPointer = &pObjTmp; // pick up the object (or stack)
DoAttachment((UINT8)gubPopupStatusIndex, guiPopupItemPos); // try to attach it
//gpItemPointer = NULL; // dont drop it!
// If attaching failed, change mouse cursor to item as we're still holding it
if ( gpItemPointer->exists() ) {
// Set mouse
guiExternVo = GetInterfaceGraphicForItem(&(Item[gpItemPointer->usItem]));
gusExternVoSubIndex = Item[gpItemPointer->usItem].ubGraphicNum;
MSYS_ChangeRegionCursor(&gMPanelRegion, EXTERN_CURSOR);
MSYS_SetCurrentCursor(EXTERN_CURSOR);
fMapInventoryItem = TRUE;
fTeamPanelDirty = TRUE;
//Dirty interface
fInterfacePanelDirty = DIRTYLEVEL2;
UpdateItemHatches();
}
gItemDescAttachmentPopups[giActiveAttachmentPopup]->hide();
RenderItemDescriptionBox();
@@ -6060,7 +6076,8 @@ void ItemDescAmmoCallback(GUI_BUTTON *btn,INT32 reason)
gfItemAmmoDown = FALSE;
//CHRISL: We dont' want to be able to reload guns using the ammo crate from this function
if((gpItemPointer != NULL && Magazine[Item[gpItemPointer->usItem].ubClassIndex].ubMagType >= AMMO_BOX) || !EnoughPoints(gpItemDescSoldier, APBPConstants[AP_RELOAD_GUN], 0, TRUE))//dnl ch65 040913
//Greysa: add check for ammo item
if( gpItemPointer != NULL && ( (Item[gpItemPointer->usItem].usItemClass != IC_AMMO || Magazine[Item[gpItemPointer->usItem].ubClassIndex].ubMagType >= AMMO_BOX) ) || !EnoughPoints(gpItemDescSoldier, APBPConstants[AP_RELOAD_GUN], 0, TRUE) )//dnl ch65 040913
{
fInterfacePanelDirty = DIRTYLEVEL2;
btn->uiFlags &= (~BUTTON_CLICKED_ON );
@@ -6083,7 +6100,8 @@ void ItemDescAmmoCallback(GUI_BUTTON *btn,INT32 reason)
else
{
//holding an item
if(Magazine[Item[gpItemPointer->usItem].ubClassIndex].ubCalibre == Weapon[Item[gpItemDescObject->usItem].ubClassIndex].ubCalibre)
//Greysa: add check for ammo item
if( Item[gpItemPointer->usItem].usItemClass == IC_AMMO && Magazine[Item[gpItemPointer->usItem].ubClassIndex].ubCalibre == Weapon[Item[gpItemDescObject->usItem].ubClassIndex].ubCalibre )
{
ReloadGun(gpItemDescSoldier, gpItemDescObject, gpItemPointer, ubStatusIndex);
}
+137 -45
View File
@@ -1995,7 +1995,7 @@ OBJECTTYPE* FindAttachment( OBJECTTYPE * pObj, UINT16 usItem, UINT8 subObject )
{
if (pObj->exists() == true) {
for (attachmentList::iterator iter = (*pObj)[subObject]->attachments.begin(); iter != (*pObj)[subObject]->attachments.end(); ++iter) {
if (iter->usItem == usItem && iter->exists())
if ( iter->exists() && iter->usItem == usItem )
{
return &(*iter);
}
@@ -2008,7 +2008,7 @@ OBJECTTYPE* FindAttachmentByClass( OBJECTTYPE * pObj, UINT32 uiItemClass, UINT8
{
if (pObj->exists() == true) {
for (attachmentList::iterator iter = (*pObj)[subObject]->attachments.begin(); iter != (*pObj)[subObject]->attachments.end(); ++iter) {
if (Item[iter->usItem].usItemClass == uiItemClass && iter->exists())
if ( iter->exists() && Item[iter->usItem].usItemClass == uiItemClass )
{
return &(*iter);
}
@@ -2021,7 +2021,7 @@ OBJECTTYPE* FindAttachmentByAttachmentClass( OBJECTTYPE * pObj, UINT32 uiAttachm
{
if (pObj->exists() == true) {
for (attachmentList::iterator iter = (*pObj)[subObject]->attachments.begin(); iter != (*pObj)[subObject]->attachments.end(); ++iter) {
if (Item[iter->usItem].attachmentclass == uiAttachmentClass && iter->exists())
if ( iter->exists() && Item[iter->usItem].attachmentclass == uiAttachmentClass )
{
return &(*iter);
}
@@ -2139,7 +2139,7 @@ OBJECTTYPE* FindNonSmokeLaunchableAttachment( OBJECTTYPE * pObj, UINT16 usWeapon
if (pObj->exists() == true) {
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter) {
if (ValidLaunchable( iter->usItem, usWeapon) && Explosive[Item[iter->usItem].ubClassIndex].ubType != EXPLOSV_SMOKE && iter->exists())
if ( iter->exists() && ValidLaunchable( iter->usItem, usWeapon) && Explosive[Item[iter->usItem].ubClassIndex].ubType != EXPLOSV_SMOKE )
{
return &(*iter);
}
@@ -2162,7 +2162,7 @@ BOOLEAN ItemHasAttachments( OBJECTTYPE * pObj, SOLDIERTYPE * pSoldier, UINT8 ite
{
for(attachmentList::iterator att = (*pObj)[iter]->attachments.begin(); att != (*pObj)[iter]->attachments.end(); ++att)
{
if ( att->usItem != 0 && !ItemIsHiddenAttachment(att->usItem) )
if ( att->exists() && att->usItem != 0 && !ItemIsHiddenAttachment(att->usItem) )
{
attachmentHidden = FALSE;
break;
@@ -2178,7 +2178,7 @@ BOOLEAN ItemHasAttachments( OBJECTTYPE * pObj, SOLDIERTYPE * pSoldier, UINT8 ite
{
for(attachmentList::iterator att = (*pObj)[iter]->attachments.begin(); att != (*pObj)[iter]->attachments.end(); ++att)
{
if ( att->usItem != 0 && !ItemIsHiddenAttachment(att->usItem) )
if ( att->exists() && att->usItem != 0 && !ItemIsHiddenAttachment(att->usItem) )
{
attachmentHidden = FALSE;
break;
@@ -3872,13 +3872,111 @@ BOOLEAN AutoReload( SOLDIERTYPE * pSoldier, bool aReloadEvenIfNotEmpty )
{
OBJECTTYPE *pObj, *pObj2;
INT8 bSlot;
INT16 bAPCost;
INT16 bAPCost;
BOOLEAN fRet = FALSE;
CHECKF( pSoldier );
// Flugente: check for underbarrel weapons and use that object if necessary
pObj = pSoldier->GetUsedWeapon( &(pSoldier->inv[HANDPOS]) );
pObj2 = NULL;
if (pSoldier->IsValidSecondHandShotForReloadingPurposes()) //check for valid second hand weapon for reloading purposes (something that doesn't use ammo)
{
pObj2 = pSoldier->GetUsedWeapon( &(pSoldier->inv[SECONDHANDPOS]) );
}
// Greysa: Check if weapon is jammed and unjam it first
if ((*pObj)[0]->data.gun.bGunAmmoStatus < 0 || ((pObj2 != NULL) && (*pObj2)[0]->data.gun.bGunAmmoStatus < 0))
{
if ((*pObj)[0]->data.gun.bGunAmmoStatus < 0)
{
//borrowed from Weapons.cpp
if (EnoughPoints(pSoldier, APBPConstants[AP_UNJAM], APBPConstants[BP_UNJAM], FALSE))
{
DeductPoints(pSoldier, APBPConstants[AP_UNJAM], APBPConstants[BP_UNJAM]);
INT8 bChanceMod;
if (Weapon[pObj->usItem].EasyUnjam)
bChanceMod = 100;
else
bChanceMod = (INT8)(GetReliability(pObj) * 4);
int iResult = SkillCheck(pSoldier, UNJAM_GUN_CHECK, bChanceMod);
if (iResult > 0)
{
// yay! unjammed the gun
(*pObj)[0]->data.gun.bGunAmmoStatus *= -1;
// MECHANICAL/DEXTERITY GAIN: Unjammed a gun
if (bChanceMod < 100) // don't give exp for unjamming an easily unjammable gun
{
StatChange(pSoldier, MECHANAMT, 5, FALSE);
StatChange(pSoldier, DEXTAMT, 5, FALSE);
}
DirtyMercPanelInterface(pSoldier, DIRTYLEVEL2);
PlayJA2Sample(Weapon[Item[pObj->usItem].ubClassIndex].ManualReloadSound, RATE_11025, SoundVolume(HIGHVOLUME, pSoldier->sGridNo), 1, SoundDir(pSoldier->sGridNo));
ScreenMsg(FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, Message[STR_UNJAMMED], pSoldier->GetName(), ItemNames[pObj->usItem]);
// merc voice feedback?
}
else
{
ScreenMsg(FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, Message[STR_FAILED_UNJAM], pSoldier->GetName(), ItemNames[pObj->usItem]);
}
}
else
{
ScreenMsg(FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, Message[STR_NO_AP_NO_UNJAM], pSoldier->GetName(), ItemNames[pObj->usItem]);
}
}
if ((pObj2 != NULL) && (*pObj2)[0]->data.gun.bGunAmmoStatus < 0)
{
if (EnoughPoints(pSoldier, APBPConstants[AP_UNJAM], APBPConstants[BP_UNJAM], FALSE))
{
DeductPoints(pSoldier, APBPConstants[AP_UNJAM], APBPConstants[BP_UNJAM]);
INT8 bChanceMod;
if (Weapon[pObj2->usItem].EasyUnjam)
bChanceMod = 100;
else
bChanceMod = (INT8)(GetReliability(pObj2) * 4);
int iResult = SkillCheck(pSoldier, UNJAM_GUN_CHECK, bChanceMod);
if (iResult > 0)
{
// yay! unjammed the gun
(*pObj2)[0]->data.gun.bGunAmmoStatus *= -1;
// MECHANICAL/DEXTERITY GAIN: Unjammed a gun
if (bChanceMod < 100) // don't give exp for unjamming an easily unjammable gun
{
StatChange(pSoldier, MECHANAMT, 5, FALSE);
StatChange(pSoldier, DEXTAMT, 5, FALSE);
}
DirtyMercPanelInterface(pSoldier, DIRTYLEVEL2);
PlayJA2Sample(Weapon[Item[pObj2->usItem].ubClassIndex].ManualReloadSound, RATE_11025, SoundVolume(HIGHVOLUME, pSoldier->sGridNo), 1, SoundDir(pSoldier->sGridNo));
ScreenMsg(FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, Message[STR_UNJAMMED], pSoldier->GetName(), ItemNames[pObj2->usItem]);
// merc voice feedback?
}
else
{
ScreenMsg(FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, Message[STR_FAILED_UNJAM], pSoldier->GetName(), ItemNames[pObj2->usItem]);
}
}
else
{
ScreenMsg(FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, Message[STR_NO_AP_NO_UNJAM], pSoldier->GetName(), ItemNames[pObj2->usItem]);
}
}
return FALSE; // Greysa: We want to skip reloading if we attempted to unjam, regardless of outcome. Return value doesn't seem to matter as there doesn't seem to be any actual checks on the returned value. I picked FALSE as actual reload hasn't occurred
}
//<SB> manual recharge
if ((*pObj)[0]->data.gun.ubGunShotsLeft && !((*pObj)[0]->data.gun.ubGunState & GS_CARTRIDGE_IN_CHAMBER) )
@@ -3915,10 +4013,8 @@ BOOLEAN AutoReload( SOLDIERTYPE * pSoldier, bool aReloadEvenIfNotEmpty )
PlayJA2Sample( Weapon[ Item[pObj->usItem].ubClassIndex ].ManualReloadSound, RATE_11025, SoundVolume( HIGHVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ) );
if ( pSoldier->IsValidSecondHandShot( ) )
if (pObj2 != NULL)
{
pObj2 = &(pSoldier->inv[SECONDHANDPOS]);
if ((*pObj2)[0]->data.gun.ubGunShotsLeft && !((*pObj2)[0]->data.gun.ubGunState & GS_CARTRIDGE_IN_CHAMBER) )
{
(*pObj2)[0]->data.gun.ubGunState |= GS_CARTRIDGE_IN_CHAMBER;
@@ -3930,10 +4026,8 @@ BOOLEAN AutoReload( SOLDIERTYPE * pSoldier, bool aReloadEvenIfNotEmpty )
}
else
{
if ( pSoldier->IsValidSecondHandShot( ) )
if (pObj2 != NULL)
{
pObj2 = &(pSoldier->inv[SECONDHANDPOS]);
if ((*pObj2)[0]->data.gun.ubGunShotsLeft && !((*pObj2)[0]->data.gun.ubGunState & GS_CARTRIDGE_IN_CHAMBER) )
{
(*pObj2)[0]->data.gun.ubGunState |= GS_CARTRIDGE_IN_CHAMBER;
@@ -3989,21 +4083,19 @@ BOOLEAN AutoReload( SOLDIERTYPE * pSoldier, bool aReloadEvenIfNotEmpty )
// if we are valid for two-pistol shooting (reloading) and we have enough APs still
// then do a reload of both guns!
// Flugente: only reload if it's empty, or we really want to
if ( pSoldier->IsValidSecondHandShotForReloadingPurposes()
&& ( aReloadEvenIfNotEmpty || !EnoughAmmo( pSoldier, FALSE, SECONDHANDPOS ) ) )
if ( pObj2 != NULL && ( aReloadEvenIfNotEmpty || !EnoughAmmo( pSoldier, FALSE, SECONDHANDPOS ) ) )
{
// Flugente: check for underbarrel weapons and use that object if necessary
pObj = pSoldier->GetUsedWeapon( &( pSoldier->inv[SECONDHANDPOS] ) );
bSlot = FindAmmoToReload( pSoldier, SECONDHANDPOS, NO_SLOT );
if ( bSlot != NO_SLOT )
{
// ce would reload using this ammo!
bAPCost = GetAPsToReloadGunWithAmmo( pSoldier, pObj, &( pSoldier->inv[bSlot] ) );
bAPCost = GetAPsToReloadGunWithAmmo( pSoldier, pObj2, &( pSoldier->inv[bSlot] ) );
if ( EnoughPoints( pSoldier, (INT16)bAPCost, 0, FALSE ) )
{
// reload the 2nd gun too
fRet = ReloadGun( pSoldier, pObj, &( pSoldier->inv[bSlot] ) );
fRet = ReloadGun( pSoldier, pObj2, &( pSoldier->inv[bSlot] ) );
}
else
{
@@ -5566,7 +5658,7 @@ BOOLEAN OBJECTTYPE::AttachObjectNAS( SOLDIERTYPE * pSoldier, OBJECTTYPE * pAttac
//Madd: if the attaching/merging item had any attachments on it, then try to move them to the first result
for (attachmentList::iterator iter = (*pAttachment)[0]->attachments.begin(); iter != (*pAttachment)[0]->attachments.end();) {
if( ValidItemAttachmentSlot(this, iter->usItem, TRUE, FALSE, subObject )){
if( iter->exists() && ValidItemAttachmentSlot(this, iter->usItem, TRUE, FALSE, subObject )){
//This seems to be rather valid. Can't be 100% sure though.
OBJECTTYPE tempAttachment; // Madd: we must recreate the attachments because they may themselves have default inseparable attachments...
CreateItem(iter->usItem, (*iter)[0]->data.objectStatus, &tempAttachment);
@@ -5903,7 +5995,7 @@ void RemoveProhibitedAttachments(SOLDIERTYPE* pSoldier, OBJECTTYPE* pObj, UINT16
//Start by trying to re-attach inseperable items. They take precedence over items that can normally be removed
for (attachmentList::iterator iter = tempAttachList.begin(); iter != tempAttachList.end();) {
if(Item[iter->usItem].inseparable && ValidItemAttachmentSlot(pObj, iter->usItem, TRUE, FALSE, 0, -1, 0, NULL, usAttachmentSlotIndexVector)){
if( iter->exists() && Item[iter->usItem].inseparable && ValidItemAttachmentSlot(pObj, iter->usItem, TRUE, FALSE, 0, -1, 0, NULL, usAttachmentSlotIndexVector)){
//This seems to be rather valid. Can't be 100% sure though.
if(pObj->AttachObject(NULL, &(*iter), FALSE, 0, -1, FALSE, usAttachmentSlotIndexVector)){
//Ok now we can be sure, lets remove this object so we don't try to drop it later.
@@ -5917,7 +6009,7 @@ void RemoveProhibitedAttachments(SOLDIERTYPE* pSoldier, OBJECTTYPE* pObj, UINT16
}
//Try to attach all the other attachments that didn't fit their current slot.
for (attachmentList::iterator iter = tempAttachList.begin(); iter != tempAttachList.end();) {
if(ValidItemAttachmentSlot(pObj, iter->usItem, TRUE, FALSE, 0, -1, 0, NULL, usAttachmentSlotIndexVector)){
if( iter->exists() && ValidItemAttachmentSlot(pObj, iter->usItem, TRUE, FALSE, 0, -1, 0, NULL, usAttachmentSlotIndexVector)){
//This seems to be rather valid. Can't be 100% sure though.
if(pObj->AttachObject(NULL, &(*iter), FALSE, 0, -1, FALSE, usAttachmentSlotIndexVector)){
//Ok now we can be sure, lets remove this object so we don't try to drop it later.
@@ -6093,7 +6185,7 @@ attachmentList ReInitMergedItem(SOLDIERTYPE* pSoldier, OBJECTTYPE* pObj, UINT16
//First re-attach any slot-changing attachments.
for (attachmentList::iterator iter = tempSlotChangingAttachList.begin(); iter != tempSlotChangingAttachList.end();) {
if( ValidItemAttachmentSlot(pObj, iter->usItem, TRUE, FALSE, ubStatusIndex )){
if( iter->exists() && ValidItemAttachmentSlot(pObj, iter->usItem, TRUE, FALSE, ubStatusIndex )){
//This seems to be rather valid. Can't be 100% sure though.
OBJECTTYPE tempAttachment; // Madd: we must recreate the attachments because they may themselves have default inseparable attachments...
CreateItem(iter->usItem, (*iter)[0]->data.objectStatus, &tempAttachment);
@@ -6110,7 +6202,7 @@ attachmentList ReInitMergedItem(SOLDIERTYPE* pSoldier, OBJECTTYPE* pObj, UINT16
//Time to re-attach the other attachments, if we can. I am the king of copy pasta.
for (attachmentList::iterator iter = tempAttachList.begin(); iter != tempAttachList.end();) {
if( ValidItemAttachmentSlot(pObj, iter->usItem, TRUE, FALSE, ubStatusIndex)){
if( iter->exists() && ValidItemAttachmentSlot(pObj, iter->usItem, TRUE, FALSE, ubStatusIndex)){
//This seems to be rather valid. Can't be 100% sure though.
OBJECTTYPE tempAttachment; // Madd: we must recreate the attachments because they may themselves have default inseparable attachments...
CreateItem(iter->usItem, (*iter)[0]->data.objectStatus, &tempAttachment);
@@ -6127,7 +6219,7 @@ attachmentList ReInitMergedItem(SOLDIERTYPE* pSoldier, OBJECTTYPE* pObj, UINT16
//drop all items we couldn't re-attach.
for (attachmentList::iterator iter = tempSlotChangingAttachList.begin(); iter != tempSlotChangingAttachList.end(); ++iter) {
if ( Item[iter->usItem].inseparable != 1)
if ( iter->exists() && Item[iter->usItem].inseparable != 1)
{//WarmSteel - Couldn't re-attach this item, try to drop it.
if (pSoldier) {
OBJECTTYPE tempAttachment; // Madd: we must recreate the attachments because they may themselves have default inseparable attachments...
@@ -6145,7 +6237,7 @@ attachmentList ReInitMergedItem(SOLDIERTYPE* pSoldier, OBJECTTYPE* pObj, UINT16
}
//and the rest too
for (attachmentList::iterator iter = tempAttachList.begin(); iter != tempAttachList.end(); ++iter) {
if ( Item[iter->usItem].inseparable != 1)
if ( iter->exists() && Item[iter->usItem].inseparable != 1)
{//WarmSteel - Couldn't re-attach this item, try to drop it.
if (pSoldier) {
OBJECTTYPE tempAttachment; // Madd: we must recreate the attachments because they may themselves have default inseparable attachments...
@@ -10330,7 +10422,7 @@ BOOLEAN NCTHIsScoped( OBJECTTYPE * pObj )
return TRUE;
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter) {
if ( Item[iter->usItem].scopemagfactor > 1.0 && iter->exists() )
if ( iter->exists() && Item[iter->usItem].scopemagfactor > 1.0 )
return TRUE;
}
}
@@ -10349,7 +10441,7 @@ BOOLEAN IsScoped( OBJECTTYPE * pObj )
return TRUE;
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter) {
if ( Item[iter->usItem].aimbonus > 0 && iter->exists())
if ( iter->exists() && Item[iter->usItem].aimbonus > 0 )
return TRUE;
}
}
@@ -10436,7 +10528,7 @@ INT16 GetBaseScopeAimBonus( OBJECTTYPE * pObj, INT32 iRange )
//Search for the most powerful scope we can use.
for(attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); iter++)
{
if(Item[iter->usItem].aimbonus > bonus && iRange >= Item[iter->usItem].minrangeforaimbonus && iter->exists())
if( iter->exists() && Item[iter->usItem].aimbonus > bonus && iRange >= Item[iter->usItem].minrangeforaimbonus )
{
bonus = Item[iter->usItem].aimbonus;
}
@@ -10514,7 +10606,7 @@ UINT32 FindRangeBonusAttachment( OBJECTTYPE * pObj )
{
if (pObj->exists() == true) {
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter) {
if (Item[iter->usItem].rangebonus > 0 && iter->exists())
if ( iter->exists() && Item[iter->usItem].rangebonus > 0 )
{
return( Item[iter->usItem].uiIndex );
}
@@ -10535,7 +10627,7 @@ INT16 GetRangeBonus( OBJECTTYPE * pObj )
bonus += Item[(*pObj)[0]->data.gun.usGunAmmoItem].rangebonus;
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter) {
if ( !ItemIsDuckbill(iter->usItem) || (ItemIsDuckbill(iter->usItem) && (*pObj)[0]->data.gun.ubGunAmmoType == AMMO_BUCKSHOT ) && iter->exists())
if ( iter->exists() && !ItemIsDuckbill(iter->usItem) || (ItemIsDuckbill(iter->usItem) && (*pObj)[0]->data.gun.ubGunAmmoType == AMMO_BUCKSHOT ) )
bonus += BonusReduce( Item[iter->usItem].rangebonus, (*iter)[0]->data.objectStatus );
}
}
@@ -11961,7 +12053,7 @@ BOOLEAN HasThermalOptics( SOLDIERTYPE * pSoldier )
OBJECTTYPE* pObj = &pSoldier->inv[HANDPOS];
if (pObj->exists() == true) {
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter) {
if (ItemIsThermalOptics(iter->usItem) && iter->exists() )
if ( iter->exists() && ItemIsThermalOptics(iter->usItem) )
return TRUE;
}
}
@@ -12018,7 +12110,7 @@ BOOLEAN IsDuckbill( OBJECTTYPE * pObj )
return TRUE;
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter) {
if (ItemIsDuckbill(iter->usItem) && iter->exists() )
if ( iter->exists() && ItemIsDuckbill(iter->usItem) )
{
return( TRUE );
}
@@ -12069,7 +12161,7 @@ BOOLEAN IsDetonatorAttached( OBJECTTYPE * pObj )
// return TRUE;
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter) {
if ( IsAttachmentClass( iter->usItem, AC_DETONATOR ) && iter->exists() )
if ( iter->exists() && IsAttachmentClass( iter->usItem, AC_DETONATOR ) )
{
return( TRUE );
}
@@ -12085,7 +12177,7 @@ BOOLEAN IsRemoteDetonatorAttached( OBJECTTYPE * pObj )
// return TRUE;
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter) {
if ( IsAttachmentClass( iter->usItem, AC_REMOTEDET ) && iter->exists() )
if ( iter->exists() && IsAttachmentClass( iter->usItem, AC_REMOTEDET ) )
{
return( TRUE );
}
@@ -12357,7 +12449,7 @@ OBJECTTYPE* FindAttachedBatteries( OBJECTTYPE * pObj )
{
if (pObj->exists() == true) {
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter) {
if (ItemIsBatteries(iter->usItem) && iter->exists())
if ( iter->exists() && ItemIsBatteries(iter->usItem) )
{
return( &(*iter) );
}
@@ -12589,7 +12681,7 @@ INT16 GetCamoBonus( OBJECTTYPE * pObj )
bonus = (Item[pObj->usItem].camobonus);// * (WEAPON_STATUS_MOD((*pObj)[0]->data.objectStatus) / 100)) ;
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter) {
if (!ItemIsCamoKit(iter->usItem) && iter->exists())
if ( iter->exists() && !ItemIsCamoKit(iter->usItem) )
bonus += (INT16) (Item[iter->usItem].camobonus);// * (WEAPON_STATUS_MOD((*iter)[0]->data.objectStatus) / 100));
}
}
@@ -12602,7 +12694,7 @@ INT16 GetUrbanCamoBonus( OBJECTTYPE * pObj )
bonus = (Item[pObj->usItem].urbanCamobonus);// * (WEAPON_STATUS_MOD((*pObj)[0]->data.objectStatus) / 100)) ;
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter) {
if (!ItemIsCamoKit(iter->usItem) && iter->exists())
if ( iter->exists() && !ItemIsCamoKit(iter->usItem) )
bonus += (INT16) (Item[iter->usItem].urbanCamobonus);// * (WEAPON_STATUS_MOD((*iter)[0]->data.objectStatus) / 100));
}
}
@@ -12615,7 +12707,7 @@ INT16 GetDesertCamoBonus( OBJECTTYPE * pObj )
bonus = (Item[pObj->usItem].desertCamobonus);// * (WEAPON_STATUS_MOD((*pObj)[0]->data.objectStatus) / 100)) ;
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter) {
if (!ItemIsCamoKit(iter->usItem) && iter->exists())
if ( iter->exists() && !ItemIsCamoKit(iter->usItem) )
bonus += (INT16) (Item[iter->usItem].desertCamobonus);// * (WEAPON_STATUS_MOD((*iter)[0]->data.objectStatus) / 100));
}
}
@@ -12628,7 +12720,7 @@ INT16 GetSnowCamoBonus( OBJECTTYPE * pObj )
bonus = (Item[pObj->usItem].snowCamobonus);// * (WEAPON_STATUS_MOD((*pObj)[0]->data.objectStatus) / 100)) ;
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter) {
if (!ItemIsCamoKit(iter->usItem) && iter->exists())
if ( iter->exists() && !ItemIsCamoKit(iter->usItem) )
bonus += (INT16) (Item[iter->usItem].snowCamobonus);// * (WEAPON_STATUS_MOD((*iter)[0]->data.objectStatus) / 100));
}
}
@@ -13073,7 +13165,7 @@ OBJECTTYPE* FindNightGogglesInInv( SOLDIERTYPE * pSoldier, INT8 * bSlot, BOOLEAN
if (searchAllInventory) {
for (UINT8 loop = 0; loop < pSoldier->inv[bLoop].ubNumberOfObjects; loop ++){
for (attachmentList::iterator iter = pSoldier->inv[bLoop][loop]->attachments.begin(); iter != pSoldier->inv[bLoop][loop]->attachments.end(); ++iter) {
if ( Item[ iter->usItem ].cavevisionrangebonus > bonusToBeat && Item[ iter->usItem ].usItemClass == IC_FACE && iter->exists() ) {
if ( iter->exists() && Item[ iter->usItem ].cavevisionrangebonus > bonusToBeat && Item[ iter->usItem ].usItemClass == IC_FACE ) {
pGoggles = &(*iter);
*bSlot = bLoop;
*isAttach = TRUE;
@@ -13131,7 +13223,7 @@ INT16 GetMinRangeForAimBonus( SOLDIERTYPE* pSoldier, OBJECTTYPE * pObj )
attachmentList::iterator iterend = (*pObj)[0]->attachments.end();
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != iterend; ++iter)
{
if ( !gGameExternalOptions.fScopeModes || !IsAttachmentClass(iter->usItem, AC_SCOPE|AC_SIGHT|AC_IRONSIGHT ) )
if ( !gGameExternalOptions.fScopeModes || (iter->exists() && !IsAttachmentClass(iter->usItem, AC_SCOPE|AC_SIGHT|AC_IRONSIGHT )) )
bonus += Item[iter->usItem].minrangeforaimbonus;
}
}
@@ -14049,7 +14141,7 @@ INT16 GetAverageBestLaserRange( OBJECTTYPE * pObj )
}
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter)
{
if (Item[iter->usItem].bestlaserrange > 0 && iter->exists())
if ( iter->exists() && Item[iter->usItem].bestlaserrange > 0 )
{
numModifiers++;
bonus += (FLOAT) Item[iter->usItem].bestlaserrange;
@@ -14075,7 +14167,7 @@ INT16 GetBestLaserRange( OBJECTTYPE * pObj )
}
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter)
{
if (Item[iter->usItem].bestlaserrange > range && iter->exists())
if ( iter->exists() && Item[iter->usItem].bestlaserrange > range )
{
range = Item[iter->usItem].bestlaserrange;
}
@@ -15088,7 +15180,7 @@ BOOLEAN OBJECTTYPE::TransformObject( SOLDIERTYPE * pSoldier, UINT8 ubStatusIndex
// I am the prince of copy pasta ;)
for (attachmentList::iterator iter = unattachableList.begin(); iter != unattachableList.end();)
{
if( ValidItemAttachmentSlot(&gTempObject, iter->usItem, TRUE, FALSE, ubStatusIndex ))
if( iter->exists() && ValidItemAttachmentSlot(&gTempObject, iter->usItem, TRUE, FALSE, ubStatusIndex ))
{
//This seems to be rather valid. Can't be 100% sure though.
OBJECTTYPE tempAttachment; // Madd: we must recreate the attachments because they may themselves have default inseparable attachments...
@@ -15776,7 +15868,7 @@ INT32 GetPercentRangeBonus( OBJECTTYPE * pObj )
bonus = ( bonus * ( 100 + Item[(*pObj)[0]->data.gun.usGunAmmoItem].percentrangebonus ) ) / 100;
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter) {
if ( !ItemIsDuckbill(iter->usItem) || (ItemIsDuckbill(iter->usItem) && (*pObj)[0]->data.gun.ubGunAmmoType == AMMO_BUCKSHOT ))
if ( iter->exists() && !ItemIsDuckbill(iter->usItem) || (ItemIsDuckbill(iter->usItem) && (*pObj)[0]->data.gun.ubGunAmmoType == AMMO_BUCKSHOT ))
bonus = ( bonus * ( 100 + BonusReduce( Item[iter->usItem].percentrangebonus, (*iter)[0]->data.objectStatus ) ) ) / 100;
}
}
+1 -1
View File
@@ -171,7 +171,7 @@ INT32 GetSpreadPattern( OBJECTTYPE * pObj )
//If there are attachments, check them. Stop on the first one with something defined.
//Dear God, I hate C++ iterators. What a fugly mess. //WarmSteel - I made it even messier ;3
for (attachmentList::iterator iter = pObj[0][0]->attachments.begin(); iter != pObj[0][0]->attachments.end(); ++iter){
if( (n=Item[ iter->usItem ].spreadPattern) && iter->exists()){
if( iter->exists() && (n=Item[ iter->usItem ].spreadPattern) ){
//An attachment has it, and it trumps everything, so return it's value.
return n;}
}
+1 -1
View File
@@ -106,7 +106,7 @@ namespace LogicalBodyTypes {
data->filter = FilterDB::Instance().FindFilter(aFilter);
if (data->filter == NULL) throw XMLParseException("Unknown filter specified!", name, data->pParser);
}
if (aPalette != NULL && strcmp(aFilter, "") != 0 && strcmp(aFilter, "default") != 0) {
if (aPalette != NULL && strcmp(aPalette, "") != 0 && strcmp(aPalette, "default") != 0) {
data->paletteTable = PaletteDB::Instance().FindPaletteTable(aPalette);
if (data->paletteTable == NULL) throw XMLParseException("Unknown palette specified!", name, data->pParser);
}
+1
View File
@@ -20,6 +20,7 @@ FLOAT gdMajorMapVersion = MAJOR_MAP_VERSION;
BOOLEAN gfWorldLoaded;
MAPCREATE_STRUCT gMapInformation;
MAPCREATE_STRUCT gMapInformationAutoResolve;
//CHRISL: MINOR_MAP_VERSION information moved to worlddef.h by ADB. We're using these values elsewhere and need them
// in the header file
+1
View File
@@ -57,6 +57,7 @@ public:
};
extern MAPCREATE_STRUCT gMapInformation;
extern MAPCREATE_STRUCT gMapInformationAutoResolve;
void LoadMapInformation(INT8** hBuffer, FLOAT dMajorMapVersion);
void SaveMapInformation(HWFILE hFile, FLOAT dMajorMapVersion, UINT8 ubMinorMapVersion);
+1 -1
View File
@@ -11403,7 +11403,7 @@ void TeamDropAll(UINT8 bTeam, BOOLEAN fForce)
// if soldier is in the current sector, drop all equipment (that has the TAKEN_BY_MILITIA-flag set)
if( pSoldier->bActive && ( pSoldier->sSectorX == gWorldSectorX ) && ( pSoldier->sSectorY == gWorldSectorY ) && ( pSoldier->bSectorZ == gbWorldSectorZ) )
{
pSoldier->DropSectorEquipment();
pSoldier->DropSectorEquipment( NOWHERE );
}
}
}
+1 -1
View File
@@ -1380,7 +1380,7 @@ INT16 AStarPathfinder::CalcAP(int const terrainCost, UINT8 const direction)
}
// Flugente: dragging someone
if ( pSoldier->IsDragging( false ) )
if ( pSoldier->IsDragging() )
{
movementAPCost *= gItemSettings.fDragAPCostModifier;
}
+9 -7
View File
@@ -713,6 +713,10 @@ void RemoveCorpse( INT32 iCorpseID )
DeleteAniTile( gRottingCorpse[ iCorpseID ].pAniTile );
FreeCorpsePalettes( &( gRottingCorpse[ iCorpseID ] ) );
const auto sGridNo = gRottingCorpse[iCorpseID].def.sGridNo;
auto pStructure = FindLastStructure(sGridNo, STRUCTURE_CORPSE);
DeleteStructureFromWorld(pStructure);
}
BOOLEAN CreateCorpsePalette( ROTTING_CORPSE *pCorpse )
@@ -1062,7 +1066,7 @@ BOOLEAN TurnSoldierIntoCorpse( SOLDIERTYPE *pSoldier, BOOLEAN fRemoveMerc, BOOLE
DropKeysInKeyRing( pSoldier, pSoldier->sGridNo, pSoldier->pathing.bLevel, bVisible, FALSE, 0, FALSE );
// Flugente: even if we forbid militia from dropping their equipment, they will still drop what they took via sector inventory (this functions only drops what they took)
pSoldier->DropSectorEquipment();
pSoldier->DropSectorEquipment( NOWHERE );
}
// Make team look for items
@@ -1108,7 +1112,8 @@ BOOLEAN TurnSoldierIntoCorpse( SOLDIERTYPE *pSoldier, BOOLEAN fRemoveMerc, BOOLE
iCorpseID = AddRottingCorpse( &Corpse );
// If this is our guy......make visible...
if ( iCorpseID != -1 && pSoldier->bTeam == OUR_TEAM || gbPublicOpplist[OUR_TEAM][pSoldier->ubID] == SEEN_CURRENTLY )
//if ( pSoldier->bTeam == gbPlayerNum )
if ( iCorpseID != -1 )
{
MakeCorpseVisible( pSoldier, &( gRottingCorpse[ iCorpseID ] ) );
}
@@ -1770,10 +1775,10 @@ BOOLEAN IsValidDecapitationCorpse( ROTTING_CORPSE *pCorpse )
ROTTING_CORPSE *GetCorpseAtGridNo( INT32 sGridNo, INT8 bLevel )
{
STRUCTURE *pStructure, *pBaseStructure;
STRUCTURE *pStructure, *pBaseStructure;
INT32 sBaseGridNo;
pStructure = FindStructure( sGridNo, STRUCTURE_CORPSE );
pStructure = FindLastStructure( sGridNo, STRUCTURE_CORPSE );
if ( pStructure != NULL )
{
@@ -2535,9 +2540,6 @@ void LookForAndMayCommentOnSeeingCorpse( SOLDIERTYPE *pSoldier, INT32 sGridNo, U
return;
}
if (pCorpse->fActivated && pCorpse->def.bVisible != 1)
pCorpse->def.bVisible = 1;
if ( pCorpse->def.ubType != ROTTING_STAGE2 )
{
return;
+1 -1
View File
@@ -3031,7 +3031,7 @@ BOOLEAN RepairIsDone(DEALER_SPECIAL_ITEM* pSpecial)
// max condition of all permanent attachments on it
for (attachmentList::iterator iter = RepairItem.ItemObject[0]->attachments.begin(); iter != RepairItem.ItemObject[0]->attachments.end(); ++iter) {
if ( CanDealerRepairItem( gbSelectedArmsDealerID, iter->usItem ) && iter->exists())
if ( iter->exists() && CanDealerRepairItem( gbSelectedArmsDealerID, iter->usItem ) )
{
// fix it up
(*iter)[0]->data.objectStatus = 100;
+6 -6
View File
@@ -9046,7 +9046,7 @@ void CalculateSoldierAniSpeed( SOLDIERTYPE *pSoldier, SOLDIERTYPE *pStatsSoldier
}
// Flugente: drag people
if ( pSoldier->IsDragging( false ) )
if ( pSoldier->IsDragging() )
{
pSoldier->sAniDelay = gItemSettings.fDragAPCostModifier * pSoldier->sAniDelay;
}
@@ -11516,7 +11516,7 @@ void SOLDIERTYPE::MoveMerc( FLOAT dMovementChange, FLOAT dAngle, BOOLEAN fCheckR
// Flugente: as we move a tile, we would now be too far away to drag someone.
// So remember whether we were dragging (we have to set our position now, otherwise the person we drag woul soon occupy our gridno).
BOOLEAN currentlydragging = this->IsDragging();
BOOLEAN currentlydragging = this->IsDragging(true);
INT32 sOldGridNo = this->sGridNo;
// OK, set new position
@@ -14668,7 +14668,7 @@ void SOLDIERTYPE::SoldierInventoryCoolDown( void )
attachmentList::iterator iterend = (*pObj)[0]->attachments.end( );
for ( attachmentList::iterator iter = (*pObj)[0]->attachments.begin( ); iter != iterend; ++iter )
{
if ( Item[iter->usItem].usFlashLightRange )
if ( iter->exists() && Item[iter->usItem].usFlashLightRange )
flashlightfound = TRUE;
}
}
@@ -16818,7 +16818,7 @@ BOOLEAN SOLDIERTYPE::UpdateMultiTurnAction( )
return TRUE;
}
void SOLDIERTYPE::DropSectorEquipment( )
void SOLDIERTYPE::DropSectorEquipment( INT32 UnloadedSectorGridNo)
{
// not if we already dropped the gear
if ( this->usSoldierFlagMask & SOLDIER_EQUIPMENT_DROPPED )
@@ -16887,7 +16887,7 @@ void SOLDIERTYPE::DropSectorEquipment( )
}
}
AddItemsToUnLoadedSector( this->sSectorX, this->sSectorY, this->bSectorZ, RandomGridNo( ), counter, pObject, 0, WORLD_ITEM_REACHABLE, 0, 1, FALSE );
AddItemsToUnLoadedSector( this->sSectorX, this->sSectorY, this->bSectorZ, UnloadedSectorGridNo, counter, pObject, 0, WORLD_ITEM_REACHABLE, 0, 1, FALSE );
}
}
@@ -24226,7 +24226,7 @@ BOOLEAN SOLDIERTYPE::CanBreakWindow(void)
BOOLEAN SOLDIERTYPE::CanStartDrag(void)
{
if (!this->IsDragging(false) && this->CanDragInPrinciple())
if (!this->IsDragging() && this->CanDragInPrinciple())
{
INT32 sNewGridNo = NewGridNo(this->sGridNo, DirectionInc(this->ubDirection));
+2 -2
View File
@@ -1916,7 +1916,7 @@ public:
void CancelMultiTurnAction(BOOLEAN fFinished);
BOOLEAN UpdateMultiTurnAction();
void DropSectorEquipment();
void DropSectorEquipment( INT32 UnloadedSectorGridNo);
// sevenfm: Take new bomb with id = usItem from iventory to HANDPOS
void TakeNewBombFromInventory(UINT16 usItem);
@@ -2056,7 +2056,7 @@ public:
BOOLEAN CanDragPerson(SoldierID usID, BOOLEAN fCheckStance = FALSE);
BOOLEAN CanDragCorpse(UINT16 usCorpseNum, BOOLEAN fCheckStance = FALSE);
BOOLEAN CanDragStructure(INT32 sGridNo, BOOLEAN fCheckStance = FALSE);
BOOLEAN IsDragging(bool aStopIfConditionNotSatisfied = true);
BOOLEAN IsDragging(bool aStopIfConditionNotSatisfied = false);
void SetDragOrderPerson( SoldierID usID );
void SetDragOrderCorpse( UINT32 uiCorpseID );
void SetDragOrderStructure( INT32 sGridNo );
+1 -1
View File
@@ -147,7 +147,7 @@ void SoldierTooltip( SOLDIERTYPE* pSoldier )
{
OBJECTTYPE* pObject = &(gusSelectedSoldier->inv[HANDPOS]);
for (attachmentList::iterator iter = (*pObject)[0]->attachments.begin(); iter != (*pObject)[0]->attachments.end(); ++iter) {
if ( Item[iter->usItem].visionrangebonus > 0 && iter->exists())
if ( iter->exists() && Item[iter->usItem].visionrangebonus > 0 )
{
fMercIsUsingScope = TRUE;
break;
+17 -13
View File
@@ -2221,7 +2221,7 @@ void GetKeyboardInput( UINT32 *puiNewEvent )
// sevenfm: also stop dragging
if (gusSelectedSoldier != NOBODY &&
gusSelectedSoldier &&
gusSelectedSoldier->IsDragging(false))
gusSelectedSoldier->IsDragging())
{
gusSelectedSoldier->CancelDrag();
DirtyMercPanelInterface(gusSelectedSoldier, DIRTYLEVEL2);
@@ -4303,21 +4303,25 @@ void GetKeyboardInput( UINT32 *puiNewEvent )
// Make auto reload with magazines from sector inventory
case 'R':
HandleTBReloadAll();
if (fAlt && gusSelectedSoldier != NOBODY ) // Greysa: Moved here from 'r' to retain all functionality during testing.
{
if (CHEATER_CHEAT_LEVEL())
{
ReloadWeapon(gusSelectedSoldier, gusSelectedSoldier->ubAttackingHand);
}
}
else
{
HandleTBReloadAll();
}
break;
case 'r':
if( gusSelectedSoldier != NOBODY )
{
if( fAlt ) //reload selected merc's weapon
if( fAlt )
{
if ( CHEATER_CHEAT_LEVEL( ) )
{
ReloadWeapon( gusSelectedSoldier, gusSelectedSoldier->ubAttackingHand );
}
else
HandleTBReload();
}
HandleTBReload();
}
else if( fCtrl )
{
if ( INFORMATION_CHEAT_LEVEL( ) )
@@ -6766,7 +6770,7 @@ void SwapGogglesUniformly(SOLDIERTYPE *pTeamSoldier, BOOLEAN fToNightVision)
pObj = &(pTeamSoldier->inv[gear]);
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter)
{
if ( Item[ iter->usItem ].nightvisionrangebonus > bestBonus && Item[ iter->usItem ].usItemClass == IC_FACE && iter->exists())
if ( iter->exists() && Item[ iter->usItem ].nightvisionrangebonus > bestBonus && Item[ iter->usItem ].usItemClass == IC_FACE )
{
pGoggles = &(*iter);
bestBonus = Item[ iter->usItem ].nightvisionrangebonus;
@@ -6814,7 +6818,7 @@ void SwapGogglesUniformly(SOLDIERTYPE *pTeamSoldier, BOOLEAN fToNightVision)
pObj = &(pTeamSoldier->inv[gear]);
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter)
{
if ( Item[ iter->usItem ].brightlightvisionrangebonus > bestBonus && Item[ iter->usItem ].usItemClass == IC_FACE && iter->exists())
if ( iter->exists() && Item[ iter->usItem ].brightlightvisionrangebonus > bestBonus && Item[ iter->usItem ].usItemClass == IC_FACE )
{
pGoggles = &(*iter);
bestBonus = Item[ iter->usItem ].brightlightvisionrangebonus;
+1 -1
View File
@@ -2081,7 +2081,7 @@ UINT8 HandleNonActivatedTossCursor( SOLDIERTYPE *pSoldier, INT32 sGridNo, BOOLEA
//sevenfm this should be checked only for guns because we can throw items with attached explosives
if(Item[pObj->usItem].usItemClass & IC_WEAPON )
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter) {
if ( Item[ iter->usItem ].usItemClass & IC_EXPLOSV && iter->exists())
if ( iter->exists() && Item[ iter->usItem ].usItemClass & IC_EXPLOSV )
{
pObject = &(*iter);
break;
+11 -11
View File
@@ -1036,7 +1036,7 @@ INT32 EffectiveArmour( OBJECTTYPE * pObj )
iValue = iValue * (*pObj)[0]->data.objectStatus * Armour[ Item[pObj->usItem].ubClassIndex ].ubCoverage / 10000;
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter) {
if (Item[iter->usItem].usItemClass == IC_ARMOUR && (*iter)[0]->data.objectStatus > 0 && iter->exists())
if ( iter->exists() && Item[iter->usItem].usItemClass == IC_ARMOUR && (*iter)[0]->data.objectStatus > 0 )
{
INT32 iValue2;
@@ -1062,7 +1062,7 @@ INT32 EffectiveArmourLBE( OBJECTTYPE * pObj )
iValue = 0;
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter) {
if (Item[iter->usItem].usItemClass == IC_ARMOUR && (*iter)[0]->data.objectStatus > 0 )
if ( iter->exists() && Item[iter->usItem].usItemClass == IC_ARMOUR && (*iter)[0]->data.objectStatus > 0 )
{
INT32 iValue2;
@@ -1088,7 +1088,7 @@ INT32 ExplosiveEffectiveArmourLBE( OBJECTTYPE * pObj )
iValue = 0;
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter) {
if (Item[iter->usItem].usItemClass == IC_ARMOUR && (*iter)[0]->data.objectStatus > 0 )
if ( iter->exists() && Item[iter->usItem].usItemClass == IC_ARMOUR && (*iter)[0]->data.objectStatus > 0 )
{
INT32 iValue2;
@@ -1214,7 +1214,7 @@ INT32 ExplosiveEffectiveArmour( OBJECTTYPE * pObj )
}
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter) {
if (Item[iter->usItem].usItemClass == IC_ARMOUR && (*iter)[0]->data.objectStatus > 0 && iter->exists())
if ( iter->exists() && Item[iter->usItem].usItemClass == IC_ARMOUR && (*iter)[0]->data.objectStatus > 0 )
{
INT32 iValue2;
@@ -1295,7 +1295,7 @@ INT16 FireEffectiveArmour( OBJECTTYPE * pObj )
for ( attachmentList::iterator iter = ( *pObj )[0]->attachments.begin(); iter != ( *pObj )[0]->attachments.end(); ++iter )
{
if ( Item[iter->usItem].usItemClass == IC_ARMOUR && ( *iter )[0]->data.objectStatus > 0 && iter->exists() )
if ( iter->exists() && Item[iter->usItem].usItemClass == IC_ARMOUR && ( *iter )[0]->data.objectStatus > 0 )
{
iValue += Item[iter->usItem].sFireResistance * ( *iter )[0]->data.objectStatus / 100;
}
@@ -2560,7 +2560,7 @@ BOOLEAN UseGunNCTH( SOLDIERTYPE *pSoldier , INT32 sTargetGridNo )
{
for (attachmentList::iterator iter = (*pObjAttHand)[0]->attachments.begin(); iter != (*pObjAttHand)[0]->attachments.end(); ++iter)
{
if (ItemHasHiddenMuzzleFlash(iter->usItem))
if ( iter->exists() && ItemHasHiddenMuzzleFlash(iter->usItem))
{
OBJECTTYPE* pA= &(*iter);
if ( (*pA)[0]->data.objectStatus >=USABLE)
@@ -3346,7 +3346,7 @@ BOOLEAN UseGun( SOLDIERTYPE *pSoldier , INT32 sTargetGridNo )
{
for (attachmentList::iterator iter = (*pObjUsed)[0]->attachments.begin(); iter != (*pObjUsed)[0]->attachments.end(); ++iter)
{
if (ItemHasHiddenMuzzleFlash(iter->usItem))
if ( iter->exists() && ItemHasHiddenMuzzleFlash(iter->usItem))
{
OBJECTTYPE* pA= &(*iter);
if ( (*pA)[0]->data.objectStatus >=USABLE)
@@ -5111,7 +5111,7 @@ BOOLEAN UseLauncher( SOLDIERTYPE *pSoldier, INT32 sTargetGridNo )
pObj = &(pSoldier->inv[HANDPOS]);
attachmentList::iterator iter;
for (iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter) {
if ( Item[ iter->usItem ].usItemClass & IC_EXPLOSV && iter->exists())
if ( iter->exists() && Item[ iter->usItem ].usItemClass & IC_EXPLOSV )
{
break;
}
@@ -7993,7 +7993,7 @@ INT32 TotalArmourProtection( SOLDIERTYPE * pTarget, UINT8 ubHitLocation, INT32 i
if (iSlot == VESTPOS && pVestPack->exists() == true)
{
for (attachmentList::iterator iter = (*pVestPack)[0]->attachments.begin(); iter != (*pVestPack)[0]->attachments.end(); ++iter) {
if (Item[iter->usItem].usItemClass == IC_ARMOUR && (*iter)[0]->data.objectStatus > 0 )
if ( iter->exists() && Item[iter->usItem].usItemClass == IC_ARMOUR && (*iter)[0]->data.objectStatus > 0 )
{
INT32 protection = ArmourProtection( pTarget, Item[iter->usItem].ubClassIndex, &((*iter)[0]->data.objectStatus), iImpact, ubAmmoType, &plateHit );
@@ -8025,7 +8025,7 @@ INT32 TotalArmourProtection( SOLDIERTYPE * pTarget, UINT8 ubHitLocation, INT32 i
if (pArmour->exists() == true)
{
for (attachmentList::iterator iter = (*pArmour)[0]->attachments.begin(); iter != (*pArmour)[0]->attachments.end(); ++iter) {
if (Item[iter->usItem].usItemClass == IC_ARMOUR && (*iter)[0]->data.objectStatus > 0 && iter->exists())
if ( iter->exists() && Item[iter->usItem].usItemClass == IC_ARMOUR && (*iter)[0]->data.objectStatus > 0 )
{
// bullet got through jacket; apply ceramic plate armour
INT32 protection = ArmourProtection( pTarget, Item[iter->usItem].ubClassIndex, &((*iter)[0]->data.objectStatus), iImpact, ubAmmoType, &plateHit );
@@ -8071,7 +8071,7 @@ INT32 TotalArmourProtection( SOLDIERTYPE * pTarget, UINT8 ubHitLocation, INT32 i
{
//Madd: put any attachments that someone might have added to the armour in the merc's inventory
for (attachmentList::iterator iter = (*pArmour)[0]->attachments.begin(); iter != (*pArmour)[0]->attachments.end(); ++iter) {
if ( !AutoPlaceObject( pTarget, &(*iter), FALSE ) && iter->exists())
if ( iter->exists() && !AutoPlaceObject( pTarget, &(*iter), FALSE ) )
{ // put it on the ground
AddItemToPool( pTarget->sGridNo, &(*iter), 1, pTarget->pathing.bLevel, 0 , -1 );
}
+1 -1
View File
@@ -2207,7 +2207,7 @@ INT32 EstimateShotDamage(SOLDIERTYPE *pSoldier, SOLDIERTYPE *pOpponent, INT16 ub
// check for ceramic plates; these do affect monster spit
for (attachmentList::iterator iter = pOpponent->inv[VESTPOS][0]->attachments.begin(); iter != pOpponent->inv[VESTPOS][0]->attachments.end(); ++iter) {
if (Item[iter->usItem].usItemClass == IC_ARMOUR && (*iter)[0]->data.objectStatus > 0 && iter->exists() )
if ( iter->exists() && Item[iter->usItem].usItemClass == IC_ARMOUR && (*iter)[0]->data.objectStatus > 0 )
{
iTorsoProt += (INT32) Armour[Item[iter->usItem].ubClassIndex].ubProtection *
(INT32) (*iter)[0]->data.objectStatus / 100;
+64 -1
View File
@@ -1319,7 +1319,7 @@ BOOLEAN FindFenceJumpDirection( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bStar
return( FALSE );
}
//Simply chooses a random gridno within valid boundaries (for dropping things in unloaded sectors)
//Simply chooses a random gridno within valid boundaries (for dropping things in loaded sectors)
INT32 RandomGridNo()
{
INT32 iMapXPos, iMapYPos, iMapIndex;
@@ -1332,6 +1332,69 @@ INT32 RandomGridNo()
return iMapIndex;
}
static bool pointLeftOfEdge(INT32 xp, INT32 yp, INT32 x1, INT32 y1, INT32 x2, INT32 y2)
{
//Test whether the point(xp, yp) lies on the left-hand side of the edge(x1, y1) - (x2, y2)
const auto D = (x2 - x1) * (yp - y1) - (xp - x1) * (y2 - y1);
return (D > 0);
}
INT32 RandomGridNoUnloadedSector(INT32 worldRows, INT32 worldCols)
{
INT32 iMapIndex;
const auto centerHeight = gpWorldLevelDataAutoResolve[gMapInformationAutoResolve.sCenterGridNo].sHeight;
const auto CenterWorldX = (WORLD_ROWS) / 2 * CELL_X_SIZE;
const auto CenterWorldY = (WORLD_COLS) / 2 * CELL_Y_SIZE;
// Sector corners are shifted inwards a bit to limit the area to be slightly smaller than actual sector.
// It fixed a few annyoing edge cases where a tile would evaluate to being inside the map, but it was juuust out of reach in actual gameplay
const auto TLX = 2*CELL_X_SIZE; // Shift X-coordinate by one tile inwards from actual edge.
const auto TLY = (WORLD_ROWS / 2) * CELL_X_SIZE;
const auto TRX = (WORLD_COLS / 2) * CELL_Y_SIZE;
const auto TRY = 2*CELL_X_SIZE; // Shift Y-coordinate by one tile inwards from actual edge
const auto BLX = ((WORLD_COLS / 2) * CELL_Y_SIZE);
const auto BLY = ((WORLD_ROWS-1) * CELL_Y_SIZE); // Shift Y-coordinate by one row inwards from actual edge
const auto BRX = ((WORLD_COLS-1) * CELL_Y_SIZE); // Shift X-coordinate by one row inwards from actual edge
const auto BRY = ((WORLD_ROWS / 2) * CELL_X_SIZE);
UINT8 randomGridHeight = 255;
do
{
randomGridHeight = 255; // Reset height to be tested
INT32 iMapXPos = Random(worldCols);
INT32 iMapYPos = Random(worldRows);
iMapIndex = iMapYPos * worldCols + iMapXPos;
// Discard gridno that is not within map bounds.
// Check point against world area's edges. If any edge test fails, it means point is not inside.
// Edge traverals goes counterclockwise, Top Right -> Top Left -> Bottom Left -> Bottom Right -> Top Right
const auto pX = iMapXPos * CELL_X_SIZE;
const auto pY = iMapYPos * CELL_Y_SIZE;
//TR->TL
if ( !pointLeftOfEdge(pX, pY, TLX, TLY, TRX, TRY) )
continue;
//TL->BL
if ( !pointLeftOfEdge(pX, pY, BLX, BLY, TLX, TLY) )
continue;
//BL->BR
if ( !pointLeftOfEdge(pX, pY, BRX, BRY, BLX, BLY) )
continue;
//BR->TR
if ( !pointLeftOfEdge(pX, pY, TRX, TRY, BRX, BRY) )
continue;
// Compare randomGridHeight with height of the center grid of the map, as long as the center of the map is on walkable height it will work properly
randomGridHeight = gpWorldLevelDataAutoResolve[iMapIndex].sHeight;
} while ( !(randomGridHeight == centerHeight) );
return iMapIndex;
}
// Flugente: is this gridno near a player merc?
BOOLEAN GridNoNearPlayerMercs( INT32 sGridNo, INT16 sRadius )
{
+1
View File
@@ -113,6 +113,7 @@ BOOLEAN FindFenceJumpDirection( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bStar
//Simply chooses a random gridno within valid boundaries (for dropping things in unloaded sectors)
INT32 RandomGridNo();
INT32 RandomGridNoUnloadedSector(INT32 worldRows, INT32 worldCols);
extern UINT32 guiForceRefreshMousePositionCalculation;
+28
View File
@@ -1428,6 +1428,7 @@ STRUCTURE * SwapStructureForPartnerForcingGraphicalChange( INT32 sGridNo, STRUCT
}
#endif
// Finds the first structure with matching flag
STRUCTURE * FindStructure( INT32 sGridNo, UINT32 fFlags )
{
// finds a structure that matches any of the given flags
@@ -1451,6 +1452,33 @@ STRUCTURE * FindStructure( INT32 sGridNo, UINT32 fFlags )
return( NULL );
}
// Finds the last structure with matching flag
STRUCTURE* FindLastStructure(INT32 sGridNo, UINT32 fFlags)
{
// finds a structure that matches any of the given flags
STRUCTURE* pCurrent;
STRUCTURE* pLastMatch = nullptr;
//bug fix for win98 crash when traveling between sectors
if ( TileIsOutOfBounds(sGridNo) )
{
return(NULL);
}
pCurrent = gpWorldLevelData[sGridNo].pStructureHead;
while ( pCurrent != NULL )
{
if ( (pCurrent->fFlags & fFlags) != 0 )
{
pLastMatch = pCurrent;
//return(pCurrent);
}
pCurrent = pCurrent->pNext;
}
return(pLastMatch);
}
STRUCTURE * FindNextStructure( STRUCTURE * pStructure, UINT32 fFlags )
{
STRUCTURE * pCurrent;
+1
View File
@@ -47,6 +47,7 @@ BOOLEAN DeleteStructureFromWorld( STRUCTURE * pStructure );
// functions to find a structure in a location
//
STRUCTURE * FindStructure( INT32 sGridNo, UINT32 fFlags );
STRUCTURE* FindLastStructure(INT32 sGridNo, UINT32 fFlags);
STRUCTURE * FindNextStructure( STRUCTURE * pStructure, UINT32 fFlags );
STRUCTURE * FindStructureByID( INT32 sGridNo, UINT16 usStructureID );
STRUCTURE * FindBaseStructure( STRUCTURE * pStructure );
+292 -1
View File
@@ -138,7 +138,8 @@ void SaveMapLights( HWFILE hfile );
void LoadMapLights( INT8 **hBuffer );
// Global Variables
MAP_ELEMENT *gpWorldLevelData;
MAP_ELEMENT* gpWorldLevelData;
MAP_ELEMENT *gpWorldLevelDataAutoResolve;
INT32 *gpDirtyData;
UINT32 gSurfaceMemUsage;
//UINT8 gubWorldMovementCosts[ WORLD_MAX ][MAXDIR][2];
@@ -3312,6 +3313,296 @@ BOOLEAN LoadWorld(const STR8 puiFilename, FLOAT* pMajorMapVersion, UINT8* pMinor
return(TRUE);
}
// A stub LoadWorld function so we can read a sector's tile height values into gpWorldLevelDataAutoResolve[].sHeight and entrypoint gridnos into gMapInformationAutoResolve
// They are needed when placing corpses and dropped items into a random gridno in an unloaded sector when we're finished with autoresolve battle.
BOOLEAN LoadWorldInfoForAutoResolve(const STR8 puiFilename, INT32& iRowSize, INT32& iColSize)
{
HWFILE hfile;
FLOAT dMajorMapVersion;
UINT8 ubMinorMapVersion;
UINT32 uiFlags;
UINT32 uiBytesRead;
UINT32 uiFileSize;
INT32 i, cnt, cnt2;
UINT8 ubType;
CHAR8 aFilename[2 * FILENAME_BUFLEN];
UINT8 ubCombine;
UINT8(*bCounts)[8] = NULL;
INT8* pBuffer;
INT8* pBufferHead;
// Append exension to filename!
if ( gfForceLoad )
sprintf(aFilename, "MAPS\\%s", gzForceLoadFile);
else
sprintf(aFilename, "MAPS\\%s", puiFilename);
// Open file
hfile = FileOpen(aFilename, FILE_ACCESS_READ);
if ( !hfile )
{
#ifndef JA2EDITOR
SET_ERROR("Could not load map file %S", aFilename);
#endif
return(FALSE);
}
// Get the file size and alloc one huge buffer for it. We will use this buffer to transfer all of the data from.
uiFileSize = FileGetSize(hfile);
pBuffer = (INT8*)MemAlloc(uiFileSize);
pBufferHead = pBuffer;
FileRead(hfile, pBuffer, uiFileSize, &uiBytesRead);
FileClose(hfile);
// Read JA2 Version ID
LOADDATA(&dMajorMapVersion, pBuffer, sizeof(FLOAT));
LOADDATA(&ubMinorMapVersion, pBuffer, sizeof(UINT8));
iRowSize = OLD_WORLD_ROWS;
iColSize = OLD_WORLD_COLS;
if ( dMajorMapVersion >= 7.00 )
{
LOADDATA(&iRowSize, pBuffer, sizeof(INT32));
LOADDATA(&iColSize, pBuffer, sizeof(INT32));
}
// Actual world size of the map we loaded!
INT32 iWorldSize = iRowSize * iColSize;
gMapTrn.ResizeTrnCfg(WORLD_ROWS, WORLD_COLS, iRowSize, iColSize);
// Initialize world data
if ( gpWorldLevelDataAutoResolve != NULL )
MemFree(gpWorldLevelDataAutoResolve);
gpWorldLevelDataAutoResolve = (MAP_ELEMENT*)MemAlloc(sizeof(MAP_ELEMENT) * WORLD_MAX);
memset(gpWorldLevelDataAutoResolve, 0, sizeof(MAP_ELEMENT) * WORLD_MAX);
bCounts = (UINT8(*)[8])MemAlloc(WORLD_MAX * 8);
memset(bCounts, 0, sizeof(UINT8) * WORLD_MAX * 8);
// Read FLAGS FOR WORLD
LOADDATA(&uiFlags, pBuffer, sizeof(INT32));
SKIPDATA(pBuffer, pBuffer, sizeof(INT32)); // TilesetID
// Load soldier size
SKIPDATA(pBuffer, pBuffer, sizeof(INT32));
// NOTE! We need this!
// Read height values
for ( i = 0; i < iWorldSize; i++ )
{
gMapTrn.GetTrnCnt(cnt = i);
LOADDATA(&gpWorldLevelDataAutoResolve[cnt].sHeight, pBuffer, sizeof(INT16));
}
// Read layer counts
for ( i = 0; i < iWorldSize; i++ )
{
gMapTrn.GetTrnCnt(cnt = i);
// Read combination of land/world flags
LOADDATA(&ubCombine, pBuffer, sizeof(UINT8));
// Split
bCounts[cnt][0] = (UINT8)(ubCombine & 0x0F);
gpWorldLevelDataAutoResolve[cnt].uiFlags |= (UINT8)((ubCombine & 0xF0) >> 4);
// Read #objects, structs
LOADDATA(&ubCombine, pBuffer, sizeof(UINT8));
// Split
bCounts[cnt][1] = (UINT8)(ubCombine & 0x0F);
bCounts[cnt][2] = (UINT8)((ubCombine & 0xF0) >> 4);
// Read shadows, roof
LOADDATA(&ubCombine, pBuffer, sizeof(UINT8));
// Split
bCounts[cnt][3] = (UINT8)(ubCombine & 0x0F);
bCounts[cnt][4] = (UINT8)((ubCombine & 0xF0) >> 4);
// Read OnRoof, nothing
LOADDATA(&ubCombine, pBuffer, sizeof(UINT8));
// Split
bCounts[cnt][5] = (UINT8)(ubCombine & 0x0F);
}
for ( i = 0; i < iWorldSize; i++ )
{
gMapTrn.GetTrnCnt(cnt = i);
for ( cnt2 = 0; cnt2 < bCounts[cnt][0]; cnt2++ )
{
SKIPDATA(pBuffer, pBuffer, sizeof(UINT8));
SKIPDATA(pBuffer, pBuffer, sizeof(UINT8));
}
}
// New load require UINT16 for the type subindex due to the fact that ROADPIECES contain over 300 type subindices.
for ( i = 0; i < iWorldSize; i++ )
{
gMapTrn.GetTrnCnt(cnt = i);
// Set objects
for ( cnt2 = 0; cnt2 < bCounts[cnt][1]; cnt2++ )
{
LOADDATA(&ubType, pBuffer, sizeof(UINT8));
SKIPDATA(pBuffer, pBuffer, sizeof(UINT16));
if ( ubType >= FIRSTPOINTERS )
continue;
}
}
for ( i = 0; i < iWorldSize; i++ )
{
gMapTrn.GetTrnCnt(cnt = i);
// Set structs
for ( cnt2 = 0; cnt2 < bCounts[cnt][2]; cnt2++ )
{
SKIPDATA(pBuffer, pBuffer, sizeof(UINT8));
SKIPDATA(pBuffer, pBuffer, sizeof(UINT8));
}
}
for ( i = 0; i < iWorldSize; i++ )
{
gMapTrn.GetTrnCnt(cnt = i);
for ( cnt2 = 0; cnt2 < bCounts[cnt][3]; cnt2++ )
{
SKIPDATA(pBuffer, pBuffer, sizeof(UINT8));
SKIPDATA(pBuffer, pBuffer, sizeof(UINT8));
}
}
for ( i = 0; i < iWorldSize; i++ )
{
gMapTrn.GetTrnCnt(cnt = i);
for ( cnt2 = 0; cnt2 < bCounts[cnt][4]; cnt2++ )
{
SKIPDATA(pBuffer, pBuffer, sizeof(UINT8));
SKIPDATA(pBuffer, pBuffer, sizeof(UINT8));
}
}
for ( i = 0; i < iWorldSize; i++ )
{
gMapTrn.GetTrnCnt(cnt = i);
for ( cnt2 = 0; cnt2 < bCounts[cnt][5]; cnt2++ )
{
SKIPDATA(pBuffer, pBuffer, sizeof(UINT8));
SKIPDATA(pBuffer, pBuffer, sizeof(UINT8));
}
}
// For old Russian Maps which have version 6.0
if ( dMajorMapVersion == 6.00 && ubMinorMapVersion < 27 )
{
UINT32 uiNums[37];
LOADDATA(uiNums, pBuffer, sizeof(INT32) * 37);
dMajorMapVersion = 5.00;
}
// For new maps
else if ( dMajorMapVersion == 6.00 && ubMinorMapVersion < 27 && MAJOR_MAP_VERSION == 6.00 )
{
UINT32 uiNums[37];
LOADDATA(uiNums, pBuffer, sizeof(UINT32) * 37);
}
//now the data is discarded and when saved, as 6.27, you won't have this problem!
for ( i = 0; i < iWorldSize; i++ ) {
// Read room information, 2 byte for new files
if ( ubMinorMapVersion < 29 ) {
SKIPDATA(pBuffer, pBuffer, sizeof(INT8));
}
else {
SKIPDATA(pBuffer, pBuffer, sizeof(UINT16));
}
}
// Load out item information
if ( uiFlags & MAP_WORLDITEMS_SAVED )
{
WORLDITEM dummyItem;
UINT32 uiNumWorldItems;
//Read the number of items that were saved in the map.
LOADDATA(&uiNumWorldItems, pBuffer, 4);
if ( gTacticalStatus.uiFlags & LOADING_SAVED_GAME && !gfEditMode )
{ //The sector has already been visited. The items are saved in a different format that will be
//loaded later on. So, all we need to do is skip the data entirely.
if ( dMajorMapVersion >= 6.0 && ubMinorMapVersion > 26 ) {
for ( unsigned int x = 0; x < uiNumWorldItems; ++x )
{
//ADB WORLDITEM's size on disk is unknown
dummyItem.Load(&pBuffer, dMajorMapVersion, ubMinorMapVersion);
}
}
else
{
pBuffer += sizeof(OLD_WORLDITEM_101) * uiNumWorldItems;
}
}
else for ( i = 0; i < uiNumWorldItems; i++ )
{
dummyItem.Load(&pBuffer, dMajorMapVersion, ubMinorMapVersion);
}
}
if ( uiFlags & MAP_AMBIENTLIGHTLEVEL_SAVED )
{
//Ambient light levels are only saved in underground levels
SKIPDATA(pBuffer, pBuffer, sizeof(BOOLEAN));
SKIPDATA(pBuffer, pBuffer, sizeof(BOOLEAN));
SKIPDATA(pBuffer, pBuffer, sizeof(UINT8));
}
if ( uiFlags & MAP_WORLDLIGHTS_SAVED )
{
SGPPaletteEntry LColors[3];
UINT8 ubNumColors;
UINT16 usNumLights;
CHAR8 str[30];
UINT8 ubStrLen;
LIGHT_SPRITE TmpLight;
// read in the light colors!
LOADDATA(&ubNumColors, pBuffer, 1);
LOADDATA(LColors, pBuffer, sizeof(SGPPaletteEntry) * ubNumColors);
LOADDATA(&usNumLights, pBuffer, 2);
for ( cnt = 0; cnt < usNumLights; cnt++ )
{
LOADDATA(&TmpLight, pBuffer, sizeof(LIGHT_SPRITE));
LOADDATA(&ubStrLen, pBuffer, 1);
if ( ubStrLen )
{
LOADDATA(str, pBuffer, ubStrLen);
}
}
}
gMapInformationAutoResolve.Load(&pBuffer, dMajorMapVersion);
// NOTE! We need these!
// Translation routine for map grid numbers
gMapTrn.GetTrnCnt(gMapInformationAutoResolve.sCenterGridNo);
gMapTrn.GetTrnCnt(gMapInformationAutoResolve.sIsolatedGridNo);
gMapTrn.GetTrnCnt(gMapInformationAutoResolve.sNorthGridNo);
gMapTrn.GetTrnCnt(gMapInformationAutoResolve.sEastGridNo);
gMapTrn.GetTrnCnt(gMapInformationAutoResolve.sWestGridNo);
gMapTrn.GetTrnCnt(gMapInformationAutoResolve.sSouthGridNo);
// Remove this rather large chunk of memory from the system now!
MemFree(pBufferHead);
MemFree(bCounts);
return(TRUE);
}
//****************************************************************************************
//
// Deletes everything then re-creates the world with simple ground tiles
+2
View File
@@ -281,6 +281,7 @@ typedef struct
// World Data
extern MAP_ELEMENT *gpWorldLevelData;
extern MAP_ELEMENT* gpWorldLevelDataAutoResolve;
extern UINT8 (*gubWorldMovementCosts)[MAXDIR][2];//dnl ch43 260909
//dnl ch44 290909 Translation routine
@@ -339,6 +340,7 @@ BOOLEAN NewWorld( INT32 nMapRows, INT32 nMapCols );
BOOLEAN SaveWorld(const STR8 puiFilename, FLOAT dMajorMapVersion=MAJOR_MAP_VERSION, UINT8 ubMinorMapVersion=MINOR_MAP_VERSION);//dnl ch33 150909
BOOLEAN LoadWorld(const STR8 puiFilename, FLOAT* pMajorMapVersion=NULL, UINT8* pMinorMapVersion=NULL);//dnl ch44 290909
BOOLEAN LoadWorldInfoForAutoResolve(const STR8 puiFilename, INT32& iRowSize, INT32& iColSize);
void CompileWorldMovementCosts(void);//dnl ch56 151009
void RecompileLocalMovementCosts( INT32 sCentreGridNo );
+58 -47
View File
@@ -199,7 +199,10 @@ WRAPPED_STRING *LineWrap(INT32 iFont, UINT16 usLineWidthPixels, UINT16 *pusLineW
usCurrentWidthPixels = usCurrentWidthPixels + WFStringPixLength( OneChar, iFont);
//If we are at the end of the string
if(TempString[ usCurIndex ] == 0)
//Juqi: Add NEWLINE_CHAR detect
// NEWLINE_CHAR "±" is only used to handle Chinese ITMES.XML file.
if (TempString[ usCurIndex ] == 0 && !fNewLine)
{
//get to next WrappedString structure
pWrappedString = &FirstWrappedString;
@@ -224,10 +227,13 @@ WRAPPED_STRING *LineWrap(INT32 iFont, UINT16 usLineWidthPixels, UINT16 *pusLineW
}
if( (g_lang != i18n::Lang::zh && usCurrentWidthPixels > usLineWidthPixels)
||
(g_lang == i18n::Lang::zh && usCurrentWidthPixels > usLineWidthPixels
//Juqi: Allow manual line breaks to be added in XML,
// rather than relying solely on width for automatic line breaks.
if((usCurrentWidthPixels > usLineWidthPixels || fNewLine)
&&
((g_lang != i18n::Lang::zh)
||
(g_lang == i18n::Lang::zh
&& TempString[usCurIndex] != L''
&& TempString[usCurIndex] != L''
&& TempString[usCurIndex] != L''
@@ -239,8 +245,9 @@ WRAPPED_STRING *LineWrap(INT32 iFont, UINT16 usLineWidthPixels, UINT16 *pusLineW
&& TempString[usCurIndex] != L''
&& TempString[usCurIndex] != L')'
&& TempString[usCurIndex] != L''
)//||(DestString[ usDestIndex ]==NEWLINE_CHAR )||(fNewLine))
)
))
)
{
//if an error has occured, and the string is too long
@@ -251,51 +258,55 @@ WRAPPED_STRING *LineWrap(INT32 iFont, UINT16 usLineWidthPixels, UINT16 *pusLineW
// Fix really long unbroken strings, the above code dosent work for it
usLastMaxWidthIndex = usDestIndex;
//Go back to begining of word
while(
(g_lang != i18n::Lang::zh && DestString[ usDestIndex ] != L' ' && usCurIndex > 0 && usDestIndex > 0)
||
(g_lang == i18n::Lang::zh && DestString[ usDestIndex ] != L' ' && usCurIndex > 0 && usDestIndex > 0 && DestString[usDestIndex] < 255))
{
OneChar[0] = DestString[ usDestIndex ];
//Juqi: if NEWLINE_CHAR, don't go back
if (!fNewLine)
{
//Go back to begining of word
while(
(g_lang != i18n::Lang::zh && DestString[ usDestIndex ] != L' ' && usCurIndex > 0 && usDestIndex > 0)
||
(g_lang == i18n::Lang::zh && DestString[ usDestIndex ] != L' ' && usCurIndex > 0 && usDestIndex > 0 && DestString[usDestIndex] < 255))
{
OneChar[0] = DestString[ usDestIndex ];
usCurrentWidthPixels = usCurrentWidthPixels - WFStringPixLength( OneChar, iFont);
usCurrentWidthPixels = usCurrentWidthPixels - WFStringPixLength( OneChar, iFont);
usCurIndex--;
usDestIndex--;
}
if (g_lang == i18n::Lang::zh && DestString[usDestIndex] > 255)
{
if (DestString[usDestIndex] == L''
|| DestString[usDestIndex] == L','
|| DestString[usDestIndex] == L''
|| DestString[usDestIndex] == L''
|| DestString[usDestIndex] == L''
|| DestString[usDestIndex] == L''
|| DestString[usDestIndex] == L''
|| DestString[usDestIndex] == L''
|| DestString[usDestIndex] == L'?'
|| DestString[usDestIndex] == L''
|| DestString[usDestIndex] == L')'
|| DestString[usDestIndex] == L'')
{usDestIndex++;}
else
{usCurIndex--;}
}
usCurIndex--;
usDestIndex--;
}
if (g_lang == i18n::Lang::zh && DestString[usDestIndex] > 255)
{
if (DestString[usDestIndex] == L''
|| DestString[usDestIndex] == L','
|| DestString[usDestIndex] == L''
|| DestString[usDestIndex] == L''
|| DestString[usDestIndex] == L''
|| DestString[usDestIndex] == L''
|| DestString[usDestIndex] == L''
|| DestString[usDestIndex] == L''
|| DestString[usDestIndex] == L'?'
|| DestString[usDestIndex] == L''
|| DestString[usDestIndex] == L')'
|| DestString[usDestIndex] == L'')
{usDestIndex++;}
else
{usCurIndex--;}
}
usEndIndex = usDestIndex;
usEndIndex = usDestIndex;
// OJW - 20090427
// Fix really long unbroken strings
if( usEndIndex <= 0 )
{
usEndIndex = usLastMaxWidthIndex;
usDestIndex = usLastMaxWidthIndex;
usCurIndex += usLastMaxWidthIndex - 1;
}
// OJW - 20090427
// Fix really long unbroken strings
if( usEndIndex <= 0 )
{
usEndIndex = usLastMaxWidthIndex;
usDestIndex = usLastMaxWidthIndex;
usCurIndex += usLastMaxWidthIndex - 1;
}
// put next line into temp buffer
DestString[usEndIndex] = 0;
// put next line into temp buffer
DestString[usEndIndex] = 0;
} //Juqi: endif
//get to next WrappedString structure
pWrappedString = &FirstWrappedString;
+148 -143
View File
@@ -2361,6 +2361,11 @@ CHAR16 Message[][STRING_LENGTH] =
L"没有能够训练的民兵。", //L"No militia that can be drilled present.",
L"%s 已经完全的探索了 %s。", //L"%s has fully explored %s."
// The first %s is a merc name and the second %s is an item name
L"%s 排除了 %s 的故障。", //L"%s unjammed %s.",
L"%s 未能排除 %s 的故障。", //L"%s failed to unjam %s.",
L"%s 的行动点数不足以排除 %s 的故障。", //L"%s does not have enough APs to unjam %s.",
};
// the country and its noun in the game
@@ -7551,7 +7556,7 @@ STR16 gzLateLocalizedString[] =
L"%s用完了医药箱里的药品!", //"%s ran out of medical kits!",
L"%s没有所需技能来医疗他人!", //"%s lacks the necessary skill to doctor anyone!",
L"%s用完工具箱里的工具!", //"%s ran out of tool kits!",
L"%s没有所需技能来修理物品!", //"%s lacks the necessary skill to repair anything!",
L"%s没有所需技能或属性来修理物品!", //"%s lacks the necessary skill to repair anything!",
//44-45
L"修理时间", //L"Repair Time",
@@ -9385,7 +9390,7 @@ STR16 szBackgroundText_Value[]=
L" %s%d% 对人员治疗疾病的效率 \n", //L" %s%d%% effectiveness at treating population against diseases\n",
L" 能够发现%d格之内的脚印 \n", //L"Can spot tracks up to %d tiles away\n",
L" %s%d% 被伏击时的初始距离 \n", //L" %s%d%% initial distance to enemy in ambush\n",
L" %s%d% 几率回避攻击 \n", //L" %s%d%% chance to evade snake attacks\n",
L" %s%d% 闪避蛇类攻击 \n", //L" %s%d%% chance to evade snake attacks\n",
L" 对某些其他背景的厌恶 \n", //L" dislikes some other backgrounds\n",
L" 吸烟者", //L"Smoker",
@@ -9482,8 +9487,8 @@ STR16 szNationalityText[]=
L"古巴人", // 5
L"丹麦人",
L"法国人",
L"",
L"Tracona", // (UB takes place in Tracona)
L"罗斯",
L"特拉科纳", // (UB takes place in Tracona)
L"瑞士人", // 10
L"牙买加人",
L"波兰人",
@@ -9492,103 +9497,103 @@ STR16 szNationalityText[]=
L"南非人", // 15
L"匈牙利人",
L"苏格兰人",
L"Arulco",
L"阿鲁科",
L"德国人",
L"非洲人", // 20
L"意大利人",
L"荷兰人",
L"罗马亚人",
L"Metavira",
L"罗马亚人",
L"梅塔维拉",
// newly added from here on
L"Afghan", // 25
L"Albanian",
L"Argentinian",
L"Armenian",
L"Azerbaijani",
L"Bangladeshi ", // 30
L"阿富汗人", // 25
L"阿尔巴尼亚人",
L"阿根廷人",
L"亚美尼亚人",
L"阿塞拜疆人",
L"孟加拉国人", // 30
L"白俄罗斯人",
L"比利时人",
L"Beninese",
L"Bolivian",
L"Bosnian", // 35
L"贝宁人",
L"玻利维亚人",
L"波斯尼亚人", // 35
L"巴西人",
L"保加利亚人",
L"Cambodian",
L"Chadian",
L"Chilean", // 40
L"Columbian",
L"Congolese",
L"Croatian",
L"Ecuadorian",
L"Egyptian", // 45
L"English",
L"Eritrean",
L"柬埔寨人",
L"乍得人",
L"智利人", // 40
L"哥伦比亚人",
L"刚果人",
L"克罗地亚人",
L"厄瓜多尔人",
L"埃及人", // 45
L"英格兰人",
L"厄立特里亚人",
L"爱沙尼亚人",
L"Ethiopian",
L"Filipino", // 50
L"埃塞俄比亚人",
L"菲律宾人", // 50
L"芬兰人",
L"Georgian",
L"格鲁吉亚人",
L"希腊人",
L"Guatemalan",
L"Haitian", // 55
L"Honduran",
L"危地马拉人",
L"海地人", // 55
L"洪都拉斯人",
L"印度人",
L"Indonesian",
L"印度尼西亚人",
L"伊朗人",
L"伊拉克人", // 60
L"Islandic",
L"冰岛人",
L"以色列人",
L"日本人",
L"Jordanian",
L"Kazakhstani", // 65
L"Korean",
L"Kyrgyzstani",
L"Laotian",
L"Latvian",
L"Lebanese", // 70
L"Lithuanian",
L"Lybian",
L"Macedonian",
L"Malaysian",
L"约旦人",
L"哈萨克斯坦人", // 65
L"韩国人和朝鲜人",
L"吉尔吉斯斯坦人",
L"老挝人",
L"拉脱维亚人",
L"黎巴嫩人", // 70
L"立陶宛人",
L"利比亚人",
L"马其顿人",
L"马来西亚人",
L"墨西哥人", // 75
L"Mongolian",
L"Moroccan",
L"Mozambican",
L"Myanma",
L"Namibian", // 80
L"Nicaraguan",
L"蒙古人",
L"摩洛哥人",
L"莫桑比克人",
L"缅甸人",
L"纳米比亚人", // 80
L"尼加拉瓜人",
L"尼日利亚人",
L"Nigerien",
L"尼日尔人",
L"挪威人",
L"Pakistani", // 85
L"Panamanian",
L"巴基斯坦人", // 85
L"巴拿马人",
L"葡萄牙人",
L"Rwandanese",
L"Salvadoran",
L"Saudi", // 90
L"卢旺达人",
L"萨尔瓦多人",
L"沙特人", // 90
L"塞尔维亚人",
L"Slovakian",
L"Slovenian",
L"Somali",
L"斯洛伐克人",
L"斯洛文尼亚人",
L"索马里人",
L"西班牙人", // 95
L"Sudanese",
L"苏丹人",
L"瑞典人",
L"叙利亚人",
L"Thai",
L"Togolese", // 100
L"Tunisian",
L"泰国人",
L"多哥人", // 100
L"突尼斯人",
L"土耳其人",
L"Ugandan",
L"Ukrainian",
L"Uruguayan", // 105
L"Uzbekistani",
L"乌干达人",
L"乌克兰人",
L"乌拉圭人", // 105
L"乌兹别克斯坦人",
L"委内瑞拉人",
L"Vietnamese",
L"Welsh",
L"Yemeni", // 110
L"Zamundan", // Zamunda
L"Zimbabwean",
L"越南人",
L"威尔士人",
L"也门人", // 110
L"扎蒙达人", // Zamunda
L"津巴布韦人",
};
STR16 szNationalityTextAdjective[] =
@@ -9601,8 +9606,8 @@ STR16 szNationalityTextAdjective[] =
L"古巴人", // 5
L"丹麦人",
L"法国人",
L"",
L"traconia" // UB takes place in Tracona
L"罗斯",
L"特拉科纳" // UB takes place in Tracona
L"瑞士人", // 10
L"牙买加人",
L"波兰人",
@@ -9611,103 +9616,103 @@ STR16 szNationalityTextAdjective[] =
L"南非人", // 15
L"匈牙利人",
L"苏格兰人",
L"Arulco",
L"阿鲁科",
L"德国人",
L"非洲人", // 20
L"意大利人",
L"荷兰人",
L"罗马亚人",
L"Metavira",
L"罗马亚人",
L"梅塔维拉",
// newly added from here on
L"afghans", // 25
L"albanians",
L"argentinians",
L"armenians",
L"azerbaijani",
L"bangladeshi", // 30
L"阿富汗人", // 25
L"阿尔巴尼亚人",
L"阿根廷人",
L"亚美尼亚人",
L"阿塞拜疆人",
L"孟加拉国人", // 30
L"白俄罗斯人",
L"比利时人",
L"beninese",
L"bolivians",
L"bosnians", // 35
L"贝宁人",
L"玻利维亚人",
L"波斯尼亚人", // 35
L"巴西人",
L"保加利亚人",
L"cambodians",
L"chadians",
L"chileans", // 40
L"columbians",
L"congolese",
L"croatians",
L"ecuadorians",
L"egyptians", // 45
L"englishmen",
L"eritreans",
L"柬埔寨人",
L"乍得人",
L"智利人", // 40
L"哥伦比亚人",
L"刚果人",
L"克罗地亚人",
L"厄瓜多尔人",
L"埃及人", // 45
L"英格兰人",
L"厄立特里亚人",
L"爱沙尼亚人",
L"ethiopians",
L"filipinos", // 50
L"埃塞俄比亚人",
L"菲律宾人", // 50
L"芬兰人",
L"georgians",
L"格鲁吉亚人",
L"希腊人",
L"guatemalans",
L"haitians", // 55
L"hondurans",
L"危地马拉人",
L"海地人", // 55
L"洪都拉斯人",
L"印度人",
L"indonesians",
L"印度尼西亚人",
L"伊朗人",
L"伊拉克人", // 60
L"islandics",
L"冰岛人",
L"以色列人",
L"日本人",
L"jordanians",
L"kazakhstani", // 65
L"koreans",
L"kyrgyzstani",
L"laotians",
L"latvians",
L"lebanese", // 70
L"lithuanians",
L"lybians",
L"macedonians",
L"malaysians",
L"约旦人",
L"哈萨克斯坦人", // 65
L"韩国人和朝鲜人",
L"吉尔吉斯斯坦人",
L"老挝人",
L"拉脱维亚人",
L"黎巴嫩人", // 70
L"立陶宛人",
L"利比亚人",
L"马其顿人",
L"马来西亚人",
L"墨西哥人", // 75
L"mongolians",
L"moroccans",
L"mozambicans",
L"myanmarians",
L"namibians", // 80
L"nicaraguans",
L"蒙古人",
L"摩洛哥人",
L"莫桑比克人",
L"缅甸人",
L"纳米比亚人", // 80
L"尼加拉瓜人",
L"尼日利亚人",
L"nigeriens",
L"尼日尔人",
L"挪威人",
L"巴基斯坦人", // 85
L"panamanians",
L"巴拿马人",
L"葡萄牙人",
L"rwandanese",
L"salvadorans",
L"saudis", // 90
L"卢旺达人",
L"萨尔瓦多人",
L"沙特人", // 90
L"塞尔维亚人",
L"slovakians",
L"slovenians",
L"somali",
L"斯洛伐克人",
L"斯洛文尼亚人",
L"索马里人",
L"西班牙人", // 95
L"sudanese",
L"苏丹人",
L"瑞典人",
L"叙利亚人",
L"thais",
L"togolese", // 100
L"tunisians",
L"泰国人",
L"多哥人", // 100
L"突尼斯人",
L"土耳其人",
L"ugandans",
L"ukrainians",
L"uruguayans", // 105
L"uzbekistani",
L"乌干达人",
L"乌克兰人",
L"乌拉圭人", // 105
L"乌兹别克斯坦人",
L"委内瑞拉人",
L"vietnamese",
L"welshs",
L"yemenites", // 110
L"zamundans", // Zamunda
L"zimbabweans",
L"越南人",
L"威尔士人",
L"也门人", // 110
L"扎蒙达人", // Zamunda
L"津巴布韦人",
};
// special text used if we do not hate any nation (value of -1)
+5
View File
@@ -2360,6 +2360,11 @@ CHAR16 Message[][STRING_LENGTH] =
L"No militia that can be drilled present.",
L"%s has fully explored %s.", // TODO.Translate
// The first %s is a merc name and the second %s is an item name
L"%s unjammed %s.",
L"%s failed to unjam %s.",
L"%s does not have enough APs to unjam %s."
};
// the country and its noun in the game
+5
View File
@@ -2361,6 +2361,11 @@ CHAR16 Message[][STRING_LENGTH] =
L"No militia that can be drilled present.",
L"%s has fully explored %s.",
// The first %s is a merc name and the second %s is an item name
L"%s unjammed %s.",
L"%s failed to unjam %s.",
L"%s does not have enough APs to unjam %s."
};
// the country and its noun in the game
+5
View File
@@ -2369,6 +2369,11 @@ CHAR16 Message[][STRING_LENGTH] =
L"No militia that can be drilled present.",
L"%s has fully explored %s.", // TODO.Translate
// The first %s is a merc name and the second %s is an item name
L"%s unjammed %s.",
L"%s failed to unjam %s.",
L"%s does not have enough APs to unjam %s."
};
// the country and its noun in the game // TODO.Translate
+5
View File
@@ -2403,6 +2403,11 @@ CHAR16 Message[][STRING_LENGTH] =
L"No militia that can be drilled present.",
L"%s hat %s vollständig erkundet.",
// The first %s is a merc name and the second %s is an item name
L"%s unjammed %s.",
L"%s failed to unjam %s.",
L"%s does not have enough APs to unjam %s."
};
// the country and its noun in the game
+5
View File
@@ -2355,6 +2355,11 @@ CHAR16 Message[][STRING_LENGTH] =
L"No militia that can be drilled present.",
L"%s has fully explored %s.", // TODO.Translate
// The first %s is a merc name and the second %s is an item name
L"%s unjammed %s.",
L"%s failed to unjam %s.",
L"%s does not have enough APs to unjam %s."
};
// the country and its noun in the game
+2 -2
View File
@@ -396,8 +396,8 @@ STR16 gzIMPMajorTraitsHelpTextsSurvival[] =
L"疾病抗性 %s%d%%\n",//L" %s%d%% disease resistance\n",
L"食物消耗 %s%d%%\n",//L" %s%d%% food consumption\n",
L"耗 %s%d%%\n",//L" %s%d%% water consumption\n",
L"回避几率 +%d%%\n", //L"+%d%% snake evasion\n",
L"耗 %s%d%%\n",//L" %s%d%% water consumption\n",
L"闪避蛇类 +%d%%\n", //L"+%d%% snake evasion\n",
L"迷彩涂装效果 +%d%%\n",// L"+%d%s camouflage effectiveness\n",
};
+5
View File
@@ -2367,6 +2367,11 @@ CHAR16 Message[][STRING_LENGTH] =
L"No militia that can be drilled present.",
L"%s has fully explored %s.", // TODO.Translate
// The first %s is a merc name and the second %s is an item name
L"%s unjammed %s.",
L"%s failed to unjam %s.",
L"%s does not have enough APs to unjam %s."
};
// the country and its noun in the game
+5
View File
@@ -2361,6 +2361,11 @@ CHAR16 Message[][STRING_LENGTH] =
L"No militia that can be drilled present.",
L"%s has fully explored %s.", // TODO.Translate
// The first %s is a merc name and the second %s is an item name
L"%s unjammed %s.",
L"%s failed to unjam %s.",
L"%s does not have enough APs to unjam %s."
};
// the country and its noun in the game
+4
View File
@@ -612,6 +612,10 @@ enum
STR_ASSIGNMENT_EXPLORATION_DONE,
STR_UNJAMMED,
STR_FAILED_UNJAM,
STR_NO_AP_NO_UNJAM,
TEXT_NUM_STR_MESSAGE,
};
+19 -5
View File
@@ -836,8 +836,11 @@ void Load32bppPNGImage(HIMAGE hImage, png::png_bytepp rows, png::png_infop info)
hImage->p32BPPData = (UINT32*)MemAlloc(SIZE);
if(!hImage->p32BPPData)
{
CHAR8 errorText[512];
sprintf(errorText, "Bad allocation loading image. Filename: %s", hImage->ImageFile);
MemFree(hImage->pETRLEObject);
SGP_THROW(L"bad alloc");
SGP_THROW(errorText);
}
memset(hImage->p32BPPData, 0, SIZE);
@@ -878,8 +881,11 @@ void Load24bppPNGImage(HIMAGE hImage, png::png_bytepp rows, png::png_infop info)
hImage->p16BPPData = (UINT16*)MemAlloc(SIZE);
if(!hImage->p16BPPData)
{
CHAR8 errorText[512];
sprintf(errorText, "Bad allocation loading image. Filename: %s", hImage->ImageFile);
MemFree(hImage->pETRLEObject);
SGP_THROW(L"bad alloc");
SGP_THROW(errorText);
}
memset(hImage->p16BPPData, 0, SIZE);
@@ -899,11 +905,15 @@ void Load24bppPNGImage(HIMAGE hImage, png::png_bytepp rows, png::png_infop info)
void LoadPalettedPNGImage(HIMAGE hImage, png::png_bytepp rows, png::png_infop info)
{
CHAR8 errorText[512];
UINT32 SIZE = info->height * info->width * sizeof(UINT8);
UINT8 *data = (UINT8*)MemAlloc(SIZE);
if(!data)
{
SGP_THROW(L"bad alloc");
sprintf(errorText, "Bad allocation loading image. Filename: %s", hImage->ImageFile);
MemFree(hImage->pETRLEObject);
SGP_THROW(errorText);
}
memset(data,0,SIZE);
for(unsigned int i = 0; i < info->height; ++i)
@@ -915,8 +925,10 @@ void LoadPalettedPNGImage(HIMAGE hImage, png::png_bytepp rows, png::png_infop in
hImage->pETRLEObject = (ETRLEObject*)MemAlloc(hImage->usNumberOfObjects * sizeof(ETRLEObject));
if(!hImage->pETRLEObject)
{
sprintf(errorText, "Bad allocation for ETRLEObject. Filename: %s", hImage->ImageFile);
MemFree(data);
SGP_THROW(L"bad alloc");
SGP_THROW(errorText);
}
memset(hImage->pETRLEObject,0, hImage->usNumberOfObjects * sizeof(ETRLEObject));
@@ -931,9 +943,11 @@ void LoadPalettedPNGImage(HIMAGE hImage, png::png_bytepp rows, png::png_infop in
hImage->p8BPPData = (UINT8*)MemAlloc( RESIZE );
if(!hImage->p8BPPData)
{
sprintf(errorText, "Bad allocation for image pixel data. Filename: %s", hImage->ImageFile);
MemFree(hImage->pETRLEObject);
MemFree(data);
SGP_THROW(L"bad alloc");
SGP_THROW(errorText);
}
UINT8 *compressed = hImage->p8BPPData;
memset(hImage->p8BPPData,0,RESIZE);