2007-01-15 12:09:25 -08:00
/*
This file is part of Warzone 2100.
Copyright ( C ) 1999 - 2004 Eidos Interactive
2013-01-16 12:34:57 -08:00
Copyright ( C ) 2005 - 2013 Warzone 2100 Project
2007-01-15 12:09:25 -08:00
Warzone 2100 is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 2 of the License , or
( at your option ) any later version .
Warzone 2100 is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with Warzone 2100 ; if not , write to the Free Software
Foundation , Inc . , 51 Franklin St , Fifth Floor , Boston , MA 02110 - 1301 USA
*/
2008-02-16 05:05:34 -08:00
/**
2008-03-10 06:31:08 -07:00
* @ file hci . c
2007-06-28 10:47:08 -07:00
*
* Functions for the in game interface .
2008-02-16 05:05:34 -08:00
* ( Human Computer Interface - thanks to Alex for the file name ) .
2007-06-28 10:47:08 -07:00
*
2008-07-11 05:41:42 -07:00
* Obviously HCI should mean " Hellish Code Incoming " - - Toksyuryel .
*
2007-06-28 10:47:08 -07:00
*/
2006-11-06 06:40:07 -08:00
# include <string.h>
2011-01-04 06:48:00 -08:00
# include <algorithm>
2007-06-28 10:47:08 -07:00
2006-05-27 09:37:17 -07:00
# include "lib/framework/frame.h"
2006-09-23 10:24:55 -07:00
# include "lib/framework/strres.h"
2009-02-10 09:23:09 -08:00
# include "lib/framework/stdio_ext.h"
2006-12-02 04:50:28 -08:00
# include "lib/gamelib/gtime.h"
2010-12-31 13:37:14 -08:00
# include "lib/ivis_opengl/bitimage.h"
# include "lib/ivis_opengl/pieblitfunc.h"
# include "lib/ivis_opengl/piepalette.h"
# include "lib/ivis_opengl/piestate.h"
2006-05-27 09:37:17 -07:00
// FIXME Direct iVis implementation include!
# include "lib/ivis_opengl/screen.h"
2006-12-02 04:50:28 -08:00
# include "lib/script/script.h"
2009-06-07 11:10:13 -07:00
# include "lib/netplay/netplay.h"
2007-06-28 10:47:08 -07:00
2006-12-02 04:50:28 -08:00
# include "action.h"
2007-03-27 11:59:03 -07:00
# include "lib/sound/audio_id.h"
2007-07-13 15:14:47 -07:00
# include "lib/sound/audio.h"
2013-02-25 15:24:53 -08:00
# include "lib/widget/label.h"
# include "lib/widget/bar.h"
2013-05-21 11:48:17 -07:00
# include "lib/widget/button.h"
2006-12-02 04:50:28 -08:00
# include "console.h"
# include "design.h"
# include "display.h"
2007-06-28 10:47:08 -07:00
# include "display3d.h"
2006-12-02 04:50:28 -08:00
# include "drive.h"
2007-06-28 10:47:08 -07:00
# include "edit3d.h"
2006-12-02 04:50:28 -08:00
# include "effects.h"
2007-06-28 10:47:08 -07:00
# include "game.h"
2006-12-02 04:50:28 -08:00
# include "hci.h"
# include "ingameop.h"
2007-06-28 10:47:08 -07:00
# include "intdisplay.h"
# include "intelmap.h"
# include "intorder.h"
2006-12-02 04:50:28 -08:00
# include "keymap.h"
# include "loadsave.h"
# include "loop.h"
2007-06-28 10:47:08 -07:00
# include "mapdisplay.h"
# include "mission.h"
2006-12-02 04:50:28 -08:00
# include "multimenu.h"
# include "multiplay.h"
2008-01-06 13:55:23 -08:00
# include "multigifts.h"
2006-12-02 04:50:28 -08:00
# include "radar.h"
# include "research.h"
# include "scriptcb.h"
# include "scriptextern.h"
# include "scripttabs.h"
2007-06-28 10:47:08 -07:00
# include "transporter.h"
# include "warcam.h"
2007-09-24 11:16:10 -07:00
# include "main.h"
2011-12-17 15:23:51 -08:00
# include "template.h"
2007-06-28 10:47:08 -07:00
# include "wrappers.h"
2008-04-21 01:28:39 -07:00
# include "keybind.h"
2011-12-30 11:48:40 -08:00
# include "qtscript.h"
2007-06-28 10:47:08 -07:00
2013-08-02 11:27:20 -07:00
// Is a button widget highlighted, either because the cursor is over it or it is flashing.
//
# define buttonIsHilite(p) ((p->getState() & WBUT_HIGHLIGHT) != 0)
2007-06-28 10:47:08 -07:00
2008-04-05 15:58:33 -07:00
// Empty edit window
2012-12-21 07:32:23 -08:00
static bool SecondaryWindowUp = false ;
2008-01-26 09:12:20 -08:00
2007-06-28 10:47:08 -07:00
# define RETXOFFSET (0) // Reticule button offset
# define RETYOFFSET (0)
# define NUMRETBUTS 7 // Number of reticule buttons.
2012-12-21 07:35:35 -08:00
enum / / Reticule button indecies .
{
2007-06-28 10:47:08 -07:00
RETBUT_CANCEL ,
RETBUT_FACTORY ,
RETBUT_RESEARCH ,
RETBUT_BUILD ,
RETBUT_DESIGN ,
RETBUT_INTELMAP ,
RETBUT_COMMAND ,
} ;
2011-02-25 12:30:13 -08:00
struct BUTSTATE
{
2007-06-28 10:47:08 -07:00
UDWORD id ;
2011-03-12 17:32:15 -08:00
bool Enabled ;
bool Hidden ;
2011-02-25 12:30:13 -08:00
} ;
2007-06-28 10:47:08 -07:00
2011-02-25 12:30:13 -08:00
struct BUTOFFSET
{
2007-06-28 10:47:08 -07:00
SWORD x ;
SWORD y ;
2011-02-25 12:30:13 -08:00
} ;
2007-06-28 10:47:08 -07:00
2012-12-27 14:34:15 -08:00
static BUTOFFSET ReticuleOffsets [ NUMRETBUTS ] = // Reticule button form relative positions.
2012-12-21 07:35:35 -08:00
{
{ 48 , 47 } , // RETBUT_CANCEL,
{ 53 , 15 } , // RETBUT_FACTORY,
{ 87 , 33 } , // RETBUT_RESEARCH,
{ 87 , 68 } , // RETBUT_BUILD,
{ 53 , 86 } , // RETBUT_DESIGN,
{ 19 , 68 } , // RETBUT_INTELMAP,
{ 19 , 33 } , // RETBUT_COMMAND,
2007-06-28 10:47:08 -07:00
} ;
2012-12-27 14:34:15 -08:00
static BUTSTATE ReticuleEnabled [ NUMRETBUTS ] = // Reticule button enable states.
2012-12-21 07:35:35 -08:00
{
{ IDRET_CANCEL , false , false } ,
{ IDRET_MANUFACTURE , false , false } ,
{ IDRET_RESEARCH , false , false } ,
{ IDRET_BUILD , false , false } ,
{ IDRET_DESIGN , false , false } ,
{ IDRET_INTEL_MAP , false , false } ,
{ IDRET_COMMAND , false , false } ,
2007-06-28 10:47:08 -07:00
} ;
static UDWORD keyButtonMapping = 0 ;
2012-12-21 06:01:30 -08:00
static bool ReticuleUp = false ;
2012-12-27 14:34:15 -08:00
static bool Refreshing = false ;
2007-06-28 10:47:08 -07:00
/***************************************************************************************/
/* Widget ID numbers */
# define IDPOW_FORM 100 // power bar form
/* Option screen IDs */
# define IDOPT_FORM 1000 // The option form
# define IDOPT_CLOSE 1006 // The close button
# define IDOPT_LABEL 1007 // The Option screen label
# define IDOPT_PLAYERFORM 1008 // The player button form
# define IDOPT_PLAYERLABEL 1009 // The player form label
# define IDOPT_PLAYERSTART 1010 // The first player button
# define IDOPT_PLAYEREND 1030 // The last possible player button
# define IDOPT_QUIT 1031 // Quit the game
# define IDOPT_DROID 1037 // The place droid button
# define IDOPT_STRUCT 1038 // The place struct button
# define IDOPT_FEATURE 1039 // The place feature button
2010-03-06 15:06:35 -08:00
# define IDOPT_IVISFORM 1043 // iViS engine form
# define IDOPT_IVISLABEL 1044 // iViS form label
2007-06-28 10:47:08 -07:00
2010-01-22 02:25:42 -08:00
# define IDPROX_START 120000 // The first proximity button
# define IDPROX_END 129999 // The last proximity button
2007-06-28 10:47:08 -07:00
# define PROX_BUTWIDTH 9
# define PROX_BUTHEIGHT 9
/***************************************************************************************/
/* Widget Positions */
/* Reticule positions */
# define RET_BUTWIDTH 25
# define RET_BUTHEIGHT 28
/* Option positions */
# define OPT_X (640-300)
# define OPT_Y 20
# define OPT_WIDTH 275
# define OPT_HEIGHT 350
# define OPT_BUTWIDTH 60
# define OPT_BUTHEIGHT 20
2012-12-21 06:01:30 -08:00
# define OPT_EDITY 50
2007-06-28 10:47:08 -07:00
# define OPT_PLAYERY 150
2012-12-21 07:32:23 -08:00
2007-06-28 10:47:08 -07:00
# define STAT_BUTX 4
# define STAT_BUTY 2
/* Structure type screen positions */
# define STAT_GAP 2
2006-05-27 09:37:17 -07:00
# define STAT_BUTWIDTH 60
2007-06-28 10:47:08 -07:00
# define STAT_BUTHEIGHT 46
/* Close strings */
2006-11-03 13:35:50 -08:00
static char pCloseText [ ] = " X " ;
2007-06-28 10:47:08 -07:00
/* Player button strings */
2007-04-13 08:18:49 -07:00
static const char * apPlayerText [ ] =
2007-06-28 10:47:08 -07:00
{
" 0 " , " 1 " , " 2 " , " 3 " , " 4 " , " 5 " , " 6 " , " 7 " ,
2011-01-18 13:57:37 -08:00
" 8 " , " 9 " , " 10 " , " 11 " , " 12 " , " 13 " , " 14 " , " 15 " ,
2007-06-28 10:47:08 -07:00
} ;
2007-04-13 08:18:49 -07:00
static const char * apPlayerTip [ ] =
2007-06-28 10:47:08 -07:00
{
" Select Player 0 " ,
" Select Player 1 " ,
" Select Player 2 " ,
" Select Player 3 " ,
" Select Player 4 " ,
" Select Player 5 " ,
" Select Player 6 " ,
" Select Player 7 " ,
2011-01-03 05:48:41 -08:00
" Select Player 8 " ,
" Select Player 9 " ,
2011-01-18 13:57:37 -08:00
" Select Player 10 " ,
" Select Player 11 " ,
" Select Player 12 " ,
" Select Player 13 " ,
" Select Player 14 " ,
" Select Player 15 " ,
2007-06-28 10:47:08 -07:00
} ;
/* The widget screen */
W_SCREEN * psWScreen ;
// The last widget ID from widgRunScreen
UDWORD intLastWidget ;
INTMODE intMode ;
/* Status of the positioning for the object placement */
2012-12-18 06:59:49 -08:00
static enum _edit_pos_mode
2007-06-28 10:47:08 -07:00
{
2006-05-27 09:37:17 -07:00
IED_NOPOS ,
2007-06-28 10:47:08 -07:00
IED_POS ,
} editPosMode ;
/* Which type of object screen is being displayed. Starting value is where the intMode left off*/
2012-12-18 06:59:49 -08:00
static enum _obj_mode
2007-06-28 10:47:08 -07:00
{
2006-05-27 09:37:17 -07:00
IOBJ_NONE = INT_MAXMODE , // Nothing doing.
2007-06-28 10:47:08 -07:00
IOBJ_BUILD , // The build screen
IOBJ_BUILDSEL , // Selecting a position for a new structure
IOBJ_DEMOLISHSEL , // Selecting a structure to demolish
IOBJ_MANUFACTURE , // The manufacture screen
IOBJ_RESEARCH , // The research screen
IOBJ_COMMAND , // the command droid screen
IOBJ_MAX , // maximum object mode
} objMode ;
/* Function type for selecting a base object while building the object screen */
2011-03-12 17:32:15 -08:00
typedef bool ( * OBJ_SELECT ) ( BASE_OBJECT * psObj ) ;
2012-12-21 07:32:23 -08:00
2007-06-28 10:47:08 -07:00
/* Function type for getting the appropriate stats for an object */
typedef BASE_STATS * ( * OBJ_GETSTATS ) ( BASE_OBJECT * psObj ) ;
2012-12-21 07:32:23 -08:00
2007-06-28 10:47:08 -07:00
/* Function type for setting the appropriate stats for an object */
2011-03-12 17:32:15 -08:00
typedef bool ( * OBJ_SETSTATS ) ( BASE_OBJECT * psObj , BASE_STATS * psStats ) ;
2007-06-28 10:47:08 -07:00
/* functions to select and get stats from the current object list */
static OBJ_SELECT objSelectFunc ;
2012-12-18 06:59:49 -08:00
static OBJ_GETSTATS objGetStatsFunc ;
2007-06-28 10:47:08 -07:00
static OBJ_SETSTATS objSetStatsFunc ;
/* Whether the objects that are on the object screen have changed this frame */
2011-03-12 17:32:15 -08:00
static bool objectsChanged ;
2007-06-28 10:47:08 -07:00
/* The current stats list being used by the stats screen */
static BASE_STATS * * ppsStatsList ;
static UDWORD numStatsListEntries ;
/* The selected object on the object screen when the stats screen is displayed */
static BASE_OBJECT * psObjSelected ;
/* The button ID of the objects stat when the stat screen is displayed */
UDWORD objStatID ;
/* The button ID of an objects stat on the stat screen if it is locked down */
static UDWORD statID ;
/* The stats for the current getStructPos */
static BASE_STATS * psPositionStats ;
/* The tab positions of the object form when the structure form is displayed */
2013-02-13 01:11:10 -08:00
static UWORD objMajor ;
2007-06-28 10:47:08 -07:00
/* Store a list of stats pointers from the main structure stats */
static STRUCTURE_STATS * * apsStructStatsList ;
/* Store a list of research pointers for topics that can be performed*/
static RESEARCH * * ppResearchList ;
/* Store a list of Template pointers for Droids that can be built */
2011-02-13 09:57:25 -08:00
std : : vector < DROID_TEMPLATE * > apsTemplateList ;
std : : list < DROID_TEMPLATE > localTemplates ;
2007-06-28 10:47:08 -07:00
/* Store a list of Feature pointers for features to be placed on the map */
static FEATURE_STATS * * apsFeatureList ;
/*Store a list of research indices which can be performed*/
static UWORD * pList ;
static UWORD * pSList ;
/* Store a list of component stats pointers for the design screen */
UDWORD numComponent ;
2008-07-11 08:37:46 -07:00
COMPONENT_STATS * * apsComponentList ;
2007-06-28 10:47:08 -07:00
UDWORD numExtraSys ;
2008-07-11 08:37:46 -07:00
COMPONENT_STATS * * apsExtraSysList ;
2007-06-28 10:47:08 -07:00
// store the objects that are being used for the object bar
2011-01-04 06:48:00 -08:00
std : : vector < BASE_OBJECT * > apsObjectList ;
2007-06-28 10:47:08 -07:00
/* Flags to check whether the power bars are currently on the screen */
2011-03-12 17:32:15 -08:00
static bool powerBarUp = false ;
static bool StatsUp = false ;
2007-06-28 10:47:08 -07:00
static BASE_OBJECT * psStatsScreenOwner = NULL ;
/* The previous object for each object bar */
static BASE_OBJECT * apsPreviousObj [ IOBJ_MAX ] ;
/* The jump position for each object on the base bar */
2011-01-04 06:48:00 -08:00
static std : : vector < Vector2i > asJumpPos ;
2007-06-28 10:47:08 -07:00
/***************************************************************************************/
/* Function Prototypes */
2012-12-21 07:35:35 -08:00
static bool intUpdateObject ( BASE_OBJECT * psObjects , BASE_OBJECT * psSelected , bool bForceStats ) ;
2007-06-28 10:47:08 -07:00
/* Remove the object widgets from the widget screen */
void intRemoveObject ( void ) ;
static void intRemoveObjectNoAnim ( void ) ;
/* Process the object widgets */
static void intProcessObject ( UDWORD id ) ;
/* Get the object refered to by a button ID on the object screen.
* This works for droid or structure buttons
*/
static BASE_OBJECT * intGetObject ( UDWORD id ) ;
/* Reset the stats button for an object */
static void intSetStats ( UDWORD id , BASE_STATS * psStats ) ;
/* Add the stats widgets to the widget screen */
/* If psSelected != NULL it specifies which stat should be hilited */
2011-03-12 17:32:15 -08:00
static bool intAddStats ( BASE_STATS * * ppsStatsList , UDWORD numStats ,
2012-12-21 07:35:35 -08:00
BASE_STATS * psSelected , BASE_OBJECT * psOwner ) ;
2007-06-28 10:47:08 -07:00
/* Process return codes from the stats screen */
static void intProcessStats ( UDWORD id ) ;
// clean up when an object dies
2007-05-27 15:15:10 -07:00
static void intObjectDied ( UDWORD objID ) ;
2007-06-28 10:47:08 -07:00
/* Add the build widgets to the widget screen */
/* If psSelected != NULL it specifies which droid should be hilited */
2011-03-12 17:32:15 -08:00
static bool intAddBuild ( DROID * psSelected ) ;
2007-06-28 10:47:08 -07:00
/* Add the manufacture widgets to the widget screen */
/* If psSelected != NULL it specifies which factory should be hilited */
2011-03-12 17:32:15 -08:00
static bool intAddManufacture ( STRUCTURE * psSelected ) ;
2007-06-28 10:47:08 -07:00
/* Add the research widgets to the widget screen */
/* If psSelected != NULL it specifies which droid should be hilited */
2011-03-12 17:32:15 -08:00
static bool intAddResearch ( STRUCTURE * psSelected ) ;
2007-06-28 10:47:08 -07:00
/* Add the command droid widgets to the widget screen */
/* If psSelected != NULL it specifies which droid should be hilited */
2011-03-12 17:32:15 -08:00
static bool intAddCommand ( DROID * psSelected ) ;
2007-06-28 10:47:08 -07:00
/* Start looking for a structure location */
2008-10-14 15:02:35 -07:00
static void intStartStructPosition ( BASE_STATS * psStats ) ;
2007-06-28 10:47:08 -07:00
/* Stop looking for a structure location */
static void intStopStructPosition ( void ) ;
static STRUCTURE * CurrentStruct = NULL ;
static SWORD CurrentStructType = 0 ;
static DROID * CurrentDroid = NULL ;
2012-12-21 07:32:23 -08:00
static DROID_TYPE CurrentDroidType = DROID_ANY ;
2007-06-28 10:47:08 -07:00
/******************Power Bar Stuff!**************/
/* Set the shadow for the PowerBar */
static void intRunPower ( void ) ;
static void intRunStats ( void ) ;
/*Deals with the RMB click for the stats screen */
static void intStatsRMBPressed ( UDWORD id ) ;
/*Deals with the RMB click for the object screen */
static void intObjectRMBPressed ( UDWORD id ) ;
/*Deals with the RMB click for the Object Stats buttons */
static void intObjStatRMBPressed ( UDWORD id ) ;
//proximity display stuff
static void processProximityButtons ( UDWORD id ) ;
2012-12-21 07:35:35 -08:00
static DROID * intCheckForDroid ( UDWORD droidType ) ;
static STRUCTURE * intCheckForStructure ( UDWORD structType ) ;
2007-06-28 10:47:08 -07:00
static void intCheckReticuleButtons ( void ) ;
// count the number of selected droids of a type
2007-05-27 15:15:10 -07:00
static SDWORD intNumSelectedDroids ( UDWORD droidType ) ;
2007-06-28 10:47:08 -07:00
/***************************GAME CODE ****************************/
2012-12-21 06:01:30 -08:00
2013-08-02 11:27:20 -07:00
struct RETBUTSTATS
{
int downTime ;
QString filename ;
QString filenameDown ;
2013-08-02 12:05:32 -07:00
QString tip ;
2013-08-02 11:27:20 -07:00
int flashing ;
int flashTime ;
} ;
static RETBUTSTATS retbutstats [ NUMRETBUTS ] ;
2013-08-02 12:05:32 -07:00
void setReticuleStats ( int ButId , QString tip , QString filename , QString filenameDown )
{
retbutstats [ ButId ] . tip = tip ;
retbutstats [ ButId ] . filename = filename ;
retbutstats [ ButId ] . filenameDown = filenameDown ;
retbutstats [ ButId ] . downTime = 0 ;
retbutstats [ ButId ] . flashing = 0 ;
retbutstats [ ButId ] . flashTime = 0 ;
}
2013-08-02 11:27:20 -07:00
static void intDisplayReticuleButton ( WIDGET * psWidget , UDWORD xOffset , UDWORD yOffset )
{
int x = xOffset + psWidget - > x ( ) ;
int y = yOffset + psWidget - > y ( ) ;
bool Hilight = false ;
bool Down = false ;
UBYTE DownTime = retbutstats [ psWidget - > UserData ] . downTime ;
UBYTE flashing = retbutstats [ psWidget - > UserData ] . flashing ;
UBYTE flashTime = retbutstats [ psWidget - > UserData ] . flashTime ;
ASSERT ( psWidget - > type = = WIDG_BUTTON , " Not a button " ) ;
W_BUTTON * psButton = ( W_BUTTON * ) psWidget ;
if ( psButton - > state & WBUT_DISABLE )
{
iV_DrawImage ( IntImages , IMAGE_RETICULE_GREY , x , y ) ;
return ;
}
Down = psButton - > state & ( WBUT_DOWN | WBUT_CLICKLOCK ) ;
Hilight = buttonIsHilite ( psButton ) ;
if ( Down )
{
if ( ( DownTime < 1 ) & & ( psWidget - > UserData ! = RETBUT_CANCEL ) )
{
iV_DrawImage ( IntImages , IMAGE_RETICULE_BUTDOWN , x , y ) ;
}
else
{
iV_DrawImage2 ( retbutstats [ psWidget - > UserData ] . filenameDown , x , y ) ;
}
DownTime + + ;
flashing = false ; // stop the reticule from flashing if it was
}
else
{
if ( flashing )
{
if ( ( ( realTime / 250 ) % 2 ) ! = 0 )
{
iV_DrawImage2 ( retbutstats [ psWidget - > UserData ] . filenameDown , x , y ) ;
flashTime = 0 ;
}
else
{
iV_DrawImage2 ( retbutstats [ psWidget - > UserData ] . filename , x , y ) ;
}
flashTime + + ;
}
else
{
iV_DrawImage2 ( retbutstats [ psWidget - > UserData ] . filename , x , y ) ;
DownTime = 0 ;
}
}
if ( Hilight )
{
if ( psWidget - > UserData = = RETBUT_CANCEL )
{
iV_DrawImage ( IntImages , IMAGE_CANCEL_HILIGHT , x , y ) ;
}
else
{
iV_DrawImage ( IntImages , IMAGE_RETICULE_HILIGHT , x , y ) ;
}
}
retbutstats [ psWidget - > UserData ] . flashTime = flashTime ;
retbutstats [ psWidget - > UserData ] . flashing = flashing ;
retbutstats [ psWidget - > UserData ] . downTime = DownTime ;
}
2012-12-21 06:01:30 -08:00
// Set the x,y members of a button widget initialiser given a reticule button index.
//
2013-08-02 12:05:32 -07:00
void setReticuleBut ( int ButId )
2012-12-21 06:01:30 -08:00
{
2012-12-27 14:34:15 -08:00
/* Default button data */
W_BUTINIT sButInit ;
sButInit . formID = IDRET_FORM ;
sButInit . id = ReticuleEnabled [ ButId ] . id ;
sButInit . width = RET_BUTWIDTH ;
sButInit . height = RET_BUTHEIGHT ;
sButInit . pDisplay = intDisplayReticuleButton ;
sButInit . x = ReticuleOffsets [ ButId ] . x + RETXOFFSET ;
sButInit . y = ReticuleOffsets [ ButId ] . y + RETYOFFSET ;
2013-08-02 12:05:32 -07:00
sButInit . pTip = retbutstats [ ButId ] . tip ;
2013-08-02 11:27:20 -07:00
sButInit . style = WBUT_SECONDARY ;
sButInit . UserData = ButId ;
retbutstats [ ButId ] . downTime = 0 ;
retbutstats [ ButId ] . flashing = 0 ;
retbutstats [ ButId ] . flashTime = 0 ;
2012-12-27 14:34:15 -08:00
if ( ! widgAddButton ( psWScreen , & sButInit ) )
{
debug ( LOG_ERROR , " Failed to add reticule button " ) ;
}
2012-12-21 06:01:30 -08:00
}
2007-06-28 10:47:08 -07:00
/* Initialise the in game interface */
2011-03-12 17:32:15 -08:00
bool intInitialise ( void )
2007-06-28 10:47:08 -07:00
{
2012-12-21 06:50:06 -08:00
for ( int i = 0 ; i < NUMRETBUTS ; i + + )
{
ReticuleEnabled [ i ] . Hidden = false ;
}
2007-06-28 10:47:08 -07:00
2008-04-20 10:17:50 -07:00
widgSetTipColour ( WZCOL_TOOLTIP_TEXT ) ;
2007-06-28 10:47:08 -07:00
2012-12-21 07:35:35 -08:00
if ( GetGameMode ( ) = = GS_NORMAL )
{
WidgSetAudio ( WidgetAudioCallback , - 1 , ID_SOUND_SELECT ) ;
}
else
{
WidgSetAudio ( WidgetAudioCallback , - 1 , ID_SOUND_SELECT ) ;
2007-06-28 10:47:08 -07:00
}
/* Create storage for Structures that can be built */
2012-12-21 07:32:23 -08:00
apsStructStatsList = ( STRUCTURE_STATS * * ) malloc ( sizeof ( STRUCTURE_STATS * ) * MAXSTRUCTURES ) ;
2007-06-28 10:47:08 -07:00
//create the storage for Research topics - max possible size
2007-04-15 03:43:05 -07:00
ppResearchList = ( RESEARCH * * ) malloc ( sizeof ( RESEARCH * ) * MAXRESEARCH ) ;
2007-06-28 10:47:08 -07:00
//create the list for the selected player
//needs to be UWORD sized for Patches
2012-12-21 07:35:35 -08:00
pList = ( UWORD * ) malloc ( sizeof ( UWORD ) * MAXRESEARCH ) ;
pSList = ( UWORD * ) malloc ( sizeof ( UWORD ) * MAXRESEARCH ) ;
2007-06-28 10:47:08 -07:00
/* Create storage for Templates that can be built */
2011-02-13 09:57:25 -08:00
apsTemplateList . clear ( ) ;
2007-06-28 10:47:08 -07:00
/* Create storage for the feature list */
2012-12-21 07:32:23 -08:00
apsFeatureList = ( FEATURE_STATS * * ) malloc ( sizeof ( FEATURE_STATS * ) * MAXFEATURES ) ;
2007-06-28 10:47:08 -07:00
/* Create storage for the component list */
2012-12-21 07:32:23 -08:00
apsComponentList = ( COMPONENT_STATS * * ) malloc ( sizeof ( COMPONENT_STATS * ) * MAXCOMPONENT ) ;
2007-06-28 10:47:08 -07:00
/* Create storage for the extra systems list */
2012-12-21 07:32:23 -08:00
apsExtraSysList = ( COMPONENT_STATS * * ) malloc ( sizeof ( COMPONENT_STATS * ) * MAXEXTRASYS ) ;
2007-06-28 10:47:08 -07:00
// allocate the object list
2011-01-04 06:48:00 -08:00
apsObjectList . clear ( ) ;
2007-06-28 10:47:08 -07:00
intInitialiseGraphics ( ) ;
2013-02-15 23:44:47 -08:00
psWScreen = new W_SCREEN ;
2007-06-28 10:47:08 -07:00
/* Note the current screen state */
intMode = INT_NORMAL ;
2008-03-24 09:51:17 -07:00
objectsChanged = false ;
2007-06-28 10:47:08 -07:00
// reset the previous objects
intResetPreviousObj ( ) ;
// reset the jump positions
2011-01-04 06:48:00 -08:00
asJumpPos . clear ( ) ;
2007-06-28 10:47:08 -07:00
/* make demolish stat always available */
2012-12-21 07:35:35 -08:00
if ( ! bInTutorial )
2007-06-28 10:47:08 -07:00
{
2012-12-21 07:32:23 -08:00
for ( int comp = 0 ; comp < numStructureStats ; comp + + )
2007-06-28 10:47:08 -07:00
{
if ( asStructureStats [ comp ] . type = = REF_DEMOLISH )
{
2012-12-21 07:32:23 -08:00
for ( int inc = 0 ; inc < MAX_PLAYERS ; inc + + )
2007-06-28 10:47:08 -07:00
{
apStructTypeLists [ inc ] [ comp ] = AVAILABLE ;
}
}
}
}
2008-03-24 09:51:17 -07:00
return true ;
2007-06-28 10:47:08 -07:00
}
//initialise all the previous obj - particularly useful for when go Off world!
void intResetPreviousObj ( void )
{
2012-12-21 07:35:35 -08:00
//make sure stats screen doesn't think it should be up
StatsUp = false ;
2007-06-28 10:47:08 -07:00
// reset the previous objects
memset ( apsPreviousObj , 0 , sizeof ( apsPreviousObj ) ) ;
}
/* Shut down the in game interface */
2008-10-22 13:04:16 -07:00
void interfaceShutDown ( void )
2007-06-28 10:47:08 -07:00
{
2013-02-15 23:44:47 -08:00
delete psWScreen ;
psWScreen = NULL ;
2007-06-28 10:47:08 -07:00
2007-04-15 03:43:05 -07:00
free ( apsStructStatsList ) ;
free ( ppResearchList ) ;
free ( pList ) ;
free ( pSList ) ;
2011-02-13 09:57:25 -08:00
apsTemplateList . clear ( ) ;
2007-04-15 03:43:05 -07:00
free ( apsFeatureList ) ;
free ( apsComponentList ) ;
free ( apsExtraSysList ) ;
2011-01-04 06:48:00 -08:00
apsObjectList . clear ( ) ;
2007-06-28 10:47:08 -07:00
2011-12-15 12:37:16 -08:00
psWScreen = NULL ;
2007-06-12 11:58:14 -07:00
apsStructStatsList = NULL ;
ppResearchList = NULL ;
pList = NULL ;
pSList = NULL ;
apsFeatureList = NULL ;
apsComponentList = NULL ;
apsExtraSysList = NULL ;
2007-06-28 10:47:08 -07:00
//obviously!
2008-03-24 09:51:17 -07:00
ReticuleUp = false ;
2007-06-28 10:47:08 -07:00
}
2011-03-12 17:32:15 -08:00
static bool IntRefreshPending = false ;
2007-06-28 10:47:08 -07:00
// Set widget refresh pending flag.
//
2006-09-13 02:09:05 -07:00
void intRefreshScreen ( void )
2007-06-28 10:47:08 -07:00
{
2008-03-24 09:51:17 -07:00
IntRefreshPending = true ;
2007-06-28 10:47:08 -07:00
}
2011-03-12 17:32:15 -08:00
bool intIsRefreshing ( void )
2007-06-28 10:47:08 -07:00
{
return Refreshing ;
}
// see if a delivery point is selected
2006-12-02 04:50:28 -08:00
static FLAG_POSITION * intFindSelectedDelivPoint ( void )
2007-06-28 10:47:08 -07:00
{
FLAG_POSITION * psFlagPos ;
for ( psFlagPos = apsFlagPosLists [ selectedPlayer ] ; psFlagPos ;
2012-12-21 07:35:35 -08:00
psFlagPos = psFlagPos - > psNext )
2007-06-28 10:47:08 -07:00
{
if ( psFlagPos - > selected & & ( psFlagPos - > type = = POS_DELIVERY ) )
{
return psFlagPos ;
}
}
return NULL ;
}
// Refresh widgets once per game cycle if pending flag is set.
//
2006-12-02 04:50:28 -08:00
static void intDoScreenRefresh ( void )
2007-06-28 10:47:08 -07:00
{
2013-02-13 01:11:10 -08:00
UWORD objMajor = 0 , statMajor = 0 ;
2007-06-28 10:47:08 -07:00
FLAG_POSITION * psFlag ;
2012-12-21 07:35:35 -08:00
if ( IntRefreshPending )
{
2008-03-24 09:51:17 -07:00
Refreshing = true ;
2007-06-28 10:47:08 -07:00
2013-02-16 02:20:55 -08:00
if ( ( intMode = = INT_OBJECT | |
intMode = = INT_STAT | |
intMode = = INT_CMDORDER | |
intMode = = INT_ORDER | |
intMode = = INT_TRANSPORTER ) & &
widgGetFromID ( psWScreen , IDOBJ_FORM ) ! = NULL & &
widgGetFromID ( psWScreen , IDOBJ_FORM ) - > visible ( ) )
2007-06-28 10:47:08 -07:00
{
2011-03-12 17:32:15 -08:00
bool StatsWasUp = false ;
bool OrderWasUp = false ;
2006-05-27 09:37:17 -07:00
2007-06-28 10:47:08 -07:00
// If the stats form is up then remove it, but remember that it was up.
2012-12-21 07:35:35 -08:00
if ( ( intMode = = INT_STAT ) & & widgGetFromID ( psWScreen , IDSTAT_FORM ) ! = NULL )
2007-06-28 10:47:08 -07:00
{
2008-03-24 09:51:17 -07:00
StatsWasUp = true ;
2007-06-28 10:47:08 -07:00
}
// store the current tab position
if ( widgGetFromID ( psWScreen , IDOBJ_TABFORM ) ! = NULL )
{
2013-03-09 09:52:28 -08:00
objMajor = ( ( ListTabWidget * ) widgGetFromID ( psWScreen , IDOBJ_TABFORM ) ) - > currentPage ( ) ;
2007-06-28 10:47:08 -07:00
}
if ( StatsWasUp )
{
2013-03-08 11:46:19 -08:00
statMajor = ( ( ListTabWidget * ) widgGetFromID ( psWScreen , IDSTAT_TABFORM ) ) - > currentPage ( ) ;
2007-06-28 10:47:08 -07:00
}
// now make sure the stats screen isn't up
2012-12-21 07:35:35 -08:00
if ( widgGetFromID ( psWScreen , IDSTAT_FORM ) ! = NULL )
2007-06-28 10:47:08 -07:00
{
intRemoveStatsNoAnim ( ) ;
}
if ( psObjSelected & &
2012-12-21 07:35:35 -08:00
psObjSelected - > died )
2007-06-28 10:47:08 -07:00
{
// refresh when unit dies
psObjSelected = NULL ;
2013-02-13 01:11:10 -08:00
objMajor = 0 ;
statMajor = 0 ;
2007-06-28 10:47:08 -07:00
}
// see if there was a delivery point being positioned
psFlag = intFindSelectedDelivPoint ( ) ;
// see if the commander order screen is up
2012-12-21 07:35:35 -08:00
if ( ( intMode = = INT_CMDORDER ) & &
( widgGetFromID ( psWScreen , IDORDER_FORM ) ! = NULL ) )
2007-06-28 10:47:08 -07:00
{
2008-03-24 09:51:17 -07:00
OrderWasUp = true ;
2007-06-28 10:47:08 -07:00
}
2012-12-21 07:35:35 -08:00
switch ( objMode )
2007-06-28 10:47:08 -07:00
{
case IOBJ_MANUFACTURE : // The manufacture screen (factorys on bottom bar)
case IOBJ_RESEARCH : // The research screen
//pass in the currently selected object
2012-04-02 20:56:20 -07:00
intUpdateObject ( ( BASE_OBJECT * ) interfaceStructList ( ) , psObjSelected , StatsWasUp ) ;
2007-06-28 10:47:08 -07:00
break ;
case IOBJ_BUILD :
case IOBJ_COMMAND : // the command droid screen
case IOBJ_BUILDSEL : // Selecting a position for a new structure
case IOBJ_DEMOLISHSEL : // Selecting a structure to demolish
//pass in the currently selected object
2012-04-02 20:56:20 -07:00
intUpdateObject ( ( BASE_OBJECT * ) apsDroidLists [ selectedPlayer ] , psObjSelected , StatsWasUp ) ;
2007-06-28 10:47:08 -07:00
break ;
default :
// generic refresh (trouble at the moment, cant just always pass in a null to addobject
2006-05-27 09:37:17 -07:00
// if object screen is up, refresh it if stats screen is up, refresh that.
2007-06-28 10:47:08 -07:00
break ;
}
// set the tabs again
if ( widgGetFromID ( psWScreen , IDOBJ_TABFORM ) ! = NULL )
{
2013-03-09 09:52:28 -08:00
( ( ListTabWidget * ) widgGetFromID ( psWScreen , IDOBJ_TABFORM ) ) - > setCurrentPage ( objMajor ) ;
2007-06-28 10:47:08 -07:00
}
2008-05-09 13:32:31 -07:00
2012-12-21 07:35:35 -08:00
if ( widgGetFromID ( psWScreen , IDSTAT_TABFORM ) ! = NULL )
2007-06-28 10:47:08 -07:00
{
2013-03-08 11:46:19 -08:00
( ( ListTabWidget * ) widgGetFromID ( psWScreen , IDSTAT_TABFORM ) ) - > setCurrentPage ( statMajor ) ;
2007-06-28 10:47:08 -07:00
}
if ( psFlag ! = NULL )
{
// need to restart the delivery point position
2012-06-21 15:34:04 -07:00
startDeliveryPosition ( psFlag ) ;
2007-06-28 10:47:08 -07:00
}
// make sure the commander order screen is in the right state
2012-12-21 07:35:35 -08:00
if ( ( intMode = = INT_CMDORDER ) & &
! OrderWasUp & &
( widgGetFromID ( psWScreen , IDORDER_FORM ) ! = NULL ) )
2007-06-28 10:47:08 -07:00
{
intRemoveOrderNoAnim ( ) ;
2010-01-12 11:10:59 -08:00
if ( statID )
{
widgSetButtonState ( psWScreen , statID , 0 ) ;
}
2007-06-28 10:47:08 -07:00
}
}
// Refresh the transporter interface.
intRefreshTransporter ( ) ;
// Refresh the order interface.
intRefreshOrder ( ) ;
2008-03-24 09:51:17 -07:00
Refreshing = false ;
2007-06-28 10:47:08 -07:00
}
2008-03-24 09:51:17 -07:00
IntRefreshPending = false ;
2007-06-28 10:47:08 -07:00
}
2006-12-02 04:50:28 -08:00
//hides the power bar from the display
2013-08-02 12:50:11 -07:00
void intHidePowerBar ( )
2006-12-02 04:50:28 -08:00
{
//only hides the power bar if the player has requested no power bar
if ( ! powerBarUp )
2007-06-28 10:47:08 -07:00
{
2006-12-02 04:50:28 -08:00
if ( widgGetFromID ( psWScreen , IDPOW_POWERBAR_T ) )
{
widgHide ( psWScreen , IDPOW_POWERBAR_T ) ;
}
2007-06-28 10:47:08 -07:00
}
2006-12-02 04:50:28 -08:00
}
2007-06-28 10:47:08 -07:00
2006-12-02 04:50:28 -08:00
/* Remove the options widgets from the widget screen */
static void intRemoveOptions ( void )
{
widgDelete ( psWScreen , IDOPT_FORM ) ;
}
2007-06-28 10:47:08 -07:00
2007-06-24 14:58:42 -07:00
2006-12-02 04:50:28 -08:00
/* Reset the widget screen to just the reticule */
2011-03-12 17:32:15 -08:00
void intResetScreen ( bool NoAnim )
2006-12-02 04:50:28 -08:00
{
2012-12-21 06:01:30 -08:00
// Ensure driver mode is turned off.
2008-02-08 03:05:31 -08:00
StopDriverMode ( ) ;
2006-12-02 04:50:28 -08:00
2012-12-21 07:35:35 -08:00
if ( getWidgetsStatus ( ) = = false )
2006-12-02 04:50:28 -08:00
{
2008-03-24 09:51:17 -07:00
NoAnim = true ;
2006-12-02 04:50:28 -08:00
}
2008-04-21 02:19:10 -07:00
if ( ReticuleUp )
{
2006-12-02 04:50:28 -08:00
/* Reset the reticule buttons */
widgSetButtonState ( psWScreen , IDRET_COMMAND , 0 ) ;
widgSetButtonState ( psWScreen , IDRET_BUILD , 0 ) ;
widgSetButtonState ( psWScreen , IDRET_MANUFACTURE , 0 ) ;
widgSetButtonState ( psWScreen , IDRET_INTEL_MAP , 0 ) ;
widgSetButtonState ( psWScreen , IDRET_RESEARCH , 0 ) ;
widgSetButtonState ( psWScreen , IDRET_DESIGN , 0 ) ;
}
/* Remove whatever extra screen was displayed */
switch ( intMode )
{
case INT_OPTION :
intRemoveOptions ( ) ;
break ;
case INT_EDITSTAT :
intStopStructPosition ( ) ;
2012-12-21 07:35:35 -08:00
if ( NoAnim )
{
2006-12-02 04:50:28 -08:00
intRemoveStatsNoAnim ( ) ;
2012-12-21 07:35:35 -08:00
}
else
{
2006-12-02 04:50:28 -08:00
intRemoveStats ( ) ;
}
break ;
case INT_OBJECT :
intStopStructPosition ( ) ;
2012-12-21 07:35:35 -08:00
if ( NoAnim )
{
2006-12-02 04:50:28 -08:00
intRemoveObjectNoAnim ( ) ;
2012-12-21 07:35:35 -08:00
}
else
{
2006-12-02 04:50:28 -08:00
intRemoveObject ( ) ;
}
break ;
case INT_STAT :
2012-12-21 07:35:35 -08:00
if ( NoAnim )
{
2006-12-02 04:50:28 -08:00
intRemoveStatsNoAnim ( ) ;
intRemoveObjectNoAnim ( ) ;
2012-12-21 07:35:35 -08:00
}
else
{
2006-12-02 04:50:28 -08:00
intRemoveStats ( ) ;
intRemoveObject ( ) ;
}
break ;
case INT_CMDORDER :
2012-12-21 07:35:35 -08:00
if ( NoAnim )
{
2006-12-02 04:50:28 -08:00
intRemoveOrderNoAnim ( ) ;
intRemoveObjectNoAnim ( ) ;
2012-12-21 07:35:35 -08:00
}
else
{
2006-12-02 04:50:28 -08:00
intRemoveOrder ( ) ;
intRemoveObject ( ) ;
}
break ;
case INT_ORDER :
2012-12-21 07:35:35 -08:00
if ( NoAnim )
{
2006-12-02 04:50:28 -08:00
intRemoveOrderNoAnim ( ) ;
2012-12-21 07:35:35 -08:00
}
else
{
2006-12-02 04:50:28 -08:00
intRemoveOrder ( ) ;
}
break ;
case INT_INGAMEOP :
2012-12-21 07:35:35 -08:00
if ( NoAnim )
{
2008-03-24 09:51:17 -07:00
intCloseInGameOptionsNoAnim ( true ) ;
2012-12-21 07:35:35 -08:00
}
else
{
2008-03-24 09:51:17 -07:00
intCloseInGameOptions ( false , true ) ;
2006-12-02 04:50:28 -08:00
}
break ;
case INT_MISSIONRES :
2010-12-17 11:06:53 -08:00
intRemoveMissionResultNoAnim ( ) ;
2006-12-02 04:50:28 -08:00
break ;
case INT_MULTIMENU :
2012-12-21 07:35:35 -08:00
if ( NoAnim )
{
2006-12-02 04:50:28 -08:00
intCloseMultiMenuNoAnim ( ) ;
2012-12-21 07:35:35 -08:00
}
else
{
2006-12-02 04:50:28 -08:00
intCloseMultiMenu ( ) ;
}
break ;
case INT_DESIGN :
intRemoveDesign ( ) ;
intHidePowerBar ( ) ;
if ( bInTutorial )
{
eventFireCallbackTrigger ( ( TRIGGER_TYPE ) CALL_DESIGN_QUIT ) ;
2007-06-28 10:47:08 -07:00
}
break ;
case INT_INTELMAP :
if ( NoAnim )
{
intRemoveIntelMapNoAnim ( ) ;
}
else
{
intRemoveIntelMap ( ) ;
}
intHidePowerBar ( ) ;
2012-12-21 07:35:35 -08:00
if ( ! bMultiPlayer )
2007-06-28 10:47:08 -07:00
{
gameTimeStart ( ) ;
}
break ;
case INT_TRANSPORTER :
2012-12-21 07:35:35 -08:00
if ( NoAnim )
2007-06-28 10:47:08 -07:00
{
intRemoveTransNoAnim ( ) ;
2006-05-27 09:37:17 -07:00
}
else
2007-06-28 10:47:08 -07:00
{
intRemoveTrans ( ) ;
}
break ;
default :
break ;
}
2012-04-02 20:56:20 -07:00
SecondaryWindowUp = false ;
2007-06-28 10:47:08 -07:00
intMode = INT_NORMAL ;
2010-12-17 11:06:53 -08:00
//clearSel() sets IntRefreshPending = true by calling intRefreshScreen() but if we're doing this then we won't need to refresh - hopefully!
2008-03-24 09:51:17 -07:00
IntRefreshPending = false ;
2007-06-28 10:47:08 -07:00
}
// calulate the center world coords for a structure stat given
// top left tile coords
2010-03-06 13:56:30 -08:00
static void intCalcStructCenter ( STRUCTURE_STATS * psStats , UDWORD tilex , UDWORD tiley , uint16_t direction , UDWORD * pcx , UDWORD * pcy )
2007-06-28 10:47:08 -07:00
{
2012-12-21 07:35:35 -08:00
unsigned width = getStructureStatsWidth ( psStats , direction ) * TILE_UNITS ;
2010-09-01 16:14:10 -07:00
unsigned height = getStructureStatsBreadth ( psStats , direction ) * TILE_UNITS ;
2007-06-28 10:47:08 -07:00
2012-12-21 07:35:35 -08:00
* pcx = tilex * TILE_UNITS + width / 2 ;
* pcy = tiley * TILE_UNITS + height / 2 ;
2007-06-28 10:47:08 -07:00
}
2006-12-02 04:50:28 -08:00
/* Process return codes from the Options screen */
static void intProcessOptions ( UDWORD id )
2007-06-28 10:47:08 -07:00
{
2006-12-02 04:50:28 -08:00
if ( id > = IDOPT_PLAYERSTART & & id < = IDOPT_PLAYEREND )
2007-06-28 10:47:08 -07:00
{
2012-06-02 11:37:46 -07:00
int oldSelectedPlayer = selectedPlayer ;
2006-12-02 04:50:28 -08:00
widgSetButtonState ( psWScreen , IDOPT_PLAYERSTART + selectedPlayer , 0 ) ;
selectedPlayer = id - IDOPT_PLAYERSTART ;
2012-06-02 11:37:46 -07:00
NetPlay . players [ selectedPlayer ] . allocated = ! NetPlay . players [ selectedPlayer ] . allocated ;
NetPlay . players [ oldSelectedPlayer ] . allocated = ! NetPlay . players [ oldSelectedPlayer ] . allocated ;
2010-09-01 12:05:22 -07:00
// Do not change realSelectedPlayer here, so game doesn't pause.
2006-12-02 04:50:28 -08:00
widgSetButtonState ( psWScreen , IDOPT_PLAYERSTART + selectedPlayer , WBUT_LOCK ) ;
2007-06-28 10:47:08 -07:00
}
2006-12-02 04:50:28 -08:00
else
2007-06-28 10:47:08 -07:00
{
2006-12-02 04:50:28 -08:00
switch ( id )
2007-06-28 10:47:08 -07:00
{
2006-12-02 04:50:28 -08:00
/* The add object buttons */
case IDOPT_DROID :
intRemoveOptions ( ) ;
2011-02-13 09:57:25 -08:00
apsTemplateList . clear ( ) ;
for ( std : : list < DROID_TEMPLATE > : : iterator i = localTemplates . begin ( ) ; i ! = localTemplates . end ( ) ; + + i )
2006-12-02 04:50:28 -08:00
{
2011-02-13 09:57:25 -08:00
apsTemplateList . push_back ( & * i ) ;
2006-12-02 04:50:28 -08:00
}
2012-12-21 07:35:35 -08:00
ppsStatsList = ( BASE_STATS * * ) & apsTemplateList [ 0 ] ; // FIXME Ugly cast, and is undefined behaviour (strict-aliasing violation) in C/C++.
2006-12-02 04:50:28 -08:00
objMode = IOBJ_MANUFACTURE ;
2011-02-13 09:57:25 -08:00
intAddStats ( ppsStatsList , apsTemplateList . size ( ) , NULL , NULL ) ;
2006-12-02 04:50:28 -08:00
intMode = INT_EDITSTAT ;
editPosMode = IED_NOPOS ;
break ;
case IDOPT_STRUCT :
intRemoveOptions ( ) ;
2011-02-13 09:57:25 -08:00
for ( unsigned i = 0 ; i < std : : min < unsigned > ( numStructureStats , MAXSTRUCTURES ) ; + + i )
2006-12-02 04:50:28 -08:00
{
apsStructStatsList [ i ] = asStructureStats + i ;
}
2012-12-21 07:35:35 -08:00
ppsStatsList = ( BASE_STATS * * ) apsStructStatsList ;
2006-12-02 04:50:28 -08:00
objMode = IOBJ_BUILD ;
2011-02-13 09:57:25 -08:00
intAddStats ( ppsStatsList , std : : min < unsigned > ( numStructureStats , MAXSTRUCTURES ) , NULL , NULL ) ;
2006-12-02 04:50:28 -08:00
intMode = INT_EDITSTAT ;
editPosMode = IED_NOPOS ;
break ;
case IDOPT_FEATURE :
intRemoveOptions ( ) ;
2011-02-13 09:57:25 -08:00
for ( unsigned i = 0 ; i < std : : min < unsigned > ( numFeatureStats , MAXFEATURES ) ; + + i )
2006-12-02 04:50:28 -08:00
{
apsFeatureList [ i ] = asFeatureStats + i ;
}
2012-12-21 07:35:35 -08:00
ppsStatsList = ( BASE_STATS * * ) apsFeatureList ;
2011-02-13 09:57:25 -08:00
intAddStats ( ppsStatsList , std : : min < unsigned > ( numFeatureStats , MAXFEATURES ) , NULL , NULL ) ;
2006-12-02 04:50:28 -08:00
intMode = INT_EDITSTAT ;
editPosMode = IED_NOPOS ;
break ;
/* Close window buttons */
case IDOPT_CLOSE :
intRemoveOptions ( ) ;
intMode = INT_NORMAL ;
break ;
/* Ignore these */
case IDOPT_FORM :
case IDOPT_LABEL :
case IDOPT_PLAYERFORM :
case IDOPT_PLAYERLABEL :
2010-03-06 15:06:35 -08:00
case IDOPT_IVISFORM :
case IDOPT_IVISLABEL :
2006-12-02 04:50:28 -08:00
break ;
default :
2012-12-21 07:32:23 -08:00
ASSERT ( false , " Unknown return code " ) ;
2006-12-02 04:50:28 -08:00
break ;
}
}
}
/* Process return codes from the object placement stats screen */
static void intProcessEditStats ( UDWORD id )
{
if ( id > = IDSTAT_START & & id < = IDSTAT_END )
{
/* Clicked on a stat button - need to look for a location for it */
psPositionStats = ppsStatsList [ id - IDSTAT_START ] ;
if ( psPositionStats - > ref > = REF_TEMPLATE_START & &
psPositionStats - > ref < REF_TEMPLATE_START + REF_RANGE )
{
2012-06-21 15:34:04 -07:00
FLAG_POSITION debugMenuDroidDeliveryPoint ;
2011-12-16 12:45:56 -08:00
// Placing a droid from the debug menu, set up the flag. (This would probably be safe to do, even if we're placing something else.)
2011-12-16 07:43:14 -08:00
debugMenuDroidDeliveryPoint . factoryType = REPAIR_FLAG ;
debugMenuDroidDeliveryPoint . factoryInc = 0 ;
2012-06-21 15:34:04 -07:00
debugMenuDroidDeliveryPoint . player = selectedPlayer ;
2013-10-21 12:41:55 -07:00
debugMenuDroidDeliveryPoint . selected = false ;
debugMenuDroidDeliveryPoint . psNext = NULL ;
2012-06-21 15:34:04 -07:00
startDeliveryPosition ( & debugMenuDroidDeliveryPoint ) ;
}
else
{
intStartStructPosition ( psPositionStats ) ;
2006-12-02 04:50:28 -08:00
}
editPosMode = IED_POS ;
}
else if ( id = = IDSTAT_CLOSE )
{
intRemoveStats ( ) ;
intStopStructPosition ( ) ;
intMode = INT_NORMAL ;
objMode = IOBJ_NONE ;
}
}
/* Run the widgets for the in game interface */
INT_RETVAL intRunWidgets ( void )
{
INT_RETVAL retCode ;
2011-03-12 17:32:15 -08:00
bool quitting = false ;
2012-12-21 07:35:35 -08:00
UDWORD structX , structY , structX2 , structY2 ;
2013-02-13 01:11:10 -08:00
UWORD objMajor ;
2006-12-02 04:50:28 -08:00
STRUCTURE * psStructure ;
DROID * psDroid ;
SDWORD i ;
UDWORD widgOverID ;
intDoScreenRefresh ( ) ;
/* Update the object list if necessary */
if ( intMode = = INT_OBJECT | | intMode = = INT_STAT | | intMode = = INT_CMDORDER )
{
// see if there is a dead object in the list
2012-12-21 07:35:35 -08:00
for ( unsigned i = 0 ; i < apsObjectList . size ( ) ; + + i )
2006-12-02 04:50:28 -08:00
{
if ( apsObjectList [ i ] & & apsObjectList [ i ] - > died )
{
intObjectDied ( ( UDWORD ) ( i + IDOBJ_OBJSTART ) ) ;
apsObjectList [ i ] = NULL ;
}
}
}
/* Update the previous object array */
2012-12-21 07:35:35 -08:00
for ( i = 0 ; i < IOBJ_MAX ; i + + )
2006-12-02 04:50:28 -08:00
{
if ( apsPreviousObj [ i ] & & apsPreviousObj [ i ] - > died )
{
apsPreviousObj [ i ] = NULL ;
}
}
/* if objects in the world have changed, may have to update the interface */
2007-06-28 10:47:08 -07:00
if ( objectsChanged )
{
/* The objects on the object screen have changed */
if ( intMode = = INT_OBJECT )
{
2012-12-21 07:35:35 -08:00
ASSERT ( widgGetFromID ( psWScreen , IDOBJ_TABFORM ) ! = NULL , " No object form " ) ;
2007-06-28 10:47:08 -07:00
/* Remove the old screen */
2013-03-09 09:52:28 -08:00
objMajor = ( ( ListTabWidget * ) widgGetFromID ( psWScreen , IDOBJ_TABFORM ) ) - > currentPage ( ) ;
2007-06-28 10:47:08 -07:00
intRemoveObject ( ) ;
/* Add the new screen */
switch ( objMode )
{
case IOBJ_BUILD :
case IOBJ_BUILDSEL :
intAddBuild ( NULL ) ;
break ;
case IOBJ_MANUFACTURE :
intAddManufacture ( NULL ) ;
break ;
case IOBJ_RESEARCH :
intAddResearch ( NULL ) ;
break ;
default :
break ;
}
/* Reset the tabs on the object screen */
2013-03-09 09:52:28 -08:00
( ( ListTabWidget * ) widgGetFromID ( psWScreen , IDOBJ_TABFORM ) ) - > setCurrentPage ( objMajor ) ;
2007-06-28 10:47:08 -07:00
}
else if ( intMode = = INT_STAT )
{
/* Need to get the stats screen to update as well */
}
}
2008-03-24 09:51:17 -07:00
objectsChanged = false ;
2007-06-28 10:47:08 -07:00
2012-12-21 07:32:23 -08:00
if ( bLoadSaveUp & & runLoadSave ( true ) & & strlen ( sRequestResult ) > 0 )
2007-06-28 10:47:08 -07:00
{
2012-12-21 07:35:35 -08:00
if ( bRequestLoad )
{
NET_InitPlayers ( ) ; // reinitialize starting positions
loopMissionState = LMS_LOADGAME ;
sstrcpy ( saveGameName , sRequestResult ) ;
}
else
{
if ( saveGame ( sRequestResult , GTYPE_SAVE_START ) )
{
char msg [ 256 ] = { ' \0 ' } ;
2009-05-24 17:30:53 -07:00
2012-12-21 07:35:35 -08:00
sstrcpy ( msg , _ ( " GAME SAVED: " ) ) ;
sstrcat ( msg , saveGameName ) ;
addConsoleMessage ( msg , LEFT_JUSTIFY , NOTIFY_MESSAGE ) ;
2006-05-27 09:37:17 -07:00
2012-12-21 07:35:35 -08:00
if ( widgGetFromID ( psWScreen , IDMISSIONRES_SAVE ) )
{
widgDelete ( psWScreen , IDMISSIONRES_SAVE ) ;
2007-06-28 10:47:08 -07:00
}
2012-12-21 07:35:35 -08:00
}
else
{
ASSERT ( false , " intRunWidgets: saveGame Failed " ) ;
deleteSaveGame ( sRequestResult ) ;
}
}
2007-06-28 10:47:08 -07:00
}
2012-12-21 07:35:35 -08:00
if ( MissionResUp )
{
2007-06-28 10:47:08 -07:00
intRunMissionResult ( ) ;
}
2006-05-27 09:37:17 -07:00
2007-06-28 10:47:08 -07:00
/* Run the current set of widgets */
2013-01-27 00:02:31 -08:00
std : : vector < unsigned > retIDs ;
2007-06-28 10:47:08 -07:00
if ( ! bLoadSaveUp )
{
2013-01-27 00:02:31 -08:00
WidgetTriggers const & triggers = widgRunScreen ( psWScreen ) ;
for ( WidgetTriggers : : const_iterator trigger = triggers . begin ( ) ; trigger ! = triggers . end ( ) ; + + trigger )
{
retIDs . push_back ( trigger - > widget - > id ) ;
}
2007-06-28 10:47:08 -07:00
}
2006-07-24 13:12:36 -07:00
2007-06-28 10:47:08 -07:00
/* We may need to trigger widgets with a key press */
2012-12-21 07:35:35 -08:00
if ( keyButtonMapping )
2007-06-28 10:47:08 -07:00
{
/* Set the appropriate id */
2013-01-27 00:02:31 -08:00
retIDs . push_back ( keyButtonMapping ) ;
2007-06-28 10:47:08 -07:00
/* Clear it so it doesn't trigger next time around */
keyButtonMapping = 0 ;
}
2013-01-27 00:02:31 -08:00
intLastWidget = retIDs . empty ( ) ? 0 : retIDs . back ( ) ;
if ( bInTutorial & & ! retIDs . empty ( ) )
2007-06-28 10:47:08 -07:00
{
eventFireCallbackTrigger ( ( TRIGGER_TYPE ) CALL_BUTTON_PRESSED ) ;
}
/* Extra code for the power bars to deal with the shadow */
if ( powerBarUp )
{
intRunPower ( ) ;
}
2012-12-21 07:35:35 -08:00
if ( StatsUp )
{
2007-06-28 10:47:08 -07:00
intRunStats ( ) ;
}
2012-12-21 07:35:35 -08:00
if ( OrderUp )
{
2007-06-28 10:47:08 -07:00
intRunOrder ( ) ;
}
2012-12-21 07:35:35 -08:00
if ( MultiMenuUp )
2007-06-28 10:47:08 -07:00
{
intRunMultiMenu ( ) ;
}
/* Extra code for the design screen to deal with the shadow bar graphs */
if ( intMode = = INT_DESIGN )
{
2012-04-02 20:56:20 -07:00
SecondaryWindowUp = true ;
2007-06-28 10:47:08 -07:00
intRunDesign ( ) ;
}
2013-01-27 00:02:31 -08:00
// Deal with any clicks.
for ( std : : vector < unsigned > : : const_iterator rit = retIDs . begin ( ) ; rit ! = retIDs . end ( ) ; + + rit )
2007-06-28 10:47:08 -07:00
{
2013-01-27 00:02:31 -08:00
unsigned retID = * rit ;
2007-06-28 10:47:08 -07:00
2013-01-27 00:02:31 -08:00
if ( retID > = IDPROX_START & & retID < = IDPROX_END )
2007-06-28 10:47:08 -07:00
{
2013-01-27 00:02:31 -08:00
processProximityButtons ( retID ) ;
return INT_NONE ;
2007-06-28 10:47:08 -07:00
}
2013-01-27 00:02:31 -08:00
switch ( retID )
2008-04-21 02:19:10 -07:00
{
2013-01-27 00:02:31 -08:00
/***************** Reticule buttons *****************/
2007-06-28 10:47:08 -07:00
2013-01-27 00:02:31 -08:00
case IDRET_OPTIONS :
intResetScreen ( false ) ;
( void ) intAddOptions ( ) ;
intMode = INT_OPTION ;
break ;
2007-06-28 10:47:08 -07:00
2013-01-27 00:02:31 -08:00
case IDRET_COMMAND :
intResetScreen ( false ) ;
widgSetButtonState ( psWScreen , IDRET_COMMAND , WBUT_CLICKLOCK ) ;
intAddCommand ( NULL ) ;
break ;
2007-06-28 10:47:08 -07:00
2013-01-27 00:02:31 -08:00
case IDRET_BUILD :
intResetScreen ( true ) ;
widgSetButtonState ( psWScreen , IDRET_BUILD , WBUT_CLICKLOCK ) ;
2013-01-29 07:22:16 -08:00
intAddBuild ( NULL ) ;
2013-01-27 00:02:31 -08:00
break ;
2007-06-28 10:47:08 -07:00
2013-01-27 00:02:31 -08:00
case IDRET_MANUFACTURE :
intResetScreen ( true ) ;
widgSetButtonState ( psWScreen , IDRET_MANUFACTURE , WBUT_CLICKLOCK ) ;
2013-01-29 07:22:16 -08:00
intAddManufacture ( NULL ) ;
2007-06-28 10:47:08 -07:00
break ;
2013-01-27 00:02:31 -08:00
case IDRET_RESEARCH :
intResetScreen ( true ) ;
widgSetButtonState ( psWScreen , IDRET_RESEARCH , WBUT_CLICKLOCK ) ;
( void ) intAddResearch ( NULL ) ;
2007-06-28 10:47:08 -07:00
break ;
2013-01-27 00:02:31 -08:00
case IDRET_INTEL_MAP :
// check if RMB was clicked
if ( widgGetButtonKey_DEPRECATED ( psWScreen ) = = WKEY_SECONDARY )
{
//set the current message to be the last non-proximity message added
setCurrentMsg ( ) ;
setMessageImmediate ( true ) ;
}
else
{
psCurrentMsg = NULL ;
}
addIntelScreen ( ) ;
2007-06-28 10:47:08 -07:00
break ;
2013-01-27 00:02:31 -08:00
case IDRET_DESIGN :
intResetScreen ( true ) ;
widgSetButtonState ( psWScreen , IDRET_DESIGN , WBUT_CLICKLOCK ) ;
/*add the power bar - for looks! */
intShowPowerBar ( ) ;
2013-01-29 07:22:16 -08:00
intAddDesign ( false ) ;
2013-01-27 00:02:31 -08:00
intMode = INT_DESIGN ;
2007-06-28 10:47:08 -07:00
break ;
2013-01-27 00:02:31 -08:00
case IDRET_CANCEL :
intResetScreen ( false ) ;
psCurrentMsg = NULL ;
2007-06-28 10:47:08 -07:00
break ;
2013-01-27 00:02:31 -08:00
/*Transporter button pressed - OFFWORLD Mission Maps ONLY *********/
case IDTRANTIMER_BUTTON :
addTransporterInterface ( NULL , true ) ;
2007-06-28 10:47:08 -07:00
break ;
2013-01-27 00:02:31 -08:00
case IDTRANS_LAUNCH :
processLaunchTransporter ( ) ;
2007-06-28 10:47:08 -07:00
break ;
2013-01-27 00:02:31 -08:00
/* Catch the quit button here */
case INTINGAMEOP_POPUP_QUIT :
case IDMISSIONRES_QUIT : // mission quit
case INTINGAMEOP_QUIT_CONFIRM : // esc quit confrim
case IDOPT_QUIT : // options screen quit
intResetScreen ( false ) ;
quitting = true ;
2007-06-28 10:47:08 -07:00
break ;
2013-01-27 00:02:31 -08:00
/* Default case passes remaining IDs to appropriate function */
2007-06-28 10:47:08 -07:00
default :
2013-01-27 00:02:31 -08:00
switch ( intMode )
{
case INT_OPTION :
intProcessOptions ( retID ) ;
break ;
case INT_EDITSTAT :
intProcessEditStats ( retID ) ;
break ;
case INT_STAT :
case INT_CMDORDER :
/* In stat mode ids get passed to processObject
* and then through to processStats
*/
// NO BREAK HERE! THIS IS CORRECT;
case INT_OBJECT :
intProcessObject ( retID ) ;
break ;
case INT_ORDER :
intProcessOrder ( retID ) ;
break ;
case INT_MISSIONRES :
intProcessMissionResult ( retID ) ;
break ;
case INT_INGAMEOP :
intProcessInGameOptions ( retID ) ;
break ;
case INT_MULTIMENU :
intProcessMultiMenu ( retID ) ;
break ;
case INT_DESIGN :
intProcessDesign ( retID ) ;
break ;
case INT_INTELMAP :
intProcessIntelMap ( retID ) ;
break ;
case INT_TRANSPORTER :
intProcessTransporter ( retID ) ;
break ;
case INT_NORMAL :
break ;
default :
2013-01-29 07:22:16 -08:00
ASSERT ( false , " intRunWidgets: unknown interface mode " ) ;
2013-01-27 00:02:31 -08:00
break ;
}
2007-06-28 10:47:08 -07:00
break ;
}
2006-05-27 09:37:17 -07:00
}
2007-06-28 10:47:08 -07:00
2013-01-27 00:02:31 -08:00
if ( ! quitting & & retIDs . empty ( ) )
2007-06-28 10:47:08 -07:00
{
if ( ( intMode = = INT_OBJECT | | intMode = = INT_STAT ) & & objMode = = IOBJ_BUILDSEL )
{
// See if a position for the structure has been found
2007-06-24 12:38:36 -07:00
if ( found3DBuildLocTwo ( & structX , & structY , & structX2 , & structY2 ) )
2007-06-28 10:47:08 -07:00
{
// check if it's a straight line.
2012-12-21 07:35:35 -08:00
if ( ( structX = = structX2 ) | | ( structY = = structY2 ) )
2007-06-28 10:47:08 -07:00
{
2006-05-27 09:37:17 -07:00
// Send the droid off to build the structure assuming the droid
2007-06-28 10:47:08 -07:00
// can get to the location chosen
2007-09-28 10:39:33 -07:00
structX = world_coord ( structX ) + TILE_UNITS / 2 ;
structY = world_coord ( structY ) + TILE_UNITS / 2 ;
structX2 = world_coord ( structX2 ) + TILE_UNITS / 2 ;
structY2 = world_coord ( structY2 ) + TILE_UNITS / 2 ;
2007-06-28 10:47:08 -07:00
2012-11-03 07:23:30 -07:00
// Set the droid order
if ( intNumSelectedDroids ( DROID_CONSTRUCT ) = = 0
& & intNumSelectedDroids ( DROID_CYBORG_CONSTRUCT ) = = 0
& & psObjSelected ! = NULL & & isConstructionDroid ( psObjSelected ) )
2008-10-16 06:22:02 -07:00
{
2012-11-03 07:23:30 -07:00
orderDroidStatsTwoLocDir ( ( DROID * ) psObjSelected , DORDER_LINEBUILD , ( STRUCTURE_STATS * ) psPositionStats , structX , structY , structX2 , structY2 , player . r . y , ModeQueue ) ;
}
else
{
orderSelectedStatsTwoLocDir ( selectedPlayer , DORDER_LINEBUILD , ( STRUCTURE_STATS * ) psPositionStats , structX , structY , structX2 , structY2 , player . r . y , ctrlShiftDown ( ) ) ;
2007-06-28 10:47:08 -07:00
}
}
2010-05-02 12:22:09 -07:00
if ( ! quickQueueMode )
2007-06-28 10:47:08 -07:00
{
2010-05-02 12:22:09 -07:00
// Clear the object screen, only if we aren't immediately building something else
2008-03-24 09:51:17 -07:00
intResetScreen ( false ) ;
2007-06-28 10:47:08 -07:00
}
}
2008-07-27 13:13:41 -07:00
else if ( found3DBuilding ( & structX , & structY ) ) //found building
2007-06-28 10:47:08 -07:00
{
//check droid hasn't died
if ( ( psObjSelected = = NULL ) | |
2012-12-21 07:35:35 -08:00
! psObjSelected - > died )
2007-06-28 10:47:08 -07:00
{
2011-03-12 17:32:15 -08:00
bool CanBuild = true ;
2007-06-28 10:47:08 -07:00
2006-05-27 09:37:17 -07:00
// Send the droid off to build the structure assuming the droid
2007-06-28 10:47:08 -07:00
// can get to the location chosen
2010-03-06 13:56:30 -08:00
intCalcStructCenter ( ( STRUCTURE_STATS * ) psPositionStats , structX , structY , player . r . y , & structX , & structY ) ;
2007-06-28 10:47:08 -07:00
// Don't allow derrick to be built on burning ground.
2012-12-21 07:35:35 -08:00
if ( ( ( STRUCTURE_STATS * ) psPositionStats ) - > type = = REF_RESOURCE_EXTRACTOR )
{
if ( fireOnLocation ( structX , structY ) )
{
2007-06-28 10:47:08 -07:00
AddDerrickBurningMessage ( ) ;
}
}
2008-10-16 06:22:02 -07:00
if ( CanBuild )
{
2012-11-03 07:23:30 -07:00
// Set the droid order
if ( intNumSelectedDroids ( DROID_CONSTRUCT ) = = 0
& & intNumSelectedDroids ( DROID_CYBORG_CONSTRUCT ) = = 0
& & psObjSelected ! = NULL )
{
orderDroidStatsLocDir ( ( DROID * ) psObjSelected , DORDER_BUILD , ( STRUCTURE_STATS * ) psPositionStats , structX , structY , player . r . y , ModeQueue ) ;
}
else
2008-10-16 06:22:02 -07:00
{
2012-11-03 07:23:30 -07:00
orderSelectedStatsLocDir ( selectedPlayer , DORDER_BUILD , ( STRUCTURE_STATS * ) psPositionStats , structX , structY , player . r . y , ctrlShiftDown ( ) ) ;
2007-06-28 10:47:08 -07:00
}
}
}
2010-05-02 12:22:09 -07:00
if ( ! quickQueueMode )
2007-06-28 10:47:08 -07:00
{
2010-05-02 12:22:09 -07:00
// Clear the object screen, only if we aren't immediately building something else
2008-03-24 09:51:17 -07:00
intResetScreen ( false ) ;
2007-06-28 10:47:08 -07:00
}
2010-05-02 12:22:09 -07:00
}
if ( buildState = = BUILD3D_NONE )
{
2008-03-24 09:51:17 -07:00
intResetScreen ( false ) ;
2007-06-28 10:47:08 -07:00
}
}
else if ( intMode = = INT_EDITSTAT & & editPosMode = = IED_POS )
{
/* Directly positioning some type of object */
2011-12-26 08:21:41 -08:00
unsigned structX1 = INT32_MAX ;
unsigned structY1 = INT32_MAX ;
2012-06-21 15:34:04 -07:00
FLAG_POSITION flag ;
2011-12-26 08:21:41 -08:00
structX2 = INT32_MAX - 1 ;
structY2 = INT32_MAX - 1 ;
2012-06-21 15:34:04 -07:00
if ( sBuildDetails . psStats & & ( found3DBuilding ( & structX1 , & structY1 ) | | found3DBuildLocTwo ( & structX1 , & structY1 , & structX2 , & structY2 ) ) )
2007-06-28 10:47:08 -07:00
{
2011-12-26 08:21:41 -08:00
if ( structX2 = = INT32_MAX - 1 )
{
structX2 = structX1 ;
structY2 = structY1 ;
}
if ( structX1 > structX2 )
{
std : : swap ( structX1 , structX2 ) ;
}
if ( structY1 > structY2 )
{
std : : swap ( structY1 , structY2 ) ;
}
}
2012-06-21 15:34:04 -07:00
else if ( deliveryReposFinished ( & flag ) )
{
structX2 = structX1 = map_coord ( flag . coords . x ) ;
structY2 = structY1 = map_coord ( flag . coords . y ) ;
}
2011-12-26 08:21:41 -08:00
for ( unsigned j = structY1 ; j < = structY2 ; + + j )
for ( unsigned i = structX1 ; i < = structX2 ; + + i )
2007-06-28 10:47:08 -07:00
{
2012-12-21 07:35:35 -08:00
structX = i ;
structY = j ;
/* See what type of thing is being put down */
if ( psPositionStats - > ref > = REF_STRUCTURE_START
& & psPositionStats - > ref < REF_STRUCTURE_START + REF_RANGE )
2007-05-31 11:19:54 -07:00
{
2012-12-21 07:35:35 -08:00
STRUCTURE_STATS * psBuilding = ( STRUCTURE_STATS * ) psPositionStats ;
STRUCTURE tmp ( 0 , selectedPlayer ) ;
2007-05-31 11:19:54 -07:00
2012-12-21 07:35:35 -08:00
intCalcStructCenter ( psBuilding , structX , structY , player . r . y , & structX , & structY ) ;
if ( psBuilding - > type = = REF_DEMOLISH )
2007-05-31 11:19:54 -07:00
{
2012-12-21 07:35:35 -08:00
MAPTILE * psTile = mapTile ( map_coord ( structX ) , map_coord ( structY ) ) ;
FEATURE * psFeature = ( FEATURE * ) psTile - > psObject ;
psStructure = ( STRUCTURE * ) psTile - > psObject ; /* reuse var */
if ( psStructure & & psTile - > psObject - > type = = OBJ_STRUCTURE )
{
//removeStruct(psStructure, true);
SendDestroyStructure ( psStructure ) ;
}
else if ( psFeature & & psTile - > psObject - > type = = OBJ_FEATURE )
{
removeFeature ( psFeature ) ;
}
psStructure = NULL ;
2007-06-02 16:01:29 -07:00
}
2012-12-21 07:35:35 -08:00
else
2007-05-31 11:19:54 -07:00
{
2012-12-21 07:35:35 -08:00
psStructure = & tmp ;
tmp . id = generateNewObjectId ( ) ;
tmp . pStructureType = ( STRUCTURE_STATS * ) psPositionStats ;
tmp . pos . x = structX ;
tmp . pos . y = structY ;
tmp . pos . z = map_Height ( structX , structY ) + world_coord ( 1 ) / 10 ;
const char * msg ;
// In multiplayer games be sure to send a message to the
// other players, telling them a new structure has been
// placed.
SendBuildFinished ( psStructure ) ;
// Send a text message to all players, notifying them of
// the fact that we're cheating ourselves a new
// structure.
sasprintf ( ( char * * ) & msg , _ ( " Player %u is cheating (debug menu) him/herself a new structure: %s. " ) ,
2013-05-12 14:50:57 -07:00
selectedPlayer , getName ( psStructure - > pStructureType ) ) ;
2012-12-21 07:35:35 -08:00
sendTextMessage ( msg , true ) ;
Cheated = true ;
2007-05-31 11:19:54 -07:00
}
2007-12-24 12:23:55 -08:00
}
2012-12-21 07:35:35 -08:00
else if ( psPositionStats - > ref > = REF_FEATURE_START & & psPositionStats - > ref < REF_FEATURE_START + REF_RANGE )
2007-12-24 12:23:55 -08:00
{
2012-12-21 07:35:35 -08:00
const char * msg ;
2009-03-01 15:50:18 -08:00
// Send a text message to all players, notifying them of the fact that we're cheating ourselves a new feature.
2012-12-21 07:35:35 -08:00
sasprintf ( ( char * * ) & msg , _ ( " Player %u is cheating (debug menu) him/herself a new feature: %s. " ) ,
2013-05-12 14:50:57 -07:00
selectedPlayer , getName ( psPositionStats ) ) ;
2009-03-01 15:50:18 -08:00
sendTextMessage ( msg , true ) ;
Cheated = true ;
// Notify the other hosts that we've just built ourselves a feature
2010-11-28 16:32:33 -08:00
//sendMultiPlayerFeature(result->psStats->subType, result->pos.x, result->pos.y, result->id);
2014-01-26 13:54:19 -08:00
sendMultiPlayerFeature ( ( ( FEATURE_STATS * ) psPositionStats ) - > ref , world_coord ( structX ) , world_coord ( structY ) , generateNewObjectId ( ) ) ;
2012-12-21 07:35:35 -08:00
}
else if ( psPositionStats - > ref > = REF_TEMPLATE_START & &
psPositionStats - > ref < REF_TEMPLATE_START + REF_RANGE )
2006-12-02 04:50:28 -08:00
{
2012-12-21 07:35:35 -08:00
const char * msg ;
psDroid = buildDroid ( ( DROID_TEMPLATE * ) psPositionStats ,
world_coord ( structX ) + TILE_UNITS / 2 , world_coord ( structY ) + TILE_UNITS / 2 ,
selectedPlayer , false , NULL ) ;
cancelDeliveryRepos ( ) ;
if ( psDroid )
{
addDroid ( psDroid , apsDroidLists ) ;
2008-01-06 13:55:23 -08:00
2012-12-21 07:35:35 -08:00
// Send a text message to all players, notifying them of
// the fact that we're cheating ourselves a new droid.
sasprintf ( ( char * * ) & msg , _ ( " Player %u is cheating (debug menu) him/herself a new droid: %s. " ) , selectedPlayer , psDroid - > aName ) ;
2010-06-14 23:35:52 -07:00
2012-12-21 07:35:35 -08:00
psScrCBNewDroid = psDroid ;
psScrCBNewDroidFact = NULL ;
eventFireCallbackTrigger ( ( TRIGGER_TYPE ) CALL_NEWDROID ) ; // notify scripts so it will get assigned jobs
psScrCBNewDroid = NULL ;
2011-12-30 11:48:40 -08:00
2012-12-21 07:35:35 -08:00
triggerEventDroidBuilt ( psDroid , NULL ) ;
}
else
{
// Send a text message to all players, notifying them of
// the fact that we're cheating ourselves a new droid.
sasprintf ( ( char * * ) & msg , _ ( " Player %u is cheating (debug menu) him/herself a new droid. " ) , selectedPlayer ) ;
}
sendTextMessage ( msg , true ) ;
Cheated = true ;
2006-12-02 04:50:28 -08:00
}
2012-12-21 07:35:35 -08:00
if ( ! quickQueueMode )
2010-02-22 04:29:28 -08:00
{
2012-12-21 07:35:35 -08:00
editPosMode = IED_NOPOS ;
2010-02-22 04:29:28 -08:00
}
2006-12-02 04:50:28 -08:00
}
2007-06-28 10:47:08 -07:00
}
}
2006-12-02 04:50:28 -08:00
widgOverID = widgGetMouseOver ( psWScreen ) ;
2007-06-28 10:47:08 -07:00
2006-12-02 04:50:28 -08:00
retCode = INT_NONE ;
if ( quitting )
2007-06-28 10:47:08 -07:00
{
2006-12-02 04:50:28 -08:00
retCode = INT_QUIT ;
}
2013-01-27 00:02:31 -08:00
else if ( ! retIDs . empty ( ) | | intMode = = INT_EDIT | | intMode = = INT_MISSIONRES | | widgOverID ! = 0 )
2006-12-02 04:50:28 -08:00
{
retCode = INT_INTERCEPT ;
2007-06-28 10:47:08 -07:00
}
2006-12-02 04:50:28 -08:00
2012-12-21 07:32:23 -08:00
if ( ( testPlayerHasLost ( ) | | testPlayerHasWon ( ) ) & & ! bMultiPlayer & & intMode ! = INT_MISSIONRES & & ! getDebugMappingStatus ( ) )
2007-06-28 10:47:08 -07:00
{
2012-12-21 07:32:23 -08:00
debug ( LOG_ERROR , " PlayerHasLost Or Won " ) ;
2008-03-24 09:51:17 -07:00
intResetScreen ( true ) ;
2006-12-02 04:50:28 -08:00
retCode = INT_QUIT ;
2007-06-28 10:47:08 -07:00
}
2006-12-02 04:50:28 -08:00
return retCode ;
2007-06-28 10:47:08 -07:00
}
/* Set the shadow for the PowerBar */
static void intRunPower ( void )
{
UDWORD statID ;
BASE_STATS * psStat ;
UDWORD quantity = 0 ;
RESEARCH * psResearch ;
/* Find out which button was hilited */
statID = widgGetMouseOver ( psWScreen ) ;
2007-02-10 08:39:39 -08:00
if ( statID > = IDSTAT_START & & statID < = IDSTAT_END )
2007-06-28 10:47:08 -07:00
{
psStat = ppsStatsList [ statID - IDSTAT_START ] ;
2006-05-27 09:37:17 -07:00
if ( psStat - > ref > = REF_STRUCTURE_START & & psStat - > ref <
2012-12-21 07:35:35 -08:00
REF_STRUCTURE_START + REF_RANGE )
2007-06-28 10:47:08 -07:00
{
//get the structure build points
2006-05-27 09:37:17 -07:00
quantity = ( ( STRUCTURE_STATS * ) apsStructStatsList [ statID -
2012-12-21 07:35:35 -08:00
IDSTAT_START ] ) - > powerToBuild ;
2007-06-28 10:47:08 -07:00
}
else if ( psStat - > ref > = REF_TEMPLATE_START & &
2012-12-21 07:35:35 -08:00
psStat - > ref < REF_TEMPLATE_START + REF_RANGE )
2007-06-28 10:47:08 -07:00
{
//get the template build points
2011-02-13 09:57:25 -08:00
quantity = calcTemplatePower ( apsTemplateList [ statID - IDSTAT_START ] ) ;
2007-06-28 10:47:08 -07:00
}
else if ( psStat - > ref > = REF_RESEARCH_START & &
2012-12-21 07:35:35 -08:00
psStat - > ref < REF_RESEARCH_START + REF_RANGE )
2007-06-28 10:47:08 -07:00
{
//get the research points
psResearch = ( RESEARCH * ) ppResearchList [ statID - IDSTAT_START ] ;
// has research been not been canceled
2011-12-02 05:26:37 -08:00
int rindex = psResearch - > index ;
if ( IsResearchCancelled ( & asPlayerResList [ selectedPlayer ] [ rindex ] ) = = 0 )
2007-06-28 10:47:08 -07:00
{
2011-12-02 05:26:37 -08:00
quantity = ( ( RESEARCH * ) ppResearchList [ statID - IDSTAT_START ] ) - > researchPower ;
2007-06-28 10:47:08 -07:00
}
}
//update the power bars
intSetShadowPower ( quantity ) ;
}
else
{
intSetShadowPower ( 0 ) ;
}
}
// Process stats screen.
static void intRunStats ( void )
{
BASE_OBJECT * psOwner ;
STRUCTURE * psStruct ;
FACTORY * psFactory ;
2012-12-21 07:35:35 -08:00
if ( intMode ! = INT_EDITSTAT & & objMode = = IOBJ_MANUFACTURE )
2007-06-28 10:47:08 -07:00
{
psOwner = ( BASE_OBJECT * ) widgGetUserData ( psWScreen , IDSTAT_LOOP_LABEL ) ;
2012-12-21 07:35:35 -08:00
ASSERT ( psOwner - > type = = OBJ_STRUCTURE , " intRunStats: Invalid object type " ) ;
2007-06-28 10:47:08 -07:00
psStruct = ( STRUCTURE * ) psOwner ;
2012-12-21 07:35:35 -08:00
ASSERT ( StructIsFactory ( psStruct ) , " intRunStats: Invalid Structure type " ) ;
2007-06-28 10:47:08 -07:00
psFactory = ( FACTORY * ) psStruct - > pFunctionality ;
//adjust the loop button if necessary
2010-02-23 09:43:18 -08:00
if ( psFactory - > psSubject ! = NULL & & psFactory - > productionLoops ! = 0 )
2007-06-28 10:47:08 -07:00
{
widgSetButtonState ( psWScreen , IDSTAT_LOOP_BUTTON , WBUT_CLICKLOCK ) ;
}
}
}
/* Add the stats screen for a given object */
static void intAddObjectStats ( BASE_OBJECT * psObj , UDWORD id )
{
BASE_STATS * psStats ;
2013-03-08 11:46:19 -08:00
UWORD statMajor = 0 ;
2012-12-21 07:35:35 -08:00
UDWORD i , j , index ;
2007-06-28 10:47:08 -07:00
UDWORD count ;
SDWORD iconNumber , entryIN ;
/* Clear a previous structure pos if there is one */
intStopStructPosition ( ) ;
/* Get the current tab pos */
2013-03-09 09:52:28 -08:00
objMajor = ( ( ListTabWidget * ) widgGetFromID ( psWScreen , IDOBJ_TABFORM ) ) - > currentPage ( ) ;
2007-06-28 10:47:08 -07:00
// Store the tab positions.
2006-05-27 09:37:17 -07:00
if ( intMode = = INT_STAT )
2007-06-28 10:47:08 -07:00
{
2012-12-21 07:35:35 -08:00
if ( widgGetFromID ( psWScreen , IDSTAT_FORM ) ! = NULL )
{
2013-03-08 11:46:19 -08:00
statMajor = ( ( ListTabWidget * ) widgGetFromID ( psWScreen , IDSTAT_TABFORM ) ) - > currentPage ( ) ;
2007-06-28 10:47:08 -07:00
}
intRemoveStatsNoAnim ( ) ;
}
/* Display the stats window
* - restore the tab position if there is no stats selected
*/
psStats = objGetStatsFunc ( psObj ) ;
// note the object for the screen
apsPreviousObj [ objMode ] = psObj ;
2006-05-27 09:37:17 -07:00
2007-12-03 12:47:05 -08:00
// NOTE! The below functions populate our list (building/units...)
// up to MAX____. We have unlimited potential, but it is capped at 200 now.
2007-06-28 10:47:08 -07:00
//determine the Structures that can be built
if ( objMode = = IOBJ_BUILD )
{
numStatsListEntries = fillStructureList ( apsStructStatsList ,
2012-12-21 07:35:35 -08:00
selectedPlayer , MAXSTRUCTURES - 1 ) ;
2007-06-28 10:47:08 -07:00
ppsStatsList = ( BASE_STATS * * ) apsStructStatsList ;
}
//have to determine the Template list once the factory has been chosen
if ( objMode = = IOBJ_MANUFACTURE )
{
2011-02-13 09:57:25 -08:00
fillTemplateList ( apsTemplateList , ( STRUCTURE * ) psObj ) ;
numStatsListEntries = apsTemplateList . size ( ) ;
ppsStatsList = ( BASE_STATS * * ) & apsTemplateList [ 0 ] ; // FIXME Ugly cast, and is undefined behaviour (strict-aliasing violation) in C/C++.
2007-06-28 10:47:08 -07:00
}
/*have to calculate the list each time the Topic button is pressed
so that only one topic can be researched at a time */
if ( objMode = = IOBJ_RESEARCH )
{
//set to value that won't be reached in fillResearchList
2011-12-02 05:26:37 -08:00
index = asResearch . size ( ) + 1 ;
2007-06-28 10:47:08 -07:00
if ( psStats )
{
2011-12-02 05:26:37 -08:00
index = ( ( RESEARCH * ) psStats ) - > index ;
2007-06-28 10:47:08 -07:00
}
//recalculate the list
2012-12-21 07:35:35 -08:00
numStatsListEntries = fillResearchList ( pList , selectedPlayer , ( UWORD ) index , MAXRESEARCH ) ;
2006-05-27 09:37:17 -07:00
2007-06-28 10:47:08 -07:00
// -- Alex's reordering of the list
2007-12-03 12:47:05 -08:00
// NOTE! Do we even want this anymore, since we can have basically
// unlimted tabs? Future enhancement assign T1/2/3 button on form
// so we can pick what level of tech we want to build instead of
// Alex picking for us?
2007-06-28 10:47:08 -07:00
count = 0 ;
2012-12-21 07:35:35 -08:00
for ( i = 0 ; i < RID_MAXRID ; i + + )
2007-06-28 10:47:08 -07:00
{
iconNumber = mapRIDToIcon ( i ) ;
2012-12-21 07:35:35 -08:00
for ( j = 0 ; j < numStatsListEntries ; j + + )
2007-06-28 10:47:08 -07:00
{
entryIN = asResearch [ pList [ j ] ] . iconID ;
2012-12-21 07:35:35 -08:00
if ( entryIN = = iconNumber )
2007-06-28 10:47:08 -07:00
{
2006-05-27 09:37:17 -07:00
pSList [ count + + ] = pList [ j ] ;
2007-06-28 10:47:08 -07:00
}
}
}
2007-12-03 12:47:05 -08:00
// Tag on the ones at the end that have no BASTARD icon IDs - why is this?!!?!?!?
// NOTE! more pruning [future ref]
2012-12-21 07:35:35 -08:00
for ( j = 0 ; j < numStatsListEntries ; j + + )
2007-06-28 10:47:08 -07:00
{
2010-12-05 14:20:09 -08:00
iconNumber = mapIconToRID ( asResearch [ pList [ j ] ] . iconID ) ;
if ( iconNumber < 0 )
2007-06-28 10:47:08 -07:00
{
pSList [ count + + ] = pList [ j ] ;
}
}
//fill up the list with topics
2012-12-21 07:35:35 -08:00
for ( i = 0 ; i < numStatsListEntries ; i + + )
2007-06-28 10:47:08 -07:00
{
2011-12-02 05:26:37 -08:00
ppResearchList [ i ] = & asResearch [ pSList [ i ] ] ; // note change from pList
2007-06-28 10:47:08 -07:00
}
}
intAddStats ( ppsStatsList , numStatsListEntries , psStats , psObj ) ;
2010-12-17 11:06:53 -08:00
// get the tab positions for the new stat form
// Restore the tab positions.
// only restore if we've still got at least that many tabs
2013-03-08 11:46:19 -08:00
if ( psStats = = nullptr & & widgGetFromID ( psWScreen , IDSTAT_TABFORM ) ! = nullptr )
{
( ( ListTabWidget * ) widgGetFromID ( psWScreen , IDSTAT_TABFORM ) ) - > setCurrentPage ( statMajor ) ;
2010-12-17 11:06:53 -08:00
}
2007-06-28 10:47:08 -07:00
intMode = INT_STAT ;
/* Note the object */
psObjSelected = psObj ;
objStatID = id ;
/* Reset the tabs and lock the button */
2013-03-09 09:52:28 -08:00
( ( ListTabWidget * ) widgGetFromID ( psWScreen , IDOBJ_TABFORM ) ) - > setCurrentPage ( objMajor ) ;
2012-12-21 07:35:35 -08:00
if ( id ! = 0 )
2007-06-28 10:47:08 -07:00
{
widgSetButtonState ( psWScreen , id , WBUT_CLICKLOCK ) ;
}
}
static void intSelectDroid ( BASE_OBJECT * psObj )
{
2012-12-21 07:35:35 -08:00
if ( driveModeActive ( ) )
{
2007-06-28 10:47:08 -07:00
clearSel ( ) ;
2012-12-21 07:35:35 -08:00
( ( DROID * ) psObj ) - > selected = true ;
2007-06-28 10:47:08 -07:00
driveSelectionChanged ( ) ;
driveDisableControl ( ) ;
2012-12-21 07:35:35 -08:00
}
else
{
2007-06-28 10:47:08 -07:00
clearSelection ( ) ;
2012-12-21 07:35:35 -08:00
( ( DROID * ) psObj ) - > selected = true ;
2007-06-28 10:47:08 -07:00
}
2012-12-30 02:58:45 -08:00
triggerEventSelected ( ) ;
2007-06-28 10:47:08 -07:00
}
static void intResetWindows ( BASE_OBJECT * psObj )
{
if ( psObj )
{
// reset the object screen with the new object
switch ( objMode )
{
case IOBJ_BUILD :
case IOBJ_BUILDSEL :
case IOBJ_DEMOLISHSEL :
intAddBuild ( ( DROID * ) psObj ) ;
break ;
case IOBJ_RESEARCH :
intAddResearch ( ( STRUCTURE * ) psObj ) ;
break ;
case IOBJ_MANUFACTURE :
intAddManufacture ( ( STRUCTURE * ) psObj ) ;
break ;
case IOBJ_COMMAND :
intAddCommand ( ( DROID * ) psObj ) ;
break ;
default :
break ;
}
}
}
/* Process return codes from the object screen */
static void intProcessObject ( UDWORD id )
{
BASE_OBJECT * psObj ;
STRUCTURE * psStruct ;
SDWORD butIndex ;
UDWORD statButID ;
2012-12-21 07:32:23 -08:00
ASSERT ( widgGetFromID ( psWScreen , IDOBJ_TABFORM ) ! = NULL , " Missing form " ) ;
2007-06-28 10:47:08 -07:00
// deal with CRTL clicks
if ( objMode = = IOBJ_BUILD & & // What..................?
2012-12-21 07:35:35 -08:00
( keyDown ( KEY_LCTRL ) | | keyDown ( KEY_RCTRL ) | | keyDown ( KEY_LSHIFT ) | | keyDown ( KEY_RSHIFT ) ) & &
( ( id > = IDOBJ_OBJSTART & & id < = IDOBJ_OBJEND ) | |
( id > = IDOBJ_STATSTART & & id < = IDOBJ_STATEND ) ) )
2007-06-28 10:47:08 -07:00
{
/* Find the object that the ID refers to */
psObj = intGetObject ( id ) ;
if ( id > = IDOBJ_OBJSTART & & id < = IDOBJ_OBJEND )
{
statButID = IDOBJ_STATSTART + id - IDOBJ_OBJSTART ;
}
else
{
statButID = id ;
}
2013-11-17 06:18:46 -08:00
if ( psObj & & psObj - > selected )
2007-06-28 10:47:08 -07:00
{
2008-03-24 09:51:17 -07:00
psObj - > selected = false ;
2007-06-28 10:47:08 -07:00
widgSetButtonState ( psWScreen , statButID , 0 ) ;
2012-12-21 07:32:23 -08:00
if ( intNumSelectedDroids ( DROID_CONSTRUCT ) = = 0 & & intNumSelectedDroids ( DROID_CYBORG_CONSTRUCT ) = = 0 )
2007-06-28 10:47:08 -07:00
{
intRemoveStats ( ) ;
}
if ( psObjSelected = = psObj )
{
psObjSelected = ( BASE_OBJECT * ) intCheckForDroid ( DROID_CONSTRUCT ) ;
2012-12-21 07:35:35 -08:00
if ( ! psObjSelected )
{
psObjSelected = ( BASE_OBJECT * ) intCheckForDroid ( DROID_CYBORG_CONSTRUCT ) ;
}
2007-06-28 10:47:08 -07:00
}
}
else
{
if ( psObjSelected )
{
2008-03-24 09:51:17 -07:00
psObjSelected - > selected = true ;
2007-06-28 10:47:08 -07:00
}
2008-03-24 09:51:17 -07:00
psObj - > selected = true ;
2007-06-28 10:47:08 -07:00
widgSetButtonState ( psWScreen , statButID , WBUT_CLICKLOCK ) ;
intAddObjectStats ( psObj , statButID ) ;
}
2012-12-30 02:58:45 -08:00
triggerEventSelected ( ) ;
2007-06-28 10:47:08 -07:00
}
2012-12-21 07:32:23 -08:00
else if ( id > = IDOBJ_OBJSTART & & id < = IDOBJ_OBJEND )
2007-06-28 10:47:08 -07:00
{
/* deal with RMB clicks */
2013-01-26 08:48:54 -08:00
if ( widgGetButtonKey_DEPRECATED ( psWScreen ) = = WKEY_SECONDARY )
2007-06-28 10:47:08 -07:00
{
intObjectRMBPressed ( id ) ;
}
/* deal with LMB clicks */
else
{
/* An object button has been pressed */
/* Find the object that the ID refers to */
psObj = intGetObject ( id ) ;
2012-12-21 07:32:23 -08:00
if ( ! psObj )
2007-06-28 10:47:08 -07:00
{
2012-12-21 07:32:23 -08:00
return ;
}
2012-12-21 07:35:35 -08:00
if ( psObj - > type = = OBJ_STRUCTURE & & ! offWorldKeepLists )
{
/* Deselect old buildings */
for ( psStruct = apsStructLists [ selectedPlayer ] ; psStruct ; psStruct = psStruct - > psNext )
{
psStruct - > selected = false ;
}
2006-05-27 09:37:17 -07:00
2012-12-21 07:35:35 -08:00
/* Select new one */
( ( STRUCTURE * ) psObj ) - > selected = true ;
2012-12-30 02:58:45 -08:00
triggerEventSelected ( ) ;
2012-12-21 07:35:35 -08:00
}
2006-05-27 09:37:17 -07:00
2012-12-21 07:35:35 -08:00
if ( ! driveModeActive ( ) )
{
// don't do this if offWorld and a structure object has been selected
if ( ! ( psObj - > type = = OBJ_STRUCTURE & & offWorldKeepLists ) )
{
// set the map position - either the object position, or the position jumped from
butIndex = id - IDOBJ_OBJSTART ;
if ( butIndex > = 0 & & butIndex < = IDOBJ_OBJEND - IDOBJ_OBJSTART )
2012-12-18 06:59:49 -08:00
{
2012-12-21 07:35:35 -08:00
asJumpPos . resize ( IDOBJ_OBJEND - IDOBJ_OBJSTART , Vector2i ( 0 , 0 ) ) ;
if ( ( ( asJumpPos [ butIndex ] . x = = 0 ) & & ( asJumpPos [ butIndex ] . y = = 0 ) ) | |
! DrawnInLastFrame ( ( SDWORD ) psObj - > sDisplay . frameNumber ) | |
( ( psObj - > sDisplay . screenX > pie_GetVideoBufferWidth ( ) ) | |
( psObj - > sDisplay . screenY > pie_GetVideoBufferHeight ( ) ) ) )
2012-12-18 06:59:49 -08:00
{
2012-12-21 07:35:35 -08:00
asJumpPos [ butIndex ] = getPlayerPos ( ) ;
setPlayerPos ( psObj - > pos . x , psObj - > pos . y ) ;
if ( getWarCamStatus ( ) )
{
camToggleStatus ( ) ;
2012-12-18 06:59:49 -08:00
}
}
2012-12-21 07:35:35 -08:00
else
{
setPlayerPos ( asJumpPos [ butIndex ] . x , asJumpPos [ butIndex ] . y ) ;
if ( getWarCamStatus ( ) )
{
camToggleStatus ( ) ;
}
asJumpPos [ butIndex ] . x = 0 ;
asJumpPos [ butIndex ] . y = 0 ;
}
2012-12-18 06:59:49 -08:00
}
2012-12-21 07:35:35 -08:00
}
}
2007-06-28 10:47:08 -07:00
2012-12-21 07:35:35 -08:00
intResetWindows ( psObj ) ;
2007-06-28 10:47:08 -07:00
2012-12-21 07:35:35 -08:00
// If a construction droid button was clicked then
// clear all other selections and select it.
if ( psObj - > type = = OBJ_DROID )
{
intSelectDroid ( psObj ) ;
psObjSelected = psObj ;
2007-06-28 10:47:08 -07:00
2012-12-21 07:35:35 -08:00
}
2007-06-28 10:47:08 -07:00
}
}
/* A object stat button has been pressed */
else if ( id > = IDOBJ_STATSTART & &
2012-12-21 07:35:35 -08:00
id < = IDOBJ_STATEND )
2007-06-28 10:47:08 -07:00
{
/* deal with RMB clicks */
2013-01-26 08:48:54 -08:00
if ( widgGetButtonKey_DEPRECATED ( psWScreen ) = = WKEY_SECONDARY )
2007-06-28 10:47:08 -07:00
{
intObjStatRMBPressed ( id ) ;
}
else
{
/* Find the object that the stats ID refers to */
psObj = intGetObject ( id ) ;
2013-11-17 06:18:46 -08:00
ASSERT_OR_RETURN ( , psObj , " Missing referred to object id %u " , id ) ;
2007-06-28 10:47:08 -07:00
intResetWindows ( psObj ) ;
// If a droid button was clicked then clear all other selections and select it.
2012-12-21 07:35:35 -08:00
if ( psObj - > type = = OBJ_DROID )
2007-06-28 10:47:08 -07:00
{
// Select the droid when the stat button (in the object window) is pressed.
intSelectDroid ( psObj ) ;
psObjSelected = psObj ;
}
else if ( psObj - > type = = OBJ_STRUCTURE )
{
if ( StructIsFactory ( ( STRUCTURE * ) psObj ) )
{
//might need to cancel the hold on production
2010-10-22 09:13:04 -07:00
releaseProduction ( ( STRUCTURE * ) psObj , ModeQueue ) ;
2007-06-28 10:47:08 -07:00
}
2010-07-22 00:34:42 -07:00
else if ( ( ( STRUCTURE * ) psObj ) - > pStructureType - > type = = REF_RESEARCH )
{
2007-06-28 10:47:08 -07:00
//might need to cancel the hold on research facilty
2010-10-22 09:13:04 -07:00
releaseResearch ( ( STRUCTURE * ) psObj , ModeQueue ) ;
2010-07-22 00:34:42 -07:00
}
2012-03-17 11:54:17 -07:00
for ( STRUCTURE * psCurr = apsStructLists [ selectedPlayer ] ; psCurr ; psCurr = psCurr - > psNext )
{
psCurr - > selected = false ;
}
psObj - > selected = true ;
2012-12-30 02:58:45 -08:00
triggerEventSelected ( ) ;
2007-06-28 10:47:08 -07:00
}
}
}
else if ( id = = IDOBJ_CLOSE )
{
2008-03-24 09:51:17 -07:00
intResetScreen ( false ) ;
2007-06-28 10:47:08 -07:00
intMode = INT_NORMAL ;
}
else
{
if ( objMode ! = IOBJ_COMMAND & & id ! = IDOBJ_TABFORM )
{
/* Not a button on the build form, must be on the stats form */
intProcessStats ( id ) ;
}
else if ( id ! = IDOBJ_TABFORM )
{
intProcessOrder ( id ) ;
}
}
}
/* Process return codes from the stats screen */
static void intProcessStats ( UDWORD id )
{
BASE_STATS * psStats ;
STRUCTURE * psStruct ;
FLAG_POSITION * psFlag ;
2010-06-27 12:12:18 -07:00
int compIndex ;
2007-06-28 10:47:08 -07:00
2012-12-21 07:35:35 -08:00
ASSERT ( widgGetFromID ( psWScreen , IDOBJ_TABFORM ) ! = NULL , " Missing form " ) ;
2007-06-28 10:47:08 -07:00
if ( id > = IDSTAT_START & &
2012-12-21 07:35:35 -08:00
id < = IDSTAT_END )
2007-06-28 10:47:08 -07:00
{
2012-12-21 07:35:35 -08:00
ASSERT ( id - IDSTAT_START < numStatsListEntries ,
" intProcessStructure: Invalid structure stats id " ) ;
2007-06-28 10:47:08 -07:00
/* deal with RMB clicks */
2013-01-26 08:48:54 -08:00
if ( widgGetButtonKey_DEPRECATED ( psWScreen ) = = WKEY_SECONDARY )
2007-06-28 10:47:08 -07:00
{
intStatsRMBPressed ( id ) ;
}
/* deal with LMB clicks */
else
{
//manufacture works differently!
2012-12-21 07:35:35 -08:00
if ( objMode = = IOBJ_MANUFACTURE )
2007-06-28 10:47:08 -07:00
{
2010-06-27 12:12:18 -07:00
compIndex = id - IDSTAT_START ;
2007-06-28 10:47:08 -07:00
//get the stats
2012-12-21 07:35:35 -08:00
ASSERT_OR_RETURN ( , compIndex < numStatsListEntries , " Invalid range referenced for numStatsListEntries, %d > %d " , compIndex , numStatsListEntries ) ;
2010-06-27 12:12:18 -07:00
psStats = ppsStatsList [ compIndex ] ;
2012-12-21 07:35:35 -08:00
ASSERT_OR_RETURN ( , psObjSelected ! = NULL , " Invalid structure pointer " ) ;
ASSERT_OR_RETURN ( , psStats ! = NULL , " Invalid template pointer " ) ;
2010-06-27 12:12:18 -07:00
if ( productionPlayer = = ( SBYTE ) selectedPlayer )
{
2010-07-20 13:57:19 -07:00
STRUCTURE * psStructure = ( STRUCTURE * ) psObjSelected ;
FACTORY * psFactory = & psStructure - > pFunctionality - > factory ;
DROID_TEMPLATE * psNext = ( DROID_TEMPLATE * ) psStats ;
2006-05-27 09:37:17 -07:00
2010-07-20 13:57:19 -07:00
//increase the production
factoryProdAdjust ( psStructure , psNext , true ) ;
//need to check if this was the template that was mid-production
2010-12-23 16:13:01 -08:00
if ( getProduction ( psStructure , FactoryGetTemplate ( psFactory ) ) . numRemaining ( ) = = 0 )
2010-07-20 13:57:19 -07:00
{
2010-12-07 12:58:37 -08:00
doNextProduction ( psStructure , FactoryGetTemplate ( psFactory ) , ModeQueue ) ;
2010-07-20 13:57:19 -07:00
psNext = FactoryGetTemplate ( psFactory ) ;
}
2010-12-23 16:13:01 -08:00
else if ( ! StructureIsManufacturingPending ( psStructure ) )
{
structSetManufacture ( psStructure , psNext , ModeQueue ) ;
}
2010-07-20 13:57:19 -07:00
if ( StructureIsOnHoldPending ( psStructure ) )
{
2010-10-22 09:13:04 -07:00
releaseProduction ( psStructure , ModeQueue ) ;
2010-07-20 13:57:19 -07:00
}
// Reset the button on the object form
intSetStats ( objStatID , ( BASE_STATS * ) psNext ) ;
}
2007-06-28 10:47:08 -07:00
}
else
{
/* See if this was a click on an already selected stat */
psStats = objGetStatsFunc ( psObjSelected ) ;
2010-01-12 11:43:09 -08:00
// only do the cancel operation if not trying to add to the build list
if ( psStats = = ppsStatsList [ id - IDSTAT_START ] & & objMode ! = IOBJ_BUILD )
2007-06-28 10:47:08 -07:00
{
2010-01-12 11:43:09 -08:00
// this needs to be done before the topic is cancelled from the structure
2007-06-28 10:47:08 -07:00
/* If Research then need to set topic to be cancelled */
if ( objMode = = IOBJ_RESEARCH )
{
2012-12-21 07:35:35 -08:00
if ( psObjSelected - > type = = OBJ_STRUCTURE )
2007-06-28 10:47:08 -07:00
{
2012-02-06 04:54:32 -08:00
// TODO This call seems to be redundant, since cancelResearch is called from objSetStatsFunc==setResearchStats.
2010-10-22 09:13:04 -07:00
cancelResearch ( ( STRUCTURE * ) psObjSelected , ModeQueue ) ;
2007-06-28 10:47:08 -07:00
}
}
/* Clear the object stats */
objSetStatsFunc ( psObjSelected , NULL ) ;
2006-05-27 09:37:17 -07:00
2007-06-28 10:47:08 -07:00
/* Reset the button on the object form */
intSetStats ( objStatID , NULL ) ;
/* Unlock the button on the stats form */
widgSetButtonState ( psWScreen , id , 0 ) ;
}
else
{
//If Research then need to set the topic - if one, to be cancelled
if ( objMode = = IOBJ_RESEARCH )
{
if ( psObjSelected - > type = = OBJ_STRUCTURE & & ( ( STRUCTURE * )
2012-12-21 07:35:35 -08:00
psObjSelected ) - > pStructureType - > type = = REF_RESEARCH )
2007-06-28 10:47:08 -07:00
{
//if there was a topic currently being researched - cancel it
if ( ( ( RESEARCH_FACILITY * ) ( ( STRUCTURE * ) psObjSelected ) - >
2012-12-21 07:35:35 -08:00
pFunctionality ) - > psSubject )
2007-06-28 10:47:08 -07:00
{
2010-10-22 09:13:04 -07:00
cancelResearch ( ( STRUCTURE * ) psObjSelected , ModeQueue ) ;
2007-06-28 10:47:08 -07:00
}
2006-05-27 09:37:17 -07:00
}
2007-06-28 10:47:08 -07:00
}
// call the tutorial callback if necessary
if ( bInTutorial & & objMode = = IOBJ_BUILD )
{
eventFireCallbackTrigger ( ( TRIGGER_TYPE ) CALL_BUILDGRID ) ;
}
// Set the object stats
2010-06-27 12:12:18 -07:00
compIndex = id - IDSTAT_START ;
2012-12-21 07:35:35 -08:00
ASSERT_OR_RETURN ( , compIndex < numStatsListEntries , " Invalid range referenced for numStatsListEntries, %d > %d " , compIndex , numStatsListEntries ) ;
2010-06-27 12:12:18 -07:00
psStats = ppsStatsList [ compIndex ] ;
2006-05-27 09:37:17 -07:00
2007-06-28 10:47:08 -07:00
// Reset the button on the object form
2008-03-24 09:51:17 -07:00
//if this returns false, there's a problem so set the button to NULL
2007-06-28 10:47:08 -07:00
if ( ! objSetStatsFunc ( psObjSelected , psStats ) )
{
intSetStats ( objStatID , NULL ) ;
}
else
{
// Reset the button on the object form
intSetStats ( objStatID , psStats ) ;
}
}
// Get the tabs on the object form
2013-03-09 09:52:28 -08:00
objMajor = ( ( ListTabWidget * ) widgGetFromID ( psWScreen , IDOBJ_TABFORM ) ) - > currentPage ( ) ;
2007-06-28 10:47:08 -07:00
// Close the stats box
intRemoveStats ( ) ;
intMode = INT_OBJECT ;
2006-07-24 13:12:36 -07:00
2007-06-28 10:47:08 -07:00
// Reset the tabs on the object form
2013-03-09 09:52:28 -08:00
( ( ListTabWidget * ) widgGetFromID ( psWScreen , IDOBJ_TABFORM ) ) - > setCurrentPage ( objMajor ) ;
2007-06-28 10:47:08 -07:00
// Close the object box as well if selecting a location to build- no longer hide/reveal
2010-12-05 14:20:09 -08:00
// or if selecting a structure to demolish
2007-02-10 08:39:39 -08:00
if ( objMode = = IOBJ_BUILDSEL | | objMode = = IOBJ_DEMOLISHSEL )
2007-06-28 10:47:08 -07:00
{
2010-12-05 14:20:09 -08:00
if ( driveModeActive ( ) )
{
2007-06-28 10:47:08 -07:00
// Make sure weve got a construction droid selected.
2010-12-05 14:20:09 -08:00
if ( driveGetDriven ( ) - > droidType ! = DROID_CONSTRUCT
& & driveGetDriven ( ) - > droidType ! = DROID_CYBORG_CONSTRUCT )
{
2007-06-28 10:47:08 -07:00
driveDisableControl ( ) ;
}
2012-12-21 07:35:35 -08:00
driveDisableTactical ( ) ;
2007-06-28 10:47:08 -07:00
driveStartBuild ( ) ;
intRemoveObject ( ) ;
}
intRemoveObject ( ) ;
2010-12-05 14:20:09 -08:00
// hack to stop the stats window re-opening in demolish mode
if ( objMode = = IOBJ_DEMOLISHSEL )
{
IntRefreshPending = false ;
}
2007-06-28 10:47:08 -07:00
}
}
}
}
else if ( id = = IDSTAT_CLOSE )
{
/* Get the tabs on the object form */
2013-03-09 09:52:28 -08:00
objMajor = ( ( ListTabWidget * ) widgGetFromID ( psWScreen , IDOBJ_TABFORM ) ) - > currentPage ( ) ;
2007-06-28 10:47:08 -07:00
/* Close the structure box without doing anything */
intRemoveStats ( ) ;
intMode = INT_OBJECT ;
/* Reset the tabs on the build form */
2013-03-09 09:52:28 -08:00
( ( ListTabWidget * ) widgGetFromID ( psWScreen , IDOBJ_TABFORM ) ) - > setCurrentPage ( objMajor ) ;
2007-06-28 10:47:08 -07:00
/* Unlock the stats button */
widgSetButtonState ( psWScreen , objStatID , 0 ) ;
}
2012-12-21 07:35:35 -08:00
else if ( id = = IDSTAT_SLIDER )
{
2007-06-28 10:47:08 -07:00
// Process the quantity slider.
}
2012-12-21 07:35:35 -08:00
else if ( id > = IDPROX_START & & id < = IDPROX_END )
2007-06-28 10:47:08 -07:00
{
// process the proximity blip buttons.
}
2012-12-21 07:35:35 -08:00
else if ( id = = IDSTAT_LOOP_BUTTON )
2007-06-28 10:47:08 -07:00
{
// Process the loop button.
2012-12-21 07:35:35 -08:00
psStruct = ( STRUCTURE * ) widgGetUserData ( psWScreen , IDSTAT_LOOP_LABEL ) ;
2007-06-28 10:47:08 -07:00
if ( psStruct )
{
//LMB pressed
2013-01-26 08:48:54 -08:00
if ( widgGetButtonKey_DEPRECATED ( psWScreen ) = = WKEY_PRIMARY )
2007-06-28 10:47:08 -07:00
{
2008-03-24 09:51:17 -07:00
factoryLoopAdjust ( psStruct , true ) ;
2007-06-28 10:47:08 -07:00
}
//RMB pressed
2013-01-26 08:48:54 -08:00
else if ( widgGetButtonKey_DEPRECATED ( psWScreen ) = = WKEY_SECONDARY )
2007-06-28 10:47:08 -07:00
{
2008-03-24 09:51:17 -07:00
factoryLoopAdjust ( psStruct , false ) ;
2007-06-28 10:47:08 -07:00
}
2010-02-23 09:43:18 -08:00
if ( ( ( FACTORY * ) psStruct - > pFunctionality ) - > psSubject ! = NULL & & ( ( FACTORY * ) psStruct - > pFunctionality ) - > productionLoops ! = 0 )
2007-06-28 10:47:08 -07:00
{
//lock the button
widgSetButtonState ( psWScreen , IDSTAT_LOOP_BUTTON , WBUT_CLICKLOCK ) ;
}
else
{
//unlock
widgSetButtonState ( psWScreen , IDSTAT_LOOP_BUTTON , 0 ) ;
}
}
}
2012-12-21 07:35:35 -08:00
else if ( id = = IDSTAT_DP_BUTTON )
2007-06-28 10:47:08 -07:00
{
// Process the DP button
2012-12-21 07:35:35 -08:00
psStruct = ( STRUCTURE * ) widgGetUserData ( psWScreen , IDSTAT_DP_BUTTON ) ;
2007-06-28 10:47:08 -07:00
if ( psStruct )
{
// make sure that the factory isn't assigned to a commander
assignFactoryCommandDroid ( psStruct , NULL ) ;
psFlag = FindFactoryDelivery ( psStruct ) ;
if ( psFlag )
{
2012-06-21 15:34:04 -07:00
startDeliveryPosition ( psFlag ) ;
2007-06-28 10:47:08 -07:00
}
}
}
2013-05-21 11:48:17 -07:00
else if ( id = = IDSTAT_OBSOLETE_BUTTON )
{
includeRedundantDesigns = ! includeRedundantDesigns ;
StateButton * obsoleteButton = ( StateButton * ) widgGetFromID ( psWScreen , IDSTAT_OBSOLETE_BUTTON ) ;
obsoleteButton - > setState ( includeRedundantDesigns ) ;
intRefreshScreen ( ) ;
}
2007-06-28 10:47:08 -07:00
}
/* Set the map view point to the world coordinates x,y */
void intSetMapPos ( UDWORD x , UDWORD y )
{
2007-11-04 07:04:43 -08:00
if ( ! driveModeActive ( ) )
{
2008-03-24 09:51:17 -07:00
setViewPos ( map_coord ( x ) , map_coord ( y ) , true ) ;
2007-06-28 10:47:08 -07:00
}
}
/* Sync the interface to an object */
// If psObj is NULL then reset interface displays.
//
// There should be two version of this function, one for left clicking and one got right.
//
void intObjectSelected ( BASE_OBJECT * psObj )
{
2012-12-21 07:35:35 -08:00
if ( psObj )
2010-12-05 14:20:09 -08:00
{
2008-03-24 09:51:17 -07:00
setWidgetsStatus ( true ) ;
2012-12-21 07:35:35 -08:00
switch ( psObj - > type )
2007-06-28 10:47:08 -07:00
{
case OBJ_DROID :
2012-12-21 07:35:35 -08:00
if ( ! OrderUp )
2007-06-28 10:47:08 -07:00
{
2008-03-24 09:51:17 -07:00
intResetScreen ( false ) ;
2010-12-05 14:20:09 -08:00
// changed to a BASE_OBJECT to accomodate the factories - AB 21/04/99
intAddOrder ( psObj ) ;
2007-06-28 10:47:08 -07:00
intMode = INT_ORDER ;
}
else
{
2010-12-05 14:20:09 -08:00
// changed to a BASE_OBJECT to accomodate the factories - AB 21/04/99
intAddOrder ( psObj ) ;
2007-06-28 10:47:08 -07:00
}
break ;
case OBJ_STRUCTURE :
//don't do anything if structure is only partially built
2008-03-24 09:51:17 -07:00
intResetScreen ( false ) ;
2007-06-28 10:47:08 -07:00
2012-12-21 07:35:35 -08:00
if ( objMode = = IOBJ_DEMOLISHSEL )
2007-06-28 10:47:08 -07:00
{
/* do nothing here */
break ;
}
if ( ( ( STRUCTURE * ) psObj ) - > status = = SS_BUILT )
{
2007-02-10 08:39:39 -08:00
if ( ( ( STRUCTURE * ) psObj ) - > pStructureType - > type = = REF_FACTORY | |
2012-12-21 07:35:35 -08:00
( ( STRUCTURE * ) psObj ) - > pStructureType - > type = = REF_CYBORG_FACTORY | |
( ( STRUCTURE * ) psObj ) - > pStructureType - > type = = REF_VTOL_FACTORY )
2007-06-28 10:47:08 -07:00
{
intAddManufacture ( ( STRUCTURE * ) psObj ) ;
}
else if ( ( ( STRUCTURE * ) psObj ) - > pStructureType - > type = = REF_RESEARCH )
{
intAddResearch ( ( STRUCTURE * ) psObj ) ;
}
}
break ;
default :
break ;
}
2012-12-21 07:35:35 -08:00
}
else
{
2008-03-24 09:51:17 -07:00
intResetScreen ( false ) ;
2007-06-28 10:47:08 -07:00
}
}
// add the construction interface if a constructor droid is selected
void intConstructorSelected ( DROID * psDroid )
{
2008-03-24 09:51:17 -07:00
setWidgetsStatus ( true ) ;
2007-06-28 10:47:08 -07:00
intAddBuild ( psDroid ) ;
widgHide ( psWScreen , IDOBJ_FORM ) ;
}
// add the construction interface if a constructor droid is selected
void intCommanderSelected ( DROID * psDroid )
{
2008-03-24 09:51:17 -07:00
setWidgetsStatus ( true ) ;
2007-06-28 10:47:08 -07:00
intAddCommand ( psDroid ) ;
widgHide ( psWScreen , IDOBJ_FORM ) ;
}
/* Start looking for a structure location */
2008-10-14 15:02:35 -07:00
static void intStartStructPosition ( BASE_STATS * psStats )
2007-06-28 10:47:08 -07:00
{
2012-12-21 07:35:35 -08:00
init3DBuilding ( psStats , NULL , NULL ) ;
2007-06-28 10:47:08 -07:00
}
/* Stop looking for a structure location */
static void intStopStructPosition ( void )
{
/* Check there is still a struct position running */
2010-12-05 14:20:09 -08:00
if ( ( intMode = = INT_OBJECT | | intMode = = INT_STAT ) & & objMode = = IOBJ_BUILDSEL )
{
2006-05-27 09:37:17 -07:00
// Reset the stats button
2007-06-28 10:47:08 -07:00
objMode = IOBJ_BUILD ;
}
kill3DBuilding ( ) ;
}
/* Display the widgets for the in game interface */
void intDisplayWidgets ( void )
{
2007-11-12 11:08:55 -08:00
if ( ReticuleUp & & ! bInTutorial )
{
2007-06-28 10:47:08 -07:00
intCheckReticuleButtons ( ) ;
}
/*draw the background for the design screen and the Intelligence screen*/
2007-02-10 08:39:39 -08:00
if ( intMode = = INT_DESIGN | | intMode = = INT_INTELMAP )
2007-06-28 10:47:08 -07:00
{
2007-11-12 11:08:55 -08:00
// When will they ever learn!!!!
2007-06-28 10:47:08 -07:00
if ( ! bMultiPlayer )
{
2006-07-24 13:12:36 -07:00
screen_RestartBackDrop ( ) ;
2007-06-28 10:47:08 -07:00
// We need to add the console messages to the intelmap for the tutorial so that it can display messages
2012-12-21 07:35:35 -08:00
if ( ( intMode = = INT_DESIGN ) | | ( bInTutorial & & intMode = = INT_INTELMAP ) )
2007-06-28 10:47:08 -07:00
{
displayConsoleMessages ( ) ;
}
}
}
widgDisplayScreen ( psWScreen ) ;
2012-12-21 07:35:35 -08:00
if ( bLoadSaveUp )
2007-06-28 10:47:08 -07:00
{
displayLoadSave ( ) ;
}
}
/* Tell the interface when an object is created - it may have to be added to a screen */
void intNewObj ( BASE_OBJECT * psObj )
{
if ( intMode = = INT_OBJECT | | intMode = = INT_STAT )
{
if ( ( objMode = = IOBJ_BUILD | | objMode = = IOBJ_BUILDSEL ) & &
2012-12-21 07:35:35 -08:00
psObj - > type = = OBJ_DROID & & objSelectFunc ( psObj ) )
2007-06-28 10:47:08 -07:00
{
2008-03-24 09:51:17 -07:00
objectsChanged = true ;
2007-06-28 10:47:08 -07:00
}
else if ( ( objMode = = IOBJ_RESEARCH | | objMode = = IOBJ_MANUFACTURE ) & &
2012-12-21 07:35:35 -08:00
psObj - > type = = OBJ_STRUCTURE & & objSelectFunc ( psObj ) )
2007-06-28 10:47:08 -07:00
{
2008-03-24 09:51:17 -07:00
objectsChanged = true ;
2007-06-28 10:47:08 -07:00
}
}
}
// clean up when an object dies
2007-05-27 15:15:10 -07:00
static void intObjectDied ( UDWORD objID )
2007-06-28 10:47:08 -07:00
{
UDWORD statsID , gubbinsID ;
// clear the object button
2013-03-13 00:57:13 -07:00
IntObjectButton * psBut = ( IntObjectButton * ) widgGetFromID ( psWScreen , objID ) ;
2013-03-16 00:37:56 -07:00
if ( psBut ! = nullptr & & psBut - > clearData ( ) )
2007-06-28 10:47:08 -07:00
{
// and its gubbins
gubbinsID = IDOBJ_FACTORYSTART + objID - IDOBJ_OBJSTART ;
widgSetUserData ( psWScreen , gubbinsID , NULL ) ;
gubbinsID = IDOBJ_COUNTSTART + objID - IDOBJ_OBJSTART ;
widgSetUserData ( psWScreen , gubbinsID , NULL ) ;
gubbinsID = IDOBJ_PROGBARSTART + objID - IDOBJ_OBJSTART ;
widgSetUserData ( psWScreen , gubbinsID , NULL ) ;
// clear the stats button
statsID = IDOBJ_STATSTART + objID - IDOBJ_OBJSTART ;
intSetStats ( statsID , NULL ) ;
// and disable it
widgSetButtonState ( psWScreen , statsID , WBUT_DISABLE ) ;
// remove the stat screen if necessary
2012-12-21 07:35:35 -08:00
if ( ( intMode = = INT_STAT ) & & statsID = = objStatID )
2007-06-28 10:47:08 -07:00
{
intRemoveStatsNoAnim ( ) ;
intMode = INT_OBJECT ;
}
}
}
/* Tell the interface a construction droid has finished building */
void intBuildFinished ( DROID * psDroid )
{
UDWORD droidID ;
DROID * psCurr ;
2010-12-05 14:20:09 -08:00
ASSERT ( psDroid ! = NULL , " Invalid droid pointer " ) ;
2007-06-28 10:47:08 -07:00
if ( ( intMode = = INT_OBJECT | | intMode = = INT_STAT ) & &
2012-12-21 07:35:35 -08:00
objMode = = IOBJ_BUILD )
2007-06-28 10:47:08 -07:00
{
/* Find which button the droid is on and clear it's stats */
droidID = 0 ;
for ( psCurr = apsDroidLists [ selectedPlayer ] ; psCurr ; psCurr = psCurr - > psNext )
{
if ( objSelectFunc ( ( BASE_OBJECT * ) psCurr ) )
{
if ( psCurr = = psDroid )
{
intSetStats ( droidID + IDOBJ_STATSTART , NULL ) ;
break ;
}
droidID + + ;
}
}
}
}
/* Tell the interface a construction droid has started building*/
void intBuildStarted ( DROID * psDroid )
{
UDWORD droidID ;
DROID * psCurr ;
2012-12-21 07:35:35 -08:00
ASSERT ( psDroid ! = NULL ,
" intBuildStarted: Invalid droid pointer " ) ;
2007-06-28 10:47:08 -07:00
if ( ( intMode = = INT_OBJECT | | intMode = = INT_STAT ) & &
2012-12-21 07:35:35 -08:00
objMode = = IOBJ_BUILD )
2007-06-28 10:47:08 -07:00
{
/* Find which button the droid is on and clear it's stats */
droidID = 0 ;
for ( psCurr = apsDroidLists [ selectedPlayer ] ; psCurr ; psCurr = psCurr - > psNext )
{
if ( objSelectFunc ( ( BASE_OBJECT * ) psCurr ) )
{
if ( psCurr = = psDroid )
{
2011-12-30 08:43:49 -08:00
intSetStats ( droidID + IDOBJ_STATSTART , ( ( STRUCTURE * ) psCurr - > order . psObj ) - > pStructureType ) ;
2007-06-28 10:47:08 -07:00
break ;
}
droidID + + ;
}
}
}
}
/* Are we in build select mode*/
2011-03-12 17:32:15 -08:00
bool intBuildSelectMode ( void )
2007-06-28 10:47:08 -07:00
{
return ( objMode = = IOBJ_BUILDSEL ) ;
}
/* Are we in demolish select mode*/
2011-03-12 17:32:15 -08:00
bool intDemolishSelectMode ( void )
2007-06-28 10:47:08 -07:00
{
return ( objMode = = IOBJ_DEMOLISHSEL ) ;
}
//is the build interface up?
2011-03-12 17:32:15 -08:00
bool intBuildMode ( void )
2007-06-28 10:47:08 -07:00
{
return ( objMode = = IOBJ_BUILD ) ;
}
//Written to allow demolish order to be added to the queuing system
void intDemolishCancel ( void )
{
2012-12-21 07:35:35 -08:00
if ( objMode = = IOBJ_DEMOLISHSEL )
{
objMode = IOBJ_NONE ;
}
2007-06-28 10:47:08 -07:00
}
2006-12-02 04:50:28 -08:00
//reorder the research facilities so that first built is first in the list
static void orderResearch ( void )
{
2011-01-04 06:48:00 -08:00
std : : reverse ( apsObjectList . begin ( ) , apsObjectList . end ( ) ) ; // Why reverse this list, instead of sorting it?
2006-12-02 04:50:28 -08:00
}
2011-01-04 06:48:00 -08:00
static inline bool sortObjectByIdFunction ( BASE_OBJECT * a , BASE_OBJECT * b )
{
2012-12-21 07:35:35 -08:00
return ( a = = NULL ? 0 : a - > id ) < ( b = = NULL ? 0 : b - > id ) ;
2011-01-04 06:48:00 -08:00
}
2006-12-02 04:50:28 -08:00
// reorder the commanders
static void orderDroids ( void )
{
// bubble sort on the ID - first built will always be first in the list
2011-01-04 06:48:00 -08:00
std : : sort ( apsObjectList . begin ( ) , apsObjectList . end ( ) , sortObjectByIdFunction ) ; // Why sort this list, instead of reversing it?
}
static inline bool sortFactoryByTypeFunction ( BASE_OBJECT * a , BASE_OBJECT * b )
{
if ( a = = NULL | | b = = NULL )
2006-12-02 04:50:28 -08:00
{
2011-01-04 06:48:00 -08:00
return ( a = = NULL ) < ( b = = NULL ) ;
2006-12-02 04:50:28 -08:00
}
2011-01-04 06:48:00 -08:00
STRUCTURE * s = castStructure ( a ) , * t = castStructure ( b ) ;
ASSERT ( s ! = NULL & & StructIsFactory ( s ) & & t ! = NULL & & StructIsFactory ( t ) , " object is not a factory " ) ;
FACTORY * x = ( FACTORY * ) s - > pFunctionality , * y = ( FACTORY * ) t - > pFunctionality ;
if ( x - > psAssemblyPoint - > factoryType ! = y - > psAssemblyPoint - > factoryType )
{
return x - > psAssemblyPoint - > factoryType < y - > psAssemblyPoint - > factoryType ;
}
return x - > psAssemblyPoint - > factoryInc < y - > psAssemblyPoint - > factoryInc ;
2006-12-02 04:50:28 -08:00
}
/*puts the selected players factories in order - Standard factories 1-5, then
cyborg factories 1 - 5 and then Vtol factories 1 - 5 */
static void orderFactories ( void )
{
2011-01-04 06:48:00 -08:00
std : : sort ( apsObjectList . begin ( ) , apsObjectList . end ( ) , sortFactoryByTypeFunction ) ;
2006-12-02 04:50:28 -08:00
}
2008-05-04 13:58:20 -07:00
/** Order the objects in the bottom bar according to their type. */
2006-12-02 04:50:28 -08:00
static void orderObjectInterface ( void )
{
2011-01-04 06:48:00 -08:00
if ( apsObjectList . empty ( ) )
2006-12-02 04:50:28 -08:00
{
//no objects so nothing to order!
return ;
}
2012-12-21 07:35:35 -08:00
switch ( apsObjectList [ 0 ] - > type )
2006-12-02 04:50:28 -08:00
{
case OBJ_STRUCTURE :
2008-05-04 13:58:20 -07:00
if ( StructIsFactory ( ( STRUCTURE * ) apsObjectList [ 0 ] ) )
2006-12-02 04:50:28 -08:00
{
orderFactories ( ) ;
}
2008-05-04 13:58:20 -07:00
else if ( ( ( STRUCTURE * ) apsObjectList [ 0 ] ) - > pStructureType - > type = = REF_RESEARCH )
{
orderResearch ( ) ;
}
2006-12-02 04:50:28 -08:00
break ;
case OBJ_DROID :
orderDroids ( ) ;
default :
//nothing to do as yet!
break ;
}
}
2011-01-04 06:48:00 -08:00
// Rebuilds apsObjectList, and returns the index of psBuilding in apsObjectList, or returns apsObjectList.size() if not present (not sure whether that's supposed to be possible).
static unsigned rebuildFactoryListAndFindIndex ( STRUCTURE * psBuilding )
{
apsObjectList . clear ( ) ;
for ( STRUCTURE * psCurr = interfaceStructList ( ) ; psCurr ; psCurr = psCurr - > psNext )
{
if ( objSelectFunc ( psCurr ) )
{
// The list is ordered now so we have to get all possible entries and sort it before checking if this is the one!
apsObjectList . push_back ( psCurr ) ;
}
}
// order the list
orderFactories ( ) ;
// now look thru the list to see which one corresponds to the factory that has just finished
return std : : find ( apsObjectList . begin ( ) , apsObjectList . end ( ) , psBuilding ) - apsObjectList . begin ( ) ;
}
2006-12-02 04:50:28 -08:00
2007-06-28 10:47:08 -07:00
/* Tell the interface a factory has completed building ALL droids */
void intManufactureFinished ( STRUCTURE * psBuilding )
{
2008-05-04 14:31:44 -07:00
ASSERT ( psBuilding ! = NULL , " Invalid structure pointer " ) ;
2007-06-28 10:47:08 -07:00
2008-05-04 14:31:44 -07:00
if ( ( intMode = = INT_OBJECT | | intMode = = INT_STAT ) & & objMode = = IOBJ_MANUFACTURE )
2007-06-28 10:47:08 -07:00
{
/* Find which button the structure is on and clear it's stats */
2011-01-04 06:48:00 -08:00
unsigned structureIndex = rebuildFactoryListAndFindIndex ( psBuilding ) ;
if ( structureIndex ! = apsObjectList . size ( ) )
2010-12-05 14:20:09 -08:00
{
2011-01-04 06:48:00 -08:00
intSetStats ( structureIndex + IDOBJ_STATSTART , NULL ) ;
// clear the loop button if interface is up
if ( widgGetFromID ( psWScreen , IDSTAT_LOOP_BUTTON ) )
2007-06-28 10:47:08 -07:00
{
2011-01-04 06:48:00 -08:00
widgSetButtonState ( psWScreen , IDSTAT_LOOP_BUTTON , 0 ) ;
2007-06-28 10:47:08 -07:00
}
}
}
}
2010-12-07 12:58:37 -08:00
void intUpdateManufacture ( STRUCTURE * psBuilding )
{
ASSERT ( psBuilding ! = NULL , " Invalid structure pointer " ) ;
if ( ( intMode = = INT_OBJECT | | intMode = = INT_STAT ) & & objMode = = IOBJ_MANUFACTURE )
{
/* Find which button the structure is on and update its stats */
2011-01-04 06:48:00 -08:00
unsigned structureIndex = rebuildFactoryListAndFindIndex ( psBuilding ) ;
if ( structureIndex ! = apsObjectList . size ( ) )
2010-12-07 12:58:37 -08:00
{
2011-01-04 06:48:00 -08:00
intSetStats ( structureIndex + IDOBJ_STATSTART , psBuilding - > pFunctionality - > factory . psSubject ) ;
2010-12-07 12:58:37 -08:00
}
}
}
2007-06-28 10:47:08 -07:00
/* Tell the interface a research facility has completed a topic */
void intResearchFinished ( STRUCTURE * psBuilding )
{
2009-03-29 13:48:31 -07:00
ASSERT ( psBuilding ! = NULL , " Invalid structure pointer " ) ;
2007-06-28 10:47:08 -07:00
// just do a screen refresh
intRefreshScreen ( ) ;
}
2011-02-28 14:33:57 -08:00
void intAlliedResearchChanged ( )
{
if ( ( intMode = = INT_OBJECT | | intMode = = INT_STAT ) & & objMode = = IOBJ_RESEARCH )
{
intRefreshScreen ( ) ;
}
}
2007-06-28 10:47:08 -07:00
/* Add the reticule widgets to the widget screen */
2012-12-27 14:34:15 -08:00
bool intAddReticule ( )
2007-06-28 10:47:08 -07:00
{
2012-12-27 14:34:15 -08:00
if ( ReticuleUp )
2010-12-22 06:02:14 -08:00
{
2012-12-27 14:34:15 -08:00
return true ; // all fine
2007-06-28 10:47:08 -07:00
}
2013-02-27 23:29:08 -08:00
WIDGET * parent = psWScreen - > psForm ;
IntFormAnimated * retForm = new IntFormAnimated ( parent , false ) ;
retForm - > id = IDRET_FORM ;
retForm - > setGeometry ( RET_X , RET_Y , RET_FORMWIDTH , RET_FORMHEIGHT ) ;
2013-08-02 12:05:32 -07:00
for ( int i = 0 ; i < NUMRETBUTS ; i + + )
{
setReticuleBut ( i ) ;
}
2012-12-27 14:34:15 -08:00
ReticuleUp = true ;
2008-03-24 09:51:17 -07:00
return true ;
2007-06-28 10:47:08 -07:00
}
void intRemoveReticule ( void )
{
2010-01-11 08:19:39 -08:00
if ( ReticuleUp = = true )
{
widgDelete ( psWScreen , IDRET_FORM ) ; // remove reticule
2008-03-24 09:51:17 -07:00
ReticuleUp = false ;
2007-06-28 10:47:08 -07:00
}
}
//toggles the Power Bar display on and off
void togglePowerBar ( void )
{
//toggle the flag
powerBarUp = ! powerBarUp ;
if ( powerBarUp )
{
intShowPowerBar ( ) ;
}
else
{
intHidePowerBar ( ) ;
}
}
/* Add the power bars to the screen */
2013-08-02 12:05:32 -07:00
bool intAddPower ( )
2007-06-28 10:47:08 -07:00
{
2010-12-22 06:02:14 -08:00
W_BARINIT sBarInit ;
2007-06-28 10:47:08 -07:00
/* Add the trough bar */
sBarInit . formID = 0 ; //IDPOW_FORM;
sBarInit . id = IDPOW_POWERBAR_T ;
//start the power bar off in view (default)
sBarInit . style = WBAR_TROUGH ;
sBarInit . x = ( SWORD ) POW_X ;
sBarInit . y = ( SWORD ) POW_Y ;
sBarInit . width = POW_BARWIDTH ;
2012-12-21 07:35:35 -08:00
sBarInit . height = iV_GetImageHeight ( IntImages , IMAGE_PBAR_EMPTY ) ;
2010-04-04 04:46:51 -07:00
sBarInit . sCol = WZCOL_POWER_BAR ;
2007-06-28 10:47:08 -07:00
sBarInit . pDisplay = intDisplayPowerBar ;
sBarInit . iRange = POWERBAR_SCALE ;
2007-04-01 13:15:46 -07:00
sBarInit . pTip = _ ( " Power " ) ;
2007-06-28 10:47:08 -07:00
if ( ! widgAddBarGraph ( psWScreen , & sBarInit ) )
{
2008-03-24 09:51:17 -07:00
return false ;
2007-06-28 10:47:08 -07:00
}
2008-03-24 09:51:17 -07:00
powerBarUp = true ;
return true ;
2007-06-28 10:47:08 -07:00
}
/* Add the options widgets to the widget screen */
2011-03-12 17:32:15 -08:00
bool intAddOptions ( void )
2007-06-28 10:47:08 -07:00
{
W_FORMINIT sFormInit ;
W_EDBINIT sEdInit ;
W_BUTINIT sButInit ;
W_LABINIT sLabInit ;
UDWORD player ;
/* Add the option form */
sFormInit . formID = 0 ;
sFormInit . id = IDOPT_FORM ;
sFormInit . style = WFORM_PLAIN ;
sFormInit . x = OPT_X ;
sFormInit . y = OPT_Y ;
sFormInit . width = OPT_WIDTH ;
sFormInit . height = OPT_HEIGHT ;
if ( ! widgAddForm ( psWScreen , & sFormInit ) )
{
2008-03-24 09:51:17 -07:00
return false ;
2007-06-28 10:47:08 -07:00
}
// set the interface mode
intMode = INT_OPTION ;
/* Add the Option screen label */
sLabInit . formID = IDOPT_FORM ;
sLabInit . id = IDOPT_LABEL ;
sLabInit . x = OPT_GAP ;
sLabInit . y = OPT_GAP ;
sLabInit . width = OPT_BUTWIDTH ;
sLabInit . height = OPT_BUTHEIGHT ;
2010-08-25 07:37:44 -07:00
sLabInit . pText = _ ( " Options " ) ;
2007-06-28 10:47:08 -07:00
if ( ! widgAddLabel ( psWScreen , & sLabInit ) )
{
2008-03-24 09:51:17 -07:00
return false ;
2007-06-28 10:47:08 -07:00
}
/* Add the close box */
sButInit . formID = IDOPT_FORM ;
sButInit . id = IDOPT_CLOSE ;
sButInit . x = OPT_WIDTH - OPT_GAP - CLOSE_SIZE ;
sButInit . y = OPT_GAP ;
sButInit . width = CLOSE_SIZE ;
sButInit . height = CLOSE_SIZE ;
sButInit . pText = pCloseText ;
2007-04-01 13:15:46 -07:00
sButInit . pTip = _ ( " Close " ) ;
2007-06-28 10:47:08 -07:00
if ( ! widgAddButton ( psWScreen , & sButInit ) )
{
2008-03-24 09:51:17 -07:00
return false ;
2007-06-28 10:47:08 -07:00
}
2012-12-21 06:01:30 -08:00
/* Add the add object buttons */
sButInit . id = IDOPT_DROID ;
2007-06-24 14:58:42 -07:00
sButInit . width = OPT_BUTWIDTH ;
sButInit . height = OPT_BUTHEIGHT ;
2008-04-05 16:09:55 -07:00
sButInit . x = OPT_GAP ;
sButInit . y = OPT_EDITY ;
2007-09-25 13:21:18 -07:00
sButInit . pText = _ ( " Unit " ) ;
2008-03-16 16:53:36 -07:00
sButInit . pTip = _ ( " Place Unit on map " ) ;
2007-06-28 10:47:08 -07:00
if ( ! widgAddButton ( psWScreen , & sButInit ) )
{
2008-03-24 09:51:17 -07:00
return false ;
2007-06-28 10:47:08 -07:00
}
sButInit . id = IDOPT_STRUCT ;
sButInit . x + = OPT_GAP + OPT_BUTWIDTH ;
2007-09-25 13:21:18 -07:00
sButInit . pText = _ ( " Struct " ) ;
2008-03-16 16:53:36 -07:00
sButInit . pTip = _ ( " Place Structures on map " ) ;
2007-06-28 10:47:08 -07:00
if ( ! widgAddButton ( psWScreen , & sButInit ) )
{
2008-03-24 09:51:17 -07:00
return false ;
2007-06-28 10:47:08 -07:00
}
sButInit . id = IDOPT_FEATURE ;
sButInit . x + = OPT_GAP + OPT_BUTWIDTH ;
2007-09-25 13:21:18 -07:00
sButInit . pText = _ ( " Feat " ) ;
2008-03-16 16:53:36 -07:00
sButInit . pTip = _ ( " Place Features on map " ) ;
2007-06-28 10:47:08 -07:00
if ( ! widgAddButton ( psWScreen , & sButInit ) )
{
2008-03-24 09:51:17 -07:00
return false ;
2007-06-28 10:47:08 -07:00
}
2012-02-19 23:07:13 -08:00
if ( NetPlay . bComms )
{
widgSetButtonState ( psWScreen , sButInit . id , WBUT_DISABLE ) ;
}
2007-06-28 10:47:08 -07:00
/* Add the quit button */
sButInit . formID = IDOPT_FORM ;
sButInit . id = IDOPT_QUIT ;
sButInit . x = OPT_GAP ;
sButInit . y = OPT_HEIGHT - OPT_GAP - OPT_BUTHEIGHT ;
2012-12-21 07:35:35 -08:00
sButInit . width = OPT_WIDTH - OPT_GAP * 2 ;
2007-06-28 10:47:08 -07:00
sButInit . height = OPT_BUTHEIGHT ;
2007-09-25 13:21:18 -07:00
sButInit . pText = _ ( " Quit " ) ;
2007-04-01 13:15:46 -07:00
sButInit . pTip = _ ( " Exit Game " ) ;
2011-01-03 05:48:41 -08:00
int quitButtonY = sButInit . y - OPT_GAP ;
2007-06-28 10:47:08 -07:00
if ( ! widgAddButton ( psWScreen , & sButInit ) )
{
2008-03-24 09:51:17 -07:00
return false ;
2007-06-28 10:47:08 -07:00
}
/* Add the player form */
sFormInit . formID = IDOPT_FORM ;
sFormInit . id = IDOPT_PLAYERFORM ;
sFormInit . style = WFORM_PLAIN ;
sFormInit . x = OPT_GAP ;
sFormInit . y = OPT_PLAYERY ;
2012-12-21 07:35:35 -08:00
sFormInit . width = OPT_WIDTH - OPT_GAP * 2 ;
sFormInit . height = ( OPT_BUTHEIGHT + OPT_GAP ) * ( 1 + ( MAX_PLAYERS + 3 ) / 4 ) + OPT_GAP ;
2011-01-03 05:48:41 -08:00
int nextFormY = sFormInit . y + sFormInit . height + OPT_GAP ;
2007-06-28 10:47:08 -07:00
if ( ! widgAddForm ( psWScreen , & sFormInit ) )
{
2008-03-24 09:51:17 -07:00
return false ;
2007-06-28 10:47:08 -07:00
}
/* Add the player label */
sLabInit . formID = IDOPT_PLAYERFORM ;
sLabInit . id = IDOPT_PLAYERLABEL ;
sLabInit . x = OPT_GAP ;
sLabInit . y = OPT_GAP ;
2010-08-25 07:37:44 -07:00
sLabInit . pText = _ ( " Current Player: " ) ;
2007-06-28 10:47:08 -07:00
if ( ! widgAddLabel ( psWScreen , & sLabInit ) )
{
2008-03-24 09:51:17 -07:00
return false ;
2007-06-28 10:47:08 -07:00
}
/* Add the player buttons */
sButInit . formID = IDOPT_PLAYERFORM ;
sButInit . id = IDOPT_PLAYERSTART ;
sButInit . x = OPT_GAP ;
2012-12-21 07:35:35 -08:00
sButInit . y = OPT_BUTHEIGHT + OPT_GAP * 2 ;
2007-06-28 10:47:08 -07:00
sButInit . width = OPT_BUTWIDTH ;
sButInit . height = OPT_BUTHEIGHT ;
2012-12-21 07:35:35 -08:00
for ( player = 0 ; player < MAX_PLAYERS ; player + + )
2007-06-28 10:47:08 -07:00
{
2011-01-03 05:48:41 -08:00
STATIC_ASSERT ( MAX_PLAYERS < = ARRAY_SIZE ( apPlayerText ) & & MAX_PLAYERS < = ARRAY_SIZE ( apPlayerTip ) ) ;
2007-06-28 10:47:08 -07:00
sButInit . pText = apPlayerText [ player ] ;
sButInit . pTip = apPlayerTip [ player ] ;
if ( ! widgAddButton ( psWScreen , & sButInit ) )
{
2008-03-24 09:51:17 -07:00
return false ;
2007-06-28 10:47:08 -07:00
}
2012-02-19 23:07:13 -08:00
if ( NetPlay . bComms )
{
widgSetButtonState ( psWScreen , sButInit . id , WBUT_DISABLE ) ;
}
2007-06-28 10:47:08 -07:00
/* Update the initialisation structure for the next button */
sButInit . id + = 1 ;
2012-12-21 07:35:35 -08:00
sButInit . x + = OPT_BUTWIDTH + OPT_GAP ;
if ( sButInit . x + OPT_BUTWIDTH + OPT_GAP > OPT_WIDTH - OPT_GAP * 2 )
2007-06-28 10:47:08 -07:00
{
sButInit . x = OPT_GAP ;
sButInit . y + = OPT_BUTHEIGHT + OPT_GAP ;
}
}
2010-03-06 15:06:35 -08:00
/* Add iViS form */
sFormInit . formID = IDOPT_FORM ;
sFormInit . id = IDOPT_IVISFORM ;
sFormInit . style = WFORM_PLAIN ;
sFormInit . x = OPT_GAP ;
2011-01-03 05:48:41 -08:00
sFormInit . y = nextFormY ; //OPT_PLAYERY + OPT_BUTHEIGHT * 3 + OPT_GAP * 5;
2010-03-06 15:06:35 -08:00
sFormInit . width = OPT_WIDTH - OPT_GAP * 2 ;
2011-01-03 05:48:41 -08:00
sFormInit . height = quitButtonY - nextFormY ; //OPT_BUTHEIGHT * 3 + OPT_GAP * 4;
2010-03-06 15:06:35 -08:00
if ( ! widgAddForm ( psWScreen , & sFormInit ) )
{
return false ;
}
2007-06-28 10:47:08 -07:00
widgSetButtonState ( psWScreen , IDOPT_PLAYERSTART + selectedPlayer , WBUT_LOCK ) ;
2008-03-24 09:51:17 -07:00
return true ;
2007-06-28 10:47:08 -07:00
}
/* Add the object screen widgets to the widget screen.
* select is a pointer to a function that returns true when the object is
* to be added to the screen .
* getStats is a pointer to a function that returns the appropriate stats
* for the object .
* If psSelected ! = NULL it specifies which object should be hilited .
*/
2012-12-21 07:35:35 -08:00
static bool intAddObjectWindow ( BASE_OBJECT * psObjects , BASE_OBJECT * psSelected , bool bForceStats )
2007-06-28 10:47:08 -07:00
{
2011-01-04 06:48:00 -08:00
UDWORD statID = 0 ;
2012-12-21 07:35:35 -08:00
BASE_OBJECT * psFirst ;
2007-06-28 10:47:08 -07:00
BASE_STATS * psStats ;
DROID * Droid ;
STRUCTURE * Structure ;
2010-06-27 12:12:18 -07:00
int compIndex ;
2007-06-28 10:47:08 -07:00
2008-05-04 14:31:44 -07:00
// Is the form already up?
2012-12-21 07:35:35 -08:00
if ( widgGetFromID ( psWScreen , IDOBJ_FORM ) ! = NULL )
{
2007-06-28 10:47:08 -07:00
intRemoveObjectNoAnim ( ) ;
}
else
{
// reset the object position array
2011-01-04 06:48:00 -08:00
asJumpPos . clear ( ) ;
2007-06-28 10:47:08 -07:00
}
/* See how many objects the player has */
2011-01-04 06:48:00 -08:00
apsObjectList . clear ( ) ;
for ( BASE_OBJECT * psObj = psObjects ; psObj ; psObj = psObj - > psNext )
2007-06-28 10:47:08 -07:00
{
if ( objSelectFunc ( psObj ) )
{
2011-01-04 06:48:00 -08:00
apsObjectList . push_back ( psObj ) ;
2007-06-28 10:47:08 -07:00
}
}
2011-01-04 06:48:00 -08:00
if ( apsObjectList . empty ( ) )
{
2007-06-28 10:47:08 -07:00
// No objects so close the stats window if it's up...
2012-12-21 07:35:35 -08:00
if ( widgGetFromID ( psWScreen , IDSTAT_FORM ) ! = NULL )
{
2007-06-28 10:47:08 -07:00
intRemoveStatsNoAnim ( ) ;
}
// and return.
2008-03-24 09:51:17 -07:00
return false ;
2007-06-28 10:47:08 -07:00
}
2011-01-04 06:48:00 -08:00
psFirst = apsObjectList . front ( ) ;
2007-06-28 10:47:08 -07:00
2012-12-21 07:35:35 -08:00
/*if psSelected != NULL then check its in the list of suitable objects for
this instance of the interface - this could happen when a structure is upgraded */
//if have reached the end of the loop and not quit out, then can't have found the selected object in the list
2011-01-04 06:48:00 -08:00
if ( std : : find ( apsObjectList . begin ( ) , apsObjectList . end ( ) , psSelected ) = = apsObjectList . end ( ) )
{
//initialise psSelected so gets set up with an iten in the list
psSelected = NULL ;
}
2007-06-28 10:47:08 -07:00
//order the objects according to what they are
orderObjectInterface ( ) ;
// set the selected object if necessary
if ( psSelected = = NULL )
{
//first check if there is an object selected of the required type
switch ( objMode )
{
case IOBJ_RESEARCH :
psSelected = ( BASE_OBJECT * ) intCheckForStructure ( REF_RESEARCH ) ;
break ;
case IOBJ_MANUFACTURE :
psSelected = ( BASE_OBJECT * ) intCheckForStructure ( REF_FACTORY ) ;
//if haven't got a Factory, check for specific types of factory
if ( ! psSelected )
{
psSelected = ( BASE_OBJECT * ) intCheckForStructure ( REF_CYBORG_FACTORY ) ;
}
if ( ! psSelected )
{
psSelected = ( BASE_OBJECT * ) intCheckForStructure ( REF_VTOL_FACTORY ) ;
}
break ;
case IOBJ_BUILD :
psSelected = ( BASE_OBJECT * ) intCheckForDroid ( DROID_CONSTRUCT ) ;
2012-12-21 06:01:30 -08:00
if ( ! psSelected )
{
psSelected = ( BASE_OBJECT * ) intCheckForDroid ( DROID_CYBORG_CONSTRUCT ) ;
}
2007-06-28 10:47:08 -07:00
break ;
case IOBJ_COMMAND :
psSelected = ( BASE_OBJECT * ) intCheckForDroid ( DROID_COMMAND ) ;
break ;
default :
break ;
}
if ( ! psSelected )
{
2008-04-22 16:49:08 -07:00
if ( apsPreviousObj [ objMode ]
2012-12-21 07:35:35 -08:00
& & apsPreviousObj [ objMode ] - > player = = selectedPlayer )
2007-06-28 10:47:08 -07:00
{
psSelected = apsPreviousObj [ objMode ] ;
//it is possible for a structure to change status - building of modules
2008-04-22 16:49:08 -07:00
if ( psSelected - > type = = OBJ_STRUCTURE
2012-12-21 07:35:35 -08:00
& & ( ( STRUCTURE * ) psSelected ) - > status ! = SS_BUILT )
2007-06-28 10:47:08 -07:00
{
2008-04-22 16:49:08 -07:00
//structure not complete so just set selected to the first valid object
psSelected = psFirst ;
2007-06-28 10:47:08 -07:00
}
}
else
{
psSelected = psFirst ;
}
}
}
/* Reset the current object and store the current list */
psObjSelected = NULL ;
2013-02-27 23:29:08 -08:00
WIDGET * parent = psWScreen - > psForm ;
2007-06-28 10:47:08 -07:00
2013-02-27 23:29:08 -08:00
/* Create the basic form */
IntFormAnimated * objForm = new IntFormAnimated ( parent , false ) ;
objForm - > id = IDOBJ_FORM ;
objForm - > setGeometry ( OBJ_BACKX , OBJ_BACKY , OBJ_BACKWIDTH , OBJ_BACKHEIGHT ) ;
2007-06-28 10:47:08 -07:00
/* Add the close button */
2010-12-22 06:02:14 -08:00
W_BUTINIT sButInit ;
2007-06-28 10:47:08 -07:00
sButInit . formID = IDOBJ_FORM ;
sButInit . id = IDOBJ_CLOSE ;
sButInit . x = OBJ_BACKWIDTH - CLOSE_WIDTH ;
sButInit . y = 0 ;
sButInit . width = CLOSE_WIDTH ;
sButInit . height = CLOSE_HEIGHT ;
2007-04-01 13:15:46 -07:00
sButInit . pTip = _ ( " Close " ) ;
2007-06-28 10:47:08 -07:00
sButInit . pDisplay = intDisplayImageHilight ;
2012-12-21 07:35:35 -08:00
sButInit . UserData = PACKDWORD_TRI ( 0 , IMAGE_CLOSEHILIGHT , IMAGE_CLOSE ) ;
2007-06-28 10:47:08 -07:00
if ( ! widgAddButton ( psWScreen , & sButInit ) )
{
2008-03-24 09:51:17 -07:00
return false ;
2007-06-28 10:47:08 -07:00
}
/*add the tabbed form */
2013-03-09 09:52:28 -08:00
IntListTabWidget * objList = new IntListTabWidget ( objForm ) ;
objList - > id = IDOBJ_TABFORM ;
objList - > setChildSize ( OBJ_BUTWIDTH , OBJ_BUTHEIGHT * 2 ) ;
objList - > setChildSpacing ( OBJ_GAP , OBJ_GAP ) ;
int objListWidth = OBJ_BUTWIDTH * 5 + STAT_GAP * 4 ;
objList - > setGeometry ( ( OBJ_BACKWIDTH - objListWidth ) / 2 , OBJ_TABY , objListWidth , OBJ_BACKHEIGHT - OBJ_TABY ) ;
2007-06-28 10:47:08 -07:00
/* Add the object and stats buttons */
2013-03-09 09:52:28 -08:00
int nextObjButtonId = IDOBJ_OBJSTART ;
int nextStatButtonId = IDOBJ_STATSTART ;
2007-06-28 10:47:08 -07:00
2010-12-17 11:06:53 -08:00
// Action progress bar.
2010-12-22 06:02:14 -08:00
W_BARINIT sBarInit ;
2007-06-28 10:47:08 -07:00
sBarInit . formID = IDOBJ_OBJSTART ;
sBarInit . id = IDOBJ_PROGBARSTART ;
sBarInit . style = WBAR_TROUGH | WIDG_HIDDEN ;
sBarInit . x = STAT_PROGBARX ;
sBarInit . y = STAT_PROGBARY ;
sBarInit . width = STAT_PROGBARWIDTH ;
sBarInit . height = STAT_PROGBARHEIGHT ;
sBarInit . size = 0 ;
2010-04-04 04:46:51 -07:00
sBarInit . sCol = WZCOL_ACTION_PROGRESS_BAR_MAJOR ;
sBarInit . sMinorCol = WZCOL_ACTION_PROGRESS_BAR_MINOR ;
2007-04-01 13:15:46 -07:00
sBarInit . pTip = _ ( " Progress Bar " ) ;
2007-06-28 10:47:08 -07:00
2010-12-17 11:06:53 -08:00
// object output bar ie manuf power o/p, research power o/p
2010-12-22 06:02:14 -08:00
W_BARINIT sBarInit2 = sBarInit ;
2007-06-28 10:47:08 -07:00
sBarInit2 . id = IDOBJ_POWERBARSTART ;
sBarInit2 . style = WBAR_PLAIN ;
sBarInit2 . x = STAT_POWERBARX ;
sBarInit2 . y = STAT_POWERBARY ;
sBarInit2 . size = 50 ;
2010-12-22 06:02:14 -08:00
W_LABINIT sLabInit ;
2007-06-28 10:47:08 -07:00
sLabInit . id = IDOBJ_COUNTSTART ;
2010-12-22 06:02:14 -08:00
sLabInit . style = WIDG_HIDDEN ;
2007-06-28 10:47:08 -07:00
sLabInit . x = OBJ_TEXTX ;
sLabInit . y = OBJ_T1TEXTY ;
sLabInit . width = 16 ;
sLabInit . height = 16 ;
2010-07-20 13:57:19 -07:00
sLabInit . pText = " BUG! (a) " ;
2007-06-28 10:47:08 -07:00
2010-12-22 06:02:14 -08:00
W_LABINIT sLabInitCmdFac ;
2007-06-28 10:47:08 -07:00
sLabInitCmdFac . id = IDOBJ_CMDFACSTART ;
2010-12-22 06:02:14 -08:00
sLabInitCmdFac . style = WIDG_HIDDEN ;
2007-06-28 10:47:08 -07:00
sLabInitCmdFac . x = OBJ_TEXTX ;
sLabInitCmdFac . y = OBJ_T2TEXTY ;
sLabInitCmdFac . width = 16 ;
sLabInitCmdFac . height = 16 ;
2010-07-20 13:57:19 -07:00
sLabInitCmdFac . pText = " BUG! (b) " ;
2007-06-28 10:47:08 -07:00
2010-12-22 06:02:14 -08:00
W_LABINIT sLabInitCmdFac2 ;
2007-06-28 10:47:08 -07:00
sLabInitCmdFac2 . id = IDOBJ_CMDVTOLFACSTART ;
2010-12-22 06:02:14 -08:00
sLabInitCmdFac2 . style = WIDG_HIDDEN ;
2007-06-28 10:47:08 -07:00
sLabInitCmdFac2 . x = OBJ_TEXTX ;
sLabInitCmdFac2 . y = OBJ_T3TEXTY ;
sLabInitCmdFac2 . width = 16 ;
sLabInitCmdFac2 . height = 16 ;
2010-07-20 13:57:19 -07:00
sLabInitCmdFac2 . pText = " BUG! (c) " ;
2007-06-28 10:47:08 -07:00
2010-12-22 06:02:14 -08:00
W_LABINIT sLabIntObjText ;
2007-06-28 10:47:08 -07:00
sLabIntObjText . id = IDOBJ_FACTORYSTART ;
2010-12-22 06:02:14 -08:00
sLabIntObjText . style = WIDG_HIDDEN ;
2007-06-28 10:47:08 -07:00
sLabIntObjText . x = OBJ_TEXTX ;
sLabIntObjText . y = OBJ_B1TEXTY ;
sLabIntObjText . width = 16 ;
sLabIntObjText . height = 16 ;
sLabIntObjText . pText = " xxx/xxx - overrun " ;
2010-12-22 06:02:14 -08:00
W_LABINIT sLabInitCmdExp ;
2007-06-28 10:47:08 -07:00
sLabInitCmdExp . id = IDOBJ_CMDEXPSTART ;
2010-12-22 06:02:14 -08:00
sLabInitCmdExp . style = WIDG_HIDDEN ;
2007-06-28 10:47:08 -07:00
sLabInitCmdExp . x = STAT_POWERBARX ;
sLabInitCmdExp . y = STAT_POWERBARY ;
sLabInitCmdExp . width = 16 ;
sLabInitCmdExp . height = 16 ;
sLabInitCmdExp . pText = " @@@@@ - overrun " ;
2013-01-21 11:43:02 -08:00
W_LABINIT sAllyResearch ;
sAllyResearch . id = IDOBJ_ALLYRESEARCHSTART ;
sAllyResearch . width = iV_GetImageWidth ( IntImages , IMAGE_ALLY_RESEARCH ) ;
sAllyResearch . height = iV_GetImageHeight ( IntImages , IMAGE_ALLY_RESEARCH ) ;
sAllyResearch . y = 10 ;
sAllyResearch . pDisplay = intDisplayAllyIcon ;
2011-01-04 06:48:00 -08:00
for ( unsigned i = 0 ; i < apsObjectList . size ( ) ; + + i )
2007-06-28 10:47:08 -07:00
{
2011-01-04 06:48:00 -08:00
BASE_OBJECT * psObj = apsObjectList [ i ] ;
2012-12-21 07:35:35 -08:00
if ( psObj - > died ! = 0 )
2012-12-21 07:32:23 -08:00
{
continue ; // Don't add the button if the objects dead.
}
2013-01-29 07:22:16 -08:00
bool IsFactory = false ;
bool isResearch = false ;
2007-06-28 10:47:08 -07:00
2013-03-09 09:52:28 -08:00
WIDGET * buttonHolder = new WIDGET ( objList ) ;
objList - > addWidgetToLayout ( buttonHolder ) ;
2007-06-28 10:47:08 -07:00
2013-03-13 00:57:13 -07:00
IntStatusButton * statButton = new IntStatusButton ( buttonHolder ) ;
2013-03-09 09:52:28 -08:00
statButton - > id = nextStatButtonId ;
statButton - > setGeometry ( 0 , 0 , OBJ_BUTWIDTH , OBJ_BUTHEIGHT ) ;
statButton - > style | = WFORM_SECONDARY ;
2007-06-28 10:47:08 -07:00
2013-03-13 00:57:13 -07:00
IntObjectButton * objButton = new IntObjectButton ( buttonHolder ) ;
2013-03-09 09:52:28 -08:00
objButton - > id = nextObjButtonId ;
2013-03-13 00:57:13 -07:00
objButton - > setObject ( psObj ) ;
2013-03-09 09:52:28 -08:00
objButton - > setGeometry ( 0 , OBJ_STARTY , OBJ_BUTWIDTH , OBJ_BUTHEIGHT ) ;
2007-06-28 10:47:08 -07:00
2012-12-21 07:35:35 -08:00
/* Got an object - set the text and tip for the button */
switch ( psObj - > type )
{
case OBJ_DROID :
// Get the construction power of a construction droid.. Not convinced this is right.
Droid = ( DROID * ) psObj ;
if ( Droid - > droidType = = DROID_CONSTRUCT | | Droid - > droidType = = DROID_CYBORG_CONSTRUCT )
2007-06-28 10:47:08 -07:00
{
2013-05-09 04:24:19 -07:00
compIndex = Droid - > asBits [ COMP_CONSTRUCT ] ;
ASSERT_OR_RETURN ( false , Droid - > asBits [ COMP_CONSTRUCT ] , " Invalid droid type " ) ;
2012-12-21 07:35:35 -08:00
ASSERT_OR_RETURN ( false , compIndex < numConstructStats , " Invalid range referenced for numConstructStats, %d > %d " , compIndex , numConstructStats ) ;
psStats = ( BASE_STATS * ) ( asConstructStats + compIndex ) ;
sBarInit2 . size = ( UWORD ) constructorPoints ( ( CONSTRUCT_STATS * ) psStats , Droid - > player ) ;
if ( sBarInit2 . size > WBAR_SCALE )
2007-06-28 10:47:08 -07:00
{
2012-12-21 07:35:35 -08:00
sBarInit2 . size = WBAR_SCALE ;
2007-06-28 10:47:08 -07:00
}
2012-12-21 07:35:35 -08:00
}
2013-03-09 09:52:28 -08:00
objButton - > setTip ( droidGetName ( ( DROID * ) psObj ) ) ;
2012-12-21 07:35:35 -08:00
break ;
2007-06-28 10:47:08 -07:00
2012-12-21 07:35:35 -08:00
case OBJ_STRUCTURE :
// Get the construction power of a structure
Structure = ( STRUCTURE * ) psObj ;
switch ( Structure - > pStructureType - > type )
{
case REF_FACTORY :
case REF_CYBORG_FACTORY :
case REF_VTOL_FACTORY :
2013-05-05 04:34:59 -07:00
sBarInit2 . size = getBuildingProductionPoints ( Structure ) ;
2012-12-21 07:35:35 -08:00
if ( sBarInit2 . size > WBAR_SCALE )
{
sBarInit2 . size = WBAR_SCALE ;
2007-06-28 10:47:08 -07:00
}
2012-12-21 07:35:35 -08:00
IsFactory = true ;
//right click on factory centres on DP
2013-03-09 09:52:28 -08:00
objButton - > style | = WFORM_SECONDARY ;
2007-06-28 10:47:08 -07:00
break ;
2012-12-21 07:35:35 -08:00
case REF_RESEARCH :
2013-05-05 04:34:59 -07:00
sBarInit2 . size = getBuildingResearchPoints ( Structure ) ;
2012-12-21 07:35:35 -08:00
if ( sBarInit2 . size > WBAR_SCALE )
{
sBarInit2 . size = WBAR_SCALE ;
}
2013-01-29 07:22:16 -08:00
isResearch = true ;
2007-06-28 10:47:08 -07:00
break ;
default :
2012-12-21 07:35:35 -08:00
ASSERT ( false , " intAddObject: invalid structure type " ) ;
2007-06-28 10:47:08 -07:00
}
2013-05-12 14:50:57 -07:00
objButton - > setTip ( getName ( ( ( STRUCTURE * ) psObj ) - > pStructureType ) ) ;
2012-12-21 07:35:35 -08:00
break ;
2007-06-28 10:47:08 -07:00
2012-12-21 07:35:35 -08:00
case OBJ_FEATURE :
2013-05-12 14:50:57 -07:00
objButton - > setTip ( getName ( ( ( FEATURE * ) psObj ) - > psStats ) ) ;
2012-12-21 07:35:35 -08:00
break ;
2007-06-28 10:47:08 -07:00
2012-12-21 07:35:35 -08:00
default :
2013-03-09 09:52:28 -08:00
break ;
2012-12-21 07:35:35 -08:00
}
if ( IsFactory )
{
// Add a text label for the factory Inc.
2013-03-09 09:52:28 -08:00
sLabIntObjText . formID = nextObjButtonId ;
2012-12-21 07:35:35 -08:00
sLabIntObjText . pCallback = intAddFactoryInc ;
sLabIntObjText . pUserData = psObj ;
if ( ! widgAddLabel ( psWScreen , & sLabIntObjText ) )
2007-06-28 10:47:08 -07:00
{
2012-12-21 07:35:35 -08:00
return false ;
2007-06-28 10:47:08 -07:00
}
2012-12-21 07:35:35 -08:00
sLabIntObjText . id + + ;
}
2013-01-29 07:22:16 -08:00
if ( isResearch )
{
RESEARCH * Stat = ( ( RESEARCH_FACILITY * ) ( ( STRUCTURE * ) psObj ) - > pFunctionality ) - > psSubject ;
if ( Stat ! = NULL )
2007-06-28 10:47:08 -07:00
{
2013-01-29 07:22:16 -08:00
// Show if allies are researching the same as us.
std : : vector < AllyResearch > const & researches = listAllyResearch ( Stat - > ref ) ;
unsigned numResearches = std : : min < unsigned > ( researches . size ( ) , 4 ) ; // Only display at most 4 allies, since that's what there's room for.
for ( unsigned ii = 0 ; ii < numResearches ; + + ii )
{
2013-03-09 09:52:28 -08:00
sAllyResearch . formID = nextObjButtonId ;
2013-01-29 07:22:16 -08:00
sAllyResearch . x = STAT_BUTWIDTH - ( sAllyResearch . width + 2 ) * ii - sAllyResearch . width - 2 ;
sAllyResearch . UserData = PACKDWORD ( Stat - > ref - REF_RESEARCH_START , ii ) ;
sAllyResearch . pTip = getPlayerName ( researches [ ii ] . player ) ;
widgAddLabel ( psWScreen , & sAllyResearch ) ;
ASSERT ( sAllyResearch . id < = IDOBJ_ALLYRESEARCHEND , " " ) ;
+ + sAllyResearch . id ;
}
2007-06-28 10:47:08 -07:00
}
2013-01-29 07:22:16 -08:00
}
2012-12-21 07:35:35 -08:00
// Add the power bar.
if ( psObj - > type ! = OBJ_DROID | | ( ( ( DROID * ) psObj ) - > droidType = = DROID_CONSTRUCT | | ( ( DROID * ) psObj ) - > droidType = = DROID_CYBORG_CONSTRUCT ) )
{
2013-03-09 09:52:28 -08:00
sBarInit2 . formID = nextObjButtonId ;
2012-12-21 07:35:35 -08:00
sBarInit . iRange = GAME_TICKS_PER_SEC ;
if ( ! widgAddBarGraph ( psWScreen , & sBarInit2 ) )
2007-06-28 10:47:08 -07:00
{
2012-12-21 07:35:35 -08:00
return false ;
2007-06-28 10:47:08 -07:00
}
2012-12-21 07:35:35 -08:00
}
2007-06-28 10:47:08 -07:00
2012-12-21 07:35:35 -08:00
// Add command droid bits
if ( ( psObj - > type = = OBJ_DROID ) & &
( ( ( DROID * ) psObj ) - > droidType = = DROID_COMMAND ) )
{
// the group size label
2013-03-09 09:52:28 -08:00
sLabIntObjText . formID = nextObjButtonId ;
2012-12-21 07:35:35 -08:00
sLabIntObjText . pCallback = intUpdateCommandSize ;
sLabIntObjText . pUserData = psObj ;
if ( ! widgAddLabel ( psWScreen , & sLabIntObjText ) )
2007-06-28 10:47:08 -07:00
{
2012-12-21 07:35:35 -08:00
return false ;
2007-06-28 10:47:08 -07:00
}
2012-12-21 07:35:35 -08:00
sLabIntObjText . id + + ;
2006-05-27 09:37:17 -07:00
2012-12-21 07:35:35 -08:00
// the experience stars
2013-03-09 09:52:28 -08:00
sLabInitCmdExp . formID = nextObjButtonId ;
2012-12-21 07:35:35 -08:00
sLabInitCmdExp . pCallback = intUpdateCommandExp ;
sLabInitCmdExp . pUserData = psObj ;
if ( ! widgAddLabel ( psWScreen , & sLabInitCmdExp ) )
2007-06-28 10:47:08 -07:00
{
2012-12-21 07:35:35 -08:00
return false ;
}
sLabInitCmdExp . id + + ;
}
2007-06-28 10:47:08 -07:00
2012-12-21 07:35:35 -08:00
/* Now do the stats button */
psStats = objGetStatsFunc ( psObj ) ;
2007-06-28 10:47:08 -07:00
2012-12-21 07:35:35 -08:00
if ( psStats ! = NULL )
{
2013-05-12 14:50:57 -07:00
statButton - > setTip ( getName ( psStats ) ) ;
2013-03-13 00:57:13 -07:00
statButton - > setObjectAndStats ( psObj , psStats ) ;
2012-12-21 07:35:35 -08:00
}
else if ( ( psObj - > type = = OBJ_DROID ) & & ( ( ( DROID * ) psObj ) - > droidType = = DROID_COMMAND ) )
{
2013-03-13 00:57:13 -07:00
statButton - > setObject ( psObj ) ;
2012-12-21 07:35:35 -08:00
}
else
{
2013-03-13 00:57:13 -07:00
statButton - > setObject ( nullptr ) ;
2012-12-21 07:35:35 -08:00
}
// Add command droid bits
if ( ( psObj - > type = = OBJ_DROID ) & &
( ( ( DROID * ) psObj ) - > droidType = = DROID_COMMAND ) )
{
// the assigned factories label
2013-03-09 09:52:28 -08:00
sLabInit . formID = nextStatButtonId ;
2012-12-21 07:35:35 -08:00
sLabInit . pCallback = intUpdateCommandFact ;
sLabInit . pUserData = psObj ;
// the assigned cyborg factories label
2013-03-09 09:52:28 -08:00
sLabInitCmdFac . formID = nextStatButtonId ;
2012-12-21 07:35:35 -08:00
sLabInitCmdFac . pCallback = intUpdateCommandFact ;
sLabInitCmdFac . pUserData = psObj ;
2013-02-25 15:24:53 -08:00
widgAddLabel ( psWScreen , & sLabInitCmdFac ) ;
2012-12-21 07:35:35 -08:00
// the assigned VTOL factories label
2013-03-09 09:52:28 -08:00
sLabInitCmdFac2 . formID = nextStatButtonId ;
2012-12-21 07:35:35 -08:00
sLabInitCmdFac2 . pCallback = intUpdateCommandFact ;
sLabInitCmdFac2 . pUserData = psObj ;
2013-02-25 15:24:53 -08:00
widgAddLabel ( psWScreen , & sLabInitCmdFac2 ) ;
2012-12-21 07:35:35 -08:00
}
else
{
// Add a text label for the size of the production run.
2013-03-09 09:52:28 -08:00
sLabInit . formID = nextStatButtonId ;
2012-12-21 07:35:35 -08:00
sLabInit . pCallback = intUpdateQuantity ;
sLabInit . pUserData = psObj ;
}
2013-02-25 15:24:53 -08:00
W_LABEL * label = widgAddLabel ( psWScreen , & sLabInit ) ;
2007-06-28 10:47:08 -07:00
2012-12-21 07:35:35 -08:00
// Add the progress bar.
2013-03-09 09:52:28 -08:00
sBarInit . formID = nextStatButtonId ;
2012-12-21 07:35:35 -08:00
// Setup widget update callback and object pointer so we can update the progress bar.
sBarInit . pCallback = intUpdateProgressBar ;
sBarInit . pUserData = psObj ;
sBarInit . iRange = GAME_TICKS_PER_SEC ;
2007-06-28 10:47:08 -07:00
2013-02-25 15:24:53 -08:00
W_BARGRAPH * bar = widgAddBarGraph ( psWScreen , & sBarInit ) ;
if ( psObj - > type ! = OBJ_DROID | | ( ( ( DROID * ) psObj ) - > droidType = = DROID_CONSTRUCT | | ( ( DROID * ) psObj ) - > droidType = = DROID_CYBORG_CONSTRUCT ) )
2012-12-21 07:35:35 -08:00
{
2013-02-25 15:24:53 -08:00
// Set the colour for the production run size text.
label - > setFontColour ( WZCOL_ACTION_PRODUCTION_RUN_TEXT ) ;
bar - > setBackgroundColour ( WZCOL_ACTION_PRODUCTION_RUN_BACKGROUND ) ;
2012-12-21 07:35:35 -08:00
}
2007-06-28 10:47:08 -07:00
2012-12-21 07:35:35 -08:00
/* If this matches psSelected note which form to display */
if ( psSelected = = psObj )
{
2013-03-09 09:52:28 -08:00
objList - > setCurrentPage ( objList - > pages ( ) - 1 ) ;
statID = nextStatButtonId ;
2012-12-21 07:35:35 -08:00
}
2007-06-28 10:47:08 -07:00
2012-12-21 07:35:35 -08:00
/* Set up the next button (Objects) */
2013-03-09 09:52:28 -08:00
+ + nextObjButtonId ;
ASSERT ( nextObjButtonId < IDOBJ_OBJEND , " Too many object buttons " ) ;
2007-06-28 10:47:08 -07:00
2012-12-21 07:35:35 -08:00
/* Set up the next button (Stats) */
sLabInit . id + = 1 ;
sLabInitCmdFac . id + = 1 ;
sLabInitCmdFac2 . id + = 1 ;
2007-06-28 10:47:08 -07:00
2012-12-21 07:35:35 -08:00
sBarInit . id + = 1 ;
ASSERT ( sBarInit . id < IDOBJ_PROGBAREND , " Too many progress bars " ) ;
2007-06-28 10:47:08 -07:00
2012-12-21 07:35:35 -08:00
sBarInit2 . id + = 1 ;
ASSERT ( sBarInit2 . id < IDOBJ_POWERBAREND , " Too many power bars " ) ;
2007-06-28 10:47:08 -07:00
2013-03-09 09:52:28 -08:00
+ + nextStatButtonId ;
ASSERT ( nextStatButtonId < IDOBJ_STATEND , " Too many stat buttons " ) ;
2007-06-28 10:47:08 -07:00
2013-03-09 09:52:28 -08:00
if ( nextObjButtonId > IDOBJ_OBJEND )
2012-12-21 07:35:35 -08:00
{
//can't fit any more on the screen!
debug ( LOG_WARNING , " This is just a Warning! Max buttons have been allocated " ) ;
break ;
}
2007-06-28 10:47:08 -07:00
}
// if the selected object isn't on one of the main buttons (too many objects)
// reset the selected pointer
if ( statID = = 0 )
{
psSelected = NULL ;
}
if ( psSelected & & ( objMode ! = IOBJ_COMMAND ) )
{
2012-12-21 07:35:35 -08:00
if ( bForceStats | | widgGetFromID ( psWScreen , IDSTAT_FORM ) )
2007-06-28 10:47:08 -07:00
{
objStatID = statID ;
intAddObjectStats ( psSelected , statID ) ;
intMode = INT_STAT ;
2012-12-21 07:35:35 -08:00
}
else
{
2007-06-28 10:47:08 -07:00
widgSetButtonState ( psWScreen , statID , WBUT_CLICKLOCK ) ;
intMode = INT_OBJECT ;
}
}
else if ( psSelected )
{
/* Note the object */
psObjSelected = psSelected ;
objStatID = statID ;
2010-12-05 14:20:09 -08:00
intAddOrder ( psSelected ) ;
2007-06-28 10:47:08 -07:00
widgSetButtonState ( psWScreen , statID , WBUT_CLICKLOCK ) ;
intMode = INT_CMDORDER ;
}
else
{
intMode = INT_OBJECT ;
}
if ( objMode = = IOBJ_BUILD | | objMode = = IOBJ_MANUFACTURE | | objMode = = IOBJ_RESEARCH )
{
intShowPowerBar ( ) ;
}
if ( bInTutorial )
{
2012-12-21 07:32:23 -08:00
debug ( LOG_NEVER , " Go with object open callback! " ) ;
2012-12-21 07:35:35 -08:00
eventFireCallbackTrigger ( ( TRIGGER_TYPE ) CALL_OBJECTOPEN ) ;
2007-06-28 10:47:08 -07:00
}
2008-03-24 09:51:17 -07:00
return true ;
2007-06-28 10:47:08 -07:00
}
2012-12-21 07:35:35 -08:00
static bool intUpdateObject ( BASE_OBJECT * psObjects , BASE_OBJECT * psSelected , bool bForceStats )
2007-06-28 10:47:08 -07:00
{
2012-12-21 07:35:35 -08:00
intAddObjectWindow ( psObjects , psSelected , bForceStats ) ;
2007-06-28 10:47:08 -07:00
// if the stats screen is up and..
2008-05-04 13:58:20 -07:00
if ( StatsUp )
{
if ( psStatsScreenOwner ! = NULL )
{
2007-06-28 10:47:08 -07:00
// it's owner is dead then..
2008-05-04 13:58:20 -07:00
if ( psStatsScreenOwner - > died ! = 0 )
{
2007-06-28 10:47:08 -07:00
// remove it.
intRemoveStatsNoAnim ( ) ;
}
}
}
2008-03-24 09:51:17 -07:00
return true ;
2007-06-28 10:47:08 -07:00
}
/* Remove the build widgets from the widget screen */
void intRemoveObject ( void )
{
widgDelete ( psWScreen , IDOBJ_TABFORM ) ;
widgDelete ( psWScreen , IDOBJ_CLOSE ) ;
2010-12-17 11:06:53 -08:00
// Start the window close animation.
2013-02-27 23:29:08 -08:00
IntFormAnimated * Form = ( IntFormAnimated * ) widgGetFromID ( psWScreen , IDOBJ_FORM ) ;
2012-12-21 07:35:35 -08:00
if ( Form )
{
2013-02-28 01:07:36 -08:00
Form - > closeAnimateDelete ( ) ;
2007-06-28 10:47:08 -07:00
}
intHidePowerBar ( ) ;
if ( bInTutorial )
{
2012-12-21 07:32:23 -08:00
debug ( LOG_NEVER , " Go with object close callback! " ) ;
2012-12-21 07:35:35 -08:00
eventFireCallbackTrigger ( ( TRIGGER_TYPE ) CALL_OBJECTCLOSE ) ;
2007-06-28 10:47:08 -07:00
}
}
/* Remove the build widgets from the widget screen */
static void intRemoveObjectNoAnim ( void )
{
widgDelete ( psWScreen , IDOBJ_TABFORM ) ;
widgDelete ( psWScreen , IDOBJ_CLOSE ) ;
widgDelete ( psWScreen , IDOBJ_FORM ) ;
intHidePowerBar ( ) ;
}
/* Remove the stats widgets from the widget screen */
void intRemoveStats ( void )
{
widgDelete ( psWScreen , IDSTAT_CLOSE ) ;
widgDelete ( psWScreen , IDSTAT_TABFORM ) ;
2010-12-17 11:11:01 -08:00
// Start the window close animation.
2013-02-27 23:29:08 -08:00
IntFormAnimated * Form = ( IntFormAnimated * ) widgGetFromID ( psWScreen , IDSTAT_FORM ) ;
2012-12-21 07:35:35 -08:00
if ( Form )
{
2013-02-28 01:07:36 -08:00
Form - > closeAnimateDelete ( ) ;
2007-06-28 10:47:08 -07:00
}
2008-03-24 09:51:17 -07:00
StatsUp = false ;
2007-06-28 10:47:08 -07:00
psStatsScreenOwner = NULL ;
}
/* Remove the stats widgets from the widget screen */
void intRemoveStatsNoAnim ( void )
{
widgDelete ( psWScreen , IDSTAT_CLOSE ) ;
widgDelete ( psWScreen , IDSTAT_TABFORM ) ;
widgDelete ( psWScreen , IDSTAT_FORM ) ;
2008-03-24 09:51:17 -07:00
StatsUp = false ;
2007-06-28 10:47:08 -07:00
psStatsScreenOwner = NULL ;
}
2009-04-09 02:25:46 -07:00
/**
* Get the object refered to by a button ID on the object screen . This works for object or stats buttons .
2007-06-28 10:47:08 -07:00
*/
static BASE_OBJECT * intGetObject ( UDWORD id )
{
BASE_OBJECT * psObj ;
/* If this is a stats button, find the object button linked to it */
2009-04-09 02:25:46 -07:00
if ( id > = IDOBJ_STATSTART & & id < = IDOBJ_STATEND )
2007-06-28 10:47:08 -07:00
{
id = IDOBJ_OBJSTART + id - IDOBJ_STATSTART ;
}
/* Find the object that the ID refers to */
2011-01-04 06:48:00 -08:00
ASSERT_OR_RETURN ( NULL , id - IDOBJ_OBJSTART < apsObjectList . size ( ) , " Invalid button ID %u " , id ) ;
2007-06-28 10:47:08 -07:00
psObj = apsObjectList [ id - IDOBJ_OBJSTART ] ;
return psObj ;
}
/* Reset the stats button for an object */
2006-12-02 04:50:28 -08:00
static void intSetStats ( UDWORD id , BASE_STATS * psStats )
2007-06-28 10:47:08 -07:00
{
/* Update the button on the object screen */
2013-03-13 00:57:13 -07:00
IntStatusButton * statButton = ( IntStatusButton * ) widgGetFromID ( psWScreen , id ) ;
2013-03-16 00:37:56 -07:00
if ( statButton = = nullptr )
{
return ;
}
2013-03-09 09:52:28 -08:00
statButton - > setTip ( " " ) ;
WIDGET : : Children children = statButton - > children ( ) ;
for ( WIDGET : : Children : : const_iterator i = children . begin ( ) ; i ! = children . end ( ) ; + + i )
{
delete * i ;
}
2007-06-28 10:47:08 -07:00
// Action progress bar.
2010-12-22 06:02:14 -08:00
W_BARINIT sBarInit ;
2007-06-28 10:47:08 -07:00
sBarInit . formID = id ;
sBarInit . id = ( id - IDOBJ_STATSTART ) + IDOBJ_PROGBARSTART ;
sBarInit . style = WBAR_TROUGH ;
sBarInit . x = STAT_PROGBARX ;
sBarInit . y = STAT_PROGBARY ;
sBarInit . width = STAT_PROGBARWIDTH ;
sBarInit . height = STAT_PROGBARHEIGHT ;
sBarInit . size = 0 ;
2010-04-04 04:46:51 -07:00
sBarInit . sCol = WZCOL_ACTION_PROGRESS_BAR_MAJOR ;
sBarInit . sMinorCol = WZCOL_ACTION_PROGRESS_BAR_MINOR ;
2007-06-28 10:47:08 -07:00
sBarInit . iRange = GAME_TICKS_PER_SEC ;
// Setup widget update callback and object pointer so we can update the progress bar.
sBarInit . pCallback = intUpdateProgressBar ;
2007-11-09 13:01:23 -08:00
sBarInit . pUserData = intGetObject ( id ) ;
2007-06-28 10:47:08 -07:00
2010-12-22 06:02:14 -08:00
W_LABINIT sLabInit ;
2007-06-28 10:47:08 -07:00
sLabInit . formID = id ;
sLabInit . id = ( id - IDOBJ_STATSTART ) + IDOBJ_COUNTSTART ;
2010-12-22 06:02:14 -08:00
sLabInit . style = WIDG_HIDDEN ;
2007-06-28 10:47:08 -07:00
sLabInit . x = OBJ_TEXTX ;
sLabInit . y = OBJ_T1TEXTY ;
sLabInit . width = 16 ;
sLabInit . height = 16 ;
2010-07-20 13:57:19 -07:00
sLabInit . pText = " BUG! (d) " ;
2007-06-28 10:47:08 -07:00
if ( psStats )
{
2013-05-12 14:50:57 -07:00
statButton - > setTip ( getName ( psStats ) ) ;
2013-03-13 00:57:13 -07:00
statButton - > setObjectAndStats ( intGetObject ( id ) , psStats ) ;
2007-06-28 10:47:08 -07:00
// Add a text label for the size of the production run.
sLabInit . pCallback = intUpdateQuantity ;
2007-11-09 13:01:23 -08:00
sLabInit . pUserData = sBarInit . pUserData ;
2007-06-28 10:47:08 -07:00
}
else
{
2013-03-13 00:57:13 -07:00
statButton - > setObject ( nullptr ) ;
2007-06-28 10:47:08 -07:00
/* Reset the stats screen button if necessary */
2006-11-02 12:15:08 -08:00
if ( ( INTMODE ) objMode = = INT_STAT & & statID ! = 0 )
2007-06-28 10:47:08 -07:00
{
widgSetButtonState ( psWScreen , statID , 0 ) ;
}
}
// Set the colour for the production run size text.
2013-02-25 15:24:53 -08:00
widgAddLabel ( psWScreen , & sLabInit ) - > setFontColour ( WZCOL_ACTION_PRODUCTION_RUN_TEXT ) ;
widgAddBarGraph ( psWScreen , & sBarInit ) - > setBackgroundColour ( WZCOL_ACTION_PRODUCTION_RUN_BACKGROUND ) ;
2007-06-28 10:47:08 -07:00
2013-03-09 09:52:28 -08:00
BASE_OBJECT * psObj = intGetObject ( id ) ;
2007-06-28 10:47:08 -07:00
if ( psObj & & psObj - > selected )
{
widgSetButtonState ( psWScreen , id , WBUT_CLICKLOCK ) ;
}
}
2013-05-21 11:48:17 -07:00
StateButton * makeObsoleteButton ( WIDGET * parent )
{
StateButton * obsoleteButton = new StateButton ( parent ) ;
obsoleteButton - > id = IDSTAT_OBSOLETE_BUTTON ;
obsoleteButton - > style | = WBUT_SECONDARY ;
obsoleteButton - > setState ( includeRedundantDesigns ) ;
obsoleteButton - > setImages ( false , StateButton : : Images ( Image ( IntImages , IMAGE_OBSOLETE_HIDE_UP ) , Image ( IntImages , IMAGE_OBSOLETE_HIDE_DOWN ) , Image ( IntImages , IMAGE_OBSOLETE_HIDE_HI ) ) ) ;
obsoleteButton - > setTip ( false , _ ( " Hiding Obsolete Tech " ) ) ;
obsoleteButton - > setImages ( true , StateButton : : Images ( Image ( IntImages , IMAGE_OBSOLETE_SHOW_UP ) , Image ( IntImages , IMAGE_OBSOLETE_SHOW_DOWN ) , Image ( IntImages , IMAGE_OBSOLETE_SHOW_HI ) ) ) ;
obsoleteButton - > setTip ( true , _ ( " Showing Obsolete Tech " ) ) ;
obsoleteButton - > move ( 4 + Image ( IntImages , IMAGE_FDP_UP ) . width ( ) + 4 , STAT_SLDY ) ;
return obsoleteButton ;
}
2007-06-28 10:47:08 -07:00
/* Add the stats widgets to the widget screen */
2006-05-27 09:37:17 -07:00
/* If psSelected != NULL it specifies which stat should be hilited
2007-06-28 10:47:08 -07:00
psOwner specifies which object is hilighted on the object bar for this stat */
2011-03-12 17:32:15 -08:00
static bool intAddStats ( BASE_STATS * * ppsStatsList , UDWORD numStats ,
2012-12-21 07:35:35 -08:00
BASE_STATS * psSelected , BASE_OBJECT * psOwner )
2007-06-28 10:47:08 -07:00
{
FACTORY * psFactory ;
2011-03-17 10:41:47 -07:00
int allyResearchIconCount = 0 ;
2007-06-28 10:47:08 -07:00
// should this ever be called with psOwner == NULL?
// Is the form already up?
2012-12-21 07:35:35 -08:00
if ( widgGetFromID ( psWScreen , IDSTAT_FORM ) ! = NULL )
{
2007-06-28 10:47:08 -07:00
intRemoveStatsNoAnim ( ) ;
}
// is the order form already up ?
if ( widgGetFromID ( psWScreen , IDORDER_FORM ) ! = NULL )
{
intRemoveOrderNoAnim ( ) ;
}
2007-08-03 10:39:04 -07:00
if ( psOwner ! = NULL )
{
2007-06-28 10:47:08 -07:00
// Return if the owner is dead.
2007-08-03 10:39:04 -07:00
if ( psOwner - > died )
{
debug ( LOG_GUI , " intAddStats: Owner is dead " ) ;
2008-03-24 09:51:17 -07:00
return false ;
2007-06-28 10:47:08 -07:00
}
}
2012-04-02 20:56:20 -07:00
SecondaryWindowUp = true ;
2007-06-28 10:47:08 -07:00
psStatsScreenOwner = psOwner ;
2013-02-27 23:29:08 -08:00
WIDGET * parent = psWScreen - > psForm ;
2007-06-28 10:47:08 -07:00
/* Create the basic form */
2013-03-09 09:52:28 -08:00
IntFormAnimated * statForm = new IntFormAnimated ( parent , false ) ;
statForm - > id = IDSTAT_FORM ;
statForm - > setGeometry ( STAT_X , STAT_Y , STAT_WIDTH , STAT_HEIGHT ) ;
2007-06-28 10:47:08 -07:00
2010-12-22 06:02:14 -08:00
W_LABINIT sLabInit ;
2007-06-28 10:47:08 -07:00
// Add the quantity slider ( if it's a factory ).
2013-05-21 11:48:17 -07:00
if ( objMode = = IOBJ_MANUFACTURE & & psOwner ! = nullptr )
2007-06-28 10:47:08 -07:00
{
2013-05-21 11:48:17 -07:00
STRUCTURE_TYPE factoryType = ( ( STRUCTURE * ) psOwner ) - > pStructureType - > type ;
2007-06-28 10:47:08 -07:00
2013-05-21 11:48:17 -07:00
//add the Factory DP button
W_BUTTON * deliveryPointButton = new W_BUTTON ( statForm ) ;
deliveryPointButton - > id = IDSTAT_DP_BUTTON ;
deliveryPointButton - > style | = WBUT_SECONDARY ;
switch ( factoryType )
2007-06-28 10:47:08 -07:00
{
2013-05-21 11:48:17 -07:00
default :
case REF_FACTORY : deliveryPointButton - > setImages ( Image ( IntImages , IMAGE_FDP_UP ) , Image ( IntImages , IMAGE_FDP_DOWN ) , Image ( IntImages , IMAGE_FDP_HI ) ) ; break ;
case REF_CYBORG_FACTORY : deliveryPointButton - > setImages ( Image ( IntImages , IMAGE_CDP_UP ) , Image ( IntImages , IMAGE_CDP_DOWN ) , Image ( IntImages , IMAGE_CDP_HI ) ) ; break ;
case REF_VTOL_FACTORY : deliveryPointButton - > setImages ( Image ( IntImages , IMAGE_VDP_UP ) , Image ( IntImages , IMAGE_VDP_DOWN ) , Image ( IntImages , IMAGE_VDP_HI ) ) ; break ;
2007-06-28 10:47:08 -07:00
}
2013-05-21 11:48:17 -07:00
deliveryPointButton - > move ( 4 , STAT_SLDY ) ;
deliveryPointButton - > setTip ( _ ( " Factory Delivery Point " ) ) ;
deliveryPointButton - > pUserData = psOwner ;
2007-06-28 10:47:08 -07:00
//add the Factory Loop button!
2013-05-21 11:48:17 -07:00
W_BUTTON * loopButton = new W_BUTTON ( statForm ) ;
loopButton - > id = IDSTAT_LOOP_BUTTON ;
loopButton - > style | = WBUT_SECONDARY ;
loopButton - > setImages ( Image ( IntImages , IMAGE_LOOP_UP ) , Image ( IntImages , IMAGE_LOOP_DOWN ) , Image ( IntImages , IMAGE_LOOP_HI ) ) ;
loopButton - > move ( STAT_SLDX + STAT_SLDWIDTH + 2 , STAT_SLDY ) ;
loopButton - > setTip ( _ ( " Loop Production " ) ) ;
2007-06-28 10:47:08 -07:00
2012-12-21 07:35:35 -08:00
if ( psOwner ! = NULL )
2007-06-28 10:47:08 -07:00
{
psFactory = ( FACTORY * ) ( ( STRUCTURE * ) psOwner ) - > pFunctionality ;
2010-02-23 09:43:18 -08:00
if ( psFactory - > psSubject ! = NULL & & psFactory - > productionLoops ! = 0 )
2007-06-28 10:47:08 -07:00
{
widgSetButtonState ( psWScreen , IDSTAT_LOOP_BUTTON , WBUT_CLICKLOCK ) ;
}
}
// create a text label for the loop quantity.
sLabInit . formID = IDSTAT_FORM ;
sLabInit . id = IDSTAT_LOOP_LABEL ;
2010-12-22 06:02:14 -08:00
sLabInit . style = WIDG_HIDDEN ;
2013-05-21 11:48:17 -07:00
sLabInit . x = loopButton - > x ( ) - 15 ;
sLabInit . y = loopButton - > y ( ) ;
2007-06-28 10:47:08 -07:00
sLabInit . width = 12 ;
sLabInit . height = 15 ;
2007-11-09 13:01:23 -08:00
sLabInit . pUserData = psOwner ;
2007-06-28 10:47:08 -07:00
sLabInit . pCallback = intAddLoopQuantity ;
if ( ! widgAddLabel ( psWScreen , & sLabInit ) )
{
2008-03-24 09:51:17 -07:00
return false ;
2007-06-28 10:47:08 -07:00
}
2013-05-21 11:48:17 -07:00
}
2007-06-28 10:47:08 -07:00
2013-05-21 11:48:17 -07:00
if ( objMode = = IOBJ_MANUFACTURE )
{
2006-05-27 09:37:17 -07:00
/* store the common values for the text labels for the quantity
2007-06-28 10:47:08 -07:00
to produce ( on each button ) . */
2010-12-22 06:02:14 -08:00
sLabInit = W_LABINIT ( ) ;
2007-06-28 10:47:08 -07:00
sLabInit . id = IDSTAT_PRODSTART ;
2010-12-23 16:13:01 -08:00
sLabInit . style = WIDG_HIDDEN | WLAB_ALIGNRIGHT ;
2007-06-28 10:47:08 -07:00
2012-12-21 07:35:35 -08:00
sLabInit . x = STAT_BUTWIDTH - 12 - 6 ;
2007-06-28 10:47:08 -07:00
sLabInit . y = 2 ;
sLabInit . width = 12 ;
sLabInit . height = 15 ;
sLabInit . pCallback = intAddProdQuantity ;
}
2013-05-21 11:48:17 -07:00
if ( ( objMode = = IOBJ_MANUFACTURE | | objMode = = IOBJ_BUILD ) & & psOwner ! = nullptr )
{
// Add the obsolete items button.
makeObsoleteButton ( statForm ) ;
}
2007-06-28 10:47:08 -07:00
/* Add the close button */
2010-12-22 06:02:14 -08:00
W_BUTINIT sButInit ;
2007-06-28 10:47:08 -07:00
sButInit . formID = IDSTAT_FORM ;
sButInit . id = IDSTAT_CLOSE ;
sButInit . x = STAT_WIDTH - CLOSE_WIDTH ;
sButInit . y = 0 ;
sButInit . width = CLOSE_WIDTH ;
sButInit . height = CLOSE_HEIGHT ;
2007-04-01 13:15:46 -07:00
sButInit . pTip = _ ( " Close " ) ;
2007-06-28 10:47:08 -07:00
sButInit . pDisplay = intDisplayImageHilight ;
2012-12-21 07:35:35 -08:00
sButInit . UserData = PACKDWORD_TRI ( 0 , IMAGE_CLOSEHILIGHT , IMAGE_CLOSE ) ;
2007-06-28 10:47:08 -07:00
if ( ! widgAddButton ( psWScreen , & sButInit ) )
{
2008-03-24 09:51:17 -07:00
return false ;
2007-06-28 10:47:08 -07:00
}
2013-03-08 11:46:19 -08:00
2007-12-24 03:36:21 -08:00
// Add the tabbed form
2013-03-09 09:52:28 -08:00
IntListTabWidget * statList = new IntListTabWidget ( statForm ) ;
2013-03-08 11:46:19 -08:00
statList - > id = IDSTAT_TABFORM ;
statList - > setChildSize ( STAT_BUTWIDTH , STAT_BUTHEIGHT ) ;
statList - > setChildSpacing ( STAT_GAP , STAT_GAP ) ;
int statListWidth = STAT_BUTWIDTH * 2 + STAT_GAP ;
statList - > setGeometry ( ( STAT_WIDTH - statListWidth ) / 2 , STAT_TABFORMY , statListWidth , STAT_HEIGHT - STAT_TABFORMY ) ;
2007-06-28 10:47:08 -07:00
/* Add the stat buttons */
2013-03-08 11:46:19 -08:00
int nextButtonId = IDSTAT_START ;
2007-06-28 10:47:08 -07:00
2010-12-22 06:02:14 -08:00
W_BARINIT sBarInit ;
2007-06-28 10:47:08 -07:00
sBarInit . id = IDSTAT_TIMEBARSTART ;
sBarInit . x = STAT_TIMEBARX ;
sBarInit . width = STAT_PROGBARWIDTH ;
sBarInit . height = STAT_PROGBARHEIGHT ;
sBarInit . size = 50 ;
2010-04-04 04:46:51 -07:00
sBarInit . sCol = WZCOL_ACTION_PROGRESS_BAR_MAJOR ;
sBarInit . sMinorCol = WZCOL_ACTION_PROGRESS_BAR_MINOR ;
2007-06-28 10:47:08 -07:00
statID = 0 ;
2013-03-13 00:57:13 -07:00
for ( unsigned i = 0 ; i < numStats ; i + + )
2007-06-28 10:47:08 -07:00
{
2011-03-18 16:34:44 -07:00
sBarInit . y = STAT_TIMEBARY ;
2013-03-08 11:46:19 -08:00
if ( nextButtonId > IDSTAT_END )
2007-06-28 10:47:08 -07:00
{
//can't fit any more on the screen!
2012-12-21 07:32:23 -08:00
debug ( LOG_WARNING , " This is just a Warning! Max buttons have been allocated " ) ;
2007-06-28 10:47:08 -07:00
break ;
}
2013-03-13 00:57:13 -07:00
IntStatsButton * button = new IntStatsButton ( statList ) ;
2013-03-08 11:46:19 -08:00
button - > id = nextButtonId ;
button - > style | = WFORM_SECONDARY ;
2013-03-13 00:57:13 -07:00
button - > setStats ( ppsStatsList [ i ] ) ;
2013-03-08 11:46:19 -08:00
statList - > addWidgetToLayout ( button ) ;
2007-06-28 10:47:08 -07:00
2013-03-08 11:46:19 -08:00
BASE_STATS * Stat = ppsStatsList [ i ] ;
2013-05-12 14:50:57 -07:00
QString tipString = ppsStatsList [ i ] - > name ;
2013-03-08 12:37:56 -08:00
unsigned powerCost = 0 ;
2013-03-08 11:46:19 -08:00
W_BARGRAPH * bar ;
2006-05-27 09:37:17 -07:00
if ( Stat - > ref > = REF_STRUCTURE_START & &
2012-12-21 07:35:35 -08:00
Stat - > ref < REF_STRUCTURE_START + REF_RANGE ) // It's a structure.
{
2013-03-08 12:37:56 -08:00
powerCost = ( ( STRUCTURE_STATS * ) Stat ) - > powerToBuild ;
sBarInit . size = powerCost / POWERPOINTS_DROIDDIV ;
2012-12-21 07:35:35 -08:00
if ( sBarInit . size > 100 )
{
sBarInit . size = 100 ;
}
2007-06-28 10:47:08 -07:00
2013-03-08 11:46:19 -08:00
sBarInit . formID = nextButtonId ;
2007-06-28 10:47:08 -07:00
sBarInit . iRange = GAME_TICKS_PER_SEC ;
2013-02-25 15:24:53 -08:00
bar = widgAddBarGraph ( psWScreen , & sBarInit ) ;
bar - > setBackgroundColour ( WZCOL_BLACK ) ;
2012-12-21 07:35:35 -08:00
}
else if ( Stat - > ref > = REF_TEMPLATE_START & &
Stat - > ref < REF_TEMPLATE_START + REF_RANGE ) // It's a droid.
{
2013-05-08 09:47:58 -07:00
powerCost = calcTemplatePower ( ( DROID_TEMPLATE * ) Stat ) ;
2013-03-08 12:37:56 -08:00
sBarInit . size = powerCost / POWERPOINTS_DROIDDIV ;
2012-12-21 07:35:35 -08:00
if ( sBarInit . size > 100 )
{
sBarInit . size = 100 ;
}
2007-06-28 10:47:08 -07:00
2013-03-08 11:46:19 -08:00
sBarInit . formID = nextButtonId ;
2007-06-28 10:47:08 -07:00
sBarInit . iRange = GAME_TICKS_PER_SEC ;
2013-02-25 15:24:53 -08:00
bar = widgAddBarGraph ( psWScreen , & sBarInit ) ;
bar - > setBackgroundColour ( WZCOL_BLACK ) ;
2007-06-28 10:47:08 -07:00
// Add a text label for the quantity to produce.
2013-03-08 11:46:19 -08:00
sLabInit . formID = nextButtonId ;
2007-11-09 13:01:23 -08:00
sLabInit . pUserData = Stat ;
2007-06-28 10:47:08 -07:00
if ( ! widgAddLabel ( psWScreen , & sLabInit ) )
{
2008-03-24 09:51:17 -07:00
return false ;
2007-06-28 10:47:08 -07:00
}
sLabInit . id + + ;
}
2012-12-21 07:35:35 -08:00
else if ( Stat - > ref > = REF_RESEARCH_START & &
Stat - > ref < REF_RESEARCH_START + REF_RANGE ) // It's a Research topic.
2006-05-27 09:37:17 -07:00
{
2010-12-22 06:02:14 -08:00
sLabInit = W_LABINIT ( ) ;
2013-03-08 11:46:19 -08:00
sLabInit . formID = nextButtonId ;
sLabInit . id = IDSTAT_RESICONSTART + ( nextButtonId - IDSTAT_START ) ;
2007-06-28 10:47:08 -07:00
sLabInit . x = STAT_BUTWIDTH - 16 ;
sLabInit . y = 3 ;
sLabInit . width = 12 ;
sLabInit . height = 15 ;
2010-12-22 06:02:14 -08:00
sLabInit . pUserData = Stat ;
2007-06-28 10:47:08 -07:00
sLabInit . pDisplay = intDisplayResSubGroup ;
widgAddLabel ( psWScreen , & sLabInit ) ;
2006-05-27 09:37:17 -07:00
2007-06-28 10:47:08 -07:00
//add power bar as well
2013-03-08 12:37:56 -08:00
powerCost = ( ( RESEARCH * ) Stat ) - > researchPower ;
sBarInit . size = powerCost / POWERPOINTS_DROIDDIV ;
2012-12-21 07:35:35 -08:00
if ( sBarInit . size > 100 )
{
sBarInit . size = 100 ;
}
2007-06-28 10:47:08 -07:00
2007-08-03 10:39:04 -07:00
// if multiplayer, if research topic is being done by another ally then mark as such..
2012-12-21 07:35:35 -08:00
if ( bMultiPlayer )
2007-06-28 10:47:08 -07:00
{
2013-01-21 00:43:47 -08:00
std : : vector < AllyResearch > const & researches = listAllyResearch ( Stat - > ref ) ;
unsigned numResearches = std : : min < unsigned > ( researches . size ( ) , 4 ) ; // Only display at most 4 allies, since that's what there's room for.
for ( unsigned ii = 0 ; ii < numResearches ; + + ii )
2007-06-28 10:47:08 -07:00
{
2013-01-21 00:43:47 -08:00
// add a label.
sLabInit = W_LABINIT ( ) ;
2013-03-08 11:46:19 -08:00
sLabInit . formID = nextButtonId ;
2013-01-21 00:43:47 -08:00
sLabInit . id = IDSTAT_ALLYSTART + allyResearchIconCount ;
sLabInit . width = iV_GetImageWidth ( IntImages , IMAGE_ALLY_RESEARCH ) ;
sLabInit . height = iV_GetImageHeight ( IntImages , IMAGE_ALLY_RESEARCH ) ;
sLabInit . x = STAT_BUTWIDTH - ( sLabInit . width + 2 ) * ii - sLabInit . width - 2 ;
sLabInit . y = STAT_BUTHEIGHT - sLabInit . height - 3 - STAT_PROGBARHEIGHT ;
2013-01-21 04:52:40 -08:00
sLabInit . UserData = PACKDWORD ( Stat - > ref - REF_RESEARCH_START , ii ) ;
2013-01-21 00:43:47 -08:00
sLabInit . pTip = getPlayerName ( researches [ ii ] . player ) ;
sLabInit . pDisplay = intDisplayAllyIcon ;
widgAddLabel ( psWScreen , & sLabInit ) ;
+ + allyResearchIconCount ;
ASSERT ( allyResearchIconCount < IDSTAT_ALLYEND - IDSTAT_ALLYSTART , " " ) ;
2007-06-28 10:47:08 -07:00
}
2013-01-21 00:43:47 -08:00
if ( numResearches > 0 )
2011-03-18 16:34:44 -07:00
{
W_BARINIT progress ;
2013-03-08 11:46:19 -08:00
progress . formID = nextButtonId ;
2011-03-18 16:34:44 -07:00
progress . id = IDSTAT_ALLYSTART + allyResearchIconCount ;
progress . width = STAT_PROGBARWIDTH ;
progress . height = STAT_PROGBARHEIGHT ;
progress . x = STAT_TIMEBARX ;
progress . y = STAT_TIMEBARY ;
progress . UserData = Stat - > ref - REF_RESEARCH_START ;
progress . pTip = _ ( " Ally progress " ) ;
progress . pDisplay = intDisplayAllyBar ;
2013-02-26 15:06:35 -08:00
W_BARGRAPH * bar = widgAddBarGraph ( psWScreen , & progress ) ;
bar - > setBackgroundColour ( WZCOL_BLACK ) ;
2011-03-18 16:34:44 -07:00
+ + allyResearchIconCount ;
sBarInit . y - = STAT_PROGBARHEIGHT + 2 ; // Move cost bar up, to avoid overlap.
}
2007-06-28 10:47:08 -07:00
}
2011-03-17 10:41:47 -07:00
2013-03-08 11:46:19 -08:00
sBarInit . formID = nextButtonId ;
2013-02-25 15:24:53 -08:00
bar = widgAddBarGraph ( psWScreen , & sBarInit ) ;
bar - > setBackgroundColour ( WZCOL_BLACK ) ;
2007-06-28 10:47:08 -07:00
}
2013-03-08 12:37:56 -08:00
tipString . append ( QString : : fromUtf8 ( _ ( " \n Cost: %1 " ) ) . arg ( powerCost ) ) ;
button - > setTip ( tipString ) ;
2007-06-28 10:47:08 -07:00
/* If this matches psSelected note the form and button */
if ( ppsStatsList [ i ] = = psSelected )
{
2013-03-08 11:46:19 -08:00
statID = nextButtonId ;
button - > setState ( WBUT_CLICKLOCK ) ;
statList - > setCurrentPage ( statList - > pages ( ) - 1 ) ;
2007-06-28 10:47:08 -07:00
}
/* Update the init struct for the next button */
2013-03-08 11:46:19 -08:00
+ + nextButtonId ;
2007-06-28 10:47:08 -07:00
sBarInit . id + = 1 ;
}
2008-03-24 09:51:17 -07:00
StatsUp = true ;
2007-06-28 10:47:08 -07:00
// call the tutorial callbacks if necessary
if ( bInTutorial )
{
switch ( objMode )
{
case IOBJ_BUILD :
eventFireCallbackTrigger ( ( TRIGGER_TYPE ) CALL_BUILDLIST ) ;
break ;
case IOBJ_RESEARCH :
eventFireCallbackTrigger ( ( TRIGGER_TYPE ) CALL_RESEARCHLIST ) ;
break ;
case IOBJ_MANUFACTURE :
eventFireCallbackTrigger ( ( TRIGGER_TYPE ) CALL_MANULIST ) ;
break ;
default :
break ;
}
}
2008-03-24 09:51:17 -07:00
return true ;
2007-06-28 10:47:08 -07:00
}
/* Select a command droid */
2011-03-12 17:32:15 -08:00
static bool selectCommand ( BASE_OBJECT * psObj )
2007-06-28 10:47:08 -07:00
{
2012-12-21 06:01:30 -08:00
ASSERT ( psObj & & psObj - > type = = OBJ_DROID , " Invalid droid pointer " ) ;
DROID * psDroid = ( DROID * ) psObj ;
if ( psDroid - > droidType = = DROID_COMMAND & & psDroid - > died = = 0 )
2007-06-28 10:47:08 -07:00
{
2008-03-24 09:51:17 -07:00
return true ;
2007-06-28 10:47:08 -07:00
}
2008-03-24 09:51:17 -07:00
return false ;
2007-06-28 10:47:08 -07:00
}
/* Return the stats for a command droid */
2008-04-20 10:17:50 -07:00
static BASE_STATS * getCommandStats ( WZ_DECL_UNUSED BASE_OBJECT * psObj )
2007-06-28 10:47:08 -07:00
{
return NULL ;
}
/* Set the stats for a command droid */
2011-03-12 17:32:15 -08:00
static bool setCommandStats ( WZ_DECL_UNUSED BASE_OBJECT * psObj , WZ_DECL_UNUSED BASE_STATS * psStats )
2007-06-28 10:47:08 -07:00
{
2008-03-24 09:51:17 -07:00
return true ;
2007-06-28 10:47:08 -07:00
}
/* Select a construction droid */
2011-03-12 17:32:15 -08:00
static bool selectConstruction ( BASE_OBJECT * psObj )
2007-06-28 10:47:08 -07:00
{
DROID * psDroid ;
2012-12-21 07:35:35 -08:00
ASSERT ( psObj ! = NULL & & psObj - > type = = OBJ_DROID ,
" selectConstruction: invalid droid pointer " ) ;
2007-06-28 10:47:08 -07:00
psDroid = ( DROID * ) psObj ;
//check the droid type
2010-12-17 11:06:53 -08:00
if ( ( psDroid - > droidType = = DROID_CONSTRUCT | | psDroid - > droidType = = DROID_CYBORG_CONSTRUCT ) & & ( psDroid - > died = = 0 ) )
2007-06-28 10:47:08 -07:00
{
2008-03-24 09:51:17 -07:00
return true ;
2007-06-28 10:47:08 -07:00
}
2008-03-24 09:51:17 -07:00
return false ;
2007-06-28 10:47:08 -07:00
}
/* Return the stats for a construction droid */
static BASE_STATS * getConstructionStats ( BASE_OBJECT * psObj )
{
2008-03-10 06:31:08 -07:00
DROID * psDroid = ( DROID * ) psObj ;
2007-06-28 10:47:08 -07:00
BASE_STATS * Stats ;
2008-03-10 06:31:08 -07:00
BASE_OBJECT * Structure ;
UDWORD x , y ;
2007-06-28 10:47:08 -07:00
2012-12-21 07:35:35 -08:00
ASSERT ( psObj ! = NULL & & psObj - > type = = OBJ_DROID ,
" getConstructionStats: invalid droid pointer " ) ;
2007-06-28 10:47:08 -07:00
2008-03-10 06:31:08 -07:00
if ( ! ( droidType ( psDroid ) = = DROID_CONSTRUCT | |
2012-12-21 07:35:35 -08:00
droidType ( psDroid ) = = DROID_CYBORG_CONSTRUCT ) )
2008-03-10 06:31:08 -07:00
{
return NULL ;
}
2007-06-28 10:47:08 -07:00
2012-12-21 07:35:35 -08:00
if ( orderStateStatsLoc ( psDroid , DORDER_BUILD , & Stats , & x , & y ) ) // Moving to build location?
2008-03-10 06:31:08 -07:00
{
2007-06-28 10:47:08 -07:00
return Stats ;
2008-03-10 06:31:08 -07:00
}
2008-03-11 07:44:03 -07:00
else if ( ( Structure = orderStateObj ( psDroid , DORDER_BUILD ) )
2012-12-21 07:35:35 -08:00
& & psDroid - > order . type = = DORDER_BUILD ) // Is building
2008-03-10 06:31:08 -07:00
{
2011-12-30 08:43:49 -08:00
return psDroid - > order . psStats ;
2008-03-10 06:31:08 -07:00
}
2008-03-11 07:44:03 -07:00
else if ( ( Structure = orderStateObj ( psDroid , DORDER_HELPBUILD ) )
2012-12-21 07:35:35 -08:00
& & ( psDroid - > order . type = = DORDER_HELPBUILD
| | psDroid - > order . type = = DORDER_LINEBUILD ) ) // Is helping
2008-03-10 06:31:08 -07:00
{
2012-12-21 07:35:35 -08:00
return ( BASE_STATS * ) ( ( STRUCTURE * ) Structure ) - > pStructureType ;
2008-03-10 06:31:08 -07:00
}
else if ( orderState ( psDroid , DORDER_DEMOLISH ) )
{
return ( BASE_STATS * ) structGetDemolishStat ( ) ;
}
2007-06-28 10:47:08 -07:00
return NULL ;
}
/* Set the stats for a construction droid */
2011-03-12 17:32:15 -08:00
static bool setConstructionStats ( BASE_OBJECT * psObj , BASE_STATS * psStats )
2007-06-28 10:47:08 -07:00
{
2011-02-25 09:22:08 -08:00
DROID * psDroid = castDroid ( psObj ) ;
ASSERT ( psDroid ! = NULL , " invalid droid pointer " ) ;
2007-06-28 10:47:08 -07:00
/* psStats might be NULL if the operation is canceled in the middle */
if ( psStats ! = NULL )
{
//check for demolish first
2011-02-25 09:22:08 -08:00
if ( psStats = = structGetDemolishStat ( ) )
2007-06-28 10:47:08 -07:00
{
objMode = IOBJ_DEMOLISHSEL ;
2008-03-24 09:51:17 -07:00
return true ;
2007-06-28 10:47:08 -07:00
}
/* Store the stats for future use */
psPositionStats = psStats ;
/* Now start looking for a location for the structure */
2011-02-25 09:22:08 -08:00
objMode = IOBJ_BUILDSEL ;
2007-06-28 10:47:08 -07:00
2011-02-25 09:22:08 -08:00
intStartStructPosition ( psStats ) ;
2007-06-28 10:47:08 -07:00
2011-02-25 09:22:08 -08:00
return true ;
2007-06-28 10:47:08 -07:00
}
2011-02-25 09:22:08 -08:00
orderDroid ( psDroid , DORDER_STOP , ModeQueue ) ;
2008-03-24 09:51:17 -07:00
return true ;
2007-06-28 10:47:08 -07:00
}
/* Select a research facility */
2011-03-12 17:32:15 -08:00
static bool selectResearch ( BASE_OBJECT * psObj )
2007-06-28 10:47:08 -07:00
{
STRUCTURE * psResFacility ;
2012-12-21 07:35:35 -08:00
ASSERT ( psObj ! = NULL & & psObj - > type = = OBJ_STRUCTURE ,
" selectResearch: invalid Structure pointer " ) ;
2007-06-28 10:47:08 -07:00
psResFacility = ( STRUCTURE * ) psObj ;
2006-05-27 09:37:17 -07:00
/* A Structure is a research facility if its type = REF_RESEARCH and is
2007-06-28 10:47:08 -07:00
completely built */
2007-02-10 08:39:39 -08:00
if ( psResFacility - > pStructureType - > type = = REF_RESEARCH & & ( psResFacility - >
2012-12-21 07:35:35 -08:00
status = = SS_BUILT ) & & ( psResFacility - > died = = 0 ) )
2007-06-28 10:47:08 -07:00
{
2008-03-24 09:51:17 -07:00
return true ;
2007-06-28 10:47:08 -07:00
}
2008-03-24 09:51:17 -07:00
return false ;
2007-06-28 10:47:08 -07:00
}
/* Return the stats for a research facility */
static BASE_STATS * getResearchStats ( BASE_OBJECT * psObj )
{
2010-07-19 08:17:53 -07:00
STRUCTURE * psBuilding ;
RESEARCH_FACILITY * psResearchFacility ;
2007-06-28 10:47:08 -07:00
2012-12-21 07:35:35 -08:00
ASSERT ( psObj ! = NULL & & psObj - > type = = OBJ_STRUCTURE ,
" getResearchTip: invalid Structure pointer " ) ;
2007-06-28 10:47:08 -07:00
psBuilding = ( STRUCTURE * ) psObj ;
2010-07-19 08:17:53 -07:00
psResearchFacility = & psBuilding - > pFunctionality - > researchFacility ;
2007-06-28 10:47:08 -07:00
2012-09-14 23:21:32 -07:00
if ( psResearchFacility - > psSubjectPending ! = NULL & & ! IsResearchCompleted ( & asPlayerResList [ psObj - > player ] [ psResearchFacility - > psSubjectPending - > index ] ) )
2010-07-19 08:17:53 -07:00
{
return psResearchFacility - > psSubjectPending ;
}
return psResearchFacility - > psSubject ;
2007-06-28 10:47:08 -07:00
}
/* Set the stats for a research facility */
2011-03-12 17:32:15 -08:00
static bool setResearchStats ( BASE_OBJECT * psObj , BASE_STATS * psStats )
2007-06-28 10:47:08 -07:00
{
STRUCTURE * psBuilding ;
2012-12-21 07:35:35 -08:00
RESEARCH * pResearch = ( RESEARCH * ) psStats ;
2007-06-28 10:47:08 -07:00
PLAYER_RESEARCH * pPlayerRes ;
UDWORD count ;
RESEARCH_FACILITY * psResFacilty ;
2012-12-21 07:35:35 -08:00
ASSERT ( psObj ! = NULL & & psObj - > type = = OBJ_STRUCTURE ,
" setResearchStats: invalid Structure pointer " ) ;
2007-06-28 10:47:08 -07:00
/* psStats might be NULL if the operation is canceled in the middle */
psBuilding = ( STRUCTURE * ) psObj ;
2010-07-19 08:17:53 -07:00
psResFacilty = & psBuilding - > pFunctionality - > researchFacility ;
2007-06-28 10:47:08 -07:00
2010-02-22 16:18:22 -08:00
if ( bMultiMessages )
{
2011-02-22 14:42:33 -08:00
if ( pResearch ! = NULL )
2010-02-24 12:15:17 -08:00
{
// Say that we want to do reseach [sic].
2011-02-22 14:42:33 -08:00
sendResearchStatus ( psBuilding , pResearch - > ref - REF_RESEARCH_START , selectedPlayer , true ) ;
2011-12-05 05:22:18 -08:00
setStatusPendingStart ( * psResFacilty , pResearch ) ; // Tell UI that we are going to research.
2010-02-24 12:15:17 -08:00
}
else
{
2010-10-22 09:13:04 -07:00
cancelResearch ( psBuilding , ModeQueue ) ;
2010-02-24 12:15:17 -08:00
}
2010-02-22 16:18:22 -08:00
//stop the button from flashing once a topic has been chosen
stopReticuleButtonFlash ( IDRET_RESEARCH ) ;
return true ;
}
2010-02-24 12:15:17 -08:00
//initialise the subject
psResFacilty - > psSubject = NULL ;
2007-06-28 10:47:08 -07:00
//set up the player_research
2011-02-22 14:42:33 -08:00
if ( pResearch ! = NULL )
2007-06-28 10:47:08 -07:00
{
count = pResearch - > ref - REF_RESEARCH_START ;
//meant to still be in the list but greyed out
2011-12-02 05:26:37 -08:00
pPlayerRes = & asPlayerResList [ selectedPlayer ] [ count ] ;
2007-06-28 10:47:08 -07:00
//set the subject up
2011-02-22 14:42:33 -08:00
psResFacilty - > psSubject = pResearch ;
2007-06-28 10:47:08 -07:00
2012-12-21 07:35:35 -08:00
sendResearchStatus ( psBuilding , count , selectedPlayer , true ) ; // inform others, I'm researching this.
2007-06-28 10:47:08 -07:00
MakeResearchStarted ( pPlayerRes ) ;
2010-12-17 11:06:53 -08:00
psResFacilty - > timeStartHold = 0 ;
2007-06-28 10:47:08 -07:00
//stop the button from flashing once a topic has been chosen
stopReticuleButtonFlash ( IDRET_RESEARCH ) ;
2006-05-27 09:37:17 -07:00
}
2008-03-24 09:51:17 -07:00
return true ;
2007-06-28 10:47:08 -07:00
}
/* Select a Factory */
2011-03-12 17:32:15 -08:00
static bool selectManufacture ( BASE_OBJECT * psObj )
2007-06-28 10:47:08 -07:00
{
STRUCTURE * psBuilding ;
2012-12-21 07:35:35 -08:00
ASSERT ( psObj ! = NULL & & psObj - > type = = OBJ_STRUCTURE ,
" selectManufacture: invalid Structure pointer " ) ;
2007-06-28 10:47:08 -07:00
psBuilding = ( STRUCTURE * ) psObj ;
/* A Structure is a Factory if its type = REF_FACTORY or REF_CYBORG_FACTORY or
REF_VTOL_FACTORY and it is completely built */
2007-02-10 08:39:39 -08:00
if ( ( psBuilding - > pStructureType - > type = = REF_FACTORY | |
2012-12-21 07:35:35 -08:00
psBuilding - > pStructureType - > type = = REF_CYBORG_FACTORY | |
psBuilding - > pStructureType - > type = = REF_VTOL_FACTORY ) & &
( psBuilding - > status = = SS_BUILT ) & & ( psBuilding - > died = = 0 ) )
2007-06-28 10:47:08 -07:00
{
2008-03-24 09:51:17 -07:00
return true ;
2007-06-28 10:47:08 -07:00
}
2008-03-24 09:51:17 -07:00
return false ;
2007-06-28 10:47:08 -07:00
}
/* Return the stats for a Factory */
static BASE_STATS * getManufactureStats ( BASE_OBJECT * psObj )
{
STRUCTURE * psBuilding ;
2012-12-21 07:35:35 -08:00
ASSERT ( psObj ! = NULL & & psObj - > type = = OBJ_STRUCTURE ,
" getManufactureTip: invalid Structure pointer " ) ;
2007-06-28 10:47:08 -07:00
psBuilding = ( STRUCTURE * ) psObj ;
2012-12-21 07:35:35 -08:00
return ( ( BASE_STATS * ) ( ( FACTORY * ) psBuilding - > pFunctionality ) - > psSubject ) ;
2007-06-28 10:47:08 -07:00
}
/* Set the stats for a Factory */
2011-03-12 17:32:15 -08:00
static bool setManufactureStats ( BASE_OBJECT * psObj , BASE_STATS * psStats )
2007-06-28 10:47:08 -07:00
{
STRUCTURE * Structure ;
2012-12-21 07:35:35 -08:00
ASSERT ( psObj ! = NULL & & psObj - > type = = OBJ_STRUCTURE ,
" setManufactureStats: invalid Structure pointer " ) ;
2007-06-28 10:47:08 -07:00
/* psStats might be NULL if the operation is canceled in the middle */
2012-12-21 07:35:35 -08:00
Structure = ( STRUCTURE * ) psObj ;
2007-06-28 10:47:08 -07:00
//check to see if the factory was already building something
if ( ! ( ( FACTORY * ) Structure - > pFunctionality ) - > psSubject )
{
//factory not currently building so set up the factory stats
if ( psStats ! = NULL )
{
/* Set the factory to build droid(s) */
2010-10-22 09:13:04 -07:00
if ( ! structSetManufacture ( Structure , ( DROID_TEMPLATE * ) psStats , ModeQueue ) )
2007-06-28 10:47:08 -07:00
{
2008-03-24 09:51:17 -07:00
return false ;
2007-06-28 10:47:08 -07:00
}
}
}
2008-03-24 09:51:17 -07:00
return true ;
2007-06-28 10:47:08 -07:00
}
/* Add the build widgets to the widget screen */
/* If psSelected != NULL it specifies which droid should be hilited */
2011-03-12 17:32:15 -08:00
static bool intAddBuild ( DROID * psSelected )
2007-06-28 10:47:08 -07:00
{
/* Store the correct stats list for future reference */
ppsStatsList = ( BASE_STATS * * ) apsStructStatsList ;
objSelectFunc = selectConstruction ;
objGetStatsFunc = getConstructionStats ;
objSetStatsFunc = setConstructionStats ;
/* Set the sub mode */
objMode = IOBJ_BUILD ;
2006-05-27 09:37:17 -07:00
2007-06-28 10:47:08 -07:00
/* Create the object screen with the required data */
2006-12-02 06:38:09 -08:00
return intAddObjectWindow ( ( BASE_OBJECT * ) apsDroidLists [ selectedPlayer ] ,
2012-12-21 07:35:35 -08:00
( BASE_OBJECT * ) psSelected , true ) ;
2007-06-28 10:47:08 -07:00
}
/* Add the manufacture widgets to the widget screen */
/* If psSelected != NULL it specifies which factory should be hilited */
2011-03-12 17:32:15 -08:00
static bool intAddManufacture ( STRUCTURE * psSelected )
2007-06-28 10:47:08 -07:00
{
/* Store the correct stats list for future reference */
2012-12-21 07:35:35 -08:00
ppsStatsList = ( BASE_STATS * * ) & apsTemplateList [ 0 ] ; // FIXME Ugly cast, and is undefined behaviour (strict-aliasing violation) in C/C++.
2007-06-28 10:47:08 -07:00
objSelectFunc = selectManufacture ;
objGetStatsFunc = getManufactureStats ;
objSetStatsFunc = setManufactureStats ;
/* Set the sub mode */
objMode = IOBJ_MANUFACTURE ;
/* Create the object screen with the required data */
2006-12-02 06:38:09 -08:00
return intAddObjectWindow ( ( BASE_OBJECT * ) interfaceStructList ( ) ,
2012-12-21 07:35:35 -08:00
( BASE_OBJECT * ) psSelected , true ) ;
2007-06-28 10:47:08 -07:00
}
/* Add the research widgets to the widget screen */
/* If psSelected != NULL it specifies which droid should be hilited */
2011-03-12 17:32:15 -08:00
static bool intAddResearch ( STRUCTURE * psSelected )
2007-06-28 10:47:08 -07:00
{
ppsStatsList = ( BASE_STATS * * ) ppResearchList ;
objSelectFunc = selectResearch ;
objGetStatsFunc = getResearchStats ;
objSetStatsFunc = setResearchStats ;
/* Set the sub mode */
objMode = IOBJ_RESEARCH ;
/* Create the object screen with the required data */
2006-12-02 06:38:09 -08:00
return intAddObjectWindow ( ( BASE_OBJECT * ) interfaceStructList ( ) ,
2012-12-21 07:35:35 -08:00
( BASE_OBJECT * ) psSelected , true ) ;
2007-06-28 10:47:08 -07:00
}
/* Add the command droid widgets to the widget screen */
/* If psSelected != NULL it specifies which droid should be hilited */
2011-03-12 17:32:15 -08:00
static bool intAddCommand ( DROID * psSelected )
2007-06-28 10:47:08 -07:00
{
ppsStatsList = NULL ; //(BASE_STATS **)ppResearchList;
objSelectFunc = selectCommand ;
objGetStatsFunc = getCommandStats ;
objSetStatsFunc = setCommandStats ;
/* Set the sub mode */
objMode = IOBJ_COMMAND ;
/* Create the object screen with the required data */
2006-12-02 06:38:09 -08:00
return intAddObjectWindow ( ( BASE_OBJECT * ) apsDroidLists [ selectedPlayer ] ,
2012-12-21 07:35:35 -08:00
( BASE_OBJECT * ) psSelected , true ) ;
2007-06-28 10:47:08 -07:00
}
/*Deals with the RMB click for the stats screen */
static void intStatsRMBPressed ( UDWORD id )
{
2012-12-21 07:35:35 -08:00
ASSERT_OR_RETURN ( , id - IDSTAT_START < numStatsListEntries , " Invalid range referenced for numStatsListEntries, %d > %d " , id - IDSTAT_START , numStatsListEntries ) ;
2007-06-28 10:47:08 -07:00
if ( objMode = = IOBJ_MANUFACTURE )
{
2010-07-20 13:57:19 -07:00
BASE_STATS * psStats = ppsStatsList [ id - IDSTAT_START ] ;
2007-06-28 10:47:08 -07:00
//this now causes the production run to be decreased by one
2012-12-21 07:35:35 -08:00
ASSERT_OR_RETURN ( , psObjSelected ! = NULL , " Invalid structure pointer " ) ;
ASSERT_OR_RETURN ( , psStats ! = NULL , " Invalid template pointer " ) ;
2010-06-27 12:12:18 -07:00
if ( productionPlayer = = ( SBYTE ) selectedPlayer )
{
2010-07-20 13:57:19 -07:00
STRUCTURE * psStructure = ( STRUCTURE * ) psObjSelected ;
FACTORY * psFactory = & psStructure - > pFunctionality - > factory ;
DROID_TEMPLATE * psNext = ( DROID_TEMPLATE * ) psStats ;
2007-06-28 10:47:08 -07:00
2010-07-20 13:57:19 -07:00
//decrease the production
factoryProdAdjust ( psStructure , psNext , false ) ;
//need to check if this was the template that was mid-production
2010-12-23 16:13:01 -08:00
if ( getProduction ( psStructure , FactoryGetTemplate ( psFactory ) ) . numRemaining ( ) = = 0 )
2010-07-20 13:57:19 -07:00
{
2010-12-07 12:58:37 -08:00
doNextProduction ( psStructure , FactoryGetTemplate ( psFactory ) , ModeQueue ) ;
2010-07-20 13:57:19 -07:00
psNext = FactoryGetTemplate ( psFactory ) ;
}
2010-12-23 16:13:01 -08:00
else if ( ! StructureIsManufacturingPending ( psStructure ) )
{
structSetManufacture ( psStructure , psNext , ModeQueue ) ;
}
2010-07-20 13:57:19 -07:00
if ( StructureIsOnHoldPending ( psStructure ) )
{
2010-10-22 09:13:04 -07:00
releaseProduction ( psStructure , ModeQueue ) ;
2010-07-20 13:57:19 -07:00
}
// Reset the button on the object form
intSetStats ( objStatID , ( BASE_STATS * ) psNext ) ;
}
2007-06-28 10:47:08 -07:00
}
}
/*Deals with the RMB click for the Object screen */
static void intObjectRMBPressed ( UDWORD id )
{
BASE_OBJECT * psObj ;
STRUCTURE * psStructure ;
2011-01-04 06:48:00 -08:00
ASSERT ( id - IDOBJ_OBJSTART < apsObjectList . size ( ) , " intObjectRMBPressed: Invalid object id " ) ;
2007-06-28 10:47:08 -07:00
/* Find the object that the ID refers to */
psObj = intGetObject ( id ) ;
if ( psObj )
{
2012-12-21 07:35:35 -08:00
//don't jump around when offworld
2007-02-10 08:39:39 -08:00
if ( psObj - > type = = OBJ_STRUCTURE & & ! offWorldKeepLists )
2007-06-28 10:47:08 -07:00
{
psStructure = ( STRUCTURE * ) psObj ;
2007-02-10 08:39:39 -08:00
if ( psStructure - > pStructureType - > type = = REF_FACTORY | |
2012-12-21 07:35:35 -08:00
psStructure - > pStructureType - > type = = REF_CYBORG_FACTORY | |
psStructure - > pStructureType - > type = = REF_VTOL_FACTORY )
2007-06-28 10:47:08 -07:00
{
//centre the view on the delivery point
2007-09-28 10:39:33 -07:00
setViewPos ( map_coord ( ( ( FACTORY * ) psStructure - > pFunctionality ) - > psAssemblyPoint - > coords . x ) ,
2012-12-21 07:35:35 -08:00
map_coord ( ( ( FACTORY * ) psStructure - > pFunctionality ) - > psAssemblyPoint - > coords . y ) ,
true ) ;
2007-06-28 10:47:08 -07:00
}
}
}
}
/*Deals with the RMB click for the Object Stats buttons */
static void intObjStatRMBPressed ( UDWORD id )
{
BASE_OBJECT * psObj ;
STRUCTURE * psStructure ;
2012-12-21 07:35:35 -08:00
ASSERT ( id - IDOBJ_STATSTART < apsObjectList . size ( ) , " intObjStatRMBPressed: Invalid stat id " ) ;
2007-06-28 10:47:08 -07:00
/* Find the object that the ID refers to */
psObj = intGetObject ( id ) ;
2012-12-21 07:32:23 -08:00
if ( ! psObj )
2007-06-28 10:47:08 -07:00
{
2012-12-21 07:32:23 -08:00
return ;
}
2012-12-21 07:35:35 -08:00
intResetWindows ( psObj ) ;
if ( psObj - > type = = OBJ_STRUCTURE )
{
psStructure = ( STRUCTURE * ) psObj ;
if ( StructIsFactory ( psStructure ) )
2007-06-28 10:47:08 -07:00
{
2012-12-21 07:35:35 -08:00
//check if active
if ( StructureIsManufacturingPending ( psStructure ) )
2007-06-28 10:47:08 -07:00
{
2012-12-21 07:35:35 -08:00
//if not curently on hold, set it
if ( ! StructureIsOnHoldPending ( psStructure ) )
2007-06-28 10:47:08 -07:00
{
2012-12-21 07:35:35 -08:00
holdProduction ( psStructure , ModeQueue ) ;
}
else
{
//cancel if have RMB-clicked twice
cancelProduction ( psStructure , ModeQueue ) ;
//play audio to indicate cancelled
audio_PlayTrack ( ID_SOUND_WINDOWCLOSE ) ;
2007-06-28 10:47:08 -07:00
}
}
2012-12-21 07:35:35 -08:00
}
else if ( psStructure - > pStructureType - > type = = REF_RESEARCH )
{
//check if active
if ( structureIsResearchingPending ( psStructure ) )
2010-07-20 13:57:19 -07:00
{
2012-12-21 07:35:35 -08:00
//if not curently on hold, set it
if ( ! StructureIsOnHoldPending ( psStructure ) )
2007-06-28 10:47:08 -07:00
{
2012-12-21 07:35:35 -08:00
holdResearch ( psStructure , ModeQueue ) ;
}
else
{
//cancel if have RMB-clicked twice
cancelResearch ( psStructure , ModeQueue ) ;
//play audio to indicate cancelled
audio_PlayTrack ( ID_SOUND_WINDOWCLOSE ) ;
2007-06-28 10:47:08 -07:00
}
2010-07-20 13:57:19 -07:00
}
2007-06-28 10:47:08 -07:00
}
2012-12-21 07:35:35 -08:00
}
2007-06-28 10:47:08 -07:00
}
//sets up the Intelligence Screen as far as the interface is concerned
void addIntelScreen ( void )
{
2011-03-12 17:32:15 -08:00
bool radOnScreen ;
2007-06-28 10:47:08 -07:00
2012-12-21 07:35:35 -08:00
if ( driveModeActive ( ) & & ! driveInterfaceEnabled ( ) )
{
2007-06-28 10:47:08 -07:00
driveDisableControl ( ) ;
2008-03-24 09:51:17 -07:00
driveEnableInterface ( true ) ;
2007-06-28 10:47:08 -07:00
}
2008-03-24 09:51:17 -07:00
intResetScreen ( false ) ;
2007-06-28 10:47:08 -07:00
//lock the reticule button
widgSetButtonState ( psWScreen , IDRET_INTEL_MAP , WBUT_CLICKLOCK ) ;
2007-08-03 10:39:04 -07:00
2007-06-28 10:47:08 -07:00
//add the power bar - for looks!
intShowPowerBar ( ) ;
// Only do this in main game.
2012-12-21 07:35:35 -08:00
if ( ( GetGameMode ( ) = = GS_NORMAL ) & & ! bMultiPlayer )
2006-05-27 09:37:17 -07:00
{
2007-06-28 10:47:08 -07:00
radOnScreen = radarOnScreen ;
2006-05-27 09:37:17 -07:00
2008-03-24 09:51:17 -07:00
bRender3DOnly = true ;
radarOnScreen = false ;
2007-06-28 10:47:08 -07:00
2010-12-17 11:06:53 -08:00
// Just display the 3d, no interface
2007-06-28 10:47:08 -07:00
displayWorld ( ) ;
2010-12-17 11:06:53 -08:00
2007-06-28 10:47:08 -07:00
radarOnScreen = radOnScreen ;
2008-03-24 09:51:17 -07:00
bRender3DOnly = false ;
2007-06-28 10:47:08 -07:00
}
//add all the intelligence screen interface
( void ) intAddIntelMap ( ) ;
intMode = INT_INTELMAP ;
}
//sets up the Transporter Screen as far as the interface is concerned
2011-03-12 17:32:15 -08:00
void addTransporterInterface ( DROID * psSelected , bool onMission )
2007-06-28 10:47:08 -07:00
{
2010-12-17 11:06:53 -08:00
// if psSelected = NULL add interface but if psSelected != NULL make sure its not flying
if ( ! psSelected | | ( psSelected & & ! transporterFlying ( psSelected ) ) )
{
intResetScreen ( false ) ;
intAddTransporter ( psSelected , onMission ) ;
intMode = INT_TRANSPORTER ;
}
2007-06-28 10:47:08 -07:00
}
/*sets which list of structures to use for the interface*/
2012-12-21 07:35:35 -08:00
STRUCTURE * interfaceStructList ( void )
2007-06-28 10:47:08 -07:00
{
if ( offWorldKeepLists )
{
return mission . apsStructLists [ selectedPlayer ] ;
}
else
{
return apsStructLists [ selectedPlayer ] ;
}
}
/*causes a reticule button to start flashing*/
void flashReticuleButton ( UDWORD buttonID )
{
//get the button for the id
2013-03-12 01:32:55 -07:00
WIDGET * psButton = widgGetFromID ( psWScreen , buttonID ) ;
2007-06-28 10:47:08 -07:00
if ( psButton )
{
2013-08-02 11:27:20 -07:00
retbutstats [ psButton - > UserData ] . flashing = 1 ;
2007-06-28 10:47:08 -07:00
}
}
// stop a reticule button flashing
void stopReticuleButtonFlash ( UDWORD buttonID )
{
2012-12-21 07:35:35 -08:00
WIDGET * psButton = widgGetFromID ( psWScreen , buttonID ) ;
2007-06-28 10:47:08 -07:00
if ( psButton )
{
2013-08-02 11:27:20 -07:00
retbutstats [ psButton - > UserData ] . flashTime = 0 ;
retbutstats [ psButton - > UserData ] . flashing = 0 ;
2007-06-28 10:47:08 -07:00
}
}
//displays the Power Bar
void intShowPowerBar ( void )
{
//if its not already on display
2012-12-21 07:35:35 -08:00
if ( widgGetFromID ( psWScreen , IDPOW_POWERBAR_T ) )
2007-06-28 10:47:08 -07:00
{
widgReveal ( psWScreen , IDPOW_POWERBAR_T ) ;
}
}
//hides the power bar from the display - regardless of what player requested!
void forceHidePowerBar ( void )
{
2012-12-21 07:35:35 -08:00
if ( widgGetFromID ( psWScreen , IDPOW_POWERBAR_T ) )
2007-06-28 10:47:08 -07:00
{
widgHide ( psWScreen , IDPOW_POWERBAR_T ) ;
}
}
/* Add the Proximity message buttons */
2011-03-12 17:32:15 -08:00
bool intAddProximityButton ( PROXIMITY_DISPLAY * psProxDisp , UDWORD inc )
2007-06-28 10:47:08 -07:00
{
PROXIMITY_DISPLAY * psProxDisp2 ;
UDWORD cnt ;
2010-12-22 06:02:14 -08:00
W_FORMINIT sBFormInit ;
2007-06-28 10:47:08 -07:00
sBFormInit . formID = 0 ;
sBFormInit . id = IDPROX_START + inc ;
//store the ID so we can detect which one has been clicked on
psProxDisp - > buttonID = sBFormInit . id ;
2010-01-18 09:12:58 -08:00
// loop back and find a free one!
2012-12-21 07:35:35 -08:00
if ( sBFormInit . id > = IDPROX_END )
2007-06-28 10:47:08 -07:00
{
2012-12-21 07:35:35 -08:00
for ( cnt = IDPROX_START ; cnt < IDPROX_END ; cnt + + )
{
// go down the prox msgs and see if it's free.
2010-12-20 09:16:45 -08:00
for ( psProxDisp2 = apsProxDisp [ selectedPlayer ] ; psProxDisp2 & & psProxDisp2 - > buttonID ! = cnt ; psProxDisp2 = psProxDisp2 - > psNext ) { }
2006-05-27 09:37:17 -07:00
2012-12-21 07:35:35 -08:00
if ( psProxDisp2 = = NULL ) // value was unused.
2007-06-28 10:47:08 -07:00
{
sBFormInit . id = cnt ;
break ;
}
}
2010-01-22 02:25:42 -08:00
ASSERT_OR_RETURN ( false , cnt ! = IDPROX_END , " Ran out of proximity displays " ) ;
2007-06-28 10:47:08 -07:00
}
2010-01-18 09:12:58 -08:00
ASSERT ( sBFormInit . id < IDPROX_END , " Invalid proximity message button ID %d " , ( int ) sBFormInit . id ) ;
2007-06-28 10:47:08 -07:00
sBFormInit . majorID = 0 ;
sBFormInit . style = WFORM_CLICKABLE ;
sBFormInit . width = PROX_BUTWIDTH ;
sBFormInit . height = PROX_BUTHEIGHT ;
//the x and y need to be set up each time the button is drawn - see intDisplayProximityBlips
sBFormInit . pDisplay = intDisplayProximityBlips ;
//set the data for this button
2007-11-09 13:01:23 -08:00
sBFormInit . pUserData = psProxDisp ;
2007-06-28 10:47:08 -07:00
if ( ! widgAddForm ( psWScreen , & sBFormInit ) )
{
2008-03-24 09:51:17 -07:00
return false ;
2007-06-28 10:47:08 -07:00
}
2008-03-24 09:51:17 -07:00
return true ;
2007-06-28 10:47:08 -07:00
}
/*Remove a Proximity Button - when the message is deleted*/
void intRemoveProximityButton ( PROXIMITY_DISPLAY * psProxDisp )
{
2010-01-18 09:12:58 -08:00
ASSERT ( psProxDisp - > buttonID > = IDPROX_START & & psProxDisp - > buttonID < = IDPROX_END , " Invalid proximity ID " ) ;
2007-06-28 10:47:08 -07:00
widgDelete ( psWScreen , psProxDisp - > buttonID ) ;
}
/*deals with the proximity message when clicked on*/
void processProximityButtons ( UDWORD id )
{
PROXIMITY_DISPLAY * psProxDisp ;
2012-12-21 07:35:35 -08:00
if ( ! doWeDrawProximitys ( ) )
2007-06-28 10:47:08 -07:00
{
return ;
}
//find which proximity display this relates to
psProxDisp = NULL ;
2012-12-18 06:59:49 -08:00
for ( psProxDisp = apsProxDisp [ selectedPlayer ] ; psProxDisp ; psProxDisp = psProxDisp - > psNext )
2007-06-28 10:47:08 -07:00
{
if ( psProxDisp - > buttonID = = id )
{
break ;
}
}
if ( psProxDisp )
{
//if not been read - display info
if ( ! psProxDisp - > psMessage - > read )
{
displayProximityMessage ( psProxDisp ) ;
}
}
}
2006-05-27 09:37:17 -07:00
/* Fools the widgets by setting a key value */
2012-12-21 07:35:35 -08:00
void setKeyButtonMapping ( UDWORD val )
2007-06-28 10:47:08 -07:00
{
keyButtonMapping = val ;
}
2006-05-27 09:37:17 -07:00
/*Looks through the players list of structures to see if there is one selected
of the required type . If there is more than one , they are all deselected and
2007-06-28 10:47:08 -07:00
the first one reselected */
2012-12-21 07:35:35 -08:00
STRUCTURE * intCheckForStructure ( UDWORD structType )
2007-06-28 10:47:08 -07:00
{
STRUCTURE * psStruct , * psSel = NULL ;
2012-12-21 07:32:23 -08:00
for ( psStruct = interfaceStructList ( ) ; psStruct ! = NULL ; psStruct = psStruct - > psNext )
2007-06-28 10:47:08 -07:00
{
2012-12-21 07:32:23 -08:00
if ( psStruct - > selected & & psStruct - > pStructureType - > type = = structType & & psStruct - > status = = SS_BUILT )
2007-06-28 10:47:08 -07:00
{
if ( psSel ! = NULL )
{
clearSelection ( ) ;
2008-03-24 09:51:17 -07:00
psSel - > selected = true ;
2007-06-28 10:47:08 -07:00
break ;
}
psSel = psStruct ;
}
}
2012-12-30 02:58:45 -08:00
triggerEventSelected ( ) ;
2007-06-28 10:47:08 -07:00
return psSel ;
}
2006-05-27 09:37:17 -07:00
/*Looks through the players list of droids to see if there is one selected
of the required type . If there is more than one , they are all deselected and
2007-06-28 10:47:08 -07:00
the first one reselected */
// no longer do this for constructor droids - (gleeful its-near-the-end-of-the-project hack - JOHN)
2012-12-21 07:35:35 -08:00
DROID * intCheckForDroid ( UDWORD droidType )
2007-06-28 10:47:08 -07:00
{
DROID * psDroid , * psSel = NULL ;
2007-03-16 09:20:16 -07:00
for ( psDroid = apsDroidLists [ selectedPlayer ] ; psDroid ! = NULL ; psDroid = psDroid - > psNext )
2007-06-28 10:47:08 -07:00
{
2007-03-16 09:20:16 -07:00
if ( psDroid - > selected & & psDroid - > droidType = = droidType )
2007-06-28 10:47:08 -07:00
{
if ( psSel ! = NULL )
{
2007-08-03 10:39:04 -07:00
if ( droidType ! = DROID_CONSTRUCT
& & droidType ! = DROID_CYBORG_CONSTRUCT )
2007-06-28 10:47:08 -07:00
{
clearSelection ( ) ;
}
SelectDroid ( psSel ) ;
break ;
}
psSel = psDroid ;
}
}
return psSel ;
}
// count the number of selected droids of a type
2007-05-27 15:15:10 -07:00
static SDWORD intNumSelectedDroids ( UDWORD droidType )
2007-06-28 10:47:08 -07:00
{
DROID * psDroid ;
SDWORD num ;
num = 0 ;
2012-12-21 07:35:35 -08:00
for ( psDroid = apsDroidLists [ selectedPlayer ] ; psDroid ; psDroid = psDroid - > psNext )
2007-06-28 10:47:08 -07:00
{
2007-03-16 09:20:16 -07:00
if ( psDroid - > selected & & psDroid - > droidType = = droidType )
2007-06-28 10:47:08 -07:00
{
num + = 1 ;
}
}
return num ;
}
// Check that each reticule button has the structure or droid required for it and
// enable/disable accordingly.
//
void intCheckReticuleButtons ( void )
{
STRUCTURE * psStruct ;
DROID * psDroid ;
2008-03-24 09:51:17 -07:00
ReticuleEnabled [ RETBUT_CANCEL ] . Enabled = true ;
2012-12-29 15:09:42 -08:00
ReticuleEnabled [ RETBUT_FACTORY ] . Enabled = false ;
2008-03-24 09:51:17 -07:00
ReticuleEnabled [ RETBUT_RESEARCH ] . Enabled = false ;
2012-12-29 15:09:42 -08:00
ReticuleEnabled [ RETBUT_BUILD ] . Enabled = false ;
2012-01-18 13:24:27 -08:00
ReticuleEnabled [ RETBUT_DESIGN ] . Enabled = allowDesign ;
2008-03-24 09:51:17 -07:00
ReticuleEnabled [ RETBUT_INTELMAP ] . Enabled = true ;
ReticuleEnabled [ RETBUT_COMMAND ] . Enabled = false ;
2007-06-28 10:47:08 -07:00
2008-04-21 02:19:10 -07:00
for ( psStruct = interfaceStructList ( ) ; psStruct ! = NULL ; psStruct = psStruct - > psNext )
2007-06-28 10:47:08 -07:00
{
2008-04-21 02:19:10 -07:00
if ( psStruct - > status = = SS_BUILT )
{
2012-12-21 07:35:35 -08:00
switch ( psStruct - > pStructureType - > type )
2008-04-21 02:19:10 -07:00
{
2012-12-21 07:35:35 -08:00
case REF_RESEARCH :
if ( ! missionLimboExpand ( ) )
{
ReticuleEnabled [ RETBUT_RESEARCH ] . Enabled = true ;
}
break ;
case REF_FACTORY :
case REF_CYBORG_FACTORY :
case REF_VTOL_FACTORY :
if ( ! missionLimboExpand ( ) )
{
ReticuleEnabled [ RETBUT_FACTORY ] . Enabled = true ;
}
break ;
default :
break ;
2007-06-28 10:47:08 -07:00
}
}
}
2012-12-29 15:09:42 -08:00
for ( psDroid = apsDroidLists [ selectedPlayer ] ; psDroid ! = NULL ; psDroid = psDroid - > psNext )
2007-06-28 10:47:08 -07:00
{
2008-04-21 02:19:10 -07:00
switch ( psDroid - > droidType )
{
2007-06-28 10:47:08 -07:00
case DROID_CONSTRUCT :
case DROID_CYBORG_CONSTRUCT :
2008-03-24 09:51:17 -07:00
ReticuleEnabled [ RETBUT_BUILD ] . Enabled = true ;
2007-06-28 10:47:08 -07:00
break ;
case DROID_COMMAND :
2008-03-24 09:51:17 -07:00
ReticuleEnabled [ RETBUT_COMMAND ] . Enabled = true ;
2007-06-28 10:47:08 -07:00
break ;
default :
break ;
}
}
2012-12-29 15:09:42 -08:00
for ( int i = 0 ; i < NUMRETBUTS ; i + + )
2008-04-21 02:19:10 -07:00
{
2012-12-21 07:35:35 -08:00
WIDGET * psWidget = widgGetFromID ( psWScreen , ReticuleEnabled [ i ] . id ) ;
2007-06-28 10:47:08 -07:00
2008-04-21 02:19:10 -07:00
if ( psWidget ! = NULL )
{
if ( psWidget - > type ! = WIDG_LABEL )
{
if ( ReticuleEnabled [ i ] . Enabled )
{
2007-06-28 10:47:08 -07:00
widgSetButtonState ( psWScreen , ReticuleEnabled [ i ] . id , 0 ) ;
2008-04-21 02:19:10 -07:00
}
else
{
2007-06-28 10:47:08 -07:00
widgSetButtonState ( psWScreen , ReticuleEnabled [ i ] . id , WBUT_DISABLE ) ;
}
2008-04-21 02:19:10 -07:00
if ( ReticuleEnabled [ i ] . Hidden )
{
2007-06-28 10:47:08 -07:00
widgHide ( psWScreen , ReticuleEnabled [ i ] . id ) ;
2008-04-21 02:19:10 -07:00
}
else
{
2007-06-28 10:47:08 -07:00
widgReveal ( psWScreen , ReticuleEnabled [ i ] . id ) ;
}
}
}
}
}
2006-05-27 09:37:17 -07:00
/*Checks to see if there are any research topics to do and flashes the button -
2007-06-28 10:47:08 -07:00
only if research facility is free */
2012-02-07 09:15:40 -08:00
int intGetResearchState ( )
2007-06-28 10:47:08 -07:00
{
2012-02-07 09:15:40 -08:00
bool resFree = false ;
for ( STRUCTURE * psStruct = interfaceStructList ( ) ; psStruct ! = NULL ; psStruct = psStruct - > psNext )
2007-06-28 10:47:08 -07:00
{
2007-02-10 08:39:39 -08:00
if ( psStruct - > pStructureType - > type = = REF_RESEARCH & &
2010-07-19 08:17:53 -07:00
psStruct - > status = = SS_BUILT & &
2012-02-07 09:15:40 -08:00
getResearchStats ( psStruct ) = = NULL )
2007-06-28 10:47:08 -07:00
{
2008-03-24 09:51:17 -07:00
resFree = true ;
2007-06-28 10:47:08 -07:00
break ;
}
}
2012-02-07 09:15:40 -08:00
int count = 0 ;
2007-06-28 10:47:08 -07:00
if ( resFree )
{
//set to value that won't be reached in fillResearchList
2012-02-07 09:15:40 -08:00
int index = asResearch . size ( ) + 1 ;
2007-06-28 10:47:08 -07:00
//calculate the list
2012-02-07 09:15:40 -08:00
int preCount = fillResearchList ( pList , selectedPlayer , index , MAXRESEARCH ) ;
count = preCount ;
for ( int n = 0 ; n < preCount ; + + n )
2007-06-28 10:47:08 -07:00
{
2012-02-07 09:15:40 -08:00
for ( int player = 0 ; player < MAX_PLAYERS ; + + player )
{
if ( aiCheckAlliances ( player , selectedPlayer ) & & IsResearchStarted ( & asPlayerResList [ player ] [ pList [ n ] ] ) )
{
- - count ; // An ally is already researching this topic, so don't flash the button because of it.
break ;
}
}
2007-06-28 10:47:08 -07:00
}
}
2012-02-07 09:15:40 -08:00
return count ;
2007-06-28 10:47:08 -07:00
}
2012-02-07 09:15:40 -08:00
void intNotifyResearchButton ( int prevState )
{
int newState = intGetResearchState ( ) ;
if ( newState > prevState )
{
// Set the research reticule button to flash.
flashReticuleButton ( IDRET_RESEARCH ) ;
}
else if ( newState = = 0 & & prevState > 0 )
{
stopReticuleButtonFlash ( IDRET_RESEARCH ) ;
}
}
2007-06-28 10:47:08 -07:00
// see if a reticule button is enabled
2011-03-12 17:32:15 -08:00
bool intCheckReticuleButEnabled ( UDWORD id )
2007-06-28 10:47:08 -07:00
{
2012-12-21 07:35:35 -08:00
for ( int i = 0 ; i < NUMRETBUTS ; i + + )
2007-06-28 10:47:08 -07:00
{
if ( ReticuleEnabled [ i ] . id = = id )
{
return ReticuleEnabled [ i ] . Enabled ;
}
}
2008-03-24 09:51:17 -07:00
return false ;
2007-06-28 10:47:08 -07:00
}
// Find any structure. Returns NULL if none found.
//
STRUCTURE * intFindAStructure ( void )
{
STRUCTURE * Struct ;
// First try and find a factory.
2012-12-21 07:35:35 -08:00
Struct = intGotoNextStructureType ( REF_FACTORY , false , false ) ;
if ( Struct = = NULL )
{
2007-06-28 10:47:08 -07:00
// If that fails then look for a command center.
2012-12-21 07:35:35 -08:00
Struct = intGotoNextStructureType ( REF_HQ , false , false ) ;
if ( Struct = = NULL )
{
2007-06-28 10:47:08 -07:00
// If that fails then look for a any structure.
2012-12-21 07:35:35 -08:00
Struct = intGotoNextStructureType ( REF_ANY , false , false ) ;
2007-06-28 10:47:08 -07:00
}
}
return Struct ;
}
// Look through the players structures and find the next one of type structType.
//
2012-12-21 07:35:35 -08:00
STRUCTURE * intGotoNextStructureType ( UDWORD structType , bool JumpTo , bool CancelDrive )
2007-06-28 10:47:08 -07:00
{
STRUCTURE * psStruct ;
2011-03-12 17:32:15 -08:00
bool Found = false ;
2007-06-28 10:47:08 -07:00
2012-12-21 07:35:35 -08:00
if ( ( SWORD ) structType ! = CurrentStructType )
{
2007-06-28 10:47:08 -07:00
CurrentStruct = NULL ;
CurrentStructType = ( SWORD ) structType ;
}
2012-12-21 07:35:35 -08:00
if ( CurrentStruct ! = NULL )
{
2007-06-28 10:47:08 -07:00
psStruct = CurrentStruct ;
2012-12-21 07:35:35 -08:00
}
else
{
2007-06-28 10:47:08 -07:00
psStruct = interfaceStructList ( ) ;
}
2012-12-21 07:35:35 -08:00
for ( ; psStruct ! = NULL ; psStruct = psStruct - > psNext )
2007-06-28 10:47:08 -07:00
{
2012-12-21 07:32:23 -08:00
if ( ( psStruct - > pStructureType - > type = = structType | | structType = = REF_ANY ) & & psStruct - > status = = SS_BUILT )
2007-06-28 10:47:08 -07:00
{
2012-12-21 07:35:35 -08:00
if ( psStruct ! = CurrentStruct )
{
if ( CancelDrive )
{
2007-06-28 10:47:08 -07:00
clearSelection ( ) ;
2012-12-21 07:35:35 -08:00
}
else
{
2007-06-28 10:47:08 -07:00
clearSel ( ) ;
}
2008-03-24 09:51:17 -07:00
psStruct - > selected = true ;
2007-06-28 10:47:08 -07:00
CurrentStruct = psStruct ;
2008-03-24 09:51:17 -07:00
Found = true ;
2007-06-28 10:47:08 -07:00
break ;
}
}
}
// Start back at the begining?
2012-12-21 07:35:35 -08:00
if ( ( ! Found ) & & ( CurrentStruct ! = NULL ) )
{
2012-12-21 07:32:23 -08:00
for ( psStruct = interfaceStructList ( ) ; psStruct ! = CurrentStruct & & psStruct ! = NULL ; psStruct = psStruct - > psNext )
2007-06-28 10:47:08 -07:00
{
2012-12-21 07:32:23 -08:00
if ( ( psStruct - > pStructureType - > type = = structType | | structType = = REF_ANY ) & & psStruct - > status = = SS_BUILT )
2007-06-28 10:47:08 -07:00
{
2012-12-21 07:35:35 -08:00
if ( psStruct ! = CurrentStruct )
{
if ( CancelDrive )
{
2007-06-28 10:47:08 -07:00
clearSelection ( ) ;
2012-12-21 07:35:35 -08:00
}
else
{
2007-06-28 10:47:08 -07:00
clearSel ( ) ;
}
2008-03-24 09:51:17 -07:00
psStruct - > selected = true ;
2007-06-28 10:47:08 -07:00
CurrentStruct = psStruct ;
break ;
}
}
}
}
// Center it on screen.
2012-12-21 07:35:35 -08:00
if ( ( CurrentStruct ) & & ( JumpTo ) )
{
2007-12-15 07:39:29 -08:00
intSetMapPos ( CurrentStruct - > pos . x , CurrentStruct - > pos . y ) ;
2007-06-28 10:47:08 -07:00
}
2012-12-30 02:58:45 -08:00
triggerEventSelected ( ) ;
2007-06-28 10:47:08 -07:00
return CurrentStruct ;
}
// Look through the players droids and find the next one of type droidType.
// If Current=NULL then start at the beginning overwise start at Current.
//
2012-12-21 07:35:35 -08:00
DROID * intGotoNextDroidType ( DROID * CurrDroid , DROID_TYPE droidType , bool AllowGroup )
2007-06-28 10:47:08 -07:00
{
DROID * psDroid ;
2011-03-12 17:32:15 -08:00
bool Found = false ;
2007-06-28 10:47:08 -07:00
2012-12-21 07:35:35 -08:00
if ( CurrDroid ! = NULL )
2012-02-25 16:21:29 -08:00
{
2007-06-28 10:47:08 -07:00
CurrentDroid = CurrDroid ;
}
2012-12-21 07:32:23 -08:00
if ( droidType ! = CurrentDroidType & & droidType ! = DROID_ANY )
2012-02-25 16:21:29 -08:00
{
2007-06-28 10:47:08 -07:00
CurrentDroid = NULL ;
2012-12-21 07:32:23 -08:00
CurrentDroidType = droidType ;
2007-06-28 10:47:08 -07:00
}
2012-12-21 07:35:35 -08:00
if ( CurrentDroid ! = NULL )
2012-02-25 16:21:29 -08:00
{
2007-06-28 10:47:08 -07:00
psDroid = CurrentDroid ;
2012-02-25 16:21:29 -08:00
}
else
{
2007-06-28 10:47:08 -07:00
psDroid = apsDroidLists [ selectedPlayer ] ;
}
2012-12-21 07:35:35 -08:00
for ( ; psDroid ! = NULL ; psDroid = psDroid - > psNext )
2007-06-28 10:47:08 -07:00
{
2012-12-21 07:32:23 -08:00
if ( ( psDroid - > droidType = = droidType
| | ( droidType = = DROID_ANY & & ( psDroid - > droidType ! = DROID_TRANSPORTER & & psDroid - > droidType ! = DROID_SUPERTRANSPORTER ) ) )
& & ( psDroid - > group = = UBYTE_MAX | | AllowGroup ) )
2007-06-28 10:47:08 -07:00
{
2012-12-21 07:35:35 -08:00
if ( psDroid ! = CurrentDroid )
2012-02-25 16:21:29 -08:00
{
2007-06-28 10:47:08 -07:00
clearSel ( ) ;
SelectDroid ( psDroid ) ;
CurrentDroid = psDroid ;
2008-03-24 09:51:17 -07:00
Found = true ;
2007-06-28 10:47:08 -07:00
break ;
}
}
}
// Start back at the begining?
2012-12-21 07:35:35 -08:00
if ( ( ! Found ) & & ( CurrentDroid ! = NULL ) )
2012-02-25 16:21:29 -08:00
{
2012-12-21 07:35:35 -08:00
for ( psDroid = apsDroidLists [ selectedPlayer ] ; ( psDroid ! = CurrentDroid ) & & ( psDroid ! = NULL ) ; psDroid = psDroid - > psNext )
2007-06-28 10:47:08 -07:00
{
2012-12-21 07:32:23 -08:00
if ( ( psDroid - > droidType = = droidType | |
2012-12-21 07:35:35 -08:00
( ( droidType = = DROID_ANY ) & & ( psDroid - > droidType ! = DROID_TRANSPORTER & & psDroid - > droidType ! = DROID_SUPERTRANSPORTER ) ) ) & &
( ( psDroid - > group = = UBYTE_MAX ) | | AllowGroup ) )
2007-06-28 10:47:08 -07:00
{
2012-12-21 07:35:35 -08:00
if ( psDroid ! = CurrentDroid )
2012-02-25 16:21:29 -08:00
{
2007-06-28 10:47:08 -07:00
clearSel ( ) ;
SelectDroid ( psDroid ) ;
CurrentDroid = psDroid ;
2008-03-24 09:51:17 -07:00
Found = true ;
2007-06-28 10:47:08 -07:00
break ;
}
}
}
}
2010-03-11 04:17:15 -08:00
if ( Found = = true )
{
psCBSelectedDroid = CurrentDroid ;
eventFireCallbackTrigger ( ( TRIGGER_TYPE ) CALL_DROID_SELECTED ) ;
psCBSelectedDroid = NULL ;
2007-06-28 10:47:08 -07:00
// Center it on screen.
2012-12-21 07:35:35 -08:00
if ( CurrentDroid )
2012-02-25 16:21:29 -08:00
{
2007-12-15 07:39:29 -08:00
intSetMapPos ( CurrentDroid - > pos . x , CurrentDroid - > pos . y ) ;
2007-06-28 10:47:08 -07:00
}
return CurrentDroid ;
}
return NULL ;
}
//access function for selected object in the interface
2012-12-21 07:35:35 -08:00
BASE_OBJECT * getCurrentSelected ( void )
2007-06-28 10:47:08 -07:00
{
return psObjSelected ;
}
2010-10-20 21:55:55 -07:00
// Checks if a coordinate is over the build menu
2011-03-12 17:32:15 -08:00
bool CoordInBuild ( int x , int y )
2010-10-20 21:55:55 -07:00
{
// This measurement is valid for the menu, so the buildmenu_height
// value is used to "nudge" it all upwards from the command menu.
// FIXME: hardcoded value (?)
const int buildmenu_height = 300 ;
Vector2f pos ;
2012-12-21 07:35:35 -08:00
2010-10-20 21:55:55 -07:00
pos . x = x - RET_X ;
pos . y = y - RET_Y + buildmenu_height ; // guesstimation
2012-04-02 20:56:20 -07:00
if ( ( pos . x < 0 | | pos . y < 0 | | pos . x > = RET_FORMWIDTH | | pos . y > = buildmenu_height ) | | ! SecondaryWindowUp )
2010-10-20 21:55:55 -07:00
{
return false ;
}
return true ;
}