mirror of
https://github.com/unknownworlds/NS.git
synced 2024-11-24 21:41:19 +00:00
5dcc163bd5
git-svn-id: https://unknownworlds.svn.cloudforge.com/ns1@379 67975925-1194-0748-b3d5-c16f83f1a3a1
7017 lines
189 KiB
C++
7017 lines
189 KiB
C++
//======== (C) Copyright 2001 Charles G. Cleveland All rights reserved. =========
|
|
//
|
|
// The copyright to the contents herein is the property of Charles G. Cleveland.
|
|
// The contents may be used and/or copied only with the written permission of
|
|
// Charles G. Cleveland, or in accordance with the terms and conditions stipulated in
|
|
// the agreement/contract under which the contents have been supplied.
|
|
//
|
|
// Purpose: Main NS NUD, also interface to client network messages
|
|
//
|
|
// $Workfile: AvHHud.cpp $
|
|
// $Date: 2002/10/28 20:35:32 $
|
|
//
|
|
//-------------------------------------------------------------------------------
|
|
// $Log: AvHHud.cpp,v $
|
|
// Revision 1.70 2002/10/28 20:35:32 Flayra
|
|
// - Fix for gamma reset with VAC
|
|
// - Info location fix after changelevel
|
|
//
|
|
// Revision 1.69 2002/10/25 21:49:10 Flayra
|
|
// - Updated skin to sit in pev->skin
|
|
// - Reset components every tick to fix problem with disappearing team resource label
|
|
//
|
|
// Revision 1.68 2002/10/24 21:29:49 Flayra
|
|
// - Moved help client-side
|
|
// - Fixed particle/changelevel crash
|
|
// - Reworked marine upgrade drawing
|
|
// - Added lots of utility functions for help system (mirrors functions on server)
|
|
// - Removed gamma message unless it failed or if maxplayers is 1
|
|
// - Fixed alien hive sight crash
|
|
// - Show players under reticle while in ready room and spectating
|
|
// - Removed ugly/too-prevalent user3 icons
|
|
//
|
|
// Revision 1.67 2002/10/18 22:19:49 Flayra
|
|
// - Added alien easter egg sayings
|
|
//
|
|
// Revision 1.66 2002/10/16 20:53:41 Flayra
|
|
// - Draw scan model specially so it looks right
|
|
//
|
|
// Revision 1.65 2002/10/16 00:58:02 Flayra
|
|
// - Removed hotgroups
|
|
// - Added "need order" alert
|
|
//
|
|
// Revision 1.64 2002/10/03 20:24:39 Flayra
|
|
// - Changes for "more resources required"
|
|
//
|
|
// Revision 1.63 2002/10/03 18:54:30 Flayra
|
|
// - Allow right-click to cancel building placement
|
|
// - Fixed help icons
|
|
// - Added a couple utility functions
|
|
// - Reworked order notification
|
|
// - Reworked blip network messages to avoid hard-coded limit
|
|
// - Sent max resources down with current resources
|
|
// - Countdown sound no longer prevents other hud sounds
|
|
// - Alien trigger sounds
|
|
// - New order sounds
|
|
// - No longer disable nodes out of our cost range
|
|
//
|
|
// Revision 1.62 2002/09/25 20:47:19 Flayra
|
|
// - Don't draw elements on HUD when dead
|
|
// - UI refactoring
|
|
// - Split reticle help into help text and reticle text
|
|
// - Removed use order
|
|
// - Added separate select sound for alien
|
|
// - Multiple move sounds
|
|
// - Only draw entity build/health status when under reticle (no more scanning around you)
|
|
// - Added 3 new sayings
|
|
//
|
|
// Revision 1.61 2002/09/23 22:18:25 Flayra
|
|
// - Added alien build circles
|
|
// - Game status changes so particles aren't sent every time
|
|
// - Demo playback changes (save restore basic data that HUD already has)
|
|
// - New alert sounds
|
|
// - Skin support
|
|
//
|
|
// Revision 1.60 2002/09/09 19:55:24 Flayra
|
|
// - Added hive info indicator
|
|
// - Fixed bug where reticle tooltip help text wasn't being set until a weapon was selected
|
|
// - Fixed release mode bug where tooltips weren't expiring
|
|
// - Fixed bug where marine upgrades blinked
|
|
// - "No commander" indicator now blinks
|
|
//
|
|
// Revision 1.59 2002/08/31 18:01:01 Flayra
|
|
// - Work at VALVe
|
|
//
|
|
// Revision 1.58 2002/08/16 02:37:49 Flayra
|
|
// - HUD sounds no longer cut each other off (they won't play instead of cutting off another sound)
|
|
// - Tooltip sounds
|
|
// - Selection issues
|
|
// - Draw rings around buildings that need to be built
|
|
// - Removed old overwatch code
|
|
//
|
|
// Revision 1.57 2002/08/09 01:02:40 Flayra
|
|
// - Added hooks for demo playback, removed prediction selection
|
|
//
|
|
// Revision 1.56 2002/08/02 21:59:12 Flayra
|
|
// - Added reticle help, new tooltip system and much nicer order drawing! Refactored view model drawing a bit, hoping to make texture blending work for it.
|
|
//
|
|
// Revision 1.55 2002/07/26 23:05:01 Flayra
|
|
// - Generate numerical feedback for damage events
|
|
// - Refactoring for more info when looking at something (instead of bad-looking player names only)
|
|
//
|
|
// Revision 1.54 2002/07/24 18:45:41 Flayra
|
|
// - Linux and scripting changes
|
|
//
|
|
// Revision 1.53 2002/07/23 17:07:36 Flayra
|
|
// - Added visually-smooth energy level, added versatile location code, new hive sight info, refactored to remove extra sprites (128 HUD sprites bug), commander tech help fixes
|
|
//
|
|
// Revision 1.52 2002/07/10 14:41:55 Flayra
|
|
// - Fixed bug where non-sighted particle systems weren't being drawn for players on the ground (bug #127)
|
|
//
|
|
// Revision 1.51 2002/07/08 17:07:56 Flayra
|
|
// - Started to add display of marine upgrade sprite, fixed bug where building indicators aren't displayed after a map change, info_location drawing changes, primal scream color tweak, removed old hive drawing code
|
|
//
|
|
// Revision 1.50 2002/07/01 21:35:05 Flayra
|
|
// - Removed lots of outdated sprites and sprite code, added building ranges, fixed ghost building problem (bug #82)
|
|
//
|
|
// Revision 1.49 2002/06/25 18:03:09 Flayra
|
|
// - Added info_locations, removed old weapon help system, added smooth resource swelling, lots of alien UI usability changes, fixed problem with ghost building
|
|
//
|
|
// Revision 1.48 2002/06/10 19:55:36 Flayra
|
|
// - New commander UI (bindable via hotkeys, added REMOVE_SELECTION for when clicking menu options when no players selected)
|
|
//
|
|
// Revision 1.47 2002/06/03 16:48:45 Flayra
|
|
// - Help sprites moved into one animated sprite, select sound volume reduced (now that sound is normalized)
|
|
//
|
|
// Revision 1.46 2002/05/28 17:48:14 Flayra
|
|
// - Minimap refactoring, reinforcement refactoring, new hive sight fixes, recycling support
|
|
//
|
|
// Revision 1.45 2002/05/23 02:33:42 Flayra
|
|
// - Post-crash checkin. Restored @Backup from around 4/16. Contains changes for last four weeks of development.
|
|
//
|
|
//===============================================================================
|
|
#include "mod/AvHConstants.h"
|
|
#include "mod/AvHHud.h"
|
|
#include "cl_dll/hud.h"
|
|
#include "cl_dll/cl_util.h"
|
|
#include "vgui_label.h"
|
|
#include "ui/PieMenu.h"
|
|
#include "mod/AvHTeamHierarchy.h"
|
|
#include "mod/AvHPieMenuHandler.h"
|
|
#include "mod/AvHParticleTemplateClient.h"
|
|
#include "mod/AvHParticleSystemManager.h"
|
|
#include "mod/AvHClientVariables.h"
|
|
#include "mod/AvHSpecials.h"
|
|
#include "ui/FadingImageLabel.h"
|
|
#include "mod/AvHScrollHandler.h"
|
|
#include "mod/AvHEvents.h"
|
|
#include "pm_shared/pm_shared.h"
|
|
#include "common/cl_entity.h"
|
|
#include "mod/AvHCommanderModeHandler.h"
|
|
#include "mod/AvHParticleEditorHandler.h"
|
|
#include "mod/AvHTechTree.h"
|
|
#include "mod/AvHMovementUtil.h"
|
|
#include "mod/AvHTitles.h"
|
|
#include "mod/AvHSelectionHelper.h"
|
|
#include "mod/AvHActionButtons.h"
|
|
#include "pm_shared/pm_debug.h"
|
|
#include "util/MathUtil.h"
|
|
#include "util/STLUtil.h"
|
|
#include "mod/AvHSharedUtil.h"
|
|
#include "common/r_efx.h"
|
|
#include "cl_dll/eventscripts.h"
|
|
#include <stdlib.h>
|
|
#include "mod/AvHSprites.h"
|
|
#include "ui/UIUtil.h"
|
|
#include "mod/AvHMiniMap.h"
|
|
#include "types.h"
|
|
#include <signal.h>
|
|
#include "common/event_api.h"
|
|
#include "mod/AvHHulls.h"
|
|
#include "common/com_model.h"
|
|
#include "mod/AvHBasePlayerWeaponConstants.h"
|
|
#include "cl_dll/vgui_ScorePanel.h"
|
|
#include "mod/AvHAlienAbilityConstants.h"
|
|
#include "mod/AvHSharedUtil.h"
|
|
#include "mod/AvHScriptManager.h"
|
|
#include "mod/AvHHudConstants.h"
|
|
#include "cl_dll/demo.h"
|
|
#include "common/demo_api.h"
|
|
#include "cl_dll/ammohistory.h"
|
|
#include "mod/AvHTechImpulsePanel.h"
|
|
#include "mod/AvHServerVariables.h"
|
|
#include "mod/AvHPlayerUpgrade.h"
|
|
#include "mod/AvHCommandConstants.h"
|
|
#include "mod/AvHDebugUtil.h"
|
|
#include "engine/keydefs.h"
|
|
#include "ui/ChatPanel.h"
|
|
#include "cl_dll/r_studioint.h"
|
|
#include "util/Tokenizer.h"
|
|
#include <sstream>
|
|
#include "mod/AvHNetworkMessages.h"
|
|
|
|
//#include "cl_dll/studio_util.h"
|
|
//#include "cl_dll/r_studioint.h"
|
|
|
|
void IN_GetMousePos( int *mx, int *my );
|
|
extern playermove_t *pmove;
|
|
void RemoveAllDecals();
|
|
void ScorePanel_InitializeDemoRecording();
|
|
|
|
// Include windows for GDI and gamma functions
|
|
#include "windows.h"
|
|
|
|
extern engine_studio_api_t IEngineStudio;
|
|
|
|
AvHPieMenuHandler gPieMenuHandler;
|
|
AvHScrollHandler gScrollHandler;
|
|
AvHCommanderModeHandler gCommanderHandler;
|
|
AvHParticleEditorHandler gParticleEditorHandler;
|
|
extern AvHParticleTemplateListClient gParticleTemplateList;
|
|
extern DebugPointListType gTriDebugLocations;
|
|
extern extra_player_info_t g_PlayerExtraInfo[MAX_PLAYERS+1];
|
|
extern WeaponsResource gWR;
|
|
|
|
extern double gClientTimeLastUpdate;
|
|
extern "C" Vector gPredictedPlayerOrigin;
|
|
extern "C" Vector gPredictedPlayerVOfs;
|
|
extern void __CmdFunc_Close(void);
|
|
extern int CL_ButtonBits(int);
|
|
extern int g_iVisibleMouse;
|
|
|
|
GammaTable AvHHud::sPregameGammaTable;
|
|
GammaTable AvHHud::sGameGammaTable;
|
|
|
|
bool AvHHud::sShowMap = false;
|
|
|
|
// Global because of global HUD complilation error
|
|
AvHMiniMap gMiniMap;
|
|
|
|
#include "VGUI_RepaintSignal.h"
|
|
|
|
//extern vec3_t v_origin;
|
|
//extern vec3_t v_angles;
|
|
//vec3_t gPlayerOrigin;
|
|
//vec3_t gPlayerAngles;
|
|
|
|
extern AvHSelectionHelper gSelectionHelper;
|
|
|
|
//#if defined( AVH_CLIENT )
|
|
//extern "C" float gOverwatchTargetRange;
|
|
extern float gOverwatchTargetRange;
|
|
//#endif
|
|
|
|
extern bool gResetViewAngles;
|
|
extern vec3_t gViewAngles;
|
|
extern char sDebugString[128];
|
|
|
|
float kOverwatchFlashInterval = 2.5f;
|
|
const float kReticleInfoMaxAlpha = 50;
|
|
int gVisibleMouse = 0;
|
|
|
|
//voogru: cvar pointers, these should always remain valid once they are set.
|
|
|
|
cvar_t *gl_monolights = NULL;
|
|
cvar_t *gl_overbright = NULL;
|
|
cvar_t *gl_clear = NULL;
|
|
cvar_t *hud_draw = NULL;
|
|
cvar_t *r_drawviewmodel = NULL;
|
|
extern cvar_t *cl_movespeedkey;
|
|
cvar_t *gl_d3dflip = NULL;
|
|
cvar_t *s_show = NULL;
|
|
cvar_t *lightgamma = NULL;
|
|
cvar_t *r_detailtextures = NULL;
|
|
cvar_t *gl_max_size = NULL;
|
|
|
|
const AvHMapExtents& GetMapExtents()
|
|
{
|
|
return gHUD.GetMapExtents();
|
|
}
|
|
|
|
NumericalInfoEffect::NumericalInfoEffect(float inPosition[3], float inNumber, int inEventType, float inTimeCreated)
|
|
{
|
|
this->mPosition[0] = inPosition[0];
|
|
this->mPosition[1] = inPosition[1];
|
|
this->mPosition[2] = inPosition[2];
|
|
|
|
this->mNumber = inNumber;
|
|
this->mEventType = inEventType;
|
|
|
|
this->mTimeCreated = inTimeCreated;
|
|
}
|
|
|
|
void NumericalInfoEffect::GetPosition(float* outPosition) const
|
|
{
|
|
outPosition[0] = this->mPosition[0];
|
|
outPosition[1] = this->mPosition[1];
|
|
outPosition[2] = this->mPosition[2];
|
|
}
|
|
|
|
float NumericalInfoEffect::GetNumber() const
|
|
{
|
|
return this->mNumber;
|
|
}
|
|
|
|
int NumericalInfoEffect::GetEventType() const
|
|
{
|
|
return this->mEventType;
|
|
}
|
|
|
|
float NumericalInfoEffect::GetTimeCreated() const
|
|
{
|
|
return this->mTimeCreated;
|
|
}
|
|
|
|
void NumericalInfoEffect::SetPosition(float inPosition[3])
|
|
{
|
|
this->mPosition[0] = inPosition[0];
|
|
this->mPosition[1] = inPosition[1];
|
|
this->mPosition[2] = inPosition[2];
|
|
}
|
|
|
|
void AvHHud::OnActivateSteamUI()
|
|
{
|
|
// Set the normal gamma so the Steam UI looks correct.
|
|
sPregameGammaTable.InitializeToVideoState();
|
|
mSteamUIActive = true;
|
|
}
|
|
|
|
void AvHHud::OnDeactivateSteamUI()
|
|
{
|
|
|
|
// Set the special NS gamma.
|
|
SetGamma(mDesiredGammaSlope);
|
|
mSteamUIActive = false;
|
|
|
|
// The Steam UI screws up the mouse cursor so reset it.
|
|
if (gViewPort != NULL)
|
|
{
|
|
gViewPort->UpdateCursorState();
|
|
}
|
|
|
|
}
|
|
|
|
void AvHHud::OnLostFocus()
|
|
{
|
|
sPregameGammaTable.InitializeToVideoState();
|
|
}
|
|
|
|
bool AvHHud::OnKeyEvent(int virtualKey, int scanCode, bool pressed)
|
|
{
|
|
|
|
if (gViewPort != NULL && !mSteamUIActive)
|
|
{
|
|
|
|
ChatPanel* theChatPanel = gViewPort->GetChatPanel();
|
|
|
|
if (theChatPanel && theChatPanel->isVisible())
|
|
{
|
|
if (pressed)
|
|
{
|
|
theChatPanel->KeyDown(virtualKey, scanCode);
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
// If the key wasn't pressed while the chat window was open,
|
|
// the key up needs to go to HL.
|
|
return theChatPanel->WasKeyPushed(virtualKey);
|
|
}
|
|
}
|
|
|
|
if (virtualKey == VK_ESCAPE && GetInTopDownMode() && mGhostBuilding != MESSAGE_NULL)
|
|
{
|
|
if (pressed)
|
|
{
|
|
CancelBuilding();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
int AvHHud::GetGameTime() const
|
|
{
|
|
int theGameTime = 0;
|
|
|
|
if(this->mGameTime > 0)
|
|
{
|
|
theGameTime = (int)(this->mGameTime);
|
|
}
|
|
|
|
return theGameTime;
|
|
}
|
|
|
|
int AvHHud::GetGameTimeLimit() const
|
|
{
|
|
return this->mTimeLimit;
|
|
}
|
|
|
|
int AvHHud::GetCombatAttackingTeamNumber() const
|
|
{
|
|
return this->mCombatAttackingTeamNumber;
|
|
}
|
|
|
|
bool AvHHud::GetShowingMap()
|
|
{
|
|
return sShowMap;
|
|
}
|
|
|
|
bool AvHHud::GetGameStarted() const
|
|
{
|
|
return (this->mGameTime >= 0) && !this->mGameEnded;
|
|
}
|
|
|
|
bool AvHHud::GetIsAlive(bool inIncludeSpectating) const
|
|
{
|
|
bool theIsAlive = false;
|
|
|
|
cl_entity_s* thePlayer = gEngfuncs.GetLocalPlayer();
|
|
if(inIncludeSpectating)
|
|
{
|
|
thePlayer = this->GetVisiblePlayer();
|
|
}
|
|
|
|
if(thePlayer)
|
|
{
|
|
int thePlayerIndex = thePlayer->index;
|
|
if((thePlayerIndex) && (thePlayerIndex <= MAX_PLAYERS))
|
|
{
|
|
int thePlayerClass = g_PlayerExtraInfo[thePlayerIndex].playerclass;
|
|
switch(thePlayerClass)
|
|
{
|
|
case PLAYERCLASS_ALIVE_MARINE:
|
|
case PLAYERCLASS_ALIVE_HEAVY_MARINE:
|
|
case PLAYERCLASS_ALIVE_JETPACK_MARINE:
|
|
case PLAYERCLASS_ALIVE_LEVEL1:
|
|
case PLAYERCLASS_ALIVE_LEVEL2:
|
|
case PLAYERCLASS_ALIVE_LEVEL3:
|
|
case PLAYERCLASS_ALIVE_LEVEL4:
|
|
case PLAYERCLASS_ALIVE_LEVEL5:
|
|
case PLAYERCLASS_ALIVE_DIGESTING:
|
|
case PLAYERCLASS_ALIVE_GESTATING:
|
|
case PLAYERCLASS_COMMANDER:
|
|
theIsAlive = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return theIsAlive;
|
|
}
|
|
|
|
bool GetIsWithinRegion(float inNormX, float inNormY, float inLowX, float inLowY, float inHighX, float inHighY)
|
|
{
|
|
bool inRegion = false;
|
|
|
|
if((inNormX >= inLowX) && (inNormY >= inLowY) && (inNormX <= inHighX) && (inNormY < inHighY))
|
|
{
|
|
inRegion = true;
|
|
}
|
|
|
|
return inRegion;
|
|
}
|
|
|
|
bool AvHHud::GetIsRegionBlockedByUI(float inNormX, float inNormY)
|
|
{
|
|
bool theIsBlocked = true;
|
|
|
|
if( GetIsWithinRegion(inNormX, inNormY, 0, .061, .3017, .6797) ||
|
|
GetIsWithinRegion(inNormX, inNormY, .248, .0791, .7753, .6823) ||
|
|
GetIsWithinRegion(inNormX, inNormY, .748, .092, 1, .6575) ||
|
|
GetIsWithinRegion(inNormX, inNormY, .751, .645, .870, .678) ||
|
|
GetIsWithinRegion(inNormX, inNormY, .337, .679, .729, .754) ||
|
|
GetIsWithinRegion(inNormX, inNormY, .337, .717, .703, .823) )
|
|
{
|
|
theIsBlocked = false;
|
|
|
|
// Now check pending requests (the only HUD element not drawn as part of the outlying frame
|
|
for(PendingRequestListType::const_iterator theIterator = this->mPendingRequests.begin(); theIterator != this->mPendingRequests.end(); theIterator++)
|
|
{
|
|
AvHMessageID theMessageID = theIterator->first;
|
|
char theComponentName[256];
|
|
sprintf(theComponentName, kPendingImpulseSpecifier, (int)theMessageID);
|
|
|
|
AvHTechImpulsePanel* theTechImpulsePanel = NULL;
|
|
if(this->GetManager().GetVGUIComponentNamed(theComponentName, theTechImpulsePanel))
|
|
{
|
|
int thePosX, thePosY;
|
|
theTechImpulsePanel->getPos(thePosX, thePosY);
|
|
|
|
int theWidth, theHeight;
|
|
theTechImpulsePanel->getSize(theWidth, theHeight);
|
|
|
|
int theHighX = thePosX + theWidth;
|
|
int theHighY = thePosY + theHeight;
|
|
|
|
float theScreenWidth = ScreenWidth();
|
|
float theScreenHeight = ScreenHeight();
|
|
|
|
if(GetIsWithinRegion(inNormX, inNormY, thePosX/theScreenWidth, thePosY/theScreenHeight, theHighX/theScreenWidth, theHighY/theScreenHeight))
|
|
{
|
|
theIsBlocked = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return theIsBlocked;
|
|
}
|
|
|
|
bool AvHHud::GetIsShowingMap() const
|
|
{
|
|
return sShowMap;
|
|
}
|
|
|
|
void AvHHud::ClearSelection()
|
|
{
|
|
gSelectionHelper.ClearSelection();
|
|
this->mGroupEvent = COMMANDER_REMOVESELECTION;
|
|
}
|
|
|
|
|
|
void CLinkGhostBuildingCallback( struct tempent_s *ent, float frametime, float currenttime)
|
|
{
|
|
gHUD.GhostBuildingCallback(ent, frametime, currenttime);
|
|
}
|
|
|
|
// For easily adding message functions
|
|
#define BIND_MESSAGE(x) \
|
|
int __MsgFunc_##x(const char *pszName, int iSize, void *pbuf) \
|
|
{ \
|
|
return gHUD.##x(pszName, iSize, pbuf ); \
|
|
}
|
|
|
|
AvHHud::AvHHud(const string& inFilename, UIFactory* inFactory) : UIHud(inFilename, inFactory)
|
|
{
|
|
this->ClearData();
|
|
mSteamUIActive = false;
|
|
}
|
|
|
|
void AvHHud::AddNumericalInfoMessage(float inOrigin[3], float inNumber, int inEventType)
|
|
{
|
|
NumericalInfoEffect theEffect(inOrigin, inNumber, inEventType, this->mTimeOfLastUpdate);
|
|
this->mNumericalInfoEffects.push_back(theEffect);
|
|
}
|
|
|
|
void AvHHud::AddTooltip(const char* inMessageText, bool inIsToolTip, float inTooltipWidth)
|
|
{
|
|
if(!gEngfuncs.pDemoAPI->IsPlayingback() && (strlen(inMessageText) > 0))
|
|
{
|
|
if(gEngfuncs.pfnGetCvarFloat(kvAutoHelp) || !inIsToolTip)
|
|
{
|
|
AvHTooltip theNewTooltip;
|
|
|
|
theNewTooltip.SetText(string(inMessageText));
|
|
theNewTooltip.SetNormalizedScreenX(1.0f - inTooltipWidth - kHelpMessageLeftEdgeInset);
|
|
theNewTooltip.SetNormalizedScreenY(0.01f);
|
|
theNewTooltip.SetCentered(false);
|
|
theNewTooltip.SetIgnoreFadeForLifetime(true);
|
|
theNewTooltip.SetNormalizedMaxWidth(inTooltipWidth);
|
|
|
|
if(inIsToolTip)
|
|
{
|
|
this->PlayHUDSound(HUD_SOUND_TOOLTIP);
|
|
}
|
|
|
|
this->mTooltips.push_back(theNewTooltip);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool AvHHud::AddTooltipOnce(const char* inMessageText, bool inIsToolTip)
|
|
{
|
|
bool theAddedTooltip = false;
|
|
|
|
string theMessage(inMessageText);
|
|
|
|
// Check if message is in sent list
|
|
StringList::iterator theIter = std::find(this->mDisplayedToolTipList.begin(), this->mDisplayedToolTipList.end(), theMessage);
|
|
if(theIter == this->mDisplayedToolTipList.end())
|
|
{
|
|
// If not
|
|
// Call AddTooltip
|
|
this->AddTooltip(inMessageText, inIsToolTip);
|
|
theAddedTooltip = true;
|
|
|
|
// Add message to list
|
|
this->mDisplayedToolTipList.push_back(theMessage);
|
|
}
|
|
|
|
return theAddedTooltip;
|
|
}
|
|
|
|
|
|
void AvHHud::Cancel(void)
|
|
{
|
|
ASSERT(this->mInTopDownMode);
|
|
gCommanderHandler.CancelHit();
|
|
}
|
|
|
|
void AvHHud::ClearData()
|
|
{
|
|
this->mResources = 0;
|
|
|
|
this->mHierarchy = NULL;
|
|
this->mShowMapHierarchy = NULL;
|
|
|
|
this->mCommanderResourceLabel = NULL;
|
|
this->mGenericProgressBar = NULL;
|
|
this->mResearchProgressBar = NULL;
|
|
this->mAlienProgressBar = NULL;
|
|
this->mResearchLabel = NULL;
|
|
//this->mArmorLevel = ARMOR_BASE;
|
|
this->mTimeOfLastUpdate = 0.0;
|
|
this->mTimeOfNextHudSound = -1;
|
|
this->mLastHUDSoundPlayed = HUD_SOUND_INVALID;
|
|
this->mTimeOfLastEntityUpdate = -1;
|
|
this->mInTopDownMode = false;
|
|
this->mLeftMouseStarted = false;
|
|
this->mLeftMouseEnded = false;
|
|
this->mPlacingBuilding = false;
|
|
this->mRightMouseStarted = false;
|
|
this->mRightMouseEnded = false;
|
|
//this->mOrderMode = ORDERTYPE_UNDEFINED;
|
|
this->mTechEvent = MESSAGE_NULL;
|
|
this->mAlienAbility = MESSAGE_NULL;
|
|
this->mGroupEvent = MESSAGE_NULL;
|
|
this->mTrackingEntity = 0;
|
|
this->mNumLocalSelectEvents = 0;
|
|
|
|
this->mSelected.clear();
|
|
this->mSelectionJustChanged = false;
|
|
this->mMouseOneDown = false;
|
|
this->mMouseTwoDown = false;
|
|
this->mMouseOneStartX = 0;
|
|
this->mMouseOneStartY = 0;
|
|
this->mMouseTwoStartX = 0;
|
|
this->mMouseTwoStartY = 0;
|
|
|
|
this->mMouseCursorX = this->mMouseCursorY = 0;
|
|
this->mPieMenuControl = "";
|
|
|
|
this->mPreviousHelpText = "";
|
|
this->mTimeLastHelpTextChanged = -1;
|
|
this->mCurrentCursorFrame = 0;
|
|
|
|
this->mMapExtents.ResetMapExtents();
|
|
this->mMapName = "";
|
|
|
|
this->mGhostBuilding = MESSAGE_NULL;
|
|
this->mValidatedBuilding = MESSAGE_NULL;
|
|
this->mCreatedGhost = false;
|
|
this->mCurrentGhostIsValid = false;
|
|
|
|
this->mAmbientSounds.clear();
|
|
|
|
// tankefugl: 0000971
|
|
this->mTeammateOrder.clear();
|
|
this->mDisplayOrderIndex = 0;
|
|
this->mDisplayOrderTime = 0;
|
|
this->mDisplayOrderType = 0;
|
|
// :tankefugl
|
|
}
|
|
|
|
|
|
AvHHud::~AvHHud(void)
|
|
{
|
|
//this->ResetGamma();
|
|
//delete [] sOriginalGammaTable;
|
|
//delete [] sGammaTable;
|
|
AvHHud::ResetGammaAtExit();
|
|
}
|
|
|
|
void DummyFunction()
|
|
{
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
int gGlobalDebugAuth = 0;
|
|
void TestIcon()
|
|
{
|
|
gGlobalDebugAuth = rand() % 7;
|
|
}
|
|
|
|
typedef struct alias_t {
|
|
alias_t* next;
|
|
char name[32];
|
|
char* cmds;
|
|
} alias_s;
|
|
|
|
void TestAlias()
|
|
{
|
|
alias_s* alias = *(alias_s**)0x2D5929C;
|
|
while(alias)
|
|
{
|
|
gEngfuncs.Con_Printf("name: %s\n%x - %x\n", alias->name, alias->name, gEngfuncs);
|
|
alias = alias->next;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
// Used for console command
|
|
void AvHHud::PlayRandomSongHook()
|
|
{
|
|
gHUD.PlayRandomSong();
|
|
}
|
|
|
|
void AvHHud::AddCommands()
|
|
{
|
|
gEngfuncs.pfnAddCommand ("+popupmenu", AvHPieMenuHandler::OpenPieMenu);
|
|
gEngfuncs.pfnAddCommand ("-popupmenu", AvHPieMenuHandler::ClosePieMenu);
|
|
|
|
gEngfuncs.pfnAddCommand ("+mousepopupmenu", AvHPieMenuHandler::OpenPieMenu);
|
|
gEngfuncs.pfnAddCommand ("-mousepopupmenu", AvHPieMenuHandler::ClosePieMenu);
|
|
|
|
// Add scrolling commands
|
|
gEngfuncs.pfnAddCommand ("+scrollup", AvHScrollHandler::ScrollUp);
|
|
gEngfuncs.pfnAddCommand ("-scrollup", AvHScrollHandler::StopScroll);
|
|
|
|
gEngfuncs.pfnAddCommand ("+scrolldown", AvHScrollHandler::ScrollDown);
|
|
gEngfuncs.pfnAddCommand ("-scrolldown", AvHScrollHandler::StopScroll);
|
|
|
|
gEngfuncs.pfnAddCommand ("+scrollleft", AvHScrollHandler::ScrollLeft);
|
|
gEngfuncs.pfnAddCommand ("-scrollleft", AvHScrollHandler::StopScroll);
|
|
|
|
gEngfuncs.pfnAddCommand ("+scrollright", AvHScrollHandler::ScrollRight);
|
|
gEngfuncs.pfnAddCommand ("-scrollright", AvHScrollHandler::StopScroll);
|
|
|
|
gEngfuncs.pfnAddCommand ("toggleeditps", AvHParticleEditorHandler::ToggleEdit);
|
|
|
|
gEngfuncs.pfnAddCommand ("nexttrack", AvHHud::PlayRandomSongHook);
|
|
|
|
gEngfuncs.pfnAddCommand ("+showmap", AvHHud::ShowMap);
|
|
gEngfuncs.pfnAddCommand ("-showmap", AvHHud::HideMap);
|
|
|
|
gEngfuncs.pfnAddCommand ("playstream", AvHHud::PlayStream);
|
|
gEngfuncs.pfnAddCommand ("stopstream", AvHHud::StopStream);
|
|
|
|
#ifdef DEBUG
|
|
gEngfuncs.pfnAddCommand("testicon", TestIcon);
|
|
gEngfuncs.pfnAddCommand("testalias", TestAlias);
|
|
#endif
|
|
|
|
int i = 0;
|
|
char theBinding[128];
|
|
for(i = (int)(RESOURCE_UPGRADE); i <= (int)(BUILD_RECYCLE); i++)
|
|
{
|
|
sprintf(theBinding, "%s%d", kHotKeyPrefix, i);
|
|
gEngfuncs.pfnAddCommand(theBinding, DummyFunction);
|
|
}
|
|
|
|
for(i = (int)(MENU_BUILD); i <= (int)(MENU_EQUIP); i++)
|
|
{
|
|
sprintf(theBinding, "%s%d", kHotKeyPrefix, i);
|
|
gEngfuncs.pfnAddCommand(theBinding, DummyFunction);
|
|
}
|
|
}
|
|
|
|
void AvHHud::ClientProcessEntity(struct entity_state_s* inEntity)
|
|
{
|
|
// Check if we need to create or destroy particle systems
|
|
int theIndex = inEntity->number;
|
|
bool theParticleOn = inEntity->iuser3 == AVH_USER3_PARTICLE_ON;
|
|
bool theParticleOff = inEntity->iuser3 == AVH_USER3_PARTICLE_OFF;
|
|
if(theParticleOn || theParticleOff)
|
|
{
|
|
int theHandle = -1;
|
|
if(theParticleOn)
|
|
{
|
|
// Ent index and template index stored in fuser1
|
|
int theValue = (int)(inEntity->fuser1);
|
|
int theGenEntIndex = (0xFFFF0000 & theValue) >> 16;
|
|
//int theTemplateIndex = (0x0000FFFF & theValue);
|
|
int theTemplateIndex = (((int(inEntity->fuser1)) & 0x0000FF00) >> 8);
|
|
|
|
//int theTemplateIndex = theValue;
|
|
|
|
// Handle stored in fuser2
|
|
theHandle = (int)(inEntity->fuser2);
|
|
|
|
// Don't create particle systems marked as high-detail if we don't have that option set. Note, this could cause collision
|
|
// differences between the client and server if the particle system doesn't use this flag with care
|
|
const AvHParticleTemplate* theTemplate = gParticleTemplateList.GetTemplateAtIndex(theTemplateIndex);
|
|
if(theTemplate)
|
|
{
|
|
if(!theTemplate->GetHighDetailOnly() || gEngfuncs.pfnGetCvarFloat(kvHighDetail))
|
|
{
|
|
AvHParticleSystemManager::Instance()->CreateParticleSystemIfNotCreated(inEntity->number, theTemplateIndex, /*theEntIndex,*/ theHandle);
|
|
|
|
// Update postion and visibility
|
|
if(theGenEntIndex > 0)
|
|
{
|
|
cl_entity_s* theGenEntity = gEngfuncs.GetEntityByIndex(theGenEntIndex);
|
|
if(theGenEntity)
|
|
{
|
|
AvHParticleSystemManager::Instance()->SetParticleSystemGenerationEntityExtents(theGenEntity->curstate.mins, theGenEntity->curstate.maxs, theHandle);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
AvHParticleSystemManager::Instance()->SetParticleSystemPosition(inEntity->origin, theHandle);
|
|
}
|
|
|
|
// Set the particle system custom data
|
|
//uint16 theCustomData = (uint16)(((int)inEntity->fuser3) >> 16);
|
|
//uint16 theCustomData = (uint16)(inEntity->fuser3);
|
|
uint16 theCustomData = (uint16)(inEntity->weaponmodel);
|
|
AvHParticleSystemManager::Instance()->SetParticleSystemCustomData(theCustomData, theHandle);
|
|
}
|
|
}
|
|
}
|
|
else if(theParticleOff)
|
|
{
|
|
theHandle = (int)(inEntity->fuser1);
|
|
//AvHParticleSystemManager::Instance()->DestroyParticleSystemIfNotDestroyed(inEntity->number, theHandle);
|
|
AvHParticleSystemManager::Instance()->MarkParticleSystemForDeletion(inEntity->number, theHandle);
|
|
}
|
|
|
|
// Always update visibility
|
|
bool theVisibilityState = false;
|
|
if(this->GetInTopDownMode())
|
|
{
|
|
if(GetHasUpgrade(inEntity->iuser4, MASK_VIS_SIGHTED))
|
|
{
|
|
theVisibilityState = true;
|
|
}
|
|
else
|
|
{
|
|
theVisibilityState = false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
theVisibilityState = true;
|
|
}
|
|
|
|
AvHParticleSystemManager::Instance()->SetParticleSystemVisibility(theVisibilityState, theHandle);
|
|
}
|
|
else if((inEntity->iuser3 == AVH_USER3_AUDIO_ON) || (inEntity->iuser3 == AVH_USER3_AUDIO_OFF))
|
|
{
|
|
// Read values
|
|
int theEntIndex = (int)(inEntity->fuser1) >> 16;
|
|
//int theSoundIndex = (int)(inEntity->fuser1) & 0x0000FFFF;
|
|
|
|
// memcpy so value isn't interpreted
|
|
//int theSoundIndex = 0;
|
|
//memcpy(&theSoundIndex, &inEntity->fuser1, sizeof(float));
|
|
//theSoundIndex = theSoundIndex & 0x0000FFFF;
|
|
int theSoundIndex = (((int(inEntity->fuser1)) & 0x0000FF00) >> 8);
|
|
|
|
// Top byte is flags, next byte is volume, bottom two bytes are fade distance
|
|
int theFlags = inEntity->iuser4 >> 24;
|
|
int theVolume = (inEntity->iuser4 >> 16) & 0x00FF;
|
|
int theFadeDistance = (inEntity->iuser4) & 0x0000FFFF;
|
|
|
|
float theTimeOfAction = inEntity->fuser2;
|
|
|
|
bool theSoundOn = (inEntity->iuser3 == AVH_USER3_AUDIO_ON);
|
|
|
|
this->ModifyAmbientSoundEntryIfChanged(theSoundOn, theSoundIndex, theEntIndex, theTimeOfAction, theVolume, theFadeDistance, theFlags, inEntity->origin);
|
|
}
|
|
}
|
|
|
|
string LookupAndTranslate(AvHMessageID inMessageID)
|
|
{
|
|
string theKey = string(kTechNodeLabelPrefix) + MakeStringFromInt((int)inMessageID);
|
|
|
|
string theTranslatedTechName;
|
|
LocalizeString(theKey.c_str(), theTranslatedTechName);
|
|
|
|
return theTranslatedTechName;
|
|
}
|
|
|
|
void AvHHud::DisplayCombatUpgradeMenu(bool inVisible)
|
|
{
|
|
if(inVisible)
|
|
{
|
|
// Parse current tech nodes and set text
|
|
const AvHTechID kLineStart[kNumUpgradeLines] = {TECH_ONE_LEVEL_ONE, TECH_TWO_LEVEL_ONE, TECH_THREE_LEVEL_ONE, TECH_FOUR_LEVEL_ONE, TECH_FIVE_LEVEL_ONE};
|
|
|
|
// Add "you are now x"!
|
|
string theYouAreNow;
|
|
LocalizeString(kYouAreNowA, theYouAreNow);
|
|
|
|
string theRankTitle = this->GetRankTitle(false);
|
|
|
|
string theExclamation;
|
|
LocalizeString(kExclamation, theExclamation);
|
|
|
|
string theChooseAnUpgrade;
|
|
LocalizeString(kChooseAnUpgrade, theChooseAnUpgrade);
|
|
|
|
string theFinalText = theYouAreNow + string(" ") + theRankTitle + theExclamation + string("\n");
|
|
theFinalText += theChooseAnUpgrade + string("\n\n");
|
|
|
|
// Set the lines
|
|
this->mCombatUpgradeMenu.SetText(theFinalText);
|
|
}
|
|
|
|
// Parse text above every time, but only set position once so it doesn't keep animating
|
|
if(inVisible && !this->mDrawCombatUpgradeMenu)
|
|
{
|
|
// Start off screen, and scroll right
|
|
const float kWidth = .4f;
|
|
this->mCombatUpgradeMenu.SetNormalizedScreenX(-kWidth);
|
|
this->mCombatUpgradeMenu.SetNormalizedScreenY(.25f);
|
|
this->mCombatUpgradeMenu.SetNormalizedMaxWidth(kWidth);
|
|
}
|
|
|
|
this->mDrawCombatUpgradeMenu = inVisible;
|
|
}
|
|
|
|
void AvHHud::DisplayMessage(const char* inMessage)
|
|
{
|
|
this->m_Message.MessageAdd(inMessage, this->m_flTime);
|
|
|
|
// Remember the time -- to fix up level transitions
|
|
//this->m_Message.m_parms.time = this->m_flTime;
|
|
|
|
// Turn on drawing
|
|
if ( !(this->m_Message.m_iFlags & HUD_ACTIVE) )
|
|
this->m_Message.m_iFlags |= HUD_ACTIVE;
|
|
}
|
|
|
|
//int AvHHud::GetArmorLevel(void) const
|
|
//{
|
|
// return this->mArmorLevel;
|
|
//}
|
|
|
|
int AvHHud::GetFrameForOrderType(AvHOrderType inOrderType) const
|
|
{
|
|
int theFrame = 0;
|
|
|
|
switch(inOrderType)
|
|
{
|
|
case ORDERTYPEL_DEFAULT:
|
|
theFrame = 2;
|
|
break;
|
|
|
|
case ORDERTYPEL_MOVE:
|
|
theFrame = 2;
|
|
break;
|
|
|
|
case ORDERTYPET_ATTACK:
|
|
theFrame = 4;
|
|
break;
|
|
|
|
case ORDERTYPET_BUILD:
|
|
theFrame = 5;
|
|
break;
|
|
|
|
case ORDERTYPET_GUARD:
|
|
theFrame = 6;
|
|
break;
|
|
|
|
case ORDERTYPET_WELD:
|
|
theFrame = 7;
|
|
break;
|
|
|
|
case ORDERTYPET_GET:
|
|
theFrame = 8;
|
|
break;
|
|
}
|
|
|
|
return theFrame;
|
|
}
|
|
|
|
AvHPlayMode AvHHud::GetPlayMode(void) const
|
|
{
|
|
AvHPlayMode thePlayMode = PLAYMODE_UNDEFINED;
|
|
|
|
cl_entity_s* thePlayer = gEngfuncs.GetLocalPlayer();
|
|
if(thePlayer)
|
|
{
|
|
if(gEngfuncs.IsSpectateOnly())
|
|
{
|
|
thePlayMode = PLAYMODE_OBSERVER;
|
|
}
|
|
else
|
|
{
|
|
thePlayMode = AvHPlayMode(thePlayer->curstate.playerclass);
|
|
}
|
|
}
|
|
|
|
return thePlayMode;
|
|
}
|
|
|
|
AvHPlayMode AvHHud::GetHUDPlayMode() const
|
|
{
|
|
AvHPlayMode thePlayMode = this->GetPlayMode();
|
|
|
|
cl_entity_s* thePlayer = this->GetVisiblePlayer();
|
|
if(thePlayer)
|
|
{
|
|
thePlayMode = AvHPlayMode(thePlayer->curstate.playerclass);
|
|
}
|
|
|
|
return thePlayMode;
|
|
}
|
|
|
|
cl_entity_s* AvHHud::GetVisiblePlayer() const
|
|
{
|
|
cl_entity_s* thePlayer = gEngfuncs.GetLocalPlayer();
|
|
if(g_iUser1 == OBS_IN_EYE)
|
|
{
|
|
cl_entity_t* theEnt = gEngfuncs.GetEntityByIndex(g_iUser2);
|
|
if(theEnt)
|
|
{
|
|
thePlayer = theEnt;
|
|
}
|
|
}
|
|
|
|
return thePlayer;
|
|
}
|
|
|
|
int AvHHud::GetLocalUpgrades() const
|
|
{
|
|
static int theUpgrades = 0;
|
|
|
|
cl_entity_s* thePlayer = this->GetVisiblePlayer();
|
|
if(thePlayer)
|
|
{
|
|
theUpgrades = thePlayer->curstate.iuser4;
|
|
}
|
|
|
|
return theUpgrades;
|
|
}
|
|
|
|
// Players could hack their client dll and see all the orders on their team. Minor cheat but definitely possible.
|
|
EntityListType AvHHud::GetDrawPlayerOrders() const
|
|
{
|
|
EntityListType theList;
|
|
|
|
cl_entity_s* theVisiblePlayer = this->GetVisiblePlayer();
|
|
if(theVisiblePlayer)
|
|
{
|
|
int theVisiblePlayerIndex = theVisiblePlayer->index;
|
|
|
|
if(this->GetHUDUser3() == AVH_USER3_MARINE_PLAYER)
|
|
{
|
|
// Only draw orders for us
|
|
theList.push_back(theVisiblePlayerIndex);
|
|
}
|
|
else if(this->GetHUDUser3() == AVH_USER3_COMMANDER_PLAYER)
|
|
{
|
|
// Add everyone that he has selected!
|
|
return this->mSelected;
|
|
}
|
|
}
|
|
|
|
return theList;
|
|
}
|
|
|
|
bool AvHHud::GetInTopDownMode() const
|
|
{
|
|
return this->mInTopDownMode;
|
|
}
|
|
|
|
bool AvHHud::GetIsSelecting() const
|
|
{
|
|
return mSelectionBoxVisible;
|
|
}
|
|
|
|
OrderListType AvHHud::GetOrderList() const
|
|
{
|
|
return this->mOrders;
|
|
}
|
|
|
|
//AvHOrderType AvHHud::GetOrderMode() const
|
|
//{
|
|
// return this->mOrderMode;
|
|
//}
|
|
|
|
bool AvHHud::GetCenterPositionForGroup(int inGroupNumber, vec3_t& outCenterPosition) const
|
|
{
|
|
bool theSuccess = false;
|
|
|
|
if((inGroupNumber >= 1) && (inGroupNumber <= kNumHotkeyGroups))
|
|
{
|
|
vec3_t theCenterPosition;
|
|
VectorClear(theCenterPosition);
|
|
|
|
int theNumFound = 0;
|
|
|
|
const EntityListType& theGroup = this->mGroups[inGroupNumber - 1];
|
|
if(theGroup.size() > 0)
|
|
{
|
|
for(EntityListType::const_iterator theIter = theGroup.begin(); theIter != theGroup.end(); theIter++)
|
|
{
|
|
int theEntIndex = *theIter;
|
|
|
|
Vector thePosition;
|
|
cl_entity_s* theEntity = gEngfuncs.GetEntityByIndex(theEntIndex);
|
|
if(theEntity)
|
|
{
|
|
thePosition = theEntity->curstate.origin;
|
|
}
|
|
|
|
if(AvHSHUGetEntityLocation(theEntIndex, thePosition))
|
|
{
|
|
theCenterPosition.x += thePosition.x;
|
|
theCenterPosition.y += thePosition.y;
|
|
theNumFound++;
|
|
}
|
|
}
|
|
|
|
if(theNumFound > 0)
|
|
{
|
|
theCenterPosition.x /= theNumFound;
|
|
theCenterPosition.y /= theNumFound;
|
|
|
|
outCenterPosition = theCenterPosition;
|
|
|
|
theSuccess = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return theSuccess;
|
|
}
|
|
|
|
void AvHHud::GetMousePos(int& outX, int& outY) const
|
|
{
|
|
gEngfuncs.GetMousePosition(&outX, &outY);
|
|
|
|
// Clip mouse to window (weird)
|
|
outX = min(max(0, outX), ScreenWidth());
|
|
outY = min(max(0, outY), ScreenHeight());
|
|
|
|
//char theMouseMessage[256];
|
|
//sprintf(theMouseMessage, "Mouse coords: %d, %d", outX, outY);
|
|
//CenterPrint(theMouseMessage);
|
|
}
|
|
|
|
bool AvHHud::GetAndClearTopDownScrollAmount(int& outX, int& outY, int& outZ)
|
|
{
|
|
bool theSuccess = false;
|
|
outX = 0;
|
|
outY = 0;
|
|
outZ = 0;
|
|
|
|
// Don't scroll if the the commander is dragging a selection box.
|
|
|
|
if(this->GetInTopDownMode() && !GetIsSelecting())
|
|
{
|
|
const int kScreenWidth = ScreenWidth();
|
|
const int kScreenHeight = ScreenHeight();
|
|
const kScrollHorizontal = .0152f*kScreenWidth;
|
|
const kScrollVertical = .015f*kScreenHeight;
|
|
|
|
// Left side
|
|
if(this->GetIsMouseInRegion(0, 0, kScrollHorizontal, kScreenHeight) || (gScrollHandler.GetXScroll() < 0))
|
|
{
|
|
outX = -1;
|
|
}
|
|
// Right side
|
|
else if(this->GetIsMouseInRegion(kScreenWidth - kScrollHorizontal, 0, kScrollHorizontal, kScreenHeight) || (gScrollHandler.GetXScroll() > 0))
|
|
{
|
|
outX = 1;
|
|
}
|
|
|
|
// Top edge
|
|
if(this->GetIsMouseInRegion(0, 0, kScreenWidth, kScrollVertical) || (gScrollHandler.GetYScroll() > 0))
|
|
{
|
|
outY = 1;
|
|
}
|
|
// Bottom edge
|
|
else if(this->GetIsMouseInRegion(0, kScreenHeight - kScrollVertical, kScreenWidth, kScrollVertical) || (gScrollHandler.GetYScroll() < 0))
|
|
{
|
|
outY = -1;
|
|
}
|
|
|
|
// Only clear z scroll because of the way events work (invnext/invprev vs. holding a key down)
|
|
//gScrollHandler.ClearScrollHeight();
|
|
|
|
theSuccess = true;
|
|
}
|
|
|
|
return theSuccess;
|
|
}
|
|
|
|
bool AvHHud::GetAndClearSelectionEvent(vec3_t& outSelection, AvHMessageID& outMessageID)
|
|
{
|
|
bool theSuccess = false;
|
|
|
|
// Return a build event if there is one, else return a COMMANDER_MOUSECOORD event
|
|
if(this->mLeftMouseStarted)
|
|
{
|
|
if(this->mValidatedBuilding == MESSAGE_NULL)
|
|
{
|
|
VectorCopy(this->mLeftMouseWorldStart, outSelection);
|
|
outMessageID = COMMANDER_MOUSECOORD;
|
|
}
|
|
else
|
|
{
|
|
VectorCopy(this->mNormBuildLocation, outSelection);
|
|
outMessageID = this->mValidatedBuilding;
|
|
this->mValidatedBuilding = this->mGhostBuilding = MESSAGE_NULL;
|
|
this->mPlacingBuilding = true;
|
|
}
|
|
theSuccess = true;
|
|
}
|
|
else if(this->mLeftMouseEnded)
|
|
{
|
|
if(!this->mPlacingBuilding)
|
|
{
|
|
outSelection = this->mLeftMouseWorldEnd;
|
|
outMessageID = COMMANDER_MOUSECOORD;
|
|
theSuccess = true;
|
|
}
|
|
this->mPlacingBuilding = false;
|
|
}
|
|
else if(this->mRightMouseStarted)
|
|
{
|
|
// Cancel building placement
|
|
if(this->mGhostBuilding != MESSAGE_NULL)
|
|
{
|
|
CancelBuilding();
|
|
}
|
|
else
|
|
{
|
|
outSelection = this->mRightMouseWorldStart;
|
|
outMessageID = COMMANDER_MOUSECOORD;
|
|
theSuccess = true;
|
|
}
|
|
}
|
|
else if(this->mRightMouseEnded)
|
|
{
|
|
outSelection = this->mRightMouseWorldEnd;
|
|
outMessageID = COMMANDER_MOUSECOORD;
|
|
theSuccess = true;
|
|
}
|
|
else
|
|
{
|
|
outSelection = this->mMouseWorldPosition;
|
|
outMessageID = COMMANDER_MOUSECOORD;
|
|
theSuccess = true;
|
|
}
|
|
|
|
return theSuccess;
|
|
}
|
|
|
|
EntityListType AvHHud::GetSelected() const
|
|
{
|
|
return this->mSelected;
|
|
}
|
|
|
|
const AvHTechSlotManager& AvHHud::GetTechSlotManager() const
|
|
{
|
|
return this->mTechSlotManager;
|
|
}
|
|
|
|
bool AvHHud::GetAndClearAlienAbility(AvHMessageID& outMessageID)
|
|
{
|
|
bool theAlienAbilityWaiting = false;
|
|
|
|
if(this->mAlienAbility != MESSAGE_NULL)
|
|
{
|
|
outMessageID = this->mAlienAbility;
|
|
theAlienAbilityWaiting = true;
|
|
this->mAlienAbility = MESSAGE_NULL;
|
|
}
|
|
|
|
return theAlienAbilityWaiting;
|
|
}
|
|
|
|
bool AvHHud::GetAndClearGroupEvent(AvHMessageID& outMessageID)
|
|
{
|
|
bool theGroupEventWaiting = false;
|
|
|
|
if(this->mGroupEvent != MESSAGE_NULL)
|
|
{
|
|
outMessageID = this->mGroupEvent;
|
|
theGroupEventWaiting = true;
|
|
|
|
// if(!this->mIsTracking)
|
|
// {
|
|
this->mGroupEvent = MESSAGE_NULL;
|
|
// }
|
|
}
|
|
|
|
return theGroupEventWaiting;
|
|
}
|
|
|
|
int AvHHud::GetTrackingEntity() const
|
|
{
|
|
return this->mTrackingEntity;
|
|
}
|
|
|
|
void AvHHud::ClearTrackingEntity()
|
|
{
|
|
this->mTrackingEntity = 0;
|
|
}
|
|
|
|
void AvHHud::SetSelectionEffects(EntityListType& inUnitList)
|
|
{
|
|
// Make sure we have an effect created for each unit in this list. If there are units that
|
|
// have selection effects that aren't in this list, delete them. This is called locally when the
|
|
// selection is predicted, then it's called again when the selection is confirmed.
|
|
this->mSelectionEffects.clear();
|
|
|
|
for(EntityListType::iterator theIter = inUnitList.begin(); theIter != inUnitList.end(); theIter++)
|
|
{
|
|
SelectionEffect theNewEffect;
|
|
theNewEffect.mEntIndex = *theIter;
|
|
theNewEffect.mAngleOffset = 0;
|
|
this->mSelectionEffects.push_back(theNewEffect);
|
|
}
|
|
}
|
|
|
|
UIMode AvHHud::GetUIMode() const
|
|
{
|
|
return this->mCurrentUIMode;
|
|
}
|
|
|
|
bool AvHHud::SwitchUIMode(UIMode inNewMode)
|
|
{
|
|
bool theSuccess = false;
|
|
|
|
// Only allow switching to a non-main mode when we're in main, always allow switching back to main mode
|
|
if((inNewMode == MAIN_MODE) || (this->mCurrentUIMode == MAIN_MODE))
|
|
{
|
|
if(inNewMode != this->mCurrentUIMode)
|
|
{
|
|
// Move pop-up menu components away or back so they don't block other compoments...ugh
|
|
if(inNewMode != MAIN_MODE)
|
|
{
|
|
gHUD.GetManager().TranslateComponent(kSoldierMenu, true);
|
|
gHUD.GetManager().TranslateComponent(kSoldierCombatMenu, true);
|
|
gHUD.GetManager().TranslateComponent(kAlienMenu, true);
|
|
gHUD.GetManager().TranslateComponent(kAlienCombatMenu, true);
|
|
gHUD.GetManager().TranslateComponent(kAlienMembrane, true);
|
|
gHUD.GetManager().TranslateComponent(kScroller, true);
|
|
gHUD.GetManager().TranslateComponent(kSelectionText, true);
|
|
//CenterPrint("Pop-up controls moved off screen");
|
|
}
|
|
else
|
|
{
|
|
gHUD.GetManager().TranslateComponent(kSoldierMenu, false);
|
|
gHUD.GetManager().TranslateComponent(kSoldierCombatMenu, false);
|
|
gHUD.GetManager().TranslateComponent(kAlienMenu, false);
|
|
gHUD.GetManager().TranslateComponent(kAlienCombatMenu, false);
|
|
gHUD.GetManager().TranslateComponent(kAlienMembrane, false);
|
|
gHUD.GetManager().TranslateComponent(kScroller, false);
|
|
gHUD.GetManager().TranslateComponent(kSelectionText, false);
|
|
//CenterPrint("Pop-up controls moved on screen");
|
|
}
|
|
|
|
this->mCurrentUIMode = inNewMode;
|
|
}
|
|
|
|
theSuccess = true;
|
|
}
|
|
|
|
return theSuccess;
|
|
}
|
|
|
|
bool AvHHud::Update(float inCurrentTime, string& outErrorString)
|
|
{
|
|
bool theSuccess = false;
|
|
|
|
if(inCurrentTime > this->mTimeOfLastUpdate)
|
|
{
|
|
|
|
this->mTimeOfCurrentUpdate = inCurrentTime;
|
|
|
|
// Predict game time
|
|
if(this->GetGameStarted())
|
|
{
|
|
this->mGameTime += (inCurrentTime - this->mTimeOfLastUpdate);
|
|
}
|
|
|
|
AvHParticleSystemManager::Instance()->Start();
|
|
|
|
// This component must always be visible to allow us to hook mouse cursor sprite drawing
|
|
this->ResetComponentsForUser3();
|
|
|
|
this->UpdateDataFromVuser4(inCurrentTime);
|
|
|
|
this->UpdateSpectating();
|
|
|
|
this->GetManager().UnhideComponent(kLastComponent);
|
|
|
|
this->UpdateDemoRecordPlayback();
|
|
|
|
theSuccess = UIHud::Update(inCurrentTime, outErrorString);
|
|
if(!theSuccess)
|
|
{
|
|
this->AddTooltip(outErrorString.c_str());
|
|
}
|
|
|
|
this->UpdateProgressBar();
|
|
|
|
this->UpdateCommonUI();
|
|
|
|
this->UpdateAlienUI(inCurrentTime);
|
|
|
|
this->UpdateMarineUI(inCurrentTime);
|
|
|
|
this->UpdateCountdown(inCurrentTime);
|
|
|
|
this->UpdateExploitPrevention();
|
|
this->UpdateFromEntities(inCurrentTime);
|
|
|
|
this->UpdateEntityID(inCurrentTime);
|
|
|
|
this->UpdateHelpText();
|
|
|
|
this->UpdateTooltips(inCurrentTime);
|
|
|
|
this->UpdateStructureNotification(inCurrentTime);
|
|
|
|
this->UpdateMusic(inCurrentTime);
|
|
|
|
this->UpdatePieMenuControl();
|
|
|
|
// Reset cursor every tick, update selection may change it
|
|
// This cursor is used when we're on the ground for pie menus as well
|
|
this->SetCursor(ORDERTYPE_UNDEFINED);
|
|
|
|
this->UpdateHierarchy();
|
|
|
|
this->UpdateInfoLocation();
|
|
|
|
if(this->GetInTopDownMode())
|
|
{
|
|
this->UpdateSelection();
|
|
gCommanderHandler.Update(this->mTechNodes, this->mResources);
|
|
|
|
// char theDebugString[128];
|
|
// sprintf(theDebugString, "norm X/Y: %f, %f", (float)this->mMouseCursorX/ScreenWidth, (float)this->mMouseCursorY/ScreenHeight);
|
|
// CenterPrint(theDebugString);
|
|
}
|
|
else
|
|
{
|
|
this->ResetTopDownUI();
|
|
}
|
|
|
|
// Update orders
|
|
//for(OrderListType::iterator theIter = this->mOrders.begin(); theIter != this->mOrders.end(); theIter++)
|
|
//{
|
|
// theIter->Update();
|
|
//}
|
|
|
|
this->UpdateTechNodes();
|
|
|
|
this->UpdateAmbientSounds();
|
|
|
|
this->UpdateViewModelEffects();
|
|
|
|
mOverviewMap.UpdateOrders(mOrders, GetDrawPlayerOrders());
|
|
mOverviewMap.Update(inCurrentTime);
|
|
|
|
float theTimePassed = inCurrentTime - this->mTimeOfLastUpdate;
|
|
|
|
AvHParticleSystemManager::Instance()->Update(theTimePassed);
|
|
|
|
AvHScriptManager::Instance()->ClientUpdate(theTimePassed);
|
|
|
|
this->UpdateResources(theTimePassed);
|
|
|
|
if((this->GetHUDPlayMode() == PLAYMODE_PLAYING) && !this->GetIsAlive())
|
|
{
|
|
this->mCommanderResourceLabel->setVisible(false);
|
|
this->mHierarchy->setVisible(false);
|
|
this->mShowMapHierarchy->setVisible(false);
|
|
}
|
|
|
|
if(cl_particleinfo->value)
|
|
{
|
|
char theDebugText[128];
|
|
int theNumVisible = AvHParticleSystemManager::Instance()->GetNumVisibleParticleSystems();
|
|
int theNum = AvHParticleSystemManager::Instance()->GetNumberParticleSystems();
|
|
int theNumTemplates = gParticleTemplateList.GetNumberTemplates();
|
|
sprintf(theDebugText, "(vis, total, list): %d, %d, %d", theNumVisible, theNum, theNumTemplates);
|
|
|
|
//sprintf(theDebugText, "step interval: %d", pmove->flTimeStepSound);
|
|
|
|
/*
|
|
if(this->mMarineResourceLabel)
|
|
{
|
|
this->mMarineResourceLabel->setText(theDebugText);
|
|
this->mMarineResourceLabel->setVisible(true);
|
|
}
|
|
*/
|
|
|
|
}
|
|
|
|
if(!gEngfuncs.pDemoAPI->IsPlayingback())
|
|
{
|
|
IN_GetMousePos(&this->mMouseCursorX, &this->mMouseCursorY);
|
|
}
|
|
|
|
// Update user3 and team
|
|
this->mLastUser3 = this->GetHUDUser3();
|
|
this->mLastTeamNumber = this->GetHUDTeam();
|
|
this->mLastPlayMode = this->GetPlayMode();
|
|
|
|
this->mTimeOfLastUpdate = inCurrentTime;
|
|
|
|
// Save view origin and angles before we do crazy viewport stuff
|
|
// gPlayerOrigin = v_origin;
|
|
// gPlayerAngles = v_angles;
|
|
}
|
|
|
|
return theSuccess;
|
|
}
|
|
|
|
//void AvHHud::UpdateSelectionEffects(float inTimePassed)
|
|
//{
|
|
// // Radians/sec
|
|
// const float kSpinRate = 1.5f;
|
|
// for(SelectionListType::iterator theIter = this->mSelectionEffects.begin(); theIter != this->mSelectionEffects.end(); theIter++)
|
|
// {
|
|
// theIter->mAngleOffset = (theIter->mAngleOffset += inTimePassed*kSpinRate) % 360;
|
|
// }
|
|
//}
|
|
|
|
bool AvHHud::GetAndClearTechEvent(AvHMessageID& outMessageID)
|
|
{
|
|
bool theTechEventWaiting = false;
|
|
|
|
if(this->mTechEvent != MESSAGE_NULL)
|
|
{
|
|
outMessageID = this->mTechEvent;
|
|
theTechEventWaiting = true;
|
|
this->mTechEvent = MESSAGE_NULL;
|
|
}
|
|
|
|
return theTechEventWaiting;
|
|
}
|
|
|
|
bool AvHHud::GetLastHotkeySelectionEvent(AvHMessageID& outMessageID)
|
|
{
|
|
bool theSuccess = false;
|
|
|
|
switch(this->mLastHotkeySelectionEvent)
|
|
{
|
|
case GROUP_SELECT_1:
|
|
case GROUP_SELECT_2:
|
|
case GROUP_SELECT_3:
|
|
case GROUP_SELECT_4:
|
|
case GROUP_SELECT_5:
|
|
outMessageID = this->mLastHotkeySelectionEvent;
|
|
theSuccess = true;
|
|
break;
|
|
}
|
|
|
|
return theSuccess;
|
|
}
|
|
|
|
void AvHHud::SetLastHotkeySelectionEvent(AvHMessageID inMessageID)
|
|
{
|
|
switch(inMessageID)
|
|
{
|
|
case MESSAGE_NULL:
|
|
case GROUP_CREATE_1:
|
|
case GROUP_CREATE_2:
|
|
case GROUP_CREATE_3:
|
|
case GROUP_CREATE_4:
|
|
case GROUP_CREATE_5:
|
|
case GROUP_SELECT_1:
|
|
case GROUP_SELECT_2:
|
|
case GROUP_SELECT_3:
|
|
case GROUP_SELECT_4:
|
|
case GROUP_SELECT_5:
|
|
case COMMANDER_REMOVESELECTION:
|
|
this->mLastHotkeySelectionEvent = inMessageID;
|
|
break;
|
|
|
|
default:
|
|
ASSERT(false);
|
|
break;
|
|
}
|
|
}
|
|
|
|
bool AvHHud::GetIsAlien() const
|
|
{
|
|
bool theIsAlien = false;
|
|
|
|
AvHUser3 theUser3 = this->GetHUDUser3();
|
|
|
|
switch(theUser3)
|
|
{
|
|
case AVH_USER3_ALIEN_PLAYER1:
|
|
case AVH_USER3_ALIEN_PLAYER2:
|
|
case AVH_USER3_ALIEN_PLAYER3:
|
|
case AVH_USER3_ALIEN_PLAYER4:
|
|
case AVH_USER3_ALIEN_PLAYER5:
|
|
case AVH_USER3_ALIEN_EMBRYO:
|
|
theIsAlien = true;
|
|
break;
|
|
}
|
|
|
|
return theIsAlien;
|
|
}
|
|
|
|
bool AvHHud::GetIsBeingDigested() const
|
|
{
|
|
bool theIsBeingDigested = false;
|
|
|
|
int theUpgrades = this->GetHUDUpgrades();
|
|
|
|
if(GetHasUpgrade(theUpgrades, MASK_DIGESTING))
|
|
{
|
|
cl_entity_t* theVisiblePlayer = this->GetVisiblePlayer();
|
|
if(theVisiblePlayer && (theVisiblePlayer->curstate.effects & EF_NODRAW))
|
|
{
|
|
theIsBeingDigested = true;
|
|
}
|
|
}
|
|
|
|
return theIsBeingDigested;
|
|
}
|
|
|
|
bool AvHHud::GetIsEnsnared() const
|
|
{
|
|
int theUpgrades = this->GetHUDUpgrades();
|
|
return GetHasUpgrade(theUpgrades, MASK_ENSNARED);
|
|
}
|
|
|
|
bool AvHHud::GetIsStunned() const
|
|
{
|
|
int theUpgrades = this->GetHUDUpgrades();
|
|
return GetHasUpgrade(theUpgrades, MASK_PLAYER_STUNNED);
|
|
}
|
|
|
|
bool AvHHud::GetIsDigesting() const
|
|
{
|
|
bool theIsDigesting = false;
|
|
|
|
int theUpgrades = this->GetHUDUpgrades();
|
|
|
|
if(GetHasUpgrade(theUpgrades, MASK_DIGESTING))
|
|
{
|
|
cl_entity_t* theVisiblePlayer = this->GetVisiblePlayer();
|
|
if(theVisiblePlayer && !(theVisiblePlayer->curstate.effects & EF_NODRAW))
|
|
{
|
|
theIsDigesting = true;
|
|
}
|
|
}
|
|
|
|
return theIsDigesting;
|
|
}
|
|
|
|
bool AvHHud::GetIsNotInControl() const
|
|
{
|
|
return GetIsBeingDigested() || !IEngineStudio.IsHardware();
|
|
}
|
|
|
|
bool AvHHud::GetIsInTopDownMode() const
|
|
{
|
|
bool theIsInTopDownMode = false;
|
|
|
|
if(GetHasUpgrade(this->GetHUDUpgrades(), MASK_TOPDOWN))
|
|
{
|
|
theIsInTopDownMode = true;
|
|
}
|
|
|
|
return theIsInTopDownMode;
|
|
}
|
|
|
|
int AvHHud::GetCommanderIndex() const
|
|
{
|
|
int theCommanderIndex = -1;
|
|
|
|
for(int i = 1; i <= MAX_PLAYERS; i++)
|
|
{
|
|
extra_player_info_t* theExtraPlayerInfo = &g_PlayerExtraInfo[i];
|
|
ASSERT(theExtraPlayerInfo);
|
|
int thePlayerClass = theExtraPlayerInfo->playerclass;
|
|
if(thePlayerClass == PLAYERCLASS_COMMANDER)
|
|
{
|
|
theCommanderIndex = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return theCommanderIndex;
|
|
}
|
|
|
|
|
|
bool AvHHud::GetHasJetpack() const
|
|
{
|
|
int theLocalUpgrades = this->GetHUDUpgrades();
|
|
bool theHasJetpackUpgrade = GetHasUpgrade(theLocalUpgrades, MASK_UPGRADE_7) && this->GetIsMarine();
|
|
|
|
return theHasJetpackUpgrade;
|
|
}
|
|
|
|
bool AvHHud::GetHasAlienUpgradesAvailable() const
|
|
{
|
|
bool theHasUpgradesAvailable = false;
|
|
|
|
if(this->GetIsAlien() && this->GetIsRelevant() && !this->GetIsBeingDigested())
|
|
{
|
|
int theUpgradeVar = this->GetLocalUpgrades();
|
|
bool theHasDefensiveUpgradesAvailable = AvHGetHasUpgradeChoiceInCategory(ALIEN_UPGRADE_CATEGORY_DEFENSE, this->mUpgrades, theUpgradeVar);
|
|
bool theHasMovementUpgradesAvailable = AvHGetHasUpgradeChoiceInCategory(ALIEN_UPGRADE_CATEGORY_MOVEMENT, this->mUpgrades, theUpgradeVar);
|
|
bool theHasSensoryUpgradesAvailable = AvHGetHasUpgradeChoiceInCategory(ALIEN_UPGRADE_CATEGORY_SENSORY, this->mUpgrades, theUpgradeVar);
|
|
|
|
theHasUpgradesAvailable = theHasDefensiveUpgradesAvailable || theHasMovementUpgradesAvailable || theHasSensoryUpgradesAvailable;
|
|
}
|
|
|
|
return theHasUpgradesAvailable;
|
|
}
|
|
|
|
bool AvHHud::GetIsMarine() const
|
|
{
|
|
bool theIsMarine = false;
|
|
|
|
AvHUser3 theUser3 = this->GetHUDUser3();
|
|
|
|
switch(theUser3)
|
|
{
|
|
case AVH_USER3_MARINE_PLAYER:
|
|
case AVH_USER3_COMMANDER_PLAYER:
|
|
theIsMarine = true;
|
|
break;
|
|
}
|
|
|
|
return theIsMarine;
|
|
}
|
|
|
|
bool AvHHud::GetIsRelevant() const
|
|
{
|
|
bool theIsRelevant = false;
|
|
|
|
if(this->GetIsAlive() && (this->GetPlayMode() == PLAYMODE_PLAYING) /*&& !this->GetIsSpectator()*/)
|
|
{
|
|
theIsRelevant = true;
|
|
}
|
|
|
|
return theIsRelevant;
|
|
}
|
|
|
|
vec3_t AvHHud::GetVisualOrigin() const
|
|
{
|
|
vec3_t theVisualOrigin = gPredictedPlayerOrigin;
|
|
|
|
theVisualOrigin.z += gPredictedPlayerVOfs[2];
|
|
|
|
return theVisualOrigin;
|
|
}
|
|
|
|
AvHMessageID AvHHud::HotKeyHit(char inChar)
|
|
{
|
|
return gCommanderHandler.HotKeyHit(inChar);
|
|
}
|
|
|
|
float AvHHud::GetGammaSlope() const
|
|
{
|
|
return sGameGammaTable.GetGammaSlope();
|
|
}
|
|
|
|
string AvHHud::GetMapName(bool inLocalOnly) const
|
|
{
|
|
string theMapName = this->mMapName;
|
|
|
|
if((theMapName == "") && !inLocalOnly )
|
|
{
|
|
const char* theLevelName = gEngfuncs.pfnGetLevelName();
|
|
if(theLevelName)
|
|
{
|
|
theMapName = string(theLevelName);
|
|
|
|
// Remove maps/ from the beginning and .bsp from the end.
|
|
StringVector theVector;
|
|
Tokenizer::split(theMapName, "/.", theVector);
|
|
if(theVector.size() >= 2)
|
|
{
|
|
theMapName = theVector[1];
|
|
}
|
|
}
|
|
}
|
|
|
|
return theMapName;
|
|
}
|
|
|
|
int AvHHud::GetNumActiveHives() const
|
|
{
|
|
int theNumActiveHives = 0;
|
|
|
|
if(this->GetIsAlien())
|
|
{
|
|
for(HiveInfoListType::const_iterator theIter = this->mHiveInfoList.begin(); theIter != this->mHiveInfoList.end(); theIter++)
|
|
{
|
|
if(theIter->mStatus == kHiveInfoStatusBuilt)
|
|
{
|
|
theNumActiveHives++;
|
|
}
|
|
}
|
|
}
|
|
|
|
return theNumActiveHives;
|
|
}
|
|
|
|
int AvHHud::GetMaxAlienResources() const
|
|
{
|
|
int theMaxAlienResources = kMaxAlienResources;
|
|
|
|
if(this->mMaxResources >= 0)
|
|
{
|
|
theMaxAlienResources = this->mMaxResources;
|
|
}
|
|
|
|
return theMaxAlienResources;
|
|
}
|
|
|
|
bool AvHHud::SetGamma(float inSlope)
|
|
{
|
|
bool theSuccess = false;
|
|
|
|
// Disable gamma stuff in debug for sanity
|
|
// #ifndef DEBUG
|
|
|
|
HDC theDC = GetDC(NULL);
|
|
if(theDC != 0)
|
|
{
|
|
const float kGammaIncrement = 0.05f;
|
|
float theGammaToTry = inSlope + kGammaIncrement;
|
|
while(!theSuccess && (theGammaToTry > 1.0f))
|
|
{
|
|
theGammaToTry -= kGammaIncrement;
|
|
|
|
sGameGammaTable.ProcessSlope(theGammaToTry);
|
|
// tankefugl: fakes a successful gamma ramp change if cl_gammaramp is set to 0
|
|
if((CVAR_GET_FLOAT(kvGammaRamp) == 0) || sGameGammaTable.InitializeToVideoState())
|
|
{
|
|
// Tell UI components so they can change shading to look the same
|
|
this->GetManager().NotifyGammaChange(theGammaToTry);
|
|
|
|
// aww yeah
|
|
theSuccess = true;
|
|
}
|
|
}
|
|
|
|
char theMessage[256];
|
|
if(theSuccess)
|
|
{
|
|
sprintf(theMessage, "Gamma set to %f.", theGammaToTry);
|
|
}
|
|
else
|
|
{
|
|
sprintf(theMessage, "Display doesn't support downloadable gamma ramps.");
|
|
}
|
|
|
|
if(!theSuccess || (gEngfuncs.GetMaxClients() == 1))
|
|
{
|
|
CenterPrint(theMessage);
|
|
}
|
|
|
|
if(!ReleaseDC(NULL, theDC))
|
|
{
|
|
// emit error about leak
|
|
}
|
|
}
|
|
|
|
//#endif
|
|
|
|
return theSuccess;
|
|
}
|
|
|
|
bool AvHHud::SlotInput(int inSlot)
|
|
{
|
|
bool theHandled = false;
|
|
|
|
if(this->mInTopDownMode)
|
|
{
|
|
if((inSlot >= 0) && (inSlot < kNumHotkeyGroups))
|
|
{
|
|
// TODO: Read state of control/duck here
|
|
bool theCreateGroup = false;
|
|
|
|
int theButtonBits = CL_ButtonBits(0);
|
|
if(theButtonBits & IN_DUCK)
|
|
{
|
|
theCreateGroup = true;
|
|
}
|
|
|
|
int theBaseOffset = theCreateGroup ? GROUP_CREATE_1 : GROUP_SELECT_1;
|
|
|
|
this->mGroupEvent = (AvHMessageID)(theBaseOffset + inSlot);
|
|
|
|
theHandled = true;
|
|
}
|
|
}
|
|
|
|
return theHandled;
|
|
}
|
|
|
|
int AvHHud::Redraw( float flTime, int intermission )
|
|
{
|
|
|
|
if (!gViewPort->IsOptionsMenuVisible() &&
|
|
!gParticleEditorHandler.GetInEditMode())
|
|
{
|
|
Render();
|
|
}
|
|
|
|
int theRC = UIHud::Redraw(flTime, intermission);
|
|
|
|
return theRC;
|
|
}
|
|
|
|
void AvHHud::ResetGammaAtExit()
|
|
{
|
|
sPregameGammaTable.InitializeToVideoState();
|
|
}
|
|
|
|
int AvHHud::ResetGammaAtExitForOnExit()
|
|
{
|
|
sPregameGammaTable.InitializeToVideoState();
|
|
return TRUE;
|
|
}
|
|
|
|
void AvHHud::ResetGammaAtExit(int inSig)
|
|
{
|
|
AvHHud::ResetGammaAtExit();
|
|
}
|
|
|
|
void AvHHud::ResetTopDownUI()
|
|
{
|
|
this->mGhostBuilding = MESSAGE_NULL;
|
|
this->mSelected.clear();
|
|
this->mSelectionEffects.clear();
|
|
|
|
gCommanderHandler.Reset();
|
|
|
|
for(int i = 0; i < kNumHotkeyGroups; i++)
|
|
{
|
|
this->mGroups[i].clear();
|
|
this->mGroupTypes[i] = AVH_USER3_NONE;
|
|
this->mGroupAlerts[i] = ALERT_NONE;
|
|
}
|
|
|
|
this->mSelectAllGroup.clear();
|
|
}
|
|
|
|
void AvHHud::SetSelectingWeaponID(int inWeaponID, int inR, int inG, int inB)
|
|
{
|
|
if(gEngfuncs.pfnGetCvarFloat(kvAutoHelp))
|
|
{
|
|
if(inR != -1)
|
|
{
|
|
this->mHelpMessage.SetR(inR);
|
|
}
|
|
if(inG != -1)
|
|
{
|
|
this->mHelpMessage.SetG(inG);
|
|
}
|
|
if(inB != -1)
|
|
{
|
|
this->mHelpMessage.SetB(inB);
|
|
}
|
|
|
|
this->mSelectingWeaponID = inWeaponID;
|
|
}
|
|
}
|
|
|
|
void AvHHud::SetTechHelpText(const string& inTechHelpText)
|
|
{
|
|
this->mTechHelpText = inTechHelpText;
|
|
}
|
|
|
|
BIND_MESSAGE(Countdown);
|
|
int AvHHud::Countdown(const char* pszName, int iSize, void* pbuf)
|
|
{
|
|
NetMsg_UpdateCountdown( pbuf, iSize, this->mNumTicksToPlay );
|
|
this->mLastTickPlayed = 1;
|
|
this->mCountDownClock = this->m_flTime;
|
|
|
|
return 1;
|
|
}
|
|
|
|
bool AvHHud::GetAmbientSoundNameFromIndex(string& outSoundName, int inSoundIndex) const
|
|
{
|
|
bool theFoundName = false;
|
|
|
|
if(inSoundIndex < (int)(this->mSoundNameList.size()))
|
|
{
|
|
outSoundName = this->mSoundNameList[inSoundIndex];
|
|
theFoundName = true;
|
|
}
|
|
|
|
return theFoundName;
|
|
}
|
|
|
|
void AvHHud::ModifyAmbientSoundEntryIfChanged(bool inSoundOn, int inSoundIndex, int inEntIndex, float inTimeStarted, int inVolume, int inFadeDistance, int inFlags, Vector inOrigin)
|
|
{
|
|
bool theFoundSound = false;
|
|
|
|
// Look up sound using inSoundIndex
|
|
string theSoundName;
|
|
if(this->GetAmbientSoundNameFromIndex(theSoundName, inSoundIndex))
|
|
{
|
|
// Loop through current sounds
|
|
for(AmbientSoundListType::iterator theIter = this->mAmbientSounds.begin(); theIter != this->mAmbientSounds.end(); )
|
|
{
|
|
bool theErasedSound = false;
|
|
if(theIter->GetEntityIndex() == inEntIndex)
|
|
{
|
|
// If found, remember that we found it
|
|
theFoundSound = true;
|
|
|
|
// Set position
|
|
theIter->SetPosition(inOrigin);
|
|
|
|
// If we're turning off sound, kill the sound
|
|
if(!inSoundOn)
|
|
{
|
|
theIter->ClearData();
|
|
theIter = this->mAmbientSounds.erase(theIter);
|
|
theErasedSound = true;
|
|
}
|
|
}
|
|
if(!theErasedSound)
|
|
{
|
|
theIter++;
|
|
}
|
|
}
|
|
|
|
// If we're turning a sound on, and we didn't find one
|
|
if(inSoundOn && !theFoundSound)
|
|
{
|
|
bool theLooping = inFlags & 2;
|
|
float theTimeElapsed = this->mTimeOfLastUpdate - inTimeStarted;
|
|
|
|
// Add new entry with these values
|
|
this->mAmbientSounds.push_back(AvHAmbientSound(theSoundName, inVolume, inFadeDistance, theLooping, inOrigin, inEntIndex, theTimeElapsed));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// We may not have the sound list yet, it's OK
|
|
//ASSERT(false);
|
|
}
|
|
}
|
|
|
|
// tankefugl:
|
|
void AvHHud::SetCenterText(const char* inText)
|
|
{
|
|
LocalizeString(inText, this->mCenterText);
|
|
this->mCenterTextTime = this->mTimeOfLastUpdate;
|
|
}
|
|
|
|
void AvHHud::ClearCenterText()
|
|
{
|
|
this->mCenterText.clear();
|
|
this->mCenterTextTime = -1;
|
|
}
|
|
|
|
// :tankefugl
|
|
|
|
// Look at incoming order. If we are one of the receivers, play a HUD sound
|
|
// indicating our new order
|
|
void AvHHud::OrderNotification(const AvHOrder& inOrder)
|
|
{
|
|
//if(!inOrder.GetOrderCompleted())
|
|
//{
|
|
// If we are commander, or we are in receiver list
|
|
int theLocalPlayer = gEngfuncs.GetLocalPlayer()->index;
|
|
if((this->GetHUDUser3() == AVH_USER3_COMMANDER_PLAYER) || (inOrder.GetHasReceiver(theLocalPlayer)))
|
|
{
|
|
// Do a switch on the order type
|
|
AvHOrderType theOrderType = inOrder.GetOrderType();
|
|
AvHHUDSound theSound = HUD_SOUND_INVALID;
|
|
|
|
// tankefugl: 0000992
|
|
// popup indicator for order
|
|
bool thePopup = false;
|
|
|
|
// Play HUD sound depending on order
|
|
switch(theOrderType)
|
|
{
|
|
case ORDERTYPEL_MOVE:
|
|
theSound = HUD_SOUND_ORDER_MOVE;
|
|
thePopup = true;
|
|
break;
|
|
|
|
case ORDERTYPET_ATTACK:
|
|
theSound = HUD_SOUND_ORDER_ATTACK;
|
|
thePopup = true;
|
|
break;
|
|
|
|
case ORDERTYPET_BUILD:
|
|
theSound = HUD_SOUND_ORDER_BUILD;
|
|
thePopup = true;
|
|
break;
|
|
|
|
case ORDERTYPET_GUARD:
|
|
theSound = HUD_SOUND_ORDER_GUARD;
|
|
thePopup = true;
|
|
break;
|
|
|
|
case ORDERTYPET_WELD:
|
|
theSound = HUD_SOUND_ORDER_WELD;
|
|
thePopup = true;
|
|
break;
|
|
|
|
case ORDERTYPET_GET:
|
|
theSound = HUD_SOUND_ORDER_GET;
|
|
thePopup = true;
|
|
break;
|
|
}
|
|
|
|
if((this->GetHUDUser3() == AVH_USER3_MARINE_PLAYER) && (inOrder.GetOrderCompleted()))
|
|
{
|
|
theSound = HUD_SOUND_ORDER_COMPLETE;
|
|
}
|
|
|
|
this->PlayHUDSound(theSound);
|
|
|
|
// tankefugl: 0000992 | 0001052
|
|
if (thePopup && (this->GetInTopDownMode() == false) && (inOrder.GetOrderActive()))
|
|
{
|
|
this->SetDisplayOrder(2, this->GetFrameForOrderType(theOrderType), "", "", "");
|
|
}
|
|
// :tankefugl
|
|
}
|
|
//}
|
|
}
|
|
|
|
void AvHHud::ResetComponentsForUser3()
|
|
{
|
|
|
|
this->mPieMenuControl = "";
|
|
|
|
this->GetManager().HideComponents();
|
|
|
|
if(gParticleEditorHandler.GetInEditMode())
|
|
{
|
|
gHUD.GetManager().UnhideComponent(kPSESizeSlider);
|
|
gHUD.GetManager().UnhideComponent(kPSESizeLabel);
|
|
|
|
gHUD.GetManager().UnhideComponent(kPSEScaleSlider);
|
|
gHUD.GetManager().UnhideComponent(kPSEScaleLabel);
|
|
|
|
gHUD.GetManager().UnhideComponent(kPSEGenerationRateSlider);
|
|
gHUD.GetManager().UnhideComponent(kPSEGenerationRateLabel);
|
|
|
|
gHUD.GetManager().UnhideComponent(kPSEParticleLifetimeSlider);
|
|
gHUD.GetManager().UnhideComponent(kPSEParticleLifetimeLabel);
|
|
|
|
gHUD.GetManager().UnhideComponent(kPSEParticleSystemLifetimeSlider);
|
|
gHUD.GetManager().UnhideComponent(kPSEParticleSystemLifetimeLabel);
|
|
|
|
gHUD.GetManager().UnhideComponent(kPSEMaxParticlesSlider);
|
|
gHUD.GetManager().UnhideComponent(kPSEMaxParticlesLabel);
|
|
|
|
gHUD.GetManager().UnhideComponent(kPSEDrawModeSlider);
|
|
gHUD.GetManager().UnhideComponent(kPSEDrawModeLabel);
|
|
|
|
gHUD.GetManager().UnhideComponent(PSEGenVelToggleSlider);
|
|
gHUD.GetManager().UnhideComponent(kPSEGenVelToggleLabel);
|
|
|
|
gHUD.GetManager().UnhideComponent(kPSEGenVelShapeSlider);
|
|
gHUD.GetManager().UnhideComponent(kPSEGenVelShapeLabel);
|
|
|
|
gHUD.GetManager().UnhideComponent(kPSEGenVelParamNumSlider);
|
|
gHUD.GetManager().UnhideComponent(kPSEGenVelParamNumLabel);
|
|
|
|
gHUD.GetManager().UnhideComponent(kPSEGenVelParamValueSlider);
|
|
gHUD.GetManager().UnhideComponent(kPSEGenVelParamValueLabel);
|
|
}
|
|
else
|
|
{
|
|
bool theIsCombatMode = (this->mMapMode == MAP_MODE_CO);
|
|
bool theIsNSMode = (this->mMapMode == MAP_MODE_NS);
|
|
|
|
if((this->GetHUDPlayMode() == PLAYMODE_PLAYING) && !this->GetIsNotInControl() && !gViewPort->IsOptionsMenuVisible())
|
|
{
|
|
switch(this->GetHUDUser3())
|
|
{
|
|
case AVH_USER3_MARINE_PLAYER:
|
|
if(theIsCombatMode)
|
|
{
|
|
this->mPieMenuControl = kSoldierCombatMenu;
|
|
}
|
|
else if(theIsNSMode)
|
|
{
|
|
this->mPieMenuControl = kSoldierMenu;
|
|
}
|
|
|
|
if (g_iUser1 == OBS_NONE)
|
|
{
|
|
this->GetManager().UnhideComponent(mPieMenuControl.c_str());
|
|
}
|
|
|
|
// Removed these for recording footage until they look better
|
|
//this->GetManager().UnhideComponent(kReinforcementsLabel);
|
|
//this->GetManager().UnhideComponent(kResourceLabel);
|
|
//this->GetManager().UnhideComponent(kMouseCursorLabel);
|
|
//this->GetManager().UnhideComponent(kDebugCSPServerLabel);
|
|
//this->GetManager().UnhideComponent(kDebugCSPClientLabel);
|
|
break;
|
|
|
|
case AVH_USER3_COMMANDER_PLAYER:
|
|
if(this->mInTopDownMode)
|
|
{
|
|
this->GetManager().UnhideComponent(kSelectionBox);
|
|
this->GetManager().UnhideComponent(kCommanderResourceLabel);
|
|
//this->GetManager().UnhideComponent(kMouseCursorLabel);
|
|
this->GetManager().UnhideComponent(kLeaveCommanderButton);
|
|
this->GetManager().UnhideComponent(kScroller);
|
|
this->GetManager().UnhideComponent(kTechHelpText);
|
|
this->GetManager().UnhideComponent(kHierarchy);
|
|
this->GetManager().UnhideComponent(kResearchBackgroundPanel);
|
|
this->GetManager().UnhideComponent(kActionButtonsComponents);
|
|
this->GetManager().UnhideComponent(kSelectAllImpulsePanel);
|
|
//this->GetManager().UnhideComponent(kTopDownHUDTopSpritePanel);
|
|
//this->GetManager().UnhideComponent(kTopDownHUDBottomSpritePanel);
|
|
}
|
|
//this->GetManager().UnhideComponent(kReinforcementsLabel);
|
|
break;
|
|
|
|
case AVH_USER3_ALIEN_PLAYER1:
|
|
case AVH_USER3_ALIEN_PLAYER2:
|
|
case AVH_USER3_ALIEN_PLAYER3:
|
|
case AVH_USER3_ALIEN_PLAYER4:
|
|
case AVH_USER3_ALIEN_PLAYER5:
|
|
if(theIsCombatMode)
|
|
{
|
|
this->mPieMenuControl = kAlienCombatMenu;
|
|
}
|
|
else if(theIsNSMode)
|
|
{
|
|
this->mPieMenuControl = kAlienMenu;
|
|
}
|
|
|
|
if (g_iUser1 == OBS_NONE)
|
|
{
|
|
this->GetManager().UnhideComponent(mPieMenuControl.c_str());
|
|
}
|
|
|
|
//this->GetManager().UnhideComponent(kMouseCursorLabel);
|
|
//this->GetManager().UnhideComponent(kDebugCSPServerLabel);
|
|
//this->GetManager().UnhideComponent(kDebugCSPClientLabel);
|
|
break;
|
|
|
|
case AVH_USER3_ALIEN_EMBRYO:
|
|
//this->GetManager().UnhideComponent(kAlienMembrane);
|
|
break;
|
|
}
|
|
|
|
if(sShowMap)
|
|
{
|
|
this->GetManager().UnhideComponent(kShowMapHierarchy);
|
|
}
|
|
|
|
mOverviewMap.SetUser3(this->GetHUDUser3());
|
|
|
|
// Update command hierarchy so it can potentially display differently
|
|
if(this->mHierarchy)
|
|
{
|
|
this->mHierarchy->setPos(.0105f*ScreenWidth(), .728*ScreenHeight());
|
|
this->mHierarchy->setSize(.265*ScreenWidth(), .247*ScreenHeight());
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
BIND_MESSAGE(BalanceVar);
|
|
int AvHHud::BalanceVar(const char* pszName, int iSize, void* pbuf)
|
|
{
|
|
string name;
|
|
BalanceMessageAction action;
|
|
int ivalue;
|
|
float fvalue;
|
|
string svalue;
|
|
NetMsg_BalanceVar( pbuf, iSize, name, action, ivalue, fvalue, svalue );
|
|
BalanceValueContainer* container = BalanceValueContainerFactory::get();
|
|
|
|
switch( action )
|
|
{
|
|
case BALANCE_ACTION_INSERT_INT:
|
|
container->insert(name,ivalue);
|
|
break;
|
|
case BALANCE_ACTION_INSERT_FLOAT:
|
|
container->insert(name,fvalue);
|
|
break;
|
|
case BALANCE_ACTION_INSERT_STRING:
|
|
container->insert(name,svalue);
|
|
break;
|
|
case BALANCE_ACTION_REMOVE:
|
|
container->remove(name);
|
|
break;
|
|
case BALANCE_ACTION_CLEAR:
|
|
container->clear();
|
|
break;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
BIND_MESSAGE(GameStatus);
|
|
int AvHHud::GameStatus(const char* pszName, int iSize, void* pbuf)
|
|
{
|
|
int status, game_time, timelimit, misc_data;
|
|
AvHMapMode map_mode;
|
|
NetMsg_GameStatus( pbuf, iSize, status, map_mode, game_time, timelimit, misc_data );
|
|
|
|
this->mMapMode = map_mode;
|
|
|
|
switch( status )
|
|
{
|
|
case kGameStatusReset:
|
|
case kGameStatusResetNewMap:
|
|
if(this->mInTopDownMode)
|
|
{
|
|
this->ToggleMouse();
|
|
}
|
|
|
|
this->ResetGame( status == kGameStatusResetNewMap ? true : false );
|
|
break;
|
|
case kGameStatusEnded: // Victor determined, but we are still in the cooldown time
|
|
this->mGameEnded = true; // Stop research
|
|
break;
|
|
case kGameStatusGameTime:
|
|
this->mGameTime = game_time;
|
|
this->mTimeLimit = timelimit;
|
|
this->mCombatAttackingTeamNumber = misc_data;
|
|
break;
|
|
case kGameStatusUnspentLevels:
|
|
this->mExperienceLevelSpent = misc_data;
|
|
break;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
BIND_MESSAGE(MiniMap);
|
|
int AvHHud::MiniMap(const char* pszName, int iSize, void* pbuf)
|
|
{
|
|
gMiniMap.ReceiveFromNetworkStream( pbuf, iSize );
|
|
return 1;
|
|
}
|
|
|
|
// tankefugl: 0000971
|
|
BIND_MESSAGE(IssueOrder);
|
|
int AvHHud::IssueOrder(const char* pszName, int iSize, void* pbuf)
|
|
{
|
|
int ordertype, ordersource, ordertarget;
|
|
NetMsg_IssueOrder( pbuf, iSize, ordertype, ordersource, ordertarget);
|
|
|
|
float now = this->GetTimeOfLastUpdate();
|
|
TeammateOrderListType::iterator theIter = this->mTeammateOrder.find(ordersource);
|
|
if (theIter == this->mTeammateOrder.end())
|
|
{
|
|
this->mTeammateOrder.insert(theIter, pair<int, TeammateOrderType>(ordersource, TeammateOrderType(ordertype, now)));
|
|
}
|
|
else
|
|
{
|
|
TeammateOrderType *theOrder = &((*theIter).second);
|
|
(*theOrder).first = ordertype;
|
|
(*theOrder).second = now;
|
|
}
|
|
|
|
if (this->GetInTopDownMode() == false)
|
|
{
|
|
cl_entity_s* theLocalPlayer = gEngfuncs.GetLocalPlayer();
|
|
if (theLocalPlayer->index == ordertarget)
|
|
{
|
|
hud_player_info_t info;
|
|
memset(&info, 0, sizeof(info));
|
|
GetPlayerInfo(ordersource, &info);
|
|
|
|
string temp;
|
|
string nameFormat;
|
|
// fetch from titles.txt
|
|
sprintf(temp, "TeammateOrder%d", ordertype);
|
|
LocalizeString(temp.c_str(), nameFormat);
|
|
sprintf(temp, nameFormat.c_str(), info.name);
|
|
|
|
this->SetDisplayOrder(1, ordertype, temp, "", "");
|
|
}
|
|
if (theLocalPlayer->index == ordersource)
|
|
{
|
|
this->mCurrentOrderTarget = ordertarget;
|
|
this->mCurrentOrderType = ordertype;
|
|
this->mCurrentOrderTime = now;
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
// :tankefugl
|
|
|
|
BIND_MESSAGE(ServerVar);
|
|
int AvHHud::ServerVar(const char* pszName, int iSize, void* pbuf)
|
|
{
|
|
string name, value;
|
|
NetMsg_ServerVar( pbuf, iSize, name, value );
|
|
|
|
mServerVariableMap[name] = value;
|
|
return 1;
|
|
}
|
|
|
|
BIND_MESSAGE(Progress);
|
|
int AvHHud::Progress(const char* pszName, int iSize, void* pbuf)
|
|
{
|
|
NetMsg_ProgressBar( pbuf, iSize, this->mProgressBarEntityIndex, this->mProgressBarParam );
|
|
return 1;
|
|
}
|
|
|
|
// Start the game over. Called after the game ends and also after a map change
|
|
void AvHHud::ResetGame(bool inMapChanged)
|
|
{
|
|
UIHud::ResetGame();
|
|
|
|
this->mResources = 0;
|
|
this->mMaxResources = -1;
|
|
this->mVisualResources = 0;
|
|
this->mUser2OfLastResourceMessage = 0;
|
|
this->mTimeOfLastEntityUpdate = -1;
|
|
this->mVisualEnergyLevel = 0;
|
|
this->mUser2OfLastEnergyLevel = 0;
|
|
|
|
// Don't use a menu yet
|
|
//this->ResetUpgradeCosts();
|
|
|
|
// Reset armor as well.
|
|
//this->mArmorLevel = ARMOR_BASE;
|
|
|
|
// Clear out all particle systems and templates
|
|
if(inMapChanged)
|
|
{
|
|
gParticleTemplateList.Clear();
|
|
this->mTimeOfLastUpdate = 0.0f;
|
|
this->mInfoLocationList.clear();
|
|
}
|
|
|
|
// puzl: 1066 reset overview map on game restart
|
|
gHUD.GetOverviewMap().Clear();
|
|
|
|
AvHParticleSystemManager::Instance()->Reset();
|
|
|
|
this->mTechSlotManager.Clear();
|
|
|
|
this->mTechNodes.Clear();
|
|
|
|
this->mTimeOfCurrentUpdate = 0.0f;
|
|
|
|
// On game reset, clear blips (happens on server as well)
|
|
|
|
this->mEntityHierarchy.Clear();
|
|
|
|
// Clear selection effects
|
|
this->mSelectionEffects.clear();
|
|
|
|
// End any jetpack effects
|
|
//EndJetpackEffects();
|
|
|
|
// Clear client scripts
|
|
AvHScriptManager::Instance()->Reset();
|
|
|
|
// Selection and commander variables
|
|
this->mNumLocalSelectEvents = 0;
|
|
this->mMapMode = MAP_MODE_UNDEFINED;
|
|
this->mInTopDownMode = false;
|
|
this->mLeftMouseStarted = false;
|
|
this->mLeftMouseEnded = false;
|
|
this->mPlacingBuilding = false;
|
|
|
|
sShowMap = false;
|
|
|
|
this->StopMusic();
|
|
|
|
for(AmbientSoundListType::iterator theIter = this->mAmbientSounds.begin(); theIter != this->mAmbientSounds.end(); theIter++)
|
|
{
|
|
theIter->ClearData();
|
|
}
|
|
this->mAmbientSounds.clear();
|
|
|
|
this->SetReinforcements(0);
|
|
|
|
this->mOrders.clear();
|
|
|
|
this->mCurrentCursorFrame = 0;
|
|
this->mProgressBarEntityIndex = -1;
|
|
this->mProgressBarParam = -1;
|
|
|
|
this->mEnemyBlips.Clear();
|
|
this->mFriendlyBlips.Clear();
|
|
|
|
// Reset view angles (in case player was in commander mode)
|
|
gViewAngles.z = 0.0f;
|
|
gResetViewAngles = true;
|
|
|
|
// Clear location
|
|
this->mLocationText = "";
|
|
|
|
this->mUpgrades.clear();
|
|
|
|
this->mNumUpgradesAvailable = 0;
|
|
int i;
|
|
for(i = 0; i < ALIEN_UPGRADE_CATEGORY_MAX_PLUS_ONE; i++)
|
|
{
|
|
this->mCurrentUpgradeCategory[i] = ALIEN_UPGRADE_CATEGORY_INVALID;
|
|
}
|
|
|
|
// Remove all decals (no idea how to get the total decals)
|
|
//for(i = 0; i < 1024; i++)
|
|
//{
|
|
// gEngfuncs.pEfxAPI->R_DecalRemoveAll(i);
|
|
//}
|
|
RemoveAllDecals();
|
|
|
|
// Remove temp ghost building
|
|
if(this->mLastGhostBuilding)
|
|
{
|
|
this->mLastGhostBuilding->die = -1;
|
|
}
|
|
|
|
this->mNumericalInfoEffects.clear();
|
|
this->mTimeOfNextHudSound = -1;
|
|
this->mLastHUDSoundPlayed = HUD_SOUND_INVALID;
|
|
|
|
//this->mTooltips.clear();
|
|
|
|
this->mHiveInfoList.clear();
|
|
|
|
this->mDesiredGammaSlope = kDefaultMapGamma;
|
|
this->mRecordingLastFrame = false;
|
|
this->mTimeOfLastHelpText = -1;
|
|
this->mDisplayedToolTipList.clear();
|
|
this->mCurrentWeaponID = -1;
|
|
this->mCurrentWeaponEnabled = false;
|
|
|
|
// Is this needed?
|
|
//this->mCurrentUIMode = MAIN_MODE;
|
|
|
|
this->mMenuTechSlots = 0;
|
|
this->mPendingRequests.clear();
|
|
|
|
for(i = 0; i < kNumHotkeyGroups; i++)
|
|
{
|
|
this->mGroups[i].clear();
|
|
this->mGroupTypes[i] = AVH_USER3_NONE;
|
|
this->mGroupAlerts[i] = ALERT_NONE;
|
|
}
|
|
this->mSelectAllGroup.clear();
|
|
|
|
this->mCurrentSquad = 0;
|
|
this->mBlinkingAlertType = 0;
|
|
|
|
this->mLastTeamSpectated = TEAM_IND;
|
|
|
|
this->mStructureNotificationList.clear();
|
|
|
|
this->mGameTime = -1;
|
|
this->mTimeLimit = -1;
|
|
this->mCombatAttackingTeamNumber = 0;
|
|
this->mGameEnded = false;
|
|
|
|
this->mExperience = 0;
|
|
this->mExperienceLevel = 1;
|
|
this->mExperienceLevelLastDrawn = 1;
|
|
this->mExperienceLevelSpent = 0;
|
|
this->mTimeOfLastLevelUp = -1;
|
|
|
|
memset(this->mMenuImpulses, MESSAGE_NULL, sizeof(AvHMessageID)*kNumUpgradeLines);
|
|
|
|
// tankefugl: 0000992 & 0000971
|
|
this->mTeammateOrder.clear();
|
|
this->mCurrentOrderTarget = 0;
|
|
this->mCurrentOrderType = 0;
|
|
this->mCurrentOrderTime = 0.0f;
|
|
|
|
this->mDisplayOrderTime = 0.0f;
|
|
this->mDisplayOrderType = 0;
|
|
this->mDisplayOrderIndex = 0;
|
|
this->mDisplayOrderText1 = "";
|
|
this->mDisplayOrderText2 = "";
|
|
this->mDisplayOrderText3 = "";
|
|
|
|
this->mCenterText.clear();
|
|
this->mCenterTextTime = -1;
|
|
// :tankefugl
|
|
}
|
|
|
|
BIND_MESSAGE(SetGmma);
|
|
int AvHHud::SetGmma(const char* pszName, int iSize, void* pbuf)
|
|
{
|
|
NetMsg_SetGammaRamp( pbuf, iSize, this->mDesiredGammaSlope );
|
|
if (!mSteamUIActive)
|
|
{
|
|
this->SetGamma(this->mDesiredGammaSlope);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
BIND_MESSAGE(BlipList);
|
|
int AvHHud::BlipList(const char* pszName, int iSize, void* pbuf)
|
|
{
|
|
bool friendly_blips;
|
|
AvHVisibleBlipList list;
|
|
NetMsg_BlipList( pbuf, iSize, friendly_blips, list );
|
|
|
|
float theCurrentTime = gEngfuncs.GetClientTime();
|
|
|
|
if( friendly_blips )
|
|
{
|
|
this->mFriendlyBlips.Clear();
|
|
this->mFriendlyBlips.AddBlipList(list);
|
|
this->mFriendlyBlips.SetTimeBlipsReceived(theCurrentTime);
|
|
}
|
|
else
|
|
{
|
|
this->mEnemyBlips.Clear();
|
|
this->mEnemyBlips.AddBlipList(list);
|
|
this->mEnemyBlips.SetTimeBlipsReceived(theCurrentTime);
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
BIND_MESSAGE(ClScript);
|
|
int AvHHud::ClScript(const char *pszName, int iSize, void *pbuf)
|
|
{
|
|
StringList script_names;
|
|
NetMsg_ClientScripts( pbuf, iSize, script_names );
|
|
StringList::iterator current, end = script_names.end();
|
|
for( current = script_names.begin(); current != end; ++current )
|
|
{
|
|
AvHScriptManager::Instance()->RunScript(current->c_str());
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
BIND_MESSAGE(Particles);
|
|
int AvHHud::Particles(const char *pszName, int iSize, void *pbuf)
|
|
{
|
|
AvHParticleTemplate particle_template;
|
|
NetMsg_SetParticleTemplate( pbuf, iSize, particle_template );
|
|
gParticleTemplateList.Insert( particle_template );
|
|
|
|
return 1;
|
|
}
|
|
|
|
BIND_MESSAGE(SoundNames);
|
|
int AvHHud::SoundNames(const char *pszName, int iSize, void *pbuf)
|
|
{
|
|
bool theClearSoundList;
|
|
string sound_name;
|
|
NetMsg_SetSoundNames( pbuf, iSize, theClearSoundList, sound_name );
|
|
|
|
if(theClearSoundList)
|
|
{
|
|
this->mSoundNameList.clear();
|
|
}
|
|
else
|
|
{
|
|
this->mSoundNameList.push_back(sound_name);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
BIND_MESSAGE(SetSelect);
|
|
int AvHHud::SetSelect(const char* pszName, int iSize, void* pbuf)
|
|
{
|
|
Selection selection;
|
|
NetMsg_SetSelect( pbuf, iSize, selection );
|
|
|
|
EntityListType theGroup;
|
|
|
|
switch( selection.group_number )
|
|
{
|
|
case 0:
|
|
this->mTrackingEntity = selection.tracking_entity;
|
|
if( selection.selected_entities != this->mSelected )
|
|
{
|
|
this->mSelectionJustChanged = true;
|
|
this->mSelected = selection.selected_entities;
|
|
}
|
|
break;
|
|
case kSelectAllHotGroup:
|
|
this->mSelectAllGroup = selection.selected_entities;
|
|
break;
|
|
default:
|
|
this->mGroups[selection.group_number-1] = selection.selected_entities;
|
|
this->mGroupTypes[selection.group_number-1] = selection.group_type;
|
|
this->mGroupAlerts[selection.group_number-1] = selection.group_alert;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
BIND_MESSAGE(SetRequest);
|
|
int AvHHud::SetRequest(const char* pszName, int iSize, void* pbuf)
|
|
{
|
|
int request_type, request_count;
|
|
NetMsg_SetRequest( pbuf, iSize, request_type, request_count );
|
|
this->mPendingRequests[(AvHMessageID)request_type] = request_count;
|
|
|
|
return 1;
|
|
}
|
|
|
|
BIND_MESSAGE(SetOrder);
|
|
int AvHHud::SetOrder(const char* pszName, int iSize, void* pbuf)
|
|
{
|
|
AvHOrder theNewOrder;
|
|
NetMsg_SetOrder( pbuf, iSize, theNewOrder );
|
|
|
|
AvHChangeOrder(this->mOrders, theNewOrder);
|
|
|
|
// Give feedback on order
|
|
this->OrderNotification(theNewOrder);
|
|
|
|
// Run through orders, deleting any that are complete
|
|
for(OrderListType::iterator theIter = this->mOrders.begin(); theIter != this->mOrders.end(); /* no inc */)
|
|
{
|
|
if(theIter->GetOrderCompleted())
|
|
{
|
|
this->mOrders.erase(theIter);
|
|
}
|
|
else
|
|
{
|
|
theIter++;
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
BIND_MESSAGE(SetupMap);
|
|
int AvHHud::SetupMap(const char* pszName, int iSize, void* pbuf)
|
|
{
|
|
bool is_location, draw_background;
|
|
float min_extents[3], max_extents[3];
|
|
string name;
|
|
NetMsg_SetupMap( pbuf, iSize, is_location, name, min_extents, max_extents, draw_background );
|
|
|
|
if( is_location )
|
|
{
|
|
vec3_t theMaxExtent;
|
|
theMaxExtent.x = max_extents[0];
|
|
theMaxExtent.y = max_extents[1];
|
|
theMaxExtent.z = max_extents[2];
|
|
vec3_t theMinExtent;
|
|
theMinExtent.x = min_extents[0];
|
|
theMinExtent.y = min_extents[1];
|
|
theMinExtent.z = min_extents[2];
|
|
|
|
this->mInfoLocationList.push_back( AvHBaseInfoLocation( name, theMaxExtent, theMinExtent ) );
|
|
}
|
|
else
|
|
{
|
|
this->mMapName = name;
|
|
this->mMapExtents.SetMaxMapX( max_extents[0] );
|
|
this->mMapExtents.SetMaxMapY( max_extents[1] );
|
|
this->mMapExtents.SetMaxViewHeight( max_extents[2] );
|
|
this->mMapExtents.SetMinMapX( min_extents[0] );
|
|
this->mMapExtents.SetMinMapY( min_extents[1] );
|
|
this->mMapExtents.SetMinViewHeight( min_extents[2] );
|
|
this->mMapExtents.SetDrawMapBG( draw_background );
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
BIND_MESSAGE(SetTopDown);
|
|
int AvHHud::SetTopDown(const char* pszName, int iSize, void* pbuf)
|
|
{
|
|
bool is_menu_tech, is_top_down;
|
|
float position[3];
|
|
int tech_slots;
|
|
NetMsg_SetTopDown( pbuf, iSize, is_menu_tech, is_top_down, position, tech_slots );
|
|
|
|
if(is_menu_tech)
|
|
{
|
|
this->mMenuTechSlots = tech_slots;
|
|
}
|
|
else
|
|
{
|
|
if(this->mInTopDownMode && !is_top_down)
|
|
{
|
|
// Switch away from top down mode
|
|
this->mInTopDownMode = false;
|
|
this->ToggleMouse();
|
|
|
|
// Reset angles
|
|
gViewAngles[0] = position[0];
|
|
gViewAngles[1] = position[1];
|
|
gViewAngles[2] = position[2];
|
|
|
|
gResetViewAngles = true;
|
|
|
|
this->mSelectionEffects.clear();
|
|
}
|
|
else if(!this->mInTopDownMode && is_top_down)
|
|
{
|
|
// Switch to top down mode!
|
|
this->mInTopDownMode = true;
|
|
this->ToggleMouse();
|
|
}
|
|
|
|
if(is_top_down)
|
|
{
|
|
// Read new PAS
|
|
this->mCommanderPAS.x = position[0];
|
|
this->mCommanderPAS.y = position[1];
|
|
this->mCommanderPAS.z = position[2];
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
BIND_MESSAGE(EntHier);
|
|
int AvHHud::EntHier(const char *pszName, int iSize, void *pbuf)
|
|
{
|
|
MapEntityMap new_items;
|
|
EntityListType old_items;
|
|
NetMsg_UpdateEntityHierarchy( pbuf, iSize, new_items, old_items );
|
|
|
|
MapEntityMap::iterator current, end = new_items.end();
|
|
for( current = new_items.begin(); current != end; ++current )
|
|
{
|
|
this->mEntityHierarchy.InsertEntity( current->first, current->second );
|
|
}
|
|
|
|
EntityListType::iterator d_current, d_end = old_items.end();
|
|
for( d_current = old_items.begin(); d_current != d_end; ++d_current )
|
|
{
|
|
this->mEntityHierarchy.DeleteEntity( *d_current );
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
BIND_MESSAGE(EditPS);
|
|
int AvHHud::EditPS(const char* pszName, int iSize, void* pbuf)
|
|
{
|
|
int particle_index;
|
|
NetMsg_EditPS( pbuf, iSize, particle_index );
|
|
AvHParticleEditorHandler::SetEditIndex((uint32)particle_index);
|
|
|
|
return 1;
|
|
}
|
|
|
|
BIND_MESSAGE(Fog);
|
|
int AvHHud::Fog(const char* pszName, int iSize, void* pbuf)
|
|
{
|
|
bool enabled;
|
|
int R, G, B;
|
|
float start, end;
|
|
NetMsg_Fog( pbuf, iSize, enabled, R, G, B, start, end );
|
|
|
|
this->mFogActive = enabled;
|
|
if(enabled)
|
|
{
|
|
this->mFogColor.x = R;
|
|
this->mFogColor.y = G;
|
|
this->mFogColor.z = B;
|
|
this->mFogStart = start;
|
|
this->mFogEnd = end;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
BIND_MESSAGE(ListPS);
|
|
int AvHHud::ListPS(const char* pszName, int iSize, void* pbuf)
|
|
{
|
|
string name;
|
|
NetMsg_ListPS( pbuf, iSize, name );
|
|
this->m_SayText.SayTextPrint(name.c_str(), 256, 0);
|
|
|
|
return 1;
|
|
}
|
|
|
|
BIND_MESSAGE(PlayHUDNot);
|
|
int AvHHud::PlayHUDNot(const char* pszName, int iSize, void* pbuf)
|
|
{
|
|
int message_id, sound;
|
|
float location_x, location_y;
|
|
NetMsg_PlayHUDNotification( pbuf, iSize, message_id, sound, location_x, location_y );
|
|
|
|
if(message_id == 0)
|
|
{
|
|
// Hack to avoid adding another network message (at max)
|
|
if(!this->GetInTopDownMode())
|
|
{
|
|
switch(sound)
|
|
{
|
|
case HUD_SOUND_SQUAD1:
|
|
this->mCurrentSquad = 1;
|
|
break;
|
|
case HUD_SOUND_SQUAD2:
|
|
this->mCurrentSquad = 2;
|
|
break;
|
|
case HUD_SOUND_SQUAD3:
|
|
this->mCurrentSquad = 3;
|
|
break;
|
|
case HUD_SOUND_SQUAD4:
|
|
this->mCurrentSquad = 4;
|
|
break;
|
|
case HUD_SOUND_SQUAD5:
|
|
this->mCurrentSquad = 5;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch((AvHHUDSound)sound)
|
|
{
|
|
// Danger
|
|
case HUD_SOUND_MARINE_SOLDIER_UNDER_ATTACK:
|
|
case HUD_SOUND_MARINE_BASE_UNDER_ATTACK:
|
|
case HUD_SOUND_MARINE_SENTRYDAMAGED:
|
|
case HUD_SOUND_MARINE_SOLDIERLOST:
|
|
case HUD_SOUND_MARINE_CCUNDERATTACK:
|
|
this->mBlinkingAlertType = 2;
|
|
AddMiniMapAlert(location_x, location_y);
|
|
break;
|
|
|
|
// Just research or something like that
|
|
case HUD_SOUND_MARINE_UPGRADE_COMPLETE:
|
|
case HUD_SOUND_MARINE_RESEARCHCOMPLETE:
|
|
this->mBlinkingAlertType = 1;
|
|
AddMiniMapAlert(location_x, location_y);
|
|
break;
|
|
}
|
|
}
|
|
|
|
this->PlayHUDSound((AvHHUDSound)sound);
|
|
}
|
|
else
|
|
{
|
|
// Push back icon
|
|
HUDNotificationType theNotification;
|
|
theNotification.mStructureID = (AvHMessageID)sound; //message_id;
|
|
theNotification.mTime = this->mTimeOfCurrentUpdate;
|
|
theNotification.mLocation = Vector(location_x, location_y, 0.0f);
|
|
|
|
if(CVAR_GET_FLOAT(kvBuildMessages))
|
|
{
|
|
this->mStructureNotificationList.push_back(theNotification);
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
BIND_MESSAGE(AlienInfo);
|
|
int AvHHud::AlienInfo(const char* pszName, int iSize, void* pbuf)
|
|
{
|
|
bool was_hive_info;
|
|
AvHAlienUpgradeListType upgrades;
|
|
HiveInfoListType hives;
|
|
NetMsg_AlienInfo( pbuf, iSize, was_hive_info, this->mUpgrades, this->mHiveInfoList );
|
|
return 1;
|
|
}
|
|
|
|
void AvHHud::PlayHUDSound(const char *szSound, float vol, float inSoundLength)
|
|
{
|
|
if((this->mTimeOfNextHudSound == -1) || (this->mTimeOfCurrentUpdate > this->mTimeOfNextHudSound))
|
|
{
|
|
if(szSound)
|
|
{
|
|
char theSoundName[512];
|
|
strcpy(theSoundName, szSound);
|
|
gEngfuncs.pfnPlaySoundByName(theSoundName, vol);
|
|
this->mTimeOfNextHudSound = this->mTimeOfCurrentUpdate + inSoundLength;
|
|
}
|
|
}
|
|
}
|
|
|
|
void AvHHud::PlayHUDSound(int iSound, float vol, float inSoundLength)
|
|
{
|
|
if((this->mTimeOfNextHudSound == -1) || (this->mTimeOfCurrentUpdate > this->mTimeOfNextHudSound))
|
|
{
|
|
gEngfuncs.pfnPlaySoundByIndex(iSound, vol);
|
|
this->mTimeOfNextHudSound = this->mTimeOfCurrentUpdate + inSoundLength;
|
|
}
|
|
}
|
|
|
|
void AvHHud::PlayHUDSound(AvHHUDSound inSound)
|
|
{
|
|
char* theSoundPtr = NULL;
|
|
float theVolume = 1.0f;
|
|
|
|
// Some sounds are forced, but don't allow them to be spammed or cut themselves off
|
|
bool theForceSound = AvHSHUGetForceHUDSound(inSound) && (inSound != this->mLastHUDSoundPlayed);
|
|
|
|
// tankefugl: 0000407
|
|
bool theAutoHelpEnabled = gEngfuncs.pfnGetCvarFloat(kvAutoHelp);
|
|
// :tankefugl
|
|
|
|
if((this->mTimeOfNextHudSound == -1) || (this->mTimeOfCurrentUpdate >= this->mTimeOfNextHudSound) || theForceSound)
|
|
{
|
|
float theSoundLength = 2.0f;
|
|
|
|
switch(inSound)
|
|
{
|
|
case HUD_SOUND_POINTS_SPENT:
|
|
theSoundPtr = kPointsSpentSound;
|
|
theSoundLength = .2f;
|
|
break;
|
|
case HUD_SOUND_COUNTDOWN:
|
|
theSoundPtr = kCountdownSound;
|
|
theSoundLength = 0.0f;
|
|
break;
|
|
case HUD_SOUND_SELECT:
|
|
if(gHUD.GetIsAlien())
|
|
theSoundPtr = kSelectAlienSound;
|
|
else
|
|
theSoundPtr = kSelectSound;
|
|
|
|
// Set to 0 so it never blocks other sounds
|
|
theVolume = .2f;
|
|
theSoundLength = 0.0f;
|
|
break;
|
|
case HUD_SOUND_SQUAD1:
|
|
if(this->GetInTopDownMode())
|
|
{
|
|
theSoundPtr = kSquad1Sound;
|
|
theSoundLength = 1.2f;
|
|
}
|
|
else
|
|
{
|
|
theSoundPtr = kMarineSquad1Sound;
|
|
theSoundLength = 2.0f;
|
|
}
|
|
break;
|
|
case HUD_SOUND_SQUAD2:
|
|
if(this->GetInTopDownMode())
|
|
{
|
|
theSoundPtr = kSquad2Sound;
|
|
theSoundLength = 1.2f;
|
|
}
|
|
else
|
|
{
|
|
theSoundPtr = kMarineSquad2Sound;
|
|
theSoundLength = 2.0f;
|
|
}
|
|
break;
|
|
case HUD_SOUND_SQUAD3:
|
|
if(this->GetInTopDownMode())
|
|
{
|
|
theSoundPtr = kSquad3Sound;
|
|
theSoundLength = 1.2f;
|
|
}
|
|
else
|
|
{
|
|
theSoundPtr = kMarineSquad3Sound;
|
|
theSoundLength = 2.0f;
|
|
}
|
|
break;
|
|
case HUD_SOUND_SQUAD4:
|
|
if(this->GetInTopDownMode())
|
|
{
|
|
theSoundPtr = kSquad4Sound;
|
|
theSoundLength = 1.2f;
|
|
}
|
|
else
|
|
{
|
|
theSoundPtr = kMarineSquad4Sound;
|
|
theSoundLength = 2.0f;
|
|
}
|
|
break;
|
|
case HUD_SOUND_SQUAD5:
|
|
if(this->GetInTopDownMode())
|
|
{
|
|
theSoundPtr = kSquad5Sound;
|
|
theSoundLength = 1.2f;
|
|
}
|
|
else
|
|
{
|
|
theSoundPtr = kMarineSquad5Sound;
|
|
theSoundLength = 2.0f;
|
|
}
|
|
break;
|
|
case HUD_SOUND_PLACE_BUILDING:
|
|
theSoundPtr = kPlaceBuildingSound;
|
|
theSoundLength = .2f;
|
|
break;
|
|
|
|
case HUD_SOUND_MARINE_POINTS_RECEIVED:
|
|
theSoundPtr = kMarinePointsReceivedSound;
|
|
theSoundLength = 1.42f;
|
|
break;
|
|
|
|
case HUD_SOUND_MARINE_RESEARCHCOMPLETE:
|
|
theSoundPtr = kMarineResearchComplete;
|
|
theSoundLength = 2.0f;
|
|
break;
|
|
case HUD_SOUND_MARINE_SOLDIER_UNDER_ATTACK:
|
|
theSoundPtr = kMarineSoldierUnderAttack;
|
|
theSoundLength = 3.0f;
|
|
break;
|
|
case HUD_SOUND_MARINE_CCONLINE:
|
|
if(rand() % 2)
|
|
{
|
|
theSoundPtr = kMarineCCOnline1;
|
|
}
|
|
else
|
|
{
|
|
theSoundPtr = kMarineCCOnline2;
|
|
}
|
|
theSoundLength = 2.3f;
|
|
break;
|
|
case HUD_SOUND_MARINE_CCUNDERATTACK:
|
|
if(rand() % 2)
|
|
{
|
|
theSoundPtr = kMarineCCUnderAttack1;
|
|
}
|
|
else
|
|
{
|
|
theSoundPtr = kMarineCCUnderAttack2;
|
|
}
|
|
theSoundLength = 3.0f;
|
|
break;
|
|
case HUD_SOUND_MARINE_COMMANDER_EJECTED:
|
|
theSoundPtr = kMarineCommanderEjected;
|
|
theSoundLength = 3.0f;
|
|
break;
|
|
case HUD_SOUND_MARINE_BASE_UNDER_ATTACK:
|
|
if(rand() % 2)
|
|
{
|
|
theSoundPtr = kMarineBaseUnderAttack1;
|
|
}
|
|
else
|
|
{
|
|
theSoundPtr = kMarineBaseUnderAttack2;
|
|
}
|
|
theSoundLength = 3.0f;
|
|
break;
|
|
case HUD_SOUND_MARINE_UPGRADE_COMPLETE:
|
|
theSoundPtr = kMarineUpgradeComplete;
|
|
theSoundLength = 1.0f;
|
|
break;
|
|
case HUD_SOUND_MARINE_MORE:
|
|
theSoundPtr = kMarineMoreResources;
|
|
theSoundLength = 1.8f;
|
|
break;
|
|
case HUD_SOUND_MARINE_RESOURCES_LOW:
|
|
theSoundPtr = kMarineLowResources;
|
|
theSoundLength = 2.0f;
|
|
break;
|
|
case HUD_SOUND_MARINE_NEEDS_AMMO:
|
|
if(rand() % 2)
|
|
theSoundPtr = kMarineNeedsAmmo1;
|
|
else
|
|
theSoundPtr = kMarineNeedsAmmo2;
|
|
theSoundLength = 1.5f;
|
|
break;
|
|
case HUD_SOUND_MARINE_NEEDS_HEALTH:
|
|
if(rand() % 2)
|
|
theSoundPtr = kMarineNeedsHealth1;
|
|
else
|
|
theSoundPtr = kMarineNeedsHealth2;
|
|
theSoundLength = 1.3f;
|
|
break;
|
|
|
|
case HUD_SOUND_MARINE_NEEDS_ORDER:
|
|
if(rand() % 2)
|
|
theSoundPtr = kMarineNeedsOrder1;
|
|
else
|
|
theSoundPtr = kMarineNeedsOrder2;
|
|
theSoundLength = 1.5f;
|
|
break;
|
|
|
|
case HUD_SOUND_MARINE_SOLDIER_LOST:
|
|
if(rand() % 2)
|
|
theSoundPtr = kMarineSoldierLost1;
|
|
else
|
|
theSoundPtr = kMarineSoldierLost2;
|
|
theSoundLength = 1.3f;
|
|
break;
|
|
case HUD_SOUND_MARINE_SENTRYFIRING:
|
|
if(rand() % 2)
|
|
theSoundPtr = kMarineSentryFiring1;
|
|
else
|
|
theSoundPtr = kMarineSentryFiring2;
|
|
theSoundLength = 1.3f;
|
|
break;
|
|
case HUD_SOUND_MARINE_SENTRYDAMAGED:
|
|
if(rand() % 2)
|
|
theSoundPtr = kMarineSentryTakingDamage1;
|
|
else
|
|
theSoundPtr = kMarineSentryTakingDamage2;
|
|
theSoundLength = 1.5f;
|
|
break;
|
|
|
|
case HUD_SOUND_MARINE_GIVEORDERS:
|
|
// tankefugl: 0000407
|
|
if (theAutoHelpEnabled)
|
|
{
|
|
theSoundPtr = kMarineGiveOrders;
|
|
theSoundLength = 2.2f;
|
|
}
|
|
// :tankefugl
|
|
break;
|
|
|
|
case HUD_SOUND_MARINE_NEEDPORTAL:
|
|
// tankefugl: 0000407
|
|
if (theAutoHelpEnabled)
|
|
{
|
|
if(rand() % 2)
|
|
theSoundPtr = kMarineNeedPortal1;
|
|
else
|
|
theSoundPtr = kMarineNeedPortal2;
|
|
theSoundLength = 1.8f;
|
|
}
|
|
// :tankefugl
|
|
break;
|
|
|
|
case HUD_SOUND_MARINE_GOTOALERT:
|
|
// tankefugl: 0000407
|
|
if (theAutoHelpEnabled)
|
|
{
|
|
theSoundPtr = kMarineGotoAlert;
|
|
theSoundLength = 2.2f;
|
|
}
|
|
// :tankefugl
|
|
break;
|
|
|
|
case HUD_SOUND_MARINE_COMMANDERIDLE:
|
|
// tankefugl: 0000407
|
|
if (theAutoHelpEnabled)
|
|
{
|
|
if(rand() % 2)
|
|
theSoundPtr = kMarineCommanderIdle1;
|
|
else
|
|
theSoundPtr = kMarineCommanderIdle2;
|
|
theSoundLength = 1.5f;
|
|
}
|
|
// :tankefugl
|
|
break;
|
|
|
|
case HUD_SOUND_MARINE_ARMORYUPGRADING:
|
|
theSoundPtr = kMarineArmoryUpgrading;
|
|
theSoundLength = 3.4;
|
|
break;
|
|
|
|
case HUD_SOUND_ALIEN_ENEMY_APPROACHES:
|
|
if(rand() %2)
|
|
theSoundPtr = kAlienEnemyApproaches1;
|
|
else
|
|
theSoundPtr = kAlienEnemyApproaches2;
|
|
theSoundLength = 1.6;
|
|
break;
|
|
|
|
case HUD_SOUND_ALIEN_GAMEOVERMAN:
|
|
theSoundPtr = kAlienGameOverMan;
|
|
theSoundLength = 2.2f;
|
|
break;
|
|
|
|
case HUD_SOUND_ALIEN_HIVE_ATTACK:
|
|
theSoundPtr = kAlienHiveAttack;
|
|
theSoundLength = 1.6f;
|
|
break;
|
|
case HUD_SOUND_ALIEN_HIVE_COMPLETE:
|
|
if(rand() % 2)
|
|
theSoundPtr = kAlienHiveComplete1;
|
|
else
|
|
theSoundPtr = kAlienHiveComplete2;
|
|
theSoundLength = 2.1f;
|
|
break;
|
|
case HUD_SOUND_ALIEN_HIVE_DYING:
|
|
if(rand() % 2)
|
|
{
|
|
theSoundPtr = kAlienHiveDying1;
|
|
theSoundLength = 1.7f;
|
|
}
|
|
else
|
|
{
|
|
theSoundPtr = kAlienHiveDying2;
|
|
theSoundLength = 2.4f;
|
|
}
|
|
break;
|
|
case HUD_SOUND_ALIEN_LIFEFORM_ATTACK:
|
|
if(rand() % 2)
|
|
theSoundPtr = kAlienLifeformAttack1;
|
|
else
|
|
theSoundPtr = kAlienLifeformAttack2;
|
|
theSoundLength = 1.8f;
|
|
break;
|
|
case HUD_SOUND_ALIEN_RESOURCES_LOW:
|
|
theSoundPtr = kAlienLowResources;
|
|
theSoundLength = 1.7f;
|
|
break;
|
|
case HUD_SOUND_ALIEN_MESS:
|
|
theSoundPtr = kAlienMess;
|
|
theSoundLength = 2.0f;
|
|
break;
|
|
case HUD_SOUND_ALIEN_MORE:
|
|
if(rand() % 2)
|
|
theSoundPtr = kAlienMoreResources1;
|
|
else
|
|
theSoundPtr = kAlienMoreResources2;
|
|
theSoundLength = 1.8f;
|
|
break;
|
|
case HUD_SOUND_ALIEN_NEED_BUILDERS:
|
|
if(rand() % 2)
|
|
theSoundPtr = kAlienNeedBuilders1;
|
|
else
|
|
theSoundPtr = kAlienNeedBuilders2;
|
|
theSoundLength = 1.4f;
|
|
break;
|
|
|
|
case HUD_SOUND_ALIEN_NEED_BETTER:
|
|
theSoundPtr = kAlienNeedBetter;
|
|
theSoundLength = 2.5f;
|
|
break;
|
|
|
|
case HUD_SOUND_ALIEN_NOW_DONCE:
|
|
theSoundPtr = kAlienNowDonce;
|
|
theSoundLength = 2.1f;
|
|
break;
|
|
|
|
case HUD_SOUND_ALIEN_NEW_TRAIT:
|
|
if(rand() % 2)
|
|
theSoundPtr = kAlienNewTrait1;
|
|
else
|
|
theSoundPtr = kAlienNewTrait2;
|
|
theSoundLength = 1.5f;
|
|
break;
|
|
|
|
case HUD_SOUND_ALIEN_POINTS_RECEIVED:
|
|
theSoundPtr = kAlienPointsReceivedSound;
|
|
theSoundLength = 1.57f;
|
|
break;
|
|
|
|
case HUD_SOUND_ALIEN_RESOURCES_ATTACK:
|
|
if(rand() % 2)
|
|
theSoundPtr = kAlienResourceAttack1;
|
|
else
|
|
theSoundPtr = kAlienResourceAttack2;
|
|
theSoundLength = 2.1f;
|
|
break;
|
|
case HUD_SOUND_ALIEN_STRUCTURE_ATTACK:
|
|
if(rand() % 2)
|
|
theSoundPtr = kAlienStructureAttack1;
|
|
else
|
|
theSoundPtr = kAlienStructureAttack2;
|
|
theSoundLength = 1.9f;
|
|
break;
|
|
case HUD_SOUND_ALIEN_UPGRADELOST:
|
|
theSoundPtr = kAlienUpgradeLost;
|
|
theSoundLength = 1.5f;
|
|
break;
|
|
|
|
case HUD_SOUND_ORDER_MOVE:
|
|
switch(rand() % 4)
|
|
{
|
|
case 0:
|
|
theSoundPtr = kSoundOrderMove1;
|
|
theSoundLength = 1.8f;
|
|
break;
|
|
case 1:
|
|
theSoundPtr = kSoundOrderMove2;
|
|
theSoundLength = 2.3f;
|
|
break;
|
|
case 2:
|
|
theSoundPtr = kSoundOrderMove3;
|
|
theSoundLength = 1.9f;
|
|
break;
|
|
case 3:
|
|
theSoundPtr = kSoundOrderMove4;
|
|
theSoundLength = 2.3f;
|
|
break;
|
|
}
|
|
break;
|
|
case HUD_SOUND_ORDER_ATTACK:
|
|
theSoundPtr = kSoundOrderAttack;
|
|
break;
|
|
case HUD_SOUND_ORDER_BUILD:
|
|
theSoundPtr = kSoundOrderBuild;
|
|
break;
|
|
case HUD_SOUND_ORDER_WELD:
|
|
theSoundPtr = kSoundOrderWeld;
|
|
break;
|
|
case HUD_SOUND_ORDER_GUARD:
|
|
theSoundPtr = kSoundOrderGuard;
|
|
break;
|
|
case HUD_SOUND_ORDER_GET:
|
|
theSoundPtr = kSoundOrderGet;
|
|
break;
|
|
|
|
case HUD_SOUND_ORDER_COMPLETE:
|
|
switch(rand() % 6)
|
|
{
|
|
case 0:
|
|
theSoundPtr = kSoundOrderComplete1;
|
|
theSoundLength = 1.6f;
|
|
break;
|
|
case 1:
|
|
theSoundPtr = kSoundOrderComplete2;
|
|
theSoundLength = 1.9f;
|
|
break;
|
|
case 2:
|
|
theSoundPtr = kSoundOrderComplete3;
|
|
theSoundLength = 1.9f;
|
|
break;
|
|
case 3:
|
|
theSoundPtr = kSoundOrderComplete4;
|
|
theSoundLength = 1.4f;
|
|
break;
|
|
case 4:
|
|
theSoundPtr = kSoundOrderComplete5;
|
|
theSoundLength = 1.6f;
|
|
break;
|
|
case 5:
|
|
theSoundPtr = kSoundOrderComplete6;
|
|
theSoundLength = 1.4f;
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case HUD_SOUND_GAMESTART:
|
|
if(this->GetIsMarine())
|
|
{
|
|
if(rand() % 2)
|
|
theSoundPtr = kMarineGameStart1;
|
|
else
|
|
theSoundPtr = kMarineGameStart2;
|
|
theSoundLength = 1.9f;
|
|
}
|
|
else if(this->GetIsAlien())
|
|
{
|
|
if(rand() % 2)
|
|
theSoundPtr = kAlienGameStart1;
|
|
else
|
|
theSoundPtr = kAlienGameStart2;
|
|
theSoundLength = 2.2f;
|
|
}
|
|
break;
|
|
|
|
case HUD_SOUND_YOU_WIN:
|
|
theSoundPtr = kYouWinSound;
|
|
theSoundLength = 6.0f;
|
|
break;
|
|
case HUD_SOUND_YOU_LOSE:
|
|
theSoundPtr = kYouLoseSound;
|
|
theSoundLength = 6.0f;
|
|
break;
|
|
case HUD_SOUND_TOOLTIP:
|
|
theSoundPtr = kTooltipSound;
|
|
// Tooltip sounds should never stop other sounds
|
|
theSoundLength = -1.0f;
|
|
theVolume = .6f;
|
|
break;
|
|
// joev: bug 0000767
|
|
case HUD_SOUND_PLAYERJOIN:
|
|
theSoundPtr = kPlayerJoinedSound;
|
|
theSoundLength = 3.0f;
|
|
theVolume = 1.1;
|
|
break;
|
|
// :joev
|
|
}
|
|
|
|
if(theSoundPtr)
|
|
{
|
|
gEngfuncs.pfnPlaySoundByName(theSoundPtr, theVolume);
|
|
if(theSoundLength >= 0.0f)
|
|
{
|
|
this->mTimeOfNextHudSound = this->mTimeOfCurrentUpdate + theSoundLength;
|
|
}
|
|
this->mLastHUDSoundPlayed = inSound;
|
|
}
|
|
}
|
|
}
|
|
|
|
BIND_MESSAGE(SetTech);
|
|
int AvHHud::SetTech(const char* pszName, int iSize, void* pbuf)
|
|
{
|
|
AvHTechNode* theTechNode = NULL;
|
|
NetMsg_SetTechNode( pbuf, iSize, theTechNode );
|
|
this->mTechNodes.InsertNode(theTechNode);
|
|
delete theTechNode;
|
|
|
|
return 1;
|
|
}
|
|
|
|
BIND_MESSAGE(TechSlots);
|
|
int AvHHud::TechSlots(const char* pszName, int iSize, void* pbuf)
|
|
{
|
|
AvHTechSlots theNewTechSlots;
|
|
NetMsg_SetTechSlots( pbuf, iSize, theNewTechSlots );
|
|
|
|
this->mTechSlotManager.AddTechSlots(theNewTechSlots);
|
|
|
|
return 1;
|
|
}
|
|
|
|
BIND_MESSAGE(DebugCSP);
|
|
int AvHHud::DebugCSP(const char* pszName, int iSize, void* pbuf)
|
|
{
|
|
weapon_data_t weapon_data;
|
|
float next_attack;
|
|
NetMsg_DebugCSP( pbuf, iSize, weapon_data, next_attack );
|
|
|
|
char theServerInfoString[512];
|
|
sprintf(theServerInfoString, "Server: id: %d, clip: %d, prim attack: %f, idle: %f, next attack: %f",
|
|
weapon_data.m_iId,
|
|
weapon_data.m_iClip,
|
|
weapon_data.m_flNextPrimaryAttack,
|
|
weapon_data.m_flTimeWeaponIdle,
|
|
weapon_data.m_flNextSecondaryAttack,
|
|
next_attack
|
|
);
|
|
|
|
vgui::Label* theLabel = NULL;
|
|
if(this->GetManager().GetVGUIComponentNamed(kDebugCSPServerLabel, theLabel))
|
|
{
|
|
theLabel->setText(theServerInfoString);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
AvHVisibleBlipList& AvHHud::GetEnemyBlipList()
|
|
{
|
|
return this->mEnemyBlips;
|
|
}
|
|
|
|
AvHEntityHierarchy& AvHHud::GetEntityHierarchy()
|
|
{
|
|
return this->mEntityHierarchy;
|
|
}
|
|
|
|
AvHVisibleBlipList& AvHHud::GetFriendlyBlipList()
|
|
{
|
|
return this->mFriendlyBlips;
|
|
}
|
|
|
|
bool AvHHud::GetMouseOneDown() const
|
|
{
|
|
return this->mMouseOneDown;
|
|
}
|
|
|
|
bool AvHHud::GetMouseTwoDown() const
|
|
{
|
|
return this->mMouseTwoDown;
|
|
}
|
|
|
|
void AvHHud::HideProgressStatus()
|
|
{
|
|
if(this->mGenericProgressBar)
|
|
{
|
|
this->mGenericProgressBar->setVisible(false);
|
|
}
|
|
|
|
if(this->mAlienProgressBar)
|
|
{
|
|
this->mAlienProgressBar->setVisible(false);
|
|
}
|
|
}
|
|
|
|
void AvHHud::HideResearchProgressStatus()
|
|
{
|
|
if(this->mResearchProgressBar)
|
|
{
|
|
this->mResearchProgressBar->setVisible(false);
|
|
this->mResearchLabel->setVisible(false);
|
|
}
|
|
}
|
|
|
|
void AvHHud::Init(void)
|
|
{
|
|
UIHud::Init();
|
|
|
|
HOOK_MESSAGE(EntHier);
|
|
HOOK_MESSAGE(Particles);
|
|
HOOK_MESSAGE(SoundNames);
|
|
HOOK_MESSAGE(PlayHUDNot);
|
|
HOOK_MESSAGE(BalanceVar);
|
|
HOOK_MESSAGE(GameStatus);
|
|
HOOK_MESSAGE(Progress);
|
|
HOOK_MESSAGE(Countdown);
|
|
HOOK_MESSAGE(MiniMap);
|
|
HOOK_MESSAGE(SetOrder);
|
|
HOOK_MESSAGE(SetSelect);
|
|
HOOK_MESSAGE(SetRequest);
|
|
HOOK_MESSAGE(SetupMap);
|
|
HOOK_MESSAGE(SetTopDown);
|
|
HOOK_MESSAGE(SetTech);
|
|
HOOK_MESSAGE(EditPS);
|
|
HOOK_MESSAGE(Fog);
|
|
HOOK_MESSAGE(ListPS);
|
|
HOOK_MESSAGE(SetGmma);
|
|
HOOK_MESSAGE(BlipList);
|
|
HOOK_MESSAGE(ClScript);
|
|
HOOK_MESSAGE(AlienInfo);
|
|
HOOK_MESSAGE(DebugCSP);
|
|
HOOK_MESSAGE(TechSlots);
|
|
// tankefugl: 0000971
|
|
HOOK_MESSAGE(IssueOrder);
|
|
// :tankefugl
|
|
|
|
HOOK_MESSAGE(ServerVar);
|
|
|
|
this->AddCommands();
|
|
|
|
this->mCountDownClock = -1;
|
|
|
|
mOverviewMap.Clear();
|
|
|
|
this->mEntityHierarchy.Clear();
|
|
//this->mUpgradeCosts.clear();
|
|
|
|
sPregameGammaTable.InitializeFromVideoState();
|
|
sGameGammaTable.InitializeFromVideoState();
|
|
|
|
int theRC = atexit(AvHHud::ResetGammaAtExit);
|
|
_onexit_t theExit = _onexit(AvHHud::ResetGammaAtExitForOnExit);
|
|
|
|
signal(SIGILL, AvHHud::ResetGammaAtExit);
|
|
signal(SIGFPE, AvHHud::ResetGammaAtExit);
|
|
signal(SIGSEGV, AvHHud::ResetGammaAtExit);
|
|
signal(SIGTERM, AvHHud::ResetGammaAtExit);
|
|
signal(SIGBREAK, AvHHud::ResetGammaAtExit);
|
|
signal(SIGABRT, AvHHud::ResetGammaAtExit);
|
|
|
|
//memset(this->mAlienUILifeforms, 0, sizeof(HSPRITE)*kNumAlienLifeforms);
|
|
this->mAlienUIUpgrades = 0;
|
|
this->mAlienUIUpgradeCategories = 0;
|
|
this->mOrderSprite = 0;
|
|
this->mCursorSprite = 0;
|
|
this->mMarineCursor = 0;
|
|
this->mAlienCursor = 0;
|
|
|
|
this->mMarineUIJetpackSprite = 0;
|
|
this->mMembraneSprite = 0;
|
|
this->mBackgroundSprite = 0;
|
|
|
|
this->mProgressBarEntityIndex = -1;
|
|
this->mProgressBarParam = -1;
|
|
this->mSelectedNodeResourceCost = -1;
|
|
this->mCurrentUseableEnergyLevel = 0;
|
|
this->mVisualEnergyLevel = 0.0f;
|
|
|
|
this->mFogActive = false;
|
|
this->mFogColor.x = this->mFogColor.y = this->mFogColor.z = 0;
|
|
this->mFogStart = 0;
|
|
this->mFogEnd = 0;
|
|
|
|
this->mLocationText = "";
|
|
this->mInfoLocationList.clear();
|
|
|
|
this->mLastHotkeySelectionEvent = MESSAGE_NULL;
|
|
this->mUpgrades.clear();
|
|
|
|
this->mLastGhostBuilding = NULL;
|
|
this->mReticleInfoText = "";
|
|
this->mSelectingWeaponID = -1;
|
|
this->mSelectingNodeID = MESSAGE_NULL;
|
|
this->mDesiredGammaSlope = 1;
|
|
this->mTimeOfLastHelpText = -1;
|
|
this->mCurrentWeaponID = -1;
|
|
this->mCurrentWeaponEnabled = false;
|
|
this->mCurrentUIMode = MAIN_MODE;
|
|
this->mMenuTechSlots = 0;
|
|
this->mBlinkingAlertType = 0;
|
|
this->mLastUser3 = AVH_USER3_NONE;
|
|
this->mLastTeamNumber = TEAM_IND;
|
|
this->mLastPlayMode = PLAYMODE_UNDEFINED;
|
|
|
|
this->mCrosshairShowCount = 1;
|
|
this->mCrosshairSprite = 0;
|
|
this->mCrosshairR = 0;
|
|
this->mCrosshairG = 0;
|
|
this->mCrosshairB = 0;
|
|
|
|
this->mDrawCombatUpgradeMenu = false;
|
|
|
|
// Initialize viewport
|
|
this->mViewport[0] = this->mViewport[1] = this->mViewport[2] = this->mViewport[3] = 0;
|
|
|
|
gl_monolights = gEngfuncs.pfnGetCvarPointer("gl_monolights");
|
|
gl_overbright = gEngfuncs.pfnGetCvarPointer("gl_overbright");
|
|
gl_clear = gEngfuncs.pfnGetCvarPointer("gl_clear");
|
|
hud_draw = gEngfuncs.pfnGetCvarPointer("hud_draw");
|
|
r_drawviewmodel = gEngfuncs.pfnGetCvarPointer("r_drawviewmodel");
|
|
gl_d3dflip = gEngfuncs.pfnGetCvarPointer("gl_d3dflip");
|
|
s_show = gEngfuncs.pfnGetCvarPointer("s_show");
|
|
lightgamma = gEngfuncs.pfnGetCvarPointer("lightgamma");
|
|
r_detailtextures = gEngfuncs.pfnGetCvarPointer("r_detailtextures");
|
|
gl_max_size = gEngfuncs.pfnGetCvarPointer("gl_max_size");
|
|
}
|
|
|
|
// This gives the HUD a chance to draw after the VGUI. A component must allow itself to be hooked by calling this function
|
|
// at the end of it's paint() routine. This is done so the mouse cursor can draw on top of the other components.
|
|
void AvHHud::ComponentJustPainted(Panel* inPanel)
|
|
{
|
|
// if(this->GetInTopDownMode())
|
|
// {
|
|
// AvHTeamHierarchy* theComponent = dynamic_cast<AvHTeamHierarchy*>(inPanel);
|
|
// if(theComponent)
|
|
// {
|
|
// int theBasePosX;
|
|
// int theBasePosY;
|
|
// theComponent->getPos(theBasePosX, theBasePosY);
|
|
// this->DrawMouseCursor(theBasePosX, theBasePosY);
|
|
// }
|
|
// }
|
|
// else
|
|
// {
|
|
// PieMenu* theComponent = dynamic_cast<PieMenu*>(inPanel);
|
|
// if(theComponent)
|
|
// {
|
|
// int theBasePosX;
|
|
// int theBasePosY;
|
|
// theComponent->getPos(theBasePosX, theBasePosY);
|
|
// this->DrawMouseCursor(theBasePosX, theBasePosY);
|
|
// }
|
|
// }
|
|
|
|
|
|
DummyPanel* theComponent = dynamic_cast<DummyPanel*>(inPanel);
|
|
if(theComponent)
|
|
{
|
|
int theBasePosX;
|
|
int theBasePosY;
|
|
theComponent->getPos(theBasePosX, theBasePosY);
|
|
this->DrawMouseCursor(theBasePosX, theBasePosY);
|
|
}
|
|
|
|
}
|
|
|
|
bool AvHHud::SetCursor(AvHOrderType inOrderType)
|
|
{
|
|
bool theSuccess = false;
|
|
|
|
if(!this->GetIsAlien())
|
|
{
|
|
this->mCursorSprite = this->mMarineCursor;
|
|
|
|
if((inOrderType >= 0) && (inOrderType < ORDERTYPE_MAX))
|
|
{
|
|
this->mCurrentCursorFrame = (int)(inOrderType);
|
|
theSuccess = true;
|
|
}
|
|
// Change cursor when over a valid choice
|
|
if(this->mSelectingNodeID > 0)
|
|
{
|
|
this->mCurrentCursorFrame = 1;
|
|
theSuccess = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
this->mCursorSprite = this->mAlienCursor;
|
|
this->mCurrentCursorFrame = 0;
|
|
|
|
if(this->mSelectingNodeID > 0)
|
|
{
|
|
// Set cursor to lifeform to evolve to
|
|
switch(this->mSelectingNodeID)
|
|
{
|
|
case ALIEN_LIFEFORM_ONE:
|
|
case ALIEN_LIFEFORM_TWO:
|
|
case ALIEN_LIFEFORM_THREE:
|
|
case ALIEN_LIFEFORM_FOUR:
|
|
case ALIEN_LIFEFORM_FIVE:
|
|
this->mCurrentCursorFrame = 2 + (int)this->mSelectingNodeID - (int)ALIEN_LIFEFORM_ONE;
|
|
break;
|
|
|
|
default:
|
|
this->mCurrentCursorFrame = 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
theSuccess = true;
|
|
}
|
|
|
|
// Scheme::SchemeCursor theSchemeCursor = Scheme::SchemeCursor::scu_arrow;
|
|
// //Scheme::SchemeCursor theSchemeCursor = Scheme::SchemeCursor::scu_no;
|
|
//
|
|
// switch(inOrderType)
|
|
// {
|
|
//// case ORDERTYPE_UNDEFINED:
|
|
//// theSchemeCursor = Scheme::SchemeCursor::scu_no;
|
|
//// theSuccess = true;
|
|
//// break;
|
|
//
|
|
// //case ORDERTYPEL_MOVE:
|
|
//
|
|
// case ORDERTYPET_ATTACK:
|
|
// case ORDERTYPET_GUARD:
|
|
// case ORDERTYPET_WELD:
|
|
// case ORDERTYPET_BUILD:
|
|
// case ORDERTYPEL_USE:
|
|
// case ORDERTYPET_GET:
|
|
// theSchemeCursor = Scheme::SchemeCursor::scu_hand;
|
|
// theSuccess = true;
|
|
// break;
|
|
// }
|
|
//
|
|
// App::getInstance()->setCursorOveride( App::getInstance()->getScheme()->getCursor(theSchemeCursor));
|
|
|
|
return theSuccess;
|
|
}
|
|
|
|
void AvHHud::GetCursor(HSPRITE& outSprite, int& outFrame)
|
|
{
|
|
|
|
if (g_iUser1 == 0)
|
|
{
|
|
outSprite = mCursorSprite;
|
|
outFrame = mCurrentCursorFrame;
|
|
}
|
|
else
|
|
{
|
|
// Always use the marine cursor in spectator mode.
|
|
outSprite = mMarineCursor;
|
|
outFrame = 0;
|
|
}
|
|
|
|
}
|
|
|
|
void AvHHud::SetHelpMessage(const string& inHelpText, bool inForce, float inNormX, float inNormY)
|
|
{
|
|
if(inForce || gEngfuncs.pfnGetCvarFloat(kvAutoHelp))
|
|
{
|
|
float theReticleX = kHelpMessageLeftEdgeInset;
|
|
float theReticleY = kHelpMessageTopEdgeInset - 0.03f; // + 0.15f;
|
|
bool theCentered = false;
|
|
|
|
if(this->GetInTopDownMode())
|
|
{
|
|
int theMouseX, theMouseY;
|
|
this->GetMousePos(theMouseX, theMouseY);
|
|
theReticleX = theMouseX/(float)ScreenWidth();
|
|
theReticleY = theMouseY/(float)ScreenHeight();
|
|
|
|
// Move text up a bit so it doesn't obscure
|
|
theReticleY -= .1f;
|
|
|
|
theCentered = true;
|
|
}
|
|
// Alien HUD forces this to be inset a bit
|
|
else
|
|
{
|
|
if(this->GetIsAlien())
|
|
{
|
|
theReticleX = kHelpMessageAlienLeftedgeInset;
|
|
theReticleY = kHelpMessageAlienTopEdgeInset - 0.15f;
|
|
}
|
|
|
|
if(inNormX != -1)
|
|
{
|
|
theReticleX = inNormX;
|
|
}
|
|
if(inNormY != -1)
|
|
{
|
|
theReticleY = inNormY;
|
|
}
|
|
}
|
|
|
|
this->mHelpMessage.SetText(inHelpText);
|
|
|
|
this->mHelpMessage.SetNormalizedScreenX(theReticleX);
|
|
this->mHelpMessage.SetNormalizedScreenY(theReticleY);
|
|
this->mHelpMessage.SetCentered(theCentered);
|
|
this->mHelpMessage.SetNormalizedMaxWidth(kReticleMaxWidth);
|
|
//this->mHelpMessage.SetIgnoreFadeForLifetime(true);
|
|
|
|
float theTimePassed = (this->mTimeOfCurrentUpdate - this->mTimeOfLastUpdate);
|
|
this->mHelpMessage.FadeText(theTimePassed, false);
|
|
|
|
// Set color
|
|
int theR, theG, theB;
|
|
this->GetPrimaryHudColor(theR, theG, theB, true, false);
|
|
this->mHelpMessage.SetRGB(theR, theG, theB);
|
|
}
|
|
}
|
|
|
|
void AvHHud::SetActionButtonHelpMessage(const string& inHelpText)
|
|
{
|
|
this->mTopDownActionButtonHelp.SetText(inHelpText);
|
|
|
|
const float kNormX = .73f;
|
|
this->mTopDownActionButtonHelp.SetNormalizedScreenX(kNormX);
|
|
|
|
// Treat this as the bottom of the tooltip. Scale the tooltip so it's bottom is here.
|
|
const float kNormY = .68f;
|
|
int theHeight = this->mTopDownActionButtonHelp.GetScreenHeight();
|
|
float theNormalizedHeight = (float)theHeight/ScreenHeight();
|
|
this->mTopDownActionButtonHelp.SetNormalizedScreenY(kNormY - theNormalizedHeight);
|
|
|
|
this->mTopDownActionButtonHelp.SetBackgroundA(128);
|
|
|
|
this->mTopDownActionButtonHelp.SetCentered(false);
|
|
this->mTopDownActionButtonHelp.SetNormalizedMaxWidth(1.0f - kNormX - .01f);
|
|
//this->mTopDownActionButtonHelp.SetIgnoreFadeForLifetime(true);
|
|
|
|
float theTimePassed = (this->mTimeOfCurrentUpdate - this->mTimeOfLastUpdate);
|
|
this->mTopDownActionButtonHelp.FadeText(theTimePassed, false);
|
|
|
|
// Set color
|
|
int theR, theG, theB;
|
|
this->GetPrimaryHudColor(theR, theG, theB, true, false);
|
|
this->mTopDownActionButtonHelp.SetRGB(theR, theG, theB);
|
|
}
|
|
|
|
void AvHHud::SetReticleMessage(const string& inHelpText)
|
|
{
|
|
float theReticleX;
|
|
float theReticleY;
|
|
bool theIsCentered;
|
|
this->GetReticleTextDrawingInfo(theReticleX, theReticleY, theIsCentered);
|
|
|
|
this->mReticleMessage.SetText(inHelpText);
|
|
|
|
this->mReticleMessage.SetNormalizedScreenX(theReticleX);
|
|
this->mReticleMessage.SetNormalizedScreenY(theReticleY);
|
|
this->mReticleMessage.SetCentered(theIsCentered);
|
|
this->mReticleMessage.SetNormalizedMaxWidth(kReticleMaxWidth);
|
|
|
|
// Need instant fade-in and slow fade down for player names and info
|
|
this->mReticleMessage.SetFadeDownSpeed(-100);
|
|
this->mReticleMessage.SetFadeUpSpeed(10000);
|
|
//this->mReticleMessage.SetIgnoreFadeForLifetime(true);
|
|
|
|
float theTimePassed = (this->mTimeOfCurrentUpdate - this->mTimeOfLastUpdate);
|
|
this->mReticleMessage.FadeText(theTimePassed, false);
|
|
}
|
|
|
|
void AvHHud::SetCurrentUseableEnergyLevel(float inEnergyLevel)
|
|
{
|
|
this->mCurrentUseableEnergyLevel = inEnergyLevel;
|
|
}
|
|
|
|
const AvHMapExtents& AvHHud::GetMapExtents()
|
|
{
|
|
return this->mMapExtents;
|
|
}
|
|
|
|
void AvHHud::InitCommanderMode()
|
|
{
|
|
Panel* thePanel = NULL;
|
|
|
|
if(this->GetManager().GetVGUIComponentNamed(kLeaveCommanderButton, thePanel))
|
|
{
|
|
thePanel->addInputSignal(&gCommanderHandler);
|
|
}
|
|
|
|
if(this->GetManager().GetVGUIComponentNamed(kHierarchy, thePanel))
|
|
{
|
|
thePanel->addInputSignal(&gCommanderHandler);
|
|
}
|
|
|
|
if(this->GetManager().GetVGUIComponentNamed(kActionButtonsComponents, thePanel))
|
|
{
|
|
thePanel->addInputSignal(&gCommanderHandler);
|
|
}
|
|
|
|
if(this->GetManager().GetVGUIComponentNamed(kSelectAllImpulsePanel, thePanel))
|
|
{
|
|
thePanel->addInputSignal(&gCommanderHandler);
|
|
}
|
|
|
|
// Add handler for all pending request buttons
|
|
for(int i = 0; i < MESSAGE_LAST; i++)
|
|
{
|
|
AvHMessageID theMessageID = AvHMessageID(i);
|
|
|
|
char theComponentName[256];
|
|
sprintf(theComponentName, kPendingImpulseSpecifier, (int)theMessageID);
|
|
|
|
AvHTechImpulsePanel* theTechImpulsePanel = NULL;
|
|
if(this->GetManager().GetVGUIComponentNamed(theComponentName, theTechImpulsePanel))
|
|
{
|
|
theTechImpulsePanel->addInputSignal(&gCommanderHandler);
|
|
}
|
|
}
|
|
|
|
//this->GetManager().GetVGUIComponentNamed(kScroller, thePanel);
|
|
//if(thePanel)
|
|
//{
|
|
// thePanel->addInputSignal(&gScrollHandler);
|
|
//}
|
|
|
|
// Get input from every control
|
|
this->GetManager().AddInputSignal(&gScrollHandler);
|
|
|
|
// TODO: Add others here
|
|
}
|
|
|
|
// Read in base state from stream (called by Demo_ReadBuffer)
|
|
int AvHHud::InitializeDemoPlayback(int inSize, unsigned char* inBuffer)
|
|
{
|
|
// Read in base state
|
|
int theBytesRead = 0;
|
|
|
|
// Read in num upgrades
|
|
int theNumUpgrades = 0;
|
|
//this->mUpgradeCosts.clear();
|
|
LoadData(&theNumUpgrades, inBuffer, sizeof(int), theBytesRead);
|
|
|
|
for(int i = 0; i < theNumUpgrades; i++)
|
|
{
|
|
// Read in upgrades (for backwards-compatibility)
|
|
int theFirst = 0;
|
|
LoadData(&theFirst, inBuffer, sizeof(int), theBytesRead);
|
|
|
|
int theSecond = 0;
|
|
LoadData(&theSecond, inBuffer, sizeof(int), theBytesRead);
|
|
}
|
|
|
|
// Read in gamma
|
|
LoadData(&this->mDesiredGammaSlope, inBuffer, sizeof(this->mDesiredGammaSlope), theBytesRead);
|
|
|
|
if (!mSteamUIActive)
|
|
{
|
|
this->SetGamma(this->mDesiredGammaSlope);
|
|
}
|
|
|
|
// Read in resources
|
|
LoadData(&this->mResources, inBuffer, sizeof(this->mResources), theBytesRead);
|
|
|
|
// Read in commander (TODO: REMOVE)
|
|
int theCommander;
|
|
LoadData(&theCommander, inBuffer, sizeof(theCommander), theBytesRead);
|
|
|
|
// Read in number of hive infos
|
|
this->mHiveInfoList.clear();
|
|
|
|
int theNumHiveInfos = 0;
|
|
LoadData(&theNumHiveInfos, inBuffer, sizeof(int), theBytesRead);
|
|
|
|
// For each one, add a new hive info
|
|
for(i = 0; i < theNumHiveInfos; i++)
|
|
{
|
|
AvHHiveInfo theHiveInfo;
|
|
LoadData(&theHiveInfo, inBuffer, sizeof(AvHHiveInfo), theBytesRead);
|
|
this->mHiveInfoList.push_back(theHiveInfo);
|
|
}
|
|
|
|
// Load and set current pie menu control
|
|
int thePieMenuControlLength = 0;
|
|
LoadData(&thePieMenuControlLength, inBuffer, sizeof(int), theBytesRead);
|
|
|
|
char thePieMenuControl[256];
|
|
memset(thePieMenuControl, 0, 256);
|
|
LoadData(thePieMenuControl, inBuffer, thePieMenuControlLength, theBytesRead);
|
|
this->mPieMenuControl = string(thePieMenuControl);
|
|
|
|
// Read in selected units size
|
|
this->mSelected.clear();
|
|
int theNumSelected = 0;
|
|
LoadData(&theNumSelected, inBuffer, sizeof(theNumSelected), theBytesRead);
|
|
|
|
for(i = 0; i < theNumSelected; i++)
|
|
{
|
|
// Read in selected units
|
|
EntityInfo theSelectedEntity = 0;
|
|
LoadData(&theSelectedEntity, inBuffer, sizeof(theSelectedEntity), theBytesRead);
|
|
}
|
|
|
|
ASSERT((theBytesRead + (int)sizeof(int)) == inSize);
|
|
|
|
// Clear existing particle system templates
|
|
gParticleTemplateList.Clear();
|
|
AvHParticleSystemManager::Instance()->Reset();
|
|
|
|
// Clear weapon info
|
|
gWR.Reset();
|
|
|
|
return theBytesRead;
|
|
}
|
|
|
|
int AvHHud::InitializeDemoPlayback2(int inSize, unsigned char* inBuffer)
|
|
{
|
|
// Read in base state 2
|
|
int theBytesRead = 0;
|
|
|
|
LOAD_DATA(this->mTimeOfLastUpdate);
|
|
LOAD_DATA(this->mTimeOfNextHudSound);
|
|
LOAD_DATA(this->mTimeOfCurrentUpdate);
|
|
LOAD_DATA(this->mCountDownClock);
|
|
LOAD_DATA(this->mLastTickPlayed);
|
|
LOAD_DATA(this->mNumTicksToPlay);
|
|
LoadStringData(this->mMapName, inBuffer, theBytesRead);
|
|
|
|
float theMinViewHeight;
|
|
LOAD_DATA(theMinViewHeight);
|
|
this->mMapExtents.SetMinViewHeight(theMinViewHeight);
|
|
|
|
float theMaxViewHeight;
|
|
LOAD_DATA(theMaxViewHeight);
|
|
this->mMapExtents.SetMaxViewHeight(theMaxViewHeight);
|
|
|
|
float theMinMapX;
|
|
LOAD_DATA(theMinMapX);
|
|
this->mMapExtents.SetMinMapX(theMinMapX);
|
|
|
|
float theMaxMapX;
|
|
LOAD_DATA(theMaxMapX);
|
|
this->mMapExtents.SetMaxMapX(theMaxMapX);
|
|
|
|
float theMinMapY;
|
|
LOAD_DATA(theMinMapY);
|
|
this->mMapExtents.SetMinMapY(theMinMapY);
|
|
|
|
float theMaxMapY;
|
|
LOAD_DATA(theMaxMapY);
|
|
this->mMapExtents.SetMaxMapY(theMaxMapY);
|
|
|
|
bool theDrawMapBG;
|
|
LOAD_DATA(theDrawMapBG);
|
|
this->mMapExtents.SetDrawMapBG(theDrawMapBG);
|
|
|
|
// Clear then load sound names
|
|
int theSoundNameListSize;
|
|
LOAD_DATA(theSoundNameListSize);
|
|
this->mSoundNameList.clear();
|
|
|
|
for(int i = 0; i < theSoundNameListSize; i++)
|
|
{
|
|
string theCurrentSoundName;
|
|
LoadStringData(theCurrentSoundName, inBuffer, theBytesRead);
|
|
this->mSoundNameList.push_back(theCurrentSoundName);
|
|
}
|
|
|
|
ASSERT((theBytesRead + (int)sizeof(int)) == inSize);
|
|
|
|
return theBytesRead;
|
|
}
|
|
|
|
// Write out base HUD data to stream
|
|
void AvHHud::InitializeDemoRecording()
|
|
{
|
|
// Figure out total size of buffer needed
|
|
|
|
// Write number of upgrades, then each upgrade
|
|
// No longer done, but need to add in upgrades for backwards compatibility
|
|
int theUpgrades = 0;
|
|
int theUpgradesSize = sizeof(theUpgrades);
|
|
|
|
// Gamma, resources
|
|
int theGammaSize = sizeof(this->mDesiredGammaSlope);
|
|
int theResourcesSizes = sizeof(this->mResources);
|
|
|
|
// Save commander index (TODO: REMOVE)
|
|
int theCommanderIndex = this->GetCommanderIndex();
|
|
int theCommanderSize = sizeof(theCommanderIndex);
|
|
|
|
int theNumHiveInfoRecords = (int)this->mHiveInfoList.size();
|
|
int theHiveInfoSize = sizeof(int) + theNumHiveInfoRecords*sizeof(AvHHiveInfo);
|
|
|
|
string thePieMenuControl = gPieMenuHandler.GetPieMenuControl();
|
|
int theCurrentPieMenuControlSize = sizeof(int) + (int)thePieMenuControl.size();
|
|
|
|
int theSelectedSize = sizeof(int) + (int)this->mSelected.size()*sizeof(EntityInfo);
|
|
|
|
int theTotalSize = theUpgradesSize + theGammaSize + theResourcesSizes + theCommanderSize + theHiveInfoSize + theCurrentPieMenuControlSize + theSelectedSize;
|
|
|
|
// New a char array of this size
|
|
int theCounter = 0;
|
|
|
|
unsigned char* theCharArray = new unsigned char[theTotalSize];
|
|
if(theCharArray)
|
|
{
|
|
// Write out number of upgrades (for backwards-compatibility)
|
|
int theNumUpgradeCosts = 0;
|
|
SaveData(theCharArray, &theNumUpgradeCosts, sizeof(theNumUpgradeCosts), theCounter);
|
|
|
|
// Write out gamma
|
|
SaveData(theCharArray, &this->mDesiredGammaSlope, theGammaSize, theCounter);
|
|
SaveData(theCharArray, &this->mResources, theResourcesSizes, theCounter);
|
|
SaveData(theCharArray, &theCommanderIndex, theCommanderSize, theCounter);
|
|
|
|
// Write out num hive info records
|
|
SaveData(theCharArray, &theNumHiveInfoRecords, sizeof(int), theCounter);
|
|
for(HiveInfoListType::iterator theHiveInfoIter = this->mHiveInfoList.begin(); theHiveInfoIter != this->mHiveInfoList.end(); theHiveInfoIter++)
|
|
{
|
|
SaveData(theCharArray, &(*theHiveInfoIter), sizeof(AvHHiveInfo), theCounter);
|
|
}
|
|
|
|
// Save length of pie menu control name
|
|
int thePieMenuControlNameLength = (int)thePieMenuControl.size();
|
|
SaveData(theCharArray, &thePieMenuControlNameLength, sizeof(int), theCounter);
|
|
SaveData(theCharArray, thePieMenuControl.c_str(), thePieMenuControlNameLength, theCounter);
|
|
|
|
// Save out size of selected
|
|
int theNumSelected = (int)this->mSelected.size();
|
|
SaveData(theCharArray, &theNumSelected, sizeof(theNumSelected), theCounter);
|
|
|
|
for(EntityListType::const_iterator theSelectedIter = this->mSelected.begin(); theSelectedIter != this->mSelected.end(); theSelectedIter++)
|
|
{
|
|
EntityInfo theCurrentInfo = *theSelectedIter;
|
|
SaveData(theCharArray, &theCurrentInfo, sizeof(EntityInfo), theCounter);
|
|
}
|
|
|
|
ASSERT(theCounter == theTotalSize);
|
|
|
|
// Write it out
|
|
Demo_WriteBuffer(TYPE_BASESTATE, theTotalSize, theCharArray);
|
|
|
|
// Delete char array
|
|
delete [] theCharArray;
|
|
theCharArray = NULL;
|
|
|
|
// Save out particle templates
|
|
gParticleTemplateList.InitializeDemoRecording();
|
|
}
|
|
|
|
theTotalSize = theCounter = 0;
|
|
theTotalSize += sizeof(this->mTimeOfLastUpdate);
|
|
theTotalSize += sizeof(this->mTimeOfNextHudSound);
|
|
theTotalSize += sizeof(this->mTimeOfCurrentUpdate);
|
|
theTotalSize += sizeof(this->mCountDownClock);
|
|
theTotalSize += sizeof(this->mLastTickPlayed);
|
|
theTotalSize += sizeof(this->mNumTicksToPlay);
|
|
theTotalSize += GetDataSize(this->mMapName);
|
|
theTotalSize += sizeof(this->mMapExtents.GetMinViewHeight());
|
|
theTotalSize += sizeof(this->mMapExtents.GetMaxViewHeight());
|
|
theTotalSize += sizeof(this->mMapExtents.GetMinMapX());
|
|
theTotalSize += sizeof(this->mMapExtents.GetMaxMapX());
|
|
theTotalSize += sizeof(this->mMapExtents.GetMinMapY());
|
|
theTotalSize += sizeof(this->mMapExtents.GetMaxMapY());
|
|
theTotalSize += sizeof(this->mMapExtents.GetDrawMapBG());
|
|
|
|
// Save sound names
|
|
int theSoundNameListSize = (int)this->mSoundNameList.size();
|
|
theTotalSize += sizeof(theSoundNameListSize);
|
|
|
|
for(int i = 0; i < theSoundNameListSize; i++)
|
|
{
|
|
string theCurrentSoundName = this->mSoundNameList[i];
|
|
theTotalSize += GetDataSize(theCurrentSoundName);
|
|
}
|
|
|
|
theCharArray = new unsigned char[theTotalSize];
|
|
if(theCharArray)
|
|
{
|
|
SAVE_DATA(this->mTimeOfLastUpdate);
|
|
SAVE_DATA(this->mTimeOfNextHudSound);
|
|
SAVE_DATA(this->mTimeOfCurrentUpdate);
|
|
SAVE_DATA(this->mCountDownClock);
|
|
SAVE_DATA(this->mLastTickPlayed);
|
|
SAVE_DATA(this->mNumTicksToPlay);
|
|
SaveStringData(theCharArray, this->mMapName, theCounter);
|
|
|
|
float theMinViewHeight = this->mMapExtents.GetMinViewHeight();
|
|
SAVE_DATA(theMinViewHeight);
|
|
float theMaxViewHeight = this->mMapExtents.GetMaxViewHeight();
|
|
SAVE_DATA(theMaxViewHeight);
|
|
float theMinMapX = this->mMapExtents.GetMinMapX();
|
|
SAVE_DATA(theMinMapX);
|
|
float theMaxMapX = this->mMapExtents.GetMaxMapX();
|
|
SAVE_DATA(theMaxMapX);
|
|
float theMinMapY = this->mMapExtents.GetMinMapY();
|
|
SAVE_DATA(theMinMapY);
|
|
float theMaxMapY = this->mMapExtents.GetMaxMapY();
|
|
SAVE_DATA(theMaxMapY);
|
|
bool theDrawMapBG = this->mMapExtents.GetDrawMapBG();
|
|
SAVE_DATA(theDrawMapBG);
|
|
|
|
SAVE_DATA(theSoundNameListSize);
|
|
for(int i = 0; i < theSoundNameListSize; i++)
|
|
{
|
|
string theCurrentSoundName = this->mSoundNameList[i];
|
|
SaveStringData(theCharArray, theCurrentSoundName, theCounter);
|
|
}
|
|
|
|
// TODO: Save out locations?
|
|
|
|
ASSERT(theCounter == theTotalSize);
|
|
|
|
// Write out TYPE_BASESTATE2 chunk separately for backwards-compatibility
|
|
Demo_WriteBuffer(TYPE_BASESTATE2, theTotalSize, theCharArray);
|
|
|
|
delete [] theCharArray;
|
|
theCharArray = NULL;
|
|
}
|
|
|
|
ScorePanel_InitializeDemoRecording();
|
|
|
|
// Write out weapon info
|
|
for(i = 0; i < MAX_WEAPONS; i++)
|
|
{
|
|
WEAPON* theWeapon = gWR.GetWeapon(i);
|
|
if( theWeapon )
|
|
{
|
|
theTotalSize = sizeof(theWeapon->szName) + sizeof(theWeapon->iAmmoType) + sizeof(theWeapon->iAmmo2Type) + sizeof(theWeapon->iMax1) + sizeof(theWeapon->iMax2) + sizeof(theWeapon->iSlot) + sizeof(theWeapon->iSlotPos) + sizeof(theWeapon->iFlags) + sizeof(theWeapon->iId) + sizeof(theWeapon->iClip) + sizeof(theWeapon->iCount);// + sizeof(int); // last one is for ammo
|
|
theCharArray = new unsigned char[theTotalSize];
|
|
|
|
int theWeaponCoreDataLength = theTotalSize;// - sizeof(int);
|
|
memcpy(theCharArray, theWeapon, theWeaponCoreDataLength); // Everything but ammo
|
|
//int theAmmo = gWR.GetAmmo(theWeapon->iId);
|
|
//memcpy(theCharArray + theWeaponCoreDataLength, &theAmmo, sizeof(int));
|
|
|
|
Demo_WriteBuffer(TYPE_WEAPONINFO, theTotalSize, (unsigned char*)theWeapon);
|
|
|
|
delete [] theCharArray;
|
|
theCharArray = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
int AvHHud::InitializeWeaponInfoPlayback(int inSize, unsigned char* inBuffer)
|
|
{
|
|
// Make sure weapons are cleared out first
|
|
WEAPON theWeapon;
|
|
memset(&theWeapon, 0, sizeof(theWeapon));
|
|
|
|
int theWeaponCoreDataLength = inSize;// - sizeof(int);
|
|
memcpy(&theWeapon, inBuffer, theWeaponCoreDataLength);
|
|
|
|
if(theWeapon.iId)
|
|
{
|
|
gWR.AddWeapon( &theWeapon );
|
|
//int theAmmo = 0;
|
|
//memcpy(&theAmmo, inBuffer + theWeaponCoreDataLength, sizeof(int));
|
|
//gWR.SetAmmo(theWeapon.iId, theAmmo);
|
|
}
|
|
|
|
return inSize;
|
|
}
|
|
|
|
void AvHHud::InitMenu(const string& inMenuName)
|
|
{
|
|
PieMenu* theMenu = NULL;
|
|
if(this->GetManager().GetVGUIComponentNamed(inMenuName, theMenu))
|
|
{
|
|
theMenu->AddInputSignalForNodes(&gPieMenuHandler);
|
|
//outMenu->DisableNodesGreaterThanCost(this->mResources);
|
|
this->GetManager().HideComponent(inMenuName);
|
|
}
|
|
}
|
|
|
|
void AvHHud::PostUIInit(void)
|
|
{
|
|
this->InitMenu(kSoldierMenu);
|
|
this->InitMenu(kSoldierCombatMenu);
|
|
this->InitMenu(kAlienMenu);
|
|
this->InitMenu(kAlienCombatMenu);
|
|
|
|
this->InitCommanderMode();
|
|
|
|
this->GetManager().GetVGUIComponentNamed(kCommanderResourceLabel, this->mCommanderResourceLabel);
|
|
this->GetManager().GetVGUIComponentNamed(kGenericProgress, this->mGenericProgressBar);
|
|
this->GetManager().GetVGUIComponentNamed(kResearchProgress, this->mResearchProgressBar);
|
|
this->GetManager().GetVGUIComponentNamed(kAlienProgress, this->mAlienProgressBar);
|
|
this->GetManager().GetVGUIComponentNamed(kSelectionBox, this->mSelectionBox);
|
|
this->GetManager().GetVGUIComponentNamed(kResearchingLabel, this->mResearchLabel);
|
|
|
|
// Init particle editor
|
|
gParticleEditorHandler.Setup();
|
|
|
|
if(this->GetManager().GetVGUIComponentNamed(kHierarchy, this->mHierarchy))
|
|
{
|
|
this->mHierarchy->setEnabled(false);
|
|
}
|
|
if(this->GetManager().GetVGUIComponentNamed(kShowMapHierarchy, this->mShowMapHierarchy))
|
|
{
|
|
this->mShowMapHierarchy->setEnabled(false);
|
|
}
|
|
|
|
// Don't turn on gamma by default, it is annoying for testing
|
|
//this->SetGamma();
|
|
}
|
|
|
|
AvHMessageID AvHHud::GetGhostBuilding() const
|
|
{
|
|
return this->mGhostBuilding;
|
|
}
|
|
|
|
void AvHHud::SetGhostBuildingMode(AvHMessageID inGhostBuilding)
|
|
{
|
|
this->mGhostBuilding = inGhostBuilding;
|
|
this->mCreatedGhost = false;
|
|
}
|
|
|
|
void AvHHud::SetClientDebugCSP(weapon_data_t* inWeaponData, float inNextPlayerAttack)
|
|
{
|
|
char theClientInfoString[512];
|
|
sprintf(theClientInfoString, "Client: id: %d, clip: %d, prim attack: %f, idle: %f, next attack: %f", inWeaponData->m_iId, inWeaponData->m_iClip, inWeaponData->m_flNextPrimaryAttack, inWeaponData->m_flTimeWeaponIdle, inNextPlayerAttack);
|
|
|
|
vgui::Label* theLabel = NULL;
|
|
if(this->GetManager().GetVGUIComponentNamed(kDebugCSPClientLabel, theLabel))
|
|
{
|
|
theLabel->setText(theClientInfoString);
|
|
}
|
|
}
|
|
|
|
void AvHHud::SetCurrentWeaponData(int inCurrentWeaponID, bool inEnabled)
|
|
{
|
|
this->mCurrentWeaponID = inCurrentWeaponID;
|
|
this->mCurrentWeaponEnabled = inEnabled;
|
|
}
|
|
|
|
int AvHHud::GetCurrentWeaponID(void)
|
|
{
|
|
return this->mCurrentWeaponID;
|
|
}
|
|
|
|
void AvHHud::SetAlienAbility(AvHMessageID inAlienAbility)
|
|
{
|
|
this->mAlienAbility = inAlienAbility;
|
|
}
|
|
|
|
void AvHHud::SetProgressStatus(float inPercentage)
|
|
{
|
|
if(this->mGenericProgressBar)
|
|
{
|
|
this->mGenericProgressBar->setVisible(false);
|
|
}
|
|
|
|
if(this->mAlienProgressBar)
|
|
{
|
|
this->mAlienProgressBar->setVisible(false);
|
|
}
|
|
|
|
ProgressBar* theProgressBar = this->mGenericProgressBar;
|
|
if(this->GetIsAlien())
|
|
{
|
|
theProgressBar = this->mAlienProgressBar;
|
|
}
|
|
|
|
if(theProgressBar)
|
|
{
|
|
theProgressBar->setVisible(true);
|
|
|
|
int theNumSegments = theProgressBar->getSegmentCount();
|
|
int theSegment = inPercentage*theNumSegments;
|
|
theProgressBar->setProgress(theSegment);
|
|
}
|
|
}
|
|
|
|
void AvHHud::SetReinforcements(int inReinforcements)
|
|
{
|
|
Label* theLabel = NULL;
|
|
if(this->GetManager().GetVGUIComponentNamed(kReinforcementsLabel, theLabel))
|
|
{
|
|
string thePrefix;
|
|
if(LocalizeString(kReinforcementsText, thePrefix))
|
|
{
|
|
string theText = thePrefix + string(" ") + MakeStringFromInt(inReinforcements);
|
|
theLabel->setText(theText.c_str());
|
|
}
|
|
}
|
|
}
|
|
|
|
void AvHHud::SetResearchProgressStatus(float inPercentage)
|
|
{
|
|
if(this->mResearchProgressBar)
|
|
{
|
|
this->mResearchProgressBar->setVisible(true);
|
|
|
|
int theNumSegments = this->mResearchProgressBar->getSegmentCount();
|
|
int theSegment = inPercentage*theNumSegments;
|
|
this->mResearchProgressBar->setProgress(theSegment);
|
|
|
|
this->mResearchLabel->setVisible(true);
|
|
|
|
// Center research label
|
|
int theX, theY;
|
|
this->mResearchLabel->getPos(theX, theY);
|
|
int theTextWidth, theTextHeight;
|
|
this->mResearchLabel->getTextSize(theTextWidth, theTextHeight);
|
|
this->mResearchLabel->setPos(ScreenWidth()/2 - theTextWidth/2, theY);
|
|
}
|
|
}
|
|
|
|
void AvHHud::UpdateDemoRecordPlayback()
|
|
{
|
|
// If the mouse is visible, allow it to work with demos
|
|
if(gEngfuncs.pDemoAPI->IsRecording())
|
|
{
|
|
// Write out first frame if needed
|
|
if(!this->mRecordingLastFrame)
|
|
{
|
|
this->InitializeDemoRecording();
|
|
this->mRecordingLastFrame = true;
|
|
}
|
|
|
|
// Write view origin (and angles?)
|
|
//Demo_WriteVector(TYPE_VIEWANGLES, v_angles);
|
|
//Demo_WriteVector(TYPE_VIEWORIGIN, v_origin);
|
|
// Demo_WriteByte(TYPE_MOUSEVIS, g_iVisibleMouse);
|
|
//
|
|
// if(g_iVisibleMouse)
|
|
// {
|
|
// int theMouseScreenX, theMouseScreenY;
|
|
//
|
|
// IN_GetMousePos(&theMouseScreenX, &theMouseScreenY);
|
|
//
|
|
// //theMouseScreenX += ScreenWidth/2;
|
|
// //theMouseScreenY += ScreenHeight/2;
|
|
//
|
|
// // Write mouse position
|
|
// float theNormX = (float)theMouseScreenX/ScreenWidth;
|
|
// float theNormY = (float)theMouseScreenY/ScreenHeight;
|
|
//
|
|
// Demo_WriteFloat(TYPE_MOUSEX, theNormX);
|
|
// Demo_WriteFloat(TYPE_MOUSEY, theNormY);
|
|
//
|
|
// //char theBuffer[256];
|
|
// //sprintf(theBuffer, "Saving mouse coords %f %f\n", theNormX, theNormY);
|
|
// //CenterPrint(theBuffer);
|
|
// }
|
|
}
|
|
else if(gEngfuncs.pDemoAPI->IsPlayingback())
|
|
{
|
|
//char theBuffer[256];
|
|
//sprintf(theBuffer, "Restoring mouse coords %f %f\n", gNormMouseX, gNormMouseY);
|
|
//CenterPrint(theBuffer);
|
|
|
|
//int theCurrentMouseX = gNormMouseX*ScreenWidth;
|
|
//int theCurrentMouseY = gNormMouseY*ScreenHeight;
|
|
//
|
|
////App::getInstance()->setCursorPos(theCurrentMouseX, theCurrentMouseY);
|
|
//
|
|
//SetCursorPos(theCurrentMouseX, theCurrentMouseY);
|
|
//
|
|
//this->mMouseCursorX = theCurrentMouseX;
|
|
//this->mMouseCursorY = theCurrentMouseY;
|
|
|
|
this->mRecordingLastFrame = false;
|
|
}
|
|
else
|
|
{
|
|
this->mRecordingLastFrame = false;
|
|
}
|
|
}
|
|
|
|
void AvHHud::UpdateDataFromVuser4(float inCurrentTime)
|
|
{
|
|
cl_entity_s* theLocalPlayer = gEngfuncs.GetLocalPlayer();
|
|
if(theLocalPlayer)
|
|
{
|
|
// Fetch data from vuser4
|
|
vec3_t theVUser = theLocalPlayer->curstate.vuser4;
|
|
|
|
//int theVUserVar0 = 0;
|
|
//int theVUserVar1 = 0;
|
|
//int theVUserVar2 = 0;
|
|
//
|
|
//memcpy(&theVUserVar0, (int*)(&theVUser.x), 4);
|
|
//memcpy(&theVUserVar1, (int*)(&theVUser.y), 4);
|
|
//memcpy(&theVUserVar2, (int*)(&theVUser.z), 4);
|
|
|
|
// Fetch new resource level
|
|
//theVUserVar2;// & 0x0000FFFF;
|
|
|
|
if(this->GetIsCombatMode())
|
|
{
|
|
this->mExperience = (int)ceil(theVUser.z/kNumericNetworkConstant);
|
|
this->mExperienceLevel = AvHPlayerUpgrade::GetPlayerLevel(this->mExperience);
|
|
|
|
const float kShowMenuInterval = 5.0f;
|
|
|
|
// If we are at a level greater then we've drawn, set visible again to reparse
|
|
if(this->mExperienceLevel > this->mExperienceLevelLastDrawn)
|
|
{
|
|
this->DisplayCombatUpgradeMenu(true);
|
|
this->mTimeOfLastLevelUp = inCurrentTime;
|
|
this->mExperienceLevelLastDrawn = this->mExperienceLevel;
|
|
}
|
|
// else if we have no more levels to spend or if we've been displaying it longer then the time out (+1 because we start at level 1)
|
|
else if((this->mExperienceLevel == (this->mExperienceLevelSpent + 1)) || (inCurrentTime > (this->mTimeOfLastLevelUp + kShowMenuInterval)))
|
|
{
|
|
// stop displaying it
|
|
this->DisplayCombatUpgradeMenu(false);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
int theNewValue = (int)ceil(theVUser.z/kNumericNetworkConstant);
|
|
|
|
if(theNewValue != this->mResources)
|
|
{
|
|
this->mResources = theNewValue;
|
|
}
|
|
|
|
// Don't smooth resources nicely when switching targets
|
|
if((g_iUser1 == OBS_IN_EYE) && (g_iUser2 != this->mUser2OfLastResourceMessage))
|
|
{
|
|
this->mVisualResources = this->mResources;
|
|
}
|
|
}
|
|
this->mUser2OfLastResourceMessage = g_iUser2;
|
|
}
|
|
}
|
|
|
|
void AvHHud::UpdateSpectating()
|
|
{
|
|
// If we're spectating and the team of our target switched, delete all blips
|
|
if((this->GetPlayMode() == PLAYMODE_AWAITINGREINFORCEMENT) || (this->GetPlayMode() == PLAYMODE_OBSERVER))
|
|
{
|
|
AvHTeamNumber theCurrentTargetTeam = TEAM_IND;
|
|
|
|
int theCurrentTarget = g_iUser2;//thePlayer->curstate.iuser2;
|
|
cl_entity_s* theEntity = gEngfuncs.GetEntityByIndex(theCurrentTarget);
|
|
if(theEntity)
|
|
{
|
|
theCurrentTargetTeam = AvHTeamNumber(theEntity->curstate.team);
|
|
}
|
|
|
|
if((theCurrentTargetTeam != this->mLastTeamSpectated) && (theCurrentTargetTeam != TEAM_IND))
|
|
{
|
|
this->mEnemyBlips.Clear();
|
|
this->mFriendlyBlips.Clear();
|
|
this->mLastTeamSpectated = theCurrentTargetTeam;
|
|
//CenterPrint("Clearing blips.");
|
|
}
|
|
}
|
|
}
|
|
|
|
void AvHHud::UpdateCommonUI()
|
|
{
|
|
// Find currently selected node and draw help text if it's been open for a little bit
|
|
PieMenu* thePieMenu = NULL;
|
|
AvHMessageID theCurrentNodeID = MESSAGE_NULL;
|
|
|
|
this->mSelectingNodeID = MESSAGE_NULL;
|
|
|
|
if(this->GetManager().GetVGUIComponentNamed(this->mPieMenuControl, thePieMenu))
|
|
{
|
|
// tankefugl: Added check to ensure that it is only updated when a menu is visible
|
|
if (thePieMenu->getChildCount() > 0)
|
|
{
|
|
vgui::Panel *rootMenu = thePieMenu->getChild(0);
|
|
if (rootMenu && rootMenu->isVisible())
|
|
{
|
|
this->UpdateUpgradeCosts();
|
|
}
|
|
}
|
|
|
|
PieNode* theCurrentNode = NULL;
|
|
if(thePieMenu && thePieMenu->GetSelectedNode(theCurrentNode))
|
|
{
|
|
theCurrentNodeID = (AvHMessageID)theCurrentNode->GetMessageID();
|
|
|
|
if(theCurrentNodeID > 0)
|
|
{
|
|
this->mSelectingNodeID = theCurrentNodeID;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Clear squad on team change
|
|
if(!this->GetIsMarine())
|
|
{
|
|
this->mCurrentSquad = 0;
|
|
}
|
|
}
|
|
|
|
#define FORCE_CVAR(a,b) if(a)a->value = b;
|
|
|
|
void AvHHud::UpdateExploitPrevention()
|
|
{
|
|
//Note: Sometimes some clients will not have these cvars, so be sure to check that they are not null.
|
|
FORCE_CVAR(gl_monolights, 0.0f);
|
|
FORCE_CVAR(gl_overbright, 0.0f);
|
|
FORCE_CVAR(gl_clear, 0.0f);
|
|
FORCE_CVAR(hud_draw, 1.0f);
|
|
FORCE_CVAR(r_drawviewmodel, 1.0f);
|
|
FORCE_CVAR(cl_movespeedkey, AvHMUGetWalkSpeedFactor(this->GetHUDUser3()));
|
|
FORCE_CVAR(gl_d3dflip, 1.0f);
|
|
FORCE_CVAR(s_show, 0.0f);
|
|
FORCE_CVAR(r_detailtextures, 0.0f);
|
|
FORCE_CVAR(gl_max_size, 256.0f);
|
|
|
|
if(lightgamma && lightgamma->value < 2.0)
|
|
lightgamma->value = 2.0f;
|
|
}
|
|
|
|
void AvHHud::UpdateAlienUI(float inCurrentTime)
|
|
{
|
|
// Always hide it by default
|
|
this->GetManager().HideComponent(kPieHelpText);
|
|
|
|
if(this->GetIsAlien() && this->GetIsAlive())
|
|
{
|
|
float theTimePassed = inCurrentTime - this->mTimeOfLastUpdate;
|
|
// int theNumFrames = SPR_Frames(this->mAlienUIHiveSprite);
|
|
//
|
|
// for(AnimatedSpriteListType::iterator theIter = this->mAlienUIHiveList.begin(); theIter != this->mAlienUIHiveList.end(); theIter++)
|
|
// {
|
|
// const float kAnimationSpeed = 16.0f;
|
|
//
|
|
// float theCurrentFrame = theIter->mCurrentFrame + theTimePassed*kAnimationSpeed;
|
|
// if(theCurrentFrame >= theNumFrames)
|
|
// {
|
|
// theCurrentFrame -= theNumFrames;
|
|
// }
|
|
// theIter->mCurrentFrame = theCurrentFrame;
|
|
// }
|
|
|
|
// Check to see if we have any unspent upgrades. If so, change the pie menu and HUD state to reflect this
|
|
this->mNumUpgradesAvailable = 0;
|
|
for(int i = 0; i < ALIEN_UPGRADE_CATEGORY_MAX_PLUS_ONE; i++)
|
|
{
|
|
this->mCurrentUpgradeCategory[i] = ALIEN_UPGRADE_CATEGORY_INVALID;
|
|
}
|
|
|
|
int theUpgradeVar = this->GetLocalUpgrades();
|
|
|
|
if(AvHGetHasUpgradeChoiceInCategory(ALIEN_UPGRADE_CATEGORY_SENSORY, this->mUpgrades, theUpgradeVar))
|
|
{
|
|
this->mCurrentUpgradeCategory[this->mNumUpgradesAvailable] = ALIEN_UPGRADE_CATEGORY_SENSORY;
|
|
this->mNumUpgradesAvailable += 1;
|
|
}
|
|
if(AvHGetHasUpgradeChoiceInCategory(ALIEN_UPGRADE_CATEGORY_MOVEMENT, this->mUpgrades, theUpgradeVar))
|
|
{
|
|
this->mCurrentUpgradeCategory[this->mNumUpgradesAvailable] = ALIEN_UPGRADE_CATEGORY_MOVEMENT;
|
|
this->mNumUpgradesAvailable += 1;
|
|
}
|
|
if(AvHGetHasUpgradeChoiceInCategory(ALIEN_UPGRADE_CATEGORY_OFFENSE, this->mUpgrades, theUpgradeVar))
|
|
{
|
|
this->mCurrentUpgradeCategory[this->mNumUpgradesAvailable] = ALIEN_UPGRADE_CATEGORY_OFFENSE;
|
|
this->mNumUpgradesAvailable += 1;
|
|
}
|
|
if(AvHGetHasUpgradeChoiceInCategory(ALIEN_UPGRADE_CATEGORY_DEFENSE, this->mUpgrades, theUpgradeVar))
|
|
{
|
|
this->mCurrentUpgradeCategory[this->mNumUpgradesAvailable] = ALIEN_UPGRADE_CATEGORY_DEFENSE;
|
|
this->mNumUpgradesAvailable += 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
bool AvHHud::GetCommanderLabelText(std::string& outCommanderName) const
|
|
{
|
|
|
|
int theCommander = this->GetCommanderIndex();
|
|
bool theHasCommander = (theCommander > 0) && (theCommander <= gEngfuncs.GetMaxClients());
|
|
|
|
if(!theHasCommander)
|
|
{
|
|
LocalizeString(kNoCommander, outCommanderName);
|
|
return false; // No commander
|
|
}
|
|
else
|
|
{
|
|
|
|
std::stringstream theStream;
|
|
|
|
string theCommanderText;
|
|
LocalizeString(kCommander, theCommanderText);
|
|
|
|
theStream << theCommanderText;
|
|
theStream << ": ";
|
|
|
|
hud_player_info_t thePlayerInfo;
|
|
gEngfuncs.pfnGetPlayerInfo(theCommander, &thePlayerInfo);
|
|
|
|
if(thePlayerInfo.name)
|
|
{
|
|
const int kMaxCommNameLen = 8;
|
|
theStream << string(thePlayerInfo.name).substr(0, kMaxCommNameLen);
|
|
}
|
|
|
|
outCommanderName = theStream.str();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void AvHHud::UpdateMarineUI(float inCurrentTime)
|
|
{
|
|
// Find commander label
|
|
Label* theCommanderStatusLabel = NULL;
|
|
|
|
|
|
if(this->mMapMode == MAP_MODE_NS)
|
|
{
|
|
|
|
// Add handler for all pending request buttons (this does hotgroups too)
|
|
for(int i = 0; i < MESSAGE_LAST; i++)
|
|
{
|
|
AvHMessageID theMessageID = AvHMessageID(i);
|
|
|
|
char theComponentName[256];
|
|
sprintf(theComponentName, kPendingImpulseSpecifier, (int)theMessageID);
|
|
|
|
AvHTechImpulsePanel* theTechImpulsePanel = NULL;
|
|
if(this->GetManager().GetVGUIComponentNamed(theComponentName, theTechImpulsePanel))
|
|
{
|
|
bool theVisibility = false;
|
|
|
|
// Do we have any requests pending?
|
|
if(this->GetIsInTopDownMode())
|
|
{
|
|
PendingRequestListType::iterator theIterator;
|
|
for(theIterator = this->mPendingRequests.begin(); theIterator != this->mPendingRequests.end(); theIterator++)
|
|
{
|
|
if(theIterator->first == theMessageID)
|
|
{
|
|
if(theIterator->second > 0)
|
|
{
|
|
theVisibility = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
switch(theMessageID)
|
|
{
|
|
case GROUP_SELECT_1:
|
|
case GROUP_SELECT_2:
|
|
case GROUP_SELECT_3:
|
|
case GROUP_SELECT_4:
|
|
case GROUP_SELECT_5:
|
|
case COMMANDER_SELECTALL:
|
|
theVisibility = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
theTechImpulsePanel->setVisible(theVisibility);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void AvHHud::UpdateCountdown(float inCurrentTime)
|
|
{
|
|
if(this->mCountDownClock != -1)
|
|
{
|
|
if(inCurrentTime - this->mCountDownClock > this->mLastTickPlayed)
|
|
{
|
|
// Play tick
|
|
this->PlayHUDSound(HUD_SOUND_COUNTDOWN);
|
|
this->mLastTickPlayed++;
|
|
}
|
|
|
|
if(this->mLastTickPlayed > this->mNumTicksToPlay)
|
|
{
|
|
this->AddTooltip(kGameBegun, false);
|
|
this->mCountDownClock = -1;
|
|
}
|
|
}
|
|
}
|
|
|
|
void AvHHud::UpdateHierarchy()
|
|
{
|
|
|
|
// Start the starting point on the map to our local position
|
|
this->mOverviewMap.SetMapExtents(this->GetMapName(), this->mMapExtents);
|
|
this->mOverviewMap.SetWorldPosition(gPredictedPlayerOrigin[0], gPredictedPlayerOrigin[1]);
|
|
|
|
if(this->mHierarchy)
|
|
{
|
|
this->mHierarchy->SetFullScreen(this->GetHUDUser3() == AVH_USER3_COMMANDER_PLAYER);
|
|
}
|
|
if(this->mShowMapHierarchy)
|
|
{
|
|
this->mShowMapHierarchy->SetFullScreen(true);
|
|
}
|
|
|
|
}
|
|
|
|
string AvHHud::GetNameOfLocation(vec3_t inLocation) const
|
|
{
|
|
string theLocationName;
|
|
|
|
AvHSHUGetNameOfLocation(this->mInfoLocationList, inLocation, theLocationName);
|
|
|
|
return theLocationName;
|
|
}
|
|
|
|
|
|
void AvHHud::UpdateInfoLocation()
|
|
{
|
|
if(this->GetIsAlive() && this->GetHUDUser3() != AVH_USER3_ALIEN_EMBRYO)
|
|
{
|
|
// Don't clear our location, disconcerting to see our location disappear
|
|
//this->mLocationText = "";
|
|
|
|
this->mLocationText = this->GetNameOfLocation(gPredictedPlayerOrigin);
|
|
}
|
|
else
|
|
{
|
|
this->mLocationText = "";
|
|
}
|
|
}
|
|
|
|
bool AvHHud::GetIsCombatMode() const
|
|
{
|
|
return (this->mMapMode == MAP_MODE_CO);
|
|
}
|
|
|
|
bool AvHHud::GetIsNSMode() const
|
|
{
|
|
return (this->mMapMode == MAP_MODE_NS);
|
|
}
|
|
|
|
bool AvHHud::GetIsMouseInRegion(int inX, int inY, int inWidth, int inHeight)
|
|
{
|
|
bool theMouseIsInRegion = false;
|
|
|
|
if(this->GetInTopDownMode())
|
|
{
|
|
int theMouseX, theMouseY;
|
|
this->GetMousePos(theMouseX, theMouseY);
|
|
|
|
if((theMouseX >= inX) && (theMouseX <= (inX + inWidth)))
|
|
{
|
|
if((theMouseY >= inY) && (theMouseY <= (inY + inHeight)))
|
|
{
|
|
theMouseIsInRegion = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return theMouseIsInRegion;
|
|
}
|
|
|
|
void AvHHud::TraceEntityID(int& outEntityID)
|
|
{
|
|
pmtrace_t tr;
|
|
vec3_t up, right, forward;
|
|
|
|
// Trace forward to see if we see a player
|
|
gEngfuncs.pEventAPI->EV_PushPMStates();
|
|
|
|
// Now add in all of the players.
|
|
gEngfuncs.pEventAPI->EV_SetSolidPlayers (-1);
|
|
|
|
gEngfuncs.pEventAPI->EV_SetTraceHull(2);
|
|
|
|
cl_entity_s* theLocalPlayer = gEngfuncs.GetLocalPlayer();
|
|
int theLocalPlayerIndex = theLocalPlayer->index;
|
|
//AngleVectors(theLocalPlayer->curstate.angles, forward, right, up);
|
|
|
|
pVector theRealView;
|
|
gEngfuncs.pfnAngleVectors(pmove->angles, forward, right, up);
|
|
|
|
Vector theStartTrace;
|
|
//VectorMA(gPredictedPlayerOrigin, kMaxPlayerHullWidth, forward, theStartTrace);
|
|
VectorCopy(gPredictedPlayerOrigin, theStartTrace);
|
|
|
|
Vector theEndTrace;
|
|
VectorMA(gPredictedPlayerOrigin, 8192, forward, theEndTrace);
|
|
bool theDone = false;
|
|
|
|
do
|
|
{
|
|
gEngfuncs.pEventAPI->EV_PlayerTrace(theStartTrace, theEndTrace, PM_NORMAL, -1, &tr);
|
|
|
|
// Ignore local player, and ignore the player we're spectating
|
|
int theHit = gEngfuncs.pEventAPI->EV_IndexFromTrace(&tr);
|
|
if(theHit == theLocalPlayerIndex)
|
|
{
|
|
VectorMA(tr.endpos, kHitOffsetAmount, forward, theStartTrace);
|
|
}
|
|
// We hit something
|
|
else if(tr.fraction < 1.0)
|
|
{
|
|
physent_t* pe = gEngfuncs.pEventAPI->EV_GetPhysent( tr.ent );
|
|
if(pe)
|
|
{
|
|
int thePotentialEntity = pe->info;
|
|
//if((thePotentialEntity >= 1) && (thePotentialEntity < gEngfuncs.GetMaxClients()))
|
|
//{
|
|
outEntityID = pe->info;
|
|
//}
|
|
}
|
|
theDone = true;
|
|
}
|
|
} while(!theDone);
|
|
|
|
gEngfuncs.pEventAPI->EV_PopPMStates();
|
|
}
|
|
|
|
bool AvHHud::GetAlienHelpForMessage(int inMessageID, string& outHelpText, int& outPointCost) const
|
|
{
|
|
bool theSuccess = false;
|
|
|
|
char theNumber[8];
|
|
sprintf(theNumber, "%d", inMessageID);
|
|
string theNumberString(theNumber);
|
|
|
|
string theTechHelpText;
|
|
string theKey = string(kTechNodeHelpPrefix) + theNumberString;
|
|
if(LocalizeString(theKey.c_str(), theTechHelpText))
|
|
{
|
|
string thePointString;
|
|
if(LocalizeString(kPointsSuffix, thePointString))
|
|
{
|
|
/*
|
|
// Lookup point cost
|
|
for(UpgradeCostListType::const_iterator theIter = this->mPersonalUpgradeCosts.begin(); theIter != this->mPersonalUpgradeCosts.end(); theIter++)
|
|
{
|
|
if(theIter->first == inMessageID)
|
|
{
|
|
char theCostSuffix[128];
|
|
sprintf(theCostSuffix, " (%d %s)", theIter->second, thePointString.c_str());
|
|
outPointCost = theIter->second;
|
|
theTechHelpText += string(theCostSuffix);
|
|
outHelpText = theTechHelpText;
|
|
theSuccess = true;
|
|
break;
|
|
}
|
|
}
|
|
*/
|
|
}
|
|
}
|
|
return theSuccess;
|
|
}
|
|
|
|
bool AvHHud::GetDoesPlayerHaveOrder() const
|
|
{
|
|
bool thePlayerHasOrder = false;
|
|
|
|
for(OrderListType::const_iterator theIter = this->mOrders.begin(); theIter != this->mOrders.end(); theIter++)
|
|
{
|
|
// Draw the order if the order is for any plays that are in our draw player list
|
|
EntityInfo theReceiverPlayer = theIter->GetReceiver();
|
|
|
|
cl_entity_s* thePlayer = gEngfuncs.GetLocalPlayer();
|
|
if(thePlayer)
|
|
{
|
|
int thePlayerIndex = thePlayer->index;
|
|
if (thePlayerIndex == theReceiverPlayer )
|
|
{
|
|
thePlayerHasOrder = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return thePlayerHasOrder;
|
|
}
|
|
|
|
|
|
bool AvHHud::GetHelpForMessage(int inMessageID, string& outHelpText) const
|
|
{
|
|
bool theSuccess = false;
|
|
|
|
char theNumber[8];
|
|
sprintf(theNumber, "%d", (int)inMessageID);
|
|
string theNumberString(theNumber);
|
|
|
|
string theKey = string(kTechNodeLabelPrefix) + theNumberString;
|
|
string theTechNodeLabel;
|
|
if(LocalizeString(theKey.c_str(), theTechNodeLabel))
|
|
{
|
|
theKey = string(kTechNodeHelpPrefix) + theNumberString;
|
|
string theTechNodeHelp;
|
|
if(LocalizeString(theKey.c_str(), theTechNodeHelp))
|
|
{
|
|
outHelpText = /*theTechNodeLabel + " " +*/ theTechNodeLabel;
|
|
theSuccess = true;
|
|
|
|
int theCost;
|
|
bool theResearchable;
|
|
float theTime;
|
|
this->mTechNodes.GetResearchInfo((AvHMessageID)(inMessageID), theResearchable, theCost, theTime);
|
|
|
|
// Add cost
|
|
if(theCost > 0)
|
|
{
|
|
string theCostString;
|
|
if(AvHSHUGetDoesTechCostEnergy((AvHMessageID)inMessageID))
|
|
{
|
|
LocalizeString(kEnergyPrefix, theCostString);
|
|
}
|
|
else
|
|
{
|
|
LocalizeString(kMessageButtonCost, theCostString);
|
|
}
|
|
|
|
outHelpText += " ";
|
|
outHelpText += theCostString;
|
|
outHelpText += " ";
|
|
outHelpText += MakeStringFromInt(theCost);
|
|
|
|
// Draw description below
|
|
//outHelpText += "\n";
|
|
//outHelpText += theTechNodeHelp;
|
|
}
|
|
}
|
|
}
|
|
|
|
return theSuccess;
|
|
}
|
|
|
|
void AvHHud::UpdateMusic(float inCurrentTime)
|
|
{
|
|
bool theMusicEnabled = false;
|
|
|
|
if(this->GetGameStarted())
|
|
{
|
|
// If we're entering play mode and music is enabled, allow playing of music
|
|
if(this->GetHUDPlayMode() != PLAYMODE_READYROOM && (cl_musicenabled->value == 1.0f) && (cl_musicvolume->value > 0))
|
|
{
|
|
theMusicEnabled = true;
|
|
}
|
|
}
|
|
|
|
this->SetMusicAllowed(theMusicEnabled);
|
|
|
|
UIHud::UpdateMusic(inCurrentTime);
|
|
}
|
|
|
|
void AvHHud::UpdatePieMenuControl()
|
|
{
|
|
// Set which pie menu to use ("" for none)
|
|
bool theScoreBoardIsOpen = false;
|
|
|
|
ScorePanel* theScoreBoard = gViewPort->GetScoreBoard();
|
|
if(theScoreBoard && theScoreBoard->isVisible())
|
|
{
|
|
theScoreBoardIsOpen = true;
|
|
}
|
|
|
|
if(theScoreBoardIsOpen)
|
|
{
|
|
AvHPieMenuHandler::SetPieMenuControl("");
|
|
}
|
|
else
|
|
{
|
|
AvHPieMenuHandler::SetPieMenuControl(this->mPieMenuControl);
|
|
}
|
|
|
|
// Clear all nodes in case VGUI didn't catch events (seems to happen with lag)
|
|
if(!gPieMenuHandler.GetIsPieMenuOpen())
|
|
{
|
|
PieMenu* theCurrentPieMenu = gPieMenuHandler.GetActivePieMenu();
|
|
if(theCurrentPieMenu)
|
|
{
|
|
theCurrentPieMenu->SetFadeState(false);
|
|
}
|
|
}
|
|
|
|
// If we're dead, make sure the popup menu is closed
|
|
if(!this->GetIsAlive(false))
|
|
{
|
|
gPieMenuHandler.ClosePieMenu();
|
|
}
|
|
}
|
|
|
|
bool AvHHud::GetEntityInfoString(int inEntityID, string& outEntityInfoString, bool& outIsEnemy)
|
|
{
|
|
bool theSuccess = false;
|
|
bool theIsEnemy = false;
|
|
|
|
cl_entity_s* theEntity = gEngfuncs.GetEntityByIndex(inEntityID);
|
|
if(theEntity)
|
|
{
|
|
AvHTeamNumber theTeam = this->GetHUDTeam();
|
|
|
|
if((inEntityID >= 1) && (inEntityID <= gEngfuncs.GetMaxClients()))
|
|
{
|
|
hud_player_info_t thePlayerInfo;
|
|
gEngfuncs.pfnGetPlayerInfo(inEntityID, &thePlayerInfo);
|
|
|
|
string thePrePendString;
|
|
|
|
// Don't show cloaked enemies
|
|
if((theTeam != TEAM_IND) && !this->GetInTopDownMode() && ((theEntity->curstate.team == theTeam) || (theEntity->curstate.rendermode == kRenderNormal)))
|
|
{
|
|
//string thePostPendString;
|
|
if((theEntity->curstate.team == theTeam))
|
|
{
|
|
//LocalizeString(kFriendText, thePrePendString);
|
|
//sprintf(thePostPendString, " (health: %d)", theEntity->curstate.health);
|
|
}
|
|
else
|
|
{
|
|
LocalizeString(kEnemyText, thePrePendString);
|
|
theIsEnemy = true;
|
|
}
|
|
|
|
if(thePrePendString != "")
|
|
{
|
|
outEntityInfoString = thePrePendString + " - ";
|
|
}
|
|
}
|
|
|
|
if(thePlayerInfo.name)
|
|
{
|
|
outEntityInfoString += thePlayerInfo.name;// + thePostPendString;
|
|
|
|
// Get string from status bar and append it
|
|
const char* theStatusCStr = this->m_StatusBar.GetStatusString();
|
|
if(strlen(theStatusCStr) > 0)
|
|
{
|
|
outEntityInfoString += string(theStatusCStr);
|
|
}
|
|
|
|
outIsEnemy = theIsEnemy;
|
|
theSuccess = true;
|
|
}
|
|
|
|
// sprintf(thePlayerName, "%s (health: %d)", thePlayerInfo.name, thePlayer->curstate.health);
|
|
//}
|
|
}
|
|
else
|
|
{
|
|
bool theAutoHelpEnabled = gEngfuncs.pfnGetCvarFloat(kvAutoHelp);
|
|
|
|
// Return the type of thing it is
|
|
AvHUser3 theUser3 = (AvHUser3)(theEntity->curstate.iuser3);
|
|
|
|
if(this->GetTranslatedUser3Name(theUser3, outEntityInfoString))
|
|
{
|
|
if((theEntity->curstate.team != TEAM_IND) && (theEntity->curstate.team != theTeam))
|
|
{
|
|
outIsEnemy = true;
|
|
}
|
|
|
|
// Upper case first character
|
|
if(outEntityInfoString.length() > 0)
|
|
{
|
|
int theFirstChar = outEntityInfoString[0];
|
|
int theUpperFirstChar = toupper(theFirstChar);
|
|
outEntityInfoString[0] = theUpperFirstChar;
|
|
}
|
|
|
|
// Assume status bar set to health/armor/info data
|
|
const char* theStatusCStr = this->m_StatusBar.GetStatusString();
|
|
bool theHasStatusString = (strlen(theStatusCStr) > 0);
|
|
if(theHasStatusString)
|
|
{
|
|
outEntityInfoString += string(theStatusCStr);
|
|
}
|
|
|
|
if(theAutoHelpEnabled)
|
|
{
|
|
string theDescription;
|
|
bool theIsFriendly = (this->GetHUDTeam() == theEntity->curstate.team);
|
|
if(this->GetTranslatedUser3Description(theUser3, theIsFriendly, theDescription))
|
|
{
|
|
outEntityInfoString += " - " + theDescription;
|
|
}
|
|
}
|
|
|
|
// Only display help when asked for or important
|
|
if(theAutoHelpEnabled || theHasStatusString)
|
|
{
|
|
theSuccess = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return theSuccess;
|
|
}
|
|
|
|
void AvHHud::UpdateEntityID(float inCurrentTime)
|
|
{
|
|
this->mBuildingEffectsEntityList.clear();
|
|
|
|
bool theSetHelpMessage = false;
|
|
bool theSetReticleMessage = false;
|
|
|
|
//char* theNewPlayerName = NULL;
|
|
int theEntityIndex = -1;
|
|
|
|
if(this->GetHUDUser3() == AVH_USER3_COMMANDER_PLAYER)
|
|
{
|
|
int theCurrentX, theCurrentY;
|
|
this->GetMousePos(theCurrentX, theCurrentY);
|
|
|
|
// Don't show help when mouse is over the UI
|
|
float theNormX = ((float)theCurrentX)/(ScreenWidth());
|
|
float theNormY = ((float)theCurrentY)/(ScreenHeight());
|
|
if(!this->GetIsRegionBlockedByUI(theNormX, theNormY))
|
|
{
|
|
Vector theNormRay;
|
|
|
|
CreatePickingRay(theCurrentX, theCurrentY, theNormRay);
|
|
|
|
// Look for player and entities under/near the mouse
|
|
AvHSHUGetEntityAtRay(this->GetVisualOrigin(), theNormRay, theEntityIndex);
|
|
}
|
|
}
|
|
else if(g_iUser1 != OBS_IN_EYE)
|
|
{
|
|
// Trace entity id in front of us
|
|
this->TraceEntityID(theEntityIndex);
|
|
}
|
|
|
|
if(this->mSelectingWeaponID != -1)
|
|
{
|
|
// Look up help, set our current help to it
|
|
string theWeaponHelpKey;
|
|
sprintf(theWeaponHelpKey, kWeaponHelpText, this->mSelectingWeaponID);
|
|
|
|
string theHelpText;
|
|
if(LocalizeString(theWeaponHelpKey.c_str(), theHelpText))
|
|
{
|
|
// Get damage amount from weapon
|
|
ASSERT(this->mSelectingWeaponID >= 0);
|
|
ASSERT(this->mSelectingWeaponID < 32);
|
|
WEAPON* theWeapon = gWR.GetWeapon(this->mSelectingWeaponID);
|
|
if( theWeapon )
|
|
{
|
|
int theDamage = theWeapon->iMax2;
|
|
|
|
char theHelpTextWithDamage[1024];
|
|
sprintf(theHelpTextWithDamage, theHelpText.c_str(), theDamage);
|
|
|
|
this->SetHelpMessage(theHelpTextWithDamage);
|
|
theSetHelpMessage = true;
|
|
}
|
|
}
|
|
}
|
|
else if(this->mTechHelpText != "")
|
|
{
|
|
this->SetHelpMessage(this->mTechHelpText, false, .8f, .6f);
|
|
theSetHelpMessage = true;
|
|
}
|
|
else if(this->mSelectingNodeID > 0)
|
|
{
|
|
char theNumber[8];
|
|
sprintf(theNumber, "%d", this->mSelectingNodeID);
|
|
string theNumberString(theNumber);
|
|
|
|
string theKey = string(kTechNodeHelpPrefix) + theNumberString;
|
|
if(LocalizeString(theKey.c_str(), this->mReticleInfoText))
|
|
{
|
|
string theCostString;
|
|
if(LocalizeString(kCostMarker, theCostString))
|
|
{
|
|
string thePointsString;
|
|
if(LocalizeString(kPointsSuffix, thePointsString))
|
|
{
|
|
}
|
|
|
|
// Don't draw marine sayings, as they are printed on the controls and the aliens are using the titles.txt entries
|
|
if(this->GetIsMarine())
|
|
{
|
|
switch(this->mSelectingNodeID)
|
|
{
|
|
case SAYING_1:
|
|
case SAYING_2:
|
|
case SAYING_3:
|
|
case SAYING_4:
|
|
case SAYING_5:
|
|
case SAYING_6:
|
|
case SAYING_7:
|
|
case SAYING_8:
|
|
case SAYING_9:
|
|
this->mReticleInfoText = "";
|
|
break;
|
|
}
|
|
}
|
|
|
|
this->SetHelpMessage(this->mReticleInfoText);
|
|
theSetHelpMessage = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(theEntityIndex > 0)
|
|
{
|
|
// Don't draw info for cloaked structures
|
|
cl_entity_s* theProgressEntity = gEngfuncs.GetEntityByIndex(theEntityIndex);
|
|
if(theProgressEntity)
|
|
{
|
|
if((theProgressEntity->curstate.rendermode != kRenderTransTexture) || (theProgressEntity->curstate.renderamt > kAlienStructureCloakAmount))
|
|
{
|
|
if(std::find(this->mBuildingEffectsEntityList.begin(), this->mBuildingEffectsEntityList.end(), theEntityIndex) == this->mBuildingEffectsEntityList.end())
|
|
{
|
|
this->mBuildingEffectsEntityList.push_back(theEntityIndex);
|
|
}
|
|
|
|
bool theEntityIsPlayer = ((theEntityIndex > 0) && (theEntityIndex <= gEngfuncs.GetMaxClients()));
|
|
|
|
string theHelpText;
|
|
bool theIsEnemy = false;
|
|
|
|
if(this->GetEntityInfoString(theEntityIndex, theHelpText, theIsEnemy))
|
|
{
|
|
// Set color to red if enemy, otherise to our HUD color
|
|
int theR, theG, theB;
|
|
if(theIsEnemy)
|
|
{
|
|
theR = 255;
|
|
theG = theB = 0;
|
|
}
|
|
else
|
|
{
|
|
this->GetPrimaryHudColor(theR, theG, theB, true, false);
|
|
}
|
|
|
|
// If we have auto help on, or we're in top down mode, display as help
|
|
if(gEngfuncs.pfnGetCvarFloat(kvAutoHelp) || this->GetInTopDownMode())
|
|
{
|
|
this->SetHelpMessage(theHelpText);
|
|
|
|
this->mHelpMessage.SetRGB(theR, theG, theB);
|
|
|
|
theSetHelpMessage = true;
|
|
}
|
|
// else, display as reticle message
|
|
else
|
|
{
|
|
this->SetReticleMessage(theHelpText);
|
|
|
|
this->mReticleMessage.SetRGB(theR, theG, theB);
|
|
|
|
theSetReticleMessage = true;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//char theMessage[128];
|
|
//sprintf(theMessage, "Entity %d cloaked, not drawing circle.", theProgressEntity->curstate.iuser3);
|
|
//CenterPrint(theMessage);
|
|
}
|
|
}
|
|
}
|
|
|
|
float theTimePassed = (inCurrentTime - this->mTimeOfLastUpdate);
|
|
if(!theSetHelpMessage)
|
|
{
|
|
this->mHelpMessage.FadeText(theTimePassed, true);
|
|
}
|
|
if(!theSetReticleMessage)
|
|
{
|
|
this->mReticleMessage.FadeText(theTimePassed, true);
|
|
}
|
|
}
|
|
|
|
int AvHHud::GetMenuTechSlots() const
|
|
{
|
|
return this->mMenuTechSlots;
|
|
}
|
|
|
|
const AvHTechTree& AvHHud::GetTechNodes() const
|
|
{
|
|
return this->mTechNodes;
|
|
}
|
|
|
|
void AvHHud::GetTooltipDrawingInfo(float& outNormX, float& outNormY) const
|
|
{
|
|
outNormX = kHelpMessageLeftEdgeInset;
|
|
outNormY = kHelpMessageTopEdgeInset;
|
|
|
|
if(this->GetPlayMode() == PLAYMODE_READYROOM)
|
|
{
|
|
outNormY = 1.0f;
|
|
}
|
|
else if(this->GetInTopDownMode())
|
|
{
|
|
outNormY = kHelpMessageCommanderTopEdgeInset;
|
|
}
|
|
else if(this->GetIsAlien())
|
|
{
|
|
outNormY = kHelpMessageAlienTopEdgeInset;
|
|
}
|
|
|
|
outNormY -= kToolTipVerticalSpacing;
|
|
}
|
|
|
|
string AvHHud::GetRankTitle(bool inShowUnspentLevels) const
|
|
{
|
|
string theText;
|
|
|
|
char* theTeamName = this->GetIsMarine() ? "Marine" : "Alien";
|
|
int theCurrentLevel = this->GetHUDExperienceLevel();
|
|
|
|
char theCharArray[512];
|
|
sprintf(theCharArray, kRankText, theTeamName, theCurrentLevel);
|
|
LocalizeString(theCharArray, theText);
|
|
|
|
// Add unspent levels, if any
|
|
int theUnspentLevels = (this->mExperienceLevel - this->mExperienceLevelSpent - 1);
|
|
if(inShowUnspentLevels && (theUnspentLevels > 0))
|
|
{
|
|
// We can't accurately draw player's unspent levels when we're dead, as we only know our own
|
|
if(this->GetIsAlive(false))
|
|
{
|
|
string theUnspentLevelText = "(+" + MakeStringFromInt(theUnspentLevels) + ")";
|
|
theText += theUnspentLevelText;
|
|
}
|
|
}
|
|
|
|
return theText;
|
|
}
|
|
|
|
void AvHHud::GetReticleTextDrawingInfo(float& outNormX, float& outNormY, bool& outCentered) const
|
|
{
|
|
outCentered = false;
|
|
|
|
if(this->GetInTopDownMode())
|
|
{
|
|
int theCurrentX, theCurrentY;
|
|
this->GetMousePos(theCurrentX, theCurrentY);
|
|
outNormX = theCurrentX/(float)ScreenWidth();
|
|
outNormY = theCurrentY/(float)ScreenHeight();
|
|
|
|
// Move text up a bit so it doesn't obscure
|
|
outNormY -= .1f;
|
|
|
|
outCentered = true;
|
|
}
|
|
else
|
|
{
|
|
if(gEngfuncs.pfnGetCvarFloat(kvCenterEntityID))
|
|
{
|
|
outNormX = .5f;
|
|
outNormY = .5f;
|
|
outCentered = true;
|
|
}
|
|
else
|
|
{
|
|
outNormX = kHelpMessageLeftEdgeInset;
|
|
outNormY = kHelpMessageTopEdgeInset - kReticleMessageHeight;
|
|
|
|
// Alien HUD forces this to be inset a bit
|
|
if(this->GetIsAlien())
|
|
{
|
|
outNormX = kHelpMessageAlienLeftedgeInset + kReticleMessageAlienLeftInset;
|
|
outNormY = kHelpMessageAlienTopEdgeInset - kReticleMessageHeight;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Assumes that the tooltips aren't centered
|
|
void AvHHud::UpdateTooltips(float inCurrentTime)
|
|
{
|
|
float theReticleX;
|
|
float theReticleY;
|
|
this->GetTooltipDrawingInfo(theReticleX, theReticleY);
|
|
|
|
float theBottomMostY = theReticleY;
|
|
|
|
float theTimePassed = inCurrentTime - this->mTimeOfLastUpdate;
|
|
float kMovement = 1.0f*theTimePassed;
|
|
|
|
int theBottomScreenY = theBottomMostY*ScreenHeight();
|
|
|
|
// Clear all tooltips on a role change, or on a playmode change
|
|
AvHUser3 theCurrentUser3 = this->GetHUDUser3();
|
|
AvHTeamNumber theCurrentTeam = this->GetHUDTeam();
|
|
AvHPlayMode thePlayMode = this->GetPlayMode();
|
|
|
|
if((theCurrentUser3 != this->mLastUser3) || (this->mLastTeamNumber != theCurrentTeam) || ((thePlayMode != this->mLastPlayMode) && (this->mLastPlayMode != PLAYMODE_UNDEFINED)) )
|
|
{
|
|
this->mTooltips.clear();
|
|
}
|
|
|
|
// Stuff to get reset on a team change
|
|
if(this->mLastTeamNumber != theCurrentTeam)
|
|
{
|
|
this->mExperienceLevelLastDrawn = 1;
|
|
}
|
|
|
|
// Run through list, dropping them down as far as they can go. Assumes the first one in the list is the bottommost one
|
|
for(AvHTooltipListType::iterator theIter = this->mTooltips.begin(); theIter != this->mTooltips.end(); /* no inc */)
|
|
{
|
|
// Recompute settings, if it hasn't been updated before
|
|
theIter->RecomputeIfNeccessary();
|
|
|
|
// Get height of current tool tip
|
|
int theTooltipScreenHeight = theIter->GetScreenHeight();
|
|
|
|
// Move it down towards the current limit
|
|
float theCurrentMinScreenY = theIter->GetNormalizedScreenY();
|
|
int theCurrentTipScreenBottom = (int)(theCurrentMinScreenY) + theTooltipScreenHeight;
|
|
|
|
float theCurrentMaxNormY = (float)(theBottomScreenY - theTooltipScreenHeight)/ScreenHeight();
|
|
float theNewNormY = min(theCurrentMaxNormY, (theCurrentMinScreenY + kMovement));
|
|
|
|
// Now this is a crazy bug! In release mode without the following two statements, theNewNormY isn't > theCurrentMinScreenY when it should be.
|
|
// It's as if a little time is needed between the computation of theNewNormY and using theNewNormY for it to work
|
|
char theMessage[256];
|
|
sprintf(theMessage, "theNewNormY %f, minScreenY: %f)", theNewNormY, theCurrentMinScreenY);
|
|
//CenterPrint(theMessage);
|
|
|
|
// If we moved it down
|
|
if(theNewNormY > theCurrentMinScreenY)
|
|
{
|
|
// Fade it in while it's dropping
|
|
theIter->FadeText(theTimePassed, false);
|
|
}
|
|
else
|
|
{
|
|
if(theIter == this->mTooltips.begin())
|
|
{
|
|
// If it's at the bottom of the list, start fading it out
|
|
theIter->FadeText(theTimePassed, true);
|
|
}
|
|
}
|
|
|
|
// Set the new position
|
|
theIter->SetNormalizedScreenY(theNewNormY);
|
|
|
|
// Subtract it's height to the current limit
|
|
theBottomScreenY -= theTooltipScreenHeight;
|
|
|
|
// Subtract out small spacing amount
|
|
theBottomScreenY -= max(1, kToolTipVerticalSpacing*ScreenHeight());
|
|
|
|
// If it's totally faded out, remove it from the list, else process next
|
|
int theAlpha = theIter->GetA();
|
|
if(theAlpha == 0)
|
|
{
|
|
theIter = this->mTooltips.erase(theIter);
|
|
}
|
|
else
|
|
{
|
|
theIter++;
|
|
}
|
|
|
|
//char theTempBuffer[256];
|
|
//sprintf(theTempBuffer, "UpdateTooltips, alpha: %d\n", theAlpha);
|
|
//CenterPrint(theTempBuffer);
|
|
}
|
|
|
|
// Update combat upgrade menu too
|
|
if(this->GetIsCombatMode())
|
|
{
|
|
const int kScrollDirection = this->mDrawCombatUpgradeMenu ? 1 : -1;
|
|
const float kScrollingSpeed = .7f*kScrollDirection;
|
|
|
|
float theXDiff = (theTimePassed*kScrollingSpeed);
|
|
const float kNormalizedWidth = this->mCombatUpgradeMenu.GetNormalizedMaxWidth();
|
|
|
|
const float kLeftEdgeInset = .02f;
|
|
float theNewX = this->mCombatUpgradeMenu.GetNormalizedScreenX() + theXDiff;
|
|
theNewX = max(-kNormalizedWidth, theNewX);
|
|
theNewX = min(theNewX, kLeftEdgeInset);
|
|
|
|
this->mCombatUpgradeMenu.SetNormalizedScreenX(theNewX);
|
|
}
|
|
}
|
|
|
|
void AvHHud::UpdateStructureNotification(float inCurrentTime)
|
|
{
|
|
const float kTimeToDisplayIcon = 6.0f;
|
|
const int kMaxIcons = 5;
|
|
|
|
for(StructureHUDNotificationListType::iterator theIter = this->mStructureNotificationList.begin(); theIter != this->mStructureNotificationList.end(); /* no inc */)
|
|
{
|
|
if((inCurrentTime > (theIter->mTime + kTimeToDisplayIcon)) || (this->mStructureNotificationList.size() > kMaxIcons))
|
|
{
|
|
theIter = this->mStructureNotificationList.erase(theIter);
|
|
}
|
|
else
|
|
{
|
|
theIter++;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//void AvHHud::FadeText(float inCurrentTime, bool inFadeDown)
|
|
//{
|
|
// const float kReticleInfoFadeUpSpeed = 500;
|
|
// const float kReticleInfoFadeDownSpeed = -150;
|
|
//
|
|
// // Fade reticle nicely
|
|
// int theFadeSpeed = inFadeDown ? kReticleInfoFadeDownSpeed : kReticleInfoFadeUpSpeed;
|
|
//
|
|
// float theTimePassed = (inCurrentTime - this->mTimeOfLastUpdate);
|
|
// float theNewAlpha = this->mReticleInfoColorA + theTimePassed*theFadeSpeed;
|
|
// this->mReticleInfoColorA = max(0, min(255, theNewAlpha));
|
|
//}
|
|
|
|
float AvHHud::GetTimeOfLastUpdate() const
|
|
{
|
|
return this->mTimeOfLastUpdate;
|
|
}
|
|
|
|
void AvHHud::UpdateProgressBar()
|
|
{
|
|
this->HideProgressStatus();
|
|
|
|
float thePercentage;
|
|
if(gMiniMap.GetIsProcessing(&thePercentage))
|
|
{
|
|
if(gMiniMap.WriteSpritesIfJustFinished())
|
|
{
|
|
this->HideProgressStatus();
|
|
}
|
|
else
|
|
{
|
|
this->SetProgressStatus(thePercentage);
|
|
}
|
|
}
|
|
// else if(this->mProgressBarEntityIndex == -1)
|
|
// {
|
|
// this->HideGenericProgressStatus();
|
|
// }
|
|
else
|
|
{
|
|
// Look up entity, and set progress according to it's fuser1
|
|
cl_entity_s* theProgressEntity = gEngfuncs.GetEntityByIndex(this->mProgressBarEntityIndex);
|
|
if(theProgressEntity)
|
|
{
|
|
ASSERT(this->mProgressBarParam >= 1);
|
|
ASSERT(this->mProgressBarParam <= 4);
|
|
|
|
float theProgress = 0.0f;
|
|
switch(this->mProgressBarParam)
|
|
{
|
|
case 1:
|
|
theProgress = theProgressEntity->curstate.fuser1;
|
|
break;
|
|
case 2:
|
|
theProgress = theProgressEntity->curstate.fuser2;
|
|
break;
|
|
case 3:
|
|
theProgress = theProgressEntity->curstate.fuser3;
|
|
break;
|
|
case 4: // NOTE: check delta.lst for fuser4, it isn't propagated currently
|
|
theProgress = theProgressEntity->curstate.fuser4;
|
|
break;
|
|
}
|
|
|
|
if((this->GetHUDUser3() == AVH_USER3_ALIEN_EMBRYO) || this->GetIsDigesting())
|
|
{
|
|
theProgress = pmove->fuser3;
|
|
}
|
|
|
|
thePercentage = theProgress/kNormalizationNetworkFactor;
|
|
if(thePercentage < 1.0f)
|
|
{
|
|
this->SetProgressStatus(thePercentage);
|
|
}
|
|
// else
|
|
// {
|
|
// this->HideGenericProgressStatus();
|
|
// }
|
|
}
|
|
else
|
|
{
|
|
// Look at selection. If selection has research and research isn't done, draw research bar. Else, hide research bar
|
|
if(this->mSelected.size() == 1)
|
|
{
|
|
cl_entity_s* theEntity = gEngfuncs.GetEntityByIndex(*this->mSelected.begin());
|
|
if(theEntity)
|
|
{
|
|
this->HideProgressStatus();
|
|
this->HideResearchProgressStatus();
|
|
|
|
bool theIsBuilding, theIsResearching;
|
|
float thePercentage;
|
|
AvHSHUGetBuildResearchState(theEntity->curstate.iuser3, theEntity->curstate.iuser4, theEntity->curstate.fuser1, theIsBuilding, theIsResearching, thePercentage);
|
|
|
|
if(theIsBuilding && (thePercentage > 0.0f) && (thePercentage < 1.0f))
|
|
{
|
|
// Turned off progress bar now that we have circular build icons
|
|
//this->SetGenericProgressStatus(thePercentage);
|
|
}
|
|
else if(theIsResearching && (thePercentage > 0) && (thePercentage < 1.0f))
|
|
{
|
|
this->SetResearchProgressStatus(thePercentage);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void AvHHud::GhostBuildingCallback(struct tempent_s* inEntity, float inFrametime, float inCurrentTime)
|
|
{
|
|
if(this->mGhostBuilding != MESSAGE_NULL)
|
|
{
|
|
// Don't let it die
|
|
inEntity->die = gClientTimeLastUpdate + 2.0f;
|
|
|
|
// Update position to be where mouse is
|
|
VectorCopy(this->mGhostWorldLocation, inEntity->entity.origin);
|
|
|
|
// Visually indicate whether this is a valid position or not
|
|
if(this->mCurrentGhostIsValid)
|
|
{
|
|
inEntity->entity.curstate.renderfx = kRenderFxGlowShell;
|
|
inEntity->entity.curstate.rendercolor.r = 0;
|
|
inEntity->entity.curstate.rendercolor.g = 255;
|
|
inEntity->entity.curstate.rendercolor.b = 0;
|
|
inEntity->entity.curstate.renderamt = kShellRenderAmount;
|
|
}
|
|
else
|
|
{
|
|
inEntity->entity.curstate.renderfx = kRenderFxGlowShell;
|
|
inEntity->entity.curstate.rendercolor.r = 255;
|
|
inEntity->entity.curstate.rendercolor.g = 0;
|
|
inEntity->entity.curstate.rendercolor.b = 0;
|
|
inEntity->entity.curstate.renderamt = kShellRenderAmount;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Kill it off immediately
|
|
inEntity->die = gClientTimeLastUpdate;
|
|
}
|
|
}
|
|
|
|
void AvHHud::UpdateBuildingPlacement()
|
|
{
|
|
if(this->mGhostBuilding != MESSAGE_NULL)
|
|
{
|
|
// Fetch current mouse up/down state from gScrollHandler and store
|
|
bool theMouseOneDown = gScrollHandler.GetMouseOneDown() && !gCommanderHandler.GetMouseOneDown();
|
|
bool theMouseTwoDown = gScrollHandler.GetMouseTwoDown();
|
|
|
|
// If we haven't created the temp entity, create it
|
|
if(!this->mCreatedGhost)
|
|
{
|
|
// Create the temporary entity
|
|
int theModelIndex;
|
|
char* theModelName = AvHSHUGetBuildTechModelName(this->mGhostBuilding);
|
|
if(theModelName)
|
|
{
|
|
if(this->mLastGhostBuilding)
|
|
{
|
|
this->mLastGhostBuilding->die = -1;
|
|
this->mLastGhostBuilding = NULL;
|
|
}
|
|
|
|
vec3_t theOrigin = this->GetVisualOrigin();
|
|
struct model_s* theModel = gEngfuncs.CL_LoadModel(theModelName, &theModelIndex);
|
|
TEMPENTITY* theTempEntity = gEngfuncs.pEfxAPI->CL_TentEntAllocCustom(gPredictedPlayerOrigin, theModel, 0, CLinkGhostBuildingCallback);
|
|
if(theTempEntity)
|
|
{
|
|
theTempEntity->die += 10.0f;
|
|
theTempEntity->flags |= FTENT_PERSIST;
|
|
// Temp entities interpret baseline origin as velocity.
|
|
VectorCopy(vec3_origin, theTempEntity->entity.baseline.origin);
|
|
|
|
// Set special properties for some models
|
|
if(this->mGhostBuilding == BUILD_SCAN)
|
|
{
|
|
theTempEntity->entity.curstate.rendermode = kRenderTransAdd;
|
|
theTempEntity->entity.curstate.renderamt = 255;
|
|
|
|
theTempEntity->entity.baseline.rendermode = kRenderTransAdd;
|
|
theTempEntity->entity.baseline.renderamt = 255;
|
|
}
|
|
|
|
this->mCreatedGhost = true;
|
|
}
|
|
|
|
this->mLastGhostBuilding = theTempEntity;
|
|
}
|
|
}
|
|
|
|
// Update location we draw ghosted entity
|
|
int theMouseX, theMouseY;
|
|
this->GetMousePos(theMouseX, theMouseY);
|
|
|
|
Vector theNormMousePos;
|
|
CreatePickingRay(theMouseX, theMouseY, theNormMousePos);
|
|
|
|
//char theMessage[256];
|
|
//sprintf(theMessage, "Ghost: %f, %f, %f", this->mGhostWorldLocation[0], this->mGhostWorldLocation[1],this->mGhostWorldLocation[2]);
|
|
//CenterPrint(theMessage);
|
|
|
|
// Was either mouse button pressed?
|
|
bool theMouseOneReleased = (theMouseOneDown && !this->mMouseOneDown);
|
|
bool theMouseTwoReleased = (theMouseTwoDown && !this->mMouseTwoDown);
|
|
if(theMouseOneReleased)
|
|
{
|
|
VectorCopy(this->mLeftMouseWorldStart, this->mNormBuildLocation);
|
|
}
|
|
else if(theMouseTwoReleased)
|
|
{
|
|
VectorCopy(this->mRightMouseWorldStart, this->mNormBuildLocation);
|
|
}
|
|
|
|
// Test to see if we're in a valid position
|
|
this->mCurrentGhostIsValid = false;
|
|
|
|
vec3_t theLocation;
|
|
if(AvHSHUTraceAndGetIsSiteValidForBuild(this->mGhostBuilding, this->GetVisualOrigin(), theNormMousePos, &theLocation))
|
|
{
|
|
// Update with cost and research info
|
|
bool theIsResearchable;
|
|
int theCost;
|
|
float theTime;
|
|
if(this->mTechNodes.GetResearchInfo(this->mGhostBuilding, theIsResearchable, theCost, theTime))
|
|
{
|
|
// Ghost is valid if message available and
|
|
// we have enough resources OR
|
|
// tech takes energy and we have enough energy
|
|
this->mCurrentGhostIsValid = false;
|
|
|
|
if(this->mTechNodes.GetIsMessageAvailable(this->mGhostBuilding))
|
|
{
|
|
bool theTakesEnergy = AvHSHUGetDoesTechCostEnergy(this->mGhostBuilding);
|
|
if((theCost <= this->mResources) || (theTakesEnergy))
|
|
{
|
|
this->mCurrentGhostIsValid = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Draw at selection start range * invalid range multiplier if invalid placement, draw on at target location if valid
|
|
//VectorMA(this->GetVisualOrigin(), kSelectionStartRange*kBuildInvalidRangeMultiplier, theNormMousePos, this->mGhostWorldLocation);
|
|
VectorMA(this->GetVisualOrigin(), kSelectionStartRange*8, theNormMousePos, this->mGhostWorldLocation);
|
|
//if(this->mCurrentGhostIsValid)
|
|
//{
|
|
VectorCopy(theLocation, this->mGhostWorldLocation);
|
|
//}
|
|
|
|
if((theMouseOneReleased) || (theMouseTwoReleased))
|
|
{
|
|
// If this is a valid location
|
|
if(this->mCurrentGhostIsValid)
|
|
{
|
|
// Play sound
|
|
this->PlayHUDSound(HUD_SOUND_PLACE_BUILDING);
|
|
|
|
// Remember it for input to grab
|
|
this->mValidatedBuilding = this->mGhostBuilding;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void AvHHud::CancelBuilding()
|
|
{
|
|
SetGhostBuildingMode(MESSAGE_NULL);
|
|
this->mValidatedBuilding = MESSAGE_NULL;
|
|
}
|
|
|
|
void AvHHud::UpdateSelection()
|
|
{
|
|
// Fetch current mouse up/down state from gScrollHandler and store
|
|
bool theMouseOneDown = gScrollHandler.GetMouseOneDown() && !gCommanderHandler.GetMouseOneDown();
|
|
bool theMouseTwoDown = gScrollHandler.GetMouseTwoDown();
|
|
|
|
int theCurrentX, theCurrentY;
|
|
this->GetMousePos(theCurrentX, theCurrentY);
|
|
|
|
CreatePickingRay(theCurrentX, theCurrentY, this->mMouseWorldPosition);
|
|
//ASSERT(this->mMouseWorldPosition.z < 0.0f);
|
|
|
|
// Left mouse button //
|
|
// If mouse just pressed, set starting point
|
|
if(theMouseOneDown && !this->mMouseOneDown)
|
|
{
|
|
this->mMouseOneStartX = theCurrentX;
|
|
this->mMouseOneStartY = theCurrentY;
|
|
this->mLeftMouseStarted = true;
|
|
|
|
//CreatePickingRay(theCurrentX, theCurrentY, this->mLeftMouseWorldStart);
|
|
//ASSERT(this->mLeftMouseWorldStart.z < 0.0f);
|
|
VectorCopy(this->mMouseWorldPosition, this->mLeftMouseWorldStart);
|
|
}
|
|
else
|
|
{
|
|
this->mLeftMouseStarted = false;
|
|
}
|
|
|
|
// If mouse just released, set flag to indicate selection just changed
|
|
if(!theMouseOneDown && this->mMouseOneDown)
|
|
{
|
|
//CreatePickingRay(theCurrentX, theCurrentY, this->mLeftMouseWorldEnd);
|
|
//ASSERT(this->mLeftMouseWorldEnd.z < 0.0f);
|
|
VectorCopy(this->mMouseWorldPosition, this->mLeftMouseWorldEnd);
|
|
|
|
//this->mSelectionJustChanged = true;
|
|
this->mLeftMouseEnded = true;
|
|
}
|
|
else
|
|
{
|
|
this->mLeftMouseEnded = false;
|
|
}
|
|
|
|
// Right mouse button //
|
|
// If mouse two just pressed, set starting point
|
|
if(theMouseTwoDown && !this->mMouseTwoDown)
|
|
{
|
|
this->mMouseTwoStartX = theCurrentX;
|
|
this->mMouseTwoStartY = theCurrentY;
|
|
this->mRightMouseStarted = true;
|
|
|
|
//CreatePickingRay(theCurrentX, theCurrentY, this->mRightMouseWorldStart);
|
|
//ASSERT(this->mRightMouseWorldStart.z < 0.0f);
|
|
VectorCopy(this->mMouseWorldPosition, this->mRightMouseWorldStart);
|
|
}
|
|
else
|
|
{
|
|
this->mRightMouseStarted = false;
|
|
}
|
|
|
|
// If mouse just released, set flag to indicate selection just changed
|
|
if(!theMouseTwoDown && this->mMouseTwoDown)
|
|
{
|
|
//CreatePickingRay(theCurrentX, theCurrentY, this->mRightMouseWorldEnd);
|
|
//ASSERT(this->mRightMouseWorldEnd.z < 0.0f);
|
|
VectorCopy(this->mMouseWorldPosition, this->mRightMouseWorldEnd);
|
|
|
|
//this->mSelectionJustChanged = true;
|
|
this->mRightMouseEnded = true;
|
|
}
|
|
else
|
|
{
|
|
this->mRightMouseEnded = false;
|
|
}
|
|
|
|
// Set extents of marquee control
|
|
this->mSelectionBox->SetStartPos(this->mMouseOneStartX, this->mMouseOneStartY);
|
|
this->mSelectionBox->SetEndPos(theCurrentX, theCurrentY);
|
|
|
|
// Set visibility state of marquee control
|
|
//this->mSelectionBox->setVisible(theMouseOneDown);
|
|
this->mSelectionBox->setVisible(false);
|
|
|
|
this->mSelectionBoxX1 = mMouseOneStartX;
|
|
this->mSelectionBoxY1 = mMouseOneStartY;
|
|
this->mSelectionBoxX2 = theCurrentX;
|
|
this->mSelectionBoxY2 = theCurrentY;
|
|
|
|
this->mSelectionBoxVisible = theMouseOneDown;
|
|
|
|
// If we're just selecting stuff, don't want to hit this button by mistake
|
|
//gCommanderHandler.SetActive(!theMouseOneDown);
|
|
|
|
// Change context sensitive cursor depending on current position
|
|
//if(this->mSelected.size() > 0)
|
|
//{
|
|
// if(this->mGhostBuilding == MESSAGE_NULL)
|
|
// {
|
|
// Vector theCurrentMouseRay;
|
|
// CreatePickingRay(theCurrentX, theCurrentY, theCurrentMouseRay);
|
|
//
|
|
// int theTargetIndex;
|
|
// AvHOrderTargetType theTargetType;
|
|
// Vector theTargetLocation;
|
|
// AvHUser3 theUser3 = AVH_USER3_NONE;
|
|
// AvHOrderType theOrderType = AvHGetDefaultOrderType(this->GetHUDTeam(), this->GetVisualOrigin(), theCurrentMouseRay, theTargetIndex, theTargetLocation, theUser3, theTargetType);
|
|
// Test UI blocking
|
|
// theOrderType = ORDERTYPEL_DEFAULT;
|
|
// if(!AvHSHUGetIsRegionBlockedByUI((float)theCurrentX/ScreenWidth, (float)theCurrentY/ScreenHeight))
|
|
// {
|
|
// theOrderType = ORDERTYPET_GUARD;
|
|
// }
|
|
// this->SetCursor(theOrderType);
|
|
|
|
// Change cursor depending on order type
|
|
//if(theOrderType != ORDERTYPEL_MOVE && this->mSelected.size() > 0 )
|
|
//{
|
|
// if(!this->GetIsRegionBlockedByUI(theCurrentX/ScreenWidth(), theCurrentY/ScreenHeight()))
|
|
// {
|
|
//this->SetCursor(theOrderType);
|
|
// }
|
|
//}
|
|
// }
|
|
//}
|
|
|
|
if(this->mLeftMouseEnded)
|
|
{
|
|
// Select all units at this click or in this area (but don't select when clicking a building down)
|
|
if(!this->mPlacingBuilding)
|
|
{
|
|
gSelectionHelper.QueueSelection(this->GetVisualOrigin(), this->mLeftMouseWorldStart, this->mLeftMouseWorldEnd, this->GetHUDTeam());
|
|
gSelectionHelper.ProcessPendingSelections();
|
|
}
|
|
}
|
|
|
|
if(gSelectionHelper.SelectionResultsWaiting())
|
|
{
|
|
EntityListType theNewSelection;
|
|
gSelectionHelper.GetAndClearSelection(theNewSelection);
|
|
// this->mNumLocalSelectEvents++;
|
|
|
|
if(theNewSelection != this->mSelected)
|
|
{
|
|
this->mSelected = theNewSelection;
|
|
this->mSelectionJustChanged = true;
|
|
}
|
|
|
|
this->ClearTrackingEntity();
|
|
}
|
|
|
|
// If selection just changed, make sure we have selection effects for everyone
|
|
if(this->mSelectionJustChanged)
|
|
{
|
|
// Create effects
|
|
this->SetSelectionEffects(this->mSelected);
|
|
|
|
this->PlayHUDSound(HUD_SOUND_SELECT);
|
|
|
|
gCommanderHandler.SetSelectedUnits(this->mSelected);
|
|
|
|
// Clear flag
|
|
this->mSelectionJustChanged = false;
|
|
|
|
// // Set default order mode
|
|
// if(this->mSelected.size() > 0)
|
|
// {
|
|
// this->mOrderMode = ORDERTYPEL_DEFAULT;
|
|
// }
|
|
// else
|
|
// {
|
|
// this->mOrderMode = ORDERTYPE_UNDEFINED;
|
|
// }
|
|
}
|
|
|
|
this->UpdateBuildingPlacement();
|
|
|
|
// Store current mouse state
|
|
this->mMouseOneDown = theMouseOneDown;
|
|
this->mMouseTwoDown = theMouseTwoDown;
|
|
}
|
|
|
|
void AvHHud::UpdateBuildResearchText()
|
|
{
|
|
// Hide unchanging ("unhelpful"?) help text after this amount of time
|
|
const float kHelpTextInterval = 2.5f;
|
|
|
|
if(this->GetHUDUser3() == AVH_USER3_COMMANDER_PLAYER)
|
|
{
|
|
Label* theHelpTextLabel = NULL;
|
|
if(this->GetManager().GetVGUIComponentNamed(kTechHelpText, theHelpTextLabel))
|
|
{
|
|
gCommanderHandler.RecalculateBuildResearchText();
|
|
|
|
// Display build/research text
|
|
string theBuildResearchText = gCommanderHandler.GetBuildResearchText();
|
|
theHelpTextLabel->setText(theBuildResearchText.c_str());
|
|
|
|
// Center it
|
|
int theWidth, theHeight;
|
|
theHelpTextLabel->getTextSize(theWidth, theHeight);
|
|
|
|
int theX, theY;
|
|
theHelpTextLabel->getPos(theX, theY);
|
|
|
|
int theScreenWidth = ScreenWidth();
|
|
theHelpTextLabel->setPos(theScreenWidth/2 - theWidth/2, theY);
|
|
|
|
// Vanish if no text (but keep build/research text visible)
|
|
theHelpTextLabel->setVisible(true);
|
|
if(theBuildResearchText.length() == 0)// || ((this->mTimeLastHelpTextChanged != -1) && (this->mTimeLastHelpTextChanged + kHelpTextInterval < this->mTimeOfLastUpdate)))
|
|
{
|
|
theHelpTextLabel->setVisible(false);
|
|
}
|
|
|
|
// Display action button tool tip
|
|
string theTechHelpText = gCommanderHandler.GetTechHelpText();
|
|
if(theTechHelpText != "")
|
|
{
|
|
this->SetActionButtonHelpMessage(theTechHelpText);
|
|
}
|
|
|
|
if(theTechHelpText != this->mPreviousHelpText)
|
|
{
|
|
this->mTimeLastHelpTextChanged = this->mTimeOfLastUpdate;
|
|
}
|
|
|
|
this->mPreviousHelpText = theTechHelpText;
|
|
}
|
|
}
|
|
}
|
|
|
|
void AvHHud::UpdateTechNodes()
|
|
{
|
|
this->UpdateBuildResearchText();
|
|
|
|
// Don't get new node until existing one has been processed
|
|
if(this->mTechEvent == MESSAGE_NULL)
|
|
{
|
|
//if(this->mGameStarted)
|
|
//{
|
|
//AvHTechNode theTechNode;
|
|
//if(gCommanderHandler.GetAndClearTechNodePressed(theTechNode))
|
|
AvHMessageID theMessageID;
|
|
if(gCommanderHandler.GetAndClearTechNodePressed(theMessageID))
|
|
{
|
|
// Check for grouping and request events and handle separately
|
|
if(this->mTechNodes.GetIsMessageAvailable(theMessageID))
|
|
{
|
|
bool theIsResearchable;
|
|
int theCost;
|
|
float theTime;
|
|
|
|
if(this->mTechNodes.GetResearchInfo(theMessageID, theIsResearchable, theCost, theTime))
|
|
{
|
|
if(AvHSHUGetIsBuildTech(theMessageID))
|
|
{
|
|
// Don't check for enough points yet, they might get enough points before they put it down
|
|
|
|
// Get ready to build it, don't send a research message
|
|
this->SetGhostBuildingMode(theMessageID);
|
|
}
|
|
else if(AvHSHUGetIsResearchTech(theMessageID) && theIsResearchable)
|
|
{
|
|
// If we hit cancel, and we're in building mode, get out of build mode and throw event away
|
|
if((theMessageID == MESSAGE_CANCEL) && (this->GetGhostBuilding() != MESSAGE_NULL))
|
|
{
|
|
CancelBuilding();
|
|
}
|
|
else if(theCost <= this->mResources)
|
|
{
|
|
this->mTechEvent = theMessageID;
|
|
}
|
|
else
|
|
{
|
|
// Emit error message that you don't have the resources
|
|
this->PlayHUDSound(HUD_SOUND_MARINE_MORE);
|
|
}
|
|
}
|
|
else if(theMessageID == BUILD_RECYCLE)
|
|
{
|
|
this->mTechEvent = theMessageID;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
this->mTechEvent = theMessageID;
|
|
}
|
|
}
|
|
else if((theMessageID >= SAYING_1) && (theMessageID <= SAYING_9))
|
|
{
|
|
this->mTechEvent = theMessageID;
|
|
}
|
|
}
|
|
//}
|
|
}
|
|
}
|
|
|
|
void AvHHud::UpdateAmbientSounds()
|
|
{
|
|
Vector theListenerPosition;
|
|
VectorCopy(gPredictedPlayerOrigin, theListenerPosition);
|
|
|
|
// Commanders have a different PAS then themselves
|
|
if(this->mInTopDownMode)
|
|
{
|
|
VectorCopy(this->mCommanderPAS, theListenerPosition);
|
|
}
|
|
|
|
for(AmbientSoundListType::iterator theIter = this->mAmbientSounds.begin(); theIter != this->mAmbientSounds.end(); theIter++)
|
|
{
|
|
theIter->StartPlayingIfNot();
|
|
theIter->UpdateVolume(theListenerPosition);
|
|
}
|
|
}
|
|
|
|
void AvHHud::UpdateFromEntities(float inCurrentTime)
|
|
{
|
|
// Only update every so often for performance reasons
|
|
const float kEntityUpdateInterval = .4f;
|
|
if(inCurrentTime > (this->mTimeOfLastEntityUpdate + kEntityUpdateInterval))
|
|
{
|
|
this->mHelpIcons.clear();
|
|
this->mHelpEnts.clear();
|
|
|
|
bool theAutoHelpEnabled = gEngfuncs.pfnGetCvarFloat(kvAutoHelp);
|
|
|
|
// Clear help icons
|
|
this->mHelpEnts.clear();
|
|
|
|
// Clear building effects
|
|
//this->mBuildingEffectsEntityList.clear();
|
|
|
|
this->mTimeOfLastEntityUpdate = inCurrentTime;
|
|
|
|
// Scan for entities, adding help icons
|
|
// Only draw if enabled
|
|
const int kHelpDistance = 350;
|
|
const int kBuildDistance = 500;
|
|
const int kHealthDistance = 125;
|
|
|
|
// Look for entities that have help icons in front of us. Don't search to far away, it could give players away.
|
|
EntityListType theHelpEntities;
|
|
AvHSHUGetEntities(-1, theHelpEntities);
|
|
|
|
cl_entity_t* theLocalPlayer = gEngfuncs.GetLocalPlayer();
|
|
|
|
for(EntityListType::iterator theIter = theHelpEntities.begin(); theIter != theHelpEntities.end(); theIter++)
|
|
{
|
|
vec3_t theLocation;
|
|
if(AvHSHUGetEntityLocation(*theIter, theLocation))
|
|
{
|
|
float theDistance = VectorDistance((float*)&theLocation, theLocalPlayer->origin);
|
|
if(theDistance < kHelpDistance)
|
|
{
|
|
// If iuser3 isn't 0, try looking up an icon for it
|
|
physent_t* theEntity = gEngfuncs.pEventAPI->EV_GetPhysent(*theIter);
|
|
if(theEntity)
|
|
{
|
|
// Don't add cloaked entities (I wish this could be more general purpose)
|
|
if((theEntity->team == this->GetHUDTeam()) || (theEntity->rendermode == kRenderNormal))
|
|
{
|
|
int theUser3 = theEntity->iuser3;
|
|
vec3_t theEntityOrigin = AvHSHUGetRealLocation(theEntity->origin, theEntity->mins, theEntity->maxs);
|
|
|
|
// Some entities always draw
|
|
bool theAlwaysDraw = false;
|
|
switch(theUser3)
|
|
{
|
|
case AVH_USER3_WELD:
|
|
//case AVH_USER3_COMMANDER_STATION:
|
|
//case AVH_USER3_HIVE:
|
|
theAlwaysDraw = true;
|
|
break;
|
|
}
|
|
|
|
if(theAutoHelpEnabled || theAlwaysDraw)
|
|
{
|
|
this->mHelpIcons.push_back( make_pair(theEntityOrigin, theUser3) );
|
|
|
|
// Push back entity for displaying helpful tooltips
|
|
this->mHelpEnts.push_back(*theIter);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void AvHHud::UpdateViewModelEffects()
|
|
{
|
|
cl_entity_t* theViewModel = GetViewEntity();
|
|
if(theViewModel)
|
|
{
|
|
int theRenderMode = kRenderNormal;
|
|
int theRenderAmount = 0;
|
|
int theRenderFx = theViewModel->curstate.renderfx;
|
|
color24 theRenderColor = theViewModel->curstate.rendercolor;
|
|
short theSkin = 0;
|
|
|
|
// Set the skin, stored in playerclass
|
|
|
|
//cl_entity_s* theLocalPlayer = gEngfuncs.GetLocalPlayer();
|
|
|
|
// Use the visible player so that when we are spectating we can tell
|
|
// when the player is cloaked.
|
|
cl_entity_s* theLocalPlayer = GetVisiblePlayer();
|
|
|
|
if(theLocalPlayer)
|
|
{
|
|
|
|
//theViewModel->curstate.skin = theLocalPlayer->curstate.skin;
|
|
theRenderMode = theLocalPlayer->curstate.rendermode;
|
|
theRenderAmount = theLocalPlayer->curstate.renderamt;
|
|
theRenderFx = theLocalPlayer->curstate.renderfx;
|
|
theRenderColor = theLocalPlayer->curstate.rendercolor;
|
|
theSkin = theLocalPlayer->curstate.skin;
|
|
// Hack to make cloaking work for viewmodels (if only view models rendered in additive properly).
|
|
// Draw view model normally unless fully cloaked.
|
|
//bool theIsCloakedViaUpgrade = GetHasUpgrade(theLocalPlayer->curstate.iuser4, MASK_ALIEN_CLOAKED);
|
|
int old=theRenderAmount;
|
|
if((theRenderMode == kRenderTransTexture) /*|| theIsCloakedViaUpgrade*/)
|
|
{
|
|
theRenderFx = kRenderFxNone;
|
|
theRenderColor.r = theRenderColor.g = theRenderColor.b = 0;
|
|
|
|
if ( theRenderAmount == kAlienSelfCloakingBaseOpacity )
|
|
{
|
|
theRenderMode = kAlienCloakViewModelRenderMode;
|
|
theRenderAmount = 10;
|
|
}
|
|
else if( theRenderAmount > kAlienSelfCloakingBaseOpacity && theRenderAmount < 186)
|
|
{
|
|
theRenderMode = kAlienCloakViewModelRenderMode;
|
|
theRenderAmount = 40;
|
|
}
|
|
else if ( theRenderAmount == 186 ) {
|
|
theRenderMode = kAlienCloakViewModelRenderMode;
|
|
theRenderAmount = 50;
|
|
}
|
|
else
|
|
{
|
|
theRenderMode = kRenderNormal;
|
|
theRenderAmount = 255;
|
|
}
|
|
}
|
|
|
|
|
|
//char theMessage[128];
|
|
//sprintf(theMessage, "Setting view model mode: %d amount: %d\n", theRenderMode, theRenderAmount);
|
|
//CenterPrint(theMessage);
|
|
}
|
|
|
|
// if(GetHasUpgrade(this->GetLocalUpgrades(), MASK_ALIEN_CLOAKED))
|
|
// {
|
|
// theRenderMode = kAlienCloakViewModelRenderMode;
|
|
// int theCloakingLevel = AvHGetAlienUpgradeLevel(this->GetLocalUpgrades(), MASK_UPGRADE_7);
|
|
// theRenderAmount = kAlienCloakViewModelAmount - theCloakingLevel*kAlienCloakViewModelLevelAmount;
|
|
//
|
|
// // Put in color, because texture rendering needs it
|
|
// theRenderFx = kRenderFxNone;
|
|
// theRenderColor.r = theRenderColor.g = theRenderColor.b = 0;
|
|
// }
|
|
|
|
if(this->mInTopDownMode)
|
|
{
|
|
theRenderMode = kRenderTransAdd;
|
|
theRenderAmount = 1;
|
|
}
|
|
|
|
theViewModel->curstate.skin = theSkin;
|
|
theViewModel->curstate.rendermode = theRenderMode;
|
|
theViewModel->curstate.renderamt = theRenderAmount;
|
|
theViewModel->curstate.renderfx = theRenderFx;
|
|
theViewModel->curstate.rendercolor = theRenderColor;
|
|
}
|
|
}
|
|
|
|
void AvHHud::UpdateResources(float inTimePassed)
|
|
{
|
|
const float kResourceRate = this->GetMaxAlienResources()/50.0f;
|
|
int thePointsToMove = max(inTimePassed*kResourceRate, 1);
|
|
|
|
// Update visual resources if different this resources
|
|
if(this->mVisualResources != this->mResources)
|
|
{
|
|
if(abs(this->mVisualResources - this->mResources) <= thePointsToMove)
|
|
{
|
|
this->mVisualResources = this->mResources;
|
|
}
|
|
else
|
|
{
|
|
if(this->mVisualResources < this->mResources)
|
|
{
|
|
this->mVisualResources += thePointsToMove;
|
|
}
|
|
else
|
|
{
|
|
this->mVisualResources -= thePointsToMove;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Smoothly adjust energy level
|
|
float theCurrentEnergyLevel = pmove->fuser3/kNormalizationNetworkFactor;
|
|
|
|
if((g_iUser1 == OBS_IN_EYE) && (g_iUser2 != this->mUser2OfLastEnergyLevel))
|
|
{
|
|
// This isn't working yet
|
|
this->mVisualEnergyLevel = theCurrentEnergyLevel;
|
|
this->mUser2OfLastEnergyLevel = g_iUser2;
|
|
}
|
|
else
|
|
{
|
|
float kEnergyRate = 1.0f;
|
|
float theEnergyToMove = inTimePassed*kEnergyRate;
|
|
if(this->mVisualEnergyLevel != theCurrentEnergyLevel)
|
|
{
|
|
float theDiff = fabs(this->mVisualEnergyLevel - theCurrentEnergyLevel);
|
|
if(theDiff <= theEnergyToMove)
|
|
{
|
|
this->mVisualEnergyLevel = theCurrentEnergyLevel;
|
|
}
|
|
else
|
|
{
|
|
if(this->mVisualEnergyLevel < theCurrentEnergyLevel)
|
|
{
|
|
this->mVisualEnergyLevel += theEnergyToMove;
|
|
}
|
|
else
|
|
{
|
|
this->mVisualEnergyLevel -= theEnergyToMove;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
string theResourceText;
|
|
char theResourceBuffer[64];
|
|
|
|
if(this->GetInTopDownMode() && this->mCommanderResourceLabel)
|
|
{
|
|
LocalizeString(kMarineResourcePrefix, theResourceText);
|
|
sprintf(theResourceBuffer, "%s %d", theResourceText.c_str(), this->mVisualResources);
|
|
this->mCommanderResourceLabel->setText(64, theResourceBuffer);
|
|
}
|
|
|
|
// Update visual resource indicators, expiring old ones
|
|
const float kNumericalInfoEffectLifetime = 1.1f;
|
|
const float kNumericalInfoScrollSpeed = 24;
|
|
for(NumericalInfoEffectListType::iterator theIter = this->mNumericalInfoEffects.begin(); theIter != this->mNumericalInfoEffects.end(); /* no inc */)
|
|
{
|
|
if((theIter->GetTimeCreated() + kNumericalInfoEffectLifetime) < this->mTimeOfLastUpdate)
|
|
{
|
|
theIter = this->mNumericalInfoEffects.erase(theIter);
|
|
}
|
|
else
|
|
{
|
|
// Update position
|
|
float thePosition[3];
|
|
theIter->GetPosition(thePosition);
|
|
|
|
thePosition[2] += inTimePassed*kNumericalInfoScrollSpeed;
|
|
|
|
theIter->SetPosition(thePosition);
|
|
|
|
// Next
|
|
theIter++;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
//void AvHHud::ChangeUpgradeCosts(int inOldMessageID, int inNewMessageID, const char* inText)
|
|
//{
|
|
// this->ChangeUpgradeCostsForMenu(this->mSoldierMenu, inOldMessageID, inNewMessageID, inText);
|
|
// this->ChangeUpgradeCostsForMenu(this->mLeaderMenu, inOldMessageID, inNewMessageID, inText);
|
|
// this->ChangeUpgradeCostsForMenu(this->mCommanderMenu, inOldMessageID, inNewMessageID, inText);
|
|
//
|
|
// this->UpdateUpgradeCosts();
|
|
//}
|
|
//
|
|
//void AvHHud::ChangeUpgradeCostsForMenu(PieMenu* inMenu, int inOldMessageID, int inNewMessageID, const char* inText)
|
|
//{
|
|
// if(inMenu)
|
|
// {
|
|
// inMenu->ChangeNode(inOldMessageID, inNewMessageID, string(inText));
|
|
// }
|
|
//}
|
|
//
|
|
//void AvHHud::ResetUpgradeCosts()
|
|
//{
|
|
// this->ResetUpgradeCostsForMenu(this->mSoldierMenu);
|
|
// this->ResetUpgradeCostsForMenu(this->mLeaderMenu);
|
|
// this->ResetUpgradeCostsForMenu(this->mCommanderMenu);
|
|
//
|
|
// this->UpdateUpgradeCosts();
|
|
//}
|
|
|
|
//void AvHHud::ResetUpgradeCostsForMenu(PieMenu* inMenu)
|
|
//{
|
|
// if(inMenu)
|
|
// {
|
|
// inMenu->ResetToDefaults();
|
|
// }
|
|
//}
|
|
|
|
bool AvHHud::GetParticlesVisible() const
|
|
{
|
|
|
|
if (g_iUser1 == OBS_NONE)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
if (m_Spectator.IsInOverviewMode())
|
|
{
|
|
return m_Spectator.m_iDrawCycle == 1;
|
|
}
|
|
else
|
|
{
|
|
return true;
|
|
}
|
|
|
|
}
|
|
|
|
// Sprite drawing on a level change is problematic and can cause crashing or disconcerting "no such sprite" error messages
|
|
bool AvHHud::GetSafeForSpriteDrawing() const
|
|
{
|
|
bool theSafeForDrawing = false;
|
|
|
|
const char* theLevelName = gEngfuncs.pfnGetLevelName();
|
|
string theCurrentMapName = this->GetMapName(true);
|
|
if(theLevelName && (theCurrentMapName != ""))
|
|
{
|
|
string theLevelNameString(theLevelName);
|
|
int thePos = (int)theLevelNameString.find(theCurrentMapName);
|
|
if(thePos != string::npos)
|
|
{
|
|
theSafeForDrawing = true;
|
|
}
|
|
}
|
|
|
|
return theSafeForDrawing;
|
|
}
|
|
|
|
bool AvHHud::GetShouldDisplayUser3(AvHUser3 inUser3) const
|
|
{
|
|
bool theShouldDisplay = false;
|
|
|
|
if((inUser3 > AVH_USER3_NONE) && (inUser3 < AVH_USER3_MAX))
|
|
{
|
|
theShouldDisplay = true;
|
|
|
|
switch(inUser3)
|
|
{
|
|
case AVH_USER3_BREAKABLE:
|
|
case AVH_USER3_USEABLE:
|
|
case AVH_USER3_PARTICLE_ON:
|
|
case AVH_USER3_PARTICLE_OFF:
|
|
case AVH_USER3_ALPHA:
|
|
case AVH_USER3_WAYPOINT:
|
|
case AVH_USER3_NOBUILD:
|
|
case AVH_USER3_SPAWN_TEAMA:
|
|
case AVH_USER3_SPAWN_TEAMB:
|
|
theShouldDisplay = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return theShouldDisplay;
|
|
}
|
|
|
|
bool AvHHud::GetTranslatedUser3Name(AvHUser3 inUser3, string& outString) const
|
|
{
|
|
bool theSuccess = false;
|
|
|
|
if(this->GetShouldDisplayUser3(inUser3))
|
|
{
|
|
char theUser3String[512];
|
|
sprintf(theUser3String, "#%s%d", kUser3Name, inUser3);
|
|
theSuccess = LocalizeString(theUser3String, outString);
|
|
}
|
|
|
|
return theSuccess;
|
|
}
|
|
|
|
bool AvHHud::GetTranslatedUser3Description(AvHUser3 inUser3, bool inFriendly, string& outString) const
|
|
{
|
|
bool theSuccess = false;
|
|
|
|
if(this->GetShouldDisplayUser3(inUser3))
|
|
{
|
|
char theUser3String[512];
|
|
sprintf(theUser3String, "#%s%d", kUser3Description, inUser3);
|
|
theSuccess = LocalizeString(theUser3String, outString);
|
|
|
|
// If we're commanding, look for that description if it exists
|
|
if(this->GetInTopDownMode())
|
|
{
|
|
string theCommanderDescription;
|
|
sprintf(theUser3String, "#%s%d", kUser3CommanderDescription, inUser3);
|
|
if(LocalizeString(theUser3String, theCommanderDescription))
|
|
{
|
|
outString = theCommanderDescription;
|
|
theSuccess = true;
|
|
}
|
|
}
|
|
// Else look for a message that tell us what to do with this thing (assumes we're not commanding though)
|
|
else if(inFriendly)
|
|
{
|
|
string theFriendlyDescription;
|
|
sprintf(theUser3String, "#%s%d", kUser3FriendlyDescription, inUser3);
|
|
if(LocalizeString(theUser3String, theFriendlyDescription))
|
|
{
|
|
outString = theFriendlyDescription;
|
|
theSuccess = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return theSuccess;
|
|
}
|
|
|
|
|
|
void AvHHud::UpdateUpgradeCosts()
|
|
{
|
|
PieMenu* theCurrentMenu = NULL;
|
|
if(this->GetManager().GetVGUIComponentNamed(this->mPieMenuControl, theCurrentMenu))
|
|
{
|
|
this->UpdateEnableState(theCurrentMenu);
|
|
}
|
|
}
|
|
|
|
void AvHHud::AddMiniMapAlert(float x, float y)
|
|
{
|
|
mOverviewMap.AddAlert(x, y);
|
|
}
|
|
|
|
void AvHHud::UpdateEnableState(PieMenu* inMenu)
|
|
{
|
|
if(inMenu)
|
|
{
|
|
int thePurchaseLevel = this->GetIsCombatMode() ? max(0, this->mExperienceLevel - this->mExperienceLevelSpent - 1) : this->mResources;
|
|
|
|
inMenu->UpdateMenuFromTech(this->mTechNodes, thePurchaseLevel);
|
|
|
|
// if(this->GetIsNSMode())
|
|
//{
|
|
// Now disable any nodes whose children are all disabled (in NS, only end nodes can be chosen)
|
|
//inMenu->DisableNodesWhoseChildrenAreDisabled();
|
|
//}
|
|
|
|
inMenu->RecomputeVisibleSize();
|
|
}
|
|
}
|
|
|
|
void AvHHud::ShowMap()
|
|
{
|
|
if (!sShowMap && gHUD.GetIsNSMode())
|
|
{
|
|
sShowMap = true;
|
|
gHUD.HideCrosshair();
|
|
gHUD.GetManager().UnhideComponent(kShowMapHierarchy);
|
|
}
|
|
}
|
|
|
|
void AvHHud::HideMap()
|
|
{
|
|
if (sShowMap)
|
|
{
|
|
sShowMap = false;
|
|
gHUD.GetManager().HideComponent(kShowMapHierarchy);
|
|
gHUD.ShowCrosshair();
|
|
}
|
|
}
|
|
|
|
void AvHHud::GetSpriteForUser3(AvHUser3 inUser3, int& outSprite, int& outFrame, int& outRenderMode)
|
|
{
|
|
|
|
switch (inUser3)
|
|
{
|
|
|
|
// Marines
|
|
case AVH_USER3_WAYPOINT:
|
|
outSprite = Safe_SPR_Load(kSmallOrderSprite);
|
|
outFrame = 2;
|
|
outRenderMode = kRenderTransAdd;
|
|
break;
|
|
case AVH_USER3_MARINE_PLAYER:
|
|
outSprite = Safe_SPR_Load(kMarinePlayersSprite);
|
|
outFrame = 0;
|
|
break;
|
|
case AVH_USER3_HEAVY: // This really means a marine with heavy armor, not a heavy armor object.
|
|
outSprite = Safe_SPR_Load(kMarinePlayersSprite);
|
|
outFrame = 1;
|
|
break;
|
|
case AVH_USER3_COMMANDER_STATION:
|
|
outSprite = Safe_SPR_Load(kStructuresSprite);
|
|
outFrame = 5;
|
|
break;
|
|
case AVH_USER3_TURRET_FACTORY:
|
|
case AVH_USER3_ADVANCED_TURRET_FACTORY:
|
|
outSprite = Safe_SPR_Load(kStructuresSprite);
|
|
outFrame = 6;
|
|
break;
|
|
case AVH_USER3_ARMORY:
|
|
outSprite = Safe_SPR_Load(kStructuresSprite);
|
|
outFrame = 7;
|
|
break;
|
|
case AVH_USER3_ADVANCED_ARMORY:
|
|
outSprite = Safe_SPR_Load(kStructuresSprite);
|
|
outFrame = 8;
|
|
break;
|
|
case AVH_USER3_ARMSLAB:
|
|
outSprite = Safe_SPR_Load(kStructuresSprite);
|
|
outFrame = 9;
|
|
break;
|
|
case AVH_USER3_PROTOTYPE_LAB:
|
|
outSprite = Safe_SPR_Load(kStructuresSprite);
|
|
outFrame = 10;
|
|
break;
|
|
case AVH_USER3_OBSERVATORY:
|
|
outSprite = Safe_SPR_Load(kStructuresSprite);
|
|
outFrame = 11;
|
|
break;
|
|
case AVH_USER3_TURRET:
|
|
outSprite = Safe_SPR_Load(kStructuresSprite);
|
|
outFrame = 12;
|
|
break;
|
|
case AVH_USER3_SIEGETURRET:
|
|
outSprite = Safe_SPR_Load(kStructuresSprite);
|
|
outFrame = 13;
|
|
break;
|
|
case AVH_USER3_RESTOWER:
|
|
outSprite = Safe_SPR_Load(kStructuresSprite);
|
|
outFrame = 14;
|
|
break;
|
|
case AVH_USER3_INFANTRYPORTAL:
|
|
outSprite = Safe_SPR_Load(kStructuresSprite);
|
|
outFrame = 15;
|
|
break;
|
|
case AVH_USER3_PHASEGATE:
|
|
outSprite = Safe_SPR_Load(kStructuresSprite);
|
|
outFrame = 16;
|
|
break;
|
|
|
|
// Aliens
|
|
case AVH_USER3_DEFENSE_CHAMBER:
|
|
outSprite = Safe_SPR_Load(kStructuresSprite);
|
|
outFrame = 17;
|
|
break;
|
|
case AVH_USER3_MOVEMENT_CHAMBER:
|
|
outSprite = Safe_SPR_Load(kStructuresSprite);
|
|
outFrame = 18;
|
|
break;
|
|
case AVH_USER3_OFFENSE_CHAMBER:
|
|
outSprite = Safe_SPR_Load(kStructuresSprite);
|
|
outFrame = 19;
|
|
break;
|
|
case AVH_USER3_SENSORY_CHAMBER:
|
|
outSprite = Safe_SPR_Load(kStructuresSprite);
|
|
outFrame = 20;
|
|
break;
|
|
case AVH_USER3_ALIENRESTOWER:
|
|
outSprite = Safe_SPR_Load(kStructuresSprite);
|
|
outFrame = 21;
|
|
break;
|
|
case AVH_USER3_HIVE:
|
|
outSprite = Safe_SPR_Load(kStructuresSprite);
|
|
outFrame = 3;
|
|
break;
|
|
case AVH_USER3_ALIEN_PLAYER1:
|
|
outSprite = Safe_SPR_Load(kAlienPlayersSprite);
|
|
outFrame = 0;
|
|
break;
|
|
case AVH_USER3_ALIEN_PLAYER2:
|
|
outSprite = Safe_SPR_Load(kAlienPlayersSprite);
|
|
outFrame = 1;
|
|
break;
|
|
case AVH_USER3_ALIEN_PLAYER3:
|
|
outSprite = Safe_SPR_Load(kAlienPlayersSprite);
|
|
outFrame = 2;
|
|
break;
|
|
case AVH_USER3_ALIEN_PLAYER4:
|
|
outSprite = Safe_SPR_Load(kAlienPlayersSprite);
|
|
outFrame = 3;
|
|
break;
|
|
case AVH_USER3_ALIEN_PLAYER5:
|
|
outSprite = Safe_SPR_Load(kAlienPlayersSprite);
|
|
outFrame = 4;
|
|
break;
|
|
case AVH_USER3_ALIEN_EMBRYO :
|
|
outSprite = Safe_SPR_Load(kAlienPlayersSprite);
|
|
outFrame = 5;
|
|
break;
|
|
|
|
case AVH_USER3_FUNC_RESOURCE:
|
|
outSprite = Safe_SPR_Load(kStructuresSprite);
|
|
outFrame = 4;
|
|
break;
|
|
case AVH_USER3_WELD:
|
|
outSprite = Safe_SPR_Load(kStructuresSprite);
|
|
outFrame = 0;
|
|
break;
|
|
|
|
default:
|
|
outSprite = 0;
|
|
outFrame = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
int AvHHud::GetCurrentSquad() const
|
|
{
|
|
return mCurrentSquad;
|
|
}
|
|
|
|
AvHOverviewMap& AvHHud::GetOverviewMap()
|
|
{
|
|
return mOverviewMap;
|
|
}
|
|
|
|
void AvHHud::ShowCrosshair()
|
|
{
|
|
|
|
++mCrosshairShowCount;
|
|
|
|
if (mCrosshairShowCount > 0)
|
|
{
|
|
SetCrosshair(mCrosshairSprite, mCrosshairRect, mCrosshairR, mCrosshairG, mCrosshairB);
|
|
}
|
|
|
|
}
|
|
|
|
void AvHHud::HideCrosshair()
|
|
{
|
|
|
|
--mCrosshairShowCount;
|
|
|
|
if (mCrosshairShowCount <= 0)
|
|
{
|
|
wrect_t nullrect = { 0, 0, 0, 0 };
|
|
SetCrosshair(0, nullrect, 0, 0, 0);
|
|
}
|
|
|
|
}
|
|
|
|
void AvHHud::SetCurrentCrosshair(HSPRITE hspr, wrect_t rc, int r, int g, int b)
|
|
{
|
|
mCrosshairSprite = hspr;
|
|
mCrosshairRect = rc;
|
|
mCrosshairR = r;
|
|
mCrosshairG = g;
|
|
mCrosshairB = b;
|
|
|
|
if (mCrosshairShowCount > 0)
|
|
{
|
|
SetCrosshair(mCrosshairSprite, mCrosshairRect, mCrosshairR, mCrosshairG, mCrosshairB);
|
|
}
|
|
|
|
}
|
|
|
|
void AvHHud::SetViewport(const int inViewport[4])
|
|
{
|
|
if (!m_Spectator.IsInOverviewMode())
|
|
{
|
|
mViewport[0] = inViewport[0];
|
|
mViewport[1] = inViewport[1];
|
|
mViewport[2] = inViewport[2];
|
|
mViewport[3] = inViewport[3];
|
|
}
|
|
else
|
|
{
|
|
mSpecialViewport[0] = inViewport[0];
|
|
mSpecialViewport[1] = inViewport[1];
|
|
mSpecialViewport[2] = inViewport[2];
|
|
mSpecialViewport[3] = inViewport[3];
|
|
|
|
mViewport[0] = 0;
|
|
mViewport[1] = 0;
|
|
mViewport[2] = ScreenWidth();
|
|
mViewport[3] = ScreenHeight();
|
|
|
|
}
|
|
}
|
|
|
|
void AvHHud::GetViewport(int outViewport[4]) const
|
|
{
|
|
outViewport[0] = mViewport[0];
|
|
outViewport[1] = mViewport[1];
|
|
outViewport[2] = mViewport[2];
|
|
outViewport[3] = mViewport[3];
|
|
}
|
|
|
|
const AvHFont& AvHHud::GetSmallFont() const
|
|
{
|
|
return mSmallFont;
|
|
}
|
|
|
|
void AvHHud::PlayStream()
|
|
{
|
|
if(gEngfuncs.Cmd_Argc() <= 1)
|
|
{
|
|
gEngfuncs.Con_Printf( "usage: playstream <url>\n" );
|
|
}
|
|
else
|
|
{
|
|
if ( gEngfuncs.Cmd_Argc() >= 2 )
|
|
{
|
|
// Read URL
|
|
string theURL;
|
|
theURL = string("http://") + string(gEngfuncs.Cmd_Argv(1));
|
|
|
|
string theError;
|
|
if(!gHUD.PlayInternetStream(theURL, theError))
|
|
{
|
|
gHUD.AddTooltip(theError.c_str());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void AvHHud::StopStream()
|
|
{
|
|
gHUD.StopInternetStream();
|
|
}
|
|
|
|
float AvHHud::GetServerVariableFloat(const char* inName) const
|
|
{
|
|
ServerVariableMapType::const_iterator iterator;
|
|
iterator = mServerVariableMap.find(inName);
|
|
|
|
if ( iterator == mServerVariableMap.end() )
|
|
{
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
return atof( iterator->second.c_str() );
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/**
|
|
* Prints the call stack when an unhandled exception occurs.
|
|
*/
|
|
LONG WINAPI ExceptionFilter(EXCEPTION_POINTERS* pExp)
|
|
{
|
|
|
|
/*
|
|
// E-mail the exception log to the programmers.
|
|
|
|
std::stringstream buffer;
|
|
LogException(buffer, pExp);
|
|
|
|
const char* serverName = "66.111.4.62";
|
|
const char* fromAddress = "noreply@overmind.com";
|
|
|
|
const char* programmerAddress[] =
|
|
{
|
|
"max_mcguire@yahoo.com",
|
|
};
|
|
|
|
for (int i = 0; i < sizeof(programmerAddress) / sizeof(char*); ++i)
|
|
{
|
|
SendMail(serverName, fromAddress, fromAddress, programmerAddress[i],
|
|
"Exception Log", buffer.str().c_str());
|
|
}
|
|
*/
|
|
|
|
AvHHud::ResetGammaAtExit();
|
|
|
|
return EXCEPTION_EXECUTE_HANDLER;
|
|
|
|
}
|
|
|
|
// Added DLL entry point to try to reset gamma properly under VAC
|
|
BOOL WINAPI DllMain(HINSTANCE hinstDLL,
|
|
DWORD fdwReason,
|
|
LPVOID lpvReserved)
|
|
{
|
|
if (fdwReason == DLL_PROCESS_ATTACH)
|
|
{
|
|
|
|
// Install a crash handler.
|
|
//SetUnhandledExceptionFilter(ExceptionFilter);
|
|
|
|
}
|
|
else if (fdwReason == DLL_PROCESS_DETACH)
|
|
{
|
|
AvHHud::ResetGammaAtExit();
|
|
}
|
|
return TRUE;
|
|
}
|