From 82a2b6c2db8a5b1d91da5cb3bf16da05459378b4 Mon Sep 17 00:00:00 2001 From: Flugente Date: Sun, 4 Mar 2018 21:20:38 +0000 Subject: [PATCH] Added new assignments for training existing militia and doctoring them. For more info, see http://thepit.ja-galaxy-forum.com/index.php?t=msg&th=23044&goto=352617&#msg_352617 git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@8537 3b4a5df2-a311-0410-b5c6-a8a6f20db521 --- GameSettings.cpp | 11 +- GameSettings.h | 1 + GameVersion.cpp | 18 +- GameVersion.h | 3 +- Laptop/finances.cpp | 12 + Laptop/finances.h | 1 + Strategic/Assignments.cpp | 1046 +++++++++++++++++++++++++--- Strategic/Assignments.h | 14 + Strategic/Map Screen Interface.cpp | 9 + Strategic/Map Screen Interface.h | 2 +- Strategic/MilitiaIndividual.cpp | 305 ++++++-- Strategic/MilitiaIndividual.h | 20 +- Strategic/MilitiaSquads.cpp | 8 +- Strategic/Strategic Movement.cpp | 2 +- Tactical/Campaign.cpp | 4 +- Tactical/Faces.cpp | 23 +- Tactical/Soldier Add.cpp | 2 +- Tactical/Soldier Create.cpp | 2 +- Utils/Text.h | 2 + Utils/_ChineseText.cpp | 83 ++- Utils/_DutchText.cpp | 95 ++- Utils/_EnglishText.cpp | 31 +- Utils/_FrenchText.cpp | 83 ++- Utils/_GermanText.cpp | 95 ++- Utils/_ItalianText.cpp | 95 ++- Utils/_PolishText.cpp | 95 ++- Utils/_RussianText.cpp | 95 ++- 27 files changed, 1939 insertions(+), 218 deletions(-) diff --git a/GameSettings.cpp b/GameSettings.cpp index f84c8d53..20deff30 100644 --- a/GameSettings.cpp +++ b/GameSettings.cpp @@ -1557,14 +1557,15 @@ void LoadGameExternalOptions() //################# Individual Militia Settings ################## // Flugente: individual militia - gGameExternalOptions.fIndividualMilitia = iniReader.ReadBoolean( "Individual Militia Settings", "INDIVIDUAL_MILITIA", FALSE ); + gGameExternalOptions.fIndividualMilitia = iniReader.ReadBoolean( "Individual Militia Settings", "INDIVIDUAL_MILITIA", FALSE ); gGameExternalOptions.usIndividualMilitia_PromotionPoints_To_Regular = iniReader.ReadInteger( "Individual Militia Settings", "INDIVIDUAL_MILITIA_PROMOTIONPOINTS_TO_REGULAR", 4, 1, 100 ); - gGameExternalOptions.usIndividualMilitia_PromotionPoints_To_Elite = iniReader.ReadInteger( "Individual Militia Settings", "INDIVIDUAL_MILITIA_PROMOTIONPOINTS_TO_ELITE", 10, 1, 100 ); - - gGameExternalOptions.fIndividualMilitia_ManageHealth = iniReader.ReadBoolean( "Individual Militia Settings", "INDIVIDUAL_MILITIA_MANAGE_HEALTH", TRUE ); - gGameExternalOptions.dIndividualMilitiaHourlyHealthPercentageGain = iniReader.ReadFloat( "Individual Militia Settings", "INDIVIDUAL_MILITIA_HOURLYHEALTHPERCENTAGEGAIN", 2.0f, 0.0f, 100.0f ); + gGameExternalOptions.usIndividualMilitia_PromotionPoints_To_Elite = iniReader.ReadInteger( "Individual Militia Settings", "INDIVIDUAL_MILITIA_PROMOTIONPOINTS_TO_ELITE", 6, 1, 100 ); + gGameExternalOptions.fIndividualMilitia_ManageHealth = iniReader.ReadBoolean( "Individual Militia Settings", "INDIVIDUAL_MILITIA_MANAGE_HEALTH", TRUE ); + gGameExternalOptions.dIndividualMilitiaHourlyHealthPercentageGain = iniReader.ReadFloat( "Individual Militia Settings", "INDIVIDUAL_MILITIA_HOURLYHEALTHPERCENTAGEGAIN", 2.0f, 0.0f, 100.0f ); + gGameExternalOptions.dIndividualMilitiaDoctorHealModifier = iniReader.ReadFloat( "Individual Militia Settings", "INDIVIDUAL_MILITIA_DOCTORHEALMODIFIER", 0.01f, 0.01f, 1.0f ); + //################# Tactical Cover System Settings ################## // CPT: Cover System Settings diff --git a/GameSettings.h b/GameSettings.h index 1fd9f9eb..c0245f2e 100644 --- a/GameSettings.h +++ b/GameSettings.h @@ -1479,6 +1479,7 @@ typedef struct UINT16 usIndividualMilitia_PromotionPoints_To_Elite; BOOLEAN fIndividualMilitia_ManageHealth; FLOAT dIndividualMilitiaHourlyHealthPercentageGain; + FLOAT dIndividualMilitiaDoctorHealModifier; // Sandro: Alternative weapon holding (rifles fired from hip / pistols fired one-handed) UINT8 ubAllowAlternativeWeaponHolding; diff --git a/GameVersion.cpp b/GameVersion.cpp index ac02ce21..b9f1e55a 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.8531 (Development Build)" }; + CHAR16 zVersionLabel[256] = { L"Unfinished Business - Map Editor v1.13.8537 (Development Build)" }; #else - CHAR16 zVersionLabel[256] = { L"Map Editor v1.13.8531 (Development Build)" }; + CHAR16 zVersionLabel[256] = { L"Map Editor v1.13.8537 (Development Build)" }; #endif // ------------------------------ @@ -27,11 +27,11 @@ //DEBUG BUILD VERSION #ifdef JA2UB - CHAR16 zVersionLabel[256] = { L"Debug: Unfinished Business - v1.13.8531 (Development Build)" }; + CHAR16 zVersionLabel[256] = { L"Debug: Unfinished Business - v1.13.8537 (Development Build)" }; #elif defined (JA113DEMO) - CHAR16 zVersionLabel[256] = { L"Debug: JA2 Demo - v1.13.8531 (Development Build)" }; + CHAR16 zVersionLabel[256] = { L"Debug: JA2 Demo - v1.13.8537 (Development Build)" }; #else - CHAR16 zVersionLabel[256] = { L"Debug: v1.13.8531 (Development Build)" }; + CHAR16 zVersionLabel[256] = { L"Debug: v1.13.8537 (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.8531 (Development Build)" }; + CHAR16 zVersionLabel[256] = { L"Release Unfinished Business - v1.13.8537 (Development Build)" }; #elif defined (JA113DEMO) - CHAR16 zVersionLabel[256] = { L"Release JA2 Demo - v1.13.8531 (Development Build)" }; + CHAR16 zVersionLabel[256] = { L"Release JA2 Demo - v1.13.8537 (Development Build)" }; #else - CHAR16 zVersionLabel[256] = { L"Release v1.13.8531 (Development Build)" }; + CHAR16 zVersionLabel[256] = { L"Release v1.13.8537 (Development Build)" }; #endif #endif -CHAR8 czVersionNumber[16] = { "Build 18.02.28" }; //YY.MM.DD +CHAR8 czVersionNumber[16] = { "Build 18.03.04" }; //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 6dfd1401..7da1a337 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 INDIVIDUAL_MILITIA_EXP_FLOAT 177 // Flugente: changed the way we store individual militia experience #define CHAT_TO_DISTRACT 176 // Flugente: internal variable allows us to distract enemies by engrossing them in conversation #define INDIVIDUAL_MILITIA_RANKFIX 175 // Flugente: internal individual militia change requires variable change #define DRAGPERSONS 174 // Flugente: we can drag people and corpses now @@ -95,7 +96,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 CHAT_TO_DISTRACT +#define SAVE_GAME_VERSION INDIVIDUAL_MILITIA_EXP_FLOAT //#define RUSSIANGOLD #ifdef __cplusplus diff --git a/Laptop/finances.cpp b/Laptop/finances.cpp index 3f4a22ac..c7f9aa4d 100644 --- a/Laptop/finances.cpp +++ b/Laptop/finances.cpp @@ -1585,6 +1585,18 @@ void ProcessTransactionString(STR16 pString, FinanceUnitPtr pFinance) case WORKERS_TRAINED: swprintf( pString, L"%s", pTransactionText[pFinance->ubCode] ); break; + + case PROMOTE_MILITIA: + { + CHAR16 str[128]; + UINT8 ubSectorX; + UINT8 ubSectorY; + ubSectorX = (UINT8)SECTORX( pFinance->ubSecondCode ); + ubSectorY = (UINT8)SECTORY( pFinance->ubSecondCode ); + GetSectorIDString( ubSectorX, ubSectorY, 0, str, TRUE ); + swprintf( pString, pTransactionText[PROMOTE_MILITIA], str ); + } + break; } } diff --git a/Laptop/finances.h b/Laptop/finances.h index 5d9974de..e369b893 100644 --- a/Laptop/finances.h +++ b/Laptop/finances.h @@ -58,6 +58,7 @@ enum PMC_CONTRACT, // Flugente: hired militia from a PMC SAM_REPAIR, // Flugente: repair SAM site WORKERS_TRAINED, // Flugente: train workers + PROMOTE_MILITIA, // Flugente: drill militia TEXT_NUM_FINCANCES }; diff --git a/Strategic/Assignments.cpp b/Strategic/Assignments.cpp index c45c76f6..31cd69dc 100644 --- a/Strategic/Assignments.cpp +++ b/Strategic/Assignments.cpp @@ -154,6 +154,15 @@ enum { INTEL_MENU_CANCEL, }; +enum { + MILITIA_MENU_TRAIN, + MILITIA_MENU_DRILL, + MILITIA_MENU_DOCTOR, + MILITIA_MENU_CANCEL, + + MILITIA_MENU_MAX, +}; + /* CHRISL: Adjusted enumerations to allow for seperation of the three different pocket types in the new inventory system. */ @@ -200,6 +209,7 @@ INT32 ghSquadBox = -1; INT32 ghVehicleBox = -1; INT32 ghRepairBox = -1; INT32 ghMoveItemBox = -1; +INT32 ghMilitiaBox = -1; INT32 ghDiseaseBox = -1; INT32 ghSpyBox = -1; INT32 ghTrainingBox = -1; @@ -222,7 +232,6 @@ INT32 ghPrisonerBox = -1; // the x,y position of assignment pop up in tactical INT16 gsAssignmentBoxesX, gsAssignmentBoxesY; - // assignment menu mouse regions MOUSE_REGION gAssignmentMenuRegion[ MAX_ASSIGN_STRING_COUNT ]; MOUSE_REGION gTrainingMenuRegion[ MAX_TRAIN_STRING_COUNT ]; @@ -235,6 +244,7 @@ MOUSE_REGION gRepairMenuRegion[ 20 ]; MOUSE_REGION gMoveItem[MOVEITEM_MAX_SECTORS_WITH_MODIFIER + 1]; MOUSE_REGION gDisease[DISEASE_MENU_CANCEL + 1]; MOUSE_REGION gSpy[INTEL_MENU_CANCEL + 1]; +MOUSE_REGION gMilitia[MILITIA_MENU_MAX]; UINT16 usMoveItemSectors[MOVEITEM_MAX_SECTORS_WITH_MODIFIER]; @@ -403,6 +413,9 @@ UINT16 TotalMedicalKitPoints(SOLDIERTYPE *pSoldier); // handle doctor in this sector void HandleDoctorsInSector( INT16 sX, INT16 sY, INT8 bZ ); +// handle doctoring militia +void HandleDoctorMilitia(); + // handle any repair man in sector void HandleRepairmenInSector( INT16 sX, INT16 sY, INT8 bZ ); @@ -523,6 +536,7 @@ void HandleShadingOfLinesForVehicleMenu( void ); void HandleShadingOfLinesForRepairMenu( void ); void HandleShadingOfLinesForDiseaseMenu(); void HandleShadingOfLinesForSpyMenu(); +void HandleShadingOfLinesForMilitiaMenu(); void HandleShadingOfLinesForTrainingMenu( void ); void HandleShadingOfLinesForAttributeMenus( void ); // HEADROCK HAM 3.6: Shade Facility Box Lines @@ -549,6 +563,7 @@ BOOLEAN DisplayFacilityAssignmentMenu( SOLDIERTYPE *pSoldier, UINT8 ubFacilityTy BOOLEAN DisplayMoveItemsMenu( SOLDIERTYPE *pSoldier ); BOOLEAN DisplayDiseaseMenu( SOLDIERTYPE *pSoldier ); BOOLEAN DisplaySpyMenu( SOLDIERTYPE *pSoldier ); +BOOLEAN DisplayMilitiaMenu( SOLDIERTYPE *pSoldier ); // create menus void CreateEPCBox( void ); @@ -558,6 +573,7 @@ void CreateRepairBox( void ); void CreateMoveItemBox( void ); void CreateDiseaseBox(); void CreateSpyBox(); +void CreateMilitiaBox(); // HEADROCK HAM 3.6: Facility Box. void CreateFacilityBox( void ); void CreateFacilityAssignmentBox( void ); @@ -638,6 +654,7 @@ BOOLEAN CanCharacterRepairAnotherSoldiersStuff( SOLDIERTYPE *pSoldier, SOLDIERTY // can this character EVER train militia? BOOLEAN BasicCanCharacterTrainMilitia( SOLDIERTYPE *pCharacter ); +BOOLEAN BasicCanCharacterDrillMilitia( SOLDIERTYPE *pSoldier ); BOOLEAN BasicCanCharacterTrainMobileMilitia( SOLDIERTYPE *pSoldier ); // Can this character EVER work in any facility? BOOLEAN BasicCanCharacterFacility( SOLDIERTYPE *pSoldier ); @@ -760,7 +777,6 @@ void ChangeSoldiersAssignment( SOLDIERTYPE *pSoldier, INT8 bAssignment ) fMapPanelDirty = TRUE; } - BOOLEAN BasicCanCharacterAssignment( SOLDIERTYPE * pSoldier, BOOLEAN fNotInCombat ) { AssertNotNIL(pSoldier); @@ -778,8 +794,6 @@ BOOLEAN BasicCanCharacterAssignment( SOLDIERTYPE * pSoldier, BOOLEAN fNotInComba return( TRUE ); } - - /* BOOLEAN CanSoldierAssignment( SOLDIERTYPE *pSoldier, INT8 bAssignment ) { @@ -900,7 +914,7 @@ BOOLEAN CanCharacterDoctor( SOLDIERTYPE *pSoldier ) // find med kit // CHRISL: Changed to dynamically determine max inventory locations. - for (bPocket = HANDPOS; bPocket < NUM_INV_SLOTS; bPocket++) + for (bPocket = HANDPOS; bPocket < NUM_INV_SLOTS; ++bPocket) { // doctoring is allowed using either type of med kit (but first aid kit halves doctoring effectiveness) if( IsMedicalKitItem( &( pSoldier -> inv[ bPocket ] ) ) ) @@ -919,6 +933,30 @@ BOOLEAN CanCharacterDoctor( SOLDIERTYPE *pSoldier ) return ( TRUE ); } +// can this character doctor militia (assignmentwise)? +BOOLEAN CanCharacterDoctorMilitia( SOLDIERTYPE *pSoldier ) +{ + if ( !gGameExternalOptions.fIndividualMilitia || !gGameExternalOptions.fIndividualMilitia_ManageHealth ) + return FALSE; + + if ( !CanCharacterDoctor( pSoldier ) ) + return FALSE; + + UINT8 sector = SECTOR( pSoldier->sSectorX, pSoldier->sSectorY ); + + std::vector::iterator itend = gIndividualMilitiaVector.end(); + for ( std::vector::iterator it = gIndividualMilitiaVector.begin(); it != itend; ++it ) + { + if ( !( ( *it ).flagmask & ( MILITIAFLAG_DEAD | MILITIAFLAG_FIRED ) ) && ( *it ).sector == sector ) + { + if ( ( *it ).healthratio < 100.0f ) + return TRUE; + } + } + + return FALSE; +} + // can this character diagnose diseases? BOOLEAN CanCharacterDiagnoseDisease( SOLDIERTYPE *pSoldier ) { @@ -1562,6 +1600,176 @@ BOOLEAN BasicCanCharacterTrainMilitia( SOLDIERTYPE *pSoldier ) return ( TRUE ); } +BOOLEAN BasicCanCharacterDrillMilitia( SOLDIERTYPE *pSoldier ) +{ + ///////////////////////////////////////////////////// + // Tests whether character can do assignments at all! + + AssertNotNIL( pSoldier ); + + if ( !BasicCanCharacterAssignment( pSoldier, TRUE ) ) + { + return( FALSE ); + } + + // Flugente: we can't perform most assignments while concealed + if ( SPY_LOCATION( pSoldier->bAssignment ) ) + return( FALSE ); + + // make sure character is alive and conscious + if ( pSoldier->stats.bLife < OKLIFE ) + { + // dead or unconscious... + return ( FALSE ); + } + + // underground training is not allowed (code doesn't support and it's a reasonable enough limitation) + if ( pSoldier->bSectorZ != 0 ) + { + return( FALSE ); + } + + // Is character on the way into/out of Arulco? + if ( IsCharacterInTransit( pSoldier ) == TRUE ) + { + return ( FALSE ); + } + + // Is character travelling between sectors? + if ( CharacterIsBetweenSectors( pSoldier ) ) + { + return( FALSE ); + } + + // Is character an Escortee? + if ( pSoldier->ubWhatKindOfMercAmI == MERC_TYPE__EPC ) + { + // epcs can't do this + return( FALSE ); + } + + // Is character a Vehicle or Robot? + if ( ( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE ) || AM_A_ROBOT( pSoldier ) ) + { + return( FALSE ); + } + + // enemies in sector + if ( NumNonPlayerTeamMembersInSector( pSoldier->sSectorX, pSoldier->sSectorY, ENEMY_TEAM ) > 0 ) + { + return( FALSE ); + } + + return ( TRUE ); +} + +BOOLEAN CanCharacterMilitiaAssignment( SOLDIERTYPE *pSoldier ) +{ + if ( CanCharacterTrainMilitia( pSoldier ) ) + return TRUE; + + if ( CanCharacterDrillMilitia( pSoldier ) ) + return TRUE; + + if ( CanCharacterDoctorMilitia( pSoldier ) ) + return TRUE; + + return FALSE; +} + +BOOLEAN CanCharacterDrillMilitia( SOLDIERTYPE *pSoldier, BOOLEAN aErrorReport ) +{ + if ( !gGameExternalOptions.fIndividualMilitia ) + return FALSE; + + AssertNotNIL( pSoldier ); + + if ( LaptopSaveInfo.iCurrentBalance <= 0 ) + { + if ( aErrorReport ) + DoScreenIndependantMessageBox( sATMText[4], MSG_BOX_FLAG_OK, NULL ); + return( FALSE ); + } + + if ( !BasicCanCharacterDrillMilitia( pSoldier ) ) + { + if ( aErrorReport ) + DoScreenIndependantMessageBox( L"Assignment not possible at the moment", MSG_BOX_FLAG_OK, NULL ); + return( FALSE ); + } + + // enemies in sector + if ( NumNonPlayerTeamMembersInSector( pSoldier->sSectorX, pSoldier->sSectorY, ENEMY_TEAM ) > 0 ) + { + if ( aErrorReport ) + DoScreenIndependantMessageBox( L"Assignment not possible while enemies are still around.", MSG_BOX_FLAG_OK, NULL ); + return( FALSE ); + } + + // Has leadership skill? + if ( pSoldier->stats.bLeadership <= 0 ) + { + if ( aErrorReport ) + DoScreenIndependantMessageBox( L"Not enough leadership.", MSG_BOX_FLAG_OK, NULL ); + return ( FALSE ); + } + + // HEADROCK HAM 3: When "Minimum Leadership for Militia Training" is enforced, this value holds the + // merc's effective leadership, after the "TEACHER" trait is taken into account. + UINT16 usEffectiveLeadership; + + // HEADROCK HAM 3: Determine whether the merc has enough leadership to train militia. The teacher trait may + // increase or decrease the effective skill. + if ( gGameExternalOptions.ubMinimumLeadershipToTrainMilitia > 0 ) + { + // Read BASE leadership + usEffectiveLeadership = pSoldier->stats.bLeadership; + + if ( gGameOptions.fNewTraitSystem ) // SANDRO - old/new traits + { + if ( HAS_SKILL_TRAIT( pSoldier, TEACHING_NT ) ) + { + // bonus from Teaching trait + usEffectiveLeadership = ( usEffectiveLeadership * ( 100 + gSkillTraitValues.ubTGEffectiveLDRToTrainMilitia ) / 100 ); + } + } + // Apply modifier for TEACHER trait, if that feature is activated + else if ( gGameExternalOptions.usTeacherTraitEffectOnLeadership > 0 && gGameExternalOptions.usTeacherTraitEffectOnLeadership != 100 ) + { + // Modifier applied once for each TEACHING level. + for ( UINT8 i = 0; i < NUM_SKILL_TRAITS( pSoldier, TEACHING_OT ); i++ ) + { + // This is a percentage modifier. + usEffectiveLeadership = ( usEffectiveLeadership * gGameExternalOptions.usTeacherTraitEffectOnLeadership ) / 100; + } + } + + usEffectiveLeadership = __min( 100, usEffectiveLeadership ); + + // Is leadership too low to proceed? + if ( usEffectiveLeadership < gGameExternalOptions.ubMinimumLeadershipToTrainMilitia ) + { + if ( aErrorReport ) + DoScreenIndependantMessageBox( L"Not enough leadership.", MSG_BOX_FLAG_OK, NULL ); + return ( FALSE ); + } + } + + // are any militia that could be promoted present? + UINT32 militiaid = 0; + MILITIA militia; + if ( GetIdOfIndividualMilitiaWithClassSector( SOLDIER_CLASS_GREEN_MILITIA, SECTOR( pSoldier->sSectorX, pSoldier->sSectorY ), militiaid ) || + ( gGameExternalOptions.gfTrainVeteranMilitia && GetIdOfIndividualMilitiaWithClassSector( SOLDIER_CLASS_REG_MILITIA, SECTOR( pSoldier->sSectorX, pSoldier->sSectorY ), militiaid ) ) ) + { + if ( GetMilitia( militiaid, &militia ) ) + return TRUE; + } + + if ( aErrorReport ) + DoScreenIndependantMessageBox( L"No militia that can be trained present.", MSG_BOX_FLAG_OK, NULL ); + return FALSE; +} + // Determines whether the character has the required condition to train Militia at this time. // The conditions tested in this function might change WHILE THE CHARACTER IS ALREADY TRAINING MILITIA, which is // how this function is normally different from "BasicCan...". @@ -2691,6 +2899,9 @@ void UpdateAssignments() // Flugente: individual militia HandleHourlyMilitiaHealing(); + // Flugente: handle doctoring militia + HandleDoctorMilitia(); + // Flugente: handle militia command HandleMilitiaCommand(); @@ -3767,6 +3978,62 @@ void HandleDoctorsInSector( INT16 sX, INT16 sY, INT8 bZ ) // total healing pts for this sector, now heal people } +// handle doctoring militia +void HandleDoctorMilitia() +{ + INT32 cnt = 0; + + // set psoldier as first in merc ptrs + SOLDIERTYPE* pSoldier = MercPtrs[0]; + + // will handle doctor/patient relationship in sector + + // go through list of characters, find all doctors in sector + for ( pSoldier = MercPtrs[cnt]; cnt <= gTacticalStatus.Team[gbPlayerNum].bLastID; ++cnt, ++pSoldier ) + { + if ( pSoldier && pSoldier->bActive && !pSoldier->bSectorZ && pSoldier->bAssignment == DOCTOR_MILITIA && !( pSoldier->flags.fMercAsleep ) ) + { + // character is in sector, check if can doctor, if so...heal people + if ( EnoughTimeOnAssignment( pSoldier ) && CanCharacterDoctorMilitia( pSoldier ) ) + { + UINT16 max = 0; + UINT16 healpoints = CalculateHealingPointsForDoctor( pSoldier, &max, TRUE ); + + // how good is the doctor? + INT8 sDoctortraits = gGameOptions.fNewTraitSystem ? NUM_SKILL_TRAITS( pSoldier, DOCTOR_NT ) : 0; + + INT8 bMedFactor = 1; // basic medical factor + // Added a penalty for not experienced mercs, they consume the bag faster + // if healing an repairing stat at the same time, this is increased again, but we wont recalculate for now + if ( gGameOptions.fNewTraitSystem && !sDoctortraits && ( pSoldier->stats.bMedical < 50 ) ) + bMedFactor += 1; + + // we are limited by our supplies + // calculate how much total points we have in all medical bags - this ultimately limits how much we can heal + UINT16 usTotalMedPoints = TotalMedicalKitPoints( pSoldier ); + + healpoints = min( healpoints, ( usTotalMedPoints * 100 ) / bMedFactor ); + + // militia less effort for healing (how would we reasistically treat 30 wounded militia otherwise?), so simply alter the points + // each healing point normally represents 1 hundreth of a HP + healpoints *= gGameExternalOptions.dIndividualMilitiaDoctorHealModifier; + + UINT32 healpointsused = MilitiaIndividual_Heal( healpoints, SECTOR( pSoldier->sSectorX, pSoldier->sSectorY ) ); + + // Finally use all kit points (we are sure, we have that much) + if ( !UseTotalMedicalKitPoints( pSoldier, max( 1, ( (healpointsused / gGameExternalOptions.dIndividualMilitiaDoctorHealModifier ) * bMedFactor ) / 100 ) ) ) + { + // throw message if this went wrong for feedback on debugging + ScreenMsg( FONT_MCOLOR_RED, MSG_TESTVERSION, L"Warning! UseTotalMedicalKitPoints returned false, not all points were probably used." ); + } + + if ( healpointsused < healpoints ) + AssignmentDone( pSoldier, TRUE, TRUE ); + } + } + } +} + void UpdatePatientsWhoAreDoneHealing( void ) { INT32 cnt = 0; @@ -5481,6 +5748,7 @@ void FatigueCharacter( SOLDIERTYPE *pSoldier ) CASE_REPAIR: case TRAIN_TEAMMATE: case TRAIN_TOWN: + case DRILL_MILITIA: break; case TRAIN_BY_OTHER: case TRAIN_SELF: @@ -5754,6 +6022,65 @@ void HandleTrainingInSector( INT16 sMapX, INT16 sMapY, INT8 bZ ) } } } + + // Flugente: drill militia - promote existing militia without creating new ones + if ( gGameExternalOptions.fIndividualMilitia ) + { + FLOAT drillpoints = 0; + for ( uiCnt = 0, pTrainer = MercPtrs[uiCnt]; uiCnt <= gTacticalStatus.Team[gbPlayerNum].bLastID; ++uiCnt, pTrainer++ ) + { + if ( pTrainer->bActive && ( pTrainer->sSectorX == sMapX ) && ( pTrainer->sSectorY == sMapY ) && ( pTrainer->bSectorZ == bZ ) ) + { + // HEADROCK HAM 3.6: TRAIN_MOBILE also possible now. Handled the same way. + if ( pTrainer->bAssignment == DRILL_MILITIA && ( EnoughTimeOnAssignment( pTrainer ) ) && ( pTrainer->flags.fMercAsleep == FALSE ) ) + { + drillpoints += GetTownTrainPtsForCharacter( pTrainer, &usMaxPts ); + } + } + } + + // a normal militia training session requires 10000 points. + // such a session would allow promoting gGameExternalOptions.iTrainingSquadSize + // a green militia requires gGameExternalOptions.usIndividualMilitia_PromotionPoints_To_Regular to promote + // it thus follows that one point of militia experience is worth (10000 / gGameExternalOptions.iTrainingSquadSize) / gGameExternalOptions.usIndividualMilitia_PromotionPoints_To_Regular training points + + drillpoints *= ( gGameExternalOptions.iTrainingSquadSize * gGameExternalOptions.usIndividualMilitia_PromotionPoints_To_Regular / 10000.0 ); + + // we also need to pay for training we applied (otherwise promoting via normal training would + // a normal training session costs gGameExternalOptions.iMilitiaTrainingCost * gGameExternalOptions.iRegularCostModifier + // it promotes gGameExternalOptions.iTrainingSquadSize militia with gGameExternalOptions.usIndividualMilitia_PromotionPoints_To_Regular points each + // thus a point costs gGameExternalOptions.iMilitiaTrainingCost * gGameExternalOptions.iRegularCostModifier / ( gGameExternalOptions.iTrainingSquadSize * gGameExternalOptions.usIndividualMilitia_PromotionPoints_To_Regular) points + FLOAT costperpoint = ( FLOAT)(gGameExternalOptions.iMilitiaTrainingCost * gGameExternalOptions.iRegularCostModifier / ( gGameExternalOptions.iTrainingSquadSize * gGameExternalOptions.usIndividualMilitia_PromotionPoints_To_Regular )); + + FLOAT totalcost = drillpoints * costperpoint; + + if ( totalcost > 0 && LaptopSaveInfo.iCurrentBalance < totalcost ) + { + drillpoints *= LaptopSaveInfo.iCurrentBalance / totalcost; + } + + FLOAT drillpoints_used = PromoteIndividualMilitiaInSector( SECTOR( sMapX, sMapY ), drillpoints ); + + if ( drillpoints_used > 0 ) + { + for ( uiCnt = 0, pTrainer = MercPtrs[uiCnt]; uiCnt <= gTacticalStatus.Team[gbPlayerNum].bLastID; ++uiCnt, ++pTrainer ) + { + if ( pTrainer->bActive && ( pTrainer->sSectorX == sMapX ) && ( pTrainer->sSectorY == sMapY ) && ( pTrainer->bSectorZ == bZ ) ) + { + if ( pTrainer->bAssignment == DRILL_MILITIA && ( EnoughTimeOnAssignment( pTrainer ) ) && ( pTrainer->flags.fMercAsleep == FALSE ) ) + { + INT16 personaldrillpoints = GetTownTrainPtsForCharacter( pTrainer, &usMaxPts ); + + // trainer gains leadership - training argument is FALSE, because the trainer is not the one training! + StatChange( pTrainer, LDRAMT, (UINT16)( 1 + ( ( personaldrillpoints * drillpoints_used / drillpoints ) / 200 ) ), FALSE ); + StatChange( pTrainer, WISDOMAMT, (UINT16)( 1 + ( ( personaldrillpoints * drillpoints_used / drillpoints ) / 400 ) ), FALSE ); + } + } + } + + AddTransactionToPlayersBook( PROMOTE_MILITIA, SECTOR( sMapX, sMapY ), GetWorldTotalMin(), -( drillpoints_used * costperpoint ) ); + } + } } // handle radio scanning assignments @@ -8161,11 +8488,11 @@ INT16 GetTownTrainPtsForCharacter( SOLDIERTYPE *pTrainer, UINT16 *pusMaxPts ) // HEADROCK HAM 3.5: Training bonus given by local facilities if (pTrainer->bSectorZ == 0) { - for (UINT16 cnt = 0; cnt < NUM_FACILITY_TYPES; cnt++) + for (UINT16 cnt = 0; cnt < NUM_FACILITY_TYPES; ++cnt) { if (gFacilityLocations[SECTOR(pTrainer->sSectorX, pTrainer->sSectorY)][cnt].fFacilityHere) { - if (pTrainer->bAssignment == TRAIN_TOWN) + if (pTrainer->bAssignment == TRAIN_TOWN || pTrainer->bAssignment == DRILL_MILITIA ) { sTrainingBonus += (100 - gFacilityTypes[cnt].usMilitiaTraining); } @@ -8295,14 +8622,11 @@ void AssignmentDone( SOLDIERTYPE *pSoldier, BOOLEAN fSayQuote, BOOLEAN fMeToo ) if ( fSayQuote ) { // HEADROCK HAM 3.6: Separated Militia Training - if ( ( fMeToo == FALSE ) && (pSoldier->bAssignment == TRAIN_TOWN || pSoldier->bAssignment == TRAIN_MOBILE ) ) + if ( ( fMeToo == FALSE ) && (pSoldier->bAssignment == TRAIN_TOWN || pSoldier->bAssignment == TRAIN_MOBILE || pSoldier->bAssignment == DRILL_MILITIA ) ) { TacticalCharacterDialogue( pSoldier, QUOTE_ASSIGNMENT_COMPLETE ); - if( pSoldier->bAssignment == TRAIN_TOWN || pSoldier->bAssignment == TRAIN_MOBILE ) - { - AddSectorForSoldierToListOfSectorsThatCompletedMilitiaTraining( pSoldier ); - } + AddSectorForSoldierToListOfSectorsThatCompletedMilitiaTraining( pSoldier ); } } @@ -9710,6 +10034,16 @@ void HandleShadingOfLinesForAssignmentMenus( void ) { ShadeStringInBox( ghAssignmentBox, ASSIGN_MENU_SPY ); } + + // militia + if ( CanCharacterMilitiaAssignment( pSoldier ) ) + { + UnShadeStringInBox( ghAssignmentBox, ASSIGN_MENU_MILITIA ); + } + else + { + ShadeStringInBox( ghAssignmentBox, ASSIGN_MENU_MILITIA ); + } } } @@ -9725,6 +10059,7 @@ void HandleShadingOfLinesForAssignmentMenus( void ) // disease menu HandleShadingOfLinesForDiseaseMenu(); HandleShadingOfLinesForSpyMenu(); + HandleShadingOfLinesForMilitiaMenu(); // training submenu HandleShadingOfLinesForTrainingMenu( ); @@ -9803,6 +10138,7 @@ void DetermineWhichAssignmentMenusCanBeShown( void ) CreateDestroyMouseRegionForMoveItemMenu(); CreateDestroyMouseRegionForDiseaseMenu(); CreateDestroyMouseRegionForSpyMenu(); + CreateDestroyMouseRegionForMilitiaMenu(); // HEADROCK HAM 3.6: Facility Menu, Submenu CreateDestroyMouseRegionForFacilityMenu( ); CreateDestroyMouseRegionsForFacilityAssignmentMenu( ); @@ -9857,6 +10193,12 @@ void DetermineWhichAssignmentMenusCanBeShown( void ) fTeamPanelDirty = TRUE; gfRenderPBInterface = TRUE; } + if ( IsBoxShown( ghMilitiaBox ) ) + { + HideBox( ghMilitiaBox ); + fTeamPanelDirty = TRUE; + gfRenderPBInterface = TRUE; + } if ( IsBoxShown( ghAttributeBox ) ) { HideBox( ghAttributeBox ); @@ -9944,6 +10286,7 @@ void DetermineWhichAssignmentMenusCanBeShown( void ) CreateDestroyMouseRegionForMoveItemMenu(); CreateDestroyMouseRegionForDiseaseMenu( ); CreateDestroyMouseRegionForSpyMenu(); + CreateDestroyMouseRegionForMilitiaMenu(); CreateDestroyMouseRegionsForSnitchMenu( ); CreateDestroyMouseRegionsForSnitchToggleMenu( ); CreateDestroyMouseRegionsForSnitchSectorMenu( ); @@ -10061,6 +10404,24 @@ void DetermineWhichAssignmentMenusCanBeShown( void ) gfRenderPBInterface = TRUE; } } + + // militia menu + if ( gAssignMenuState == ASMENU_MILITIA ) + { + HandleShadingOfLinesForMilitiaMenu(); + ShowBox( ghMilitiaBox ); + } + else + { + // hide box + if ( IsBoxShown( ghMilitiaBox ) ) + { + HideBox( ghMilitiaBox ); + fTeamPanelDirty = TRUE; + fMapPanelDirty = TRUE; + gfRenderPBInterface = TRUE; + } + } // ATTRIBUTE menu if( fShowAttributeMenu == TRUE ) @@ -10294,6 +10655,7 @@ void ClearScreenMaskForMapScreenExit( void ) CreateDestroyMouseRegionForMoveItemMenu(); CreateDestroyMouseRegionForDiseaseMenu( ); CreateDestroyMouseRegionForSpyMenu(); + CreateDestroyMouseRegionForMilitiaMenu(); // HEADROCK HAM 3.6: Facility Menu CreateDestroyMouseRegionForFacilityMenu( ); CreateDestroyMouseRegionsForSnitchMenu( ); @@ -12114,63 +12476,7 @@ void TrainingMenuBtnCallback( MOUSE_REGION * pRegion, INT32 iReason ) DetermineBoxPositions( ); break; - case( TRAIN_MENU_TOWN): - - // Full test of Character and Sector to see if this training is possible at the moment. - if( !BasicCanCharacterTrainMilitia(pSoldier) ) - { - // No feedback. The menu options should be greyed out, anyway. - break; - } - - // Check for specific errors why this merc should not be able to train, - // and display a specific error message if one is encountered. - if( !CanCharacterTrainMilitiaWithErrorReport(pSoldier) ) - { - // Error found. Breaking. Note that the above function DOES display feedback if an error is - // encountered at all. - break; - } - - // PASSED ALL THE TESTS - ALLOW SOLDIER TO TRAIN MILITIA HERE - - pSoldier->bOldAssignment = pSoldier->bAssignment; - - if( ( pSoldier->bAssignment != TRAIN_TOWN ) ) - { - SetTimeOfAssignmentChangeForMerc( pSoldier ); - } - - MakeSoldiersTacticalAnimationReflectAssignment( pSoldier ); - - // stop showing menu - fShowAssignmentMenu = FALSE; - giAssignHighLine = -1; - - // remove from squad - - if( pSoldier->bOldAssignment == VEHICLE ) - { - TakeSoldierOutOfVehicle( pSoldier ); - } - RemoveCharacterFromSquads( pSoldier ); - - ChangeSoldiersAssignment( pSoldier, TRAIN_TOWN ); - - // assign to a movement group - AssignMercToAMovementGroup( pSoldier ); - if( SectorInfo[ SECTOR( pSoldier->sSectorX, pSoldier->sSectorY ) ].fMilitiaTrainingPaid == FALSE ) - { - // show a message to confirm player wants to charge cost - HandleInterfaceMessageForCostOfTrainingMilitia( pSoldier ); - } - else - { - SetAssignmentForList( TRAIN_TOWN, 0 ); - } - gfRenderPBInterface = TRUE; - break; - + // HEADROCK HAM 3.6: New separate Mobile Militia training. case( TRAIN_MENU_MOBILE ): @@ -13193,6 +13499,26 @@ void AssignmentMenuBtnCallback( MOUSE_REGION * pRegion, INT32 iReason ) } break; + case ASSIGN_MENU_MILITIA: + if ( CanCharacterMilitiaAssignment( pSoldier ) ) + { + gAssignMenuState = ASMENU_NONE; + + fShowPrisonerMenu = FALSE; + fShownContractMenu = FALSE; + fTeamPanelDirty = TRUE; + fMapScreenBottomDirty = TRUE; + + pSoldier->bOldAssignment = pSoldier->bAssignment; + + if ( DisplayMilitiaMenu( pSoldier ) ) + { + gAssignMenuState = ASMENU_MILITIA; + DetermineBoxPositions(); + } + } + break; + // HEADROCK HAM 3.6: New assignments for Facility operation. case( ASSIGN_MENU_FACILITY ): if ( BasicCanCharacterFacility( pSoldier ) ) @@ -13623,6 +13949,38 @@ void CreateSpyBox() SetBoxPosition( ghSpyBox, pPoint ); } + +void CreateMilitiaBox() +{ + SGPPoint pPoint; + SGPRect pDimensions; + + CreatePopUpBox( &ghMilitiaBox, FacilityAssignmentDimensions, FacilityAssignmentPosition, ( POPUP_BOX_FLAG_CLIP_TEXT | POPUP_BOX_FLAG_CENTER_TEXT | POPUP_BOX_FLAG_RESIZE ) ); + SetBoxBuffer( ghMilitiaBox, FRAME_BUFFER ); + SetBorderType( ghMilitiaBox, guiPOPUPBORDERS ); + SetBackGroundSurface( ghMilitiaBox, guiPOPUPTEX ); + SetMargins( ghMilitiaBox, 6, 6, 4, 4 ); + SetLineSpace( ghMilitiaBox, 2 ); + + // set current box to this one + SetCurrentBox( ghMilitiaBox ); + + // resize box to text + ResizeBoxToText( ghMilitiaBox ); + + DetermineBoxPositions(); + + GetBoxPosition( ghMilitiaBox, &pPoint ); + GetBoxSize( ghMilitiaBox, &pDimensions ); + + if ( giBoxY + pDimensions.iBottom > 479 ) + { + pPoint.iY = FacilityAssignmentPosition.iY = 479 - pDimensions.iBottom; + } + + SetBoxPosition( ghMilitiaBox, pPoint ); +} + void CreateSnitchBox() { UINT32 hStringHandle; @@ -14110,7 +14468,7 @@ void CreateTrainingBox( void ) // add strings for box - for(uiCounter=0; uiCounter < MAX_TRAIN_STRING_COUNT; uiCounter++) + for(uiCounter=0; uiCounter < MAX_TRAIN_STRING_COUNT; ++uiCounter) { AddMonoString(&hStringHandle, pTrainingMenuStrings[uiCounter]); @@ -14358,6 +14716,9 @@ BOOLEAN CreateDestroyAssignmentPopUpBoxes( void ) RemoveBox( ghSpyBox ); ghSpyBox = -1; + RemoveBox( ghMilitiaBox ); + ghMilitiaBox = -1; + RemoveBox(ghTrainingBox); ghTrainingBox = -1; @@ -14543,6 +14904,13 @@ void DetermineBoxPositions( void ) SetBoxPosition( ghSnitchSectorBox, pNewPoint ); } } + else if ( gAssignMenuState == ASMENU_MILITIA && ( ghMilitiaBox != -1 ) ) + { + pNewPoint.iY += ( ( GetFontHeight( MAP_SCREEN_FONT ) + 2 ) * ASSIGN_MENU_MILITIA ); + + SetBoxPosition( ghMilitiaBox, pNewPoint ); + CreateDestroyMouseRegionForMilitiaMenu(); + } if ( fShowPrisonerMenu && (ghPrisonerBox != -1) ) { @@ -14857,6 +15225,28 @@ void CheckAndUpdateTacticalAssignmentPopUpPositions( void ) SetBoxPosition( ghFacilityBox, pPoint ); } + else if ( gAssignMenuState == ASMENU_MILITIA ) + { + GetBoxSize( ghMilitiaBox, &pDimensions ); + + if ( gsAssignmentBoxesX + pDimensions2.iRight + pDimensions.iRight >= SCREEN_WIDTH ) + { + gsAssignmentBoxesX = (INT16)( ( SCREEN_WIDTH - 1 ) - ( pDimensions2.iRight + pDimensions.iRight ) ); + SetRenderFlags( RENDER_FLAG_FULL ); + } + + if ( gsAssignmentBoxesY + pDimensions2.iBottom + ( ( GetFontHeight( MAP_SCREEN_FONT ) + 2 ) * ASSIGN_MENU_MILITIA ) >= ( SCREEN_HEIGHT - 120 ) ) + { + gsAssignmentBoxesY = (INT16)( ( SCREEN_HEIGHT - 121 ) - ( pDimensions2.iBottom ) - ( ( GetFontHeight( MAP_SCREEN_FONT ) + 2 ) * ASSIGN_MENU_MILITIA ) ); + SetRenderFlags( RENDER_FLAG_FULL ); + } + + pPoint.iX = gsAssignmentBoxesX + pDimensions2.iRight; + pPoint.iY = gsAssignmentBoxesY; + pPoint.iY += ( ( GetFontHeight( MAP_SCREEN_FONT ) + 2 ) * ASSIGN_MENU_MILITIA ); + + SetBoxPosition( ghMilitiaBox, pPoint ); + } // HEADROCK HAM 3.6: Facility Sub-menu if ( fShowFacilityAssignmentMenu == TRUE ) @@ -15437,6 +15827,7 @@ void SetSoldierAssignment( SOLDIERTYPE *pSoldier, INT8 bAssignment, INT32 iParam AssignMercToAMovementGroup( pSoldier ); } break; + CASE_PATIENT: if( CanCharacterPatient( pSoldier ) ) { @@ -16008,6 +16399,11 @@ void SetSoldierAssignment( SOLDIERTYPE *pSoldier, INT8 bAssignment, INT32 iParam ChangeSoldiersAssignment( pSoldier, bAssignment ); AssignMercToAMovementGroup( pSoldier ); + + // set dirty flag + fTeamPanelDirty = TRUE; + fMapScreenBottomDirty = TRUE; + gfRenderPBInterface = TRUE; } break; @@ -16053,10 +16449,71 @@ void SetSoldierAssignment( SOLDIERTYPE *pSoldier, INT8 bAssignment, INT32 iParam ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, gzLateLocalizedString[ 18 ], zVehicleName[ pVehicleList[ iParam1 ].ubVehicleType ] ); } } - break; - } + break; - return; + case DOCTOR_MILITIA: + if ( CanCharacterDoctorMilitia( pSoldier ) ) + { + pSoldier->bOldAssignment = pSoldier->bAssignment; + + // remove from squad + RemoveCharacterFromSquads( pSoldier ); + + // remove from any vehicle + if ( pSoldier->bOldAssignment == VEHICLE ) + { + TakeSoldierOutOfVehicle( pSoldier ); + } + + if ( pSoldier->bAssignment != bAssignment ) + { + SetTimeOfAssignmentChangeForMerc( pSoldier ); + } + + ChangeSoldiersAssignment( pSoldier, bAssignment ); + AssignMercToAMovementGroup( pSoldier ); + + // set dirty flag + fTeamPanelDirty = TRUE; + fMapScreenBottomDirty = TRUE; + gfRenderPBInterface = TRUE; + } + break; + + case DRILL_MILITIA: + if ( CanCharacterDrillMilitia( pSoldier ) ) + { + // train militia + pSoldier->bOldAssignment = pSoldier->bAssignment; + + // set dirty flag + fTeamPanelDirty = TRUE; + fMapScreenBottomDirty = TRUE; + + // remove from squad + RemoveCharacterFromSquads( pSoldier ); + + // remove from any vehicle + if ( pSoldier->bOldAssignment == VEHICLE ) + { + TakeSoldierOutOfVehicle( pSoldier ); + } + + if ( ( pSoldier->bAssignment != bAssignment ) ) + { + SetTimeOfAssignmentChangeForMerc( pSoldier ); + } + + ChangeSoldiersAssignment( pSoldier, bAssignment ); + AssignMercToAMovementGroup( pSoldier ); + + // set dirty flag + fTeamPanelDirty = TRUE; + fMapScreenBottomDirty = TRUE; + gfRenderPBInterface = TRUE; + } + break; + } } @@ -16184,6 +16641,13 @@ BOOLEAN HandleAssignmentExpansionAndHighLightForAssignMenu( SOLDIERTYPE *pSoldie return( TRUE ); } break; + + case ASMENU_MILITIA: + { + HighLightBoxLine( ghAssignmentBox, ASSIGN_MENU_MILITIA ); + return( TRUE ); + } + break; } return( FALSE ); @@ -16309,30 +16773,7 @@ void HandleShadingOfLinesForTrainingMenu( void ) { UnShadeStringInBox( ghTrainingBox, TRAIN_MENU_SELF ); } - - // can character EVER train militia? - if( BasicCanCharacterTrainMilitia( pSoldier ) ) - { - // can he train here, now? - if( CanCharacterTrainMilitia( pSoldier ) ) - { - // unshade train militia line - UnShadeStringInBox( ghTrainingBox, TRAIN_MENU_TOWN ); - UnSecondaryShadeStringInBox( ghTrainingBox, TRAIN_MENU_TOWN ); - } - else - { - UnShadeStringInBox( ghTrainingBox, TRAIN_MENU_TOWN ); - SecondaryShadeStringInBox( ghTrainingBox, TRAIN_MENU_TOWN ); - } - } - else - { - UnSecondaryShadeStringInBox( ghTrainingBox, TRAIN_MENU_TOWN ); - // shade train militia line - ShadeStringInBox( ghTrainingBox, TRAIN_MENU_TOWN ); - } - + // HEADROCK HAM 3.6: Training Mobile Militia. // can character EVER train Mobile Militia? if( BasicCanCharacterTrainMobileMilitia( pSoldier ) ) @@ -17236,6 +17677,14 @@ void ReEvaluateEveryonesNothingToDo( BOOLEAN aDoExtensiveCheck ) fNothingToDo = !CanCharacterSpyAssignment( pSoldier ); break; + case DOCTOR_MILITIA: + fNothingToDo = !CanCharacterDoctorMilitia( pSoldier ); + break; + + case DRILL_MILITIA: + fNothingToDo = !CanCharacterDrillMilitia( pSoldier ); + break; + case VEHICLE: default: // squads fNothingToDo = FALSE; @@ -17563,6 +18012,24 @@ void SetAssignmentForList( INT8 bAssignment, INT8 bParam ) } break; + case DOCTOR_MILITIA: + if ( CanCharacterDoctorMilitia( pSoldier ) ) + { + pSoldier->bOldAssignment = pSoldier->bAssignment; + SetSoldierAssignment( pSoldier, bAssignment, bParam, 0, 0 ); + fItWorked = TRUE; + } + break; + + case DRILL_MILITIA: + if ( CanCharacterDrillMilitia( pSoldier ) ) + { + pSoldier->bOldAssignment = pSoldier->bAssignment; + SetSoldierAssignment( pSoldier, bAssignment, bParam, 0, 0 ); + fItWorked = TRUE; + } + break; + case( SQUAD_1 ): case( SQUAD_2 ): case( SQUAD_3 ): @@ -21922,6 +22389,7 @@ void CreateDestroyMouseRegionForDiseaseMenu( void ) // get dimensions..mostly for width GetBoxSize( ghDiseaseBox, &pDimensions ); + SetBoxSecondaryShade( ghDiseaseBox, FONT_YELLOW ); // get width iBoxWidth = pDimensions.iRight; @@ -22154,12 +22622,13 @@ void CreateDestroyMouseRegionForSpyMenu( void ) // get dimensions..mostly for width GetBoxSize( ghSpyBox, &pDimensions ); + SetBoxSecondaryShade( ghSpyBox, FONT_YELLOW ); // get width iBoxWidth = pDimensions.iRight; SetCurrentBox( ghSpyBox ); - + pSoldier = GetSelectedAssignSoldier( FALSE ); // conceal assignment @@ -22297,3 +22766,384 @@ void SpyMenuMvtCallback( MOUSE_REGION * pRegion, INT32 iReason ) UnHighLightBox( ghSpyBox ); } } + +// Flugente: militia menu +BOOLEAN DisplayMilitiaMenu( SOLDIERTYPE *pSoldier ) +{ + INT32 hStringHandle = 0; + INT32 iCount = 0; + + // first, clear pop up box + RemoveBox( ghMilitiaBox ); + ghMilitiaBox = -1; + + CreateMilitiaBox(); + SetCurrentBox( ghMilitiaBox ); + + AddMonoString( (UINT32 *)&hStringHandle, szMilitiaText[MILITIA_MENU_TRAIN] ); + + if ( gGameExternalOptions.fIndividualMilitia ) + { + AddMonoString( (UINT32 *)&hStringHandle, szMilitiaText[MILITIA_MENU_DRILL] ); + + if ( gGameExternalOptions.fIndividualMilitia_ManageHealth ) + { + AddMonoString( (UINT32 *)&hStringHandle, szMilitiaText[MILITIA_MENU_DOCTOR] ); + } + } + + AddMonoString( (UINT32 *)&hStringHandle, szMilitiaText[MILITIA_MENU_CANCEL] ); + + SetBoxFont( ghMilitiaBox, MAP_SCREEN_FONT ); + SetBoxHighLight( ghMilitiaBox, FONT_WHITE ); + SetBoxShade( ghMilitiaBox, FONT_GRAY7 ); + SetBoxForeground( ghMilitiaBox, FONT_LTGREEN ); + SetBoxBackground( ghMilitiaBox, FONT_BLACK ); + + // resize box to text + ResizeBoxToText( ghMilitiaBox ); + + CheckAndUpdateTacticalAssignmentPopUpPositions(); + + return TRUE; +} + +void HandleShadingOfLinesForMilitiaMenu( void ) +{ + if ( gAssignMenuState != ASMENU_MILITIA || ( ghMilitiaBox == -1 ) ) + return; + + SOLDIERTYPE* pSoldier = GetSelectedAssignSoldier( FALSE ); + + if ( !pSoldier ) + return; + + // can character EVER train militia? + if ( BasicCanCharacterTrainMilitia( pSoldier ) ) + { + // can he train here, now? + if ( CanCharacterTrainMilitia( pSoldier ) ) + { + // unshade train militia line + UnShadeStringInBox( ghMilitiaBox, MILITIA_MENU_TRAIN ); + } + else + { + SecondaryShadeStringInBox( ghMilitiaBox, MILITIA_MENU_TRAIN ); + } + } + else + { + // shade train militia line + ShadeStringInBox( ghMilitiaBox, MILITIA_MENU_TRAIN ); + } + + if ( gGameExternalOptions.fIndividualMilitia ) + { + if ( BasicCanCharacterDrillMilitia( pSoldier ) ) + { + // can he train here, now? + if ( CanCharacterDrillMilitia( pSoldier ) ) + { + UnShadeStringInBox( ghMilitiaBox, MILITIA_MENU_DRILL ); + } + else + { + SecondaryShadeStringInBox( ghMilitiaBox, MILITIA_MENU_DRILL ); + } + } + else + { + ShadeStringInBox( ghMilitiaBox, MILITIA_MENU_DRILL ); + } + + if ( gGameExternalOptions.fIndividualMilitia_ManageHealth ) + { + if ( CanCharacterDoctorMilitia( pSoldier ) ) + UnShadeStringInBox( ghMilitiaBox, MILITIA_MENU_DOCTOR ); + else + ShadeStringInBox( ghMilitiaBox, MILITIA_MENU_DOCTOR ); + } + } +} + +void CreateDestroyMouseRegionForMilitiaMenu( void ) +{ + static BOOLEAN fCreated = FALSE; + + UINT32 uiCounter = 0; + INT32 iCount = 0; + INT32 iFontHeight = 0; + INT32 iBoxXPosition = 0; + INT32 iBoxYPosition = 0; + SGPPoint pPosition; + INT32 iBoxWidth = 0; + SGPRect pDimensions; + SOLDIERTYPE *pSoldier = NULL; + + if ( gAssignMenuState == ASMENU_MILITIA && !fCreated ) + { + // grab height of font + iFontHeight = GetLineSpace( ghMilitiaBox ) + GetFontHeight( GetBoxFont( ghMilitiaBox ) ); + + // get x.y position of box + GetBoxPosition( ghMilitiaBox, &pPosition ); + + // grab box x and y position + iBoxXPosition = pPosition.iX; + iBoxYPosition = pPosition.iY; + + // get dimensions..mostly for width + GetBoxSize( ghMilitiaBox, &pDimensions ); + + SetBoxSecondaryShade( ghMilitiaBox, FONT_YELLOW ); + + // get width + iBoxWidth = pDimensions.iRight; + + SetCurrentBox( ghMilitiaBox ); + + pSoldier = GetSelectedAssignSoldier( FALSE ); + + // train assignment + MSYS_DefineRegion( &gMilitia[iCount], (INT16)( iBoxXPosition ), (INT16)( iBoxYPosition + GetTopMarginSize( ghAssignmentBox ) + (iFontHeight)* iCount ), (INT16)( iBoxXPosition + iBoxWidth ), (INT16)( iBoxYPosition + GetTopMarginSize( ghAssignmentBox ) + ( iFontHeight )* ( iCount + 1 ) ), MSYS_PRIORITY_HIGHEST - 4, + MSYS_NO_CURSOR, MilitiaMenuMvtCallback, MilitiaMenuBtnCallback ); + + MSYS_SetRegionUserData( &gMilitia[iCount], 0, iCount ); + MSYS_SetRegionUserData( &gMilitia[iCount], 1, MILITIA_MENU_TRAIN ); + ++iCount; + + if ( gGameExternalOptions.fIndividualMilitia ) + { + // drill assignment + MSYS_DefineRegion( &gMilitia[iCount], (INT16)( iBoxXPosition ), (INT16)( iBoxYPosition + GetTopMarginSize( ghAssignmentBox ) + (iFontHeight)* iCount ), (INT16)( iBoxXPosition + iBoxWidth ), (INT16)( iBoxYPosition + GetTopMarginSize( ghAssignmentBox ) + ( iFontHeight )* ( iCount + 1 ) ), MSYS_PRIORITY_HIGHEST - 4, + MSYS_NO_CURSOR, MilitiaMenuMvtCallback, MilitiaMenuBtnCallback ); + + MSYS_SetRegionUserData( &gMilitia[iCount], 0, iCount ); + MSYS_SetRegionUserData( &gMilitia[iCount], 1, MILITIA_MENU_DRILL ); + ++iCount; + + if ( gGameExternalOptions.fIndividualMilitia_ManageHealth ) + { + // doctor militia assignment + MSYS_DefineRegion( &gMilitia[iCount], (INT16)( iBoxXPosition ), (INT16)( iBoxYPosition + GetTopMarginSize( ghAssignmentBox ) + (iFontHeight)* iCount ), (INT16)( iBoxXPosition + iBoxWidth ), (INT16)( iBoxYPosition + GetTopMarginSize( ghAssignmentBox ) + ( iFontHeight )* ( iCount + 1 ) ), MSYS_PRIORITY_HIGHEST - 4, + MSYS_NO_CURSOR, MilitiaMenuMvtCallback, MilitiaMenuBtnCallback ); + + MSYS_SetRegionUserData( &gMilitia[iCount], 0, iCount ); + MSYS_SetRegionUserData( &gMilitia[iCount], 1, MILITIA_MENU_DOCTOR ); + ++iCount; + } + } + + // cancel + MSYS_DefineRegion( &gMilitia[iCount], (INT16)( iBoxXPosition ), (INT16)( iBoxYPosition + GetTopMarginSize( ghAssignmentBox ) + (iFontHeight)* iCount ), (INT16)( iBoxXPosition + iBoxWidth ), (INT16)( iBoxYPosition + GetTopMarginSize( ghAssignmentBox ) + ( iFontHeight )* ( iCount + 1 ) ), MSYS_PRIORITY_HIGHEST - 4, + MSYS_NO_CURSOR, MilitiaMenuMvtCallback, MilitiaMenuBtnCallback ); + + MSYS_SetRegionUserData( &gMilitia[iCount], 0, iCount ); + MSYS_SetRegionUserData( &gMilitia[iCount], 1, MILITIA_MENU_CANCEL ); + + PauseGame(); + + // unhighlight all strings in box + UnHighLightBox( ghMilitiaBox ); + + fCreated = TRUE; + } + else if ( ( gAssignMenuState != ASMENU_MILITIA || !fShowAssignmentMenu ) && fCreated ) + { + fCreated = FALSE; + + // remove these regions + for ( uiCounter = 0; uiCounter < GetNumberOfLinesOfTextInBox( ghMilitiaBox ); ++uiCounter ) + { + MSYS_RemoveRegion( &gMilitia[uiCounter] ); + } + + gAssignMenuState = ASMENU_NONE; + + SetRenderFlags( RENDER_FLAG_FULL ); + + HideBox( ghMilitiaBox ); + + fMapPanelDirty = TRUE; + + if ( fShowAssignmentMenu ) + { + // remove highlight on the parent menu + UnHighLightBox( ghAssignmentBox ); + } + } +} + +void MilitiaMenuBtnCallback( MOUSE_REGION * pRegion, INT32 iReason ) +{ + INT32 iValue = MSYS_GetRegionUserData( pRegion, 0 ); + + // ignore clicks on disabled lines + if ( GetBoxShadeFlag( ghMilitiaBox, iValue ) ) + return; + + // WHAT is being repaired is stored in the second user data argument + INT32 iWhat = MSYS_GetRegionUserData( pRegion, 1 ); + + SOLDIERTYPE* pSoldier = GetSelectedAssignSoldier( FALSE ); + + if ( pSoldier && pSoldier->bActive && ( iReason & MSYS_CALLBACK_REASON_LBUTTON_UP ) ) + { + switch ( iWhat ) + { + case MILITIA_MENU_TRAIN: + // Full test of Character and Sector to see if this training is possible at the moment. + if ( !BasicCanCharacterTrainMilitia( pSoldier ) ) + { + // No feedback. The menu options should be greyed out, anyway. + break; + } + + // Check for specific errors why this merc should not be able to train, + // and display a specific error message if one is encountered. + if ( !CanCharacterTrainMilitiaWithErrorReport( pSoldier ) ) + { + // Error found. Breaking. Note that the above function DOES display feedback if an error is + // encountered at all. + break; + } + + // PASSED ALL THE TESTS - ALLOW SOLDIER TO TRAIN MILITIA HERE + + pSoldier->bOldAssignment = pSoldier->bAssignment; + + if ( ( pSoldier->bAssignment != TRAIN_TOWN ) ) + { + SetTimeOfAssignmentChangeForMerc( pSoldier ); + } + + MakeSoldiersTacticalAnimationReflectAssignment( pSoldier ); + + // stop showing menu + fShowAssignmentMenu = FALSE; + giAssignHighLine = -1; + + // remove from squad + + if ( pSoldier->bOldAssignment == VEHICLE ) + { + TakeSoldierOutOfVehicle( pSoldier ); + } + + RemoveCharacterFromSquads( pSoldier ); + + ChangeSoldiersAssignment( pSoldier, TRAIN_TOWN ); + + // assign to a movement group + AssignMercToAMovementGroup( pSoldier ); + if ( SectorInfo[SECTOR( pSoldier->sSectorX, pSoldier->sSectorY )].fMilitiaTrainingPaid == FALSE ) + { + // show a message to confirm player wants to charge cost + HandleInterfaceMessageForCostOfTrainingMilitia( pSoldier ); + } + else + { + SetAssignmentForList( TRAIN_TOWN, 0 ); + } + gfRenderPBInterface = TRUE; + break; + + case MILITIA_MENU_DRILL: + if ( !CanCharacterDrillMilitia( pSoldier, TRUE ) ) + { + break; + } + + pSoldier->bOldAssignment = pSoldier->bAssignment; + + if ( pSoldier->bAssignment != DRILL_MILITIA ) + { + SetTimeOfAssignmentChangeForMerc( pSoldier ); + } + + if ( pSoldier->bOldAssignment == VEHICLE ) + { + TakeSoldierOutOfVehicle( pSoldier ); + } + + ChangeSoldiersAssignment( pSoldier, DRILL_MILITIA ); + + // set assignment for group + SetAssignmentForList( (INT8)DRILL_MILITIA, 0 ); + fShowAssignmentMenu = FALSE; + + break; + + case MILITIA_MENU_DOCTOR: + pSoldier->bOldAssignment = pSoldier->bAssignment; + + if ( pSoldier->bAssignment != DOCTOR_MILITIA ) + { + SetTimeOfAssignmentChangeForMerc( pSoldier ); + } + + if ( pSoldier->bOldAssignment == VEHICLE ) + { + TakeSoldierOutOfVehicle( pSoldier ); + } + + ChangeSoldiersAssignment( pSoldier, DOCTOR_MILITIA ); + + // set assignment for group + SetAssignmentForList( (INT8)DOCTOR_MILITIA, 0 ); + fShowAssignmentMenu = FALSE; + break; + + case MILITIA_MENU_CANCEL: + default: + // CANCEL + gAssignMenuState = ASMENU_NONE; + break; + } + + // update mapscreen + fCharacterInfoPanelDirty = TRUE; + fTeamPanelDirty = TRUE; + fMapScreenBottomDirty = TRUE; + + giAssignHighLine = -1; + } +} + +void MilitiaMenuMvtCallback( MOUSE_REGION * pRegion, INT32 iReason ) +{ + // mvt callback handler for assignment region + //INT32 iValue = MSYS_GetRegionUserData( pRegion, 1 ); + + if ( iReason & MSYS_CALLBACK_REASON_GAIN_MOUSE ) + { + /*if ( iValue < MILITIA_MENU_CANCEL ) + { + if ( GetBoxShadeFlag( ghMilitiaBox, iValue ) == FALSE ) + { + // highlight choice + HighLightBoxLine( ghMilitiaBox, iValue ); + } + } + else + { + // highlight cancel line + HighLightBoxLine( ghMilitiaBox, GetNumberOfLinesOfTextInBox( ghMilitiaBox ) - 1 ); + }*/ + + // mvt callback handler for assignment region + INT32 iValue = MSYS_GetRegionUserData( pRegion, 0 ); + + if ( GetBoxShadeFlag( ghMilitiaBox, iValue ) == FALSE ) + { + // highlight choice + HighLightBoxLine( ghMilitiaBox, iValue ); + } + } + else if ( iReason & MSYS_CALLBACK_REASON_LOST_MOUSE ) + { + // unhighlight all strings in box + UnHighLightBox( ghMilitiaBox ); + } +} diff --git a/Strategic/Assignments.h b/Strategic/Assignments.h index 337e5f52..d7e22d02 100644 --- a/Strategic/Assignments.h +++ b/Strategic/Assignments.h @@ -94,6 +94,8 @@ enum TRAIN_WORKERS, CONCEALED, // Flugente: spy hides among the population GATHERINTEL, // gathers information while disguised in enemy territory + DOCTOR_MILITIA, // heal militia + DRILL_MILITIA, // train existing militia (does not create new ones) NUM_ASSIGNMENTS, }; @@ -172,6 +174,9 @@ typedef struct TOWN_TRAINER_TYPE // can this character be assigned as a doctor? BOOLEAN CanCharacterDoctor( SOLDIERTYPE *pCharacter ); +// can this character doctor militia (assignmentwise)? +BOOLEAN CanCharacterDoctorMilitia( SOLDIERTYPE *pSoldier ); + // can this character diagnose diseases? BOOLEAN CanCharacterDiagnoseDisease( SOLDIERTYPE *pSoldier ); @@ -189,6 +194,8 @@ BOOLEAN CanCharacterRepair( SOLDIERTYPE *pCharacter ); BOOLEAN CanCharacterPatient( SOLDIERTYPE *pCharacter ); // can character train militia? +BOOLEAN CanCharacterMilitiaAssignment( SOLDIERTYPE *pSoldier ); +BOOLEAN CanCharacterDrillMilitia( SOLDIERTYPE *pSoldier, BOOLEAN aErrorReport = FALSE ); BOOLEAN CanCharacterTrainMilitia( SOLDIERTYPE *pCharacter ); BOOLEAN CanCharacterTrainMobileMilitia( SOLDIERTYPE *pSoldier ); @@ -319,6 +326,7 @@ extern INT32 ghTrainingBox; extern INT32 ghMoveItemBox; extern INT32 ghDiseaseBox; extern INT32 ghSpyBox; +extern INT32 ghMilitiaBox; extern INT32 ghAttributeBox; extern INT32 ghRemoveMercAssignBox; extern INT32 ghContractBox; @@ -361,6 +369,7 @@ enum ASMENU_TRAIN, ASMENU_SQUAD, ASMENU_SNITCH, + ASMENU_MILITIA, }; extern int gAssignMenuState; @@ -419,6 +428,11 @@ void CreateDestroyMouseRegionForSpyMenu( void ); void SpyMenuMvtCallback( MOUSE_REGION * pRegion, INT32 iReason ); void SpyMenuBtnCallback( MOUSE_REGION * pRegion, INT32 iReason ); +// Flugente: militia menu +void CreateDestroyMouseRegionForMilitiaMenu( void ); +void MilitiaMenuMvtCallback( MOUSE_REGION * pRegion, INT32 iReason ); +void MilitiaMenuBtnCallback( MOUSE_REGION * pRegion, INT32 iReason ); + // HEADROCK HAM 3.6: Facility Menu void CreateDestroyMouseRegionForFacilityMenu( void ); void FacilityMenuMvtCallback(MOUSE_REGION * pRegion, INT32 iReason ); diff --git a/Strategic/Map Screen Interface.cpp b/Strategic/Map Screen Interface.cpp index 2b63bdf4..6096c448 100644 --- a/Strategic/Map Screen Interface.cpp +++ b/Strategic/Map Screen Interface.cpp @@ -2329,6 +2329,15 @@ void UpdateMapScreenAssignmentPositions( void ) SetBoxPosition( ghFacilityBox, pPoint ); } break; + + case ASMENU_MILITIA: + { + GetBoxPosition( ghMilitiaBox, &pPoint ); + pPoint.iY = giBoxY + ( GetFontHeight( MAP_SCREEN_FONT ) + 2 ) * ASSIGN_MENU_MILITIA; + + SetBoxPosition( ghMilitiaBox, pPoint ); + } + break; } if( fShowAttributeMenu ) diff --git a/Strategic/Map Screen Interface.h b/Strategic/Map Screen Interface.h index 4b002c68..8d9fba53 100644 --- a/Strategic/Map Screen Interface.h +++ b/Strategic/Map Screen Interface.h @@ -129,6 +129,7 @@ enum { ASSIGN_MENU_RADIO_SCAN, // added by Flugente ASSIGN_MENU_SNITCH, ASSIGN_MENU_TRAIN, + ASSIGN_MENU_MILITIA, // added by Flugente: all things militia ASSIGN_MENU_MOVE_ITEMS, // added by Flugente ASSIGN_MENU_FORTIFY, // added by Flugente ASSIGN_MENU_SPY, // added by Flugente @@ -176,7 +177,6 @@ enum { // training assignment menu defines enum { TRAIN_MENU_SELF, - TRAIN_MENU_TOWN, TRAIN_MENU_MOBILE, TRAIN_MENU_WORKERS, TRAIN_MENU_TEAMMATES, diff --git a/Strategic/MilitiaIndividual.cpp b/Strategic/MilitiaIndividual.cpp index 6ebbc98f..59783ede 100644 --- a/Strategic/MilitiaIndividual.cpp +++ b/Strategic/MilitiaIndividual.cpp @@ -73,8 +73,21 @@ MILITIA::Load( HWFILE hwFile ) numBytesRead = ReadFieldByField( hwFile, &healthratio, sizeof(healthratio), sizeof(FLOAT), numBytesRead ); numBytesRead = ReadFieldByField( hwFile, &kills, sizeof(kills), sizeof(UINT16), numBytesRead); numBytesRead = ReadFieldByField( hwFile, &assists, sizeof(assists), sizeof(UINT16), numBytesRead ); - numBytesRead = ReadFieldByField( hwFile, &promotionpoints, sizeof(promotionpoints), sizeof(UINT16), numBytesRead ); - numBytesRead = ReadFieldByField( hwFile, &filler1, sizeof(filler1), sizeof(UINT16), numBytesRead ); + + // promotionpoints has been changed from UINT16 to FLOAT, so we need changes here + if ( guiCurrentSaveGameVersion >= INDIVIDUAL_MILITIA_EXP_FLOAT ) + { + numBytesRead = ReadFieldByField( hwFile, &promotionpoints, sizeof( promotionpoints ), sizeof( FLOAT ), numBytesRead ); + } + else + { + UINT16 tmp; + numBytesRead = ReadFieldByField( hwFile, &tmp, sizeof( tmp ), sizeof( UINT16 ), numBytesRead ); + + promotionpoints = tmp; + + numBytesRead = ReadFieldByField( hwFile, &tmp, sizeof( tmp ), sizeof( UINT16 ), numBytesRead ); + } if ( numBytesRead != SIZEOF_MILITIA_POD ) return(FALSE); @@ -272,8 +285,8 @@ SOLDIERTYPE* GetUsedSoldierToIndividualMilitia( UINT32 aMilitiaId ) return NULL; } -// update the health values of all militia in tactical -void UpdateAllMilitiaHealthInTactical() +// apply tactical life ratio to militia health ratio +void ApplyTacticalLifeRatioToMilitia() { if ( !gGameExternalOptions.fIndividualMilitia ) return; @@ -299,52 +312,95 @@ void UpdateAllMilitiaHealthInTactical() } } -void HandleHourlyMilitiaHealing( ) +void ApplyMilitiaHealthRatioToTactical() { if ( !gGameExternalOptions.fIndividualMilitia || !gGameExternalOptions.fIndividualMilitia_ManageHealth ) return; - INT32 cnt = gTacticalStatus.Team[MILITIA_TEAM].bFirstID; + SOLDIERTYPE* pSoldier; + UINT32 cnt = gTacticalStatus.Team[MILITIA_TEAM].bFirstID; INT32 lastid = gTacticalStatus.Team[MILITIA_TEAM].bLastID; - SOLDIERTYPE* pSoldier = NULL; - + for ( pSoldier = MercPtrs[cnt]; cnt < lastid; ++cnt, ++pSoldier ) + { + MILITIA militia; + if ( pSoldier && pSoldier->bActive && pSoldier->stats.bLifeMax && GetMilitia( pSoldier->usIndividualMilitiaID, &militia ) ) + { + INT8 oldlife = pSoldier->stats.bLife; + + FLOAT currenthealthratio = 100.0f * oldlife / pSoldier->stats.bLifeMax; + + militia.healthratio = max( militia.healthratio, currenthealthratio ); + + pSoldier->stats.bLife = min( pSoldier->stats.bLifeMax, ( militia.healthratio / 100.0f ) * pSoldier->stats.bLifeMax ); + + // healing done will be displayed the next time the player sees this soldier + pSoldier->flags.fDisplayDamage = TRUE; + pSoldier->sDamage -= pSoldier->stats.bLife - oldlife; + + // while we're here, update kills and assists too + militia.AddKills( pSoldier->ubMilitiaKills, pSoldier->ubMilitiaAssists ); + + pSoldier->ubMilitiaKills = 0; + pSoldier->ubMilitiaAssists = 0; + + UpdateMilitia( militia ); + } + } +} + +void HandleHourlyMilitiaHealing( ) +{ + if ( !gGameExternalOptions.fIndividualMilitia || !gGameExternalOptions.fIndividualMilitia_ManageHealth ) + return; + std::vector::iterator itend = gIndividualMilitiaVector.end( ); for ( std::vector::iterator it = gIndividualMilitiaVector.begin( ); it != itend; ++it ) { if ( !((*it).flagmask & MILITIAFLAG_DEAD) ) { (*it).healthratio = min( 100.0f, (*it).healthratio + gGameExternalOptions.dIndividualMilitiaHourlyHealthPercentageGain ); - - // if this guy is in the currently loaded sector, heal the soldier instead (and update health ratio while you're there) - if ( !gbWorldSectorZ && (*it).sector == SECTOR( gWorldSectorX, gWorldSectorY ) ) - { - for ( pSoldier = MercPtrs[cnt]; cnt < lastid; ++cnt, ++pSoldier ) - { - if ( pSoldier && pSoldier->bActive && (*it).id == pSoldier->usIndividualMilitiaID && - gWorldSectorX == pSoldier->sSectorX && gWorldSectorY == pSoldier->sSectorY && !pSoldier->bSectorZ && - pSoldier->stats.bLifeMax > 0 ) - { - INT8 oldlife = pSoldier->stats.bLife; - - FLOAT currenthealthratio = 100.0f * oldlife / pSoldier->stats.bLifeMax; - - currenthealthratio = min( 100.0f, currenthealthratio + gGameExternalOptions.dIndividualMilitiaHourlyHealthPercentageGain ); - - pSoldier->stats.bLife = min( pSoldier->stats.bLifeMax, (currenthealthratio / 100.0f) * pSoldier->stats.bLifeMax ); - - // healing done will be displayed the next time the player sees this soldier - pSoldier->flags.fDisplayDamage = TRUE; - pSoldier->sDamage -= pSoldier->stats.bLife - oldlife; - - // update new health ratio - (*it).healthratio = currenthealthratio; - - break; - } - } - } } } + + ApplyMilitiaHealthRatioToTactical(); +} + +UINT32 MilitiaIndividual_Heal( UINT32 points, UINT8 aSector ) +{ + if ( !gGameExternalOptions.fIndividualMilitia || !gGameExternalOptions.fIndividualMilitia_ManageHealth ) + return 0; + + FLOAT totalhealthmissing = 0.0f; + + std::vector::iterator itend = gIndividualMilitiaVector.end(); + for ( std::vector::iterator it = gIndividualMilitiaVector.begin(); it != itend; ++it ) + { + if ( !( ( *it ).flagmask & (MILITIAFLAG_DEAD | MILITIAFLAG_FIRED ) ) && (*it).sector == aSector && ( *it ).healthratio < 100.0f ) + { + totalhealthmissing += ( 100.0f - ( *it ).healthratio ); + } + } + + if ( totalhealthmissing <= 0.0f ) + return 0; + + FLOAT pointstouse = min( (FLOAT)points, totalhealthmissing ); + + for ( std::vector::iterator it = gIndividualMilitiaVector.begin(); it != itend; ++it ) + { + if ( !( ( *it ).flagmask & ( MILITIAFLAG_DEAD | MILITIAFLAG_FIRED ) ) && ( *it ).sector == aSector && ( *it ).healthratio < 100.0f ) + { + ( *it ).healthratio += ( 100.0f - ( *it ).healthratio ) * pointstouse / totalhealthmissing; + } + } + + // update militia in current sector + if ( !gbWorldSectorZ && SECTOR( gWorldSectorX, gWorldSectorY ) == aSector ) + { + ApplyMilitiaHealthRatioToTactical(); + } + + return (UINT32)pointstouse; } UINT32 CreateRandomIndividualMilitia( UINT8 aMilitiaRank, UINT8 aOrigin, UINT8 aSector ) @@ -490,7 +546,7 @@ UINT32 CreateNewIndividualMilitia( UINT8 aMilitiaRank, UINT8 aOrigin, UINT8 aSec newmilitia.kills = 0; newmilitia.assists = 0; - newmilitia.promotionpoints = 0; + newmilitia.promotionpoints = 0.0f; // promotion points are based on kills and assists. For proper accounting, award points for current rank newmilitia.AddKills( 0, 0 ); @@ -509,7 +565,7 @@ UINT32 CreateNewIndividualMilitia( UINT8 aMilitiaRank, UINT8 aOrigin, UINT8 aSec // search for a individual militia that is alive and not currently in use in this sector, and return its id // if none is found, create new and return that one -UINT32 GetIdOfUnusedindividualMilitia( UINT8 aSoldierClass, UINT8 aSector ) +UINT32 GetIdOfUnusedIndividualMilitia( UINT8 aSoldierClass, UINT8 aSector ) { if ( !gGameExternalOptions.fIndividualMilitia ) return 0; @@ -557,6 +613,123 @@ UINT32 GetIdOfUnusedindividualMilitia( UINT8 aSoldierClass, UINT8 aSector ) return CreateNewIndividualMilitia( militialevel, MO_ARULCO, aSector ); } +BOOLEAN GetIdOfIndividualMilitiaWithClassSector( UINT8 aSoldierClass, UINT8 aSector, UINT32& arId ) +{ + arId = 0; + + if ( !gGameExternalOptions.fIndividualMilitia ) + return FALSE; + + UINT8 militialevel = SoldierClassToMilitiaRank( aSoldierClass ); + + std::vector::iterator itend = gIndividualMilitiaVector.end(); + for ( std::vector::iterator it = gIndividualMilitiaVector.begin(); it != itend; ++it ) + { + if ( !( ( *it ).flagmask & ( MILITIAFLAG_DEAD | MILITIAFLAG_FIRED ) ) && ( *it ).sector == aSector && ( *it ).militiarank == militialevel ) + { + arId = ( *it ).id; + + return TRUE; + } + } + + return FALSE; +} + +extern void ResetMilitia(); + +FLOAT PromoteIndividualMilitiaInSector( UINT8 aSector, FLOAT aPointsToAdd ) +{ + FLOAT pointsused = 0.0f; + + if ( !gGameExternalOptions.fIndividualMilitia ) + return pointsused; + + std::vector::iterator itend = gIndividualMilitiaVector.end(); + for ( std::vector::iterator it = gIndividualMilitiaVector.begin(); it != itend; ++it ) + { + if ( !( ( *it ).flagmask & ( MILITIAFLAG_DEAD | MILITIAFLAG_FIRED ) ) && ( *it ).sector == aSector && ( *it ).militiarank == GREEN_MILITIA ) + { + MILITIA militia = ( *it ); + + FLOAT pointstoadd = min( aPointsToAdd - pointsused, max( 0, gGameExternalOptions.usIndividualMilitia_PromotionPoints_To_Regular - militia.promotionpoints ) ); + + pointsused += pointstoadd; + militia.promotionpoints += pointstoadd; + + PossiblyPromoteIndividualMilitia( militia ); + + if ( militia.militiarank == REGULAR_MILITIA ) + StrategicPromoteMilitiaInSector( SECTORX( aSector ), SECTORY( aSector ), GREEN_MILITIA, 1 ); + else if ( militia.militiarank == ELITE_MILITIA ) + { + StrategicPromoteMilitiaInSector( SECTORX( aSector ), SECTORY( aSector ), GREEN_MILITIA, 1 ); + StrategicPromoteMilitiaInSector( SECTORX( aSector ), SECTORY( aSector ), REGULAR_MILITIA, 1 ); + } + + UpdateMilitia( militia ); + } + + if ( pointsused >= aPointsToAdd ) + break; + } + + if ( gGameExternalOptions.gfTrainVeteranMilitia ) + { + std::vector::iterator itend = gIndividualMilitiaVector.end(); + for ( std::vector::iterator it = gIndividualMilitiaVector.begin(); it != itend; ++it ) + { + if ( !( ( *it ).flagmask & ( MILITIAFLAG_DEAD | MILITIAFLAG_FIRED ) ) && ( *it ).sector == aSector && ( *it ).militiarank == REGULAR_MILITIA ) + { + MILITIA militia = ( *it ); + + FLOAT pointstoadd = min( aPointsToAdd - pointsused, max( 0, gGameExternalOptions.usIndividualMilitia_PromotionPoints_To_Regular + gGameExternalOptions.usIndividualMilitia_PromotionPoints_To_Elite - militia.promotionpoints ) ); + + pointsused += pointstoadd; + militia.promotionpoints += pointstoadd; + + PossiblyPromoteIndividualMilitia( militia ); + + if ( militia.militiarank == ELITE_MILITIA ) + StrategicPromoteMilitiaInSector( SECTORX( aSector ), SECTORY( aSector ), REGULAR_MILITIA, 1 ); + + UpdateMilitia( militia ); + } + + if ( pointsused >= aPointsToAdd ) + break; + } + } + + // do possible update in tactical + if ( !gbWorldSectorZ && SECTORX( aSector ) == gWorldSectorX && SECTORY( aSector ) == gWorldSectorY ) + { + BOOLEAN changesnecessary = FALSE; + + SOLDIERTYPE* pSoldier = NULL; + int cnt = gTacticalStatus.Team[MILITIA_TEAM].bFirstID; + for ( pSoldier = MercPtrs[cnt]; cnt <= gTacticalStatus.Team[MILITIA_TEAM].bLastID; ++cnt, ++pSoldier ) + { + MILITIA militia; + + if ( pSoldier && GetMilitia( pSoldier->usIndividualMilitiaID, &militia ) ) + { + if ( SoldierClassToMilitiaRank( pSoldier->ubSoldierClass ) < militia.militiarank ) + { + pSoldier->ubSoldierClass = MilitiaRankToSoldierClass( militia.militiarank ); + + changesnecessary = TRUE; + } + } + } + + if ( changesnecessary ) + ResetMilitia(); + } + + return pointsused; +} + // handle possible militia promotion and individual militia update void HandlePossibleMilitiaPromotion( SOLDIERTYPE* pSoldier, BOOLEAN aAutoResolve ) { @@ -775,6 +948,60 @@ void PromoteIndividualMilitia( UINT8 aSector, UINT8 aSoldierClass ) ScreenMsg( FONT_MCOLOR_RED, MSG_INTERFACE, L"Possible error: Not enough individual militia found in PromoteIndividualMilitia" ); } +void PossiblyPromoteIndividualMilitia( MILITIA& aMilitia ) +{ + if ( !( aMilitia.flagmask & ( MILITIAFLAG_DEAD | MILITIAFLAG_FIRED ) ) ) + { + // Flugente: check whether we have the resources to promote militia + BOOLEAN fCanPromoteToRegular = TRUE; + BOOLEAN fCanPromoteToElite = TRUE; + if ( gGameExternalOptions.fMilitiaResources && !gGameExternalOptions.fMilitiaUseSectorInventory ) + { + FLOAT val_gun, val_armour, val_misc; + GetResources( val_gun, val_armour, val_misc ); + + // regular militia require an additional gun and armour + if ( val_gun <= 1.0f || val_armour <= 1.0f ) + { + fCanPromoteToRegular = FALSE; + fCanPromoteToElite = FALSE; + } + // elite also require misc resources + else if ( val_misc <= 1.0f ) + { + fCanPromoteToElite = FALSE; + } + } + + // if we have enough points, promote + if ( aMilitia.militiarank == GREEN_MILITIA ) + { + if ( aMilitia.promotionpoints >= gGameExternalOptions.usIndividualMilitia_PromotionPoints_To_Regular ) + { + if ( fCanPromoteToRegular ) + { + aMilitia.militiarank = REGULAR_MILITIA; + + AddResources( -1, -1, 0 ); + } + } + } + + if ( aMilitia.militiarank == REGULAR_MILITIA ) + { + if ( aMilitia.promotionpoints >= gGameExternalOptions.usIndividualMilitia_PromotionPoints_To_Regular + gGameExternalOptions.usIndividualMilitia_PromotionPoints_To_Elite ) + { + if ( fCanPromoteToElite ) + { + aMilitia.militiarank = ELITE_MILITIA; + + AddResources( -1, -1, -1 ); + } + } + } + } +} + // return the sum of daily wages, and the number of individual militia per class UINT32 GetDailyUpkeep_IndividualMilitia( UINT32& arNumGreen, UINT32& arNumRegular, UINT32& arNumElite ) { diff --git a/Strategic/MilitiaIndividual.h b/Strategic/MilitiaIndividual.h index ad1ea375..68c789c7 100644 --- a/Strategic/MilitiaIndividual.h +++ b/Strategic/MilitiaIndividual.h @@ -123,9 +123,7 @@ public: // we don't store the experience level, we store the amount of points in regard to promotion. // While this is made up of kills and assists, we need this, as we have to account for militia initially starting at regular level - UINT16 promotionpoints; - - UINT16 filler1; // necessary for padding - fill up so that SIZEOF_MILITIA_POD is doubly even + FLOAT promotionpoints; char endOfPOD; // marker for end of POD (plain old data) @@ -154,16 +152,24 @@ void UpdateMilitia( MILITIA aMilitia ); SOLDIERTYPE* GetUsedSoldierToIndividualMilitia( UINT32 aMilitiaId ); -// update the health values of all militia in tactical -void UpdateAllMilitiaHealthInTactical(); +// apply tactical life ratio to militia health ratio +void ApplyTacticalLifeRatioToMilitia(); + +// apply health ratios to militia in tactical +void ApplyMilitiaHealthRatioToTactical(); void HandleHourlyMilitiaHealing( ); +UINT32 MilitiaIndividual_Heal(UINT32 points, UINT8 aSector ); UINT32 CreateRandomIndividualMilitia( UINT8 aMilitiaRank, UINT8 aOrigin, UINT8 aSector ); UINT32 CreateNewIndividualMilitia( UINT8 aMilitiaRank, UINT8 aOrigin, UINT8 aSector ); -UINT32 GetIdOfUnusedindividualMilitia( UINT8 aSoldierClass, UINT8 aSector ); +UINT32 GetIdOfUnusedIndividualMilitia( UINT8 aSoldierClass, UINT8 aSector ); + +BOOLEAN GetIdOfIndividualMilitiaWithClassSector( UINT8 aSoldierClass, UINT8 aSector, UINT32& arId ); + +FLOAT PromoteIndividualMilitiaInSector( UINT8 aSector, FLOAT aPointsToAdd ); // handle possible militia promotion and individual militia update void HandlePossibleMilitiaPromotion( SOLDIERTYPE* pSoldier, BOOLEAN aAutoResolve ); @@ -175,6 +181,8 @@ void DisbandIndividualMilitia( UINT8 aSector, UINT8 usGreens, UINT8 usRegulars, void PromoteIndividualMilitia( UINT8 aSector, UINT8 aSoldierClass ); +void PossiblyPromoteIndividualMilitia( MILITIA& aMilitia ); + // return the sum of daily wages, and the number of individual militia per class UINT32 GetDailyUpkeep_IndividualMilitia( UINT32& arNumGreen, UINT32& arNumRegular, UINT32& arNumElite ); diff --git a/Strategic/MilitiaSquads.cpp b/Strategic/MilitiaSquads.cpp index 9cddc7dc..2f020ff3 100644 --- a/Strategic/MilitiaSquads.cpp +++ b/Strategic/MilitiaSquads.cpp @@ -641,7 +641,7 @@ void MoveMilitiaSquad(INT16 sMapX, INT16 sMapY, INT16 sTMapX, INT16 sTMapY, BOOL MoveMilitiaEquipment(sMapX, sMapY, sTMapX, sTMapY, elites, regulars, greens); // Flugente: update individual militia data - UpdateAllMilitiaHealthInTactical( ); + ApplyTacticalLifeRatioToMilitia( ); // Flugente: disease PopulationMove( sMapX, sMapY, sTMapX, sTMapY, elites + regulars + greens ); @@ -686,7 +686,7 @@ void MoveMilitiaSquad(INT16 sMapX, INT16 sMapY, INT16 sTMapX, INT16 sTMapY, BOOL MoveMilitiaEquipment(sMapX, sMapY, sTMapX, sTMapY, elites, regulars, greens); // Flugente: update individual militia data - UpdateAllMilitiaHealthInTactical( ); + ApplyTacticalLifeRatioToMilitia( ); // Flugente: disease PopulationMove( sMapX, sMapY, sTMapX, sTMapY, elites + regulars + greens ); @@ -779,7 +779,7 @@ void MoveMilitiaSquad(INT16 sMapX, INT16 sMapY, INT16 sTMapX, INT16 sTMapY, BOOL MoveMilitiaEquipment(sMapX, sMapY, sTMapX, sTMapY, elites, regulars, greens); // Flugente: update individual militia data - UpdateAllMilitiaHealthInTactical( ); + ApplyTacticalLifeRatioToMilitia( ); // Flugente: disease PopulationMove( sMapX, sMapY, sTMapX, sTMapY, elites + regulars + greens ); @@ -809,7 +809,7 @@ void MoveMilitiaSquad(INT16 sMapX, INT16 sMapY, INT16 sTMapX, INT16 sTMapY, BOOL MoveMilitiaEquipment(sMapX, sMapY, sTMapX, sTMapY, pSectorInfo->ubNumberOfCivsAtLevel[ ELITE_MILITIA ], pSectorInfo->ubNumberOfCivsAtLevel[ REGULAR_MILITIA ], pSectorInfo->ubNumberOfCivsAtLevel[ GREEN_MILITIA ]); // Flugente: update individual militia data - UpdateAllMilitiaHealthInTactical( ); + ApplyTacticalLifeRatioToMilitia( ); UINT8 greens = pSectorInfo->ubNumberOfCivsAtLevel[GREEN_MILITIA]; UINT8 regulars = pSectorInfo->ubNumberOfCivsAtLevel[REGULAR_MILITIA]; diff --git a/Strategic/Strategic Movement.cpp b/Strategic/Strategic Movement.cpp index 2b0b52a7..9dc63c26 100644 --- a/Strategic/Strategic Movement.cpp +++ b/Strategic/Strategic Movement.cpp @@ -2306,7 +2306,7 @@ void GroupArrivedAtSector( UINT8 ubGroupID, BOOLEAN fCheckForBattle, BOOLEAN fNe TeamDropAll( MILITIA_TEAM ); // Flugente: update individual militia data - UpdateAllMilitiaHealthInTactical( ); + ApplyTacticalLifeRatioToMilitia( ); // we now force a resetting of militia - they will be removed and recreated // as the group's coordinates have alreay 'moved' to the next sector, the group militia will now be gone diff --git a/Tactical/Campaign.cpp b/Tactical/Campaign.cpp index 8d6619ae..c5ffc22c 100644 --- a/Tactical/Campaign.cpp +++ b/Tactical/Campaign.cpp @@ -715,10 +715,10 @@ void ChangeStat( MERCPROFILESTRUCT *pProfile, SOLDIERTYPE *pSoldier, UINT8 ubSta //Madd: option to make mercs quiet during training / doctoring / repairing if ( ((pSoldier->bAssignment == TRAIN_BY_OTHER || pSoldier->bAssignment == TRAIN_TEAMMATE || pSoldier->bAssignment == TRAIN_SELF || pSoldier->bAssignment == FACILITY_STAFF || pSoldier->bAssignment == TRAIN_TOWN || pSoldier->bAssignment == TRAIN_MOBILE - || pSoldier->bAssignment == TRAIN_WORKERS ) + || pSoldier->bAssignment == TRAIN_WORKERS || pSoldier->bAssignment == DRILL_MILITIA ) && !gGameSettings.fOptions[TOPTION_QUIET_TRAINING]) || (IS_REPAIR(pSoldier->bAssignment) && !gGameSettings.fOptions[TOPTION_QUIET_REPAIRING]) || - (IS_DOCTOR(pSoldier->bAssignment) && !gGameSettings.fOptions[TOPTION_QUIET_DOCTORING])) + ((IS_DOCTOR(pSoldier->bAssignment) || pSoldier->bAssignment == DOCTOR_MILITIA ) && !gGameSettings.fOptions[TOPTION_QUIET_DOCTORING])) TacticalCharacterDialogue( pSoldier, QUOTE_EXPERIENCE_GAIN ); } diff --git a/Tactical/Faces.cpp b/Tactical/Faces.cpp index 74262386..a1637fab 100644 --- a/Tactical/Faces.cpp +++ b/Tactical/Faces.cpp @@ -2277,15 +2277,26 @@ void HandleRenderFaceAdjustments( FACETYPE *pFace, BOOLEAN fDisplayBuffer, BOOLE switch( pSoldier->bAssignment ) { CASE_DOCTOR: + case DOCTOR_MILITIA: sIconIndex_Assignment = 1; fDoIcon_Assignment = TRUE; sPtsAvailable = CalculateHealingPointsForDoctor( MercPtrs[ pFace->ubSoldierID ], &usMaximumPts, FALSE ); - fShowNumber = TRUE; - fShowMaximum = TRUE; - // divide both amounts by 10 to make the displayed numbers a little more user-palatable (smaller) - sPtsAvailable = ( sPtsAvailable + 5 ) / 10; - usMaximumPts = ( usMaximumPts + 5 ) / 10; + fShowCustomText = TRUE; + + if ( pSoldier->bAssignment == DOCTOR_MILITIA ) + { + // show percentage that we can heal + swprintf( sString, L"%3.1f/%3.1f", (FLOAT)( sPtsAvailable * gGameExternalOptions.dIndividualMilitiaDoctorHealModifier ), (FLOAT)( usMaximumPts * gGameExternalOptions.dIndividualMilitiaDoctorHealModifier ) ); + } + else + { + // shos HP we can heal + swprintf( sString, L"%3.1f/%3.1f", (FLOAT)( sPtsAvailable ) / 100.0f, (FLOAT)( usMaximumPts ) / 100.0f ); + } + + usTextWidth = StringPixLength( sString, FONT10ARIAL ); + break; CASE_PATIENT: @@ -2305,6 +2316,7 @@ void HandleRenderFaceAdjustments( FACETYPE *pFace, BOOLEAN fDisplayBuffer, BOOLE case TRAIN_TEAMMATE: case TRAIN_BY_OTHER: case TRAIN_WORKERS: + case DRILL_MILITIA: sIconIndex_Assignment = 3; fDoIcon_Assignment = TRUE; fShowNumber = TRUE; @@ -2320,6 +2332,7 @@ void HandleRenderFaceAdjustments( FACETYPE *pFace, BOOLEAN fDisplayBuffer, BOOLE break; case( TRAIN_TOWN ): case( TRAIN_MOBILE ): + case DRILL_MILITIA: sPtsAvailable = GetTownTrainPtsForCharacter( MercPtrs[ pFace->ubSoldierID ], &usMaximumPts ); // divide both amounts by 10 to make the displayed numbers a little more user-palatable (smaller) sPtsAvailable = ( sPtsAvailable + 5 ) / 10; diff --git a/Tactical/Soldier Add.cpp b/Tactical/Soldier Add.cpp index 146fb41b..b2301057 100644 --- a/Tactical/Soldier Add.cpp +++ b/Tactical/Soldier Add.cpp @@ -1731,7 +1731,7 @@ void AddSoldierToSectorGridNo( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT8 ubDir { InternalSoldierInSectorSleep( pSoldier, pSoldier->sInsertionGridNo, FALSE ); } - else if ( IS_DOCTOR(pSoldier->bAssignment) ) + else if ( IS_DOCTOR(pSoldier->bAssignment) || pSoldier->bAssignment == DOCTOR_MILITIA ) { SoldierInSectorDoctor( pSoldier, pSoldier->sInsertionGridNo ); } diff --git a/Tactical/Soldier Create.cpp b/Tactical/Soldier Create.cpp index d98e752b..17c44af7 100644 --- a/Tactical/Soldier Create.cpp +++ b/Tactical/Soldier Create.cpp @@ -635,7 +635,7 @@ SOLDIERTYPE* TacticalCreateSoldier( SOLDIERCREATE_STRUCT *pCreateStruct, UINT8 * // do not do so during loading of a savegame if ( tbTeam == MILITIA_TEAM && !pCreateStruct->fUseExistingSoldier ) { - Soldier.usIndividualMilitiaID = GetIdOfUnusedindividualMilitia( pCreateStruct->ubSoldierClass, SECTOR( pCreateStruct->sSectorX, pCreateStruct->sSectorY ) ); + Soldier.usIndividualMilitiaID = GetIdOfUnusedIndividualMilitia( pCreateStruct->ubSoldierClass, SECTOR( pCreateStruct->sSectorX, pCreateStruct->sSectorY ) ); } // OK, CHECK IF WE HAVE A VALID PROFILE ID! diff --git a/Utils/Text.h b/Utils/Text.h index 0f990a5f..97be4804 100644 --- a/Utils/Text.h +++ b/Utils/Text.h @@ -3066,6 +3066,8 @@ extern STR16 szIntelText[]; extern STR16 szChatTextSpy[]; extern STR16 szChatTextEnemy[]; +extern STR16 szMilitiaText[]; + #define TACTICAL_INVENTORY_DIALOG_NUM 16 #define TACTICAL_COVER_DIALOG_NUM 16 diff --git a/Utils/_ChineseText.cpp b/Utils/_ChineseText.cpp index 1de499cc..1fcad2ed 100644 --- a/Utils/_ChineseText.cpp +++ b/Utils/_ChineseText.cpp @@ -2470,6 +2470,8 @@ STR16 pAssignmentStrings[] = L"培训工人",//L"Train W.", L"Hide", // TODO.Translate L"GetIntel", + L"DoctorM.", + L"DMilitia", }; @@ -2575,6 +2577,8 @@ STR16 pPersonnelAssignmentStrings[] = L"培训工人",//L"Train workers", L"Hide while disguised", // TODO.Translate L"Get intel while disguised", + L"Doctor wounded militia", + L"Drill existing militia", }; @@ -2639,6 +2643,8 @@ STR16 pLongAssignmentStrings[] = L"培训工人",//L"Train workers", L"Hide while disguised", // TODO.Translate L"Get intel while disguised", + L"Doctor wounded militia", + L"Drill existing militia", }; @@ -2758,6 +2764,7 @@ STR16 pAssignMenuStrings[] = L"无线电扫描", // Flugente: the merc is scanning for patrols in neighbouring sectors L"告发", // anv: snitch actions L"训练", + L"Militia", // all things militia L"搬运物品", // get items L"筑防", //L"Fortify", fortify sector L"Intel", // covert assignments // TODO.Translate @@ -2983,7 +2990,6 @@ STR16 pAttributeMenuStrings[] = STR16 pTrainingMenuStrings[] = { L"锻炼", // train yourself - L"民兵", // train the town L"游击队", // L"Mobile Militia", //ham3.6 L"培训工人", //L"Train workers", L"教练", // train your teammates @@ -4587,6 +4593,7 @@ STR16 pTransactionText[] = L"Kerberus安保公司的费用", //L"Payment to Kerberus",  // Flugente: PMC L"修理SAM基地",//L"SAM site repair", // Flugente: SAM repair L"培训工人",//L"Trained workers", // Flugente: train workers + L"Drill militia in %s", // Flugente: drill militia // TODO.Translate }; STR16 pTransactionAlternateText[] = @@ -11364,6 +11371,80 @@ STR16 szIntelText[] = L"%s has been discovered, going to sector!", }; +STR16 szChatTextSpy[] = +{ + L"... so imagine my surprise when suddenly...", + L"... and did I ever tell you the story of that one time...", + L"... so, in conclusion, the colonel decided...", + L"... tell you, they did not see that coming...", + + L"... so, without further consideration...", + L"... but then SHE said...", + L"... and, speaking of llamas...", + L"... there I was, in the middle of the dustbowl, when...", + + L"... and let me tell, those things chafe...", + L"... you should have seen his face...", + L"... which wasn't the last of what we saw of them...", + L"... which reminds me, my grandmother used to say...", + + L"... who, by the way, is a total berk...", + L"... also, the roots were off by a margin...", + L"... and I was like, 'Back off, heathen!'...", + L"... at that point the vicars were in oben rebellion...", + + L"... not that I would've minded, you know, but...", + L"... if not for that ridiculous hat...", + L"... besides, it wasn't his favourite leg anyway...", + L"... even though the ships were still watertight...", + + L"... aside from the fact that giraffes can't do that...", + L"... totally wasted that fork, mind you...", + L"... and no bakery in sight. After that...", + L"... even though regulations are clear in that regard...", +}; + +STR16 szChatTextEnemy[] = +{ + L"Whoa. I had no idea!", + L"Really?", + L"Uhhhh....", + L"Well... you see, uhh...", + + L"I am not entirely sure that...", + L"I... well...", + L"If I could just...", + L"But...", + + L"I don't mean to intrude, but...", + L"Really? I had no idea!", + L"What? All of it?", + L"No way!", + + L"Haha!", + L"Whoa, the guys are not going to believe me!", + L"... yeah, just...", + L"That's just like the gypsy woman said!", + + L"... yeah, is that why...", + L"... hehe, talk about refurbishing...", + L"... yeah, I guess...", + L"Wait. What?", + + L"... wouldn't have minded seeing that...", + L"... now that you mention it...", + L"... but where did all the chalk go...", + L"... had never even considered that...", +}; + +STR16 szMilitiaText[] = +{ + L"Train new militia", + L"Drill militia", + L"Doctor militia", + L"Cancel", +}; + // WANNE: Some Chinese specific strings that needs to be in unicode! STR16 ChineseSpecString1 = L"%%"; //defined in _ChineseText.cpp as this file is already unicode STR16 ChineseSpecString2 = L"*%3d%%%%"; //defined in _ChineseText.cpp as this file is already unicode diff --git a/Utils/_DutchText.cpp b/Utils/_DutchText.cpp index 13b7cfe6..37ff955a 100644 --- a/Utils/_DutchText.cpp +++ b/Utils/_DutchText.cpp @@ -2469,6 +2469,8 @@ STR16 pAssignmentStrings[] = L"Train W.", L"Hide", // TODO.Translate L"GetIntel", + L"DoctorM.", + L"DMilitia", }; @@ -2574,6 +2576,8 @@ STR16 pPersonnelAssignmentStrings[] = L"Train workers", L"Hide while disguised", // TODO.Translate L"Get intel while disguised", + L"Doctor wounded militia", + L"Drill existing militia", }; @@ -2638,6 +2642,8 @@ STR16 pLongAssignmentStrings[] = L"Train workers", L"Hide while disguised", // TODO.Translate L"Get intel while disguised", + L"Doctor wounded militia", + L"Drill existing militia", }; @@ -2757,6 +2763,7 @@ STR16 pAssignMenuStrings[] = L"Radio Scan", // Flugente: the merc is scanning for patrols in neighbouring sectors L"Snitch", // TODO.Translate // anv: snitch actions L"Train", // the merc is training + L"Militia", // all things militia L"Get Item", // get items // TODO.Translate L"Fortify", // fortify sector // TODO.Translate L"Intel", // covert assignments // TODO.Translate @@ -2983,13 +2990,12 @@ STR16 pAttributeMenuStrings[] = STR16 pTrainingMenuStrings[] = { - L"Oefenen", // train yourself - L"Militie", // train the town - L"Mobile Militia", // TODO.Translate - L"Train workers", // TODO.Translate - L"Trainer", // train your teammates - L"Student", // be trained by an instructor - L"Stop", // cancel this menu + L"Oefenen", // train yourself + L"Mobile Militia", // TODO.Translate + L"Train workers", // TODO.Translate + L"Trainer", // train your teammates + L"Student", // be trained by an instructor + L"Stop", // cancel this menu }; @@ -4592,6 +4598,7 @@ STR16 pTransactionText[] = L"Payment to Kerberus", // Flugente: PMC L"SAM site repair", // Flugente: SAM repair // TODO.Translate L"Trained workers", // Flugente: train workers + L"Drill militia in %s", // Flugente: drill militia // TODO.Translate }; STR16 pTransactionAlternateText[] = @@ -11382,4 +11389,78 @@ STR16 szIntelText[] = L"%s has been discovered, going to sector!", }; +STR16 szChatTextSpy[] = +{ + L"... so imagine my surprise when suddenly...", + L"... and did I ever tell you the story of that one time...", + L"... so, in conclusion, the colonel decided...", + L"... tell you, they did not see that coming...", + + L"... so, without further consideration...", + L"... but then SHE said...", + L"... and, speaking of llamas...", + L"... there I was, in the middle of the dustbowl, when...", + + L"... and let me tell, those things chafe...", + L"... you should have seen his face...", + L"... which wasn't the last of what we saw of them...", + L"... which reminds me, my grandmother used to say...", + + L"... who, by the way, is a total berk...", + L"... also, the roots were off by a margin...", + L"... and I was like, 'Back off, heathen!'...", + L"... at that point the vicars were in oben rebellion...", + + L"... not that I would've minded, you know, but...", + L"... if not for that ridiculous hat...", + L"... besides, it wasn't his favourite leg anyway...", + L"... even though the ships were still watertight...", + + L"... aside from the fact that giraffes can't do that...", + L"... totally wasted that fork, mind you...", + L"... and no bakery in sight. After that...", + L"... even though regulations are clear in that regard...", +}; + +STR16 szChatTextEnemy[] = +{ + L"Whoa. I had no idea!", + L"Really?", + L"Uhhhh....", + L"Well... you see, uhh...", + + L"I am not entirely sure that...", + L"I... well...", + L"If I could just...", + L"But...", + + L"I don't mean to intrude, but...", + L"Really? I had no idea!", + L"What? All of it?", + L"No way!", + + L"Haha!", + L"Whoa, the guys are not going to believe me!", + L"... yeah, just...", + L"That's just like the gypsy woman said!", + + L"... yeah, is that why...", + L"... hehe, talk about refurbishing...", + L"... yeah, I guess...", + L"Wait. What?", + + L"... wouldn't have minded seeing that...", + L"... now that you mention it...", + L"... but where did all the chalk go...", + L"... had never even considered that...", +}; + +STR16 szMilitiaText[] = +{ + L"Train new militia", + L"Drill militia", + L"Doctor militia", + L"Cancel", +}; + #endif //DUTCH diff --git a/Utils/_EnglishText.cpp b/Utils/_EnglishText.cpp index 5b61440c..baefa295 100644 --- a/Utils/_EnglishText.cpp +++ b/Utils/_EnglishText.cpp @@ -2470,6 +2470,8 @@ STR16 pAssignmentStrings[] = L"Train W.", L"Hide", L"GetIntel", + L"DoctorM.", + L"DMilitia", }; @@ -2575,6 +2577,8 @@ STR16 pPersonnelAssignmentStrings[] = L"Train workers", L"Hide while disguised", L"Get intel while disguised", + L"Doctor wounded militia", + L"Drill existing militia", }; @@ -2639,6 +2643,8 @@ STR16 pLongAssignmentStrings[] = L"Train workers", L"Hide while disguised", L"Get intel while disguised", + L"Doctor wounded militia", + L"Drill existing militia", }; @@ -2755,9 +2761,10 @@ STR16 pAssignMenuStrings[] = L"Patient", // the merc is receiving medical attention L"Vehicle", // the merc is in a vehicle L"Repair", // the merc is repairing items - L"Radio Scan", // Flugente: the merc is scanning for patrols in neighbouring sectors + L"Radio Scan", // the merc is scanning for patrols in neighbouring sectors L"Snitch", // anv: snitch actions L"Train", // the merc is training + L"Militia", // all things militia L"Get Item", // move items L"Fortify", // fortify sector L"Intel", // covert assignments @@ -2982,13 +2989,12 @@ STR16 pAttributeMenuStrings[] = STR16 pTrainingMenuStrings[] = { - L"Practice", // train yourself - L"Militia", // train the town - L"Mobile Militia", - L"Train workers", - L"Trainer", // train your teammates - L"Student", // be trained by an instructor - L"Cancel", // cancel this menu + L"Practice", // train yourself + L"Mobile Militia", + L"Train workers", + L"Trainer", // train your teammates + L"Student", // be trained by an instructor + L"Cancel", // cancel this menu }; @@ -4588,6 +4594,7 @@ STR16 pTransactionText[] = L"Payment to Kerberus", // Flugente: PMC L"SAM site repair", // Flugente: SAM repair L"Trained workers", // Flugente: train workers + L"Drill militia in %s", // Flugente: drill militia }; STR16 pTransactionAlternateText[] = @@ -11432,4 +11439,12 @@ STR16 szChatTextEnemy[] = L"... had never even considered that...", }; +STR16 szMilitiaText[] = +{ + L"Train new militia", + L"Drill militia", + L"Doctor militia", + L"Cancel", +}; + #endif //ENGLISH diff --git a/Utils/_FrenchText.cpp b/Utils/_FrenchText.cpp index 2fbd560a..79a0dad6 100644 --- a/Utils/_FrenchText.cpp +++ b/Utils/_FrenchText.cpp @@ -2478,6 +2478,8 @@ STR16 pAssignmentStrings[] = L"Train W.", L"Hide", // TODO.Translate L"GetIntel", + L"DoctorM.", + L"DMilitia", }; @@ -2583,6 +2585,8 @@ STR16 pPersonnelAssignmentStrings[] = L"Train workers", L"Hide while disguised", // TODO.Translate L"Get intel while disguised", + L"Doctor wounded militia", + L"Drill existing militia", }; @@ -2647,6 +2651,8 @@ STR16 pLongAssignmentStrings[] = L"Train workers", L"Hide while disguised", // TODO.Translate L"Get intel while disguised", + L"Doctor wounded militia", + L"Drill existing militia", }; @@ -2766,6 +2772,7 @@ STR16 pAssignMenuStrings[] = L"Radio", // Flugente: the merc is scanning for patrols in neighbouring sectors L"Infiltré", // anv: snitch actions L"Formation", // the merc is training + L"Militia", // all things militia L"Dépl obj.", // move items L"Fortify", // fortify sector // TODO.Translate L"Intel", // covert assignments // TODO.Translate @@ -2991,7 +2998,6 @@ STR16 pAttributeMenuStrings[] = STR16 pTrainingMenuStrings[] = { L"Formation", // train yourself - L"Milice", // train the town L"Milice mobile", L"Train workers", // TODO.Translate L"Entraîneur", // train your teammates @@ -4596,6 +4602,7 @@ STR16 pTransactionText[] = L"Payment to Kerberus", // Flugente: PMC L"SAM site repair", // Flugente: SAM repair // TODO.Translate L"Trained workers", // Flugente: train workers + L"Drill militia in %s", // Flugente: drill militia // TODO.Translate }; STR16 pTransactionAlternateText[] = @@ -11364,4 +11371,78 @@ STR16 szIntelText[] = L"%s has been discovered, going to sector!", }; +STR16 szChatTextSpy[] = +{ + L"... so imagine my surprise when suddenly...", + L"... and did I ever tell you the story of that one time...", + L"... so, in conclusion, the colonel decided...", + L"... tell you, they did not see that coming...", + + L"... so, without further consideration...", + L"... but then SHE said...", + L"... and, speaking of llamas...", + L"... there I was, in the middle of the dustbowl, when...", + + L"... and let me tell, those things chafe...", + L"... you should have seen his face...", + L"... which wasn't the last of what we saw of them...", + L"... which reminds me, my grandmother used to say...", + + L"... who, by the way, is a total berk...", + L"... also, the roots were off by a margin...", + L"... and I was like, 'Back off, heathen!'...", + L"... at that point the vicars were in oben rebellion...", + + L"... not that I would've minded, you know, but...", + L"... if not for that ridiculous hat...", + L"... besides, it wasn't his favourite leg anyway...", + L"... even though the ships were still watertight...", + + L"... aside from the fact that giraffes can't do that...", + L"... totally wasted that fork, mind you...", + L"... and no bakery in sight. After that...", + L"... even though regulations are clear in that regard...", +}; + +STR16 szChatTextEnemy[] = +{ + L"Whoa. I had no idea!", + L"Really?", + L"Uhhhh....", + L"Well... you see, uhh...", + + L"I am not entirely sure that...", + L"I... well...", + L"If I could just...", + L"But...", + + L"I don't mean to intrude, but...", + L"Really? I had no idea!", + L"What? All of it?", + L"No way!", + + L"Haha!", + L"Whoa, the guys are not going to believe me!", + L"... yeah, just...", + L"That's just like the gypsy woman said!", + + L"... yeah, is that why...", + L"... hehe, talk about refurbishing...", + L"... yeah, I guess...", + L"Wait. What?", + + L"... wouldn't have minded seeing that...", + L"... now that you mention it...", + L"... but where did all the chalk go...", + L"... had never even considered that...", +}; + +STR16 szMilitiaText[] = +{ + L"Train new militia", + L"Drill militia", + L"Doctor militia", + L"Cancel", +}; + #endif //FRENCH diff --git a/Utils/_GermanText.cpp b/Utils/_GermanText.cpp index a861b124..ff5f0cf0 100644 --- a/Utils/_GermanText.cpp +++ b/Utils/_GermanText.cpp @@ -2483,6 +2483,8 @@ STR16 pAssignmentStrings[] = L"Train W.", L"Hide", // TODO.Translate L"GetIntel", + L"DoctorM.", + L"DMilitia", }; STR16 pMilitiaString[] = @@ -2584,6 +2586,8 @@ STR16 pPersonnelAssignmentStrings[] = L"Train workers", L"Hide while disguised", // TODO.Translate L"Get intel while disguised", + L"Doctor wounded militia", + L"Drill existing militia", }; // refer to above for comments @@ -2646,6 +2650,8 @@ STR16 pLongAssignmentStrings[] = L"Train workers", L"Hide while disguised", // TODO.Translate L"Get intel while disguised", + L"Doctor wounded militia", + L"Drill existing militia", }; // the contract options @@ -2761,6 +2767,7 @@ STR16 pAssignMenuStrings[] = L"Radio Scan", // Flugente: the merc is scanning for patrols in neighbouring sectors L"Snitch", // TODO.Translate // anv: snitch actions L"Training", // the merc is training + L"Miliz", // all things militia L"Umzug", // move items L"Fortify", // fortify sector // TODO.Translate L"Intel", // covert assignments // TODO.Translate @@ -2986,13 +2993,12 @@ STR16 pAttributeMenuStrings[] = STR16 pTrainingMenuStrings[] = { - L"Üben", // train yourself - L"Miliz", // train the town - L"Mobile Miliz", - L"Train workers", // TODO.Translate - L"Trainer", // train your teammates - L"Rekrut", // be trained by an instructor - L"Abbrechen", // cancel this menu + L"Üben", // train yourself + L"Mobile Miliz", + L"Train workers", // TODO.Translate + L"Trainer", // train your teammates + L"Rekrut", // be trained by an instructor + L"Abbrechen", // cancel this menu }; STR16 pSquadMenuStrings[] = @@ -4568,6 +4574,7 @@ STR16 pTransactionText[] = L"Payment to Kerberus", // Flugente: PMC L"SAM site repair", // Flugente: SAM repair // TODO.Translate L"Trained workers", // Flugente: train workers + L"Drill militia in %s", // Flugente: drill militia // TODO.Translate }; STR16 pTransactionAlternateText[] = @@ -11194,4 +11201,78 @@ STR16 szIntelText[] = L"%s has been discovered, going to sector!", }; +STR16 szChatTextSpy[] = +{ + L"... so imagine my surprise when suddenly...", + L"... and did I ever tell you the story of that one time...", + L"... so, in conclusion, the colonel decided...", + L"... tell you, they did not see that coming...", + + L"... so, without further consideration...", + L"... but then SHE said...", + L"... and, speaking of llamas...", + L"... there I was, in the middle of the dustbowl, when...", + + L"... and let me tell, those things chafe...", + L"... you should have seen his face...", + L"... which wasn't the last of what we saw of them...", + L"... which reminds me, my grandmother used to say...", + + L"... who, by the way, is a total berk...", + L"... also, the roots were off by a margin...", + L"... and I was like, 'Back off, heathen!'...", + L"... at that point the vicars were in oben rebellion...", + + L"... not that I would've minded, you know, but...", + L"... if not for that ridiculous hat...", + L"... besides, it wasn't his favourite leg anyway...", + L"... even though the ships were still watertight...", + + L"... aside from the fact that giraffes can't do that...", + L"... totally wasted that fork, mind you...", + L"... and no bakery in sight. After that...", + L"... even though regulations are clear in that regard...", +}; + +STR16 szChatTextEnemy[] = +{ + L"Whoa. I had no idea!", + L"Really?", + L"Uhhhh....", + L"Well... you see, uhh...", + + L"I am not entirely sure that...", + L"I... well...", + L"If I could just...", + L"But...", + + L"I don't mean to intrude, but...", + L"Really? I had no idea!", + L"What? All of it?", + L"No way!", + + L"Haha!", + L"Whoa, the guys are not going to believe me!", + L"... yeah, just...", + L"That's just like the gypsy woman said!", + + L"... yeah, is that why...", + L"... hehe, talk about refurbishing...", + L"... yeah, I guess...", + L"Wait. What?", + + L"... wouldn't have minded seeing that...", + L"... now that you mention it...", + L"... but where did all the chalk go...", + L"... had never even considered that...", +}; + +STR16 szMilitiaText[] = +{ + L"Train new militia", + L"Drill militia", + L"Doctor militia", + L"Cancel", +}; + #endif //GERMAN diff --git a/Utils/_ItalianText.cpp b/Utils/_ItalianText.cpp index a1e68179..d4f7ea0b 100644 --- a/Utils/_ItalianText.cpp +++ b/Utils/_ItalianText.cpp @@ -2464,6 +2464,8 @@ STR16 pAssignmentStrings[] = L"Train W.", L"Hide", // TODO.Translate L"GetIntel", + L"DoctorM.", + L"DMilitia", }; @@ -2569,6 +2571,8 @@ STR16 pPersonnelAssignmentStrings[] = L"Train workers", L"Hide while disguised", // TODO.Translate L"Get intel while disguised", + L"Doctor wounded militia", + L"Drill existing militia", }; @@ -2633,6 +2637,8 @@ STR16 pLongAssignmentStrings[] = L"Train workers", L"Hide while disguised", // TODO.Translate L"Get intel while disguised", + L"Doctor wounded militia", + L"Drill existing militia", }; @@ -2752,6 +2758,7 @@ STR16 pAssignMenuStrings[] = L"Radio Scan", // Flugente: the merc is scanning for patrols in neighbouring sectors L"Snitch", // TODO.Translate // anv: snitch actions L"Si esercita", // the merc is training + L"Militia", // all things militia L"Get Item", // get items // TODO.Translate L"Fortify", // fortify sector // TODO.Translate L"Intel", // covert assignments // TODO.Translate @@ -2978,13 +2985,12 @@ STR16 pAttributeMenuStrings[] = STR16 pTrainingMenuStrings[] = { - L"Allenati", // train yourself - L"Esercito", // train the town - L"Mobile Militia", // TODO.Translate - L"Train workers", // TODO.Translate - L"Allenatore", // train your teammates - L"Studente", // be trained by an instructor - L"Annulla", // cancel this menu + L"Allenati", // train yourself + L"Mobile Militia", // TODO.Translate + L"Train workers", // TODO.Translate + L"Allenatore", // train your teammates + L"Studente", // be trained by an instructor + L"Annulla", // cancel this menu }; @@ -4586,6 +4592,7 @@ STR16 pTransactionText[] = L"Payment to Kerberus", // Flugente: PMC L"SAM site repair", // Flugente: SAM repair // TODO.Translate L"Trained workers", // Flugente: train workers + L"Drill militia in %s", // Flugente: drill militia // TODO.Translate }; STR16 pTransactionAlternateText[] = @@ -11373,4 +11380,78 @@ STR16 szIntelText[] = L"%s has been discovered, going to sector!", }; +STR16 szChatTextSpy[] = +{ + L"... so imagine my surprise when suddenly...", + L"... and did I ever tell you the story of that one time...", + L"... so, in conclusion, the colonel decided...", + L"... tell you, they did not see that coming...", + + L"... so, without further consideration...", + L"... but then SHE said...", + L"... and, speaking of llamas...", + L"... there I was, in the middle of the dustbowl, when...", + + L"... and let me tell, those things chafe...", + L"... you should have seen his face...", + L"... which wasn't the last of what we saw of them...", + L"... which reminds me, my grandmother used to say...", + + L"... who, by the way, is a total berk...", + L"... also, the roots were off by a margin...", + L"... and I was like, 'Back off, heathen!'...", + L"... at that point the vicars were in oben rebellion...", + + L"... not that I would've minded, you know, but...", + L"... if not for that ridiculous hat...", + L"... besides, it wasn't his favourite leg anyway...", + L"... even though the ships were still watertight...", + + L"... aside from the fact that giraffes can't do that...", + L"... totally wasted that fork, mind you...", + L"... and no bakery in sight. After that...", + L"... even though regulations are clear in that regard...", +}; + +STR16 szChatTextEnemy[] = +{ + L"Whoa. I had no idea!", + L"Really?", + L"Uhhhh....", + L"Well... you see, uhh...", + + L"I am not entirely sure that...", + L"I... well...", + L"If I could just...", + L"But...", + + L"I don't mean to intrude, but...", + L"Really? I had no idea!", + L"What? All of it?", + L"No way!", + + L"Haha!", + L"Whoa, the guys are not going to believe me!", + L"... yeah, just...", + L"That's just like the gypsy woman said!", + + L"... yeah, is that why...", + L"... hehe, talk about refurbishing...", + L"... yeah, I guess...", + L"Wait. What?", + + L"... wouldn't have minded seeing that...", + L"... now that you mention it...", + L"... but where did all the chalk go...", + L"... had never even considered that...", +}; + +STR16 szMilitiaText[] = +{ + L"Train new militia", + L"Drill militia", + L"Doctor militia", + L"Cancel", +}; + #endif //ITALIAN diff --git a/Utils/_PolishText.cpp b/Utils/_PolishText.cpp index aca8a4bb..731bb391 100644 --- a/Utils/_PolishText.cpp +++ b/Utils/_PolishText.cpp @@ -2476,6 +2476,8 @@ STR16 pAssignmentStrings[] = L"Train W.", L"Hide", // TODO.Translate L"GetIntel", + L"DoctorM.", + L"DMilitia", }; @@ -2581,6 +2583,8 @@ STR16 pPersonnelAssignmentStrings[] = L"Train workers", L"Hide while disguised", // TODO.Translate L"Get intel while disguised", + L"Doctor wounded militia", + L"Drill existing militia", }; @@ -2645,6 +2649,8 @@ STR16 pLongAssignmentStrings[] = L"Train workers", L"Hide while disguised", // TODO.Translate L"Get intel while disguised", + L"Doctor wounded militia", + L"Drill existing militia", }; @@ -2764,6 +2770,7 @@ STR16 pAssignMenuStrings[] = L"Nasłuch", // Flugente: the merc is scanning for patrols in neighbouring sectors L"Kapuś", // anv: snitch actions L"Szkolenie", // the merc is training + L"Militia", // all things militia L"Get Item", // get items // TODO.Translate L"Fortify", // fortify sector // TODO.Translate L"Intel", // covert assignments // TODO.Translate @@ -2988,13 +2995,12 @@ STR16 pAttributeMenuStrings[] = STR16 pTrainingMenuStrings[] = { - L"Praktyka", // train yourself - L"Samoobrona", // train the town - L"Mobile Militia", // TODO.Translate - L"Train workers", // TODO.Translate - L"Instruktor", // train your teammates - L"Uczeń", // be trained by an instructor - L"Anuluj", // cancel this menu + L"Praktyka", // train yourself + L"Mobile Militia", // TODO.Translate + L"Train workers", // TODO.Translate + L"Instruktor", // train your teammates + L"Uczeń", // be trained by an instructor + L"Anuluj", // cancel this menu }; @@ -4597,6 +4603,7 @@ STR16 pTransactionText[] = L"Payment to Kerberus", // Flugente: PMC L"SAM site repair", // Flugente: SAM repair // TODO.Translate L"Trained workers", // Flugente: train workers + L"Drill militia in %s", // Flugente: drill militia // TODO.Translate }; STR16 pTransactionAlternateText[] = @@ -11386,4 +11393,78 @@ STR16 szIntelText[] = L"%s has been discovered, going to sector!", }; +STR16 szChatTextSpy[] = +{ + L"... so imagine my surprise when suddenly...", + L"... and did I ever tell you the story of that one time...", + L"... so, in conclusion, the colonel decided...", + L"... tell you, they did not see that coming...", + + L"... so, without further consideration...", + L"... but then SHE said...", + L"... and, speaking of llamas...", + L"... there I was, in the middle of the dustbowl, when...", + + L"... and let me tell, those things chafe...", + L"... you should have seen his face...", + L"... which wasn't the last of what we saw of them...", + L"... which reminds me, my grandmother used to say...", + + L"... who, by the way, is a total berk...", + L"... also, the roots were off by a margin...", + L"... and I was like, 'Back off, heathen!'...", + L"... at that point the vicars were in oben rebellion...", + + L"... not that I would've minded, you know, but...", + L"... if not for that ridiculous hat...", + L"... besides, it wasn't his favourite leg anyway...", + L"... even though the ships were still watertight...", + + L"... aside from the fact that giraffes can't do that...", + L"... totally wasted that fork, mind you...", + L"... and no bakery in sight. After that...", + L"... even though regulations are clear in that regard...", +}; + +STR16 szChatTextEnemy[] = +{ + L"Whoa. I had no idea!", + L"Really?", + L"Uhhhh....", + L"Well... you see, uhh...", + + L"I am not entirely sure that...", + L"I... well...", + L"If I could just...", + L"But...", + + L"I don't mean to intrude, but...", + L"Really? I had no idea!", + L"What? All of it?", + L"No way!", + + L"Haha!", + L"Whoa, the guys are not going to believe me!", + L"... yeah, just...", + L"That's just like the gypsy woman said!", + + L"... yeah, is that why...", + L"... hehe, talk about refurbishing...", + L"... yeah, I guess...", + L"Wait. What?", + + L"... wouldn't have minded seeing that...", + L"... now that you mention it...", + L"... but where did all the chalk go...", + L"... had never even considered that...", +}; + +STR16 szMilitiaText[] = +{ + L"Train new militia", + L"Drill militia", + L"Doctor militia", + L"Cancel", +}; + #endif //POLISH diff --git a/Utils/_RussianText.cpp b/Utils/_RussianText.cpp index 8b898706..3b25386d 100644 --- a/Utils/_RussianText.cpp +++ b/Utils/_RussianText.cpp @@ -2470,6 +2470,8 @@ STR16 pAssignmentStrings[] = L"Учит рабочих", L"Hide", // TODO.Translate L"GetIntel", + L"DoctorM.", + L"DMilitia", }; @@ -2575,6 +2577,8 @@ STR16 pPersonnelAssignmentStrings[] = L"Учит рабочих", L"Hide while disguised", // TODO.Translate L"Get intel while disguised", + L"Doctor wounded militia", + L"Drill existing militia", }; @@ -2639,6 +2643,8 @@ STR16 pLongAssignmentStrings[] = L"Учит рабочих", L"Hide while disguised", // TODO.Translate L"Get intel while disguised", + L"Doctor wounded militia", + L"Drill existing militia", }; @@ -2758,6 +2764,7 @@ STR16 pAssignMenuStrings[] = L"Радио", // Flugente: the merc is scanning for patrols in neighbouring sectors L"Осведомитель", // anv: snitch actions L"Обучение", // the merc is training + L"Militia", // all things militia L"Носильщик", // move items L"Укреплять", // fortify sector L"Intel", // covert assignments // TODO.Translate @@ -2982,13 +2989,12 @@ STR16 pAttributeMenuStrings[] = STR16 pTrainingMenuStrings[] = { - L"Практика", // train yourself - L"Ополчение", // train the town - L"Патрульные", - L"Рабочие", // Train workers - L"Тренер", // train your teammates - L"Ученик", // be trained by an instructor - L"Отмена", // cancel this menu + L"Практика", // train yourself + L"Патрульные", + L"Рабочие", // Train workers + L"Тренер", // train your teammates + L"Ученик", // be trained by an instructor + L"Отмена", // cancel this menu }; @@ -4588,6 +4594,7 @@ STR16 pTransactionText[] = L"Оплата услуг Цербер", // Flugente: PMC L"Стоимость ремонта базы ПВО", // Flugente: SAM repair L"Trained workers", // Flugente: train workers // TODO.Translate + L"Drill militia in %s", // Flugente: drill militia // TODO.Translate }; STR16 pTransactionAlternateText[] = @@ -11366,4 +11373,78 @@ STR16 szIntelText[] = L"%s has been discovered, going to sector!", }; +STR16 szChatTextSpy[] = +{ + L"... so imagine my surprise when suddenly...", + L"... and did I ever tell you the story of that one time...", + L"... so, in conclusion, the colonel decided...", + L"... tell you, they did not see that coming...", + + L"... so, without further consideration...", + L"... but then SHE said...", + L"... and, speaking of llamas...", + L"... there I was, in the middle of the dustbowl, when...", + + L"... and let me tell, those things chafe...", + L"... you should have seen his face...", + L"... which wasn't the last of what we saw of them...", + L"... which reminds me, my grandmother used to say...", + + L"... who, by the way, is a total berk...", + L"... also, the roots were off by a margin...", + L"... and I was like, 'Back off, heathen!'...", + L"... at that point the vicars were in oben rebellion...", + + L"... not that I would've minded, you know, but...", + L"... if not for that ridiculous hat...", + L"... besides, it wasn't his favourite leg anyway...", + L"... even though the ships were still watertight...", + + L"... aside from the fact that giraffes can't do that...", + L"... totally wasted that fork, mind you...", + L"... and no bakery in sight. After that...", + L"... even though regulations are clear in that regard...", +}; + +STR16 szChatTextEnemy[] = +{ + L"Whoa. I had no idea!", + L"Really?", + L"Uhhhh....", + L"Well... you see, uhh...", + + L"I am not entirely sure that...", + L"I... well...", + L"If I could just...", + L"But...", + + L"I don't mean to intrude, but...", + L"Really? I had no idea!", + L"What? All of it?", + L"No way!", + + L"Haha!", + L"Whoa, the guys are not going to believe me!", + L"... yeah, just...", + L"That's just like the gypsy woman said!", + + L"... yeah, is that why...", + L"... hehe, talk about refurbishing...", + L"... yeah, I guess...", + L"Wait. What?", + + L"... wouldn't have minded seeing that...", + L"... now that you mention it...", + L"... but where did all the chalk go...", + L"... had never even considered that...", +}; + +STR16 szMilitiaText[] = +{ + L"Train new militia", + L"Drill militia", + L"Doctor militia", + L"Cancel", +}; + #endif //RUSSIAN