New feature: militia resources requires the player to convert items to resources to be able to train and promote militia

git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@8271 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
Flugente
2016-07-15 19:33:44 +00:00
parent 5dcfe09a77
commit 7a34e9a154
21 changed files with 711 additions and 105 deletions
+31 -1
View File
@@ -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 );
+112 -41
View File
@@ -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
{
+81 -12
View File
@@ -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 )
+36 -2
View File
@@ -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 )
+255 -5
View File
@@ -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;
}
+8 -1
View File
@@ -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