mirror of
https://github.com/scp-fs2open/fs2open.github.com.git
synced 2026-11-10 12:41:35 -10:00
2372 lines
54 KiB
C++
2372 lines
54 KiB
C++
/*
|
|
* Created by WMCoolmon for the FreeSpace2 Source Code Project.
|
|
* You may not sell or otherwise commercially exploit the source or things you
|
|
* create based on the source.
|
|
*/
|
|
|
|
/*
|
|
* $Logfile: /Freespace2/code/hud/hudparse.cpp $
|
|
* $Revision: 2.43.2.4 $
|
|
* $Date: 2007-01-07 13:18:32 $
|
|
* $Author: taylor $
|
|
*
|
|
* Contains code to parse hud gauge locations
|
|
*
|
|
* $Log: not supported by cvs2svn $
|
|
* Revision 2.43.2.3 2006/12/07 18:17:19 taylor
|
|
* add "$Weapons Energy Text:" to hud_gauges.tbl so that the low energy text can be positioned as well (Mantis bug #1166)
|
|
*
|
|
* Revision 2.43.2.2 2006/09/20 04:59:29 taylor
|
|
* the resolution checks needed to be based on the unscaled res since you would have to include correct sizes for every single resolution otherwise (fixes a bug noticed in WCS)
|
|
*
|
|
* Revision 2.43.2.1 2006/09/11 01:15:04 taylor
|
|
* fixes for stuff_string() bounds checking
|
|
*
|
|
* Revision 2.43 2006/04/20 06:32:07 Goober5000
|
|
* proper capitalization according to Volition
|
|
*
|
|
* Revision 2.42 2006/02/13 00:20:45 Goober5000
|
|
* more tweaks, plus clarification of checks for the existence of files
|
|
* --Goober5000
|
|
*
|
|
* Revision 2.41 2005/12/29 08:08:33 wmcoolmon
|
|
* Codebase commit, most notably including objecttypes.tbl
|
|
*
|
|
* Revision 2.40 2005/12/28 22:17:01 taylor
|
|
* deal with cf_find_file_location() changes
|
|
* add a central parse_modular_table() function which anything can use
|
|
* fix up weapon_expl so that it can properly handle modular tables and LOD count changes
|
|
* add support for for a fireball TBM (handled a little different than a normal TBM is since it only changes rather than adds)
|
|
*
|
|
* Revision 2.39 2005/12/21 08:27:37 taylor
|
|
* add the name of the modular table about to be parsed to the debug log
|
|
* a missing weapon_expl table should just be a note in the debug log rather than a popup warning
|
|
*
|
|
* Revision 2.38 2005/12/06 03:17:48 taylor
|
|
* cleanup some debug log messages:
|
|
* note that a nprintf() with "Warning" or "General" is basically the same thing as mprintf()
|
|
* make sure that OpenAL init failures always get to the debug log
|
|
*
|
|
* Revision 2.37 2005/11/08 01:03:59 wmcoolmon
|
|
* More warnings instead of Int3s/Asserts, better Lua scripting, weapons_expl.tbl is no longer needed nor read, added "$Disarmed ImpactSnd:", fire-beam fix
|
|
*
|
|
* Revision 2.36 2005/10/28 14:47:16 taylor
|
|
* fix issue where GR_640 based non-standard resolutions (ie. 800x600) would use GR_1024 screen coordinates/sizes
|
|
*
|
|
* Revision 2.35 2005/09/29 04:26:08 Goober5000
|
|
* parse fixage
|
|
* --Goober5000
|
|
*
|
|
* Revision 2.34 2005/09/25 05:13:06 Goober5000
|
|
* hopefully complete species upgrade
|
|
* --Goober5000
|
|
*
|
|
* Revision 2.33 2005/07/18 03:44:01 taylor
|
|
* cleanup hudtargetbox rendering from that total hack job that had been done on it (fixes wireframe view as well)
|
|
* more non-standard res fixing
|
|
* - I think everything should default to resize now (much easier than having to figure that crap out)
|
|
* - new mouse_get_pos_unscaled() function to return 1024x768/640x480 relative values so we don't have to do it later
|
|
* - lots of little cleanups which fix several strange offset/size problems
|
|
* - fix gr_resize/unsize_screen_pos() so that it won't wrap on int (took too long to track this down)
|
|
*
|
|
* Revision 2.32 2005/07/13 02:01:29 Goober5000
|
|
* fixed a bunch of "issues" caused by me with the species stuff
|
|
* --Goober5000
|
|
*
|
|
* Revision 2.31 2005/07/13 00:44:22 Goober5000
|
|
* improved species support and removed need for #define
|
|
* --Goober5000
|
|
*
|
|
* Revision 2.30 2005/07/09 03:02:07 wmcoolmon
|
|
* Added fixes for custom gauges discussed in the recent thread
|
|
*
|
|
* Revision 2.29 2005/04/28 01:34:33 wmcoolmon
|
|
* stuff_byte to stuff_ubyte; does the same thing, but with a better name.
|
|
*
|
|
* Revision 2.28 2005/04/24 08:27:17 Goober5000
|
|
* fix0red the CVS log
|
|
* --Goober5000
|
|
*
|
|
* Revision 2.27 2005/04/08 20:03:59 wmcoolmon
|
|
* *crosses fingers*
|
|
*
|
|
* Revision 2.26 2005/03/06 11:23:45 wmcoolmon
|
|
* RE-fixed stuff. Ogg support. Briefings.
|
|
*
|
|
* Revision 2.25 2005/02/27 23:27:50 wmcoolmon
|
|
* Some HUD work
|
|
*
|
|
* Revision 2.24 2005/02/14 23:59:23 taylor
|
|
* make hudparse GCC 3.4 friendly (WMCoolmon way want to check this with tbl)
|
|
* fix OSX compile problem
|
|
* debug message in weapons_page_in() should have been real debug message
|
|
*
|
|
* Revision 2.23 2005/02/04 23:29:32 taylor
|
|
* merge with Linux/OSX tree - p0204-3
|
|
*
|
|
* Revision 2.22 2005/01/12 00:18:00 phreak
|
|
* nude hud? was this some kind of freudian slip of a sort or what?
|
|
*
|
|
* Revision 2.21 2005/01/01 19:37:05 wmcoolmon
|
|
* Erg, always make sure CVS is completely up-to-date.
|
|
*
|
|
* Revision 2.20 2005/01/01 07:18:47 wmcoolmon
|
|
* NEW_HUD stuff, turned off this time. :) It's in a state of disrepair at the moment, doesn't show anything.
|
|
*
|
|
* Revision 2.19 2004/12/25 09:27:41 wmcoolmon
|
|
* Fix to modular tables workaround with Fs2NetD + Sync to current NEW_HUD code
|
|
*
|
|
* Revision 2.18 2004/12/24 05:07:05 wmcoolmon
|
|
* NEW_HUD compiles now. :)
|
|
*
|
|
* Revision 2.17 2004/12/23 23:26:35 wmcoolmon
|
|
* Proposed HUD system stuffs - within NEW_HUD defines.
|
|
*
|
|
* Revision 2.16 2004/12/22 09:09:38 wmcoolmon
|
|
* Quick fix to hudparse.cpp; If this causes any problems, roll it back and I'll take another look at it.
|
|
*
|
|
* Revision 2.15 2004/11/27 10:50:32 taylor
|
|
* correct positions for default graphics with no table
|
|
* compiler warning fix
|
|
*
|
|
* Revision 2.14 2004/09/05 19:23:24 Goober5000
|
|
* fixed a few warnings
|
|
* --Goober5000
|
|
*
|
|
* Revision 2.13 2004/07/26 20:47:32 Kazan
|
|
* remove MCD complete
|
|
*
|
|
* Revision 2.12 2004/07/17 09:25:59 taylor
|
|
* add CF_SORT_REVERSE to real sort routine, makes CF_SORT_TIME work again
|
|
*
|
|
* Revision 2.11 2004/07/12 16:32:49 Kazan
|
|
* MCD - define _MCD_CHECK to use memory tracking
|
|
*
|
|
* Revision 2.10 2004/06/26 03:19:53 wmcoolmon
|
|
* Displayed escorts now settable up to MAX_COMPLETE_ESCORT_LIST via "$Max Escort Ships:" in hud_gauges.tbl
|
|
* Escort list is now hud_gauges.tbl compatible.
|
|
*
|
|
* Revision 2.9 2004/06/18 04:59:54 wmcoolmon
|
|
* Only used weapons paged in instead of all, fixed music box in FRED, sound quality settable with SoundSampleRate and SoundSampleBits registry values
|
|
*
|
|
* Revision 2.8 2004/06/08 01:12:58 wmcoolmon
|
|
* Fix0red the current target's hud info appearing in the corner of the screen.
|
|
*
|
|
* Revision 2.7 2004/06/08 00:35:43 wmcoolmon
|
|
* Added +Color: option for custom gauges.
|
|
*
|
|
* Revision 2.6 2004/06/05 23:31:12 wmcoolmon
|
|
* More HUD update stuff. Coordinates are now floats, addparent is now obsolete.
|
|
*
|
|
* Revision 2.5 2004/06/01 07:31:56 wmcoolmon
|
|
* Lotsa stuff. Custom gauges w/ ANIs support added, SEXPs to set gauge text, gauge image frames, and gauge coords. These SEXPs and toggle-hud reside in the Hud/change category.
|
|
*
|
|
* Revision 2.4 2004/05/31 08:32:25 wmcoolmon
|
|
* Custom HUD support, better loading, etc etc.
|
|
*
|
|
* Revision 2.3 2004/05/30 08:04:49 wmcoolmon
|
|
* Final draft of the HUD parsing system structure. May change how individual coord positions are specified in the TBL. -C
|
|
*
|
|
* Revision 2.2 2004/05/29 04:09:04 wmcoolmon
|
|
* First bugfix in this! Don't want FreeSpace exiting if it can't load a hud_gauge file.
|
|
*
|
|
* Revision 2.1 2004/05/29 03:02:53 wmcoolmon
|
|
* Added HUD gauges placement table, "hud_gauges.tbl" or "*-hdg.tbm" table module
|
|
*
|
|
*/
|
|
|
|
#include <cstddef>
|
|
|
|
#include "parse/parselo.h"
|
|
#include "graphics/2d.h"
|
|
#include "localization/localize.h"
|
|
#include "hud/hud.h"
|
|
#include "hud/hudescort.h"
|
|
//#include "weapon/emp.h"
|
|
#include "hud/hudparse.h" //Duh.
|
|
#include "ship/ship.h" //for ship struct
|
|
#include "graphics/font.h" //for gr_force_fit_string
|
|
|
|
|
|
//Global stuffs
|
|
#ifdef NEW_HUD
|
|
hud_info *current_hud = NULL;
|
|
//Storage for the default and ship huds
|
|
hud_info default_hud;
|
|
hud_info ship_huds[MAX_SHIP_CLASSES];
|
|
#else
|
|
hud_info *current_hud = NULL; //If not set, it's NULL. This should always be null outside of a mission.
|
|
hud_info default_hud;
|
|
hud_info ship_huds[MAX_SHIP_CLASSES];
|
|
#endif
|
|
extern int ships_inited; //Need this
|
|
|
|
#ifndef NEW_HUD
|
|
//Set coord_x or coord_y to -1 to not change that value
|
|
//void resize_coords(int* values, float* factors);
|
|
//void set_coords_if_clear(int* dest_coords, int coord_x, int coord_y = -1);
|
|
|
|
//ADD YOUR VARIABLES HERE
|
|
//Gauges MUST come first, and all variables MUST be in the hud struct.
|
|
|
|
//Use this when setting gauge variables. It gets the OFFSET of the value in the hud_info struct
|
|
#define HUD_VAR(a) offsetof(hud_info, a)
|
|
|
|
gauge_info gauges[MAX_HUD_GAUGE_TYPES] = {
|
|
{ NULL, HUD_VAR(Player_shield_coords), "$Player Shield:", 396, 379, 634, 670, 0, 0, 0, 0, 0, -1, -1 },
|
|
{ NULL, HUD_VAR(Target_shield_coords), "$Target Shield:", 142, 379, 292, 670, 0, 0, 0, 0, 0, -1, -1 },
|
|
{ NULL, HUD_VAR(Shield_mini_coords), "$Shield Mini:", 305, 291, 497, 470, 0, HUD_VAR(Shield_mini_fname), 0, 0, 0, -1, -1 },
|
|
{ NULL, HUD_VAR(Aburn_coords), "$Afterburner Energy:", 171, 265, 274, 424, HUD_VAR(Aburn_size), HUD_VAR(Aburn_fname), 0, 0, 0, -1, -1 },
|
|
{ NULL, HUD_VAR(Wenergy_coords), "$Weapons Energy:", 416, 265, 666, 424, HUD_VAR(Wenergy_size), HUD_VAR(Wenergy_fname), 0, 0, 0, -1, -1 },
|
|
{ NULL, HUD_VAR(Wenergy_text_coords), "$Weapons Energy Text:", 439, 318, 708, 509, 0, 0, 0, 0, 0, -1, -1 },
|
|
{ NULL, HUD_VAR(Escort_coords), "$Escort List:", 486, 206, 865, 330, 0, HUD_VAR(Escort_filename[0]), 0, HUD_VAR(Escort_htext), 0, -1, -1 },
|
|
|
|
//Mini-gauges
|
|
{ &gauges[2], HUD_VAR(Hud_mini_3digit), "$Text Base:", 310, 298, 502, 477, 0, 0, 0, 0, 0, -1, -1 },
|
|
{ &gauges[2], HUD_VAR(Hud_mini_1digit), "$Text 1 digit:", 316, 298, 511, 477, 0, 0, 0, 0, 0, -1, -1 },
|
|
// { &gauges[2], HUD_VAR(Hud_mini_2digit), "$Text 2 digit:", 213, 298, 346, 477, 0, 0, 0, 0, 0, -1, -1 },
|
|
{ &gauges[2], HUD_VAR(Hud_mini_2digit), "$Text 2 digit:", 313, 298, 506, 477, 0, 0, 0, 0, 0, -1, -1 },
|
|
{ &gauges[5], HUD_VAR(Escort_htext_coords), "$Header Text:", 489, 208, 869, 331, 0, 0, 0, 0, 0, -1, -1 },
|
|
{ &gauges[5], HUD_VAR(Escort_list), "$List:", 0, 12, 0, 13, 0, 0, 0, 0, 0, HG_NOADD, -1 },
|
|
{ &gauges[5], HUD_VAR(Escort_entry), "$Ship:", 0, 11, 0, 11, 0, HUD_VAR(Escort_filename[1]), 0, 0, 0, HG_NOADD, -1 },
|
|
{ &gauges[5], HUD_VAR(Escort_entry_last), "$Last Ship:", 0, 11, 0, 11, 0, HUD_VAR(Escort_filename[2]), 0, 0, 0, HG_NOADD, -1 },
|
|
{ &gauges[5], HUD_VAR(Escort_name), "$Ship Name:", 3, 0, 4, 0, 0, 0, 0, 0, 0, HG_NOADD, -1 },
|
|
{ &gauges[5], HUD_VAR(Escort_integrity), "$Ship Hull:", 128, 0, 116, 0, 0, 0, 0, 0, 0, HG_NOADD, -1 },
|
|
{ &gauges[5], HUD_VAR(Escort_status), "$Ship Status:", -12, 0, -11, 0, 0, 0, 0, 0, 0, HG_NOADD, -1 }
|
|
};
|
|
|
|
//Number of gauges
|
|
int Num_gauge_types = 17;
|
|
int Num_custom_gauges = 0;
|
|
#endif
|
|
#ifdef NEW_HUD
|
|
/*
|
|
int hud_escort_list(gauge_data* cg, ship* gauge_owner)
|
|
{
|
|
if ( !Show_escort_view ) {
|
|
return -1;
|
|
}
|
|
|
|
if ( !Num_escort_ships ) {
|
|
return -1;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
int hud_escort_ship(gauge_data* cg, ship* gauge_owner)
|
|
{
|
|
int curr_item = cg->get_update_num();
|
|
if(curr_item < Num_escort_ships)
|
|
{
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
int hud_escort_ship_name()
|
|
{
|
|
return 1;
|
|
}*/
|
|
/*
|
|
int hud_player_shield(gauge_data* cg, ship* gauge_owner)
|
|
{
|
|
//Don't show if object isn't a ship
|
|
if(Objects[gauge_owner->objnum].type != OBJ_SHIP)
|
|
{
|
|
return HG_RETURNNODRAW;
|
|
}
|
|
|
|
//Or current ship has primitive sensors
|
|
if(gauge_owner->flags & SF2_PRIMITIVE_SENSORS)
|
|
{
|
|
return HG_RETURNNODRAW;
|
|
}
|
|
|
|
object* targetp = Objects[Ai_info[gauge_owner->ai_index].target_objnum];
|
|
float max_shield = get_max_shield_quad(targetp);
|
|
if(targetp->flags & OF_NO_SHIELDS)
|
|
{
|
|
return HG_RETURNLASTUPDATE;
|
|
}
|
|
}*/
|
|
|
|
int hud_weapon_energy_text(gauge_data* cg, ship* gauge_owner)
|
|
{
|
|
static float old_percent_left;
|
|
static ship* old_owner;
|
|
float percent_left;
|
|
|
|
percent_left = gauge_owner->weapon_energy/Ship_info[gauge_owner->ship_info_index].max_weapon_reserve;
|
|
|
|
if ( percent_left > 1 )
|
|
{
|
|
percent_left = 1.0f;
|
|
}
|
|
|
|
//If it's the same, don't bother updating info
|
|
if(percent_left == old_percent_left && old_owner == gauge_owner)
|
|
{
|
|
//mprintf(("REDRAWING WEAPONS ENERGY LIKE A GOOD FUNCTION"));
|
|
return 2;
|
|
}
|
|
|
|
old_percent_left = percent_left;
|
|
old_owner = gauge_owner;
|
|
|
|
if ( percent_left <= 0.3 )
|
|
{
|
|
if ( percent_left < 0.1 ) {
|
|
gr_init_alphacolor(&cg->g_color, 200, 0, 0, 255);
|
|
}
|
|
sprintf(cg->text,XSTR( "%d%%", 326), fl2i(percent_left*100+0.5f));
|
|
hud_num_make_mono(cg->text);
|
|
}
|
|
else
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
int hud_weapon_energy(gauge_data* cg, ship* gauge_owner)
|
|
{
|
|
static float old_percent_left;
|
|
static ship* old_owner;
|
|
float percent_left;
|
|
|
|
if ( Player_ship->weapons.num_primary_banks <= 0 )
|
|
{
|
|
return HG_RETURNNODRAW;
|
|
}
|
|
|
|
// also leave if no energy can be stored for weapons - Goober5000
|
|
if (!ship_has_energy_weapons(gauge_owner))
|
|
return HG_RETURNNODRAW;
|
|
|
|
percent_left = gauge_owner->weapon_energy/Ship_info[gauge_owner->ship_info_index].max_weapon_reserve;
|
|
if ( percent_left > 1 )
|
|
{
|
|
percent_left = 1.0f;
|
|
}
|
|
|
|
//If it's the same, don't bother updating info
|
|
if(percent_left == old_percent_left && old_owner == gauge_owner)
|
|
{
|
|
//mprintf(("REDRAWING WEAPONS ENERGY LIKE A GOOD FUNCTION"));
|
|
return HG_RETURNREDRAW;
|
|
}
|
|
|
|
old_percent_left = percent_left;
|
|
old_owner = gauge_owner;
|
|
|
|
//wtf is this??
|
|
/* if ( percent_left <= 0.3 ) {
|
|
char buf[32];
|
|
if ( percent_left < 0.1 ) {
|
|
gr_set_color_fast(&Color_bright_red);
|
|
}
|
|
sprintf(buf,XSTR( "%d%%", 326), fl2i(percent_left*100+0.5f));
|
|
hud_num_make_mono(buf);
|
|
gr_string(Weapon_energy_text_coords[gr_screen.res][0], Weapon_energy_text_coords[gr_screen.res][1], buf);
|
|
}*/
|
|
|
|
int clip_h = fl2i( (1.0f - percent_left) * cg->image_size[0] + 0.5f );
|
|
|
|
//Background
|
|
cg->frame[0] = 2;
|
|
cg->frame_attrib[0][2] = cg->image_size[0] - clip_h;
|
|
|
|
//The gauge
|
|
cg->frame[1] = 3;
|
|
cg->frame_attrib[1][0] = clip_h;
|
|
|
|
return HG_RETURNLASTUPDATE;
|
|
}
|
|
|
|
int hud_afterburner_energy(gauge_data* cg, ship* gauge_owner)
|
|
{
|
|
Assert(gauge_owner);
|
|
static float old_percent_left = 0.0f;
|
|
static ship* old_owner = NULL;
|
|
|
|
//No afterburner? Don't draw it
|
|
if ( !(Ship_info[gauge_owner->ship_info_index].flags & SIF_AFTERBURNER) )
|
|
{
|
|
//Don't draw the gauge at all
|
|
return HG_RETURNNODRAW;
|
|
}
|
|
|
|
float percent_left;
|
|
percent_left = gauge_owner->afterburner_fuel/Ship_info[gauge_owner->ship_info_index].afterburner_fuel_capacity;
|
|
|
|
//Can't have over 100% displayed in gauge
|
|
if ( percent_left > 1 )
|
|
{
|
|
percent_left = 1.0f;
|
|
}
|
|
|
|
//If it's the same, don't bother updating info
|
|
if(percent_left == old_percent_left && old_owner == gauge_owner)
|
|
{
|
|
//mprintf(("REDRAWING AFTERBURNER LIKE A GOOD FUNCTION"));
|
|
//Redraw the gauge with the current info
|
|
return HG_RETURNREDRAW;
|
|
}
|
|
|
|
old_percent_left = percent_left;
|
|
old_owner = gauge_owner;
|
|
|
|
//How much do we want to clip off
|
|
int clip_h = fl2i( (1.0f - percent_left) * cg->image_size[0] + 0.5f );
|
|
|
|
//Set the clipping for the background
|
|
cg->frame[0] = 0;
|
|
cg->frame_attrib[0][2] = cg->image_size[0] - clip_h; //From the bottom
|
|
|
|
//Set the clipping for the actual energy stuff
|
|
cg->frame[1] = 1;
|
|
cg->frame_attrib[1][0] = clip_h; //From the top
|
|
|
|
//Only draw once
|
|
return HG_RETURNLASTUPDATE;
|
|
}
|
|
/*
|
|
int hud_shield_mini(gauge_data* cg, ship* gauge_owner)
|
|
{
|
|
int hud_shield_icon(gauge_data* cg, ship* gauge_owner)
|
|
{
|
|
float max_shield;
|
|
object* objp = &Objects[gauge_info->target_objnum];
|
|
|
|
max_shield = get_max_shield_quad(objp);
|
|
|
|
for ( int i = 0; i < MAX_SHIELD_SECTIONS; i++ ) {
|
|
|
|
if ( objp->flags & OF_NO_SHIELDS ) {
|
|
break;
|
|
}
|
|
|
|
if ( objp->shield_quadrant[Quadrant_xlate[i]] < 0.1f ) {
|
|
continue;
|
|
}
|
|
|
|
range = HUD_color_alpha;
|
|
hud_color_index = fl2i( (objp->shield_quadrant[Quadrant_xlate[i]] / max_shield) * range + 0.5);
|
|
Assert(hud_color_index >= 0 && hud_color_index <= range);
|
|
|
|
if ( hud_color_index < 0 ) {
|
|
hud_color_index = 0;
|
|
}
|
|
if ( hud_color_index >= HUD_NUM_COLOR_LEVELS ) {
|
|
hud_color_index = HUD_NUM_COLOR_LEVELS - 1;
|
|
}
|
|
|
|
if ( hud_gauge_maybe_flash(HUD_TARGET_MINI_ICON) == 1) {
|
|
// hud_set_bright_color();
|
|
hud_set_gauge_color(HUD_TARGET_MINI_ICON, HUD_C_BRIGHT);
|
|
} else {
|
|
// gr_set_color_fast(&HUD_color_defaults[hud_color_index]);
|
|
hud_set_gauge_color(HUD_TARGET_MINI_ICON, hud_color_index);
|
|
}
|
|
|
|
frames[i] = Shield_mini_gauge.first_frame + i;
|
|
}
|
|
|
|
return 1;
|
|
}*/
|
|
#endif
|
|
|
|
//Loads defaults for if a hud isn't specified in the table
|
|
#ifdef NEW_HUD
|
|
static void load_hud_defaults(hud* hud)
|
|
{
|
|
/* gauge_data* cgp = NULL;
|
|
|
|
//Shield mini
|
|
gauge_data *cg = hud->add_gauge("Shield Mini", 497, 470);
|
|
cg->set_image("targhit1");
|
|
|
|
cg = hud->add_gauge("Afterburner Energy", 274, 424);
|
|
cg->set_image("2_energy2");
|
|
cg->update_func = hud_afterburner_energy;
|
|
|
|
cgp = cg = hud->add_gauge("Weapons Energy", 666, 424);
|
|
cg->set_image("2_energy2");
|
|
cg->update_func = hud_weapon_energy;
|
|
|
|
//The cgp assigns the parent
|
|
Assert(cgp != NULL);
|
|
Assert(cg != NULL);
|
|
cg = hud->add_gauge("Weapons Energy Text", 42, 85, cgp);
|
|
cg->update_func = hud_weapon_energy_text;*/
|
|
|
|
//Escort stuff
|
|
/* cgp = cg = hud->add_gauge("Escort List", 865, 330);
|
|
cg->set_image("escort1");
|
|
cg->update_func = hud_escort_ship;
|
|
|
|
cg = hud->add_gauge("Escort Header", 4, 1, cgp);
|
|
strcpy(cg->text, XSTR( "monitoring", 285));
|
|
|
|
cgp = hud->add_gauge("Escort Ships", 12, 13, cgp);
|
|
|
|
cgp = cg = hud->add_gauge("Escort Ship", 0, 11, cgp);
|
|
cg->set_image("escort2");
|
|
|
|
hud->add_gauge("Escort Ship Name", 4, 0, cgp);
|
|
hud->add_gauge("Escort Ship Integrity", 116, 0, cgp);
|
|
hud->add_gauge("Escort Ship Status", -11, 0, cgp);*/
|
|
}
|
|
#else
|
|
static void load_hud_defaults(hud_info *hud)
|
|
{
|
|
//X values
|
|
if(gr_screen.res == GR_640)
|
|
{
|
|
//Size defaults
|
|
hud->Aburn_size[0] = hud->Wenergy_size[0] = 60;
|
|
|
|
//Image defaults
|
|
strcpy(hud->Aburn_fname, "energy2");
|
|
strcpy(hud->Wenergy_fname, "energy2");
|
|
|
|
/**************************************************/
|
|
//DO NOT CHANGE
|
|
hud->resolution[0] = 640;
|
|
hud->resolution[1] = 480;
|
|
/**************************************************/
|
|
}
|
|
else
|
|
{
|
|
//Size defaults
|
|
hud->Aburn_size[0] = hud->Wenergy_size[0] = 96;
|
|
|
|
//Image defaults
|
|
strcpy(hud->Aburn_fname, "2_energy2");
|
|
strcpy(hud->Wenergy_fname, "2_energy2");
|
|
|
|
/**************************************************/
|
|
//DO NOT CHANGE
|
|
hud->resolution[0] = 1024;
|
|
hud->resolution[1] = 768;
|
|
/**************************************************/
|
|
}
|
|
|
|
//Neither
|
|
strcpy(hud->Shield_mini_fname, "targhit1");
|
|
strcpy(hud->Escort_filename[0], "escort1");
|
|
strcpy(hud->Escort_filename[1], "escort2");
|
|
strcpy(hud->Escort_filename[2], "escort3");
|
|
strcpy(hud->Escort_htext, XSTR( "monitoring", 285));
|
|
|
|
/**************************************************/
|
|
//NONE OF THIS NEEDS TO BE MODIFIED TO SETUP VARS
|
|
gauge_info* cg;
|
|
for(int i = 0; i < Num_gauge_types; i++)
|
|
{
|
|
cg = &gauges[i];
|
|
if(gr_screen.res == GR_640)
|
|
{
|
|
HUD_INT(hud, cg->coord_dest)[0] = cg->defaultx_640;
|
|
HUD_INT(hud, cg->coord_dest)[1] = cg->defaulty_480;
|
|
}
|
|
else
|
|
{
|
|
HUD_INT(hud, cg->coord_dest)[0] = cg->defaultx_1024;
|
|
HUD_INT(hud, cg->coord_dest)[1] = cg->defaulty_768;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
static void calculate_gauges(hud_info* dest_hud)
|
|
{
|
|
//Put any post-loading calculation code after the beep. *BEEP*
|
|
|
|
/**************************************************/
|
|
//DO NOT MODIFY this stuff, unless you're changing the loading system.
|
|
//Calculate parent gauge info
|
|
gauge_info* cg;
|
|
for(int i = 0; i < Num_gauge_types; i++)
|
|
{
|
|
cg = &gauges[i];
|
|
if(cg->parent && !(cg->placement_flags & HG_NOADD))
|
|
{
|
|
HUD_INT(dest_hud, cg->coord_dest)[0] = HUD_INT(dest_hud, cg->coord_dest)[0] + HUD_INT(dest_hud, cg->parent->coord_dest)[0];
|
|
HUD_INT(dest_hud, cg->coord_dest)[1] = HUD_INT(dest_hud, cg->coord_dest)[1] + HUD_INT(dest_hud, cg->parent->coord_dest)[1];
|
|
}
|
|
}
|
|
}
|
|
|
|
/****************************************************************************************************/
|
|
/* You shouldn't have to modify anything past here to add gauges */
|
|
/****************************************************************************************************/
|
|
//This doesn't belong in parse_lo, it's not really that low.
|
|
static int size_temp[2];
|
|
static float percentage_temp[2];
|
|
int stuff_coords(hud_info* dest_hud, gauge_info* cg, bool required = false)
|
|
{
|
|
//Speed up calculations
|
|
static hud_info* factor_for_hud;
|
|
static float resize_factor[2];
|
|
float fl_buffer[2];
|
|
bool size_defined = false;
|
|
|
|
if(required)
|
|
{
|
|
required_string(cg->fieldname);
|
|
}
|
|
if(!required && !optional_string(cg->fieldname))
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
//stuff_int_list(HUD_INT(dest_hud, i), 2, RAW_INTEGER_TYPE);
|
|
stuff_float_list(fl_buffer, 2);
|
|
if(!cg->parent)
|
|
{
|
|
factor_for_hud = NULL;
|
|
resize_factor[0] = 1;
|
|
resize_factor[1] = 1;
|
|
}
|
|
else if(dest_hud != factor_for_hud)
|
|
{
|
|
resize_factor[0] = (float)gr_screen.max_w / (float)dest_hud->resolution[0];
|
|
resize_factor[1] = (float)gr_screen.max_h / (float)dest_hud->resolution[1];
|
|
}
|
|
//Resize to current res
|
|
HUD_INT(dest_hud, cg->coord_dest)[0] = fl2i(fl_buffer[0] * resize_factor[0]);
|
|
HUD_INT(dest_hud, cg->coord_dest)[1] = fl2i(fl_buffer[1] * resize_factor[1]);
|
|
|
|
if(optional_string("+Size:"))
|
|
{
|
|
stuff_int_list(size_temp, 2, RAW_INTEGER_TYPE);
|
|
if(cg->size_dest)
|
|
{
|
|
HUD_INT(dest_hud, cg->size_dest)[0] = size_temp[0];
|
|
HUD_INT(dest_hud, cg->size_dest)[1] = size_temp[1];
|
|
}
|
|
|
|
//For %
|
|
size_defined = false;
|
|
}
|
|
|
|
if(optional_string("+Percentage:"))
|
|
{
|
|
stuff_float_list(percentage_temp, 2);
|
|
percentage_temp[0] *= (gr_screen.max_w / 100.0f);
|
|
percentage_temp[1] *= (gr_screen.max_h / 100.0f);
|
|
|
|
//Bool true, size defined
|
|
if(!size_defined)
|
|
{
|
|
if(percentage_temp[0])
|
|
{
|
|
percentage_temp[0] -= size_temp[0] / 2;
|
|
}
|
|
if(percentage_temp[1])
|
|
{
|
|
percentage_temp[1] -= size_temp[1] / 2;
|
|
}
|
|
}
|
|
HUD_INT(dest_hud, cg->coord_dest)[0] += fl2i(percentage_temp[0]);
|
|
HUD_INT(dest_hud, cg->coord_dest)[1] += fl2i(percentage_temp[1]);
|
|
}
|
|
|
|
char buffer[MAX_FILENAME_LEN];
|
|
if(optional_string("+Image:"))
|
|
{
|
|
if(cg->image_dest)
|
|
{
|
|
stuff_string(HUD_CHAR(dest_hud, cg->image_dest), F_NAME, MAX_FILENAME_LEN);
|
|
}
|
|
else
|
|
{
|
|
stuff_string(buffer, F_NAME, MAX_FILENAME_LEN);
|
|
}
|
|
}
|
|
if(optional_string("+Text:"))
|
|
{
|
|
if(cg->text_dest)
|
|
{
|
|
stuff_string(HUD_CHAR(dest_hud, cg->text_dest), F_NAME, NAME_LENGTH);
|
|
}
|
|
else
|
|
{
|
|
stuff_string(buffer, F_NAME, MAX_FILENAME_LEN);
|
|
}
|
|
}
|
|
if(optional_string("+Color:"))
|
|
{
|
|
if(cg->color_dest)
|
|
{
|
|
stuff_ubyte(&HUD_COLOR(dest_hud, cg->color_dest)->red);
|
|
stuff_ubyte(&HUD_COLOR(dest_hud, cg->color_dest)->green);
|
|
stuff_ubyte(&HUD_COLOR(dest_hud, cg->color_dest)->blue);
|
|
}
|
|
else
|
|
{
|
|
ubyte junk_byte;
|
|
stuff_ubyte(&junk_byte);
|
|
stuff_ubyte(&junk_byte);
|
|
stuff_ubyte(&junk_byte);
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
|
|
static void parse_resolution(hud_info* dest_hud)
|
|
{
|
|
//Parse it
|
|
gauge_info* cg;
|
|
for(int i = 0; i < Num_gauge_types; i++)
|
|
{
|
|
cg = &gauges[i];
|
|
if(cg->parent == NULL && strlen(cg->fieldname))
|
|
{
|
|
|
|
stuff_coords(dest_hud, cg);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void parse_resolution_gauges(hud_info* dest_hud)
|
|
{
|
|
char gaugename[NAME_LENGTH];
|
|
gauge_info *cg, *parent;
|
|
while(!required_string_3("$Gauge:","$Resolution:","#End"))
|
|
{
|
|
required_string("$Gauge:");
|
|
stuff_string(gaugename, F_NAME, NAME_LENGTH);
|
|
|
|
parent = NULL;
|
|
|
|
for(int i = 0; i < Num_gauge_types; i++)
|
|
{
|
|
cg = &gauges[i];
|
|
if(!parent)
|
|
{
|
|
if(!strnicmp(cg->fieldname + sizeof(char), gaugename, strlen(cg->fieldname) - 2))
|
|
{
|
|
parent = cg;
|
|
}
|
|
}
|
|
else if(parent == cg->parent)
|
|
{
|
|
stuff_coords(dest_hud, cg);
|
|
}
|
|
}
|
|
}
|
|
|
|
dest_hud->loaded = true;
|
|
}
|
|
|
|
|
|
/*
|
|
void set_coords_if_clear(int* dest_coords, int coord_x, int coord_y)
|
|
{
|
|
if(dest_coords[0] == -1 && coord_x != -1)
|
|
{
|
|
dest_coords[0] = coord_x;
|
|
}
|
|
if(dest_coords[1] == -1 && coord_y != -1)
|
|
{
|
|
dest_coords[1] = coord_y;
|
|
}
|
|
}
|
|
|
|
|
|
void resize_coords(int* values, float* factors)
|
|
{
|
|
values[0] = fl2i(values[0] * factors[0]);
|
|
values[1] = fl2i(values[1] * factors[1]);
|
|
}*/
|
|
|
|
hud_info* parse_ship_start()
|
|
{
|
|
hud_info* dest_hud = NULL;
|
|
|
|
required_string("$Ship:");
|
|
char shipname[NAME_LENGTH];
|
|
int ship_index;
|
|
stuff_string(shipname, F_NAME, NAME_LENGTH);
|
|
ship_index = ship_info_lookup(shipname);
|
|
|
|
if(ship_index == -1)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
dest_hud = &ship_huds[ship_index];
|
|
return dest_hud;
|
|
}
|
|
|
|
hud_info* parse_resolution_start(hud_info* dest_hud, int str_token)
|
|
{
|
|
int buffer[2];
|
|
|
|
if(str_token == 1)
|
|
{
|
|
required_string("$Default:");
|
|
if(!dest_hud->loaded)
|
|
{
|
|
stuff_int_list(dest_hud->resolution, 2, RAW_INTEGER_TYPE);
|
|
if(dest_hud->resolution[0] == 0 || dest_hud->resolution == 0)
|
|
{
|
|
dest_hud->resolution[0] = gr_screen.max_w;
|
|
dest_hud->resolution[1] = gr_screen.max_h;
|
|
}
|
|
return dest_hud;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
required_string("$Resolution:");
|
|
stuff_int_list(buffer, 2, RAW_INTEGER_TYPE);
|
|
|
|
if ( (buffer[0] == gr_screen.max_w_unscaled) && (buffer[1] == gr_screen.max_h_unscaled) )
|
|
{
|
|
//Get the ship HUD ready w/ defaults
|
|
if(default_hud.loaded)
|
|
{
|
|
memcpy(dest_hud, &default_hud, sizeof(hud_info));
|
|
//It's not really loaded
|
|
dest_hud->loaded = false;
|
|
}
|
|
else
|
|
{
|
|
//Set the resolution
|
|
memcpy(dest_hud->resolution, buffer, sizeof(buffer));
|
|
}
|
|
|
|
return dest_hud;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
void parse_custom_gauge()
|
|
{
|
|
if(Num_gauge_types < MAX_HUD_GAUGE_TYPES)
|
|
{
|
|
char buffer[NAME_LENGTH];
|
|
|
|
gauge_info* cg = &gauges[Num_gauge_types];
|
|
memset(cg, 0, sizeof(gauge_info));
|
|
//Set all the ptrs (modified to work with GCC 3.4 - taylor)
|
|
cg->coord_dest = HUD_VAR(custom_gauge_coords[0]) + (Num_custom_gauges * (2*sizeof(int)));
|
|
cg->size_dest = HUD_VAR(custom_gauge_sizes[0]) + (Num_custom_gauges * (2*sizeof(int)));
|
|
cg->image_dest = HUD_VAR(custom_gauge_images[0]) + (Num_custom_gauges * (MAX_FILENAME_LEN * sizeof(char)));
|
|
cg->frame_dest = HUD_VAR(custom_gauge_frames[0]) + (Num_custom_gauges * sizeof(int));
|
|
cg->text_dest = HUD_VAR(custom_gauge_text[0]) + (Num_custom_gauges * (NAME_LENGTH * sizeof(char)));
|
|
cg->color_dest = HUD_VAR(custom_gauge_colors[0]) + (Num_custom_gauges * sizeof(color));
|
|
|
|
required_string("$Name:");
|
|
//Gotta make this a token
|
|
cg->fieldname[0] = '$';
|
|
stuff_string(cg->fieldname + 1, F_NAME, sizeof(cg->fieldname) - 1);
|
|
strcat(cg->fieldname, ":");
|
|
|
|
if(optional_string("+Default640X:"))
|
|
{
|
|
stuff_int(&cg->defaultx_640);
|
|
}
|
|
if(optional_string("+Default640Y:"))
|
|
{
|
|
stuff_int(&cg->defaulty_480);
|
|
}
|
|
if(optional_string("+Default1024X:"))
|
|
{
|
|
stuff_int(&cg->defaultx_1024);
|
|
}
|
|
if(optional_string("+Default1024Y:"))
|
|
{
|
|
stuff_int(&cg->defaulty_768);
|
|
}
|
|
if(optional_string("+Parent:"))
|
|
{
|
|
stuff_string(buffer, F_NAME, NAME_LENGTH);
|
|
cg->parent = hud_get_gauge(buffer);
|
|
}
|
|
|
|
Num_gauge_types++;
|
|
Num_custom_gauges++;
|
|
}
|
|
else
|
|
{
|
|
skip_to_start_of_string_either("$Name:", "#End");
|
|
}
|
|
}
|
|
|
|
void parse_hud_gauges_tbl(char* longname)
|
|
{
|
|
int rval;
|
|
lcl_ext_open();
|
|
if ((rval = setjmp(parse_abort)) != 0)
|
|
{
|
|
mprintf(("Unable to parse %s! Code = %i.\n", longname, rval));
|
|
lcl_ext_close();
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
read_file_text(longname);
|
|
reset_parse();
|
|
}
|
|
|
|
read_file_text(longname);
|
|
|
|
if(optional_string("$Max Escort Ships:"))
|
|
{
|
|
stuff_int(&Max_escort_ships);
|
|
}
|
|
|
|
if(optional_string("#Custom Gauges"))
|
|
{
|
|
while(required_string_either("#End", "$Name:"))
|
|
{
|
|
parse_custom_gauge();
|
|
}
|
|
required_string("#End");
|
|
}
|
|
|
|
//It's parsing time everehbody!
|
|
hud_info* dest_hud = &default_hud;
|
|
|
|
if(optional_string("#Main Gauges"))
|
|
{
|
|
while(rval = required_string_3("#End", "$Default:", "$Resolution:"), rval)
|
|
{
|
|
if(parse_resolution_start(dest_hud, rval))
|
|
{
|
|
parse_resolution(dest_hud);
|
|
}
|
|
else
|
|
{
|
|
skip_to_start_of_string_either("$Resolution:", "$Default:", "#End");
|
|
}
|
|
}
|
|
required_string("#End");
|
|
}
|
|
|
|
if(optional_string("#Gauges"))
|
|
{
|
|
while(rval = required_string_3("#End", "$Default:", "$Resolution:"), rval)
|
|
{
|
|
if(parse_resolution_start(dest_hud, rval))
|
|
{
|
|
parse_resolution_gauges(dest_hud);
|
|
}
|
|
else
|
|
{
|
|
skip_to_start_of_string_either("$Resolution:", "$Default:", "#End");
|
|
}
|
|
}
|
|
required_string("#End");
|
|
}
|
|
|
|
calculate_gauges(&default_hud);
|
|
|
|
if(ships_inited)
|
|
{
|
|
//Parse main ship gauges
|
|
if(optional_string("#Ship Main Gauges"))
|
|
{
|
|
while (required_string_either("#End","$Ship:"))
|
|
{
|
|
if(dest_hud = parse_ship_start(), dest_hud)
|
|
{
|
|
while(rval = required_string_3("#End", "$Default:", "$Resolution:"), rval)
|
|
{
|
|
if(parse_resolution_start(dest_hud, rval))
|
|
{
|
|
parse_resolution(dest_hud);
|
|
}
|
|
else
|
|
{
|
|
skip_to_start_of_string_either("$Resolution:", "$Default:", "$Ship:");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
required_string("#End");
|
|
}
|
|
|
|
//Parse individual extra ship gauge info
|
|
if(optional_string("#Ship Gauges"))
|
|
{
|
|
while (required_string_either("#End","$Ship:"))
|
|
{
|
|
if(dest_hud = parse_ship_start(), dest_hud)
|
|
{
|
|
while(rval = required_string_3("#End", "$Default:", "$Resolution:"), rval)
|
|
{
|
|
if(parse_resolution_start(dest_hud, rval))
|
|
{
|
|
parse_resolution_gauges(dest_hud);
|
|
}
|
|
else
|
|
{
|
|
skip_to_start_of_string_either("$Resolution:", "$Default:", "$Ship:");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
required_string("#End");
|
|
}
|
|
|
|
for(int i = 0; i < MAX_SHIP_CLASSES; i++)
|
|
{
|
|
if(ship_huds[i].loaded)
|
|
{
|
|
calculate_gauges(&ship_huds[i]);
|
|
}
|
|
}
|
|
}
|
|
lcl_ext_close();
|
|
}
|
|
#endif
|
|
|
|
extern int Ships_inited;
|
|
void hud_positions_init()
|
|
{
|
|
if(!ships_inited)
|
|
{
|
|
Error(LOCATION, "Could not initialize hudparse.cpp as ships were not inited first.");
|
|
return;
|
|
}
|
|
|
|
load_hud_defaults(&default_hud);
|
|
#ifndef NEW_HUD
|
|
|
|
if (cf_exists_full("hud_gauges.tbl", CF_TYPE_TABLES))
|
|
parse_hud_gauges_tbl("hud_gauges.tbl");
|
|
else
|
|
calculate_gauges(&default_hud);
|
|
|
|
parse_modular_table(NOX("*-hdg.tbm"), parse_hud_gauges_tbl);
|
|
|
|
set_current_hud(-1);
|
|
#endif
|
|
}
|
|
|
|
//Depending on the ship number specified, this copies either the default hud or a ship hud
|
|
//to a temporary hud_info struct and sets the current_hud pointer to it.
|
|
//This enables ship-specific huds.
|
|
//Note that this creates a temporary current hud, so changes aren't permanently saved.
|
|
#ifdef NEW_HUD
|
|
void set_current_hud(ship* owner)
|
|
#else
|
|
void set_current_hud(int player_ship_num)
|
|
#endif
|
|
{
|
|
#ifdef NEW_HUD
|
|
if(!owner->ship_hud.is_loaded())
|
|
{
|
|
if(ship_huds[owner->ship_info_index].is_loaded() == true)
|
|
{
|
|
ship_huds[owner->ship_info_index].copy(&owner->ship_hud);
|
|
}
|
|
else if(Species_info[Ship_info[owner->ship_info_index].species].hud.is_loaded() == true)
|
|
{
|
|
Species_info[Ship_info[owner->ship_info_index].species].hud.copy(&owner->ship_hud);
|
|
}
|
|
else
|
|
{
|
|
default_hud.copy(&owner->ship_hud);
|
|
}
|
|
mprintf(("NEW_HUD: Hud created for ship %s", owner->ship_name));
|
|
}
|
|
current_hud = &owner->ship_hud;
|
|
current_hud->owner = owner;
|
|
#else
|
|
static hud_info real_current_hud;
|
|
|
|
if(player_ship_num >= 0 && player_ship_num < MAX_SHIP_CLASSES && ship_huds[player_ship_num].loaded)
|
|
{
|
|
memcpy(&real_current_hud, &ship_huds[player_ship_num], sizeof(hud_info));
|
|
}
|
|
else
|
|
{
|
|
memcpy(&real_current_hud, &default_hud, sizeof(hud_info));
|
|
}
|
|
|
|
current_hud = &real_current_hud;
|
|
#endif
|
|
}
|
|
|
|
#ifndef NEW_HUD
|
|
|
|
/* - not POD so GCC won't take it for offsetof - taylor
|
|
hud_info::hud_info()
|
|
{
|
|
memset(this, 0, sizeof(hud_info));
|
|
}
|
|
*/
|
|
|
|
#else
|
|
|
|
/*
|
|
//Note: user range should be 50 to 150
|
|
ubyte hud_info::get_preset_alpha(int preset_id)
|
|
{
|
|
if(!flags & HI_CONTRAST)
|
|
{
|
|
switch(preset_id)
|
|
{
|
|
case HI_DIM:
|
|
return hud_color.alpha - 40;
|
|
case HI_NORMAL:
|
|
return hud_color.alpha;
|
|
case HI_BRIGHT:
|
|
return hud_color.alpha + 100;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch(preset_id)
|
|
{
|
|
case HI_DIM:
|
|
return hud_color.alpha +10;
|
|
case HI_NORMAL:
|
|
return hud_color.alpha + 70;
|
|
case HI_BRIGHT:
|
|
return 255;
|
|
}
|
|
}
|
|
}*/
|
|
hud::hud()
|
|
{
|
|
resolution[0] = resolution[1] = 0;
|
|
num_gauges = 0;
|
|
first_gauge = NULL;
|
|
loaded = false;
|
|
}
|
|
hud::~hud()
|
|
{
|
|
//Delete all gauges
|
|
gauge_data *cg = first_gauge;
|
|
while(cg != NULL)
|
|
{
|
|
first_gauge = cg->next;
|
|
delete cg;
|
|
cg = first_gauge;
|
|
}
|
|
}
|
|
|
|
void hud::show()
|
|
{
|
|
gauge_data *cg = first_gauge;
|
|
while(cg != NULL)
|
|
{
|
|
if(cg->type == HG_MAINGAUGE)
|
|
{
|
|
cg->show(owner);
|
|
}
|
|
|
|
cg = cg->next;
|
|
}
|
|
}
|
|
|
|
//Parents are responsible for setting child prev and next variables
|
|
//Remember dat.
|
|
int hud::copy(hud* dest_hud)
|
|
{
|
|
memcpy(dest_hud->resolution, resolution, sizeof(resolution));
|
|
dest_hud->num_gauges = num_gauges;
|
|
memcpy(&dest_hud->hud_color, &hud_color, sizeof(color));
|
|
|
|
gauge_data *cg = first_gauge;
|
|
gauge_data *pg = NULL;
|
|
gauge_data **dcg = &dest_hud->first_gauge;
|
|
while(cg != NULL)
|
|
{
|
|
(*dcg) = new gauge_data;
|
|
|
|
Assert((*dcg) != NULL);
|
|
|
|
cg->copy((*dcg));
|
|
(*dcg)->prev = pg;
|
|
pg = (*dcg);
|
|
dcg = &((*dcg)->next);
|
|
cg = cg->next;
|
|
}
|
|
|
|
dest_hud->loaded = true;
|
|
|
|
return 1;
|
|
}
|
|
|
|
//Gets a gauge by its name
|
|
//Names are unique and case-insensitive
|
|
//Returns NULL on failure
|
|
gauge_data *hud::get_gauge(char* name)
|
|
{
|
|
gauge_data *cg = first_gauge;
|
|
gauge_data *rv = NULL;
|
|
|
|
while(cg != NULL)
|
|
{
|
|
if(!stricmp(cg->name, name))
|
|
{
|
|
return cg;
|
|
}
|
|
if(cg->first_child)
|
|
{
|
|
rv = cg->get_gauge(name);
|
|
|
|
if(rv != NULL)
|
|
{
|
|
//You bastard...how dare you steal a Winnebago?
|
|
return rv;
|
|
}
|
|
}
|
|
|
|
cg = cg->next;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
gauge_data *gauge_data::get_gauge(char *name)
|
|
{
|
|
gauge_data *cg = first_child;
|
|
while(cg != NULL)
|
|
{
|
|
if(!stricmp(cg->name, name))
|
|
{
|
|
return cg;
|
|
}
|
|
|
|
cg = cg->next;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
//Adds a gauge to the end of the list. Will add priority crap later.
|
|
//Priority of -1 means place at the very front
|
|
//Priority of -2 means place at the very end
|
|
gauge_data *hud::add_gauge(char* name, int def_x_coord, int def_y_coord, gauge_data* new_gauge_parent, int priority)
|
|
{
|
|
//If no gauges exist, add them.
|
|
gauge_data *new_gauge = new gauge_data;
|
|
if(new_gauge == NULL)
|
|
{
|
|
Warning(LOCATION, "Could not allocate memory for gauge \"%s\"", name);
|
|
return NULL;
|
|
}
|
|
if(get_gauge(name) != NULL)
|
|
{
|
|
Warning(LOCATION, "Gauge with name \"%s\" already exists; new gauge was not added. Note that gauge names ARE case-sensitive.", name);
|
|
return NULL;
|
|
}
|
|
|
|
//Make the fgp variable a double pointer,
|
|
//so we can set the first-gauge as well if necessary.
|
|
gauge_data **fgp;
|
|
if(new_gauge_parent == NULL)
|
|
{
|
|
fgp = &first_gauge;
|
|
}
|
|
else
|
|
{
|
|
fgp = &new_gauge_parent->first_child;
|
|
}
|
|
|
|
if((*fgp) != NULL && priority != -1)
|
|
{
|
|
gauge_data *cg = (*fgp);
|
|
while(cg != NULL)
|
|
{
|
|
if(cg->next != NULL)
|
|
{
|
|
if(cg->next->priority > priority)
|
|
{
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
cg = cg->next;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
//We've found an empty spot, put it there.
|
|
new_gauge->next = cg->next;
|
|
new_gauge->prev = cg;
|
|
cg->next = new_gauge;
|
|
}
|
|
else
|
|
{
|
|
if((*fgp) != NULL)
|
|
{
|
|
//Replace existing first gauge
|
|
new_gauge->next = (*fgp);
|
|
(*fgp)->prev = new_gauge;
|
|
(*fgp) = new_gauge;
|
|
}
|
|
else
|
|
{
|
|
//Only one gauge, the new one
|
|
(*fgp) = new_gauge;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
new_gauge->set_up(name, def_x_coord, def_y_coord, new_gauge_parent, priority);
|
|
|
|
return new_gauge;
|
|
}
|
|
|
|
#endif
|
|
|
|
gauge_info* hud_get_gauge(char* name)
|
|
{
|
|
#ifndef NEW_HUD
|
|
int id = hud_get_gauge_index(name);
|
|
if(id > -1)
|
|
{
|
|
return &gauges[id];
|
|
}
|
|
#endif
|
|
|
|
return NULL;
|
|
}
|
|
|
|
int hud_get_gauge_index(char* name)
|
|
{
|
|
#ifndef NEW_HUD
|
|
for(int i = 0; i < Num_gauge_types; i++)
|
|
{
|
|
if(!strnicmp(gauges[i].fieldname + sizeof(char), name, strlen(gauges[i].fieldname) - 2))
|
|
{
|
|
return i;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
return -1;
|
|
}
|
|
|
|
|
|
#ifdef NEW_HUD
|
|
int gauge_data::set_up(char* gauge_name, int def_x, int def_y, gauge_data* gauge_parent, int priority)
|
|
{
|
|
//Don't set up the same gauge twice
|
|
if(type != HG_UNUSED)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
//If a parent was given, set it
|
|
if(gauge_parent)
|
|
{
|
|
type = HG_CHILDGAUGE;
|
|
}
|
|
else
|
|
{
|
|
type = HG_MAINGAUGE;
|
|
}
|
|
|
|
Assert(strlen(gauge_name) < sizeof(name));
|
|
|
|
strcpy(name, gauge_name);
|
|
coords[0] = def_x;
|
|
coords[1] = def_y;
|
|
priority = 100;
|
|
|
|
return 1;
|
|
}
|
|
|
|
int gauge_data::set_image(char* image_name, int newframe, int sizex, int sizey)
|
|
{
|
|
//Make sure we aren't trying to reset an image
|
|
if(!stricmp(image_name, image))
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
//Get the NEW model id
|
|
int new_image_id = bm_load_animation(image_name, &num_frames);
|
|
if(new_image_id == -1)
|
|
{
|
|
new_image_id = bm_load(image_name);
|
|
//Make sure the new one is valid
|
|
if(new_image_id == -1)
|
|
{
|
|
//Warning(("Warning","Could not load image %s for a HUD gauge", image_name));
|
|
return 0;
|
|
}
|
|
num_frames = 1;
|
|
}
|
|
|
|
strcpy(image, image_name);
|
|
|
|
//Give up the old one
|
|
if(image_id != -1)
|
|
{
|
|
bm_unload(image_id); //maybe unload?
|
|
}
|
|
|
|
//Set image_id
|
|
image_id = new_image_id;
|
|
Assert(newframe < num_frames);
|
|
for(int i = 0; i < MAX_GAUGE_FRAMES; i++)
|
|
{
|
|
frame[i] = -1;
|
|
}
|
|
frame[0] = newframe;
|
|
bm_get_info(image_id, &image_size[0], &image_size[1]);
|
|
|
|
//Set size values
|
|
if(sizex)
|
|
{
|
|
image_size[0] = sizex;
|
|
}
|
|
if(sizey)
|
|
{
|
|
image_size[1] = sizey;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
int gauge_data::reset()
|
|
{
|
|
draw_coords[0] = draw_coords[1] = 0;
|
|
/* if(image_id != -1)
|
|
{
|
|
bm_unload(image_id);
|
|
}*/
|
|
|
|
return 1;
|
|
}
|
|
int gauge_data::page_in()
|
|
{
|
|
if(strlen(image))
|
|
{
|
|
if(image_id == -1)
|
|
{
|
|
image_id = bm_load_animation(image, &num_frames);
|
|
if(image_id == -1)
|
|
{
|
|
image_id = bm_load(image);
|
|
//Make sure the new one is valid
|
|
if(image_id != -1)
|
|
{
|
|
num_frames = 1;
|
|
}
|
|
else
|
|
{
|
|
num_frames = 0;
|
|
}
|
|
}
|
|
}
|
|
bm_page_in_aabitmap(image_id, num_frames);
|
|
}
|
|
return 1;
|
|
}
|
|
gauge_data::gauge_data()
|
|
{
|
|
int i;
|
|
|
|
type = HG_UNUSED;
|
|
priority = 100;
|
|
coords[0] = coords[1] = 0;
|
|
draw_coords[0] = draw_coords[1] = 0;
|
|
|
|
//Color
|
|
g_color.alpha = 0;
|
|
user_color.alpha = 0;
|
|
|
|
//Text
|
|
text[0] = '\0';
|
|
max_text_lines = 1;
|
|
max_text_width = -1;
|
|
|
|
//By default, show HUD gauges only if view is a cockpit
|
|
show_flags = VM_OTHER_SHIP;
|
|
|
|
//Shape
|
|
for(i = 0; i < MAX_GAUGE_SHAPES; i++)
|
|
{
|
|
shape_id[i] = -1;
|
|
}
|
|
memset(shape_attrib, 0, sizeof(shape_attrib));
|
|
|
|
//Image/animation
|
|
image_id = -1;
|
|
num_frames = 0;
|
|
for(i = 0; i < MAX_GAUGE_FRAMES; i++)
|
|
{
|
|
frame[i] = -1;
|
|
}
|
|
memset(frame_attrib, 0, sizeof(frame_attrib));
|
|
|
|
//Model
|
|
model_id = -1;
|
|
memset(model_attrib, 0, sizeof(model_attrib));
|
|
|
|
prev = next = NULL;
|
|
first_child = NULL;
|
|
|
|
update_func = NULL;
|
|
}
|
|
gauge_data::~gauge_data()
|
|
{
|
|
//deletes child gauges
|
|
gauge_data *cg;
|
|
cg = first_child;
|
|
while(cg != NULL)
|
|
{
|
|
cg = cg->next;
|
|
delete first_child;
|
|
first_child = cg;
|
|
}
|
|
}
|
|
|
|
int gauge_data::copy(gauge_data *dest_gauge)
|
|
{
|
|
memcpy(dest_gauge, this, sizeof(gauge_data));
|
|
|
|
//Just...no.
|
|
dest_gauge->next = dest_gauge->prev = NULL;
|
|
|
|
//Now clone the children. Fun with recursive functions.
|
|
gauge_data *cg = first_child; //Current Gauge
|
|
gauge_data **cdgp = &dest_gauge->first_child;//Current Destination Gauge Pointer
|
|
gauge_data *odg = NULL; //Old Destination Gauge
|
|
while(cg != NULL)
|
|
{
|
|
//Create the new child gauge (Also setting the next or first_child pointer)
|
|
(*cdgp) = new gauge_data;
|
|
|
|
//This is bad.
|
|
Assert((*cdgp) != NULL);
|
|
|
|
//Copy contents from the old child gauge to the new
|
|
cg->copy((*cdgp));
|
|
|
|
//Set prev for the current destination child-gauge to the last gauge added
|
|
(*cdgp)->prev = odg;
|
|
//Set old destination gauge var to the current gauge
|
|
odg = (*cdgp);
|
|
//Set cdgp to the next gauge's next pointer
|
|
cdgp = &(*cdgp)->next;
|
|
//Advance to the next source gauge
|
|
cg = cg->next;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
void gauge_data::draw_text()
|
|
{
|
|
if(max_text_width > 0 && max_text_lines <= 1)
|
|
{
|
|
char *short_str = new char[strlen(text) + 1];
|
|
strcpy(short_str, text);
|
|
gr_force_fit_string(short_str, sizeof(text), max_text_width);
|
|
gr_string(draw_coords[0], draw_coords[1], short_str);
|
|
delete[] short_str;
|
|
}
|
|
else
|
|
{
|
|
gr_string(draw_coords[0], draw_coords[1], text);
|
|
}
|
|
}
|
|
|
|
void gauge_data::draw_image()
|
|
{
|
|
color framecolor;
|
|
for(int i = 0; i < MAX_GAUGE_FRAMES; i++)
|
|
{
|
|
if(frame_attrib[i][4])
|
|
{
|
|
gr_init_alphacolor(&framecolor, g_color.red, g_color.green, g_color.blue, frame_attrib[i][4]);
|
|
gr_set_color_fast(&framecolor);
|
|
}
|
|
if(frame[i] != -1)
|
|
{
|
|
gr_set_bitmap(image_id + frame[i]);
|
|
//clipping
|
|
//0 top
|
|
//1 left
|
|
//2 bottom
|
|
//3 right
|
|
gr_aabitmap_ex(draw_coords[0] + frame_attrib[i][1], //X position
|
|
draw_coords[1] + frame_attrib[i][0], //Y position
|
|
image_size[0] - frame_attrib[i][1] - frame_attrib[i][3], //Width to show
|
|
image_size[1] - frame_attrib[i][0] - frame_attrib[i][2], //Height to show
|
|
frame_attrib[i][1], //Offset from left
|
|
frame_attrib[i][0]); //Offset from top
|
|
}
|
|
}
|
|
}
|
|
|
|
void gauge_data::draw_shape()
|
|
{
|
|
//Notes on shape stuff
|
|
//Where a bool is in the attributes, 0 is false, anything else is true
|
|
//Values will likely not be checked for validity for speed
|
|
for(int i = 0; i < MAX_GAUGE_SHAPES; i++)
|
|
{
|
|
switch(shape_id[i])
|
|
{
|
|
case HG_SHAPERECTANGLE:
|
|
//0 - x offset
|
|
//1 - y offset
|
|
//2 - width
|
|
//3 - height
|
|
gr_rect(draw_coords[0] + shape_attrib[i][0],
|
|
draw_coords[0] + shape_attrib[i][1],
|
|
shape_attrib[i][2],
|
|
shape_attrib[i][3], false);
|
|
break;
|
|
case HG_SHAPECIRCLE:
|
|
//0 - x offset
|
|
//1 - y offset
|
|
//2 - diameter
|
|
gr_circle(draw_coords[0] + shape_attrib[i][0],
|
|
draw_coords[0] + shape_attrib[i][1],
|
|
shape_attrib[i][2]);
|
|
break;
|
|
case HG_SHAPELINE:
|
|
//0 - 1st point x offset
|
|
//1 - 1st point y offset
|
|
//2 - 2nd point x offset
|
|
//3 - 2nd point y offset
|
|
//4 - Change line points so they aren't offscreen?
|
|
gr_line(draw_coords[0] + shape_attrib[i][0],
|
|
draw_coords[1] + shape_attrib[i][1],
|
|
draw_coords[0] + shape_attrib[i][2],
|
|
draw_coords[1] + shape_attrib[i][3],
|
|
shape_attrib[i][4] == 0 ? false : true);
|
|
break;
|
|
/* case HG_SHAPEAALINE:
|
|
//Draws anti-aliased line; slower than normal line
|
|
//0 - 1st point x offset
|
|
//1 - 1st point y offset
|
|
//2 - 2nd point x offset
|
|
//3 - 2nd point y offset
|
|
//4 - Change line points so they aren't offscreen?
|
|
gr_aaline(draw_coords[0] + shape_attrib[i][0],
|
|
draw_coords[1] + shape_attrib[i][1],
|
|
draw_coords[0] + shape_attrib[i][2],
|
|
draw_coords[1] + shape_attrib[i][3],
|
|
shape_attrib[i][4]);
|
|
break;*/
|
|
case HG_SHAPEGRADIENT:
|
|
//Draws a line that slowly fades to 0 alpha
|
|
//Auto-changes line points so they aren't offscreen
|
|
//0 - 1st point x offset
|
|
//1 - 1st point y offset
|
|
//2 - 2nd point x offset
|
|
//3 - 2nd point y offset
|
|
gr_gradient(draw_coords[0] + shape_attrib[i][0],
|
|
draw_coords[1] + shape_attrib[i][1],
|
|
draw_coords[0] + shape_attrib[i][2],
|
|
draw_coords[1] + shape_attrib[i][3]);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void gauge_data::draw_model()
|
|
{
|
|
//A lot of this stuff is shamelessly ripped from hud_render_target_ship
|
|
|
|
// model_render(model_id,
|
|
}
|
|
|
|
int gauge_data::draw()
|
|
{
|
|
//Color
|
|
if(g_color.alpha && (!user_color.alpha || data_flags & HG_PRIORITYCOLOR))
|
|
{
|
|
gr_set_color_fast(&g_color);
|
|
}
|
|
else if(user_color.alpha)
|
|
{
|
|
gr_set_color_fast(&user_color);
|
|
}
|
|
else
|
|
{
|
|
hud_set_default_color();
|
|
}
|
|
|
|
//Shape
|
|
//No if clause needed here, shapes are individually checked
|
|
draw_shape();
|
|
|
|
//Image
|
|
if(image_id != -1)
|
|
{
|
|
draw_image();
|
|
}
|
|
|
|
//Model
|
|
if(model_id != -1)
|
|
{
|
|
draw_model();
|
|
}
|
|
|
|
//Text
|
|
if(text[0] != '\0')
|
|
{
|
|
draw_text();
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
int gauge_data::show(ship* gauge_owner, gauge_data* cgp)
|
|
{
|
|
//Don't execute if we can't see the gauge
|
|
if(!(Viewer_mode & show_flags) && Viewer_mode != 0)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
|
|
update_num = 0;
|
|
int rval = 0;
|
|
|
|
//Increment by parent coords, if it has a parent
|
|
if(cgp)
|
|
{
|
|
draw_coords[0] = cgp->coords[0];
|
|
draw_coords[1] = cgp->coords[1];
|
|
}
|
|
|
|
do
|
|
{
|
|
if(update_func != NULL)
|
|
{
|
|
rval = update_func(this, gauge_owner);
|
|
}
|
|
else
|
|
{
|
|
rval = 1;
|
|
}
|
|
//rval -1:Don't draw
|
|
//rval 0: update again
|
|
//rval 1: this is the last update
|
|
//all else: just draw the gauge
|
|
if(rval == -1)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
//If we aren't redrawing and starting the loop, set to 0
|
|
if(update_num ==0 && (rval == 1 || rval == 0))
|
|
{
|
|
if(cgp == NULL)
|
|
{
|
|
draw_coords[0] = draw_coords[1] = 0;
|
|
}
|
|
else
|
|
{
|
|
draw_coords[0] = cgp->coords[0];
|
|
draw_coords[1] = cgp->coords[1];
|
|
}
|
|
|
|
}
|
|
|
|
//If we aren't redrawing, set new draw coordinates
|
|
if(rval == 1 || rval == 0)
|
|
{
|
|
draw_coords[0] += coords[0];
|
|
draw_coords[1] += coords[1];
|
|
}
|
|
|
|
if(first_child != NULL)
|
|
{
|
|
gauge_data *cg = first_child;
|
|
while(cg != NULL)
|
|
{
|
|
Assert(cg != this);
|
|
|
|
cg->show(gauge_owner, this);
|
|
cg = cg->next;
|
|
}
|
|
}
|
|
|
|
draw();
|
|
|
|
update_num++;
|
|
} while(rval == 0);
|
|
|
|
if(data_flags & HG_NEEDSUPDATE)
|
|
{
|
|
data_flags &= HG_NEEDSUPDATE;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
int gauge_var::Evaluate(int* result)
|
|
{
|
|
(*result) = 0;
|
|
gauge_var* cv = this;
|
|
int temp_result;
|
|
|
|
while(cv != NULL)
|
|
{
|
|
switch(data_type)
|
|
{
|
|
case GV_INTPTR:
|
|
case GV_INTVAR:
|
|
temp_result = (*int_variable);
|
|
break;
|
|
case GV_CHARPTR:
|
|
temp_result = atoi(*char_pointer);
|
|
break;
|
|
case GV_CHARVAR:
|
|
temp_result = atoi(char_variable);
|
|
break;
|
|
case GV_FLOATPTR:
|
|
case GV_FLOATVAR:
|
|
temp_result = fl2i(*float_variable);
|
|
break;
|
|
case GV_GAUGEVAR:
|
|
case GV_GAUGEVARPTR:
|
|
gv_variable->Evaluate(&temp_result);
|
|
break;
|
|
default:
|
|
Error(LOCATION, "Unknown data type handed to gauge_var::Evaluate(int* result)!");
|
|
return HG_RETURNNODRAW;
|
|
}
|
|
|
|
switch(var_operator)
|
|
{
|
|
case GV_NONE:
|
|
case GV_ADD:
|
|
(*result) += temp_result;
|
|
break;
|
|
case GV_SUBTRACT:
|
|
(*result) -= temp_result;
|
|
break;
|
|
case GV_MULTIPLY:
|
|
(*result) *= temp_result;
|
|
break;
|
|
case GV_DIVIDE:
|
|
(*result) /= temp_result;
|
|
break;
|
|
default:
|
|
Error(LOCATION, "Unknown operator handed to gauge_var::Evaluate(int* result)!");
|
|
return HG_RETURNNODRAW;
|
|
}
|
|
|
|
cv = cv->next;
|
|
}
|
|
|
|
if(prev_data_type == GV_INTVAR && result == prev_int_result)
|
|
{
|
|
return HG_RETURNREDRAW;
|
|
}
|
|
else
|
|
{
|
|
if(prev_data_type != GV_INTVAR)
|
|
{
|
|
prev_data_type = GV_INTVAR;
|
|
DeallocPrevVars();
|
|
prev_int_result = new int;
|
|
}
|
|
(*prev_int_result) = (*result);
|
|
|
|
return HG_RETURNLASTUPDATE;
|
|
}
|
|
}
|
|
|
|
int gauge_var::Evaluate(float* result)
|
|
{
|
|
(*result) = 0;
|
|
gauge_var* cv = this;
|
|
float temp_result;
|
|
|
|
while(cv != NULL)
|
|
{
|
|
switch(data_type)
|
|
{
|
|
case GV_INTPTR:
|
|
case GV_INTVAR:
|
|
temp_result = i2fl(*int_variable);
|
|
break;
|
|
case GV_CHARPTR:
|
|
temp_result = atof(*char_pointer);
|
|
break;
|
|
case GV_CHARVAR:
|
|
temp_result = atof(char_variable);
|
|
break;
|
|
case GV_FLOATPTR:
|
|
case GV_FLOATVAR:
|
|
temp_result = (*float_variable);
|
|
break;
|
|
default:
|
|
Error(LOCATION, "Unknown data type handed to gauge_var::Evaluate(float* result)!");
|
|
return HG_RETURNNODRAW;
|
|
}
|
|
|
|
switch(var_operator)
|
|
{
|
|
case GV_NONE:
|
|
case GV_ADD:
|
|
(*result) += temp_result;
|
|
break;
|
|
case GV_SUBTRACT:
|
|
(*result) -= temp_result;
|
|
break;
|
|
case GV_MULTIPLY:
|
|
(*result) *= temp_result;
|
|
break;
|
|
case GV_DIVIDE:
|
|
(*result) /= temp_result;
|
|
break;
|
|
default:
|
|
Error(LOCATION, "Unknown operator handed to gauge_var::Evaluate(float* result)!");
|
|
return HG_RETURNNODRAW;
|
|
}
|
|
|
|
cv = cv->next;
|
|
}
|
|
|
|
if(prev_data_type == GV_FLOATVAR && result == prev_float_result)
|
|
{
|
|
return HG_RETURNREDRAW;
|
|
}
|
|
else
|
|
{
|
|
if(prev_data_type != GV_FLOATVAR)
|
|
{
|
|
prev_data_type = GV_FLOATVAR;
|
|
DeallocPrevVars();
|
|
prev_float_result = new float;
|
|
}
|
|
(*prev_float_result) = (*result);
|
|
|
|
return HG_RETURNLASTUPDATE;
|
|
}
|
|
}
|
|
|
|
//This is going to be really, really hard...
|
|
//What it needs to do is add two number types if they're adjacent, but concatenate a string if it exists
|
|
//So that way, 1 + 2.5 + " to " + 4 * 2 gives a string of "3.5 to 8", not "12.5 to 4" and dies on an error.
|
|
//So...
|
|
//TODO: Implement this properly.
|
|
int gauge_var::Evaluate(char** result)
|
|
{
|
|
//This should be big enough.
|
|
(*result) = new char[32];
|
|
char* temp_result = new char[32];
|
|
|
|
gauge_var* cv = this;
|
|
|
|
while(cv != NULL)
|
|
{
|
|
switch(data_type)
|
|
{
|
|
case GV_INTPTR:
|
|
case GV_INTVAR:
|
|
temp_result = itoa(*int_variable, temp_result, 10);
|
|
break;
|
|
case GV_CHARPTR:
|
|
strcpy(temp_result, *char_pointer);
|
|
break;
|
|
case GV_CHARVAR:
|
|
strcpy(temp_result, char_variable);
|
|
break;
|
|
case GV_FLOATPTR:
|
|
case GV_FLOATVAR:
|
|
sprintf(temp_result, "%d%%", *float_variable);
|
|
break;
|
|
default:
|
|
Error(LOCATION, "Unknown data type handed to gauge_var::Evaluate(char** result)!");
|
|
return HG_RETURNNODRAW;
|
|
}
|
|
|
|
switch(var_operator)
|
|
{
|
|
case GV_ADD:
|
|
strcat(*result, temp_result);
|
|
break;
|
|
default:
|
|
Error(LOCATION, "Unknown operator handed to gauge_var::Evaluate(char** result)!");
|
|
return HG_RETURNNODRAW;
|
|
}
|
|
|
|
cv = cv->next;
|
|
}
|
|
|
|
if(prev_data_type == GV_CHARVAR && !strcmp(*result, prev_char_result))
|
|
{
|
|
return HG_RETURNREDRAW;
|
|
}
|
|
else
|
|
{
|
|
size_t new_char_size = strlen(*result) + 1;
|
|
if(prev_data_type != GV_CHARVAR || prev_char_size < new_char_size)
|
|
{
|
|
prev_data_type = GV_CHARVAR;
|
|
DeallocPrevVars();
|
|
prev_char_result = new char[new_char_size];
|
|
}
|
|
strcpy(prev_char_result, (*result));
|
|
|
|
return HG_RETURNLASTUPDATE;
|
|
}
|
|
}
|
|
void gauge_var::DeallocVars()
|
|
{
|
|
if(data_type < GV_PTRSTART)
|
|
{
|
|
//This may be unneccessary since this is a union
|
|
//But I'm taking no chances.
|
|
//TODO: Investigate so this isn't taking up CPU time
|
|
switch(data_type)
|
|
{
|
|
case GV_NOVAR:
|
|
break;
|
|
case GV_INTVAR:
|
|
delete int_variable;
|
|
break;
|
|
case GV_CHARVAR:
|
|
delete[] char_variable;
|
|
break;
|
|
case GV_FLOATVAR:
|
|
delete float_variable;
|
|
break;
|
|
case GV_GAUGEVAR:
|
|
delete gv_variable;
|
|
break;
|
|
default:
|
|
delete[] char_variable;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void gauge_var::DeallocPrevVars()
|
|
{
|
|
switch(prev_data_type)
|
|
{
|
|
case GV_NOVAR:
|
|
break;
|
|
case GV_INTVAR:
|
|
delete prev_int_result;
|
|
break;
|
|
case GV_CHARVAR:
|
|
delete[] prev_char_result;
|
|
break;
|
|
case GV_FLOATVAR:
|
|
delete prev_float_result;
|
|
break;
|
|
default:
|
|
delete[] prev_char_result;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//Functioning as normal storage space
|
|
void gauge_var::operator=(int* pointer)
|
|
{
|
|
data_type = GV_INTPTR;
|
|
DeallocVars();
|
|
int_variable = pointer;
|
|
}
|
|
|
|
void gauge_var::operator=(char** pointer)
|
|
{
|
|
data_type = GV_CHARPTR;
|
|
DeallocVars();
|
|
char_pointer = pointer;
|
|
}
|
|
|
|
void gauge_var::operator=(float* pointer)
|
|
{
|
|
data_type = GV_FLOATPTR;
|
|
DeallocVars();
|
|
float_variable = pointer;
|
|
}
|
|
|
|
void gauge_var::operator=(int value)
|
|
{
|
|
if(data_type != GV_INTVAR)
|
|
{
|
|
data_type = GV_INTVAR;
|
|
DeallocVars();
|
|
int_variable = new int;
|
|
}
|
|
|
|
(*int_variable) = value;
|
|
}
|
|
|
|
void gauge_var::operator=(char* value)
|
|
{
|
|
size_t new_size = strlen(value) + 1;
|
|
if(data_type != GV_CHARVAR || char_size < new_size)
|
|
{
|
|
data_type = GV_CHARVAR;
|
|
DeallocVars();
|
|
char_variable = new char[new_size];
|
|
char_size = new_size;
|
|
}
|
|
|
|
strcpy(char_variable, value);
|
|
}
|
|
|
|
void gauge_var::operator=(float value)
|
|
{
|
|
if(data_type != GV_FLOATVAR)
|
|
{
|
|
data_type = GV_FLOATVAR;
|
|
DeallocVars();
|
|
float_variable = new float;
|
|
}
|
|
|
|
(*float_variable) = value;
|
|
}
|
|
|
|
gauge_var::gauge_var()
|
|
{
|
|
//I assume NULL is 0 for this code. Panic if it isn't.
|
|
Assert(NULL == 0);
|
|
|
|
memset(this, 0, sizeof(gauge_var));
|
|
}
|
|
gauge_var::~gauge_var()
|
|
{
|
|
DeallocVars();
|
|
}
|
|
|
|
#define MAX_CHILD_OBJECTS
|
|
#define MAX_OFFSET_NUM
|
|
|
|
struct gauge_offset
|
|
{
|
|
size_t offset;
|
|
int array_index; //-1 if not an array. -2 if an array. Anything else if it's an indice into array
|
|
}
|
|
|
|
struct gauge_child
|
|
{
|
|
gauge_object* child;
|
|
|
|
unsigned int num_offsets;
|
|
|
|
gauge_offset offsets[MAX_OFFSET_NUM]; //If this isn't NULL, offset is interpreted to indicate an index into this array
|
|
}
|
|
|
|
class gauge_object_instance
|
|
{
|
|
private:
|
|
struct gauge_object_instance *next, *prev;
|
|
char name[NAME_LENGTH];
|
|
void *pointer;
|
|
|
|
std::vector<gauge_object*> (*manual_get_object_types)();
|
|
std::vector<gauge_object*> object_types;
|
|
int flags;
|
|
|
|
public:
|
|
gauge_object_instance(){name[0]='\0';pointer=NULL;get_object_types=NULL;flags=0;}
|
|
void add(class gauge_object_instance* ngip);
|
|
void set_type_func(std::vector<gauge_object*> (*manual_get_object_types)());
|
|
std::vector<gauge_object*> (*get_object_types)();
|
|
};
|
|
|
|
gauge_object_instance::gauge_object_instance(char *in_name, void *in_pointer, int in_flags, gauge_object* in_object_types, ...)
|
|
{
|
|
if(strlen(in_name) > sizeof(name))
|
|
return;
|
|
|
|
strcpy(name, in_name);
|
|
|
|
pointer = in_pointer;
|
|
flags = in_flags;
|
|
|
|
//Add the types
|
|
va_list marker;
|
|
unsigned int count = 0;
|
|
gauge_object* cotp = in_object_types;
|
|
|
|
va_start(marker, in_offsets);
|
|
while(cotp != -1)
|
|
{
|
|
object_types.push_back(cotp);
|
|
count++;
|
|
cotp = va_arg(marker, gauge_object*);
|
|
}
|
|
va_end(marker);
|
|
}
|
|
|
|
//Only call this from the main array
|
|
void gauge_object_instance::add(gauge_object_instance *ngip)
|
|
{
|
|
list_append(this, ngip);
|
|
}
|
|
|
|
class gauge_object
|
|
{
|
|
private:
|
|
struct gauge_object *next, *prev;
|
|
|
|
char name[NAME_LENGTH];
|
|
bool has_value;
|
|
|
|
unsigned int num_children;
|
|
gauge_child children[MAX_CHILD_OBJECTS];
|
|
int flags;
|
|
public:
|
|
gauge_object* add(char* in_name, bool in_has_value, int in_flags = 0);
|
|
bool copy_children(gauge_object *in_copyee);
|
|
bool add_child(gauge_object* in_child, gauge_offset* in_offsets, ...);
|
|
~gauge_object();
|
|
};
|
|
|
|
//Call delete on the first in a list of gauge_objects, and they all go away. :)
|
|
gauge_object::~gauge_object()
|
|
{
|
|
if(next != NULL)
|
|
delete next;
|
|
}
|
|
|
|
//OK, so true object derivation and that crap is out. This lets you quickly copy children.
|
|
bool gauge_object::copy_children(gauge_object *in_copyee)
|
|
{
|
|
for(unsigned int i = 0; i < in_copyee->num_children; i++)
|
|
{
|
|
if(j==MAX_CHILD_OBJECTS)
|
|
{
|
|
Warning(LOCATION, "Could only copy %d child objects to %s", name);
|
|
return false;
|
|
}
|
|
|
|
in_copyee->children[num_children] = in_copyee->children[i];
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool gauge_object::add_child(gauge_object* in_child, gauge_offset* in_offsets, ...)
|
|
{
|
|
Assert(in_child != NULL);
|
|
if(num_children == MAX_CHILD_OBJECTS)
|
|
{
|
|
Warning(LOCATION, "Could not add child object to %s", name);
|
|
return false;
|
|
}
|
|
|
|
gauge_child *gc = &children[num_children];
|
|
|
|
gc->child = in_child;
|
|
|
|
//DO Handle offset variables
|
|
va_list marker;
|
|
unsigned int count = 0;
|
|
gauge_offset* curr_offset = in_offsets;
|
|
|
|
va_start(marker, in_offsets);
|
|
while(curr_offset != -1 && count < MAX_OFFSET_NUM)
|
|
{
|
|
gc->offsets[count] = curr_offset;
|
|
count++;
|
|
curr_offset = va_arg(marker, size_t);
|
|
}
|
|
va_end(marker);
|
|
return true;
|
|
}
|
|
|
|
gauge_object* add(char* in_name, bool in_has_value, int in_flags)
|
|
{
|
|
gauge_object* gop = this; //sigh...
|
|
|
|
//Look for entries before or at this entry for a common name
|
|
while(gop != NULL)
|
|
{
|
|
if(!stricmp(gop->name, in_name))
|
|
return NULL;
|
|
else
|
|
gop = gop->prev;
|
|
}
|
|
|
|
//Look for entries after this entry for a commmon name
|
|
gop = next;
|
|
while(gop != NULL)
|
|
{
|
|
if(!stricmp(gop->name, in_name))
|
|
return NULL;
|
|
else
|
|
gop = gop->next;
|
|
}
|
|
|
|
//OK, apparently nothing has the same name...we're clear to go
|
|
gop = new gauge_object;
|
|
|
|
//Set the values
|
|
gop->prev = this;
|
|
gop->next = NULL;
|
|
strcpy(gop->name, in_name);
|
|
gop->has_value = in_has_value;
|
|
gop->num_offsets = 0;
|
|
memset(children, 0, sizeof(children));
|
|
gop->flags = in_flags;
|
|
|
|
//We're done, return a pointer to the new gauge object
|
|
return gop;
|
|
}
|
|
|
|
gauge_object* Gauge_obj_list = NULL;
|
|
std::vector<gauge_object_instances> Gauge_obj_instances;
|
|
//To use:
|
|
//Gauge_obj_list = Gauge_obj_list->Add("object", false);
|
|
//then...
|
|
//delete Gauge_obj_list;
|
|
|
|
void init()
|
|
{
|
|
if(!ships_inited)
|
|
{
|
|
Error(LOCATION, "Could not initialize hudparse.cpp as ships were not inited first.");
|
|
return;
|
|
}
|
|
//Initialize variables
|
|
gauge_offset goff;
|
|
|
|
goff.offset = 0;
|
|
goff.array_pointer = NULL;
|
|
|
|
//"core" objects
|
|
gauge_object *gol_object, *gol_escort;
|
|
gol_object = Gauge_obj_list = Gauge_obj_list->add("object", false);
|
|
gol_ship = Gauge_obj_list->add("ship", false);
|
|
|
|
//"child" objects, ie variables
|
|
gauge_object *gol_object_type;
|
|
gol_object_type = Gauge_obj_list->add("type", true);
|
|
|
|
//Assign child objects
|
|
goff.offset = offsetof(object, type);
|
|
gol_object->add_child(gol_object_type, &goff);
|
|
|
|
//Instances
|
|
|
|
Gauge_obj_instances.push_back
|
|
}
|
|
|
|
#endif
|