mirror of
https://github.com/1dot13/source.git
synced 2026-07-22 13:40:22 +02:00
- bugfix: proper sam site marking for Strategic AI git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@633 3b4a5df2-a311-0410-b5c6-a8a6f20db521
2047 lines
64 KiB
C++
2047 lines
64 KiB
C++
//Strategic AI Viewer
|
|
|
|
#ifdef PRECOMPILEDHEADERS
|
|
#include "Strategic All.h"
|
|
#include "INIReader.h"
|
|
#else
|
|
#include <stdio.h>
|
|
#include "types.h"
|
|
#include "english.h"
|
|
#include "Timer Control.h"
|
|
#include "vsurface.h"
|
|
#include "Button System.h"
|
|
#include "Font Control.h"
|
|
#include "Simple Render Utils.h"
|
|
#include "Editor Taskbar Utils.h"
|
|
#include "line.h"
|
|
#include "input.h"
|
|
#include "vobject_blitters.h"
|
|
#include "Text Input.h"
|
|
#include "mousesystem.h"
|
|
#include "strategicmap.h"
|
|
#include "Fileman.h"
|
|
#include "Map Information.h"
|
|
#include "render dirty.h"
|
|
#include "Game Clock.h"
|
|
#include "Campaign Types.h"
|
|
#include "Queen Command.h"
|
|
#include "Campaign Init.h"
|
|
#include "overhead.h"
|
|
#include "Strategic Movement.h"
|
|
#include "GameSettings.h"
|
|
#include "Game Event Hook.h"
|
|
#include "Creature Spreading.h"
|
|
#include "message.h"
|
|
#include "Game Init.h"
|
|
#endif
|
|
|
|
#ifdef JA2BETAVERSION
|
|
|
|
#define VIEWER_LEFT 15
|
|
#define VIEWER_TOP 15
|
|
#define VIEWER_WIDTH 417
|
|
#define VIEWER_HEIGHT 353
|
|
#define VIEWER_CELLW 26
|
|
#define VIEWER_CELLH 22
|
|
#define VIEWER_RIGHT (VIEWER_LEFT+VIEWER_WIDTH)
|
|
#define VIEWER_BOTTOM (VIEWER_TOP+VIEWER_HEIGHT)
|
|
|
|
enum{
|
|
VIEWER_EXIT,
|
|
VIEWER_TIMEPANEL,
|
|
VIEWER_RESET,
|
|
RESET_EASY,
|
|
RESET_NORMAL,
|
|
RESET_HARD,
|
|
COMPRESSION0,
|
|
COMPRESSION5,
|
|
COMPRESSION15,
|
|
COMPRESSION60,
|
|
//COMPRESSION6H,
|
|
TEST_INCOMING_4SIDES,
|
|
START_CREATURE_QUEST,
|
|
SPREAD_CREATURES,
|
|
CREATURE_ATTACK,
|
|
VIEW_ENEMIES,
|
|
VIEW_CREATURES,
|
|
BASEMENT1_BTN,
|
|
BASEMENT2_BTN,
|
|
BASEMENT3_BTN,
|
|
RELOAD_SECTOR,
|
|
QUEEN_AWAKE_TOGGLE,
|
|
NUM_VIEWER_BUTTONS
|
|
};
|
|
|
|
enum
|
|
{
|
|
MOVE_RED_ICON,
|
|
MOVE_BLUE_ICON,
|
|
MOVE_YELLOW_ICON,
|
|
MOVE_GRAY_ICON,
|
|
MOVE_BURGUNDY_ICON,
|
|
MOVE_ORANGE_ICON,
|
|
MOVE_GREEN_ICON,
|
|
STOP_RED_ICON,
|
|
STOP_BLUE_ICON,
|
|
STOP_YELLOW_ICON,
|
|
STOP_GRAY_ICON,
|
|
STOP_BURGUNDY_ICON,
|
|
STOP_ORANGE_ICON,
|
|
STOP_GREEN_ICON,
|
|
REIN_RED_ICON,
|
|
REIN_BLUE_ICON,
|
|
REIN_YELLOW_ICON,
|
|
REIN_GRAY_ICON,
|
|
REIN_BURGUNDY_ICON,
|
|
REIN_ORANGE_ICON,
|
|
REIN_GREEN_ICON,
|
|
STAGE_RED_ICON,
|
|
STAGE_BLUE_ICON,
|
|
STAGE_YELLOW_ICON,
|
|
STAGE_GRAY_ICON,
|
|
STAGE_BURGUNDY_ICON,
|
|
STAGE_ORANGE_ICON,
|
|
STAGE_GREEN_ICON,
|
|
SAM_ICON,
|
|
MINING_ICON,
|
|
GROUP_ANCHOR,
|
|
};
|
|
|
|
enum
|
|
{
|
|
ICON_TYPE_PATROL,
|
|
ICON_TYPE_STOPPED,
|
|
ICON_TYPE_REINFORCEMENT,
|
|
ICON_TYPE_ASSAULT,
|
|
NUM_ICON_TYPES
|
|
};
|
|
|
|
enum
|
|
{
|
|
ICON_COLOR_RED,
|
|
ICON_COLOR_BLUE,
|
|
ICON_COLOR_YELLOW,
|
|
ICON_COLOR_GRAY,
|
|
ICON_COLOR_BURGUNDY,
|
|
ICON_COLOR_ORANGE,
|
|
ICON_COLOR_GREEN,
|
|
NUM_ICON_COLORS
|
|
};
|
|
|
|
|
|
void ClearViewerRegion( INT16 sLeft, INT16 sTop, INT16 sRight, INT16 sBottom );
|
|
void HandleViewerInput();
|
|
void RenderViewer();
|
|
void ViewerMapMoveCallback( MOUSE_REGION *reg, INT32 reason );
|
|
void ViewerMapClickCallback( MOUSE_REGION *reg, INT32 reason );
|
|
void ViewerExitCallback( GUI_BUTTON *btn, INT32 reason );
|
|
void Compression0Callback( GUI_BUTTON *btn, INT32 reason );
|
|
void Compression5Callback( GUI_BUTTON *btn, INT32 reason );
|
|
void Compression15Callback( GUI_BUTTON *btn, INT32 reason );
|
|
void Compression60Callback( GUI_BUTTON *btn, INT32 reason );
|
|
void Compression6HCallback( GUI_BUTTON *btn, INT32 reason );
|
|
void EasyCallback( GUI_BUTTON *btn, INT32 reason );
|
|
void NormalCallback( GUI_BUTTON *btn, INT32 reason );
|
|
void HardCallback( GUI_BUTTON *btn, INT32 reason );
|
|
void TestIncoming4SidesCallback( GUI_BUTTON *btn, INT32 reason );
|
|
void StartCreatureQuestCallback( GUI_BUTTON *btn, INT32 reason );
|
|
void SpreadCreaturesCallback( GUI_BUTTON *btn, INT32 reason );
|
|
void CreatureAttackCallback( GUI_BUTTON *btn, INT32 reason );
|
|
void B1Callback( GUI_BUTTON *btn, INT32 reason );
|
|
void B2Callback( GUI_BUTTON *btn, INT32 reason );
|
|
void B3Callback( GUI_BUTTON *btn, INT32 reason );
|
|
void ReloadSectorCallback( GUI_BUTTON *btn, INT32 reason );
|
|
void ToggleQueenAwake( GUI_BUTTON *btn, INT32 reason );
|
|
void ViewEnemiesCallback( GUI_BUTTON *btn, INT32 reason );
|
|
void ViewCreaturesCallback( GUI_BUTTON *btn, INT32 reason );
|
|
void ExtractAndUpdatePopulations();
|
|
void PrintEnemyPopTable();
|
|
void PrintEnemiesKilledTable();
|
|
UINT8 ChooseEnemyIconColor( UINT8 ubAdmins, UINT8 ubTroops, UINT8 ubElites );
|
|
void BlitGroupIcon( UINT8 ubIconType, UINT8 ubIconColor, UINT32 uiX, UINT32 uiY, HVOBJECT hVObject );
|
|
void PrintDetailedEnemiesInSectorInfo( INT32 iScreenX, INT32 iScreenY, UINT8 ubSectorX, UINT8 ubSectorY );
|
|
|
|
|
|
|
|
MOUSE_REGION ViewerRegion;
|
|
|
|
UINT32 guiMapGraphicID;
|
|
UINT32 guiMapIconsID;
|
|
|
|
BOOLEAN gfViewerEntry;
|
|
BOOLEAN gfExitViewer;
|
|
|
|
BOOLEAN gfRenderViewer;
|
|
BOOLEAN gfRenderMap;
|
|
|
|
BOOLEAN gfViewEnemies = TRUE;
|
|
INT8 gbViewLevel = 0;
|
|
|
|
UINT16 gusBlue;
|
|
UINT16 gusLtBlue;
|
|
UINT16 gusDkBlue;
|
|
|
|
INT16 gsAINumAdmins = -1;
|
|
INT16 gsAINumTroops = -1;
|
|
INT16 gsAINumElites = -1;
|
|
INT16 gsAINumCreatures = -1;
|
|
BOOLEAN gfOverrideSector = FALSE;
|
|
|
|
UINT32 guiLastTime;
|
|
|
|
INT32 giSaveTCMode; //time compression mode;
|
|
|
|
//The sector coordinates of the mouse position (yellow)
|
|
INT16 gsHiSectorX = 0;
|
|
INT16 gsHiSectorY = 0;
|
|
//The sector coordinates of the selected sector (red)
|
|
INT16 gsSelSectorX = 0, gsSelSectorY = 0;
|
|
|
|
INT32 iViewerButton[ NUM_VIEWER_BUTTONS ];
|
|
|
|
|
|
extern BOOLEAN gfQueenAIAwake;
|
|
extern INT32 giReinforcementPool;
|
|
extern UINT32 guiEventListCurrNodes, guiEventListPeekNodes;
|
|
extern INT32 giReinforcementPoints, giRequestPoints;
|
|
extern ARMY_COMPOSITION gArmyComp[ MAX_ARMY_COMPOSITIONS ];
|
|
extern GARRISON_GROUP *gGarrisonGroup;
|
|
extern INT32 giGarrisonArraySize;
|
|
|
|
|
|
|
|
UINT16 gwGroupTypeString[ NUM_ENEMY_INTENTIONS ][ 20 ] =
|
|
{
|
|
L"RETREAT",
|
|
L"ASSAULT",
|
|
L"STAGING",
|
|
L"PATROL",
|
|
L"REINFORCE"
|
|
};
|
|
|
|
|
|
void StringFromValue( UINT16 *str, INT32 iValue, UINT32 uiMax )
|
|
{
|
|
if( iValue < 0 ) //a blank string is determined by a negative value.
|
|
str[0] = '\0';
|
|
else if( (UINT32)iValue > uiMax ) //higher than max attribute value, so convert it to the max.
|
|
swprintf( str, L"%d", uiMax );
|
|
else //this is a valid static value, so convert it to a string.
|
|
swprintf( str, L"%d", iValue );
|
|
}
|
|
|
|
BOOLEAN CreateAIViewer()
|
|
{
|
|
VOBJECT_DESC VObjectDesc;
|
|
UINT16 str[6];
|
|
|
|
//Kaiden: Loading INI file to read Values...
|
|
// Here's another one of those INI reads
|
|
// killing the Map Editor>
|
|
//CIniReader iniReader("..\\Ja2_Options.ini");
|
|
//INT32 iMaxEnemyGroupSize = iniReader.ReadInteger("Options","MAX_STRATEGIC_TEAM_SIZE",20);
|
|
|
|
//Check to see if data exists.
|
|
if( !FileExists( "DevTools\\arulco.sti" ) ||
|
|
!FileExists( "DevTools\\icons.sti" ) ||
|
|
!FileExists( "DevTools\\SmCheckbox.sti" ) )
|
|
{
|
|
ScreenMsg( FONT_WHITE, MSG_BETAVERSION, L"AIViewer missing data. Aborted." );
|
|
gfExitViewer = FALSE;
|
|
gfViewerEntry = TRUE;
|
|
return FALSE;
|
|
}
|
|
|
|
DisableScrollMessages();
|
|
giSaveTCMode = giTimeCompressMode;
|
|
|
|
VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE;
|
|
sprintf( VObjectDesc.ImageFile, "DevTools\\arulco.sti" );
|
|
if( !AddVideoObject( &VObjectDesc, &guiMapGraphicID ) )
|
|
AssertMsg( 0, "Failed to load data\\DevTools\\arulco.sti" );
|
|
sprintf( VObjectDesc.ImageFile, "DevTools\\icons.sti" );
|
|
if( !AddVideoObject( &VObjectDesc, &guiMapIconsID ) )
|
|
AssertMsg( 0, "Failed to load data\\DevTools\\icons.sti" );
|
|
|
|
gfRenderViewer = TRUE;
|
|
|
|
//Create all of the buttons here
|
|
iViewerButton[ VIEWER_EXIT ] =
|
|
CreateTextButton(L"Exit", BLOCKFONT2, FONT_RED, FONT_BLACK, BUTTON_USE_DEFAULT,
|
|
585, 425, 50, 30, BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, DEFAULT_MOVE_CALLBACK,
|
|
ViewerExitCallback );
|
|
|
|
iViewerButton[ VIEWER_TIMEPANEL ] =
|
|
CreateTextButton( WORLDTIMESTR, FONT12POINT1, FONT_BLACK, FONT_BLACK, BUTTON_USE_DEFAULT,
|
|
VIEWER_RIGHT + 3, 0, 88, 20, BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, BUTTON_NO_CALLBACK,
|
|
BUTTON_NO_CALLBACK );
|
|
DisableButton( iViewerButton[ VIEWER_TIMEPANEL ] );
|
|
SpecifyDisabledButtonStyle( iViewerButton[ VIEWER_TIMEPANEL ], DISABLED_STYLE_NONE );
|
|
iViewerButton[ COMPRESSION0 ] =
|
|
CreateTextButton( L"0", FONT12POINT1, FONT_BLACK, FONT_BLACK, BUTTON_USE_DEFAULT,
|
|
VIEWER_RIGHT + 3, 20, 17, 16, BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, DEFAULT_MOVE_CALLBACK,
|
|
Compression0Callback );
|
|
iViewerButton[ COMPRESSION5 ] =
|
|
CreateTextButton( L"5", FONT12POINT1, FONT_BLACK, FONT_BLACK, BUTTON_USE_DEFAULT,
|
|
VIEWER_RIGHT + 20, 20, 17, 16, BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, DEFAULT_MOVE_CALLBACK,
|
|
Compression5Callback );
|
|
iViewerButton[ COMPRESSION15 ] =
|
|
CreateTextButton( L"15", FONT12POINT1, FONT_BLACK, FONT_BLACK, BUTTON_USE_DEFAULT,
|
|
VIEWER_RIGHT + 37, 20, 18, 16, BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, DEFAULT_MOVE_CALLBACK,
|
|
Compression15Callback );
|
|
iViewerButton[ COMPRESSION60 ] =
|
|
CreateTextButton( L"60", FONT12POINT1, FONT_BLACK, FONT_BLACK, BUTTON_USE_DEFAULT,
|
|
VIEWER_RIGHT + 55, 20, 18, 16, BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, DEFAULT_MOVE_CALLBACK,
|
|
Compression60Callback );
|
|
/*
|
|
iViewerButton[ COMPRESSION6H ] =
|
|
CreateTextButton( L"6H", FONT12POINT1, FONT_BLACK, FONT_BLACK, BUTTON_USE_DEFAULT,
|
|
VIEWER_RIGHT + 73, 20, 18, 16, BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, DEFAULT_MOVE_CALLBACK,
|
|
Compression6HCallback );
|
|
*/
|
|
|
|
iViewerButton[ VIEWER_RESET ] =
|
|
CreateTextButton( L"Reset Enemies", FONT12POINT1, FONT_BLACK, FONT_BLACK, BUTTON_USE_DEFAULT,
|
|
526, 0, 114, 20, BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, BUTTON_NO_CALLBACK,
|
|
BUTTON_NO_CALLBACK );
|
|
DisableButton( iViewerButton[ VIEWER_RESET ] );
|
|
SpecifyDisabledButtonStyle( iViewerButton[ VIEWER_RESET ], DISABLED_STYLE_NONE );
|
|
iViewerButton[ RESET_EASY ] =
|
|
CreateTextButton( L"Easy", FONT12POINT1, FONT_BLACK, FONT_BLACK, BUTTON_USE_DEFAULT,
|
|
526, 20, 35, 16, BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, DEFAULT_MOVE_CALLBACK,
|
|
EasyCallback );
|
|
iViewerButton[ RESET_NORMAL ] =
|
|
CreateTextButton( L"Normal", FONT12POINT1, FONT_BLACK, FONT_BLACK, BUTTON_USE_DEFAULT,
|
|
561, 20, 44, 16, BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, DEFAULT_MOVE_CALLBACK,
|
|
NormalCallback );
|
|
iViewerButton[ RESET_HARD ] =
|
|
CreateTextButton( L"Hard", FONT12POINT1, FONT_BLACK, FONT_BLACK, BUTTON_USE_DEFAULT,
|
|
605, 20, 35, 16, BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, DEFAULT_MOVE_CALLBACK,
|
|
HardCallback );
|
|
|
|
iViewerButton[ TEST_INCOMING_4SIDES ] =
|
|
CreateTextButton( L"Incoming 4 Sides", FONT12POINT1, FONT_BLACK, FONT_BLACK, BUTTON_USE_DEFAULT,
|
|
VIEWER_RIGHT + 20, 100, 120, 18, BUTTON_NO_TOGGLE, MSYS_PRIORITY_HIGH, DEFAULT_MOVE_CALLBACK,
|
|
TestIncoming4SidesCallback );
|
|
iViewerButton[ START_CREATURE_QUEST ] =
|
|
CreateTextButton( L"Start Creature Quest", FONT12POINT1, FONT_BLACK, FONT_BLACK, BUTTON_USE_DEFAULT,
|
|
VIEWER_RIGHT + 20, 125, 120, 18, BUTTON_NO_TOGGLE, MSYS_PRIORITY_HIGH, DEFAULT_MOVE_CALLBACK,
|
|
StartCreatureQuestCallback );
|
|
iViewerButton[ SPREAD_CREATURES ] =
|
|
CreateTextButton( L"Spread Creatures", FONT12POINT1, FONT_BLACK, FONT_BLACK, BUTTON_USE_DEFAULT,
|
|
VIEWER_RIGHT + 20, 150, 120, 18, BUTTON_NO_TOGGLE, MSYS_PRIORITY_HIGH, DEFAULT_MOVE_CALLBACK,
|
|
SpreadCreaturesCallback );
|
|
iViewerButton[ CREATURE_ATTACK ] =
|
|
CreateTextButton( L"Creature Attack", FONT12POINT1, FONT_BLACK, FONT_BLACK, BUTTON_USE_DEFAULT,
|
|
VIEWER_RIGHT + 20, 175, 120, 18, BUTTON_NO_TOGGLE, MSYS_PRIORITY_HIGH, DEFAULT_MOVE_CALLBACK,
|
|
CreatureAttackCallback );
|
|
|
|
iViewerButton[ QUEEN_AWAKE_TOGGLE ] =
|
|
CreateCheckBoxButton( 104, VIEWER_BOTTOM + 22, "DevTools//SmCheckbox.sti", MSYS_PRIORITY_HIGH, ToggleQueenAwake );
|
|
if( gfQueenAIAwake )
|
|
{
|
|
ButtonList[ iViewerButton[ QUEEN_AWAKE_TOGGLE ] ]->uiFlags |= BUTTON_CLICKED_ON;
|
|
}
|
|
|
|
iViewerButton[ RELOAD_SECTOR ] =
|
|
CreateTextButton( L"Override Sector", FONT12POINT1, FONT_BLACK, FONT_BLACK, BUTTON_USE_DEFAULT,
|
|
10, VIEWER_BOTTOM + 5, 90, 18, BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, DEFAULT_MOVE_CALLBACK,
|
|
ReloadSectorCallback );
|
|
|
|
iViewerButton[ VIEW_ENEMIES ] =
|
|
CreateTextButton( L"View Enemies", FONT12POINT1, FONT_BLACK, FONT_BLACK, BUTTON_USE_DEFAULT,
|
|
VIEWER_RIGHT + 13, 40, 90, 20, BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, DEFAULT_MOVE_CALLBACK,
|
|
ViewEnemiesCallback );
|
|
iViewerButton[ VIEW_CREATURES ] =
|
|
CreateTextButton( L"View Creatures", FONT12POINT1, FONT_BLACK, FONT_BLACK, BUTTON_USE_DEFAULT,
|
|
VIEWER_RIGHT + 103, 40, 90, 20, BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, DEFAULT_MOVE_CALLBACK,
|
|
ViewCreaturesCallback );
|
|
|
|
iViewerButton[ BASEMENT1_BTN ] =
|
|
CreateTextButton( L"B1", FONT16ARIAL, FONT_BLACK, FONT_BLACK, BUTTON_USE_DEFAULT,
|
|
VIEWER_RIGHT + 58, 60, 30, 24, BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, DEFAULT_MOVE_CALLBACK,
|
|
B1Callback );
|
|
iViewerButton[ BASEMENT2_BTN ] =
|
|
CreateTextButton( L"B2", FONT16ARIAL, FONT_BLACK, FONT_BLACK, BUTTON_USE_DEFAULT,
|
|
VIEWER_RIGHT + 88, 60, 30, 24, BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, DEFAULT_MOVE_CALLBACK,
|
|
B2Callback );
|
|
iViewerButton[ BASEMENT3_BTN ] =
|
|
CreateTextButton( L"B3", FONT16ARIAL, FONT_BLACK, FONT_BLACK, BUTTON_USE_DEFAULT,
|
|
VIEWER_RIGHT + 118, 60, 30, 24, BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, DEFAULT_MOVE_CALLBACK,
|
|
B3Callback );
|
|
if( gfViewEnemies )
|
|
ButtonList[ iViewerButton[ VIEW_ENEMIES ] ]->uiFlags |= BUTTON_CLICKED_ON;
|
|
else
|
|
ButtonList[ iViewerButton[ VIEW_CREATURES ] ]->uiFlags |= BUTTON_CLICKED_ON;
|
|
|
|
MSYS_DefineRegion( &ViewerRegion, VIEWER_LEFT, VIEWER_TOP, VIEWER_RIGHT, VIEWER_BOTTOM, MSYS_PRIORITY_HIGH, 0,
|
|
ViewerMapMoveCallback, ViewerMapClickCallback );
|
|
|
|
//Add the enemy population override fields
|
|
InitTextInputModeWithScheme( DEFAULT_SCHEME );
|
|
StringFromValue( str, gsAINumAdmins, gGameExternalOptions.iMaxEnemyGroupSize );
|
|
AddTextInputField( 10, VIEWER_BOTTOM + 30, 25, 15, MSYS_PRIORITY_NORMAL, str, 2, INPUTTYPE_NUMERICSTRICT );
|
|
StringFromValue( str, gsAINumTroops, gGameExternalOptions.iMaxEnemyGroupSize );
|
|
AddTextInputField( 10, VIEWER_BOTTOM + 50, 25, 15, MSYS_PRIORITY_NORMAL, str, 2, INPUTTYPE_NUMERICSTRICT );
|
|
StringFromValue( str, gsAINumElites, gGameExternalOptions.iMaxEnemyGroupSize );
|
|
AddTextInputField( 10, VIEWER_BOTTOM + 70, 25, 15, MSYS_PRIORITY_NORMAL, str, 2, INPUTTYPE_NUMERICSTRICT );
|
|
StringFromValue( str, gsAINumCreatures, gGameExternalOptions.iMaxEnemyGroupSize );
|
|
AddTextInputField( 10, VIEWER_BOTTOM + 90, 25, 15, MSYS_PRIORITY_NORMAL, str, 2, INPUTTYPE_NUMERICSTRICT );
|
|
|
|
//Press buttons in based on current settings
|
|
Assert( gGameOptions.ubDifficultyLevel >= DIF_LEVEL_EASY && gGameOptions.ubDifficultyLevel <= DIF_LEVEL_HARD );
|
|
ButtonList[ iViewerButton[ RESET_EASY + gGameOptions.ubDifficultyLevel - DIF_LEVEL_EASY ] ]->uiFlags |= BUTTON_CLICKED_ON;
|
|
ButtonList[ iViewerButton[ COMPRESSION0 ] ]->uiFlags |= BUTTON_CLICKED_ON;
|
|
if( !GamePaused() )
|
|
SetGameMinutesPerSecond( 0 );
|
|
ClearViewerRegion( 0, 0, 640, 480 );
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void DestroyAIViewer()
|
|
{
|
|
INT32 i;
|
|
gfExitViewer = FALSE;
|
|
gfViewerEntry = TRUE;
|
|
for( i = 0; i < NUM_VIEWER_BUTTONS; i++ )
|
|
{
|
|
RemoveButton( iViewerButton[ i ] );
|
|
}
|
|
DeleteVideoObjectFromIndex( guiMapGraphicID );
|
|
DeleteVideoObjectFromIndex( guiMapIconsID );
|
|
MSYS_RemoveRegion( &ViewerRegion );
|
|
|
|
KillTextInputMode();
|
|
|
|
SetGameTimeCompressionLevel( giSaveTCMode );
|
|
EnableScrollMessages();
|
|
}
|
|
|
|
void ClearViewerRegion( INT16 sLeft, INT16 sTop, INT16 sRight, INT16 sBottom )
|
|
{
|
|
ColorFillVideoSurfaceArea( ButtonDestBuffer, sLeft, sTop, sRight, sBottom, gusBlue );
|
|
InvalidateRegion( sLeft, sTop, sRight, sBottom );
|
|
|
|
if( !sLeft )
|
|
{
|
|
ColorFillVideoSurfaceArea( ButtonDestBuffer, 0, sTop, 1, sBottom, gusLtBlue );
|
|
sLeft++;
|
|
}
|
|
if( !sTop )
|
|
{
|
|
ColorFillVideoSurfaceArea( ButtonDestBuffer, sLeft, 0, sRight, 1, gusLtBlue );
|
|
sTop++;
|
|
}
|
|
if( sBottom == 480 )
|
|
ColorFillVideoSurfaceArea( ButtonDestBuffer, sLeft, 479, sRight, 480, gusDkBlue );
|
|
if( sRight == 640 )
|
|
ColorFillVideoSurfaceArea( ButtonDestBuffer, 639, sTop, 640, sBottom, gusDkBlue );
|
|
}
|
|
|
|
void RenderStationaryGroups()
|
|
{
|
|
HVOBJECT hVObject;
|
|
SECTORINFO *pSector;
|
|
INT32 x, y, xp, yp;
|
|
UINT16 str[20];
|
|
INT32 iSector = 0;
|
|
UINT8 ubIconColor;
|
|
UINT8 ubGroupSize = 0;
|
|
|
|
|
|
SetFont( FONT10ARIAL );
|
|
SetFontShadow( FONT_NEARBLACK );
|
|
|
|
GetVideoObject( &hVObject, guiMapIconsID );
|
|
|
|
//Render groups that are stationary...
|
|
for( y = 0; y < 16; y++ )
|
|
{
|
|
yp = VIEWER_TOP + VIEWER_CELLH * y + 1;
|
|
for( x = 0; x < 16; x++ )
|
|
{
|
|
SetFontForeground( FONT_YELLOW );
|
|
xp = VIEWER_LEFT + VIEWER_CELLW * x + 1;
|
|
pSector = &SectorInfo[ iSector ];
|
|
|
|
if( pSector->uiFlags & SF_MINING_SITE )
|
|
BltVideoObject( FRAME_BUFFER, hVObject, MINING_ICON, xp + 25, yp - 1, VO_BLT_SRCTRANSPARENCY, NULL );
|
|
|
|
if( pSector->uiFlags & SF_SAM_SITE )
|
|
BltVideoObject( FRAME_BUFFER, hVObject, SAM_ICON, xp + 20, yp + 4, VO_BLT_SRCTRANSPARENCY, NULL );
|
|
|
|
|
|
if( pSector->ubNumberOfCivsAtLevel[0] + pSector->ubNumberOfCivsAtLevel[1] + pSector->ubNumberOfCivsAtLevel[2] )
|
|
{
|
|
// show militia
|
|
ubIconColor = ICON_COLOR_BLUE;
|
|
ubGroupSize = pSector->ubNumberOfCivsAtLevel[0] + pSector->ubNumberOfCivsAtLevel[1] + pSector->ubNumberOfCivsAtLevel[2];
|
|
}
|
|
else
|
|
if( pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites )
|
|
{
|
|
// show enemies
|
|
ubIconColor = ChooseEnemyIconColor( pSector->ubNumAdmins, pSector->ubNumTroops, pSector->ubNumElites );
|
|
ubGroupSize = pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites;
|
|
if( pSector->ubGarrisonID != NO_GARRISON )
|
|
{
|
|
if( gGarrisonGroup[ pSector->ubGarrisonID ].ubPendingGroupID )
|
|
{
|
|
if( GetJA2Clock() % 1000 < 333 )
|
|
{
|
|
SetFontForeground( FONT_LTRED );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if( GetJA2Clock() % 1000 < 333 )
|
|
{
|
|
SetFontForeground( FONT_LTKHAKI );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ubGroupSize = 0;
|
|
}
|
|
|
|
if ( ubGroupSize > 0 )
|
|
{
|
|
// draw the icon
|
|
BlitGroupIcon( ICON_TYPE_STOPPED, ubIconColor, xp, yp, hVObject );
|
|
|
|
//Print the group size
|
|
swprintf( str, L"%d", ubGroupSize );
|
|
mprintf( xp + 2, yp + 2, str );
|
|
}
|
|
|
|
iSector++;
|
|
}
|
|
}
|
|
}
|
|
|
|
void RenderMovingGroupsAndMercs()
|
|
{
|
|
GROUP *pGroup;
|
|
HVOBJECT hVObject;
|
|
INT32 x, y;
|
|
UINT8 ubNumTroops, ubNumAdmins, ubNumElites;
|
|
float ratio;
|
|
INT32 minX, maxX, minY, maxY;
|
|
INT32 iSector = 0;
|
|
UINT8 ubIconType;
|
|
UINT8 ubIconColor;
|
|
UINT8 ubFontColor;
|
|
|
|
|
|
SetFont( FONT10ARIAL );
|
|
SetFontShadow( FONT_NEARBLACK );
|
|
|
|
GetVideoObject( &hVObject, guiMapIconsID );
|
|
|
|
//Render groups that are moving...
|
|
pGroup = gpGroupList;
|
|
while( pGroup )
|
|
{
|
|
if( pGroup->ubGroupSize && !pGroup->fVehicle)
|
|
{
|
|
if( pGroup->uiTraverseTime )
|
|
{
|
|
// display how far along to the next sector they are
|
|
ratio = (pGroup->uiTraverseTime-pGroup->uiArrivalTime + GetWorldTotalMin())/(float)pGroup->uiTraverseTime;
|
|
minX = VIEWER_LEFT + VIEWER_CELLW * (pGroup->ubSectorX-1);
|
|
maxX = VIEWER_LEFT + VIEWER_CELLW * (pGroup->ubNextX-1);
|
|
x = (UINT32)(minX + ratio *(maxX-minX));
|
|
minY = VIEWER_TOP + VIEWER_CELLH * (pGroup->ubSectorY-1);
|
|
maxY = VIEWER_TOP + VIEWER_CELLH * (pGroup->ubNextY-1);
|
|
y = (UINT32)(minY + ratio *(maxY-minY));
|
|
}
|
|
else
|
|
{
|
|
x = VIEWER_LEFT + VIEWER_CELLW * (pGroup->ubSectorX-1);
|
|
y = VIEWER_TOP + VIEWER_CELLH * (pGroup->ubSectorY-1);
|
|
}
|
|
|
|
|
|
if( pGroup->fPlayer )
|
|
{
|
|
ubIconType = ( pGroup->uiTraverseTime ) ? ICON_TYPE_ASSAULT : ICON_TYPE_STOPPED;
|
|
ubIconColor = ICON_COLOR_GREEN;
|
|
ubFontColor = FONT_YELLOW;
|
|
}
|
|
else
|
|
{
|
|
//if the group was moving, then draw the anchor to visually indicate the sector of
|
|
//influence for enemy patrol groups.
|
|
if( pGroup->uiTraverseTime )
|
|
{
|
|
BltVideoObject( FRAME_BUFFER, hVObject, GROUP_ANCHOR, VIEWER_LEFT + VIEWER_CELLW * (pGroup->ubSectorX - 1), VIEWER_TOP + VIEWER_CELLH * (pGroup->ubSectorY - 1), VO_BLT_SRCTRANSPARENCY, NULL );
|
|
}
|
|
|
|
ubNumAdmins = pGroup->pEnemyGroup->ubNumAdmins;//+ pGroup->pEnemyGroup->ubAdminsInBattle;
|
|
ubNumTroops = pGroup->pEnemyGroup->ubNumTroops;//+ pGroup->pEnemyGroup->ubTroopsInBattle;
|
|
ubNumElites = pGroup->pEnemyGroup->ubNumElites;// + pGroup->pEnemyGroup->ubElitesInBattle;
|
|
|
|
// must have one of the three, already checked groupsize!
|
|
Assert( ubNumAdmins || ubNumTroops || ubNumElites );
|
|
|
|
//determine icon color
|
|
ubIconColor = ChooseEnemyIconColor( ubNumAdmins, ubNumTroops, ubNumElites );
|
|
|
|
// must have a valid intention
|
|
Assert( pGroup->pEnemyGroup->ubIntention < NUM_ENEMY_INTENTIONS );
|
|
|
|
// determine icon type - shows the groups intentions
|
|
switch ( pGroup->pEnemyGroup->ubIntention )
|
|
{
|
|
case REINFORCEMENTS: ubIconType = ICON_TYPE_REINFORCEMENT; ubFontColor = FONT_YELLOW; break;
|
|
case PATROL: ubIconType = ICON_TYPE_PATROL; ubFontColor = FONT_YELLOW; break;
|
|
case STAGING: ubIconType = ICON_TYPE_PATROL; ubFontColor = FONT_LTBLUE; break;
|
|
case PURSUIT: ubIconType = ICON_TYPE_ASSAULT; ubFontColor = FONT_YELLOW; break;
|
|
case ASSAULT: ubIconType = ICON_TYPE_ASSAULT; ubFontColor = FONT_LTBLUE; break;
|
|
|
|
default:
|
|
Assert(0);
|
|
return;
|
|
}
|
|
}
|
|
|
|
// draw the icon
|
|
BlitGroupIcon( ubIconType, ubIconColor, x, y, hVObject );
|
|
|
|
// set color
|
|
SetFontForeground( ubFontColor );
|
|
|
|
//Print the group size
|
|
if( pGroup->fPlayer && !pGroup->uiTraverseTime )
|
|
// stationary player - count all mercs there, not just the group
|
|
mprintf( x+11, y+11, L"%d", PlayerMercsInSector( pGroup->ubSectorX, pGroup->ubSectorY, pGroup->ubSectorZ ) );
|
|
else
|
|
{
|
|
if( !pGroup->pWaypoints )
|
|
{
|
|
if( GetJA2Clock() % 1000 < 750 )
|
|
{
|
|
SetFontForeground( FONT_WHITE );
|
|
}
|
|
}
|
|
mprintf( x+7, y+7, L"%d", pGroup->ubGroupSize );
|
|
}
|
|
}
|
|
|
|
pGroup = pGroup->next;
|
|
}
|
|
}
|
|
|
|
|
|
void RenderInfoInSector()
|
|
{
|
|
UINT8 ubSectorX, ubSectorY;
|
|
UINT8 ubMercs=0, ubActive=0, ubUnconcious=0, ubCollapsed=0;
|
|
INT32 i, yp;
|
|
|
|
if( gfViewEnemies && !gbViewLevel )
|
|
{
|
|
RenderStationaryGroups();
|
|
RenderMovingGroupsAndMercs();
|
|
SetFontForeground( FONT_LTRED );
|
|
mprintf( 78, 358, L"%3d", giReinforcementPool );
|
|
|
|
//Render general enemy statistics
|
|
ClearViewerRegion( 105, VIEWER_BOTTOM + 10, 265, VIEWER_BOTTOM + 66 );
|
|
SetFontForeground( FONT_YELLOW );
|
|
mprintf( 105, VIEWER_BOTTOM + 10, L"GLOBAL INFO" );
|
|
SetFontForeground( FONT_GRAY2 );
|
|
mprintf( 118, VIEWER_BOTTOM + 24, L"Strategic AI Awake" );
|
|
mprintf( 105, VIEWER_BOTTOM + 36, L"Total Request Points: %d", giRequestPoints );
|
|
mprintf( 105, VIEWER_BOTTOM + 46, L"Total Reinforcement Points: %d", giReinforcementPoints );
|
|
mprintf( 105, VIEWER_BOTTOM + 56, L"Progress (Current/Highest): %d%%/%d%%", CurrentPlayerProgressPercentage(), HighestPlayerProgressPercentage() );
|
|
|
|
PrintEnemyPopTable();
|
|
PrintEnemiesKilledTable();
|
|
}
|
|
|
|
if( gsHiSectorX && gsHiSectorY && ( gsHiSectorX != gsSelSectorX || gsHiSectorY != gsSelSectorY ) )
|
|
{ //Render sector info for the hilighted sector
|
|
SetFontForeground( FONT_YELLOW );
|
|
ubSectorX = (UINT8)gsHiSectorX;
|
|
ubSectorY = (UINT8)gsHiSectorY;
|
|
}
|
|
else if( gsSelSectorX && gsSelSectorY )
|
|
{ //Render sector info for the selected sector
|
|
SetFontForeground( FONT_RED );
|
|
ubSectorX = (UINT8)gsSelSectorX;
|
|
ubSectorY = (UINT8)gsSelSectorY;
|
|
}
|
|
else
|
|
{
|
|
return;
|
|
}
|
|
|
|
|
|
//Count the number of mercs and their states (even for underground sectors)
|
|
for( i = gTacticalStatus.Team[ OUR_TEAM ].bFirstID; i <= gTacticalStatus.Team[ OUR_TEAM ].bLastID; i++ )
|
|
{
|
|
SOLDIERTYPE *pSoldier;
|
|
|
|
pSoldier = MercPtrs[ i ];
|
|
if( pSoldier->bActive && pSoldier->sSectorX == ubSectorX && pSoldier->sSectorY == ubSectorY && pSoldier->bSectorZ == gbViewLevel )
|
|
{
|
|
if( pSoldier->bLife )
|
|
{
|
|
ubMercs++;
|
|
if( pSoldier->bLife >= OKLIFE )
|
|
{
|
|
if( pSoldier->bBreath < OKBREATH )
|
|
ubCollapsed++;
|
|
else
|
|
ubActive++;
|
|
}
|
|
else
|
|
ubUnconcious++;
|
|
}
|
|
}
|
|
}
|
|
|
|
yp = 375;
|
|
if( !gbViewLevel )
|
|
{
|
|
SECTORINFO *pSector;
|
|
GROUP *pGroup;
|
|
UINT8 ubNumAdmins=0, ubNumTroops=0, ubNumElites=0, ubAdminsInBattle=0, ubTroopsInBattle=0, ubElitesInBattle=0, ubNumGroups=0;
|
|
|
|
pSector = &SectorInfo[ SECTOR( ubSectorX, ubSectorY ) ];
|
|
|
|
//Now count the number of mobile groups in the sector.
|
|
pGroup = gpGroupList;
|
|
while( pGroup )
|
|
{
|
|
if( !pGroup->fPlayer && !pGroup->fVehicle && pGroup->ubSectorX == ubSectorX && pGroup->ubSectorY == ubSectorY )
|
|
{
|
|
ubNumTroops += pGroup->pEnemyGroup->ubNumTroops;
|
|
ubNumElites += pGroup->pEnemyGroup->ubNumElites;
|
|
ubNumAdmins += pGroup->pEnemyGroup->ubNumAdmins;
|
|
ubTroopsInBattle += pGroup->pEnemyGroup->ubTroopsInBattle;
|
|
ubElitesInBattle += pGroup->pEnemyGroup->ubElitesInBattle;
|
|
ubAdminsInBattle += pGroup->pEnemyGroup->ubAdminsInBattle;
|
|
ubNumGroups++;
|
|
}
|
|
pGroup = pGroup->next;
|
|
}
|
|
ClearViewerRegion( 280, 375, 640, 480 );
|
|
mprintf( 280, yp, L"SECTOR INFO: %c%d (ID: %d)", ubSectorY + 'A' - 1, ubSectorX, SECTOR( ubSectorX, ubSectorY ) );
|
|
yp += 10;
|
|
SetFontForeground( FONT_LTGREEN );
|
|
mprintf( 280, yp, L"%d Player Mercs: (%d Active, %d Unconcious, %d Collapsed)",
|
|
ubMercs, ubActive, ubUnconcious, ubCollapsed );
|
|
yp += 10;
|
|
SetFontForeground( FONT_LTBLUE );
|
|
mprintf( 280, yp, L"Militia: (%d Green, %d Regular, %d Elite)",
|
|
pSector->ubNumberOfCivsAtLevel[0], pSector->ubNumberOfCivsAtLevel[1], pSector->ubNumberOfCivsAtLevel[2] );
|
|
yp += 10;
|
|
SetFontForeground( FONT_ORANGE );
|
|
mprintf( 280, yp, L"Garrison: (%d:%d Admins, %d:%d Troops, %d:%d Elites)",
|
|
pSector->ubAdminsInBattle, pSector->ubNumAdmins,
|
|
pSector->ubTroopsInBattle, pSector->ubNumTroops,
|
|
pSector->ubElitesInBattle, pSector->ubNumElites );
|
|
yp += 10;
|
|
mprintf( 280, yp, L"%d Groups: (%d:%d Admins, %d:%d Troops, %d:%d Elites)", ubNumGroups,
|
|
ubAdminsInBattle, ubNumAdmins,
|
|
ubTroopsInBattle, ubNumTroops,
|
|
ubElitesInBattle, ubNumElites );
|
|
yp += 10;
|
|
SetFontForeground( FONT_WHITE );
|
|
|
|
if( gfViewEnemies )
|
|
{
|
|
PrintDetailedEnemiesInSectorInfo( 280, yp, ubSectorX, ubSectorY );
|
|
yp += 10;
|
|
}
|
|
else
|
|
{
|
|
SetFontForeground( FONT_YELLOW );
|
|
mprintf( 280, yp, L"Monsters: (%d:%d)", pSector->ubCreaturesInBattle, pSector->ubNumCreatures );
|
|
yp += 10;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
UNDERGROUND_SECTORINFO *pSector;
|
|
ClearViewerRegion( 280, 375, 640, 480 );
|
|
pSector = FindUnderGroundSector( ubSectorX, ubSectorY, gbViewLevel );
|
|
if( !pSector )
|
|
{
|
|
return;
|
|
}
|
|
mprintf( 280, yp, L"SECTOR INFO: %c%d_b%d", ubSectorY + 'A' - 1, ubSectorX, gbViewLevel );
|
|
yp += 10;
|
|
SetFontForeground( FONT_LTGREEN );
|
|
mprintf( 280, yp, L"%d Player Mercs: (%d Active, %d Unconcious, %d Collapsed)",
|
|
ubMercs, ubActive, ubUnconcious, ubCollapsed );
|
|
yp += 10;
|
|
SetFontForeground( FONT_YELLOW );
|
|
mprintf( 280, yp, L"Monsters: (%d:%d)", pSector->ubCreaturesInBattle, pSector->ubNumCreatures );
|
|
yp += 10;
|
|
if( pSector->uiFlags & SF_PENDING_ALTERNATE_MAP )
|
|
{
|
|
mprintf( 280, yp, L"SF_PENDING_ALTERNATE_MAP", pSector->ubCreaturesInBattle, pSector->ubNumCreatures );
|
|
yp += 10;
|
|
}
|
|
if( pSector->uiFlags & SF_USE_ALTERNATE_MAP )
|
|
{
|
|
mprintf( 280, yp, L"SF_USE_ALTERNATE_MAP", pSector->ubCreaturesInBattle, pSector->ubNumCreatures );
|
|
yp += 10;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
void RenderViewer()
|
|
{
|
|
UINT8 *pDestBuf;
|
|
UINT32 uiDestPitchBYTES;
|
|
SGPRect ClipRect;
|
|
INT32 i, x, y, xp, yp;
|
|
if( gfRenderViewer )
|
|
{
|
|
ClearViewerRegion( VIEWER_LEFT, VIEWER_TOP, VIEWER_RIGHT, VIEWER_BOTTOM );
|
|
|
|
gfRenderViewer = FALSE;
|
|
gfRenderMap = TRUE;
|
|
for( i = 0; i < NUM_VIEWER_BUTTONS; i++ )
|
|
{
|
|
MarkAButtonDirty( iViewerButton[ i ] );
|
|
}
|
|
|
|
SetFont( FONT10ARIAL );
|
|
SetFontForeground( FONT_YELLOW );
|
|
SetFontShadow( FONT_NEARBLACK );
|
|
|
|
mprintf( 38, VIEWER_BOTTOM + 33, L"Admins" );
|
|
mprintf( 38, VIEWER_BOTTOM + 53, L"Troops" );
|
|
mprintf( 38, VIEWER_BOTTOM + 73, L"Elites" );
|
|
mprintf( 38, VIEWER_BOTTOM + 93, L"Creatures" );
|
|
}
|
|
|
|
if( gfRenderMap )
|
|
{
|
|
gfRenderMap = FALSE;
|
|
BltVideoObjectFromIndex( FRAME_BUFFER, guiMapGraphicID, 0, VIEWER_LEFT, VIEWER_TOP, VO_BLT_SRCTRANSPARENCY, NULL );
|
|
InvalidateRegion( VIEWER_LEFT, VIEWER_TOP, VIEWER_RIGHT, VIEWER_BOTTOM );
|
|
//Draw the coordinates
|
|
ClearViewerRegion( 0, 0, VIEWER_RIGHT, 14 );
|
|
ClearViewerRegion( 0, 0, 14, VIEWER_BOTTOM );
|
|
SetFont( FONT10ARIAL );
|
|
SetFontShadow( FONT_NEARBLACK );
|
|
for( y = 0; y < 16; y++ )
|
|
{
|
|
if( y+1 == gsSelSectorY )
|
|
SetFontForeground( FONT_RED );
|
|
else if( y+1 == gsHiSectorY )
|
|
SetFontForeground( FONT_YELLOW );
|
|
else
|
|
SetFontForeground( FONT_GRAY1 );
|
|
mprintf( VIEWER_LEFT-10, VIEWER_TOP+7+y*22, L"%c", 'A' + y );
|
|
}
|
|
for( x = 1; x <= 16; x++ )
|
|
{
|
|
UINT16 str[3];
|
|
if( x == gsSelSectorX )
|
|
SetFontForeground( FONT_RED );
|
|
else if( x == gsHiSectorX )
|
|
SetFontForeground( FONT_YELLOW );
|
|
else
|
|
SetFontForeground( FONT_GRAY1 );
|
|
swprintf( str, L"%d", x );
|
|
mprintf( VIEWER_LEFT+x*26-(26+StringPixLength( str, FONT12POINT1 ))/2, VIEWER_TOP-12, str );
|
|
}
|
|
if( gbViewLevel )
|
|
{
|
|
UNDERGROUND_SECTORINFO *pUnder;
|
|
SetFont( FONT10ARIAL );
|
|
SetFontForeground( FONT_YELLOW );
|
|
SetFontShadow( FONT_NEARBLACK );
|
|
for( y = 0; y < 16; y++ )
|
|
{
|
|
ClipRect.iTop = VIEWER_TOP + y*VIEWER_CELLH;
|
|
ClipRect.iBottom = ClipRect.iTop + VIEWER_CELLH - 1;
|
|
for( x = 0; x < 16; x++ )
|
|
{
|
|
pUnder = FindUnderGroundSector( (INT16)(x + 1), (INT16)(y + 1), gbViewLevel );
|
|
if( pUnder )
|
|
{
|
|
xp = VIEWER_LEFT+x*VIEWER_CELLW+2;
|
|
yp = VIEWER_TOP+y*VIEWER_CELLH+2;
|
|
mprintf( xp, yp, L"%d", pUnder->ubNumCreatures );
|
|
}
|
|
else
|
|
{ //not found, so visually shade it darker.
|
|
pDestBuf = LockVideoSurface( FRAME_BUFFER, &uiDestPitchBYTES );
|
|
ClipRect.iLeft = VIEWER_LEFT + x*VIEWER_CELLW;
|
|
ClipRect.iRight = ClipRect.iLeft + VIEWER_CELLW - 1;
|
|
Blt16BPPBufferShadowRect( (UINT16*)pDestBuf, uiDestPitchBYTES, &ClipRect );
|
|
Blt16BPPBufferShadowRect( (UINT16*)pDestBuf, uiDestPitchBYTES, &ClipRect );
|
|
UnLockVideoSurface( FRAME_BUFFER );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
RenderInfoInSector();
|
|
}
|
|
|
|
pDestBuf = LockVideoSurface( FRAME_BUFFER, &uiDestPitchBYTES );
|
|
SetClippingRegionAndImageWidth( uiDestPitchBYTES, 0, 0, 640, 480 );
|
|
//Render the grid for the sector if the mouse is over it (yellow).
|
|
if( gsHiSectorX > 0 )
|
|
{
|
|
x = VIEWER_LEFT + (gsHiSectorX-1) * 26;
|
|
y = VIEWER_TOP + (gsHiSectorY-1) * 22;
|
|
RectangleDraw( TRUE, x, y, x+26, y+22, Get16BPPColor( FROMRGB( 200, 200, 50 ) ), pDestBuf );
|
|
}
|
|
//Render the grid for the sector currently in focus (red).
|
|
if( gsSelSectorX > 0 )
|
|
{
|
|
x = VIEWER_LEFT + (gsSelSectorX-1) * 26 ;
|
|
y = VIEWER_TOP + (gsSelSectorY-1) * 22 ;
|
|
RectangleDraw( TRUE, x, y, x+26, y+22, Get16BPPColor( FROMRGB( 200, 50, 50 ) ), pDestBuf );
|
|
}
|
|
UnLockVideoSurface( FRAME_BUFFER );
|
|
}
|
|
|
|
void ViewerExitCallback( GUI_BUTTON *btn, INT32 reason )
|
|
{
|
|
if( reason & MSYS_CALLBACK_REASON_LBUTTON_UP )
|
|
{
|
|
gfExitViewer = TRUE;
|
|
}
|
|
}
|
|
|
|
void HandleViewerInput()
|
|
{
|
|
SECTORINFO *pSector;
|
|
InputAtom Event;
|
|
while( DequeueEvent( &Event ) )
|
|
{
|
|
if( !HandleTextInput( &Event ) && Event.usEvent == KEY_DOWN )
|
|
{
|
|
switch( Event.usParam )
|
|
{
|
|
case ESC:
|
|
gfExitViewer = TRUE;
|
|
break;
|
|
case ENTER:
|
|
// this means GO! for doing overrides
|
|
ExtractAndUpdatePopulations();
|
|
break;
|
|
case 'x':
|
|
if( Event.usKeyState & ALT_DOWN )
|
|
{
|
|
gfExitViewer = TRUE;
|
|
gfProgramIsRunning = FALSE;
|
|
}
|
|
break;
|
|
case 'm':
|
|
//Kill all enemies and add militia
|
|
if( Event.usKeyState & ALT_DOWN )
|
|
{
|
|
pSector = NULL;
|
|
if( gsSelSectorX && gsSelSectorY )
|
|
{
|
|
pSector = &SectorInfo[ SECTOR( gsSelSectorX, gsSelSectorY ) ];
|
|
pSector->ubNumberOfCivsAtLevel[0] = 15;
|
|
pSector->ubNumberOfCivsAtLevel[1] = 4;
|
|
pSector->ubNumberOfCivsAtLevel[2] = 1;
|
|
gfRenderMap = TRUE;
|
|
EliminateAllEnemies( (UINT8)gsSelSectorX, (UINT8)gsSelSectorY );
|
|
}
|
|
else if( gsHiSectorX && gsHiSectorY )
|
|
{
|
|
pSector = &SectorInfo[ SECTOR( gsHiSectorX, gsHiSectorY ) ];
|
|
pSector->ubNumberOfCivsAtLevel[0] = 15;
|
|
pSector->ubNumberOfCivsAtLevel[1] = 4;
|
|
pSector->ubNumberOfCivsAtLevel[2] = 1;
|
|
gfRenderMap = TRUE;
|
|
EliminateAllEnemies( (UINT8)gsHiSectorX, (UINT8)gsHiSectorY );
|
|
}
|
|
}
|
|
break;
|
|
case 'o':
|
|
// kill all enemies!
|
|
if( Event.usKeyState & ALT_DOWN )
|
|
{
|
|
pSector = NULL;
|
|
if( gsSelSectorX && gsSelSectorY )
|
|
{
|
|
gfRenderMap = TRUE;
|
|
EliminateAllEnemies( (UINT8)gsSelSectorX, (UINT8)gsSelSectorY );
|
|
}
|
|
else if( gsHiSectorX && gsHiSectorY )
|
|
{
|
|
gfRenderMap = TRUE;
|
|
EliminateAllEnemies( (UINT8)gsHiSectorX, (UINT8)gsHiSectorY );
|
|
}
|
|
}
|
|
break;
|
|
case 'g':
|
|
//Add a group of 8 stationary enemies
|
|
if( gsSelSectorX && gsSelSectorY )
|
|
{
|
|
pSector = &SectorInfo[ SECTOR( gsSelSectorX, gsSelSectorY ) ];
|
|
pSector->ubNumElites += 1;
|
|
pSector->ubNumTroops += 7;
|
|
}
|
|
else if( gsHiSectorX && gsHiSectorY )
|
|
{
|
|
pSector = &SectorInfo[ SECTOR( gsHiSectorX, gsHiSectorY ) ];
|
|
pSector->ubNumElites += 1;
|
|
pSector->ubNumTroops += 7;
|
|
}
|
|
break;
|
|
case 'c':
|
|
//Add a group of 8 creatures.
|
|
if( gsSelSectorX && gsSelSectorY )
|
|
{
|
|
pSector = &SectorInfo[ SECTOR( gsSelSectorX, gsSelSectorY ) ];
|
|
pSector->ubNumCreatures += 8;
|
|
}
|
|
else if( gsHiSectorX && gsHiSectorY )
|
|
{
|
|
pSector = &SectorInfo[ SECTOR( gsHiSectorX, gsHiSectorY ) ];
|
|
pSector->ubNumCreatures += 8;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void EasyCallback( GUI_BUTTON *btn, INT32 reason )
|
|
{
|
|
if( reason & MSYS_CALLBACK_REASON_LBUTTON_UP )
|
|
{
|
|
ButtonList[ iViewerButton[ RESET_EASY ] ]->uiFlags |= BUTTON_CLICKED_ON;
|
|
ButtonList[ iViewerButton[ RESET_NORMAL ] ]->uiFlags &= (~BUTTON_CLICKED_ON);
|
|
ButtonList[ iViewerButton[ RESET_HARD ] ]->uiFlags &= (~BUTTON_CLICKED_ON);
|
|
ButtonList[ iViewerButton[ QUEEN_AWAKE_TOGGLE ] ]->uiFlags &= (~BUTTON_CLICKED_ON);
|
|
gfRenderViewer = TRUE;
|
|
gGameOptions.ubDifficultyLevel = DIF_LEVEL_EASY;
|
|
ShutdownStrategicLayer();
|
|
InitStrategicLayer();
|
|
Compression0Callback( ButtonList[ iViewerButton[ COMPRESSION0 ] ], MSYS_CALLBACK_REASON_LBUTTON_UP );
|
|
MarkButtonsDirty();
|
|
WarpGameTime( 45 * 60, WARPTIME_PROCESS_EVENTS_NORMALLY );
|
|
}
|
|
}
|
|
|
|
void NormalCallback( GUI_BUTTON *btn, INT32 reason )
|
|
{
|
|
if( reason & MSYS_CALLBACK_REASON_LBUTTON_UP )
|
|
{
|
|
ButtonList[ iViewerButton[ RESET_EASY ] ]->uiFlags &= (~BUTTON_CLICKED_ON);
|
|
ButtonList[ iViewerButton[ RESET_NORMAL ] ]->uiFlags |= BUTTON_CLICKED_ON;
|
|
ButtonList[ iViewerButton[ RESET_HARD ] ]->uiFlags &= (~BUTTON_CLICKED_ON);
|
|
ButtonList[ iViewerButton[ QUEEN_AWAKE_TOGGLE ] ]->uiFlags &= (~BUTTON_CLICKED_ON);
|
|
gfRenderViewer = TRUE;
|
|
gGameOptions.ubDifficultyLevel = DIF_LEVEL_MEDIUM;
|
|
ShutdownStrategicLayer();
|
|
InitStrategicLayer();
|
|
Compression0Callback( ButtonList[ iViewerButton[ COMPRESSION0 ] ], MSYS_CALLBACK_REASON_LBUTTON_UP );
|
|
MarkButtonsDirty();
|
|
WarpGameTime( 45 * 60, WARPTIME_PROCESS_EVENTS_NORMALLY );
|
|
}
|
|
}
|
|
|
|
void HardCallback( GUI_BUTTON *btn, INT32 reason )
|
|
{
|
|
if( reason & MSYS_CALLBACK_REASON_LBUTTON_UP )
|
|
{
|
|
ButtonList[ iViewerButton[ RESET_EASY ] ]->uiFlags &= (~BUTTON_CLICKED_ON);
|
|
ButtonList[ iViewerButton[ RESET_NORMAL ] ]->uiFlags &= (~BUTTON_CLICKED_ON);
|
|
ButtonList[ iViewerButton[ RESET_HARD ] ]->uiFlags |= BUTTON_CLICKED_ON;
|
|
ButtonList[ iViewerButton[ QUEEN_AWAKE_TOGGLE ] ]->uiFlags &= (~BUTTON_CLICKED_ON);
|
|
gfRenderViewer = TRUE;
|
|
gGameOptions.ubDifficultyLevel = DIF_LEVEL_HARD;
|
|
ShutdownStrategicLayer();
|
|
InitStrategicLayer();
|
|
Compression0Callback( ButtonList[ iViewerButton[ COMPRESSION0 ] ], MSYS_CALLBACK_REASON_LBUTTON_UP );
|
|
MarkButtonsDirty();
|
|
WarpGameTime( 45 * 60, WARPTIME_PROCESS_EVENTS_NORMALLY );
|
|
}
|
|
}
|
|
|
|
void ViewerMapMoveCallback( MOUSE_REGION *reg, INT32 reason )
|
|
{
|
|
static INT16 gsPrevX = 0, gsPrevY = 0;
|
|
//calc current sector highlighted.
|
|
if( reason & MSYS_CALLBACK_REASON_LOST_MOUSE )
|
|
{
|
|
gsPrevX = gsHiSectorX = 0;
|
|
gsPrevY = gsHiSectorY = 0;
|
|
gfRenderViewer = TRUE;
|
|
return;
|
|
}
|
|
gsHiSectorX = min( (reg->RelativeXPos / 26) + 1, 16 );
|
|
gsHiSectorY = min( (reg->RelativeYPos / 22) + 1, 16 );
|
|
if( gsPrevX != gsHiSectorX || gsPrevY != gsHiSectorY )
|
|
{
|
|
gsPrevX = gsHiSectorX;
|
|
gsPrevY = gsHiSectorY;
|
|
gfRenderViewer = TRUE;
|
|
}
|
|
}
|
|
|
|
void ViewerMapClickCallback( MOUSE_REGION *reg, INT32 reason )
|
|
{
|
|
static INT16 sLastX = -1, sLastY = -1;
|
|
//calc current sector selected.
|
|
if( reason & MSYS_CALLBACK_REASON_LBUTTON_UP )
|
|
{
|
|
gsSelSectorX = min( (reg->RelativeXPos / 26) + 1, 16 );
|
|
gsSelSectorY = min( (reg->RelativeYPos / 22) + 1, 16 );
|
|
if( gsSelSectorX != sLastX || gsSelSectorY != sLastY )
|
|
{ //clicked in a new sector
|
|
sLastX = gsSelSectorX;
|
|
sLastY = gsSelSectorY;
|
|
gfRenderViewer = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
UINT32 AIViewerScreenInit()
|
|
{
|
|
gfViewerEntry = TRUE;
|
|
gusBlue = Get16BPPColor( FROMRGB( 65, 79, 94 ) );
|
|
gusLtBlue = Get16BPPColor( FROMRGB( 122, 124, 121 ) );
|
|
gusDkBlue = Get16BPPColor( FROMRGB( 22, 55, 73 ) );
|
|
return TRUE;
|
|
}
|
|
|
|
UINT32 AIViewerScreenHandle()
|
|
{
|
|
StartFrameBufferRender();
|
|
|
|
RestoreBackgroundRects();
|
|
|
|
if( gfViewerEntry )
|
|
{
|
|
gfViewerEntry = FALSE;
|
|
if( !CreateAIViewer() )
|
|
{
|
|
return MAP_SCREEN;
|
|
}
|
|
}
|
|
|
|
if( GetWorldTotalSeconds() != guiLastTime )
|
|
{
|
|
guiLastTime = GetWorldTotalSeconds();
|
|
gfRenderViewer = TRUE;
|
|
SpecifyButtonText( iViewerButton[ VIEWER_TIMEPANEL ], WORLDTIMESTR );
|
|
}
|
|
|
|
HandleViewerInput();
|
|
RenderViewer();
|
|
|
|
RenderAllTextFields();
|
|
RenderButtons();
|
|
|
|
SaveBackgroundRects( );
|
|
|
|
RenderButtonsFastHelp();
|
|
|
|
ExecuteBaseDirtyRectQueue();
|
|
EndFrameBufferRender();
|
|
|
|
if( gfExitViewer )
|
|
{
|
|
DestroyAIViewer();
|
|
return MAP_SCREEN;
|
|
}
|
|
return AIVIEWER_SCREEN;
|
|
}
|
|
|
|
UINT32 AIViewerScreenShutdown()
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
void Compression0Callback( GUI_BUTTON *btn, INT32 reason )
|
|
{
|
|
if( reason & MSYS_CALLBACK_REASON_LBUTTON_UP )
|
|
{
|
|
ButtonList[ iViewerButton[ COMPRESSION0 ] ]->uiFlags |= BUTTON_CLICKED_ON;
|
|
ButtonList[ iViewerButton[ COMPRESSION5 ] ]->uiFlags &= (~BUTTON_CLICKED_ON);
|
|
ButtonList[ iViewerButton[ COMPRESSION15 ] ]->uiFlags &= (~BUTTON_CLICKED_ON);
|
|
ButtonList[ iViewerButton[ COMPRESSION60 ] ]->uiFlags &= (~BUTTON_CLICKED_ON);
|
|
// ButtonList[ iViewerButton[ COMPRESSION6H ] ]->uiFlags &= (~BUTTON_CLICKED_ON);
|
|
SetGameMinutesPerSecond( 0 );
|
|
}
|
|
}
|
|
|
|
void Compression5Callback( GUI_BUTTON *btn, INT32 reason )
|
|
{
|
|
if( reason & MSYS_CALLBACK_REASON_LBUTTON_UP )
|
|
{
|
|
ButtonList[ iViewerButton[ COMPRESSION0 ] ]->uiFlags &= (~BUTTON_CLICKED_ON);
|
|
ButtonList[ iViewerButton[ COMPRESSION5 ] ]->uiFlags |= BUTTON_CLICKED_ON;
|
|
ButtonList[ iViewerButton[ COMPRESSION15 ] ]->uiFlags &= (~BUTTON_CLICKED_ON);
|
|
ButtonList[ iViewerButton[ COMPRESSION60 ] ]->uiFlags &= (~BUTTON_CLICKED_ON);
|
|
// ButtonList[ iViewerButton[ COMPRESSION6H ] ]->uiFlags &= (~BUTTON_CLICKED_ON);
|
|
SetGameMinutesPerSecond( 5 );
|
|
SetFactTimeCompressHasOccured( );
|
|
}
|
|
}
|
|
|
|
void Compression15Callback( GUI_BUTTON *btn, INT32 reason )
|
|
{
|
|
if( reason & MSYS_CALLBACK_REASON_LBUTTON_UP )
|
|
{
|
|
ButtonList[ iViewerButton[ COMPRESSION0 ] ]->uiFlags &= (~BUTTON_CLICKED_ON);
|
|
ButtonList[ iViewerButton[ COMPRESSION5 ] ]->uiFlags &= (~BUTTON_CLICKED_ON);
|
|
ButtonList[ iViewerButton[ COMPRESSION15 ] ]->uiFlags |= BUTTON_CLICKED_ON;
|
|
ButtonList[ iViewerButton[ COMPRESSION60 ] ]->uiFlags &= (~BUTTON_CLICKED_ON);
|
|
// ButtonList[ iViewerButton[ COMPRESSION6H ] ]->uiFlags &= (~BUTTON_CLICKED_ON);
|
|
SetGameMinutesPerSecond( 15 );
|
|
SetFactTimeCompressHasOccured( );
|
|
}
|
|
}
|
|
|
|
void Compression60Callback( GUI_BUTTON *btn, INT32 reason )
|
|
{
|
|
if( reason & MSYS_CALLBACK_REASON_LBUTTON_UP )
|
|
{
|
|
ButtonList[ iViewerButton[ COMPRESSION0 ] ]->uiFlags &= (~BUTTON_CLICKED_ON);
|
|
ButtonList[ iViewerButton[ COMPRESSION5 ] ]->uiFlags &= (~BUTTON_CLICKED_ON);
|
|
ButtonList[ iViewerButton[ COMPRESSION15 ] ]->uiFlags &= (~BUTTON_CLICKED_ON);
|
|
ButtonList[ iViewerButton[ COMPRESSION60 ] ]->uiFlags |= BUTTON_CLICKED_ON;
|
|
// ButtonList[ iViewerButton[ COMPRESSION6H ] ]->uiFlags &= (~BUTTON_CLICKED_ON);
|
|
SetGameHoursPerSecond( 1 );
|
|
SetFactTimeCompressHasOccured( );
|
|
}
|
|
}
|
|
|
|
void Compression6HCallback( GUI_BUTTON *btn, INT32 reason )
|
|
{
|
|
if( reason & MSYS_CALLBACK_REASON_LBUTTON_UP )
|
|
{
|
|
ButtonList[ iViewerButton[ COMPRESSION0 ] ]->uiFlags &= (~BUTTON_CLICKED_ON);
|
|
ButtonList[ iViewerButton[ COMPRESSION5 ] ]->uiFlags &= (~BUTTON_CLICKED_ON);
|
|
ButtonList[ iViewerButton[ COMPRESSION15 ] ]->uiFlags &= (~BUTTON_CLICKED_ON);
|
|
ButtonList[ iViewerButton[ COMPRESSION60 ] ]->uiFlags &= (~BUTTON_CLICKED_ON);
|
|
// ButtonList[ iViewerButton[ COMPRESSION6H ] ]->uiFlags |= BUTTON_CLICKED_ON;
|
|
SetGameHoursPerSecond( 6 );
|
|
SetFactTimeCompressHasOccured( );
|
|
}
|
|
}
|
|
|
|
void TestIncoming4SidesCallback( GUI_BUTTON *btn, INT32 reason )
|
|
{
|
|
if( reason & MSYS_CALLBACK_REASON_LBUTTON_UP )
|
|
{
|
|
GROUP *pGroup;
|
|
UINT8 ubSector;
|
|
UINT32 uiWorldMin;
|
|
Compression0Callback( ButtonList[ iViewerButton[ COMPRESSION0 ] ], MSYS_CALLBACK_REASON_LBUTTON_UP );
|
|
if( ( gsSelSectorX == 0 ) || ( gsSelSectorY == 0 ) )
|
|
gsSelSectorX = 9, gsSelSectorY = 1;
|
|
|
|
ubSector = SECTOR( gsSelSectorX, gsSelSectorY );
|
|
uiWorldMin = GetWorldTotalMin();
|
|
gfRenderViewer = TRUE;
|
|
if( gsSelSectorY > 1 )
|
|
{
|
|
pGroup = CreateNewEnemyGroupDepartingFromSector( ubSector-16, 0, 11, 5 );
|
|
pGroup->ubNextX = (UINT8)gsSelSectorX;
|
|
pGroup->ubNextY = (UINT8)gsSelSectorY;
|
|
pGroup->uiTraverseTime = 10;
|
|
pGroup->pEnemyGroup->ubIntention = ASSAULT;
|
|
SetGroupArrivalTime( pGroup, uiWorldMin + 10 );
|
|
pGroup->ubMoveType = ONE_WAY;
|
|
pGroup->fDebugGroup = TRUE;
|
|
AddStrategicEvent( EVENT_GROUP_ARRIVAL, pGroup->uiArrivalTime, pGroup->ubGroupID );
|
|
}
|
|
if( gsSelSectorY < 16 )
|
|
{
|
|
pGroup = CreateNewEnemyGroupDepartingFromSector( ubSector+16, 0, 8, 8 );
|
|
pGroup->ubNextX = (UINT8)gsSelSectorX;
|
|
pGroup->ubNextY = (UINT8)gsSelSectorY;
|
|
pGroup->uiTraverseTime = 12;
|
|
pGroup->pEnemyGroup->ubIntention = ASSAULT;
|
|
SetGroupArrivalTime( pGroup, uiWorldMin + 12 );
|
|
pGroup->ubMoveType = ONE_WAY;
|
|
pGroup->fDebugGroup = TRUE;
|
|
AddStrategicEvent( EVENT_GROUP_ARRIVAL, pGroup->uiArrivalTime, pGroup->ubGroupID );
|
|
}
|
|
if( gsSelSectorX > 1 )
|
|
{
|
|
pGroup = CreateNewEnemyGroupDepartingFromSector( ubSector-1, 0, 11, 5 );
|
|
pGroup->ubNextX = (UINT8)gsSelSectorX;
|
|
pGroup->ubNextY = (UINT8)gsSelSectorY;
|
|
pGroup->uiTraverseTime = 11;
|
|
pGroup->pEnemyGroup->ubIntention = ASSAULT;
|
|
SetGroupArrivalTime( pGroup, uiWorldMin + 11 );
|
|
pGroup->ubMoveType = ONE_WAY;
|
|
pGroup->fDebugGroup = TRUE;
|
|
AddStrategicEvent( EVENT_GROUP_ARRIVAL, pGroup->uiArrivalTime, pGroup->ubGroupID );
|
|
}
|
|
if( gsSelSectorX < 16 )
|
|
{
|
|
pGroup = CreateNewEnemyGroupDepartingFromSector( ubSector+1, 0, 14, 0 );
|
|
pGroup->ubNextX = (UINT8)gsSelSectorX;
|
|
pGroup->ubNextY = (UINT8)gsSelSectorY;
|
|
pGroup->uiTraverseTime = 13;
|
|
pGroup->pEnemyGroup->ubIntention = ASSAULT;
|
|
SetGroupArrivalTime( pGroup, uiWorldMin + 13 );
|
|
pGroup->ubMoveType = ONE_WAY;
|
|
pGroup->fDebugGroup = TRUE;
|
|
AddStrategicEvent( EVENT_GROUP_ARRIVAL, pGroup->uiArrivalTime, pGroup->ubGroupID );
|
|
}
|
|
}
|
|
}
|
|
|
|
void StartCreatureQuestCallback( GUI_BUTTON *btn, INT32 reason )
|
|
{
|
|
if( reason & MSYS_CALLBACK_REASON_LBUTTON_UP )
|
|
{
|
|
//Madd: wtf? gGameOptions.ubGameStyle == STYLE_PLATINUM;
|
|
gfRenderMap = TRUE;
|
|
ClearCreatureQuest();
|
|
InitCreatureQuest();
|
|
}
|
|
}
|
|
|
|
void SpreadCreaturesCallback( GUI_BUTTON *btn, INT32 reason )
|
|
{
|
|
if( reason & MSYS_CALLBACK_REASON_LBUTTON_UP )
|
|
{
|
|
gfRenderMap = TRUE;
|
|
if( _KeyDown( ALT ) )
|
|
{
|
|
INT32 i;
|
|
// spread 10 times
|
|
for( i = 0; i < 10; i++ )
|
|
{
|
|
SpreadCreatures();
|
|
}
|
|
}
|
|
SpreadCreatures();
|
|
}
|
|
}
|
|
|
|
void CreatureAttackCallback( GUI_BUTTON *btn, INT32 reason )
|
|
{
|
|
if( reason & MSYS_CALLBACK_REASON_LBUTTON_UP )
|
|
{
|
|
if( ( gsSelSectorX != 0 ) && ( gsSelSectorX != 0 ) )
|
|
{
|
|
if( _KeyDown( ALT ) )
|
|
{
|
|
AddStrategicEventUsingSeconds( EVENT_CREATURE_ATTACK, GetWorldTotalSeconds()+4, SECTOR( gsSelSectorX, gsSelSectorY ) );
|
|
}
|
|
else
|
|
{
|
|
CreatureAttackTown( (UINT8)SECTOR( gsSelSectorX, gsSelSectorY ), TRUE );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void ViewEnemiesCallback( GUI_BUTTON *btn, INT32 reason )
|
|
{
|
|
if( reason & MSYS_CALLBACK_REASON_LBUTTON_UP )
|
|
{
|
|
gfViewEnemies = TRUE;
|
|
gfRenderMap = TRUE;
|
|
ButtonList[ iViewerButton[ VIEW_CREATURES ] ]->uiFlags &= ~BUTTON_CLICKED_ON;
|
|
gbViewLevel = 0;
|
|
ButtonList[ iViewerButton[ BASEMENT1_BTN ] ]->uiFlags &= ~BUTTON_CLICKED_ON;
|
|
ButtonList[ iViewerButton[ BASEMENT2_BTN ] ]->uiFlags &= ~BUTTON_CLICKED_ON;
|
|
ButtonList[ iViewerButton[ BASEMENT3_BTN ] ]->uiFlags &= ~BUTTON_CLICKED_ON;
|
|
}
|
|
}
|
|
|
|
void ViewCreaturesCallback( GUI_BUTTON *btn, INT32 reason )
|
|
{
|
|
if( reason & MSYS_CALLBACK_REASON_LBUTTON_UP )
|
|
{
|
|
gfViewEnemies = FALSE;
|
|
gfRenderMap = TRUE;
|
|
ButtonList[ iViewerButton[ VIEW_ENEMIES] ]->uiFlags &= ~BUTTON_CLICKED_ON;
|
|
if( !gbViewLevel )
|
|
{
|
|
gbViewLevel = 1;
|
|
ButtonList[ iViewerButton[ BASEMENT1_BTN ] ]->uiFlags |= BUTTON_CLICKED_ON;
|
|
ButtonList[ iViewerButton[ BASEMENT2_BTN ] ]->uiFlags &= ~BUTTON_CLICKED_ON;
|
|
ButtonList[ iViewerButton[ BASEMENT3_BTN ] ]->uiFlags &= ~BUTTON_CLICKED_ON;
|
|
}
|
|
}
|
|
}
|
|
|
|
void B1Callback( GUI_BUTTON *btn, INT32 reason )
|
|
{
|
|
if( reason & MSYS_CALLBACK_REASON_LBUTTON_UP )
|
|
{
|
|
gfRenderMap = TRUE;
|
|
gbViewLevel = 1;
|
|
ButtonList[ iViewerButton[ BASEMENT2_BTN ] ]->uiFlags &= ~BUTTON_CLICKED_ON;
|
|
ButtonList[ iViewerButton[ BASEMENT3_BTN ] ]->uiFlags &= ~BUTTON_CLICKED_ON;
|
|
}
|
|
}
|
|
|
|
void B2Callback( GUI_BUTTON *btn, INT32 reason )
|
|
{
|
|
if( reason & MSYS_CALLBACK_REASON_LBUTTON_UP )
|
|
{
|
|
gfRenderMap = TRUE;
|
|
gbViewLevel = 2;
|
|
ButtonList[ iViewerButton[ BASEMENT1_BTN ] ]->uiFlags &= ~BUTTON_CLICKED_ON;
|
|
ButtonList[ iViewerButton[ BASEMENT3_BTN ] ]->uiFlags &= ~BUTTON_CLICKED_ON;
|
|
}
|
|
}
|
|
|
|
void B3Callback( GUI_BUTTON *btn, INT32 reason )
|
|
{
|
|
if( reason & MSYS_CALLBACK_REASON_LBUTTON_UP )
|
|
{
|
|
gfRenderMap = TRUE;
|
|
gbViewLevel = 3;
|
|
ButtonList[ iViewerButton[ BASEMENT1_BTN ] ]->uiFlags &= ~BUTTON_CLICKED_ON;
|
|
ButtonList[ iViewerButton[ BASEMENT2_BTN ] ]->uiFlags &= ~BUTTON_CLICKED_ON;
|
|
}
|
|
}
|
|
|
|
void ReloadSectorCallback( GUI_BUTTON *btn, INT32 reason )
|
|
{
|
|
if( reason & MSYS_CALLBACK_REASON_LBUTTON_UP )
|
|
{
|
|
gfOverrideSector = TRUE;
|
|
ExtractAndUpdatePopulations();
|
|
SetCurrentWorldSector( gWorldSectorX, gWorldSectorY, gbWorldSectorZ );
|
|
gfOverrideSector = FALSE;
|
|
DestroyAIViewer();
|
|
}
|
|
}
|
|
|
|
void ExtractAndUpdatePopulations()
|
|
{
|
|
|
|
|
|
//Kaiden: Loading INI file to read Values...
|
|
//Tag for later - this is one of the reasons the
|
|
// Map Editor won't compile. And I feel stupid about it.
|
|
// Pointing to a static location for the INI file.
|
|
// Not only bad, the file is no longer there.
|
|
//CIniReader iniReader("..\\Ja2_Options.ini");
|
|
//INT32 iMaxEnemyGroupSize = iniReader.ReadInteger("Options","MAX_STRATEGIC_TEAM_SIZE",20);
|
|
|
|
gsAINumAdmins = min( GetNumericStrictValueFromField( 0 ), gGameExternalOptions.iMaxEnemyGroupSize );
|
|
SetInputFieldStringWithNumericStrictValue( 0, gsAINumAdmins );
|
|
|
|
gsAINumTroops = min( GetNumericStrictValueFromField( 1 ), gGameExternalOptions.iMaxEnemyGroupSize );
|
|
SetInputFieldStringWithNumericStrictValue( 1, gsAINumTroops );
|
|
|
|
gsAINumElites = min( GetNumericStrictValueFromField( 2 ), gGameExternalOptions.iMaxEnemyGroupSize );
|
|
SetInputFieldStringWithNumericStrictValue( 2, gsAINumElites );
|
|
|
|
gsAINumCreatures = min( GetNumericStrictValueFromField( 3 ), gGameExternalOptions.iMaxEnemyGroupSize );
|
|
SetInputFieldStringWithNumericStrictValue( 3, gsAINumCreatures );
|
|
}
|
|
|
|
void ToggleQueenAwake( GUI_BUTTON *btn, INT32 reason )
|
|
{
|
|
if( reason & MSYS_CALLBACK_REASON_LBUTTON_UP )
|
|
{
|
|
if( btn->uiFlags & BUTTON_CLICKED_ON )
|
|
{
|
|
WakeUpQueen();
|
|
}
|
|
else
|
|
{
|
|
gfQueenAIAwake = FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
enum
|
|
{
|
|
ENEMY_RANK_TOTAL = NUM_ENEMY_RANKS,
|
|
ENEMY_RANK_PERCENT,
|
|
TABLE_ENEMY_RANKS
|
|
};
|
|
|
|
UINT16 EnemyRankString[ TABLE_ENEMY_RANKS ][ 10 ] =
|
|
{
|
|
L"Adm",
|
|
L"Trp",
|
|
L"Elt",
|
|
L"TOT",
|
|
L"%%",
|
|
};
|
|
|
|
|
|
enum
|
|
{
|
|
ENEMY_TYPE_POOL,
|
|
ENEMY_TYPE_GARRISON,
|
|
ENEMY_TYPE_PATROL,
|
|
ENEMY_TYPE_REINFORCEMENTS,
|
|
ENEMY_TYPE_ASSAULT,
|
|
ENEMY_TYPE_STAGING,
|
|
ENEMY_TYPE_RETREATING,
|
|
ENEMY_TYPE_TOTAL,
|
|
ENEMY_TYPE_PERCENT,
|
|
POP_TABLE_ENEMY_TYPES
|
|
};
|
|
|
|
UINT16 EnemyTypeString[ POP_TABLE_ENEMY_TYPES ][ 10 ] =
|
|
{
|
|
L"Pool",
|
|
L"Garr",
|
|
L"Ptrl",
|
|
L"Rein",
|
|
L"Aslt",
|
|
L"Stag",
|
|
L"Rtrt",
|
|
L" TOT",
|
|
L" %%",
|
|
};
|
|
|
|
|
|
#define POP_TABLE_X_OFFSET 30
|
|
#define POP_TABLE_X_GAP 30
|
|
#define POP_TABLE_Y_GAP 10
|
|
|
|
void PrintEnemyPopTable()
|
|
{
|
|
UINT16 usX, usY;
|
|
UINT16 usEnemyPopTable[ TABLE_ENEMY_RANKS ][ POP_TABLE_ENEMY_TYPES ];
|
|
UINT32 uiSector = 0;
|
|
UINT8 ubEnemyRank;
|
|
UINT8 ubEnemyType;
|
|
SECTORINFO *pSector;
|
|
GROUP *pGroup;
|
|
UINT16 wPrintSpec[ 10 ];
|
|
UINT16 wTempString [10 ];
|
|
|
|
|
|
memset( &usEnemyPopTable, 0, sizeof ( usEnemyPopTable ) );
|
|
|
|
// count how many enemies of each type & rank there are
|
|
|
|
// this is quite inaccurate, since elites can also come from the pool
|
|
usEnemyPopTable[ ENEMY_RANK_TROOP ][ ENEMY_TYPE_POOL ] += ( UINT16 ) giReinforcementPool;
|
|
|
|
// count stationary enemies (garrisons)
|
|
for ( uiSector = 0; uiSector < 256; uiSector++ )
|
|
{
|
|
pSector = &SectorInfo[ uiSector ];
|
|
|
|
usEnemyPopTable[ ENEMY_RANK_ADMIN ][ ENEMY_TYPE_GARRISON ] += pSector->ubNumAdmins;
|
|
usEnemyPopTable[ ENEMY_RANK_TROOP ][ ENEMY_TYPE_GARRISON ] += pSector->ubNumTroops;
|
|
usEnemyPopTable[ ENEMY_RANK_ELITE ][ ENEMY_TYPE_GARRISON ] += pSector->ubNumElites;
|
|
}
|
|
|
|
// count moving enemies
|
|
pGroup = gpGroupList;
|
|
while( pGroup )
|
|
{
|
|
if( !pGroup->fPlayer && !pGroup->fDebugGroup )
|
|
{
|
|
Assert( pGroup->pEnemyGroup != NULL );
|
|
|
|
switch ( pGroup->pEnemyGroup->ubIntention )
|
|
{
|
|
case REINFORCEMENTS: ubEnemyType = ENEMY_TYPE_REINFORCEMENTS; break;
|
|
case ASSAULT: ubEnemyType = ENEMY_TYPE_ASSAULT; break;
|
|
case STAGING: ubEnemyType = ENEMY_TYPE_STAGING; break;
|
|
case PATROL: ubEnemyType = ENEMY_TYPE_PATROL; break;
|
|
case PURSUIT: ubEnemyType = ENEMY_TYPE_ASSAULT; break;
|
|
|
|
default:
|
|
AssertMsg( 0, String( "Unknown moving group intention %d", pGroup->pEnemyGroup->ubIntention ) );
|
|
continue;
|
|
}
|
|
|
|
usEnemyPopTable[ ENEMY_RANK_ADMIN ][ ubEnemyType ] += pGroup->pEnemyGroup->ubNumAdmins;
|
|
usEnemyPopTable[ ENEMY_RANK_TROOP ][ ubEnemyType ] += pGroup->pEnemyGroup->ubNumTroops;
|
|
usEnemyPopTable[ ENEMY_RANK_ELITE ][ ubEnemyType ] += pGroup->pEnemyGroup->ubNumElites;
|
|
}
|
|
|
|
pGroup = pGroup->next;
|
|
}
|
|
|
|
|
|
// add up totals across rows (ranks) by type
|
|
for ( ubEnemyType = 0; ubEnemyType < ENEMY_TYPE_TOTAL; ubEnemyType++ )
|
|
{
|
|
for ( ubEnemyRank = 0; ubEnemyRank < ENEMY_RANK_TOTAL; ubEnemyRank++ )
|
|
{
|
|
usEnemyPopTable[ ENEMY_RANK_TOTAL ][ ubEnemyType ] += usEnemyPopTable[ ubEnemyRank ][ ubEnemyType ];
|
|
}
|
|
}
|
|
|
|
// add up totals by rank across columns (types)
|
|
for ( ubEnemyRank = 0; ubEnemyRank <= ENEMY_RANK_TOTAL; ubEnemyRank++ )
|
|
{
|
|
for ( ubEnemyType = 0; ubEnemyType < ENEMY_TYPE_TOTAL; ubEnemyType++ )
|
|
{
|
|
usEnemyPopTable[ ubEnemyRank ][ ENEMY_TYPE_TOTAL ] += usEnemyPopTable[ ubEnemyRank ][ ubEnemyType ];
|
|
}
|
|
}
|
|
|
|
|
|
// avoid division by zero
|
|
if ( usEnemyPopTable[ ENEMY_RANK_TOTAL ][ ENEMY_TYPE_TOTAL ] > 0 )
|
|
{
|
|
// calculate rank percentages
|
|
for ( ubEnemyRank = 0; ubEnemyRank < ENEMY_RANK_PERCENT; ubEnemyRank++ )
|
|
{
|
|
usEnemyPopTable[ ubEnemyRank ][ ENEMY_TYPE_PERCENT ] = ( ( 100 * usEnemyPopTable[ ubEnemyRank ][ ENEMY_TYPE_TOTAL ] ) /
|
|
usEnemyPopTable[ ENEMY_RANK_TOTAL ][ ENEMY_TYPE_TOTAL ] );
|
|
}
|
|
|
|
// calculate type percentages
|
|
for ( ubEnemyType = 0; ubEnemyType < ENEMY_TYPE_PERCENT; ubEnemyType++ )
|
|
{
|
|
usEnemyPopTable[ ENEMY_RANK_PERCENT ][ ubEnemyType ] = ( ( 100 * usEnemyPopTable[ ENEMY_RANK_TOTAL ][ ubEnemyType ] ) /
|
|
usEnemyPopTable[ ENEMY_RANK_TOTAL ][ ENEMY_TYPE_TOTAL ] );
|
|
}
|
|
}
|
|
|
|
usX = VIEWER_RIGHT + 10;
|
|
usY = 200;
|
|
|
|
// titles and headings mean 2 extra rows
|
|
ClearViewerRegion( usX, usY, 640, ( INT16 ) ( usY + ( POP_TABLE_Y_GAP * ( POP_TABLE_ENEMY_TYPES + 2 )) + 11 ) );
|
|
|
|
// print table title
|
|
SetFontForeground( FONT_RED );
|
|
mprintf( usX, usY, L"ENEMY POPULATION:" );
|
|
usY += POP_TABLE_Y_GAP;
|
|
|
|
// print horizontal labels
|
|
for ( ubEnemyRank = 0; ubEnemyRank < TABLE_ENEMY_RANKS; ubEnemyRank++ )
|
|
{
|
|
DrawTextToScreen( EnemyRankString[ ubEnemyRank ], ( UINT16 ) ( usX + POP_TABLE_X_OFFSET + ( POP_TABLE_X_GAP * ubEnemyRank ) ), usY, POP_TABLE_X_GAP, FONT10ARIAL, FONT_LTBLUE, 0, FALSE, RIGHT_JUSTIFIED );
|
|
}
|
|
|
|
|
|
// print vertical labels
|
|
for ( ubEnemyType = 0; ubEnemyType < POP_TABLE_ENEMY_TYPES; ubEnemyType++ )
|
|
{
|
|
DrawTextToScreen( EnemyTypeString[ ubEnemyType ], usX, ( UINT16 ) ( usY + POP_TABLE_Y_GAP + ( POP_TABLE_Y_GAP * ubEnemyType ) ), POP_TABLE_X_OFFSET, FONT10ARIAL, FONT_LTBLUE, 0, FALSE, RIGHT_JUSTIFIED );
|
|
}
|
|
|
|
// over to first column, and down 1 line
|
|
usY += POP_TABLE_Y_GAP;
|
|
usX += POP_TABLE_X_OFFSET;
|
|
|
|
SetFontForeground( FONT_YELLOW );
|
|
|
|
// print table values
|
|
for ( ubEnemyRank = 0; ubEnemyRank < TABLE_ENEMY_RANKS; ubEnemyRank++ )
|
|
{
|
|
for ( ubEnemyType = 0; ubEnemyType < POP_TABLE_ENEMY_TYPES; ubEnemyType++ )
|
|
{
|
|
// an exclusive OR operator, how often do ya see that, huh? :-)
|
|
if ( ( ubEnemyRank == ENEMY_RANK_PERCENT ) ^ ( ubEnemyType == ENEMY_TYPE_PERCENT ) )
|
|
{
|
|
wcscpy( wPrintSpec, L"%3d%%%%" );
|
|
}
|
|
else
|
|
if ( ( ubEnemyRank == ENEMY_RANK_PERCENT ) && ( ubEnemyType == ENEMY_TYPE_PERCENT ) )
|
|
{
|
|
wcscpy( wPrintSpec, L"" );
|
|
}
|
|
else
|
|
{
|
|
wcscpy( wPrintSpec, L"%4d" );
|
|
}
|
|
|
|
swprintf( wTempString, wPrintSpec, usEnemyPopTable[ ubEnemyRank ][ ubEnemyType ] );
|
|
DrawTextToScreen( wTempString, ( UINT16 ) ( usX + ( POP_TABLE_X_GAP * ubEnemyRank ) ), ( UINT16 ) ( usY + ( POP_TABLE_Y_GAP * ubEnemyType ) ), POP_TABLE_X_GAP, FONT10ARIAL, FONT_YELLOW, 0, FALSE, RIGHT_JUSTIFIED );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
enum
|
|
{
|
|
ENEMIES_KILLED_IN_TACTICAL,
|
|
ENEMIES_KILLED_IN_AUTO_RESOLVE,
|
|
ENEMIES_KILLED_TOTAL,
|
|
ENEMIES_KILLED_PERCENT,
|
|
KILLED_TABLE_ROWS
|
|
};
|
|
|
|
UINT16 EnemiesKilledString[ KILLED_TABLE_ROWS ][ 10 ] =
|
|
{
|
|
L"Tact",
|
|
L"Auto",
|
|
L" TOT",
|
|
L" %%",
|
|
};
|
|
|
|
|
|
#define KILLED_TABLE_X_OFFSET 30
|
|
#define KILLED_TABLE_X_GAP 30
|
|
#define KILLED_TABLE_Y_GAP 10
|
|
|
|
void PrintEnemiesKilledTable()
|
|
{
|
|
UINT16 usX, usY;
|
|
UINT16 usEnemiesKilledTable[ TABLE_ENEMY_RANKS ][ KILLED_TABLE_ROWS ];
|
|
UINT8 ubEnemyRank;
|
|
UINT8 ubKillType;
|
|
UINT16 wPrintSpec[ 10 ];
|
|
UINT16 wTempString [10 ];
|
|
|
|
|
|
memset( &usEnemiesKilledTable, 0, sizeof ( usEnemiesKilledTable ) );
|
|
|
|
// fill table with raw data
|
|
for ( ubKillType = 0; ubKillType < ENEMIES_KILLED_TOTAL; ubKillType++ )
|
|
{
|
|
for ( ubEnemyRank = 0; ubEnemyRank < ENEMY_RANK_TOTAL; ubEnemyRank++ )
|
|
{
|
|
usEnemiesKilledTable[ ubEnemyRank ][ ubKillType ] = gStrategicStatus.usEnemiesKilled[ ubKillType ][ ubEnemyRank ];
|
|
}
|
|
}
|
|
|
|
// count how many enemies of each type & rank there are
|
|
|
|
// add up totals across rows (ranks) by type
|
|
for ( ubKillType = 0; ubKillType < ENEMIES_KILLED_TOTAL; ubKillType++ )
|
|
{
|
|
for ( ubEnemyRank = 0; ubEnemyRank < ENEMY_RANK_TOTAL; ubEnemyRank++ )
|
|
{
|
|
usEnemiesKilledTable[ ENEMY_RANK_TOTAL ][ ubKillType ] += usEnemiesKilledTable[ ubEnemyRank ][ ubKillType ];
|
|
}
|
|
}
|
|
|
|
// add up totals by rank across columns (types)
|
|
for ( ubEnemyRank = 0; ubEnemyRank <= ENEMY_RANK_TOTAL; ubEnemyRank++ )
|
|
{
|
|
for ( ubKillType = 0; ubKillType < ENEMIES_KILLED_TOTAL; ubKillType++ )
|
|
{
|
|
usEnemiesKilledTable[ ubEnemyRank ][ ENEMIES_KILLED_TOTAL ] += usEnemiesKilledTable[ ubEnemyRank ][ ubKillType ];
|
|
}
|
|
}
|
|
|
|
// avoid division by zero
|
|
if ( usEnemiesKilledTable[ ENEMY_RANK_TOTAL ][ ENEMIES_KILLED_TOTAL ] > 0 )
|
|
{
|
|
// calculate rank percentages
|
|
for ( ubEnemyRank = 0; ubEnemyRank < ENEMY_RANK_PERCENT; ubEnemyRank++ )
|
|
{
|
|
usEnemiesKilledTable[ ubEnemyRank ][ ENEMIES_KILLED_PERCENT ] = ( ( 100 * usEnemiesKilledTable[ ubEnemyRank ][ ENEMIES_KILLED_TOTAL ] ) /
|
|
usEnemiesKilledTable[ ENEMY_RANK_TOTAL ][ ENEMIES_KILLED_TOTAL ] );
|
|
}
|
|
|
|
// calculate kill type percentages
|
|
for ( ubKillType = 0; ubKillType < ENEMIES_KILLED_PERCENT; ubKillType++ )
|
|
{
|
|
usEnemiesKilledTable[ ENEMY_RANK_PERCENT ][ ubKillType ] = ( ( 100 * usEnemiesKilledTable[ ENEMY_RANK_TOTAL ][ ubKillType ] ) /
|
|
usEnemiesKilledTable[ ENEMY_RANK_TOTAL ][ ENEMIES_KILLED_TOTAL ] );
|
|
}
|
|
}
|
|
|
|
usX = VIEWER_RIGHT + 10;
|
|
usY = 310;
|
|
|
|
// titles and headings mean 2 extra rows
|
|
ClearViewerRegion( usX, usY, 640, ( INT16 ) ( usY + ( KILLED_TABLE_Y_GAP * ( KILLED_TABLE_ROWS + 2 ) ) + 11) );
|
|
|
|
// print table title
|
|
SetFontForeground( FONT_RED );
|
|
mprintf( usX, usY, L"ENEMIES KILLED:" );
|
|
usY += KILLED_TABLE_Y_GAP;
|
|
|
|
// print horizontal labels
|
|
for ( ubEnemyRank = 0; ubEnemyRank < TABLE_ENEMY_RANKS; ubEnemyRank++ )
|
|
{
|
|
DrawTextToScreen( EnemyRankString[ ubEnemyRank ], ( UINT16 ) ( usX + KILLED_TABLE_X_OFFSET + ( KILLED_TABLE_X_GAP * ubEnemyRank ) ), usY, KILLED_TABLE_X_GAP, FONT10ARIAL, FONT_LTBLUE, 0, FALSE, RIGHT_JUSTIFIED );
|
|
}
|
|
|
|
|
|
// print vertical labels
|
|
for ( ubKillType = 0; ubKillType < KILLED_TABLE_ROWS; ubKillType++ )
|
|
{
|
|
DrawTextToScreen( EnemiesKilledString[ ubKillType ], usX, ( UINT16 ) ( usY + KILLED_TABLE_Y_GAP + ( KILLED_TABLE_Y_GAP * ubKillType ) ), KILLED_TABLE_X_OFFSET, FONT10ARIAL, FONT_LTBLUE, 0, FALSE, RIGHT_JUSTIFIED );
|
|
}
|
|
|
|
// over to first column, and down 1 line
|
|
usY += KILLED_TABLE_Y_GAP;
|
|
usX += KILLED_TABLE_X_OFFSET;
|
|
|
|
SetFontForeground( FONT_YELLOW );
|
|
|
|
// print table values
|
|
for ( ubEnemyRank = 0; ubEnemyRank < TABLE_ENEMY_RANKS; ubEnemyRank++ )
|
|
{
|
|
for ( ubKillType = 0; ubKillType < KILLED_TABLE_ROWS; ubKillType++ )
|
|
{
|
|
// an exclusive OR operator, how often do ya see that, huh? :-)
|
|
if ( ( ubEnemyRank == ENEMY_RANK_PERCENT ) ^ ( ubKillType == ENEMIES_KILLED_PERCENT ) )
|
|
{
|
|
wcscpy( wPrintSpec, L"%3d%%%%" );
|
|
}
|
|
else
|
|
if ( ( ubEnemyRank == ENEMY_RANK_PERCENT ) && ( ubKillType == ENEMIES_KILLED_PERCENT ) )
|
|
{
|
|
wcscpy( wPrintSpec, L"" );
|
|
}
|
|
else
|
|
{
|
|
wcscpy( wPrintSpec, L"%4d" );
|
|
}
|
|
|
|
swprintf( wTempString, wPrintSpec, usEnemiesKilledTable[ ubEnemyRank ][ ubKillType ] );
|
|
DrawTextToScreen( wTempString, ( UINT16 ) ( usX + ( KILLED_TABLE_X_GAP * ubEnemyRank ) ), ( UINT16 ) ( usY + ( KILLED_TABLE_Y_GAP * ubKillType ) ), KILLED_TABLE_X_GAP, FONT10ARIAL, FONT_YELLOW, 0, FALSE, RIGHT_JUSTIFIED );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
UINT8 ChooseEnemyIconColor( UINT8 ubAdmins, UINT8 ubTroops, UINT8 ubElites )
|
|
{
|
|
UINT8 ubIconColor;
|
|
|
|
// The colors are:
|
|
// Yellow Admins only
|
|
// Red Troops only
|
|
// Gray Elites only
|
|
// Orange Mixed, no elites (Admins + Troops)
|
|
// Burgundy Mixed, with elites (Elites + (Admins OR Troops))
|
|
|
|
Assert( ubAdmins || ubTroops || ubElites );
|
|
|
|
if ( ubElites )
|
|
{
|
|
if ( ubTroops || ubAdmins )
|
|
ubIconColor = ICON_COLOR_BURGUNDY;
|
|
else
|
|
ubIconColor = ICON_COLOR_GRAY;
|
|
}
|
|
else // no elites
|
|
{
|
|
if ( ubTroops )
|
|
{
|
|
if ( ubAdmins )
|
|
ubIconColor = ICON_COLOR_ORANGE;
|
|
else
|
|
ubIconColor = ICON_COLOR_RED;
|
|
}
|
|
else // admins only
|
|
{
|
|
ubIconColor = ICON_COLOR_YELLOW;
|
|
}
|
|
}
|
|
|
|
return ( ubIconColor );
|
|
}
|
|
|
|
|
|
void BlitGroupIcon( UINT8 ubIconType, UINT8 ubIconColor, UINT32 uiX, UINT32 uiY, HVOBJECT hVObject )
|
|
{
|
|
UINT8 ubObjectIndex;
|
|
|
|
Assert( ubIconType < NUM_ICON_TYPES );
|
|
Assert( ubIconColor < NUM_ICON_COLORS );
|
|
|
|
ubObjectIndex = ( ubIconType * NUM_ICON_COLORS ) + ubIconColor;
|
|
BltVideoObject( FRAME_BUFFER, hVObject, ubObjectIndex, uiX, uiY, VO_BLT_SRCTRANSPARENCY, NULL );
|
|
}
|
|
|
|
|
|
|
|
void PrintDetailedEnemiesInSectorInfo( INT32 iScreenX, INT32 iScreenY, UINT8 ubSectorX, UINT8 ubSectorY )
|
|
{
|
|
SECTORINFO *pSector;
|
|
GROUP *pGroup;
|
|
INT32 iDesired, iSurplus;
|
|
UINT8 ubGroupCnt = 0;
|
|
UINT8 ubSectorID;
|
|
UINT16 wString[ 120 ];
|
|
UINT16 wSubString[ 120 ];
|
|
INT16 iGarrisonIndex;
|
|
INT16 iPatrolIndex;
|
|
WAYPOINT *pFinalWaypoint;
|
|
|
|
|
|
pSector = &SectorInfo[ SECTOR( ubSectorX, ubSectorY ) ];
|
|
|
|
// handle garrisoned enemies
|
|
if( pSector->ubGarrisonID != NO_GARRISON )
|
|
{
|
|
iDesired = gArmyComp[ gGarrisonGroup[ pSector->ubGarrisonID ].ubComposition ].bDesiredPopulation;
|
|
iSurplus = pSector->ubNumTroops + pSector->ubNumAdmins + pSector->ubNumElites - iDesired;
|
|
SetFontForeground( FONT_WHITE );
|
|
|
|
swprintf( wString, L"Garrison #%d: %d desired, ", pSector->ubGarrisonID, iDesired );
|
|
|
|
if( iSurplus >= 0 )
|
|
{
|
|
swprintf( wSubString, L"%d surplus troops", iSurplus );
|
|
wcscat( wString, wSubString );
|
|
}
|
|
else
|
|
{
|
|
swprintf( wSubString, L"%d reinforcements requested", -iSurplus );
|
|
wcscat( wString, wSubString );
|
|
}
|
|
mprintf( iScreenX, iScreenY, wString );
|
|
iScreenY += 10;
|
|
|
|
if( gGarrisonGroup[ pSector->ubGarrisonID ].ubPendingGroupID )
|
|
{
|
|
pGroup = GetGroup( gGarrisonGroup[ pSector->ubGarrisonID ].ubPendingGroupID );
|
|
if( pGroup )
|
|
{
|
|
mprintf( iScreenX, iScreenY, L"%d reinforcements on route from group %d in %c%d", pGroup->ubGroupSize, pGroup->ubGroupID,
|
|
pGroup->ubSectorY + 'A' - 1, pGroup->ubSectorX );
|
|
}
|
|
else
|
|
{ //ERROR! Should be a valid group...
|
|
}
|
|
}
|
|
else
|
|
{
|
|
mprintf( iScreenX, iScreenY, L"No pending reinforcements for this sector." );
|
|
}
|
|
iScreenY += 10;
|
|
}
|
|
else
|
|
{
|
|
SetFontForeground( FONT_GRAY2 );
|
|
mprintf( iScreenX, iScreenY, L"No garrison information for this sector." );
|
|
iScreenY += 10;
|
|
}
|
|
|
|
|
|
// handle mobile enemies anchored in this sector
|
|
pGroup = gpGroupList;
|
|
while( pGroup )
|
|
{
|
|
if( !pGroup->fPlayer && !pGroup->fVehicle )
|
|
{
|
|
if ( ( pGroup->ubSectorX == ubSectorX ) && ( pGroup->ubSectorY == ubSectorY ) )
|
|
{
|
|
Assert( pGroup->pEnemyGroup->ubIntention < NUM_ENEMY_INTENTIONS );
|
|
|
|
swprintf( wString, L"Group %c: %s", 'A' + ubGroupCnt, gwGroupTypeString[ pGroup->pEnemyGroup->ubIntention ] );
|
|
|
|
switch ( pGroup->pEnemyGroup->ubIntention )
|
|
{
|
|
case ASSAULT:
|
|
case PURSUIT:
|
|
iGarrisonIndex = FindGarrisonIndexForGroupIDPending( pGroup->ubGroupID );
|
|
if ( iGarrisonIndex != -1 )
|
|
{
|
|
ubSectorID = gGarrisonGroup[ iGarrisonIndex ].ubSectorID;
|
|
swprintf( wSubString, L", target sector %c%d", SECTORY( ubSectorID ) + 'A' - 1, SECTORX( ubSectorID ) );
|
|
}
|
|
else
|
|
{
|
|
pFinalWaypoint = GetFinalWaypoint( pGroup );
|
|
if( pFinalWaypoint )
|
|
{
|
|
if( pFinalWaypoint->x == 3 && pFinalWaypoint->y == 16 )
|
|
{
|
|
swprintf( wSubString, L" - group returning to pool.");
|
|
}
|
|
else
|
|
{
|
|
swprintf( wSubString, L" - moving to %c%d", pFinalWaypoint->y + 'A' - 1, pFinalWaypoint->x );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
swprintf( wSubString, L" - can't determine target sector" );
|
|
}
|
|
}
|
|
wcscat( wString, wSubString );
|
|
break;
|
|
case REINFORCEMENTS:
|
|
case STAGING:
|
|
// check if it's reinforcing a garrison
|
|
iGarrisonIndex = FindGarrisonIndexForGroupIDPending( pGroup->ubGroupID );
|
|
if ( iGarrisonIndex != -1 )
|
|
{
|
|
ubSectorID = gGarrisonGroup[ iGarrisonIndex ].ubSectorID;
|
|
swprintf( wSubString, L", dest sector %c%d", SECTORY( ubSectorID ) + 'A' - 1, SECTORX( ubSectorID ) );
|
|
wcscat( wString, wSubString );
|
|
}
|
|
else // must be reinforcing a patrol
|
|
{
|
|
iPatrolIndex = FindPatrolGroupIndexForGroupIDPending( pGroup->ubGroupID );
|
|
if( iPatrolIndex != -1 )
|
|
{
|
|
pFinalWaypoint = GetFinalWaypoint( pGroup );
|
|
Assert( pFinalWaypoint );
|
|
|
|
swprintf( wSubString, L", Patrol #%d, dest sector %c%d", iPatrolIndex, pFinalWaypoint->y + 'A' - 1, pFinalWaypoint->x );
|
|
wcscat( wString, wSubString );
|
|
}
|
|
else
|
|
{
|
|
pFinalWaypoint = GetFinalWaypoint( pGroup );
|
|
if( pFinalWaypoint )
|
|
{
|
|
if( pFinalWaypoint->x == 3 && pFinalWaypoint->y == 16 )
|
|
{
|
|
swprintf( wSubString, L" - group returning to pool.");
|
|
}
|
|
else
|
|
{
|
|
swprintf( wSubString, L" - lost group moving to %c%d", pFinalWaypoint->y + 'A' - 1, pFinalWaypoint->x );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
swprintf( wSubString, L" (LOST GROUP!)" );
|
|
}
|
|
wcscat( wString, wSubString );
|
|
}
|
|
}
|
|
break;
|
|
case PATROL:
|
|
iPatrolIndex = FindPatrolGroupIndexForGroupID( pGroup->ubGroupID );
|
|
if( iPatrolIndex != -1 )
|
|
{
|
|
swprintf( wSubString, L"#%d, next sector %c%d", iPatrolIndex, pGroup->ubNextY + 'A' - 1, pGroup->ubNextX );
|
|
}
|
|
else
|
|
{
|
|
swprintf( wSubString, L"#err, FLOATING GROUP!" );
|
|
}
|
|
wcscat( wString, wSubString );
|
|
break;
|
|
}
|
|
|
|
mprintf( iScreenX, iScreenY, wString );
|
|
iScreenY += 10;
|
|
|
|
ubGroupCnt++;
|
|
|
|
// no room on screen to display info for more than 3 groups in one sector!
|
|
if ( ubGroupCnt >= 3 )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
pGroup = pGroup->next;
|
|
}
|
|
}
|
|
|
|
|
|
#endif |