mirror of
https://github.com/ENSL/NS.git
synced 2024-11-15 09:21:54 +00:00
877b337309
o Fixed bug that made items on the popupmenu be disabled for aliens in classic games The bug was in AvHPlayer::UpdateTechNodes(), where the techs would not be set to researchable once flagged as unresearchable, causing them all to be unresearchable from the start of the game, and disallowing lifeforms after gestating to them. I also added a check so that the menu states won't be updated every frame for the client unless the menu is active. git-svn-id: https://unknownworlds.svn.cloudforge.com/ns1@262 67975925-1194-0748-b3d5-c16f83f1a3a1
7014 lines
189 KiB
C++
7014 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;
|
|
|
|
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");
|
|
}
|
|
|
|
// 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);
|
|
|
|
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;
|
|
}
|