mirror of
https://github.com/1dot13/source.git
synced 2026-07-22 13:40:22 +02:00
3879 lines
140 KiB
C++
3879 lines
140 KiB
C++
#include "builddefines.h"
|
|
|
|
#ifdef JA2EDITOR
|
|
|
|
#include <windows.h>
|
|
#include "tiledef.h"
|
|
#include "edit_sys.h"
|
|
#include "vsurface.h"
|
|
#include "vobject.h"
|
|
#include "mousesystem.h"
|
|
#include "Button System.h"
|
|
#include "wcheck.h"
|
|
#include "vsurface.h"
|
|
#include "line.h"
|
|
#include "input.h"
|
|
#include "sysutil.h"
|
|
#include "font.h"
|
|
#include "Font Control.h"
|
|
#include "editscreen.h"
|
|
#include "selectwin.h"
|
|
#include "video.h"
|
|
#include "vobject_blitters.h"
|
|
#include "interface panels.h"
|
|
#include "interface items.h"
|
|
#include "text.h"
|
|
#include "utilities.h"
|
|
#include "World Items.h"
|
|
#include "worldman.h"
|
|
#include "overhead.h" //GetSoldier
|
|
#include "renderworld.h"
|
|
#include "Animation Data.h"
|
|
#include "Animation Control.h"
|
|
#include "EditorDefines.h"
|
|
#include "EditorMercs.h"
|
|
#include "EditorTerrain.h" //for access to TerrainTileDrawMode
|
|
#include "Soldier Create.h" //The stuff that connects the editor generated information
|
|
//to the saved map and the game itself.
|
|
#include "Inventory Choosing.h"
|
|
#include "Soldier Init List.h"
|
|
#include "strategicmap.h"
|
|
#include "Soldier Add.h"
|
|
#include "Soldier Profile Type.h"
|
|
#include "Soldier Profile.h"
|
|
#include "Text Input.h"
|
|
#include "Random.h"
|
|
#include "wordwrap.h"
|
|
#include "EditorItems.h"
|
|
#include "Editor Taskbar Utils.h"
|
|
#include "Exit Grids.h"
|
|
#include "Editor Undo.h"
|
|
#include "Item Statistics.h"
|
|
#include "Simple Render Utils.h"
|
|
#include "Map Information.h"
|
|
#include "Isometric Utils.h"
|
|
#include "Render Dirty.h"
|
|
#include "popupmenu.h"
|
|
#include "Scheduling.h"
|
|
#include "Timer Control.h"
|
|
#include "message.h"
|
|
#include "InterfaceItemImages.h"
|
|
#include "english.h"
|
|
//forward declarations of common classes to eliminate includes
|
|
class OBJECTTYPE;
|
|
class SOLDIERTYPE;
|
|
|
|
extern void GetSoldierAboveGuyPositions( SOLDIERTYPE *pSoldier, INT16 *psX, INT16 *psY, BOOLEAN fRadio );
|
|
|
|
//--------------------------------------------------
|
|
// NON_CIV_GROUP,
|
|
// REBEL_CIV_GROUP,
|
|
// KINGPIN_CIV_GROUP,
|
|
// SANMONA_ARMS_GROUP,
|
|
// ANGELS_GROUP,
|
|
// NUM_CIV_GROUPS
|
|
|
|
CHAR16 gszCivGroupNames[ NUM_CIV_GROUPS ][ 128 ];
|
|
|
|
|
|
/*
|
|
CHAR16 gszCivGroupNames[ NUM_CIV_GROUPS ][ 20 ] =
|
|
{
|
|
L"NONE",
|
|
L"REBEL",
|
|
L"KINGPIN",
|
|
L"SANMONA ARMS",
|
|
L"ANGELS",
|
|
|
|
L"BEGGARS",
|
|
L"TOURISTS",
|
|
L"ALMA MIL",
|
|
L"DOCTORS",
|
|
L"COUPLE1",
|
|
|
|
L"HICKS",
|
|
L"WARDEN",
|
|
L"JUNKYARD",
|
|
L"FACTORY KIDS",
|
|
L"QUEENS",
|
|
L"UNUSED15",
|
|
L"UNUSED16",
|
|
L"UNUSED17",
|
|
L"UNUSED18",
|
|
L"UNUSED19",
|
|
};
|
|
*/
|
|
//--------------------------------------------------
|
|
|
|
// SCHEDULE_ACTION_NONE,
|
|
// SCHEDULE_ACTION_LOCKDOOR,
|
|
// SCHEDULE_ACTION_UNLOCKDOOR,
|
|
// SCHEDULE_ACTION_OPENDOOR,
|
|
// SCHEDULE_ACTION_CLOSEDOOR,
|
|
// SCHEDULE_ACTION_GRIDNO,
|
|
// SCHEDULE_ACTION_LEAVESECTOR,
|
|
// SCHEDULE_ACTION_ENTERSECTOR,
|
|
// SCHEDULE_ACTION_STAYINSECTOR,
|
|
// SCHEDULE_ACTION_SLEEP,
|
|
/*
|
|
CHAR16 gszScheduleActions[ NUM_SCHEDULE_ACTIONS ][20] =
|
|
{
|
|
L"No action",
|
|
L"Lock door",
|
|
L"Unlock door",
|
|
L"Open door",
|
|
L"Close door",
|
|
L"Move to gridno",
|
|
L"Leave sector",
|
|
L"Enter sector",
|
|
L"Stay in sector",
|
|
L"Sleep",
|
|
L"Ignore this!"
|
|
};
|
|
*/
|
|
|
|
enum
|
|
{
|
|
SCHEDULE_INSTRUCTIONS_NONE,
|
|
SCHEDULE_INSTRUCTIONS_DOOR1,
|
|
SCHEDULE_INSTRUCTIONS_DOOR2,
|
|
SCHEDULE_INSTRUCTIONS_GRIDNO,
|
|
SCHEDULE_INSTRUCTIONS_SLEEP,
|
|
NUM_SCHEDULE_INSTRUCTIONS
|
|
};
|
|
|
|
extern BOOLEAN gfSingleAction = FALSE;
|
|
BOOLEAN gfUseScheduleData2 = FALSE;
|
|
UINT8 gubCurrentScheduleActionIndex = 0;
|
|
SCHEDULENODE gCurrSchedule;
|
|
UINT8 gubScheduleInstructions = SCHEDULE_INSTRUCTIONS_NONE;
|
|
void DetermineScheduleEditability();
|
|
void RenderCurrentSchedule();
|
|
void UpdateScheduleInfo();
|
|
|
|
void ShowEditMercPalettes( SOLDIERTYPE *pSoldier );
|
|
void ShowEditMercColorSet( UINT8 ubPaletteRep, INT16 sSet );
|
|
|
|
void ChangeBaseSoldierStats( SOLDIERTYPE *pSoldier );
|
|
void AskDefaultDifficulty( void );
|
|
|
|
//internal merc inventory functions
|
|
void AddNewItemToSelectedMercsInventory( BOOLEAN fCreate );
|
|
void RenderMercInventoryPanel();
|
|
void SetDroppableCheckboxesBasedOnMercsInventory();
|
|
|
|
extern BOOLEAN InternalAddSoldierToSector( SoldierID ubID, BOOLEAN fCalculateDirection, BOOLEAN fUseAnimation, UINT16 usAnimState, UINT16 usAnimCode );
|
|
|
|
//array which keeps track of which item is in which slot. This is dependant on the selected merc, so
|
|
//these temp values must be updated when different mercs are selected, and reset when a merc detailed
|
|
//placement is created.
|
|
OBJECTTYPE *gpMercSlotItem[9] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
|
|
//Because we only support these nine slots, they aren't continuous values, so this array helps
|
|
//processing functions by referring to this array to get the appropriate slot.
|
|
INT8 gbMercSlotTypes[9] = { HELMETPOS, VESTPOS, LEGPOS, HANDPOS, SECONDHANDPOS,
|
|
BIGPOCK1POS, BIGPOCK2POS, BIGPOCK3POS, BIGPOCK4POS };
|
|
//returns the usItem index of specified slot in the currently selected merc.
|
|
#define GetSelectedMercSlotItemIndex( x ) (gpSelected->pDetailedPlacement->Inv[gbMercSlotTypes[x]].usItem)
|
|
#define GetSelectedMercSlot( x ) (&gpSelected->pDetailedPlacement->Inv[gbMercSlotTypes[x]])
|
|
//values indicating which merc inventory slot is hilited and which slot is selected.
|
|
INT8 gbCurrHilite = -1;
|
|
INT8 gbCurrSelect = -1;
|
|
//when a new merc is selected, this function sets up all of the information for the slots,
|
|
//selections, and hilites.
|
|
void UpdateMercItemSlots();
|
|
|
|
//internal merc utility functions
|
|
void SetupTextInputForMercAttributes();
|
|
void SetupTextInputForMercProfile();
|
|
void SetupTextInputForMercSchedule();
|
|
void ExtractAndUpdateMercAttributes();
|
|
void ExtractAndUpdateMercProfile();
|
|
void ExtractAndUpdateMercSchedule();
|
|
void CalcStringForValue( STR16 str, INT32 iValue, UINT32 uiMax );
|
|
void ChangeBodyType( INT8 bOffset ); //+1 or -1 only
|
|
|
|
//internal merc variables
|
|
BASIC_SOLDIERCREATE_STRUCT gTempBasicPlacement;
|
|
SOLDIERCREATE_STRUCT gTempDetailedPlacement;
|
|
|
|
INT16 gsSelectedMercID;
|
|
INT32 gsSelectedMercGridNo;
|
|
SOLDIERINITNODE *gpSelected;
|
|
|
|
UINT8 gubCurrMercMode = MERC_TEAMMODE;
|
|
UINT8 gubPrevMercMode = MERC_NOMODE;
|
|
UINT8 gubLastDetailedMercMode = MERC_GENERALMODE;
|
|
INT8 gbDefaultOrders = STATIONARY;
|
|
INT8 gbDefaultAttitude = DEFENSIVE;
|
|
INT8 gbDefaultRelativeEquipmentLevel = 2;
|
|
INT8 gbDefaultRelativeAttributeLevel = 2;
|
|
INT8 gbDefaultDirection = NORTHWEST;
|
|
INT8 gubSoldierClass = SOLDIER_CLASS_ARMY;
|
|
UINT8 gubCivGroup = NON_CIV_GROUP;
|
|
|
|
SOLDIERTYPE *pTempSoldier;
|
|
BOOLEAN gfRoofPlacement;
|
|
|
|
//Below are all flags that have to do with editing detailed placement mercs:
|
|
|
|
//Determines if the user is allowed to edit merc colors. User must specifically
|
|
//click on the checkbox by the colors to confirm that colors will be specified. If
|
|
//not, the colors will be randomly generated upon creation in the game.
|
|
BOOLEAN gfCanEditMercColors = FALSE;
|
|
//A rendering flag that is set whenever a full update of the merc editing information
|
|
//needs to be done.
|
|
BOOLEAN gfRenderMercInfo = FALSE;
|
|
//When the user specifies a profile index for the merc, all editing is disabled. This is
|
|
//because the profile contains all of the information. When this happens, all of the editing
|
|
//buttons are disabled, but you are allowed to view stats, inventory, etc., as well as specify
|
|
//orders, attitude, and direction.
|
|
BOOLEAN gfCanEditMercs = TRUE;
|
|
//When in inventory mode, this flag is set when the user wishes to get an item, which requires hooking
|
|
//into the item editing features. This is processed during the editor update, which in turn, sets the
|
|
//new mode.
|
|
BOOLEAN gfMercGetItem = FALSE;
|
|
//As soon as an item is selected, the items index is stored here, so the item can be copied into the
|
|
//slot for editing and rendering purposes. This is a temp store value only when leaving the editor items
|
|
//mode.
|
|
UINT16 gusMercsNewItemIndex = 0xffff;
|
|
|
|
//old and probably obsolete
|
|
//BOOLEAN fMercEdUseLeftSide = FALSE;
|
|
//BOOLEAN fEditingMerc = FALSE;
|
|
//BOOLEAN fKeepWindowHidden = FALSE;
|
|
INT32 iEditMercPage = 1;
|
|
INT32 iEditMercEnd = -1;
|
|
INT32 iEditMercBkgrndArea = -1;
|
|
INT32 iEditMercLocation;
|
|
INT32 iEditStatTimer = 0;
|
|
INT32 iEditWhichStat = -1;
|
|
INT32 iEditMercMode = EDIT_MERC_NONE;
|
|
INT32 iEditMercColorPage = -1;
|
|
INT32 iEditMercStatPage = -1;
|
|
INT32 iEditMercFindButton = -1;
|
|
INT32 iEditMercSlotNumber;
|
|
INT32 iEditColorStart[EDIT_NUM_COLORS];
|
|
|
|
BOOLEAN gfShowPlayers = TRUE;
|
|
BOOLEAN gfShowEnemies = TRUE;
|
|
BOOLEAN gfShowCreatures = TRUE;
|
|
BOOLEAN gfShowRebels = TRUE;
|
|
BOOLEAN gfShowCivilians = TRUE;
|
|
|
|
#define BASE_STAT_DEVIATION 7
|
|
#define BASE_EXPLVL_DEVIATION 1
|
|
#define BASE_PROTLVL_DEVIATION 0
|
|
#define BASE_GUNTYPE_DEVIATION 4
|
|
#define DEFAULT_DIFF 2
|
|
|
|
INT16 sCurBaseDiff = DEFAULT_DIFF;
|
|
BOOLEAN fAskForBaseDifficulty = TRUE;
|
|
//STR16 zDiffNames[NUM_DIFF_LVLS] = { L"Wimp", L"Easy", L"Average", L"Tough", L"Steroid Users Only" };
|
|
INT16 sBaseStat[NUM_DIFF_LVLS] = { 50, 60, 70, 80, 90 };
|
|
INT16 sBaseExpLvl[NUM_DIFF_LVLS] = { 1, 3, 5, 7, 9 };
|
|
/*
|
|
STR16 EditMercStat[12] = { L"Max Health",L"Cur Health",L"Strength",
|
|
L"Agility",L"Dexterity",L"Charisma",
|
|
L"Wisdom",L"Marksmanship",L"Explosives",
|
|
L"Medical",L"Scientific",L"Exp Level" };
|
|
*/
|
|
#define NUM_MERC_ORDERS 8
|
|
/*
|
|
STR16 EditMercOrders[8] = { L"Stationary",L"On Guard",L"Close Patrol",
|
|
L"Far Patrol",L"Point Patrol",L"On Call",
|
|
L"Seek Enemy", L"Random Point Patrol"};
|
|
|
|
STR16 EditMercAttitudes[6] = { L"Defensive",L"Brave Loner",L"Brave Buddy",
|
|
L"Cunning Loner",L"Cunning Buddy",
|
|
L"Aggressive" };
|
|
*/
|
|
//information for bodytypes.
|
|
#ifdef RANDOM
|
|
#undef RANDOM
|
|
#endif
|
|
#define RANDOM -1
|
|
#ifdef JA113DEMO
|
|
#define MAX_ENEMYTYPES 5
|
|
#define MAX_CREATURETYPES 1
|
|
#define MAX_REBELTYPES 6
|
|
#define MAX_CIVTYPES 6
|
|
#else
|
|
#define MAX_ENEMYTYPES 11
|
|
//#define MAX_ENEMYRANDOMTYPES 5
|
|
#define MAX_CREATURETYPES 8
|
|
#define MAX_REBELTYPES 7
|
|
#define MAX_CIVTYPES 18
|
|
//#define MAX_CIVRANDOMTYPES 11
|
|
#endif
|
|
|
|
#ifdef JA113DEMO
|
|
INT8 bEnemyArray[MAX_ENEMYTYPES]={ RANDOM, REGMALE, BIGMALE, STOCKYMALE, REGFEMALE };
|
|
INT8 bCreatureArray[MAX_CREATURETYPES]={ ADULTFEMALEMONSTER };
|
|
INT8 bRebelArray[MAX_REBELTYPES]={ RANDOM, MANCIV, REGMALE, BIGMALE, STOCKYMALE, REGFEMALE };
|
|
INT8 bCivArray[MAX_CIVTYPES]={ RANDOM, MANCIV, REGMALE, BIGMALE, STOCKYMALE, REGFEMALE };
|
|
#else
|
|
INT8 bEnemyArray[MAX_ENEMYTYPES] = {RANDOM, REGMALE, BIGMALE, STOCKYMALE, REGFEMALE, TANK_NW, TANK_NE, COMBAT_JEEP};
|
|
INT8 bCreatureArray[MAX_CREATURETYPES]={ BLOODCAT, LARVAE_MONSTER, INFANT_MONSTER, YAF_MONSTER, YAM_MONSTER, ADULTFEMALEMONSTER, AM_MONSTER, QUEENMONSTER };
|
|
INT8 bRebelArray[MAX_REBELTYPES]={ RANDOM, FATCIV, MANCIV, REGMALE, BIGMALE, STOCKYMALE, REGFEMALE };
|
|
INT8 bCivArray[MAX_CIVTYPES]={ RANDOM, FATCIV, MANCIV, MINICIV, DRESSCIV, HATKIDCIV, KIDCIV, REGMALE, BIGMALE, STOCKYMALE, REGFEMALE,
|
|
HUMVEE, ELDORADO, ICECREAMTRUCK, JEEP, CRIPPLECIV, ROBOTNOWEAPON, COW };
|
|
#endif
|
|
|
|
#ifdef JA113DEMO
|
|
INT8 gbCurrCreature = ADULTFEMALEMONSTER;
|
|
#else
|
|
INT8 gbCurrCreature = BLOODCAT;
|
|
#endif
|
|
|
|
|
|
BOOLEAN gfSaveBuffer = FALSE;
|
|
extern BASIC_SOLDIERCREATE_STRUCT gSaveBufferBasicPlacement;
|
|
extern SOLDIERCREATE_STRUCT gSaveBufferDetailedPlacement;
|
|
//void CopyMercPlacement(); // moved to header (jonathanl)
|
|
//void PasteMercPlacement(); // moved to header (jonathanl)
|
|
|
|
|
|
//legion2 jazz
|
|
|
|
wchar_t *GetGrupaString( SOLDIERTYPE *pSoldier ) //Legion 2
|
|
{
|
|
INT32 cnt, cntStart,par;
|
|
|
|
cntStart = 0;
|
|
for ( cnt = cntStart; cnt < NUM_CIV_GROUPS; cnt ++ )
|
|
{
|
|
if (pSoldier->ubCivilianGroup == cnt)
|
|
{
|
|
par = cnt;
|
|
}
|
|
|
|
}
|
|
return gszCivGroupNames[ par ];
|
|
}
|
|
//------------
|
|
|
|
|
|
void GameInitEditorMercsInfo()
|
|
{
|
|
INT32 i;
|
|
//Initialize the placement list
|
|
InitSoldierInitList();
|
|
gMapInformation.ubNumIndividuals = 0;
|
|
memset( &gCurrSchedule, 0, sizeof( SCHEDULENODE ) );
|
|
for( i = 0; i < 4; i++ )
|
|
{
|
|
gCurrSchedule.usTime[i] = 0xffff;
|
|
gCurrSchedule.usData1[i] = 0xffffffff;
|
|
gCurrSchedule.usData2[i] = 0xffffffff;
|
|
}
|
|
}
|
|
|
|
void GameShutdownEditorMercsInfo()
|
|
{
|
|
UseEditorAlternateList();
|
|
KillSoldierInitList();
|
|
UseEditorOriginalList();
|
|
KillSoldierInitList();
|
|
}
|
|
|
|
void EntryInitEditorMercsInfo()
|
|
{
|
|
INT32 x, iCurStart = 0;
|
|
iEditColorStart[0] = 0;
|
|
for ( x = 1; x < EDIT_NUM_COLORS; x++ )
|
|
{
|
|
iCurStart += gubpNumReplacementsPerRange[ x - 1 ];
|
|
iEditColorStart[x] = iCurStart;
|
|
}
|
|
gsSelectedMercID = -1;
|
|
gsSelectedMercGridNo = 0;
|
|
|
|
gfCanEditMercs = TRUE;
|
|
}
|
|
|
|
enum
|
|
{
|
|
HAIR_PAL,
|
|
SKIN_PAL,
|
|
VEST_PAL,
|
|
PANTS_PAL
|
|
};
|
|
|
|
void ProcessMercEditing()
|
|
{
|
|
UINT8 ubType, ubPaletteRep;
|
|
SOLDIERTYPE *pSoldier;
|
|
if ( iEditMercMode == EDIT_MERC_NONE )
|
|
{
|
|
return;
|
|
}
|
|
GetSoldier( &pSoldier, gsSelectedMercID );
|
|
|
|
switch ( iEditMercMode )
|
|
{
|
|
case EDIT_MERC_PREV_COLOR:
|
|
case EDIT_MERC_NEXT_COLOR:
|
|
// Handle changes to the merc colors
|
|
switch ( iEditWhichStat )
|
|
{
|
|
case 0:
|
|
ubType = EDIT_COLOR_HEAD;
|
|
GetPaletteRepIndexFromID( pSoldier->HeadPal, &ubPaletteRep );
|
|
|
|
ubPaletteRep--;
|
|
if ( (ubPaletteRep < (UINT8)iEditColorStart[ubType]) || (ubPaletteRep > ((UINT8)iEditColorStart[ubType] + gubpNumReplacementsPerRange[ubType])) )
|
|
ubPaletteRep = (UINT8)iEditColorStart[ubType] + gubpNumReplacementsPerRange[ubType] - 1;
|
|
|
|
SET_PALETTEREP_ID( pSoldier->HeadPal, gpPalRep[ ubPaletteRep ].ID );
|
|
sprintf( gpSelected->pDetailedPlacement->HeadPal, pSoldier->HeadPal );
|
|
pSoldier->CreateSoldierPalettes( );
|
|
break;
|
|
case 1:
|
|
ubType = EDIT_COLOR_HEAD;
|
|
GetPaletteRepIndexFromID( pSoldier->HeadPal, &ubPaletteRep );
|
|
|
|
ubPaletteRep++;
|
|
if ( ubPaletteRep >= ((UINT8)iEditColorStart[ubType] + gubpNumReplacementsPerRange[ubType]) )
|
|
ubPaletteRep = (UINT8)iEditColorStart[ubType];
|
|
|
|
SET_PALETTEREP_ID( pSoldier->HeadPal, gpPalRep[ ubPaletteRep ].ID );
|
|
sprintf( gpSelected->pDetailedPlacement->HeadPal, pSoldier->HeadPal );
|
|
pSoldier->CreateSoldierPalettes( );
|
|
break;
|
|
|
|
case 2:
|
|
ubType = EDIT_COLOR_SKIN;
|
|
GetPaletteRepIndexFromID( pSoldier->SkinPal, &ubPaletteRep );
|
|
|
|
ubPaletteRep--;
|
|
if ( ubPaletteRep < (UINT8)iEditColorStart[ubType] )
|
|
ubPaletteRep = (UINT8)iEditColorStart[ubType] + gubpNumReplacementsPerRange[ubType] - 1;
|
|
|
|
SET_PALETTEREP_ID( pSoldier->SkinPal, gpPalRep[ ubPaletteRep ].ID );
|
|
sprintf( gpSelected->pDetailedPlacement->SkinPal, pSoldier->SkinPal );
|
|
pSoldier->CreateSoldierPalettes( );
|
|
break;
|
|
case 3:
|
|
ubType = EDIT_COLOR_SKIN;
|
|
GetPaletteRepIndexFromID( pSoldier->SkinPal, &ubPaletteRep );
|
|
|
|
ubPaletteRep++;
|
|
if ( ubPaletteRep >= ((UINT8)iEditColorStart[ubType] + gubpNumReplacementsPerRange[ubType]) )
|
|
ubPaletteRep = (UINT8)iEditColorStart[ubType];
|
|
|
|
SET_PALETTEREP_ID( pSoldier->SkinPal, gpPalRep[ ubPaletteRep ].ID );
|
|
sprintf( gpSelected->pDetailedPlacement->SkinPal, pSoldier->SkinPal );
|
|
pSoldier->CreateSoldierPalettes( );
|
|
break;
|
|
|
|
case 4:
|
|
ubType = EDIT_COLOR_VEST;
|
|
GetPaletteRepIndexFromID( pSoldier->VestPal, &ubPaletteRep );
|
|
|
|
ubPaletteRep--;
|
|
if ( ubPaletteRep < (UINT8)iEditColorStart[ubType] )
|
|
ubPaletteRep = (UINT8)iEditColorStart[ubType] + gubpNumReplacementsPerRange[ubType] - 1;
|
|
|
|
SET_PALETTEREP_ID( pSoldier->VestPal, gpPalRep[ ubPaletteRep ].ID );
|
|
sprintf( gpSelected->pDetailedPlacement->VestPal, pSoldier->VestPal );
|
|
pSoldier->CreateSoldierPalettes( );
|
|
break;
|
|
case 5:
|
|
ubType = EDIT_COLOR_VEST;
|
|
GetPaletteRepIndexFromID( pSoldier->VestPal, &ubPaletteRep );
|
|
|
|
ubPaletteRep++;
|
|
if ( ubPaletteRep >= ((UINT8)iEditColorStart[ubType] + gubpNumReplacementsPerRange[ubType]) )
|
|
ubPaletteRep = (UINT8)iEditColorStart[ubType];
|
|
|
|
SET_PALETTEREP_ID( pSoldier->VestPal, gpPalRep[ ubPaletteRep ].ID );
|
|
sprintf( gpSelected->pDetailedPlacement->VestPal, pSoldier->VestPal );
|
|
pSoldier->CreateSoldierPalettes( );
|
|
break;
|
|
|
|
case 6:
|
|
ubType = EDIT_COLOR_PANTS;
|
|
GetPaletteRepIndexFromID( pSoldier->PantsPal, &ubPaletteRep );
|
|
|
|
ubPaletteRep--;
|
|
if ( ubPaletteRep < (UINT8)iEditColorStart[ubType] )
|
|
ubPaletteRep = (UINT8)iEditColorStart[ubType] + gubpNumReplacementsPerRange[ubType] - 1;
|
|
|
|
SET_PALETTEREP_ID( pSoldier->PantsPal, gpPalRep[ ubPaletteRep ].ID );
|
|
sprintf( gpSelected->pDetailedPlacement->PantsPal, pSoldier->PantsPal );
|
|
pSoldier->CreateSoldierPalettes( );
|
|
break;
|
|
case 7:
|
|
ubType = EDIT_COLOR_PANTS;
|
|
GetPaletteRepIndexFromID( pSoldier->PantsPal, &ubPaletteRep );
|
|
|
|
ubPaletteRep++;
|
|
if ( ubPaletteRep >= ((UINT8)iEditColorStart[ubType] + gubpNumReplacementsPerRange[ubType]) )
|
|
ubPaletteRep = (UINT8)iEditColorStart[ubType];
|
|
|
|
SET_PALETTEREP_ID( pSoldier->PantsPal, gpPalRep[ ubPaletteRep ].ID );
|
|
sprintf( gpSelected->pDetailedPlacement->PantsPal, pSoldier->PantsPal );
|
|
pSoldier->CreateSoldierPalettes( );
|
|
break;
|
|
}
|
|
iEditMercMode = EDIT_MERC_NONE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
void AddMercToWorld( INT32 iMapIndex )
|
|
{
|
|
SOLDIERTYPE *pSoldier;
|
|
INT32 i;
|
|
|
|
memset( &gTempBasicPlacement, 0, sizeof( BASIC_SOLDIERCREATE_STRUCT ) );
|
|
|
|
gTempBasicPlacement.ubBodyType = -1;
|
|
|
|
//calculate specific information based on the team.
|
|
switch( iDrawMode )
|
|
{
|
|
case DRAW_MODE_ENEMY:
|
|
gTempBasicPlacement.bTeam = ENEMY_TEAM;
|
|
gTempBasicPlacement.ubBodyType = RANDOM;
|
|
gTempBasicPlacement.ubSoldierClass = gubSoldierClass;
|
|
break;
|
|
case DRAW_MODE_CREATURE:
|
|
gTempBasicPlacement.bTeam = CREATURE_TEAM;
|
|
gTempBasicPlacement.ubBodyType = gbCurrCreature;
|
|
break;
|
|
case DRAW_MODE_REBEL:
|
|
gTempBasicPlacement.bTeam = MILITIA_TEAM;
|
|
gTempBasicPlacement.ubBodyType = RANDOM;
|
|
break;
|
|
case DRAW_MODE_CIVILIAN:
|
|
gTempBasicPlacement.bTeam = CIV_TEAM;
|
|
gTempBasicPlacement.ubBodyType = RANDOM;
|
|
gTempBasicPlacement.ubCivilianGroup = gubCivGroup;
|
|
if( giCurrentTilesetID == 1 ) //caves
|
|
{
|
|
gTempBasicPlacement.ubSoldierClass = SOLDIER_CLASS_MINER;
|
|
}
|
|
break;
|
|
}
|
|
|
|
if( IsLocationSittable( iMapIndex, gfRoofPlacement ) )
|
|
{
|
|
SoldierID ubID;
|
|
INT16 sSectorX, sSectorY;
|
|
SOLDIERINITNODE *pNode;
|
|
|
|
GetCurrentWorldSector( &sSectorX, &sSectorY );
|
|
|
|
//Set up some general information.
|
|
gTempBasicPlacement.fDetailedPlacement = FALSE;
|
|
gTempBasicPlacement.fPriorityExistance = FALSE;
|
|
gTempBasicPlacement.usStartingGridNo = iMapIndex;
|
|
gTempBasicPlacement.bOrders = gbDefaultOrders;
|
|
gTempBasicPlacement.bAttitude = gbDefaultAttitude;
|
|
gTempBasicPlacement.bRelativeAttributeLevel = gbDefaultRelativeAttributeLevel;
|
|
gTempBasicPlacement.bRelativeEquipmentLevel = gbDefaultRelativeEquipmentLevel;
|
|
gTempBasicPlacement.ubDirection = gbDefaultDirection;
|
|
|
|
//Generate detailed placement information given the temp placement information.
|
|
CreateDetailedPlacementGivenBasicPlacementInfo( &gTempDetailedPlacement, &gTempBasicPlacement );
|
|
|
|
//Set the sector information -- probably unnecessary.
|
|
gTempDetailedPlacement.sSectorX = sSectorX;
|
|
gTempDetailedPlacement.sSectorY = sSectorY;
|
|
|
|
//Create the soldier, but don't place it yet.
|
|
if ( pSoldier = TacticalCreateSoldier( &gTempDetailedPlacement, &ubID ) )
|
|
{
|
|
pSoldier->bVisible = 1;
|
|
pSoldier->bLastRenderVisibleValue = 1;
|
|
//Set up the soldier in the list, so we can track the soldier in the
|
|
//future (saving, loading, strategic AI)
|
|
pNode = AddBasicPlacementToSoldierInitList( &gTempBasicPlacement );
|
|
Assert( pNode );
|
|
pNode->pSoldier = pSoldier;
|
|
|
|
//Add the soldier to physically appear on the map now.
|
|
InternalAddSoldierToSector( ubID, FALSE, FALSE, 0, 0 );
|
|
IndicateSelectedMerc( ubID );
|
|
|
|
//Move him to the roof if intended and possible.
|
|
if( gfRoofPlacement && FlatRoofAboveGridNo( iMapIndex ) )
|
|
{
|
|
gpSelected->pBasicPlacement->fOnRoof = TRUE;
|
|
if( gpSelected->pDetailedPlacement )
|
|
gpSelected->pDetailedPlacement->fOnRoof = TRUE;
|
|
gpSelected->pSoldier->SetSoldierHeight( 58.0 );
|
|
}
|
|
UnclickEditorButtons( FIRST_MERCS_INVENTORY_BUTTON, LAST_MERCS_INVENTORY_BUTTON );
|
|
for( i = FIRST_MERCS_INVENTORY_BUTTON; i <= LAST_MERCS_INVENTORY_BUTTON; i++ )
|
|
{
|
|
SetEnemyDroppableStatus( gbMercSlotTypes[i-FIRST_MERCS_INVENTORY_BUTTON], FALSE );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void HandleRightClickOnMerc( INT32 iMapIndex )
|
|
{
|
|
SOLDIERINITNODE *pNode;
|
|
INT16 sThisMercID;
|
|
INT16 sCellX, sCellY;
|
|
|
|
ConvertGridNoToCellXY( iMapIndex, &sCellX, &sCellY );
|
|
|
|
sThisMercID = (INT16)IsMercHere( iMapIndex );
|
|
|
|
if ( sThisMercID != -1)
|
|
{
|
|
if ( gsSelectedMercID != sThisMercID )
|
|
{ // We want to edit a new merc (or different merc)
|
|
//We need to avoid the editing of player mercs.
|
|
pNode = FindSoldierInitNodeWithID( (UINT8)sThisMercID );
|
|
if( !pNode )
|
|
return; //this is a player merc (which isn't in the list), or an error in logic.
|
|
IndicateSelectedMerc( sThisMercID );
|
|
}
|
|
}
|
|
else if( gsSelectedMercID != -1 && IsLocationSittable( iMapIndex, gfRoofPlacement ) )// We want to move the selected merc to this new location.
|
|
{
|
|
RemoveAllObjectsOfTypeRange( gsSelectedMercGridNo, CONFIRMMOVE, CONFIRMMOVE );
|
|
gpSelected->pSoldier->EVENT_SetSoldierPosition( (FLOAT)(sCellX + 5), (FLOAT)(sCellY + 5) );
|
|
if( gfRoofPlacement && FlatRoofAboveGridNo( iMapIndex ) )
|
|
{
|
|
gpSelected->pBasicPlacement->fOnRoof = TRUE;
|
|
if( gpSelected->pDetailedPlacement )
|
|
gpSelected->pDetailedPlacement->fOnRoof = TRUE;
|
|
gpSelected->pSoldier->SetSoldierHeight( 58.0 );
|
|
}
|
|
else
|
|
{
|
|
gpSelected->pBasicPlacement->fOnRoof = FALSE;
|
|
if( gpSelected->pDetailedPlacement )
|
|
gpSelected->pDetailedPlacement->fOnRoof = FALSE;
|
|
gpSelected->pSoldier->SetSoldierHeight( 0.0 );
|
|
}
|
|
gsSelectedMercGridNo = iMapIndex;
|
|
gpSelected->pBasicPlacement->usStartingGridNo = gsSelectedMercGridNo;
|
|
if( gpSelected->pDetailedPlacement )
|
|
gpSelected->pDetailedPlacement->sInsertionGridNo = gsSelectedMercGridNo;
|
|
AddObjectToHead( gsSelectedMercGridNo, CONFIRMMOVE1 );
|
|
}
|
|
}
|
|
|
|
void ResetAllMercPositions()
|
|
{
|
|
SOLDIERINITNODE *curr;
|
|
//Remove all of the alternate placements (editor takes precedence)
|
|
UseEditorAlternateList();
|
|
curr = gSoldierInitHead;
|
|
while( curr )
|
|
{
|
|
gpSelected = curr;
|
|
curr = curr->next;
|
|
RemoveSoldierNodeFromInitList( gpSelected );
|
|
}
|
|
//Now, remove any existing original list mercs, then readd them.
|
|
UseEditorOriginalList();
|
|
curr = gSoldierInitHead;
|
|
while( curr )
|
|
{
|
|
if( curr->pSoldier )
|
|
{
|
|
TacticalRemoveSoldier( curr->pSoldier->ubID );
|
|
curr->pSoldier = NULL;
|
|
}
|
|
//usMapIndex = gpSelected->pBasicPlacement->usStartingGridNo;
|
|
//ConvertGridNoToCellXY( sMapIndex, &sCellX, &sCellY );
|
|
//if( gpSelected->pSoldier )
|
|
//{
|
|
// EVENT_SetSoldierPosition( gpSelected->pSoldier, (FLOAT)(sCellX + 5), (FLOAT)(sCellY + 5) );
|
|
// if( gpSelected->pBasicPlacement->fOnRoof )
|
|
// gpSelected->pSoldier->SetSoldierHeight( 58.0 );
|
|
// SetMercDirection( gpSelected->pBasicPlacement->ubDirection );
|
|
//}
|
|
curr = curr->next;
|
|
}
|
|
AddSoldierInitListTeamToWorld( ENEMY_TEAM, TOTAL_SOLDIERS + 1 );
|
|
AddSoldierInitListTeamToWorld( CREATURE_TEAM, TOTAL_SOLDIERS + 1 );
|
|
AddSoldierInitListTeamToWorld( MILITIA_TEAM, TOTAL_SOLDIERS + 1 );
|
|
AddSoldierInitListTeamToWorld( CIV_TEAM, TOTAL_SOLDIERS + 1 );
|
|
gpSelected = NULL;
|
|
gsSelectedMercID = -1;
|
|
}
|
|
|
|
void AddMercWaypoint( INT32 iMapIndex )
|
|
{
|
|
INT32 iNum;
|
|
// index 0 isn't used
|
|
if ( iActionParam == 0 )
|
|
return;
|
|
|
|
if ( gsSelectedMercID == -1 || (gsSelectedMercID <= (INT32)gTacticalStatus.Team[ OUR_TEAM ].bLastID) || gsSelectedMercID >= MAXMERCS )
|
|
return;
|
|
|
|
if ( iActionParam > gpSelected->pSoldier->aiData.bPatrolCnt )
|
|
{
|
|
// Fill up missing waypoints with same value as new one
|
|
for(iNum = gpSelected->pSoldier->aiData.bPatrolCnt + 1; iNum <= iActionParam; iNum++)
|
|
{
|
|
gpSelected->pBasicPlacement->sPatrolGrid[iNum] = iMapIndex;
|
|
if( gpSelected->pDetailedPlacement )
|
|
gpSelected->pDetailedPlacement->sPatrolGrid[iNum] = iMapIndex;
|
|
gpSelected->pSoldier->aiData.sPatrolGrid[iNum] = iMapIndex;
|
|
}
|
|
|
|
gpSelected->pBasicPlacement->bPatrolCnt = (INT8)iActionParam;
|
|
if( gpSelected->pDetailedPlacement )
|
|
gpSelected->pDetailedPlacement->bPatrolCnt = (INT8)iActionParam;
|
|
gpSelected->pSoldier->aiData.bPatrolCnt = (INT8) iActionParam;
|
|
gpSelected->pSoldier->aiData.bNextPatrolPnt = 1;
|
|
}
|
|
else
|
|
{
|
|
// Set this way point
|
|
gpSelected->pBasicPlacement->sPatrolGrid[iActionParam] = iMapIndex;
|
|
if( gpSelected->pDetailedPlacement )
|
|
gpSelected->pDetailedPlacement->sPatrolGrid[iActionParam] = iMapIndex;
|
|
gpSelected->pSoldier->aiData.sPatrolGrid[iActionParam] = iMapIndex;
|
|
}
|
|
gfRenderWorld = TRUE;
|
|
}
|
|
|
|
void EraseMercWaypoint()
|
|
{
|
|
INT32 iNum;
|
|
// index 0 isn't used
|
|
if ( iActionParam == 0 )
|
|
return;
|
|
|
|
if ( gsSelectedMercID == -1 || (gsSelectedMercID <= (INT32)gTacticalStatus.Team[ OUR_TEAM ].bLastID) || gsSelectedMercID >= MAXMERCS )
|
|
return;
|
|
|
|
// Fill up missing areas
|
|
if ( iActionParam > gpSelected->pSoldier->aiData.bPatrolCnt )
|
|
return;
|
|
|
|
for(iNum = iActionParam; iNum < gpSelected->pSoldier->aiData.bPatrolCnt; iNum++)
|
|
{
|
|
gpSelected->pBasicPlacement->sPatrolGrid[iNum] = gpSelected->pBasicPlacement->sPatrolGrid[iNum+1];
|
|
if( gpSelected->pDetailedPlacement )
|
|
gpSelected->pDetailedPlacement->sPatrolGrid[iNum] = gpSelected->pDetailedPlacement->sPatrolGrid[iNum+1];
|
|
gpSelected->pSoldier->aiData.sPatrolGrid[iNum] = gpSelected->pSoldier->aiData.sPatrolGrid[iNum+1];
|
|
}
|
|
|
|
gpSelected->pBasicPlacement->bPatrolCnt--;
|
|
if( gpSelected->pDetailedPlacement )
|
|
gpSelected->pDetailedPlacement->bPatrolCnt--;
|
|
gpSelected->pSoldier->aiData.bPatrolCnt--;
|
|
gfRenderWorld = TRUE;
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------------------------
|
|
// ChangeBaseSoldierStats
|
|
//
|
|
// This functions changes the stats of a given merc (PC or NPC, though should only be used
|
|
// for NPC mercs) to reflect the base difficulty level selected.
|
|
//
|
|
void ChangeBaseSoldierStats( SOLDIERTYPE *pSoldier )
|
|
{
|
|
if ( pSoldier == NULL )
|
|
return;
|
|
|
|
pSoldier->stats.bLifeMax = (UINT8)(sBaseStat[sCurBaseDiff] + (UINT16)(Random(BASE_STAT_DEVIATION * 2)-BASE_STAT_DEVIATION));
|
|
pSoldier->stats.bLife = pSoldier->stats.bLifeMax;
|
|
|
|
pSoldier->bBleeding = 0;
|
|
pSoldier->bBreath = 100;
|
|
|
|
pSoldier->stats.bMarksmanship = (UINT8)(sBaseStat[sCurBaseDiff] + (UINT16)(Random(BASE_STAT_DEVIATION * 2)-BASE_STAT_DEVIATION));
|
|
pSoldier->stats.bMedical = (UINT8)(sBaseStat[sCurBaseDiff] + (UINT16)(Random(BASE_STAT_DEVIATION * 2)-BASE_STAT_DEVIATION));
|
|
pSoldier->stats.bMechanical = (UINT8)(sBaseStat[sCurBaseDiff] + (UINT16)(Random(BASE_STAT_DEVIATION * 2)-BASE_STAT_DEVIATION));
|
|
pSoldier->stats.bExplosive = (UINT8)(sBaseStat[sCurBaseDiff] + (UINT16)(Random(BASE_STAT_DEVIATION * 2)-BASE_STAT_DEVIATION));
|
|
pSoldier->stats.bAgility = (UINT8)(sBaseStat[sCurBaseDiff] + (UINT16)(Random(BASE_STAT_DEVIATION * 2)-BASE_STAT_DEVIATION));
|
|
pSoldier->stats.bDexterity = (UINT8)(sBaseStat[sCurBaseDiff] + (UINT16)(Random(BASE_STAT_DEVIATION * 2)-BASE_STAT_DEVIATION));
|
|
|
|
pSoldier->stats.bStrength = (UINT8)(sBaseStat[sCurBaseDiff] + (UINT16)(Random(BASE_STAT_DEVIATION * 2)-BASE_STAT_DEVIATION));
|
|
pSoldier->stats.bLeadership = (UINT8)(sBaseStat[sCurBaseDiff] + (UINT16)(Random(BASE_STAT_DEVIATION * 2)-BASE_STAT_DEVIATION));
|
|
pSoldier->stats.bWisdom = (UINT8)(sBaseStat[sCurBaseDiff] + (UINT16)(Random(BASE_STAT_DEVIATION * 2)-BASE_STAT_DEVIATION));
|
|
pSoldier->stats.bScientific = (UINT8)(sBaseStat[sCurBaseDiff] + (UINT16)(Random(BASE_STAT_DEVIATION * 2)-BASE_STAT_DEVIATION));
|
|
|
|
pSoldier->stats.bExpLevel = (UINT8)sBaseExpLvl[sCurBaseDiff];
|
|
pSoldier->bGunType = (INT8)Random(BASE_GUNTYPE_DEVIATION);
|
|
|
|
pSoldier->bActionPoints = pSoldier->CalcActionPoints( );
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------------------------
|
|
// DisplayEditMercWindow
|
|
//
|
|
// Displays the edit merc stat page while editing mercs. If the merc color editing page is
|
|
// to be displayed, this function will dispatch it instead.
|
|
//
|
|
void DisplayEditMercWindow( void )
|
|
{
|
|
INT32 iXPos, iYPos, iHeight, iWidth;
|
|
UINT16 usFillColorBack, usFillColorDark, usFillColorLight, usFillColorTextBk;
|
|
INT32 x, iXOff;
|
|
CHAR16 TempString[30];
|
|
SOLDIERTYPE *pSoldier;
|
|
INT8 iEditStat[12];
|
|
|
|
usFillColorBack = 0;
|
|
|
|
if ( gsSelectedMercID == -1 )
|
|
{
|
|
// fEditingMerc = FALSE;
|
|
// DestroyEditMercWindow();
|
|
return;
|
|
}
|
|
|
|
|
|
GetSoldier( &pSoldier, (INT16)gsSelectedMercID );
|
|
|
|
// usFillColorBack = GenericButtonFillColors[0];
|
|
usFillColorDark = Get16BPPColor(FROMRGB(24, 61, 81));
|
|
usFillColorLight = Get16BPPColor(FROMRGB(136, 138, 135));
|
|
usFillColorTextBk = Get16BPPColor(FROMRGB(250, 240, 188));
|
|
|
|
iWidth = 266;
|
|
iHeight = 360;
|
|
iYPos = iScreenHeightOffset + 0;
|
|
iXPos = iScreenWidthOffset + 0;
|
|
|
|
// Main window
|
|
ColorFillVideoSurfaceArea(FRAME_BUFFER, iXPos, iYPos, iXPos + iWidth, iYPos + iHeight, usFillColorLight );
|
|
ColorFillVideoSurfaceArea(FRAME_BUFFER, iXPos + 1, iYPos + 1, iXPos + iWidth, iYPos + iHeight, usFillColorDark );
|
|
ColorFillVideoSurfaceArea(FRAME_BUFFER, iXPos + 1, iYPos + 1, iXPos + iWidth - 1, iYPos + iHeight - 1, usFillColorBack );
|
|
|
|
SetFont( FONT12POINT1 );
|
|
|
|
// Name window
|
|
gprintf( iXPos + 128, iYPos + 3, pDisplayEditMercWindowText[0] );
|
|
ColorFillVideoSurfaceArea(FRAME_BUFFER, iXPos + 128, iYPos + 16, iXPos + 128 + 104, iYPos + 16 + 19, usFillColorDark );
|
|
ColorFillVideoSurfaceArea(FRAME_BUFFER, iXPos + 129, iYPos + 17, iXPos + 128 + 104, iYPos + 17 + 19, usFillColorLight );
|
|
ColorFillVideoSurfaceArea(FRAME_BUFFER, iXPos + 129, iYPos + 17, iXPos + 128 + 103, iYPos + 17 + 18, usFillColorTextBk );
|
|
iXOff = (105 - StringPixLength( pSoldier->name, FONT12POINT1 )) / 2;
|
|
gprintf( iXPos + 130 + iXOff, iYPos + 20, L"%s", pSoldier->name );
|
|
|
|
// Orders window
|
|
gprintf( iXPos + 128, iYPos + 38, pDisplayEditMercWindowText[1] );
|
|
ColorFillVideoSurfaceArea(FRAME_BUFFER, iXPos + 128, iYPos + 51, iXPos + 128 + 104, iYPos + 51 + 19, usFillColorDark );
|
|
ColorFillVideoSurfaceArea(FRAME_BUFFER, iXPos + 129, iYPos + 52, iXPos + 128 + 104, iYPos + 52 + 19, usFillColorLight );
|
|
ColorFillVideoSurfaceArea(FRAME_BUFFER, iXPos + 129, iYPos + 52, iXPos + 128 + 103, iYPos + 52 + 18, usFillColorTextBk );
|
|
iXOff = (105 - StringPixLength( EditMercOrders[pSoldier->aiData.bOrders], FONT12POINT1 )) / 2;
|
|
gprintf( iXPos + 130 + iXOff, iYPos + 55, L"%s", EditMercOrders[pSoldier->aiData.bOrders] );
|
|
|
|
// Combat window
|
|
gprintf( iXPos + 128, iYPos + 73, pDisplayEditMercWindowText[2] );
|
|
ColorFillVideoSurfaceArea(FRAME_BUFFER, iXPos + 128, iYPos + 86, iXPos + 128 + 104, iYPos + 86 + 19, usFillColorDark );
|
|
ColorFillVideoSurfaceArea(FRAME_BUFFER, iXPos + 129, iYPos + 87, iXPos + 128 + 104, iYPos + 87 + 19, usFillColorLight );
|
|
ColorFillVideoSurfaceArea(FRAME_BUFFER, iXPos + 129, iYPos + 87, iXPos + 128 + 103, iYPos + 87 + 18, usFillColorTextBk );
|
|
iXOff = (105 - StringPixLength( EditMercAttitudes[pSoldier->aiData.bAttitude], FONT12POINT1 )) / 2;
|
|
gprintf( iXPos + 130 + iXOff, iYPos + 90, L"%s", EditMercAttitudes[pSoldier->aiData.bAttitude] );
|
|
|
|
// Get stats
|
|
iEditStat[0] = pSoldier->stats.bLifeMax; // 12 13
|
|
iEditStat[1] = pSoldier->stats.bLife; // 14 15
|
|
iEditStat[2] = pSoldier->stats.bStrength; // 16 17
|
|
iEditStat[3] = pSoldier->stats.bAgility; // 18 19
|
|
iEditStat[4] = pSoldier->stats.bDexterity; // 20 21
|
|
iEditStat[5] = pSoldier->stats.bLeadership; // 22 23
|
|
iEditStat[6] = pSoldier->stats.bWisdom; // 24 25
|
|
iEditStat[7] = pSoldier->stats.bMarksmanship; // 26 27
|
|
iEditStat[8] = pSoldier->stats.bExplosive; // 28 29
|
|
iEditStat[9] = pSoldier->stats.bMedical; // 30 31
|
|
iEditStat[10] = pSoldier->stats.bScientific; // 32 33
|
|
iEditStat[11] = pSoldier->stats.bExpLevel; // 34 35
|
|
|
|
// Stat value windows
|
|
for ( x = 0; x < 12; x++ )
|
|
{
|
|
gprintf( iXPos + 6, iYPos + 114 + (20 * x), L"%s", EditMercStat[x] );
|
|
ColorFillVideoSurfaceArea(FRAME_BUFFER, iXPos + 116, iYPos + 110 + (20 * x), iXPos + 116 + 30, iYPos + 110 + (20 * x) + 19, usFillColorDark );
|
|
ColorFillVideoSurfaceArea(FRAME_BUFFER, iXPos + 117, iYPos + 111 + (20 * x), iXPos + 116 + 30, iYPos + 111 + (20 * x) + 19, usFillColorLight );
|
|
ColorFillVideoSurfaceArea(FRAME_BUFFER, iXPos + 117, iYPos + 111 + (20 * x), iXPos + 116 + 29, iYPos + 111 + (20 * x) + 18, usFillColorTextBk );
|
|
|
|
swprintf( TempString, L"%d", iEditStat[x] );
|
|
iXOff = (30 - StringPixLength( TempString, FONT12POINT1 )) / 2;
|
|
gprintf( iXPos + 118 + iXOff, iYPos + 114 + (20 * x), L"%s", TempString );
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------------------------
|
|
// IsMercHere
|
|
//
|
|
// Checks for a soldier at the given map coordinates. If there is one, it returns it's ID number,
|
|
// otherwise it returns -1.
|
|
//
|
|
INT32 IsMercHere( INT32 iMapIndex )
|
|
{
|
|
INT32 IDNumber;
|
|
INT32 RetIDNumber;
|
|
SOLDIERTYPE *pSoldier;
|
|
BOOLEAN fSoldierFound;
|
|
|
|
RetIDNumber = -1;
|
|
fSoldierFound = FALSE;
|
|
for ( IDNumber = 0; IDNumber < MAX_NUM_SOLDIERS && !fSoldierFound; IDNumber++ )
|
|
{
|
|
if ( GetSoldier( &pSoldier, (INT16)IDNumber ) )
|
|
{
|
|
if ( pSoldier->sGridNo == iMapIndex )
|
|
{
|
|
fSoldierFound = TRUE;
|
|
RetIDNumber = IDNumber;
|
|
}
|
|
}
|
|
}
|
|
|
|
return( RetIDNumber );
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------------------------
|
|
//----------------------------------------------------------------------------------------------
|
|
// The following are the button callback functions for the merc editing pages
|
|
//----------------------------------------------------------------------------------------------
|
|
//----------------------------------------------------------------------------------------------
|
|
|
|
void EditMercChangeToStatsPageCallback(GUI_BUTTON *btn,INT32 reason)
|
|
{
|
|
if (reason & MSYS_CALLBACK_REASON_LBUTTON_UP)
|
|
{
|
|
iEditStatTimer = 0;
|
|
iEditMercMode = EDIT_MERC_TO_STATS;
|
|
}
|
|
}
|
|
|
|
|
|
void EditMercChangeToColorPageCallback(GUI_BUTTON *btn,INT32 reason)
|
|
{
|
|
if (reason & MSYS_CALLBACK_REASON_LBUTTON_UP)
|
|
{
|
|
iEditStatTimer = 0;
|
|
iEditMercMode = EDIT_MERC_TO_COLOR;
|
|
}
|
|
}
|
|
|
|
void EditMercDoneEditCallback(GUI_BUTTON *btn,INT32 reason)
|
|
{
|
|
if (reason & MSYS_CALLBACK_REASON_LBUTTON_UP)
|
|
{
|
|
iEditStatTimer = 0;
|
|
iEditMercMode = EDIT_MERC_DONE;
|
|
}
|
|
}
|
|
|
|
|
|
void EditMercBkgrndCallback(GUI_BUTTON *btn,INT32 reason)
|
|
{
|
|
if (reason & MSYS_CALLBACK_REASON_RBUTTON_DWN)
|
|
{
|
|
iEditStatTimer = 0;
|
|
iEditMercMode = EDIT_MERC_DONE;
|
|
}
|
|
}
|
|
|
|
|
|
void EditMercPrevOrderCallback(GUI_BUTTON *btn,INT32 reason)
|
|
{
|
|
if (reason & MSYS_CALLBACK_REASON_LBUTTON_UP)
|
|
{
|
|
btn->uiFlags |= BUTTON_CLICKED_ON;
|
|
iEditStatTimer = 0;
|
|
iEditMercMode = EDIT_MERC_PREV_ORDER;
|
|
}
|
|
}
|
|
|
|
|
|
void EditMercNextOrderCallback(GUI_BUTTON *btn,INT32 reason)
|
|
{
|
|
if (reason & MSYS_CALLBACK_REASON_LBUTTON_UP)
|
|
{
|
|
btn->uiFlags |= BUTTON_CLICKED_ON;
|
|
iEditStatTimer = 0;
|
|
iEditMercMode = EDIT_MERC_NEXT_ORDER;
|
|
}
|
|
}
|
|
|
|
void EditMercPrevAttCallback(GUI_BUTTON *btn,INT32 reason)
|
|
{
|
|
if (reason & MSYS_CALLBACK_REASON_LBUTTON_UP)
|
|
{
|
|
btn->uiFlags |= BUTTON_CLICKED_ON;
|
|
iEditStatTimer = 0;
|
|
iEditMercMode = EDIT_MERC_PREV_ATT;
|
|
}
|
|
}
|
|
|
|
void EditMercNextAttCallback(GUI_BUTTON *btn,INT32 reason)
|
|
{
|
|
if (reason & MSYS_CALLBACK_REASON_LBUTTON_UP)
|
|
{
|
|
btn->uiFlags |= BUTTON_CLICKED_ON;
|
|
iEditStatTimer = 0;
|
|
iEditMercMode = EDIT_MERC_NEXT_ATT;
|
|
}
|
|
}
|
|
|
|
void EditMercStatUpCallback(GUI_BUTTON *btn,INT32 reason)
|
|
{
|
|
INT32 iBtn;
|
|
|
|
if (reason & MSYS_CALLBACK_REASON_LBUTTON_UP)
|
|
{
|
|
iEditWhichStat = -1;
|
|
for ( iBtn = 0; iBtn < 36 && iEditWhichStat == -1; iBtn++ )
|
|
{
|
|
if ( btn->IDNum == iEditorButton[iBtn] )
|
|
iEditWhichStat = iBtn;
|
|
}
|
|
|
|
if ( iEditWhichStat != -1 )
|
|
{
|
|
iEditStatTimer = 0;
|
|
iEditMercMode = EDIT_MERC_INC_STAT;
|
|
}
|
|
|
|
btn->uiFlags |= BUTTON_CLICKED_ON;
|
|
}
|
|
else if (reason & MSYS_CALLBACK_REASON_LBUTTON_UP)
|
|
{
|
|
iEditStatTimer = 0;
|
|
iEditMercMode = EDIT_MERC_NONE;
|
|
btn->uiFlags &= (~BUTTON_CLICKED_ON);
|
|
}
|
|
}
|
|
|
|
void EditMercStatDwnCallback(GUI_BUTTON *btn,INT32 reason)
|
|
{
|
|
INT32 iBtn;
|
|
|
|
if (reason & MSYS_CALLBACK_REASON_LBUTTON_UP)
|
|
{
|
|
iEditWhichStat = -1;
|
|
for ( iBtn = 0; iBtn < 36 && iEditWhichStat == -1; iBtn++ )
|
|
{
|
|
if ( btn->IDNum == iEditorButton[iBtn] )
|
|
iEditWhichStat = iBtn;
|
|
}
|
|
|
|
if ( iEditWhichStat != -1 )
|
|
{
|
|
iEditStatTimer = 0;
|
|
iEditMercMode = EDIT_MERC_DEC_STAT;
|
|
}
|
|
|
|
btn->uiFlags |= BUTTON_CLICKED_ON;
|
|
}
|
|
else if (reason & MSYS_CALLBACK_REASON_LBUTTON_UP)
|
|
{
|
|
iEditStatTimer = 0;
|
|
iEditMercMode = EDIT_MERC_NONE;
|
|
btn->uiFlags &= (~BUTTON_CLICKED_ON);
|
|
}
|
|
}
|
|
|
|
|
|
void EditMercSetDirCallback(GUI_BUTTON *btn,INT32 reason)
|
|
{
|
|
INT32 iBtn;
|
|
|
|
if (reason & MSYS_CALLBACK_REASON_LBUTTON_UP)
|
|
{
|
|
iEditWhichStat = -1;
|
|
for ( iBtn = 0; iBtn < 36 && iEditWhichStat == -1; iBtn++ )
|
|
{
|
|
if ( btn->IDNum == iEditorButton[iBtn] )
|
|
iEditWhichStat = iBtn;
|
|
}
|
|
|
|
if ( iEditWhichStat != -1 )
|
|
{
|
|
iEditStatTimer = 0;
|
|
iEditMercMode = EDIT_MERC_SET_DIR;
|
|
}
|
|
|
|
btn->uiFlags |= BUTTON_CLICKED_ON;
|
|
}
|
|
}
|
|
|
|
|
|
void EditMercCenterCallback(GUI_BUTTON *btn,INT32 reason)
|
|
{
|
|
if (reason & MSYS_CALLBACK_REASON_LBUTTON_UP)
|
|
{
|
|
iEditStatTimer = 0;
|
|
iEditMercMode = EDIT_MERC_FIND;
|
|
|
|
btn->uiFlags |= BUTTON_CLICKED_ON;
|
|
}
|
|
}
|
|
|
|
|
|
void EditMercColorDwnCallback(GUI_BUTTON *btn,INT32 reason)
|
|
{
|
|
INT32 iBtn;
|
|
|
|
if (reason & MSYS_CALLBACK_REASON_LBUTTON_UP)
|
|
{
|
|
iEditWhichStat = -1;
|
|
for ( iBtn = 0; iBtn < 8 && iEditWhichStat == -1; iBtn++ )
|
|
{
|
|
if ( btn->IDNum == iEditorButton[iBtn] )
|
|
iEditWhichStat = iBtn;
|
|
}
|
|
|
|
if ( iEditWhichStat != -1 )
|
|
{
|
|
iEditStatTimer = 0;
|
|
iEditMercMode = EDIT_MERC_PREV_COLOR;
|
|
}
|
|
|
|
btn->uiFlags |= BUTTON_CLICKED_ON;
|
|
}
|
|
}
|
|
|
|
void MercsToggleColorModeCallback( GUI_BUTTON *btn, INT32 reason )
|
|
{
|
|
if( reason & MSYS_CALLBACK_REASON_LBUTTON_UP )
|
|
{
|
|
if( btn->uiFlags & BUTTON_CLICKED_ON ) //button is checked
|
|
{
|
|
EnableEditorButtons( FIRST_MERCS_COLOR_BUTTON, LAST_MERCS_COLOR_BUTTON );
|
|
gpSelected->pDetailedPlacement->fVisible = TRUE;
|
|
sprintf( gpSelected->pDetailedPlacement->HeadPal, gpSelected->pSoldier->HeadPal );
|
|
sprintf( gpSelected->pDetailedPlacement->SkinPal, gpSelected->pSoldier->SkinPal );
|
|
sprintf( gpSelected->pDetailedPlacement->VestPal, gpSelected->pSoldier->VestPal );
|
|
sprintf( gpSelected->pDetailedPlacement->PantsPal, gpSelected->pSoldier->PantsPal );
|
|
}
|
|
else //button is unchecked.
|
|
{
|
|
DisableEditorButtons( FIRST_MERCS_COLOR_BUTTON, LAST_MERCS_COLOR_BUTTON );
|
|
gpSelected->pDetailedPlacement->fVisible = FALSE;
|
|
}
|
|
gfRenderMercInfo = TRUE;
|
|
gfRenderTaskbar = TRUE;
|
|
}
|
|
}
|
|
|
|
void MercsSetColorsCallback( GUI_BUTTON *btn, INT32 reason )
|
|
{
|
|
INT32 iBtn;
|
|
if (reason & MSYS_CALLBACK_REASON_LBUTTON_UP)
|
|
{
|
|
iEditWhichStat = -1;
|
|
for ( iBtn = FIRST_MERCS_COLOR_BUTTON; iBtn <= LAST_MERCS_COLOR_BUTTON; iBtn++ )
|
|
{
|
|
if ( btn->IDNum == iEditorButton[iBtn] )
|
|
{
|
|
iEditWhichStat = iBtn - FIRST_MERCS_COLOR_BUTTON;
|
|
iEditStatTimer = 0;
|
|
iEditMercMode = EDIT_MERC_NEXT_COLOR;
|
|
gfRenderMercInfo = TRUE;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void MercsSetBodyTypeCallback( GUI_BUTTON *btn, INT32 reason )
|
|
{
|
|
if( reason & MSYS_CALLBACK_REASON_LBUTTON_UP )
|
|
{
|
|
gfRenderMercInfo = TRUE;
|
|
if( btn->IDNum == iEditorButton[ MERCS_BODYTYPE_DOWN ] )
|
|
ChangeBodyType( 1 ); //next
|
|
else
|
|
ChangeBodyType( -1 ); //previous
|
|
}
|
|
}
|
|
|
|
void EditMercDecDifficultyCallback(GUI_BUTTON *btn,INT32 reason)
|
|
{
|
|
if(reason & MSYS_CALLBACK_REASON_LBUTTON_UP)
|
|
{
|
|
btn->uiFlags |= BUTTON_CLICKED_ON;
|
|
|
|
iEditorToolbarState = TBAR_MODE_DEC_DIFF;
|
|
}
|
|
}
|
|
|
|
|
|
void EditMercIncDifficultyCallback(GUI_BUTTON *btn,INT32 reason)
|
|
{
|
|
if(reason & MSYS_CALLBACK_REASON_LBUTTON_UP)
|
|
{
|
|
btn->uiFlags |= BUTTON_CLICKED_ON;
|
|
|
|
iEditorToolbarState = TBAR_MODE_INC_DIFF;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------------------------
|
|
// ShowEditMercPalettes
|
|
//
|
|
// Displays the palette of the given merc (used by the edit merc color page)
|
|
//
|
|
void ShowEditMercPalettes( SOLDIERTYPE *pSoldier )
|
|
{
|
|
UINT8 ubPaletteRep;
|
|
if( !pSoldier )
|
|
ubPaletteRep = 0xff;
|
|
|
|
if( pSoldier )
|
|
{
|
|
if( !strlen( pSoldier->HeadPal ) )
|
|
ubPaletteRep = 0xff;
|
|
else
|
|
GetPaletteRepIndexFromID( pSoldier->HeadPal, &ubPaletteRep );
|
|
}
|
|
ShowEditMercColorSet( ubPaletteRep, 0 );
|
|
|
|
if( pSoldier )
|
|
{
|
|
if( !strlen( pSoldier->SkinPal ) )
|
|
ubPaletteRep = 0xff;
|
|
else
|
|
GetPaletteRepIndexFromID( pSoldier->SkinPal, &ubPaletteRep );
|
|
}
|
|
ShowEditMercColorSet( ubPaletteRep, 1 );
|
|
|
|
if( pSoldier )
|
|
{
|
|
if( !strlen( pSoldier->VestPal ) )
|
|
ubPaletteRep = 0xff;
|
|
else
|
|
GetPaletteRepIndexFromID( pSoldier->VestPal, &ubPaletteRep );
|
|
}
|
|
ShowEditMercColorSet( ubPaletteRep, 2 );
|
|
|
|
if( pSoldier )
|
|
{
|
|
if( !strlen( pSoldier->VestPal ) )
|
|
ubPaletteRep = 0xff;
|
|
else
|
|
GetPaletteRepIndexFromID( pSoldier->PantsPal, &ubPaletteRep );
|
|
}
|
|
ShowEditMercColorSet( ubPaletteRep, 3 );
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------------------------
|
|
// ShowEditMercColorSet
|
|
//
|
|
// Displays a single palette set. (used by ShowEditMercPalettes)
|
|
//
|
|
void ShowEditMercColorSet( UINT8 ubPaletteRep, INT16 sSet )
|
|
{
|
|
UINT16 us16BPPColor, usFillColorDark, usFillColorLight;
|
|
UINT8 cnt1;
|
|
UINT8 ubSize;
|
|
INT16 sUnitSize;
|
|
INT16 sLeft, sTop, sRight, sBottom;
|
|
|
|
if( ubPaletteRep == 0xff )
|
|
ubSize = 16;
|
|
else
|
|
ubSize = gpPalRep[ ubPaletteRep ].ubPaletteSize;
|
|
|
|
sUnitSize = 128 / (INT16)(ubSize);
|
|
|
|
sTop = 2 * iScreenHeightOffset + 364 + (sSet * 24);
|
|
sBottom = sTop + 20;
|
|
sLeft = iScreenWidthOffset + 230;
|
|
sRight = iScreenWidthOffset + 359;
|
|
|
|
usFillColorDark = Get16BPPColor(FROMRGB(24, 61, 81));
|
|
usFillColorLight = Get16BPPColor(FROMRGB(136, 138, 135));
|
|
|
|
// Draw color bar window area
|
|
ColorFillVideoSurfaceArea(FRAME_BUFFER, sLeft, sTop, sRight, sBottom, usFillColorDark );
|
|
ColorFillVideoSurfaceArea(FRAME_BUFFER, sLeft + 1, sTop + 1, sRight, sBottom, usFillColorLight );
|
|
InvalidateRegion( sLeft, sTop, sRight, sBottom );
|
|
|
|
sTop++;
|
|
sBottom--;
|
|
sLeft++;
|
|
sRight = sLeft + sUnitSize;
|
|
|
|
// Draw the color bar
|
|
for ( cnt1 = 0; cnt1 < ubSize; cnt1++ )
|
|
{
|
|
if (cnt1 == (ubSize - 1) )
|
|
sRight = iScreenWidthOffset + 358;
|
|
if( ubPaletteRep == 0xff )
|
|
us16BPPColor = Get16BPPColor( FROMRGB( (16 - cnt1)*10, (16 - cnt1)*10, (16 - cnt1)*10 ) );
|
|
else
|
|
us16BPPColor = Get16BPPColor( FROMRGB( gpPalRep[ ubPaletteRep ].r[ cnt1 ], gpPalRep[ ubPaletteRep ].g[ cnt1 ], gpPalRep[ ubPaletteRep ].b[ cnt1 ] ) );
|
|
ColorFillVideoSurfaceArea( FRAME_BUFFER, sLeft, sTop, sRight, sBottom, us16BPPColor );
|
|
|
|
sLeft += sUnitSize;
|
|
sRight += sUnitSize;
|
|
}
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------------------------
|
|
// DisplayWayPoints
|
|
//
|
|
// Displays the way points of the currently selected merc.
|
|
//
|
|
void DisplayWayPoints(void)
|
|
{
|
|
INT16 sX,sY;
|
|
INT16 sXMapPos,sYMapPos;
|
|
INT16 sScreenX,sScreenY;
|
|
FLOAT ScrnX,ScrnY,dOffsetX,dOffsetY;
|
|
INT8 bPoint;
|
|
SOLDIERTYPE *pSoldier;
|
|
INT32 sGridNo;
|
|
|
|
|
|
if ( gsSelectedMercID == -1 || (gsSelectedMercID <= (INT32)gTacticalStatus.Team[ OUR_TEAM ].bLastID) || gsSelectedMercID >= MAXMERCS )
|
|
return;
|
|
|
|
GetSoldier( &pSoldier, (UINT16)gsSelectedMercID );
|
|
if ( pSoldier == NULL || !pSoldier->bActive)
|
|
return;
|
|
|
|
// point 0 is not used!
|
|
for ( bPoint = 1; bPoint <= pSoldier->aiData.bPatrolCnt; bPoint++ )
|
|
{
|
|
// Get the next point
|
|
sGridNo = pSoldier->aiData.sPatrolGrid[bPoint];
|
|
|
|
// Can we see it?
|
|
if ( !GridNoOnVisibleWorldTile( sGridNo ) )
|
|
continue;
|
|
|
|
if((sGridNo < 0) || (sGridNo > WORLD_MAX))
|
|
continue;
|
|
|
|
// Convert it's location to screen coordinates
|
|
ConvertGridNoToXY( sGridNo, &sXMapPos, &sYMapPos );
|
|
|
|
dOffsetX = (FLOAT)(sXMapPos * CELL_X_SIZE) - gsRenderCenterX;
|
|
dOffsetY = (FLOAT)(sYMapPos * CELL_Y_SIZE) - gsRenderCenterY;
|
|
|
|
FloatFromCellToScreenCoordinates( dOffsetX, dOffsetY, &ScrnX, &ScrnY);
|
|
|
|
sScreenX = ( ( gsVIEWPORT_END_X - gsVIEWPORT_START_X ) /2 ) + (INT16)ScrnX;
|
|
sScreenY = ( ( gsVIEWPORT_END_Y - gsVIEWPORT_START_Y ) /2 ) + (INT16)ScrnY;
|
|
|
|
// Adjust for tiles height factor!
|
|
sScreenY -= gpWorldLevelData[sGridNo].sHeight;
|
|
// Bring it down a touch
|
|
sScreenY += 5;
|
|
|
|
if( sScreenY <= (2 * iScreenHeightOffset + 355 ))
|
|
{
|
|
// Shown it on screen!
|
|
SetFont(TINYFONT1);
|
|
if( pSoldier->pathing.bLevel == 1 )
|
|
{
|
|
SetFontBackground( FONT_LTBLUE );
|
|
sScreenY -= 68;
|
|
}
|
|
else
|
|
SetFontBackground( FONT_LTRED );
|
|
SetFontForeground( FONT_WHITE );
|
|
VarFindFontCenterCoordinates( sScreenX, sScreenY, 1, 1, TINYFONT1, &sX, &sY, L"%d", bPoint );
|
|
mprintf(sX,sY,L"%d",bPoint);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void CreateEditMercWindow( void )
|
|
{
|
|
INT32 iXPos, iYPos, iHeight, iWidth;
|
|
INT32 x;
|
|
SOLDIERTYPE *pSoldier;
|
|
|
|
iWidth = 266;
|
|
iHeight = 360;
|
|
iYPos = iScreenHeightOffset + 0;
|
|
iXPos = iScreenWidthOffset + 0;
|
|
|
|
|
|
GetSoldier( &pSoldier, (INT16)gsSelectedMercID );
|
|
iEditMercLocation = (INT32)pSoldier->sGridNo;
|
|
gpWorldLevelData[ iEditMercLocation ].pObjectHead->ubShadeLevel = DEFAULT_SHADE_LEVEL;
|
|
|
|
iEditMercBkgrndArea = CreateHotSpot((INT16)iXPos, (INT16)iYPos, (INT16)iWidth, (INT16)iHeight, MSYS_PRIORITY_NORMAL, DEFAULT_MOVE_CALLBACK, EditMercBkgrndCallback );
|
|
|
|
iEditMercColorPage = CreateTextButton( pCreateEditMercWindowText[0], (INT16)FONT12POINT1, FONT_BLACK, FONT_BLACK,
|
|
BUTTON_USE_DEFAULT, (INT16)(iXPos + 183), (INT16)(iYPos + 315), 80, 20, BUTTON_NO_TOGGLE, MSYS_PRIORITY_NORMAL + 1, DEFAULT_MOVE_CALLBACK, EditMercChangeToColorPageCallback );
|
|
iEditMercEnd = CreateTextButton( pCreateEditMercWindowText[1], (INT16)FONT12POINT1, FONT_MCOLOR_BLACK, FONT_BLACK,
|
|
BUTTON_USE_DEFAULT, (INT16)(iXPos + 183), (INT16)(iYPos + 337), 80, 20, BUTTON_NO_TOGGLE, MSYS_PRIORITY_NORMAL + 1, DEFAULT_MOVE_CALLBACK, EditMercDoneEditCallback );
|
|
|
|
// Disable color editing for PC Mercs
|
|
if ( (UINT16)gsSelectedMercID >= gTacticalStatus.Team[ OUR_TEAM ].bFirstID && (UINT16)gsSelectedMercID <= gTacticalStatus.Team[ OUR_TEAM ].bLastID )
|
|
DisableButton( iEditMercColorPage );
|
|
|
|
iEditorButton[8] = QuickCreateButton( giEditMercImage[0], (INT16)(iXPos + 98), (INT16)(iYPos + 51), BUTTON_NO_TOGGLE, MSYS_PRIORITY_NORMAL + 1, DEFAULT_MOVE_CALLBACK, EditMercPrevOrderCallback );
|
|
iEditorButton[9] = QuickCreateButton( giEditMercImage[1], (INT16)(iXPos + 233), (INT16)(iYPos + 51), BUTTON_NO_TOGGLE, MSYS_PRIORITY_NORMAL + 1, DEFAULT_MOVE_CALLBACK, EditMercNextOrderCallback );
|
|
SetButtonFastHelpText( iEditorButton[8], pCreateEditMercWindowText[2] );
|
|
SetButtonFastHelpText( iEditorButton[9], pCreateEditMercWindowText[3] );
|
|
|
|
iEditorButton[10] = QuickCreateButton( giEditMercImage[0], (INT16)(iXPos + 98), (INT16)(iYPos + 86), BUTTON_NO_TOGGLE, MSYS_PRIORITY_NORMAL + 1, DEFAULT_MOVE_CALLBACK, EditMercPrevAttCallback );
|
|
iEditorButton[11] = QuickCreateButton( giEditMercImage[1], (INT16)(iXPos + 233), (INT16)(iYPos + 86), BUTTON_NO_TOGGLE, MSYS_PRIORITY_NORMAL + 1, DEFAULT_MOVE_CALLBACK, EditMercNextAttCallback );
|
|
SetButtonFastHelpText( iEditorButton[10], pCreateEditMercWindowText[4] );
|
|
SetButtonFastHelpText( iEditorButton[11], pCreateEditMercWindowText[5] );
|
|
|
|
iEditorButton[12] = QuickCreateButton( giEditMercImage[0], (INT16)(iXPos + 86), (INT16)(iYPos + 110), BUTTON_NO_TOGGLE, MSYS_PRIORITY_NORMAL + 1, DEFAULT_MOVE_CALLBACK, EditMercStatDwnCallback );
|
|
iEditorButton[13] = QuickCreateButton( giEditMercImage[1], (INT16)(iXPos + 146), (INT16)(iYPos + 110), BUTTON_NO_TOGGLE, MSYS_PRIORITY_NORMAL + 1, DEFAULT_MOVE_CALLBACK, EditMercStatUpCallback );
|
|
|
|
iEditorButton[14] = QuickCreateButton( giEditMercImage[0], (INT16)(iXPos + 86), (INT16)(iYPos + 130), BUTTON_NO_TOGGLE, MSYS_PRIORITY_NORMAL + 1, DEFAULT_MOVE_CALLBACK, EditMercStatDwnCallback );
|
|
iEditorButton[15] = QuickCreateButton( giEditMercImage[1], (INT16)(iXPos + 146), (INT16)(iYPos + 130), BUTTON_NO_TOGGLE, MSYS_PRIORITY_NORMAL + 1, DEFAULT_MOVE_CALLBACK, EditMercStatUpCallback );
|
|
|
|
iEditorButton[16] = QuickCreateButton( giEditMercImage[0], (INT16)(iXPos + 86), (INT16)(iYPos + 150), BUTTON_NO_TOGGLE, MSYS_PRIORITY_NORMAL + 1, DEFAULT_MOVE_CALLBACK, EditMercStatDwnCallback );
|
|
iEditorButton[17] = QuickCreateButton( giEditMercImage[1], (INT16)(iXPos + 146), (INT16)(iYPos + 150), BUTTON_NO_TOGGLE, MSYS_PRIORITY_NORMAL + 1, DEFAULT_MOVE_CALLBACK, EditMercStatUpCallback );
|
|
|
|
iEditorButton[18] = QuickCreateButton( giEditMercImage[0], (INT16)(iXPos + 86), (INT16)(iYPos + 170), BUTTON_NO_TOGGLE, MSYS_PRIORITY_NORMAL + 1, DEFAULT_MOVE_CALLBACK, EditMercStatDwnCallback );
|
|
iEditorButton[19] = QuickCreateButton( giEditMercImage[1], (INT16)(iXPos + 146), (INT16)(iYPos + 170), BUTTON_NO_TOGGLE, MSYS_PRIORITY_NORMAL + 1, DEFAULT_MOVE_CALLBACK, EditMercStatUpCallback );
|
|
|
|
iEditorButton[20] = QuickCreateButton( giEditMercImage[0], (INT16)(iXPos + 86), (INT16)(iYPos + 190), BUTTON_NO_TOGGLE, MSYS_PRIORITY_NORMAL + 1, DEFAULT_MOVE_CALLBACK, EditMercStatDwnCallback );
|
|
iEditorButton[21] = QuickCreateButton( giEditMercImage[1], (INT16)(iXPos + 146), (INT16)(iYPos + 190), BUTTON_NO_TOGGLE, MSYS_PRIORITY_NORMAL + 1, DEFAULT_MOVE_CALLBACK, EditMercStatUpCallback );
|
|
|
|
iEditorButton[22] = QuickCreateButton( giEditMercImage[0], (INT16)(iXPos + 86), (INT16)(iYPos + 210), BUTTON_NO_TOGGLE, MSYS_PRIORITY_NORMAL + 1, DEFAULT_MOVE_CALLBACK, EditMercStatDwnCallback );
|
|
iEditorButton[23] = QuickCreateButton( giEditMercImage[1], (INT16)(iXPos + 146), (INT16)(iYPos + 210), BUTTON_NO_TOGGLE, MSYS_PRIORITY_NORMAL + 1, DEFAULT_MOVE_CALLBACK, EditMercStatUpCallback );
|
|
|
|
iEditorButton[24] = QuickCreateButton( giEditMercImage[0], (INT16)(iXPos + 86), (INT16)(iYPos + 230), BUTTON_NO_TOGGLE, MSYS_PRIORITY_NORMAL + 1, DEFAULT_MOVE_CALLBACK, EditMercStatDwnCallback );
|
|
iEditorButton[25] = QuickCreateButton( giEditMercImage[1], (INT16)(iXPos + 146), (INT16)(iYPos + 230), BUTTON_NO_TOGGLE, MSYS_PRIORITY_NORMAL + 1, DEFAULT_MOVE_CALLBACK, EditMercStatUpCallback );
|
|
|
|
iEditorButton[26] = QuickCreateButton( giEditMercImage[0], (INT16)(iXPos + 86), (INT16)(iYPos + 250), BUTTON_NO_TOGGLE, MSYS_PRIORITY_NORMAL + 1, DEFAULT_MOVE_CALLBACK, EditMercStatDwnCallback );
|
|
iEditorButton[27] = QuickCreateButton( giEditMercImage[1], (INT16)(iXPos + 146), (INT16)(iYPos + 250), BUTTON_NO_TOGGLE, MSYS_PRIORITY_NORMAL + 1, DEFAULT_MOVE_CALLBACK, EditMercStatUpCallback );
|
|
|
|
iEditorButton[28] = QuickCreateButton( giEditMercImage[0], (INT16)(iXPos + 86), (INT16)(iYPos + 270), BUTTON_NO_TOGGLE, MSYS_PRIORITY_NORMAL + 1, DEFAULT_MOVE_CALLBACK, EditMercStatDwnCallback );
|
|
iEditorButton[29] = QuickCreateButton( giEditMercImage[1], (INT16)(iXPos + 146), (INT16)(iYPos + 270), BUTTON_NO_TOGGLE, MSYS_PRIORITY_NORMAL + 1, DEFAULT_MOVE_CALLBACK, EditMercStatUpCallback );
|
|
|
|
iEditorButton[30] = QuickCreateButton( giEditMercImage[0], (INT16)(iXPos + 86), (INT16)(iYPos + 290), BUTTON_NO_TOGGLE, MSYS_PRIORITY_NORMAL + 1, DEFAULT_MOVE_CALLBACK, EditMercStatDwnCallback );
|
|
iEditorButton[31] = QuickCreateButton( giEditMercImage[1], (INT16)(iXPos + 146), (INT16)(iYPos + 290), BUTTON_NO_TOGGLE, MSYS_PRIORITY_NORMAL + 1, DEFAULT_MOVE_CALLBACK, EditMercStatUpCallback );
|
|
|
|
iEditorButton[32] = QuickCreateButton( giEditMercImage[0], (INT16)(iXPos + 86), (INT16)(iYPos + 310), BUTTON_NO_TOGGLE, MSYS_PRIORITY_NORMAL + 1, DEFAULT_MOVE_CALLBACK, EditMercStatDwnCallback );
|
|
iEditorButton[33] = QuickCreateButton( giEditMercImage[1], (INT16)(iXPos + 146), (INT16)(iYPos + 310), BUTTON_NO_TOGGLE, MSYS_PRIORITY_NORMAL + 1, DEFAULT_MOVE_CALLBACK, EditMercStatUpCallback );
|
|
|
|
iEditorButton[34] = QuickCreateButton( giEditMercImage[0], (INT16)(iXPos + 86), (INT16)(iYPos + 330), BUTTON_NO_TOGGLE, MSYS_PRIORITY_NORMAL + 1, DEFAULT_MOVE_CALLBACK, EditMercStatDwnCallback );
|
|
iEditorButton[35] = QuickCreateButton( giEditMercImage[1], (INT16)(iXPos + 146), (INT16)(iYPos + 330), BUTTON_NO_TOGGLE, MSYS_PRIORITY_NORMAL + 1, DEFAULT_MOVE_CALLBACK, EditMercStatUpCallback );
|
|
|
|
for ( x = 12; x < 36; x += 2 )
|
|
{
|
|
SetButtonFastHelpText( iEditorButton[x], pCreateEditMercWindowText[6] );
|
|
SetButtonFastHelpText( iEditorButton[x + 1], pCreateEditMercWindowText[7] );
|
|
}
|
|
}
|
|
void SetMercOrders( INT8 bOrders )
|
|
{
|
|
gpSelected->pSoldier->aiData.bOrders = bOrders;
|
|
gpSelected->pBasicPlacement->bOrders = bOrders;
|
|
UnclickEditorButtons( FIRST_MERCS_ORDERS_BUTTON, LAST_MERCS_ORDERS_BUTTON );
|
|
ClickEditorButton( FIRST_MERCS_ORDERS_BUTTON + bOrders );
|
|
gbDefaultOrders = bOrders;
|
|
}
|
|
|
|
void SetMercAttitude( INT8 bAttitude )
|
|
{
|
|
gpSelected->pSoldier->aiData.bAttitude = bAttitude;
|
|
gpSelected->pBasicPlacement->bAttitude = bAttitude;
|
|
UnclickEditorButtons( FIRST_MERCS_ATTITUDE_BUTTON, LAST_MERCS_ATTITUDE_BUTTON );
|
|
ClickEditorButton( FIRST_MERCS_ATTITUDE_BUTTON + bAttitude );
|
|
gbDefaultAttitude = bAttitude;
|
|
}
|
|
|
|
void SetMercDirection( INT8 bDirection )
|
|
{
|
|
UnclickEditorButtons( FIRST_MERCS_DIRECTION_BUTTON, LAST_MERCS_DIRECTION_BUTTON );
|
|
ClickEditorButton( FIRST_MERCS_DIRECTION_BUTTON + bDirection );
|
|
|
|
gbDefaultDirection = bDirection;
|
|
gpSelected->pBasicPlacement->ubDirection = bDirection;
|
|
|
|
// ATE: Changed these to call functions....
|
|
gpSelected->pSoldier->EVENT_SetSoldierDirection( bDirection );
|
|
gpSelected->pSoldier->EVENT_SetSoldierDesiredDirection( bDirection );
|
|
|
|
gpSelected->pSoldier->ConvertAniCodeToAniFrame( 0 );
|
|
}
|
|
|
|
void SetMercRelativeEquipment( INT8 bLevel )
|
|
{
|
|
gpSelected->pBasicPlacement->bRelativeEquipmentLevel = bLevel;
|
|
|
|
UnclickEditorButtons( FIRST_MERCS_REL_EQUIPMENT_BUTTON, LAST_MERCS_REL_EQUIPMENT_BUTTON );
|
|
ClickEditorButton( FIRST_MERCS_REL_EQUIPMENT_BUTTON + bLevel );
|
|
gbDefaultRelativeEquipmentLevel = bLevel;
|
|
}
|
|
|
|
void SetMercRelativeAttributes( INT8 bLevel )
|
|
{
|
|
gpSelected->pBasicPlacement->bRelativeAttributeLevel = bLevel;
|
|
//We also have to modify the existing soldier incase the user wishes to enter game.
|
|
ModifySoldierAttributesWithNewRelativeLevel( gpSelected->pSoldier, bLevel );
|
|
|
|
UnclickEditorButtons( FIRST_MERCS_REL_ATTRIBUTE_BUTTON, LAST_MERCS_REL_ATTRIBUTE_BUTTON );
|
|
ClickEditorButton( FIRST_MERCS_REL_ATTRIBUTE_BUTTON + bLevel );
|
|
gbDefaultRelativeAttributeLevel = bLevel;
|
|
}
|
|
|
|
void IndicateSelectedMerc( INT16 sID )
|
|
{
|
|
SOLDIERINITNODE *prev;
|
|
INT8 bTeam;
|
|
BOOLEAN fSelectPrevious;
|
|
|
|
//If we are trying to select a merc that is already selected, ignore.
|
|
if( sID >= 0 && sID == gsSelectedMercGridNo )
|
|
return;
|
|
|
|
//first remove the cursor of the previous merc.
|
|
//NOTE: It doesn't matter what the value is, even if a merc isn't selected.
|
|
//There is no need to validate the gridNo value, because it is always valid.
|
|
RemoveAllObjectsOfTypeRange( gsSelectedMercGridNo, CONFIRMMOVE, CONFIRMMOVE );
|
|
|
|
//This is very important, because clearing the merc editing mode actually,
|
|
//updates the edited merc. If this call isn't here, it is possible to update the
|
|
//newly selected merc with the wrong information.
|
|
SetMercEditingMode( MERC_NOMODE );
|
|
|
|
bTeam = -1;
|
|
|
|
// hotkey to select previous instead of next merc
|
|
fSelectPrevious = gfKeyState[ CTRL ];
|
|
|
|
//determine selection method
|
|
switch( sID )
|
|
{
|
|
case SELECT_NEXT_MERC:
|
|
prev = gpSelected;
|
|
if( gsSelectedMercID == -1 || !gpSelected )
|
|
{ //if no merc selected, then select the first one in list.
|
|
gpSelected = gSoldierInitHead;
|
|
}
|
|
else
|
|
{ //validate this merc in the list.
|
|
if( fSelectPrevious )
|
|
{
|
|
if( gpSelected->prev )
|
|
{ //select the prev merc in the list
|
|
gpSelected = gpSelected->prev;
|
|
}
|
|
else
|
|
{ //we are at the beginning of the list, so select the last merc in the list.
|
|
gpSelected = gSoldierInitTail;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if( gpSelected->next )
|
|
{ //select the next merc in the list
|
|
gpSelected = gpSelected->next;
|
|
}
|
|
else
|
|
{ //we are at the end of the list, so select the first merc in the list.
|
|
gpSelected = gSoldierInitHead;
|
|
}
|
|
}
|
|
}
|
|
if( !gpSelected ) //list is empty
|
|
{
|
|
SetMercEditability( TRUE );
|
|
SetMercEditingMode( MERC_TEAMMODE );
|
|
return;
|
|
}
|
|
while( gpSelected != prev )
|
|
{
|
|
if( !gpSelected )
|
|
{
|
|
if( fSelectPrevious )
|
|
gpSelected = gSoldierInitTail;
|
|
else
|
|
gpSelected = gSoldierInitHead;
|
|
continue;
|
|
}
|
|
if( gpSelected->pSoldier && gpSelected->pSoldier->bVisible == 1 )
|
|
{ //we have found a visible soldier, so select him.
|
|
break;
|
|
}
|
|
if( fSelectPrevious )
|
|
gpSelected = gpSelected->prev;
|
|
else
|
|
gpSelected = gpSelected->next;
|
|
}
|
|
//we have a valid merc now.
|
|
break;
|
|
case SELECT_NO_MERC:
|
|
SetMercEditability( TRUE );
|
|
gpSelected = NULL;
|
|
gsSelectedMercID = -1;
|
|
gsSelectedGridNo = 0;
|
|
SetMercEditingMode( MERC_TEAMMODE );
|
|
return; //we already deselected the previous merc.
|
|
case SELECT_NEXT_ENEMY:
|
|
bTeam = ENEMY_TEAM;
|
|
break;
|
|
case SELECT_NEXT_CREATURE:
|
|
bTeam = CREATURE_TEAM;
|
|
break;
|
|
case SELECT_NEXT_REBEL:
|
|
bTeam = MILITIA_TEAM;
|
|
break;
|
|
case SELECT_NEXT_CIV:
|
|
bTeam = CIV_TEAM;
|
|
break;
|
|
default:
|
|
//search for the merc with the specific ID.
|
|
gpSelected = FindSoldierInitNodeWithID( (UINT8)sID );
|
|
if( !gpSelected )
|
|
{
|
|
gsSelectedMercID = -1;
|
|
gsSelectedGridNo = 0;
|
|
SetMercEditability( TRUE );
|
|
SetMercEditingMode( MERC_TEAMMODE );
|
|
return; //Invalid merc ID.
|
|
}
|
|
break;
|
|
}
|
|
if( bTeam != -1 )
|
|
{ //We are searching for the next occurence of a particular team.
|
|
prev = gpSelected;
|
|
if( gsSelectedMercID == -1 || !gpSelected )
|
|
{ //if no merc selected, then select the first one in list.
|
|
gpSelected = gSoldierInitHead;
|
|
}
|
|
else
|
|
{ //validate this merc in the list.
|
|
if( fSelectPrevious )
|
|
{
|
|
if( gpSelected->prev )
|
|
{ //select the prev merc in the list
|
|
gpSelected = gpSelected->prev;
|
|
}
|
|
else
|
|
{ //we are at the beginning of the list, so select the last merc in the list.
|
|
gpSelected = gSoldierInitTail;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if( gpSelected->next )
|
|
{ //select the next merc in the list
|
|
gpSelected = gpSelected->next;
|
|
}
|
|
else
|
|
{ //we are at the end of the list, so select the first merc in the list.
|
|
gpSelected = gSoldierInitHead;
|
|
}
|
|
}
|
|
}
|
|
if( !gpSelected ) //list is empty
|
|
{
|
|
SetMercEditability( TRUE );
|
|
SetMercEditingMode( MERC_TEAMMODE );
|
|
return;
|
|
}
|
|
while( gpSelected != prev )
|
|
{
|
|
if( !gpSelected )
|
|
{
|
|
if( fSelectPrevious )
|
|
gpSelected = gSoldierInitTail;
|
|
else
|
|
gpSelected = gSoldierInitHead;
|
|
continue;
|
|
}
|
|
if( gpSelected->pSoldier && gpSelected->pSoldier->bVisible == 1 && gpSelected->pSoldier->bTeam == bTeam )
|
|
{ //we have found a visible soldier on the desired team, so select him.
|
|
break;
|
|
}
|
|
if( fSelectPrevious )
|
|
gpSelected = gpSelected->prev;
|
|
else
|
|
gpSelected = gpSelected->next;
|
|
}
|
|
if( !gpSelected )
|
|
return;
|
|
if( gpSelected == prev )
|
|
{ //we have cycled through the list already, so choose the same guy (if he is on the desired team)...
|
|
if( !gpSelected->pSoldier || gpSelected->pSoldier->bVisible != 1 || gpSelected->pSoldier->bTeam != bTeam )
|
|
{
|
|
SetMercEditability( TRUE );
|
|
SetMercEditingMode( MERC_TEAMMODE );
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
//if we made it this far, then we have a new merc cursor indicator to draw.
|
|
if( gpSelected && gpSelected->pSoldier )//dnl ch75 261013
|
|
gsSelectedMercGridNo = gpSelected->pSoldier->sGridNo;
|
|
else
|
|
{
|
|
SetMercEditability( TRUE );
|
|
SetMercEditingMode( MERC_TEAMMODE );
|
|
return;
|
|
}
|
|
gsSelectedMercID = gpSelected->pSoldier->ubID;
|
|
AddObjectToHead( gsSelectedMercGridNo, CONFIRMMOVE1 );
|
|
|
|
//If the merc has a valid profile, then turn off editability
|
|
if( gpSelected->pDetailedPlacement )
|
|
SetMercEditability( (BOOLEAN)(gpSelected->pDetailedPlacement->ubProfile == NO_PROFILE) );
|
|
else
|
|
SetMercEditability( TRUE );
|
|
|
|
if( sID < 0 )
|
|
{ //We want to center the screen on the next merc, and update the interface.
|
|
gsRenderCenterX = (INT16)gpSelected->pSoldier->dXPos;
|
|
gsRenderCenterY = (INT16)gpSelected->pSoldier->dYPos;
|
|
gfRenderWorld = TRUE;
|
|
}
|
|
|
|
//update the merc item slots to reflect what the merc currently has.
|
|
UpdateMercItemSlots();
|
|
|
|
//Whatever the case, we want to update the gui to press the appropriate buttons
|
|
//depending on the merc's attributes.
|
|
//Click the appropriate team button
|
|
UnclickEditorButton( MERCS_ENEMY );
|
|
UnclickEditorButton( MERCS_CREATURE );
|
|
UnclickEditorButton( MERCS_REBEL );
|
|
UnclickEditorButton( MERCS_CIVILIAN );
|
|
switch( gpSelected->pSoldier->bTeam )
|
|
{
|
|
case ENEMY_TEAM: ClickEditorButton( MERCS_ENEMY ); iDrawMode = DRAW_MODE_ENEMY; break;
|
|
case CREATURE_TEAM: ClickEditorButton( MERCS_CREATURE ); iDrawMode = DRAW_MODE_CREATURE; break;
|
|
case MILITIA_TEAM: ClickEditorButton( MERCS_REBEL ); iDrawMode = DRAW_MODE_REBEL; break;
|
|
case CIV_TEAM: ClickEditorButton( MERCS_CIVILIAN ); iDrawMode = DRAW_MODE_CIVILIAN; break;
|
|
}
|
|
//Update the editing mode
|
|
if( gpSelected->pDetailedPlacement )
|
|
SetMercEditingMode( gubLastDetailedMercMode );
|
|
else
|
|
SetMercEditingMode( MERC_BASICMODE );
|
|
//Determine which team button to press.
|
|
gfRenderMercInfo = TRUE;
|
|
//These calls will set the proper button states, even though it redundantly
|
|
//assigns the soldier with the same orders/attitude.
|
|
SetMercOrders( gpSelected->pSoldier->aiData.bOrders );
|
|
SetMercAttitude( gpSelected->pSoldier->aiData.bAttitude );
|
|
SetMercDirection( gpSelected->pSoldier->ubDirection );
|
|
if( gpSelected->pBasicPlacement->fPriorityExistance )
|
|
ClickEditorButton( MERCS_PRIORITYEXISTANCE_CHECKBOX );
|
|
else
|
|
UnclickEditorButton( MERCS_PRIORITYEXISTANCE_CHECKBOX );
|
|
if( gpSelected->pBasicPlacement->fHasKeys )
|
|
ClickEditorButton( MERCS_HASKEYS_CHECKBOX );
|
|
else
|
|
UnclickEditorButton( MERCS_HASKEYS_CHECKBOX );
|
|
if( gpSelected->pSoldier->ubProfile == NO_PROFILE )
|
|
{
|
|
SetMercRelativeEquipment( gpSelected->pBasicPlacement->bRelativeEquipmentLevel );
|
|
SetMercRelativeAttributes( gpSelected->pBasicPlacement->bRelativeAttributeLevel );
|
|
SetEnemyColorCode( gpSelected->pBasicPlacement->ubSoldierClass );
|
|
}
|
|
if( iDrawMode == DRAW_MODE_CIVILIAN )
|
|
{
|
|
ChangeCivGroup( gpSelected->pSoldier->ubCivilianGroup );
|
|
}
|
|
}
|
|
|
|
void DeleteSelectedMerc()
|
|
{
|
|
if( gsSelectedMercID != -1 )
|
|
{
|
|
RemoveSoldierNodeFromInitList( gpSelected );
|
|
gpSelected = NULL;
|
|
gsSelectedMercID = -1;
|
|
gfRenderWorld = TRUE;
|
|
if( TextInputMode() )
|
|
KillTextInputMode();
|
|
IndicateSelectedMerc( SELECT_NO_MERC );
|
|
}
|
|
}
|
|
|
|
void SetupTextInputForMercProfile()
|
|
{
|
|
CHAR16 str[4];
|
|
INT16 sNum;
|
|
|
|
InitTextInputModeWithScheme( DEFAULT_SCHEME );
|
|
AddUserInputField(NULL);//dnl ch78 271113 to avoid automatic textbox selection and enable shortcut keys while not typing
|
|
sNum = gpSelected->pDetailedPlacement->ubProfile;
|
|
if( sNum == NO_PROFILE )
|
|
str[0] = '\0';
|
|
else
|
|
CalcStringForValue( str, gpSelected->pDetailedPlacement->ubProfile, NUM_PROFILES );
|
|
AddTextInputField( iScreenWidthOffset + 200, 2 * iScreenHeightOffset + 430, 30, 20, MSYS_PRIORITY_NORMAL, str, 3, INPUTTYPE_NUMERICSTRICT );
|
|
|
|
}
|
|
|
|
void SetupTextInputForMercAttributes()
|
|
{
|
|
CHAR16 str[4];
|
|
|
|
InitTextInputModeWithScheme( DEFAULT_SCHEME );
|
|
|
|
CalcStringForValue( str, gpSelected->pDetailedPlacement->bExpLevel, 100 );
|
|
AddTextInputField( iScreenWidthOffset + 200, 2 * iScreenHeightOffset + 365, 20, 15, MSYS_PRIORITY_NORMAL, str, 1, INPUTTYPE_NUMERICSTRICT );
|
|
CalcStringForValue( str, gpSelected->pDetailedPlacement->bLife, 100 );
|
|
AddTextInputField( iScreenWidthOffset + 200, 2 * iScreenHeightOffset + 390, 20, 15, MSYS_PRIORITY_NORMAL, str, 3, INPUTTYPE_NUMERICSTRICT );
|
|
CalcStringForValue( str, gpSelected->pDetailedPlacement->bLifeMax, 100 );
|
|
AddTextInputField( iScreenWidthOffset + 200, 2 * iScreenHeightOffset + 415, 20, 15, MSYS_PRIORITY_NORMAL, str, 3, INPUTTYPE_NUMERICSTRICT );
|
|
CalcStringForValue( str, gpSelected->pDetailedPlacement->bMarksmanship, 100 );
|
|
AddTextInputField( iScreenWidthOffset + 200, 2 * iScreenHeightOffset + 440, 20, 15, MSYS_PRIORITY_NORMAL, str, 3, INPUTTYPE_NUMERICSTRICT );
|
|
CalcStringForValue( str, gpSelected->pDetailedPlacement->bStrength, 100 );
|
|
AddTextInputField( iScreenWidthOffset + 300, 2 * iScreenHeightOffset + 365, 20, 15, MSYS_PRIORITY_NORMAL, str, 3, INPUTTYPE_NUMERICSTRICT );
|
|
CalcStringForValue( str, gpSelected->pDetailedPlacement->bAgility, 100 );
|
|
AddTextInputField( iScreenWidthOffset + 300, 2 * iScreenHeightOffset + 390, 20, 15, MSYS_PRIORITY_NORMAL, str, 3, INPUTTYPE_NUMERICSTRICT );
|
|
CalcStringForValue( str, gpSelected->pDetailedPlacement->bDexterity, 100 );
|
|
AddTextInputField( iScreenWidthOffset + 300, 2 * iScreenHeightOffset + 415, 20, 15, MSYS_PRIORITY_NORMAL, str, 3, INPUTTYPE_NUMERICSTRICT );
|
|
CalcStringForValue( str, gpSelected->pDetailedPlacement->bWisdom, 100 );
|
|
AddTextInputField( iScreenWidthOffset + 300, 2 * iScreenHeightOffset + 440, 20, 15, MSYS_PRIORITY_NORMAL, str, 3, INPUTTYPE_NUMERICSTRICT );
|
|
CalcStringForValue( str, gpSelected->pDetailedPlacement->bLeadership, 100 );
|
|
AddTextInputField( iScreenWidthOffset + 400, 2 * iScreenHeightOffset + 365, 20, 15, MSYS_PRIORITY_NORMAL, str, 3, INPUTTYPE_NUMERICSTRICT );
|
|
CalcStringForValue( str, gpSelected->pDetailedPlacement->bExplosive, 100 );
|
|
AddTextInputField( iScreenWidthOffset + 400, 2 * iScreenHeightOffset + 390, 20, 15, MSYS_PRIORITY_NORMAL, str, 3, INPUTTYPE_NUMERICSTRICT );
|
|
CalcStringForValue( str, gpSelected->pDetailedPlacement->bMedical, 100 );
|
|
AddTextInputField( iScreenWidthOffset + 400, 2 * iScreenHeightOffset + 415, 20, 15, MSYS_PRIORITY_NORMAL, str, 3, INPUTTYPE_NUMERICSTRICT );
|
|
CalcStringForValue( str, gpSelected->pDetailedPlacement->bMechanical, 100 );
|
|
AddTextInputField( iScreenWidthOffset + 400, 2 * iScreenHeightOffset + 440, 20, 15, MSYS_PRIORITY_NORMAL, str, 3, INPUTTYPE_NUMERICSTRICT );
|
|
CalcStringForValue( str, gpSelected->pDetailedPlacement->bMorale, 100 );
|
|
AddTextInputField( iScreenWidthOffset + 500, 2 * iScreenHeightOffset + 365, 20, 15, MSYS_PRIORITY_NORMAL, str, 3, INPUTTYPE_NUMERICSTRICT );
|
|
|
|
if( !gfCanEditMercs )
|
|
DisableAllTextFields();
|
|
}
|
|
|
|
//In the merc editing, all detailed placement values for generated attributes are set to -1.
|
|
//When making a generated attribute static, we then set the value to its applicable value.
|
|
//This function is similar to the itoa function except that -1 is converted to a null string.
|
|
void CalcStringForValue( 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 );
|
|
}
|
|
|
|
void ExtractAndUpdateMercAttributes()
|
|
{
|
|
//If we have just deleted the merc's detailed placement in the editor, we don't
|
|
//need to extract the information
|
|
if( !gpSelected->pDetailedPlacement )
|
|
return;
|
|
|
|
//It just so happens that GetNumericStrict...() will return -1 for any blank fields.
|
|
//-1 values in the detailed placement work nicely, because that signifies that specific
|
|
//field isn't static. Any other value becomes static, and static values override any
|
|
//generated values.
|
|
gpSelected->pDetailedPlacement->bExpLevel = (INT8)min( GetNumericStrictValueFromField( 0 ), 100 );
|
|
gpSelected->pDetailedPlacement->bLife = (INT8)min( GetNumericStrictValueFromField( 1 ), 100 );
|
|
gpSelected->pDetailedPlacement->bLifeMax = (INT8)min( GetNumericStrictValueFromField( 2 ), 100 );
|
|
gpSelected->pDetailedPlacement->bMarksmanship = (INT8)min( GetNumericStrictValueFromField( 3 ), 100 );
|
|
gpSelected->pDetailedPlacement->bStrength = (INT8)min( GetNumericStrictValueFromField( 4 ), 100 );
|
|
gpSelected->pDetailedPlacement->bAgility = (INT8)min( GetNumericStrictValueFromField( 5 ), 100 );
|
|
gpSelected->pDetailedPlacement->bDexterity = (INT8)min( GetNumericStrictValueFromField( 6 ), 100 );
|
|
gpSelected->pDetailedPlacement->bWisdom = (INT8)min( GetNumericStrictValueFromField( 7 ), 100 );
|
|
gpSelected->pDetailedPlacement->bLeadership = (INT8)min( GetNumericStrictValueFromField( 8 ), 100 );
|
|
gpSelected->pDetailedPlacement->bExplosive = (INT8)min( GetNumericStrictValueFromField( 9 ), 100 );
|
|
gpSelected->pDetailedPlacement->bMedical = (INT8)min( GetNumericStrictValueFromField( 10 ), 100 );
|
|
gpSelected->pDetailedPlacement->bMechanical = (INT8)min( GetNumericStrictValueFromField( 11 ), 100 );
|
|
gpSelected->pDetailedPlacement->bMorale = (INT8)min( GetNumericStrictValueFromField( 11 ), 100 );
|
|
|
|
//make sure that experience level ranges between 1 and 10
|
|
if( gpSelected->pDetailedPlacement->bExpLevel != -1 )
|
|
gpSelected->pDetailedPlacement->bExpLevel = max( min( gpSelected->pDetailedPlacement->bExpLevel , 10 ), 1 );
|
|
|
|
//no such thing as a life max of 0
|
|
if( !gpSelected->pDetailedPlacement->bLifeMax )
|
|
gpSelected->pDetailedPlacement->bLifeMax = 1;
|
|
|
|
//make sure the life doesn't exceed the maxlife...
|
|
if( gpSelected->pDetailedPlacement->bLifeMax != -1 && gpSelected->pDetailedPlacement->bLife != -1 &&
|
|
gpSelected->pDetailedPlacement->bLife > gpSelected->pDetailedPlacement->bLifeMax )
|
|
gpSelected->pDetailedPlacement->bLife = gpSelected->pDetailedPlacement->bLifeMax;
|
|
|
|
//update the soldier
|
|
UpdateSoldierWithStaticDetailedInformation( gpSelected->pSoldier, gpSelected->pDetailedPlacement );
|
|
}
|
|
|
|
void ExtractAndUpdateMercProfile()
|
|
{
|
|
INT16 sNum;
|
|
static INT16 sPrev = NO_PROFILE;
|
|
|
|
//If we have just deleted the merc's detailed placement in the editor, we don't
|
|
//need to extract the information
|
|
if( !gpSelected->pDetailedPlacement )
|
|
return;
|
|
|
|
//if the string is blank, returning -1, then set the value to NO_PROFILE
|
|
//because ubProfile is unsigned.
|
|
sNum = (INT16)min(GetNumericStrictValueFromField(1), NUM_PROFILES-1);//dnl ch54 101009 //dnl ch78 271113
|
|
if( sNum == -1 )
|
|
{
|
|
gpSelected->pDetailedPlacement->ubProfile = NO_PROFILE;
|
|
gpSelected->pDetailedPlacement->fCopyProfileItemsOver = FALSE;
|
|
SetMercEditability( TRUE );
|
|
}
|
|
else if( sPrev != sNum )
|
|
{
|
|
gpSelected->pDetailedPlacement->ubProfile = (UINT8)sNum;
|
|
gpSelected->pDetailedPlacement->fCopyProfileItemsOver = TRUE;
|
|
gpSelected->pBasicPlacement->fPriorityExistance = TRUE;
|
|
ClickEditorButton( MERCS_PRIORITYEXISTANCE_CHECKBOX );
|
|
SetMercEditability( FALSE );
|
|
}
|
|
else
|
|
return;
|
|
|
|
UpdateSoldierWithStaticDetailedInformation( gpSelected->pSoldier, gpSelected->pDetailedPlacement );
|
|
if( gpSelected->pSoldier->bTeam == CIV_TEAM )
|
|
{
|
|
ChangeCivGroup( gpSelected->pSoldier->ubCivilianGroup );
|
|
}
|
|
}
|
|
|
|
void SetupTextInputForMercSchedule()
|
|
{
|
|
InitTextInputModeWithScheme( DEFAULT_SCHEME );
|
|
AddUserInputField( NULL );
|
|
AddTextInputField( iScreenWidthOffset + 268, 2 * iScreenHeightOffset + 373, 36, 16, MSYS_PRIORITY_NORMAL, L"", 6, INPUTTYPE_EXCLUSIVE_24HOURCLOCK );
|
|
SetExclusive24HourTimeValue( 1, gCurrSchedule.usTime[0] );
|
|
AddTextInputField( iScreenWidthOffset + 268, 2 * iScreenHeightOffset + 394, 36, 16, MSYS_PRIORITY_NORMAL, L"", 6, INPUTTYPE_EXCLUSIVE_24HOURCLOCK );
|
|
SetExclusive24HourTimeValue( 2, gCurrSchedule.usTime[1] );
|
|
AddTextInputField( iScreenWidthOffset + 268, 2 * iScreenHeightOffset + 415, 36, 16, MSYS_PRIORITY_NORMAL, L"", 6, INPUTTYPE_EXCLUSIVE_24HOURCLOCK );
|
|
SetExclusive24HourTimeValue( 3, gCurrSchedule.usTime[2] );
|
|
AddTextInputField( iScreenWidthOffset + 268, 2 * iScreenHeightOffset + 436, 36, 16, MSYS_PRIORITY_NORMAL, L"", 6, INPUTTYPE_EXCLUSIVE_24HOURCLOCK );
|
|
SetExclusive24HourTimeValue( 4, gCurrSchedule.usTime[3] );
|
|
}
|
|
|
|
void ExtractAndUpdateMercSchedule()
|
|
{
|
|
INT32 i;
|
|
BOOLEAN fValidSchedule = FALSE;
|
|
BOOLEAN fScheduleNeedsUpdate = FALSE;
|
|
SCHEDULENODE *pNext = NULL;
|
|
if( !gpSelected )
|
|
return;
|
|
//extract all of the fields into a temp schedulenode.
|
|
//memset( &gScheduleNode, 0, sizeof( SCHEDULENODE ) );
|
|
for( i = 0; i < 4; i++ )
|
|
{
|
|
gCurrSchedule.usTime[i] = GetExclusive24HourTimeValueFromField( (UINT8)(i+1) );
|
|
gCurrSchedule.ubAction[i] = (UINT8)MSYS_GetBtnUserData( ButtonList[ iEditorButton[ MERCS_SCHEDULE_ACTION1 + i ]], 0 );
|
|
if( gCurrSchedule.ubAction[i] )
|
|
fValidSchedule = TRUE;
|
|
}
|
|
|
|
if( !gpSelected->pSoldier->ubScheduleID )
|
|
{ //The soldier doesn't actually have a schedule yet, so create one if necessary (not blank)
|
|
if( fValidSchedule )
|
|
{ //create a new schedule
|
|
if( SortSchedule( &gCurrSchedule ) )
|
|
fScheduleNeedsUpdate = TRUE;
|
|
CopyScheduleToList( &gCurrSchedule, gpSelected );
|
|
ShowEditorButton( MERCS_GLOWSCHEDULE );
|
|
HideEditorButton( MERCS_SCHEDULE );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
SCHEDULENODE *pSchedule;
|
|
pSchedule = GetSchedule( gpSelected->pSoldier->ubScheduleID );
|
|
if( !pSchedule )
|
|
{
|
|
gpSelected->pSoldier->ubScheduleID = 0;
|
|
gpSelected->pDetailedPlacement->ubScheduleID = 0;
|
|
HideEditorButton( MERCS_GLOWSCHEDULE );
|
|
ShowEditorButton( MERCS_SCHEDULE );
|
|
return;
|
|
}
|
|
if( fValidSchedule )
|
|
{ //overwrite the existing schedule with the new one.
|
|
gCurrSchedule.ubScheduleID = gpSelected->pSoldier->ubScheduleID;
|
|
if( SortSchedule( &gCurrSchedule ) )
|
|
fScheduleNeedsUpdate = TRUE;
|
|
pNext = pSchedule->next;
|
|
memcpy( pSchedule, &gCurrSchedule, sizeof( SCHEDULENODE ) );
|
|
pSchedule->next = pNext;
|
|
}
|
|
else
|
|
{ //remove the existing schedule, as the new one is blank.
|
|
DeleteSchedule( pSchedule->ubScheduleID );
|
|
gpSelected->pSoldier->ubScheduleID = 0;
|
|
gpSelected->pDetailedPlacement->ubScheduleID = 0;
|
|
HideEditorButton( MERCS_GLOWSCHEDULE );
|
|
ShowEditorButton( MERCS_SCHEDULE );
|
|
}
|
|
}
|
|
if( fScheduleNeedsUpdate )
|
|
{ //The schedule was sorted, so update the gui.
|
|
UpdateScheduleInfo();
|
|
}
|
|
SetActiveField( 0 );
|
|
}
|
|
|
|
void ExtractCurrentMercModeInfo( BOOLEAN fKillTextInputMode )
|
|
{
|
|
//This happens if we deleted a merc
|
|
if( gsSelectedMercID == -1 )
|
|
return;
|
|
//Extract and update mercs via text fields if applicable
|
|
switch( gubCurrMercMode )
|
|
{
|
|
case MERC_ATTRIBUTEMODE:
|
|
ExtractAndUpdateMercAttributes();
|
|
break;
|
|
case MERC_PROFILEMODE:
|
|
ExtractAndUpdateMercProfile();
|
|
break;
|
|
case MERC_SCHEDULEMODE:
|
|
ExtractAndUpdateMercSchedule();
|
|
break;
|
|
default:
|
|
fKillTextInputMode = FALSE;
|
|
break;
|
|
}
|
|
if( fKillTextInputMode )
|
|
KillTextInputMode();
|
|
}
|
|
|
|
void InitDetailedPlacementForMerc()
|
|
{
|
|
Assert( !gpSelected->pDetailedPlacement );
|
|
|
|
gpSelected->pDetailedPlacement = new SOLDIERCREATE_STRUCT;
|
|
Assert( gpSelected->pDetailedPlacement );
|
|
|
|
gpSelected->pBasicPlacement->fDetailedPlacement = TRUE;
|
|
gpSelected->pBasicPlacement->fPriorityExistance = FALSE;
|
|
CreateStaticDetailedPlacementGivenBasicPlacementInfo( gpSelected->pDetailedPlacement, gpSelected->pBasicPlacement );
|
|
|
|
ClearCurrentSchedule();
|
|
|
|
//update the soldier
|
|
UpdateSoldierWithStaticDetailedInformation ( gpSelected->pSoldier, gpSelected->pDetailedPlacement );
|
|
}
|
|
|
|
void KillDetailedPlacementForMerc()
|
|
{
|
|
Assert( gpSelected->pDetailedPlacement );
|
|
MemFree( gpSelected->pDetailedPlacement );
|
|
gpSelected->pDetailedPlacement = NULL;
|
|
gpSelected->pBasicPlacement->fDetailedPlacement = FALSE;
|
|
SetMercEditability( TRUE );
|
|
}
|
|
|
|
|
|
void ChangeBodyType( INT8 bOffset ) //+1 or -1 only
|
|
{
|
|
INT8 *pbArray;
|
|
INT32 iMax, x;
|
|
INT32 iIndex;
|
|
|
|
gfRenderTaskbar = TRUE;
|
|
gfRenderMercInfo = TRUE;
|
|
//verify that we have a proper offset ( only +-1 allowed )
|
|
Assert( bOffset == -1 || bOffset == 1 );
|
|
//get access to information depending on the team
|
|
switch( gpSelected->pBasicPlacement->bTeam )
|
|
{
|
|
case ENEMY_TEAM:
|
|
pbArray = bEnemyArray;
|
|
iMax = MAX_ENEMYTYPES;
|
|
break;
|
|
case CREATURE_TEAM:
|
|
pbArray = bCreatureArray;
|
|
iMax = MAX_CREATURETYPES;
|
|
break;
|
|
case MILITIA_TEAM:
|
|
pbArray = bRebelArray;
|
|
iMax = MAX_REBELTYPES;
|
|
break;
|
|
case CIV_TEAM:
|
|
pbArray = bCivArray;
|
|
iMax = MAX_CIVTYPES;
|
|
break;
|
|
}
|
|
//find the matching bodytype index within the array.
|
|
for( x = 0; x < iMax; x++ )
|
|
{
|
|
iIndex = pbArray[ x ];
|
|
if( iIndex == gpSelected->pBasicPlacement->ubBodyType )
|
|
break;
|
|
}
|
|
Assert( iIndex == gpSelected->pBasicPlacement->ubBodyType );
|
|
//now we have a match, so go to the next element (depending on offset value)
|
|
x += bOffset;
|
|
if( x >= iMax )
|
|
x = 0;
|
|
else if( x < 0 )
|
|
x = iMax-1;
|
|
iIndex = pbArray[ x ];
|
|
//Set the new bodytype into the and update the soldier info
|
|
if( iIndex != -1 )
|
|
{
|
|
gpSelected->pSoldier->ubBodyType = (UINT8)iIndex;
|
|
//Set the flags based on the bodytype
|
|
gpSelected->pSoldier->flags.uiStatusFlags &= ~(SOLDIER_VEHICLE | SOLDIER_ROBOT | SOLDIER_ANIMAL | SOLDIER_MONSTER);
|
|
switch( gpSelected->pSoldier->ubBodyType )
|
|
{
|
|
case ADULTFEMALEMONSTER:
|
|
case AM_MONSTER:
|
|
case YAF_MONSTER:
|
|
case YAM_MONSTER:
|
|
case LARVAE_MONSTER:
|
|
case INFANT_MONSTER:
|
|
case QUEENMONSTER:
|
|
gpSelected->pSoldier->flags.uiStatusFlags |= SOLDIER_MONSTER;
|
|
break;
|
|
case BLOODCAT:
|
|
case COW:
|
|
case CROW:
|
|
gpSelected->pSoldier->flags.uiStatusFlags |= SOLDIER_ANIMAL;
|
|
break;
|
|
case ROBOTNOWEAPON:
|
|
gpSelected->pSoldier->flags.uiStatusFlags |= SOLDIER_ROBOT;
|
|
break;
|
|
case HUMVEE:
|
|
case ELDORADO:
|
|
case ICECREAMTRUCK:
|
|
case JEEP:
|
|
case TANK_NW:
|
|
case TANK_NE:
|
|
case COMBAT_JEEP:
|
|
gpSelected->pSoldier->flags.uiStatusFlags |= SOLDIER_VEHICLE;
|
|
break;
|
|
}
|
|
SetSoldierAnimationSurface( gpSelected->pSoldier, gpSelected->pSoldier->usAnimState );
|
|
gpSelected->pSoldier->ConvertAniCodeToAniFrame( 0 );
|
|
}
|
|
//Update the placement's info as well.
|
|
gpSelected->pBasicPlacement->ubBodyType = (INT8)iIndex;
|
|
if( gpSelected->pDetailedPlacement )
|
|
{
|
|
gpSelected->pDetailedPlacement->ubBodyType = (INT8)iIndex;
|
|
}
|
|
if( gpSelected->pSoldier->bTeam == CREATURE_TEAM )
|
|
{
|
|
gbCurrCreature = (INT8)iIndex;
|
|
AssignCreatureInventory( gpSelected->pSoldier );
|
|
}
|
|
gpSelected->pSoldier->CreateSoldierPalettes( );
|
|
}
|
|
|
|
void SetMercEditability( BOOLEAN fEditable )
|
|
{
|
|
gfRenderMercInfo = TRUE;
|
|
if( fEditable == gfCanEditMercs )
|
|
return;
|
|
gfCanEditMercs = fEditable;
|
|
if( gfCanEditMercs )
|
|
{ //enable buttons to allow editing
|
|
EnableEditorButtons( MERCS_EQUIPMENT_BAD, MERCS_ATTRIBUTES_GREAT );
|
|
EnableEditorButtons( FIRST_MERCS_COLORMODE_BUTTON, LAST_MERCS_COLORMODE_BUTTON );
|
|
if( gpSelected && gpSelected->pDetailedPlacement && !gpSelected->pDetailedPlacement->fVisible )
|
|
UnclickEditorButton( MERCS_TOGGLECOLOR_BUTTON );
|
|
EnableEditorButton( MERCS_PRIORITYEXISTANCE_CHECKBOX );
|
|
EnableEditorButton( MERCS_CIVILIAN_GROUP );
|
|
}
|
|
else
|
|
{ //disable buttons to prevent editing
|
|
DisableEditorButtons( MERCS_EQUIPMENT_BAD, MERCS_ATTRIBUTES_GREAT );
|
|
DisableEditorButtons( FIRST_MERCS_COLORMODE_BUTTON, LAST_MERCS_COLORMODE_BUTTON );
|
|
ClickEditorButton( MERCS_TOGGLECOLOR_BUTTON );
|
|
DisableEditorButton( MERCS_PRIORITYEXISTANCE_CHECKBOX );
|
|
DisableEditorButton( MERCS_CIVILIAN_GROUP );
|
|
}
|
|
}
|
|
|
|
|
|
//There are 4 exclusive entry points in a map. Only one of each type can exist on a
|
|
//map, and these points are used to validate the map by attempting to connect the four
|
|
//points together. If one of the points is isolated, then the map will be rejected. It
|
|
//isn't necessary to specify all four points. You wouldn't want to specify a north point if
|
|
//there isn't going to be any traversing to adjacent maps from that side.
|
|
//dnl ch41 210909 undo is never implemented for entry points and deletion never work
|
|
void SpecifyEntryPoint(INT32 iMapIndex)
|
|
{
|
|
INT32 *psEntryGridNo;
|
|
switch((iDrawMode>=DRAW_MODE_ERASE ? iDrawMode-DRAW_MODE_ERASE : iDrawMode))
|
|
{
|
|
case DRAW_MODE_NORTHPOINT:
|
|
psEntryGridNo = &gMapInformation.sNorthGridNo;
|
|
break;
|
|
case DRAW_MODE_WESTPOINT:
|
|
psEntryGridNo = &gMapInformation.sWestGridNo;
|
|
break;
|
|
case DRAW_MODE_EASTPOINT:
|
|
psEntryGridNo = &gMapInformation.sEastGridNo;
|
|
break;
|
|
case DRAW_MODE_SOUTHPOINT:
|
|
psEntryGridNo = &gMapInformation.sSouthGridNo;
|
|
break;
|
|
case DRAW_MODE_CENTERPOINT:
|
|
psEntryGridNo = &gMapInformation.sCenterGridNo;
|
|
break;
|
|
case DRAW_MODE_ISOLATEDPOINT:
|
|
psEntryGridNo = &gMapInformation.sIsolatedGridNo;
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
if(iDrawMode >= DRAW_MODE_ERASE)
|
|
{
|
|
*psEntryGridNo = -1;
|
|
}
|
|
else
|
|
{
|
|
*psEntryGridNo = iMapIndex;
|
|
ValidateEntryPointGridNo(psEntryGridNo);
|
|
}
|
|
}
|
|
|
|
void SetMercEditingMode( UINT8 ubNewMode )
|
|
{
|
|
//We need to update the taskbar for the buttons that were erased.
|
|
gfRenderTaskbar = TRUE;
|
|
|
|
//set up the new mode values.
|
|
if( gubCurrMercMode >= MERC_GENERALMODE )
|
|
gubLastDetailedMercMode = gubCurrMercMode;
|
|
|
|
//Depending on the mode we were just in, we may want to extract and update the
|
|
//merc first. Then we change modes...
|
|
ExtractCurrentMercModeInfo( TRUE );
|
|
|
|
//Change modes now.
|
|
gubPrevMercMode = gubCurrMercMode;
|
|
gubCurrMercMode = ubNewMode;
|
|
|
|
//Hide all of the merc buttons except the team buttons which are static.
|
|
HideEditorButtons( FIRST_MERCS_BASICMODE_BUTTON, LAST_MERCS_BUTTON );
|
|
|
|
switch( gubPrevMercMode )
|
|
{
|
|
case MERC_GETITEMMODE:
|
|
EnableEditorButtons( TAB_TERRAIN, TAB_OPTIONS );
|
|
HideEditorButtons( FIRST_MERCS_GETITEM_BUTTON, LAST_MERCS_GETITEM_BUTTON );
|
|
AddNewItemToSelectedMercsInventory( TRUE );
|
|
break;
|
|
case MERC_INVENTORYMODE:
|
|
HideItemStatsPanel();
|
|
DisableEditorRegion( MERC_REGION_ID );
|
|
break;
|
|
case MERC_GENERALMODE:
|
|
EnableEditorButton( MERCS_APPEARANCE );
|
|
break;
|
|
case MERC_SCHEDULEMODE:
|
|
//ClearCurrentSchedule();
|
|
break;
|
|
}
|
|
|
|
//If we leave the merc tab, then we want to update editable fields such as
|
|
//attributes, which was just handled above, then turn everything off, and exit.
|
|
if( ubNewMode == MERC_NOMODE )
|
|
{
|
|
HideEditorButtons( FIRST_MERCS_BUTTON, LAST_MERCS_TEAMMODE_BUTTON );
|
|
HideEditorButtons( MERCS_SCHEDULE, MERCS_GLOWSCHEDULE );
|
|
return;
|
|
}
|
|
if( gubPrevMercMode == MERC_NOMODE || gubPrevMercMode == MERC_GETITEMMODE )
|
|
{
|
|
ShowEditorButtons( FIRST_MERCS_BUTTON, LAST_MERCS_TEAMMODE_BUTTON );
|
|
}
|
|
|
|
//Release the currently selected merc if you just selected a new team.
|
|
if( gsSelectedMercID != -1 && ubNewMode == MERC_TEAMMODE )
|
|
{
|
|
//attempt to weed out conditions where we select a team that matches the currently
|
|
//selected merc. We don't want to deselect him in this case.
|
|
if( gpSelected->pSoldier->bTeam == ENEMY_TEAM && iDrawMode == DRAW_MODE_ENEMY ||
|
|
gpSelected->pSoldier->bTeam == CREATURE_TEAM && iDrawMode == DRAW_MODE_CREATURE ||
|
|
gpSelected->pSoldier->bTeam == MILITIA_TEAM && iDrawMode == DRAW_MODE_REBEL ||
|
|
gpSelected->pSoldier->bTeam == CIV_TEAM && iDrawMode == DRAW_MODE_CIVILIAN )
|
|
{ //Same team, so don't deselect merc. Instead, keep the previous editing mode
|
|
//because we are still editing this merc.
|
|
gubCurrMercMode = gubPrevMercMode;
|
|
//if we don't have a detailed placement, auto set to basic mode.
|
|
if( !gpSelected->pDetailedPlacement )
|
|
gubCurrMercMode = MERC_BASICMODE;
|
|
}
|
|
else
|
|
{
|
|
//Different teams, so deselect the current merc and the detailed checkbox if applicable.
|
|
IndicateSelectedMerc( SELECT_NO_MERC );
|
|
ShowEditorButtons( FIRST_MERCS_BUTTON, LAST_MERCS_TEAMMODE_BUTTON );
|
|
UnclickEditorButton( MERCS_DETAILEDCHECKBOX );
|
|
}
|
|
}
|
|
|
|
ShowButton( iEditorButton[ MERCS_NEXT ] );
|
|
if( gsSelectedMercID != -1 )
|
|
ShowButton( iEditorButton[ MERCS_DELETE ] );
|
|
|
|
if( gubCurrMercMode > MERC_TEAMMODE )
|
|
{ //Add the basic buttons if applicable.
|
|
ShowEditorButtons( FIRST_MERCS_BASICMODE_BUTTON, LAST_MERCS_BASICMODE_BUTTON );
|
|
}
|
|
if( gubCurrMercMode > MERC_BASICMODE )
|
|
{ //Add the detailed buttons if applicable.
|
|
ClickEditorButton( MERCS_DETAILEDCHECKBOX );
|
|
ShowEditorButtons( FIRST_MERCS_PRIORITYMODE_BUTTON, LAST_MERCS_PRIORITYMODE_BUTTON );
|
|
}
|
|
else
|
|
UnclickEditorButton( MERCS_DETAILEDCHECKBOX );
|
|
//Now we are setting up the button states for the new mode, as well as show the
|
|
//applicable buttons for the detailed placement modes.
|
|
if( gubCurrMercMode == MERC_APPEARANCEMODE && iDrawMode == DRAW_MODE_CREATURE ||
|
|
gubCurrMercMode == MERC_SCHEDULEMODE && iDrawMode != DRAW_MODE_CIVILIAN )
|
|
{
|
|
gubCurrMercMode = MERC_GENERALMODE;
|
|
}
|
|
switch( gubCurrMercMode )
|
|
{
|
|
case MERC_GETITEMMODE:
|
|
DisableEditorButtons( TAB_TERRAIN, TAB_OPTIONS );
|
|
EnableEditorButton( TAB_MERCS );
|
|
HideEditorButtons( FIRST_MERCS_BUTTON, LAST_MERCS_TEAMMODE_BUTTON );
|
|
HideEditorButtons( MERCS_SCHEDULE, MERCS_GLOWSCHEDULE );
|
|
ShowEditorButtons( FIRST_MERCS_GETITEM_BUTTON, LAST_MERCS_GETITEM_BUTTON );
|
|
InitEditorItemsInfo( eInfo.uiItemType );
|
|
ClickEditorButton( ITEMS_WEAPONS + eInfo.uiItemType - TBAR_MODE_ITEM_WEAPONS );
|
|
break;
|
|
case MERC_INVENTORYMODE:
|
|
UpdateMercItemSlots();
|
|
ShowItemStatsPanel();
|
|
if( gbCurrSelect == -1 )
|
|
SpecifyItemToEdit( NULL, -1 );
|
|
else
|
|
SpecifyItemToEdit( gpMercSlotItem[ gbCurrSelect ], -1 );
|
|
HideEditorButtons( MERCS_DELETE, MERCS_NEXT );
|
|
ShowEditorButtons( FIRST_MERCS_INVENTORY_BUTTON, LAST_MERCS_INVENTORY_BUTTON );
|
|
EnableEditorRegion( MERC_REGION_ID );
|
|
UnclickEditorButtons( FIRST_MERCS_PRIORITYMODE_BUTTON, LAST_MERCS_PRIORITYMODE_BUTTON );
|
|
ClickEditorButton( MERCS_INVENTORY );
|
|
break;
|
|
case MERC_BASICMODE:
|
|
ShowEditorButtons( FIRST_MERCS_GENERAL_BUTTON, LAST_MERCS_GENERAL_BUTTON );
|
|
if( iDrawMode == DRAW_MODE_CREATURE )
|
|
{ //Set up alternate general mode. This one doesn't allow you to specify relative attributes
|
|
//but requires you to specify a body type.
|
|
HideEditorButtons( FIRST_MERCS_REL_EQUIPMENT_BUTTON, LAST_MERCS_REL_EQUIPMENT_BUTTON );
|
|
ShowEditorButtons( FIRST_MERCS_BODYTYPE_BUTTON, LAST_MERCS_BODYTYPE_BUTTON );
|
|
}
|
|
if( iDrawMode != DRAW_MODE_ENEMY )
|
|
HideEditorButtons( FIRST_MERCS_COLORCODE_BUTTON, LAST_MERCS_COLORCODE_BUTTON );
|
|
if( iDrawMode == DRAW_MODE_CIVILIAN )
|
|
ShowEditorButton( MERCS_CIVILIAN_GROUP );
|
|
break;
|
|
case MERC_GENERALMODE:
|
|
ShowEditorButtons( FIRST_MERCS_GENERAL_BUTTON, LAST_MERCS_GENERAL_BUTTON );
|
|
UnclickEditorButtons( FIRST_MERCS_PRIORITYMODE_BUTTON, LAST_MERCS_PRIORITYMODE_BUTTON );
|
|
ClickEditorButton( MERCS_GENERAL );
|
|
if( iDrawMode == DRAW_MODE_CREATURE )
|
|
{ //Set up alternate general mode. This one doesn't allow you to specify relative equipment
|
|
//but requires you to specify a body type.
|
|
HideEditorButtons( FIRST_MERCS_REL_EQUIPMENT_BUTTON, LAST_MERCS_REL_EQUIPMENT_BUTTON );
|
|
ShowEditorButtons( FIRST_MERCS_BODYTYPE_BUTTON, LAST_MERCS_BODYTYPE_BUTTON );
|
|
DisableEditorButton( MERCS_APPEARANCE );
|
|
}
|
|
if( iDrawMode != DRAW_MODE_ENEMY )
|
|
HideEditorButtons( FIRST_MERCS_COLORCODE_BUTTON, LAST_MERCS_COLORCODE_BUTTON );
|
|
if( iDrawMode == DRAW_MODE_CIVILIAN )
|
|
ShowEditorButton( MERCS_CIVILIAN_GROUP );
|
|
break;
|
|
case MERC_ATTRIBUTEMODE:
|
|
UnclickEditorButtons( FIRST_MERCS_PRIORITYMODE_BUTTON, LAST_MERCS_PRIORITYMODE_BUTTON );
|
|
ClickEditorButton( MERCS_ATTRIBUTES );
|
|
SetupTextInputForMercAttributes();
|
|
break;
|
|
case MERC_APPEARANCEMODE:
|
|
ShowEditorButtons( FIRST_MERCS_COLORMODE_BUTTON, LAST_MERCS_COLORMODE_BUTTON );
|
|
UnclickEditorButtons( FIRST_MERCS_PRIORITYMODE_BUTTON, LAST_MERCS_PRIORITYMODE_BUTTON );
|
|
ClickEditorButton( MERCS_APPEARANCE );
|
|
if( gfCanEditMercs && gpSelected && gpSelected->pDetailedPlacement )
|
|
{
|
|
if( !gpSelected->pDetailedPlacement->fVisible )
|
|
{
|
|
UnclickEditorButton( MERCS_TOGGLECOLOR_BUTTON );
|
|
DisableEditorButtons( FIRST_MERCS_COLOR_BUTTON, LAST_MERCS_COLOR_BUTTON );
|
|
}
|
|
else
|
|
{
|
|
ClickEditorButton( MERCS_TOGGLECOLOR_BUTTON );
|
|
EnableEditorButtons( FIRST_MERCS_COLOR_BUTTON, LAST_MERCS_COLOR_BUTTON );
|
|
}
|
|
}
|
|
break;
|
|
case MERC_PROFILEMODE:
|
|
UnclickEditorButtons( FIRST_MERCS_PRIORITYMODE_BUTTON, LAST_MERCS_PRIORITYMODE_BUTTON );
|
|
ClickEditorButton( MERCS_PROFILE );
|
|
SetupTextInputForMercProfile();
|
|
break;
|
|
case MERC_SCHEDULEMODE:
|
|
ShowEditorButtons( MERCS_SCHEDULE_ACTION1, MERCS_SCHEDULE_VARIANCE4 );
|
|
ShowEditorButton( MERCS_SCHEDULE_CLEAR );
|
|
UnclickEditorButtons( FIRST_MERCS_PRIORITYMODE_BUTTON, LAST_MERCS_PRIORITYMODE_BUTTON );
|
|
ClickEditorButton( MERCS_SCHEDULE );
|
|
SetupTextInputForMercSchedule();
|
|
UpdateScheduleInfo();
|
|
DetermineScheduleEditability();
|
|
}
|
|
//Show or hide the schedule buttons
|
|
if( gpSelected && gubCurrMercMode != MERC_GETITEMMODE )
|
|
{
|
|
if( gpSelected->pDetailedPlacement && gpSelected->pDetailedPlacement->ubScheduleID )
|
|
{
|
|
HideEditorButton( MERCS_SCHEDULE );
|
|
ShowEditorButton( MERCS_GLOWSCHEDULE );
|
|
}
|
|
else
|
|
{
|
|
HideEditorButton( MERCS_GLOWSCHEDULE );
|
|
if( gpSelected->pDetailedPlacement )
|
|
{
|
|
ShowEditorButton( MERCS_SCHEDULE );
|
|
if( gpSelected->pSoldier->bTeam == CIV_TEAM )
|
|
EnableEditorButton( MERCS_SCHEDULE );
|
|
else
|
|
DisableEditorButton( MERCS_SCHEDULE );
|
|
}
|
|
else
|
|
{
|
|
HideEditorButton( MERCS_SCHEDULE );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
HideEditorButtons( MERCS_SCHEDULE, MERCS_GLOWSCHEDULE );
|
|
}
|
|
}
|
|
|
|
void DisplayBodyTypeInfo()
|
|
{
|
|
CHAR16 str[20];
|
|
switch( gpSelected->pBasicPlacement->ubBodyType )
|
|
{
|
|
case RANDOM: swprintf( str, pDisplayBodyTypeInfoText[0] ); break;
|
|
case REGMALE: swprintf( str, pDisplayBodyTypeInfoText[1] ); break;
|
|
case BIGMALE: swprintf( str, pDisplayBodyTypeInfoText[2] ); break;
|
|
case STOCKYMALE: swprintf( str, pDisplayBodyTypeInfoText[3] ); break;
|
|
case REGFEMALE: swprintf( str, pDisplayBodyTypeInfoText[4] ); break;
|
|
case TANK_NE: swprintf( str, pDisplayBodyTypeInfoText[5] ); break;
|
|
case TANK_NW: swprintf( str, pDisplayBodyTypeInfoText[6] ); break;
|
|
case FATCIV: swprintf( str, pDisplayBodyTypeInfoText[7] ); break;
|
|
case MANCIV: swprintf( str, pDisplayBodyTypeInfoText[8] ); break;
|
|
case MINICIV: swprintf( str, pDisplayBodyTypeInfoText[9] ); break;
|
|
case DRESSCIV: swprintf( str, pDisplayBodyTypeInfoText[10] ); break;
|
|
case HATKIDCIV: swprintf( str, pDisplayBodyTypeInfoText[11] ); break;
|
|
case HUMVEE: swprintf( str, pDisplayBodyTypeInfoText[12] ); break;
|
|
case ELDORADO: swprintf( str, pDisplayBodyTypeInfoText[13] ); break;
|
|
case ICECREAMTRUCK: swprintf( str, pDisplayBodyTypeInfoText[14] ); break;
|
|
case JEEP: swprintf( str, pDisplayBodyTypeInfoText[15] ); break;
|
|
case KIDCIV: swprintf( str, pDisplayBodyTypeInfoText[16] ); break;
|
|
case COW: swprintf( str, pDisplayBodyTypeInfoText[17] ); break;
|
|
case CRIPPLECIV: swprintf( str, pDisplayBodyTypeInfoText[18] ); break;
|
|
case ROBOTNOWEAPON: swprintf( str, pDisplayBodyTypeInfoText[19] ); break;
|
|
case LARVAE_MONSTER: swprintf( str, pDisplayBodyTypeInfoText[20] ); break;
|
|
case INFANT_MONSTER: swprintf( str, pDisplayBodyTypeInfoText[21] ); break;
|
|
case YAF_MONSTER: swprintf( str, pDisplayBodyTypeInfoText[22] ); break;
|
|
case YAM_MONSTER: swprintf( str, pDisplayBodyTypeInfoText[23] ); break;
|
|
case ADULTFEMALEMONSTER: swprintf( str, pDisplayBodyTypeInfoText[24] ); break;
|
|
case AM_MONSTER: swprintf( str, pDisplayBodyTypeInfoText[25] ); break;
|
|
case QUEENMONSTER: swprintf( str, pDisplayBodyTypeInfoText[26] ); break;
|
|
case BLOODCAT: swprintf( str, pDisplayBodyTypeInfoText[27] ); break;
|
|
case COMBAT_JEEP: swprintf( str, pDisplayBodyTypeInfoText[28] ); break;
|
|
}
|
|
DrawEditorInfoBox( str, FONT10ARIAL, iScreenWidthOffset + 490, 2 * iScreenHeightOffset + 364, 70, 20 );
|
|
}
|
|
|
|
void UpdateMercsInfo()
|
|
{
|
|
if( !gfRenderMercInfo )
|
|
return;
|
|
|
|
//We are rendering it now, so signify that it has been done, so
|
|
//it doesn't get rendered every frame.
|
|
gfRenderMercInfo = FALSE;
|
|
|
|
switch( gubCurrMercMode )
|
|
{
|
|
case MERC_GETITEMMODE:
|
|
RenderEditorItemsInfo();
|
|
break;
|
|
case MERC_INVENTORYMODE:
|
|
if( gfMercGetItem )
|
|
SetMercEditingMode( MERC_GETITEMMODE );
|
|
else
|
|
RenderMercInventoryPanel();
|
|
break;
|
|
case MERC_BASICMODE:
|
|
case MERC_GENERALMODE:
|
|
BltVideoObjectFromIndex( FRAME_BUFFER, guiExclamation, 0, iScreenWidthOffset + 188, 2 * iScreenHeightOffset + 362, VO_BLT_SRCTRANSPARENCY, NULL );
|
|
BltVideoObjectFromIndex( FRAME_BUFFER, guiKeyImage, 0, iScreenWidthOffset + 186, 2 * iScreenHeightOffset + 387, VO_BLT_SRCTRANSPARENCY, NULL );
|
|
SetFont( SMALLCOMPFONT );
|
|
SetFontForeground( FONT_YELLOW );
|
|
SetFontShadow( FONT_NEARBLACK );
|
|
mprintf( iScreenWidthOffset + 240, 2 * iScreenHeightOffset + 363, pUpdateMercsInfoText[0] );
|
|
mprintf( iScreenWidthOffset + 240, 2 * iScreenHeightOffset + 419, pUpdateMercsInfoText[1] );
|
|
if( iDrawMode == DRAW_MODE_CREATURE )
|
|
{
|
|
DisplayBodyTypeInfo();
|
|
SetFont( SMALLCOMPFONT );
|
|
SetFontForeground( FONT_LTBLUE );
|
|
mprintf( iScreenWidthOffset + 493, 2 * iScreenHeightOffset + 416, pUpdateMercsInfoText[2] );
|
|
mprintf( iScreenWidthOffset + 480, 2 * iScreenHeightOffset + 422, pUpdateMercsInfoText[3] );
|
|
}
|
|
else
|
|
{
|
|
SetFontForeground( FONT_LTGREEN );
|
|
mprintf( iScreenWidthOffset + 480, 2 * iScreenHeightOffset + 363, pUpdateMercsInfoText[4] );
|
|
mprintf( iScreenWidthOffset + 480, 2 * iScreenHeightOffset + 371, pUpdateMercsInfoText[5] );
|
|
SetFontForeground( FONT_LTBLUE );
|
|
mprintf( iScreenWidthOffset + 530, 2 * iScreenHeightOffset + 363, pUpdateMercsInfoText[6] );
|
|
mprintf( iScreenWidthOffset + 530, 2 * iScreenHeightOffset + 371, pUpdateMercsInfoText[7] );
|
|
}
|
|
if( iDrawMode == DRAW_MODE_ENEMY )
|
|
{
|
|
SetFont( FONT10ARIAL );
|
|
SetFontForeground( FONT_YELLOW );
|
|
mprintf( iScreenWidthOffset + 590, 2 * iScreenHeightOffset + 411, pUpdateMercsInfoText[8] );
|
|
mprintf( iScreenWidthOffset + 590, 2 * iScreenHeightOffset + 425, pUpdateMercsInfoText[9] );
|
|
mprintf( iScreenWidthOffset + 590, 2 * iScreenHeightOffset + 439, pUpdateMercsInfoText[10] );
|
|
}
|
|
break;
|
|
case MERC_ATTRIBUTEMODE:
|
|
SetFont( FONT10ARIAL );
|
|
SetFontForeground( FONT_YELLOW );
|
|
SetFontShadow( FONT_NEARBLACK );
|
|
mprintf( iScreenWidthOffset + 225, 2 * iScreenHeightOffset + 370, pUpdateMercsInfoText[11] );
|
|
mprintf( iScreenWidthOffset + 225, 2 * iScreenHeightOffset + 395, pUpdateMercsInfoText[12] );
|
|
mprintf( iScreenWidthOffset + 225, 2 * iScreenHeightOffset + 420, pUpdateMercsInfoText[13] );
|
|
mprintf( iScreenWidthOffset + 225, 2 * iScreenHeightOffset + 445, pUpdateMercsInfoText[14] );
|
|
mprintf( iScreenWidthOffset + 325, 2 * iScreenHeightOffset + 370, pUpdateMercsInfoText[15] );
|
|
mprintf( iScreenWidthOffset + 325, 2 * iScreenHeightOffset + 395, pUpdateMercsInfoText[16] );
|
|
mprintf( iScreenWidthOffset + 325, 2 * iScreenHeightOffset + 420, pUpdateMercsInfoText[17] );
|
|
mprintf( iScreenWidthOffset + 325, 2 * iScreenHeightOffset + 445, pUpdateMercsInfoText[18] );
|
|
mprintf( iScreenWidthOffset + 425, 2 * iScreenHeightOffset + 370, pUpdateMercsInfoText[19] );
|
|
mprintf( iScreenWidthOffset + 425, 2 * iScreenHeightOffset + 395, pUpdateMercsInfoText[20] );
|
|
mprintf( iScreenWidthOffset + 425, 2 * iScreenHeightOffset + 420, pUpdateMercsInfoText[21] );
|
|
mprintf( iScreenWidthOffset + 425, 2 * iScreenHeightOffset + 445, pUpdateMercsInfoText[22] );
|
|
mprintf( iScreenWidthOffset + 525, 2 * iScreenHeightOffset + 370, pUpdateMercsInfoText[23] );
|
|
break;
|
|
case MERC_APPEARANCEMODE:
|
|
SetFont( FONT10ARIAL );
|
|
if( gpSelected->pDetailedPlacement->fVisible || gpSelected->pDetailedPlacement->ubProfile != NO_PROFILE )
|
|
SetFontForeground( FONT_YELLOW );
|
|
else
|
|
SetFontForeground( FONT_DKYELLOW );
|
|
SetFontShadow( FONT_NEARBLACK );
|
|
|
|
mprintf( iScreenWidthOffset + 396, 2 * iScreenHeightOffset + 364, pUpdateMercsInfoText[24] );
|
|
mprintf( iScreenWidthOffset + 396, 2 * iScreenHeightOffset + 388, pUpdateMercsInfoText[25]);
|
|
mprintf( iScreenWidthOffset + 396, 2 * iScreenHeightOffset + 412, pUpdateMercsInfoText[26]);
|
|
mprintf( iScreenWidthOffset + 396, 2 * iScreenHeightOffset + 436, pUpdateMercsInfoText[27]);
|
|
|
|
SetFont( SMALLCOMPFONT );
|
|
SetFontForeground( FONT_BLACK );
|
|
if( gpSelected->pDetailedPlacement->fVisible || gpSelected->pDetailedPlacement->ubProfile != NO_PROFILE )
|
|
{
|
|
mprintfEditor( iScreenWidthOffset + 396, 2 * iScreenHeightOffset + 374, L"%S ", gpSelected->pSoldier->HeadPal );
|
|
mprintfEditor( iScreenWidthOffset + 396, 2 * iScreenHeightOffset + 398, L"%S ", gpSelected->pSoldier->SkinPal );
|
|
mprintfEditor( iScreenWidthOffset + 396, 2 * iScreenHeightOffset + 422, L"%S ", gpSelected->pSoldier->VestPal );
|
|
mprintfEditor( iScreenWidthOffset + 396, 2 * iScreenHeightOffset + 446, L"%S ", gpSelected->pSoldier->PantsPal );
|
|
ShowEditMercPalettes( gpSelected->pSoldier );
|
|
}
|
|
else
|
|
{
|
|
mprintf( iScreenWidthOffset + 396, 2 * iScreenHeightOffset + 374, pUpdateMercsInfoText[28]);
|
|
mprintf( iScreenWidthOffset + 396, 2 * iScreenHeightOffset + 398, pUpdateMercsInfoText[29]);
|
|
mprintf( iScreenWidthOffset + 396, 2 * iScreenHeightOffset + 422, pUpdateMercsInfoText[30]);
|
|
mprintf( iScreenWidthOffset + 396, 2 * iScreenHeightOffset + 446, pUpdateMercsInfoText[31]);
|
|
ShowEditMercPalettes( NULL ); //will display grey scale to signify random
|
|
}
|
|
DisplayBodyTypeInfo();
|
|
break;
|
|
case MERC_PROFILEMODE:
|
|
SetFont( FONT10ARIAL );
|
|
SetFontForeground( FONT_YELLOW );
|
|
SetFontShadow( FONT_NEARBLACK );
|
|
{ //scope trick
|
|
CHAR16 tempStr[500];
|
|
swprintf( tempStr, L"%s%s%s%s%s%d.",
|
|
pUpdateMercsInfoText[32],
|
|
pUpdateMercsInfoText[33],
|
|
pUpdateMercsInfoText[34],
|
|
pUpdateMercsInfoText[35],
|
|
pUpdateMercsInfoText[36], NUM_PROFILES-1 );
|
|
DisplayWrappedString(iScreenWidthOffset + 180, 2 * iScreenHeightOffset + 370, 400, 2, FONT10ARIAL, 146, tempStr, FONT_BLACK, FALSE, LEFT_JUSTIFIED );
|
|
SetFont( FONT12POINT1 );
|
|
if( gpSelected->pDetailedPlacement->ubProfile == NO_PROFILE )
|
|
{
|
|
SetFontForeground( FONT_GRAY3 );
|
|
mprintfEditor( iScreenWidthOffset + 240, 2 * iScreenHeightOffset + 435, pUpdateMercsInfoText[37]);
|
|
}
|
|
else
|
|
{
|
|
SetFontForeground( FONT_WHITE );
|
|
ClearTaskbarRegion( iScreenWidthOffset + 240, 2 * iScreenHeightOffset + 435, iScreenWidthOffset + 580, 2 * iScreenHeightOffset + 445 );
|
|
mprintf( iScreenWidthOffset + 240, 2 * iScreenHeightOffset + 435, pUpdateMercsInfoText[38], gMercProfiles[ gpSelected->pDetailedPlacement->ubProfile ].zName );
|
|
}
|
|
}
|
|
break;
|
|
case MERC_SCHEDULEMODE:
|
|
SetFont( FONT10ARIAL );
|
|
SetFontForeground( FONT_WHITE );
|
|
SetFontShadow( FONT_NEARBLACK );
|
|
switch( gpSelected->pSoldier->aiData.bOrders )
|
|
{
|
|
case STATIONARY: mprintf( iScreenWidthOffset + 430, 2 * iScreenHeightOffset + 363, pUpdateMercsInfoText[39] ); break;
|
|
case ONCALL: mprintf( iScreenWidthOffset + 430, 2 * iScreenHeightOffset + 363, pUpdateMercsInfoText[40] ); break;
|
|
case ONGUARD: mprintf( iScreenWidthOffset + 430, 2 * iScreenHeightOffset + 363, pUpdateMercsInfoText[41] ); break;
|
|
case SEEKENEMY: mprintf( iScreenWidthOffset + 430, 2 * iScreenHeightOffset + 363, pUpdateMercsInfoText[42] ); break;
|
|
case CLOSEPATROL: mprintf( iScreenWidthOffset + 430, 2 * iScreenHeightOffset + 363, pUpdateMercsInfoText[43] ); break;
|
|
case FARPATROL: mprintf( iScreenWidthOffset + 430, 2 * iScreenHeightOffset + 363, pUpdateMercsInfoText[44] ); break;
|
|
case POINTPATROL: mprintf( iScreenWidthOffset + 430, 2 * iScreenHeightOffset + 363, pUpdateMercsInfoText[45] ); break;
|
|
case RNDPTPATROL: mprintf( iScreenWidthOffset + 430, 2 * iScreenHeightOffset + 363, pUpdateMercsInfoText[46] ); break;
|
|
}
|
|
SetFontForeground( FONT_YELLOW );
|
|
mprintf( iScreenWidthOffset + 186, 2 * iScreenHeightOffset + 363, pUpdateMercsInfoText[47] );
|
|
mprintf( iScreenWidthOffset + 268, 2 * iScreenHeightOffset + 363, pUpdateMercsInfoText[48] );
|
|
mprintf( iScreenWidthOffset + 309, 2 * iScreenHeightOffset + 363, pUpdateMercsInfoText[49] );
|
|
mprintf( iScreenWidthOffset + 331, 2 * iScreenHeightOffset + 363, pUpdateMercsInfoText[50] );
|
|
mprintf( iScreenWidthOffset + 381, 2 * iScreenHeightOffset + 363, pUpdateMercsInfoText[51] );
|
|
mprintf( iScreenWidthOffset + 172, 2 * iScreenHeightOffset + 376, pUpdateMercsInfoText[52] );
|
|
mprintf( iScreenWidthOffset + 172, 2 * iScreenHeightOffset + 397, pUpdateMercsInfoText[53] );
|
|
mprintf( iScreenWidthOffset + 172, 2 * iScreenHeightOffset + 418, pUpdateMercsInfoText[54] );
|
|
mprintf( iScreenWidthOffset + 172, 2 * iScreenHeightOffset + 439, pUpdateMercsInfoText[55] );
|
|
if( gubScheduleInstructions )
|
|
{
|
|
CHAR16 str[255];
|
|
CHAR16 keyword[10] = L"";
|
|
ColorFillVideoSurfaceArea( FRAME_BUFFER, iScreenWidthOffset + 431, 2 * iScreenHeightOffset + 388, iScreenWidthOffset + 590, 2 * iScreenHeightOffset + 450, Get16BPPColor( FROMRGB( 32, 45, 72 ) ) );
|
|
switch( gCurrSchedule.ubAction[ gubCurrentScheduleActionIndex ] )
|
|
{
|
|
case SCHEDULE_ACTION_LOCKDOOR: swprintf( keyword, pUpdateMercsInfoText[56] ); break;
|
|
case SCHEDULE_ACTION_UNLOCKDOOR: swprintf( keyword, pUpdateMercsInfoText[57] ); break;
|
|
case SCHEDULE_ACTION_OPENDOOR: swprintf( keyword, pUpdateMercsInfoText[58] ); break;
|
|
case SCHEDULE_ACTION_CLOSEDOOR: swprintf( keyword, pUpdateMercsInfoText[59] ); break;
|
|
}
|
|
switch( gubScheduleInstructions )
|
|
{
|
|
case SCHEDULE_INSTRUCTIONS_DOOR1:
|
|
swprintf( str, pUpdateMercsInfoText[60], keyword );
|
|
break;
|
|
case SCHEDULE_INSTRUCTIONS_DOOR2:
|
|
swprintf( str, pUpdateMercsInfoText[61], keyword );
|
|
break;
|
|
case SCHEDULE_INSTRUCTIONS_GRIDNO:
|
|
swprintf( str, pUpdateMercsInfoText[62] );
|
|
break;
|
|
case SCHEDULE_INSTRUCTIONS_SLEEP:
|
|
swprintf( str, pUpdateMercsInfoText[63] );
|
|
default:
|
|
return;
|
|
}
|
|
|
|
if ( gCurrSchedule.ubAction[ gubCurrentScheduleActionIndex ] == SCHEDULE_ACTION_SLEEP ) swprintf( str, pUpdateMercsInfoText[63] );
|
|
|
|
wcscat( str, pUpdateMercsInfoText[64] );
|
|
DisplayWrappedString( iScreenWidthOffset + 436, 2 * iScreenHeightOffset + 392, 149, 2, FONT10ARIAL, FONT_YELLOW, str, FONT_BLACK, FALSE, LEFT_JUSTIFIED );
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
//When a detailed placement merc is in the inventory panel, there is a overall region
|
|
//blanketing this panel. As the user moves the mouse around and clicks, etc., this function
|
|
//is called by the region callback functions to handle these cases. The event types are defined
|
|
//in Editor Taskbar Utils.h. Here are the internal functions...
|
|
|
|
SGPRect mercRects[9] =
|
|
{
|
|
{ 75, 0, 104, 19 }, //head
|
|
{ 75, 22, 104, 41 }, //body
|
|
{ 76, 73, 105, 92 }, //legs
|
|
{ 26, 43, 78, 62 }, //left hand
|
|
{ 104, 42, 156, 61 }, //right hand
|
|
{ 180, 6, 232, 25 }, //pack 1
|
|
{ 180, 29, 232, 48 }, //pack 2
|
|
{ 180, 52, 232, 71 }, //pack 3
|
|
{ 180, 75, 232, 94 } //pack 4
|
|
};
|
|
|
|
|
|
BOOLEAN PointInRect( SGPRect *pRect, INT32 x, INT32 y )
|
|
{
|
|
return( x >= pRect->iLeft && x <= pRect->iRight && y >= pRect->iTop && y <= pRect->iBottom );
|
|
}
|
|
|
|
void DrawRect( SGPRect *pRect, INT16 color )
|
|
{
|
|
UINT32 uiDestPitchBYTES;
|
|
UINT8 *pDestBuf;
|
|
pDestBuf = LockVideoSurface( FRAME_BUFFER, &uiDestPitchBYTES );
|
|
SetClippingRegionAndImageWidth( uiDestPitchBYTES, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT );
|
|
RectangleDraw( TRUE, pRect->iLeft+MERCPANEL_X, pRect->iTop+MERCPANEL_Y, pRect->iRight+MERCPANEL_X, pRect->iBottom+MERCPANEL_Y, color, pDestBuf );
|
|
UnLockVideoSurface( FRAME_BUFFER );
|
|
//InvalidateRegion( pRect->iLeft+175, pRect->iTop+361, pRect->iRight+176, pRect->iBottom+362 );
|
|
}
|
|
|
|
void RenderSelectedMercsInventory()
|
|
{
|
|
INT32 i;
|
|
UINT8 *pSrc, *pDst;
|
|
INT32 xp, yp;
|
|
UINT32 uiSrcPitchBYTES, uiDstPitchBYTES;
|
|
CHAR16 pItemName[100];
|
|
UINT8 ubFontColor;
|
|
if( gsSelectedMercID == -1 )
|
|
return;
|
|
for( i = 0; i < 9; i++ )
|
|
{
|
|
if( gpMercSlotItem[i] )
|
|
{ //Render the current image.
|
|
xp = mercRects[ i ].iLeft + 4 + MERCPANEL_X;
|
|
yp = mercRects[ i ].iTop + MERCPANEL_Y;
|
|
pDst = LockVideoSurface( FRAME_BUFFER, &uiDstPitchBYTES );
|
|
pSrc = LockVideoSurface( guiMercInvPanelBuffers[i], &uiSrcPitchBYTES );
|
|
Blt16BPPTo16BPPTrans( (UINT16*)pDst, uiDstPitchBYTES,
|
|
(UINT16 *)pSrc, uiSrcPitchBYTES, xp, yp, 0, 0, i<3 ? 22 : 44, 15, 0 );
|
|
UnLockVideoSurface( FRAME_BUFFER );
|
|
UnLockVideoSurface( guiMercInvPanelBuffers[i] );
|
|
LoadItemInfo( gpMercSlotItem[i]->usItem, pItemName, NULL );
|
|
//Render the text
|
|
switch( i )
|
|
{
|
|
case 2: //legs (to the right of the box, but move it down to make room for right hand text)
|
|
xp = mercRects[i].iRight + 2;
|
|
yp = mercRects[i].iTop + 8;
|
|
break;
|
|
case 3: //left hand (underneath box and to the left -- obscurred by checkbox)
|
|
xp = mercRects[i].iLeft - 20;
|
|
yp = mercRects[i].iBottom + 2;
|
|
break;
|
|
case 4: //right hand (underneath box)
|
|
xp = mercRects[i].iLeft;
|
|
yp = mercRects[i].iBottom + 2;
|
|
break;
|
|
default: //normal cases (to the right of the box)
|
|
xp = mercRects[i].iRight + 2;
|
|
yp = mercRects[i].iTop;
|
|
break;
|
|
}
|
|
xp += MERCPANEL_X;
|
|
yp += MERCPANEL_Y;
|
|
SetFont( SMALLCOMPFONT );
|
|
if( i == gbCurrSelect )
|
|
ubFontColor = FONT_LTRED;
|
|
else if( i == gbCurrHilite )
|
|
ubFontColor = FONT_YELLOW;
|
|
else
|
|
ubFontColor = FONT_WHITE;
|
|
DisplayWrappedString( (UINT16)xp, (UINT16)yp, 60, 2, SMALLCOMPFONT, ubFontColor, pItemName, 0, FALSE, LEFT_JUSTIFIED );
|
|
}
|
|
}
|
|
}
|
|
|
|
void DeleteSelectedMercsItem()
|
|
{
|
|
if( gbCurrSelect != -1 )
|
|
{
|
|
gusMercsNewItemIndex = 0;
|
|
AddNewItemToSelectedMercsInventory( TRUE );
|
|
}
|
|
}
|
|
|
|
//This function does two main things:
|
|
// 1) Allows a new item to be created via usItem and assigned to the currently selected merc.
|
|
// 2) Converts the image from interface size to the smaller panel used by the editor. The slots
|
|
// in the editor are approximately 80% of that size. This involves scaling calculations. These
|
|
// images are saved in individual slots are are blitted to the screen during rendering, not here.
|
|
// NOTE: Step one can be skipped (when selecting an existing merc). By setting the
|
|
void AddNewItemToSelectedMercsInventory( BOOLEAN fCreate )
|
|
{
|
|
UINT32 uiVideoObjectIndex;
|
|
UINT32 uiSrcID, uiDstID;
|
|
HVOBJECT hVObject;
|
|
ETRLEObject *pObject;
|
|
INVTYPE *item;
|
|
SGPRect SrcRect, DstRect;
|
|
INT32 iSrcWidth, iSrcHeight;
|
|
INT32 iDstWidth, iDstHeight;
|
|
float rScalar, rWidthScalar, rHeightScalar;
|
|
BOOLEAN fUnDroppable;
|
|
|
|
if( fCreate )
|
|
{
|
|
/*
|
|
if( gpMercSlotItem[ gbCurrSelect ] && gpMercSlotItem[ gbCurrSelect ]->usItem == gusMercsNewItemIndex )
|
|
{ //User selected same item, so ignore.
|
|
gusMercsNewItemIndex = 0xffff;
|
|
return;
|
|
}
|
|
*/
|
|
if( gusMercsNewItemIndex == 0xffff )
|
|
{ //User selected no item, so ignore.
|
|
return;
|
|
}
|
|
//Create the item, and set up the slot.
|
|
fUnDroppable = gpSelected->pDetailedPlacement->Inv[ gbMercSlotTypes[ gbCurrSelect ] ].fFlags & OBJECT_UNDROPPABLE ? TRUE : FALSE;
|
|
|
|
if ( Item[ gusMercsNewItemIndex ].usItemClass == IC_KEY )
|
|
{
|
|
CreateKeyObject( &gpSelected->pDetailedPlacement->Inv[ gbMercSlotTypes[ gbCurrSelect ] ], 1, (UINT8) eInfo.sSelItemIndex );
|
|
}
|
|
else
|
|
{
|
|
CreateItem( gusMercsNewItemIndex, 100, &gpSelected->pDetailedPlacement->Inv[ gbMercSlotTypes[ gbCurrSelect ] ] );
|
|
}
|
|
if( fUnDroppable )
|
|
{
|
|
gpSelected->pDetailedPlacement->Inv[ gbMercSlotTypes[ gbCurrSelect ] ].fFlags |= OBJECT_UNDROPPABLE;
|
|
}
|
|
|
|
//randomize the status on non-ammo items.
|
|
if( !(Item[ gpSelected->pDetailedPlacement->Inv[ gbMercSlotTypes[ gbCurrSelect ] ].usItem ].usItemClass & IC_AMMO) )
|
|
{
|
|
gpSelected->pDetailedPlacement->Inv[ gbMercSlotTypes[ gbCurrSelect ] ][0]->data.objectStatus = (INT8)(80 + Random( 21 ));
|
|
gpSelected->pDetailedPlacement->Inv[ gbMercSlotTypes[ gbCurrSelect ] ][0]->data.sRepairThreshold = max(1, min(100, (100 + gpSelected->pDetailedPlacement->Inv[ gbMercSlotTypes[ gbCurrSelect ] ][0]->data.objectStatus)/2 ));
|
|
}
|
|
|
|
if( gusMercsNewItemIndex )
|
|
{
|
|
gpSelected->pDetailedPlacement->Inv[ gbMercSlotTypes[ gbCurrSelect ] ].fFlags |= OBJECT_NO_OVERWRITE;
|
|
}
|
|
}
|
|
//allow the slot to point to the selected merc's inventory for editing/rendering purposes.
|
|
gpMercSlotItem[ gbCurrSelect ] = &gpSelected->pDetailedPlacement->Inv[ gbMercSlotTypes[ gbCurrSelect ] ];
|
|
|
|
if( !fCreate )
|
|
{ //it is possible to have a null item which we don't want to blit! Also, we need to set the
|
|
//new item index, so that it can extract the item's image using that.
|
|
gusMercsNewItemIndex = gpMercSlotItem[ gbCurrSelect ]->usItem;
|
|
if( !gpMercSlotItem[ gbCurrSelect ] )
|
|
return;
|
|
}
|
|
//GOAL:
|
|
//From here on, we are going to first render the new item into a temp buffer, then crop the image in
|
|
//the buffer and scale it down to fit into it's associated slot in the panel (which on average will
|
|
//require scaling the item by 80%). We have to do a bunch of calculations to override the offsets, etc.
|
|
//Each slot has it's own smaller version buffer, and this is what gets drawn when the rendering happens.
|
|
|
|
//assign the buffers
|
|
uiSrcID = guiMercTempBuffer;
|
|
uiDstID = guiMercInvPanelBuffers[ gbCurrSelect ];
|
|
|
|
//build the rects
|
|
iDstWidth = gbCurrSelect < 3 ? MERCINV_SMSLOT_WIDTH : MERCINV_LGSLOT_WIDTH;
|
|
iDstHeight = MERCINV_SLOT_HEIGHT;
|
|
SrcRect.iLeft = 0;
|
|
SrcRect.iTop = 0;
|
|
SrcRect.iRight = 60;
|
|
SrcRect.iBottom = 25;
|
|
DstRect.iLeft = 0;
|
|
DstRect.iTop = 0;
|
|
DstRect.iRight = iDstWidth;
|
|
DstRect.iBottom = iDstHeight;
|
|
|
|
//clear both buffers (fill with black to erase previous graphic)
|
|
ColorFillVideoSurfaceArea( uiSrcID, SrcRect.iLeft, SrcRect.iTop, SrcRect.iRight, SrcRect.iBottom, 0 );
|
|
ColorFillVideoSurfaceArea( uiDstID, DstRect.iLeft, DstRect.iTop, DstRect.iRight, DstRect.iBottom, 0 );
|
|
|
|
//if the index is 0, then there is no item.
|
|
if( !gusMercsNewItemIndex )
|
|
return;
|
|
|
|
//now draw the fullsize item into the temp buffer
|
|
item = &Item[ gusMercsNewItemIndex ];
|
|
uiVideoObjectIndex = GetInterfaceGraphicForItem( item );
|
|
GetVideoObject( &hVObject, uiVideoObjectIndex );
|
|
|
|
UINT16 usGraphicNum = g_bUsePngItemImages ? 0 : item->ubGraphicNum;
|
|
BltVideoObjectOutlineFromIndex( uiSrcID, uiVideoObjectIndex, usGraphicNum, 0, 0, 0, FALSE );
|
|
|
|
//crop the source image
|
|
pObject = &hVObject->pETRLEObject[ usGraphicNum ];
|
|
iSrcWidth = pObject->usWidth;
|
|
iSrcHeight = pObject->usHeight;
|
|
SrcRect.iLeft += pObject->sOffsetX;
|
|
SrcRect.iRight = SrcRect.iLeft + iSrcWidth;
|
|
SrcRect.iTop += pObject->sOffsetY;
|
|
SrcRect.iBottom = SrcRect.iTop + iSrcHeight;
|
|
|
|
//if the source image width is less than 30 (small slot), then modify the DstRect.
|
|
if( iSrcWidth < 30 )
|
|
iDstWidth = MERCINV_SMSLOT_WIDTH;
|
|
else
|
|
iDstWidth = MERCINV_LGSLOT_WIDTH;
|
|
|
|
//compare the sizes of the cropped image to the destination buffer size, and calculate the
|
|
//scalar value. It is possible to have scalars > 1.0, in which case, we change it to 1.0 and
|
|
//use the other value.
|
|
rWidthScalar = (float)iDstWidth/(float)iSrcWidth;
|
|
if( rWidthScalar > 1.0 )
|
|
rWidthScalar = 1.0;
|
|
rHeightScalar = (float)iDstHeight/(float)iSrcHeight;
|
|
if( rHeightScalar > 1.0 )
|
|
rHeightScalar = 1.0;
|
|
|
|
//determine which scalar to use.
|
|
if( rWidthScalar == 1.0 )
|
|
rScalar = rHeightScalar;
|
|
else if( rHeightScalar == 1.0 )
|
|
rScalar = rWidthScalar ;
|
|
else
|
|
rScalar = max( rWidthScalar, rHeightScalar );
|
|
|
|
//apply the scalar to the destination width and height
|
|
iDstWidth = (INT32)( iSrcWidth * rScalar );
|
|
iDstHeight = (INT32)( iSrcHeight * rScalar );
|
|
|
|
//sometimes it is possible to scale too big, so clip if applicable
|
|
if( iDstWidth > MERCINV_LGSLOT_WIDTH )
|
|
iDstWidth = MERCINV_LGSLOT_WIDTH;
|
|
else if( gbCurrSelect < 3 && iDstWidth > MERCINV_SMSLOT_WIDTH )
|
|
iDstWidth = MERCINV_SMSLOT_WIDTH;
|
|
if( iDstHeight > MERCINV_SLOT_HEIGHT )
|
|
iDstHeight = MERCINV_SLOT_HEIGHT;
|
|
|
|
//use the new width and height values to calculate the new dest rect (center the item)
|
|
DstRect.iLeft = (DstRect.iRight - DstRect.iLeft - iDstWidth) / 2;
|
|
DstRect.iRight = DstRect.iLeft + iDstWidth;
|
|
DstRect.iTop = (DstRect.iBottom - DstRect.iTop - iDstHeight) / 2;
|
|
DstRect.iBottom = DstRect.iTop + iDstHeight;
|
|
|
|
//scale the item down to the smaller buffer.
|
|
BltStretchVideoSurface( uiDstID, uiSrcID, 0, 0, VO_BLT_SRCTRANSPARENCY, &SrcRect, &DstRect );
|
|
|
|
//invalidate the mercs new item index
|
|
gusMercsNewItemIndex = 0xffff;
|
|
}
|
|
|
|
void RenderMercInventoryPanel()
|
|
{
|
|
INT32 x;
|
|
//Draw the graphical panel
|
|
BltVideoObjectFromIndex( FRAME_BUFFER, guiMercInventoryPanel, 0, MERCPANEL_X, MERCPANEL_Y, VO_BLT_SRCTRANSPARENCY, NULL );
|
|
//Mark the buttons dirty, so they don't disappear.
|
|
for( x = FIRST_MERCS_INVENTORY_BUTTON; x <= LAST_MERCS_INVENTORY_BUTTON; x++ )
|
|
{
|
|
MarkAButtonDirty( iEditorButton[ x ] );
|
|
}
|
|
RenderButtons();
|
|
if( gbCurrHilite != -1 )
|
|
DrawRect( &mercRects[ gbCurrHilite ], Get16BPPColor( FROMRGB( 200, 200, 0 ) ) );
|
|
if( gbCurrSelect != -1 )
|
|
DrawRect( &mercRects[ gbCurrSelect ], Get16BPPColor( FROMRGB( 200, 0, 0 ) ) );
|
|
RenderSelectedMercsInventory();
|
|
InvalidateRegion( MERCPANEL_X, MERCPANEL_Y, iScreenWidthOffset + 475, 2 * iScreenHeightOffset + 460 );
|
|
UpdateItemStatsPanel();
|
|
}
|
|
|
|
|
|
//This function is called by the move and click callback functions for the region blanketing the
|
|
//9 slots in the inventory panel. It passes the event type as well as the relative x and y positions
|
|
//which are processed here. This basically checks for new changes in hilighting and selections, which
|
|
//will set the rendering flag, and getitem flag if the user wishes to choose an item.
|
|
void HandleMercInventoryPanel( INT16 sX, INT16 sY, INT8 bEvent )
|
|
{
|
|
INT8 x;
|
|
if( !gfCanEditMercs && bEvent == GUI_RCLICK_EVENT )
|
|
{ //if we are dealing with a profile merc, we can't allow editing
|
|
//of items, but we can look at them. So, treat all right clicks
|
|
//as if they were left clicks.
|
|
bEvent = GUI_LCLICK_EVENT;
|
|
}
|
|
switch( bEvent )
|
|
{
|
|
case GUI_MOVE_EVENT:
|
|
//user is moving the mouse around the panel, so determine which slot
|
|
//needs to be hilighted yellow.
|
|
for( x = 0; x < 9; x++ )
|
|
{
|
|
if( PointInRect( &mercRects[x], sX, sY ) )
|
|
{
|
|
if( gbCurrHilite != x ) //only render if the slot isn't the same one.
|
|
gfRenderMercInfo = TRUE;
|
|
gbCurrHilite = x;
|
|
return;
|
|
}
|
|
}
|
|
//if we don't find a valid slot, then we need to turn it off.
|
|
if( gbCurrHilite != -1 )
|
|
{ //only turn off if it isn't already off. This avoids unecessary rendering.
|
|
gbCurrHilite = -1;
|
|
gfRenderMercInfo = TRUE;
|
|
}
|
|
break;
|
|
case GUI_LCLICK_EVENT:
|
|
case GUI_RCLICK_EVENT:
|
|
//The user has clicked in the inventory panel. Determine if he clicked in
|
|
//a slot. Left click selects the slot for editing, right clicking enables
|
|
//the user to choose an item for that slot.
|
|
for( x = 0; x < 9; x++ )
|
|
{
|
|
if( PointInRect( &mercRects[x], sX, sY ) )
|
|
{
|
|
if( gbCurrSelect != x ) //only if it isn't the same slot.
|
|
{
|
|
gfRenderMercInfo = TRUE;
|
|
if( bEvent == GUI_LCLICK_EVENT )
|
|
SpecifyItemToEdit( gpMercSlotItem[ x ], -1 );
|
|
}
|
|
if( bEvent == GUI_RCLICK_EVENT ) //user r-clicked, so enable item choosing
|
|
{
|
|
gfRenderMercInfo = TRUE;//dnl ch79 271113
|
|
gfMercGetItem = TRUE;
|
|
}
|
|
gbCurrSelect = x;
|
|
return;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
void UpdateMercItemSlots()
|
|
{
|
|
INT8 x;
|
|
if( !gpSelected->pDetailedPlacement )
|
|
{
|
|
for( x = 0; x < 9; x++ )
|
|
{
|
|
gpMercSlotItem[ x ] = NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if( gpSelected->pDetailedPlacement->ubProfile != NO_PROFILE )
|
|
{
|
|
gpSelected->pDetailedPlacement->Inv = gpSelected->pSoldier->inv;
|
|
}
|
|
for( x = 0; x < 9; x++ )
|
|
{
|
|
//Set the curr select and the addnewitem function will handle the rest, including rebuilding
|
|
//the nine slot buffers, etc.
|
|
gbCurrSelect = x;
|
|
AddNewItemToSelectedMercsInventory( FALSE );
|
|
}
|
|
}
|
|
SetDroppableCheckboxesBasedOnMercsInventory();
|
|
SpecifyItemToEdit( NULL, -1 );
|
|
gbCurrSelect = -1;
|
|
gbCurrHilite = -1;
|
|
}
|
|
|
|
void SetDroppableCheckboxesBasedOnMercsInventory()
|
|
{
|
|
OBJECTTYPE *pItem;
|
|
INT32 i;
|
|
if( gpSelected && gpSelected->pDetailedPlacement )
|
|
{
|
|
for( i = 0; i < 9; i++ )
|
|
{
|
|
pItem = &gpSelected->pDetailedPlacement->Inv[ gbMercSlotTypes[ i ] ];
|
|
if( (*pItem).fFlags & OBJECT_UNDROPPABLE )
|
|
{ //check box is clear
|
|
UnclickEditorButton( MERCS_HEAD_SLOT + i );
|
|
}
|
|
else
|
|
{
|
|
ClickEditorButton( MERCS_HEAD_SLOT + i );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void SetEnemyColorCode( UINT8 ubColorCode )
|
|
{
|
|
if( gpSelected->pDetailedPlacement && gpSelected->pDetailedPlacement->ubProfile != NO_PROFILE )
|
|
return;
|
|
|
|
UnclickEditorButtons( FIRST_MERCS_COLORCODE_BUTTON, LAST_MERCS_COLORCODE_BUTTON );
|
|
switch( ubColorCode )
|
|
{
|
|
case SOLDIER_CLASS_ARMY:
|
|
gpSelected->pBasicPlacement->ubSoldierClass = SOLDIER_CLASS_ARMY;
|
|
gubSoldierClass = SOLDIER_CLASS_ARMY;
|
|
if( gpSelected->pDetailedPlacement )
|
|
gpSelected->pDetailedPlacement->ubSoldierClass = SOLDIER_CLASS_ARMY;
|
|
SET_PALETTEREP_ID( gpSelected->pSoldier->VestPal, "REDVEST" );
|
|
SET_PALETTEREP_ID( gpSelected->pSoldier->PantsPal, "GREENPANTS" );
|
|
ClickEditorButton( MERCS_ARMY_CODE );
|
|
break;
|
|
case SOLDIER_CLASS_ADMINISTRATOR:
|
|
gpSelected->pBasicPlacement->ubSoldierClass = SOLDIER_CLASS_ADMINISTRATOR;
|
|
gubSoldierClass = SOLDIER_CLASS_ADMINISTRATOR;
|
|
if( gpSelected->pDetailedPlacement )
|
|
gpSelected->pDetailedPlacement->ubSoldierClass = SOLDIER_CLASS_ADMINISTRATOR;
|
|
ClickEditorButton( MERCS_ADMIN_CODE );
|
|
SET_PALETTEREP_ID( gpSelected->pSoldier->VestPal, "BLUEVEST" );
|
|
SET_PALETTEREP_ID( gpSelected->pSoldier->PantsPal, "BLUEPANTS" );
|
|
break;
|
|
case SOLDIER_CLASS_ELITE:
|
|
gpSelected->pBasicPlacement->ubSoldierClass = SOLDIER_CLASS_ELITE;
|
|
gubSoldierClass = SOLDIER_CLASS_ELITE;
|
|
if( gpSelected->pDetailedPlacement )
|
|
gpSelected->pDetailedPlacement->ubSoldierClass = SOLDIER_CLASS_ELITE;
|
|
SET_PALETTEREP_ID( gpSelected->pSoldier->VestPal, "BLACKSHIRT" );
|
|
SET_PALETTEREP_ID( gpSelected->pSoldier->PantsPal, "BLACKPANTS" );
|
|
ClickEditorButton( MERCS_ELITE_CODE );
|
|
break;
|
|
case SOLDIER_CLASS_MINER:
|
|
//will probably never get called
|
|
|
|
// WANNE: Fix a vanilla bug in the editor: When selecting a miner, he was turned into an elite soldier.
|
|
// Fixed by Tron (Straciatella): Revision: 6650
|
|
gpSelected->pBasicPlacement->ubSoldierClass = SOLDIER_CLASS_MINER;
|
|
gubSoldierClass = SOLDIER_CLASS_MINER;
|
|
if( gpSelected->pDetailedPlacement )
|
|
gpSelected->pDetailedPlacement->ubSoldierClass = SOLDIER_CLASS_MINER;
|
|
SET_PALETTEREP_ID( gpSelected->pSoldier->VestPal, "greyVEST" );
|
|
SET_PALETTEREP_ID( gpSelected->pSoldier->PantsPal, "BEIGEPANTS" );
|
|
break;
|
|
|
|
default:
|
|
return;
|
|
}
|
|
gpSelected->pSoldier->CreateSoldierPalettes( );
|
|
}
|
|
|
|
void SetEnemyDroppableStatus( UINT32 uiSlot, BOOLEAN fDroppable )
|
|
{
|
|
if( gpSelected )
|
|
{
|
|
if( fDroppable )
|
|
{
|
|
if( gpSelected->pDetailedPlacement )
|
|
gpSelected->pDetailedPlacement->Inv[ uiSlot ].fFlags &= (~OBJECT_UNDROPPABLE);
|
|
if( gpSelected->pSoldier )
|
|
gpSelected->pSoldier->inv[ uiSlot ].fFlags &= (~OBJECT_UNDROPPABLE);
|
|
}
|
|
else
|
|
{
|
|
if( gpSelected->pDetailedPlacement )
|
|
gpSelected->pDetailedPlacement->Inv[ uiSlot ].fFlags |= OBJECT_UNDROPPABLE;
|
|
if( gpSelected->pSoldier )
|
|
gpSelected->pSoldier->inv[ uiSlot ].fFlags |= OBJECT_UNDROPPABLE;
|
|
}
|
|
}
|
|
if( gbCurrSelect != -1 && uiSlot == (UINT32)gbMercSlotTypes[ gbCurrSelect ] )
|
|
{
|
|
if( gpMercSlotItem[ gbCurrSelect ]->exists() == false )
|
|
SpecifyItemToEdit( gpMercSlotItem[ gbCurrSelect ], -1 );
|
|
}
|
|
}
|
|
|
|
void ChangeCivGroup( UINT8 ubNewCivGroup )
|
|
{
|
|
Assert( ubNewCivGroup < NUM_CIV_GROUPS );
|
|
if( gubCivGroup == ubNewCivGroup )
|
|
return;
|
|
gubCivGroup = ubNewCivGroup;
|
|
if( gpSelected && gpSelected->pSoldier )
|
|
{
|
|
gpSelected->pBasicPlacement->ubCivilianGroup = gubCivGroup;
|
|
if( gpSelected->pDetailedPlacement )
|
|
gpSelected->pDetailedPlacement->ubCivilianGroup = gubCivGroup;
|
|
gpSelected->pSoldier->ubCivilianGroup = gubCivGroup;
|
|
}
|
|
//Adjust the text on the button
|
|
SpecifyButtonText( iEditorButton[ MERCS_CIVILIAN_GROUP ], gszCivGroupNames[ gubCivGroup ] );
|
|
}
|
|
|
|
void RenderMercStrings()
|
|
{
|
|
SOLDIERTYPE *pSoldier;
|
|
INT16 sXPos, sYPos;
|
|
INT16 sX, sY;
|
|
STR16 pStr, pStr2;
|
|
SOLDIERINITNODE *curr;
|
|
CHAR16 str[50];
|
|
|
|
curr = gSoldierInitHead;
|
|
while( curr )
|
|
{
|
|
if( curr->pSoldier && curr->pSoldier->bVisible == 1 )
|
|
{ //Render the health text
|
|
pSoldier = curr->pSoldier;
|
|
GetSoldierAboveGuyPositions( pSoldier, &sXPos, &sYPos, FALSE );
|
|
// Display name
|
|
SetFont( TINYFONT1 );
|
|
SetFontBackground( FONT_BLACK );
|
|
SetFontForeground( FONT_WHITE );
|
|
if ( pSoldier->ubProfile != NO_PROFILE )
|
|
{
|
|
FindFontCenterCoordinates( sXPos, sYPos, (INT16)(80 ), 1, pSoldier->name, TINYFONT1, &sX, &sY );
|
|
if( sY < (2 * iScreenHeightOffset + 352 ))
|
|
{
|
|
gprintfdirty( sX, sY, pSoldier->name );
|
|
mprintf( sX, sY, pSoldier->name );
|
|
}
|
|
sYPos += 10;
|
|
|
|
pStr = GetSoldierHealthString( pSoldier );
|
|
|
|
SetFont( TINYFONT1 );
|
|
SetFontBackground( FONT_BLACK );
|
|
SetFontForeground( FONT_RED );
|
|
|
|
FindFontCenterCoordinates( sXPos, sYPos, 80, 1, pStr, TINYFONT1, &sX, &sY );
|
|
if( sY < (2 * iScreenHeightOffset + 352 ))
|
|
{
|
|
gprintfdirty( sX, sY, pStr );
|
|
mprintf( sX, sY, pStr );
|
|
}
|
|
sYPos += 10;
|
|
|
|
SetFontForeground( FONT_GRAY2 );
|
|
swprintf( str, pRenderMercStringsText[0], pSoldier->ubID );
|
|
FindFontCenterCoordinates( sXPos, sYPos, 80, 1, str, TINYFONT1, &sX, &sY );
|
|
if( sY < (2 * iScreenHeightOffset + 352 ))
|
|
{
|
|
gprintfdirty( sX, sY, str );
|
|
mprintf( sX, sY, str );
|
|
}
|
|
sYPos += 10;
|
|
|
|
|
|
if (pSoldier->bTeam == CIV_TEAM )
|
|
{
|
|
//legion2
|
|
pStr2 = GetGrupaString( pSoldier );
|
|
|
|
SetFontBackground( FONT_MCOLOR_BLACK );
|
|
SetFontForeground( FONT_YELLOW ); //FONT_MCOLOR_WHITE
|
|
FindFontCenterCoordinates( sXPos, sYPos, 80, 1, pStr2, TINYFONT1, &sX, &sY );
|
|
if( sY < (2 * iScreenHeightOffset + 352 ))
|
|
{
|
|
gprintfdirty( sX, sY, pStr2 );
|
|
mprintf( sX, sY, pStr2 );
|
|
}
|
|
sYPos += 10;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
pStr = GetSoldierHealthString( pSoldier );
|
|
|
|
SetFont( TINYFONT1 );
|
|
SetFontBackground( FONT_BLACK );
|
|
SetFontForeground( FONT_RED );
|
|
|
|
FindFontCenterCoordinates( sXPos, sYPos, 80, 1, pStr, TINYFONT1, &sX, &sY );
|
|
if( sY < (2 * iScreenHeightOffset + 352 ))
|
|
{
|
|
gprintfdirty( sX, sY, pStr );
|
|
mprintf( sX, sY, pStr );
|
|
}
|
|
sYPos += 10;
|
|
|
|
SetFontForeground( FONT_GRAY2 );
|
|
swprintf( str, pRenderMercStringsText[0], pSoldier->ubID );
|
|
FindFontCenterCoordinates( sXPos, sYPos, 80, 1, str, TINYFONT1, &sX, &sY );
|
|
if( sY < (2 * iScreenHeightOffset + 352) )
|
|
{
|
|
gprintfdirty( sX, sY, str );
|
|
mprintf( sX, sY, str );
|
|
}
|
|
sYPos += 10;
|
|
|
|
//legion
|
|
if (pSoldier->bTeam == CIV_TEAM ) //(pSoldier->bTeam == ENEMY_TEAM || pSoldier->bTeam == CREATURE_TEAM || pSoldier->bTeam == MILITIA_TEAM)
|
|
{
|
|
//legion 2
|
|
pStr2 = GetGrupaString( pSoldier );
|
|
|
|
//SetFont( TINYFONT1 );
|
|
SetFontBackground( FONT_MCOLOR_BLACK );
|
|
SetFontForeground( FONT_YELLOW ); //FONT_MCOLOR_WHITE
|
|
FindFontCenterCoordinates( sXPos, sYPos, 80, 1, pStr2, TINYFONT1, &sX, &sY );
|
|
if( sY < (2 * iScreenHeightOffset + 352 ))
|
|
{
|
|
gprintfdirty( sX, sY, pStr2 );
|
|
mprintf( sX, sY, pStr2 );
|
|
}
|
|
sYPos += 10;
|
|
}
|
|
|
|
}
|
|
if( curr->pBasicPlacement->bOrders == RNDPTPATROL || curr->pBasicPlacement->bOrders == POINTPATROL )
|
|
{ //make sure the placement has at least one waypoint.
|
|
if( !curr->pBasicPlacement->bPatrolCnt )
|
|
{
|
|
if( GetJA2Clock() % 1000 < 500 )
|
|
SetFontForeground( FONT_DKRED );
|
|
else
|
|
SetFontForeground( FONT_RED );
|
|
swprintf( str, pRenderMercStringsText[1] );
|
|
FindFontCenterCoordinates( sXPos, sYPos, 80, 1, str, TINYFONT1, &sX, &sY );
|
|
if( sY < (2 * iScreenHeightOffset + 352) )
|
|
{
|
|
gprintfdirty( sX, sY, str );
|
|
mprintf( sX, sY, str );
|
|
}
|
|
sYPos += 10;
|
|
}
|
|
}
|
|
else if( curr->pBasicPlacement->bPatrolCnt )
|
|
{
|
|
if( GetJA2Clock() % 1000 < 500 )
|
|
SetFontForeground( FONT_DKRED );
|
|
else
|
|
SetFontForeground( FONT_RED );
|
|
swprintf( str, pRenderMercStringsText[2] );
|
|
FindFontCenterCoordinates( sXPos, sYPos, 80, 1, str, TINYFONT1, &sX, &sY );
|
|
if( sY < (2 * iScreenHeightOffset + 352) )
|
|
{
|
|
gprintfdirty( sX, sY, str );
|
|
mprintf( sX, sY, str );
|
|
}
|
|
sYPos += 10;
|
|
}
|
|
}
|
|
curr = curr->next;
|
|
}
|
|
if( gubCurrMercMode == MERC_SCHEDULEMODE )
|
|
{
|
|
RenderCurrentSchedule();
|
|
}
|
|
}
|
|
|
|
void SetMercTeamVisibility( INT8 bTeam, BOOLEAN fVisible )
|
|
{
|
|
SOLDIERINITNODE *curr;
|
|
INT8 bVisible;
|
|
curr = gSoldierInitHead;
|
|
bVisible = fVisible ? 1 : -1;
|
|
while( curr )
|
|
{
|
|
if( curr->pBasicPlacement->bTeam == bTeam )
|
|
{
|
|
if( curr->pSoldier )
|
|
{
|
|
curr->pSoldier->bLastRenderVisibleValue = bVisible;
|
|
curr->pSoldier->bVisible = bVisible;
|
|
}
|
|
}
|
|
curr = curr->next;
|
|
}
|
|
if( gpSelected && gpSelected->pSoldier && gpSelected->pSoldier->bTeam == bTeam && !fVisible )
|
|
{
|
|
IndicateSelectedMerc( SELECT_NO_MERC );
|
|
}
|
|
}
|
|
|
|
void DetermineScheduleEditability()
|
|
{
|
|
INT32 i;
|
|
EnableEditorButtons( MERCS_SCHEDULE_ACTION1, MERCS_SCHEDULE_DATA4B );
|
|
EnableTextFields( 1, 4 );
|
|
for( i = 0; i < 4; i++ )
|
|
{
|
|
switch( gCurrSchedule.ubAction[i] )
|
|
{
|
|
case SCHEDULE_ACTION_NONE:
|
|
case SCHEDULE_ACTION_LEAVESECTOR:
|
|
EnableEditorButton( MERCS_SCHEDULE_ACTION1 + i );
|
|
EnableEditorButton( MERCS_SCHEDULE_VARIANCE1 + i );
|
|
HideEditorButton( MERCS_SCHEDULE_DATA1A + i );
|
|
HideEditorButton( MERCS_SCHEDULE_DATA1B + i );
|
|
break;
|
|
case SCHEDULE_ACTION_LOCKDOOR:
|
|
case SCHEDULE_ACTION_UNLOCKDOOR:
|
|
case SCHEDULE_ACTION_OPENDOOR:
|
|
case SCHEDULE_ACTION_CLOSEDOOR:
|
|
EnableEditorButton( MERCS_SCHEDULE_ACTION1 + i );
|
|
EnableEditorButton( MERCS_SCHEDULE_VARIANCE1 + i );
|
|
ShowEditorButton( MERCS_SCHEDULE_DATA1A + i );
|
|
ShowEditorButton( MERCS_SCHEDULE_DATA1B + i );
|
|
EnableEditorButton( MERCS_SCHEDULE_DATA1A + i );
|
|
EnableEditorButton( MERCS_SCHEDULE_DATA1B + i );
|
|
break;
|
|
case SCHEDULE_ACTION_GRIDNO:
|
|
case SCHEDULE_ACTION_ENTERSECTOR:
|
|
case SCHEDULE_ACTION_SLEEP:
|
|
EnableEditorButton( MERCS_SCHEDULE_ACTION1 + i );
|
|
EnableEditorButton( MERCS_SCHEDULE_VARIANCE1 + i );
|
|
ShowEditorButton( MERCS_SCHEDULE_DATA1A + i );
|
|
HideEditorButton( MERCS_SCHEDULE_DATA1B + i );
|
|
EnableEditorButton( MERCS_SCHEDULE_DATA1A + i );
|
|
break;
|
|
case SCHEDULE_ACTION_STAYINSECTOR:
|
|
DisableTextField( (UINT8)(i+1) );
|
|
EnableEditorButton( MERCS_SCHEDULE_ACTION1 + i );
|
|
DisableEditorButton( MERCS_SCHEDULE_VARIANCE1 + i );
|
|
HideEditorButton( MERCS_SCHEDULE_DATA1A + i );
|
|
HideEditorButton( MERCS_SCHEDULE_DATA1B + i );
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CancelCurrentScheduleAction()
|
|
{
|
|
UpdateScheduleAction( SCHEDULE_ACTION_NONE );
|
|
DetermineScheduleEditability();
|
|
}
|
|
|
|
void RegisterCurrentScheduleAction( INT32 iMapIndex )
|
|
{
|
|
CHAR16 str[10];
|
|
MarkWorldDirty();
|
|
swprintf( str, L"%d", iMapIndex );
|
|
if( gfUseScheduleData2 )
|
|
{
|
|
if( gfSingleAction )
|
|
return;
|
|
iDrawMode = DRAW_MODE_PLAYER + gpSelected->pBasicPlacement->bTeam;
|
|
gCurrSchedule.usData2[ gubCurrentScheduleActionIndex ] = iMapIndex;
|
|
SpecifyButtonText( iEditorButton[ MERCS_SCHEDULE_DATA1B + gubCurrentScheduleActionIndex ], str );
|
|
DetermineScheduleEditability();
|
|
gubScheduleInstructions = SCHEDULE_INSTRUCTIONS_NONE;
|
|
gfRenderTaskbar = TRUE;
|
|
gfUseScheduleData2 = FALSE;
|
|
}
|
|
else
|
|
{
|
|
switch( gCurrSchedule.ubAction[ gubCurrentScheduleActionIndex ] )
|
|
{
|
|
case SCHEDULE_ACTION_LOCKDOOR:
|
|
case SCHEDULE_ACTION_UNLOCKDOOR:
|
|
case SCHEDULE_ACTION_OPENDOOR:
|
|
case SCHEDULE_ACTION_CLOSEDOOR:
|
|
if( gfSingleAction )
|
|
{
|
|
gfSingleAction = FALSE;
|
|
gubScheduleInstructions = SCHEDULE_INSTRUCTIONS_NONE;
|
|
gfRenderTaskbar = TRUE;
|
|
DetermineScheduleEditability();
|
|
break;
|
|
}
|
|
DisableEditorButton( MERCS_SCHEDULE_DATA1A + gubCurrentScheduleActionIndex );
|
|
EnableEditorButton( MERCS_SCHEDULE_DATA1B + gubCurrentScheduleActionIndex );
|
|
gfUseScheduleData2 = TRUE;
|
|
iDrawMode = DRAW_MODE_SCHEDULEACTION;
|
|
gubScheduleInstructions = SCHEDULE_INSTRUCTIONS_DOOR2;
|
|
gfRenderTaskbar = TRUE;
|
|
break;
|
|
case SCHEDULE_ACTION_GRIDNO:
|
|
case SCHEDULE_ACTION_ENTERSECTOR:
|
|
case SCHEDULE_ACTION_SLEEP:
|
|
iDrawMode = DRAW_MODE_PLAYER + gpSelected->pBasicPlacement->bTeam;
|
|
DetermineScheduleEditability();
|
|
gubScheduleInstructions = SCHEDULE_INSTRUCTIONS_NONE;
|
|
gfRenderTaskbar = TRUE;
|
|
break;
|
|
case SCHEDULE_ACTION_LEAVESECTOR:
|
|
case SCHEDULE_ACTION_STAYINSECTOR:
|
|
case SCHEDULE_ACTION_NONE:
|
|
break;
|
|
}
|
|
gCurrSchedule.usData1[ gubCurrentScheduleActionIndex ] = iMapIndex;
|
|
SpecifyButtonText( iEditorButton[ MERCS_SCHEDULE_DATA1A + gubCurrentScheduleActionIndex ], str );
|
|
}
|
|
}
|
|
|
|
void StartScheduleAction()
|
|
{
|
|
switch( gCurrSchedule.ubAction[ gubCurrentScheduleActionIndex ] )
|
|
{
|
|
case SCHEDULE_ACTION_NONE:
|
|
EnableEditorButtons( MERCS_SCHEDULE_ACTION1, MERCS_SCHEDULE_DATA4B );
|
|
EnableTextFields( 1, 4 );
|
|
gubScheduleInstructions = SCHEDULE_INSTRUCTIONS_NONE;
|
|
gfRenderTaskbar = TRUE;
|
|
gCurrSchedule.usData1[ gubCurrentScheduleActionIndex ] = 0xffffffff;
|
|
gCurrSchedule.usData2[ gubCurrentScheduleActionIndex ] = 0xffffffff;
|
|
break;
|
|
case SCHEDULE_ACTION_LOCKDOOR:
|
|
case SCHEDULE_ACTION_UNLOCKDOOR:
|
|
case SCHEDULE_ACTION_OPENDOOR:
|
|
case SCHEDULE_ACTION_CLOSEDOOR:
|
|
//First disable everything -- its easier that way.
|
|
ShowEditorButton( MERCS_SCHEDULE_DATA1A + gubCurrentScheduleActionIndex );
|
|
ShowEditorButton( MERCS_SCHEDULE_DATA1B + gubCurrentScheduleActionIndex );
|
|
DisableEditorButtons( MERCS_SCHEDULE_ACTION1, MERCS_SCHEDULE_DATA4B );
|
|
DisableTextFields( 1, 4 );
|
|
EnableEditorButton( MERCS_SCHEDULE_DATA1A + gubCurrentScheduleActionIndex );
|
|
gfUseScheduleData2 = FALSE;
|
|
iDrawMode = DRAW_MODE_SCHEDULEACTION;
|
|
gubScheduleInstructions = SCHEDULE_INSTRUCTIONS_DOOR1;
|
|
gfRenderTaskbar = TRUE;
|
|
break;
|
|
case SCHEDULE_ACTION_GRIDNO:
|
|
case SCHEDULE_ACTION_ENTERSECTOR:
|
|
case SCHEDULE_ACTION_SLEEP:
|
|
ShowEditorButton( MERCS_SCHEDULE_DATA1A + gubCurrentScheduleActionIndex );
|
|
HideEditorButton( MERCS_SCHEDULE_DATA1B + gubCurrentScheduleActionIndex );
|
|
DisableEditorButtons( MERCS_SCHEDULE_ACTION1, MERCS_SCHEDULE_DATA4B );
|
|
DisableTextFields( 1, 4 );
|
|
EnableEditorButton( MERCS_SCHEDULE_DATA1A + gubCurrentScheduleActionIndex );
|
|
gfUseScheduleData2 = FALSE;
|
|
iDrawMode = DRAW_MODE_SCHEDULEACTION;
|
|
gubScheduleInstructions = SCHEDULE_INSTRUCTIONS_GRIDNO;
|
|
gfRenderTaskbar = TRUE;
|
|
gCurrSchedule.usData2[ gubCurrentScheduleActionIndex ] = 0xffffffff;
|
|
break;
|
|
case SCHEDULE_ACTION_LEAVESECTOR:
|
|
case SCHEDULE_ACTION_STAYINSECTOR:
|
|
gubScheduleInstructions = SCHEDULE_INSTRUCTIONS_NONE;
|
|
gfRenderTaskbar = TRUE;
|
|
gCurrSchedule.usData1[ gubCurrentScheduleActionIndex ] = 0xffffffff;
|
|
gCurrSchedule.usData2[ gubCurrentScheduleActionIndex ] = 0xffffffff;
|
|
break;
|
|
}
|
|
MarkWorldDirty();
|
|
}
|
|
|
|
void UpdateScheduleAction( UINT8 ubNewAction )
|
|
{
|
|
gCurrSchedule.ubAction[ gubCurrentScheduleActionIndex ] = ubNewAction;
|
|
SpecifyButtonText( iEditorButton[ MERCS_SCHEDULE_ACTION1 + gubCurrentScheduleActionIndex ],
|
|
gszScheduleActions[ ubNewAction ] );
|
|
MSYS_SetBtnUserData( iEditorButton[ MERCS_SCHEDULE_ACTION1 + gubCurrentScheduleActionIndex ], 0, ubNewAction );
|
|
//Now, based on this action, disable the other buttons
|
|
StartScheduleAction();
|
|
gfSingleAction = FALSE;
|
|
}
|
|
|
|
// 0:1A, 1:1B, 2:2A, 3:2B, ...
|
|
void FindScheduleGridNo( UINT8 ubScheduleData )
|
|
{
|
|
INT32 iMapIndex = 0xffffffff;
|
|
switch( ubScheduleData )
|
|
{
|
|
case 0: //1a
|
|
iMapIndex = gCurrSchedule.usData1[0];
|
|
break;
|
|
case 1: //1b
|
|
iMapIndex = gCurrSchedule.usData2[0];
|
|
break;
|
|
case 2: //2a
|
|
iMapIndex = gCurrSchedule.usData1[1];
|
|
break;
|
|
case 3: //2b
|
|
iMapIndex = gCurrSchedule.usData2[1];
|
|
break;
|
|
case 4: //3a
|
|
iMapIndex = gCurrSchedule.usData1[2];
|
|
break;
|
|
case 5: //3b
|
|
iMapIndex = gCurrSchedule.usData2[2];
|
|
break;
|
|
case 6: //4a
|
|
iMapIndex = gCurrSchedule.usData1[3];
|
|
break;
|
|
case 7: //4b
|
|
iMapIndex = gCurrSchedule.usData2[3];
|
|
break;
|
|
default:
|
|
AssertMsg( 0, "FindScheduleGridNo passed incorrect dataID." );
|
|
}
|
|
if( iMapIndex != 0xffffffff )
|
|
{
|
|
CenterScreenAtMapIndex( iMapIndex );
|
|
}
|
|
}
|
|
|
|
void ClearCurrentSchedule()
|
|
{
|
|
UINT8 i;
|
|
memset( &gCurrSchedule, 0, sizeof( SCHEDULENODE ) );
|
|
for( i = 0; i < 4; i++ )
|
|
{
|
|
MSYS_SetBtnUserData( iEditorButton[ MERCS_SCHEDULE_ACTION1 + i ], 0, 0 );
|
|
SpecifyButtonText( iEditorButton[ MERCS_SCHEDULE_ACTION1 + i ], pClearCurrentScheduleText[0] );
|
|
gCurrSchedule.usTime[i] = 0xffff;
|
|
SetExclusive24HourTimeValue( (UINT8)(i+1), gCurrSchedule.usTime[ i ] ); //blanks the field
|
|
gCurrSchedule.usData1[i] = 0xffffffff;
|
|
SpecifyButtonText( iEditorButton[ MERCS_SCHEDULE_DATA1A + i ], L"" );
|
|
gCurrSchedule.usData2[i] = 0xffffffff;
|
|
SpecifyButtonText( iEditorButton[ MERCS_SCHEDULE_DATA1B + i ], L"" );
|
|
}
|
|
//Remove the variance stuff
|
|
gCurrSchedule.usFlags = 0;
|
|
UnclickEditorButtons( MERCS_SCHEDULE_VARIANCE1, MERCS_SCHEDULE_VARIANCE4 );
|
|
|
|
gubCurrentScheduleActionIndex = 0;
|
|
DetermineScheduleEditability();
|
|
gfRenderTaskbar = TRUE;
|
|
MarkWorldDirty();
|
|
}
|
|
|
|
void RenderCurrentSchedule()
|
|
{
|
|
FLOAT dOffsetX, dOffsetY;
|
|
FLOAT ScrnX, ScrnY;
|
|
INT32 i;
|
|
INT32 iMapIndex;
|
|
INT16 sXMapPos, sYMapPos;
|
|
INT16 sScreenX, sScreenY;
|
|
INT16 sX, sY;
|
|
CHAR16 str[ 3 ];
|
|
for( i = 0; i < 8; i++ )
|
|
{
|
|
if( i % 2 )
|
|
iMapIndex = gCurrSchedule.usData2[ i / 2 ];
|
|
else
|
|
iMapIndex = gCurrSchedule.usData1[ i / 2 ];
|
|
|
|
if( iMapIndex == 0xffff )
|
|
continue;
|
|
|
|
// Convert it's location to screen coordinates
|
|
ConvertGridNoToXY( iMapIndex, &sXMapPos, &sYMapPos );
|
|
|
|
dOffsetX = (FLOAT)(sXMapPos * CELL_X_SIZE) - gsRenderCenterX;
|
|
dOffsetY = (FLOAT)(sYMapPos * CELL_Y_SIZE) - gsRenderCenterY;
|
|
|
|
FloatFromCellToScreenCoordinates( dOffsetX, dOffsetY, &ScrnX, &ScrnY);
|
|
|
|
sScreenX = ( ( gsVIEWPORT_END_X - gsVIEWPORT_START_X ) /2 ) + (INT16)ScrnX;
|
|
sScreenY = ( ( gsVIEWPORT_END_Y - gsVIEWPORT_START_Y ) /2 ) + (INT16)ScrnY;
|
|
|
|
// Adjust for tiles height factor!
|
|
sScreenY -= gpWorldLevelData[ iMapIndex ].sHeight;
|
|
// Bring it down a touch
|
|
sScreenY += 5;
|
|
|
|
if( sScreenY <= (2 * iScreenHeightOffset + 355) )
|
|
{
|
|
// Shown it on screen!
|
|
SetFont(TINYFONT1);
|
|
SetFontBackground( FONT_LTKHAKI );
|
|
SetFontForeground( FONT_WHITE );
|
|
swprintf( str, L"%d%c", i/2 + 1, 'A' + (i%2) );
|
|
VarFindFontCenterCoordinates( sScreenX, sScreenY, 1, 1, TINYFONT1, &sX, &sY, str );
|
|
mprintf( sX, sY, str );
|
|
}
|
|
}
|
|
}
|
|
|
|
void UpdateScheduleInfo()
|
|
{
|
|
INT32 i;
|
|
SCHEDULENODE *pSchedule;
|
|
CHAR16 str[6];
|
|
if( gpSelected->pSoldier->ubScheduleID )
|
|
{
|
|
pSchedule = GetSchedule( gpSelected->pSoldier->ubScheduleID );
|
|
if( !pSchedule )
|
|
{
|
|
return;
|
|
}
|
|
for( i = 0; i < 4; i++ )
|
|
{ //Update the text and buttons
|
|
MSYS_SetBtnUserData( iEditorButton[ MERCS_SCHEDULE_ACTION1 + i ], 0, pSchedule->ubAction[i] );
|
|
SpecifyButtonText( iEditorButton[ MERCS_SCHEDULE_ACTION1 + i ], gszScheduleActions[ pSchedule->ubAction[i] ] );
|
|
swprintf( str, L"" );
|
|
if( pSchedule->usData1[i] != 0xffffffff )
|
|
swprintf( str, L"%d", pSchedule->usData1[i] );
|
|
SpecifyButtonText( iEditorButton[ MERCS_SCHEDULE_DATA1A + i ], str );
|
|
swprintf( str, L"" );
|
|
if( pSchedule->usData2[i] != 0xffffffff )
|
|
swprintf( str, L"%d", pSchedule->usData2[i] );
|
|
SpecifyButtonText( iEditorButton[ MERCS_SCHEDULE_DATA1B + i ], str );
|
|
if( gubCurrMercMode == MERC_SCHEDULEMODE )
|
|
{ //Update the text input fields too!
|
|
SetExclusive24HourTimeValue( (UINT8)(i+1), pSchedule->usTime[i] );
|
|
}
|
|
}
|
|
|
|
//Check or uncheck the checkbox buttons based on the schedule's status.
|
|
UnclickEditorButtons( MERCS_SCHEDULE_VARIANCE1, MERCS_SCHEDULE_VARIANCE4 );
|
|
if( pSchedule->usFlags & SCHEDULE_FLAGS_VARIANCE1 )
|
|
ClickEditorButton( MERCS_SCHEDULE_VARIANCE1 );
|
|
if( pSchedule->usFlags & SCHEDULE_FLAGS_VARIANCE2 )
|
|
ClickEditorButton( MERCS_SCHEDULE_VARIANCE2 );
|
|
if( pSchedule->usFlags & SCHEDULE_FLAGS_VARIANCE3 )
|
|
ClickEditorButton( MERCS_SCHEDULE_VARIANCE3 );
|
|
if( pSchedule->usFlags & SCHEDULE_FLAGS_VARIANCE4 )
|
|
ClickEditorButton( MERCS_SCHEDULE_VARIANCE4 );
|
|
|
|
//Copy the schedule over to the current global schedule used for editing purposes.
|
|
memcpy( &gCurrSchedule, pSchedule, sizeof( SCHEDULENODE ) );
|
|
DetermineScheduleEditability();
|
|
}
|
|
else
|
|
{
|
|
ClearCurrentSchedule();
|
|
}
|
|
}
|
|
|
|
BASIC_SOLDIERCREATE_STRUCT gSaveBufferBasicPlacement;
|
|
SOLDIERCREATE_STRUCT gSaveBufferDetailedPlacement;
|
|
|
|
void CopyMercPlacement( INT32 iMapIndex )
|
|
{
|
|
if( gsSelectedMercID == -1 )
|
|
{
|
|
ScreenMsg( FONT_MCOLOR_LTRED, MSG_INTERFACE, pCopyMercPlacementText[0] );
|
|
return;
|
|
}
|
|
gfSaveBuffer = TRUE;
|
|
memcpy( &gSaveBufferBasicPlacement, gpSelected->pBasicPlacement, sizeof( BASIC_SOLDIERCREATE_STRUCT ) );
|
|
if( gSaveBufferBasicPlacement.fDetailedPlacement )
|
|
{
|
|
gSaveBufferDetailedPlacement = *gpSelected->pDetailedPlacement;
|
|
}
|
|
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, pCopyMercPlacementText[1] );
|
|
}
|
|
|
|
void PasteMercPlacement( INT32 iMapIndex )
|
|
{
|
|
SOLDIERTYPE *pSoldier;
|
|
SOLDIERCREATE_STRUCT tempDetailedPlacement;
|
|
INT32 i;
|
|
|
|
if( !gfSaveBuffer )
|
|
{
|
|
ScreenMsg( FONT_MCOLOR_LTRED, MSG_INTERFACE, pPasteMercPlacementText[0] );
|
|
return;
|
|
}
|
|
|
|
memcpy( &gTempBasicPlacement, &gSaveBufferBasicPlacement, sizeof( BASIC_SOLDIERCREATE_STRUCT ) );
|
|
|
|
gTempBasicPlacement.ubBodyType = -1;
|
|
|
|
//calculate specific information based on the team.
|
|
switch( iDrawMode )
|
|
{
|
|
case DRAW_MODE_ENEMY:
|
|
gTempBasicPlacement.bTeam = ENEMY_TEAM;
|
|
gTempBasicPlacement.ubBodyType = RANDOM;
|
|
gTempBasicPlacement.ubSoldierClass = gubSoldierClass;
|
|
break;
|
|
case DRAW_MODE_CREATURE:
|
|
gTempBasicPlacement.bTeam = CREATURE_TEAM;
|
|
gTempBasicPlacement.ubBodyType = gbCurrCreature;
|
|
break;
|
|
case DRAW_MODE_REBEL:
|
|
gTempBasicPlacement.bTeam = MILITIA_TEAM;
|
|
gTempBasicPlacement.ubBodyType = RANDOM;
|
|
break;
|
|
case DRAW_MODE_CIVILIAN:
|
|
gTempBasicPlacement.bTeam = CIV_TEAM;
|
|
gTempBasicPlacement.ubBodyType = RANDOM;
|
|
gTempBasicPlacement.ubCivilianGroup = gubCivGroup;
|
|
if( giCurrentTilesetID == 1 ) //caves
|
|
{
|
|
gTempBasicPlacement.ubSoldierClass = SOLDIER_CLASS_MINER;
|
|
}
|
|
break;
|
|
}
|
|
|
|
if( IsLocationSittable( iMapIndex, gfRoofPlacement ) )
|
|
{
|
|
SoldierID ubID;
|
|
INT16 sSectorX, sSectorY;
|
|
SOLDIERINITNODE *pNode;
|
|
|
|
GetCurrentWorldSector( &sSectorX, &sSectorY );
|
|
|
|
//Set up some general information.
|
|
//gTempBasicPlacement.fDetailedPlacement = TRUE;
|
|
gTempBasicPlacement.usStartingGridNo = iMapIndex;
|
|
|
|
//Generate detailed placement information given the temp placement information.
|
|
if( gTempBasicPlacement.fDetailedPlacement )
|
|
{
|
|
gTempDetailedPlacement = gSaveBufferDetailedPlacement;
|
|
}
|
|
else
|
|
{
|
|
CreateDetailedPlacementGivenBasicPlacementInfo( &gTempDetailedPlacement, &gTempBasicPlacement );
|
|
}
|
|
|
|
//Set the sector information -- probably unnecessary.
|
|
gTempDetailedPlacement.sSectorX = sSectorX;
|
|
gTempDetailedPlacement.sSectorY = sSectorY;
|
|
|
|
if( gTempBasicPlacement.fDetailedPlacement )
|
|
{
|
|
CreateDetailedPlacementGivenStaticDetailedPlacementAndBasicPlacementInfo( &tempDetailedPlacement, &gTempDetailedPlacement, &gTempBasicPlacement, sSectorX, sSectorY );
|
|
}
|
|
else
|
|
{
|
|
tempDetailedPlacement = gTempDetailedPlacement;
|
|
}
|
|
|
|
//Create the soldier, but don't place it yet.
|
|
if ( pSoldier = TacticalCreateSoldier( &tempDetailedPlacement, &ubID ) )
|
|
{
|
|
pSoldier->bVisible = 1;
|
|
pSoldier->bLastRenderVisibleValue = 1;
|
|
//Set up the soldier in the list, so we can track the soldier in the
|
|
//future (saving, loading, strategic AI)
|
|
pNode = AddBasicPlacementToSoldierInitList( &gTempBasicPlacement );
|
|
Assert( pNode );
|
|
pNode->pSoldier = pSoldier;
|
|
if( gSaveBufferBasicPlacement.fDetailedPlacement )
|
|
{ //Add the static detailed placement information in the same newly created node as the basic placement.
|
|
//read static detailed placement from file
|
|
//allocate memory for new static detailed placement
|
|
gTempBasicPlacement.fDetailedPlacement = TRUE;
|
|
gTempBasicPlacement.fPriorityExistance = gSaveBufferBasicPlacement.fPriorityExistance;
|
|
pNode->pDetailedPlacement = new SOLDIERCREATE_STRUCT(gSaveBufferDetailedPlacement);
|
|
//copy the file information from temp var to node in list.
|
|
if( !pNode->pDetailedPlacement )
|
|
{
|
|
AssertMsg( 0, "Failed to allocate memory for new detailed placement in PasteMercPlacement." );
|
|
return;
|
|
}
|
|
}
|
|
|
|
//Add the soldier to physically appear on the map now.
|
|
InternalAddSoldierToSector( ubID, FALSE, FALSE, 0, 0 );
|
|
IndicateSelectedMerc( ubID );
|
|
|
|
//Move him to the roof if intended and possible.
|
|
if( gfRoofPlacement && FlatRoofAboveGridNo( iMapIndex ) )
|
|
{
|
|
gpSelected->pBasicPlacement->fOnRoof = TRUE;
|
|
if( gpSelected->pDetailedPlacement )
|
|
gpSelected->pDetailedPlacement->fOnRoof = TRUE;
|
|
gpSelected->pSoldier->SetSoldierHeight( 58.0 );
|
|
}
|
|
UnclickEditorButtons( FIRST_MERCS_INVENTORY_BUTTON, LAST_MERCS_INVENTORY_BUTTON );
|
|
for( i = FIRST_MERCS_INVENTORY_BUTTON; i <= LAST_MERCS_INVENTORY_BUTTON; i++ )
|
|
{
|
|
SetEnemyDroppableStatus( gbMercSlotTypes[i-FIRST_MERCS_INVENTORY_BUTTON], FALSE );
|
|
}
|
|
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, pPasteMercPlacementText[1] );
|
|
}
|
|
else
|
|
{
|
|
ScreenMsg( FONT_MCOLOR_LTRED, MSG_INTERFACE, pPasteMercPlacementText[2] );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|