From 6031257dcd0bebe7bb26e157478edca4b1339759 Mon Sep 17 00:00:00 2001 From: Flugente Date: Sun, 17 Sep 2017 22:16:30 +0000 Subject: [PATCH] New feature: mercs can drag people and corpses Requires GameDir >= r2386. For more info, see http://thepit.ja-galaxy-forum.com/index.php?t=msg&th=23508&goto=350989&#msg_350989 git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@8474 3b4a5df2-a311-0410-b5c6-a8a6f20db521 --- GameSettings.cpp | 3 +- GameSettings.h | 3 +- GameVersion.cpp | 18 +-- GameVersion.h | 3 +- SaveLoadGame.cpp | 12 +- Tactical/Faces.cpp | 9 +- Tactical/Items.cpp | 20 ++- Tactical/Items.h | 2 +- Tactical/Overhead.cpp | 16 +- Tactical/PATHAI.cpp | 27 ++++ Tactical/Points.cpp | 17 ++- Tactical/Rotting Corpses.cpp | 45 +++++- Tactical/Rotting Corpses.h | 5 + Tactical/SkillMenu.cpp | 93 +++++++++++- Tactical/SkillMenu.h | 11 ++ Tactical/Soldier Control.cpp | 283 ++++++++++++++++++++++++++++++++++- Tactical/Soldier Control.h | 25 +++- Utils/Text.h | 4 + Utils/_ChineseText.cpp | 16 +- Utils/_DutchText.cpp | 16 +- Utils/_EnglishText.cpp | 10 +- Utils/_FrenchText.cpp | 16 +- Utils/_GermanText.cpp | 16 +- Utils/_ItalianText.cpp | 16 +- Utils/_PolishText.cpp | 16 +- Utils/_RussianText.cpp | 16 +- 26 files changed, 621 insertions(+), 97 deletions(-) diff --git a/GameSettings.cpp b/GameSettings.cpp index fafb1b30..7d046381 100644 --- a/GameSettings.cpp +++ b/GameSettings.cpp @@ -2060,7 +2060,7 @@ void LoadGameExternalOptions() gGameExternalOptions.fEnemyHeliActive = iniReader.ReadBoolean( "Enemy Helicopter Settings", "ENEMYHELI_ACTIVE", TRUE ); gGameExternalOptions.usEnemyHeliMinimumProgress = iniReader.ReadInteger( "Enemy Helicopter Settings", "ENEMYHELI_DEFINITE_UNLOCK_AT_PROGRESS", 30, 0, 100 ); - gGameExternalOptions.gEnemyHeliMaxHP = iniReader.ReadInteger( "Enemy Helicopter Settings", "ENEMYHELI_HP", 100, 1, 500 ); + gGameExternalOptions.gEnemyHeliMaxHP = iniReader.ReadInteger( "Enemy Helicopter Settings", "ENEMYHELI_HP", 100, 1, 255 ); gGameExternalOptions.gEnemyHeliTimePerHPRepair = iniReader.ReadInteger( "Enemy Helicopter Settings", "ENEMYHELI_HP_REPAIRTIME", 6, 1, 20 ); gGameExternalOptions.gEnemyHeliCostPerRepair1HP = iniReader.ReadInteger( "Enemy Helicopter Settings", "ENEMYHELI_HP_COST", 200, 10, 1000 ); gGameExternalOptions.gEnemyHeliMaxFuel = iniReader.ReadInteger( "Enemy Helicopter Settings", "ENEMYHELI_FUEL", 50, 25, 200 ); @@ -3151,6 +3151,7 @@ void LoadItemSettings() // ------------ MISC MODIFIERS -------------- gItemSettings.fShieldMovementAPCostModifier = iniReader.ReadFloat ("Misc Settings", "SHIELD_MOVEMENT_APCOST_MODIFIER", 1.7f, 1.0f, 10.0f ); + gItemSettings.fDragAPCostModifier = iniReader.ReadFloat ("Misc Settings", "DRAG_MOVEMENT_APCOST_MODIFIER", 1.5f, 1.0f, 10.0f ); } INT16 DynamicAdjustAPConstants(INT16 iniReadValue, INT16 iniDefaultValue, BOOLEAN reverse) diff --git a/GameSettings.h b/GameSettings.h index e93964f6..f880e420 100644 --- a/GameSettings.h +++ b/GameSettings.h @@ -693,7 +693,7 @@ typedef struct BOOLEAN fEnemyHeliActive; UINT8 usEnemyHeliMinimumProgress; - UINT16 gEnemyHeliMaxHP; + UINT8 gEnemyHeliMaxHP; UINT16 gEnemyHeliTimePerHPRepair; INT32 gEnemyHeliCostPerRepair1HP; UINT16 gEnemyHeliMaxFuel; @@ -2379,6 +2379,7 @@ typedef struct // ------------ MISC MODIFIERS -------------- // Flugente FLOAT fShieldMovementAPCostModifier; // movement AP costs are multiplied with this while a shield is equipped + FLOAT fDragAPCostModifier; }ITEM_SETTINGS; diff --git a/GameVersion.cpp b/GameVersion.cpp index 8034ad55..473f32bd 100644 --- a/GameVersion.cpp +++ b/GameVersion.cpp @@ -15,9 +15,9 @@ #ifdef JA2EDITOR #ifdef JA2UB - CHAR16 zVersionLabel[256] = { L"Unfinished Business - Map Editor v1.13.8440 (Development Build)" }; + CHAR16 zVersionLabel[256] = { L"Unfinished Business - Map Editor v1.13.8474 (Development Build)" }; #else - CHAR16 zVersionLabel[256] = { L"Map Editor v1.13.8440 (Development Build)" }; + CHAR16 zVersionLabel[256] = { L"Map Editor v1.13.8474 (Development Build)" }; #endif // ------------------------------ @@ -27,11 +27,11 @@ //DEBUG BUILD VERSION #ifdef JA2UB - CHAR16 zVersionLabel[256] = { L"Debug: Unfinished Business - v1.13.8440 (Development Build)" }; + CHAR16 zVersionLabel[256] = { L"Debug: Unfinished Business - v1.13.8474 (Development Build)" }; #elif defined (JA113DEMO) - CHAR16 zVersionLabel[256] = { L"Debug: JA2 Demo - v1.13.8440 (Development Build)" }; + CHAR16 zVersionLabel[256] = { L"Debug: JA2 Demo - v1.13.8474 (Development Build)" }; #else - CHAR16 zVersionLabel[256] = { L"Debug: v1.13.8440 (Development Build)" }; + CHAR16 zVersionLabel[256] = { L"Debug: v1.13.8474 (Development Build)" }; #endif #elif defined CRIPPLED_VERSION @@ -46,16 +46,16 @@ //RELEASE BUILD VERSION #ifdef JA2UB - CHAR16 zVersionLabel[256] = { L"Release Unfinished Business - v1.13.8440 (Development Build)" }; + CHAR16 zVersionLabel[256] = { L"Release Unfinished Business - v1.13.8474 (Development Build)" }; #elif defined (JA113DEMO) - CHAR16 zVersionLabel[256] = { L"Release JA2 Demo - v1.13.8440 (Development Build)" }; + CHAR16 zVersionLabel[256] = { L"Release JA2 Demo - v1.13.8474 (Development Build)" }; #else - CHAR16 zVersionLabel[256] = { L"Release v1.13.8440 (Development Build)" }; + CHAR16 zVersionLabel[256] = { L"Release v1.13.8474 (Development Build)" }; #endif #endif -CHAR8 czVersionNumber[16] = { "Build 17.08.06" }; //YY.MM.DD +CHAR8 czVersionNumber[16] = { "Build 17.09.16" }; //YY.MM.DD CHAR16 zTrackingNumber[16] = { L"Z" }; // SAVE_GAME_VERSION is defined in header, change it there diff --git a/GameVersion.h b/GameVersion.h index d7c0ee59..0132a7df 100644 --- a/GameVersion.h +++ b/GameVersion.h @@ -21,6 +21,7 @@ extern CHAR16 zTrackingNumber[16]; // Keeps track of the saved game version. Increment the saved game version whenever // you will invalidate the saved game file +#define DRAGPERSONS 174 // Flugente: we can drag people and corpses now #define SEPARATE_VOICESETS 173 // Flugente: voice sets are now separate from profile slots, and we can have many more of them #define HACKABLE_SAMS 172 // Flugente: SAM sites now have a status for hacking #define LUA_MODDERDATA 171 // Flugente: modders can set and use data in an exclusive array @@ -92,7 +93,7 @@ extern CHAR16 zTrackingNumber[16]; #define AP100_SAVEGAME_DATATYPE_CHANGE 105 // Before this, we didn't have the 100AP structure changes #define NIV_SAVEGAME_DATATYPE_CHANGE 102 // Before this, we used the old structure system -#define SAVE_GAME_VERSION SEPARATE_VOICESETS +#define SAVE_GAME_VERSION DRAGPERSONS //#define RUSSIANGOLD #ifdef __cplusplus diff --git a/SaveLoadGame.cpp b/SaveLoadGame.cpp index 470733ee..8a48ad0c 100644 --- a/SaveLoadGame.cpp +++ b/SaveLoadGame.cpp @@ -2208,8 +2208,16 @@ BOOLEAN SOLDIERTYPE::Load(HWFILE hFile) numBytesRead = ReadFieldByField(hFile, &this->bScopeMode, sizeof(bScopeMode), sizeof(INT8), numBytesRead); numBytesRead = ReadFieldByField(hFile, &this->ubMilitiaAssists, sizeof(ubMilitiaAssists), sizeof(UINT8), numBytesRead ); numBytesRead = ReadFieldByField(hFile, &this->sNonNPCTraderID, sizeof(sNonNPCTraderID), sizeof(INT8), numBytesRead ); - numBytesRead = ReadFieldByField(hFile, &this->bUnusedINT8_3, sizeof(bUnusedINT8_3), sizeof(INT8), numBytesRead ); - numBytesRead = ReadFieldByField(hFile, &this->bUnusedINT16_4, sizeof(bUnusedINT16_4), sizeof(INT16), numBytesRead ); + //numBytesRead = ReadFieldByField(hFile, &this->bUnusedINT8_3, sizeof(bUnusedINT8_3), sizeof(INT8), numBytesRead ); + numBytesRead = ReadFieldByField(hFile, &this->usDragPersonID, sizeof(usDragPersonID), sizeof(UINT8), numBytesRead ); + //numBytesRead = ReadFieldByField(hFile, &this->bUnusedINT16_4, sizeof(bUnusedINT16_4), sizeof(INT16), numBytesRead ); + numBytesRead = ReadFieldByField(hFile, &this->sDragCorpseID, sizeof(sDragCorpseID), sizeof(INT16), numBytesRead ); + + if ( guiCurrentSaveGameVersion < DRAGPERSONS ) + { + this->CancelDrag(); + } + numBytesRead = ReadFieldByField(hFile, &this->bUnusedINT16_5, sizeof(bUnusedINT16_5), sizeof(INT16), numBytesRead ); numBytesRead = ReadFieldByField(hFile, &this->bExtraStrength, sizeof(bExtraStrength), sizeof(INT16), numBytesRead); diff --git a/Tactical/Faces.cpp b/Tactical/Faces.cpp index d40f0257..55f9dbdd 100644 --- a/Tactical/Faces.cpp +++ b/Tactical/Faces.cpp @@ -2267,7 +2267,14 @@ void HandleRenderFaceAdjustments( FACETYPE *pFace, BOOLEAN fDisplayBuffer, BOOLE DoRightIcon( uiRenderBuffer, pFace, sFaceX, sFaceY, bNumRightIcons, 28 ); bNumRightIcons++; } - + + // Flugente: drag stuff + if ( MercPtrs[pFace->ubSoldierID]->IsDraggingSomeone() ) + { + DoRightIcon( uiRenderBuffer, pFace, sFaceX, sFaceY, bNumRightIcons, 31 ); + ++bNumRightIcons; + } + switch( pSoldier->bAssignment ) { CASE_DOCTOR: diff --git a/Tactical/Items.cpp b/Tactical/Items.cpp index 9057518c..97055499 100644 --- a/Tactical/Items.cpp +++ b/Tactical/Items.cpp @@ -3087,9 +3087,27 @@ UINT32 GetTotalWeight( SOLDIERTYPE* pSoldier ) return uiTotalWeight; } -UINT32 CalculateCarriedWeight( SOLDIERTYPE * pSoldier ) +UINT32 CalculateCarriedWeight( SOLDIERTYPE * pSoldier, BOOLEAN fConsiderDragging) { UINT32 uiTotalWeight = GetTotalWeight( pSoldier ); + + // Flugente: if we drag someone, add their weight to ours + if ( fConsiderDragging && pSoldier->IsDraggingSomeone() ) + { + if (pSoldier->usDragPersonID != NOBODY) + { + SOLDIERTYPE* pOtherSoldier = MercPtrs[pSoldier->usDragPersonID]; + + uiTotalWeight += GetTotalWeight( pOtherSoldier ); + uiTotalWeight += pOtherSoldier->GetBodyWeight(); + } + else if (pSoldier->sDragCorpseID >= 0) + { + // just give corpses a flat weight + uiTotalWeight += 100.0f; + } + } + UINT32 uiPercent; UINT32 ubStrengthForCarrying; diff --git a/Tactical/Items.h b/Tactical/Items.h index 8a0cf952..78498912 100644 --- a/Tactical/Items.h +++ b/Tactical/Items.h @@ -52,7 +52,7 @@ extern BOOLEAN PlaceObjectAtObjectIndex( OBJECTTYPE * pSourceObj, OBJECTTYPE * p UINT16 CalculateAmmoWeight( UINT16 usGunAmmoItem, UINT16 ubShotsLeft ); UINT16 CalculateObjectWeight( OBJECTTYPE *pObject ); UINT32 GetTotalWeight( SOLDIERTYPE* pSoldier ); -UINT32 CalculateCarriedWeight( SOLDIERTYPE * pSoldier ); +UINT32 CalculateCarriedWeight( SOLDIERTYPE * pSoldier, BOOLEAN fConsiderDragging = FALSE ); // CHRISL: UINT16 CalculateItemSize( OBJECTTYPE *pObject ); diff --git a/Tactical/Overhead.cpp b/Tactical/Overhead.cpp index 3e2227af..04632a19 100644 --- a/Tactical/Overhead.cpp +++ b/Tactical/Overhead.cpp @@ -1767,21 +1767,19 @@ BOOLEAN ExecuteOverhead( ) // dAngle = (FLOAT)atan2( dDeltaX, dDeltaY ); dAngle = gdRadiansForAngle[ pSoldier->bMovementDirection ]; + FLOAT movementchange = gAnimControl[pSoldier->usAnimState].dMovementChange; + // For walking, base it on body type! if ( pSoldier->usAnimState == WALKING || pSoldier->usAnimState == WALKING_WEAPON_RDY || pSoldier->usAnimState == WALKING_DUAL_RDY || pSoldier->usAnimState == WALKING_ALTERNATIVE_RDY ) { - pSoldier->MoveMerc( gubAnimWalkSpeeds[ pSoldier->ubBodyType ].dMovementChange, dAngle, TRUE ); - + movementchange = gubAnimWalkSpeeds[pSoldier->ubBodyType].dMovementChange; } - else - { - pSoldier->MoveMerc( gAnimControl[ pSoldier->usAnimState ].dMovementChange, dAngle, TRUE ); - } - } + pSoldier->MoveMerc( movementchange, dAngle, TRUE ); + } } // Check for direction change if ( gAnimControl[ pSoldier->usAnimState ].uiFlags & ANIM_TURNING ) @@ -2007,8 +2005,8 @@ void HandleLocateToGuyAsHeWalks( SOLDIERTYPE *pSoldier ) } } -#pragma optimize("gpt",on) - __forceinline +//#pragma optimize("gpt",on) + // __forceinline BOOLEAN HandleGotoNewGridNo( SOLDIERTYPE *pSoldier, BOOLEAN *pfKeepMoving, BOOLEAN fInitialMove, UINT16 usAnimState ) { INT16 sAPCost; diff --git a/Tactical/PATHAI.cpp b/Tactical/PATHAI.cpp index a418fe1a..f53de82e 100644 --- a/Tactical/PATHAI.cpp +++ b/Tactical/PATHAI.cpp @@ -1410,6 +1410,12 @@ INT16 AStarPathfinder::CalcAP(int const terrainCost, UINT8 const direction) movementAPCost *= gItemSettings.fShieldMovementAPCostModifier; } + // Flugente: dragging someone + if ( pSoldier->IsDraggingSomeone( ) ) + { + movementAPCost *= gItemSettings.fDragAPCostModifier; + } + if (terrainCost == TRAVELCOST_FENCE) { switch( movementModeToUseForAPs ) @@ -3641,6 +3647,12 @@ if(!GridNoOnVisibleWorldTile(iDestination)) ubAPCost *= gItemSettings.fShieldMovementAPCostModifier; } + // Flugente: dragging someone + if ( s->IsDraggingSomeone( ) ) + { + ubAPCost *= gItemSettings.fDragAPCostModifier; + } + // SANDRO - moved backpack check to here // Moa: backpack penalty //if((UsingNewInventorySystem() == true) && FindBackpackOnSoldier( s ) != ITEM_NOT_FOUND ) @@ -4717,6 +4729,12 @@ INT32 PlotPath( SOLDIERTYPE *pSold, INT32 sDestGridNo, INT8 bCopyRoute, INT8 bPl { sMovementAPsCost *= gItemSettings.fShieldMovementAPCostModifier; } + + // Flugente: dragging someone + if ( pSold->IsDraggingSomeone( ) ) + { + sMovementAPsCost *= gItemSettings.fDragAPCostModifier; + } // Check for backpack //if((UsingNewInventorySystem() == true) && FindBackpackOnSoldier( pSold ) != ITEM_NOT_FOUND ) @@ -4849,6 +4867,15 @@ INT32 PlotPath( SOLDIERTYPE *pSold, INT32 sDestGridNo, INT8 bCopyRoute, INT8 bPl sPointsRun *= gItemSettings.fShieldMovementAPCostModifier; } + // Flugente: dragging someone + if ( pSold->IsDraggingSomeone() ) + { + sPointsWalk *= gItemSettings.fDragAPCostModifier; + sPointsCrawl *= gItemSettings.fDragAPCostModifier; + sPointsSwat *= gItemSettings.fDragAPCostModifier; + sPointsRun *= gItemSettings.fDragAPCostModifier; + } + // Check for backpack //if((UsingNewInventorySystem() == true) && FindBackpackOnSoldier( pSold ) != ITEM_NOT_FOUND ) //{ diff --git a/Tactical/Points.cpp b/Tactical/Points.cpp index e21d55e4..0bb82c7b 100644 --- a/Tactical/Points.cpp +++ b/Tactical/Points.cpp @@ -216,7 +216,7 @@ INT16 BreathPointAdjustmentForCarriedWeight( SOLDIERTYPE * pSoldier ) UINT32 uiCarriedPercent; UINT32 uiPercentCost; - uiCarriedPercent = CalculateCarriedWeight( pSoldier ); + uiCarriedPercent = CalculateCarriedWeight( pSoldier, TRUE ); if (uiCarriedPercent < 101) { // normal BP costs @@ -476,9 +476,11 @@ INT16 ActionPointCost( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bDir, UINT16 u // Flugente: riot shields lower movement speed if ( pSoldier->IsRiotShieldEquipped( ) ) - { sPoints *= gItemSettings.fShieldMovementAPCostModifier; - } + + // Flugente: dragging someone + if ( pSoldier->IsDraggingSomeone( ) ) + sPoints *= gItemSettings.fDragAPCostModifier; // Flugente: scuba fins reduce movement cost in water, but increase cost on land if ( pSoldier->inv[LEGPOS].exists() && HasItemFlag( pSoldier->inv[LEGPOS].usItem, SCUBA_FINS ) ) @@ -724,9 +726,11 @@ INT16 EstimateActionPointCost( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bDir, // Flugente: riot shields lower movement speed if ( pSoldier->IsRiotShieldEquipped( ) ) - { sPoints *= gItemSettings.fShieldMovementAPCostModifier; - } + + // Flugente: dragging someone + if ( pSoldier->IsDraggingSomeone( ) ) + sPoints *= gItemSettings.fDragAPCostModifier; // Check if doors if not player's merc (they have to open them manually) if ( sSwitchValue == TRAVELCOST_DOOR && pSoldier->bTeam != gbPlayerNum ) @@ -4228,6 +4232,9 @@ INT16 GetAPsStartRun( SOLDIERTYPE *pSoldier ) if ( pSoldier->IsRiotShieldEquipped( ) ) val *= gItemSettings.fShieldMovementAPCostModifier; + if ( pSoldier->IsDraggingSomeone( ) ) + val *= gItemSettings.fDragAPCostModifier; + // Athletics trait if( HAS_SKILL_TRAIT( pSoldier, ATHLETICS_NT ) && gGameOptions.fNewTraitSystem ) val = max( 1, (INT16)((val * (100 - gSkillTraitValues.ubATAPsMovementReduction) / 100) + 0.5) ); diff --git a/Tactical/Rotting Corpses.cpp b/Tactical/Rotting Corpses.cpp index 0887594d..42f6ddf3 100644 --- a/Tactical/Rotting Corpses.cpp +++ b/Tactical/Rotting Corpses.cpp @@ -557,8 +557,19 @@ INT32 AddRottingCorpse( ROTTING_CORPSE_DEFINITION *pCorpseDef ) AniParams.sDelay = (INT16)( 150 ); AniParams.sStartFrame = 0; AniParams.uiFlags = ANITILE_CACHEDTILE | ANITILE_PAUSED | ANITILE_OPTIMIZEFORSLOWMOVING | ANITILE_ANIMATE_Z | ANITILE_ERASEITEMFROMSAVEBUFFFER | uiDirectionUseFlag; - AniParams.sX = CenterX( pCorpse->def.sGridNo ); - AniParams.sY = CenterY( pCorpse->def.sGridNo ); + + // use the x,y coordinates provided in the definition when adding a corpse + if (pCorpse->def.usFlags |= ROTTING_CORPSE_USE_XY_PROVIDED) + { + AniParams.sX = pCorpse->def.dXPos; + AniParams.sY = pCorpse->def.dYPos; + } + else + { + AniParams.sX = CenterX(pCorpse->def.sGridNo); + AniParams.sY = CenterY(pCorpse->def.sGridNo); + } + AniParams.sZ = (INT16)pCorpse->def.sHeightAdjustment; AniParams.uiUserData3 = pCorpse->def.ubDirection; @@ -2575,6 +2586,36 @@ UINT8 GetNearestRottingCorpseAIWarning( INT32 sGridNo ) return( ubHighestWarning ); } +ROTTING_CORPSE* GetRottingCorpse( INT16 aNum ) +{ + if ( aNum < giNumRottingCorpse ) + return &(gRottingCorpse[aNum]); + + return NULL; +} + +std::vector GetCorpseIDsNearGridNo( INT32 sGridNo, INT8 bLevel, INT8 sRadius ) +{ + std::vector idvec; + + ROTTING_CORPSE* pCorpse; + + for ( INT32 cnt = 0; cnt < giNumRottingCorpse; ++cnt ) + { + pCorpse = &(gRottingCorpse[cnt]); + + if ( pCorpse->fActivated && pCorpse->def.bLevel == bLevel ) + { + if ( PythSpacesAway( sGridNo, pCorpse->def.sGridNo ) <= sRadius ) + { + idvec.push_back(cnt); + } + } + } + + return idvec; +} + // Flugente Zombies: resurrect zombies void RaiseZombies( void ) { diff --git a/Tactical/Rotting Corpses.h b/Tactical/Rotting Corpses.h index 897bd913..12b54d0c 100644 --- a/Tactical/Rotting Corpses.h +++ b/Tactical/Rotting Corpses.h @@ -94,6 +94,8 @@ enum RottingCorpseDefines #define ROTTING_CORPSE_NO_VEST 0x00004000 // corpse has no vest (atm not visually) #define ROTTING_CORPSE_NO_PANTS 0x00008000 // corpse has no vest (atm not visually) +#define ROTTING_CORPSE_USE_XY_PROVIDED 0x00010000 // use the x,y coordinates provided in the definition when adding a corpse + typedef struct { UINT8 ubType; @@ -220,6 +222,9 @@ INT32 GetGridNoOfCorpseGivenProfileID( UINT8 ubProfileID ); void DecayRottingCorpseAIWarnings( void ); UINT8 GetNearestRottingCorpseAIWarning( INT32 sGridNo ); +ROTTING_CORPSE* GetRottingCorpse( INT16 aNum ); +std::vector GetCorpseIDsNearGridNo( INT32 sGridNo, INT8 bLevel, INT8 sRadius ); + // Flugente: Raise zombies void RaiseZombies( void ); diff --git a/Tactical/SkillMenu.cpp b/Tactical/SkillMenu.cpp index 0f91c4ee..ec525445 100644 --- a/Tactical/SkillMenu.cpp +++ b/Tactical/SkillMenu.cpp @@ -13,6 +13,8 @@ #include "Queen Command.h" #include "strategicmap.h" #include "Map Screen Interface.h" +#include "Rotting Corpses.h" + extern void GetEquipmentTemplates( ); @@ -109,6 +111,13 @@ void Wrapper_Setup_SoldierSelection( UINT32 aVal) { gSoldierSelection.Setup(aVa void Wrapper_Cancel_SoldierSelection( UINT32 aVal ) { gSoldierSelection.Cancel(); } /////////////////////////////// Soldier Target Selection //////////////////////////////////////////// +/////////////////////////////// Drag Selection //////////////////////////////////////////// +DragSelection gDragSelection; + +void Wrapper_Function_DragSelection( UINT32 aVal) { gDragSelection.Functions(aVal); } +void Wrapper_Setup_DragSelection( UINT32 aVal ) { gDragSelection.Setup( aVal ); } +void Wrapper_Cancel_DragSelection( UINT32 aVal ) { gDragSelection.Cancel( ); } +/////////////////////////////// Drag Selection //////////////////////////////////////////// /////////////////////////////// Trait Selection //////////////////////////////////////////// void @@ -236,7 +245,10 @@ SkillSelection::Setup( UINT32 aVal ) { swprintf( pStr, pTraitSkillsMenuStrings[uiCounter] ); - pOption = new POPUP_OPTION(&std::wstring( pStr ), new popupCallbackFunction( &Wrapper_Function_SkillSelection, uiCounter ) ); + if ( uiCounter == SKILLS_DRAG ) + pOption = new POPUP_OPTION( &std::wstring( pStr ), new popupCallbackFunction( &Wrapper_Setup_DragSelection, uiCounter ) ); + else + pOption = new POPUP_OPTION( &std::wstring( pStr ), new popupCallbackFunction( &Wrapper_Function_SkillSelection, uiCounter ) ); // if we cannot perform this skill, grey it out if ( !(pSoldier->CanUseSkill( uiCounter, TRUE, sTraitsMenuTargetGridNo )) ) @@ -738,6 +750,85 @@ SoldierSelection::Functions( UINT32 aVal ) } /////////////////////////////// Soldier Target Selection //////////////////////////////////////////// +/////////////////////////////// Drag Selection //////////////////////////////////////////// +void +DragSelection::Setup( UINT32 aVal ) +{ + Destroy( ); + + SOLDIERTYPE * pSoldier = NULL; + + GetSoldier( &pSoldier, gusSelectedSoldier ); + + if ( pSoldier == NULL ) + return; + + if ( pSoldier->CanUseSkill( aVal ) ) + { + usSkill = aVal; + + SetupPopup( "DragSelection" ); + + POPUP_OPTION *pOption; + + CHAR16 pStr[300]; + + // pretty simple: we find every soldier in a radius around the target position and add him to the list + // loop through all soldiers around + for ( UINT32 cnt = gTacticalStatus.Team[OUR_TEAM].bFirstID; cnt <= gTacticalStatus.Team[CIV_TEAM].bLastID; ++cnt ) + { + if ( cnt != pSoldier->ubID && pSoldier->CanDragPerson(cnt) ) + { + swprintf( pStr, L"%s", MercPtrs[cnt]->GetName( ) ); + + pOption = new POPUP_OPTION( &std::wstring( pStr ), new popupCallbackFunction( &Wrapper_Function_DragSelection, cnt ) ); + + GetPopup( )->addOption( *pOption ); + } + } + + // corpses + std::vector corpseids = GetCorpseIDsNearGridNo( pSoldier->sGridNo, pSoldier->pathing.bLevel, 1 ); + + for ( std::vector::iterator it = corpseids.begin(); it != corpseids.end(); ++it ) + { + ROTTING_CORPSE* pCorpse = GetRottingCorpse( (*it) ); + + swprintf( pStr, pSkillMenuStrings[SKILLMENU_CORPSES], pCorpse->name ); + + // we have to use an offset of NOBODY in order to differentiate between person and corpse + pOption = new POPUP_OPTION( &std::wstring( pStr ), new popupCallbackFunction( &Wrapper_Function_DragSelection, (*it) + NOBODY ) ); + + GetPopup( )->addOption( *pOption ); + } + + // cancel option + swprintf( pStr, pSkillMenuStrings[SKILLMENU_CANCEL] ); + pOption = new POPUP_OPTION( &std::wstring( pStr ), new popupCallbackFunction( &Wrapper_Cancel_SoldierSelection, 0 ) ); + GetPopup( )->addOption( *pOption ); + } + + // same y, different x + SetPos( gSkillSelection.GetMaxPosX( ), usTraitMenuPosY ); +} + +void +DragSelection::Functions( UINT32 aVal ) +{ + SOLDIERTYPE * pSoldier = NULL; + + GetSoldier( &pSoldier, gusSelectedSoldier ); + + if ( pSoldier ) + { + pSoldier->UseSkill( usSkill, sTraitsMenuTargetGridNo, aVal ); + } + + Cancel( ); + gSkillSelection.Cancel(); + gTraitSelection.Cancel( ); +} +/////////////////////////////// Drag Selection //////////////////////////////////////////// /** * Flugente: traits menu popup box diff --git a/Tactical/SkillMenu.h b/Tactical/SkillMenu.h index 0fdc7f1b..e06252d5 100644 --- a/Tactical/SkillMenu.h +++ b/Tactical/SkillMenu.h @@ -155,6 +155,17 @@ private: UINT32 usSkill; }; +class DragSelection : public SkillMenuItem +{ +public: + DragSelection( ) {} + + void Setup( UINT32 aVal ); + void Functions( UINT32 aVal ); + +private: + UINT32 usSkill; +}; /** * Flugente: traits menu popup box diff --git a/Tactical/Soldier Control.cpp b/Tactical/Soldier Control.cpp index 9acf0a36..267c17e6 100644 --- a/Tactical/Soldier Control.cpp +++ b/Tactical/Soldier Control.cpp @@ -101,6 +101,7 @@ #include "MilitiaIndividual.h" // added by Flugente #include "Arms Dealer Init.h" // added by Flugente for armsDealerInfo[] #include "LuaInitNPCs.h" // added by Flugente +#include "SaveLoadMap.h" // added by Flugente #endif #include "ub_config.h" @@ -1027,6 +1028,8 @@ SOLDIERTYPE& SOLDIERTYPE::operator=(const OLDSOLDIERTYPE_101& src) this->bScopeMode = USE_BEST_SCOPE; this->ubMilitiaAssists = 0; + + this->CancelDrag(); this->bFoodLevel = 0; this->bDrinkLevel = 0; @@ -11193,12 +11196,10 @@ InternalpSoldier->GivingSoldierCancelServices(, FALSE ); void SOLDIERTYPE::MoveMerc( FLOAT dMovementChange, FLOAT dAngle, BOOLEAN fCheckRange ) { - //INT16 dDegAngle; FLOAT dDeltaPos; FLOAT dXPos, dYPos; - BOOLEAN fStop = FALSE; - - + BOOLEAN fStop = FALSE; + //dDegAngle = (INT16)( dAngle * 180 / PI ); //sprintf( gDebugStr, "Move Angle: %d", (int)dDegAngle ); @@ -11306,11 +11307,104 @@ 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->IsDraggingSomeone(); + INT32 sOldGridNo = this->sGridNo; + // OK, set new position this->EVENT_InternalSetSoldierPosition( dXPos, dYPos, FALSE, FALSE, FALSE ); + + // Flugente: drag people + if ( currentlydragging ) + { + if ( this->usDragPersonID != NOBODY ) + { + SOLDIERTYPE* pSoldier = MercPtrs[this->usDragPersonID]; + + // while it would be neat to take the opposite direction (which would make it look like we drag the other person by the legs), + // this causes problems, as a prone person needs additional space for the legs. So just take the same direction + //pSoldier->ubDirection = (this->ubDirection + 4 ) % NUM_WORLD_DIRECTIONS; + pSoldier->ubDirection = this->ubDirection; + + FLOAT dx = 0; + FLOAT dy = 0; + INT32 gridnotouse = pSoldier->sGridNo; + if ( sOldGridNo != this->sGridNo ) + { + gridnotouse = sOldGridNo; + } + else + { + INT16 this_base_x = 0; + INT16 this_base_y = 0; + ConvertMapPosToWorldTileCenter(this->sGridNo, &this_base_x, &this_base_y); + + dx = this->dXPos - this_base_x; + dy = this->dYPos - this_base_y; + } + + INT16 base_x = 0; + INT16 base_y = 0; + ConvertMapPosToWorldTileCenter( gridnotouse, &base_x, &base_y ); + + pSoldier->EVENT_InternalSetSoldierPosition( base_x + dx, base_y + dy, FALSE, FALSE, FALSE ); + } + else if ( this->sDragCorpseID >= 0 ) + { + ROTTING_CORPSE* pCorpse = GetRottingCorpse( this->sDragCorpseID ); + + if ( pCorpse ) + { + // move corpse to new location. We have to actually delete and recreate the corpse, otherwise direction changes will only be visible after saving the game + ROTTING_CORPSE_DEFINITION CorpseDef; + + // Copy corpse definition... + memcpy(&CorpseDef, &(pCorpse->def), sizeof(ROTTING_CORPSE_DEFINITION)); + + // Remove old one... + RemoveCorpse(pCorpse->iID); + + // drop blood at old location + InternalDropBlood(pCorpse->def.sGridNo, this->pathing.bLevel, 0, 5, 1); + + // adjust both gridno and x,y coordinates + if (sOldGridNo != this->sGridNo) + { + CorpseDef.sGridNo = sOldGridNo; + CorpseDef.dXPos = CenterX(CorpseDef.sGridNo); + CorpseDef.dYPos = CenterY(CorpseDef.sGridNo); + } + else + { + // move corpse a bit + INT16 this_base_x = 0; + INT16 this_base_y = 0; + ConvertMapPosToWorldTileCenter(this->sGridNo, &this_base_x, &this_base_y); + + FLOAT dx = this->dXPos - this_base_x; + FLOAT dy = this->dYPos - this_base_y; + + INT16 base_x = 0; + INT16 base_y = 0; + ConvertMapPosToWorldTileCenter(pCorpse->def.sGridNo, &base_x, &base_y); + + CorpseDef.sGridNo = pCorpse->def.sGridNo; + CorpseDef.dXPos = CenterX(CorpseDef.sGridNo) + dx; + CorpseDef.dYPos = CenterY(CorpseDef.sGridNo) + dy; + } + + CorpseDef.usFlags |= ROTTING_CORPSE_USE_XY_PROVIDED; + + CorpseDef.ubDirection = this->ubDirection; + + this->sDragCorpseID = AddRottingCorpse(&CorpseDef); + } + } + } + // DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("X: %f Y: %f", dXPos, dYPos ) ); - } BOOLEAN GetDirectionChangeAmount( INT32 sGridNo, SOLDIERTYPE *pSoldier, UINT8 uiTurnAmount ) @@ -17361,6 +17455,13 @@ BOOLEAN SOLDIERTYPE::CanUseSkill( INT8 iSkill, BOOLEAN fAPCheck, INT32 sGridNo ) canuse = TRUE; break; + case SKILLS_DRAG: + + // TODO: a better check would be whether we can drag anything at the moment - CanDrag is more used for a specific person + if ( CanDragInPrinciple() ) + canuse = TRUE; + break; + default: break; } @@ -17369,7 +17470,7 @@ BOOLEAN SOLDIERTYPE::CanUseSkill( INT8 iSkill, BOOLEAN fAPCheck, INT32 sGridNo ) } // use a skill. For safety reasons, this calls CanUseSkill again -BOOLEAN SOLDIERTYPE::UseSkill( UINT8 iSkill, INT32 usMapPos, UINT8 ID ) +BOOLEAN SOLDIERTYPE::UseSkill( UINT8 iSkill, INT32 usMapPos, UINT32 ID ) { if ( !CanUseSkill( iSkill, TRUE, usMapPos ) ) { @@ -17430,6 +17531,13 @@ BOOLEAN SOLDIERTYPE::UseSkill( UINT8 iSkill, INT32 usMapPos, UINT8 ID ) } break; + case SKILLS_DRAG: + if ( ID < NOBODY ) + SetDragOrderPerson( ID ); + else + SetDragOrderCorpse( ID - NOBODY ); + break; + default: break; } @@ -17507,6 +17615,19 @@ STR16 SOLDIERTYPE::PrintSkillDesc( INT8 iSkill ) break; + case SKILLS_DRAG: + + swprintf( atStr, pTraitSkillsDenialStrings[TEXT_SKILL_DENIAL_PRONEPERSONORCORPSE] ); + wcscat( skilldescarray, atStr ); + + swprintf( atStr, pTraitSkillsDenialStrings[TEXT_SKILL_DENIAL_CROUCH] ); + wcscat( skilldescarray, atStr ); + + swprintf( atStr, pTraitSkillsDenialStrings[TEXT_SKILL_DENIAL_FREEHANDS] ); + wcscat( skilldescarray, atStr ); + + break; + default: break; } @@ -19353,6 +19474,156 @@ void SOLDIERTYPE::RiotShieldTakeDamage( INT32 sDamage ) } } +// Flugente: drag people +BOOLEAN SOLDIERTYPE::CanDragInPrinciple() +{ + // only prone while crouched + if ( gAnimControl[this->usAnimState].ubEndHeight != ANIM_CROUCH ) + return FALSE; + + // not in water + if ( TERRAIN_IS_HIGH_WATER( this->sGridNo ) ) + return FALSE; + + // main hand must be free + if ( this->inv[HANDPOS].exists( ) ) + return FALSE; + + return TRUE; +} + +BOOLEAN SOLDIERTYPE::CanDragPerson( UINT8 usID ) +{ + if ( !CanDragInPrinciple() ) + return FALSE; + + // check whether this guy exists etc. + SOLDIERTYPE* pSoldier = MercPtrs[usID]; + + if ( pSoldier && pSoldier->bActive && pSoldier->bInSector ) + { + // must be on same level + if ( pSoldier->pathing.bLevel != this->pathing.bLevel ) + return FALSE; + + // only prone people can be dragged + if ( gAnimControl[pSoldier->usAnimState].ubEndHeight != ANIM_PRONE ) + return FALSE; + + // not in water + if ( TERRAIN_IS_HIGH_WATER( pSoldier->sGridNo ) ) + return FALSE; + + // don't drag nonsense around + if ( pSoldier->ubBodyType >= COW || pSoldier->ubBodyType == QUEENMONSTER ) + return FALSE; + + // must be near us + if ( PythSpacesAway( pSoldier->sGridNo, this->sGridNo ) > 1 ) + return FALSE; + + // we must be able to see the other guy even if if both would be prone. This is to stop the player from dragging someone through solid structures + if ( !LocationToLocationLineOfSightTest(pSoldier->sGridNo, pSoldier->pathing.bLevel, this->sGridNo, this->pathing.bLevel, TRUE, CALC_FROM_ALL_DIRS, PRONE_LOS_POS, PRONE_LOS_POS)) + return FALSE; + + return TRUE; + } + + return FALSE; +} + +BOOLEAN SOLDIERTYPE::CanDragCorpse( UINT16 usCorpseNum ) +{ + if ( !CanDragInPrinciple( ) ) + return FALSE; + + ROTTING_CORPSE* pCorpse = GetRottingCorpse( usCorpseNum ); + + if ( pCorpse ) + { + // must be on same level + if ( pCorpse->def.bLevel != this->pathing.bLevel ) + return FALSE; + + // don't drag nonsense around + if ( pCorpse->def.ubBodyType >= COW || pCorpse->def.ubBodyType == QUEENMONSTER ) + return FALSE; + + // must be near us + if ( PythSpacesAway( pCorpse->def.sGridNo, this->sGridNo ) > 2 ) + return FALSE; + + // we must be able to see the other guy even if if both would be prone. This is to stop the player from dragging someone through solid structures + if (!LocationToLocationLineOfSightTest(pCorpse->def.sGridNo, this->pathing.bLevel, this->sGridNo, this->pathing.bLevel, TRUE, CALC_FROM_ALL_DIRS, PRONE_LOS_POS, PRONE_LOS_POS)) + return FALSE; + + return TRUE; + } + + return FALSE; +} + +BOOLEAN SOLDIERTYPE::IsDraggingSomeone( ) +{ + if ( this->sDragCorpseID >= 0 ) + { + if ( this->CanDragCorpse(this->sDragCorpseID) ) + return TRUE; + else + CancelDrag(); + } + else if ( this->usDragPersonID != NOBODY ) + { + if ( this->CanDragPerson(this->usDragPersonID) ) + return TRUE; + else + CancelDrag(); + } + + return FALSE; +} + +void SOLDIERTYPE::SetDragOrderPerson( UINT16 usID ) +{ + if ( CanDragPerson( usID ) ) + { + CancelDrag(); + + this->usDragPersonID = usID; + } +} + +void SOLDIERTYPE::SetDragOrderCorpse( UINT32 usID ) +{ + if ( CanDragCorpse( usID ) ) + { + CancelDrag(); + + this->sDragCorpseID = usID; + } +} + +void SOLDIERTYPE::CancelDrag() +{ + // if we are dragging a person, set them to the center of their gridno, otherwise their position might be off + if (this->usDragPersonID != NOBODY) + { + SOLDIERTYPE* pSoldier = MercPtrs[this->usDragPersonID]; + + if ( pSoldier && !TileIsOutOfBounds(pSoldier->sGridNo) ) + { + INT16 base_x = 0; + INT16 base_y = 0; + ConvertMapPosToWorldTileCenter(pSoldier->sGridNo, &base_x, &base_y); + + pSoldier->EVENT_InternalSetSoldierPosition(base_x, base_y, FALSE, FALSE, FALSE); + } + } + + this->usDragPersonID = NOBODY; + this->sDragCorpseID = -1; +} + INT32 CheckBleeding( SOLDIERTYPE *pSoldier ) { INT8 bBandaged; //,savedOurTurn; diff --git a/Tactical/Soldier Control.h b/Tactical/Soldier Control.h index 8360625f..40ed5268 100644 --- a/Tactical/Soldier Control.h +++ b/Tactical/Soldier Control.h @@ -416,6 +416,7 @@ enum #define SOLDIER_COVERT_NOREDISGUISE 0x00001000 // this soldier does not want to be redisguised #define SOLDIER_TRAIT_FOCUS 0x00002000 // 'focus' skill is active +#define SOLDIER_DRAG_CORPSE 0x00004000 // we are dragging a corpse, not a person #define SOLDIER_INTERROGATE_ALL 0x000001F8 // all interrogation flags // ---------------------------------------------------------------- @@ -590,7 +591,8 @@ enum{ SKILLS_VARIOUS_FIRST, SKILLS_SPOTTER = SKILLS_VARIOUS_FIRST, SKILLS_FOCUS, - SKILLS_VARIOUS_LAST = SKILLS_FOCUS, + SKILLS_DRAG, + SKILLS_VARIOUS_LAST = SKILLS_DRAG, SKILLS_MAX, }; @@ -1485,12 +1487,14 @@ public: // Flugente: this was the location of required variables required for the now removed poison feature. They can be used again UINT8 ubMilitiaAssists; // Flugente: stores militia assists INT8 sNonNPCTraderID; // Flugente: we can set up non-NPC soldiers to be merchants, we store their dealer id here (value > 0 means arms dealer entry x) - INT8 bUnusedINT8_3; + //INT8 bUnusedINT8_3; + UINT8 usDragPersonID; // Flugente: id of person we are dragging + + //INT16 bUnusedINT16_4; + INT16 sDragCorpseID; // Flugente: id of corpse we are dragging - INT16 bUnusedINT16_4; INT16 bUnusedINT16_5; - /////////////////////////////////////////////////////// - + // Flugente: new variables for extra stats INT16 bExtraStrength; // additional strength gained via power armor INT16 bExtraDexterity; // additional dexterity gained via drugs @@ -1866,7 +1870,7 @@ public: BOOLEAN CanUseSkill( INT8 iSkill, BOOLEAN fAPCheck = TRUE, INT32 sGridNo = -1 ); // use a skill. For safety reasons, this calls CanUseSkill again (it is possible to switch the soldier while the menu is open) - BOOLEAN UseSkill( UINT8 iSkill, INT32 usMapPos, UINT8 ID ); + BOOLEAN UseSkill( UINT8 iSkill, INT32 usMapPos, UINT32 ID ); // is the AI allowed to use a skill? we have to check how much breath and life using this skill would cost, as otherwise the AI might commit suicide by casting BOOLEAN IsAIAllowedtoUseSkill( INT8 iSkill ); @@ -1949,6 +1953,15 @@ public: BOOLEAN IsRiotShieldEquipped(); void DestroyEquippedRiotShield(); void RiotShieldTakeDamage(INT32 sDamage); + + // Flugente: drag people + BOOLEAN CanDragInPrinciple(); + BOOLEAN CanDragPerson( UINT8 usID ); + BOOLEAN CanDragCorpse( UINT16 usCorpseNum ); + BOOLEAN IsDraggingSomeone(); + void SetDragOrderPerson( UINT16 usID ); + void SetDragOrderCorpse( UINT32 usID ); + void CancelDrag(); ////////////////////////////////////////////////////////////////////////////// }; // SOLDIERTYPE; diff --git a/Utils/Text.h b/Utils/Text.h index 3605d9a8..01c6d126 100644 --- a/Utils/Text.h +++ b/Utils/Text.h @@ -168,6 +168,7 @@ enum SKILLMENU_X_MILITIA, SKILLMENU_ALL_MILITIA, SKILLMENU_MORE, + SKILLMENU_CORPSES, }; extern STR16 pSkillMenuStrings[]; //Flugente @@ -2637,6 +2638,9 @@ enum TEXT_SKILL_DENIAL_NODEMON, TEXT_SKILL_DENIAL_GUNTRAIT, TEXT_SKILL_DENIAL_AIMEDGUN, + TEXT_SKILL_DENIAL_PRONEPERSONORCORPSE, + TEXT_SKILL_DENIAL_CROUCH, + TEXT_SKILL_DENIAL_FREEHANDS, TEXT_SKILL_DENIAL_MAX, }; diff --git a/Utils/_ChineseText.cpp b/Utils/_ChineseText.cpp index f9595877..e9e91cd0 100644 --- a/Utils/_ChineseText.cpp +++ b/Utils/_ChineseText.cpp @@ -2783,9 +2783,6 @@ STR16 pMilitiaControlMenuStrings[] = //Flugente STR16 pTraitSkillsMenuStrings[] = { - // sniper - L"聚焦", //L"Focus", - // radio operator L"火炮攻击", //L"Artillery Strike", L"通讯干扰", //L"Jam communications", @@ -2796,24 +2793,25 @@ STR16 pTraitSkillsMenuStrings[] = // various L"侦查员", + L"聚焦", //L"Focus", + L"Drag", // TODO.Translate }; //Flugente: short description of the above skills for the skill selection menu STR16 pTraitSkillsMenuDescStrings[] = { - // sniper - L"提高中断修正 (malus outside of area)", //L"Increase interrupt modifier (malus outside of area)", // TODO.Translate - // radio operator L"命令某分区发动火炮攻击。", //L"Order an artillery strike from sector...", L"所有通讯频率加入空白噪音,阻断正常通讯。", //L"Fill all radio frequencies with white noise, making communications impossible.", L"查找干扰信号源。", //L"Scan for jamming signals.", L"使用无线电设备持续监听敌军动向。", //L"Use your radio equipment to continously listen for enemy movement", L"从邻区呼叫支援。", //L"Call in reinforcements from neighbouring sectors.", - L"关闭无线电设备以节约电池。", //L"Turn off radio set to save batteries.", + L"Turn off radio set.", // TODO.Translate // various L"侦查一个区域,友军狙击手在瞄准你所观察到的目标时会增加命中率值。", + L"提高中断修正 (malus outside of area)", //L"Increase interrupt modifier (malus outside of area)", + L"Drag a person or corpse while you move.", // TODO.Translate }; STR16 pTraitSkillsDenialStrings[] = @@ -2829,6 +2827,9 @@ STR16 pTraitSkillsDenialStrings[] = L" - 恶魔的财产\n", //L" - posession by a demon" L" - 与枪有关的特长\n", //L" - a gun-related trait\n", L" - 针对枪\n", //L" - aimed gun\n", + L" - prone person or corpse next to merc\n", // TODO.Translate + L" - crouched position\n", + L" - free main hand\n", }; STR16 pSkillMenuStrings[] = @@ -2840,6 +2841,7 @@ STR16 pSkillMenuStrings[] = L"所有民兵", L"More", + L"Corpse: %s", // TODO.Translate }; STR16 pSnitchMenuStrings[] = diff --git a/Utils/_DutchText.cpp b/Utils/_DutchText.cpp index 45ea4d0e..ad51d334 100644 --- a/Utils/_DutchText.cpp +++ b/Utils/_DutchText.cpp @@ -2782,9 +2782,6 @@ STR16 pMilitiaControlMenuStrings[] = //Flugente STR16 pTraitSkillsMenuStrings[] = // TODO.Translate { - // sniper - L"Focus", // TODO.Translate - // radio operator L"Artillery Strike", L"Jam communications", @@ -2795,24 +2792,25 @@ STR16 pTraitSkillsMenuStrings[] = // TODO.Translate // various L"Spotter", // TODO.Translate + L"Focus", + L"Drag", }; //Flugente: short description of the above skills for the skill selection menu STR16 pTraitSkillsMenuDescStrings[] = { - // sniper - L"Increase interrupt modifier (malus outside of area)", // TODO.Translate - // radio operator L"Order an artillery strike from sector...", L"Fill all radio frequencies with white noise, making communications impossible.", L"Scan for jamming signals.", L"Use your radio equipment to continously listen for enemy movement.", L"Call in reinforcements from neighbouring sectors.", - L"Turn off radio set to save batteries.", + L"Turn off radio set.", // TODO.Translate // various L"Observe an area, granting allied snipers a bonus to cth on anything you see.", // TODO.Translate + L"Increase interrupt modifier (penalty outside of area).", // TODO.Translate + L"Drag a person or corpse while you move.", }; STR16 pTraitSkillsDenialStrings[] = @@ -2828,6 +2826,9 @@ STR16 pTraitSkillsDenialStrings[] = L" - possession by a demon", L" - a gun-related trait\n", // TODO.Translate L" - aimed gun\n", + L" - prone person or corpse next to merc\n", // TODO.Translate + L" - crouched position\n", + L" - free main hand\n", }; STR16 pSkillMenuStrings[] = // TODO.Translate @@ -2839,6 +2840,7 @@ STR16 pSkillMenuStrings[] = // TODO.Translate L"All Militia", L"More", + L"Corpse: %s", // TODO.Translate }; // TODO.Translate diff --git a/Utils/_EnglishText.cpp b/Utils/_EnglishText.cpp index 08efbba0..ac9f6709 100644 --- a/Utils/_EnglishText.cpp +++ b/Utils/_EnglishText.cpp @@ -2794,6 +2794,7 @@ STR16 pTraitSkillsMenuStrings[] = // various L"Spotter", L"Focus", + L"Drag", }; //Flugente: short description of the above skills for the skill selection menu @@ -2805,11 +2806,12 @@ STR16 pTraitSkillsMenuDescStrings[] = L"Scan for jamming signals.", L"Use your radio equipment to continously listen for enemy movement.", L"Call in reinforcements from neighbouring sectors.", - L"Turn off radio set to save batteries.", + L"Turn off radio set.", // various L"Observe an area, granting allied snipers a bonus to cth on anything you see.", - L"Increase interrupt modifier (penalty outside of area)", + L"Increase interrupt modifier (penalty outside of area).", + L"Drag a person or corpse while you move.", }; STR16 pTraitSkillsDenialStrings[] = @@ -2825,6 +2827,9 @@ STR16 pTraitSkillsDenialStrings[] = L" - possession by a demon\n", L" - a gun-related trait\n", L" - aimed gun\n", + L" - prone person or corpse next to merc\n", + L" - crouched position\n", + L" - free main hand\n", }; STR16 pSkillMenuStrings[] = @@ -2836,6 +2841,7 @@ STR16 pSkillMenuStrings[] = L"All Militia", L"More", + L"Corpse: %s", }; STR16 pSnitchMenuStrings[] = diff --git a/Utils/_FrenchText.cpp b/Utils/_FrenchText.cpp index 0184f810..d7cd364c 100644 --- a/Utils/_FrenchText.cpp +++ b/Utils/_FrenchText.cpp @@ -2791,9 +2791,6 @@ STR16 pMilitiaControlMenuStrings[] = //Flugente STR16 pTraitSkillsMenuStrings[] = { - // sniper - L"Focus", // TODO.Translate - // radio operator L"Tir d'artillerie", L"Brouiller les communications", @@ -2804,24 +2801,25 @@ STR16 pTraitSkillsMenuStrings[] = // various L"Guetteur", + L"Focus", // TODO.Translate + L"Drag", }; //Flugente: short description of the above skills for the skill selection menu STR16 pTraitSkillsMenuDescStrings[] = { - // sniper - L"Increase interrupt modifier (malus outside of area)", // TODO.Translate - // radio operator L"Ordonner un tir d'artillerie au secteur...", L"Brouiller toutes les fréquences radios pour rendre les communications impossibles.", L"Pour trouver une fréquence émettrice.", L"Utiliser votre radio pour connaître les mouvements de l'ennemi.", L"Appeler des renforts des secteurs voisins.", - L"Éteindre la radio pour économiser la batterie.", + L"Éteindre la radio.", // various L"Observer une zone avec un tireur d'élite donne un bonus de CDT sur tout ce que vous voyez.", + L"Increase interrupt modifier (penalty outside of area).", // TODO.Translate + L"Drag a person or corpse while you move.", }; STR16 pTraitSkillsDenialStrings[] = @@ -2837,6 +2835,9 @@ STR16 pTraitSkillsDenialStrings[] = L" - possession par un démon", L" - a gun-related trait\n", // TODO.Translate L" - aimed gun\n", + L" - prone person or corpse next to merc\n", // TODO.Translate + L" - crouched position\n", + L" - free main hand\n", }; STR16 pSkillMenuStrings[] = @@ -2848,6 +2849,7 @@ STR16 pSkillMenuStrings[] = L"Tous", L"More", // TODO.Translate + L"Corpse: %s", // TODO.Translate }; STR16 pSnitchMenuStrings[] = diff --git a/Utils/_GermanText.cpp b/Utils/_GermanText.cpp index 8e665631..e889805d 100644 --- a/Utils/_GermanText.cpp +++ b/Utils/_GermanText.cpp @@ -2786,9 +2786,6 @@ STR16 pMilitiaControlMenuStrings[] = //Flugente STR16 pTraitSkillsMenuStrings[] = { - // sniper - L"Fokus", - // radio operator L"Artillerie befehligen", L"Kommunikation stören", @@ -2799,24 +2796,25 @@ STR16 pTraitSkillsMenuStrings[] = // various L"Spotter", + L"Fokus", + L"Greifen", }; //Flugente: short description of the above skills for the skill selection menu STR16 pTraitSkillsMenuDescStrings[] = { - // sniper - L"Increase interrupt modifier (malus outside of area)", // TODO.Translate - // radio operator L"Artillerieschlag befehligen von einem Sektor...", L"Alle Funkfrequenzen mit weißem Rauschen füllen, sodass eine Kommunikation nicht mehr möglich ist.", L"Nach Störsignalen scannen.", L"Das Radiogerät verwenden, um feindliche Bewegungen zu orten.", L"Verstärkung aus dem Nachbarsektor anfordern.", - L"Radiogerät ausschalten, um Batterien zu sparen.", + L"Radiogerät ausschalten.", // various L"Bestimmtes Gebiet beobachten, damit Scharfschützen einen Bonus auf deren Treffsicherheit erhalten.", + L"Increase interrupt modifier (penalty outside of area).", // TODO.Translate + L"Drag a person or corpse while you move.", }; STR16 pTraitSkillsDenialStrings[] = @@ -2832,6 +2830,9 @@ STR16 pTraitSkillsDenialStrings[] = L" - besessen von einem Dämon", L" - a gun-related trait\n", // TODO.Translate L" - aimed gun\n", + L" - prone person or corpse next to merc\n", // TODO.Translate + L" - crouched position\n", + L" - free main hand\n", }; STR16 pSkillMenuStrings[] = // TODO.Translate @@ -2843,6 +2844,7 @@ STR16 pSkillMenuStrings[] = // TODO.Translate L"All Militia", L"More", // TODO.Translate + L"Corpse: %s", // TODO.Translate }; // TODO.Translate diff --git a/Utils/_ItalianText.cpp b/Utils/_ItalianText.cpp index 87aa57cb..a3299c2e 100644 --- a/Utils/_ItalianText.cpp +++ b/Utils/_ItalianText.cpp @@ -2777,9 +2777,6 @@ STR16 pMilitiaControlMenuStrings[] = //Flugente STR16 pTraitSkillsMenuStrings[] = // TODO.Translate { - // sniper - L"Focus", // TODO.Translate - // radio operator L"Artillery Strike", L"Jam communications", @@ -2790,24 +2787,25 @@ STR16 pTraitSkillsMenuStrings[] = // TODO.Translate // various L"Spotter", // TODO.Translate + L"Focus", // TODO.Translate + L"Drag", }; //Flugente: short description of the above skills for the skill selection menu STR16 pTraitSkillsMenuDescStrings[] = { - // sniper - L"Increase interrupt modifier (malus outside of area)", // TODO.Translate - // radio operator L"Order an artillery strike from sector...", L"Fill all radio frequencies with white noise, making communications impossible.", L"Scan for jamming signals.", L"Use your radio equipment to continously listen for enemy movement.", L"Call in reinforcements from neighbouring sectors.", - L"Turn off radio set to save batteries.", + L"Turn off radio set.", // TODO.Translate // various L"Observe an area, granting allied snipers a bonus to cth on anything you see.", // TODO.Translate + L"Increase interrupt modifier (penalty outside of area).", // TODO.Translate + L"Drag a person or corpse while you move.", }; STR16 pTraitSkillsDenialStrings[] = @@ -2823,6 +2821,9 @@ STR16 pTraitSkillsDenialStrings[] = L" - possession by a demon", L" - a gun-related trait\n", // TODO.Translate L" - aimed gun\n", + L" - prone person or corpse next to merc\n", // TODO.Translate + L" - crouched position\n", + L" - free main hand\n", }; STR16 pSkillMenuStrings[] = // TODO.Translate @@ -2834,6 +2835,7 @@ STR16 pSkillMenuStrings[] = // TODO.Translate L"All Militia", L"More", // TODO.Translate + L"Corpse: %s", // TODO.Translate }; // TODO.Translate diff --git a/Utils/_PolishText.cpp b/Utils/_PolishText.cpp index ab7bec2c..d70300b9 100644 --- a/Utils/_PolishText.cpp +++ b/Utils/_PolishText.cpp @@ -2789,9 +2789,6 @@ STR16 pMilitiaControlMenuStrings[] = //Flugente STR16 pTraitSkillsMenuStrings[] = // TODO.Translate { - // sniper - L"Focus", // TODO.Translate - // radio operator L"Artillery Strike", L"Jam communications", @@ -2802,24 +2799,25 @@ STR16 pTraitSkillsMenuStrings[] = // TODO.Translate // various L"Spotter", // TODO.Translate + L"Focus", // TODO.Translate + L"Drag", }; //Flugente: short description of the above skills for the skill selection menu STR16 pTraitSkillsMenuDescStrings[] = { - // sniper - L"Increase interrupt modifier (malus outside of area)", // TODO.Translate - // radio operator L"Order an artillery strike from sector...", L"Fill all radio frequencies with white noise, making communications impossible.", L"Scan for jamming signals.", L"Use your radio equipment to continously listen for enemy movement.", L"Call in reinforcements from neighbouring sectors.", - L"Turn off radio set to save batteries.", + L"Turn off radio set.", // TODO.Translate // various L"Observe an area, granting allied snipers a bonus to cth on anything you see.", // TODO.Translate + L"Increase interrupt modifier (penalty outside of area).", // TODO.Translate + L"Drag a person or corpse while you move.", }; STR16 pTraitSkillsDenialStrings[] = @@ -2835,6 +2833,9 @@ STR16 pTraitSkillsDenialStrings[] = L" - possession by a demon", L" - a gun-related trait\n", // TODO.Translate L" - aimed gun\n", + L" - prone person or corpse next to merc\n", // TODO.Translate + L" - crouched position\n", + L" - free main hand\n", }; STR16 pSkillMenuStrings[] = // TODO.Translate @@ -2846,6 +2847,7 @@ STR16 pSkillMenuStrings[] = // TODO.Translate L"All Militia", L"More", // TODO.Translate + L"Corpse: %s", // TODO.Translate }; STR16 pSnitchMenuStrings[] = diff --git a/Utils/_RussianText.cpp b/Utils/_RussianText.cpp index 79a88519..cf84a106 100644 --- a/Utils/_RussianText.cpp +++ b/Utils/_RussianText.cpp @@ -2783,9 +2783,6 @@ STR16 pMilitiaControlMenuStrings[] = //Flugente STR16 pTraitSkillsMenuStrings[] = { - // sniper - L"Focus", // TODO.Translate - // radio operator L"Артналет", L"Постановка помех", @@ -2796,24 +2793,25 @@ STR16 pTraitSkillsMenuStrings[] = // various L"Наблюдатель", + L"Focus", // TODO.Translate + L"Drag", }; //Flugente: short description of the above skills for the skill selection menu STR16 pTraitSkillsMenuDescStrings[] = { - // sniper - L"Increase interrupt modifier (malus outside of area)", // TODO.Translate - // radio operator L"Вызвать артиллерийский удар из сектора...", L"Заполнить эфир помехами, чтобы сделать невозможным использование средств связи.", L"Искать источник помех.", L"Использовать радиопрослушку для обнаружения противника.", L"Вызвать подкрепления из соседних секторов.", - L"Выключить радиостанцию для экономии батарей.", + L"Turn off radio set.", // TODO.Translate // various L"Наблюдать за местностью, чтобы обеспечить более меткую стрельбу своим снайперам.", + L"Increase interrupt modifier (penalty outside of area).", // TODO.Translate + L"Drag a person or corpse while you move.", }; STR16 pTraitSkillsDenialStrings[] = @@ -2829,6 +2827,9 @@ STR16 pTraitSkillsDenialStrings[] = L" - одержим бесами", L" - a gun-related trait\n", // TODO.Translate L" - aimed gun\n", + L" - prone person or corpse next to merc\n", // TODO.Translate + L" - crouched position\n", + L" - free main hand\n", }; STR16 pSkillMenuStrings[] = @@ -2840,6 +2841,7 @@ STR16 pSkillMenuStrings[] = L"Все ополченцы", L"More", // TODO.Translate + L"Corpse: %s", // TODO.Translate }; STR16 pSnitchMenuStrings[] =