Files
fs2open.github.com/code/hud/hudescort.cpp
T
taylor bf18c71316 various bmpman related fixes
- some new error checking (and fixes related to that) and cleanup
 - fix EFFs not getting released/unloaded properly (was in a local tree but apparently missed CVS)
 - minor fixes for bm_release() to produce a more properly cleaned slot
 - use fast unloading for page_in stuff since we don't actually want really want the load count changing for texture maps
   and to make sure that we free the memory usage regardless of load count
2006-02-16 05:00:01 +00:00

1216 lines
31 KiB
C++

/*
* Copyright (C) Volition, Inc. 1999. All rights reserved.
*
* All source code herein is the property of Volition, Inc. You may not sell
* or otherwise commercially exploit the source or things you created based on the
* source.
*
*/
/*
* $Logfile: /Freespace2/code/Hud/HUDescort.cpp $
* $Revision: 2.29 $
* $Date: 2006-02-16 05:00:01 $
* $Author: taylor $
*
* C module for managing and displaying ships that are in an escort
*
* $Log: not supported by cvs2svn $
* Revision 2.28 2006/01/27 06:21:10 Goober5000
* replace quick sort with insertion sort in many places
* --Goober5000
*
* Revision 2.27 2006/01/16 05:54:21 Goober5000
* use IFF colors in escort list
*
* Revision 2.26 2006/01/13 03:30:59 Goober5000
* übercommit of custom IFF stuff :)
*
* Revision 2.25 2005/10/10 17:21:04 taylor
* remove NO_NETWORK
*
* Revision 2.24 2005/07/22 10:18:38 Goober5000
* CVS header tweaks
* --Goober5000
*
* Revision 2.23 2005/07/13 03:15:51 Goober5000
* remove PreProcDefine #includes in FS2
* --Goober5000
*
* Revision 2.22 2005/03/27 12:28:33 Goober5000
* clarified max hull/shield strength names and added ship guardian thresholds
* --Goober5000
*
* Revision 2.21 2005/03/02 21:24:44 taylor
* more network/inferno goodness for Windows, takes care of a few warnings too
*
* Revision 2.20 2005/02/04 10:12:30 taylor
* merge with Linux/OSX tree - p0204
*
* Revision 2.19 2004/12/25 17:02:18 wmcoolmon
* Fixed a couple of blonde moments.
*
* Revision 2.18 2004/12/24 05:07:05 wmcoolmon
* NEW_HUD compiles now. :)
*
* Revision 2.17 2004/07/26 20:47:32 Kazan
* remove MCD complete
*
* Revision 2.16 2004/07/12 16:32:49 Kazan
* MCD - define _MCD_CHECK to use memory tracking
*
* Revision 2.15 2004/07/11 03:22:50 bobboau
* added the working decal code
*
* Revision 2.14 2004/07/09 07:32:55 wmcoolmon
* Fixed conditional.
*
* Revision 2.13 2004/07/09 05:53:05 wmcoolmon
* Fixed HUD escort list for dogfight mode, and for any usage.
*
* Revision 2.12 2004/07/07 23:34:08 Kazan
* fixed a typo in one of the fs2netd strings
* played with WMCoolmon's hacked up escort list
*
* Revision 2.11 2004/07/07 21:00:07 Kazan
* FS2NetD: C2S Ping/Pong, C2S Ping/Pong, Global IP Banlist, Global Network Messages
*
* Revision 2.10 2004/07/05 05:09:19 bobboau
* FVF code, only the data that is needed is sent off to the card,,
* OGL can take advantage of this if they want but it won't break
* anything if they don't. also state block code has been implemented,
* that's totaly internal to D3D no high level code is involved.
*
* Revision 2.9 2004/06/28 02:13:07 bobboau
* high level index buffer suport and d3d implementation,
* OGL people need to get this working on your end as it's broke now
*
* Revision 2.8 2004/06/27 01:47:16 wmcoolmon
* Unneccessary warning removed, small change for VC6.
*
* Revision 2.7 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.6 2004/03/05 09:02:03 Goober5000
* Uber pass at reducing #includes
* --Goober5000
*
* Revision 2.5 2003/04/29 01:03:23 Goober5000
* implemented the custom hitpoints mod
* --Goober5000
*
* Revision 2.4 2003/01/18 09:25:41 Goober5000
* fixed bug I inadvertently introduced by modifying SIF_ flags with sexps rather
* than SF_ flags
* --Goober5000
*
* Revision 2.3 2002/12/31 07:26:40 Goober5000
* added damaged-escort-priority-all sexp
* --Goober5000
*
* Revision 2.2 2002/12/31 05:17:13 Goober5000
* fixed escort list behavior for stealthy ships
* --Goober5000
*
* Revision 2.1 2002/08/01 01:41:05 penguin
* The big include file move
*
* Revision 2.0 2002/06/03 04:02:23 penguin
* Warpcore CVS sync
*
* Revision 1.2 2002/05/13 15:11:03 mharris
* More NO_NETWORK ifndefs added
*
* Revision 1.1 2002/05/02 18:03:08 mharris
* Initial checkin - converted filenames and includes to lower case
*
*
* 22 8/04/99 2:24a Dave
* Fixed escort gauge ordering for dogfight.
*
* 21 7/30/99 7:01p Dave
* Dogfight escort gauge. Fixed up laser rendering in Glide.
*
* 20 7/29/99 1:57p Jefff
* Fixed location of "D" for disabled ships in hi-res
*
* 19 7/22/99 7:49p Dave
* Show enemy ships on the escort list in red.
*
* 18 6/23/99 10:13p Andsager
* Fix Baranec hud escort default color bug!
*
* 17 6/10/99 3:43p Dave
* Do a better job of syncing text colors to HUD gauges.
*
* 16 5/24/99 11:28a Dave
* Sexpression for adding/removing ships from the hud escort list.
*
* 15 3/30/99 5:40p Dave
* Fixed reinforcements for TvT in multiplayer.
*
* 14 3/19/99 9:51a Dave
* Checkin to repair massive source safe crash. Also added support for
* pof-style nebulae, and some new weapons code.
*
* 14 3/12/99 4:24p Andsager
* Fix bug where two or more ships are culled from escort list same frame
*
* 13 3/04/99 9:22a Andsager
* Make escort list work with ship-is-visible. When not visible, dump,
* when becoming visible, maybe add.
*
* 12 3/02/99 12:27p Andsager
* Fixed bug in hud_add_ship_to_escort -- multiple entries and
* uninitialized entries.
*
* 11 3/02/99 11:45a Anoop
* put in assert for escort list
*
* 10 3/01/99 12:00p Andsager
* Fix escort priority to look at newly added ships.
*
* 9 2/03/99 6:13p Andsager
* Added priorities to escort list. Folded escort hit info into
* escort_info struct.
*
* 8 2/01/99 9:47a Jasen
* Tweaked coords for the monitoring window in hi res.
*
* 7 1/30/99 7:48p Jasen
*
* 6 1/07/99 9:07a Jasen
* HUD coords
*
* 5 12/28/98 3:17p Dave
* Support for multiple hud bitmap filenames for hi-res mode.
*
*
* $NoKeywords: $
*/
#include "object/object.h"
#include "ship/ship.h"
#include "globalincs/linklist.h"
#include "hud/hud.h"
#include "hud/hudmessage.h"
#include "hud/hudtargetbox.h"
#include "hud/hudescort.h"
#include "hud/hudshield.h"
#include "gamesnd/gamesnd.h"
#include "graphics/font.h"
#include "io/timer.h"
#include "weapon/emp.h"
#include "globalincs/alphacolors.h"
#include "globalincs/systemvars.h"
#include "playerman/player.h"
#include "hud/hudparse.h"
#include "network/multi.h"
#include "network/multiutil.h"
#include "iff_defs/iff_defs.h"
int Show_escort_view;
typedef struct escort_info
{
int objnum;
int obj_signature; // so we are sure we have a valid objnum
int priority; // higher priority is higher in the list
short np_id; // netplayer id (for multiplayer dogfight mode)
shield_hit_info hit_info;
} escort_info;
escort_info Escort_ships[MAX_COMPLETE_ESCORT_LIST];
int Num_escort_ships;
int Max_escort_ships = 3;
hud_frames Escort_gauges[NUM_ESCORT_FRAMES];
int Escort_gauges_loaded = 0;
//int Escort_gauge_y[MAX_ESCORT_SHIPS] = { 219, 230, 241 };
/*
int Escort_gauge_text_coords[GR_NUM_RESOLUTIONS][MAX_ESCORT_SHIPS][4][2] =
{
{ // GR_640
{
{489,219},
{599,212},
{604,219},
{474,219}
},
{
{489,230},
{599,223},
{604,230},
{474,230}
},
{
{489,241},
{599,234},
{604,241},
{474,241}
},
},
{ // GR_1024
{
{869,343},
{973,338},
{981,343},
{854,343}
},
{
{869,354},
{973,349},
{981,354},
{854,354}
},
{
{869,365},
{973,360},
{981,365},
{854,365}
},
}
};
// escort gauge coords
int Escort_coords[GR_NUM_RESOLUTIONS][4][2] = {
{ // GR_640
{486, 206},
{486, 219},
{486, 230},
{486, 241}
},
{ // GR_1024
{865, 330},
{865, 343},
{865, 354},
{865, 365}
}
};
// monitoring text coords
int Monitoring_coords[GR_NUM_RESOLUTIONS][2] = {
{ // GR_640
489, 208
},
{ // GR_1024
869, 331
}
};
char *Escort_gauge_filenames[GR_NUM_RESOLUTIONS][MAX_ESCORT_SHIPS] =
{
//XSTR:OFF
{ // GR_640
"escort1",
"escort2",
"escort3"
},
{ // GR_1024
"escort1",
"escort2",
"escort3"
}
//XSTR:ON
};*/
static int Last_target_index; // index into Escort_gauges for last targeted via 'Next Escort Target' key
// data needed from HUDshield.cpp
extern hud_frames Shield_mini_gauge;
// called from HUD init, loads the bitmap data in once, and resets any data for each level
void hud_escort_init()
{
#ifndef NEW_HUD
int i;
if ( !Escort_gauges_loaded ) {
for ( i = 0; i < NUM_ESCORT_FRAMES; i++ ) {
if ( strlen(current_hud->Escort_filename[i]) ) {
Escort_gauges[i].first_frame = bm_load_animation(current_hud->Escort_filename[i], &Escort_gauges[i].num_frames);
if (Escort_gauges[i].first_frame == -1) {
Warning(LOCATION, "Could not load in ani: %s\n", current_hud->Escort_filename[i]);
return;
}
} else {
Escort_gauges[i].first_frame = -1;
}
}
Escort_gauges_loaded = 1;
}
Last_target_index = -1;
if (Max_escort_ships > MAX_COMPLETE_ESCORT_LIST) {
Max_escort_ships = MAX_COMPLETE_ESCORT_LIST;
}
#endif
}
// ----------------------------------------------------------------------
// hud_escort_clear_all()
//
void hud_escort_clear_all()
{
int i;
Num_escort_ships = 0;
for ( i = 0; i < Max_escort_ships; i++ ) {
Escort_ships[i].obj_signature = -99;
Escort_ships[i].np_id = -1;
shield_info_reset(&Escort_ships[i].hit_info);
}
}
// internal helper function for sort.
// sorts first by priority number and then alphabetically
int escort_compare_func(const void *e1, const void *e2)
{
escort_info *escort1, *escort2;
int diff;
int ret;
escort1 = (escort_info*) e1;
escort2 = (escort_info*) e2;
// multiplayer dogfight
if((Game_mode & GM_MULTIPLAYER) && (Netgame.type_flags & NG_TYPE_DOGFIGHT)){
int n1, n2;
n1 = find_player_id(escort1->np_id);
n2 = find_player_id(escort2->np_id);
if((n1 < 0) || (n2 < 0) || (Net_players[n1].m_player == NULL) || (Net_players[n2].m_player == NULL)){
ret = 0;
} else {
// player 1 is higher than player 2
if(Net_players[n1].m_player->stats.m_kill_count_ok >= Net_players[n2].m_player->stats.m_kill_count_ok){
ret = -1;
} else {
ret = 1;
}
}
} else {
diff = escort2->priority - escort1->priority;
if (diff != 0) {
ret = diff;
} else {
char *name1, *name2;
name1 = Ships[Objects[escort1->objnum].instance].ship_name;
name2 = Ships[Objects[escort2->objnum].instance].ship_name;
ret = stricmp(name1, name2);
}
}
return ret;
}
// create complete priority sorted escort list for all active ships
// escorts - array of escort info
// num_escorts - number of escorts requests in field of active ships
// This will be culled to MAX_ESCORTS, selecting the top set from escorts
void hud_create_complete_escort_list(escort_info *escorts, int *num_escorts)
{
ship_obj *so;
object *objp;
// start with none on list
*num_escorts = 0;
int idx;
// multiplayer dogfight
if((Game_mode & GM_MULTIPLAYER) && (Netgame.type_flags & NG_TYPE_DOGFIGHT)){
for(idx=0; idx<MAX_PLAYERS; idx++){
// break out of the loop when we have reached our max
if ( *num_escorts == MAX_COMPLETE_ESCORT_LIST ) {
mprintf(("exceeded max ships in big escort list"));
break;
}
// is this a valid player
if(MULTI_CONNECTED(Net_players[idx]) && !MULTI_OBSERVER(Net_players[idx]) && !MULTI_STANDALONE(Net_players[idx])){
// add the ship
escorts[*num_escorts].objnum = -1;
escorts[*num_escorts].obj_signature = -1;
escorts[*num_escorts].priority = -1;
escorts[*num_escorts].np_id = Net_players[idx].player_id;
(*num_escorts)++;
}
}
}
// all others
else {
for ( so = GET_FIRST(&Ship_obj_list); so != END_OF_LIST(&Ship_obj_list); so = GET_NEXT(so) ) {
Assert( so->objnum >= 0 && so->objnum < MAX_OBJECTS);
if((so->objnum < 0) || (so->objnum >= MAX_OBJECTS)){
continue;
}
objp = &Objects[so->objnum];
Assert( objp->type == OBJ_SHIP );
if(objp->type != OBJ_SHIP){
continue;
}
// break out of the loop when we have reached our max
if ( *num_escorts == MAX_COMPLETE_ESCORT_LIST ) {
mprintf(("exceeded max ships in big escort list"));
break;
}
// only process ships that might be on the list
if ( !(Ships[objp->instance].flags & SF_ESCORT) ){
continue;
}
// only process ships that can be seen by sensors
if ( (Ships[objp->instance].flags & SF_HIDDEN_FROM_SENSORS) ){
continue;
}
// don't process most stealth ships
if ( (Ships[objp->instance].flags2 & SF2_STEALTH) )
{
if ( Ships[objp->instance].team == Player_ship->team )
{
// friendly stealths are only not seen when explicitly specified
if ( Ships[objp->instance].flags2 & SF2_FRIENDLY_STEALTH_INVIS )
{
continue;
}
}
// non-friendly stealths are never seen
else
{
continue;
}
}
// don't process ships that are dying, or objects that should be dead
if ( (Ships[objp->instance].flags & (SF_DYING|SF_DEPARTING)) || (objp->flags & OF_SHOULD_BE_DEAD) ){
continue;
}
// add the ship
escorts[*num_escorts].objnum = so->objnum;
escorts[*num_escorts].obj_signature = objp->signature;
escorts[*num_escorts].priority = Ships[objp->instance].escort_priority;
escorts[*num_escorts].np_id = -1;
(*num_escorts)++;
}
}
}
// ----------------------------------------------------------------------
// hud_init_escort_info()
//
// Set up the escort list
//
void hud_setup_escort_list(int level)
{
int num_escorts, num_complete_escorts;
escort_info complete_escorts[MAX_COMPLETE_ESCORT_LIST];
hud_escort_clear_all();
// get complete escort list
hud_create_complete_escort_list(complete_escorts, &num_complete_escorts);
// sort escort list by priority
insertion_sort(complete_escorts, num_complete_escorts, sizeof(escort_info), escort_compare_func);
// set number in escort list
num_escorts = num_complete_escorts;
if (num_escorts > Max_escort_ships) {
num_escorts = Max_escort_ships;
}
// add ships to escort list
for (Num_escort_ships=0; Num_escort_ships<num_escorts; Num_escort_ships++) {
Escort_ships[Num_escort_ships].obj_signature = complete_escorts[Num_escort_ships].obj_signature;
Escort_ships[Num_escort_ships].priority = complete_escorts[Num_escort_ships].priority;
Escort_ships[Num_escort_ships].objnum = complete_escorts[Num_escort_ships].objnum;
Escort_ships[Num_escort_ships].np_id = complete_escorts[Num_escort_ships].np_id;
}
if(level){
Show_escort_view = 1;
}
}
// combine complete escort list with Escort_ships, keeping valid hit info
void merge_escort_lists(escort_info *complete_escorts, int num_complete_escorts)
{
int i, j, top_complete_escorts;
int valid_hit_info[MAX_COMPLETE_ESCORT_LIST];
// may be > 1 ship change to list (ie, 2 or 3 culled during same frame)
// set Num_escort_ships and cap
Num_escort_ships = num_complete_escorts;
if (Num_escort_ships > Max_escort_ships) {
Num_escort_ships = Max_escort_ships;
}
// nothing to do
if (Num_escort_ships == 0) {
return;
}
// check used as a flag whether top slots in complete_escorts were copied
// this is important re. hit info
for (i=0; i<Max_escort_ships; i++) {
valid_hit_info[i] = 0;
}
// get the top slots in complete escort list that will be copied onto Escort_ships
top_complete_escorts = num_complete_escorts;
if (top_complete_escorts > Max_escort_ships) {
top_complete_escorts = Max_escort_ships;
}
// copy for Escort_ships to complete_escorts to retain hit_info
if(!((Game_mode & GM_MULTIPLAYER) && (Netgame.type_flags & NG_TYPE_DOGFIGHT))) {
for (i=0; i<top_complete_escorts; i++) {
for (j=0; j<Num_escort_ships; j++) {
if (Escort_ships[j].obj_signature == complete_escorts[i].obj_signature) {
complete_escorts[i] = Escort_ships[j];
valid_hit_info[i] = 1;
break;
}
}
}
// copy top slots to Escort_ships
for (i=0; i<top_complete_escorts; i++) {
Escort_ships[i] = complete_escorts[i];
// check all ships are valid
int objnum = Escort_ships[i].objnum;
Assert( objnum >=0 && objnum < MAX_OBJECTS );
if((objnum < 0) || (objnum >= MAX_OBJECTS)){
continue;
}
if ( !valid_hit_info[i] ) {
shield_info_reset(&Escort_ships[i].hit_info);
}
}
}
// reset Num_escort_ships
Num_escort_ships = top_complete_escorts;
}
// ----------------------------------------------------------------------
// hud_remove_ship_from_escort_index()
//
// Take a ship out of the escort list
void hud_remove_ship_from_escort_index(int dead_index, int objnum)
{
int i, count, num_complete_escorts;
escort_info bakup_arr[MAX_COMPLETE_ESCORT_LIST], complete_escorts[MAX_COMPLETE_ESCORT_LIST];
// remove him from escort list
if((objnum >= 0) && (Objects[objnum].type == OBJ_SHIP) && (Objects[objnum].instance >= 0)){
Ships[Objects[objnum].instance].flags &= ~SF_ESCORT;
}
count = 0;
for ( i = 0; i < Num_escort_ships; i++ ) {
if ( i != dead_index ) {
bakup_arr[count++] = Escort_ships[i];
}
}
for ( i = 0; i < count; i++ ) {
Escort_ships[i] = bakup_arr[i];
}
Num_escort_ships--;
Assert(Num_escort_ships >= 0);
// get complete escort list
hud_create_complete_escort_list(complete_escorts, &num_complete_escorts);
// sort escort list by priority
insertion_sort(complete_escorts, num_complete_escorts, sizeof(escort_info), escort_compare_func);
// merge list
merge_escort_lists(complete_escorts, num_complete_escorts);
hud_gauge_popup_start(HUD_ESCORT_VIEW);
}
// called once per frame to remove dead or departed ships from the escort list
void hud_escort_cull_list()
{
int i, objnum;
int np_index;
// multiplayer dogfight
if((Game_mode & GM_MULTIPLAYER) && (Netgame.type_flags & NG_TYPE_DOGFIGHT)){
for ( i = 0; i < Num_escort_ships; i++ ) {
np_index = find_player_id(Escort_ships[i].np_id);
// maybe remove him if he left
if ( np_index < 0 ) {
hud_remove_ship_from_escort_index(i, -1);
i--;
}
}
}
// everything else
else {
for ( i = 0; i < Num_escort_ships; i++ ) {
objnum = Escort_ships[i].objnum;
Assert( objnum >=0 && objnum < MAX_OBJECTS );
if ( Objects[objnum].flags & OF_SHOULD_BE_DEAD || Ships[Objects[objnum].instance].flags & SF_HIDDEN_FROM_SENSORS ) {
hud_remove_ship_from_escort_index(i, objnum);
i--;
}
}
}
}
// Set the color for the text to be displayed
// Goober5000 - changed second parameter from "friendly" (true/false) to "team";
// also changed from hud color or red to team color
int hud_escort_set_gauge_color(int index, int team)
{
int is_flashing = 0;
int is_bright = 0;
int seen_from_team = (Player_ship != NULL) ? Player_ship->team : -1;
shield_hit_info *shi;
shi = &Escort_ships[index].hit_info;
// multiplayer dogfight
if((Game_mode & GM_MULTIPLAYER) && (Netgame.type_flags & NG_TYPE_DOGFIGHT))
{
hud_set_gauge_color(HUD_ESCORT_VIEW);
return 0;
}
// set flashing color
if (!timestamp_elapsed(shi->shield_hit_timers[HULL_HIT_OFFSET]))
{
if (timestamp_elapsed(shi->shield_hit_next_flash[HULL_HIT_OFFSET]))
{
shi->shield_hit_next_flash[HULL_HIT_OFFSET] = timestamp(SHIELD_FLASH_INTERVAL);
shi->shield_show_bright ^= (1 << HULL_HIT_OFFSET); // toggle between default and bright frames
}
is_flashing = 1;
if (shi->shield_show_bright & (1 << HULL_HIT_OFFSET))
{
is_bright = 1;
}
}
// Goober5000 - now base this on team color
gr_set_color_fast(iff_get_color_by_team(team, seen_from_team, is_bright));
// Goober5000 - an alternative; same as original but incorporating teams for non-friendlies
/*
if ((seen_from_team == team) || (seen_from_team < 0)) // :V: sez assume friendly if Player_ship is NULL
hud_set_gauge_color(HUD_ESCORT_VIEW, is_bright ? HUD_C_BRIGHT : HUD_C_DIM);
else
gr_set_color_fast(iff_get_color_by_team(team, seen_from_team, is_bright));
*/
// Goober5000 - original color logic
/*
if ((seen_from_team == team) || (seen_from_team < 0)) // :V: sez assume friendly if Player_ship is NULL
hud_set_gauge_color(HUD_ESCORT_VIEW, is_bright ? HUD_C_BRIGHT : HUD_C_DIM);
else
gr_set_color_fast(is_bright ? &Color_bright_red : &Color_red);
*/
return is_flashing;
}
// multiplayer dogfight
void hud_escort_show_icon_dogfight(int x, int y, int index)
{
#ifndef NEW_HUD
int hull_integrity = 100;
char buf[255];
int np_index;
object *objp;
ship_info *sip;
int stat_shift = 40;
// always use the standard color to avoid confusion
hud_set_gauge_color(HUD_ESCORT_VIEW);
// netplayer index
np_index = find_player_id(Escort_ships[index].np_id);
if((np_index < 0) || (np_index >= MAX_PLAYERS) || (Net_players[np_index].m_player == NULL)){
return;
}
// print out player name
strcpy(buf, Net_players[np_index].m_player->callsign);
gr_force_fit_string(buf, 255, 100 - stat_shift);
emp_hud_string( x + current_hud->Escort_name[0], y + current_hud->Escort_name[1], EG_ESCORT1 + index, buf);
// can we get the player object?
objp = NULL;
if((Net_players[np_index].m_player->objnum >= 0) && (Net_players[np_index].m_player->objnum < MAX_OBJECTS) && (Objects[Net_players[np_index].m_player->objnum].type == OBJ_SHIP)){
objp = &Objects[Net_players[np_index].m_player->objnum];
if((objp->instance >= 0) && (objp->instance < MAX_SHIPS) && (Ships[objp->instance].ship_info_index >= 0) && (Ships[objp->instance].ship_info_index < MAX_SHIPS)){
sip = &Ship_info[Ships[objp->instance].ship_info_index];
} else {
return;
}
hull_integrity = (int)(((float)objp->hull_strength / (float)Ships[objp->instance].ship_max_hull_strength) * 100.0f);
if(hull_integrity < 0){
hull_integrity = 0;
}
}
// show ship integrity
if(objp == NULL){
emp_hud_printf( x+current_hud->Escort_integrity[0] - stat_shift, y+current_hud->Escort_integrity[1], EG_NULL, "%d", Net_players[np_index].m_player->stats.m_kill_count_ok);
} else {
emp_hud_printf( x+current_hud->Escort_integrity[0] - stat_shift, y+current_hud->Escort_integrity[1], EG_NULL, "(%d%%) %d", hull_integrity, Net_players[np_index].m_player->stats.m_kill_count_ok);
}
#endif
}
// draw the shield icon and integrity for the escort ship
void hud_escort_show_icon(int x, int y, int index)
{
#ifndef NEW_HUD
if((Game_mode & GM_MULTIPLAYER) && (Netgame.type_flags & NG_TYPE_DOGFIGHT) && index <= 2)
{
hud_escort_show_icon_dogfight(x, y, index);
return;
}
float shields, integrity;
int screen_integrity, offset;
char buf[255];
object *objp = &Objects[Escort_ships[index].objnum];
ship *sp = &Ships[objp->instance];
// determine if its "friendly" or not
// Goober5000 - changed in favor of just passing the team
hud_escort_set_gauge_color(index, sp->team);
/*
if(Player_ship != NULL){
hud_escort_set_gauge_color(index, (sp->team == Player_ship->team) ? 1 : 0);
} else {
hud_escort_set_gauge_color(index, 1);
}
*/
// draw a 'D' if a ship is disabled
if ( (sp->flags & SF_DISABLED) || (ship_subsys_disrupted(sp, SUBSYSTEM_ENGINE)) ) {
emp_hud_string( x + current_hud->Escort_status[0], y + current_hud->Escort_status[1], EG_NULL, XSTR( "D", 284));
}
// print out ship name
strcpy(buf, sp->ship_name);
gr_force_fit_string(buf, 255, 100);
emp_hud_string( x + current_hud->Escort_name[0], y + current_hud->Escort_name[1], EG_ESCORT1 + index, buf);
// show ship integrity
hud_get_target_strength(objp, &shields, &integrity);
screen_integrity = fl2i(integrity*100 + 0.5f);
offset = 0;
if ( screen_integrity < 100 ) {
offset = 2;
if ( screen_integrity == 0 ) {
if ( integrity > 0 ) {
screen_integrity = 1;
}
}
}
emp_hud_printf( x+current_hud->Escort_integrity[0] + offset, y+current_hud->Escort_integrity[1], EG_NULL, "%d", screen_integrity);
//Let's be nice.
hud_set_gauge_color(HUD_ESCORT_VIEW);
#endif
}
// ----------------------------------------------------------------------
// hud_display_escort()
//
// Display the data on ships in the escort list
void hud_display_escort()
{
#ifndef NEW_HUD
int i = 0;
if ( !Show_escort_view ) {
return;
}
if ( !Num_escort_ships ) {
return;
}
// hud_set_default_color();
hud_set_gauge_color(HUD_ESCORT_VIEW);
// draw the top of the escort view
GR_AABITMAP(Escort_gauges[0].first_frame, current_hud->Escort_coords[0], current_hud->Escort_coords[1]);
gr_string(current_hud->Escort_htext_coords[0], current_hud->Escort_htext_coords[1], current_hud->Escort_htext);
int x = current_hud->Escort_coords[0] + current_hud->Escort_list[0];
int y = current_hud->Escort_coords[1] + current_hud->Escort_list[1];
//This is temporary
Num_escort_ships--;
i=0;
if(Num_escort_ships)
{
for(; i < Num_escort_ships; i++)
{
if(i != 0)
{
x += current_hud->Escort_entry[0];
y += current_hud->Escort_entry[1];
}
GR_AABITMAP(Escort_gauges[1].first_frame, x, y);
//Now we just show the ships info
hud_escort_show_icon(x, y, i);
}
//Increment for last entry
x += current_hud->Escort_entry_last[0];
y += current_hud->Escort_entry_last[1];
}
//Back to right #
Num_escort_ships++;
//Show the last escort entry
GR_AABITMAP(Escort_gauges[2].first_frame, x, y);
hud_escort_show_icon(x, y, i);
/*
if ( Num_escort_ships >= 2 ) {
GR_AABITMAP(Escort_gauges[1].first_frame, Escort_coords[gr_screen.res][1][0], Escort_coords[gr_screen.res][1][1]);
}
if ( Num_escort_ships >= 3 ) {
GR_AABITMAP(Escort_gauges[1].first_frame, Escort_coords[gr_screen.res][2][0], Escort_coords[gr_screen.res][2][1]);
}
// draw bottom of box
GR_AABITMAP(Escort_gauges[2].first_frame, Escort_coords[gr_screen.res][3][0], Escort_coords[gr_screen.res][Num_escort_ships][1]);
// multiplayer dogfight
if((Game_mode & GM_MULTIPLAYER) && (Netgame.type_flags & NG_TYPE_DOGFIGHT)){
// draw the escort ship data
for ( i = 0; i < Num_escort_ships; i++ ) {
// oops. only show top 3
if(i > 2){
break;
}
// draw
hud_escort_show_icon_dogfight(i);
}
}
// everything else
else {
// draw the escort ship data
for ( i = 0; i < Num_escort_ships; i++ ) {
objp = &Objects[Escort_ships[i].objnum];
hud_escort_show_icon(i, objp);
}
}*/
#endif
}
// ----------------------------------------------------------------------
// hud_escort_view_toggle()
//
void hud_escort_view_toggle()
{
Show_escort_view ^= 1;
if ( Show_escort_view ) {
HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "Escort view enabled", 286));
} else {
HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "Escort view disabled", 287));
}
}
// try to add a ship to the escort list, if slot available
void hud_add_ship_to_escort(int objnum, int supress_feedback)
{
escort_info complete_escorts[MAX_COMPLETE_ESCORT_LIST];
int num_complete_escorts, idx, found;
// get complete escort list
hud_create_complete_escort_list(complete_escorts, &num_complete_escorts);
// check if ship is already on complete escort list
found = 0;
for (idx=0; idx<num_complete_escorts; idx++) {
if (complete_escorts[idx].obj_signature == Objects[objnum].signature) {
found = 1;
break;
}
}
// add new ship into complete list
if ( !found ) {
complete_escorts[num_complete_escorts].objnum = objnum;
complete_escorts[num_complete_escorts].obj_signature = Objects[objnum].signature;
complete_escorts[num_complete_escorts].priority = Ships[Objects[objnum].instance].escort_priority;
// remove him from escort list
Ships[Objects[objnum].instance].flags |= SF_ESCORT;
num_complete_escorts++;
}
// sort escort list by priority
insertion_sort(complete_escorts, num_complete_escorts, sizeof(escort_info), escort_compare_func);
// merge list
merge_escort_lists(complete_escorts, num_complete_escorts);
// maybe do feedback
if ( (Num_escort_ships == Max_escort_ships) && !supress_feedback) {
found = 0;
// search thru list for objnum
for (idx=0; idx<Num_escort_ships; idx++) {
if (Escort_ships[idx].objnum == objnum) {
found = 1;
break;
}
}
if (!found) {
HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "Escort list is full with %d ships", 288), Num_escort_ships);
snd_play( &Snds[SND_TARGET_FAIL]);
}
}
hud_gauge_popup_start(HUD_ESCORT_VIEW);
}
// ----------------------------------------------------------------------
// hud_add_remove_ship_escort()
//
void hud_add_remove_ship_escort(int objnum, int supress_feedback)
{
int in_escort, i;
// no ships on the escort list in multiplayer dogfight
if((Game_mode & GM_MULTIPLAYER) && (Netgame.type_flags & NG_TYPE_DOGFIGHT)){
return;
}
if ( objnum < 0 ) {
Int3();
return;
}
if ( Objects[objnum].type != OBJ_SHIP ) {
if ( !supress_feedback ) {
snd_play( &Snds[SND_TARGET_FAIL]);
}
return;
}
in_escort = 0;
for ( i = 0; i < Num_escort_ships; i++ ) {
if ( Escort_ships[i].obj_signature == Objects[objnum].signature ) {
in_escort = 1;
break;
}
}
if ( in_escort ) {
hud_remove_ship_from_escort_index(i, objnum);
return;
}
hud_add_ship_to_escort(objnum, supress_feedback);
}
void hud_remove_ship_from_escort(int objnum)
{
int in_escort, i;
// no ships on the escort list in multiplayer dogfight
if((Game_mode & GM_MULTIPLAYER) && (Netgame.type_flags & NG_TYPE_DOGFIGHT)){
return;
}
if ( objnum < 0 ) {
Int3();
return;
}
in_escort = 0;
for ( i = 0; i < Num_escort_ships; i++ ) {
if ( Escort_ships[i].obj_signature == Objects[objnum].signature ) {
in_escort = 1;
break;
}
}
if ( in_escort ) {
hud_remove_ship_from_escort_index(i, objnum);
return;
}
}
// Called whenever a ship is hit to determine if that ship is in the escort list. If it
// is, then start timers to flash the name hull/shield icon for that ship.
void hud_escort_ship_hit(object *objp, int quadrant)
{
int num, i;
shield_hit_info *shi;
// no ships on the escort list in multiplayer dogfight
if((Game_mode & GM_MULTIPLAYER) && (Netgame.type_flags & NG_TYPE_DOGFIGHT)){
return;
}
for ( i = 0; i < Num_escort_ships; i++ ) {
if ( Escort_ships[i].objnum == OBJ_INDEX(objp) ) {
shi = &Escort_ships[i].hit_info;
num = Quadrant_xlate[quadrant];
hud_gauge_popup_start(HUD_ESCORT_VIEW);
if ( quadrant >= 0 ) {
shi->shield_hit_timers[num] = timestamp(SHIELD_HIT_DURATION);
} else {
shi->shield_hit_timers[HULL_HIT_OFFSET] = timestamp(SHIELD_HIT_DURATION);
}
}
}
}
// target the next ship in the escort list
void hud_escort_target_next()
{
int objnum;
if ( Num_escort_ships == 0 ) {
snd_play( &Snds[SND_TARGET_FAIL], 0.0f );
return;
}
Last_target_index++;
if ( Last_target_index >= Num_escort_ships ) {
Last_target_index = 0;
}
objnum = Escort_ships[Last_target_index].objnum;
set_target_objnum( Player_ai, objnum);
hud_restore_subsystem_target(&Ships[Objects[objnum].instance]);
}
// return the number of ships currently on the escort list
int hud_escort_num_ships_on_list()
{
return Num_escort_ships;
}
// Return the object number for the ship at index position in the escort list
int hud_escort_return_objnum(int index)
{
int escort_objnum, escort_sig;
if ( index >= Num_escort_ships ) {
return -1;
}
escort_objnum = Escort_ships[index].objnum;
escort_sig = Escort_ships[index].obj_signature;
if ( escort_objnum < 0 ) {
return -1;
}
// ensure this is still a valid index
if ( Objects[escort_objnum].signature != escort_sig ) {
return -1;
}
return Escort_ships[index].objnum;
}
void hudescort_page_in()
{
int i;
for ( i = 0; i < NUM_ESCORT_FRAMES; i++ ) {
bm_page_in_aabitmap( Escort_gauges[i].first_frame, Escort_gauges[i].num_frames);
}
}
void hud_escort_add_player(short id)
{
Assert(Game_mode & GM_MULTIPLAYER);
if(!(Game_mode & GM_MULTIPLAYER)){
return;
}
int idx;
// just go through and add as long as its not a duplicate
for(idx=0; idx<Num_escort_ships; idx++){
if(Escort_ships[idx].np_id == id){
return;
}
}
// re-setup the escort list
hud_setup_escort_list(0);
}
void hud_escort_remove_player(short id)
{
Assert(Game_mode & GM_MULTIPLAYER);
if(!(Game_mode & GM_MULTIPLAYER)){
return;
}
int idx;
// find the instance and remove it if possible
for(idx=0; idx<Num_escort_ships; idx++){
if(Escort_ships[idx].np_id == id){
hud_remove_ship_from_escort_index(idx, -1);
return;
}
}
}