2014-06-01 17:55:23 +00:00
|
|
|
/*
|
|
|
|
* This file is part of the DXX-Rebirth project <http://www.dxx-rebirth.com/>.
|
|
|
|
* It is copyright by its individual contributors, as recorded in the
|
|
|
|
* project's Git history. See COPYING.txt at the top level for license
|
|
|
|
* terms and a link to the Git history.
|
|
|
|
*/
|
2006-03-20 17:12:09 +00:00
|
|
|
/*
|
|
|
|
*
|
|
|
|
* Routines for displaying HUD messages...
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
|
|
#include "hudmsg.h"
|
|
|
|
#include "pstypes.h"
|
|
|
|
#include "u_mem.h"
|
|
|
|
#include "strutil.h"
|
|
|
|
#include "console.h"
|
2014-11-23 04:36:58 +00:00
|
|
|
#include "object.h"
|
2006-03-20 17:12:09 +00:00
|
|
|
#include "inferno.h"
|
|
|
|
#include "game.h"
|
|
|
|
#include "screens.h"
|
|
|
|
#include "gauges.h"
|
|
|
|
#include "physics.h"
|
2012-07-07 18:35:06 +00:00
|
|
|
#include "dxxerror.h"
|
2006-03-20 17:12:09 +00:00
|
|
|
#include "menu.h" // For the font.
|
|
|
|
#include "collide.h"
|
|
|
|
#include "newdemo.h"
|
|
|
|
#include "player.h"
|
|
|
|
#include "gamefont.h"
|
|
|
|
#include "screens.h"
|
|
|
|
#include "text.h"
|
|
|
|
#include "laser.h"
|
|
|
|
#include "args.h"
|
2008-04-13 00:28:36 +00:00
|
|
|
#include "playsave.h"
|
2013-12-20 00:07:07 +00:00
|
|
|
#include "countarray.h"
|
2006-03-20 17:12:09 +00:00
|
|
|
|
2015-08-12 03:11:46 +00:00
|
|
|
namespace {
|
|
|
|
|
2013-12-20 00:07:07 +00:00
|
|
|
struct hudmsg
|
2006-03-20 17:12:09 +00:00
|
|
|
{
|
2010-07-13 06:35:25 +00:00
|
|
|
fix time;
|
2015-01-29 04:27:36 +00:00
|
|
|
ntstring<HUD_MESSAGE_LENGTH> message;
|
|
|
|
template <typename M>
|
|
|
|
hudmsg(const fix& t, M &&m) :
|
2013-12-20 00:07:07 +00:00
|
|
|
time(t)
|
|
|
|
{
|
2015-01-29 04:27:36 +00:00
|
|
|
message.copy_if(m);
|
2013-12-20 00:07:07 +00:00
|
|
|
}
|
|
|
|
};
|
2006-03-20 17:12:09 +00:00
|
|
|
|
2015-08-12 03:11:46 +00:00
|
|
|
}
|
|
|
|
|
2013-12-20 00:07:07 +00:00
|
|
|
struct hudmsg_array_t : public count_array_t<hudmsg, HUD_MAX_NUM_STOR> {};
|
|
|
|
static hudmsg_array_t HUD_messages;
|
2006-03-20 17:12:09 +00:00
|
|
|
|
|
|
|
|
2010-07-13 06:35:25 +00:00
|
|
|
int HUD_toolong = 0;
|
|
|
|
static int HUD_color = -1;
|
2013-06-23 16:27:34 +00:00
|
|
|
static int HUD_init_message_literal_worth_showing(int class_flag, const char *message);
|
2006-03-20 17:12:09 +00:00
|
|
|
|
|
|
|
void HUD_clear_messages()
|
|
|
|
{
|
2013-12-20 00:07:07 +00:00
|
|
|
HUD_messages.clear();
|
2010-07-13 06:35:25 +00:00
|
|
|
HUD_toolong = 0;
|
|
|
|
HUD_color = -1;
|
2006-03-20 17:12:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// Writes a message on the HUD and checks its timer.
|
|
|
|
void HUD_render_message_frame()
|
|
|
|
{
|
2013-12-20 00:07:07 +00:00
|
|
|
int y;
|
2010-07-13 06:35:25 +00:00
|
|
|
|
|
|
|
HUD_toolong = 0;
|
2006-03-20 17:12:09 +00:00
|
|
|
|
2013-12-20 00:07:07 +00:00
|
|
|
if (HUD_messages.empty())
|
2006-03-20 17:12:09 +00:00
|
|
|
return;
|
|
|
|
|
2013-12-20 00:07:07 +00:00
|
|
|
auto expired = [](hudmsg &h) -> int {
|
|
|
|
if (h.time <= FrameTime)
|
|
|
|
return 1;
|
|
|
|
h.time -= FrameTime;
|
|
|
|
return 0;
|
|
|
|
};
|
|
|
|
HUD_messages.erase_if(expired);
|
2006-03-20 17:12:09 +00:00
|
|
|
|
2010-07-13 06:35:25 +00:00
|
|
|
// display last $HUD_MAX_NUM_DISP messages on the list
|
2013-12-20 00:07:07 +00:00
|
|
|
if (!HUD_messages.empty())
|
2010-07-13 06:35:25 +00:00
|
|
|
{
|
2006-03-20 17:12:09 +00:00
|
|
|
if (HUD_color == -1)
|
|
|
|
HUD_color = BM_XRGB(0,28,0);
|
|
|
|
|
2008-02-24 14:41:27 +00:00
|
|
|
gr_set_curfont( GAME_FONT );
|
|
|
|
y = FSPACY(1);
|
2007-06-14 20:52:14 +00:00
|
|
|
|
2015-06-13 22:42:22 +00:00
|
|
|
const auto &&line_spacing = LINE_SPACING;
|
2013-03-03 01:03:33 +00:00
|
|
|
#if defined(DXX_BUILD_DESCENT_II)
|
2007-06-14 20:52:14 +00:00
|
|
|
if (Guided_missile[Player_num] && Guided_missile[Player_num]->type==OBJ_WEAPON && Guided_missile[Player_num]->id==GUIDEDMISS_ID &&
|
2008-04-13 00:28:36 +00:00
|
|
|
Guided_missile[Player_num]->signature==Guided_missile_sig[Player_num] && PlayerCfg.GuidedInBigWindow)
|
2015-06-13 22:42:22 +00:00
|
|
|
y += line_spacing;
|
2013-03-03 01:03:33 +00:00
|
|
|
#endif
|
2007-06-14 20:52:14 +00:00
|
|
|
|
2013-12-20 00:07:07 +00:00
|
|
|
hudmsg_array_t::iterator i, e = HUD_messages.end();
|
|
|
|
if (HUD_messages.count() < HUD_MAX_NUM_DISP)
|
|
|
|
i = HUD_messages.begin();
|
|
|
|
else
|
|
|
|
i = e - HUD_MAX_NUM_DISP;
|
|
|
|
if (strlen(i->message) > 38)
|
|
|
|
HUD_toolong = 1;
|
|
|
|
for (; i != e; ++i ) {
|
2007-06-14 20:52:14 +00:00
|
|
|
gr_set_fontcolor( HUD_color, -1);
|
|
|
|
|
2013-12-20 00:07:07 +00:00
|
|
|
gr_string(0x8000,y, &i->message[0] );
|
2015-06-13 22:42:22 +00:00
|
|
|
y += line_spacing;
|
2006-03-20 17:12:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
gr_set_curfont( GAME_FONT );
|
|
|
|
}
|
|
|
|
|
2013-06-23 16:19:50 +00:00
|
|
|
static int is_worth_showing(int class_flag)
|
|
|
|
{
|
|
|
|
if (PlayerCfg.NoRedundancy && (class_flag & HM_REDUNDANT))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (PlayerCfg.MultiMessages && (Game_mode & GM_MULTI) && !(class_flag & HM_MULTI))
|
|
|
|
return 0;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2006-03-20 17:12:09 +00:00
|
|
|
// Call to flash a message on the HUD. Returns true if message drawn.
|
|
|
|
// (message might not be drawn if previous message was same)
|
2013-06-23 16:19:50 +00:00
|
|
|
int HUD_init_message_va(int class_flag, const char * format, va_list args)
|
2006-03-20 17:12:09 +00:00
|
|
|
{
|
2013-06-23 16:19:50 +00:00
|
|
|
if (!is_worth_showing(class_flag))
|
|
|
|
return 0;
|
|
|
|
|
2010-10-10 10:48:24 +00:00
|
|
|
#ifndef macintosh
|
2010-07-13 06:35:25 +00:00
|
|
|
char message[HUD_MESSAGE_LENGTH+1] = "";
|
2010-10-10 10:48:24 +00:00
|
|
|
#else
|
|
|
|
char message[1024] = "";
|
|
|
|
#endif
|
2006-03-20 17:12:09 +00:00
|
|
|
|
2010-10-10 10:48:24 +00:00
|
|
|
#ifndef macintosh
|
2010-07-13 06:35:25 +00:00
|
|
|
vsnprintf(message, sizeof(char)*HUD_MESSAGE_LENGTH, format, args);
|
2010-10-10 10:48:24 +00:00
|
|
|
#else
|
|
|
|
vsprintf(message, format, args);
|
|
|
|
#endif
|
2013-12-22 17:18:44 +00:00
|
|
|
int r = HUD_init_message_literal_worth_showing(class_flag, message);
|
|
|
|
if (r)
|
|
|
|
con_puts(CON_HUD, message);
|
|
|
|
return r;
|
2013-06-23 16:27:34 +00:00
|
|
|
}
|
2006-03-20 17:12:09 +00:00
|
|
|
|
2010-11-21 20:20:00 +00:00
|
|
|
|
2013-06-23 16:27:34 +00:00
|
|
|
static int HUD_init_message_literal_worth_showing(int class_flag, const char *message)
|
|
|
|
{
|
2010-11-21 20:20:00 +00:00
|
|
|
// check if message is already in list and bail out if so
|
2013-12-20 00:07:07 +00:00
|
|
|
if (!HUD_messages.empty())
|
2010-07-13 06:35:25 +00:00
|
|
|
{
|
2013-12-20 00:07:07 +00:00
|
|
|
hudmsg_array_t::iterator i, e = HUD_messages.end();
|
2011-04-11 19:27:31 +00:00
|
|
|
// if "normal" message, only check if it's the same at the most recent one, if marked as "may duplicate" check whole list
|
2013-12-20 00:07:07 +00:00
|
|
|
if (class_flag & HM_MAYDUPL)
|
|
|
|
i = HUD_messages.begin();
|
|
|
|
else
|
|
|
|
i = e - 1;
|
|
|
|
for (; i != e; ++i)
|
2010-07-13 06:35:25 +00:00
|
|
|
{
|
2013-12-20 00:07:07 +00:00
|
|
|
if (!d_stricmp(message, i->message))
|
2010-11-21 20:20:00 +00:00
|
|
|
{
|
2013-12-20 00:07:07 +00:00
|
|
|
i->time = F1_0*2; // keep redundant message in list
|
|
|
|
if (std::distance(i, e) < HUD_MAX_NUM_DISP) // if redundant message on display, update them all
|
|
|
|
{
|
|
|
|
if (HUD_messages.count() < HUD_MAX_NUM_DISP)
|
|
|
|
i = HUD_messages.begin();
|
|
|
|
else
|
|
|
|
i = HUD_messages.end() - HUD_MAX_NUM_DISP;
|
|
|
|
for (unsigned j = 1; i != e; ++i, j++)
|
|
|
|
i->time = F1_0*(j*2);
|
|
|
|
}
|
2010-11-21 20:20:00 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2010-07-13 06:35:25 +00:00
|
|
|
}
|
|
|
|
}
|
2006-03-20 17:12:09 +00:00
|
|
|
|
2013-12-20 00:07:07 +00:00
|
|
|
if (HUD_messages.count() >= HUD_MAX_NUM_STOR)
|
2010-07-13 06:35:25 +00:00
|
|
|
{
|
2015-01-29 04:27:36 +00:00
|
|
|
std::move(HUD_messages.begin() + 1, HUD_messages.end(), HUD_messages.begin());
|
2013-12-20 00:07:07 +00:00
|
|
|
HUD_messages.pop_back();
|
2006-03-20 17:12:09 +00:00
|
|
|
}
|
2013-12-20 00:07:07 +00:00
|
|
|
fix t;
|
|
|
|
if (HUD_messages.count() + 1 < HUD_MAX_NUM_DISP)
|
|
|
|
t = F1_0*3; // one message - display 3 secs
|
2010-07-13 06:35:25 +00:00
|
|
|
else
|
|
|
|
{
|
2013-12-20 00:07:07 +00:00
|
|
|
hudmsg_array_t::iterator e = HUD_messages.end(), i = e - HUD_MAX_NUM_DISP;
|
|
|
|
for (unsigned j = 1; ++i != e; j++) // multiple messages - display 2 seconds each
|
|
|
|
i->time = F1_0*(j*2);
|
|
|
|
t = F1_0 * ((HUD_MAX_NUM_DISP + 1) * 2);
|
2006-03-20 17:12:09 +00:00
|
|
|
}
|
2013-12-20 00:07:07 +00:00
|
|
|
HUD_messages.emplace_back(t, message);
|
2007-01-14 01:55:59 +00:00
|
|
|
|
2007-08-26 11:46:10 +00:00
|
|
|
if (HUD_color == -1)
|
|
|
|
HUD_color = BM_XRGB(0,28,0);
|
|
|
|
|
2006-03-20 17:12:09 +00:00
|
|
|
if (Newdemo_state == ND_STATE_RECORDING )
|
|
|
|
newdemo_record_hud_message( message );
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2013-12-08 23:37:40 +00:00
|
|
|
int (HUD_init_message)(int class_flag, const char * format, ... )
|
2006-03-20 17:12:09 +00:00
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
va_list args;
|
|
|
|
|
|
|
|
va_start(args, format);
|
2010-11-21 20:20:00 +00:00
|
|
|
ret = HUD_init_message_va(class_flag, format, args);
|
2006-03-20 17:12:09 +00:00
|
|
|
va_end(args);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2013-06-23 16:27:34 +00:00
|
|
|
int HUD_init_message_literal(int class_flag, const char *str)
|
|
|
|
{
|
|
|
|
if (!is_worth_showing(class_flag))
|
|
|
|
return 0;
|
2013-12-22 17:18:44 +00:00
|
|
|
int r = HUD_init_message_literal_worth_showing(class_flag, str);
|
|
|
|
if (r)
|
|
|
|
con_puts(CON_HUD, str);
|
|
|
|
return r;
|
2013-06-23 16:27:34 +00:00
|
|
|
}
|
2006-03-20 17:12:09 +00:00
|
|
|
|
|
|
|
void player_dead_message(void)
|
|
|
|
{
|
2008-02-24 14:41:27 +00:00
|
|
|
if (Player_exploded) {
|
2015-07-25 23:10:46 +00:00
|
|
|
if ( get_local_player().lives < 2 ) {
|
2015-09-29 02:41:22 +00:00
|
|
|
int x, y, w, h;
|
2008-02-24 14:41:27 +00:00
|
|
|
gr_set_curfont( HUGE_FONT );
|
2015-09-29 02:41:22 +00:00
|
|
|
gr_get_string_size(TXT_GAME_OVER, &w, &h, nullptr);
|
2008-02-24 14:41:27 +00:00
|
|
|
w += 20;
|
|
|
|
h += 8;
|
|
|
|
x = (grd_curcanv->cv_bitmap.bm_w - w ) / 2;
|
|
|
|
y = (grd_curcanv->cv_bitmap.bm_h - h ) / 2;
|
|
|
|
|
2011-02-23 16:46:39 +00:00
|
|
|
gr_settransblend(14, GR_BLEND_NORMAL);
|
2008-02-24 14:41:27 +00:00
|
|
|
gr_setcolor( BM_XRGB(0,0,0) );
|
|
|
|
gr_rect( x, y, x+w, y+h );
|
2011-02-23 16:46:39 +00:00
|
|
|
gr_settransblend(GR_FADE_OFF, GR_BLEND_NORMAL);
|
2008-02-24 14:41:27 +00:00
|
|
|
|
2013-01-03 16:23:24 +00:00
|
|
|
gr_string(0x8000, (GHEIGHT - h)/2 + h/8, TXT_GAME_OVER );
|
2008-02-24 14:41:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
gr_set_curfont( GAME_FONT );
|
|
|
|
if (HUD_color == -1)
|
|
|
|
HUD_color = BM_XRGB(0,28,0);
|
|
|
|
gr_set_fontcolor( HUD_color, -1);
|
2015-11-21 18:12:13 +00:00
|
|
|
gr_string(0x8000, GHEIGHT - LINE_SPACING, PlayerCfg.RespawnMode == RespawnPress::Any ? TXT_PRESS_ANY_KEY : "Press fire key or button to continue...");
|
2008-02-24 14:41:27 +00:00
|
|
|
}
|
2006-03-20 17:12:09 +00:00
|
|
|
}
|