/* =========================================================================== Copyright (C) 2015 the OpenMoHAA team This file is part of OpenMoHAA source code. OpenMoHAA source code is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. OpenMoHAA source code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenMoHAA source code; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA =========================================================================== */ // hud.cpp: New HUD handler for MoHAA // #include "glb_local.h" #include "hud.h" #ifdef CGAME_DLL # include "cgamex86.h" # include "cgame/cg_hud.h" # include "script/centity.h" # include "archive.h" #endif #ifdef GAME_DLL # include "../fgame/player.h" #endif #include "game.h" #include "level.h" #include "scriptexception.h" Event EV_HUD_GetAlignX ( "alignx", EV_DEFAULT, NULL, NULL, "Gets the horizontal alignment for the HUD. Specified by 'left', 'center', or 'right'", EV_GETTER ); Event EV_HUD_GetAlignY ( "aligny", EV_DEFAULT, NULL, NULL, "Gets the vertical alignment for the HUD", EV_GETTER ); Event EV_HUD_GetAlpha ( "alpha", EV_DEFAULT, NULL, NULL, "Gets the HUD alpha", EV_GETTER ); Event EV_HUD_GetColor ( "color", EV_DEFAULT, NULL, NULL, "Gets the HUD colors", EV_GETTER ); Event EV_HUD_GetFont ( "font", EV_DEFAULT, NULL, NULL, "Gets the HUD font", EV_GETTER ); Event EV_HUD_GetRectX ( "x", EV_DEFAULT, NULL, NULL, "Gets the HUD horizontal position", EV_GETTER ); Event EV_HUD_GetRectY ( "y", EV_DEFAULT, NULL, NULL, "Gets the HUD vertical position", EV_GETTER ); Event EV_HUD_GetTime ( "gettime", EV_DEFAULT, NULL, NULL, "Gets the HUD time", EV_RETURN ); Event EV_HUD_GetHeight ( "getheight", EV_DEFAULT, NULL, NULL, "Gets the HUD height", EV_RETURN ); Event EV_HUD_GetWidth ( "getwidth", EV_DEFAULT, NULL, NULL, "Gets the HUD width", EV_RETURN ); Event EV_HUD_Set3D ( "setdimension", EV_DEFAULT, "vbbE", "vector_or_offset always_show depth entity", "Sets this huddraw element to be a 3D world icon and can specify if this icon is always shown on-screen even if the player isn't looking at.\n" "It uses xy pos from huddraw_rect.\n" "If entity is specified, the vector will be an offset relative to the entity.\n" "depth specify if the icon is shown through walls.", EV_NORMAL ); Event EV_HUD_SetNon3D ( "resetdimension", EV_DEFAULT, NULL, NULL, "Bring the HUD back to normal dimension (non-3D)", EV_NORMAL ); Event EV_HUD_SetAlignX ( "alignx", EV_DEFAULT, "s", "align", "Sets the horizontal alignment for the HUD. Specified by 'left', 'center', or 'right'", EV_SETTER ); Event EV_HUD_SetAlignY ( "aligny", EV_DEFAULT, "s", "align", "Sets the vertical alignment for the HUD. Specified by 'top', 'center', or 'bottom'", EV_SETTER ); Event EV_HUD_SetAlpha ( "alpha", EV_DEFAULT, "f", "alpha", "Sets the HUD alpha", EV_SETTER ); Event EV_HUD_SetColor ( "color", EV_DEFAULT, "v", "color", "Sets the HUD colors", EV_SETTER ); Event EV_HUD_SetFont ( "font", EV_DEFAULT, "s", "font", "Sets the HUD font", EV_SETTER ); Event EV_HUD_SetPlayer ( "setplayer", EV_DEFAULT, "eB", "entity clears", "Sets to which player this HUD is shown and possibly clears the HUD to the previous player(s) it was shown. A NULL/NIL entity means the HUD will be shown to all players\n" "Note : you will need to call in HUD functions again as it won't refresh to the player(s)", EV_NORMAL ); Event EV_HUD_SetRectX ( "x", EV_DEFAULT, "i", "x", "Sets the HUD horizontal position", EV_SETTER ); Event EV_HUD_SetRectY ( "y", EV_DEFAULT, "i", "y", "Sets the HUD vertical position", EV_SETTER ); Event EV_HUD_SetShader ( "setshader", EV_DEFAULT, "sii", "shader width height", "Sets the HUD shader", EV_NORMAL ); Event EV_HUD_SetText ( "settext", EV_DEFAULT, "s", "text", "Sets the HUD text", EV_NORMAL ); Event EV_HUD_SetTimer ( "settimer", EV_DEFAULT, "fF", "time fade_at_time", "Sets a timer to count down an optionally fade at the specified time", EV_NORMAL ); Event EV_HUD_SetTimerUp ( "settimerup", EV_DEFAULT, "fF", "time fade_at_time", "Sets a timer to count up an optionally fade at the specified time", EV_NORMAL ); Event EV_HUD_SetVirtualSize ( "setvirtualsize", EV_DEFAULT, "b", "virtual", "Sets if the HUD should use virtual screen resolution for positioning and size", EV_NORMAL ); Event EV_HUD_FadeOverTime ( "fadeovertime", EV_DEFAULT, "f", "time", "Sets the HUD to transition in color (or alpha) over time", EV_NORMAL ); Event EV_HUD_MoveOverTime ( "moveovertime", EV_DEFAULT, "f", "time", "Sets the HUD to move over time", EV_NORMAL ); Event EV_HUD_ScaleOverTime ( "scaleovertime", EV_DEFAULT, "fii", "time width height", "Sets the HUD to scale over time", EV_NORMAL ); Event EV_HUD_Refresh ( "refresh", EV_DEFAULT, NULL, NULL, "Refresh the HUD", EV_NORMAL ); Container hudElements; int lastNumberRemoved = -1; Hud *Hud::Find(int index) { for (int i = 0; i < hudElements.NumObjects(); i++) { Hud *hud = hudElements[i]; if (hud->number == index) { return hud; } } return NULL; } Hud *Hud::FindOrCreate(int index) { Hud *hud = Hud::Find(index); if (hud == NULL) { hud = new Hud(index); } return hud; } void Hud::ProcessThink() { #ifdef CGAME_DLL if (!ui_hud->integer && !cg_hud->integer) { return; } #endif for (int i = 0; i < hudElements.NumObjects(); i++) { hudElements[i]->Think(); } } int Hud::Sort(const void *elem1, const void *elem2) { const Hud *hud1 = *(Hud **)elem1; const Hud *hud2 = *(Hud **)elem2; // Sort HUDs by their number if (hud1->number < hud2->number) { return -1; } else if (hud1->number > hud2->number) { return 1; } else { return 0; } } int Hud::GetFreeNumber() { for (int i = 0; i < hudElements.NumObjects(); i++) { Hud *hud = hudElements[i]; if (hud->number != i) { return i; } } return hudElements.NumObjects(); } #ifdef GAME_DLL Hud::Hud(int client) #else Hud::Hud(int index) #endif { #ifdef GAME_DLL if (client < -1 || client > game.maxclients) { delete this; ScriptError("Invalid client number %d !\n", client); return; } #endif #ifdef CGAME_DLL if (index == -1) { #endif number = GetFreeNumber(); /*if( lastNumberRemoved != -1 ) { number = GetFreeNumber(); lastNumberRemoved = -1; } else { number = hudElements.NumObjects(); }*/ #ifdef CGAME_DLL } else { number = index; } #endif #ifdef GAME_DLL clientnum = client; #endif alignX = HUD_CENTER; alignY = HUD_CENTER; color = Vector(1.f, 1.f, 1.f); alpha = 0.0f; x = 0; y = 0; width = 8; height = 8; #ifdef CGAME_DLL font = NULL; shaderHandle = NULL; #endif fade_alpha = false; fade_move = false; fade_scale = false; fade_timer_flags = 0; fade_alpha_first = false; fade_move_x_first = false; fade_move_y_first = false; fade_alpha_current = 0.f; fade_move_current = 0.f; fade_scale_current = 0.f; fade_time_current = 0.f; isDimensional = false; org = Vector(0, 0, 0); lastOrg = org; always_show = false; depth = false; enttarget = -1; virtualSize = false; fontName = ""; shader = ""; text = ""; hudElements.AddObject(this); hudElements.Sort(Hud::Sort); } Hud::~Hud() { lastNumberRemoved = number; SetAlpha(0.f); if (isDimensional) { SetNon3D(); } /* #ifdef GAME_DLL SetBroadcast(); gi.MSG_StartCGM( BG_MapCGMToProtocol(g_protocol, CGM_HUDDRAW_DELETE ); WriteNumber(); gi.MSG_EndCGM(); #endif */ hudElements.RemoveObject(this); } #ifdef CGAME_DLL qboolean CG_WorldToScreen(Vector pt, float *x, float *y, qboolean bOptionalSeen, float shader_width, float shader_height) { float xzi, yzi; Vector local, transformed; Vector vfwd, vright, vup; qboolean bNotShown = false; AngleVectors(cg->refdefViewAngles, vfwd, vright, vup); //VectorSub( pt, cg->refdef.viewOrg, local ); local = pt - cg->refdef.viewOrg; transformed[0] = DotProduct(local, vright); transformed[1] = DotProduct(local, vup); transformed[2] = DotProduct(local, vfwd); if (transformed[2] < 0.01f) { if (!bOptionalSeen) { return false; } bNotShown = true; } float centerX = ((float)cgs->glConfig.vidWidth / 2); float centerY = ((float)cgs->glConfig.vidHeight / 2); xzi = centerX / transformed[2] * (100.0f / cg->refdef.fovX); yzi = centerY / transformed[2] * (100.0f / cg->refdef.fovY); *x = centerX + (xzi * transformed[0]) - (shader_width / 2.0f); *y = centerY - (yzi * transformed[1]) - (shader_height / 2.0f); if (!bOptionalSeen) { return true; } float limitX = ((float)cgs->glConfig.vidWidth - shader_width); float limitY = ((float)cgs->glConfig.vidHeight - shader_height); if (bNotShown) { if (*x < limitX) { *x = limitX; } else if (*x > 0) { *x = 0; } else if (*y < limitY) { *y = limitY; } else if (*y > 0) { *y = 0; } } if (*x > limitX) { *x = limitX; } else if (*x < 0) { *x = 0; } if (*y > limitY) { *y = limitY; } else if (*y < 0) { *y = 0; } return true; } void Hud::Draw3D() { float tmpX = 0, tmpY = 0; Vector loc; alignX = HUD_LEFT; alignY = HUD_TOP; virtualSize = false; if (enttarget != -1) { centity_t *ce = CG_GetEntity(enttarget); if (ce != NULL) { loc = ce->currentState.origin + org; lastOrg = loc; } else { loc = lastOrg; } } else { loc = org; } if (!shaderHandle && text[0] != '\0') { height = 5; width = re.GetFontStringWidth(font == NULL ? facfont20 : font, text); } if (!CG_WorldToScreen(loc, &tmpX, &tmpY, always_show, width, height)) { return; } x = tmpX; y = tmpY; } #endif void Hud::FadeThink() { #ifdef CGAME_DLL float frametime = (float)cg->frametime; #else float frametime = level.frametime * 1000.0f; #endif fade_alpha_current += frametime; float ratio = fade_alpha_current / fade_alpha_time; if (ratio >= 1.0f) { fade_alpha = false; fade_alpha_current = 0.f; fade_alpha_first = false; alpha = fade_alpha_target; return; } alpha = fade_alpha_start + (fade_alpha_target - fade_alpha_start) * ratio; } void Hud::MoveThink() { #ifdef CGAME_DLL float frametime = (float)cg->frametime; #else float frametime = level.frametime * 1000.0f; #endif fade_move_current += frametime; float ratio = fade_move_current / fade_move_time; if (ratio >= 1.0f) { fade_move = false; fade_move_current = 0.f; fade_move_x_first = false; fade_move_y_first = false; x = fade_move_x_target; y = fade_move_y_target; return; } x = (short)(fade_move_x_start + (fade_move_x_target - fade_move_x_start) * ratio); y = (short)(fade_move_y_start + (fade_move_y_target - fade_move_y_start) * ratio); } void Hud::ScaleThink() { #ifdef CGAME_DLL float frametime = (float)cg->frametime; #else float frametime = level.frametime * 1000.0f; #endif fade_scale_current += frametime; float ratio = fade_scale_current / fade_scale_time; if (ratio >= 1.0f) { fade_scale = false; fade_scale_current = 0.f; width = fade_scale_w_target; height = fade_scale_h_target; return; } width = (short)(fade_scale_w_start + (fade_scale_w_target - fade_scale_w_start) * ratio); height = (short)(fade_scale_h_start + (fade_scale_h_target - fade_scale_h_start) * ratio); } void Hud::TimerThink() { int minutes; float seconds; const char *string; char buffer[128]; #ifdef CGAME_DLL float frametime = (float)cg->frametime; #else float frametime = level.frametime * 1000.0f; #endif if (fade_timer_flags & TIMER_UP) { fade_time_current += 0.001f * frametime; } else { fade_time_current -= 0.001f * frametime; } if (fade_time_current <= 0.0f) { if (fade_out_time > 0.0f) { alpha = 0.0f; } fade_time_current = 0.0f; } if (fade_time_current >= 60.0f) { seconds = (float)((int)fade_time_current % 60); minutes = (int)(fade_time_current / 60.0f); } else { if (fade_time_current >= 30.0f) { seconds = (float)(int)fade_time_current; } else { seconds = fade_time_current; } minutes = 0; } if (fade_time_current >= 30.0f) { string = "%d:%02.0f"; } else { if (fade_time_current >= 10.0f) { string = "%d:%02.1f"; } else { string = "%d:0%.1f"; } } if ((!(fade_timer_flags & TIMER_UP) && fade_time_current * 1000.0f < fade_out_time) || ((fade_timer_flags & TIMER_UP) && fade_time_current * 1000.0f > fade_out_time && fade_out_time >= 0.0f)) { alpha -= (2.0f - fade_time_alpha_start) / fade_out_time * frametime; if (alpha < 0.0f) { alpha = 0.0f; } } else { fade_time_alpha_start = alpha; } #ifdef CGAME_DLL if (!shaderHandle) { #else if (!*shader) { #endif Com_sprintf(buffer, sizeof(buffer), string, minutes, seconds); SetText(buffer); } else { SetText(""); } } void Hud::Think(void) { if (!text.c_str() && !shader.c_str()) { return; } if (fade_alpha) { FadeThink(); } if (fade_move) { MoveThink(); } if (fade_scale) { ScaleThink(); } if (fade_timer_flags & TIMER_ACTIVE) { TimerThink(); } if (alpha <= 0.0f) { return; } #ifdef CGAME_DLL if (isDimensional) { Draw3D(); } int vidWidth = virtualSize ? 640 : cgs->glConfig.vidWidth; int vidHeight = virtualSize ? 480 : cgs->glConfig.vidHeight; float hudX = x; float hudY = y; float hudW = width; float hudH = height; if (alignX == HUD_CENTER) { hudX += vidWidth * 0.5f - hudW * 0.5f; } else if (alignX == HUD_RIGHT) { hudX += vidWidth; } if (alignY == HUD_CENTER) { hudY += vidHeight * 0.5f - hudH * 0.5f; } else if (alignY == HUD_BOTTOM) { hudY += vidHeight; } vec4_t col = {color[0], color[1], color[2], alpha}; cgi.R_SetColor(col); if (shaderHandle == NULL) { const char *Localized = cgi.LV_ConvertString(text); fontHeader_t **f = (fontHeader_t **)0x302B7D28; if (font == NULL && *f == NULL) { return; } cgi.R_DrawString(font == NULL ? *f : font, Localized, hudX, hudY, -1, virtualSize); } else { if (virtualSize) { hudX *= cgs->screenXScale; hudY *= cgs->screenYScale; hudW *= cgs->screenXScale; hudH *= cgs->screenYScale; } cgi.R_DrawStretchPic(hudX, hudY, hudW, hudH, 0.0f, 0.0f, 1.0f, 1.0f, shaderHandle); } #endif } void Hud::Archive(Archiver& arc) { Listener::Archive(arc); #ifdef CGAME_DLL arc.ArchiveInteger((int *)&number); arc.ArchiveInteger((int *)&alignX); arc.ArchiveInteger((int *)&alignY); arc.ArchiveFloat(&x); arc.ArchiveFloat(&y); arc.ArchiveFloat(&width); arc.ArchiveFloat(&height); arc.ArchiveVector(&color); arc.ArchiveFloat(&alpha); arc.ArchiveString(&fontName); arc.ArchiveString(&shader); arc.ArchiveString(&text); arc.ArchiveBool(&virtualSize); arc.ArchiveBool(&fade_alpha); arc.ArchiveBool(&fade_move); arc.ArchiveBool(&fade_scale); arc.ArchiveFloat(&fade_alpha_current); arc.ArchiveFloat(&fade_move_current); arc.ArchiveFloat(&fade_scale_current); arc.ArchiveFloat(&fade_alpha_time); arc.ArchiveFloat(&fade_move_time); arc.ArchiveFloat(&fade_scale_time); arc.ArchiveFloat(&fade_alpha_start); arc.ArchiveFloat(&fade_move_x_start); arc.ArchiveFloat(&fade_move_y_start); arc.ArchiveFloat(&fade_scale_w_start); arc.ArchiveFloat(&fade_scale_h_start); arc.ArchiveFloat(&fade_alpha_target); arc.ArchiveFloat(&fade_move_x_target); arc.ArchiveFloat(&fade_move_y_target); arc.ArchiveFloat(&fade_scale_w_target); arc.ArchiveFloat(&fade_scale_h_target); if (arc.Loading()) { if (fontName[0] != '\0') { SetFont(fontName); } if (shader[0] != '\0') { SetShader(shader, width, height); } hudElements.AddObject(this); hudElements.Sort(Hud::Sort); } #endif } #ifdef GAME_DLL int Hud::GetClient(void) { return clientnum; } #endif void Hud::FadeOverTime(float time) { if (time <= 0.0f) { return; } fade_alpha = true; fade_alpha_first = true; fade_alpha_time = time * 1000.0f; fade_alpha_current = 0.f; fade_alpha_start = alpha; fade_alpha_target = alpha; // FIXME: delete /* #ifdef GAME_DLL SetBroadcast(); gi.MSG_StartCGM( BG_MapCGMToProtocol(g_protocol, CGM_HUDDRAW_FADE )); WriteNumber(); gi.MSG_WriteFloat( time ); gi.MSG_EndCGM(); #endif */ } void Hud::MoveOverTime(float time) { if (time <= 0.0f) { return; } fade_move = true; fade_move_x_first = true; fade_move_y_first = true; fade_move_time = time * 1000.0f; fade_move_current = 0.f; fade_move_x_start = x; fade_move_y_start = y; fade_move_x_target = x; fade_move_y_target = y; /* #ifdef GAME_DLL SetBroadcast(); gi.MSG_StartCGM( BG_MapCGMToProtocol(g_protocol, CGM_HUDDRAW_MOVE )); WriteNumber(); gi.MSG_WriteFloat( time ); gi.MSG_EndCGM(); #endif */ } void Hud::Refresh(int clientNumber) { SetBroadcast(clientNumber); gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_HUDDRAW_ALIGN)); WriteNumber(); gi.MSG_WriteBits(alignX, 2); gi.MSG_WriteBits(alignY, 2); gi.MSG_EndCGM(); SetBroadcast(clientNumber); gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_HUDDRAW_ALPHA)); WriteNumber(); gi.MSG_WriteByte((uchar)(alpha * 255.0f)); gi.MSG_EndCGM(); SetBroadcast(clientNumber); gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_HUDDRAW_COLOR)); WriteNumber(); gi.MSG_WriteByte((uchar)(color.x * 255.0f)); gi.MSG_WriteByte((uchar)(color.y * 255.0f)); gi.MSG_WriteByte((uchar)(color.z * 255.0f)); gi.MSG_EndCGM(); SetBroadcast(clientNumber); gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_HUDDRAW_FONT)); WriteNumber(); gi.MSG_WriteString(fontName); gi.MSG_EndCGM(); SetBroadcast(clientNumber); /*if( sv_reborn->integer ) { gi.MSG_StartCGM( BG_MapCGMToProtocol(g_protocol, CGM_HUDDRAW_RECTX )); WriteNumber(); gi.MSG_WriteShort( ( short )x ); gi.MSG_EndCGM(); gi.MSG_StartCGM( BG_MapCGMToProtocol(g_protocol, CGM_HUDDRAW_RECTY )); WriteNumber(); gi.MSG_WriteShort( ( short )y ); gi.MSG_EndCGM(); gi.MSG_StartCGM( BG_MapCGMToProtocol(g_protocol, CGM_HUDDRAW_RECTWH )); WriteNumber(); gi.MSG_WriteShort( ( short )width ); gi.MSG_WriteShort( ( short )height ); gi.MSG_EndCGM(); } else { gi.MSG_StartCGM( BG_MapCGMToProtocol(g_protocol, CGM_HUDDRAW_RECT )); WriteNumber(); gi.MSG_WriteShort( ( short )x ); gi.MSG_WriteShort( ( short )y ); gi.MSG_WriteShort( ( short )width ); gi.MSG_WriteShort( ( short )height ); gi.MSG_EndCGM(); }*/ gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_HUDDRAW_RECT)); WriteNumber(); gi.MSG_WriteShort((short)x); gi.MSG_WriteShort((short)y); gi.MSG_WriteShort((short)width); gi.MSG_WriteShort((short)height); gi.MSG_EndCGM(); SetBroadcast(clientNumber); gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_HUDDRAW_SHADER)); WriteNumber(); gi.MSG_WriteString(shader); gi.MSG_EndCGM(); SetBroadcast(clientNumber); gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_HUDDRAW_STRING)); WriteNumber(); gi.MSG_WriteString(text); gi.MSG_EndCGM(); SetBroadcast(clientNumber); gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_HUDDRAW_VIRTUALSIZE)); WriteNumber(); gi.MSG_WriteBits(virtualSize, 1); gi.MSG_EndCGM(); #ifdef OPM_FEATURES if (sv_specialgame->integer) { if (isDimensional) { SetBroadcast(); gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_HUDDRAW_3D)); WriteNumber(); gi.MSG_WriteCoord(org[0]); gi.MSG_WriteCoord(org[1]); gi.MSG_WriteCoord(org[2]); gi.MSG_WriteShort(enttarget); gi.MSG_WriteBits(!!always_show, 1); gi.MSG_WriteBits(!!depth, 1); gi.MSG_EndCGM(); } if (fade_alpha) { SetBroadcast(); gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_HUDDRAW_FADE)); WriteNumber(); gi.MSG_WriteFloat(fade_alpha_current); gi.MSG_EndCGM(); SetBroadcast(); gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_HUDDRAW_ALPHA)); WriteNumber(); gi.MSG_WriteByte((uchar)(fade_alpha_target * 255.0f)); gi.MSG_EndCGM(); } if (fade_move) { SetBroadcast(); gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_HUDDRAW_MOVE)); WriteNumber(); gi.MSG_WriteFloat(fade_move_current); gi.MSG_EndCGM(); SetBroadcast(); gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_HUDDRAW_RECT)); WriteNumber(); gi.MSG_WriteShort((short)fade_move_x_target); gi.MSG_WriteShort((short)fade_move_y_target); gi.MSG_EndCGM(); } if (fade_timer_flags & TIMER_ACTIVE) { SetBroadcast(); gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_HUDDRAW_TIMER)); WriteNumber(); gi.MSG_WriteFloat(fade_time_current); gi.MSG_WriteFloat(fade_out_time); if (fade_timer_flags & TIMER_UP) { gi.MSG_WriteBits(1, 1); } else { gi.MSG_WriteBits(0, 1); } gi.MSG_EndCGM(); } } #endif } void Hud::ScaleOverTime(float time, short w, short h) { if (time <= 0.0f) { width = w; height = h; return; } fade_scale = true; fade_scale_time = time * 1000.0f; fade_scale_current = 0.f; fade_scale_w_start = width; fade_scale_h_start = height; fade_scale_w_target = w; fade_scale_h_target = h; // FIXME: delete /* width = w; height = h; SetBroadcast(); gi.MSG_StartCGM( BG_MapCGMToProtocol(g_protocol, CGM_HUDDRAW_SCALE )); WriteNumber(); gi.MSG_WriteFloat( time ); gi.MSG_WriteShort( w ); gi.MSG_WriteShort( h ); gi.MSG_EndCGM(); */ } #ifdef GAME_DLL void Hud::SetBroadcast(int clientNumber) { if (clientNumber == -1) { clientNumber = clientnum; } if (clientnum == char(-1)) { gi.SetBroadcastAll(); } else { gi.MSG_SetClient(clientnum); } } #endif #ifdef GAME_DLL void Hud::WriteNumber() { # ifdef OPM_FEATURES if (sv_specialgame->integer) { gi.MSG_WriteShort(number); } else { gi.MSG_WriteByte(number); } # else gi.MSG_WriteByte(number); # endif } #endif void Hud::Set3D(Vector vector_or_offset, qboolean alwaysOnScreen, qboolean hasDepth, int entnum) { org = vector_or_offset; lastOrg = vector_or_offset; always_show = alwaysOnScreen; depth = hasDepth; enttarget = entnum; isDimensional = true; /* #ifdef GAME_DLL SetBroadcast(); gi.MSG_StartCGM( BG_MapCGMToProtocol(g_protocol, CGM_HUDDRAW_3D )); WriteNumber(); gi.MSG_WriteCoord( vector_or_offset[ 0 ] ); gi.MSG_WriteCoord( vector_or_offset[ 1 ] ); gi.MSG_WriteCoord( vector_or_offset[ 2 ] ); gi.MSG_WriteShort( entnum ); gi.MSG_WriteBits( !!alwaysOnScreen, 1 ); gi.MSG_WriteBits( !!hasDepth, 1 ); gi.MSG_EndCGM(); #endif */ } void Hud::SetNon3D() { isDimensional = false; // FIXME? /* SetBroadcast(); gi.MSG_StartCGM( BG_MapCGMToProtocol(g_protocol, CGM_HUDDRAW_BREAK3D )); WriteNumber(); gi.MSG_EndCGM(); */ } void Hud::SetAlignX(hudAlign_t align) { if (align >= HUD_INVALID) { ScriptError("Wrong %d X align!", align); } alignX = align; #ifdef GAME_DLL SetBroadcast(); gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_HUDDRAW_ALIGN)); WriteNumber(); gi.MSG_WriteBits(alignX, 2); gi.MSG_WriteBits(alignY, 2); gi.MSG_EndCGM(); #endif } void Hud::SetAlignY(hudAlign_t align) { if (align >= HUD_INVALID) { ScriptError("Wrong %d Y align!", align); } alignY = align; #ifdef GAME_DLL SetBroadcast(); gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_HUDDRAW_ALIGN)); WriteNumber(); gi.MSG_WriteBits(alignX, 2); gi.MSG_WriteBits(alignY, 2); gi.MSG_EndCGM(); #endif } void Hud::SetAlpha(float value) { //#ifdef CGAME_DLL if (fade_alpha_first) { fade_alpha_target = value; fade_alpha_first = false; } else { alpha = value; fade_alpha = false; } //#else // alpha = value; //#endif #ifdef GAME_DLL long int ucharvalue; ucharvalue = (long int)(value * 255.0f); SetBroadcast(); gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_HUDDRAW_ALPHA)); WriteNumber(); gi.MSG_WriteByte(ucharvalue); gi.MSG_EndCGM(); #endif } void Hud::SetColor(Vector c) { color = c; #ifdef GAME_DLL SetBroadcast(); gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_HUDDRAW_COLOR)); WriteNumber(); gi.MSG_WriteByte((uchar)(c.x * 255.0f)); gi.MSG_WriteByte((uchar)(c.y * 255.0f)); gi.MSG_WriteByte((uchar)(c.z * 255.0f)); gi.MSG_EndCGM(); #endif } void Hud::SetClient(int c, qboolean clears) { #ifdef GAME_DLL if (c == -1) { clears = false; } if (clears) { # ifdef GAME_DLL SetBroadcast(); gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_HUDDRAW_ALPHA)); WriteNumber(); gi.MSG_WriteByte(0); gi.MSG_EndCGM(); # endif } clientnum = c; #endif } void Hud::SetFont(const char *f) { if (f != NULL && strlen(f) > 0) { fontName = f; } else { fontName = ""; } #ifdef CGAME_DLL if (fontName[0] != '\0') { font = cgi.R_LoadFont(fontName); } else { font = NULL; } #endif #ifdef GAME_DLL SetBroadcast(); gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_HUDDRAW_FONT)); WriteNumber(); gi.MSG_WriteString(f); gi.MSG_EndCGM(); #endif } void Hud::SetRectX(short value) { //#ifdef CGAME_DLL if (fade_move_x_first) { fade_move_x_target = value; fade_move_x_first = false; } else { x = value; fade_move = false; } //#else // x = value; //#endif #ifdef GAME_DLL SetBroadcast(); gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_HUDDRAW_RECT)); WriteNumber(); gi.MSG_WriteShort((short)fade_move_x_target); gi.MSG_WriteShort((short)fade_move_y_target); gi.MSG_WriteShort((short)width); gi.MSG_WriteShort((short)height); gi.MSG_EndCGM(); #endif } void Hud::SetRectY(short value) { if (fade_move_y_first) { fade_move_y_target = value; fade_move_y_first = false; } else { y = value; fade_move = false; } #ifdef GAME_DLL SetBroadcast(); gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_HUDDRAW_RECT)); WriteNumber(); gi.MSG_WriteShort((short)fade_move_x_target); gi.MSG_WriteShort((short)fade_move_y_target); gi.MSG_WriteShort((short)width); gi.MSG_WriteShort((short)height); gi.MSG_EndCGM(); #endif } void Hud::SetRectHeight(short h) { height = h; } void Hud::SetRectWidth(short w) { width = w; } void Hud::SetShader(const char *s, float w, float h) { if (s != NULL && strlen(s) > 0) { shader = s; text = ""; } else { shader = ""; } fade_scale = false; if (w != -1) { width = w; } if (h != -1) { height = h; } #ifdef CGAME_DLL if (shader[0] != '\0') { shaderHandle = cgi.R_RegisterShaderNoMip(shader); } else { shaderHandle = NULL; } #endif #ifdef GAME_DLL SetBroadcast(); gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_HUDDRAW_RECT)); WriteNumber(); gi.MSG_WriteShort((short)x); gi.MSG_WriteShort((short)y); gi.MSG_WriteShort((short)width); gi.MSG_WriteShort((short)height); gi.MSG_EndCGM(); SetBroadcast(); gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_HUDDRAW_SHADER)); WriteNumber(); gi.MSG_WriteString(s); gi.MSG_EndCGM(); #endif } void Hud::SetText(const char *t) { if (t != NULL && strlen(t) > 0) { //width = strlen( t ); //height = 32; text = t; shader = ""; #ifdef CGAME_DLL shaderHandle = NULL; #endif } else { text = ""; } #ifdef GAME_DLL SetBroadcast(); gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_HUDDRAW_STRING)); WriteNumber(); gi.MSG_WriteString(t); gi.MSG_EndCGM(); #endif } void Hud::SetTimer(float time, float fade_at_time) { fade_time_current = time; if (fade_at_time >= 0.0f) { fade_out_time = fade_at_time * 1000.0f; } else { fade_out_time = -1.0f; } fade_time_target = 0.0f; fade_timer_flags = TIMER_ACTIVE; // FIXME... /* SetBroadcast(); gi.MSG_StartCGM( BG_MapCGMToProtocol(g_protocol, CGM_HUDDRAW_TIMER )); WriteNumber(); gi.MSG_WriteFloat( time ); gi.MSG_WriteFloat( fade_at_time ); gi.MSG_WriteBits( 0, 1 ); gi.MSG_EndCGM(); */ } void Hud::SetTimerUp(float time, float fade_at_time) { fade_time_current = 0.0f; if (fade_at_time >= 0.0f) { fade_out_time = fade_at_time * 1000.0f; } else { fade_out_time = -1.0f; } fade_time_target = time; fade_timer_flags = TIMER_ACTIVE | TIMER_UP; /* #ifdef GAME_DLL SetBroadcast(); gi.MSG_StartCGM( BG_MapCGMToProtocol(g_protocol, CGM_HUDDRAW_TIMER )); WriteNumber(); gi.MSG_WriteFloat( time ); gi.MSG_WriteFloat( fade_at_time ); gi.MSG_WriteBits( 1, 1 ); gi.MSG_EndCGM(); #endif */ } void Hud::SetVirtualSize(qboolean v) { virtualSize = !!v; #ifdef GAME_DLL SetBroadcast(); gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_HUDDRAW_VIRTUALSIZE)); WriteNumber(); gi.MSG_WriteBits(virtualSize, 1); gi.MSG_EndCGM(); #endif } // Events void Hud::EventGetAlignX(Event *ev) { switch (alignX) { case HUD_LEFT: return ev->AddString("left"); case HUD_CENTER: return ev->AddString("center"); case HUD_RIGHT: return ev->AddString("right"); default: return ev->AddString("none"); } } void Hud::EventGetAlignY(Event *ev) { switch (alignY) { case HUD_TOP: return ev->AddString("top"); case HUD_CENTER: return ev->AddString("center"); case HUD_BOTTOM: return ev->AddString("bottom"); default: return ev->AddString("none"); } } void Hud::EventGetAlpha(Event *ev) { ev->AddFloat(alpha); } void Hud::EventGetColor(Event *ev) { ev->AddVector(color); } void Hud::EventGetFont(Event *ev) { ev->AddString(fontName); } void Hud::EventGetHeight(Event *ev) { ev->AddFloat(height); } void Hud::EventGetRectX(Event *ev) { ev->AddFloat(x); } void Hud::EventGetRectY(Event *ev) { ev->AddFloat(y); } void Hud::EventGetTime(Event *ev) { ev->AddFloat(fade_time_current); } void Hud::EventGetWidth(Event *ev) { ev->AddFloat(width); } void Hud::EventFadeOverTime(Event *ev) { FadeOverTime(ev->GetFloat(1)); } void Hud::EventMoveOverTime(Event *ev) { MoveOverTime(ev->GetFloat(1)); } void Hud::EventRefresh(Event *ev) { Refresh(); } void Hud::EventScaleOverTime(Event *ev) { ScaleOverTime(ev->GetFloat(1), ev->GetInteger(2), ev->GetInteger(3)); } void Hud::EventSet3D(Event *ev) { Vector vector; int ent_num = -1; qboolean bAlwaysShow, bDepth; vector = ev->GetVector(1); bAlwaysShow = ev->GetInteger(2); bDepth = ev->GetInteger(3); if (ev->NumArgs() > 3) { Entity *entity = ev->GetEntity(4); ent_num = entity->entnum; } Set3D(vector, bAlwaysShow, bDepth, ent_num); } void Hud::EventSetNon3D(Event *ev) { SetNon3D(); } void Hud::EventSetAlignX(Event *ev) { str name = ev->GetString(1); hudAlign_t alignment = HUD_INVALID; if (name == "left") { alignment = HUD_LEFT; } else if (name == "center") { alignment = HUD_CENTER; } else if (name == "right") { alignment = HUD_RIGHT; } else { ScriptError("Invalid alignment %s!\n", name.c_str()); } SetAlignX(alignment); } void Hud::EventSetAlignY(Event *ev) { str name = ev->GetString(1); hudAlign_t alignment = HUD_INVALID; if (name == "top") { alignment = HUD_TOP; } else if (name == "center") { alignment = HUD_CENTER; } else if (name == "bottom") { alignment = HUD_BOTTOM; } else { ScriptError("Invalid alignment %s!\n", name.c_str()); } SetAlignY(alignment); } void Hud::EventSetAlpha(Event *ev) { float a = ev->GetFloat(1); SetAlpha(a); } void Hud::EventSetColor(Event *ev) { Vector c = ev->GetVector(1); SetColor(c); } void Hud::EventSetFont(Event *ev) { str font = ev->GetString(1); SetFont(font); } void Hud::EventSetPlayer(Event *ev) { #ifdef GAME_DLL int clientNum = -1; qboolean clears = false; if (!ev->IsNilAt(1)) { Player *player = (Player *)ev->GetEntity(1); clientNum = player->edict - g_entities; if (ev->NumArgs() > 1) { clears = ev->GetBoolean(2); } else { clears = false; } } SetClient(clientNum, clears); #endif } void Hud::EventSetRectX(Event *ev) { int val = ev->GetInteger(1); SetRectX(val); } void Hud::EventSetRectY(Event *ev) { int val = ev->GetInteger(1); SetRectY(val); } void Hud::EventSetShader(Event *ev) { str shader = ev->GetString(1); float w = ev->GetFloat(2); float h = ev->GetFloat(3); SetShader(shader, w, h); } void Hud::EventSetText(Event *ev) { str text = ev->GetString(1); SetText(text); } void Hud::EventSetTimer(Event *ev) { float time = ev->GetFloat(1); float fade_at_time = -1.0f; if (ev->NumArgs() > 1) { fade_at_time = ev->GetFloat(2); } SetTimer(time, fade_at_time); } void Hud::EventSetTimerUp(Event *ev) { float time = ev->GetFloat(1); float fade_at_time = -1.0f; if (ev->NumArgs() > 1) { fade_at_time = ev->GetFloat(2); } SetTimerUp(time, fade_at_time); } void Hud::EventSetVirtualSize(Event *ev) { qboolean bVirtual = ev->GetBoolean(1); SetVirtualSize(bVirtual); } CLASS_DECLARATION(Listener, Hud, NULL) { {&EV_HUD_GetAlignX, &Hud::EventGetAlignX }, {&EV_HUD_GetAlignY, &Hud::EventGetAlignY }, {&EV_HUD_GetAlpha, &Hud::EventGetAlpha }, {&EV_HUD_GetColor, &Hud::EventGetColor }, {&EV_HUD_GetFont, &Hud::EventGetFont }, {&EV_HUD_GetHeight, &Hud::EventGetHeight }, {&EV_HUD_GetRectX, &Hud::EventGetRectX }, {&EV_HUD_GetRectY, &Hud::EventGetRectY }, {&EV_HUD_GetTime, &Hud::EventGetTime }, {&EV_HUD_GetWidth, &Hud::EventGetWidth }, {&EV_HUD_FadeOverTime, &Hud::EventFadeOverTime }, {&EV_HUD_MoveOverTime, &Hud::EventMoveOverTime }, {&EV_HUD_Refresh, &Hud::EventRefresh }, {&EV_HUD_ScaleOverTime, &Hud::EventScaleOverTime }, {&EV_HUD_Set3D, &Hud::EventSet3D }, {&EV_HUD_SetNon3D, &Hud::EventSetNon3D }, {&EV_HUD_SetAlignX, &Hud::EventSetAlignX }, {&EV_HUD_SetAlignY, &Hud::EventSetAlignY }, {&EV_HUD_SetAlpha, &Hud::EventSetAlpha }, {&EV_HUD_SetColor, &Hud::EventSetColor }, {&EV_HUD_SetFont, &Hud::EventSetFont }, {&EV_HUD_SetPlayer, &Hud::EventSetPlayer }, {&EV_HUD_SetRectX, &Hud::EventSetRectX }, {&EV_HUD_SetRectY, &Hud::EventSetRectY }, {&EV_HUD_SetShader, &Hud::EventSetShader }, {&EV_HUD_SetText, &Hud::EventSetText }, {&EV_HUD_SetTimer, &Hud::EventSetTimer }, {&EV_HUD_SetTimerUp, &Hud::EventSetTimerUp }, {&EV_HUD_SetVirtualSize, &Hud::EventSetVirtualSize}, {NULL, NULL } };