New feature: individual militia creates small militia profiles that track a militia's history and allow it to be recreated, thereby maintaining the illusion of persistent militia.

Requires GameDir >= r2316.

For more info, see http://thepit.ja-galaxy-forum.com/index.php?t=tree&th=23044&goto=345324&#msg_345324

git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@8202 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
Flugente
2016-05-06 14:51:24 +00:00
parent 67927ed723
commit 9f52c940a8
75 changed files with 6740 additions and 703 deletions
+15 -6
View File
@@ -901,12 +901,12 @@ void LoadGameExternalOptions()
gGameExternalOptions.iMilitiaCostModifier = iniReader.ReadInteger("Financial Settings","MILITIA_COST_MULTIPLIER_MOBILE",3, 1, 10);
// HEADROCK HAM 3.6: Daily upkeep costs for militia
gGameExternalOptions.usDailyCostTownGreen = iniReader.ReadInteger("Financial Settings","DAILY_MILITIA_UPKEEP_TOWN_GREEN", 0, 0, 10000);
gGameExternalOptions.usDailyCostTownRegular = iniReader.ReadInteger("Financial Settings","DAILY_MILITIA_UPKEEP_TOWN_REGULAR", 0, 0, 10000);
gGameExternalOptions.usDailyCostTownElite = iniReader.ReadInteger("Financial Settings","DAILY_MILITIA_UPKEEP_TOWN_ELITE", 0, 0, 10000);
gGameExternalOptions.usDailyCostMobileGreen = iniReader.ReadInteger("Financial Settings","DAILY_MILITIA_UPKEEP_MOBILE_GREEN", 0, 0, 10000);
gGameExternalOptions.usDailyCostMobileRegular = iniReader.ReadInteger("Financial Settings","DAILY_MILITIA_UPKEEP_MOBILE_REGULAR", 0, 0, 10000);
gGameExternalOptions.usDailyCostMobileElite = iniReader.ReadInteger("Financial Settings","DAILY_MILITIA_UPKEEP_MOBILE_ELITE", 0, 0, 10000);
gGameExternalOptions.usDailyCostTown[GREEN_MILITIA] = iniReader.ReadInteger( "Financial Settings", "DAILY_MILITIA_UPKEEP_TOWN_GREEN", 0, 0, 10000 );
gGameExternalOptions.usDailyCostTown[REGULAR_MILITIA] = iniReader.ReadInteger( "Financial Settings", "DAILY_MILITIA_UPKEEP_TOWN_REGULAR", 0, 0, 10000 );
gGameExternalOptions.usDailyCostTown[ELITE_MILITIA] = iniReader.ReadInteger( "Financial Settings", "DAILY_MILITIA_UPKEEP_TOWN_ELITE", 0, 0, 10000 );
gGameExternalOptions.usDailyCostMobile[GREEN_MILITIA] = iniReader.ReadInteger( "Financial Settings", "DAILY_MILITIA_UPKEEP_MOBILE_GREEN", 0, 0, 10000 );
gGameExternalOptions.usDailyCostMobile[REGULAR_MILITIA] = iniReader.ReadInteger( "Financial Settings", "DAILY_MILITIA_UPKEEP_MOBILE_REGULAR", 0, 0, 10000 );
gGameExternalOptions.usDailyCostMobile[ELITE_MILITIA] = iniReader.ReadInteger( "Financial Settings", "DAILY_MILITIA_UPKEEP_MOBILE_ELITE", 0, 0, 10000 );
// HEADROCK HAM 3.5: Helicopter - Base cost per sector. GREEN = Free airspace, RED = Enemy-controlled airspace.
gGameExternalOptions.usHelicopterBaseCostPerGreenTile = iniReader.ReadInteger("Financial Settings","HELICOPTER_BASE_COST_PER_GREEN_TILE", 100, 0, 60000);
@@ -1533,6 +1533,15 @@ void LoadGameExternalOptions()
gGameExternalOptions.fEnemyGeneralStrategicDecisionSpeedBonus = iniReader.ReadFloat( "Tactical Enemy Role Settings", "ENEMY_GENERALS_STRATEGIC_DECISION_SPEEDBONUS", 0.05f, 0.00f, 0.1f );
gGameExternalOptions.fEnemyGeneralStrategicMovementSpeedBonus = iniReader.ReadFloat( "Tactical Enemy Role Settings", "ENEMY_GENERALS_STRATEGIC_MOVEMENT_SPEEDBONUS", 0.03f, 0.00f, 0.1f );
//################# Individual Militia Settings ##################
// Flugente: individual militia
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 );
//################# Tactical Cover System Settings ##################
+9 -6
View File
@@ -5,6 +5,7 @@
#include "Strategic Status.h"
#include "Morale.h"
#include "GameInitOptionsScreen.h"
#include "Campaign Types.h"
#define GAME_INI_FILE "Ja2.ini"
@@ -1172,12 +1173,8 @@ typedef struct
UINT8 ubMaxMessagesTactical;
// HEADROCK HAM 3.6: Daily upkeep costs for militia
UINT16 usDailyCostTownGreen;
UINT16 usDailyCostTownRegular;
UINT16 usDailyCostTownElite;
UINT16 usDailyCostMobileGreen;
UINT16 usDailyCostMobileRegular;
UINT16 usDailyCostMobileElite;
UINT16 usDailyCostTown[MAX_MILITIA_LEVELS];
UINT16 usDailyCostMobile[MAX_MILITIA_LEVELS];
// HEADROCK HAM 3.6: Non-Combat Bodytypes can't become hostile
BOOLEAN fCanTrueCiviliansBecomeHostile;
@@ -1401,6 +1398,12 @@ typedef struct
FLOAT fEnemyGeneralStrategicDecisionSpeedBonus;
FLOAT fEnemyGeneralStrategicMovementSpeedBonus;
// Flugente: individual militia
BOOLEAN fIndividualMilitia;
UINT16 usIndividualMilitia_PromotionPoints_To_Regular;
UINT16 usIndividualMilitia_PromotionPoints_To_Elite;
BOOLEAN fIndividualMilitia_ManageHealth;
FLOAT dIndividualMilitiaHourlyHealthPercentageGain;
// Sandro: Alternative weapon holding (rifles fired from hip / pistols fired one-handed)
UINT8 ubAllowAlternativeWeaponHolding;
+2 -1
View File
@@ -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 166 // Flugente: individual militia
#define ENEMY_JEEPS 165 // Flugente: enemy jeeps
#define ENEMY_HELICOPTERS 164 // Flugente: enemy helicopters
#define DRUG_SYSTEM_REDONE 163 // Flugente: reworked the drug system
@@ -84,7 +85,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 ENEMY_JEEPS
#define SAVE_GAME_VERSION INDIVIDUAL_MILITIA
//#define RUSSIANGOLD
#ifdef __cplusplus
+6
View File
@@ -1077,6 +1077,12 @@ BOOLEAN LoadExternalGameplayData(STR directoryName)
}
#endif
// Flugente: individual militia
strcpy( fileName, directoryName );
strcat( fileName, INDIVIDUALMILITIAFILENAME );
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String( "LoadExternalGameplayData, fileName = %s", fileName ) );
SGP_THROW_IFFALSE( ReadInMilitiaIndividual( fileName, FALSE ), INDIVIDUALMILITIAFILENAME );
// Flugente: campaign stats
strcpy(fileName, directoryName);
strcat(fileName, CAMPAIGNSTATSEVENTSFILENAME);
+937
View File
@@ -0,0 +1,937 @@
/**
* @file
* @author Flugente (bears-pit.com)
*/
#include "BaseTable.h"
#include "Font.h"
#include "laptop.h"
#include "Cursors.h"
#include "Utilities.h"
#include "vobject.h"
#include "WCheck.h"
#include "line.h"
#include "WordWrap.h"
#include "input.h" // for gfLeftButtonState
#include "insurance.h" // for DisplaySmallColouredLineWithShadow
BaseTable::BaseTable( )
: WidgetBase( ),
mName(L""),
fInit(FALSE),
musHeight(0),
musWidth(0),
musFrameWorkSpace(0),
mActive(TRUE),
mMouseRegionActive(TRUE)
{
}
void
BaseTable::Init( UINT16 sX, UINT16 sY, UINT16 sX_End, UINT16 sY_End )
{
SetX( sX );
SetY( sY );
SetWidth( sX_End - sX );
SetHeight( sY_End - sY );
for ( std::vector<BaseTable*>::iterator it = mRegisteredMembers.begin( ); it != mRegisteredMembers.end( ); ++it )
{
if ( (*it) )
(*it)->Init( sX, sY, sX_End, sY_End );
}
SetInit( TRUE );
}
void
BaseTable::Create( UINT16 sX, UINT16 sY, UINT16 sX_End, UINT16 sY_End )
{
Destroy( );
Init( sX, sY, sX_End, sY_End );
}
void
BaseTable::Destroy( )
{
if ( !IsInit() )
return;
DestroyMouseRegions();
for ( std::vector<BaseTable*>::iterator it = mRegisteredMembers.begin( ); it != mRegisteredMembers.end( ); ++it )
{
if ( (*it) )
(*it)->Destroy( );
}
mRegisteredMembers.clear( );
SetInit(FALSE);
SetRefresh( );
}
void
BaseTable::Display( )
{
if ( !IsInit() )
return;
for ( std::vector<BaseTable*>::iterator it = mRegisteredMembers.begin( ); it != mRegisteredMembers.end( ); ++it )
{
if ( (*it) && (*it)->IsActive() )
(*it)->Display( );
}
}
void
BaseTable::DestroyMouseRegions( )
{
if ( !IsInit( ) )
return;
for ( std::vector<BaseTable*>::iterator it = mRegisteredMembers.begin( ); it != mRegisteredMembers.end( ); ++it )
{
if ( (*it) )
(*it)->DestroyMouseRegions( );
}
}
STR16 cdp_string_func_dummy( UINT32 aNum )
{
return L"nothing found";
}
void cdp_image_func_dummy( UINT32 aNum, UINT32& arImageLib, UINT16& arImage )
{
}
void cdp_statusbar_func_dummy( UINT32 aId, UINT16& arCol1, UINT16& arVal1, UINT16& arCol2, UINT16& arVal2, UINT16& arCol3, UINT16& arVal3, UINT16& arCol4, UINT16& arVal4 )
{
}
void
ColumnDataProvider::CalcRequiredLength( )
{
mRequiredLength = 0;
if ( CDP_STRING == GetProviderType() )
{
for ( UINT32 i = 0; i < mNumberOfEntries; ++i )
{
mRequiredLength = max( mRequiredLength, 7 * wcslen( GetString( i ) ) );
}
}
else if ( CDP_IMAGE == GetProviderType() )
{
for ( UINT32 i = 0; i < mNumberOfEntries; ++i )
{
// TODO...
mRequiredLength = max( mRequiredLength, 40 );
}
}
else if ( CDP_STATUSBAR == GetProviderType( ) )
{
mRequiredLength = 4;
}
}
extern void callbackmilitialist( INT32 usId );
extern void callbackmilitiadetail( INT32 usId );
void
ColumnDataProvider::RegionClickCallBack( MOUSE_REGION * pRegion, INT32 iReason )
{
if ( iReason & MSYS_CALLBACK_REASON_INIT )
{
}
else if ( iReason & MSYS_CALLBACK_REASON_LBUTTON_UP )
{
//gfScrollBoxIsScrolling = FALSE;
//gHelpScreen.iLastMouseClickY = -1;
}
else if ( iReason & MSYS_CALLBACK_REASON_LBUTTON_DWN )
{
CDP_CALLBACKTYPE chosenentry = (CDP_CALLBACKTYPE)(pRegion->UserData[0]);
// do stuff
switch ( chosenentry )
{
case CDP_MILITIA_LIST:
callbackmilitialist( pRegion->UserData[1] );
break;
case CDP_MILITIADETAIL:
callbackmilitiadetail( pRegion->UserData[1] );
break;
case CDP_DEFAULT:
default:
break;
}
}
else if ( iReason & MSYS_CALLBACK_REASON_RBUTTON_UP )
{
}
}
void
ColumnDataProvider::DestroyMouseRegions( )
{
for ( int i = 0; i < COLUMNDATAPROVIDER_MOUSEREGIONS; ++i )
{
if ( mMouseRegion_Defined[i] )
{
MSYS_RemoveRegion( &mMouseRegion[i] );
mMouseRegion_Defined[i] = FALSE;
}
}
}
// Flugente: this unused page will now be a testbed for the BaseTable development
#define TESTTABLE_FONT_MED FONT12ARIAL
#define TESTTABLE_OFFSET_ROW 20
#define TESTTABLE_FONT_COLOR_REGULAR 2
////////////// TestPanel///////////////////////////////////////
TestPanel::TestPanel( )
: BaseTable( )
{
SetFrameWorkSpace( 4 );
}
void
TestPanel::Display( )
{
if ( !IsInit( ) )
return;
SetColorLine( Get16BPPColor( FROMRGB( 128, 128, 128 ) ) );
SetColorLineShadow( Get16BPPColor( FROMRGB( 255, 255, 255 ) ) );
SetColorMarked(Get16BPPColor( FROMRGB( 200, 169, 87 ) ));
SetColorHighLight(Get16BPPColor( FROMRGB( 235, 222, 171 )) );
//Display the background
ColorFillVideoSurfaceArea( FRAME_BUFFER, GetX( ), GetY( ), GetX( ) + GetWidth( ), GetY( ) + GetHeight( ), GetColorMarked( ) );
// framework
// top
Display2Line2ShadowHorizontal( GetX( ), GetY( ), GetX( ) + GetWidth( ), GetColorLine( ), GetColorLineShadow( ) );
// bottom
Display2Line2ShadowHorizontal( GetX( ), GetY( ) + GetHeight( ) - GetFrameWorkSpace( ) * 3 / 2, GetX( ) + GetWidth( ), GetColorLineShadow( ), GetColorLine( ) );
// left
Display2Line2ShadowVertical( GetX( ), GetY( ) + GetFrameWorkSpace( )/2, GetY( ) + GetHeight( ) - 5, GetColorLine( ), GetColorLineShadow( ) );
// right
Display2Line2ShadowVertical( GetX( ) + GetWidth( ) - GetFrameWorkSpace( ) * 3 / 2, GetY( ) + GetFrameWorkSpace( ) / 2, GetY( ) + GetHeight( ) - 5, GetColorLineShadow( ), GetColorLine( ) );
BaseTable::Display( );
}
void
TestPanel::SetRefresh( )
{
}
TestPanel gTestPanel3;
////////////////////////// TestPanel /////////////////////////////////////
////////////////////////// TabBox /////////////////////////////////////
TabBox::TabBox( )
: BaseTable( )
{
SetFrameWorkSpace(4);
}
void
TabBox::Init( UINT16 sX, UINT16 sY, UINT16 sX_End, UINT16 sY_End )
{
SetColorLine( Get16BPPColor( FROMRGB( 128, 128, 128 ) ) );
SetColorLineShadow( Get16BPPColor( FROMRGB( 255, 255, 255 ) ) );
SetColorMarked( Get16BPPColor( FROMRGB( 200, 169, 87 ) ) );
SetColorHighLight( Get16BPPColor( FROMRGB( 235, 222, 171 ) ) );
BaseTable::Init( sX, sY, sX_End, sY_End );
}
void
TabBox::Create( UINT16 sX, UINT16 sY, UINT16 sX_End, UINT16 sY_End )
{
Destroy( );
Init( sX, sY, sX_End, sY_End );
UINT16 usPosX = GetX( );
UINT16 panelcnt = 0;
for ( std::vector<TestPanelButtonStruct>::iterator it = mRegisteredTables.begin( ); it != mRegisteredTables.end( ); ++it )
{
if ( !(*it).mMouseRegion_Defined && IsMouseRegionActive() )
{
// determine required width of mouse region
UINT32 textwidth = 7 * wcslen( (*it).mTestPanel->GetName( ) );
MSYS_DefineRegion( &(*it).mMouseRegion, usPosX, GetY( ), usPosX + textwidth, GetY( ) + TESTTABLE_OFFSET_ROW, MSYS_PRIORITY_HIGH,
CURSOR_WWW,
RegionCallBackWrapper( (void*) this, CALLBACK_REGION_MOVE, &RegionDummyfunc ),
RegionCallBackWrapper( (void*) this, CALLBACK_REGION_CLICK, &RegionDummyfunc ) );
MSYS_AddRegion( &(*it).mMouseRegion );
MSYS_SetRegionUserData( &(*it).mMouseRegion, 0, panelcnt );
(*it).mMouseRegion_Defined = TRUE;
++panelcnt;
usPosX += textwidth;
}
}
}
void
TabBox::Destroy( )
{
if ( !IsInit( ) )
return;
for ( std::vector<TestPanelButtonStruct>::iterator it = mRegisteredTables.begin( ); it != mRegisteredTables.end( ); ++it )
{
if ( (*it).mMouseRegion_Defined )
{
MSYS_RemoveRegion( &(*it).mMouseRegion );
(*it).mMouseRegion_Defined = FALSE;
}
}
mRegisteredTables.clear( );
BaseTable::Destroy( );
}
void
TabBox::Display( )
{
if ( !IsInit( ) )
return;
DestroyMouseRegions();
CHAR16 sText[800];
swprintf( sText, L"" );
UINT16 usPosX = GetX( );
UINT16 panelcnt = 0;
UINT16 selectedx = 0;
UINT16 selectedwidth = 0;
SetFontShadow( NO_SHADOW );
for ( std::vector<TestPanelButtonStruct>::iterator it = mRegisteredTables.begin( ); it != mRegisteredTables.end( ); ++it )
{
if ( IsActive() )
{
// determine required width
UINT32 textwidth = 7 * wcslen( (*it).mTestPanel->GetName( ) );
if ( (*it).mTestPanel->IsActive( ) )
{
ColorFillVideoSurfaceArea( FRAME_BUFFER,
usPosX, GetY( ),
usPosX + textwidth, GetY( ) + TESTTABLE_OFFSET_ROW,
GetColorMarked() );
selectedx = usPosX;
selectedwidth = textwidth;
}
else
{
ColorFillVideoSurfaceArea( FRAME_BUFFER,
usPosX, GetY( ),
usPosX + textwidth, GetY( ) + TESTTABLE_OFFSET_ROW,
GetColorHighLight() );
}
// framework
// top
Display2Line2ShadowHorizontal( usPosX, GetY( ), usPosX + textwidth, GetColorLine( ), GetColorLineShadow( ) );
// left
Display2Line2ShadowVertical( usPosX, GetY( ) + GetFrameWorkSpace( ) / 2, GetY( ) + TESTTABLE_OFFSET_ROW - 1, GetColorLine( ), GetColorLineShadow( ) );
// right
Display2Line2ShadowVertical( usPosX + textwidth - 3, GetY( ) + GetFrameWorkSpace( ) / 2, GetY( ) + TESTTABLE_OFFSET_ROW, GetColorLineShadow( ), GetColorLine( ) );
swprintf( sText, (*it).mTestPanel->GetName( ) );
DrawTextToScreen( sText, usPosX + 7, GetY( ) + 7, GetWidth( ), TESTTABLE_FONT_MED, TESTTABLE_FONT_COLOR_REGULAR, FONT_MCOLOR_BLACK, FALSE, 0 );
// mouse region
if ( !(*it).mMouseRegion_Defined && IsMouseRegionActive( ) )
{
MSYS_DefineRegion( &(*it).mMouseRegion, usPosX, GetY( ), usPosX + textwidth, GetY( ) + TESTTABLE_OFFSET_ROW, MSYS_PRIORITY_HIGH,
CURSOR_WWW,
RegionCallBackWrapper( (void*) this, CALLBACK_REGION_MOVE, &RegionDummyfunc ),
RegionCallBackWrapper( (void*) this, CALLBACK_REGION_CLICK, &RegionDummyfunc ) );
MSYS_AddRegion( &(*it).mMouseRegion );
MSYS_SetRegionUserData( &(*it).mMouseRegion, 0, panelcnt );
(*it).mMouseRegion_Defined = TRUE;
++panelcnt;
}
usPosX += textwidth;
}
}
BaseTable::Display( );
// to indicate which frame is the active one we 'delete' the border to the content below
ColorFillVideoSurfaceArea( FRAME_BUFFER,
selectedx + GetFrameWorkSpace( ), GetY( ) + TESTTABLE_OFFSET_ROW,
selectedx + selectedwidth - 3, GetY( ) + TESTTABLE_OFFSET_ROW + GetFrameWorkSpace( ),
GetColorMarked( ) );
// left
Display2Line2ShadowVertical( selectedx, GetY( ) + TESTTABLE_OFFSET_ROW - 3, GetY( ) + TESTTABLE_OFFSET_ROW + 1, GetColorLine( ), GetColorLineShadow( ) );
// right
Display2Line2ShadowVertical( selectedx + selectedwidth - 3, GetY( ) + TESTTABLE_OFFSET_ROW - 3, GetY( ) + TESTTABLE_OFFSET_ROW + 1, GetColorLineShadow( ), GetColorLine( ) );
}
void
TabBox::DestroyMouseRegions( )
{
for ( std::vector<TestPanelButtonStruct>::iterator it = mRegisteredTables.begin( ); it != mRegisteredTables.end( ); ++it )
{
if ( (*it).mMouseRegion_Defined )
{
MSYS_RemoveRegion( &(*it).mMouseRegion );
(*it).mMouseRegion_Defined = FALSE;
}
}
BaseTable::DestroyMouseRegions( );
}
void
TabBox::RegionClickCallBack( MOUSE_REGION * pRegion, INT32 iReason )
{
if ( iReason & MSYS_CALLBACK_REASON_INIT )
{
}
else if ( iReason & MSYS_CALLBACK_REASON_LBUTTON_UP )
{
//gfScrollBoxIsScrolling = FALSE;
//gHelpScreen.iLastMouseClickY = -1;
}
else if ( iReason & MSYS_CALLBACK_REASON_LBUTTON_DWN )
{
for ( std::vector<TestPanelButtonStruct>::iterator it = mRegisteredTables.begin(); it != mRegisteredTables.end(); ++it )
{
if ( pRegion->IDNumber == (*it).mMouseRegion.IDNumber )
(*it).mTestPanel->SetActive( TRUE );
else
(*it).mTestPanel->SetActive( FALSE );
}
SetRefresh( );
//gfScrollBoxIsScrolling = TRUE;
//HelpScreenMouseMoveScrollBox( pRegion->MouseYPos );
}
else if ( iReason & MSYS_CALLBACK_REASON_RBUTTON_UP )
{
}
}
////////////////////////// TabBox /////////////////////////////////////
////////////////////////// TestTable /////////////////////////////////////
#define SCROLLARROW_WIDTH 20
#define SCROLLARROW_HEIGTH 20
TestTable::TestTable( )
: BaseTable( ),
mScrollBarDefined( FALSE ),
mFirstEntryShown(0),
mLastEntryShown( 0 )
{
}
void
TestTable::Init( UINT16 sX, UINT16 sY, UINT16 sX_End, UINT16 sY_End )
{
SetX( sX );
SetY( sY );
SetHeight( sY_End - sY );
SetWidth( sX_End - sX );
CalcRows( );
SetInit( TRUE );
}
extern UINT32 guiHelpScreenBackGround;
void
TestTable::Create( UINT16 sX, UINT16 sY, UINT16 sX_End, UINT16 sY_End )
{
VOBJECT_DESC VObjectDesc;
VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE;
FilenameForBPP( "INTERFACE\\HelpScreen.sti", VObjectDesc.ImageFile );
if ( !AddVideoObject( &VObjectDesc, &guiHelpScreenBackGround ) )
return;
Destroy( );
Init( sX, sY, sX_End, sY_End );
}
void
TestTable::Destroy( )
{
if ( !IsInit( ) )
return;
if ( mScrollBarDefined )
{
for ( UINT16 i = 0; i < 2; ++i )
{
RemoveButton( mScrollArrow[i] );
UnloadButtonImage( mScrollArrowImage[i] );
}
MSYS_RemoveRegion( &mScrollRegion );
mScrollBarDefined = FALSE;
}
std::vector<ColumnDataProvider>::iterator itend = mColumnDataProviderVector.end( );
for ( std::vector<ColumnDataProvider>::iterator it = mColumnDataProviderVector.begin( ); it != itend; ++it )
{
(*it).DestroyMouseRegions();
}
ClearColumnDataProvider();
DeleteVideoObjectFromIndex( guiHelpScreenBackGround );
SetInit( FALSE );
SetRefresh( );
}
void
TestTable::Display( )
{
if ( !IsInit( ) )
return;
CHAR16 sText[800];
swprintf( sText, L"" );
UINT16 usPosX, usPosY;
usPosX = GetX( );
usPosY = GetY( );
DestroyMouseRegions();
if ( IsActive() )
{
for ( std::vector<ColumnDataProvider>::iterator it = mColumnDataProviderVector.begin( ); it != mColumnDataProviderVector.end( ); ++it )
{
swprintf( sText, (*it).GetName( ) );
DrawTextToScreen( sText, usPosX, usPosY, GetWidth( ), TESTTABLE_FONT_MED, TESTTABLE_FONT_COLOR_REGULAR, FONT_MCOLOR_BLACK, FALSE, 0 );
usPosX += (*it).GetRequiredLength( );
}
usPosY += TESTTABLE_OFFSET_ROW - 4;
UINT32 heightperrow = GetRequiredHeigthPerRow( );
for ( UINT32 i = mFirstEntryShown; i < mLastEntryShown; ++i )
{
usPosX = GetX( );
DisplaySmallColouredLineWithShadow( usPosX, usPosY - 2, usPosX + GetWidth( ) - SCROLLARROW_WIDTH, usPosY - 2, FROMRGB( 0, 255, 0 ) );
std::vector<ColumnDataProvider>::iterator itend = mColumnDataProviderVector.end( );
for ( std::vector<ColumnDataProvider>::iterator it = mColumnDataProviderVector.begin( ); it != itend; ++it )
{
if ( it->GetProviderType( ) == ColumnDataProvider::CDP_STRING )
{
swprintf( sText, (*it).GetString( i ) );
DrawTextToScreen( sText, usPosX, usPosY + 7, GetWidth( ), TESTTABLE_FONT_MED, TESTTABLE_FONT_COLOR_REGULAR, FONT_MCOLOR_BLACK, FALSE, 0 );
}
else if ( it->GetProviderType( ) == ColumnDataProvider::CDP_IMAGE )
{
UINT32 imagelib = 0;
UINT16 imageid = 0;
it->GetImageData( i, imagelib, imageid );
BltVideoObjectFromIndex( FRAME_BUFFER, imagelib, imageid, usPosX, usPosY, VO_BLT_SRCTRANSPARENCY, NULL );
}
else if ( it->GetProviderType( ) == ColumnDataProvider::CDP_STATUSBAR )
{
UINT16 col1 = 0;
UINT16 col2 = 0;
UINT16 col3 = 0;
UINT16 col4 = 0;
UINT16 val1 = 0;
UINT16 val2 = 0;
UINT16 val3 = 0;
UINT16 val4 = 0;
it->GetStatusBarData( i, col1, val1, col2, val2, col3, val3, col4, val4 );
UINT16 height1 = (heightperrow * val1) / 100;
UINT16 height2 = (heightperrow * val2) / 100;
UINT16 height3 = (heightperrow * val3) / 100;
UINT16 height4 = (heightperrow * val4) / 100;
UINT16 endY = usPosY + heightperrow - 1;
// first a grey background (that way we get a grey 'border' for our bar, then the content
UINT16 bg = Get16BPPColor( FROMRGB( 158, 158, 158 ) );
DisplaySmallLine( usPosX + 0, usPosY, usPosX + 0, endY, bg );
DisplaySmallLine( usPosX + 1, usPosY, usPosX + 1, endY, bg );
DisplaySmallLine( usPosX + 2, usPosY, usPosX + 2, endY, bg );
DisplaySmallLine( usPosX + 3, usPosY, usPosX + 3, endY, bg );
DisplaySmallLine( usPosX + 1, endY - height1, usPosX + 1, endY, col1 );
DisplaySmallLine( usPosX + 2, endY - height1, usPosX + 2, endY, col1 );
DisplaySmallLine( usPosX + 1, endY - height2, usPosX + 1, endY, col2 );
DisplaySmallLine( usPosX + 2, endY - height2, usPosX + 2, endY, col2 );
DisplaySmallLine( usPosX + 1, endY - height3, usPosX + 1, endY, col3 );
DisplaySmallLine( usPosX + 2, endY - height3, usPosX + 2, endY, col3 );
DisplaySmallLine( usPosX + 1, endY - height4, usPosX + 1, endY, col4 );
DisplaySmallLine( usPosX + 2, endY - height4, usPosX + 2, endY, col4 );
}
if ( i - mFirstEntryShown < COLUMNDATAPROVIDER_MOUSEREGIONS && IsMouseRegionActive( ) )
{
MSYS_DefineRegion( &it->mMouseRegion[i - mFirstEntryShown],
usPosX, usPosY, usPosX + it->GetRequiredLength( ), usPosY + heightperrow,
MSYS_PRIORITY_HIGHEST, CURSOR_WWW,
MSYS_NO_CALLBACK, (*it).RegionClickCallBack );
MSYS_AddRegion( &it->mMouseRegion[i - mFirstEntryShown] );
// first entry of userdata is the callback type - we need to know what kind of callback function should be called
MSYS_SetRegionUserData( &it->mMouseRegion[i - mFirstEntryShown], 0, it->GetCallBackType() );
// second entry: the id to use as input in the callback
MSYS_SetRegionUserData( &it->mMouseRegion[i - mFirstEntryShown], 1, i );
it->mMouseRegion_Defined[i - mFirstEntryShown] = TRUE;
}
usPosX += (*it).GetRequiredLength( );
}
usPosY += heightperrow;
}
UINT32 shownentries = GetNumberOfDataRowsShown( );
UINT32 totalentries = GetNumberOfDataRows( );
// do we need scrollbars in the first place?
if ( shownentries < totalentries )
{
// length of scrollbar and length of scrollbar element
UINT32 scrollbarheigth = GetHeight( ) - 2 * SCROLLARROW_HEIGTH;
UINT32 scrollareaheigth = (scrollbarheigth * shownentries) / totalentries;
UINT32 areabegin = (scrollbarheigth * mFirstEntryShown) / totalentries;
ColorFillVideoSurfaceArea( FRAME_BUFFER,
GetX( ) + GetWidth( ) - SCROLLARROW_WIDTH - 2,
GetY( ) + SCROLLARROW_HEIGTH + areabegin,
GetX( ) + GetWidth( ) - 2,
GetY( ) + SCROLLARROW_HEIGTH + areabegin + scrollareaheigth,
Get16BPPColor( FROMRGB( 20, 250, 50 ) ) );
CreateScrollAreaButtons( );
}
}
BaseTable::Display( );
}
void
TestTable::DestroyMouseRegions()
{
std::vector<ColumnDataProvider>::iterator itend = mColumnDataProviderVector.end( );
for ( std::vector<ColumnDataProvider>::iterator it = mColumnDataProviderVector.begin( ); it != itend; ++it )
{
(*it).DestroyMouseRegions( );
}
if ( mScrollBarDefined )
{
for ( UINT16 i = 0; i < 2; ++i )
{
RemoveButton( mScrollArrow[i] );
UnloadButtonImage( mScrollArrowImage[i] );
}
MSYS_RemoveRegion( &mScrollRegion );
mScrollBarDefined = FALSE;
}
BaseTable::DestroyMouseRegions( );
}
void
TestTable::RegionMoveCallBack( MOUSE_REGION * pRegion, INT32 iReason )
{
if ( iReason & MSYS_CALLBACK_REASON_LOST_MOUSE )
{
// InvalidateRegion(pRegion->RegionTopLeftX, pRegion->RegionTopLeftY, pRegion->RegionBottomRightX, pRegion->RegionBottomRightY);
}
else if ( iReason & MSYS_CALLBACK_REASON_GAIN_MOUSE )
{
}
else if ( iReason & MSYS_CALLBACK_REASON_MOVE )
{
if ( gfLeftButtonState )
{
// if mouse is outside of the bar, simply move bar up or down
if ( pRegion->MouseYPos < mScrollRegion.RegionTopLeftY )
{
mLastEntryShown = max( 0, mLastEntryShown - 1 );
}
else if ( pRegion->MouseYPos > mScrollRegion.RegionBottomRightY )
{
++mLastEntryShown;
}
// inside the scroll bar, determine where the middle of the slider is to determine where to go
else
{
// length of scrollbar
UINT32 scrollbarheigth = GetHeight( ) - 2 * SCROLLARROW_HEIGTH;
if ( scrollbarheigth > 0 )
{
FLOAT rate = (FLOAT)(pRegion->MouseYPos - GetY( ) + SCROLLARROW_HEIGTH) / (FLOAT)(scrollbarheigth);
mLastEntryShown = rate * GetNumberOfDataRows();
}
}
// simply altering the position of mLastEntryShown and the recalculating the rows does the trick
CalcRows();
SetRefresh( );
}
}
}
void
TestTable::RegionClickCallBack( MOUSE_REGION * pRegion, INT32 iReason )
{
iReason = iReason;
if ( iReason & MSYS_CALLBACK_REASON_INIT )
{
}
else if ( iReason & MSYS_CALLBACK_REASON_LBUTTON_UP )
{
//gfScrollBoxIsScrolling = FALSE;
//gHelpScreen.iLastMouseClickY = -1;
}
else if ( iReason & MSYS_CALLBACK_REASON_LBUTTON_DWN )
{
//gfScrollBoxIsScrolling = TRUE;
//HelpScreenMouseMoveScrollBox( pRegion->MouseYPos );
}
else if ( iReason & MSYS_CALLBACK_REASON_RBUTTON_UP )
{
}
}
void
TestTable::ButtonClickCallBack( GUI_BUTTON *btn, INT32 reason )
{
if ( reason & MSYS_CALLBACK_REASON_INIT )
{
return;
}
if ( reason & MSYS_CALLBACK_REASON_LBUTTON_UP )
{
// up-arrow
if ( btn->IDNum == this->mScrollArrow[0] )
{
// do things!
if ( mFirstEntryShown )
--mFirstEntryShown;
mLastEntryShown = mFirstEntryShown + GetNumberOfDataRowsShown( );
}
// down-arrow
else if ( btn->IDNum == this->mScrollArrow[1] )
{
// do slightly different things!
mLastEntryShown = min( mLastEntryShown + 1, GetNumberOfDataRows( ) );
mFirstEntryShown = mLastEntryShown - GetNumberOfDataRowsShown( );
}
// this should not happen
else
{
return;
}
SetRefresh( );
}
else if ( reason & MSYS_CALLBACK_REASON_RBUTTON_UP )
{
// nothing yet
}
}
void
TestTable::CalcRows()
{
// don't show more entries than exist
UINT32 numrows = GetNumberOfDataRows( );
UINT32 rowsshown = GetNumberOfDataRowsShown( );
mLastEntryShown = max( mLastEntryShown, rowsshown );
mLastEntryShown = min( mLastEntryShown, numrows );
if ( mLastEntryShown > rowsshown )
mFirstEntryShown = mLastEntryShown - rowsshown;
else
mFirstEntryShown = 0;
mLastEntryShown = mFirstEntryShown + rowsshown;
}
void
TestTable::CreateScrollAreaButtons( )
{
if ( !mScrollBarDefined )
{
if ( IsMouseRegionActive() )
{
MSYS_DefineRegion( &mScrollRegion, GetX( ) + GetWidth( ) - SCROLLARROW_WIDTH - 2, GetY( ), GetX( ) + GetWidth( ) - 2, GetY( ) + GetHeight( ) - 2, MSYS_PRIORITY_HIGHEST,
CURSOR_WWW,
RegionCallBackWrapper( (void*) this, CALLBACK_REGION_MOVE, &RegionDummyfunc ),
RegionCallBackWrapper( (void*) this, CALLBACK_REGION_CLICK, &RegionDummyfunc ) );
MSYS_AddRegion( &mScrollRegion );
MSYS_SetRegionUserData( &mScrollRegion, 0, 0 );
mScrollArrowImage[0] = LoadButtonImage( "INTERFACE\\HelpScreen.sti", 14, 10, 11, 12, 13 );
mScrollArrowImage[1] = UseLoadedButtonImage( mScrollArrowImage[0], 19, 15, 16, 17, 18 );
//Create the scroll arrows
mScrollArrow[0] = QuickCreateButton( mScrollArrowImage[0], GetX( ) + GetWidth( ) - SCROLLARROW_WIDTH - 2, GetY( ),
BUTTON_TOGGLE, MSYS_PRIORITY_HIGHEST,
ButtonCallBackWrapper( (void*) this, CALLBACK_BUTTON_MOVE, &ButtonDummyfunc ),
ButtonCallBackWrapper( (void*) this, CALLBACK_BUTTON_CLICK, &ButtonDummyfunc ) );
MSYS_SetBtnUserData( mScrollArrow[0], 0, 0 );
//Create the scroll arrows
mScrollArrow[1] = QuickCreateButton( mScrollArrowImage[1], GetX( ) + GetWidth( ) - SCROLLARROW_WIDTH - 2, GetY( ) + GetHeight( ) - SCROLLARROW_HEIGTH - 2,
BUTTON_TOGGLE, MSYS_PRIORITY_HIGHEST,
ButtonCallBackWrapper( (void*) this, CALLBACK_BUTTON_MOVE, &ButtonDummyfunc ),
ButtonCallBackWrapper( (void*) this, CALLBACK_BUTTON_CLICK, &ButtonDummyfunc ) );
MSYS_SetBtnUserData( mScrollArrow[1], 0, 1 );
mScrollBarDefined = TRUE;
}
else
{
// if buttons are disabled, we'll display the images of the buttons instead
HVOBJECT hArrowHandle;
//get and display the up and down arrows
GetVideoObject( &hArrowHandle, guiHelpScreenBackGround );
if ( hArrowHandle )
{
// top arrow
BltVideoObject( FRAME_BUFFER, hArrowHandle, 10,
GetX( ) + GetWidth( ) - SCROLLARROW_WIDTH - 2,
GetY( ),
VO_BLT_SRCTRANSPARENCY, NULL );
// down arrow
BltVideoObject( FRAME_BUFFER, hArrowHandle, 17,
GetX( ) + GetWidth( ) - SCROLLARROW_WIDTH - 2,
GetY( ) + GetHeight( ) - SCROLLARROW_HEIGTH - 2,
VO_BLT_SRCTRANSPARENCY, NULL );
}
}
}
}
UINT32
TestTable::GetNumberOfDataRows( )
{
BOOLEAN fFound = FALSE;
UINT32 minrowsinproviders = 1000;
std::vector<ColumnDataProvider>::iterator itend = mColumnDataProviderVector.end( );
for ( std::vector<ColumnDataProvider>::iterator it = mColumnDataProviderVector.begin( ); it != itend; ++it )
{
minrowsinproviders = min( minrowsinproviders, (*it).GetNumberOfEntries( ) );
fFound = TRUE;
}
if ( fFound && minrowsinproviders )
return minrowsinproviders;
return 0;
}
UINT32
TestTable::GetNumberOfDataRowsShown( )
{
// determine total height that can be used for display - we have to substract space for the header and the column headers
UINT32 heightperrow = GetRequiredHeigthPerRow();
if ( !heightperrow )
return 0;
UINT32 totalheighttodistribute = GetHeight( );
if ( totalheighttodistribute < heightperrow + TESTTABLE_OFFSET_ROW )
return 0;
totalheighttodistribute -= TESTTABLE_OFFSET_ROW;
UINT32 rows = GetNumberOfDataRows( );
if ( !rows )
return 0;
// we need TESTTABLE_OFFSET_ROW space for each row. We cannot display more than we have
return min( totalheighttodistribute / heightperrow, rows );
}
UINT32
TestTable::GetRequiredHeigthPerRow( )
{
UINT32 heigth = 0;
std::vector<ColumnDataProvider>::iterator itend = mColumnDataProviderVector.end( );
for ( std::vector<ColumnDataProvider>::iterator it = mColumnDataProviderVector.begin( ); it != itend; ++it )
{
heigth = max( heigth, (*it).GetRequiredHeigth( ) );
}
return heigth;
}
////////////////////////// TestTable /////////////////////////////////////
+510
View File
@@ -0,0 +1,510 @@
#ifndef __BASETABLE_H
#define __BASETABLE_H
/**
* @file
* @author Flugente (bears-pit.com)
*/
#include "DropDown.h"
/*
* A base class for tables
*/
class BaseTable : public WidgetBase
{
public:
BaseTable( );
void SetInit( BOOLEAN fVal ) { fInit = fVal ; }
BOOLEAN IsInit() { return fInit ; }
/*
* set maximum width and height
*/
void SetWidth( UINT16 aVal ) { musWidth = aVal; }
virtual UINT16 GetWidth( ) { return musWidth; }
void SetHeight( UINT16 aVal ) { musHeight = aVal; }
virtual UINT16 GetHeight( ) { return musHeight; }
void SetFrameWorkSpace( UINT16 aVal ) { musFrameWorkSpace = aVal; }
virtual UINT16 GetFrameWorkSpace( ) { return musFrameWorkSpace; }
/*
* Initialise variables. Called after each creation which allows moving a dropdown
*/
virtual void Init( UINT16 sX, UINT16 sY, UINT16 sX_End, UINT16 sY_End );
/*
* Create a Dropdown with upper left coordinates
*/
virtual void Create( UINT16 sX, UINT16 sY, UINT16 sX_End, UINT16 sY_End );
/*
* Destroy Dropdown, for example once a website isn't displayed anymore
*/
virtual void Destroy( );
/*
* Display DropDownBase. Use this when refreshing
*/
virtual void Display( );
/*
* Sometimes a refresh inside the class isn't enough - best example is closing the dropdown area, after which the previous background cannot be restored by this class.
* In that case, the background and this class has to be redrawn.
* This function is called internally whenever such a refresh is necessary.
* It has to be defined in derived classes and should notify your dialogues to redraw at appropriate times
*
* This function has to be implemented!
*/
virtual void SetRefresh( ) = 0;
virtual void DestroyMouseRegions();
void SetActive( BOOLEAN aVal ) { mActive = aVal; }
BOOLEAN IsActive( ) { return mActive; }
virtual void SetMouseRegionActive( BOOLEAN aVal ) { mMouseRegionActive = aVal; }
BOOLEAN IsMouseRegionActive( ) { return mMouseRegionActive; }
virtual void RegisterMemberThingy( BaseTable * arP )
{
if ( mRegisteredMembers.empty() )
{
mRegisteredMembers.push_back( arP );
arP->SetActive( TRUE );
}
else
{
mRegisteredMembers.push_back( arP );
}
}
void SetName( STR16 aName ) { mName = aName; }
STR16 GetName() { return mName; }
private:
// declare but don't define
BaseTable( BaseTable const& );
void operator=(BaseTable const&);
private:
STR16 mName;
BOOLEAN fInit;
UINT16 musHeight;
UINT16 musWidth;
// as blank square dialogues are ugly, we can a framework on the edges - in this case we need to reserve some space for this
UINT16 musFrameWorkSpace;
// determines whether or not this widget will currently be shown
BOOLEAN mActive;
// if FALSE, do not display mouse regions
BOOLEAN mMouseRegionActive;
std::vector<BaseTable*> mRegisteredMembers;
};
// a simple panel into which we can embed other widgets
class TestPanel : public BaseTable
{
public:
TestPanel( );
/*
* Display DropDownBase. Use this when refreshing
*/
virtual void Display( );
virtual void SetRefresh( );
};
extern TestPanel gTestPanel3;
// callback types
enum {
CALLBACK_BUTTON_MOVE = 0,
CALLBACK_BUTTON_CLICK,
CALLBACK_REGION_MOVE,
CALLBACK_REGION_CLICK,
};
class WidgetCallBackInstance
{
public:
WidgetCallBackInstance( ) {}
virtual ~WidgetCallBackInstance( ) {}
virtual void RegionMoveCallBack( MOUSE_REGION * pRegion, INT32 iReason ) {}
virtual void RegionClickCallBack( MOUSE_REGION * pRegion, INT32 iReason ) {}
virtual void ButtonMoveCallBack( GUI_BUTTON *btn, INT32 reason ) {}
virtual void ButtonClickCallBack( GUI_BUTTON *btn, INT32 reason ) {}
/*
* This function is implemented again in DropDownTemplate
*/
virtual MOUSE_CALLBACK RegionCallBackWrapper( void* pt2Object, UINT8 arg, void( *pt2Function )(MOUSE_REGION * pRegion, INT32 iReason) ) { return RegionDummyfunc; }
virtual GUI_CALLBACK ButtonCallBackWrapper( void* pt2Object, UINT8 arg, void( *pt2Function )(GUI_BUTTON * btn, INT32 iReason) ) { return ButtonDummyfunc; }
/*
* This dummy is needed internally and does nothing when called
*/
static void RegionDummyfunc( MOUSE_REGION * pRegion, INT32 iReason ) {}
static void ButtonDummyfunc( GUI_BUTTON * btn, INT32 iReason ) {}
};
typedef STR16( *cdp_string_func )(UINT32 aNum);
STR16 cdp_string_func_dummy( UINT32 aNum );
typedef void( *cdp_image_func )(UINT32 aNum, UINT32& arImageLib, UINT16& arImage );
void cdp_image_func_dummy( UINT32 aNum, UINT32& arImageLib, UINT16& arImage );
typedef void( *cdp_statusbar_func )(UINT32 aId, UINT16& arCol1, UINT16& arVal1, UINT16& arCol2, UINT16& arVal2, UINT16& arCol3, UINT16& arVal3, UINT16& arCol4, UINT16& arVal4);
void cdp_statusbar_func_dummy( UINT32 aId, UINT16& arCol1, UINT16& arVal1, UINT16& arCol2, UINT16& arVal2, UINT16& arCol3, UINT16& arVal3, UINT16& arCol4, UINT16& arVal4 );
#define COLUMNDATAPROVIDER_MOUSEREGIONS 50
class ColumnDataProvider
{
public:
ColumnDataProvider( STR16 aName ) : mName( aName ), mNumberOfEntries( 0 ), mRequiredHeigth(20),
mType( CDP_STRING ), mCallbackType( CDP_DEFAULT ),
mFuncString( cdp_string_func_dummy ), mFuncImage( cdp_image_func_dummy )
{
}
// general provider functions
void SetNumberOfEntries( UINT32 aVal ) { mNumberOfEntries = aVal; CalcRequiredLength( ); }
UINT32 GetNumberOfEntries( ) { return mNumberOfEntries; }
void CalcRequiredLength( );
UINT32 GetRequiredLength( ) { return mRequiredLength; }
void SetRequiredLength( UINT32 aVal ) { mRequiredLength = aVal; } // this overrides the calculated value
UINT32 GetRequiredHeigth( ) { return mRequiredHeigth; }
void SetRequiredHeigth( UINT32 aVal ) { mRequiredHeigth = aVal; }
STR16 GetName( ) { return mName; }
typedef enum
{
CDP_DEFAULT = 0,
CDP_MILITIA_LIST,
CDP_MILITIADETAIL,
} CDP_CALLBACKTYPE;
typedef enum
{
CDP_STRING,
CDP_IMAGE,
CDP_STATUSBAR,
} CDP_TYPE;
CDP_TYPE GetProviderType( ) { return mType ; }
void SetProviderType( CDP_TYPE aType ) { mType = aType; }
// functions for handling string contents
void SetMethodString( cdp_string_func afunc ) { mFuncString = afunc; SetProviderType( CDP_STRING ); CalcRequiredLength( ); }
STR16 GetString( UINT32 aNum ) { return mFuncString( aNum ); }
// functions for handling images
void SetMethodImage( cdp_image_func afunc ) { mFuncImage = afunc; SetProviderType( CDP_IMAGE ); CalcRequiredLength( ); }
void GetImageData( UINT32 aNum, UINT32& arImageLib, UINT16& arImage ) { return mFuncImage( aNum, arImageLib, arImage ); }
// functions for handling healthbars
void SetMethodStatusBar( cdp_statusbar_func afunc ) { mFuncStatusBar = afunc; SetProviderType( CDP_STATUSBAR ); CalcRequiredLength( ); }
void GetStatusBarData( UINT32 aId, UINT16& arCol1, UINT16& arVal1, UINT16& arCol2, UINT16& arVal2, UINT16& arCol3, UINT16& arVal3, UINT16& arCol4, UINT16& arVal4 )
{
return mFuncStatusBar( aId, arCol1, arVal1, arCol2, arVal2, arCol3, arVal3, arCol4, arVal4 );
}
// callbacks for clicking on a column
void SetCallBackType( CDP_CALLBACKTYPE aVal ) { mCallbackType = aVal; }
CDP_CALLBACKTYPE GetCallBackType( ) { return mCallbackType; }
static void RegionClickCallBack( MOUSE_REGION * pRegion, INT32 iReason );
void DestroyMouseRegions();
public:
MOUSE_REGION mMouseRegion[COLUMNDATAPROVIDER_MOUSEREGIONS];
BOOLEAN mMouseRegion_Defined[COLUMNDATAPROVIDER_MOUSEREGIONS];
private:
STR16 mName;
UINT32 mNumberOfEntries;
// the maximum length required for a column according to its contents
UINT32 mRequiredLength;
UINT32 mRequiredHeigth;
CDP_TYPE mType;
CDP_CALLBACKTYPE mCallbackType;
cdp_string_func mFuncString;
cdp_image_func mFuncImage;
cdp_statusbar_func mFuncStatusBar;
};
// a simple panel into which we can embed other widgets
class TabBox : public BaseTable, public WidgetCallBackInstance
{
public:
TabBox( );
/*
* Initialise variables. Called after each creation which allows moving a dropdown
*/
virtual void Init( UINT16 sX, UINT16 sY, UINT16 sX_End, UINT16 sY_End );
/*
* Create a Dropdown with upper left coordinates
*/
virtual void Create( UINT16 sX, UINT16 sY, UINT16 sX_End, UINT16 sY_End );
/*
* Destroy Dropdown, for example once a website isn't displayed anymore
*/
virtual void Destroy( );
/*
* Display DropDownBase. Use this when refreshing
*/
virtual void Display( );
virtual void DestroyMouseRegions( );
struct TestPanelButtonStruct
{
BaseTable* mTestPanel;
MOUSE_REGION mMouseRegion;
BOOLEAN mMouseRegion_Defined;
};
virtual void RegisterMemberThingy( BaseTable * arP )
{
if ( !mRegisteredTables.empty( ) )
arP->SetActive( FALSE );
TestPanelButtonStruct tmp;
tmp.mTestPanel = arP;
tmp.mMouseRegion_Defined = FALSE;
mRegisteredTables.push_back( tmp );
BaseTable::RegisterMemberThingy( arP );
}
virtual void RegionMoveCallBack( MOUSE_REGION * pRegion, INT32 iReason ) {}
virtual void RegionClickCallBack( MOUSE_REGION * pRegion, INT32 iReason );
private:
std::vector<TestPanelButtonStruct> mRegisteredTables;
};
class TestTable : public BaseTable, public WidgetCallBackInstance
{
public:
TestTable( );
/*
* Initialise variables. Called after each creation which allows moving a dropdown
*/
virtual void Init( UINT16 sX, UINT16 sY, UINT16 sX_End, UINT16 sY_End );
/*
* Create a Dropdown with upper left coordinates
*/
virtual void Create( UINT16 sX, UINT16 sY, UINT16 sX_End, UINT16 sY_End );
/*
* Destroy Dropdown, for example once a website isn't displayed anymore
*/
virtual void Destroy( );
/*
* Display DropDownBase. Use this when refreshing
*/
virtual void Display( );
virtual void DestroyMouseRegions( ) ;
virtual void RegionMoveCallBack( MOUSE_REGION * pRegion, INT32 iReason );
virtual void RegionClickCallBack( MOUSE_REGION * pRegion, INT32 iReason );
virtual void ButtonClickCallBack( GUI_BUTTON *btn, INT32 reason );
void AddColumnDataProvider( ColumnDataProvider aCP ) { mColumnDataProviderVector.push_back( aCP ); }
void ClearColumnDataProvider( ) { mColumnDataProviderVector.clear(); }
void CalcRows();
private:
void CreateScrollAreaButtons( );
UINT32 GetNumberOfDataRows( );
UINT32 GetNumberOfDataRowsShown( );
UINT32 GetRequiredHeigthPerRow();
private:
// parts of the scrollbar
BOOLEAN mScrollBarDefined;
INT32 mScrollArrow[2];
UINT32 mScrollArrowImage[2];
MOUSE_REGION mScrollRegion;
UINT32 mFirstEntryShown;
UINT32 mLastEntryShown;
std::vector<ColumnDataProvider> mColumnDataProviderVector;
};
template<int N>
class TestTableTemplate : public TestTable
{
public:
static TestTableTemplate<N>& getInstance( )
{
static TestTableTemplate<N> instance; // Guaranteed to be destroyed.
// Instantiated on first use.
return instance;
}
// this function has to be implemented!
virtual void SetRefresh( );
virtual void Init( UINT16 sX, UINT16 sY, UINT16 sX_End, UINT16 sY_End );
static void RegionMove( MOUSE_REGION * pRegion, INT32 iReason ) { return static_cast<TestTable*>(mpSelf)->RegionMoveCallBack( pRegion, iReason ); }
static void RegionClick( MOUSE_REGION * pRegion, INT32 iReason ) { return static_cast<TestTable*>(mpSelf)->RegionClickCallBack( pRegion, iReason ); }
static void ButtonMove( GUI_BUTTON *btn, INT32 iReason ) { return static_cast<TestTable*>(mpSelf)->ButtonMoveCallBack( btn, iReason ); }
static void ButtonClick( GUI_BUTTON *btn, INT32 iReason ) { return static_cast<TestTable*>(mpSelf)->ButtonClickCallBack( btn, iReason ); }
MOUSE_CALLBACK
RegionCallBackWrapper( void* pt2Object, UINT8 arg, void( *pt2Function )(MOUSE_REGION * pRegion, INT32 iReason) )
{
mpSelf = pt2Object;
switch ( arg )
{
case CALLBACK_REGION_MOVE: return &RegionMove; break;
case CALLBACK_REGION_CLICK: return &RegionClick; break;
}
return *pt2Function;
}
GUI_CALLBACK
ButtonCallBackWrapper( void* pt2Object, UINT8 arg, void( *pt2Function )(GUI_BUTTON *btn, INT32 iReason) )
{
mpSelf = pt2Object;
switch ( arg )
{
case CALLBACK_BUTTON_MOVE: return &ButtonMove; break;
case CALLBACK_BUTTON_CLICK: return &ButtonClick; break;
}
return *pt2Function;
}
private:
static void* mpSelf;
private:
TestTableTemplate<N>( ) {}; // private constructor, so we cannot create more instances
// declare but don't define
TestTableTemplate( TestTableTemplate const& );
void operator=(TestTableTemplate const&);
};
template <int N>
void TestTableTemplate<N>::SetRefresh();
template <int N>
void TestTableTemplate<N>::Init( UINT16 sX, UINT16 sY, UINT16 sX_End, UINT16 sY_End );
template <int N>
void* TestTableTemplate<N>::mpSelf = NULL;
template<int N>
class TabBoxTemplate : public TabBox
{
public:
static TabBoxTemplate<N>& getInstance( )
{
static TabBoxTemplate<N> instance; // Guaranteed to be destroyed.
// Instantiated on first use.
return instance;
}
static TabBox* GetPSelf( ) { return static_cast<TabBox*>(mpSelf); }
// this function has to be implemented!
virtual void SetRefresh( );
static void RegionMove( MOUSE_REGION * pRegion, INT32 iReason ) { return GetPSelf()->RegionMoveCallBack( pRegion, iReason ); }
static void RegionClick( MOUSE_REGION * pRegion, INT32 iReason ) { return GetPSelf()->RegionClickCallBack( pRegion, iReason ); }
static void ButtonMove( GUI_BUTTON *btn, INT32 iReason ) { return GetPSelf()->ButtonMoveCallBack( btn, iReason ); }
static void ButtonClick( GUI_BUTTON *btn, INT32 iReason ) { return GetPSelf()->ButtonClickCallBack( btn, iReason ); }
void SetPSelf( void* pt2Object ) { mpSelf = pt2Object; }
MOUSE_CALLBACK
RegionCallBackWrapper( void* pt2Object, UINT8 arg, void( *pt2Function )(MOUSE_REGION * pRegion, INT32 iReason) )
{
SetPSelf ( pt2Object );
switch ( arg )
{
case CALLBACK_REGION_MOVE: return &RegionMove; break;
case CALLBACK_REGION_CLICK: return &RegionClick; break;
}
return *pt2Function;
}
GUI_CALLBACK
ButtonCallBackWrapper( void* pt2Object, UINT8 arg, void( *pt2Function )(GUI_BUTTON *btn, INT32 iReason) )
{
SetPSelf( pt2Object );
switch ( arg )
{
case CALLBACK_BUTTON_MOVE: return &ButtonMove; break;
case CALLBACK_BUTTON_CLICK: return &ButtonClick; break;
}
return *pt2Function;
}
private:
static void* mpSelf;
private:
TabBoxTemplate<N>( ) {}; // private constructor, so we cannot create more instances
// declare but don't define
TabBoxTemplate( TabBoxTemplate const& );
void operator=(TabBoxTemplate const&);
};
template <int N>
void TabBoxTemplate<N>::SetRefresh( );
template <int N>
void* TabBoxTemplate<N>::mpSelf = NULL;
#endif
+18 -76
View File
@@ -437,10 +437,12 @@ void RenderCampaignHistory_MostImportant()
usPosX = LAPTOP_SCREEN_UL_X;
usPosY = LAPTOP_SCREEN_WEB_UL_Y + 70;
// return if there are no incidents yet
if ( !gCampaignStats.usNumIncidents )
return;
// fix if bad number
if ( gusMostImportantPage >= gCampaignStats.usNumIncidents )
gusMostImportantPage = 0;
if ( gusMostImportantPage < gCampaignStats.usNumIncidents )
{
Incident_Stats incident = gCampaignStats.mIncidentVector[ gusMostImportantPage ];
CHAR16 wSectorName_Target[ 100 ];
@@ -453,39 +455,9 @@ void RenderCampaignHistory_MostImportant()
UINT32 hour = ( incident.usTime - ( day * NUM_SEC_IN_DAY ) ) / NUM_SEC_IN_HOUR;
UINT32 minute = ( incident.usTime - ( ( day * NUM_SEC_IN_DAY ) + ( hour * NUM_SEC_IN_HOUR ) ) ) / NUM_SEC_IN_MIN;
// a funny operation name might be more entertaining than a simple number
/*UINT8 importancenr = TEXT_CAMPAIGNHISTORY_IMPORTANCE_MOMENTOUS;
if ( incident.usInterestRating < 500 )
importancenr = TEXT_CAMPAIGNHISTORY_IMPORTANCE_IRRELEVANT;
else if ( incident.usInterestRating < 1000 )
importancenr = TEXT_CAMPAIGNHISTORY_IMPORTANCE_INSIGNIFICANT;
else if ( incident.usInterestRating < 2000 )
importancenr = TEXT_CAMPAIGNHISTORY_IMPORTANCE_NOTABLE;
else if ( incident.usInterestRating < 3000 )
importancenr = TEXT_CAMPAIGNHISTORY_IMPORTANCE_NOTEWORTHY;
else if ( incident.usInterestRating < 4000 )
importancenr = TEXT_CAMPAIGNHISTORY_IMPORTANCE_SIGNIFICANT;
else if ( incident.usInterestRating < 5000 )
importancenr = TEXT_CAMPAIGNHISTORY_IMPORTANCE_INTERESTING;
else if ( incident.usInterestRating < 6000 )
importancenr = TEXT_CAMPAIGNHISTORY_IMPORTANCE_IMPORTANT;
else if ( incident.usInterestRating < 7000 )
importancenr = TEXT_CAMPAIGNHISTORY_IMPORTANCE_VERYIMPORTANT;
else if ( incident.usInterestRating < 8000 )
importancenr = TEXT_CAMPAIGNHISTORY_IMPORTANCE_GRAVE;
else if ( incident.usInterestRating < 10000 )
importancenr = TEXT_CAMPAIGNHISTORY_IMPORTANCE_MAJOR;
STR16 operationstr = GetIncidentName( incident.usID );
swprintf(sText, L"%s %s #%d - %s, %s %d, %02d:%02d", szCampaignHistoryImportanceString[importancenr], szCampaignHistoryWebpageString[WEBPAGE_CAMPAIGNHISTORY_INCIDENT], incident.usID, wSectorName_Target, szCampaignHistoryWebpageString[WEBPAGE_CAMPAIGNHISTORY_DAY], day, hour, minute);
DrawTextToScreen( sText, usPosX, usPosY, LAPTOP_SCREEN_LR_X-LAPTOP_SCREEN_UL_X, CAMPHIS_FONT_BIG, CAMPHIS_FONT_COLOR, FONT_MCOLOR_BLACK, FALSE, LEFT_JUSTIFIED );*/
UINT32 prefix = (incident.usTime + incident.usKills[CAMPAIGNHISTORY_SD_ENEMY_ARMY] + incident.usID) % CAMPAIGNSTATS_OPERATION_NUM_PREFIX;
UINT32 suffix = (incident.usTime + incident.usShots[CAMPAIGNHISTORY_SD_MERC] + 7 * incident.usID) % CAMPAIGNSTATS_OPERATION_NUM_SUFFIX;
CHAR16 operationame[200];
swprintf( operationame, szCampaignStatsOperationPrefix[prefix], szCampaignStatsOperationSuffix[suffix] );
swprintf( sText, L"Operation %s - %s, %s %d, %02d:%02d", operationame, wSectorName_Target, szCampaignHistoryWebpageString[WEBPAGE_CAMPAIGNHISTORY_DAY], day, hour, minute );
swprintf( sText, L"Operation %s - %s, %s %d, %02d:%02d", operationstr, wSectorName_Target, szCampaignHistoryWebpageString[WEBPAGE_CAMPAIGNHISTORY_DAY], day, hour, minute );
DrawTextToScreen( sText, usPosX, usPosY, LAPTOP_SCREEN_LR_X-LAPTOP_SCREEN_UL_X, CAMPHIS_FONT_BIG, CAMPHIS_FONT_COLOR, FONT_MCOLOR_BLACK, FALSE, LEFT_JUSTIFIED );
usPosY = LAPTOP_SCREEN_WEB_UL_Y + 90;
@@ -864,6 +836,7 @@ void RenderCampaignHistory_MostImportant()
}
}
}
}
// previous/next buttons
usPosX = CAMPAIGN_HISTORY_PAGEBTN_X;
@@ -936,9 +909,11 @@ void SelectCampaignHistoryMostImportantRegionCallBack(MOUSE_REGION * pRegion, IN
////////////////////////// MOST IMPORTANT PAGE //////////////////////////////////
////////////////////////// NEWS PAGE //////////////////////////////////
BOOLEAN gfCampaignHistoryNewsRedraw = FALSE;
//link to the various pages
MOUSE_REGION gCampaignHistoryNewsLinkRegion[4];
void SelectCampaignHistoryNewsRegionCallBack(MOUSE_REGION * pRegion, INT32 iReason );
void SelectCampaignHistoryNewsRegionCallBack( MOUSE_REGION * pRegion, INT32 iReason );
UINT32 gusNewsPage = 0;
@@ -976,11 +951,17 @@ void ExitCampaignHistory_News()
// previous/next buttons
for(int i=0; i<4; ++i)
MSYS_RemoveRegion( &gCampaignHistoryNewsLinkRegion[i]);
gfCampaignHistoryNewsRedraw = FALSE;
}
void HandleCampaignHistory_News()
{
if ( gfCampaignHistoryNewsRedraw )
{
RenderCampaignHistory_News( );
gfCampaignHistoryNewsRedraw = FALSE;
}
}
void RenderCampaignHistory_News()
@@ -997,45 +978,6 @@ void RenderCampaignHistory_News()
usPosX = LAPTOP_SCREEN_UL_X;
usPosY = LAPTOP_SCREEN_WEB_UL_Y + 80;
// return if there are no incidents yet
/*if ( !gCampaignStats.usNumIncidents )
return;
Incident_Stats incident = gCampaignStats.mIncidentVector[ gusNewsPage ];
CHAR16 wSectorName_Target[ 100 ];
GetSectorIDString( SECTORX(incident.usSector), SECTORY(incident.usSector), incident.usLevel, wSectorName_Target, TRUE );
//Calculate the day, hour, and minutes.
UINT32 day = ( incident.usTime / NUM_SEC_IN_DAY );
UINT32 hour = ( incident.usTime - ( day * NUM_SEC_IN_DAY ) ) / NUM_SEC_IN_HOUR;
UINT32 minute = ( incident.usTime - ( ( day * NUM_SEC_IN_DAY ) + ( hour * NUM_SEC_IN_HOUR ) ) ) / NUM_SEC_IN_MIN;*/
//swprintf(sText, L"Incident #%d - %s, Day %d, %02d:%02d", incident.usID, wSectorName_Target, day, hour, minute);
swprintf(sText, L"--- currently under construction ---");
DrawTextToScreen( sText, usPosX, usPosY, LAPTOP_SCREEN_LR_X-LAPTOP_SCREEN_UL_X, CAMPHIS_FONT_BIG, CAMPAIGN_HISTORY_FONT_COLOR_REGULAR, FONT_MCOLOR_BLACK, FALSE, LEFT_JUSTIFIED );
// previous/next buttons
/*usPosX = CAMPAIGN_HISTORY_PAGEBTN_X;
usPosY = CAMPAIGN_HISTORY_PAGEBTN_Y;
swprintf(sText, L"Summary");
DrawTextToScreen( sText, usPosX, usPosY, LAPTOP_SCREEN_LR_X-LAPTOP_SCREEN_UL_X, INS_FONT_SMALL, CAMPAIGN_HISTORY_FONT_COLOR_REGULAR, FONT_MCOLOR_BLACK, FALSE, 0 );
usPosX += CAMPAIGN_HISTORY_PAGEBTN_STEP_X;
swprintf(sText, L"Detail");
DrawTextToScreen( sText, usPosX, usPosY, LAPTOP_SCREEN_LR_X-LAPTOP_SCREEN_UL_X, INS_FONT_SMALL, CAMPAIGN_HISTORY_FONT_COLOR_REGULAR, FONT_MCOLOR_BLACK, FALSE, 0 );
usPosX += CAMPAIGN_HISTORY_PAGEBTN_STEP_X;
swprintf(sText, L"Previous");
DrawTextToScreen( sText, usPosX, usPosY, LAPTOP_SCREEN_LR_X-LAPTOP_SCREEN_UL_X, INS_FONT_SMALL, CAMPAIGN_HISTORY_FONT_COLOR_REGULAR, FONT_MCOLOR_BLACK, FALSE, 0 );
usPosX += CAMPAIGN_HISTORY_PAGEBTN_STEP_X;
swprintf(sText, L"Next");
DrawTextToScreen( sText, usPosX, usPosY, LAPTOP_SCREEN_LR_X-LAPTOP_SCREEN_UL_X, INS_FONT_SMALL, CAMPAIGN_HISTORY_FONT_COLOR_REGULAR, FONT_MCOLOR_BLACK, FALSE, 0 );*/
SetFontShadow( DEFAULT_SHADOW );
MarkButtonsDirty( );
RenderWWWProgramTitleBar( );
+45 -2
View File
@@ -21,8 +21,6 @@ Incident_Stats gCurrentIncident; // we might save during an incident, thus we h
CAMPAIGNSTATSEVENT zCampaignStatsEvent[NUM_CAMPAIGNSTATSEVENTS];
extern INT32 ReadFieldByField(HWFILE hFile, PTR pDest, UINT32 uiFieldSize, UINT32 uiElementSize, UINT32 uiCurByteCount);
void
Incident_Stats::clear()
{
@@ -748,3 +746,48 @@ void StartIncident(INT16 sX, INT16 sY, INT8 sZ)
gCurrentIncident.usSector = SECTOR(sX, sY);
gCurrentIncident.usLevel = sZ;
}
INT32 GetPositionOfIncident( UINT32 aIncidentId )
{
INT32 cnt = 0;
std::vector<Incident_Stats>::iterator itend = gCampaignStats.mIncidentVector.end( );
for ( std::vector<Incident_Stats>::iterator it = gCampaignStats.mIncidentVector.begin( ); it != itend; ++it )
{
if ( (*it).usID == aIncidentId )
return cnt;
++cnt;
}
return -1;
}
static CHAR16 gIncidentNameText[100];
STR16 GetIncidentName( UINT32 aIncidentId )
{
swprintf( gIncidentNameText, L"NAME NOT FOUND" );
std::vector<Incident_Stats>::iterator itend = gCampaignStats.mIncidentVector.end( );
for ( std::vector<Incident_Stats>::iterator it = gCampaignStats.mIncidentVector.begin( ); it != itend; ++it )
{
if ( (*it).usID == aIncidentId )
{
Incident_Stats incident = (*it);
UINT32 prefix = (incident.usTime + incident.usKills[CAMPAIGNHISTORY_SD_ENEMY_ARMY] + incident.usID) % CAMPAIGNSTATS_OPERATION_NUM_PREFIX;
UINT32 suffix = (incident.usTime + incident.usShots[CAMPAIGNHISTORY_SD_MERC] + 7 * incident.usID) % CAMPAIGNSTATS_OPERATION_NUM_SUFFIX;
swprintf( gIncidentNameText, szCampaignStatsOperationPrefix[prefix], szCampaignStatsOperationSuffix[suffix] );
break;
}
}
return gIncidentNameText;
}
UINT32 GetIdOfCurrentlyOngoingIncident()
{
return gCampaignStats.usHighestID + 1;
}
+5
View File
@@ -327,4 +327,9 @@ void FinishIncident(INT16 sX, INT16 sY, INT8 sZ);
// start a new incident
void StartIncident(INT16 sX, INT16 sY, INT8 sZ);
INT32 GetPositionOfIncident( UINT32 aIncidentId );
STR16 GetIncidentName( UINT32 aIncidentId );
UINT32 GetIdOfCurrentlyOngoingIncident();
#endif // __CAMPAIGNSTATS_H
+5
View File
@@ -136,6 +136,11 @@ enum definedDropDowns
DROPDOWNNR_MSGBOX_1,
DROPDOWNNR_MSGBOX_2,
DROPDOWN_MILTIAWEBSITE_FILTER_DEAD,
DROPDOWN_MILTIAWEBSITE_FILTER_RANK,
DROPDOWN_MILTIAWEBSITE_FILTER_ORIGIN,
DROPDOWN_MILTIAWEBSITE_FILTER_SECTOR,
};
/*
+12 -19
View File
@@ -136,7 +136,6 @@ extern BOOLEAN fNewIMPGearMethodUsed;
void IMPGearDisplay( );
void DisplayGear( UINT16 usItem, UINT16 usPosX, UINT16 usPosY, BOOLEAN fWithBackGround );
void BtnIMPGearFinishCallback( GUI_BUTTON *btn, INT32 reason );
// determine all items that are selectable according to xml and choices
@@ -482,22 +481,11 @@ void IMPGearDisplay( )
INT16 sItem = (UINT16)pIMPGEARDropDown[i]->GetSelectedEntryKey( );
DisplayGear( (UINT16)sItem, pIMPGEARDropDown[i]->GetX( ) - IMP_GEAR_ITEMDISPLAY_WIDTH, pIMPGEARDropDown[i]->GetY( ), TRUE );
DisplayGear( (UINT16)sItem, pIMPGEARDropDown[i]->GetX( ) - IMP_GEAR_ITEMDISPLAY_WIDTH, pIMPGEARDropDown[i]->GetY( ), TRUE, gIMPGearCount[i], TRUE );
if ( sItem > 0 )
{
if ( sItem )
gIMPGearCost += gIMPGearCount[i] * Item[sItem].usPrice;
// if more than 1?
if ( gIMPGearCount[i] > 1 )
{
CHAR16 sString[128];
swprintf( sString, L"%d", gIMPGearCount[i] );
INT16 sX, sY;
FindFontRightCoordinates( (INT16)(pIMPGEARDropDown[i]->GetX( ) - IMP_GEAR_ITEMDISPLAY_WIDTH), (INT16)(pIMPGEARDropDown[i]->GetY( ) + 6), (INT16)(10), (INT16)(GetFontHeight( FONT10ARIAL )), sString, FONT10ARIAL, &sX, &sY );
mprintf( sX, sY, sString );
}
}
}
else
@@ -511,7 +499,7 @@ void IMPGearDisplay( )
DrawTextToScreen( wTemp, LAPTOP_SCREEN_UL_X + 180, LAPTOP_SCREEN_WEB_UL_Y + 360, LAPTOP_TEXT_WIDTH, FONT14ARIAL, IMP_GEAR__COLOR, FONT_MCOLOR_BLACK, FALSE, LEFT_JUSTIFIED );
}
void DisplayGear( UINT16 usItem, UINT16 usPosX, UINT16 usPosY, BOOLEAN fWithBackGround )
void DisplayGear( UINT16 usItem, UINT16 usPosX, UINT16 usPosY, BOOLEAN fWithBackGround, UINT8 aNumber, BOOLEAN fDisplayNumber )
{
if ( usItem )
{
@@ -549,12 +537,17 @@ void DisplayGear( UINT16 usItem, UINT16 usPosX, UINT16 usPosY, BOOLEAN fWithBack
//blt the item
BltVideoObjectOutlineFromIndex( FRAME_BUFFER, GetInterfaceGraphicForItem( pItem ), usGraphicNum, PosX, PosY, 0, FALSE );
}
/*else
// display number if more than 1
if ( fDisplayNumber && aNumber > 1 )
{
// if there is not item to display, use a different colour for the box
ColorFillVideoSurfaceArea( FRAME_BUFFER, usPosX, usPosY, usPosX + IMP_GEAR_ITEMDISPLAY_WIDTH, usPosY + IMP_GEAR_ITEMDISPLAY_HEIGHT, Get16BPPColor( FROMRGB( 230, 84, 43 ) ) );
}*/
CHAR16 sString[128];
swprintf( sString, L"%d", aNumber );
INT16 sX, sY;
FindFontRightCoordinates( (INT16)(usPosX), (INT16)(usPosY + 6), 10, (INT16)(GetFontHeight( FONT10ARIAL )), sString, FONT10ARIAL, &sX, &sY );
mprintf( sX, sY, sString );
}
}
}
void BtnIMPGearFinishCallback( GUI_BUTTON *btn, INT32 reason )
+2
View File
@@ -14,6 +14,8 @@ void RenderIMPGear( void );
void ExitIMPGear( void );
void HandleIMPGear( void );
void DisplayGear( UINT16 usItem, UINT16 usPosX, UINT16 usPosY, BOOLEAN fWithBackGround, UINT8 aNumber, BOOLEAN fDisplayNumber );
void GiveIMPSelectedGear( MERCPROFILESTRUCT *pProfile );
INT32 GetIMPGearCost();
+24
View File
@@ -370,6 +370,10 @@
RelativePath=".\AimSort.h"
>
</File>
<File
RelativePath=".\BaseTable.h"
>
</File>
<File
RelativePath=".\BobbyR.h"
>
@@ -654,6 +658,14 @@
RelativePath=".\mercs.h"
>
</File>
<File
RelativePath=".\MilitiaInterface.h"
>
</File>
<File
RelativePath=".\MilitiaWebsite.h"
>
</File>
<File
RelativePath=".\personnel.h"
>
@@ -720,6 +732,10 @@
RelativePath=".\AimSort.cpp"
>
</File>
<File
RelativePath=".\BaseTable.cpp"
>
</File>
<File
RelativePath=".\BobbyR.cpp"
>
@@ -984,6 +1000,14 @@
RelativePath=".\mercs.cpp"
>
</File>
<File
RelativePath=".\MilitiaInterface.cpp"
>
</File>
<File
RelativePath=".\MilitiaWebsite.cpp"
>
</File>
<File
RelativePath=".\personnel.cpp"
>
+24
View File
@@ -370,6 +370,10 @@
RelativePath="AimSort.h"
>
</File>
<File
RelativePath="BaseTable.h"
>
</File>
<File
RelativePath="BobbyR.h"
>
@@ -654,6 +658,14 @@
RelativePath="mercs.h"
>
</File>
<File
RelativePath="MilitiaInterface.h"
>
</File>
<File
RelativePath="MilitiaWebsite.h"
>
</File>
<File
RelativePath="personnel.h"
>
@@ -718,6 +730,10 @@
RelativePath="AimSort.cpp"
>
</File>
<File
RelativePath="BaseTable.cpp"
>
</File>
<File
RelativePath="BobbyR.cpp"
>
@@ -986,6 +1002,14 @@
RelativePath="mercs.cpp"
>
</File>
<File
RelativePath="MilitiaInterface.cpp"
>
</File>
<File
RelativePath="MilitiaWebsite.cpp"
>
</File>
<File
RelativePath="personnel.cpp"
>
+6
View File
@@ -31,6 +31,7 @@
<ClInclude Include="AimMembers.h" />
<ClInclude Include="AimPolicies.h" />
<ClInclude Include="AimSort.h" />
<ClInclude Include="BaseTable.h" />
<ClInclude Include="BobbyR.h" />
<ClInclude Include="BobbyRAmmo.h" />
<ClInclude Include="BobbyRArmour.h" />
@@ -102,6 +103,8 @@
<ClInclude Include="mercs Files.h" />
<ClInclude Include="mercs No Account.h" />
<ClInclude Include="mercs.h" />
<ClInclude Include="MilitiaInterface.h" />
<ClInclude Include="MilitiaWebsite.h" />
<ClInclude Include="personnel.h" />
<ClInclude Include="PMC.h" />
<ClInclude Include="PostalService.h" />
@@ -119,6 +122,7 @@
<ClCompile Include="AimMembers.cpp" />
<ClCompile Include="AimPolicies.cpp" />
<ClCompile Include="AimSort.cpp" />
<ClCompile Include="BaseTable.cpp" />
<ClCompile Include="BobbyR.cpp" />
<ClCompile Include="BobbyRAmmo.cpp" />
<ClCompile Include="BobbyRArmour.cpp" />
@@ -186,6 +190,8 @@
<ClCompile Include="mercs Files.cpp" />
<ClCompile Include="mercs No Account.cpp" />
<ClCompile Include="mercs.cpp" />
<ClCompile Include="MilitiaInterface.cpp" />
<ClCompile Include="MilitiaWebsite.cpp" />
<ClCompile Include="personnel.cpp" />
<ClCompile Include="PMC.cpp" />
<ClCompile Include="PostalService.cpp" />
+18
View File
@@ -32,6 +32,9 @@
</ClInclude>
<ClInclude Include="AimSort.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="BaseTable.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="BobbyR.h">
<Filter>Header Files</Filter>
@@ -203,6 +206,12 @@
</ClInclude>
<ClInclude Include="mercs.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="MilitiaInterface.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="MilitiaWebsite.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="personnel.h">
<Filter>Header Files</Filter>
@@ -292,6 +301,9 @@
</ClCompile>
<ClCompile Include="AimSort.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="BaseTable.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="BobbyR.cpp">
<Filter>Source Files</Filter>
@@ -454,6 +466,12 @@
</ClCompile>
<ClCompile Include="mercs.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="MilitiaInterface.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="MilitiaWebsite.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="personnel.cpp">
<Filter>Source Files</Filter>
+6
View File
@@ -31,6 +31,7 @@
<ClInclude Include="AimMembers.h" />
<ClInclude Include="AimPolicies.h" />
<ClInclude Include="AimSort.h" />
<ClInclude Include="BaseTable.h" />
<ClInclude Include="BobbyR.h" />
<ClInclude Include="BobbyRAmmo.h" />
<ClInclude Include="BobbyRArmour.h" />
@@ -102,6 +103,8 @@
<ClInclude Include="mercs Files.h" />
<ClInclude Include="mercs No Account.h" />
<ClInclude Include="mercs.h" />
<ClInclude Include="MilitiaInterface.h" />
<ClInclude Include="MilitiaWebsite.h" />
<ClInclude Include="personnel.h" />
<ClInclude Include="PMC.h" />
<ClInclude Include="PostalService.h" />
@@ -119,6 +122,7 @@
<ClCompile Include="AimMembers.cpp" />
<ClCompile Include="AimPolicies.cpp" />
<ClCompile Include="AimSort.cpp" />
<ClCompile Include="BaseTable.cpp" />
<ClCompile Include="BobbyR.cpp" />
<ClCompile Include="BobbyRAmmo.cpp" />
<ClCompile Include="BobbyRArmour.cpp" />
@@ -186,6 +190,8 @@
<ClCompile Include="mercs Files.cpp" />
<ClCompile Include="mercs No Account.cpp" />
<ClCompile Include="mercs.cpp" />
<ClCompile Include="MilitiaInterface.cpp" />
<ClCompile Include="MilitiaWebsite.cpp" />
<ClCompile Include="personnel.cpp" />
<ClCompile Include="PMC.cpp" />
<ClCompile Include="PostalService.cpp" />
+18
View File
@@ -267,6 +267,15 @@
<ClInclude Include="IMP Gear Entrance.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="BaseTable.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="MilitiaInterface.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="MilitiaWebsite.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="aim.cpp">
@@ -548,5 +557,14 @@
<ClCompile Include="IMP Gear Entrance.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="BaseTable.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="MilitiaInterface.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="MilitiaWebsite.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>
+642
View File
@@ -0,0 +1,642 @@
/**
* @file
* @author Flugente (bears-pit.com)
*/
#include "MilitiaInterface.h"
#include "Font.h"
#include "laptop.h"
#include "Cursors.h"
#include "Utilities.h"
#include "vobject.h"
#include "WCheck.h"
#include "line.h"
#include "WordWrap.h"
#include "input.h" // for gfLeftButtonState
#include "personnel.h"
#include "Animation Data.h"
#include "Text.h"
#include "MilitiaWebsite.h"
#include "Game Clock.h"
#include "Militia Control.h"
#include "Town Militia.h"
#include "Interface Items.h"
#include "Interface.h" // for DIRTYLEVEL2
extern BOOLEAN gfMilitiaWebsiteMainRedraw;
UINT32 guTraitImages = 0;
MilitiaServiceRecordTable::MilitiaServiceRecordTable( )
: BaseTable( )
{
}
void
MilitiaServiceRecordTable::Init( UINT16 sX, UINT16 sY, UINT16 sX_End, UINT16 sY_End )
{
SetColorLine( Get16BPPColor( FROMRGB( 128, 128, 128 ) ) );
SetColorLineShadow( Get16BPPColor( FROMRGB( 255, 255, 255 ) ) );
SetColorMarked( Get16BPPColor( FROMRGB( 200, 169, 87 ) ) );
SetColorHighLight( Get16BPPColor( FROMRGB( 235, 222, 171 ) ) );
BaseTable::Init( sX, sY, sX_End, sY_End );
}
void
MilitiaServiceRecordTable::Create( UINT16 sX, UINT16 sY, UINT16 sX_End, UINT16 sY_End )
{
Destroy( );
Init( sX, sY, sX_End, sY_End );
TestTableTemplate<2>::getInstance( ).Create( sX + 4, sY + 14, sX_End, sY_End );
RegisterMemberThingy( &TestTableTemplate<2>::getInstance( ) );
}
void
MilitiaServiceRecordTable::Destroy( )
{
if ( !IsInit( ) )
return;
BaseTable::Destroy( );
}
void
MilitiaServiceRecordTable::Display( )
{
if ( !IsInit( ) )
return;
DestroyMouseRegions( );
SetFontShadow( NO_SHADOW );
CHAR16 sText[800];
swprintf( sText, L"" );
UINT16 usPosX = GetX( ) + 10;
UINT16 usPosY = GetY( ) + 10;
MILITIA militia;
if ( GetMilitia( mMilitiaId, &militia ) )
{
TestTableTemplate<2>::getInstance( ).ClearColumnDataProvider( );
ColumnDataProvider namcol( szIdividualMilitiaWebsiteText[0] );
namcol.SetMethodString( OperationText );
namcol.SetNumberOfEntries( militia.history.size( ) );
namcol.SetCallBackType( ColumnDataProvider::CDP_MILITIADETAIL );
TestTableTemplate<2>::getInstance( ).AddColumnDataProvider( namcol );
TestTableTemplate<2>::getInstance( ).CalcRows( );
BaseTable::Display();
}
}
void
MilitiaServiceRecordTable::SetRefresh( )
{
gfMilitiaWebsiteMainRedraw = TRUE;
}
/////////////////////////////////////////////////////
MilitiaPersonalDataTable::MilitiaPersonalDataTable( )
: TestPanel( )
, mButtonFire(-1)
, mButtonFireCreated(FALSE)
{
}
void
MilitiaPersonalDataTable::Init( UINT16 sX, UINT16 sY, UINT16 sX_End, UINT16 sY_End )
{
SetColorLine( Get16BPPColor( FROMRGB( 128, 128, 128 ) ) );
SetColorLineShadow( Get16BPPColor( FROMRGB( 255, 255, 255 ) ) );
SetColorMarked( Get16BPPColor( FROMRGB( 200, 169, 87 ) ) );
SetColorHighLight( Get16BPPColor( FROMRGB( 235, 222, 171 ) ) );
TestPanel::Init( sX, sY, sX_End, sY_End );
}
////// callback for buttons ////////
void
MilitiaPersonalDataTableFireConfirmationCallback( UINT8 val )
{
if ( val == MSG_BOX_RETURN_YES )
{
MILITIA militia;
if ( GetMilitia( gusCurrentMilitia, &militia ) )
{
if ( !(militia.flagmask & (MILITIAFLAG_DEAD | MILITIAFLAG_FIRED)) )
{
militia.Fire();
UpdateMilitia( militia );
INT8 type = SoldierClassToMilitiaRank( militia.soldierclass);
if ( type > -1 )
{
StrategicRemoveMilitiaFromSector( SECTORX( militia.sector ), SECTORY( militia.sector ), (UINT8)type, 1 );
ResetMilitia();
}
militiaindividualmainwidget.SetRefresh();
}
}
}
}
void MilitiaPersonalDataTableFireCallback( GUI_BUTTON *btn, INT32 reason )
{
if ( reason & MSYS_CALLBACK_REASON_LBUTTON_UP )
{
MILITIA militia;
if ( GetMilitia( gusCurrentMilitia, &militia ) )
{
if ( !(militia.flagmask & (MILITIAFLAG_DEAD | MILITIAFLAG_FIRED)) )
{
CHAR16 sString[256];
swprintf( sString, szIdividualMilitiaWebsiteText[1], militia.GetName( ) );
DoLowerScreenIndependantMessageBox( sString, MSG_BOX_FLAG_YESNO, MilitiaPersonalDataTableFireConfirmationCallback );
}
}
}
}
////// callback for buttons ////////
void
MilitiaPersonalDataTable::Create( UINT16 sX, UINT16 sY, UINT16 sX_End, UINT16 sY_End )
{
Destroy( );
Init( sX, sY, sX_End, sY_End );
}
void
MilitiaPersonalDataTable::Destroy( )
{
if ( !IsInit( ) )
return;
if ( mButtonFireCreated )
{
RemoveButton( mButtonFire );
mButtonFireCreated = FALSE;
}
TestPanel::Destroy( );
}
void
MilitiaPersonalDataTable::Display( )
{
if ( !IsInit( ) )
return;
DestroyMouseRegions( );
MILITIA militia;
if ( GetMilitia( mMilitiaId, &militia ) )
{
CHAR16 sText[800];
swprintf( sText, L"" );
UINT16 usPosX = GetX( ) + 10;
UINT16 usPosY = GetY( ) + 10;
// show image of militia with correct visuals
{
VOBJECT_DESC VObjectDesc;
HVOBJECT hHandle;
UINT32 uiGraphicHandle;
BOOLEAN success = TRUE;
// load it
VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE;
// Pick images based on body type
switch ( militia.bodytype )
{
case REGMALE: FilenameForBPP( "Laptop\\IMPSmallMercImages.sti", VObjectDesc.ImageFile ); break;
case BIGMALE: FilenameForBPP( "Laptop\\IMPBigMercImages.sti", VObjectDesc.ImageFile ); break;
case STOCKYMALE: FilenameForBPP( "Laptop\\IMPBigMercImages.sti", VObjectDesc.ImageFile ); break;
case REGFEMALE: FilenameForBPP( "Laptop\\IMPFemaleMercImages.sti", VObjectDesc.ImageFile ); break;
default:
success = FALSE;
break;
}
// only show images if they can be loaded
if ( success )
{
// safety check if loaded
CHECKV( AddVideoObject( &VObjectDesc, &uiGraphicHandle ) );
// Get it
GetVideoObject( &hHandle, uiGraphicHandle );
if ( hHandle )
{
UINT8 vest = GREENVEST;
UINT8 pants = BEIGEPANTS;
if ( militia.soldierclass == SOLDIER_CLASS_REG_MILITIA )
vest = JEANVEST;
else if ( militia.soldierclass == SOLDIER_CLASS_ELITE_MILITIA )
vest = BLUEVEST;
// show background first
BltVideoObject( FRAME_BUFFER, hHandle, 0, usPosX, usPosY, VO_BLT_SRCTRANSPARENCY, NULL );
// show skin (1 - 4)
BltVideoObject( FRAME_BUFFER, hHandle, (militia.skin + 1), usPosX, usPosY, VO_BLT_SRCTRANSPARENCY, NULL );
// show head (5 - 9)
BltVideoObject( FRAME_BUFFER, hHandle, (militia.hair + 5), usPosX, usPosY, VO_BLT_SRCTRANSPARENCY, NULL );
// show vest (10 - 20)
BltVideoObject( FRAME_BUFFER, hHandle, (vest + 10), usPosX, usPosY, VO_BLT_SRCTRANSPARENCY, NULL );
// show pants (21 - 26)
BltVideoObject( FRAME_BUFFER, hHandle, (pants + 21), usPosX, usPosY, VO_BLT_SRCTRANSPARENCY, NULL );
DeleteVideoObjectFromIndex( uiGraphicHandle );
}
}
}
usPosX += 120;
SetFontShadow( NO_SHADOW );
if ( militia.flagmask & MILITIAFLAG_DEAD )
{
swprintf( sText, szIdividualMilitiaWebsiteText[5] );
DrawTextToScreen( sText, usPosX, usPosY + 5, GetWidth( ), FONT12ARIAL, FONT_MCOLOR_RED, FONT_MCOLOR_BLACK, FALSE, 0 );
usPosY += 20;
}
else if ( militia.flagmask & MILITIAFLAG_FIRED )
{
swprintf( sText, szIdividualMilitiaWebsiteText[6] );
DrawTextToScreen( sText, usPosX, usPosY + 5, GetWidth( ), FONT12ARIAL, FONT_MCOLOR_DKGRAY, FONT_MCOLOR_BLACK, FALSE, 0 );
usPosY += 20;
}
else
{
swprintf( sText, szIdividualMilitiaWebsiteText[7] );
DrawTextToScreen( sText, usPosX, usPosY + 5, GetWidth( ), FONT12ARIAL, FONT_MCOLOR_LTGREEN, FONT_MCOLOR_BLACK, FALSE, 0 );
usPosY += 20;
}
if ( gGameExternalOptions.fIndividualMilitia_ManageHealth )
{
swprintf( sText, szIdividualMilitiaWebsiteText[15], militia.healthratio );
DrawTextToScreen( sText, usPosX, usPosY + 5, GetWidth( ), FONT12ARIAL, 2, FONT_MCOLOR_BLACK, FALSE, 0 );
usPosY += 20;
}
swprintf( sText, szIdividualMilitiaWebsiteText[3], militia.GetWage( ), militia.age );
DrawTextToScreen( sText, usPosX, usPosY + 5, GetWidth( ), FONT12ARIAL, 2, FONT_MCOLOR_BLACK, FALSE, 0 );
usPosY += 20;
swprintf( sText, szIdividualMilitiaWebsiteText[4], militia.kills, militia.assists );
DrawTextToScreen( sText, usPosX, usPosY + 5, GetWidth( ), FONT12ARIAL, 2, FONT_MCOLOR_BLACK, FALSE, 0 );
usPosY += 20;
usPosY += 4;
usPosX -= 2;
// button for firing this guy
if ( mButtonFireCreated )
{
RemoveButton( mButtonFire );
mButtonFireCreated = FALSE;
}
// if we can still fire this guy, set up the button
if ( !(militia.flagmask & (MILITIAFLAG_DEAD | MILITIAFLAG_FIRED)) )
{
// we can't fire someone if they are in combat
if ( SectorOursAndPeaceful( SECTORX( militia.sector ), SECTORY( militia.sector ), 0 ) )
{
mButtonFire = CreateTextButton( szIdividualMilitiaWebsiteText[8], FONT12ARIAL, FONT_YELLOW, FONT_BLACK, BUTTON_USE_DEFAULT,
usPosX, usPosY, 120, 20, BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, DEFAULT_MOVE_CALLBACK, MilitiaPersonalDataTableFireCallback );
mButtonFireCreated = TRUE;
}
else
{
mButtonFire = CreateTextButton( szIdividualMilitiaWebsiteText[8], FONT12ARIAL, FONT_RED, FONT_BLACK, BUTTON_USE_DEFAULT,
usPosX, usPosY, 120, 20, BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, DEFAULT_MOVE_CALLBACK, NULL );
mButtonFireCreated = TRUE;
}
}
SetFontShadow( NO_SHADOW );
}
BaseTable::Display( );
}
void
MilitiaPersonalDataTable::SetRefresh( )
{
gfMilitiaWebsiteMainRedraw = TRUE;
}
void
MilitiaPersonalDataTable::DestroyMouseRegions( )
{
if ( !IsInit( ) )
return;
if ( mButtonFireCreated )
{
RemoveButton( mButtonFire );
mButtonFireCreated = FALSE;
}
BaseTable::DestroyMouseRegions( );
}
/////////////////////////////////////////////
MilitiaPersonalInventoryTable::MilitiaPersonalInventoryTable( )
: TestPanel( )
{
}
void
MilitiaPersonalInventoryTable::Init( UINT16 sX, UINT16 sY, UINT16 sX_End, UINT16 sY_End )
{
SetColorLine( Get16BPPColor( FROMRGB( 128, 128, 128 ) ) );
SetColorLineShadow( Get16BPPColor( FROMRGB( 255, 255, 255 ) ) );
SetColorMarked( Get16BPPColor( FROMRGB( 200, 169, 87 ) ) );
SetColorHighLight( Get16BPPColor( FROMRGB( 235, 222, 171 ) ) );
TestPanel::Init( sX, sY, sX_End, sY_End );
}
void
MilitiaPersonalInventoryTable::Create( UINT16 sX, UINT16 sY, UINT16 sX_End, UINT16 sY_End )
{
Destroy( );
Init( sX, sY, sX_End, sY_End );
}
void
MilitiaPersonalInventoryTable::Destroy( )
{
if ( !IsInit( ) )
return;
TestPanel::Destroy( );
}
void
MilitiaPersonalInventoryTable::Display( )
{
if ( !IsInit( ) )
return;
DestroyMouseRegions( );
SetFontShadow( NO_SHADOW );
CHAR16 sText[800];
swprintf( sText, L"" );
UINT16 usPosX = GetX( ) + 10;
UINT16 usPosY = GetY( ) + 10;
SOLDIERTYPE* pSoldier = GetUsedSoldierToIndividualMilitia( mMilitiaId );
if ( pSoldier )
{
SetFontShadow( DEFAULT_SHADOW );
for ( UINT8 pocketIndex = HELMETPOS; pocketIndex < NUM_INV_SLOTS; ++pocketIndex )
{
OBJECTTYPE* pObj = &(pSoldier)->inv[pocketIndex];
if ( pObj == NULL || pObj->ubNumberOfObjects == NOTHING || pObj->usItem == NOTHING )
continue;
ColorFillVideoSurfaceArea( FRAME_BUFFER, usPosX, usPosY, usPosX + 60, usPosY + 23, Get16BPPColor( FROMRGB( 255, 255, 255 ) ) );
// do not use the pSoldier-pointer, as the displays look ugly (and some images might not be initialised here)
INVRenderItem( FRAME_BUFFER, NULL, pObj, usPosX, usPosY, 60, 23, DIRTYLEVEL2, NULL, (UINT8)0, FALSE, 0, 0 );
usPosY += 25;
if ( usPosY > GetY() + GetHeight() - 27 )
{
usPosX += 62;
usPosY = GetY( ) + 10;
}
}
}
else
{
MILITIA militia;
if( GetMilitia( mMilitiaId, &militia ) )
{
swprintf( sText, szIdividualMilitiaWebsiteText[16], militia.GetName( ) );
DrawTextToScreen( sText, usPosX, usPosY + 5, GetWidth( ), FONT12ARIAL, 2, FONT_MCOLOR_BLACK, FALSE, 0 );
usPosY += 20;
}
}
SetFontShadow( NO_SHADOW );
BaseTable::Display( );
}
void
MilitiaPersonalInventoryTable::SetRefresh( )
{
gfMilitiaWebsiteMainRedraw = TRUE;
}
void
MilitiaPersonalInventoryTable::DestroyMouseRegions( )
{
if ( !IsInit( ) )
return;
BaseTable::DestroyMouseRegions( );
}
/////
extern void GetFaceData( UINT32 aNum, UINT32& arImageLib, UINT16& arImage );
//extern void ItemImage( UINT32 usItem, UINT32& arImageLib, UINT16& arImage );
extern STR16 ItemLongNamegetter( UINT32 aNum );
MilitiaInidividualMainWidget::MilitiaInidividualMainWidget( )
: TestPanel( ),
mMilitiaId( 0 )
{
}
void
MilitiaInidividualMainWidget::Init( UINT16 sX, UINT16 sY, UINT16 sX_End, UINT16 sY_End )
{
SetColorLine( Get16BPPColor( FROMRGB( 128, 128, 128 ) ) );
SetColorLineShadow( Get16BPPColor( FROMRGB( 255, 255, 255 ) ) );
SetColorMarked( Get16BPPColor( FROMRGB( 200, 169, 87 ) ) );
SetColorHighLight( Get16BPPColor( FROMRGB( 235, 222, 171 ) ) );
BaseTable::Init( sX, sY, sX_End, sY_End );
}
void
MilitiaInidividualMainWidget::Create( UINT16 sX, UINT16 sY, UINT16 sX_End, UINT16 sY_End )
{
Destroy( );
Init( sX, sY, sX_End, sY_End );
TabBoxTemplate<1>::getInstance( ).Create( sX, sY + 30, sX_End, sY_End );
mPersonalDataPanel.Create( sX, sY + 50, sX_End, sY_End );
mPersonalDataPanel.SetName( szIdividualMilitiaWebsiteText[9] );
mPersonalData.Create( sX, sY + 50, sX_End, sY_End );
mPersonalDataPanel.RegisterMemberThingy( &mPersonalData );
mServiceRecordPanel.Create( sX, sY + 50, sX_End, sY_End );
mServiceRecordPanel.SetName( szIdividualMilitiaWebsiteText[10] );
mServiceRecord.Create( sX, sY + 50, sX_End, sY_End );
mServiceRecordPanel.RegisterMemberThingy( &mServiceRecord );
mItemPanel.Create( sX, sY + 50, sX_End, sY_End );
mItemPanel.SetName( szIdividualMilitiaWebsiteText[11] );
mItemsTable.Create( sX, sY + 50, sX_End, sY_End );
mItemPanel.RegisterMemberThingy( &mItemsTable );
TabBoxTemplate<1>::getInstance( ).RegisterMemberThingy( &mPersonalDataPanel );
TabBoxTemplate<1>::getInstance( ).RegisterMemberThingy( &mServiceRecordPanel );
TabBoxTemplate<1>::getInstance( ).RegisterMemberThingy( &mItemPanel );
RegisterMemberThingy( &TabBoxTemplate<1>::getInstance( ) );
}
template<> void TabBoxTemplate<1>::SetRefresh( ) { gfMilitiaWebsiteMainRedraw = TRUE; }
void
MilitiaInidividualMainWidget::Destroy( )
{
if ( !IsInit( ) )
return;
BaseTable::Destroy( );
}
void
MilitiaInidividualMainWidget::Display( )
{
if ( !IsInit( ) )
return;
DestroyMouseRegions( );
TestPanel::Display( );
SetFontShadow( NO_SHADOW );
MILITIA militia;
if ( GetMilitia( mMilitiaId, &militia ) )
{
CHAR16 sText[800];
swprintf( sText, L"" );
UINT16 usPosX = GetX( );
UINT16 usPosY = GetY( );
// face
UINT32 imagelib = 0;
UINT16 imageid = 0;
GetFaceData( mMilitiaId, imagelib, imageid );
BltVideoObjectFromIndex( FRAME_BUFFER, imagelib, imageid, usPosX + 4, usPosY + 4, VO_BLT_SRCTRANSPARENCY, NULL );
usPosX += 44;
usPosY += 8;
// name
swprintf( sText, L"%s - %s", militia.GetName( ), militia.GetSector( ) );
DrawTextToScreen( sText, usPosX, usPosY + 5, GetWidth( ), FONT12ARIAL, 2, FONT_MCOLOR_BLACK, FALSE, 0 );
usPosX += 7 * wcslen( sText );
/*// gun
ItemImage( mMilitiaId, imagelib, imageid );
BltVideoObjectFromIndex( FRAME_BUFFER, imagelib, imageid, usPosX + 4, usPosY - 3, VO_BLT_SRCTRANSPARENCY, NULL );
usPosX += 90;*/
//swprintf( sText, ItemLongNamegetter( mMilitiaId ) );
//DrawTextToScreen( sText, usPosX, usPosY + 5, GetWidth( ), FONT12ARIAL, 2, FONT_MCOLOR_BLACK, FALSE, 0 );
//usPosX += 7 * wcslen( sText );
usPosY += 30;
}
mCloseImage = LoadButtonImage( "INTERFACE\\skilltree.sti", 71, 71, 71, 71, 71 );
// save changes
mCloseButton = QuickCreateButton( mCloseImage,
GetX( ) + GetWidth( ) - 26, GetY( ) + 4,
BUTTON_TOGGLE, MSYS_PRIORITY_HIGHEST,
MSYS_NO_CALLBACK,
CloseButtonCallback );
mCloseButtonDefined = TRUE;
}
void
MilitiaInidividualMainWidget::SetRefresh( )
{
gfMilitiaWebsiteMainRedraw = TRUE;
}
void
MilitiaInidividualMainWidget::DestroyMouseRegions( )
{
if ( mCloseButtonDefined )
{
RemoveButton( mCloseButton );
UnloadButtonImage( mCloseImage );
mCloseButtonDefined = FALSE;
}
TestPanel::DestroyMouseRegions( );
}
extern BOOLEAN gfMilitiaDetailsOpen;
void
MilitiaInidividualMainWidget::CloseButtonCallback( GUI_BUTTON * btn, INT32 iReason )
{
if ( iReason & MSYS_CALLBACK_REASON_INIT )
{
}
else if ( iReason & MSYS_CALLBACK_REASON_LBUTTON_UP )
{
militiaindividualmainwidget.SetMouseRegionActive( FALSE );
militiaindividualmainwidget.DestroyMouseRegions( );
TestTableTemplate<3>::getInstance( ).SetMouseRegionActive( TRUE );
gfMilitiaDetailsOpen = FALSE;
TestTableTemplate<3>::getInstance( ).SetRefresh( );
militiaindividualmainwidget.SetRefresh( );
}
else if ( iReason & MSYS_CALLBACK_REASON_RBUTTON_UP )
{
}
}
MilitiaInidividualMainWidget militiaindividualmainwidget;
+233
View File
@@ -0,0 +1,233 @@
#ifndef __MILITIAINTERFACE_H
#define __MILITIAINTERFACE_H
/**
* @file
* @author Flugente (bears-pit.com)
*/
#include "BaseTable.h"
#include "MilitiaIndividual.h"
extern UINT32 gusCurrentMilitia;
// the data of an individual militia is displayed on its own widget. There are several parts:
// - face, name, traits and gun are displayed on top. This data is also displayed for each militia in a list
// - Below that there is a tabbox with 3 entries:
// - On the service record, we see their current body, stats & health and their history - which battles they took part in, and where and when they were recruited
// Clicking on a history item links us to to campaign history. The history items are in a table.
// - The skilltree is a separate tab. Here we can choose traits and promote militia, provided they have sufficient experience (currently not used)
// - The inventory is a separate tab as well.
class MilitiaServiceRecordTable : public BaseTable
{
public:
MilitiaServiceRecordTable( );
/*
* Initialise variables. Called after each creation which allows moving a dropdown
*/
virtual void Init( UINT16 sX, UINT16 sY, UINT16 sX_End, UINT16 sY_End );
/*
* Create a Dropdown with upper left coordinates
*/
virtual void Create( UINT16 sX, UINT16 sY, UINT16 sX_End, UINT16 sY_End );
/*
* Destroy Dropdown, for example once a website isn't displayed anymore
*/
virtual void Destroy( );
/*
* Display DropDownBase. Use this when refreshing
*/
virtual void Display( );
/*
* Sometimes a refresh inside the class isn't enough - best example is closing the dropdown area, after which the previous background cannot be restored by this class.
* In that case, the background and this class has to be redrawn.
* This function is called internally whenever such a refresh is necessary.
* It has to be defined in derived classes and should notify your dialogues to redraw at appropriate times
*
* This function has to be implemented!
*/
virtual void SetRefresh( );
void SetId( UINT32 usId ) { mMilitiaId = usId; }
private:
// declare but don't define
MilitiaServiceRecordTable( MilitiaServiceRecordTable const& );
void operator=(MilitiaServiceRecordTable const&);
private:
UINT32 mMilitiaId; // the id of the militia whose data we display
};
class MilitiaPersonalDataTable : public TestPanel
{
public:
MilitiaPersonalDataTable( );
/*
* Initialise variables. Called after each creation which allows moving a dropdown
*/
virtual void Init( UINT16 sX, UINT16 sY, UINT16 sX_End, UINT16 sY_End );
/*
* Create a Dropdown with upper left coordinates
*/
virtual void Create( UINT16 sX, UINT16 sY, UINT16 sX_End, UINT16 sY_End );
/*
* Destroy Dropdown, for example once a website isn't displayed anymore
*/
virtual void Destroy( );
/*
* Display DropDownBase. Use this when refreshing
*/
virtual void Display( );
/*
* Sometimes a refresh inside the class isn't enough - best example is closing the dropdown area, after which the previous background cannot be restored by this class.
* In that case, the background and this class has to be redrawn.
* This function is called internally whenever such a refresh is necessary.
* It has to be defined in derived classes and should notify your dialogues to redraw at appropriate times
*
* This function has to be implemented!
*/
virtual void SetRefresh( );
virtual void DestroyMouseRegions( );
void SetId( UINT32 usId ) { mMilitiaId = usId; }
private:
// declare but don't define
MilitiaPersonalDataTable( MilitiaPersonalDataTable const& );
void operator=(MilitiaPersonalDataTable const&);
private:
UINT32 mMilitiaId; // the id of the militia whose data we display
INT32 mButtonFire;
BOOLEAN mButtonFireCreated;
};
class MilitiaPersonalInventoryTable : public TestPanel
{
public:
MilitiaPersonalInventoryTable( );
/*
* Initialise variables. Called after each creation which allows moving a dropdown
*/
virtual void Init( UINT16 sX, UINT16 sY, UINT16 sX_End, UINT16 sY_End );
/*
* Create a Dropdown with upper left coordinates
*/
virtual void Create( UINT16 sX, UINT16 sY, UINT16 sX_End, UINT16 sY_End );
/*
* Destroy Dropdown, for example once a website isn't displayed anymore
*/
virtual void Destroy( );
/*
* Display DropDownBase. Use this when refreshing
*/
virtual void Display( );
/*
* Sometimes a refresh inside the class isn't enough - best example is closing the dropdown area, after which the previous background cannot be restored by this class.
* In that case, the background and this class has to be redrawn.
* This function is called internally whenever such a refresh is necessary.
* It has to be defined in derived classes and should notify your dialogues to redraw at appropriate times
*
* This function has to be implemented!
*/
virtual void SetRefresh( );
virtual void DestroyMouseRegions( );
void SetId( UINT32 usId ) { mMilitiaId = usId; }
private:
// declare but don't define
MilitiaPersonalInventoryTable( MilitiaPersonalInventoryTable const& );
void operator=(MilitiaPersonalInventoryTable const&);
private:
UINT32 mMilitiaId; // the id of the militia whose data we display
};
class MilitiaInidividualMainWidget : public TestPanel
{
public:
MilitiaInidividualMainWidget( );
/*
* Initialise variables. Called after each creation which allows moving a dropdown
*/
virtual void Init( UINT16 sX, UINT16 sY, UINT16 sX_End, UINT16 sY_End );
/*
* Create a Dropdown with upper left coordinates
*/
virtual void Create( UINT16 sX, UINT16 sY, UINT16 sX_End, UINT16 sY_End );
/*
* Destroy Dropdown, for example once a website isn't displayed anymore
*/
virtual void Destroy( );
/*
* Display DropDownBase. Use this when refreshing
*/
virtual void Display( );
/*
* Sometimes a refresh inside the class isn't enough - best example is closing the dropdown area, after which the previous background cannot be restored by this class.
* In that case, the background and this class has to be redrawn.
* This function is called internally whenever such a refresh is necessary.
* It has to be defined in derived classes and should notify your dialogues to redraw at appropriate times
*
* This function has to be implemented!
*/
virtual void SetRefresh( );
virtual void DestroyMouseRegions( );
virtual void SetMouseRegionActive( BOOLEAN aVal ) { TabBoxTemplate<1>::getInstance( ).SetMouseRegionActive( aVal ); }
void SetId( UINT32 usId ) { mMilitiaId = usId; gusCurrentMilitia = usId; mPersonalData.SetId( usId ); mServiceRecord.SetId( usId ); mItemsTable.SetId( usId ); }
static void CloseButtonCallback( GUI_BUTTON * btn, INT32 iReason );
private:
// declare but don't define
MilitiaInidividualMainWidget( MilitiaInidividualMainWidget const& );
void operator=(MilitiaInidividualMainWidget const&);
private:
UINT32 mMilitiaId; // the id of the militia whose data we display
TestPanel mPersonalDataPanel;
MilitiaPersonalDataTable mPersonalData;
TestPanel mServiceRecordPanel;
MilitiaServiceRecordTable mServiceRecord;
TestPanel mItemPanel;
MilitiaPersonalInventoryTable mItemsTable;
// close buttons
BOOLEAN mCloseButtonDefined;
INT32 mCloseButton;
UINT32 mCloseImage;
};
extern MilitiaInidividualMainWidget militiaindividualmainwidget;
#endif
+858
View File
@@ -0,0 +1,858 @@
/**
* @file
* @author Flugente (bears-pit.com)
*/
#ifdef PRECOMPILEDHEADERS
#include "Laptop All.h"
#else
#include "laptop.h"
#include "insurance.h"
#include "insurance Contract.h"
#include "WCheck.h"
#include "Utilities.h"
#include "WordWrap.h"
#include "Cursors.h"
#include "Line.h"
#include "Insurance Text.h"
#include "Encrypted File.h"
#include "Text.h"
#include "Multi Language Graphic Utils.h"
#include "MilitiaWebsite.h"
#include "random.h"
#include "Interface.h"
#include "Soldier Add.h"
#include "Soldier Profile.h"
#include "DropDown.h"
#include "Overhead.h"
#include "Map Screen Interface.h"
#include "Quests.h"
#include "finances.h"
#include "Game Clock.h"
#include "Animation Data.h"
#include "SaveLoadGame.h"
#include "GameVersion.h"
#include "message.h"
#include "Game Event Hook.h"
#include "militia control.h"
#include "Town Militia.h"
#include "Strategic Town Loyalty.h"
#include "BaseTable.h"
#include "Soldier Profile.h"
#include "Auto Resolve.h"
#include "MilitiaIndividual.h"
#include "Animation Data.h"
#include "MilitiaInterface.h"
#include "Interface Items.h"
#include "InterfaceItemImages.h"
#include "CampaignStats.h"
#endif
#define MERCOMP_FONT_COLOR 2
#define CAMPHIS_FONT_COLOR_RED FONT_MCOLOR_RED
#define CAMPHIS_FONT_BIG FONT14ARIAL
#define CAMPHIS_FONT_MED FONT12ARIAL
#define CAMPHIS_FONT_SMALL FONT10ARIAL
#define MERCOMP_FONT_SHADOW FONT_MCOLOR_WHITE
#define CAMPAIGN_HISTORY_LINK_START_X LAPTOP_SCREEN_UL_X
#define CAMPAIGN_HISTORY_LINK_START_Y LAPTOP_SCREEN_WEB_UL_Y + 5
#define CAMPAIGN_HISTORY_LINK_TEXT_WIDTH 107
#define CAMPAIGN_HISTORY_LINK_STEP_Y 14
#define BACKGROUND_WIDTH 125
#define CAMPAIGN_HISTORY_BACKGROUND_HEIGHT 100
#define CAMPAIGN_HISTORY_BIG_TITLE_X 115 + LAPTOP_SCREEN_UL_X
#define CAMPAIGN_HISTORY_BIG_TITLE_Y 10 + LAPTOP_SCREEN_WEB_UL_Y
#define CAMPAIGN_HISTORY_SUBTITLE_X CAMPAIGN_HISTORY_BIG_TITLE_X
#define CAMPAIGN_HISTORY_SUBTITLE_Y CAMPAIGN_HISTORY_BIG_TITLE_Y + 20
#define NUM_LINKS 3
#define MCA_START_CONTENT_Y (LAPTOP_SCREEN_WEB_UL_Y + NUM_LINKS * 17)
extern UINT32 guiInsuranceBackGround;
extern UINT32 guiInsuranceSmallTitleImage;
extern UINT32 guiInsuranceBigRedLineImage;
extern UINT32 guiMercCompareBulletImage;
extern UINT32 guiMercCompareLogoImage;
extern UINT32 gusMostImportantPage;
//link to the various pages
MOUSE_REGION gLinkRegion_MilitiaWebsite[NUM_LINKS];
UINT32 gARFacesLib = 0;
void SelectLinkRegionCallBack_MilitiaWebsite( MOUSE_REGION * pRegion, INT32 iReason )
{
if ( iReason & MSYS_CALLBACK_REASON_INIT )
{
}
else if ( iReason & MSYS_CALLBACK_REASON_LBUTTON_UP )
{
UINT32 uiLink = MSYS_GetRegionUserData( pRegion, 0 );
if ( uiLink == 0 )
guiCurrentLaptopMode = LAPTOP_MODE_MILITIAROSTER_MAIN;
else if ( uiLink == 1 )
guiCurrentLaptopMode = LAPTOP_MODE_MILITIAROSTER_ABOUT;
else if ( uiLink == 2 )
guiCurrentLaptopMode = LAPTOP_MODE_BROKEN_LINK;
}
else if ( iReason & MSYS_CALLBACK_REASON_RBUTTON_UP )
{
}
}
void InitDefaults_MilitiaWebsite( )
{
VOBJECT_DESC VObjectDesc;
// load the Insurance bullet graphic and add it
VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE;
FilenameForBPP( "LAPTOP\\bullet.sti", VObjectDesc.ImageFile );
CHECKV( AddVideoObject( &VObjectDesc, &guiMercCompareBulletImage ) );
// load the Flower Account Box graphic and add it
VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE;
FilenameForBPP( "LAPTOP\\BackGroundTile.sti", VObjectDesc.ImageFile );
CHECKV( AddVideoObject( &VObjectDesc, &guiInsuranceBackGround ) );
// load the red bar on the side of the page and add it
VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE;
FilenameForBPP( "LAPTOP\\LargeBar.sti", VObjectDesc.ImageFile );
CHECKV( AddVideoObject( &VObjectDesc, &guiInsuranceBigRedLineImage ) );
VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE;
FilenameForBPP( "LAPTOP\\PressLogos.sti", VObjectDesc.ImageFile );
CHECKV( AddVideoObject( &VObjectDesc, &guiMercCompareLogoImage ) );
VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE;
FilenameForBPP( "Interface\\SmFaces.sti", VObjectDesc.ImageFile );
CHECKV( AddVideoObject( &VObjectDesc, &gARFacesLib ) );
UINT16 usPosX = CAMPAIGN_HISTORY_LINK_START_X;
UINT16 usPosY = CAMPAIGN_HISTORY_LINK_START_Y;
for ( int i = 0; i<NUM_LINKS; ++i )
{
MSYS_DefineRegion( &gLinkRegion_MilitiaWebsite[i], usPosX, usPosY, (UINT16)(usPosX + CAMPAIGN_HISTORY_LINK_TEXT_WIDTH), usPosY + CAMPAIGN_HISTORY_LINK_STEP_Y, MSYS_PRIORITY_HIGH,
CURSOR_WWW, MSYS_NO_CALLBACK, SelectLinkRegionCallBack_MilitiaWebsite );
MSYS_AddRegion( &gLinkRegion_MilitiaWebsite[i] );
MSYS_SetRegionUserData( &gLinkRegion_MilitiaWebsite[i], 0, i );
usPosY += CAMPAIGN_HISTORY_LINK_STEP_Y;
}
}
void DisplayDefaults_MilitiaWebsite( )
{
HVOBJECT hPixHandle;
GetVideoObject( &hPixHandle, guiMercCompareLogoImage );
SetFontShadow( NO_SHADOW );
CHAR16 sText[800];
UINT16 usPosX = CAMPAIGN_HISTORY_LINK_START_X;
UINT16 usPosY = CAMPAIGN_HISTORY_LINK_START_Y;
WebPageTileBackground( 4, 4, BACKGROUND_WIDTH, CAMPAIGN_HISTORY_BACKGROUND_HEIGHT, guiInsuranceBackGround );
//Display the title slogan
swprintf( sText, szMilitiaWebSite[TEXT_MILITIAWEBSITE_WEBSITENAME] );
DrawTextToScreen( sText, CAMPAIGN_HISTORY_BIG_TITLE_X, CAMPAIGN_HISTORY_BIG_TITLE_Y, LAPTOP_SCREEN_LR_X - LAPTOP_SCREEN_UL_X, CAMPHIS_FONT_BIG, MERCOMP_FONT_COLOR, FONT_MCOLOR_BLACK, FALSE, 0 );
//Display the subtitle slogan
swprintf( sText, szMilitiaWebSite[TEXT_MILITIAWEBSITE_SLOGAN] );
DrawTextToScreen( sText, CAMPAIGN_HISTORY_SUBTITLE_X, CAMPAIGN_HISTORY_SUBTITLE_Y, 0, CAMPHIS_FONT_BIG, MERCOMP_FONT_COLOR, FONT_MCOLOR_BLACK, FALSE, 0 );
usPosX = CAMPAIGN_HISTORY_LINK_START_X;
usPosY = CAMPAIGN_HISTORY_LINK_START_Y;
for ( int i = 0; i<NUM_LINKS; ++i )
{
swprintf( sText, szMilitiaWebSite[TEXT_MILITIAWEBSITE_SUBSITE1 + i] );
DisplayWrappedString( usPosX, usPosY, CAMPAIGN_HISTORY_LINK_TEXT_WIDTH, 2, CAMPHIS_FONT_MED, MERCOMP_FONT_COLOR, sText, FONT_MCOLOR_BLACK, FALSE, 0 );
usPosY += CAMPAIGN_HISTORY_LINK_STEP_Y;
//Display the red bar under the link at the bottom. and the text
DisplaySmallColouredLineWithShadow( usPosX, usPosY - 2, LAPTOP_SCREEN_UL_X + CAMPAIGN_HISTORY_LINK_TEXT_WIDTH, usPosY - 2, FROMRGB( 255, 127, 0 ) );
}
// closing line that separates header from individual page
DisplaySmallColouredLineWithShadow( usPosX, usPosY - 2, LAPTOP_SCREEN_LR_X, usPosY - 2, FROMRGB( 255, 127, 0 ) );
usPosX = LAPTOP_SCREEN_LR_X - 60;
usPosY = CAMPAIGN_HISTORY_LINK_START_Y;
BltVideoObject( FRAME_BUFFER, hPixHandle, 4, usPosX, usPosY, VO_BLT_SRCTRANSPARENCY, NULL );
SetFontShadow( NO_SHADOW );
}
void RemoveDefaults_MilitiaWebsite( )
{
DeleteVideoObjectFromIndex( guiInsuranceBackGround );
DeleteVideoObjectFromIndex( guiInsuranceBigRedLineImage );
DeleteVideoObjectFromIndex( guiMercCompareBulletImage );
DeleteVideoObjectFromIndex( guiMercCompareLogoImage );
for ( int i = 0; i<NUM_LINKS; ++i )
MSYS_RemoveRegion( &gLinkRegion_MilitiaWebsite[i] );
}
////////////////////////// MAIN PAGE ////////////////////////////////
BOOLEAN gfMilitiaWebsiteMainRedraw = FALSE;
BOOLEAN gfMilitiaDetailsOpen = FALSE;
// filter data
BOOLEAN gfMilitiaWebsiteRedoFilters = FALSE;
enum InidivualMilitiaLifeState
{
IMLS_ALL,
IMLS_DEAD,
IMLS_ALIVE,
IMLS_FIRED
};
enum InidivualMilitiaRankState
{
IMRS_ALL,
IMRS_GREEN,
IMRS_REGULAR,
IMRS_ELITE
};
enum InidivualMilitiaOriginState
{
IMOS_ALL,
IMOS_ARULCO,
IMOS_PMC,
IMOS_DEFECTOR
};
CHAR16 gInidividualMilitiaWebsiteSectorNamesstr[256][10];
std::vector<std::pair<INT16, STR16> > GetMilitiaSectorDropVector( )
{
std::vector<std::pair<INT16, STR16> > sectorvector;
// 'Everywhere' is always an option
sectorvector.push_back( std::make_pair( -1, szIdividualMilitiaWebsiteFilterText_Sector[0] ) );
std::set<UINT8> sectorset;
for ( std::vector<MILITIA>::iterator it = gIndividualMilitiaVector.begin( ); it != gIndividualMilitiaVector.end( ); ++it )
{
sectorset.insert( (*it).sector );
}
for ( std::set<UINT8>::iterator it = sectorset.begin( ); it != sectorset.end(); ++it )
{
GetShortSectorString( SECTORX( (*it) ), SECTORY( (*it) ), gInidividualMilitiaWebsiteSectorNamesstr[(*it)] );
sectorvector.push_back( std::make_pair( (INT16)(*it), gInidividualMilitiaWebsiteSectorNamesstr[(*it)] ) );
}
return sectorvector;
}
// later on, make this an array with a vector for each sector
std::vector<UINT32> gIndividualMilitiaFilteredIdsVector;
void FilterIndividualMilitia( InidivualMilitiaLifeState aLifeState, InidivualMilitiaRankState aRankState, InidivualMilitiaOriginState aOriginState, INT16 aSector )
{
gIndividualMilitiaFilteredIdsVector.clear();
std::vector<MILITIA>::iterator itend = gIndividualMilitiaVector.end( );
for ( std::vector<MILITIA>::iterator it = gIndividualMilitiaVector.begin( ); it != itend; ++it )
{
if ( ( aLifeState == IMLS_DEAD && !((*it).flagmask & MILITIAFLAG_DEAD) )
|| (aLifeState == IMLS_ALIVE && ((*it).flagmask & MILITIAFLAG_DEAD)) )
continue;
if ( (aLifeState == IMLS_FIRED && !((*it).flagmask & MILITIAFLAG_FIRED))
|| (aLifeState != IMLS_FIRED && aLifeState != IMLS_ALL && ((*it).flagmask & MILITIAFLAG_FIRED)) )
continue;
if ( (aRankState == IMRS_GREEN && (*it).soldierclass != SOLDIER_CLASS_GREEN_MILITIA ) ||
(aRankState == IMRS_REGULAR && (*it).soldierclass != SOLDIER_CLASS_REG_MILITIA) ||
(aRankState == IMRS_ELITE && (*it).soldierclass != SOLDIER_CLASS_ELITE_MILITIA) )
continue;
if ( (aOriginState == IMOS_ARULCO && (*it).origin != MO_ARULCO) ||
(aOriginState == IMOS_PMC && (*it).origin != MO_PMC) ||
(aOriginState == IMOS_DEFECTOR && (*it).origin != MO_DEFECTOR) )
continue;
if ( aSector > 0 && (UINT8)aSector != (*it).sector )
continue;
gIndividualMilitiaFilteredIdsVector.push_back( (*it).id );
}
}
// on dropdown change, redraw and redo filter selection
template<> void DropDownTemplate<DROPDOWN_MILTIAWEBSITE_FILTER_DEAD>::SetRefresh( ) { gfMilitiaWebsiteMainRedraw = TRUE; gfMilitiaWebsiteRedoFilters = TRUE; }
template<> void DropDownTemplate<DROPDOWN_MILTIAWEBSITE_FILTER_RANK>::SetRefresh( ) { gfMilitiaWebsiteMainRedraw = TRUE; gfMilitiaWebsiteRedoFilters = TRUE; }
template<> void DropDownTemplate<DROPDOWN_MILTIAWEBSITE_FILTER_ORIGIN>::SetRefresh( ) { gfMilitiaWebsiteMainRedraw = TRUE; gfMilitiaWebsiteRedoFilters = TRUE; }
template<> void DropDownTemplate<DROPDOWN_MILTIAWEBSITE_FILTER_SECTOR>::SetRefresh( ) { gfMilitiaWebsiteMainRedraw = TRUE; gfMilitiaWebsiteRedoFilters = TRUE; }
BOOLEAN EnterMilitiaWebsiteMain( )
{
InitDefaults_MilitiaWebsite( );
if ( !gGameExternalOptions.fIndividualMilitia )
return TRUE;
// we add several filter dropdowns here (otherwise this list will become tedious to use later on when there are hundreds of militia)
{
UINT16 usDropX = LAPTOP_SCREEN_UL_X + 4;
{
std::vector<std::pair<INT16, STR16> > filtervector;
filtervector.push_back( std::make_pair( (INT16)IMLS_ALL, szIdividualMilitiaWebsiteFilterText_Dead[0] ) );
filtervector.push_back( std::make_pair( (INT16)IMLS_DEAD, szIdividualMilitiaWebsiteFilterText_Dead[1] ) );
filtervector.push_back( std::make_pair( (INT16)IMLS_ALIVE, szIdividualMilitiaWebsiteFilterText_Dead[2] ) );
filtervector.push_back( std::make_pair( (INT16)IMLS_FIRED, szIdividualMilitiaWebsiteFilterText_Dead[3] ) );
if ( !filtervector.empty( ) )
{
DropDownTemplate<DROPDOWN_MILTIAWEBSITE_FILTER_DEAD>::getInstance( ).SetEntries( filtervector );
DropDownTemplate<DROPDOWN_MILTIAWEBSITE_FILTER_DEAD>::getInstance().SetSelectedEntryKey( IMLS_ALIVE );
DropDownTemplate<DROPDOWN_MILTIAWEBSITE_FILTER_DEAD>::getInstance( ).Create( usDropX, MCA_START_CONTENT_Y + 4 );
usDropX = DropDownTemplate<DROPDOWN_MILTIAWEBSITE_FILTER_DEAD>::getInstance( ).GetLastX( ) + 10;
}
else
{
DropDownTemplate<DROPDOWN_MILTIAWEBSITE_FILTER_DEAD>::getInstance().ClearEntries();
}
}
{
std::vector<std::pair<INT16, STR16> > filtervector;
filtervector.push_back( std::make_pair( (INT16)IMRS_ALL, szIdividualMilitiaWebsiteFilterText_Rank[0] ) );
filtervector.push_back( std::make_pair( (INT16)IMRS_GREEN, szIdividualMilitiaWebsiteFilterText_Rank[1] ) );
filtervector.push_back( std::make_pair( (INT16)IMRS_REGULAR, szIdividualMilitiaWebsiteFilterText_Rank[2] ) );
filtervector.push_back( std::make_pair( (INT16)IMRS_ELITE, szIdividualMilitiaWebsiteFilterText_Rank[3] ) );
if ( !filtervector.empty( ) )
{
DropDownTemplate<DROPDOWN_MILTIAWEBSITE_FILTER_RANK>::getInstance( ).SetEntries( filtervector );
DropDownTemplate<DROPDOWN_MILTIAWEBSITE_FILTER_RANK>::getInstance( ).SetSelectedEntryKey( IMRS_ALL );
DropDownTemplate<DROPDOWN_MILTIAWEBSITE_FILTER_RANK>::getInstance( ).Create( usDropX, MCA_START_CONTENT_Y + 4 );
usDropX = DropDownTemplate<DROPDOWN_MILTIAWEBSITE_FILTER_RANK>::getInstance( ).GetLastX( ) + 10;
}
else
{
DropDownTemplate<DROPDOWN_MILTIAWEBSITE_FILTER_RANK>::getInstance( ).ClearEntries( );
}
}
{
std::vector<std::pair<INT16, STR16> > filtervector;
filtervector.push_back( std::make_pair( (INT16)IMOS_ALL, szIdividualMilitiaWebsiteFilterText_Origin[0] ) );
filtervector.push_back( std::make_pair( (INT16)IMOS_ARULCO, szIdividualMilitiaWebsiteFilterText_Origin[1] ) );
filtervector.push_back( std::make_pair( (INT16)IMOS_PMC, szIdividualMilitiaWebsiteFilterText_Origin[2] ) );
filtervector.push_back( std::make_pair( (INT16)IMOS_DEFECTOR, szIdividualMilitiaWebsiteFilterText_Origin[3] ) );
if ( !filtervector.empty( ) )
{
DropDownTemplate<DROPDOWN_MILTIAWEBSITE_FILTER_ORIGIN>::getInstance( ).SetEntries( filtervector );
DropDownTemplate<DROPDOWN_MILTIAWEBSITE_FILTER_ORIGIN>::getInstance( ).SetSelectedEntryKey( IMOS_ALL );
DropDownTemplate<DROPDOWN_MILTIAWEBSITE_FILTER_ORIGIN>::getInstance( ).Create( usDropX, MCA_START_CONTENT_Y + 4 );
usDropX = DropDownTemplate<DROPDOWN_MILTIAWEBSITE_FILTER_ORIGIN>::getInstance( ).GetLastX( ) + 10;
}
else
{
DropDownTemplate<DROPDOWN_MILTIAWEBSITE_FILTER_ORIGIN>::getInstance( ).ClearEntries( );
}
}
{
std::vector<std::pair<INT16, STR16> > filtervector = GetMilitiaSectorDropVector();
if ( !filtervector.empty( ) )
{
DropDownTemplate<DROPDOWN_MILTIAWEBSITE_FILTER_SECTOR>::getInstance( ).SetEntries( filtervector );
DropDownTemplate<DROPDOWN_MILTIAWEBSITE_FILTER_SECTOR>::getInstance( ).SetSelectedEntryKey( -1 );
DropDownTemplate<DROPDOWN_MILTIAWEBSITE_FILTER_SECTOR>::getInstance( ).Create( usDropX, MCA_START_CONTENT_Y + 4 );
usDropX = DropDownTemplate<DROPDOWN_MILTIAWEBSITE_FILTER_SECTOR>::getInstance( ).GetLastX( ) + 10;
}
else
{
DropDownTemplate<DROPDOWN_MILTIAWEBSITE_FILTER_SECTOR>::getInstance( ).ClearEntries( );
}
}
}
INT16 key_dead = DropDownTemplate<DROPDOWN_MILTIAWEBSITE_FILTER_DEAD>::getInstance( ).GetSelectedEntryKey( );
INT16 key_rank = DropDownTemplate<DROPDOWN_MILTIAWEBSITE_FILTER_RANK>::getInstance( ).GetSelectedEntryKey( );
INT16 key_origin = DropDownTemplate<DROPDOWN_MILTIAWEBSITE_FILTER_ORIGIN>::getInstance( ).GetSelectedEntryKey( );
INT16 key_sector = DropDownTemplate<DROPDOWN_MILTIAWEBSITE_FILTER_SECTOR>::getInstance( ).GetSelectedEntryKey( );
// as we might filter out militia, we use a vector that contains all currently used militia IDs, and access data via that
FilterIndividualMilitia( (InidivualMilitiaLifeState)key_dead, (InidivualMilitiaRankState)key_rank, (InidivualMilitiaOriginState)key_origin, key_sector );
gTestPanel3.Create( LAPTOP_SCREEN_UL_X, MCA_START_CONTENT_Y, LAPTOP_SCREEN_LR_X, LAPTOP_SCREEN_WEB_LR_Y );
TestTableTemplate<3>::getInstance( ).Create( LAPTOP_SCREEN_UL_X + 4, MCA_START_CONTENT_Y + 44, LAPTOP_SCREEN_LR_X - 4, LAPTOP_SCREEN_WEB_LR_Y - 4 );
gTestPanel3.RegisterMemberThingy( &TestTableTemplate<3>::getInstance( ) );
// militia details (opens upon interacting with militia list)
militiaindividualmainwidget.Create( LAPTOP_SCREEN_UL_X + 50, MCA_START_CONTENT_Y + 40, LAPTOP_SCREEN_LR_X, LAPTOP_SCREEN_WEB_LR_Y );
gfMilitiaDetailsOpen = FALSE;
militiaindividualmainwidget.SetMouseRegionActive( FALSE );
TestTableTemplate<3>::getInstance( ).SetMouseRegionActive( TRUE );
return(TRUE);
}
void ExitMilitiaWebsiteMain( )
{
militiaindividualmainwidget.Destroy( );
DropDownTemplate<DROPDOWN_MILTIAWEBSITE_FILTER_DEAD>::getInstance( ).Destroy( );
DropDownTemplate<DROPDOWN_MILTIAWEBSITE_FILTER_RANK>::getInstance( ).Destroy( );
DropDownTemplate<DROPDOWN_MILTIAWEBSITE_FILTER_ORIGIN>::getInstance( ).Destroy( );
DropDownTemplate<DROPDOWN_MILTIAWEBSITE_FILTER_SECTOR>::getInstance( ).Destroy( );
gTestPanel3.Destroy( );
RemoveDefaults_MilitiaWebsite( );
DeleteVideoObjectFromIndex( gARFacesLib );
}
void HandleMilitiaWebsiteMain( )
{
if ( gfMilitiaWebsiteMainRedraw )
{
if ( gGameExternalOptions.fIndividualMilitia )
{
if ( gfMilitiaWebsiteRedoFilters )
{
INT16 key_dead = DropDownTemplate<DROPDOWN_MILTIAWEBSITE_FILTER_DEAD>::getInstance( ).GetSelectedEntryKey( );
INT16 key_rank = DropDownTemplate<DROPDOWN_MILTIAWEBSITE_FILTER_RANK>::getInstance( ).GetSelectedEntryKey( );
INT16 key_origin = DropDownTemplate<DROPDOWN_MILTIAWEBSITE_FILTER_ORIGIN>::getInstance( ).GetSelectedEntryKey( );
INT16 key_sector = DropDownTemplate<DROPDOWN_MILTIAWEBSITE_FILTER_SECTOR>::getInstance( ).GetSelectedEntryKey( );
// as we might filter out militia, we use a vector that contains all currently used militia IDs, and access data via that
FilterIndividualMilitia( (InidivualMilitiaLifeState)key_dead, (InidivualMilitiaRankState)key_rank, (InidivualMilitiaOriginState)key_origin, key_sector );
TestTableTemplate<3>::getInstance( ).Create( TestTableTemplate<3>::getInstance( ).GetX( ), TestTableTemplate<3>::getInstance( ).GetY( ),
TestTableTemplate<3>::getInstance( ).GetX( ) + TestTableTemplate<3>::getInstance( ).GetWidth( ),
TestTableTemplate<3>::getInstance( ).GetY( ) + TestTableTemplate<3>::getInstance( ).GetHeight() );
gfMilitiaWebsiteRedoFilters = FALSE;
}
}
RenderMilitiaWebsiteMain();
gfMilitiaWebsiteMainRedraw = FALSE;
}
}
void RenderMilitiaWebsiteMain( )
{
DisplayDefaults_MilitiaWebsite( );
SetFontShadow( NO_SHADOW );
if ( gGameExternalOptions.fIndividualMilitia )
{
gTestPanel3.Display( );
DropDownTemplate<DROPDOWN_MILTIAWEBSITE_FILTER_DEAD>::getInstance( ).Display( );
DropDownTemplate<DROPDOWN_MILTIAWEBSITE_FILTER_RANK>::getInstance( ).Display( );
DropDownTemplate<DROPDOWN_MILTIAWEBSITE_FILTER_ORIGIN>::getInstance( ).Display( );
DropDownTemplate<DROPDOWN_MILTIAWEBSITE_FILTER_SECTOR>::getInstance( ).Display( );
if ( gfMilitiaDetailsOpen )
militiaindividualmainwidget.Display( );
}
SetFontShadow( NO_SHADOW );
MarkButtonsDirty( );
RenderWWWProgramTitleBar( );
InvalidateRegion( LAPTOP_SCREEN_UL_X, LAPTOP_SCREEN_WEB_UL_Y, LAPTOP_SCREEN_LR_X, LAPTOP_SCREEN_WEB_LR_Y );
}
////////////////////////// MAIN PAGE ////////////////////////////////
BOOLEAN gMilitiaDetailOn = FALSE;
STR16 Profilenamegetter( UINT32 aNum )
{
if ( aNum < gIndividualMilitiaFilteredIdsVector.size( ) )
{
UINT32 militiaid = gIndividualMilitiaFilteredIdsVector[aNum];
MILITIA militia;
if ( GetMilitia( militiaid, &militia ) )
return militia.GetName( );
}
return L"No entry found in database";
}
STR16 Sectornamegetter( UINT32 aNum )
{
if ( aNum < gIndividualMilitiaFilteredIdsVector.size( ) )
{
UINT32 militiaid = gIndividualMilitiaFilteredIdsVector[aNum];
MILITIA militia;
if ( GetMilitia( militiaid, &militia ) )
return militia.GetSector( );
}
return L"No entry found in database";
}
UINT32 gusCurrentMilitia = 0;
CHAR16 gMilitiaOperationText[100];
STR16 OperationText( UINT32 aNum )
{
MILITIA militia;
if ( GetMilitia( gusCurrentMilitia, &militia ) && aNum < militia.history.size( ) )
{
MILITIA_BATTLEREPORT battlereport = militia.history[aNum];
UINT32 day = battlereport.id / (1440);
UINT32 hours = (battlereport.id - day * 1440) / 60;
UINT32 minutes = battlereport.id - day * 1440 - hours * 60;
STR16 operationame = GetIncidentName( battlereport.id );
if ( battlereport.flagmask & MILITIA_BATTLEREPORT_FLAG_RECRUITED )
{
STR16 originsectorstr = militia.GetOriginSector( );
if ( militia.origin == MO_PMC )
swprintf( gMilitiaOperationText, szIndividualMilitiaBattleReportText[8], day, hours, minutes, originsectorstr );
else if ( militia.origin == MO_DEFECTOR )
swprintf( gMilitiaOperationText, szIndividualMilitiaBattleReportText[9], day, hours, minutes, originsectorstr );
else
swprintf( gMilitiaOperationText, szIndividualMilitiaBattleReportText[1], day, hours, minutes, originsectorstr );
}
else if ( battlereport.flagmask & MILITIA_BATTLEREPORT_FLAG_PROMOTED )
swprintf( gMilitiaOperationText, szIndividualMilitiaBattleReportText[2], day, hours, minutes );
else if ( battlereport.flagmask & MILITIA_BATTLEREPORT_FLAG_DIED )
swprintf( gMilitiaOperationText, szIndividualMilitiaBattleReportText[3], operationame );
else if ( battlereport.flagmask & MILITIA_BATTLEREPORT_FLAG_WOUNDED_COMA )
swprintf( gMilitiaOperationText, szIndividualMilitiaBattleReportText[6], operationame );
else if ( battlereport.flagmask & MILITIA_BATTLEREPORT_FLAG_KILLEDENEMY )
swprintf( gMilitiaOperationText, szIndividualMilitiaBattleReportText[7], operationame );
else if ( battlereport.flagmask & MILITIA_BATTLEREPORT_FLAG_WOUNDED_HEAVY )
swprintf( gMilitiaOperationText, szIndividualMilitiaBattleReportText[5], operationame );
else if ( battlereport.flagmask & MILITIA_BATTLEREPORT_FLAG_WOUNDED_SMALL )
swprintf( gMilitiaOperationText, szIndividualMilitiaBattleReportText[4], operationame );
else if ( battlereport.flagmask & MILITIA_BATTLEREPORT_FLAG_FIRED )
swprintf( gMilitiaOperationText, szIndividualMilitiaBattleReportText[10], day, hours, minutes );
else
swprintf( gMilitiaOperationText, szIndividualMilitiaBattleReportText[0], operationame );
return gMilitiaOperationText;
}
return L"No entry found in database";
}
CHAR16 gItemLongNamegetterText[800];
STR16 ItemLongNamegetter( UINT32 aNum )
{
if ( aNum < gIndividualMilitiaVector.size( ) )
{
swprintf( gItemLongNamegetterText, L"%s", Item[aNum].szLongItemName );
return gItemLongNamegetterText;
}
return L"unarmed";
}
void GetFaceData( UINT32 aMilitiaId, UINT32& arImageLib, UINT16& arImage )
{
arImageLib = gARFacesLib;
arImage = HUMAN_SKULL;
MILITIA militia;
if ( GetMilitia( aMilitiaId, &militia ) )
{
if ( militia.flagmask & MILITIAFLAG_DEAD )
arImage = HUMAN_SKULL;
else if ( militia.soldierclass == SOLDIER_CLASS_GREEN_MILITIA )
arImage = militia.bodytype == REGFEMALE ? MILITIA1F_FACE : MILITIA1_FACE;
else if ( militia.soldierclass == SOLDIER_CLASS_REG_MILITIA )
arImage = militia.bodytype == REGFEMALE ? MILITIA2F_FACE : MILITIA2_FACE;
else if ( militia.soldierclass == SOLDIER_CLASS_ELITE_MILITIA )
arImage = militia.bodytype == REGFEMALE ? MILITIA3F_FACE : MILITIA3_FACE;
}
}
void AutoResolveFaces( UINT32 aNum, UINT32& arImageLib, UINT16& arImage )
{
arImageLib = gARFacesLib;
arImage = HUMAN_SKULL;
if ( aNum < gIndividualMilitiaFilteredIdsVector.size( ) )
{
UINT32 militiaid = gIndividualMilitiaFilteredIdsVector[aNum];
GetFaceData( militiaid, arImageLib, arImage );
}
}
/*void ItemImage( UINT32 usItem, UINT32& arImageLib, UINT16& arImage )
{
if ( usItem != NONE )
{
INVTYPE* pItem = &Item[usItem];
arImage = g_bUsePngItemImages ? 0 : pItem->ubGraphicNum;
arImageLib = GetInterfaceGraphicForItem( pItem );
}
}*/
/*extern UINT32 guTraitImages;
void TraitImage1( UINT32 aNum, UINT32& arImageLib, UINT16& arImage )
{
MILITIA& militia = GetMilitiabyNumber( aNum );
arImageLib = guTraitImages;
arImage = 3 * militia.traits[0];
}
void TraitImage2( UINT32 aNum, UINT32& arImageLib, UINT16& arImage )
{
MILITIA& militia = GetMilitiabyNumber( aNum );
arImageLib = guTraitImages;
arImage = 3 * militia.traits[1];
}
void TraitImage3( UINT32 aNum, UINT32& arImageLib, UINT16& arImage )
{
MILITIA& militia = GetMilitiabyNumber( aNum );
arImageLib = guTraitImages;
arImage = 3 * militia.traits[2];
}*/
void MilitiaHealthBar( UINT32 aId, UINT16& arCol1, UINT16& arVal1, UINT16& arCol2, UINT16& arVal2, UINT16& arCol3, UINT16& arVal3, UINT16& arCol4, UINT16& arVal4 )
{
if ( aId < gIndividualMilitiaFilteredIdsVector.size() )
{
UINT32 militiaid = gIndividualMilitiaFilteredIdsVector[aId];
MILITIA militia;
if ( GetMilitia( militiaid, &militia ) )
{
// we create a 'health bar' here
// first a black background
arCol1 = Get16BPPColor( FROMRGB( 0, 0, 0 ) );
arVal1 = 100;
// we might be bleeding - draw the potential life here
arCol2 = Get16BPPColor( FROMRGB( 255, 255, 0 ) );
arVal2 = 100;//militia.stats[HEALTH];
// we might be wounded - draw the potential life here
arCol3 = Get16BPPColor( FROMRGB( 255, 125, 125 ) );
arVal3 = 100;//militia.stats[HEALTH];
// the red life part that we really have
arCol4 = Get16BPPColor( FROMRGB( 255, 0, 0 ) );
arVal4 = UINT16( militia.healthratio );
}
}
}
void callbackmilitialist( INT32 usId )
{
if ( usId < gIndividualMilitiaFilteredIdsVector.size() )
{
UINT32 militiaid = gIndividualMilitiaFilteredIdsVector[usId];
militiaindividualmainwidget.SetMouseRegionActive( TRUE );
militiaindividualmainwidget.SetId( (UINT32)militiaid );
TestTableTemplate<3>::getInstance( ).SetMouseRegionActive( FALSE );
TestTableTemplate<3>::getInstance( ).DestroyMouseRegions( );
gfMilitiaDetailsOpen = TRUE;
TestTableTemplate<3>::getInstance( ).SetRefresh( );
}
}
void callbackmilitiadetail( INT32 usId )
{
MILITIA militia;
if ( GetMilitia( gusCurrentMilitia, &militia ) && usId < militia.history.size( ) )
{
MILITIA_BATTLEREPORT battlereport = militia.history[usId];
// if this is a valid ID of an incident, go to its website, otherwise, do nothing
INT32 incidentposition = GetPositionOfIncident( battlereport.id );
if ( incidentposition >= 0 )
{
militiaindividualmainwidget.SetMouseRegionActive( FALSE );
militiaindividualmainwidget.DestroyMouseRegions( );
TestTableTemplate<3>::getInstance( ).SetMouseRegionActive( TRUE );
TestTableTemplate<3>::getInstance( ).SetRefresh( );
guiCurrentLaptopMode = LAPTOP_MODE_CAMPAIGNHISTORY_MOSTIMPORTANT;
gusMostImportantPage = incidentposition;
}
}
}
template<> void TestTableTemplate<1>::SetRefresh( ) { gfMilitiaWebsiteMainRedraw = TRUE; }
template<> void TestTableTemplate<2>::SetRefresh( ) { gfMilitiaWebsiteMainRedraw = TRUE; }
template<> void TestTableTemplate<3>::SetRefresh( ) { gfMilitiaWebsiteMainRedraw = TRUE; }
template<> void TestTableTemplate<1>::Init( UINT16 sX, UINT16 sY, UINT16 sX_End, UINT16 sY_End )
{
ClearColumnDataProvider( );
ColumnDataProvider imagecol( L"" );
imagecol.SetMethodImage( AutoResolveFaces );
imagecol.SetNumberOfEntries( gIndividualMilitiaFilteredIdsVector.size( ) );
imagecol.SetRequiredHeigth( 27 );
imagecol.SetCallBackType( ColumnDataProvider::CDP_MILITIADETAIL );
AddColumnDataProvider( imagecol );
TestTable::Init( sX, sY, sX_End, sY_End );
}
template<> void TestTableTemplate<2>::Init( UINT16 sX, UINT16 sY, UINT16 sX_End, UINT16 sY_End )
{
ClearColumnDataProvider( );
ColumnDataProvider namcol( szIdividualMilitiaWebsiteText[0] );
namcol.SetMethodString( OperationText );
MILITIA militia;
if ( GetMilitia( gusCurrentMilitia, &militia ) )
namcol.SetNumberOfEntries( militia.history.size( ) );
else
namcol.SetNumberOfEntries( 0 );
namcol.SetCallBackType( ColumnDataProvider::CDP_MILITIADETAIL );
AddColumnDataProvider( namcol );
TestTable::Init( sX, sY, sX_End, sY_End );
}
template<> void TestTableTemplate<3>::Init( UINT16 sX, UINT16 sY, UINT16 sX_End, UINT16 sY_End )
{
ClearColumnDataProvider( );
if ( gGameExternalOptions.fIndividualMilitia_ManageHealth )
{
ColumnDataProvider healthbarcol( L"" );
healthbarcol.SetMethodStatusBar( MilitiaHealthBar );
healthbarcol.SetNumberOfEntries( gIndividualMilitiaFilteredIdsVector.size( ) );
healthbarcol.SetRequiredHeigth( 29 );
healthbarcol.SetCallBackType( ColumnDataProvider::CDP_MILITIA_LIST );
AddColumnDataProvider( healthbarcol );
}
// face
ColumnDataProvider imagecol( L"" );
imagecol.SetMethodImage( AutoResolveFaces );
imagecol.SetNumberOfEntries( gIndividualMilitiaFilteredIdsVector.size( ) );
imagecol.SetRequiredHeigth( 27 );
imagecol.SetRequiredLength( 35 );
imagecol.SetCallBackType( ColumnDataProvider::CDP_MILITIA_LIST );
AddColumnDataProvider( imagecol );
// name
ColumnDataProvider namcol( szIdividualMilitiaWebsiteText[12] );
namcol.SetMethodString( Profilenamegetter );
namcol.SetNumberOfEntries( gIndividualMilitiaFilteredIdsVector.size( ) );
namcol.SetCallBackType( ColumnDataProvider::CDP_MILITIA_LIST );
AddColumnDataProvider( namcol );
// sector
ColumnDataProvider sectorcol( szIdividualMilitiaWebsiteText[13] );
sectorcol.SetMethodString( Sectornamegetter );
sectorcol.SetNumberOfEntries( gIndividualMilitiaFilteredIdsVector.size( ) );
sectorcol.SetCallBackType( ColumnDataProvider::CDP_MILITIA_LIST );
AddColumnDataProvider( sectorcol );
/*// trait 1,2,3
ColumnDataProvider traitcol1( L"" );
traitcol1.SetMethodImage( TraitImage1 );
traitcol1.SetNumberOfEntries( gIndividualMilitiaFilteredIdsVector.size( ) );
traitcol1.SetRequiredHeigth( 20 );
traitcol1.SetRequiredLength( 22 );
traitcol1.SetCallBackType( ColumnDataProvider::CDP_MILITIA_LIST );
AddColumnDataProvider( traitcol1 );
ColumnDataProvider traitcol2( L"" );
traitcol2.SetMethodImage( TraitImage2 );
traitcol2.SetNumberOfEntries( gIndividualMilitiaFilteredIdsVector.size( ) );
traitcol2.SetRequiredHeigth( 20 );
traitcol2.SetRequiredLength( 26 );
traitcol2.SetCallBackType( ColumnDataProvider::CDP_MILITIA_LIST );
AddColumnDataProvider( traitcol2 );
ColumnDataProvider traitcol3( L"" );
traitcol3.SetMethodImage( TraitImage3 );
traitcol3.SetNumberOfEntries( gIndividualMilitiaFilteredIdsVector.size( ) );
traitcol3.SetRequiredHeigth( 20 );
traitcol3.SetRequiredLength( 22 );
traitcol3.SetCallBackType( ColumnDataProvider::CDP_MILITIA_LIST );
AddColumnDataProvider( traitcol3 );*/
/*// weapon
ColumnDataProvider itemimagecol( szIdividualMilitiaWebsiteText[14] );
itemimagecol.SetMethodImage( ItemImage );
itemimagecol.SetNumberOfEntries( gIndividualMilitiaFilteredIdsVector.size( ) );
itemimagecol.SetRequiredHeigth( 29 );
itemimagecol.SetCallBackType( ColumnDataProvider::CDP_MILITIA_LIST );
AddColumnDataProvider( itemimagecol );*/
// name of weapon
/*ColumnDataProvider itemnamecol( L"" );
itemnamecol.SetMethodString( ItemLongNamegetter );
itemnamecol.SetNumberOfEntries( gIndividualMilitiaFilteredIdsVector.size() );
itemnamecol.SetCallBackType( ColumnDataProvider::CDP_MILITIA_LIST );
AddColumnDataProvider( itemnamecol );*/
TestTable::Init( sX, sY, sX_End, sY_End );
}
+19
View File
@@ -0,0 +1,19 @@
#ifndef __MILITIA_WEBSITE_H
#define __MILITIA_WEBSITE_H
/**
* @file
* @author Flugente (bears-pit.com)
*/
// main page (explains what this is all about)
BOOLEAN EnterMilitiaWebsiteMain( );
void ExitMilitiaWebsiteMain( );
void HandleMilitiaWebsiteMain( );
void RenderMilitiaWebsiteMain( );
STR16 OperationText( UINT32 aNum );
extern std::vector<UINT32> gIndividualMilitiaFilteredIdsVector;
#endif //__MILITIA_WEBSITE_H
+19 -5
View File
@@ -38,10 +38,9 @@
#include "militia control.h"
#include "Town Militia.h"
#include "Strategic Town Loyalty.h"
#include "MilitiaIndividual.h"
#endif
extern INT32 ReadFieldByField( HWFILE hFile, PTR pDest, UINT32 uiFieldSize, UINT32 uiElementSize, UINT32 uiCurByteCount );
std::vector<PMCReinforcesHireEvent> gPMCHiringEvents;
PMCGlobalData gPMCData;
@@ -274,17 +273,25 @@ PMCPersonnelData pmcdata[2];
// how much does it cost to hire a militia from the PMC?
UINT16 GetMilitiaCostPMC( UINT8 aSoldierClass )
{
// Flugente: if individual militia is on, the upfront payment is much smaller (a single day's wage). In exchange, we have to pay higher wages for these guys
if ( gGameExternalOptions.fIndividualMilitia )
{
return gMilitiaOriginData[MO_PMC].dailycost[aSoldierClass];
}
else
{
switch ( aSoldierClass )
{
case REGULAR_MILITIA:
return (4 * gGameExternalOptions.iMilitiaTrainingCost * gGameExternalOptions.iRegularCostModifier) / gGameExternalOptions.iTrainingSquadSize + 7 * gGameExternalOptions.usDailyCostTownRegular;
return (4 * gGameExternalOptions.iMilitiaTrainingCost * gGameExternalOptions.iRegularCostModifier) / gGameExternalOptions.iTrainingSquadSize + 7 * gGameExternalOptions.usDailyCostTown[REGULAR_MILITIA];
break;
case ELITE_MILITIA:
// elites are upgradded regulars, so we pay for the basic + specail training
return ((4 * gGameExternalOptions.iMilitiaTrainingCost * gGameExternalOptions.iRegularCostModifier) + (2 * gGameExternalOptions.iMilitiaTrainingCost * gGameExternalOptions.iVeteranCostModifier)) / gGameExternalOptions.iTrainingSquadSize + 7 * gGameExternalOptions.usDailyCostTownElite;
// elites are upgraded regulars, so we pay for the basic + special training
return ((4 * gGameExternalOptions.iMilitiaTrainingCost * gGameExternalOptions.iRegularCostModifier) + (2 * gGameExternalOptions.iMilitiaTrainingCost * gGameExternalOptions.iVeteranCostModifier)) / gGameExternalOptions.iTrainingSquadSize + 7 * gGameExternalOptions.usDailyCostTown[ELITE_MILITIA];
break;
}
}
return 0;
}
@@ -752,6 +759,13 @@ void HandlePMCArrival( UINT8 usId )
StrategicAddMilitiaToSector( SECTORX( (*it).usSectorToArrive ), SECTORY( (*it).usSectorToArrive ), REGULAR_MILITIA, (*it).usRegulars );
StrategicAddMilitiaToSector( SECTORX( (*it).usSectorToArrive ), SECTORY( (*it).usSectorToArrive ), ELITE_MILITIA, (*it).usVeterans );
// Flugente: create individual militia
for ( int i = 0; i < (*it).usRegulars; ++i )
CreateNewIndividualMilitia( REGULAR_MILITIA, MO_PMC, (*it).usSectorToArrive );
for ( int i = 0; i < (*it).usVeterans; ++i )
CreateNewIndividualMilitia( ELITE_MILITIA, MO_PMC, (*it).usSectorToArrive );
// if this is in the current sector, militia will be updated
ResetMilitia( );
+5
View File
@@ -3735,6 +3735,11 @@ BOOLEAN HandleMailSpecialMessages( UINT16 usMessageId, INT32 *iResults, EmailPtr
fReDrawScreenFlag = TRUE;
break;
case(MILITIAROSTER_INTRO) :
SetBookMark( MILITIAROSTER_BOOKMARK );
fReDrawScreenFlag = TRUE;
break;
#endif
}
+3
View File
@@ -381,6 +381,9 @@
#define KINGPIN_BOUNTY_TARGET_GOTAWAY (KINGPIN_BOUNTY_BH_GOTTARGET + KINGPIN_BOUNTY_BH_GOTTARGET_LENGTH)
#define KINGPIN_BOUNTY_TARGET_GOTAWAY_LENGTH 4
#define MILITIAROSTER_INTRO (KINGPIN_BOUNTY_TARGET_GOTAWAY + KINGPIN_BOUNTY_TARGET_GOTAWAY_LENGTH)
#define MILITIAROSTER_INTRO_LENGTH 4
#endif
// WANNE: New 1.13 MERC merc mail text for level up that Speck sends
+42
View File
@@ -90,6 +90,7 @@
#include "MercCompare.h" // added by Flugente
#include "WHO.h" // added by Flugente
#include "PMC.h" // added by Flugente
#include "MilitiaWebsite.h" // added by Flugente
#endif
#include "connect.h"
@@ -1498,6 +1499,11 @@ void RenderLaptop()
case LAPTOP_MODE_PMC_CONTRACT_INDIVIDUAL:
RenderPMCContract( );
break;
case LAPTOP_MODE_MILITIAROSTER_MAIN:
case LAPTOP_MODE_MILITIAROSTER_ABOUT:
RenderMilitiaWebsiteMain( );
break;
}
if( guiCurrentLaptopMode >= LAPTOP_MODE_WWW )
@@ -1954,6 +1960,11 @@ void EnterNewLaptopMode()
case LAPTOP_MODE_PMC_CONTRACT_INDIVIDUAL:
EnterPMCContract( );
break;
case LAPTOP_MODE_MILITIAROSTER_MAIN:
case LAPTOP_MODE_MILITIAROSTER_ABOUT:
EnterMilitiaWebsiteMain( );
break;
}
// first time using webbrowser in this laptop session
@@ -2227,6 +2238,11 @@ void HandleLapTopHandles()
case LAPTOP_MODE_PMC_CONTRACT_INDIVIDUAL:
HandlePMCContract( );
break;
case LAPTOP_MODE_MILITIAROSTER_MAIN:
case LAPTOP_MODE_MILITIAROSTER_ABOUT:
HandleMilitiaWebsiteMain( );
break;
}
}
@@ -2809,6 +2825,11 @@ UINT32 ExitLaptopMode(UINT32 uiMode)
case LAPTOP_MODE_PMC_CONTRACT_INDIVIDUAL:
ExitPMCContract( );
break;
case LAPTOP_MODE_MILITIAROSTER_MAIN:
case LAPTOP_MODE_MILITIAROSTER_ABOUT:
ExitMilitiaWebsiteMain();
break;
}
if( ( uiMode != LAPTOP_MODE_NONE )&&( uiMode < LAPTOP_MODE_WWW ) )
@@ -4444,6 +4465,27 @@ if( (gubQuest[ QUEST_FIX_LAPTOP ] != QUESTINPROGRESS) || (gGameUBOptions.LaptopQ
}
}
break;
case MILITIAROSTER_BOOKMARK:
{
guiCurrentWWWMode = LAPTOP_MODE_MILITIAROSTER_MAIN;
guiCurrentLaptopMode = LAPTOP_MODE_MILITIAROSTER_MAIN;
// do we have to have a World Wide Wait
if ( LaptopSaveInfo.fVisitedBookmarkAlready[MILITIAROSTER_BOOKMARK] == FALSE )
{
// reset flag and set load pending flag
LaptopSaveInfo.fVisitedBookmarkAlready[MILITIAROSTER_BOOKMARK] = TRUE;
fLoadPendingFlag = TRUE;
}
else
{
// fast reload
fLoadPendingFlag = TRUE;
fFastLoadFlag = TRUE;
}
}
break;
}
#ifdef JA2UB
+5
View File
@@ -162,6 +162,10 @@ enum
LAPTOP_MODE_PMC_CONTRACT_MILITIA,
LAPTOP_MODE_PMC_CONTRACT_INDIVIDUAL,
// Flugente: militia roster
LAPTOP_MODE_MILITIAROSTER_MAIN,
LAPTOP_MODE_MILITIAROSTER_ABOUT,
LAPTOP_MODE_BOBBYR_SHIPMENTS,
//ENCYCLOPEDIA
@@ -241,6 +245,7 @@ enum{
MERCCOMPARE_BOOKMARK, // added by Flugente
WHO_BOOKMARK, // added by Flugente
PMC_BOOKMARK, // added by Flugente
MILITIAROSTER_BOOKMARK, // added by Flugente
TEXT_NUM_LAPTOP_BOOKMARKS
};
+41 -3
View File
@@ -117,6 +117,7 @@
#include "DynamicDialogue.h" // added by Flugente
#include "PMC.h" // added by Flugente
#include "ASD.h" // added by Flugente
#include "MilitiaIndividual.h" // added by Flugente
#endif
#include "BobbyR.h"
@@ -524,8 +525,6 @@ extern EmailPtr pEmailList;
extern UINT32 guiCurrentUniqueSoldierId;
extern BOOLEAN gfHavePurchasedItemsFromTony;
INT32 ReadFieldByField(HWFILE hFile, PTR pDest, UINT32 uiFieldSize, UINT32 uiElementSize, UINT32 uiCurByteCount);
/////////////////////////////////////////////////////
//
// Function Prototypes
@@ -1772,6 +1771,7 @@ BOOLEAN SOLDIERTYPE::Save(HWFILE hFile)
}
return TRUE;
}
/*CHRISL: This function is designed to allow reading the save game file one field at a time. We currently save structures by saving a block of memory,
but variables are stored in memory so that they fit neatly into a WORD resulting in the program automatically adding some padding. This padding is saved
during the save game process and this function is designed to calculate where that padding is so that we can account for it during the load process. The
@@ -2178,7 +2178,7 @@ BOOLEAN SOLDIERTYPE::Load(HWFILE hFile)
this->bAssignment = FACILITY_REPAIR;
}
numBytesRead = ReadFieldByField(hFile, &this->bScopeMode, sizeof(bScopeMode), sizeof(INT8), numBytesRead);
numBytesRead = ReadFieldByField(hFile, &this->bUnusedINT8_1, sizeof(bUnusedINT8_1), sizeof(INT8), numBytesRead );
numBytesRead = ReadFieldByField(hFile, &this->ubMilitiaAssists, sizeof(ubMilitiaAssists), sizeof(UINT8), numBytesRead );
numBytesRead = ReadFieldByField(hFile, &this->bUnusedINT8_2, sizeof(bUnusedINT8_2), sizeof(INT8), numBytesRead );
numBytesRead = ReadFieldByField(hFile, &this->bUnusedINT8_3, sizeof(bUnusedINT8_3), sizeof(INT8), numBytesRead );
numBytesRead = ReadFieldByField(hFile, &this->bUnusedINT16_4, sizeof(bUnusedINT16_4), sizeof(INT16), numBytesRead );
@@ -2355,6 +2355,18 @@ BOOLEAN SOLDIERTYPE::Load(HWFILE hFile)
if ( guiCurrentSaveGameVersion >= SNITCH_TRAIT_EXTENDED )
{
numBytesRead = ReadFieldByField(hFile, &this->usSoldierFlagMask2, sizeof(usSoldierFlagMask2), sizeof(UINT32), numBytesRead);
if ( guiCurrentSaveGameVersion >= INDIVIDUAL_MILITIA )
{
numBytesRead = ReadFieldByField( hFile, &this->usIndividualMilitiaID, sizeof(usIndividualMilitiaID), sizeof(UINT32), numBytesRead );
}
else
{
this->usIndividualMilitiaID = 0;
for ( int i = 0; i < sizeof(usIndividualMilitiaID); ++i )
buffer++;
}
}
else
{
@@ -4405,6 +4417,13 @@ BOOLEAN SaveGame( int ubSaveGameID, STR16 pGameDesc )
goto FAILED_TO_SAVE;
}
// Flugente: individual militia
if ( !SaveIndividualMilitiaData( hFile ) )
{
ScreenMsg( FONT_MCOLOR_WHITE, MSG_ERROR, L"ERROR writing individual militia data" );
goto FAILED_TO_SAVE;
}
//Close the saved game file
FileClose( hFile );
@@ -6126,6 +6145,25 @@ BOOLEAN LoadSavedGame( int ubSavedGameID )
InitASD();
}
if ( guiCurrentSaveGameVersion >= INDIVIDUAL_MILITIA )
{
uiRelEndPerc += 1;
SetRelativeStartAndEndPercentage( 0, uiRelStartPerc, uiRelEndPerc, L"Load individual militia data..." );
RenderProgressBar( 0, 100 );
uiRelStartPerc = uiRelEndPerc;
if ( !LoadIndividualMilitiaData( hFile ) )
{
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String( "Individual militia data Load failed" ) );
FileClose( hFile );
return(FALSE);
}
}
else
{
InitIndividualMilitiaData();
}
//
//Close the saved game file
//
+6
View File
@@ -101,4 +101,10 @@ void GetBestPossibleSectorXYZValues( INT16 *psSectorX, INT16 *psSectorY, INT8 *p
extern UINT32 guiLastSaveGameNum; // The end turn auto save number (0 = Auto00.sav, 1 = Auto01.sav)
INT8 GetNumberForAutoSave( BOOLEAN fLatestAutoSave );
/*CHRISL: This function is designed to allow reading the save game file one field at a time. We currently save structures by saving a block of memory,
but variables are stored in memory so that they fit neatly into a WORD resulting in the program automatically adding some padding. This padding is saved
during the save game process and this function is designed to calculate where that padding is so that we can account for it during the load process. The
use of this function should allow changes to be made to various structures within the designated "POD", while still allowing for save game continuity.*/
INT32 ReadFieldByField( HWFILE hFile, PTR pDest, UINT32 uiFieldSize, UINT32 uiElementSize, UINT32 uiCurByteCount );
#endif
-3
View File
@@ -55,9 +55,6 @@
#endif
extern INT32 ReadFieldByField( HWFILE hFile, PTR pDest, UINT32 uiFieldSize, UINT32 uiElementSize, UINT32 uiCurByteCount );
extern INT32 giReinforcementPool;
extern BOOLEAN gfTacticalDoHeliRun;
+16
View File
@@ -71,6 +71,7 @@
#include "Queen Command.h" // added by Flugente
#include "PMC.h" // added by Flugente
#include "Drugs And Alcohol.h" // added by Flugente for DoesMercHaveDisability( ... )
#include "MilitiaIndividual.h" // added by Flugente
#endif
#include <vector>
#include <queue>
@@ -2550,6 +2551,9 @@ void UpdateAssignments()
}
}
// Flugente: individual militia
HandleHourlyMilitiaHealing();
// Flugente: handle militia command
HandleMilitiaCommand();
@@ -6946,6 +6950,18 @@ void HandlePrisonerProcessingInSector( INT16 sMapX, INT16 sMapY, INT8 bZ )
StrategicAddMilitiaToSector( sMapX, sMapY, ELITE_MILITIA, turnedmilitia[PRISONER_ELITE] + turnedmilitia[PRISONER_OFFICER] );
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szPrisonerTextStr[STR_PRISONER_TURN_MILITIA], turnedmilitia[PRISONER_OFFICER], turnedmilitia[PRISONER_ELITE], turnedmilitia[PRISONER_REGULAR], turnedmilitia[PRISONER_ADMIN] );
// Flugente: create individual militia
for ( int i = 0; i < turnedmilitia[PRISONER_ADMIN]; ++i )
CreateNewIndividualMilitia( GREEN_MILITIA, MO_DEFECTOR, SECTOR( sMapX, sMapY ) );
for ( int i = 0; i < turnedmilitia[PRISONER_REGULAR]; ++i )
CreateNewIndividualMilitia( REGULAR_MILITIA, MO_DEFECTOR, SECTOR( sMapX, sMapY ) );
for ( int i = 0; i < turnedmilitia[PRISONER_ELITE] + turnedmilitia[PRISONER_OFFICER]; ++i )
CreateNewIndividualMilitia( ELITE_MILITIA, MO_DEFECTOR, SECTOR( sMapX, sMapY ) );
AddStrategicEvent( EVENT_MILITIAROSTER_EMAIL, GetWorldTotalMin( ) + 60 * (1 + Random( 4 )), 0 );
}
if ( volunteers )
+107 -107
View File
@@ -71,6 +71,7 @@
#include "Bullets.h" // HEADROCK HAM 5, for use with Bullet Impact.
#include "CampaignStats.h" // added by Flugente
#include "DynamicDialogue.h" // added by Flugente
#include "MilitiaIndividual.h" // added by Flugente
#endif
#include "Reinforcement.h"
@@ -268,33 +269,6 @@ enum
OTHER_PANEL,
};
//generic face images
enum
{
ADMIN_FACE,
TROOP_FACE,
ELITE_FACE,
TANK_FACE,
MILITIA1_FACE,
MILITIA2_FACE,
MILITIA3_FACE,
YM_CREATURE_FACE,
AM_CREATURE_FACE,
YF_CREATURE_FACE,
AF_CREATURE_FACE,
HUMAN_SKULL,
TANK_WRECK,
CREATURE_SKULL,
ADMINF_FACE,
TROOPF_FACE,
ELITEF_FACE,
MILITIA1F_FACE,
MILITIA2F_FACE,
MILITIA3F_FACE,
JEEP_FACE,
JEEP_WRECK,
};
extern void CreateDestroyMapInvButton();
//Autoresolve sets this variable which defaults to -1 when not needed.
@@ -616,7 +590,7 @@ void EnterAutoResolveMode( UINT8 ubSectorX, UINT8 ubSectorY )
CreateDestroyMapInvButton();
RenderButtons();
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Autoresolve1");
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Autoresolve1");
// WDS - make number of mercenaries, etc. be configurable
//Allocate memory for all the globals while we are in this mode.
gpAR = (AUTORESOLVE_STRUCT*)MemAlloc( sizeof( AUTORESOLVE_STRUCT ) );
@@ -794,8 +768,8 @@ void AssociateEnemiesWithStrategicGroups()
{
if ( gpEnemies[i].uiFlags & CELL_TANK && ubNumTanks ) //is this soldier a tank? and we still have some tanks to add? (since there might not be a static tank in sector)
{
gpEnemies[i].pSoldier->ubGroupID = 0;
gpEnemies[i].uiFlags |= CELL_ASSIGNED;
gpEnemies[ i ].pSoldier->ubGroupID = 0;
gpEnemies[ i ].uiFlags |= CELL_ASSIGNED;
ubNumTanks--;
}
else if ( gpEnemies[i].uiFlags & CELL_JEEP && ubNumJeeps )
@@ -910,8 +884,8 @@ void AssociateEnemiesWithStrategicGroups()
{
if (ubNumTanks && ubNumTanksInGroup && gpEnemies[i].uiFlags & CELL_TANK)
{
gpEnemies[i].pSoldier->ubGroupID = pGroup->ubGroupID;
gpEnemies[i].uiFlags |= CELL_ASSIGNED;
gpEnemies[ i ].pSoldier->ubGroupID = pGroup->ubGroupID;
gpEnemies[ i ].uiFlags |= CELL_ASSIGNED;
ubNumTanks--;
ubNumTanksInGroup--;
}
@@ -970,10 +944,10 @@ void AssociateEnemiesWithStrategicGroups()
{
if ( gpEnemies[i].uiFlags & CELL_TANK && ubISNumTanks && ubNumTanks )
{
gpEnemies[i].pSoldier->ubGroupID = 0;
gpEnemies[i].uiFlags |= CELL_ASSIGNED;
gpEnemies[i].pSoldier->sSectorX = SECTORX( pSectors[ubCurrSI] );
gpEnemies[i].pSoldier->sSectorY = SECTORY( pSectors[ubCurrSI] );
gpEnemies[ i ].pSoldier->ubGroupID = 0;
gpEnemies[ i ].uiFlags |= CELL_ASSIGNED;
gpEnemies[ i ].pSoldier->sSectorX = SECTORX( pSectors[ ubCurrSI ] );
gpEnemies[ i ].pSoldier->sSectorY = SECTORY( pSectors[ ubCurrSI ] );
ubISNumTanks--;
ubNumTanks--;
}
@@ -1020,7 +994,7 @@ void AssociateEnemiesWithStrategicGroups()
Because number and type of cells should be computed for the same composition of enemies as the one we see in this function, it should not happen though*/
AssertMsg( !(ubISNumAdmins & ubISNumTroops & ubISNumElites & ubISNumTanks & ubISNumJeeps), "Mapping between actual enemies and autoresolve cells is wrong." );
}
}
void CalculateSoldierCells( BOOLEAN fReset )
@@ -1129,9 +1103,9 @@ void CalculateSoldierCells( BOOLEAN fReset )
if( gubEnemyEncounterCode != CREATURE_ATTACK_CODE )
{
if ( index < gpAR->ubElites )
gpEnemies[index].uiFlags = CELL_ELITE;
gpEnemies[ index ].uiFlags = CELL_ELITE;
else if ( index < gpAR->ubElites + gpAR->ubTroops )
gpEnemies[index].uiFlags = CELL_TROOP;
gpEnemies[ index ].uiFlags = CELL_TROOP;
else if ( index < gpAR->ubElites + gpAR->ubTroops + gpAR->ubAdmins )
gpEnemies[index].uiFlags = CELL_ADMIN;
else if ( index < gpAR->ubElites + gpAR->ubTroops + gpAR->ubAdmins + gpAR->ubTanks )
@@ -2522,6 +2496,27 @@ DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Autoresolve2");
if( fDeleteForGood && gpCivs[ i ].pSoldier->stats.bLife < OKLIFE/2 )
{
// Flugente: individual militia
// we not only handle promotions here, but basically update this guy (if not already counted as dead)
MILITIA militia;
if ( GetMilitia( gpCivs[i].pSoldier->usIndividualMilitiaID, &militia ) && !(militia.flagmask & MILITIAFLAG_DEAD) )
{
MILITIA_BATTLEREPORT report;
report.id = GetIdOfCurrentlyOngoingIncident( );
report.flagmask |= MILITIA_BATTLEREPORT_FLAG_DIED;
if ( gpCivs[i].pSoldier->ubMilitiaKills )
report.flagmask |= MILITIA_BATTLEREPORT_FLAG_KILLEDENEMY;
militia.history.push_back( report );
militia.healthratio = 0.0f;
militia.flagmask |= MILITIAFLAG_DEAD;
UpdateMilitia( militia );
}
AddDeadSoldierToUnLoadedSector( gpAR->ubSectorX, gpAR->ubSectorY, 0, gpCivs[ i ].pSoldier, RandomGridNo(), ADD_DEAD_SOLDIER_TO_SWEETSPOT );
StrategicRemoveMilitiaFromSector( gpCivs[ i ].pSoldier->sSectorX, gpCivs[ i ].pSoldier->sSectorY, ubCurrentRank, 1 );
@@ -2530,36 +2525,10 @@ DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Autoresolve2");
}
else
{
// this will check for promotions and handle them for you
if( fDeleteForGood && ( gpCivs[ i ].pSoldier->ubMilitiaKills > 0) && ( ubCurrentRank < ELITE_MILITIA ) )
{
UINT8 ubPromotions = CheckOneMilitiaForPromotion( gpCivs[i].pSoldier->sSectorX, gpCivs[i].pSoldier->sSectorY, ubCurrentRank, gpCivs[i].pSoldier->ubMilitiaKills );
if( ubPromotions )
{
if( ubPromotions == 2 )
{
++gbGreenToElitePromotions;
++gbMilitiaPromotions;
// Flugente: take care of promotions and individual militia update
HandlePossibleMilitiaPromotion( gpCivs[i].pSoldier );
}
ubCurrentRank = ELITE_MILITIA;
}
else if( gpCivs[ i ].pSoldier->ubSoldierClass == SOLDIER_CLASS_GREEN_MILITIA )
{
++gbGreenToRegPromotions;
++gbMilitiaPromotions;
ubCurrentRank = REGULAR_MILITIA;
}
else if( gpCivs[ i ].pSoldier->ubSoldierClass == SOLDIER_CLASS_REG_MILITIA )
{
++gbRegToElitePromotions;
++gbMilitiaPromotions;
ubCurrentRank = ELITE_MILITIA;
}
}
}
}
TacticalRemoveSoldierPointer( gpCivs[ i ].pSoldier, FALSE );
memset( &gpCivs[ i ], 0, sizeof( SOLDIERCELL ) );
}
@@ -3045,7 +3014,7 @@ void ResetAutoResolveInterface()
{
switch( PreRandom( 5 ) )
{
case 0: if ( gpAR->ubElites ) { gpAR->ubElites--; break; }
case 0: if( gpAR->ubElites ) { gpAR->ubElites--; break; }
case 1: if ( gpAR->ubAdmins ) { gpAR->ubAdmins--; break; }
case 2: if ( gpAR->ubTroops ) { gpAR->ubTroops--; break; }
case 3: if ( gpAR->ubTanks ) { gpAR->ubTanks--; break; }
@@ -4095,7 +4064,7 @@ BOOLEAN FireAShot( SOLDIERCELL *pAttacker )
PlayAutoResolveSample( Weapon[ pItem->usItem ].sLocknLoadSound, RATE_11025, 50, 1, MIDDLEPAN );
}
}
if ( (*pItem)[0]->data.gun.ubGunShotsLeft )
if( (*pItem)[0]->data.gun.ubGunShotsLeft )
{
PlayAutoResolveSample( Weapon[ pItem->usItem ].sSound, RATE_11025, 50, 1, MIDDLEPAN );
if( pAttacker->uiFlags & CELL_MERC )
@@ -4399,7 +4368,7 @@ void AttackTarget( SOLDIERCELL *pAttacker, SOLDIERCELL *pTarget )
if ( fAntiTank )
pTarget->usNextHit[ bAttackIndex ] = (UINT16)( 200 + PreRandom( 400 ) );
else
pTarget->usNextHit[bAttackIndex] = (UINT16)(50 + PreRandom( 400 ));
pTarget->usNextHit[ bAttackIndex ] = (UINT16)( 50 + PreRandom( 400 ) );
pTarget->pAttacker[ bAttackIndex ] = pAttacker;
}
@@ -4672,6 +4641,26 @@ void AttackTarget( SOLDIERCELL *pAttacker, SOLDIERCELL *pTarget )
// Flugente: campaign stats
gCurrentIncident.AddStat( pTarget->pSoldier, CAMPAIGNHISTORY_TYPE_KILL );
// Flugente: individual militia
MILITIA militia;
if ( GetMilitia( pTarget->pSoldier->usIndividualMilitiaID, &militia ) && !(militia.flagmask & MILITIAFLAG_DEAD) )
{
militia.healthratio = 0.0f;
militia.flagmask |= MILITIAFLAG_DEAD;
// note the current incident (when closing the incident, we only do this for those still alive)
MILITIA_BATTLEREPORT report;
report.id = GetIdOfCurrentlyOngoingIncident( );
report.flagmask = MILITIA_BATTLEREPORT_FLAG_DIED;
if ( pTarget->pSoldier->ubMilitiaKills )
report.flagmask |= MILITIA_BATTLEREPORT_FLAG_KILLEDENEMY;
militia.history.push_back( report );
UpdateMilitia( militia );
}
// Flugente: disease
HandleDeathDiseaseImplications( pTarget->pSoldier );
@@ -4722,7 +4711,7 @@ void AttackTarget( SOLDIERCELL *pAttacker, SOLDIERCELL *pTarget )
}
else if( pAttacker->uiFlags & CELL_MILITIA )
{
pAttacker->pSoldier->ubMilitiaKills += 2;
pAttacker->pSoldier->ubMilitiaKills += 1;
}
if( pTarget->uiFlags & CELL_MERC && gpAR->fSound )
{
@@ -4870,6 +4859,26 @@ void TargetHitCallback( SOLDIERCELL *pTarget, INT32 index )
// Flugente: campaign stats
gCurrentIncident.AddStat( pTarget->pSoldier, CAMPAIGNHISTORY_TYPE_KILL );
// Flugente: individual militia
MILITIA militia;
if ( GetMilitia( pTarget->pSoldier->usIndividualMilitiaID, &militia ) && !(militia.flagmask & MILITIAFLAG_DEAD) )
{
militia.healthratio = 0.0f;
militia.flagmask |= MILITIAFLAG_DEAD;
// note the current incident (when closing the incident, we only do this for those still alive)
MILITIA_BATTLEREPORT report;
report.id = GetIdOfCurrentlyOngoingIncident( );
report.flagmask = MILITIA_BATTLEREPORT_FLAG_DIED;
if ( pTarget->pSoldier->ubMilitiaKills )
report.flagmask |= MILITIA_BATTLEREPORT_FLAG_KILLEDENEMY;
militia.history.push_back( report );
UpdateMilitia( militia );
}
// Flugente: disease
HandleDeathDiseaseImplications( pTarget->pSoldier );
@@ -4928,7 +4937,7 @@ void TargetHitCallback( SOLDIERCELL *pTarget, INT32 index )
HandleMoraleEvent( pKiller->pSoldier, MORALE_KILLED_ENEMY, gpAR->ubSectorX, gpAR->ubSectorY, 0 );
}
else if( pKiller->uiFlags & CELL_MILITIA )
pKiller->pSoldier->ubMilitiaKills += 2;
pKiller->pSoldier->ubMilitiaKills += 1;
}
if( pAssister1 )
{
@@ -4954,7 +4963,7 @@ void TargetHitCallback( SOLDIERCELL *pTarget, INT32 index )
StatChange( pAssister1->pSoldier, EXPERAMT, ( UINT16 )( 5 * pTarget->pSoldier->pathing.bLevel ), FALSE );
}
else if( pAssister1->uiFlags & CELL_MILITIA )
pAssister1->pSoldier->ubMilitiaKills++;
pAssister1->pSoldier->ubMilitiaAssists++;
}
else if( pAssister2 )
{
@@ -4980,7 +4989,7 @@ void TargetHitCallback( SOLDIERCELL *pTarget, INT32 index )
StatChange( pAssister2->pSoldier, EXPERAMT, ( UINT16 )( 5 * pTarget->pSoldier->pathing.bLevel ), FALSE );
}
else if( pAssister2->uiFlags & CELL_MILITIA )
pAssister2->pSoldier->ubMilitiaKills++;
pAssister2->pSoldier->ubMilitiaAssists++;
}
}
if( pTarget->uiFlags & CELL_MERC && gpAR->fSound )
@@ -5767,42 +5776,33 @@ void AutoResolveMilitiaDropAndPromote()
if ( gpCivs[i].pSoldier->stats.bLife < OKLIFE / 2 )
{
// Flugente: individual militia
// we not only handle promotions here, but basically update this guy
MILITIA militia;
if ( GetMilitia( gpCivs[i].pSoldier->usIndividualMilitiaID, &militia ) && !(militia.flagmask & MILITIAFLAG_DEAD) )
{
MILITIA_BATTLEREPORT report;
report.id = GetIdOfCurrentlyOngoingIncident( );
report.flagmask |= MILITIA_BATTLEREPORT_FLAG_DIED;
if ( gpCivs[i].pSoldier->ubMilitiaKills )
report.flagmask |= MILITIA_BATTLEREPORT_FLAG_KILLEDENEMY;
militia.history.push_back( report );
militia.healthratio = 0.0f;
militia.flagmask |= MILITIAFLAG_DEAD;
UpdateMilitia( militia );
}
StrategicRemoveMilitiaFromSector( gpCivs[i].pSoldier->sSectorX, gpCivs[i].pSoldier->sSectorY, ubCurrentRank, 1 );
}
else if ( gpCivs[i].pSoldier->stats.bLife >= OKLIFE / 2 )
{
// this will check for promotions and handle them for you
if ( gpCivs[i].pSoldier->ubMilitiaKills && ubCurrentRank < ELITE_MILITIA )
{
UINT8 ubPromotions = CheckOneMilitiaForPromotion( gpCivs[i].pSoldier->sSectorX, gpCivs[i].pSoldier->sSectorY, ubCurrentRank, gpCivs[i].pSoldier->ubMilitiaKills );
if ( ubPromotions )
{
if ( ubPromotions == 2 )
{
++gbGreenToElitePromotions;
++gbMilitiaPromotions;
ubCurrentRank = ELITE_MILITIA;
}
else if ( gpCivs[i].pSoldier->ubSoldierClass == SOLDIER_CLASS_GREEN_MILITIA )
{
++gbGreenToRegPromotions;
++gbMilitiaPromotions;
ubCurrentRank = REGULAR_MILITIA;
}
else if ( gpCivs[i].pSoldier->ubSoldierClass == SOLDIER_CLASS_REG_MILITIA )
{
++gbRegToElitePromotions;
++gbMilitiaPromotions;
ubCurrentRank = ELITE_MILITIA;
}
}
}
// in any case, we had our chance to be promoted, clear the counter
gpCivs[i].pSoldier->ubMilitiaKills = 0;
// Flugente: take care of promotions and individual militia update
HandlePossibleMilitiaPromotion( gpCivs[i].pSoldier );
}
// DO NOT DELETE HERE!!!!
+29
View File
@@ -3,6 +3,35 @@
#include "types.h"
//generic face images
enum
{
ADMIN_FACE,
TROOP_FACE,
ELITE_FACE,
TANK_FACE,
MILITIA1_FACE,
MILITIA2_FACE,
MILITIA3_FACE,
YM_CREATURE_FACE,
AM_CREATURE_FACE,
YF_CREATURE_FACE,
AF_CREATURE_FACE,
HUMAN_SKULL,
TANK_WRECK,
CREATURE_SKULL,
ADMINF_FACE,
TROOPF_FACE,
ELITEF_FACE,
MILITIA1F_FACE,
MILITIA2F_FACE,
MILITIA3F_FACE,
JEEP_FACE,
JEEP_WRECK,
AUTORESOLVEFACES_MAX
};
void EnterAutoResolveMode( UINT8 ubSectorX, UINT8 ubSectorY );
// is the autoresolve active?
+6
View File
@@ -624,6 +624,12 @@ BOOLEAN ExecuteStrategicEvent( STRATEGICEVENT *pEvent )
case EVENT_SAMSITE_REPAIRED:
RepairSamSite( pEvent->uiParam );
break;
case EVENT_MILITIAROSTER_EMAIL:
// only send the email if we haven't already visited the site, otherwise continue to spam ;-)
if ( !IsBookMarkSet( MILITIAROSTER_BOOKMARK ) )
AddEmail( MILITIAROSTER_INTRO, MILITIAROSTER_INTRO_LENGTH, MAIL_ENRICO, GetWorldTotalMin( ), -1, -1, TYPE_EMAIL_EMAIL_EDT );
break;
}
gfPreventDeletionOfAnyEvent = fOrigPreventFlag;
return TRUE;
+2
View File
@@ -132,6 +132,8 @@ enum
EVENT_SAMSITE_REPAIRED, // Flugente: have a SAM site be fully repaired
EVENT_MILITIAROSTER_EMAIL, // Flugente: we get an email giving us the bookmark to the militia roster webpage
NUMBER_OF_EVENT_TYPES_PLUS_ONE,
NUMBER_OF_EVENT_TYPES = NUMBER_OF_EVENT_TYPES_PLUS_ONE - 1
};
+1
View File
@@ -124,6 +124,7 @@ CHAR16 gEventName[NUMBER_OF_EVENT_TYPES_PLUS_ONE][40]={
L"EnemyHeliRepair",
L"EnemyHeliRefuel",
L"SAMsiteRepaired",
L"MilitiaWebsiteEmail",
};
#endif
+65 -7
View File
@@ -45,6 +45,7 @@
#include "Air Raid.h"
#include "Auto Resolve.h"
#include "ASD.h" // added by Flugente
#include "MilitiaIndividual.h" // added by Flugente
#endif
#include "Quests.h"
@@ -4804,6 +4805,9 @@ BOOLEAN PickUpATownPersonFromSector( UINT8 ubType, INT16 sX, INT16 sY )
// reduce number in this sector
SectorInfo[ SECTOR( sX, sY )].ubNumberOfCivsAtLevel[ ubType ] -= countMovedCivs;
// Flugente: indivdual militia
PickIndividualMilitia( SECTOR( sX, sY ), ubType, countMovedCivs );
fMapPanelDirty = TRUE;
return( TRUE );
@@ -4924,6 +4928,9 @@ DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Map Screen2");
// up the number in this sector of this type of militia
SectorInfo[ SECTOR( sX, sY )].ubNumberOfCivsAtLevel[ ubType ] += countMovedCivs;
// Flugente: indivdual militia
DropIndividualMilitia( SECTOR( sX, sY ), ubType, countMovedCivs );
fMapPanelDirty = TRUE;
return( TRUE );
@@ -5658,6 +5665,9 @@ DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Map Screen3");
StrategicAddMilitiaToSector( sX, sY, GREEN_MILITIA, 1 );
++iCount;
--sGreensOnCursor;
// Flugente: indivdual militia
DropIndividualMilitia( SECTOR( sX, sY ), GREEN_MILITIA, 1 );
}
// regular
@@ -5666,6 +5676,9 @@ DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Map Screen3");
StrategicAddMilitiaToSector( sX, sY, REGULAR_MILITIA, 1 );
++iCount;
--sRegularsOnCursor;
// Flugente: indivdual militia
DropIndividualMilitia( SECTOR( sX, sY ), REGULAR_MILITIA, 1 );
}
// elite
@@ -5674,6 +5687,9 @@ DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Map Screen3");
StrategicAddMilitiaToSector( sX, sY, ELITE_MILITIA, 1 );
++iCount;
--sElitesOnCursor;
// Flugente: indivdual militia
DropIndividualMilitia( SECTOR( sX, sY ), ELITE_MILITIA, 1 );
}
}
}
@@ -5697,6 +5713,11 @@ DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Map Screen3");
StrategicAddMilitiaToSector( sX, sY, GREEN_MILITIA, (UINT8)(sGreensOnCursor % iNumberUnderControl) );
StrategicAddMilitiaToSector( sX, sY, REGULAR_MILITIA, (UINT8)(sRegularsOnCursor % iNumberUnderControl) );
StrategicAddMilitiaToSector( sX, sY, ELITE_MILITIA, (UINT8)(sElitesOnCursor % iNumberUnderControl) );
// Flugente: indivdual militia
DropIndividualMilitia( SECTOR( sX, sY ), GREEN_MILITIA, (UINT8)(sGreensOnCursor % iNumberUnderControl) );
DropIndividualMilitia( SECTOR( sX, sY ), REGULAR_MILITIA, (UINT8)(sRegularsOnCursor % iNumberUnderControl) );
DropIndividualMilitia( SECTOR( sX, sY ), ELITE_MILITIA, (UINT8)(sElitesOnCursor % iNumberUnderControl) );
}
}
@@ -5746,16 +5767,25 @@ void HandleRemovalOfAllTroopsAmongstSectors( void )
if( !StrategicMap[ CALCULATE_STRATEGIC_INDEX( sSectorX, sSectorY ) ].fEnemyControlled )
{
// Flugente: we no use these handy functions, as this will make altering militia distribution behaviour much easier
// Flugente: we now use these handy functions, as this will make altering militia distribution behaviour much easier
// get number of each
iNumberOfGreens += MilitiaInSectorOfRankStationary( sSectorX, sSectorY, GREEN_MILITIA );
iNumberOfRegulars += MilitiaInSectorOfRankStationary( sSectorX, sSectorY, REGULAR_MILITIA );
iNumberOfElites += MilitiaInSectorOfRankStationary( sSectorX, sSectorY, ELITE_MILITIA );
UINT8 green = MilitiaInSectorOfRankStationary( sSectorX, sSectorY, GREEN_MILITIA );
UINT8 regular = MilitiaInSectorOfRankStationary( sSectorX, sSectorY, REGULAR_MILITIA );
UINT8 elite = MilitiaInSectorOfRankStationary( sSectorX, sSectorY, ELITE_MILITIA );
iNumberOfGreens += green;
iNumberOfRegulars += regular;
iNumberOfElites += elite;
//zero out all numbers in sectors
StrategicRemoveAllStaticMilitiaFromSector( sSectorX, sSectorY, GREEN_MILITIA );
StrategicRemoveAllStaticMilitiaFromSector( sSectorX, sSectorY, REGULAR_MILITIA );
StrategicRemoveAllStaticMilitiaFromSector( sSectorX, sSectorY, ELITE_MILITIA );
// Flugente: indivdual militia
PickIndividualMilitia( SECTOR( sSectorX, sSectorY ), GREEN_MILITIA, green );
PickIndividualMilitia( SECTOR( sSectorX, sSectorY ), REGULAR_MILITIA, regular );
PickIndividualMilitia( SECTOR( sSectorX, sSectorY ), ELITE_MILITIA, elite );
}
}
@@ -5816,9 +5846,18 @@ DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Map Screen4");
if( !StrategicMap[ CALCULATE_STRATEGIC_INDEX( sSectorX, sSectorY ) ].fEnemyControlled )
{
// get number of each
iNumberOfGreens += MilitiaInSectorOfRankStationary( sSectorX, sSectorY, GREEN_MILITIA );
iNumberOfRegulars += MilitiaInSectorOfRankStationary( sSectorX, sSectorY, REGULAR_MILITIA );
iNumberOfElites += MilitiaInSectorOfRankStationary( sSectorX, sSectorY, ELITE_MILITIA );
UINT8 green = MilitiaInSectorOfRankStationary( sSectorX, sSectorY, GREEN_MILITIA );
UINT8 regular = MilitiaInSectorOfRankStationary( sSectorX, sSectorY, REGULAR_MILITIA );
UINT8 elite = MilitiaInSectorOfRankStationary( sSectorX, sSectorY, ELITE_MILITIA );
iNumberOfGreens += green;
iNumberOfRegulars += regular;
iNumberOfElites += elite;
// Flugente: indivdual militia
PickIndividualMilitia( SECTOR( sSectorX, sSectorY ), GREEN_MILITIA, green );
PickIndividualMilitia( SECTOR( sSectorX, sSectorY ), REGULAR_MILITIA, regular );
PickIndividualMilitia( SECTOR( sSectorX, sSectorY ), ELITE_MILITIA, elite );
}
}
@@ -5858,6 +5897,11 @@ DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Map Screen4");
SectorInfo[ sSector ].ubNumberOfCivsAtLevel[ REGULAR_MILITIA ] = ( UINT8 )( iNumberOfRegulars / iNumberUnderControl );
SectorInfo[ sSector ].ubNumberOfCivsAtLevel[ ELITE_MILITIA ] = ( UINT8 )( iNumberOfElites / iNumberUnderControl );
// Flugente: indivdual militia
DropIndividualMilitia( sSector, GREEN_MILITIA, (UINT8)(iNumberOfGreens / iNumberUnderControl) );
DropIndividualMilitia( sSector, REGULAR_MILITIA, (UINT8)(iNumberOfRegulars / iNumberUnderControl) );
DropIndividualMilitia( sSector, ELITE_MILITIA, (UINT8)(iNumberOfElites / iNumberUnderControl) );
// Flugente: as we do not move the group militia, we have to make sure we don't accidentally overfill a sector
sTotalSoFar = NumNonPlayerTeamMembersInSector( sSectorX, sSectorY, MILITIA_TEAM );
@@ -5867,6 +5911,9 @@ DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Map Screen4");
SectorInfo[ sSector ].ubNumberOfCivsAtLevel[ GREEN_MILITIA ]++;
++sTotalSoFar;
--iNumberLeftOverGreen;
// Flugente: indivdual militia
DropIndividualMilitia( sSector, GREEN_MILITIA, 1 );
}
if( ( iNumberLeftOverRegular )&&( sTotalSoFar < iMaxMilitiaPerSector ) )
@@ -5874,6 +5921,9 @@ DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Map Screen4");
SectorInfo[ sSector ].ubNumberOfCivsAtLevel[ REGULAR_MILITIA ]++;
++sTotalSoFar;
--iNumberLeftOverRegular;
// Flugente: indivdual militia
DropIndividualMilitia( sSector, REGULAR_MILITIA, 1 );
}
if( ( iNumberLeftOverElite )&&( sTotalSoFar < iMaxMilitiaPerSector ) )
@@ -5881,6 +5931,9 @@ DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Map Screen4");
SectorInfo[ sSector ].ubNumberOfCivsAtLevel[ ELITE_MILITIA ]++;
++sTotalSoFar;
--iNumberLeftOverElite;
// Flugente: indivdual militia
DropIndividualMilitia( sSector, ELITE_MILITIA, 1 );
}
// if this sector is currently loaded
@@ -7386,6 +7439,11 @@ void MilitiaDisbandYesNoBoxCallback( UINT8 bExitValue )
DecrementTownLoyalty( (UINT8)sSelectedMilitiaTown, uiTownLoyaltyBonus );
}
// Flugente: individual militia
INT16 sGlobalMapSector = GetBaseSectorForCurrentTown() + ((sSectorMilitiaMapSector % MILITIA_BOX_ROWS) + (sSectorMilitiaMapSector / MILITIA_BOX_ROWS) * (16));
DisbandIndividualMilitia( sGlobalMapSector, sGreensOnCursor, sRegularsOnCursor, sElitesOnCursor );
// zero out numbers on the cursor
sGreensOnCursor = 0;
sRegularsOnCursor = 0;
+872
View File
@@ -0,0 +1,872 @@
/**
* @file
* @author Flugente (bears-pit.com)
*/
#include "MilitiaIndividual.h"
#include "random.h"
#include "text.h"
#include "Overhead Types.h"
#include "Game Clock.h"
#include "strategicmap.h"
#include "GameVersion.h"
#include "SaveLoadGame.h"
#include "CampaignStats.h"
#include "Town Militia.h"
#include "message.h"
MilitiaOriginData gMilitiaOriginData[MO_MAX];
// later on, make this an array with a vector for each sector
std::vector<MILITIA> gIndividualMilitiaVector;
MILITIA::MILITIA()
{
memset( this, 0, sizeof(MILITIA) );
}
BOOLEAN
MILITIA::Save( HWFILE hFile )
{
UINT32 uiNumBytesWritten = 0;
if ( !FileWrite( hFile, this, SIZEOF_MILITIA_POD, &uiNumBytesWritten ) )
return(FALSE);
// in order to save a vector, we first save its size and then its content
UINT32 size = history.size( );
if ( !FileWrite( hFile, &size, sizeof(UINT32), &uiNumBytesWritten ) )
return(FALSE);
std::vector<MILITIA_BATTLEREPORT>::iterator itend = history.end( );
for ( std::vector<MILITIA_BATTLEREPORT>::iterator it = history.begin( ); it != itend; ++it )
{
if ( !FileWrite( hFile, &(*it), sizeof(MILITIA_BATTLEREPORT), &uiNumBytesWritten ) )
return(FALSE);
}
return(TRUE);
}
BOOLEAN
MILITIA::Load( HWFILE hwFile )
{
if ( guiCurrentSaveGameVersion >= INDIVIDUAL_MILITIA )
{
UINT32 numBytesRead = 0;
numBytesRead = ReadFieldByField( hwFile, &id, sizeof(id), sizeof(UINT32), numBytesRead );
numBytesRead = ReadFieldByField( hwFile, &flagmask, sizeof(flagmask), sizeof(UINT32), numBytesRead );
numBytesRead = ReadFieldByField( hwFile, &origin, sizeof(origin), sizeof(UINT8), numBytesRead );
numBytesRead = ReadFieldByField( hwFile, &originsector, sizeof(originsector), sizeof(UINT8), numBytesRead );
numBytesRead = ReadFieldByField( hwFile, &sector, sizeof(sector), sizeof(UINT8), numBytesRead );
numBytesRead = ReadFieldByField( hwFile, &age, sizeof(age), sizeof(UINT8), numBytesRead );
numBytesRead = ReadFieldByField( hwFile, &soldierclass, sizeof(soldierclass), sizeof(UINT8), numBytesRead );
numBytesRead = ReadFieldByField( hwFile, &bodytype, sizeof(bodytype), sizeof(UINT8), numBytesRead );
numBytesRead = ReadFieldByField( hwFile, &skin, sizeof(skin), sizeof(UINT8), numBytesRead );
numBytesRead = ReadFieldByField( hwFile, &hair, sizeof(hair), sizeof(UINT8), numBytesRead );
numBytesRead = ReadFieldByField( hwFile, &forename, sizeof(forename), sizeof(UINT16), numBytesRead );
numBytesRead = ReadFieldByField( hwFile, &surname, sizeof(surname), sizeof(UINT16), numBytesRead );
numBytesRead = ReadFieldByField( hwFile, &callsign, sizeof(callsign), sizeof(UINT16), numBytesRead );
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 );
if ( numBytesRead != SIZEOF_MILITIA_POD )
return(FALSE);
UINT32 size = 0;
numBytesRead = ReadFieldByField( hwFile, &size, sizeof(size), sizeof(UINT32), numBytesRead );
for ( UINT32 i = 0; i < size; ++i )
{
MILITIA_BATTLEREPORT data;
if ( !FileRead( hwFile, &data, sizeof(MILITIA_BATTLEREPORT), &numBytesRead ) )
return(FALSE);
history.push_back( data );
}
}
return(TRUE);
}
static CHAR16 gMilitiaNameText[100];
STR16 MILITIA::GetName()
{
swprintf( gMilitiaNameText, L"NAME NOT FOUND" );
if ( bodytype == REGFEMALE )
{
if ( gMilitiaOriginData[origin].szFemale_Forename.size() > forename && gMilitiaOriginData[origin].szFemale_Surname.size() > surname )
{
swprintf( gMilitiaNameText, L"%s %s", gMilitiaOriginData[origin].szFemale_Forename[forename].c_str( ), gMilitiaOriginData[origin].szFemale_Surname[surname].c_str( ) );
}
}
else
{
if ( gMilitiaOriginData[origin].szMale_Forename.size( ) > forename && gMilitiaOriginData[origin].szMale_Surname.size( ) > surname )
{
swprintf( gMilitiaNameText, L"%s %s", gMilitiaOriginData[origin].szMale_Forename[forename].c_str( ), gMilitiaOriginData[origin].szMale_Surname[surname].c_str( ) );
}
}
return gMilitiaNameText;
}
static CHAR16 gMilitiaSectorText[100];
STR16 MILITIA::GetSector( )
{
swprintf( gMilitiaSectorText, L"NAME NOT FOUND" );
GetShortSectorString( SECTORX( sector ), SECTORY( sector ), gMilitiaSectorText );
return gMilitiaSectorText;
}
STR16 MILITIA::GetOriginSector( )
{
swprintf( gMilitiaSectorText, L"NAME NOT FOUND" );
GetShortSectorString( SECTORX( originsector ), SECTORY( originsector ), gMilitiaSectorText );
return gMilitiaSectorText;
}
void MILITIA::AddKills( UINT16 aKills, UINT16 aAssists )
{
kills += aKills;
assists += aAssists;
// important: increase by the NEW points (as militia that start with a higher rank have their points adjusted, promotion points are not always the sum of kills and assists)
promotionpoints += 2 * aKills + aAssists;
if ( soldierclass == SOLDIER_CLASS_REG_MILITIA )
{
promotionpoints = max( promotionpoints, gGameExternalOptions.usIndividualMilitia_PromotionPoints_To_Regular );
}
else if ( soldierclass == SOLDIER_CLASS_ELITE_MILITIA )
{
promotionpoints = max( promotionpoints, gGameExternalOptions.usIndividualMilitia_PromotionPoints_To_Regular + gGameExternalOptions.usIndividualMilitia_PromotionPoints_To_Elite );
}
}
UINT16 MILITIA::GetWage( )
{
UINT8 type = GREEN_MILITIA;
if ( soldierclass == SOLDIER_CLASS_REG_MILITIA )
type = REGULAR_MILITIA;
else if ( soldierclass == SOLDIER_CLASS_ELITE_MILITIA )
type = ELITE_MILITIA;
return gMilitiaOriginData[origin].dailycost[type];
}
// release militia from our service. Does not take care of actually removing a militia from the sector!
void MILITIA::Fire( )
{
flagmask |= MILITIAFLAG_FIRED;
MILITIA_BATTLEREPORT report;
report.id = GetWorldTotalMin( );
report.flagmask |= MILITIA_BATTLEREPORT_FLAG_FIRED;
history.push_back( report );
}
BOOLEAN SaveIndividualMilitiaData( HWFILE hwFile )
{
UINT32 uiNumBytesWritten = 0;
// in order to save a vector, we first save its size and then its content
UINT32 size = gIndividualMilitiaVector.size( );
if ( !FileWrite( hwFile, &size, sizeof(UINT32), &uiNumBytesWritten ) )
return(FALSE);
std::vector<MILITIA>::iterator itend = gIndividualMilitiaVector.end( );
for ( std::vector<MILITIA>::iterator it = gIndividualMilitiaVector.begin( ); it != itend; ++it )
{
if ( !(*it).Save( hwFile ) )
return(FALSE);
}
return TRUE;
}
void InitIndividualMilitiaData()
{
gIndividualMilitiaVector.clear();
}
BOOLEAN LoadIndividualMilitiaData( HWFILE hwFile )
{
InitIndividualMilitiaData();
UINT32 numBytesRead = 0;
UINT32 size = 0;
numBytesRead = ReadFieldByField( hwFile, &size, sizeof(size), sizeof(UINT32), numBytesRead );
for ( UINT32 i = 0; i < size; ++i )
{
MILITIA data;
if ( !data.Load( hwFile ) )
return(FALSE);
gIndividualMilitiaVector.push_back(data);
}
return TRUE;
}
UINT32 TotalNumberIndividualMilitia( )
{
return gIndividualMilitiaVector.size( );
}
UINT32 GetFreeIndividualMilitiaId()
{
return 1 + TotalNumberIndividualMilitia();
}
BOOLEAN IsLegalMilitiaId( UINT32 aId )
{
return (aId > 0 && aId < GetFreeIndividualMilitiaId( ));
}
BOOLEAN GetMilitia( UINT32 aId, MILITIA* apMilitia )
{
if ( gGameExternalOptions.fIndividualMilitia && IsLegalMilitiaId( aId ) )
{
if ( apMilitia )
*apMilitia = gIndividualMilitiaVector[aId - 1];
return TRUE;
}
return FALSE;
}
// update data
void UpdateMilitia( MILITIA aMilitia )
{
if ( gGameExternalOptions.fIndividualMilitia && IsLegalMilitiaId( aMilitia.id ) )
{
gIndividualMilitiaVector[aMilitia.id - 1] = aMilitia;
}
}
SOLDIERTYPE* GetUsedSoldierToIndividualMilitia( UINT32 aMilitiaId )
{
for ( UINT32 cnt = gTacticalStatus.Team[MILITIA_TEAM].bFirstID; cnt < gTacticalStatus.Team[MILITIA_TEAM].bLastID; ++cnt )
{
if ( MercPtrs[cnt] && MercPtrs[cnt]->bActive && MercPtrs[cnt]->usIndividualMilitiaID == aMilitiaId )
{
return MercPtrs[cnt];
}
}
return NULL;
}
// update the health values of all militia in tactical
void UpdateAllMilitiaHealthInTactical()
{
if ( !gGameExternalOptions.fIndividualMilitia )
return;
SOLDIERTYPE* pSoldier;
UINT32 cnt = gTacticalStatus.Team[MILITIA_TEAM].bFirstID;
INT32 lastid = gTacticalStatus.Team[MILITIA_TEAM].bLastID;
for ( pSoldier = MercPtrs[cnt]; cnt < lastid; ++cnt, ++pSoldier )
{
MILITIA militia;
if ( pSoldier && pSoldier->bActive && pSoldier->stats.bLifeMax && GetMilitia( pSoldier->usIndividualMilitiaID, &militia ) )
{
militia.healthratio = 100.0f * pSoldier->stats.bLife / pSoldier->stats.bLifeMax;
// 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;
INT32 cnt = gTacticalStatus.Team[MILITIA_TEAM].bFirstID;
INT32 lastid = gTacticalStatus.Team[MILITIA_TEAM].bLastID;
SOLDIERTYPE* pSoldier = NULL;
std::vector<MILITIA>::iterator itend = gIndividualMilitiaVector.end( );
for ( std::vector<MILITIA>::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;
}
}
}
}
}
}
UINT32 CreateRandomIndividualMilitia( UINT8 aSoldierClass, UINT8 aOrigin, UINT8 aSector )
{
UINT32 militiaid = CreateNewIndividualMilitia( aSoldierClass, aOrigin, aSector );
MILITIA newmilitia;
if ( GetMilitia( militiaid, &newmilitia ) )
{
newmilitia.healthratio = (OKLIFE + Random( 85 ));
newmilitia.AddKills( Random( 5 ), Random( 10 ) );
// make up some history
UINT16 mineventtime = Random( 70000 );
int numhistory = Random( 30 );
for ( int j = 0; j < numhistory; ++j )
{
MILITIA_BATTLEREPORT report;
report.id = Random( 100 );
switch ( Random( 20 ) )
{
case 0:
case 1:
report.flagmask |= MILITIA_BATTLEREPORT_FLAG_PROMOTED;
mineventtime = max( mineventtime + 6, report.id );
report.id = mineventtime;
break;
case 2:
case 3: report.flagmask |= MILITIA_BATTLEREPORT_FLAG_WOUNDED_SMALL; break;
case 4:
case 5: report.flagmask |= MILITIA_BATTLEREPORT_FLAG_WOUNDED_HEAVY; break;
case 6:
case 7: report.flagmask |= MILITIA_BATTLEREPORT_FLAG_WOUNDED_COMA; break;
case 8:
case 9:
case 10: report.flagmask |= MILITIA_BATTLEREPORT_FLAG_KILLEDENEMY; break;
// once dead, stop adding more events and kill of the soldier
case 11: report.flagmask |= MILITIA_BATTLEREPORT_FLAG_DIED;
j = numhistory;
newmilitia.healthratio = 0.0f;
newmilitia.flagmask |= MILITIAFLAG_DEAD;
break;
case 12: report.flagmask |= MILITIA_BATTLEREPORT_FLAG_FIRED;
j = numhistory;
newmilitia.flagmask |= MILITIAFLAG_FIRED;
break;
default: break;
}
newmilitia.history.push_back( report );
}
UpdateMilitia( newmilitia );
}
return militiaid;
}
UINT32 CreateNewIndividualMilitia( UINT8 aSoldierClass, UINT8 aOrigin, UINT8 aSector )
{
if ( !gGameExternalOptions.fIndividualMilitia )
return 0;
// make sure we use a valid soldier class
UINT8 soldierclass = aSoldierClass;
if ( soldierclass < SOLDIER_CLASS_GREEN_MILITIA || soldierclass > SOLDIER_CLASS_ELITE_MILITIA )
soldierclass = SOLDIER_CLASS_GREEN_MILITIA;
MILITIA newmilitia;
newmilitia.id = GetFreeIndividualMilitiaId( );
newmilitia.soldierclass = soldierclass;
// according to origin, we choose bodytype, skin, hair, fore- and surname
newmilitia.origin = aOrigin;
// age is random
newmilitia.age = 16 + Random( 2 ) * (1 + Random( 8 ) )
+ Random( 2 ) * (1 + Random( 8 ))
+ Random( 2 ) * (1 + Random( 8 ))
+ Random( 2 ) * (1 + Random( 8 ))
+ Random( 2 ) * (1 + Random( 8 ))
+ Random( 2 ) * (1 + Random( 8 ));
newmilitia.originsector = aSector;
newmilitia.sector = aSector;
UINT8 rnd = Random( 100 );
newmilitia.bodytype = REGMALE;
for ( int i = 0; i < ADULTFEMALEMONSTER; ++i )
{
if ( rnd < gMilitiaOriginData[newmilitia.origin].chance_bodytype[i] )
{
newmilitia.bodytype = i;
break;
}
else
{
rnd -= gMilitiaOriginData[newmilitia.origin].chance_bodytype[i];
}
}
rnd = Random( 100 );
newmilitia.skin = PINKSKIN;
for ( int i = 0; i < NUMSKINS; ++i )
{
if ( rnd < gMilitiaOriginData[newmilitia.origin].chance_skin[i] )
{
newmilitia.skin = i;
break;
}
else
{
rnd -= gMilitiaOriginData[newmilitia.origin].chance_skin[i];
}
}
newmilitia.hair = ChooseHairColor( newmilitia.bodytype, newmilitia.skin );
if ( newmilitia.age > 50 && Chance( newmilitia.age - 50 ) )
newmilitia.hair = WHITEHEAD;
if ( newmilitia.bodytype == REGFEMALE )
{
newmilitia.forename = Random( gMilitiaOriginData[newmilitia.origin].szFemale_Forename.size( ) );
newmilitia.surname = Random( gMilitiaOriginData[newmilitia.origin].szFemale_Surname.size( ) );
}
else
{
newmilitia.forename = Random( gMilitiaOriginData[newmilitia.origin].szMale_Forename.size( ) );
newmilitia.surname = Random( gMilitiaOriginData[newmilitia.origin].szMale_Surname.size( ) );
}
newmilitia.flagmask = 0;
newmilitia.healthratio = 100.0f;
newmilitia.kills = 0;
newmilitia.assists = 0;
newmilitia.promotionpoints = 0;
// promotion points are based on kills and assists. For proper accounting, award points for current rank
newmilitia.AddKills( 0, 0 );
// make up some history
MILITIA_BATTLEREPORT report;
report.flagmask |= MILITIA_BATTLEREPORT_FLAG_RECRUITED;
report.id = GetWorldTotalMin( );
newmilitia.history.push_back( report );
gIndividualMilitiaVector.push_back( newmilitia );
return newmilitia.id;
}
// 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 )
{
if ( !gGameExternalOptions.fIndividualMilitia )
return 0;
std::vector<MILITIA>::iterator itend = gIndividualMilitiaVector.end();
for ( std::vector<MILITIA>::iterator it = gIndividualMilitiaVector.begin( ); it != itend; ++it )
{
if ( !((*it).flagmask & (MILITIAFLAG_DEAD | MILITIAFLAG_FIRED)) && (*it).sector == aSector && (*it).soldierclass == aSoldierClass )
{
// fitting data found - now we have to make sure this one isn't already in use
BOOLEAN found = FALSE;
SOLDIERTYPE* pSoldier;
INT32 cnt = gTacticalStatus.Team[MILITIA_TEAM].bFirstID;
INT32 lastid = gTacticalStatus.Team[MILITIA_TEAM].bLastID;
for ( pSoldier = MercPtrs[cnt]; cnt < lastid; ++cnt, ++pSoldier )
{
if ( pSoldier && pSoldier->bActive && (*it).id == pSoldier->usIndividualMilitiaID && IsLegalMilitiaId( pSoldier->usIndividualMilitiaID ) )
{
found = TRUE;
break;
}
}
if ( !found )
{
return (*it).id;
}
}
}
// if this feature is on and we get to this point, then there aren't enough individual militia. This is odd, the player should be informed
if ( gGameExternalOptions.fIndividualMilitia )
ScreenMsg( FONT_MCOLOR_RED, MSG_INTERFACE, L"Possible error: Not enough individual militia found in GetIdOfUnusedindividualMilitia" );
// nobody found. That shouldn't really happen, as we are supposed to create data whenever new militia is created. Create new data and use that
return CreateNewIndividualMilitia( aSoldierClass, MO_ARULCO, aSector );
}
// handle possible militia promotion and individual militia update
void HandlePossibleMilitiaPromotion( SOLDIERTYPE* pSoldier )
{
// we not only handle promotions here, but basically update this guy
MILITIA militia;
if ( GetMilitia( pSoldier->usIndividualMilitiaID, &militia ) )
{
militia.AddKills( pSoldier->ubMilitiaKills, pSoldier->ubMilitiaAssists );
// if we have enough points, promote
if ( militia.soldierclass == SOLDIER_CLASS_GREEN_MILITIA )
{
if ( militia.promotionpoints >= gGameExternalOptions.usIndividualMilitia_PromotionPoints_To_Regular )
{
if ( militia.promotionpoints >= gGameExternalOptions.usIndividualMilitia_PromotionPoints_To_Regular + gGameExternalOptions.usIndividualMilitia_PromotionPoints_To_Elite )
{
++gbGreenToElitePromotions;
++gbMilitiaPromotions;
pSoldier->ubSoldierClass = SOLDIER_CLASS_ELITE_MILITIA;
StrategicPromoteMilitiaInSector( pSoldier->sSectorX, pSoldier->sSectorY, GREEN_MILITIA, 1 );
StrategicPromoteMilitiaInSector( pSoldier->sSectorX, pSoldier->sSectorY, REGULAR_MILITIA, 1 );
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szIdividualMilitiaWebsiteText[18], militia.GetName( ) );
}
else
{
++gbGreenToRegPromotions;
++gbMilitiaPromotions;
pSoldier->ubSoldierClass = SOLDIER_CLASS_REG_MILITIA;
StrategicPromoteMilitiaInSector( pSoldier->sSectorX, pSoldier->sSectorY, GREEN_MILITIA, 1 );
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szIdividualMilitiaWebsiteText[17], militia.GetName( ) );
}
}
}
else if ( militia.soldierclass == SOLDIER_CLASS_REG_MILITIA )
{
if ( militia.promotionpoints >= gGameExternalOptions.usIndividualMilitia_PromotionPoints_To_Regular + gGameExternalOptions.usIndividualMilitia_PromotionPoints_To_Elite )
{
++gbRegToElitePromotions;
++gbMilitiaPromotions;
pSoldier->ubSoldierClass = SOLDIER_CLASS_ELITE_MILITIA;
StrategicPromoteMilitiaInSector( pSoldier->sSectorX, pSoldier->sSectorY, REGULAR_MILITIA, 1 );
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szIdividualMilitiaWebsiteText[18], militia.GetName( ) );
}
}
// add a battle report if there was a battle (if there was a battle there will have been participants
if ( gCurrentIncident.usParticipants[CAMPAIGNHISTORY_SD_MILITIA_GREEN] +
gCurrentIncident.usParticipants[CAMPAIGNHISTORY_SD_MILITIA_REGULAR] +
gCurrentIncident.usParticipants[CAMPAIGNHISTORY_SD_MILITIA_ELITE] )
{
MILITIA_BATTLEREPORT report;
report.id = GetIdOfCurrentlyOngoingIncident( );
if ( pSoldier->stats.bLife < OKLIFE )
report.flagmask |= MILITIA_BATTLEREPORT_FLAG_WOUNDED_COMA;
if ( pSoldier->ubMilitiaKills )
report.flagmask |= MILITIA_BATTLEREPORT_FLAG_KILLEDENEMY;
if ( militia.healthratio - 100.0f * pSoldier->stats.bLife / pSoldier->stats.bLifeMax > 50 )
report.flagmask |= MILITIA_BATTLEREPORT_FLAG_WOUNDED_HEAVY;
else if ( militia.healthratio - 100.0f * pSoldier->stats.bLife / pSoldier->stats.bLifeMax > 5 )
report.flagmask |= MILITIA_BATTLEREPORT_FLAG_WOUNDED_SMALL;
militia.history.push_back( report );
}
// separate report for promotion
if ( militia.soldierclass != pSoldier->ubSoldierClass )
{
MILITIA_BATTLEREPORT report;
report.id = GetWorldTotalMin( );
report.flagmask |= MILITIA_BATTLEREPORT_FLAG_PROMOTED;
militia.history.push_back( report );
}
militia.healthratio = 100.0f * pSoldier->stats.bLife / pSoldier->stats.bLifeMax;
militia.soldierclass = pSoldier->ubSoldierClass;
UpdateMilitia( militia );
}
else if ( pSoldier->ubMilitiaKills + pSoldier->ubMilitiaAssists > 0 )
{
UINT8 ubMilitiaRank = SoldierClassToMilitiaRank( pSoldier->ubSoldierClass );
UINT8 ubPromotions = CheckOneMilitiaForPromotion( pSoldier->sSectorX, pSoldier->sSectorY, ubMilitiaRank, 2 * pSoldier->ubMilitiaKills + pSoldier->ubMilitiaAssists );
if ( ubPromotions )
{
if ( ubPromotions == 2 )
{
++gbGreenToElitePromotions;
++gbMilitiaPromotions;
pSoldier->ubSoldierClass = SOLDIER_CLASS_ELITE_MILITIA;
}
else if ( pSoldier->ubSoldierClass == SOLDIER_CLASS_GREEN_MILITIA )
{
++gbGreenToRegPromotions;
++gbMilitiaPromotions;
pSoldier->ubSoldierClass = SOLDIER_CLASS_REG_MILITIA;
}
else if ( pSoldier->ubSoldierClass == SOLDIER_CLASS_REG_MILITIA )
{
++gbRegToElitePromotions;
++gbMilitiaPromotions;
pSoldier->ubSoldierClass = SOLDIER_CLASS_ELITE_MILITIA;
}
}
}
pSoldier->ubMilitiaKills = 0;
pSoldier->ubMilitiaAssists = 0;
}
void MoveIndividualMilitiaProfiles( UINT8 aSourceSector, UINT8 aTargetSector, UINT8 usGreens, UINT8 usRegulars, UINT8 usElites )
{
std::vector<MILITIA>::iterator itend = gIndividualMilitiaVector.end( );
for ( std::vector<MILITIA>::iterator it = gIndividualMilitiaVector.begin( ); it != itend; ++it )
{
if ( !usGreens && !usRegulars && !usElites )
return;
if ( !((*it).flagmask & (MILITIAFLAG_DEAD | MILITIAFLAG_FIRED)) && (*it).sector == aSourceSector )
{
if ( usGreens && ( *it ).soldierclass == SOLDIER_CLASS_GREEN_MILITIA )
{
(*it).sector = aTargetSector;
--usGreens;
}
else if ( usRegulars && (*it).soldierclass == SOLDIER_CLASS_REG_MILITIA )
{
(*it).sector = aTargetSector;
--usRegulars;
}
else if ( usElites && (*it).soldierclass == SOLDIER_CLASS_ELITE_MILITIA )
{
(*it).sector = aTargetSector;
--usElites;
}
}
}
// if this feature is on and we get to this point, then there aren't enough individual militia. This is odd, the player should be informed
if ( gGameExternalOptions.fIndividualMilitia )
ScreenMsg( FONT_MCOLOR_RED, MSG_INTERFACE, L"Possible error: Not enough individual militia found in MoveIndividualMilitiaProfiles" );
}
// militia are disbanded - we have to take note of that
void DisbandIndividualMilitia( UINT8 aSector, UINT8 usGreens, UINT8 usRegulars, UINT8 usElites )
{
std::vector<MILITIA>::iterator itend = gIndividualMilitiaVector.end( );
for ( std::vector<MILITIA>::iterator it = gIndividualMilitiaVector.begin( ); it != itend; ++it )
{
if ( !usGreens && !usRegulars && !usElites )
return;
if ( !((*it).flagmask & (MILITIAFLAG_DEAD | MILITIAFLAG_FIRED)) && (*it).sector == aSector )
{
if ( usGreens && (*it).soldierclass == SOLDIER_CLASS_GREEN_MILITIA )
{
--usGreens;
}
else if ( usRegulars && (*it).soldierclass == SOLDIER_CLASS_REG_MILITIA )
{
--usRegulars;
}
else if ( usElites && (*it).soldierclass == SOLDIER_CLASS_ELITE_MILITIA )
{
--usElites;
}
(*it).Fire();
}
}
// if this feature is on and we get to this point, then there aren't enough individual militia. This is odd, the player should be informed
if ( gGameExternalOptions.fIndividualMilitia )
ScreenMsg( FONT_MCOLOR_RED, MSG_INTERFACE, L"Possible error: Not enough individual militia found in DisbandIndividualMilitia" );
}
void PromoteIndividualMilitia( UINT8 aSector, UINT8 aSoldierClass )
{
std::vector<MILITIA>::iterator itend = gIndividualMilitiaVector.end( );
for ( std::vector<MILITIA>::iterator it = gIndividualMilitiaVector.begin( ); it != itend; ++it )
{
if ( !((*it).flagmask & (MILITIAFLAG_DEAD | MILITIAFLAG_FIRED)) && (*it).sector == aSector && (*it).soldierclass == aSoldierClass )
{
(*it).soldierclass++;
// to properly update promotion points
(*it).AddKills(0, 0);
return;
}
}
// if this feature is on and we get to this point, then there aren't enough individual militia. This is odd, the player should be informed
if ( gGameExternalOptions.fIndividualMilitia )
ScreenMsg( FONT_MCOLOR_RED, MSG_INTERFACE, L"Possible error: Not enough individual militia found in PromoteIndividualMilitia" );
}
// return the sum of daily wages, and the number of individual militia per class
UINT32 GetDailyUpkeep_IndividualMilitia( UINT32& arNumGreen, UINT32& arNumRegular, UINT32& arNumElite )
{
UINT32 cost = 0;
std::vector<MILITIA>::iterator itend = gIndividualMilitiaVector.end( );
for ( std::vector<MILITIA>::iterator it = gIndividualMilitiaVector.begin( ); it != itend; ++it )
{
if ( !((*it).flagmask & (MILITIAFLAG_DEAD | MILITIAFLAG_FIRED)) )
{
if ( (*it).soldierclass == SOLDIER_CLASS_REG_MILITIA )
{
++arNumRegular;
}
else if ( (*it).soldierclass == SOLDIER_CLASS_ELITE_MILITIA )
{
++arNumElite;
}
else
{
++arNumGreen;
}
cost += (*it).GetWage();
}
}
return cost;
}
// if the player repositions militia in a town in strategic, we need to reposition militia as well
void PickIndividualMilitia( UINT8 aSector, UINT8 ubType, UINT16 aNumber )
{
std::vector<MILITIA>::iterator itend = gIndividualMilitiaVector.end( );
for ( std::vector<MILITIA>::iterator it = gIndividualMilitiaVector.begin( ); it != itend; ++it )
{
if ( !aNumber )
return;
if ( !((*it).flagmask & (MILITIAFLAG_DEAD | MILITIAFLAG_FIRED | MILITIAFLAG_NEEDS_SECTOR)) && (*it).sector == aSector )
{
if ( ubType == GREEN_MILITIA && (*it).soldierclass == SOLDIER_CLASS_GREEN_MILITIA )
{
(*it).flagmask |= MILITIAFLAG_NEEDS_SECTOR;
--aNumber;
}
else if ( ubType == REGULAR_MILITIA && (*it).soldierclass == SOLDIER_CLASS_REG_MILITIA )
{
(*it).flagmask |= MILITIAFLAG_NEEDS_SECTOR;
--aNumber;
}
else if ( ubType == ELITE_MILITIA && (*it).soldierclass == SOLDIER_CLASS_ELITE_MILITIA )
{
(*it).flagmask |= MILITIAFLAG_NEEDS_SECTOR;
--aNumber;
}
}
}
// if this feature is on and we get to this point, then there aren't enough individual militia. This is odd, the player should be informed
if ( gGameExternalOptions.fIndividualMilitia )
ScreenMsg( FONT_MCOLOR_RED, MSG_INTERFACE, L"Possible error: Not enough individual militia found in PickIndividualMilitia" );
}
void DropIndividualMilitia( UINT8 aSector, UINT8 ubType, UINT16 aNumber )
{
std::vector<MILITIA>::iterator itend = gIndividualMilitiaVector.end( );
for ( std::vector<MILITIA>::iterator it = gIndividualMilitiaVector.begin( ); it != itend; ++it )
{
if ( !aNumber )
return;
if ( !((*it).flagmask & (MILITIAFLAG_DEAD | MILITIAFLAG_FIRED)) && ((*it).flagmask & MILITIAFLAG_NEEDS_SECTOR) )
{
if ( ubType == GREEN_MILITIA && (*it).soldierclass == SOLDIER_CLASS_GREEN_MILITIA )
{
(*it).flagmask &= ~MILITIAFLAG_NEEDS_SECTOR;
(*it).sector = aSector;
--aNumber;
}
else if ( ubType == REGULAR_MILITIA && (*it).soldierclass == SOLDIER_CLASS_REG_MILITIA )
{
(*it).flagmask &= ~MILITIAFLAG_NEEDS_SECTOR;
(*it).sector = aSector;
--aNumber;
}
else if ( ubType == ELITE_MILITIA && (*it).soldierclass == SOLDIER_CLASS_ELITE_MILITIA )
{
(*it).flagmask &= ~MILITIAFLAG_NEEDS_SECTOR;
(*it).sector = aSector;
--aNumber;
}
}
}
// if this feature is on and we get to this point, then there aren't enough individual militia. This is odd, the player should be informed
if ( gGameExternalOptions.fIndividualMilitia )
ScreenMsg( FONT_MCOLOR_RED, MSG_INTERFACE, L"Possible error: Not enough individual militia found in DropIndividualMilitia" );
}
+185
View File
@@ -0,0 +1,185 @@
#ifndef _MILITIA_INDIVIDUAL_H
#define _MILITIA_INDIVIDUAL_H
/**
* @file
* @author Flugente (bears-pit.com)
*/
// These functions are used for the individual militia feature
#include "Assignments.h"
#include "soldier profile type.h"
#include "Animation Data.h"
#include "Soldier Create.h"
// not used atm
/*typedef struct
{
UINT16 item; // item id, refers to the ones in Items.xml
UINT16 status; // status of item. In case of ammo items, this instead refers to the ammo count. No bullets lost here.
} MILITIA_ITEM;*/
/*enum
{
WISDOM = NUM_TRAINABLE_STATS,
LEVEL,
HEALTH_CURRENT,
NUM_TOTAL_STATS
};*/
#define MILITIA_BATTLEREPORT_FLAG_RECRUITED 0x00000001 // this was not a battle, but we were recruited - use id as timestamp in hours
#define MILITIA_BATTLEREPORT_FLAG_PROMOTED 0x00000002 // this was not a battle, but we were promoted - use id as timestamp in hours
#define MILITIA_BATTLEREPORT_FLAG_DIED 0x00000004 // militia died in this battle
#define MILITIA_BATTLEREPORT_FLAG_WOUNDED_SMALL 0x00000008 // was lightly wounded
#define MILITIA_BATTLEREPORT_FLAG_WOUNDED_HEAVY 0x00000010 // was heavily wounded
#define MILITIA_BATTLEREPORT_FLAG_WOUNDED_COMA 0x00000020 // wounds were so heavy that we fell into a coma
#define MILITIA_BATTLEREPORT_FLAG_KILLEDENEMY 0x00000040 // killed an enemy
#define MILITIA_BATTLEREPORT_FLAG_FIRED 0x00000080 // militia was fired
struct MILITIA_BATTLEREPORT
{
MILITIA_BATTLEREPORT( ) : id( 0 ), flagmask( 0 ) {}
UINT32 id; // id of battle militia took part in. Ties to campaign history, thus we know with more detail what happened there.
UINT32 flagmask; // we can note up to 16 different properties here - perhaps wether we were a reinforcement, or were wounded and such
};
// a militia's origin affects the chances of his makeout
enum MilitiaOrigin
{
MO_ARULCO, // standard, militia was an aruclan volunteer that has been trained by the player
MO_PMC, // militia was hired from a PMC by the player
MO_DEFECTOR, // militia was an enemy captured by the player and switched to the player side during interrogation
MO_MAX
};
// This struct defines necessary data for a pool of militia origins.
// For example, if you want PMC militia to resemble eastern european buff guys, you only need to define the specific fore- and surnames,
// set the chance for huge male bodytpes high, and give according skin colour chances
typedef struct
{
// possible name pool
std::vector<std::wstring> szMale_Forename;
std::vector<std::wstring> szMale_Surname;
std::vector<std::wstring> szFemale_Forename;
std::vector<std::wstring> szFemale_Surname;
// chances for bodytypes and skin colours (hair is chosen auomatically according to coded scheme)
UINT8 chance_bodytype[ADULTFEMALEMONSTER];
UINT8 chance_skin[NUMSKINS];
UINT16 dailycost[MAX_MILITIA_LEVELS];
} MilitiaOriginData;
extern MilitiaOriginData gMilitiaOriginData[MO_MAX];
#define MILITIAFLAG_DEAD 0x00000001 // this guy is dead
#define MILITIAFLAG_FIRED 0x00000002 // this guy no longer works for us - we fired him, or didn't have the money to keep them
#define MILITIAFLAG_NEEDS_SECTOR 0x00000004 // as the player currently resets militia in a town's sector in the map, this militia's sector is not clear
class MILITIA
{
public:
MILITIA();
BOOLEAN Save( HWFILE hFile );
BOOLEAN Load( HWFILE hwFile );
STR16 GetName( );
STR16 GetSector( );
STR16 GetOriginSector( );
void AddKills( UINT16 aKills, UINT16 aAssists );
UINT16 GetWage();
void Fire(); // release militia from our service. Does not take care of actually removing a militia from the sector!
UINT32 id; // number of militia. Tied with one or more separate tables of names, this gives us a name
UINT32 flagmask; // individual flags - we are dead etc.
// origin
UINT8 origin; // one of MilitiaOrigin
UINT8 originsector; // sector militia was first created in
UINT8 sector; // sector militia currently is in
UINT8 age;
// visuals
UINT8 soldierclass; // green/veteran/elite
UINT8 bodytype; // male/bigmale1/bigmale2/female
UINT8 skin;
UINT8 hair;
// name
UINT16 forename;
UINT16 surname;
UINT16 callsign;
// As stats are highly dependent of game progress and current sector, storing the stats themselves is ill-advised.
// We thus only store the current HP percentage.
FLOAT healthratio;
UINT16 kills;
UINT16 assists;
// 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
char endOfPOD; // marker for end of POD (plain old data)
std::vector<MILITIA_BATTLEREPORT> history; // reports on all battles this militia took part in
};
#define SIZEOF_MILITIA_POD offsetof( MILITIA, endOfPOD )
// later on, make this an array with a vector for each sector
extern std::vector<MILITIA> gIndividualMilitiaVector;
void InitIndividualMilitiaData();
BOOLEAN SaveIndividualMilitiaData( HWFILE hwFile );
BOOLEAN LoadIndividualMilitiaData( HWFILE hwFile );
// wrapper functions to retrieve militia
UINT32 TotalNumberIndividualMilitia( );
UINT32 GetFreeIndividualMilitiaId();
BOOLEAN IsLegalMilitiaId( UINT32 aId );
// return militia with a certain id
BOOLEAN GetMilitia( UINT32 aId, MILITIA* apMilitia );
// update data
void UpdateMilitia( MILITIA aMilitia );
SOLDIERTYPE* GetUsedSoldierToIndividualMilitia( UINT32 aMilitiaId );
// update the health values of all militia in tactical
void UpdateAllMilitiaHealthInTactical();
void HandleHourlyMilitiaHealing( );
UINT32 CreateRandomIndividualMilitia( UINT8 aSoldierClass, UINT8 aOrigin, UINT8 aSector );
UINT32 CreateNewIndividualMilitia( UINT8 aSoldierClass, UINT8 aOrigin, UINT8 aSector );
UINT32 GetIdOfUnusedindividualMilitia( UINT8 aSoldierClass, UINT8 aSector );
// handle possible militia promotion and individual militia update
void HandlePossibleMilitiaPromotion( SOLDIERTYPE* pSoldier );
void MoveIndividualMilitiaProfiles( UINT8 aSourceSector, UINT8 aTargetSector, UINT8 usGreens, UINT8 usRegulars, UINT8 usElites );
// militia are disbanded - we have to take note of that
void DisbandIndividualMilitia( UINT8 aSector, UINT8 usGreens, UINT8 usRegulars, UINT8 usElites );
void PromoteIndividualMilitia( UINT8 aSector, UINT8 aSoldierClass );
// return the sum of daily wages, and the number of individual militia per class
UINT32 GetDailyUpkeep_IndividualMilitia( UINT32& arNumGreen, UINT32& arNumRegular, UINT32& arNumElite );
// if the player repositions militia in a town in strategic, we need to reposition militia as well
void PickIndividualMilitia( UINT8 aSector, UINT8 ubType, UINT16 aNumber );
void DropIndividualMilitia( UINT8 aSector, UINT8 ubType, UINT16 aNumber );
#endif
+69 -22
View File
@@ -33,6 +33,7 @@
#include "MilitiaSquads.h"
#include "Reinforcement.h"
#include "Inventory Choosing.h" // added by Flugente for MoveOneMilitiaEquipmentSet() and MoveMilitiaEquipment()
#include "MilitiaIndividual.h" // added by Flugente
// Debug defines
@@ -325,7 +326,7 @@ void GenerateMilitiaSquad(INT16 sMapX, INT16 sMapY, INT16 sTMapX, INT16 sTMapY,
// Do we have room in the target sector?
if ( usTotalMilitiaAtTarget + trained < gGameExternalOptions.iMaxMilitiaPerSector )
{
if ( ubTargetElite > 0 )
if (ubTargetElite > 0)
{
// Add elite.
++numcreated[ELITE_MILITIA];
@@ -334,7 +335,7 @@ void GenerateMilitiaSquad(INT16 sMapX, INT16 sMapY, INT16 sTMapX, INT16 sTMapY,
++trained;
fFoundOne = TRUE;
}
else if ( ubTargetRegular > 0 )
else if (ubTargetRegular > 0)
{
// Add regular.
++numcreated[REGULAR_MILITIA];
@@ -343,7 +344,7 @@ void GenerateMilitiaSquad(INT16 sMapX, INT16 sMapY, INT16 sTMapX, INT16 sTMapY,
++trained;
fFoundOne = TRUE;
}
else if ( ubTargetGreen > 0 )
else if (ubTargetGreen > 0)
{
// Add green.
++numcreated[GREEN_MILITIA];
@@ -382,6 +383,16 @@ 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 ) );
for ( int i = 0; i < numcreated[REGULAR_MILITIA]; ++i )
CreateNewIndividualMilitia( REGULAR_MILITIA, MO_ARULCO, SECTOR( sTMapX, sTMapY ) );
for ( int i = 0; i < numcreated[ELITE_MILITIA]; ++i )
CreateNewIndividualMilitia( ELITE_MILITIA, MO_ARULCO, SECTOR( sTMapX, sTMapY ) );
}
// This reduces the group back to "maximum" size. It starts by eliminating extra greens, then regulars, then elites.
@@ -559,8 +570,12 @@ void MoveMilitiaSquad(INT16 sMapX, INT16 sMapY, INT16 sTMapX, INT16 sTMapY, BOOL
UINT8 elites = max(0, bElitesDestTeam - pTSectorInfo->ubNumberOfCivsAtLevel[ ELITE_MILITIA ]);
UINT8 regulars = max(0, bRegularsDestTeam - pTSectorInfo->ubNumberOfCivsAtLevel[ REGULAR_MILITIA ]);
UINT8 greens = max(0, bGreensDestTeam - pTSectorInfo->ubNumberOfCivsAtLevel[ GREEN_MILITIA ]);
MoveMilitiaEquipment(sMapX, sMapY, sTMapX, sTMapY, elites, regulars, greens);
// Flugente: update individual militia data
UpdateAllMilitiaHealthInTactical( );
// Flugente: disease
PopulationMove( sMapX, sMapY, sTMapX, sTMapY, elites + regulars + greens );
@@ -572,6 +587,9 @@ void MoveMilitiaSquad(INT16 sMapX, INT16 sMapY, INT16 sTMapX, INT16 sTMapY, BOOL
StrategicRemoveMilitiaFromSector( sTMapX, sTMapY, REGULAR_MILITIA, pTSectorInfo->ubNumberOfCivsAtLevel[ REGULAR_MILITIA ] );
StrategicRemoveMilitiaFromSector( sTMapX, sTMapY, ELITE_MILITIA, pTSectorInfo->ubNumberOfCivsAtLevel[ ELITE_MILITIA ] );
// Flugente: move along individual militia data
MoveIndividualMilitiaProfiles( SECTOR( sMapX, sMapY ), SECTOR( sTMapX, sTMapY ), greens, regulars, elites );
// Add new militia.
StrategicAddMilitiaToSector( sMapX, sMapY, GREEN_MILITIA, bGreensSourceTeam );
StrategicAddMilitiaToSector( sMapX, sMapY, REGULAR_MILITIA, bRegularsSourceTeam );
@@ -597,21 +615,28 @@ void MoveMilitiaSquad(INT16 sMapX, INT16 sMapY, INT16 sTMapX, INT16 sTMapY, BOOL
UINT8 elites = max(0, bElitesDestTeam - pTSectorInfo->ubNumberOfCivsAtLevel[ ELITE_MILITIA ]);
UINT8 regulars = max(0, bRegularsDestTeam - pTSectorInfo->ubNumberOfCivsAtLevel[ REGULAR_MILITIA ]);
UINT8 greens = max(0, bGreensDestTeam - pTSectorInfo->ubNumberOfCivsAtLevel[ GREEN_MILITIA ]);
MoveMilitiaEquipment(sMapX, sMapY, sTMapX, sTMapY, elites, regulars, greens);
// Flugente: update individual militia data
UpdateAllMilitiaHealthInTactical( );
// Flugente: disease
PopulationMove( sMapX, sMapY, sTMapX, sTMapY, elites + regulars + greens );
// Add half team to target sector
StrategicAddMilitiaToSector( sTMapX, sTMapY, GREEN_MILITIA, bGreensDestTeam );
StrategicAddMilitiaToSector( sTMapX, sTMapY, REGULAR_MILITIA, bRegularsDestTeam );
StrategicAddMilitiaToSector( sTMapX, sTMapY, ELITE_MILITIA, bElitesDestTeam );
// Remove half team from source sector
StrategicRemoveMilitiaFromSector( sMapX, sMapY, GREEN_MILITIA, bGreensDestTeam );
StrategicRemoveMilitiaFromSector( sMapX, sMapY, REGULAR_MILITIA, bRegularsDestTeam );
StrategicRemoveMilitiaFromSector( sMapX, sMapY, ELITE_MILITIA, bElitesDestTeam );
// Flugente: move along individual militia data
MoveIndividualMilitiaProfiles( SECTOR( sMapX, sMapY ), SECTOR( sTMapX, sTMapY ), pSectorInfo->ubNumberOfCivsAtLevel[GREEN_MILITIA], pSectorInfo->ubNumberOfCivsAtLevel[REGULAR_MILITIA], pSectorInfo->ubNumberOfCivsAtLevel[ELITE_MILITIA] );
// Add half team to target sector
StrategicAddMilitiaToSector( sTMapX, sTMapY, GREEN_MILITIA, bGreensDestTeam );
StrategicAddMilitiaToSector( sTMapX, sTMapY, REGULAR_MILITIA, bRegularsDestTeam );
StrategicAddMilitiaToSector( sTMapX, sTMapY, ELITE_MILITIA, bElitesDestTeam );
// Units that move into an empty square do not get to move again.
AddToBlockMoveList( sTMapX, sTMapY );
}
@@ -683,8 +708,12 @@ void MoveMilitiaSquad(INT16 sMapX, INT16 sMapY, INT16 sTMapX, INT16 sTMapY, BOOL
UINT8 elites = max(0, bElitesDestTeam - pTSectorInfo->ubNumberOfCivsAtLevel[ ELITE_MILITIA ]);
UINT8 regulars = max(0, bRegularsDestTeam - pTSectorInfo->ubNumberOfCivsAtLevel[ REGULAR_MILITIA ]);
UINT8 greens = max(0, bGreensDestTeam - pTSectorInfo->ubNumberOfCivsAtLevel[ GREEN_MILITIA ]);
MoveMilitiaEquipment(sMapX, sMapY, sTMapX, sTMapY, elites, regulars, greens);
// Flugente: update individual militia data
UpdateAllMilitiaHealthInTactical( );
// Flugente: disease
PopulationMove( sMapX, sMapY, sTMapX, sTMapY, elites + regulars + greens );
@@ -696,6 +725,9 @@ void MoveMilitiaSquad(INT16 sMapX, INT16 sMapY, INT16 sTMapX, INT16 sTMapY, BOOL
StrategicRemoveMilitiaFromSector( sTMapX, sTMapY, REGULAR_MILITIA, pTSectorInfo->ubNumberOfCivsAtLevel[ REGULAR_MILITIA ] );
StrategicRemoveMilitiaFromSector( sTMapX, sTMapY, ELITE_MILITIA, pTSectorInfo->ubNumberOfCivsAtLevel[ ELITE_MILITIA ] );
// Flugente: move along individual militia data
MoveIndividualMilitiaProfiles( SECTOR( sMapX, sMapY ), SECTOR( sTMapX, sTMapY ), greens, regulars, elites );
// Add new militia.
StrategicAddMilitiaToSector( sMapX, sMapY, GREEN_MILITIA, bGreensSourceTeam );
StrategicAddMilitiaToSector( sMapX, sMapY, REGULAR_MILITIA, bRegularsSourceTeam );
@@ -709,15 +741,21 @@ void MoveMilitiaSquad(INT16 sMapX, INT16 sMapY, INT16 sTMapX, INT16 sTMapY, BOOL
// Flugente: mobiles take along their gear
MoveMilitiaEquipment(sMapX, sMapY, sTMapX, sTMapY, pSectorInfo->ubNumberOfCivsAtLevel[ ELITE_MILITIA ], pSectorInfo->ubNumberOfCivsAtLevel[ REGULAR_MILITIA ], pSectorInfo->ubNumberOfCivsAtLevel[ GREEN_MILITIA ]);
// Flugente: update individual militia data
UpdateAllMilitiaHealthInTactical( );
StrategicRemoveMilitiaFromSector( sMapX, sMapY, GREEN_MILITIA, pSectorInfo->ubNumberOfCivsAtLevel[GREEN_MILITIA] );
StrategicRemoveMilitiaFromSector( sMapX, sMapY, REGULAR_MILITIA, pSectorInfo->ubNumberOfCivsAtLevel[REGULAR_MILITIA] );
StrategicRemoveMilitiaFromSector( sMapX, sMapY, ELITE_MILITIA, pSectorInfo->ubNumberOfCivsAtLevel[ELITE_MILITIA] );
// Flugente: move along individual militia data
MoveIndividualMilitiaProfiles( SECTOR( sMapX, sMapY ), SECTOR( sTMapX, sTMapY ), pSectorInfo->ubNumberOfCivsAtLevel[GREEN_MILITIA], pSectorInfo->ubNumberOfCivsAtLevel[REGULAR_MILITIA], pSectorInfo->ubNumberOfCivsAtLevel[ELITE_MILITIA] );
// Entire group moves from Source to Target, leaving no one behind.
StrategicAddMilitiaToSector( sTMapX, sTMapY, GREEN_MILITIA, pSectorInfo->ubNumberOfCivsAtLevel[ GREEN_MILITIA ] );
StrategicAddMilitiaToSector( sTMapX, sTMapY, REGULAR_MILITIA, pSectorInfo->ubNumberOfCivsAtLevel[ REGULAR_MILITIA ] );
StrategicAddMilitiaToSector( sTMapX, sTMapY, ELITE_MILITIA, pSectorInfo->ubNumberOfCivsAtLevel[ ELITE_MILITIA ] );
StrategicRemoveMilitiaFromSector( sMapX, sMapY, GREEN_MILITIA, pSectorInfo->ubNumberOfCivsAtLevel[ GREEN_MILITIA ] );
StrategicRemoveMilitiaFromSector( sMapX, sMapY, REGULAR_MILITIA, pSectorInfo->ubNumberOfCivsAtLevel[ REGULAR_MILITIA ] );
StrategicRemoveMilitiaFromSector( sMapX, sMapY, ELITE_MILITIA, pSectorInfo->ubNumberOfCivsAtLevel[ ELITE_MILITIA ] );
// Block target group from moving. It has just assimilated another group.
AddToBlockMoveList( sTMapX, sTMapY );
}
@@ -754,6 +792,9 @@ BOOLEAN MoveOneBestMilitiaMan(INT16 sMapX, INT16 sMapY, INT16 sTMapX, INT16 sTMa
{
StrategicAddMilitiaToSector( sTMapX, sTMapY, ELITE_MILITIA, 1 );
StrategicRemoveMilitiaFromSector( sMapX, sMapY, ELITE_MILITIA, 1 );
MoveIndividualMilitiaProfiles( SECTOR( sMapX, sMapY ), SECTOR( sTMapX, sTMapY ), 0, 0, 1 );
return TRUE;
}
@@ -761,6 +802,9 @@ BOOLEAN MoveOneBestMilitiaMan(INT16 sMapX, INT16 sMapY, INT16 sTMapX, INT16 sTMa
{
StrategicAddMilitiaToSector( sTMapX, sTMapY, REGULAR_MILITIA, 1 );
StrategicRemoveMilitiaFromSector( sMapX, sMapY, REGULAR_MILITIA, 1 );
MoveIndividualMilitiaProfiles( SECTOR( sMapX, sMapY ), SECTOR( sTMapX, sTMapY ), 0, 1, 0 );
return TRUE;
}
@@ -768,6 +812,9 @@ BOOLEAN MoveOneBestMilitiaMan(INT16 sMapX, INT16 sMapY, INT16 sTMapX, INT16 sTMa
{
StrategicAddMilitiaToSector( sTMapX, sTMapY, GREEN_MILITIA, 1 );
StrategicRemoveMilitiaFromSector( sMapX, sMapY, GREEN_MILITIA, 1 );
MoveIndividualMilitiaProfiles( SECTOR( sMapX, sMapY ), SECTOR( sTMapX, sTMapY ), 1, 0, 0 );
return TRUE;
}
@@ -1894,7 +1941,7 @@ BOOLEAN CallMilitiaReinforcements( INT16 sTargetMapX, INT16 sTargetMapY, INT16 s
gpAttackDirs[guiDirNumber][0] = uiNumGreen = MilitiaInSectorOfRank( sTargetMapX, sTargetMapY, GREEN_MILITIA );
gpAttackDirs[guiDirNumber][1] = uiNumReg = MilitiaInSectorOfRank( sTargetMapX, sTargetMapY, REGULAR_MILITIA );
gpAttackDirs[guiDirNumber][2] = uiNumElite = MilitiaInSectorOfRank( sTargetMapX, sTargetMapY, ELITE_MILITIA );
gpAttackDirs[guiDirNumber][3] = INSERTION_CODE_CENTER;
gpAttackDirs[ guiDirNumber ][3] = INSERTION_CODE_CENTER;
guiDirNumber = insertioncode + 1;
@@ -1913,7 +1960,7 @@ BOOLEAN CallMilitiaReinforcements( INT16 sTargetMapX, INT16 sTargetMapY, INT16 s
gpAttackDirs[guiDirNumber][0] += militia_green - uiNumGreen;
gpAttackDirs[guiDirNumber][1] += militia_troop - uiNumReg;
gpAttackDirs[guiDirNumber][2] += militia_elite - uiNumElite;
gpAttackDirs[guiDirNumber][3] = insertioncode;
gpAttackDirs[ guiDirNumber ][3] = insertioncode;
uiNumGreen = militia_green;
uiNumReg = militia_troop;
@@ -2202,9 +2249,9 @@ void GenerateDirectionInfosForTraining( INT16 sMapX, INT16 sMapY, UINT8* uiDirNu
pMoveDir[ *uiDirNumber ][1] = usMilitiaCapacity + usUpgradeCapacity;
pMoveDir[ *uiDirNumber ][2] = INSERTION_CODE_NORTH;
#ifdef DEBUG_SHOW_RATINGS
#ifdef DEBUG_SHOW_RATINGS
if( DEBUG_RATINGS_CONDITION )ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Priority of north direction - %ld", pMoveDir[ *uiDirNumber ][1]);
#endif
#endif
++(*uiDirNumber);
}
@@ -2230,9 +2277,9 @@ void GenerateDirectionInfosForTraining( INT16 sMapX, INT16 sMapY, UINT8* uiDirNu
pMoveDir[ *uiDirNumber ][1] = usMilitiaCapacity + usUpgradeCapacity;
pMoveDir[ *uiDirNumber ][2] = INSERTION_CODE_WEST;
#ifdef DEBUG_SHOW_RATINGS
#ifdef DEBUG_SHOW_RATINGS
if( DEBUG_RATINGS_CONDITION )ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Priority of north direction - %ld", pMoveDir[ *uiDirNumber ][1]);
#endif
#endif
++(*uiDirNumber);
}
@@ -2258,9 +2305,9 @@ void GenerateDirectionInfosForTraining( INT16 sMapX, INT16 sMapY, UINT8* uiDirNu
pMoveDir[ *uiDirNumber ][1] = usMilitiaCapacity + usUpgradeCapacity;
pMoveDir[ *uiDirNumber ][2] = INSERTION_CODE_SOUTH;
#ifdef DEBUG_SHOW_RATINGS
#ifdef DEBUG_SHOW_RATINGS
if( DEBUG_RATINGS_CONDITION )ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Priority of north direction - %ld", pMoveDir[ *uiDirNumber ][1]);
#endif
#endif
++(*uiDirNumber);
}
@@ -2286,9 +2333,9 @@ void GenerateDirectionInfosForTraining( INT16 sMapX, INT16 sMapY, UINT8* uiDirNu
pMoveDir[ *uiDirNumber ][1] = usMilitiaCapacity + usUpgradeCapacity;
pMoveDir[ *uiDirNumber ][2] = INSERTION_CODE_EAST;
#ifdef DEBUG_SHOW_RATINGS
#ifdef DEBUG_SHOW_RATINGS
if( DEBUG_RATINGS_CONDITION )ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Priority of north direction - %ld", pMoveDir[ *uiDirNumber ][1]);
#endif
#endif
++(*uiDirNumber);
}
+10
View File
@@ -51,6 +51,7 @@
#include "Reinforcement.h" // added by Flugente for AddPossiblePendingMilitiaToBattle()
#include "Militia Control.h" // added by Flugente for ResetMilitia()
#include "Creature Spreading.h" // added by Flugente
#include "MilitiaIndividual.h" // added by Flugente
#endif
#include "MilitiaSquads.h"
@@ -2281,6 +2282,9 @@ void GroupArrivedAtSector( UINT8 ubGroupID, BOOLEAN fCheckForBattle, BOOLEAN fNe
if ( gGameExternalOptions.fMilitiaUseSectorInventory )
TeamDropAll( MILITIA_TEAM );
// Flugente: update individual militia data
UpdateAllMilitiaHealthInTactical( );
// 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
gfStrategicMilitiaChangesMade = TRUE;
@@ -2294,6 +2298,9 @@ void GroupArrivedAtSector( UINT8 ubGroupID, BOOLEAN fCheckForBattle, BOOLEAN fNe
// move the gear along to the next sector
MoveMilitiaEquipment( pGroup->ubPrevX, pGroup->ubPrevY, pGroup->ubSectorX, pGroup->ubSectorY, pGroup->pEnemyGroup->ubNumElites, pGroup->pEnemyGroup->ubNumTroops, pGroup->pEnemyGroup->ubNumAdmins );
// Flugente: move along individual militia data
MoveIndividualMilitiaProfiles( SECTOR( pGroup->ubPrevX, pGroup->ubPrevY ), SECTOR( pGroup->ubSectorX, pGroup->ubSectorY ), pGroup->pEnemyGroup->ubNumAdmins, pGroup->pEnemyGroup->ubNumTroops, pGroup->pEnemyGroup->ubNumElites );
// if this is the last sector along the path, destroy the group after this and make the militia static
if ( !fBattlePending &&GroupAtFinalDestination( pGroup ) )
{
@@ -2309,6 +2316,9 @@ void GroupArrivedAtSector( UINT8 ubGroupID, BOOLEAN fCheckForBattle, BOOLEAN fNe
// move the gear along to the next sector
MoveMilitiaEquipment( pGroup->ubPrevX, pGroup->ubPrevY, pGroup->ubSectorX, pGroup->ubSectorY, pGroup->pEnemyGroup->ubNumElites, pGroup->pEnemyGroup->ubNumTroops, pGroup->pEnemyGroup->ubNumAdmins );
// Flugente: move along individual militia data
MoveIndividualMilitiaProfiles( SECTOR( pGroup->ubPrevX, pGroup->ubPrevY ), SECTOR( pGroup->ubSectorX, pGroup->ubSectorY ), pGroup->pEnemyGroup->ubNumAdmins, pGroup->pEnemyGroup->ubNumTroops, pGroup->pEnemyGroup->ubNumElites );
// if this is the last sector along the path, destroy the group after this and make the militia static
if ( !fBattlePending && GroupAtFinalDestination( pGroup ) )
{
+8
View File
@@ -442,6 +442,10 @@
RelativePath=".\MilitiaSquads.h"
>
</File>
<File
RelativePath=".\MilitiaIndividual.h"
>
</File>
<File
RelativePath=".\Player Command.h"
>
@@ -652,6 +656,10 @@
RelativePath=".\MilitiaSquads.cpp"
>
</File>
<File
RelativePath=".\MilitiaIndividual.cpp"
>
</File>
<File
RelativePath=".\Player Command.cpp"
>
+8
View File
@@ -442,6 +442,10 @@
RelativePath="MilitiaSquads.h"
>
</File>
<File
RelativePath="MilitiaIndividual.h"
>
</File>
<File
RelativePath="Player Command.h"
>
@@ -650,6 +654,10 @@
RelativePath="MilitiaSquads.cpp"
>
</File>
<File
RelativePath="MilitiaIndividual.cpp"
>
</File>
<File
RelativePath="Player Command.cpp"
>
+2
View File
@@ -49,6 +49,7 @@
<ClInclude Include="Meanwhile.h" />
<ClInclude Include="Merc Contract.h" />
<ClInclude Include="MilitiaSquads.h" />
<ClInclude Include="MilitiaIndividual.h" />
<ClInclude Include="Player Command.h" />
<ClInclude Include="PreBattle Interface.h" />
<ClInclude Include="Queen Command.h" />
@@ -102,6 +103,7 @@
<ClCompile Include="Meanwhile.cpp" />
<ClCompile Include="Merc Contract.cpp" />
<ClCompile Include="MilitiaSquads.cpp" />
<ClCompile Include="MilitiaIndividual.cpp" />
<ClCompile Include="Player Command.cpp" />
<ClCompile Include="PreBattle Interface.cpp" />
<ClCompile Include="Queen Command.cpp" />
@@ -80,6 +80,9 @@
</ClInclude>
<ClInclude Include="MilitiaSquads.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="MilitiaIndividual.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Player Command.h">
<Filter>Header Files</Filter>
@@ -235,6 +238,9 @@
</ClCompile>
<ClCompile Include="MilitiaSquads.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="MilitiaIndividual.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Player Command.cpp">
<Filter>Source Files</Filter>
+2
View File
@@ -48,6 +48,7 @@
<ClInclude Include="mapscreen.h" />
<ClInclude Include="Meanwhile.h" />
<ClInclude Include="Merc Contract.h" />
<ClInclude Include="MilitiaIndividual.h" />
<ClInclude Include="MilitiaSquads.h" />
<ClInclude Include="Player Command.h" />
<ClInclude Include="PreBattle Interface.h" />
@@ -101,6 +102,7 @@
<ClCompile Include="mapscreen.cpp" />
<ClCompile Include="Meanwhile.cpp" />
<ClCompile Include="Merc Contract.cpp" />
<ClCompile Include="MilitiaIndividual.cpp" />
<ClCompile Include="MilitiaSquads.cpp" />
<ClCompile Include="Player Command.cpp" />
<ClCompile Include="PreBattle Interface.cpp" />
@@ -159,6 +159,9 @@
<ClInclude Include="ASD.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="MilitiaIndividual.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="AI Viewer.cpp">
@@ -350,5 +353,8 @@
<ClCompile Include="ASD.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="MilitiaIndividual.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>
+62 -13
View File
@@ -31,6 +31,7 @@
#include "Map Screen Interface Map.h"
#include "laptop.h" // added by Flugente
#include "Game Event Hook.h" // added by Flugente
#include "MilitiaIndividual.h" // added by Flugente
#endif
// HEADROCK HAM 3: include these files so that a militia trainer's Effective Leadership can be determined. Used
@@ -128,6 +129,8 @@ BOOLEAN TownMilitiaTrainingPromotion( INT16 sMapX, INT16 sMapY )
// great! Promote a GREEN militia guy in the training sector to a REGULAR
StrategicPromoteMilitiaInSector( sMapX, sMapY, GREEN_MILITIA, 1 );
PromoteIndividualMilitia( SECTOR( sMapX, sMapY ), SOLDIER_CLASS_GREEN_MILITIA );
if ( sMapX == gWorldSectorX && sMapY == gWorldSectorY )
gfStrategicMilitiaChangesMade = TRUE;
@@ -149,6 +152,8 @@ BOOLEAN TownMilitiaTrainingPromotion( INT16 sMapX, INT16 sMapY )
// great! Promote a GREEN militia guy in the neighbouring sector to a REGULAR
StrategicPromoteMilitiaInSector( sNeighbourX, sNeighbourY, GREEN_MILITIA, 1 );
PromoteIndividualMilitia( SECTOR( sNeighbourX, sNeighbourY ), SOLDIER_CLASS_GREEN_MILITIA );
if ( sNeighbourX == gWorldSectorX && sNeighbourY == gWorldSectorY )
gfStrategicMilitiaChangesMade = TRUE;
@@ -168,6 +173,8 @@ BOOLEAN TownMilitiaTrainingPromotion( INT16 sMapX, INT16 sMapY )
// great! Promote a REGULAR militia guy in the training sector to a VETERAN
StrategicPromoteMilitiaInSector( sMapX, sMapY, REGULAR_MILITIA, 1 );
PromoteIndividualMilitia( SECTOR( sMapX, sMapY ), SOLDIER_CLASS_REG_MILITIA );
if ( sMapX == gWorldSectorX && sMapY == gWorldSectorY )
gfStrategicMilitiaChangesMade = TRUE;
@@ -189,6 +196,8 @@ BOOLEAN TownMilitiaTrainingPromotion( INT16 sMapX, INT16 sMapY )
// great! Promote a Regular militia guy in the neighbouring sector to a Veteran
StrategicPromoteMilitiaInSector( sNeighbourX, sNeighbourY, REGULAR_MILITIA, 1 );
PromoteIndividualMilitia( SECTOR( sNeighbourX, sNeighbourY ), SOLDIER_CLASS_REG_MILITIA );
if ( sNeighbourX == gWorldSectorX && sNeighbourY == gWorldSectorY )
gfStrategicMilitiaChangesMade = TRUE;
@@ -277,6 +286,8 @@ void TownMilitiaTrainingCompleted( SOLDIERTYPE *pTrainer, INT16 sMapX, INT16 sMa
// next, please!
++ubMilitiaTrained;
CreateNewIndividualMilitia( GREEN_MILITIA, MO_ARULCO, SECTOR( sMapX, sMapY ) );
}
else
{
@@ -301,6 +312,8 @@ void TownMilitiaTrainingCompleted( SOLDIERTYPE *pTrainer, INT16 sMapX, INT16 sMa
// next, please!
++ubMilitiaTrained;
CreateNewIndividualMilitia( GREEN_MILITIA, MO_ARULCO, SECTOR( sNeighbourX, sNeighbourY ) );
fFoundOne = TRUE;
break;
}
@@ -359,6 +372,8 @@ void TownMilitiaTrainingCompleted( SOLDIERTYPE *pTrainer, INT16 sMapX, INT16 sMa
// Flugente: if we trained militia, the PMC notices us and offers their services
if ( gGameExternalOptions.fPMC )
AddStrategicEvent( EVENT_PMC_EMAIL, GetWorldTotalMin() + 60 * (1 + Random(6)), 0 );
AddStrategicEvent( EVENT_MILITIAROSTER_EMAIL, GetWorldTotalMin( ) + 60 * (1 + Random( 4 )), 0 );
}
@@ -2232,6 +2247,9 @@ void HandleMilitiaUpkeepPayment( void )
// Find and remove militia across the map. This is done randomly, starting with elites.
UINT32 uiNumMilitiaDisbanded = 0;
UINT32 usGreenDisbanded = 0;
UINT32 usRegularsDisbanded = 0;
UINT32 usElitesDisbanded = 0;
MILITIA_LIST_TYPE MilitiaList[256];
@@ -2293,50 +2311,57 @@ void HandleMilitiaUpkeepPayment( void )
// Adjust list entry
MilitiaList[0].ubNumMobileElites--;
// Reduce debt appropriately
uiMoneyUnpaid -= gGameExternalOptions.usDailyCostMobileElite;
uiMoneyUnpaid -= gGameExternalOptions.usDailyCostMobile[ELITE_MILITIA];
// Increase tally of militia removed
++uiNumMilitiaDisbanded;
++usElitesDisbanded;
}
else if (MilitiaList[0].ubNumMobileRegulars > 0)
{
StrategicRemoveMilitiaFromSector( sX, sY, REGULAR_MILITIA, 1 );
MilitiaList[0].ubNumMobileRegulars--;
uiMoneyUnpaid -= gGameExternalOptions.usDailyCostMobileRegular;
uiMoneyUnpaid -= gGameExternalOptions.usDailyCostMobile[REGULAR_MILITIA];
++uiNumMilitiaDisbanded;
++usRegularsDisbanded;
}
else if (MilitiaList[0].ubNumMobileGreens > 0)
{
StrategicRemoveMilitiaFromSector( sX, sY, GREEN_MILITIA, 1 );
MilitiaList[0].ubNumMobileGreens--;
uiMoneyUnpaid -= gGameExternalOptions.usDailyCostMobileGreen;
uiMoneyUnpaid -= gGameExternalOptions.usDailyCostMobile[GREEN_MILITIA];
++uiNumMilitiaDisbanded;
++usGreenDisbanded;
}
else if (MilitiaList[0].ubNumTownElites > 0)
{
StrategicRemoveMilitiaFromSector( sX, sY, ELITE_MILITIA, 1 );
MilitiaList[0].ubNumTownElites--;
uiMoneyUnpaid -= gGameExternalOptions.usDailyCostTownElite;
uiMoneyUnpaid -= gGameExternalOptions.usDailyCostTown[ELITE_MILITIA];
++uiNumMilitiaDisbanded;
++usElitesDisbanded;
}
else if (MilitiaList[0].ubNumTownRegulars > 0)
{
StrategicRemoveMilitiaFromSector( sX, sY, REGULAR_MILITIA, 1 );
MilitiaList[0].ubNumTownRegulars--;
uiMoneyUnpaid -= gGameExternalOptions.usDailyCostTownRegular;
uiMoneyUnpaid -= gGameExternalOptions.usDailyCostTown[REGULAR_MILITIA];
++uiNumMilitiaDisbanded;
++usRegularsDisbanded;
}
else if (MilitiaList[0].ubNumTownGreens > 0)
{
StrategicRemoveMilitiaFromSector( sX, sY, GREEN_MILITIA, 1 );
MilitiaList[0].ubNumTownGreens--;
uiMoneyUnpaid -= gGameExternalOptions.usDailyCostTownGreen;
uiMoneyUnpaid -= gGameExternalOptions.usDailyCostTown[GREEN_MILITIA];
++uiNumMilitiaDisbanded;
++usGreenDisbanded;
}
else
{
// Somehow there are none to remove?!
Assert(1);
}
// Resort the list!
qsort( MilitiaList, 256, sizeof(MILITIA_LIST_TYPE), MilitiaListQsortCompare);
}
@@ -2344,6 +2369,9 @@ void HandleMilitiaUpkeepPayment( void )
// Pay all we can
uiPayment = LaptopSaveInfo.iCurrentBalance;
// Flugente: individual militia
DisbandIndividualMilitia( MilitiaList[0].ubSectorId, usGreenDisbanded, usRegularsDisbanded, usElitesDisbanded );
// Notify player that X militia have been automatically disbanded due to debt.
CHAR16 sString[256];
swprintf( sString, New113HAMMessage[21], uiNumMilitiaDisbanded );
@@ -2421,6 +2449,10 @@ UINT32 CalcMilitiaUpkeep( void )
{
UINT32 uiTotalPayment = 0;
UINT32 militia_static[MAX_MILITIA_LEVELS] = {0, 0, 0};
UINT32 militia_mobile[MAX_MILITIA_LEVELS] = {0, 0, 0};
UINT32 militia_individual[MAX_MILITIA_LEVELS] = {0, 0, 0};
for (UINT16 cnt = 0; cnt < 256; ++cnt)
{
SECTORINFO *pSectorInfo = &( SectorInfo[ cnt ] );
@@ -2431,19 +2463,36 @@ UINT32 CalcMilitiaUpkeep( void )
if ((ubTownId != BLANK_SECTOR && MilitiaTrainingAllowedInTown(ubTownId)) || // Major Town
IsThisSectorASAMSector( sMapX, sMapY, 0 ) ) // SAM Site
{
uiTotalPayment += MilitiaInSectorOfRank( sMapX, sMapY, GREEN_MILITIA ) * gGameExternalOptions.usDailyCostTownGreen;
uiTotalPayment += MilitiaInSectorOfRank( sMapX, sMapY, REGULAR_MILITIA ) * gGameExternalOptions.usDailyCostTownRegular;
uiTotalPayment += MilitiaInSectorOfRank( sMapX, sMapY, ELITE_MILITIA ) * gGameExternalOptions.usDailyCostTownElite;
for ( int i = GREEN_MILITIA; i < MAX_MILITIA_LEVELS; ++i )
militia_static[i] += MilitiaInSectorOfRank( sMapX, sMapY, i );
}
else
{
uiTotalPayment += MilitiaInSectorOfRank( sMapX, sMapY, GREEN_MILITIA ) * gGameExternalOptions.usDailyCostMobileGreen;
uiTotalPayment += MilitiaInSectorOfRank( sMapX, sMapY, REGULAR_MILITIA ) * gGameExternalOptions.usDailyCostMobileRegular;
uiTotalPayment += MilitiaInSectorOfRank( sMapX, sMapY, ELITE_MILITIA ) * gGameExternalOptions.usDailyCostMobileElite;
for ( int i = GREEN_MILITIA; i < MAX_MILITIA_LEVELS; ++i )
militia_mobile[i] += MilitiaInSectorOfRank( sMapX, sMapY, i );
}
}
return (uiTotalPayment);
// Flugente: if indivídual militia is on, calculate costs there and use the above as a fallback option
if ( gGameExternalOptions.fIndividualMilitia )
{
uiTotalPayment = GetDailyUpkeep_IndividualMilitia( militia_individual[GREEN_MILITIA], militia_individual[REGULAR_MILITIA], militia_individual[ELITE_MILITIA] );
}
for ( int i = GREEN_MILITIA; i < MAX_MILITIA_LEVELS; ++i )
{
if ( militia_static[i] + militia_mobile[i] > militia_individual[i] )
{
UINT32 exceed = militia_static[i] + militia_mobile[i] - militia_individual[i];
UINT32 exceed_mobile = min( exceed, militia_mobile[i] );
UINT32 exced_static = exceed - exceed_mobile;
uiTotalPayment += exced_static * gGameExternalOptions.usDailyCostTown[i];
uiTotalPayment += exceed_mobile * gGameExternalOptions.usDailyCostMobile[i];
}
}
return uiTotalPayment;
}
// Flugente: our militia volunteer pool is limited
-2
View File
@@ -30,8 +30,6 @@
#include "Campaign.h"
#include "Points.h"
extern INT32 ReadFieldByField( HWFILE hFile, PTR pDest, UINT32 uiFieldSize, UINT32 uiElementSize, UINT32 uiCurByteCount );
// event id counter
// has to be saved/loaded/reset
UINT32 gDynamicDialogueEventCounter = 0;
+2 -2
View File
@@ -2207,7 +2207,7 @@ void DrawSelectedUIAboveGuy( UINT16 usSoldierID )
}
}
// Flugente: soldier profiles
else if ( pSoldier->bTeam == MILITIA_TEAM && gGameExternalOptions.fSoldierProfiles_Militia && pSoldier->usSoldierProfile )
else if ( pSoldier->bTeam == MILITIA_TEAM && ((gGameExternalOptions.fSoldierProfiles_Militia && pSoldier->usSoldierProfile) || pSoldier->usIndividualMilitiaID) )
{
// get a proper chaos name
swprintf(NameStr, pSoldier->GetName());
@@ -2362,7 +2362,7 @@ void DrawSelectedUIAboveGuy( UINT16 usSoldierID )
ShowRankIcon( sXPos, sYPos, pSoldier );
}
// Flugente: soldier profiles
else if ( pSoldier->bTeam == MILITIA_TEAM && gGameExternalOptions.fSoldierProfiles_Militia && pSoldier->usSoldierProfile )
else if ( pSoldier->bTeam == MILITIA_TEAM && ((gGameExternalOptions.fSoldierProfiles_Militia && pSoldier->usSoldierProfile) || pSoldier->usIndividualMilitiaID) )
{
// get a proper name
swprintf(NameStr, pSoldier->GetName());
+5 -29
View File
@@ -30,10 +30,11 @@
#include "Campaign.h"
#include "ai.h"
#include "Isometric Utils.h"
#include "MilitiaSquads.h"
#include "MilitiaIndividual.h" // added by Flugente
#include "CampaignStats.h" // added by Flugente
#endif
#include "MilitiaSquads.h"
//forward declarations of common classes to eliminate includes
class OBJECTTYPE;
class SOLDIERTYPE;
@@ -281,9 +282,7 @@ void PrepareMilitiaForTactical( BOOLEAN fPrepareAll)
void HandleMilitiaPromotions( void )
{
UINT8 cnt;
UINT8 ubMilitiaRank;
SOLDIERTYPE* pTeamSoldier;
UINT8 ubPromotions;
gbGreenToElitePromotions = 0;
gbGreenToRegPromotions = 0;
@@ -296,31 +295,8 @@ void HandleMilitiaPromotions( void )
{
if ( pTeamSoldier->bActive && pTeamSoldier->bInSector && pTeamSoldier->stats.bLife > 0 )
{
if ( pTeamSoldier->ubMilitiaKills > 0 )
{
ubMilitiaRank = SoldierClassToMilitiaRank( pTeamSoldier->ubSoldierClass );
ubPromotions = CheckOneMilitiaForPromotion( gWorldSectorX, gWorldSectorY, ubMilitiaRank, pTeamSoldier->ubMilitiaKills );
if( ubPromotions )
{
if( ubPromotions == 2 )
{
++gbGreenToElitePromotions;
++gbMilitiaPromotions;
}
else if( pTeamSoldier->ubSoldierClass == SOLDIER_CLASS_GREEN_MILITIA )
{
++gbGreenToRegPromotions;
++gbMilitiaPromotions;
}
else if( pTeamSoldier->ubSoldierClass == SOLDIER_CLASS_REG_MILITIA )
{
++gbRegToElitePromotions;
++gbMilitiaPromotions;
}
}
pTeamSoldier->ubMilitiaKills = 0;
}
// Flugente: take care of promotions and individual militia update
HandlePossibleMilitiaPromotion( pTeamSoldier );
}
}
+1 -1
View File
@@ -4026,7 +4026,7 @@ void HandleNPCTeamMemberDeath( SOLDIERTYPE *pSoldierOld )
if (pSoldierOld->ubAttackerID != NOBODY && MercPtrs[ pSoldierOld->ubAttackerID ]->bTeam == MILITIA_TEAM )
{
MercPtrs[ pSoldierOld->ubAttackerID ]->ubMilitiaKills++;
MercPtrs[pSoldierOld->ubAttackerID]->ubMilitiaAssists++;
}
//if the NPC is a dealer, add the dealers items to the ground
+24 -3
View File
@@ -63,6 +63,7 @@
#include "Food.h"
#include "CampaignStats.h" // added by Flugente
#include "DynamicDialogue.h" // added by Flugente
#include "MilitiaIndividual.h" // added by Flugente
#endif
// anv: for enemy taunts
@@ -3995,7 +3996,7 @@ BOOLEAN HandleSoldierDeath( SOLDIERTYPE *pSoldier , BOOLEAN *pfMadeCorpse )
else if ( MercPtrs[ ubAttacker ]->bTeam == MILITIA_TEAM )
{
// get a kill! 2 points!
MercPtrs[ ubAttacker ]->ubMilitiaKills += 2;
MercPtrs[ ubAttacker ]->ubMilitiaKills += 1;
}
}
@@ -4025,7 +4026,7 @@ BOOLEAN HandleSoldierDeath( SOLDIERTYPE *pSoldier , BOOLEAN *pfMadeCorpse )
else if ( MercPtrs[ ubAssister ]->bTeam == MILITIA_TEAM )
{
// get an assist - 1 points
MercPtrs[ ubAssister ]->ubMilitiaKills += 1;
MercPtrs[ubAssister]->ubMilitiaAssists += 1;
}
}
/*
@@ -4040,7 +4041,7 @@ BOOLEAN HandleSoldierDeath( SOLDIERTYPE *pSoldier , BOOLEAN *pfMadeCorpse )
else if ( MercPtrs[ pSoldier->ubPreviousAttackerID ]->bTeam == MILITIA_TEAM )
{
// get an assist - 1 points
MercPtrs[ pSoldier->ubPreviousAttackerID ]->ubMilitiaKills += 1;
MercPtrs[ pSoldier->ubPreviousAttackerID ]->ubMilitiaAssists += 1;
}
}
*/
@@ -4050,6 +4051,26 @@ BOOLEAN HandleSoldierDeath( SOLDIERTYPE *pSoldier , BOOLEAN *pfMadeCorpse )
// Flugente: campaign stats
gCurrentIncident.AddStat( pSoldier, CAMPAIGNHISTORY_TYPE_KILL );
// Flugente: individual militia
MILITIA militia;
if ( GetMilitia( pSoldier->usIndividualMilitiaID, &militia ) && !(militia.flagmask & MILITIAFLAG_DEAD) )
{
militia.healthratio = 0.0f;
militia.flagmask |= MILITIAFLAG_DEAD;
// note the current incident (when closing the incident, we only do this for those still alive)
MILITIA_BATTLEREPORT report;
report.id = GetIdOfCurrentlyOngoingIncident( );
report.flagmask = MILITIA_BATTLEREPORT_FLAG_DIED;
if ( pSoldier->ubMilitiaKills )
report.flagmask |= MILITIA_BATTLEREPORT_FLAG_KILLEDENEMY;
militia.history.push_back( report );
UpdateMilitia(militia);
}
// Flugente: disease
HandleDeathDiseaseImplications( pSoldier );
+10
View File
@@ -98,6 +98,7 @@
#include "Auto Bandage.h" // added by Flugente
#include "Facilities.h" // added by Flugente
#include "Cheats.h" // added by Flugente
#include "MilitiaIndividual.h" // added by Flugente
#endif
#include "ub_config.h"
@@ -1023,12 +1024,15 @@ SOLDIERTYPE& SOLDIERTYPE::operator=(const OLDSOLDIERTYPE_101& src)
this->bScopeMode = USE_BEST_SCOPE;
this->ubMilitiaAssists = 0;
this->bFoodLevel = 0;
this->bDrinkLevel = 0;
this->usStarveDamageHealth = 0;
this->usStarveDamageStrength = 0;
this->bAIIndex = 0;
this->usSoldierProfile = 0;
this->usIndividualMilitiaID = 0;
this->usAISkillUse = 0;
for ( UINT8 i = 0; i < SOLDIER_COUNTER_MAX; ++i ) this->usSkillCounter[i] = 0;
@@ -16633,6 +16637,12 @@ STR16 SOLDIERTYPE::GetName( )
tmpname[tmpuser][0] = '\0';
wcscat( tmpname[tmpuser], this->name );
MILITIA militia;
if ( GetMilitia( this->usIndividualMilitiaID, &militia ) )
{
return militia.GetName( );
}
if ( this->usSoldierProfile )
{
INT8 type = this->GetSoldierProfileType( this->bTeam );
+3 -1
View File
@@ -1477,7 +1477,7 @@ public:
///////////////////////////////////////////////////////
// Flugente: this was the location of required variables required for the now removed poison feature. They can be used again
INT8 bUnusedINT8_1;
UINT8 ubMilitiaAssists; // Flugente: stores militia assists
INT8 bUnusedINT8_2;
INT8 bUnusedINT8_3;
@@ -1528,6 +1528,8 @@ public:
UINT32 usSoldierFlagMask2; // anv: another usSoldierFlagMask
UINT32 usIndividualMilitiaID; // Flugente: if this is a militia, this is the ID of the militia data
#ifdef JA2UB
//ja25
+28 -1
View File
@@ -46,6 +46,7 @@
#include "Game Clock.h" // added this one - SANDRO
#include "Interface.h" // added by Flugente
#include "Soldier macros.h" // added by Flugente
#include "MilitiaIndividual.h" // added by Flugente
#endif
#include "connect.h"
@@ -630,6 +631,12 @@ SOLDIERTYPE* TacticalCreateSoldier( SOLDIERCREATE_STRUCT *pCreateStruct, UINT8 *
guiCurrentUniqueSoldierId++;
// Flugente: if this miltia, set individual ID
if ( tbTeam == MILITIA_TEAM )
{
Soldier.usIndividualMilitiaID = GetIdOfUnusedindividualMilitia( pCreateStruct->ubSoldierClass, SECTOR( pCreateStruct->sSectorX, pCreateStruct->sSectorY ) );
}
// OK, CHECK IF WE HAVE A VALID PROFILE ID!
if ( pCreateStruct->ubProfile != NO_PROFILE )
{
@@ -1526,7 +1533,13 @@ void GeneratePaletteForSoldier( SOLDIERTYPE *pSoldier, UINT8 ubSoldierClass, UIN
//Choose hair color which uses the skin color to limit choices
hair = ChooseHairColor( pSoldier->ubBodyType, skin );
if ( pSoldier->usSoldierProfile )
MILITIA militia;
if ( GetMilitia( pSoldier->usIndividualMilitiaID, &militia ) )
{
skin = militia.skin;
hair = militia.hair;
}
else if ( pSoldier->usSoldierProfile )
{
INT8 type = pSoldier->GetSoldierProfileType(ubTeam);
@@ -1735,6 +1748,19 @@ BOOLEAN TacticalCopySoldierFromCreateStruct( SOLDIERTYPE *pSoldier, SOLDIERCREAT
// Flugente: soldier profiles
// silversurfer: Don't replace tanks!
if ( !ARMED_VEHICLE( pCreateStruct ) )
{
MILITIA militia;
if ( GetMilitia( pSoldier->usIndividualMilitiaID, &militia ) )
{
pSoldier->ubBodyType = militia.bodytype;
if ( gGameExternalOptions.fIndividualMilitia_ManageHealth )
{
// make sure militia has at least OKLIFE
pSoldier->stats.bLife = max( OKLIFE, (militia.healthratio / 100.0f) * pSoldier->stats.bLifeMax );
}
}
else
{
// We have a function for this
INT8 type = pSoldier->GetSoldierProfileType( pCreateStruct->bTeam );
@@ -1760,6 +1786,7 @@ BOOLEAN TacticalCopySoldierFromCreateStruct( SOLDIERTYPE *pSoldier, SOLDIERCREAT
}
}
}
}
if( pCreateStruct->fVisible )
{
+2 -2
View File
@@ -41,9 +41,9 @@ enum
enum
{
WHITEHEAD,
BLACKHEAD, //black skin (only this line )
BROWNHEAD, //dark skin (this line plus all above)
BLACKHEAD, //black skin (only this line )
WHITEHEAD,
BLONDEHEAD,
REDHEAD, //pink/tan skin (this line plus all above )
NUMHEADS
+4
View File
@@ -1192,6 +1192,10 @@
RelativePath=".\XML_Merge.cpp"
>
</File>
<File
RelativePath=".\XML_MilitiaIndividual.cpp"
>
</File>
<File
RelativePath=".\XML_NewFaceGear.cpp"
>
+4
View File
@@ -1190,6 +1190,10 @@
RelativePath="XML_MercStartingGear.cpp"
>
</File>
<File
RelativePath="XML_MilitiaIndividual.cpp"
>
</File>
<File
RelativePath="XML_Merge.cpp"
>
+1
View File
@@ -235,6 +235,7 @@
<ClCompile Include="XML_Merchants.cpp" />
<ClCompile Include="XML_MercStartingGear.cpp" />
<ClCompile Include="XML_Merge.cpp" />
<ClCompile Include="XML_MilitiaIndividual.cpp" />
<ClCompile Include="XML_NewFaceGear.cpp" />
<ClCompile Include="XML_Opinions.cpp" />
<ClCompile Include="XML_Profiles.cpp" />
+3
View File
@@ -617,6 +617,9 @@
<ClCompile Include="XML_Qarray.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="XML_MilitiaIndividual.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="XML_NewFaceGear.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+1
View File
@@ -236,6 +236,7 @@
<ClCompile Include="XML_Merchants.cpp" />
<ClCompile Include="XML_MercStartingGear.cpp" />
<ClCompile Include="XML_Merge.cpp" />
<ClCompile Include="XML_MilitiaIndividual.cpp" />
<ClCompile Include="XML_NewFaceGear.cpp" />
<ClCompile Include="XML_Opinions.cpp" />
<ClCompile Include="XML_Profiles.cpp" />
+3
View File
@@ -698,5 +698,8 @@
<ClCompile Include="XML_Disease.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="XML_MilitiaIndividual.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>
+5
View File
@@ -250,6 +250,7 @@ typedef PARSE_STAGE;
#define VEHICLESFILENAME "Vehicles.xml"
#define SQUADNAMEFILENAME "SquadNames.xml"
#define BACKGROUNDSFILENAME "Backgrounds.xml"
#define INDIVIDUALMILITIAFILENAME "MilitiaIndividual.xml"
#define CAMPAIGNSTATSEVENTSFILENAME "CampaignStatsEvents.xml"
#define DISEASEFILENAME "Disease.xml"
@@ -518,6 +519,10 @@ extern void LoadIMPPortraitsTEMP();
extern BOOLEAN ReadInBackgrounds(STR fileName, BOOLEAN localizedVersion );
extern BOOLEAN WriteBackgrounds( STR fileName);
// Flugente: individual militia
extern BOOLEAN ReadInMilitiaIndividual( STR fileName, BOOLEAN localizedVersion );
extern BOOLEAN WriteMilitiaIndividual( STR fileName );
// Flugente: campaign stats events
extern BOOLEAN ReadInCampaignStatsEvents(STR fileName, BOOLEAN localizedVersion );
extern BOOLEAN WriteCampaignStatsEvents( STR fileName);
+308
View File
@@ -0,0 +1,308 @@
/**
* @file
* @author Flugente (bears-pit.com)
*/
#ifdef PRECOMPILEDHEADERS
#include "Tactical All.h"
#else
#include "sgp.h"
#include "Debug Control.h"
#include "expat.h"
#include "XML.h"
#include "MilitiaIndividual.h"
#endif
struct
{
PARSE_STAGE curElement;
CHAR8 szCharData[MAX_CHAR_DATA_LENGTH + 1];
MilitiaOriginData curBackground;
MilitiaOriginData * curArray;
UINT32 maxArraySize;
UINT32 curIndex;
UINT32 currentDepth;
UINT32 maxReadDepth;
CHAR16 gzBackground[MAX_ENEMY_NAMES_CHARS];
}
typedef parseData;
BOOLEAN localizedTextOnly_MI;
static void XMLCALL
militiaindividualStartElementHandle( void *userData, const XML_Char *name, const XML_Char **atts )
{
parseData * pData = (parseData *)userData;
if ( pData->currentDepth <= pData->maxReadDepth ) //are we reading this element?
{
if ( strcmp( name, "MILITIAORIGINDATA" ) == 0 && pData->curElement == ELEMENT_NONE )
{
pData->curElement = ELEMENT_LIST;
if ( !localizedTextOnly_MI )
memset( pData->curArray, 0, sizeof(MilitiaOriginData)*pData->maxArraySize );
pData->maxReadDepth++; //we are not skipping this element
}
else if ( strcmp( name, "ORIGINDATA" ) == 0 && pData->curElement == ELEMENT_LIST )
{
pData->curElement = ELEMENT;
if ( !localizedTextOnly_MI )
memset( &pData->curBackground, 0, sizeof(MilitiaOriginData) );
pData->maxReadDepth++; //we are not skipping this element
}
else if ( pData->curElement == ELEMENT &&
(strcmp( name, "male_forename" ) == 0 ||
strcmp( name, "male_surname" ) == 0 ||
strcmp( name, "female_forename" ) == 0 ||
strcmp( name, "female_surname" ) == 0 ||
strcmp( name, "chance_bodytype_REGMALE" ) == 0 ||
strcmp( name, "chance_bodytype_BIGMALE" ) == 0 ||
strcmp( name, "chance_bodytype_STOCKYMALE" ) == 0 ||
strcmp( name, "chance_bodytype_REGFEMALE" ) == 0 ||
strcmp( name, "chance_skin_PINKSKIN" ) == 0 ||
strcmp( name, "chance_skin_TANSKIN" ) == 0 ||
strcmp( name, "chance_skin_DARKSKIN" ) == 0 ||
strcmp( name, "chance_skin_BLACKSKIN" ) == 0 ||
strcmp( name, "dailycost_green" ) == 0 ||
strcmp( name, "dailycost_regular" ) == 0 ||
strcmp( name, "dailycost_elite" ) == 0) )
{
pData->curElement = ELEMENT_PROPERTY;
pData->maxReadDepth++; //we are not skipping this element
}
pData->szCharData[0] = '\0';
}
pData->currentDepth++;
}
static void XMLCALL
militiaindividualCharacterDataHandle( void *userData, const XML_Char *str, int len )
{
parseData * pData = (parseData *)userData;
if ( (pData->currentDepth <= pData->maxReadDepth) &&
(strlen( pData->szCharData ) < MAX_CHAR_DATA_LENGTH)
){
strncat( pData->szCharData, str, __min( (unsigned int)len, MAX_CHAR_DATA_LENGTH - strlen( pData->szCharData ) ) );
}
}
static void XMLCALL
militiaindividualEndElementHandle( void *userData, const XML_Char *name )
{
parseData * pData = (parseData *)userData;
if ( pData->currentDepth <= pData->maxReadDepth )
{
if ( strcmp( name, "MILITIAORIGINDATA" ) == 0 )
{
pData->curElement = ELEMENT_NONE;
}
else if ( strcmp( name, "ORIGINDATA" ) == 0 )
{
pData->curElement = ELEMENT_LIST;
if ( pData->curIndex < pData->maxArraySize )
{
pData->curArray[pData->curIndex] = pData->curBackground;
}
++pData->curIndex;
}
else if ( strcmp( name, "male_forename" ) == 0 )
{
pData->curElement = ELEMENT;
CHAR16 bla[30];
MultiByteToWideChar( CP_UTF8, 0, pData->szCharData, -1, bla, sizeof(bla) / sizeof(bla[0]) );
bla[sizeof(bla) / sizeof(bla[0]) - 1] = '\0';
pData->curBackground.szMale_Forename.push_back( bla );
}
else if ( strcmp( name, "male_surname" ) == 0 )
{
pData->curElement = ELEMENT;
CHAR16 bla[30];
MultiByteToWideChar( CP_UTF8, 0, pData->szCharData, -1, bla, sizeof(bla) / sizeof(bla[0]) );
bla[sizeof(bla) / sizeof(bla[0]) - 1] = '\0';
pData->curBackground.szMale_Surname.push_back( bla );
}
else if ( strcmp( name, "female_forename" ) == 0 )
{
pData->curElement = ELEMENT;
CHAR16 bla[30];
MultiByteToWideChar( CP_UTF8, 0, pData->szCharData, -1, bla, sizeof(bla) / sizeof(bla[0]) );
bla[sizeof(bla) / sizeof(bla[0]) - 1] = '\0';
pData->curBackground.szFemale_Forename.push_back( bla );
}
else if ( strcmp( name, "female_surname" ) == 0 )
{
pData->curElement = ELEMENT;
CHAR16 bla[30];
MultiByteToWideChar( CP_UTF8, 0, pData->szCharData, -1, bla, sizeof(bla) / sizeof(bla[0]) );
bla[sizeof(bla) / sizeof(bla[0]) - 1] = '\0';
pData->curBackground.szFemale_Surname.push_back( bla );
}
else if ( strcmp( name, "chance_bodytype_REGMALE" ) == 0 )
{
pData->curElement = ELEMENT;
pData->curBackground.chance_bodytype[REGMALE] = min( 100, max( 0, (UINT8)atol( pData->szCharData ) ) );
}
else if ( strcmp( name, "chance_bodytype_BIGMALE" ) == 0 )
{
pData->curElement = ELEMENT;
pData->curBackground.chance_bodytype[BIGMALE] = min( 100, max( 0, (UINT8)atol( pData->szCharData ) ) );
}
else if ( strcmp( name, "chance_bodytype_STOCKYMALE" ) == 0 )
{
pData->curElement = ELEMENT;
pData->curBackground.chance_bodytype[STOCKYMALE] = min( 100, max( 0, (UINT8)atol( pData->szCharData ) ) );
}
else if ( strcmp( name, "chance_bodytype_REGFEMALE" ) == 0 )
{
pData->curElement = ELEMENT;
pData->curBackground.chance_bodytype[REGFEMALE] = min( 100, max( 0, (UINT8)atol( pData->szCharData ) ) );
}
else if ( strcmp( name, "chance_skin_PINKSKIN" ) == 0 )
{
pData->curElement = ELEMENT;
pData->curBackground.chance_skin[PINKSKIN] = min( 100, max( 0, (UINT8)atol( pData->szCharData ) ) );
}
else if ( strcmp( name, "chance_skin_TANSKIN" ) == 0 )
{
pData->curElement = ELEMENT;
pData->curBackground.chance_skin[TANSKIN] = min( 100, max( 0, (UINT8)atol( pData->szCharData ) ) );
}
else if ( strcmp( name, "chance_skin_DARKSKIN" ) == 0 )
{
pData->curElement = ELEMENT;
pData->curBackground.chance_skin[DARKSKIN] = min( 100, max( 0, (UINT8)atol( pData->szCharData ) ) );
}
else if ( strcmp( name, "chance_skin_BLACKSKIN" ) == 0 )
{
pData->curElement = ELEMENT;
pData->curBackground.chance_skin[BLACKSKIN] = min( 100, max( 0, (UINT8)atol( pData->szCharData ) ) );
}
else if ( strcmp( name, "dailycost_green" ) == 0 )
{
pData->curElement = ELEMENT;
pData->curBackground.dailycost[GREEN_MILITIA] = (UINT16)atol( pData->szCharData );
}
else if ( strcmp( name, "dailycost_regular" ) == 0 )
{
pData->curElement = ELEMENT;
pData->curBackground.dailycost[REGULAR_MILITIA] = (UINT16)atol( pData->szCharData );
}
else if ( strcmp( name, "dailycost_elite" ) == 0 )
{
pData->curElement = ELEMENT;
pData->curBackground.dailycost[ELITE_MILITIA] = (UINT16)atol( pData->szCharData );
}
pData->maxReadDepth--;
}
pData->currentDepth--;
}
BOOLEAN ReadInMilitiaIndividual( STR fileName, BOOLEAN localizedVersion )
{
HWFILE hFile;
UINT32 uiBytesRead;
UINT32 uiFSize;
CHAR8 * lpcBuffer;
XML_Parser parser = XML_ParserCreate( NULL );
parseData pData;
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, "Loading MilitiaIndividual.xml" );
localizedTextOnly_MI = localizedVersion;
// Open file
hFile = FileOpen( fileName, FILE_ACCESS_READ, FALSE );
if ( !hFile )
return(FALSE);
uiFSize = FileGetSize( hFile );
lpcBuffer = (CHAR8 *)MemAlloc( uiFSize + 1 );
//Read in block
if ( !FileRead( hFile, lpcBuffer, uiFSize, &uiBytesRead ) )
{
MemFree( lpcBuffer );
return(FALSE);
}
lpcBuffer[uiFSize] = 0; //add a null terminator
FileClose( hFile );
XML_SetElementHandler( parser, militiaindividualStartElementHandle, militiaindividualEndElementHandle );
XML_SetCharacterDataHandler( parser, militiaindividualCharacterDataHandle );
memset( &pData, 0, sizeof(pData) );
pData.curArray = gMilitiaOriginData;
pData.maxArraySize = MO_MAX;
XML_SetUserData( parser, &pData );
if ( !XML_Parse( parser, lpcBuffer, uiFSize, TRUE ) )
{
CHAR8 errorBuf[511];
sprintf( errorBuf, "XML Parser Error in MilitiaIndividual.xml: %s at line %d", XML_ErrorString( XML_GetErrorCode( parser ) ), XML_GetCurrentLineNumber( parser ) );
LiveMessage( errorBuf );
MemFree( lpcBuffer );
return FALSE;
}
MemFree( lpcBuffer );
XML_ParserFree( parser );
return(TRUE);
}
BOOLEAN WriteMilitiaIndividual( STR fileName )
{
//Debug code; make sure that what we got from the file is the same as what's there
// Open a new file
HWFILE hFile = FileOpen( fileName, FILE_ACCESS_WRITE | FILE_CREATE_ALWAYS, FALSE );
if ( !hFile )
return(FALSE);
{
FilePrintf( hFile, "<MILITIAORIGINDATA>\r\n" );
for ( UINT32 cnt = 0; cnt < NUM_BACKGROUND; ++cnt )
{
FilePrintf( hFile, "\t<ORIGINDATA>\r\n" );
FilePrintf( hFile, "\t\t<Origin>%d</Origin>\r\n", cnt );
}
FilePrintf( hFile, "</ORIGINDATA>\r\n" );
}
FileClose( hFile );
return(TRUE);
}
+1 -2
View File
@@ -55,6 +55,7 @@
#include "Map Screen Helicopter.h"
#include "Drugs And Alcohol.h" // added by Flugente for DoesMercHavePersonality( ... )
#include "SaveLoadGame.h"
#ifdef JA2UB
#include "Ja25_Tactical.h"
@@ -3223,8 +3224,6 @@ BOOLEAN SaveNPCInfoToSaveGameFile( HWFILE hFile )
return( TRUE );
}
extern INT32 ReadFieldByField(HWFILE hFile, PTR pDest, UINT32 uiFieldSize, UINT32 uiElementSize, UINT32 uiCurByteCount);
BOOLEAN LoadNPCInfoFromSavedGameFile( HWFILE hFile, UINT32 uiSaveGameVersion )
{
UINT32 uiNumBytesRead=0;
+24
View File
@@ -2935,6 +2935,30 @@ extern STR16 szEnemyHeliText[];
// Flugente: fortification
extern STR16 szFortificationText[];
// Flugente: militia website
enum
{
// main page
TEXT_MILITIAWEBSITE_WEBSITENAME,
TEXT_MILITIAWEBSITE_SLOGAN,
// links to other pages
TEXT_MILITIAWEBSITE_SUBSITE1,
TEXT_MILITIAWEBSITE_MAIN1 = TEXT_PMC_SUBSITE1 + 3,
TEXT_MILITIAWEBSITE_MAX,
};
extern STR16 szMilitiaWebSite[];
extern STR16 szIndividualMilitiaBattleReportText[];
extern STR16 szIndividualMilitiaTraitRequirements[];
extern STR16 szIdividualMilitiaWebsiteText[];
extern STR16 szIdividualMilitiaWebsiteFilterText_Dead[];
extern STR16 szIdividualMilitiaWebsiteFilterText_Rank[] ;
extern STR16 szIdividualMilitiaWebsiteFilterText_Origin[];
extern STR16 szIdividualMilitiaWebsiteFilterText_Sector[];
#define TACTICAL_INVENTORY_DIALOG_NUM 16
#define TACTICAL_COVER_DIALOG_NUM 16
+117 -1
View File
@@ -4979,6 +4979,7 @@ STR16 pBookMarkStrings[] =
L"佣兵之家", //L"MeLoDY",
L"世界卫生组织", //L"WHO", 
L"Kerberus安保公司", //L"Kerberus",
L"Militia Overview", // TODO.Translate
};
STR16 pBookmarkTitle[] =
@@ -5101,6 +5102,8 @@ STR16 pWebPagesTitles[] =
L"Kerberus安保公司 - 关于我们", //L"Kerberus - About Us",
L"Kerberus安保公司 - 雇佣队伍", //L"Kerberus - Hire a Team",
L"Kerberus安保公司 - 独立协议", //L"Kerberus - Individual Contracts",
L"Militia Roster", // TODO.Translate
L"Militia Statistics",
L"Bobby Ray - 最近的运货",
L"百科全书",
L"百科全书 - 数据",
@@ -6895,7 +6898,8 @@ STR16 gzLaptopHelpText[] =
L"战役历史",
L"佣兵喜欢或不喜欢你", //L"Mercenaries Love or Dislike You",
L"世界卫生组织", //L"World Health Organization",
L"Kerberus安保公司 - 最佳的安保工作", //L"Kerberus - Excellence In Security",
L"Kerberus - Experience In Security",
L"Militia Overview", // TODO.Translate
};
@@ -10883,6 +10887,118 @@ STR16 szFortificationText[] =
L"Tileset %d: %s",
};
STR16 szMilitiaWebSite[] =
{
// main page
L"Militia",
L"Militia Forces Overview",
// links to other pages
L"Militia Roster",
L"Statistics",
L"About",
};
STR16 szIndividualMilitiaBattleReportText[] =
{
L"Took part in Operation %s",
L"Recruited on Day %d, %d:%2d in %s",
L"Promoted on Day %d, %d:%2d",
L"KIA, Operation %s",
L"Lightly wounded during Operation %s",
L"Heavily wounded during Operation %s",
L"Critically wounded during Operation %s",
L"Valiantly fought in Operation %s",
L"Hired from Kerberus on Day %d, %d:%2d in %s",
L"Defected to us on Day %d, %d:%2d in %s",
L"Contract terminated on Day %d, %d:%2d",
};
STR16 szIndividualMilitiaTraitRequirements[] =
{
L"HP",
L"AGI",
L"DEX",
L"STR",
L"LDR",
L"MRK",
L"MEC",
L"EXP",
L"MED",
L"WIS",
L"\nMust have regular or elite rank",
L"\nMust have elite rank",
L"\n\n|F|u|l|f|i|l|l|e|d |R|e|q|u|i|r|e|m|e|n|t|s",
L"\n\n|F|a|i|l|e|d |R|e|q|u|i|r|e|m|e|n|t|s",
L"\n%d %s",
L"\nBasic version of trait",
L" (Expert)"
};
STR16 szIdividualMilitiaWebsiteText[] =
{
L"Operations",
L"Are you sure you want to release %s from your service?",
L"HP ratio: %3.0f %% Daily Wage: %3d$ Age: %d years",
L"Daily Wage: %3d$ Age: %d years",
L"Kills: %d Assists: %d",
L"Status: Deceased",
L"Status: Fired",
L"Status: Active",
L"Terminate Contract",
L"Personal Data",
L"Service Record",
L"Inventory",
L"Militia name",
L"Sector name",
L"Weapon",
L"HP ratio: %3.1f%%%%%%%",
L"%s is not active in the currently loaded sector.",
L"%s has been promoted to regular militia",
L"%s has been promoted to elite militia",
};
STR16 szIdividualMilitiaWebsiteFilterText_Dead[] =
{
L"All statuses",
L"Deceased",
L"Active",
L"Fired",
};
STR16 szIdividualMilitiaWebsiteFilterText_Rank[] =
{
L"All ranks",
L"Green",
L"Regular",
L"Elite",
};
STR16 szIdividualMilitiaWebsiteFilterText_Origin[] =
{
L"All origins",
L"Rebel",
L"PMC",
L"Defector",
};
STR16 szIdividualMilitiaWebsiteFilterText_Sector[] =
{
L"All sectors",
};
// 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
+119
View File
@@ -4983,6 +4983,7 @@ STR16 pBookMarkStrings[] =
L"MeLoDY",
L"WHO",
L"Kerberus",
L"Militia Overview", // TODO.Translate
};
STR16 pBookmarkTitle[] =
@@ -5102,6 +5103,11 @@ STR16 pWebPagesTitles[] =
L"WHO - About WHO",
L"WHO - Disease in Arulco",
L"WHO - Helpful Tips",
L"Kerberus - About Us",
L"Kerberus - Hire a Team",
L"Kerberus - Individual Contracts",
L"Militia Roster", // TODO.Translate
L"Militia Statistics",
L"Bobby Ray's - Recentelijke Zendingen",
L"Encyclopedia",
L"Encyclopedia - Data",
@@ -6906,6 +6912,7 @@ STR16 gzLaptopHelpText[] =
L"Mercenaries Love or Dislike You", // TODO.Translate
L"World Health Organization",
L"Kerberus - Excellence In Security",
L"Militia Overview", // TODO.Translate
};
@@ -10897,4 +10904,116 @@ STR16 szFortificationText[] =
L"Tileset %d: %s",
};
STR16 szMilitiaWebSite[] =
{
// main page
L"Militia",
L"Militia Forces Overview",
// links to other pages
L"Militia Roster",
L"Statistics",
L"About",
};
STR16 szIndividualMilitiaBattleReportText[] =
{
L"Took part in Operation %s",
L"Recruited on Day %d, %d:%2d in %s",
L"Promoted on Day %d, %d:%2d",
L"KIA, Operation %s",
L"Lightly wounded during Operation %s",
L"Heavily wounded during Operation %s",
L"Critically wounded during Operation %s",
L"Valiantly fought in Operation %s",
L"Hired from Kerberus on Day %d, %d:%2d in %s",
L"Defected to us on Day %d, %d:%2d in %s",
L"Contract terminated on Day %d, %d:%2d",
};
STR16 szIndividualMilitiaTraitRequirements[] =
{
L"HP",
L"AGI",
L"DEX",
L"STR",
L"LDR",
L"MRK",
L"MEC",
L"EXP",
L"MED",
L"WIS",
L"\nMust have regular or elite rank",
L"\nMust have elite rank",
L"\n\n|F|u|l|f|i|l|l|e|d |R|e|q|u|i|r|e|m|e|n|t|s",
L"\n\n|F|a|i|l|e|d |R|e|q|u|i|r|e|m|e|n|t|s",
L"\n%d %s",
L"\nBasic version of trait",
L" (Expert)"
};
STR16 szIdividualMilitiaWebsiteText[] =
{
L"Operations",
L"Are you sure you want to release %s from your service?",
L"HP ratio: %3.0f %% Daily Wage: %3d$ Age: %d years",
L"Daily Wage: %3d$ Age: %d years",
L"Kills: %d Assists: %d",
L"Status: Deceased",
L"Status: Fired",
L"Status: Active",
L"Terminate Contract",
L"Personal Data",
L"Service Record",
L"Inventory",
L"Militia name",
L"Sector name",
L"Weapon",
L"HP ratio: %3.1f%%%%%%%",
L"%s is not active in the currently loaded sector.",
L"%s has been promoted to regular militia",
L"%s has been promoted to elite militia",
};
STR16 szIdividualMilitiaWebsiteFilterText_Dead[] =
{
L"All statuses",
L"Deceased",
L"Active",
L"Fired",
};
STR16 szIdividualMilitiaWebsiteFilterText_Rank[] =
{
L"All ranks",
L"Green",
L"Regular",
L"Elite",
};
STR16 szIdividualMilitiaWebsiteFilterText_Origin[] =
{
L"All origins",
L"Rebel",
L"PMC",
L"Defector",
};
STR16 szIdividualMilitiaWebsiteFilterText_Sector[] =
{
L"All sectors",
};
#endif //DUTCH
+116 -1
View File
@@ -4976,6 +4976,7 @@ STR16 pBookMarkStrings[] =
L"MeLoDY",
L"WHO",
L"Kerberus",
L"Militia Overview",
};
STR16 pBookmarkTitle[] =
@@ -5098,6 +5099,8 @@ STR16 pWebPagesTitles[] =
L"Kerberus - About Us",
L"Kerberus - Hire a Team",
L"Kerberus - Individual Contracts",
L"Militia Roster",
L"Militia Statistics",
L"Bobby Ray's - Recent Shipments",
L"Encyclopedia",
L"Encyclopedia - Data",
@@ -6892,7 +6895,8 @@ STR16 gzLaptopHelpText[] =
L"Campaign History",
L"Mercenaries Love or Dislike You",
L"World Health Organization",
L"Kerberus - Excellence In Security",
L"Kerberus - Experience In Security",
L"Militia Overview",
};
@@ -10935,4 +10939,115 @@ STR16 szFortificationText[] =
L"Tileset %d: %s",
};
STR16 szMilitiaWebSite[] =
{
// main page
L"Militia",
L"Militia Forces Overview",
// links to other pages
L"Militia Roster",
L"Statistics",
L"About",
};
STR16 szIndividualMilitiaBattleReportText[] =
{
L"Took part in Operation %s",
L"Recruited on Day %d, %d:%2d in %s",
L"Promoted on Day %d, %d:%2d",
L"KIA, Operation %s",
L"Lightly wounded during Operation %s",
L"Heavily wounded during Operation %s",
L"Critically wounded during Operation %s",
L"Valiantly fought in Operation %s",
L"Hired from Kerberus on Day %d, %d:%2d in %s",
L"Defected to us on Day %d, %d:%2d in %s",
L"Contract terminated on Day %d, %d:%2d",
};
STR16 szIndividualMilitiaTraitRequirements[] =
{
L"HP",
L"AGI",
L"DEX",
L"STR",
L"LDR",
L"MRK",
L"MEC",
L"EXP",
L"MED",
L"WIS",
L"\nMust have regular or elite rank",
L"\nMust have elite rank",
L"\n\n|F|u|l|f|i|l|l|e|d |R|e|q|u|i|r|e|m|e|n|t|s",
L"\n\n|F|a|i|l|e|d |R|e|q|u|i|r|e|m|e|n|t|s",
L"\n%d %s",
L"\nBasic version of trait",
L" (Expert)"
};
STR16 szIdividualMilitiaWebsiteText[] =
{
L"Operations",
L"Are you sure you want to release %s from your service?",
L"HP ratio: %3.0f %% Daily Wage: %3d$ Age: %d years",
L"Daily Wage: %3d$ Age: %d years",
L"Kills: %d Assists: %d",
L"Status: Deceased",
L"Status: Fired",
L"Status: Active",
L"Terminate Contract",
L"Personal Data",
L"Service Record",
L"Inventory",
L"Militia name",
L"Sector name",
L"Weapon",
L"HP ratio: %3.1f%%%%%%%",
L"%s is not active in the currently loaded sector.",
L"%s has been promoted to regular militia",
L"%s has been promoted to elite militia",
};
STR16 szIdividualMilitiaWebsiteFilterText_Dead[] =
{
L"All statuses",
L"Deceased",
L"Active",
L"Fired",
};
STR16 szIdividualMilitiaWebsiteFilterText_Rank[] =
{
L"All ranks",
L"Green",
L"Regular",
L"Elite",
};
STR16 szIdividualMilitiaWebsiteFilterText_Origin[] =
{
L"All origins",
L"Rebel",
L"PMC",
L"Defector",
};
STR16 szIdividualMilitiaWebsiteFilterText_Sector[] =
{
L"All sectors",
};
#endif //ENGLISH
+117 -1
View File
@@ -4988,6 +4988,7 @@ STR16 pBookMarkStrings[] =
L"MeLoDY",
L"WHO",
L"Kerberus",
L"Militia Overview", // TODO.Translate
};
STR16 pBookmarkTitle[] =
@@ -5110,6 +5111,8 @@ STR16 pWebPagesTitles[] =
L"Kerberus - About Us",
L"Kerberus - Hire a Team",
L"Kerberus - Individual Contracts",
L"Militia Roster", // TODO.Translate
L"Militia Statistics",
L"Bobby Ray : Dernières commandes",
L"Encyclopédie",
L"Encyclopédie : Données",
@@ -6905,7 +6908,8 @@ STR16 gzLaptopHelpText[] =
L"Comptes rendus",
L"Mercenaries Love or Dislike You", // TODO.Translate
L"World Health Organization",
L"Kerberus - Excellence In Security",
L"Kerberus - Experience In Security",
L"Militia Overview", // TODO.Translate
};
@@ -10882,4 +10886,116 @@ STR16 szFortificationText[] =
L"Tileset %d: %s",
};
STR16 szMilitiaWebSite[] =
{
// main page
L"Militia",
L"Militia Forces Overview",
// links to other pages
L"Militia Roster",
L"Statistics",
L"About",
};
STR16 szIndividualMilitiaBattleReportText[] =
{
L"Took part in Operation %s",
L"Recruited on Day %d, %d:%2d in %s",
L"Promoted on Day %d, %d:%2d",
L"KIA, Operation %s",
L"Lightly wounded during Operation %s",
L"Heavily wounded during Operation %s",
L"Critically wounded during Operation %s",
L"Valiantly fought in Operation %s",
L"Hired from Kerberus on Day %d, %d:%2d in %s",
L"Defected to us on Day %d, %d:%2d in %s",
L"Contract terminated on Day %d, %d:%2d",
};
STR16 szIndividualMilitiaTraitRequirements[] =
{
L"HP",
L"AGI",
L"DEX",
L"STR",
L"LDR",
L"MRK",
L"MEC",
L"EXP",
L"MED",
L"WIS",
L"\nMust have regular or elite rank",
L"\nMust have elite rank",
L"\n\n|F|u|l|f|i|l|l|e|d |R|e|q|u|i|r|e|m|e|n|t|s",
L"\n\n|F|a|i|l|e|d |R|e|q|u|i|r|e|m|e|n|t|s",
L"\n%d %s",
L"\nBasic version of trait",
L" (Expert)"
};
STR16 szIdividualMilitiaWebsiteText[] =
{
L"Operations",
L"Are you sure you want to release %s from your service?",
L"HP ratio: %3.0f %% Daily Wage: %3d$ Age: %d years",
L"Daily Wage: %3d$ Age: %d years",
L"Kills: %d Assists: %d",
L"Status: Deceased",
L"Status: Fired",
L"Status: Active",
L"Terminate Contract",
L"Personal Data",
L"Service Record",
L"Inventory",
L"Militia name",
L"Sector name",
L"Weapon",
L"HP ratio: %3.1f%%%%%%%",
L"%s is not active in the currently loaded sector.",
L"%s has been promoted to regular militia",
L"%s has been promoted to elite militia",
};
STR16 szIdividualMilitiaWebsiteFilterText_Dead[] =
{
L"All statuses",
L"Deceased",
L"Active",
L"Fired",
};
STR16 szIdividualMilitiaWebsiteFilterText_Rank[] =
{
L"All ranks",
L"Green",
L"Regular",
L"Elite",
};
STR16 szIdividualMilitiaWebsiteFilterText_Origin[] =
{
L"All origins",
L"Rebel",
L"PMC",
L"Defector",
};
STR16 szIdividualMilitiaWebsiteFilterText_Sector[] =
{
L"All sectors",
};
#endif //FRENCH
+117 -1
View File
@@ -4932,6 +4932,7 @@ STR16 pBookMarkStrings[] =
L"MeLoDY",
L"WHO",
L"Kerberus",
L"Militia Overview", // TODO.Translate
};
STR16 pBookmarkTitle[] =
@@ -5046,6 +5047,8 @@ STR16 pWebPagesTitles[] =
L"Kerberus - About Us",
L"Kerberus - Hire a Team",
L"Kerberus - Individual Contracts",
L"Militia Roster", // TODO.Translate
L"Militia Statistics",
L"Bobby Rays - Letzte Lieferungen",
L"Enzyklopädie",
L"Enzyklopädie - Daten",
@@ -6738,7 +6741,8 @@ STR16 gzLaptopHelpText[] =
L"Geschichte",
L"Mercenaries Love or Dislike You", // TODO.Translate
L"World Health Organization",
L"Kerberus - Excellence In Security",
L"Kerberus - Experience In Security",
L"Militia Overview", // TODO.Translate
};
STR16 gzHelpScreenText[] =
@@ -10712,4 +10716,116 @@ STR16 szFortificationText[] =
L"Tileset %d: %s",
};
STR16 szMilitiaWebSite[] =
{
// main page
L"Militia",
L"Militia Forces Overview",
// links to other pages
L"Militia Roster",
L"Statistics",
L"About",
};
STR16 szIndividualMilitiaBattleReportText[] =
{
L"Took part in Operation %s",
L"Recruited on Day %d, %d:%2d in %s",
L"Promoted on Day %d, %d:%2d",
L"KIA, Operation %s",
L"Lightly wounded during Operation %s",
L"Heavily wounded during Operation %s",
L"Critically wounded during Operation %s",
L"Valiantly fought in Operation %s",
L"Hired from Kerberus on Day %d, %d:%2d in %s",
L"Defected to us on Day %d, %d:%2d in %s",
L"Contract terminated on Day %d, %d:%2d",
};
STR16 szIndividualMilitiaTraitRequirements[] =
{
L"HP",
L"AGI",
L"DEX",
L"STR",
L"LDR",
L"MRK",
L"MEC",
L"EXP",
L"MED",
L"WIS",
L"\nMust have regular or elite rank",
L"\nMust have elite rank",
L"\n\n|F|u|l|f|i|l|l|e|d |R|e|q|u|i|r|e|m|e|n|t|s",
L"\n\n|F|a|i|l|e|d |R|e|q|u|i|r|e|m|e|n|t|s",
L"\n%d %s",
L"\nBasic version of trait",
L" (Expert)"
};
STR16 szIdividualMilitiaWebsiteText[] =
{
L"Operations",
L"Are you sure you want to release %s from your service?",
L"HP ratio: %3.0f %% Daily Wage: %3d$ Age: %d years",
L"Daily Wage: %3d$ Age: %d years",
L"Kills: %d Assists: %d",
L"Status: Deceased",
L"Status: Fired",
L"Status: Active",
L"Terminate Contract",
L"Personal Data",
L"Service Record",
L"Inventory",
L"Militia name",
L"Sector name",
L"Weapon",
L"HP ratio: %3.1f%%%%%%%",
L"%s is not active in the currently loaded sector.",
L"%s has been promoted to regular militia",
L"%s has been promoted to elite militia",
};
STR16 szIdividualMilitiaWebsiteFilterText_Dead[] =
{
L"All statuses",
L"Deceased",
L"Active",
L"Fired",
};
STR16 szIdividualMilitiaWebsiteFilterText_Rank[] =
{
L"All ranks",
L"Green",
L"Regular",
L"Elite",
};
STR16 szIdividualMilitiaWebsiteFilterText_Origin[] =
{
L"All origins",
L"Rebel",
L"PMC",
L"Defector",
};
STR16 szIdividualMilitiaWebsiteFilterText_Sector[] =
{
L"All sectors",
};
#endif //GERMAN
+117 -1
View File
@@ -4970,6 +4970,7 @@ STR16 pBookMarkStrings[] =
L"MeLoDY",
L"WHO",
L"Kerberus",
L"Militia Overview", // TODO.Translate
};
STR16 pBookmarkTitle[] =
@@ -5092,6 +5093,8 @@ STR16 pWebPagesTitles[] =
L"Kerberus - About Us",
L"Kerberus - Hire a Team",
L"Kerberus - Individual Contracts",
L"Militia Roster", // TODO.Translate
L"Militia Statistics",
L"Bobby Ray - Spedizioni recenti",
L"Encyclopedia",
L"Encyclopedia - Data",
@@ -6892,7 +6895,8 @@ STR16 gzLaptopHelpText[] =
L"Campaign History", // TODO.Translate
L"Mercenaries Love or Dislike You", // TODO.Translate
L"World Health Organization",
L"Kerberus - Excellence In Security",
L"Kerberus - Experience In Security",
L"Militia Overview", // TODO.Translate
};
@@ -10891,4 +10895,116 @@ STR16 szFortificationText[] =
L"Tileset %d: %s",
};
STR16 szMilitiaWebSite[] =
{
// main page
L"Militia",
L"Militia Forces Overview",
// links to other pages
L"Militia Roster",
L"Statistics",
L"About",
};
STR16 szIndividualMilitiaBattleReportText[] =
{
L"Took part in Operation %s",
L"Recruited on Day %d, %d:%2d in %s",
L"Promoted on Day %d, %d:%2d",
L"KIA, Operation %s",
L"Lightly wounded during Operation %s",
L"Heavily wounded during Operation %s",
L"Critically wounded during Operation %s",
L"Valiantly fought in Operation %s",
L"Hired from Kerberus on Day %d, %d:%2d in %s",
L"Defected to us on Day %d, %d:%2d in %s",
L"Contract terminated on Day %d, %d:%2d",
};
STR16 szIndividualMilitiaTraitRequirements[] =
{
L"HP",
L"AGI",
L"DEX",
L"STR",
L"LDR",
L"MRK",
L"MEC",
L"EXP",
L"MED",
L"WIS",
L"\nMust have regular or elite rank",
L"\nMust have elite rank",
L"\n\n|F|u|l|f|i|l|l|e|d |R|e|q|u|i|r|e|m|e|n|t|s",
L"\n\n|F|a|i|l|e|d |R|e|q|u|i|r|e|m|e|n|t|s",
L"\n%d %s",
L"\nBasic version of trait",
L" (Expert)"
};
STR16 szIdividualMilitiaWebsiteText[] =
{
L"Operations",
L"Are you sure you want to release %s from your service?",
L"HP ratio: %3.0f %% Daily Wage: %3d$ Age: %d years",
L"Daily Wage: %3d$ Age: %d years",
L"Kills: %d Assists: %d",
L"Status: Deceased",
L"Status: Fired",
L"Status: Active",
L"Terminate Contract",
L"Personal Data",
L"Service Record",
L"Inventory",
L"Militia name",
L"Sector name",
L"Weapon",
L"HP ratio: %3.1f%%%%%%%",
L"%s is not active in the currently loaded sector.",
L"%s has been promoted to regular militia",
L"%s has been promoted to elite militia",
};
STR16 szIdividualMilitiaWebsiteFilterText_Dead[] =
{
L"All statuses",
L"Deceased",
L"Active",
L"Fired",
};
STR16 szIdividualMilitiaWebsiteFilterText_Rank[] =
{
L"All ranks",
L"Green",
L"Regular",
L"Elite",
};
STR16 szIdividualMilitiaWebsiteFilterText_Origin[] =
{
L"All origins",
L"Rebel",
L"PMC",
L"Defector",
};
STR16 szIdividualMilitiaWebsiteFilterText_Sector[] =
{
L"All sectors",
};
#endif //ITALIAN
+117 -1
View File
@@ -4985,6 +4985,7 @@ STR16 pBookMarkStrings[] =
L"MeLoDY",
L"WHO",
L"Kerberus",
L"Militia Overview", // TODO.Translate
};
STR16 pBookmarkTitle[] =
@@ -5107,6 +5108,8 @@ STR16 pWebPagesTitles[] =
L"Kerberus - About Us",
L"Kerberus - Hire a Team",
L"Kerberus - Individual Contracts",
L"Militia Roster", // TODO.Translate
L"Militia Statistics",
L"Bobby Ray's - Ostatnie dostawy",
L"Encyclopedia",
L"Encyclopedia - Dane",
@@ -6906,7 +6909,8 @@ STR16 gzLaptopHelpText[] =
L"Campaign History", // TODO.Translate
L"Mercenaries Love or Dislike You", // TODO.Translate
L"World Health Organization",
L"Kerberus - Excellence In Security",
L"Kerberus - Experience In Security",
L"Militia Overview", // TODO.Translate
};
@@ -10904,4 +10908,116 @@ STR16 szFortificationText[] =
L"Tileset %d: %s",
};
STR16 szMilitiaWebSite[] =
{
// main page
L"Militia",
L"Militia Forces Overview",
// links to other pages
L"Militia Roster",
L"Statistics",
L"About",
};
STR16 szIndividualMilitiaBattleReportText[] =
{
L"Took part in Operation %s",
L"Recruited on Day %d, %d:%2d in %s",
L"Promoted on Day %d, %d:%2d",
L"KIA, Operation %s",
L"Lightly wounded during Operation %s",
L"Heavily wounded during Operation %s",
L"Critically wounded during Operation %s",
L"Valiantly fought in Operation %s",
L"Hired from Kerberus on Day %d, %d:%2d in %s",
L"Defected to us on Day %d, %d:%2d in %s",
L"Contract terminated on Day %d, %d:%2d",
};
STR16 szIndividualMilitiaTraitRequirements[] =
{
L"HP",
L"AGI",
L"DEX",
L"STR",
L"LDR",
L"MRK",
L"MEC",
L"EXP",
L"MED",
L"WIS",
L"\nMust have regular or elite rank",
L"\nMust have elite rank",
L"\n\n|F|u|l|f|i|l|l|e|d |R|e|q|u|i|r|e|m|e|n|t|s",
L"\n\n|F|a|i|l|e|d |R|e|q|u|i|r|e|m|e|n|t|s",
L"\n%d %s",
L"\nBasic version of trait",
L" (Expert)"
};
STR16 szIdividualMilitiaWebsiteText[] =
{
L"Operations",
L"Are you sure you want to release %s from your service?",
L"HP ratio: %3.0f %% Daily Wage: %3d$ Age: %d years",
L"Daily Wage: %3d$ Age: %d years",
L"Kills: %d Assists: %d",
L"Status: Deceased",
L"Status: Fired",
L"Status: Active",
L"Terminate Contract",
L"Personal Data",
L"Service Record",
L"Inventory",
L"Militia name",
L"Sector name",
L"Weapon",
L"HP ratio: %3.1f%%%%%%%",
L"%s is not active in the currently loaded sector.",
L"%s has been promoted to regular militia",
L"%s has been promoted to elite militia",
};
STR16 szIdividualMilitiaWebsiteFilterText_Dead[] =
{
L"All statuses",
L"Deceased",
L"Active",
L"Fired",
};
STR16 szIdividualMilitiaWebsiteFilterText_Rank[] =
{
L"All ranks",
L"Green",
L"Regular",
L"Elite",
};
STR16 szIdividualMilitiaWebsiteFilterText_Origin[] =
{
L"All origins",
L"Rebel",
L"PMC",
L"Defector",
};
STR16 szIdividualMilitiaWebsiteFilterText_Sector[] =
{
L"All sectors",
};
#endif //POLISH
+118 -2
View File
@@ -4976,6 +4976,7 @@ STR16 pBookMarkStrings[] =
L"БоЛТиК",
L"ВОЗ",
L"Цербер",
L"Militia Overview", // TODO.Translate
};
STR16 pBookmarkTitle[] =
@@ -5098,6 +5099,8 @@ STR16 pWebPagesTitles[] =
L"Цербер",
L"Цербер - Найм команды",
L"Цербер - Индивидуальные контракты",
L"Militia Roster", // TODO.Translate
L"Militia Statistics",
L"Бобби Рэй - последние поступления",
L"Энциклопедия",
L"Энциклопедия - данные",
@@ -6892,7 +6895,8 @@ STR16 gzLaptopHelpText[] =
L"События и факты. Арулькийские новости",
L"Бойцы Любят Тебя или Клянут",
L"Всемирная организация здравоохранения",
L"Подготовка сотрудников службы безопасности",
L"Kerberus - Experience In Security",
L"Militia Overview", // TODO.Translate
};
@@ -10924,7 +10928,7 @@ STR16 szEnemyHeliText[] =
L"База ПВО в %s обстреляла вражеский вертолёт в %s.",
};
STR16 szFortificationText[] =
STR16 szFortificationText[] = // TODO.Translate
{
L"No valid structure selected, nothing added to build plan.",
L"No gridno found to create items in %s - created items are lost.",
@@ -10935,4 +10939,116 @@ STR16 szFortificationText[] =
L"Tileset %d: %s",
};
STR16 szMilitiaWebSite[] =
{
// main page
L"Militia",
L"Militia Forces Overview",
// links to other pages
L"Militia Roster",
L"Statistics",
L"About",
};
STR16 szIndividualMilitiaBattleReportText[] =
{
L"Took part in Operation %s",
L"Recruited on Day %d, %d:%2d in %s",
L"Promoted on Day %d, %d:%2d",
L"KIA, Operation %s",
L"Lightly wounded during Operation %s",
L"Heavily wounded during Operation %s",
L"Critically wounded during Operation %s",
L"Valiantly fought in Operation %s",
L"Hired from Kerberus on Day %d, %d:%2d in %s",
L"Defected to us on Day %d, %d:%2d in %s",
L"Contract terminated on Day %d, %d:%2d",
};
STR16 szIndividualMilitiaTraitRequirements[] =
{
L"HP",
L"AGI",
L"DEX",
L"STR",
L"LDR",
L"MRK",
L"MEC",
L"EXP",
L"MED",
L"WIS",
L"\nMust have regular or elite rank",
L"\nMust have elite rank",
L"\n\n|F|u|l|f|i|l|l|e|d |R|e|q|u|i|r|e|m|e|n|t|s",
L"\n\n|F|a|i|l|e|d |R|e|q|u|i|r|e|m|e|n|t|s",
L"\n%d %s",
L"\nBasic version of trait",
L" (Expert)"
};
STR16 szIdividualMilitiaWebsiteText[] =
{
L"Operations",
L"Are you sure you want to release %s from your service?",
L"HP ratio: %3.0f %% Daily Wage: %3d$ Age: %d years",
L"Daily Wage: %3d$ Age: %d years",
L"Kills: %d Assists: %d",
L"Status: Deceased",
L"Status: Fired",
L"Status: Active",
L"Terminate Contract",
L"Personal Data",
L"Service Record",
L"Inventory",
L"Militia name",
L"Sector name",
L"Weapon",
L"HP ratio: %3.1f%%%%%%%",
L"%s is not active in the currently loaded sector.",
L"%s has been promoted to regular militia",
L"%s has been promoted to elite militia",
};
STR16 szIdividualMilitiaWebsiteFilterText_Dead[] =
{
L"All statuses",
L"Deceased",
L"Active",
L"Fired",
};
STR16 szIdividualMilitiaWebsiteFilterText_Rank[] =
{
L"All ranks",
L"Green",
L"Regular",
L"Elite",
};
STR16 szIdividualMilitiaWebsiteFilterText_Origin[] =
{
L"All origins",
L"Rebel",
L"PMC",
L"Defector",
};
STR16 szIdividualMilitiaWebsiteFilterText_Sector[] =
{
L"All sectors",
};
#endif //RUSSIAN