mirror of
https://github.com/1dot13/source.git
synced 2026-07-22 13:40:22 +02:00
Added missing #includes Added LUA scripting and console Changed the way tracers are visualized, so they work more like real tracers instead of a light fountain Fixed signedness of many grid variables used in GetMouseMapPos calls Fixed enemy weapon choosing: Sometimes a mortar is chosen but later rejected, but the grenade class was not reset. Caused assertion failure Added checks so enemies don't try to chuck RPG grenades with their hands Now possible to shoot a someone in the head if he's in water Fixed InitSightArrays to also clear soldier interrupt duel points. This was causing an assertion failure elsewhere in the code because the interrupt list still had soldiers on it sometimes when this function was called. Soldiers are much less willing to forfeit their turn over an attempt to use more APs than they have Removed early setting of muzzle flash. This would allow enemies to get an interrupt before you even fired. Fixed item dropping by AI. If AI tried to drop something while standing it would cause deadlock Change to greatly speed up closing the sector inventory window in an unloaded sector Added conditional compile flag to always give robot weapon ready advantage, even for 360 degree sighting Check builddefines.h for the conditional flags. Of greatest interest might be LUA_CONSOLE. This will cause the game to bring up a command console when run. However this console is severely lacking in many areas. If anybody knows of an open-source terminal/console that could be used instead, it would be appreciated. The existing console does bad things when you try to close it, and since it counts as a separate app, it pauses the game while it has focus. LUA scripting is very limited, basically just proof of concept. There is one global variable, the Soldiers array. An array index gives you the soldier in that slot in the currently loaded sector. The soldier has a few things that can be accessed: name (short name); fullname (long name); grid (current grid #, can be changed); walkto(grid) (function to walk to another grid); runto(grid) (function to run to another grid) git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@924 3b4a5df2-a311-0410-b5c6-a8a6f20db521
2058 lines
65 KiB
C++
2058 lines
65 KiB
C++
//Strategic AI Viewer
|
|
|
|
#ifdef PRECOMPILEDHEADERS
|
|
#include "Strategic All.h"
|
|
#include "INIReader.h"
|
|
#else
|
|
#include "builddefines.h"
|
|
#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"
|
|
#include "Strategic AI.h"
|
|
#include "Campaign.h"
|
|
#include "Auto Resolve.h"
|
|
#include "Strategic Status.h"
|
|
#include "wordwrap.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;
|
|
|
|
|
|
extern void Ensure_RepairedGarrisonGroup( GARRISON_GROUP **ppGarrison, INT32 *pGarraySize );
|
|
|
|
|
|
|
|
CHAR16 gwGroupTypeString[ NUM_ENEMY_INTENTIONS ][ 20 ] =
|
|
{
|
|
L"RETREAT",
|
|
L"ASSAULT",
|
|
L"STAGING",
|
|
L"PATROL",
|
|
L"REINFORCE"
|
|
};
|
|
|
|
|
|
void StringFromValue( STR16 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;
|
|
CHAR16 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;
|
|
CHAR16 str[20];
|
|
INT32 iSector = 0;
|
|
UINT8 ubIconColor;
|
|
UINT8 ubGroupSize = 0;
|
|
|
|
|
|
SetFont( FONT10ARIAL );
|
|
SetFontShadow( FONT_NEARBLACK );
|
|
|
|
GetVideoObject( &hVObject, guiMapIconsID );
|
|
Ensure_RepairedGarrisonGroup( &gGarrisonGroup, &giGarrisonArraySize ); /* added NULL fix, 2007-03-03, Sgt. Kolja */
|
|
|
|
//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++ )
|
|
{
|
|
CHAR16 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
|
|
};
|
|
|
|
CHAR16 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
|
|
};
|
|
|
|
CHAR16 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;
|
|
CHAR16 wPrintSpec[ 10 ];
|
|
CHAR16 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
|
|
};
|
|
|
|
CHAR16 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;
|
|
CHAR16 wPrintSpec[ 10 ];
|
|
CHAR16 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;
|
|
CHAR16 wString[ 120 ];
|
|
CHAR16 wSubString[ 120 ];
|
|
INT16 iGarrisonIndex;
|
|
INT16 iPatrolIndex;
|
|
WAYPOINT *pFinalWaypoint;
|
|
|
|
|
|
pSector = &SectorInfo[ SECTOR( ubSectorX, ubSectorY ) ];
|
|
Ensure_RepairedGarrisonGroup( &gGarrisonGroup, &giGarrisonArraySize ); /* added NULL fix, 2007-03-03, Sgt. Kolja */
|
|
|
|
// 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 |