Files
source/Editor/Editor Taskbar Utils.cpp
T
Overhaul 7a27e7105d New attack busy system
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
2007-06-09 09:01:04 +00:00

999 lines
32 KiB
C++

// WANNE: EDITOR?
#ifdef PRECOMPILEDHEADERS
#include "Editor All.h"
#else
#include "builddefines.h"
#endif
#ifdef JA2EDITOR
#ifndef PRECOMPILEDHEADERS
#include <stdio.h>
#include "types.h"
#include "mousesystem.h"
#include "Button System.h"
#include "Font Control.h"
#include "Isometric Utils.h"
#include "WorldDat.h"
#include "Render Dirty.h"
#include "sysutil.h"
#include "wordwrap.h"
#include "environment.h"
#include "Interface Items.h"
#include "Soldier Find.h"
#include "World Items.h"
#include "Text.h"
#include "Overhead map.h"
#include "Cursor Modes.h"
#include "editscreen.h"
#include "EditorTerrain.h"
#include "Cursor Modes.h"
#include "EditorItems.h"
#include "EditorMercs.h"
#include "EditorBuildings.h"
#include "EditorMapInfo.h"
#include "EditorDefines.h"
#include "Editor Taskbar Utils.h"
#include "Editor Taskbar Creation.h"
#include "Editor Callback Prototypes.h"
#include "Editor Modes.h"
#include "Text Input.h"
#include "Item Statistics.h"
#include "Map Information.h"
#include "Sector Summary.h"
#include "Item Statistics.h"
#include "pits.h"
#include "Soldier Find.h"
#include "lighting.h"
#include "Keys.h"
#endif
void RenderEditorInfo();
extern ITEM_POOL *gpItemPool;
//editor icon storage vars
INT32 giEditMercDirectionIcons[2];
UINT32 guiMercInventoryPanel;
UINT32 guiOmertaMap;
UINT32 guiMercInvPanelBuffers[9];
UINT32 guiMercTempBuffer;
INT32 giEditMercImage[2];
UINT32 guiExclamation;
UINT32 guiKeyImage;
//editor Mouseregion storage vars
MOUSE_REGION TerrainTileButtonRegion[ NUM_TERRAIN_TILE_REGIONS ];
MOUSE_REGION ItemsRegion;
MOUSE_REGION MercRegion;
MOUSE_REGION EditorRegion;
void EnableEditorRegion( INT8 bRegionID )
{
switch( bRegionID )
{
case BASE_TERRAIN_TILE_REGION_ID:
case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8:
MSYS_EnableRegion( &TerrainTileButtonRegion[ bRegionID ] );
break;
case ITEM_REGION_ID:
MSYS_EnableRegion( &ItemsRegion );
break;
case MERC_REGION_ID:
MSYS_EnableRegion( &MercRegion );
break;
}
}
void DisableEditorRegion( INT8 bRegionID )
{
switch( bRegionID )
{
case BASE_TERRAIN_TILE_REGION_ID:
case 1: case 2: case 3: case 4: case 5: case 6: case 7:
MSYS_DisableRegion( &TerrainTileButtonRegion[ bRegionID ] );
break;
case ITEM_REGION_ID:
MSYS_DisableRegion( &ItemsRegion );
break;
case MERC_REGION_ID:
MSYS_DisableRegion( &MercRegion );
break;
}
}
void RemoveEditorRegions()
{
INT32 x;
MSYS_RemoveRegion( &EditorRegion );
for(x = BASE_TERRAIN_TILE_REGION_ID; x < NUM_TERRAIN_TILE_REGIONS; x++ )
{
MSYS_RemoveRegion( &TerrainTileButtonRegion[ x ] );
}
MSYS_RemoveRegion( &ItemsRegion );
MSYS_RemoveRegion( &MercRegion );
}
void InitEditorRegions()
{
INT32 x;
//By doing this, all of the buttons underneath are blanketed and can't be used anymore.
//Any new buttons will cover this up as well. Think of it as a barrier between the editor buttons,
//and the game's interface panel buttons and regions.
MSYS_DefineRegion( &EditorRegion, 0, SCREEN_HEIGHT - 120, SCREEN_WIDTH, SCREEN_HEIGHT, MSYS_PRIORITY_NORMAL, 0, MSYS_NO_CALLBACK, MSYS_NO_CALLBACK );
//Create the regions for the terrain tile selections
for( x = 0; x < NUM_TERRAIN_TILE_REGIONS; x++ )
{
MSYS_DefineRegion(&TerrainTileButtonRegion[x],(INT16)(iScreenWidthOffset + 261+x*42), 2 * iScreenHeightOffset + 369,(INT16)(iScreenWidthOffset + 303+x*42),2 * iScreenHeightOffset + 391,
MSYS_PRIORITY_NORMAL, 0, MSYS_NO_CALLBACK,(MOUSE_CALLBACK)TerrainTileButtonRegionCallback);
MSYS_SetRegionUserData( &TerrainTileButtonRegion[x], 0, x );
MSYS_DisableRegion( &TerrainTileButtonRegion[x] );
}
gfShowTerrainTileButtons=FALSE;
//Create the region for the items selection window.
MSYS_DefineRegion( &ItemsRegion, iScreenWidthOffset + 100, 2 * iScreenHeightOffset + 360, iScreenWidthOffset + 540, 2 * iScreenHeightOffset + 440, MSYS_PRIORITY_NORMAL, 0,
(MOUSE_CALLBACK)MouseMovedInItemsRegion, (MOUSE_CALLBACK)MouseClickedInItemsRegion );
MSYS_DisableRegion( &ItemsRegion );
//Create the region for the merc inventory panel.
MSYS_DefineRegion( &MercRegion, iScreenWidthOffset + 175, 2 * iScreenHeightOffset + 361, iScreenWidthOffset + 450, 2 * iScreenHeightOffset + 460, MSYS_PRIORITY_NORMAL, 0,
MouseMovedInMercRegion, MouseClickedInMercRegion );
MSYS_DisableRegion( &MercRegion );
}
void LoadEditorImages()
{
VOBJECT_DESC VObjectDesc;
//Set up the merc inventory panel
VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE;
sprintf( VObjectDesc.ImageFile, "EDITOR\\InvPanel.sti" );
if( !AddVideoObject( &VObjectDesc, &guiMercInventoryPanel ) )
AssertMsg( 0, "Failed to load data\\editor\\InvPanel.sti" );
//Set up small omerta map
sprintf( VObjectDesc.ImageFile, "EDITOR\\omerta.sti" );
if( !AddVideoObject( &VObjectDesc, &guiOmertaMap ) )
AssertMsg( 0, "Failed to load data\\editor\\omerta.sti" );
//Set up the merc directional buttons.
giEditMercDirectionIcons[0] = LoadGenericButtonIcon("EDITOR//arrowsoff.sti");
giEditMercDirectionIcons[1] = LoadGenericButtonIcon("EDITOR//arrowson.sti");
giEditMercImage[0] = LoadButtonImage("EDITOR\\leftarrow.sti",0,1,2,3,4);
giEditMercImage[1] = LoadButtonImage("EDITOR\\rightarrow.sti",0,1,2,3,4);
sprintf( VObjectDesc.ImageFile, "EDITOR\\Exclamation.sti" );
if( !AddVideoObject( &VObjectDesc, &guiExclamation ) )
AssertMsg( 0, "Failed to load data\\editor\\Exclamation.sti" );
sprintf( VObjectDesc.ImageFile, "EDITOR\\KeyImage.sti" );
if( !AddVideoObject( &VObjectDesc, &guiKeyImage ) )
AssertMsg( 0, "Failed to load data\\editor\\KeyImage.sti" );
}
void DeleteEditorImages()
{
//The merc inventory panel
DeleteVideoObjectFromIndex( guiMercInventoryPanel );
DeleteVideoObjectFromIndex( guiOmertaMap );
//The merc directional buttons
UnloadGenericButtonIcon( (INT16)giEditMercDirectionIcons[0] );
UnloadGenericButtonIcon( (INT16)giEditMercDirectionIcons[1] );
UnloadButtonImage( giEditMercImage[0] );
UnloadButtonImage( giEditMercImage[1] );
}
void CreateEditorBuffers()
{
INT32 i;
VSURFACE_DESC vs_desc;
UINT16 usUselessWidth, usUselessHeight;
UINT8 ubBitDepth;
//create buffer for the transition slot for merc items. This slot contains the newly
//selected item graphic in it's inventory size version. This buffer is then scaled down
//into the associated merc inventory panel slot buffer which is approximately 20% smaller.
GetCurrentVideoSettings( &usUselessWidth, &usUselessHeight, &ubBitDepth );
vs_desc.fCreateFlags = VSURFACE_CREATE_DEFAULT | VSURFACE_SYSTEM_MEM_USAGE;
vs_desc.usWidth = 60;
vs_desc.usHeight = 25;
vs_desc.ubBitDepth = ubBitDepth;
if( !AddVideoSurface( &vs_desc, &guiMercTempBuffer ) )
AssertMsg( 0, "Failed to allocate memory for merc tempitem buffer." );
//create the nine buffers for the merc's inventory slots.
vs_desc.usHeight = MERCINV_SLOT_HEIGHT;
for( i = 0; i < 9; i++ )
{
vs_desc.usWidth = i<3 ? MERCINV_SMSLOT_WIDTH : MERCINV_LGSLOT_WIDTH;
if( !AddVideoSurface( &vs_desc, &guiMercInvPanelBuffers[i] ) )
AssertMsg( 0, "Failed to allocate memory for merc item[] buffers." );
}
}
void DeleteEditorBuffers()
{
INT32 i;
DeleteVideoSurfaceFromIndex( guiMercTempBuffer );
for( i = 0; i < 9; i++ )
{
DeleteVideoSurfaceFromIndex( guiMercInvPanelBuffers[ i ] );
}
}
void ShowEditorToolbar( INT32 iNewTaskMode )
{
switch( iNewTaskMode )
{
case TASK_TERRAIN: ShowEditorButtons( FIRST_TERRAIN_BUTTON, LAST_TERRAIN_BUTTON ); break;
case TASK_BUILDINGS: ShowEditorButtons( FIRST_BUILDINGS_BUTTON, LAST_BUILDINGS_BUTTON ); break;
case TASK_ITEMS: ShowEditorButtons( FIRST_ITEMS_BUTTON, LAST_ITEMS_BUTTON ); break;
case TASK_MERCS: ShowEditorButtons( FIRST_MERCS_TEAMMODE_BUTTON, LAST_MERCS_TEAMMODE_BUTTON ); break;
case TASK_MAPINFO: ShowEditorButtons( FIRST_MAPINFO_BUTTON, LAST_MAPINFO_BUTTON ); break;
case TASK_OPTIONS: ShowEditorButtons( FIRST_OPTIONS_BUTTON, LAST_OPTIONS_BUTTON ); break;
default: return;
}
}
void HideEditorToolbar( INT32 iOldTaskMode )
{
INT32 i, iStart, iEnd;
switch( iOldTaskMode )
{
case TASK_TERRAIN: iStart = FIRST_TERRAIN_BUTTON; iEnd = LAST_TERRAIN_BUTTON; break;
case TASK_BUILDINGS: iStart = FIRST_BUILDINGS_BUTTON; iEnd = LAST_BUILDINGS_BUTTON; break;
case TASK_ITEMS: iStart = FIRST_ITEMS_BUTTON; iEnd = LAST_ITEMS_BUTTON; break;
case TASK_MERCS: iStart = FIRST_MERCS_BUTTON; iEnd = LAST_MERCS_BUTTON; break;
case TASK_MAPINFO: iStart = FIRST_MAPINFO_BUTTON; iEnd = LAST_MAPINFO_BUTTON; break;
case TASK_OPTIONS: iStart = FIRST_OPTIONS_BUTTON; iEnd = LAST_OPTIONS_BUTTON; break;
default: return;
}
for( i = iStart; i <= iEnd; i++ )
{
HideButton( iEditorButton[ i ] );
UnclickEditorButton( i );
}
}
void CreateEditorTaskbar()
{
InitEditorRegions();
LoadEditorImages();
CreateEditorBuffers();
CreateEditorTaskbarInternal();
HideItemStatsPanel();
}
void DeleteEditorTaskbar()
{
INT32 x;
iOldTaskMode = iCurrentTaskbar;
for( x = 0; x < NUMBER_EDITOR_BUTTONS; x++ )
RemoveButton( iEditorButton[ x ] );
RemoveEditorRegions();
DeleteEditorImages();
DeleteEditorBuffers();
}
void DoTaskbar(void)
{
if(!iTaskMode || iTaskMode == iCurrentTaskbar )
{
return;
}
gfRenderTaskbar = TRUE;
HideEditorToolbar( iCurrentTaskbar );
//Special code when exiting previous editor tab
switch( iCurrentTaskbar )
{
case TASK_TERRAIN:
UnclickEditorButton( TAB_TERRAIN );
HideTerrainTileButtons();
break;
case TASK_BUILDINGS:
UnclickEditorButton( TAB_BUILDINGS );
KillTextInputMode();
break;
case TASK_ITEMS:
UnclickEditorButton( TAB_ITEMS );
HideItemStatsPanel();
if( eInfo.fActive )
ClearEditorItemsInfo();
gfShowPits = FALSE;
RemoveAllPits();
break;
case TASK_MERCS:
UnclickEditorButton( TAB_MERCS );
IndicateSelectedMerc( SELECT_NO_MERC );
SetMercEditingMode( MERC_NOMODE );
break;
case TASK_MAPINFO:
UnclickEditorButton( TAB_MAPINFO );
ExtractAndUpdateMapInfo();
KillTextInputMode();
HideExitGrids();
break;
case TASK_OPTIONS:
UnclickEditorButton( TAB_OPTIONS );
break;
}
//Setup the new tab mode
iCurrentTaskbar = iTaskMode;
ShowEditorToolbar( iTaskMode );
iTaskMode = TASK_NONE;
//Special code when entering a new editor tab
switch( iCurrentTaskbar )
{
case TASK_MERCS:
ClickEditorButton( TAB_MERCS );
ClickEditorButton( MERCS_ENEMY);
iDrawMode = DRAW_MODE_ENEMY;
SetMercEditingMode( MERC_TEAMMODE );
fBuildingShowRoofs = FALSE;
UpdateRoofsView();
break;
case TASK_TERRAIN:
ClickEditorButton( TAB_TERRAIN );
ShowTerrainTileButtons();
SetEditorTerrainTaskbarMode( TERRAIN_FGROUND_TEXTURES );
break;
case TASK_BUILDINGS:
ClickEditorButton( TAB_BUILDINGS );
if(fBuildingShowRoofs)
ClickEditorButton( BUILDING_TOGGLE_ROOF_VIEW );
if(fBuildingShowWalls)
ClickEditorButton( BUILDING_TOGGLE_WALL_VIEW );
if(fBuildingShowRoomInfo)
ClickEditorButton( BUILDING_TOGGLE_INFO_VIEW );
if( gfCaves )
{
ClickEditorButton( BUILDING_CAVE_DRAWING );
iDrawMode = DRAW_MODE_CAVES;
}
else
{
ClickEditorButton( BUILDING_NEW_ROOM );
iDrawMode = DRAW_MODE_ROOM;
}
TerrainTileDrawMode = TERRAIN_TILES_BRETS_STRANGEMODE;
SetEditorSmoothingMode( gMapInformation.ubEditorSmoothingType );
gusSelectionType = gusSavedBuildingSelectionType;
SetupTextInputForBuildings();
break;
case TASK_ITEMS:
SetFont( FONT10ARIAL );
SetFontForeground( FONT_YELLOW );
ClickEditorButton( TAB_ITEMS );
ClickEditorButton( ITEMS_WEAPONS + eInfo.uiItemType - TBAR_MODE_ITEM_WEAPONS );
InitEditorItemsInfo( eInfo.uiItemType );
ShowItemStatsPanel();
gfShowPits = TRUE;
AddAllPits();
iDrawMode = DRAW_MODE_PLACE_ITEM;
break;
case TASK_MAPINFO:
ClickEditorButton( TAB_MAPINFO );
if ( gfFakeLights )
ClickEditorButton( MAPINFO_TOGGLE_FAKE_LIGHTS );
ClickEditorButton( MAPINFO_ADD_LIGHT1_SOURCE );
iDrawMode = DRAW_MODE_LIGHT;
TerrainTileDrawMode = TERRAIN_TILES_BRETS_STRANGEMODE;
SetupTextInputForMapInfo();
break;
case TASK_OPTIONS:
ClickEditorButton( TAB_OPTIONS );
TerrainTileDrawMode = TERRAIN_TILES_NODRAW;
break;
}
}
//Disables the task bar, but leaves it on screen. Used when a selection window is up.
void DisableEditorTaskbar(void)
{
INT32 x;
for(x = 0; x < NUMBER_EDITOR_BUTTONS; x++ )
DisableButton( iEditorButton[ x ] );
}
void EnableEditorTaskbar(void)
{
INT32 x;
for(x = 0; x < NUMBER_EDITOR_BUTTONS; x++ )
EnableButton( iEditorButton[ x ] );
//Keep permanent buttons disabled.
DisableButton( iEditorButton[ MERCS_1 ] );
DisableButton( iEditorButton[ MAPINFO_LIGHT_PANEL ] );
DisableButton( iEditorButton[ MAPINFO_RADIO_PANEL ] );
DisableButton( iEditorButton[ ITEMSTATS_PANEL ] );
DisableButton( iEditorButton[ MERCS_PLAYERTOGGLE ] );
DisableButton( iEditorButton[ MERCS_PLAYER ] );
if( iCurrentTaskbar == TASK_ITEMS )
DetermineItemsScrolling();
}
//A specialized mprint function that'll restore the editor panel underneath the
//string before rendering the string. This is obviously only useful for drawing text
//in the editor taskbar.
void mprintfEditor(INT16 x, INT16 y, STR16 pFontString, ...)
{
va_list argptr;
CHAR16 string[512];
UINT16 uiStringLength, uiStringHeight;
Assert( pFontString != NULL );
va_start( argptr, pFontString ); // Set up variable argument pointer
vswprintf( string, pFontString, argptr); // process gprintf string (get output str)
va_end( argptr );
uiStringLength = StringPixLength( string, FontDefault );
uiStringHeight = GetFontHeight( FontDefault );
ClearTaskbarRegion( x, y, (INT16)(x+uiStringLength), (INT16)(y+uiStringHeight) );
mprintf( x, y, string );
}
// WANNE: EDITOR continue
void ClearTaskbarRegion( INT16 sLeft, INT16 sTop, INT16 sRight, INT16 sBottom )
{
ColorFillVideoSurfaceArea( ButtonDestBuffer, sLeft, sTop, sRight, sBottom, gusEditorTaskbarColor );
if( !sLeft )
{
ColorFillVideoSurfaceArea( ButtonDestBuffer, 0, sTop, 1, sBottom, gusEditorTaskbarHiColor );
sLeft++;
}
if( sTop == (SCREEN_HEIGHT - 120) )
{
ColorFillVideoSurfaceArea( ButtonDestBuffer, sLeft, 2 * iScreenHeightOffset + 360, sRight, 2 * iScreenHeightOffset + 361, gusEditorTaskbarHiColor );
sTop++;
}
if( sBottom == SCREEN_HEIGHT )
ColorFillVideoSurfaceArea( ButtonDestBuffer, sLeft, 2 * iScreenHeightOffset + 479, sRight, 2 * iScreenHeightOffset + 480, gusEditorTaskbarLoColor );
if( sRight == SCREEN_WIDTH )
ColorFillVideoSurfaceArea( ButtonDestBuffer, iScreenWidthOffset + 639, sTop, iScreenWidthOffset + 640, sBottom, gusEditorTaskbarLoColor );
InvalidateRegion( sLeft, sTop, sRight, sBottom );
}
//Kris:
//This is a new function which duplicates the older "yellow info boxes" that
//are common throughout the editor. This draws the yellow box with the indentation
//look.
void DrawEditorInfoBox( STR16 str, UINT32 uiFont, UINT16 x, UINT16 y, UINT16 w, UINT16 h )
{
UINT16 usFillColorDark, usFillColorLight, usFillColorBack;
UINT16 x2, y2;
UINT16 usStrWidth;
x2 = x + w;
y2 = y + h;
usFillColorDark = Get16BPPColor(FROMRGB(24, 61, 81));
usFillColorLight = Get16BPPColor(FROMRGB(136, 138, 135));
usFillColorBack = Get16BPPColor(FROMRGB(250, 240, 188));
ColorFillVideoSurfaceArea(ButtonDestBuffer, x, y, x2, y2, usFillColorDark);
ColorFillVideoSurfaceArea(ButtonDestBuffer, x + 1, y + 1, x2, y2, usFillColorLight);
ColorFillVideoSurfaceArea(ButtonDestBuffer, x + 1, y + 1, x2 - 1, y2 - 1, usFillColorBack);
usStrWidth = StringPixLength( str, uiFont );
if( usStrWidth > w )
{ //the string is too long, so use the wrapped method
y += 1;
DisplayWrappedString( x, y, w, 2, uiFont, FONT_BLACK, str, FONT_BLACK, TRUE, CENTER_JUSTIFIED );
return;
}
//center the string vertically and horizontally.
SetFont( uiFont );
SetFontForeground( FONT_BLACK );
SetFontShadow( FONT_BLACK );
x += (w - (UINT16)StringPixLength( str, uiFont )) / 2;
y += (h - (UINT16)GetFontHeight( uiFont)) / 2;
mprintf( x, y, L"%s", str );
InvalidateRegion( x, y, x2, y2 );
}
void ClickEditorButton( INT32 iEditorButtonID )
{
GUI_BUTTON *butn;
if ( iEditorButtonID < 0 || iEditorButtonID >= NUMBER_EDITOR_BUTTONS )
return;
if ( iEditorButton[ iEditorButtonID ] != -1 )
{
butn = ButtonList[ iEditorButton[ iEditorButtonID ] ];
if( butn )
butn->uiFlags |= BUTTON_CLICKED_ON;
}
}
void UnclickEditorButton( INT32 iEditorButtonID )
{
GUI_BUTTON *butn;
if ( iEditorButtonID < 0 || iEditorButtonID >= NUMBER_EDITOR_BUTTONS )
return;
if ( iEditorButton[ iEditorButtonID ] != -1 )
{
butn = ButtonList[ iEditorButton[ iEditorButtonID ] ];
if( butn )
butn->uiFlags &= (~BUTTON_CLICKED_ON);
}
}
void HideEditorButton( INT32 iEditorButtonID )
{
HideButton( iEditorButton[ iEditorButtonID ] );
}
void ShowEditorButton( INT32 iEditorButtonID )
{
ShowButton( iEditorButton[ iEditorButtonID ] );
}
void DisableEditorButton( INT32 iEditorButtonID )
{
DisableButton( iEditorButton[ iEditorButtonID ] );
}
void EnableEditorButton( INT32 iEditorButtonID )
{
EnableButton( iEditorButton[ iEditorButtonID ] );
}
void ClickEditorButtons( INT32 iFirstEditorButtonID, INT32 iLastEditorButtonID )
{
INT32 i;
GUI_BUTTON *b;
for( i = iFirstEditorButtonID; i <= iLastEditorButtonID; i++ )
{
Assert( iEditorButton[ i ] != -1 );
b = ButtonList[ iEditorButton[ i ] ];
Assert( b );
b->uiFlags |= BUTTON_CLICKED_ON;
}
}
void UnclickEditorButtons( INT32 iFirstEditorButtonID, INT32 iLastEditorButtonID )
{
INT32 i;
GUI_BUTTON *b;
for( i = iFirstEditorButtonID; i <= iLastEditorButtonID; i++ )
{
Assert( iEditorButton[ i ] != -1 );
b = ButtonList[ iEditorButton[ i ] ];
Assert( b );
b->uiFlags &= (~BUTTON_CLICKED_ON);
}
}
void HideEditorButtons( INT32 iFirstEditorButtonID, INT32 iLastEditorButtonID )
{
INT32 i;
for( i = iFirstEditorButtonID; i <= iLastEditorButtonID; i++ )
HideButton( iEditorButton[ i ] );
}
void ShowEditorButtons( INT32 iFirstEditorButtonID, INT32 iLastEditorButtonID )
{
INT32 i;
for( i = iFirstEditorButtonID; i <= iLastEditorButtonID; i++ )
ShowButton( iEditorButton[ i ] );
}
void DisableEditorButtons( INT32 iFirstEditorButtonID, INT32 iLastEditorButtonID )
{
INT32 i;
for( i = iFirstEditorButtonID; i <= iLastEditorButtonID; i++ )
DisableButton( iEditorButton[ i ] );
}
void EnableEditorButtons( INT32 iFirstEditorButtonID, INT32 iLastEditorButtonID )
{
INT32 i;
for( i = iFirstEditorButtonID; i <= iLastEditorButtonID; i++ )
EnableButton( iEditorButton[ i ] );
}
void RenderMapEntryPointsAndLights()
{
INT16 sGridNo;
INT16 sScreenX, sScreenY;
INT32 i;
if( gfSummaryWindowActive )
return;
SetFont( FONT10ARIAL );
SetFontForeground( FONT_YELLOW );
SetFontShadow( FONT_NEARBLACK );
sGridNo = gMapInformation.sNorthGridNo;
if( sGridNo != -1 )
{
GetGridNoScreenPos( sGridNo, 0, &sScreenX, &sScreenY );
if( sScreenY >= (- 20) && sScreenY < (2 * iScreenHeightOffset + 340) && sScreenX >= (- 40) && sScreenX < SCREEN_WIDTH )
{
DisplayWrappedString( sScreenX, (INT16)(sScreenY-5), 40, 2, FONT10ARIAL, FONT_YELLOW, L"North Entry Point", FONT_BLACK, TRUE, CENTER_JUSTIFIED );
}
}
sGridNo = gMapInformation.sWestGridNo;
if( sGridNo != -1 )
{
GetGridNoScreenPos( sGridNo, 0, &sScreenX, &sScreenY );
if( sScreenY >= (- 20) && sScreenY < (2 * iScreenHeightOffset + 340) && sScreenX >= (- 40) && sScreenX < SCREEN_WIDTH )
{
DisplayWrappedString( sScreenX, (INT16)(sScreenY-5), 40, 2, FONT10ARIAL, FONT_YELLOW, L"West Entry Point", FONT_BLACK, TRUE, CENTER_JUSTIFIED );
}
}
sGridNo = gMapInformation.sEastGridNo;
if( sGridNo != -1 )
{
GetGridNoScreenPos( sGridNo, 0, &sScreenX, &sScreenY );
if( sScreenY >= (- 20) && sScreenY < (2 * iScreenHeightOffset + 340) && sScreenX >= (- 40) && sScreenX < SCREEN_WIDTH )
{
DisplayWrappedString( sScreenX, (INT16)(sScreenY-5), 40, 2, FONT10ARIAL, FONT_YELLOW, L"East Entry Point", FONT_BLACK, TRUE, CENTER_JUSTIFIED );
}
}
sGridNo = gMapInformation.sSouthGridNo;
if( sGridNo != -1 )
{
GetGridNoScreenPos( sGridNo, 0, &sScreenX, &sScreenY );
if( sScreenY >= ( - 20) && sScreenY < (2 * iScreenHeightOffset + 340) && sScreenX >= (- 40) && sScreenX < SCREEN_WIDTH )
{
DisplayWrappedString( sScreenX, (INT16)(sScreenY-5), 40, 2, FONT10ARIAL, FONT_YELLOW, L"South Entry Point", FONT_BLACK, TRUE, CENTER_JUSTIFIED );
}
}
sGridNo = gMapInformation.sCenterGridNo;
if( sGridNo != -1 )
{
GetGridNoScreenPos( sGridNo, 0, &sScreenX, &sScreenY );
if( sScreenY >= (- 20) && sScreenY < (2 * iScreenHeightOffset + 340) && sScreenX >= (- 40) && sScreenX < SCREEN_WIDTH )
{
DisplayWrappedString( sScreenX, (INT16)(sScreenY-5), 40, 2, FONT10ARIAL, FONT_YELLOW, L"Center Entry Point", FONT_BLACK, TRUE, CENTER_JUSTIFIED );
}
}
sGridNo = gMapInformation.sIsolatedGridNo;
if( sGridNo != -1 )
{
GetGridNoScreenPos( sGridNo, 0, &sScreenX, &sScreenY );
if( sScreenY >= (- 20) && sScreenY < (2 * iScreenHeightOffset + 340) && sScreenX >= (- 40) && sScreenX < SCREEN_WIDTH )
{
DisplayWrappedString( sScreenX, (INT16)(sScreenY-5), 40, 2, FONT10ARIAL, FONT_YELLOW, L"Isolated Entry Point", FONT_BLACK, TRUE, CENTER_JUSTIFIED );
}
}
//Do the lights now.
for( i = 0; i < MAX_LIGHT_SPRITES; i++ )
{
if( LightSprites[ i ].uiFlags & LIGHT_SPR_ACTIVE )
{
sGridNo = LightSprites[ i ].iY * WORLD_COLS + LightSprites[ i ].iX;
GetGridNoScreenPos( sGridNo, 0, &sScreenX, &sScreenY );
if( sScreenY >= (- 50) && sScreenY < (2 * iScreenHeightOffset + 300) && sScreenX >= (- 40) && sScreenX < SCREEN_WIDTH )
{
if( LightSprites[ i ].uiFlags & LIGHT_PRIMETIME )
DisplayWrappedString( sScreenX, (INT16)(sScreenY-5), 50, 2, FONT10ARIAL, FONT_ORANGE, L"Prime", FONT_BLACK, TRUE, CENTER_JUSTIFIED );
else if( LightSprites[ i ].uiFlags & LIGHT_NIGHTTIME )
DisplayWrappedString( sScreenX, (INT16)(sScreenY-5), 50, 2, FONT10ARIAL, FONT_RED, L"Night", FONT_BLACK, TRUE, CENTER_JUSTIFIED );
else
DisplayWrappedString( sScreenX, (INT16)(sScreenY-5), 50, 2, FONT10ARIAL, FONT_YELLOW, L"24Hour", FONT_BLACK, TRUE, CENTER_JUSTIFIED );
}
}
}
}
void BuildTriggerName( OBJECTTYPE *pItem, STR16 szItemName )
{
if( pItem->usItem == SWITCH )
{
if( pItem->bFrequency == PANIC_FREQUENCY )
swprintf( szItemName, L"Panic Trigger1" );
else if( pItem->bFrequency == PANIC_FREQUENCY_2 )
swprintf( szItemName, L"Panic Trigger2" );
else if( pItem->bFrequency == PANIC_FREQUENCY_3 )
swprintf( szItemName, L"Panic Trigger3" );
else
swprintf( szItemName, L"Trigger%d", pItem->bFrequency - 50 );
}
else
{ //action item
if( pItem->bDetonatorType == BOMB_PRESSURE )
swprintf( szItemName, L"Pressure Action" );
else if( pItem->bFrequency == PANIC_FREQUENCY )
swprintf( szItemName, L"Panic Action1" );
else if( pItem->bFrequency == PANIC_FREQUENCY_2 )
swprintf( szItemName, L"Panic Action2" );
else if( pItem->bFrequency == PANIC_FREQUENCY_3 )
swprintf( szItemName, L"Panic Action3" );
else
swprintf( szItemName, L"Action%d", pItem->bFrequency - 50 );
}
}
// WANNE: EDITOR?
void RenderDoorLockInfo()
{
INT16 i, xp, yp;
INT16 sScreenX, sScreenY;
CHAR16 str[ 50 ];
for( i = 0; i < gubNumDoors; i++ )
{
GetGridNoScreenPos( DoorTable[ i ].sGridNo, 0, &sScreenX, &sScreenY );
if( sScreenY > (2 * iScreenHeightOffset + 390) )
continue;
if( DoorTable[ i ].ubLockID != 255 )
swprintf( str, L"%S", LockTable[ DoorTable[ i ].ubLockID ].ubEditorName );
else
swprintf( str, L"No Lock ID" );
xp = sScreenX - 10;
yp = sScreenY - 40;
DisplayWrappedString( xp, yp, 60, 2, FONT10ARIAL, FONT_LTKHAKI, str, FONT_BLACK, TRUE, CENTER_JUSTIFIED );
if( DoorTable[ i ].ubTrapID )
{
SetFont( FONT10ARIAL );
SetFontForeground( FONT_RED );
SetFontShadow( FONT_NEARBLACK );
switch( DoorTable[ i ].ubTrapID )
{
case EXPLOSION:
swprintf( str, L"Explosion Trap" );
break;
case ELECTRIC:
swprintf( str, L"Electric Trap" );
break;
case SIREN:
swprintf( str, L"Siren Trap" );
break;
case SILENT_ALARM:
swprintf( str, L"Silent Alarm" );
break;
case SUPER_ELECTRIC:
swprintf( str, L"Super Electric Trap" );
break;
}
xp = sScreenX + 20 - StringPixLength( str, FONT10ARIAL ) / 2;
yp = sScreenY;
mprintf( xp, yp, str );
swprintf( str, L"Trap Level %d", DoorTable[ i ].ubTrapLevel );
xp = sScreenX + 20 - StringPixLength( str, FONT10ARIAL ) / 2;
mprintf( xp, yp+10, str );
}
}
}
// WANNE: EDITOR?
void RenderSelectedItemBlownUp()
{
UINT32 uiVideoObjectIndex;
HVOBJECT hVObject;
INT16 sScreenX, sScreenY, xp, yp;
ITEM_POOL *pItemPool;
CHAR16 szItemName[ SIZE_ITEM_NAME ];
INT32 i;
INT16 sWidth, sHeight, sOffsetX, sOffsetY;
GetGridNoScreenPos( gsItemGridNo, 0, &sScreenX, &sScreenY );
if( sScreenY > (2 * iScreenHeightOffset + 340) )
return;
//Display the enlarged item graphic
uiVideoObjectIndex = GetInterfaceGraphicForItem( &Item[ gpItem->usItem ] );
GetVideoObject( &hVObject, uiVideoObjectIndex );
sWidth = hVObject->pETRLEObject[ Item[ gpItem->usItem ].ubGraphicNum ].usWidth;
sOffsetX = hVObject->pETRLEObject[ Item[ gpItem->usItem ].ubGraphicNum ].sOffsetX;
xp = sScreenX + (40 - sWidth - sOffsetX*2) / 2;
sHeight = hVObject->pETRLEObject[ Item[ gpItem->usItem ].ubGraphicNum ].usHeight;
sOffsetY = hVObject->pETRLEObject[ Item[ gpItem->usItem ].ubGraphicNum ].sOffsetY;
yp = sScreenY + (20 - sHeight - sOffsetY*2) / 2;
BltVideoObjectOutlineFromIndex( FRAME_BUFFER, uiVideoObjectIndex, Item[ gpItem->usItem ].ubGraphicNum, xp, yp, Get16BPPColor(FROMRGB(0, 140, 170)), TRUE );
//Display the item name above it
SetFont( FONT10ARIAL );
SetFontForeground( FONT_YELLOW );
SetFontShadow( FONT_NEARBLACK );
if( gpItem->usItem == ACTION_ITEM || gpItem->usItem == SWITCH )
{
BuildTriggerName( gpItem, szItemName );
}
else if( Item[ gpItem->usItem ].usItemClass == IC_KEY )
{
swprintf( szItemName, L"%S", LockTable[ gpItem->ubKeyID ].ubEditorName );
}
else
{
LoadItemInfo( gpItem->usItem, szItemName, NULL );
}
xp = sScreenX - (StringPixLength( szItemName, FONT10ARIAL ) - 40) / 2;
yp -= 10;
mprintf( xp, yp, szItemName );
if( gpItem->usItem == ACTION_ITEM )
{
STR16 pStr;
pStr = GetActionItemName( gpItem );
xp = sScreenX - (StringPixLength( pStr, FONT10ARIALBOLD ) - 40) / 2;
yp += 10;
SetFont( FONT10ARIALBOLD );
SetFontForeground( FONT_LTKHAKI );
mprintf( xp, yp, pStr );
SetFontForeground( FONT_YELLOW );
}
//Count the number of items in the current pool, and display that.
i = 0;
GetItemPool( gsItemGridNo, &pItemPool, 0 );
Assert( pItemPool );
while( pItemPool )
{
i++;
pItemPool = pItemPool->pNext;
}
xp = sScreenX;
yp = sScreenY + 10;
mprintf( xp, yp, L"%d", i );
//If the item is hidden, render a blinking H (just like DG)
if( gWorldItems[ gpItemPool->iItemIndex ].bVisible == HIDDEN_ITEM ||
gWorldItems[ gpItemPool->iItemIndex ].bVisible == BURIED )
{
SetFont( FONT10ARIALBOLD );
if( GetJA2Clock() % 1000 > 500 )
{
SetFontForeground( 249 );
}
mprintf( sScreenX + 16, sScreenY + 7, L"H" );
InvalidateRegion( sScreenX + 16, sScreenY + 7, sScreenX + 24, sScreenY + 27 );
}
}
void RenderEditorInfo( )
{
CHAR16 FPSText[ 50 ];
static INT32 iSpewWarning = 0;
UINT16 uiMapIndex;
SetFont( FONT12POINT1 );
SetFontForeground( FONT_BLACK );
SetFontBackground( FONT_BLACK );
//Display the mapindex position
if( GetMouseMapPos( &uiMapIndex ) )
swprintf( FPSText, L" (%d) ", uiMapIndex );
else
swprintf( FPSText, L" " );
mprintfEditor( (UINT16)(iScreenWidthOffset + 50-StringPixLength( FPSText, FONT12POINT1 )/2), 2 * iScreenHeightOffset + 463, FPSText );
switch( iCurrentTaskbar )
{
case TASK_OPTIONS:
if( !gfWorldLoaded || giCurrentTilesetID < 0 )
mprintf( iScreenWidthOffset + 260, 2 * iScreenHeightOffset + 445, L"No map currently loaded." );
else
mprintf( iScreenWidthOffset + 260, 2 * iScreenHeightOffset + 445, L"File: %S, Current Tileset: %s",
gubFilename, gTilesets[ giCurrentTilesetID ].zName );
break;
case TASK_TERRAIN:
// WANNE: EDITOR: comment this two lines, because we always get an exception here!
//if( gusSelectionType == LINESELECTION )
// swprintf( wszSelType[LINESELECTION], L"Width: %d", gusSelectionWidth );
DrawEditorInfoBox( wszSelType[gusSelectionType], FONT12POINT1, iScreenWidthOffset + 220, 2 * iScreenHeightOffset + 430, 60, 30 );
swprintf( FPSText, L"%d%%", gusSelectionDensity );
DrawEditorInfoBox( FPSText, FONT12POINT1, iScreenWidthOffset + 310, 2 * iScreenHeightOffset + 430, 40, 30 );
break;
case TASK_ITEMS:
RenderEditorItemsInfo();
UpdateItemStatsPanel();
break;
case TASK_BUILDINGS:
UpdateBuildingsInfo();
// WANNE: EDITOR: comment this two lines, because we always get an exception here!
//if( gusSelectionType == LINESELECTION )
// swprintf( wszSelType[LINESELECTION], L"%d", gusSelectionWidth );
DrawEditorInfoBox( wszSelType[gusSelectionType], FONT12POINT1, iScreenWidthOffset + 530, 2 * iScreenHeightOffset + 430, 60, 30 );
break;
case TASK_MERCS:
UpdateMercsInfo();
break;
case TASK_MAPINFO:
UpdateMapInfo();
// WANNE: EDITOR: comment this two lines, because we always get an exception here!
//if( gusSelectionType == LINESELECTION )
// swprintf( wszSelType[LINESELECTION], L"Width: %d", gusSelectionWidth );
DrawEditorInfoBox( wszSelType[gusSelectionType], FONT12POINT1, iScreenWidthOffset + 440, 2 * iScreenHeightOffset + 430, 60, 30 );
break;
}
}
//This is in ButtonSystem.c as a hack. Because we need to save the buffer whenever we do a full
//taskbar render, we need to draw the buttons without hilites, hence this flag. This flag is
//always true in ButtonSystem.c, so it won't effect anything else.
extern BOOLEAN gfGotoGridNoUI;
void ProcessEditorRendering()
{
BOOLEAN fSaveBuffer = FALSE;
if( gfRenderTaskbar ) //do a full taskbar render.
{
ClearTaskbarRegion( 0, SCREEN_HEIGHT - 120, SCREEN_WIDTH, SCREEN_HEIGHT );
RenderTerrainTileButtons();
MarkButtonsDirty();
gfRenderTaskbar = FALSE;
fSaveBuffer = TRUE;
gfRenderDrawingMode = TRUE;
gfRenderHilights = FALSE;
gfRenderMercInfo = TRUE;
}
if( gfRenderDrawingMode )
{
if( iCurrentTaskbar == TASK_BUILDINGS || iCurrentTaskbar == TASK_TERRAIN || iCurrentTaskbar == TASK_ITEMS )
{
ShowCurrentDrawingMode();
gfRenderDrawingMode = FALSE;
}
}
//render dynamically changed buttons only
RenderButtons( );
if( gfSummaryWindowActive )
RenderSummaryWindow();
else if( !gfGotoGridNoUI && !InOverheadMap() )
RenderMercStrings();
if( gfEditingDoor )
RenderDoorEditingWindow();
if( TextInputMode() )
RenderAllTextFields();
RenderEditorInfo();
if( !gfSummaryWindowActive && !gfGotoGridNoUI && !InOverheadMap() )
{
if( gpItem && gsItemGridNo != -1 )
RenderSelectedItemBlownUp();
if( iCurrentTaskbar == TASK_MAPINFO )
RenderMapEntryPointsAndLights();
if( iDrawMode == DRAW_MODE_PLACE_ITEM && eInfo.uiItemType == TBAR_MODE_ITEM_KEYS ||
iDrawMode == DRAW_MODE_DOORKEYS )
RenderDoorLockInfo();
}
if( fSaveBuffer )
// WANNE: EDITOR?
BlitBufferToBuffer( FRAME_BUFFER, guiSAVEBUFFER, 0, 2 * iScreenHeightOffset + 360, SCREEN_WIDTH, 120 );
//Make sure this is TRUE at all times.
//It is set to false when before we save the buffer, so the buttons don't get
//rendered with hilites, in case the mouse is over one.
gfRenderHilights = TRUE;
RenderButtonsFastHelp();
}
#endif