diff --git a/GameSettings.cpp b/GameSettings.cpp index 7bac3a65..318d52c7 100644 --- a/GameSettings.cpp +++ b/GameSettings.cpp @@ -2213,7 +2213,34 @@ void LoadGameExternalOptions() gGameExternalOptions.usMilitiaAmmo_Max = iniReader.ReadInteger("Militia Equipment Settings","MILITIA_USE_SECTOR_EQUIPMENT_AMMO_MAX", 200, 30, 400); gGameExternalOptions.usMilitiaAmmo_OptimalMagCount = iniReader.ReadInteger("Militia Equipment Settings","MILITIA_USE_SECTOR_EQUIPMENT_AMMO_OPTIMAL_MAG_COUNT", 2, 1, 10); gGameExternalOptions.fMilitiaUseSectorClassSpecificTaboos = iniReader.ReadBoolean("Militia Equipment Settings","MILITIA_USE_SECTOR_EQUIPMENT_CLASS_SPECIFIC_TABOOS", TRUE); - + + //################# Militia Resource Settings ################## + + gGameExternalOptions.fMilitiaResources = iniReader.ReadBoolean( "Militia Resource Settings", "MILITIA_REQUIRE_RESOURCES", FALSE ); + gGameExternalOptions.fMilitiaResources_ProgressFactor = iniReader.ReadFloat( "Militia Resource Settings", "MILITIA_RESOURCES_PROGRESSFACTOR", 10.0f, 1.0f, 100.0f ); + + gGameExternalOptions.fMilitiaResources_ItemClassMod_Ammo_Bullet = iniReader.ReadFloat( "Militia Resource Settings", "MILITIA_RESOURCES_ITEMCLASSMOD_AMMO_BULLET", 0.01f, 0.0f, 1.0f ); + gGameExternalOptions.fMilitiaResources_ItemClassMod_Gun = iniReader.ReadFloat( "Militia Resource Settings", "MILITIA_RESOURCES_ITEMCLASSMOD_GUN", 1.0f, 0.0f, 1.0f ); + gGameExternalOptions.fMilitiaResources_ItemClassMod_Armour = iniReader.ReadFloat( "Militia Resource Settings", "MILITIA_RESOURCES_ITEMCLASSMOD_ARMOUR", 1.0f, 0.0f, 1.0f ); + gGameExternalOptions.fMilitiaResources_ItemClassMod_Melee = iniReader.ReadFloat( "Militia Resource Settings", "MILITIA_RESOURCES_ITEMCLASSMOD_MELEE", 0.25f, 0.0f, 1.0f ); + gGameExternalOptions.fMilitiaResources_ItemClassMod_Bomb = iniReader.ReadFloat( "Militia Resource Settings", "MILITIA_RESOURCES_ITEMCLASSMOD_BOMB", 0.25f, 0.0f, 1.0f ); + gGameExternalOptions.fMilitiaResources_ItemClassMod_Grenade = iniReader.ReadFloat( "Militia Resource Settings", "MILITIA_RESOURCES_ITEMCLASSMOD_GRENADE", 0.17f, 0.0f, 1.0f ); + gGameExternalOptions.fMilitiaResources_ItemClassMod_Face = iniReader.ReadFloat( "Militia Resource Settings", "MILITIA_RESOURCES_ITEMCLASSMOD_FACE", 0.2f, 0.0f, 1.0f ); + gGameExternalOptions.fMilitiaResources_ItemClassMod_LBE = iniReader.ReadFloat( "Militia Resource Settings", "MILITIA_RESOURCES_ITEMCLASSMOD_LBE", 0.17f, 0.0f, 1.0f ); + gGameExternalOptions.fMilitiaResources_ItemClassMod_Attachment_Low = iniReader.ReadFloat( "Militia Resource Settings", "MILITIA_RESOURCES_ITEMCLASSMOD_ATTACHMENT_LOW", 0.05f, 0.0f, 1.0f ); + gGameExternalOptions.fMilitiaResources_ItemClassMod_Attachment_Medium = iniReader.ReadFloat( "Militia Resource Settings", "MILITIA_RESOURCES_ITEMCLASSMOD_ATTACHMENT_MEDIUM", 0.1f, 0.0f, 1.0f ); + gGameExternalOptions.fMilitiaResources_ItemClassMod_Attachment_High = iniReader.ReadFloat( "Militia Resource Settings", "MILITIA_RESOURCES_ITEMCLASSMOD_ATTACHMENT_HIGH", 0.2f, 0.0f, 1.0f ); + + gGameExternalOptions.fMilitiaResources_WeaponMod[NOT_GUN] = 1.0f; + gGameExternalOptions.fMilitiaResources_WeaponMod[GUN_PISTOL] = iniReader.ReadFloat( "Militia Resource Settings", "MILITIA_RESOURCES_WEAPONMOD_PISTOL", 0.6f, 0.0f, 1.0f ); + gGameExternalOptions.fMilitiaResources_WeaponMod[GUN_M_PISTOL] = iniReader.ReadFloat( "Militia Resource Settings", "MILITIA_RESOURCES_WEAPONMOD_M_PISTOL", 0.7f, 0.0f, 1.0f ); + gGameExternalOptions.fMilitiaResources_WeaponMod[GUN_SMG] = iniReader.ReadFloat( "Militia Resource Settings", "MILITIA_RESOURCES_WEAPONMOD_SMG", 0.8f, 0.0f, 1.0f ); + gGameExternalOptions.fMilitiaResources_WeaponMod[GUN_RIFLE] = iniReader.ReadFloat( "Militia Resource Settings", "MILITIA_RESOURCES_WEAPONMOD_RIFLE", 0.9f, 0.0f, 1.0f ); + gGameExternalOptions.fMilitiaResources_WeaponMod[GUN_SN_RIFLE] = iniReader.ReadFloat( "Militia Resource Settings", "MILITIA_RESOURCES_WEAPONMOD_SN_RIFLE", 1.0f, 0.0f, 1.0f ); + gGameExternalOptions.fMilitiaResources_WeaponMod[GUN_AS_RIFLE] = iniReader.ReadFloat( "Militia Resource Settings", "MILITIA_RESOURCES_WEAPONMOD_AS_RIFLE", 1.0f, 0.0f, 1.0f ); + gGameExternalOptions.fMilitiaResources_WeaponMod[GUN_LMG] = iniReader.ReadFloat( "Militia Resource Settings", "MILITIA_RESOURCES_WEAPONMOD_LMG", 1.0f, 0.0f, 1.0f ); + gGameExternalOptions.fMilitiaResources_WeaponMod[GUN_SHOTGUN] = iniReader.ReadFloat( "Militia Resource Settings", "MILITIA_RESOURCES_WEAPONMOD_SHOTGUN", 1.0f, 0.0f, 1.0f ); + //################# Shopkeeper Inventory Settings ################## // WDS - Improve Tony's and Devin's inventory like BR's diff --git a/GameSettings.h b/GameSettings.h index e8d808e5..602517d6 100644 --- a/GameSettings.h +++ b/GameSettings.h @@ -224,6 +224,22 @@ enum ASD_RESOURCE_MAX }; +// exact gun types +enum +{ + NOT_GUN = 0, + GUN_PISTOL, + GUN_M_PISTOL, + GUN_SMG, + GUN_RIFLE, + GUN_SN_RIFLE, + GUN_AS_RIFLE, + GUN_LMG, + GUN_SHOTGUN, + + GUN_TYPES_MAX +}; + typedef struct { BOOLEAN fGunNut; @@ -512,6 +528,24 @@ typedef struct UINT16 usMilitiaAmmo_OptimalMagCount; BOOLEAN fMilitiaUseSectorClassSpecificTaboos; + // Flugente: militia resources + BOOLEAN fMilitiaResources; + FLOAT fMilitiaResources_ProgressFactor; + + FLOAT fMilitiaResources_ItemClassMod_Ammo_Bullet; + FLOAT fMilitiaResources_ItemClassMod_Gun; + FLOAT fMilitiaResources_ItemClassMod_Armour; + FLOAT fMilitiaResources_ItemClassMod_Melee; + FLOAT fMilitiaResources_ItemClassMod_Bomb; + FLOAT fMilitiaResources_ItemClassMod_Grenade; + FLOAT fMilitiaResources_ItemClassMod_Face; + FLOAT fMilitiaResources_ItemClassMod_LBE; + FLOAT fMilitiaResources_ItemClassMod_Attachment_Low; + FLOAT fMilitiaResources_ItemClassMod_Attachment_Medium; + FLOAT fMilitiaResources_ItemClassMod_Attachment_High; + + FLOAT fMilitiaResources_WeaponMod[GUN_TYPES_MAX]; + // Flugente - allow accessing other mercs inventory via 'stealing' BOOLEAN fAccessOtherMercInventories; @@ -2290,7 +2324,7 @@ typedef struct FLOAT fRangeModifierGrenade; // damage modifiers - FLOAT fDamageModifierGun[9]; + FLOAT fDamageModifierGun[GUN_TYPES_MAX]; FLOAT fDamageModifierBlade; FLOAT fDamageModifierPunch; FLOAT fDamageModifierTentacle; @@ -2302,23 +2336,23 @@ typedef struct FLOAT fShotsPer4TurnsModifierTentacle; FLOAT fShotsPer4TurnsModifierThrowKnife; // Burst AP modifiers - FLOAT fBurstAPModifierGun[9]; + FLOAT fBurstAPModifierGun[GUN_TYPES_MAX]; // AP modifiers for Auto Fire Shots per 5 AP (bAutofireShotsPerFiveAP) - FLOAT fAFShotsPer5APModifierGun[9]; + FLOAT fAFShotsPer5APModifierGun[GUN_TYPES_MAX]; // AP to Reload modifiers - FLOAT fAPtoReloadModifierGun[9]; + FLOAT fAPtoReloadModifierGun[GUN_TYPES_MAX]; FLOAT fAPtoReloadModifierLauncher; // AP to Reload manually modifiers - FLOAT fAPtoReloadManuallyModifierGun[9]; + FLOAT fAPtoReloadManuallyModifierGun[GUN_TYPES_MAX]; FLOAT fAPtoReloadManuallyModifierLauncher; // Max Distance for messy shot modifiers - FLOAT fDistMessyModifierGun[9]; + FLOAT fDistMessyModifierGun[GUN_TYPES_MAX]; // Handling modifiers - FLOAT fHandlingModifierGun[9]; + FLOAT fHandlingModifierGun[GUN_TYPES_MAX]; FLOAT fHandlingModifierLauncher; // Recoil modifiers - FLOAT fRecoilXModifierGun[9]; - FLOAT fRecoilYModifierGun[9]; + FLOAT fRecoilXModifierGun[GUN_TYPES_MAX]; + FLOAT fRecoilYModifierGun[GUN_TYPES_MAX]; // -------------- ARMOR MODIFIERS ---------------- FLOAT fCamoLBEoverVestModifier; diff --git a/GameVersion.cpp b/GameVersion.cpp index b5f72990..c873059a 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.8253 (Development Build)" }; + CHAR16 zVersionLabel[256] = { L"Unfinished Business - Map Editor v1.13.8270 (Development Build)" }; #else - CHAR16 zVersionLabel[256] = { L"Map Editor v1.13.8253 (Development Build)" }; + CHAR16 zVersionLabel[256] = { L"Map Editor v1.13.8270 (Development Build)" }; #endif // ------------------------------ @@ -27,11 +27,11 @@ //DEBUG BUILD VERSION #ifdef JA2UB - CHAR16 zVersionLabel[256] = { L"Debug: Unfinished Business - v1.13.8253 (Development Build)" }; + CHAR16 zVersionLabel[256] = { L"Debug: Unfinished Business - v1.13.8270 (Development Build)" }; #elif defined (JA113DEMO) - CHAR16 zVersionLabel[256] = { L"Debug: JA2 Demo - v1.13.8253 (Development Build)" }; + CHAR16 zVersionLabel[256] = { L"Debug: JA2 Demo - v1.13.8270 (Development Build)" }; #else - CHAR16 zVersionLabel[256] = { L"Debug: v1.13.8253 (Development Build)" }; + CHAR16 zVersionLabel[256] = { L"Debug: v1.13.8270 (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.8253 (Development Build)" }; + CHAR16 zVersionLabel[256] = { L"Release Unfinished Business - v1.13.8270 (Development Build)" }; #elif defined (JA113DEMO) - CHAR16 zVersionLabel[256] = { L"Release JA2 Demo - v1.13.8253 (Development Build)" }; + CHAR16 zVersionLabel[256] = { L"Release JA2 Demo - v1.13.8270 (Development Build)" }; #else - CHAR16 zVersionLabel[256] = { L"Release v1.13.8253 (Development Build)" }; + CHAR16 zVersionLabel[256] = { L"Release v1.13.8270 (Development Build)" }; #endif #endif -CHAR8 czVersionNumber[16] = { "Build 18.06.06" }; //YY.MM.DD +CHAR8 czVersionNumber[16] = { "Build 16.07.15" }; //YY.MM.DD CHAR16 zTrackingNumber[16] = { L"Z" }; // SAVE_GAME_VERSION is defined in header, change it there diff --git a/Laptop/LaptopSave.h b/Laptop/LaptopSave.h index 8c3526e4..7c7d424a 100644 --- a/Laptop/LaptopSave.h +++ b/Laptop/LaptopSave.h @@ -169,7 +169,12 @@ typedef struct // Flugente: militia volunteer pool. No relation to the laptop whatsoever, but I'm not creating a new struct for one variable FLOAT dMilitiaVolunteerPool; - UINT8 bPadding[ 72 ]; + // Flugente: additional militia resources + FLOAT dMilitiaGunPool; + FLOAT dMilitiaArmourPool; + FLOAT dMilitiaMiscPool; + + UINT8 bPadding[ 60 ]; } LaptopSaveInfoStruct; diff --git a/Strategic/Assignments.cpp b/Strategic/Assignments.cpp index 40192fd3..5d0c7036 100644 --- a/Strategic/Assignments.cpp +++ b/Strategic/Assignments.cpp @@ -1440,6 +1440,15 @@ BOOLEAN CanCharacterTrainMilitia( SOLDIERTYPE *pSoldier ) if ( !GetVolunteerPool() ) return FALSE; + if ( gGameExternalOptions.fMilitiaResources && !gGameExternalOptions.fMilitiaUseSectorInventory ) + { + FLOAT val_gun, val_armour, val_misc; + GetResources( val_gun, val_armour, val_misc ); + + if ( val_gun <= 1.0f ) + return FALSE; + } + // Make sure the basic sector/merc variables are still applicable. This is simply a fail-safe. if( !BasicCanCharacterTrainMilitia( pSoldier ) ) { @@ -6988,6 +6997,14 @@ void HandlePrisonerProcessingInSector( INT16 sMapX, INT16 sMapY, INT8 bZ ) if ( turnedmilitia[PRISONER_ADMIN] + turnedmilitia[PRISONER_REGULAR] + turnedmilitia[PRISONER_ELITE] + turnedmilitia[PRISONER_OFFICER] ) { + // we need to remove resources for these guys + if ( gGameExternalOptions.fMilitiaResources && !gGameExternalOptions.fMilitiaUseSectorInventory ) + { + AddResources( -turnedmilitia[PRISONER_ADMIN] - turnedmilitia[PRISONER_REGULAR] - (turnedmilitia[PRISONER_ELITE] + turnedmilitia[PRISONER_OFFICER]), + -turnedmilitia[PRISONER_REGULAR] - (turnedmilitia[PRISONER_ELITE] + turnedmilitia[PRISONER_OFFICER]), + -(turnedmilitia[PRISONER_ELITE] + turnedmilitia[PRISONER_OFFICER]) ); + } + // add these guys to the local garrison as green militias StrategicAddMilitiaToSector( sMapX, sMapY, GREEN_MILITIA, turnedmilitia[PRISONER_ADMIN] ); StrategicAddMilitiaToSector( sMapX, sMapY, REGULAR_MILITIA, turnedmilitia[PRISONER_REGULAR] ); @@ -18689,11 +18706,24 @@ BOOLEAN CanCharacterTrainMilitiaWithErrorReport( SOLDIERTYPE *pSoldier ) if ( !GetVolunteerPool() ) { - swprintf( sString, L"There are no volunteers for militia left!" ); + swprintf( sString, szSMilitiaResourceText[4] ); DoScreenIndependantMessageBox( sString, MSG_BOX_FLAG_OK, NULL ); return (FALSE); } + if ( gGameExternalOptions.fMilitiaResources && !gGameExternalOptions.fMilitiaUseSectorInventory ) + { + FLOAT val_gun, val_armour, val_misc; + GetResources( val_gun, val_armour, val_misc ); + + if ( val_gun <= 1.0f ) + { + swprintf( sString, szSMilitiaResourceText[5] ); + DoScreenIndependantMessageBox( sString, MSG_BOX_FLAG_OK, NULL ); + return (FALSE); + } + } + if ( 100 <= GetMobileMilitiaQuota( TRUE ) ) return ( FALSE ); diff --git a/Strategic/Map Screen Interface Map Inventory.cpp b/Strategic/Map Screen Interface Map Inventory.cpp index e0db1723..3f0c244c 100644 --- a/Strategic/Map Screen Interface Map Inventory.cpp +++ b/Strategic/Map Screen Interface Map Inventory.cpp @@ -33,6 +33,7 @@ #include "Soldier macros.h" #include "rt time defines.h" #include "Encyclopedia_new.h" //Moa: item visibility + #include "Town Militia.h" // added by Flugente #endif #include "ShopKeeper Interface.h" @@ -520,15 +521,11 @@ void BlitInventoryPoolSlotGraphics( void ) void RenderItemsForCurrentPageOfInventoryPool( void ) { - INT32 iCounter = 0; - // go through list of items on this page and place graphics to screen - for( iCounter = 0; iCounter < MAP_INVENTORY_POOL_SLOT_COUNT ; iCounter++ ) + for ( INT32 iCounter = 0; iCounter < MAP_INVENTORY_POOL_SLOT_COUNT; ++iCounter ) { RenderItemInPoolSlot( iCounter, ( iCurrentInventoryPoolPage * MAP_INVENTORY_POOL_SLOT_COUNT ) ); } - - return; } BOOLEAN RenderItemInPoolSlot( INT32 iCurrentSlot, INT32 iFirstSlotOnPage ) @@ -565,7 +562,6 @@ BOOLEAN RenderItemInPoolSlot( INT32 iCurrentSlot, INT32 iFirstSlotOnPage ) sCenX = sX + ( abs( MAP_INVEN_SPACE_BTWN_SLOTS - usWidth ) / 2 ) - pTrav->sOffsetX; sCenY = sY + ( abs( MAP_INVEN_SLOT_HEIGHT - 5 - usHeight ) / 2 ) - pTrav->sOffsetY; - if( fMapInventoryItemCompatable[ iCurrentSlot ] || gfMapInventoryItemToZoom[ iCurrentSlot ] ) { fOutLine = TRUE; @@ -617,7 +613,6 @@ BOOLEAN RenderItemInPoolSlot( INT32 iCurrentSlot, INT32 iFirstSlotOnPage ) SetFontDestBuffer( FRAME_BUFFER, 0,0, SCREEN_WIDTH, SCREEN_HEIGHT, FALSE ); - if( pInventoryPoolList[ iCurrentSlot + iFirstSlotOnPage ].object.exists() == false ) { return ( FALSE ); @@ -630,7 +625,6 @@ BOOLEAN RenderItemInPoolSlot( INT32 iCurrentSlot, INT32 iFirstSlotOnPage ) ( INT16 )( ITEMDESC_ITEM_STATUS_INV_POOL_OFFSET_Y + MAP_INVENTORY_POOL_SLOT_START_Y + ( ( MAP_INVEN_SLOT_HEIGHT ) * ( iCurrentSlot % ( MAP_INV_SLOT_COLS ) ) ) ) , ITEMDESC_ITEM_STATUS_WIDTH_INV_POOL, ITEMDESC_ITEM_STATUS_HEIGHT_INV_POOL, Get16BPPColor( DESC_STATUS_BAR ), Get16BPPColor( DESC_STATUS_BAR_SHADOW ), TRUE, guiSAVEBUFFER ); - // // if the item is not reachable, or if the selected merc is not in the current sector // @@ -682,7 +676,6 @@ BOOLEAN RenderItemInPoolSlot( INT32 iCurrentSlot, INT32 iFirstSlotOnPage ) } // the name - wcscpy( sString, ShortItemNames[ pInventoryPoolList[ iCurrentSlot + iFirstSlotOnPage ].object.usItem ] ); if( StringPixLength( sString, MAP_INVEN_NAME_FONT ) >= ( MAP_INVEN_SLOT_WIDTH ) ) @@ -709,35 +702,71 @@ BOOLEAN RenderItemInPoolSlot( INT32 iCurrentSlot, INT32 iFirstSlotOnPage ) // HEADROCK HAM 5: If ALT is pressed, draw sale price. if( _KeyDown( ALT ) ) { - INT32 iPrice; - if ( _KeyDown( SHIFT ) ) - { - iPrice = SellItem( pInventoryPoolList[ iCurrentSlot + iFirstSlotOnPage ].object, TRUE ); - } - else - { - iPrice = SellItem( pInventoryPoolList[ iCurrentSlot + iFirstSlotOnPage ].object, FALSE ); - } - - swprintf( sString, L"$%d", iPrice ); - UINT32 uiSalePriceFont = (fMapInventoryZoom ? FONT12ARIAL : FONT10ARIAL); + SetFont( uiSalePriceFont ); + UINT16 usFontHeight = GetFontHeight( uiSalePriceFont ); - SetFontDestBuffer( guiSAVEBUFFER, 0,0, SCREEN_WIDTH, SCREEN_HEIGHT, FALSE ); - - SetFont( uiSalePriceFont ); - SetFontForeground( FONT_LTRED ); - SetFontBackground( FONT_BLACK ); + SetFontDestBuffer( guiSAVEBUFFER, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, FALSE ); INT16 sOffsetX = (fMapInventoryZoom ? 12 : 10); INT16 sOffsetY = (fMapInventoryZoom ? 5 : 3); - sX = (INT16)( sOffsetX + MAP_INVENTORY_POOL_SLOT_START_X + ( ( MAP_INVEN_SPACE_BTWN_SLOTS ) * ( iCurrentSlot / MAP_INV_SLOT_COLS ) ) ); - sY = (INT16)( sOffsetY + MAP_INVENTORY_POOL_SLOT_START_Y + ( ( MAP_INVEN_SLOT_HEIGHT ) * ( iCurrentSlot % MAP_INV_SLOT_COLS ) ) ); + sX = (INT16)(sOffsetX + MAP_INVENTORY_POOL_SLOT_START_X + ((MAP_INVEN_SPACE_BTWN_SLOTS)* (iCurrentSlot / MAP_INV_SLOT_COLS))); + sY = (INT16)(sOffsetY + MAP_INVENTORY_POOL_SLOT_START_Y + ((MAP_INVEN_SLOT_HEIGHT)* (iCurrentSlot % MAP_INV_SLOT_COLS))); - mprintf( sX, sY, sString ); + if ( gGameExternalOptions.fSellAll ) + { + SetFontForeground( FONT_LTRED ); + SetFontBackground( FONT_BLACK ); + INT32 iPrice = SellItem( pInventoryPoolList[iCurrentSlot + iFirstSlotOnPage].object, _KeyDown( SHIFT ) ); + + swprintf( sString, L"$%d", iPrice ); + + mprintf( sX, sY, sString ); + sY += usFontHeight; + } + + if ( gGameExternalOptions.fMilitiaResources && !gGameExternalOptions.fMilitiaUseSectorInventory ) + { + FLOAT dvalue_Gun = 0; + FLOAT dvalue_Armour = 0; + FLOAT dvalue_Misc = 0; + + if ( ConvertItemToResources( pInventoryPoolList[iCurrentSlot + iFirstSlotOnPage].object, _KeyDown( SHIFT ), dvalue_Gun, dvalue_Armour, dvalue_Misc ) ) + { + if ( dvalue_Gun > 0.0001f ) + { + SetFontForeground( FONT_BEIGE ); + SetFontBackground( FONT_BLACK ); + + swprintf( sString, L"%5.2f", dvalue_Gun ); + mprintf( sX, sY, sString ); + sY += usFontHeight; + } + + if ( dvalue_Armour > 0.0001f ) + { + SetFontForeground( FONT_LTKHAKI ); + SetFontBackground( FONT_BLACK ); + + swprintf( sString, L"%5.2f", dvalue_Armour ); + mprintf( sX, sY, sString ); + sY += usFontHeight; + } + + if ( dvalue_Misc > 0.0001f ) + { + SetFontForeground( FONT_LTBLUE ); + SetFontBackground( FONT_BLACK ); + + swprintf( sString, L"%5.2f", dvalue_Misc ); + mprintf( sX, sY, sString ); + sY += usFontHeight; + } + } + } } SetFontDestBuffer( FRAME_BUFFER, 0,0, SCREEN_WIDTH, SCREEN_HEIGHT, FALSE ); @@ -2284,7 +2313,6 @@ void BeginInventoryPoolPtr( OBJECTTYPE *pInventorySlot ) { BOOLEAN fOk = FALSE; BOOLEAN fShift = FALSE; - BOOLEAN fSELLALL = gGameExternalOptions.fSellAll; // If not null return if ( gpItemPointer != NULL ) @@ -2425,24 +2453,67 @@ void BeginInventoryPoolPtr( OBJECTTYPE *pInventorySlot ) if ( fShowMapInventoryPool ) HandleButtonStatesWhileMapInventoryActive(); } - else if ( _KeyDown ( ALT ) && fSELLALL)//Sell Item + // Flugente: convert gear to resources + else if ( _KeyDown( ALT ) && _KeyDown( SHIFT ) && gGameExternalOptions.fMilitiaResources && !gGameExternalOptions.fMilitiaUseSectorInventory ) + { + FLOAT dvalue_Gun = 0; + FLOAT dvalue_Armour = 0; + FLOAT dvalue_Misc = 0; + + UINT16 usItem = gItemPointer.usItem; + + if ( ConvertItemToResources( gItemPointer, TRUE, dvalue_Gun, dvalue_Armour, dvalue_Misc ) ) + { + AddResources( dvalue_Gun, dvalue_Armour, dvalue_Misc ); + + dvalue_Gun = dvalue_Armour = dvalue_Misc = 0; + + PlayJA2Sample( COMPUTER_BEEP2_IN, RATE_11025, 15, 1, MIDDLEPAN ); + gpItemPointer = NULL; + fMapInventoryItem = FALSE; + + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szSMilitiaResourceText[0], Item[usItem].szItemName ); + } + + if ( _KeyDown( 89 ) ) + { + for ( UINT32 iNumber = 0; iNumber < pInventoryPoolList.size( ); ++iNumber ) + { + if ( pInventoryPoolList[iNumber].object.usItem == usItem && pInventoryPoolList[iNumber].usFlags & WORLD_ITEM_REACHABLE ) + { + if ( ConvertItemToResources( pInventoryPoolList[iNumber].object, TRUE, dvalue_Gun, dvalue_Armour, dvalue_Misc ) ) + { + AddResources( dvalue_Gun, dvalue_Armour, dvalue_Misc ); + + dvalue_Gun = dvalue_Armour = dvalue_Misc = 0; + + DeleteObj( &pInventoryPoolList[iNumber].object ); + } + } + } + } + + if ( fShowMapInventoryPool ) + HandleButtonStatesWhileMapInventoryActive( ); + } + else if ( _KeyDown( ALT ) && gGameExternalOptions.fSellAll )//Sell Item { // HEADROCK HAM 5: Added argument INT32 iPrice = SellItem( gItemPointer, TRUE ); - PlayJA2Sample( COMPUTER_BEEP2_IN, RATE_11025, 15, 1, MIDDLEPAN ); + PlayJA2Sample( COMPUTER_BEEP2_IN, RATE_11025, 15, 1, MIDDLEPAN ); gpItemPointer = NULL; fMapInventoryItem = FALSE; - if ( _KeyDown ( 89 )) //Lalien: sell all items of this type on Alt+Y + if ( _KeyDown( 89 ) ) //Lalien: sell all items of this type on Alt+Y { - for( UINT32 iNumber = 0 ; iNumber < pInventoryPoolList.size() ; ++iNumber) + for ( UINT32 iNumber = 0; iNumber < pInventoryPoolList.size( ); ++iNumber ) { // WANNE: Fix by Headrock //if ( pInventoryPoolList[ iNumber ].object.usItem == gItemPointer.usItem ) - if ( pInventoryPoolList[ iNumber ].object.usItem == gItemPointer.usItem && pInventoryPoolList[ iNumber ].usFlags & WORLD_ITEM_REACHABLE) + if ( pInventoryPoolList[iNumber].object.usItem == gItemPointer.usItem && pInventoryPoolList[iNumber].usFlags & WORLD_ITEM_REACHABLE ) { // HEADROCK HAM 5: Added argument - iPrice += SellItem( pInventoryPoolList[ iNumber ].object, TRUE ); - DeleteObj( &pInventoryPoolList [ iNumber ].object ); + iPrice += SellItem( pInventoryPoolList[iNumber].object, TRUE ); + DeleteObj( &pInventoryPoolList[iNumber].object ); } } } @@ -2453,7 +2524,7 @@ void BeginInventoryPoolPtr( OBJECTTYPE *pInventorySlot ) // iPrice = 1; //} - if ( _KeyDown ( 89 )) //Lalien: sell all items of this type on Alt+Y + if ( _KeyDown( 89 ) ) //Lalien: sell all items of this type on Alt+Y { ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, New113Message[MSG113_SOLD_ALL] ); } @@ -2462,13 +2533,13 @@ void BeginInventoryPoolPtr( OBJECTTYPE *pInventorySlot ) } // HEADROCK HAM 5: No transaction if no money. - if (iPrice > 0) + if ( iPrice > 0 ) { - AddTransactionToPlayersBook( SOLD_ITEMS, 0, GetWorldTotalMin(), iPrice ); + AddTransactionToPlayersBook( SOLD_ITEMS, 0, GetWorldTotalMin( ), iPrice ); } if ( fShowMapInventoryPool ) - HandleButtonStatesWhileMapInventoryActive(); + HandleButtonStatesWhileMapInventoryActive( ); } else { diff --git a/Strategic/Map Screen Interface Map.cpp b/Strategic/Map Screen Interface Map.cpp index 769634fd..dca9c053 100644 --- a/Strategic/Map Screen Interface Map.cpp +++ b/Strategic/Map Screen Interface Map.cpp @@ -46,6 +46,7 @@ #include "Auto Resolve.h" #include "ASD.h" // added by Flugente #include "MilitiaIndividual.h" // added by Flugente + #include "Map Screen Interface Map Inventory.h" // added by Flugente #endif #include "Quests.h" @@ -7818,22 +7819,90 @@ void DisplayMilitiaGroupBox() // if we play with a limited militia pool, show us how many we have if ( fShowMilitia && gGameExternalOptions.fMilitiaVolunteerPool ) { - CHAR16 sVolunteerString[200]; - SetFont( FONT12ARIAL ); - INT32 volunteers = GetVolunteerPool(); + INT32 x = MapScreenRect.iLeft + 20; + INT32 y = MapScreenRect.iBottom - 10; - if ( volunteers >= 2 * gGameExternalOptions.iTrainingSquadSize ) - SetFontForeground( FONT_FCOLOR_GREEN ); - else if ( volunteers >= gGameExternalOptions.iTrainingSquadSize ) - SetFontForeground( FONT_FCOLOR_YELLOW ); - else - SetFontForeground( FONT_FCOLOR_RED ); + if ( gGameExternalOptions.fMilitiaVolunteerPool ) + { + CHAR16 sString[200]; - // header - swprintf( sVolunteerString, szMilitiaStrategicMovementText[8], volunteers, CalcHourlyVolunteerGain( ) ); - mprintf( MapScreenRect.iLeft + 20, MapScreenRect.iBottom - 10, sVolunteerString ); + INT32 volunteers = GetVolunteerPool(); + + if ( volunteers >= 2 * gGameExternalOptions.iTrainingSquadSize ) + SetFontForeground( FONT_FCOLOR_GREEN ); + else if ( volunteers >= gGameExternalOptions.iTrainingSquadSize ) + SetFontForeground( FONT_FCOLOR_YELLOW ); + else + SetFontForeground( FONT_FCOLOR_RED ); + + swprintf( sString, szMilitiaStrategicMovementText[8], volunteers, CalcHourlyVolunteerGain( ) ); + mprintf( x, y, sString ); + + x += StringPixLength( sString, FONT12ARIAL ); + y -= 10; + } + + if ( gGameExternalOptions.fMilitiaResources && !gGameExternalOptions.fMilitiaUseSectorInventory ) + { + x = MapScreenRect.iLeft + 20; + + CHAR16 sString[200]; + + FLOAT val_gun, val_armour, val_misc; + GetResources( val_gun, val_armour, val_misc ); + + SetFontForeground( FONT_BEIGE ); + swprintf( sString, szSMilitiaResourceText[1] ); + mprintf( x, y, sString ); + x += 5 + StringPixLength( sString, FONT12ARIAL ); + + if ( val_gun > 20.0 ) + SetFontForeground( FONT_FCOLOR_GREEN ); + else if ( val_gun > 10.0 ) + SetFontForeground( FONT_FCOLOR_YELLOW ); + else + SetFontForeground( FONT_FCOLOR_RED ); + + swprintf( sString, L"%5.2f", val_gun ); + mprintf( x, y, sString ); + x += 5 + StringPixLength( sString, FONT12ARIAL ); + + SetFontForeground( FONT_LTKHAKI ); + swprintf( sString, szSMilitiaResourceText[2] ); + mprintf( x, y, sString ); + x += 5 + StringPixLength( sString, FONT12ARIAL ); + + if ( val_armour > 20.0 ) + SetFontForeground( FONT_FCOLOR_GREEN ); + else if ( val_armour > 10.0 ) + SetFontForeground( FONT_FCOLOR_YELLOW ); + else + SetFontForeground( FONT_FCOLOR_RED ); + + swprintf( sString, L"%5.2f", val_armour ); + mprintf( x, y, sString ); + x += 5 + StringPixLength( sString, FONT12ARIAL ); + + SetFontForeground( FONT_LTBLUE ); + swprintf( sString, szSMilitiaResourceText[3] ); + mprintf( x, y, sString ); + x += 5 + StringPixLength( sString, FONT12ARIAL ); + + if ( val_misc > 20.0 ) + SetFontForeground( FONT_FCOLOR_GREEN ); + else if ( val_misc > 10.0 ) + SetFontForeground( FONT_FCOLOR_YELLOW ); + else + SetFontForeground( FONT_FCOLOR_RED ); + + swprintf( sString, L"%5.2f", val_misc ); + mprintf( x, y, sString ); + x += 5 + StringPixLength( sString, FONT12ARIAL ); + + y -= 10; + } } if ( !gMilitiaGroupBoxCreated ) diff --git a/Strategic/MilitiaSquads.cpp b/Strategic/MilitiaSquads.cpp index 74eb5465..63a6154d 100644 --- a/Strategic/MilitiaSquads.cpp +++ b/Strategic/MilitiaSquads.cpp @@ -198,6 +198,17 @@ void GenerateMilitiaSquad(INT16 sMapX, INT16 sMapY, INT16 sTMapX, INT16 sTMapY, // if we can't train as many militia as we should due to lack of volunteers, the excess training goes into promoting militia UINT8 promotionsfromvolunteers = ubMilitiaToTrain; ubMilitiaToTrain = min( ubMilitiaToTrain, GetVolunteerPool( ) ); + + if ( gGameExternalOptions.fMilitiaResources && !gGameExternalOptions.fMilitiaUseSectorInventory ) + { + FLOAT val_gun, val_armour, val_misc; + GetResources( val_gun, val_armour, val_misc ); + + ubMilitiaToTrain = min( ubMilitiaToTrain, (INT32)val_gun ); + ubMilitiaToTrain = min( ubMilitiaToTrain, (INT32)val_armour ); + ubMilitiaToTrain = min( ubMilitiaToTrain, (INT32)val_misc ); + } + promotionsfromvolunteers -= ubMilitiaToTrain; // HEADROCK HAM 3.4: Composition of new Mobile Militia groups is now dictated by two INI settings controlling @@ -371,11 +382,28 @@ void GenerateMilitiaSquad(INT16 sMapX, INT16 sMapY, INT16 sTMapX, INT16 sTMapY, MoveMilitiaEquipment( sMapX, sMapY, sTMapX, sTMapY, numcreated[ELITE_MILITIA], numcreated[REGULAR_MILITIA], numcreated[GREEN_MILITIA] ); + // we have to remove the resources for trained militia before we do promotions, in order to remove these resource + if ( gGameExternalOptions.fMilitiaResources && !gGameExternalOptions.fMilitiaUseSectorInventory ) + { + // use up resources for new militia + AddResources( -numcreated[GREEN_MILITIA] - numcreated[REGULAR_MILITIA] - numcreated[ELITE_MILITIA], -numcreated[REGULAR_MILITIA] - numcreated[ELITE_MILITIA], -numcreated[ELITE_MILITIA] ); + } + // handle promotions UINT8 promotions = 0; - while ( promotions < promotionstodo + promotionsfromvolunteers && TownMilitiaTrainingPromotion( sTMapX, sTMapY ) ) + UINT8 promotedto = 0; + UINT8 promotedto_regular = 0; + UINT8 promotedto_elite = 0; + while ( promotions < promotionstodo + promotionsfromvolunteers && TownMilitiaTrainingPromotion( sTMapX, sTMapY, promotedto ) ) + { ++promotions; + if ( promotedto == SOLDIER_CLASS_REG_MILITIA ) + ++promotedto_regular; + else + ++promotedto_elite; + } + // SANDRO - merc records (num militia trained) if ( trained > 0 ) { @@ -383,7 +411,7 @@ void GenerateMilitiaSquad(INT16 sMapX, INT16 sMapY, INT16 sTMapX, INT16 sTMapY, // Flugente: substract volunteers AddVolunteers( -trained ); - + // Flugente: create individual militia for ( int i = 0; i < numcreated[GREEN_MILITIA]; ++i ) CreateNewIndividualMilitia( GREEN_MILITIA, MO_ARULCO, SECTOR( sTMapX, sTMapY ) ); @@ -395,6 +423,12 @@ void GenerateMilitiaSquad(INT16 sMapX, INT16 sMapY, INT16 sTMapX, INT16 sTMapY, CreateNewIndividualMilitia( ELITE_MILITIA, MO_ARULCO, SECTOR( sTMapX, sTMapY ) ); } + if ( gGameExternalOptions.fMilitiaResources && !gGameExternalOptions.fMilitiaUseSectorInventory ) + { + // promotion resources + AddResources( - promotedto_regular - promotedto_elite, - promotedto_regular - promotedto_elite, - promotedto_elite ); + } + // This reduces the group back to "maximum" size. It starts by eliminating extra greens, then regulars, then elites. // That produces a group of max size, with only the best troops remaining. while ( NumNonPlayerTeamMembersInSector( sTMapX, sTMapY, MILITIA_TEAM ) > gGameExternalOptions.iMaxMilitiaPerSector ) diff --git a/Strategic/Town Militia.cpp b/Strategic/Town Militia.cpp index 274157ef..65767f06 100644 --- a/Strategic/Town Militia.cpp +++ b/Strategic/Town Militia.cpp @@ -32,6 +32,7 @@ #include "laptop.h" // added by Flugente #include "Game Event Hook.h" // added by Flugente #include "MilitiaIndividual.h" // added by Flugente + #include "Campaign.h" // added by Flugente #endif // HEADROCK HAM 3: include these files so that a militia trainer's Effective Leadership can be determined. Used @@ -116,15 +117,36 @@ void VerifyTownTrainingIsPaidFor( void ); #endif // handle promoting a militia during militia training. return TRUE if militia could be promoted -BOOLEAN TownMilitiaTrainingPromotion( INT16 sMapX, INT16 sMapY ) +BOOLEAN TownMilitiaTrainingPromotion( INT16 sMapX, INT16 sMapY, UINT8& arusPromotedTo ) { INT16 sNeighbourX, sNeighbourY; UINT8 ubTownId = StrategicMap[sMapX + sMapY * MAP_WORLD_X].bNameId; // alrighty, then. We'll have to *promote* guys instead. + // 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; + } + } + // are there any GREEN militia men in the training sector itself? - if ( MilitiaInSectorOfRank( sMapX, sMapY, GREEN_MILITIA ) > 0 ) + if ( fCanPromoteToRegular && MilitiaInSectorOfRank( sMapX, sMapY, GREEN_MILITIA ) > 0 ) { // great! Promote a GREEN militia guy in the training sector to a REGULAR StrategicPromoteMilitiaInSector( sMapX, sMapY, GREEN_MILITIA, 1 ); @@ -134,11 +156,13 @@ BOOLEAN TownMilitiaTrainingPromotion( INT16 sMapX, INT16 sMapY ) if ( sMapX == gWorldSectorX && sMapY == gWorldSectorY ) gfStrategicMilitiaChangesMade = TRUE; + arusPromotedTo = SOLDIER_CLASS_REG_MILITIA; + return TRUE; } else { - if ( ubTownId != BLANK_SECTOR ) + if ( fCanPromoteToRegular && ubTownId != BLANK_SECTOR ) { // dammit! Last chance - try to find other eligible sectors in the same town with a Green guy to be promoted InitFriendlyTownSectorServer( ubTownId, sMapX, sMapY ); @@ -157,6 +181,8 @@ BOOLEAN TownMilitiaTrainingPromotion( INT16 sMapX, INT16 sMapY ) if ( sNeighbourX == gWorldSectorX && sNeighbourY == gWorldSectorY ) gfStrategicMilitiaChangesMade = TRUE; + arusPromotedTo = SOLDIER_CLASS_REG_MILITIA; + return TRUE; } } @@ -165,7 +191,7 @@ BOOLEAN TownMilitiaTrainingPromotion( INT16 sMapX, INT16 sMapY ) // Kaiden: Veteran militia training // This is essentially copy/pasted from above // But the names have been changed to protect the innocent - if ( gGameExternalOptions.gfTrainVeteranMilitia && (GetWorldDay( ) >= gGameExternalOptions.guiTrainVeteranMilitiaDelay) ) + if ( fCanPromoteToElite && gGameExternalOptions.gfTrainVeteranMilitia && (GetWorldDay( ) >= gGameExternalOptions.guiTrainVeteranMilitiaDelay) ) { // are there any REGULAR militia men in the training sector itself? if ( MilitiaInSectorOfRank( sMapX, sMapY, REGULAR_MILITIA ) > 0 ) @@ -178,6 +204,8 @@ BOOLEAN TownMilitiaTrainingPromotion( INT16 sMapX, INT16 sMapY ) if ( sMapX == gWorldSectorX && sMapY == gWorldSectorY ) gfStrategicMilitiaChangesMade = TRUE; + arusPromotedTo = SOLDIER_CLASS_ELITE_MILITIA; + return TRUE; } else @@ -201,6 +229,8 @@ BOOLEAN TownMilitiaTrainingPromotion( INT16 sMapX, INT16 sMapY ) if ( sNeighbourX == gWorldSectorX && sNeighbourY == gWorldSectorY ) gfStrategicMilitiaChangesMade = TRUE; + arusPromotedTo = SOLDIER_CLASS_ELITE_MILITIA; + return TRUE; } } @@ -233,6 +263,17 @@ void TownMilitiaTrainingCompleted( SOLDIERTYPE *pTrainer, INT16 sMapX, INT16 sMa // if we can't train as many militia as we should due to lack of volunteers, the excess training goes into promoting militia UINT8 promotionsfromvolunteers = iTrainingSquadSize; iTrainingSquadSize = min( iTrainingSquadSize, GetVolunteerPool( ) ); + + if ( gGameExternalOptions.fMilitiaResources && !gGameExternalOptions.fMilitiaUseSectorInventory ) + { + FLOAT val_gun, val_armour, val_misc; + GetResources( val_gun, val_armour, val_misc ); + + iTrainingSquadSize = min( iTrainingSquadSize, (INT32)val_gun ); + iTrainingSquadSize = min( iTrainingSquadSize, (INT32)val_armour ); + iTrainingSquadSize = min( iTrainingSquadSize, (INT32)val_misc ); + } + promotionsfromvolunteers -= iTrainingSquadSize; DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Militia1"); @@ -331,11 +372,28 @@ void TownMilitiaTrainingCompleted( SOLDIERTYPE *pTrainer, INT16 sMapX, INT16 sMa } } + // we have to remove the resources for trained militia before we do promotions, in order to remove these resource + if ( gGameExternalOptions.fMilitiaResources && !gGameExternalOptions.fMilitiaUseSectorInventory ) + { + // use up resources for new militia + AddResources( -ubMilitiaTrained, 0, 0 ); + } + // handle promotions UINT8 promotions = 0; - while ( promotions < promotionstodo + promotionsfromvolunteers && TownMilitiaTrainingPromotion( sMapX, sMapY ) ) + UINT8 promotedto = 0; + UINT8 promotedto_regular = 0; + UINT8 promotedto_elite = 0; + while ( promotions < promotionstodo + promotionsfromvolunteers && TownMilitiaTrainingPromotion( sMapX, sMapY, promotedto ) ) + { ++promotions; + if ( promotedto == SOLDIER_CLASS_REG_MILITIA ) + ++promotedto_regular; + else + ++promotedto_elite; + } + if (gfStrategicMilitiaChangesMade) { ResetMilitia(); @@ -362,6 +420,12 @@ void TownMilitiaTrainingCompleted( SOLDIERTYPE *pTrainer, INT16 sMapX, INT16 sMa RecordNumMilitiaTrainedForMercs( sMapX, sMapY, pTrainer->bSectorZ, ubMilitiaTrained, FALSE ); } + if ( gGameExternalOptions.fMilitiaResources && !gGameExternalOptions.fMilitiaUseSectorInventory ) + { + // promotion resources + AddResources( - promotedto_regular - promotedto_elite, - promotedto_regular - promotedto_elite, -promotedto_elite ); + } + // the trainer announces to player that he's finished his assignment. Make his sector flash! AssignmentDone( pTrainer, TRUE, FALSE ); @@ -2551,3 +2615,189 @@ void UpdateVolunteers() { AddVolunteers( CalcHourlyVolunteerGain() ); } + +// Flugente: militia resources +BOOLEAN ConvertItemToResources( OBJECTTYPE& object, BOOLEAN fAll, FLOAT& arValue_Gun, FLOAT& arValue_Armour, FLOAT& arValue_Misc ) +{ + UINT16 usItemType = object.usItem; + UINT8 ubNumberOfObjects = fAll ? object.ubNumberOfObjects : 1; + UINT8 coolness = Item[usItemType].ubCoolness; + UINT8 progress = HighestPlayerProgressPercentage( ); + FLOAT mod_progress = ResourceProgressModifier( progress ); + + if ( Item[usItemType].usItemClass & IC_AMMO ) + { + // different ammo items of the same caliber and ammotype have different coolness. To fix that, we simply always use that of the corresponing crate item. Should it not exist, we use 1. + UINT8 ammocoolness = 1; + + for ( int iCrateLoop = 0; iCrateLoop < gMAXITEMS_READ; ++iCrateLoop ) + { + // Is it the right ammo crate? + if ( Item[iCrateLoop].usItemClass == IC_AMMO && + Magazine[Item[iCrateLoop].ubClassIndex].ubMagType == AMMO_CRATE && // An ammo crate or box + Magazine[Item[iCrateLoop].ubClassIndex].ubCalibre == Magazine[Item[usItemType].ubClassIndex].ubCalibre && //Same caliber + Magazine[Item[iCrateLoop].ubClassIndex].ubAmmoType == Magazine[Item[usItemType].ubClassIndex].ubAmmoType ) // Same ammotype + { + // Found a crate for this ammo. + ammocoolness = Item[iCrateLoop].ubCoolness; + break; + } + } + + UINT32 bullets = 0; + for ( UINT8 ubLoop = 0; ubLoop < object.ubNumberOfObjects; ++ubLoop ) + { + bullets += object[ubLoop]->data.ubShotsLeft; + } + + arValue_Gun += (FLOAT)(gGameExternalOptions.fMilitiaResources_ItemClassMod_Ammo_Bullet * ammocoolness * mod_progress * bullets); + } + else + { + for ( UINT8 ubLoop = 0; ubLoop < object.ubNumberOfObjects; ++ubLoop ) + { + if ( Item[usItemType].usItemClass & IC_GUN ) + { + arValue_Gun += (FLOAT)(gGameExternalOptions.fMilitiaResources_ItemClassMod_Gun * gGameExternalOptions.fMilitiaResources_WeaponMod[Weapon[usItemType].ubWeaponType] * coolness * mod_progress * object[ubLoop]->data.objectStatus / 100.0f); + + // take into account any loaded mag + if ( object[ubLoop]->data.gun.ubGunShotsLeft > 0 ) + { + // different ammo items of the same caliber and ammotype have different coolness. To fix that, we simply always use that of the corresponing crate item. Should it not exist, we use 1. + UINT8 ammocoolness = 1; + + for ( int iCrateLoop = 0; iCrateLoop < gMAXITEMS_READ; ++iCrateLoop ) + { + // Is it the right ammo crate? + if ( Item[iCrateLoop].usItemClass == IC_AMMO && + Magazine[Item[iCrateLoop].ubClassIndex].ubMagType == AMMO_CRATE && // An ammo crate or box + Magazine[Item[iCrateLoop].ubClassIndex].ubCalibre == Magazine[Item[object[ubLoop]->data.gun.usGunAmmoItem].ubClassIndex].ubCalibre && //Same caliber + Magazine[Item[iCrateLoop].ubClassIndex].ubAmmoType == Magazine[Item[object[ubLoop]->data.gun.usGunAmmoItem].ubClassIndex].ubAmmoType ) // Same ammotype + { + // Found a crate for this ammo. + ammocoolness = Item[iCrateLoop].ubCoolness; + break; + } + } + + UINT32 bullets = object[ubLoop]->data.gun.ubGunShotsLeft; + + arValue_Gun += (FLOAT)(gGameExternalOptions.fMilitiaResources_ItemClassMod_Ammo_Bullet * ammocoolness * mod_progress * bullets); + } + } + else if ( Item[usItemType].usItemClass & (IC_BLADE | IC_THROWING_KNIFE | IC_PUNCH | IC_THROWN) ) + { + arValue_Misc += (FLOAT)(gGameExternalOptions.fMilitiaResources_ItemClassMod_Melee * coolness * mod_progress * object[ubLoop]->data.objectStatus / 100.0f); + } + else if ( Item[usItemType].usItemClass & IC_LAUNCHER ) + { + arValue_Misc += (FLOAT)(gGameExternalOptions.fMilitiaResources_ItemClassMod_Gun * coolness * mod_progress * object[ubLoop]->data.objectStatus / 100.0f); + } + else if ( Item[usItemType].usItemClass & (IC_GRENADE) ) + { + arValue_Misc += (FLOAT)(gGameExternalOptions.fMilitiaResources_ItemClassMod_Grenade * coolness * mod_progress * object[ubLoop]->data.objectStatus / 100.0f); + } + else if ( Item[usItemType].usItemClass & (IC_BOMB) ) + { + arValue_Misc += (FLOAT)(gGameExternalOptions.fMilitiaResources_ItemClassMod_Bomb * coolness * mod_progress * object[ubLoop]->data.objectStatus / 100.0f); + } + else if ( Item[usItemType].usItemClass & IC_ARMOUR ) + { + arValue_Armour += (FLOAT)(gGameExternalOptions.fMilitiaResources_ItemClassMod_Armour * coolness * mod_progress * object[ubLoop]->data.objectStatus / 100.0f); + } + else if ( Item[usItemType].usItemClass & IC_FACE ) + { + arValue_Armour += (FLOAT)(gGameExternalOptions.fMilitiaResources_ItemClassMod_Face * coolness * mod_progress * object[ubLoop]->data.objectStatus / 100.0f); + } + else if ( Item[usItemType].usItemClass & IC_LBEGEAR ) + { + arValue_Armour += (FLOAT)(gGameExternalOptions.fMilitiaResources_ItemClassMod_LBE * coolness * mod_progress * object[ubLoop]->data.objectStatus / 100.0f); + } + else if ( Item[usItemType].usItemClass & IC_MISC ) + { + UINT32 attachmentClass = Item[usItemType].attachmentclass; + + if ( attachmentClass & ( AC_MUZZLE | AC_SIGHT | AC_MAGWELL | AC_INTERNAL | AC_EXTERNAL | AC_EXTENDER | AC_IRONSIGHT | AC_FEEDER ) ) + { + arValue_Gun += (FLOAT)(gGameExternalOptions.fMilitiaResources_ItemClassMod_Attachment_Low * coolness * mod_progress * object[ubLoop]->data.objectStatus / 100.0f); + } + if ( attachmentClass & ( AC_FOREGRIP | AC_STOCK | AC_LASER) ) + { + arValue_Gun += (FLOAT)(gGameExternalOptions.fMilitiaResources_ItemClassMod_Attachment_Medium * coolness * mod_progress * object[ubLoop]->data.objectStatus / 100.0f); + } + if ( attachmentClass & (AC_BIPOD | AC_SCOPE | AC_UNDERBARREL ) ) + { + arValue_Gun += (FLOAT)(gGameExternalOptions.fMilitiaResources_ItemClassMod_Attachment_High * coolness * mod_progress * object[ubLoop]->data.objectStatus / 100.0f); + } + else if ( attachmentClass & (AC_SLING | AC_MODPOUCH ) ) + { + arValue_Armour += (FLOAT)(gGameExternalOptions.fMilitiaResources_ItemClassMod_Attachment_Low * coolness * mod_progress * object[ubLoop]->data.objectStatus / 100.0f); + } + else if ( attachmentClass & (AC_HELMET | AC_VEST | AC_PANTS ) ) + { + arValue_Armour += (FLOAT)(gGameExternalOptions.fMilitiaResources_ItemClassMod_Attachment_Medium * coolness * mod_progress * object[ubLoop]->data.objectStatus / 100.0f); + } + else if ( attachmentClass & ( AC_DETONATOR | AC_BATTERY | AC_REMOTEDET | AC_DEFUSE) ) + { + arValue_Misc += (FLOAT)(gGameExternalOptions.fMilitiaResources_ItemClassMod_Attachment_Low * coolness * mod_progress * object[ubLoop]->data.objectStatus / 100.0f); + } + else if ( attachmentClass & (AC_GRENADE | AC_RIFLEGRENADE | AC_BAYONET) ) + { + arValue_Misc += (FLOAT)(gGameExternalOptions.fMilitiaResources_ItemClassMod_Attachment_Medium * coolness * mod_progress * object[ubLoop]->data.objectStatus / 100.0f); + } + else if ( attachmentClass & ( AC_ROCKET ) ) + { + arValue_Misc += (FLOAT)(gGameExternalOptions.fMilitiaResources_ItemClassMod_Attachment_High * coolness * mod_progress * object[ubLoop]->data.objectStatus / 100.0f); + } + } + else + continue; + + for ( attachmentList::iterator iter = object[ubLoop]->attachments.begin( ); iter != object[ubLoop]->attachments.end( ); ++iter ) + { + if ( iter->exists( ) ) + { + ConvertItemToResources( *iter, TRUE, arValue_Gun, arValue_Armour, arValue_Misc ); + } + } + } + } + + return (arValue_Gun + arValue_Armour + arValue_Misc > 0.0001f); +} + +void AddResources( FLOAT aValue_Gun, FLOAT aValue_Armour, FLOAT aValue_Misc ) +{ + LaptopSaveInfo.dMilitiaGunPool = max( 0, LaptopSaveInfo.dMilitiaGunPool + aValue_Gun ); + LaptopSaveInfo.dMilitiaArmourPool = max( 0, LaptopSaveInfo.dMilitiaArmourPool + aValue_Armour ); + LaptopSaveInfo.dMilitiaMiscPool = max( 0, LaptopSaveInfo.dMilitiaMiscPool + aValue_Misc ); +} + +void GetResources( FLOAT& arValue_Gun, FLOAT& arValue_Armour, FLOAT& arValue_Misc ) +{ + arValue_Gun = LaptopSaveInfo.dMilitiaGunPool; + arValue_Armour = LaptopSaveInfo.dMilitiaArmourPool; + arValue_Misc = LaptopSaveInfo.dMilitiaMiscPool; +} + +FLOAT ResourceProgressModifier( UINT8 aProgress ) +{ + // value need to be between 1 and 100 + aProgress = max( 1, min( 100, aProgress ) ); + + return (FLOAT)(gGameExternalOptions.fMilitiaResources_ProgressFactor / aProgress); +} + +void DevalueResources( UINT8 aOldProgress, UINT8 aNewProgress ) +{ + // both progress values need to be between 1 and 100 + aOldProgress = max( 1, min( 100, aOldProgress ) ); + aNewProgress = max( 1, min( 100, aNewProgress ) ); + + // modifier is new progress value / old value + FLOAT modifier = ResourceProgressModifier( aNewProgress ) / ResourceProgressModifier( aOldProgress ); + + LaptopSaveInfo.dMilitiaGunPool *= modifier; + LaptopSaveInfo.dMilitiaArmourPool *= modifier; + LaptopSaveInfo.dMilitiaMiscPool *= modifier; +} diff --git a/Strategic/Town Militia.h b/Strategic/Town Militia.h index b67269a1..912c042f 100644 --- a/Strategic/Town Militia.h +++ b/Strategic/Town Militia.h @@ -21,7 +21,7 @@ // handle promoting a militia during militia training. return TRUE if militia could be promoted -BOOLEAN TownMilitiaTrainingPromotion( INT16 sMapX, INT16 sMapY ); +BOOLEAN TownMilitiaTrainingPromotion( INT16 sMapX, INT16 sMapY, UINT8& arusPromotedTo ); // this handles what happens when a new militia unit is finishes getting trained void TownMilitiaTrainingCompleted( SOLDIERTYPE *pTrainer, INT16 sMapX, INT16 sMapY ); @@ -126,4 +126,11 @@ FLOAT CalcHourlyVolunteerGain(); // every hour, controlled sectors add to our volunteer pool void UpdateVolunteers(); +// Flugente: militia resources +BOOLEAN ConvertItemToResources( OBJECTTYPE& object, BOOLEAN fAll, FLOAT& arValue_Gun, FLOAT& arValue_Armour, FLOAT& arValue_Misc ); +void AddResources( FLOAT aValue_Gun, FLOAT aValue_Armour, FLOAT aValue_Misc ); +void GetResources( FLOAT& arValue_Gun, FLOAT& arValue_Armour, FLOAT& arValue_Misc ); +FLOAT ResourceProgressModifier( UINT8 aProgress ); +void DevalueResources(UINT8 aOldProgress, UINT8 aNewProgress); + #endif \ No newline at end of file diff --git a/Tactical/Campaign.cpp b/Tactical/Campaign.cpp index f30e4838..1f73364e 100644 --- a/Tactical/Campaign.cpp +++ b/Tactical/Campaign.cpp @@ -1719,6 +1719,9 @@ void HourlyProgressUpdate(void) ExecuteStrategicAIAction( NPC_ACTION_GLOBAL_OFFENSIVE_2, 0, 0 ); } + // Flugente: our resources slowly lose their value + DevalueResources( gStrategicStatus.ubHighestProgress, ubCurrentProgress ); + gStrategicStatus.ubHighestProgress = ubCurrentProgress; // debug message diff --git a/Tactical/Weapons.h b/Tactical/Weapons.h index 2b437c12..21524af8 100644 --- a/Tactical/Weapons.h +++ b/Tactical/Weapons.h @@ -98,21 +98,6 @@ enum NUM_WEAPON_CLASSES }; -// exact gun types -enum -{ - NOT_GUN = 0, - GUN_PISTOL, - GUN_M_PISTOL, - GUN_SMG, - GUN_RIFLE, - GUN_SN_RIFLE, - GUN_AS_RIFLE, - GUN_LMG, - GUN_SHOTGUN -}; - - // ARMOUR CLASSES enum { diff --git a/Utils/Text.h b/Utils/Text.h index 36f184f8..3d8967e6 100644 --- a/Utils/Text.h +++ b/Utils/Text.h @@ -2974,6 +2974,9 @@ extern STR16 szWeatherTypeText[]; // Flugente: snakes extern STR16 szSnakeText[]; +// Flugente: militia resources +extern STR16 szSMilitiaResourceText[]; + #define TACTICAL_INVENTORY_DIALOG_NUM 16 #define TACTICAL_COVER_DIALOG_NUM 16 diff --git a/Utils/_ChineseText.cpp b/Utils/_ChineseText.cpp index 7aad79b8..a3b06946 100644 --- a/Utils/_ChineseText.cpp +++ b/Utils/_ChineseText.cpp @@ -10984,7 +10984,7 @@ STR16 szMilitiaStrategicMovementText[] = L"第%d小队", //L"Group %d", L"最终", //L"Final", - L"民兵的志愿者: %d (+%5.3f)", //L"Militia Volunteers: %d (+%5.3f)", + L"Volunteers: %d (+%5.3f)", // TODO.Translate }; STR16 szEnemyHeliText[] = // TODO.Translate @@ -11148,6 +11148,17 @@ STR16 szSnakeText[] = L"%s was attacked by a snake!", }; +STR16 szSMilitiaResourceText[] = +{ + L"Converted %s into resources", + L"Guns: ", + L"Armour: ", + L"Misc: ", + + L"There are no volunteers left for militia!", + L"Not enough resources to train militia!", +}; + // 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 2cc381a4..b5fe0275 100644 --- a/Utils/_DutchText.cpp +++ b/Utils/_DutchText.cpp @@ -11001,7 +11001,7 @@ STR16 szMilitiaStrategicMovementText[] = L"Group %d", L"Final", - L"Militia Volunteers: %d (+%5.3f)", + L"Volunteers: %d (+%5.3f)", }; STR16 szEnemyHeliText[] = // TODO.Translate @@ -11165,4 +11165,15 @@ STR16 szSnakeText[] = L"%s was attacked by a snake!", }; +STR16 szSMilitiaResourceText[] = +{ + L"Converted %s into resources", + L"Guns: ", + L"Armour: ", + L"Misc: ", + + L"There are no volunteers left for militia!", + L"Not enough resources to train militia!", +}; + #endif //DUTCH diff --git a/Utils/_EnglishText.cpp b/Utils/_EnglishText.cpp index cf968aa3..0ed2ddb6 100644 --- a/Utils/_EnglishText.cpp +++ b/Utils/_EnglishText.cpp @@ -10984,7 +10984,7 @@ STR16 szMilitiaStrategicMovementText[] = L"Group %d", L"Final", - L"Militia Volunteers: %d (+%5.3f)", + L"Volunteers: %d (+%5.3f)", }; STR16 szEnemyHeliText[] = @@ -11148,4 +11148,15 @@ STR16 szSnakeText[] = L"%s was attacked by a snake!", }; +STR16 szSMilitiaResourceText[] = +{ + L"Converted %s into resources", + L"Guns: ", + L"Armour: ", + L"Misc: ", + + L"There are no volunteers left for militia!", + L"Not enough resources to train militia!", +}; + #endif //ENGLISH diff --git a/Utils/_FrenchText.cpp b/Utils/_FrenchText.cpp index 6d404301..031948ab 100644 --- a/Utils/_FrenchText.cpp +++ b/Utils/_FrenchText.cpp @@ -10983,7 +10983,7 @@ STR16 szMilitiaStrategicMovementText[] = L"Group %d", L"Final", - L"Militia Volunteers: %d (+%5.3f)", + L"Volunteers: %d (+%5.3f)", }; STR16 szEnemyHeliText[] = // TODO.Translate @@ -11147,4 +11147,15 @@ STR16 szSnakeText[] = L"%s was attacked by a snake!", }; +STR16 szSMilitiaResourceText[] = +{ + L"Converted %s into resources", + L"Guns: ", + L"Armour: ", + L"Misc: ", + + L"There are no volunteers left for militia!", + L"Not enough resources to train militia!", +}; + #endif //FRENCH diff --git a/Utils/_GermanText.cpp b/Utils/_GermanText.cpp index cbb5bf30..cc20bd6a 100644 --- a/Utils/_GermanText.cpp +++ b/Utils/_GermanText.cpp @@ -10813,7 +10813,7 @@ STR16 szMilitiaStrategicMovementText[] = L"Group %d", L"Final", - L"Militia Volunteers: %d (+%5.3f)", + L"Volunteers: %d (+%5.3f)", }; STR16 szEnemyHeliText[] = // TODO.Translate @@ -10977,4 +10977,15 @@ STR16 szSnakeText[] = L"%s was attacked by a snake!", }; +STR16 szSMilitiaResourceText[] = +{ + L"Converted %s into resources", + L"Guns: ", + L"Armour: ", + L"Misc: ", + + L"There are no volunteers left for militia!", + L"Not enough resources to train militia!", +}; + #endif //GERMAN diff --git a/Utils/_ItalianText.cpp b/Utils/_ItalianText.cpp index da22144c..b4254840 100644 --- a/Utils/_ItalianText.cpp +++ b/Utils/_ItalianText.cpp @@ -10992,7 +10992,7 @@ STR16 szMilitiaStrategicMovementText[] = L"Group %d", L"Final", - L"Militia Volunteers: %d (+%5.3f)", + L"Volunteers: %d (+%5.3f)", }; STR16 szEnemyHeliText[] = // TODO.Translate @@ -11156,4 +11156,15 @@ STR16 szSnakeText[] = L"%s was attacked by a snake!", }; +STR16 szSMilitiaResourceText[] = +{ + L"Converted %s into resources", + L"Guns: ", + L"Armour: ", + L"Misc: ", + + L"There are no volunteers left for militia!", + L"Not enough resources to train militia!", +}; + #endif //ITALIAN diff --git a/Utils/_PolishText.cpp b/Utils/_PolishText.cpp index bf68eaa3..bef1a78c 100644 --- a/Utils/_PolishText.cpp +++ b/Utils/_PolishText.cpp @@ -11005,7 +11005,7 @@ STR16 szMilitiaStrategicMovementText[] = L"Group %d", L"Final", - L"Militia Volunteers: %d (+%5.3f)", + L"Volunteers: %d (+%5.3f)", }; STR16 szEnemyHeliText[] = // TODO.Translate @@ -11169,4 +11169,15 @@ STR16 szSnakeText[] = L"%s was attacked by a snake!", }; +STR16 szSMilitiaResourceText[] = +{ + L"Converted %s into resources", + L"Guns: ", + L"Armour: ", + L"Misc: ", + + L"There are no volunteers left for militia!", + L"Not enough resources to train militia!", +}; + #endif //POLISH diff --git a/Utils/_RussianText.cpp b/Utils/_RussianText.cpp index e31c86dc..f03b4bb2 100644 --- a/Utils/_RussianText.cpp +++ b/Utils/_RussianText.cpp @@ -10984,7 +10984,7 @@ STR16 szMilitiaStrategicMovementText[] = L"Группа %d", L"Final", - L"Ополченцы добровольцы: %d (+%5.3f)", + L"Volunteers: %d (+%5.3f)", // TODO.Translate }; STR16 szEnemyHeliText[] = @@ -11148,4 +11148,15 @@ STR16 szSnakeText[] = L"%s was attacked by a snake!", }; +STR16 szSMilitiaResourceText[] = +{ + L"Converted %s into resources", + L"Guns: ", + L"Armour: ", + L"Misc: ", + + L"There are no volunteers left for militia!", + L"Not enough resources to train militia!", +}; + #endif //RUSSIAN