diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 00000000..b9ed3f3b
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,93 @@
+###############################################################################
+# Set default behavior to automatically normalize line endings.
+###############################################################################
+main/source/**/* text=auto
+
+###############################################################################
+# Set the merge driver for project and solution files
+#
+# Merging from the command prompt will add diff markers to the files if there
+# are conflicts (Merging from VS is not affected by the settings below, in VS
+# the diff markers are never inserted). Diff markers may cause the following
+# file extensions to fail to load in VS. An alternative would be to treat
+# these files as binary and thus will always conflict and require user
+# intervention with every merge. To do so, just comment the entries below and
+# uncomment the group further below
+###############################################################################
+
+main/source/**/*.sln text eol=crlf
+main/source/**/*.csproj text eol=crlf
+main/source/**/*.vbproj text eol=crlf
+main/source/**/*.vcxproj text eol=crlf
+main/source/**/*.vcproj text eol=crlf
+main/source/**/*.dbproj text eol=crlf
+main/source/**/*.fsproj text eol=crlf
+main/source/**/*.lsproj text eol=crlf
+main/source/**/*.wixproj text eol=crlf
+main/source/**/*.modelproj text eol=crlf
+main/source/**/*.sqlproj text eol=crlf
+main/source/**/*.wmaproj text eol=crlf
+
+main/source/**/*.xproj text eol=crlf
+main/source/**/*.props text eol=crlf
+main/source/**/*.filters text eol=crlf
+main/source/**/*.vcxitems text eol=crlf
+
+
+#*.sln merge=binary
+#*.csproj merge=binary
+#*.vbproj merge=binary
+#*.vcxproj merge=binary
+#*.vcproj merge=binary
+#*.dbproj merge=binary
+#*.fsproj merge=binary
+#*.lsproj merge=binary
+#*.wixproj merge=binary
+#*.modelproj merge=binary
+#*.sqlproj merge=binary
+#*.wwaproj merge=binary
+
+#*.xproj merge=binary
+#*.props merge=binary
+#*.filters merge=binary
+#*.vcxitems merge=binary
+
+# C++ Stuff
+
+# sources
+main/source/**/*.c text
+main/source/**/*.cc text
+main/source/**/*.cxx text
+main/source/**/*.cpp text
+main/source/**/*.c++ text
+main/source/**/*.hpp text
+main/source/**/*.h text
+main/source/**/*.h++ text
+main/source/**/*.hh text
+
+# Compiled Object files
+*.slo binary
+*.lo binary
+*.o binary
+*.obj binary
+
+# Precompiled Headers
+*.gch binary
+*.pch binary
+
+# Compiled Dynamic libraries
+*.so binary
+*.dylib binary
+*.dll binary
+
+# Compiled Static libraries
+*.lai binary
+*.la binary
+*.a binary
+*.lib binary
+
+# Executables
+*.exe binary
+*.out binary
+*.app binary
+
diff --git a/.gitignore b/.gitignore
index 3d78a2bd..8c273b57 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,46 +1,51 @@
-# Compiled source #
-###################
-*.com
-*.class
-*.dll
-*.exe
-*.o
-*.so
-
-# Packages #
-############
-# it's better to unpack these files and commit the raw source
-# git has its own built in compression methods
-*.7z
-*.dmg
-*.gz
-*.iso
-*.jar
-*.rar
-*.tar
-*.zip
-
-# Logs and databases #
-######################
-*.log
-*.sql
-*.sqlite
-
-# OS generated files #
-######################
-.DS_Store
-.DS_Store?
-._*
-.Spotlight-V100
-.Trashes
-ehthumbs.db
-Thumbs.db
-
-# Visual Studio #
-#################
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+
+# User-specific files
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+bld/
+[Bb]in/
+[Oo]bj/
+
+# Visual Studio 2015 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUNIT
+*.VisualState.xml
+TestResult.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# DNX
+project.lock.json
+artifacts/
*_i.c
*_p.c
+*_i.h
*.ilk
*.meta
*.obj
@@ -61,13 +66,179 @@ Thumbs.db
*.vssscc
.builds
*.pidb
-*.log
+*.svclog
*.scc
-*.wav
-*.XML
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# JustCode is a .NET coding add-in
+.JustCode
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# TODO: Comment the next line if you want to checkin your web deploy settings
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# NuGet Packages
+*.nupkg
+# The packages folder can be ignored because of Package Restore
+**/packages/*
+# except build/, which is used as an MSBuild target.
+!**/packages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/packages/repositories.config
+# NuGet v3's project.json files produces more ignoreable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Microsoft Azure ApplicationInsights config file
+ApplicationInsights.config
+
+# Windows Store app package directory
+AppPackages/
+BundleArtifacts/
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.pfx
+*.publishsettings
+node_modules/
+orleans.codegen.cs
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+
+# SQL Server files
+*.mdf
+*.ldf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+
+# FAKE - F# Make
+.fake/
# Add include dir #
###################
!main/source/includes/
+
diff --git a/main/source/HPB_bot.sln b/main/source/HPB_bot.sln
index 2181a55a..a9ab843e 100644
--- a/main/source/HPB_bot.sln
+++ b/main/source/HPB_bot.sln
@@ -1,21 +1,21 @@
-Microsoft Visual Studio Solution File, Format Version 8.00
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HPB_bot", "HPB_bot\dlls\HPB_bot.vcproj", "{4D2D2333-4ACF-44B3-925C-1625FC8EFEA8}"
- ProjectSection(ProjectDependencies) = postProject
- EndProjectSection
-EndProject
-Global
- GlobalSection(SolutionConfiguration) = preSolution
- Debug = Debug
- Release = Release
- EndGlobalSection
- GlobalSection(ProjectConfiguration) = postSolution
- {4D2D2333-4ACF-44B3-925C-1625FC8EFEA8}.Debug.ActiveCfg = Debug|Win32
- {4D2D2333-4ACF-44B3-925C-1625FC8EFEA8}.Debug.Build.0 = Debug|Win32
- {4D2D2333-4ACF-44B3-925C-1625FC8EFEA8}.Release.ActiveCfg = Release|Win32
- {4D2D2333-4ACF-44B3-925C-1625FC8EFEA8}.Release.Build.0 = Release|Win32
- EndGlobalSection
- GlobalSection(ExtensibilityGlobals) = postSolution
- EndGlobalSection
- GlobalSection(ExtensibilityAddIns) = postSolution
- EndGlobalSection
-EndGlobal
+Microsoft Visual Studio Solution File, Format Version 8.00
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HPB_bot", "HPB_bot\dlls\HPB_bot.vcproj", "{4D2D2333-4ACF-44B3-925C-1625FC8EFEA8}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfiguration) = preSolution
+ Debug = Debug
+ Release = Release
+ EndGlobalSection
+ GlobalSection(ProjectConfiguration) = postSolution
+ {4D2D2333-4ACF-44B3-925C-1625FC8EFEA8}.Debug.ActiveCfg = Debug|Win32
+ {4D2D2333-4ACF-44B3-925C-1625FC8EFEA8}.Debug.Build.0 = Debug|Win32
+ {4D2D2333-4ACF-44B3-925C-1625FC8EFEA8}.Release.ActiveCfg = Release|Win32
+ {4D2D2333-4ACF-44B3-925C-1625FC8EFEA8}.Release.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ EndGlobalSection
+ GlobalSection(ExtensibilityAddIns) = postSolution
+ EndGlobalSection
+EndGlobal
diff --git a/main/source/HPB_bot/dlls/HPB_bot.def b/main/source/HPB_bot/dlls/HPB_bot.def
index e3e89fda..4bccf81b 100644
--- a/main/source/HPB_bot/dlls/HPB_bot.def
+++ b/main/source/HPB_bot/dlls/HPB_bot.def
@@ -1,5 +1,5 @@
-LIBRARY HPB_bot
-EXPORTS
- GiveFnptrsToDll @1
-SECTIONS
- .data READ WRITE
+LIBRARY HPB_bot
+EXPORTS
+ GiveFnptrsToDll @1
+SECTIONS
+ .data READ WRITE
diff --git a/main/source/HPB_bot/dlls/HPB_bot.vcproj b/main/source/HPB_bot/dlls/HPB_bot.vcproj
index f1bd37ac..eb944285 100644
--- a/main/source/HPB_bot/dlls/HPB_bot.vcproj
+++ b/main/source/HPB_bot/dlls/HPB_bot.vcproj
@@ -1,394 +1,394 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/main/source/HPB_bot/dlls/bot.cpp b/main/source/HPB_bot/dlls/bot.cpp
index 5c8afe29..8601f530 100644
--- a/main/source/HPB_bot/dlls/bot.cpp
+++ b/main/source/HPB_bot/dlls/bot.cpp
@@ -1,2087 +1,2087 @@
-//
-// HPB bot - botman's High Ping Bastard bot
-//
-// (http://planethalflife.com/botman/)
-//
-// bot.cpp
-//
-
-//#include "windows.h"
-#include "dlls/extdll.h"
-#include "dlls/util.h"
-#include "dlls/cbase.h"
-
-#include "bot.h"
-#include "bot_func.h"
-#include "waypoint.h"
-#include "bot_weapons.h"
-
-#include
-#include
-#include "mod/AvHMarineEquipmentConstants.h"
-#include "mod/AvHMessage.h"
-#include "mod/AvHCommandConstants.h"
-#include "mod/AvHMessage.h"
-#include "mod/AvHPlayer.h"
-
-#ifndef __linux__
-extern HINSTANCE h_Library;
-#else
-extern void *h_Library;
-#endif
-
-
-extern int mod_id;
-extern WAYPOINT waypoints[MAX_WAYPOINTS];
-extern int num_waypoints; // number of waypoints currently in use
-extern int default_bot_skill;
-extern edict_t *pent_info_ctfdetect;
-
-extern int max_team_players[4];
-extern int team_class_limits[4];
-extern int max_teams;
-extern char bot_whine[MAX_BOT_WHINE][81];
-extern int whine_count;
-
-extern int flf_bug_fix;
-
-static FILE *fp;
-
-
-#define PLAYER_SEARCH_RADIUS 40.0
-#define FLF_PLAYER_SEARCH_RADIUS 60.0
-
-
-bot_t bots[32]; // max of 32 bots in a game
-bool b_observer_mode = FALSE;
-bool b_botdontshoot = FALSE;
-
-extern int recent_bot_whine[5];
-
-int number_names = 0;
-
-#define MAX_BOT_NAMES 100
-
-#define VALVE_MAX_SKINS 10
-#define GEARBOX_MAX_SKINS 20
-
-// indicate which models are currently used for random model allocation
-bool valve_skin_used[VALVE_MAX_SKINS] = {
- FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE};
-
-bool gearbox_skin_used[GEARBOX_MAX_SKINS] = {
- FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
- FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE};
-
-// store the names of the models...
-char *valve_bot_skins[VALVE_MAX_SKINS] = {
- "barney", "gina", "gman", "gordon", "helmet",
- "hgrunt", "recon", "robo", "scientist", "zombie"};
-
-char *gearbox_bot_skins[GEARBOX_MAX_SKINS] = {
- "barney", "beret", "cl_suit", "drill", "fassn", "gina", "gman",
- "gordon", "grunt", "helmet", "hgrunt", "massn", "otis", "recon",
- "recruit", "robo", "scientist", "shepard", "tower", "zombie"};
-
-// store the player names for each of the models...
-char *valve_bot_names[VALVE_MAX_SKINS] = {
- "Barney", "Gina", "G-Man", "Gordon", "Helmet",
- "H-Grunt", "Recon", "Robo", "Scientist", "Zombie"};
-
-char *gearbox_bot_names[GEARBOX_MAX_SKINS] = {
- "Barney", "Beret", "Cl_suit", "Drill", "Fassn", "Gina", "G-Man",
- "Gordon", "Grunt", "Helmet", "H-Grunt", "Massn", "Otis", "Recon",
- "Recruit", "Robo", "Scientist", "Shepard", "Tower", "Zombie"};
-
-char bot_names[MAX_BOT_NAMES][BOT_NAME_LEN+1];
-
-// how often (out of 1000 times) the bot will pause, based on bot skill
-float pause_frequency[5] = {4, 7, 10, 15, 20};
-
-float pause_time[5][2] = {
- {0.2, 0.5}, {0.5, 1.0}, {0.7, 1.3}, {1.0, 1.7}, {1.2, 2.0}};
-
-
-inline edict_t *CREATE_FAKE_CLIENT( const char *netname )
-{
- return (*g_engfuncs.pfnCreateFakeClient)( netname );
-}
-
-inline char *GET_INFOBUFFER( edict_t *e )
-{
- return (*g_engfuncs.pfnGetInfoKeyBuffer)( e );
-}
-
-inline char *GET_INFO_KEY_VALUE( char *infobuffer, char *key )
-{
- return (g_engfuncs.pfnInfoKeyValue( infobuffer, key ));
-}
-
-inline void SET_CLIENT_KEY_VALUE( int clientIndex, char *infobuffer,
- char *key, char *value )
-{
- (*g_engfuncs.pfnSetClientKeyValue)( clientIndex, infobuffer, key, value );
-}
-
-
-// this is the LINK_ENTITY_TO_CLASS function that creates a player (bot)
-void player( entvars_t *pev )
-{
- static LINK_ENTITY_FUNC otherClassName = NULL;
- if (otherClassName == NULL)
- otherClassName = (LINK_ENTITY_FUNC)GetProcAddress(h_Library, "player");
- if (otherClassName != NULL)
- {
- (*otherClassName)(pev);
- }
-}
-
-void BotProcessVoiceCommands(bot_t* pBot)
-{
- if((pBot->mTimeOfNextOrderRequest != -1) && (gpGlobals->time > pBot->mTimeOfNextOrderRequest))
- {
- if(pBot->pEdict->v.impulse == 0)
- {
- pBot->pEdict->v.impulse = ORDER_REQUEST;
- pBot->mTimeOfNextOrderRequest = -1;
- }
- }
- if((pBot->mTimeOfNextAmmoRequest != -1) && (gpGlobals->time > pBot->mTimeOfNextAmmoRequest))
- {
- if(pBot->pEdict->v.impulse == 0)
- {
- pBot->pEdict->v.impulse = SAYING_5;
- pBot->mTimeOfNextAmmoRequest = -1;
- }
- }
- if((pBot->mTimeOfNextRandomSaying != -1) && (gpGlobals->time > pBot->mTimeOfNextRandomSaying))
- {
- if(pBot->pEdict->v.impulse == 0)
- {
- pBot->pEdict->v.impulse = SAYING_1 + g_engfuncs.pfnRandomLong(0, 5);
- pBot->mTimeOfNextRandomSaying = -1;
- }
- }
- if((pBot->mTimeOfNextTaunt != -1) && (gpGlobals->time > pBot->mTimeOfNextTaunt))
- {
- if(pBot->pEdict->v.impulse == 0)
- {
- pBot->pEdict->v.impulse = SAYING_3;
- pBot->mTimeOfNextTaunt = -1;
- }
- }
- if((pBot->mTimeOfNextAcknowledge != -1) && (gpGlobals->time > pBot->mTimeOfNextAcknowledge))
- {
- if(pBot->pEdict->v.impulse == 0)
- {
- pBot->pEdict->v.impulse = ORDER_ACK;
- pBot->mTimeOfNextAcknowledge = -1;
- }
- }
-}
-
-void BotSpawnInit( bot_t *pBot )
-{
- pBot->v_prev_origin = Vector(9999.0, 9999.0, 9999.0);
- pBot->prev_time = gpGlobals->time;
-
- pBot->waypoint_origin = Vector(0, 0, 0);
- pBot->f_waypoint_time = 0.0;
- pBot->curr_waypoint_index = -1;
- pBot->prev_waypoint_index[0] = -1;
- pBot->prev_waypoint_index[1] = -1;
- pBot->prev_waypoint_index[2] = -1;
- pBot->prev_waypoint_index[3] = -1;
- pBot->prev_waypoint_index[4] = -1;
-
- pBot->f_random_waypoint_time = gpGlobals->time;
- pBot->waypoint_goal = -1;
- pBot->f_waypoint_goal_time = 0.0;
- pBot->waypoint_near_flag = FALSE;
- pBot->waypoint_flag_origin = Vector(0, 0, 0);
- pBot->prev_waypoint_distance = 0.0;
-
- pBot->msecnum = 0;
- pBot->msecdel = 0.0;
- pBot->msecval = 0.0;
-
- pBot->bot_health = 0;
- pBot->bot_armor = 0;
- pBot->bot_weapons = 0;
- pBot->blinded_time = 0.0;
-
- // Init AvH variables
- pBot->mBotPlayMode = PLAYMODE_READYROOM;
-
- pBot->mOrderState = 0;
- pBot->mOrderNumPlayers = -1;
- pBot->mOrderType = ORDERTYPE_UNDEFINED;
- pBot->mOrderTargetType = ORDERTARGETTYPE_UNDEFINED;
- pBot->mOrderLocation[0] = pBot->mOrderLocation[1] = pBot->mOrderLocation[2] = 0.0f;
- pBot->mOrderTargetIndex = -1;
- pBot->mOrderCompleted = false;
-
- pBot->mTimeOfNextAcknowledge = -1;
- pBot->mTimeOfNextAmmoRequest = -1;
- pBot->mTimeOfNextOrderRequest = -1;
- pBot->mTimeOfNextTaunt = -1;
- pBot->mTimeOfNextRandomSaying = -1;
-
- pBot->mGestateUser3 = AVH_USER3_NONE;
- pBot->mResources = 0;
- // end AvH variable init
-
- pBot->f_max_speed = CVAR_GET_FLOAT("sv_maxspeed");
-
- pBot->prev_speed = 0.0; // fake "paused" since bot is NOT stuck
-
- pBot->f_find_item = 0.0;
-
- pBot->ladder_dir = LADDER_UNKNOWN;
- pBot->f_start_use_ladder_time = 0.0;
- pBot->f_end_use_ladder_time = 0.0;
- pBot->waypoint_top_of_ladder = FALSE;
-
- pBot->f_wall_check_time = 0.0;
- pBot->f_wall_on_right = 0.0;
- pBot->f_wall_on_left = 0.0;
- pBot->f_dont_avoid_wall_time = 0.0;
- pBot->f_look_for_waypoint_time = 0.0;
- pBot->f_jump_time = 0.0;
- pBot->f_dont_check_stuck = 0.0;
-
- // pick a wander direction (50% of the time to the left, 50% to the right)
- if (RANDOM_LONG(1, 100) <= 50)
- pBot->wander_dir = WANDER_LEFT;
- else
- pBot->wander_dir = WANDER_RIGHT;
-
- pBot->f_exit_water_time = 0.0;
-
- pBot->pBotEnemy = NULL;
- pBot->f_bot_see_enemy_time = gpGlobals->time;
- pBot->f_bot_find_enemy_time = gpGlobals->time;
- pBot->pBotUser = NULL;
- pBot->f_bot_use_time = 0.0;
- pBot->b_bot_say_killed = FALSE;
- pBot->f_bot_say_killed = 0.0;
- pBot->f_sniper_aim_time = 0.0;
-
- pBot->f_shoot_time = gpGlobals->time;
- pBot->f_primary_charging = -1.0;
- pBot->f_secondary_charging = -1.0;
- pBot->charging_weapon_id = 0;
-
- pBot->f_pause_time = 0.0;
- pBot->f_sound_update_time = 0.0;
- pBot->bot_has_flag = FALSE;
-
- pBot->b_see_tripmine = FALSE;
- pBot->b_shoot_tripmine = FALSE;
- pBot->v_tripmine = Vector(0,0,0);
-
- pBot->b_use_health_station = FALSE;
- pBot->f_use_health_time = 0.0;
- pBot->b_use_HEV_station = FALSE;
- pBot->f_use_HEV_time = 0.0;
-
- pBot->b_use_button = FALSE;
- pBot->f_use_button_time = 0;
- pBot->b_lift_moving = FALSE;
-
- pBot->b_use_capture = FALSE;
- pBot->f_use_capture_time = 0.0;
- pBot->pCaptureEdict = NULL;
-
- memset(&(pBot->current_weapon), 0, sizeof(pBot->current_weapon));
- memset(&(pBot->m_rgAmmo), 0, sizeof(pBot->m_rgAmmo));
-}
-
-
-void BotNameInit( void )
-{
- FILE *bot_name_fp;
- char bot_name_filename[256];
- int str_index;
- char name_buffer[80];
- int length, index;
-
- UTIL_BuildFileName(bot_name_filename, "bot_names.txt", NULL);
-
- bot_name_fp = fopen(bot_name_filename, "r");
-
- if (bot_name_fp != NULL)
- {
- while ((number_names < MAX_BOT_NAMES) &&
- (fgets(name_buffer, 80, bot_name_fp) != NULL))
- {
- length = strlen(name_buffer);
-
- if (name_buffer[length-1] == '\n')
- {
- name_buffer[length-1] = 0; // remove '\n'
- length--;
- }
-
- str_index = 0;
- while (str_index < length)
- {
- if ((name_buffer[str_index] < ' ') || (name_buffer[str_index] > '~') ||
- (name_buffer[str_index] == '"'))
- for (index=str_index; index < length; index++)
- name_buffer[index] = name_buffer[index+1];
-
- str_index++;
- }
-
- if (name_buffer[0] != 0)
- {
- strncpy(bot_names[number_names], name_buffer, BOT_NAME_LEN);
-
- number_names++;
- }
- }
-
- fclose(bot_name_fp);
- }
-}
-
-
-void BotPickName( char *name_buffer )
-{
- int name_index, index;
- bool used;
- edict_t *pPlayer;
- int attempts = 0;
-
- // see if a name exists from a kicked bot (if so, reuse it)
- for (index=0; index < 32; index++)
- {
- if ((bots[index].is_used == FALSE) && (bots[index].name[0]))
- {
- strcpy(name_buffer, bots[index].name);
-
- return;
- }
- }
-
- name_index = RANDOM_LONG(1, number_names) - 1; // zero based
-
- // check make sure this name isn't used
- used = TRUE;
-
- while (used)
- {
- used = FALSE;
-
- for (index = 1; index <= gpGlobals->maxClients; index++)
- {
- pPlayer = INDEXENT(index);
-
- if (pPlayer && !pPlayer->free)
- {
- if (strcmp(bot_names[name_index], STRING(pPlayer->v.netname)) == 0)
- {
- used = TRUE;
- break;
- }
- }
- }
-
- if (used)
- {
- name_index++;
-
- if (name_index == number_names)
- name_index = 0;
-
- attempts++;
-
- if (attempts == number_names)
- used = FALSE; // break out of loop even if already used
- }
- }
-
- strcpy(name_buffer, bot_names[name_index]);
-}
-
-
-void BotCreate( edict_t *pPlayer, const char *arg1, const char *arg2,
- const char *arg3, const char *arg4)
-{
- edict_t *BotEnt;
- bot_t *pBot;
- char c_skin[BOT_SKIN_LEN+1];
- char c_name[BOT_NAME_LEN+1];
- int skill;
- int index;
- int i, j, length;
- bool found = FALSE;
-
-
- if ((mod_id == VALVE_DLL) ||
- ((mod_id == GEARBOX_DLL) && (pent_info_ctfdetect == NULL)))
- {
- int max_skin_index;
-
- if (mod_id == VALVE_DLL)
- max_skin_index = VALVE_MAX_SKINS;
- else // must be GEARBOX_DLL
- max_skin_index = GEARBOX_MAX_SKINS;
-
- if ((arg1 == NULL) || (*arg1 == 0))
- {
- bool *pSkinUsed;
-
- // pick a random skin
- if (mod_id == VALVE_DLL)
- {
- index = RANDOM_LONG(0, VALVE_MAX_SKINS-1);
- pSkinUsed = &valve_skin_used[0];
- }
- else // must be GEARBOX_DLL
- {
- index = RANDOM_LONG(0, GEARBOX_MAX_SKINS-1);
- pSkinUsed = &gearbox_skin_used[0];
- }
-
- // check if this skin has already been used...
- while (pSkinUsed[index] == TRUE)
- {
- index++;
-
- if (index == max_skin_index)
- index = 0;
- }
-
- pSkinUsed[index] = TRUE;
-
- // check if all skins are now used...
- for (i = 0; i < max_skin_index; i++)
- {
- if (pSkinUsed[i] == FALSE)
- break;
- }
-
- // if all skins are used, reset used to FALSE for next selection
- if (i == max_skin_index)
- {
- for (i = 0; i < max_skin_index; i++)
- pSkinUsed[i] = FALSE;
- }
-
- if (mod_id == VALVE_DLL)
- strcpy( c_skin, valve_bot_skins[index] );
- else // must be GEARBOX_DLL
- strcpy( c_skin, gearbox_bot_skins[index] );
- }
- else
- {
- strncpy( c_skin, arg1, BOT_SKIN_LEN-1 );
- c_skin[BOT_SKIN_LEN] = 0; // make sure c_skin is null terminated
- }
-
- for (i = 0; c_skin[i] != 0; i++)
- c_skin[i] = tolower( c_skin[i] ); // convert to all lowercase
-
- index = 0;
-
- while ((!found) && (index < max_skin_index))
- {
- if (mod_id == VALVE_DLL)
- {
- if (strcmp(c_skin, valve_bot_skins[index]) == 0)
- found = TRUE;
- else
- index++;
- }
- else // must be GEARBOX_DLL
- {
- if (strcmp(c_skin, gearbox_bot_skins[index]) == 0)
- found = TRUE;
- else
- index++;
- }
- }
-
- if (found == TRUE)
- {
- if ((arg2 != NULL) && (*arg2 != 0))
- {
- strncpy( c_name, arg2, BOT_SKIN_LEN-1 );
- c_name[BOT_SKIN_LEN] = 0; // make sure c_name is null terminated
- }
- else
- {
- if (number_names > 0)
- BotPickName( c_name );
- else if (mod_id == VALVE_DLL)
- strcpy( c_name, valve_bot_names[index] );
- else // must be GEARBOX_DLL
- strcpy( c_name, gearbox_bot_names[index] );
- }
- }
- else
- {
- char dir_name[32];
- char filename[128];
-
- struct stat stat_str;
-
- GET_GAME_DIR(dir_name);
-
-#ifndef __linux__
- sprintf(filename, "%s\\models\\player\\%s", dir_name, c_skin);
-#else
- sprintf(filename, "%s/models/player/%s", dir_name, c_skin);
-#endif
-
- if (stat(filename, &stat_str) != 0)
- {
-#ifndef __linux__
- sprintf(filename, "valve\\models\\player\\%s", c_skin);
-#else
- sprintf(filename, "valve/models/player/%s", c_skin);
-#endif
- if (stat(filename, &stat_str) != 0)
- {
- char err_msg[80];
-
- sprintf( err_msg, "model \"%s\" is unknown.\n", c_skin );
- if (pPlayer)
- ClientPrint(pPlayer, HUD_PRINTNOTIFY, err_msg );
- if (IS_DEDICATED_SERVER())
- printf(err_msg);
-
- if (pPlayer)
- ClientPrint(pPlayer, HUD_PRINTNOTIFY,
- "use barney, gina, gman, gordon, helmet, hgrunt,\n");
- if (IS_DEDICATED_SERVER())
- printf("use barney, gina, gman, gordon, helmet, hgrunt,\n");
- if (pPlayer)
- ClientPrint(pPlayer, HUD_PRINTNOTIFY,
- " recon, robo, scientist, or zombie\n");
- if (IS_DEDICATED_SERVER())
- printf(" recon, robo, scientist, or zombie\n");
- return;
- }
- }
-
- if ((arg2 != NULL) && (*arg2 != 0))
- {
- strncpy( c_name, arg2, BOT_NAME_LEN-1 );
- c_name[BOT_NAME_LEN] = 0; // make sure c_name is null terminated
- }
- else
- {
- if (number_names > 0)
- BotPickName( c_name );
- else
- {
- // copy the name of the model to the bot's name...
- strncpy( c_name, arg1, BOT_NAME_LEN-1 );
- c_name[BOT_NAME_LEN] = 0; // make sure c_skin is null terminated
- }
- }
- }
-
- skill = 0;
-
- if ((arg3 != NULL) && (*arg3 != 0))
- skill = atoi(arg3);
-
- if ((skill < 1) || (skill > 5))
- skill = default_bot_skill;
- }
- else
- {
- if ((arg3 != NULL) && (*arg3 != 0))
- {
- strncpy( c_name, arg3, BOT_NAME_LEN-1 );
- c_name[BOT_NAME_LEN] = 0; // make sure c_name is null terminated
- }
- else
- {
- if (number_names > 0)
- BotPickName( c_name );
- else
- strcpy(c_name, "Bot");
- }
-
- skill = 0;
-
- if ((arg4 != NULL) && (*arg4 != 0))
- skill = atoi(arg4);
-
- if ((skill < 1) || (skill > 5))
- skill = default_bot_skill;
- }
-
- length = strlen(c_name);
-
- // remove any illegal characters from name...
- for (i = 0; i < length; i++)
- {
- if ((c_name[i] <= ' ') || (c_name[i] > '~') ||
- (c_name[i] == '"'))
- {
- for (j = i; j < length; j++) // shuffle chars left (and null)
- c_name[j] = c_name[j+1];
- length--;
- }
- }
-
- BotEnt = CREATE_FAKE_CLIENT( c_name );
-
- if (FNullEnt( BotEnt ))
- {
- if (pPlayer)
- ClientPrint( pPlayer, HUD_PRINTNOTIFY, "Max. Players reached. Can't create bot!\n");
- }
- else
- {
- char ptr[128]; // allocate space for message from ClientConnect
- char *infobuffer;
- int clientIndex;
- int index;
-
- if (IS_DEDICATED_SERVER())
- printf("Creating bot...\n");
- else if (pPlayer)
- ClientPrint( pPlayer, HUD_PRINTNOTIFY, "Creating bot...\n");
-
- index = 0;
- while ((bots[index].is_used) && (index < 32))
- index++;
-
- if (index == 32)
- {
- ClientPrint( pPlayer, HUD_PRINTNOTIFY, "Can't create bot!\n");
- return;
- }
-
- // create the player entity by calling MOD's player function
- // (from LINK_ENTITY_TO_CLASS for player object)
-
- player( VARS(BotEnt) );
-
- infobuffer = GET_INFOBUFFER( BotEnt );
- clientIndex = ENTINDEX( BotEnt );
-
-
- if ((mod_id == VALVE_DLL) || (mod_id == GEARBOX_DLL))
- SET_CLIENT_KEY_VALUE( clientIndex, infobuffer, "model", c_skin );
- else // other mods
- SET_CLIENT_KEY_VALUE( clientIndex, infobuffer, "model", "gina" );
-
- if (mod_id == CSTRIKE_DLL)
- {
- SET_CLIENT_KEY_VALUE( clientIndex, infobuffer, "rate", "3500.000000");
- SET_CLIENT_KEY_VALUE( clientIndex, infobuffer, "cl_updaterate", "20");
- SET_CLIENT_KEY_VALUE( clientIndex, infobuffer, "cl_lw", "1");
- SET_CLIENT_KEY_VALUE( clientIndex, infobuffer, "cl_lc", "1");
- SET_CLIENT_KEY_VALUE( clientIndex, infobuffer, "tracker", "0");
- SET_CLIENT_KEY_VALUE( clientIndex, infobuffer, "cl_dlmax", "128");
- SET_CLIENT_KEY_VALUE( clientIndex, infobuffer, "lefthand", "1");
- SET_CLIENT_KEY_VALUE( clientIndex, infobuffer, "friends", "0");
- SET_CLIENT_KEY_VALUE( clientIndex, infobuffer, "dm", "0");
- SET_CLIENT_KEY_VALUE( clientIndex, infobuffer, "ah", "1");
- }
-
- ClientConnect( BotEnt, c_name, "127.0.0.1", ptr );
-
- // Pieter van Dijk - use instead of DispatchSpawn() - Hip Hip Hurray!
- ClientPutInServer( BotEnt );
-
- BotEnt->v.flags |= FL_FAKECLIENT;
-
- // initialize all the variables for this bot...
-
- pBot = &bots[index];
-
- pBot->is_used = TRUE;
- pBot->respawn_state = RESPAWN_IDLE;
- pBot->create_time = gpGlobals->time;
- pBot->name[0] = 0; // name not set by server yet
- pBot->bot_money = 0;
-
- strcpy(pBot->skin, c_skin);
-
- pBot->pEdict = BotEnt;
-
- pBot->not_started = 1; // hasn't joined game yet
-
- if (mod_id == TFC_DLL)
- pBot->start_action = MSG_TFC_IDLE;
- else if (mod_id == CSTRIKE_DLL)
- pBot->start_action = MSG_CS_IDLE;
- else if ((mod_id == GEARBOX_DLL) && (pent_info_ctfdetect != NULL))
- pBot->start_action = MSG_OPFOR_IDLE;
- else if (mod_id == FRONTLINE_DLL)
- pBot->start_action = MSG_FLF_IDLE;
- else if (mod_id == AVH_DLL)
- pBot->start_action = MSG_AVH_IDLE;
- else
- pBot->start_action = 0; // not needed for non-team MODs
-
-
- BotSpawnInit(pBot);
-
- pBot->need_to_initialize = FALSE; // don't need to initialize yet
-
- BotEnt->v.idealpitch = BotEnt->v.v_angle.x;
- BotEnt->v.ideal_yaw = BotEnt->v.v_angle.y;
- BotEnt->v.pitch_speed = BOT_PITCH_SPEED;
- BotEnt->v.yaw_speed = BOT_YAW_SPEED;
-
- pBot->warmup = 0; // for Front Line Force
- pBot->idle_angle = 0.0;
- pBot->idle_angle_time = 0.0;
- pBot->round_end = 0;
- pBot->defender = 0;
-
- pBot->bot_skill = skill - 1; // 0 based for array indexes
-
- pBot->bot_team = -1;
- pBot->bot_class = -1;
-
- if ((mod_id == TFC_DLL) || (mod_id == CSTRIKE_DLL) ||
- ((mod_id == GEARBOX_DLL) && (pent_info_ctfdetect != NULL)) ||
- (mod_id == FRONTLINE_DLL))
- {
- if ((arg1 != NULL) && (arg1[0] != 0))
- {
- pBot->bot_team = atoi(arg1);
-
- if ((arg2 != NULL) && (arg2[0] != 0))
- {
- pBot->bot_class = atoi(arg2);
- }
- }
- }
- }
-}
-
-
-int BotInFieldOfView(bot_t *pBot, Vector dest)
-{
- // find angles from source to destination...
- Vector entity_angles = UTIL_VecToAngles( dest );
-
- // make yaw angle 0 to 360 degrees if negative...
- if (entity_angles.y < 0)
- entity_angles.y += 360;
-
- // get bot's current view angle...
- float view_angle = pBot->pEdict->v.v_angle.y;
-
- // make view angle 0 to 360 degrees if negative...
- if (view_angle < 0)
- view_angle += 360;
-
- // return the absolute value of angle to destination entity
- // zero degrees means straight ahead, 45 degrees to the left or
- // 45 degrees to the right is the limit of the normal view angle
-
- // rsm - START angle bug fix
- int angle = abs((int)view_angle - (int)entity_angles.y);
-
- if (angle > 180)
- angle = 360 - angle;
-
- return angle;
- // rsm - END
-}
-
-
-bool BotEntityIsVisible( bot_t *pBot, Vector dest )
-{
- TraceResult tr;
-
- // trace a line from bot's eyes to destination...
- UTIL_TraceLine( pBot->pEdict->v.origin + pBot->pEdict->v.view_ofs,
- dest, ignore_monsters,
- pBot->pEdict->v.pContainingEntity, &tr );
-
- // check if line of sight to object is not blocked (i.e. visible)
- if (tr.flFraction >= 1.0)
- return TRUE;
- else
- return FALSE;
-}
-
-
-void BotFindItem( bot_t *pBot )
-{
- edict_t *pent = NULL;
- edict_t *pPickupEntity = NULL;
- Vector pickup_origin;
- Vector entity_origin;
- float radius = 500;
- bool can_pickup;
- float min_distance;
- char item_name[40];
- TraceResult tr;
- Vector vecStart;
- Vector vecEnd;
- int angle_to_entity;
- edict_t *pEdict = pBot->pEdict;
-
- pBot->pBotPickupItem = NULL;
-
- // use a MUCH smaller search radius when waypoints are available
- if ((num_waypoints > 0) && (pBot->curr_waypoint_index != -1))
- radius = 100.0;
- else
- radius = 500.0;
-
- min_distance = radius + 1.0;
-
- while ((pent = UTIL_FindEntityInSphere( pent, pEdict->v.origin, radius )) != NULL)
- {
- can_pickup = FALSE; // assume can't use it until known otherwise
-
- strcpy(item_name, STRING(pent->v.classname));
-
- // see if this is a "func_" type of entity (func_button, etc.)...
- if (strncmp("func_", item_name, 5) == 0)
- {
- // BModels have 0,0,0 for origin so must use VecBModelOrigin...
- entity_origin = VecBModelOrigin(pent);
-
- vecStart = pEdict->v.origin + pEdict->v.view_ofs;
- vecEnd = entity_origin;
-
- angle_to_entity = BotInFieldOfView( pBot, vecEnd - vecStart );
-
- // check if entity is outside field of view (+/- 45 degrees)
- if (angle_to_entity > 45)
- continue; // skip this item if bot can't "see" it
-
- // check if entity is a ladder (ladders are a special case)
- // DON'T search for ladders if there are waypoints in this level...
- if ((strcmp("func_ladder", item_name) == 0) && (num_waypoints == 0))
- {
- // force ladder origin to same z coordinate as bot since
- // the VecBModelOrigin is the center of the ladder. For
- // LONG ladders, the center MAY be hundreds of units above
- // the bot. Fake an origin at the same level as the bot...
-
- entity_origin.z = pEdict->v.origin.z;
- vecEnd = entity_origin;
-
- // trace a line from bot's eyes to func_ladder entity...
- UTIL_TraceLine( vecStart, vecEnd, dont_ignore_monsters,
- pEdict->v.pContainingEntity, &tr);
-
- // check if traced all the way up to the entity (didn't hit wall)
- if (tr.flFraction >= 1.0)
- {
- // find distance to item for later use...
- float distance = (vecEnd - vecStart).Length( );
-
- // use the ladder about 100% of the time, if haven't
- // used a ladder in at least 5 seconds...
- if ((RANDOM_LONG(1, 100) <= 100) &&
- ((pBot->f_end_use_ladder_time + 5.0) < gpGlobals->time))
- {
- // if close to ladder...
- if (distance < 100)
- {
- // don't avoid walls for a while
- pBot->f_dont_avoid_wall_time = gpGlobals->time + 5.0;
- }
-
- can_pickup = TRUE;
- }
- }
- }
- else
- {
- // trace a line from bot's eyes to func_ entity...
- UTIL_TraceLine( vecStart, vecEnd, dont_ignore_monsters,
- pEdict->v.pContainingEntity, &tr);
-
- // check if traced all the way up to the entity (didn't hit wall)
- if (strcmp(item_name, STRING(tr.pHit->v.classname)) == 0)
- {
- // find distance to item for later use...
- float distance = (vecEnd - vecStart).Length( );
-
- // check if entity is wall mounted health charger...
- if (strcmp("func_healthcharger", item_name) == 0)
- {
- // check if the bot can use this item and
- // check if the recharger is ready to use (has power left)...
- if ((pEdict->v.health < 100) && (pent->v.frame == 0))
- {
- // check if flag not set...
- if (!pBot->b_use_health_station)
- {
- // check if close enough and facing it directly...
- if ((distance < PLAYER_SEARCH_RADIUS) &&
- (angle_to_entity <= 10))
- {
- pBot->b_use_health_station = TRUE;
- pBot->f_use_health_time = gpGlobals->time;
- }
-
- // if close to health station...
- if (distance < 100)
- {
- // don't avoid walls for a while
- pBot->f_dont_avoid_wall_time = gpGlobals->time + 5.0;
- }
-
- can_pickup = TRUE;
- }
- }
- else
- {
- // don't need or can't use this item...
- pBot->b_use_health_station = FALSE;
- }
- }
-
- // check if entity is wall mounted HEV charger...
- else if (strcmp("func_recharge", item_name) == 0)
- {
- // check if the bot can use this item and
- // check if the recharger is ready to use (has power left)...
- if ((pEdict->v.armorvalue < VALVE_MAX_NORMAL_BATTERY) &&
- (pent->v.frame == 0))
- {
- // check if flag not set and facing it...
- if (!pBot->b_use_HEV_station)
- {
- // check if close enough and facing it directly...
- if ((distance < PLAYER_SEARCH_RADIUS) &&
- (angle_to_entity <= 10))
- {
- pBot->b_use_HEV_station = TRUE;
- pBot->f_use_HEV_time = gpGlobals->time;
- }
-
- // if close to HEV recharger...
- if (distance < 100)
- {
- // don't avoid walls for a while
- pBot->f_dont_avoid_wall_time = gpGlobals->time + 5.0;
- }
-
- can_pickup = TRUE;
- }
- }
- else
- {
- // don't need or can't use this item...
- pBot->b_use_HEV_station = FALSE;
- }
- }
-
- // check if entity is a button...
- else if (strcmp("func_button", item_name) == 0)
- {
- // use the button about 100% of the time, if haven't
- // used a button in at least 5 seconds...
- if ((RANDOM_LONG(1, 100) <= 100) &&
- ((pBot->f_use_button_time + 5) < gpGlobals->time))
- {
- // check if flag not set and facing it...
- if (!pBot->b_use_button)
- {
- // check if close enough and facing it directly...
- if ((distance < PLAYER_SEARCH_RADIUS) &&
- (angle_to_entity <= 10))
- {
- pBot->b_use_button = TRUE;
- pBot->b_lift_moving = FALSE;
- pBot->f_use_button_time = gpGlobals->time;
- }
-
- // if close to button...
- if (distance < 100)
- {
- // don't avoid walls for a while
- pBot->f_dont_avoid_wall_time = gpGlobals->time + 5.0;
- }
-
- can_pickup = TRUE;
- }
- }
- else
- {
- // don't need or can't use this item...
- pBot->b_use_button = FALSE;
- }
- }
- }
- }
- }
- else // everything else...
- {
- entity_origin = pent->v.origin;
-
- vecStart = pEdict->v.origin + pEdict->v.view_ofs;
- vecEnd = entity_origin;
-
- // find angles from bot origin to entity...
- angle_to_entity = BotInFieldOfView( pBot, vecEnd - vecStart );
-
- // check if entity is outside field of view (+/- 45 degrees)
- if (angle_to_entity > 45)
- continue; // skip this item if bot can't "see" it
-
- // check if line of sight to object is not blocked (i.e. visible)
- if (BotEntityIsVisible( pBot, vecEnd ))
- {
- // check if entity is a weapon...
- if (strncmp("weapon_", item_name, 7) == 0)
- {
- if (pent->v.effects & EF_NODRAW)
- {
- // someone owns this weapon or it hasn't respawned yet
- continue;
- }
-
- can_pickup = TRUE;
- }
-
- // check if entity is ammo...
- else if (strncmp("ammo_", item_name, 5) == 0)
- {
- // check if the item is not visible (i.e. has not respawned)
- if (pent->v.effects & EF_NODRAW)
- continue;
-
- can_pickup = TRUE;
- }
-
- // check if entity is a battery...
- else if (strcmp("item_battery", item_name) == 0)
- {
- // check if the item is not visible (i.e. has not respawned)
- if (pent->v.effects & EF_NODRAW)
- continue;
-
- // check if the bot can use this item...
- if (pEdict->v.armorvalue < VALVE_MAX_NORMAL_BATTERY)
- {
- can_pickup = TRUE;
- }
- }
-
- // check if entity is a healthkit...
- else if (strcmp("item_healthkit", item_name) == 0)
- {
- // check if the item is not visible (i.e. has not respawned)
- if (pent->v.effects & EF_NODRAW)
- continue;
-
- // check if the bot can use this item...
- if (pEdict->v.health < 100)
- {
- can_pickup = TRUE;
- }
- }
-
- // check if entity is a packed up weapons box...
- else if (strcmp("weaponbox", item_name) == 0)
- {
- can_pickup = TRUE;
- }
-
- // check if entity is the spot from RPG laser
- else if (strcmp("laser_spot", item_name) == 0)
- {
- }
-
- // check if entity is an armed tripmine
- //else if (strcmp("monster_tripmine", item_name) == 0)
- else if (strcmp(kwsDeployedMine, item_name) == 0)
- {
- float distance = (pent->v.origin - pEdict->v.origin).Length( );
-
- if (pBot->b_see_tripmine)
- {
- // see if this tripmine is closer to bot...
- if (distance < (pBot->v_tripmine - pEdict->v.origin).Length())
- {
- pBot->v_tripmine = pent->v.origin;
- pBot->b_shoot_tripmine = FALSE;
-
- // see if bot is far enough to shoot the tripmine...
- if (distance >= 375)
- {
- pBot->b_shoot_tripmine = TRUE;
- }
- }
- }
- else
- {
- pBot->b_see_tripmine = TRUE;
- pBot->v_tripmine = pent->v.origin;
- pBot->b_shoot_tripmine = FALSE;
-
- // see if bot is far enough to shoot the tripmine...
- if (distance >= 375) // 375 is damage radius
- {
- pBot->b_shoot_tripmine = TRUE;
- }
- }
- }
-
- // check if entity is an armed satchel charge
- else if (strcmp("monster_satchel", item_name) == 0)
- {
- }
-
- // check if entity is a snark (squeak grenade)
- else if (strcmp("monster_snark", item_name) == 0)
- {
- }
-
- else if ((mod_id == FRONTLINE_DLL) && (!pBot->defender) &&
- (strcmp("capture_point", item_name) == 0))
- {
- int team = UTIL_GetTeam(pEdict); // skin and team must match
-
- if (flf_bug_fix)
- team = 1 - team; // BACKWARDS bug!
-
- // check if flag not set and point not captured...
- if ((!pBot->b_use_capture) && (pent->v.skin == team))
- {
- float distance = (pent->v.origin - pEdict->v.origin).Length( );
-
- // check if close enough and facing it directly...
- if ((distance < FLF_PLAYER_SEARCH_RADIUS) &&
- (angle_to_entity <= 20))
- {
- pBot->b_use_capture = TRUE;
- pBot->f_use_capture_time = gpGlobals->time + 8.0;
- pBot->pCaptureEdict = pent;
- }
-
- // if close to capture point...
- if (distance < 160)
- {
- // don't avoid walls for a while
- pBot->f_dont_avoid_wall_time = gpGlobals->time + 5.0;
- }
-
- can_pickup = TRUE;
- }
- }
-
- } // end if object is visible
- } // end else not "func_" entity
-
- if (can_pickup) // if the bot found something it can pickup...
- {
- float distance = (entity_origin - pEdict->v.origin).Length( );
-
- // see if it's the closest item so far...
- if (distance < min_distance)
- {
- min_distance = distance; // update the minimum distance
- pPickupEntity = pent; // remember this entity
- pickup_origin = entity_origin; // remember location of entity
- }
- }
- } // end while loop
-
- if (pPickupEntity != NULL)
- {
- // let's head off toward that item...
- Vector v_item = pickup_origin - pEdict->v.origin;
-
- Vector bot_angles = UTIL_VecToAngles( v_item );
-
- pEdict->v.ideal_yaw = bot_angles.y;
-
- BotFixIdealYaw(pEdict);
-
- pBot->pBotPickupItem = pPickupEntity; // save the item bot is trying to get
- }
-}
-
-
-void BotThink( bot_t *pBot )
-{
- int index = 0;
- Vector v_diff; // vector from previous to current location
- float pitch_degrees;
- float yaw_degrees;
- float moved_distance; // length of v_diff vector (distance bot moved)
- TraceResult tr;
- bool found_waypoint;
- bool is_idle;
-
- edict_t *pEdict = pBot->pEdict;
-
-
- pEdict->v.flags |= FL_FAKECLIENT;
-
- if (pBot->name[0] == 0) // name filled in yet?
- strcpy(pBot->name, STRING(pBot->pEdict->v.netname));
-
-
-// TheFatal - START from Advanced Bot Framework (Thanks Rich!)
-
- // adjust the millisecond delay based on the frame rate interval...
- if (pBot->msecdel <= gpGlobals->time)
- {
- pBot->msecdel = gpGlobals->time + 0.5;
- if (pBot->msecnum > 0)
- pBot->msecval = 450.0/pBot->msecnum;
- pBot->msecnum = 0;
- }
- else
- pBot->msecnum++;
-
- if (pBot->msecval < 1) // don't allow msec to be less than 1...
- pBot->msecval = 1;
-
- if (pBot->msecval > 100) // ...or greater than 100
- pBot->msecval = 100;
-
-// TheFatal - END
-
-
- pEdict->v.button = 0;
- pBot->f_move_speed = 0.0;
-
- if(pBot->mBotPlayMode == PLAYMODE_READYROOM)
- {
- // Look at desired team and head to nearest start entity
- AvHClassType theClassType = AVH_CLASS_TYPE_UNDEFINED;
-
- FakeClientCommand(pEdict, kcAutoAssign, NULL, NULL);
-
- // bot has now joined the game (doesn't need to be started)
- pBot->not_started = 0;
- }
-
- // if the bot hasn't selected stuff to start the game yet, go do that...
- if (pBot->not_started)
- {
- BotStartGame( pBot );
-
- // Do this to test server performance
- //return;
-
- g_engfuncs.pfnRunPlayerMove( pEdict, pEdict->v.v_angle, 0.0,
- 0, 0, pEdict->v.button, 0, pBot->msecval);
-
- //return;
- }
-
- if((pBot->mOrderType != ORDERTYPE_UNDEFINED) && (!pBot->mOrderCompleted))
- {
- // Every once in a while mention our order
- if(RANDOM_LONG(0, 200) == 0)
- {
- char theMessage[256];
- sprintf(theMessage, "Order type: %d, target type: %d\n", pBot->mOrderType, pBot->mOrderTargetType);
- //UTIL_HostSay(pBot->pEdict, 0, theMessage);
- }
- }
- else
- {
- // Occasionally ask for orders when not doing anything else
- if(RANDOM_LONG(0, 1800) == 0)
- {
- if(pBot->mTimeOfNextOrderRequest == -1)
- {
- pBot->mTimeOfNextOrderRequest = gpGlobals->time;
- }
- }
- }
-
- if(RANDOM_LONG(0, 1000))
- {
- pBot->mTimeOfNextRandomSaying = gpGlobals->time;
- }
-
- // If we're out of ammo, occasionally ask for more
- // Get current weapon
- int theWeaponID = pBot->current_weapon.iId;
- if(theWeaponID > 0)
- {
- if((pBot->current_weapon.iAmmo1 != -1) && (pBot->current_weapon.iClip <= 10))
- {
- if(RANDOM_LONG(0, 40))
- {
- if(pBot->mTimeOfNextAmmoRequest == -1)
- {
- pBot->mTimeOfNextAmmoRequest = gpGlobals->time;
- }
- }
- }
- }
-
-
- if ((pBot->b_bot_say_killed) && (pBot->f_bot_say_killed < gpGlobals->time))
- {
- int whine_index = 0;
- bool used;
- int i, recent_count;
- char msg[120];
-
- pBot->b_bot_say_killed = FALSE;
-
- recent_count = 0;
-
- while (recent_count < 5)
- {
- whine_index = RANDOM_LONG(0, whine_count-1);
-
- used = FALSE;
-
- for (i=0; i < 5; i++)
- {
- if (recent_bot_whine[i] == whine_index)
- used = TRUE;
- }
-
- if (used)
- recent_count++;
- else
- break;
- }
-
- for (i=4; i > 0; i--)
- recent_bot_whine[i] = recent_bot_whine[i-1];
-
- recent_bot_whine[0] = whine_index;
-
- if (strstr(bot_whine[whine_index], "%s") != NULL) // is "%s" in whine text?
- sprintf(msg, bot_whine[whine_index], STRING(pBot->killer_edict->v.netname));
- else
- sprintf(msg, bot_whine[whine_index]);
-
- UTIL_HostSay(pEdict, 0, msg);
- }
-
- // if the bot is dead, randomly press fire to respawn...
- if ((pEdict->v.health < 1) || (pEdict->v.deadflag != DEAD_NO))
- {
- if (pBot->need_to_initialize)
- {
- BotSpawnInit(pBot);
-
- // did another player kill this bot AND bot whine messages loaded AND
- // has the bot been alive for at least 15 seconds AND
- if ((pBot->killer_edict != NULL) && (whine_count > 0) &&
- ((pBot->f_bot_spawn_time + 15.0) <= gpGlobals->time))
- {
- if ((RANDOM_LONG(1,100) <= 10))
- {
- pBot->b_bot_say_killed = TRUE;
- pBot->f_bot_say_killed = gpGlobals->time + 10.0 + RANDOM_FLOAT(0.0, 5.0);
- }
- }
-
- pBot->need_to_initialize = FALSE;
- }
-
- if (RANDOM_LONG(1, 100) > 50)
- pEdict->v.button = IN_ATTACK;
-
- g_engfuncs.pfnRunPlayerMove( pEdict, pEdict->v.v_angle, pBot->f_move_speed,
- 0, 0, pEdict->v.button, 0, pBot->msecval);
-
- return;
- }
-
- // set this for the next time the bot dies so it will initialize stuff
- if (pBot->need_to_initialize == FALSE)
- {
- pBot->need_to_initialize = TRUE;
- pBot->f_bot_spawn_time = gpGlobals->time;
- }
-
- is_idle = FALSE;
-
- if ((mod_id == FRONTLINE_DLL) && (pBot->round_end))
- {
- if (pBot->warmup) // has warmup started (i.e. start of round?)
- {
- pBot->round_end = 0;
-
- BotSpawnInit(pBot);
- }
-
- is_idle = TRUE;
-
- flf_bug_fix = 0; // BACKWARDS bug off now!
- }
-
- if ((mod_id == FRONTLINE_DLL) && (pBot->warmup) && (!pBot->defender))
- {
- if (pBot->curr_waypoint_index == -1)
- {
- // find the nearest visible waypoint
- int i = WaypointFindNearest(pEdict, REACHABLE_RANGE, pBot->defender);
-
- if (i != -1)
- {
- Vector v_direction = waypoints[i].origin - pEdict->v.origin;
-
- Vector bot_angles = UTIL_VecToAngles( v_direction );
-
- pBot->idle_angle = bot_angles.y;
- }
- else
- pBot->idle_angle = pEdict->v.v_angle.y;
- }
-
- is_idle = TRUE;
- }
-
- if (pBot->blinded_time > gpGlobals->time)
- {
- is_idle = TRUE; // don't do anything while blinded
- }
-
- if(CVAR_GET_FLOAT("freezebots") > 0)
- {
- return; // Don't move.
- }
-
- if (is_idle)
- {
- if (pBot->idle_angle_time <= gpGlobals->time)
- {
- pBot->idle_angle_time = gpGlobals->time + RANDOM_FLOAT(0.5, 2.0);
-
- pEdict->v.ideal_yaw = pBot->idle_angle + RANDOM_FLOAT(0.0, 40.0) - 20.0;
-
- BotFixIdealYaw(pEdict);
- }
-
- // turn towards ideal_yaw by yaw_speed degrees (slower than normal)
- BotChangeYaw( pBot, pEdict->v.yaw_speed / 2 );
-
- g_engfuncs.pfnRunPlayerMove( pEdict, pEdict->v.v_angle, pBot->f_move_speed,
- 0, 0, pEdict->v.button, 0, pBot->msecval);
-
- return;
- }
- else
- {
- pBot->idle_angle = pEdict->v.v_angle.y;
- }
-
- // check if time to check for player sounds (if don't already have enemy)
- if ((pBot->f_sound_update_time <= gpGlobals->time) &&
- (pBot->pBotEnemy == NULL))
- {
- int ind;
- edict_t *pPlayer;
-
- pBot->f_sound_update_time = gpGlobals->time + 1.0;
-
- for (ind = 1; ind <= gpGlobals->maxClients; ind++)
- {
- pPlayer = INDEXENT(ind);
-
- // is this player slot is valid and it's not this bot...
- if ((pPlayer) && (!pPlayer->free) && (pPlayer != pEdict))
- {
- // if observer mode enabled, don't listen to this player...
- if ((b_observer_mode) && !(pPlayer->v.flags & FL_FAKECLIENT))
- continue;
-
- if (IsAlive(pPlayer) &&
- (FBitSet(pPlayer->v.flags, FL_CLIENT) ||
- FBitSet(pPlayer->v.flags, FL_FAKECLIENT)))
- {
- // check for sounds being made by other players...
- if (UpdateSounds(pEdict, pPlayer))
- {
- // don't check for sounds for another 30 seconds
- pBot->f_sound_update_time = gpGlobals->time + 30.0;
- }
- }
- }
- }
- }
-
- pBot->f_move_speed = pBot->f_max_speed; // set to max speed
-
- if (pBot->prev_time <= gpGlobals->time)
- {
- // see how far bot has moved since the previous position...
- v_diff = pBot->v_prev_origin - pEdict->v.origin;
- moved_distance = v_diff.Length();
-
- // save current position as previous
- pBot->v_prev_origin = pEdict->v.origin;
- pBot->prev_time = gpGlobals->time + 0.2;
- }
- else
- {
- moved_distance = 2.0;
- }
-
- // if the bot is under water, adjust pitch by pitch_speed degrees
- if ((pEdict->v.waterlevel == 2) ||
- (pEdict->v.waterlevel == 3))
- {
- // turn towards ideal_pitch by pitch_speed degrees
- pitch_degrees = BotChangePitch( pBot, pEdict->v.pitch_speed );
- }
- else
- pitch_degrees = 0.0;
-
- // turn towards ideal_yaw by yaw_speed degrees
- yaw_degrees = BotChangeYaw( pBot, pEdict->v.yaw_speed );
-
- if ((pitch_degrees >= pEdict->v.pitch_speed) ||
- (yaw_degrees >= pEdict->v.yaw_speed))
- {
- pBot->f_move_speed = 0.0; // don't move while turning a lot
- }
- else if ((pitch_degrees >= 10) ||
- (yaw_degrees >= 10)) // turning more than 10 degrees?
- {
- pBot->f_move_speed = pBot->f_move_speed / 4; // slow down while turning
- }
- else // else handle movement related actions...
- {
- if (b_botdontshoot == 0)
- {
- if ((mod_id == TFC_DLL) && (pBot->bot_has_flag == TRUE))
- {
- // is it time to check whether bot should look for enemies yet?
- if (pBot->f_bot_find_enemy_time <= gpGlobals->time)
- {
- pBot->f_bot_find_enemy_time = gpGlobals->time + 5.0;
-
- if (RANDOM_LONG(1, 100) <= 40)
- pBot->pBotEnemy = BotFindEnemy( pBot );
- }
- }
- else
- {
- // Now that bots scan every entity in the world, do this less often
- if(RANDOM_LONG(1, 100) <= 20)
- {
- pBot->pBotEnemy = BotFindEnemy( pBot );
- }
- }
- }
- else
- pBot->pBotEnemy = NULL; // clear enemy pointer (no ememy for you!)
-
- if (pBot->pBotEnemy != NULL) // does an enemy exist?
- {
- BotShootAtEnemy( pBot ); // shoot at the enemy
-
- pBot->f_pause_time = 0; // dont't pause if enemy exists
- }
-
- else if (pBot->f_pause_time > gpGlobals->time) // is bot "paused"?
- {
- // you could make the bot look left then right, or look up
- // and down, to make it appear that the bot is hunting for
- // something (don't do anything right now)
- }
-
- // is bot being "used" and can still follow "user"?
- else if ((pBot->pBotUser != NULL) && BotFollowUser( pBot ))
- {
- // do nothing here!
- ;
- }
-
- else
- {
- // no enemy, let's just wander around...
-
- if ((pEdict->v.waterlevel != 2) && // is bot NOT under water?
- (pEdict->v.waterlevel != 3))
- {
- // reset pitch to 0 (level horizontally)
- pEdict->v.idealpitch = 0;
- pEdict->v.v_angle.x = 0;
- }
-
- pEdict->v.v_angle.z = 0; // reset roll to 0 (straight up and down)
-
- pEdict->v.angles.x = 0;
- pEdict->v.angles.y = pEdict->v.v_angle.y;
- pEdict->v.angles.z = 0;
-
- // check if bot should look for items now or not...
- if (pBot->f_find_item < gpGlobals->time)
- {
- BotFindItem( pBot ); // see if there are any visible items
- }
-
- // check if bot sees a tripmine...
- if (pBot->b_see_tripmine)
- {
- // check if bot can shoot the tripmine...
- if ((pBot->b_shoot_tripmine) && BotShootTripmine( pBot ))
- {
- // shot at tripmine, may or may not have hit it, clear
- // flags anyway, next BotFindItem will see it again if
- // it is still there...
-
- pBot->b_shoot_tripmine = FALSE;
- pBot->b_see_tripmine = FALSE;
-
- // pause for a while to allow tripmine to explode...
- pBot->f_pause_time = gpGlobals->time + 0.5;
- }
- else // run away!!!
- {
- Vector tripmine_angles;
-
- tripmine_angles = UTIL_VecToAngles( pBot->v_tripmine - pEdict->v.origin );
-
- // face away from the tripmine
- pEdict->v.ideal_yaw += 180; // rotate 180 degrees
-
- BotFixIdealYaw(pEdict);
-
- pBot->b_see_tripmine = FALSE;
-
- pBot->f_move_speed = 0; // don't run while turning
- }
- }
-
- // check if should use wall mounted health station...
- else if (pBot->b_use_health_station)
- {
- if ((pBot->f_use_health_time + 10.0) > gpGlobals->time)
- {
- pBot->f_move_speed = 0; // don't move while using health station
-
- pEdict->v.button = IN_USE;
- }
- else
- {
- // bot is stuck trying to "use" a health station...
-
- pBot->b_use_health_station = FALSE;
-
- // don't look for items for a while since the bot
- // could be stuck trying to get to an item
- pBot->f_find_item = gpGlobals->time + 0.5;
- }
- }
-
- // check if should use wall mounted HEV station...
- else if (pBot->b_use_HEV_station)
- {
- if ((pBot->f_use_HEV_time + 10.0) > gpGlobals->time)
- {
- pBot->f_move_speed = 0; // don't move while using HEV station
-
- pEdict->v.button = IN_USE;
- }
- else
- {
- // bot is stuck trying to "use" a HEV station...
-
- pBot->b_use_HEV_station = FALSE;
-
- // don't look for items for a while since the bot
- // could be stuck trying to get to an item
- pBot->f_find_item = gpGlobals->time + 0.5;
- }
- }
-
- // check if should capture a point by using it...
- else if (pBot->b_use_capture)
- {
- int team = UTIL_GetTeam(pEdict); // skin and team must match
-
- if (flf_bug_fix)
- team = 1 - team; // BACKWARDS bug fix!
-
- // still capturing and hasn't captured yet...
- if ((pBot->f_use_capture_time > gpGlobals->time) &&
- (pBot->pCaptureEdict->v.skin == team))
- {
- pBot->f_move_speed = 0; // don't move while capturing
-
- pEdict->v.button = IN_USE;
- }
- else
- {
- // bot is stuck trying to "use" a capture point...
-
- pBot->b_use_capture = FALSE;
-
- // don't look for items for a while since the bot
- // could be stuck trying to get to an item
- pBot->f_find_item = gpGlobals->time + 0.5;
- }
- }
-
- else if (pBot->b_use_button)
- {
- pBot->f_move_speed = 0; // don't move while using elevator
-
- BotUseLift( pBot, moved_distance );
- }
-
- else
- {
- if (pEdict->v.waterlevel == 3) // check if the bot is underwater...
- {
- BotUnderWater( pBot );
- }
-
- found_waypoint = FALSE;
-
- // if the bot is not trying to get to something AND
- // it is time to look for a waypoint AND
- // there are waypoints in this level...
-
- if ((pBot->pBotPickupItem == NULL) &&
- (pBot->f_look_for_waypoint_time <= gpGlobals->time) &&
- (num_waypoints != 0))
- {
- found_waypoint = BotHeadTowardWaypoint(pBot);
- }
-
- // check if the bot is on a ladder...
- if (pEdict->v.movetype == MOVETYPE_FLY)
- {
- // check if bot JUST got on the ladder...
- if ((pBot->f_end_use_ladder_time + 1.0) < gpGlobals->time)
- pBot->f_start_use_ladder_time = gpGlobals->time;
-
- // go handle the ladder movement
- BotOnLadder( pBot, moved_distance );
-
- pBot->f_dont_avoid_wall_time = gpGlobals->time + 2.0;
- pBot->f_end_use_ladder_time = gpGlobals->time;
- }
- else
- {
- // check if the bot JUST got off the ladder...
- if ((pBot->f_end_use_ladder_time + 1.0) > gpGlobals->time)
- {
- pBot->ladder_dir = LADDER_UNKNOWN;
- }
- }
-
- // if the bot isn't headed toward a waypoint...
- if (found_waypoint == FALSE)
- {
- TraceResult tr;
-
- // check if we should be avoiding walls
- if (pBot->f_dont_avoid_wall_time <= gpGlobals->time)
- {
- // let's just randomly wander around
- if (BotStuckInCorner( pBot ))
- {
- pEdict->v.ideal_yaw += 180; // turn 180 degrees
-
- BotFixIdealYaw(pEdict);
-
- pBot->f_move_speed = 0; // don't move while turning
- pBot->f_dont_avoid_wall_time = gpGlobals->time + 1.0;
-
- moved_distance = 2.0; // dont use bot stuck code
- }
- else
- {
- // check if there is a wall on the left...
- if (!BotCheckWallOnLeft( pBot ))
- {
- // if there was a wall on the left over 1/2 a second ago then
- // 20% of the time randomly turn between 45 and 60 degrees
-
- if ((pBot->f_wall_on_left != 0) &&
- (pBot->f_wall_on_left <= gpGlobals->time - 0.5) &&
- (RANDOM_LONG(1, 100) <= 20))
- {
- pEdict->v.ideal_yaw += RANDOM_LONG(45, 60);
-
- BotFixIdealYaw(pEdict);
-
- pBot->f_move_speed = 0; // don't move while turning
- pBot->f_dont_avoid_wall_time = gpGlobals->time + 1.0;
- }
-
- pBot->f_wall_on_left = 0; // reset wall detect time
- }
- else if (!BotCheckWallOnRight( pBot ))
- {
- // if there was a wall on the right over 1/2 a second ago then
- // 20% of the time randomly turn between 45 and 60 degrees
-
- if ((pBot->f_wall_on_right != 0) &&
- (pBot->f_wall_on_right <= gpGlobals->time - 0.5) &&
- (RANDOM_LONG(1, 100) <= 20))
- {
- pEdict->v.ideal_yaw -= RANDOM_LONG(45, 60);
-
- BotFixIdealYaw(pEdict);
-
- pBot->f_move_speed = 0; // don't move while turning
- pBot->f_dont_avoid_wall_time = gpGlobals->time + 1.0;
- }
-
- pBot->f_wall_on_right = 0; // reset wall detect time
- }
- }
- }
-
- // check if bot is about to hit a wall. TraceResult gets returned
- if ((pBot->f_dont_avoid_wall_time <= gpGlobals->time) &&
- BotCantMoveForward( pBot, &tr ))
- {
- // ADD LATER
- // need to check if bot can jump up or duck under here...
- // ADD LATER
-
- BotTurnAtWall( pBot, &tr );
- }
- }
-
- // check if bot is on a ladder and has been on a ladder for
- // more than 5 seconds...
- if ((pEdict->v.movetype == MOVETYPE_FLY) &&
- (pBot->f_start_use_ladder_time > 0.0) &&
- ((pBot->f_start_use_ladder_time + 5.0) <= gpGlobals->time))
- {
- // bot is stuck on a ladder...
-
- BotRandomTurn(pBot);
-
- // don't look for items for 2 seconds
- pBot->f_find_item = gpGlobals->time + 2.0;
-
- pBot->f_start_use_ladder_time = 0.0; // reset start ladder time
- }
-
- // check if the bot hasn't moved much since the last location
- // (and NOT on a ladder since ladder stuck handled elsewhere)
- // (don't check for stuck if f_dont_check_stuck in the future)
- if ((moved_distance <= 1.0) && (pBot->prev_speed >= 1.0) &&
- (pEdict->v.movetype != MOVETYPE_FLY) &&
- (pBot->f_dont_check_stuck < gpGlobals->time))
- {
- // the bot must be stuck!
-
- pBot->f_dont_avoid_wall_time = gpGlobals->time + 1.0;
- pBot->f_look_for_waypoint_time = gpGlobals->time + 1.0;
-
- if (BotCanJumpUp( pBot )) // can the bot jump onto something?
- {
- if ((pBot->f_jump_time + 2.0) <= gpGlobals->time)
- {
- pBot->f_jump_time = gpGlobals->time;
- pEdict->v.button |= IN_JUMP; // jump up and move forward
- }
- else
- {
- // bot already tried jumping less than two seconds ago, just turn
- BotRandomTurn(pBot);
- }
- }
- else if (BotCanDuckUnder( pBot )) // can the bot duck under something?
- {
- pEdict->v.button |= IN_DUCK; // duck down and move forward
- }
- else
- {
- BotRandomTurn(pBot);
-
- // is the bot trying to get to an item?...
- if (pBot->pBotPickupItem != NULL)
- {
- // don't look for items for a while since the bot
- // could be stuck trying to get to an item
- pBot->f_find_item = gpGlobals->time + 0.5;
- }
- }
- }
-
- // should the bot pause for a while here?
- // (don't pause on ladders or while being "used"...
- if ((RANDOM_LONG(1, 1000) <= pause_frequency[pBot->bot_skill]) &&
- (pEdict->v.movetype != MOVETYPE_FLY) &&
- (pBot->pBotUser == NULL))
- {
- // set the time that the bot will stop "pausing"
- pBot->f_pause_time = gpGlobals->time +
- RANDOM_FLOAT(pause_time[pBot->bot_skill][0],
- pause_time[pBot->bot_skill][1]);
- }
- }
- }
- }
-
- // Potentially morph up if we're an alien
- AvHUser3 theUser3 = (AvHUser3)(pBot->pEdict->v.iuser3);
- if((pBot->pBotEnemy == NULL) && (theUser3 >= AVH_USER3_ALIEN_PLAYER1) && (theUser3 <= AVH_USER3_ALIEN_PLAYER4))
- {
- int theMaxUpgrade = (int)(AVH_USER3_ALIEN_PLAYER5 - theUser3);
- //const UpgradeCostListType& theUpgradeCosts = GetGameRules()->GetUpgradeCosts();
-
- if(RANDOM_LONG(0, 400) == 0)
- {
- // Pick a random upgrade
- AvHUser3 theMinUpgrade = (AvHUser3)(theUser3 + 1);
- int theMaxUpgrade = AVH_USER3_ALIEN_PLAYER5;
- AvHUser3 theUpgradeUser3 = (AvHUser3)(RANDOM_LONG((int)theMinUpgrade, (int)theMaxUpgrade));
- int thePointCost = 0;
- AvHMessageID theMessage = MESSAGE_NULL;
- switch(theUpgradeUser3)
- {
- case AVH_USER3_ALIEN_PLAYER2:
- thePointCost = 15;
- theMessage = ALIEN_LIFEFORM_TWO;
- break;
- case AVH_USER3_ALIEN_PLAYER3:
- thePointCost = 30;
- theMessage = ALIEN_LIFEFORM_THREE;
- break;
- case AVH_USER3_ALIEN_PLAYER4:
- thePointCost = 50;
- theMessage = ALIEN_LIFEFORM_FOUR;
- break;
- case AVH_USER3_ALIEN_PLAYER5:
- thePointCost = 75;
- theMessage = ALIEN_LIFEFORM_FIVE;
- break;
- }
-
- //thePointCost = GetGameRules()->GetPointCostForMessageID(theMessage);
-
- //if(pBot->mResources >= thePointCost)
- //{
- pBot->pEdict->v.impulse = theMessage;
- //}
- }
-
- if(RANDOM_LONG(0, 75) == 0)
- {
- // Pick a random upgrade to try to "buy"
- AvHMessageID theUpgrade = (AvHMessageID)(ALIEN_EVOLUTION_ONE + RANDOM_LONG(0, kNumAlienUpgrades-1));
- pBot->pEdict->v.impulse = theUpgrade;
- }
- }
-
- // TODO: Help build a nearby team structure
- if(pBot->pBotEnemy == NULL && (theUser3 == AVH_USER3_MARINE_PLAYER))
- {
- }
-
- if (pBot->curr_waypoint_index != -1) // does the bot have a waypoint?
- {
- // check if the next waypoint is a door waypoint...
- if (waypoints[pBot->curr_waypoint_index].flags & W_FL_DOOR)
- {
- pBot->f_move_speed = pBot->f_max_speed / 3; // slow down for doors
- }
-
- // check if the next waypoint is a ladder waypoint...
- if (waypoints[pBot->curr_waypoint_index].flags & W_FL_LADDER)
- {
- // check if the waypoint is at the top of a ladder AND
- // the bot isn't currenly on a ladder...
- if ((pBot->waypoint_top_of_ladder) &&
- (pEdict->v.movetype != MOVETYPE_FLY))
- {
- // is the bot on "ground" above the ladder?
- if (pEdict->v.flags & FL_ONGROUND)
- {
- float waypoint_distance = (pEdict->v.origin - pBot->waypoint_origin).Length();
-
- if (waypoint_distance <= 20.0) // if VERY close...
- pBot->f_move_speed = 20.0; // go VERY slow
- else if (waypoint_distance <= 100.0) // if fairly close...
- pBot->f_move_speed = 50.0; // go fairly slow
-
- pBot->ladder_dir = LADDER_DOWN;
- pBot->f_dont_check_stuck = gpGlobals->time + 1.0;
- }
- else // bot must be in mid-air, go BACKWARDS to touch ladder...
- {
- pBot->f_move_speed = -pBot->f_max_speed;
- }
- }
- else
- {
- // don't avoid walls for a while
- pBot->f_dont_avoid_wall_time = gpGlobals->time + 5.0;
-
- pBot->waypoint_top_of_ladder = FALSE;
- }
- }
-
- // check if the next waypoint is a crouch waypoint...
- if (waypoints[pBot->curr_waypoint_index].flags & W_FL_CROUCH)
- pEdict->v.button |= IN_DUCK; // duck down while moving forward
-
- // check if the waypoint is a sniper waypoint AND
- // bot isn't currently aiming at an ememy...
- if ((waypoints[pBot->curr_waypoint_index].flags & W_FL_SNIPER) &&
- (pBot->pBotEnemy == NULL))
- {
- if ((mod_id != TFC_DLL) ||
- ((mod_id == TFC_DLL) && (pEdict->v.playerclass == TFC_CLASS_SNIPER)))
- {
- // check if it's time to adjust aim yet...
- if (pBot->f_sniper_aim_time <= gpGlobals->time)
- {
- int aim_index;
-
- aim_index = WaypointFindNearestAiming(waypoints[pBot->curr_waypoint_index].origin);
-
- if (aim_index != -1)
- {
- Vector v_aim = waypoints[aim_index].origin - waypoints[pBot->curr_waypoint_index].origin;
-
- Vector aim_angles = UTIL_VecToAngles( v_aim );
-
- aim_angles.y += RANDOM_LONG(0, 30) - 15;
-
- pEdict->v.ideal_yaw = aim_angles.y;
-
- BotFixIdealYaw(pEdict);
- }
-
- // don't adjust aim again until after a few seconds...
- pBot->f_sniper_aim_time = gpGlobals->time + RANDOM_FLOAT(3.0, 5.0);
- }
- }
- }
- }
-
- // Process voice commands
- BotProcessVoiceCommands(pBot);
-
- if (pBot->f_pause_time > gpGlobals->time) // is the bot "paused"?
- pBot->f_move_speed = 0; // don't move while pausing
-
- // make the body face the same way the bot is looking
- pEdict->v.angles.y = pEdict->v.v_angle.y;
-
- // save the previous speed (for checking if stuck)
- pBot->prev_speed = pBot->f_move_speed;
-
- //CBaseEntity* theEntity = CBaseEntity::Instance(pEdict);
- //CBasePlayer* thePlayer = (CBasePlayer*)(theEntity);
- //thePlayer->PreThink();
-
- g_engfuncs.pfnRunPlayerMove( pEdict, pEdict->v.v_angle, pBot->f_move_speed,
- 0, 0, pEdict->v.button, 0, pBot->msecval);
-
- //thePlayer->PostThink();
-
- return;
-}
-
+//
+// HPB bot - botman's High Ping Bastard bot
+//
+// (http://planethalflife.com/botman/)
+//
+// bot.cpp
+//
+
+//#include "windows.h"
+#include "dlls/extdll.h"
+#include "dlls/util.h"
+#include "dlls/cbase.h"
+
+#include "bot.h"
+#include "bot_func.h"
+#include "waypoint.h"
+#include "bot_weapons.h"
+
+#include
+#include
+#include "mod/AvHMarineEquipmentConstants.h"
+#include "mod/AvHMessage.h"
+#include "mod/AvHCommandConstants.h"
+#include "mod/AvHMessage.h"
+#include "mod/AvHPlayer.h"
+
+#ifndef __linux__
+extern HINSTANCE h_Library;
+#else
+extern void *h_Library;
+#endif
+
+
+extern int mod_id;
+extern WAYPOINT waypoints[MAX_WAYPOINTS];
+extern int num_waypoints; // number of waypoints currently in use
+extern int default_bot_skill;
+extern edict_t *pent_info_ctfdetect;
+
+extern int max_team_players[4];
+extern int team_class_limits[4];
+extern int max_teams;
+extern char bot_whine[MAX_BOT_WHINE][81];
+extern int whine_count;
+
+extern int flf_bug_fix;
+
+static FILE *fp;
+
+
+#define PLAYER_SEARCH_RADIUS 40.0
+#define FLF_PLAYER_SEARCH_RADIUS 60.0
+
+
+bot_t bots[32]; // max of 32 bots in a game
+bool b_observer_mode = FALSE;
+bool b_botdontshoot = FALSE;
+
+extern int recent_bot_whine[5];
+
+int number_names = 0;
+
+#define MAX_BOT_NAMES 100
+
+#define VALVE_MAX_SKINS 10
+#define GEARBOX_MAX_SKINS 20
+
+// indicate which models are currently used for random model allocation
+bool valve_skin_used[VALVE_MAX_SKINS] = {
+ FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE};
+
+bool gearbox_skin_used[GEARBOX_MAX_SKINS] = {
+ FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
+ FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE};
+
+// store the names of the models...
+char *valve_bot_skins[VALVE_MAX_SKINS] = {
+ "barney", "gina", "gman", "gordon", "helmet",
+ "hgrunt", "recon", "robo", "scientist", "zombie"};
+
+char *gearbox_bot_skins[GEARBOX_MAX_SKINS] = {
+ "barney", "beret", "cl_suit", "drill", "fassn", "gina", "gman",
+ "gordon", "grunt", "helmet", "hgrunt", "massn", "otis", "recon",
+ "recruit", "robo", "scientist", "shepard", "tower", "zombie"};
+
+// store the player names for each of the models...
+char *valve_bot_names[VALVE_MAX_SKINS] = {
+ "Barney", "Gina", "G-Man", "Gordon", "Helmet",
+ "H-Grunt", "Recon", "Robo", "Scientist", "Zombie"};
+
+char *gearbox_bot_names[GEARBOX_MAX_SKINS] = {
+ "Barney", "Beret", "Cl_suit", "Drill", "Fassn", "Gina", "G-Man",
+ "Gordon", "Grunt", "Helmet", "H-Grunt", "Massn", "Otis", "Recon",
+ "Recruit", "Robo", "Scientist", "Shepard", "Tower", "Zombie"};
+
+char bot_names[MAX_BOT_NAMES][BOT_NAME_LEN+1];
+
+// how often (out of 1000 times) the bot will pause, based on bot skill
+float pause_frequency[5] = {4, 7, 10, 15, 20};
+
+float pause_time[5][2] = {
+ {0.2, 0.5}, {0.5, 1.0}, {0.7, 1.3}, {1.0, 1.7}, {1.2, 2.0}};
+
+
+inline edict_t *CREATE_FAKE_CLIENT( const char *netname )
+{
+ return (*g_engfuncs.pfnCreateFakeClient)( netname );
+}
+
+inline char *GET_INFOBUFFER( edict_t *e )
+{
+ return (*g_engfuncs.pfnGetInfoKeyBuffer)( e );
+}
+
+inline char *GET_INFO_KEY_VALUE( char *infobuffer, char *key )
+{
+ return (g_engfuncs.pfnInfoKeyValue( infobuffer, key ));
+}
+
+inline void SET_CLIENT_KEY_VALUE( int clientIndex, char *infobuffer,
+ char *key, char *value )
+{
+ (*g_engfuncs.pfnSetClientKeyValue)( clientIndex, infobuffer, key, value );
+}
+
+
+// this is the LINK_ENTITY_TO_CLASS function that creates a player (bot)
+void player( entvars_t *pev )
+{
+ static LINK_ENTITY_FUNC otherClassName = NULL;
+ if (otherClassName == NULL)
+ otherClassName = (LINK_ENTITY_FUNC)GetProcAddress(h_Library, "player");
+ if (otherClassName != NULL)
+ {
+ (*otherClassName)(pev);
+ }
+}
+
+void BotProcessVoiceCommands(bot_t* pBot)
+{
+ if((pBot->mTimeOfNextOrderRequest != -1) && (gpGlobals->time > pBot->mTimeOfNextOrderRequest))
+ {
+ if(pBot->pEdict->v.impulse == 0)
+ {
+ pBot->pEdict->v.impulse = ORDER_REQUEST;
+ pBot->mTimeOfNextOrderRequest = -1;
+ }
+ }
+ if((pBot->mTimeOfNextAmmoRequest != -1) && (gpGlobals->time > pBot->mTimeOfNextAmmoRequest))
+ {
+ if(pBot->pEdict->v.impulse == 0)
+ {
+ pBot->pEdict->v.impulse = SAYING_5;
+ pBot->mTimeOfNextAmmoRequest = -1;
+ }
+ }
+ if((pBot->mTimeOfNextRandomSaying != -1) && (gpGlobals->time > pBot->mTimeOfNextRandomSaying))
+ {
+ if(pBot->pEdict->v.impulse == 0)
+ {
+ pBot->pEdict->v.impulse = SAYING_1 + g_engfuncs.pfnRandomLong(0, 5);
+ pBot->mTimeOfNextRandomSaying = -1;
+ }
+ }
+ if((pBot->mTimeOfNextTaunt != -1) && (gpGlobals->time > pBot->mTimeOfNextTaunt))
+ {
+ if(pBot->pEdict->v.impulse == 0)
+ {
+ pBot->pEdict->v.impulse = SAYING_3;
+ pBot->mTimeOfNextTaunt = -1;
+ }
+ }
+ if((pBot->mTimeOfNextAcknowledge != -1) && (gpGlobals->time > pBot->mTimeOfNextAcknowledge))
+ {
+ if(pBot->pEdict->v.impulse == 0)
+ {
+ pBot->pEdict->v.impulse = ORDER_ACK;
+ pBot->mTimeOfNextAcknowledge = -1;
+ }
+ }
+}
+
+void BotSpawnInit( bot_t *pBot )
+{
+ pBot->v_prev_origin = Vector(9999.0, 9999.0, 9999.0);
+ pBot->prev_time = gpGlobals->time;
+
+ pBot->waypoint_origin = Vector(0, 0, 0);
+ pBot->f_waypoint_time = 0.0;
+ pBot->curr_waypoint_index = -1;
+ pBot->prev_waypoint_index[0] = -1;
+ pBot->prev_waypoint_index[1] = -1;
+ pBot->prev_waypoint_index[2] = -1;
+ pBot->prev_waypoint_index[3] = -1;
+ pBot->prev_waypoint_index[4] = -1;
+
+ pBot->f_random_waypoint_time = gpGlobals->time;
+ pBot->waypoint_goal = -1;
+ pBot->f_waypoint_goal_time = 0.0;
+ pBot->waypoint_near_flag = FALSE;
+ pBot->waypoint_flag_origin = Vector(0, 0, 0);
+ pBot->prev_waypoint_distance = 0.0;
+
+ pBot->msecnum = 0;
+ pBot->msecdel = 0.0;
+ pBot->msecval = 0.0;
+
+ pBot->bot_health = 0;
+ pBot->bot_armor = 0;
+ pBot->bot_weapons = 0;
+ pBot->blinded_time = 0.0;
+
+ // Init AvH variables
+ pBot->mBotPlayMode = PLAYMODE_READYROOM;
+
+ pBot->mOrderState = 0;
+ pBot->mOrderNumPlayers = -1;
+ pBot->mOrderType = ORDERTYPE_UNDEFINED;
+ pBot->mOrderTargetType = ORDERTARGETTYPE_UNDEFINED;
+ pBot->mOrderLocation[0] = pBot->mOrderLocation[1] = pBot->mOrderLocation[2] = 0.0f;
+ pBot->mOrderTargetIndex = -1;
+ pBot->mOrderCompleted = false;
+
+ pBot->mTimeOfNextAcknowledge = -1;
+ pBot->mTimeOfNextAmmoRequest = -1;
+ pBot->mTimeOfNextOrderRequest = -1;
+ pBot->mTimeOfNextTaunt = -1;
+ pBot->mTimeOfNextRandomSaying = -1;
+
+ pBot->mGestateUser3 = AVH_USER3_NONE;
+ pBot->mResources = 0;
+ // end AvH variable init
+
+ pBot->f_max_speed = CVAR_GET_FLOAT("sv_maxspeed");
+
+ pBot->prev_speed = 0.0; // fake "paused" since bot is NOT stuck
+
+ pBot->f_find_item = 0.0;
+
+ pBot->ladder_dir = LADDER_UNKNOWN;
+ pBot->f_start_use_ladder_time = 0.0;
+ pBot->f_end_use_ladder_time = 0.0;
+ pBot->waypoint_top_of_ladder = FALSE;
+
+ pBot->f_wall_check_time = 0.0;
+ pBot->f_wall_on_right = 0.0;
+ pBot->f_wall_on_left = 0.0;
+ pBot->f_dont_avoid_wall_time = 0.0;
+ pBot->f_look_for_waypoint_time = 0.0;
+ pBot->f_jump_time = 0.0;
+ pBot->f_dont_check_stuck = 0.0;
+
+ // pick a wander direction (50% of the time to the left, 50% to the right)
+ if (RANDOM_LONG(1, 100) <= 50)
+ pBot->wander_dir = WANDER_LEFT;
+ else
+ pBot->wander_dir = WANDER_RIGHT;
+
+ pBot->f_exit_water_time = 0.0;
+
+ pBot->pBotEnemy = NULL;
+ pBot->f_bot_see_enemy_time = gpGlobals->time;
+ pBot->f_bot_find_enemy_time = gpGlobals->time;
+ pBot->pBotUser = NULL;
+ pBot->f_bot_use_time = 0.0;
+ pBot->b_bot_say_killed = FALSE;
+ pBot->f_bot_say_killed = 0.0;
+ pBot->f_sniper_aim_time = 0.0;
+
+ pBot->f_shoot_time = gpGlobals->time;
+ pBot->f_primary_charging = -1.0;
+ pBot->f_secondary_charging = -1.0;
+ pBot->charging_weapon_id = 0;
+
+ pBot->f_pause_time = 0.0;
+ pBot->f_sound_update_time = 0.0;
+ pBot->bot_has_flag = FALSE;
+
+ pBot->b_see_tripmine = FALSE;
+ pBot->b_shoot_tripmine = FALSE;
+ pBot->v_tripmine = Vector(0,0,0);
+
+ pBot->b_use_health_station = FALSE;
+ pBot->f_use_health_time = 0.0;
+ pBot->b_use_HEV_station = FALSE;
+ pBot->f_use_HEV_time = 0.0;
+
+ pBot->b_use_button = FALSE;
+ pBot->f_use_button_time = 0;
+ pBot->b_lift_moving = FALSE;
+
+ pBot->b_use_capture = FALSE;
+ pBot->f_use_capture_time = 0.0;
+ pBot->pCaptureEdict = NULL;
+
+ memset(&(pBot->current_weapon), 0, sizeof(pBot->current_weapon));
+ memset(&(pBot->m_rgAmmo), 0, sizeof(pBot->m_rgAmmo));
+}
+
+
+void BotNameInit( void )
+{
+ FILE *bot_name_fp;
+ char bot_name_filename[256];
+ int str_index;
+ char name_buffer[80];
+ int length, index;
+
+ UTIL_BuildFileName(bot_name_filename, "bot_names.txt", NULL);
+
+ bot_name_fp = fopen(bot_name_filename, "r");
+
+ if (bot_name_fp != NULL)
+ {
+ while ((number_names < MAX_BOT_NAMES) &&
+ (fgets(name_buffer, 80, bot_name_fp) != NULL))
+ {
+ length = strlen(name_buffer);
+
+ if (name_buffer[length-1] == '\n')
+ {
+ name_buffer[length-1] = 0; // remove '\n'
+ length--;
+ }
+
+ str_index = 0;
+ while (str_index < length)
+ {
+ if ((name_buffer[str_index] < ' ') || (name_buffer[str_index] > '~') ||
+ (name_buffer[str_index] == '"'))
+ for (index=str_index; index < length; index++)
+ name_buffer[index] = name_buffer[index+1];
+
+ str_index++;
+ }
+
+ if (name_buffer[0] != 0)
+ {
+ strncpy(bot_names[number_names], name_buffer, BOT_NAME_LEN);
+
+ number_names++;
+ }
+ }
+
+ fclose(bot_name_fp);
+ }
+}
+
+
+void BotPickName( char *name_buffer )
+{
+ int name_index, index;
+ bool used;
+ edict_t *pPlayer;
+ int attempts = 0;
+
+ // see if a name exists from a kicked bot (if so, reuse it)
+ for (index=0; index < 32; index++)
+ {
+ if ((bots[index].is_used == FALSE) && (bots[index].name[0]))
+ {
+ strcpy(name_buffer, bots[index].name);
+
+ return;
+ }
+ }
+
+ name_index = RANDOM_LONG(1, number_names) - 1; // zero based
+
+ // check make sure this name isn't used
+ used = TRUE;
+
+ while (used)
+ {
+ used = FALSE;
+
+ for (index = 1; index <= gpGlobals->maxClients; index++)
+ {
+ pPlayer = INDEXENT(index);
+
+ if (pPlayer && !pPlayer->free)
+ {
+ if (strcmp(bot_names[name_index], STRING(pPlayer->v.netname)) == 0)
+ {
+ used = TRUE;
+ break;
+ }
+ }
+ }
+
+ if (used)
+ {
+ name_index++;
+
+ if (name_index == number_names)
+ name_index = 0;
+
+ attempts++;
+
+ if (attempts == number_names)
+ used = FALSE; // break out of loop even if already used
+ }
+ }
+
+ strcpy(name_buffer, bot_names[name_index]);
+}
+
+
+void BotCreate( edict_t *pPlayer, const char *arg1, const char *arg2,
+ const char *arg3, const char *arg4)
+{
+ edict_t *BotEnt;
+ bot_t *pBot;
+ char c_skin[BOT_SKIN_LEN+1];
+ char c_name[BOT_NAME_LEN+1];
+ int skill;
+ int index;
+ int i, j, length;
+ bool found = FALSE;
+
+
+ if ((mod_id == VALVE_DLL) ||
+ ((mod_id == GEARBOX_DLL) && (pent_info_ctfdetect == NULL)))
+ {
+ int max_skin_index;
+
+ if (mod_id == VALVE_DLL)
+ max_skin_index = VALVE_MAX_SKINS;
+ else // must be GEARBOX_DLL
+ max_skin_index = GEARBOX_MAX_SKINS;
+
+ if ((arg1 == NULL) || (*arg1 == 0))
+ {
+ bool *pSkinUsed;
+
+ // pick a random skin
+ if (mod_id == VALVE_DLL)
+ {
+ index = RANDOM_LONG(0, VALVE_MAX_SKINS-1);
+ pSkinUsed = &valve_skin_used[0];
+ }
+ else // must be GEARBOX_DLL
+ {
+ index = RANDOM_LONG(0, GEARBOX_MAX_SKINS-1);
+ pSkinUsed = &gearbox_skin_used[0];
+ }
+
+ // check if this skin has already been used...
+ while (pSkinUsed[index] == TRUE)
+ {
+ index++;
+
+ if (index == max_skin_index)
+ index = 0;
+ }
+
+ pSkinUsed[index] = TRUE;
+
+ // check if all skins are now used...
+ for (i = 0; i < max_skin_index; i++)
+ {
+ if (pSkinUsed[i] == FALSE)
+ break;
+ }
+
+ // if all skins are used, reset used to FALSE for next selection
+ if (i == max_skin_index)
+ {
+ for (i = 0; i < max_skin_index; i++)
+ pSkinUsed[i] = FALSE;
+ }
+
+ if (mod_id == VALVE_DLL)
+ strcpy( c_skin, valve_bot_skins[index] );
+ else // must be GEARBOX_DLL
+ strcpy( c_skin, gearbox_bot_skins[index] );
+ }
+ else
+ {
+ strncpy( c_skin, arg1, BOT_SKIN_LEN-1 );
+ c_skin[BOT_SKIN_LEN] = 0; // make sure c_skin is null terminated
+ }
+
+ for (i = 0; c_skin[i] != 0; i++)
+ c_skin[i] = tolower( c_skin[i] ); // convert to all lowercase
+
+ index = 0;
+
+ while ((!found) && (index < max_skin_index))
+ {
+ if (mod_id == VALVE_DLL)
+ {
+ if (strcmp(c_skin, valve_bot_skins[index]) == 0)
+ found = TRUE;
+ else
+ index++;
+ }
+ else // must be GEARBOX_DLL
+ {
+ if (strcmp(c_skin, gearbox_bot_skins[index]) == 0)
+ found = TRUE;
+ else
+ index++;
+ }
+ }
+
+ if (found == TRUE)
+ {
+ if ((arg2 != NULL) && (*arg2 != 0))
+ {
+ strncpy( c_name, arg2, BOT_SKIN_LEN-1 );
+ c_name[BOT_SKIN_LEN] = 0; // make sure c_name is null terminated
+ }
+ else
+ {
+ if (number_names > 0)
+ BotPickName( c_name );
+ else if (mod_id == VALVE_DLL)
+ strcpy( c_name, valve_bot_names[index] );
+ else // must be GEARBOX_DLL
+ strcpy( c_name, gearbox_bot_names[index] );
+ }
+ }
+ else
+ {
+ char dir_name[32];
+ char filename[128];
+
+ struct stat stat_str;
+
+ GET_GAME_DIR(dir_name);
+
+#ifndef __linux__
+ sprintf(filename, "%s\\models\\player\\%s", dir_name, c_skin);
+#else
+ sprintf(filename, "%s/models/player/%s", dir_name, c_skin);
+#endif
+
+ if (stat(filename, &stat_str) != 0)
+ {
+#ifndef __linux__
+ sprintf(filename, "valve\\models\\player\\%s", c_skin);
+#else
+ sprintf(filename, "valve/models/player/%s", c_skin);
+#endif
+ if (stat(filename, &stat_str) != 0)
+ {
+ char err_msg[80];
+
+ sprintf( err_msg, "model \"%s\" is unknown.\n", c_skin );
+ if (pPlayer)
+ ClientPrint(pPlayer, HUD_PRINTNOTIFY, err_msg );
+ if (IS_DEDICATED_SERVER())
+ printf(err_msg);
+
+ if (pPlayer)
+ ClientPrint(pPlayer, HUD_PRINTNOTIFY,
+ "use barney, gina, gman, gordon, helmet, hgrunt,\n");
+ if (IS_DEDICATED_SERVER())
+ printf("use barney, gina, gman, gordon, helmet, hgrunt,\n");
+ if (pPlayer)
+ ClientPrint(pPlayer, HUD_PRINTNOTIFY,
+ " recon, robo, scientist, or zombie\n");
+ if (IS_DEDICATED_SERVER())
+ printf(" recon, robo, scientist, or zombie\n");
+ return;
+ }
+ }
+
+ if ((arg2 != NULL) && (*arg2 != 0))
+ {
+ strncpy( c_name, arg2, BOT_NAME_LEN-1 );
+ c_name[BOT_NAME_LEN] = 0; // make sure c_name is null terminated
+ }
+ else
+ {
+ if (number_names > 0)
+ BotPickName( c_name );
+ else
+ {
+ // copy the name of the model to the bot's name...
+ strncpy( c_name, arg1, BOT_NAME_LEN-1 );
+ c_name[BOT_NAME_LEN] = 0; // make sure c_skin is null terminated
+ }
+ }
+ }
+
+ skill = 0;
+
+ if ((arg3 != NULL) && (*arg3 != 0))
+ skill = atoi(arg3);
+
+ if ((skill < 1) || (skill > 5))
+ skill = default_bot_skill;
+ }
+ else
+ {
+ if ((arg3 != NULL) && (*arg3 != 0))
+ {
+ strncpy( c_name, arg3, BOT_NAME_LEN-1 );
+ c_name[BOT_NAME_LEN] = 0; // make sure c_name is null terminated
+ }
+ else
+ {
+ if (number_names > 0)
+ BotPickName( c_name );
+ else
+ strcpy(c_name, "Bot");
+ }
+
+ skill = 0;
+
+ if ((arg4 != NULL) && (*arg4 != 0))
+ skill = atoi(arg4);
+
+ if ((skill < 1) || (skill > 5))
+ skill = default_bot_skill;
+ }
+
+ length = strlen(c_name);
+
+ // remove any illegal characters from name...
+ for (i = 0; i < length; i++)
+ {
+ if ((c_name[i] <= ' ') || (c_name[i] > '~') ||
+ (c_name[i] == '"'))
+ {
+ for (j = i; j < length; j++) // shuffle chars left (and null)
+ c_name[j] = c_name[j+1];
+ length--;
+ }
+ }
+
+ BotEnt = CREATE_FAKE_CLIENT( c_name );
+
+ if (FNullEnt( BotEnt ))
+ {
+ if (pPlayer)
+ ClientPrint( pPlayer, HUD_PRINTNOTIFY, "Max. Players reached. Can't create bot!\n");
+ }
+ else
+ {
+ char ptr[128]; // allocate space for message from ClientConnect
+ char *infobuffer;
+ int clientIndex;
+ int index;
+
+ if (IS_DEDICATED_SERVER())
+ printf("Creating bot...\n");
+ else if (pPlayer)
+ ClientPrint( pPlayer, HUD_PRINTNOTIFY, "Creating bot...\n");
+
+ index = 0;
+ while ((bots[index].is_used) && (index < 32))
+ index++;
+
+ if (index == 32)
+ {
+ ClientPrint( pPlayer, HUD_PRINTNOTIFY, "Can't create bot!\n");
+ return;
+ }
+
+ // create the player entity by calling MOD's player function
+ // (from LINK_ENTITY_TO_CLASS for player object)
+
+ player( VARS(BotEnt) );
+
+ infobuffer = GET_INFOBUFFER( BotEnt );
+ clientIndex = ENTINDEX( BotEnt );
+
+
+ if ((mod_id == VALVE_DLL) || (mod_id == GEARBOX_DLL))
+ SET_CLIENT_KEY_VALUE( clientIndex, infobuffer, "model", c_skin );
+ else // other mods
+ SET_CLIENT_KEY_VALUE( clientIndex, infobuffer, "model", "gina" );
+
+ if (mod_id == CSTRIKE_DLL)
+ {
+ SET_CLIENT_KEY_VALUE( clientIndex, infobuffer, "rate", "3500.000000");
+ SET_CLIENT_KEY_VALUE( clientIndex, infobuffer, "cl_updaterate", "20");
+ SET_CLIENT_KEY_VALUE( clientIndex, infobuffer, "cl_lw", "1");
+ SET_CLIENT_KEY_VALUE( clientIndex, infobuffer, "cl_lc", "1");
+ SET_CLIENT_KEY_VALUE( clientIndex, infobuffer, "tracker", "0");
+ SET_CLIENT_KEY_VALUE( clientIndex, infobuffer, "cl_dlmax", "128");
+ SET_CLIENT_KEY_VALUE( clientIndex, infobuffer, "lefthand", "1");
+ SET_CLIENT_KEY_VALUE( clientIndex, infobuffer, "friends", "0");
+ SET_CLIENT_KEY_VALUE( clientIndex, infobuffer, "dm", "0");
+ SET_CLIENT_KEY_VALUE( clientIndex, infobuffer, "ah", "1");
+ }
+
+ ClientConnect( BotEnt, c_name, "127.0.0.1", ptr );
+
+ // Pieter van Dijk - use instead of DispatchSpawn() - Hip Hip Hurray!
+ ClientPutInServer( BotEnt );
+
+ BotEnt->v.flags |= FL_FAKECLIENT;
+
+ // initialize all the variables for this bot...
+
+ pBot = &bots[index];
+
+ pBot->is_used = TRUE;
+ pBot->respawn_state = RESPAWN_IDLE;
+ pBot->create_time = gpGlobals->time;
+ pBot->name[0] = 0; // name not set by server yet
+ pBot->bot_money = 0;
+
+ strcpy(pBot->skin, c_skin);
+
+ pBot->pEdict = BotEnt;
+
+ pBot->not_started = 1; // hasn't joined game yet
+
+ if (mod_id == TFC_DLL)
+ pBot->start_action = MSG_TFC_IDLE;
+ else if (mod_id == CSTRIKE_DLL)
+ pBot->start_action = MSG_CS_IDLE;
+ else if ((mod_id == GEARBOX_DLL) && (pent_info_ctfdetect != NULL))
+ pBot->start_action = MSG_OPFOR_IDLE;
+ else if (mod_id == FRONTLINE_DLL)
+ pBot->start_action = MSG_FLF_IDLE;
+ else if (mod_id == AVH_DLL)
+ pBot->start_action = MSG_AVH_IDLE;
+ else
+ pBot->start_action = 0; // not needed for non-team MODs
+
+
+ BotSpawnInit(pBot);
+
+ pBot->need_to_initialize = FALSE; // don't need to initialize yet
+
+ BotEnt->v.idealpitch = BotEnt->v.v_angle.x;
+ BotEnt->v.ideal_yaw = BotEnt->v.v_angle.y;
+ BotEnt->v.pitch_speed = BOT_PITCH_SPEED;
+ BotEnt->v.yaw_speed = BOT_YAW_SPEED;
+
+ pBot->warmup = 0; // for Front Line Force
+ pBot->idle_angle = 0.0;
+ pBot->idle_angle_time = 0.0;
+ pBot->round_end = 0;
+ pBot->defender = 0;
+
+ pBot->bot_skill = skill - 1; // 0 based for array indexes
+
+ pBot->bot_team = -1;
+ pBot->bot_class = -1;
+
+ if ((mod_id == TFC_DLL) || (mod_id == CSTRIKE_DLL) ||
+ ((mod_id == GEARBOX_DLL) && (pent_info_ctfdetect != NULL)) ||
+ (mod_id == FRONTLINE_DLL))
+ {
+ if ((arg1 != NULL) && (arg1[0] != 0))
+ {
+ pBot->bot_team = atoi(arg1);
+
+ if ((arg2 != NULL) && (arg2[0] != 0))
+ {
+ pBot->bot_class = atoi(arg2);
+ }
+ }
+ }
+ }
+}
+
+
+int BotInFieldOfView(bot_t *pBot, Vector dest)
+{
+ // find angles from source to destination...
+ Vector entity_angles = UTIL_VecToAngles( dest );
+
+ // make yaw angle 0 to 360 degrees if negative...
+ if (entity_angles.y < 0)
+ entity_angles.y += 360;
+
+ // get bot's current view angle...
+ float view_angle = pBot->pEdict->v.v_angle.y;
+
+ // make view angle 0 to 360 degrees if negative...
+ if (view_angle < 0)
+ view_angle += 360;
+
+ // return the absolute value of angle to destination entity
+ // zero degrees means straight ahead, 45 degrees to the left or
+ // 45 degrees to the right is the limit of the normal view angle
+
+ // rsm - START angle bug fix
+ int angle = abs((int)view_angle - (int)entity_angles.y);
+
+ if (angle > 180)
+ angle = 360 - angle;
+
+ return angle;
+ // rsm - END
+}
+
+
+bool BotEntityIsVisible( bot_t *pBot, Vector dest )
+{
+ TraceResult tr;
+
+ // trace a line from bot's eyes to destination...
+ UTIL_TraceLine( pBot->pEdict->v.origin + pBot->pEdict->v.view_ofs,
+ dest, ignore_monsters,
+ pBot->pEdict->v.pContainingEntity, &tr );
+
+ // check if line of sight to object is not blocked (i.e. visible)
+ if (tr.flFraction >= 1.0)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+
+void BotFindItem( bot_t *pBot )
+{
+ edict_t *pent = NULL;
+ edict_t *pPickupEntity = NULL;
+ Vector pickup_origin;
+ Vector entity_origin;
+ float radius = 500;
+ bool can_pickup;
+ float min_distance;
+ char item_name[40];
+ TraceResult tr;
+ Vector vecStart;
+ Vector vecEnd;
+ int angle_to_entity;
+ edict_t *pEdict = pBot->pEdict;
+
+ pBot->pBotPickupItem = NULL;
+
+ // use a MUCH smaller search radius when waypoints are available
+ if ((num_waypoints > 0) && (pBot->curr_waypoint_index != -1))
+ radius = 100.0;
+ else
+ radius = 500.0;
+
+ min_distance = radius + 1.0;
+
+ while ((pent = UTIL_FindEntityInSphere( pent, pEdict->v.origin, radius )) != NULL)
+ {
+ can_pickup = FALSE; // assume can't use it until known otherwise
+
+ strcpy(item_name, STRING(pent->v.classname));
+
+ // see if this is a "func_" type of entity (func_button, etc.)...
+ if (strncmp("func_", item_name, 5) == 0)
+ {
+ // BModels have 0,0,0 for origin so must use VecBModelOrigin...
+ entity_origin = VecBModelOrigin(pent);
+
+ vecStart = pEdict->v.origin + pEdict->v.view_ofs;
+ vecEnd = entity_origin;
+
+ angle_to_entity = BotInFieldOfView( pBot, vecEnd - vecStart );
+
+ // check if entity is outside field of view (+/- 45 degrees)
+ if (angle_to_entity > 45)
+ continue; // skip this item if bot can't "see" it
+
+ // check if entity is a ladder (ladders are a special case)
+ // DON'T search for ladders if there are waypoints in this level...
+ if ((strcmp("func_ladder", item_name) == 0) && (num_waypoints == 0))
+ {
+ // force ladder origin to same z coordinate as bot since
+ // the VecBModelOrigin is the center of the ladder. For
+ // LONG ladders, the center MAY be hundreds of units above
+ // the bot. Fake an origin at the same level as the bot...
+
+ entity_origin.z = pEdict->v.origin.z;
+ vecEnd = entity_origin;
+
+ // trace a line from bot's eyes to func_ladder entity...
+ UTIL_TraceLine( vecStart, vecEnd, dont_ignore_monsters,
+ pEdict->v.pContainingEntity, &tr);
+
+ // check if traced all the way up to the entity (didn't hit wall)
+ if (tr.flFraction >= 1.0)
+ {
+ // find distance to item for later use...
+ float distance = (vecEnd - vecStart).Length( );
+
+ // use the ladder about 100% of the time, if haven't
+ // used a ladder in at least 5 seconds...
+ if ((RANDOM_LONG(1, 100) <= 100) &&
+ ((pBot->f_end_use_ladder_time + 5.0) < gpGlobals->time))
+ {
+ // if close to ladder...
+ if (distance < 100)
+ {
+ // don't avoid walls for a while
+ pBot->f_dont_avoid_wall_time = gpGlobals->time + 5.0;
+ }
+
+ can_pickup = TRUE;
+ }
+ }
+ }
+ else
+ {
+ // trace a line from bot's eyes to func_ entity...
+ UTIL_TraceLine( vecStart, vecEnd, dont_ignore_monsters,
+ pEdict->v.pContainingEntity, &tr);
+
+ // check if traced all the way up to the entity (didn't hit wall)
+ if (strcmp(item_name, STRING(tr.pHit->v.classname)) == 0)
+ {
+ // find distance to item for later use...
+ float distance = (vecEnd - vecStart).Length( );
+
+ // check if entity is wall mounted health charger...
+ if (strcmp("func_healthcharger", item_name) == 0)
+ {
+ // check if the bot can use this item and
+ // check if the recharger is ready to use (has power left)...
+ if ((pEdict->v.health < 100) && (pent->v.frame == 0))
+ {
+ // check if flag not set...
+ if (!pBot->b_use_health_station)
+ {
+ // check if close enough and facing it directly...
+ if ((distance < PLAYER_SEARCH_RADIUS) &&
+ (angle_to_entity <= 10))
+ {
+ pBot->b_use_health_station = TRUE;
+ pBot->f_use_health_time = gpGlobals->time;
+ }
+
+ // if close to health station...
+ if (distance < 100)
+ {
+ // don't avoid walls for a while
+ pBot->f_dont_avoid_wall_time = gpGlobals->time + 5.0;
+ }
+
+ can_pickup = TRUE;
+ }
+ }
+ else
+ {
+ // don't need or can't use this item...
+ pBot->b_use_health_station = FALSE;
+ }
+ }
+
+ // check if entity is wall mounted HEV charger...
+ else if (strcmp("func_recharge", item_name) == 0)
+ {
+ // check if the bot can use this item and
+ // check if the recharger is ready to use (has power left)...
+ if ((pEdict->v.armorvalue < VALVE_MAX_NORMAL_BATTERY) &&
+ (pent->v.frame == 0))
+ {
+ // check if flag not set and facing it...
+ if (!pBot->b_use_HEV_station)
+ {
+ // check if close enough and facing it directly...
+ if ((distance < PLAYER_SEARCH_RADIUS) &&
+ (angle_to_entity <= 10))
+ {
+ pBot->b_use_HEV_station = TRUE;
+ pBot->f_use_HEV_time = gpGlobals->time;
+ }
+
+ // if close to HEV recharger...
+ if (distance < 100)
+ {
+ // don't avoid walls for a while
+ pBot->f_dont_avoid_wall_time = gpGlobals->time + 5.0;
+ }
+
+ can_pickup = TRUE;
+ }
+ }
+ else
+ {
+ // don't need or can't use this item...
+ pBot->b_use_HEV_station = FALSE;
+ }
+ }
+
+ // check if entity is a button...
+ else if (strcmp("func_button", item_name) == 0)
+ {
+ // use the button about 100% of the time, if haven't
+ // used a button in at least 5 seconds...
+ if ((RANDOM_LONG(1, 100) <= 100) &&
+ ((pBot->f_use_button_time + 5) < gpGlobals->time))
+ {
+ // check if flag not set and facing it...
+ if (!pBot->b_use_button)
+ {
+ // check if close enough and facing it directly...
+ if ((distance < PLAYER_SEARCH_RADIUS) &&
+ (angle_to_entity <= 10))
+ {
+ pBot->b_use_button = TRUE;
+ pBot->b_lift_moving = FALSE;
+ pBot->f_use_button_time = gpGlobals->time;
+ }
+
+ // if close to button...
+ if (distance < 100)
+ {
+ // don't avoid walls for a while
+ pBot->f_dont_avoid_wall_time = gpGlobals->time + 5.0;
+ }
+
+ can_pickup = TRUE;
+ }
+ }
+ else
+ {
+ // don't need or can't use this item...
+ pBot->b_use_button = FALSE;
+ }
+ }
+ }
+ }
+ }
+ else // everything else...
+ {
+ entity_origin = pent->v.origin;
+
+ vecStart = pEdict->v.origin + pEdict->v.view_ofs;
+ vecEnd = entity_origin;
+
+ // find angles from bot origin to entity...
+ angle_to_entity = BotInFieldOfView( pBot, vecEnd - vecStart );
+
+ // check if entity is outside field of view (+/- 45 degrees)
+ if (angle_to_entity > 45)
+ continue; // skip this item if bot can't "see" it
+
+ // check if line of sight to object is not blocked (i.e. visible)
+ if (BotEntityIsVisible( pBot, vecEnd ))
+ {
+ // check if entity is a weapon...
+ if (strncmp("weapon_", item_name, 7) == 0)
+ {
+ if (pent->v.effects & EF_NODRAW)
+ {
+ // someone owns this weapon or it hasn't respawned yet
+ continue;
+ }
+
+ can_pickup = TRUE;
+ }
+
+ // check if entity is ammo...
+ else if (strncmp("ammo_", item_name, 5) == 0)
+ {
+ // check if the item is not visible (i.e. has not respawned)
+ if (pent->v.effects & EF_NODRAW)
+ continue;
+
+ can_pickup = TRUE;
+ }
+
+ // check if entity is a battery...
+ else if (strcmp("item_battery", item_name) == 0)
+ {
+ // check if the item is not visible (i.e. has not respawned)
+ if (pent->v.effects & EF_NODRAW)
+ continue;
+
+ // check if the bot can use this item...
+ if (pEdict->v.armorvalue < VALVE_MAX_NORMAL_BATTERY)
+ {
+ can_pickup = TRUE;
+ }
+ }
+
+ // check if entity is a healthkit...
+ else if (strcmp("item_healthkit", item_name) == 0)
+ {
+ // check if the item is not visible (i.e. has not respawned)
+ if (pent->v.effects & EF_NODRAW)
+ continue;
+
+ // check if the bot can use this item...
+ if (pEdict->v.health < 100)
+ {
+ can_pickup = TRUE;
+ }
+ }
+
+ // check if entity is a packed up weapons box...
+ else if (strcmp("weaponbox", item_name) == 0)
+ {
+ can_pickup = TRUE;
+ }
+
+ // check if entity is the spot from RPG laser
+ else if (strcmp("laser_spot", item_name) == 0)
+ {
+ }
+
+ // check if entity is an armed tripmine
+ //else if (strcmp("monster_tripmine", item_name) == 0)
+ else if (strcmp(kwsDeployedMine, item_name) == 0)
+ {
+ float distance = (pent->v.origin - pEdict->v.origin).Length( );
+
+ if (pBot->b_see_tripmine)
+ {
+ // see if this tripmine is closer to bot...
+ if (distance < (pBot->v_tripmine - pEdict->v.origin).Length())
+ {
+ pBot->v_tripmine = pent->v.origin;
+ pBot->b_shoot_tripmine = FALSE;
+
+ // see if bot is far enough to shoot the tripmine...
+ if (distance >= 375)
+ {
+ pBot->b_shoot_tripmine = TRUE;
+ }
+ }
+ }
+ else
+ {
+ pBot->b_see_tripmine = TRUE;
+ pBot->v_tripmine = pent->v.origin;
+ pBot->b_shoot_tripmine = FALSE;
+
+ // see if bot is far enough to shoot the tripmine...
+ if (distance >= 375) // 375 is damage radius
+ {
+ pBot->b_shoot_tripmine = TRUE;
+ }
+ }
+ }
+
+ // check if entity is an armed satchel charge
+ else if (strcmp("monster_satchel", item_name) == 0)
+ {
+ }
+
+ // check if entity is a snark (squeak grenade)
+ else if (strcmp("monster_snark", item_name) == 0)
+ {
+ }
+
+ else if ((mod_id == FRONTLINE_DLL) && (!pBot->defender) &&
+ (strcmp("capture_point", item_name) == 0))
+ {
+ int team = UTIL_GetTeam(pEdict); // skin and team must match
+
+ if (flf_bug_fix)
+ team = 1 - team; // BACKWARDS bug!
+
+ // check if flag not set and point not captured...
+ if ((!pBot->b_use_capture) && (pent->v.skin == team))
+ {
+ float distance = (pent->v.origin - pEdict->v.origin).Length( );
+
+ // check if close enough and facing it directly...
+ if ((distance < FLF_PLAYER_SEARCH_RADIUS) &&
+ (angle_to_entity <= 20))
+ {
+ pBot->b_use_capture = TRUE;
+ pBot->f_use_capture_time = gpGlobals->time + 8.0;
+ pBot->pCaptureEdict = pent;
+ }
+
+ // if close to capture point...
+ if (distance < 160)
+ {
+ // don't avoid walls for a while
+ pBot->f_dont_avoid_wall_time = gpGlobals->time + 5.0;
+ }
+
+ can_pickup = TRUE;
+ }
+ }
+
+ } // end if object is visible
+ } // end else not "func_" entity
+
+ if (can_pickup) // if the bot found something it can pickup...
+ {
+ float distance = (entity_origin - pEdict->v.origin).Length( );
+
+ // see if it's the closest item so far...
+ if (distance < min_distance)
+ {
+ min_distance = distance; // update the minimum distance
+ pPickupEntity = pent; // remember this entity
+ pickup_origin = entity_origin; // remember location of entity
+ }
+ }
+ } // end while loop
+
+ if (pPickupEntity != NULL)
+ {
+ // let's head off toward that item...
+ Vector v_item = pickup_origin - pEdict->v.origin;
+
+ Vector bot_angles = UTIL_VecToAngles( v_item );
+
+ pEdict->v.ideal_yaw = bot_angles.y;
+
+ BotFixIdealYaw(pEdict);
+
+ pBot->pBotPickupItem = pPickupEntity; // save the item bot is trying to get
+ }
+}
+
+
+void BotThink( bot_t *pBot )
+{
+ int index = 0;
+ Vector v_diff; // vector from previous to current location
+ float pitch_degrees;
+ float yaw_degrees;
+ float moved_distance; // length of v_diff vector (distance bot moved)
+ TraceResult tr;
+ bool found_waypoint;
+ bool is_idle;
+
+ edict_t *pEdict = pBot->pEdict;
+
+
+ pEdict->v.flags |= FL_FAKECLIENT;
+
+ if (pBot->name[0] == 0) // name filled in yet?
+ strcpy(pBot->name, STRING(pBot->pEdict->v.netname));
+
+
+// TheFatal - START from Advanced Bot Framework (Thanks Rich!)
+
+ // adjust the millisecond delay based on the frame rate interval...
+ if (pBot->msecdel <= gpGlobals->time)
+ {
+ pBot->msecdel = gpGlobals->time + 0.5;
+ if (pBot->msecnum > 0)
+ pBot->msecval = 450.0/pBot->msecnum;
+ pBot->msecnum = 0;
+ }
+ else
+ pBot->msecnum++;
+
+ if (pBot->msecval < 1) // don't allow msec to be less than 1...
+ pBot->msecval = 1;
+
+ if (pBot->msecval > 100) // ...or greater than 100
+ pBot->msecval = 100;
+
+// TheFatal - END
+
+
+ pEdict->v.button = 0;
+ pBot->f_move_speed = 0.0;
+
+ if(pBot->mBotPlayMode == PLAYMODE_READYROOM)
+ {
+ // Look at desired team and head to nearest start entity
+ AvHClassType theClassType = AVH_CLASS_TYPE_UNDEFINED;
+
+ FakeClientCommand(pEdict, kcAutoAssign, NULL, NULL);
+
+ // bot has now joined the game (doesn't need to be started)
+ pBot->not_started = 0;
+ }
+
+ // if the bot hasn't selected stuff to start the game yet, go do that...
+ if (pBot->not_started)
+ {
+ BotStartGame( pBot );
+
+ // Do this to test server performance
+ //return;
+
+ g_engfuncs.pfnRunPlayerMove( pEdict, pEdict->v.v_angle, 0.0,
+ 0, 0, pEdict->v.button, 0, pBot->msecval);
+
+ //return;
+ }
+
+ if((pBot->mOrderType != ORDERTYPE_UNDEFINED) && (!pBot->mOrderCompleted))
+ {
+ // Every once in a while mention our order
+ if(RANDOM_LONG(0, 200) == 0)
+ {
+ char theMessage[256];
+ sprintf(theMessage, "Order type: %d, target type: %d\n", pBot->mOrderType, pBot->mOrderTargetType);
+ //UTIL_HostSay(pBot->pEdict, 0, theMessage);
+ }
+ }
+ else
+ {
+ // Occasionally ask for orders when not doing anything else
+ if(RANDOM_LONG(0, 1800) == 0)
+ {
+ if(pBot->mTimeOfNextOrderRequest == -1)
+ {
+ pBot->mTimeOfNextOrderRequest = gpGlobals->time;
+ }
+ }
+ }
+
+ if(RANDOM_LONG(0, 1000))
+ {
+ pBot->mTimeOfNextRandomSaying = gpGlobals->time;
+ }
+
+ // If we're out of ammo, occasionally ask for more
+ // Get current weapon
+ int theWeaponID = pBot->current_weapon.iId;
+ if(theWeaponID > 0)
+ {
+ if((pBot->current_weapon.iAmmo1 != -1) && (pBot->current_weapon.iClip <= 10))
+ {
+ if(RANDOM_LONG(0, 40))
+ {
+ if(pBot->mTimeOfNextAmmoRequest == -1)
+ {
+ pBot->mTimeOfNextAmmoRequest = gpGlobals->time;
+ }
+ }
+ }
+ }
+
+
+ if ((pBot->b_bot_say_killed) && (pBot->f_bot_say_killed < gpGlobals->time))
+ {
+ int whine_index = 0;
+ bool used;
+ int i, recent_count;
+ char msg[120];
+
+ pBot->b_bot_say_killed = FALSE;
+
+ recent_count = 0;
+
+ while (recent_count < 5)
+ {
+ whine_index = RANDOM_LONG(0, whine_count-1);
+
+ used = FALSE;
+
+ for (i=0; i < 5; i++)
+ {
+ if (recent_bot_whine[i] == whine_index)
+ used = TRUE;
+ }
+
+ if (used)
+ recent_count++;
+ else
+ break;
+ }
+
+ for (i=4; i > 0; i--)
+ recent_bot_whine[i] = recent_bot_whine[i-1];
+
+ recent_bot_whine[0] = whine_index;
+
+ if (strstr(bot_whine[whine_index], "%s") != NULL) // is "%s" in whine text?
+ sprintf(msg, bot_whine[whine_index], STRING(pBot->killer_edict->v.netname));
+ else
+ sprintf(msg, bot_whine[whine_index]);
+
+ UTIL_HostSay(pEdict, 0, msg);
+ }
+
+ // if the bot is dead, randomly press fire to respawn...
+ if ((pEdict->v.health < 1) || (pEdict->v.deadflag != DEAD_NO))
+ {
+ if (pBot->need_to_initialize)
+ {
+ BotSpawnInit(pBot);
+
+ // did another player kill this bot AND bot whine messages loaded AND
+ // has the bot been alive for at least 15 seconds AND
+ if ((pBot->killer_edict != NULL) && (whine_count > 0) &&
+ ((pBot->f_bot_spawn_time + 15.0) <= gpGlobals->time))
+ {
+ if ((RANDOM_LONG(1,100) <= 10))
+ {
+ pBot->b_bot_say_killed = TRUE;
+ pBot->f_bot_say_killed = gpGlobals->time + 10.0 + RANDOM_FLOAT(0.0, 5.0);
+ }
+ }
+
+ pBot->need_to_initialize = FALSE;
+ }
+
+ if (RANDOM_LONG(1, 100) > 50)
+ pEdict->v.button = IN_ATTACK;
+
+ g_engfuncs.pfnRunPlayerMove( pEdict, pEdict->v.v_angle, pBot->f_move_speed,
+ 0, 0, pEdict->v.button, 0, pBot->msecval);
+
+ return;
+ }
+
+ // set this for the next time the bot dies so it will initialize stuff
+ if (pBot->need_to_initialize == FALSE)
+ {
+ pBot->need_to_initialize = TRUE;
+ pBot->f_bot_spawn_time = gpGlobals->time;
+ }
+
+ is_idle = FALSE;
+
+ if ((mod_id == FRONTLINE_DLL) && (pBot->round_end))
+ {
+ if (pBot->warmup) // has warmup started (i.e. start of round?)
+ {
+ pBot->round_end = 0;
+
+ BotSpawnInit(pBot);
+ }
+
+ is_idle = TRUE;
+
+ flf_bug_fix = 0; // BACKWARDS bug off now!
+ }
+
+ if ((mod_id == FRONTLINE_DLL) && (pBot->warmup) && (!pBot->defender))
+ {
+ if (pBot->curr_waypoint_index == -1)
+ {
+ // find the nearest visible waypoint
+ int i = WaypointFindNearest(pEdict, REACHABLE_RANGE, pBot->defender);
+
+ if (i != -1)
+ {
+ Vector v_direction = waypoints[i].origin - pEdict->v.origin;
+
+ Vector bot_angles = UTIL_VecToAngles( v_direction );
+
+ pBot->idle_angle = bot_angles.y;
+ }
+ else
+ pBot->idle_angle = pEdict->v.v_angle.y;
+ }
+
+ is_idle = TRUE;
+ }
+
+ if (pBot->blinded_time > gpGlobals->time)
+ {
+ is_idle = TRUE; // don't do anything while blinded
+ }
+
+ if(CVAR_GET_FLOAT("freezebots") > 0)
+ {
+ return; // Don't move.
+ }
+
+ if (is_idle)
+ {
+ if (pBot->idle_angle_time <= gpGlobals->time)
+ {
+ pBot->idle_angle_time = gpGlobals->time + RANDOM_FLOAT(0.5, 2.0);
+
+ pEdict->v.ideal_yaw = pBot->idle_angle + RANDOM_FLOAT(0.0, 40.0) - 20.0;
+
+ BotFixIdealYaw(pEdict);
+ }
+
+ // turn towards ideal_yaw by yaw_speed degrees (slower than normal)
+ BotChangeYaw( pBot, pEdict->v.yaw_speed / 2 );
+
+ g_engfuncs.pfnRunPlayerMove( pEdict, pEdict->v.v_angle, pBot->f_move_speed,
+ 0, 0, pEdict->v.button, 0, pBot->msecval);
+
+ return;
+ }
+ else
+ {
+ pBot->idle_angle = pEdict->v.v_angle.y;
+ }
+
+ // check if time to check for player sounds (if don't already have enemy)
+ if ((pBot->f_sound_update_time <= gpGlobals->time) &&
+ (pBot->pBotEnemy == NULL))
+ {
+ int ind;
+ edict_t *pPlayer;
+
+ pBot->f_sound_update_time = gpGlobals->time + 1.0;
+
+ for (ind = 1; ind <= gpGlobals->maxClients; ind++)
+ {
+ pPlayer = INDEXENT(ind);
+
+ // is this player slot is valid and it's not this bot...
+ if ((pPlayer) && (!pPlayer->free) && (pPlayer != pEdict))
+ {
+ // if observer mode enabled, don't listen to this player...
+ if ((b_observer_mode) && !(pPlayer->v.flags & FL_FAKECLIENT))
+ continue;
+
+ if (IsAlive(pPlayer) &&
+ (FBitSet(pPlayer->v.flags, FL_CLIENT) ||
+ FBitSet(pPlayer->v.flags, FL_FAKECLIENT)))
+ {
+ // check for sounds being made by other players...
+ if (UpdateSounds(pEdict, pPlayer))
+ {
+ // don't check for sounds for another 30 seconds
+ pBot->f_sound_update_time = gpGlobals->time + 30.0;
+ }
+ }
+ }
+ }
+ }
+
+ pBot->f_move_speed = pBot->f_max_speed; // set to max speed
+
+ if (pBot->prev_time <= gpGlobals->time)
+ {
+ // see how far bot has moved since the previous position...
+ v_diff = pBot->v_prev_origin - pEdict->v.origin;
+ moved_distance = v_diff.Length();
+
+ // save current position as previous
+ pBot->v_prev_origin = pEdict->v.origin;
+ pBot->prev_time = gpGlobals->time + 0.2;
+ }
+ else
+ {
+ moved_distance = 2.0;
+ }
+
+ // if the bot is under water, adjust pitch by pitch_speed degrees
+ if ((pEdict->v.waterlevel == 2) ||
+ (pEdict->v.waterlevel == 3))
+ {
+ // turn towards ideal_pitch by pitch_speed degrees
+ pitch_degrees = BotChangePitch( pBot, pEdict->v.pitch_speed );
+ }
+ else
+ pitch_degrees = 0.0;
+
+ // turn towards ideal_yaw by yaw_speed degrees
+ yaw_degrees = BotChangeYaw( pBot, pEdict->v.yaw_speed );
+
+ if ((pitch_degrees >= pEdict->v.pitch_speed) ||
+ (yaw_degrees >= pEdict->v.yaw_speed))
+ {
+ pBot->f_move_speed = 0.0; // don't move while turning a lot
+ }
+ else if ((pitch_degrees >= 10) ||
+ (yaw_degrees >= 10)) // turning more than 10 degrees?
+ {
+ pBot->f_move_speed = pBot->f_move_speed / 4; // slow down while turning
+ }
+ else // else handle movement related actions...
+ {
+ if (b_botdontshoot == 0)
+ {
+ if ((mod_id == TFC_DLL) && (pBot->bot_has_flag == TRUE))
+ {
+ // is it time to check whether bot should look for enemies yet?
+ if (pBot->f_bot_find_enemy_time <= gpGlobals->time)
+ {
+ pBot->f_bot_find_enemy_time = gpGlobals->time + 5.0;
+
+ if (RANDOM_LONG(1, 100) <= 40)
+ pBot->pBotEnemy = BotFindEnemy( pBot );
+ }
+ }
+ else
+ {
+ // Now that bots scan every entity in the world, do this less often
+ if(RANDOM_LONG(1, 100) <= 20)
+ {
+ pBot->pBotEnemy = BotFindEnemy( pBot );
+ }
+ }
+ }
+ else
+ pBot->pBotEnemy = NULL; // clear enemy pointer (no ememy for you!)
+
+ if (pBot->pBotEnemy != NULL) // does an enemy exist?
+ {
+ BotShootAtEnemy( pBot ); // shoot at the enemy
+
+ pBot->f_pause_time = 0; // dont't pause if enemy exists
+ }
+
+ else if (pBot->f_pause_time > gpGlobals->time) // is bot "paused"?
+ {
+ // you could make the bot look left then right, or look up
+ // and down, to make it appear that the bot is hunting for
+ // something (don't do anything right now)
+ }
+
+ // is bot being "used" and can still follow "user"?
+ else if ((pBot->pBotUser != NULL) && BotFollowUser( pBot ))
+ {
+ // do nothing here!
+ ;
+ }
+
+ else
+ {
+ // no enemy, let's just wander around...
+
+ if ((pEdict->v.waterlevel != 2) && // is bot NOT under water?
+ (pEdict->v.waterlevel != 3))
+ {
+ // reset pitch to 0 (level horizontally)
+ pEdict->v.idealpitch = 0;
+ pEdict->v.v_angle.x = 0;
+ }
+
+ pEdict->v.v_angle.z = 0; // reset roll to 0 (straight up and down)
+
+ pEdict->v.angles.x = 0;
+ pEdict->v.angles.y = pEdict->v.v_angle.y;
+ pEdict->v.angles.z = 0;
+
+ // check if bot should look for items now or not...
+ if (pBot->f_find_item < gpGlobals->time)
+ {
+ BotFindItem( pBot ); // see if there are any visible items
+ }
+
+ // check if bot sees a tripmine...
+ if (pBot->b_see_tripmine)
+ {
+ // check if bot can shoot the tripmine...
+ if ((pBot->b_shoot_tripmine) && BotShootTripmine( pBot ))
+ {
+ // shot at tripmine, may or may not have hit it, clear
+ // flags anyway, next BotFindItem will see it again if
+ // it is still there...
+
+ pBot->b_shoot_tripmine = FALSE;
+ pBot->b_see_tripmine = FALSE;
+
+ // pause for a while to allow tripmine to explode...
+ pBot->f_pause_time = gpGlobals->time + 0.5;
+ }
+ else // run away!!!
+ {
+ Vector tripmine_angles;
+
+ tripmine_angles = UTIL_VecToAngles( pBot->v_tripmine - pEdict->v.origin );
+
+ // face away from the tripmine
+ pEdict->v.ideal_yaw += 180; // rotate 180 degrees
+
+ BotFixIdealYaw(pEdict);
+
+ pBot->b_see_tripmine = FALSE;
+
+ pBot->f_move_speed = 0; // don't run while turning
+ }
+ }
+
+ // check if should use wall mounted health station...
+ else if (pBot->b_use_health_station)
+ {
+ if ((pBot->f_use_health_time + 10.0) > gpGlobals->time)
+ {
+ pBot->f_move_speed = 0; // don't move while using health station
+
+ pEdict->v.button = IN_USE;
+ }
+ else
+ {
+ // bot is stuck trying to "use" a health station...
+
+ pBot->b_use_health_station = FALSE;
+
+ // don't look for items for a while since the bot
+ // could be stuck trying to get to an item
+ pBot->f_find_item = gpGlobals->time + 0.5;
+ }
+ }
+
+ // check if should use wall mounted HEV station...
+ else if (pBot->b_use_HEV_station)
+ {
+ if ((pBot->f_use_HEV_time + 10.0) > gpGlobals->time)
+ {
+ pBot->f_move_speed = 0; // don't move while using HEV station
+
+ pEdict->v.button = IN_USE;
+ }
+ else
+ {
+ // bot is stuck trying to "use" a HEV station...
+
+ pBot->b_use_HEV_station = FALSE;
+
+ // don't look for items for a while since the bot
+ // could be stuck trying to get to an item
+ pBot->f_find_item = gpGlobals->time + 0.5;
+ }
+ }
+
+ // check if should capture a point by using it...
+ else if (pBot->b_use_capture)
+ {
+ int team = UTIL_GetTeam(pEdict); // skin and team must match
+
+ if (flf_bug_fix)
+ team = 1 - team; // BACKWARDS bug fix!
+
+ // still capturing and hasn't captured yet...
+ if ((pBot->f_use_capture_time > gpGlobals->time) &&
+ (pBot->pCaptureEdict->v.skin == team))
+ {
+ pBot->f_move_speed = 0; // don't move while capturing
+
+ pEdict->v.button = IN_USE;
+ }
+ else
+ {
+ // bot is stuck trying to "use" a capture point...
+
+ pBot->b_use_capture = FALSE;
+
+ // don't look for items for a while since the bot
+ // could be stuck trying to get to an item
+ pBot->f_find_item = gpGlobals->time + 0.5;
+ }
+ }
+
+ else if (pBot->b_use_button)
+ {
+ pBot->f_move_speed = 0; // don't move while using elevator
+
+ BotUseLift( pBot, moved_distance );
+ }
+
+ else
+ {
+ if (pEdict->v.waterlevel == 3) // check if the bot is underwater...
+ {
+ BotUnderWater( pBot );
+ }
+
+ found_waypoint = FALSE;
+
+ // if the bot is not trying to get to something AND
+ // it is time to look for a waypoint AND
+ // there are waypoints in this level...
+
+ if ((pBot->pBotPickupItem == NULL) &&
+ (pBot->f_look_for_waypoint_time <= gpGlobals->time) &&
+ (num_waypoints != 0))
+ {
+ found_waypoint = BotHeadTowardWaypoint(pBot);
+ }
+
+ // check if the bot is on a ladder...
+ if (pEdict->v.movetype == MOVETYPE_FLY)
+ {
+ // check if bot JUST got on the ladder...
+ if ((pBot->f_end_use_ladder_time + 1.0) < gpGlobals->time)
+ pBot->f_start_use_ladder_time = gpGlobals->time;
+
+ // go handle the ladder movement
+ BotOnLadder( pBot, moved_distance );
+
+ pBot->f_dont_avoid_wall_time = gpGlobals->time + 2.0;
+ pBot->f_end_use_ladder_time = gpGlobals->time;
+ }
+ else
+ {
+ // check if the bot JUST got off the ladder...
+ if ((pBot->f_end_use_ladder_time + 1.0) > gpGlobals->time)
+ {
+ pBot->ladder_dir = LADDER_UNKNOWN;
+ }
+ }
+
+ // if the bot isn't headed toward a waypoint...
+ if (found_waypoint == FALSE)
+ {
+ TraceResult tr;
+
+ // check if we should be avoiding walls
+ if (pBot->f_dont_avoid_wall_time <= gpGlobals->time)
+ {
+ // let's just randomly wander around
+ if (BotStuckInCorner( pBot ))
+ {
+ pEdict->v.ideal_yaw += 180; // turn 180 degrees
+
+ BotFixIdealYaw(pEdict);
+
+ pBot->f_move_speed = 0; // don't move while turning
+ pBot->f_dont_avoid_wall_time = gpGlobals->time + 1.0;
+
+ moved_distance = 2.0; // dont use bot stuck code
+ }
+ else
+ {
+ // check if there is a wall on the left...
+ if (!BotCheckWallOnLeft( pBot ))
+ {
+ // if there was a wall on the left over 1/2 a second ago then
+ // 20% of the time randomly turn between 45 and 60 degrees
+
+ if ((pBot->f_wall_on_left != 0) &&
+ (pBot->f_wall_on_left <= gpGlobals->time - 0.5) &&
+ (RANDOM_LONG(1, 100) <= 20))
+ {
+ pEdict->v.ideal_yaw += RANDOM_LONG(45, 60);
+
+ BotFixIdealYaw(pEdict);
+
+ pBot->f_move_speed = 0; // don't move while turning
+ pBot->f_dont_avoid_wall_time = gpGlobals->time + 1.0;
+ }
+
+ pBot->f_wall_on_left = 0; // reset wall detect time
+ }
+ else if (!BotCheckWallOnRight( pBot ))
+ {
+ // if there was a wall on the right over 1/2 a second ago then
+ // 20% of the time randomly turn between 45 and 60 degrees
+
+ if ((pBot->f_wall_on_right != 0) &&
+ (pBot->f_wall_on_right <= gpGlobals->time - 0.5) &&
+ (RANDOM_LONG(1, 100) <= 20))
+ {
+ pEdict->v.ideal_yaw -= RANDOM_LONG(45, 60);
+
+ BotFixIdealYaw(pEdict);
+
+ pBot->f_move_speed = 0; // don't move while turning
+ pBot->f_dont_avoid_wall_time = gpGlobals->time + 1.0;
+ }
+
+ pBot->f_wall_on_right = 0; // reset wall detect time
+ }
+ }
+ }
+
+ // check if bot is about to hit a wall. TraceResult gets returned
+ if ((pBot->f_dont_avoid_wall_time <= gpGlobals->time) &&
+ BotCantMoveForward( pBot, &tr ))
+ {
+ // ADD LATER
+ // need to check if bot can jump up or duck under here...
+ // ADD LATER
+
+ BotTurnAtWall( pBot, &tr );
+ }
+ }
+
+ // check if bot is on a ladder and has been on a ladder for
+ // more than 5 seconds...
+ if ((pEdict->v.movetype == MOVETYPE_FLY) &&
+ (pBot->f_start_use_ladder_time > 0.0) &&
+ ((pBot->f_start_use_ladder_time + 5.0) <= gpGlobals->time))
+ {
+ // bot is stuck on a ladder...
+
+ BotRandomTurn(pBot);
+
+ // don't look for items for 2 seconds
+ pBot->f_find_item = gpGlobals->time + 2.0;
+
+ pBot->f_start_use_ladder_time = 0.0; // reset start ladder time
+ }
+
+ // check if the bot hasn't moved much since the last location
+ // (and NOT on a ladder since ladder stuck handled elsewhere)
+ // (don't check for stuck if f_dont_check_stuck in the future)
+ if ((moved_distance <= 1.0) && (pBot->prev_speed >= 1.0) &&
+ (pEdict->v.movetype != MOVETYPE_FLY) &&
+ (pBot->f_dont_check_stuck < gpGlobals->time))
+ {
+ // the bot must be stuck!
+
+ pBot->f_dont_avoid_wall_time = gpGlobals->time + 1.0;
+ pBot->f_look_for_waypoint_time = gpGlobals->time + 1.0;
+
+ if (BotCanJumpUp( pBot )) // can the bot jump onto something?
+ {
+ if ((pBot->f_jump_time + 2.0) <= gpGlobals->time)
+ {
+ pBot->f_jump_time = gpGlobals->time;
+ pEdict->v.button |= IN_JUMP; // jump up and move forward
+ }
+ else
+ {
+ // bot already tried jumping less than two seconds ago, just turn
+ BotRandomTurn(pBot);
+ }
+ }
+ else if (BotCanDuckUnder( pBot )) // can the bot duck under something?
+ {
+ pEdict->v.button |= IN_DUCK; // duck down and move forward
+ }
+ else
+ {
+ BotRandomTurn(pBot);
+
+ // is the bot trying to get to an item?...
+ if (pBot->pBotPickupItem != NULL)
+ {
+ // don't look for items for a while since the bot
+ // could be stuck trying to get to an item
+ pBot->f_find_item = gpGlobals->time + 0.5;
+ }
+ }
+ }
+
+ // should the bot pause for a while here?
+ // (don't pause on ladders or while being "used"...
+ if ((RANDOM_LONG(1, 1000) <= pause_frequency[pBot->bot_skill]) &&
+ (pEdict->v.movetype != MOVETYPE_FLY) &&
+ (pBot->pBotUser == NULL))
+ {
+ // set the time that the bot will stop "pausing"
+ pBot->f_pause_time = gpGlobals->time +
+ RANDOM_FLOAT(pause_time[pBot->bot_skill][0],
+ pause_time[pBot->bot_skill][1]);
+ }
+ }
+ }
+ }
+
+ // Potentially morph up if we're an alien
+ AvHUser3 theUser3 = (AvHUser3)(pBot->pEdict->v.iuser3);
+ if((pBot->pBotEnemy == NULL) && (theUser3 >= AVH_USER3_ALIEN_PLAYER1) && (theUser3 <= AVH_USER3_ALIEN_PLAYER4))
+ {
+ int theMaxUpgrade = (int)(AVH_USER3_ALIEN_PLAYER5 - theUser3);
+ //const UpgradeCostListType& theUpgradeCosts = GetGameRules()->GetUpgradeCosts();
+
+ if(RANDOM_LONG(0, 400) == 0)
+ {
+ // Pick a random upgrade
+ AvHUser3 theMinUpgrade = (AvHUser3)(theUser3 + 1);
+ int theMaxUpgrade = AVH_USER3_ALIEN_PLAYER5;
+ AvHUser3 theUpgradeUser3 = (AvHUser3)(RANDOM_LONG((int)theMinUpgrade, (int)theMaxUpgrade));
+ int thePointCost = 0;
+ AvHMessageID theMessage = MESSAGE_NULL;
+ switch(theUpgradeUser3)
+ {
+ case AVH_USER3_ALIEN_PLAYER2:
+ thePointCost = 15;
+ theMessage = ALIEN_LIFEFORM_TWO;
+ break;
+ case AVH_USER3_ALIEN_PLAYER3:
+ thePointCost = 30;
+ theMessage = ALIEN_LIFEFORM_THREE;
+ break;
+ case AVH_USER3_ALIEN_PLAYER4:
+ thePointCost = 50;
+ theMessage = ALIEN_LIFEFORM_FOUR;
+ break;
+ case AVH_USER3_ALIEN_PLAYER5:
+ thePointCost = 75;
+ theMessage = ALIEN_LIFEFORM_FIVE;
+ break;
+ }
+
+ //thePointCost = GetGameRules()->GetPointCostForMessageID(theMessage);
+
+ //if(pBot->mResources >= thePointCost)
+ //{
+ pBot->pEdict->v.impulse = theMessage;
+ //}
+ }
+
+ if(RANDOM_LONG(0, 75) == 0)
+ {
+ // Pick a random upgrade to try to "buy"
+ AvHMessageID theUpgrade = (AvHMessageID)(ALIEN_EVOLUTION_ONE + RANDOM_LONG(0, kNumAlienUpgrades-1));
+ pBot->pEdict->v.impulse = theUpgrade;
+ }
+ }
+
+ // TODO: Help build a nearby team structure
+ if(pBot->pBotEnemy == NULL && (theUser3 == AVH_USER3_MARINE_PLAYER))
+ {
+ }
+
+ if (pBot->curr_waypoint_index != -1) // does the bot have a waypoint?
+ {
+ // check if the next waypoint is a door waypoint...
+ if (waypoints[pBot->curr_waypoint_index].flags & W_FL_DOOR)
+ {
+ pBot->f_move_speed = pBot->f_max_speed / 3; // slow down for doors
+ }
+
+ // check if the next waypoint is a ladder waypoint...
+ if (waypoints[pBot->curr_waypoint_index].flags & W_FL_LADDER)
+ {
+ // check if the waypoint is at the top of a ladder AND
+ // the bot isn't currenly on a ladder...
+ if ((pBot->waypoint_top_of_ladder) &&
+ (pEdict->v.movetype != MOVETYPE_FLY))
+ {
+ // is the bot on "ground" above the ladder?
+ if (pEdict->v.flags & FL_ONGROUND)
+ {
+ float waypoint_distance = (pEdict->v.origin - pBot->waypoint_origin).Length();
+
+ if (waypoint_distance <= 20.0) // if VERY close...
+ pBot->f_move_speed = 20.0; // go VERY slow
+ else if (waypoint_distance <= 100.0) // if fairly close...
+ pBot->f_move_speed = 50.0; // go fairly slow
+
+ pBot->ladder_dir = LADDER_DOWN;
+ pBot->f_dont_check_stuck = gpGlobals->time + 1.0;
+ }
+ else // bot must be in mid-air, go BACKWARDS to touch ladder...
+ {
+ pBot->f_move_speed = -pBot->f_max_speed;
+ }
+ }
+ else
+ {
+ // don't avoid walls for a while
+ pBot->f_dont_avoid_wall_time = gpGlobals->time + 5.0;
+
+ pBot->waypoint_top_of_ladder = FALSE;
+ }
+ }
+
+ // check if the next waypoint is a crouch waypoint...
+ if (waypoints[pBot->curr_waypoint_index].flags & W_FL_CROUCH)
+ pEdict->v.button |= IN_DUCK; // duck down while moving forward
+
+ // check if the waypoint is a sniper waypoint AND
+ // bot isn't currently aiming at an ememy...
+ if ((waypoints[pBot->curr_waypoint_index].flags & W_FL_SNIPER) &&
+ (pBot->pBotEnemy == NULL))
+ {
+ if ((mod_id != TFC_DLL) ||
+ ((mod_id == TFC_DLL) && (pEdict->v.playerclass == TFC_CLASS_SNIPER)))
+ {
+ // check if it's time to adjust aim yet...
+ if (pBot->f_sniper_aim_time <= gpGlobals->time)
+ {
+ int aim_index;
+
+ aim_index = WaypointFindNearestAiming(waypoints[pBot->curr_waypoint_index].origin);
+
+ if (aim_index != -1)
+ {
+ Vector v_aim = waypoints[aim_index].origin - waypoints[pBot->curr_waypoint_index].origin;
+
+ Vector aim_angles = UTIL_VecToAngles( v_aim );
+
+ aim_angles.y += RANDOM_LONG(0, 30) - 15;
+
+ pEdict->v.ideal_yaw = aim_angles.y;
+
+ BotFixIdealYaw(pEdict);
+ }
+
+ // don't adjust aim again until after a few seconds...
+ pBot->f_sniper_aim_time = gpGlobals->time + RANDOM_FLOAT(3.0, 5.0);
+ }
+ }
+ }
+ }
+
+ // Process voice commands
+ BotProcessVoiceCommands(pBot);
+
+ if (pBot->f_pause_time > gpGlobals->time) // is the bot "paused"?
+ pBot->f_move_speed = 0; // don't move while pausing
+
+ // make the body face the same way the bot is looking
+ pEdict->v.angles.y = pEdict->v.v_angle.y;
+
+ // save the previous speed (for checking if stuck)
+ pBot->prev_speed = pBot->f_move_speed;
+
+ //CBaseEntity* theEntity = CBaseEntity::Instance(pEdict);
+ //CBasePlayer* thePlayer = (CBasePlayer*)(theEntity);
+ //thePlayer->PreThink();
+
+ g_engfuncs.pfnRunPlayerMove( pEdict, pEdict->v.v_angle, pBot->f_move_speed,
+ 0, 0, pEdict->v.button, 0, pBot->msecval);
+
+ //thePlayer->PostThink();
+
+ return;
+}
+
diff --git a/main/source/HPB_bot/dlls/bot.h b/main/source/HPB_bot/dlls/bot.h
index 8687d3ab..7337cfb6 100644
--- a/main/source/HPB_bot/dlls/bot.h
+++ b/main/source/HPB_bot/dlls/bot.h
@@ -1,309 +1,309 @@
-//
-// HPB_bot - botman's High Ping Bastard bot
-//
-// (http://planethalflife.com/botman/)
-//
-// bot.h
-//
-
-#ifndef BOT_H
-#define BOT_H
-
-// stuff for Win32 vs. Linux builds
-
-#ifndef __linux__
-
-typedef int (FAR *GETENTITYAPI)(DLL_FUNCTIONS *, int);
-typedef int (FAR *GETNEWDLLFUNCTIONS)(NEW_DLL_FUNCTIONS *, int *);
-typedef void (DLLEXPORT *GIVEFNPTRSTODLL)(enginefuncs_t *, globalvars_t *);
-typedef void (FAR *LINK_ENTITY_FUNC)(entvars_t *);
-
-#else
-
-#include
-#define GetProcAddress dlsym
-
-typedef int BOOL;
-
-typedef int (*GETENTITYAPI)(DLL_FUNCTIONS *, int);
-typedef int (*GETNEWDLLFUNCTIONS)(NEW_DLL_FUNCTIONS *, int *);
-typedef void (*GIVEFNPTRSTODLL)(enginefuncs_t *, globalvars_t *);
-typedef void (*LINK_ENTITY_FUNC)(entvars_t *);
-
-#endif
-
-
-
-// define constants used to identify the MOD we are playing...
-
-#define VALVE_DLL 1
-#define TFC_DLL 2
-#define CSTRIKE_DLL 3
-#define GEARBOX_DLL 4
-#define FRONTLINE_DLL 5
-#define AVH_DLL 6
-
-
-// define some function prototypes...
-BOOL ClientConnect( edict_t *pEntity, const char *pszName,
- const char *pszAddress, char szRejectReason[ 128 ] );
-void ClientPutInServer( edict_t *pEntity );
-void ClientCommand( edict_t *pEntity );
-
-void FakeClientCommand(edict_t *pBot, char *arg1, char *arg2, char *arg3);
-
-
-const char *Cmd_Args( void );
-const char *Cmd_Argv( int argc );
-int Cmd_Argc( void );
-
-
-#define LADDER_UNKNOWN 0
-#define LADDER_UP 1
-#define LADDER_DOWN 2
-
-#define WANDER_LEFT 1
-#define WANDER_RIGHT 2
-
-#define BOT_PITCH_SPEED 20
-#define BOT_YAW_SPEED 20
-
-#define RESPAWN_IDLE 1
-#define RESPAWN_NEED_TO_RESPAWN 2
-#define RESPAWN_IS_RESPAWNING 3
-
-// game start messages for TFC...
-#define MSG_TFC_IDLE 1
-#define MSG_TFC_TEAM_SELECT 2
-#define MSG_TFC_CLASS_SELECT 3
-
-// game start messages for CS...
-#define MSG_CS_IDLE 1
-#define MSG_CS_TEAM_SELECT 2
-#define MSG_CS_CT_SELECT 3
-#define MSG_CS_T_SELECT 4
-
-// game start messages for OpFor...
-#define MSG_OPFOR_IDLE 1
-#define MSG_OPFOR_TEAM_SELECT 2
-#define MSG_OPFOR_CLASS_SELECT 3
-
-// game start messages for FrontLineForce...
-#define MSG_FLF_IDLE 1
-#define MSG_FLF_TEAM_SELECT 2
-#define MSG_FLF_CLASS_SELECT 3
-#define MSG_FLF_PISTOL_SELECT 4
-#define MSG_FLF_WEAPON_SELECT 5
-#define MSG_FLF_RIFLE_SELECT 6
-#define MSG_FLF_SHOTGUN_SELECT 7
-#define MSG_FLF_SUBMACHINE_SELECT 8
-#define MSG_FLF_HEAVYWEAPONS_SELECT 9
-
-// game start messages for Aliens vs. Humans...
-#define MSG_AVH_IDLE 1
-
-#define TFC_CLASS_CIVILIAN 0
-#define TFC_CLASS_SCOUT 1
-#define TFC_CLASS_SNIPER 2
-#define TFC_CLASS_SOLDIER 3
-#define TFC_CLASS_DEMOMAN 4
-#define TFC_CLASS_MEDIC 5
-#define TFC_CLASS_HWGUY 6
-#define TFC_CLASS_PYRO 7
-#define TFC_CLASS_SPY 8
-#define TFC_CLASS_ENGINEER 9
-
-
-#define BOT_SKIN_LEN 32
-#define BOT_NAME_LEN 32
-
-#define MAX_BOT_WHINE 100
-
-#include "mod/AvHConstants.h"
-#include "mod/AvHSpecials.h"
-
-typedef struct
-{
- int iId; // weapon ID
- int iClip; // amount of ammo in the clip
- int iAmmo1; // amount of ammo in primary reserve
- int iAmmo2; // amount of ammo in secondary reserve
-} bot_current_weapon_t;
-
-
-typedef struct
-{
- bool is_used;
- int respawn_state;
- edict_t *pEdict;
- bool need_to_initialize;
- char name[BOT_NAME_LEN+1];
- char skin[BOT_SKIN_LEN+1];
- int bot_skill;
- int not_started;
- int start_action;
- float kick_time;
- float create_time;
-
-// TheFatal - START
- int msecnum;
- float msecdel;
- float msecval;
-// TheFatal - END
-
- // things from pev in CBasePlayer...
- int bot_team;
- int bot_class;
- int bot_health;
- int bot_armor;
- int bot_weapons; // bit map of weapons the bot is carrying
- int bot_money; // for Counter-Strike
- int primary_weapon; // for Front Line Force
- int secondary_weapon; // for Front Line Force
- int defender; // for Front Line Force
- int warmup; // for Front Line Force
- float idle_angle;
- float idle_angle_time; // for Front Line Force
- int round_end; // round has ended (in round based games)
- float blinded_time;
-
- // For AvH
- AvHPlayMode mBotPlayMode;
-
- int mOrderState;
- int mOrderNumPlayers;
- AvHOrderType mOrderType;
- AvHOrderTargetType mOrderTargetType;
- float mOrderLocation[3];
- int mOrderTargetIndex;
- bool mOrderCompleted;
-
- float mTimeOfNextTaunt;
- float mTimeOfNextAmmoRequest;
- float mTimeOfNextOrderRequest;
- float mTimeOfNextAcknowledge;
- float mTimeOfNextRandomSaying;
-
- AvHUser3 mGestateUser3;
- int mResources;
- // end for AvH
-
- float f_max_speed;
- float prev_speed;
- float prev_time;
- Vector v_prev_origin;
-
- float f_find_item;
- edict_t *pBotPickupItem;
-
- int ladder_dir;
- float f_start_use_ladder_time;
- float f_end_use_ladder_time;
- bool waypoint_top_of_ladder;
-
- float f_wall_check_time;
- float f_wall_on_right;
- float f_wall_on_left;
- float f_dont_avoid_wall_time;
- float f_look_for_waypoint_time;
- float f_jump_time;
- float f_dont_check_stuck;
-
- int wander_dir;
- float f_exit_water_time;
-
- Vector waypoint_origin;
- float f_waypoint_time;
- int curr_waypoint_index;
- int prev_waypoint_index[5];
- float f_random_waypoint_time;
- int waypoint_goal;
- float f_waypoint_goal_time;
- bool waypoint_near_flag;
- Vector waypoint_flag_origin;
- float prev_waypoint_distance;
-
- edict_t *pBotEnemy;
- float f_bot_see_enemy_time;
- float f_bot_find_enemy_time;
- edict_t *pBotUser;
- float f_bot_use_time;
- float f_bot_spawn_time;
- edict_t *killer_edict;
- bool b_bot_say_killed;
- float f_bot_say_killed;
- float f_sniper_aim_time;
-
-
- float f_shoot_time;
- float f_primary_charging;
- float f_secondary_charging;
- int charging_weapon_id;
- float f_move_speed;
- float f_pause_time;
- float f_sound_update_time;
- bool bot_has_flag;
-
- bool b_see_tripmine;
- bool b_shoot_tripmine;
- Vector v_tripmine;
-
- bool b_use_health_station;
- float f_use_health_time;
- bool b_use_HEV_station;
- float f_use_HEV_time;
-
- bool b_use_button;
- float f_use_button_time;
- bool b_lift_moving;
-
- bool b_use_capture;
- float f_use_capture_time;
- edict_t *pCaptureEdict;
-
- bot_current_weapon_t current_weapon; // one current weapon for each bot
- int m_rgAmmo[MAX_AMMO_SLOTS]; // total ammo amounts (1 array for each bot)
-
-} bot_t;
-
-
-//#define MAX_TEAMS 32
-//#define MAX_TEAMNAME_LENGTH 16
-#include "game_shared/teamconst.h"
-
-
-#define MAX_FLAGS 5
-
-typedef struct {
- bool mdl_match;
- int team_no;
- edict_t *edict;
-} FLAG_S;
-
-
-// new UTIL.CPP functions...
-edict_t *UTIL_FindEntityInSphere( edict_t *pentStart, const Vector &vecCenter, float flRadius );
-edict_t *UTIL_FindEntityByString( edict_t *pentStart, const char *szKeyword, const char *szValue );
-edict_t *UTIL_FindEntityByClassname( edict_t *pentStart, const char *szName );
-edict_t *UTIL_FindEntityByTargetname( edict_t *pentStart, const char *szName );
-void ClientPrint( edict_t *pEdict, int msg_dest, const char *msg_name);
-void UTIL_SayText( const char *pText, edict_t *pEdict );
-void UTIL_HostSay( edict_t *pEntity, int teamonly, char *message );
-int UTIL_GetTeam(edict_t *pEntity);
-int UTIL_GetClass(edict_t *pEntity);
-int UTIL_GetBotIndex(edict_t *pEdict);
-bot_t *UTIL_GetBotPointer(edict_t *pEdict);
-bool IsAlive(edict_t *pEdict);
-bool FInViewCone(Vector *pOrigin, edict_t *pEdict);
-bool FVisible( const Vector &vecOrigin, edict_t *pEdict );
-Vector Center(edict_t *pEdict);
-Vector GetGunPosition(edict_t *pEdict);
-void UTIL_SelectItem(edict_t *pEdict, char *item_name);
-Vector VecBModelOrigin(edict_t *pEdict);
-bool UpdateSounds(edict_t *pEdict, edict_t *pPlayer);
-void UTIL_ShowMenu( edict_t *pEdict, int slots, int displaytime, bool needmore, char *pText );
-void UTIL_BuildFileName(char *filename, char *arg1, char *arg2);
-
-
-#endif // BOT_H
-
+//
+// HPB_bot - botman's High Ping Bastard bot
+//
+// (http://planethalflife.com/botman/)
+//
+// bot.h
+//
+
+#ifndef BOT_H
+#define BOT_H
+
+// stuff for Win32 vs. Linux builds
+
+#ifndef __linux__
+
+typedef int (FAR *GETENTITYAPI)(DLL_FUNCTIONS *, int);
+typedef int (FAR *GETNEWDLLFUNCTIONS)(NEW_DLL_FUNCTIONS *, int *);
+typedef void (DLLEXPORT *GIVEFNPTRSTODLL)(enginefuncs_t *, globalvars_t *);
+typedef void (FAR *LINK_ENTITY_FUNC)(entvars_t *);
+
+#else
+
+#include
+#define GetProcAddress dlsym
+
+typedef int BOOL;
+
+typedef int (*GETENTITYAPI)(DLL_FUNCTIONS *, int);
+typedef int (*GETNEWDLLFUNCTIONS)(NEW_DLL_FUNCTIONS *, int *);
+typedef void (*GIVEFNPTRSTODLL)(enginefuncs_t *, globalvars_t *);
+typedef void (*LINK_ENTITY_FUNC)(entvars_t *);
+
+#endif
+
+
+
+// define constants used to identify the MOD we are playing...
+
+#define VALVE_DLL 1
+#define TFC_DLL 2
+#define CSTRIKE_DLL 3
+#define GEARBOX_DLL 4
+#define FRONTLINE_DLL 5
+#define AVH_DLL 6
+
+
+// define some function prototypes...
+BOOL ClientConnect( edict_t *pEntity, const char *pszName,
+ const char *pszAddress, char szRejectReason[ 128 ] );
+void ClientPutInServer( edict_t *pEntity );
+void ClientCommand( edict_t *pEntity );
+
+void FakeClientCommand(edict_t *pBot, char *arg1, char *arg2, char *arg3);
+
+
+const char *Cmd_Args( void );
+const char *Cmd_Argv( int argc );
+int Cmd_Argc( void );
+
+
+#define LADDER_UNKNOWN 0
+#define LADDER_UP 1
+#define LADDER_DOWN 2
+
+#define WANDER_LEFT 1
+#define WANDER_RIGHT 2
+
+#define BOT_PITCH_SPEED 20
+#define BOT_YAW_SPEED 20
+
+#define RESPAWN_IDLE 1
+#define RESPAWN_NEED_TO_RESPAWN 2
+#define RESPAWN_IS_RESPAWNING 3
+
+// game start messages for TFC...
+#define MSG_TFC_IDLE 1
+#define MSG_TFC_TEAM_SELECT 2
+#define MSG_TFC_CLASS_SELECT 3
+
+// game start messages for CS...
+#define MSG_CS_IDLE 1
+#define MSG_CS_TEAM_SELECT 2
+#define MSG_CS_CT_SELECT 3
+#define MSG_CS_T_SELECT 4
+
+// game start messages for OpFor...
+#define MSG_OPFOR_IDLE 1
+#define MSG_OPFOR_TEAM_SELECT 2
+#define MSG_OPFOR_CLASS_SELECT 3
+
+// game start messages for FrontLineForce...
+#define MSG_FLF_IDLE 1
+#define MSG_FLF_TEAM_SELECT 2
+#define MSG_FLF_CLASS_SELECT 3
+#define MSG_FLF_PISTOL_SELECT 4
+#define MSG_FLF_WEAPON_SELECT 5
+#define MSG_FLF_RIFLE_SELECT 6
+#define MSG_FLF_SHOTGUN_SELECT 7
+#define MSG_FLF_SUBMACHINE_SELECT 8
+#define MSG_FLF_HEAVYWEAPONS_SELECT 9
+
+// game start messages for Aliens vs. Humans...
+#define MSG_AVH_IDLE 1
+
+#define TFC_CLASS_CIVILIAN 0
+#define TFC_CLASS_SCOUT 1
+#define TFC_CLASS_SNIPER 2
+#define TFC_CLASS_SOLDIER 3
+#define TFC_CLASS_DEMOMAN 4
+#define TFC_CLASS_MEDIC 5
+#define TFC_CLASS_HWGUY 6
+#define TFC_CLASS_PYRO 7
+#define TFC_CLASS_SPY 8
+#define TFC_CLASS_ENGINEER 9
+
+
+#define BOT_SKIN_LEN 32
+#define BOT_NAME_LEN 32
+
+#define MAX_BOT_WHINE 100
+
+#include "mod/AvHConstants.h"
+#include "mod/AvHSpecials.h"
+
+typedef struct
+{
+ int iId; // weapon ID
+ int iClip; // amount of ammo in the clip
+ int iAmmo1; // amount of ammo in primary reserve
+ int iAmmo2; // amount of ammo in secondary reserve
+} bot_current_weapon_t;
+
+
+typedef struct
+{
+ bool is_used;
+ int respawn_state;
+ edict_t *pEdict;
+ bool need_to_initialize;
+ char name[BOT_NAME_LEN+1];
+ char skin[BOT_SKIN_LEN+1];
+ int bot_skill;
+ int not_started;
+ int start_action;
+ float kick_time;
+ float create_time;
+
+// TheFatal - START
+ int msecnum;
+ float msecdel;
+ float msecval;
+// TheFatal - END
+
+ // things from pev in CBasePlayer...
+ int bot_team;
+ int bot_class;
+ int bot_health;
+ int bot_armor;
+ int bot_weapons; // bit map of weapons the bot is carrying
+ int bot_money; // for Counter-Strike
+ int primary_weapon; // for Front Line Force
+ int secondary_weapon; // for Front Line Force
+ int defender; // for Front Line Force
+ int warmup; // for Front Line Force
+ float idle_angle;
+ float idle_angle_time; // for Front Line Force
+ int round_end; // round has ended (in round based games)
+ float blinded_time;
+
+ // For AvH
+ AvHPlayMode mBotPlayMode;
+
+ int mOrderState;
+ int mOrderNumPlayers;
+ AvHOrderType mOrderType;
+ AvHOrderTargetType mOrderTargetType;
+ float mOrderLocation[3];
+ int mOrderTargetIndex;
+ bool mOrderCompleted;
+
+ float mTimeOfNextTaunt;
+ float mTimeOfNextAmmoRequest;
+ float mTimeOfNextOrderRequest;
+ float mTimeOfNextAcknowledge;
+ float mTimeOfNextRandomSaying;
+
+ AvHUser3 mGestateUser3;
+ int mResources;
+ // end for AvH
+
+ float f_max_speed;
+ float prev_speed;
+ float prev_time;
+ Vector v_prev_origin;
+
+ float f_find_item;
+ edict_t *pBotPickupItem;
+
+ int ladder_dir;
+ float f_start_use_ladder_time;
+ float f_end_use_ladder_time;
+ bool waypoint_top_of_ladder;
+
+ float f_wall_check_time;
+ float f_wall_on_right;
+ float f_wall_on_left;
+ float f_dont_avoid_wall_time;
+ float f_look_for_waypoint_time;
+ float f_jump_time;
+ float f_dont_check_stuck;
+
+ int wander_dir;
+ float f_exit_water_time;
+
+ Vector waypoint_origin;
+ float f_waypoint_time;
+ int curr_waypoint_index;
+ int prev_waypoint_index[5];
+ float f_random_waypoint_time;
+ int waypoint_goal;
+ float f_waypoint_goal_time;
+ bool waypoint_near_flag;
+ Vector waypoint_flag_origin;
+ float prev_waypoint_distance;
+
+ edict_t *pBotEnemy;
+ float f_bot_see_enemy_time;
+ float f_bot_find_enemy_time;
+ edict_t *pBotUser;
+ float f_bot_use_time;
+ float f_bot_spawn_time;
+ edict_t *killer_edict;
+ bool b_bot_say_killed;
+ float f_bot_say_killed;
+ float f_sniper_aim_time;
+
+
+ float f_shoot_time;
+ float f_primary_charging;
+ float f_secondary_charging;
+ int charging_weapon_id;
+ float f_move_speed;
+ float f_pause_time;
+ float f_sound_update_time;
+ bool bot_has_flag;
+
+ bool b_see_tripmine;
+ bool b_shoot_tripmine;
+ Vector v_tripmine;
+
+ bool b_use_health_station;
+ float f_use_health_time;
+ bool b_use_HEV_station;
+ float f_use_HEV_time;
+
+ bool b_use_button;
+ float f_use_button_time;
+ bool b_lift_moving;
+
+ bool b_use_capture;
+ float f_use_capture_time;
+ edict_t *pCaptureEdict;
+
+ bot_current_weapon_t current_weapon; // one current weapon for each bot
+ int m_rgAmmo[MAX_AMMO_SLOTS]; // total ammo amounts (1 array for each bot)
+
+} bot_t;
+
+
+//#define MAX_TEAMS 32
+//#define MAX_TEAMNAME_LENGTH 16
+#include "game_shared/teamconst.h"
+
+
+#define MAX_FLAGS 5
+
+typedef struct {
+ bool mdl_match;
+ int team_no;
+ edict_t *edict;
+} FLAG_S;
+
+
+// new UTIL.CPP functions...
+edict_t *UTIL_FindEntityInSphere( edict_t *pentStart, const Vector &vecCenter, float flRadius );
+edict_t *UTIL_FindEntityByString( edict_t *pentStart, const char *szKeyword, const char *szValue );
+edict_t *UTIL_FindEntityByClassname( edict_t *pentStart, const char *szName );
+edict_t *UTIL_FindEntityByTargetname( edict_t *pentStart, const char *szName );
+void ClientPrint( edict_t *pEdict, int msg_dest, const char *msg_name);
+void UTIL_SayText( const char *pText, edict_t *pEdict );
+void UTIL_HostSay( edict_t *pEntity, int teamonly, char *message );
+int UTIL_GetTeam(edict_t *pEntity);
+int UTIL_GetClass(edict_t *pEntity);
+int UTIL_GetBotIndex(edict_t *pEdict);
+bot_t *UTIL_GetBotPointer(edict_t *pEdict);
+bool IsAlive(edict_t *pEdict);
+bool FInViewCone(Vector *pOrigin, edict_t *pEdict);
+bool FVisible( const Vector &vecOrigin, edict_t *pEdict );
+Vector Center(edict_t *pEdict);
+Vector GetGunPosition(edict_t *pEdict);
+void UTIL_SelectItem(edict_t *pEdict, char *item_name);
+Vector VecBModelOrigin(edict_t *pEdict);
+bool UpdateSounds(edict_t *pEdict, edict_t *pPlayer);
+void UTIL_ShowMenu( edict_t *pEdict, int slots, int displaytime, bool needmore, char *pText );
+void UTIL_BuildFileName(char *filename, char *arg1, char *arg2);
+
+
+#endif // BOT_H
+
diff --git a/main/source/HPB_bot/dlls/bot_client.cpp b/main/source/HPB_bot/dlls/bot_client.cpp
index f0e93204..807e729a 100644
--- a/main/source/HPB_bot/dlls/bot_client.cpp
+++ b/main/source/HPB_bot/dlls/bot_client.cpp
@@ -1,960 +1,960 @@
-//
-// HPB bot - botman's High Ping Bastard bot
-//
-// (http://planethalflife.com/botman/)
-//
-// bot_client.cpp
-//
-
-#include "dlls/extdll.h"
-#include "dlls/util.h"
-#include "dlls/cbase.h"
-
-#include "bot.h"
-#include "bot_func.h"
-#include "bot_client.h"
-#include "bot_weapons.h"
-
-// types of damage to ignore...
-#define IGNORE_DAMAGE (DMG_CRUSH | DMG_FREEZE | DMG_FALL | DMG_SHOCK | \
- DMG_DROWN | DMG_NERVEGAS | DMG_RADIATION | \
- DMG_DROWNRECOVER | DMG_ACID | DMG_SLOWBURN | \
- DMG_SLOWFREEZE | 0xFF000000)
-
-extern int mod_id;
-extern bot_t bots[32];
-
-bot_weapon_t weapon_defs[MAX_WEAPONS]; // array of weapon definitions
-
-
-// This message is sent when the TFC VGUI menu is displayed.
-void BotClient_TFC_VGUI(void *p, int bot_index)
-{
- if ((*(int *)p) == 2) // is it a team select menu?
-
- bots[bot_index].start_action = MSG_TFC_TEAM_SELECT;
-
- else if ((*(int *)p) == 3) // is is a class selection menu?
-
- bots[bot_index].start_action = MSG_TFC_CLASS_SELECT;
-}
-
-
-// This message is sent when the Counter-Strike VGUI menu is displayed.
-void BotClient_CS_VGUI(void *p, int bot_index)
-{
- if ((*(int *)p) == 2) // is it a team select menu?
-
- bots[bot_index].start_action = MSG_CS_TEAM_SELECT;
-
- else if ((*(int *)p) == 26) // is is a terrorist model select menu?
-
- bots[bot_index].start_action = MSG_CS_T_SELECT;
-
- else if ((*(int *)p) == 27) // is is a counter-terrorist model select menu?
-
- bots[bot_index].start_action = MSG_CS_CT_SELECT;
-}
-
-
-// This message is sent when a menu is being displayed in Counter-Strike.
-void BotClient_CS_ShowMenu(void *p, int bot_index)
-{
- static int state = 0; // current state machine state
-
- if (state < 3)
- {
- state++; // ignore first 3 fields of message
- return;
- }
-
- if (strcmp((char *)p, "#Team_Select") == 0) // team select menu?
- {
- bots[bot_index].start_action = MSG_CS_TEAM_SELECT;
- }
- else if (strcmp((char *)p, "#Terrorist_Select") == 0) // T model select?
- {
- bots[bot_index].start_action = MSG_CS_T_SELECT;
- }
- else if (strcmp((char *)p, "#CT_Select") == 0) // CT model select menu?
- {
- bots[bot_index].start_action = MSG_CS_CT_SELECT;
- }
-
- state = 0; // reset state machine
-}
-
-
-// This message is sent when the TFC VGUI menu is displayed.
-void BotClient_Gearbox_VGUI(void *p, int bot_index)
-{
- if ((*(int *)p) == 2) // is it a team select menu?
-
- bots[bot_index].start_action = MSG_OPFOR_TEAM_SELECT;
-
- else if ((*(int *)p) == 3) // is is a class selection menu?
-
- bots[bot_index].start_action = MSG_OPFOR_CLASS_SELECT;
-}
-
-
-// This message is sent when the FrontLineForce VGUI menu is displayed.
-void BotClient_FLF_VGUI(void *p, int bot_index)
-{
- if ((*(int *)p) == 2) // is it a team select menu?
- bots[bot_index].start_action = MSG_FLF_TEAM_SELECT;
- else if ((*(int *)p) == 3) // is it a class selection menu?
- bots[bot_index].start_action = MSG_FLF_CLASS_SELECT;
- else if ((*(int *)p) == 70) // is it a weapon selection menu?
- bots[bot_index].start_action = MSG_FLF_WEAPON_SELECT;
- else if ((*(int *)p) == 72) // is it a submachine gun selection menu?
- bots[bot_index].start_action = MSG_FLF_SUBMACHINE_SELECT;
- else if ((*(int *)p) == 73) // is it a shotgun selection menu?
- bots[bot_index].start_action = MSG_FLF_SHOTGUN_SELECT;
- else if ((*(int *)p) == 75) // is it a rifle selection menu?
- bots[bot_index].start_action = MSG_FLF_RIFLE_SELECT;
- else if ((*(int *)p) == 76) // is it a pistol selection menu?
- bots[bot_index].start_action = MSG_FLF_PISTOL_SELECT;
- else if ((*(int *)p) == 78) // is it a heavyweapons selection menu?
- bots[bot_index].start_action = MSG_FLF_HEAVYWEAPONS_SELECT;
-}
-
-
-// This message is sent when a client joins the game. All of the weapons
-// are sent with the weapon ID and information about what ammo is used.
-void BotClient_Valve_WeaponList(void *p, int bot_index)
-{
- static int state = 0; // current state machine state
- static bot_weapon_t bot_weapon;
-
- if (state == 0)
- {
- state++;
- strcpy(bot_weapon.szClassname, (char *)p);
- }
- else if (state == 1)
- {
- state++;
- bot_weapon.iAmmo1 = *(int *)p; // ammo index 1
- }
- else if (state == 2)
- {
- state++;
- bot_weapon.iAmmo1Max = *(int *)p; // max ammo1
- }
- else if (state == 3)
- {
- state++;
- bot_weapon.iAmmo2 = *(int *)p; // ammo index 2
- }
- else if (state == 4)
- {
- state++;
- bot_weapon.iAmmo2Max = *(int *)p; // max ammo2
- }
- else if (state == 5)
- {
- state++;
- bot_weapon.iSlot = *(int *)p; // slot for this weapon
- }
- else if (state == 6)
- {
- state++;
- bot_weapon.iPosition = *(int *)p; // position in slot
- }
- else if (state == 7)
- {
- state++;
- bot_weapon.iId = *(int *)p; // weapon ID
- }
- else if (state == 8)
- {
- state = 0;
-
- bot_weapon.iFlags = *(int *)p; // flags for weapon (WTF???)
-
- // store away this weapon with it's ammo information...
- weapon_defs[bot_weapon.iId] = bot_weapon;
- }
-}
-
-void BotClient_TFC_WeaponList(void *p, int bot_index)
-{
- // this is just like the Valve Weapon List message
- BotClient_Valve_WeaponList(p, bot_index);
-}
-
-void BotClient_CS_WeaponList(void *p, int bot_index)
-{
- // this is just like the Valve Weapon List message
- BotClient_Valve_WeaponList(p, bot_index);
-}
-
-void BotClient_Gearbox_WeaponList(void *p, int bot_index)
-{
- // this is just like the Valve Weapon List message
- BotClient_Valve_WeaponList(p, bot_index);
-}
-
-void BotClient_FLF_WeaponList(void *p, int bot_index)
-{
- // this is just like the Valve Weapon List message
- BotClient_Valve_WeaponList(p, bot_index);
-}
-
-
-// This message is sent when a weapon is selected (either by the bot chosing
-// a weapon or by the server auto assigning the bot a weapon).
-void BotClient_Valve_CurrentWeapon(void *p, int bot_index)
-{
- static int state = 0; // current state machine state
- static int iState;
- static int iId;
- static int iClip;
-
- if (state == 0)
- {
- state++;
- iState = *(int *)p; // state of the current weapon
- }
- else if (state == 1)
- {
- state++;
- iId = *(int *)p; // weapon ID of current weapon
- }
- else if (state == 2)
- {
- state = 0;
-
- iClip = *(int *)p; // ammo currently in the clip for this weapon
-
- if (iId <= 31)
- {
- bots[bot_index].bot_weapons |= (1< 0) || (damage_taken > 0))
- {
- // ignore certain types of damage...
- if (damage_bits & IGNORE_DAMAGE)
- return;
-
- // if the bot doesn't have an enemy and someone is shooting at it then
- // turn in the attacker's direction...
- if (bots[bot_index].pBotEnemy == NULL)
- {
- // face the attacker...
- Vector v_enemy = damage_origin - bots[bot_index].pEdict->v.origin;
- Vector bot_angles = UTIL_VecToAngles( v_enemy );
-
- bots[bot_index].pEdict->v.ideal_yaw = bot_angles.y;
-
- BotFixIdealYaw(bots[bot_index].pEdict);
-
- // stop using health or HEV stations...
- bots[bot_index].b_use_health_station = FALSE;
- bots[bot_index].b_use_HEV_station = FALSE;
- bots[bot_index].b_use_capture = FALSE;
- }
- }
- }
-}
-
-void BotClient_TFC_Damage(void *p, int bot_index)
-{
- // this is just like the Valve Battery message
- BotClient_Valve_Damage(p, bot_index);
-}
-
-void BotClient_CS_Damage(void *p, int bot_index)
-{
- // this is just like the Valve Battery message
- BotClient_Valve_Damage(p, bot_index);
-}
-
-void BotClient_Gearbox_Damage(void *p, int bot_index)
-{
- // this is just like the Valve Battery message
- BotClient_Valve_Damage(p, bot_index);
-}
-
-void BotClient_FLF_Damage(void *p, int bot_index)
-{
- // this is just like the Valve Battery message
- BotClient_Valve_Damage(p, bot_index);
-}
-
-
-// This message gets sent when the bots money ammount changes (for CS)
-void BotClient_CS_Money(void *p, int bot_index)
-{
- static int state = 0; // current state machine state
-
- if (state == 0)
- {
- state++;
-
- bots[bot_index].bot_money = *(int *)p; // amount of money
- }
- else
- {
- state = 0; // ingore this field
- }
-}
-
-// This message gets sent when the bots get killed
-void BotClient_Valve_DeathMsg(void *p, int bot_index)
-{
- static int state = 0; // current state machine state
- static int killer_index;
- static int victim_index;
- static edict_t *victim_edict;
- static int index;
-
- if (state == 0)
- {
- state++;
- killer_index = *(int *)p; // ENTINDEX() of killer
- }
- else if (state == 1)
- {
- state++;
- victim_index = *(int *)p; // ENTINDEX() of victim
- }
- else if (state == 2)
- {
- state = 0;
-
- victim_edict = INDEXENT(victim_index);
-
- index = UTIL_GetBotIndex(victim_edict);
-
- // is this message about a bot being killed?
- if (index != -1)
- {
- if ((killer_index == 0) || (killer_index == victim_index))
- {
- // bot killed by world (worldspawn) or bot killed self...
- bots[index].killer_edict = NULL;
- }
- else
- {
- // store edict of player that killed this bot...
- bots[index].killer_edict = INDEXENT(killer_index);
- }
- }
- }
-}
-
-void BotClient_TFC_DeathMsg(void *p, int bot_index)
-{
- // this is just like the Valve DeathMsg message
- BotClient_Valve_DeathMsg(p, bot_index);
-}
-
-void BotClient_CS_DeathMsg(void *p, int bot_index)
-{
- // this is just like the Valve DeathMsg message
- BotClient_Valve_DeathMsg(p, bot_index);
-}
-
-void BotClient_Gearbox_DeathMsg(void *p, int bot_index)
-{
- // this is just like the Valve DeathMsg message
- BotClient_Valve_DeathMsg(p, bot_index);
-}
-
-void BotClient_FLF_DeathMsg(void *p, int bot_index)
-{
- // this is just like the Valve DeathMsg message
- BotClient_Valve_DeathMsg(p, bot_index);
-}
-
-
-// This message gets sent when a text message is displayed
-void BotClient_FLF_TextMsg(void *p, int bot_index)
-{
- static int state = 0; // current state machine state
- static int msg_dest = 0;
-
- if (state == 0)
- {
- state++;
- msg_dest = *(int *)p; // HUD_PRINTCENTER, etc.
- }
- else if (state == 1)
- {
- state = 0;
-
- if (strcmp((char *)p, "You are Attacking\n") == 0) // attacker msg
- {
- bots[bot_index].defender = 0; // attacker
- }
- else if (strcmp((char *)p, "You are Defending\n") == 0) // defender msg
- {
- bots[bot_index].defender = 1; // defender
- }
- }
-}
-
-
-// This message gets sent when the WarmUpTime is enabled/disabled
-void BotClient_FLF_WarmUp(void *p, int bot_index)
-{
- bots[bot_index].warmup = *(int *)p;
-}
-
-
-// This message gets sent to ALL when the WarmUpTime is enabled/disabled
-void BotClient_FLF_WarmUpAll(void *p, int bot_index)
-{
- for (int i=0; i < 32; i++)
- {
- if (bots[i].is_used) // count the number of bots in use
- bots[i].warmup = *(int *)p;
- }
-}
-
-
-// This message gets sent when the round is over
-void BotClient_FLF_WinMessage(void *p, int bot_index)
-{
- for (int i=0; i < 32; i++)
- {
- if (bots[i].is_used) // count the number of bots in use
- bots[i].round_end = 1;
- }
-}
-
-
-// This message gets sent when a temp entity is created
-void BotClient_FLF_TempEntity(void *p, int bot_index)
-{
- static int state = 0; // current state machine state
- static int te_type; // TE_ message type
-
- if (p == NULL) // end of message?
- {
- state = 0;
- return;
- }
-
- if (state == 0)
- {
- state++;
- te_type = *(int *)p;
-
- return;
- }
-
- if (te_type == TE_TEXTMESSAGE)
- {
- if (state == 16)
- {
- if (strncmp((char *)p, "Capturing ", 10) == 0)
- {
- // if bot is currently capturing, keep timer alive...
- if (bots[bot_index].b_use_capture)
- bots[bot_index].f_use_capture_time = gpGlobals->time + 2.0;
- }
- }
-
- state++;
- }
-}
-
-
-void BotClient_Valve_ScreenFade(void *p, int bot_index)
-{
- static int state = 0; // current state machine state
- static int duration;
- static int hold_time;
- static int fade_flags;
- int length;
-
- if (state == 0)
- {
- state++;
- duration = *(int *)p;
- }
- else if (state == 1)
- {
- state++;
- hold_time = *(int *)p;
- }
- else if (state == 2)
- {
- state++;
- fade_flags = *(int *)p;
- }
- else if (state == 6)
- {
- state = 0;
-
- length = (duration + hold_time) / 4096;
- bots[bot_index].blinded_time = gpGlobals->time + length - 2.0;
- }
- else
- {
- state++;
- }
-}
-
-void BotClient_TFC_ScreenFade(void *p, int bot_index)
-{
- // this is just like the Valve ScreenFade message
- BotClient_Valve_ScreenFade(p, bot_index);
-}
-
-void BotClient_CS_ScreenFade(void *p, int bot_index)
-{
- // this is just like the Valve ScreenFade message
- BotClient_Valve_ScreenFade(p, bot_index);
-}
-
-void BotClient_Gearbox_ScreenFade(void *p, int bot_index)
-{
- // this is just like the Valve ScreenFade message
- BotClient_Valve_ScreenFade(p, bot_index);
-}
-
-void BotClient_FLF_ScreenFade(void *p, int bot_index)
-{
- // this is just like the Valve ScreenFade message
- BotClient_Valve_ScreenFade(p, bot_index);
-}
-
-// AvH client functions
-void BotClient_AVH_SetOrder(void *p, int bot_index)
-{
- bot_t* theCurrentBot = &bots[bot_index];
-
- if(theCurrentBot->mOrderNumPlayers == -1)
- {
- if (theCurrentBot->mOrderState == 0)
- {
- // Read num players
- theCurrentBot->mOrderState++;
- theCurrentBot->mOrderNumPlayers = *(byte *)p;
- }
- }
- else
- {
- if(theCurrentBot->mOrderState <= theCurrentBot->mOrderNumPlayers)
- {
- // Skip by players
- theCurrentBot->mOrderState++;
- }
- else
- {
- int theRealState = theCurrentBot->mOrderState - theCurrentBot->mOrderNumPlayers - 1;
- if(theRealState == 0)
- {
- // read order
- theCurrentBot->mOrderState++;
- theCurrentBot->mOrderType = *((AvHOrderType *)p);
- }
- else if(theRealState == 1)
- {
- // read order target type
- theCurrentBot->mOrderState++;
- theCurrentBot->mOrderTargetType = *((AvHOrderTargetType *)p);
- }
- else
- {
- if((theCurrentBot->mOrderTargetType == ORDERTARGETTYPE_LOCATION) && ((theRealState >= 2) && (theRealState <= 4)))
- {
- theCurrentBot->mOrderLocation[theRealState-2] = *((float*)p);
- theCurrentBot->mOrderState++;
- }
- else if((theCurrentBot->mOrderTargetType == ORDERTARGETTYPE_TARGET) && (theRealState == 2))
- {
- theCurrentBot->mOrderTargetIndex = *((int*)p);
- theCurrentBot->mOrderState++;
- }
- else if( ((theCurrentBot->mOrderTargetType == ORDERTARGETTYPE_LOCATION) && (theRealState == 5)) ||
- ((theCurrentBot->mOrderTargetType == ORDERTARGETTYPE_TARGET) && (theRealState == 3)) ||
- (theRealState == 2) )
- {
- theCurrentBot->mOrderCompleted = *((int*)p);
- theCurrentBot->mOrderState++;
- }
- else
- {
- // Reset
- theCurrentBot->mOrderState = 0;
- theCurrentBot->mOrderNumPlayers = -1;
- theCurrentBot->mOrderType = ORDERTYPE_UNDEFINED;
- theCurrentBot->mOrderTargetType = ORDERTARGETTYPE_UNDEFINED;
- theCurrentBot->mOrderLocation[0] = theCurrentBot->mOrderLocation[1] = theCurrentBot->mOrderLocation[2] = 0.0f;
- theCurrentBot->mOrderTargetIndex = -1;
- theCurrentBot->mOrderCompleted = false;
- }
- }
- }
- }
-}
-
-
-
-void BotClient_AVH_SetPlayMode(void *p, int bot_index)
-{
- static int state = 0; // current state machine state
-
- if (state == 0)
- {
- state++;
-
- bots[bot_index].mBotPlayMode = (AvHPlayMode)(*(byte *)p); // amount of money
- bots[bot_index].pBotEnemy = NULL;
- }
- else
- {
- state = 0; // ingore this field
- }
-}
-
-void BotClient_AVH_SetResources(void *p, int bot_index)
-{
- static int state = 0; // current state machine state
-
- if(state == 0)
- {
- state++;
- }
- else if(state == 1)
- {
- bots[bot_index].mResources = (*(int *)p); // amount of money
- state += 4;
- }
- else
- {
- state = 0; // ingore this field
- }
-}
-
-
-
+//
+// HPB bot - botman's High Ping Bastard bot
+//
+// (http://planethalflife.com/botman/)
+//
+// bot_client.cpp
+//
+
+#include "dlls/extdll.h"
+#include "dlls/util.h"
+#include "dlls/cbase.h"
+
+#include "bot.h"
+#include "bot_func.h"
+#include "bot_client.h"
+#include "bot_weapons.h"
+
+// types of damage to ignore...
+#define IGNORE_DAMAGE (DMG_CRUSH | DMG_FREEZE | DMG_FALL | DMG_SHOCK | \
+ DMG_DROWN | DMG_NERVEGAS | DMG_RADIATION | \
+ DMG_DROWNRECOVER | DMG_ACID | DMG_SLOWBURN | \
+ DMG_SLOWFREEZE | 0xFF000000)
+
+extern int mod_id;
+extern bot_t bots[32];
+
+bot_weapon_t weapon_defs[MAX_WEAPONS]; // array of weapon definitions
+
+
+// This message is sent when the TFC VGUI menu is displayed.
+void BotClient_TFC_VGUI(void *p, int bot_index)
+{
+ if ((*(int *)p) == 2) // is it a team select menu?
+
+ bots[bot_index].start_action = MSG_TFC_TEAM_SELECT;
+
+ else if ((*(int *)p) == 3) // is is a class selection menu?
+
+ bots[bot_index].start_action = MSG_TFC_CLASS_SELECT;
+}
+
+
+// This message is sent when the Counter-Strike VGUI menu is displayed.
+void BotClient_CS_VGUI(void *p, int bot_index)
+{
+ if ((*(int *)p) == 2) // is it a team select menu?
+
+ bots[bot_index].start_action = MSG_CS_TEAM_SELECT;
+
+ else if ((*(int *)p) == 26) // is is a terrorist model select menu?
+
+ bots[bot_index].start_action = MSG_CS_T_SELECT;
+
+ else if ((*(int *)p) == 27) // is is a counter-terrorist model select menu?
+
+ bots[bot_index].start_action = MSG_CS_CT_SELECT;
+}
+
+
+// This message is sent when a menu is being displayed in Counter-Strike.
+void BotClient_CS_ShowMenu(void *p, int bot_index)
+{
+ static int state = 0; // current state machine state
+
+ if (state < 3)
+ {
+ state++; // ignore first 3 fields of message
+ return;
+ }
+
+ if (strcmp((char *)p, "#Team_Select") == 0) // team select menu?
+ {
+ bots[bot_index].start_action = MSG_CS_TEAM_SELECT;
+ }
+ else if (strcmp((char *)p, "#Terrorist_Select") == 0) // T model select?
+ {
+ bots[bot_index].start_action = MSG_CS_T_SELECT;
+ }
+ else if (strcmp((char *)p, "#CT_Select") == 0) // CT model select menu?
+ {
+ bots[bot_index].start_action = MSG_CS_CT_SELECT;
+ }
+
+ state = 0; // reset state machine
+}
+
+
+// This message is sent when the TFC VGUI menu is displayed.
+void BotClient_Gearbox_VGUI(void *p, int bot_index)
+{
+ if ((*(int *)p) == 2) // is it a team select menu?
+
+ bots[bot_index].start_action = MSG_OPFOR_TEAM_SELECT;
+
+ else if ((*(int *)p) == 3) // is is a class selection menu?
+
+ bots[bot_index].start_action = MSG_OPFOR_CLASS_SELECT;
+}
+
+
+// This message is sent when the FrontLineForce VGUI menu is displayed.
+void BotClient_FLF_VGUI(void *p, int bot_index)
+{
+ if ((*(int *)p) == 2) // is it a team select menu?
+ bots[bot_index].start_action = MSG_FLF_TEAM_SELECT;
+ else if ((*(int *)p) == 3) // is it a class selection menu?
+ bots[bot_index].start_action = MSG_FLF_CLASS_SELECT;
+ else if ((*(int *)p) == 70) // is it a weapon selection menu?
+ bots[bot_index].start_action = MSG_FLF_WEAPON_SELECT;
+ else if ((*(int *)p) == 72) // is it a submachine gun selection menu?
+ bots[bot_index].start_action = MSG_FLF_SUBMACHINE_SELECT;
+ else if ((*(int *)p) == 73) // is it a shotgun selection menu?
+ bots[bot_index].start_action = MSG_FLF_SHOTGUN_SELECT;
+ else if ((*(int *)p) == 75) // is it a rifle selection menu?
+ bots[bot_index].start_action = MSG_FLF_RIFLE_SELECT;
+ else if ((*(int *)p) == 76) // is it a pistol selection menu?
+ bots[bot_index].start_action = MSG_FLF_PISTOL_SELECT;
+ else if ((*(int *)p) == 78) // is it a heavyweapons selection menu?
+ bots[bot_index].start_action = MSG_FLF_HEAVYWEAPONS_SELECT;
+}
+
+
+// This message is sent when a client joins the game. All of the weapons
+// are sent with the weapon ID and information about what ammo is used.
+void BotClient_Valve_WeaponList(void *p, int bot_index)
+{
+ static int state = 0; // current state machine state
+ static bot_weapon_t bot_weapon;
+
+ if (state == 0)
+ {
+ state++;
+ strcpy(bot_weapon.szClassname, (char *)p);
+ }
+ else if (state == 1)
+ {
+ state++;
+ bot_weapon.iAmmo1 = *(int *)p; // ammo index 1
+ }
+ else if (state == 2)
+ {
+ state++;
+ bot_weapon.iAmmo1Max = *(int *)p; // max ammo1
+ }
+ else if (state == 3)
+ {
+ state++;
+ bot_weapon.iAmmo2 = *(int *)p; // ammo index 2
+ }
+ else if (state == 4)
+ {
+ state++;
+ bot_weapon.iAmmo2Max = *(int *)p; // max ammo2
+ }
+ else if (state == 5)
+ {
+ state++;
+ bot_weapon.iSlot = *(int *)p; // slot for this weapon
+ }
+ else if (state == 6)
+ {
+ state++;
+ bot_weapon.iPosition = *(int *)p; // position in slot
+ }
+ else if (state == 7)
+ {
+ state++;
+ bot_weapon.iId = *(int *)p; // weapon ID
+ }
+ else if (state == 8)
+ {
+ state = 0;
+
+ bot_weapon.iFlags = *(int *)p; // flags for weapon (WTF???)
+
+ // store away this weapon with it's ammo information...
+ weapon_defs[bot_weapon.iId] = bot_weapon;
+ }
+}
+
+void BotClient_TFC_WeaponList(void *p, int bot_index)
+{
+ // this is just like the Valve Weapon List message
+ BotClient_Valve_WeaponList(p, bot_index);
+}
+
+void BotClient_CS_WeaponList(void *p, int bot_index)
+{
+ // this is just like the Valve Weapon List message
+ BotClient_Valve_WeaponList(p, bot_index);
+}
+
+void BotClient_Gearbox_WeaponList(void *p, int bot_index)
+{
+ // this is just like the Valve Weapon List message
+ BotClient_Valve_WeaponList(p, bot_index);
+}
+
+void BotClient_FLF_WeaponList(void *p, int bot_index)
+{
+ // this is just like the Valve Weapon List message
+ BotClient_Valve_WeaponList(p, bot_index);
+}
+
+
+// This message is sent when a weapon is selected (either by the bot chosing
+// a weapon or by the server auto assigning the bot a weapon).
+void BotClient_Valve_CurrentWeapon(void *p, int bot_index)
+{
+ static int state = 0; // current state machine state
+ static int iState;
+ static int iId;
+ static int iClip;
+
+ if (state == 0)
+ {
+ state++;
+ iState = *(int *)p; // state of the current weapon
+ }
+ else if (state == 1)
+ {
+ state++;
+ iId = *(int *)p; // weapon ID of current weapon
+ }
+ else if (state == 2)
+ {
+ state = 0;
+
+ iClip = *(int *)p; // ammo currently in the clip for this weapon
+
+ if (iId <= 31)
+ {
+ bots[bot_index].bot_weapons |= (1< 0) || (damage_taken > 0))
+ {
+ // ignore certain types of damage...
+ if (damage_bits & IGNORE_DAMAGE)
+ return;
+
+ // if the bot doesn't have an enemy and someone is shooting at it then
+ // turn in the attacker's direction...
+ if (bots[bot_index].pBotEnemy == NULL)
+ {
+ // face the attacker...
+ Vector v_enemy = damage_origin - bots[bot_index].pEdict->v.origin;
+ Vector bot_angles = UTIL_VecToAngles( v_enemy );
+
+ bots[bot_index].pEdict->v.ideal_yaw = bot_angles.y;
+
+ BotFixIdealYaw(bots[bot_index].pEdict);
+
+ // stop using health or HEV stations...
+ bots[bot_index].b_use_health_station = FALSE;
+ bots[bot_index].b_use_HEV_station = FALSE;
+ bots[bot_index].b_use_capture = FALSE;
+ }
+ }
+ }
+}
+
+void BotClient_TFC_Damage(void *p, int bot_index)
+{
+ // this is just like the Valve Battery message
+ BotClient_Valve_Damage(p, bot_index);
+}
+
+void BotClient_CS_Damage(void *p, int bot_index)
+{
+ // this is just like the Valve Battery message
+ BotClient_Valve_Damage(p, bot_index);
+}
+
+void BotClient_Gearbox_Damage(void *p, int bot_index)
+{
+ // this is just like the Valve Battery message
+ BotClient_Valve_Damage(p, bot_index);
+}
+
+void BotClient_FLF_Damage(void *p, int bot_index)
+{
+ // this is just like the Valve Battery message
+ BotClient_Valve_Damage(p, bot_index);
+}
+
+
+// This message gets sent when the bots money ammount changes (for CS)
+void BotClient_CS_Money(void *p, int bot_index)
+{
+ static int state = 0; // current state machine state
+
+ if (state == 0)
+ {
+ state++;
+
+ bots[bot_index].bot_money = *(int *)p; // amount of money
+ }
+ else
+ {
+ state = 0; // ingore this field
+ }
+}
+
+// This message gets sent when the bots get killed
+void BotClient_Valve_DeathMsg(void *p, int bot_index)
+{
+ static int state = 0; // current state machine state
+ static int killer_index;
+ static int victim_index;
+ static edict_t *victim_edict;
+ static int index;
+
+ if (state == 0)
+ {
+ state++;
+ killer_index = *(int *)p; // ENTINDEX() of killer
+ }
+ else if (state == 1)
+ {
+ state++;
+ victim_index = *(int *)p; // ENTINDEX() of victim
+ }
+ else if (state == 2)
+ {
+ state = 0;
+
+ victim_edict = INDEXENT(victim_index);
+
+ index = UTIL_GetBotIndex(victim_edict);
+
+ // is this message about a bot being killed?
+ if (index != -1)
+ {
+ if ((killer_index == 0) || (killer_index == victim_index))
+ {
+ // bot killed by world (worldspawn) or bot killed self...
+ bots[index].killer_edict = NULL;
+ }
+ else
+ {
+ // store edict of player that killed this bot...
+ bots[index].killer_edict = INDEXENT(killer_index);
+ }
+ }
+ }
+}
+
+void BotClient_TFC_DeathMsg(void *p, int bot_index)
+{
+ // this is just like the Valve DeathMsg message
+ BotClient_Valve_DeathMsg(p, bot_index);
+}
+
+void BotClient_CS_DeathMsg(void *p, int bot_index)
+{
+ // this is just like the Valve DeathMsg message
+ BotClient_Valve_DeathMsg(p, bot_index);
+}
+
+void BotClient_Gearbox_DeathMsg(void *p, int bot_index)
+{
+ // this is just like the Valve DeathMsg message
+ BotClient_Valve_DeathMsg(p, bot_index);
+}
+
+void BotClient_FLF_DeathMsg(void *p, int bot_index)
+{
+ // this is just like the Valve DeathMsg message
+ BotClient_Valve_DeathMsg(p, bot_index);
+}
+
+
+// This message gets sent when a text message is displayed
+void BotClient_FLF_TextMsg(void *p, int bot_index)
+{
+ static int state = 0; // current state machine state
+ static int msg_dest = 0;
+
+ if (state == 0)
+ {
+ state++;
+ msg_dest = *(int *)p; // HUD_PRINTCENTER, etc.
+ }
+ else if (state == 1)
+ {
+ state = 0;
+
+ if (strcmp((char *)p, "You are Attacking\n") == 0) // attacker msg
+ {
+ bots[bot_index].defender = 0; // attacker
+ }
+ else if (strcmp((char *)p, "You are Defending\n") == 0) // defender msg
+ {
+ bots[bot_index].defender = 1; // defender
+ }
+ }
+}
+
+
+// This message gets sent when the WarmUpTime is enabled/disabled
+void BotClient_FLF_WarmUp(void *p, int bot_index)
+{
+ bots[bot_index].warmup = *(int *)p;
+}
+
+
+// This message gets sent to ALL when the WarmUpTime is enabled/disabled
+void BotClient_FLF_WarmUpAll(void *p, int bot_index)
+{
+ for (int i=0; i < 32; i++)
+ {
+ if (bots[i].is_used) // count the number of bots in use
+ bots[i].warmup = *(int *)p;
+ }
+}
+
+
+// This message gets sent when the round is over
+void BotClient_FLF_WinMessage(void *p, int bot_index)
+{
+ for (int i=0; i < 32; i++)
+ {
+ if (bots[i].is_used) // count the number of bots in use
+ bots[i].round_end = 1;
+ }
+}
+
+
+// This message gets sent when a temp entity is created
+void BotClient_FLF_TempEntity(void *p, int bot_index)
+{
+ static int state = 0; // current state machine state
+ static int te_type; // TE_ message type
+
+ if (p == NULL) // end of message?
+ {
+ state = 0;
+ return;
+ }
+
+ if (state == 0)
+ {
+ state++;
+ te_type = *(int *)p;
+
+ return;
+ }
+
+ if (te_type == TE_TEXTMESSAGE)
+ {
+ if (state == 16)
+ {
+ if (strncmp((char *)p, "Capturing ", 10) == 0)
+ {
+ // if bot is currently capturing, keep timer alive...
+ if (bots[bot_index].b_use_capture)
+ bots[bot_index].f_use_capture_time = gpGlobals->time + 2.0;
+ }
+ }
+
+ state++;
+ }
+}
+
+
+void BotClient_Valve_ScreenFade(void *p, int bot_index)
+{
+ static int state = 0; // current state machine state
+ static int duration;
+ static int hold_time;
+ static int fade_flags;
+ int length;
+
+ if (state == 0)
+ {
+ state++;
+ duration = *(int *)p;
+ }
+ else if (state == 1)
+ {
+ state++;
+ hold_time = *(int *)p;
+ }
+ else if (state == 2)
+ {
+ state++;
+ fade_flags = *(int *)p;
+ }
+ else if (state == 6)
+ {
+ state = 0;
+
+ length = (duration + hold_time) / 4096;
+ bots[bot_index].blinded_time = gpGlobals->time + length - 2.0;
+ }
+ else
+ {
+ state++;
+ }
+}
+
+void BotClient_TFC_ScreenFade(void *p, int bot_index)
+{
+ // this is just like the Valve ScreenFade message
+ BotClient_Valve_ScreenFade(p, bot_index);
+}
+
+void BotClient_CS_ScreenFade(void *p, int bot_index)
+{
+ // this is just like the Valve ScreenFade message
+ BotClient_Valve_ScreenFade(p, bot_index);
+}
+
+void BotClient_Gearbox_ScreenFade(void *p, int bot_index)
+{
+ // this is just like the Valve ScreenFade message
+ BotClient_Valve_ScreenFade(p, bot_index);
+}
+
+void BotClient_FLF_ScreenFade(void *p, int bot_index)
+{
+ // this is just like the Valve ScreenFade message
+ BotClient_Valve_ScreenFade(p, bot_index);
+}
+
+// AvH client functions
+void BotClient_AVH_SetOrder(void *p, int bot_index)
+{
+ bot_t* theCurrentBot = &bots[bot_index];
+
+ if(theCurrentBot->mOrderNumPlayers == -1)
+ {
+ if (theCurrentBot->mOrderState == 0)
+ {
+ // Read num players
+ theCurrentBot->mOrderState++;
+ theCurrentBot->mOrderNumPlayers = *(byte *)p;
+ }
+ }
+ else
+ {
+ if(theCurrentBot->mOrderState <= theCurrentBot->mOrderNumPlayers)
+ {
+ // Skip by players
+ theCurrentBot->mOrderState++;
+ }
+ else
+ {
+ int theRealState = theCurrentBot->mOrderState - theCurrentBot->mOrderNumPlayers - 1;
+ if(theRealState == 0)
+ {
+ // read order
+ theCurrentBot->mOrderState++;
+ theCurrentBot->mOrderType = *((AvHOrderType *)p);
+ }
+ else if(theRealState == 1)
+ {
+ // read order target type
+ theCurrentBot->mOrderState++;
+ theCurrentBot->mOrderTargetType = *((AvHOrderTargetType *)p);
+ }
+ else
+ {
+ if((theCurrentBot->mOrderTargetType == ORDERTARGETTYPE_LOCATION) && ((theRealState >= 2) && (theRealState <= 4)))
+ {
+ theCurrentBot->mOrderLocation[theRealState-2] = *((float*)p);
+ theCurrentBot->mOrderState++;
+ }
+ else if((theCurrentBot->mOrderTargetType == ORDERTARGETTYPE_TARGET) && (theRealState == 2))
+ {
+ theCurrentBot->mOrderTargetIndex = *((int*)p);
+ theCurrentBot->mOrderState++;
+ }
+ else if( ((theCurrentBot->mOrderTargetType == ORDERTARGETTYPE_LOCATION) && (theRealState == 5)) ||
+ ((theCurrentBot->mOrderTargetType == ORDERTARGETTYPE_TARGET) && (theRealState == 3)) ||
+ (theRealState == 2) )
+ {
+ theCurrentBot->mOrderCompleted = *((int*)p);
+ theCurrentBot->mOrderState++;
+ }
+ else
+ {
+ // Reset
+ theCurrentBot->mOrderState = 0;
+ theCurrentBot->mOrderNumPlayers = -1;
+ theCurrentBot->mOrderType = ORDERTYPE_UNDEFINED;
+ theCurrentBot->mOrderTargetType = ORDERTARGETTYPE_UNDEFINED;
+ theCurrentBot->mOrderLocation[0] = theCurrentBot->mOrderLocation[1] = theCurrentBot->mOrderLocation[2] = 0.0f;
+ theCurrentBot->mOrderTargetIndex = -1;
+ theCurrentBot->mOrderCompleted = false;
+ }
+ }
+ }
+ }
+}
+
+
+
+void BotClient_AVH_SetPlayMode(void *p, int bot_index)
+{
+ static int state = 0; // current state machine state
+
+ if (state == 0)
+ {
+ state++;
+
+ bots[bot_index].mBotPlayMode = (AvHPlayMode)(*(byte *)p); // amount of money
+ bots[bot_index].pBotEnemy = NULL;
+ }
+ else
+ {
+ state = 0; // ingore this field
+ }
+}
+
+void BotClient_AVH_SetResources(void *p, int bot_index)
+{
+ static int state = 0; // current state machine state
+
+ if(state == 0)
+ {
+ state++;
+ }
+ else if(state == 1)
+ {
+ bots[bot_index].mResources = (*(int *)p); // amount of money
+ state += 4;
+ }
+ else
+ {
+ state = 0; // ingore this field
+ }
+}
+
+
+
diff --git a/main/source/HPB_bot/dlls/bot_client.h b/main/source/HPB_bot/dlls/bot_client.h
index 4dc9e030..67b51fce 100644
--- a/main/source/HPB_bot/dlls/bot_client.h
+++ b/main/source/HPB_bot/dlls/bot_client.h
@@ -1,96 +1,96 @@
-//
-// HPB_bot - botman's High Ping Bastard bot
-//
-// (http://planethalflife.com/botman/)
-//
-// bot_client.h
-//
-
-void BotClient_TFC_VGUI(void *p, int bot_index);
-void BotClient_CS_VGUI(void *p, int bot_index);
-void BotClient_CS_ShowMenu(void *p, int bot_index);
-void BotClient_Gearbox_VGUI(void *p, int bot_index);
-void BotClient_FLF_VGUI(void *p, int bot_index);
-
-void BotClient_Valve_WeaponList(void *p, int bot_index);
-void BotClient_TFC_WeaponList(void *p, int bot_index);
-void BotClient_CS_WeaponList(void *p, int bot_index);
-void BotClient_Gearbox_WeaponList(void *p, int bot_index);
-void BotClient_FLF_WeaponList(void *p, int bot_index);
-
-void BotClient_Valve_CurrentWeapon(void *p, int bot_index);
-void BotClient_TFC_CurrentWeapon(void *p, int bot_index);
-void BotClient_CS_CurrentWeapon(void *p, int bot_index);
-void BotClient_Gearbox_CurrentWeapon(void *p, int bot_index);
-void BotClient_FLF_CurrentWeapon(void *p, int bot_index);
-
-void BotClient_Valve_AmmoX(void *p, int bot_index);
-void BotClient_TFC_AmmoX(void *p, int bot_index);
-void BotClient_CS_AmmoX(void *p, int bot_index);
-void BotClient_Gearbox_AmmoX(void *p, int bot_index);
-void BotClient_FLF_AmmoX(void *p, int bot_index);
-
-void BotClient_Valve_AmmoPickup(void *p, int bot_index);
-void BotClient_TFC_AmmoPickup(void *p, int bot_index);
-void BotClient_CS_AmmoPickup(void *p, int bot_index);
-void BotClient_Gearbox_AmmoPickup(void *p, int bot_index);
-void BotClient_FLF_AmmoPickup(void *p, int bot_index);
-
-void BotClient_Valve_WeaponPickup(void *p, int bot_index);
-void BotClient_TFC_WeaponPickup(void *p, int bot_index);
-void BotClient_CS_WeaponPickup(void *p, int bot_index);
-void BotClient_Gearbox_WeaponPickup(void *p, int bot_index);
-void BotClient_FLF_WeaponPickup(void *p, int bot_index);
-
-void BotClient_Valve_ItemPickup(void *p, int bot_index);
-void BotClient_TFC_ItemPickup(void *p, int bot_index);
-void BotClient_CS_ItemPickup(void *p, int bot_index);
-void BotClient_Gearbox_ItemPickup(void *p, int bot_index);
-void BotClient_FLF_ItemPickup(void *p, int bot_index);
-
-void BotClient_Valve_Health(void *p, int bot_index);
-void BotClient_TFC_Health(void *p, int bot_index);
-void BotClient_CS_Health(void *p, int bot_index);
-void BotClient_Gearbox_Health(void *p, int bot_index);
-void BotClient_FLF_Health(void *p, int bot_index);
-
-void BotClient_Valve_Battery(void *p, int bot_index);
-void BotClient_TFC_Battery(void *p, int bot_index);
-void BotClient_CS_Battery(void *p, int bot_index);
-void BotClient_Gearbox_Battery(void *p, int bot_index);
-void BotClient_FLF_Battery(void *p, int bot_index);
-
-void BotClient_Valve_Damage(void *p, int bot_index);
-void BotClient_TFC_Damage(void *p, int bot_index);
-void BotClient_CS_Damage(void *p, int bot_index);
-void BotClient_Gearbox_Damage(void *p, int bot_index);
-void BotClient_FLF_Damage(void *p, int bot_index);
-
-void BotClient_CS_Money(void *p, int bot_index);
-
-void BotClient_Valve_DeathMsg(void *p, int bot_index);
-void BotClient_TFC_DeathMsg(void *p, int bot_index);
-void BotClient_CS_DeathMsg(void *p, int bot_index);
-void BotClient_Gearbox_DeathMsg(void *p, int bot_index);
-void BotClient_FLF_DeathMsg(void *p, int bot_index);
-
-void BotClient_FLF_TextMsg(void *p, int bot_index);
-
-void BotClient_FLF_WarmUp(void *p, int bot_index);
-void BotClient_FLF_WarmUpAll(void *p, int bot_index);
-
-void BotClient_FLF_WinMessage(void *p, int bot_index);
-
-void BotClient_FLF_TempEntity(void *p, int bot_index);
-
-void BotClient_Valve_ScreenFade(void *p, int bot_index);
-void BotClient_TFC_ScreenFade(void *p, int bot_index);
-void BotClient_CS_ScreenFade(void *p, int bot_index);
-void BotClient_Gearbox_ScreenFade(void *p, int bot_index);
-void BotClient_FLF_ScreenFade(void *p, int bot_index);
-
-// AvH client functions
-void BotClient_AVH_SetOrder(void *p, int bot_index);
-void BotClient_AVH_SetPlayMode(void *p, int bot_index);
-void BotClient_AVH_SetResources(void *p, int bot_index);
-
+//
+// HPB_bot - botman's High Ping Bastard bot
+//
+// (http://planethalflife.com/botman/)
+//
+// bot_client.h
+//
+
+void BotClient_TFC_VGUI(void *p, int bot_index);
+void BotClient_CS_VGUI(void *p, int bot_index);
+void BotClient_CS_ShowMenu(void *p, int bot_index);
+void BotClient_Gearbox_VGUI(void *p, int bot_index);
+void BotClient_FLF_VGUI(void *p, int bot_index);
+
+void BotClient_Valve_WeaponList(void *p, int bot_index);
+void BotClient_TFC_WeaponList(void *p, int bot_index);
+void BotClient_CS_WeaponList(void *p, int bot_index);
+void BotClient_Gearbox_WeaponList(void *p, int bot_index);
+void BotClient_FLF_WeaponList(void *p, int bot_index);
+
+void BotClient_Valve_CurrentWeapon(void *p, int bot_index);
+void BotClient_TFC_CurrentWeapon(void *p, int bot_index);
+void BotClient_CS_CurrentWeapon(void *p, int bot_index);
+void BotClient_Gearbox_CurrentWeapon(void *p, int bot_index);
+void BotClient_FLF_CurrentWeapon(void *p, int bot_index);
+
+void BotClient_Valve_AmmoX(void *p, int bot_index);
+void BotClient_TFC_AmmoX(void *p, int bot_index);
+void BotClient_CS_AmmoX(void *p, int bot_index);
+void BotClient_Gearbox_AmmoX(void *p, int bot_index);
+void BotClient_FLF_AmmoX(void *p, int bot_index);
+
+void BotClient_Valve_AmmoPickup(void *p, int bot_index);
+void BotClient_TFC_AmmoPickup(void *p, int bot_index);
+void BotClient_CS_AmmoPickup(void *p, int bot_index);
+void BotClient_Gearbox_AmmoPickup(void *p, int bot_index);
+void BotClient_FLF_AmmoPickup(void *p, int bot_index);
+
+void BotClient_Valve_WeaponPickup(void *p, int bot_index);
+void BotClient_TFC_WeaponPickup(void *p, int bot_index);
+void BotClient_CS_WeaponPickup(void *p, int bot_index);
+void BotClient_Gearbox_WeaponPickup(void *p, int bot_index);
+void BotClient_FLF_WeaponPickup(void *p, int bot_index);
+
+void BotClient_Valve_ItemPickup(void *p, int bot_index);
+void BotClient_TFC_ItemPickup(void *p, int bot_index);
+void BotClient_CS_ItemPickup(void *p, int bot_index);
+void BotClient_Gearbox_ItemPickup(void *p, int bot_index);
+void BotClient_FLF_ItemPickup(void *p, int bot_index);
+
+void BotClient_Valve_Health(void *p, int bot_index);
+void BotClient_TFC_Health(void *p, int bot_index);
+void BotClient_CS_Health(void *p, int bot_index);
+void BotClient_Gearbox_Health(void *p, int bot_index);
+void BotClient_FLF_Health(void *p, int bot_index);
+
+void BotClient_Valve_Battery(void *p, int bot_index);
+void BotClient_TFC_Battery(void *p, int bot_index);
+void BotClient_CS_Battery(void *p, int bot_index);
+void BotClient_Gearbox_Battery(void *p, int bot_index);
+void BotClient_FLF_Battery(void *p, int bot_index);
+
+void BotClient_Valve_Damage(void *p, int bot_index);
+void BotClient_TFC_Damage(void *p, int bot_index);
+void BotClient_CS_Damage(void *p, int bot_index);
+void BotClient_Gearbox_Damage(void *p, int bot_index);
+void BotClient_FLF_Damage(void *p, int bot_index);
+
+void BotClient_CS_Money(void *p, int bot_index);
+
+void BotClient_Valve_DeathMsg(void *p, int bot_index);
+void BotClient_TFC_DeathMsg(void *p, int bot_index);
+void BotClient_CS_DeathMsg(void *p, int bot_index);
+void BotClient_Gearbox_DeathMsg(void *p, int bot_index);
+void BotClient_FLF_DeathMsg(void *p, int bot_index);
+
+void BotClient_FLF_TextMsg(void *p, int bot_index);
+
+void BotClient_FLF_WarmUp(void *p, int bot_index);
+void BotClient_FLF_WarmUpAll(void *p, int bot_index);
+
+void BotClient_FLF_WinMessage(void *p, int bot_index);
+
+void BotClient_FLF_TempEntity(void *p, int bot_index);
+
+void BotClient_Valve_ScreenFade(void *p, int bot_index);
+void BotClient_TFC_ScreenFade(void *p, int bot_index);
+void BotClient_CS_ScreenFade(void *p, int bot_index);
+void BotClient_Gearbox_ScreenFade(void *p, int bot_index);
+void BotClient_FLF_ScreenFade(void *p, int bot_index);
+
+// AvH client functions
+void BotClient_AVH_SetOrder(void *p, int bot_index);
+void BotClient_AVH_SetPlayMode(void *p, int bot_index);
+void BotClient_AVH_SetResources(void *p, int bot_index);
+
diff --git a/main/source/HPB_bot/dlls/bot_combat.cpp b/main/source/HPB_bot/dlls/bot_combat.cpp
index 5854c873..feb19f2e 100644
--- a/main/source/HPB_bot/dlls/bot_combat.cpp
+++ b/main/source/HPB_bot/dlls/bot_combat.cpp
@@ -1,1301 +1,1301 @@
-//
-// HPB bot - botman's High Ping Bastard bot
-//
-// (http://planethalflife.com/botman/)
-//
-// bot_combat.cpp
-//
-
-#include "dlls/extdll.h"
-#include "dlls/util.h"
-#include "dlls/cbase.h"
-
-#include "bot.h"
-#include "bot_func.h"
-#include "bot_weapons.h"
-#include "mod/AvHBasePlayerWeaponConstants.h"
-#include "mod/AvHMarineWeaponConstants.h"
-#include "mod/AvHAlienWeaponConstants.h"
-#include "mod/AvHPlayer.h"
-
-extern int mod_id;
-extern bot_weapon_t weapon_defs[MAX_WEAPONS];
-extern bool b_observer_mode;
-extern int team_allies[4];
-extern edict_t *pent_info_ctfdetect;
-extern float is_team_play;
-extern bool checked_teamplay;
-
-FILE *fp;
-
-
-typedef struct
-{
- int iId; // the weapon ID value
- char weapon_name[64]; // name of the weapon when selecting it
- int skill_level; // bot skill must be less than or equal to this value
- float primary_min_distance; // 0 = no minimum
- float primary_max_distance; // 9999 = no maximum
- float secondary_min_distance; // 0 = no minimum
- float secondary_max_distance; // 9999 = no maximum
- int use_percent; // times out of 100 to use this weapon when available
- bool can_use_underwater; // can use this weapon underwater
- int primary_fire_percent; // times out of 100 to use primary fire
- int min_primary_ammo; // minimum ammout of primary ammo needed to fire
- int min_secondary_ammo; // minimum ammout of seconday ammo needed to fire
- bool primary_fire_hold; // hold down primary fire button to use?
- bool secondary_fire_hold; // hold down secondary fire button to use?
- bool primary_fire_charge; // charge weapon using primary fire?
- bool secondary_fire_charge; // charge weapon using secondary fire?
- float primary_charge_delay; // time to charge weapon
- float secondary_charge_delay; // time to charge weapon
-} bot_weapon_select_t;
-
-typedef struct
-{
- int iId;
- float primary_base_delay;
- float primary_min_delay[5];
- float primary_max_delay[5];
- float secondary_base_delay;
- float secondary_min_delay[5];
- float secondary_max_delay[5];
-} bot_fire_delay_t;
-
-
-// weapons are stored in priority order, most desired weapon should be at
-// the start of the array and least desired should be at the end
-
-bot_weapon_select_t valve_weapon_select[] = {
- {VALVE_WEAPON_CROWBAR, "weapon_crowbar", 2, 0.0, 50.0, 0.0, 0.0,
- 100, TRUE, 100, 0, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
- {VALVE_WEAPON_HANDGRENADE, "weapon_handgrenade", 5, 250.0, 750.0, 0.0, 0.0,
- 30, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
- {VALVE_WEAPON_SNARK, "weapon_snark", 5, 150.0, 500.0, 0.0, 0.0,
- 50, FALSE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
- {VALVE_WEAPON_EGON, "weapon_egon", 5, 0.0, 9999.0, 0.0, 0.0,
- 100, FALSE, 100, 1, 0, TRUE, FALSE, FALSE, FALSE, 0.0, 0.0},
- {VALVE_WEAPON_GAUSS, "weapon_gauss", 5, 0.0, 9999.0, 0.0, 9999.0,
- 100, FALSE, 80, 1, 10, FALSE, FALSE, FALSE, TRUE, 0.0, 0.8},
- {VALVE_WEAPON_SHOTGUN, "weapon_shotgun", 5, 30.0, 150.0, 30.0, 150.0,
- 100, FALSE, 70, 1, 2, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
- {VALVE_WEAPON_PYTHON, "weapon_357", 5, 30.0, 700.0, 0.0, 0.0,
- 100, FALSE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
- {VALVE_WEAPON_HORNETGUN, "weapon_hornetgun", 5, 30.0, 1000.0, 30.0, 1000.0,
- 100, TRUE, 50, 1, 4, FALSE, TRUE, FALSE, FALSE, 0.0, 0.0},
- {VALVE_WEAPON_MP5, "weapon_9mmAR", 5, 0.0, 250.0, 300.0, 600.0,
- 100, FALSE, 90, 1, 1, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
- {VALVE_WEAPON_CROSSBOW, "weapon_crossbow", 5, 100.0, 1000.0, 0.0, 0.0,
- 100, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
- {VALVE_WEAPON_RPG, "weapon_rpg", 5, 300.0, 9999.0, 0.0, 0.0,
- 100, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
- {VALVE_WEAPON_GLOCK, "weapon_9mmhandgun", 5, 0.0, 1200.0, 0.0, 1200.0,
- 100, TRUE, 70, 1, 1, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
- /* terminator */
- {0, "", 0, 0.0, 0.0, 0.0, 0.0, 0, TRUE, 0, 1, 1, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0}
-};
-
-bot_weapon_select_t tfc_weapon_select[] = {
- {TF_WEAPON_AXE, "tf_weapon_axe", 5, 0.0, 50.0, 0.0, 0.0,
- 100, TRUE, 100, 0, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
- {TF_WEAPON_KNIFE, "tf_weapon_knife", 5, 0.0, 40.0, 0.0, 0.0,
- 100, TRUE, 100, 0, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
- {TF_WEAPON_SPANNER, "tf_weapon_knife", 5, 0.0, 40.0, 0.0, 0.0,
- 100, TRUE, 100, 0, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
- {TF_WEAPON_MEDIKIT, "tf_weapon_medikit", 5, 0.0, 40.0, 0.0, 0.0,
- 100, TRUE, 100, 0, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
- {TF_WEAPON_SNIPERRIFLE, "tf_weapon_sniperrifle", 5, 300.0, 2500.0, 0.0, 0.0,
- 100, TRUE, 100, 1, 0, FALSE, FALSE, TRUE, FALSE, 1.0, 0.0},
- {TF_WEAPON_FLAMETHROWER, "tf_weapon_flamethrower", 5, 100.0, 500.0, 0.0, 0.0,
- 100, FALSE, 100, 1, 0, TRUE, FALSE, FALSE, FALSE, 0.0, 0.0},
- {TF_WEAPON_AC, "tf_weapon_ac", 5, 50.0, 1000.0, 0.0, 0.0,
- 100, TRUE, 100, 1, 0, TRUE, FALSE, FALSE, FALSE, 0.0, 0.0},
- {TF_WEAPON_GL, "tf_weapon_gl", 5, 300.0, 900.0, 0.0, 0.0,
- 100, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
- {TF_WEAPON_RPG, "tf_weapon_rpg", 5, 300.0, 900.0, 0.0, 0.0,
- 100, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
- {TF_WEAPON_IC, "tf_weapon_ic", 5, 300.0, 800.0, 0.0, 0.0,
- 100, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
- {TF_WEAPON_TRANQ, "tf_weapon_tranq", 5, 40.0, 1000.0, 0.0, 0.0,
- 100, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
- {TF_WEAPON_RAILGUN, "tf_weapon_railgun", 5, 40.0, 800.0, 0.0, 0.0,
- 100, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
- {TF_WEAPON_SUPERNAILGUN, "tf_weapon_superng", 5, 40.0, 800.0, 0.0, 0.0,
- 100, TRUE, 100, 1, 0, TRUE, FALSE, FALSE, FALSE, 0.0, 0.0},
- {TF_WEAPON_SUPERSHOTGUN, "tf_weapon_supershotgun", 5, 40.0, 500.0, 0.0, 0.0,
- 100, TRUE, 100, 2, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
- {TF_WEAPON_AUTORIFLE, "tf_weapon_autorifle", 5, 0.0, 800.0, 0.0, 0.0,
- 100, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
- {TF_WEAPON_SHOTGUN, "tf_weapon_shotgun", 5, 40.0, 400.0, 0.0, 0.0,
- 100, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
- {TF_WEAPON_NAILGUN, "tf_weapon_ng", 5, 40.0, 600.0, 0.0, 0.0,
- 100, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
- /* terminator */
- {0, "", 0, 0.0, 0.0, 0.0, 0.0, 0, TRUE, 0, 1, 1, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0}
-};
-
-bot_weapon_select_t cs_weapon_select[] = {
- {CS_WEAPON_KNIFE, "weapon_knife", 5, 0.0, 50.0, 0.0, 0.0,
- 100, TRUE, 100, 0, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
- {CS_WEAPON_USP, "weapon_usp", 5, 0.0, 1200.0, 0.0, 1200.0,
- 100, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
- {CS_WEAPON_GLOCK18, "weapon_glock18", 5, 0.0, 1200.0, 0.0, 1200.0,
- 100, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
- /* terminator */
- {0, "", 0, 0.0, 0.0, 0.0, 0.0, 0, TRUE, 0, 1, 1, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0}
-};
-
-bot_weapon_select_t gearbox_weapon_select[] = {
- {GEARBOX_WEAPON_PIPEWRENCH, "weapon_pipewrench", 3, 0.0, 50.0, 0.0, 0.0,
- 100, TRUE, 100, 0, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
- {GEARBOX_WEAPON_KNIFE, "weapon_knife", 4, 0.0, 50.0, 0.0, 0.0,
- 100, TRUE, 100, 0, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
- {GEARBOX_WEAPON_CROWBAR, "weapon_crowbar", 2, 0.0, 50.0, 0.0, 0.0,
- 100, TRUE, 100, 0, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
- {GEARBOX_WEAPON_DISPLACER, "weapon_displacer", 5, 100.0, 1000.0, 0.0, 0.0,
- 100, TRUE, 100, 0, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
- {GEARBOX_WEAPON_SPORELAUNCHER, "weapon_sporelauncher", 5, 500.0, 1000.0, 0.0, 0.0,
- 100, TRUE, 100, 0, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
- {GEARBOX_WEAPON_SHOCKRIFLE, "weapon_shockrifle", 5, 50.0, 800.0, 0.0, 0.0,
- 100, TRUE, 100, 0, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
- {GEARBOX_WEAPON_SNIPERRIFLE, "weapon_sniperrifle", 5, 50.0, 1500.0, 0.0, 0.0,
- 100, FALSE, 100, 0, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
- {GEARBOX_WEAPON_HANDGRENADE, "weapon_handgrenade", 5, 250.0, 750.0, 0.0, 0.0,
- 30, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
- {GEARBOX_WEAPON_SNARK, "weapon_snark", 5, 150.0, 500.0, 0.0, 0.0,
- 50, FALSE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
- {GEARBOX_WEAPON_EGON, "weapon_egon", 5, 0.0, 9999.0, 0.0, 0.0,
- 100, FALSE, 100, 1, 0, TRUE, FALSE, FALSE, FALSE, 0.0, 0.0},
- {GEARBOX_WEAPON_GAUSS, "weapon_gauss", 5, 0.0, 9999.0, 0.0, 9999.0,
- 100, FALSE, 80, 1, 10, FALSE, FALSE, FALSE, TRUE, 0.0, 0.8},
- {GEARBOX_WEAPON_M249, "weapon_m249", 5, 0.0, 400.0, 0.0, 0.0,
- 100, FALSE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
- {GEARBOX_WEAPON_SHOTGUN, "weapon_shotgun", 5, 30.0, 150.0, 30.0, 150.0,
- 100, FALSE, 70, 1, 2, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
- {GEARBOX_WEAPON_EAGLE, "weapon_eagle", 5, 0.0, 1200.0, 0.0, 0.0,
- 100, FALSE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
- {GEARBOX_WEAPON_PYTHON, "weapon_357", 5, 30.0, 700.0, 0.0, 0.0,
- 100, FALSE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
- {GEARBOX_WEAPON_HORNETGUN, "weapon_hornetgun", 5, 30.0, 1000.0, 30.0, 1000.0,
- 100, TRUE, 50, 1, 4, FALSE, TRUE, FALSE, FALSE, 0.0, 0.0},
- {GEARBOX_WEAPON_MP5, "weapon_9mmAR", 5, 0.0, 250.0, 300.0, 600.0,
- 100, FALSE, 90, 1, 1, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
- {GEARBOX_WEAPON_CROSSBOW, "weapon_crossbow", 5, 100.0, 1000.0, 0.0, 0.0,
- 100, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
- {GEARBOX_WEAPON_RPG, "weapon_rpg", 5, 300.0, 9999.0, 0.0, 0.0,
- 100, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
- {GEARBOX_WEAPON_GLOCK, "weapon_9mmhandgun", 5, 0.0, 1200.0, 0.0, 1200.0,
- 100, TRUE, 70, 1, 1, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
- /* terminator */
- {0, "", 0, 0.0, 0.0, 0.0, 0.0, 0, TRUE, 0, 1, 1, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0}
-};
-
-bot_weapon_select_t frontline_weapon_select[] = {
- {FLF_WEAPON_HEGRENADE, "weapon_hegrenade", 3, 200.0, 1000.0, 0.0, 0.0,
- 100, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
- {FLF_WEAPON_FLASHBANG, "weapon_flashbang", 3, 100.0, 800.0, 0.0, 0.0,
- 100, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
-// {FLF_WEAPON_KNIFE, "weapon_knife", 3, 0.0, 60.0, 0.0, 0.0,
-// 100, TRUE, 100, 0, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
- {FLF_WEAPON_HK21, "weapon_hk21", 5, 0.0, 900.0, 0.0, 0.0,
- 100, TRUE, 100, 1, 0, TRUE, FALSE, FALSE, FALSE, 0.0, 0.0},
- {FLF_WEAPON_UMP45, "weapon_ump45", 5, 0.0, 900.0, 0.0, 0.0,
- 100, TRUE, 100, 1, 0, TRUE, FALSE, FALSE, FALSE, 0.0, 0.0},
- {FLF_WEAPON_FAMAS, "weapon_famas", 5, 0.0, 500.0, 0.0, 0.0,
- 100, TRUE, 100, 1, 0, TRUE, FALSE, FALSE, FALSE, 0.0, 0.0},
- {FLF_WEAPON_MSG90, "weapon_msg90", 5, 0.0, 2500.0, 0.0, 0.0,
- 100, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
- {FLF_WEAPON_MP5A2, "weapon_mp5a2", 5, 0.0, 900.0, 0.0, 0.0,
- 100, TRUE, 100, 1, 0, TRUE, FALSE, FALSE, FALSE, 0.0, 0.0},
- {FLF_WEAPON_AK5, "weapon_ak5", 5, 0.0, 900.0, 0.0, 0.0,
- 100, TRUE, 100, 1, 0, TRUE, FALSE, FALSE, FALSE, 0.0, 0.0},
- {FLF_WEAPON_MP5SD, "weapon_mp5sd", 5, 0.0, 900.0, 0.0, 0.0,
- 100, TRUE, 100, 1, 0, TRUE, FALSE, FALSE, FALSE, 0.0, 0.0},
- {FLF_WEAPON_M4, "weapon_m4", 5, 0.0, 900.0, 0.0, 0.0,
- 100, TRUE, 100, 1, 0, TRUE, FALSE, FALSE, FALSE, 0.0, 0.0},
- {FLF_WEAPON_SPAS12, "weapon_spas12", 5, 0.0, 900.0, 0.0, 0.0,
- 100, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
- {FLF_WEAPON_MAC10, "weapon_mac10", 5, 0.0, 500.0, 0.0, 0.0,
- 100, TRUE, 100, 1, 0, TRUE, FALSE, FALSE, FALSE, 0.0, 0.0},
- {FLF_WEAPON_BERETTA, "weapon_beretta", 5, 0.0, 1200.0, 0.0, 1200.0,
- 100, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
- {FLF_WEAPON_MK23, "weapon_mk23", 5, 0.0, 1200.0, 0.0, 1200.0,
- 100, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
- /* terminator */
- {0, "", 0, 0.0, 0.0, 0.0, 0.0, 0, TRUE, 0, 1, 1, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0}
-};
-
-//int iId; // the weapon ID value
-//char weapon_name[64]; // name of the weapon when selecting it
-//int skill_level; // bot skill must be less than or equal to this value
-//float primary_min_distance; // 0 = no minimum
-//float primary_max_distance; // 9999 = no maximum
-//float secondary_min_distance; // 0 = no minimum
-//float secondary_max_distance; // 9999 = no maximum
-//int use_percent; // times out of 100 to use this weapon when available
-//bool can_use_underwater; // can use this weapon underwater
-//int primary_fire_percent; // times out of 100 to use primary fire
-//int min_primary_ammo; // minimum ammout of primary ammo needed to fire
-//int min_secondary_ammo; // minimum ammout of seconday ammo needed to fire
-//bool primary_fire_hold; // hold down primary fire button to use?
-//bool secondary_fire_hold; // hold down secondary fire button to use?
-//bool primary_fire_charge; // charge weapon using primary fire?
-//bool secondary_fire_charge; // charge weapon using secondary fire?
-//float primary_charge_delay; // time to charge weapon
-//float secondary_charge_delay; // time to charge weapon
-
-bot_weapon_select_t ns_weapon_select[] = {
- {AVH_WEAPON_GRENADE_GUN, kwsGrenadeGun, 3, 120, kGGRange, 0.0, 0.0, 100, FALSE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0f, 0.0f},
- {AVH_WEAPON_SONIC, kwsShotGun, 3, 0.0, kSGRange, 0.0, 0.0, 100, FALSE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0f, 0.0f},
- {AVH_WEAPON_HMG, kwsHeavyMachineGun, 3, 0.0, kHMGRange, 0.0, 0.0, 100, FALSE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0f, 0.0f},
- {AVH_WEAPON_MG, kwsMachineGun, 3, 0.0, kMGRange, 0.0, 0.0, 100, FALSE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0f, 0.0f},
- {AVH_WEAPON_PISTOL, kwsPistol, 3, 0.0, kHGRange, 0.0, 0.0, 75, FALSE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0f, 0.0f},
- {AVH_WEAPON_KNIFE, kwsKnife, 3, 0.0, kKNRange, 0.0, 0.0, 50, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0f, 0.0f},
-
- // Base alien abilities
- {AVH_WEAPON_PRIMALSCREAM, kwsPrimalScream, 3, 0.0, 300, 0.0, 0.0, 20, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0f, 0.0f},
- {AVH_WEAPON_SWIPE, kwsSwipe, 3, 0.0, kSwipeRange, 0.0, 0.0, 75, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0f, 0.0f},
- {AVH_WEAPON_SPORES, kwsSporeGun, 3, 0.0, kSporeRange, 0.0, 0.0, 75, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0f, 0.0f},
- {AVH_WEAPON_SPIT, kwsSpitGun, 3, 0.0, kSpitGRange, 0.0, 0.0, 75, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0f, 0.0f},
- {AVH_WEAPON_CLAWS, kwsClaws, 3, 0.0, kClawsRange, 0.0, 0.0, 75, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0f, 0.0f},
- {AVH_WEAPON_BITE, kwsBiteGun, 3, 0.0, 60, 0.0, 0.0, 75, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0f, 0.0f},
- {AVH_ABILITY_LEAP, kwsLeap, 3, 0.0, 600, 0.0, 0.0, 50, FALSE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0f, 0.0f},
- {AVH_WEAPON_SPIKE, kwsSpikeGun, 3, 0.0, kSpikeRange, 0.0, 0.0, 75, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0f, 0.0f},
-};
-
-// weapon firing delay based on skill (min and max delay for each weapon)
-// THESE MUST MATCH THE SAME ORDER AS THE WEAPON SELECT ARRAY!!!
-
-bot_fire_delay_t valve_fire_delay[] = {
- {VALVE_WEAPON_CROWBAR,
- 0.3, {0.0, 0.2, 0.3, 0.4, 0.6}, {0.1, 0.3, 0.5, 0.7, 1.0},
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
- {VALVE_WEAPON_HANDGRENADE,
- 0.1, {1.0, 2.0, 3.0, 4.0, 5.0}, {3.0, 4.0, 5.0, 6.0, 7.0},
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
- {VALVE_WEAPON_SNARK,
- 0.1, {0.0, 0.1, 0.2, 0.4, 0.6}, {0.1, 0.2, 0.5, 0.7, 1.0},
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
- {VALVE_WEAPON_EGON,
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0},
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
- {VALVE_WEAPON_GAUSS,
- 0.2, {0.0, 0.2, 0.3, 0.5, 1.0}, {0.1, 0.3, 0.5, 0.8, 1.2},
- 1.0, {0.2, 0.3, 0.5, 0.8, 1.2}, {0.5, 0.7, 1.0, 1.5, 2.0}},
- {VALVE_WEAPON_SHOTGUN,
- 0.75, {0.0, 0.2, 0.4, 0.6, 0.8}, {0.25, 0.5, 0.8, 1.2, 2.0},
- 1.5, {0.0, 0.2, 0.4, 0.6, 0.8}, {0.25, 0.5, 0.8, 1.2, 2.0}},
- {VALVE_WEAPON_PYTHON,
- 0.75, {0.0, 0.2, 0.4, 1.0, 1.5}, {0.25, 0.5, 0.8, 1.3, 2.2},
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
- {VALVE_WEAPON_HORNETGUN,
- 0.25, {0.0, 0.25, 0.4, 0.6, 1.0}, {0.1, 0.4, 0.7, 1.0, 1.5},
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
- {VALVE_WEAPON_MP5,
- 0.1, {0.0, 0.1, 0.25, 0.4, 0.5}, {0.1, 0.3, 0.45, 0.65, 0.8},
- 1.0, {0.0, 0.4, 0.7, 1.0, 1.4}, {0.3, 0.7, 1.0, 1.6, 2.0}},
- {VALVE_WEAPON_CROSSBOW,
- 0.75, {0.0, 0.2, 0.5, 0.8, 1.0}, {0.25, 0.4, 0.7, 1.0, 1.3},
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
- {VALVE_WEAPON_RPG,
- 1.5, {1.0, 2.0, 3.0, 4.0, 5.0}, {3.0, 4.0, 5.0, 6.0, 7.0},
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
- {VALVE_WEAPON_GLOCK,
- 0.3, {0.0, 0.1, 0.2, 0.3, 0.4}, {0.1, 0.2, 0.3, 0.4, 0.5},
- 0.2, {0.0, 0.0, 0.1, 0.1, 0.2}, {0.1, 0.1, 0.2, 0.2, 0.4}},
- /* terminator */
- {0, 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0},
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}}
-};
-
-bot_fire_delay_t tfc_fire_delay[] = {
- {TF_WEAPON_AXE,
- 0.3, {0.0, 0.2, 0.3, 0.4, 0.6}, {0.1, 0.3, 0.5, 0.7, 1.0},
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
- {TF_WEAPON_KNIFE,
- 0.3, {0.0, 0.2, 0.3, 0.4, 0.6}, {0.1, 0.3, 0.5, 0.7, 1.0},
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
- {TF_WEAPON_SPANNER,
- 0.3, {0.0, 0.2, 0.3, 0.4, 0.6}, {0.1, 0.3, 0.5, 0.7, 1.0},
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
- {TF_WEAPON_MEDIKIT,
- 0.3, {0.0, 0.2, 0.3, 0.4, 0.6}, {0.1, 0.3, 0.5, 0.7, 1.0},
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
- {TF_WEAPON_SNIPERRIFLE,
- 1.0, {0.0, 0.4, 0.7, 1.0, 1.4}, {0.3, 0.7, 1.0, 1.6, 2.0},
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
- {TF_WEAPON_FLAMETHROWER,
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0},
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
- {TF_WEAPON_AC,
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0},
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
- {TF_WEAPON_GL,
- 0.6, {0.0, 0.2, 0.5, 0.8, 1.0}, {0.25, 0.4, 0.7, 1.0, 1.3},
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
- {TF_WEAPON_RPG,
- 0.5, {0.0, 0.1, 0.3, 0.6, 1.0}, {0.1, 0.2, 0.7, 1.0, 2.0},
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
- {TF_WEAPON_IC,
- 2.0, {1.0, 2.0, 3.0, 4.0, 5.0}, {3.0, 4.0, 5.0, 6.0, 7.0},
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
- {TF_WEAPON_TRANQ,
- 1.5, {1.0, 2.0, 3.0, 4.0, 5.0}, {3.0, 4.0, 5.0, 6.0, 7.0},
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
- {TF_WEAPON_RAILGUN,
- 0.4, {0.0, 0.1, 0.2, 0.3, 0.4}, {0.1, 0.2, 0.3, 0.4, 0.5},
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
- {TF_WEAPON_SUPERNAILGUN,
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0},
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
- {TF_WEAPON_SUPERSHOTGUN,
- 0.6, {0.0, 0.2, 0.5, 0.8, 1.0}, {0.25, 0.4, 0.7, 1.0, 1.3},
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
- {TF_WEAPON_AUTORIFLE,
- 0.1, {0.0, 0.1, 0.2, 0.4, 0.6}, {0.1, 0.2, 0.5, 0.7, 1.0},
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
- {TF_WEAPON_SHOTGUN,
- 0.5, {0.0, 0.2, 0.4, 0.6, 0.8}, {0.25, 0.5, 0.8, 1.2, 2.0},
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
- {TF_WEAPON_NAILGUN,
- 0.1, {0.0, 0.1, 0.2, 0.4, 0.6}, {0.1, 0.2, 0.5, 0.7, 1.0},
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
- /* terminator */
- {0, 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0},
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}}
-};
-
-bot_fire_delay_t cs_fire_delay[] = {
- {CS_WEAPON_KNIFE,
- 0.3, {0.0, 0.2, 0.3, 0.4, 0.6}, {0.1, 0.3, 0.5, 0.7, 1.0},
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
- {CS_WEAPON_USP,
- 0.3, {0.0, 0.1, 0.2, 0.3, 0.4}, {0.1, 0.2, 0.3, 0.4, 0.5},
- 0.2, {0.0, 0.0, 0.1, 0.1, 0.2}, {0.1, 0.1, 0.2, 0.2, 0.4}},
- {CS_WEAPON_GLOCK18,
- 0.3, {0.0, 0.1, 0.2, 0.3, 0.4}, {0.1, 0.2, 0.3, 0.4, 0.5},
- 0.2, {0.0, 0.0, 0.1, 0.1, 0.2}, {0.1, 0.1, 0.2, 0.2, 0.4}},
- /* terminator */
- {0, 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0},
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}}
-};
-
-bot_fire_delay_t gearbox_fire_delay[] = {
- {GEARBOX_WEAPON_PIPEWRENCH,
- 0.5, {0.0, 0.2, 0.3, 0.4, 0.6}, {0.1, 0.3, 0.5, 0.7, 1.0},
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
- {GEARBOX_WEAPON_KNIFE,
- 0.4, {0.0, 0.2, 0.3, 0.4, 0.6}, {0.1, 0.3, 0.5, 0.7, 1.0},
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
- {GEARBOX_WEAPON_CROWBAR,
- 0.3, {0.0, 0.2, 0.3, 0.4, 0.6}, {0.1, 0.3, 0.5, 0.7, 1.0},
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
- {GEARBOX_WEAPON_DISPLACER,
- 5.0, {0.0, 0.5, 0.8, 1.6, 2.5}, {0.3, 0.8, 1.4, 2.2, 3.5},
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
- {GEARBOX_WEAPON_SPORELAUNCHER,
- 0.5, {0.0, 0.2, 0.3, 0.4, 0.6}, {0.1, 0.3, 0.5, 0.7, 1.0},
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
- {GEARBOX_WEAPON_SHOCKRIFLE,
- 0.1, {0.0, 0.1, 0.2, 0.3, 0.4}, {0.1, 0.2, 0.3, 0.4, 0.5},
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
- {GEARBOX_WEAPON_SNIPERRIFLE,
- 1.5, {0.0, 0.2, 0.4, 0.6, 0.8}, {0.25, 0.5, 0.8, 1.2, 2.0},
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
- {GEARBOX_WEAPON_HANDGRENADE,
- 0.1, {1.0, 2.0, 3.0, 4.0, 5.0}, {3.0, 4.0, 5.0, 6.0, 7.0},
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
- {GEARBOX_WEAPON_SNARK,
- 0.1, {0.0, 0.1, 0.2, 0.4, 0.6}, {0.1, 0.2, 0.5, 0.7, 1.0},
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
- {GEARBOX_WEAPON_EGON,
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0},
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
- {GEARBOX_WEAPON_GAUSS,
- 0.2, {0.0, 0.2, 0.3, 0.5, 1.0}, {0.1, 0.3, 0.5, 0.8, 1.2},
- 1.0, {0.2, 0.3, 0.5, 0.8, 1.2}, {0.5, 0.7, 1.0, 1.5, 2.0}},
- {GEARBOX_WEAPON_M249,
- 0.1, {0.0, 0.1, 0.25, 0.4, 0.5}, {0.1, 0.3, 0.45, 0.65, 0.8},
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
- {GEARBOX_WEAPON_SHOTGUN,
- 0.75, {0.0, 0.2, 0.4, 0.6, 0.8}, {0.25, 0.5, 0.8, 1.2, 2.0},
- 1.5, {0.0, 0.2, 0.4, 0.6, 0.8}, {0.25, 0.5, 0.8, 1.2, 2.0}},
- {GEARBOX_WEAPON_EAGLE,
- 0.25, {0.0, 0.1, 0.2, 0.3, 0.5}, {0.1, 0.25, 0.4, 0.7, 1.0},
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
- {GEARBOX_WEAPON_PYTHON,
- 0.75, {0.0, 0.2, 0.4, 1.0, 1.5}, {0.25, 0.5, 0.8, 1.3, 2.2},
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
- {GEARBOX_WEAPON_HORNETGUN,
- 0.25, {0.0, 0.25, 0.4, 0.6, 1.0}, {0.1, 0.4, 0.7, 1.0, 1.5},
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
- {GEARBOX_WEAPON_MP5,
- 0.1, {0.0, 0.1, 0.25, 0.4, 0.5}, {0.1, 0.3, 0.45, 0.65, 0.8},
- 1.0, {0.0, 0.4, 0.7, 1.0, 1.4}, {0.3, 0.7, 1.0, 1.6, 2.0}},
- {GEARBOX_WEAPON_CROSSBOW,
- 0.75, {0.0, 0.2, 0.5, 0.8, 1.0}, {0.25, 0.4, 0.7, 1.0, 1.3},
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
- {GEARBOX_WEAPON_RPG,
- 1.5, {1.0, 2.0, 3.0, 4.0, 5.0}, {3.0, 4.0, 5.0, 6.0, 7.0},
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
- {GEARBOX_WEAPON_GLOCK,
- 0.3, {0.0, 0.1, 0.2, 0.3, 0.4}, {0.1, 0.2, 0.3, 0.4, 0.5},
- 0.2, {0.0, 0.0, 0.1, 0.1, 0.2}, {0.1, 0.1, 0.2, 0.2, 0.4}},
- /* terminator */
- {0, 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0},
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}}
-};
-
-bot_fire_delay_t frontline_fire_delay[] = {
- {FLF_WEAPON_HEGRENADE,
- 0.3, {0.0, 0.1, 0.2, 0.3, 0.4}, {0.1, 0.2, 0.3, 0.4, 0.5},
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
- {FLF_WEAPON_FLASHBANG,
- 0.3, {0.0, 0.1, 0.2, 0.3, 0.4}, {0.1, 0.2, 0.3, 0.4, 0.5},
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
-// {FLF_WEAPON_KNIFE,
-// 0.3, {0.0, 0.1, 0.2, 0.3, 0.4}, {0.1, 0.2, 0.3, 0.4, 0.5},
-// 0.2, {0.0, 0.0, 0.1, 0.1, 0.2}, {0.1, 0.1, 0.2, 0.2, 0.4}},
- {FLF_WEAPON_HK21,
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0},
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
- {FLF_WEAPON_UMP45,
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0},
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
- {FLF_WEAPON_FAMAS,
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0},
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
- {FLF_WEAPON_MSG90,
- 1.2, {0.0, 0.1, 0.2, 0.3, 0.4}, {0.1, 0.2, 0.3, 0.4, 0.5},
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
- {FLF_WEAPON_MP5A2,
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0},
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
- {FLF_WEAPON_AK5,
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0},
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
- {FLF_WEAPON_MP5SD,
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0},
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
- {FLF_WEAPON_M4,
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0},
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
- {FLF_WEAPON_SPAS12,
- 0.9, {0.0, 0.1, 0.2, 0.3, 0.4}, {0.1, 0.2, 0.3, 0.4, 0.5},
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
- {FLF_WEAPON_MAC10,
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0},
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
- {FLF_WEAPON_BERETTA,
- 0.4, {0.0, 0.1, 0.2, 0.3, 0.4}, {0.1, 0.2, 0.3, 0.4, 0.5},
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
- {FLF_WEAPON_MK23,
- 0.4, {0.0, 0.1, 0.2, 0.3, 0.4}, {0.1, 0.2, 0.3, 0.4, 0.5},
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
- /* terminator */
- {0, 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0},
- 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}}
-};
-bot_fire_delay_t ns_fire_delay[] = {
- {AVH_WEAPON_GRENADE_GUN, 0.3f, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.2, 0.3, 0.4, 0.5, 1.0}, 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
- {AVH_WEAPON_SONIC, 0.0f, {0.0, 0.0, 0.0, 0.1, 0.3}, {0.0, 0.0, 0.0, 0.2, 0.6}, 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
- {AVH_WEAPON_HMG, 0.0f, {0.0, 0.0, 0.0, 0.1, 0.3}, {0.0, 0.0, 0.0, 0.2, 0.6}, 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
- {AVH_WEAPON_MG, 0.0f, {0.0, 0.0, 0.0, 0.1, 0.3}, {0.0, 0.0, 0.0, 0.2, 0.6}, 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
- {AVH_WEAPON_PISTOL, 0.0f, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.1, 0.15, 0.2, 0.0, 0.0}, 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
- {AVH_WEAPON_KNIFE, 0.0f, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}, 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
-
- {AVH_WEAPON_PRIMALSCREAM, 0.0f, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}, 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
- {AVH_WEAPON_SWIPE, 0.0f, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}, 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
- {AVH_WEAPON_SPORES, 0.0f, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}, 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
- {AVH_WEAPON_SPIT, 0.0f, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}, 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
- {AVH_WEAPON_CLAWS, 0.0f, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.4, 0.5}, 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
- {AVH_WEAPON_BITE, 0.0f, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}, 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
- {AVH_ABILITY_LEAP, 0.0f, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}, 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
- {AVH_WEAPON_SPIKE, 0.0f, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}, 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}}
-};
-
-void BotCheckTeamplay(void)
-{
- // is this TFC or Counter-Strike or OpFor teamplay or FrontLineForce?
- if ((mod_id == TFC_DLL) || (mod_id == CSTRIKE_DLL) ||
- ((mod_id == GEARBOX_DLL) && (pent_info_ctfdetect != NULL)) ||
- (mod_id == FRONTLINE_DLL) ||
- (mod_id == AVH_DLL) )
- is_team_play = 1.0;
- else
- is_team_play = CVAR_GET_FLOAT("mp_teamplay"); // teamplay enabled?
-
- checked_teamplay = TRUE;
-}
-
-
-edict_t *BotFindEnemy( bot_t *pBot )
-{
- Vector vecEnd;
- static bool flag=TRUE;
- edict_t *pent = NULL;
- edict_t *pNewEnemy;
- float nearestdistance;
- int i;
-
- edict_t *pEdict = pBot->pEdict;
-
- if(pBot->mBotPlayMode != PLAYMODE_PLAYING)
- {
- pBot->pBotEnemy = NULL;
- }
-
- if (pBot->pBotEnemy != NULL) // does the bot already have an enemy?
- {
- vecEnd = pBot->pBotEnemy->v.origin + pBot->pBotEnemy->v.view_ofs;
-
- // if the enemy is dead?
- if (!IsAlive(pBot->pBotEnemy)) // is the enemy dead?, assume bot killed it
- {
- // the enemy is dead, jump for joy about 10% of the time
- if (RANDOM_LONG(1, 100) <= 10)
- pEdict->v.button |= IN_JUMP;
-
- // Taunt sometimes after a kill
- if(RANDOM_LONG(1, 5) == 1)
- {
- pBot->mTimeOfNextTaunt = gpGlobals->time + RANDOM_FLOAT(.3f, 4.0f);
- }
-
- // don't have an enemy anymore so null out the pointer...
- pBot->pBotEnemy = NULL;
- }
- else if (FInViewCone( &vecEnd, pEdict ) &&
- FVisible( vecEnd, pEdict ))
- {
- if ((mod_id == TFC_DLL) &&
- (pEdict->v.playerclass == TFC_CLASS_MEDIC))
- {
- if (pBot->pBotEnemy->v.health >= pBot->pBotEnemy->v.max_health)
- {
- pBot->pBotEnemy = NULL; // player is healed, null out pointer
- }
- }
- else
- {
- // if enemy is still visible and in field of view, keep it
-
- // face the enemy
- Vector v_enemy = pBot->pBotEnemy->v.origin - pEdict->v.origin;
- Vector bot_angles = UTIL_VecToAngles( v_enemy );
-
- pEdict->v.ideal_yaw = bot_angles.y;
-
- BotFixIdealYaw(pEdict);
-
- // keep track of when we last saw an enemy
- pBot->f_bot_see_enemy_time = gpGlobals->time;
-
- return (pBot->pBotEnemy);
- }
- }
- }
-
- pent = NULL;
- pNewEnemy = NULL;
- nearestdistance = 1000;
-
- if (mod_id == TFC_DLL)
- {
- if (pEdict->v.playerclass == TFC_CLASS_MEDIC)
- {
- // search the world for players...
- for (i = 1; i <= gpGlobals->maxClients; i++)
- {
- edict_t *pPlayer = INDEXENT(i);
-
- // skip invalid players and skip self (i.e. this bot)
- if ((pPlayer) && (!pPlayer->free) && (pPlayer != pEdict))
- {
- // skip this player if not alive (i.e. dead or dying)
- if (!IsAlive(pPlayer))
- continue;
-
- if ((b_observer_mode) && !(pPlayer->v.flags & FL_FAKECLIENT))
- continue;
-
- int player_team = UTIL_GetTeam(pPlayer);
- int bot_team = UTIL_GetTeam(pEdict);
-
- // don't target your enemies...
- if ((bot_team != player_team) &&
- !(team_allies[bot_team] & (1<v.health / pPlayer->v.max_health) > 0.50)
- continue; // health greater than 50% so ignore
-
- vecEnd = pPlayer->v.origin + pPlayer->v.view_ofs;
-
- // see if bot can see the player...
- if (FInViewCone( &vecEnd, pEdict ) &&
- FVisible( vecEnd, pEdict ))
- {
- float distance = (pPlayer->v.origin - pEdict->v.origin).Length();
-
- if (distance < nearestdistance)
- {
- nearestdistance = distance;
- pNewEnemy = pPlayer;
-
- pBot->pBotUser = NULL; // don't follow user when enemy found
- }
- }
- }
- }
- }
-
- if (pNewEnemy == NULL)
- {
- while ((pent = UTIL_FindEntityByClassname( pent, "building_sentrygun" )) != NULL)
- {
- int sentry_team = -1;
- int bot_team = UTIL_GetTeam(pEdict);
-
- if (pent->v.colormap == 0xA096)
- sentry_team = 0; // blue team's sentry
- else if (pent->v.colormap == 0x04FA)
- sentry_team = 1; // red team's sentry
- else if (pent->v.colormap == 0x372D)
- sentry_team = 2; // yellow team's sentry
- else if (pent->v.colormap == 0x6E64)
- sentry_team = 3; // green team's sentry
-
- // don't target your own team's sentry guns...
- if (bot_team == sentry_team)
- continue;
-
- // don't target your allie's sentry guns either...
- if (team_allies[bot_team] & (1<v.origin + pent->v.view_ofs;
-
- // is this sentry gun visible?
- if (FInViewCone( &vecEnd, pEdict ) &&
- FVisible( vecEnd, pEdict ))
- {
- float distance = (pent->v.origin - pEdict->v.origin).Length();
-
- // is this the closest sentry gun?
- if (distance < nearestdistance)
- {
- nearestdistance = distance;
- pNewEnemy = pent;
-
- pBot->pBotUser = NULL; // don't follow user when enemy found
- }
- }
- }
- }
- }
-
- if (pNewEnemy == NULL)
- {
- nearestdistance = 2500;
-
- // search the world for players...(and enemies)
- //for (i = 1; i <= gpGlobals->maxClients; i++)
- for (i = 1; i <= gpGlobals->maxEntities; i++)
- {
- edict_t *pEntity = INDEXENT(i);
-
- // skip invalid players and skip self (i.e. this bot)
- if ((pEntity) && (!pEntity->free) && (pEntity != pEdict) && (FBitSet(pEntity->v.flags, FL_MONSTER) || FBitSet(pEntity->v.flags, FL_CLIENT)))
- {
- // Skip webs?
- const char* theClassName = STRING(pEntity->v.classname);
-
- // Skip cloaked players
-// if(pEntity->v.iuser4 & MASK_ALIEN_CLOAKED)
-// continue;
-
- // skip this player if not alive (i.e. dead or dying)
- if (!IsAlive(pEntity))
- continue;
-
- if ((b_observer_mode) && !(pEntity->v.flags & FL_FAKECLIENT))
- continue;
-
- if (!checked_teamplay) // check for team play...
- BotCheckTeamplay();
-
- // is team play enabled?
- if (is_team_play > 0.0)
- {
- int player_team = UTIL_GetTeam(pEntity);
- int bot_team = UTIL_GetTeam(pEdict);
-
- // don't target your teammates...
- if (bot_team == player_team)
- continue;
-
- if (mod_id == TFC_DLL)
- {
- // don't target your allies either...
- if (team_allies[bot_team] & (1<v.origin + pEntity->v.view_ofs;
-
- float theDistance = (pEdict->v.origin - pEntity->v.origin).Length();
-
- // see if bot can see the player...
- if ((FInViewCone( &vecEnd, pEdict ) &&
- FVisible( vecEnd, pEdict )) || (theDistance < 32))
- {
- float distance = (pEntity->v.origin - pEdict->v.origin).Length();
- if (distance < nearestdistance)
- {
- nearestdistance = distance;
- pNewEnemy = pEntity;
-
- pBot->pBotUser = NULL; // don't follow user when enemy found
- }
- }
- }
- }
- }
-
- if (pNewEnemy)
- {
- // face the enemy
- Vector v_enemy = pNewEnemy->v.origin - pEdict->v.origin;
- Vector bot_angles = UTIL_VecToAngles( v_enemy );
-
- pEdict->v.ideal_yaw = bot_angles.y;
-
- BotFixIdealYaw(pEdict);
-
- // keep track of when we last saw an enemy
- pBot->f_bot_see_enemy_time = gpGlobals->time;
- }
-
- // has the bot NOT seen an ememy for at least 5 seconds (time to reload)?
- if ((pBot->f_bot_see_enemy_time > 0) &&
- ((pBot->f_bot_see_enemy_time + 5.0) <= gpGlobals->time))
- {
- pBot->f_bot_see_enemy_time = -1; // so we won't keep reloading
-
- if ((mod_id == VALVE_DLL) || (mod_id == GEARBOX_DLL) || (mod_id == AVH_DLL))
- {
- pEdict->v.button |= IN_RELOAD; // press reload button
- }
- }
-
- return (pNewEnemy);
-}
-
-
-Vector BotBodyTarget( edict_t *pBotEnemy, bot_t *pBot )
-{
- Vector target;
- float f_distance;
- float f_scale;
- int d_x = 0;
- int d_y = 0;
- int d_z = 0;
-
- edict_t *pEdict = pBot->pEdict;
-
- f_distance = (pBotEnemy->v.origin - pEdict->v.origin).Length();
-
- if (f_distance > 1000)
- f_scale = 1.0;
- else if (f_distance > 100)
- f_scale = f_distance / 1000.0;
- else
- f_scale = 0.1;
-
- switch (pBot->bot_skill)
- {
- case 0:
- // VERY GOOD, same as from CBasePlayer::BodyTarget (in player.h)
- target = pBotEnemy->v.origin + pBotEnemy->v.view_ofs * RANDOM_FLOAT( 0.5, 1.1 );
- d_x = 0; // no offset
- d_y = 0;
- d_z = 0;
- break;
- case 1:
- // GOOD, offset a little for x, y, and z
- target = pBotEnemy->v.origin + pBotEnemy->v.view_ofs; // aim for the head (if you can find it)
- d_x = RANDOM_FLOAT(-5, 5) * f_scale;
- d_y = RANDOM_FLOAT(-5, 5) * f_scale;
- d_z = RANDOM_FLOAT(-10, 10) * f_scale;
- break;
- case 2:
- // FAIR, offset somewhat for x, y, and z
- target = pBotEnemy->v.origin; // aim for the body
- d_x = RANDOM_FLOAT(-10, 10) * f_scale;
- d_y = RANDOM_FLOAT(-10, 10) * f_scale;
- d_z = RANDOM_FLOAT(-18, 18) * f_scale;
- break;
- case 3:
- // POOR, offset for x, y, and z
- target = pBotEnemy->v.origin; // aim for the body
- d_x = RANDOM_FLOAT(-20, 20) * f_scale;
- d_y = RANDOM_FLOAT(-20, 20) * f_scale;
- d_z = RANDOM_FLOAT(-32, 32) * f_scale;
- break;
- case 4:
- // BAD, offset lots for x, y, and z
- target = pBotEnemy->v.origin; // aim for the body
- d_x = RANDOM_FLOAT(-35, 35) * f_scale;
- d_y = RANDOM_FLOAT(-35, 35) * f_scale;
- d_z = RANDOM_FLOAT(-50, 50) * f_scale;
- break;
- }
-
- target = target + Vector(d_x, d_y, d_z);
-
- return target;
-}
-
-
-// specifing a weapon_choice allows you to choose the weapon the bot will
-// use (assuming enough ammo exists for that weapon)
-// BotFireWeapon will return TRUE if weapon was fired, FALSE otherwise
-
-bool BotFireWeapon( Vector v_enemy, bot_t *pBot, int weapon_choice)
-{
- bot_weapon_select_t *pSelect = NULL;
- bot_fire_delay_t *pDelay = NULL;
- int select_index;
- int iId;
- bool use_primary;
- bool use_secondary;
- int use_percent;
- int primary_percent;
-
- edict_t *pEdict = pBot->pEdict;
-
- float distance = v_enemy.Length(); // how far away is the enemy?
-
- if (mod_id == VALVE_DLL)
- {
- pSelect = &valve_weapon_select[0];
- pDelay = &valve_fire_delay[0];
- }
- else if (mod_id == TFC_DLL)
- {
- pSelect = &tfc_weapon_select[0];
- pDelay = &tfc_fire_delay[0];
- }
- else if (mod_id == CSTRIKE_DLL)
- {
- pSelect = &cs_weapon_select[0];
- pDelay = &cs_fire_delay[0];
- }
- else if (mod_id == GEARBOX_DLL)
- {
- pSelect = &gearbox_weapon_select[0];
- pDelay = &gearbox_fire_delay[0];
- }
- else if (mod_id == FRONTLINE_DLL)
- {
- pSelect = &frontline_weapon_select[0];
- pDelay = &frontline_fire_delay[0];
- }
- else if (mod_id == AVH_DLL)
- {
- pSelect = &ns_weapon_select[0];
- pDelay = &ns_fire_delay[0];
- }
-
- if (pSelect)
- {
- // are we charging the primary fire?
- if (pBot->f_primary_charging > 0)
- {
- iId = pBot->charging_weapon_id;
-
- if (mod_id == TFC_DLL)
- {
- if (iId == TF_WEAPON_SNIPERRIFLE)
- {
- pBot->f_move_speed = 0; // don't move while using sniper rifle
- }
- }
-
- // is it time to fire the charged weapon?
- if (pBot->f_primary_charging <= gpGlobals->time)
- {
- // we DON'T set pEdict->v.button here to release the
- // fire button which will fire the charged weapon
-
- pBot->f_primary_charging = -1; // -1 means not charging
-
- // find the correct fire delay for this weapon
- select_index = 0;
-
- while ((pSelect[select_index].iId) &&
- (pSelect[select_index].iId != iId))
- select_index++;
-
- // set next time to shoot
- int skill = pBot->bot_skill;
- float base_delay, min_delay, max_delay;
-
- base_delay = pDelay[select_index].primary_base_delay;
- min_delay = pDelay[select_index].primary_min_delay[skill];
- max_delay = pDelay[select_index].primary_max_delay[skill];
-
- pBot->f_shoot_time = gpGlobals->time + base_delay +
- RANDOM_FLOAT(min_delay, max_delay);
-
- return TRUE;
- }
- else
- {
- pEdict->v.button |= IN_ATTACK; // charge the weapon
- pBot->f_shoot_time = gpGlobals->time; // keep charging
-
- return TRUE;
- }
- }
-
- // are we charging the secondary fire?
- if (pBot->f_secondary_charging > 0)
- {
- iId = pBot->charging_weapon_id;
-
- // is it time to fire the charged weapon?
- if (pBot->f_secondary_charging <= gpGlobals->time)
- {
- // we DON'T set pEdict->v.button here to release the
- // fire button which will fire the charged weapon
-
- pBot->f_secondary_charging = -1; // -1 means not charging
-
- // find the correct fire delay for this weapon
- select_index = 0;
-
- while ((pSelect[select_index].iId) &&
- (pSelect[select_index].iId != iId))
- select_index++;
-
- // set next time to shoot
- int skill = pBot->bot_skill;
- float base_delay, min_delay, max_delay;
-
- base_delay = pDelay[select_index].secondary_base_delay;
- min_delay = pDelay[select_index].secondary_min_delay[skill];
- max_delay = pDelay[select_index].secondary_max_delay[skill];
-
- pBot->f_shoot_time = gpGlobals->time + base_delay +
- RANDOM_FLOAT(min_delay, max_delay);
-
- return TRUE;
- }
- else
- {
- pEdict->v.button |= IN_ATTACK2; // charge the weapon
- pBot->f_shoot_time = gpGlobals->time; // keep charging
-
- return TRUE;
- }
- }
-
- select_index = 0;
-
- // loop through all the weapons until terminator is found...
- while (pSelect[select_index].iId)
- {
- // was a weapon choice specified? (and if so do they NOT match?)
- if ((weapon_choice != 0) &&
- (weapon_choice != pSelect[select_index].iId))
- {
- select_index++; // skip to next weapon
- continue;
- }
-
- // is the bot NOT carrying this weapon?
- if (!(pBot->bot_weapons & (1<bot_skill+1) > pSelect[select_index].skill_level)
- {
- select_index++; // skip to next weapon
- continue;
- }
-
- // is the bot underwater and does this weapon NOT work under water?
- if ((pEdict->v.waterlevel == 3) &&
- !(pSelect[select_index].can_use_underwater))
- {
- select_index++; // skip to next weapon
- continue;
- }
-
- use_percent = RANDOM_LONG(1, 100);
-
- // is use percent greater than weapon use percent?
- if (use_percent > pSelect[select_index].use_percent)
- {
- select_index++; // skip to next weapon
- continue;
- }
-
- iId = pSelect[select_index].iId;
- use_primary = FALSE;
- use_secondary = FALSE;
- primary_percent = RANDOM_LONG(1, 100);
-
- // is primary percent less than weapon primary percent AND
- // no ammo required for this weapon OR
- // enough ammo available to fire AND
- // the bot is far enough away to use primary fire AND
- // the bot is close enough to the enemy to use primary fire
-
- if ((primary_percent <= pSelect[select_index].primary_fire_percent) &&
- ((weapon_defs[iId].iAmmo1 == -1) ||
- (pBot->m_rgAmmo[weapon_defs[iId].iAmmo1] >=
- pSelect[select_index].min_primary_ammo)) &&
- (distance >= pSelect[select_index].primary_min_distance) &&
- (distance <= pSelect[select_index].primary_max_distance))
- {
- use_primary = TRUE;
- }
-
- // otherwise see if there is enough secondary ammo AND
- // the bot is far enough away to use secondary fire AND
- // the bot is close enough to the enemy to use secondary fire
-
- else if (((weapon_defs[iId].iAmmo2 == -1) ||
- (pBot->m_rgAmmo[weapon_defs[iId].iAmmo2] >=
- pSelect[select_index].min_secondary_ammo)) &&
- (distance >= pSelect[select_index].secondary_min_distance) &&
- (distance <= pSelect[select_index].secondary_max_distance))
- {
- use_secondary = TRUE;
- }
-
- // see if there wasn't enough ammo to fire the weapon...
- if ((use_primary == FALSE) && (use_secondary == FALSE))
- {
- select_index++; // skip to next weapon
- continue;
- }
-
- // select this weapon if it isn't already selected
- if (pBot->current_weapon.iId != iId)
- UTIL_SelectItem(pEdict, pSelect[select_index].weapon_name);
-
- if (pDelay[select_index].iId != iId)
- {
- char msg[80];
- sprintf(msg, "fire_delay mismatch for weapon id=%d\n",iId);
- ALERT(at_console, msg);
-
- return FALSE;
- }
-
- if (mod_id == TFC_DLL)
- {
- if (iId == TF_WEAPON_SNIPERRIFLE)
- {
- pBot->f_move_speed = 0; // don't move while using sniper rifle
-
- if (pEdict->v.velocity.Length() > 50)
- {
- return FALSE; // don't press attack key until velocity is < 50
- }
- }
-
- if (pEdict->v.playerclass == TFC_CLASS_MEDIC)
- {
- int player_team = UTIL_GetTeam(pBot->pBotEnemy);
- int bot_team = UTIL_GetTeam(pEdict);
-
- // only heal your teammates or allies...
- if (((bot_team == player_team) ||
- (team_allies[bot_team] & (1<v.button |= IN_ATTACK; // use primary attack
-
- if (pSelect[select_index].primary_fire_charge)
- {
- pBot->charging_weapon_id = iId;
-
- // release primary fire after the appropriate delay...
- pBot->f_primary_charging = gpGlobals->time +
- pSelect[select_index].primary_charge_delay;
-
- pBot->f_shoot_time = gpGlobals->time; // keep charging
- }
- else
- {
- // set next time to shoot
- if (pSelect[select_index].primary_fire_hold)
- pBot->f_shoot_time = gpGlobals->time; // don't let button up
- else
- {
- int skill = pBot->bot_skill;
- float base_delay, min_delay, max_delay;
-
- base_delay = pDelay[select_index].primary_base_delay;
- min_delay = pDelay[select_index].primary_min_delay[skill];
- max_delay = pDelay[select_index].primary_max_delay[skill];
-
- pBot->f_shoot_time = gpGlobals->time + base_delay +
- RANDOM_FLOAT(min_delay, max_delay);
- }
- }
- }
- else // MUST be use_secondary...
- {
- pEdict->v.button |= IN_ATTACK2; // use secondary attack
-
- if (pSelect[select_index].secondary_fire_charge)
- {
- pBot->charging_weapon_id = iId;
-
- // release secondary fire after the appropriate delay...
- pBot->f_secondary_charging = gpGlobals->time +
- pSelect[select_index].secondary_charge_delay;
-
- pBot->f_shoot_time = gpGlobals->time; // keep charging
- }
- else
- {
- // set next time to shoot
- if (pSelect[select_index].secondary_fire_hold)
- pBot->f_shoot_time = gpGlobals->time; // don't let button up
- else
- {
- int skill = pBot->bot_skill;
- float base_delay, min_delay, max_delay;
-
- base_delay = pDelay[select_index].secondary_base_delay;
- min_delay = pDelay[select_index].secondary_min_delay[skill];
- max_delay = pDelay[select_index].secondary_max_delay[skill];
-
- pBot->f_shoot_time = gpGlobals->time + base_delay +
- RANDOM_FLOAT(min_delay, max_delay);
- }
- }
- }
-
- return TRUE; // weapon was fired
- }
- }
-
- // didn't have any available weapons or ammo, return FALSE
- return FALSE;
-}
-
-
-void BotShootAtEnemy( bot_t *pBot )
-{
- float f_distance;
-
- edict_t *pEdict = pBot->pEdict;
-
- // aim for the head and/or body
- Vector v_enemy = BotBodyTarget( pBot->pBotEnemy, pBot ) - GetGunPosition(pEdict);
-
- pEdict->v.v_angle = UTIL_VecToAngles( v_enemy );
-
- if (pEdict->v.v_angle.y > 180)
- pEdict->v.v_angle.y -=360;
-
- // Paulo-La-Frite - START bot aiming bug fix
- if (pEdict->v.v_angle.x > 180)
- pEdict->v.v_angle.x -=360;
-
- // set the body angles to point the gun correctly
- pEdict->v.angles.x = pEdict->v.v_angle.x / 3;
- pEdict->v.angles.y = pEdict->v.v_angle.y;
- pEdict->v.angles.z = 0;
-
- // adjust the view angle pitch to aim correctly (MUST be after body v.angles stuff)
- pEdict->v.v_angle.x = -pEdict->v.v_angle.x;
- // Paulo-La-Frite - END
-
- float x = pEdict->v.v_angle.y;
- if (x > 180) x -= 360;
- if (abs(pEdict->v.ideal_yaw - x) > 2.0)
- fp = NULL;
-
- pEdict->v.ideal_yaw = pEdict->v.v_angle.y;
-
- BotFixIdealYaw(pEdict);
-
-
- v_enemy.z = 0; // ignore z component (up & down)
-
- f_distance = v_enemy.Length(); // how far away is the enemy scum?
-
- if (f_distance > 200) // run if distance to enemy is far
- pBot->f_move_speed = pBot->f_max_speed;
- else if (f_distance > 20) // walk if distance is closer
- pBot->f_move_speed = pBot->f_max_speed / 2;
- else // don't move if close enough
- pBot->f_move_speed = 0.0;
-
-
- // is it time to shoot yet?
- if (pBot->f_shoot_time <= gpGlobals->time)
- {
- // select the best weapon to use at this distance and fire...
- BotFireWeapon(v_enemy, pBot, 0);
- }
-}
-
-
-bool BotShootTripmine( bot_t *pBot )
-{
- edict_t *pEdict = pBot->pEdict;
-
- if (pBot->b_shoot_tripmine != TRUE)
- return FALSE;
-
- // aim at the tripmine and fire the glock...
-
- Vector v_enemy = pBot->v_tripmine - GetGunPosition( pEdict );
-
- pEdict->v.v_angle = UTIL_VecToAngles( v_enemy );
-
- if (pEdict->v.v_angle.y > 180)
- pEdict->v.v_angle.y -=360;
-
- // Paulo-La-Frite - START bot aiming bug fix
- if (pEdict->v.v_angle.x > 180)
- pEdict->v.v_angle.x -=360;
-
- // set the body angles to point the gun correctly
- pEdict->v.angles.x = pEdict->v.v_angle.x / 3;
- pEdict->v.angles.y = pEdict->v.v_angle.y;
- pEdict->v.angles.z = 0;
-
- // adjust the view angle pitch to aim correctly (MUST be after body v.angles stuff)
- pEdict->v.v_angle.x = -pEdict->v.v_angle.x;
- // Paulo-La-Frite - END
-
- pEdict->v.ideal_yaw = pEdict->v.v_angle.y;
-
- BotFixIdealYaw(pEdict);
-
- return (BotFireWeapon( v_enemy, pBot, VALVE_WEAPON_GLOCK ));
-}
-
+//
+// HPB bot - botman's High Ping Bastard bot
+//
+// (http://planethalflife.com/botman/)
+//
+// bot_combat.cpp
+//
+
+#include "dlls/extdll.h"
+#include "dlls/util.h"
+#include "dlls/cbase.h"
+
+#include "bot.h"
+#include "bot_func.h"
+#include "bot_weapons.h"
+#include "mod/AvHBasePlayerWeaponConstants.h"
+#include "mod/AvHMarineWeaponConstants.h"
+#include "mod/AvHAlienWeaponConstants.h"
+#include "mod/AvHPlayer.h"
+
+extern int mod_id;
+extern bot_weapon_t weapon_defs[MAX_WEAPONS];
+extern bool b_observer_mode;
+extern int team_allies[4];
+extern edict_t *pent_info_ctfdetect;
+extern float is_team_play;
+extern bool checked_teamplay;
+
+FILE *fp;
+
+
+typedef struct
+{
+ int iId; // the weapon ID value
+ char weapon_name[64]; // name of the weapon when selecting it
+ int skill_level; // bot skill must be less than or equal to this value
+ float primary_min_distance; // 0 = no minimum
+ float primary_max_distance; // 9999 = no maximum
+ float secondary_min_distance; // 0 = no minimum
+ float secondary_max_distance; // 9999 = no maximum
+ int use_percent; // times out of 100 to use this weapon when available
+ bool can_use_underwater; // can use this weapon underwater
+ int primary_fire_percent; // times out of 100 to use primary fire
+ int min_primary_ammo; // minimum ammout of primary ammo needed to fire
+ int min_secondary_ammo; // minimum ammout of seconday ammo needed to fire
+ bool primary_fire_hold; // hold down primary fire button to use?
+ bool secondary_fire_hold; // hold down secondary fire button to use?
+ bool primary_fire_charge; // charge weapon using primary fire?
+ bool secondary_fire_charge; // charge weapon using secondary fire?
+ float primary_charge_delay; // time to charge weapon
+ float secondary_charge_delay; // time to charge weapon
+} bot_weapon_select_t;
+
+typedef struct
+{
+ int iId;
+ float primary_base_delay;
+ float primary_min_delay[5];
+ float primary_max_delay[5];
+ float secondary_base_delay;
+ float secondary_min_delay[5];
+ float secondary_max_delay[5];
+} bot_fire_delay_t;
+
+
+// weapons are stored in priority order, most desired weapon should be at
+// the start of the array and least desired should be at the end
+
+bot_weapon_select_t valve_weapon_select[] = {
+ {VALVE_WEAPON_CROWBAR, "weapon_crowbar", 2, 0.0, 50.0, 0.0, 0.0,
+ 100, TRUE, 100, 0, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
+ {VALVE_WEAPON_HANDGRENADE, "weapon_handgrenade", 5, 250.0, 750.0, 0.0, 0.0,
+ 30, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
+ {VALVE_WEAPON_SNARK, "weapon_snark", 5, 150.0, 500.0, 0.0, 0.0,
+ 50, FALSE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
+ {VALVE_WEAPON_EGON, "weapon_egon", 5, 0.0, 9999.0, 0.0, 0.0,
+ 100, FALSE, 100, 1, 0, TRUE, FALSE, FALSE, FALSE, 0.0, 0.0},
+ {VALVE_WEAPON_GAUSS, "weapon_gauss", 5, 0.0, 9999.0, 0.0, 9999.0,
+ 100, FALSE, 80, 1, 10, FALSE, FALSE, FALSE, TRUE, 0.0, 0.8},
+ {VALVE_WEAPON_SHOTGUN, "weapon_shotgun", 5, 30.0, 150.0, 30.0, 150.0,
+ 100, FALSE, 70, 1, 2, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
+ {VALVE_WEAPON_PYTHON, "weapon_357", 5, 30.0, 700.0, 0.0, 0.0,
+ 100, FALSE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
+ {VALVE_WEAPON_HORNETGUN, "weapon_hornetgun", 5, 30.0, 1000.0, 30.0, 1000.0,
+ 100, TRUE, 50, 1, 4, FALSE, TRUE, FALSE, FALSE, 0.0, 0.0},
+ {VALVE_WEAPON_MP5, "weapon_9mmAR", 5, 0.0, 250.0, 300.0, 600.0,
+ 100, FALSE, 90, 1, 1, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
+ {VALVE_WEAPON_CROSSBOW, "weapon_crossbow", 5, 100.0, 1000.0, 0.0, 0.0,
+ 100, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
+ {VALVE_WEAPON_RPG, "weapon_rpg", 5, 300.0, 9999.0, 0.0, 0.0,
+ 100, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
+ {VALVE_WEAPON_GLOCK, "weapon_9mmhandgun", 5, 0.0, 1200.0, 0.0, 1200.0,
+ 100, TRUE, 70, 1, 1, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
+ /* terminator */
+ {0, "", 0, 0.0, 0.0, 0.0, 0.0, 0, TRUE, 0, 1, 1, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0}
+};
+
+bot_weapon_select_t tfc_weapon_select[] = {
+ {TF_WEAPON_AXE, "tf_weapon_axe", 5, 0.0, 50.0, 0.0, 0.0,
+ 100, TRUE, 100, 0, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
+ {TF_WEAPON_KNIFE, "tf_weapon_knife", 5, 0.0, 40.0, 0.0, 0.0,
+ 100, TRUE, 100, 0, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
+ {TF_WEAPON_SPANNER, "tf_weapon_knife", 5, 0.0, 40.0, 0.0, 0.0,
+ 100, TRUE, 100, 0, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
+ {TF_WEAPON_MEDIKIT, "tf_weapon_medikit", 5, 0.0, 40.0, 0.0, 0.0,
+ 100, TRUE, 100, 0, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
+ {TF_WEAPON_SNIPERRIFLE, "tf_weapon_sniperrifle", 5, 300.0, 2500.0, 0.0, 0.0,
+ 100, TRUE, 100, 1, 0, FALSE, FALSE, TRUE, FALSE, 1.0, 0.0},
+ {TF_WEAPON_FLAMETHROWER, "tf_weapon_flamethrower", 5, 100.0, 500.0, 0.0, 0.0,
+ 100, FALSE, 100, 1, 0, TRUE, FALSE, FALSE, FALSE, 0.0, 0.0},
+ {TF_WEAPON_AC, "tf_weapon_ac", 5, 50.0, 1000.0, 0.0, 0.0,
+ 100, TRUE, 100, 1, 0, TRUE, FALSE, FALSE, FALSE, 0.0, 0.0},
+ {TF_WEAPON_GL, "tf_weapon_gl", 5, 300.0, 900.0, 0.0, 0.0,
+ 100, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
+ {TF_WEAPON_RPG, "tf_weapon_rpg", 5, 300.0, 900.0, 0.0, 0.0,
+ 100, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
+ {TF_WEAPON_IC, "tf_weapon_ic", 5, 300.0, 800.0, 0.0, 0.0,
+ 100, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
+ {TF_WEAPON_TRANQ, "tf_weapon_tranq", 5, 40.0, 1000.0, 0.0, 0.0,
+ 100, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
+ {TF_WEAPON_RAILGUN, "tf_weapon_railgun", 5, 40.0, 800.0, 0.0, 0.0,
+ 100, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
+ {TF_WEAPON_SUPERNAILGUN, "tf_weapon_superng", 5, 40.0, 800.0, 0.0, 0.0,
+ 100, TRUE, 100, 1, 0, TRUE, FALSE, FALSE, FALSE, 0.0, 0.0},
+ {TF_WEAPON_SUPERSHOTGUN, "tf_weapon_supershotgun", 5, 40.0, 500.0, 0.0, 0.0,
+ 100, TRUE, 100, 2, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
+ {TF_WEAPON_AUTORIFLE, "tf_weapon_autorifle", 5, 0.0, 800.0, 0.0, 0.0,
+ 100, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
+ {TF_WEAPON_SHOTGUN, "tf_weapon_shotgun", 5, 40.0, 400.0, 0.0, 0.0,
+ 100, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
+ {TF_WEAPON_NAILGUN, "tf_weapon_ng", 5, 40.0, 600.0, 0.0, 0.0,
+ 100, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
+ /* terminator */
+ {0, "", 0, 0.0, 0.0, 0.0, 0.0, 0, TRUE, 0, 1, 1, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0}
+};
+
+bot_weapon_select_t cs_weapon_select[] = {
+ {CS_WEAPON_KNIFE, "weapon_knife", 5, 0.0, 50.0, 0.0, 0.0,
+ 100, TRUE, 100, 0, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
+ {CS_WEAPON_USP, "weapon_usp", 5, 0.0, 1200.0, 0.0, 1200.0,
+ 100, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
+ {CS_WEAPON_GLOCK18, "weapon_glock18", 5, 0.0, 1200.0, 0.0, 1200.0,
+ 100, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
+ /* terminator */
+ {0, "", 0, 0.0, 0.0, 0.0, 0.0, 0, TRUE, 0, 1, 1, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0}
+};
+
+bot_weapon_select_t gearbox_weapon_select[] = {
+ {GEARBOX_WEAPON_PIPEWRENCH, "weapon_pipewrench", 3, 0.0, 50.0, 0.0, 0.0,
+ 100, TRUE, 100, 0, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
+ {GEARBOX_WEAPON_KNIFE, "weapon_knife", 4, 0.0, 50.0, 0.0, 0.0,
+ 100, TRUE, 100, 0, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
+ {GEARBOX_WEAPON_CROWBAR, "weapon_crowbar", 2, 0.0, 50.0, 0.0, 0.0,
+ 100, TRUE, 100, 0, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
+ {GEARBOX_WEAPON_DISPLACER, "weapon_displacer", 5, 100.0, 1000.0, 0.0, 0.0,
+ 100, TRUE, 100, 0, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
+ {GEARBOX_WEAPON_SPORELAUNCHER, "weapon_sporelauncher", 5, 500.0, 1000.0, 0.0, 0.0,
+ 100, TRUE, 100, 0, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
+ {GEARBOX_WEAPON_SHOCKRIFLE, "weapon_shockrifle", 5, 50.0, 800.0, 0.0, 0.0,
+ 100, TRUE, 100, 0, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
+ {GEARBOX_WEAPON_SNIPERRIFLE, "weapon_sniperrifle", 5, 50.0, 1500.0, 0.0, 0.0,
+ 100, FALSE, 100, 0, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
+ {GEARBOX_WEAPON_HANDGRENADE, "weapon_handgrenade", 5, 250.0, 750.0, 0.0, 0.0,
+ 30, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
+ {GEARBOX_WEAPON_SNARK, "weapon_snark", 5, 150.0, 500.0, 0.0, 0.0,
+ 50, FALSE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
+ {GEARBOX_WEAPON_EGON, "weapon_egon", 5, 0.0, 9999.0, 0.0, 0.0,
+ 100, FALSE, 100, 1, 0, TRUE, FALSE, FALSE, FALSE, 0.0, 0.0},
+ {GEARBOX_WEAPON_GAUSS, "weapon_gauss", 5, 0.0, 9999.0, 0.0, 9999.0,
+ 100, FALSE, 80, 1, 10, FALSE, FALSE, FALSE, TRUE, 0.0, 0.8},
+ {GEARBOX_WEAPON_M249, "weapon_m249", 5, 0.0, 400.0, 0.0, 0.0,
+ 100, FALSE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
+ {GEARBOX_WEAPON_SHOTGUN, "weapon_shotgun", 5, 30.0, 150.0, 30.0, 150.0,
+ 100, FALSE, 70, 1, 2, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
+ {GEARBOX_WEAPON_EAGLE, "weapon_eagle", 5, 0.0, 1200.0, 0.0, 0.0,
+ 100, FALSE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
+ {GEARBOX_WEAPON_PYTHON, "weapon_357", 5, 30.0, 700.0, 0.0, 0.0,
+ 100, FALSE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
+ {GEARBOX_WEAPON_HORNETGUN, "weapon_hornetgun", 5, 30.0, 1000.0, 30.0, 1000.0,
+ 100, TRUE, 50, 1, 4, FALSE, TRUE, FALSE, FALSE, 0.0, 0.0},
+ {GEARBOX_WEAPON_MP5, "weapon_9mmAR", 5, 0.0, 250.0, 300.0, 600.0,
+ 100, FALSE, 90, 1, 1, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
+ {GEARBOX_WEAPON_CROSSBOW, "weapon_crossbow", 5, 100.0, 1000.0, 0.0, 0.0,
+ 100, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
+ {GEARBOX_WEAPON_RPG, "weapon_rpg", 5, 300.0, 9999.0, 0.0, 0.0,
+ 100, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
+ {GEARBOX_WEAPON_GLOCK, "weapon_9mmhandgun", 5, 0.0, 1200.0, 0.0, 1200.0,
+ 100, TRUE, 70, 1, 1, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
+ /* terminator */
+ {0, "", 0, 0.0, 0.0, 0.0, 0.0, 0, TRUE, 0, 1, 1, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0}
+};
+
+bot_weapon_select_t frontline_weapon_select[] = {
+ {FLF_WEAPON_HEGRENADE, "weapon_hegrenade", 3, 200.0, 1000.0, 0.0, 0.0,
+ 100, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
+ {FLF_WEAPON_FLASHBANG, "weapon_flashbang", 3, 100.0, 800.0, 0.0, 0.0,
+ 100, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
+// {FLF_WEAPON_KNIFE, "weapon_knife", 3, 0.0, 60.0, 0.0, 0.0,
+// 100, TRUE, 100, 0, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
+ {FLF_WEAPON_HK21, "weapon_hk21", 5, 0.0, 900.0, 0.0, 0.0,
+ 100, TRUE, 100, 1, 0, TRUE, FALSE, FALSE, FALSE, 0.0, 0.0},
+ {FLF_WEAPON_UMP45, "weapon_ump45", 5, 0.0, 900.0, 0.0, 0.0,
+ 100, TRUE, 100, 1, 0, TRUE, FALSE, FALSE, FALSE, 0.0, 0.0},
+ {FLF_WEAPON_FAMAS, "weapon_famas", 5, 0.0, 500.0, 0.0, 0.0,
+ 100, TRUE, 100, 1, 0, TRUE, FALSE, FALSE, FALSE, 0.0, 0.0},
+ {FLF_WEAPON_MSG90, "weapon_msg90", 5, 0.0, 2500.0, 0.0, 0.0,
+ 100, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
+ {FLF_WEAPON_MP5A2, "weapon_mp5a2", 5, 0.0, 900.0, 0.0, 0.0,
+ 100, TRUE, 100, 1, 0, TRUE, FALSE, FALSE, FALSE, 0.0, 0.0},
+ {FLF_WEAPON_AK5, "weapon_ak5", 5, 0.0, 900.0, 0.0, 0.0,
+ 100, TRUE, 100, 1, 0, TRUE, FALSE, FALSE, FALSE, 0.0, 0.0},
+ {FLF_WEAPON_MP5SD, "weapon_mp5sd", 5, 0.0, 900.0, 0.0, 0.0,
+ 100, TRUE, 100, 1, 0, TRUE, FALSE, FALSE, FALSE, 0.0, 0.0},
+ {FLF_WEAPON_M4, "weapon_m4", 5, 0.0, 900.0, 0.0, 0.0,
+ 100, TRUE, 100, 1, 0, TRUE, FALSE, FALSE, FALSE, 0.0, 0.0},
+ {FLF_WEAPON_SPAS12, "weapon_spas12", 5, 0.0, 900.0, 0.0, 0.0,
+ 100, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
+ {FLF_WEAPON_MAC10, "weapon_mac10", 5, 0.0, 500.0, 0.0, 0.0,
+ 100, TRUE, 100, 1, 0, TRUE, FALSE, FALSE, FALSE, 0.0, 0.0},
+ {FLF_WEAPON_BERETTA, "weapon_beretta", 5, 0.0, 1200.0, 0.0, 1200.0,
+ 100, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
+ {FLF_WEAPON_MK23, "weapon_mk23", 5, 0.0, 1200.0, 0.0, 1200.0,
+ 100, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
+ /* terminator */
+ {0, "", 0, 0.0, 0.0, 0.0, 0.0, 0, TRUE, 0, 1, 1, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0}
+};
+
+//int iId; // the weapon ID value
+//char weapon_name[64]; // name of the weapon when selecting it
+//int skill_level; // bot skill must be less than or equal to this value
+//float primary_min_distance; // 0 = no minimum
+//float primary_max_distance; // 9999 = no maximum
+//float secondary_min_distance; // 0 = no minimum
+//float secondary_max_distance; // 9999 = no maximum
+//int use_percent; // times out of 100 to use this weapon when available
+//bool can_use_underwater; // can use this weapon underwater
+//int primary_fire_percent; // times out of 100 to use primary fire
+//int min_primary_ammo; // minimum ammout of primary ammo needed to fire
+//int min_secondary_ammo; // minimum ammout of seconday ammo needed to fire
+//bool primary_fire_hold; // hold down primary fire button to use?
+//bool secondary_fire_hold; // hold down secondary fire button to use?
+//bool primary_fire_charge; // charge weapon using primary fire?
+//bool secondary_fire_charge; // charge weapon using secondary fire?
+//float primary_charge_delay; // time to charge weapon
+//float secondary_charge_delay; // time to charge weapon
+
+bot_weapon_select_t ns_weapon_select[] = {
+ {AVH_WEAPON_GRENADE_GUN, kwsGrenadeGun, 3, 120, kGGRange, 0.0, 0.0, 100, FALSE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0f, 0.0f},
+ {AVH_WEAPON_SONIC, kwsShotGun, 3, 0.0, kSGRange, 0.0, 0.0, 100, FALSE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0f, 0.0f},
+ {AVH_WEAPON_HMG, kwsHeavyMachineGun, 3, 0.0, kHMGRange, 0.0, 0.0, 100, FALSE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0f, 0.0f},
+ {AVH_WEAPON_MG, kwsMachineGun, 3, 0.0, kMGRange, 0.0, 0.0, 100, FALSE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0f, 0.0f},
+ {AVH_WEAPON_PISTOL, kwsPistol, 3, 0.0, kHGRange, 0.0, 0.0, 75, FALSE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0f, 0.0f},
+ {AVH_WEAPON_KNIFE, kwsKnife, 3, 0.0, kKNRange, 0.0, 0.0, 50, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0f, 0.0f},
+
+ // Base alien abilities
+ {AVH_WEAPON_PRIMALSCREAM, kwsPrimalScream, 3, 0.0, 300, 0.0, 0.0, 20, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0f, 0.0f},
+ {AVH_WEAPON_SWIPE, kwsSwipe, 3, 0.0, kSwipeRange, 0.0, 0.0, 75, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0f, 0.0f},
+ {AVH_WEAPON_SPORES, kwsSporeGun, 3, 0.0, kSporeRange, 0.0, 0.0, 75, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0f, 0.0f},
+ {AVH_WEAPON_SPIT, kwsSpitGun, 3, 0.0, kSpitGRange, 0.0, 0.0, 75, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0f, 0.0f},
+ {AVH_WEAPON_CLAWS, kwsClaws, 3, 0.0, kClawsRange, 0.0, 0.0, 75, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0f, 0.0f},
+ {AVH_WEAPON_BITE, kwsBiteGun, 3, 0.0, 60, 0.0, 0.0, 75, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0f, 0.0f},
+ {AVH_ABILITY_LEAP, kwsLeap, 3, 0.0, 600, 0.0, 0.0, 50, FALSE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0f, 0.0f},
+ {AVH_WEAPON_SPIKE, kwsSpikeGun, 3, 0.0, kSpikeRange, 0.0, 0.0, 75, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0f, 0.0f},
+};
+
+// weapon firing delay based on skill (min and max delay for each weapon)
+// THESE MUST MATCH THE SAME ORDER AS THE WEAPON SELECT ARRAY!!!
+
+bot_fire_delay_t valve_fire_delay[] = {
+ {VALVE_WEAPON_CROWBAR,
+ 0.3, {0.0, 0.2, 0.3, 0.4, 0.6}, {0.1, 0.3, 0.5, 0.7, 1.0},
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
+ {VALVE_WEAPON_HANDGRENADE,
+ 0.1, {1.0, 2.0, 3.0, 4.0, 5.0}, {3.0, 4.0, 5.0, 6.0, 7.0},
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
+ {VALVE_WEAPON_SNARK,
+ 0.1, {0.0, 0.1, 0.2, 0.4, 0.6}, {0.1, 0.2, 0.5, 0.7, 1.0},
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
+ {VALVE_WEAPON_EGON,
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0},
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
+ {VALVE_WEAPON_GAUSS,
+ 0.2, {0.0, 0.2, 0.3, 0.5, 1.0}, {0.1, 0.3, 0.5, 0.8, 1.2},
+ 1.0, {0.2, 0.3, 0.5, 0.8, 1.2}, {0.5, 0.7, 1.0, 1.5, 2.0}},
+ {VALVE_WEAPON_SHOTGUN,
+ 0.75, {0.0, 0.2, 0.4, 0.6, 0.8}, {0.25, 0.5, 0.8, 1.2, 2.0},
+ 1.5, {0.0, 0.2, 0.4, 0.6, 0.8}, {0.25, 0.5, 0.8, 1.2, 2.0}},
+ {VALVE_WEAPON_PYTHON,
+ 0.75, {0.0, 0.2, 0.4, 1.0, 1.5}, {0.25, 0.5, 0.8, 1.3, 2.2},
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
+ {VALVE_WEAPON_HORNETGUN,
+ 0.25, {0.0, 0.25, 0.4, 0.6, 1.0}, {0.1, 0.4, 0.7, 1.0, 1.5},
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
+ {VALVE_WEAPON_MP5,
+ 0.1, {0.0, 0.1, 0.25, 0.4, 0.5}, {0.1, 0.3, 0.45, 0.65, 0.8},
+ 1.0, {0.0, 0.4, 0.7, 1.0, 1.4}, {0.3, 0.7, 1.0, 1.6, 2.0}},
+ {VALVE_WEAPON_CROSSBOW,
+ 0.75, {0.0, 0.2, 0.5, 0.8, 1.0}, {0.25, 0.4, 0.7, 1.0, 1.3},
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
+ {VALVE_WEAPON_RPG,
+ 1.5, {1.0, 2.0, 3.0, 4.0, 5.0}, {3.0, 4.0, 5.0, 6.0, 7.0},
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
+ {VALVE_WEAPON_GLOCK,
+ 0.3, {0.0, 0.1, 0.2, 0.3, 0.4}, {0.1, 0.2, 0.3, 0.4, 0.5},
+ 0.2, {0.0, 0.0, 0.1, 0.1, 0.2}, {0.1, 0.1, 0.2, 0.2, 0.4}},
+ /* terminator */
+ {0, 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0},
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}}
+};
+
+bot_fire_delay_t tfc_fire_delay[] = {
+ {TF_WEAPON_AXE,
+ 0.3, {0.0, 0.2, 0.3, 0.4, 0.6}, {0.1, 0.3, 0.5, 0.7, 1.0},
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
+ {TF_WEAPON_KNIFE,
+ 0.3, {0.0, 0.2, 0.3, 0.4, 0.6}, {0.1, 0.3, 0.5, 0.7, 1.0},
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
+ {TF_WEAPON_SPANNER,
+ 0.3, {0.0, 0.2, 0.3, 0.4, 0.6}, {0.1, 0.3, 0.5, 0.7, 1.0},
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
+ {TF_WEAPON_MEDIKIT,
+ 0.3, {0.0, 0.2, 0.3, 0.4, 0.6}, {0.1, 0.3, 0.5, 0.7, 1.0},
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
+ {TF_WEAPON_SNIPERRIFLE,
+ 1.0, {0.0, 0.4, 0.7, 1.0, 1.4}, {0.3, 0.7, 1.0, 1.6, 2.0},
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
+ {TF_WEAPON_FLAMETHROWER,
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0},
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
+ {TF_WEAPON_AC,
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0},
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
+ {TF_WEAPON_GL,
+ 0.6, {0.0, 0.2, 0.5, 0.8, 1.0}, {0.25, 0.4, 0.7, 1.0, 1.3},
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
+ {TF_WEAPON_RPG,
+ 0.5, {0.0, 0.1, 0.3, 0.6, 1.0}, {0.1, 0.2, 0.7, 1.0, 2.0},
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
+ {TF_WEAPON_IC,
+ 2.0, {1.0, 2.0, 3.0, 4.0, 5.0}, {3.0, 4.0, 5.0, 6.0, 7.0},
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
+ {TF_WEAPON_TRANQ,
+ 1.5, {1.0, 2.0, 3.0, 4.0, 5.0}, {3.0, 4.0, 5.0, 6.0, 7.0},
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
+ {TF_WEAPON_RAILGUN,
+ 0.4, {0.0, 0.1, 0.2, 0.3, 0.4}, {0.1, 0.2, 0.3, 0.4, 0.5},
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
+ {TF_WEAPON_SUPERNAILGUN,
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0},
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
+ {TF_WEAPON_SUPERSHOTGUN,
+ 0.6, {0.0, 0.2, 0.5, 0.8, 1.0}, {0.25, 0.4, 0.7, 1.0, 1.3},
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
+ {TF_WEAPON_AUTORIFLE,
+ 0.1, {0.0, 0.1, 0.2, 0.4, 0.6}, {0.1, 0.2, 0.5, 0.7, 1.0},
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
+ {TF_WEAPON_SHOTGUN,
+ 0.5, {0.0, 0.2, 0.4, 0.6, 0.8}, {0.25, 0.5, 0.8, 1.2, 2.0},
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
+ {TF_WEAPON_NAILGUN,
+ 0.1, {0.0, 0.1, 0.2, 0.4, 0.6}, {0.1, 0.2, 0.5, 0.7, 1.0},
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
+ /* terminator */
+ {0, 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0},
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}}
+};
+
+bot_fire_delay_t cs_fire_delay[] = {
+ {CS_WEAPON_KNIFE,
+ 0.3, {0.0, 0.2, 0.3, 0.4, 0.6}, {0.1, 0.3, 0.5, 0.7, 1.0},
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
+ {CS_WEAPON_USP,
+ 0.3, {0.0, 0.1, 0.2, 0.3, 0.4}, {0.1, 0.2, 0.3, 0.4, 0.5},
+ 0.2, {0.0, 0.0, 0.1, 0.1, 0.2}, {0.1, 0.1, 0.2, 0.2, 0.4}},
+ {CS_WEAPON_GLOCK18,
+ 0.3, {0.0, 0.1, 0.2, 0.3, 0.4}, {0.1, 0.2, 0.3, 0.4, 0.5},
+ 0.2, {0.0, 0.0, 0.1, 0.1, 0.2}, {0.1, 0.1, 0.2, 0.2, 0.4}},
+ /* terminator */
+ {0, 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0},
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}}
+};
+
+bot_fire_delay_t gearbox_fire_delay[] = {
+ {GEARBOX_WEAPON_PIPEWRENCH,
+ 0.5, {0.0, 0.2, 0.3, 0.4, 0.6}, {0.1, 0.3, 0.5, 0.7, 1.0},
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
+ {GEARBOX_WEAPON_KNIFE,
+ 0.4, {0.0, 0.2, 0.3, 0.4, 0.6}, {0.1, 0.3, 0.5, 0.7, 1.0},
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
+ {GEARBOX_WEAPON_CROWBAR,
+ 0.3, {0.0, 0.2, 0.3, 0.4, 0.6}, {0.1, 0.3, 0.5, 0.7, 1.0},
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
+ {GEARBOX_WEAPON_DISPLACER,
+ 5.0, {0.0, 0.5, 0.8, 1.6, 2.5}, {0.3, 0.8, 1.4, 2.2, 3.5},
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
+ {GEARBOX_WEAPON_SPORELAUNCHER,
+ 0.5, {0.0, 0.2, 0.3, 0.4, 0.6}, {0.1, 0.3, 0.5, 0.7, 1.0},
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
+ {GEARBOX_WEAPON_SHOCKRIFLE,
+ 0.1, {0.0, 0.1, 0.2, 0.3, 0.4}, {0.1, 0.2, 0.3, 0.4, 0.5},
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
+ {GEARBOX_WEAPON_SNIPERRIFLE,
+ 1.5, {0.0, 0.2, 0.4, 0.6, 0.8}, {0.25, 0.5, 0.8, 1.2, 2.0},
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
+ {GEARBOX_WEAPON_HANDGRENADE,
+ 0.1, {1.0, 2.0, 3.0, 4.0, 5.0}, {3.0, 4.0, 5.0, 6.0, 7.0},
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
+ {GEARBOX_WEAPON_SNARK,
+ 0.1, {0.0, 0.1, 0.2, 0.4, 0.6}, {0.1, 0.2, 0.5, 0.7, 1.0},
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
+ {GEARBOX_WEAPON_EGON,
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0},
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
+ {GEARBOX_WEAPON_GAUSS,
+ 0.2, {0.0, 0.2, 0.3, 0.5, 1.0}, {0.1, 0.3, 0.5, 0.8, 1.2},
+ 1.0, {0.2, 0.3, 0.5, 0.8, 1.2}, {0.5, 0.7, 1.0, 1.5, 2.0}},
+ {GEARBOX_WEAPON_M249,
+ 0.1, {0.0, 0.1, 0.25, 0.4, 0.5}, {0.1, 0.3, 0.45, 0.65, 0.8},
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
+ {GEARBOX_WEAPON_SHOTGUN,
+ 0.75, {0.0, 0.2, 0.4, 0.6, 0.8}, {0.25, 0.5, 0.8, 1.2, 2.0},
+ 1.5, {0.0, 0.2, 0.4, 0.6, 0.8}, {0.25, 0.5, 0.8, 1.2, 2.0}},
+ {GEARBOX_WEAPON_EAGLE,
+ 0.25, {0.0, 0.1, 0.2, 0.3, 0.5}, {0.1, 0.25, 0.4, 0.7, 1.0},
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
+ {GEARBOX_WEAPON_PYTHON,
+ 0.75, {0.0, 0.2, 0.4, 1.0, 1.5}, {0.25, 0.5, 0.8, 1.3, 2.2},
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
+ {GEARBOX_WEAPON_HORNETGUN,
+ 0.25, {0.0, 0.25, 0.4, 0.6, 1.0}, {0.1, 0.4, 0.7, 1.0, 1.5},
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
+ {GEARBOX_WEAPON_MP5,
+ 0.1, {0.0, 0.1, 0.25, 0.4, 0.5}, {0.1, 0.3, 0.45, 0.65, 0.8},
+ 1.0, {0.0, 0.4, 0.7, 1.0, 1.4}, {0.3, 0.7, 1.0, 1.6, 2.0}},
+ {GEARBOX_WEAPON_CROSSBOW,
+ 0.75, {0.0, 0.2, 0.5, 0.8, 1.0}, {0.25, 0.4, 0.7, 1.0, 1.3},
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
+ {GEARBOX_WEAPON_RPG,
+ 1.5, {1.0, 2.0, 3.0, 4.0, 5.0}, {3.0, 4.0, 5.0, 6.0, 7.0},
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
+ {GEARBOX_WEAPON_GLOCK,
+ 0.3, {0.0, 0.1, 0.2, 0.3, 0.4}, {0.1, 0.2, 0.3, 0.4, 0.5},
+ 0.2, {0.0, 0.0, 0.1, 0.1, 0.2}, {0.1, 0.1, 0.2, 0.2, 0.4}},
+ /* terminator */
+ {0, 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0},
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}}
+};
+
+bot_fire_delay_t frontline_fire_delay[] = {
+ {FLF_WEAPON_HEGRENADE,
+ 0.3, {0.0, 0.1, 0.2, 0.3, 0.4}, {0.1, 0.2, 0.3, 0.4, 0.5},
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
+ {FLF_WEAPON_FLASHBANG,
+ 0.3, {0.0, 0.1, 0.2, 0.3, 0.4}, {0.1, 0.2, 0.3, 0.4, 0.5},
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
+// {FLF_WEAPON_KNIFE,
+// 0.3, {0.0, 0.1, 0.2, 0.3, 0.4}, {0.1, 0.2, 0.3, 0.4, 0.5},
+// 0.2, {0.0, 0.0, 0.1, 0.1, 0.2}, {0.1, 0.1, 0.2, 0.2, 0.4}},
+ {FLF_WEAPON_HK21,
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0},
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
+ {FLF_WEAPON_UMP45,
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0},
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
+ {FLF_WEAPON_FAMAS,
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0},
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
+ {FLF_WEAPON_MSG90,
+ 1.2, {0.0, 0.1, 0.2, 0.3, 0.4}, {0.1, 0.2, 0.3, 0.4, 0.5},
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
+ {FLF_WEAPON_MP5A2,
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0},
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
+ {FLF_WEAPON_AK5,
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0},
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
+ {FLF_WEAPON_MP5SD,
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0},
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
+ {FLF_WEAPON_M4,
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0},
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
+ {FLF_WEAPON_SPAS12,
+ 0.9, {0.0, 0.1, 0.2, 0.3, 0.4}, {0.1, 0.2, 0.3, 0.4, 0.5},
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
+ {FLF_WEAPON_MAC10,
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0},
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
+ {FLF_WEAPON_BERETTA,
+ 0.4, {0.0, 0.1, 0.2, 0.3, 0.4}, {0.1, 0.2, 0.3, 0.4, 0.5},
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
+ {FLF_WEAPON_MK23,
+ 0.4, {0.0, 0.1, 0.2, 0.3, 0.4}, {0.1, 0.2, 0.3, 0.4, 0.5},
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
+ /* terminator */
+ {0, 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0},
+ 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}}
+};
+bot_fire_delay_t ns_fire_delay[] = {
+ {AVH_WEAPON_GRENADE_GUN, 0.3f, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.2, 0.3, 0.4, 0.5, 1.0}, 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
+ {AVH_WEAPON_SONIC, 0.0f, {0.0, 0.0, 0.0, 0.1, 0.3}, {0.0, 0.0, 0.0, 0.2, 0.6}, 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
+ {AVH_WEAPON_HMG, 0.0f, {0.0, 0.0, 0.0, 0.1, 0.3}, {0.0, 0.0, 0.0, 0.2, 0.6}, 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
+ {AVH_WEAPON_MG, 0.0f, {0.0, 0.0, 0.0, 0.1, 0.3}, {0.0, 0.0, 0.0, 0.2, 0.6}, 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
+ {AVH_WEAPON_PISTOL, 0.0f, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.1, 0.15, 0.2, 0.0, 0.0}, 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
+ {AVH_WEAPON_KNIFE, 0.0f, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}, 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
+
+ {AVH_WEAPON_PRIMALSCREAM, 0.0f, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}, 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
+ {AVH_WEAPON_SWIPE, 0.0f, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}, 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
+ {AVH_WEAPON_SPORES, 0.0f, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}, 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
+ {AVH_WEAPON_SPIT, 0.0f, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}, 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
+ {AVH_WEAPON_CLAWS, 0.0f, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.4, 0.5}, 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
+ {AVH_WEAPON_BITE, 0.0f, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}, 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
+ {AVH_ABILITY_LEAP, 0.0f, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}, 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
+ {AVH_WEAPON_SPIKE, 0.0f, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}, 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}}
+};
+
+void BotCheckTeamplay(void)
+{
+ // is this TFC or Counter-Strike or OpFor teamplay or FrontLineForce?
+ if ((mod_id == TFC_DLL) || (mod_id == CSTRIKE_DLL) ||
+ ((mod_id == GEARBOX_DLL) && (pent_info_ctfdetect != NULL)) ||
+ (mod_id == FRONTLINE_DLL) ||
+ (mod_id == AVH_DLL) )
+ is_team_play = 1.0;
+ else
+ is_team_play = CVAR_GET_FLOAT("mp_teamplay"); // teamplay enabled?
+
+ checked_teamplay = TRUE;
+}
+
+
+edict_t *BotFindEnemy( bot_t *pBot )
+{
+ Vector vecEnd;
+ static bool flag=TRUE;
+ edict_t *pent = NULL;
+ edict_t *pNewEnemy;
+ float nearestdistance;
+ int i;
+
+ edict_t *pEdict = pBot->pEdict;
+
+ if(pBot->mBotPlayMode != PLAYMODE_PLAYING)
+ {
+ pBot->pBotEnemy = NULL;
+ }
+
+ if (pBot->pBotEnemy != NULL) // does the bot already have an enemy?
+ {
+ vecEnd = pBot->pBotEnemy->v.origin + pBot->pBotEnemy->v.view_ofs;
+
+ // if the enemy is dead?
+ if (!IsAlive(pBot->pBotEnemy)) // is the enemy dead?, assume bot killed it
+ {
+ // the enemy is dead, jump for joy about 10% of the time
+ if (RANDOM_LONG(1, 100) <= 10)
+ pEdict->v.button |= IN_JUMP;
+
+ // Taunt sometimes after a kill
+ if(RANDOM_LONG(1, 5) == 1)
+ {
+ pBot->mTimeOfNextTaunt = gpGlobals->time + RANDOM_FLOAT(.3f, 4.0f);
+ }
+
+ // don't have an enemy anymore so null out the pointer...
+ pBot->pBotEnemy = NULL;
+ }
+ else if (FInViewCone( &vecEnd, pEdict ) &&
+ FVisible( vecEnd, pEdict ))
+ {
+ if ((mod_id == TFC_DLL) &&
+ (pEdict->v.playerclass == TFC_CLASS_MEDIC))
+ {
+ if (pBot->pBotEnemy->v.health >= pBot->pBotEnemy->v.max_health)
+ {
+ pBot->pBotEnemy = NULL; // player is healed, null out pointer
+ }
+ }
+ else
+ {
+ // if enemy is still visible and in field of view, keep it
+
+ // face the enemy
+ Vector v_enemy = pBot->pBotEnemy->v.origin - pEdict->v.origin;
+ Vector bot_angles = UTIL_VecToAngles( v_enemy );
+
+ pEdict->v.ideal_yaw = bot_angles.y;
+
+ BotFixIdealYaw(pEdict);
+
+ // keep track of when we last saw an enemy
+ pBot->f_bot_see_enemy_time = gpGlobals->time;
+
+ return (pBot->pBotEnemy);
+ }
+ }
+ }
+
+ pent = NULL;
+ pNewEnemy = NULL;
+ nearestdistance = 1000;
+
+ if (mod_id == TFC_DLL)
+ {
+ if (pEdict->v.playerclass == TFC_CLASS_MEDIC)
+ {
+ // search the world for players...
+ for (i = 1; i <= gpGlobals->maxClients; i++)
+ {
+ edict_t *pPlayer = INDEXENT(i);
+
+ // skip invalid players and skip self (i.e. this bot)
+ if ((pPlayer) && (!pPlayer->free) && (pPlayer != pEdict))
+ {
+ // skip this player if not alive (i.e. dead or dying)
+ if (!IsAlive(pPlayer))
+ continue;
+
+ if ((b_observer_mode) && !(pPlayer->v.flags & FL_FAKECLIENT))
+ continue;
+
+ int player_team = UTIL_GetTeam(pPlayer);
+ int bot_team = UTIL_GetTeam(pEdict);
+
+ // don't target your enemies...
+ if ((bot_team != player_team) &&
+ !(team_allies[bot_team] & (1<v.health / pPlayer->v.max_health) > 0.50)
+ continue; // health greater than 50% so ignore
+
+ vecEnd = pPlayer->v.origin + pPlayer->v.view_ofs;
+
+ // see if bot can see the player...
+ if (FInViewCone( &vecEnd, pEdict ) &&
+ FVisible( vecEnd, pEdict ))
+ {
+ float distance = (pPlayer->v.origin - pEdict->v.origin).Length();
+
+ if (distance < nearestdistance)
+ {
+ nearestdistance = distance;
+ pNewEnemy = pPlayer;
+
+ pBot->pBotUser = NULL; // don't follow user when enemy found
+ }
+ }
+ }
+ }
+ }
+
+ if (pNewEnemy == NULL)
+ {
+ while ((pent = UTIL_FindEntityByClassname( pent, "building_sentrygun" )) != NULL)
+ {
+ int sentry_team = -1;
+ int bot_team = UTIL_GetTeam(pEdict);
+
+ if (pent->v.colormap == 0xA096)
+ sentry_team = 0; // blue team's sentry
+ else if (pent->v.colormap == 0x04FA)
+ sentry_team = 1; // red team's sentry
+ else if (pent->v.colormap == 0x372D)
+ sentry_team = 2; // yellow team's sentry
+ else if (pent->v.colormap == 0x6E64)
+ sentry_team = 3; // green team's sentry
+
+ // don't target your own team's sentry guns...
+ if (bot_team == sentry_team)
+ continue;
+
+ // don't target your allie's sentry guns either...
+ if (team_allies[bot_team] & (1<v.origin + pent->v.view_ofs;
+
+ // is this sentry gun visible?
+ if (FInViewCone( &vecEnd, pEdict ) &&
+ FVisible( vecEnd, pEdict ))
+ {
+ float distance = (pent->v.origin - pEdict->v.origin).Length();
+
+ // is this the closest sentry gun?
+ if (distance < nearestdistance)
+ {
+ nearestdistance = distance;
+ pNewEnemy = pent;
+
+ pBot->pBotUser = NULL; // don't follow user when enemy found
+ }
+ }
+ }
+ }
+ }
+
+ if (pNewEnemy == NULL)
+ {
+ nearestdistance = 2500;
+
+ // search the world for players...(and enemies)
+ //for (i = 1; i <= gpGlobals->maxClients; i++)
+ for (i = 1; i <= gpGlobals->maxEntities; i++)
+ {
+ edict_t *pEntity = INDEXENT(i);
+
+ // skip invalid players and skip self (i.e. this bot)
+ if ((pEntity) && (!pEntity->free) && (pEntity != pEdict) && (FBitSet(pEntity->v.flags, FL_MONSTER) || FBitSet(pEntity->v.flags, FL_CLIENT)))
+ {
+ // Skip webs?
+ const char* theClassName = STRING(pEntity->v.classname);
+
+ // Skip cloaked players
+// if(pEntity->v.iuser4 & MASK_ALIEN_CLOAKED)
+// continue;
+
+ // skip this player if not alive (i.e. dead or dying)
+ if (!IsAlive(pEntity))
+ continue;
+
+ if ((b_observer_mode) && !(pEntity->v.flags & FL_FAKECLIENT))
+ continue;
+
+ if (!checked_teamplay) // check for team play...
+ BotCheckTeamplay();
+
+ // is team play enabled?
+ if (is_team_play > 0.0)
+ {
+ int player_team = UTIL_GetTeam(pEntity);
+ int bot_team = UTIL_GetTeam(pEdict);
+
+ // don't target your teammates...
+ if (bot_team == player_team)
+ continue;
+
+ if (mod_id == TFC_DLL)
+ {
+ // don't target your allies either...
+ if (team_allies[bot_team] & (1<v.origin + pEntity->v.view_ofs;
+
+ float theDistance = (pEdict->v.origin - pEntity->v.origin).Length();
+
+ // see if bot can see the player...
+ if ((FInViewCone( &vecEnd, pEdict ) &&
+ FVisible( vecEnd, pEdict )) || (theDistance < 32))
+ {
+ float distance = (pEntity->v.origin - pEdict->v.origin).Length();
+ if (distance < nearestdistance)
+ {
+ nearestdistance = distance;
+ pNewEnemy = pEntity;
+
+ pBot->pBotUser = NULL; // don't follow user when enemy found
+ }
+ }
+ }
+ }
+ }
+
+ if (pNewEnemy)
+ {
+ // face the enemy
+ Vector v_enemy = pNewEnemy->v.origin - pEdict->v.origin;
+ Vector bot_angles = UTIL_VecToAngles( v_enemy );
+
+ pEdict->v.ideal_yaw = bot_angles.y;
+
+ BotFixIdealYaw(pEdict);
+
+ // keep track of when we last saw an enemy
+ pBot->f_bot_see_enemy_time = gpGlobals->time;
+ }
+
+ // has the bot NOT seen an ememy for at least 5 seconds (time to reload)?
+ if ((pBot->f_bot_see_enemy_time > 0) &&
+ ((pBot->f_bot_see_enemy_time + 5.0) <= gpGlobals->time))
+ {
+ pBot->f_bot_see_enemy_time = -1; // so we won't keep reloading
+
+ if ((mod_id == VALVE_DLL) || (mod_id == GEARBOX_DLL) || (mod_id == AVH_DLL))
+ {
+ pEdict->v.button |= IN_RELOAD; // press reload button
+ }
+ }
+
+ return (pNewEnemy);
+}
+
+
+Vector BotBodyTarget( edict_t *pBotEnemy, bot_t *pBot )
+{
+ Vector target;
+ float f_distance;
+ float f_scale;
+ int d_x = 0;
+ int d_y = 0;
+ int d_z = 0;
+
+ edict_t *pEdict = pBot->pEdict;
+
+ f_distance = (pBotEnemy->v.origin - pEdict->v.origin).Length();
+
+ if (f_distance > 1000)
+ f_scale = 1.0;
+ else if (f_distance > 100)
+ f_scale = f_distance / 1000.0;
+ else
+ f_scale = 0.1;
+
+ switch (pBot->bot_skill)
+ {
+ case 0:
+ // VERY GOOD, same as from CBasePlayer::BodyTarget (in player.h)
+ target = pBotEnemy->v.origin + pBotEnemy->v.view_ofs * RANDOM_FLOAT( 0.5, 1.1 );
+ d_x = 0; // no offset
+ d_y = 0;
+ d_z = 0;
+ break;
+ case 1:
+ // GOOD, offset a little for x, y, and z
+ target = pBotEnemy->v.origin + pBotEnemy->v.view_ofs; // aim for the head (if you can find it)
+ d_x = RANDOM_FLOAT(-5, 5) * f_scale;
+ d_y = RANDOM_FLOAT(-5, 5) * f_scale;
+ d_z = RANDOM_FLOAT(-10, 10) * f_scale;
+ break;
+ case 2:
+ // FAIR, offset somewhat for x, y, and z
+ target = pBotEnemy->v.origin; // aim for the body
+ d_x = RANDOM_FLOAT(-10, 10) * f_scale;
+ d_y = RANDOM_FLOAT(-10, 10) * f_scale;
+ d_z = RANDOM_FLOAT(-18, 18) * f_scale;
+ break;
+ case 3:
+ // POOR, offset for x, y, and z
+ target = pBotEnemy->v.origin; // aim for the body
+ d_x = RANDOM_FLOAT(-20, 20) * f_scale;
+ d_y = RANDOM_FLOAT(-20, 20) * f_scale;
+ d_z = RANDOM_FLOAT(-32, 32) * f_scale;
+ break;
+ case 4:
+ // BAD, offset lots for x, y, and z
+ target = pBotEnemy->v.origin; // aim for the body
+ d_x = RANDOM_FLOAT(-35, 35) * f_scale;
+ d_y = RANDOM_FLOAT(-35, 35) * f_scale;
+ d_z = RANDOM_FLOAT(-50, 50) * f_scale;
+ break;
+ }
+
+ target = target + Vector(d_x, d_y, d_z);
+
+ return target;
+}
+
+
+// specifing a weapon_choice allows you to choose the weapon the bot will
+// use (assuming enough ammo exists for that weapon)
+// BotFireWeapon will return TRUE if weapon was fired, FALSE otherwise
+
+bool BotFireWeapon( Vector v_enemy, bot_t *pBot, int weapon_choice)
+{
+ bot_weapon_select_t *pSelect = NULL;
+ bot_fire_delay_t *pDelay = NULL;
+ int select_index;
+ int iId;
+ bool use_primary;
+ bool use_secondary;
+ int use_percent;
+ int primary_percent;
+
+ edict_t *pEdict = pBot->pEdict;
+
+ float distance = v_enemy.Length(); // how far away is the enemy?
+
+ if (mod_id == VALVE_DLL)
+ {
+ pSelect = &valve_weapon_select[0];
+ pDelay = &valve_fire_delay[0];
+ }
+ else if (mod_id == TFC_DLL)
+ {
+ pSelect = &tfc_weapon_select[0];
+ pDelay = &tfc_fire_delay[0];
+ }
+ else if (mod_id == CSTRIKE_DLL)
+ {
+ pSelect = &cs_weapon_select[0];
+ pDelay = &cs_fire_delay[0];
+ }
+ else if (mod_id == GEARBOX_DLL)
+ {
+ pSelect = &gearbox_weapon_select[0];
+ pDelay = &gearbox_fire_delay[0];
+ }
+ else if (mod_id == FRONTLINE_DLL)
+ {
+ pSelect = &frontline_weapon_select[0];
+ pDelay = &frontline_fire_delay[0];
+ }
+ else if (mod_id == AVH_DLL)
+ {
+ pSelect = &ns_weapon_select[0];
+ pDelay = &ns_fire_delay[0];
+ }
+
+ if (pSelect)
+ {
+ // are we charging the primary fire?
+ if (pBot->f_primary_charging > 0)
+ {
+ iId = pBot->charging_weapon_id;
+
+ if (mod_id == TFC_DLL)
+ {
+ if (iId == TF_WEAPON_SNIPERRIFLE)
+ {
+ pBot->f_move_speed = 0; // don't move while using sniper rifle
+ }
+ }
+
+ // is it time to fire the charged weapon?
+ if (pBot->f_primary_charging <= gpGlobals->time)
+ {
+ // we DON'T set pEdict->v.button here to release the
+ // fire button which will fire the charged weapon
+
+ pBot->f_primary_charging = -1; // -1 means not charging
+
+ // find the correct fire delay for this weapon
+ select_index = 0;
+
+ while ((pSelect[select_index].iId) &&
+ (pSelect[select_index].iId != iId))
+ select_index++;
+
+ // set next time to shoot
+ int skill = pBot->bot_skill;
+ float base_delay, min_delay, max_delay;
+
+ base_delay = pDelay[select_index].primary_base_delay;
+ min_delay = pDelay[select_index].primary_min_delay[skill];
+ max_delay = pDelay[select_index].primary_max_delay[skill];
+
+ pBot->f_shoot_time = gpGlobals->time + base_delay +
+ RANDOM_FLOAT(min_delay, max_delay);
+
+ return TRUE;
+ }
+ else
+ {
+ pEdict->v.button |= IN_ATTACK; // charge the weapon
+ pBot->f_shoot_time = gpGlobals->time; // keep charging
+
+ return TRUE;
+ }
+ }
+
+ // are we charging the secondary fire?
+ if (pBot->f_secondary_charging > 0)
+ {
+ iId = pBot->charging_weapon_id;
+
+ // is it time to fire the charged weapon?
+ if (pBot->f_secondary_charging <= gpGlobals->time)
+ {
+ // we DON'T set pEdict->v.button here to release the
+ // fire button which will fire the charged weapon
+
+ pBot->f_secondary_charging = -1; // -1 means not charging
+
+ // find the correct fire delay for this weapon
+ select_index = 0;
+
+ while ((pSelect[select_index].iId) &&
+ (pSelect[select_index].iId != iId))
+ select_index++;
+
+ // set next time to shoot
+ int skill = pBot->bot_skill;
+ float base_delay, min_delay, max_delay;
+
+ base_delay = pDelay[select_index].secondary_base_delay;
+ min_delay = pDelay[select_index].secondary_min_delay[skill];
+ max_delay = pDelay[select_index].secondary_max_delay[skill];
+
+ pBot->f_shoot_time = gpGlobals->time + base_delay +
+ RANDOM_FLOAT(min_delay, max_delay);
+
+ return TRUE;
+ }
+ else
+ {
+ pEdict->v.button |= IN_ATTACK2; // charge the weapon
+ pBot->f_shoot_time = gpGlobals->time; // keep charging
+
+ return TRUE;
+ }
+ }
+
+ select_index = 0;
+
+ // loop through all the weapons until terminator is found...
+ while (pSelect[select_index].iId)
+ {
+ // was a weapon choice specified? (and if so do they NOT match?)
+ if ((weapon_choice != 0) &&
+ (weapon_choice != pSelect[select_index].iId))
+ {
+ select_index++; // skip to next weapon
+ continue;
+ }
+
+ // is the bot NOT carrying this weapon?
+ if (!(pBot->bot_weapons & (1<bot_skill+1) > pSelect[select_index].skill_level)
+ {
+ select_index++; // skip to next weapon
+ continue;
+ }
+
+ // is the bot underwater and does this weapon NOT work under water?
+ if ((pEdict->v.waterlevel == 3) &&
+ !(pSelect[select_index].can_use_underwater))
+ {
+ select_index++; // skip to next weapon
+ continue;
+ }
+
+ use_percent = RANDOM_LONG(1, 100);
+
+ // is use percent greater than weapon use percent?
+ if (use_percent > pSelect[select_index].use_percent)
+ {
+ select_index++; // skip to next weapon
+ continue;
+ }
+
+ iId = pSelect[select_index].iId;
+ use_primary = FALSE;
+ use_secondary = FALSE;
+ primary_percent = RANDOM_LONG(1, 100);
+
+ // is primary percent less than weapon primary percent AND
+ // no ammo required for this weapon OR
+ // enough ammo available to fire AND
+ // the bot is far enough away to use primary fire AND
+ // the bot is close enough to the enemy to use primary fire
+
+ if ((primary_percent <= pSelect[select_index].primary_fire_percent) &&
+ ((weapon_defs[iId].iAmmo1 == -1) ||
+ (pBot->m_rgAmmo[weapon_defs[iId].iAmmo1] >=
+ pSelect[select_index].min_primary_ammo)) &&
+ (distance >= pSelect[select_index].primary_min_distance) &&
+ (distance <= pSelect[select_index].primary_max_distance))
+ {
+ use_primary = TRUE;
+ }
+
+ // otherwise see if there is enough secondary ammo AND
+ // the bot is far enough away to use secondary fire AND
+ // the bot is close enough to the enemy to use secondary fire
+
+ else if (((weapon_defs[iId].iAmmo2 == -1) ||
+ (pBot->m_rgAmmo[weapon_defs[iId].iAmmo2] >=
+ pSelect[select_index].min_secondary_ammo)) &&
+ (distance >= pSelect[select_index].secondary_min_distance) &&
+ (distance <= pSelect[select_index].secondary_max_distance))
+ {
+ use_secondary = TRUE;
+ }
+
+ // see if there wasn't enough ammo to fire the weapon...
+ if ((use_primary == FALSE) && (use_secondary == FALSE))
+ {
+ select_index++; // skip to next weapon
+ continue;
+ }
+
+ // select this weapon if it isn't already selected
+ if (pBot->current_weapon.iId != iId)
+ UTIL_SelectItem(pEdict, pSelect[select_index].weapon_name);
+
+ if (pDelay[select_index].iId != iId)
+ {
+ char msg[80];
+ sprintf(msg, "fire_delay mismatch for weapon id=%d\n",iId);
+ ALERT(at_console, msg);
+
+ return FALSE;
+ }
+
+ if (mod_id == TFC_DLL)
+ {
+ if (iId == TF_WEAPON_SNIPERRIFLE)
+ {
+ pBot->f_move_speed = 0; // don't move while using sniper rifle
+
+ if (pEdict->v.velocity.Length() > 50)
+ {
+ return FALSE; // don't press attack key until velocity is < 50
+ }
+ }
+
+ if (pEdict->v.playerclass == TFC_CLASS_MEDIC)
+ {
+ int player_team = UTIL_GetTeam(pBot->pBotEnemy);
+ int bot_team = UTIL_GetTeam(pEdict);
+
+ // only heal your teammates or allies...
+ if (((bot_team == player_team) ||
+ (team_allies[bot_team] & (1<v.button |= IN_ATTACK; // use primary attack
+
+ if (pSelect[select_index].primary_fire_charge)
+ {
+ pBot->charging_weapon_id = iId;
+
+ // release primary fire after the appropriate delay...
+ pBot->f_primary_charging = gpGlobals->time +
+ pSelect[select_index].primary_charge_delay;
+
+ pBot->f_shoot_time = gpGlobals->time; // keep charging
+ }
+ else
+ {
+ // set next time to shoot
+ if (pSelect[select_index].primary_fire_hold)
+ pBot->f_shoot_time = gpGlobals->time; // don't let button up
+ else
+ {
+ int skill = pBot->bot_skill;
+ float base_delay, min_delay, max_delay;
+
+ base_delay = pDelay[select_index].primary_base_delay;
+ min_delay = pDelay[select_index].primary_min_delay[skill];
+ max_delay = pDelay[select_index].primary_max_delay[skill];
+
+ pBot->f_shoot_time = gpGlobals->time + base_delay +
+ RANDOM_FLOAT(min_delay, max_delay);
+ }
+ }
+ }
+ else // MUST be use_secondary...
+ {
+ pEdict->v.button |= IN_ATTACK2; // use secondary attack
+
+ if (pSelect[select_index].secondary_fire_charge)
+ {
+ pBot->charging_weapon_id = iId;
+
+ // release secondary fire after the appropriate delay...
+ pBot->f_secondary_charging = gpGlobals->time +
+ pSelect[select_index].secondary_charge_delay;
+
+ pBot->f_shoot_time = gpGlobals->time; // keep charging
+ }
+ else
+ {
+ // set next time to shoot
+ if (pSelect[select_index].secondary_fire_hold)
+ pBot->f_shoot_time = gpGlobals->time; // don't let button up
+ else
+ {
+ int skill = pBot->bot_skill;
+ float base_delay, min_delay, max_delay;
+
+ base_delay = pDelay[select_index].secondary_base_delay;
+ min_delay = pDelay[select_index].secondary_min_delay[skill];
+ max_delay = pDelay[select_index].secondary_max_delay[skill];
+
+ pBot->f_shoot_time = gpGlobals->time + base_delay +
+ RANDOM_FLOAT(min_delay, max_delay);
+ }
+ }
+ }
+
+ return TRUE; // weapon was fired
+ }
+ }
+
+ // didn't have any available weapons or ammo, return FALSE
+ return FALSE;
+}
+
+
+void BotShootAtEnemy( bot_t *pBot )
+{
+ float f_distance;
+
+ edict_t *pEdict = pBot->pEdict;
+
+ // aim for the head and/or body
+ Vector v_enemy = BotBodyTarget( pBot->pBotEnemy, pBot ) - GetGunPosition(pEdict);
+
+ pEdict->v.v_angle = UTIL_VecToAngles( v_enemy );
+
+ if (pEdict->v.v_angle.y > 180)
+ pEdict->v.v_angle.y -=360;
+
+ // Paulo-La-Frite - START bot aiming bug fix
+ if (pEdict->v.v_angle.x > 180)
+ pEdict->v.v_angle.x -=360;
+
+ // set the body angles to point the gun correctly
+ pEdict->v.angles.x = pEdict->v.v_angle.x / 3;
+ pEdict->v.angles.y = pEdict->v.v_angle.y;
+ pEdict->v.angles.z = 0;
+
+ // adjust the view angle pitch to aim correctly (MUST be after body v.angles stuff)
+ pEdict->v.v_angle.x = -pEdict->v.v_angle.x;
+ // Paulo-La-Frite - END
+
+ float x = pEdict->v.v_angle.y;
+ if (x > 180) x -= 360;
+ if (abs(pEdict->v.ideal_yaw - x) > 2.0)
+ fp = NULL;
+
+ pEdict->v.ideal_yaw = pEdict->v.v_angle.y;
+
+ BotFixIdealYaw(pEdict);
+
+
+ v_enemy.z = 0; // ignore z component (up & down)
+
+ f_distance = v_enemy.Length(); // how far away is the enemy scum?
+
+ if (f_distance > 200) // run if distance to enemy is far
+ pBot->f_move_speed = pBot->f_max_speed;
+ else if (f_distance > 20) // walk if distance is closer
+ pBot->f_move_speed = pBot->f_max_speed / 2;
+ else // don't move if close enough
+ pBot->f_move_speed = 0.0;
+
+
+ // is it time to shoot yet?
+ if (pBot->f_shoot_time <= gpGlobals->time)
+ {
+ // select the best weapon to use at this distance and fire...
+ BotFireWeapon(v_enemy, pBot, 0);
+ }
+}
+
+
+bool BotShootTripmine( bot_t *pBot )
+{
+ edict_t *pEdict = pBot->pEdict;
+
+ if (pBot->b_shoot_tripmine != TRUE)
+ return FALSE;
+
+ // aim at the tripmine and fire the glock...
+
+ Vector v_enemy = pBot->v_tripmine - GetGunPosition( pEdict );
+
+ pEdict->v.v_angle = UTIL_VecToAngles( v_enemy );
+
+ if (pEdict->v.v_angle.y > 180)
+ pEdict->v.v_angle.y -=360;
+
+ // Paulo-La-Frite - START bot aiming bug fix
+ if (pEdict->v.v_angle.x > 180)
+ pEdict->v.v_angle.x -=360;
+
+ // set the body angles to point the gun correctly
+ pEdict->v.angles.x = pEdict->v.v_angle.x / 3;
+ pEdict->v.angles.y = pEdict->v.v_angle.y;
+ pEdict->v.angles.z = 0;
+
+ // adjust the view angle pitch to aim correctly (MUST be after body v.angles stuff)
+ pEdict->v.v_angle.x = -pEdict->v.v_angle.x;
+ // Paulo-La-Frite - END
+
+ pEdict->v.ideal_yaw = pEdict->v.v_angle.y;
+
+ BotFixIdealYaw(pEdict);
+
+ return (BotFireWeapon( v_enemy, pBot, VALVE_WEAPON_GLOCK ));
+}
+
diff --git a/main/source/HPB_bot/dlls/bot_func.h b/main/source/HPB_bot/dlls/bot_func.h
index c7427485..e03e1fb3 100644
--- a/main/source/HPB_bot/dlls/bot_func.h
+++ b/main/source/HPB_bot/dlls/bot_func.h
@@ -1,52 +1,52 @@
-//
-// HPB_bot - botman's High Ping Bastard bot
-//
-// (http://planethalflife.com/botman/)
-//
-// bot_func.h
-//
-
-#ifndef BOT_FUNC_H
-#define BOT_FUNC_H
-
-
-//prototypes of bot functions...
-
-void BotSpawnInit( bot_t *pBot );
-void BotCreate( edict_t *pPlayer, const char *arg1, const char *arg2,
- const char *arg3, const char *arg4 );
-void BotStartGame( bot_t *pBot );
-int BotInFieldOfView( bot_t *pBot, Vector dest );
-bool BotEntityIsVisible( bot_t *pBot, Vector dest );
-void BotFindItem( bot_t *pBot );
-void BotThink( bot_t *pBot );
-
-
-void BotFixIdealPitch( edict_t *pEdict );
-float BotChangePitch( bot_t *pBot, float speed );
-void BotFixIdealYaw( edict_t *pEdict );
-float BotChangeYaw( bot_t *pBot, float speed );
-bool BotFindWaypoint( bot_t *pBot );
-bool BotHeadTowardWaypoint( bot_t *pBot );
-void BotOnLadder( bot_t *pBot, float moved_distance );
-void BotUnderWater( bot_t *pBot );
-void BotUseLift( bot_t *pBot, float moved_distance );
-bool BotStuckInCorner( bot_t *pBot );
-void BotTurnAtWall( bot_t *pBot, TraceResult *tr );
-bool BotCantMoveForward( bot_t *pBot, TraceResult *tr );
-bool BotCanJumpUp( bot_t *pBot );
-bool BotCanDuckUnder( bot_t *pBot );
-void BotRandomTurn( bot_t *pBot );
-bool BotFollowUser( bot_t *pBot );
-bool BotCheckWallOnLeft( bot_t *pBot );
-bool BotCheckWallOnRight( bot_t *pBot );
-
-edict_t *BotFindEnemy( bot_t *pBot );
-Vector BotBodyTarget( edict_t *pBotEnemy, bot_t *pBot );
-bool BotFireWeapon( Vector v_enemy, bot_t *pBot, int weapon_choice);
-void BotShootAtEnemy( bot_t *pBot );
-bool BotShootTripmine( bot_t *pBot );
-
-
-#endif // BOT_FUNC_H
-
+//
+// HPB_bot - botman's High Ping Bastard bot
+//
+// (http://planethalflife.com/botman/)
+//
+// bot_func.h
+//
+
+#ifndef BOT_FUNC_H
+#define BOT_FUNC_H
+
+
+//prototypes of bot functions...
+
+void BotSpawnInit( bot_t *pBot );
+void BotCreate( edict_t *pPlayer, const char *arg1, const char *arg2,
+ const char *arg3, const char *arg4 );
+void BotStartGame( bot_t *pBot );
+int BotInFieldOfView( bot_t *pBot, Vector dest );
+bool BotEntityIsVisible( bot_t *pBot, Vector dest );
+void BotFindItem( bot_t *pBot );
+void BotThink( bot_t *pBot );
+
+
+void BotFixIdealPitch( edict_t *pEdict );
+float BotChangePitch( bot_t *pBot, float speed );
+void BotFixIdealYaw( edict_t *pEdict );
+float BotChangeYaw( bot_t *pBot, float speed );
+bool BotFindWaypoint( bot_t *pBot );
+bool BotHeadTowardWaypoint( bot_t *pBot );
+void BotOnLadder( bot_t *pBot, float moved_distance );
+void BotUnderWater( bot_t *pBot );
+void BotUseLift( bot_t *pBot, float moved_distance );
+bool BotStuckInCorner( bot_t *pBot );
+void BotTurnAtWall( bot_t *pBot, TraceResult *tr );
+bool BotCantMoveForward( bot_t *pBot, TraceResult *tr );
+bool BotCanJumpUp( bot_t *pBot );
+bool BotCanDuckUnder( bot_t *pBot );
+void BotRandomTurn( bot_t *pBot );
+bool BotFollowUser( bot_t *pBot );
+bool BotCheckWallOnLeft( bot_t *pBot );
+bool BotCheckWallOnRight( bot_t *pBot );
+
+edict_t *BotFindEnemy( bot_t *pBot );
+Vector BotBodyTarget( edict_t *pBotEnemy, bot_t *pBot );
+bool BotFireWeapon( Vector v_enemy, bot_t *pBot, int weapon_choice);
+void BotShootAtEnemy( bot_t *pBot );
+bool BotShootTripmine( bot_t *pBot );
+
+
+#endif // BOT_FUNC_H
+
diff --git a/main/source/HPB_bot/dlls/bot_navigate.cpp b/main/source/HPB_bot/dlls/bot_navigate.cpp
index 5af51f66..f2ed3d48 100644
--- a/main/source/HPB_bot/dlls/bot_navigate.cpp
+++ b/main/source/HPB_bot/dlls/bot_navigate.cpp
@@ -1,1094 +1,1094 @@
-//
-// HPB bot - botman's High Ping Bastard bot
-//
-// (http://planethalflife.com/botman/)
-//
-// bot_navigate.cpp
-//
-
-#include "dlls/extdll.h"
-#include "dlls/util.h"
-#include "dlls/cbase.h"
-
-#include "bot.h"
-#include "bot_func.h"
-#include "waypoint.h"
-
-
-extern int mod_id;
-extern WAYPOINT waypoints[MAX_WAYPOINTS];
-extern int num_waypoints; // number of waypoints currently in use
-extern int team_allies[4];
-extern edict_t *pent_info_ctfdetect;
-extern float is_team_play;
-extern bool checked_teamplay;
-extern FLAG_S flags[MAX_FLAGS];
-extern int num_flags;
-
-extern int flf_bug_fix;
-
-static FILE *fp;
-
-
-
-void BotFixIdealPitch(edict_t *pEdict)
-{
- // check for wrap around of angle...
- if (pEdict->v.idealpitch > 180)
- pEdict->v.idealpitch -= 360;
-
- if (pEdict->v.idealpitch < -180)
- pEdict->v.idealpitch += 360;
-}
-
-
-float BotChangePitch( bot_t *pBot, float speed )
-{
- edict_t *pEdict = pBot->pEdict;
- float ideal;
- float current;
- float current_180; // current +/- 180 degrees
- float diff;
-
- // turn from the current v_angle pitch to the idealpitch by selecting
- // the quickest way to turn to face that direction
-
- current = pEdict->v.v_angle.x;
-
- ideal = pEdict->v.idealpitch;
-
- // find the difference in the current and ideal angle
- diff = abs(current - ideal);
-
- // check if the bot is already facing the idealpitch direction...
- if (diff <= 1)
- return diff; // return number of degrees turned
-
- // check if difference is less than the max degrees per turn
- if (diff < speed)
- speed = diff; // just need to turn a little bit (less than max)
-
- // here we have four cases, both angle positive, one positive and
- // the other negative, one negative and the other positive, or
- // both negative. handle each case separately...
-
- if ((current >= 0) && (ideal >= 0)) // both positive
- {
- if (current > ideal)
- current -= speed;
- else
- current += speed;
- }
- else if ((current >= 0) && (ideal < 0))
- {
- current_180 = current - 180;
-
- if (current_180 > ideal)
- current += speed;
- else
- current -= speed;
- }
- else if ((current < 0) && (ideal >= 0))
- {
- current_180 = current + 180;
- if (current_180 > ideal)
- current += speed;
- else
- current -= speed;
- }
- else // (current < 0) && (ideal < 0) both negative
- {
- if (current > ideal)
- current -= speed;
- else
- current += speed;
- }
-
- // check for wrap around of angle...
- if (current > 180)
- current -= 360;
- if (current < -180)
- current += 360;
-
- pEdict->v.v_angle.x = current;
-
- return speed; // return number of degrees turned
-}
-
-
-void BotFixIdealYaw(edict_t *pEdict)
-{
- // check for wrap around of angle...
- if (pEdict->v.ideal_yaw > 180)
- pEdict->v.ideal_yaw -= 360;
-
- if (pEdict->v.ideal_yaw < -180)
- pEdict->v.ideal_yaw += 360;
-}
-
-
-float BotChangeYaw( bot_t *pBot, float speed )
-{
- edict_t *pEdict = pBot->pEdict;
- float ideal;
- float current;
- float current_180; // current +/- 180 degrees
- float diff;
-
- // turn from the current v_angle yaw to the ideal_yaw by selecting
- // the quickest way to turn to face that direction
-
- current = pEdict->v.v_angle.y;
-
- ideal = pEdict->v.ideal_yaw;
-
- // find the difference in the current and ideal angle
- diff = abs(current - ideal);
-
- // check if the bot is already facing the ideal_yaw direction...
- if (diff <= 1)
- return diff; // return number of degrees turned
-
- // check if difference is less than the max degrees per turn
- if (diff < speed)
- speed = diff; // just need to turn a little bit (less than max)
-
- // here we have four cases, both angle positive, one positive and
- // the other negative, one negative and the other positive, or
- // both negative. handle each case separately...
-
- if ((current >= 0) && (ideal >= 0)) // both positive
- {
- if (current > ideal)
- current -= speed;
- else
- current += speed;
- }
- else if ((current >= 0) && (ideal < 0))
- {
- current_180 = current - 180;
-
- if (current_180 > ideal)
- current += speed;
- else
- current -= speed;
- }
- else if ((current < 0) && (ideal >= 0))
- {
- current_180 = current + 180;
- if (current_180 > ideal)
- current += speed;
- else
- current -= speed;
- }
- else // (current < 0) && (ideal < 0) both negative
- {
- if (current > ideal)
- current -= speed;
- else
- current += speed;
- }
-
- // check for wrap around of angle...
- if (current > 180)
- current -= 360;
- if (current < -180)
- current += 360;
-
- pEdict->v.v_angle.y = current;
-
- return speed; // return number of degrees turned
-}
-
-
-bool BotFindWaypoint( bot_t *pBot )
-{
- // Do whatever you want here to find the next waypoint that the
- // bot should head towards
-
- return FALSE; // couldn't find a waypoint
-}
-
-
-bool BotHeadTowardWaypoint( bot_t *pBot )
-{
- // You could do other stuff here if you needed to.
-
- // This would probably be a good place to check to see how close to a
- // the current waypoint the bot is, and if the bot is close enough to
- // the desired waypoint then call BotFindWaypoint to find the next one.
-
- if (BotFindWaypoint(pBot))
- return TRUE;
- else
- return FALSE;
-}
-
-
-void BotOnLadder( bot_t *pBot, float moved_distance )
-{
- Vector v_src, v_dest, view_angles;
- TraceResult tr;
- float angle = 0.0;
- bool done = FALSE;
-
- edict_t *pEdict = pBot->pEdict;
-
- // check if the bot has JUST touched this ladder...
- if (pBot->ladder_dir == LADDER_UNKNOWN)
- {
- // try to square up the bot on the ladder...
- while ((!done) && (angle < 180.0))
- {
- // try looking in one direction (forward + angle)
- view_angles = pEdict->v.v_angle;
- view_angles.y = pEdict->v.v_angle.y + angle;
-
- if (view_angles.y < 0.0)
- view_angles.y += 360.0;
- if (view_angles.y > 360.0)
- view_angles.y -= 360.0;
-
- UTIL_MakeVectors( view_angles );
-
- v_src = pEdict->v.origin + pEdict->v.view_ofs;
- v_dest = v_src + gpGlobals->v_forward * 30;
-
- UTIL_TraceLine( v_src, v_dest, dont_ignore_monsters,
- pEdict->v.pContainingEntity, &tr);
-
- if (tr.flFraction < 1.0) // hit something?
- {
- if (strcmp("func_wall", STRING(tr.pHit->v.classname)) == 0)
- {
- // square up to the wall...
- view_angles = UTIL_VecToAngles(tr.vecPlaneNormal);
-
- // Normal comes OUT from wall, so flip it around...
- view_angles.y += 180;
-
- if (view_angles.y > 180)
- view_angles.y -= 360;
-
- pEdict->v.ideal_yaw = view_angles.y;
-
- BotFixIdealYaw(pEdict);
-
- done = TRUE;
- }
- }
- else
- {
- // try looking in the other direction (forward - angle)
- view_angles = pEdict->v.v_angle;
- view_angles.y = pEdict->v.v_angle.y - angle;
-
- if (view_angles.y < 0.0)
- view_angles.y += 360.0;
- if (view_angles.y > 360.0)
- view_angles.y -= 360.0;
-
- UTIL_MakeVectors( view_angles );
-
- v_src = pEdict->v.origin + pEdict->v.view_ofs;
- v_dest = v_src + gpGlobals->v_forward * 30;
-
- UTIL_TraceLine( v_src, v_dest, dont_ignore_monsters,
- pEdict->v.pContainingEntity, &tr);
-
- if (tr.flFraction < 1.0) // hit something?
- {
- if (strcmp("func_wall", STRING(tr.pHit->v.classname)) == 0)
- {
- // square up to the wall...
- view_angles = UTIL_VecToAngles(tr.vecPlaneNormal);
-
- // Normal comes OUT from wall, so flip it around...
- view_angles.y += 180;
-
- if (view_angles.y > 180)
- view_angles.y -= 360;
-
- pEdict->v.ideal_yaw = view_angles.y;
-
- BotFixIdealYaw(pEdict);
-
- done = TRUE;
- }
- }
- }
-
- angle += 10;
- }
-
- if (!done) // if didn't find a wall, just reset ideal_yaw...
- {
- // set ideal_yaw to current yaw (so bot won't keep turning)
- pEdict->v.ideal_yaw = pEdict->v.v_angle.y;
-
- BotFixIdealYaw(pEdict);
- }
- }
-
- // moves the bot up or down a ladder. if the bot can't move
- // (i.e. get's stuck with someone else on ladder), the bot will
- // change directions and go the other way on the ladder.
-
- if (pBot->ladder_dir == LADDER_UP) // is the bot currently going up?
- {
- pEdict->v.v_angle.x = -60; // look upwards
-
- // check if the bot hasn't moved much since the last location...
- if ((moved_distance <= 1) && (pBot->prev_speed >= 1.0))
- {
- // the bot must be stuck, change directions...
-
- pEdict->v.v_angle.x = 60; // look downwards
- pBot->ladder_dir = LADDER_DOWN;
- }
- }
- else if (pBot->ladder_dir == LADDER_DOWN) // is the bot currently going down?
- {
- pEdict->v.v_angle.x = 60; // look downwards
-
- // check if the bot hasn't moved much since the last location...
- if ((moved_distance <= 1) && (pBot->prev_speed >= 1.0))
- {
- // the bot must be stuck, change directions...
-
- pEdict->v.v_angle.x = -60; // look upwards
- pBot->ladder_dir = LADDER_UP;
- }
- }
- else // the bot hasn't picked a direction yet, try going up...
- {
- pEdict->v.v_angle.x = -60; // look upwards
- pBot->ladder_dir = LADDER_UP;
- }
-
- // move forward (i.e. in the direction the bot is looking, up or down)
- pEdict->v.button |= IN_FORWARD;
-}
-
-
-void BotUnderWater( bot_t *pBot )
-{
- bool found_waypoint = FALSE;
-
- edict_t *pEdict = pBot->pEdict;
-
- // are there waypoints in this level (and not trying to exit water)?
- if ((num_waypoints > 0) &&
- (pBot->f_exit_water_time < gpGlobals->time))
- {
- // head towards a waypoint
- found_waypoint = BotHeadTowardWaypoint(pBot);
- }
-
- if (found_waypoint == FALSE)
- {
- // handle movements under water. right now, just try to keep from
- // drowning by swimming up towards the surface and look to see if
- // there is a surface the bot can jump up onto to get out of the
- // water. bots DON'T like water!
-
- Vector v_src, v_forward;
- TraceResult tr;
- int contents;
-
- // swim up towards the surface
- pEdict->v.v_angle.x = -60; // look upwards
-
- // move forward (i.e. in the direction the bot is looking, up or down)
- pEdict->v.button |= IN_FORWARD;
-
- // set gpGlobals angles based on current view angle (for TraceLine)
- UTIL_MakeVectors( pEdict->v.v_angle );
-
- // look from eye position straight forward (remember: the bot is looking
- // upwards at a 60 degree angle so TraceLine will go out and up...
-
- v_src = pEdict->v.origin + pEdict->v.view_ofs; // EyePosition()
- v_forward = v_src + gpGlobals->v_forward * 90;
-
- // trace from the bot's eyes straight forward...
- UTIL_TraceLine( v_src, v_forward, dont_ignore_monsters,
- pEdict->v.pContainingEntity, &tr);
-
- // check if the trace didn't hit anything (i.e. nothing in the way)...
- if (tr.flFraction >= 1.0)
- {
- // find out what the contents is of the end of the trace...
- contents = UTIL_PointContents( tr.vecEndPos );
-
- // check if the trace endpoint is in open space...
- if (contents == CONTENTS_EMPTY)
- {
- // ok so far, we are at the surface of the water, continue...
-
- v_src = tr.vecEndPos;
- v_forward = v_src;
- v_forward.z -= 90;
-
- // trace from the previous end point straight down...
- UTIL_TraceLine( v_src, v_forward, dont_ignore_monsters,
- pEdict->v.pContainingEntity, &tr);
-
- // check if the trace hit something...
- if (tr.flFraction < 1.0)
- {
- contents = UTIL_PointContents( tr.vecEndPos );
-
- // if contents isn't water then assume it's land, jump!
- if (contents != CONTENTS_WATER)
- {
- pEdict->v.button |= IN_JUMP;
- }
- }
- }
- }
- }
-}
-
-
-void BotUseLift( bot_t *pBot, float moved_distance )
-{
- edict_t *pEdict = pBot->pEdict;
-
- // just need to press the button once, when the flag gets set...
- if (pBot->f_use_button_time == gpGlobals->time)
- {
- pEdict->v.button = IN_USE;
-
- // face opposite from the button
- pEdict->v.ideal_yaw += 180; // rotate 180 degrees
-
- BotFixIdealYaw(pEdict);
- }
-
- // check if the bot has waited too long for the lift to move...
- if (((pBot->f_use_button_time + 2.0) < gpGlobals->time) &&
- (!pBot->b_lift_moving))
- {
- // clear use button flag
- pBot->b_use_button = FALSE;
-
- // bot doesn't have to set f_find_item since the bot
- // should already be facing away from the button
-
- pBot->f_move_speed = pBot->f_max_speed;
- }
-
- // check if lift has started moving...
- if ((moved_distance > 1) && (!pBot->b_lift_moving))
- {
- pBot->b_lift_moving = TRUE;
- }
-
- // check if lift has stopped moving...
- if ((moved_distance <= 1) && (pBot->b_lift_moving))
- {
- TraceResult tr1, tr2;
- Vector v_src, v_forward, v_right, v_left;
- Vector v_down, v_forward_down, v_right_down, v_left_down;
-
- pBot->b_use_button = FALSE;
-
- // TraceLines in 4 directions to find which way to go...
-
- UTIL_MakeVectors( pEdict->v.v_angle );
-
- v_src = pEdict->v.origin + pEdict->v.view_ofs;
- v_forward = v_src + gpGlobals->v_forward * 90;
- v_right = v_src + gpGlobals->v_right * 90;
- v_left = v_src + gpGlobals->v_right * -90;
-
- v_down = pEdict->v.v_angle;
- v_down.x = v_down.x + 45; // look down at 45 degree angle
-
- UTIL_MakeVectors( v_down );
-
- v_forward_down = v_src + gpGlobals->v_forward * 100;
- v_right_down = v_src + gpGlobals->v_right * 100;
- v_left_down = v_src + gpGlobals->v_right * -100;
-
- // try tracing forward first...
- UTIL_TraceLine( v_src, v_forward, dont_ignore_monsters,
- pEdict->v.pContainingEntity, &tr1);
- UTIL_TraceLine( v_src, v_forward_down, dont_ignore_monsters,
- pEdict->v.pContainingEntity, &tr2);
-
- // check if we hit a wall or didn't find a floor...
- if ((tr1.flFraction < 1.0) || (tr2.flFraction >= 1.0))
- {
- // try tracing to the RIGHT side next...
- UTIL_TraceLine( v_src, v_right, dont_ignore_monsters,
- pEdict->v.pContainingEntity, &tr1);
- UTIL_TraceLine( v_src, v_right_down, dont_ignore_monsters,
- pEdict->v.pContainingEntity, &tr2);
-
- // check if we hit a wall or didn't find a floor...
- if ((tr1.flFraction < 1.0) || (tr2.flFraction >= 1.0))
- {
- // try tracing to the LEFT side next...
- UTIL_TraceLine( v_src, v_left, dont_ignore_monsters,
- pEdict->v.pContainingEntity, &tr1);
- UTIL_TraceLine( v_src, v_left_down, dont_ignore_monsters,
- pEdict->v.pContainingEntity, &tr2);
-
- // check if we hit a wall or didn't find a floor...
- if ((tr1.flFraction < 1.0) || (tr2.flFraction >= 1.0))
- {
- // only thing to do is turn around...
- pEdict->v.ideal_yaw += 180; // turn all the way around
- }
- else
- {
- pEdict->v.ideal_yaw += 90; // turn to the LEFT
- }
- }
- else
- {
- pEdict->v.ideal_yaw -= 90; // turn to the RIGHT
- }
-
- BotFixIdealYaw(pEdict);
- }
-
- BotChangeYaw( pBot, pEdict->v.yaw_speed );
-
- pBot->f_move_speed = pBot->f_max_speed;
- }
-}
-
-
-bool BotStuckInCorner( bot_t *pBot )
-{
- TraceResult tr;
- Vector v_src, v_dest;
- edict_t *pEdict = pBot->pEdict;
-
- UTIL_MakeVectors( pEdict->v.v_angle );
-
- // trace 45 degrees to the right...
- v_src = pEdict->v.origin;
- v_dest = v_src + gpGlobals->v_forward*20 + gpGlobals->v_right*20;
-
- UTIL_TraceLine( v_src, v_dest, dont_ignore_monsters,
- pEdict->v.pContainingEntity, &tr);
-
- if (tr.flFraction >= 1.0)
- return FALSE; // no wall, so not in a corner
-
- // trace 45 degrees to the left...
- v_src = pEdict->v.origin;
- v_dest = v_src + gpGlobals->v_forward*20 - gpGlobals->v_right*20;
-
- UTIL_TraceLine( v_src, v_dest, dont_ignore_monsters,
- pEdict->v.pContainingEntity, &tr);
-
- if (tr.flFraction >= 1.0)
- return FALSE; // no wall, so not in a corner
-
- return TRUE; // bot is in a corner
-}
-
-
-void BotTurnAtWall( bot_t *pBot, TraceResult *tr )
-{
- edict_t *pEdict = pBot->pEdict;
- Vector Normal;
- float Y, Y1, Y2, D1, D2, Z;
-
- // Find the normal vector from the trace result. The normal vector will
- // be a vector that is perpendicular to the surface from the TraceResult.
-
- Normal = UTIL_VecToAngles(tr->vecPlaneNormal);
-
- // Since the bot keeps it's view angle in -180 < x < 180 degrees format,
- // and since TraceResults are 0 < x < 360, we convert the bot's view
- // angle (yaw) to the same format at TraceResult.
-
- Y = pEdict->v.v_angle.y;
- Y = Y + 180;
- if (Y > 359) Y -= 360;
-
- // Turn the normal vector around 180 degrees (i.e. make it point towards
- // the wall not away from it. That makes finding the angles that the
- // bot needs to turn a little easier.
-
- Normal.y = Normal.y - 180;
- if (Normal.y < 0)
- Normal.y += 360;
-
- // Here we compare the bots view angle (Y) to the Normal - 90 degrees (Y1)
- // and the Normal + 90 degrees (Y2). These two angles (Y1 & Y2) represent
- // angles that are parallel to the wall surface, but heading in opposite
- // directions. We want the bot to choose the one that will require the
- // least amount of turning (saves time) and have the bot head off in that
- // direction.
-
- Y1 = Normal.y - 90;
- if (RANDOM_LONG(1, 100) <= 50)
- {
- Y1 = Y1 - RANDOM_FLOAT(5.0, 20.0);
- }
- if (Y1 < 0) Y1 += 360;
-
- Y2 = Normal.y + 90;
- if (RANDOM_LONG(1, 100) <= 50)
- {
- Y2 = Y2 + RANDOM_FLOAT(5.0, 20.0);
- }
- if (Y2 > 359) Y2 -= 360;
-
- // D1 and D2 are the difference (in degrees) between the bot's current
- // angle and Y1 or Y2 (respectively).
-
- D1 = abs(Y - Y1);
- if (D1 > 179) D1 = abs(D1 - 360);
- D2 = abs(Y - Y2);
- if (D2 > 179) D2 = abs(D2 - 360);
-
- // If difference 1 (D1) is more than difference 2 (D2) then the bot will
- // have to turn LESS if it heads in direction Y1 otherwise, head in
- // direction Y2. I know this seems backwards, but try some sample angles
- // out on some graph paper and go through these equations using a
- // calculator, you'll see what I mean.
-
- if (D1 > D2)
- Z = Y1;
- else
- Z = Y2;
-
- // convert from TraceResult 0 to 360 degree format back to bot's
- // -180 to 180 degree format.
-
- if (Z > 180)
- Z -= 360;
-
- // set the direction to head off into...
- pEdict->v.ideal_yaw = Z;
-
- BotFixIdealYaw(pEdict);
-}
-
-
-bool BotCantMoveForward( bot_t *pBot, TraceResult *tr )
-{
- edict_t *pEdict = pBot->pEdict;
-
- // use some TraceLines to determine if anything is blocking the current
- // path of the bot.
-
- Vector v_src, v_forward;
-
- UTIL_MakeVectors( pEdict->v.v_angle );
-
- // first do a trace from the bot's eyes forward...
-
- v_src = pEdict->v.origin + pEdict->v.view_ofs; // EyePosition()
- v_forward = v_src + gpGlobals->v_forward * 40;
-
- // trace from the bot's eyes straight forward...
- UTIL_TraceLine( v_src, v_forward, dont_ignore_monsters,
- pEdict->v.pContainingEntity, tr);
-
- // check if the trace hit something...
- if (tr->flFraction < 1.0)
- {
- return TRUE; // bot's head will hit something
- }
-
- // bot's head is clear, check at waist level...
-
- v_src = pEdict->v.origin;
- v_forward = v_src + gpGlobals->v_forward * 40;
-
- // trace from the bot's waist straight forward...
- UTIL_TraceLine( v_src, v_forward, dont_ignore_monsters,
- pEdict->v.pContainingEntity, tr);
-
- // check if the trace hit something...
- if (tr->flFraction < 1.0)
- {
- return TRUE; // bot's body will hit something
- }
-
- return FALSE; // bot can move forward, return false
-}
-
-
-bool BotCanJumpUp( bot_t *pBot )
-{
- // What I do here is trace 3 lines straight out, one unit higher than
- // the highest normal jumping distance. I trace once at the center of
- // the body, once at the right side, and once at the left side. If all
- // three of these TraceLines don't hit an obstruction then I know the
- // area to jump to is clear. I then need to trace from head level,
- // above where the bot will jump to, downward to see if there is anything
- // blocking the jump. There could be a narrow opening that the body
- // will not fit into. These horizontal and vertical TraceLines seem
- // to catch most of the problems with falsely trying to jump on something
- // that the bot can not get onto.
-
- // Make flier imitate flight
- if(pBot->pEdict->v.iuser3 == AVH_USER3_ALIEN_PLAYER3)
- {
- if(RANDOM_LONG(0, 2) == 0)
- {
- return TRUE;
- }
- }
-
- TraceResult tr;
- Vector v_jump, v_source, v_dest;
- edict_t *pEdict = pBot->pEdict;
-
- // convert current view angle to vectors for TraceLine math...
-
- v_jump = pEdict->v.v_angle;
- v_jump.x = 0; // reset pitch to 0 (level horizontally)
- v_jump.z = 0; // reset roll to 0 (straight up and down)
-
- UTIL_MakeVectors( v_jump );
-
- // use center of the body first...
-
- // maximum jump height is 45, so check one unit above that (46)
- v_source = pEdict->v.origin + Vector(0, 0, -36 + 46);
- v_dest = v_source + gpGlobals->v_forward * 24;
-
- // trace a line forward at maximum jump height...
- UTIL_TraceLine( v_source, v_dest, dont_ignore_monsters,
- pEdict->v.pContainingEntity, &tr);
-
- // if trace hit something, return FALSE
- if (tr.flFraction < 1.0)
- return FALSE;
-
- // now check same height to one side of the bot...
- v_source = pEdict->v.origin + gpGlobals->v_right * 16 + Vector(0, 0, -36 + 46);
- v_dest = v_source + gpGlobals->v_forward * 24;
-
- // trace a line forward at maximum jump height...
- UTIL_TraceLine( v_source, v_dest, dont_ignore_monsters,
- pEdict->v.pContainingEntity, &tr);
-
- // if trace hit something, return FALSE
- if (tr.flFraction < 1.0)
- return FALSE;
-
- // now check same height on the other side of the bot...
- v_source = pEdict->v.origin + gpGlobals->v_right * -16 + Vector(0, 0, -36 + 46);
- v_dest = v_source + gpGlobals->v_forward * 24;
-
- // trace a line forward at maximum jump height...
- UTIL_TraceLine( v_source, v_dest, dont_ignore_monsters,
- pEdict->v.pContainingEntity, &tr);
-
- // if trace hit something, return FALSE
- if (tr.flFraction < 1.0)
- return FALSE;
-
- // now trace from head level downward to check for obstructions...
-
- // start of trace is 24 units in front of bot, 72 units above head...
- v_source = pEdict->v.origin + gpGlobals->v_forward * 24;
-
- // offset 72 units from top of head (72 + 36)
- v_source.z = v_source.z + 108;
-
- // end point of trace is 99 units straight down from start...
- // (99 is 108 minus the jump limit height which is 45 - 36 = 9)
- v_dest = v_source + Vector(0, 0, -99);
-
- // trace a line straight down toward the ground...
- UTIL_TraceLine( v_source, v_dest, dont_ignore_monsters,
- pEdict->v.pContainingEntity, &tr);
-
- // if trace hit something, return FALSE
- if (tr.flFraction < 1.0)
- return FALSE;
-
- // now check same height to one side of the bot...
- v_source = pEdict->v.origin + gpGlobals->v_right * 16 + gpGlobals->v_forward * 24;
- v_source.z = v_source.z + 108;
- v_dest = v_source + Vector(0, 0, -99);
-
- // trace a line straight down toward the ground...
- UTIL_TraceLine( v_source, v_dest, dont_ignore_monsters,
- pEdict->v.pContainingEntity, &tr);
-
- // if trace hit something, return FALSE
- if (tr.flFraction < 1.0)
- return FALSE;
-
- // now check same height on the other side of the bot...
- v_source = pEdict->v.origin + gpGlobals->v_right * -16 + gpGlobals->v_forward * 24;
- v_source.z = v_source.z + 108;
- v_dest = v_source + Vector(0, 0, -99);
-
- // trace a line straight down toward the ground...
- UTIL_TraceLine( v_source, v_dest, dont_ignore_monsters,
- pEdict->v.pContainingEntity, &tr);
-
- // if trace hit something, return FALSE
- if (tr.flFraction < 1.0)
- return FALSE;
-
- return TRUE;
-}
-
-
-bool BotCanDuckUnder( bot_t *pBot )
-{
- // What I do here is trace 3 lines straight out, one unit higher than
- // the ducking height. I trace once at the center of the body, once
- // at the right side, and once at the left side. If all three of these
- // TraceLines don't hit an obstruction then I know the area to duck to
- // is clear. I then need to trace from the ground up, 72 units, to make
- // sure that there is something blocking the TraceLine. Then we know
- // we can duck under it.
-
- TraceResult tr;
- Vector v_duck, v_source, v_dest;
- edict_t *pEdict = pBot->pEdict;
-
- // convert current view angle to vectors for TraceLine math...
-
- v_duck = pEdict->v.v_angle;
- v_duck.x = 0; // reset pitch to 0 (level horizontally)
- v_duck.z = 0; // reset roll to 0 (straight up and down)
-
- UTIL_MakeVectors( v_duck );
-
- // use center of the body first...
-
- // duck height is 36, so check one unit above that (37)
- v_source = pEdict->v.origin + Vector(0, 0, -36 + 37);
- v_dest = v_source + gpGlobals->v_forward * 24;
-
- // trace a line forward at duck height...
- UTIL_TraceLine( v_source, v_dest, dont_ignore_monsters,
- pEdict->v.pContainingEntity, &tr);
-
- // if trace hit something, return FALSE
- if (tr.flFraction < 1.0)
- return FALSE;
-
- // now check same height to one side of the bot...
- v_source = pEdict->v.origin + gpGlobals->v_right * 16 + Vector(0, 0, -36 + 37);
- v_dest = v_source + gpGlobals->v_forward * 24;
-
- // trace a line forward at duck height...
- UTIL_TraceLine( v_source, v_dest, dont_ignore_monsters,
- pEdict->v.pContainingEntity, &tr);
-
- // if trace hit something, return FALSE
- if (tr.flFraction < 1.0)
- return FALSE;
-
- // now check same height on the other side of the bot...
- v_source = pEdict->v.origin + gpGlobals->v_right * -16 + Vector(0, 0, -36 + 37);
- v_dest = v_source + gpGlobals->v_forward * 24;
-
- // trace a line forward at duck height...
- UTIL_TraceLine( v_source, v_dest, dont_ignore_monsters,
- pEdict->v.pContainingEntity, &tr);
-
- // if trace hit something, return FALSE
- if (tr.flFraction < 1.0)
- return FALSE;
-
- // now trace from the ground up to check for object to duck under...
-
- // start of trace is 24 units in front of bot near ground...
- v_source = pEdict->v.origin + gpGlobals->v_forward * 24;
- v_source.z = v_source.z - 35; // offset to feet + 1 unit up
-
- // end point of trace is 72 units straight up from start...
- v_dest = v_source + Vector(0, 0, 72);
-
- // trace a line straight up in the air...
- UTIL_TraceLine( v_source, v_dest, dont_ignore_monsters,
- pEdict->v.pContainingEntity, &tr);
-
- // if trace didn't hit something, return FALSE
- if (tr.flFraction >= 1.0)
- return FALSE;
-
- // now check same height to one side of the bot...
- v_source = pEdict->v.origin + gpGlobals->v_right * 16 + gpGlobals->v_forward * 24;
- v_source.z = v_source.z - 35; // offset to feet + 1 unit up
- v_dest = v_source + Vector(0, 0, 72);
-
- // trace a line straight up in the air...
- UTIL_TraceLine( v_source, v_dest, dont_ignore_monsters,
- pEdict->v.pContainingEntity, &tr);
-
- // if trace didn't hit something, return FALSE
- if (tr.flFraction >= 1.0)
- return FALSE;
-
- // now check same height on the other side of the bot...
- v_source = pEdict->v.origin + gpGlobals->v_right * -16 + gpGlobals->v_forward * 24;
- v_source.z = v_source.z - 35; // offset to feet + 1 unit up
- v_dest = v_source + Vector(0, 0, 72);
-
- // trace a line straight up in the air...
- UTIL_TraceLine( v_source, v_dest, dont_ignore_monsters,
- pEdict->v.pContainingEntity, &tr);
-
- // if trace didn't hit something, return FALSE
- if (tr.flFraction >= 1.0)
- return FALSE;
-
- return TRUE;
-}
-
-
-void BotRandomTurn( bot_t *pBot )
-{
- pBot->f_move_speed = 0; // don't move while turning
-
- if (RANDOM_LONG(1, 100) <= 10)
- {
- // 10 percent of the time turn completely around...
- pBot->pEdict->v.ideal_yaw += 180;
- }
- else
- {
- // turn randomly between 30 and 60 degress
- if (pBot->wander_dir == WANDER_LEFT)
- pBot->pEdict->v.ideal_yaw += RANDOM_LONG(30, 60);
- else
- pBot->pEdict->v.ideal_yaw -= RANDOM_LONG(30, 60);
- }
-
- BotFixIdealYaw(pBot->pEdict);
-}
-
-
-bool BotFollowUser( bot_t *pBot )
-{
- bool user_visible;
- float f_distance;
- edict_t *pEdict = pBot->pEdict;
-
- Vector vecEnd = pBot->pBotUser->v.origin + pBot->pBotUser->v.view_ofs;
-
- if (pBot->pEdict->v.waterlevel != 3) // is bot NOT under water?
- pEdict->v.v_angle.x = 0; // reset pitch to 0 (level horizontally)
-
- pEdict->v.v_angle.z = 0; // reset roll to 0 (straight up and down)
-
- pEdict->v.angles.x = 0;
- pEdict->v.angles.y = pEdict->v.v_angle.y;
- pEdict->v.angles.z = 0;
-
- // Stop following when person crouches
- if (!IsAlive( pBot->pBotUser ) || (pBot->pBotUser->v.flags & FL_DUCKING))
- {
- // the bot's user is dead!
- pBot->pBotUser = NULL;
- return FALSE;
- }
-
- user_visible = FInViewCone( &vecEnd, pEdict ) &&
- FVisible( vecEnd, pEdict );
-
- // check if the "user" is still visible or if the user has been visible
- // in the last 5 seconds (or the player just starting "using" the bot)
-
- if (user_visible || (pBot->f_bot_use_time + 5 > gpGlobals->time))
- {
- if (user_visible)
- pBot->f_bot_use_time = gpGlobals->time; // reset "last visible time"
-
- // face the user
- Vector v_user = pBot->pBotUser->v.origin - pEdict->v.origin;
- Vector bot_angles = UTIL_VecToAngles( v_user );
-
- pEdict->v.ideal_yaw = bot_angles.y;
-
- BotFixIdealYaw(pEdict);
-
- f_distance = v_user.Length( ); // how far away is the "user"?
-
- if (f_distance > 200) // run if distance to enemy is far
- pBot->f_move_speed = pBot->f_max_speed;
- else if (f_distance > 50) // walk if distance is closer
- pBot->f_move_speed = pBot->f_max_speed / 2;
- else // don't move if close enough
- pBot->f_move_speed = 0.0;
-
- return TRUE;
- }
- else
- {
- // person to follow has gone out of sight...
- pBot->pBotUser = NULL;
-
- return FALSE;
- }
-}
-
-
-bool BotCheckWallOnLeft( bot_t *pBot )
-{
- edict_t *pEdict = pBot->pEdict;
- Vector v_src, v_left;
- TraceResult tr;
-
- UTIL_MakeVectors( pEdict->v.v_angle );
-
- // do a trace to the left...
-
- v_src = pEdict->v.origin;
- v_left = v_src + gpGlobals->v_right * -40; // 40 units to the left
-
- UTIL_TraceLine( v_src, v_left, dont_ignore_monsters,
- pEdict->v.pContainingEntity, &tr);
-
- // check if the trace hit something...
- if (tr.flFraction < 1.0)
- {
- if (pBot->f_wall_on_left < 1.0)
- pBot->f_wall_on_left = gpGlobals->time;
-
- return TRUE;
- }
-
- return FALSE;
-}
-
-
-bool BotCheckWallOnRight( bot_t *pBot )
-{
- edict_t *pEdict = pBot->pEdict;
- Vector v_src, v_right;
- TraceResult tr;
-
- UTIL_MakeVectors( pEdict->v.v_angle );
-
- // do a trace to the right...
-
- v_src = pEdict->v.origin;
- v_right = v_src + gpGlobals->v_right * 40; // 40 units to the right
-
- UTIL_TraceLine( v_src, v_right, dont_ignore_monsters,
- pEdict->v.pContainingEntity, &tr);
-
- // check if the trace hit something...
- if (tr.flFraction < 1.0)
- {
- if (pBot->f_wall_on_right < 1.0)
- pBot->f_wall_on_right = gpGlobals->time;
-
- return TRUE;
- }
-
- return FALSE;
-}
-
+//
+// HPB bot - botman's High Ping Bastard bot
+//
+// (http://planethalflife.com/botman/)
+//
+// bot_navigate.cpp
+//
+
+#include "dlls/extdll.h"
+#include "dlls/util.h"
+#include "dlls/cbase.h"
+
+#include "bot.h"
+#include "bot_func.h"
+#include "waypoint.h"
+
+
+extern int mod_id;
+extern WAYPOINT waypoints[MAX_WAYPOINTS];
+extern int num_waypoints; // number of waypoints currently in use
+extern int team_allies[4];
+extern edict_t *pent_info_ctfdetect;
+extern float is_team_play;
+extern bool checked_teamplay;
+extern FLAG_S flags[MAX_FLAGS];
+extern int num_flags;
+
+extern int flf_bug_fix;
+
+static FILE *fp;
+
+
+
+void BotFixIdealPitch(edict_t *pEdict)
+{
+ // check for wrap around of angle...
+ if (pEdict->v.idealpitch > 180)
+ pEdict->v.idealpitch -= 360;
+
+ if (pEdict->v.idealpitch < -180)
+ pEdict->v.idealpitch += 360;
+}
+
+
+float BotChangePitch( bot_t *pBot, float speed )
+{
+ edict_t *pEdict = pBot->pEdict;
+ float ideal;
+ float current;
+ float current_180; // current +/- 180 degrees
+ float diff;
+
+ // turn from the current v_angle pitch to the idealpitch by selecting
+ // the quickest way to turn to face that direction
+
+ current = pEdict->v.v_angle.x;
+
+ ideal = pEdict->v.idealpitch;
+
+ // find the difference in the current and ideal angle
+ diff = abs(current - ideal);
+
+ // check if the bot is already facing the idealpitch direction...
+ if (diff <= 1)
+ return diff; // return number of degrees turned
+
+ // check if difference is less than the max degrees per turn
+ if (diff < speed)
+ speed = diff; // just need to turn a little bit (less than max)
+
+ // here we have four cases, both angle positive, one positive and
+ // the other negative, one negative and the other positive, or
+ // both negative. handle each case separately...
+
+ if ((current >= 0) && (ideal >= 0)) // both positive
+ {
+ if (current > ideal)
+ current -= speed;
+ else
+ current += speed;
+ }
+ else if ((current >= 0) && (ideal < 0))
+ {
+ current_180 = current - 180;
+
+ if (current_180 > ideal)
+ current += speed;
+ else
+ current -= speed;
+ }
+ else if ((current < 0) && (ideal >= 0))
+ {
+ current_180 = current + 180;
+ if (current_180 > ideal)
+ current += speed;
+ else
+ current -= speed;
+ }
+ else // (current < 0) && (ideal < 0) both negative
+ {
+ if (current > ideal)
+ current -= speed;
+ else
+ current += speed;
+ }
+
+ // check for wrap around of angle...
+ if (current > 180)
+ current -= 360;
+ if (current < -180)
+ current += 360;
+
+ pEdict->v.v_angle.x = current;
+
+ return speed; // return number of degrees turned
+}
+
+
+void BotFixIdealYaw(edict_t *pEdict)
+{
+ // check for wrap around of angle...
+ if (pEdict->v.ideal_yaw > 180)
+ pEdict->v.ideal_yaw -= 360;
+
+ if (pEdict->v.ideal_yaw < -180)
+ pEdict->v.ideal_yaw += 360;
+}
+
+
+float BotChangeYaw( bot_t *pBot, float speed )
+{
+ edict_t *pEdict = pBot->pEdict;
+ float ideal;
+ float current;
+ float current_180; // current +/- 180 degrees
+ float diff;
+
+ // turn from the current v_angle yaw to the ideal_yaw by selecting
+ // the quickest way to turn to face that direction
+
+ current = pEdict->v.v_angle.y;
+
+ ideal = pEdict->v.ideal_yaw;
+
+ // find the difference in the current and ideal angle
+ diff = abs(current - ideal);
+
+ // check if the bot is already facing the ideal_yaw direction...
+ if (diff <= 1)
+ return diff; // return number of degrees turned
+
+ // check if difference is less than the max degrees per turn
+ if (diff < speed)
+ speed = diff; // just need to turn a little bit (less than max)
+
+ // here we have four cases, both angle positive, one positive and
+ // the other negative, one negative and the other positive, or
+ // both negative. handle each case separately...
+
+ if ((current >= 0) && (ideal >= 0)) // both positive
+ {
+ if (current > ideal)
+ current -= speed;
+ else
+ current += speed;
+ }
+ else if ((current >= 0) && (ideal < 0))
+ {
+ current_180 = current - 180;
+
+ if (current_180 > ideal)
+ current += speed;
+ else
+ current -= speed;
+ }
+ else if ((current < 0) && (ideal >= 0))
+ {
+ current_180 = current + 180;
+ if (current_180 > ideal)
+ current += speed;
+ else
+ current -= speed;
+ }
+ else // (current < 0) && (ideal < 0) both negative
+ {
+ if (current > ideal)
+ current -= speed;
+ else
+ current += speed;
+ }
+
+ // check for wrap around of angle...
+ if (current > 180)
+ current -= 360;
+ if (current < -180)
+ current += 360;
+
+ pEdict->v.v_angle.y = current;
+
+ return speed; // return number of degrees turned
+}
+
+
+bool BotFindWaypoint( bot_t *pBot )
+{
+ // Do whatever you want here to find the next waypoint that the
+ // bot should head towards
+
+ return FALSE; // couldn't find a waypoint
+}
+
+
+bool BotHeadTowardWaypoint( bot_t *pBot )
+{
+ // You could do other stuff here if you needed to.
+
+ // This would probably be a good place to check to see how close to a
+ // the current waypoint the bot is, and if the bot is close enough to
+ // the desired waypoint then call BotFindWaypoint to find the next one.
+
+ if (BotFindWaypoint(pBot))
+ return TRUE;
+ else
+ return FALSE;
+}
+
+
+void BotOnLadder( bot_t *pBot, float moved_distance )
+{
+ Vector v_src, v_dest, view_angles;
+ TraceResult tr;
+ float angle = 0.0;
+ bool done = FALSE;
+
+ edict_t *pEdict = pBot->pEdict;
+
+ // check if the bot has JUST touched this ladder...
+ if (pBot->ladder_dir == LADDER_UNKNOWN)
+ {
+ // try to square up the bot on the ladder...
+ while ((!done) && (angle < 180.0))
+ {
+ // try looking in one direction (forward + angle)
+ view_angles = pEdict->v.v_angle;
+ view_angles.y = pEdict->v.v_angle.y + angle;
+
+ if (view_angles.y < 0.0)
+ view_angles.y += 360.0;
+ if (view_angles.y > 360.0)
+ view_angles.y -= 360.0;
+
+ UTIL_MakeVectors( view_angles );
+
+ v_src = pEdict->v.origin + pEdict->v.view_ofs;
+ v_dest = v_src + gpGlobals->v_forward * 30;
+
+ UTIL_TraceLine( v_src, v_dest, dont_ignore_monsters,
+ pEdict->v.pContainingEntity, &tr);
+
+ if (tr.flFraction < 1.0) // hit something?
+ {
+ if (strcmp("func_wall", STRING(tr.pHit->v.classname)) == 0)
+ {
+ // square up to the wall...
+ view_angles = UTIL_VecToAngles(tr.vecPlaneNormal);
+
+ // Normal comes OUT from wall, so flip it around...
+ view_angles.y += 180;
+
+ if (view_angles.y > 180)
+ view_angles.y -= 360;
+
+ pEdict->v.ideal_yaw = view_angles.y;
+
+ BotFixIdealYaw(pEdict);
+
+ done = TRUE;
+ }
+ }
+ else
+ {
+ // try looking in the other direction (forward - angle)
+ view_angles = pEdict->v.v_angle;
+ view_angles.y = pEdict->v.v_angle.y - angle;
+
+ if (view_angles.y < 0.0)
+ view_angles.y += 360.0;
+ if (view_angles.y > 360.0)
+ view_angles.y -= 360.0;
+
+ UTIL_MakeVectors( view_angles );
+
+ v_src = pEdict->v.origin + pEdict->v.view_ofs;
+ v_dest = v_src + gpGlobals->v_forward * 30;
+
+ UTIL_TraceLine( v_src, v_dest, dont_ignore_monsters,
+ pEdict->v.pContainingEntity, &tr);
+
+ if (tr.flFraction < 1.0) // hit something?
+ {
+ if (strcmp("func_wall", STRING(tr.pHit->v.classname)) == 0)
+ {
+ // square up to the wall...
+ view_angles = UTIL_VecToAngles(tr.vecPlaneNormal);
+
+ // Normal comes OUT from wall, so flip it around...
+ view_angles.y += 180;
+
+ if (view_angles.y > 180)
+ view_angles.y -= 360;
+
+ pEdict->v.ideal_yaw = view_angles.y;
+
+ BotFixIdealYaw(pEdict);
+
+ done = TRUE;
+ }
+ }
+ }
+
+ angle += 10;
+ }
+
+ if (!done) // if didn't find a wall, just reset ideal_yaw...
+ {
+ // set ideal_yaw to current yaw (so bot won't keep turning)
+ pEdict->v.ideal_yaw = pEdict->v.v_angle.y;
+
+ BotFixIdealYaw(pEdict);
+ }
+ }
+
+ // moves the bot up or down a ladder. if the bot can't move
+ // (i.e. get's stuck with someone else on ladder), the bot will
+ // change directions and go the other way on the ladder.
+
+ if (pBot->ladder_dir == LADDER_UP) // is the bot currently going up?
+ {
+ pEdict->v.v_angle.x = -60; // look upwards
+
+ // check if the bot hasn't moved much since the last location...
+ if ((moved_distance <= 1) && (pBot->prev_speed >= 1.0))
+ {
+ // the bot must be stuck, change directions...
+
+ pEdict->v.v_angle.x = 60; // look downwards
+ pBot->ladder_dir = LADDER_DOWN;
+ }
+ }
+ else if (pBot->ladder_dir == LADDER_DOWN) // is the bot currently going down?
+ {
+ pEdict->v.v_angle.x = 60; // look downwards
+
+ // check if the bot hasn't moved much since the last location...
+ if ((moved_distance <= 1) && (pBot->prev_speed >= 1.0))
+ {
+ // the bot must be stuck, change directions...
+
+ pEdict->v.v_angle.x = -60; // look upwards
+ pBot->ladder_dir = LADDER_UP;
+ }
+ }
+ else // the bot hasn't picked a direction yet, try going up...
+ {
+ pEdict->v.v_angle.x = -60; // look upwards
+ pBot->ladder_dir = LADDER_UP;
+ }
+
+ // move forward (i.e. in the direction the bot is looking, up or down)
+ pEdict->v.button |= IN_FORWARD;
+}
+
+
+void BotUnderWater( bot_t *pBot )
+{
+ bool found_waypoint = FALSE;
+
+ edict_t *pEdict = pBot->pEdict;
+
+ // are there waypoints in this level (and not trying to exit water)?
+ if ((num_waypoints > 0) &&
+ (pBot->f_exit_water_time < gpGlobals->time))
+ {
+ // head towards a waypoint
+ found_waypoint = BotHeadTowardWaypoint(pBot);
+ }
+
+ if (found_waypoint == FALSE)
+ {
+ // handle movements under water. right now, just try to keep from
+ // drowning by swimming up towards the surface and look to see if
+ // there is a surface the bot can jump up onto to get out of the
+ // water. bots DON'T like water!
+
+ Vector v_src, v_forward;
+ TraceResult tr;
+ int contents;
+
+ // swim up towards the surface
+ pEdict->v.v_angle.x = -60; // look upwards
+
+ // move forward (i.e. in the direction the bot is looking, up or down)
+ pEdict->v.button |= IN_FORWARD;
+
+ // set gpGlobals angles based on current view angle (for TraceLine)
+ UTIL_MakeVectors( pEdict->v.v_angle );
+
+ // look from eye position straight forward (remember: the bot is looking
+ // upwards at a 60 degree angle so TraceLine will go out and up...
+
+ v_src = pEdict->v.origin + pEdict->v.view_ofs; // EyePosition()
+ v_forward = v_src + gpGlobals->v_forward * 90;
+
+ // trace from the bot's eyes straight forward...
+ UTIL_TraceLine( v_src, v_forward, dont_ignore_monsters,
+ pEdict->v.pContainingEntity, &tr);
+
+ // check if the trace didn't hit anything (i.e. nothing in the way)...
+ if (tr.flFraction >= 1.0)
+ {
+ // find out what the contents is of the end of the trace...
+ contents = UTIL_PointContents( tr.vecEndPos );
+
+ // check if the trace endpoint is in open space...
+ if (contents == CONTENTS_EMPTY)
+ {
+ // ok so far, we are at the surface of the water, continue...
+
+ v_src = tr.vecEndPos;
+ v_forward = v_src;
+ v_forward.z -= 90;
+
+ // trace from the previous end point straight down...
+ UTIL_TraceLine( v_src, v_forward, dont_ignore_monsters,
+ pEdict->v.pContainingEntity, &tr);
+
+ // check if the trace hit something...
+ if (tr.flFraction < 1.0)
+ {
+ contents = UTIL_PointContents( tr.vecEndPos );
+
+ // if contents isn't water then assume it's land, jump!
+ if (contents != CONTENTS_WATER)
+ {
+ pEdict->v.button |= IN_JUMP;
+ }
+ }
+ }
+ }
+ }
+}
+
+
+void BotUseLift( bot_t *pBot, float moved_distance )
+{
+ edict_t *pEdict = pBot->pEdict;
+
+ // just need to press the button once, when the flag gets set...
+ if (pBot->f_use_button_time == gpGlobals->time)
+ {
+ pEdict->v.button = IN_USE;
+
+ // face opposite from the button
+ pEdict->v.ideal_yaw += 180; // rotate 180 degrees
+
+ BotFixIdealYaw(pEdict);
+ }
+
+ // check if the bot has waited too long for the lift to move...
+ if (((pBot->f_use_button_time + 2.0) < gpGlobals->time) &&
+ (!pBot->b_lift_moving))
+ {
+ // clear use button flag
+ pBot->b_use_button = FALSE;
+
+ // bot doesn't have to set f_find_item since the bot
+ // should already be facing away from the button
+
+ pBot->f_move_speed = pBot->f_max_speed;
+ }
+
+ // check if lift has started moving...
+ if ((moved_distance > 1) && (!pBot->b_lift_moving))
+ {
+ pBot->b_lift_moving = TRUE;
+ }
+
+ // check if lift has stopped moving...
+ if ((moved_distance <= 1) && (pBot->b_lift_moving))
+ {
+ TraceResult tr1, tr2;
+ Vector v_src, v_forward, v_right, v_left;
+ Vector v_down, v_forward_down, v_right_down, v_left_down;
+
+ pBot->b_use_button = FALSE;
+
+ // TraceLines in 4 directions to find which way to go...
+
+ UTIL_MakeVectors( pEdict->v.v_angle );
+
+ v_src = pEdict->v.origin + pEdict->v.view_ofs;
+ v_forward = v_src + gpGlobals->v_forward * 90;
+ v_right = v_src + gpGlobals->v_right * 90;
+ v_left = v_src + gpGlobals->v_right * -90;
+
+ v_down = pEdict->v.v_angle;
+ v_down.x = v_down.x + 45; // look down at 45 degree angle
+
+ UTIL_MakeVectors( v_down );
+
+ v_forward_down = v_src + gpGlobals->v_forward * 100;
+ v_right_down = v_src + gpGlobals->v_right * 100;
+ v_left_down = v_src + gpGlobals->v_right * -100;
+
+ // try tracing forward first...
+ UTIL_TraceLine( v_src, v_forward, dont_ignore_monsters,
+ pEdict->v.pContainingEntity, &tr1);
+ UTIL_TraceLine( v_src, v_forward_down, dont_ignore_monsters,
+ pEdict->v.pContainingEntity, &tr2);
+
+ // check if we hit a wall or didn't find a floor...
+ if ((tr1.flFraction < 1.0) || (tr2.flFraction >= 1.0))
+ {
+ // try tracing to the RIGHT side next...
+ UTIL_TraceLine( v_src, v_right, dont_ignore_monsters,
+ pEdict->v.pContainingEntity, &tr1);
+ UTIL_TraceLine( v_src, v_right_down, dont_ignore_monsters,
+ pEdict->v.pContainingEntity, &tr2);
+
+ // check if we hit a wall or didn't find a floor...
+ if ((tr1.flFraction < 1.0) || (tr2.flFraction >= 1.0))
+ {
+ // try tracing to the LEFT side next...
+ UTIL_TraceLine( v_src, v_left, dont_ignore_monsters,
+ pEdict->v.pContainingEntity, &tr1);
+ UTIL_TraceLine( v_src, v_left_down, dont_ignore_monsters,
+ pEdict->v.pContainingEntity, &tr2);
+
+ // check if we hit a wall or didn't find a floor...
+ if ((tr1.flFraction < 1.0) || (tr2.flFraction >= 1.0))
+ {
+ // only thing to do is turn around...
+ pEdict->v.ideal_yaw += 180; // turn all the way around
+ }
+ else
+ {
+ pEdict->v.ideal_yaw += 90; // turn to the LEFT
+ }
+ }
+ else
+ {
+ pEdict->v.ideal_yaw -= 90; // turn to the RIGHT
+ }
+
+ BotFixIdealYaw(pEdict);
+ }
+
+ BotChangeYaw( pBot, pEdict->v.yaw_speed );
+
+ pBot->f_move_speed = pBot->f_max_speed;
+ }
+}
+
+
+bool BotStuckInCorner( bot_t *pBot )
+{
+ TraceResult tr;
+ Vector v_src, v_dest;
+ edict_t *pEdict = pBot->pEdict;
+
+ UTIL_MakeVectors( pEdict->v.v_angle );
+
+ // trace 45 degrees to the right...
+ v_src = pEdict->v.origin;
+ v_dest = v_src + gpGlobals->v_forward*20 + gpGlobals->v_right*20;
+
+ UTIL_TraceLine( v_src, v_dest, dont_ignore_monsters,
+ pEdict->v.pContainingEntity, &tr);
+
+ if (tr.flFraction >= 1.0)
+ return FALSE; // no wall, so not in a corner
+
+ // trace 45 degrees to the left...
+ v_src = pEdict->v.origin;
+ v_dest = v_src + gpGlobals->v_forward*20 - gpGlobals->v_right*20;
+
+ UTIL_TraceLine( v_src, v_dest, dont_ignore_monsters,
+ pEdict->v.pContainingEntity, &tr);
+
+ if (tr.flFraction >= 1.0)
+ return FALSE; // no wall, so not in a corner
+
+ return TRUE; // bot is in a corner
+}
+
+
+void BotTurnAtWall( bot_t *pBot, TraceResult *tr )
+{
+ edict_t *pEdict = pBot->pEdict;
+ Vector Normal;
+ float Y, Y1, Y2, D1, D2, Z;
+
+ // Find the normal vector from the trace result. The normal vector will
+ // be a vector that is perpendicular to the surface from the TraceResult.
+
+ Normal = UTIL_VecToAngles(tr->vecPlaneNormal);
+
+ // Since the bot keeps it's view angle in -180 < x < 180 degrees format,
+ // and since TraceResults are 0 < x < 360, we convert the bot's view
+ // angle (yaw) to the same format at TraceResult.
+
+ Y = pEdict->v.v_angle.y;
+ Y = Y + 180;
+ if (Y > 359) Y -= 360;
+
+ // Turn the normal vector around 180 degrees (i.e. make it point towards
+ // the wall not away from it. That makes finding the angles that the
+ // bot needs to turn a little easier.
+
+ Normal.y = Normal.y - 180;
+ if (Normal.y < 0)
+ Normal.y += 360;
+
+ // Here we compare the bots view angle (Y) to the Normal - 90 degrees (Y1)
+ // and the Normal + 90 degrees (Y2). These two angles (Y1 & Y2) represent
+ // angles that are parallel to the wall surface, but heading in opposite
+ // directions. We want the bot to choose the one that will require the
+ // least amount of turning (saves time) and have the bot head off in that
+ // direction.
+
+ Y1 = Normal.y - 90;
+ if (RANDOM_LONG(1, 100) <= 50)
+ {
+ Y1 = Y1 - RANDOM_FLOAT(5.0, 20.0);
+ }
+ if (Y1 < 0) Y1 += 360;
+
+ Y2 = Normal.y + 90;
+ if (RANDOM_LONG(1, 100) <= 50)
+ {
+ Y2 = Y2 + RANDOM_FLOAT(5.0, 20.0);
+ }
+ if (Y2 > 359) Y2 -= 360;
+
+ // D1 and D2 are the difference (in degrees) between the bot's current
+ // angle and Y1 or Y2 (respectively).
+
+ D1 = abs(Y - Y1);
+ if (D1 > 179) D1 = abs(D1 - 360);
+ D2 = abs(Y - Y2);
+ if (D2 > 179) D2 = abs(D2 - 360);
+
+ // If difference 1 (D1) is more than difference 2 (D2) then the bot will
+ // have to turn LESS if it heads in direction Y1 otherwise, head in
+ // direction Y2. I know this seems backwards, but try some sample angles
+ // out on some graph paper and go through these equations using a
+ // calculator, you'll see what I mean.
+
+ if (D1 > D2)
+ Z = Y1;
+ else
+ Z = Y2;
+
+ // convert from TraceResult 0 to 360 degree format back to bot's
+ // -180 to 180 degree format.
+
+ if (Z > 180)
+ Z -= 360;
+
+ // set the direction to head off into...
+ pEdict->v.ideal_yaw = Z;
+
+ BotFixIdealYaw(pEdict);
+}
+
+
+bool BotCantMoveForward( bot_t *pBot, TraceResult *tr )
+{
+ edict_t *pEdict = pBot->pEdict;
+
+ // use some TraceLines to determine if anything is blocking the current
+ // path of the bot.
+
+ Vector v_src, v_forward;
+
+ UTIL_MakeVectors( pEdict->v.v_angle );
+
+ // first do a trace from the bot's eyes forward...
+
+ v_src = pEdict->v.origin + pEdict->v.view_ofs; // EyePosition()
+ v_forward = v_src + gpGlobals->v_forward * 40;
+
+ // trace from the bot's eyes straight forward...
+ UTIL_TraceLine( v_src, v_forward, dont_ignore_monsters,
+ pEdict->v.pContainingEntity, tr);
+
+ // check if the trace hit something...
+ if (tr->flFraction < 1.0)
+ {
+ return TRUE; // bot's head will hit something
+ }
+
+ // bot's head is clear, check at waist level...
+
+ v_src = pEdict->v.origin;
+ v_forward = v_src + gpGlobals->v_forward * 40;
+
+ // trace from the bot's waist straight forward...
+ UTIL_TraceLine( v_src, v_forward, dont_ignore_monsters,
+ pEdict->v.pContainingEntity, tr);
+
+ // check if the trace hit something...
+ if (tr->flFraction < 1.0)
+ {
+ return TRUE; // bot's body will hit something
+ }
+
+ return FALSE; // bot can move forward, return false
+}
+
+
+bool BotCanJumpUp( bot_t *pBot )
+{
+ // What I do here is trace 3 lines straight out, one unit higher than
+ // the highest normal jumping distance. I trace once at the center of
+ // the body, once at the right side, and once at the left side. If all
+ // three of these TraceLines don't hit an obstruction then I know the
+ // area to jump to is clear. I then need to trace from head level,
+ // above where the bot will jump to, downward to see if there is anything
+ // blocking the jump. There could be a narrow opening that the body
+ // will not fit into. These horizontal and vertical TraceLines seem
+ // to catch most of the problems with falsely trying to jump on something
+ // that the bot can not get onto.
+
+ // Make flier imitate flight
+ if(pBot->pEdict->v.iuser3 == AVH_USER3_ALIEN_PLAYER3)
+ {
+ if(RANDOM_LONG(0, 2) == 0)
+ {
+ return TRUE;
+ }
+ }
+
+ TraceResult tr;
+ Vector v_jump, v_source, v_dest;
+ edict_t *pEdict = pBot->pEdict;
+
+ // convert current view angle to vectors for TraceLine math...
+
+ v_jump = pEdict->v.v_angle;
+ v_jump.x = 0; // reset pitch to 0 (level horizontally)
+ v_jump.z = 0; // reset roll to 0 (straight up and down)
+
+ UTIL_MakeVectors( v_jump );
+
+ // use center of the body first...
+
+ // maximum jump height is 45, so check one unit above that (46)
+ v_source = pEdict->v.origin + Vector(0, 0, -36 + 46);
+ v_dest = v_source + gpGlobals->v_forward * 24;
+
+ // trace a line forward at maximum jump height...
+ UTIL_TraceLine( v_source, v_dest, dont_ignore_monsters,
+ pEdict->v.pContainingEntity, &tr);
+
+ // if trace hit something, return FALSE
+ if (tr.flFraction < 1.0)
+ return FALSE;
+
+ // now check same height to one side of the bot...
+ v_source = pEdict->v.origin + gpGlobals->v_right * 16 + Vector(0, 0, -36 + 46);
+ v_dest = v_source + gpGlobals->v_forward * 24;
+
+ // trace a line forward at maximum jump height...
+ UTIL_TraceLine( v_source, v_dest, dont_ignore_monsters,
+ pEdict->v.pContainingEntity, &tr);
+
+ // if trace hit something, return FALSE
+ if (tr.flFraction < 1.0)
+ return FALSE;
+
+ // now check same height on the other side of the bot...
+ v_source = pEdict->v.origin + gpGlobals->v_right * -16 + Vector(0, 0, -36 + 46);
+ v_dest = v_source + gpGlobals->v_forward * 24;
+
+ // trace a line forward at maximum jump height...
+ UTIL_TraceLine( v_source, v_dest, dont_ignore_monsters,
+ pEdict->v.pContainingEntity, &tr);
+
+ // if trace hit something, return FALSE
+ if (tr.flFraction < 1.0)
+ return FALSE;
+
+ // now trace from head level downward to check for obstructions...
+
+ // start of trace is 24 units in front of bot, 72 units above head...
+ v_source = pEdict->v.origin + gpGlobals->v_forward * 24;
+
+ // offset 72 units from top of head (72 + 36)
+ v_source.z = v_source.z + 108;
+
+ // end point of trace is 99 units straight down from start...
+ // (99 is 108 minus the jump limit height which is 45 - 36 = 9)
+ v_dest = v_source + Vector(0, 0, -99);
+
+ // trace a line straight down toward the ground...
+ UTIL_TraceLine( v_source, v_dest, dont_ignore_monsters,
+ pEdict->v.pContainingEntity, &tr);
+
+ // if trace hit something, return FALSE
+ if (tr.flFraction < 1.0)
+ return FALSE;
+
+ // now check same height to one side of the bot...
+ v_source = pEdict->v.origin + gpGlobals->v_right * 16 + gpGlobals->v_forward * 24;
+ v_source.z = v_source.z + 108;
+ v_dest = v_source + Vector(0, 0, -99);
+
+ // trace a line straight down toward the ground...
+ UTIL_TraceLine( v_source, v_dest, dont_ignore_monsters,
+ pEdict->v.pContainingEntity, &tr);
+
+ // if trace hit something, return FALSE
+ if (tr.flFraction < 1.0)
+ return FALSE;
+
+ // now check same height on the other side of the bot...
+ v_source = pEdict->v.origin + gpGlobals->v_right * -16 + gpGlobals->v_forward * 24;
+ v_source.z = v_source.z + 108;
+ v_dest = v_source + Vector(0, 0, -99);
+
+ // trace a line straight down toward the ground...
+ UTIL_TraceLine( v_source, v_dest, dont_ignore_monsters,
+ pEdict->v.pContainingEntity, &tr);
+
+ // if trace hit something, return FALSE
+ if (tr.flFraction < 1.0)
+ return FALSE;
+
+ return TRUE;
+}
+
+
+bool BotCanDuckUnder( bot_t *pBot )
+{
+ // What I do here is trace 3 lines straight out, one unit higher than
+ // the ducking height. I trace once at the center of the body, once
+ // at the right side, and once at the left side. If all three of these
+ // TraceLines don't hit an obstruction then I know the area to duck to
+ // is clear. I then need to trace from the ground up, 72 units, to make
+ // sure that there is something blocking the TraceLine. Then we know
+ // we can duck under it.
+
+ TraceResult tr;
+ Vector v_duck, v_source, v_dest;
+ edict_t *pEdict = pBot->pEdict;
+
+ // convert current view angle to vectors for TraceLine math...
+
+ v_duck = pEdict->v.v_angle;
+ v_duck.x = 0; // reset pitch to 0 (level horizontally)
+ v_duck.z = 0; // reset roll to 0 (straight up and down)
+
+ UTIL_MakeVectors( v_duck );
+
+ // use center of the body first...
+
+ // duck height is 36, so check one unit above that (37)
+ v_source = pEdict->v.origin + Vector(0, 0, -36 + 37);
+ v_dest = v_source + gpGlobals->v_forward * 24;
+
+ // trace a line forward at duck height...
+ UTIL_TraceLine( v_source, v_dest, dont_ignore_monsters,
+ pEdict->v.pContainingEntity, &tr);
+
+ // if trace hit something, return FALSE
+ if (tr.flFraction < 1.0)
+ return FALSE;
+
+ // now check same height to one side of the bot...
+ v_source = pEdict->v.origin + gpGlobals->v_right * 16 + Vector(0, 0, -36 + 37);
+ v_dest = v_source + gpGlobals->v_forward * 24;
+
+ // trace a line forward at duck height...
+ UTIL_TraceLine( v_source, v_dest, dont_ignore_monsters,
+ pEdict->v.pContainingEntity, &tr);
+
+ // if trace hit something, return FALSE
+ if (tr.flFraction < 1.0)
+ return FALSE;
+
+ // now check same height on the other side of the bot...
+ v_source = pEdict->v.origin + gpGlobals->v_right * -16 + Vector(0, 0, -36 + 37);
+ v_dest = v_source + gpGlobals->v_forward * 24;
+
+ // trace a line forward at duck height...
+ UTIL_TraceLine( v_source, v_dest, dont_ignore_monsters,
+ pEdict->v.pContainingEntity, &tr);
+
+ // if trace hit something, return FALSE
+ if (tr.flFraction < 1.0)
+ return FALSE;
+
+ // now trace from the ground up to check for object to duck under...
+
+ // start of trace is 24 units in front of bot near ground...
+ v_source = pEdict->v.origin + gpGlobals->v_forward * 24;
+ v_source.z = v_source.z - 35; // offset to feet + 1 unit up
+
+ // end point of trace is 72 units straight up from start...
+ v_dest = v_source + Vector(0, 0, 72);
+
+ // trace a line straight up in the air...
+ UTIL_TraceLine( v_source, v_dest, dont_ignore_monsters,
+ pEdict->v.pContainingEntity, &tr);
+
+ // if trace didn't hit something, return FALSE
+ if (tr.flFraction >= 1.0)
+ return FALSE;
+
+ // now check same height to one side of the bot...
+ v_source = pEdict->v.origin + gpGlobals->v_right * 16 + gpGlobals->v_forward * 24;
+ v_source.z = v_source.z - 35; // offset to feet + 1 unit up
+ v_dest = v_source + Vector(0, 0, 72);
+
+ // trace a line straight up in the air...
+ UTIL_TraceLine( v_source, v_dest, dont_ignore_monsters,
+ pEdict->v.pContainingEntity, &tr);
+
+ // if trace didn't hit something, return FALSE
+ if (tr.flFraction >= 1.0)
+ return FALSE;
+
+ // now check same height on the other side of the bot...
+ v_source = pEdict->v.origin + gpGlobals->v_right * -16 + gpGlobals->v_forward * 24;
+ v_source.z = v_source.z - 35; // offset to feet + 1 unit up
+ v_dest = v_source + Vector(0, 0, 72);
+
+ // trace a line straight up in the air...
+ UTIL_TraceLine( v_source, v_dest, dont_ignore_monsters,
+ pEdict->v.pContainingEntity, &tr);
+
+ // if trace didn't hit something, return FALSE
+ if (tr.flFraction >= 1.0)
+ return FALSE;
+
+ return TRUE;
+}
+
+
+void BotRandomTurn( bot_t *pBot )
+{
+ pBot->f_move_speed = 0; // don't move while turning
+
+ if (RANDOM_LONG(1, 100) <= 10)
+ {
+ // 10 percent of the time turn completely around...
+ pBot->pEdict->v.ideal_yaw += 180;
+ }
+ else
+ {
+ // turn randomly between 30 and 60 degress
+ if (pBot->wander_dir == WANDER_LEFT)
+ pBot->pEdict->v.ideal_yaw += RANDOM_LONG(30, 60);
+ else
+ pBot->pEdict->v.ideal_yaw -= RANDOM_LONG(30, 60);
+ }
+
+ BotFixIdealYaw(pBot->pEdict);
+}
+
+
+bool BotFollowUser( bot_t *pBot )
+{
+ bool user_visible;
+ float f_distance;
+ edict_t *pEdict = pBot->pEdict;
+
+ Vector vecEnd = pBot->pBotUser->v.origin + pBot->pBotUser->v.view_ofs;
+
+ if (pBot->pEdict->v.waterlevel != 3) // is bot NOT under water?
+ pEdict->v.v_angle.x = 0; // reset pitch to 0 (level horizontally)
+
+ pEdict->v.v_angle.z = 0; // reset roll to 0 (straight up and down)
+
+ pEdict->v.angles.x = 0;
+ pEdict->v.angles.y = pEdict->v.v_angle.y;
+ pEdict->v.angles.z = 0;
+
+ // Stop following when person crouches
+ if (!IsAlive( pBot->pBotUser ) || (pBot->pBotUser->v.flags & FL_DUCKING))
+ {
+ // the bot's user is dead!
+ pBot->pBotUser = NULL;
+ return FALSE;
+ }
+
+ user_visible = FInViewCone( &vecEnd, pEdict ) &&
+ FVisible( vecEnd, pEdict );
+
+ // check if the "user" is still visible or if the user has been visible
+ // in the last 5 seconds (or the player just starting "using" the bot)
+
+ if (user_visible || (pBot->f_bot_use_time + 5 > gpGlobals->time))
+ {
+ if (user_visible)
+ pBot->f_bot_use_time = gpGlobals->time; // reset "last visible time"
+
+ // face the user
+ Vector v_user = pBot->pBotUser->v.origin - pEdict->v.origin;
+ Vector bot_angles = UTIL_VecToAngles( v_user );
+
+ pEdict->v.ideal_yaw = bot_angles.y;
+
+ BotFixIdealYaw(pEdict);
+
+ f_distance = v_user.Length( ); // how far away is the "user"?
+
+ if (f_distance > 200) // run if distance to enemy is far
+ pBot->f_move_speed = pBot->f_max_speed;
+ else if (f_distance > 50) // walk if distance is closer
+ pBot->f_move_speed = pBot->f_max_speed / 2;
+ else // don't move if close enough
+ pBot->f_move_speed = 0.0;
+
+ return TRUE;
+ }
+ else
+ {
+ // person to follow has gone out of sight...
+ pBot->pBotUser = NULL;
+
+ return FALSE;
+ }
+}
+
+
+bool BotCheckWallOnLeft( bot_t *pBot )
+{
+ edict_t *pEdict = pBot->pEdict;
+ Vector v_src, v_left;
+ TraceResult tr;
+
+ UTIL_MakeVectors( pEdict->v.v_angle );
+
+ // do a trace to the left...
+
+ v_src = pEdict->v.origin;
+ v_left = v_src + gpGlobals->v_right * -40; // 40 units to the left
+
+ UTIL_TraceLine( v_src, v_left, dont_ignore_monsters,
+ pEdict->v.pContainingEntity, &tr);
+
+ // check if the trace hit something...
+ if (tr.flFraction < 1.0)
+ {
+ if (pBot->f_wall_on_left < 1.0)
+ pBot->f_wall_on_left = gpGlobals->time;
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+bool BotCheckWallOnRight( bot_t *pBot )
+{
+ edict_t *pEdict = pBot->pEdict;
+ Vector v_src, v_right;
+ TraceResult tr;
+
+ UTIL_MakeVectors( pEdict->v.v_angle );
+
+ // do a trace to the right...
+
+ v_src = pEdict->v.origin;
+ v_right = v_src + gpGlobals->v_right * 40; // 40 units to the right
+
+ UTIL_TraceLine( v_src, v_right, dont_ignore_monsters,
+ pEdict->v.pContainingEntity, &tr);
+
+ // check if the trace hit something...
+ if (tr.flFraction < 1.0)
+ {
+ if (pBot->f_wall_on_right < 1.0)
+ pBot->f_wall_on_right = gpGlobals->time;
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
diff --git a/main/source/HPB_bot/dlls/bot_start.cpp b/main/source/HPB_bot/dlls/bot_start.cpp
index 203b259f..f91863fd 100644
--- a/main/source/HPB_bot/dlls/bot_start.cpp
+++ b/main/source/HPB_bot/dlls/bot_start.cpp
@@ -1,813 +1,813 @@
-//
-// HPB bot - botman's High Ping Bastard bot
-//
-// (http://planethalflife.com/botman/)
-//
-// bot_start.cpp
-//
-
-#include "dlls/extdll.h"
-#include "dlls/util.h"
-#include "dlls/cbase.h"
-
-#include "bot.h"
-#include "bot_func.h"
-#include "bot_weapons.h"
-#include "mod/AvHMessage.h"
-
-extern int mod_id;
-extern edict_t *pent_info_ctfdetect;
-
-extern int max_team_players[4];
-extern int team_class_limits[4];
-extern int max_teams;
-
-
-void BotStartGame( bot_t *pBot )
-{
- char c_team[32];
- char c_class[32];
- char c_item[32];
- int index, count, retry_count;
- edict_t *pPlayer;
- int team;
- int class_not_allowed;
-
- edict_t *pEdict = pBot->pEdict;
-
- //CBaseEntity* theEntity = CBaseEntity::Instance(pEdict);
- //AvHPlayer* thePlayer = dynamic_cast(theEntity);
-
- if (mod_id == TFC_DLL)
- {
- if ((pBot->start_action == MSG_TFC_IDLE) &&
- (pBot->create_time + 3.0 <= gpGlobals->time))
- {
- pBot->start_action = MSG_TFC_TEAM_SELECT; // force team selection
- }
-
- // handle Team Fortress Classic stuff here...
-
- if (pBot->start_action == MSG_TFC_TEAM_SELECT)
- {
- pBot->start_action = MSG_TFC_IDLE; // switch back to idle
- pBot->create_time = gpGlobals->time; // reset
-
- if ((pBot->bot_team != 1) && (pBot->bot_team != 2) &&
- (pBot->bot_team != 3) && (pBot->bot_team != 4) &&
- (pBot->bot_team != 5))
- pBot->bot_team = -1;
-
- if (pBot->bot_team == -1)
- pBot->bot_team = RANDOM_LONG(1, max_teams);
-
- retry_count = 0;
-
- while ((retry_count < 4) &&
- (max_team_players[pBot->bot_team-1] > 0)) // not unlimited?
- {
- count = 0;
-
- // count number of players on this team...
- for (index = 1; index <= gpGlobals->maxClients; index++)
- {
- pPlayer = INDEXENT(index);
-
- if (pPlayer && !pPlayer->free)
- {
- if (UTIL_GetTeam(pPlayer) == (pBot->bot_team - 1))
- count++;
- }
- }
-
- if (count < max_team_players[pBot->bot_team-1])
- break; // haven't reached limit yet, continue
- else
- {
- pBot->bot_team++;
-
- if (pBot->bot_team > max_teams)
- pBot->bot_team = 1;
-
- retry_count++;
- }
- }
-
- // select the team the bot wishes to join...
- if (pBot->bot_team == 1)
- strcpy(c_team, "1");
- else if (pBot->bot_team == 2)
- strcpy(c_team, "2");
- else if (pBot->bot_team == 3)
- strcpy(c_team, "3");
- else if (pBot->bot_team == 4)
- strcpy(c_team, "4");
- else
- strcpy(c_team, "5");
-
- FakeClientCommand(pEdict, "jointeam", c_team, NULL);
-
- return;
- }
-
- if (pBot->start_action == MSG_TFC_CLASS_SELECT)
- {
- pBot->start_action = MSG_TFC_IDLE; // switch back to idle
- pBot->create_time = gpGlobals->time; // reset
-
- if ((pBot->bot_class < 0) || (pBot->bot_class > 10))
- pBot->bot_class = -1;
-
- if (pBot->bot_class == -1)
- pBot->bot_class = RANDOM_LONG(1, 10);
-
- team = UTIL_GetTeam(pEdict);
-
- if (team_class_limits[team] == -1) // civilian only?
- {
- pBot->bot_class = 0; // civilian
- }
- else
- {
- if (pBot->bot_class == 10)
- class_not_allowed = team_class_limits[team] & (1<<7);
- else if (pBot->bot_class <= 7)
- class_not_allowed = team_class_limits[team] & (1<<(pBot->bot_class-1));
- else
- class_not_allowed = team_class_limits[team] & (1<<(pBot->bot_class));
-
- while (class_not_allowed)
- {
- pBot->bot_class = RANDOM_LONG(1, 10);
-
- if (pBot->bot_class == 10)
- class_not_allowed = team_class_limits[team] & (1<<7);
- else if (pBot->bot_class <= 7)
- class_not_allowed = team_class_limits[team] & (1<<(pBot->bot_class-1));
- else
- class_not_allowed = team_class_limits[team] & (1<<(pBot->bot_class));
- }
- }
-
- // select the class the bot wishes to use...
- if (pBot->bot_class == 0)
- strcpy(c_class, "civilian");
- else if (pBot->bot_class == 1)
- strcpy(c_class, "scout");
- else if (pBot->bot_class == 2)
- strcpy(c_class, "sniper");
- else if (pBot->bot_class == 3)
- strcpy(c_class, "soldier");
- else if (pBot->bot_class == 4)
- strcpy(c_class, "demoman");
- else if (pBot->bot_class == 5)
- strcpy(c_class, "medic");
- else if (pBot->bot_class == 6)
- strcpy(c_class, "hwguy");
- else if (pBot->bot_class == 7)
- strcpy(c_class, "pyro");
- else if (pBot->bot_class == 8)
- strcpy(c_class, "spy");
- else if (pBot->bot_class == 9)
- strcpy(c_class, "engineer");
- else
- strcpy(c_class, "randompc");
-
- FakeClientCommand(pEdict, c_class, NULL, NULL);
-
- // bot has now joined the game (doesn't need to be started)
- pBot->not_started = 0;
-
- return;
- }
- }
- else if (mod_id == CSTRIKE_DLL)
- {
- // handle Counter-Strike stuff here...
-
- if (pBot->start_action == MSG_CS_TEAM_SELECT)
- {
- pBot->start_action = MSG_CS_IDLE; // switch back to idle
-
- if ((pBot->bot_team != 1) && (pBot->bot_team != 2) &&
- (pBot->bot_team != 5))
- pBot->bot_team = -1;
-
- if (pBot->bot_team == -1)
- pBot->bot_team = RANDOM_LONG(1, 2);
-
- // select the team the bot wishes to join...
- if (pBot->bot_team == 1)
- strcpy(c_team, "1");
- else if (pBot->bot_team == 2)
- strcpy(c_team, "2");
- else
- strcpy(c_team, "5");
-
- FakeClientCommand(pEdict, "menuselect", c_team, NULL);
-
- return;
- }
-
- if (pBot->start_action == MSG_CS_CT_SELECT) // counter terrorist
- {
- pBot->start_action = MSG_CS_IDLE; // switch back to idle
-
- if ((pBot->bot_class < 1) || (pBot->bot_class > 4))
- pBot->bot_class = -1; // use random if invalid
-
- if (pBot->bot_class == -1)
- pBot->bot_class = RANDOM_LONG(1, 4);
-
- // select the class the bot wishes to use...
- if (pBot->bot_class == 1)
- strcpy(c_class, "1");
- else if (pBot->bot_class == 2)
- strcpy(c_class, "2");
- else if (pBot->bot_class == 3)
- strcpy(c_class, "3");
- else if (pBot->bot_class == 4)
- strcpy(c_class, "4");
- else
- strcpy(c_class, "5"); // random
-
- FakeClientCommand(pEdict, "menuselect", c_class, NULL);
-
- // bot has now joined the game (doesn't need to be started)
- pBot->not_started = 0;
-
- return;
- }
-
- if (pBot->start_action == MSG_CS_T_SELECT) // terrorist select
- {
- pBot->start_action = MSG_CS_IDLE; // switch back to idle
-
- if ((pBot->bot_class < 1) || (pBot->bot_class > 4))
- pBot->bot_class = -1; // use random if invalid
-
- if (pBot->bot_class == -1)
- pBot->bot_class = RANDOM_LONG(1, 4);
-
- // select the class the bot wishes to use...
- if (pBot->bot_class == 1)
- strcpy(c_class, "1");
- else if (pBot->bot_class == 2)
- strcpy(c_class, "2");
- else if (pBot->bot_class == 3)
- strcpy(c_class, "3");
- else if (pBot->bot_class == 4)
- strcpy(c_class, "4");
- else
- strcpy(c_class, "5"); // random
-
- FakeClientCommand(pEdict, "menuselect", c_class, NULL);
-
- // bot has now joined the game (doesn't need to be started)
- pBot->not_started = 0;
-
- return;
- }
- }
- else if ((mod_id == GEARBOX_DLL) && (pent_info_ctfdetect != NULL))
- {
- // handle Opposing Force CTF stuff here...
-
- if (pBot->start_action == MSG_OPFOR_TEAM_SELECT)
- {
- pBot->start_action = MSG_OPFOR_IDLE; // switch back to idle
-
- if ((pBot->bot_team != 1) && (pBot->bot_team != 2) &&
- (pBot->bot_team != 3))
- pBot->bot_team = -1;
-
- if (pBot->bot_team == -1)
- pBot->bot_team = RANDOM_LONG(1, 2);
-
- // select the team the bot wishes to join...
- if (pBot->bot_team == 1)
- strcpy(c_team, "1");
- else if (pBot->bot_team == 2)
- strcpy(c_team, "2");
- else
- strcpy(c_team, "3");
-
- FakeClientCommand(pEdict, "jointeam", c_team, NULL);
-
- return;
- }
-
- if (pBot->start_action == MSG_OPFOR_CLASS_SELECT)
- {
- pBot->start_action = MSG_OPFOR_IDLE; // switch back to idle
-
- if ((pBot->bot_class < 0) || (pBot->bot_class > 10))
- pBot->bot_class = -1;
-
- if (pBot->bot_class == -1)
- pBot->bot_class = RANDOM_LONG(1, 10);
-
- // select the class the bot wishes to use...
- if (pBot->bot_class == 1)
- strcpy(c_class, "1");
- else if (pBot->bot_class == 2)
- strcpy(c_class, "2");
- else if (pBot->bot_class == 3)
- strcpy(c_class, "3");
- else if (pBot->bot_class == 4)
- strcpy(c_class, "4");
- else if (pBot->bot_class == 5)
- strcpy(c_class, "5");
- else if (pBot->bot_class == 6)
- strcpy(c_class, "6");
- else
- strcpy(c_class, "7");
-
- FakeClientCommand(pEdict, "selectchar", c_class, NULL);
-
- // bot has now joined the game (doesn't need to be started)
- pBot->not_started = 0;
-
- return;
- }
- }
- else if (mod_id == FRONTLINE_DLL)
- {
- // handle FrontLineForce stuff here...
-
- if (pBot->start_action == MSG_FLF_TEAM_SELECT)
- {
- pBot->start_action = MSG_FLF_IDLE; // switch back to idle
-
- if ((pBot->bot_team != 1) && (pBot->bot_team != 2) &&
- (pBot->bot_team != 5))
- pBot->bot_team = -1;
-
- if (pBot->bot_team == -1)
- pBot->bot_team = RANDOM_LONG(1, 2);
-
- // select the team the bot wishes to join...
- if (pBot->bot_team == 1)
- strcpy(c_team, "1");
- else if (pBot->bot_team == 2)
- strcpy(c_team, "2");
- else
- strcpy(c_team, "5");
-
- FakeClientCommand(pEdict, "jointeam", c_team, NULL);
-
- return;
- }
-
- if (pBot->start_action == MSG_FLF_CLASS_SELECT)
- {
- pBot->start_action = MSG_FLF_IDLE; // switch back to idle
-
- team = UTIL_GetTeam(pEdict);
-
- if (team == 0) // rebels
- {
- if ((pBot->bot_class < 0) || (pBot->bot_class > 3))
- pBot->bot_class = -1;
-
- if (pBot->bot_class == -1)
- pBot->bot_class = RANDOM_LONG(1, 3);
-
- // select the class the bot wishes to use...
- if (pBot->bot_class == 1)
- strcpy(c_class, "rebelsrecon");
- else if (pBot->bot_class == 2)
- strcpy(c_class, "rebelsassault");
- else
- strcpy(c_class, "rebelssupport");
- }
- else // commandos
- {
- if ((pBot->bot_class < 0) || (pBot->bot_class > 3))
- pBot->bot_class = -1;
-
- if (pBot->bot_class == -1)
- pBot->bot_class = RANDOM_LONG(1, 3);
-
- // select the class the bot wishes to use...
- if (pBot->bot_class == 1)
- strcpy(c_class, "commandosrecon");
- else if (pBot->bot_class == 2)
- strcpy(c_class, "commandosassault");
- else
- strcpy(c_class, "commandossupport");
- }
-
- FakeClientCommand(pEdict, c_class, NULL, NULL);
-
- return;
- }
-
- if (pBot->start_action == MSG_FLF_PISTOL_SELECT)
- {
- int prim_weapon_group, sec_weapon_group;
-
- pBot->start_action = MSG_FLF_IDLE; // switch back to idle
-
- int flf_class = UTIL_GetClass(pEdict);
-
- if (flf_class == 0) // recon
- {
- prim_weapon_group = RANDOM_LONG(1, 3);
-
- if (prim_weapon_group == 1) // shotguns
- pBot->primary_weapon = FLF_WEAPON_SPAS12;
- else if (prim_weapon_group == 2) // submachine
- {
- int weapon = RANDOM_LONG(1, 4);
-
- if (weapon == 1)
- pBot->primary_weapon = FLF_WEAPON_MP5A2;
- else if (weapon == 2)
- pBot->primary_weapon = FLF_WEAPON_MP5SD;
- else if (weapon == 3)
- pBot->primary_weapon = FLF_WEAPON_MAC10;
- else
- pBot->primary_weapon = FLF_WEAPON_UMP45;
- }
- else // rifles
- {
- pBot->primary_weapon = FLF_WEAPON_MSG90;
- }
-
- if (prim_weapon_group == 1)
- sec_weapon_group = RANDOM_LONG(2, 3);
- else if (prim_weapon_group == 3)
- sec_weapon_group = RANDOM_LONG(1, 2);
- else
- {
- if (RANDOM_LONG(1, 100) <= 50)
- sec_weapon_group = 1;
- else
- sec_weapon_group = 3;
- }
-
- if (sec_weapon_group == 1) // shotguns
- pBot->secondary_weapon = FLF_WEAPON_SPAS12;
- else if (sec_weapon_group == 2) // submachine
- {
- int weapon = RANDOM_LONG(1, 4);
-
- if (weapon == 1)
- pBot->secondary_weapon = FLF_WEAPON_MP5A2;
- else if (weapon == 2)
- pBot->secondary_weapon = FLF_WEAPON_MP5SD;
- else if (weapon == 3)
- pBot->secondary_weapon = FLF_WEAPON_MAC10;
- else
- pBot->secondary_weapon = FLF_WEAPON_UMP45;
- }
- else // rifles
- {
- pBot->secondary_weapon = FLF_WEAPON_MSG90;
- }
- }
- else if (flf_class == 1) // assault
- {
- prim_weapon_group = RANDOM_LONG(1, 3);
-
- if (prim_weapon_group == 1) // shotguns
- pBot->primary_weapon = FLF_WEAPON_SPAS12;
- else if (prim_weapon_group == 2) // submachine
- {
- int weapon = RANDOM_LONG(1, 4);
-
- if (weapon == 1)
- pBot->primary_weapon = FLF_WEAPON_MP5A2;
- else if (weapon == 2)
- pBot->primary_weapon = FLF_WEAPON_MP5SD;
- else if (weapon == 3)
- pBot->primary_weapon = FLF_WEAPON_MAC10;
- else
- pBot->primary_weapon = FLF_WEAPON_UMP45;
- }
- else // rifles
- {
- int weapon = RANDOM_LONG(1, 3);
-
- if (weapon == 1)
- pBot->primary_weapon = FLF_WEAPON_M4;
- else if (weapon == 2)
- pBot->primary_weapon = FLF_WEAPON_FAMAS;
- else
- pBot->primary_weapon = FLF_WEAPON_AK5;
- }
-
- if (prim_weapon_group == 1)
- sec_weapon_group = RANDOM_LONG(2, 3);
- else if (prim_weapon_group == 2)
- {
- if (RANDOM_LONG(1, 100) <= 50)
- sec_weapon_group = 1;
- else
- sec_weapon_group = 3;
- }
- else // prim == 3
- sec_weapon_group = RANDOM_LONG(1, 2);
-
- if (sec_weapon_group == 1) // shotguns
- pBot->secondary_weapon = FLF_WEAPON_SPAS12;
- else if (sec_weapon_group == 2) // submachine
- {
- int weapon = RANDOM_LONG(1, 4);
-
- if (weapon == 1)
- pBot->secondary_weapon = FLF_WEAPON_MP5A2;
- else if (weapon == 2)
- pBot->secondary_weapon = FLF_WEAPON_MP5SD;
- else if (weapon == 3)
- pBot->secondary_weapon = FLF_WEAPON_MAC10;
- else
- pBot->secondary_weapon = FLF_WEAPON_UMP45;
- }
- else // rifles
- {
- int weapon = RANDOM_LONG(1, 3);
-
- if (weapon == 1)
- pBot->secondary_weapon = FLF_WEAPON_M4;
- else if (weapon == 2)
- pBot->secondary_weapon = FLF_WEAPON_FAMAS;
- else
- pBot->secondary_weapon = FLF_WEAPON_AK5;
- }
- }
- else // support
- {
- prim_weapon_group = RANDOM_LONG(1, 3);
-
- if (prim_weapon_group == 1) // shotguns
- pBot->primary_weapon = FLF_WEAPON_SPAS12;
- else if (prim_weapon_group == 2) // submachine
- {
- int weapon = RANDOM_LONG(1, 4);
-
- if (weapon == 1)
- pBot->primary_weapon = FLF_WEAPON_MP5A2;
- else if (weapon == 2)
- pBot->primary_weapon = FLF_WEAPON_MP5SD;
- else if (weapon == 3)
- pBot->primary_weapon = FLF_WEAPON_MAC10;
- else
- pBot->primary_weapon = FLF_WEAPON_UMP45;
- }
- else if (prim_weapon_group == 3) // rifles & heavyweapons
- {
- if (RANDOM_LONG(1, 100) <= 50)
- {
- int weapon = RANDOM_LONG(1, 3); // rifles
-
- if (weapon == 1)
- pBot->primary_weapon = FLF_WEAPON_M4;
- else if (weapon == 2)
- pBot->primary_weapon = FLF_WEAPON_FAMAS;
- else
- pBot->primary_weapon = FLF_WEAPON_AK5;
- }
- else // heavy weapons
- {
- pBot->primary_weapon = FLF_WEAPON_HK21;
- }
- }
-
- if (prim_weapon_group == 1)
- sec_weapon_group = RANDOM_LONG(2, 3);
- else if (prim_weapon_group == 2)
- {
- if (RANDOM_LONG(1, 100) <= 50)
- sec_weapon_group = 1;
- else
- sec_weapon_group = 3;
- }
- else // prim == 3
- sec_weapon_group = RANDOM_LONG(1, 2);
-
- if (sec_weapon_group == 1) // shotguns
- pBot->secondary_weapon = FLF_WEAPON_SPAS12;
- else if (sec_weapon_group == 2) // submachine
- {
- int weapon = RANDOM_LONG(1, 4);
-
- if (weapon == 1)
- pBot->secondary_weapon = FLF_WEAPON_MP5A2;
- else if (weapon == 2)
- pBot->secondary_weapon = FLF_WEAPON_MP5SD;
- else if (weapon == 3)
- pBot->secondary_weapon = FLF_WEAPON_MAC10;
- else
- pBot->secondary_weapon = FLF_WEAPON_UMP45;
- }
- else if (sec_weapon_group == 3) // rifles & heavyweapons
- {
- if (RANDOM_LONG(1, 100) <= 50)
- {
- int weapon = RANDOM_LONG(1, 3); // rifles
-
- if (weapon == 1)
- pBot->secondary_weapon = FLF_WEAPON_M4;
- else if (weapon == 2)
- pBot->secondary_weapon = FLF_WEAPON_FAMAS;
- else
- pBot->secondary_weapon = FLF_WEAPON_AK5;
- }
- else // heavy weapons
- {
- pBot->secondary_weapon = FLF_WEAPON_HK21;
- }
- }
- }
-
- int pistol = RANDOM_LONG(1, 2);
-
- if (pistol == 1)
- strcpy(c_item, "26"); // mk23
- else
- strcpy(c_item, "23"); // beretta
-
- FakeClientCommand(pEdict, "pistols", c_item, NULL);
-
- return;
- }
-
- if (pBot->start_action == MSG_FLF_WEAPON_SELECT)
- {
- int weapon_class;
-
- pBot->start_action = MSG_FLF_IDLE; // switch back to idle
-
- if (pBot->primary_weapon)
- weapon_class = pBot->primary_weapon;
- else
- weapon_class = pBot->secondary_weapon;
-
- if (weapon_class == FLF_WEAPON_SPAS12) // shotguns
- strcpy(c_item, "shotgun");
- else if ((weapon_class == FLF_WEAPON_MP5A2) || // submachine
- (weapon_class == FLF_WEAPON_MP5SD) ||
- (weapon_class == FLF_WEAPON_MAC10) ||
- (weapon_class == FLF_WEAPON_UMP45))
- strcpy(c_item, "submachine");
- else if ((weapon_class == FLF_WEAPON_M4) ||
- (weapon_class == FLF_WEAPON_FAMAS) ||
- (weapon_class == FLF_WEAPON_AK5) ||
- (weapon_class == FLF_WEAPON_MSG90))
- strcpy(c_item, "rifles");
- else
- strcpy(c_item, "heavyweapons");
-
- FakeClientCommand(pEdict, "wpnclass", c_item, NULL);
-
- return;
- }
-
- if (pBot->start_action == MSG_FLF_SHOTGUN_SELECT)
- {
- int weapon_class;
-
- pBot->start_action = MSG_FLF_IDLE; // switch back to idle
-
- if (pBot->primary_weapon)
- {
- weapon_class = pBot->primary_weapon;
- pBot->primary_weapon = 0;
- }
- else
- {
- weapon_class = pBot->secondary_weapon;
-
- // bot has now joined the game (doesn't need to be started)
- pBot->not_started = 0;
- }
-
- sprintf(c_item, "%d", weapon_class);
-
- FakeClientCommand(pEdict, "shotgun", c_item, NULL);
-
- return;
- }
-
- if (pBot->start_action == MSG_FLF_SUBMACHINE_SELECT)
- {
- int weapon_class;
-
- pBot->start_action = MSG_FLF_IDLE; // switch back to idle
-
- if (pBot->primary_weapon)
- {
- weapon_class = pBot->primary_weapon;
- pBot->primary_weapon = 0;
- }
- else
- {
- weapon_class = pBot->secondary_weapon;
-
- // bot has now joined the game (doesn't need to be started)
- pBot->not_started = 0;
- }
-
- sprintf(c_item, "%d", weapon_class);
-
- FakeClientCommand(pEdict, "submach", c_item, NULL);
-
- return;
- }
-
- if (pBot->start_action == MSG_FLF_RIFLE_SELECT)
- {
- int weapon_class;
-
- pBot->start_action = MSG_FLF_IDLE; // switch back to idle
-
- if (pBot->primary_weapon)
- {
- weapon_class = pBot->primary_weapon;
- pBot->primary_weapon = 0;
- }
- else
- {
- weapon_class = pBot->secondary_weapon;
-
- // bot has now joined the game (doesn't need to be started)
- pBot->not_started = 0;
- }
-
- sprintf(c_item, "%d", weapon_class);
-
- FakeClientCommand(pEdict, "rifles", c_item, NULL);
-
- return;
- }
-
- if (pBot->start_action == MSG_FLF_HEAVYWEAPONS_SELECT)
- {
- int weapon_class;
-
- pBot->start_action = MSG_FLF_IDLE; // switch back to idle
-
- if (pBot->primary_weapon)
- {
- weapon_class = pBot->primary_weapon;
- pBot->primary_weapon = 0;
- }
- else
- {
- weapon_class = pBot->secondary_weapon;
-
- // bot has now joined the game (doesn't need to be started)
- pBot->not_started = 0;
- }
-
- sprintf(c_item, "%d", weapon_class);
-
- FakeClientCommand(pEdict, "heavyweapons", c_item, NULL);
-
- return;
- }
-
- }
- else if (mod_id == AVH_DLL)
- {
-// if(pBot->mBotPlayMode == PLAYMODE_READYROOM)
-// {
-// // Look at desired team and head to nearest start entity
-// AvHClassType theClassType = AVH_CLASS_TYPE_UNDEFINED;
-//// if(pBot->mBotRole == ROLE_UNDEFINED)
-//// {
-//// // Choose a random team
-//// theClassType = AvHClassType(RANDOM_LONG(1, 2));
-//// }
-//// else
-//// {
-//// theClassType = (AvHClassType)pBot->mBotRole;
-//// }
-////
-//// // Now navigate to the nearest start entity
-//// if(theClassType == AVH_CLASS_TYPE_MARINE)
-//// {
-// FakeClientCommand(pEdict, kcAutoAssign, c_item, NULL);
-// //FakeClientCommand(pEdict, kcJoinTeamOne, c_item, NULL);
-//
-// // Try to become a squad leader if possible
-//// pBot->pEdict->v.impulse = RANK_PROMOTE;
-//// }
-//// else if(theClassType == AVH_CLASS_TYPE_ALIEN)
-//// {
-//// FakeClientCommand(pEdict, kcJoinTeamTwo, c_item, NULL);
-//// }
-//
-// // bot has now joined the game (doesn't need to be started)
-// pBot->not_started = 0;
-// }
- }
- else
- {
- // otherwise, don't need to do anything to start game...
- pBot->not_started = 0;
- }
-}
-
+//
+// HPB bot - botman's High Ping Bastard bot
+//
+// (http://planethalflife.com/botman/)
+//
+// bot_start.cpp
+//
+
+#include "dlls/extdll.h"
+#include "dlls/util.h"
+#include "dlls/cbase.h"
+
+#include "bot.h"
+#include "bot_func.h"
+#include "bot_weapons.h"
+#include "mod/AvHMessage.h"
+
+extern int mod_id;
+extern edict_t *pent_info_ctfdetect;
+
+extern int max_team_players[4];
+extern int team_class_limits[4];
+extern int max_teams;
+
+
+void BotStartGame( bot_t *pBot )
+{
+ char c_team[32];
+ char c_class[32];
+ char c_item[32];
+ int index, count, retry_count;
+ edict_t *pPlayer;
+ int team;
+ int class_not_allowed;
+
+ edict_t *pEdict = pBot->pEdict;
+
+ //CBaseEntity* theEntity = CBaseEntity::Instance(pEdict);
+ //AvHPlayer* thePlayer = dynamic_cast(theEntity);
+
+ if (mod_id == TFC_DLL)
+ {
+ if ((pBot->start_action == MSG_TFC_IDLE) &&
+ (pBot->create_time + 3.0 <= gpGlobals->time))
+ {
+ pBot->start_action = MSG_TFC_TEAM_SELECT; // force team selection
+ }
+
+ // handle Team Fortress Classic stuff here...
+
+ if (pBot->start_action == MSG_TFC_TEAM_SELECT)
+ {
+ pBot->start_action = MSG_TFC_IDLE; // switch back to idle
+ pBot->create_time = gpGlobals->time; // reset
+
+ if ((pBot->bot_team != 1) && (pBot->bot_team != 2) &&
+ (pBot->bot_team != 3) && (pBot->bot_team != 4) &&
+ (pBot->bot_team != 5))
+ pBot->bot_team = -1;
+
+ if (pBot->bot_team == -1)
+ pBot->bot_team = RANDOM_LONG(1, max_teams);
+
+ retry_count = 0;
+
+ while ((retry_count < 4) &&
+ (max_team_players[pBot->bot_team-1] > 0)) // not unlimited?
+ {
+ count = 0;
+
+ // count number of players on this team...
+ for (index = 1; index <= gpGlobals->maxClients; index++)
+ {
+ pPlayer = INDEXENT(index);
+
+ if (pPlayer && !pPlayer->free)
+ {
+ if (UTIL_GetTeam(pPlayer) == (pBot->bot_team - 1))
+ count++;
+ }
+ }
+
+ if (count < max_team_players[pBot->bot_team-1])
+ break; // haven't reached limit yet, continue
+ else
+ {
+ pBot->bot_team++;
+
+ if (pBot->bot_team > max_teams)
+ pBot->bot_team = 1;
+
+ retry_count++;
+ }
+ }
+
+ // select the team the bot wishes to join...
+ if (pBot->bot_team == 1)
+ strcpy(c_team, "1");
+ else if (pBot->bot_team == 2)
+ strcpy(c_team, "2");
+ else if (pBot->bot_team == 3)
+ strcpy(c_team, "3");
+ else if (pBot->bot_team == 4)
+ strcpy(c_team, "4");
+ else
+ strcpy(c_team, "5");
+
+ FakeClientCommand(pEdict, "jointeam", c_team, NULL);
+
+ return;
+ }
+
+ if (pBot->start_action == MSG_TFC_CLASS_SELECT)
+ {
+ pBot->start_action = MSG_TFC_IDLE; // switch back to idle
+ pBot->create_time = gpGlobals->time; // reset
+
+ if ((pBot->bot_class < 0) || (pBot->bot_class > 10))
+ pBot->bot_class = -1;
+
+ if (pBot->bot_class == -1)
+ pBot->bot_class = RANDOM_LONG(1, 10);
+
+ team = UTIL_GetTeam(pEdict);
+
+ if (team_class_limits[team] == -1) // civilian only?
+ {
+ pBot->bot_class = 0; // civilian
+ }
+ else
+ {
+ if (pBot->bot_class == 10)
+ class_not_allowed = team_class_limits[team] & (1<<7);
+ else if (pBot->bot_class <= 7)
+ class_not_allowed = team_class_limits[team] & (1<<(pBot->bot_class-1));
+ else
+ class_not_allowed = team_class_limits[team] & (1<<(pBot->bot_class));
+
+ while (class_not_allowed)
+ {
+ pBot->bot_class = RANDOM_LONG(1, 10);
+
+ if (pBot->bot_class == 10)
+ class_not_allowed = team_class_limits[team] & (1<<7);
+ else if (pBot->bot_class <= 7)
+ class_not_allowed = team_class_limits[team] & (1<<(pBot->bot_class-1));
+ else
+ class_not_allowed = team_class_limits[team] & (1<<(pBot->bot_class));
+ }
+ }
+
+ // select the class the bot wishes to use...
+ if (pBot->bot_class == 0)
+ strcpy(c_class, "civilian");
+ else if (pBot->bot_class == 1)
+ strcpy(c_class, "scout");
+ else if (pBot->bot_class == 2)
+ strcpy(c_class, "sniper");
+ else if (pBot->bot_class == 3)
+ strcpy(c_class, "soldier");
+ else if (pBot->bot_class == 4)
+ strcpy(c_class, "demoman");
+ else if (pBot->bot_class == 5)
+ strcpy(c_class, "medic");
+ else if (pBot->bot_class == 6)
+ strcpy(c_class, "hwguy");
+ else if (pBot->bot_class == 7)
+ strcpy(c_class, "pyro");
+ else if (pBot->bot_class == 8)
+ strcpy(c_class, "spy");
+ else if (pBot->bot_class == 9)
+ strcpy(c_class, "engineer");
+ else
+ strcpy(c_class, "randompc");
+
+ FakeClientCommand(pEdict, c_class, NULL, NULL);
+
+ // bot has now joined the game (doesn't need to be started)
+ pBot->not_started = 0;
+
+ return;
+ }
+ }
+ else if (mod_id == CSTRIKE_DLL)
+ {
+ // handle Counter-Strike stuff here...
+
+ if (pBot->start_action == MSG_CS_TEAM_SELECT)
+ {
+ pBot->start_action = MSG_CS_IDLE; // switch back to idle
+
+ if ((pBot->bot_team != 1) && (pBot->bot_team != 2) &&
+ (pBot->bot_team != 5))
+ pBot->bot_team = -1;
+
+ if (pBot->bot_team == -1)
+ pBot->bot_team = RANDOM_LONG(1, 2);
+
+ // select the team the bot wishes to join...
+ if (pBot->bot_team == 1)
+ strcpy(c_team, "1");
+ else if (pBot->bot_team == 2)
+ strcpy(c_team, "2");
+ else
+ strcpy(c_team, "5");
+
+ FakeClientCommand(pEdict, "menuselect", c_team, NULL);
+
+ return;
+ }
+
+ if (pBot->start_action == MSG_CS_CT_SELECT) // counter terrorist
+ {
+ pBot->start_action = MSG_CS_IDLE; // switch back to idle
+
+ if ((pBot->bot_class < 1) || (pBot->bot_class > 4))
+ pBot->bot_class = -1; // use random if invalid
+
+ if (pBot->bot_class == -1)
+ pBot->bot_class = RANDOM_LONG(1, 4);
+
+ // select the class the bot wishes to use...
+ if (pBot->bot_class == 1)
+ strcpy(c_class, "1");
+ else if (pBot->bot_class == 2)
+ strcpy(c_class, "2");
+ else if (pBot->bot_class == 3)
+ strcpy(c_class, "3");
+ else if (pBot->bot_class == 4)
+ strcpy(c_class, "4");
+ else
+ strcpy(c_class, "5"); // random
+
+ FakeClientCommand(pEdict, "menuselect", c_class, NULL);
+
+ // bot has now joined the game (doesn't need to be started)
+ pBot->not_started = 0;
+
+ return;
+ }
+
+ if (pBot->start_action == MSG_CS_T_SELECT) // terrorist select
+ {
+ pBot->start_action = MSG_CS_IDLE; // switch back to idle
+
+ if ((pBot->bot_class < 1) || (pBot->bot_class > 4))
+ pBot->bot_class = -1; // use random if invalid
+
+ if (pBot->bot_class == -1)
+ pBot->bot_class = RANDOM_LONG(1, 4);
+
+ // select the class the bot wishes to use...
+ if (pBot->bot_class == 1)
+ strcpy(c_class, "1");
+ else if (pBot->bot_class == 2)
+ strcpy(c_class, "2");
+ else if (pBot->bot_class == 3)
+ strcpy(c_class, "3");
+ else if (pBot->bot_class == 4)
+ strcpy(c_class, "4");
+ else
+ strcpy(c_class, "5"); // random
+
+ FakeClientCommand(pEdict, "menuselect", c_class, NULL);
+
+ // bot has now joined the game (doesn't need to be started)
+ pBot->not_started = 0;
+
+ return;
+ }
+ }
+ else if ((mod_id == GEARBOX_DLL) && (pent_info_ctfdetect != NULL))
+ {
+ // handle Opposing Force CTF stuff here...
+
+ if (pBot->start_action == MSG_OPFOR_TEAM_SELECT)
+ {
+ pBot->start_action = MSG_OPFOR_IDLE; // switch back to idle
+
+ if ((pBot->bot_team != 1) && (pBot->bot_team != 2) &&
+ (pBot->bot_team != 3))
+ pBot->bot_team = -1;
+
+ if (pBot->bot_team == -1)
+ pBot->bot_team = RANDOM_LONG(1, 2);
+
+ // select the team the bot wishes to join...
+ if (pBot->bot_team == 1)
+ strcpy(c_team, "1");
+ else if (pBot->bot_team == 2)
+ strcpy(c_team, "2");
+ else
+ strcpy(c_team, "3");
+
+ FakeClientCommand(pEdict, "jointeam", c_team, NULL);
+
+ return;
+ }
+
+ if (pBot->start_action == MSG_OPFOR_CLASS_SELECT)
+ {
+ pBot->start_action = MSG_OPFOR_IDLE; // switch back to idle
+
+ if ((pBot->bot_class < 0) || (pBot->bot_class > 10))
+ pBot->bot_class = -1;
+
+ if (pBot->bot_class == -1)
+ pBot->bot_class = RANDOM_LONG(1, 10);
+
+ // select the class the bot wishes to use...
+ if (pBot->bot_class == 1)
+ strcpy(c_class, "1");
+ else if (pBot->bot_class == 2)
+ strcpy(c_class, "2");
+ else if (pBot->bot_class == 3)
+ strcpy(c_class, "3");
+ else if (pBot->bot_class == 4)
+ strcpy(c_class, "4");
+ else if (pBot->bot_class == 5)
+ strcpy(c_class, "5");
+ else if (pBot->bot_class == 6)
+ strcpy(c_class, "6");
+ else
+ strcpy(c_class, "7");
+
+ FakeClientCommand(pEdict, "selectchar", c_class, NULL);
+
+ // bot has now joined the game (doesn't need to be started)
+ pBot->not_started = 0;
+
+ return;
+ }
+ }
+ else if (mod_id == FRONTLINE_DLL)
+ {
+ // handle FrontLineForce stuff here...
+
+ if (pBot->start_action == MSG_FLF_TEAM_SELECT)
+ {
+ pBot->start_action = MSG_FLF_IDLE; // switch back to idle
+
+ if ((pBot->bot_team != 1) && (pBot->bot_team != 2) &&
+ (pBot->bot_team != 5))
+ pBot->bot_team = -1;
+
+ if (pBot->bot_team == -1)
+ pBot->bot_team = RANDOM_LONG(1, 2);
+
+ // select the team the bot wishes to join...
+ if (pBot->bot_team == 1)
+ strcpy(c_team, "1");
+ else if (pBot->bot_team == 2)
+ strcpy(c_team, "2");
+ else
+ strcpy(c_team, "5");
+
+ FakeClientCommand(pEdict, "jointeam", c_team, NULL);
+
+ return;
+ }
+
+ if (pBot->start_action == MSG_FLF_CLASS_SELECT)
+ {
+ pBot->start_action = MSG_FLF_IDLE; // switch back to idle
+
+ team = UTIL_GetTeam(pEdict);
+
+ if (team == 0) // rebels
+ {
+ if ((pBot->bot_class < 0) || (pBot->bot_class > 3))
+ pBot->bot_class = -1;
+
+ if (pBot->bot_class == -1)
+ pBot->bot_class = RANDOM_LONG(1, 3);
+
+ // select the class the bot wishes to use...
+ if (pBot->bot_class == 1)
+ strcpy(c_class, "rebelsrecon");
+ else if (pBot->bot_class == 2)
+ strcpy(c_class, "rebelsassault");
+ else
+ strcpy(c_class, "rebelssupport");
+ }
+ else // commandos
+ {
+ if ((pBot->bot_class < 0) || (pBot->bot_class > 3))
+ pBot->bot_class = -1;
+
+ if (pBot->bot_class == -1)
+ pBot->bot_class = RANDOM_LONG(1, 3);
+
+ // select the class the bot wishes to use...
+ if (pBot->bot_class == 1)
+ strcpy(c_class, "commandosrecon");
+ else if (pBot->bot_class == 2)
+ strcpy(c_class, "commandosassault");
+ else
+ strcpy(c_class, "commandossupport");
+ }
+
+ FakeClientCommand(pEdict, c_class, NULL, NULL);
+
+ return;
+ }
+
+ if (pBot->start_action == MSG_FLF_PISTOL_SELECT)
+ {
+ int prim_weapon_group, sec_weapon_group;
+
+ pBot->start_action = MSG_FLF_IDLE; // switch back to idle
+
+ int flf_class = UTIL_GetClass(pEdict);
+
+ if (flf_class == 0) // recon
+ {
+ prim_weapon_group = RANDOM_LONG(1, 3);
+
+ if (prim_weapon_group == 1) // shotguns
+ pBot->primary_weapon = FLF_WEAPON_SPAS12;
+ else if (prim_weapon_group == 2) // submachine
+ {
+ int weapon = RANDOM_LONG(1, 4);
+
+ if (weapon == 1)
+ pBot->primary_weapon = FLF_WEAPON_MP5A2;
+ else if (weapon == 2)
+ pBot->primary_weapon = FLF_WEAPON_MP5SD;
+ else if (weapon == 3)
+ pBot->primary_weapon = FLF_WEAPON_MAC10;
+ else
+ pBot->primary_weapon = FLF_WEAPON_UMP45;
+ }
+ else // rifles
+ {
+ pBot->primary_weapon = FLF_WEAPON_MSG90;
+ }
+
+ if (prim_weapon_group == 1)
+ sec_weapon_group = RANDOM_LONG(2, 3);
+ else if (prim_weapon_group == 3)
+ sec_weapon_group = RANDOM_LONG(1, 2);
+ else
+ {
+ if (RANDOM_LONG(1, 100) <= 50)
+ sec_weapon_group = 1;
+ else
+ sec_weapon_group = 3;
+ }
+
+ if (sec_weapon_group == 1) // shotguns
+ pBot->secondary_weapon = FLF_WEAPON_SPAS12;
+ else if (sec_weapon_group == 2) // submachine
+ {
+ int weapon = RANDOM_LONG(1, 4);
+
+ if (weapon == 1)
+ pBot->secondary_weapon = FLF_WEAPON_MP5A2;
+ else if (weapon == 2)
+ pBot->secondary_weapon = FLF_WEAPON_MP5SD;
+ else if (weapon == 3)
+ pBot->secondary_weapon = FLF_WEAPON_MAC10;
+ else
+ pBot->secondary_weapon = FLF_WEAPON_UMP45;
+ }
+ else // rifles
+ {
+ pBot->secondary_weapon = FLF_WEAPON_MSG90;
+ }
+ }
+ else if (flf_class == 1) // assault
+ {
+ prim_weapon_group = RANDOM_LONG(1, 3);
+
+ if (prim_weapon_group == 1) // shotguns
+ pBot->primary_weapon = FLF_WEAPON_SPAS12;
+ else if (prim_weapon_group == 2) // submachine
+ {
+ int weapon = RANDOM_LONG(1, 4);
+
+ if (weapon == 1)
+ pBot->primary_weapon = FLF_WEAPON_MP5A2;
+ else if (weapon == 2)
+ pBot->primary_weapon = FLF_WEAPON_MP5SD;
+ else if (weapon == 3)
+ pBot->primary_weapon = FLF_WEAPON_MAC10;
+ else
+ pBot->primary_weapon = FLF_WEAPON_UMP45;
+ }
+ else // rifles
+ {
+ int weapon = RANDOM_LONG(1, 3);
+
+ if (weapon == 1)
+ pBot->primary_weapon = FLF_WEAPON_M4;
+ else if (weapon == 2)
+ pBot->primary_weapon = FLF_WEAPON_FAMAS;
+ else
+ pBot->primary_weapon = FLF_WEAPON_AK5;
+ }
+
+ if (prim_weapon_group == 1)
+ sec_weapon_group = RANDOM_LONG(2, 3);
+ else if (prim_weapon_group == 2)
+ {
+ if (RANDOM_LONG(1, 100) <= 50)
+ sec_weapon_group = 1;
+ else
+ sec_weapon_group = 3;
+ }
+ else // prim == 3
+ sec_weapon_group = RANDOM_LONG(1, 2);
+
+ if (sec_weapon_group == 1) // shotguns
+ pBot->secondary_weapon = FLF_WEAPON_SPAS12;
+ else if (sec_weapon_group == 2) // submachine
+ {
+ int weapon = RANDOM_LONG(1, 4);
+
+ if (weapon == 1)
+ pBot->secondary_weapon = FLF_WEAPON_MP5A2;
+ else if (weapon == 2)
+ pBot->secondary_weapon = FLF_WEAPON_MP5SD;
+ else if (weapon == 3)
+ pBot->secondary_weapon = FLF_WEAPON_MAC10;
+ else
+ pBot->secondary_weapon = FLF_WEAPON_UMP45;
+ }
+ else // rifles
+ {
+ int weapon = RANDOM_LONG(1, 3);
+
+ if (weapon == 1)
+ pBot->secondary_weapon = FLF_WEAPON_M4;
+ else if (weapon == 2)
+ pBot->secondary_weapon = FLF_WEAPON_FAMAS;
+ else
+ pBot->secondary_weapon = FLF_WEAPON_AK5;
+ }
+ }
+ else // support
+ {
+ prim_weapon_group = RANDOM_LONG(1, 3);
+
+ if (prim_weapon_group == 1) // shotguns
+ pBot->primary_weapon = FLF_WEAPON_SPAS12;
+ else if (prim_weapon_group == 2) // submachine
+ {
+ int weapon = RANDOM_LONG(1, 4);
+
+ if (weapon == 1)
+ pBot->primary_weapon = FLF_WEAPON_MP5A2;
+ else if (weapon == 2)
+ pBot->primary_weapon = FLF_WEAPON_MP5SD;
+ else if (weapon == 3)
+ pBot->primary_weapon = FLF_WEAPON_MAC10;
+ else
+ pBot->primary_weapon = FLF_WEAPON_UMP45;
+ }
+ else if (prim_weapon_group == 3) // rifles & heavyweapons
+ {
+ if (RANDOM_LONG(1, 100) <= 50)
+ {
+ int weapon = RANDOM_LONG(1, 3); // rifles
+
+ if (weapon == 1)
+ pBot->primary_weapon = FLF_WEAPON_M4;
+ else if (weapon == 2)
+ pBot->primary_weapon = FLF_WEAPON_FAMAS;
+ else
+ pBot->primary_weapon = FLF_WEAPON_AK5;
+ }
+ else // heavy weapons
+ {
+ pBot->primary_weapon = FLF_WEAPON_HK21;
+ }
+ }
+
+ if (prim_weapon_group == 1)
+ sec_weapon_group = RANDOM_LONG(2, 3);
+ else if (prim_weapon_group == 2)
+ {
+ if (RANDOM_LONG(1, 100) <= 50)
+ sec_weapon_group = 1;
+ else
+ sec_weapon_group = 3;
+ }
+ else // prim == 3
+ sec_weapon_group = RANDOM_LONG(1, 2);
+
+ if (sec_weapon_group == 1) // shotguns
+ pBot->secondary_weapon = FLF_WEAPON_SPAS12;
+ else if (sec_weapon_group == 2) // submachine
+ {
+ int weapon = RANDOM_LONG(1, 4);
+
+ if (weapon == 1)
+ pBot->secondary_weapon = FLF_WEAPON_MP5A2;
+ else if (weapon == 2)
+ pBot->secondary_weapon = FLF_WEAPON_MP5SD;
+ else if (weapon == 3)
+ pBot->secondary_weapon = FLF_WEAPON_MAC10;
+ else
+ pBot->secondary_weapon = FLF_WEAPON_UMP45;
+ }
+ else if (sec_weapon_group == 3) // rifles & heavyweapons
+ {
+ if (RANDOM_LONG(1, 100) <= 50)
+ {
+ int weapon = RANDOM_LONG(1, 3); // rifles
+
+ if (weapon == 1)
+ pBot->secondary_weapon = FLF_WEAPON_M4;
+ else if (weapon == 2)
+ pBot->secondary_weapon = FLF_WEAPON_FAMAS;
+ else
+ pBot->secondary_weapon = FLF_WEAPON_AK5;
+ }
+ else // heavy weapons
+ {
+ pBot->secondary_weapon = FLF_WEAPON_HK21;
+ }
+ }
+ }
+
+ int pistol = RANDOM_LONG(1, 2);
+
+ if (pistol == 1)
+ strcpy(c_item, "26"); // mk23
+ else
+ strcpy(c_item, "23"); // beretta
+
+ FakeClientCommand(pEdict, "pistols", c_item, NULL);
+
+ return;
+ }
+
+ if (pBot->start_action == MSG_FLF_WEAPON_SELECT)
+ {
+ int weapon_class;
+
+ pBot->start_action = MSG_FLF_IDLE; // switch back to idle
+
+ if (pBot->primary_weapon)
+ weapon_class = pBot->primary_weapon;
+ else
+ weapon_class = pBot->secondary_weapon;
+
+ if (weapon_class == FLF_WEAPON_SPAS12) // shotguns
+ strcpy(c_item, "shotgun");
+ else if ((weapon_class == FLF_WEAPON_MP5A2) || // submachine
+ (weapon_class == FLF_WEAPON_MP5SD) ||
+ (weapon_class == FLF_WEAPON_MAC10) ||
+ (weapon_class == FLF_WEAPON_UMP45))
+ strcpy(c_item, "submachine");
+ else if ((weapon_class == FLF_WEAPON_M4) ||
+ (weapon_class == FLF_WEAPON_FAMAS) ||
+ (weapon_class == FLF_WEAPON_AK5) ||
+ (weapon_class == FLF_WEAPON_MSG90))
+ strcpy(c_item, "rifles");
+ else
+ strcpy(c_item, "heavyweapons");
+
+ FakeClientCommand(pEdict, "wpnclass", c_item, NULL);
+
+ return;
+ }
+
+ if (pBot->start_action == MSG_FLF_SHOTGUN_SELECT)
+ {
+ int weapon_class;
+
+ pBot->start_action = MSG_FLF_IDLE; // switch back to idle
+
+ if (pBot->primary_weapon)
+ {
+ weapon_class = pBot->primary_weapon;
+ pBot->primary_weapon = 0;
+ }
+ else
+ {
+ weapon_class = pBot->secondary_weapon;
+
+ // bot has now joined the game (doesn't need to be started)
+ pBot->not_started = 0;
+ }
+
+ sprintf(c_item, "%d", weapon_class);
+
+ FakeClientCommand(pEdict, "shotgun", c_item, NULL);
+
+ return;
+ }
+
+ if (pBot->start_action == MSG_FLF_SUBMACHINE_SELECT)
+ {
+ int weapon_class;
+
+ pBot->start_action = MSG_FLF_IDLE; // switch back to idle
+
+ if (pBot->primary_weapon)
+ {
+ weapon_class = pBot->primary_weapon;
+ pBot->primary_weapon = 0;
+ }
+ else
+ {
+ weapon_class = pBot->secondary_weapon;
+
+ // bot has now joined the game (doesn't need to be started)
+ pBot->not_started = 0;
+ }
+
+ sprintf(c_item, "%d", weapon_class);
+
+ FakeClientCommand(pEdict, "submach", c_item, NULL);
+
+ return;
+ }
+
+ if (pBot->start_action == MSG_FLF_RIFLE_SELECT)
+ {
+ int weapon_class;
+
+ pBot->start_action = MSG_FLF_IDLE; // switch back to idle
+
+ if (pBot->primary_weapon)
+ {
+ weapon_class = pBot->primary_weapon;
+ pBot->primary_weapon = 0;
+ }
+ else
+ {
+ weapon_class = pBot->secondary_weapon;
+
+ // bot has now joined the game (doesn't need to be started)
+ pBot->not_started = 0;
+ }
+
+ sprintf(c_item, "%d", weapon_class);
+
+ FakeClientCommand(pEdict, "rifles", c_item, NULL);
+
+ return;
+ }
+
+ if (pBot->start_action == MSG_FLF_HEAVYWEAPONS_SELECT)
+ {
+ int weapon_class;
+
+ pBot->start_action = MSG_FLF_IDLE; // switch back to idle
+
+ if (pBot->primary_weapon)
+ {
+ weapon_class = pBot->primary_weapon;
+ pBot->primary_weapon = 0;
+ }
+ else
+ {
+ weapon_class = pBot->secondary_weapon;
+
+ // bot has now joined the game (doesn't need to be started)
+ pBot->not_started = 0;
+ }
+
+ sprintf(c_item, "%d", weapon_class);
+
+ FakeClientCommand(pEdict, "heavyweapons", c_item, NULL);
+
+ return;
+ }
+
+ }
+ else if (mod_id == AVH_DLL)
+ {
+// if(pBot->mBotPlayMode == PLAYMODE_READYROOM)
+// {
+// // Look at desired team and head to nearest start entity
+// AvHClassType theClassType = AVH_CLASS_TYPE_UNDEFINED;
+//// if(pBot->mBotRole == ROLE_UNDEFINED)
+//// {
+//// // Choose a random team
+//// theClassType = AvHClassType(RANDOM_LONG(1, 2));
+//// }
+//// else
+//// {
+//// theClassType = (AvHClassType)pBot->mBotRole;
+//// }
+////
+//// // Now navigate to the nearest start entity
+//// if(theClassType == AVH_CLASS_TYPE_MARINE)
+//// {
+// FakeClientCommand(pEdict, kcAutoAssign, c_item, NULL);
+// //FakeClientCommand(pEdict, kcJoinTeamOne, c_item, NULL);
+//
+// // Try to become a squad leader if possible
+//// pBot->pEdict->v.impulse = RANK_PROMOTE;
+//// }
+//// else if(theClassType == AVH_CLASS_TYPE_ALIEN)
+//// {
+//// FakeClientCommand(pEdict, kcJoinTeamTwo, c_item, NULL);
+//// }
+//
+// // bot has now joined the game (doesn't need to be started)
+// pBot->not_started = 0;
+// }
+ }
+ else
+ {
+ // otherwise, don't need to do anything to start game...
+ pBot->not_started = 0;
+ }
+}
+
diff --git a/main/source/HPB_bot/dlls/bot_weapons.h b/main/source/HPB_bot/dlls/bot_weapons.h
index 1c47d9db..afeb48a4 100644
--- a/main/source/HPB_bot/dlls/bot_weapons.h
+++ b/main/source/HPB_bot/dlls/bot_weapons.h
@@ -1,158 +1,158 @@
-//
-// HPB_bot - botman's High Ping Bastard bot
-//
-// (http://planethalflife.com/botman/)
-//
-// bot_weapons.h
-//
-
-#ifndef BOT_WEAPONS_H
-#define BOT_WEAPONS_H
-
-// weapon ID values for Valve's Half-Life Deathmatch
-#define VALVE_WEAPON_CROWBAR 1
-#define VALVE_WEAPON_GLOCK 2
-#define VALVE_WEAPON_PYTHON 3
-#define VALVE_WEAPON_MP5 4
-#define VALVE_WEAPON_CHAINGUN 5
-#define VALVE_WEAPON_CROSSBOW 6
-#define VALVE_WEAPON_SHOTGUN 7
-#define VALVE_WEAPON_RPG 8
-#define VALVE_WEAPON_GAUSS 9
-#define VALVE_WEAPON_EGON 10
-#define VALVE_WEAPON_HORNETGUN 11
-#define VALVE_WEAPON_HANDGRENADE 12
-#define VALVE_WEAPON_TRIPMINE 13
-#define VALVE_WEAPON_SATCHEL 14
-#define VALVE_WEAPON_SNARK 15
-
-#define VALVE_MAX_NORMAL_BATTERY 100
-#define VALVE_HORNET_MAX_CARRY 8
-
-
-// weapon ID values for Valve's Team Fortress Classic & 1.5
-#define TF_WEAPON_UNKNOWN1 1
-#define TF_WEAPON_UNKNOWN2 2
-#define TF_WEAPON_MEDIKIT 3
-#define TF_WEAPON_SPANNER 4
-#define TF_WEAPON_AXE 5
-#define TF_WEAPON_SNIPERRIFLE 6
-#define TF_WEAPON_AUTORIFLE 7
-#define TF_WEAPON_SHOTGUN 8
-#define TF_WEAPON_SUPERSHOTGUN 9
-#define TF_WEAPON_NAILGUN 10
-#define TF_WEAPON_SUPERNAILGUN 11
-#define TF_WEAPON_GL 12
-#define TF_WEAPON_FLAMETHROWER 13
-#define TF_WEAPON_RPG 14
-#define TF_WEAPON_IC 15
-#define TF_WEAPON_UNKNOWN16 16
-#define TF_WEAPON_AC 17
-#define TF_WEAPON_UNKNOWN18 18
-#define TF_WEAPON_UNKNOWN19 19
-#define TF_WEAPON_TRANQ 20
-#define TF_WEAPON_RAILGUN 21
-#define TF_WEAPON_PL 22
-#define TF_WEAPON_KNIFE 23
-
-
-// weapon ID values for Counter-Strike
-#define CS_WEAPON_P228 1
-#define CS_WEAPON_UNKNOWN2 2
-#define CS_WEAPON_SCOUT 3
-#define CS_WEAPON_HEGRENADE 4
-#define CS_WEAPON_XM1014 5
-#define CS_WEAPON_C4 6
-#define CS_WEAPON_MAC10 7
-#define CS_WEAPON_AUG 8
-#define CS_WEAPON_SMOKEGRENADE 9
-#define CS_WEAPON_ELITE 10
-#define CS_WEAPON_FIVESEVEN 11
-#define CS_WEAPON_UMP45 12
-#define CS_WEAPON_SG550 13
-#define CS_WEAPON_UNKNOWN14 14
-#define CS_WEAPON_UNKNOWN15 15
-#define CS_WEAPON_USP 16
-#define CS_WEAPON_GLOCK18 17
-#define CS_WEAPON_AWP 18
-#define CS_WEAPON_MP5NAVY 19
-#define CS_WEAPON_M249 20
-#define CS_WEAPON_M3 21
-#define CS_WEAPON_M4A1 22
-#define CS_WEAPON_TMP 23
-#define CS_WEAPON_G3SG1 24
-#define CS_WEAPON_FLASHBANG 25
-#define CS_WEAPON_DEAGLE 26
-#define CS_WEAPON_SG552 27
-#define CS_WEAPON_AK47 28
-#define CS_WEAPON_KNIFE 29
-#define CS_WEAPON_P90 30
-
-
-// weapon ID values for Gearbox's OpFor Deathmatch
-#define GEARBOX_WEAPON_CROWBAR 1
-#define GEARBOX_WEAPON_GLOCK 2
-#define GEARBOX_WEAPON_PYTHON 3
-#define GEARBOX_WEAPON_MP5 4
-#define GEARBOX_WEAPON_CHAINGUN 5
-#define GEARBOX_WEAPON_CROSSBOW 6
-#define GEARBOX_WEAPON_SHOTGUN 7
-#define GEARBOX_WEAPON_RPG 8
-#define GEARBOX_WEAPON_GAUSS 9
-#define GEARBOX_WEAPON_EGON 10
-#define GEARBOX_WEAPON_HORNETGUN 11
-#define GEARBOX_WEAPON_HANDGRENADE 12
-#define GEARBOX_WEAPON_TRIPMINE 13
-#define GEARBOX_WEAPON_SATCHEL 14
-#define GEARBOX_WEAPON_SNARK 15
-#define GEARBOX_WEAPON_GRAPPLE 16
-#define GEARBOX_WEAPON_EAGLE 17
-#define GEARBOX_WEAPON_PIPEWRENCH 18
-#define GEARBOX_WEAPON_M249 19
-#define GEARBOX_WEAPON_DISPLACER 20
-#define GEARBOX_WEAPON_UNKNOWN21 21
-#define GEARBOX_WEAPON_SHOCKRIFLE 22
-#define GEARBOX_WEAPON_SPORELAUNCHER 23
-#define GEARBOX_WEAPON_SNIPERRIFLE 24
-#define GEARBOX_WEAPON_KNIFE 25
-
-
-// weapon ID values for FrontLineForce
-#define FLF_WEAPON_AK5 10
-#define FLF_WEAPON_UNKNOWN11 11
-#define FLF_WEAPON_UNKNOWN12 12
-#define FLF_WEAPON_UNKNOWN13 13
-#define FLF_WEAPON_UNKNOWN14 14
-#define FLF_WEAPON_UNKNOWN15 15
-#define FLF_WEAPON_MP5SD 16
-#define FLF_WEAPON_M4 17
-#define FLF_WEAPON_FLASHBANG 18
-#define FLF_WEAPON_HEGRENADE 19
-#define FLF_WEAPON_MP5A2 20
-#define FLF_WEAPON_UMP45 21
-#define FLF_WEAPON_SPAS12 22
-#define FLF_WEAPON_BERETTA 23
-#define FLF_WEAPON_KNIFE 24
-#define FLF_WEAPON_MAC10 25
-#define FLF_WEAPON_MK23 26
-#define FLF_WEAPON_MSG90 27
-#define FLF_WEAPON_FAMAS 28
-#define FLF_WEAPON_HK21 29
-
-
-typedef struct
-{
- char szClassname[64];
- int iAmmo1; // ammo index for primary ammo
- int iAmmo1Max; // max primary ammo
- int iAmmo2; // ammo index for secondary ammo
- int iAmmo2Max; // max secondary ammo
- int iSlot; // HUD slot (0 based)
- int iPosition; // slot position
- int iId; // weapon ID
- int iFlags; // flags???
-} bot_weapon_t;
-
-
-#endif // BOT_WEAPONS_H
-
+//
+// HPB_bot - botman's High Ping Bastard bot
+//
+// (http://planethalflife.com/botman/)
+//
+// bot_weapons.h
+//
+
+#ifndef BOT_WEAPONS_H
+#define BOT_WEAPONS_H
+
+// weapon ID values for Valve's Half-Life Deathmatch
+#define VALVE_WEAPON_CROWBAR 1
+#define VALVE_WEAPON_GLOCK 2
+#define VALVE_WEAPON_PYTHON 3
+#define VALVE_WEAPON_MP5 4
+#define VALVE_WEAPON_CHAINGUN 5
+#define VALVE_WEAPON_CROSSBOW 6
+#define VALVE_WEAPON_SHOTGUN 7
+#define VALVE_WEAPON_RPG 8
+#define VALVE_WEAPON_GAUSS 9
+#define VALVE_WEAPON_EGON 10
+#define VALVE_WEAPON_HORNETGUN 11
+#define VALVE_WEAPON_HANDGRENADE 12
+#define VALVE_WEAPON_TRIPMINE 13
+#define VALVE_WEAPON_SATCHEL 14
+#define VALVE_WEAPON_SNARK 15
+
+#define VALVE_MAX_NORMAL_BATTERY 100
+#define VALVE_HORNET_MAX_CARRY 8
+
+
+// weapon ID values for Valve's Team Fortress Classic & 1.5
+#define TF_WEAPON_UNKNOWN1 1
+#define TF_WEAPON_UNKNOWN2 2
+#define TF_WEAPON_MEDIKIT 3
+#define TF_WEAPON_SPANNER 4
+#define TF_WEAPON_AXE 5
+#define TF_WEAPON_SNIPERRIFLE 6
+#define TF_WEAPON_AUTORIFLE 7
+#define TF_WEAPON_SHOTGUN 8
+#define TF_WEAPON_SUPERSHOTGUN 9
+#define TF_WEAPON_NAILGUN 10
+#define TF_WEAPON_SUPERNAILGUN 11
+#define TF_WEAPON_GL 12
+#define TF_WEAPON_FLAMETHROWER 13
+#define TF_WEAPON_RPG 14
+#define TF_WEAPON_IC 15
+#define TF_WEAPON_UNKNOWN16 16
+#define TF_WEAPON_AC 17
+#define TF_WEAPON_UNKNOWN18 18
+#define TF_WEAPON_UNKNOWN19 19
+#define TF_WEAPON_TRANQ 20
+#define TF_WEAPON_RAILGUN 21
+#define TF_WEAPON_PL 22
+#define TF_WEAPON_KNIFE 23
+
+
+// weapon ID values for Counter-Strike
+#define CS_WEAPON_P228 1
+#define CS_WEAPON_UNKNOWN2 2
+#define CS_WEAPON_SCOUT 3
+#define CS_WEAPON_HEGRENADE 4
+#define CS_WEAPON_XM1014 5
+#define CS_WEAPON_C4 6
+#define CS_WEAPON_MAC10 7
+#define CS_WEAPON_AUG 8
+#define CS_WEAPON_SMOKEGRENADE 9
+#define CS_WEAPON_ELITE 10
+#define CS_WEAPON_FIVESEVEN 11
+#define CS_WEAPON_UMP45 12
+#define CS_WEAPON_SG550 13
+#define CS_WEAPON_UNKNOWN14 14
+#define CS_WEAPON_UNKNOWN15 15
+#define CS_WEAPON_USP 16
+#define CS_WEAPON_GLOCK18 17
+#define CS_WEAPON_AWP 18
+#define CS_WEAPON_MP5NAVY 19
+#define CS_WEAPON_M249 20
+#define CS_WEAPON_M3 21
+#define CS_WEAPON_M4A1 22
+#define CS_WEAPON_TMP 23
+#define CS_WEAPON_G3SG1 24
+#define CS_WEAPON_FLASHBANG 25
+#define CS_WEAPON_DEAGLE 26
+#define CS_WEAPON_SG552 27
+#define CS_WEAPON_AK47 28
+#define CS_WEAPON_KNIFE 29
+#define CS_WEAPON_P90 30
+
+
+// weapon ID values for Gearbox's OpFor Deathmatch
+#define GEARBOX_WEAPON_CROWBAR 1
+#define GEARBOX_WEAPON_GLOCK 2
+#define GEARBOX_WEAPON_PYTHON 3
+#define GEARBOX_WEAPON_MP5 4
+#define GEARBOX_WEAPON_CHAINGUN 5
+#define GEARBOX_WEAPON_CROSSBOW 6
+#define GEARBOX_WEAPON_SHOTGUN 7
+#define GEARBOX_WEAPON_RPG 8
+#define GEARBOX_WEAPON_GAUSS 9
+#define GEARBOX_WEAPON_EGON 10
+#define GEARBOX_WEAPON_HORNETGUN 11
+#define GEARBOX_WEAPON_HANDGRENADE 12
+#define GEARBOX_WEAPON_TRIPMINE 13
+#define GEARBOX_WEAPON_SATCHEL 14
+#define GEARBOX_WEAPON_SNARK 15
+#define GEARBOX_WEAPON_GRAPPLE 16
+#define GEARBOX_WEAPON_EAGLE 17
+#define GEARBOX_WEAPON_PIPEWRENCH 18
+#define GEARBOX_WEAPON_M249 19
+#define GEARBOX_WEAPON_DISPLACER 20
+#define GEARBOX_WEAPON_UNKNOWN21 21
+#define GEARBOX_WEAPON_SHOCKRIFLE 22
+#define GEARBOX_WEAPON_SPORELAUNCHER 23
+#define GEARBOX_WEAPON_SNIPERRIFLE 24
+#define GEARBOX_WEAPON_KNIFE 25
+
+
+// weapon ID values for FrontLineForce
+#define FLF_WEAPON_AK5 10
+#define FLF_WEAPON_UNKNOWN11 11
+#define FLF_WEAPON_UNKNOWN12 12
+#define FLF_WEAPON_UNKNOWN13 13
+#define FLF_WEAPON_UNKNOWN14 14
+#define FLF_WEAPON_UNKNOWN15 15
+#define FLF_WEAPON_MP5SD 16
+#define FLF_WEAPON_M4 17
+#define FLF_WEAPON_FLASHBANG 18
+#define FLF_WEAPON_HEGRENADE 19
+#define FLF_WEAPON_MP5A2 20
+#define FLF_WEAPON_UMP45 21
+#define FLF_WEAPON_SPAS12 22
+#define FLF_WEAPON_BERETTA 23
+#define FLF_WEAPON_KNIFE 24
+#define FLF_WEAPON_MAC10 25
+#define FLF_WEAPON_MK23 26
+#define FLF_WEAPON_MSG90 27
+#define FLF_WEAPON_FAMAS 28
+#define FLF_WEAPON_HK21 29
+
+
+typedef struct
+{
+ char szClassname[64];
+ int iAmmo1; // ammo index for primary ammo
+ int iAmmo1Max; // max primary ammo
+ int iAmmo2; // ammo index for secondary ammo
+ int iAmmo2Max; // max secondary ammo
+ int iSlot; // HUD slot (0 based)
+ int iPosition; // slot position
+ int iId; // weapon ID
+ int iFlags; // flags???
+} bot_weapon_t;
+
+
+#endif // BOT_WEAPONS_H
+
diff --git a/main/source/HPB_bot/dlls/dll.cpp b/main/source/HPB_bot/dlls/dll.cpp
index 9cb8c342..55b6604a 100644
--- a/main/source/HPB_bot/dlls/dll.cpp
+++ b/main/source/HPB_bot/dlls/dll.cpp
@@ -1,1890 +1,1890 @@
-//
-// HPB bot - botman's High Ping Bastard bot
-//
-// (http://planethalflife.com/botman/)
-//
-// dll.cpp
-//
-
-#include "dlls/extdll.h"
-#include "dlls/enginecallback.h"
-#include "dlls/util.h"
-#include "dlls/cbase.h"
-#include "common/entity_state.h"
-
-#include "bot.h"
-#include "bot_func.h"
-#include "waypoint.h"
-#include "mod/AvHServerVariables.h"
-
-#define MENU_NONE 0
-#define MENU_1 1
-#define MENU_2 2
-#define MENU_3 3
-
-extern GETENTITYAPI other_GetEntityAPI;
-extern GETNEWDLLFUNCTIONS other_GetNewDLLFunctions;
-extern enginefuncs_t g_engfuncs;
-extern int debug_engine;
-extern globalvars_t *gpGlobals;
-extern char *g_argv;
-extern bool g_waypoint_on;
-extern bool g_auto_waypoint;
-extern bool g_path_waypoint;
-extern int num_waypoints; // number of waypoints currently in use
-extern WAYPOINT waypoints[MAX_WAYPOINTS];
-extern float wp_display_time[MAX_WAYPOINTS];
-extern bot_t bots[32];
-extern bool b_observer_mode;
-extern bool b_botdontshoot;
-//char welcome_msg[] = "HPB bot - http://planethalflife.com/botman";
-
-static FILE *fp;
-
-DLL_FUNCTIONS other_gFunctionTable;
-DLL_GLOBAL const Vector g_vecZero = Vector(0,0,0);
-
-// AvH dll
-int mod_id = AVH_DLL;
-int m_spriteTexture = 0;
-int default_bot_skill = 4;
-int isFakeClientCommand = 0;
-int fake_arg_count;
-float bot_check_time = 30.0;
-int min_bots = -1;
-int max_bots = -1;
-int num_bots = 0;
-int prev_num_bots = 0;
-bool g_GameRules = FALSE;
-edict_t *clients[32];
-edict_t *listenserver_edict = NULL;
-float welcome_time = 0.0;
-bool welcome_sent = FALSE;
-int g_menu_waypoint;
-int g_menu_state = 0;
-
-float is_team_play = 0.0;
-char team_names[MAX_TEAMS][MAX_TEAMNAME_LENGTH];
-int num_teams = 0;
-bool checked_teamplay = FALSE;
-edict_t *pent_info_tfdetect = NULL;
-edict_t *pent_info_ctfdetect = NULL;
-edict_t *pent_info_frontline = NULL;
-edict_t *pent_item_tfgoal = NULL;
-int max_team_players[4]; // for TFC
-int team_class_limits[4]; // for TFC
-int team_allies[4]; // TFC bit mapped allies BLUE, RED, YELLOW, and GREEN
-int max_teams = 0; // for TFC
-FLAG_S flags[MAX_FLAGS]; // for TFC
-int num_flags = 0; // for TFC
-
-FILE *bot_cfg_fp = NULL;
-bool need_to_open_cfg = TRUE;
-float bot_cfg_pause_time = 0.0;
-float respawn_time = 0.0;
-bool spawn_time_reset = FALSE;
-
-int flf_bug_fix; // for FLF 1.1 capture point bug
-int flf_bug_check; // for FLF 1.1 capture point bug
-
-
-char bot_whine[MAX_BOT_WHINE][81];
-int whine_count;
-int recent_bot_whine[5];
-
-cvar_t sv_bot = {"bot",""};
-cvar_t sv_freezebots = {"freezebots","0"};
-
-char *show_menu_1 =
- {"Waypoint Tags\n\n1. Team Specific\n2. Wait for Lift\n3. Door\n4. Sniper Spot\n5. More..."};
-char *show_menu_2 =
- {"Waypoint Tags\n\n1. Team 1\n2. Team 2\n3. Team 3\n4. Team 4\n5. CANCEL"};
-char *show_menu_2_flf =
- {"Waypoint Tags\n\n1. Attackers\n2. Defenders\n\n5. CANCEL"};
-char *show_menu_3 =
- {"Waypoint Tags\n\n1. Flag Location\n2. Flag Goal Location\n\n5. CANCEL"};
-char *show_menu_3_flf =
- {"Waypoint Tags\n\n1. Capture Point\n2. Defend Point\n3. Prone\n\n5. CANCEL"};
-
-
-void BotNameInit(void);
-void UpdateClientData(const struct edict_s *ent, int sendweapons, struct clientdata_s *cd);
-void ProcessBotCfgFile(void);
-
-
-void GameDLLInit( void )
-{
- char filename[256];
- char buffer[256];
- int i, length;
- FILE *bfp;
- char *ptr;
-
- CVAR_REGISTER (&sv_bot);
- CVAR_REGISTER (&sv_freezebots);
-
- for (i=0; i<32; i++)
- clients[i] = NULL;
-
- whine_count = 0;
-
- // initialize the bots array of structures...
- memset(bots, 0, sizeof(bots));
-
- for (i=0; i < 5; i++)
- recent_bot_whine[i] = -1;
-
- BotNameInit();
-
-
- UTIL_BuildFileName(filename, "bot_whine.txt", NULL);
-
- bfp = fopen(filename, "r");
-
- if (bfp != NULL)
- {
- while ((whine_count < MAX_BOT_WHINE) &&
- (fgets(buffer, 80, bfp) != NULL))
- {
- length = strlen(buffer);
-
- if (buffer[length-1] == '\n')
- {
- buffer[length-1] = 0; // remove '\n'
- length--;
- }
-
- if ((ptr = strstr(buffer, "%n")) != NULL)
- {
- *(ptr+1) = 's'; // change %n to %s
- }
-
- if (length > 0)
- {
- strcpy(bot_whine[whine_count], buffer);
- whine_count++;
- }
- }
-
- fclose(bfp);
- }
-
- (*other_gFunctionTable.pfnGameInit)();
-}
-
-int DispatchSpawn( edict_t *pent )
-{
- int index;
-
- if (gpGlobals->deathmatch)
- {
- char *pClassname = (char *)STRING(pent->v.classname);
-
- if (debug_engine)
- {
- fp=fopen("bot.txt","a");
- fprintf(fp, "DispatchSpawn: %x %s\n",pent,pClassname);
- if (pent->v.model != 0)
- fprintf(fp, " model=%s\n",STRING(pent->v.model));
- fclose(fp);
- }
-
- if (strcmp(pClassname, "worldspawn") == 0)
- {
- // do level initialization stuff here...
-
- WaypointInit();
- WaypointLoad(NULL);
-
- pent_info_tfdetect = NULL;
- pent_info_ctfdetect = NULL;
- pent_info_frontline = NULL;
- pent_item_tfgoal = NULL;
-
- for (index=0; index < 4; index++)
- {
- max_team_players[index] = 0; // no player limit
- team_class_limits[index] = 0; // no class limits
- team_allies[index] = 0;
- }
-
- max_teams = 0;
- num_flags = 0;
-
- PRECACHE_SOUND("weapons/xbow_hit1.wav"); // waypoint add
- PRECACHE_SOUND("weapons/mine_activate.wav"); // waypoint delete
- PRECACHE_SOUND("common/wpn_hudoff.wav"); // path add/delete start
- PRECACHE_SOUND("common/wpn_hudon.wav"); // path add/delete done
- PRECACHE_SOUND("common/wpn_moveselect.wav"); // path add/delete cancel
- PRECACHE_SOUND("common/wpn_denyselect.wav"); // path add/delete error
-
- m_spriteTexture = PRECACHE_MODEL( "sprites/lgtning.spr");
-
- g_GameRules = TRUE;
-
- is_team_play = 0.0;
- memset(team_names, 0, sizeof(team_names));
- num_teams = 0;
- checked_teamplay = FALSE;
-
- bot_cfg_pause_time = 0.0;
- respawn_time = 0.0;
- spawn_time_reset = FALSE;
-
- prev_num_bots = num_bots;
- num_bots = 0;
-
- flf_bug_fix = 0;
- flf_bug_check = 0;
-
- bot_check_time = gpGlobals->time + 30.0;
- }
- }
-
- return (*other_gFunctionTable.pfnSpawn)(pent);
-}
-
-void DispatchThink( edict_t *pent )
-{
- (*other_gFunctionTable.pfnThink)(pent);
-}
-
-void DispatchUse( edict_t *pentUsed, edict_t *pentOther )
-{
- (*other_gFunctionTable.pfnUse)(pentUsed, pentOther);
-}
-
-void DispatchTouch( edict_t *pentTouched, edict_t *pentOther )
-{
- (*other_gFunctionTable.pfnTouch)(pentTouched, pentOther);
-}
-
-void DispatchBlocked( edict_t *pentBlocked, edict_t *pentOther )
-{
- (*other_gFunctionTable.pfnBlocked)(pentBlocked, pentOther);
-}
-
-void DispatchKeyValue( edict_t *pentKeyvalue, KeyValueData *pkvd )
-{
- static edict_t *temp_pent;
- static int flag_index;
-
-// fp=fopen("bot.txt","a"); fprintf(fp, "DispatchKeyValue: %x %s=%s\n",pentKeyvalue,pkvd->szKeyName,pkvd->szValue); fclose(fp);
-
- if (mod_id == TFC_DLL)
- {
- if (pentKeyvalue == pent_info_tfdetect)
- {
- if (strcmp(pkvd->szKeyName, "ammo_medikit") == 0) // max BLUE players
- max_team_players[0] = atoi(pkvd->szValue);
- else if (strcmp(pkvd->szKeyName, "ammo_detpack") == 0) // max RED players
- max_team_players[1] = atoi(pkvd->szValue);
- else if (strcmp(pkvd->szKeyName, "maxammo_medikit") == 0) // max YELLOW players
- max_team_players[2] = atoi(pkvd->szValue);
- else if (strcmp(pkvd->szKeyName, "maxammo_detpack") == 0) // max GREEN players
- max_team_players[3] = atoi(pkvd->szValue);
-
- else if (strcmp(pkvd->szKeyName, "maxammo_shells") == 0) // BLUE class limits
- team_class_limits[0] = atoi(pkvd->szValue);
- else if (strcmp(pkvd->szKeyName, "maxammo_nails") == 0) // RED class limits
- team_class_limits[1] = atoi(pkvd->szValue);
- else if (strcmp(pkvd->szKeyName, "maxammo_rockets") == 0) // YELLOW class limits
- team_class_limits[2] = atoi(pkvd->szValue);
- else if (strcmp(pkvd->szKeyName, "maxammo_cells") == 0) // GREEN class limits
- team_class_limits[3] = atoi(pkvd->szValue);
-
- else if (strcmp(pkvd->szKeyName, "team1_allies") == 0) // BLUE allies
- team_allies[0] = atoi(pkvd->szValue);
- else if (strcmp(pkvd->szKeyName, "team2_allies") == 0) // RED allies
- team_allies[1] = atoi(pkvd->szValue);
- else if (strcmp(pkvd->szKeyName, "team3_allies") == 0) // YELLOW allies
- team_allies[2] = atoi(pkvd->szValue);
- else if (strcmp(pkvd->szKeyName, "team4_allies") == 0) // GREEN allies
- team_allies[3] = atoi(pkvd->szValue);
- }
- else if (pent_info_tfdetect == NULL)
- {
- if ((strcmp(pkvd->szKeyName, "classname") == 0) &&
- (strcmp(pkvd->szValue, "info_tfdetect") == 0))
- {
- pent_info_tfdetect = pentKeyvalue;
- }
- }
-
- if (pentKeyvalue == pent_item_tfgoal)
- {
- if (strcmp(pkvd->szKeyName, "team_no") == 0)
- flags[flag_index].team_no = atoi(pkvd->szValue);
-
- if ((strcmp(pkvd->szKeyName, "mdl") == 0) &&
- ((strcmp(pkvd->szValue, "models/flag.mdl") == 0) ||
- (strcmp(pkvd->szValue, "models/keycard.mdl") == 0) ||
- (strcmp(pkvd->szValue, "models/ball.mdl") == 0)))
- {
- flags[flag_index].mdl_match = TRUE;
- num_flags++;
- }
- }
- else if (pent_item_tfgoal == NULL)
- {
- if ((strcmp(pkvd->szKeyName, "classname") == 0) &&
- (strcmp(pkvd->szValue, "item_tfgoal") == 0))
- {
- if (num_flags < MAX_FLAGS)
- {
- pent_item_tfgoal = pentKeyvalue;
-
- flags[num_flags].mdl_match = FALSE;
- flags[num_flags].team_no = 0; // any team unless specified
- flags[num_flags].edict = pentKeyvalue;
-
- flag_index = num_flags; // in case the mdl comes before team_no
- }
- }
- }
- else
- {
- pent_item_tfgoal = NULL; // reset for non-flag item_tfgoal's
- }
-
- if ((strcmp(pkvd->szKeyName, "classname") == 0) &&
- ((strcmp(pkvd->szValue, "info_player_teamspawn") == 0) ||
- (strcmp(pkvd->szValue, "i_p_t") == 0)))
- {
- temp_pent = pentKeyvalue;
- }
- else if (pentKeyvalue == temp_pent)
- {
- if (strcmp(pkvd->szKeyName, "team_no") == 0)
- {
- int value = atoi(pkvd->szValue);
-
- if (value > max_teams)
- max_teams = value;
- }
- }
- }
- else if (mod_id == GEARBOX_DLL)
- {
- if (pent_info_ctfdetect == NULL)
- {
- if ((strcmp(pkvd->szKeyName, "classname") == 0) &&
- (strcmp(pkvd->szValue, "info_ctfdetect") == 0))
- {
- pent_info_ctfdetect = pentKeyvalue;
- }
- }
- }
-
- (*other_gFunctionTable.pfnKeyValue)(pentKeyvalue, pkvd);
-}
-
-void DispatchSave( edict_t *pent, SAVERESTOREDATA *pSaveData )
-{
- (*other_gFunctionTable.pfnSave)(pent, pSaveData);
-}
-
-int DispatchRestore( edict_t *pent, SAVERESTOREDATA *pSaveData, int globalEntity )
-{
- return (*other_gFunctionTable.pfnRestore)(pent, pSaveData, globalEntity);
-}
-
-void DispatchObjectCollsionBox( edict_t *pent )
-{
- (*other_gFunctionTable.pfnSetAbsBox)(pent);
-}
-
-void SaveWriteFields( SAVERESTOREDATA *pSaveData, const char *pname, void *pBaseData, TYPEDESCRIPTION *pFields, int fieldCount )
-{
- (*other_gFunctionTable.pfnSaveWriteFields)(pSaveData, pname, pBaseData, pFields, fieldCount);
-}
-
-void SaveReadFields( SAVERESTOREDATA *pSaveData, const char *pname, void *pBaseData, TYPEDESCRIPTION *pFields, int fieldCount )
-{
- (*other_gFunctionTable.pfnSaveReadFields)(pSaveData, pname, pBaseData, pFields, fieldCount);
-}
-
-void SaveGlobalState( SAVERESTOREDATA *pSaveData )
-{
- (*other_gFunctionTable.pfnSaveGlobalState)(pSaveData);
-}
-
-void RestoreGlobalState( SAVERESTOREDATA *pSaveData )
-{
- (*other_gFunctionTable.pfnRestoreGlobalState)(pSaveData);
-}
-
-void ResetGlobalState( void )
-{
- (*other_gFunctionTable.pfnResetGlobalState)();
-}
-
-BOOL ClientConnect( edict_t *pEntity, const char *pszName, const char *pszAddress, char szRejectReason[ 128 ] )
-{
- if (gpGlobals->deathmatch)
- {
- int i;
- int count = 0;
-
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp, "ClientConnect: pent=%x name=%s\n",pEntity,pszName); fclose(fp); }
-
- // check if this client is the listen server client
- if (strcmp(pszAddress, "loopback") == 0)
- {
- // save the edict of the listen server client...
- listenserver_edict = pEntity;
- }
-
- // check if this is NOT a bot joining the server...
- if (strcmp(pszAddress, "127.0.0.1") != 0)
- {
- // don't try to add bots for 60 seconds, give client time to get added
- bot_check_time = gpGlobals->time + 60.0;
-
- for (i=0; i < 32; i++)
- {
- if (bots[i].is_used) // count the number of bots in use
- count++;
- }
-
- // if there are currently more than the minimum number of bots running
- // then kick one of the bots off the server...
- if ((count > min_bots) && (min_bots != -1))
- {
- for (i=0; i < 32; i++)
- {
- if (bots[i].is_used) // is this slot used?
- {
- char cmd[80];
-
- sprintf(cmd, "kick \"%s\"\n", bots[i].name);
-
- SERVER_COMMAND(cmd); // kick the bot using (kick "name")
-
- break;
- }
- }
- }
- }
- }
-
- return (*other_gFunctionTable.pfnClientConnect)(pEntity, pszName, pszAddress, szRejectReason);
-}
-
-void ClientDisconnect( edict_t *pEntity )
-{
- if (gpGlobals->deathmatch)
- {
- int i;
-
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp, "ClientDisconnect: %x\n",pEntity); fclose(fp); }
-
- i = 0;
- while ((i < 32) && (clients[i] != pEntity))
- i++;
-
- if (i < 32)
- clients[i] = NULL;
-
-
- for (i=0; i < 32; i++)
- {
- if (bots[i].pEdict == pEntity)
- {
- // someone kicked this bot off of the server...
-
- bots[i].is_used = FALSE; // this slot is now free to use
-
- bots[i].kick_time = gpGlobals->time; // save the kicked time
-
- break;
- }
- }
- }
-
- (*other_gFunctionTable.pfnClientDisconnect)(pEntity);
-}
-
-void ClientKill( edict_t *pEntity )
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp, "ClientKill: %x\n",pEntity); fclose(fp); }
- (*other_gFunctionTable.pfnClientKill)(pEntity);
-}
-
-void ClientPutInServer( edict_t *pEntity )
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp, "ClientPutInServer: %x\n",pEntity); fclose(fp); }
-
- int i = 0;
-
- while ((i < 32) && (clients[i] != NULL))
- i++;
-
- if (i < 32)
- clients[i] = pEntity; // store this clients edict in the clients array
-
- (*other_gFunctionTable.pfnClientPutInServer)(pEntity);
-}
-
-void ClientCommand( edict_t *pEntity )
-{
- // only allow custom commands if deathmatch mode and NOT dedicated server and
- // client sending command is the listen server client...
-
- if ((gpGlobals->deathmatch) && /*(!IS_DEDICATED_SERVER()) &&*/
- (pEntity == listenserver_edict))
- {
- const char *pcmd = Cmd_Argv(0);
- const char *arg1 = Cmd_Argv(1);
- const char *arg2 = Cmd_Argv(2);
- const char *arg3 = Cmd_Argv(3);
- const char *arg4 = Cmd_Argv(4);
- char msg[80];
-
- if (debug_engine)
- {
- fp=fopen("bot.txt","a"); fprintf(fp,"ClientCommand: %s",pcmd);
- if ((arg1 != NULL) && (*arg1 != 0))
- fprintf(fp," %s", arg1);
- if ((arg2 != NULL) && (*arg2 != 0))
- fprintf(fp," %s", arg2);
- if ((arg3 != NULL) && (*arg3 != 0))
- fprintf(fp," %s", arg3);
- if ((arg4 != NULL) && (*arg4 != 0))
- fprintf(fp," %s", arg4);
- fprintf(fp, "\n");
- fclose(fp);
- }
-
- if (FStrEq(pcmd, "addbot"))
- {
- BotCreate( pEntity, arg1, arg2, arg3, arg4 );
-
- bot_check_time = gpGlobals->time + 5.0;
-
- return;
- }
- else if (FStrEq(pcmd, "observer"))
- {
- if ((arg1 != NULL) && (*arg1 != 0))
- {
- int temp = atoi(arg1);
- if (temp)
- b_observer_mode = TRUE;
- else
- b_observer_mode = FALSE;
- }
-
- if (b_observer_mode)
- ClientPrint(pEntity, HUD_PRINTNOTIFY, "observer mode ENABLED\n");
- else
- ClientPrint(pEntity, HUD_PRINTNOTIFY, "observer mode DISABLED\n");
-
- return;
- }
- else if (FStrEq(pcmd, "botskill"))
- {
- if ((arg1 != NULL) && (*arg1 != 0))
- {
- int temp = atoi(arg1);
-
- if ((temp < 1) || (temp > 5))
- ClientPrint(pEntity, HUD_PRINTNOTIFY, "invalid botskill value!\n");
- else
- default_bot_skill = temp;
- }
-
- sprintf(msg, "botskill is %d\n", default_bot_skill);
- ClientPrint(pEntity, HUD_PRINTNOTIFY, msg);
-
- return;
- }
- else if (FStrEq(pcmd, "botdontshoot"))
- {
- if ((arg1 != NULL) && (*arg1 != 0))
- {
- int temp = atoi(arg1);
- if (temp)
- b_botdontshoot = TRUE;
- else
- b_botdontshoot = FALSE;
- }
-
- if (b_botdontshoot)
- ClientPrint(pEntity, HUD_PRINTNOTIFY, "botdontshoot ENABLED\n");
- else
- ClientPrint(pEntity, HUD_PRINTNOTIFY, "botdontshoot DISABLED\n");
-
- return;
- }
- else if (FStrEq(pcmd, "debug_engine"))
- {
- debug_engine = 1;
-
- ClientPrint(pEntity, HUD_PRINTNOTIFY, "debug_engine enabled!\n");
-
- return;
- }
- else if (FStrEq(pcmd, "waypoint"))
- {
- if (FStrEq(arg1, "on"))
- {
- g_waypoint_on = TRUE;
-
- ClientPrint(pEntity, HUD_PRINTNOTIFY, "waypoints are ON\n");
- }
- else if (FStrEq(arg1, "off"))
- {
- g_waypoint_on = FALSE;
-
- ClientPrint(pEntity, HUD_PRINTNOTIFY, "waypoints are OFF\n");
- }
- else if (FStrEq(arg1, "add"))
- {
- if (!g_waypoint_on)
- g_waypoint_on = TRUE; // turn waypoints on if off
-
- WaypointAdd(pEntity);
- }
- else if (FStrEq(arg1, "delete"))
- {
- if (!g_waypoint_on)
- g_waypoint_on = TRUE; // turn waypoints on if off
-
- WaypointDelete(pEntity);
- }
- else if (FStrEq(arg1, "save"))
- {
- WaypointSave();
-
- ClientPrint(pEntity, HUD_PRINTNOTIFY, "waypoints saved\n");
- }
- else if (FStrEq(arg1, "load"))
- {
- if (WaypointLoad(pEntity))
- ClientPrint(pEntity, HUD_PRINTNOTIFY, "waypoints loaded\n");
- }
- else if (FStrEq(arg1, "menu"))
- {
- int index;
-
- if (num_waypoints < 1)
- return;
-
- index = WaypointFindNearest(pEntity, 50.0, -1);
-
- if (index == -1)
- return;
-
- g_menu_waypoint = index;
- g_menu_state = MENU_1;
-
- UTIL_ShowMenu(pEntity, 0x1F, -1, FALSE, show_menu_1);
- }
- else if (FStrEq(arg1, "info"))
- {
- WaypointPrintInfo(pEntity);
- }
- else
- {
- if (g_waypoint_on)
- ClientPrint(pEntity, HUD_PRINTNOTIFY, "waypoints are ON\n");
- else
- ClientPrint(pEntity, HUD_PRINTNOTIFY, "waypoints are OFF\n");
- }
-
- return;
- }
- else if (FStrEq(pcmd, "autowaypoint"))
- {
- if (FStrEq(arg1, "on"))
- {
- g_auto_waypoint = TRUE;
- g_waypoint_on = TRUE; // turn this on just in case
- }
- else if (FStrEq(arg1, "off"))
- {
- g_auto_waypoint = FALSE;
- }
-
- if (g_auto_waypoint)
- sprintf(msg, "autowaypoint is ON\n");
- else
- sprintf(msg, "autowaypoint is OFF\n");
-
- ClientPrint(pEntity, HUD_PRINTNOTIFY, msg);
-
- return;
- }
- else if (FStrEq(pcmd, "pathwaypoint"))
- {
- if (FStrEq(arg1, "on"))
- {
- g_path_waypoint = TRUE;
- g_waypoint_on = TRUE; // turn this on just in case
-
- ClientPrint(pEntity, HUD_PRINTNOTIFY, "pathwaypoint is ON\n");
- }
- else if (FStrEq(arg1, "off"))
- {
- g_path_waypoint = FALSE;
-
- ClientPrint(pEntity, HUD_PRINTNOTIFY, "pathwaypoint is OFF\n");
- }
- else if (FStrEq(arg1, "create1"))
- {
- WaypointCreatePath(pEntity, 1);
- }
- else if (FStrEq(arg1, "create2"))
- {
- WaypointCreatePath(pEntity, 2);
- }
- else if (FStrEq(arg1, "remove1"))
- {
- WaypointRemovePath(pEntity, 1);
- }
- else if (FStrEq(arg1, "remove2"))
- {
- WaypointRemovePath(pEntity, 2);
- }
-
- return;
- }
- else if (FStrEq(pcmd, "menuselect") && (g_menu_state != MENU_NONE))
- {
- if (g_menu_state == MENU_1) // main menu...
- {
- if (FStrEq(arg1, "1")) // team specific...
- {
- g_menu_state = MENU_2; // display team specific menu...
-
- if (mod_id == FRONTLINE_DLL)
- UTIL_ShowMenu(pEntity, 0x13, -1, FALSE, show_menu_2_flf);
- else
- UTIL_ShowMenu(pEntity, 0x1F, -1, FALSE, show_menu_2);
-
- return;
- }
- else if (FStrEq(arg1, "2")) // wait for lift...
- {
- if (waypoints[g_menu_waypoint].flags & W_FL_LIFT)
- waypoints[g_menu_waypoint].flags &= ~W_FL_LIFT; // off
- else
- waypoints[g_menu_waypoint].flags |= W_FL_LIFT; // on
- }
- else if (FStrEq(arg1, "3")) // door waypoint
- {
- if (waypoints[g_menu_waypoint].flags & W_FL_DOOR)
- waypoints[g_menu_waypoint].flags &= ~W_FL_DOOR; // off
- else
- waypoints[g_menu_waypoint].flags |= W_FL_DOOR; // on
- }
- else if (FStrEq(arg1, "4")) // sniper spot
- {
- if (waypoints[g_menu_waypoint].flags & W_FL_SNIPER)
- waypoints[g_menu_waypoint].flags &= ~W_FL_SNIPER; // off
- else
- {
- waypoints[g_menu_waypoint].flags |= W_FL_SNIPER; // on
-
- // set the aiming waypoint...
-
- WaypointAddAiming(pEntity);
- }
- }
- else if (FStrEq(arg1, "5")) // more...
- {
- g_menu_state = MENU_3;
-
- if (mod_id == FRONTLINE_DLL)
- UTIL_ShowMenu(pEntity, 0x17, -1, FALSE, show_menu_3_flf);
- else
- UTIL_ShowMenu(pEntity, 0x13, -1, FALSE, show_menu_3);
-
- return;
- }
- }
- else if (g_menu_state == MENU_2) // team specific menu
- {
- if (waypoints[g_menu_waypoint].flags & W_FL_TEAM_SPECIFIC)
- {
- waypoints[g_menu_waypoint].flags &= ~W_FL_TEAM;
- waypoints[g_menu_waypoint].flags &= ~W_FL_TEAM_SPECIFIC; // off
- }
- else
- {
- int team = atoi(arg1);
-
- team--; // make 0 to 3
-
- // this is kind of a kludge (team bits MUST be LSB!!!)
- waypoints[g_menu_waypoint].flags |= team;
- waypoints[g_menu_waypoint].flags |= W_FL_TEAM_SPECIFIC; // on
- }
- }
- else if (g_menu_state == MENU_3) // second menu...
- {
- if (mod_id == FRONTLINE_DLL)
- {
- if (FStrEq(arg1, "1")) // capture point
- {
- if (waypoints[g_menu_waypoint].flags & W_FL_FLF_CAP)
- waypoints[g_menu_waypoint].flags &= ~W_FL_FLF_CAP; // off
- else
- waypoints[g_menu_waypoint].flags |= W_FL_FLF_CAP; // on
- }
- else if (FStrEq(arg1, "2")) // defend point
- {
- if (waypoints[g_menu_waypoint].flags & W_FL_FLF_DEFEND)
- waypoints[g_menu_waypoint].flags &= ~W_FL_FLF_DEFEND; // off
- else
- {
- waypoints[g_menu_waypoint].flags |= W_FL_FLF_DEFEND; // on
-
- // set the aiming waypoint...
-
- WaypointAddAiming(pEntity);
- }
- }
- else if (FStrEq(arg1, "3")) // go prone
- {
- if (waypoints[g_menu_waypoint].flags & W_FL_PRONE)
- waypoints[g_menu_waypoint].flags &= ~W_FL_PRONE; // off
- else
- waypoints[g_menu_waypoint].flags |= W_FL_PRONE; // on
- }
- }
- else
- {
- if (FStrEq(arg1, "1")) // flag location
- {
- if (waypoints[g_menu_waypoint].flags & W_FL_TFC_FLAG)
- waypoints[g_menu_waypoint].flags &= ~W_FL_TFC_FLAG; // off
- else
- waypoints[g_menu_waypoint].flags |= W_FL_TFC_FLAG; // on
- }
- else if (FStrEq(arg1, "2")) // flag goal
- {
- if (waypoints[g_menu_waypoint].flags & W_FL_TFC_FLAG_GOAL)
- waypoints[g_menu_waypoint].flags &= ~W_FL_TFC_FLAG_GOAL; // off
- else
- waypoints[g_menu_waypoint].flags |= W_FL_TFC_FLAG_GOAL; // on
- }
- }
- }
-
- g_menu_state = MENU_NONE;
-
- return;
- }
- else if (FStrEq(pcmd, "search"))
- {
- edict_t *pent = NULL;
- float radius = 50;
- char str[80];
-
- ClientPrint(pEntity, HUD_PRINTCONSOLE, "searching...\n");
-
- while ((pent = UTIL_FindEntityInSphere( pent, pEntity->v.origin, radius )) != NULL)
- {
- sprintf(str, "Found %s at %5.2f %5.2f %5.2f\n",
- STRING(pent->v.classname),
- pent->v.origin.x, pent->v.origin.y,
- pent->v.origin.z);
- ClientPrint(pEntity, HUD_PRINTCONSOLE, str);
-
- FILE *fp=fopen("bot.txt", "a");
- fprintf(fp, "ClientCommmand: search %s", str);
- fclose(fp);
- }
-
- return;
- }
- }
-
- (*other_gFunctionTable.pfnClientCommand)(pEntity);
-}
-
-void ClientUserInfoChanged( edict_t *pEntity, char *infobuffer )
-{
- if (debug_engine) { fp=fopen("bot.txt", "a"); fprintf(fp, "ClientUserInfoChanged: pEntity=%x infobuffer=%s\n", pEntity, infobuffer); fclose(fp); }
-
- (*other_gFunctionTable.pfnClientUserInfoChanged)(pEntity, infobuffer);
-}
-
-void ServerActivate( edict_t *pEdictList, int edictCount, int clientMax )
-{
- (*other_gFunctionTable.pfnServerActivate)(pEdictList, edictCount, clientMax);
-}
-
-void ServerDeactivate( void )
-{
- (*other_gFunctionTable.pfnServerDeactivate)();
-}
-
-void PlayerPreThink( edict_t *pEntity )
-{
- (*other_gFunctionTable.pfnPlayerPreThink)(pEntity);
-}
-
-void PlayerPostThink( edict_t *pEntity )
-{
- (*other_gFunctionTable.pfnPlayerPostThink)(pEntity);
-}
-
-void StartFrame( void )
-{
- if (gpGlobals->deathmatch)
- {
- edict_t *pPlayer;
- static float check_server_cmd = 0.0;
- static int i, index, player_index, bot_index;
- static float previous_time = -1.0;
- static float client_update_time = 0.0;
- clientdata_s cd;
- char msg[256];
- int count;
-
- // if a new map has started then (MUST BE FIRST IN StartFrame)...
- if ((gpGlobals->time + 0.1) < previous_time)
- {
- char filename[256];
- char mapname[64];
-
- check_server_cmd = 0.0; // reset at start of map
-
- // check if mapname_bot.cfg file exists...
-
- strcpy(mapname, STRING(gpGlobals->mapname));
- strcat(mapname, "_bot.cfg");
-
- UTIL_BuildFileName(filename, "maps", mapname);
-
- if ((bot_cfg_fp = fopen(filename, "r")) != NULL)
- {
- sprintf(msg, "Executing %s\n", filename);
- ALERT( at_console, msg );
-
- for (index = 0; index < 32; index++)
- {
- bots[index].is_used = FALSE;
- bots[index].respawn_state = 0;
- bots[index].kick_time = 0.0;
- }
-
- if (IS_DEDICATED_SERVER())
- bot_cfg_pause_time = gpGlobals->time + 5.0;
- else
- bot_cfg_pause_time = gpGlobals->time + 20.0;
- }
- else
- {
- count = 0;
-
- // mark the bots as needing to be respawned...
- for (index = 0; index < 32; index++)
- {
- if (count >= prev_num_bots)
- {
- bots[index].is_used = FALSE;
- bots[index].respawn_state = 0;
- bots[index].kick_time = 0.0;
- }
-
- if (bots[index].is_used) // is this slot used?
- {
- bots[index].respawn_state = RESPAWN_NEED_TO_RESPAWN;
- count++;
- }
-
- // check for any bots that were very recently kicked...
- if ((bots[index].kick_time + 5.0) > previous_time)
- {
- bots[index].respawn_state = RESPAWN_NEED_TO_RESPAWN;
- count++;
- }
- else
- bots[index].kick_time = 0.0; // reset to prevent false spawns later
- }
-
- // set the respawn time
- if (IS_DEDICATED_SERVER())
- respawn_time = gpGlobals->time + 5.0;
- else
- respawn_time = gpGlobals->time + 20.0;
- }
-
- client_update_time = gpGlobals->time + 10.0; // start updating client data again
-
- bot_check_time = gpGlobals->time + 30.0;
- }
-
- if (!IS_DEDICATED_SERVER())
- {
- if ((listenserver_edict != NULL) && (welcome_sent == FALSE) &&
- (welcome_time < 1.0))
- {
- // are they out of observer mode yet?
- if (IsAlive(listenserver_edict))
- welcome_time = gpGlobals->time + 5.0; // welcome in 5 seconds
- }
-
- if ((welcome_time > 0.0) && (welcome_time < gpGlobals->time) &&
- (welcome_sent == FALSE))
- {
- // let's send a welcome message to this client...
- //UTIL_SayText(welcome_msg, listenserver_edict);
-
- welcome_sent = TRUE; // clear this so we only do it once
- }
- }
-
- if (client_update_time <= gpGlobals->time)
- {
- client_update_time = gpGlobals->time + 1.0;
-
- for (i=0; i < 32; i++)
- {
- if (bots[i].is_used)
- {
- memset(&cd, 0, sizeof(cd));
-
- UpdateClientData( bots[i].pEdict, 1, &cd );
-
- // see if a weapon was dropped...
- if (bots[i].bot_weapons != cd.weapons)
- {
- bots[i].bot_weapons = cd.weapons;
- }
- }
- }
- }
-
- count = 0;
-
- for (bot_index = 0; bot_index < gpGlobals->maxClients; bot_index++)
- {
- if ((bots[bot_index].is_used) && // is this slot used AND
- (bots[bot_index].respawn_state == RESPAWN_IDLE)) // not respawning
- {
- BotThink(&bots[bot_index]);
-
- count++;
-
- if ((mod_id == FRONTLINE_DLL) && (flf_bug_check == 0))
- {
- edict_t *pent = NULL;
- int fix_flag = 0;
-
- flf_bug_check = 1;
-
- while ((pent = UTIL_FindEntityByClassname( pent, "capture_point" )) != NULL)
- {
- if (pent->v.skin != 0) // not blue skin?
- {
- flf_bug_fix = 1; // need to use bug fix code
- }
- }
- }
- }
- }
-
- if (count > num_bots)
- num_bots = count;
-
- for (player_index = 1; player_index <= gpGlobals->maxClients; player_index++)
- {
- pPlayer = INDEXENT(player_index);
-
- if (pPlayer && !pPlayer->free)
- {
- if ((g_waypoint_on) && FBitSet(pPlayer->v.flags, FL_CLIENT))
- {
- WaypointThink(pPlayer);
- }
-
- if ((mod_id == FRONTLINE_DLL) && (flf_bug_check == 0))
- {
- edict_t *pent = NULL;
- int fix_flag = 0;
-
- flf_bug_check = 1;
-
- while ((pent = UTIL_FindEntityByClassname( pent, "capture_point" )) != NULL)
- {
- if (pent->v.skin != 0) // not blue skin?
- {
- flf_bug_fix = 1; // need to use bug fix code
- }
- }
- }
- }
- }
-
- // are we currently respawning bots and is it time to spawn one yet?
- if ((respawn_time > 1.0) && (respawn_time <= gpGlobals->time))
- {
- int index = 0;
-
- // find bot needing to be respawned...
- while ((index < 32) &&
- (bots[index].respawn_state != RESPAWN_NEED_TO_RESPAWN))
- index++;
-
- if (index < 32)
- {
- bots[index].respawn_state = RESPAWN_IS_RESPAWNING;
- bots[index].is_used = FALSE; // free up this slot
-
- // respawn 1 bot then wait a while (otherwise engine crashes)
- if ((mod_id == VALVE_DLL) ||
- ((mod_id == GEARBOX_DLL) && (pent_info_ctfdetect == NULL)))
- {
- char c_skill[2];
-
- sprintf(c_skill, "%d", bots[index].bot_skill);
-
- BotCreate(NULL, bots[index].skin, bots[index].name, c_skill, NULL);
- }
- else
- {
- char c_skill[2];
- char c_team[2];
- char c_class[3];
-
- sprintf(c_skill, "%d", bots[index].bot_skill);
- sprintf(c_team, "%d", bots[index].bot_team);
- sprintf(c_class, "%d", bots[index].bot_class);
-
- if ((mod_id == TFC_DLL) || (mod_id == GEARBOX_DLL))
- BotCreate(NULL, NULL, NULL, bots[index].name, c_skill);
- else
- BotCreate(NULL, c_team, c_class, bots[index].name, c_skill);
- }
-
- respawn_time = gpGlobals->time + 2.0; // set next respawn time
-
- bot_check_time = gpGlobals->time + 5.0;
- }
- else
- {
- respawn_time = 0.0;
- }
- }
-
- if (g_GameRules)
- {
- if (need_to_open_cfg) // have we open bot.cfg file yet?
- {
- char filename[256];
- char mapname[64];
-
- need_to_open_cfg = FALSE; // only do this once!!!
-
- // check if mapname_bot.cfg file exists...
-
- strcpy(mapname, STRING(gpGlobals->mapname));
- strcat(mapname, "_bot.cfg");
-
- UTIL_BuildFileName(filename, "maps", mapname);
-
- if ((bot_cfg_fp = fopen(filename, "r")) != NULL)
- {
- sprintf(msg, "Executing %s\n", filename);
- ALERT( at_console, msg );
- }
- else
- {
- UTIL_BuildFileName(filename, "bot.cfg", NULL);
-
- sprintf(msg, "Executing %s\n", filename);
- ALERT( at_console, msg );
-
- bot_cfg_fp = fopen(filename, "r");
-
- if (bot_cfg_fp == NULL)
- ALERT( at_console, "bot.cfg file not found\n" );
- }
-
- if (IS_DEDICATED_SERVER())
- bot_cfg_pause_time = gpGlobals->time + 5.0;
- else
- bot_cfg_pause_time = gpGlobals->time + 20.0;
- }
-
- if (!IS_DEDICATED_SERVER() && !spawn_time_reset)
- {
- if (listenserver_edict != NULL)
- {
- if (IsAlive(listenserver_edict))
- {
- spawn_time_reset = TRUE;
-
- if (respawn_time >= 1.0)
- respawn_time = min(respawn_time, gpGlobals->time + (float)1.0);
-
- if (bot_cfg_pause_time >= 1.0)
- bot_cfg_pause_time = min(bot_cfg_pause_time, gpGlobals->time + (float)1.0);
- }
- }
- }
-
- if ((bot_cfg_fp) &&
- (bot_cfg_pause_time >= 1.0) && (bot_cfg_pause_time <= gpGlobals->time))
- {
- // process bot.cfg file options...
- ProcessBotCfgFile();
- }
-
- }
-
- // if time to check for server commands then do so...
- if ((check_server_cmd <= gpGlobals->time) && IS_DEDICATED_SERVER())
- {
- check_server_cmd = gpGlobals->time + 1.0;
-
- char *cvar_bot = (char *)CVAR_GET_STRING( "bot" );
-
- if ( cvar_bot && cvar_bot[0] )
- {
- char cmd_line[80];
- char *cmd, *arg1, *arg2, *arg3, *arg4;
-
- strcpy(cmd_line, cvar_bot);
-
- index = 0;
- cmd = cmd_line;
- arg1 = arg2 = arg3 = arg4 = NULL;
-
- // skip to blank or end of string...
- while ((cmd_line[index] != ' ') && (cmd_line[index] != 0))
- index++;
-
- if (cmd_line[index] == ' ')
- {
- cmd_line[index++] = 0;
- arg1 = &cmd_line[index];
-
- // skip to blank or end of string...
- while ((cmd_line[index] != ' ') && (cmd_line[index] != 0))
- index++;
-
- if (cmd_line[index] == ' ')
- {
- cmd_line[index++] = 0;
- arg2 = &cmd_line[index];
-
- // skip to blank or end of string...
- while ((cmd_line[index] != ' ') && (cmd_line[index] != 0))
- index++;
-
- if (cmd_line[index] == ' ')
- {
- cmd_line[index++] = 0;
- arg3 = &cmd_line[index];
-
- // skip to blank or end of string...
- while ((cmd_line[index] != ' ') && (cmd_line[index] != 0))
- index++;
-
- if (cmd_line[index] == ' ')
- {
- cmd_line[index++] = 0;
- arg4 = &cmd_line[index];
- }
- }
- }
- }
-
- if (strcmp(cmd, "addbot") == 0)
- {
- BotCreate( NULL, arg1, arg2, arg3, arg4 );
-
- bot_check_time = gpGlobals->time + 5.0;
- }
- else if (strcmp(cmd, "min_bots") == 0)
- {
- min_bots = atoi( arg1 );
-
- if ((min_bots < 0) || (min_bots > 31))
- min_bots = 1;
-
- sprintf(msg, "min_bots set to %d\n", min_bots);
- printf(msg);
- }
- else if (strcmp(cmd, "max_bots") == 0)
- {
- max_bots = atoi( arg1 );
-
- if ((max_bots < 0) || (max_bots > 31))
- max_bots = 1;
-
- sprintf(msg, "max_bots set to %d\n", max_bots);
- printf(msg);
- }
-
- CVAR_SET_STRING("bot", "");
- }
- }
-
- // check if time to see if a bot needs to be created...
- if (bot_check_time < gpGlobals->time)
- {
- int count = 0;
-
- bot_check_time = gpGlobals->time + 5.0;
-
- for (i = 0; i < 32; i++)
- {
- if (clients[i] != NULL)
- count++;
- }
-
- // if there are currently less than the maximum number of "players"
- // then add another bot using the default skill level...
- if ((count < max_bots) && (max_bots != -1))
- {
- BotCreate( NULL, NULL, NULL, NULL, NULL );
- }
- }
-
- previous_time = gpGlobals->time;
- }
-
- (*other_gFunctionTable.pfnStartFrame)();
-}
-
-void ParmsNewLevel( void )
-{
- (*other_gFunctionTable.pfnParmsNewLevel)();
-}
-
-void ParmsChangeLevel( void )
-{
- (*other_gFunctionTable.pfnParmsChangeLevel)();
-}
-
-const char *GetGameDescription( void )
-{
- return (*other_gFunctionTable.pfnGetGameDescription)();
-}
-
-void PlayerCustomization( edict_t *pEntity, customization_t *pCust )
-{
- if (debug_engine) { fp=fopen("bot.txt", "a"); fprintf(fp, "PlayerCustomization: %x\n",pEntity); fclose(fp); }
-
- (*other_gFunctionTable.pfnPlayerCustomization)(pEntity, pCust);
-}
-
-void SpectatorConnect( edict_t *pEntity )
-{
- (*other_gFunctionTable.pfnSpectatorConnect)(pEntity);
-}
-
-void SpectatorDisconnect( edict_t *pEntity )
-{
- (*other_gFunctionTable.pfnSpectatorDisconnect)(pEntity);
-}
-
-void SpectatorThink( edict_t *pEntity )
-{
- (*other_gFunctionTable.pfnSpectatorThink)(pEntity);
-}
-
-void Sys_Error( const char *error_string )
-{
- (*other_gFunctionTable.pfnSys_Error)(error_string);
-}
-
-void PM_Move ( struct playermove_s *ppmove, int server )
-{
- (*other_gFunctionTable.pfnPM_Move)(ppmove, server);
-}
-
-void PM_Init ( struct playermove_s *ppmove )
-{
- (*other_gFunctionTable.pfnPM_Init)(ppmove);
-}
-
-char PM_FindTextureType( char *name )
-{
- return (*other_gFunctionTable.pfnPM_FindTextureType)(name);
-}
-
-void SetupVisibility( edict_t *pViewEntity, edict_t *pClient, unsigned char **pvs, unsigned char **pas )
-{
- (*other_gFunctionTable.pfnSetupVisibility)(pViewEntity, pClient, pvs, pas);
-}
-
-void UpdateClientData ( const struct edict_s *ent, int sendweapons, struct clientdata_s *cd )
-{
- (*other_gFunctionTable.pfnUpdateClientData)(ent, sendweapons, cd);
-}
-
-int AddToFullPack( struct entity_state_s *state, int e, edict_t *ent, edict_t *host, int hostflags, int player, unsigned char *pSet )
-{
- return (*other_gFunctionTable.pfnAddToFullPack)(state, e, ent, host, hostflags, player, pSet);
-}
-
-void CreateBaseline( int player, int eindex, struct entity_state_s *baseline, struct edict_s *entity, int playermodelindex, vec3_t player_mins, vec3_t player_maxs )
-{
- (*other_gFunctionTable.pfnCreateBaseline)(player, eindex, baseline, entity, playermodelindex, player_mins, player_maxs);
-}
-
-void RegisterEncoders( void )
-{
- (*other_gFunctionTable.pfnRegisterEncoders)();
-}
-
-int GetWeaponData( struct edict_s *player, struct weapon_data_s *info )
-{
- return (*other_gFunctionTable.pfnGetWeaponData)(player, info);
-}
-
-void CmdStart( const edict_t *player, const struct usercmd_s *cmd, unsigned int random_seed )
-{
- (*other_gFunctionTable.pfnCmdStart)(player, cmd, random_seed);
-}
-
-void CmdEnd ( const edict_t *player )
-{
- (*other_gFunctionTable.pfnCmdEnd)(player);
-}
-
-int ConnectionlessPacket( const struct netadr_s *net_from, const char *args, char *response_buffer, int *response_buffer_size )
-{
- return (*other_gFunctionTable.pfnConnectionlessPacket)(net_from, args, response_buffer, response_buffer_size);
-}
-
-int GetHullBounds( int hullnumber, float *mins, float *maxs )
-{
- return (*other_gFunctionTable.pfnGetHullBounds)(hullnumber, mins, maxs);
-}
-
-void CreateInstancedBaselines( void )
-{
- (*other_gFunctionTable.pfnCreateInstancedBaselines)();
-}
-
-int InconsistentFile( const edict_t *player, const char *filename, char *disconnect_message )
-{
- if (debug_engine) { fp=fopen("bot.txt", "a"); fprintf(fp, "InconsistentFile: %x filename=%s\n",player,filename); fclose(fp); }
-
- return (*other_gFunctionTable.pfnInconsistentFile)(player, filename, disconnect_message);
-}
-
-int AllowLagCompensation( void )
-{
- return (*other_gFunctionTable.pfnAllowLagCompensation)();
-}
-
-
-DLL_FUNCTIONS gFunctionTable =
-{
- GameDLLInit, //pfnGameInit
- DispatchSpawn, //pfnSpawn
- DispatchThink, //pfnThink
- DispatchUse, //pfnUse
- DispatchTouch, //pfnTouch
- DispatchBlocked, //pfnBlocked
- DispatchKeyValue, //pfnKeyValue
- DispatchSave, //pfnSave
- DispatchRestore, //pfnRestore
- DispatchObjectCollsionBox, //pfnAbsBox
-
- SaveWriteFields, //pfnSaveWriteFields
- SaveReadFields, //pfnSaveReadFields
-
- SaveGlobalState, //pfnSaveGlobalState
- RestoreGlobalState, //pfnRestoreGlobalState
- ResetGlobalState, //pfnResetGlobalState
-
- ClientConnect, //pfnClientConnect
- ClientDisconnect, //pfnClientDisconnect
- ClientKill, //pfnClientKill
- ClientPutInServer, //pfnClientPutInServer
- ClientCommand, //pfnClientCommand
- ClientUserInfoChanged, //pfnClientUserInfoChanged
- ServerActivate, //pfnServerActivate
- ServerDeactivate, //pfnServerDeactivate
-
- PlayerPreThink, //pfnPlayerPreThink
- PlayerPostThink, //pfnPlayerPostThink
-
- StartFrame, //pfnStartFrame
- ParmsNewLevel, //pfnParmsNewLevel
- ParmsChangeLevel, //pfnParmsChangeLevel
-
- GetGameDescription, //pfnGetGameDescription Returns string describing current .dll game.
- PlayerCustomization, //pfnPlayerCustomization Notifies .dll of new customization for player.
-
- SpectatorConnect, //pfnSpectatorConnect Called when spectator joins server
- SpectatorDisconnect, //pfnSpectatorDisconnect Called when spectator leaves the server
- SpectatorThink, //pfnSpectatorThink Called when spectator sends a command packet (usercmd_t)
-
- Sys_Error, //pfnSys_Error Called when engine has encountered an error
-
- PM_Move, //pfnPM_Move
- PM_Init, //pfnPM_Init Server version of player movement initialization
- PM_FindTextureType, //pfnPM_FindTextureType
-
- SetupVisibility, //pfnSetupVisibility Set up PVS and PAS for networking for this client
- UpdateClientData, //pfnUpdateClientData Set up data sent only to specific client
- AddToFullPack, //pfnAddToFullPack
- CreateBaseline, //pfnCreateBaseline Tweak entity baseline for network encoding, allows setup of player baselines, too.
- RegisterEncoders, //pfnRegisterEncoders Callbacks for network encoding
- GetWeaponData, //pfnGetWeaponData
- CmdStart, //pfnCmdStart
- CmdEnd, //pfnCmdEnd
- ConnectionlessPacket, //pfnConnectionlessPacket
- GetHullBounds, //pfnGetHullBounds
- CreateInstancedBaselines, //pfnCreateInstancedBaselines
- InconsistentFile, //pfnInconsistentFile
- AllowLagCompensation, //pfnAllowLagCompensation
-};
-
-#ifdef __BORLANDC__
-int EXPORT GetEntityAPI( DLL_FUNCTIONS *pFunctionTable, int interfaceVersion )
-#else
-extern "C" EXPORT int GetEntityAPI( DLL_FUNCTIONS *pFunctionTable, int interfaceVersion )
-#endif
-{
- // check if engine's pointer is valid and version is correct...
-
- if ( !pFunctionTable || interfaceVersion != INTERFACE_VERSION )
- return FALSE;
-
- // pass engine callback function table to engine...
- memcpy( pFunctionTable, &gFunctionTable, sizeof( DLL_FUNCTIONS ) );
-
- // pass other DLLs engine callbacks to function table...
- if (!(*other_GetEntityAPI)(&other_gFunctionTable, INTERFACE_VERSION))
- {
- return FALSE; // error initializing function table!!!
- }
-
- return TRUE;
-}
-
-
-#ifdef __BORLANDC__
-int EXPORT GetNewDLLFunctions( NEW_DLL_FUNCTIONS *pFunctionTable, int *interfaceVersion )
-#else
-extern "C" EXPORT int GetNewDLLFunctions( NEW_DLL_FUNCTIONS *pFunctionTable, int *interfaceVersion )
-#endif
-{
- if (other_GetNewDLLFunctions == NULL)
- return FALSE;
-
- // pass other DLLs engine callbacks to function table...
- if (!(*other_GetNewDLLFunctions)(pFunctionTable, interfaceVersion))
- {
- return FALSE; // error initializing function table!!!
- }
-
- return TRUE;
-}
-
-
-void FakeClientCommand(edict_t *pBot, char *arg1, char *arg2, char *arg3)
-{
- int length;
-
- memset(g_argv, 0, sizeof(g_argv));
-
- isFakeClientCommand = 1;
-
- if ((arg1 == NULL) || (*arg1 == 0))
- return;
-
- if ((arg2 == NULL) || (*arg2 == 0))
- {
- length = sprintf(&g_argv[0], "%s", arg1);
- fake_arg_count = 1;
- }
- else if ((arg3 == NULL) || (*arg3 == 0))
- {
- length = sprintf(&g_argv[0], "%s %s", arg1, arg2);
- fake_arg_count = 2;
- }
- else
- {
- length = sprintf(&g_argv[0], "%s %s %s", arg1, arg2, arg3);
- fake_arg_count = 3;
- }
-
- g_argv[length] = 0; // null terminate just in case
-
- strcpy(&g_argv[64], arg1);
-
- if (arg2)
- strcpy(&g_argv[128], arg2);
-
- if (arg3)
- strcpy(&g_argv[192], arg3);
-
- // allow the MOD DLL to execute the ClientCommand...
- ClientCommand(pBot);
-
- isFakeClientCommand = 0;
-}
-
-
-const char *Cmd_Args( void )
-{
- if (isFakeClientCommand)
- {
- return &g_argv[0];
- }
- else
- {
- return (*g_engfuncs.pfnCmd_Args)();
- }
-}
-
-
-const char *Cmd_Argv( int argc )
-{
- if (isFakeClientCommand)
- {
- if (argc == 0)
- {
- return &g_argv[64];
- }
- else if (argc == 1)
- {
- return &g_argv[128];
- }
- else if (argc == 2)
- {
- return &g_argv[192];
- }
- else
- {
- return NULL;
- }
- }
- else
- {
- return (*g_engfuncs.pfnCmd_Argv)(argc);
- }
-}
-
-
-int Cmd_Argc( void )
-{
- if (isFakeClientCommand)
- {
- return fake_arg_count;
- }
- else
- {
- return (*g_engfuncs.pfnCmd_Argc)();
- }
-}
-
-
-void ProcessBotCfgFile(void)
-{
- int ch;
- char cmd_line[256];
- int cmd_index;
- static char server_cmd[80];
- char *cmd, *arg1, *arg2, *arg3, *arg4;
- char msg[80];
-
- if (bot_cfg_pause_time > gpGlobals->time)
- return;
-
- if (bot_cfg_fp == NULL)
- return;
-
- cmd_index = 0;
- cmd_line[cmd_index] = 0;
-
- ch = fgetc(bot_cfg_fp);
-
- // skip any leading blanks
- while (ch == ' ')
- ch = fgetc(bot_cfg_fp);
-
- while ((ch != EOF) && (ch != '\r') && (ch != '\n'))
- {
- if (ch == '\t') // convert tabs to spaces
- ch = ' ';
-
- cmd_line[cmd_index] = ch;
-
- ch = fgetc(bot_cfg_fp);
-
- // skip multiple spaces in input file
- while ((cmd_line[cmd_index] == ' ') &&
- (ch == ' '))
- ch = fgetc(bot_cfg_fp);
-
- cmd_index++;
- }
-
- if (ch == '\r') // is it a carriage return?
- {
- ch = fgetc(bot_cfg_fp); // skip the linefeed
- }
-
- // if reached end of file, then close it
- if (ch == EOF)
- {
- fclose(bot_cfg_fp);
-
- bot_cfg_fp = NULL;
-
- bot_cfg_pause_time = 0.0;
- }
-
- cmd_line[cmd_index] = 0; // terminate the command line
-
- // copy the command line to a server command buffer...
- strcpy(server_cmd, cmd_line);
- strcat(server_cmd, "\n");
-
- cmd_index = 0;
- cmd = cmd_line;
- arg1 = arg2 = arg3 = arg4 = NULL;
-
- // skip to blank or end of string...
- while ((cmd_line[cmd_index] != ' ') && (cmd_line[cmd_index] != 0))
- cmd_index++;
-
- if (cmd_line[cmd_index] == ' ')
- {
- cmd_line[cmd_index++] = 0;
- arg1 = &cmd_line[cmd_index];
-
- // skip to blank or end of string...
- while ((cmd_line[cmd_index] != ' ') && (cmd_line[cmd_index] != 0))
- cmd_index++;
-
- if (cmd_line[cmd_index] == ' ')
- {
- cmd_line[cmd_index++] = 0;
- arg2 = &cmd_line[cmd_index];
-
- // skip to blank or end of string...
- while ((cmd_line[cmd_index] != ' ') && (cmd_line[cmd_index] != 0))
- cmd_index++;
-
- if (cmd_line[cmd_index] == ' ')
- {
- cmd_line[cmd_index++] = 0;
- arg3 = &cmd_line[cmd_index];
-
- // skip to blank or end of string...
- while ((cmd_line[cmd_index] != ' ') && (cmd_line[cmd_index] != 0))
- cmd_index++;
-
- if (cmd_line[cmd_index] == ' ')
- {
- cmd_line[cmd_index++] = 0;
- arg4 = &cmd_line[cmd_index];
- }
- }
- }
- }
-
- if ((cmd_line[0] == '#') || (cmd_line[0] == 0))
- return; // return if comment or blank line
-
- if (strcmp(cmd, "addbot") == 0)
- {
- BotCreate( NULL, arg1, arg2, arg3, arg4 );
-
- // have to delay here or engine gives "Tried to write to
- // uninitialized sizebuf_t" error and crashes...
-
- bot_cfg_pause_time = gpGlobals->time + 2.0;
- bot_check_time = gpGlobals->time + 5.0;
-
- return;
- }
-
- if (strcmp(cmd, "botskill") == 0)
- {
- int temp = atoi(arg1);
-
- if ((temp >= 1) && (temp <= 5))
- default_bot_skill = atoi( arg1 ); // set default bot skill level
-
- return;
- }
-
- if (strcmp(cmd, "observer") == 0)
- {
- int temp = atoi(arg1);
-
- if (temp)
- b_observer_mode = TRUE;
- else
- b_observer_mode = FALSE;
-
- return;
- }
-
- if (strcmp(cmd, "botdontshoot") == 0)
- {
- int temp = atoi(arg1);
-
- if (temp)
- b_botdontshoot = TRUE;
- else
- b_botdontshoot = FALSE;
-
- return;
- }
-
- if (strcmp(cmd, "min_bots") == 0)
- {
- min_bots = atoi( arg1 );
-
- if ((min_bots < 0) || (min_bots > 31))
- min_bots = 1;
-
- if (IS_DEDICATED_SERVER())
- {
- sprintf(msg, "min_bots set to %d\n", min_bots);
- printf(msg);
- }
-
- return;
- }
-
- if (strcmp(cmd, "max_bots") == 0)
- {
- max_bots = atoi( arg1 );
-
- if ((max_bots < 0) || (max_bots > 31))
- max_bots = 1;
-
- if (IS_DEDICATED_SERVER())
- {
- sprintf(msg, "max_bots set to %d\n", max_bots);
- printf(msg);
- }
-
- return;
- }
-
- if (strcmp(cmd, "pause") == 0)
- {
- bot_cfg_pause_time = gpGlobals->time + atoi( arg1 );
-
- return;
- }
-
- sprintf(msg, "executing server command: %s\n", server_cmd);
- ALERT( at_console, msg );
-
- if (IS_DEDICATED_SERVER())
- printf(msg);
-
- SERVER_COMMAND(server_cmd);
-}
-
+//
+// HPB bot - botman's High Ping Bastard bot
+//
+// (http://planethalflife.com/botman/)
+//
+// dll.cpp
+//
+
+#include "dlls/extdll.h"
+#include "dlls/enginecallback.h"
+#include "dlls/util.h"
+#include "dlls/cbase.h"
+#include "common/entity_state.h"
+
+#include "bot.h"
+#include "bot_func.h"
+#include "waypoint.h"
+#include "mod/AvHServerVariables.h"
+
+#define MENU_NONE 0
+#define MENU_1 1
+#define MENU_2 2
+#define MENU_3 3
+
+extern GETENTITYAPI other_GetEntityAPI;
+extern GETNEWDLLFUNCTIONS other_GetNewDLLFunctions;
+extern enginefuncs_t g_engfuncs;
+extern int debug_engine;
+extern globalvars_t *gpGlobals;
+extern char *g_argv;
+extern bool g_waypoint_on;
+extern bool g_auto_waypoint;
+extern bool g_path_waypoint;
+extern int num_waypoints; // number of waypoints currently in use
+extern WAYPOINT waypoints[MAX_WAYPOINTS];
+extern float wp_display_time[MAX_WAYPOINTS];
+extern bot_t bots[32];
+extern bool b_observer_mode;
+extern bool b_botdontshoot;
+//char welcome_msg[] = "HPB bot - http://planethalflife.com/botman";
+
+static FILE *fp;
+
+DLL_FUNCTIONS other_gFunctionTable;
+DLL_GLOBAL const Vector g_vecZero = Vector(0,0,0);
+
+// AvH dll
+int mod_id = AVH_DLL;
+int m_spriteTexture = 0;
+int default_bot_skill = 4;
+int isFakeClientCommand = 0;
+int fake_arg_count;
+float bot_check_time = 30.0;
+int min_bots = -1;
+int max_bots = -1;
+int num_bots = 0;
+int prev_num_bots = 0;
+bool g_GameRules = FALSE;
+edict_t *clients[32];
+edict_t *listenserver_edict = NULL;
+float welcome_time = 0.0;
+bool welcome_sent = FALSE;
+int g_menu_waypoint;
+int g_menu_state = 0;
+
+float is_team_play = 0.0;
+char team_names[MAX_TEAMS][MAX_TEAMNAME_LENGTH];
+int num_teams = 0;
+bool checked_teamplay = FALSE;
+edict_t *pent_info_tfdetect = NULL;
+edict_t *pent_info_ctfdetect = NULL;
+edict_t *pent_info_frontline = NULL;
+edict_t *pent_item_tfgoal = NULL;
+int max_team_players[4]; // for TFC
+int team_class_limits[4]; // for TFC
+int team_allies[4]; // TFC bit mapped allies BLUE, RED, YELLOW, and GREEN
+int max_teams = 0; // for TFC
+FLAG_S flags[MAX_FLAGS]; // for TFC
+int num_flags = 0; // for TFC
+
+FILE *bot_cfg_fp = NULL;
+bool need_to_open_cfg = TRUE;
+float bot_cfg_pause_time = 0.0;
+float respawn_time = 0.0;
+bool spawn_time_reset = FALSE;
+
+int flf_bug_fix; // for FLF 1.1 capture point bug
+int flf_bug_check; // for FLF 1.1 capture point bug
+
+
+char bot_whine[MAX_BOT_WHINE][81];
+int whine_count;
+int recent_bot_whine[5];
+
+cvar_t sv_bot = {"bot",""};
+cvar_t sv_freezebots = {"freezebots","0"};
+
+char *show_menu_1 =
+ {"Waypoint Tags\n\n1. Team Specific\n2. Wait for Lift\n3. Door\n4. Sniper Spot\n5. More..."};
+char *show_menu_2 =
+ {"Waypoint Tags\n\n1. Team 1\n2. Team 2\n3. Team 3\n4. Team 4\n5. CANCEL"};
+char *show_menu_2_flf =
+ {"Waypoint Tags\n\n1. Attackers\n2. Defenders\n\n5. CANCEL"};
+char *show_menu_3 =
+ {"Waypoint Tags\n\n1. Flag Location\n2. Flag Goal Location\n\n5. CANCEL"};
+char *show_menu_3_flf =
+ {"Waypoint Tags\n\n1. Capture Point\n2. Defend Point\n3. Prone\n\n5. CANCEL"};
+
+
+void BotNameInit(void);
+void UpdateClientData(const struct edict_s *ent, int sendweapons, struct clientdata_s *cd);
+void ProcessBotCfgFile(void);
+
+
+void GameDLLInit( void )
+{
+ char filename[256];
+ char buffer[256];
+ int i, length;
+ FILE *bfp;
+ char *ptr;
+
+ CVAR_REGISTER (&sv_bot);
+ CVAR_REGISTER (&sv_freezebots);
+
+ for (i=0; i<32; i++)
+ clients[i] = NULL;
+
+ whine_count = 0;
+
+ // initialize the bots array of structures...
+ memset(bots, 0, sizeof(bots));
+
+ for (i=0; i < 5; i++)
+ recent_bot_whine[i] = -1;
+
+ BotNameInit();
+
+
+ UTIL_BuildFileName(filename, "bot_whine.txt", NULL);
+
+ bfp = fopen(filename, "r");
+
+ if (bfp != NULL)
+ {
+ while ((whine_count < MAX_BOT_WHINE) &&
+ (fgets(buffer, 80, bfp) != NULL))
+ {
+ length = strlen(buffer);
+
+ if (buffer[length-1] == '\n')
+ {
+ buffer[length-1] = 0; // remove '\n'
+ length--;
+ }
+
+ if ((ptr = strstr(buffer, "%n")) != NULL)
+ {
+ *(ptr+1) = 's'; // change %n to %s
+ }
+
+ if (length > 0)
+ {
+ strcpy(bot_whine[whine_count], buffer);
+ whine_count++;
+ }
+ }
+
+ fclose(bfp);
+ }
+
+ (*other_gFunctionTable.pfnGameInit)();
+}
+
+int DispatchSpawn( edict_t *pent )
+{
+ int index;
+
+ if (gpGlobals->deathmatch)
+ {
+ char *pClassname = (char *)STRING(pent->v.classname);
+
+ if (debug_engine)
+ {
+ fp=fopen("bot.txt","a");
+ fprintf(fp, "DispatchSpawn: %x %s\n",pent,pClassname);
+ if (pent->v.model != 0)
+ fprintf(fp, " model=%s\n",STRING(pent->v.model));
+ fclose(fp);
+ }
+
+ if (strcmp(pClassname, "worldspawn") == 0)
+ {
+ // do level initialization stuff here...
+
+ WaypointInit();
+ WaypointLoad(NULL);
+
+ pent_info_tfdetect = NULL;
+ pent_info_ctfdetect = NULL;
+ pent_info_frontline = NULL;
+ pent_item_tfgoal = NULL;
+
+ for (index=0; index < 4; index++)
+ {
+ max_team_players[index] = 0; // no player limit
+ team_class_limits[index] = 0; // no class limits
+ team_allies[index] = 0;
+ }
+
+ max_teams = 0;
+ num_flags = 0;
+
+ PRECACHE_SOUND("weapons/xbow_hit1.wav"); // waypoint add
+ PRECACHE_SOUND("weapons/mine_activate.wav"); // waypoint delete
+ PRECACHE_SOUND("common/wpn_hudoff.wav"); // path add/delete start
+ PRECACHE_SOUND("common/wpn_hudon.wav"); // path add/delete done
+ PRECACHE_SOUND("common/wpn_moveselect.wav"); // path add/delete cancel
+ PRECACHE_SOUND("common/wpn_denyselect.wav"); // path add/delete error
+
+ m_spriteTexture = PRECACHE_MODEL( "sprites/lgtning.spr");
+
+ g_GameRules = TRUE;
+
+ is_team_play = 0.0;
+ memset(team_names, 0, sizeof(team_names));
+ num_teams = 0;
+ checked_teamplay = FALSE;
+
+ bot_cfg_pause_time = 0.0;
+ respawn_time = 0.0;
+ spawn_time_reset = FALSE;
+
+ prev_num_bots = num_bots;
+ num_bots = 0;
+
+ flf_bug_fix = 0;
+ flf_bug_check = 0;
+
+ bot_check_time = gpGlobals->time + 30.0;
+ }
+ }
+
+ return (*other_gFunctionTable.pfnSpawn)(pent);
+}
+
+void DispatchThink( edict_t *pent )
+{
+ (*other_gFunctionTable.pfnThink)(pent);
+}
+
+void DispatchUse( edict_t *pentUsed, edict_t *pentOther )
+{
+ (*other_gFunctionTable.pfnUse)(pentUsed, pentOther);
+}
+
+void DispatchTouch( edict_t *pentTouched, edict_t *pentOther )
+{
+ (*other_gFunctionTable.pfnTouch)(pentTouched, pentOther);
+}
+
+void DispatchBlocked( edict_t *pentBlocked, edict_t *pentOther )
+{
+ (*other_gFunctionTable.pfnBlocked)(pentBlocked, pentOther);
+}
+
+void DispatchKeyValue( edict_t *pentKeyvalue, KeyValueData *pkvd )
+{
+ static edict_t *temp_pent;
+ static int flag_index;
+
+// fp=fopen("bot.txt","a"); fprintf(fp, "DispatchKeyValue: %x %s=%s\n",pentKeyvalue,pkvd->szKeyName,pkvd->szValue); fclose(fp);
+
+ if (mod_id == TFC_DLL)
+ {
+ if (pentKeyvalue == pent_info_tfdetect)
+ {
+ if (strcmp(pkvd->szKeyName, "ammo_medikit") == 0) // max BLUE players
+ max_team_players[0] = atoi(pkvd->szValue);
+ else if (strcmp(pkvd->szKeyName, "ammo_detpack") == 0) // max RED players
+ max_team_players[1] = atoi(pkvd->szValue);
+ else if (strcmp(pkvd->szKeyName, "maxammo_medikit") == 0) // max YELLOW players
+ max_team_players[2] = atoi(pkvd->szValue);
+ else if (strcmp(pkvd->szKeyName, "maxammo_detpack") == 0) // max GREEN players
+ max_team_players[3] = atoi(pkvd->szValue);
+
+ else if (strcmp(pkvd->szKeyName, "maxammo_shells") == 0) // BLUE class limits
+ team_class_limits[0] = atoi(pkvd->szValue);
+ else if (strcmp(pkvd->szKeyName, "maxammo_nails") == 0) // RED class limits
+ team_class_limits[1] = atoi(pkvd->szValue);
+ else if (strcmp(pkvd->szKeyName, "maxammo_rockets") == 0) // YELLOW class limits
+ team_class_limits[2] = atoi(pkvd->szValue);
+ else if (strcmp(pkvd->szKeyName, "maxammo_cells") == 0) // GREEN class limits
+ team_class_limits[3] = atoi(pkvd->szValue);
+
+ else if (strcmp(pkvd->szKeyName, "team1_allies") == 0) // BLUE allies
+ team_allies[0] = atoi(pkvd->szValue);
+ else if (strcmp(pkvd->szKeyName, "team2_allies") == 0) // RED allies
+ team_allies[1] = atoi(pkvd->szValue);
+ else if (strcmp(pkvd->szKeyName, "team3_allies") == 0) // YELLOW allies
+ team_allies[2] = atoi(pkvd->szValue);
+ else if (strcmp(pkvd->szKeyName, "team4_allies") == 0) // GREEN allies
+ team_allies[3] = atoi(pkvd->szValue);
+ }
+ else if (pent_info_tfdetect == NULL)
+ {
+ if ((strcmp(pkvd->szKeyName, "classname") == 0) &&
+ (strcmp(pkvd->szValue, "info_tfdetect") == 0))
+ {
+ pent_info_tfdetect = pentKeyvalue;
+ }
+ }
+
+ if (pentKeyvalue == pent_item_tfgoal)
+ {
+ if (strcmp(pkvd->szKeyName, "team_no") == 0)
+ flags[flag_index].team_no = atoi(pkvd->szValue);
+
+ if ((strcmp(pkvd->szKeyName, "mdl") == 0) &&
+ ((strcmp(pkvd->szValue, "models/flag.mdl") == 0) ||
+ (strcmp(pkvd->szValue, "models/keycard.mdl") == 0) ||
+ (strcmp(pkvd->szValue, "models/ball.mdl") == 0)))
+ {
+ flags[flag_index].mdl_match = TRUE;
+ num_flags++;
+ }
+ }
+ else if (pent_item_tfgoal == NULL)
+ {
+ if ((strcmp(pkvd->szKeyName, "classname") == 0) &&
+ (strcmp(pkvd->szValue, "item_tfgoal") == 0))
+ {
+ if (num_flags < MAX_FLAGS)
+ {
+ pent_item_tfgoal = pentKeyvalue;
+
+ flags[num_flags].mdl_match = FALSE;
+ flags[num_flags].team_no = 0; // any team unless specified
+ flags[num_flags].edict = pentKeyvalue;
+
+ flag_index = num_flags; // in case the mdl comes before team_no
+ }
+ }
+ }
+ else
+ {
+ pent_item_tfgoal = NULL; // reset for non-flag item_tfgoal's
+ }
+
+ if ((strcmp(pkvd->szKeyName, "classname") == 0) &&
+ ((strcmp(pkvd->szValue, "info_player_teamspawn") == 0) ||
+ (strcmp(pkvd->szValue, "i_p_t") == 0)))
+ {
+ temp_pent = pentKeyvalue;
+ }
+ else if (pentKeyvalue == temp_pent)
+ {
+ if (strcmp(pkvd->szKeyName, "team_no") == 0)
+ {
+ int value = atoi(pkvd->szValue);
+
+ if (value > max_teams)
+ max_teams = value;
+ }
+ }
+ }
+ else if (mod_id == GEARBOX_DLL)
+ {
+ if (pent_info_ctfdetect == NULL)
+ {
+ if ((strcmp(pkvd->szKeyName, "classname") == 0) &&
+ (strcmp(pkvd->szValue, "info_ctfdetect") == 0))
+ {
+ pent_info_ctfdetect = pentKeyvalue;
+ }
+ }
+ }
+
+ (*other_gFunctionTable.pfnKeyValue)(pentKeyvalue, pkvd);
+}
+
+void DispatchSave( edict_t *pent, SAVERESTOREDATA *pSaveData )
+{
+ (*other_gFunctionTable.pfnSave)(pent, pSaveData);
+}
+
+int DispatchRestore( edict_t *pent, SAVERESTOREDATA *pSaveData, int globalEntity )
+{
+ return (*other_gFunctionTable.pfnRestore)(pent, pSaveData, globalEntity);
+}
+
+void DispatchObjectCollsionBox( edict_t *pent )
+{
+ (*other_gFunctionTable.pfnSetAbsBox)(pent);
+}
+
+void SaveWriteFields( SAVERESTOREDATA *pSaveData, const char *pname, void *pBaseData, TYPEDESCRIPTION *pFields, int fieldCount )
+{
+ (*other_gFunctionTable.pfnSaveWriteFields)(pSaveData, pname, pBaseData, pFields, fieldCount);
+}
+
+void SaveReadFields( SAVERESTOREDATA *pSaveData, const char *pname, void *pBaseData, TYPEDESCRIPTION *pFields, int fieldCount )
+{
+ (*other_gFunctionTable.pfnSaveReadFields)(pSaveData, pname, pBaseData, pFields, fieldCount);
+}
+
+void SaveGlobalState( SAVERESTOREDATA *pSaveData )
+{
+ (*other_gFunctionTable.pfnSaveGlobalState)(pSaveData);
+}
+
+void RestoreGlobalState( SAVERESTOREDATA *pSaveData )
+{
+ (*other_gFunctionTable.pfnRestoreGlobalState)(pSaveData);
+}
+
+void ResetGlobalState( void )
+{
+ (*other_gFunctionTable.pfnResetGlobalState)();
+}
+
+BOOL ClientConnect( edict_t *pEntity, const char *pszName, const char *pszAddress, char szRejectReason[ 128 ] )
+{
+ if (gpGlobals->deathmatch)
+ {
+ int i;
+ int count = 0;
+
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp, "ClientConnect: pent=%x name=%s\n",pEntity,pszName); fclose(fp); }
+
+ // check if this client is the listen server client
+ if (strcmp(pszAddress, "loopback") == 0)
+ {
+ // save the edict of the listen server client...
+ listenserver_edict = pEntity;
+ }
+
+ // check if this is NOT a bot joining the server...
+ if (strcmp(pszAddress, "127.0.0.1") != 0)
+ {
+ // don't try to add bots for 60 seconds, give client time to get added
+ bot_check_time = gpGlobals->time + 60.0;
+
+ for (i=0; i < 32; i++)
+ {
+ if (bots[i].is_used) // count the number of bots in use
+ count++;
+ }
+
+ // if there are currently more than the minimum number of bots running
+ // then kick one of the bots off the server...
+ if ((count > min_bots) && (min_bots != -1))
+ {
+ for (i=0; i < 32; i++)
+ {
+ if (bots[i].is_used) // is this slot used?
+ {
+ char cmd[80];
+
+ sprintf(cmd, "kick \"%s\"\n", bots[i].name);
+
+ SERVER_COMMAND(cmd); // kick the bot using (kick "name")
+
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ return (*other_gFunctionTable.pfnClientConnect)(pEntity, pszName, pszAddress, szRejectReason);
+}
+
+void ClientDisconnect( edict_t *pEntity )
+{
+ if (gpGlobals->deathmatch)
+ {
+ int i;
+
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp, "ClientDisconnect: %x\n",pEntity); fclose(fp); }
+
+ i = 0;
+ while ((i < 32) && (clients[i] != pEntity))
+ i++;
+
+ if (i < 32)
+ clients[i] = NULL;
+
+
+ for (i=0; i < 32; i++)
+ {
+ if (bots[i].pEdict == pEntity)
+ {
+ // someone kicked this bot off of the server...
+
+ bots[i].is_used = FALSE; // this slot is now free to use
+
+ bots[i].kick_time = gpGlobals->time; // save the kicked time
+
+ break;
+ }
+ }
+ }
+
+ (*other_gFunctionTable.pfnClientDisconnect)(pEntity);
+}
+
+void ClientKill( edict_t *pEntity )
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp, "ClientKill: %x\n",pEntity); fclose(fp); }
+ (*other_gFunctionTable.pfnClientKill)(pEntity);
+}
+
+void ClientPutInServer( edict_t *pEntity )
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp, "ClientPutInServer: %x\n",pEntity); fclose(fp); }
+
+ int i = 0;
+
+ while ((i < 32) && (clients[i] != NULL))
+ i++;
+
+ if (i < 32)
+ clients[i] = pEntity; // store this clients edict in the clients array
+
+ (*other_gFunctionTable.pfnClientPutInServer)(pEntity);
+}
+
+void ClientCommand( edict_t *pEntity )
+{
+ // only allow custom commands if deathmatch mode and NOT dedicated server and
+ // client sending command is the listen server client...
+
+ if ((gpGlobals->deathmatch) && /*(!IS_DEDICATED_SERVER()) &&*/
+ (pEntity == listenserver_edict))
+ {
+ const char *pcmd = Cmd_Argv(0);
+ const char *arg1 = Cmd_Argv(1);
+ const char *arg2 = Cmd_Argv(2);
+ const char *arg3 = Cmd_Argv(3);
+ const char *arg4 = Cmd_Argv(4);
+ char msg[80];
+
+ if (debug_engine)
+ {
+ fp=fopen("bot.txt","a"); fprintf(fp,"ClientCommand: %s",pcmd);
+ if ((arg1 != NULL) && (*arg1 != 0))
+ fprintf(fp," %s", arg1);
+ if ((arg2 != NULL) && (*arg2 != 0))
+ fprintf(fp," %s", arg2);
+ if ((arg3 != NULL) && (*arg3 != 0))
+ fprintf(fp," %s", arg3);
+ if ((arg4 != NULL) && (*arg4 != 0))
+ fprintf(fp," %s", arg4);
+ fprintf(fp, "\n");
+ fclose(fp);
+ }
+
+ if (FStrEq(pcmd, "addbot"))
+ {
+ BotCreate( pEntity, arg1, arg2, arg3, arg4 );
+
+ bot_check_time = gpGlobals->time + 5.0;
+
+ return;
+ }
+ else if (FStrEq(pcmd, "observer"))
+ {
+ if ((arg1 != NULL) && (*arg1 != 0))
+ {
+ int temp = atoi(arg1);
+ if (temp)
+ b_observer_mode = TRUE;
+ else
+ b_observer_mode = FALSE;
+ }
+
+ if (b_observer_mode)
+ ClientPrint(pEntity, HUD_PRINTNOTIFY, "observer mode ENABLED\n");
+ else
+ ClientPrint(pEntity, HUD_PRINTNOTIFY, "observer mode DISABLED\n");
+
+ return;
+ }
+ else if (FStrEq(pcmd, "botskill"))
+ {
+ if ((arg1 != NULL) && (*arg1 != 0))
+ {
+ int temp = atoi(arg1);
+
+ if ((temp < 1) || (temp > 5))
+ ClientPrint(pEntity, HUD_PRINTNOTIFY, "invalid botskill value!\n");
+ else
+ default_bot_skill = temp;
+ }
+
+ sprintf(msg, "botskill is %d\n", default_bot_skill);
+ ClientPrint(pEntity, HUD_PRINTNOTIFY, msg);
+
+ return;
+ }
+ else if (FStrEq(pcmd, "botdontshoot"))
+ {
+ if ((arg1 != NULL) && (*arg1 != 0))
+ {
+ int temp = atoi(arg1);
+ if (temp)
+ b_botdontshoot = TRUE;
+ else
+ b_botdontshoot = FALSE;
+ }
+
+ if (b_botdontshoot)
+ ClientPrint(pEntity, HUD_PRINTNOTIFY, "botdontshoot ENABLED\n");
+ else
+ ClientPrint(pEntity, HUD_PRINTNOTIFY, "botdontshoot DISABLED\n");
+
+ return;
+ }
+ else if (FStrEq(pcmd, "debug_engine"))
+ {
+ debug_engine = 1;
+
+ ClientPrint(pEntity, HUD_PRINTNOTIFY, "debug_engine enabled!\n");
+
+ return;
+ }
+ else if (FStrEq(pcmd, "waypoint"))
+ {
+ if (FStrEq(arg1, "on"))
+ {
+ g_waypoint_on = TRUE;
+
+ ClientPrint(pEntity, HUD_PRINTNOTIFY, "waypoints are ON\n");
+ }
+ else if (FStrEq(arg1, "off"))
+ {
+ g_waypoint_on = FALSE;
+
+ ClientPrint(pEntity, HUD_PRINTNOTIFY, "waypoints are OFF\n");
+ }
+ else if (FStrEq(arg1, "add"))
+ {
+ if (!g_waypoint_on)
+ g_waypoint_on = TRUE; // turn waypoints on if off
+
+ WaypointAdd(pEntity);
+ }
+ else if (FStrEq(arg1, "delete"))
+ {
+ if (!g_waypoint_on)
+ g_waypoint_on = TRUE; // turn waypoints on if off
+
+ WaypointDelete(pEntity);
+ }
+ else if (FStrEq(arg1, "save"))
+ {
+ WaypointSave();
+
+ ClientPrint(pEntity, HUD_PRINTNOTIFY, "waypoints saved\n");
+ }
+ else if (FStrEq(arg1, "load"))
+ {
+ if (WaypointLoad(pEntity))
+ ClientPrint(pEntity, HUD_PRINTNOTIFY, "waypoints loaded\n");
+ }
+ else if (FStrEq(arg1, "menu"))
+ {
+ int index;
+
+ if (num_waypoints < 1)
+ return;
+
+ index = WaypointFindNearest(pEntity, 50.0, -1);
+
+ if (index == -1)
+ return;
+
+ g_menu_waypoint = index;
+ g_menu_state = MENU_1;
+
+ UTIL_ShowMenu(pEntity, 0x1F, -1, FALSE, show_menu_1);
+ }
+ else if (FStrEq(arg1, "info"))
+ {
+ WaypointPrintInfo(pEntity);
+ }
+ else
+ {
+ if (g_waypoint_on)
+ ClientPrint(pEntity, HUD_PRINTNOTIFY, "waypoints are ON\n");
+ else
+ ClientPrint(pEntity, HUD_PRINTNOTIFY, "waypoints are OFF\n");
+ }
+
+ return;
+ }
+ else if (FStrEq(pcmd, "autowaypoint"))
+ {
+ if (FStrEq(arg1, "on"))
+ {
+ g_auto_waypoint = TRUE;
+ g_waypoint_on = TRUE; // turn this on just in case
+ }
+ else if (FStrEq(arg1, "off"))
+ {
+ g_auto_waypoint = FALSE;
+ }
+
+ if (g_auto_waypoint)
+ sprintf(msg, "autowaypoint is ON\n");
+ else
+ sprintf(msg, "autowaypoint is OFF\n");
+
+ ClientPrint(pEntity, HUD_PRINTNOTIFY, msg);
+
+ return;
+ }
+ else if (FStrEq(pcmd, "pathwaypoint"))
+ {
+ if (FStrEq(arg1, "on"))
+ {
+ g_path_waypoint = TRUE;
+ g_waypoint_on = TRUE; // turn this on just in case
+
+ ClientPrint(pEntity, HUD_PRINTNOTIFY, "pathwaypoint is ON\n");
+ }
+ else if (FStrEq(arg1, "off"))
+ {
+ g_path_waypoint = FALSE;
+
+ ClientPrint(pEntity, HUD_PRINTNOTIFY, "pathwaypoint is OFF\n");
+ }
+ else if (FStrEq(arg1, "create1"))
+ {
+ WaypointCreatePath(pEntity, 1);
+ }
+ else if (FStrEq(arg1, "create2"))
+ {
+ WaypointCreatePath(pEntity, 2);
+ }
+ else if (FStrEq(arg1, "remove1"))
+ {
+ WaypointRemovePath(pEntity, 1);
+ }
+ else if (FStrEq(arg1, "remove2"))
+ {
+ WaypointRemovePath(pEntity, 2);
+ }
+
+ return;
+ }
+ else if (FStrEq(pcmd, "menuselect") && (g_menu_state != MENU_NONE))
+ {
+ if (g_menu_state == MENU_1) // main menu...
+ {
+ if (FStrEq(arg1, "1")) // team specific...
+ {
+ g_menu_state = MENU_2; // display team specific menu...
+
+ if (mod_id == FRONTLINE_DLL)
+ UTIL_ShowMenu(pEntity, 0x13, -1, FALSE, show_menu_2_flf);
+ else
+ UTIL_ShowMenu(pEntity, 0x1F, -1, FALSE, show_menu_2);
+
+ return;
+ }
+ else if (FStrEq(arg1, "2")) // wait for lift...
+ {
+ if (waypoints[g_menu_waypoint].flags & W_FL_LIFT)
+ waypoints[g_menu_waypoint].flags &= ~W_FL_LIFT; // off
+ else
+ waypoints[g_menu_waypoint].flags |= W_FL_LIFT; // on
+ }
+ else if (FStrEq(arg1, "3")) // door waypoint
+ {
+ if (waypoints[g_menu_waypoint].flags & W_FL_DOOR)
+ waypoints[g_menu_waypoint].flags &= ~W_FL_DOOR; // off
+ else
+ waypoints[g_menu_waypoint].flags |= W_FL_DOOR; // on
+ }
+ else if (FStrEq(arg1, "4")) // sniper spot
+ {
+ if (waypoints[g_menu_waypoint].flags & W_FL_SNIPER)
+ waypoints[g_menu_waypoint].flags &= ~W_FL_SNIPER; // off
+ else
+ {
+ waypoints[g_menu_waypoint].flags |= W_FL_SNIPER; // on
+
+ // set the aiming waypoint...
+
+ WaypointAddAiming(pEntity);
+ }
+ }
+ else if (FStrEq(arg1, "5")) // more...
+ {
+ g_menu_state = MENU_3;
+
+ if (mod_id == FRONTLINE_DLL)
+ UTIL_ShowMenu(pEntity, 0x17, -1, FALSE, show_menu_3_flf);
+ else
+ UTIL_ShowMenu(pEntity, 0x13, -1, FALSE, show_menu_3);
+
+ return;
+ }
+ }
+ else if (g_menu_state == MENU_2) // team specific menu
+ {
+ if (waypoints[g_menu_waypoint].flags & W_FL_TEAM_SPECIFIC)
+ {
+ waypoints[g_menu_waypoint].flags &= ~W_FL_TEAM;
+ waypoints[g_menu_waypoint].flags &= ~W_FL_TEAM_SPECIFIC; // off
+ }
+ else
+ {
+ int team = atoi(arg1);
+
+ team--; // make 0 to 3
+
+ // this is kind of a kludge (team bits MUST be LSB!!!)
+ waypoints[g_menu_waypoint].flags |= team;
+ waypoints[g_menu_waypoint].flags |= W_FL_TEAM_SPECIFIC; // on
+ }
+ }
+ else if (g_menu_state == MENU_3) // second menu...
+ {
+ if (mod_id == FRONTLINE_DLL)
+ {
+ if (FStrEq(arg1, "1")) // capture point
+ {
+ if (waypoints[g_menu_waypoint].flags & W_FL_FLF_CAP)
+ waypoints[g_menu_waypoint].flags &= ~W_FL_FLF_CAP; // off
+ else
+ waypoints[g_menu_waypoint].flags |= W_FL_FLF_CAP; // on
+ }
+ else if (FStrEq(arg1, "2")) // defend point
+ {
+ if (waypoints[g_menu_waypoint].flags & W_FL_FLF_DEFEND)
+ waypoints[g_menu_waypoint].flags &= ~W_FL_FLF_DEFEND; // off
+ else
+ {
+ waypoints[g_menu_waypoint].flags |= W_FL_FLF_DEFEND; // on
+
+ // set the aiming waypoint...
+
+ WaypointAddAiming(pEntity);
+ }
+ }
+ else if (FStrEq(arg1, "3")) // go prone
+ {
+ if (waypoints[g_menu_waypoint].flags & W_FL_PRONE)
+ waypoints[g_menu_waypoint].flags &= ~W_FL_PRONE; // off
+ else
+ waypoints[g_menu_waypoint].flags |= W_FL_PRONE; // on
+ }
+ }
+ else
+ {
+ if (FStrEq(arg1, "1")) // flag location
+ {
+ if (waypoints[g_menu_waypoint].flags & W_FL_TFC_FLAG)
+ waypoints[g_menu_waypoint].flags &= ~W_FL_TFC_FLAG; // off
+ else
+ waypoints[g_menu_waypoint].flags |= W_FL_TFC_FLAG; // on
+ }
+ else if (FStrEq(arg1, "2")) // flag goal
+ {
+ if (waypoints[g_menu_waypoint].flags & W_FL_TFC_FLAG_GOAL)
+ waypoints[g_menu_waypoint].flags &= ~W_FL_TFC_FLAG_GOAL; // off
+ else
+ waypoints[g_menu_waypoint].flags |= W_FL_TFC_FLAG_GOAL; // on
+ }
+ }
+ }
+
+ g_menu_state = MENU_NONE;
+
+ return;
+ }
+ else if (FStrEq(pcmd, "search"))
+ {
+ edict_t *pent = NULL;
+ float radius = 50;
+ char str[80];
+
+ ClientPrint(pEntity, HUD_PRINTCONSOLE, "searching...\n");
+
+ while ((pent = UTIL_FindEntityInSphere( pent, pEntity->v.origin, radius )) != NULL)
+ {
+ sprintf(str, "Found %s at %5.2f %5.2f %5.2f\n",
+ STRING(pent->v.classname),
+ pent->v.origin.x, pent->v.origin.y,
+ pent->v.origin.z);
+ ClientPrint(pEntity, HUD_PRINTCONSOLE, str);
+
+ FILE *fp=fopen("bot.txt", "a");
+ fprintf(fp, "ClientCommmand: search %s", str);
+ fclose(fp);
+ }
+
+ return;
+ }
+ }
+
+ (*other_gFunctionTable.pfnClientCommand)(pEntity);
+}
+
+void ClientUserInfoChanged( edict_t *pEntity, char *infobuffer )
+{
+ if (debug_engine) { fp=fopen("bot.txt", "a"); fprintf(fp, "ClientUserInfoChanged: pEntity=%x infobuffer=%s\n", pEntity, infobuffer); fclose(fp); }
+
+ (*other_gFunctionTable.pfnClientUserInfoChanged)(pEntity, infobuffer);
+}
+
+void ServerActivate( edict_t *pEdictList, int edictCount, int clientMax )
+{
+ (*other_gFunctionTable.pfnServerActivate)(pEdictList, edictCount, clientMax);
+}
+
+void ServerDeactivate( void )
+{
+ (*other_gFunctionTable.pfnServerDeactivate)();
+}
+
+void PlayerPreThink( edict_t *pEntity )
+{
+ (*other_gFunctionTable.pfnPlayerPreThink)(pEntity);
+}
+
+void PlayerPostThink( edict_t *pEntity )
+{
+ (*other_gFunctionTable.pfnPlayerPostThink)(pEntity);
+}
+
+void StartFrame( void )
+{
+ if (gpGlobals->deathmatch)
+ {
+ edict_t *pPlayer;
+ static float check_server_cmd = 0.0;
+ static int i, index, player_index, bot_index;
+ static float previous_time = -1.0;
+ static float client_update_time = 0.0;
+ clientdata_s cd;
+ char msg[256];
+ int count;
+
+ // if a new map has started then (MUST BE FIRST IN StartFrame)...
+ if ((gpGlobals->time + 0.1) < previous_time)
+ {
+ char filename[256];
+ char mapname[64];
+
+ check_server_cmd = 0.0; // reset at start of map
+
+ // check if mapname_bot.cfg file exists...
+
+ strcpy(mapname, STRING(gpGlobals->mapname));
+ strcat(mapname, "_bot.cfg");
+
+ UTIL_BuildFileName(filename, "maps", mapname);
+
+ if ((bot_cfg_fp = fopen(filename, "r")) != NULL)
+ {
+ sprintf(msg, "Executing %s\n", filename);
+ ALERT( at_console, msg );
+
+ for (index = 0; index < 32; index++)
+ {
+ bots[index].is_used = FALSE;
+ bots[index].respawn_state = 0;
+ bots[index].kick_time = 0.0;
+ }
+
+ if (IS_DEDICATED_SERVER())
+ bot_cfg_pause_time = gpGlobals->time + 5.0;
+ else
+ bot_cfg_pause_time = gpGlobals->time + 20.0;
+ }
+ else
+ {
+ count = 0;
+
+ // mark the bots as needing to be respawned...
+ for (index = 0; index < 32; index++)
+ {
+ if (count >= prev_num_bots)
+ {
+ bots[index].is_used = FALSE;
+ bots[index].respawn_state = 0;
+ bots[index].kick_time = 0.0;
+ }
+
+ if (bots[index].is_used) // is this slot used?
+ {
+ bots[index].respawn_state = RESPAWN_NEED_TO_RESPAWN;
+ count++;
+ }
+
+ // check for any bots that were very recently kicked...
+ if ((bots[index].kick_time + 5.0) > previous_time)
+ {
+ bots[index].respawn_state = RESPAWN_NEED_TO_RESPAWN;
+ count++;
+ }
+ else
+ bots[index].kick_time = 0.0; // reset to prevent false spawns later
+ }
+
+ // set the respawn time
+ if (IS_DEDICATED_SERVER())
+ respawn_time = gpGlobals->time + 5.0;
+ else
+ respawn_time = gpGlobals->time + 20.0;
+ }
+
+ client_update_time = gpGlobals->time + 10.0; // start updating client data again
+
+ bot_check_time = gpGlobals->time + 30.0;
+ }
+
+ if (!IS_DEDICATED_SERVER())
+ {
+ if ((listenserver_edict != NULL) && (welcome_sent == FALSE) &&
+ (welcome_time < 1.0))
+ {
+ // are they out of observer mode yet?
+ if (IsAlive(listenserver_edict))
+ welcome_time = gpGlobals->time + 5.0; // welcome in 5 seconds
+ }
+
+ if ((welcome_time > 0.0) && (welcome_time < gpGlobals->time) &&
+ (welcome_sent == FALSE))
+ {
+ // let's send a welcome message to this client...
+ //UTIL_SayText(welcome_msg, listenserver_edict);
+
+ welcome_sent = TRUE; // clear this so we only do it once
+ }
+ }
+
+ if (client_update_time <= gpGlobals->time)
+ {
+ client_update_time = gpGlobals->time + 1.0;
+
+ for (i=0; i < 32; i++)
+ {
+ if (bots[i].is_used)
+ {
+ memset(&cd, 0, sizeof(cd));
+
+ UpdateClientData( bots[i].pEdict, 1, &cd );
+
+ // see if a weapon was dropped...
+ if (bots[i].bot_weapons != cd.weapons)
+ {
+ bots[i].bot_weapons = cd.weapons;
+ }
+ }
+ }
+ }
+
+ count = 0;
+
+ for (bot_index = 0; bot_index < gpGlobals->maxClients; bot_index++)
+ {
+ if ((bots[bot_index].is_used) && // is this slot used AND
+ (bots[bot_index].respawn_state == RESPAWN_IDLE)) // not respawning
+ {
+ BotThink(&bots[bot_index]);
+
+ count++;
+
+ if ((mod_id == FRONTLINE_DLL) && (flf_bug_check == 0))
+ {
+ edict_t *pent = NULL;
+ int fix_flag = 0;
+
+ flf_bug_check = 1;
+
+ while ((pent = UTIL_FindEntityByClassname( pent, "capture_point" )) != NULL)
+ {
+ if (pent->v.skin != 0) // not blue skin?
+ {
+ flf_bug_fix = 1; // need to use bug fix code
+ }
+ }
+ }
+ }
+ }
+
+ if (count > num_bots)
+ num_bots = count;
+
+ for (player_index = 1; player_index <= gpGlobals->maxClients; player_index++)
+ {
+ pPlayer = INDEXENT(player_index);
+
+ if (pPlayer && !pPlayer->free)
+ {
+ if ((g_waypoint_on) && FBitSet(pPlayer->v.flags, FL_CLIENT))
+ {
+ WaypointThink(pPlayer);
+ }
+
+ if ((mod_id == FRONTLINE_DLL) && (flf_bug_check == 0))
+ {
+ edict_t *pent = NULL;
+ int fix_flag = 0;
+
+ flf_bug_check = 1;
+
+ while ((pent = UTIL_FindEntityByClassname( pent, "capture_point" )) != NULL)
+ {
+ if (pent->v.skin != 0) // not blue skin?
+ {
+ flf_bug_fix = 1; // need to use bug fix code
+ }
+ }
+ }
+ }
+ }
+
+ // are we currently respawning bots and is it time to spawn one yet?
+ if ((respawn_time > 1.0) && (respawn_time <= gpGlobals->time))
+ {
+ int index = 0;
+
+ // find bot needing to be respawned...
+ while ((index < 32) &&
+ (bots[index].respawn_state != RESPAWN_NEED_TO_RESPAWN))
+ index++;
+
+ if (index < 32)
+ {
+ bots[index].respawn_state = RESPAWN_IS_RESPAWNING;
+ bots[index].is_used = FALSE; // free up this slot
+
+ // respawn 1 bot then wait a while (otherwise engine crashes)
+ if ((mod_id == VALVE_DLL) ||
+ ((mod_id == GEARBOX_DLL) && (pent_info_ctfdetect == NULL)))
+ {
+ char c_skill[2];
+
+ sprintf(c_skill, "%d", bots[index].bot_skill);
+
+ BotCreate(NULL, bots[index].skin, bots[index].name, c_skill, NULL);
+ }
+ else
+ {
+ char c_skill[2];
+ char c_team[2];
+ char c_class[3];
+
+ sprintf(c_skill, "%d", bots[index].bot_skill);
+ sprintf(c_team, "%d", bots[index].bot_team);
+ sprintf(c_class, "%d", bots[index].bot_class);
+
+ if ((mod_id == TFC_DLL) || (mod_id == GEARBOX_DLL))
+ BotCreate(NULL, NULL, NULL, bots[index].name, c_skill);
+ else
+ BotCreate(NULL, c_team, c_class, bots[index].name, c_skill);
+ }
+
+ respawn_time = gpGlobals->time + 2.0; // set next respawn time
+
+ bot_check_time = gpGlobals->time + 5.0;
+ }
+ else
+ {
+ respawn_time = 0.0;
+ }
+ }
+
+ if (g_GameRules)
+ {
+ if (need_to_open_cfg) // have we open bot.cfg file yet?
+ {
+ char filename[256];
+ char mapname[64];
+
+ need_to_open_cfg = FALSE; // only do this once!!!
+
+ // check if mapname_bot.cfg file exists...
+
+ strcpy(mapname, STRING(gpGlobals->mapname));
+ strcat(mapname, "_bot.cfg");
+
+ UTIL_BuildFileName(filename, "maps", mapname);
+
+ if ((bot_cfg_fp = fopen(filename, "r")) != NULL)
+ {
+ sprintf(msg, "Executing %s\n", filename);
+ ALERT( at_console, msg );
+ }
+ else
+ {
+ UTIL_BuildFileName(filename, "bot.cfg", NULL);
+
+ sprintf(msg, "Executing %s\n", filename);
+ ALERT( at_console, msg );
+
+ bot_cfg_fp = fopen(filename, "r");
+
+ if (bot_cfg_fp == NULL)
+ ALERT( at_console, "bot.cfg file not found\n" );
+ }
+
+ if (IS_DEDICATED_SERVER())
+ bot_cfg_pause_time = gpGlobals->time + 5.0;
+ else
+ bot_cfg_pause_time = gpGlobals->time + 20.0;
+ }
+
+ if (!IS_DEDICATED_SERVER() && !spawn_time_reset)
+ {
+ if (listenserver_edict != NULL)
+ {
+ if (IsAlive(listenserver_edict))
+ {
+ spawn_time_reset = TRUE;
+
+ if (respawn_time >= 1.0)
+ respawn_time = min(respawn_time, gpGlobals->time + (float)1.0);
+
+ if (bot_cfg_pause_time >= 1.0)
+ bot_cfg_pause_time = min(bot_cfg_pause_time, gpGlobals->time + (float)1.0);
+ }
+ }
+ }
+
+ if ((bot_cfg_fp) &&
+ (bot_cfg_pause_time >= 1.0) && (bot_cfg_pause_time <= gpGlobals->time))
+ {
+ // process bot.cfg file options...
+ ProcessBotCfgFile();
+ }
+
+ }
+
+ // if time to check for server commands then do so...
+ if ((check_server_cmd <= gpGlobals->time) && IS_DEDICATED_SERVER())
+ {
+ check_server_cmd = gpGlobals->time + 1.0;
+
+ char *cvar_bot = (char *)CVAR_GET_STRING( "bot" );
+
+ if ( cvar_bot && cvar_bot[0] )
+ {
+ char cmd_line[80];
+ char *cmd, *arg1, *arg2, *arg3, *arg4;
+
+ strcpy(cmd_line, cvar_bot);
+
+ index = 0;
+ cmd = cmd_line;
+ arg1 = arg2 = arg3 = arg4 = NULL;
+
+ // skip to blank or end of string...
+ while ((cmd_line[index] != ' ') && (cmd_line[index] != 0))
+ index++;
+
+ if (cmd_line[index] == ' ')
+ {
+ cmd_line[index++] = 0;
+ arg1 = &cmd_line[index];
+
+ // skip to blank or end of string...
+ while ((cmd_line[index] != ' ') && (cmd_line[index] != 0))
+ index++;
+
+ if (cmd_line[index] == ' ')
+ {
+ cmd_line[index++] = 0;
+ arg2 = &cmd_line[index];
+
+ // skip to blank or end of string...
+ while ((cmd_line[index] != ' ') && (cmd_line[index] != 0))
+ index++;
+
+ if (cmd_line[index] == ' ')
+ {
+ cmd_line[index++] = 0;
+ arg3 = &cmd_line[index];
+
+ // skip to blank or end of string...
+ while ((cmd_line[index] != ' ') && (cmd_line[index] != 0))
+ index++;
+
+ if (cmd_line[index] == ' ')
+ {
+ cmd_line[index++] = 0;
+ arg4 = &cmd_line[index];
+ }
+ }
+ }
+ }
+
+ if (strcmp(cmd, "addbot") == 0)
+ {
+ BotCreate( NULL, arg1, arg2, arg3, arg4 );
+
+ bot_check_time = gpGlobals->time + 5.0;
+ }
+ else if (strcmp(cmd, "min_bots") == 0)
+ {
+ min_bots = atoi( arg1 );
+
+ if ((min_bots < 0) || (min_bots > 31))
+ min_bots = 1;
+
+ sprintf(msg, "min_bots set to %d\n", min_bots);
+ printf(msg);
+ }
+ else if (strcmp(cmd, "max_bots") == 0)
+ {
+ max_bots = atoi( arg1 );
+
+ if ((max_bots < 0) || (max_bots > 31))
+ max_bots = 1;
+
+ sprintf(msg, "max_bots set to %d\n", max_bots);
+ printf(msg);
+ }
+
+ CVAR_SET_STRING("bot", "");
+ }
+ }
+
+ // check if time to see if a bot needs to be created...
+ if (bot_check_time < gpGlobals->time)
+ {
+ int count = 0;
+
+ bot_check_time = gpGlobals->time + 5.0;
+
+ for (i = 0; i < 32; i++)
+ {
+ if (clients[i] != NULL)
+ count++;
+ }
+
+ // if there are currently less than the maximum number of "players"
+ // then add another bot using the default skill level...
+ if ((count < max_bots) && (max_bots != -1))
+ {
+ BotCreate( NULL, NULL, NULL, NULL, NULL );
+ }
+ }
+
+ previous_time = gpGlobals->time;
+ }
+
+ (*other_gFunctionTable.pfnStartFrame)();
+}
+
+void ParmsNewLevel( void )
+{
+ (*other_gFunctionTable.pfnParmsNewLevel)();
+}
+
+void ParmsChangeLevel( void )
+{
+ (*other_gFunctionTable.pfnParmsChangeLevel)();
+}
+
+const char *GetGameDescription( void )
+{
+ return (*other_gFunctionTable.pfnGetGameDescription)();
+}
+
+void PlayerCustomization( edict_t *pEntity, customization_t *pCust )
+{
+ if (debug_engine) { fp=fopen("bot.txt", "a"); fprintf(fp, "PlayerCustomization: %x\n",pEntity); fclose(fp); }
+
+ (*other_gFunctionTable.pfnPlayerCustomization)(pEntity, pCust);
+}
+
+void SpectatorConnect( edict_t *pEntity )
+{
+ (*other_gFunctionTable.pfnSpectatorConnect)(pEntity);
+}
+
+void SpectatorDisconnect( edict_t *pEntity )
+{
+ (*other_gFunctionTable.pfnSpectatorDisconnect)(pEntity);
+}
+
+void SpectatorThink( edict_t *pEntity )
+{
+ (*other_gFunctionTable.pfnSpectatorThink)(pEntity);
+}
+
+void Sys_Error( const char *error_string )
+{
+ (*other_gFunctionTable.pfnSys_Error)(error_string);
+}
+
+void PM_Move ( struct playermove_s *ppmove, int server )
+{
+ (*other_gFunctionTable.pfnPM_Move)(ppmove, server);
+}
+
+void PM_Init ( struct playermove_s *ppmove )
+{
+ (*other_gFunctionTable.pfnPM_Init)(ppmove);
+}
+
+char PM_FindTextureType( char *name )
+{
+ return (*other_gFunctionTable.pfnPM_FindTextureType)(name);
+}
+
+void SetupVisibility( edict_t *pViewEntity, edict_t *pClient, unsigned char **pvs, unsigned char **pas )
+{
+ (*other_gFunctionTable.pfnSetupVisibility)(pViewEntity, pClient, pvs, pas);
+}
+
+void UpdateClientData ( const struct edict_s *ent, int sendweapons, struct clientdata_s *cd )
+{
+ (*other_gFunctionTable.pfnUpdateClientData)(ent, sendweapons, cd);
+}
+
+int AddToFullPack( struct entity_state_s *state, int e, edict_t *ent, edict_t *host, int hostflags, int player, unsigned char *pSet )
+{
+ return (*other_gFunctionTable.pfnAddToFullPack)(state, e, ent, host, hostflags, player, pSet);
+}
+
+void CreateBaseline( int player, int eindex, struct entity_state_s *baseline, struct edict_s *entity, int playermodelindex, vec3_t player_mins, vec3_t player_maxs )
+{
+ (*other_gFunctionTable.pfnCreateBaseline)(player, eindex, baseline, entity, playermodelindex, player_mins, player_maxs);
+}
+
+void RegisterEncoders( void )
+{
+ (*other_gFunctionTable.pfnRegisterEncoders)();
+}
+
+int GetWeaponData( struct edict_s *player, struct weapon_data_s *info )
+{
+ return (*other_gFunctionTable.pfnGetWeaponData)(player, info);
+}
+
+void CmdStart( const edict_t *player, const struct usercmd_s *cmd, unsigned int random_seed )
+{
+ (*other_gFunctionTable.pfnCmdStart)(player, cmd, random_seed);
+}
+
+void CmdEnd ( const edict_t *player )
+{
+ (*other_gFunctionTable.pfnCmdEnd)(player);
+}
+
+int ConnectionlessPacket( const struct netadr_s *net_from, const char *args, char *response_buffer, int *response_buffer_size )
+{
+ return (*other_gFunctionTable.pfnConnectionlessPacket)(net_from, args, response_buffer, response_buffer_size);
+}
+
+int GetHullBounds( int hullnumber, float *mins, float *maxs )
+{
+ return (*other_gFunctionTable.pfnGetHullBounds)(hullnumber, mins, maxs);
+}
+
+void CreateInstancedBaselines( void )
+{
+ (*other_gFunctionTable.pfnCreateInstancedBaselines)();
+}
+
+int InconsistentFile( const edict_t *player, const char *filename, char *disconnect_message )
+{
+ if (debug_engine) { fp=fopen("bot.txt", "a"); fprintf(fp, "InconsistentFile: %x filename=%s\n",player,filename); fclose(fp); }
+
+ return (*other_gFunctionTable.pfnInconsistentFile)(player, filename, disconnect_message);
+}
+
+int AllowLagCompensation( void )
+{
+ return (*other_gFunctionTable.pfnAllowLagCompensation)();
+}
+
+
+DLL_FUNCTIONS gFunctionTable =
+{
+ GameDLLInit, //pfnGameInit
+ DispatchSpawn, //pfnSpawn
+ DispatchThink, //pfnThink
+ DispatchUse, //pfnUse
+ DispatchTouch, //pfnTouch
+ DispatchBlocked, //pfnBlocked
+ DispatchKeyValue, //pfnKeyValue
+ DispatchSave, //pfnSave
+ DispatchRestore, //pfnRestore
+ DispatchObjectCollsionBox, //pfnAbsBox
+
+ SaveWriteFields, //pfnSaveWriteFields
+ SaveReadFields, //pfnSaveReadFields
+
+ SaveGlobalState, //pfnSaveGlobalState
+ RestoreGlobalState, //pfnRestoreGlobalState
+ ResetGlobalState, //pfnResetGlobalState
+
+ ClientConnect, //pfnClientConnect
+ ClientDisconnect, //pfnClientDisconnect
+ ClientKill, //pfnClientKill
+ ClientPutInServer, //pfnClientPutInServer
+ ClientCommand, //pfnClientCommand
+ ClientUserInfoChanged, //pfnClientUserInfoChanged
+ ServerActivate, //pfnServerActivate
+ ServerDeactivate, //pfnServerDeactivate
+
+ PlayerPreThink, //pfnPlayerPreThink
+ PlayerPostThink, //pfnPlayerPostThink
+
+ StartFrame, //pfnStartFrame
+ ParmsNewLevel, //pfnParmsNewLevel
+ ParmsChangeLevel, //pfnParmsChangeLevel
+
+ GetGameDescription, //pfnGetGameDescription Returns string describing current .dll game.
+ PlayerCustomization, //pfnPlayerCustomization Notifies .dll of new customization for player.
+
+ SpectatorConnect, //pfnSpectatorConnect Called when spectator joins server
+ SpectatorDisconnect, //pfnSpectatorDisconnect Called when spectator leaves the server
+ SpectatorThink, //pfnSpectatorThink Called when spectator sends a command packet (usercmd_t)
+
+ Sys_Error, //pfnSys_Error Called when engine has encountered an error
+
+ PM_Move, //pfnPM_Move
+ PM_Init, //pfnPM_Init Server version of player movement initialization
+ PM_FindTextureType, //pfnPM_FindTextureType
+
+ SetupVisibility, //pfnSetupVisibility Set up PVS and PAS for networking for this client
+ UpdateClientData, //pfnUpdateClientData Set up data sent only to specific client
+ AddToFullPack, //pfnAddToFullPack
+ CreateBaseline, //pfnCreateBaseline Tweak entity baseline for network encoding, allows setup of player baselines, too.
+ RegisterEncoders, //pfnRegisterEncoders Callbacks for network encoding
+ GetWeaponData, //pfnGetWeaponData
+ CmdStart, //pfnCmdStart
+ CmdEnd, //pfnCmdEnd
+ ConnectionlessPacket, //pfnConnectionlessPacket
+ GetHullBounds, //pfnGetHullBounds
+ CreateInstancedBaselines, //pfnCreateInstancedBaselines
+ InconsistentFile, //pfnInconsistentFile
+ AllowLagCompensation, //pfnAllowLagCompensation
+};
+
+#ifdef __BORLANDC__
+int EXPORT GetEntityAPI( DLL_FUNCTIONS *pFunctionTable, int interfaceVersion )
+#else
+extern "C" EXPORT int GetEntityAPI( DLL_FUNCTIONS *pFunctionTable, int interfaceVersion )
+#endif
+{
+ // check if engine's pointer is valid and version is correct...
+
+ if ( !pFunctionTable || interfaceVersion != INTERFACE_VERSION )
+ return FALSE;
+
+ // pass engine callback function table to engine...
+ memcpy( pFunctionTable, &gFunctionTable, sizeof( DLL_FUNCTIONS ) );
+
+ // pass other DLLs engine callbacks to function table...
+ if (!(*other_GetEntityAPI)(&other_gFunctionTable, INTERFACE_VERSION))
+ {
+ return FALSE; // error initializing function table!!!
+ }
+
+ return TRUE;
+}
+
+
+#ifdef __BORLANDC__
+int EXPORT GetNewDLLFunctions( NEW_DLL_FUNCTIONS *pFunctionTable, int *interfaceVersion )
+#else
+extern "C" EXPORT int GetNewDLLFunctions( NEW_DLL_FUNCTIONS *pFunctionTable, int *interfaceVersion )
+#endif
+{
+ if (other_GetNewDLLFunctions == NULL)
+ return FALSE;
+
+ // pass other DLLs engine callbacks to function table...
+ if (!(*other_GetNewDLLFunctions)(pFunctionTable, interfaceVersion))
+ {
+ return FALSE; // error initializing function table!!!
+ }
+
+ return TRUE;
+}
+
+
+void FakeClientCommand(edict_t *pBot, char *arg1, char *arg2, char *arg3)
+{
+ int length;
+
+ memset(g_argv, 0, sizeof(g_argv));
+
+ isFakeClientCommand = 1;
+
+ if ((arg1 == NULL) || (*arg1 == 0))
+ return;
+
+ if ((arg2 == NULL) || (*arg2 == 0))
+ {
+ length = sprintf(&g_argv[0], "%s", arg1);
+ fake_arg_count = 1;
+ }
+ else if ((arg3 == NULL) || (*arg3 == 0))
+ {
+ length = sprintf(&g_argv[0], "%s %s", arg1, arg2);
+ fake_arg_count = 2;
+ }
+ else
+ {
+ length = sprintf(&g_argv[0], "%s %s %s", arg1, arg2, arg3);
+ fake_arg_count = 3;
+ }
+
+ g_argv[length] = 0; // null terminate just in case
+
+ strcpy(&g_argv[64], arg1);
+
+ if (arg2)
+ strcpy(&g_argv[128], arg2);
+
+ if (arg3)
+ strcpy(&g_argv[192], arg3);
+
+ // allow the MOD DLL to execute the ClientCommand...
+ ClientCommand(pBot);
+
+ isFakeClientCommand = 0;
+}
+
+
+const char *Cmd_Args( void )
+{
+ if (isFakeClientCommand)
+ {
+ return &g_argv[0];
+ }
+ else
+ {
+ return (*g_engfuncs.pfnCmd_Args)();
+ }
+}
+
+
+const char *Cmd_Argv( int argc )
+{
+ if (isFakeClientCommand)
+ {
+ if (argc == 0)
+ {
+ return &g_argv[64];
+ }
+ else if (argc == 1)
+ {
+ return &g_argv[128];
+ }
+ else if (argc == 2)
+ {
+ return &g_argv[192];
+ }
+ else
+ {
+ return NULL;
+ }
+ }
+ else
+ {
+ return (*g_engfuncs.pfnCmd_Argv)(argc);
+ }
+}
+
+
+int Cmd_Argc( void )
+{
+ if (isFakeClientCommand)
+ {
+ return fake_arg_count;
+ }
+ else
+ {
+ return (*g_engfuncs.pfnCmd_Argc)();
+ }
+}
+
+
+void ProcessBotCfgFile(void)
+{
+ int ch;
+ char cmd_line[256];
+ int cmd_index;
+ static char server_cmd[80];
+ char *cmd, *arg1, *arg2, *arg3, *arg4;
+ char msg[80];
+
+ if (bot_cfg_pause_time > gpGlobals->time)
+ return;
+
+ if (bot_cfg_fp == NULL)
+ return;
+
+ cmd_index = 0;
+ cmd_line[cmd_index] = 0;
+
+ ch = fgetc(bot_cfg_fp);
+
+ // skip any leading blanks
+ while (ch == ' ')
+ ch = fgetc(bot_cfg_fp);
+
+ while ((ch != EOF) && (ch != '\r') && (ch != '\n'))
+ {
+ if (ch == '\t') // convert tabs to spaces
+ ch = ' ';
+
+ cmd_line[cmd_index] = ch;
+
+ ch = fgetc(bot_cfg_fp);
+
+ // skip multiple spaces in input file
+ while ((cmd_line[cmd_index] == ' ') &&
+ (ch == ' '))
+ ch = fgetc(bot_cfg_fp);
+
+ cmd_index++;
+ }
+
+ if (ch == '\r') // is it a carriage return?
+ {
+ ch = fgetc(bot_cfg_fp); // skip the linefeed
+ }
+
+ // if reached end of file, then close it
+ if (ch == EOF)
+ {
+ fclose(bot_cfg_fp);
+
+ bot_cfg_fp = NULL;
+
+ bot_cfg_pause_time = 0.0;
+ }
+
+ cmd_line[cmd_index] = 0; // terminate the command line
+
+ // copy the command line to a server command buffer...
+ strcpy(server_cmd, cmd_line);
+ strcat(server_cmd, "\n");
+
+ cmd_index = 0;
+ cmd = cmd_line;
+ arg1 = arg2 = arg3 = arg4 = NULL;
+
+ // skip to blank or end of string...
+ while ((cmd_line[cmd_index] != ' ') && (cmd_line[cmd_index] != 0))
+ cmd_index++;
+
+ if (cmd_line[cmd_index] == ' ')
+ {
+ cmd_line[cmd_index++] = 0;
+ arg1 = &cmd_line[cmd_index];
+
+ // skip to blank or end of string...
+ while ((cmd_line[cmd_index] != ' ') && (cmd_line[cmd_index] != 0))
+ cmd_index++;
+
+ if (cmd_line[cmd_index] == ' ')
+ {
+ cmd_line[cmd_index++] = 0;
+ arg2 = &cmd_line[cmd_index];
+
+ // skip to blank or end of string...
+ while ((cmd_line[cmd_index] != ' ') && (cmd_line[cmd_index] != 0))
+ cmd_index++;
+
+ if (cmd_line[cmd_index] == ' ')
+ {
+ cmd_line[cmd_index++] = 0;
+ arg3 = &cmd_line[cmd_index];
+
+ // skip to blank or end of string...
+ while ((cmd_line[cmd_index] != ' ') && (cmd_line[cmd_index] != 0))
+ cmd_index++;
+
+ if (cmd_line[cmd_index] == ' ')
+ {
+ cmd_line[cmd_index++] = 0;
+ arg4 = &cmd_line[cmd_index];
+ }
+ }
+ }
+ }
+
+ if ((cmd_line[0] == '#') || (cmd_line[0] == 0))
+ return; // return if comment or blank line
+
+ if (strcmp(cmd, "addbot") == 0)
+ {
+ BotCreate( NULL, arg1, arg2, arg3, arg4 );
+
+ // have to delay here or engine gives "Tried to write to
+ // uninitialized sizebuf_t" error and crashes...
+
+ bot_cfg_pause_time = gpGlobals->time + 2.0;
+ bot_check_time = gpGlobals->time + 5.0;
+
+ return;
+ }
+
+ if (strcmp(cmd, "botskill") == 0)
+ {
+ int temp = atoi(arg1);
+
+ if ((temp >= 1) && (temp <= 5))
+ default_bot_skill = atoi( arg1 ); // set default bot skill level
+
+ return;
+ }
+
+ if (strcmp(cmd, "observer") == 0)
+ {
+ int temp = atoi(arg1);
+
+ if (temp)
+ b_observer_mode = TRUE;
+ else
+ b_observer_mode = FALSE;
+
+ return;
+ }
+
+ if (strcmp(cmd, "botdontshoot") == 0)
+ {
+ int temp = atoi(arg1);
+
+ if (temp)
+ b_botdontshoot = TRUE;
+ else
+ b_botdontshoot = FALSE;
+
+ return;
+ }
+
+ if (strcmp(cmd, "min_bots") == 0)
+ {
+ min_bots = atoi( arg1 );
+
+ if ((min_bots < 0) || (min_bots > 31))
+ min_bots = 1;
+
+ if (IS_DEDICATED_SERVER())
+ {
+ sprintf(msg, "min_bots set to %d\n", min_bots);
+ printf(msg);
+ }
+
+ return;
+ }
+
+ if (strcmp(cmd, "max_bots") == 0)
+ {
+ max_bots = atoi( arg1 );
+
+ if ((max_bots < 0) || (max_bots > 31))
+ max_bots = 1;
+
+ if (IS_DEDICATED_SERVER())
+ {
+ sprintf(msg, "max_bots set to %d\n", max_bots);
+ printf(msg);
+ }
+
+ return;
+ }
+
+ if (strcmp(cmd, "pause") == 0)
+ {
+ bot_cfg_pause_time = gpGlobals->time + atoi( arg1 );
+
+ return;
+ }
+
+ sprintf(msg, "executing server command: %s\n", server_cmd);
+ ALERT( at_console, msg );
+
+ if (IS_DEDICATED_SERVER())
+ printf(msg);
+
+ SERVER_COMMAND(server_cmd);
+}
+
diff --git a/main/source/HPB_bot/dlls/engine.cpp b/main/source/HPB_bot/dlls/engine.cpp
index a68f36f9..43704e86 100644
--- a/main/source/HPB_bot/dlls/engine.cpp
+++ b/main/source/HPB_bot/dlls/engine.cpp
@@ -1,1233 +1,1233 @@
-//
-// HPB bot - botman's High Ping Bastard bot
-//
-// (http://planethalflife.com/botman/)
-//
-// engine.cpp
-//
-
-#include "dlls/extdll.h"
-#include "dlls/util.h"
-
-#include "bot.h"
-#include "bot_client.h"
-#include "HPB_bot/engine/engine.h"
-
-
-extern enginefuncs_t g_engfuncs;
-extern bot_t bots[32];
-extern int mod_id;
-
-
-int debug_engine = 0;
-
-void (*botMsgFunction)(void *, int) = NULL;
-void (*botMsgEndFunction)(void *, int) = NULL;
-int botMsgIndex;
-
-// messages created in RegUserMsg which will be "caught"
-int message_VGUI = 0;
-int message_ShowMenu = 0;
-int message_WeaponList = 0;
-int message_CurWeapon = 0;
-int message_AmmoX = 0;
-int message_WeapPickup = 0;
-int message_AmmoPickup = 0;
-int message_ItemPickup = 0;
-int message_Health = 0;
-int message_Battery = 0; // Armor
-int message_Damage = 0;
-int message_Money = 0; // for Counter-Strike
-int message_DeathMsg = 0;
-int message_TextMsg = 0;
-int message_WarmUp = 0; // for Front Line Force
-int message_WinMessage = 0; // for Front Line Force
-int message_ScreenFade = 0;
-
-// AvH messages
-int message_SetPlayMode = 0;
-int message_SetOrder = 0;
-int message_SetResources = 0;
-
-static FILE *fp;
-
-
-int pfnPrecacheModel(char* s)
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnPrecacheModel: %s\n",s); fclose(fp); }
- return (*g_engfuncs.pfnPrecacheModel)(s);
-}
-int pfnPrecacheSound(char* s)
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnPrecacheSound: %s\n",s); fclose(fp); }
- return (*g_engfuncs.pfnPrecacheSound)(s);
-}
-void pfnSetModel(edict_t *e, const char *m)
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnSetModel: edict=%x %s\n",e,m); fclose(fp); }
- (*g_engfuncs.pfnSetModel)(e, m);
-}
-int pfnModelIndex(const char *m)
-{
-// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnModelIndex: %s\n",m); fclose(fp); }
- return (*g_engfuncs.pfnModelIndex)(m);
-}
-int pfnModelFrames(int modelIndex)
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnModelFrames:\n"); fclose(fp); }
- return (*g_engfuncs.pfnModelFrames)(modelIndex);
-}
-void pfnSetSize(edict_t *e, const float *rgflMin, const float *rgflMax)
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnSetSize: %x\n",e); fclose(fp); }
- (*g_engfuncs.pfnSetSize)(e, rgflMin, rgflMax);
-}
-void pfnChangeLevel(char* s1, char* s2)
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnChangeLevel:\n"); fclose(fp); }
-
- // kick any bot off of the server after time/frag limit...
- for (int index = 0; index < 32; index++)
- {
- if (bots[index].is_used) // is this slot used?
- {
- char cmd[40];
-
- sprintf(cmd, "kick \"%s\"\n", bots[index].name);
-
- bots[index].respawn_state = RESPAWN_NEED_TO_RESPAWN;
-
- SERVER_COMMAND(cmd); // kick the bot using (kick "name")
- }
- }
-
- (*g_engfuncs.pfnChangeLevel)(s1, s2);
-}
-void pfnGetSpawnParms(edict_t *ent)
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnGetSpawnParms:\n"); fclose(fp); }
- (*g_engfuncs.pfnGetSpawnParms)(ent);
-}
-void pfnSaveSpawnParms(edict_t *ent)
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnSaveSpawnParms:\n"); fclose(fp); }
- (*g_engfuncs.pfnSaveSpawnParms)(ent);
-}
-float pfnVecToYaw(const float *rgflVector)
-{
-// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnVecToYaw:\n"); fclose(fp); }
- return (*g_engfuncs.pfnVecToYaw)(rgflVector);
-}
-void pfnVecToAngles(const float *rgflVectorIn, float *rgflVectorOut)
-{
-// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnVecToAngles:\n"); fclose(fp); }
- (*g_engfuncs.pfnVecToAngles)(rgflVectorIn, rgflVectorOut);
-}
-void pfnMoveToOrigin(edict_t *ent, const float *pflGoal, float dist, int iMoveType)
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnMoveToOrigin:\n"); fclose(fp); }
- (*g_engfuncs.pfnMoveToOrigin)(ent, pflGoal, dist, iMoveType);
-}
-void pfnChangeYaw(edict_t* ent)
-{
-// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnChangeYaw:\n"); fclose(fp); }
- (*g_engfuncs.pfnChangeYaw)(ent);
-}
-void pfnChangePitch(edict_t* ent)
-{
-// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnChangePitch:\n"); fclose(fp); }
- (*g_engfuncs.pfnChangePitch)(ent);
-}
-edict_t* pfnFindEntityByString(edict_t *pEdictStartSearchAfter, const char *pszField, const char *pszValue)
-{
-// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnFindEntityByString: %s\n",pszValue); fclose(fp); }
- return (*g_engfuncs.pfnFindEntityByString)(pEdictStartSearchAfter, pszField, pszValue);
-}
-int pfnGetEntityIllum(edict_t* pEnt)
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnGetEntityIllum:\n"); fclose(fp); }
- return (*g_engfuncs.pfnGetEntityIllum)(pEnt);
-}
-edict_t* pfnFindEntityInSphere(edict_t *pEdictStartSearchAfter, const float *org, float rad)
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnFindEntityInSphere:\n"); fclose(fp); }
- return (*g_engfuncs.pfnFindEntityInSphere)(pEdictStartSearchAfter, org, rad);
-}
-edict_t* pfnFindClientInPVS(edict_t *pEdict)
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnFindClientInPVS:\n"); fclose(fp); }
- return (*g_engfuncs.pfnFindClientInPVS)(pEdict);
-}
-edict_t* pfnEntitiesInPVS(edict_t *pplayer)
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnEntitiesInPVS:\n"); fclose(fp); }
- return (*g_engfuncs.pfnEntitiesInPVS)(pplayer);
-}
-void pfnMakeVectors(const float *rgflVector)
-{
-// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnMakeVectors:\n"); fclose(fp); }
- (*g_engfuncs.pfnMakeVectors)(rgflVector);
-}
-void pfnAngleVectors(const float *rgflVector, float *forward, float *right, float *up)
-{
-// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnAngleVectors:\n"); fclose(fp); }
- (*g_engfuncs.pfnAngleVectors)(rgflVector, forward, right, up);
-}
-edict_t* pfnCreateEntity(void)
-{
- edict_t *pent = (*g_engfuncs.pfnCreateEntity)();
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnCreateEntity: %x\n",pent); fclose(fp); }
- return pent;
-}
-void pfnRemoveEntity(edict_t* e)
-{
-// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnRemoveEntity: %x\n",e); fclose(fp); }
- if (debug_engine)
- {
- fp=fopen("bot.txt","a");
- fprintf(fp,"pfnRemoveEntity: %x\n",e);
- if (e->v.model != 0)
- fprintf(fp," model=%s\n", STRING(e->v.model));
- fclose(fp);
- }
-
- (*g_engfuncs.pfnRemoveEntity)(e);
-}
-edict_t* pfnCreateNamedEntity(int className)
-{
- edict_t *pent = (*g_engfuncs.pfnCreateNamedEntity)(className);
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnCreateNamedEntity: edict=%x name=%s\n",pent,STRING(className)); fclose(fp); }
- return pent;
-}
-void pfnMakeStatic(edict_t *ent)
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnMakeStatic:\n"); fclose(fp); }
- (*g_engfuncs.pfnMakeStatic)(ent);
-}
-int pfnEntIsOnFloor(edict_t *e)
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnEntIsOnFloor:\n"); fclose(fp); }
- return (*g_engfuncs.pfnEntIsOnFloor)(e);
-}
-int pfnDropToFloor(edict_t* e)
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnDropToFloor:\n"); fclose(fp); }
- return (*g_engfuncs.pfnDropToFloor)(e);
-}
-int pfnWalkMove(edict_t *ent, float yaw, float dist, int iMode)
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnWalkMove:\n"); fclose(fp); }
- return (*g_engfuncs.pfnWalkMove)(ent, yaw, dist, iMode);
-}
-void pfnSetOrigin(edict_t *e, const float *rgflOrigin)
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnSetOrigin:\n"); fclose(fp); }
- (*g_engfuncs.pfnSetOrigin)(e, rgflOrigin);
-}
-void pfnEmitSound(edict_t *entity, int channel, const char *sample, /*int*/float volume, float attenuation, int fFlags, int pitch)
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnEmitSound:\n"); fclose(fp); }
- (*g_engfuncs.pfnEmitSound)(entity, channel, sample, volume, attenuation, fFlags, pitch);
-}
-void pfnEmitAmbientSound(edict_t *entity, float *pos, const char *samp, float vol, float attenuation, int fFlags, int pitch)
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnEmitAmbientSound:\n"); fclose(fp); }
- (*g_engfuncs.pfnEmitAmbientSound)(entity, pos, samp, vol, attenuation, fFlags, pitch);
-}
-void pfnTraceLine(const float *v1, const float *v2, int fNoMonsters, edict_t *pentToSkip, TraceResult *ptr)
-{
-// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnTraceLine:\n"); fclose(fp); }
- (*g_engfuncs.pfnTraceLine)(v1, v2, fNoMonsters, pentToSkip, ptr);
-}
-void pfnTraceToss(edict_t* pent, edict_t* pentToIgnore, TraceResult *ptr)
-{
-// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnTraceToss:\n"); fclose(fp); }
- (*g_engfuncs.pfnTraceToss)(pent, pentToIgnore, ptr);
-}
-int pfnTraceMonsterHull(edict_t *pEdict, const float *v1, const float *v2, int fNoMonsters, edict_t *pentToSkip, TraceResult *ptr)
-{
-// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnTraceMonsterHull:\n"); fclose(fp); }
- return (*g_engfuncs.pfnTraceMonsterHull)(pEdict, v1, v2, fNoMonsters, pentToSkip, ptr);
-}
-void pfnTraceHull(const float *v1, const float *v2, int fNoMonsters, int hullNumber, edict_t *pentToSkip, TraceResult *ptr)
-{
-// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnTraceHull:\n"); fclose(fp); }
- (*g_engfuncs.pfnTraceHull)(v1, v2, fNoMonsters, hullNumber, pentToSkip, ptr);
-}
-void pfnTraceModel(const float *v1, const float *v2, int hullNumber, edict_t *pent, TraceResult *ptr)
-{
-// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnTraceModel:\n"); fclose(fp); }
- (*g_engfuncs.pfnTraceModel)(v1, v2, hullNumber, pent, ptr);
-}
-const char *pfnTraceTexture(edict_t *pTextureEntity, const float *v1, const float *v2 )
-{
-// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnTraceTexture:\n"); fclose(fp); }
- return (*g_engfuncs.pfnTraceTexture)(pTextureEntity, v1, v2);
-}
-void pfnTraceSphere(const float *v1, const float *v2, int fNoMonsters, float radius, edict_t *pentToSkip, TraceResult *ptr)
-{
-// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnTraceSphere:\n"); fclose(fp); }
- (*g_engfuncs.pfnTraceSphere)(v1, v2, fNoMonsters, radius, pentToSkip, ptr);
-}
-void pfnGetAimVector(edict_t* ent, float speed, float *rgflReturn)
-{
-// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnGetAimVector:\n"); fclose(fp); }
- (*g_engfuncs.pfnGetAimVector)(ent, speed, rgflReturn);
-}
-void pfnServerCommand(char* str)
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnServerCommand: %s\n",str); fclose(fp); }
- (*g_engfuncs.pfnServerCommand)(str);
-}
-void pfnServerExecute(void)
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnServerExecute:\n"); fclose(fp); }
- (*g_engfuncs.pfnServerExecute)();
-}
-void pfnClientCommand(edict_t* pEdict, char* szFmt, ...)
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnClientCommand=%s\n",szFmt); fclose(fp); }
- return;
-}
-void pfnParticleEffect(const float *org, const float *dir, float color, float count)
-{
-// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnParticleEffect:\n"); fclose(fp); }
- (*g_engfuncs.pfnParticleEffect)(org, dir, color, count);
-}
-void pfnLightStyle(int style, char* val)
-{
-// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnLightStyle:\n"); fclose(fp); }
- (*g_engfuncs.pfnLightStyle)(style, val);
-}
-int pfnDecalIndex(const char *name)
-{
-// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnDecalIndex:\n"); fclose(fp); }
- return (*g_engfuncs.pfnDecalIndex)(name);
-}
-int pfnPointContents(const float *rgflVector)
-{
-// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnPointContents:\n"); fclose(fp); }
- return (*g_engfuncs.pfnPointContents)(rgflVector);
-}
-void pfnMessageBegin(int msg_dest, int msg_type, const float *pOrigin, edict_t *ed)
-{
- if (gpGlobals->deathmatch)
- {
- int index = -1;
-
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnMessageBegin: edict=%x dest=%d type=%d\n",ed,msg_dest,msg_type); fclose(fp); }
-
- if (ed)
- {
- index = UTIL_GetBotIndex(ed);
-
- // is this message for a bot?
- if (index != -1)
- {
- botMsgFunction = NULL; // no msg function until known otherwise
- botMsgEndFunction = NULL; // no msg end function until known otherwise
- botMsgIndex = index; // index of bot receiving message
-
- if (mod_id == VALVE_DLL)
- {
- if (msg_type == message_WeaponList)
- botMsgFunction = BotClient_Valve_WeaponList;
- else if (msg_type == message_CurWeapon)
- botMsgFunction = BotClient_Valve_CurrentWeapon;
- else if (msg_type == message_AmmoX)
- botMsgFunction = BotClient_Valve_AmmoX;
- else if (msg_type == message_AmmoPickup)
- botMsgFunction = BotClient_Valve_AmmoPickup;
- else if (msg_type == message_WeapPickup)
- botMsgFunction = BotClient_Valve_WeaponPickup;
- else if (msg_type == message_ItemPickup)
- botMsgFunction = BotClient_Valve_ItemPickup;
- else if (msg_type == message_Health)
- botMsgFunction = BotClient_Valve_Health;
- else if (msg_type == message_Battery)
- botMsgFunction = BotClient_Valve_Battery;
- else if (msg_type == message_Damage)
- botMsgFunction = BotClient_Valve_Damage;
- else if (msg_type == message_ScreenFade)
- botMsgFunction = BotClient_Valve_ScreenFade;
- }
- else if (mod_id == TFC_DLL)
- {
- if (msg_type == message_VGUI)
- botMsgFunction = BotClient_TFC_VGUI;
- else if (msg_type == message_WeaponList)
- botMsgFunction = BotClient_TFC_WeaponList;
- else if (msg_type == message_CurWeapon)
- botMsgFunction = BotClient_TFC_CurrentWeapon;
- else if (msg_type == message_AmmoX)
- botMsgFunction = BotClient_TFC_AmmoX;
- else if (msg_type == message_AmmoPickup)
- botMsgFunction = BotClient_TFC_AmmoPickup;
- else if (msg_type == message_WeapPickup)
- botMsgFunction = BotClient_TFC_WeaponPickup;
- else if (msg_type == message_ItemPickup)
- botMsgFunction = BotClient_TFC_ItemPickup;
- else if (msg_type == message_Health)
- botMsgFunction = BotClient_TFC_Health;
- else if (msg_type == message_Battery)
- botMsgFunction = BotClient_TFC_Battery;
- else if (msg_type == message_Damage)
- botMsgFunction = BotClient_TFC_Damage;
- else if (msg_type == message_ScreenFade)
- botMsgFunction = BotClient_TFC_ScreenFade;
- }
- else if (mod_id == CSTRIKE_DLL)
- {
- if (msg_type == message_VGUI)
- botMsgFunction = BotClient_CS_VGUI;
- else if (msg_type == message_ShowMenu)
- botMsgFunction = BotClient_CS_ShowMenu;
- else if (msg_type == message_WeaponList)
- botMsgFunction = BotClient_CS_WeaponList;
- else if (msg_type == message_CurWeapon)
- botMsgFunction = BotClient_CS_CurrentWeapon;
- else if (msg_type == message_AmmoX)
- botMsgFunction = BotClient_CS_AmmoX;
- else if (msg_type == message_WeapPickup)
- botMsgFunction = BotClient_CS_WeaponPickup;
- else if (msg_type == message_AmmoPickup)
- botMsgFunction = BotClient_CS_AmmoPickup;
- else if (msg_type == message_ItemPickup)
- botMsgFunction = BotClient_CS_ItemPickup;
- else if (msg_type == message_Health)
- botMsgFunction = BotClient_CS_Health;
- else if (msg_type == message_Battery)
- botMsgFunction = BotClient_CS_Battery;
- else if (msg_type == message_Damage)
- botMsgFunction = BotClient_CS_Damage;
- else if (msg_type == message_Money)
- botMsgFunction = BotClient_CS_Money;
- else if (msg_type == message_ScreenFade)
- botMsgFunction = BotClient_CS_ScreenFade;
- }
- else if (mod_id == GEARBOX_DLL)
- {
- if (msg_type == message_VGUI)
- botMsgFunction = BotClient_Gearbox_VGUI;
- else if (msg_type == message_WeaponList)
- botMsgFunction = BotClient_Gearbox_WeaponList;
- else if (msg_type == message_CurWeapon)
- botMsgFunction = BotClient_Gearbox_CurrentWeapon;
- else if (msg_type == message_AmmoX)
- botMsgFunction = BotClient_Gearbox_AmmoX;
- else if (msg_type == message_AmmoPickup)
- botMsgFunction = BotClient_Gearbox_AmmoPickup;
- else if (msg_type == message_WeapPickup)
- botMsgFunction = BotClient_Gearbox_WeaponPickup;
- else if (msg_type == message_ItemPickup)
- botMsgFunction = BotClient_Gearbox_ItemPickup;
- else if (msg_type == message_Health)
- botMsgFunction = BotClient_Gearbox_Health;
- else if (msg_type == message_Battery)
- botMsgFunction = BotClient_Gearbox_Battery;
- else if (msg_type == message_Damage)
- botMsgFunction = BotClient_Gearbox_Damage;
- else if (msg_type == message_ScreenFade)
- botMsgFunction = BotClient_Gearbox_ScreenFade;
- }
- else if (mod_id == FRONTLINE_DLL)
- {
- if (msg_type == message_VGUI)
- botMsgFunction = BotClient_FLF_VGUI;
- else if (msg_type == message_WeaponList)
- botMsgFunction = BotClient_FLF_WeaponList;
- else if (msg_type == message_CurWeapon)
- botMsgFunction = BotClient_FLF_CurrentWeapon;
- else if (msg_type == message_AmmoX)
- botMsgFunction = BotClient_FLF_AmmoX;
- else if (msg_type == message_AmmoPickup)
- botMsgFunction = BotClient_FLF_AmmoPickup;
- else if (msg_type == message_WeapPickup)
- botMsgFunction = BotClient_FLF_WeaponPickup;
- else if (msg_type == message_ItemPickup)
- botMsgFunction = BotClient_FLF_ItemPickup;
- else if (msg_type == message_Health)
- botMsgFunction = BotClient_FLF_Health;
- else if (msg_type == message_Battery)
- botMsgFunction = BotClient_FLF_Battery;
- else if (msg_type == message_Damage)
- botMsgFunction = BotClient_FLF_Damage;
- else if (msg_type == message_TextMsg)
- botMsgFunction = BotClient_FLF_TextMsg;
- else if (msg_type == message_WarmUp)
- botMsgFunction = BotClient_FLF_WarmUp;
- else if (msg_type == message_ScreenFade)
- botMsgFunction = BotClient_FLF_ScreenFade;
- else if (msg_type == 23) // SVC_TEMPENTITY
- {
- botMsgFunction = BotClient_FLF_TempEntity;
- botMsgEndFunction = BotClient_FLF_TempEntity;
- }
- }
- else if (mod_id == AVH_DLL)
- {
- if (msg_type == message_SetPlayMode)
- botMsgFunction = BotClient_AVH_SetPlayMode;
- else if (msg_type == message_AmmoX)
- botMsgFunction = BotClient_Valve_AmmoX;
- else if (msg_type == message_AmmoPickup)
- botMsgFunction = BotClient_Valve_AmmoPickup;
- else if (msg_type == message_WeapPickup)
- botMsgFunction = BotClient_Valve_WeaponPickup;
- else if (msg_type == message_ItemPickup)
- botMsgFunction = BotClient_Valve_ItemPickup;
- else if (msg_type == message_WeaponList)
- botMsgFunction = BotClient_Valve_WeaponList;
- else if (msg_type == message_SetOrder)
- botMsgFunction = BotClient_AVH_SetOrder;
- else if (msg_type == message_SetResources)
- botMsgFunction = BotClient_AVH_SetResources;
- }
- }
- }
- else if (msg_dest == MSG_ALL)
- {
- botMsgFunction = NULL; // no msg function until known otherwise
- botMsgIndex = -1; // index of bot receiving message (none)
-
- if (mod_id == VALVE_DLL)
- {
- if (msg_type == message_DeathMsg)
- botMsgFunction = BotClient_Valve_DeathMsg;
- }
- else if (mod_id == TFC_DLL)
- {
- if (msg_type == message_DeathMsg)
- botMsgFunction = BotClient_TFC_DeathMsg;
- }
- else if (mod_id == CSTRIKE_DLL)
- {
- if (msg_type == message_DeathMsg)
- botMsgFunction = BotClient_CS_DeathMsg;
- }
- else if (mod_id == GEARBOX_DLL)
- {
- if (msg_type == message_DeathMsg)
- botMsgFunction = BotClient_Gearbox_DeathMsg;
- }
- else if (mod_id == FRONTLINE_DLL)
- {
- if (msg_type == message_DeathMsg)
- botMsgFunction = BotClient_FLF_DeathMsg;
- else if (msg_type == message_WarmUp)
- botMsgFunction = BotClient_FLF_WarmUpAll;
- else if (msg_type == message_WinMessage)
- botMsgFunction = BotClient_FLF_WinMessage;
- }
- }
- }
-
- (*g_engfuncs.pfnMessageBegin)(msg_dest, msg_type, pOrigin, ed);
-}
-void pfnMessageEnd(void)
-{
- if (gpGlobals->deathmatch)
- {
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnMessageEnd:\n"); fclose(fp); }
-
- if (botMsgEndFunction)
- (*botMsgEndFunction)(NULL, botMsgIndex); // NULL indicated msg end
-
- // clear out the bot message function pointers...
- botMsgFunction = NULL;
- botMsgEndFunction = NULL;
- }
-
- (*g_engfuncs.pfnMessageEnd)();
-}
-void pfnWriteByte(int iValue)
-{
- if (gpGlobals->deathmatch)
- {
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnWriteByte: %d\n",iValue); fclose(fp); }
-
- // if this message is for a bot, call the client message function...
- if (botMsgFunction)
- (*botMsgFunction)((void *)&iValue, botMsgIndex);
- }
-
- (*g_engfuncs.pfnWriteByte)(iValue);
-}
-void pfnWriteChar(int iValue)
-{
- if (gpGlobals->deathmatch)
- {
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnWriteChar: %d\n",iValue); fclose(fp); }
-
- // if this message is for a bot, call the client message function...
- if (botMsgFunction)
- (*botMsgFunction)((void *)&iValue, botMsgIndex);
- }
-
- (*g_engfuncs.pfnWriteChar)(iValue);
-}
-void pfnWriteShort(int iValue)
-{
- if (gpGlobals->deathmatch)
- {
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnWriteShort: %d\n",iValue); fclose(fp); }
-
- // if this message is for a bot, call the client message function...
- if (botMsgFunction)
- (*botMsgFunction)((void *)&iValue, botMsgIndex);
- }
-
- (*g_engfuncs.pfnWriteShort)(iValue);
-}
-void pfnWriteLong(int iValue)
-{
- if (gpGlobals->deathmatch)
- {
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnWriteLong: %d\n",iValue); fclose(fp); }
-
- // if this message is for a bot, call the client message function...
- if (botMsgFunction)
- (*botMsgFunction)((void *)&iValue, botMsgIndex);
- }
-
- (*g_engfuncs.pfnWriteLong)(iValue);
-}
-void pfnWriteAngle(float flValue)
-{
- if (gpGlobals->deathmatch)
- {
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnWriteAngle: %f\n",flValue); fclose(fp); }
-
- // if this message is for a bot, call the client message function...
- if (botMsgFunction)
- (*botMsgFunction)((void *)&flValue, botMsgIndex);
- }
-
- (*g_engfuncs.pfnWriteAngle)(flValue);
-}
-void pfnWriteCoord(float flValue)
-{
- if (gpGlobals->deathmatch)
- {
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnWriteCoord: %f\n",flValue); fclose(fp); }
-
- // if this message is for a bot, call the client message function...
- if (botMsgFunction)
- (*botMsgFunction)((void *)&flValue, botMsgIndex);
- }
-
- (*g_engfuncs.pfnWriteCoord)(flValue);
-}
-void pfnWriteString(const char *sz)
-{
- if (gpGlobals->deathmatch)
- {
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnWriteString: %s\n",sz); fclose(fp); }
-
- // if this message is for a bot, call the client message function...
- if (botMsgFunction)
- (*botMsgFunction)((void *)sz, botMsgIndex);
- }
-
- (*g_engfuncs.pfnWriteString)(sz);
-}
-void pfnWriteEntity(int iValue)
-{
- if (gpGlobals->deathmatch)
- {
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnWriteEntity: %d\n",iValue); fclose(fp); }
-
- // if this message is for a bot, call the client message function...
- if (botMsgFunction)
- (*botMsgFunction)((void *)&iValue, botMsgIndex);
- }
-
- (*g_engfuncs.pfnWriteEntity)(iValue);
-}
-void pfnCVarRegister(cvar_t *pCvar)
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnCVarRegister:\n"); fclose(fp); }
- (*g_engfuncs.pfnCVarRegister)(pCvar);
-}
-float pfnCVarGetFloat(const char *szVarName)
-{
-// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnCVarGetFloat: %s\n",szVarName); fclose(fp); }
- return (*g_engfuncs.pfnCVarGetFloat)(szVarName);
-}
-const char* pfnCVarGetString(const char *szVarName)
-{
-// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnCVarGetString:\n"); fclose(fp); }
- return (*g_engfuncs.pfnCVarGetString)(szVarName);
-}
-void pfnCVarSetFloat(const char *szVarName, float flValue)
-{
-// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnCVarSetFloat:\n"); fclose(fp); }
- (*g_engfuncs.pfnCVarSetFloat)(szVarName, flValue);
-}
-void pfnCVarSetString(const char *szVarName, const char *szValue)
-{
-// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnCVarSetString:\n"); fclose(fp); }
- (*g_engfuncs.pfnCVarSetString)(szVarName, szValue);
-}
-void* pfnPvAllocEntPrivateData(edict_t *pEdict, long cb)
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnPvAllocEntPrivateData:\n"); fclose(fp); }
- return (*g_engfuncs.pfnPvAllocEntPrivateData)(pEdict, cb);
-}
-void* pfnPvEntPrivateData(edict_t *pEdict)
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnPvEntPrivateData:\n"); fclose(fp); }
- return (*g_engfuncs.pfnPvEntPrivateData)(pEdict);
-}
-void pfnFreeEntPrivateData(edict_t *pEdict)
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnFreeEntPrivateData:\n"); fclose(fp); }
- (*g_engfuncs.pfnFreeEntPrivateData)(pEdict);
-}
-const char* pfnSzFromIndex(int iString)
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnSzFromIndex:\n"); fclose(fp); }
- return (*g_engfuncs.pfnSzFromIndex)(iString);
-}
-int pfnAllocString(const char *szValue)
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnAllocString:\n"); fclose(fp); }
- return (*g_engfuncs.pfnAllocString)(szValue);
-}
-entvars_t* pfnGetVarsOfEnt(edict_t *pEdict)
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnGetVarsOfEnt:\n"); fclose(fp); }
- return (*g_engfuncs.pfnGetVarsOfEnt)(pEdict);
-}
-edict_t* pfnPEntityOfEntOffset(int iEntOffset)
-{
-// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnPEntityOfEntOffset:\n"); fclose(fp); }
- return (*g_engfuncs.pfnPEntityOfEntOffset)(iEntOffset);
-}
-int pfnEntOffsetOfPEntity(const edict_t *pEdict)
-{
-// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnEntOffsetOfPEntity: %x\n",pEdict); fclose(fp); }
- return (*g_engfuncs.pfnEntOffsetOfPEntity)(pEdict);
-}
-int pfnIndexOfEdict(const edict_t *pEdict)
-{
-// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnIndexOfEdict: %x\n",pEdict); fclose(fp); }
- return (*g_engfuncs.pfnIndexOfEdict)(pEdict);
-}
-edict_t* pfnPEntityOfEntIndex(int iEntIndex)
-{
-// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnPEntityOfEntIndex:\n"); fclose(fp); }
- return (*g_engfuncs.pfnPEntityOfEntIndex)(iEntIndex);
-}
-edict_t* pfnFindEntityByVars(entvars_t* pvars)
-{
-// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnFindEntityByVars:\n"); fclose(fp); }
- return (*g_engfuncs.pfnFindEntityByVars)(pvars);
-}
-void* pfnGetModelPtr(edict_t* pEdict)
-{
-// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnGetModelPtr: %x\n",pEdict); fclose(fp); }
- return (*g_engfuncs.pfnGetModelPtr)(pEdict);
-}
-int pfnRegUserMsg(const char *pszName, int iSize)
-{
- int msg;
-
- msg = (*g_engfuncs.pfnRegUserMsg)(pszName, iSize);
-
- //if (gpGlobals->deathmatch)
- //{
-#ifdef _DEBUG
- fp=fopen("bot.txt","a"); fprintf(fp,"pfnRegUserMsg: pszName=%s msg=%d\n",pszName,msg); fclose(fp);
-#endif
-
- if (mod_id == VALVE_DLL)
- {
- if (strcmp(pszName, "WeaponList") == 0)
- message_WeaponList = msg;
- else if (strcmp(pszName, "CurWeapon") == 0)
- message_CurWeapon = msg;
- else if (strcmp(pszName, "AmmoX") == 0)
- message_AmmoX = msg;
- else if (strcmp(pszName, "AmmoPickup") == 0)
- message_AmmoPickup = msg;
- else if (strcmp(pszName, "WeapPickup") == 0)
- message_WeapPickup = msg;
- else if (strcmp(pszName, "ItemPickup") == 0)
- message_ItemPickup = msg;
- else if (strcmp(pszName, "Health") == 0)
- message_Health = msg;
- else if (strcmp(pszName, "Battery") == 0)
- message_Battery = msg;
- else if (strcmp(pszName, "Damage") == 0)
- message_Damage = msg;
- else if (strcmp(pszName, "DeathMsg") == 0)
- message_DeathMsg = msg;
- else if (strcmp(pszName, "ScreenFade") == 0)
- message_ScreenFade = msg;
- }
- else if (mod_id == TFC_DLL)
- {
- if (strcmp(pszName, "VGUIMenu") == 0)
- message_VGUI = msg;
- else if (strcmp(pszName, "WeaponList") == 0)
- message_WeaponList = msg;
- else if (strcmp(pszName, "CurWeapon") == 0)
- message_CurWeapon = msg;
- else if (strcmp(pszName, "AmmoX") == 0)
- message_AmmoX = msg;
- else if (strcmp(pszName, "AmmoPickup") == 0)
- message_AmmoPickup = msg;
- else if (strcmp(pszName, "WeapPickup") == 0)
- message_WeapPickup = msg;
- else if (strcmp(pszName, "ItemPickup") == 0)
- message_ItemPickup = msg;
- else if (strcmp(pszName, "Health") == 0)
- message_Health = msg;
- else if (strcmp(pszName, "Battery") == 0)
- message_Battery = msg;
- else if (strcmp(pszName, "Damage") == 0)
- message_Damage = msg;
- else if (strcmp(pszName, "DeathMsg") == 0)
- message_DeathMsg = msg;
- else if (strcmp(pszName, "ScreenFade") == 0)
- message_ScreenFade = msg;
- }
- else if (mod_id == CSTRIKE_DLL)
- {
- if (strcmp(pszName, "VGUIMenu") == 0)
- message_VGUI = msg;
- else if (strcmp(pszName, "ShowMenu") == 0)
- message_ShowMenu = msg;
- else if (strcmp(pszName, "WeaponList") == 0)
- message_WeaponList = msg;
- else if (strcmp(pszName, "CurWeapon") == 0)
- message_CurWeapon = msg;
- else if (strcmp(pszName, "AmmoX") == 0)
- message_AmmoX = msg;
- else if (strcmp(pszName, "AmmoPickup") == 0)
- message_AmmoPickup = msg;
- else if (strcmp(pszName, "WeapPickup") == 0)
- message_WeapPickup = msg;
- else if (strcmp(pszName, "ItemPickup") == 0)
- message_ItemPickup = msg;
- else if (strcmp(pszName, "Health") == 0)
- message_Health = msg;
- else if (strcmp(pszName, "Battery") == 0)
- message_Battery = msg;
- else if (strcmp(pszName, "Damage") == 0)
- message_Damage = msg;
- else if (strcmp(pszName, "Money") == 0)
- message_Money = msg;
- else if (strcmp(pszName, "DeathMsg") == 0)
- message_DeathMsg = msg;
- else if (strcmp(pszName, "ScreenFade") == 0)
- message_ScreenFade = msg;
- }
- else if (mod_id == GEARBOX_DLL)
- {
- if (strcmp(pszName, "VGUIMenu") == 0)
- message_VGUI = msg;
- else if (strcmp(pszName, "WeaponList") == 0)
- message_WeaponList = msg;
- else if (strcmp(pszName, "CurWeapon") == 0)
- message_CurWeapon = msg;
- else if (strcmp(pszName, "AmmoX") == 0)
- message_AmmoX = msg;
- else if (strcmp(pszName, "AmmoPickup") == 0)
- message_AmmoPickup = msg;
- else if (strcmp(pszName, "WeapPickup") == 0)
- message_WeapPickup = msg;
- else if (strcmp(pszName, "ItemPickup") == 0)
- message_ItemPickup = msg;
- else if (strcmp(pszName, "Health") == 0)
- message_Health = msg;
- else if (strcmp(pszName, "Battery") == 0)
- message_Battery = msg;
- else if (strcmp(pszName, "Damage") == 0)
- message_Damage = msg;
- else if (strcmp(pszName, "DeathMsg") == 0)
- message_DeathMsg = msg;
- else if (strcmp(pszName, "ScreenFade") == 0)
- message_ScreenFade = msg;
- }
- else if (mod_id == FRONTLINE_DLL)
- {
- if (strcmp(pszName, "VGUIMenu") == 0)
- message_VGUI = msg;
- else if (strcmp(pszName, "WeaponList") == 0)
- message_WeaponList = msg;
- else if (strcmp(pszName, "CurWeapon") == 0)
- message_CurWeapon = msg;
- else if (strcmp(pszName, "AmmoX") == 0)
- message_AmmoX = msg;
- else if (strcmp(pszName, "AmmoPickup") == 0)
- message_AmmoPickup = msg;
- else if (strcmp(pszName, "WeapPickup") == 0)
- message_WeapPickup = msg;
- else if (strcmp(pszName, "ItemPickup") == 0)
- message_ItemPickup = msg;
- else if (strcmp(pszName, "Health") == 0)
- message_Health = msg;
- else if (strcmp(pszName, "Battery") == 0)
- message_Battery = msg;
- else if (strcmp(pszName, "Damage") == 0)
- message_Damage = msg;
- else if (strcmp(pszName, "DeathMsg") == 0)
- message_DeathMsg = msg;
- else if (strcmp(pszName, "TextMsg") == 0)
- message_TextMsg = msg;
- else if (strcmp(pszName, "WarmUp") == 0)
- message_WarmUp = msg;
- else if (strcmp(pszName, "WinMessage") == 0)
- message_WinMessage = msg;
- else if (strcmp(pszName, "ScreenFade") == 0)
- message_ScreenFade = msg;
- }
- else if (mod_id == AVH_DLL)
- {
- if (strcmp(pszName, "SetPlayMode") == 0)
- message_SetPlayMode = msg;
- else if (strcmp(pszName, "AmmoX") == 0)
- message_AmmoX = msg;
- else if (strcmp(pszName, "AmmoPickup") == 0)
- message_AmmoPickup = msg;
- else if (strcmp(pszName, "WeapPickup") == 0)
- message_WeapPickup = msg;
- else if (strcmp(pszName, "ItemPickup") == 0)
- message_ItemPickup = msg;
- else if (strcmp(pszName, "WeaponList") == 0)
- message_WeaponList = msg;
- else if (strcmp(pszName, "SetOrder") == 0)
- message_SetOrder = msg;
- else if (strcmp(pszName, "SetRsrces") == 0)
- message_SetResources = msg;
-
- }
- //}
-
- return msg;
-}
-void pfnAnimationAutomove(const edict_t* pEdict, float flTime)
-{
-// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnAnimationAutomove:\n"); fclose(fp); }
- (*g_engfuncs.pfnAnimationAutomove)(pEdict, flTime);
-}
-void pfnGetBonePosition(const edict_t* pEdict, int iBone, float *rgflOrigin, float *rgflAngles )
-{
-// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnGetBonePosition:\n"); fclose(fp); }
- (*g_engfuncs.pfnGetBonePosition)(pEdict, iBone, rgflOrigin, rgflAngles);
-}
-unsigned long pfnFunctionFromName( const char *pName )
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnFunctionFromName:\n"); fclose(fp); }
- return (*g_engfuncs.pfnFunctionFromName)(pName);
-}
-const char *pfnNameForFunction( unsigned long function )
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnNameForFunction:\n"); fclose(fp); }
- const char* theName = (*g_engfuncs.pfnNameForFunction)(function);
- return theName;
-}
-void pfnClientPrintf( edict_t* pEdict, PRINT_TYPE ptype, const char *szMsg )
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnClientPrintf:\n"); fclose(fp); }
- (*g_engfuncs.pfnClientPrintf)(pEdict, ptype, szMsg);
-}
-void pfnServerPrint( const char *szMsg )
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnServerPrint: %s\n",szMsg); fclose(fp); }
- (*g_engfuncs.pfnServerPrint)(szMsg);
-}
-void pfnGetAttachment(const edict_t *pEdict, int iAttachment, float *rgflOrigin, float *rgflAngles )
-{
-// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnGetAttachment:\n"); fclose(fp); }
- (*g_engfuncs.pfnGetAttachment)(pEdict, iAttachment, rgflOrigin, rgflAngles);
-}
-void pfnCRC32_Init(CRC32_t *pulCRC)
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnCRC32_Init:\n"); fclose(fp); }
- (*g_engfuncs.pfnCRC32_Init)(pulCRC);
-}
-void pfnCRC32_ProcessBuffer(CRC32_t *pulCRC, void *p, int len)
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnCRC32_ProcessBuffer:\n"); fclose(fp); }
- (*g_engfuncs.pfnCRC32_ProcessBuffer)(pulCRC, p, len);
-}
-void pfnCRC32_ProcessByte(CRC32_t *pulCRC, unsigned char ch)
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnCRC32_ProcessByte:\n"); fclose(fp); }
- (*g_engfuncs.pfnCRC32_ProcessByte)(pulCRC, ch);
-}
-CRC32_t pfnCRC32_Final(CRC32_t pulCRC)
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnCRC32_Final:\n"); fclose(fp); }
- return (*g_engfuncs.pfnCRC32_Final)(pulCRC);
-}
-long pfnRandomLong(long lLow, long lHigh)
-{
-// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnRandomLong: lLow=%d lHigh=%d\n",lLow,lHigh); fclose(fp); }
- return (*g_engfuncs.pfnRandomLong)(lLow, lHigh);
-}
-float pfnRandomFloat(float flLow, float flHigh)
-{
-// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnRandomFloat:\n"); fclose(fp); }
- return (*g_engfuncs.pfnRandomFloat)(flLow, flHigh);
-}
-void pfnSetView(const edict_t *pClient, const edict_t *pViewent )
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnSetView:\n"); fclose(fp); }
- (*g_engfuncs.pfnSetView)(pClient, pViewent);
-}
-float pfnTime( void )
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnTime:\n"); fclose(fp); }
- return (*g_engfuncs.pfnTime)();
-}
-void pfnCrosshairAngle(const edict_t *pClient, float pitch, float yaw)
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnCrosshairAngle:\n"); fclose(fp); }
- (*g_engfuncs.pfnCrosshairAngle)(pClient, pitch, yaw);
-}
-byte *pfnLoadFileForMe(char *filename, int *pLength)
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnLoadFileForMe: filename=%s\n",filename); fclose(fp); }
- return (*g_engfuncs.pfnLoadFileForMe)(filename, pLength);
-}
-void pfnFreeFile(void *buffer)
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnFreeFile:\n"); fclose(fp); }
- (*g_engfuncs.pfnFreeFile)(buffer);
-}
-void pfnEndSection(const char *pszSectionName)
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnEndSection:\n"); fclose(fp); }
- (*g_engfuncs.pfnEndSection)(pszSectionName);
-}
-int pfnCompareFileTime(char *filename1, char *filename2, int *iCompare)
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnCompareFileTime:\n"); fclose(fp); }
- return (*g_engfuncs.pfnCompareFileTime)(filename1, filename2, iCompare);
-}
-void pfnGetGameDir(char *szGetGameDir)
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnGetGameDir:\n"); fclose(fp); }
- (*g_engfuncs.pfnGetGameDir)(szGetGameDir);
-}
-void pfnCvar_RegisterVariable(cvar_t *variable)
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnCvar_RegisterVariable:\n"); fclose(fp); }
- (*g_engfuncs.pfnCvar_RegisterVariable)(variable);
-}
-void pfnFadeClientVolume(const edict_t *pEdict, int fadePercent, int fadeOutSeconds, int holdTime, int fadeInSeconds)
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnFadeClientVolume:\n"); fclose(fp); }
- (*g_engfuncs.pfnFadeClientVolume)(pEdict, fadePercent, fadeOutSeconds, holdTime, fadeInSeconds);
-}
-void pfnSetClientMaxspeed(const edict_t *pEdict, float fNewMaxspeed)
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnSetClientMaxspeed: edict=%x %f\n",pEdict,fNewMaxspeed); fclose(fp); }
- (*g_engfuncs.pfnSetClientMaxspeed)(pEdict, fNewMaxspeed);
-}
-edict_t * pfnCreateFakeClient(const char *netname)
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnCreateFakeClient:\n"); fclose(fp); }
- return (*g_engfuncs.pfnCreateFakeClient)(netname);
-}
-void pfnRunPlayerMove(edict_t *fakeclient, const float *viewangles, float forwardmove, float sidemove, float upmove, unsigned short buttons, byte impulse, byte msec )
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnRunPlayerMove:\n"); fclose(fp); }
- (*g_engfuncs.pfnRunPlayerMove)(fakeclient, viewangles, forwardmove, sidemove, upmove, buttons, impulse, msec);
-}
-int pfnNumberOfEntities(void)
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnNumberOfEntities:\n"); fclose(fp); }
- return (*g_engfuncs.pfnNumberOfEntities)();
-}
-char* pfnGetInfoKeyBuffer(edict_t *e)
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnGetInfoKeyBuffer:\n"); fclose(fp); }
- return (*g_engfuncs.pfnGetInfoKeyBuffer)(e);
-}
-char* pfnInfoKeyValue(char *infobuffer, char *key)
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnInfoKeyValue: %s %s\n",infobuffer,key); fclose(fp); }
- return (*g_engfuncs.pfnInfoKeyValue)(infobuffer, key);
-}
-void pfnSetKeyValue(char *infobuffer, char *key, char *value)
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnSetKeyValue: %s %s\n",key,value); fclose(fp); }
- (*g_engfuncs.pfnSetKeyValue)(infobuffer, key, value);
-}
-void pfnSetClientKeyValue(int clientIndex, char *infobuffer, char *key, char *value)
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnSetClientKeyValue: %s %s\n",key,value); fclose(fp); }
- (*g_engfuncs.pfnSetClientKeyValue)(clientIndex, infobuffer, key, value);
-}
-int pfnIsMapValid(char *filename)
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnIsMapValid:\n"); fclose(fp); }
- return (*g_engfuncs.pfnIsMapValid)(filename);
-}
-void pfnStaticDecal( const float *origin, int decalIndex, int entityIndex, int modelIndex )
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnStaticDecal:\n"); fclose(fp); }
- (*g_engfuncs.pfnStaticDecal)(origin, decalIndex, entityIndex, modelIndex);
-}
-int pfnPrecacheGeneric(char* s)
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnPrecacheGeneric: %s\n",s); fclose(fp); }
- return (*g_engfuncs.pfnPrecacheGeneric)(s);
-}
-int pfnGetPlayerUserId(edict_t *e )
-{
- if (gpGlobals->deathmatch)
- {
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnGetPlayerUserId: %x\n",e); fclose(fp); }
-
- if (mod_id == GEARBOX_DLL)
- {
- // is this edict a bot?
- if (UTIL_GetBotPointer( e ))
- return 0; // don't return a valid index (so bot won't get kicked)
- }
- }
-
- return (*g_engfuncs.pfnGetPlayerUserId)(e);
-}
-void pfnBuildSoundMsg(edict_t *entity, int channel, const char *sample, /*int*/float volume, float attenuation, int fFlags, int pitch, int msg_dest, int msg_type, const float *pOrigin, edict_t *ed)
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnBuildSoundMsg:\n"); fclose(fp); }
- (*g_engfuncs.pfnBuildSoundMsg)(entity, channel, sample, volume, attenuation, fFlags, pitch, msg_dest, msg_type, pOrigin, ed);
-}
-int pfnIsDedicatedServer(void)
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnIsDedicatedServer:\n"); fclose(fp); }
- return (*g_engfuncs.pfnIsDedicatedServer)();
-}
-cvar_t* pfnCVarGetPointer(const char *szVarName)
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnCVarGetPointer: %s\n",szVarName); fclose(fp); }
- return (*g_engfuncs.pfnCVarGetPointer)(szVarName);
-}
-unsigned int pfnGetPlayerWONId(edict_t *e)
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnGetPlayerWONId: %x\n",e); fclose(fp); }
- return (*g_engfuncs.pfnGetPlayerWONId)(e);
-}
-
-
-// new stuff for SDK 2.0
-
-void pfnInfo_RemoveKey(char *s, const char *key)
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnInfo_RemoveKey:\n"); fclose(fp); }
- (*g_engfuncs.pfnInfo_RemoveKey)(s, key);
-}
-const char *pfnGetPhysicsKeyValue(const edict_t *pClient, const char *key)
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnGetPhysicsKeyValue:\n"); fclose(fp); }
- return (*g_engfuncs.pfnGetPhysicsKeyValue)(pClient, key);
-}
-void pfnSetPhysicsKeyValue(const edict_t *pClient, const char *key, const char *value)
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnSetPhysicsKeyValue:\n"); fclose(fp); }
- (*g_engfuncs.pfnSetPhysicsKeyValue)(pClient, key, value);
-}
-const char *pfnGetPhysicsInfoString(const edict_t *pClient)
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnGetPhysicsInfoString:\n"); fclose(fp); }
- return (*g_engfuncs.pfnGetPhysicsInfoString)(pClient);
-}
-unsigned short pfnPrecacheEvent(int type, const char *psz)
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnPrecacheEvent:\n"); fclose(fp); }
- return (*g_engfuncs.pfnPrecacheEvent)(type, psz);
-}
-void pfnPlaybackEvent(int flags, const edict_t *pInvoker, unsigned short eventindex, float delay,
- float *origin, float *angles, float fparam1,float fparam2, int iparam1, int iparam2, int bparam1, int bparam2)
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnPlaybackEvent:\n"); fclose(fp); }
- (*g_engfuncs.pfnPlaybackEvent)(flags, pInvoker, eventindex, delay, origin, angles, fparam1, fparam2, iparam1, iparam2, bparam1, bparam2);
-}
-unsigned char *pfnSetFatPVS(float *org)
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnSetFatPVS:\n"); fclose(fp); }
- return (*g_engfuncs.pfnSetFatPVS)(org);
-}
-unsigned char *pfnSetFatPAS(float *org)
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnSetFatPAS:\n"); fclose(fp); }
- return (*g_engfuncs.pfnSetFatPAS)(org);
-}
-int pfnCheckVisibility(const edict_t *entity, unsigned char *pset)
-{
-// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnCheckVisibility:\n"); fclose(fp); }
- return (*g_engfuncs.pfnCheckVisibility)(entity, pset);
-}
-void pfnDeltaSetField(struct delta_s *pFields, const char *fieldname)
-{
-// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnDeltaSetField:\n"); fclose(fp); }
- (*g_engfuncs.pfnDeltaSetField)(pFields, fieldname);
-}
-void pfnDeltaUnsetField(struct delta_s *pFields, const char *fieldname)
-{
-// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnDeltaUnsetField:\n"); fclose(fp); }
- (*g_engfuncs.pfnDeltaUnsetField)(pFields, fieldname);
-}
-void pfnDeltaAddEncoder(char *name, void (*conditionalencode)( struct delta_s *pFields, const unsigned char *from, const unsigned char *to))
-{
-// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnDeltaAddEncoder:\n"); fclose(fp); }
- (*g_engfuncs.pfnDeltaAddEncoder)(name, conditionalencode);
-}
-int pfnGetCurrentPlayer(void)
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnGetCurrentPlayer:\n"); fclose(fp); }
- return (*g_engfuncs.pfnGetCurrentPlayer)();
-}
-int pfnCanSkipPlayer(const edict_t *player)
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnCanSkipPlayer:\n"); fclose(fp); }
- return (*g_engfuncs.pfnCanSkipPlayer)(player);
-}
-int pfnDeltaFindField(struct delta_s *pFields, const char *fieldname)
-{
-// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnDeltaFindField:\n"); fclose(fp); }
- return (*g_engfuncs.pfnDeltaFindField)(pFields, fieldname);
-}
-void pfnDeltaSetFieldByIndex(struct delta_s *pFields, int fieldNumber)
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnDeltaSetFieldByIndex:\n"); fclose(fp); }
- (*g_engfuncs.pfnDeltaSetFieldByIndex)(pFields, fieldNumber);
-}
-void pfnDeltaUnsetFieldByIndex(struct delta_s *pFields, int fieldNumber)
-{
-// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnDeltaUnsetFieldByIndex:\n"); fclose(fp); }
- (*g_engfuncs.pfnDeltaUnsetFieldByIndex)(pFields, fieldNumber);
-}
-void pfnSetGroupMask(int mask, int op)
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnSetGroupMask:\n"); fclose(fp); }
- (*g_engfuncs.pfnSetGroupMask)(mask, op);
-}
-int pfnCreateInstancedBaseline(int classname, struct entity_state_s *baseline)
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnCreateInstancedBaseline:\n"); fclose(fp); }
- return (*g_engfuncs.pfnCreateInstancedBaseline)(classname, baseline);
-}
-void pfnCvar_DirectSet(struct cvar_s *var, char *value)
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnCvar_DirectSet:\n"); fclose(fp); }
- (*g_engfuncs.pfnCvar_DirectSet)(var, value);
-}
-void pfnForceUnmodified(FORCE_TYPE type, float *mins, float *maxs, const char *filename)
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnForceUnmodified:\n"); fclose(fp); }
- (*g_engfuncs.pfnForceUnmodified)(type, mins, maxs, filename);
-}
-void pfnGetPlayerStats(const edict_t *pClient, int *ping, int *packet_loss)
-{
- if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnGetPlayerStats:\n"); fclose(fp); }
- (*g_engfuncs.pfnGetPlayerStats)(pClient, ping, packet_loss);
-}
-
+//
+// HPB bot - botman's High Ping Bastard bot
+//
+// (http://planethalflife.com/botman/)
+//
+// engine.cpp
+//
+
+#include "dlls/extdll.h"
+#include "dlls/util.h"
+
+#include "bot.h"
+#include "bot_client.h"
+#include "HPB_bot/engine/engine.h"
+
+
+extern enginefuncs_t g_engfuncs;
+extern bot_t bots[32];
+extern int mod_id;
+
+
+int debug_engine = 0;
+
+void (*botMsgFunction)(void *, int) = NULL;
+void (*botMsgEndFunction)(void *, int) = NULL;
+int botMsgIndex;
+
+// messages created in RegUserMsg which will be "caught"
+int message_VGUI = 0;
+int message_ShowMenu = 0;
+int message_WeaponList = 0;
+int message_CurWeapon = 0;
+int message_AmmoX = 0;
+int message_WeapPickup = 0;
+int message_AmmoPickup = 0;
+int message_ItemPickup = 0;
+int message_Health = 0;
+int message_Battery = 0; // Armor
+int message_Damage = 0;
+int message_Money = 0; // for Counter-Strike
+int message_DeathMsg = 0;
+int message_TextMsg = 0;
+int message_WarmUp = 0; // for Front Line Force
+int message_WinMessage = 0; // for Front Line Force
+int message_ScreenFade = 0;
+
+// AvH messages
+int message_SetPlayMode = 0;
+int message_SetOrder = 0;
+int message_SetResources = 0;
+
+static FILE *fp;
+
+
+int pfnPrecacheModel(char* s)
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnPrecacheModel: %s\n",s); fclose(fp); }
+ return (*g_engfuncs.pfnPrecacheModel)(s);
+}
+int pfnPrecacheSound(char* s)
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnPrecacheSound: %s\n",s); fclose(fp); }
+ return (*g_engfuncs.pfnPrecacheSound)(s);
+}
+void pfnSetModel(edict_t *e, const char *m)
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnSetModel: edict=%x %s\n",e,m); fclose(fp); }
+ (*g_engfuncs.pfnSetModel)(e, m);
+}
+int pfnModelIndex(const char *m)
+{
+// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnModelIndex: %s\n",m); fclose(fp); }
+ return (*g_engfuncs.pfnModelIndex)(m);
+}
+int pfnModelFrames(int modelIndex)
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnModelFrames:\n"); fclose(fp); }
+ return (*g_engfuncs.pfnModelFrames)(modelIndex);
+}
+void pfnSetSize(edict_t *e, const float *rgflMin, const float *rgflMax)
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnSetSize: %x\n",e); fclose(fp); }
+ (*g_engfuncs.pfnSetSize)(e, rgflMin, rgflMax);
+}
+void pfnChangeLevel(char* s1, char* s2)
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnChangeLevel:\n"); fclose(fp); }
+
+ // kick any bot off of the server after time/frag limit...
+ for (int index = 0; index < 32; index++)
+ {
+ if (bots[index].is_used) // is this slot used?
+ {
+ char cmd[40];
+
+ sprintf(cmd, "kick \"%s\"\n", bots[index].name);
+
+ bots[index].respawn_state = RESPAWN_NEED_TO_RESPAWN;
+
+ SERVER_COMMAND(cmd); // kick the bot using (kick "name")
+ }
+ }
+
+ (*g_engfuncs.pfnChangeLevel)(s1, s2);
+}
+void pfnGetSpawnParms(edict_t *ent)
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnGetSpawnParms:\n"); fclose(fp); }
+ (*g_engfuncs.pfnGetSpawnParms)(ent);
+}
+void pfnSaveSpawnParms(edict_t *ent)
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnSaveSpawnParms:\n"); fclose(fp); }
+ (*g_engfuncs.pfnSaveSpawnParms)(ent);
+}
+float pfnVecToYaw(const float *rgflVector)
+{
+// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnVecToYaw:\n"); fclose(fp); }
+ return (*g_engfuncs.pfnVecToYaw)(rgflVector);
+}
+void pfnVecToAngles(const float *rgflVectorIn, float *rgflVectorOut)
+{
+// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnVecToAngles:\n"); fclose(fp); }
+ (*g_engfuncs.pfnVecToAngles)(rgflVectorIn, rgflVectorOut);
+}
+void pfnMoveToOrigin(edict_t *ent, const float *pflGoal, float dist, int iMoveType)
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnMoveToOrigin:\n"); fclose(fp); }
+ (*g_engfuncs.pfnMoveToOrigin)(ent, pflGoal, dist, iMoveType);
+}
+void pfnChangeYaw(edict_t* ent)
+{
+// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnChangeYaw:\n"); fclose(fp); }
+ (*g_engfuncs.pfnChangeYaw)(ent);
+}
+void pfnChangePitch(edict_t* ent)
+{
+// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnChangePitch:\n"); fclose(fp); }
+ (*g_engfuncs.pfnChangePitch)(ent);
+}
+edict_t* pfnFindEntityByString(edict_t *pEdictStartSearchAfter, const char *pszField, const char *pszValue)
+{
+// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnFindEntityByString: %s\n",pszValue); fclose(fp); }
+ return (*g_engfuncs.pfnFindEntityByString)(pEdictStartSearchAfter, pszField, pszValue);
+}
+int pfnGetEntityIllum(edict_t* pEnt)
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnGetEntityIllum:\n"); fclose(fp); }
+ return (*g_engfuncs.pfnGetEntityIllum)(pEnt);
+}
+edict_t* pfnFindEntityInSphere(edict_t *pEdictStartSearchAfter, const float *org, float rad)
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnFindEntityInSphere:\n"); fclose(fp); }
+ return (*g_engfuncs.pfnFindEntityInSphere)(pEdictStartSearchAfter, org, rad);
+}
+edict_t* pfnFindClientInPVS(edict_t *pEdict)
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnFindClientInPVS:\n"); fclose(fp); }
+ return (*g_engfuncs.pfnFindClientInPVS)(pEdict);
+}
+edict_t* pfnEntitiesInPVS(edict_t *pplayer)
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnEntitiesInPVS:\n"); fclose(fp); }
+ return (*g_engfuncs.pfnEntitiesInPVS)(pplayer);
+}
+void pfnMakeVectors(const float *rgflVector)
+{
+// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnMakeVectors:\n"); fclose(fp); }
+ (*g_engfuncs.pfnMakeVectors)(rgflVector);
+}
+void pfnAngleVectors(const float *rgflVector, float *forward, float *right, float *up)
+{
+// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnAngleVectors:\n"); fclose(fp); }
+ (*g_engfuncs.pfnAngleVectors)(rgflVector, forward, right, up);
+}
+edict_t* pfnCreateEntity(void)
+{
+ edict_t *pent = (*g_engfuncs.pfnCreateEntity)();
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnCreateEntity: %x\n",pent); fclose(fp); }
+ return pent;
+}
+void pfnRemoveEntity(edict_t* e)
+{
+// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnRemoveEntity: %x\n",e); fclose(fp); }
+ if (debug_engine)
+ {
+ fp=fopen("bot.txt","a");
+ fprintf(fp,"pfnRemoveEntity: %x\n",e);
+ if (e->v.model != 0)
+ fprintf(fp," model=%s\n", STRING(e->v.model));
+ fclose(fp);
+ }
+
+ (*g_engfuncs.pfnRemoveEntity)(e);
+}
+edict_t* pfnCreateNamedEntity(int className)
+{
+ edict_t *pent = (*g_engfuncs.pfnCreateNamedEntity)(className);
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnCreateNamedEntity: edict=%x name=%s\n",pent,STRING(className)); fclose(fp); }
+ return pent;
+}
+void pfnMakeStatic(edict_t *ent)
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnMakeStatic:\n"); fclose(fp); }
+ (*g_engfuncs.pfnMakeStatic)(ent);
+}
+int pfnEntIsOnFloor(edict_t *e)
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnEntIsOnFloor:\n"); fclose(fp); }
+ return (*g_engfuncs.pfnEntIsOnFloor)(e);
+}
+int pfnDropToFloor(edict_t* e)
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnDropToFloor:\n"); fclose(fp); }
+ return (*g_engfuncs.pfnDropToFloor)(e);
+}
+int pfnWalkMove(edict_t *ent, float yaw, float dist, int iMode)
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnWalkMove:\n"); fclose(fp); }
+ return (*g_engfuncs.pfnWalkMove)(ent, yaw, dist, iMode);
+}
+void pfnSetOrigin(edict_t *e, const float *rgflOrigin)
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnSetOrigin:\n"); fclose(fp); }
+ (*g_engfuncs.pfnSetOrigin)(e, rgflOrigin);
+}
+void pfnEmitSound(edict_t *entity, int channel, const char *sample, /*int*/float volume, float attenuation, int fFlags, int pitch)
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnEmitSound:\n"); fclose(fp); }
+ (*g_engfuncs.pfnEmitSound)(entity, channel, sample, volume, attenuation, fFlags, pitch);
+}
+void pfnEmitAmbientSound(edict_t *entity, float *pos, const char *samp, float vol, float attenuation, int fFlags, int pitch)
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnEmitAmbientSound:\n"); fclose(fp); }
+ (*g_engfuncs.pfnEmitAmbientSound)(entity, pos, samp, vol, attenuation, fFlags, pitch);
+}
+void pfnTraceLine(const float *v1, const float *v2, int fNoMonsters, edict_t *pentToSkip, TraceResult *ptr)
+{
+// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnTraceLine:\n"); fclose(fp); }
+ (*g_engfuncs.pfnTraceLine)(v1, v2, fNoMonsters, pentToSkip, ptr);
+}
+void pfnTraceToss(edict_t* pent, edict_t* pentToIgnore, TraceResult *ptr)
+{
+// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnTraceToss:\n"); fclose(fp); }
+ (*g_engfuncs.pfnTraceToss)(pent, pentToIgnore, ptr);
+}
+int pfnTraceMonsterHull(edict_t *pEdict, const float *v1, const float *v2, int fNoMonsters, edict_t *pentToSkip, TraceResult *ptr)
+{
+// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnTraceMonsterHull:\n"); fclose(fp); }
+ return (*g_engfuncs.pfnTraceMonsterHull)(pEdict, v1, v2, fNoMonsters, pentToSkip, ptr);
+}
+void pfnTraceHull(const float *v1, const float *v2, int fNoMonsters, int hullNumber, edict_t *pentToSkip, TraceResult *ptr)
+{
+// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnTraceHull:\n"); fclose(fp); }
+ (*g_engfuncs.pfnTraceHull)(v1, v2, fNoMonsters, hullNumber, pentToSkip, ptr);
+}
+void pfnTraceModel(const float *v1, const float *v2, int hullNumber, edict_t *pent, TraceResult *ptr)
+{
+// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnTraceModel:\n"); fclose(fp); }
+ (*g_engfuncs.pfnTraceModel)(v1, v2, hullNumber, pent, ptr);
+}
+const char *pfnTraceTexture(edict_t *pTextureEntity, const float *v1, const float *v2 )
+{
+// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnTraceTexture:\n"); fclose(fp); }
+ return (*g_engfuncs.pfnTraceTexture)(pTextureEntity, v1, v2);
+}
+void pfnTraceSphere(const float *v1, const float *v2, int fNoMonsters, float radius, edict_t *pentToSkip, TraceResult *ptr)
+{
+// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnTraceSphere:\n"); fclose(fp); }
+ (*g_engfuncs.pfnTraceSphere)(v1, v2, fNoMonsters, radius, pentToSkip, ptr);
+}
+void pfnGetAimVector(edict_t* ent, float speed, float *rgflReturn)
+{
+// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnGetAimVector:\n"); fclose(fp); }
+ (*g_engfuncs.pfnGetAimVector)(ent, speed, rgflReturn);
+}
+void pfnServerCommand(char* str)
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnServerCommand: %s\n",str); fclose(fp); }
+ (*g_engfuncs.pfnServerCommand)(str);
+}
+void pfnServerExecute(void)
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnServerExecute:\n"); fclose(fp); }
+ (*g_engfuncs.pfnServerExecute)();
+}
+void pfnClientCommand(edict_t* pEdict, char* szFmt, ...)
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnClientCommand=%s\n",szFmt); fclose(fp); }
+ return;
+}
+void pfnParticleEffect(const float *org, const float *dir, float color, float count)
+{
+// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnParticleEffect:\n"); fclose(fp); }
+ (*g_engfuncs.pfnParticleEffect)(org, dir, color, count);
+}
+void pfnLightStyle(int style, char* val)
+{
+// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnLightStyle:\n"); fclose(fp); }
+ (*g_engfuncs.pfnLightStyle)(style, val);
+}
+int pfnDecalIndex(const char *name)
+{
+// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnDecalIndex:\n"); fclose(fp); }
+ return (*g_engfuncs.pfnDecalIndex)(name);
+}
+int pfnPointContents(const float *rgflVector)
+{
+// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnPointContents:\n"); fclose(fp); }
+ return (*g_engfuncs.pfnPointContents)(rgflVector);
+}
+void pfnMessageBegin(int msg_dest, int msg_type, const float *pOrigin, edict_t *ed)
+{
+ if (gpGlobals->deathmatch)
+ {
+ int index = -1;
+
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnMessageBegin: edict=%x dest=%d type=%d\n",ed,msg_dest,msg_type); fclose(fp); }
+
+ if (ed)
+ {
+ index = UTIL_GetBotIndex(ed);
+
+ // is this message for a bot?
+ if (index != -1)
+ {
+ botMsgFunction = NULL; // no msg function until known otherwise
+ botMsgEndFunction = NULL; // no msg end function until known otherwise
+ botMsgIndex = index; // index of bot receiving message
+
+ if (mod_id == VALVE_DLL)
+ {
+ if (msg_type == message_WeaponList)
+ botMsgFunction = BotClient_Valve_WeaponList;
+ else if (msg_type == message_CurWeapon)
+ botMsgFunction = BotClient_Valve_CurrentWeapon;
+ else if (msg_type == message_AmmoX)
+ botMsgFunction = BotClient_Valve_AmmoX;
+ else if (msg_type == message_AmmoPickup)
+ botMsgFunction = BotClient_Valve_AmmoPickup;
+ else if (msg_type == message_WeapPickup)
+ botMsgFunction = BotClient_Valve_WeaponPickup;
+ else if (msg_type == message_ItemPickup)
+ botMsgFunction = BotClient_Valve_ItemPickup;
+ else if (msg_type == message_Health)
+ botMsgFunction = BotClient_Valve_Health;
+ else if (msg_type == message_Battery)
+ botMsgFunction = BotClient_Valve_Battery;
+ else if (msg_type == message_Damage)
+ botMsgFunction = BotClient_Valve_Damage;
+ else if (msg_type == message_ScreenFade)
+ botMsgFunction = BotClient_Valve_ScreenFade;
+ }
+ else if (mod_id == TFC_DLL)
+ {
+ if (msg_type == message_VGUI)
+ botMsgFunction = BotClient_TFC_VGUI;
+ else if (msg_type == message_WeaponList)
+ botMsgFunction = BotClient_TFC_WeaponList;
+ else if (msg_type == message_CurWeapon)
+ botMsgFunction = BotClient_TFC_CurrentWeapon;
+ else if (msg_type == message_AmmoX)
+ botMsgFunction = BotClient_TFC_AmmoX;
+ else if (msg_type == message_AmmoPickup)
+ botMsgFunction = BotClient_TFC_AmmoPickup;
+ else if (msg_type == message_WeapPickup)
+ botMsgFunction = BotClient_TFC_WeaponPickup;
+ else if (msg_type == message_ItemPickup)
+ botMsgFunction = BotClient_TFC_ItemPickup;
+ else if (msg_type == message_Health)
+ botMsgFunction = BotClient_TFC_Health;
+ else if (msg_type == message_Battery)
+ botMsgFunction = BotClient_TFC_Battery;
+ else if (msg_type == message_Damage)
+ botMsgFunction = BotClient_TFC_Damage;
+ else if (msg_type == message_ScreenFade)
+ botMsgFunction = BotClient_TFC_ScreenFade;
+ }
+ else if (mod_id == CSTRIKE_DLL)
+ {
+ if (msg_type == message_VGUI)
+ botMsgFunction = BotClient_CS_VGUI;
+ else if (msg_type == message_ShowMenu)
+ botMsgFunction = BotClient_CS_ShowMenu;
+ else if (msg_type == message_WeaponList)
+ botMsgFunction = BotClient_CS_WeaponList;
+ else if (msg_type == message_CurWeapon)
+ botMsgFunction = BotClient_CS_CurrentWeapon;
+ else if (msg_type == message_AmmoX)
+ botMsgFunction = BotClient_CS_AmmoX;
+ else if (msg_type == message_WeapPickup)
+ botMsgFunction = BotClient_CS_WeaponPickup;
+ else if (msg_type == message_AmmoPickup)
+ botMsgFunction = BotClient_CS_AmmoPickup;
+ else if (msg_type == message_ItemPickup)
+ botMsgFunction = BotClient_CS_ItemPickup;
+ else if (msg_type == message_Health)
+ botMsgFunction = BotClient_CS_Health;
+ else if (msg_type == message_Battery)
+ botMsgFunction = BotClient_CS_Battery;
+ else if (msg_type == message_Damage)
+ botMsgFunction = BotClient_CS_Damage;
+ else if (msg_type == message_Money)
+ botMsgFunction = BotClient_CS_Money;
+ else if (msg_type == message_ScreenFade)
+ botMsgFunction = BotClient_CS_ScreenFade;
+ }
+ else if (mod_id == GEARBOX_DLL)
+ {
+ if (msg_type == message_VGUI)
+ botMsgFunction = BotClient_Gearbox_VGUI;
+ else if (msg_type == message_WeaponList)
+ botMsgFunction = BotClient_Gearbox_WeaponList;
+ else if (msg_type == message_CurWeapon)
+ botMsgFunction = BotClient_Gearbox_CurrentWeapon;
+ else if (msg_type == message_AmmoX)
+ botMsgFunction = BotClient_Gearbox_AmmoX;
+ else if (msg_type == message_AmmoPickup)
+ botMsgFunction = BotClient_Gearbox_AmmoPickup;
+ else if (msg_type == message_WeapPickup)
+ botMsgFunction = BotClient_Gearbox_WeaponPickup;
+ else if (msg_type == message_ItemPickup)
+ botMsgFunction = BotClient_Gearbox_ItemPickup;
+ else if (msg_type == message_Health)
+ botMsgFunction = BotClient_Gearbox_Health;
+ else if (msg_type == message_Battery)
+ botMsgFunction = BotClient_Gearbox_Battery;
+ else if (msg_type == message_Damage)
+ botMsgFunction = BotClient_Gearbox_Damage;
+ else if (msg_type == message_ScreenFade)
+ botMsgFunction = BotClient_Gearbox_ScreenFade;
+ }
+ else if (mod_id == FRONTLINE_DLL)
+ {
+ if (msg_type == message_VGUI)
+ botMsgFunction = BotClient_FLF_VGUI;
+ else if (msg_type == message_WeaponList)
+ botMsgFunction = BotClient_FLF_WeaponList;
+ else if (msg_type == message_CurWeapon)
+ botMsgFunction = BotClient_FLF_CurrentWeapon;
+ else if (msg_type == message_AmmoX)
+ botMsgFunction = BotClient_FLF_AmmoX;
+ else if (msg_type == message_AmmoPickup)
+ botMsgFunction = BotClient_FLF_AmmoPickup;
+ else if (msg_type == message_WeapPickup)
+ botMsgFunction = BotClient_FLF_WeaponPickup;
+ else if (msg_type == message_ItemPickup)
+ botMsgFunction = BotClient_FLF_ItemPickup;
+ else if (msg_type == message_Health)
+ botMsgFunction = BotClient_FLF_Health;
+ else if (msg_type == message_Battery)
+ botMsgFunction = BotClient_FLF_Battery;
+ else if (msg_type == message_Damage)
+ botMsgFunction = BotClient_FLF_Damage;
+ else if (msg_type == message_TextMsg)
+ botMsgFunction = BotClient_FLF_TextMsg;
+ else if (msg_type == message_WarmUp)
+ botMsgFunction = BotClient_FLF_WarmUp;
+ else if (msg_type == message_ScreenFade)
+ botMsgFunction = BotClient_FLF_ScreenFade;
+ else if (msg_type == 23) // SVC_TEMPENTITY
+ {
+ botMsgFunction = BotClient_FLF_TempEntity;
+ botMsgEndFunction = BotClient_FLF_TempEntity;
+ }
+ }
+ else if (mod_id == AVH_DLL)
+ {
+ if (msg_type == message_SetPlayMode)
+ botMsgFunction = BotClient_AVH_SetPlayMode;
+ else if (msg_type == message_AmmoX)
+ botMsgFunction = BotClient_Valve_AmmoX;
+ else if (msg_type == message_AmmoPickup)
+ botMsgFunction = BotClient_Valve_AmmoPickup;
+ else if (msg_type == message_WeapPickup)
+ botMsgFunction = BotClient_Valve_WeaponPickup;
+ else if (msg_type == message_ItemPickup)
+ botMsgFunction = BotClient_Valve_ItemPickup;
+ else if (msg_type == message_WeaponList)
+ botMsgFunction = BotClient_Valve_WeaponList;
+ else if (msg_type == message_SetOrder)
+ botMsgFunction = BotClient_AVH_SetOrder;
+ else if (msg_type == message_SetResources)
+ botMsgFunction = BotClient_AVH_SetResources;
+ }
+ }
+ }
+ else if (msg_dest == MSG_ALL)
+ {
+ botMsgFunction = NULL; // no msg function until known otherwise
+ botMsgIndex = -1; // index of bot receiving message (none)
+
+ if (mod_id == VALVE_DLL)
+ {
+ if (msg_type == message_DeathMsg)
+ botMsgFunction = BotClient_Valve_DeathMsg;
+ }
+ else if (mod_id == TFC_DLL)
+ {
+ if (msg_type == message_DeathMsg)
+ botMsgFunction = BotClient_TFC_DeathMsg;
+ }
+ else if (mod_id == CSTRIKE_DLL)
+ {
+ if (msg_type == message_DeathMsg)
+ botMsgFunction = BotClient_CS_DeathMsg;
+ }
+ else if (mod_id == GEARBOX_DLL)
+ {
+ if (msg_type == message_DeathMsg)
+ botMsgFunction = BotClient_Gearbox_DeathMsg;
+ }
+ else if (mod_id == FRONTLINE_DLL)
+ {
+ if (msg_type == message_DeathMsg)
+ botMsgFunction = BotClient_FLF_DeathMsg;
+ else if (msg_type == message_WarmUp)
+ botMsgFunction = BotClient_FLF_WarmUpAll;
+ else if (msg_type == message_WinMessage)
+ botMsgFunction = BotClient_FLF_WinMessage;
+ }
+ }
+ }
+
+ (*g_engfuncs.pfnMessageBegin)(msg_dest, msg_type, pOrigin, ed);
+}
+void pfnMessageEnd(void)
+{
+ if (gpGlobals->deathmatch)
+ {
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnMessageEnd:\n"); fclose(fp); }
+
+ if (botMsgEndFunction)
+ (*botMsgEndFunction)(NULL, botMsgIndex); // NULL indicated msg end
+
+ // clear out the bot message function pointers...
+ botMsgFunction = NULL;
+ botMsgEndFunction = NULL;
+ }
+
+ (*g_engfuncs.pfnMessageEnd)();
+}
+void pfnWriteByte(int iValue)
+{
+ if (gpGlobals->deathmatch)
+ {
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnWriteByte: %d\n",iValue); fclose(fp); }
+
+ // if this message is for a bot, call the client message function...
+ if (botMsgFunction)
+ (*botMsgFunction)((void *)&iValue, botMsgIndex);
+ }
+
+ (*g_engfuncs.pfnWriteByte)(iValue);
+}
+void pfnWriteChar(int iValue)
+{
+ if (gpGlobals->deathmatch)
+ {
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnWriteChar: %d\n",iValue); fclose(fp); }
+
+ // if this message is for a bot, call the client message function...
+ if (botMsgFunction)
+ (*botMsgFunction)((void *)&iValue, botMsgIndex);
+ }
+
+ (*g_engfuncs.pfnWriteChar)(iValue);
+}
+void pfnWriteShort(int iValue)
+{
+ if (gpGlobals->deathmatch)
+ {
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnWriteShort: %d\n",iValue); fclose(fp); }
+
+ // if this message is for a bot, call the client message function...
+ if (botMsgFunction)
+ (*botMsgFunction)((void *)&iValue, botMsgIndex);
+ }
+
+ (*g_engfuncs.pfnWriteShort)(iValue);
+}
+void pfnWriteLong(int iValue)
+{
+ if (gpGlobals->deathmatch)
+ {
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnWriteLong: %d\n",iValue); fclose(fp); }
+
+ // if this message is for a bot, call the client message function...
+ if (botMsgFunction)
+ (*botMsgFunction)((void *)&iValue, botMsgIndex);
+ }
+
+ (*g_engfuncs.pfnWriteLong)(iValue);
+}
+void pfnWriteAngle(float flValue)
+{
+ if (gpGlobals->deathmatch)
+ {
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnWriteAngle: %f\n",flValue); fclose(fp); }
+
+ // if this message is for a bot, call the client message function...
+ if (botMsgFunction)
+ (*botMsgFunction)((void *)&flValue, botMsgIndex);
+ }
+
+ (*g_engfuncs.pfnWriteAngle)(flValue);
+}
+void pfnWriteCoord(float flValue)
+{
+ if (gpGlobals->deathmatch)
+ {
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnWriteCoord: %f\n",flValue); fclose(fp); }
+
+ // if this message is for a bot, call the client message function...
+ if (botMsgFunction)
+ (*botMsgFunction)((void *)&flValue, botMsgIndex);
+ }
+
+ (*g_engfuncs.pfnWriteCoord)(flValue);
+}
+void pfnWriteString(const char *sz)
+{
+ if (gpGlobals->deathmatch)
+ {
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnWriteString: %s\n",sz); fclose(fp); }
+
+ // if this message is for a bot, call the client message function...
+ if (botMsgFunction)
+ (*botMsgFunction)((void *)sz, botMsgIndex);
+ }
+
+ (*g_engfuncs.pfnWriteString)(sz);
+}
+void pfnWriteEntity(int iValue)
+{
+ if (gpGlobals->deathmatch)
+ {
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnWriteEntity: %d\n",iValue); fclose(fp); }
+
+ // if this message is for a bot, call the client message function...
+ if (botMsgFunction)
+ (*botMsgFunction)((void *)&iValue, botMsgIndex);
+ }
+
+ (*g_engfuncs.pfnWriteEntity)(iValue);
+}
+void pfnCVarRegister(cvar_t *pCvar)
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnCVarRegister:\n"); fclose(fp); }
+ (*g_engfuncs.pfnCVarRegister)(pCvar);
+}
+float pfnCVarGetFloat(const char *szVarName)
+{
+// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnCVarGetFloat: %s\n",szVarName); fclose(fp); }
+ return (*g_engfuncs.pfnCVarGetFloat)(szVarName);
+}
+const char* pfnCVarGetString(const char *szVarName)
+{
+// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnCVarGetString:\n"); fclose(fp); }
+ return (*g_engfuncs.pfnCVarGetString)(szVarName);
+}
+void pfnCVarSetFloat(const char *szVarName, float flValue)
+{
+// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnCVarSetFloat:\n"); fclose(fp); }
+ (*g_engfuncs.pfnCVarSetFloat)(szVarName, flValue);
+}
+void pfnCVarSetString(const char *szVarName, const char *szValue)
+{
+// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnCVarSetString:\n"); fclose(fp); }
+ (*g_engfuncs.pfnCVarSetString)(szVarName, szValue);
+}
+void* pfnPvAllocEntPrivateData(edict_t *pEdict, long cb)
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnPvAllocEntPrivateData:\n"); fclose(fp); }
+ return (*g_engfuncs.pfnPvAllocEntPrivateData)(pEdict, cb);
+}
+void* pfnPvEntPrivateData(edict_t *pEdict)
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnPvEntPrivateData:\n"); fclose(fp); }
+ return (*g_engfuncs.pfnPvEntPrivateData)(pEdict);
+}
+void pfnFreeEntPrivateData(edict_t *pEdict)
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnFreeEntPrivateData:\n"); fclose(fp); }
+ (*g_engfuncs.pfnFreeEntPrivateData)(pEdict);
+}
+const char* pfnSzFromIndex(int iString)
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnSzFromIndex:\n"); fclose(fp); }
+ return (*g_engfuncs.pfnSzFromIndex)(iString);
+}
+int pfnAllocString(const char *szValue)
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnAllocString:\n"); fclose(fp); }
+ return (*g_engfuncs.pfnAllocString)(szValue);
+}
+entvars_t* pfnGetVarsOfEnt(edict_t *pEdict)
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnGetVarsOfEnt:\n"); fclose(fp); }
+ return (*g_engfuncs.pfnGetVarsOfEnt)(pEdict);
+}
+edict_t* pfnPEntityOfEntOffset(int iEntOffset)
+{
+// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnPEntityOfEntOffset:\n"); fclose(fp); }
+ return (*g_engfuncs.pfnPEntityOfEntOffset)(iEntOffset);
+}
+int pfnEntOffsetOfPEntity(const edict_t *pEdict)
+{
+// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnEntOffsetOfPEntity: %x\n",pEdict); fclose(fp); }
+ return (*g_engfuncs.pfnEntOffsetOfPEntity)(pEdict);
+}
+int pfnIndexOfEdict(const edict_t *pEdict)
+{
+// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnIndexOfEdict: %x\n",pEdict); fclose(fp); }
+ return (*g_engfuncs.pfnIndexOfEdict)(pEdict);
+}
+edict_t* pfnPEntityOfEntIndex(int iEntIndex)
+{
+// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnPEntityOfEntIndex:\n"); fclose(fp); }
+ return (*g_engfuncs.pfnPEntityOfEntIndex)(iEntIndex);
+}
+edict_t* pfnFindEntityByVars(entvars_t* pvars)
+{
+// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnFindEntityByVars:\n"); fclose(fp); }
+ return (*g_engfuncs.pfnFindEntityByVars)(pvars);
+}
+void* pfnGetModelPtr(edict_t* pEdict)
+{
+// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnGetModelPtr: %x\n",pEdict); fclose(fp); }
+ return (*g_engfuncs.pfnGetModelPtr)(pEdict);
+}
+int pfnRegUserMsg(const char *pszName, int iSize)
+{
+ int msg;
+
+ msg = (*g_engfuncs.pfnRegUserMsg)(pszName, iSize);
+
+ //if (gpGlobals->deathmatch)
+ //{
+#ifdef _DEBUG
+ fp=fopen("bot.txt","a"); fprintf(fp,"pfnRegUserMsg: pszName=%s msg=%d\n",pszName,msg); fclose(fp);
+#endif
+
+ if (mod_id == VALVE_DLL)
+ {
+ if (strcmp(pszName, "WeaponList") == 0)
+ message_WeaponList = msg;
+ else if (strcmp(pszName, "CurWeapon") == 0)
+ message_CurWeapon = msg;
+ else if (strcmp(pszName, "AmmoX") == 0)
+ message_AmmoX = msg;
+ else if (strcmp(pszName, "AmmoPickup") == 0)
+ message_AmmoPickup = msg;
+ else if (strcmp(pszName, "WeapPickup") == 0)
+ message_WeapPickup = msg;
+ else if (strcmp(pszName, "ItemPickup") == 0)
+ message_ItemPickup = msg;
+ else if (strcmp(pszName, "Health") == 0)
+ message_Health = msg;
+ else if (strcmp(pszName, "Battery") == 0)
+ message_Battery = msg;
+ else if (strcmp(pszName, "Damage") == 0)
+ message_Damage = msg;
+ else if (strcmp(pszName, "DeathMsg") == 0)
+ message_DeathMsg = msg;
+ else if (strcmp(pszName, "ScreenFade") == 0)
+ message_ScreenFade = msg;
+ }
+ else if (mod_id == TFC_DLL)
+ {
+ if (strcmp(pszName, "VGUIMenu") == 0)
+ message_VGUI = msg;
+ else if (strcmp(pszName, "WeaponList") == 0)
+ message_WeaponList = msg;
+ else if (strcmp(pszName, "CurWeapon") == 0)
+ message_CurWeapon = msg;
+ else if (strcmp(pszName, "AmmoX") == 0)
+ message_AmmoX = msg;
+ else if (strcmp(pszName, "AmmoPickup") == 0)
+ message_AmmoPickup = msg;
+ else if (strcmp(pszName, "WeapPickup") == 0)
+ message_WeapPickup = msg;
+ else if (strcmp(pszName, "ItemPickup") == 0)
+ message_ItemPickup = msg;
+ else if (strcmp(pszName, "Health") == 0)
+ message_Health = msg;
+ else if (strcmp(pszName, "Battery") == 0)
+ message_Battery = msg;
+ else if (strcmp(pszName, "Damage") == 0)
+ message_Damage = msg;
+ else if (strcmp(pszName, "DeathMsg") == 0)
+ message_DeathMsg = msg;
+ else if (strcmp(pszName, "ScreenFade") == 0)
+ message_ScreenFade = msg;
+ }
+ else if (mod_id == CSTRIKE_DLL)
+ {
+ if (strcmp(pszName, "VGUIMenu") == 0)
+ message_VGUI = msg;
+ else if (strcmp(pszName, "ShowMenu") == 0)
+ message_ShowMenu = msg;
+ else if (strcmp(pszName, "WeaponList") == 0)
+ message_WeaponList = msg;
+ else if (strcmp(pszName, "CurWeapon") == 0)
+ message_CurWeapon = msg;
+ else if (strcmp(pszName, "AmmoX") == 0)
+ message_AmmoX = msg;
+ else if (strcmp(pszName, "AmmoPickup") == 0)
+ message_AmmoPickup = msg;
+ else if (strcmp(pszName, "WeapPickup") == 0)
+ message_WeapPickup = msg;
+ else if (strcmp(pszName, "ItemPickup") == 0)
+ message_ItemPickup = msg;
+ else if (strcmp(pszName, "Health") == 0)
+ message_Health = msg;
+ else if (strcmp(pszName, "Battery") == 0)
+ message_Battery = msg;
+ else if (strcmp(pszName, "Damage") == 0)
+ message_Damage = msg;
+ else if (strcmp(pszName, "Money") == 0)
+ message_Money = msg;
+ else if (strcmp(pszName, "DeathMsg") == 0)
+ message_DeathMsg = msg;
+ else if (strcmp(pszName, "ScreenFade") == 0)
+ message_ScreenFade = msg;
+ }
+ else if (mod_id == GEARBOX_DLL)
+ {
+ if (strcmp(pszName, "VGUIMenu") == 0)
+ message_VGUI = msg;
+ else if (strcmp(pszName, "WeaponList") == 0)
+ message_WeaponList = msg;
+ else if (strcmp(pszName, "CurWeapon") == 0)
+ message_CurWeapon = msg;
+ else if (strcmp(pszName, "AmmoX") == 0)
+ message_AmmoX = msg;
+ else if (strcmp(pszName, "AmmoPickup") == 0)
+ message_AmmoPickup = msg;
+ else if (strcmp(pszName, "WeapPickup") == 0)
+ message_WeapPickup = msg;
+ else if (strcmp(pszName, "ItemPickup") == 0)
+ message_ItemPickup = msg;
+ else if (strcmp(pszName, "Health") == 0)
+ message_Health = msg;
+ else if (strcmp(pszName, "Battery") == 0)
+ message_Battery = msg;
+ else if (strcmp(pszName, "Damage") == 0)
+ message_Damage = msg;
+ else if (strcmp(pszName, "DeathMsg") == 0)
+ message_DeathMsg = msg;
+ else if (strcmp(pszName, "ScreenFade") == 0)
+ message_ScreenFade = msg;
+ }
+ else if (mod_id == FRONTLINE_DLL)
+ {
+ if (strcmp(pszName, "VGUIMenu") == 0)
+ message_VGUI = msg;
+ else if (strcmp(pszName, "WeaponList") == 0)
+ message_WeaponList = msg;
+ else if (strcmp(pszName, "CurWeapon") == 0)
+ message_CurWeapon = msg;
+ else if (strcmp(pszName, "AmmoX") == 0)
+ message_AmmoX = msg;
+ else if (strcmp(pszName, "AmmoPickup") == 0)
+ message_AmmoPickup = msg;
+ else if (strcmp(pszName, "WeapPickup") == 0)
+ message_WeapPickup = msg;
+ else if (strcmp(pszName, "ItemPickup") == 0)
+ message_ItemPickup = msg;
+ else if (strcmp(pszName, "Health") == 0)
+ message_Health = msg;
+ else if (strcmp(pszName, "Battery") == 0)
+ message_Battery = msg;
+ else if (strcmp(pszName, "Damage") == 0)
+ message_Damage = msg;
+ else if (strcmp(pszName, "DeathMsg") == 0)
+ message_DeathMsg = msg;
+ else if (strcmp(pszName, "TextMsg") == 0)
+ message_TextMsg = msg;
+ else if (strcmp(pszName, "WarmUp") == 0)
+ message_WarmUp = msg;
+ else if (strcmp(pszName, "WinMessage") == 0)
+ message_WinMessage = msg;
+ else if (strcmp(pszName, "ScreenFade") == 0)
+ message_ScreenFade = msg;
+ }
+ else if (mod_id == AVH_DLL)
+ {
+ if (strcmp(pszName, "SetPlayMode") == 0)
+ message_SetPlayMode = msg;
+ else if (strcmp(pszName, "AmmoX") == 0)
+ message_AmmoX = msg;
+ else if (strcmp(pszName, "AmmoPickup") == 0)
+ message_AmmoPickup = msg;
+ else if (strcmp(pszName, "WeapPickup") == 0)
+ message_WeapPickup = msg;
+ else if (strcmp(pszName, "ItemPickup") == 0)
+ message_ItemPickup = msg;
+ else if (strcmp(pszName, "WeaponList") == 0)
+ message_WeaponList = msg;
+ else if (strcmp(pszName, "SetOrder") == 0)
+ message_SetOrder = msg;
+ else if (strcmp(pszName, "SetRsrces") == 0)
+ message_SetResources = msg;
+
+ }
+ //}
+
+ return msg;
+}
+void pfnAnimationAutomove(const edict_t* pEdict, float flTime)
+{
+// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnAnimationAutomove:\n"); fclose(fp); }
+ (*g_engfuncs.pfnAnimationAutomove)(pEdict, flTime);
+}
+void pfnGetBonePosition(const edict_t* pEdict, int iBone, float *rgflOrigin, float *rgflAngles )
+{
+// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnGetBonePosition:\n"); fclose(fp); }
+ (*g_engfuncs.pfnGetBonePosition)(pEdict, iBone, rgflOrigin, rgflAngles);
+}
+unsigned long pfnFunctionFromName( const char *pName )
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnFunctionFromName:\n"); fclose(fp); }
+ return (*g_engfuncs.pfnFunctionFromName)(pName);
+}
+const char *pfnNameForFunction( unsigned long function )
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnNameForFunction:\n"); fclose(fp); }
+ const char* theName = (*g_engfuncs.pfnNameForFunction)(function);
+ return theName;
+}
+void pfnClientPrintf( edict_t* pEdict, PRINT_TYPE ptype, const char *szMsg )
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnClientPrintf:\n"); fclose(fp); }
+ (*g_engfuncs.pfnClientPrintf)(pEdict, ptype, szMsg);
+}
+void pfnServerPrint( const char *szMsg )
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnServerPrint: %s\n",szMsg); fclose(fp); }
+ (*g_engfuncs.pfnServerPrint)(szMsg);
+}
+void pfnGetAttachment(const edict_t *pEdict, int iAttachment, float *rgflOrigin, float *rgflAngles )
+{
+// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnGetAttachment:\n"); fclose(fp); }
+ (*g_engfuncs.pfnGetAttachment)(pEdict, iAttachment, rgflOrigin, rgflAngles);
+}
+void pfnCRC32_Init(CRC32_t *pulCRC)
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnCRC32_Init:\n"); fclose(fp); }
+ (*g_engfuncs.pfnCRC32_Init)(pulCRC);
+}
+void pfnCRC32_ProcessBuffer(CRC32_t *pulCRC, void *p, int len)
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnCRC32_ProcessBuffer:\n"); fclose(fp); }
+ (*g_engfuncs.pfnCRC32_ProcessBuffer)(pulCRC, p, len);
+}
+void pfnCRC32_ProcessByte(CRC32_t *pulCRC, unsigned char ch)
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnCRC32_ProcessByte:\n"); fclose(fp); }
+ (*g_engfuncs.pfnCRC32_ProcessByte)(pulCRC, ch);
+}
+CRC32_t pfnCRC32_Final(CRC32_t pulCRC)
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnCRC32_Final:\n"); fclose(fp); }
+ return (*g_engfuncs.pfnCRC32_Final)(pulCRC);
+}
+long pfnRandomLong(long lLow, long lHigh)
+{
+// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnRandomLong: lLow=%d lHigh=%d\n",lLow,lHigh); fclose(fp); }
+ return (*g_engfuncs.pfnRandomLong)(lLow, lHigh);
+}
+float pfnRandomFloat(float flLow, float flHigh)
+{
+// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnRandomFloat:\n"); fclose(fp); }
+ return (*g_engfuncs.pfnRandomFloat)(flLow, flHigh);
+}
+void pfnSetView(const edict_t *pClient, const edict_t *pViewent )
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnSetView:\n"); fclose(fp); }
+ (*g_engfuncs.pfnSetView)(pClient, pViewent);
+}
+float pfnTime( void )
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnTime:\n"); fclose(fp); }
+ return (*g_engfuncs.pfnTime)();
+}
+void pfnCrosshairAngle(const edict_t *pClient, float pitch, float yaw)
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnCrosshairAngle:\n"); fclose(fp); }
+ (*g_engfuncs.pfnCrosshairAngle)(pClient, pitch, yaw);
+}
+byte *pfnLoadFileForMe(char *filename, int *pLength)
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnLoadFileForMe: filename=%s\n",filename); fclose(fp); }
+ return (*g_engfuncs.pfnLoadFileForMe)(filename, pLength);
+}
+void pfnFreeFile(void *buffer)
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnFreeFile:\n"); fclose(fp); }
+ (*g_engfuncs.pfnFreeFile)(buffer);
+}
+void pfnEndSection(const char *pszSectionName)
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnEndSection:\n"); fclose(fp); }
+ (*g_engfuncs.pfnEndSection)(pszSectionName);
+}
+int pfnCompareFileTime(char *filename1, char *filename2, int *iCompare)
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnCompareFileTime:\n"); fclose(fp); }
+ return (*g_engfuncs.pfnCompareFileTime)(filename1, filename2, iCompare);
+}
+void pfnGetGameDir(char *szGetGameDir)
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnGetGameDir:\n"); fclose(fp); }
+ (*g_engfuncs.pfnGetGameDir)(szGetGameDir);
+}
+void pfnCvar_RegisterVariable(cvar_t *variable)
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnCvar_RegisterVariable:\n"); fclose(fp); }
+ (*g_engfuncs.pfnCvar_RegisterVariable)(variable);
+}
+void pfnFadeClientVolume(const edict_t *pEdict, int fadePercent, int fadeOutSeconds, int holdTime, int fadeInSeconds)
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnFadeClientVolume:\n"); fclose(fp); }
+ (*g_engfuncs.pfnFadeClientVolume)(pEdict, fadePercent, fadeOutSeconds, holdTime, fadeInSeconds);
+}
+void pfnSetClientMaxspeed(const edict_t *pEdict, float fNewMaxspeed)
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnSetClientMaxspeed: edict=%x %f\n",pEdict,fNewMaxspeed); fclose(fp); }
+ (*g_engfuncs.pfnSetClientMaxspeed)(pEdict, fNewMaxspeed);
+}
+edict_t * pfnCreateFakeClient(const char *netname)
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnCreateFakeClient:\n"); fclose(fp); }
+ return (*g_engfuncs.pfnCreateFakeClient)(netname);
+}
+void pfnRunPlayerMove(edict_t *fakeclient, const float *viewangles, float forwardmove, float sidemove, float upmove, unsigned short buttons, byte impulse, byte msec )
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnRunPlayerMove:\n"); fclose(fp); }
+ (*g_engfuncs.pfnRunPlayerMove)(fakeclient, viewangles, forwardmove, sidemove, upmove, buttons, impulse, msec);
+}
+int pfnNumberOfEntities(void)
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnNumberOfEntities:\n"); fclose(fp); }
+ return (*g_engfuncs.pfnNumberOfEntities)();
+}
+char* pfnGetInfoKeyBuffer(edict_t *e)
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnGetInfoKeyBuffer:\n"); fclose(fp); }
+ return (*g_engfuncs.pfnGetInfoKeyBuffer)(e);
+}
+char* pfnInfoKeyValue(char *infobuffer, char *key)
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnInfoKeyValue: %s %s\n",infobuffer,key); fclose(fp); }
+ return (*g_engfuncs.pfnInfoKeyValue)(infobuffer, key);
+}
+void pfnSetKeyValue(char *infobuffer, char *key, char *value)
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnSetKeyValue: %s %s\n",key,value); fclose(fp); }
+ (*g_engfuncs.pfnSetKeyValue)(infobuffer, key, value);
+}
+void pfnSetClientKeyValue(int clientIndex, char *infobuffer, char *key, char *value)
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnSetClientKeyValue: %s %s\n",key,value); fclose(fp); }
+ (*g_engfuncs.pfnSetClientKeyValue)(clientIndex, infobuffer, key, value);
+}
+int pfnIsMapValid(char *filename)
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnIsMapValid:\n"); fclose(fp); }
+ return (*g_engfuncs.pfnIsMapValid)(filename);
+}
+void pfnStaticDecal( const float *origin, int decalIndex, int entityIndex, int modelIndex )
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnStaticDecal:\n"); fclose(fp); }
+ (*g_engfuncs.pfnStaticDecal)(origin, decalIndex, entityIndex, modelIndex);
+}
+int pfnPrecacheGeneric(char* s)
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnPrecacheGeneric: %s\n",s); fclose(fp); }
+ return (*g_engfuncs.pfnPrecacheGeneric)(s);
+}
+int pfnGetPlayerUserId(edict_t *e )
+{
+ if (gpGlobals->deathmatch)
+ {
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnGetPlayerUserId: %x\n",e); fclose(fp); }
+
+ if (mod_id == GEARBOX_DLL)
+ {
+ // is this edict a bot?
+ if (UTIL_GetBotPointer( e ))
+ return 0; // don't return a valid index (so bot won't get kicked)
+ }
+ }
+
+ return (*g_engfuncs.pfnGetPlayerUserId)(e);
+}
+void pfnBuildSoundMsg(edict_t *entity, int channel, const char *sample, /*int*/float volume, float attenuation, int fFlags, int pitch, int msg_dest, int msg_type, const float *pOrigin, edict_t *ed)
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnBuildSoundMsg:\n"); fclose(fp); }
+ (*g_engfuncs.pfnBuildSoundMsg)(entity, channel, sample, volume, attenuation, fFlags, pitch, msg_dest, msg_type, pOrigin, ed);
+}
+int pfnIsDedicatedServer(void)
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnIsDedicatedServer:\n"); fclose(fp); }
+ return (*g_engfuncs.pfnIsDedicatedServer)();
+}
+cvar_t* pfnCVarGetPointer(const char *szVarName)
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnCVarGetPointer: %s\n",szVarName); fclose(fp); }
+ return (*g_engfuncs.pfnCVarGetPointer)(szVarName);
+}
+unsigned int pfnGetPlayerWONId(edict_t *e)
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnGetPlayerWONId: %x\n",e); fclose(fp); }
+ return (*g_engfuncs.pfnGetPlayerWONId)(e);
+}
+
+
+// new stuff for SDK 2.0
+
+void pfnInfo_RemoveKey(char *s, const char *key)
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnInfo_RemoveKey:\n"); fclose(fp); }
+ (*g_engfuncs.pfnInfo_RemoveKey)(s, key);
+}
+const char *pfnGetPhysicsKeyValue(const edict_t *pClient, const char *key)
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnGetPhysicsKeyValue:\n"); fclose(fp); }
+ return (*g_engfuncs.pfnGetPhysicsKeyValue)(pClient, key);
+}
+void pfnSetPhysicsKeyValue(const edict_t *pClient, const char *key, const char *value)
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnSetPhysicsKeyValue:\n"); fclose(fp); }
+ (*g_engfuncs.pfnSetPhysicsKeyValue)(pClient, key, value);
+}
+const char *pfnGetPhysicsInfoString(const edict_t *pClient)
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnGetPhysicsInfoString:\n"); fclose(fp); }
+ return (*g_engfuncs.pfnGetPhysicsInfoString)(pClient);
+}
+unsigned short pfnPrecacheEvent(int type, const char *psz)
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnPrecacheEvent:\n"); fclose(fp); }
+ return (*g_engfuncs.pfnPrecacheEvent)(type, psz);
+}
+void pfnPlaybackEvent(int flags, const edict_t *pInvoker, unsigned short eventindex, float delay,
+ float *origin, float *angles, float fparam1,float fparam2, int iparam1, int iparam2, int bparam1, int bparam2)
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnPlaybackEvent:\n"); fclose(fp); }
+ (*g_engfuncs.pfnPlaybackEvent)(flags, pInvoker, eventindex, delay, origin, angles, fparam1, fparam2, iparam1, iparam2, bparam1, bparam2);
+}
+unsigned char *pfnSetFatPVS(float *org)
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnSetFatPVS:\n"); fclose(fp); }
+ return (*g_engfuncs.pfnSetFatPVS)(org);
+}
+unsigned char *pfnSetFatPAS(float *org)
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnSetFatPAS:\n"); fclose(fp); }
+ return (*g_engfuncs.pfnSetFatPAS)(org);
+}
+int pfnCheckVisibility(const edict_t *entity, unsigned char *pset)
+{
+// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnCheckVisibility:\n"); fclose(fp); }
+ return (*g_engfuncs.pfnCheckVisibility)(entity, pset);
+}
+void pfnDeltaSetField(struct delta_s *pFields, const char *fieldname)
+{
+// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnDeltaSetField:\n"); fclose(fp); }
+ (*g_engfuncs.pfnDeltaSetField)(pFields, fieldname);
+}
+void pfnDeltaUnsetField(struct delta_s *pFields, const char *fieldname)
+{
+// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnDeltaUnsetField:\n"); fclose(fp); }
+ (*g_engfuncs.pfnDeltaUnsetField)(pFields, fieldname);
+}
+void pfnDeltaAddEncoder(char *name, void (*conditionalencode)( struct delta_s *pFields, const unsigned char *from, const unsigned char *to))
+{
+// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnDeltaAddEncoder:\n"); fclose(fp); }
+ (*g_engfuncs.pfnDeltaAddEncoder)(name, conditionalencode);
+}
+int pfnGetCurrentPlayer(void)
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnGetCurrentPlayer:\n"); fclose(fp); }
+ return (*g_engfuncs.pfnGetCurrentPlayer)();
+}
+int pfnCanSkipPlayer(const edict_t *player)
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnCanSkipPlayer:\n"); fclose(fp); }
+ return (*g_engfuncs.pfnCanSkipPlayer)(player);
+}
+int pfnDeltaFindField(struct delta_s *pFields, const char *fieldname)
+{
+// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnDeltaFindField:\n"); fclose(fp); }
+ return (*g_engfuncs.pfnDeltaFindField)(pFields, fieldname);
+}
+void pfnDeltaSetFieldByIndex(struct delta_s *pFields, int fieldNumber)
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnDeltaSetFieldByIndex:\n"); fclose(fp); }
+ (*g_engfuncs.pfnDeltaSetFieldByIndex)(pFields, fieldNumber);
+}
+void pfnDeltaUnsetFieldByIndex(struct delta_s *pFields, int fieldNumber)
+{
+// if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnDeltaUnsetFieldByIndex:\n"); fclose(fp); }
+ (*g_engfuncs.pfnDeltaUnsetFieldByIndex)(pFields, fieldNumber);
+}
+void pfnSetGroupMask(int mask, int op)
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnSetGroupMask:\n"); fclose(fp); }
+ (*g_engfuncs.pfnSetGroupMask)(mask, op);
+}
+int pfnCreateInstancedBaseline(int classname, struct entity_state_s *baseline)
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnCreateInstancedBaseline:\n"); fclose(fp); }
+ return (*g_engfuncs.pfnCreateInstancedBaseline)(classname, baseline);
+}
+void pfnCvar_DirectSet(struct cvar_s *var, char *value)
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnCvar_DirectSet:\n"); fclose(fp); }
+ (*g_engfuncs.pfnCvar_DirectSet)(var, value);
+}
+void pfnForceUnmodified(FORCE_TYPE type, float *mins, float *maxs, const char *filename)
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnForceUnmodified:\n"); fclose(fp); }
+ (*g_engfuncs.pfnForceUnmodified)(type, mins, maxs, filename);
+}
+void pfnGetPlayerStats(const edict_t *pClient, int *ping, int *packet_loss)
+{
+ if (debug_engine) { fp=fopen("bot.txt","a"); fprintf(fp,"pfnGetPlayerStats:\n"); fclose(fp); }
+ (*g_engfuncs.pfnGetPlayerStats)(pClient, ping, packet_loss);
+}
+
diff --git a/main/source/HPB_bot/dlls/h_export.cpp b/main/source/HPB_bot/dlls/h_export.cpp
index c9dedfa5..acb2360b 100644
--- a/main/source/HPB_bot/dlls/h_export.cpp
+++ b/main/source/HPB_bot/dlls/h_export.cpp
@@ -1,290 +1,290 @@
-//
-// HPB bot - botman's High Ping Bastard bot
-//
-// (http://planethalflife.com/botman/)
-//
-// h_export.cpp
-//
-
-#include "dlls/extdll.h"
-#include "dlls/enginecallback.h"
-#include "dlls/util.h"
-#include "dlls/cbase.h"
-#include "mod/AvHConstants.h"
-
-#include "bot.h"
-#include "HPB_bot/engine/engine.h"
-#include "../types.h"
-
-#ifndef __linux__
-
-HINSTANCE h_Library = NULL;
-HGLOBAL h_global_argv = NULL;
-
-#else
-
-void *h_Library = NULL;
-char h_global_argv[1024];
-
-#endif
-
-enginefuncs_t g_engfuncs;
-globalvars_t *gpGlobals;
-char *g_argv;
-
-static FILE *fp;
-
-
-GETENTITYAPI other_GetEntityAPI = NULL;
-GETNEWDLLFUNCTIONS other_GetNewDLLFunctions = NULL;
-GIVEFNPTRSTODLL other_GiveFnptrsToDll = NULL;
-
-extern int mod_id;
-
-
-#ifndef __linux__
-
-// Required DLL entry point
-BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
-{
- if (fdwReason == DLL_PROCESS_ATTACH)
- {
- }
- else if (fdwReason == DLL_PROCESS_DETACH)
- {
- if (h_Library)
- FreeLibrary(h_Library);
-
- if (h_global_argv)
- {
- GlobalUnlock(h_global_argv);
- GlobalFree(h_global_argv);
- }
- }
-
- return TRUE;
-}
-
-#endif
-
-#ifndef __linux__
-#ifdef __BORLANDC__
-extern "C" DLLEXPORT void EXPORT GiveFnptrsToDll(enginefuncs_t* pengfuncsFromEngine, globalvars_t *pGlobals)
-#else
-void DLLEXPORT GiveFnptrsToDll( enginefuncs_t* pengfuncsFromEngine, globalvars_t *pGlobals )
-#endif
-#else
-extern "C" DLLEXPORT GiveFnptrsToDll( enginefuncs_t* pengfuncsFromEngine, globalvars_t *pGlobals )
-#endif
-{
- int pos;
- char game_dir[256];
- char mod_name[32];
-
-//#ifdef AVH_MAPPER_BUILD
-//strcpy(mod_name, kModDirectory);
-//#endif
-
- // get the engine functions from the engine...
-
- memcpy(&g_engfuncs, pengfuncsFromEngine, sizeof(enginefuncs_t));
- gpGlobals = pGlobals;
-
- // find the directory name of the currently running MOD...
- (*g_engfuncs.pfnGetGameDir)(game_dir);
-
- pos = strlen(game_dir) - 1;
-
- // scan backwards till first directory separator...
- while ((pos) && (game_dir[pos] != '/'))
- pos--;
-
- if (pos == 0)
- {
- // Error getting directory name!
-
- ALERT( at_error, "HPB_bot - Error determining MOD directory name!" );
- }
-
- pos++;
- strcpy(mod_name, &game_dir[pos]);
-
- mod_id = AVH_DLL;
-
-
-#ifdef WIN32
- string theTempName = string(getModDirectory()) + "\\dlls\\ns.dll";
- h_Library = LoadLibrary(theTempName.c_str());
-// TODO: Add this in when supporting linux again
-#else
- printf("DLopening ns/dlls/HPB_bot_i386.so...");
- h_Library = dlopen("ns/dlls/HPB_bot_i386.so", RTLD_NOW);
-#endif
-
-
- if (h_Library == NULL)
- {
- // Directory error or Unsupported MOD!
-
- ALERT( at_error, "HPB_bot - MOD dll not found (or unsupported MOD)!" );
- }
-
-
-#ifndef __linux__
- h_global_argv = GlobalAlloc(GMEM_SHARE, 1024);
- g_argv = (char *)GlobalLock(h_global_argv);
-#else
- g_argv = (char *)h_global_argv;
-#endif
-
- other_GetEntityAPI = (GETENTITYAPI)GetProcAddress(h_Library, "GetEntityAPI");
-
- if (other_GetEntityAPI == NULL)
- {
- // Can't find GetEntityAPI!
-
- ALERT( at_error, "HPB_bot - Can't get MOD's GetEntityAPI!" );
- }
-
- other_GetNewDLLFunctions = (GETNEWDLLFUNCTIONS)GetProcAddress(h_Library, "GetNewDLLFunctions");
-
-// if (other_GetNewDLLFunctions == NULL)
-// {
-// // Can't find GetNewDLLFunctions!
-//
-// ALERT( at_error, "HPB_bot - Can't get MOD's GetNewDLLFunctions!" );
-// }
-
- other_GiveFnptrsToDll = (GIVEFNPTRSTODLL)GetProcAddress(h_Library, "GiveFnptrsToDll");
-
- if (other_GiveFnptrsToDll == NULL)
- {
- // Can't find GiveFnptrsToDll!
-
- ALERT( at_error, "HPB_bot - Can't get MOD's GiveFnptrsToDll!" );
- }
-
- pengfuncsFromEngine->pfnCmd_Args = Cmd_Args;
- pengfuncsFromEngine->pfnCmd_Argv = Cmd_Argv;
- pengfuncsFromEngine->pfnCmd_Argc = Cmd_Argc;
-
- pengfuncsFromEngine->pfnPrecacheModel = pfnPrecacheModel;
- pengfuncsFromEngine->pfnPrecacheSound = pfnPrecacheSound;
- pengfuncsFromEngine->pfnSetModel = pfnSetModel;
- pengfuncsFromEngine->pfnModelIndex = pfnModelIndex;
- pengfuncsFromEngine->pfnModelFrames = pfnModelFrames;
- pengfuncsFromEngine->pfnSetSize = pfnSetSize;
- pengfuncsFromEngine->pfnChangeLevel = pfnChangeLevel;
- pengfuncsFromEngine->pfnGetSpawnParms = pfnGetSpawnParms;
- pengfuncsFromEngine->pfnSaveSpawnParms = pfnSaveSpawnParms;
- pengfuncsFromEngine->pfnVecToYaw = pfnVecToYaw;
- pengfuncsFromEngine->pfnVecToAngles = pfnVecToAngles;
- pengfuncsFromEngine->pfnMoveToOrigin = pfnMoveToOrigin;
- pengfuncsFromEngine->pfnChangeYaw = pfnChangeYaw;
- pengfuncsFromEngine->pfnChangePitch = pfnChangePitch;
- pengfuncsFromEngine->pfnFindEntityByString = pfnFindEntityByString;
- pengfuncsFromEngine->pfnGetEntityIllum = pfnGetEntityIllum;
- pengfuncsFromEngine->pfnFindEntityInSphere = pfnFindEntityInSphere;
- pengfuncsFromEngine->pfnFindClientInPVS = pfnFindClientInPVS;
- pengfuncsFromEngine->pfnEntitiesInPVS = pfnEntitiesInPVS;
- pengfuncsFromEngine->pfnMakeVectors = pfnMakeVectors;
- pengfuncsFromEngine->pfnAngleVectors = pfnAngleVectors;
- pengfuncsFromEngine->pfnCreateEntity = pfnCreateEntity;
- pengfuncsFromEngine->pfnRemoveEntity = pfnRemoveEntity;
- pengfuncsFromEngine->pfnCreateNamedEntity = pfnCreateNamedEntity;
- pengfuncsFromEngine->pfnMakeStatic = pfnMakeStatic;
- pengfuncsFromEngine->pfnEntIsOnFloor = pfnEntIsOnFloor;
- pengfuncsFromEngine->pfnDropToFloor = pfnDropToFloor;
- pengfuncsFromEngine->pfnWalkMove = pfnWalkMove;
- pengfuncsFromEngine->pfnSetOrigin = pfnSetOrigin;
- pengfuncsFromEngine->pfnEmitSound = pfnEmitSound;
- pengfuncsFromEngine->pfnEmitAmbientSound = pfnEmitAmbientSound;
- pengfuncsFromEngine->pfnTraceLine = pfnTraceLine;
- pengfuncsFromEngine->pfnTraceToss = pfnTraceToss;
- pengfuncsFromEngine->pfnTraceMonsterHull = pfnTraceMonsterHull;
- pengfuncsFromEngine->pfnTraceHull = pfnTraceHull;
- pengfuncsFromEngine->pfnTraceModel = pfnTraceModel;
- pengfuncsFromEngine->pfnTraceTexture = pfnTraceTexture;
- pengfuncsFromEngine->pfnTraceSphere = pfnTraceSphere;
- pengfuncsFromEngine->pfnGetAimVector = pfnGetAimVector;
- pengfuncsFromEngine->pfnServerCommand = pfnServerCommand;
- pengfuncsFromEngine->pfnServerExecute = pfnServerExecute;
-
- pengfuncsFromEngine->pfnClientCommand = pfnClientCommand;
-
- pengfuncsFromEngine->pfnParticleEffect = pfnParticleEffect;
- pengfuncsFromEngine->pfnLightStyle = pfnLightStyle;
- pengfuncsFromEngine->pfnDecalIndex = pfnDecalIndex;
- pengfuncsFromEngine->pfnPointContents = pfnPointContents;
- pengfuncsFromEngine->pfnMessageBegin = pfnMessageBegin;
- pengfuncsFromEngine->pfnMessageEnd = pfnMessageEnd;
- pengfuncsFromEngine->pfnWriteByte = pfnWriteByte;
- pengfuncsFromEngine->pfnWriteChar = pfnWriteChar;
- pengfuncsFromEngine->pfnWriteShort = pfnWriteShort;
- pengfuncsFromEngine->pfnWriteLong = pfnWriteLong;
- pengfuncsFromEngine->pfnWriteAngle = pfnWriteAngle;
- pengfuncsFromEngine->pfnWriteCoord = pfnWriteCoord;
- pengfuncsFromEngine->pfnWriteString = pfnWriteString;
- pengfuncsFromEngine->pfnWriteEntity = pfnWriteEntity;
- pengfuncsFromEngine->pfnCVarRegister = pfnCVarRegister;
- pengfuncsFromEngine->pfnCVarGetFloat = pfnCVarGetFloat;
- pengfuncsFromEngine->pfnCVarGetString = pfnCVarGetString;
- pengfuncsFromEngine->pfnCVarSetFloat = pfnCVarSetFloat;
- pengfuncsFromEngine->pfnCVarSetString = pfnCVarSetString;
- pengfuncsFromEngine->pfnPvAllocEntPrivateData = pfnPvAllocEntPrivateData;
- pengfuncsFromEngine->pfnPvEntPrivateData = pfnPvEntPrivateData;
- pengfuncsFromEngine->pfnFreeEntPrivateData = pfnFreeEntPrivateData;
- pengfuncsFromEngine->pfnSzFromIndex = pfnSzFromIndex;
- pengfuncsFromEngine->pfnAllocString = pfnAllocString;
- pengfuncsFromEngine->pfnGetVarsOfEnt = pfnGetVarsOfEnt;
- pengfuncsFromEngine->pfnPEntityOfEntOffset = pfnPEntityOfEntOffset;
- pengfuncsFromEngine->pfnEntOffsetOfPEntity = pfnEntOffsetOfPEntity;
- pengfuncsFromEngine->pfnIndexOfEdict = pfnIndexOfEdict;
- pengfuncsFromEngine->pfnPEntityOfEntIndex = pfnPEntityOfEntIndex;
- pengfuncsFromEngine->pfnFindEntityByVars = pfnFindEntityByVars;
- pengfuncsFromEngine->pfnGetModelPtr = pfnGetModelPtr;
- pengfuncsFromEngine->pfnRegUserMsg = pfnRegUserMsg;
- pengfuncsFromEngine->pfnAnimationAutomove = pfnAnimationAutomove;
- pengfuncsFromEngine->pfnGetBonePosition = pfnGetBonePosition;
- pengfuncsFromEngine->pfnFunctionFromName = pfnFunctionFromName;
- pengfuncsFromEngine->pfnNameForFunction = pfnNameForFunction;
- pengfuncsFromEngine->pfnClientPrintf = pfnClientPrintf;
- pengfuncsFromEngine->pfnServerPrint = pfnServerPrint;
- pengfuncsFromEngine->pfnGetAttachment = pfnGetAttachment;
- pengfuncsFromEngine->pfnCRC32_Init = pfnCRC32_Init;
- pengfuncsFromEngine->pfnCRC32_ProcessBuffer = pfnCRC32_ProcessBuffer;
- pengfuncsFromEngine->pfnCRC32_ProcessByte = pfnCRC32_ProcessByte;
- pengfuncsFromEngine->pfnCRC32_Final = pfnCRC32_Final;
- pengfuncsFromEngine->pfnRandomLong = pfnRandomLong;
- pengfuncsFromEngine->pfnRandomFloat = pfnRandomFloat;
- pengfuncsFromEngine->pfnSetView = pfnSetView;
- pengfuncsFromEngine->pfnTime = pfnTime;
- pengfuncsFromEngine->pfnCrosshairAngle = pfnCrosshairAngle;
- pengfuncsFromEngine->pfnLoadFileForMe = pfnLoadFileForMe;
- pengfuncsFromEngine->pfnFreeFile = pfnFreeFile;
- pengfuncsFromEngine->pfnEndSection = pfnEndSection;
- pengfuncsFromEngine->pfnCompareFileTime = pfnCompareFileTime;
- pengfuncsFromEngine->pfnGetGameDir = pfnGetGameDir;
- pengfuncsFromEngine->pfnCvar_RegisterVariable = pfnCvar_RegisterVariable;
- pengfuncsFromEngine->pfnFadeClientVolume = pfnFadeClientVolume;
- pengfuncsFromEngine->pfnSetClientMaxspeed = pfnSetClientMaxspeed;
- pengfuncsFromEngine->pfnCreateFakeClient = pfnCreateFakeClient;
- pengfuncsFromEngine->pfnRunPlayerMove = pfnRunPlayerMove;
- pengfuncsFromEngine->pfnNumberOfEntities = pfnNumberOfEntities;
- pengfuncsFromEngine->pfnGetInfoKeyBuffer = pfnGetInfoKeyBuffer;
- pengfuncsFromEngine->pfnInfoKeyValue = pfnInfoKeyValue;
- pengfuncsFromEngine->pfnSetKeyValue = pfnSetKeyValue;
- pengfuncsFromEngine->pfnSetClientKeyValue = pfnSetClientKeyValue;
- pengfuncsFromEngine->pfnIsMapValid = pfnIsMapValid;
- pengfuncsFromEngine->pfnStaticDecal = pfnStaticDecal;
- pengfuncsFromEngine->pfnPrecacheGeneric = pfnPrecacheGeneric;
- pengfuncsFromEngine->pfnGetPlayerUserId = pfnGetPlayerUserId;
- pengfuncsFromEngine->pfnBuildSoundMsg = pfnBuildSoundMsg;
- pengfuncsFromEngine->pfnIsDedicatedServer = pfnIsDedicatedServer;
- pengfuncsFromEngine->pfnCVarGetPointer = pfnCVarGetPointer;
- pengfuncsFromEngine->pfnGetPlayerWONId = pfnGetPlayerWONId;
-
- // give the engine functions to the other DLL...
- (*other_GiveFnptrsToDll)(pengfuncsFromEngine, pGlobals);
-}
-
+//
+// HPB bot - botman's High Ping Bastard bot
+//
+// (http://planethalflife.com/botman/)
+//
+// h_export.cpp
+//
+
+#include "dlls/extdll.h"
+#include "dlls/enginecallback.h"
+#include "dlls/util.h"
+#include "dlls/cbase.h"
+#include "mod/AvHConstants.h"
+
+#include "bot.h"
+#include "HPB_bot/engine/engine.h"
+#include "../types.h"
+
+#ifndef __linux__
+
+HINSTANCE h_Library = NULL;
+HGLOBAL h_global_argv = NULL;
+
+#else
+
+void *h_Library = NULL;
+char h_global_argv[1024];
+
+#endif
+
+enginefuncs_t g_engfuncs;
+globalvars_t *gpGlobals;
+char *g_argv;
+
+static FILE *fp;
+
+
+GETENTITYAPI other_GetEntityAPI = NULL;
+GETNEWDLLFUNCTIONS other_GetNewDLLFunctions = NULL;
+GIVEFNPTRSTODLL other_GiveFnptrsToDll = NULL;
+
+extern int mod_id;
+
+
+#ifndef __linux__
+
+// Required DLL entry point
+BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+{
+ if (fdwReason == DLL_PROCESS_ATTACH)
+ {
+ }
+ else if (fdwReason == DLL_PROCESS_DETACH)
+ {
+ if (h_Library)
+ FreeLibrary(h_Library);
+
+ if (h_global_argv)
+ {
+ GlobalUnlock(h_global_argv);
+ GlobalFree(h_global_argv);
+ }
+ }
+
+ return TRUE;
+}
+
+#endif
+
+#ifndef __linux__
+#ifdef __BORLANDC__
+extern "C" DLLEXPORT void EXPORT GiveFnptrsToDll(enginefuncs_t* pengfuncsFromEngine, globalvars_t *pGlobals)
+#else
+void DLLEXPORT GiveFnptrsToDll( enginefuncs_t* pengfuncsFromEngine, globalvars_t *pGlobals )
+#endif
+#else
+extern "C" DLLEXPORT GiveFnptrsToDll( enginefuncs_t* pengfuncsFromEngine, globalvars_t *pGlobals )
+#endif
+{
+ int pos;
+ char game_dir[256];
+ char mod_name[32];
+
+//#ifdef AVH_MAPPER_BUILD
+//strcpy(mod_name, kModDirectory);
+//#endif
+
+ // get the engine functions from the engine...
+
+ memcpy(&g_engfuncs, pengfuncsFromEngine, sizeof(enginefuncs_t));
+ gpGlobals = pGlobals;
+
+ // find the directory name of the currently running MOD...
+ (*g_engfuncs.pfnGetGameDir)(game_dir);
+
+ pos = strlen(game_dir) - 1;
+
+ // scan backwards till first directory separator...
+ while ((pos) && (game_dir[pos] != '/'))
+ pos--;
+
+ if (pos == 0)
+ {
+ // Error getting directory name!
+
+ ALERT( at_error, "HPB_bot - Error determining MOD directory name!" );
+ }
+
+ pos++;
+ strcpy(mod_name, &game_dir[pos]);
+
+ mod_id = AVH_DLL;
+
+
+#ifdef WIN32
+ string theTempName = string(getModDirectory()) + "\\dlls\\ns.dll";
+ h_Library = LoadLibrary(theTempName.c_str());
+// TODO: Add this in when supporting linux again
+#else
+ printf("DLopening ns/dlls/HPB_bot_i386.so...");
+ h_Library = dlopen("ns/dlls/HPB_bot_i386.so", RTLD_NOW);
+#endif
+
+
+ if (h_Library == NULL)
+ {
+ // Directory error or Unsupported MOD!
+
+ ALERT( at_error, "HPB_bot - MOD dll not found (or unsupported MOD)!" );
+ }
+
+
+#ifndef __linux__
+ h_global_argv = GlobalAlloc(GMEM_SHARE, 1024);
+ g_argv = (char *)GlobalLock(h_global_argv);
+#else
+ g_argv = (char *)h_global_argv;
+#endif
+
+ other_GetEntityAPI = (GETENTITYAPI)GetProcAddress(h_Library, "GetEntityAPI");
+
+ if (other_GetEntityAPI == NULL)
+ {
+ // Can't find GetEntityAPI!
+
+ ALERT( at_error, "HPB_bot - Can't get MOD's GetEntityAPI!" );
+ }
+
+ other_GetNewDLLFunctions = (GETNEWDLLFUNCTIONS)GetProcAddress(h_Library, "GetNewDLLFunctions");
+
+// if (other_GetNewDLLFunctions == NULL)
+// {
+// // Can't find GetNewDLLFunctions!
+//
+// ALERT( at_error, "HPB_bot - Can't get MOD's GetNewDLLFunctions!" );
+// }
+
+ other_GiveFnptrsToDll = (GIVEFNPTRSTODLL)GetProcAddress(h_Library, "GiveFnptrsToDll");
+
+ if (other_GiveFnptrsToDll == NULL)
+ {
+ // Can't find GiveFnptrsToDll!
+
+ ALERT( at_error, "HPB_bot - Can't get MOD's GiveFnptrsToDll!" );
+ }
+
+ pengfuncsFromEngine->pfnCmd_Args = Cmd_Args;
+ pengfuncsFromEngine->pfnCmd_Argv = Cmd_Argv;
+ pengfuncsFromEngine->pfnCmd_Argc = Cmd_Argc;
+
+ pengfuncsFromEngine->pfnPrecacheModel = pfnPrecacheModel;
+ pengfuncsFromEngine->pfnPrecacheSound = pfnPrecacheSound;
+ pengfuncsFromEngine->pfnSetModel = pfnSetModel;
+ pengfuncsFromEngine->pfnModelIndex = pfnModelIndex;
+ pengfuncsFromEngine->pfnModelFrames = pfnModelFrames;
+ pengfuncsFromEngine->pfnSetSize = pfnSetSize;
+ pengfuncsFromEngine->pfnChangeLevel = pfnChangeLevel;
+ pengfuncsFromEngine->pfnGetSpawnParms = pfnGetSpawnParms;
+ pengfuncsFromEngine->pfnSaveSpawnParms = pfnSaveSpawnParms;
+ pengfuncsFromEngine->pfnVecToYaw = pfnVecToYaw;
+ pengfuncsFromEngine->pfnVecToAngles = pfnVecToAngles;
+ pengfuncsFromEngine->pfnMoveToOrigin = pfnMoveToOrigin;
+ pengfuncsFromEngine->pfnChangeYaw = pfnChangeYaw;
+ pengfuncsFromEngine->pfnChangePitch = pfnChangePitch;
+ pengfuncsFromEngine->pfnFindEntityByString = pfnFindEntityByString;
+ pengfuncsFromEngine->pfnGetEntityIllum = pfnGetEntityIllum;
+ pengfuncsFromEngine->pfnFindEntityInSphere = pfnFindEntityInSphere;
+ pengfuncsFromEngine->pfnFindClientInPVS = pfnFindClientInPVS;
+ pengfuncsFromEngine->pfnEntitiesInPVS = pfnEntitiesInPVS;
+ pengfuncsFromEngine->pfnMakeVectors = pfnMakeVectors;
+ pengfuncsFromEngine->pfnAngleVectors = pfnAngleVectors;
+ pengfuncsFromEngine->pfnCreateEntity = pfnCreateEntity;
+ pengfuncsFromEngine->pfnRemoveEntity = pfnRemoveEntity;
+ pengfuncsFromEngine->pfnCreateNamedEntity = pfnCreateNamedEntity;
+ pengfuncsFromEngine->pfnMakeStatic = pfnMakeStatic;
+ pengfuncsFromEngine->pfnEntIsOnFloor = pfnEntIsOnFloor;
+ pengfuncsFromEngine->pfnDropToFloor = pfnDropToFloor;
+ pengfuncsFromEngine->pfnWalkMove = pfnWalkMove;
+ pengfuncsFromEngine->pfnSetOrigin = pfnSetOrigin;
+ pengfuncsFromEngine->pfnEmitSound = pfnEmitSound;
+ pengfuncsFromEngine->pfnEmitAmbientSound = pfnEmitAmbientSound;
+ pengfuncsFromEngine->pfnTraceLine = pfnTraceLine;
+ pengfuncsFromEngine->pfnTraceToss = pfnTraceToss;
+ pengfuncsFromEngine->pfnTraceMonsterHull = pfnTraceMonsterHull;
+ pengfuncsFromEngine->pfnTraceHull = pfnTraceHull;
+ pengfuncsFromEngine->pfnTraceModel = pfnTraceModel;
+ pengfuncsFromEngine->pfnTraceTexture = pfnTraceTexture;
+ pengfuncsFromEngine->pfnTraceSphere = pfnTraceSphere;
+ pengfuncsFromEngine->pfnGetAimVector = pfnGetAimVector;
+ pengfuncsFromEngine->pfnServerCommand = pfnServerCommand;
+ pengfuncsFromEngine->pfnServerExecute = pfnServerExecute;
+
+ pengfuncsFromEngine->pfnClientCommand = pfnClientCommand;
+
+ pengfuncsFromEngine->pfnParticleEffect = pfnParticleEffect;
+ pengfuncsFromEngine->pfnLightStyle = pfnLightStyle;
+ pengfuncsFromEngine->pfnDecalIndex = pfnDecalIndex;
+ pengfuncsFromEngine->pfnPointContents = pfnPointContents;
+ pengfuncsFromEngine->pfnMessageBegin = pfnMessageBegin;
+ pengfuncsFromEngine->pfnMessageEnd = pfnMessageEnd;
+ pengfuncsFromEngine->pfnWriteByte = pfnWriteByte;
+ pengfuncsFromEngine->pfnWriteChar = pfnWriteChar;
+ pengfuncsFromEngine->pfnWriteShort = pfnWriteShort;
+ pengfuncsFromEngine->pfnWriteLong = pfnWriteLong;
+ pengfuncsFromEngine->pfnWriteAngle = pfnWriteAngle;
+ pengfuncsFromEngine->pfnWriteCoord = pfnWriteCoord;
+ pengfuncsFromEngine->pfnWriteString = pfnWriteString;
+ pengfuncsFromEngine->pfnWriteEntity = pfnWriteEntity;
+ pengfuncsFromEngine->pfnCVarRegister = pfnCVarRegister;
+ pengfuncsFromEngine->pfnCVarGetFloat = pfnCVarGetFloat;
+ pengfuncsFromEngine->pfnCVarGetString = pfnCVarGetString;
+ pengfuncsFromEngine->pfnCVarSetFloat = pfnCVarSetFloat;
+ pengfuncsFromEngine->pfnCVarSetString = pfnCVarSetString;
+ pengfuncsFromEngine->pfnPvAllocEntPrivateData = pfnPvAllocEntPrivateData;
+ pengfuncsFromEngine->pfnPvEntPrivateData = pfnPvEntPrivateData;
+ pengfuncsFromEngine->pfnFreeEntPrivateData = pfnFreeEntPrivateData;
+ pengfuncsFromEngine->pfnSzFromIndex = pfnSzFromIndex;
+ pengfuncsFromEngine->pfnAllocString = pfnAllocString;
+ pengfuncsFromEngine->pfnGetVarsOfEnt = pfnGetVarsOfEnt;
+ pengfuncsFromEngine->pfnPEntityOfEntOffset = pfnPEntityOfEntOffset;
+ pengfuncsFromEngine->pfnEntOffsetOfPEntity = pfnEntOffsetOfPEntity;
+ pengfuncsFromEngine->pfnIndexOfEdict = pfnIndexOfEdict;
+ pengfuncsFromEngine->pfnPEntityOfEntIndex = pfnPEntityOfEntIndex;
+ pengfuncsFromEngine->pfnFindEntityByVars = pfnFindEntityByVars;
+ pengfuncsFromEngine->pfnGetModelPtr = pfnGetModelPtr;
+ pengfuncsFromEngine->pfnRegUserMsg = pfnRegUserMsg;
+ pengfuncsFromEngine->pfnAnimationAutomove = pfnAnimationAutomove;
+ pengfuncsFromEngine->pfnGetBonePosition = pfnGetBonePosition;
+ pengfuncsFromEngine->pfnFunctionFromName = pfnFunctionFromName;
+ pengfuncsFromEngine->pfnNameForFunction = pfnNameForFunction;
+ pengfuncsFromEngine->pfnClientPrintf = pfnClientPrintf;
+ pengfuncsFromEngine->pfnServerPrint = pfnServerPrint;
+ pengfuncsFromEngine->pfnGetAttachment = pfnGetAttachment;
+ pengfuncsFromEngine->pfnCRC32_Init = pfnCRC32_Init;
+ pengfuncsFromEngine->pfnCRC32_ProcessBuffer = pfnCRC32_ProcessBuffer;
+ pengfuncsFromEngine->pfnCRC32_ProcessByte = pfnCRC32_ProcessByte;
+ pengfuncsFromEngine->pfnCRC32_Final = pfnCRC32_Final;
+ pengfuncsFromEngine->pfnRandomLong = pfnRandomLong;
+ pengfuncsFromEngine->pfnRandomFloat = pfnRandomFloat;
+ pengfuncsFromEngine->pfnSetView = pfnSetView;
+ pengfuncsFromEngine->pfnTime = pfnTime;
+ pengfuncsFromEngine->pfnCrosshairAngle = pfnCrosshairAngle;
+ pengfuncsFromEngine->pfnLoadFileForMe = pfnLoadFileForMe;
+ pengfuncsFromEngine->pfnFreeFile = pfnFreeFile;
+ pengfuncsFromEngine->pfnEndSection = pfnEndSection;
+ pengfuncsFromEngine->pfnCompareFileTime = pfnCompareFileTime;
+ pengfuncsFromEngine->pfnGetGameDir = pfnGetGameDir;
+ pengfuncsFromEngine->pfnCvar_RegisterVariable = pfnCvar_RegisterVariable;
+ pengfuncsFromEngine->pfnFadeClientVolume = pfnFadeClientVolume;
+ pengfuncsFromEngine->pfnSetClientMaxspeed = pfnSetClientMaxspeed;
+ pengfuncsFromEngine->pfnCreateFakeClient = pfnCreateFakeClient;
+ pengfuncsFromEngine->pfnRunPlayerMove = pfnRunPlayerMove;
+ pengfuncsFromEngine->pfnNumberOfEntities = pfnNumberOfEntities;
+ pengfuncsFromEngine->pfnGetInfoKeyBuffer = pfnGetInfoKeyBuffer;
+ pengfuncsFromEngine->pfnInfoKeyValue = pfnInfoKeyValue;
+ pengfuncsFromEngine->pfnSetKeyValue = pfnSetKeyValue;
+ pengfuncsFromEngine->pfnSetClientKeyValue = pfnSetClientKeyValue;
+ pengfuncsFromEngine->pfnIsMapValid = pfnIsMapValid;
+ pengfuncsFromEngine->pfnStaticDecal = pfnStaticDecal;
+ pengfuncsFromEngine->pfnPrecacheGeneric = pfnPrecacheGeneric;
+ pengfuncsFromEngine->pfnGetPlayerUserId = pfnGetPlayerUserId;
+ pengfuncsFromEngine->pfnBuildSoundMsg = pfnBuildSoundMsg;
+ pengfuncsFromEngine->pfnIsDedicatedServer = pfnIsDedicatedServer;
+ pengfuncsFromEngine->pfnCVarGetPointer = pfnCVarGetPointer;
+ pengfuncsFromEngine->pfnGetPlayerWONId = pfnGetPlayerWONId;
+
+ // give the engine functions to the other DLL...
+ (*other_GiveFnptrsToDll)(pengfuncsFromEngine, pGlobals);
+}
+
diff --git a/main/source/HPB_bot/dlls/h_export.cpp~ b/main/source/HPB_bot/dlls/h_export.cpp~
deleted file mode 100644
index 68d11dd6..00000000
--- a/main/source/HPB_bot/dlls/h_export.cpp~
+++ /dev/null
@@ -1,290 +0,0 @@
-//
-// HPB bot - botman's High Ping Bastard bot
-//
-// (http://planethalflife.com/botman/)
-//
-// h_export.cpp
-//
-
-#include "dlls/extdll.h"
-#include "dlls/enginecallback.h"
-#include "dlls/util.h"
-#include "dlls/cbase.h"
-#include "mod/AvHConstants.h"
-
-#include "bot.h"
-#include "HPB_bot/engine/engine.h"
-#include "types.h"
-
-#ifndef __linux__
-
-HINSTANCE h_Library = NULL;
-HGLOBAL h_global_argv = NULL;
-
-#else
-
-void *h_Library = NULL;
-char h_global_argv[1024];
-
-#endif
-
-enginefuncs_t g_engfuncs;
-globalvars_t *gpGlobals;
-char *g_argv;
-
-static FILE *fp;
-
-
-GETENTITYAPI other_GetEntityAPI = NULL;
-GETNEWDLLFUNCTIONS other_GetNewDLLFunctions = NULL;
-GIVEFNPTRSTODLL other_GiveFnptrsToDll = NULL;
-
-extern int mod_id;
-
-
-#ifndef __linux__
-
-// Required DLL entry point
-BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
-{
- if (fdwReason == DLL_PROCESS_ATTACH)
- {
- }
- else if (fdwReason == DLL_PROCESS_DETACH)
- {
- if (h_Library)
- FreeLibrary(h_Library);
-
- if (h_global_argv)
- {
- GlobalUnlock(h_global_argv);
- GlobalFree(h_global_argv);
- }
- }
-
- return TRUE;
-}
-
-#endif
-
-#ifndef __linux__
-#ifdef __BORLANDC__
-extern "C" DLLEXPORT void EXPORT GiveFnptrsToDll(enginefuncs_t* pengfuncsFromEngine, globalvars_t *pGlobals)
-#else
-void DLLEXPORT GiveFnptrsToDll( enginefuncs_t* pengfuncsFromEngine, globalvars_t *pGlobals )
-#endif
-#else
-extern "C" DLLEXPORT GiveFnptrsToDll( enginefuncs_t* pengfuncsFromEngine, globalvars_t *pGlobals )
-#endif
-{
- int pos;
- char game_dir[256];
- char mod_name[32];
-
-//#ifdef AVH_MAPPER_BUILD
-//strcpy(mod_name, kModDirectory);
-//#endif
-
- // get the engine functions from the engine...
-
- memcpy(&g_engfuncs, pengfuncsFromEngine, sizeof(enginefuncs_t));
- gpGlobals = pGlobals;
-
- // find the directory name of the currently running MOD...
- (*g_engfuncs.pfnGetGameDir)(game_dir);
-
- pos = strlen(game_dir) - 1;
-
- // scan backwards till first directory separator...
- while ((pos) && (game_dir[pos] != '/'))
- pos--;
-
- if (pos == 0)
- {
- // Error getting directory name!
-
- ALERT( at_error, "HPB_bot - Error determining MOD directory name!" );
- }
-
- pos++;
- strcpy(mod_name, &game_dir[pos]);
-
- mod_id = AVH_DLL;
-
-
-#ifdef WIN32
- string theTempName = string(getModDirectory()) + "\\dlls\\ns.dll";
- h_Library = LoadLibrary(theTempName.c_str());
-// TODO: Add this in when supporting linux again
-#else
- printf("DLopening ns/dlls/HPB_bot_i386.so...");
- h_Library = dlopen("ns/dlls/HPB_bot_i386.so", RTLD_NOW);
-#endif
-
-
- if (h_Library == NULL)
- {
- // Directory error or Unsupported MOD!
-
- ALERT( at_error, "HPB_bot - MOD dll not found (or unsupported MOD)!" );
- }
-
-
-#ifndef __linux__
- h_global_argv = GlobalAlloc(GMEM_SHARE, 1024);
- g_argv = (char *)GlobalLock(h_global_argv);
-#else
- g_argv = (char *)h_global_argv;
-#endif
-
- other_GetEntityAPI = (GETENTITYAPI)GetProcAddress(h_Library, "GetEntityAPI");
-
- if (other_GetEntityAPI == NULL)
- {
- // Can't find GetEntityAPI!
-
- ALERT( at_error, "HPB_bot - Can't get MOD's GetEntityAPI!" );
- }
-
- other_GetNewDLLFunctions = (GETNEWDLLFUNCTIONS)GetProcAddress(h_Library, "GetNewDLLFunctions");
-
-// if (other_GetNewDLLFunctions == NULL)
-// {
-// // Can't find GetNewDLLFunctions!
-//
-// ALERT( at_error, "HPB_bot - Can't get MOD's GetNewDLLFunctions!" );
-// }
-
- other_GiveFnptrsToDll = (GIVEFNPTRSTODLL)GetProcAddress(h_Library, "GiveFnptrsToDll");
-
- if (other_GiveFnptrsToDll == NULL)
- {
- // Can't find GiveFnptrsToDll!
-
- ALERT( at_error, "HPB_bot - Can't get MOD's GiveFnptrsToDll!" );
- }
-
- pengfuncsFromEngine->pfnCmd_Args = Cmd_Args;
- pengfuncsFromEngine->pfnCmd_Argv = Cmd_Argv;
- pengfuncsFromEngine->pfnCmd_Argc = Cmd_Argc;
-
- pengfuncsFromEngine->pfnPrecacheModel = pfnPrecacheModel;
- pengfuncsFromEngine->pfnPrecacheSound = pfnPrecacheSound;
- pengfuncsFromEngine->pfnSetModel = pfnSetModel;
- pengfuncsFromEngine->pfnModelIndex = pfnModelIndex;
- pengfuncsFromEngine->pfnModelFrames = pfnModelFrames;
- pengfuncsFromEngine->pfnSetSize = pfnSetSize;
- pengfuncsFromEngine->pfnChangeLevel = pfnChangeLevel;
- pengfuncsFromEngine->pfnGetSpawnParms = pfnGetSpawnParms;
- pengfuncsFromEngine->pfnSaveSpawnParms = pfnSaveSpawnParms;
- pengfuncsFromEngine->pfnVecToYaw = pfnVecToYaw;
- pengfuncsFromEngine->pfnVecToAngles = pfnVecToAngles;
- pengfuncsFromEngine->pfnMoveToOrigin = pfnMoveToOrigin;
- pengfuncsFromEngine->pfnChangeYaw = pfnChangeYaw;
- pengfuncsFromEngine->pfnChangePitch = pfnChangePitch;
- pengfuncsFromEngine->pfnFindEntityByString = pfnFindEntityByString;
- pengfuncsFromEngine->pfnGetEntityIllum = pfnGetEntityIllum;
- pengfuncsFromEngine->pfnFindEntityInSphere = pfnFindEntityInSphere;
- pengfuncsFromEngine->pfnFindClientInPVS = pfnFindClientInPVS;
- pengfuncsFromEngine->pfnEntitiesInPVS = pfnEntitiesInPVS;
- pengfuncsFromEngine->pfnMakeVectors = pfnMakeVectors;
- pengfuncsFromEngine->pfnAngleVectors = pfnAngleVectors;
- pengfuncsFromEngine->pfnCreateEntity = pfnCreateEntity;
- pengfuncsFromEngine->pfnRemoveEntity = pfnRemoveEntity;
- pengfuncsFromEngine->pfnCreateNamedEntity = pfnCreateNamedEntity;
- pengfuncsFromEngine->pfnMakeStatic = pfnMakeStatic;
- pengfuncsFromEngine->pfnEntIsOnFloor = pfnEntIsOnFloor;
- pengfuncsFromEngine->pfnDropToFloor = pfnDropToFloor;
- pengfuncsFromEngine->pfnWalkMove = pfnWalkMove;
- pengfuncsFromEngine->pfnSetOrigin = pfnSetOrigin;
- pengfuncsFromEngine->pfnEmitSound = pfnEmitSound;
- pengfuncsFromEngine->pfnEmitAmbientSound = pfnEmitAmbientSound;
- pengfuncsFromEngine->pfnTraceLine = pfnTraceLine;
- pengfuncsFromEngine->pfnTraceToss = pfnTraceToss;
- pengfuncsFromEngine->pfnTraceMonsterHull = pfnTraceMonsterHull;
- pengfuncsFromEngine->pfnTraceHull = pfnTraceHull;
- pengfuncsFromEngine->pfnTraceModel = pfnTraceModel;
- pengfuncsFromEngine->pfnTraceTexture = pfnTraceTexture;
- pengfuncsFromEngine->pfnTraceSphere = pfnTraceSphere;
- pengfuncsFromEngine->pfnGetAimVector = pfnGetAimVector;
- pengfuncsFromEngine->pfnServerCommand = pfnServerCommand;
- pengfuncsFromEngine->pfnServerExecute = pfnServerExecute;
-
- pengfuncsFromEngine->pfnClientCommand = pfnClientCommand;
-
- pengfuncsFromEngine->pfnParticleEffect = pfnParticleEffect;
- pengfuncsFromEngine->pfnLightStyle = pfnLightStyle;
- pengfuncsFromEngine->pfnDecalIndex = pfnDecalIndex;
- pengfuncsFromEngine->pfnPointContents = pfnPointContents;
- pengfuncsFromEngine->pfnMessageBegin = pfnMessageBegin;
- pengfuncsFromEngine->pfnMessageEnd = pfnMessageEnd;
- pengfuncsFromEngine->pfnWriteByte = pfnWriteByte;
- pengfuncsFromEngine->pfnWriteChar = pfnWriteChar;
- pengfuncsFromEngine->pfnWriteShort = pfnWriteShort;
- pengfuncsFromEngine->pfnWriteLong = pfnWriteLong;
- pengfuncsFromEngine->pfnWriteAngle = pfnWriteAngle;
- pengfuncsFromEngine->pfnWriteCoord = pfnWriteCoord;
- pengfuncsFromEngine->pfnWriteString = pfnWriteString;
- pengfuncsFromEngine->pfnWriteEntity = pfnWriteEntity;
- pengfuncsFromEngine->pfnCVarRegister = pfnCVarRegister;
- pengfuncsFromEngine->pfnCVarGetFloat = pfnCVarGetFloat;
- pengfuncsFromEngine->pfnCVarGetString = pfnCVarGetString;
- pengfuncsFromEngine->pfnCVarSetFloat = pfnCVarSetFloat;
- pengfuncsFromEngine->pfnCVarSetString = pfnCVarSetString;
- pengfuncsFromEngine->pfnPvAllocEntPrivateData = pfnPvAllocEntPrivateData;
- pengfuncsFromEngine->pfnPvEntPrivateData = pfnPvEntPrivateData;
- pengfuncsFromEngine->pfnFreeEntPrivateData = pfnFreeEntPrivateData;
- pengfuncsFromEngine->pfnSzFromIndex = pfnSzFromIndex;
- pengfuncsFromEngine->pfnAllocString = pfnAllocString;
- pengfuncsFromEngine->pfnGetVarsOfEnt = pfnGetVarsOfEnt;
- pengfuncsFromEngine->pfnPEntityOfEntOffset = pfnPEntityOfEntOffset;
- pengfuncsFromEngine->pfnEntOffsetOfPEntity = pfnEntOffsetOfPEntity;
- pengfuncsFromEngine->pfnIndexOfEdict = pfnIndexOfEdict;
- pengfuncsFromEngine->pfnPEntityOfEntIndex = pfnPEntityOfEntIndex;
- pengfuncsFromEngine->pfnFindEntityByVars = pfnFindEntityByVars;
- pengfuncsFromEngine->pfnGetModelPtr = pfnGetModelPtr;
- pengfuncsFromEngine->pfnRegUserMsg = pfnRegUserMsg;
- pengfuncsFromEngine->pfnAnimationAutomove = pfnAnimationAutomove;
- pengfuncsFromEngine->pfnGetBonePosition = pfnGetBonePosition;
- pengfuncsFromEngine->pfnFunctionFromName = pfnFunctionFromName;
- pengfuncsFromEngine->pfnNameForFunction = pfnNameForFunction;
- pengfuncsFromEngine->pfnClientPrintf = pfnClientPrintf;
- pengfuncsFromEngine->pfnServerPrint = pfnServerPrint;
- pengfuncsFromEngine->pfnGetAttachment = pfnGetAttachment;
- pengfuncsFromEngine->pfnCRC32_Init = pfnCRC32_Init;
- pengfuncsFromEngine->pfnCRC32_ProcessBuffer = pfnCRC32_ProcessBuffer;
- pengfuncsFromEngine->pfnCRC32_ProcessByte = pfnCRC32_ProcessByte;
- pengfuncsFromEngine->pfnCRC32_Final = pfnCRC32_Final;
- pengfuncsFromEngine->pfnRandomLong = pfnRandomLong;
- pengfuncsFromEngine->pfnRandomFloat = pfnRandomFloat;
- pengfuncsFromEngine->pfnSetView = pfnSetView;
- pengfuncsFromEngine->pfnTime = pfnTime;
- pengfuncsFromEngine->pfnCrosshairAngle = pfnCrosshairAngle;
- pengfuncsFromEngine->pfnLoadFileForMe = pfnLoadFileForMe;
- pengfuncsFromEngine->pfnFreeFile = pfnFreeFile;
- pengfuncsFromEngine->pfnEndSection = pfnEndSection;
- pengfuncsFromEngine->pfnCompareFileTime = pfnCompareFileTime;
- pengfuncsFromEngine->pfnGetGameDir = pfnGetGameDir;
- pengfuncsFromEngine->pfnCvar_RegisterVariable = pfnCvar_RegisterVariable;
- pengfuncsFromEngine->pfnFadeClientVolume = pfnFadeClientVolume;
- pengfuncsFromEngine->pfnSetClientMaxspeed = pfnSetClientMaxspeed;
- pengfuncsFromEngine->pfnCreateFakeClient = pfnCreateFakeClient;
- pengfuncsFromEngine->pfnRunPlayerMove = pfnRunPlayerMove;
- pengfuncsFromEngine->pfnNumberOfEntities = pfnNumberOfEntities;
- pengfuncsFromEngine->pfnGetInfoKeyBuffer = pfnGetInfoKeyBuffer;
- pengfuncsFromEngine->pfnInfoKeyValue = pfnInfoKeyValue;
- pengfuncsFromEngine->pfnSetKeyValue = pfnSetKeyValue;
- pengfuncsFromEngine->pfnSetClientKeyValue = pfnSetClientKeyValue;
- pengfuncsFromEngine->pfnIsMapValid = pfnIsMapValid;
- pengfuncsFromEngine->pfnStaticDecal = pfnStaticDecal;
- pengfuncsFromEngine->pfnPrecacheGeneric = pfnPrecacheGeneric;
- pengfuncsFromEngine->pfnGetPlayerUserId = pfnGetPlayerUserId;
- pengfuncsFromEngine->pfnBuildSoundMsg = pfnBuildSoundMsg;
- pengfuncsFromEngine->pfnIsDedicatedServer = pfnIsDedicatedServer;
- pengfuncsFromEngine->pfnCVarGetPointer = pfnCVarGetPointer;
- pengfuncsFromEngine->pfnGetPlayerWONId = pfnGetPlayerWONId;
-
- // give the engine functions to the other DLL...
- (*other_GiveFnptrsToDll)(pengfuncsFromEngine, pGlobals);
-}
-
diff --git a/main/source/HPB_bot/dlls/linkfunc.cpp b/main/source/HPB_bot/dlls/linkfunc.cpp
index f9ef6bfc..a2b9e382 100644
--- a/main/source/HPB_bot/dlls/linkfunc.cpp
+++ b/main/source/HPB_bot/dlls/linkfunc.cpp
@@ -1,689 +1,689 @@
-//
-// HPB bot - botman's High Ping Bastard bot
-//
-// (http://planethalflife.com/botman/)
-//
-// linkfunc.cpp
-//
-
-#include "dlls/extdll.h"
-#include "dlls/util.h"
-#include "dlls/cbase.h"
-
-#include "bot.h"
-
-// For some reason, including these and using them doesn't work. Has something to do with
-// the preprocessor but I don't get it...
-//#include "mod/AvHConstants.h"
-//#include "mod/AvHMarineEquipmentConstants.h"
-
-#ifdef __BORLANDC__
-extern HINSTANCE _h_Library;
-#elif _WIN32
-extern HINSTANCE h_Library;
-#else
-extern void *h_Library;
-#endif
-
-#ifdef __BORLANDC__
-
-#define LINK_ENTITY_TO_FUNC(mapClassName) \
- extern "C" EXPORT void mapClassName( entvars_t *pev ); \
- void mapClassName( entvars_t *pev ) { \
- static LINK_ENTITY_FUNC otherClassName = NULL; \
- static int skip_this = 0; \
- if (skip_this) return; \
- if (otherClassName == NULL) \
- otherClassName = (LINK_ENTITY_FUNC)GetProcAddress(_h_Library, #mapClassName); \
- if (otherClassName == NULL) { \
- skip_this = 1; return; \
- } \
- (*otherClassName)(pev); }
-
-#else
-
-#define LINK_ENTITY_TO_FUNC(mapClassName) \
- extern "C" EXPORT void mapClassName( entvars_t *pev ); \
- void mapClassName( entvars_t *pev ) { \
- static LINK_ENTITY_FUNC otherClassName = NULL; \
- static int skip_this = 0; \
- if (skip_this) return; \
- if (otherClassName == NULL) \
- otherClassName = (LINK_ENTITY_FUNC)GetProcAddress(h_Library, #mapClassName); \
- if (otherClassName == NULL) { \
- skip_this = 1; return; \
- } \
- (*otherClassName)(pev); }
-
-#endif
-
-// new stuff for 1.1.0.4 release
-//LINK_ENTITY_TO_FUNC(CreateInterface);
-
-// entities for Valve's hl.dll and Standard SDK...
-LINK_ENTITY_TO_FUNC(aiscripted_sequence);
-LINK_ENTITY_TO_FUNC(ambient_generic);
-LINK_ENTITY_TO_FUNC(ammo_357);
-LINK_ENTITY_TO_FUNC(ammo_9mmAR);
-LINK_ENTITY_TO_FUNC(ammo_9mmbox);
-LINK_ENTITY_TO_FUNC(ammo_9mmclip);
-LINK_ENTITY_TO_FUNC(ammo_ARgrenades);
-LINK_ENTITY_TO_FUNC(ammo_buckshot);
-LINK_ENTITY_TO_FUNC(ammo_crossbow);
-LINK_ENTITY_TO_FUNC(ammo_egonclip);
-LINK_ENTITY_TO_FUNC(ammo_gaussclip);
-LINK_ENTITY_TO_FUNC(ammo_glockclip);
-LINK_ENTITY_TO_FUNC(ammo_mp5clip);
-LINK_ENTITY_TO_FUNC(ammo_mp5grenades);
-LINK_ENTITY_TO_FUNC(ammo_rpgclip);
-LINK_ENTITY_TO_FUNC(beam);
-LINK_ENTITY_TO_FUNC(bmortar);
-LINK_ENTITY_TO_FUNC(bodyque);
-LINK_ENTITY_TO_FUNC(button_target);
-LINK_ENTITY_TO_FUNC(cine_blood);
-LINK_ENTITY_TO_FUNC(controller_energy_ball);
-LINK_ENTITY_TO_FUNC(controller_head_ball);
-LINK_ENTITY_TO_FUNC(crossbow_bolt);
-LINK_ENTITY_TO_FUNC(cycler);
-LINK_ENTITY_TO_FUNC(cycler_prdroid);
-LINK_ENTITY_TO_FUNC(cycler_sprite);
-LINK_ENTITY_TO_FUNC(cycler_weapon);
-LINK_ENTITY_TO_FUNC(cycler_wreckage);
-LINK_ENTITY_TO_FUNC(DelayedUse);
-LINK_ENTITY_TO_FUNC(env_beam);
-LINK_ENTITY_TO_FUNC(env_beverage);
-LINK_ENTITY_TO_FUNC(env_blood);
-LINK_ENTITY_TO_FUNC(env_bubbles);
-LINK_ENTITY_TO_FUNC(env_debris);
-LINK_ENTITY_TO_FUNC(env_explosion);
-LINK_ENTITY_TO_FUNC(env_fade);
-LINK_ENTITY_TO_FUNC(env_funnel);
-LINK_ENTITY_TO_FUNC(env_global);
-LINK_ENTITY_TO_FUNC(env_glow);
-LINK_ENTITY_TO_FUNC(env_laser);
-LINK_ENTITY_TO_FUNC(env_lightning);
-LINK_ENTITY_TO_FUNC(env_message);
-LINK_ENTITY_TO_FUNC(env_render);
-LINK_ENTITY_TO_FUNC(env_shake);
-LINK_ENTITY_TO_FUNC(env_shooter);
-LINK_ENTITY_TO_FUNC(env_smoker);
-LINK_ENTITY_TO_FUNC(env_sound);
-LINK_ENTITY_TO_FUNC(env_spark);
-LINK_ENTITY_TO_FUNC(env_sprite);
-LINK_ENTITY_TO_FUNC(fireanddie);
-LINK_ENTITY_TO_FUNC(func_breakable);
-LINK_ENTITY_TO_FUNC(func_button);
-LINK_ENTITY_TO_FUNC(func_conveyor);
-LINK_ENTITY_TO_FUNC(func_door);
-LINK_ENTITY_TO_FUNC(func_door_rotating);
-LINK_ENTITY_TO_FUNC(func_friction);
-LINK_ENTITY_TO_FUNC(func_guntarget);
-LINK_ENTITY_TO_FUNC(func_healthcharger);
-LINK_ENTITY_TO_FUNC(func_illusionary);
-LINK_ENTITY_TO_FUNC(func_ladder);
-LINK_ENTITY_TO_FUNC(func_monsterclip);
-LINK_ENTITY_TO_FUNC(func_mortar_field);
-LINK_ENTITY_TO_FUNC(func_pendulum);
-LINK_ENTITY_TO_FUNC(func_plat);
-LINK_ENTITY_TO_FUNC(func_platrot);
-LINK_ENTITY_TO_FUNC(func_pushable);
-LINK_ENTITY_TO_FUNC(func_recharge);
-LINK_ENTITY_TO_FUNC(func_rot_button);
-LINK_ENTITY_TO_FUNC(func_rotating);
-LINK_ENTITY_TO_FUNC(func_tank);
-LINK_ENTITY_TO_FUNC(func_tankcontrols);
-LINK_ENTITY_TO_FUNC(func_tanklaser);
-LINK_ENTITY_TO_FUNC(func_tankmortar);
-LINK_ENTITY_TO_FUNC(func_tankrocket);
-LINK_ENTITY_TO_FUNC(func_trackautochange);
-LINK_ENTITY_TO_FUNC(func_trackchange);
-LINK_ENTITY_TO_FUNC(func_tracktrain);
-LINK_ENTITY_TO_FUNC(func_train);
-LINK_ENTITY_TO_FUNC(func_traincontrols);
-LINK_ENTITY_TO_FUNC(func_wall);
-LINK_ENTITY_TO_FUNC(func_wall_toggle);
-LINK_ENTITY_TO_FUNC(func_water);
-LINK_ENTITY_TO_FUNC(game_counter);
-LINK_ENTITY_TO_FUNC(game_counter_set);
-LINK_ENTITY_TO_FUNC(game_end);
-LINK_ENTITY_TO_FUNC(game_player_equip);
-LINK_ENTITY_TO_FUNC(game_player_hurt);
-LINK_ENTITY_TO_FUNC(game_player_team);
-LINK_ENTITY_TO_FUNC(game_score);
-LINK_ENTITY_TO_FUNC(game_team_master);
-LINK_ENTITY_TO_FUNC(game_team_set);
-LINK_ENTITY_TO_FUNC(game_text);
-LINK_ENTITY_TO_FUNC(game_zone_player);
-LINK_ENTITY_TO_FUNC(garg_stomp);
-LINK_ENTITY_TO_FUNC(gibshooter);
-LINK_ENTITY_TO_FUNC(grenade);
-LINK_ENTITY_TO_FUNC(hornet);
-LINK_ENTITY_TO_FUNC(hvr_rocket);
-LINK_ENTITY_TO_FUNC(info_bigmomma);
-LINK_ENTITY_TO_FUNC(info_intermission);
-LINK_ENTITY_TO_FUNC(info_landmark);
-LINK_ENTITY_TO_FUNC(info_node);
-LINK_ENTITY_TO_FUNC(info_node_air);
-LINK_ENTITY_TO_FUNC(info_null);
-LINK_ENTITY_TO_FUNC(info_player_deathmatch);
-LINK_ENTITY_TO_FUNC(info_player_start);
-LINK_ENTITY_TO_FUNC(info_target);
-LINK_ENTITY_TO_FUNC(info_teleport_destination);
-LINK_ENTITY_TO_FUNC(infodecal);
-LINK_ENTITY_TO_FUNC(item_airtank);
-LINK_ENTITY_TO_FUNC(item_antidote);
-LINK_ENTITY_TO_FUNC(item_battery);
-LINK_ENTITY_TO_FUNC(item_healthkit);
-LINK_ENTITY_TO_FUNC(item_longjump);
-LINK_ENTITY_TO_FUNC(item_security);
-LINK_ENTITY_TO_FUNC(item_sodacan);
-LINK_ENTITY_TO_FUNC(item_suit);
-LINK_ENTITY_TO_FUNC(laser_spot);
-LINK_ENTITY_TO_FUNC(light);
-LINK_ENTITY_TO_FUNC(light_environment);
-LINK_ENTITY_TO_FUNC(light_spot);
-LINK_ENTITY_TO_FUNC(momentary_door);
-LINK_ENTITY_TO_FUNC(momentary_rot_button);
-LINK_ENTITY_TO_FUNC(monstermaker);
-LINK_ENTITY_TO_FUNC(monster_alien_controller);
-LINK_ENTITY_TO_FUNC(monster_alien_grunt);
-LINK_ENTITY_TO_FUNC(monster_alien_slave);
-LINK_ENTITY_TO_FUNC(monster_apache);
-LINK_ENTITY_TO_FUNC(monster_babycrab);
-LINK_ENTITY_TO_FUNC(monster_barnacle);
-LINK_ENTITY_TO_FUNC(monster_barney);
-LINK_ENTITY_TO_FUNC(monster_barney_dead);
-LINK_ENTITY_TO_FUNC(monster_bigmomma);
-LINK_ENTITY_TO_FUNC(monster_bloater);
-LINK_ENTITY_TO_FUNC(monster_bullchicken);
-LINK_ENTITY_TO_FUNC(monster_cine2_hvyweapons);
-LINK_ENTITY_TO_FUNC(monster_cine2_scientist);
-LINK_ENTITY_TO_FUNC(monster_cine2_slave);
-LINK_ENTITY_TO_FUNC(monster_cine3_barney);
-LINK_ENTITY_TO_FUNC(monster_cine3_scientist);
-LINK_ENTITY_TO_FUNC(monster_cine_barney);
-LINK_ENTITY_TO_FUNC(monster_cine_panther);
-LINK_ENTITY_TO_FUNC(monster_cine_scientist);
-LINK_ENTITY_TO_FUNC(monster_cockroach);
-LINK_ENTITY_TO_FUNC(monster_flyer);
-LINK_ENTITY_TO_FUNC(monster_flyer_flock);
-LINK_ENTITY_TO_FUNC(monster_furniture);
-LINK_ENTITY_TO_FUNC(monster_gargantua);
-LINK_ENTITY_TO_FUNC(monster_generic);
-LINK_ENTITY_TO_FUNC(monster_gman);
-LINK_ENTITY_TO_FUNC(monster_grunt_repel);
-LINK_ENTITY_TO_FUNC(monster_headcrab);
-LINK_ENTITY_TO_FUNC(monster_hevsuit_dead);
-LINK_ENTITY_TO_FUNC(monster_hgrunt_dead);
-LINK_ENTITY_TO_FUNC(monster_houndeye);
-LINK_ENTITY_TO_FUNC(monster_human_assassin);
-LINK_ENTITY_TO_FUNC(monster_human_grunt);
-LINK_ENTITY_TO_FUNC(monster_ichthyosaur);
-LINK_ENTITY_TO_FUNC(monster_leech);
-LINK_ENTITY_TO_FUNC(monster_miniturret);
-LINK_ENTITY_TO_FUNC(monster_mortar);
-LINK_ENTITY_TO_FUNC(monster_nihilanth);
-LINK_ENTITY_TO_FUNC(monster_osprey);
-LINK_ENTITY_TO_FUNC(monster_rat);
-LINK_ENTITY_TO_FUNC(monster_satchel);
-LINK_ENTITY_TO_FUNC(monster_scientist);
-LINK_ENTITY_TO_FUNC(monster_scientist_dead);
-LINK_ENTITY_TO_FUNC(monster_sentry);
-LINK_ENTITY_TO_FUNC(monster_sitting_scientist);
-LINK_ENTITY_TO_FUNC(monster_snark);
-LINK_ENTITY_TO_FUNC(monster_tentacle);
-LINK_ENTITY_TO_FUNC(monster_tentaclemaw);
-LINK_ENTITY_TO_FUNC(monster_tripmine);
-LINK_ENTITY_TO_FUNC(monster_turret);
-LINK_ENTITY_TO_FUNC(monster_vortigaunt);
-LINK_ENTITY_TO_FUNC(monster_zombie);
-LINK_ENTITY_TO_FUNC(multi_manager);
-LINK_ENTITY_TO_FUNC(multisource);
-LINK_ENTITY_TO_FUNC(nihilanth_energy_ball);
-LINK_ENTITY_TO_FUNC(node_viewer);
-LINK_ENTITY_TO_FUNC(node_viewer_fly);
-LINK_ENTITY_TO_FUNC(node_viewer_human);
-LINK_ENTITY_TO_FUNC(node_viewer_large);
-LINK_ENTITY_TO_FUNC(path_corner);
-LINK_ENTITY_TO_FUNC(path_track);
-LINK_ENTITY_TO_FUNC(player);
-LINK_ENTITY_TO_FUNC(player_loadsaved);
-LINK_ENTITY_TO_FUNC(player_weaponstrip);
-LINK_ENTITY_TO_FUNC(rpg_rocket);
-LINK_ENTITY_TO_FUNC(scripted_sentence);
-LINK_ENTITY_TO_FUNC(scripted_sequence);
-LINK_ENTITY_TO_FUNC(soundent);
-LINK_ENTITY_TO_FUNC(spark_shower);
-LINK_ENTITY_TO_FUNC(speaker);
-LINK_ENTITY_TO_FUNC(squidspit);
-LINK_ENTITY_TO_FUNC(streak_spiral);
-LINK_ENTITY_TO_FUNC(target_cdaudio);
-LINK_ENTITY_TO_FUNC(test_effect);
-LINK_ENTITY_TO_FUNC(testhull);
-LINK_ENTITY_TO_FUNC(trigger);
-LINK_ENTITY_TO_FUNC(trigger_auto);
-LINK_ENTITY_TO_FUNC(trigger_autosave);
-LINK_ENTITY_TO_FUNC(trigger_camera);
-LINK_ENTITY_TO_FUNC(trigger_cdaudio);
-LINK_ENTITY_TO_FUNC(trigger_changelevel);
-LINK_ENTITY_TO_FUNC(trigger_changetarget);
-LINK_ENTITY_TO_FUNC(trigger_counter);
-LINK_ENTITY_TO_FUNC(trigger_endsection);
-LINK_ENTITY_TO_FUNC(trigger_gravity);
-LINK_ENTITY_TO_FUNC(trigger_hurt);
-LINK_ENTITY_TO_FUNC(trigger_monsterjump);
-LINK_ENTITY_TO_FUNC(trigger_multiple);
-LINK_ENTITY_TO_FUNC(trigger_once);
-LINK_ENTITY_TO_FUNC(trigger_push);
-LINK_ENTITY_TO_FUNC(trigger_relay);
-LINK_ENTITY_TO_FUNC(trigger_teleport);
-LINK_ENTITY_TO_FUNC(trigger_transition);
-LINK_ENTITY_TO_FUNC(weapon_357);
-LINK_ENTITY_TO_FUNC(weapon_9mmAR);
-LINK_ENTITY_TO_FUNC(weapon_9mmhandgun);
-LINK_ENTITY_TO_FUNC(weapon_crossbow);
-LINK_ENTITY_TO_FUNC(weapon_crowbar);
-LINK_ENTITY_TO_FUNC(weapon_egon);
-LINK_ENTITY_TO_FUNC(weapon_gauss);
-LINK_ENTITY_TO_FUNC(weapon_glock);
-LINK_ENTITY_TO_FUNC(weapon_handgrenade);
-LINK_ENTITY_TO_FUNC(weapon_hornetgun);
-LINK_ENTITY_TO_FUNC(weapon_mp5);
-LINK_ENTITY_TO_FUNC(weapon_python);
-LINK_ENTITY_TO_FUNC(weapon_rpg);
-LINK_ENTITY_TO_FUNC(weapon_satchel);
-//LINK_ENTITY_TO_FUNC(weapon_shotgun);
-LINK_ENTITY_TO_FUNC(weapon_snark);
-LINK_ENTITY_TO_FUNC(weapon_tripmine);
-LINK_ENTITY_TO_FUNC(weaponbox);
-LINK_ENTITY_TO_FUNC(world_items);
-LINK_ENTITY_TO_FUNC(worldspawn);
-LINK_ENTITY_TO_FUNC(xen_hair);
-LINK_ENTITY_TO_FUNC(xen_hull);
-LINK_ENTITY_TO_FUNC(xen_plantlight);
-LINK_ENTITY_TO_FUNC(xen_spore_large);
-LINK_ENTITY_TO_FUNC(xen_spore_medium);
-LINK_ENTITY_TO_FUNC(xen_spore_small);
-LINK_ENTITY_TO_FUNC(xen_tree);
-LINK_ENTITY_TO_FUNC(xen_ttrigger);
-
-//// entities for Team Fortress 1.5
-//LINK_ENTITY_TO_FUNC(building_dispenser);
-//LINK_ENTITY_TO_FUNC(building_sentrygun);
-//LINK_ENTITY_TO_FUNC(building_sentrygun_base);
-//LINK_ENTITY_TO_FUNC(detpack);
-//LINK_ENTITY_TO_FUNC(dispenser_refill_timer);
-//LINK_ENTITY_TO_FUNC(func_nobuild);
-//LINK_ENTITY_TO_FUNC(func_nogrenades);
-//LINK_ENTITY_TO_FUNC(ghost);
-//LINK_ENTITY_TO_FUNC(i_p_t);
-//LINK_ENTITY_TO_FUNC(i_t_g);
-//LINK_ENTITY_TO_FUNC(i_t_t);
-//LINK_ENTITY_TO_FUNC(info_areadef);
-//LINK_ENTITY_TO_FUNC(info_player_teamspawn);
-//LINK_ENTITY_TO_FUNC(info_tf_teamcheck);
-//LINK_ENTITY_TO_FUNC(info_tf_teamset);
-//LINK_ENTITY_TO_FUNC(info_tfdetect);
-//LINK_ENTITY_TO_FUNC(info_tfgoal);
-//LINK_ENTITY_TO_FUNC(info_tfgoal_timer);
-//LINK_ENTITY_TO_FUNC(item_armor1);
-//LINK_ENTITY_TO_FUNC(item_armor2);
-//LINK_ENTITY_TO_FUNC(item_armor3);
-//LINK_ENTITY_TO_FUNC(item_artifact_envirosuit);
-//LINK_ENTITY_TO_FUNC(item_artifact_invisibility);
-//LINK_ENTITY_TO_FUNC(item_artifact_invulnerability);
-//LINK_ENTITY_TO_FUNC(item_artifact_super_damage);
-//LINK_ENTITY_TO_FUNC(item_cells);
-//LINK_ENTITY_TO_FUNC(item_health);
-//LINK_ENTITY_TO_FUNC(item_rockets);
-//LINK_ENTITY_TO_FUNC(item_shells);
-//LINK_ENTITY_TO_FUNC(item_spikes);
-//LINK_ENTITY_TO_FUNC(item_tfgoal);
-//LINK_ENTITY_TO_FUNC(teledeath);
-//LINK_ENTITY_TO_FUNC(tf_ammo_rpgclip);
-//LINK_ENTITY_TO_FUNC(tf_flame);
-//LINK_ENTITY_TO_FUNC(tf_flamethrower_burst);
-//LINK_ENTITY_TO_FUNC(tf_gl_grenade);
-//LINK_ENTITY_TO_FUNC(tf_ic_rocket);
-//LINK_ENTITY_TO_FUNC(tf_nailgun_nail);
-//LINK_ENTITY_TO_FUNC(tf_rpg_rocket);
-//LINK_ENTITY_TO_FUNC(tf_weapon_ac);
-//LINK_ENTITY_TO_FUNC(tf_weapon_autorifle);
-//LINK_ENTITY_TO_FUNC(tf_weapon_axe);
-//LINK_ENTITY_TO_FUNC(tf_weapon_caltrop);
-//LINK_ENTITY_TO_FUNC(tf_weapon_caltropgrenade);
-//LINK_ENTITY_TO_FUNC(tf_weapon_concussiongrenade);
-//LINK_ENTITY_TO_FUNC(tf_weapon_empgrenade);
-//LINK_ENTITY_TO_FUNC(tf_weapon_flamethrower);
-//LINK_ENTITY_TO_FUNC(tf_weapon_gasgrenade);
-//LINK_ENTITY_TO_FUNC(tf_weapon_genericprimedgrenade);
-//LINK_ENTITY_TO_FUNC(tf_weapon_gl);
-//LINK_ENTITY_TO_FUNC(tf_weapon_ic);
-//LINK_ENTITY_TO_FUNC(tf_weapon_knife);
-//LINK_ENTITY_TO_FUNC(tf_weapon_medikit);
-//LINK_ENTITY_TO_FUNC(tf_weapon_mirvbomblet);
-//LINK_ENTITY_TO_FUNC(tf_weapon_mirvgrenade);
-//LINK_ENTITY_TO_FUNC(tf_weapon_nailgrenade);
-//LINK_ENTITY_TO_FUNC(tf_weapon_napalmgrenade);
-//LINK_ENTITY_TO_FUNC(tf_weapon_ng);
-//LINK_ENTITY_TO_FUNC(tf_weapon_normalgrenade);
-//LINK_ENTITY_TO_FUNC(tf_weapon_pl);
-//LINK_ENTITY_TO_FUNC(tf_weapon_railgun);
-//LINK_ENTITY_TO_FUNC(tf_weapon_rpg);
-//LINK_ENTITY_TO_FUNC(tf_weapon_shotgun);
-//LINK_ENTITY_TO_FUNC(tf_weapon_sniperrifle);
-//LINK_ENTITY_TO_FUNC(tf_weapon_spanner);
-//LINK_ENTITY_TO_FUNC(tf_weapon_superng);
-//LINK_ENTITY_TO_FUNC(tf_weapon_supershotgun);
-//LINK_ENTITY_TO_FUNC(tf_weapon_tranq);
-//LINK_ENTITY_TO_FUNC(timer);
-//
-//// entities for Counter-Strike (Beta 6.5, 6.6, 7.0, 7.1) & 1.0
-//LINK_ENTITY_TO_FUNC(ammo_338magnum);
-//LINK_ENTITY_TO_FUNC(ammo_357sig);
-//LINK_ENTITY_TO_FUNC(ammo_45acp);
-//LINK_ENTITY_TO_FUNC(ammo_50ae);
-//LINK_ENTITY_TO_FUNC(ammo_556nato);
-//LINK_ENTITY_TO_FUNC(ammo_556natobox);
-//LINK_ENTITY_TO_FUNC(ammo_57mm);
-//LINK_ENTITY_TO_FUNC(ammo_762nato);
-//LINK_ENTITY_TO_FUNC(ammo_9mm);
-//LINK_ENTITY_TO_FUNC(armoury_entity);
-//LINK_ENTITY_TO_FUNC(env_bombglow);
-//LINK_ENTITY_TO_FUNC(func_bomb_target);
-//LINK_ENTITY_TO_FUNC(func_buyzone);
-//LINK_ENTITY_TO_FUNC(func_escapezone);
-//LINK_ENTITY_TO_FUNC(func_grencatch);
-//LINK_ENTITY_TO_FUNC(func_hostage_rescue);
-//LINK_ENTITY_TO_FUNC(func_vehicle);
-//LINK_ENTITY_TO_FUNC(func_vehiclecontrols);
-//LINK_ENTITY_TO_FUNC(func_vip_safetyzone);
-//LINK_ENTITY_TO_FUNC(func_weaponcheck);
-//LINK_ENTITY_TO_FUNC(hostage_entity);
-//LINK_ENTITY_TO_FUNC(info_bomb_target);
-//LINK_ENTITY_TO_FUNC(info_hostage_rescue);
-//LINK_ENTITY_TO_FUNC(info_map_parameters);
-//LINK_ENTITY_TO_FUNC(info_vip_start);
-//LINK_ENTITY_TO_FUNC(item_assaultsuit);
-//LINK_ENTITY_TO_FUNC(item_kevlar);
-//LINK_ENTITY_TO_FUNC(item_thighpack);
-//LINK_ENTITY_TO_FUNC(weapon_ak47);
-//LINK_ENTITY_TO_FUNC(weapon_aug);
-//LINK_ENTITY_TO_FUNC(weapon_awp);
-//LINK_ENTITY_TO_FUNC(weapon_c4);
-//LINK_ENTITY_TO_FUNC(weapon_deagle);
-//LINK_ENTITY_TO_FUNC(weapon_elite);
-//LINK_ENTITY_TO_FUNC(weapon_fiveseven);
-//LINK_ENTITY_TO_FUNC(weapon_flashbang);
-//LINK_ENTITY_TO_FUNC(weapon_g3sg1);
-//LINK_ENTITY_TO_FUNC(weapon_glock18);
-//LINK_ENTITY_TO_FUNC(weapon_hegrenade);
-//LINK_ENTITY_TO_FUNC(weapon_knife);
-//LINK_ENTITY_TO_FUNC(weapon_m249);
-//LINK_ENTITY_TO_FUNC(weapon_m3);
-//LINK_ENTITY_TO_FUNC(weapon_m4a1);
-//LINK_ENTITY_TO_FUNC(weapon_mac10);
-//LINK_ENTITY_TO_FUNC(weapon_mp5navy);
-//LINK_ENTITY_TO_FUNC(weapon_p228);
-//LINK_ENTITY_TO_FUNC(weapon_p90);
-//LINK_ENTITY_TO_FUNC(weapon_scout);
-//LINK_ENTITY_TO_FUNC(weapon_sg550);
-//LINK_ENTITY_TO_FUNC(weapon_sg552);
-//LINK_ENTITY_TO_FUNC(weapon_smokegrenade);
-//LINK_ENTITY_TO_FUNC(weapon_tmp);
-//LINK_ENTITY_TO_FUNC(weapon_usp);
-//LINK_ENTITY_TO_FUNC(weapon_ump45);
-//LINK_ENTITY_TO_FUNC(weapon_xm1014);
-//
-//// entities for Opposing Force
-//LINK_ENTITY_TO_FUNC(ammo_556);
-//LINK_ENTITY_TO_FUNC(ammo_762);
-//LINK_ENTITY_TO_FUNC(ammo_eagleclip);
-//LINK_ENTITY_TO_FUNC(ammo_spore);
-//LINK_ENTITY_TO_FUNC(charged_bolt);
-//LINK_ENTITY_TO_FUNC(displacer_ball);
-//LINK_ENTITY_TO_FUNC(eagle_laser);
-//LINK_ENTITY_TO_FUNC(env_blowercannon);
-//LINK_ENTITY_TO_FUNC(env_electrified_wire);
-//LINK_ENTITY_TO_FUNC(env_genewormcloud);
-//LINK_ENTITY_TO_FUNC(env_genewormspawn);
-//LINK_ENTITY_TO_FUNC(env_rope);
-//LINK_ENTITY_TO_FUNC(env_spritetrain);
-//LINK_ENTITY_TO_FUNC(func_op4mortarcontroller);
-//LINK_ENTITY_TO_FUNC(func_tank_of);
-//LINK_ENTITY_TO_FUNC(func_tankcontrols_of);
-//LINK_ENTITY_TO_FUNC(func_tanklaser_of);
-//LINK_ENTITY_TO_FUNC(func_tankmortar_of);
-//LINK_ENTITY_TO_FUNC(func_tankrocket_of);
-//LINK_ENTITY_TO_FUNC(gonomeguts);
-//LINK_ENTITY_TO_FUNC(grapple_tip);
-//LINK_ENTITY_TO_FUNC(hvr_blkop_rocket);
-//LINK_ENTITY_TO_FUNC(info_ctfdetect);
-//LINK_ENTITY_TO_FUNC(info_ctfspawn);
-//LINK_ENTITY_TO_FUNC(info_ctfspawn_powerup);
-//LINK_ENTITY_TO_FUNC(info_displacer_earth_target);
-//LINK_ENTITY_TO_FUNC(info_displacer_xen_target);
-//LINK_ENTITY_TO_FUNC(info_pitworm);
-//LINK_ENTITY_TO_FUNC(info_pitworm_steam_lock);
-//LINK_ENTITY_TO_FUNC(item_ctfaccelerator);
-//LINK_ENTITY_TO_FUNC(item_ctfbackpack);
-//LINK_ENTITY_TO_FUNC(item_ctfbase);
-//LINK_ENTITY_TO_FUNC(item_ctfflag);
-//LINK_ENTITY_TO_FUNC(item_ctflongjump);
-//LINK_ENTITY_TO_FUNC(item_ctfportablehev);
-//LINK_ENTITY_TO_FUNC(item_ctfregeneration);
-//LINK_ENTITY_TO_FUNC(item_generic);
-//LINK_ENTITY_TO_FUNC(item_nuclearbomb);
-//LINK_ENTITY_TO_FUNC(item_nuclearbombbutton);
-//LINK_ENTITY_TO_FUNC(item_nuclearbombtimer);
-//LINK_ENTITY_TO_FUNC(item_vest);
-//LINK_ENTITY_TO_FUNC(monster_ShockTrooper_dead);
-//LINK_ENTITY_TO_FUNC(monster_alien_babyvoltigore);
-//LINK_ENTITY_TO_FUNC(monster_alien_slave_dead);
-//LINK_ENTITY_TO_FUNC(monster_alien_voltigore);
-//LINK_ENTITY_TO_FUNC(monster_assassin_repel);
-//LINK_ENTITY_TO_FUNC(monster_blkop_apache);
-//LINK_ENTITY_TO_FUNC(monster_blkop_osprey);
-//LINK_ENTITY_TO_FUNC(monster_cleansuit_scientist);
-//LINK_ENTITY_TO_FUNC(monster_cleansuit_scientist_dead);
-//LINK_ENTITY_TO_FUNC(monster_drillsergeant);
-//LINK_ENTITY_TO_FUNC(monster_fgrunt_repel);
-//LINK_ENTITY_TO_FUNC(monster_geneworm);
-//LINK_ENTITY_TO_FUNC(monster_gonome);
-//LINK_ENTITY_TO_FUNC(monster_gonome_dead);
-//LINK_ENTITY_TO_FUNC(monster_grunt_ally_repel);
-//LINK_ENTITY_TO_FUNC(monster_hfgrunt_dead);
-//LINK_ENTITY_TO_FUNC(monster_houndeye_dead);
-//LINK_ENTITY_TO_FUNC(monster_human_friendly_grunt);
-//LINK_ENTITY_TO_FUNC(monster_human_grunt_ally);
-//LINK_ENTITY_TO_FUNC(monster_human_grunt_ally_dead);
-//LINK_ENTITY_TO_FUNC(monster_human_medic_ally);
-//LINK_ENTITY_TO_FUNC(monster_human_torch_ally);
-//LINK_ENTITY_TO_FUNC(monster_male_assassin);
-//LINK_ENTITY_TO_FUNC(monster_massassin_dead);
-//LINK_ENTITY_TO_FUNC(monster_medic_ally_repel);
-//LINK_ENTITY_TO_FUNC(monster_op4loader);
-//LINK_ENTITY_TO_FUNC(monster_otis);
-//LINK_ENTITY_TO_FUNC(monster_otis_dead);
-//LINK_ENTITY_TO_FUNC(monster_penguin);
-//LINK_ENTITY_TO_FUNC(monster_pitdrone);
-//LINK_ENTITY_TO_FUNC(monster_pitworm);
-//LINK_ENTITY_TO_FUNC(monster_pitworm_up);
-//LINK_ENTITY_TO_FUNC(monster_recruit);
-//LINK_ENTITY_TO_FUNC(monster_shockroach);
-//LINK_ENTITY_TO_FUNC(monster_shocktrooper);
-//LINK_ENTITY_TO_FUNC(monster_shocktrooper_repel);
-//LINK_ENTITY_TO_FUNC(monster_sitting_cleansuit_scientist);
-//LINK_ENTITY_TO_FUNC(monster_skeleton_dead);
-//LINK_ENTITY_TO_FUNC(monster_torch_ally_repel);
-//LINK_ENTITY_TO_FUNC(monster_zombie_barney);
-//LINK_ENTITY_TO_FUNC(monster_zombie_soldier);
-//LINK_ENTITY_TO_FUNC(monster_zombie_soldier_dead);
-//LINK_ENTITY_TO_FUNC(mortar_shell);
-//LINK_ENTITY_TO_FUNC(op4mortar);
-//LINK_ENTITY_TO_FUNC(pitdronespike);
-//LINK_ENTITY_TO_FUNC(pitworm_gib);
-//LINK_ENTITY_TO_FUNC(pitworm_gibshooter);
-//LINK_ENTITY_TO_FUNC(rope_sample);
-//LINK_ENTITY_TO_FUNC(rope_segment);
-//LINK_ENTITY_TO_FUNC(shock_beam);
-//LINK_ENTITY_TO_FUNC(spore);
-//LINK_ENTITY_TO_FUNC(trigger_ctfgeneric);
-//LINK_ENTITY_TO_FUNC(trigger_geneworm_hit);
-//LINK_ENTITY_TO_FUNC(trigger_kill_nogib);
-//LINK_ENTITY_TO_FUNC(trigger_playerfreeze);
-//LINK_ENTITY_TO_FUNC(trigger_xen_return);
-//LINK_ENTITY_TO_FUNC(weapon_displacer);
-//LINK_ENTITY_TO_FUNC(weapon_eagle);
-//LINK_ENTITY_TO_FUNC(weapon_grapple);
-//LINK_ENTITY_TO_FUNC(weapon_penguin);
-//LINK_ENTITY_TO_FUNC(weapon_pipewrench);
-//LINK_ENTITY_TO_FUNC(weapon_shockrifle);
-//LINK_ENTITY_TO_FUNC(weapon_shockroach);
-//LINK_ENTITY_TO_FUNC(weapon_sniperrifle);
-//LINK_ENTITY_TO_FUNC(weapon_sporelauncher);
-//
-//// entities for FrontLineForce (1.0)
-//LINK_ENTITY_TO_FUNC(ammo_ak5);
-//LINK_ENTITY_TO_FUNC(ammo_beretta);
-//LINK_ENTITY_TO_FUNC(ammo_famas);
-//LINK_ENTITY_TO_FUNC(ammo_hk21);
-//LINK_ENTITY_TO_FUNC(ammo_m4);
-//LINK_ENTITY_TO_FUNC(ammo_mac10);
-//LINK_ENTITY_TO_FUNC(ammo_mk23);
-//LINK_ENTITY_TO_FUNC(ammo_mp5a2);
-//LINK_ENTITY_TO_FUNC(ammo_mp5sd);
-//LINK_ENTITY_TO_FUNC(ammo_msg90);
-//LINK_ENTITY_TO_FUNC(ammo_spas12);
-//LINK_ENTITY_TO_FUNC(ammo_ump45);
-//LINK_ENTITY_TO_FUNC(capture_point);
-//LINK_ENTITY_TO_FUNC(info_frontline);
-//LINK_ENTITY_TO_FUNC(info_player_attacker);
-//LINK_ENTITY_TO_FUNC(info_player_defender);
-//LINK_ENTITY_TO_FUNC(info_player_observer);
-//LINK_ENTITY_TO_FUNC(weapon_ak5);
-//LINK_ENTITY_TO_FUNC(weapon_beretta);
-//LINK_ENTITY_TO_FUNC(weapon_famas);
-//LINK_ENTITY_TO_FUNC(weapon_hk21);
-//LINK_ENTITY_TO_FUNC(weapon_m4);
-//LINK_ENTITY_TO_FUNC(weapon_mk23);
-//LINK_ENTITY_TO_FUNC(weapon_mp5a2);
-//LINK_ENTITY_TO_FUNC(weapon_mp5sd);
-//LINK_ENTITY_TO_FUNC(weapon_msg90);
-//LINK_ENTITY_TO_FUNC(weapon_spas12);
-
-// entities for Natural Selection
-LINK_ENTITY_TO_FUNC(info_team_start);
-LINK_ENTITY_TO_FUNC(info_spectate);
-LINK_ENTITY_TO_FUNC(info_join_team);
-LINK_ENTITY_TO_FUNC(info_leave_game);
-LINK_ENTITY_TO_FUNC(info_join_autoassign);
-LINK_ENTITY_TO_FUNC(info_mapinfo);
-LINK_ENTITY_TO_FUNC(info_gameplay);
-
-LINK_ENTITY_TO_FUNC(env_fog);
-LINK_ENTITY_TO_FUNC(env_gamma);
-LINK_ENTITY_TO_FUNC(env_particles);
-LINK_ENTITY_TO_FUNC(env_particles_custom);
-
-LINK_ENTITY_TO_FUNC(func_weldable);
-LINK_ENTITY_TO_FUNC(func_seethrough);
-LINK_ENTITY_TO_FUNC(func_seethroughdoor);
-//LINK_ENTITY_TO_FUNC(func_waypoint);
-LINK_ENTITY_TO_FUNC(func_nobuild);
-LINK_ENTITY_TO_FUNC(func_resource);
-
-LINK_ENTITY_TO_FUNC(target_mp3audio);
-LINK_ENTITY_TO_FUNC(trigger_random);
-LINK_ENTITY_TO_FUNC(trigger_presence);
-LINK_ENTITY_TO_FUNC(trigger_script);
-LINK_ENTITY_TO_FUNC(info_location);
-
-LINK_ENTITY_TO_FUNC(team_hive);
-LINK_ENTITY_TO_FUNC(team_command);
-LINK_ENTITY_TO_FUNC(team_breach);
-LINK_ENTITY_TO_FUNC(team_egg);
-LINK_ENTITY_TO_FUNC(team_webstrand);
-
-// Marine weapons and equipment
-LINK_ENTITY_TO_FUNC(weapon_knife);
-LINK_ENTITY_TO_FUNC(weapon_grenade);
-LINK_ENTITY_TO_FUNC(weapon_machinegun);
-LINK_ENTITY_TO_FUNC(weapon_pistol);
-LINK_ENTITY_TO_FUNC(weapon_flamegun);
-LINK_ENTITY_TO_FUNC(weapon_heavymachinegun);
-LINK_ENTITY_TO_FUNC(weapon_grenadegun);
-LINK_ENTITY_TO_FUNC(weapon_shotgun);
-LINK_ENTITY_TO_FUNC(weapon_nukegun);
-LINK_ENTITY_TO_FUNC(weapon_mine);
-LINK_ENTITY_TO_FUNC(weapon_welder);
-
-LINK_ENTITY_TO_FUNC(item_genericammo);
-LINK_ENTITY_TO_FUNC(item_mine);
-LINK_ENTITY_TO_FUNC(item_health);
-LINK_ENTITY_TO_FUNC(item_catalyst);
-LINK_ENTITY_TO_FUNC(item_heavyarmor);
-LINK_ENTITY_TO_FUNC(item_jetpack);
-
-LINK_ENTITY_TO_FUNC(scan);
-LINK_ENTITY_TO_FUNC(turret);
-LINK_ENTITY_TO_FUNC(phasegate);
-LINK_ENTITY_TO_FUNC(siegeturret);
-LINK_ENTITY_TO_FUNC(nuke);
-
-// Marine buildings
-LINK_ENTITY_TO_FUNC(resourcetower);
-LINK_ENTITY_TO_FUNC(team_infportal);
-LINK_ENTITY_TO_FUNC(team_turretfactory);
-LINK_ENTITY_TO_FUNC(team_advturretfactory);
-LINK_ENTITY_TO_FUNC(team_armory);
-LINK_ENTITY_TO_FUNC(team_advarmory);
-LINK_ENTITY_TO_FUNC(team_armslab);
-LINK_ENTITY_TO_FUNC(team_prototypelab);
-LINK_ENTITY_TO_FUNC(team_observatory);
-LINK_ENTITY_TO_FUNC(team_chemlab);
-LINK_ENTITY_TO_FUNC(team_medlab);
-LINK_ENTITY_TO_FUNC(team_nukeplant);
-
-// Alien buildings
-LINK_ENTITY_TO_FUNC(alienresourcetower);
-LINK_ENTITY_TO_FUNC(defensechamber);
-LINK_ENTITY_TO_FUNC(spikeprojectile);
-LINK_ENTITY_TO_FUNC(offensechamber);
-LINK_ENTITY_TO_FUNC(sensorychamber);
-LINK_ENTITY_TO_FUNC(movementchamber);
-
-// Alien abilities that are technically weapons (along with their projectiles)
-LINK_ENTITY_TO_FUNC(weapon_acidrocket);
-LINK_ENTITY_TO_FUNC(weapon_acidrocketgun);
-LINK_ENTITY_TO_FUNC(weapon_bilebomb);
-LINK_ENTITY_TO_FUNC(weapon_bilebombgun);
-LINK_ENTITY_TO_FUNC(weapon_bitegun);
-LINK_ENTITY_TO_FUNC(weapon_blink);
-LINK_ENTITY_TO_FUNC(weapon_claws);
-LINK_ENTITY_TO_FUNC(weapon_devour);
-LINK_ENTITY_TO_FUNC(weapon_divinewind);
-LINK_ENTITY_TO_FUNC(weapon_healingspray);
-LINK_ENTITY_TO_FUNC(weapon_metabolize);
-LINK_ENTITY_TO_FUNC(weapon_parasite);
-LINK_ENTITY_TO_FUNC(weapon_primalscream);
-LINK_ENTITY_TO_FUNC(weapon_spikegun);
-LINK_ENTITY_TO_FUNC(weapon_bite2gun);
-LINK_ENTITY_TO_FUNC(weapon_spit);
-LINK_ENTITY_TO_FUNC(weapon_spore);
-LINK_ENTITY_TO_FUNC(weapon_stomp);
-LINK_ENTITY_TO_FUNC(weapon_swipe);
-LINK_ENTITY_TO_FUNC(weapon_umbra);
-LINK_ENTITY_TO_FUNC(weapon_webspinner);
-
-// Alien abilities
-LINK_ENTITY_TO_FUNC(weapon_leap);
-LINK_ENTITY_TO_FUNC(weapon_charge);
-
-LINK_ENTITY_TO_FUNC(webgunprojectile);
-LINK_ENTITY_TO_FUNC(spitgunprojectile);
-LINK_ENTITY_TO_FUNC(stompprojectile);
-LINK_ENTITY_TO_FUNC(sporegunprojectile);
-LINK_ENTITY_TO_FUNC(umbracloud);
-LINK_ENTITY_TO_FUNC(umbraprojectile);
-
+//
+// HPB bot - botman's High Ping Bastard bot
+//
+// (http://planethalflife.com/botman/)
+//
+// linkfunc.cpp
+//
+
+#include "dlls/extdll.h"
+#include "dlls/util.h"
+#include "dlls/cbase.h"
+
+#include "bot.h"
+
+// For some reason, including these and using them doesn't work. Has something to do with
+// the preprocessor but I don't get it...
+//#include "mod/AvHConstants.h"
+//#include "mod/AvHMarineEquipmentConstants.h"
+
+#ifdef __BORLANDC__
+extern HINSTANCE _h_Library;
+#elif _WIN32
+extern HINSTANCE h_Library;
+#else
+extern void *h_Library;
+#endif
+
+#ifdef __BORLANDC__
+
+#define LINK_ENTITY_TO_FUNC(mapClassName) \
+ extern "C" EXPORT void mapClassName( entvars_t *pev ); \
+ void mapClassName( entvars_t *pev ) { \
+ static LINK_ENTITY_FUNC otherClassName = NULL; \
+ static int skip_this = 0; \
+ if (skip_this) return; \
+ if (otherClassName == NULL) \
+ otherClassName = (LINK_ENTITY_FUNC)GetProcAddress(_h_Library, #mapClassName); \
+ if (otherClassName == NULL) { \
+ skip_this = 1; return; \
+ } \
+ (*otherClassName)(pev); }
+
+#else
+
+#define LINK_ENTITY_TO_FUNC(mapClassName) \
+ extern "C" EXPORT void mapClassName( entvars_t *pev ); \
+ void mapClassName( entvars_t *pev ) { \
+ static LINK_ENTITY_FUNC otherClassName = NULL; \
+ static int skip_this = 0; \
+ if (skip_this) return; \
+ if (otherClassName == NULL) \
+ otherClassName = (LINK_ENTITY_FUNC)GetProcAddress(h_Library, #mapClassName); \
+ if (otherClassName == NULL) { \
+ skip_this = 1; return; \
+ } \
+ (*otherClassName)(pev); }
+
+#endif
+
+// new stuff for 1.1.0.4 release
+//LINK_ENTITY_TO_FUNC(CreateInterface);
+
+// entities for Valve's hl.dll and Standard SDK...
+LINK_ENTITY_TO_FUNC(aiscripted_sequence);
+LINK_ENTITY_TO_FUNC(ambient_generic);
+LINK_ENTITY_TO_FUNC(ammo_357);
+LINK_ENTITY_TO_FUNC(ammo_9mmAR);
+LINK_ENTITY_TO_FUNC(ammo_9mmbox);
+LINK_ENTITY_TO_FUNC(ammo_9mmclip);
+LINK_ENTITY_TO_FUNC(ammo_ARgrenades);
+LINK_ENTITY_TO_FUNC(ammo_buckshot);
+LINK_ENTITY_TO_FUNC(ammo_crossbow);
+LINK_ENTITY_TO_FUNC(ammo_egonclip);
+LINK_ENTITY_TO_FUNC(ammo_gaussclip);
+LINK_ENTITY_TO_FUNC(ammo_glockclip);
+LINK_ENTITY_TO_FUNC(ammo_mp5clip);
+LINK_ENTITY_TO_FUNC(ammo_mp5grenades);
+LINK_ENTITY_TO_FUNC(ammo_rpgclip);
+LINK_ENTITY_TO_FUNC(beam);
+LINK_ENTITY_TO_FUNC(bmortar);
+LINK_ENTITY_TO_FUNC(bodyque);
+LINK_ENTITY_TO_FUNC(button_target);
+LINK_ENTITY_TO_FUNC(cine_blood);
+LINK_ENTITY_TO_FUNC(controller_energy_ball);
+LINK_ENTITY_TO_FUNC(controller_head_ball);
+LINK_ENTITY_TO_FUNC(crossbow_bolt);
+LINK_ENTITY_TO_FUNC(cycler);
+LINK_ENTITY_TO_FUNC(cycler_prdroid);
+LINK_ENTITY_TO_FUNC(cycler_sprite);
+LINK_ENTITY_TO_FUNC(cycler_weapon);
+LINK_ENTITY_TO_FUNC(cycler_wreckage);
+LINK_ENTITY_TO_FUNC(DelayedUse);
+LINK_ENTITY_TO_FUNC(env_beam);
+LINK_ENTITY_TO_FUNC(env_beverage);
+LINK_ENTITY_TO_FUNC(env_blood);
+LINK_ENTITY_TO_FUNC(env_bubbles);
+LINK_ENTITY_TO_FUNC(env_debris);
+LINK_ENTITY_TO_FUNC(env_explosion);
+LINK_ENTITY_TO_FUNC(env_fade);
+LINK_ENTITY_TO_FUNC(env_funnel);
+LINK_ENTITY_TO_FUNC(env_global);
+LINK_ENTITY_TO_FUNC(env_glow);
+LINK_ENTITY_TO_FUNC(env_laser);
+LINK_ENTITY_TO_FUNC(env_lightning);
+LINK_ENTITY_TO_FUNC(env_message);
+LINK_ENTITY_TO_FUNC(env_render);
+LINK_ENTITY_TO_FUNC(env_shake);
+LINK_ENTITY_TO_FUNC(env_shooter);
+LINK_ENTITY_TO_FUNC(env_smoker);
+LINK_ENTITY_TO_FUNC(env_sound);
+LINK_ENTITY_TO_FUNC(env_spark);
+LINK_ENTITY_TO_FUNC(env_sprite);
+LINK_ENTITY_TO_FUNC(fireanddie);
+LINK_ENTITY_TO_FUNC(func_breakable);
+LINK_ENTITY_TO_FUNC(func_button);
+LINK_ENTITY_TO_FUNC(func_conveyor);
+LINK_ENTITY_TO_FUNC(func_door);
+LINK_ENTITY_TO_FUNC(func_door_rotating);
+LINK_ENTITY_TO_FUNC(func_friction);
+LINK_ENTITY_TO_FUNC(func_guntarget);
+LINK_ENTITY_TO_FUNC(func_healthcharger);
+LINK_ENTITY_TO_FUNC(func_illusionary);
+LINK_ENTITY_TO_FUNC(func_ladder);
+LINK_ENTITY_TO_FUNC(func_monsterclip);
+LINK_ENTITY_TO_FUNC(func_mortar_field);
+LINK_ENTITY_TO_FUNC(func_pendulum);
+LINK_ENTITY_TO_FUNC(func_plat);
+LINK_ENTITY_TO_FUNC(func_platrot);
+LINK_ENTITY_TO_FUNC(func_pushable);
+LINK_ENTITY_TO_FUNC(func_recharge);
+LINK_ENTITY_TO_FUNC(func_rot_button);
+LINK_ENTITY_TO_FUNC(func_rotating);
+LINK_ENTITY_TO_FUNC(func_tank);
+LINK_ENTITY_TO_FUNC(func_tankcontrols);
+LINK_ENTITY_TO_FUNC(func_tanklaser);
+LINK_ENTITY_TO_FUNC(func_tankmortar);
+LINK_ENTITY_TO_FUNC(func_tankrocket);
+LINK_ENTITY_TO_FUNC(func_trackautochange);
+LINK_ENTITY_TO_FUNC(func_trackchange);
+LINK_ENTITY_TO_FUNC(func_tracktrain);
+LINK_ENTITY_TO_FUNC(func_train);
+LINK_ENTITY_TO_FUNC(func_traincontrols);
+LINK_ENTITY_TO_FUNC(func_wall);
+LINK_ENTITY_TO_FUNC(func_wall_toggle);
+LINK_ENTITY_TO_FUNC(func_water);
+LINK_ENTITY_TO_FUNC(game_counter);
+LINK_ENTITY_TO_FUNC(game_counter_set);
+LINK_ENTITY_TO_FUNC(game_end);
+LINK_ENTITY_TO_FUNC(game_player_equip);
+LINK_ENTITY_TO_FUNC(game_player_hurt);
+LINK_ENTITY_TO_FUNC(game_player_team);
+LINK_ENTITY_TO_FUNC(game_score);
+LINK_ENTITY_TO_FUNC(game_team_master);
+LINK_ENTITY_TO_FUNC(game_team_set);
+LINK_ENTITY_TO_FUNC(game_text);
+LINK_ENTITY_TO_FUNC(game_zone_player);
+LINK_ENTITY_TO_FUNC(garg_stomp);
+LINK_ENTITY_TO_FUNC(gibshooter);
+LINK_ENTITY_TO_FUNC(grenade);
+LINK_ENTITY_TO_FUNC(hornet);
+LINK_ENTITY_TO_FUNC(hvr_rocket);
+LINK_ENTITY_TO_FUNC(info_bigmomma);
+LINK_ENTITY_TO_FUNC(info_intermission);
+LINK_ENTITY_TO_FUNC(info_landmark);
+LINK_ENTITY_TO_FUNC(info_node);
+LINK_ENTITY_TO_FUNC(info_node_air);
+LINK_ENTITY_TO_FUNC(info_null);
+LINK_ENTITY_TO_FUNC(info_player_deathmatch);
+LINK_ENTITY_TO_FUNC(info_player_start);
+LINK_ENTITY_TO_FUNC(info_target);
+LINK_ENTITY_TO_FUNC(info_teleport_destination);
+LINK_ENTITY_TO_FUNC(infodecal);
+LINK_ENTITY_TO_FUNC(item_airtank);
+LINK_ENTITY_TO_FUNC(item_antidote);
+LINK_ENTITY_TO_FUNC(item_battery);
+LINK_ENTITY_TO_FUNC(item_healthkit);
+LINK_ENTITY_TO_FUNC(item_longjump);
+LINK_ENTITY_TO_FUNC(item_security);
+LINK_ENTITY_TO_FUNC(item_sodacan);
+LINK_ENTITY_TO_FUNC(item_suit);
+LINK_ENTITY_TO_FUNC(laser_spot);
+LINK_ENTITY_TO_FUNC(light);
+LINK_ENTITY_TO_FUNC(light_environment);
+LINK_ENTITY_TO_FUNC(light_spot);
+LINK_ENTITY_TO_FUNC(momentary_door);
+LINK_ENTITY_TO_FUNC(momentary_rot_button);
+LINK_ENTITY_TO_FUNC(monstermaker);
+LINK_ENTITY_TO_FUNC(monster_alien_controller);
+LINK_ENTITY_TO_FUNC(monster_alien_grunt);
+LINK_ENTITY_TO_FUNC(monster_alien_slave);
+LINK_ENTITY_TO_FUNC(monster_apache);
+LINK_ENTITY_TO_FUNC(monster_babycrab);
+LINK_ENTITY_TO_FUNC(monster_barnacle);
+LINK_ENTITY_TO_FUNC(monster_barney);
+LINK_ENTITY_TO_FUNC(monster_barney_dead);
+LINK_ENTITY_TO_FUNC(monster_bigmomma);
+LINK_ENTITY_TO_FUNC(monster_bloater);
+LINK_ENTITY_TO_FUNC(monster_bullchicken);
+LINK_ENTITY_TO_FUNC(monster_cine2_hvyweapons);
+LINK_ENTITY_TO_FUNC(monster_cine2_scientist);
+LINK_ENTITY_TO_FUNC(monster_cine2_slave);
+LINK_ENTITY_TO_FUNC(monster_cine3_barney);
+LINK_ENTITY_TO_FUNC(monster_cine3_scientist);
+LINK_ENTITY_TO_FUNC(monster_cine_barney);
+LINK_ENTITY_TO_FUNC(monster_cine_panther);
+LINK_ENTITY_TO_FUNC(monster_cine_scientist);
+LINK_ENTITY_TO_FUNC(monster_cockroach);
+LINK_ENTITY_TO_FUNC(monster_flyer);
+LINK_ENTITY_TO_FUNC(monster_flyer_flock);
+LINK_ENTITY_TO_FUNC(monster_furniture);
+LINK_ENTITY_TO_FUNC(monster_gargantua);
+LINK_ENTITY_TO_FUNC(monster_generic);
+LINK_ENTITY_TO_FUNC(monster_gman);
+LINK_ENTITY_TO_FUNC(monster_grunt_repel);
+LINK_ENTITY_TO_FUNC(monster_headcrab);
+LINK_ENTITY_TO_FUNC(monster_hevsuit_dead);
+LINK_ENTITY_TO_FUNC(monster_hgrunt_dead);
+LINK_ENTITY_TO_FUNC(monster_houndeye);
+LINK_ENTITY_TO_FUNC(monster_human_assassin);
+LINK_ENTITY_TO_FUNC(monster_human_grunt);
+LINK_ENTITY_TO_FUNC(monster_ichthyosaur);
+LINK_ENTITY_TO_FUNC(monster_leech);
+LINK_ENTITY_TO_FUNC(monster_miniturret);
+LINK_ENTITY_TO_FUNC(monster_mortar);
+LINK_ENTITY_TO_FUNC(monster_nihilanth);
+LINK_ENTITY_TO_FUNC(monster_osprey);
+LINK_ENTITY_TO_FUNC(monster_rat);
+LINK_ENTITY_TO_FUNC(monster_satchel);
+LINK_ENTITY_TO_FUNC(monster_scientist);
+LINK_ENTITY_TO_FUNC(monster_scientist_dead);
+LINK_ENTITY_TO_FUNC(monster_sentry);
+LINK_ENTITY_TO_FUNC(monster_sitting_scientist);
+LINK_ENTITY_TO_FUNC(monster_snark);
+LINK_ENTITY_TO_FUNC(monster_tentacle);
+LINK_ENTITY_TO_FUNC(monster_tentaclemaw);
+LINK_ENTITY_TO_FUNC(monster_tripmine);
+LINK_ENTITY_TO_FUNC(monster_turret);
+LINK_ENTITY_TO_FUNC(monster_vortigaunt);
+LINK_ENTITY_TO_FUNC(monster_zombie);
+LINK_ENTITY_TO_FUNC(multi_manager);
+LINK_ENTITY_TO_FUNC(multisource);
+LINK_ENTITY_TO_FUNC(nihilanth_energy_ball);
+LINK_ENTITY_TO_FUNC(node_viewer);
+LINK_ENTITY_TO_FUNC(node_viewer_fly);
+LINK_ENTITY_TO_FUNC(node_viewer_human);
+LINK_ENTITY_TO_FUNC(node_viewer_large);
+LINK_ENTITY_TO_FUNC(path_corner);
+LINK_ENTITY_TO_FUNC(path_track);
+LINK_ENTITY_TO_FUNC(player);
+LINK_ENTITY_TO_FUNC(player_loadsaved);
+LINK_ENTITY_TO_FUNC(player_weaponstrip);
+LINK_ENTITY_TO_FUNC(rpg_rocket);
+LINK_ENTITY_TO_FUNC(scripted_sentence);
+LINK_ENTITY_TO_FUNC(scripted_sequence);
+LINK_ENTITY_TO_FUNC(soundent);
+LINK_ENTITY_TO_FUNC(spark_shower);
+LINK_ENTITY_TO_FUNC(speaker);
+LINK_ENTITY_TO_FUNC(squidspit);
+LINK_ENTITY_TO_FUNC(streak_spiral);
+LINK_ENTITY_TO_FUNC(target_cdaudio);
+LINK_ENTITY_TO_FUNC(test_effect);
+LINK_ENTITY_TO_FUNC(testhull);
+LINK_ENTITY_TO_FUNC(trigger);
+LINK_ENTITY_TO_FUNC(trigger_auto);
+LINK_ENTITY_TO_FUNC(trigger_autosave);
+LINK_ENTITY_TO_FUNC(trigger_camera);
+LINK_ENTITY_TO_FUNC(trigger_cdaudio);
+LINK_ENTITY_TO_FUNC(trigger_changelevel);
+LINK_ENTITY_TO_FUNC(trigger_changetarget);
+LINK_ENTITY_TO_FUNC(trigger_counter);
+LINK_ENTITY_TO_FUNC(trigger_endsection);
+LINK_ENTITY_TO_FUNC(trigger_gravity);
+LINK_ENTITY_TO_FUNC(trigger_hurt);
+LINK_ENTITY_TO_FUNC(trigger_monsterjump);
+LINK_ENTITY_TO_FUNC(trigger_multiple);
+LINK_ENTITY_TO_FUNC(trigger_once);
+LINK_ENTITY_TO_FUNC(trigger_push);
+LINK_ENTITY_TO_FUNC(trigger_relay);
+LINK_ENTITY_TO_FUNC(trigger_teleport);
+LINK_ENTITY_TO_FUNC(trigger_transition);
+LINK_ENTITY_TO_FUNC(weapon_357);
+LINK_ENTITY_TO_FUNC(weapon_9mmAR);
+LINK_ENTITY_TO_FUNC(weapon_9mmhandgun);
+LINK_ENTITY_TO_FUNC(weapon_crossbow);
+LINK_ENTITY_TO_FUNC(weapon_crowbar);
+LINK_ENTITY_TO_FUNC(weapon_egon);
+LINK_ENTITY_TO_FUNC(weapon_gauss);
+LINK_ENTITY_TO_FUNC(weapon_glock);
+LINK_ENTITY_TO_FUNC(weapon_handgrenade);
+LINK_ENTITY_TO_FUNC(weapon_hornetgun);
+LINK_ENTITY_TO_FUNC(weapon_mp5);
+LINK_ENTITY_TO_FUNC(weapon_python);
+LINK_ENTITY_TO_FUNC(weapon_rpg);
+LINK_ENTITY_TO_FUNC(weapon_satchel);
+//LINK_ENTITY_TO_FUNC(weapon_shotgun);
+LINK_ENTITY_TO_FUNC(weapon_snark);
+LINK_ENTITY_TO_FUNC(weapon_tripmine);
+LINK_ENTITY_TO_FUNC(weaponbox);
+LINK_ENTITY_TO_FUNC(world_items);
+LINK_ENTITY_TO_FUNC(worldspawn);
+LINK_ENTITY_TO_FUNC(xen_hair);
+LINK_ENTITY_TO_FUNC(xen_hull);
+LINK_ENTITY_TO_FUNC(xen_plantlight);
+LINK_ENTITY_TO_FUNC(xen_spore_large);
+LINK_ENTITY_TO_FUNC(xen_spore_medium);
+LINK_ENTITY_TO_FUNC(xen_spore_small);
+LINK_ENTITY_TO_FUNC(xen_tree);
+LINK_ENTITY_TO_FUNC(xen_ttrigger);
+
+//// entities for Team Fortress 1.5
+//LINK_ENTITY_TO_FUNC(building_dispenser);
+//LINK_ENTITY_TO_FUNC(building_sentrygun);
+//LINK_ENTITY_TO_FUNC(building_sentrygun_base);
+//LINK_ENTITY_TO_FUNC(detpack);
+//LINK_ENTITY_TO_FUNC(dispenser_refill_timer);
+//LINK_ENTITY_TO_FUNC(func_nobuild);
+//LINK_ENTITY_TO_FUNC(func_nogrenades);
+//LINK_ENTITY_TO_FUNC(ghost);
+//LINK_ENTITY_TO_FUNC(i_p_t);
+//LINK_ENTITY_TO_FUNC(i_t_g);
+//LINK_ENTITY_TO_FUNC(i_t_t);
+//LINK_ENTITY_TO_FUNC(info_areadef);
+//LINK_ENTITY_TO_FUNC(info_player_teamspawn);
+//LINK_ENTITY_TO_FUNC(info_tf_teamcheck);
+//LINK_ENTITY_TO_FUNC(info_tf_teamset);
+//LINK_ENTITY_TO_FUNC(info_tfdetect);
+//LINK_ENTITY_TO_FUNC(info_tfgoal);
+//LINK_ENTITY_TO_FUNC(info_tfgoal_timer);
+//LINK_ENTITY_TO_FUNC(item_armor1);
+//LINK_ENTITY_TO_FUNC(item_armor2);
+//LINK_ENTITY_TO_FUNC(item_armor3);
+//LINK_ENTITY_TO_FUNC(item_artifact_envirosuit);
+//LINK_ENTITY_TO_FUNC(item_artifact_invisibility);
+//LINK_ENTITY_TO_FUNC(item_artifact_invulnerability);
+//LINK_ENTITY_TO_FUNC(item_artifact_super_damage);
+//LINK_ENTITY_TO_FUNC(item_cells);
+//LINK_ENTITY_TO_FUNC(item_health);
+//LINK_ENTITY_TO_FUNC(item_rockets);
+//LINK_ENTITY_TO_FUNC(item_shells);
+//LINK_ENTITY_TO_FUNC(item_spikes);
+//LINK_ENTITY_TO_FUNC(item_tfgoal);
+//LINK_ENTITY_TO_FUNC(teledeath);
+//LINK_ENTITY_TO_FUNC(tf_ammo_rpgclip);
+//LINK_ENTITY_TO_FUNC(tf_flame);
+//LINK_ENTITY_TO_FUNC(tf_flamethrower_burst);
+//LINK_ENTITY_TO_FUNC(tf_gl_grenade);
+//LINK_ENTITY_TO_FUNC(tf_ic_rocket);
+//LINK_ENTITY_TO_FUNC(tf_nailgun_nail);
+//LINK_ENTITY_TO_FUNC(tf_rpg_rocket);
+//LINK_ENTITY_TO_FUNC(tf_weapon_ac);
+//LINK_ENTITY_TO_FUNC(tf_weapon_autorifle);
+//LINK_ENTITY_TO_FUNC(tf_weapon_axe);
+//LINK_ENTITY_TO_FUNC(tf_weapon_caltrop);
+//LINK_ENTITY_TO_FUNC(tf_weapon_caltropgrenade);
+//LINK_ENTITY_TO_FUNC(tf_weapon_concussiongrenade);
+//LINK_ENTITY_TO_FUNC(tf_weapon_empgrenade);
+//LINK_ENTITY_TO_FUNC(tf_weapon_flamethrower);
+//LINK_ENTITY_TO_FUNC(tf_weapon_gasgrenade);
+//LINK_ENTITY_TO_FUNC(tf_weapon_genericprimedgrenade);
+//LINK_ENTITY_TO_FUNC(tf_weapon_gl);
+//LINK_ENTITY_TO_FUNC(tf_weapon_ic);
+//LINK_ENTITY_TO_FUNC(tf_weapon_knife);
+//LINK_ENTITY_TO_FUNC(tf_weapon_medikit);
+//LINK_ENTITY_TO_FUNC(tf_weapon_mirvbomblet);
+//LINK_ENTITY_TO_FUNC(tf_weapon_mirvgrenade);
+//LINK_ENTITY_TO_FUNC(tf_weapon_nailgrenade);
+//LINK_ENTITY_TO_FUNC(tf_weapon_napalmgrenade);
+//LINK_ENTITY_TO_FUNC(tf_weapon_ng);
+//LINK_ENTITY_TO_FUNC(tf_weapon_normalgrenade);
+//LINK_ENTITY_TO_FUNC(tf_weapon_pl);
+//LINK_ENTITY_TO_FUNC(tf_weapon_railgun);
+//LINK_ENTITY_TO_FUNC(tf_weapon_rpg);
+//LINK_ENTITY_TO_FUNC(tf_weapon_shotgun);
+//LINK_ENTITY_TO_FUNC(tf_weapon_sniperrifle);
+//LINK_ENTITY_TO_FUNC(tf_weapon_spanner);
+//LINK_ENTITY_TO_FUNC(tf_weapon_superng);
+//LINK_ENTITY_TO_FUNC(tf_weapon_supershotgun);
+//LINK_ENTITY_TO_FUNC(tf_weapon_tranq);
+//LINK_ENTITY_TO_FUNC(timer);
+//
+//// entities for Counter-Strike (Beta 6.5, 6.6, 7.0, 7.1) & 1.0
+//LINK_ENTITY_TO_FUNC(ammo_338magnum);
+//LINK_ENTITY_TO_FUNC(ammo_357sig);
+//LINK_ENTITY_TO_FUNC(ammo_45acp);
+//LINK_ENTITY_TO_FUNC(ammo_50ae);
+//LINK_ENTITY_TO_FUNC(ammo_556nato);
+//LINK_ENTITY_TO_FUNC(ammo_556natobox);
+//LINK_ENTITY_TO_FUNC(ammo_57mm);
+//LINK_ENTITY_TO_FUNC(ammo_762nato);
+//LINK_ENTITY_TO_FUNC(ammo_9mm);
+//LINK_ENTITY_TO_FUNC(armoury_entity);
+//LINK_ENTITY_TO_FUNC(env_bombglow);
+//LINK_ENTITY_TO_FUNC(func_bomb_target);
+//LINK_ENTITY_TO_FUNC(func_buyzone);
+//LINK_ENTITY_TO_FUNC(func_escapezone);
+//LINK_ENTITY_TO_FUNC(func_grencatch);
+//LINK_ENTITY_TO_FUNC(func_hostage_rescue);
+//LINK_ENTITY_TO_FUNC(func_vehicle);
+//LINK_ENTITY_TO_FUNC(func_vehiclecontrols);
+//LINK_ENTITY_TO_FUNC(func_vip_safetyzone);
+//LINK_ENTITY_TO_FUNC(func_weaponcheck);
+//LINK_ENTITY_TO_FUNC(hostage_entity);
+//LINK_ENTITY_TO_FUNC(info_bomb_target);
+//LINK_ENTITY_TO_FUNC(info_hostage_rescue);
+//LINK_ENTITY_TO_FUNC(info_map_parameters);
+//LINK_ENTITY_TO_FUNC(info_vip_start);
+//LINK_ENTITY_TO_FUNC(item_assaultsuit);
+//LINK_ENTITY_TO_FUNC(item_kevlar);
+//LINK_ENTITY_TO_FUNC(item_thighpack);
+//LINK_ENTITY_TO_FUNC(weapon_ak47);
+//LINK_ENTITY_TO_FUNC(weapon_aug);
+//LINK_ENTITY_TO_FUNC(weapon_awp);
+//LINK_ENTITY_TO_FUNC(weapon_c4);
+//LINK_ENTITY_TO_FUNC(weapon_deagle);
+//LINK_ENTITY_TO_FUNC(weapon_elite);
+//LINK_ENTITY_TO_FUNC(weapon_fiveseven);
+//LINK_ENTITY_TO_FUNC(weapon_flashbang);
+//LINK_ENTITY_TO_FUNC(weapon_g3sg1);
+//LINK_ENTITY_TO_FUNC(weapon_glock18);
+//LINK_ENTITY_TO_FUNC(weapon_hegrenade);
+//LINK_ENTITY_TO_FUNC(weapon_knife);
+//LINK_ENTITY_TO_FUNC(weapon_m249);
+//LINK_ENTITY_TO_FUNC(weapon_m3);
+//LINK_ENTITY_TO_FUNC(weapon_m4a1);
+//LINK_ENTITY_TO_FUNC(weapon_mac10);
+//LINK_ENTITY_TO_FUNC(weapon_mp5navy);
+//LINK_ENTITY_TO_FUNC(weapon_p228);
+//LINK_ENTITY_TO_FUNC(weapon_p90);
+//LINK_ENTITY_TO_FUNC(weapon_scout);
+//LINK_ENTITY_TO_FUNC(weapon_sg550);
+//LINK_ENTITY_TO_FUNC(weapon_sg552);
+//LINK_ENTITY_TO_FUNC(weapon_smokegrenade);
+//LINK_ENTITY_TO_FUNC(weapon_tmp);
+//LINK_ENTITY_TO_FUNC(weapon_usp);
+//LINK_ENTITY_TO_FUNC(weapon_ump45);
+//LINK_ENTITY_TO_FUNC(weapon_xm1014);
+//
+//// entities for Opposing Force
+//LINK_ENTITY_TO_FUNC(ammo_556);
+//LINK_ENTITY_TO_FUNC(ammo_762);
+//LINK_ENTITY_TO_FUNC(ammo_eagleclip);
+//LINK_ENTITY_TO_FUNC(ammo_spore);
+//LINK_ENTITY_TO_FUNC(charged_bolt);
+//LINK_ENTITY_TO_FUNC(displacer_ball);
+//LINK_ENTITY_TO_FUNC(eagle_laser);
+//LINK_ENTITY_TO_FUNC(env_blowercannon);
+//LINK_ENTITY_TO_FUNC(env_electrified_wire);
+//LINK_ENTITY_TO_FUNC(env_genewormcloud);
+//LINK_ENTITY_TO_FUNC(env_genewormspawn);
+//LINK_ENTITY_TO_FUNC(env_rope);
+//LINK_ENTITY_TO_FUNC(env_spritetrain);
+//LINK_ENTITY_TO_FUNC(func_op4mortarcontroller);
+//LINK_ENTITY_TO_FUNC(func_tank_of);
+//LINK_ENTITY_TO_FUNC(func_tankcontrols_of);
+//LINK_ENTITY_TO_FUNC(func_tanklaser_of);
+//LINK_ENTITY_TO_FUNC(func_tankmortar_of);
+//LINK_ENTITY_TO_FUNC(func_tankrocket_of);
+//LINK_ENTITY_TO_FUNC(gonomeguts);
+//LINK_ENTITY_TO_FUNC(grapple_tip);
+//LINK_ENTITY_TO_FUNC(hvr_blkop_rocket);
+//LINK_ENTITY_TO_FUNC(info_ctfdetect);
+//LINK_ENTITY_TO_FUNC(info_ctfspawn);
+//LINK_ENTITY_TO_FUNC(info_ctfspawn_powerup);
+//LINK_ENTITY_TO_FUNC(info_displacer_earth_target);
+//LINK_ENTITY_TO_FUNC(info_displacer_xen_target);
+//LINK_ENTITY_TO_FUNC(info_pitworm);
+//LINK_ENTITY_TO_FUNC(info_pitworm_steam_lock);
+//LINK_ENTITY_TO_FUNC(item_ctfaccelerator);
+//LINK_ENTITY_TO_FUNC(item_ctfbackpack);
+//LINK_ENTITY_TO_FUNC(item_ctfbase);
+//LINK_ENTITY_TO_FUNC(item_ctfflag);
+//LINK_ENTITY_TO_FUNC(item_ctflongjump);
+//LINK_ENTITY_TO_FUNC(item_ctfportablehev);
+//LINK_ENTITY_TO_FUNC(item_ctfregeneration);
+//LINK_ENTITY_TO_FUNC(item_generic);
+//LINK_ENTITY_TO_FUNC(item_nuclearbomb);
+//LINK_ENTITY_TO_FUNC(item_nuclearbombbutton);
+//LINK_ENTITY_TO_FUNC(item_nuclearbombtimer);
+//LINK_ENTITY_TO_FUNC(item_vest);
+//LINK_ENTITY_TO_FUNC(monster_ShockTrooper_dead);
+//LINK_ENTITY_TO_FUNC(monster_alien_babyvoltigore);
+//LINK_ENTITY_TO_FUNC(monster_alien_slave_dead);
+//LINK_ENTITY_TO_FUNC(monster_alien_voltigore);
+//LINK_ENTITY_TO_FUNC(monster_assassin_repel);
+//LINK_ENTITY_TO_FUNC(monster_blkop_apache);
+//LINK_ENTITY_TO_FUNC(monster_blkop_osprey);
+//LINK_ENTITY_TO_FUNC(monster_cleansuit_scientist);
+//LINK_ENTITY_TO_FUNC(monster_cleansuit_scientist_dead);
+//LINK_ENTITY_TO_FUNC(monster_drillsergeant);
+//LINK_ENTITY_TO_FUNC(monster_fgrunt_repel);
+//LINK_ENTITY_TO_FUNC(monster_geneworm);
+//LINK_ENTITY_TO_FUNC(monster_gonome);
+//LINK_ENTITY_TO_FUNC(monster_gonome_dead);
+//LINK_ENTITY_TO_FUNC(monster_grunt_ally_repel);
+//LINK_ENTITY_TO_FUNC(monster_hfgrunt_dead);
+//LINK_ENTITY_TO_FUNC(monster_houndeye_dead);
+//LINK_ENTITY_TO_FUNC(monster_human_friendly_grunt);
+//LINK_ENTITY_TO_FUNC(monster_human_grunt_ally);
+//LINK_ENTITY_TO_FUNC(monster_human_grunt_ally_dead);
+//LINK_ENTITY_TO_FUNC(monster_human_medic_ally);
+//LINK_ENTITY_TO_FUNC(monster_human_torch_ally);
+//LINK_ENTITY_TO_FUNC(monster_male_assassin);
+//LINK_ENTITY_TO_FUNC(monster_massassin_dead);
+//LINK_ENTITY_TO_FUNC(monster_medic_ally_repel);
+//LINK_ENTITY_TO_FUNC(monster_op4loader);
+//LINK_ENTITY_TO_FUNC(monster_otis);
+//LINK_ENTITY_TO_FUNC(monster_otis_dead);
+//LINK_ENTITY_TO_FUNC(monster_penguin);
+//LINK_ENTITY_TO_FUNC(monster_pitdrone);
+//LINK_ENTITY_TO_FUNC(monster_pitworm);
+//LINK_ENTITY_TO_FUNC(monster_pitworm_up);
+//LINK_ENTITY_TO_FUNC(monster_recruit);
+//LINK_ENTITY_TO_FUNC(monster_shockroach);
+//LINK_ENTITY_TO_FUNC(monster_shocktrooper);
+//LINK_ENTITY_TO_FUNC(monster_shocktrooper_repel);
+//LINK_ENTITY_TO_FUNC(monster_sitting_cleansuit_scientist);
+//LINK_ENTITY_TO_FUNC(monster_skeleton_dead);
+//LINK_ENTITY_TO_FUNC(monster_torch_ally_repel);
+//LINK_ENTITY_TO_FUNC(monster_zombie_barney);
+//LINK_ENTITY_TO_FUNC(monster_zombie_soldier);
+//LINK_ENTITY_TO_FUNC(monster_zombie_soldier_dead);
+//LINK_ENTITY_TO_FUNC(mortar_shell);
+//LINK_ENTITY_TO_FUNC(op4mortar);
+//LINK_ENTITY_TO_FUNC(pitdronespike);
+//LINK_ENTITY_TO_FUNC(pitworm_gib);
+//LINK_ENTITY_TO_FUNC(pitworm_gibshooter);
+//LINK_ENTITY_TO_FUNC(rope_sample);
+//LINK_ENTITY_TO_FUNC(rope_segment);
+//LINK_ENTITY_TO_FUNC(shock_beam);
+//LINK_ENTITY_TO_FUNC(spore);
+//LINK_ENTITY_TO_FUNC(trigger_ctfgeneric);
+//LINK_ENTITY_TO_FUNC(trigger_geneworm_hit);
+//LINK_ENTITY_TO_FUNC(trigger_kill_nogib);
+//LINK_ENTITY_TO_FUNC(trigger_playerfreeze);
+//LINK_ENTITY_TO_FUNC(trigger_xen_return);
+//LINK_ENTITY_TO_FUNC(weapon_displacer);
+//LINK_ENTITY_TO_FUNC(weapon_eagle);
+//LINK_ENTITY_TO_FUNC(weapon_grapple);
+//LINK_ENTITY_TO_FUNC(weapon_penguin);
+//LINK_ENTITY_TO_FUNC(weapon_pipewrench);
+//LINK_ENTITY_TO_FUNC(weapon_shockrifle);
+//LINK_ENTITY_TO_FUNC(weapon_shockroach);
+//LINK_ENTITY_TO_FUNC(weapon_sniperrifle);
+//LINK_ENTITY_TO_FUNC(weapon_sporelauncher);
+//
+//// entities for FrontLineForce (1.0)
+//LINK_ENTITY_TO_FUNC(ammo_ak5);
+//LINK_ENTITY_TO_FUNC(ammo_beretta);
+//LINK_ENTITY_TO_FUNC(ammo_famas);
+//LINK_ENTITY_TO_FUNC(ammo_hk21);
+//LINK_ENTITY_TO_FUNC(ammo_m4);
+//LINK_ENTITY_TO_FUNC(ammo_mac10);
+//LINK_ENTITY_TO_FUNC(ammo_mk23);
+//LINK_ENTITY_TO_FUNC(ammo_mp5a2);
+//LINK_ENTITY_TO_FUNC(ammo_mp5sd);
+//LINK_ENTITY_TO_FUNC(ammo_msg90);
+//LINK_ENTITY_TO_FUNC(ammo_spas12);
+//LINK_ENTITY_TO_FUNC(ammo_ump45);
+//LINK_ENTITY_TO_FUNC(capture_point);
+//LINK_ENTITY_TO_FUNC(info_frontline);
+//LINK_ENTITY_TO_FUNC(info_player_attacker);
+//LINK_ENTITY_TO_FUNC(info_player_defender);
+//LINK_ENTITY_TO_FUNC(info_player_observer);
+//LINK_ENTITY_TO_FUNC(weapon_ak5);
+//LINK_ENTITY_TO_FUNC(weapon_beretta);
+//LINK_ENTITY_TO_FUNC(weapon_famas);
+//LINK_ENTITY_TO_FUNC(weapon_hk21);
+//LINK_ENTITY_TO_FUNC(weapon_m4);
+//LINK_ENTITY_TO_FUNC(weapon_mk23);
+//LINK_ENTITY_TO_FUNC(weapon_mp5a2);
+//LINK_ENTITY_TO_FUNC(weapon_mp5sd);
+//LINK_ENTITY_TO_FUNC(weapon_msg90);
+//LINK_ENTITY_TO_FUNC(weapon_spas12);
+
+// entities for Natural Selection
+LINK_ENTITY_TO_FUNC(info_team_start);
+LINK_ENTITY_TO_FUNC(info_spectate);
+LINK_ENTITY_TO_FUNC(info_join_team);
+LINK_ENTITY_TO_FUNC(info_leave_game);
+LINK_ENTITY_TO_FUNC(info_join_autoassign);
+LINK_ENTITY_TO_FUNC(info_mapinfo);
+LINK_ENTITY_TO_FUNC(info_gameplay);
+
+LINK_ENTITY_TO_FUNC(env_fog);
+LINK_ENTITY_TO_FUNC(env_gamma);
+LINK_ENTITY_TO_FUNC(env_particles);
+LINK_ENTITY_TO_FUNC(env_particles_custom);
+
+LINK_ENTITY_TO_FUNC(func_weldable);
+LINK_ENTITY_TO_FUNC(func_seethrough);
+LINK_ENTITY_TO_FUNC(func_seethroughdoor);
+//LINK_ENTITY_TO_FUNC(func_waypoint);
+LINK_ENTITY_TO_FUNC(func_nobuild);
+LINK_ENTITY_TO_FUNC(func_resource);
+
+LINK_ENTITY_TO_FUNC(target_mp3audio);
+LINK_ENTITY_TO_FUNC(trigger_random);
+LINK_ENTITY_TO_FUNC(trigger_presence);
+LINK_ENTITY_TO_FUNC(trigger_script);
+LINK_ENTITY_TO_FUNC(info_location);
+
+LINK_ENTITY_TO_FUNC(team_hive);
+LINK_ENTITY_TO_FUNC(team_command);
+LINK_ENTITY_TO_FUNC(team_breach);
+LINK_ENTITY_TO_FUNC(team_egg);
+LINK_ENTITY_TO_FUNC(team_webstrand);
+
+// Marine weapons and equipment
+LINK_ENTITY_TO_FUNC(weapon_knife);
+LINK_ENTITY_TO_FUNC(weapon_grenade);
+LINK_ENTITY_TO_FUNC(weapon_machinegun);
+LINK_ENTITY_TO_FUNC(weapon_pistol);
+LINK_ENTITY_TO_FUNC(weapon_flamegun);
+LINK_ENTITY_TO_FUNC(weapon_heavymachinegun);
+LINK_ENTITY_TO_FUNC(weapon_grenadegun);
+LINK_ENTITY_TO_FUNC(weapon_shotgun);
+LINK_ENTITY_TO_FUNC(weapon_nukegun);
+LINK_ENTITY_TO_FUNC(weapon_mine);
+LINK_ENTITY_TO_FUNC(weapon_welder);
+
+LINK_ENTITY_TO_FUNC(item_genericammo);
+LINK_ENTITY_TO_FUNC(item_mine);
+LINK_ENTITY_TO_FUNC(item_health);
+LINK_ENTITY_TO_FUNC(item_catalyst);
+LINK_ENTITY_TO_FUNC(item_heavyarmor);
+LINK_ENTITY_TO_FUNC(item_jetpack);
+
+LINK_ENTITY_TO_FUNC(scan);
+LINK_ENTITY_TO_FUNC(turret);
+LINK_ENTITY_TO_FUNC(phasegate);
+LINK_ENTITY_TO_FUNC(siegeturret);
+LINK_ENTITY_TO_FUNC(nuke);
+
+// Marine buildings
+LINK_ENTITY_TO_FUNC(resourcetower);
+LINK_ENTITY_TO_FUNC(team_infportal);
+LINK_ENTITY_TO_FUNC(team_turretfactory);
+LINK_ENTITY_TO_FUNC(team_advturretfactory);
+LINK_ENTITY_TO_FUNC(team_armory);
+LINK_ENTITY_TO_FUNC(team_advarmory);
+LINK_ENTITY_TO_FUNC(team_armslab);
+LINK_ENTITY_TO_FUNC(team_prototypelab);
+LINK_ENTITY_TO_FUNC(team_observatory);
+LINK_ENTITY_TO_FUNC(team_chemlab);
+LINK_ENTITY_TO_FUNC(team_medlab);
+LINK_ENTITY_TO_FUNC(team_nukeplant);
+
+// Alien buildings
+LINK_ENTITY_TO_FUNC(alienresourcetower);
+LINK_ENTITY_TO_FUNC(defensechamber);
+LINK_ENTITY_TO_FUNC(spikeprojectile);
+LINK_ENTITY_TO_FUNC(offensechamber);
+LINK_ENTITY_TO_FUNC(sensorychamber);
+LINK_ENTITY_TO_FUNC(movementchamber);
+
+// Alien abilities that are technically weapons (along with their projectiles)
+LINK_ENTITY_TO_FUNC(weapon_acidrocket);
+LINK_ENTITY_TO_FUNC(weapon_acidrocketgun);
+LINK_ENTITY_TO_FUNC(weapon_bilebomb);
+LINK_ENTITY_TO_FUNC(weapon_bilebombgun);
+LINK_ENTITY_TO_FUNC(weapon_bitegun);
+LINK_ENTITY_TO_FUNC(weapon_blink);
+LINK_ENTITY_TO_FUNC(weapon_claws);
+LINK_ENTITY_TO_FUNC(weapon_devour);
+LINK_ENTITY_TO_FUNC(weapon_divinewind);
+LINK_ENTITY_TO_FUNC(weapon_healingspray);
+LINK_ENTITY_TO_FUNC(weapon_metabolize);
+LINK_ENTITY_TO_FUNC(weapon_parasite);
+LINK_ENTITY_TO_FUNC(weapon_primalscream);
+LINK_ENTITY_TO_FUNC(weapon_spikegun);
+LINK_ENTITY_TO_FUNC(weapon_bite2gun);
+LINK_ENTITY_TO_FUNC(weapon_spit);
+LINK_ENTITY_TO_FUNC(weapon_spore);
+LINK_ENTITY_TO_FUNC(weapon_stomp);
+LINK_ENTITY_TO_FUNC(weapon_swipe);
+LINK_ENTITY_TO_FUNC(weapon_umbra);
+LINK_ENTITY_TO_FUNC(weapon_webspinner);
+
+// Alien abilities
+LINK_ENTITY_TO_FUNC(weapon_leap);
+LINK_ENTITY_TO_FUNC(weapon_charge);
+
+LINK_ENTITY_TO_FUNC(webgunprojectile);
+LINK_ENTITY_TO_FUNC(spitgunprojectile);
+LINK_ENTITY_TO_FUNC(stompprojectile);
+LINK_ENTITY_TO_FUNC(sporegunprojectile);
+LINK_ENTITY_TO_FUNC(umbracloud);
+LINK_ENTITY_TO_FUNC(umbraprojectile);
+
diff --git a/main/source/HPB_bot/dlls/make b/main/source/HPB_bot/dlls/make
index 436504db..0ab6a8c7 100644
--- a/main/source/HPB_bot/dlls/make
+++ b/main/source/HPB_bot/dlls/make
@@ -1,44 +1,44 @@
-#
-# HPB_bot makefile for Linux
-#
-# created: 12/16/2000 botman (botman@mailandnews.com)
-#
-
-# the following specifies the path to your MOD...
-MOD_DIR = ../
-
-CPP = egcs
-
-BASEFLAGS = -Dstricmp=strcasecmp -Dstrcmpi=strcasecmp -DAVH_SERVER -DLINUX
-
-CFLAGS=$(BASE_CFLAGS) -w -m486 -O2 -ffast-math -funroll-loops \
- -fomit-frame-pointer -fexpensive-optimizations -malign-loops=2 \
- -malign-jumps=2 -malign-functions=2
-
-INCLUDEDIRS=-I. -I../../engine -I../../common -I../../mod -I../../game_shared -I../../lua/include -I../../pm_shared -I../.. -I../../dlls
-
-LDFLAGS=-lm -lstdc++
-#SHLIBCFLAGS=-fPIC
-SHLIBLDFLAGS=-shared -static
-
-#CPPFLAGS = ${BASEFLAGS} -m486 -O2 -w -I../engine -I../common -I../pm_shared
-CPPFLAGS = ${BASEFLAGS} -m486 -w -I../engine -I../../common -I../../pm_shared
-
-OBJ = bot.o bot_client.o bot_combat.o bot_navigate.o bot_start.o dll.o engine.o h_export.o linkfunc.o util.o waypoint.o
-
-#${CPP} $(SHLIBLDFLAGS) $(LDFLAGS) -o $@ ${OBJ} -ldl
-
-HPB_bot_i386.so: ${OBJ}
- ${CPP} $(CFLAGS) $(SHLIBLDFLAGS) $(LDFLAGS) -o $@ ${OBJ}
- cp -f HPB_bot_i386.so ${MOD_DIR}/dlls
-
-clean:
- -rm -f *.o
- -rm -f *.so
-
-%.o: %.cpp
- ${CPP} ${CPPFLAGS} $(INCLUDEDIRS) -c $< -o $@
-
-%.o: %.c
- ${CPP} ${CPPFLAGS} $(INCLUDEDIRS) -c $< -o $@
-
+#
+# HPB_bot makefile for Linux
+#
+# created: 12/16/2000 botman (botman@mailandnews.com)
+#
+
+# the following specifies the path to your MOD...
+MOD_DIR = ../
+
+CPP = egcs
+
+BASEFLAGS = -Dstricmp=strcasecmp -Dstrcmpi=strcasecmp -DAVH_SERVER -DLINUX
+
+CFLAGS=$(BASE_CFLAGS) -w -m486 -O2 -ffast-math -funroll-loops \
+ -fomit-frame-pointer -fexpensive-optimizations -malign-loops=2 \
+ -malign-jumps=2 -malign-functions=2
+
+INCLUDEDIRS=-I. -I../../engine -I../../common -I../../mod -I../../game_shared -I../../lua/include -I../../pm_shared -I../.. -I../../dlls
+
+LDFLAGS=-lm -lstdc++
+#SHLIBCFLAGS=-fPIC
+SHLIBLDFLAGS=-shared -static
+
+#CPPFLAGS = ${BASEFLAGS} -m486 -O2 -w -I../engine -I../common -I../pm_shared
+CPPFLAGS = ${BASEFLAGS} -m486 -w -I../engine -I../../common -I../../pm_shared
+
+OBJ = bot.o bot_client.o bot_combat.o bot_navigate.o bot_start.o dll.o engine.o h_export.o linkfunc.o util.o waypoint.o
+
+#${CPP} $(SHLIBLDFLAGS) $(LDFLAGS) -o $@ ${OBJ} -ldl
+
+HPB_bot_i386.so: ${OBJ}
+ ${CPP} $(CFLAGS) $(SHLIBLDFLAGS) $(LDFLAGS) -o $@ ${OBJ}
+ cp -f HPB_bot_i386.so ${MOD_DIR}/dlls
+
+clean:
+ -rm -f *.o
+ -rm -f *.so
+
+%.o: %.cpp
+ ${CPP} ${CPPFLAGS} $(INCLUDEDIRS) -c $< -o $@
+
+%.o: %.c
+ ${CPP} ${CPPFLAGS} $(INCLUDEDIRS) -c $< -o $@
+
diff --git a/main/source/HPB_bot/dlls/util.cpp b/main/source/HPB_bot/dlls/util.cpp
index c6a034af..d7de2028 100644
--- a/main/source/HPB_bot/dlls/util.cpp
+++ b/main/source/HPB_bot/dlls/util.cpp
@@ -1,661 +1,661 @@
-/***
-*
-* Copyright (c) 1999, Valve LLC. All rights reserved.
-*
-* This product contains software technology licensed from Id
-* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
-* All Rights Reserved.
-*
-* Use, distribution, and modification of this source code and/or resulting
-* object code is restricted to non-commercial enhancements to products from
-* Valve LLC. All other use, distribution, or modification is prohibited
-* without written permission from Valve LLC.
-*
-****/
-
-//
-// HPB_bot - botman's High Ping Bastard bot
-//
-// (http://planethalflife.com/botman/)
-//
-// util.cpp
-//
-
-#include "dlls/extdll.h"
-#include "dlls/util.h"
-#include "HPB_bot/engine/engine.h"
-#include "dlls/cbase.h"
-#include "dlls/player.h"
-
-#include "bot.h"
-#include "bot_func.h"
-
-
-extern int mod_id;
-extern bot_t bots[32];
-extern edict_t *pent_info_ctfdetect;
-extern char team_names[MAX_TEAMS][MAX_TEAMNAME_LENGTH];
-extern int num_teams;
-
-int gmsgTextMsg = 0;
-int gmsgSayText = 0;
-int gmsgShowMenu = 0;
-
-
-Vector UTIL_VecToAngles( const Vector &vec )
-{
- float rgflVecOut[3];
- VEC_TO_ANGLES(vec, rgflVecOut);
- return Vector(rgflVecOut);
-}
-
-
-// Overloaded to add IGNORE_GLASS
-void UTIL_TraceLine( const Vector &vecStart, const Vector &vecEnd, IGNORE_MONSTERS igmon, IGNORE_GLASS ignoreGlass, edict_t *pentIgnore, TraceResult *ptr )
-{
- TRACE_LINE( vecStart, vecEnd, (igmon == ignore_monsters ? TRUE : FALSE) | (ignoreGlass?0x100:0), pentIgnore, ptr );
-}
-
-
-void UTIL_TraceLine( const Vector &vecStart, const Vector &vecEnd, IGNORE_MONSTERS igmon, edict_t *pentIgnore, TraceResult *ptr )
-{
- TRACE_LINE( vecStart, vecEnd, (igmon == ignore_monsters ? TRUE : FALSE), pentIgnore, ptr );
-}
-
-
-void UTIL_MakeVectors( const Vector &vecAngles )
-{
- MAKE_VECTORS( vecAngles );
-}
-
-
-edict_t *UTIL_FindEntityInSphere( edict_t *pentStart, const Vector &vecCenter, float flRadius )
-{
- edict_t *pentEntity;
-
- pentEntity = FIND_ENTITY_IN_SPHERE( pentStart, vecCenter, flRadius);
-
- if (!FNullEnt(pentEntity))
- return pentEntity;
-
- return NULL;
-}
-
-
-edict_t *UTIL_FindEntityByString( edict_t *pentStart, const char *szKeyword, const char *szValue )
-{
- edict_t *pentEntity;
-
- pentEntity = FIND_ENTITY_BY_STRING( pentStart, szKeyword, szValue );
-
- if (!FNullEnt(pentEntity))
- return pentEntity;
- return NULL;
-}
-
-edict_t *UTIL_FindEntityByClassname( edict_t *pentStart, const char *szName )
-{
- return UTIL_FindEntityByString( pentStart, "classname", szName );
-}
-
-edict_t *UTIL_FindEntityByTargetname( edict_t *pentStart, const char *szName )
-{
- return UTIL_FindEntityByString( pentStart, "targetname", szName );
-}
-
-
-int UTIL_PointContents( const Vector &vec )
-{
- return POINT_CONTENTS(vec);
-}
-
-
-void UTIL_SetSize( entvars_t *pev, const Vector &vecMin, const Vector &vecMax )
-{
- SET_SIZE( ENT(pev), vecMin, vecMax );
-}
-
-
-void UTIL_SetOrigin( entvars_t *pev, const Vector &vecOrigin )
-{
- SET_ORIGIN(ENT(pev), vecOrigin );
-}
-
-
-void ClientPrint( edict_t *pEntity, int msg_dest, const char *msg_name)
-{
-// if (gmsgTextMsg == 0)
-// gmsgTextMsg = REG_USER_MSG( "TextMsg", -1 );
-//
-// pfnMessageBegin( MSG_ONE, gmsgTextMsg, NULL, pEntity );
-//
-// pfnWriteByte( msg_dest );
-// pfnWriteString( msg_name );
-// pfnMessageEnd();
-}
-
-void UTIL_SayText( const char *pText, edict_t *pEdict )
-{
-// if (gmsgSayText == 0)
-// gmsgSayText = REG_USER_MSG( "SayText", -1 );
-//
-// pfnMessageBegin( MSG_ONE, gmsgSayText, NULL, pEdict );
-// pfnWriteByte( ENTINDEX(pEdict) );
-// if (mod_id == FRONTLINE_DLL)
-// pfnWriteShort(0);
-// pfnWriteString( pText );
-// pfnMessageEnd();
-}
-
-
-void UTIL_HostSay( edict_t *pEntity, int teamonly, char *message )
-{
-// int j;
-// char text[128];
-// char *pc;
-// int sender_team, player_team;
-// edict_t *client;
-//
-// // make sure the text has content
-// for ( pc = message; pc != NULL && *pc != 0; pc++ )
-// {
-// if ( isprint( *pc ) && !isspace( *pc ) )
-// {
-// pc = NULL; // we've found an alphanumeric character, so text is valid
-// break;
-// }
-// }
-//
-// if ( pc != NULL )
-// return; // no character found, so say nothing
-//
-// // turn on color set 2 (color on, no sound)
-// if ( teamonly )
-// sprintf( text, "%c(TEAM) %s: ", 2, STRING( pEntity->v.netname ) );
-// else
-// sprintf( text, "%c%s: ", 2, STRING( pEntity->v.netname ) );
-//
-// j = sizeof(text) - 2 - strlen(text); // -2 for /n and null terminator
-// if ( (int)strlen(message) > j )
-// message[j] = 0;
-//
-// strcat( text, message );
-// strcat( text, "\n" );
-//
-// // loop through all players
-// // Start with the first player.
-// // This may return the world in single player if the client types something between levels or during spawn
-// // so check it, or it will infinite loop
-//
-// if (gmsgSayText == 0)
-// gmsgSayText = REG_USER_MSG( "SayText", -1 );
-//
-// sender_team = UTIL_GetTeam(pEntity);
-//
-// client = NULL;
-// while ( ((client = UTIL_FindEntityByClassname( client, "player" )) != NULL) &&
-// (!FNullEnt(client)) )
-// {
-// if ( client == pEntity ) // skip sender of message
-// continue;
-//
-// player_team = UTIL_GetTeam(client);
-//
-// if ( teamonly && (sender_team != player_team) )
-// continue;
-//
-// pfnMessageBegin( MSG_ONE, gmsgSayText, NULL, client );
-// pfnWriteByte( ENTINDEX(pEntity) );
-// if (mod_id == FRONTLINE_DLL)
-// pfnWriteShort(0);
-// pfnWriteString( text );
-// pfnMessageEnd();
-// }
-//
-// // print to the sending client
-// pfnMessageBegin( MSG_ONE, gmsgSayText, NULL, pEntity );
-// pfnWriteByte( ENTINDEX(pEntity) );
-// if (mod_id == FRONTLINE_DLL)
-// pfnWriteShort(0);
-// pfnWriteString( text );
-// pfnMessageEnd();
-//
-// // echo to server console
-// g_engfuncs.pfnServerPrint( text );
-}
-
-
-#ifdef DEBUG
-edict_t *DBG_EntOfVars( const entvars_t *pev )
-{
- if (pev->pContainingEntity != NULL)
- return pev->pContainingEntity;
- ALERT(at_console, "entvars_t pContainingEntity is NULL, calling into engine");
- edict_t* pent = (*g_engfuncs.pfnFindEntityByVars)((entvars_t*)pev);
- if (pent == NULL)
- ALERT(at_console, "DAMN! Even the engine couldn't FindEntityByVars!");
- ((entvars_t *)pev)->pContainingEntity = pent;
- return pent;
-}
-#endif //DEBUG
-
-
-// return team number 0 through 3 based what MOD uses for team numbers
-int UTIL_GetTeam(edict_t *pEntity)
-{
- if (mod_id == TFC_DLL)
- {
- return pEntity->v.team - 1; // TFC teams are 1-4 based
- }
- else if (mod_id == CSTRIKE_DLL)
- {
- char *infobuffer;
- char model_name[32];
-
- infobuffer = (*g_engfuncs.pfnGetInfoKeyBuffer)( pEntity );
- strcpy(model_name, (g_engfuncs.pfnInfoKeyValue(infobuffer, "model")));
-
- if ((strcmp(model_name, "terror") == 0) || // Phoenix Connektion
- (strcmp(model_name, "arab") == 0) || // old L337 Krew
- (strcmp(model_name, "leet") == 0) || // L337 Krew
- (strcmp(model_name, "artic") == 0) || // Artic Avenger
- (strcmp(model_name, "guerilla") == 0)) // Gorilla Warfare
- {
- return 0;
- }
- else if ((strcmp(model_name, "urban") == 0) || // Seal Team 6
- (strcmp(model_name, "gsg9") == 0) || // German GSG-9
- (strcmp(model_name, "sas") == 0) || // UK SAS
- (strcmp(model_name, "gign") == 0) || // French GIGN
- (strcmp(model_name, "vip") == 0)) // VIP
- {
- return 1;
- }
-
- return 0; // return zero if team is unknown
- }
- else if ((mod_id == GEARBOX_DLL) && (pent_info_ctfdetect != NULL))
- {
- // OpFor CTF map...
-
- char *infobuffer;
- char model_name[32];
-
- infobuffer = (*g_engfuncs.pfnGetInfoKeyBuffer)( pEntity );
- strcpy(model_name, (g_engfuncs.pfnInfoKeyValue(infobuffer, "model")));
-
- if ((strcmp(model_name, "ctf_barney") == 0) ||
- (strcmp(model_name, "cl_suit") == 0) ||
- (strcmp(model_name, "ctf_gina") == 0) ||
- (strcmp(model_name, "ctf_gordon") == 0) ||
- (strcmp(model_name, "otis") == 0) ||
- (strcmp(model_name, "ctf_scientist") == 0))
- {
- return 0;
- }
- else if ((strcmp(model_name, "beret") == 0) ||
- (strcmp(model_name, "drill") == 0) ||
- (strcmp(model_name, "grunt") == 0) ||
- (strcmp(model_name, "recruit") == 0) ||
- (strcmp(model_name, "shephard") == 0) ||
- (strcmp(model_name, "tower") == 0))
- {
- return 1;
- }
-
- return 0; // return zero if team is unknown
- }
- else if (mod_id == FRONTLINE_DLL)
- {
- return pEntity->v.team - 1; // Front Line Force teams are 1-4 based
- }
- else if(mod_id == AVH_DLL)
- {
- return pEntity->v.team;
- }
- else // must be HL or OpFor deathmatch...
- {
- char *infobuffer;
- char model_name[32];
-
- if (team_names[0][0] == 0)
- {
- char *pName;
- char teamlist[MAX_TEAMS*MAX_TEAMNAME_LENGTH];
- int i;
-
- num_teams = 0;
- strcpy(teamlist, CVAR_GET_STRING("mp_teamlist"));
- pName = teamlist;
- pName = strtok(pName, ";");
-
- while (pName != NULL && *pName)
- {
- // check that team isn't defined twice
- for (i=0; i < num_teams; i++)
- if (strcmp(pName, team_names[i]) == 0)
- break;
- if (i == num_teams)
- {
- strcpy(team_names[num_teams], pName);
- num_teams++;
- }
- pName = strtok(NULL, ";");
- }
- }
-
- infobuffer = (*g_engfuncs.pfnGetInfoKeyBuffer)( pEntity );
- strcpy(model_name, (g_engfuncs.pfnInfoKeyValue(infobuffer, "model")));
-
- for (int index=0; index < num_teams; index++)
- {
- if (strcmp(model_name, team_names[index]) == 0)
- return index;
- }
-
- return 0;
- }
-}
-
-
-// return class number 0 through N
-int UTIL_GetClass(edict_t *pEntity)
-{
- char *infobuffer;
- char model_name[32];
-
- infobuffer = (*g_engfuncs.pfnGetInfoKeyBuffer)( pEntity );
- strcpy(model_name, (g_engfuncs.pfnInfoKeyValue(infobuffer, "model")));
-
- if (mod_id == FRONTLINE_DLL)
- {
- if ((strcmp(model_name, "natorecon") == 0) ||
- (strcmp(model_name, "axisrecon") == 0))
- {
- return 0; // recon
- }
- else if ((strcmp(model_name, "natoassault") == 0) ||
- (strcmp(model_name, "axisassault") == 0))
- {
- return 1; // assault
- }
- else if ((strcmp(model_name, "natosupport") == 0) ||
- (strcmp(model_name, "axissupport") == 0))
- {
- return 2; // support
- }
- }
-
- return 0;
-}
-
-
-int UTIL_GetBotIndex(edict_t *pEdict)
-{
- int index;
-
- for (index=0; index < 32; index++)
- {
- if (bots[index].pEdict == pEdict)
- {
- return index;
- }
- }
-
- return -1; // return -1 if edict is not a bot
-}
-
-
-bot_t *UTIL_GetBotPointer(edict_t *pEdict)
-{
- int index;
-
- for (index=0; index < 32; index++)
- {
- if (bots[index].pEdict == pEdict)
- {
- break;
- }
- }
-
- if (index < 32)
- return (&bots[index]);
-
- return NULL; // return NULL if edict is not a bot
-}
-
-
-bool IsAlive(edict_t *pEdict)
-{
- return ((pEdict->v.deadflag == DEAD_NO) &&
- (pEdict->v.health > 0) && !(pEdict->v.flags & FL_NOTARGET));
-}
-
-
-bool FInViewCone(Vector *pOrigin, edict_t *pEdict)
-{
- Vector2D vec2LOS;
- float flDot;
-
- UTIL_MakeVectors ( pEdict->v.angles );
-
- vec2LOS = ( *pOrigin - pEdict->v.origin ).Make2D();
- vec2LOS = vec2LOS.Normalize();
-
- flDot = DotProduct (vec2LOS , gpGlobals->v_forward.Make2D() );
-
- if ( flDot > 0.50 ) // 60 degree field of view
- {
- return TRUE;
- }
- else
- {
- return FALSE;
- }
-}
-
-
-bool FVisible( const Vector &vecOrigin, edict_t *pEdict )
-{
- TraceResult tr;
- Vector vecLookerOrigin;
-
- // look through caller's eyes
- vecLookerOrigin = pEdict->v.origin + pEdict->v.view_ofs;
-
- int bInWater = (UTIL_PointContents (vecOrigin) == CONTENTS_WATER);
- int bLookerInWater = (UTIL_PointContents (vecLookerOrigin) == CONTENTS_WATER);
-
- // don't look through water
- if (bInWater != bLookerInWater)
- return FALSE;
-
- UTIL_TraceLine(vecLookerOrigin, vecOrigin, ignore_monsters, ignore_glass, pEdict, &tr);
-
- if (tr.flFraction != 1.0)
- {
- return FALSE; // Line of sight is not established
- }
- else
- {
- return TRUE; // line of sight is valid.
- }
-}
-
-
-Vector GetGunPosition(edict_t *pEdict)
-{
- return (pEdict->v.origin + pEdict->v.view_ofs);
-}
-
-
-void UTIL_SelectItem(edict_t *pEdict, char *item_name)
-{
- FakeClientCommand(pEdict, item_name, NULL, NULL);
-}
-
-
-Vector VecBModelOrigin(edict_t *pEdict)
-{
- return pEdict->v.absmin + (pEdict->v.size * 0.5);
-}
-
-
-bool UpdateSounds(edict_t *pEdict, edict_t *pPlayer)
-{
- float distance;
- static bool check_footstep_sounds = TRUE;
- static float footstep_sounds_on;
- float sensitivity = 1.0;
- float volume;
-
- // update sounds made by this player, alert bots if they are nearby...
-
- if (check_footstep_sounds)
- {
- check_footstep_sounds = FALSE;
- footstep_sounds_on = CVAR_GET_FLOAT("mp_footsteps");
- }
-
- if (footstep_sounds_on > 0.0)
- {
- CBasePlayer* thePlayer = (CBasePlayer*)CBaseEntity::Instance(pPlayer);
-
- // check if this player is moving fast enough to make sounds...
- if (pPlayer->v.velocity.Length2D() > thePlayer->GetMaxWalkSpeed())
- {
- volume = 500.0; // volume of sound being made (just pick something)
-
- Vector v_sound = pPlayer->v.origin - pEdict->v.origin;
-
- distance = v_sound.Length();
-
- // is the bot close enough to hear this sound?
- if (distance < (volume * sensitivity))
- {
- Vector bot_angles = UTIL_VecToAngles( v_sound );
-
- pEdict->v.ideal_yaw = bot_angles.y;
-
- BotFixIdealYaw(pEdict);
-
- return TRUE;
- }
- }
- }
-
- return FALSE;
-}
-
-
-void UTIL_ShowMenu( edict_t *pEdict, int slots, int displaytime, bool needmore, char *pText )
-{
-// if (gmsgShowMenu == 0)
-// gmsgShowMenu = REG_USER_MSG( "ShowMenu", -1 );
-//
-// pfnMessageBegin( MSG_ONE, gmsgShowMenu, NULL, pEdict );
-//
-// pfnWriteShort( slots );
-// pfnWriteChar( displaytime );
-// pfnWriteByte( needmore );
-// pfnWriteString( pText );
-//
-// pfnMessageEnd();
-}
-
-void UTIL_BuildFileName(char *filename, char *arg1, char *arg2)
-{
-
- if (mod_id == VALVE_DLL)
-#ifndef __linux__
- strcpy(filename, "valve\\");
-#else
- strcpy(filename, "valve/");
-#endif
-
- else if (mod_id == TFC_DLL)
-#ifndef __linux__
- strcpy(filename, "tfc\\");
-#else
- strcpy(filename, "tfc/");
-#endif
-
- else if (mod_id == CSTRIKE_DLL)
-#ifndef __linux__
- strcpy(filename, "cstrike\\");
-#else
- strcpy(filename, "cstrike/");
-#endif
-
- else if (mod_id == GEARBOX_DLL)
-#ifndef __linux__
- strcpy(filename, "gearbox\\");
-#else
- strcpy(filename, "gearbox/");
-#endif
-
- else if (mod_id == FRONTLINE_DLL)
-#ifndef __linux__
- strcpy(filename, "frontline\\");
-#else
- strcpy(filename, "frontline/");
-#endif
-
- else if (mod_id == AVH_DLL)
- {
- string filenameString = string(getModDirectory());
-#ifndef __linux__
- filenameString += "\\";
-#else
- filenameString += '/';
-#endif
- strcpy(filename,filenameString.c_str());
- }
- else
- {
- filename[0] = 0;
- return;
- }
-
- if ((arg1) && (*arg1) && (arg2) && (*arg2))
- {
- strcat(filename, arg1);
-
-#ifndef __linux__
- strcat(filename, "\\");
-#else
- strcat(filename, "/");
-#endif
-
- strcat(filename, arg2);
- }
- else if ((arg1) && (*arg1))
- {
- strcat(filename, arg1);
- }
-
- printf("UTIL_BuildFileName:");
- printf(filename);
- printf("\n");
-}
-
-//=========================================================
-// UTIL_LogPrintf - Prints a logged message to console.
-// Preceded by LOG: ( timestamp ) < message >
-//=========================================================
-void UTIL_LogPrintf( char *fmt, ... )
-{
- va_list argptr;
- static char string[1024];
-
- va_start ( argptr, fmt );
- vsprintf ( string, fmt, argptr );
- va_end ( argptr );
-
- // Print to server console
- printf("UTIL_LogPrintf:");
- printf(string);
- printf("\n");
- ALERT( at_logged, "%s", string );
-}
-
+/***
+*
+* Copyright (c) 1999, Valve LLC. All rights reserved.
+*
+* This product contains software technology licensed from Id
+* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
+* All Rights Reserved.
+*
+* Use, distribution, and modification of this source code and/or resulting
+* object code is restricted to non-commercial enhancements to products from
+* Valve LLC. All other use, distribution, or modification is prohibited
+* without written permission from Valve LLC.
+*
+****/
+
+//
+// HPB_bot - botman's High Ping Bastard bot
+//
+// (http://planethalflife.com/botman/)
+//
+// util.cpp
+//
+
+#include "dlls/extdll.h"
+#include "dlls/util.h"
+#include "HPB_bot/engine/engine.h"
+#include "dlls/cbase.h"
+#include "dlls/player.h"
+
+#include "bot.h"
+#include "bot_func.h"
+
+
+extern int mod_id;
+extern bot_t bots[32];
+extern edict_t *pent_info_ctfdetect;
+extern char team_names[MAX_TEAMS][MAX_TEAMNAME_LENGTH];
+extern int num_teams;
+
+int gmsgTextMsg = 0;
+int gmsgSayText = 0;
+int gmsgShowMenu = 0;
+
+
+Vector UTIL_VecToAngles( const Vector &vec )
+{
+ float rgflVecOut[3];
+ VEC_TO_ANGLES(vec, rgflVecOut);
+ return Vector(rgflVecOut);
+}
+
+
+// Overloaded to add IGNORE_GLASS
+void UTIL_TraceLine( const Vector &vecStart, const Vector &vecEnd, IGNORE_MONSTERS igmon, IGNORE_GLASS ignoreGlass, edict_t *pentIgnore, TraceResult *ptr )
+{
+ TRACE_LINE( vecStart, vecEnd, (igmon == ignore_monsters ? TRUE : FALSE) | (ignoreGlass?0x100:0), pentIgnore, ptr );
+}
+
+
+void UTIL_TraceLine( const Vector &vecStart, const Vector &vecEnd, IGNORE_MONSTERS igmon, edict_t *pentIgnore, TraceResult *ptr )
+{
+ TRACE_LINE( vecStart, vecEnd, (igmon == ignore_monsters ? TRUE : FALSE), pentIgnore, ptr );
+}
+
+
+void UTIL_MakeVectors( const Vector &vecAngles )
+{
+ MAKE_VECTORS( vecAngles );
+}
+
+
+edict_t *UTIL_FindEntityInSphere( edict_t *pentStart, const Vector &vecCenter, float flRadius )
+{
+ edict_t *pentEntity;
+
+ pentEntity = FIND_ENTITY_IN_SPHERE( pentStart, vecCenter, flRadius);
+
+ if (!FNullEnt(pentEntity))
+ return pentEntity;
+
+ return NULL;
+}
+
+
+edict_t *UTIL_FindEntityByString( edict_t *pentStart, const char *szKeyword, const char *szValue )
+{
+ edict_t *pentEntity;
+
+ pentEntity = FIND_ENTITY_BY_STRING( pentStart, szKeyword, szValue );
+
+ if (!FNullEnt(pentEntity))
+ return pentEntity;
+ return NULL;
+}
+
+edict_t *UTIL_FindEntityByClassname( edict_t *pentStart, const char *szName )
+{
+ return UTIL_FindEntityByString( pentStart, "classname", szName );
+}
+
+edict_t *UTIL_FindEntityByTargetname( edict_t *pentStart, const char *szName )
+{
+ return UTIL_FindEntityByString( pentStart, "targetname", szName );
+}
+
+
+int UTIL_PointContents( const Vector &vec )
+{
+ return POINT_CONTENTS(vec);
+}
+
+
+void UTIL_SetSize( entvars_t *pev, const Vector &vecMin, const Vector &vecMax )
+{
+ SET_SIZE( ENT(pev), vecMin, vecMax );
+}
+
+
+void UTIL_SetOrigin( entvars_t *pev, const Vector &vecOrigin )
+{
+ SET_ORIGIN(ENT(pev), vecOrigin );
+}
+
+
+void ClientPrint( edict_t *pEntity, int msg_dest, const char *msg_name)
+{
+// if (gmsgTextMsg == 0)
+// gmsgTextMsg = REG_USER_MSG( "TextMsg", -1 );
+//
+// pfnMessageBegin( MSG_ONE, gmsgTextMsg, NULL, pEntity );
+//
+// pfnWriteByte( msg_dest );
+// pfnWriteString( msg_name );
+// pfnMessageEnd();
+}
+
+void UTIL_SayText( const char *pText, edict_t *pEdict )
+{
+// if (gmsgSayText == 0)
+// gmsgSayText = REG_USER_MSG( "SayText", -1 );
+//
+// pfnMessageBegin( MSG_ONE, gmsgSayText, NULL, pEdict );
+// pfnWriteByte( ENTINDEX(pEdict) );
+// if (mod_id == FRONTLINE_DLL)
+// pfnWriteShort(0);
+// pfnWriteString( pText );
+// pfnMessageEnd();
+}
+
+
+void UTIL_HostSay( edict_t *pEntity, int teamonly, char *message )
+{
+// int j;
+// char text[128];
+// char *pc;
+// int sender_team, player_team;
+// edict_t *client;
+//
+// // make sure the text has content
+// for ( pc = message; pc != NULL && *pc != 0; pc++ )
+// {
+// if ( isprint( *pc ) && !isspace( *pc ) )
+// {
+// pc = NULL; // we've found an alphanumeric character, so text is valid
+// break;
+// }
+// }
+//
+// if ( pc != NULL )
+// return; // no character found, so say nothing
+//
+// // turn on color set 2 (color on, no sound)
+// if ( teamonly )
+// sprintf( text, "%c(TEAM) %s: ", 2, STRING( pEntity->v.netname ) );
+// else
+// sprintf( text, "%c%s: ", 2, STRING( pEntity->v.netname ) );
+//
+// j = sizeof(text) - 2 - strlen(text); // -2 for /n and null terminator
+// if ( (int)strlen(message) > j )
+// message[j] = 0;
+//
+// strcat( text, message );
+// strcat( text, "\n" );
+//
+// // loop through all players
+// // Start with the first player.
+// // This may return the world in single player if the client types something between levels or during spawn
+// // so check it, or it will infinite loop
+//
+// if (gmsgSayText == 0)
+// gmsgSayText = REG_USER_MSG( "SayText", -1 );
+//
+// sender_team = UTIL_GetTeam(pEntity);
+//
+// client = NULL;
+// while ( ((client = UTIL_FindEntityByClassname( client, "player" )) != NULL) &&
+// (!FNullEnt(client)) )
+// {
+// if ( client == pEntity ) // skip sender of message
+// continue;
+//
+// player_team = UTIL_GetTeam(client);
+//
+// if ( teamonly && (sender_team != player_team) )
+// continue;
+//
+// pfnMessageBegin( MSG_ONE, gmsgSayText, NULL, client );
+// pfnWriteByte( ENTINDEX(pEntity) );
+// if (mod_id == FRONTLINE_DLL)
+// pfnWriteShort(0);
+// pfnWriteString( text );
+// pfnMessageEnd();
+// }
+//
+// // print to the sending client
+// pfnMessageBegin( MSG_ONE, gmsgSayText, NULL, pEntity );
+// pfnWriteByte( ENTINDEX(pEntity) );
+// if (mod_id == FRONTLINE_DLL)
+// pfnWriteShort(0);
+// pfnWriteString( text );
+// pfnMessageEnd();
+//
+// // echo to server console
+// g_engfuncs.pfnServerPrint( text );
+}
+
+
+#ifdef DEBUG
+edict_t *DBG_EntOfVars( const entvars_t *pev )
+{
+ if (pev->pContainingEntity != NULL)
+ return pev->pContainingEntity;
+ ALERT(at_console, "entvars_t pContainingEntity is NULL, calling into engine");
+ edict_t* pent = (*g_engfuncs.pfnFindEntityByVars)((entvars_t*)pev);
+ if (pent == NULL)
+ ALERT(at_console, "DAMN! Even the engine couldn't FindEntityByVars!");
+ ((entvars_t *)pev)->pContainingEntity = pent;
+ return pent;
+}
+#endif //DEBUG
+
+
+// return team number 0 through 3 based what MOD uses for team numbers
+int UTIL_GetTeam(edict_t *pEntity)
+{
+ if (mod_id == TFC_DLL)
+ {
+ return pEntity->v.team - 1; // TFC teams are 1-4 based
+ }
+ else if (mod_id == CSTRIKE_DLL)
+ {
+ char *infobuffer;
+ char model_name[32];
+
+ infobuffer = (*g_engfuncs.pfnGetInfoKeyBuffer)( pEntity );
+ strcpy(model_name, (g_engfuncs.pfnInfoKeyValue(infobuffer, "model")));
+
+ if ((strcmp(model_name, "terror") == 0) || // Phoenix Connektion
+ (strcmp(model_name, "arab") == 0) || // old L337 Krew
+ (strcmp(model_name, "leet") == 0) || // L337 Krew
+ (strcmp(model_name, "artic") == 0) || // Artic Avenger
+ (strcmp(model_name, "guerilla") == 0)) // Gorilla Warfare
+ {
+ return 0;
+ }
+ else if ((strcmp(model_name, "urban") == 0) || // Seal Team 6
+ (strcmp(model_name, "gsg9") == 0) || // German GSG-9
+ (strcmp(model_name, "sas") == 0) || // UK SAS
+ (strcmp(model_name, "gign") == 0) || // French GIGN
+ (strcmp(model_name, "vip") == 0)) // VIP
+ {
+ return 1;
+ }
+
+ return 0; // return zero if team is unknown
+ }
+ else if ((mod_id == GEARBOX_DLL) && (pent_info_ctfdetect != NULL))
+ {
+ // OpFor CTF map...
+
+ char *infobuffer;
+ char model_name[32];
+
+ infobuffer = (*g_engfuncs.pfnGetInfoKeyBuffer)( pEntity );
+ strcpy(model_name, (g_engfuncs.pfnInfoKeyValue(infobuffer, "model")));
+
+ if ((strcmp(model_name, "ctf_barney") == 0) ||
+ (strcmp(model_name, "cl_suit") == 0) ||
+ (strcmp(model_name, "ctf_gina") == 0) ||
+ (strcmp(model_name, "ctf_gordon") == 0) ||
+ (strcmp(model_name, "otis") == 0) ||
+ (strcmp(model_name, "ctf_scientist") == 0))
+ {
+ return 0;
+ }
+ else if ((strcmp(model_name, "beret") == 0) ||
+ (strcmp(model_name, "drill") == 0) ||
+ (strcmp(model_name, "grunt") == 0) ||
+ (strcmp(model_name, "recruit") == 0) ||
+ (strcmp(model_name, "shephard") == 0) ||
+ (strcmp(model_name, "tower") == 0))
+ {
+ return 1;
+ }
+
+ return 0; // return zero if team is unknown
+ }
+ else if (mod_id == FRONTLINE_DLL)
+ {
+ return pEntity->v.team - 1; // Front Line Force teams are 1-4 based
+ }
+ else if(mod_id == AVH_DLL)
+ {
+ return pEntity->v.team;
+ }
+ else // must be HL or OpFor deathmatch...
+ {
+ char *infobuffer;
+ char model_name[32];
+
+ if (team_names[0][0] == 0)
+ {
+ char *pName;
+ char teamlist[MAX_TEAMS*MAX_TEAMNAME_LENGTH];
+ int i;
+
+ num_teams = 0;
+ strcpy(teamlist, CVAR_GET_STRING("mp_teamlist"));
+ pName = teamlist;
+ pName = strtok(pName, ";");
+
+ while (pName != NULL && *pName)
+ {
+ // check that team isn't defined twice
+ for (i=0; i < num_teams; i++)
+ if (strcmp(pName, team_names[i]) == 0)
+ break;
+ if (i == num_teams)
+ {
+ strcpy(team_names[num_teams], pName);
+ num_teams++;
+ }
+ pName = strtok(NULL, ";");
+ }
+ }
+
+ infobuffer = (*g_engfuncs.pfnGetInfoKeyBuffer)( pEntity );
+ strcpy(model_name, (g_engfuncs.pfnInfoKeyValue(infobuffer, "model")));
+
+ for (int index=0; index < num_teams; index++)
+ {
+ if (strcmp(model_name, team_names[index]) == 0)
+ return index;
+ }
+
+ return 0;
+ }
+}
+
+
+// return class number 0 through N
+int UTIL_GetClass(edict_t *pEntity)
+{
+ char *infobuffer;
+ char model_name[32];
+
+ infobuffer = (*g_engfuncs.pfnGetInfoKeyBuffer)( pEntity );
+ strcpy(model_name, (g_engfuncs.pfnInfoKeyValue(infobuffer, "model")));
+
+ if (mod_id == FRONTLINE_DLL)
+ {
+ if ((strcmp(model_name, "natorecon") == 0) ||
+ (strcmp(model_name, "axisrecon") == 0))
+ {
+ return 0; // recon
+ }
+ else if ((strcmp(model_name, "natoassault") == 0) ||
+ (strcmp(model_name, "axisassault") == 0))
+ {
+ return 1; // assault
+ }
+ else if ((strcmp(model_name, "natosupport") == 0) ||
+ (strcmp(model_name, "axissupport") == 0))
+ {
+ return 2; // support
+ }
+ }
+
+ return 0;
+}
+
+
+int UTIL_GetBotIndex(edict_t *pEdict)
+{
+ int index;
+
+ for (index=0; index < 32; index++)
+ {
+ if (bots[index].pEdict == pEdict)
+ {
+ return index;
+ }
+ }
+
+ return -1; // return -1 if edict is not a bot
+}
+
+
+bot_t *UTIL_GetBotPointer(edict_t *pEdict)
+{
+ int index;
+
+ for (index=0; index < 32; index++)
+ {
+ if (bots[index].pEdict == pEdict)
+ {
+ break;
+ }
+ }
+
+ if (index < 32)
+ return (&bots[index]);
+
+ return NULL; // return NULL if edict is not a bot
+}
+
+
+bool IsAlive(edict_t *pEdict)
+{
+ return ((pEdict->v.deadflag == DEAD_NO) &&
+ (pEdict->v.health > 0) && !(pEdict->v.flags & FL_NOTARGET));
+}
+
+
+bool FInViewCone(Vector *pOrigin, edict_t *pEdict)
+{
+ Vector2D vec2LOS;
+ float flDot;
+
+ UTIL_MakeVectors ( pEdict->v.angles );
+
+ vec2LOS = ( *pOrigin - pEdict->v.origin ).Make2D();
+ vec2LOS = vec2LOS.Normalize();
+
+ flDot = DotProduct (vec2LOS , gpGlobals->v_forward.Make2D() );
+
+ if ( flDot > 0.50 ) // 60 degree field of view
+ {
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+
+bool FVisible( const Vector &vecOrigin, edict_t *pEdict )
+{
+ TraceResult tr;
+ Vector vecLookerOrigin;
+
+ // look through caller's eyes
+ vecLookerOrigin = pEdict->v.origin + pEdict->v.view_ofs;
+
+ int bInWater = (UTIL_PointContents (vecOrigin) == CONTENTS_WATER);
+ int bLookerInWater = (UTIL_PointContents (vecLookerOrigin) == CONTENTS_WATER);
+
+ // don't look through water
+ if (bInWater != bLookerInWater)
+ return FALSE;
+
+ UTIL_TraceLine(vecLookerOrigin, vecOrigin, ignore_monsters, ignore_glass, pEdict, &tr);
+
+ if (tr.flFraction != 1.0)
+ {
+ return FALSE; // Line of sight is not established
+ }
+ else
+ {
+ return TRUE; // line of sight is valid.
+ }
+}
+
+
+Vector GetGunPosition(edict_t *pEdict)
+{
+ return (pEdict->v.origin + pEdict->v.view_ofs);
+}
+
+
+void UTIL_SelectItem(edict_t *pEdict, char *item_name)
+{
+ FakeClientCommand(pEdict, item_name, NULL, NULL);
+}
+
+
+Vector VecBModelOrigin(edict_t *pEdict)
+{
+ return pEdict->v.absmin + (pEdict->v.size * 0.5);
+}
+
+
+bool UpdateSounds(edict_t *pEdict, edict_t *pPlayer)
+{
+ float distance;
+ static bool check_footstep_sounds = TRUE;
+ static float footstep_sounds_on;
+ float sensitivity = 1.0;
+ float volume;
+
+ // update sounds made by this player, alert bots if they are nearby...
+
+ if (check_footstep_sounds)
+ {
+ check_footstep_sounds = FALSE;
+ footstep_sounds_on = CVAR_GET_FLOAT("mp_footsteps");
+ }
+
+ if (footstep_sounds_on > 0.0)
+ {
+ CBasePlayer* thePlayer = (CBasePlayer*)CBaseEntity::Instance(pPlayer);
+
+ // check if this player is moving fast enough to make sounds...
+ if (pPlayer->v.velocity.Length2D() > thePlayer->GetMaxWalkSpeed())
+ {
+ volume = 500.0; // volume of sound being made (just pick something)
+
+ Vector v_sound = pPlayer->v.origin - pEdict->v.origin;
+
+ distance = v_sound.Length();
+
+ // is the bot close enough to hear this sound?
+ if (distance < (volume * sensitivity))
+ {
+ Vector bot_angles = UTIL_VecToAngles( v_sound );
+
+ pEdict->v.ideal_yaw = bot_angles.y;
+
+ BotFixIdealYaw(pEdict);
+
+ return TRUE;
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+
+void UTIL_ShowMenu( edict_t *pEdict, int slots, int displaytime, bool needmore, char *pText )
+{
+// if (gmsgShowMenu == 0)
+// gmsgShowMenu = REG_USER_MSG( "ShowMenu", -1 );
+//
+// pfnMessageBegin( MSG_ONE, gmsgShowMenu, NULL, pEdict );
+//
+// pfnWriteShort( slots );
+// pfnWriteChar( displaytime );
+// pfnWriteByte( needmore );
+// pfnWriteString( pText );
+//
+// pfnMessageEnd();
+}
+
+void UTIL_BuildFileName(char *filename, char *arg1, char *arg2)
+{
+
+ if (mod_id == VALVE_DLL)
+#ifndef __linux__
+ strcpy(filename, "valve\\");
+#else
+ strcpy(filename, "valve/");
+#endif
+
+ else if (mod_id == TFC_DLL)
+#ifndef __linux__
+ strcpy(filename, "tfc\\");
+#else
+ strcpy(filename, "tfc/");
+#endif
+
+ else if (mod_id == CSTRIKE_DLL)
+#ifndef __linux__
+ strcpy(filename, "cstrike\\");
+#else
+ strcpy(filename, "cstrike/");
+#endif
+
+ else if (mod_id == GEARBOX_DLL)
+#ifndef __linux__
+ strcpy(filename, "gearbox\\");
+#else
+ strcpy(filename, "gearbox/");
+#endif
+
+ else if (mod_id == FRONTLINE_DLL)
+#ifndef __linux__
+ strcpy(filename, "frontline\\");
+#else
+ strcpy(filename, "frontline/");
+#endif
+
+ else if (mod_id == AVH_DLL)
+ {
+ string filenameString = string(getModDirectory());
+#ifndef __linux__
+ filenameString += "\\";
+#else
+ filenameString += '/';
+#endif
+ strcpy(filename,filenameString.c_str());
+ }
+ else
+ {
+ filename[0] = 0;
+ return;
+ }
+
+ if ((arg1) && (*arg1) && (arg2) && (*arg2))
+ {
+ strcat(filename, arg1);
+
+#ifndef __linux__
+ strcat(filename, "\\");
+#else
+ strcat(filename, "/");
+#endif
+
+ strcat(filename, arg2);
+ }
+ else if ((arg1) && (*arg1))
+ {
+ strcat(filename, arg1);
+ }
+
+ printf("UTIL_BuildFileName:");
+ printf(filename);
+ printf("\n");
+}
+
+//=========================================================
+// UTIL_LogPrintf - Prints a logged message to console.
+// Preceded by LOG: ( timestamp ) < message >
+//=========================================================
+void UTIL_LogPrintf( char *fmt, ... )
+{
+ va_list argptr;
+ static char string[1024];
+
+ va_start ( argptr, fmt );
+ vsprintf ( string, fmt, argptr );
+ va_end ( argptr );
+
+ // Print to server console
+ printf("UTIL_LogPrintf:");
+ printf(string);
+ printf("\n");
+ ALERT( at_logged, "%s", string );
+}
+
diff --git a/main/source/HPB_bot/dlls/waypoint.cpp b/main/source/HPB_bot/dlls/waypoint.cpp
index 5eb2c8de..d99a9520 100644
--- a/main/source/HPB_bot/dlls/waypoint.cpp
+++ b/main/source/HPB_bot/dlls/waypoint.cpp
@@ -1,1938 +1,1938 @@
-// HPB bot - botman's High Ping Bastard bot
-//
-// (http://planethalflife.com/botman/)
-//
-// waypoint.cpp
-//
-
-#ifndef __linux__
-#include
-#endif
-#include
-#ifndef __linux__
-#include
-#else
-#include
-#endif
-
-#include "dlls/extdll.h"
-#include "dlls/enginecallback.h"
-#include "dlls/util.h"
-#include "dlls/cbase.h"
-
-#include "bot.h"
-#include "waypoint.h"
-//#include "mod/NetworkMeter.h"
-
-extern int mod_id;
-extern int m_spriteTexture;
-
-// waypoints with information bits (flags)
-WAYPOINT waypoints[MAX_WAYPOINTS];
-
-// number of waypoints currently in use
-int num_waypoints;
-
-// declare the array of head pointers to the path structures...
-PATH *paths[MAX_WAYPOINTS];
-
-// time that this waypoint was displayed (while editing)
-float wp_display_time[MAX_WAYPOINTS];
-
-bool g_waypoint_paths = FALSE; // have any paths been allocated?
-bool g_waypoint_on = FALSE;
-bool g_auto_waypoint = FALSE;
-bool g_path_waypoint = FALSE;
-Vector last_waypoint;
-float f_path_time = 0.0;
-
-unsigned int route_num_waypoints;
-unsigned short *shortest_path[4] = {NULL, NULL, NULL, NULL};
-unsigned short *from_to[4] = {NULL, NULL, NULL, NULL};
-
-static FILE *fp;
-
-
-void WaypointDebug(void)
-{
- int y = 1, x = 1;
-
- fp=fopen("bot.txt","a");
- fprintf(fp,"WaypointDebug: LINKED LIST ERROR!!!\n");
- fclose(fp);
-
- x = x - 1; // x is zero
- y = y / x; // cause an divide by zero exception
-
- return;
-}
-
-
-// free the linked list of waypoint path nodes...
-void WaypointFree(void)
-{
- for (int i=0; i < MAX_WAYPOINTS; i++)
- {
- int count = 0;
-
- if (paths[i])
- {
- PATH *p = paths[i];
- PATH *p_next;
-
- while (p) // free the linked list
- {
- p_next = p->next; // save the link to next
- free(p);
- p = p_next;
-
-#ifdef _DEBUG
- count++;
- if (count > 1000) WaypointDebug();
-#endif
- }
-
- paths[i] = NULL;
- }
- }
-}
-
-
-// initialize the waypoint structures...
-void WaypointInit(void)
-{
- int i;
-
- // have any waypoint path nodes been allocated yet?
- if (g_waypoint_paths)
- WaypointFree(); // must free previously allocated path memory
-
- for (i=0; i < 4; i++)
- {
- if (shortest_path[i] != NULL)
- free(shortest_path[i]);
-
- if (from_to[i] != NULL)
- free(from_to[i]);
- }
-
- for (i=0; i < MAX_WAYPOINTS; i++)
- {
- waypoints[i].flags = 0;
- waypoints[i].origin = Vector(0,0,0);
-
- wp_display_time[i] = 0.0;
-
- paths[i] = NULL; // no paths allocated yet
- }
-
- f_path_time = 0.0; // reset waypoint path display time
-
- num_waypoints = 0;
-
- last_waypoint = Vector(0,0,0);
-
- for (i=0; i < 4; i++)
- {
- shortest_path[i] = NULL;
- from_to[i] = NULL;
- }
-}
-
-
-// add a path from one waypoint (add_index) to another (path_index)...
-void WaypointAddPath(short int add_index, short int path_index)
-{
- PATH *p, *prev;
- int i;
- int count = 0;
-
- p = paths[add_index];
- prev = NULL;
-
- // find an empty slot for new path_index...
- while (p != NULL)
- {
- i = 0;
-
- while (i < MAX_PATH_INDEX)
- {
- if (p->index[i] == -1)
- {
- p->index[i] = path_index;
-
- return;
- }
-
- i++;
- }
-
- prev = p; // save the previous node in linked list
- p = p->next; // go to next node in linked list
-
-#ifdef _DEBUG
- count++;
- if (count > 100) WaypointDebug();
-#endif
- }
-
- p = (PATH *)malloc(sizeof(PATH));
-
- if (p == NULL)
- {
- ALERT(at_error, "HPB_bot - Error allocating memory for path!");
- }
-
- p->index[0] = path_index;
- p->index[1] = -1;
- p->index[2] = -1;
- p->index[3] = -1;
- p->next = NULL;
-
- if (prev != NULL)
- prev->next = p; // link new node into existing list
-
- if (paths[add_index] == NULL)
- paths[add_index] = p; // save head point if necessary
-}
-
-
-// delete all paths to this waypoint index...
-void WaypointDeletePath(short int del_index)
-{
- PATH *p;
- int index, i;
-
- // search all paths for this index...
- for (index=0; index < num_waypoints; index++)
- {
- p = paths[index];
-
- int count = 0;
-
- // search linked list for del_index...
- while (p != NULL)
- {
- i = 0;
-
- while (i < MAX_PATH_INDEX)
- {
- if (p->index[i] == del_index)
- {
- p->index[i] = -1; // unassign this path
- }
-
- i++;
- }
-
- p = p->next; // go to next node in linked list
-
-#ifdef _DEBUG
- count++;
- if (count > 100) WaypointDebug();
-#endif
- }
- }
-}
-
-
-// delete a path from a waypoint (path_index) to another waypoint
-// (del_index)...
-void WaypointDeletePath(short int path_index, short int del_index)
-{
- PATH *p;
- int i;
- int count = 0;
-
- p = paths[path_index];
-
- // search linked list for del_index...
- while (p != NULL)
- {
- i = 0;
-
- while (i < MAX_PATH_INDEX)
- {
- if (p->index[i] == del_index)
- {
- p->index[i] = -1; // unassign this path
- }
-
- i++;
- }
-
- p = p->next; // go to next node in linked list
-
-#ifdef _DEBUG
- count++;
- if (count > 100) WaypointDebug();
-#endif
- }
-}
-
-
-// find a path from the current waypoint. (pPath MUST be NULL on the
-// initial call. subsequent calls will return other paths if they exist.)
-int WaypointFindPath(PATH **pPath, int *path_index, int waypoint_index, int team)
-{
- int index;
- int count = 0;
-
- if (*pPath == NULL)
- {
- *pPath = paths[waypoint_index];
- *path_index = 0;
- }
-
- if (*path_index == MAX_PATH_INDEX)
- {
- *path_index = 0;
-
- *pPath = (*pPath)->next; // go to next node in linked list
- }
-
- while (*pPath != NULL)
- {
- while (*path_index < MAX_PATH_INDEX)
- {
- if ((*pPath)->index[*path_index] != -1) // found a path?
- {
- // save the return value
- index = (*pPath)->index[*path_index];
-
- // skip this path if next waypoint is team specific and NOT this team
- if ((team != -1) && (waypoints[index].flags & W_FL_TEAM_SPECIFIC) &&
- ((waypoints[index].flags & W_FL_TEAM) != team))
- {
- (*path_index)++;
- continue;
- }
-
- // set up stuff for subsequent calls...
- (*path_index)++;
-
- return index;
- }
-
- (*path_index)++;
- }
-
- *path_index = 0;
-
- *pPath = (*pPath)->next; // go to next node in linked list
-
-#ifdef _DEBUG
- count++;
- if (count > 100) WaypointDebug();
-#endif
- }
-
- return -1;
-}
-
-
-// find the nearest waypoint to the player and return the index
-// (-1 if not found)...
-int WaypointFindNearest(edict_t *pEntity, float range, int team)
-{
- int i, min_index;
- float distance;
- float min_distance;
- TraceResult tr;
-
- if (num_waypoints < 1)
- return -1;
-
- // find the nearest waypoint...
-
- min_index = -1;
- min_distance = 9999.0;
-
- for (i=0; i < num_waypoints; i++)
- {
- if (waypoints[i].flags & W_FL_DELETED)
- continue; // skip any deleted waypoints
-
- if (waypoints[i].flags & W_FL_AIMING)
- continue; // skip any aiming waypoints
-
- // skip this waypoint if it's team specific and teams don't match...
- if ((team != -1) && (waypoints[i].flags & W_FL_TEAM_SPECIFIC) &&
- ((waypoints[i].flags & W_FL_TEAM) != team))
- continue;
-
- distance = (waypoints[i].origin - pEntity->v.origin).Length();
-
- if ((distance < min_distance) && (distance < range))
- {
- // if waypoint is visible from current position (even behind head)...
- UTIL_TraceLine( pEntity->v.origin + pEntity->v.view_ofs, waypoints[i].origin,
- ignore_monsters, pEntity->v.pContainingEntity, &tr );
-
- if (tr.flFraction >= 1.0)
- {
- min_index = i;
- min_distance = distance;
- }
- }
- }
-
- return min_index;
-}
-
-
-// find the nearest waypoint to the source postition and return the index
-// of that waypoint...
-int WaypointFindNearest(Vector v_src, edict_t *pEntity, float range, int team)
-{
- int index, min_index;
- float distance;
- float min_distance;
- TraceResult tr;
-
- if (num_waypoints < 1)
- return -1;
-
- // find the nearest waypoint...
-
- min_index = -1;
- min_distance = 9999.0;
-
- for (index=0; index < num_waypoints; index++)
- {
- if (waypoints[index].flags & W_FL_DELETED)
- continue; // skip any deleted waypoints
-
- if (waypoints[index].flags & W_FL_AIMING)
- continue; // skip any aiming waypoints
-
- // skip this waypoint if it's team specific and teams don't match...
- if ((team != -1) && (waypoints[index].flags & W_FL_TEAM_SPECIFIC) &&
- ((waypoints[index].flags & W_FL_TEAM) != team))
- continue;
-
- distance = (waypoints[index].origin - v_src).Length();
-
- if ((distance < min_distance) && (distance < range))
- {
- // if waypoint is visible from source position...
- UTIL_TraceLine( v_src, waypoints[index].origin, ignore_monsters,
- pEntity->v.pContainingEntity, &tr );
-
- if (tr.flFraction >= 1.0)
- {
- min_index = index;
- min_distance = distance;
- }
- }
- }
-
- return min_index;
-}
-
-
-// find the goal nearest to the player matching the "flags" bits and return
-// the index of that waypoint...
-int WaypointFindNearestGoal(edict_t *pEntity, int src, int team, int flags)
-{
- int index, min_index;
- int distance, min_distance;
-
- if (num_waypoints < 1)
- return -1;
-
- // find the nearest waypoint with the matching flags...
-
- min_index = -1;
- min_distance = 99999;
-
- for (index=0; index < num_waypoints; index++)
- {
- if (index == src)
- continue; // skip the source waypoint
-
- if (waypoints[index].flags & W_FL_DELETED)
- continue; // skip any deleted waypoints
-
- if (waypoints[index].flags & W_FL_AIMING)
- continue; // skip any aiming waypoints
-
- // skip this waypoint if it's team specific and teams don't match...
- if ((team != -1) && (waypoints[index].flags & W_FL_TEAM_SPECIFIC) &&
- ((waypoints[index].flags & W_FL_TEAM) != team))
- continue;
-
- if ((waypoints[index].flags & flags) != flags)
- continue; // skip this waypoint if the flags don't match
-
- distance = WaypointDistanceFromTo(src, index, team);
-
- if (distance < min_distance)
- {
- min_index = index;
- min_distance = distance;
- }
- }
-
- return min_index;
-}
-
-
-// find the goal nearest to the source position (v_src) matching the "flags"
-// bits and return the index of that waypoint...
-int WaypointFindNearestGoal(Vector v_src, edict_t *pEntity, float range, int team, int flags)
-{
- int index, min_index;
- int distance, min_distance;
-
- if (num_waypoints < 1)
- return -1;
-
- // find the nearest waypoint with the matching flags...
-
- min_index = -1;
- min_distance = 99999;
-
- for (index=0; index < num_waypoints; index++)
- {
- if (waypoints[index].flags & W_FL_DELETED)
- continue; // skip any deleted waypoints
-
- if (waypoints[index].flags & W_FL_AIMING)
- continue; // skip any aiming waypoints
-
- // skip this waypoint if it's team specific and teams don't match...
- if ((team != -1) && (waypoints[index].flags & W_FL_TEAM_SPECIFIC) &&
- ((waypoints[index].flags & W_FL_TEAM) != team))
- continue;
-
- if ((waypoints[index].flags & flags) != flags)
- continue; // skip this waypoint if the flags don't match
-
- distance = (waypoints[index].origin - v_src).Length();
-
- if ((distance < range) && (distance < min_distance))
- {
- min_index = index;
- min_distance = distance;
- }
- }
-
- return min_index;
-}
-
-
-// find a random goal matching the "flags" bits and return the index of
-// that waypoint...
-int WaypointFindRandomGoal(edict_t *pEntity, int team, int flags)
-{
- int index;
- int indexes[50];
- int count = 0;
-
- if (num_waypoints < 1)
- return -1;
-
- // find all the waypoints with the matching flags...
-
- for (index=0; index < num_waypoints; index++)
- {
- if (waypoints[index].flags & W_FL_DELETED)
- continue; // skip any deleted waypoints
-
- if (waypoints[index].flags & W_FL_AIMING)
- continue; // skip any aiming waypoints
-
- // skip this waypoint if it's team specific and teams don't match...
- if ((team != -1) && (waypoints[index].flags & W_FL_TEAM_SPECIFIC) &&
- ((waypoints[index].flags & W_FL_TEAM) != team))
- continue;
-
- if ((waypoints[index].flags & flags) != flags)
- continue; // skip this waypoint if the flags don't match
-
- if (count < 50)
- {
- indexes[count] = index;
-
- count++;
- }
- }
-
- if (count == 0) // no matching waypoints found
- return -1;
-
- index = RANDOM_LONG(1, count) - 1;
-
- return indexes[index];
-}
-
-
-// find a random goal within a range of a position (v_src) matching the
-// "flags" bits and return the index of that waypoint...
-int WaypointFindRandomGoal(Vector v_src, edict_t *pEntity, float range, int team, int flags)
-{
- int index;
- int indexes[50];
- int count = 0;
- float distance;
-
- if (num_waypoints < 1)
- return -1;
-
- // find all the waypoints with the matching flags...
-
- for (index=0; index < num_waypoints; index++)
- {
- if (waypoints[index].flags & W_FL_DELETED)
- continue; // skip any deleted waypoints
-
- if (waypoints[index].flags & W_FL_AIMING)
- continue; // skip any aiming waypoints
-
- // skip this waypoint if it's team specific and teams don't match...
- if ((team != -1) && (waypoints[index].flags & W_FL_TEAM_SPECIFIC) &&
- ((waypoints[index].flags & W_FL_TEAM) != team))
- continue;
-
- if ((waypoints[index].flags & flags) != flags)
- continue; // skip this waypoint if the flags don't match
-
- distance = (waypoints[index].origin - v_src).Length();
-
- if ((distance < range) && (count < 50))
- {
- indexes[count] = index;
-
- count++;
- }
- }
-
- if (count == 0) // no matching waypoints found
- return -1;
-
- index = RANDOM_LONG(1, count) - 1;
-
- return indexes[index];
-}
-
-
-// find the nearest "special" aiming waypoint (for sniper aiming)...
-int WaypointFindNearestAiming(Vector v_origin)
-{
- int index;
- int min_index = -1;
- int min_distance = 9999.0;
- float distance;
-
- if (num_waypoints < 1)
- return -1;
-
- // search for nearby aiming waypoint...
- for (index=0; index < num_waypoints; index++)
- {
- if (waypoints[index].flags & W_FL_DELETED)
- continue; // skip any deleted waypoints
-
- if ((waypoints[index].flags & W_FL_AIMING) == 0)
- continue; // skip any NON aiming waypoints
-
- distance = (v_origin - waypoints[index].origin).Length();
-
- if ((distance < min_distance) && (distance < 40))
- {
- min_index = index;
- min_distance = distance;
- }
- }
-
- return min_index;
-}
-
-
-void WaypointDrawBeam(edict_t *pEntity, Vector start, Vector end, int width,
- int noise, int red, int green, int blue, int brightness, int speed)
-{
-// MESSAGE_BEGIN(MSG_ONE, SVC_TEMPENTITY, NULL, pEntity);
-// WRITE_BYTE( TE_BEAMPOINTS);
-// WRITE_COORD(start.x);
-// WRITE_COORD(start.y);
-// WRITE_COORD(start.z);
-// WRITE_COORD(end.x);
-// WRITE_COORD(end.y);
-// WRITE_COORD(end.z);
-// WRITE_SHORT( m_spriteTexture );
-// WRITE_BYTE( 1 ); // framestart
-// WRITE_BYTE( 10 ); // framerate
-// WRITE_BYTE( 10 ); // life in 0.1's
-// WRITE_BYTE( width ); // width
-// WRITE_BYTE( noise ); // noise
-//
-// WRITE_BYTE( red ); // r, g, b
-// WRITE_BYTE( green ); // r, g, b
-// WRITE_BYTE( blue ); // r, g, b
-//
-// WRITE_BYTE( brightness ); // brightness
-// WRITE_BYTE( speed ); // speed
-// MESSAGE_END();
-}
-
-
-void WaypointAdd(edict_t *pEntity)
-{
- int index;
- edict_t *pent = NULL;
- float radius = 40;
- char item_name[64];
-
- if (num_waypoints >= MAX_WAYPOINTS)
- return;
-
- index = 0;
-
- // find the next available slot for the new waypoint...
- while (index < num_waypoints)
- {
- if (waypoints[index].flags & W_FL_DELETED)
- break;
-
- index++;
- }
-
- waypoints[index].flags = 0;
-
- // store the origin (location) of this waypoint (use entity origin)
- waypoints[index].origin = pEntity->v.origin;
-
- // store the last used waypoint for the auto waypoint code...
- last_waypoint = pEntity->v.origin;
-
- // set the time that this waypoint was originally displayed...
- wp_display_time[index] = gpGlobals->time;
-
-
- Vector start, end;
-
- start = pEntity->v.origin - Vector(0, 0, 34);
- end = start + Vector(0, 0, 68);
-
- if ((pEntity->v.flags & FL_DUCKING) == FL_DUCKING)
- {
- waypoints[index].flags |= W_FL_CROUCH; // crouching waypoint
-
- start = pEntity->v.origin - Vector(0, 0, 17);
- end = start + Vector(0, 0, 34);
- }
-
- if (pEntity->v.movetype == MOVETYPE_FLY)
- waypoints[index].flags |= W_FL_LADDER; // waypoint on a ladder
-
-
- //********************************************************
- // look for lift, ammo, flag, health, armor, etc.
- //********************************************************
-
- while ((pent = UTIL_FindEntityInSphere( pent, pEntity->v.origin, radius )) != NULL)
- {
- strcpy(item_name, STRING(pent->v.classname));
-
- if (strcmp("item_healthkit", item_name) == 0)
- {
- ClientPrint(pEntity, HUD_PRINTCONSOLE, "found a healthkit!\n");
- waypoints[index].flags = W_FL_HEALTH;
- }
-
- if (strncmp("item_armor", item_name, 10) == 0)
- {
- ClientPrint(pEntity, HUD_PRINTCONSOLE, "found some armor!\n");
- waypoints[index].flags = W_FL_ARMOR;
- }
-
- // *************
- // LOOK FOR AMMO
- // *************
-
- }
-
- // draw a blue waypoint
- WaypointDrawBeam(pEntity, start, end, 30, 0, 0, 0, 255, 250, 5);
-
- EMIT_SOUND_DYN2(pEntity, CHAN_WEAPON, "weapons/xbow_hit1.wav", 1.0,
- ATTN_NORM, 0, 100);
-
- // increment total number of waypoints if adding at end of array...
- if (index == num_waypoints)
- num_waypoints++;
-
- // calculate all the paths to this new waypoint
- for (int i=0; i < num_waypoints; i++)
- {
- if (i == index)
- continue; // skip the waypoint that was just added
-
- if (waypoints[i].flags & W_FL_AIMING)
- continue; // skip any aiming waypoints
-
- // check if the waypoint is reachable from the new one (one-way)
- if ( WaypointReachable(pEntity->v.origin, waypoints[i].origin, pEntity) )
- {
- WaypointAddPath(index, i);
- }
-
- // check if the new one is reachable from the waypoint (other way)
- if ( WaypointReachable(waypoints[i].origin, pEntity->v.origin, pEntity) )
- {
- WaypointAddPath(i, index);
- }
- }
-}
-
-
-void WaypointAddAiming(edict_t *pEntity)
-{
- int index;
- edict_t *pent = NULL;
-
- if (num_waypoints >= MAX_WAYPOINTS)
- return;
-
- index = 0;
-
- // find the next available slot for the new waypoint...
- while (index < num_waypoints)
- {
- if (waypoints[index].flags & W_FL_DELETED)
- break;
-
- index++;
- }
-
- waypoints[index].flags = W_FL_AIMING; // aiming waypoint
-
- Vector v_angle = pEntity->v.v_angle;
-
- v_angle.x = 0; // reset pitch to horizontal
- v_angle.z = 0; // reset roll to level
-
- UTIL_MakeVectors(v_angle);
-
- // store the origin (location) of this waypoint (use entity origin)
- waypoints[index].origin = pEntity->v.origin + gpGlobals->v_forward * 25;
-
- // set the time that this waypoint was originally displayed...
- wp_display_time[index] = gpGlobals->time;
-
-
- Vector start, end;
-
- start = pEntity->v.origin - Vector(0, 0, 10);
- end = start + Vector(0, 0, 14);
-
- // draw a blue waypoint
- WaypointDrawBeam(pEntity, start, end, 30, 0, 0, 0, 255, 250, 5);
-
- EMIT_SOUND_DYN2(pEntity, CHAN_WEAPON, "weapons/xbow_hit1.wav", 1.0,
- ATTN_NORM, 0, 100);
-
- // increment total number of waypoints if adding at end of array...
- if (index == num_waypoints)
- num_waypoints++;
-}
-
-
-void WaypointDelete(edict_t *pEntity)
-{
- int index;
- int count = 0;
-
- if (num_waypoints < 1)
- return;
-
- index = WaypointFindNearest(pEntity, 50.0, -1);
-
- if (index == -1)
- return;
-
- if ((waypoints[index].flags & W_FL_SNIPER) ||
- ((mod_id == FRONTLINE_DLL) && (waypoints[index].flags & W_FL_FLF_DEFEND)))
- {
- int i;
- int min_index = -1;
- int min_distance = 9999.0;
- float distance;
-
- // search for nearby aiming waypoint and delete it also...
- for (i=0; i < num_waypoints; i++)
- {
- if (waypoints[i].flags & W_FL_DELETED)
- continue; // skip any deleted waypoints
-
- if ((waypoints[i].flags & W_FL_AIMING) == 0)
- continue; // skip any NON aiming waypoints
-
- distance = (waypoints[i].origin - waypoints[index].origin).Length();
-
- if ((distance < min_distance) && (distance < 40))
- {
- min_index = i;
- min_distance = distance;
- }
- }
-
- if (min_index != -1)
- {
- waypoints[min_index].flags = W_FL_DELETED; // not being used
- waypoints[min_index].origin = Vector(0,0,0);
-
- wp_display_time[min_index] = 0.0;
- }
- }
-
- // delete any paths that lead to this index...
- WaypointDeletePath(index);
-
- // free the path for this index...
-
- if (paths[index] != NULL)
- {
- PATH *p = paths[index];
- PATH *p_next;
-
- while (p) // free the linked list
- {
- p_next = p->next; // save the link to next
- free(p);
- p = p_next;
-
-#ifdef _DEBUG
- count++;
- if (count > 100) WaypointDebug();
-#endif
- }
-
- paths[index] = NULL;
- }
-
- waypoints[index].flags = W_FL_DELETED; // not being used
- waypoints[index].origin = Vector(0,0,0);
-
- wp_display_time[index] = 0.0;
-
- EMIT_SOUND_DYN2(pEntity, CHAN_WEAPON, "weapons/mine_activate.wav", 1.0,
- ATTN_NORM, 0, 100);
-}
-
-
-// allow player to manually create a path from one waypoint to another
-void WaypointCreatePath(edict_t *pEntity, int cmd)
-{
- static int waypoint1 = -1; // initialized to unassigned
- static int waypoint2 = -1; // initialized to unassigned
-
- if (cmd == 1) // assign source of path
- {
- waypoint1 = WaypointFindNearest(pEntity, 50.0, -1);
-
- if (waypoint1 == -1)
- {
- // play "cancelled" sound...
- EMIT_SOUND_DYN2(pEntity, CHAN_WEAPON, "common/wpn_moveselect.wav", 1.0,
- ATTN_NORM, 0, 100);
-
- return;
- }
-
- // play "start" sound...
- EMIT_SOUND_DYN2(pEntity, CHAN_WEAPON, "common/wpn_hudoff.wav", 1.0,
- ATTN_NORM, 0, 100);
-
- return;
- }
-
- if (cmd == 2) // assign dest of path and make path
- {
- waypoint2 = WaypointFindNearest(pEntity, 50.0, -1);
-
- if ((waypoint1 == -1) || (waypoint2 == -1))
- {
- // play "error" sound...
- EMIT_SOUND_DYN2(pEntity, CHAN_WEAPON, "common/wpn_denyselect.wav", 1.0,
- ATTN_NORM, 0, 100);
-
- return;
- }
-
- WaypointAddPath(waypoint1, waypoint2);
-
- // play "done" sound...
- EMIT_SOUND_DYN2(pEntity, CHAN_WEAPON, "common/wpn_hudon.wav", 1.0,
- ATTN_NORM, 0, 100);
- }
-}
-
-
-// allow player to manually remove a path from one waypoint to another
-void WaypointRemovePath(edict_t *pEntity, int cmd)
-{
- static int waypoint1 = -1; // initialized to unassigned
- static int waypoint2 = -1; // initialized to unassigned
-
- if (cmd == 1) // assign source of path
- {
- waypoint1 = WaypointFindNearest(pEntity, 50.0, -1);
-
- if (waypoint1 == -1)
- {
- // play "cancelled" sound...
- EMIT_SOUND_DYN2(pEntity, CHAN_WEAPON, "common/wpn_moveselect.wav", 1.0,
- ATTN_NORM, 0, 100);
-
- return;
- }
-
- // play "start" sound...
- EMIT_SOUND_DYN2(pEntity, CHAN_WEAPON, "common/wpn_hudoff.wav", 1.0,
- ATTN_NORM, 0, 100);
-
- return;
- }
-
- if (cmd == 2) // assign dest of path and make path
- {
- waypoint2 = WaypointFindNearest(pEntity, 50.0, -1);
-
- if ((waypoint1 == -1) || (waypoint2 == -1))
- {
- // play "error" sound...
- EMIT_SOUND_DYN2(pEntity, CHAN_WEAPON, "common/wpn_denyselect.wav", 1.0,
- ATTN_NORM, 0, 100);
-
- return;
- }
-
- WaypointDeletePath(waypoint1, waypoint2);
-
- // play "done" sound...
- EMIT_SOUND_DYN2(pEntity, CHAN_WEAPON, "common/wpn_hudon.wav", 1.0,
- ATTN_NORM, 0, 100);
- }
-}
-
-
-bool WaypointLoad(edict_t *pEntity)
-{
- char mapname[64];
- char filename[256];
- WAYPOINT_HDR header;
- char msg[80];
- int index, i;
- short int num;
- short int path_index;
-
- strcpy(mapname, STRING(gpGlobals->mapname));
- strcat(mapname, ".wpt");
-
- UTIL_BuildFileName(filename, "maps", mapname);
-
- if (IS_DEDICATED_SERVER())
- printf("loading waypoint file: %s\n", filename);
-
- FILE *bfp = fopen(filename, "rb");
-
- // if file exists, read the waypoint structure from it
- if (bfp != NULL)
- {
- fread(&header, sizeof(header), 1, bfp);
-
- header.filetype[7] = 0;
- if (strcmp(header.filetype, "HPB_bot") == 0)
- {
- if (header.waypoint_file_version != WAYPOINT_VERSION)
- {
- if (pEntity)
- ClientPrint(pEntity, HUD_PRINTNOTIFY, "Incompatible HPB bot waypoint file version!\nWaypoints not loaded!\n");
-
- fclose(bfp);
- return FALSE;
- }
-
- header.mapname[31] = 0;
-
- if (strcmp(header.mapname, STRING(gpGlobals->mapname)) == 0)
- {
- WaypointInit(); // remove any existing waypoints
-
- for (i=0; i < header.number_of_waypoints; i++)
- {
- fread(&waypoints[i], sizeof(waypoints[0]), 1, bfp);
- num_waypoints++;
- }
-
- // read and add waypoint paths...
- for (index=0; index < num_waypoints; index++)
- {
- // read the number of paths from this node...
- fread(&num, sizeof(num), 1, bfp);
-
- for (i=0; i < num; i++)
- {
- fread(&path_index, sizeof(path_index), 1, bfp);
-
- WaypointAddPath(index, path_index);
- }
- }
-
- g_waypoint_paths = TRUE; // keep track so path can be freed
- }
- else
- {
- if (pEntity)
- {
- sprintf(msg, "%s HPB bot waypoints are not for this map!\n", filename);
- ClientPrint(pEntity, HUD_PRINTNOTIFY, msg);
- }
-
- fclose(bfp);
- return FALSE;
- }
- }
- else
- {
- if (pEntity)
- {
- sprintf(msg, "%s is not a HPB bot waypoint file!\n", filename);
- ClientPrint(pEntity, HUD_PRINTNOTIFY, msg);
- }
-
- fclose(bfp);
- return FALSE;
- }
-
- fclose(bfp);
-
- WaypointRouteInit();
- }
- else
- {
- if (pEntity)
- {
- sprintf(msg, "Waypoint file %s does not exist!\n", filename);
- ClientPrint(pEntity, HUD_PRINTNOTIFY, msg);
- }
-
- if (IS_DEDICATED_SERVER())
- printf("waypoint file %s not found!\n", filename);
-
- return FALSE;
- }
-
- return TRUE;
-}
-
-
-void WaypointSave(void)
-{
- char filename[256];
- char mapname[64];
- WAYPOINT_HDR header;
- int index, i;
- short int num;
- PATH *p;
-
- strcpy(header.filetype, "HPB_bot");
-
- header.waypoint_file_version = WAYPOINT_VERSION;
-
- header.waypoint_file_flags = 0; // not currently used
-
- header.number_of_waypoints = num_waypoints;
-
- memset(header.mapname, 0, sizeof(header.mapname));
- strncpy(header.mapname, STRING(gpGlobals->mapname), 31);
- header.mapname[31] = 0;
-
- strcpy(mapname, STRING(gpGlobals->mapname));
- strcat(mapname, ".wpt");
-
- UTIL_BuildFileName(filename, "maps", mapname);
-
- FILE *bfp = fopen(filename, "wb");
-
- // write the waypoint header to the file...
- fwrite(&header, sizeof(header), 1, bfp);
-
- // write the waypoint data to the file...
- for (index=0; index < num_waypoints; index++)
- {
- fwrite(&waypoints[index], sizeof(waypoints[0]), 1, bfp);
- }
-
- // save the waypoint paths...
- for (index=0; index < num_waypoints; index++)
- {
- // count the number of paths from this node...
-
- p = paths[index];
- num = 0;
-
- while (p != NULL)
- {
- i = 0;
-
- while (i < MAX_PATH_INDEX)
- {
- if (p->index[i] != -1)
- num++; // count path node if it's used
-
- i++;
- }
-
- p = p->next; // go to next node in linked list
- }
-
- fwrite(&num, sizeof(num), 1, bfp); // write the count
-
- // now write out each path index...
-
- p = paths[index];
-
- while (p != NULL)
- {
- i = 0;
-
- while (i < MAX_PATH_INDEX)
- {
- if (p->index[i] != -1) // save path node if it's used
- fwrite(&p->index[i], sizeof(p->index[0]), 1, bfp);
-
- i++;
- }
-
- p = p->next; // go to next node in linked list
- }
- }
-
- fclose(bfp);
-}
-
-
-bool WaypointReachable(Vector v_src, Vector v_dest, edict_t *pEntity)
-{
- TraceResult tr;
- float curr_height, last_height;
-
- float distance = (v_dest - v_src).Length();
-
- // is the destination close enough?
- if (distance < REACHABLE_RANGE)
- {
- // check if this waypoint is "visible"...
-
- UTIL_TraceLine( v_src, v_dest, ignore_monsters,
- pEntity->v.pContainingEntity, &tr );
-
- // if waypoint is visible from current position (even behind head)...
- if (tr.flFraction >= 1.0)
- {
- // check for special case of both waypoints being underwater...
- if ((POINT_CONTENTS( v_src ) == CONTENTS_WATER) &&
- (POINT_CONTENTS( v_dest ) == CONTENTS_WATER))
- {
- return TRUE;
- }
-
- // check for special case of waypoint being suspended in mid-air...
-
- // is dest waypoint higher than src? (45 is max jump height)
- if (v_dest.z > (v_src.z + 45.0))
- {
- Vector v_new_src = v_dest;
- Vector v_new_dest = v_dest;
-
- v_new_dest.z = v_new_dest.z - 50; // straight down 50 units
-
- UTIL_TraceLine(v_new_src, v_new_dest, dont_ignore_monsters,
- pEntity->v.pContainingEntity, &tr);
-
- // check if we didn't hit anything, if not then it's in mid-air
- if (tr.flFraction >= 1.0)
- {
- return FALSE; // can't reach this one
- }
- }
-
- // check if distance to ground increases more than jump height
- // at points between source and destination...
-
- Vector v_direction = (v_dest - v_src).Normalize(); // 1 unit long
- Vector v_check = v_src;
- Vector v_down = v_src;
-
- v_down.z = v_down.z - 1000.0; // straight down 1000 units
-
- UTIL_TraceLine(v_check, v_down, ignore_monsters,
- pEntity->v.pContainingEntity, &tr);
-
- last_height = tr.flFraction * 1000.0; // height from ground
-
- distance = (v_dest - v_check).Length(); // distance from goal
-
- while (distance > 10.0)
- {
- // move 10 units closer to the goal...
- v_check = v_check + (v_direction * 10.0);
-
- v_down = v_check;
- v_down.z = v_down.z - 1000.0; // straight down 1000 units
-
- UTIL_TraceLine(v_check, v_down, ignore_monsters,
- pEntity->v.pContainingEntity, &tr);
-
- curr_height = tr.flFraction * 1000.0; // height from ground
-
- // is the difference in the last height and the current height
- // higher that the jump height?
- if ((last_height - curr_height) > 45.0)
- {
- // can't get there from here...
- return FALSE;
- }
-
- last_height = curr_height;
-
- distance = (v_dest - v_check).Length(); // distance from goal
- }
-
- return TRUE;
- }
- }
-
- return FALSE;
-}
-
-
-// find the nearest reachable waypoint
-int WaypointFindReachable(edict_t *pEntity, float range, int team)
-{
- int i, min_index;
- float distance;
- float min_distance;
- TraceResult tr;
-
- // find the nearest waypoint...
-
- min_distance = 9999.0;
-
- for (i=0; i < num_waypoints; i++)
- {
- if (waypoints[i].flags & W_FL_DELETED)
- continue; // skip any deleted waypoints
-
- if (waypoints[i].flags & W_FL_AIMING)
- continue; // skip any aiming waypoints
-
- // skip this waypoint if it's team specific and teams don't match...
- if ((team != -1) && (waypoints[i].flags & W_FL_TEAM_SPECIFIC) &&
- ((waypoints[i].flags & W_FL_TEAM) != team))
- continue;
-
- distance = (waypoints[i].origin - pEntity->v.origin).Length();
-
- if (distance < min_distance)
- {
- // if waypoint is visible from current position (even behind head)...
- UTIL_TraceLine( pEntity->v.origin + pEntity->v.view_ofs, waypoints[i].origin,
- ignore_monsters, pEntity->v.pContainingEntity, &tr );
-
- if (tr.flFraction >= 1.0)
- {
- if (WaypointReachable(pEntity->v.origin, waypoints[i].origin, pEntity))
- {
- min_index = i;
- min_distance = distance;
- }
- }
- }
- }
-
- // if not close enough to a waypoint then just return
- if (min_distance > range)
- return -1;
-
- return min_index;
-
-}
-
-
-void WaypointPrintInfo(edict_t *pEntity)
-{
- char msg[80];
- int index;
- int flags;
-
- // find the nearest waypoint...
- index = WaypointFindNearest(pEntity, 50.0, -1);
-
- if (index == -1)
- return;
-
- sprintf(msg,"Waypoint %d of %d total\n", index, num_waypoints);
- ClientPrint(pEntity, HUD_PRINTNOTIFY, msg);
-
- flags = waypoints[index].flags;
-
- if (flags & W_FL_TEAM_SPECIFIC)
- {
- if (mod_id == FRONTLINE_DLL)
- {
- if ((flags & W_FL_TEAM) == 0)
- strcpy(msg, "Waypoint is for Attackers\n");
- else if ((flags & W_FL_TEAM) == 1)
- strcpy(msg, "Waypoint is for Defenders\n");
- }
- else
- {
- if ((flags & W_FL_TEAM) == 0)
- strcpy(msg, "Waypoint is for TEAM 1\n");
- else if ((flags & W_FL_TEAM) == 1)
- strcpy(msg, "Waypoint is for TEAM 2\n");
- else if ((flags & W_FL_TEAM) == 2)
- strcpy(msg, "Waypoint is for TEAM 3\n");
- else if ((flags & W_FL_TEAM) == 3)
- strcpy(msg, "Waypoint is for TEAM 4\n");
- }
-
- ClientPrint(pEntity, HUD_PRINTNOTIFY, msg);
- }
-
- if (flags & W_FL_LIFT)
- ClientPrint(pEntity, HUD_PRINTNOTIFY, "Bot will wait for lift before approaching\n");
-
- if (flags & W_FL_LADDER)
- ClientPrint(pEntity, HUD_PRINTNOTIFY, "This waypoint is on a ladder\n");
-
- if (flags & W_FL_DOOR)
- ClientPrint(pEntity, HUD_PRINTNOTIFY, "This is a door waypoint\n");
-
- if (flags & W_FL_HEALTH)
- ClientPrint(pEntity, HUD_PRINTNOTIFY, "There is health near this waypoint\n");
-
- if (flags & W_FL_ARMOR)
- ClientPrint(pEntity, HUD_PRINTNOTIFY, "There is armor near this waypoint\n");
-
- if (flags & W_FL_AMMO)
- ClientPrint(pEntity, HUD_PRINTNOTIFY, "There is ammo near this waypoint\n");
-
- if (flags & W_FL_SNIPER)
- ClientPrint(pEntity, HUD_PRINTNOTIFY, "This is a sniper waypoint\n");
-
- if (flags & W_FL_TFC_FLAG)
- {
- if (mod_id == FRONTLINE_DLL)
- ClientPrint(pEntity, HUD_PRINTNOTIFY, "There is a capture point near this waypoint\n");
- else
- ClientPrint(pEntity, HUD_PRINTNOTIFY, "There is a flag near this waypoint\n");
- }
-
- if (flags & W_FL_TFC_FLAG_GOAL)
- {
- if (mod_id == FRONTLINE_DLL)
- ClientPrint(pEntity, HUD_PRINTNOTIFY, "This is a defender location\n");
- else
- ClientPrint(pEntity, HUD_PRINTNOTIFY, "There is a flag goal near this waypoint\n");
- }
-
- if (flags & W_FL_PRONE)
- ClientPrint(pEntity, HUD_PRINTNOTIFY, "Bot will go prone here\n");
-}
-
-
-void WaypointThink(edict_t *pEntity)
-{
- float distance, min_distance;
- Vector start, end;
- int i, index;
-
- if (g_auto_waypoint) // is auto waypoint on?
- {
- // find the distance from the last used waypoint
- distance = (last_waypoint - pEntity->v.origin).Length();
-
- if (distance > 200)
- {
- min_distance = 9999.0;
-
- // check that no other reachable waypoints are nearby...
- for (i=0; i < num_waypoints; i++)
- {
- if (waypoints[i].flags & W_FL_DELETED)
- continue;
-
- if (waypoints[i].flags & W_FL_AIMING)
- continue;
-
- if (WaypointReachable(pEntity->v.origin, waypoints[i].origin, pEntity))
- {
- distance = (waypoints[i].origin - pEntity->v.origin).Length();
-
- if (distance < min_distance)
- min_distance = distance;
- }
- }
-
- // make sure nearest waypoint is far enough away...
- if (min_distance >= 200)
- WaypointAdd(pEntity); // place a waypoint here
- }
- }
-
- min_distance = 9999.0;
-
- if (g_waypoint_on) // display the waypoints if turned on...
- {
- for (i=0; i < num_waypoints; i++)
- {
- if ((waypoints[i].flags & W_FL_DELETED) == W_FL_DELETED)
- continue;
-
- distance = (waypoints[i].origin - pEntity->v.origin).Length();
-
- if (distance < 500)
- {
- if (distance < min_distance)
- {
- index = i; // store index of nearest waypoint
- min_distance = distance;
- }
-
- if ((wp_display_time[i] + 1.0) < gpGlobals->time)
- {
- if (waypoints[i].flags & W_FL_CROUCH)
- {
- start = waypoints[i].origin - Vector(0, 0, 17);
- end = start + Vector(0, 0, 34);
- }
- else if (waypoints[i].flags & W_FL_AIMING)
- {
- start = waypoints[i].origin + Vector(0, 0, 10);
- end = start + Vector(0, 0, 14);
- }
- else
- {
- start = waypoints[i].origin - Vector(0, 0, 34);
- end = start + Vector(0, 0, 68);
- }
-
- // draw a blue waypoint
- WaypointDrawBeam(pEntity, start, end, 30, 0, 0, 0, 255, 250, 5);
-
- wp_display_time[i] = gpGlobals->time;
- }
- }
- }
-
- // check if path waypointing is on...
- if (g_path_waypoint)
- {
- // check if player is close enough to a waypoint and time to draw path...
- if ((min_distance <= 50) && (f_path_time <= gpGlobals->time))
- {
- PATH *p;
-
- f_path_time = gpGlobals->time + 1.0;
-
- p = paths[index];
-
- while (p != NULL)
- {
- i = 0;
-
- while (i < MAX_PATH_INDEX)
- {
- if (p->index[i] != -1)
- {
- Vector v_src = waypoints[index].origin;
- Vector v_dest = waypoints[p->index[i]].origin;
-
- // draw a white line to this index's waypoint
- WaypointDrawBeam(pEntity, v_src, v_dest, 10, 2, 250, 250, 250, 200, 10);
- }
-
- i++;
- }
-
- p = p->next; // go to next node in linked list
- }
- }
- }
- }
-}
-
-
-// run Floyd's algorithm on the waypoint list to generate the least cost
-// path matrix...
-void WaypointFloyds(unsigned short *shortest_path, unsigned short *from_to)
-{
- unsigned int x, y, z;
- int changed = 1;
- int distance;
-
- for (y=0; y < route_num_waypoints; y++)
- {
- for (z=0; z < route_num_waypoints; z++)
- {
- from_to[y * route_num_waypoints + z] = z;
- }
- }
-
- while (changed)
- {
- changed = 0;
-
- for (x=0; x < route_num_waypoints; x++)
- {
- for (y=0; y < route_num_waypoints; y++)
- {
- for (z=0; z < route_num_waypoints; z++)
- {
- if ((shortest_path[y * route_num_waypoints + x] == WAYPOINT_UNREACHABLE) ||
- (shortest_path[x * route_num_waypoints + z] == WAYPOINT_UNREACHABLE))
- continue;
-
- distance = shortest_path[y * route_num_waypoints + x] +
- shortest_path[x * route_num_waypoints + z];
-
- if (distance > WAYPOINT_MAX_DISTANCE)
- distance = WAYPOINT_MAX_DISTANCE;
-
- if ((distance < shortest_path[y * route_num_waypoints + z]) ||
- (shortest_path[y * route_num_waypoints + z] == WAYPOINT_UNREACHABLE))
- {
- shortest_path[y * route_num_waypoints + z] = distance;
- from_to[y * route_num_waypoints + z] = from_to[y * route_num_waypoints + x];
- changed = 1;
- }
- }
- }
- }
- }
-}
-
-
-// load the waypoint route files (.wp1, .wp2, etc.) or generate them if
-// they don't exist...
-void WaypointRouteInit(void)
-{
- unsigned int index;
- bool build_matrix[4];
- int matrix;
- unsigned int array_size;
- unsigned int row;
- int i, offset;
- unsigned int a, b;
- float distance;
- unsigned short *pShortestPath, *pFromTo;
- char msg[80];
- unsigned int num_items;
- FILE *bfp;
- char filename[256];
- char filename2[256];
- char mapname[64];
-
- if (num_waypoints == 0)
- return;
-
- // save number of current waypoints in case waypoints get added later
- route_num_waypoints = num_waypoints;
-
- strcpy(mapname, STRING(gpGlobals->mapname));
- strcat(mapname, ".wpt");
-
- UTIL_BuildFileName(filename, "maps", mapname);
-
- build_matrix[0] = TRUE; // always build matrix 0 (non-team and team 1)
- build_matrix[1] = FALSE;
- build_matrix[2] = FALSE;
- build_matrix[3] = FALSE;
-
- // find out how many route matrixes to create...
- for (index=0; index < route_num_waypoints; index++)
- {
- if (waypoints[index].flags & W_FL_TEAM_SPECIFIC)
- {
- if ((waypoints[index].flags & W_FL_TEAM) == 0x01) // team 2?
- build_matrix[1] = TRUE;
-
- if ((waypoints[index].flags & W_FL_TEAM) == 0x02) // team 3?
- build_matrix[2] = TRUE;
-
- if ((waypoints[index].flags & W_FL_TEAM) == 0x03) // team 4?
- build_matrix[3] = TRUE;
- }
- }
-
- array_size = route_num_waypoints * route_num_waypoints;
-
- for (matrix=0; matrix < 4; matrix++)
- {
- if (build_matrix[matrix])
- {
- char ext_str[5]; // ".wpX\0"
- int file1, file2;
- struct stat stat1, stat2;
-
- sprintf(ext_str, ".wp%d", matrix+1);
-
- strcpy(mapname, STRING(gpGlobals->mapname));
- strcat(mapname, ext_str);
-
- UTIL_BuildFileName(filename2, "maps", mapname);
-
- if (access(filename2, 0) == 0) // does the .wpX file exist?
- {
- file1 = open(filename, O_RDONLY);
- file2 = open(filename2, O_RDONLY);
-
- fstat(file1, &stat1);
- fstat(file2, &stat2);
-
- close(file1);
- close(file2);
-
- if (stat1.st_mtime < stat2.st_mtime) // is .wpt older than .wpX file?
- {
- sprintf(msg, "loading HPB bot waypoint paths for team %d\n", matrix+1);
- ALERT(at_console, msg);
-
- shortest_path[matrix] = (unsigned short *)malloc(sizeof(unsigned short) * array_size);
-
- if (shortest_path[matrix] == NULL)
- ALERT(at_error, "HPB_bot - Error allocating memory for shortest path!");
-
- from_to[matrix] = (unsigned short *)malloc(sizeof(unsigned short) * array_size);
-
- if (from_to[matrix] == NULL)
- ALERT(at_error, "HPB_bot - Error allocating memory for from to matrix!");
-
- bfp = fopen(filename2, "rb");
-
- if (bfp != NULL)
- {
- num_items = fread(shortest_path[matrix], sizeof(unsigned short), array_size, bfp);
-
- if (num_items != array_size)
- {
- // if couldn't read enough data, free memory to recalculate it
-
- ALERT(at_console, "error reading enough path items, recalculating...\n");
-
- free(shortest_path[matrix]);
- shortest_path[matrix] = NULL;
-
- free(from_to[matrix]);
- from_to[matrix] = NULL;
- }
- else
- {
- num_items = fread(from_to[matrix], sizeof(unsigned short), array_size, bfp);
-
- if (num_items != array_size)
- {
- // if couldn't read enough data, free memory to recalculate it
-
- ALERT(at_console, "error reading enough path items, recalculating...\n");
-
- free(shortest_path[matrix]);
- shortest_path[matrix] = NULL;
-
- free(from_to[matrix]);
- from_to[matrix] = NULL;
- }
- }
- }
- else
- {
- ALERT(at_console, "HPB_bot - Error reading waypoint paths!\n");
-
- free(shortest_path[matrix]);
- shortest_path[matrix] = NULL;
-
- free(from_to[matrix]);
- from_to[matrix] = NULL;
- }
-
- fclose(bfp);
- }
- }
-
- if (shortest_path[matrix] == NULL)
- {
- sprintf(msg, "calculating HPB bot waypoint paths for team %d...\n", matrix+1);
- ALERT(at_console, msg);
-
- shortest_path[matrix] = (unsigned short *)malloc(sizeof(unsigned short) * array_size);
-
- if (shortest_path[matrix] == NULL)
- ALERT(at_error, "HPB_bot - Error allocating memory for shortest path!");
-
- from_to[matrix] = (unsigned short *)malloc(sizeof(unsigned short) * array_size);
-
- if (from_to[matrix] == NULL)
- ALERT(at_error, "HPB_bot - Error allocating memory for from to matrix!");
-
- pShortestPath = shortest_path[matrix];
- pFromTo = from_to[matrix];
-
- for (index=0; index < array_size; index++)
- pShortestPath[index] = WAYPOINT_UNREACHABLE;
-
- for (index=0; index < route_num_waypoints; index++)
- pShortestPath[index * route_num_waypoints + index] = 0; // zero diagonal
-
- for (row=0; row < route_num_waypoints; row++)
- {
- if (paths[row] != NULL)
- {
- PATH *p = paths[row];
-
- while (p)
- {
- i = 0;
-
- while (i < MAX_PATH_INDEX)
- {
- if (p->index[i] != -1)
- {
- index = p->index[i];
-
- // check if this is NOT team specific OR matches this team
- if (!(waypoints[index].flags & W_FL_TEAM_SPECIFIC) ||
- ((waypoints[index].flags & W_FL_TEAM) == matrix))
- {
- distance = (waypoints[row].origin - waypoints[index].origin).Length();
-
- if (distance > (float)WAYPOINT_MAX_DISTANCE)
- distance = (float)WAYPOINT_MAX_DISTANCE;
-
- if (distance > REACHABLE_RANGE)
- {
- sprintf(msg, "Waypoint path distance > %4.1f at from %d to %d\n",
- REACHABLE_RANGE, row, index);
- ALERT(at_console, msg);
- }
- else
- {
- offset = row * route_num_waypoints + index;
-
- pShortestPath[offset] = (unsigned short)distance;
- }
- }
- }
-
- i++;
- }
-
- p = p->next; // go to next node in linked list
- }
- }
- }
-
- // run Floyd's Algorithm to generate the from_to matrix...
- WaypointFloyds(pShortestPath, pFromTo);
-
- for (a=0; a < route_num_waypoints; a++)
- {
- for (b=0; b < route_num_waypoints; b++)
- if (pShortestPath[a * route_num_waypoints + b] == WAYPOINT_UNREACHABLE)
- pFromTo[a * route_num_waypoints + b] = WAYPOINT_UNREACHABLE;
- }
-
- bfp = fopen(filename2, "wb");
-
- if (bfp != NULL)
- {
- num_items = fwrite(shortest_path[matrix], sizeof(unsigned short), array_size, bfp);
-
- if (num_items != array_size)
- {
- // if couldn't write enough data, close file and delete it
-
- fclose(bfp);
- unlink(filename2);
- }
- else
- {
- num_items = fwrite(from_to[matrix], sizeof(unsigned short), array_size, bfp);
-
- fclose(bfp);
-
- if (num_items != array_size)
- {
- // if couldn't write enough data, delete file
- unlink(filename2);
- }
- }
- }
- else
- {
- ALERT(at_console, "HPB_bot - Error writing waypoint paths!\n");
- }
-
- sprintf(msg, "HPB bot waypoint path calculations for team %d complete!\n",matrix+1);
- ALERT(at_console, msg);
- }
- }
- }
-
-}
-
-
-// return the next waypoint index for a path from the Floyd matrix when
-// going from a source waypoint index (src) to a destination waypoint
-// index (dest)...
-unsigned short WaypointRouteFromTo(int src, int dest, int team)
-{
- unsigned short *pFromTo;
-
- if ((team < -1) || (team > 3))
- return -1;
-
- if (team == -1) // -1 means non-team play
- team = 0;
-
- if (from_to[team] == NULL) // if no team specific waypoints use team 0
- team = 0;
-
- if (from_to[team] == NULL) // if no route information just return
- return -1;
-
- pFromTo = from_to[team];
-
- return pFromTo[src * route_num_waypoints + dest];
-}
-
-
-// return the total distance (based on the Floyd matrix) of a path from
-// the source waypoint index (src) to the destination waypoint index
-// (dest)...
-int WaypointDistanceFromTo(int src, int dest, int team)
-{
- unsigned short *pShortestPath;
-
- if ((team < -1) || (team > 3))
- return -1;
-
- if (team == -1) // -1 means non-team play
- team = 0;
-
- if (from_to[team] == NULL) // if no team specific waypoints use team 0
- team = 0;
-
- if (from_to[team] == NULL) // if no route information just return
- return -1;
-
- pShortestPath = shortest_path[team];
-
- return (int)(pShortestPath[src * route_num_waypoints + dest]);
-}
-
+// HPB bot - botman's High Ping Bastard bot
+//
+// (http://planethalflife.com/botman/)
+//
+// waypoint.cpp
+//
+
+#ifndef __linux__
+#include
+#endif
+#include
+#ifndef __linux__
+#include
+#else
+#include
+#endif
+
+#include "dlls/extdll.h"
+#include "dlls/enginecallback.h"
+#include "dlls/util.h"
+#include "dlls/cbase.h"
+
+#include "bot.h"
+#include "waypoint.h"
+//#include "mod/NetworkMeter.h"
+
+extern int mod_id;
+extern int m_spriteTexture;
+
+// waypoints with information bits (flags)
+WAYPOINT waypoints[MAX_WAYPOINTS];
+
+// number of waypoints currently in use
+int num_waypoints;
+
+// declare the array of head pointers to the path structures...
+PATH *paths[MAX_WAYPOINTS];
+
+// time that this waypoint was displayed (while editing)
+float wp_display_time[MAX_WAYPOINTS];
+
+bool g_waypoint_paths = FALSE; // have any paths been allocated?
+bool g_waypoint_on = FALSE;
+bool g_auto_waypoint = FALSE;
+bool g_path_waypoint = FALSE;
+Vector last_waypoint;
+float f_path_time = 0.0;
+
+unsigned int route_num_waypoints;
+unsigned short *shortest_path[4] = {NULL, NULL, NULL, NULL};
+unsigned short *from_to[4] = {NULL, NULL, NULL, NULL};
+
+static FILE *fp;
+
+
+void WaypointDebug(void)
+{
+ int y = 1, x = 1;
+
+ fp=fopen("bot.txt","a");
+ fprintf(fp,"WaypointDebug: LINKED LIST ERROR!!!\n");
+ fclose(fp);
+
+ x = x - 1; // x is zero
+ y = y / x; // cause an divide by zero exception
+
+ return;
+}
+
+
+// free the linked list of waypoint path nodes...
+void WaypointFree(void)
+{
+ for (int i=0; i < MAX_WAYPOINTS; i++)
+ {
+ int count = 0;
+
+ if (paths[i])
+ {
+ PATH *p = paths[i];
+ PATH *p_next;
+
+ while (p) // free the linked list
+ {
+ p_next = p->next; // save the link to next
+ free(p);
+ p = p_next;
+
+#ifdef _DEBUG
+ count++;
+ if (count > 1000) WaypointDebug();
+#endif
+ }
+
+ paths[i] = NULL;
+ }
+ }
+}
+
+
+// initialize the waypoint structures...
+void WaypointInit(void)
+{
+ int i;
+
+ // have any waypoint path nodes been allocated yet?
+ if (g_waypoint_paths)
+ WaypointFree(); // must free previously allocated path memory
+
+ for (i=0; i < 4; i++)
+ {
+ if (shortest_path[i] != NULL)
+ free(shortest_path[i]);
+
+ if (from_to[i] != NULL)
+ free(from_to[i]);
+ }
+
+ for (i=0; i < MAX_WAYPOINTS; i++)
+ {
+ waypoints[i].flags = 0;
+ waypoints[i].origin = Vector(0,0,0);
+
+ wp_display_time[i] = 0.0;
+
+ paths[i] = NULL; // no paths allocated yet
+ }
+
+ f_path_time = 0.0; // reset waypoint path display time
+
+ num_waypoints = 0;
+
+ last_waypoint = Vector(0,0,0);
+
+ for (i=0; i < 4; i++)
+ {
+ shortest_path[i] = NULL;
+ from_to[i] = NULL;
+ }
+}
+
+
+// add a path from one waypoint (add_index) to another (path_index)...
+void WaypointAddPath(short int add_index, short int path_index)
+{
+ PATH *p, *prev;
+ int i;
+ int count = 0;
+
+ p = paths[add_index];
+ prev = NULL;
+
+ // find an empty slot for new path_index...
+ while (p != NULL)
+ {
+ i = 0;
+
+ while (i < MAX_PATH_INDEX)
+ {
+ if (p->index[i] == -1)
+ {
+ p->index[i] = path_index;
+
+ return;
+ }
+
+ i++;
+ }
+
+ prev = p; // save the previous node in linked list
+ p = p->next; // go to next node in linked list
+
+#ifdef _DEBUG
+ count++;
+ if (count > 100) WaypointDebug();
+#endif
+ }
+
+ p = (PATH *)malloc(sizeof(PATH));
+
+ if (p == NULL)
+ {
+ ALERT(at_error, "HPB_bot - Error allocating memory for path!");
+ }
+
+ p->index[0] = path_index;
+ p->index[1] = -1;
+ p->index[2] = -1;
+ p->index[3] = -1;
+ p->next = NULL;
+
+ if (prev != NULL)
+ prev->next = p; // link new node into existing list
+
+ if (paths[add_index] == NULL)
+ paths[add_index] = p; // save head point if necessary
+}
+
+
+// delete all paths to this waypoint index...
+void WaypointDeletePath(short int del_index)
+{
+ PATH *p;
+ int index, i;
+
+ // search all paths for this index...
+ for (index=0; index < num_waypoints; index++)
+ {
+ p = paths[index];
+
+ int count = 0;
+
+ // search linked list for del_index...
+ while (p != NULL)
+ {
+ i = 0;
+
+ while (i < MAX_PATH_INDEX)
+ {
+ if (p->index[i] == del_index)
+ {
+ p->index[i] = -1; // unassign this path
+ }
+
+ i++;
+ }
+
+ p = p->next; // go to next node in linked list
+
+#ifdef _DEBUG
+ count++;
+ if (count > 100) WaypointDebug();
+#endif
+ }
+ }
+}
+
+
+// delete a path from a waypoint (path_index) to another waypoint
+// (del_index)...
+void WaypointDeletePath(short int path_index, short int del_index)
+{
+ PATH *p;
+ int i;
+ int count = 0;
+
+ p = paths[path_index];
+
+ // search linked list for del_index...
+ while (p != NULL)
+ {
+ i = 0;
+
+ while (i < MAX_PATH_INDEX)
+ {
+ if (p->index[i] == del_index)
+ {
+ p->index[i] = -1; // unassign this path
+ }
+
+ i++;
+ }
+
+ p = p->next; // go to next node in linked list
+
+#ifdef _DEBUG
+ count++;
+ if (count > 100) WaypointDebug();
+#endif
+ }
+}
+
+
+// find a path from the current waypoint. (pPath MUST be NULL on the
+// initial call. subsequent calls will return other paths if they exist.)
+int WaypointFindPath(PATH **pPath, int *path_index, int waypoint_index, int team)
+{
+ int index;
+ int count = 0;
+
+ if (*pPath == NULL)
+ {
+ *pPath = paths[waypoint_index];
+ *path_index = 0;
+ }
+
+ if (*path_index == MAX_PATH_INDEX)
+ {
+ *path_index = 0;
+
+ *pPath = (*pPath)->next; // go to next node in linked list
+ }
+
+ while (*pPath != NULL)
+ {
+ while (*path_index < MAX_PATH_INDEX)
+ {
+ if ((*pPath)->index[*path_index] != -1) // found a path?
+ {
+ // save the return value
+ index = (*pPath)->index[*path_index];
+
+ // skip this path if next waypoint is team specific and NOT this team
+ if ((team != -1) && (waypoints[index].flags & W_FL_TEAM_SPECIFIC) &&
+ ((waypoints[index].flags & W_FL_TEAM) != team))
+ {
+ (*path_index)++;
+ continue;
+ }
+
+ // set up stuff for subsequent calls...
+ (*path_index)++;
+
+ return index;
+ }
+
+ (*path_index)++;
+ }
+
+ *path_index = 0;
+
+ *pPath = (*pPath)->next; // go to next node in linked list
+
+#ifdef _DEBUG
+ count++;
+ if (count > 100) WaypointDebug();
+#endif
+ }
+
+ return -1;
+}
+
+
+// find the nearest waypoint to the player and return the index
+// (-1 if not found)...
+int WaypointFindNearest(edict_t *pEntity, float range, int team)
+{
+ int i, min_index;
+ float distance;
+ float min_distance;
+ TraceResult tr;
+
+ if (num_waypoints < 1)
+ return -1;
+
+ // find the nearest waypoint...
+
+ min_index = -1;
+ min_distance = 9999.0;
+
+ for (i=0; i < num_waypoints; i++)
+ {
+ if (waypoints[i].flags & W_FL_DELETED)
+ continue; // skip any deleted waypoints
+
+ if (waypoints[i].flags & W_FL_AIMING)
+ continue; // skip any aiming waypoints
+
+ // skip this waypoint if it's team specific and teams don't match...
+ if ((team != -1) && (waypoints[i].flags & W_FL_TEAM_SPECIFIC) &&
+ ((waypoints[i].flags & W_FL_TEAM) != team))
+ continue;
+
+ distance = (waypoints[i].origin - pEntity->v.origin).Length();
+
+ if ((distance < min_distance) && (distance < range))
+ {
+ // if waypoint is visible from current position (even behind head)...
+ UTIL_TraceLine( pEntity->v.origin + pEntity->v.view_ofs, waypoints[i].origin,
+ ignore_monsters, pEntity->v.pContainingEntity, &tr );
+
+ if (tr.flFraction >= 1.0)
+ {
+ min_index = i;
+ min_distance = distance;
+ }
+ }
+ }
+
+ return min_index;
+}
+
+
+// find the nearest waypoint to the source postition and return the index
+// of that waypoint...
+int WaypointFindNearest(Vector v_src, edict_t *pEntity, float range, int team)
+{
+ int index, min_index;
+ float distance;
+ float min_distance;
+ TraceResult tr;
+
+ if (num_waypoints < 1)
+ return -1;
+
+ // find the nearest waypoint...
+
+ min_index = -1;
+ min_distance = 9999.0;
+
+ for (index=0; index < num_waypoints; index++)
+ {
+ if (waypoints[index].flags & W_FL_DELETED)
+ continue; // skip any deleted waypoints
+
+ if (waypoints[index].flags & W_FL_AIMING)
+ continue; // skip any aiming waypoints
+
+ // skip this waypoint if it's team specific and teams don't match...
+ if ((team != -1) && (waypoints[index].flags & W_FL_TEAM_SPECIFIC) &&
+ ((waypoints[index].flags & W_FL_TEAM) != team))
+ continue;
+
+ distance = (waypoints[index].origin - v_src).Length();
+
+ if ((distance < min_distance) && (distance < range))
+ {
+ // if waypoint is visible from source position...
+ UTIL_TraceLine( v_src, waypoints[index].origin, ignore_monsters,
+ pEntity->v.pContainingEntity, &tr );
+
+ if (tr.flFraction >= 1.0)
+ {
+ min_index = index;
+ min_distance = distance;
+ }
+ }
+ }
+
+ return min_index;
+}
+
+
+// find the goal nearest to the player matching the "flags" bits and return
+// the index of that waypoint...
+int WaypointFindNearestGoal(edict_t *pEntity, int src, int team, int flags)
+{
+ int index, min_index;
+ int distance, min_distance;
+
+ if (num_waypoints < 1)
+ return -1;
+
+ // find the nearest waypoint with the matching flags...
+
+ min_index = -1;
+ min_distance = 99999;
+
+ for (index=0; index < num_waypoints; index++)
+ {
+ if (index == src)
+ continue; // skip the source waypoint
+
+ if (waypoints[index].flags & W_FL_DELETED)
+ continue; // skip any deleted waypoints
+
+ if (waypoints[index].flags & W_FL_AIMING)
+ continue; // skip any aiming waypoints
+
+ // skip this waypoint if it's team specific and teams don't match...
+ if ((team != -1) && (waypoints[index].flags & W_FL_TEAM_SPECIFIC) &&
+ ((waypoints[index].flags & W_FL_TEAM) != team))
+ continue;
+
+ if ((waypoints[index].flags & flags) != flags)
+ continue; // skip this waypoint if the flags don't match
+
+ distance = WaypointDistanceFromTo(src, index, team);
+
+ if (distance < min_distance)
+ {
+ min_index = index;
+ min_distance = distance;
+ }
+ }
+
+ return min_index;
+}
+
+
+// find the goal nearest to the source position (v_src) matching the "flags"
+// bits and return the index of that waypoint...
+int WaypointFindNearestGoal(Vector v_src, edict_t *pEntity, float range, int team, int flags)
+{
+ int index, min_index;
+ int distance, min_distance;
+
+ if (num_waypoints < 1)
+ return -1;
+
+ // find the nearest waypoint with the matching flags...
+
+ min_index = -1;
+ min_distance = 99999;
+
+ for (index=0; index < num_waypoints; index++)
+ {
+ if (waypoints[index].flags & W_FL_DELETED)
+ continue; // skip any deleted waypoints
+
+ if (waypoints[index].flags & W_FL_AIMING)
+ continue; // skip any aiming waypoints
+
+ // skip this waypoint if it's team specific and teams don't match...
+ if ((team != -1) && (waypoints[index].flags & W_FL_TEAM_SPECIFIC) &&
+ ((waypoints[index].flags & W_FL_TEAM) != team))
+ continue;
+
+ if ((waypoints[index].flags & flags) != flags)
+ continue; // skip this waypoint if the flags don't match
+
+ distance = (waypoints[index].origin - v_src).Length();
+
+ if ((distance < range) && (distance < min_distance))
+ {
+ min_index = index;
+ min_distance = distance;
+ }
+ }
+
+ return min_index;
+}
+
+
+// find a random goal matching the "flags" bits and return the index of
+// that waypoint...
+int WaypointFindRandomGoal(edict_t *pEntity, int team, int flags)
+{
+ int index;
+ int indexes[50];
+ int count = 0;
+
+ if (num_waypoints < 1)
+ return -1;
+
+ // find all the waypoints with the matching flags...
+
+ for (index=0; index < num_waypoints; index++)
+ {
+ if (waypoints[index].flags & W_FL_DELETED)
+ continue; // skip any deleted waypoints
+
+ if (waypoints[index].flags & W_FL_AIMING)
+ continue; // skip any aiming waypoints
+
+ // skip this waypoint if it's team specific and teams don't match...
+ if ((team != -1) && (waypoints[index].flags & W_FL_TEAM_SPECIFIC) &&
+ ((waypoints[index].flags & W_FL_TEAM) != team))
+ continue;
+
+ if ((waypoints[index].flags & flags) != flags)
+ continue; // skip this waypoint if the flags don't match
+
+ if (count < 50)
+ {
+ indexes[count] = index;
+
+ count++;
+ }
+ }
+
+ if (count == 0) // no matching waypoints found
+ return -1;
+
+ index = RANDOM_LONG(1, count) - 1;
+
+ return indexes[index];
+}
+
+
+// find a random goal within a range of a position (v_src) matching the
+// "flags" bits and return the index of that waypoint...
+int WaypointFindRandomGoal(Vector v_src, edict_t *pEntity, float range, int team, int flags)
+{
+ int index;
+ int indexes[50];
+ int count = 0;
+ float distance;
+
+ if (num_waypoints < 1)
+ return -1;
+
+ // find all the waypoints with the matching flags...
+
+ for (index=0; index < num_waypoints; index++)
+ {
+ if (waypoints[index].flags & W_FL_DELETED)
+ continue; // skip any deleted waypoints
+
+ if (waypoints[index].flags & W_FL_AIMING)
+ continue; // skip any aiming waypoints
+
+ // skip this waypoint if it's team specific and teams don't match...
+ if ((team != -1) && (waypoints[index].flags & W_FL_TEAM_SPECIFIC) &&
+ ((waypoints[index].flags & W_FL_TEAM) != team))
+ continue;
+
+ if ((waypoints[index].flags & flags) != flags)
+ continue; // skip this waypoint if the flags don't match
+
+ distance = (waypoints[index].origin - v_src).Length();
+
+ if ((distance < range) && (count < 50))
+ {
+ indexes[count] = index;
+
+ count++;
+ }
+ }
+
+ if (count == 0) // no matching waypoints found
+ return -1;
+
+ index = RANDOM_LONG(1, count) - 1;
+
+ return indexes[index];
+}
+
+
+// find the nearest "special" aiming waypoint (for sniper aiming)...
+int WaypointFindNearestAiming(Vector v_origin)
+{
+ int index;
+ int min_index = -1;
+ int min_distance = 9999.0;
+ float distance;
+
+ if (num_waypoints < 1)
+ return -1;
+
+ // search for nearby aiming waypoint...
+ for (index=0; index < num_waypoints; index++)
+ {
+ if (waypoints[index].flags & W_FL_DELETED)
+ continue; // skip any deleted waypoints
+
+ if ((waypoints[index].flags & W_FL_AIMING) == 0)
+ continue; // skip any NON aiming waypoints
+
+ distance = (v_origin - waypoints[index].origin).Length();
+
+ if ((distance < min_distance) && (distance < 40))
+ {
+ min_index = index;
+ min_distance = distance;
+ }
+ }
+
+ return min_index;
+}
+
+
+void WaypointDrawBeam(edict_t *pEntity, Vector start, Vector end, int width,
+ int noise, int red, int green, int blue, int brightness, int speed)
+{
+// MESSAGE_BEGIN(MSG_ONE, SVC_TEMPENTITY, NULL, pEntity);
+// WRITE_BYTE( TE_BEAMPOINTS);
+// WRITE_COORD(start.x);
+// WRITE_COORD(start.y);
+// WRITE_COORD(start.z);
+// WRITE_COORD(end.x);
+// WRITE_COORD(end.y);
+// WRITE_COORD(end.z);
+// WRITE_SHORT( m_spriteTexture );
+// WRITE_BYTE( 1 ); // framestart
+// WRITE_BYTE( 10 ); // framerate
+// WRITE_BYTE( 10 ); // life in 0.1's
+// WRITE_BYTE( width ); // width
+// WRITE_BYTE( noise ); // noise
+//
+// WRITE_BYTE( red ); // r, g, b
+// WRITE_BYTE( green ); // r, g, b
+// WRITE_BYTE( blue ); // r, g, b
+//
+// WRITE_BYTE( brightness ); // brightness
+// WRITE_BYTE( speed ); // speed
+// MESSAGE_END();
+}
+
+
+void WaypointAdd(edict_t *pEntity)
+{
+ int index;
+ edict_t *pent = NULL;
+ float radius = 40;
+ char item_name[64];
+
+ if (num_waypoints >= MAX_WAYPOINTS)
+ return;
+
+ index = 0;
+
+ // find the next available slot for the new waypoint...
+ while (index < num_waypoints)
+ {
+ if (waypoints[index].flags & W_FL_DELETED)
+ break;
+
+ index++;
+ }
+
+ waypoints[index].flags = 0;
+
+ // store the origin (location) of this waypoint (use entity origin)
+ waypoints[index].origin = pEntity->v.origin;
+
+ // store the last used waypoint for the auto waypoint code...
+ last_waypoint = pEntity->v.origin;
+
+ // set the time that this waypoint was originally displayed...
+ wp_display_time[index] = gpGlobals->time;
+
+
+ Vector start, end;
+
+ start = pEntity->v.origin - Vector(0, 0, 34);
+ end = start + Vector(0, 0, 68);
+
+ if ((pEntity->v.flags & FL_DUCKING) == FL_DUCKING)
+ {
+ waypoints[index].flags |= W_FL_CROUCH; // crouching waypoint
+
+ start = pEntity->v.origin - Vector(0, 0, 17);
+ end = start + Vector(0, 0, 34);
+ }
+
+ if (pEntity->v.movetype == MOVETYPE_FLY)
+ waypoints[index].flags |= W_FL_LADDER; // waypoint on a ladder
+
+
+ //********************************************************
+ // look for lift, ammo, flag, health, armor, etc.
+ //********************************************************
+
+ while ((pent = UTIL_FindEntityInSphere( pent, pEntity->v.origin, radius )) != NULL)
+ {
+ strcpy(item_name, STRING(pent->v.classname));
+
+ if (strcmp("item_healthkit", item_name) == 0)
+ {
+ ClientPrint(pEntity, HUD_PRINTCONSOLE, "found a healthkit!\n");
+ waypoints[index].flags = W_FL_HEALTH;
+ }
+
+ if (strncmp("item_armor", item_name, 10) == 0)
+ {
+ ClientPrint(pEntity, HUD_PRINTCONSOLE, "found some armor!\n");
+ waypoints[index].flags = W_FL_ARMOR;
+ }
+
+ // *************
+ // LOOK FOR AMMO
+ // *************
+
+ }
+
+ // draw a blue waypoint
+ WaypointDrawBeam(pEntity, start, end, 30, 0, 0, 0, 255, 250, 5);
+
+ EMIT_SOUND_DYN2(pEntity, CHAN_WEAPON, "weapons/xbow_hit1.wav", 1.0,
+ ATTN_NORM, 0, 100);
+
+ // increment total number of waypoints if adding at end of array...
+ if (index == num_waypoints)
+ num_waypoints++;
+
+ // calculate all the paths to this new waypoint
+ for (int i=0; i < num_waypoints; i++)
+ {
+ if (i == index)
+ continue; // skip the waypoint that was just added
+
+ if (waypoints[i].flags & W_FL_AIMING)
+ continue; // skip any aiming waypoints
+
+ // check if the waypoint is reachable from the new one (one-way)
+ if ( WaypointReachable(pEntity->v.origin, waypoints[i].origin, pEntity) )
+ {
+ WaypointAddPath(index, i);
+ }
+
+ // check if the new one is reachable from the waypoint (other way)
+ if ( WaypointReachable(waypoints[i].origin, pEntity->v.origin, pEntity) )
+ {
+ WaypointAddPath(i, index);
+ }
+ }
+}
+
+
+void WaypointAddAiming(edict_t *pEntity)
+{
+ int index;
+ edict_t *pent = NULL;
+
+ if (num_waypoints >= MAX_WAYPOINTS)
+ return;
+
+ index = 0;
+
+ // find the next available slot for the new waypoint...
+ while (index < num_waypoints)
+ {
+ if (waypoints[index].flags & W_FL_DELETED)
+ break;
+
+ index++;
+ }
+
+ waypoints[index].flags = W_FL_AIMING; // aiming waypoint
+
+ Vector v_angle = pEntity->v.v_angle;
+
+ v_angle.x = 0; // reset pitch to horizontal
+ v_angle.z = 0; // reset roll to level
+
+ UTIL_MakeVectors(v_angle);
+
+ // store the origin (location) of this waypoint (use entity origin)
+ waypoints[index].origin = pEntity->v.origin + gpGlobals->v_forward * 25;
+
+ // set the time that this waypoint was originally displayed...
+ wp_display_time[index] = gpGlobals->time;
+
+
+ Vector start, end;
+
+ start = pEntity->v.origin - Vector(0, 0, 10);
+ end = start + Vector(0, 0, 14);
+
+ // draw a blue waypoint
+ WaypointDrawBeam(pEntity, start, end, 30, 0, 0, 0, 255, 250, 5);
+
+ EMIT_SOUND_DYN2(pEntity, CHAN_WEAPON, "weapons/xbow_hit1.wav", 1.0,
+ ATTN_NORM, 0, 100);
+
+ // increment total number of waypoints if adding at end of array...
+ if (index == num_waypoints)
+ num_waypoints++;
+}
+
+
+void WaypointDelete(edict_t *pEntity)
+{
+ int index;
+ int count = 0;
+
+ if (num_waypoints < 1)
+ return;
+
+ index = WaypointFindNearest(pEntity, 50.0, -1);
+
+ if (index == -1)
+ return;
+
+ if ((waypoints[index].flags & W_FL_SNIPER) ||
+ ((mod_id == FRONTLINE_DLL) && (waypoints[index].flags & W_FL_FLF_DEFEND)))
+ {
+ int i;
+ int min_index = -1;
+ int min_distance = 9999.0;
+ float distance;
+
+ // search for nearby aiming waypoint and delete it also...
+ for (i=0; i < num_waypoints; i++)
+ {
+ if (waypoints[i].flags & W_FL_DELETED)
+ continue; // skip any deleted waypoints
+
+ if ((waypoints[i].flags & W_FL_AIMING) == 0)
+ continue; // skip any NON aiming waypoints
+
+ distance = (waypoints[i].origin - waypoints[index].origin).Length();
+
+ if ((distance < min_distance) && (distance < 40))
+ {
+ min_index = i;
+ min_distance = distance;
+ }
+ }
+
+ if (min_index != -1)
+ {
+ waypoints[min_index].flags = W_FL_DELETED; // not being used
+ waypoints[min_index].origin = Vector(0,0,0);
+
+ wp_display_time[min_index] = 0.0;
+ }
+ }
+
+ // delete any paths that lead to this index...
+ WaypointDeletePath(index);
+
+ // free the path for this index...
+
+ if (paths[index] != NULL)
+ {
+ PATH *p = paths[index];
+ PATH *p_next;
+
+ while (p) // free the linked list
+ {
+ p_next = p->next; // save the link to next
+ free(p);
+ p = p_next;
+
+#ifdef _DEBUG
+ count++;
+ if (count > 100) WaypointDebug();
+#endif
+ }
+
+ paths[index] = NULL;
+ }
+
+ waypoints[index].flags = W_FL_DELETED; // not being used
+ waypoints[index].origin = Vector(0,0,0);
+
+ wp_display_time[index] = 0.0;
+
+ EMIT_SOUND_DYN2(pEntity, CHAN_WEAPON, "weapons/mine_activate.wav", 1.0,
+ ATTN_NORM, 0, 100);
+}
+
+
+// allow player to manually create a path from one waypoint to another
+void WaypointCreatePath(edict_t *pEntity, int cmd)
+{
+ static int waypoint1 = -1; // initialized to unassigned
+ static int waypoint2 = -1; // initialized to unassigned
+
+ if (cmd == 1) // assign source of path
+ {
+ waypoint1 = WaypointFindNearest(pEntity, 50.0, -1);
+
+ if (waypoint1 == -1)
+ {
+ // play "cancelled" sound...
+ EMIT_SOUND_DYN2(pEntity, CHAN_WEAPON, "common/wpn_moveselect.wav", 1.0,
+ ATTN_NORM, 0, 100);
+
+ return;
+ }
+
+ // play "start" sound...
+ EMIT_SOUND_DYN2(pEntity, CHAN_WEAPON, "common/wpn_hudoff.wav", 1.0,
+ ATTN_NORM, 0, 100);
+
+ return;
+ }
+
+ if (cmd == 2) // assign dest of path and make path
+ {
+ waypoint2 = WaypointFindNearest(pEntity, 50.0, -1);
+
+ if ((waypoint1 == -1) || (waypoint2 == -1))
+ {
+ // play "error" sound...
+ EMIT_SOUND_DYN2(pEntity, CHAN_WEAPON, "common/wpn_denyselect.wav", 1.0,
+ ATTN_NORM, 0, 100);
+
+ return;
+ }
+
+ WaypointAddPath(waypoint1, waypoint2);
+
+ // play "done" sound...
+ EMIT_SOUND_DYN2(pEntity, CHAN_WEAPON, "common/wpn_hudon.wav", 1.0,
+ ATTN_NORM, 0, 100);
+ }
+}
+
+
+// allow player to manually remove a path from one waypoint to another
+void WaypointRemovePath(edict_t *pEntity, int cmd)
+{
+ static int waypoint1 = -1; // initialized to unassigned
+ static int waypoint2 = -1; // initialized to unassigned
+
+ if (cmd == 1) // assign source of path
+ {
+ waypoint1 = WaypointFindNearest(pEntity, 50.0, -1);
+
+ if (waypoint1 == -1)
+ {
+ // play "cancelled" sound...
+ EMIT_SOUND_DYN2(pEntity, CHAN_WEAPON, "common/wpn_moveselect.wav", 1.0,
+ ATTN_NORM, 0, 100);
+
+ return;
+ }
+
+ // play "start" sound...
+ EMIT_SOUND_DYN2(pEntity, CHAN_WEAPON, "common/wpn_hudoff.wav", 1.0,
+ ATTN_NORM, 0, 100);
+
+ return;
+ }
+
+ if (cmd == 2) // assign dest of path and make path
+ {
+ waypoint2 = WaypointFindNearest(pEntity, 50.0, -1);
+
+ if ((waypoint1 == -1) || (waypoint2 == -1))
+ {
+ // play "error" sound...
+ EMIT_SOUND_DYN2(pEntity, CHAN_WEAPON, "common/wpn_denyselect.wav", 1.0,
+ ATTN_NORM, 0, 100);
+
+ return;
+ }
+
+ WaypointDeletePath(waypoint1, waypoint2);
+
+ // play "done" sound...
+ EMIT_SOUND_DYN2(pEntity, CHAN_WEAPON, "common/wpn_hudon.wav", 1.0,
+ ATTN_NORM, 0, 100);
+ }
+}
+
+
+bool WaypointLoad(edict_t *pEntity)
+{
+ char mapname[64];
+ char filename[256];
+ WAYPOINT_HDR header;
+ char msg[80];
+ int index, i;
+ short int num;
+ short int path_index;
+
+ strcpy(mapname, STRING(gpGlobals->mapname));
+ strcat(mapname, ".wpt");
+
+ UTIL_BuildFileName(filename, "maps", mapname);
+
+ if (IS_DEDICATED_SERVER())
+ printf("loading waypoint file: %s\n", filename);
+
+ FILE *bfp = fopen(filename, "rb");
+
+ // if file exists, read the waypoint structure from it
+ if (bfp != NULL)
+ {
+ fread(&header, sizeof(header), 1, bfp);
+
+ header.filetype[7] = 0;
+ if (strcmp(header.filetype, "HPB_bot") == 0)
+ {
+ if (header.waypoint_file_version != WAYPOINT_VERSION)
+ {
+ if (pEntity)
+ ClientPrint(pEntity, HUD_PRINTNOTIFY, "Incompatible HPB bot waypoint file version!\nWaypoints not loaded!\n");
+
+ fclose(bfp);
+ return FALSE;
+ }
+
+ header.mapname[31] = 0;
+
+ if (strcmp(header.mapname, STRING(gpGlobals->mapname)) == 0)
+ {
+ WaypointInit(); // remove any existing waypoints
+
+ for (i=0; i < header.number_of_waypoints; i++)
+ {
+ fread(&waypoints[i], sizeof(waypoints[0]), 1, bfp);
+ num_waypoints++;
+ }
+
+ // read and add waypoint paths...
+ for (index=0; index < num_waypoints; index++)
+ {
+ // read the number of paths from this node...
+ fread(&num, sizeof(num), 1, bfp);
+
+ for (i=0; i < num; i++)
+ {
+ fread(&path_index, sizeof(path_index), 1, bfp);
+
+ WaypointAddPath(index, path_index);
+ }
+ }
+
+ g_waypoint_paths = TRUE; // keep track so path can be freed
+ }
+ else
+ {
+ if (pEntity)
+ {
+ sprintf(msg, "%s HPB bot waypoints are not for this map!\n", filename);
+ ClientPrint(pEntity, HUD_PRINTNOTIFY, msg);
+ }
+
+ fclose(bfp);
+ return FALSE;
+ }
+ }
+ else
+ {
+ if (pEntity)
+ {
+ sprintf(msg, "%s is not a HPB bot waypoint file!\n", filename);
+ ClientPrint(pEntity, HUD_PRINTNOTIFY, msg);
+ }
+
+ fclose(bfp);
+ return FALSE;
+ }
+
+ fclose(bfp);
+
+ WaypointRouteInit();
+ }
+ else
+ {
+ if (pEntity)
+ {
+ sprintf(msg, "Waypoint file %s does not exist!\n", filename);
+ ClientPrint(pEntity, HUD_PRINTNOTIFY, msg);
+ }
+
+ if (IS_DEDICATED_SERVER())
+ printf("waypoint file %s not found!\n", filename);
+
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+void WaypointSave(void)
+{
+ char filename[256];
+ char mapname[64];
+ WAYPOINT_HDR header;
+ int index, i;
+ short int num;
+ PATH *p;
+
+ strcpy(header.filetype, "HPB_bot");
+
+ header.waypoint_file_version = WAYPOINT_VERSION;
+
+ header.waypoint_file_flags = 0; // not currently used
+
+ header.number_of_waypoints = num_waypoints;
+
+ memset(header.mapname, 0, sizeof(header.mapname));
+ strncpy(header.mapname, STRING(gpGlobals->mapname), 31);
+ header.mapname[31] = 0;
+
+ strcpy(mapname, STRING(gpGlobals->mapname));
+ strcat(mapname, ".wpt");
+
+ UTIL_BuildFileName(filename, "maps", mapname);
+
+ FILE *bfp = fopen(filename, "wb");
+
+ // write the waypoint header to the file...
+ fwrite(&header, sizeof(header), 1, bfp);
+
+ // write the waypoint data to the file...
+ for (index=0; index < num_waypoints; index++)
+ {
+ fwrite(&waypoints[index], sizeof(waypoints[0]), 1, bfp);
+ }
+
+ // save the waypoint paths...
+ for (index=0; index < num_waypoints; index++)
+ {
+ // count the number of paths from this node...
+
+ p = paths[index];
+ num = 0;
+
+ while (p != NULL)
+ {
+ i = 0;
+
+ while (i < MAX_PATH_INDEX)
+ {
+ if (p->index[i] != -1)
+ num++; // count path node if it's used
+
+ i++;
+ }
+
+ p = p->next; // go to next node in linked list
+ }
+
+ fwrite(&num, sizeof(num), 1, bfp); // write the count
+
+ // now write out each path index...
+
+ p = paths[index];
+
+ while (p != NULL)
+ {
+ i = 0;
+
+ while (i < MAX_PATH_INDEX)
+ {
+ if (p->index[i] != -1) // save path node if it's used
+ fwrite(&p->index[i], sizeof(p->index[0]), 1, bfp);
+
+ i++;
+ }
+
+ p = p->next; // go to next node in linked list
+ }
+ }
+
+ fclose(bfp);
+}
+
+
+bool WaypointReachable(Vector v_src, Vector v_dest, edict_t *pEntity)
+{
+ TraceResult tr;
+ float curr_height, last_height;
+
+ float distance = (v_dest - v_src).Length();
+
+ // is the destination close enough?
+ if (distance < REACHABLE_RANGE)
+ {
+ // check if this waypoint is "visible"...
+
+ UTIL_TraceLine( v_src, v_dest, ignore_monsters,
+ pEntity->v.pContainingEntity, &tr );
+
+ // if waypoint is visible from current position (even behind head)...
+ if (tr.flFraction >= 1.0)
+ {
+ // check for special case of both waypoints being underwater...
+ if ((POINT_CONTENTS( v_src ) == CONTENTS_WATER) &&
+ (POINT_CONTENTS( v_dest ) == CONTENTS_WATER))
+ {
+ return TRUE;
+ }
+
+ // check for special case of waypoint being suspended in mid-air...
+
+ // is dest waypoint higher than src? (45 is max jump height)
+ if (v_dest.z > (v_src.z + 45.0))
+ {
+ Vector v_new_src = v_dest;
+ Vector v_new_dest = v_dest;
+
+ v_new_dest.z = v_new_dest.z - 50; // straight down 50 units
+
+ UTIL_TraceLine(v_new_src, v_new_dest, dont_ignore_monsters,
+ pEntity->v.pContainingEntity, &tr);
+
+ // check if we didn't hit anything, if not then it's in mid-air
+ if (tr.flFraction >= 1.0)
+ {
+ return FALSE; // can't reach this one
+ }
+ }
+
+ // check if distance to ground increases more than jump height
+ // at points between source and destination...
+
+ Vector v_direction = (v_dest - v_src).Normalize(); // 1 unit long
+ Vector v_check = v_src;
+ Vector v_down = v_src;
+
+ v_down.z = v_down.z - 1000.0; // straight down 1000 units
+
+ UTIL_TraceLine(v_check, v_down, ignore_monsters,
+ pEntity->v.pContainingEntity, &tr);
+
+ last_height = tr.flFraction * 1000.0; // height from ground
+
+ distance = (v_dest - v_check).Length(); // distance from goal
+
+ while (distance > 10.0)
+ {
+ // move 10 units closer to the goal...
+ v_check = v_check + (v_direction * 10.0);
+
+ v_down = v_check;
+ v_down.z = v_down.z - 1000.0; // straight down 1000 units
+
+ UTIL_TraceLine(v_check, v_down, ignore_monsters,
+ pEntity->v.pContainingEntity, &tr);
+
+ curr_height = tr.flFraction * 1000.0; // height from ground
+
+ // is the difference in the last height and the current height
+ // higher that the jump height?
+ if ((last_height - curr_height) > 45.0)
+ {
+ // can't get there from here...
+ return FALSE;
+ }
+
+ last_height = curr_height;
+
+ distance = (v_dest - v_check).Length(); // distance from goal
+ }
+
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+
+// find the nearest reachable waypoint
+int WaypointFindReachable(edict_t *pEntity, float range, int team)
+{
+ int i, min_index;
+ float distance;
+ float min_distance;
+ TraceResult tr;
+
+ // find the nearest waypoint...
+
+ min_distance = 9999.0;
+
+ for (i=0; i < num_waypoints; i++)
+ {
+ if (waypoints[i].flags & W_FL_DELETED)
+ continue; // skip any deleted waypoints
+
+ if (waypoints[i].flags & W_FL_AIMING)
+ continue; // skip any aiming waypoints
+
+ // skip this waypoint if it's team specific and teams don't match...
+ if ((team != -1) && (waypoints[i].flags & W_FL_TEAM_SPECIFIC) &&
+ ((waypoints[i].flags & W_FL_TEAM) != team))
+ continue;
+
+ distance = (waypoints[i].origin - pEntity->v.origin).Length();
+
+ if (distance < min_distance)
+ {
+ // if waypoint is visible from current position (even behind head)...
+ UTIL_TraceLine( pEntity->v.origin + pEntity->v.view_ofs, waypoints[i].origin,
+ ignore_monsters, pEntity->v.pContainingEntity, &tr );
+
+ if (tr.flFraction >= 1.0)
+ {
+ if (WaypointReachable(pEntity->v.origin, waypoints[i].origin, pEntity))
+ {
+ min_index = i;
+ min_distance = distance;
+ }
+ }
+ }
+ }
+
+ // if not close enough to a waypoint then just return
+ if (min_distance > range)
+ return -1;
+
+ return min_index;
+
+}
+
+
+void WaypointPrintInfo(edict_t *pEntity)
+{
+ char msg[80];
+ int index;
+ int flags;
+
+ // find the nearest waypoint...
+ index = WaypointFindNearest(pEntity, 50.0, -1);
+
+ if (index == -1)
+ return;
+
+ sprintf(msg,"Waypoint %d of %d total\n", index, num_waypoints);
+ ClientPrint(pEntity, HUD_PRINTNOTIFY, msg);
+
+ flags = waypoints[index].flags;
+
+ if (flags & W_FL_TEAM_SPECIFIC)
+ {
+ if (mod_id == FRONTLINE_DLL)
+ {
+ if ((flags & W_FL_TEAM) == 0)
+ strcpy(msg, "Waypoint is for Attackers\n");
+ else if ((flags & W_FL_TEAM) == 1)
+ strcpy(msg, "Waypoint is for Defenders\n");
+ }
+ else
+ {
+ if ((flags & W_FL_TEAM) == 0)
+ strcpy(msg, "Waypoint is for TEAM 1\n");
+ else if ((flags & W_FL_TEAM) == 1)
+ strcpy(msg, "Waypoint is for TEAM 2\n");
+ else if ((flags & W_FL_TEAM) == 2)
+ strcpy(msg, "Waypoint is for TEAM 3\n");
+ else if ((flags & W_FL_TEAM) == 3)
+ strcpy(msg, "Waypoint is for TEAM 4\n");
+ }
+
+ ClientPrint(pEntity, HUD_PRINTNOTIFY, msg);
+ }
+
+ if (flags & W_FL_LIFT)
+ ClientPrint(pEntity, HUD_PRINTNOTIFY, "Bot will wait for lift before approaching\n");
+
+ if (flags & W_FL_LADDER)
+ ClientPrint(pEntity, HUD_PRINTNOTIFY, "This waypoint is on a ladder\n");
+
+ if (flags & W_FL_DOOR)
+ ClientPrint(pEntity, HUD_PRINTNOTIFY, "This is a door waypoint\n");
+
+ if (flags & W_FL_HEALTH)
+ ClientPrint(pEntity, HUD_PRINTNOTIFY, "There is health near this waypoint\n");
+
+ if (flags & W_FL_ARMOR)
+ ClientPrint(pEntity, HUD_PRINTNOTIFY, "There is armor near this waypoint\n");
+
+ if (flags & W_FL_AMMO)
+ ClientPrint(pEntity, HUD_PRINTNOTIFY, "There is ammo near this waypoint\n");
+
+ if (flags & W_FL_SNIPER)
+ ClientPrint(pEntity, HUD_PRINTNOTIFY, "This is a sniper waypoint\n");
+
+ if (flags & W_FL_TFC_FLAG)
+ {
+ if (mod_id == FRONTLINE_DLL)
+ ClientPrint(pEntity, HUD_PRINTNOTIFY, "There is a capture point near this waypoint\n");
+ else
+ ClientPrint(pEntity, HUD_PRINTNOTIFY, "There is a flag near this waypoint\n");
+ }
+
+ if (flags & W_FL_TFC_FLAG_GOAL)
+ {
+ if (mod_id == FRONTLINE_DLL)
+ ClientPrint(pEntity, HUD_PRINTNOTIFY, "This is a defender location\n");
+ else
+ ClientPrint(pEntity, HUD_PRINTNOTIFY, "There is a flag goal near this waypoint\n");
+ }
+
+ if (flags & W_FL_PRONE)
+ ClientPrint(pEntity, HUD_PRINTNOTIFY, "Bot will go prone here\n");
+}
+
+
+void WaypointThink(edict_t *pEntity)
+{
+ float distance, min_distance;
+ Vector start, end;
+ int i, index;
+
+ if (g_auto_waypoint) // is auto waypoint on?
+ {
+ // find the distance from the last used waypoint
+ distance = (last_waypoint - pEntity->v.origin).Length();
+
+ if (distance > 200)
+ {
+ min_distance = 9999.0;
+
+ // check that no other reachable waypoints are nearby...
+ for (i=0; i < num_waypoints; i++)
+ {
+ if (waypoints[i].flags & W_FL_DELETED)
+ continue;
+
+ if (waypoints[i].flags & W_FL_AIMING)
+ continue;
+
+ if (WaypointReachable(pEntity->v.origin, waypoints[i].origin, pEntity))
+ {
+ distance = (waypoints[i].origin - pEntity->v.origin).Length();
+
+ if (distance < min_distance)
+ min_distance = distance;
+ }
+ }
+
+ // make sure nearest waypoint is far enough away...
+ if (min_distance >= 200)
+ WaypointAdd(pEntity); // place a waypoint here
+ }
+ }
+
+ min_distance = 9999.0;
+
+ if (g_waypoint_on) // display the waypoints if turned on...
+ {
+ for (i=0; i < num_waypoints; i++)
+ {
+ if ((waypoints[i].flags & W_FL_DELETED) == W_FL_DELETED)
+ continue;
+
+ distance = (waypoints[i].origin - pEntity->v.origin).Length();
+
+ if (distance < 500)
+ {
+ if (distance < min_distance)
+ {
+ index = i; // store index of nearest waypoint
+ min_distance = distance;
+ }
+
+ if ((wp_display_time[i] + 1.0) < gpGlobals->time)
+ {
+ if (waypoints[i].flags & W_FL_CROUCH)
+ {
+ start = waypoints[i].origin - Vector(0, 0, 17);
+ end = start + Vector(0, 0, 34);
+ }
+ else if (waypoints[i].flags & W_FL_AIMING)
+ {
+ start = waypoints[i].origin + Vector(0, 0, 10);
+ end = start + Vector(0, 0, 14);
+ }
+ else
+ {
+ start = waypoints[i].origin - Vector(0, 0, 34);
+ end = start + Vector(0, 0, 68);
+ }
+
+ // draw a blue waypoint
+ WaypointDrawBeam(pEntity, start, end, 30, 0, 0, 0, 255, 250, 5);
+
+ wp_display_time[i] = gpGlobals->time;
+ }
+ }
+ }
+
+ // check if path waypointing is on...
+ if (g_path_waypoint)
+ {
+ // check if player is close enough to a waypoint and time to draw path...
+ if ((min_distance <= 50) && (f_path_time <= gpGlobals->time))
+ {
+ PATH *p;
+
+ f_path_time = gpGlobals->time + 1.0;
+
+ p = paths[index];
+
+ while (p != NULL)
+ {
+ i = 0;
+
+ while (i < MAX_PATH_INDEX)
+ {
+ if (p->index[i] != -1)
+ {
+ Vector v_src = waypoints[index].origin;
+ Vector v_dest = waypoints[p->index[i]].origin;
+
+ // draw a white line to this index's waypoint
+ WaypointDrawBeam(pEntity, v_src, v_dest, 10, 2, 250, 250, 250, 200, 10);
+ }
+
+ i++;
+ }
+
+ p = p->next; // go to next node in linked list
+ }
+ }
+ }
+ }
+}
+
+
+// run Floyd's algorithm on the waypoint list to generate the least cost
+// path matrix...
+void WaypointFloyds(unsigned short *shortest_path, unsigned short *from_to)
+{
+ unsigned int x, y, z;
+ int changed = 1;
+ int distance;
+
+ for (y=0; y < route_num_waypoints; y++)
+ {
+ for (z=0; z < route_num_waypoints; z++)
+ {
+ from_to[y * route_num_waypoints + z] = z;
+ }
+ }
+
+ while (changed)
+ {
+ changed = 0;
+
+ for (x=0; x < route_num_waypoints; x++)
+ {
+ for (y=0; y < route_num_waypoints; y++)
+ {
+ for (z=0; z < route_num_waypoints; z++)
+ {
+ if ((shortest_path[y * route_num_waypoints + x] == WAYPOINT_UNREACHABLE) ||
+ (shortest_path[x * route_num_waypoints + z] == WAYPOINT_UNREACHABLE))
+ continue;
+
+ distance = shortest_path[y * route_num_waypoints + x] +
+ shortest_path[x * route_num_waypoints + z];
+
+ if (distance > WAYPOINT_MAX_DISTANCE)
+ distance = WAYPOINT_MAX_DISTANCE;
+
+ if ((distance < shortest_path[y * route_num_waypoints + z]) ||
+ (shortest_path[y * route_num_waypoints + z] == WAYPOINT_UNREACHABLE))
+ {
+ shortest_path[y * route_num_waypoints + z] = distance;
+ from_to[y * route_num_waypoints + z] = from_to[y * route_num_waypoints + x];
+ changed = 1;
+ }
+ }
+ }
+ }
+ }
+}
+
+
+// load the waypoint route files (.wp1, .wp2, etc.) or generate them if
+// they don't exist...
+void WaypointRouteInit(void)
+{
+ unsigned int index;
+ bool build_matrix[4];
+ int matrix;
+ unsigned int array_size;
+ unsigned int row;
+ int i, offset;
+ unsigned int a, b;
+ float distance;
+ unsigned short *pShortestPath, *pFromTo;
+ char msg[80];
+ unsigned int num_items;
+ FILE *bfp;
+ char filename[256];
+ char filename2[256];
+ char mapname[64];
+
+ if (num_waypoints == 0)
+ return;
+
+ // save number of current waypoints in case waypoints get added later
+ route_num_waypoints = num_waypoints;
+
+ strcpy(mapname, STRING(gpGlobals->mapname));
+ strcat(mapname, ".wpt");
+
+ UTIL_BuildFileName(filename, "maps", mapname);
+
+ build_matrix[0] = TRUE; // always build matrix 0 (non-team and team 1)
+ build_matrix[1] = FALSE;
+ build_matrix[2] = FALSE;
+ build_matrix[3] = FALSE;
+
+ // find out how many route matrixes to create...
+ for (index=0; index < route_num_waypoints; index++)
+ {
+ if (waypoints[index].flags & W_FL_TEAM_SPECIFIC)
+ {
+ if ((waypoints[index].flags & W_FL_TEAM) == 0x01) // team 2?
+ build_matrix[1] = TRUE;
+
+ if ((waypoints[index].flags & W_FL_TEAM) == 0x02) // team 3?
+ build_matrix[2] = TRUE;
+
+ if ((waypoints[index].flags & W_FL_TEAM) == 0x03) // team 4?
+ build_matrix[3] = TRUE;
+ }
+ }
+
+ array_size = route_num_waypoints * route_num_waypoints;
+
+ for (matrix=0; matrix < 4; matrix++)
+ {
+ if (build_matrix[matrix])
+ {
+ char ext_str[5]; // ".wpX\0"
+ int file1, file2;
+ struct stat stat1, stat2;
+
+ sprintf(ext_str, ".wp%d", matrix+1);
+
+ strcpy(mapname, STRING(gpGlobals->mapname));
+ strcat(mapname, ext_str);
+
+ UTIL_BuildFileName(filename2, "maps", mapname);
+
+ if (access(filename2, 0) == 0) // does the .wpX file exist?
+ {
+ file1 = open(filename, O_RDONLY);
+ file2 = open(filename2, O_RDONLY);
+
+ fstat(file1, &stat1);
+ fstat(file2, &stat2);
+
+ close(file1);
+ close(file2);
+
+ if (stat1.st_mtime < stat2.st_mtime) // is .wpt older than .wpX file?
+ {
+ sprintf(msg, "loading HPB bot waypoint paths for team %d\n", matrix+1);
+ ALERT(at_console, msg);
+
+ shortest_path[matrix] = (unsigned short *)malloc(sizeof(unsigned short) * array_size);
+
+ if (shortest_path[matrix] == NULL)
+ ALERT(at_error, "HPB_bot - Error allocating memory for shortest path!");
+
+ from_to[matrix] = (unsigned short *)malloc(sizeof(unsigned short) * array_size);
+
+ if (from_to[matrix] == NULL)
+ ALERT(at_error, "HPB_bot - Error allocating memory for from to matrix!");
+
+ bfp = fopen(filename2, "rb");
+
+ if (bfp != NULL)
+ {
+ num_items = fread(shortest_path[matrix], sizeof(unsigned short), array_size, bfp);
+
+ if (num_items != array_size)
+ {
+ // if couldn't read enough data, free memory to recalculate it
+
+ ALERT(at_console, "error reading enough path items, recalculating...\n");
+
+ free(shortest_path[matrix]);
+ shortest_path[matrix] = NULL;
+
+ free(from_to[matrix]);
+ from_to[matrix] = NULL;
+ }
+ else
+ {
+ num_items = fread(from_to[matrix], sizeof(unsigned short), array_size, bfp);
+
+ if (num_items != array_size)
+ {
+ // if couldn't read enough data, free memory to recalculate it
+
+ ALERT(at_console, "error reading enough path items, recalculating...\n");
+
+ free(shortest_path[matrix]);
+ shortest_path[matrix] = NULL;
+
+ free(from_to[matrix]);
+ from_to[matrix] = NULL;
+ }
+ }
+ }
+ else
+ {
+ ALERT(at_console, "HPB_bot - Error reading waypoint paths!\n");
+
+ free(shortest_path[matrix]);
+ shortest_path[matrix] = NULL;
+
+ free(from_to[matrix]);
+ from_to[matrix] = NULL;
+ }
+
+ fclose(bfp);
+ }
+ }
+
+ if (shortest_path[matrix] == NULL)
+ {
+ sprintf(msg, "calculating HPB bot waypoint paths for team %d...\n", matrix+1);
+ ALERT(at_console, msg);
+
+ shortest_path[matrix] = (unsigned short *)malloc(sizeof(unsigned short) * array_size);
+
+ if (shortest_path[matrix] == NULL)
+ ALERT(at_error, "HPB_bot - Error allocating memory for shortest path!");
+
+ from_to[matrix] = (unsigned short *)malloc(sizeof(unsigned short) * array_size);
+
+ if (from_to[matrix] == NULL)
+ ALERT(at_error, "HPB_bot - Error allocating memory for from to matrix!");
+
+ pShortestPath = shortest_path[matrix];
+ pFromTo = from_to[matrix];
+
+ for (index=0; index < array_size; index++)
+ pShortestPath[index] = WAYPOINT_UNREACHABLE;
+
+ for (index=0; index < route_num_waypoints; index++)
+ pShortestPath[index * route_num_waypoints + index] = 0; // zero diagonal
+
+ for (row=0; row < route_num_waypoints; row++)
+ {
+ if (paths[row] != NULL)
+ {
+ PATH *p = paths[row];
+
+ while (p)
+ {
+ i = 0;
+
+ while (i < MAX_PATH_INDEX)
+ {
+ if (p->index[i] != -1)
+ {
+ index = p->index[i];
+
+ // check if this is NOT team specific OR matches this team
+ if (!(waypoints[index].flags & W_FL_TEAM_SPECIFIC) ||
+ ((waypoints[index].flags & W_FL_TEAM) == matrix))
+ {
+ distance = (waypoints[row].origin - waypoints[index].origin).Length();
+
+ if (distance > (float)WAYPOINT_MAX_DISTANCE)
+ distance = (float)WAYPOINT_MAX_DISTANCE;
+
+ if (distance > REACHABLE_RANGE)
+ {
+ sprintf(msg, "Waypoint path distance > %4.1f at from %d to %d\n",
+ REACHABLE_RANGE, row, index);
+ ALERT(at_console, msg);
+ }
+ else
+ {
+ offset = row * route_num_waypoints + index;
+
+ pShortestPath[offset] = (unsigned short)distance;
+ }
+ }
+ }
+
+ i++;
+ }
+
+ p = p->next; // go to next node in linked list
+ }
+ }
+ }
+
+ // run Floyd's Algorithm to generate the from_to matrix...
+ WaypointFloyds(pShortestPath, pFromTo);
+
+ for (a=0; a < route_num_waypoints; a++)
+ {
+ for (b=0; b < route_num_waypoints; b++)
+ if (pShortestPath[a * route_num_waypoints + b] == WAYPOINT_UNREACHABLE)
+ pFromTo[a * route_num_waypoints + b] = WAYPOINT_UNREACHABLE;
+ }
+
+ bfp = fopen(filename2, "wb");
+
+ if (bfp != NULL)
+ {
+ num_items = fwrite(shortest_path[matrix], sizeof(unsigned short), array_size, bfp);
+
+ if (num_items != array_size)
+ {
+ // if couldn't write enough data, close file and delete it
+
+ fclose(bfp);
+ unlink(filename2);
+ }
+ else
+ {
+ num_items = fwrite(from_to[matrix], sizeof(unsigned short), array_size, bfp);
+
+ fclose(bfp);
+
+ if (num_items != array_size)
+ {
+ // if couldn't write enough data, delete file
+ unlink(filename2);
+ }
+ }
+ }
+ else
+ {
+ ALERT(at_console, "HPB_bot - Error writing waypoint paths!\n");
+ }
+
+ sprintf(msg, "HPB bot waypoint path calculations for team %d complete!\n",matrix+1);
+ ALERT(at_console, msg);
+ }
+ }
+ }
+
+}
+
+
+// return the next waypoint index for a path from the Floyd matrix when
+// going from a source waypoint index (src) to a destination waypoint
+// index (dest)...
+unsigned short WaypointRouteFromTo(int src, int dest, int team)
+{
+ unsigned short *pFromTo;
+
+ if ((team < -1) || (team > 3))
+ return -1;
+
+ if (team == -1) // -1 means non-team play
+ team = 0;
+
+ if (from_to[team] == NULL) // if no team specific waypoints use team 0
+ team = 0;
+
+ if (from_to[team] == NULL) // if no route information just return
+ return -1;
+
+ pFromTo = from_to[team];
+
+ return pFromTo[src * route_num_waypoints + dest];
+}
+
+
+// return the total distance (based on the Floyd matrix) of a path from
+// the source waypoint index (src) to the destination waypoint index
+// (dest)...
+int WaypointDistanceFromTo(int src, int dest, int team)
+{
+ unsigned short *pShortestPath;
+
+ if ((team < -1) || (team > 3))
+ return -1;
+
+ if (team == -1) // -1 means non-team play
+ team = 0;
+
+ if (from_to[team] == NULL) // if no team specific waypoints use team 0
+ team = 0;
+
+ if (from_to[team] == NULL) // if no route information just return
+ return -1;
+
+ pShortestPath = shortest_path[team];
+
+ return (int)(pShortestPath[src * route_num_waypoints + dest]);
+}
+
diff --git a/main/source/HPB_bot/dlls/waypoint.h b/main/source/HPB_bot/dlls/waypoint.h
index dc84707c..bdb7f8aa 100644
--- a/main/source/HPB_bot/dlls/waypoint.h
+++ b/main/source/HPB_bot/dlls/waypoint.h
@@ -1,104 +1,104 @@
-//
-// HPB_bot - botman's High Ping Bastard bot
-//
-// (http://planethalflife.com/botman/)
-//
-// waypoint.h
-//
-
-#ifndef WAYPOINT_H
-#define WAYPOINT_H
-
-#include
-
-#define MAX_WAYPOINTS 1024
-
-#define REACHABLE_RANGE 400.0
-
-// defines for waypoint flags field (32 bits are available)
-#define W_FL_TEAM ((1<<0) + (1<<1)) /* allow for 4 teams (0-3) */
-#define W_FL_TEAM_SPECIFIC (1<<2) /* waypoint only for specified team */
-#define W_FL_CROUCH (1<<3) /* must crouch to reach this waypoint */
-#define W_FL_LADDER (1<<4) /* waypoint on a ladder */
-#define W_FL_LIFT (1<<5) /* wait for lift to be down before approaching this waypoint */
-#define W_FL_DOOR (1<<6) /* wait for door to open */
-#define W_FL_HEALTH (1<<7) /* health kit (or wall mounted) location */
-#define W_FL_ARMOR (1<<8) /* armor (or HEV) location */
-#define W_FL_AMMO (1<<9) /* ammo location */
-#define W_FL_SNIPER (1<<10) /* sniper waypoint (a good sniper spot) */
-
-#define W_FL_TFC_FLAG (1<<11) /* flag position (or hostage or president) */
-#define W_FL_FLF_CAP (1<<11) /* Front Line Force capture point */
-
-#define W_FL_TFC_FLAG_GOAL (1<<12) /* flag return position (or rescue zone) */
-#define W_FL_FLF_DEFEND (1<<12) /* Front Line Force defend point */
-
-#define W_FL_PRONE (1<<13) /* go prone (laying down) */
-#define W_FL_AIMING (1<<14) /* aiming waypoint */
-
-#define W_FL_DELETED (1<<31) /* used by waypoint allocation code */
-
-
-#define WAYPOINT_VERSION 4
-
-// define the waypoint file header structure...
-typedef struct {
- char filetype[8]; // should be "HPB_bot\0"
- int waypoint_file_version;
- int waypoint_file_flags; // not currently used
- int number_of_waypoints;
- char mapname[32]; // name of map for these waypoints
-} WAYPOINT_HDR;
-
-
-// define the structure for waypoints...
-typedef struct {
- int flags; // button, lift, flag, health, ammo, etc.
- Vector origin; // location
-} WAYPOINT;
-
-
-
-#define WAYPOINT_UNREACHABLE USHRT_MAX
-#define WAYPOINT_MAX_DISTANCE (USHRT_MAX-1)
-
-#define MAX_PATH_INDEX 4
-
-// define the structure for waypoint paths (paths are connections between
-// two waypoint nodes that indicates the bot can get from point A to point B.
-// note that paths DON'T have to be two-way. sometimes they are just one-way
-// connections between two points. There is an array called "paths" that
-// contains head pointers to these structures for each waypoint index.
-typedef struct path {
- short int index[MAX_PATH_INDEX]; // indexes of waypoints (index -1 means not used)
- struct path *next; // link to next structure
-} PATH;
-
-
-// waypoint function prototypes...
-void WaypointInit(void);
-int WaypointFindPath(PATH **pPath, int *path_index, int waypoint_index, int team);
-int WaypointFindNearest(edict_t *pEntity, float distance, int team);
-int WaypointFindNearest(Vector v_src, edict_t *pEntity, float range, int team);
-int WaypointFindNearestGoal(edict_t *pEntity, int src, int team, int flags);
-int WaypointFindNearestGoal(Vector v_src, edict_t *pEntity, float range, int team, int flags);
-int WaypointFindRandomGoal(edict_t *pEntity, int team, int flags);
-int WaypointFindRandomGoal(Vector v_src, edict_t *pEntity, float range, int team, int flags);
-int WaypointFindNearestAiming(Vector v_origin);
-void WaypointAdd(edict_t *pEntity);
-void WaypointAddAiming(edict_t *pEntity);
-void WaypointDelete(edict_t *pEntity);
-void WaypointCreatePath(edict_t *pEntity, int cmd);
-void WaypointRemovePath(edict_t *pEntity, int cmd);
-bool WaypointLoad(edict_t *pEntity);
-void WaypointSave(void);
-bool WaypointReachable(Vector v_srv, Vector v_dest, edict_t *pEntity);
-int WaypointFindReachable(edict_t *pEntity, float range, int team);
-void WaypointPrintInfo(edict_t *pEntity);
-void WaypointThink(edict_t *pEntity);
-void WaypointFloyds(short *shortest_path, short *from_to);
-void WaypointRouteInit(void);
-unsigned short WaypointRouteFromTo(int src, int dest, int team);
-int WaypointDistanceFromTo(int src, int dest, int team);
-
-#endif // WAYPOINT_H
+//
+// HPB_bot - botman's High Ping Bastard bot
+//
+// (http://planethalflife.com/botman/)
+//
+// waypoint.h
+//
+
+#ifndef WAYPOINT_H
+#define WAYPOINT_H
+
+#include
+
+#define MAX_WAYPOINTS 1024
+
+#define REACHABLE_RANGE 400.0
+
+// defines for waypoint flags field (32 bits are available)
+#define W_FL_TEAM ((1<<0) + (1<<1)) /* allow for 4 teams (0-3) */
+#define W_FL_TEAM_SPECIFIC (1<<2) /* waypoint only for specified team */
+#define W_FL_CROUCH (1<<3) /* must crouch to reach this waypoint */
+#define W_FL_LADDER (1<<4) /* waypoint on a ladder */
+#define W_FL_LIFT (1<<5) /* wait for lift to be down before approaching this waypoint */
+#define W_FL_DOOR (1<<6) /* wait for door to open */
+#define W_FL_HEALTH (1<<7) /* health kit (or wall mounted) location */
+#define W_FL_ARMOR (1<<8) /* armor (or HEV) location */
+#define W_FL_AMMO (1<<9) /* ammo location */
+#define W_FL_SNIPER (1<<10) /* sniper waypoint (a good sniper spot) */
+
+#define W_FL_TFC_FLAG (1<<11) /* flag position (or hostage or president) */
+#define W_FL_FLF_CAP (1<<11) /* Front Line Force capture point */
+
+#define W_FL_TFC_FLAG_GOAL (1<<12) /* flag return position (or rescue zone) */
+#define W_FL_FLF_DEFEND (1<<12) /* Front Line Force defend point */
+
+#define W_FL_PRONE (1<<13) /* go prone (laying down) */
+#define W_FL_AIMING (1<<14) /* aiming waypoint */
+
+#define W_FL_DELETED (1<<31) /* used by waypoint allocation code */
+
+
+#define WAYPOINT_VERSION 4
+
+// define the waypoint file header structure...
+typedef struct {
+ char filetype[8]; // should be "HPB_bot\0"
+ int waypoint_file_version;
+ int waypoint_file_flags; // not currently used
+ int number_of_waypoints;
+ char mapname[32]; // name of map for these waypoints
+} WAYPOINT_HDR;
+
+
+// define the structure for waypoints...
+typedef struct {
+ int flags; // button, lift, flag, health, ammo, etc.
+ Vector origin; // location
+} WAYPOINT;
+
+
+
+#define WAYPOINT_UNREACHABLE USHRT_MAX
+#define WAYPOINT_MAX_DISTANCE (USHRT_MAX-1)
+
+#define MAX_PATH_INDEX 4
+
+// define the structure for waypoint paths (paths are connections between
+// two waypoint nodes that indicates the bot can get from point A to point B.
+// note that paths DON'T have to be two-way. sometimes they are just one-way
+// connections between two points. There is an array called "paths" that
+// contains head pointers to these structures for each waypoint index.
+typedef struct path {
+ short int index[MAX_PATH_INDEX]; // indexes of waypoints (index -1 means not used)
+ struct path *next; // link to next structure
+} PATH;
+
+
+// waypoint function prototypes...
+void WaypointInit(void);
+int WaypointFindPath(PATH **pPath, int *path_index, int waypoint_index, int team);
+int WaypointFindNearest(edict_t *pEntity, float distance, int team);
+int WaypointFindNearest(Vector v_src, edict_t *pEntity, float range, int team);
+int WaypointFindNearestGoal(edict_t *pEntity, int src, int team, int flags);
+int WaypointFindNearestGoal(Vector v_src, edict_t *pEntity, float range, int team, int flags);
+int WaypointFindRandomGoal(edict_t *pEntity, int team, int flags);
+int WaypointFindRandomGoal(Vector v_src, edict_t *pEntity, float range, int team, int flags);
+int WaypointFindNearestAiming(Vector v_origin);
+void WaypointAdd(edict_t *pEntity);
+void WaypointAddAiming(edict_t *pEntity);
+void WaypointDelete(edict_t *pEntity);
+void WaypointCreatePath(edict_t *pEntity, int cmd);
+void WaypointRemovePath(edict_t *pEntity, int cmd);
+bool WaypointLoad(edict_t *pEntity);
+void WaypointSave(void);
+bool WaypointReachable(Vector v_srv, Vector v_dest, edict_t *pEntity);
+int WaypointFindReachable(edict_t *pEntity, float range, int team);
+void WaypointPrintInfo(edict_t *pEntity);
+void WaypointThink(edict_t *pEntity);
+void WaypointFloyds(short *shortest_path, short *from_to);
+void WaypointRouteInit(void);
+unsigned short WaypointRouteFromTo(int src, int dest, int team);
+int WaypointDistanceFromTo(int src, int dest, int team);
+
+#endif // WAYPOINT_H
diff --git a/main/source/HPB_bot/engine/engine.h b/main/source/HPB_bot/engine/engine.h
index 02a2c4ee..8d0bb22a 100644
--- a/main/source/HPB_bot/engine/engine.h
+++ b/main/source/HPB_bot/engine/engine.h
@@ -1,156 +1,156 @@
-//
-// HPB_bot - botman's High Ping Bastard bot
-//
-// (http://planethalflife.com/botman/)
-//
-// engine.h
-//
-
-#ifndef ENGINE_H
-#define ENGINE_H
-
-// engine prototypes (from engine\eiface.h)...
-int pfnPrecacheModel( char* s );
-int pfnPrecacheSound( char* s );
-void pfnSetModel( edict_t *e, const char *m );
-int pfnModelIndex( const char *m );
-int pfnModelFrames( int modelIndex );
-void pfnSetSize( edict_t *e, const float *rgflMin, const float *rgflMax );
-void pfnChangeLevel( char* s1, char* s2 );
-void pfnGetSpawnParms( edict_t *ent );
-void pfnSaveSpawnParms( edict_t *ent );
-float pfnVecToYaw( const float *rgflVector );
-void pfnVecToAngles( const float *rgflVectorIn, float *rgflVectorOut );
-void pfnMoveToOrigin( edict_t *ent, const float *pflGoal, float dist, int iMoveType );
-void pfnChangeYaw( edict_t* ent );
-void pfnChangePitch( edict_t* ent );
-edict_t* pfnFindEntityByString( edict_t *pEdictStartSearchAfter, const char *pszField, const char *pszValue );
-int pfnGetEntityIllum( edict_t* pEnt );
-edict_t* pfnFindEntityInSphere( edict_t *pEdictStartSearchAfter, const float *org, float rad );
-edict_t* pfnFindClientInPVS( edict_t *pEdict );
-edict_t* pfnEntitiesInPVS( edict_t *pplayer );
-void pfnMakeVectors( const float *rgflVector );
-void pfnAngleVectors( const float *rgflVector, float *forward, float *right, float *up );
-edict_t* pfnCreateEntity( void );
-void pfnRemoveEntity( edict_t* e );
-edict_t* pfnCreateNamedEntity( int className );
-void pfnMakeStatic( edict_t *ent );
-int pfnEntIsOnFloor( edict_t *e );
-int pfnDropToFloor( edict_t* e );
-int pfnWalkMove( edict_t *ent, float yaw, float dist, int iMode );
-void pfnSetOrigin( edict_t *e, const float *rgflOrigin );
-void pfnEmitSound( edict_t *entity, int channel, const char *sample, /*int*/float volume, float attenuation, int fFlags, int pitch );
-void pfnEmitAmbientSound( edict_t *entity, float *pos, const char *samp, float vol, float attenuation, int fFlags, int pitch );
-void pfnTraceLine( const float *v1, const float *v2, int fNoMonsters, edict_t *pentToSkip, TraceResult *ptr );
-void pfnTraceToss( edict_t* pent, edict_t* pentToIgnore, TraceResult *ptr );
-int pfnTraceMonsterHull( edict_t *pEdict, const float *v1, const float *v2, int fNoMonsters, edict_t *pentToSkip, TraceResult *ptr );
-void pfnTraceHull( const float *v1, const float *v2, int fNoMonsters, int hullNumber, edict_t *pentToSkip, TraceResult *ptr );
-void pfnTraceModel( const float *v1, const float *v2, int hullNumber, edict_t *pent, TraceResult *ptr );
-const char *pfnTraceTexture( edict_t *pTextureEntity, const float *v1, const float *v2 );
-void pfnTraceSphere( const float *v1, const float *v2, int fNoMonsters, float radius, edict_t *pentToSkip, TraceResult *ptr );
-void pfnGetAimVector( edict_t* ent, float speed, float *rgflReturn );
-void pfnServerCommand( char* str );
-void pfnServerExecute( void );
-void pfnClientCommand( edict_t* pEdict, char* szFmt, ... );
-void pfnParticleEffect( const float *org, const float *dir, float color, float count );
-void pfnLightStyle( int style, char* val );
-int pfnDecalIndex( const char *name );
-int pfnPointContents( const float *rgflVector );
-void pfnMessageBegin( int msg_dest, int msg_type, const float *pOrigin, edict_t *ed );
-void pfnMessageEnd( void );
-void pfnWriteByte( int iValue );
-void pfnWriteChar( int iValue );
-void pfnWriteShort( int iValue );
-void pfnWriteLong( int iValue );
-void pfnWriteAngle( float flValue );
-void pfnWriteCoord( float flValue );
-void pfnWriteString( const char *sz );
-void pfnWriteEntity( int iValue );
-void pfnCVarRegister( cvar_t *pCvar );
-float pfnCVarGetFloat( const char *szVarName );
-const char* pfnCVarGetString( const char *szVarName );
-void pfnCVarSetFloat( const char *szVarName, float flValue );
-void pfnCVarSetString( const char *szVarName, const char *szValue );
-void pfnAlertMessage( ALERT_TYPE atype, char *szFmt, ... );
-void pfnEngineFprintf( FILE *pfile, char *szFmt, ... );
-void* pfnPvAllocEntPrivateData( edict_t *pEdict, long cb );
-void* pfnPvEntPrivateData( edict_t *pEdict );
-void pfnFreeEntPrivateData( edict_t *pEdict );
-const char* pfnSzFromIndex( int iString );
-int pfnAllocString( const char *szValue );
-struct entvars_s* pfnGetVarsOfEnt( edict_t *pEdict );
-edict_t* pfnPEntityOfEntOffset( int iEntOffset );
-int pfnEntOffsetOfPEntity( const edict_t *pEdict );
-int pfnIndexOfEdict( const edict_t *pEdict );
-edict_t* pfnPEntityOfEntIndex( int iEntIndex );
-edict_t* pfnFindEntityByVars( struct entvars_s* pvars );
-void* pfnGetModelPtr( edict_t* pEdict );
-int pfnRegUserMsg( const char *pszName, int iSize );
-void pfnAnimationAutomove( const edict_t* pEdict, float flTime );
-void pfnGetBonePosition( const edict_t* pEdict, int iBone, float *rgflOrigin, float *rgflAngles );
-unsigned long pfnFunctionFromName( const char *pName );
-const char *pfnNameForFunction( unsigned long function );
-void pfnClientPrintf( edict_t* pEdict, PRINT_TYPE ptype, const char *szMsg );
-void pfnServerPrint( const char *szMsg );
-const char *pfnCmd_Args( void );
-const char *pfnCmd_Argv( int argc );
-int pfnCmd_Argc( void );
-void pfnGetAttachment( const edict_t *pEdict, int iAttachment, float *rgflOrigin, float *rgflAngles );
-void pfnCRC32_Init( CRC32_t *pulCRC );
-void pfnCRC32_ProcessBuffer( CRC32_t *pulCRC, void *p, int len );
-void pfnCRC32_ProcessByte( CRC32_t *pulCRC, unsigned char ch );
-CRC32_t pfnCRC32_Final( CRC32_t pulCRC );
-long pfnRandomLong( long lLow, long lHigh );
-float pfnRandomFloat( float flLow, float flHigh );
-void pfnSetView( const edict_t *pClient, const edict_t *pViewent );
-float pfnTime( void );
-void pfnCrosshairAngle( const edict_t *pClient, float pitch, float yaw );
-byte * pfnLoadFileForMe( char *filename, int *pLength );
-void pfnFreeFile( void *buffer );
-void pfnEndSection( const char *pszSectionName );
-int pfnCompareFileTime( char *filename1, char *filename2, int *iCompare );
-void pfnGetGameDir( char *szGetGameDir );
-void pfnCvar_RegisterVariable( cvar_t *variable );
-void pfnFadeClientVolume( const edict_t *pEdict, int fadePercent, int fadeOutSeconds, int holdTime, int fadeInSeconds );
-void pfnSetClientMaxspeed( const edict_t *pEdict, float fNewMaxspeed );
-edict_t * pfnCreateFakeClient( const char *netname );
-void pfnRunPlayerMove( edict_t *fakeclient, const float *viewangles, float forwardmove, float sidemove, float upmove, unsigned short buttons, byte impulse, byte msec );
-int pfnNumberOfEntities( void );
-char* pfnGetInfoKeyBuffer( edict_t *e );
-char* pfnInfoKeyValue( char *infobuffer, char *key );
-void pfnSetKeyValue( char *infobuffer, char *key, char *value );
-void pfnSetClientKeyValue( int clientIndex, char *infobuffer, char *key, char *value );
-int pfnIsMapValid( char *filename );
-void pfnStaticDecal( const float *origin, int decalIndex, int entityIndex, int modelIndex );
-int pfnPrecacheGeneric( char* s );
-int pfnGetPlayerUserId( edict_t *e );
-void pfnBuildSoundMsg( edict_t *entity, int channel, const char *sample, /*int*/float volume, float attenuation, int fFlags, int pitch, int msg_dest, int msg_type, const float *pOrigin, edict_t *ed );
-int pfnIsDedicatedServer( void );
-cvar_t *pfnCVarGetPointer( const char *szVarName );
-unsigned int pfnGetPlayerWONId( edict_t *e );
-
-void pfnInfo_RemoveKey( char *s, const char *key );
-const char *pfnGetPhysicsKeyValue( const edict_t *pClient, const char *key );
-void pfnSetPhysicsKeyValue( const edict_t *pClient, const char *key, const char *value );
-const char *pfnGetPhysicsInfoString( const edict_t *pClient );
-unsigned short pfnPrecacheEvent( int type, const char*psz );
-void pfnPlaybackEvent( int flags, const edict_t *pInvoker, unsigned short eventindex, float delay, float *origin, float *angles, float fparam1, float fparam2, int iparam1, int iparam2, int bparam1, int bparam2 );
-unsigned char *pfnSetFatPVS( float *org );
-unsigned char *pfnSetFatPAS( float *org );
-int pfnCheckVisibility ( const edict_t *entity, unsigned char *pset );
-void pfnDeltaSetField( struct delta_s *pFields, const char *fieldname );
-void pfnDeltaUnsetField( struct delta_s *pFields, const char *fieldname );
-void pfnDeltaAddEncoder( char *name, void (*conditionalencode)( struct delta_s *pFields, const unsigned char *from, const unsigned char *to ) );
-int pfnGetCurrentPlayer( void );
-int pfnCanSkipPlayer( const edict_t *player );
-int pfnDeltaFindField( struct delta_s *pFields, const char *fieldname );
-void pfnDeltaSetFieldByIndex( struct delta_s *pFields, int fieldNumber );
-void pfnDeltaUnsetFieldByIndex( struct delta_s *pFields, int fieldNumber );
-void pfnSetGroupMask( int mask, int op );
-int pfnCreateInstancedBaseline( int classname, struct entity_state_s *baseline );
-void pfnCvar_DirectSet( struct cvar_s *var, char *value );
-void pfnForceUnmodified( FORCE_TYPE type, float *mins, float *maxs, const char *filename );
-void pfnGetPlayerStats( const edict_t *pClient, int *ping, int *packet_loss );
-
-#endif // ENGINE_H
-
+//
+// HPB_bot - botman's High Ping Bastard bot
+//
+// (http://planethalflife.com/botman/)
+//
+// engine.h
+//
+
+#ifndef ENGINE_H
+#define ENGINE_H
+
+// engine prototypes (from engine\eiface.h)...
+int pfnPrecacheModel( char* s );
+int pfnPrecacheSound( char* s );
+void pfnSetModel( edict_t *e, const char *m );
+int pfnModelIndex( const char *m );
+int pfnModelFrames( int modelIndex );
+void pfnSetSize( edict_t *e, const float *rgflMin, const float *rgflMax );
+void pfnChangeLevel( char* s1, char* s2 );
+void pfnGetSpawnParms( edict_t *ent );
+void pfnSaveSpawnParms( edict_t *ent );
+float pfnVecToYaw( const float *rgflVector );
+void pfnVecToAngles( const float *rgflVectorIn, float *rgflVectorOut );
+void pfnMoveToOrigin( edict_t *ent, const float *pflGoal, float dist, int iMoveType );
+void pfnChangeYaw( edict_t* ent );
+void pfnChangePitch( edict_t* ent );
+edict_t* pfnFindEntityByString( edict_t *pEdictStartSearchAfter, const char *pszField, const char *pszValue );
+int pfnGetEntityIllum( edict_t* pEnt );
+edict_t* pfnFindEntityInSphere( edict_t *pEdictStartSearchAfter, const float *org, float rad );
+edict_t* pfnFindClientInPVS( edict_t *pEdict );
+edict_t* pfnEntitiesInPVS( edict_t *pplayer );
+void pfnMakeVectors( const float *rgflVector );
+void pfnAngleVectors( const float *rgflVector, float *forward, float *right, float *up );
+edict_t* pfnCreateEntity( void );
+void pfnRemoveEntity( edict_t* e );
+edict_t* pfnCreateNamedEntity( int className );
+void pfnMakeStatic( edict_t *ent );
+int pfnEntIsOnFloor( edict_t *e );
+int pfnDropToFloor( edict_t* e );
+int pfnWalkMove( edict_t *ent, float yaw, float dist, int iMode );
+void pfnSetOrigin( edict_t *e, const float *rgflOrigin );
+void pfnEmitSound( edict_t *entity, int channel, const char *sample, /*int*/float volume, float attenuation, int fFlags, int pitch );
+void pfnEmitAmbientSound( edict_t *entity, float *pos, const char *samp, float vol, float attenuation, int fFlags, int pitch );
+void pfnTraceLine( const float *v1, const float *v2, int fNoMonsters, edict_t *pentToSkip, TraceResult *ptr );
+void pfnTraceToss( edict_t* pent, edict_t* pentToIgnore, TraceResult *ptr );
+int pfnTraceMonsterHull( edict_t *pEdict, const float *v1, const float *v2, int fNoMonsters, edict_t *pentToSkip, TraceResult *ptr );
+void pfnTraceHull( const float *v1, const float *v2, int fNoMonsters, int hullNumber, edict_t *pentToSkip, TraceResult *ptr );
+void pfnTraceModel( const float *v1, const float *v2, int hullNumber, edict_t *pent, TraceResult *ptr );
+const char *pfnTraceTexture( edict_t *pTextureEntity, const float *v1, const float *v2 );
+void pfnTraceSphere( const float *v1, const float *v2, int fNoMonsters, float radius, edict_t *pentToSkip, TraceResult *ptr );
+void pfnGetAimVector( edict_t* ent, float speed, float *rgflReturn );
+void pfnServerCommand( char* str );
+void pfnServerExecute( void );
+void pfnClientCommand( edict_t* pEdict, char* szFmt, ... );
+void pfnParticleEffect( const float *org, const float *dir, float color, float count );
+void pfnLightStyle( int style, char* val );
+int pfnDecalIndex( const char *name );
+int pfnPointContents( const float *rgflVector );
+void pfnMessageBegin( int msg_dest, int msg_type, const float *pOrigin, edict_t *ed );
+void pfnMessageEnd( void );
+void pfnWriteByte( int iValue );
+void pfnWriteChar( int iValue );
+void pfnWriteShort( int iValue );
+void pfnWriteLong( int iValue );
+void pfnWriteAngle( float flValue );
+void pfnWriteCoord( float flValue );
+void pfnWriteString( const char *sz );
+void pfnWriteEntity( int iValue );
+void pfnCVarRegister( cvar_t *pCvar );
+float pfnCVarGetFloat( const char *szVarName );
+const char* pfnCVarGetString( const char *szVarName );
+void pfnCVarSetFloat( const char *szVarName, float flValue );
+void pfnCVarSetString( const char *szVarName, const char *szValue );
+void pfnAlertMessage( ALERT_TYPE atype, char *szFmt, ... );
+void pfnEngineFprintf( FILE *pfile, char *szFmt, ... );
+void* pfnPvAllocEntPrivateData( edict_t *pEdict, long cb );
+void* pfnPvEntPrivateData( edict_t *pEdict );
+void pfnFreeEntPrivateData( edict_t *pEdict );
+const char* pfnSzFromIndex( int iString );
+int pfnAllocString( const char *szValue );
+struct entvars_s* pfnGetVarsOfEnt( edict_t *pEdict );
+edict_t* pfnPEntityOfEntOffset( int iEntOffset );
+int pfnEntOffsetOfPEntity( const edict_t *pEdict );
+int pfnIndexOfEdict( const edict_t *pEdict );
+edict_t* pfnPEntityOfEntIndex( int iEntIndex );
+edict_t* pfnFindEntityByVars( struct entvars_s* pvars );
+void* pfnGetModelPtr( edict_t* pEdict );
+int pfnRegUserMsg( const char *pszName, int iSize );
+void pfnAnimationAutomove( const edict_t* pEdict, float flTime );
+void pfnGetBonePosition( const edict_t* pEdict, int iBone, float *rgflOrigin, float *rgflAngles );
+unsigned long pfnFunctionFromName( const char *pName );
+const char *pfnNameForFunction( unsigned long function );
+void pfnClientPrintf( edict_t* pEdict, PRINT_TYPE ptype, const char *szMsg );
+void pfnServerPrint( const char *szMsg );
+const char *pfnCmd_Args( void );
+const char *pfnCmd_Argv( int argc );
+int pfnCmd_Argc( void );
+void pfnGetAttachment( const edict_t *pEdict, int iAttachment, float *rgflOrigin, float *rgflAngles );
+void pfnCRC32_Init( CRC32_t *pulCRC );
+void pfnCRC32_ProcessBuffer( CRC32_t *pulCRC, void *p, int len );
+void pfnCRC32_ProcessByte( CRC32_t *pulCRC, unsigned char ch );
+CRC32_t pfnCRC32_Final( CRC32_t pulCRC );
+long pfnRandomLong( long lLow, long lHigh );
+float pfnRandomFloat( float flLow, float flHigh );
+void pfnSetView( const edict_t *pClient, const edict_t *pViewent );
+float pfnTime( void );
+void pfnCrosshairAngle( const edict_t *pClient, float pitch, float yaw );
+byte * pfnLoadFileForMe( char *filename, int *pLength );
+void pfnFreeFile( void *buffer );
+void pfnEndSection( const char *pszSectionName );
+int pfnCompareFileTime( char *filename1, char *filename2, int *iCompare );
+void pfnGetGameDir( char *szGetGameDir );
+void pfnCvar_RegisterVariable( cvar_t *variable );
+void pfnFadeClientVolume( const edict_t *pEdict, int fadePercent, int fadeOutSeconds, int holdTime, int fadeInSeconds );
+void pfnSetClientMaxspeed( const edict_t *pEdict, float fNewMaxspeed );
+edict_t * pfnCreateFakeClient( const char *netname );
+void pfnRunPlayerMove( edict_t *fakeclient, const float *viewangles, float forwardmove, float sidemove, float upmove, unsigned short buttons, byte impulse, byte msec );
+int pfnNumberOfEntities( void );
+char* pfnGetInfoKeyBuffer( edict_t *e );
+char* pfnInfoKeyValue( char *infobuffer, char *key );
+void pfnSetKeyValue( char *infobuffer, char *key, char *value );
+void pfnSetClientKeyValue( int clientIndex, char *infobuffer, char *key, char *value );
+int pfnIsMapValid( char *filename );
+void pfnStaticDecal( const float *origin, int decalIndex, int entityIndex, int modelIndex );
+int pfnPrecacheGeneric( char* s );
+int pfnGetPlayerUserId( edict_t *e );
+void pfnBuildSoundMsg( edict_t *entity, int channel, const char *sample, /*int*/float volume, float attenuation, int fFlags, int pitch, int msg_dest, int msg_type, const float *pOrigin, edict_t *ed );
+int pfnIsDedicatedServer( void );
+cvar_t *pfnCVarGetPointer( const char *szVarName );
+unsigned int pfnGetPlayerWONId( edict_t *e );
+
+void pfnInfo_RemoveKey( char *s, const char *key );
+const char *pfnGetPhysicsKeyValue( const edict_t *pClient, const char *key );
+void pfnSetPhysicsKeyValue( const edict_t *pClient, const char *key, const char *value );
+const char *pfnGetPhysicsInfoString( const edict_t *pClient );
+unsigned short pfnPrecacheEvent( int type, const char*psz );
+void pfnPlaybackEvent( int flags, const edict_t *pInvoker, unsigned short eventindex, float delay, float *origin, float *angles, float fparam1, float fparam2, int iparam1, int iparam2, int bparam1, int bparam2 );
+unsigned char *pfnSetFatPVS( float *org );
+unsigned char *pfnSetFatPAS( float *org );
+int pfnCheckVisibility ( const edict_t *entity, unsigned char *pset );
+void pfnDeltaSetField( struct delta_s *pFields, const char *fieldname );
+void pfnDeltaUnsetField( struct delta_s *pFields, const char *fieldname );
+void pfnDeltaAddEncoder( char *name, void (*conditionalencode)( struct delta_s *pFields, const unsigned char *from, const unsigned char *to ) );
+int pfnGetCurrentPlayer( void );
+int pfnCanSkipPlayer( const edict_t *player );
+int pfnDeltaFindField( struct delta_s *pFields, const char *fieldname );
+void pfnDeltaSetFieldByIndex( struct delta_s *pFields, int fieldNumber );
+void pfnDeltaUnsetFieldByIndex( struct delta_s *pFields, int fieldNumber );
+void pfnSetGroupMask( int mask, int op );
+int pfnCreateInstancedBaseline( int classname, struct entity_state_s *baseline );
+void pfnCvar_DirectSet( struct cvar_s *var, char *value );
+void pfnForceUnmodified( FORCE_TYPE type, float *mins, float *maxs, const char *filename );
+void pfnGetPlayerStats( const edict_t *pClient, int *ping, int *packet_loss );
+
+#endif // ENGINE_H
+
diff --git a/main/source/HPB_bot/exports/exports.c b/main/source/HPB_bot/exports/exports.c
index 3de4c147..70c376b3 100644
--- a/main/source/HPB_bot/exports/exports.c
+++ b/main/source/HPB_bot/exports/exports.c
@@ -1,419 +1,419 @@
-//
-// (http://planethalflife.com/botman/)
-//
-// exports.c
-//
-
-#include
-#include
-#include
-#include
-
-
-#define DOS_SIGNATURE 0x5A4D /* MZ */
-#define NT_SIGNATURE 0x00004550 /* PE00 */
-
-
-// globals
-WORD *p_Ordinals = NULL;
-DWORD *p_Names = NULL;
-DWORD *p_Functions = NULL;
-int num_ordinals;
-
-
-typedef struct { // DOS .EXE header
- WORD e_magic; // Magic number
- WORD e_cblp; // Bytes on last page of file
- WORD e_cp; // Pages in file
- WORD e_crlc; // Relocations
- WORD e_cparhdr; // Size of header in paragraphs
- WORD e_minalloc; // Minimum extra paragraphs needed
- WORD e_maxalloc; // Maximum extra paragraphs needed
- WORD e_ss; // Initial (relative) SS value
- WORD e_sp; // Initial SP value
- WORD e_csum; // Checksum
- WORD e_ip; // Initial IP value
- WORD e_cs; // Initial (relative) CS value
- WORD e_lfarlc; // File address of relocation table
- WORD e_ovno; // Overlay number
- WORD e_res[4]; // Reserved words
- WORD e_oemid; // OEM identifier (for e_oeminfo)
- WORD e_oeminfo; // OEM information; e_oemid specific
- WORD e_res2[10]; // Reserved words
- LONG e_lfanew; // File address of new exe header
- } DOS_HEADER, *P_DOS_HEADER;
-
-typedef struct {
- WORD Machine;
- WORD NumberOfSections;
- DWORD TimeDateStamp;
- DWORD PointerToSymbolTable;
- DWORD NumberOfSymbols;
- WORD SizeOfOptionalHeader;
- WORD Characteristics;
-} PE_HEADER, *P_PE_HEADER;
-
-#define SIZEOF_SHORT_NAME 8
-
-typedef struct {
- BYTE Name[SIZEOF_SHORT_NAME];
- union {
- DWORD PhysicalAddress;
- DWORD VirtualSize;
- } Misc;
- DWORD VirtualAddress;
- DWORD SizeOfRawData;
- DWORD PointerToRawData;
- DWORD PointerToRelocations;
- DWORD PointerToLinenumbers;
- WORD NumberOfRelocations;
- WORD NumberOfLinenumbers;
- DWORD Characteristics;
-} SECTION_HEADER, *P_SECTION_HEADER;
-
-typedef struct {
- DWORD VirtualAddress;
- DWORD Size;
-} DATA_DIRECTORY, *P_DATA_DIRECTORY;
-
-#define NUMBEROF_DIRECTORY_ENTRIES 16
-
-typedef struct {
- WORD Magic;
- BYTE MajorLinkerVersion;
- BYTE MinorLinkerVersion;
- DWORD SizeOfCode;
- DWORD SizeOfInitializedData;
- DWORD SizeOfUninitializedData;
- DWORD AddressOfEntryPoint;
- DWORD BaseOfCode;
- DWORD BaseOfData;
- DWORD ImageBase;
- DWORD SectionAlignment;
- DWORD FileAlignment;
- WORD MajorOperatingSystemVersion;
- WORD MinorOperatingSystemVersion;
- WORD MajorImageVersion;
- WORD MinorImageVersion;
- WORD MajorSubsystemVersion;
- WORD MinorSubsystemVersion;
- DWORD Win32VersionValue;
- DWORD SizeOfImage;
- DWORD SizeOfHeaders;
- DWORD CheckSum;
- WORD Subsystem;
- WORD DllCharacteristics;
- DWORD SizeOfStackReserve;
- DWORD SizeOfStackCommit;
- DWORD SizeOfHeapReserve;
- DWORD SizeOfHeapCommit;
- DWORD LoaderFlags;
- DWORD NumberOfRvaAndSizes;
- DATA_DIRECTORY DataDirectory[NUMBEROF_DIRECTORY_ENTRIES];
-} OPTIONAL_HEADER, *P_OPTIONAL_HEADER;
-
-typedef struct {
- DWORD Characteristics;
- DWORD TimeDateStamp;
- WORD MajorVersion;
- WORD MinorVersion;
- DWORD Name;
- DWORD Base;
- DWORD NumberOfFunctions;
- DWORD NumberOfNames;
- DWORD AddressOfFunctions; // RVA from base of image
- DWORD AddressOfNames; // RVA from base of image
- DWORD AddressOfNameOrdinals; // RVA from base of image
-} EXPORT_DIRECTORY, *P_EXPORT_DIRECTORY;
-
-
-void FreeNameFuncGlobals(void)
-{
- if (p_Ordinals)
- free(p_Ordinals);
- if (p_Functions)
- free(p_Functions);
- if (p_Names)
- free(p_Names);
-}
-
-
-void FgetString(char *str, FILE *bfp)
-{
- char ch;
-
- while ((ch = fgetc(bfp)) != EOF)
- {
- *str++ = ch;
- if (ch == 0)
- break;
- }
-}
-
-
-int main(int argc, char *argv[])
-{
- FILE *bfp;
- char filename[80];
- BOOL extended = FALSE;
- DOS_HEADER dos_header;
- LONG nt_signature;
- PE_HEADER pe_header;
- SECTION_HEADER section_header;
- BOOL edata_found;
- OPTIONAL_HEADER optional_header;
- LONG edata_offset;
- LONG edata_delta;
- EXPORT_DIRECTORY export_directory;
- LONG name_offset;
- LONG ordinal_offset;
- LONG function_offset;
- char function_name[256];
- int i, index;
- BOOL error;
- //char msg[80];
-
-
- if (argc < 2)
- {
- printf("usage: exports [-e] filename.dll\n");
- return -1;
- }
-
- if (argc > 2)
- {
- if (argv[1][0] == '-')
- {
- if (argv[1][1] == 'e')
- {
- strcpy(filename, argv[2]);
- extended = TRUE;
- }
- else
- {
- printf("unknown option \"%s\"\n\n", argv[1]);
- printf("usage: exports [-e] filename.dll\n");
- return -1;
- }
- }
- else
- {
- printf("usage: exports [-e] filename.dll\n");
- return -1;
- }
- }
- else
- strcpy(filename, argv[1]);
-
- if ((bfp=fopen(filename, "rb")) == NULL)
- {
- printf("DLL file %s not found!", filename);
- return -1;
- }
-
- if (fread(&dos_header, sizeof(dos_header), 1, bfp) != 1)
- {
- printf("%s is NOT a valid DLL file!", filename);
- return -1;
- }
-
- if (dos_header.e_magic != DOS_SIGNATURE)
- {
- printf("file does not have a valid DLL signature!");
- return -1;
- }
-
- if (fseek(bfp, dos_header.e_lfanew, SEEK_SET) == -1)
- {
- printf("error seeking to new exe header!");
- return -1;
- }
-
- if (fread(&nt_signature, sizeof(nt_signature), 1, bfp) != 1)
- {
- printf("file does not have a valid NT signature!");
- return -1;
- }
-
- if (nt_signature != NT_SIGNATURE)
- {
- printf("file does not have a valid NT signature!");
- return -1;
- }
-
- if (fread(&pe_header, sizeof(pe_header), 1, bfp) != 1)
- {
- printf("file does not have a valid PE header!");
- return -1;
- }
-
- if (pe_header.SizeOfOptionalHeader == 0)
- {
- printf("file does not have an optional header!");
- return -1;
- }
-
- if (fread(&optional_header, sizeof(optional_header), 1, bfp) != 1)
- {
- printf("file does not have a valid optional header!");
- return -1;
- }
-
- edata_found = FALSE;
-
- for (i=0; i < pe_header.NumberOfSections; i++)
- {
- if (fread(§ion_header, sizeof(section_header), 1, bfp) != 1)
- {
- printf("error reading section header!");
- return -1;
- }
-
- if (strcmp((char *)section_header.Name, ".edata") == 0)
- {
- edata_found = TRUE;
- break;
- }
- }
-
- if (edata_found)
- {
- edata_offset = section_header.PointerToRawData;
- edata_delta = section_header.VirtualAddress - section_header.PointerToRawData;
- }
- else
- {
- edata_offset = optional_header.DataDirectory[0].VirtualAddress;
- edata_delta = 0L;
- }
-
-
- if (fseek(bfp, edata_offset, SEEK_SET) == -1)
- {
- printf("file does not have a valid exports section!");
- return -1;
- }
-
- if (fread(&export_directory, sizeof(export_directory), 1, bfp) != 1)
- {
- printf("file does not have a valid optional header!");
- return -1;
- }
-
- num_ordinals = export_directory.NumberOfNames; // also number of ordinals
-
-
- ordinal_offset = export_directory.AddressOfNameOrdinals - edata_delta;
-
- if (fseek(bfp, ordinal_offset, SEEK_SET) == -1)
- {
- printf("file does not have a valid ordinals section!");
- return -1;
- }
-
- if ((p_Ordinals = (WORD *)malloc(num_ordinals * sizeof(WORD))) == NULL)
- {
- printf("error allocating memory for ordinals section!");
- return -1;
- }
-
- if (fread(p_Ordinals, num_ordinals * sizeof(WORD), 1, bfp) != 1)
- {
- FreeNameFuncGlobals();
-
- printf("error reading ordinals table!");
- return -1;
- }
-
-
- function_offset = export_directory.AddressOfFunctions - edata_delta;
-
- if (fseek(bfp, function_offset, SEEK_SET) == -1)
- {
- FreeNameFuncGlobals();
-
- printf("file does not have a valid export address section!");
- return -1;
- }
-
- if ((p_Functions = (DWORD *)malloc(num_ordinals * sizeof(DWORD))) == NULL)
- {
- FreeNameFuncGlobals();
-
- printf("error allocating memory for export address section!");
- return -1;
- }
-
- if (fread(p_Functions, num_ordinals * sizeof(DWORD), 1, bfp) != 1)
- {
- FreeNameFuncGlobals();
-
- printf("error reading export address section!");
- return -1;
- }
-
-
- name_offset = export_directory.AddressOfNames - edata_delta;
-
- if (fseek(bfp, name_offset, SEEK_SET) == -1)
- {
- FreeNameFuncGlobals();
-
- printf("file does not have a valid names section!");
- return -1;
- }
-
- if ((p_Names = (DWORD *)malloc(num_ordinals * sizeof(DWORD))) == NULL)
- {
- FreeNameFuncGlobals();
-
- printf("error allocating memory for names section!");
- return -1;
- }
-
- if (fread(p_Names, num_ordinals * sizeof(DWORD), 1, bfp) != 1)
- {
- FreeNameFuncGlobals();
-
- printf("error reading names table!");
- return -1;
- }
-
- error = FALSE;
-
- for (i=0; (i < num_ordinals) && (error==FALSE); i++)
- {
- name_offset = p_Names[i] - edata_delta;
-
- if (name_offset != 0)
- {
- if (fseek(bfp, name_offset, SEEK_SET) == -1)
- {
- printf("error in loading names section!\n");
- error = TRUE;
- }
- else
- {
- FgetString(function_name, bfp);
-
- if (extended)
- {
- index = p_Ordinals[i];
-
- printf("ordinal=%3d addr=%08lX name=%s\n",
- (p_Ordinals[i]+1), p_Functions[index], function_name);
- }
- else
- printf("%s\n", function_name);
- }
- }
- }
-
- FreeNameFuncGlobals();
-
- fclose(bfp);
-
- return 0;
-}
-
-
+//
+// (http://planethalflife.com/botman/)
+//
+// exports.c
+//
+
+#include
+#include
+#include
+#include
+
+
+#define DOS_SIGNATURE 0x5A4D /* MZ */
+#define NT_SIGNATURE 0x00004550 /* PE00 */
+
+
+// globals
+WORD *p_Ordinals = NULL;
+DWORD *p_Names = NULL;
+DWORD *p_Functions = NULL;
+int num_ordinals;
+
+
+typedef struct { // DOS .EXE header
+ WORD e_magic; // Magic number
+ WORD e_cblp; // Bytes on last page of file
+ WORD e_cp; // Pages in file
+ WORD e_crlc; // Relocations
+ WORD e_cparhdr; // Size of header in paragraphs
+ WORD e_minalloc; // Minimum extra paragraphs needed
+ WORD e_maxalloc; // Maximum extra paragraphs needed
+ WORD e_ss; // Initial (relative) SS value
+ WORD e_sp; // Initial SP value
+ WORD e_csum; // Checksum
+ WORD e_ip; // Initial IP value
+ WORD e_cs; // Initial (relative) CS value
+ WORD e_lfarlc; // File address of relocation table
+ WORD e_ovno; // Overlay number
+ WORD e_res[4]; // Reserved words
+ WORD e_oemid; // OEM identifier (for e_oeminfo)
+ WORD e_oeminfo; // OEM information; e_oemid specific
+ WORD e_res2[10]; // Reserved words
+ LONG e_lfanew; // File address of new exe header
+ } DOS_HEADER, *P_DOS_HEADER;
+
+typedef struct {
+ WORD Machine;
+ WORD NumberOfSections;
+ DWORD TimeDateStamp;
+ DWORD PointerToSymbolTable;
+ DWORD NumberOfSymbols;
+ WORD SizeOfOptionalHeader;
+ WORD Characteristics;
+} PE_HEADER, *P_PE_HEADER;
+
+#define SIZEOF_SHORT_NAME 8
+
+typedef struct {
+ BYTE Name[SIZEOF_SHORT_NAME];
+ union {
+ DWORD PhysicalAddress;
+ DWORD VirtualSize;
+ } Misc;
+ DWORD VirtualAddress;
+ DWORD SizeOfRawData;
+ DWORD PointerToRawData;
+ DWORD PointerToRelocations;
+ DWORD PointerToLinenumbers;
+ WORD NumberOfRelocations;
+ WORD NumberOfLinenumbers;
+ DWORD Characteristics;
+} SECTION_HEADER, *P_SECTION_HEADER;
+
+typedef struct {
+ DWORD VirtualAddress;
+ DWORD Size;
+} DATA_DIRECTORY, *P_DATA_DIRECTORY;
+
+#define NUMBEROF_DIRECTORY_ENTRIES 16
+
+typedef struct {
+ WORD Magic;
+ BYTE MajorLinkerVersion;
+ BYTE MinorLinkerVersion;
+ DWORD SizeOfCode;
+ DWORD SizeOfInitializedData;
+ DWORD SizeOfUninitializedData;
+ DWORD AddressOfEntryPoint;
+ DWORD BaseOfCode;
+ DWORD BaseOfData;
+ DWORD ImageBase;
+ DWORD SectionAlignment;
+ DWORD FileAlignment;
+ WORD MajorOperatingSystemVersion;
+ WORD MinorOperatingSystemVersion;
+ WORD MajorImageVersion;
+ WORD MinorImageVersion;
+ WORD MajorSubsystemVersion;
+ WORD MinorSubsystemVersion;
+ DWORD Win32VersionValue;
+ DWORD SizeOfImage;
+ DWORD SizeOfHeaders;
+ DWORD CheckSum;
+ WORD Subsystem;
+ WORD DllCharacteristics;
+ DWORD SizeOfStackReserve;
+ DWORD SizeOfStackCommit;
+ DWORD SizeOfHeapReserve;
+ DWORD SizeOfHeapCommit;
+ DWORD LoaderFlags;
+ DWORD NumberOfRvaAndSizes;
+ DATA_DIRECTORY DataDirectory[NUMBEROF_DIRECTORY_ENTRIES];
+} OPTIONAL_HEADER, *P_OPTIONAL_HEADER;
+
+typedef struct {
+ DWORD Characteristics;
+ DWORD TimeDateStamp;
+ WORD MajorVersion;
+ WORD MinorVersion;
+ DWORD Name;
+ DWORD Base;
+ DWORD NumberOfFunctions;
+ DWORD NumberOfNames;
+ DWORD AddressOfFunctions; // RVA from base of image
+ DWORD AddressOfNames; // RVA from base of image
+ DWORD AddressOfNameOrdinals; // RVA from base of image
+} EXPORT_DIRECTORY, *P_EXPORT_DIRECTORY;
+
+
+void FreeNameFuncGlobals(void)
+{
+ if (p_Ordinals)
+ free(p_Ordinals);
+ if (p_Functions)
+ free(p_Functions);
+ if (p_Names)
+ free(p_Names);
+}
+
+
+void FgetString(char *str, FILE *bfp)
+{
+ char ch;
+
+ while ((ch = fgetc(bfp)) != EOF)
+ {
+ *str++ = ch;
+ if (ch == 0)
+ break;
+ }
+}
+
+
+int main(int argc, char *argv[])
+{
+ FILE *bfp;
+ char filename[80];
+ BOOL extended = FALSE;
+ DOS_HEADER dos_header;
+ LONG nt_signature;
+ PE_HEADER pe_header;
+ SECTION_HEADER section_header;
+ BOOL edata_found;
+ OPTIONAL_HEADER optional_header;
+ LONG edata_offset;
+ LONG edata_delta;
+ EXPORT_DIRECTORY export_directory;
+ LONG name_offset;
+ LONG ordinal_offset;
+ LONG function_offset;
+ char function_name[256];
+ int i, index;
+ BOOL error;
+ //char msg[80];
+
+
+ if (argc < 2)
+ {
+ printf("usage: exports [-e] filename.dll\n");
+ return -1;
+ }
+
+ if (argc > 2)
+ {
+ if (argv[1][0] == '-')
+ {
+ if (argv[1][1] == 'e')
+ {
+ strcpy(filename, argv[2]);
+ extended = TRUE;
+ }
+ else
+ {
+ printf("unknown option \"%s\"\n\n", argv[1]);
+ printf("usage: exports [-e] filename.dll\n");
+ return -1;
+ }
+ }
+ else
+ {
+ printf("usage: exports [-e] filename.dll\n");
+ return -1;
+ }
+ }
+ else
+ strcpy(filename, argv[1]);
+
+ if ((bfp=fopen(filename, "rb")) == NULL)
+ {
+ printf("DLL file %s not found!", filename);
+ return -1;
+ }
+
+ if (fread(&dos_header, sizeof(dos_header), 1, bfp) != 1)
+ {
+ printf("%s is NOT a valid DLL file!", filename);
+ return -1;
+ }
+
+ if (dos_header.e_magic != DOS_SIGNATURE)
+ {
+ printf("file does not have a valid DLL signature!");
+ return -1;
+ }
+
+ if (fseek(bfp, dos_header.e_lfanew, SEEK_SET) == -1)
+ {
+ printf("error seeking to new exe header!");
+ return -1;
+ }
+
+ if (fread(&nt_signature, sizeof(nt_signature), 1, bfp) != 1)
+ {
+ printf("file does not have a valid NT signature!");
+ return -1;
+ }
+
+ if (nt_signature != NT_SIGNATURE)
+ {
+ printf("file does not have a valid NT signature!");
+ return -1;
+ }
+
+ if (fread(&pe_header, sizeof(pe_header), 1, bfp) != 1)
+ {
+ printf("file does not have a valid PE header!");
+ return -1;
+ }
+
+ if (pe_header.SizeOfOptionalHeader == 0)
+ {
+ printf("file does not have an optional header!");
+ return -1;
+ }
+
+ if (fread(&optional_header, sizeof(optional_header), 1, bfp) != 1)
+ {
+ printf("file does not have a valid optional header!");
+ return -1;
+ }
+
+ edata_found = FALSE;
+
+ for (i=0; i < pe_header.NumberOfSections; i++)
+ {
+ if (fread(§ion_header, sizeof(section_header), 1, bfp) != 1)
+ {
+ printf("error reading section header!");
+ return -1;
+ }
+
+ if (strcmp((char *)section_header.Name, ".edata") == 0)
+ {
+ edata_found = TRUE;
+ break;
+ }
+ }
+
+ if (edata_found)
+ {
+ edata_offset = section_header.PointerToRawData;
+ edata_delta = section_header.VirtualAddress - section_header.PointerToRawData;
+ }
+ else
+ {
+ edata_offset = optional_header.DataDirectory[0].VirtualAddress;
+ edata_delta = 0L;
+ }
+
+
+ if (fseek(bfp, edata_offset, SEEK_SET) == -1)
+ {
+ printf("file does not have a valid exports section!");
+ return -1;
+ }
+
+ if (fread(&export_directory, sizeof(export_directory), 1, bfp) != 1)
+ {
+ printf("file does not have a valid optional header!");
+ return -1;
+ }
+
+ num_ordinals = export_directory.NumberOfNames; // also number of ordinals
+
+
+ ordinal_offset = export_directory.AddressOfNameOrdinals - edata_delta;
+
+ if (fseek(bfp, ordinal_offset, SEEK_SET) == -1)
+ {
+ printf("file does not have a valid ordinals section!");
+ return -1;
+ }
+
+ if ((p_Ordinals = (WORD *)malloc(num_ordinals * sizeof(WORD))) == NULL)
+ {
+ printf("error allocating memory for ordinals section!");
+ return -1;
+ }
+
+ if (fread(p_Ordinals, num_ordinals * sizeof(WORD), 1, bfp) != 1)
+ {
+ FreeNameFuncGlobals();
+
+ printf("error reading ordinals table!");
+ return -1;
+ }
+
+
+ function_offset = export_directory.AddressOfFunctions - edata_delta;
+
+ if (fseek(bfp, function_offset, SEEK_SET) == -1)
+ {
+ FreeNameFuncGlobals();
+
+ printf("file does not have a valid export address section!");
+ return -1;
+ }
+
+ if ((p_Functions = (DWORD *)malloc(num_ordinals * sizeof(DWORD))) == NULL)
+ {
+ FreeNameFuncGlobals();
+
+ printf("error allocating memory for export address section!");
+ return -1;
+ }
+
+ if (fread(p_Functions, num_ordinals * sizeof(DWORD), 1, bfp) != 1)
+ {
+ FreeNameFuncGlobals();
+
+ printf("error reading export address section!");
+ return -1;
+ }
+
+
+ name_offset = export_directory.AddressOfNames - edata_delta;
+
+ if (fseek(bfp, name_offset, SEEK_SET) == -1)
+ {
+ FreeNameFuncGlobals();
+
+ printf("file does not have a valid names section!");
+ return -1;
+ }
+
+ if ((p_Names = (DWORD *)malloc(num_ordinals * sizeof(DWORD))) == NULL)
+ {
+ FreeNameFuncGlobals();
+
+ printf("error allocating memory for names section!");
+ return -1;
+ }
+
+ if (fread(p_Names, num_ordinals * sizeof(DWORD), 1, bfp) != 1)
+ {
+ FreeNameFuncGlobals();
+
+ printf("error reading names table!");
+ return -1;
+ }
+
+ error = FALSE;
+
+ for (i=0; (i < num_ordinals) && (error==FALSE); i++)
+ {
+ name_offset = p_Names[i] - edata_delta;
+
+ if (name_offset != 0)
+ {
+ if (fseek(bfp, name_offset, SEEK_SET) == -1)
+ {
+ printf("error in loading names section!\n");
+ error = TRUE;
+ }
+ else
+ {
+ FgetString(function_name, bfp);
+
+ if (extended)
+ {
+ index = p_Ordinals[i];
+
+ printf("ordinal=%3d addr=%08lX name=%s\n",
+ (p_Ordinals[i]+1), p_Functions[index], function_name);
+ }
+ else
+ printf("%s\n", function_name);
+ }
+ }
+ }
+
+ FreeNameFuncGlobals();
+
+ fclose(bfp);
+
+ return 0;
+}
+
+
diff --git a/main/source/HPB_bot/exports/exports.dsp b/main/source/HPB_bot/exports/exports.dsp
index 65382224..77b1c2b8 100644
--- a/main/source/HPB_bot/exports/exports.dsp
+++ b/main/source/HPB_bot/exports/exports.dsp
@@ -1,100 +1,100 @@
-# Microsoft Developer Studio Project File - Name="exports" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=exports - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "exports.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "exports.mak" CFG="exports - Win32 Debug"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "exports - Win32 Release" (based on "Win32 (x86) Console Application")
-!MESSAGE "exports - Win32 Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "exports - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-
-!ELSEIF "$(CFG)" == "exports - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
-# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-
-!ENDIF
-
-# Begin Target
-
-# Name "exports - Win32 Release"
-# Name "exports - Win32 Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE=.\exports.c
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# End Group
-# Begin Group "Resource Files"
-
-# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
-# End Group
-# End Target
-# End Project
+# Microsoft Developer Studio Project File - Name="exports" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=exports - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "exports.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "exports.mak" CFG="exports - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "exports - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "exports - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "exports - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+
+!ELSEIF "$(CFG)" == "exports - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "exports - Win32 Release"
+# Name "exports - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\exports.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/main/source/Natural_Selection.sdf b/main/source/Natural_Selection.sdf
index 2a27c4ac..ca8ed647 100644
Binary files a/main/source/Natural_Selection.sdf and b/main/source/Natural_Selection.sdf differ
diff --git a/main/source/Natural_Selection.sln b/main/source/Natural_Selection.sln
index 2e575208..8f096ebf 100644
--- a/main/source/Natural_Selection.sln
+++ b/main/source/Natural_Selection.sln
@@ -1,33 +1,35 @@
-Microsoft Visual Studio Solution File, Format Version 11.00
-# Visual Studio 2010
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cl_dll.dll", "cl_dll\cl_dll.vcxproj", "{665C1DAF-9248-E06F-4E5C-A664BAFDE9D8}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ns.dll", "dlls\hl.vcxproj", "{BC87A180-F17B-83FC-5D7D-470FAD003ABC}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Developer - debug|Win32 = Developer - debug|Win32
- Developer - release|Win32 = Developer - release|Win32
- Playtest - balance disabled|Win32 = Playtest - balance disabled|Win32
- Playtest|Win32 = Playtest|Win32
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {665C1DAF-9248-E06F-4E5C-A664BAFDE9D8}.Developer - debug|Win32.ActiveCfg = Playtest|Win32
- {665C1DAF-9248-E06F-4E5C-A664BAFDE9D8}.Developer - debug|Win32.Build.0 = Playtest|Win32
- {665C1DAF-9248-E06F-4E5C-A664BAFDE9D8}.Developer - release|Win32.ActiveCfg = Playtest|Win32
- {665C1DAF-9248-E06F-4E5C-A664BAFDE9D8}.Developer - release|Win32.Build.0 = Playtest|Win32
- {665C1DAF-9248-E06F-4E5C-A664BAFDE9D8}.Playtest - balance disabled|Win32.ActiveCfg = Playtest|Win32
- {665C1DAF-9248-E06F-4E5C-A664BAFDE9D8}.Playtest - balance disabled|Win32.Build.0 = Playtest|Win32
- {665C1DAF-9248-E06F-4E5C-A664BAFDE9D8}.Playtest|Win32.ActiveCfg = Playtest|Win32
- {665C1DAF-9248-E06F-4E5C-A664BAFDE9D8}.Playtest|Win32.Build.0 = Playtest|Win32
- {BC87A180-F17B-83FC-5D7D-470FAD003ABC}.Developer - debug|Win32.ActiveCfg = Developer - debug|Win32
- {BC87A180-F17B-83FC-5D7D-470FAD003ABC}.Developer - release|Win32.ActiveCfg = Developer - release|Win32
- {BC87A180-F17B-83FC-5D7D-470FAD003ABC}.Playtest - balance disabled|Win32.ActiveCfg = Playtest - balance disabled|Win32
- {BC87A180-F17B-83FC-5D7D-470FAD003ABC}.Playtest - balance disabled|Win32.Build.0 = Playtest - balance disabled|Win32
- {BC87A180-F17B-83FC-5D7D-470FAD003ABC}.Playtest|Win32.ActiveCfg = Playtest|Win32
- {BC87A180-F17B-83FC-5D7D-470FAD003ABC}.Playtest|Win32.Build.0 = Playtest|Win32
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
-EndGlobal
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 14
+VisualStudioVersion = 14.0.24720.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cl_dll.dll", "cl_dll\cl_dll.vcxproj", "{665C1DAF-9248-E06F-4E5C-A664BAFDE9D8}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ns.dll", "dlls\hl.vcxproj", "{BC87A180-F17B-83FC-5D7D-470FAD003ABC}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Developer - debug|Win32 = Developer - debug|Win32
+ Developer - release|Win32 = Developer - release|Win32
+ Playtest - balance disabled|Win32 = Playtest - balance disabled|Win32
+ Playtest|Win32 = Playtest|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {665C1DAF-9248-E06F-4E5C-A664BAFDE9D8}.Developer - debug|Win32.ActiveCfg = Playtest|Win32
+ {665C1DAF-9248-E06F-4E5C-A664BAFDE9D8}.Developer - debug|Win32.Build.0 = Playtest|Win32
+ {665C1DAF-9248-E06F-4E5C-A664BAFDE9D8}.Developer - release|Win32.ActiveCfg = Playtest|Win32
+ {665C1DAF-9248-E06F-4E5C-A664BAFDE9D8}.Developer - release|Win32.Build.0 = Playtest|Win32
+ {665C1DAF-9248-E06F-4E5C-A664BAFDE9D8}.Playtest - balance disabled|Win32.ActiveCfg = Playtest|Win32
+ {665C1DAF-9248-E06F-4E5C-A664BAFDE9D8}.Playtest - balance disabled|Win32.Build.0 = Playtest|Win32
+ {665C1DAF-9248-E06F-4E5C-A664BAFDE9D8}.Playtest|Win32.ActiveCfg = Playtest|Win32
+ {665C1DAF-9248-E06F-4E5C-A664BAFDE9D8}.Playtest|Win32.Build.0 = Playtest|Win32
+ {BC87A180-F17B-83FC-5D7D-470FAD003ABC}.Developer - debug|Win32.ActiveCfg = Developer - debug|Win32
+ {BC87A180-F17B-83FC-5D7D-470FAD003ABC}.Developer - release|Win32.ActiveCfg = Developer - release|Win32
+ {BC87A180-F17B-83FC-5D7D-470FAD003ABC}.Playtest - balance disabled|Win32.ActiveCfg = Playtest - balance disabled|Win32
+ {BC87A180-F17B-83FC-5D7D-470FAD003ABC}.Playtest - balance disabled|Win32.Build.0 = Playtest - balance disabled|Win32
+ {BC87A180-F17B-83FC-5D7D-470FAD003ABC}.Playtest|Win32.ActiveCfg = Playtest|Win32
+ {BC87A180-F17B-83FC-5D7D-470FAD003ABC}.Playtest|Win32.Build.0 = Playtest|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/main/source/build.h b/main/source/build.h
index 56effb4e..82d12628 100644
--- a/main/source/build.h
+++ b/main/source/build.h
@@ -1,73 +1,73 @@
-//======== (C) Copyright 2002 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:
-//
-// $Workfile: build.h $
-// $Date: 2002/11/22 22:09:10 $
-//
-//-------------------------------------------------------------------------------
-// $Log: build.h,v $
-// Revision 1.17 2002/11/22 22:09:10 Flayra
-// - Updated version #
-//
-// Revision 1.16 2002/11/22 21:07:55 Flayra
-// - Removed dev build, use DEBUG instead
-//
-// Revision 1.15 2002/11/15 19:09:57 Flayra
-// - Reworked network metering to be easily toggleable
-//
-// Revision 1.14 2002/11/12 02:20:25 Flayra
-// - Updated version number
-//
-// Revision 1.13 2002/11/06 01:37:07 Flayra
-// - Regular update
-//
-// Revision 1.12 2002/11/03 04:54:45 Flayra
-// - Regular update
-//
-// Revision 1.11 2002/10/24 21:09:04 Flayra
-// - No longer needed
-//
-// Revision 1.10 2002/10/20 16:33:31 Flayra
-// - Regular update
-//
-// Revision 1.9 2002/10/16 20:48:18 Flayra
-// - Regular update
-//
-// Revision 1.8 2002/10/03 19:07:12 Flayra
-// - Profiling switch
-// - Regular game version update
-//
-// Revision 1.7 2002/09/23 21:51:39 Flayra
-// - Regular update
-//
-// Revision 1.6 2002/09/09 19:38:34 Flayra
-// - Tried implementing DirectX version of gamma ramp support
-//
-// Revision 1.5 2002/08/16 02:21:37 Flayra
-// - Re-enabled selection
-//
-// Revision 1.4 2002/08/09 00:14:59 Flayra
-// - Removed selection prediction
-//
-// Revision 1.3 2002/05/23 02:41:53 Flayra
-// - Post-crash checkin. Restored @Backup from around 4/16. Contains changes for last four weeks of development.
-//
-//===============================================================================
-#ifndef BUILD_H
-#define BUILD_H
-
-// Build in code to help playtest. Choose neither, AVH_PLAYTEST_BUILD, or AVH_PLAYTEST_BUILD _and_ AVH_LAN_PLAYTEST_BUILD
-#ifdef DEBUG
- #define AVH_PLAYTEST_BUILD
-#endif
-
-//#define PROFILE_BUILD
-//#define USE_NETWORK_METERING
-
+//======== (C) Copyright 2002 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:
+//
+// $Workfile: build.h $
+// $Date: 2002/11/22 22:09:10 $
+//
+//-------------------------------------------------------------------------------
+// $Log: build.h,v $
+// Revision 1.17 2002/11/22 22:09:10 Flayra
+// - Updated version #
+//
+// Revision 1.16 2002/11/22 21:07:55 Flayra
+// - Removed dev build, use DEBUG instead
+//
+// Revision 1.15 2002/11/15 19:09:57 Flayra
+// - Reworked network metering to be easily toggleable
+//
+// Revision 1.14 2002/11/12 02:20:25 Flayra
+// - Updated version number
+//
+// Revision 1.13 2002/11/06 01:37:07 Flayra
+// - Regular update
+//
+// Revision 1.12 2002/11/03 04:54:45 Flayra
+// - Regular update
+//
+// Revision 1.11 2002/10/24 21:09:04 Flayra
+// - No longer needed
+//
+// Revision 1.10 2002/10/20 16:33:31 Flayra
+// - Regular update
+//
+// Revision 1.9 2002/10/16 20:48:18 Flayra
+// - Regular update
+//
+// Revision 1.8 2002/10/03 19:07:12 Flayra
+// - Profiling switch
+// - Regular game version update
+//
+// Revision 1.7 2002/09/23 21:51:39 Flayra
+// - Regular update
+//
+// Revision 1.6 2002/09/09 19:38:34 Flayra
+// - Tried implementing DirectX version of gamma ramp support
+//
+// Revision 1.5 2002/08/16 02:21:37 Flayra
+// - Re-enabled selection
+//
+// Revision 1.4 2002/08/09 00:14:59 Flayra
+// - Removed selection prediction
+//
+// Revision 1.3 2002/05/23 02:41:53 Flayra
+// - Post-crash checkin. Restored @Backup from around 4/16. Contains changes for last four weeks of development.
+//
+//===============================================================================
+#ifndef BUILD_H
+#define BUILD_H
+
+// Build in code to help playtest. Choose neither, AVH_PLAYTEST_BUILD, or AVH_PLAYTEST_BUILD _and_ AVH_LAN_PLAYTEST_BUILD
+#ifdef DEBUG
+ #define AVH_PLAYTEST_BUILD
+#endif
+
+//#define PROFILE_BUILD
+//#define USE_NETWORK_METERING
+
#endif
\ No newline at end of file
diff --git a/main/source/cl_dll/CLabelHeader.h b/main/source/cl_dll/CLabelHeader.h
index 0a378528..9482b065 100644
--- a/main/source/cl_dll/CLabelHeader.h
+++ b/main/source/cl_dll/CLabelHeader.h
@@ -1,193 +1,193 @@
-#ifndef CLABELHEADER_H
-#define CLABELHEADER_H
-
-#include
-#include "cl_dll/vgui_TeamFortressViewport.h"
-
-class CTextImage2 : public Image
-{
-public:
- CTextImage2()
- {
- _image[0] = new TextImage("");
- _image[1] = new TextImage("");
- }
-
- ~CTextImage2()
- {
- delete _image[0];
- delete _image[1];
- }
-
- TextImage *GetImage(int image)
- {
- return _image[image];
- }
-
- void getSize(int &wide, int &tall)
- {
- int w1, w2, t1, t2;
- _image[0]->getTextSize(w1, t1);
- _image[1]->getTextSize(w2, t2);
-
- wide = w1 + w2;
- tall = max(t1, t2);
- setSize(wide, tall);
- }
-
- void doPaint(Panel *panel)
- {
- _image[0]->doPaint(panel);
- _image[1]->doPaint(panel);
- }
-
- void setPos(int x, int y)
- {
- _image[0]->setPos(x, y);
-
- int swide, stall;
- _image[0]->getSize(swide, stall);
-
- int wide, tall;
- _image[1]->getSize(wide, tall);
- _image[1]->setPos(x + wide, y + (stall * 0.9) - tall);
- }
-
- void setColor(Color color)
- {
- _image[0]->setColor(color);
- }
-
- void setColor2(Color color)
- {
- _image[1]->setColor(color);
- }
-
-private:
- TextImage *_image[2];
-
-};
-
-class CLabelHeader : public Label
-{
-public:
- CLabelHeader() : Label("")
- {
- _dualImage = new CTextImage2();
- _dualImage->setColor2(Color(255, 170, 0, 0));
- _row = -2;
- _useFgColorAsImageColor = true;
- _offset[0] = 0;
- _offset[1] = 0;
- }
-
- ~CLabelHeader()
- {
- delete _dualImage;
- }
-
- void setRow(int row)
- {
- _row = row;
- }
-
- void setFgColorAsImageColor(bool state)
- {
- _useFgColorAsImageColor = state;
- }
-
- virtual void setText(int textBufferLen, const char* text)
- {
- _dualImage->GetImage(0)->setText(text);
-
- // calculate the text size
- Font *font = _dualImage->GetImage(0)->getFont();
- _gap = 0;
- for (const char *ch = text; *ch != 0; ch++)
- {
- int a, b, c;
- font->getCharABCwide(*ch, a, b, c);
- _gap += (a + b + c);
- }
-
- _gap += XRES(5);
- }
-
- virtual void setText(const char* text)
- {
- // strip any non-alnum characters from the end
- char buf[512];
- strcpy(buf, text);
-
- size_t len = strlen(buf);
- while (len && isspace(buf[--len]))
- {
- buf[len] = 0;
- }
-
- CLabelHeader::setText(0, buf);
- }
-
- void setText2(const char *text)
- {
- _dualImage->GetImage(1)->setText(text);
- }
-
- void getTextSize(int &wide, int &tall)
- {
- _dualImage->getSize(wide, tall);
- }
-
- void setFgColor(int r,int g,int b,int a)
- {
- Label::setFgColor(r,g,b,a);
- Color color(r,g,b,a);
- _dualImage->setColor(color);
- _dualImage->setColor2(color);
- if (_image && _useFgColorAsImageColor)
- {
- _image->setColor(color);
- }
- repaint();
- }
-
- void setFgColor(Scheme::SchemeColor sc)
- {
- int r, g, b, a;
- Label::setFgColor(sc);
- Label::getFgColor( r, g, b, a );
-
- // Call the r,g,b,a version so it sets the color in the dualImage..
- setFgColor( r, g, b, a );
- }
-
- void setFont(Font *font)
- {
- _dualImage->GetImage(0)->setFont(font);
- }
-
- void setFont2(Font *font)
- {
- _dualImage->GetImage(1)->setFont(font);
- }
-
- // this adjust the absolute position of the text after alignment is calculated
- void setTextOffset(int x, int y)
- {
- _offset[0] = x;
- _offset[1] = y;
- }
-
- void paint();
- void paintBackground();
- void calcAlignment(int iwide, int itall, int &x, int &y);
-
-private:
- CTextImage2 *_dualImage;
- int _row;
- int _gap;
- int _offset[2];
- bool _useFgColorAsImageColor;
-};
-
+#ifndef CLABELHEADER_H
+#define CLABELHEADER_H
+
+#include
+#include "cl_dll/vgui_TeamFortressViewport.h"
+
+class CTextImage2 : public Image
+{
+public:
+ CTextImage2()
+ {
+ _image[0] = new TextImage("");
+ _image[1] = new TextImage("");
+ }
+
+ ~CTextImage2()
+ {
+ delete _image[0];
+ delete _image[1];
+ }
+
+ TextImage *GetImage(int image)
+ {
+ return _image[image];
+ }
+
+ void getSize(int &wide, int &tall)
+ {
+ int w1, w2, t1, t2;
+ _image[0]->getTextSize(w1, t1);
+ _image[1]->getTextSize(w2, t2);
+
+ wide = w1 + w2;
+ tall = max(t1, t2);
+ setSize(wide, tall);
+ }
+
+ void doPaint(Panel *panel)
+ {
+ _image[0]->doPaint(panel);
+ _image[1]->doPaint(panel);
+ }
+
+ void setPos(int x, int y)
+ {
+ _image[0]->setPos(x, y);
+
+ int swide, stall;
+ _image[0]->getSize(swide, stall);
+
+ int wide, tall;
+ _image[1]->getSize(wide, tall);
+ _image[1]->setPos(x + wide, y + (stall * 0.9) - tall);
+ }
+
+ void setColor(Color color)
+ {
+ _image[0]->setColor(color);
+ }
+
+ void setColor2(Color color)
+ {
+ _image[1]->setColor(color);
+ }
+
+private:
+ TextImage *_image[2];
+
+};
+
+class CLabelHeader : public Label
+{
+public:
+ CLabelHeader() : Label("")
+ {
+ _dualImage = new CTextImage2();
+ _dualImage->setColor2(Color(255, 170, 0, 0));
+ _row = -2;
+ _useFgColorAsImageColor = true;
+ _offset[0] = 0;
+ _offset[1] = 0;
+ }
+
+ ~CLabelHeader()
+ {
+ delete _dualImage;
+ }
+
+ void setRow(int row)
+ {
+ _row = row;
+ }
+
+ void setFgColorAsImageColor(bool state)
+ {
+ _useFgColorAsImageColor = state;
+ }
+
+ virtual void setText(int textBufferLen, const char* text)
+ {
+ _dualImage->GetImage(0)->setText(text);
+
+ // calculate the text size
+ Font *font = _dualImage->GetImage(0)->getFont();
+ _gap = 0;
+ for (const char *ch = text; *ch != 0; ch++)
+ {
+ int a, b, c;
+ font->getCharABCwide(*ch, a, b, c);
+ _gap += (a + b + c);
+ }
+
+ _gap += XRES(5);
+ }
+
+ virtual void setText(const char* text)
+ {
+ // strip any non-alnum characters from the end
+ char buf[512];
+ strcpy(buf, text);
+
+ size_t len = strlen(buf);
+ while (len && isspace(buf[--len]))
+ {
+ buf[len] = 0;
+ }
+
+ CLabelHeader::setText(0, buf);
+ }
+
+ void setText2(const char *text)
+ {
+ _dualImage->GetImage(1)->setText(text);
+ }
+
+ void getTextSize(int &wide, int &tall)
+ {
+ _dualImage->getSize(wide, tall);
+ }
+
+ void setFgColor(int r,int g,int b,int a)
+ {
+ Label::setFgColor(r,g,b,a);
+ Color color(r,g,b,a);
+ _dualImage->setColor(color);
+ _dualImage->setColor2(color);
+ if (_image && _useFgColorAsImageColor)
+ {
+ _image->setColor(color);
+ }
+ repaint();
+ }
+
+ void setFgColor(Scheme::SchemeColor sc)
+ {
+ int r, g, b, a;
+ Label::setFgColor(sc);
+ Label::getFgColor( r, g, b, a );
+
+ // Call the r,g,b,a version so it sets the color in the dualImage..
+ setFgColor( r, g, b, a );
+ }
+
+ void setFont(Font *font)
+ {
+ _dualImage->GetImage(0)->setFont(font);
+ }
+
+ void setFont2(Font *font)
+ {
+ _dualImage->GetImage(1)->setFont(font);
+ }
+
+ // this adjust the absolute position of the text after alignment is calculated
+ void setTextOffset(int x, int y)
+ {
+ _offset[0] = x;
+ _offset[1] = y;
+ }
+
+ void paint();
+ void paintBackground();
+ void calcAlignment(int iwide, int itall, int &x, int &y);
+
+private:
+ CTextImage2 *_dualImage;
+ int _row;
+ int _gap;
+ int _offset[2];
+ bool _useFgColorAsImageColor;
+};
+
#endif
\ No newline at end of file
diff --git a/main/source/cl_dll/GameStudioModelRenderer.cpp b/main/source/cl_dll/GameStudioModelRenderer.cpp
index 67c73dee..71d0c50c 100644
--- a/main/source/cl_dll/GameStudioModelRenderer.cpp
+++ b/main/source/cl_dll/GameStudioModelRenderer.cpp
@@ -1,116 +1,116 @@
-#include
-#include "hud.h"
-#include "cl_util.h"
-#include "common/const.h"
-#include "common/com_model.h"
-#include "engine/studio.h"
-#include "common/entity_state.h"
-#include "common/cl_entity.h"
-#include "common/dlight.h"
-#include "common/triangleapi.h"
-
-#include
-#include
-#include
-#include
-
-#include "studio_util.h"
-#include "r_studioint.h"
-
-#include "StudioModelRenderer.h"
-#include "GameStudioModelRenderer.h"
-
-#include "engine/APIProxy.h"
-#include "Exports.h"
-
-//
-// Override the StudioModelRender virtual member functions here to implement custom bone
-// setup, blending, etc.
-//
-
-// Global engine <-> studio model rendering code interface
-extern engine_studio_api_t IEngineStudio;
-
-// The renderer object, created on the stack.
-CGameStudioModelRenderer g_StudioRenderer;
-/*
-====================
-CGameStudioModelRenderer
-
-====================
-*/
-CGameStudioModelRenderer::CGameStudioModelRenderer( void )
-{
-}
-
-////////////////////////////////////
-// Hooks to class implementation
-////////////////////////////////////
-
-/*
-====================
-R_StudioDrawPlayer
-
-====================
-*/
-int R_StudioDrawPlayer( int flags, entity_state_t *pplayer )
-{
- return g_StudioRenderer.StudioDrawPlayer( flags, pplayer );
-}
-
-/*
-====================
-R_StudioDrawModel
-
-====================
-*/
-int R_StudioDrawModel( int flags )
-{
- return g_StudioRenderer.StudioDrawModel( flags );
-}
-
-/*
-====================
-R_StudioInit
-
-====================
-*/
-void R_StudioInit( void )
-{
- g_StudioRenderer.Init();
-}
-
-// The simple drawing interface we'll pass back to the engine
-r_studio_interface_t studio =
-{
- STUDIO_INTERFACE_VERSION,
- R_StudioDrawModel,
- R_StudioDrawPlayer,
-};
-
-/*
-====================
-HUD_GetStudioModelInterface
-
-Export this function for the engine to use the studio renderer class to render objects.
-====================
-*/
-extern "C" int CL_DLLEXPORT HUD_GetStudioModelInterface( int version, struct r_studio_interface_s **ppinterface, struct engine_studio_api_s *pstudio )
-{
-// RecClStudioInterface(version, ppinterface, pstudio);
-
- if ( version != STUDIO_INTERFACE_VERSION )
- return 0;
-
- // Point the engine to our callbacks
- *ppinterface = &studio;
-
- // Copy in engine helper functions
- memcpy( &IEngineStudio, pstudio, sizeof( IEngineStudio ) );
-
- // Initialize local variables, etc.
- R_StudioInit();
-
- // Success
- return 1;
-}
+#include
+#include "hud.h"
+#include "cl_util.h"
+#include "common/const.h"
+#include "common/com_model.h"
+#include "engine/studio.h"
+#include "common/entity_state.h"
+#include "common/cl_entity.h"
+#include "common/dlight.h"
+#include "common/triangleapi.h"
+
+#include
+#include
+#include
+#include
+
+#include "studio_util.h"
+#include "r_studioint.h"
+
+#include "StudioModelRenderer.h"
+#include "GameStudioModelRenderer.h"
+
+#include "engine/APIProxy.h"
+#include "Exports.h"
+
+//
+// Override the StudioModelRender virtual member functions here to implement custom bone
+// setup, blending, etc.
+//
+
+// Global engine <-> studio model rendering code interface
+extern engine_studio_api_t IEngineStudio;
+
+// The renderer object, created on the stack.
+CGameStudioModelRenderer g_StudioRenderer;
+/*
+====================
+CGameStudioModelRenderer
+
+====================
+*/
+CGameStudioModelRenderer::CGameStudioModelRenderer( void )
+{
+}
+
+////////////////////////////////////
+// Hooks to class implementation
+////////////////////////////////////
+
+/*
+====================
+R_StudioDrawPlayer
+
+====================
+*/
+int R_StudioDrawPlayer( int flags, entity_state_t *pplayer )
+{
+ return g_StudioRenderer.StudioDrawPlayer( flags, pplayer );
+}
+
+/*
+====================
+R_StudioDrawModel
+
+====================
+*/
+int R_StudioDrawModel( int flags )
+{
+ return g_StudioRenderer.StudioDrawModel( flags );
+}
+
+/*
+====================
+R_StudioInit
+
+====================
+*/
+void R_StudioInit( void )
+{
+ g_StudioRenderer.Init();
+}
+
+// The simple drawing interface we'll pass back to the engine
+r_studio_interface_t studio =
+{
+ STUDIO_INTERFACE_VERSION,
+ R_StudioDrawModel,
+ R_StudioDrawPlayer,
+};
+
+/*
+====================
+HUD_GetStudioModelInterface
+
+Export this function for the engine to use the studio renderer class to render objects.
+====================
+*/
+extern "C" int CL_DLLEXPORT HUD_GetStudioModelInterface( int version, struct r_studio_interface_s **ppinterface, struct engine_studio_api_s *pstudio )
+{
+// RecClStudioInterface(version, ppinterface, pstudio);
+
+ if ( version != STUDIO_INTERFACE_VERSION )
+ return 0;
+
+ // Point the engine to our callbacks
+ *ppinterface = &studio;
+
+ // Copy in engine helper functions
+ memcpy( &IEngineStudio, pstudio, sizeof( IEngineStudio ) );
+
+ // Initialize local variables, etc.
+ R_StudioInit();
+
+ // Success
+ return 1;
+}
diff --git a/main/source/cl_dll/GameStudioModelRenderer.h b/main/source/cl_dll/GameStudioModelRenderer.h
index 92c596e6..7b37d8c9 100644
--- a/main/source/cl_dll/GameStudioModelRenderer.h
+++ b/main/source/cl_dll/GameStudioModelRenderer.h
@@ -1,19 +1,19 @@
-#if !defined( GAMESTUDIOMODELRENDERER_H )
-#define GAMESTUDIOMODELRENDERER_H
-#if defined( _WIN32 )
-#pragma once
-#endif
-
-/*
-====================
-CGameStudioModelRenderer
-
-====================
-*/
-class CGameStudioModelRenderer : public CStudioModelRenderer
-{
-public:
- CGameStudioModelRenderer( void );
-};
-
+#if !defined( GAMESTUDIOMODELRENDERER_H )
+#define GAMESTUDIOMODELRENDERER_H
+#if defined( _WIN32 )
+#pragma once
+#endif
+
+/*
+====================
+CGameStudioModelRenderer
+
+====================
+*/
+class CGameStudioModelRenderer : public CStudioModelRenderer
+{
+public:
+ CGameStudioModelRenderer( void );
+};
+
#endif // GAMESTUDIOMODELRENDERER_H
\ No newline at end of file
diff --git a/main/source/cl_dll/GameStudioModelRenderer_Sample.cpp b/main/source/cl_dll/GameStudioModelRenderer_Sample.cpp
index d9592b05..03a69707 100644
--- a/main/source/cl_dll/GameStudioModelRenderer_Sample.cpp
+++ b/main/source/cl_dll/GameStudioModelRenderer_Sample.cpp
@@ -1,985 +1,985 @@
-#include
-#include "hud.h"
-#include "cl_util.h"
-#include "const.h"
-#include "com_model.h"
-#include "studio.h"
-#include "entity_state.h"
-#include "cl_entity.h"
-#include "dlight.h"
-#include "triangleapi.h"
-
-#include
-#include
-#include
-#include
-
-#include "studio_util.h"
-#include "r_studioint.h"
-
-#include "StudioModelRenderer.h"
-#include "GameStudioModelRenderer.h"
-
-// Predicted values saved off in hl_weapons.cpp
-void Game_GetSequence( int *seq, int *gaitseq );
-void Game_GetOrientation( float *o, float *a );
-
-float g_flStartScaleTime;
-int iPrevRenderState;
-int iRenderStateChanged;
-
-// Global engine <-> studio model rendering code interface
-extern engine_studio_api_t IEngineStudio;
-
-typedef struct
-{
- vec3_t origin;
- vec3_t angles;
-
- vec3_t realangles;
-
- float animtime;
- float frame;
- int sequence;
- int gaitsequence;
- float framerate;
-
- int m_fSequenceLoops;
- int m_fSequenceFinished;
-
- byte controller[ 4 ];
- byte blending[ 2 ];
-
- latchedvars_t lv;
-} client_anim_state_t;
-
-static client_anim_state_t g_state;
-static client_anim_state_t g_clientstate;
-
-// The renderer object, created on the stack.
-CGameStudioModelRenderer g_StudioRenderer;
-/*
-====================
-CGameStudioModelRenderer
-
-====================
-*/
-CGameStudioModelRenderer::CGameStudioModelRenderer( void )
-{
- // If you want to predict animations locally, set this to TRUE
- // NOTE: The animation code is somewhat broken, but gives you a sense for how
- // to do client side animation of the predicted player in a third person game.
- m_bLocal = false;
-}
-
-/*
-====================
-StudioSetupBones
-
-====================
-*/
-void CGameStudioModelRenderer::StudioSetupBones ( void )
-{
- int i;
- double f;
-
- mstudiobone_t *pbones;
- mstudioseqdesc_t *pseqdesc;
- mstudioanim_t *panim;
-
- static float pos[MAXSTUDIOBONES][3];
- static vec4_t q[MAXSTUDIOBONES];
- float bonematrix[3][4];
-
- static float pos2[MAXSTUDIOBONES][3];
- static vec4_t q2[MAXSTUDIOBONES];
- static float pos3[MAXSTUDIOBONES][3];
- static vec4_t q3[MAXSTUDIOBONES];
- static float pos4[MAXSTUDIOBONES][3];
- static vec4_t q4[MAXSTUDIOBONES];
-
- // Use default bone setup for nonplayers
- if ( !m_pCurrentEntity->player )
- {
- CStudioModelRenderer::StudioSetupBones();
- return;
- }
-
- // Bound sequence number.
- if ( m_pCurrentEntity->curstate.sequence >= m_pStudioHeader->numseq )
- {
- m_pCurrentEntity->curstate.sequence = 0;
- }
-
- pseqdesc = (mstudioseqdesc_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqindex) + m_pCurrentEntity->curstate.sequence;
-
- if ( m_pPlayerInfo && m_pPlayerInfo->gaitsequence != 0 )
- {
- f = m_pPlayerInfo->gaitframe;
- }
- else
- {
- f = StudioEstimateFrame( pseqdesc );
- }
-
- // This game knows how to do three way blending
- if ( pseqdesc->numblends == 3 )
- {
- float s;
-
- // Get left anim
- panim = StudioGetAnim( m_pRenderModel, pseqdesc );
-
- // Blending is 0-127 == Left to Middle, 128 to 255 == Middle to right
- if ( m_pCurrentEntity->curstate.blending[0] <= 127 )
- {
- StudioCalcRotations( pos, q, pseqdesc, panim, f );
-
- // Scale 0-127 blending up to 0-255
- s = m_pCurrentEntity->curstate.blending[0];
- s = ( s * 2.0 );
- }
- else
- {
-
- // Skip ahead to middle
- panim += m_pStudioHeader->numbones;
-
- StudioCalcRotations( pos, q, pseqdesc, panim, f );
-
- // Scale 127-255 blending up to 0-255
- s = m_pCurrentEntity->curstate.blending[0];
- s = 2.0 * ( s - 127.0 );
- }
-
- // Normalize interpolant
- s /= 255.0;
-
- // Go to middle or right
- panim += m_pStudioHeader->numbones;
-
- StudioCalcRotations( pos2, q2, pseqdesc, panim, f );
-
- // Spherically interpolate the bones
- StudioSlerpBones( q, pos, q2, pos2, s );
- }
- else
- {
- panim = StudioGetAnim( m_pRenderModel, pseqdesc );
- StudioCalcRotations( pos, q, pseqdesc, panim, f );
- }
-
- // Are we in the process of transitioning from one sequence to another.
- if ( m_fDoInterp &&
- m_pCurrentEntity->latched.sequencetime &&
- ( m_pCurrentEntity->latched.sequencetime + 0.2 > m_clTime ) &&
- ( m_pCurrentEntity->latched.prevsequence < m_pStudioHeader->numseq ))
- {
- // blend from last sequence
- static float pos1b[MAXSTUDIOBONES][3];
- static vec4_t q1b[MAXSTUDIOBONES];
- float s;
-
- // Blending value into last sequence
- unsigned char prevseqblending = m_pCurrentEntity->latched.prevseqblending[ 0 ];
-
- // Point at previous sequenece
- pseqdesc = (mstudioseqdesc_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqindex) + m_pCurrentEntity->latched.prevsequence;
-
- // Know how to do three way blends
- if ( pseqdesc->numblends == 3 )
- {
- float s;
-
- // Get left animation
- panim = StudioGetAnim( m_pRenderModel, pseqdesc );
-
- if ( prevseqblending <= 127 )
- {
- // Set up bones based on final frame of previous sequence
- StudioCalcRotations( pos1b, q1b, pseqdesc, panim, m_pCurrentEntity->latched.prevframe );
-
- s = prevseqblending;
- s = ( s * 2.0 );
- }
- else
- {
- // Skip to middle blend
- panim += m_pStudioHeader->numbones;
-
- StudioCalcRotations( pos1b, q1b, pseqdesc, panim, m_pCurrentEntity->latched.prevframe );
-
- s = prevseqblending;
- s = 2.0 * ( s - 127.0 );
- }
-
- // Normalize
- s /= 255.0;
-
- panim += m_pStudioHeader->numbones;
- StudioCalcRotations( pos2, q2, pseqdesc, panim, m_pCurrentEntity->latched.prevframe );
-
- // Interpolate bones
- StudioSlerpBones( q1b, pos1b, q2, pos2, s );
- }
- else
- {
- panim = StudioGetAnim( m_pRenderModel, pseqdesc );
- // clip prevframe
- StudioCalcRotations( pos1b, q1b, pseqdesc, panim, m_pCurrentEntity->latched.prevframe );
- }
-
- // Now blend last frame of previous sequence with current sequence.
- s = 1.0 - (m_clTime - m_pCurrentEntity->latched.sequencetime) / 0.2;
- StudioSlerpBones( q, pos, q1b, pos1b, s );
- }
- else
- {
- m_pCurrentEntity->latched.prevframe = f;
- }
-
- // Now convert quaternions and bone positions into matrices
- pbones = (mstudiobone_t *)((byte *)m_pStudioHeader + m_pStudioHeader->boneindex);
-
- for (i = 0; i < m_pStudioHeader->numbones; i++)
- {
- QuaternionMatrix( q[i], bonematrix );
-
- bonematrix[0][3] = pos[i][0];
- bonematrix[1][3] = pos[i][1];
- bonematrix[2][3] = pos[i][2];
-
- if (pbones[i].parent == -1)
- {
- if ( IEngineStudio.IsHardware() )
- {
- ConcatTransforms ((*m_protationmatrix), bonematrix, (*m_pbonetransform)[i]);
- ConcatTransforms ((*m_protationmatrix), bonematrix, (*m_plighttransform)[i]);
- }
- else
- {
- ConcatTransforms ((*m_paliastransform), bonematrix, (*m_pbonetransform)[i]);
- ConcatTransforms ((*m_protationmatrix), bonematrix, (*m_plighttransform)[i]);
- }
-
- // Apply client-side effects to the transformation matrix
- StudioFxTransform( m_pCurrentEntity, (*m_pbonetransform)[i] );
- }
- else
- {
- ConcatTransforms ((*m_pbonetransform)[pbones[i].parent], bonematrix, (*m_pbonetransform)[i]);
- ConcatTransforms ((*m_plighttransform)[pbones[i].parent], bonematrix, (*m_plighttransform)[i]);
- }
- }
-}
-
-/*
-====================
-StudioEstimateGait
-
-====================
-*/
-void CGameStudioModelRenderer::StudioEstimateGait( entity_state_t *pplayer )
-{
- float dt;
- vec3_t est_velocity;
-
- dt = (m_clTime - m_clOldTime);
- dt = max( 0.0, dt );
- dt = min( 1.0, dt );
-
- if (dt == 0 || m_pPlayerInfo->renderframe == m_nFrameCount)
- {
- m_flGaitMovement = 0;
- return;
- }
-
- // VectorAdd( pplayer->velocity, pplayer->prediction_error, est_velocity );
- if ( m_fGaitEstimation )
- {
- VectorSubtract( m_pCurrentEntity->origin, m_pPlayerInfo->prevgaitorigin, est_velocity );
- VectorCopy( m_pCurrentEntity->origin, m_pPlayerInfo->prevgaitorigin );
- m_flGaitMovement = Length( est_velocity );
- if (dt <= 0 || m_flGaitMovement / dt < 5)
- {
- m_flGaitMovement = 0;
- est_velocity[0] = 0;
- est_velocity[1] = 0;
- }
- }
- else
- {
- VectorCopy( pplayer->velocity, est_velocity );
- m_flGaitMovement = Length( est_velocity ) * dt;
- }
-
- if (est_velocity[1] == 0 && est_velocity[0] == 0)
- {
- float flYawDiff = m_pCurrentEntity->angles[YAW] - m_pPlayerInfo->gaityaw;
- flYawDiff = flYawDiff - (int)(flYawDiff / 360) * 360;
- if (flYawDiff > 180)
- flYawDiff -= 360;
- if (flYawDiff < -180)
- flYawDiff += 360;
-
- if (dt < 0.25)
- flYawDiff *= dt * 4;
- else
- flYawDiff *= dt;
-
- m_pPlayerInfo->gaityaw += flYawDiff;
- m_pPlayerInfo->gaityaw = m_pPlayerInfo->gaityaw - (int)(m_pPlayerInfo->gaityaw / 360) * 360;
-
- m_flGaitMovement = 0;
- }
- else
- {
- m_pPlayerInfo->gaityaw = (atan2(est_velocity[1], est_velocity[0]) * 180 / M_PI);
- if (m_pPlayerInfo->gaityaw > 180)
- m_pPlayerInfo->gaityaw = 180;
- if (m_pPlayerInfo->gaityaw < -180)
- m_pPlayerInfo->gaityaw = -180;
- }
-
-}
-
-/*
-====================
-StudioProcessGait
-
-====================
-*/
-void CGameStudioModelRenderer::StudioProcessGait( entity_state_t *pplayer )
-{
- mstudioseqdesc_t *pseqdesc;
- float dt;
- float flYaw; // view direction relative to movement
-
- pseqdesc = (mstudioseqdesc_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqindex) + m_pCurrentEntity->curstate.sequence;
-
- m_pCurrentEntity->angles[PITCH] = 0;
- m_pCurrentEntity->latched.prevangles[PITCH] = m_pCurrentEntity->angles[PITCH];
-
- dt = (m_clTime - m_clOldTime);
- dt = max( 0.0, dt );
- dt = min( 1.0, dt );
-
- StudioEstimateGait( pplayer );
-
- // calc side to side turning
- flYaw = m_pCurrentEntity->angles[YAW] - m_pPlayerInfo->gaityaw;
-
- flYaw = fmod( flYaw, 360.0 );
-
- if (flYaw < -180)
- {
- flYaw = flYaw + 360;
- }
- else if (flYaw > 180)
- {
- flYaw = flYaw - 360;
- }
-
- float maxyaw = 120.0;
-
- if (flYaw > maxyaw)
- {
- m_pPlayerInfo->gaityaw = m_pPlayerInfo->gaityaw - 180;
- m_flGaitMovement = -m_flGaitMovement;
- flYaw = flYaw - 180;
- }
- else if (flYaw < -maxyaw)
- {
- m_pPlayerInfo->gaityaw = m_pPlayerInfo->gaityaw + 180;
- m_flGaitMovement = -m_flGaitMovement;
- flYaw = flYaw + 180;
- }
-
- float blend_yaw = ( flYaw / 90.0 ) * 128.0 + 127.0;
- blend_yaw = min( 255.0, blend_yaw );
- blend_yaw = max( 0.0, blend_yaw );
-
- blend_yaw = 255.0 - blend_yaw;
-
- m_pCurrentEntity->curstate.blending[0] = (int)(blend_yaw);
- m_pCurrentEntity->latched.prevblending[0] = m_pCurrentEntity->curstate.blending[0];
- m_pCurrentEntity->latched.prevseqblending[0] = m_pCurrentEntity->curstate.blending[0];
-
- m_pCurrentEntity->angles[YAW] = m_pPlayerInfo->gaityaw;
- if (m_pCurrentEntity->angles[YAW] < -0)
- {
- m_pCurrentEntity->angles[YAW] += 360;
- }
- m_pCurrentEntity->latched.prevangles[YAW] = m_pCurrentEntity->angles[YAW];
-
- pseqdesc = (mstudioseqdesc_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqindex) + pplayer->gaitsequence;
-
- // Calc gait frame
- if (pseqdesc->linearmovement[0] > 0)
- {
- m_pPlayerInfo->gaitframe += (m_flGaitMovement / pseqdesc->linearmovement[0]) * pseqdesc->numframes;
- }
- else
- {
- m_pPlayerInfo->gaitframe += pseqdesc->fps * dt * m_pCurrentEntity->curstate.framerate;
- }
-
- // Do modulo
- m_pPlayerInfo->gaitframe = m_pPlayerInfo->gaitframe - (int)(m_pPlayerInfo->gaitframe / pseqdesc->numframes) * pseqdesc->numframes;
- if (m_pPlayerInfo->gaitframe < 0)
- {
- m_pPlayerInfo->gaitframe += pseqdesc->numframes;
- }
-}
-
-/*
-==============================
-SavePlayerState
-
-For local player, in third person, we need to store real render data and then
- setup for with fake/client side animation data
-==============================
-*/
-void CGameStudioModelRenderer::SavePlayerState( entity_state_t *pplayer )
-{
- client_anim_state_t *st;
- cl_entity_t *ent = IEngineStudio.GetCurrentEntity();
- assert( ent );
- if ( !ent )
- return;
-
- st = &g_state;
-
- st->angles = ent->curstate.angles;
- st->origin = ent->curstate.origin;
-
- st->realangles = ent->angles;
-
- st->sequence = ent->curstate.sequence;
- st->gaitsequence = pplayer->gaitsequence;
- st->animtime = ent->curstate.animtime;
- st->frame = ent->curstate.frame;
- st->framerate = ent->curstate.framerate;
- memcpy( st->blending, ent->curstate.blending, 2 );
- memcpy( st->controller, ent->curstate.controller, 4 );
-
- st->lv = ent->latched;
-}
-
-void GetSequenceInfo( void *pmodel, client_anim_state_t *pev, float *pflFrameRate, float *pflGroundSpeed )
-{
- studiohdr_t *pstudiohdr;
-
- pstudiohdr = (studiohdr_t *)pmodel;
- if (! pstudiohdr)
- return;
-
- mstudioseqdesc_t *pseqdesc;
-
- if (pev->sequence >= pstudiohdr->numseq)
- {
- *pflFrameRate = 0.0;
- *pflGroundSpeed = 0.0;
- return;
- }
-
- pseqdesc = (mstudioseqdesc_t *)((byte *)pstudiohdr + pstudiohdr->seqindex) + (int)pev->sequence;
-
- if (pseqdesc->numframes > 1)
- {
- *pflFrameRate = 256 * pseqdesc->fps / (pseqdesc->numframes - 1);
- *pflGroundSpeed = sqrt( pseqdesc->linearmovement[0]*pseqdesc->linearmovement[0]+ pseqdesc->linearmovement[1]*pseqdesc->linearmovement[1]+ pseqdesc->linearmovement[2]*pseqdesc->linearmovement[2] );
- *pflGroundSpeed = *pflGroundSpeed * pseqdesc->fps / (pseqdesc->numframes - 1);
- }
- else
- {
- *pflFrameRate = 256.0;
- *pflGroundSpeed = 0.0;
- }
-}
-
-int GetSequenceFlags( void *pmodel, client_anim_state_t *pev )
-{
- studiohdr_t *pstudiohdr;
-
- pstudiohdr = (studiohdr_t *)pmodel;
- if ( !pstudiohdr || pev->sequence >= pstudiohdr->numseq )
- return 0;
-
- mstudioseqdesc_t *pseqdesc;
- pseqdesc = (mstudioseqdesc_t *)((byte *)pstudiohdr + pstudiohdr->seqindex) + (int)pev->sequence;
-
- return pseqdesc->flags;
-}
-
-float StudioFrameAdvance ( client_anim_state_t *st, float framerate, float flInterval )
-{
- if (flInterval == 0.0)
- {
- flInterval = (gEngfuncs.GetClientTime() - st->animtime);
- if (flInterval <= 0.001)
- {
- st->animtime = gEngfuncs.GetClientTime();
- return 0.0;
- }
- }
- if (!st->animtime)
- flInterval = 0.0;
-
- st->frame += flInterval * framerate * st->framerate;
- st->animtime = gEngfuncs.GetClientTime();
-
- if (st->frame < 0.0 || st->frame >= 256.0)
- {
- if ( st->m_fSequenceLoops )
- st->frame -= (int)(st->frame / 256.0) * 256.0;
- else
- st->frame = (st->frame < 0.0) ? 0 : 255;
- st->m_fSequenceFinished = TRUE; // just in case it wasn't caught in GetEvents
- }
-
- return flInterval;
-}
-
-/*
-==============================
-SetupClientAnimation
-
-Called to set up local player's animation values
-==============================
-*/
-void CGameStudioModelRenderer::SetupClientAnimation( entity_state_t *pplayer )
-{
- static double oldtime;
- double curtime, dt;
-
- client_anim_state_t *st;
- float fr, gs;
-
- cl_entity_t *ent = IEngineStudio.GetCurrentEntity();
- assert( ent );
- if ( !ent )
- return;
-
- curtime = gEngfuncs.GetClientTime();
- dt = curtime - oldtime;
- dt = min( 1.0, max( 0.0, dt ) );
-
- oldtime = curtime;
- st = &g_clientstate;
-
- st->framerate = 1.0;
-
- int oldseq = st->sequence;
- Game_GetSequence( &st->sequence, &st->gaitsequence ); //CVAR_GET_FLOAT( "sequence" );
- Game_GetOrientation( (float *)&st->origin, (float *)&st->angles );
- st->realangles = st->angles;
-
- if ( st->sequence != oldseq )
- {
- st->frame = 0.0;
- st->lv.prevsequence = oldseq;
- st->lv.sequencetime = st->animtime;
-
- memcpy( st->lv.prevseqblending, st->blending, 2 );
- memcpy( st->lv.prevcontroller, st->controller, 4 );
- }
-
- void *pmodel = (studiohdr_t *)IEngineStudio.Mod_Extradata( ent->model );
-
- GetSequenceInfo( pmodel, st, &fr, &gs );
- st->m_fSequenceLoops = ((GetSequenceFlags( pmodel, st ) & STUDIO_LOOPING) != 0);
- StudioFrameAdvance( st, fr, dt );
-
-// gEngfuncs.Con_Printf( "gs %i frame %f\n", st->gaitsequence, st->frame );
-
- ent->angles = st->realangles;
- ent->curstate.angles = st->angles;
- ent->curstate.origin = st->origin;
-
- ent->curstate.sequence = st->sequence;
- pplayer->gaitsequence = st->gaitsequence;
- ent->curstate.animtime = st->animtime;
- ent->curstate.frame = st->frame;
- ent->curstate.framerate = st->framerate;
- memcpy( ent->curstate.blending, st->blending, 2 );
- memcpy( ent->curstate.controller, st->controller, 4 );
-
- ent->latched = st->lv;
-}
-
-/*
-==============================
-RestorePlayerState
-
-Called to restore original player state information
-==============================
-*/
-void CGameStudioModelRenderer::RestorePlayerState( entity_state_t *pplayer )
-{
- client_anim_state_t *st;
- cl_entity_t *ent = IEngineStudio.GetCurrentEntity();
- assert( ent );
- if ( !ent )
- return;
-
- st = &g_clientstate;
-
- st->angles = ent->curstate.angles;
- st->origin = ent->curstate.origin;
- st->realangles = ent->angles;
-
- st->sequence = ent->curstate.sequence;
- st->gaitsequence = pplayer->gaitsequence;
- st->animtime = ent->curstate.animtime;
- st->frame = ent->curstate.frame;
- st->framerate = ent->curstate.framerate;
- memcpy( st->blending, ent->curstate.blending, 2 );
- memcpy( st->controller, ent->curstate.controller, 4 );
-
- st->lv = ent->latched;
-
- st = &g_state;
-
- ent->curstate.angles = st->angles;
- ent->curstate.origin = st->origin;
- ent->angles = st->realangles;
-
- ent->curstate.sequence = st->sequence;
- pplayer->gaitsequence = st->gaitsequence;
- ent->curstate.animtime = st->animtime;
- ent->curstate.frame = st->frame;
- ent->curstate.framerate = st->framerate;
- memcpy( ent->curstate.blending, st->blending, 2 );
- memcpy( ent->curstate.controller, st->controller, 4 );
-
- ent->latched = st->lv;
-}
-
-/*
-==============================
-StudioDrawPlayer
-
-==============================
-*/
-int CGameStudioModelRenderer::StudioDrawPlayer( int flags, entity_state_t *pplayer )
-{
- int iret = 0;
-
- bool isLocalPlayer = false;
-
- // Set up for client?
- if ( m_bLocal && IEngineStudio.GetCurrentEntity() == gEngfuncs.GetLocalPlayer() )
- {
- isLocalPlayer = true;
- }
-
- if ( isLocalPlayer )
- {
- // Store original data
- SavePlayerState( pplayer );
-
- // Copy in client side animation data
- SetupClientAnimation( pplayer );
- }
-
- // Call real draw function
- iret = _StudioDrawPlayer( flags, pplayer );
-
- // Restore for client?
- if ( isLocalPlayer )
- {
- // Restore the original data for the player
- RestorePlayerState( pplayer );
- }
-
- return iret;
-}
-
-/*
-====================
-_StudioDrawPlayer
-
-====================
-*/
-int CGameStudioModelRenderer::_StudioDrawPlayer( int flags, entity_state_t *pplayer )
-{
- alight_t lighting;
- vec3_t dir;
-
- m_pCurrentEntity = IEngineStudio.GetCurrentEntity();
- IEngineStudio.GetTimes( &m_nFrameCount, &m_clTime, &m_clOldTime );
- IEngineStudio.GetViewInfo( m_vRenderOrigin, m_vUp, m_vRight, m_vNormal );
- IEngineStudio.GetAliasScale( &m_fSoftwareXScale, &m_fSoftwareYScale );
-
- m_nPlayerIndex = pplayer->number - 1;
-
- if (m_nPlayerIndex < 0 || m_nPlayerIndex >= gEngfuncs.GetMaxClients())
- return 0;
-
- m_pRenderModel = IEngineStudio.SetupPlayerModel( m_nPlayerIndex );
- if (m_pRenderModel == NULL)
- return 0;
-
- m_pStudioHeader = (studiohdr_t *)IEngineStudio.Mod_Extradata (m_pRenderModel);
- IEngineStudio.StudioSetHeader( m_pStudioHeader );
- IEngineStudio.SetRenderModel( m_pRenderModel );
-
- if (pplayer->gaitsequence)
- {
- vec3_t orig_angles;
- m_pPlayerInfo = IEngineStudio.PlayerInfo( m_nPlayerIndex );
-
- VectorCopy( m_pCurrentEntity->angles, orig_angles );
-
- StudioProcessGait( pplayer );
-
- m_pPlayerInfo->gaitsequence = pplayer->gaitsequence;
- m_pPlayerInfo = NULL;
-
- StudioSetUpTransform( 0 );
- VectorCopy( orig_angles, m_pCurrentEntity->angles );
- }
- else
- {
- m_pCurrentEntity->curstate.controller[0] = 127;
- m_pCurrentEntity->curstate.controller[1] = 127;
- m_pCurrentEntity->curstate.controller[2] = 127;
- m_pCurrentEntity->curstate.controller[3] = 127;
- m_pCurrentEntity->latched.prevcontroller[0] = m_pCurrentEntity->curstate.controller[0];
- m_pCurrentEntity->latched.prevcontroller[1] = m_pCurrentEntity->curstate.controller[1];
- m_pCurrentEntity->latched.prevcontroller[2] = m_pCurrentEntity->curstate.controller[2];
- m_pCurrentEntity->latched.prevcontroller[3] = m_pCurrentEntity->curstate.controller[3];
-
- m_pPlayerInfo = IEngineStudio.PlayerInfo( m_nPlayerIndex );
- m_pPlayerInfo->gaitsequence = 0;
-
- StudioSetUpTransform( 0 );
- }
-
- if (flags & STUDIO_RENDER)
- {
- // see if the bounding box lets us trivially reject, also sets
- if (!IEngineStudio.StudioCheckBBox ())
- return 0;
-
- (*m_pModelsDrawn)++;
- (*m_pStudioModelCount)++; // render data cache cookie
-
- if (m_pStudioHeader->numbodyparts == 0)
- return 1;
- }
-
- m_pPlayerInfo = IEngineStudio.PlayerInfo( m_nPlayerIndex );
- StudioSetupBones( );
- StudioSaveBones( );
- m_pPlayerInfo->renderframe = m_nFrameCount;
-
- m_pPlayerInfo = NULL;
-
- if (flags & STUDIO_EVENTS)
- {
- StudioCalcAttachments( );
- IEngineStudio.StudioClientEvents( );
- // copy attachments into global entity array
- if ( m_pCurrentEntity->index > 0 )
- {
- cl_entity_t *ent = gEngfuncs.GetEntityByIndex( m_pCurrentEntity->index );
-
- memcpy( ent->attachment, m_pCurrentEntity->attachment, sizeof( vec3_t ) * 4 );
- }
- }
-
- if (flags & STUDIO_RENDER)
- {
- /*
- if (m_pCvarHiModels->value && m_pRenderModel != m_pCurrentEntity->model )
- {
- // show highest resolution multiplayer model
- m_pCurrentEntity->curstate.body = 255;
- }
-
- if (!(m_pCvarDeveloper->value == 0 && gEngfuncs.GetMaxClients() == 1 ) && ( m_pRenderModel == m_pCurrentEntity->model ) )
- {
- m_pCurrentEntity->curstate.body = 1; // force helmet
- }
- */
-
- lighting.plightvec = dir;
- IEngineStudio.StudioDynamicLight(m_pCurrentEntity, &lighting );
-
- IEngineStudio.StudioEntityLight( &lighting );
-
- // model and frame independant
- IEngineStudio.StudioSetupLighting (&lighting);
-
- m_pPlayerInfo = IEngineStudio.PlayerInfo( m_nPlayerIndex );
-
- // get remap colors
- m_nTopColor = m_pPlayerInfo->topcolor;
- if (m_nTopColor < 0)
- m_nTopColor = 0;
- if (m_nTopColor > 360)
- m_nTopColor = 360;
- m_nBottomColor = m_pPlayerInfo->bottomcolor;
- if (m_nBottomColor < 0)
- m_nBottomColor = 0;
- if (m_nBottomColor > 360)
- m_nBottomColor = 360;
-
- IEngineStudio.StudioSetRemapColors( m_nTopColor, m_nBottomColor );
-
- StudioRenderModel( );
- m_pPlayerInfo = NULL;
-
- if (pplayer->weaponmodel)
- {
- cl_entity_t saveent = *m_pCurrentEntity;
-
- model_t *pweaponmodel = IEngineStudio.GetModelByIndex( pplayer->weaponmodel );
-
- m_pStudioHeader = (studiohdr_t *)IEngineStudio.Mod_Extradata (pweaponmodel);
- IEngineStudio.StudioSetHeader( m_pStudioHeader );
-
- StudioMergeBones( pweaponmodel);
-
- IEngineStudio.StudioSetupLighting (&lighting);
-
- StudioRenderModel( );
-
- StudioCalcAttachments( );
-
- *m_pCurrentEntity = saveent;
- }
- }
-
- return 1;
-}
-
-/*
-====================
-Studio_FxTransform
-
-====================
-*/
-void CGameStudioModelRenderer::StudioFxTransform( cl_entity_t *ent, float transform[3][4] )
-{
- switch( ent->curstate.renderfx )
- {
- case kRenderFxDistort:
- case kRenderFxHologram:
- if ( gEngfuncs.pfnRandomLong(0,49) == 0 )
- {
- int axis = gEngfuncs.pfnRandomLong(0,1);
- if ( axis == 1 ) // Choose between x & z
- axis = 2;
- VectorScale( transform[axis], gEngfuncs.pfnRandomFloat(1,1.484), transform[axis] );
- }
- else if ( gEngfuncs.pfnRandomLong(0,49) == 0 )
- {
- float offset;
- int axis = gEngfuncs.pfnRandomLong(0,1);
- if ( axis == 1 ) // Choose between x & z
- axis = 2;
- offset = gEngfuncs.pfnRandomFloat(-10,10);
- transform[gEngfuncs.pfnRandomLong(0,2)][3] += offset;
- }
- break;
- case kRenderFxExplode:
- {
- if ( iRenderStateChanged )
- {
- g_flStartScaleTime = m_clTime;
- iRenderStateChanged = FALSE;
- }
-
- // Make the Model continue to shrink
- float flTimeDelta = m_clTime - g_flStartScaleTime;
- if ( flTimeDelta > 0 )
- {
- float flScale = 0.001;
- // Goes almost all away
- if ( flTimeDelta <= 2.0 )
- flScale = 1.0 - (flTimeDelta / 2.0);
-
- for (int i = 0; i < 3; i++)
- {
- for (int j = 0; j < 3; j++)
- transform[i][j] *= flScale;
- }
- }
- }
- break;
- }
-}
-
-////////////////////////////////////
-// Hooks to class implementation
-////////////////////////////////////
-
-/*
-====================
-R_StudioDrawPlayer
-
-====================
-*/
-int R_StudioDrawPlayer( int flags, entity_state_t *pplayer )
-{
- return g_StudioRenderer.StudioDrawPlayer( flags, pplayer );
-}
-
-/*
-====================
-R_StudioDrawModel
-
-====================
-*/
-int R_StudioDrawModel( int flags )
-{
- return g_StudioRenderer.StudioDrawModel( flags );
-}
-
-/*
-====================
-R_StudioInit
-
-====================
-*/
-void R_StudioInit( void )
-{
- g_StudioRenderer.Init();
-}
-
-// The simple drawing interface we'll pass back to the engine
-r_studio_interface_t studio =
-{
- STUDIO_INTERFACE_VERSION,
- R_StudioDrawModel,
- R_StudioDrawPlayer,
-};
-
-/*
-====================
-HUD_GetStudioModelInterface
-
-Export this function for the engine to use the studio renderer class to render objects.
-====================
-*/
-#define DLLEXPORT __declspec( dllexport )
-extern "C" int DLLEXPORT HUD_GetStudioModelInterface( int version, struct r_studio_interface_s **ppinterface, struct engine_studio_api_s *pstudio )
-{
- if ( version != STUDIO_INTERFACE_VERSION )
- return 0;
-
- // Point the engine to our callbacks
- *ppinterface = &studio;
-
- // Copy in engine helper functions
- memcpy( &IEngineStudio, pstudio, sizeof( IEngineStudio ) );
-
- // Initialize local variables, etc.
- R_StudioInit();
-
- // Success
- return 1;
-}
+#include
+#include "hud.h"
+#include "cl_util.h"
+#include "const.h"
+#include "com_model.h"
+#include "studio.h"
+#include "entity_state.h"
+#include "cl_entity.h"
+#include "dlight.h"
+#include "triangleapi.h"
+
+#include
+#include
+#include
+#include
+
+#include "studio_util.h"
+#include "r_studioint.h"
+
+#include "StudioModelRenderer.h"
+#include "GameStudioModelRenderer.h"
+
+// Predicted values saved off in hl_weapons.cpp
+void Game_GetSequence( int *seq, int *gaitseq );
+void Game_GetOrientation( float *o, float *a );
+
+float g_flStartScaleTime;
+int iPrevRenderState;
+int iRenderStateChanged;
+
+// Global engine <-> studio model rendering code interface
+extern engine_studio_api_t IEngineStudio;
+
+typedef struct
+{
+ vec3_t origin;
+ vec3_t angles;
+
+ vec3_t realangles;
+
+ float animtime;
+ float frame;
+ int sequence;
+ int gaitsequence;
+ float framerate;
+
+ int m_fSequenceLoops;
+ int m_fSequenceFinished;
+
+ byte controller[ 4 ];
+ byte blending[ 2 ];
+
+ latchedvars_t lv;
+} client_anim_state_t;
+
+static client_anim_state_t g_state;
+static client_anim_state_t g_clientstate;
+
+// The renderer object, created on the stack.
+CGameStudioModelRenderer g_StudioRenderer;
+/*
+====================
+CGameStudioModelRenderer
+
+====================
+*/
+CGameStudioModelRenderer::CGameStudioModelRenderer( void )
+{
+ // If you want to predict animations locally, set this to TRUE
+ // NOTE: The animation code is somewhat broken, but gives you a sense for how
+ // to do client side animation of the predicted player in a third person game.
+ m_bLocal = false;
+}
+
+/*
+====================
+StudioSetupBones
+
+====================
+*/
+void CGameStudioModelRenderer::StudioSetupBones ( void )
+{
+ int i;
+ double f;
+
+ mstudiobone_t *pbones;
+ mstudioseqdesc_t *pseqdesc;
+ mstudioanim_t *panim;
+
+ static float pos[MAXSTUDIOBONES][3];
+ static vec4_t q[MAXSTUDIOBONES];
+ float bonematrix[3][4];
+
+ static float pos2[MAXSTUDIOBONES][3];
+ static vec4_t q2[MAXSTUDIOBONES];
+ static float pos3[MAXSTUDIOBONES][3];
+ static vec4_t q3[MAXSTUDIOBONES];
+ static float pos4[MAXSTUDIOBONES][3];
+ static vec4_t q4[MAXSTUDIOBONES];
+
+ // Use default bone setup for nonplayers
+ if ( !m_pCurrentEntity->player )
+ {
+ CStudioModelRenderer::StudioSetupBones();
+ return;
+ }
+
+ // Bound sequence number.
+ if ( m_pCurrentEntity->curstate.sequence >= m_pStudioHeader->numseq )
+ {
+ m_pCurrentEntity->curstate.sequence = 0;
+ }
+
+ pseqdesc = (mstudioseqdesc_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqindex) + m_pCurrentEntity->curstate.sequence;
+
+ if ( m_pPlayerInfo && m_pPlayerInfo->gaitsequence != 0 )
+ {
+ f = m_pPlayerInfo->gaitframe;
+ }
+ else
+ {
+ f = StudioEstimateFrame( pseqdesc );
+ }
+
+ // This game knows how to do three way blending
+ if ( pseqdesc->numblends == 3 )
+ {
+ float s;
+
+ // Get left anim
+ panim = StudioGetAnim( m_pRenderModel, pseqdesc );
+
+ // Blending is 0-127 == Left to Middle, 128 to 255 == Middle to right
+ if ( m_pCurrentEntity->curstate.blending[0] <= 127 )
+ {
+ StudioCalcRotations( pos, q, pseqdesc, panim, f );
+
+ // Scale 0-127 blending up to 0-255
+ s = m_pCurrentEntity->curstate.blending[0];
+ s = ( s * 2.0 );
+ }
+ else
+ {
+
+ // Skip ahead to middle
+ panim += m_pStudioHeader->numbones;
+
+ StudioCalcRotations( pos, q, pseqdesc, panim, f );
+
+ // Scale 127-255 blending up to 0-255
+ s = m_pCurrentEntity->curstate.blending[0];
+ s = 2.0 * ( s - 127.0 );
+ }
+
+ // Normalize interpolant
+ s /= 255.0;
+
+ // Go to middle or right
+ panim += m_pStudioHeader->numbones;
+
+ StudioCalcRotations( pos2, q2, pseqdesc, panim, f );
+
+ // Spherically interpolate the bones
+ StudioSlerpBones( q, pos, q2, pos2, s );
+ }
+ else
+ {
+ panim = StudioGetAnim( m_pRenderModel, pseqdesc );
+ StudioCalcRotations( pos, q, pseqdesc, panim, f );
+ }
+
+ // Are we in the process of transitioning from one sequence to another.
+ if ( m_fDoInterp &&
+ m_pCurrentEntity->latched.sequencetime &&
+ ( m_pCurrentEntity->latched.sequencetime + 0.2 > m_clTime ) &&
+ ( m_pCurrentEntity->latched.prevsequence < m_pStudioHeader->numseq ))
+ {
+ // blend from last sequence
+ static float pos1b[MAXSTUDIOBONES][3];
+ static vec4_t q1b[MAXSTUDIOBONES];
+ float s;
+
+ // Blending value into last sequence
+ unsigned char prevseqblending = m_pCurrentEntity->latched.prevseqblending[ 0 ];
+
+ // Point at previous sequenece
+ pseqdesc = (mstudioseqdesc_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqindex) + m_pCurrentEntity->latched.prevsequence;
+
+ // Know how to do three way blends
+ if ( pseqdesc->numblends == 3 )
+ {
+ float s;
+
+ // Get left animation
+ panim = StudioGetAnim( m_pRenderModel, pseqdesc );
+
+ if ( prevseqblending <= 127 )
+ {
+ // Set up bones based on final frame of previous sequence
+ StudioCalcRotations( pos1b, q1b, pseqdesc, panim, m_pCurrentEntity->latched.prevframe );
+
+ s = prevseqblending;
+ s = ( s * 2.0 );
+ }
+ else
+ {
+ // Skip to middle blend
+ panim += m_pStudioHeader->numbones;
+
+ StudioCalcRotations( pos1b, q1b, pseqdesc, panim, m_pCurrentEntity->latched.prevframe );
+
+ s = prevseqblending;
+ s = 2.0 * ( s - 127.0 );
+ }
+
+ // Normalize
+ s /= 255.0;
+
+ panim += m_pStudioHeader->numbones;
+ StudioCalcRotations( pos2, q2, pseqdesc, panim, m_pCurrentEntity->latched.prevframe );
+
+ // Interpolate bones
+ StudioSlerpBones( q1b, pos1b, q2, pos2, s );
+ }
+ else
+ {
+ panim = StudioGetAnim( m_pRenderModel, pseqdesc );
+ // clip prevframe
+ StudioCalcRotations( pos1b, q1b, pseqdesc, panim, m_pCurrentEntity->latched.prevframe );
+ }
+
+ // Now blend last frame of previous sequence with current sequence.
+ s = 1.0 - (m_clTime - m_pCurrentEntity->latched.sequencetime) / 0.2;
+ StudioSlerpBones( q, pos, q1b, pos1b, s );
+ }
+ else
+ {
+ m_pCurrentEntity->latched.prevframe = f;
+ }
+
+ // Now convert quaternions and bone positions into matrices
+ pbones = (mstudiobone_t *)((byte *)m_pStudioHeader + m_pStudioHeader->boneindex);
+
+ for (i = 0; i < m_pStudioHeader->numbones; i++)
+ {
+ QuaternionMatrix( q[i], bonematrix );
+
+ bonematrix[0][3] = pos[i][0];
+ bonematrix[1][3] = pos[i][1];
+ bonematrix[2][3] = pos[i][2];
+
+ if (pbones[i].parent == -1)
+ {
+ if ( IEngineStudio.IsHardware() )
+ {
+ ConcatTransforms ((*m_protationmatrix), bonematrix, (*m_pbonetransform)[i]);
+ ConcatTransforms ((*m_protationmatrix), bonematrix, (*m_plighttransform)[i]);
+ }
+ else
+ {
+ ConcatTransforms ((*m_paliastransform), bonematrix, (*m_pbonetransform)[i]);
+ ConcatTransforms ((*m_protationmatrix), bonematrix, (*m_plighttransform)[i]);
+ }
+
+ // Apply client-side effects to the transformation matrix
+ StudioFxTransform( m_pCurrentEntity, (*m_pbonetransform)[i] );
+ }
+ else
+ {
+ ConcatTransforms ((*m_pbonetransform)[pbones[i].parent], bonematrix, (*m_pbonetransform)[i]);
+ ConcatTransforms ((*m_plighttransform)[pbones[i].parent], bonematrix, (*m_plighttransform)[i]);
+ }
+ }
+}
+
+/*
+====================
+StudioEstimateGait
+
+====================
+*/
+void CGameStudioModelRenderer::StudioEstimateGait( entity_state_t *pplayer )
+{
+ float dt;
+ vec3_t est_velocity;
+
+ dt = (m_clTime - m_clOldTime);
+ dt = max( 0.0, dt );
+ dt = min( 1.0, dt );
+
+ if (dt == 0 || m_pPlayerInfo->renderframe == m_nFrameCount)
+ {
+ m_flGaitMovement = 0;
+ return;
+ }
+
+ // VectorAdd( pplayer->velocity, pplayer->prediction_error, est_velocity );
+ if ( m_fGaitEstimation )
+ {
+ VectorSubtract( m_pCurrentEntity->origin, m_pPlayerInfo->prevgaitorigin, est_velocity );
+ VectorCopy( m_pCurrentEntity->origin, m_pPlayerInfo->prevgaitorigin );
+ m_flGaitMovement = Length( est_velocity );
+ if (dt <= 0 || m_flGaitMovement / dt < 5)
+ {
+ m_flGaitMovement = 0;
+ est_velocity[0] = 0;
+ est_velocity[1] = 0;
+ }
+ }
+ else
+ {
+ VectorCopy( pplayer->velocity, est_velocity );
+ m_flGaitMovement = Length( est_velocity ) * dt;
+ }
+
+ if (est_velocity[1] == 0 && est_velocity[0] == 0)
+ {
+ float flYawDiff = m_pCurrentEntity->angles[YAW] - m_pPlayerInfo->gaityaw;
+ flYawDiff = flYawDiff - (int)(flYawDiff / 360) * 360;
+ if (flYawDiff > 180)
+ flYawDiff -= 360;
+ if (flYawDiff < -180)
+ flYawDiff += 360;
+
+ if (dt < 0.25)
+ flYawDiff *= dt * 4;
+ else
+ flYawDiff *= dt;
+
+ m_pPlayerInfo->gaityaw += flYawDiff;
+ m_pPlayerInfo->gaityaw = m_pPlayerInfo->gaityaw - (int)(m_pPlayerInfo->gaityaw / 360) * 360;
+
+ m_flGaitMovement = 0;
+ }
+ else
+ {
+ m_pPlayerInfo->gaityaw = (atan2(est_velocity[1], est_velocity[0]) * 180 / M_PI);
+ if (m_pPlayerInfo->gaityaw > 180)
+ m_pPlayerInfo->gaityaw = 180;
+ if (m_pPlayerInfo->gaityaw < -180)
+ m_pPlayerInfo->gaityaw = -180;
+ }
+
+}
+
+/*
+====================
+StudioProcessGait
+
+====================
+*/
+void CGameStudioModelRenderer::StudioProcessGait( entity_state_t *pplayer )
+{
+ mstudioseqdesc_t *pseqdesc;
+ float dt;
+ float flYaw; // view direction relative to movement
+
+ pseqdesc = (mstudioseqdesc_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqindex) + m_pCurrentEntity->curstate.sequence;
+
+ m_pCurrentEntity->angles[PITCH] = 0;
+ m_pCurrentEntity->latched.prevangles[PITCH] = m_pCurrentEntity->angles[PITCH];
+
+ dt = (m_clTime - m_clOldTime);
+ dt = max( 0.0, dt );
+ dt = min( 1.0, dt );
+
+ StudioEstimateGait( pplayer );
+
+ // calc side to side turning
+ flYaw = m_pCurrentEntity->angles[YAW] - m_pPlayerInfo->gaityaw;
+
+ flYaw = fmod( flYaw, 360.0 );
+
+ if (flYaw < -180)
+ {
+ flYaw = flYaw + 360;
+ }
+ else if (flYaw > 180)
+ {
+ flYaw = flYaw - 360;
+ }
+
+ float maxyaw = 120.0;
+
+ if (flYaw > maxyaw)
+ {
+ m_pPlayerInfo->gaityaw = m_pPlayerInfo->gaityaw - 180;
+ m_flGaitMovement = -m_flGaitMovement;
+ flYaw = flYaw - 180;
+ }
+ else if (flYaw < -maxyaw)
+ {
+ m_pPlayerInfo->gaityaw = m_pPlayerInfo->gaityaw + 180;
+ m_flGaitMovement = -m_flGaitMovement;
+ flYaw = flYaw + 180;
+ }
+
+ float blend_yaw = ( flYaw / 90.0 ) * 128.0 + 127.0;
+ blend_yaw = min( 255.0, blend_yaw );
+ blend_yaw = max( 0.0, blend_yaw );
+
+ blend_yaw = 255.0 - blend_yaw;
+
+ m_pCurrentEntity->curstate.blending[0] = (int)(blend_yaw);
+ m_pCurrentEntity->latched.prevblending[0] = m_pCurrentEntity->curstate.blending[0];
+ m_pCurrentEntity->latched.prevseqblending[0] = m_pCurrentEntity->curstate.blending[0];
+
+ m_pCurrentEntity->angles[YAW] = m_pPlayerInfo->gaityaw;
+ if (m_pCurrentEntity->angles[YAW] < -0)
+ {
+ m_pCurrentEntity->angles[YAW] += 360;
+ }
+ m_pCurrentEntity->latched.prevangles[YAW] = m_pCurrentEntity->angles[YAW];
+
+ pseqdesc = (mstudioseqdesc_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqindex) + pplayer->gaitsequence;
+
+ // Calc gait frame
+ if (pseqdesc->linearmovement[0] > 0)
+ {
+ m_pPlayerInfo->gaitframe += (m_flGaitMovement / pseqdesc->linearmovement[0]) * pseqdesc->numframes;
+ }
+ else
+ {
+ m_pPlayerInfo->gaitframe += pseqdesc->fps * dt * m_pCurrentEntity->curstate.framerate;
+ }
+
+ // Do modulo
+ m_pPlayerInfo->gaitframe = m_pPlayerInfo->gaitframe - (int)(m_pPlayerInfo->gaitframe / pseqdesc->numframes) * pseqdesc->numframes;
+ if (m_pPlayerInfo->gaitframe < 0)
+ {
+ m_pPlayerInfo->gaitframe += pseqdesc->numframes;
+ }
+}
+
+/*
+==============================
+SavePlayerState
+
+For local player, in third person, we need to store real render data and then
+ setup for with fake/client side animation data
+==============================
+*/
+void CGameStudioModelRenderer::SavePlayerState( entity_state_t *pplayer )
+{
+ client_anim_state_t *st;
+ cl_entity_t *ent = IEngineStudio.GetCurrentEntity();
+ assert( ent );
+ if ( !ent )
+ return;
+
+ st = &g_state;
+
+ st->angles = ent->curstate.angles;
+ st->origin = ent->curstate.origin;
+
+ st->realangles = ent->angles;
+
+ st->sequence = ent->curstate.sequence;
+ st->gaitsequence = pplayer->gaitsequence;
+ st->animtime = ent->curstate.animtime;
+ st->frame = ent->curstate.frame;
+ st->framerate = ent->curstate.framerate;
+ memcpy( st->blending, ent->curstate.blending, 2 );
+ memcpy( st->controller, ent->curstate.controller, 4 );
+
+ st->lv = ent->latched;
+}
+
+void GetSequenceInfo( void *pmodel, client_anim_state_t *pev, float *pflFrameRate, float *pflGroundSpeed )
+{
+ studiohdr_t *pstudiohdr;
+
+ pstudiohdr = (studiohdr_t *)pmodel;
+ if (! pstudiohdr)
+ return;
+
+ mstudioseqdesc_t *pseqdesc;
+
+ if (pev->sequence >= pstudiohdr->numseq)
+ {
+ *pflFrameRate = 0.0;
+ *pflGroundSpeed = 0.0;
+ return;
+ }
+
+ pseqdesc = (mstudioseqdesc_t *)((byte *)pstudiohdr + pstudiohdr->seqindex) + (int)pev->sequence;
+
+ if (pseqdesc->numframes > 1)
+ {
+ *pflFrameRate = 256 * pseqdesc->fps / (pseqdesc->numframes - 1);
+ *pflGroundSpeed = sqrt( pseqdesc->linearmovement[0]*pseqdesc->linearmovement[0]+ pseqdesc->linearmovement[1]*pseqdesc->linearmovement[1]+ pseqdesc->linearmovement[2]*pseqdesc->linearmovement[2] );
+ *pflGroundSpeed = *pflGroundSpeed * pseqdesc->fps / (pseqdesc->numframes - 1);
+ }
+ else
+ {
+ *pflFrameRate = 256.0;
+ *pflGroundSpeed = 0.0;
+ }
+}
+
+int GetSequenceFlags( void *pmodel, client_anim_state_t *pev )
+{
+ studiohdr_t *pstudiohdr;
+
+ pstudiohdr = (studiohdr_t *)pmodel;
+ if ( !pstudiohdr || pev->sequence >= pstudiohdr->numseq )
+ return 0;
+
+ mstudioseqdesc_t *pseqdesc;
+ pseqdesc = (mstudioseqdesc_t *)((byte *)pstudiohdr + pstudiohdr->seqindex) + (int)pev->sequence;
+
+ return pseqdesc->flags;
+}
+
+float StudioFrameAdvance ( client_anim_state_t *st, float framerate, float flInterval )
+{
+ if (flInterval == 0.0)
+ {
+ flInterval = (gEngfuncs.GetClientTime() - st->animtime);
+ if (flInterval <= 0.001)
+ {
+ st->animtime = gEngfuncs.GetClientTime();
+ return 0.0;
+ }
+ }
+ if (!st->animtime)
+ flInterval = 0.0;
+
+ st->frame += flInterval * framerate * st->framerate;
+ st->animtime = gEngfuncs.GetClientTime();
+
+ if (st->frame < 0.0 || st->frame >= 256.0)
+ {
+ if ( st->m_fSequenceLoops )
+ st->frame -= (int)(st->frame / 256.0) * 256.0;
+ else
+ st->frame = (st->frame < 0.0) ? 0 : 255;
+ st->m_fSequenceFinished = TRUE; // just in case it wasn't caught in GetEvents
+ }
+
+ return flInterval;
+}
+
+/*
+==============================
+SetupClientAnimation
+
+Called to set up local player's animation values
+==============================
+*/
+void CGameStudioModelRenderer::SetupClientAnimation( entity_state_t *pplayer )
+{
+ static double oldtime;
+ double curtime, dt;
+
+ client_anim_state_t *st;
+ float fr, gs;
+
+ cl_entity_t *ent = IEngineStudio.GetCurrentEntity();
+ assert( ent );
+ if ( !ent )
+ return;
+
+ curtime = gEngfuncs.GetClientTime();
+ dt = curtime - oldtime;
+ dt = min( 1.0, max( 0.0, dt ) );
+
+ oldtime = curtime;
+ st = &g_clientstate;
+
+ st->framerate = 1.0;
+
+ int oldseq = st->sequence;
+ Game_GetSequence( &st->sequence, &st->gaitsequence ); //CVAR_GET_FLOAT( "sequence" );
+ Game_GetOrientation( (float *)&st->origin, (float *)&st->angles );
+ st->realangles = st->angles;
+
+ if ( st->sequence != oldseq )
+ {
+ st->frame = 0.0;
+ st->lv.prevsequence = oldseq;
+ st->lv.sequencetime = st->animtime;
+
+ memcpy( st->lv.prevseqblending, st->blending, 2 );
+ memcpy( st->lv.prevcontroller, st->controller, 4 );
+ }
+
+ void *pmodel = (studiohdr_t *)IEngineStudio.Mod_Extradata( ent->model );
+
+ GetSequenceInfo( pmodel, st, &fr, &gs );
+ st->m_fSequenceLoops = ((GetSequenceFlags( pmodel, st ) & STUDIO_LOOPING) != 0);
+ StudioFrameAdvance( st, fr, dt );
+
+// gEngfuncs.Con_Printf( "gs %i frame %f\n", st->gaitsequence, st->frame );
+
+ ent->angles = st->realangles;
+ ent->curstate.angles = st->angles;
+ ent->curstate.origin = st->origin;
+
+ ent->curstate.sequence = st->sequence;
+ pplayer->gaitsequence = st->gaitsequence;
+ ent->curstate.animtime = st->animtime;
+ ent->curstate.frame = st->frame;
+ ent->curstate.framerate = st->framerate;
+ memcpy( ent->curstate.blending, st->blending, 2 );
+ memcpy( ent->curstate.controller, st->controller, 4 );
+
+ ent->latched = st->lv;
+}
+
+/*
+==============================
+RestorePlayerState
+
+Called to restore original player state information
+==============================
+*/
+void CGameStudioModelRenderer::RestorePlayerState( entity_state_t *pplayer )
+{
+ client_anim_state_t *st;
+ cl_entity_t *ent = IEngineStudio.GetCurrentEntity();
+ assert( ent );
+ if ( !ent )
+ return;
+
+ st = &g_clientstate;
+
+ st->angles = ent->curstate.angles;
+ st->origin = ent->curstate.origin;
+ st->realangles = ent->angles;
+
+ st->sequence = ent->curstate.sequence;
+ st->gaitsequence = pplayer->gaitsequence;
+ st->animtime = ent->curstate.animtime;
+ st->frame = ent->curstate.frame;
+ st->framerate = ent->curstate.framerate;
+ memcpy( st->blending, ent->curstate.blending, 2 );
+ memcpy( st->controller, ent->curstate.controller, 4 );
+
+ st->lv = ent->latched;
+
+ st = &g_state;
+
+ ent->curstate.angles = st->angles;
+ ent->curstate.origin = st->origin;
+ ent->angles = st->realangles;
+
+ ent->curstate.sequence = st->sequence;
+ pplayer->gaitsequence = st->gaitsequence;
+ ent->curstate.animtime = st->animtime;
+ ent->curstate.frame = st->frame;
+ ent->curstate.framerate = st->framerate;
+ memcpy( ent->curstate.blending, st->blending, 2 );
+ memcpy( ent->curstate.controller, st->controller, 4 );
+
+ ent->latched = st->lv;
+}
+
+/*
+==============================
+StudioDrawPlayer
+
+==============================
+*/
+int CGameStudioModelRenderer::StudioDrawPlayer( int flags, entity_state_t *pplayer )
+{
+ int iret = 0;
+
+ bool isLocalPlayer = false;
+
+ // Set up for client?
+ if ( m_bLocal && IEngineStudio.GetCurrentEntity() == gEngfuncs.GetLocalPlayer() )
+ {
+ isLocalPlayer = true;
+ }
+
+ if ( isLocalPlayer )
+ {
+ // Store original data
+ SavePlayerState( pplayer );
+
+ // Copy in client side animation data
+ SetupClientAnimation( pplayer );
+ }
+
+ // Call real draw function
+ iret = _StudioDrawPlayer( flags, pplayer );
+
+ // Restore for client?
+ if ( isLocalPlayer )
+ {
+ // Restore the original data for the player
+ RestorePlayerState( pplayer );
+ }
+
+ return iret;
+}
+
+/*
+====================
+_StudioDrawPlayer
+
+====================
+*/
+int CGameStudioModelRenderer::_StudioDrawPlayer( int flags, entity_state_t *pplayer )
+{
+ alight_t lighting;
+ vec3_t dir;
+
+ m_pCurrentEntity = IEngineStudio.GetCurrentEntity();
+ IEngineStudio.GetTimes( &m_nFrameCount, &m_clTime, &m_clOldTime );
+ IEngineStudio.GetViewInfo( m_vRenderOrigin, m_vUp, m_vRight, m_vNormal );
+ IEngineStudio.GetAliasScale( &m_fSoftwareXScale, &m_fSoftwareYScale );
+
+ m_nPlayerIndex = pplayer->number - 1;
+
+ if (m_nPlayerIndex < 0 || m_nPlayerIndex >= gEngfuncs.GetMaxClients())
+ return 0;
+
+ m_pRenderModel = IEngineStudio.SetupPlayerModel( m_nPlayerIndex );
+ if (m_pRenderModel == NULL)
+ return 0;
+
+ m_pStudioHeader = (studiohdr_t *)IEngineStudio.Mod_Extradata (m_pRenderModel);
+ IEngineStudio.StudioSetHeader( m_pStudioHeader );
+ IEngineStudio.SetRenderModel( m_pRenderModel );
+
+ if (pplayer->gaitsequence)
+ {
+ vec3_t orig_angles;
+ m_pPlayerInfo = IEngineStudio.PlayerInfo( m_nPlayerIndex );
+
+ VectorCopy( m_pCurrentEntity->angles, orig_angles );
+
+ StudioProcessGait( pplayer );
+
+ m_pPlayerInfo->gaitsequence = pplayer->gaitsequence;
+ m_pPlayerInfo = NULL;
+
+ StudioSetUpTransform( 0 );
+ VectorCopy( orig_angles, m_pCurrentEntity->angles );
+ }
+ else
+ {
+ m_pCurrentEntity->curstate.controller[0] = 127;
+ m_pCurrentEntity->curstate.controller[1] = 127;
+ m_pCurrentEntity->curstate.controller[2] = 127;
+ m_pCurrentEntity->curstate.controller[3] = 127;
+ m_pCurrentEntity->latched.prevcontroller[0] = m_pCurrentEntity->curstate.controller[0];
+ m_pCurrentEntity->latched.prevcontroller[1] = m_pCurrentEntity->curstate.controller[1];
+ m_pCurrentEntity->latched.prevcontroller[2] = m_pCurrentEntity->curstate.controller[2];
+ m_pCurrentEntity->latched.prevcontroller[3] = m_pCurrentEntity->curstate.controller[3];
+
+ m_pPlayerInfo = IEngineStudio.PlayerInfo( m_nPlayerIndex );
+ m_pPlayerInfo->gaitsequence = 0;
+
+ StudioSetUpTransform( 0 );
+ }
+
+ if (flags & STUDIO_RENDER)
+ {
+ // see if the bounding box lets us trivially reject, also sets
+ if (!IEngineStudio.StudioCheckBBox ())
+ return 0;
+
+ (*m_pModelsDrawn)++;
+ (*m_pStudioModelCount)++; // render data cache cookie
+
+ if (m_pStudioHeader->numbodyparts == 0)
+ return 1;
+ }
+
+ m_pPlayerInfo = IEngineStudio.PlayerInfo( m_nPlayerIndex );
+ StudioSetupBones( );
+ StudioSaveBones( );
+ m_pPlayerInfo->renderframe = m_nFrameCount;
+
+ m_pPlayerInfo = NULL;
+
+ if (flags & STUDIO_EVENTS)
+ {
+ StudioCalcAttachments( );
+ IEngineStudio.StudioClientEvents( );
+ // copy attachments into global entity array
+ if ( m_pCurrentEntity->index > 0 )
+ {
+ cl_entity_t *ent = gEngfuncs.GetEntityByIndex( m_pCurrentEntity->index );
+
+ memcpy( ent->attachment, m_pCurrentEntity->attachment, sizeof( vec3_t ) * 4 );
+ }
+ }
+
+ if (flags & STUDIO_RENDER)
+ {
+ /*
+ if (m_pCvarHiModels->value && m_pRenderModel != m_pCurrentEntity->model )
+ {
+ // show highest resolution multiplayer model
+ m_pCurrentEntity->curstate.body = 255;
+ }
+
+ if (!(m_pCvarDeveloper->value == 0 && gEngfuncs.GetMaxClients() == 1 ) && ( m_pRenderModel == m_pCurrentEntity->model ) )
+ {
+ m_pCurrentEntity->curstate.body = 1; // force helmet
+ }
+ */
+
+ lighting.plightvec = dir;
+ IEngineStudio.StudioDynamicLight(m_pCurrentEntity, &lighting );
+
+ IEngineStudio.StudioEntityLight( &lighting );
+
+ // model and frame independant
+ IEngineStudio.StudioSetupLighting (&lighting);
+
+ m_pPlayerInfo = IEngineStudio.PlayerInfo( m_nPlayerIndex );
+
+ // get remap colors
+ m_nTopColor = m_pPlayerInfo->topcolor;
+ if (m_nTopColor < 0)
+ m_nTopColor = 0;
+ if (m_nTopColor > 360)
+ m_nTopColor = 360;
+ m_nBottomColor = m_pPlayerInfo->bottomcolor;
+ if (m_nBottomColor < 0)
+ m_nBottomColor = 0;
+ if (m_nBottomColor > 360)
+ m_nBottomColor = 360;
+
+ IEngineStudio.StudioSetRemapColors( m_nTopColor, m_nBottomColor );
+
+ StudioRenderModel( );
+ m_pPlayerInfo = NULL;
+
+ if (pplayer->weaponmodel)
+ {
+ cl_entity_t saveent = *m_pCurrentEntity;
+
+ model_t *pweaponmodel = IEngineStudio.GetModelByIndex( pplayer->weaponmodel );
+
+ m_pStudioHeader = (studiohdr_t *)IEngineStudio.Mod_Extradata (pweaponmodel);
+ IEngineStudio.StudioSetHeader( m_pStudioHeader );
+
+ StudioMergeBones( pweaponmodel);
+
+ IEngineStudio.StudioSetupLighting (&lighting);
+
+ StudioRenderModel( );
+
+ StudioCalcAttachments( );
+
+ *m_pCurrentEntity = saveent;
+ }
+ }
+
+ return 1;
+}
+
+/*
+====================
+Studio_FxTransform
+
+====================
+*/
+void CGameStudioModelRenderer::StudioFxTransform( cl_entity_t *ent, float transform[3][4] )
+{
+ switch( ent->curstate.renderfx )
+ {
+ case kRenderFxDistort:
+ case kRenderFxHologram:
+ if ( gEngfuncs.pfnRandomLong(0,49) == 0 )
+ {
+ int axis = gEngfuncs.pfnRandomLong(0,1);
+ if ( axis == 1 ) // Choose between x & z
+ axis = 2;
+ VectorScale( transform[axis], gEngfuncs.pfnRandomFloat(1,1.484), transform[axis] );
+ }
+ else if ( gEngfuncs.pfnRandomLong(0,49) == 0 )
+ {
+ float offset;
+ int axis = gEngfuncs.pfnRandomLong(0,1);
+ if ( axis == 1 ) // Choose between x & z
+ axis = 2;
+ offset = gEngfuncs.pfnRandomFloat(-10,10);
+ transform[gEngfuncs.pfnRandomLong(0,2)][3] += offset;
+ }
+ break;
+ case kRenderFxExplode:
+ {
+ if ( iRenderStateChanged )
+ {
+ g_flStartScaleTime = m_clTime;
+ iRenderStateChanged = FALSE;
+ }
+
+ // Make the Model continue to shrink
+ float flTimeDelta = m_clTime - g_flStartScaleTime;
+ if ( flTimeDelta > 0 )
+ {
+ float flScale = 0.001;
+ // Goes almost all away
+ if ( flTimeDelta <= 2.0 )
+ flScale = 1.0 - (flTimeDelta / 2.0);
+
+ for (int i = 0; i < 3; i++)
+ {
+ for (int j = 0; j < 3; j++)
+ transform[i][j] *= flScale;
+ }
+ }
+ }
+ break;
+ }
+}
+
+////////////////////////////////////
+// Hooks to class implementation
+////////////////////////////////////
+
+/*
+====================
+R_StudioDrawPlayer
+
+====================
+*/
+int R_StudioDrawPlayer( int flags, entity_state_t *pplayer )
+{
+ return g_StudioRenderer.StudioDrawPlayer( flags, pplayer );
+}
+
+/*
+====================
+R_StudioDrawModel
+
+====================
+*/
+int R_StudioDrawModel( int flags )
+{
+ return g_StudioRenderer.StudioDrawModel( flags );
+}
+
+/*
+====================
+R_StudioInit
+
+====================
+*/
+void R_StudioInit( void )
+{
+ g_StudioRenderer.Init();
+}
+
+// The simple drawing interface we'll pass back to the engine
+r_studio_interface_t studio =
+{
+ STUDIO_INTERFACE_VERSION,
+ R_StudioDrawModel,
+ R_StudioDrawPlayer,
+};
+
+/*
+====================
+HUD_GetStudioModelInterface
+
+Export this function for the engine to use the studio renderer class to render objects.
+====================
+*/
+#define DLLEXPORT __declspec( dllexport )
+extern "C" int DLLEXPORT HUD_GetStudioModelInterface( int version, struct r_studio_interface_s **ppinterface, struct engine_studio_api_s *pstudio )
+{
+ if ( version != STUDIO_INTERFACE_VERSION )
+ return 0;
+
+ // Point the engine to our callbacks
+ *ppinterface = &studio;
+
+ // Copy in engine helper functions
+ memcpy( &IEngineStudio, pstudio, sizeof( IEngineStudio ) );
+
+ // Initialize local variables, etc.
+ R_StudioInit();
+
+ // Success
+ return 1;
+}
diff --git a/main/source/cl_dll/GameStudioModelRenderer_Sample.h b/main/source/cl_dll/GameStudioModelRenderer_Sample.h
index 3fe5ea5c..64f6c8b0 100644
--- a/main/source/cl_dll/GameStudioModelRenderer_Sample.h
+++ b/main/source/cl_dll/GameStudioModelRenderer_Sample.h
@@ -1,48 +1,48 @@
-#if !defined( GAMESTUDIOMODELRENDERER_H )
-#define GAMESTUDIOMODELRENDERER_H
-#if defined( _WIN32 )
-#pragma once
-#endif
-
-/*
-====================
-CGameStudioModelRenderer
-
-====================
-*/
-class CGameStudioModelRenderer : public CStudioModelRenderer
-{
-public:
- CGameStudioModelRenderer( void );
-
- // Set up model bone positions
- virtual void StudioSetupBones ( void );
-
- // Estimate gait frame for player
- virtual void StudioEstimateGait ( entity_state_t *pplayer );
-
- // Process movement of player
- virtual void StudioProcessGait ( entity_state_t *pplayer );
-
- // Player drawing code
- virtual int StudioDrawPlayer( int flags, entity_state_t *pplayer );
- virtual int _StudioDrawPlayer( int flags, entity_state_t *pplayer );
-
- // Apply special effects to transform matrix
- virtual void StudioFxTransform( cl_entity_t *ent, float transform[3][4] );
-
-private:
- // For local player, in third person, we need to store real render data and then
- // setup for with fake/client side animation data
- void SavePlayerState( entity_state_t *pplayer );
- // Called to set up local player's animation values
- void SetupClientAnimation( entity_state_t *pplayer );
- // Called to restore original player state information
- void RestorePlayerState( entity_state_t *pplayer );
-
-private:
- // Private data
- bool m_bLocal;
-};
-
+#if !defined( GAMESTUDIOMODELRENDERER_H )
+#define GAMESTUDIOMODELRENDERER_H
+#if defined( _WIN32 )
+#pragma once
+#endif
+
+/*
+====================
+CGameStudioModelRenderer
+
+====================
+*/
+class CGameStudioModelRenderer : public CStudioModelRenderer
+{
+public:
+ CGameStudioModelRenderer( void );
+
+ // Set up model bone positions
+ virtual void StudioSetupBones ( void );
+
+ // Estimate gait frame for player
+ virtual void StudioEstimateGait ( entity_state_t *pplayer );
+
+ // Process movement of player
+ virtual void StudioProcessGait ( entity_state_t *pplayer );
+
+ // Player drawing code
+ virtual int StudioDrawPlayer( int flags, entity_state_t *pplayer );
+ virtual int _StudioDrawPlayer( int flags, entity_state_t *pplayer );
+
+ // Apply special effects to transform matrix
+ virtual void StudioFxTransform( cl_entity_t *ent, float transform[3][4] );
+
+private:
+ // For local player, in third person, we need to store real render data and then
+ // setup for with fake/client side animation data
+ void SavePlayerState( entity_state_t *pplayer );
+ // Called to set up local player's animation values
+ void SetupClientAnimation( entity_state_t *pplayer );
+ // Called to restore original player state information
+ void RestorePlayerState( entity_state_t *pplayer );
+
+private:
+ // Private data
+ bool m_bLocal;
+};
+
#endif // GAMESTUDIOMODELRENDERER_H
\ No newline at end of file
diff --git a/main/source/cl_dll/StudioModelRenderer.cpp b/main/source/cl_dll/StudioModelRenderer.cpp
index 2bbda552..b1a72942 100644
--- a/main/source/cl_dll/StudioModelRenderer.cpp
+++ b/main/source/cl_dll/StudioModelRenderer.cpp
@@ -1,1910 +1,1910 @@
-// studio_model.cpp
-// routines for setting up to draw 3DStudio models
-
-#include "hud.h"
-#include "cl_util.h"
-#include "common/const.h"
-#include "common/com_model.h"
-#include "engine/studio.h"
-#include "common/entity_state.h"
-#include "common/cl_entity.h"
-#include "common/dlight.h"
-#include "common/triangleapi.h"
-
-#include
-#include
-#include
-#include
-
-#include "studio_util.h"
-#include "r_studioint.h"
-
-#include "StudioModelRenderer.h"
-#include "GameStudioModelRenderer.h"
-
-#include "util/MathUtil.h"
-
-// Global engine <-> studio model rendering code interface
-engine_studio_api_t IEngineStudio;
-
-#include "mod/AvHSpecials.h"
-
-int GetRenderModeForModelName(int inRenderMode, char* inName)
-{
- int theRenderMode = inRenderMode;
-
-// if(!strncmp("tcol", inName, 4))
-// {
-// theRenderMode = kRenderTransColor;
-// }
- if(!strncmp("ttex", inName, 4))
- {
- theRenderMode = kRenderTransTexture;
- }
- else if(!strncmp("glow", inName, 4))
- {
- theRenderMode = kRenderGlow;
- }
- else if(!strncmp("talp", inName, 4))
- {
- theRenderMode = kRenderTransAlpha;
- }
- else if(!strncmp("tadd", inName, 4))
- {
- theRenderMode = kRenderTransAdd;
- }
-
- return theRenderMode;
-}
-
-
-/////////////////////
-// Implementation of CStudioModelRenderer.h
-
-/*
-====================
-Init
-
-====================
-*/
-void CStudioModelRenderer::Init( void )
-{
- // Set up some variables shared with engine
- m_pCvarHiModels = IEngineStudio.GetCvar( "cl_himodels" );
- m_pCvarDeveloper = IEngineStudio.GetCvar( "developer" );
- m_pCvarDrawEntities = IEngineStudio.GetCvar( "r_drawentities" );
-
- m_pChromeSprite = IEngineStudio.GetChromeSprite();
-
- IEngineStudio.GetModelCounters( &m_pStudioModelCount, &m_pModelsDrawn );
-
- // Get pointers to engine data structures
- m_pbonetransform = (float (*)[MAXSTUDIOBONES][3][4])IEngineStudio.StudioGetBoneTransform();
- m_plighttransform = (float (*)[MAXSTUDIOBONES][3][4])IEngineStudio.StudioGetLightTransform();
- m_paliastransform = (float (*)[3][4])IEngineStudio.StudioGetAliasTransform();
- m_protationmatrix = (float (*)[3][4])IEngineStudio.StudioGetRotationMatrix();
-}
-
-/*
-====================
-CStudioModelRenderer
-
-====================
-*/
-CStudioModelRenderer::CStudioModelRenderer( void )
-{
- m_fDoInterp = 1;
- m_fGaitEstimation = 1;
- m_pCurrentEntity = NULL;
- m_pCvarHiModels = NULL;
- m_pCvarDeveloper = NULL;
- m_pCvarDrawEntities = NULL;
- m_pChromeSprite = NULL;
- m_pStudioModelCount = NULL;
- m_pModelsDrawn = NULL;
- m_protationmatrix = NULL;
- m_paliastransform = NULL;
- m_pbonetransform = NULL;
- m_plighttransform = NULL;
- m_pStudioHeader = NULL;
- m_pBodyPart = NULL;
- m_pSubModel = NULL;
- m_pPlayerInfo = NULL;
- m_pRenderModel = NULL;
-}
-
-/*
-====================
-~CStudioModelRenderer
-
-====================
-*/
-CStudioModelRenderer::~CStudioModelRenderer( void )
-{
-}
-
-/*
-====================
-StudioCalcBoneAdj
-
-====================
-*/
-void CStudioModelRenderer::StudioCalcBoneAdj( float dadt, float *adj, const byte *pcontroller1, const byte *pcontroller2, byte mouthopen )
-{
- int i, j;
- float value;
- mstudiobonecontroller_t *pbonecontroller;
-
- pbonecontroller = (mstudiobonecontroller_t *)((byte *)m_pStudioHeader + m_pStudioHeader->bonecontrollerindex);
-
- for (j = 0; j < m_pStudioHeader->numbonecontrollers; j++)
- {
- i = pbonecontroller[j].index;
- if (i <= 3)
- {
- // check for 360% wrapping
- if (pbonecontroller[j].type & STUDIO_RLOOP)
- {
- if (abs(pcontroller1[i] - pcontroller2[i]) > 128)
- {
- int a, b;
- a = (pcontroller1[j] + 128) % 256;
- b = (pcontroller2[j] + 128) % 256;
- value = ((a * dadt) + (b * (1 - dadt)) - 128) * (360.0/256.0) + pbonecontroller[j].start;
- }
- else
- {
- value = ((pcontroller1[i] * dadt + (pcontroller2[i]) * (1.0 - dadt))) * (360.0/256.0) + pbonecontroller[j].start;
- }
- }
- else
- {
- value = (pcontroller1[i] * dadt + pcontroller2[i] * (1.0 - dadt)) / 255.0;
- if (value < 0) value = 0;
- if (value > 1.0) value = 1.0;
- value = (1.0 - value) * pbonecontroller[j].start + value * pbonecontroller[j].end;
- }
- // Con_DPrintf( "%d %d %f : %f\n", m_pCurrentEntity->curstate.controller[j], m_pCurrentEntity->latched.prevcontroller[j], value, dadt );
- }
- else
- {
- value = mouthopen / 64.0;
- if (value > 1.0) value = 1.0;
- value = (1.0 - value) * pbonecontroller[j].start + value * pbonecontroller[j].end;
- // Con_DPrintf("%d %f\n", mouthopen, value );
- }
- switch(pbonecontroller[j].type & STUDIO_TYPES)
- {
- case STUDIO_XR:
- case STUDIO_YR:
- case STUDIO_ZR:
- adj[j] = value * (M_PI / 180.0);
- break;
- case STUDIO_X:
- case STUDIO_Y:
- case STUDIO_Z:
- adj[j] = value;
- break;
- }
- }
-}
-
-
-/*
-====================
-StudioCalcBoneQuaterion
-
-====================
-*/
-void CStudioModelRenderer::StudioCalcBoneQuaterion( int frame, float s, mstudiobone_t *pbone, mstudioanim_t *panim, float *adj, float *q )
-{
- int j, k;
- vec4_t q1, q2;
- vec3_t angle1, angle2;
- mstudioanimvalue_t *panimvalue;
-
- for (j = 0; j < 3; j++)
- {
- if (panim->offset[j+3] == 0)
- {
- angle2[j] = angle1[j] = pbone->value[j+3]; // default;
- }
- else
- {
- panimvalue = (mstudioanimvalue_t *)((byte *)panim + panim->offset[j+3]);
- k = frame;
- // DEBUG
- if (panimvalue->num.total < panimvalue->num.valid)
- k = 0;
- while (panimvalue->num.total <= k)
- {
- k -= panimvalue->num.total;
- panimvalue += panimvalue->num.valid + 1;
- // DEBUG
- if (panimvalue->num.total < panimvalue->num.valid)
- k = 0;
- }
- // Bah, missing blend!
- if (panimvalue->num.valid > k)
- {
- angle1[j] = panimvalue[k+1].value;
-
- if (panimvalue->num.valid > k + 1)
- {
- angle2[j] = panimvalue[k+2].value;
- }
- else
- {
- if (panimvalue->num.total > k + 1)
- angle2[j] = angle1[j];
- else
- angle2[j] = panimvalue[panimvalue->num.valid+2].value;
- }
- }
- else
- {
- angle1[j] = panimvalue[panimvalue->num.valid].value;
- if (panimvalue->num.total > k + 1)
- {
- angle2[j] = angle1[j];
- }
- else
- {
- angle2[j] = panimvalue[panimvalue->num.valid + 2].value;
- }
- }
- angle1[j] = pbone->value[j+3] + angle1[j] * pbone->scale[j+3];
- angle2[j] = pbone->value[j+3] + angle2[j] * pbone->scale[j+3];
- }
-
- if (pbone->bonecontroller[j+3] != -1)
- {
- angle1[j] += adj[pbone->bonecontroller[j+3]];
- angle2[j] += adj[pbone->bonecontroller[j+3]];
- }
- }
-
- if (!VectorCompare( angle1, angle2 ))
- {
- AngleQuaternion( angle1, q1 );
- AngleQuaternion( angle2, q2 );
- QuaternionSlerp( q1, q2, s, q );
- }
- else
- {
- AngleQuaternion( angle1, q );
- }
-}
-
-/*
-====================
-StudioCalcBonePosition
-
-====================
-*/
-void CStudioModelRenderer::StudioCalcBonePosition( int frame, float s, mstudiobone_t *pbone, mstudioanim_t *panim, float *adj, float *pos )
-{
- int j, k;
- mstudioanimvalue_t *panimvalue;
-
- for (j = 0; j < 3; j++)
- {
- pos[j] = pbone->value[j]; // default;
- if (panim->offset[j] != 0)
- {
- panimvalue = (mstudioanimvalue_t *)((byte *)panim + panim->offset[j]);
- /*
- if (i == 0 && j == 0)
- Con_DPrintf("%d %d:%d %f\n", frame, panimvalue->num.valid, panimvalue->num.total, s );
- */
-
- k = frame;
- // DEBUG
- if (panimvalue->num.total < panimvalue->num.valid)
- k = 0;
- // find span of values that includes the frame we want
- while (panimvalue->num.total <= k)
- {
- k -= panimvalue->num.total;
- panimvalue += panimvalue->num.valid + 1;
- // DEBUG
- if (panimvalue->num.total < panimvalue->num.valid)
- k = 0;
- }
- // if we're inside the span
- if (panimvalue->num.valid > k)
- {
- // and there's more data in the span
- if (panimvalue->num.valid > k + 1)
- {
- pos[j] += (panimvalue[k+1].value * (1.0 - s) + s * panimvalue[k+2].value) * pbone->scale[j];
- }
- else
- {
- pos[j] += panimvalue[k+1].value * pbone->scale[j];
- }
- }
- else
- {
- // are we at the end of the repeating values section and there's another section with data?
- if (panimvalue->num.total <= k + 1)
- {
- pos[j] += (panimvalue[panimvalue->num.valid].value * (1.0 - s) + s * panimvalue[panimvalue->num.valid + 2].value) * pbone->scale[j];
- }
- else
- {
- pos[j] += panimvalue[panimvalue->num.valid].value * pbone->scale[j];
- }
- }
- }
- if ( pbone->bonecontroller[j] != -1 && adj )
- {
- pos[j] += adj[pbone->bonecontroller[j]];
- }
- }
-}
-
-/*
-====================
-StudioSlerpBones
-
-====================
-*/
-void CStudioModelRenderer::StudioSlerpBones( vec4_t q1[], float pos1[][3], vec4_t q2[], float pos2[][3], float s )
-{
- int i;
- vec4_t q3;
- float s1;
-
- if (s < 0) s = 0;
- else if (s > 1.0) s = 1.0;
-
- s1 = 1.0 - s;
-
- for (i = 0; i < m_pStudioHeader->numbones; i++)
- {
- QuaternionSlerp( q1[i], q2[i], s, q3 );
- q1[i][0] = q3[0];
- q1[i][1] = q3[1];
- q1[i][2] = q3[2];
- q1[i][3] = q3[3];
- pos1[i][0] = pos1[i][0] * s1 + pos2[i][0] * s;
- pos1[i][1] = pos1[i][1] * s1 + pos2[i][1] * s;
- pos1[i][2] = pos1[i][2] * s1 + pos2[i][2] * s;
- }
-}
-
-/*
-====================
-StudioGetAnim
-
-====================
-*/
-mstudioanim_t *CStudioModelRenderer::StudioGetAnim( model_t *m_pSubModel, mstudioseqdesc_t *pseqdesc )
-{
- mstudioseqgroup_t *pseqgroup;
- cache_user_t *paSequences;
-
- pseqgroup = (mstudioseqgroup_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqgroupindex) + pseqdesc->seqgroup;
-
- if (pseqdesc->seqgroup == 0)
- {
+// studio_model.cpp
+// routines for setting up to draw 3DStudio models
+
+#include "hud.h"
+#include "cl_util.h"
+#include "common/const.h"
+#include "common/com_model.h"
+#include "engine/studio.h"
+#include "common/entity_state.h"
+#include "common/cl_entity.h"
+#include "common/dlight.h"
+#include "common/triangleapi.h"
+
+#include
+#include
+#include
+#include
+
+#include "studio_util.h"
+#include "r_studioint.h"
+
+#include "StudioModelRenderer.h"
+#include "GameStudioModelRenderer.h"
+
+#include "util/MathUtil.h"
+
+// Global engine <-> studio model rendering code interface
+engine_studio_api_t IEngineStudio;
+
+#include "mod/AvHSpecials.h"
+
+int GetRenderModeForModelName(int inRenderMode, char* inName)
+{
+ int theRenderMode = inRenderMode;
+
+// if(!strncmp("tcol", inName, 4))
+// {
+// theRenderMode = kRenderTransColor;
+// }
+ if(!strncmp("ttex", inName, 4))
+ {
+ theRenderMode = kRenderTransTexture;
+ }
+ else if(!strncmp("glow", inName, 4))
+ {
+ theRenderMode = kRenderGlow;
+ }
+ else if(!strncmp("talp", inName, 4))
+ {
+ theRenderMode = kRenderTransAlpha;
+ }
+ else if(!strncmp("tadd", inName, 4))
+ {
+ theRenderMode = kRenderTransAdd;
+ }
+
+ return theRenderMode;
+}
+
+
+/////////////////////
+// Implementation of CStudioModelRenderer.h
+
+/*
+====================
+Init
+
+====================
+*/
+void CStudioModelRenderer::Init( void )
+{
+ // Set up some variables shared with engine
+ m_pCvarHiModels = IEngineStudio.GetCvar( "cl_himodels" );
+ m_pCvarDeveloper = IEngineStudio.GetCvar( "developer" );
+ m_pCvarDrawEntities = IEngineStudio.GetCvar( "r_drawentities" );
+
+ m_pChromeSprite = IEngineStudio.GetChromeSprite();
+
+ IEngineStudio.GetModelCounters( &m_pStudioModelCount, &m_pModelsDrawn );
+
+ // Get pointers to engine data structures
+ m_pbonetransform = (float (*)[MAXSTUDIOBONES][3][4])IEngineStudio.StudioGetBoneTransform();
+ m_plighttransform = (float (*)[MAXSTUDIOBONES][3][4])IEngineStudio.StudioGetLightTransform();
+ m_paliastransform = (float (*)[3][4])IEngineStudio.StudioGetAliasTransform();
+ m_protationmatrix = (float (*)[3][4])IEngineStudio.StudioGetRotationMatrix();
+}
+
+/*
+====================
+CStudioModelRenderer
+
+====================
+*/
+CStudioModelRenderer::CStudioModelRenderer( void )
+{
+ m_fDoInterp = 1;
+ m_fGaitEstimation = 1;
+ m_pCurrentEntity = NULL;
+ m_pCvarHiModels = NULL;
+ m_pCvarDeveloper = NULL;
+ m_pCvarDrawEntities = NULL;
+ m_pChromeSprite = NULL;
+ m_pStudioModelCount = NULL;
+ m_pModelsDrawn = NULL;
+ m_protationmatrix = NULL;
+ m_paliastransform = NULL;
+ m_pbonetransform = NULL;
+ m_plighttransform = NULL;
+ m_pStudioHeader = NULL;
+ m_pBodyPart = NULL;
+ m_pSubModel = NULL;
+ m_pPlayerInfo = NULL;
+ m_pRenderModel = NULL;
+}
+
+/*
+====================
+~CStudioModelRenderer
+
+====================
+*/
+CStudioModelRenderer::~CStudioModelRenderer( void )
+{
+}
+
+/*
+====================
+StudioCalcBoneAdj
+
+====================
+*/
+void CStudioModelRenderer::StudioCalcBoneAdj( float dadt, float *adj, const byte *pcontroller1, const byte *pcontroller2, byte mouthopen )
+{
+ int i, j;
+ float value;
+ mstudiobonecontroller_t *pbonecontroller;
+
+ pbonecontroller = (mstudiobonecontroller_t *)((byte *)m_pStudioHeader + m_pStudioHeader->bonecontrollerindex);
+
+ for (j = 0; j < m_pStudioHeader->numbonecontrollers; j++)
+ {
+ i = pbonecontroller[j].index;
+ if (i <= 3)
+ {
+ // check for 360% wrapping
+ if (pbonecontroller[j].type & STUDIO_RLOOP)
+ {
+ if (abs(pcontroller1[i] - pcontroller2[i]) > 128)
+ {
+ int a, b;
+ a = (pcontroller1[j] + 128) % 256;
+ b = (pcontroller2[j] + 128) % 256;
+ value = ((a * dadt) + (b * (1 - dadt)) - 128) * (360.0/256.0) + pbonecontroller[j].start;
+ }
+ else
+ {
+ value = ((pcontroller1[i] * dadt + (pcontroller2[i]) * (1.0 - dadt))) * (360.0/256.0) + pbonecontroller[j].start;
+ }
+ }
+ else
+ {
+ value = (pcontroller1[i] * dadt + pcontroller2[i] * (1.0 - dadt)) / 255.0;
+ if (value < 0) value = 0;
+ if (value > 1.0) value = 1.0;
+ value = (1.0 - value) * pbonecontroller[j].start + value * pbonecontroller[j].end;
+ }
+ // Con_DPrintf( "%d %d %f : %f\n", m_pCurrentEntity->curstate.controller[j], m_pCurrentEntity->latched.prevcontroller[j], value, dadt );
+ }
+ else
+ {
+ value = mouthopen / 64.0;
+ if (value > 1.0) value = 1.0;
+ value = (1.0 - value) * pbonecontroller[j].start + value * pbonecontroller[j].end;
+ // Con_DPrintf("%d %f\n", mouthopen, value );
+ }
+ switch(pbonecontroller[j].type & STUDIO_TYPES)
+ {
+ case STUDIO_XR:
+ case STUDIO_YR:
+ case STUDIO_ZR:
+ adj[j] = value * (M_PI / 180.0);
+ break;
+ case STUDIO_X:
+ case STUDIO_Y:
+ case STUDIO_Z:
+ adj[j] = value;
+ break;
+ }
+ }
+}
+
+
+/*
+====================
+StudioCalcBoneQuaterion
+
+====================
+*/
+void CStudioModelRenderer::StudioCalcBoneQuaterion( int frame, float s, mstudiobone_t *pbone, mstudioanim_t *panim, float *adj, float *q )
+{
+ int j, k;
+ vec4_t q1, q2;
+ vec3_t angle1, angle2;
+ mstudioanimvalue_t *panimvalue;
+
+ for (j = 0; j < 3; j++)
+ {
+ if (panim->offset[j+3] == 0)
+ {
+ angle2[j] = angle1[j] = pbone->value[j+3]; // default;
+ }
+ else
+ {
+ panimvalue = (mstudioanimvalue_t *)((byte *)panim + panim->offset[j+3]);
+ k = frame;
+ // DEBUG
+ if (panimvalue->num.total < panimvalue->num.valid)
+ k = 0;
+ while (panimvalue->num.total <= k)
+ {
+ k -= panimvalue->num.total;
+ panimvalue += panimvalue->num.valid + 1;
+ // DEBUG
+ if (panimvalue->num.total < panimvalue->num.valid)
+ k = 0;
+ }
+ // Bah, missing blend!
+ if (panimvalue->num.valid > k)
+ {
+ angle1[j] = panimvalue[k+1].value;
+
+ if (panimvalue->num.valid > k + 1)
+ {
+ angle2[j] = panimvalue[k+2].value;
+ }
+ else
+ {
+ if (panimvalue->num.total > k + 1)
+ angle2[j] = angle1[j];
+ else
+ angle2[j] = panimvalue[panimvalue->num.valid+2].value;
+ }
+ }
+ else
+ {
+ angle1[j] = panimvalue[panimvalue->num.valid].value;
+ if (panimvalue->num.total > k + 1)
+ {
+ angle2[j] = angle1[j];
+ }
+ else
+ {
+ angle2[j] = panimvalue[panimvalue->num.valid + 2].value;
+ }
+ }
+ angle1[j] = pbone->value[j+3] + angle1[j] * pbone->scale[j+3];
+ angle2[j] = pbone->value[j+3] + angle2[j] * pbone->scale[j+3];
+ }
+
+ if (pbone->bonecontroller[j+3] != -1)
+ {
+ angle1[j] += adj[pbone->bonecontroller[j+3]];
+ angle2[j] += adj[pbone->bonecontroller[j+3]];
+ }
+ }
+
+ if (!VectorCompare( angle1, angle2 ))
+ {
+ AngleQuaternion( angle1, q1 );
+ AngleQuaternion( angle2, q2 );
+ QuaternionSlerp( q1, q2, s, q );
+ }
+ else
+ {
+ AngleQuaternion( angle1, q );
+ }
+}
+
+/*
+====================
+StudioCalcBonePosition
+
+====================
+*/
+void CStudioModelRenderer::StudioCalcBonePosition( int frame, float s, mstudiobone_t *pbone, mstudioanim_t *panim, float *adj, float *pos )
+{
+ int j, k;
+ mstudioanimvalue_t *panimvalue;
+
+ for (j = 0; j < 3; j++)
+ {
+ pos[j] = pbone->value[j]; // default;
+ if (panim->offset[j] != 0)
+ {
+ panimvalue = (mstudioanimvalue_t *)((byte *)panim + panim->offset[j]);
+ /*
+ if (i == 0 && j == 0)
+ Con_DPrintf("%d %d:%d %f\n", frame, panimvalue->num.valid, panimvalue->num.total, s );
+ */
+
+ k = frame;
+ // DEBUG
+ if (panimvalue->num.total < panimvalue->num.valid)
+ k = 0;
+ // find span of values that includes the frame we want
+ while (panimvalue->num.total <= k)
+ {
+ k -= panimvalue->num.total;
+ panimvalue += panimvalue->num.valid + 1;
+ // DEBUG
+ if (panimvalue->num.total < panimvalue->num.valid)
+ k = 0;
+ }
+ // if we're inside the span
+ if (panimvalue->num.valid > k)
+ {
+ // and there's more data in the span
+ if (panimvalue->num.valid > k + 1)
+ {
+ pos[j] += (panimvalue[k+1].value * (1.0 - s) + s * panimvalue[k+2].value) * pbone->scale[j];
+ }
+ else
+ {
+ pos[j] += panimvalue[k+1].value * pbone->scale[j];
+ }
+ }
+ else
+ {
+ // are we at the end of the repeating values section and there's another section with data?
+ if (panimvalue->num.total <= k + 1)
+ {
+ pos[j] += (panimvalue[panimvalue->num.valid].value * (1.0 - s) + s * panimvalue[panimvalue->num.valid + 2].value) * pbone->scale[j];
+ }
+ else
+ {
+ pos[j] += panimvalue[panimvalue->num.valid].value * pbone->scale[j];
+ }
+ }
+ }
+ if ( pbone->bonecontroller[j] != -1 && adj )
+ {
+ pos[j] += adj[pbone->bonecontroller[j]];
+ }
+ }
+}
+
+/*
+====================
+StudioSlerpBones
+
+====================
+*/
+void CStudioModelRenderer::StudioSlerpBones( vec4_t q1[], float pos1[][3], vec4_t q2[], float pos2[][3], float s )
+{
+ int i;
+ vec4_t q3;
+ float s1;
+
+ if (s < 0) s = 0;
+ else if (s > 1.0) s = 1.0;
+
+ s1 = 1.0 - s;
+
+ for (i = 0; i < m_pStudioHeader->numbones; i++)
+ {
+ QuaternionSlerp( q1[i], q2[i], s, q3 );
+ q1[i][0] = q3[0];
+ q1[i][1] = q3[1];
+ q1[i][2] = q3[2];
+ q1[i][3] = q3[3];
+ pos1[i][0] = pos1[i][0] * s1 + pos2[i][0] * s;
+ pos1[i][1] = pos1[i][1] * s1 + pos2[i][1] * s;
+ pos1[i][2] = pos1[i][2] * s1 + pos2[i][2] * s;
+ }
+}
+
+/*
+====================
+StudioGetAnim
+
+====================
+*/
+mstudioanim_t *CStudioModelRenderer::StudioGetAnim( model_t *m_pSubModel, mstudioseqdesc_t *pseqdesc )
+{
+ mstudioseqgroup_t *pseqgroup;
+ cache_user_t *paSequences;
+
+ pseqgroup = (mstudioseqgroup_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqgroupindex) + pseqdesc->seqgroup;
+
+ if (pseqdesc->seqgroup == 0)
+ {
return (mstudioanim_t *)((byte *)m_pStudioHeader + pseqdesc->animindex);
- }
-
- paSequences = (cache_user_t *)m_pSubModel->submodels;
-
- if (paSequences == NULL)
- {
- paSequences = (cache_user_t *)IEngineStudio.Mem_Calloc( 16, sizeof( cache_user_t ) ); // UNDONE: leak!
- m_pSubModel->submodels = (dmodel_t *)paSequences;
- }
-
- if (!IEngineStudio.Cache_Check( (struct cache_user_s *)&(paSequences[pseqdesc->seqgroup])))
- {
- gEngfuncs.Con_DPrintf("loading %s\n", pseqgroup->name );
- IEngineStudio.LoadCacheFile( pseqgroup->name, (struct cache_user_s *)&paSequences[pseqdesc->seqgroup] );
- }
- return (mstudioanim_t *)((byte *)paSequences[pseqdesc->seqgroup].data + pseqdesc->animindex);
-}
-
-/*
-====================
-StudioPlayerBlend
-
-====================
-*/
-void CStudioModelRenderer::StudioPlayerBlend( mstudioseqdesc_t *pseqdesc, int *pBlend, float *pPitch )
-{
- // calc up/down pointing
- *pBlend = (*pPitch * 3);
- if (*pBlend < pseqdesc->blendstart[0])
- {
- *pPitch -= pseqdesc->blendstart[0] / 3.0;
- *pBlend = 0;
- }
- else if (*pBlend > pseqdesc->blendend[0])
- {
- *pPitch -= pseqdesc->blendend[0] / 3.0;
- *pBlend = 255;
- }
- else
- {
- if (pseqdesc->blendend[0] - pseqdesc->blendstart[0] < 0.1) // catch qc error
- *pBlend = 127;
- else
- *pBlend = 255 * (*pBlend - pseqdesc->blendstart[0]) / (pseqdesc->blendend[0] - pseqdesc->blendstart[0]);
- *pPitch = 0;
- }
-}
-
-/*
-====================
-StudioSetUpTransform
-
-====================
-*/
-void CStudioModelRenderer::StudioSetUpTransform (int trivial_accept)
-{
- int i;
- vec3_t angles;
- vec3_t modelpos;
-
-// tweek model origin
- //for (i = 0; i < 3; i++)
- // modelpos[i] = m_pCurrentEntity->origin[i];
-
- VectorCopy( m_pCurrentEntity->origin, modelpos );
-
-// TODO: should really be stored with the entity instead of being reconstructed
-// TODO: should use a look-up table
-// TODO: could cache lazily, stored in the entity
- angles[ROLL] = m_pCurrentEntity->curstate.angles[ROLL];
- angles[PITCH] = m_pCurrentEntity->curstate.angles[PITCH];
- angles[YAW] = m_pCurrentEntity->curstate.angles[YAW];
-
- //Con_DPrintf("Angles %4.2f prev %4.2f for %i\n", angles[PITCH], m_pCurrentEntity->index);
- //Con_DPrintf("movetype %d %d\n", m_pCurrentEntity->movetype, m_pCurrentEntity->aiment );
- if (m_pCurrentEntity->curstate.movetype == MOVETYPE_STEP)
- {
- float f = 0;
- float d;
-
- // don't do it if the goalstarttime hasn't updated in a while.
-
- // NOTE: Because we need to interpolate multiplayer characters, the interpolation time limit
- // was increased to 1.0 s., which is 2x the max lag we are accounting for.
-
- if ( ( m_clTime < m_pCurrentEntity->curstate.animtime + 1.0f ) &&
- ( m_pCurrentEntity->curstate.animtime != m_pCurrentEntity->latched.prevanimtime ) )
- {
- f = (m_clTime - m_pCurrentEntity->curstate.animtime) / (m_pCurrentEntity->curstate.animtime - m_pCurrentEntity->latched.prevanimtime);
- //Con_DPrintf("%4.2f %.2f %.2f\n", f, m_pCurrentEntity->curstate.animtime, m_clTime);
- }
-
- if (m_fDoInterp)
- {
- // ugly hack to interpolate angle, position. current is reached 0.1 seconds after being set
- f = f - 1.0;
- }
- else
- {
- f = 0;
- }
-
- for (i = 0; i < 3; i++)
- {
- modelpos[i] += (m_pCurrentEntity->origin[i] - m_pCurrentEntity->latched.prevorigin[i]) * f;
- }
-
- // NOTE: Because multiplayer lag can be relatively large, we don't want to cap
- // f at 1.5 anymore.
- //if (f > -1.0 && f < 1.5) {}
-
-// Con_DPrintf("%.0f %.0f\n",m_pCurrentEntity->msg_angles[0][YAW], m_pCurrentEntity->msg_angles[1][YAW] );
- for (i = 0; i < 3; i++)
- {
- float ang1, ang2;
-
- ang1 = m_pCurrentEntity->angles[i];
- ang2 = m_pCurrentEntity->latched.prevangles[i];
-
- d = ang1 - ang2;
- if (d > 180)
- {
- d -= 360;
- }
- else if (d < -180)
- {
- d += 360;
- }
-
- angles[i] += d * f;
- }
- //Con_DPrintf("%.3f \n", f );
- }
- else if ( m_pCurrentEntity->curstate.movetype != MOVETYPE_NONE )
- {
- VectorCopy( m_pCurrentEntity->angles, angles );
- }
-
- // Added by mmcguire.
-
- if (m_pCurrentEntity->curstate.iuser3 == AVH_USER3_ALIEN_PLAYER1)
- {
-
- // Override the orientation with the values stored in vuser1.
-
- VectorCopy(m_pCurrentEntity->curstate.vuser1, angles);
-
- // The code that sets up the transformation negates the pitch
- // for some reason, so compensate for that here.
-
- angles[PITCH] = -angles[PITCH];
-
- }
-
-
-// bool theIsWallSticking = GetHasUpgrade(m_pCurrentEntity->curstate.iuser4, MASK_WALLSTICKING);
-// if(theIsWallSticking)
-// {
-// //RotateFloatValuesByVector(angles[ROLL], angles[YAW], angles[PITCH], m_pCurrentEntity->curstate.vuser1);
-// //VectorCopy(m_pCurrentEntity->curstate.vuser1, angles);
-//
-// // Surface normal is in vuser1. Transform current forward to new forward
-// vec3_t theCurrentForward;
-// vec3_t theCurrentRight;
-// vec3_t theCurrentUp;
-// gEngfuncs.pfnAngleVectors(angles, theCurrentForward, theCurrentRight, theCurrentUp);
-//
-// vec3_t theWallUp = m_pCurrentEntity->curstate.vuser1;
-//
-// vec3_t theWallSide;
-// CrossProduct(theWallUp, theCurrentForward, theWallSide);
-//
-// vec3_t theWallForward;
-// //CrossProduct(theWallUp, theWallSide, theWallForward);
-// VectorCopy(theCurrentForward, theWallForward);
-//
-// // Build matrix to transform current frame of reference to that of sticking to wall
-// float theViewToWallMatrix[3][4];
-// theViewToWallMatrix[0][0] = theWallForward.x;
-// theViewToWallMatrix[0][1] = theWallForward.y;
-// theViewToWallMatrix[0][2] = theWallForward.z;
-//
-// theViewToWallMatrix[1][0] = theWallSide.x;
-// theViewToWallMatrix[1][1] = theWallSide.y;
-// theViewToWallMatrix[1][2] = theWallSide.z;
-//
-// theViewToWallMatrix[2][0] = theWallUp.x;
-// theViewToWallMatrix[2][1] = theWallUp.y;
-// theViewToWallMatrix[2][2] = theWallUp.z;
-//
-// vec3_t theNewForward;
-// VectorTransform(theCurrentForward, theViewToWallMatrix, theNewForward);
-//
-// // Transform new forward to angles
-// VectorAngles(theNewForward, angles);
-// }
-
- //Con_DPrintf("%.0f %0.f %0.f\n", modelpos[0], modelpos[1], modelpos[2] );
- //Con_DPrintf("%.0f %0.f %0.f\n", angles[0], angles[1], angles[2] );
-
- angles[PITCH] = -angles[PITCH];
- AngleMatrix (angles, (*m_protationmatrix));
-
- if ( !IEngineStudio.IsHardware() )
- {
- static float viewmatrix[3][4];
-
- VectorCopy (m_vRight, viewmatrix[0]);
- VectorCopy (m_vUp, viewmatrix[1]);
- VectorInverse (viewmatrix[1]);
- VectorCopy (m_vNormal, viewmatrix[2]);
-
- (*m_protationmatrix)[0][3] = modelpos[0] - m_vRenderOrigin[0];
- (*m_protationmatrix)[1][3] = modelpos[1] - m_vRenderOrigin[1];
- (*m_protationmatrix)[2][3] = modelpos[2] - m_vRenderOrigin[2];
-
- ConcatTransforms (viewmatrix, (*m_protationmatrix), (*m_paliastransform));
-
- // do the scaling up of x and y to screen coordinates as part of the transform
- // for the unclipped case (it would mess up clipping in the clipped case).
- // Also scale down z, so 1/z is scaled 31 bits for free, and scale down x and y
- // correspondingly so the projected x and y come out right
- // FIXME: make this work for clipped case too?
- if (trivial_accept)
- {
- for (i=0 ; i<4 ; i++)
- {
- (*m_paliastransform)[0][i] *= m_fSoftwareXScale *
- (1.0 / (ZISCALE * 0x10000));
- (*m_paliastransform)[1][i] *= m_fSoftwareYScale *
- (1.0 / (ZISCALE * 0x10000));
- (*m_paliastransform)[2][i] *= 1.0 / (ZISCALE * 0x10000);
-
- }
- }
- }
-
- (*m_protationmatrix)[0][3] = modelpos[0];
- (*m_protationmatrix)[1][3] = modelpos[1];
- (*m_protationmatrix)[2][3] = modelpos[2];
-}
-
-
-/*
-====================
-StudioEstimateInterpolant
-
-====================
-*/
-float CStudioModelRenderer::StudioEstimateInterpolant( void )
-{
- float dadt = 1.0;
-
- if ( m_fDoInterp && ( m_pCurrentEntity->curstate.animtime >= m_pCurrentEntity->latched.prevanimtime + 0.01 ) )
- {
- dadt = (m_clTime - m_pCurrentEntity->curstate.animtime) / 0.1;
- if (dadt > 2.0)
- {
- dadt = 2.0;
- }
- }
- return dadt;
-}
-
-/*
-====================
-StudioCalcRotations
-
-====================
-*/
-void CStudioModelRenderer::StudioCalcRotations ( float pos[][3], vec4_t *q, mstudioseqdesc_t *pseqdesc, mstudioanim_t *panim, float f )
-{
- int i;
- int frame;
- mstudiobone_t *pbone;
-
- float s;
- float adj[MAXSTUDIOCONTROLLERS];
- float dadt;
-
- if (f > pseqdesc->numframes - 1)
- {
- f = 0; // bah, fix this bug with changing sequences too fast
- }
- // BUG ( somewhere else ) but this code should validate this data.
- // This could cause a crash if the frame # is negative, so we'll go ahead
- // and clamp it here
- else if ( f < -0.01 )
- {
- f = -0.01;
- }
-
- frame = (int)f;
-
- //gEngfuncs.Con_DPrintf("%d %.4f %.4f %.4f %.4f %d\n", m_pCurrentEntity->curstate.sequence, m_clTime, m_pCurrentEntity->animtime, m_pCurrentEntity->frame, f, frame );
-
- // gEngfuncs.Con_DPrintf( "%f %f %f\n", m_pCurrentEntity->angles[ROLL], m_pCurrentEntity->angles[PITCH], m_pCurrentEntity->angles[YAW] );
-
- //gEngfuncs.Con_DPrintf("frame %d %d\n", frame1, frame2 );
-
-
- dadt = StudioEstimateInterpolant( );
- s = (f - frame);
-
- // add in programtic controllers
- pbone = (mstudiobone_t *)((byte *)m_pStudioHeader + m_pStudioHeader->boneindex);
-
- StudioCalcBoneAdj( dadt, adj, m_pCurrentEntity->curstate.controller, m_pCurrentEntity->latched.prevcontroller, m_pCurrentEntity->mouth.mouthopen );
-
- for (i = 0; i < m_pStudioHeader->numbones; i++, pbone++, panim++)
- {
- StudioCalcBoneQuaterion( frame, s, pbone, panim, adj, q[i] );
-
- StudioCalcBonePosition( frame, s, pbone, panim, adj, pos[i] );
- // if (0 && i == 0)
- // Con_DPrintf("%d %d %d %d\n", m_pCurrentEntity->curstate.sequence, frame, j, k );
- }
-
- if (pseqdesc->motiontype & STUDIO_X)
- {
- pos[pseqdesc->motionbone][0] = 0.0;
- }
- if (pseqdesc->motiontype & STUDIO_Y)
- {
- pos[pseqdesc->motionbone][1] = 0.0;
- }
- if (pseqdesc->motiontype & STUDIO_Z)
- {
- pos[pseqdesc->motionbone][2] = 0.0;
- }
-
- //gEngfuncs.Con_Printf("framerate %f\n", m_pCurrentEntity->curstate.framerate);
-
- s = 0 * ((1.0 - (f - (int)(f))) / (pseqdesc->numframes)) * m_pCurrentEntity->curstate.framerate;
-
- if (pseqdesc->motiontype & STUDIO_LX)
- {
- pos[pseqdesc->motionbone][0] += s * pseqdesc->linearmovement[0];
- }
- if (pseqdesc->motiontype & STUDIO_LY)
- {
- pos[pseqdesc->motionbone][1] += s * pseqdesc->linearmovement[1];
- }
- if (pseqdesc->motiontype & STUDIO_LZ)
- {
- pos[pseqdesc->motionbone][2] += s * pseqdesc->linearmovement[2];
- }
-}
-
-/*
-====================
-Studio_FxTransform
-
-====================
-*/
-void CStudioModelRenderer::StudioFxTransform( cl_entity_t *ent, float transform[3][4] )
-{
- switch( ent->curstate.renderfx )
- {
- case kRenderFxDistort:
- case kRenderFxHologram:
- if ( gEngfuncs.pfnRandomLong(0,49) == 0 )
- {
- int axis = gEngfuncs.pfnRandomLong(0,1);
- if ( axis == 1 ) // Choose between x & z
- axis = 2;
- VectorScale( transform[axis], gEngfuncs.pfnRandomFloat(1,1.484), transform[axis] );
- }
- else if ( gEngfuncs.pfnRandomLong(0,49) == 0 )
- {
- float offset;
- int axis = gEngfuncs.pfnRandomLong(0,1);
- if ( axis == 1 ) // Choose between x & z
- axis = 2;
- offset = gEngfuncs.pfnRandomFloat(-10,10);
- transform[gEngfuncs.pfnRandomLong(0,2)][3] += offset;
- }
- break;
- case kRenderFxExplode:
- {
- float scale;
-
- scale = 1.0 + ( m_clTime - ent->curstate.animtime) * 10.0;
- if ( scale > 2 ) // Don't blow up more than 200%
- scale = 2;
- transform[0][1] *= scale;
- transform[1][1] *= scale;
- transform[2][1] *= scale;
- }
- break;
-
- }
-}
-
-/*
-====================
-StudioEstimateFrame
-
-====================
-*/
-float CStudioModelRenderer::StudioEstimateFrame( mstudioseqdesc_t *pseqdesc )
-{
- double dfdt, f;
-
- if ( m_fDoInterp )
- {
- if ( m_clTime < m_pCurrentEntity->curstate.animtime )
- {
- dfdt = 0;
- }
- else
- {
- dfdt = (m_clTime - m_pCurrentEntity->curstate.animtime) * m_pCurrentEntity->curstate.framerate * pseqdesc->fps;
-
- }
- }
- else
- {
- dfdt = 0;
- }
-
- if (pseqdesc->numframes <= 1)
- {
- f = 0;
- }
- else
- {
- f = (m_pCurrentEntity->curstate.frame * (pseqdesc->numframes - 1)) / 256.0;
- }
-
- f += dfdt;
-
- if (pseqdesc->flags & STUDIO_LOOPING)
- {
- if (pseqdesc->numframes > 1)
- {
- f -= (int)(f / (pseqdesc->numframes - 1)) * (pseqdesc->numframes - 1);
- }
- if (f < 0)
- {
- f += (pseqdesc->numframes - 1);
- }
- }
- else
- {
- if (f >= pseqdesc->numframes - 1.001)
- {
- f = pseqdesc->numframes - 1.001;
- }
- if (f < 0.0)
- {
- f = 0.0;
- }
- }
- return f;
-}
-
-bool GetDoesBoneHaveParent(int inMaybeBeneathBone, int inParentBone, mstudiobone_t* inBones)
-{
- bool theSuccess = false;
-
- ASSERT(inMaybeBeneathBone < MAXSTUDIOBONES);
- ASSERT(inParentBone < MAXSTUDIOBONES);
-
- int theCurrentParent = inBones[inMaybeBeneathBone].parent;
-
- if(theCurrentParent == inParentBone)
- {
- theSuccess = true;
- }
- else if(theCurrentParent != -1)
- {
- theSuccess = GetDoesBoneHaveParent(theCurrentParent, inParentBone, inBones);
- }
-
- return theSuccess;
-}
-
-/*
-====================
-StudioSetupBones
-
-====================
-*/
-void CStudioModelRenderer::StudioSetupBones ( void )
-{
- int i;
- double f;
-
- mstudiobone_t *pbones;
- mstudioseqdesc_t *pseqdesc;
- mstudioanim_t *panim;
-
- static float pos[MAXSTUDIOBONES][3];
- static vec4_t q[MAXSTUDIOBONES];
- float bonematrix[3][4];
-
- static float pos2[MAXSTUDIOBONES][3];
- static vec4_t q2[MAXSTUDIOBONES];
- static float pos3[MAXSTUDIOBONES][3];
- static vec4_t q3[MAXSTUDIOBONES];
- static float pos4[MAXSTUDIOBONES][3];
- static vec4_t q4[MAXSTUDIOBONES];
-
- if (m_pCurrentEntity->curstate.sequence >= m_pStudioHeader->numseq)
- {
- m_pCurrentEntity->curstate.sequence = 0;
- }
- else if (m_pCurrentEntity->curstate.sequence < 0)
- {
- m_pCurrentEntity->curstate.sequence = 0;
- }
-
- pseqdesc = (mstudioseqdesc_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqindex) + m_pCurrentEntity->curstate.sequence;
-
- f = StudioEstimateFrame( pseqdesc );
-
- if (m_pCurrentEntity->latched.prevframe > f)
- {
- //Con_DPrintf("%f %f\n", m_pCurrentEntity->prevframe, f );
- }
-
- panim = StudioGetAnim( m_pRenderModel, pseqdesc );
- StudioCalcRotations( pos, q, pseqdesc, panim, f );
-
- if (pseqdesc->numblends > 1)
- {
- float s;
- float dadt;
-
- panim += m_pStudioHeader->numbones;
- StudioCalcRotations( pos2, q2, pseqdesc, panim, f );
-
- dadt = StudioEstimateInterpolant();
- s = (m_pCurrentEntity->curstate.blending[0] * dadt + m_pCurrentEntity->latched.prevblending[0] * (1.0 - dadt)) / 255.0;
-
- StudioSlerpBones( q, pos, q2, pos2, s );
-
- if (pseqdesc->numblends == 4)
- {
- panim += m_pStudioHeader->numbones;
- StudioCalcRotations( pos3, q3, pseqdesc, panim, f );
-
- panim += m_pStudioHeader->numbones;
- StudioCalcRotations( pos4, q4, pseqdesc, panim, f );
-
- s = (m_pCurrentEntity->curstate.blending[0] * dadt + m_pCurrentEntity->latched.prevblending[0] * (1.0 - dadt)) / 255.0;
- StudioSlerpBones( q3, pos3, q4, pos4, s );
-
- s = (m_pCurrentEntity->curstate.blending[1] * dadt + m_pCurrentEntity->latched.prevblending[1] * (1.0 - dadt)) / 255.0;
- StudioSlerpBones( q, pos, q3, pos3, s );
- }
- }
-
- if (m_fDoInterp &&
- m_pCurrentEntity->latched.sequencetime &&
- ( m_pCurrentEntity->latched.sequencetime + 0.2 > m_clTime ) &&
- ( m_pCurrentEntity->latched.prevsequence < m_pStudioHeader->numseq ))
- {
- // blend from last sequence
- static float pos1b[MAXSTUDIOBONES][3];
- static vec4_t q1b[MAXSTUDIOBONES];
- float s;
-
- pseqdesc = (mstudioseqdesc_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqindex) + m_pCurrentEntity->latched.prevsequence;
- panim = StudioGetAnim( m_pRenderModel, pseqdesc );
- // clip prevframe
- StudioCalcRotations( pos1b, q1b, pseqdesc, panim, m_pCurrentEntity->latched.prevframe );
-
- if (pseqdesc->numblends > 1)
- {
- panim += m_pStudioHeader->numbones;
- StudioCalcRotations( pos2, q2, pseqdesc, panim, m_pCurrentEntity->latched.prevframe );
-
- s = (m_pCurrentEntity->latched.prevseqblending[0]) / 255.0;
- StudioSlerpBones( q1b, pos1b, q2, pos2, s );
-
- if (pseqdesc->numblends == 4)
- {
- panim += m_pStudioHeader->numbones;
- StudioCalcRotations( pos3, q3, pseqdesc, panim, m_pCurrentEntity->latched.prevframe );
-
- panim += m_pStudioHeader->numbones;
- StudioCalcRotations( pos4, q4, pseqdesc, panim, m_pCurrentEntity->latched.prevframe );
-
- s = (m_pCurrentEntity->latched.prevseqblending[0]) / 255.0;
- StudioSlerpBones( q3, pos3, q4, pos4, s );
-
- s = (m_pCurrentEntity->latched.prevseqblending[1]) / 255.0;
- StudioSlerpBones( q1b, pos1b, q3, pos3, s );
- }
- }
-
- s = 1.0 - (m_clTime - m_pCurrentEntity->latched.sequencetime) / 0.2;
- StudioSlerpBones( q, pos, q1b, pos1b, s );
- }
- else
- {
- //Con_DPrintf("prevframe = %4.2f\n", f);
- m_pCurrentEntity->latched.prevframe = f;
- }
-
- pbones = (mstudiobone_t *)((byte *)m_pStudioHeader + m_pStudioHeader->boneindex);
-
- // calc gait animation
- if (m_pPlayerInfo && (m_pPlayerInfo->gaitsequence != 0) && (m_pPlayerInfo->gaitsequence != 255))
- {
- m_pPlayerInfo->gaitsequence = max(min(m_pPlayerInfo->gaitsequence, m_pStudioHeader->numseq-1), 0);
-
-// // Trim sequences within range (not sure why this is out of range though)
-// int theIndex = min(max(0, m_pStudioHeader->seqindex), m_pStudioHeader->numseq - 1);
-// if(theIndex != m_pStudioHeader->seqindex)
-// {
-// m_pStudioHeader->seqindex = theIndex;
-// m_pPlayerInfo->gaitsequence = 0;
-// }
-
- pseqdesc = (mstudioseqdesc_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqindex) + m_pPlayerInfo->gaitsequence;
-
- panim = StudioGetAnim( m_pRenderModel, pseqdesc );
- StudioCalcRotations( pos2, q2, pseqdesc, panim, m_pPlayerInfo->gaitframe );
-
-// Valve way
-// for (i = 0; i < m_pStudioHeader->numbones; i++)
-// {
-// if (strcmp( pbones[i].name, "Bip01 Spine") == 0)
-// break;
-// memcpy( pos[i], pos2[i], sizeof( pos[i] ));
-// memcpy( q[i], q2[i], sizeof( q[i] ));
-// }
-
-// NS way
- // Look up parent bone that defines the boundary for gaitsequence
- int theNumParents = 0;
- int theParents[MAXSTUDIOBONES];
- memset(theParents, -1, sizeof(int)*MAXSTUDIOBONES);
-
- for (i = 0; i < m_pStudioHeader->numbones; i++)
- {
- // Must contain "Thigh"
- if(strstr(pbones[i].name, "Thigh"))
- {
- theParents[theNumParents++] = i;
- }
- }
- // If this is firing, it means a model has a gaitsequence set but doesn't have a bone that defines which bones are used for that gaitsequence
- //ASSERT(theNumParents > 0);
-
- // If there aren't any thighs, assume that the old HL way was used
- if(theNumParents > 0)
- {
- int theNumBonesWithThisParent = 0;
- int theBonesWithParent[MAXSTUDIOBONES];
-
- // For each bone
- for(i = 0; i < m_pStudioHeader->numbones; i++)
- {
- for(int j = 0; j < theNumParents; j++)
- {
- // Does bone have this parent bone?
- int theParent = theParents[j];
- //if(/*(i == theParent) ||*/ GetDoesBoneHaveParent(i, theParent, pbones))
- char* theBoneName = pbones[i].name;
- if(!strcmp(theBoneName, "Bip01") || (!strcmp(theBoneName, "Bip01 Pelvis")) || (i == theParent) || GetDoesBoneHaveParent(i, theParent, pbones))
- {
- // If so, add it to the list and increment num bones
- theBonesWithParent[theNumBonesWithThisParent++] = i;
- break;
- }
- }
- }
-
- for(int j = 0; j < theNumBonesWithThisParent; j++)
- {
- int i = theBonesWithParent[j];
-
- // If the bone is in this list, use that bones data (gaitsequence) instead of the existing data (sequence)
- memcpy( pos[i], pos2[i], sizeof( pos[i] ));
- memcpy( q[i], q2[i], sizeof( q[i] ));
- }
- }
- else
- {
- for (i = 0; i < m_pStudioHeader->numbones; i++)
- {
- if (strcmp( pbones[i].name, "Bip01 Spine") == 0)
- break;
- memcpy( pos[i], pos2[i], sizeof( pos[i] ));
- memcpy( q[i], q2[i], sizeof( q[i] ));
- }
- }
-
- //gEngfuncs.Con_Printf("gait: %d, frame: %f\n", m_pPlayerInfo->gaitsequence, m_pPlayerInfo->gaitframe);
- }
-
-
- for (i = 0; i < m_pStudioHeader->numbones; i++)
- {
- QuaternionMatrix( q[i], bonematrix );
-
- bonematrix[0][3] = pos[i][0];
- bonematrix[1][3] = pos[i][1];
- bonematrix[2][3] = pos[i][2];
-
- if (pbones[i].parent == -1)
- {
- if ( IEngineStudio.IsHardware() )
- {
- ConcatTransforms ((*m_protationmatrix), bonematrix, (*m_pbonetransform)[i]);
- // MatrixCopy should be faster...
- //ConcatTransforms ((*m_protationmatrix), bonematrix, (*m_plighttransform)[i]);
- MatrixCopy( (*m_pbonetransform)[i], (*m_plighttransform)[i] );
- }
- else
- {
- ConcatTransforms ((*m_paliastransform), bonematrix, (*m_pbonetransform)[i]);
- ConcatTransforms ((*m_protationmatrix), bonematrix, (*m_plighttransform)[i]);
- }
-
- // Apply client-side effects to the transformation matrix
- StudioFxTransform( m_pCurrentEntity, (*m_pbonetransform)[i] );
- }
- else
- {
- ConcatTransforms ((*m_pbonetransform)[pbones[i].parent], bonematrix, (*m_pbonetransform)[i]);
- ConcatTransforms ((*m_plighttransform)[pbones[i].parent], bonematrix, (*m_plighttransform)[i]);
- }
- }
-}
-
-
-/*
-====================
-StudioSaveBones
-
-====================
-*/
-void CStudioModelRenderer::StudioSaveBones( void )
-{
- int i;
-
- mstudiobone_t *pbones;
- pbones = (mstudiobone_t *)((byte *)m_pStudioHeader + m_pStudioHeader->boneindex);
-
- m_nCachedBones = m_pStudioHeader->numbones;
-
- for (i = 0; i < m_pStudioHeader->numbones; i++)
- {
- strcpy( m_nCachedBoneNames[i], pbones[i].name );
- MatrixCopy( (*m_pbonetransform)[i], m_rgCachedBoneTransform[i] );
- MatrixCopy( (*m_plighttransform)[i], m_rgCachedLightTransform[i] );
- }
-}
-
-
-/*
-====================
-StudioMergeBones
-
-====================
-*/
-void CStudioModelRenderer::StudioMergeBones ( model_t *m_pSubModel )
-{
- int i, j;
- double f;
- int do_hunt = true;
-
- mstudiobone_t *pbones;
- mstudioseqdesc_t *pseqdesc;
- mstudioanim_t *panim;
-
- static float pos[MAXSTUDIOBONES][3];
- float bonematrix[3][4];
- static vec4_t q[MAXSTUDIOBONES];
-
- if (m_pCurrentEntity->curstate.sequence >= m_pStudioHeader->numseq)
- {
- m_pCurrentEntity->curstate.sequence = 0;
- }
-
- pseqdesc = (mstudioseqdesc_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqindex) + m_pCurrentEntity->curstate.sequence;
-
- f = StudioEstimateFrame( pseqdesc );
-
- if (m_pCurrentEntity->latched.prevframe > f)
- {
- //Con_DPrintf("%f %f\n", m_pCurrentEntity->prevframe, f );
- }
-
- panim = StudioGetAnim( m_pSubModel, pseqdesc );
- StudioCalcRotations( pos, q, pseqdesc, panim, f );
-
- pbones = (mstudiobone_t *)((byte *)m_pStudioHeader + m_pStudioHeader->boneindex);
-
-
- for (i = 0; i < m_pStudioHeader->numbones; i++)
- {
- for (j = 0; j < m_nCachedBones; j++)
- {
- if (stricmp(pbones[i].name, m_nCachedBoneNames[j]) == 0)
- {
- MatrixCopy( m_rgCachedBoneTransform[j], (*m_pbonetransform)[i] );
- MatrixCopy( m_rgCachedLightTransform[j], (*m_plighttransform)[i] );
- break;
- }
- }
- if (j >= m_nCachedBones)
- {
- QuaternionMatrix( q[i], bonematrix );
-
- bonematrix[0][3] = pos[i][0];
- bonematrix[1][3] = pos[i][1];
- bonematrix[2][3] = pos[i][2];
-
- if (pbones[i].parent == -1)
- {
- if ( IEngineStudio.IsHardware() )
- {
- ConcatTransforms ((*m_protationmatrix), bonematrix, (*m_pbonetransform)[i]);
- // MatrixCopy should be faster...
- //ConcatTransforms ((*m_protationmatrix), bonematrix, (*m_plighttransform)[i]);
- MatrixCopy( (*m_pbonetransform)[i], (*m_plighttransform)[i] );
- }
- else
- {
- ConcatTransforms ((*m_paliastransform), bonematrix, (*m_pbonetransform)[i]);
- ConcatTransforms ((*m_protationmatrix), bonematrix, (*m_plighttransform)[i]);
- }
-
- // Apply client-side effects to the transformation matrix
- StudioFxTransform( m_pCurrentEntity, (*m_pbonetransform)[i] );
- }
- else
- {
- ConcatTransforms ((*m_pbonetransform)[pbones[i].parent], bonematrix, (*m_pbonetransform)[i]);
- ConcatTransforms ((*m_plighttransform)[pbones[i].parent], bonematrix, (*m_plighttransform)[i]);
- }
- }
- }
-}
-
-/*
-====================
-StudioDrawModel
-
-====================
-*/
-int CStudioModelRenderer::StudioDrawModel( int flags )
-{
- alight_t lighting;
- vec3_t dir;
-
- m_pCurrentEntity = IEngineStudio.GetCurrentEntity();
- IEngineStudio.GetTimes( &m_nFrameCount, &m_clTime, &m_clOldTime );
- IEngineStudio.GetViewInfo( m_vRenderOrigin, m_vUp, m_vRight, m_vNormal );
- IEngineStudio.GetAliasScale( &m_fSoftwareXScale, &m_fSoftwareYScale );
-
- // Horrible hack for preventing visual artifacts while being digested
- if(gHUD.GetIsBeingDigested())
- {
- return 0;
- }
-
- /*
- // Now render eyebeam if model is marine //
- // If player is a marine
- if(m_pCurrentEntity->curstate.iuser3 == AVH_USER3_MARINE_PLAYER)
- {
- // Get eyepiece attachment
- vec3_t theEyepieceOrigin;
- VectorCopy(m_pCurrentEntity->attachment[2], theEyepieceOrigin);
-
- // Build this line
-
- // Run a traceline along this line until it hits
-
- // Get endpoint
-
- // Draw red additive light along this line
- //gEngfuncs.pEfxAPI->R_RocketTrail();
- }
- */
-
- if (m_pCurrentEntity->curstate.renderfx == kRenderFxDeadPlayer)
- {
- entity_state_t deadplayer;
-
- int result;
- int save_interp;
-
- if (m_pCurrentEntity->curstate.renderamt <= 0 || m_pCurrentEntity->curstate.renderamt > gEngfuncs.GetMaxClients() )
- return 0;
-
- // get copy of player
- deadplayer = *(IEngineStudio.GetPlayerState( m_pCurrentEntity->curstate.renderamt - 1 )); //cl.frames[cl.parsecount & CL_UPDATE_MASK].playerstate[m_pCurrentEntity->curstate.renderamt-1];
-
- // clear weapon, movement state
- deadplayer.number = m_pCurrentEntity->curstate.renderamt;
- deadplayer.weaponmodel = 0;
- deadplayer.gaitsequence = 0;
-
- deadplayer.movetype = MOVETYPE_NONE;
- VectorCopy( m_pCurrentEntity->curstate.angles, deadplayer.angles );
- VectorCopy( m_pCurrentEntity->curstate.origin, deadplayer.origin );
-
- save_interp = m_fDoInterp;
- m_fDoInterp = 0;
-
- // draw as though it were a player
- result = StudioDrawPlayer( flags, &deadplayer );
-
- m_fDoInterp = save_interp;
- return result;
- }
-
- m_pRenderModel = m_pCurrentEntity->model;
- m_pStudioHeader = (studiohdr_t *)IEngineStudio.Mod_Extradata (m_pRenderModel);
- IEngineStudio.StudioSetHeader( m_pStudioHeader );
- IEngineStudio.SetRenderModel( m_pRenderModel );
-
- StudioSetUpTransform( 0 );
-
- if (flags & STUDIO_RENDER)
- {
- // see if the bounding box lets us trivially reject, also sets
- if (!IEngineStudio.StudioCheckBBox ())
- return 0;
-
- (*m_pModelsDrawn)++;
- (*m_pStudioModelCount)++; // render data cache cookie
-
- if (m_pStudioHeader->numbodyparts == 0)
- return 1;
- }
-
- if (m_pCurrentEntity->curstate.movetype == MOVETYPE_FOLLOW)
- {
- StudioMergeBones( m_pRenderModel );
- }
- else
- {
- StudioSetupBones( );
- }
- StudioSaveBones( );
-
- if (flags & STUDIO_EVENTS)
- {
- StudioCalcAttachments( );
- IEngineStudio.StudioClientEvents( );
- // copy attachments into global entity array
- if ( m_pCurrentEntity->index > 0 )
- {
- cl_entity_t *ent = gEngfuncs.GetEntityByIndex( m_pCurrentEntity->index );
-
- memcpy( ent->attachment, m_pCurrentEntity->attachment, sizeof( vec3_t ) * 4 );
- }
- }
-
- if (flags & STUDIO_RENDER)
- {
- lighting.plightvec = dir;
- IEngineStudio.StudioDynamicLight(m_pCurrentEntity, &lighting );
-
- IEngineStudio.StudioEntityLight( &lighting );
-
- // model and frame independant
- IEngineStudio.StudioSetupLighting (&lighting);
-
- // get remap colors
- m_nTopColor = m_pCurrentEntity->curstate.colormap & 0xFF;
- m_nBottomColor = (m_pCurrentEntity->curstate.colormap & 0xFF00) >> 8;
-
- IEngineStudio.StudioSetRemapColors( m_nTopColor, m_nBottomColor );
-
- StudioRenderModel();
-
- // If this is the local player's view model, hook into HUD
- char theModelName[MAX_MODEL_NAME];
- strcpy(theModelName, this->m_pCurrentEntity->model->name);
-
- gHUD.PostModelRender(theModelName);
- }
-
- return 1;
-}
-
-/*
-====================
-StudioEstimateGait
-
-====================
-*/
-void CStudioModelRenderer::StudioEstimateGait( entity_state_t *pplayer )
-{
- float dt;
- vec3_t est_velocity;
-
- dt = (m_clTime - m_clOldTime);
- if (dt < 0)
- dt = 0;
- else if (dt > 1.0)
- dt = 1;
-
- if (dt == 0 || m_pPlayerInfo->renderframe == m_nFrameCount)
- {
- m_flGaitMovement = 0;
- return;
- }
-
- // VectorAdd( pplayer->velocity, pplayer->prediction_error, est_velocity );
- if ( m_fGaitEstimation )
- {
- VectorSubtract( m_pCurrentEntity->origin, m_pPlayerInfo->prevgaitorigin, est_velocity );
- VectorCopy( m_pCurrentEntity->origin, m_pPlayerInfo->prevgaitorigin );
- m_flGaitMovement = Length( est_velocity );
- if (dt <= 0 || m_flGaitMovement / dt < 5)
- {
- m_flGaitMovement = 0;
- est_velocity[0] = 0;
- est_velocity[1] = 0;
- }
- }
- else
- {
- VectorCopy( pplayer->velocity, est_velocity );
- m_flGaitMovement = Length( est_velocity ) * dt;
- }
-
- if (est_velocity[1] == 0 && est_velocity[0] == 0)
- {
- float flYawDiff = m_pCurrentEntity->angles[YAW] - m_pPlayerInfo->gaityaw;
- flYawDiff = flYawDiff - (int)(flYawDiff / 360) * 360;
- if (flYawDiff > 180)
- flYawDiff -= 360;
- if (flYawDiff < -180)
- flYawDiff += 360;
-
- if (dt < 0.25)
- flYawDiff *= dt * 4;
- else
- flYawDiff *= dt;
-
- m_pPlayerInfo->gaityaw += flYawDiff;
- m_pPlayerInfo->gaityaw = m_pPlayerInfo->gaityaw - (int)(m_pPlayerInfo->gaityaw / 360) * 360;
-
- m_flGaitMovement = 0;
- }
- else
- {
- m_pPlayerInfo->gaityaw = (atan2(est_velocity[1], est_velocity[0]) * 180 / M_PI);
- if (m_pPlayerInfo->gaityaw > 180)
- m_pPlayerInfo->gaityaw = 180;
- if (m_pPlayerInfo->gaityaw < -180)
- m_pPlayerInfo->gaityaw = -180;
- }
-
-}
-
-/*
-====================
-StudioProcessGait
-
-====================
-*/
-void CStudioModelRenderer::StudioProcessGait( entity_state_t *pplayer )
-{
- mstudioseqdesc_t *pseqdesc;
- float dt;
- int iBlend;
- float flYaw; // view direction relative to movement
-
- m_pCurrentEntity->curstate.sequence = max(min(m_pCurrentEntity->curstate.sequence, m_pStudioHeader->numseq-1), 0);
-
- pseqdesc = (mstudioseqdesc_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqindex) + m_pCurrentEntity->curstate.sequence;
-
- StudioPlayerBlend( pseqdesc, &iBlend, &m_pCurrentEntity->angles[PITCH] );
-
- m_pCurrentEntity->latched.prevangles[PITCH] = m_pCurrentEntity->angles[PITCH];
- m_pCurrentEntity->curstate.blending[0] = iBlend;
- m_pCurrentEntity->latched.prevblending[0] = m_pCurrentEntity->curstate.blending[0];
- m_pCurrentEntity->latched.prevseqblending[0] = m_pCurrentEntity->curstate.blending[0];
-
- // Con_DPrintf("%f %d\n", m_pCurrentEntity->angles[PITCH], m_pCurrentEntity->blending[0] );
-
- dt = (m_clTime - m_clOldTime);
- if (dt < 0)
- dt = 0;
- else if (dt > 1.0)
- dt = 1;
-
- StudioEstimateGait( pplayer );
-
- // Con_DPrintf("%f %f\n", m_pCurrentEntity->angles[YAW], m_pPlayerInfo->gaityaw );
-
- // calc side to side turning
- flYaw = m_pCurrentEntity->angles[YAW] - m_pPlayerInfo->gaityaw;
- flYaw = flYaw - (int)(flYaw / 360) * 360;
- if (flYaw < -180)
- flYaw = flYaw + 360;
- if (flYaw > 180)
- flYaw = flYaw - 360;
-
- if (flYaw > 120)
- {
- m_pPlayerInfo->gaityaw = m_pPlayerInfo->gaityaw - 180;
- m_flGaitMovement = -m_flGaitMovement;
- flYaw = flYaw - 180;
- }
- else if (flYaw < -120)
- {
- m_pPlayerInfo->gaityaw = m_pPlayerInfo->gaityaw + 180;
- m_flGaitMovement = -m_flGaitMovement;
- flYaw = flYaw + 180;
- }
-
- // adjust torso
- m_pCurrentEntity->curstate.controller[0] = ((flYaw / 4.0) + 30) / (60.0 / 255.0);
- m_pCurrentEntity->curstate.controller[1] = ((flYaw / 4.0) + 30) / (60.0 / 255.0);
- m_pCurrentEntity->curstate.controller[2] = ((flYaw / 4.0) + 30) / (60.0 / 255.0);
- m_pCurrentEntity->curstate.controller[3] = ((flYaw / 4.0) + 30) / (60.0 / 255.0);
- m_pCurrentEntity->latched.prevcontroller[0] = m_pCurrentEntity->curstate.controller[0];
- m_pCurrentEntity->latched.prevcontroller[1] = m_pCurrentEntity->curstate.controller[1];
- m_pCurrentEntity->latched.prevcontroller[2] = m_pCurrentEntity->curstate.controller[2];
- m_pCurrentEntity->latched.prevcontroller[3] = m_pCurrentEntity->curstate.controller[3];
-
- m_pCurrentEntity->angles[YAW] = m_pPlayerInfo->gaityaw;
- if (m_pCurrentEntity->angles[YAW] < -0)
- m_pCurrentEntity->angles[YAW] += 360;
- m_pCurrentEntity->latched.prevangles[YAW] = m_pCurrentEntity->angles[YAW];
-
- pplayer->gaitsequence = max(min(pplayer->gaitsequence, m_pStudioHeader->numseq-1), 0);
-
- pseqdesc = (mstudioseqdesc_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqindex) + pplayer->gaitsequence;
-
- // calc gait frame
- if (pseqdesc->linearmovement[0] > 0)
- {
- m_pPlayerInfo->gaitframe += (m_flGaitMovement / pseqdesc->linearmovement[0]) * pseqdesc->numframes;
- }
- else
- {
- m_pPlayerInfo->gaitframe += pseqdesc->fps * dt;
- }
-
- // do modulo
- m_pPlayerInfo->gaitframe = m_pPlayerInfo->gaitframe - (int)(m_pPlayerInfo->gaitframe / pseqdesc->numframes) * pseqdesc->numframes;
- if (m_pPlayerInfo->gaitframe < 0)
- m_pPlayerInfo->gaitframe += pseqdesc->numframes;
-}
-
-/*
-====================
-StudioDrawPlayer
-
-====================
-*/
-int CStudioModelRenderer::StudioDrawPlayer( int flags, entity_state_t *pplayer )
-{
- alight_t lighting;
- vec3_t dir;
-
- m_pCurrentEntity = IEngineStudio.GetCurrentEntity();
- IEngineStudio.GetTimes( &m_nFrameCount, &m_clTime, &m_clOldTime );
- IEngineStudio.GetViewInfo( m_vRenderOrigin, m_vUp, m_vRight, m_vNormal );
- IEngineStudio.GetAliasScale( &m_fSoftwareXScale, &m_fSoftwareYScale );
-
- // Horrible hack for preventing visual artifacts while being digested
- if(gHUD.GetIsBeingDigested())
- {
- return 0;
- }
-
- // Con_DPrintf("DrawPlayer %d\n", m_pCurrentEntity->blending[0] );
-
- // Con_DPrintf("DrawPlayer %d %d (%d)\n", m_nFrameCount, pplayer->player_index, m_pCurrentEntity->curstate.sequence );
-
- // Con_DPrintf("Player %.2f %.2f %.2f\n", pplayer->velocity[0], pplayer->velocity[1], pplayer->velocity[2] );
-
- m_nPlayerIndex = pplayer->number - 1;
-
- if (m_nPlayerIndex < 0 || m_nPlayerIndex >= gEngfuncs.GetMaxClients())
- return 0;
-
- //m_pRenderModel = IEngineStudio.SetupPlayerModel( m_nPlayerIndex );
- m_pRenderModel = m_pCurrentEntity->model;
- if (m_pRenderModel == NULL)
- return 0;
-
- m_pStudioHeader = (studiohdr_t *)IEngineStudio.Mod_Extradata (m_pRenderModel);
- IEngineStudio.StudioSetHeader( m_pStudioHeader );
- IEngineStudio.SetRenderModel( m_pRenderModel );
-
- if (pplayer->gaitsequence)
- {
- vec3_t orig_angles;
- m_pPlayerInfo = IEngineStudio.PlayerInfo( m_nPlayerIndex );
-
- VectorCopy( m_pCurrentEntity->angles, orig_angles );
-
- StudioProcessGait( pplayer );
-
- m_pPlayerInfo->gaitsequence = pplayer->gaitsequence;
- m_pPlayerInfo = NULL;
-
- StudioSetUpTransform( 0 );
- VectorCopy( orig_angles, m_pCurrentEntity->angles );
- }
- else
- {
- m_pCurrentEntity->curstate.controller[0] = 127;
- m_pCurrentEntity->curstate.controller[1] = 127;
- m_pCurrentEntity->curstate.controller[2] = 127;
- m_pCurrentEntity->curstate.controller[3] = 127;
- m_pCurrentEntity->latched.prevcontroller[0] = m_pCurrentEntity->curstate.controller[0];
- m_pCurrentEntity->latched.prevcontroller[1] = m_pCurrentEntity->curstate.controller[1];
- m_pCurrentEntity->latched.prevcontroller[2] = m_pCurrentEntity->curstate.controller[2];
- m_pCurrentEntity->latched.prevcontroller[3] = m_pCurrentEntity->curstate.controller[3];
-
- m_pPlayerInfo = IEngineStudio.PlayerInfo( m_nPlayerIndex );
- m_pPlayerInfo->gaitsequence = 0;
-
- StudioSetUpTransform( 0 );
- }
-
- if (flags & STUDIO_RENDER)
- {
- // see if the bounding box lets us trivially reject, also sets
- if (!IEngineStudio.StudioCheckBBox ())
- return 0;
-
- (*m_pModelsDrawn)++;
- (*m_pStudioModelCount)++; // render data cache cookie
-
- if (m_pStudioHeader->numbodyparts == 0)
- return 1;
- }
-
- m_pPlayerInfo = IEngineStudio.PlayerInfo( m_nPlayerIndex );
- StudioSetupBones( );
- StudioSaveBones( );
- m_pPlayerInfo->renderframe = m_nFrameCount;
-
- m_pPlayerInfo = NULL;
-
- if (flags & STUDIO_EVENTS)
- {
- StudioCalcAttachments( );
- IEngineStudio.StudioClientEvents( );
- // copy attachments into global entity array
- if ( m_pCurrentEntity->index > 0 )
- {
- cl_entity_t *ent = gEngfuncs.GetEntityByIndex( m_pCurrentEntity->index );
-
- memcpy( ent->attachment, m_pCurrentEntity->attachment, sizeof( vec3_t ) * 4 );
- }
- }
-
- if (flags & STUDIO_RENDER)
- {
- /*
- if (m_pCvarHiModels->value && m_pRenderModel != m_pCurrentEntity->model )
- {
- // show highest resolution multiplayer model
- m_pCurrentEntity->curstate.body = 255;
- }
- */
-
- lighting.plightvec = dir;
- IEngineStudio.StudioDynamicLight(m_pCurrentEntity, &lighting );
-
- IEngineStudio.StudioEntityLight( &lighting );
-
- // model and frame independant
- IEngineStudio.StudioSetupLighting (&lighting);
-
- m_pPlayerInfo = IEngineStudio.PlayerInfo( m_nPlayerIndex );
-
- // get remap colors
- m_nTopColor = m_pPlayerInfo->topcolor;
- m_nBottomColor = m_pPlayerInfo->bottomcolor;
- if (m_nTopColor < 0)
- m_nTopColor = 0;
- if (m_nTopColor > 360)
- m_nTopColor = 360;
- if (m_nBottomColor < 0)
- m_nBottomColor = 0;
- if (m_nBottomColor > 360)
- m_nBottomColor = 360;
-
- IEngineStudio.StudioSetRemapColors( m_nTopColor, m_nBottomColor );
-
- StudioRenderModel( );
- m_pPlayerInfo = NULL;
-
- if (pplayer->weaponmodel)
- {
- cl_entity_t saveent = *m_pCurrentEntity;
-
- model_t *pweaponmodel = IEngineStudio.GetModelByIndex( pplayer->weaponmodel );
-
- m_pStudioHeader = (studiohdr_t *)IEngineStudio.Mod_Extradata (pweaponmodel);
- IEngineStudio.StudioSetHeader( m_pStudioHeader );
-
- StudioMergeBones( pweaponmodel);
-
- IEngineStudio.StudioSetupLighting (&lighting);
-
- StudioRenderModel( );
-
- StudioCalcAttachments( );
-
- *m_pCurrentEntity = saveent;
- }
- }
-
- return 1;
-}
-
-/*
-====================
-StudioCalcAttachments
-
-====================
-*/
-void CStudioModelRenderer::StudioCalcAttachments( void )
-{
- int i;
- mstudioattachment_t *pattachment;
-
- if ( m_pStudioHeader->numattachments > 4 )
- {
- gEngfuncs.Con_DPrintf( "Too many attachments on %s\n", m_pCurrentEntity->model->name );
- exit( -1 );
- }
-
- // calculate attachment points
- pattachment = (mstudioattachment_t *)((byte *)m_pStudioHeader + m_pStudioHeader->attachmentindex);
- for (i = 0; i < m_pStudioHeader->numattachments; i++)
- {
- VectorTransform( pattachment[i].org, (*m_plighttransform)[pattachment[i].bone], m_pCurrentEntity->attachment[i] );
- }
-}
-
-/*
-====================
-StudioRenderModel
-
-====================
-*/
-void CStudioModelRenderer::StudioRenderModel( void )
-{
- IEngineStudio.SetChromeOrigin();
- IEngineStudio.SetForceFaceFlags( 0 );
-
- if ( m_pCurrentEntity->curstate.renderfx == kRenderFxGlowShell )
- {
- m_pCurrentEntity->curstate.renderfx = kRenderFxNone;
- StudioRenderFinal( );
-
- if ( !IEngineStudio.IsHardware() )
- {
- gEngfuncs.pTriAPI->RenderMode( kRenderTransAdd );
- }
-
- IEngineStudio.SetForceFaceFlags( STUDIO_NF_CHROME );
-
- gEngfuncs.pTriAPI->SpriteTexture( m_pChromeSprite, 0 );
- m_pCurrentEntity->curstate.renderfx = kRenderFxGlowShell;
-
- StudioRenderFinal( );
- if ( !IEngineStudio.IsHardware() )
- {
- gEngfuncs.pTriAPI->RenderMode( kRenderNormal );
- }
- }
- else
- {
- StudioRenderFinal( );
- }
-}
-
-/*
-====================
-StudioRenderFinal_Software
-
-====================
-*/
-void CStudioModelRenderer::StudioRenderFinal_Software( void )
-{
- int i;
-
- // Note, rendermode set here has effect in SW
- IEngineStudio.SetupRenderer( 0 );
-
- // Put this in here?
- //int theRenderMode = GetRenderModeForModelName(rendermode, m_pSubModel[i].name);
-
- if (m_pCvarDrawEntities->value == 2)
- {
- IEngineStudio.StudioDrawBones( );
- }
- else if (m_pCvarDrawEntities->value == 3)
- {
- IEngineStudio.StudioDrawHulls( );
- }
- else
- {
- for (i=0 ; i < m_pStudioHeader->numbodyparts ; i++)
- {
- IEngineStudio.StudioSetupModel( i, (void **)&m_pBodyPart, (void **)&m_pSubModel );
- IEngineStudio.StudioDrawPoints( );
- }
- }
-
- if (m_pCvarDrawEntities->value == 4)
- {
- gEngfuncs.pTriAPI->RenderMode( kRenderTransAdd );
- IEngineStudio.StudioDrawHulls( );
- gEngfuncs.pTriAPI->RenderMode( kRenderNormal );
- }
-
- if (m_pCvarDrawEntities->value == 5)
- {
- IEngineStudio.StudioDrawAbsBBox( );
- }
-
- IEngineStudio.RestoreRenderer();
-}
-
-/*
-====================
-StudioRenderFinal_Hardware
-
- ====================
-*/
-void CStudioModelRenderer::StudioRenderFinal_Hardware( void )
-{
- int i;
- int rendermode;
-
- rendermode = IEngineStudio.GetForceFaceFlags() ? kRenderTransAdd : m_pCurrentEntity->curstate.rendermode;
- IEngineStudio.SetupRenderer( rendermode );
-
- if (m_pCvarDrawEntities->value == 2)
- {
- IEngineStudio.StudioDrawBones();
- }
- else if (m_pCvarDrawEntities->value == 3)
- {
- IEngineStudio.StudioDrawHulls();
- }
- else
- {
- for (i=0 ; i < m_pStudioHeader->numbodyparts ; i++)
- {
- IEngineStudio.StudioSetupModel( i, (void **)&m_pBodyPart, (void **)&m_pSubModel );
-
- if (m_fDoInterp)
- {
- // interpolation messes up bounding boxes.
- m_pCurrentEntity->trivial_accept = 0;
- }
-
- IEngineStudio.GL_SetRenderMode(rendermode);
-
-// mstudiobodyparts_t* pbodypart = (mstudiobodyparts_t *)((byte *)m_pStudioHeader + m_pStudioHeader->bodypartindex) + i;
-//
-// //int index = m_bodynum / pbodypart->base;
-// //index = index % pbodypart->nummodels;
-//
-// mstudiomodel_t* theModel = (mstudiomodel_t *)((byte *)m_pStudioHeader + pbodypart->modelindex);// + index;
-// ASSERT(theModel);
-//
-// int theModelRenderMode = rendermode;//GetRenderModeForModelName(rendermode, theModel->name);
-//
-// // This could be dangerous...how to find out?
-// //IEngineStudio.SetupRenderer( theModelRenderMode );
-//
-// IEngineStudio.GL_SetRenderMode( theModelRenderMode );
-
- IEngineStudio.StudioDrawPoints();
- IEngineStudio.GL_StudioDrawShadow();
- }
- }
-
- if ( m_pCvarDrawEntities->value == 4 )
- {
- gEngfuncs.pTriAPI->RenderMode( kRenderTransAdd );
- IEngineStudio.StudioDrawHulls( );
- gEngfuncs.pTriAPI->RenderMode( kRenderNormal );
- }
-
- if (m_pCvarDrawEntities->value == 5)
- {
- IEngineStudio.StudioDrawAbsBBox( );
- }
-
- IEngineStudio.RestoreRenderer();
-}
-
-/*
-====================
-StudioRenderFinal
-
-====================
-*/
-void CStudioModelRenderer::StudioRenderFinal(void)
-{
- if ( IEngineStudio.IsHardware() )
- {
- StudioRenderFinal_Hardware();
- }
- else
- {
- StudioRenderFinal_Software();
- }
-}
-
+ }
+
+ paSequences = (cache_user_t *)m_pSubModel->submodels;
+
+ if (paSequences == NULL)
+ {
+ paSequences = (cache_user_t *)IEngineStudio.Mem_Calloc( 16, sizeof( cache_user_t ) ); // UNDONE: leak!
+ m_pSubModel->submodels = (dmodel_t *)paSequences;
+ }
+
+ if (!IEngineStudio.Cache_Check( (struct cache_user_s *)&(paSequences[pseqdesc->seqgroup])))
+ {
+ gEngfuncs.Con_DPrintf("loading %s\n", pseqgroup->name );
+ IEngineStudio.LoadCacheFile( pseqgroup->name, (struct cache_user_s *)&paSequences[pseqdesc->seqgroup] );
+ }
+ return (mstudioanim_t *)((byte *)paSequences[pseqdesc->seqgroup].data + pseqdesc->animindex);
+}
+
+/*
+====================
+StudioPlayerBlend
+
+====================
+*/
+void CStudioModelRenderer::StudioPlayerBlend( mstudioseqdesc_t *pseqdesc, int *pBlend, float *pPitch )
+{
+ // calc up/down pointing
+ *pBlend = (*pPitch * 3);
+ if (*pBlend < pseqdesc->blendstart[0])
+ {
+ *pPitch -= pseqdesc->blendstart[0] / 3.0;
+ *pBlend = 0;
+ }
+ else if (*pBlend > pseqdesc->blendend[0])
+ {
+ *pPitch -= pseqdesc->blendend[0] / 3.0;
+ *pBlend = 255;
+ }
+ else
+ {
+ if (pseqdesc->blendend[0] - pseqdesc->blendstart[0] < 0.1) // catch qc error
+ *pBlend = 127;
+ else
+ *pBlend = 255 * (*pBlend - pseqdesc->blendstart[0]) / (pseqdesc->blendend[0] - pseqdesc->blendstart[0]);
+ *pPitch = 0;
+ }
+}
+
+/*
+====================
+StudioSetUpTransform
+
+====================
+*/
+void CStudioModelRenderer::StudioSetUpTransform (int trivial_accept)
+{
+ int i;
+ vec3_t angles;
+ vec3_t modelpos;
+
+// tweek model origin
+ //for (i = 0; i < 3; i++)
+ // modelpos[i] = m_pCurrentEntity->origin[i];
+
+ VectorCopy( m_pCurrentEntity->origin, modelpos );
+
+// TODO: should really be stored with the entity instead of being reconstructed
+// TODO: should use a look-up table
+// TODO: could cache lazily, stored in the entity
+ angles[ROLL] = m_pCurrentEntity->curstate.angles[ROLL];
+ angles[PITCH] = m_pCurrentEntity->curstate.angles[PITCH];
+ angles[YAW] = m_pCurrentEntity->curstate.angles[YAW];
+
+ //Con_DPrintf("Angles %4.2f prev %4.2f for %i\n", angles[PITCH], m_pCurrentEntity->index);
+ //Con_DPrintf("movetype %d %d\n", m_pCurrentEntity->movetype, m_pCurrentEntity->aiment );
+ if (m_pCurrentEntity->curstate.movetype == MOVETYPE_STEP)
+ {
+ float f = 0;
+ float d;
+
+ // don't do it if the goalstarttime hasn't updated in a while.
+
+ // NOTE: Because we need to interpolate multiplayer characters, the interpolation time limit
+ // was increased to 1.0 s., which is 2x the max lag we are accounting for.
+
+ if ( ( m_clTime < m_pCurrentEntity->curstate.animtime + 1.0f ) &&
+ ( m_pCurrentEntity->curstate.animtime != m_pCurrentEntity->latched.prevanimtime ) )
+ {
+ f = (m_clTime - m_pCurrentEntity->curstate.animtime) / (m_pCurrentEntity->curstate.animtime - m_pCurrentEntity->latched.prevanimtime);
+ //Con_DPrintf("%4.2f %.2f %.2f\n", f, m_pCurrentEntity->curstate.animtime, m_clTime);
+ }
+
+ if (m_fDoInterp)
+ {
+ // ugly hack to interpolate angle, position. current is reached 0.1 seconds after being set
+ f = f - 1.0;
+ }
+ else
+ {
+ f = 0;
+ }
+
+ for (i = 0; i < 3; i++)
+ {
+ modelpos[i] += (m_pCurrentEntity->origin[i] - m_pCurrentEntity->latched.prevorigin[i]) * f;
+ }
+
+ // NOTE: Because multiplayer lag can be relatively large, we don't want to cap
+ // f at 1.5 anymore.
+ //if (f > -1.0 && f < 1.5) {}
+
+// Con_DPrintf("%.0f %.0f\n",m_pCurrentEntity->msg_angles[0][YAW], m_pCurrentEntity->msg_angles[1][YAW] );
+ for (i = 0; i < 3; i++)
+ {
+ float ang1, ang2;
+
+ ang1 = m_pCurrentEntity->angles[i];
+ ang2 = m_pCurrentEntity->latched.prevangles[i];
+
+ d = ang1 - ang2;
+ if (d > 180)
+ {
+ d -= 360;
+ }
+ else if (d < -180)
+ {
+ d += 360;
+ }
+
+ angles[i] += d * f;
+ }
+ //Con_DPrintf("%.3f \n", f );
+ }
+ else if ( m_pCurrentEntity->curstate.movetype != MOVETYPE_NONE )
+ {
+ VectorCopy( m_pCurrentEntity->angles, angles );
+ }
+
+ // Added by mmcguire.
+
+ if (m_pCurrentEntity->curstate.iuser3 == AVH_USER3_ALIEN_PLAYER1)
+ {
+
+ // Override the orientation with the values stored in vuser1.
+
+ VectorCopy(m_pCurrentEntity->curstate.vuser1, angles);
+
+ // The code that sets up the transformation negates the pitch
+ // for some reason, so compensate for that here.
+
+ angles[PITCH] = -angles[PITCH];
+
+ }
+
+
+// bool theIsWallSticking = GetHasUpgrade(m_pCurrentEntity->curstate.iuser4, MASK_WALLSTICKING);
+// if(theIsWallSticking)
+// {
+// //RotateFloatValuesByVector(angles[ROLL], angles[YAW], angles[PITCH], m_pCurrentEntity->curstate.vuser1);
+// //VectorCopy(m_pCurrentEntity->curstate.vuser1, angles);
+//
+// // Surface normal is in vuser1. Transform current forward to new forward
+// vec3_t theCurrentForward;
+// vec3_t theCurrentRight;
+// vec3_t theCurrentUp;
+// gEngfuncs.pfnAngleVectors(angles, theCurrentForward, theCurrentRight, theCurrentUp);
+//
+// vec3_t theWallUp = m_pCurrentEntity->curstate.vuser1;
+//
+// vec3_t theWallSide;
+// CrossProduct(theWallUp, theCurrentForward, theWallSide);
+//
+// vec3_t theWallForward;
+// //CrossProduct(theWallUp, theWallSide, theWallForward);
+// VectorCopy(theCurrentForward, theWallForward);
+//
+// // Build matrix to transform current frame of reference to that of sticking to wall
+// float theViewToWallMatrix[3][4];
+// theViewToWallMatrix[0][0] = theWallForward.x;
+// theViewToWallMatrix[0][1] = theWallForward.y;
+// theViewToWallMatrix[0][2] = theWallForward.z;
+//
+// theViewToWallMatrix[1][0] = theWallSide.x;
+// theViewToWallMatrix[1][1] = theWallSide.y;
+// theViewToWallMatrix[1][2] = theWallSide.z;
+//
+// theViewToWallMatrix[2][0] = theWallUp.x;
+// theViewToWallMatrix[2][1] = theWallUp.y;
+// theViewToWallMatrix[2][2] = theWallUp.z;
+//
+// vec3_t theNewForward;
+// VectorTransform(theCurrentForward, theViewToWallMatrix, theNewForward);
+//
+// // Transform new forward to angles
+// VectorAngles(theNewForward, angles);
+// }
+
+ //Con_DPrintf("%.0f %0.f %0.f\n", modelpos[0], modelpos[1], modelpos[2] );
+ //Con_DPrintf("%.0f %0.f %0.f\n", angles[0], angles[1], angles[2] );
+
+ angles[PITCH] = -angles[PITCH];
+ AngleMatrix (angles, (*m_protationmatrix));
+
+ if ( !IEngineStudio.IsHardware() )
+ {
+ static float viewmatrix[3][4];
+
+ VectorCopy (m_vRight, viewmatrix[0]);
+ VectorCopy (m_vUp, viewmatrix[1]);
+ VectorInverse (viewmatrix[1]);
+ VectorCopy (m_vNormal, viewmatrix[2]);
+
+ (*m_protationmatrix)[0][3] = modelpos[0] - m_vRenderOrigin[0];
+ (*m_protationmatrix)[1][3] = modelpos[1] - m_vRenderOrigin[1];
+ (*m_protationmatrix)[2][3] = modelpos[2] - m_vRenderOrigin[2];
+
+ ConcatTransforms (viewmatrix, (*m_protationmatrix), (*m_paliastransform));
+
+ // do the scaling up of x and y to screen coordinates as part of the transform
+ // for the unclipped case (it would mess up clipping in the clipped case).
+ // Also scale down z, so 1/z is scaled 31 bits for free, and scale down x and y
+ // correspondingly so the projected x and y come out right
+ // FIXME: make this work for clipped case too?
+ if (trivial_accept)
+ {
+ for (i=0 ; i<4 ; i++)
+ {
+ (*m_paliastransform)[0][i] *= m_fSoftwareXScale *
+ (1.0 / (ZISCALE * 0x10000));
+ (*m_paliastransform)[1][i] *= m_fSoftwareYScale *
+ (1.0 / (ZISCALE * 0x10000));
+ (*m_paliastransform)[2][i] *= 1.0 / (ZISCALE * 0x10000);
+
+ }
+ }
+ }
+
+ (*m_protationmatrix)[0][3] = modelpos[0];
+ (*m_protationmatrix)[1][3] = modelpos[1];
+ (*m_protationmatrix)[2][3] = modelpos[2];
+}
+
+
+/*
+====================
+StudioEstimateInterpolant
+
+====================
+*/
+float CStudioModelRenderer::StudioEstimateInterpolant( void )
+{
+ float dadt = 1.0;
+
+ if ( m_fDoInterp && ( m_pCurrentEntity->curstate.animtime >= m_pCurrentEntity->latched.prevanimtime + 0.01 ) )
+ {
+ dadt = (m_clTime - m_pCurrentEntity->curstate.animtime) / 0.1;
+ if (dadt > 2.0)
+ {
+ dadt = 2.0;
+ }
+ }
+ return dadt;
+}
+
+/*
+====================
+StudioCalcRotations
+
+====================
+*/
+void CStudioModelRenderer::StudioCalcRotations ( float pos[][3], vec4_t *q, mstudioseqdesc_t *pseqdesc, mstudioanim_t *panim, float f )
+{
+ int i;
+ int frame;
+ mstudiobone_t *pbone;
+
+ float s;
+ float adj[MAXSTUDIOCONTROLLERS];
+ float dadt;
+
+ if (f > pseqdesc->numframes - 1)
+ {
+ f = 0; // bah, fix this bug with changing sequences too fast
+ }
+ // BUG ( somewhere else ) but this code should validate this data.
+ // This could cause a crash if the frame # is negative, so we'll go ahead
+ // and clamp it here
+ else if ( f < -0.01 )
+ {
+ f = -0.01;
+ }
+
+ frame = (int)f;
+
+ //gEngfuncs.Con_DPrintf("%d %.4f %.4f %.4f %.4f %d\n", m_pCurrentEntity->curstate.sequence, m_clTime, m_pCurrentEntity->animtime, m_pCurrentEntity->frame, f, frame );
+
+ // gEngfuncs.Con_DPrintf( "%f %f %f\n", m_pCurrentEntity->angles[ROLL], m_pCurrentEntity->angles[PITCH], m_pCurrentEntity->angles[YAW] );
+
+ //gEngfuncs.Con_DPrintf("frame %d %d\n", frame1, frame2 );
+
+
+ dadt = StudioEstimateInterpolant( );
+ s = (f - frame);
+
+ // add in programtic controllers
+ pbone = (mstudiobone_t *)((byte *)m_pStudioHeader + m_pStudioHeader->boneindex);
+
+ StudioCalcBoneAdj( dadt, adj, m_pCurrentEntity->curstate.controller, m_pCurrentEntity->latched.prevcontroller, m_pCurrentEntity->mouth.mouthopen );
+
+ for (i = 0; i < m_pStudioHeader->numbones; i++, pbone++, panim++)
+ {
+ StudioCalcBoneQuaterion( frame, s, pbone, panim, adj, q[i] );
+
+ StudioCalcBonePosition( frame, s, pbone, panim, adj, pos[i] );
+ // if (0 && i == 0)
+ // Con_DPrintf("%d %d %d %d\n", m_pCurrentEntity->curstate.sequence, frame, j, k );
+ }
+
+ if (pseqdesc->motiontype & STUDIO_X)
+ {
+ pos[pseqdesc->motionbone][0] = 0.0;
+ }
+ if (pseqdesc->motiontype & STUDIO_Y)
+ {
+ pos[pseqdesc->motionbone][1] = 0.0;
+ }
+ if (pseqdesc->motiontype & STUDIO_Z)
+ {
+ pos[pseqdesc->motionbone][2] = 0.0;
+ }
+
+ //gEngfuncs.Con_Printf("framerate %f\n", m_pCurrentEntity->curstate.framerate);
+
+ s = 0 * ((1.0 - (f - (int)(f))) / (pseqdesc->numframes)) * m_pCurrentEntity->curstate.framerate;
+
+ if (pseqdesc->motiontype & STUDIO_LX)
+ {
+ pos[pseqdesc->motionbone][0] += s * pseqdesc->linearmovement[0];
+ }
+ if (pseqdesc->motiontype & STUDIO_LY)
+ {
+ pos[pseqdesc->motionbone][1] += s * pseqdesc->linearmovement[1];
+ }
+ if (pseqdesc->motiontype & STUDIO_LZ)
+ {
+ pos[pseqdesc->motionbone][2] += s * pseqdesc->linearmovement[2];
+ }
+}
+
+/*
+====================
+Studio_FxTransform
+
+====================
+*/
+void CStudioModelRenderer::StudioFxTransform( cl_entity_t *ent, float transform[3][4] )
+{
+ switch( ent->curstate.renderfx )
+ {
+ case kRenderFxDistort:
+ case kRenderFxHologram:
+ if ( gEngfuncs.pfnRandomLong(0,49) == 0 )
+ {
+ int axis = gEngfuncs.pfnRandomLong(0,1);
+ if ( axis == 1 ) // Choose between x & z
+ axis = 2;
+ VectorScale( transform[axis], gEngfuncs.pfnRandomFloat(1,1.484), transform[axis] );
+ }
+ else if ( gEngfuncs.pfnRandomLong(0,49) == 0 )
+ {
+ float offset;
+ int axis = gEngfuncs.pfnRandomLong(0,1);
+ if ( axis == 1 ) // Choose between x & z
+ axis = 2;
+ offset = gEngfuncs.pfnRandomFloat(-10,10);
+ transform[gEngfuncs.pfnRandomLong(0,2)][3] += offset;
+ }
+ break;
+ case kRenderFxExplode:
+ {
+ float scale;
+
+ scale = 1.0 + ( m_clTime - ent->curstate.animtime) * 10.0;
+ if ( scale > 2 ) // Don't blow up more than 200%
+ scale = 2;
+ transform[0][1] *= scale;
+ transform[1][1] *= scale;
+ transform[2][1] *= scale;
+ }
+ break;
+
+ }
+}
+
+/*
+====================
+StudioEstimateFrame
+
+====================
+*/
+float CStudioModelRenderer::StudioEstimateFrame( mstudioseqdesc_t *pseqdesc )
+{
+ double dfdt, f;
+
+ if ( m_fDoInterp )
+ {
+ if ( m_clTime < m_pCurrentEntity->curstate.animtime )
+ {
+ dfdt = 0;
+ }
+ else
+ {
+ dfdt = (m_clTime - m_pCurrentEntity->curstate.animtime) * m_pCurrentEntity->curstate.framerate * pseqdesc->fps;
+
+ }
+ }
+ else
+ {
+ dfdt = 0;
+ }
+
+ if (pseqdesc->numframes <= 1)
+ {
+ f = 0;
+ }
+ else
+ {
+ f = (m_pCurrentEntity->curstate.frame * (pseqdesc->numframes - 1)) / 256.0;
+ }
+
+ f += dfdt;
+
+ if (pseqdesc->flags & STUDIO_LOOPING)
+ {
+ if (pseqdesc->numframes > 1)
+ {
+ f -= (int)(f / (pseqdesc->numframes - 1)) * (pseqdesc->numframes - 1);
+ }
+ if (f < 0)
+ {
+ f += (pseqdesc->numframes - 1);
+ }
+ }
+ else
+ {
+ if (f >= pseqdesc->numframes - 1.001)
+ {
+ f = pseqdesc->numframes - 1.001;
+ }
+ if (f < 0.0)
+ {
+ f = 0.0;
+ }
+ }
+ return f;
+}
+
+bool GetDoesBoneHaveParent(int inMaybeBeneathBone, int inParentBone, mstudiobone_t* inBones)
+{
+ bool theSuccess = false;
+
+ ASSERT(inMaybeBeneathBone < MAXSTUDIOBONES);
+ ASSERT(inParentBone < MAXSTUDIOBONES);
+
+ int theCurrentParent = inBones[inMaybeBeneathBone].parent;
+
+ if(theCurrentParent == inParentBone)
+ {
+ theSuccess = true;
+ }
+ else if(theCurrentParent != -1)
+ {
+ theSuccess = GetDoesBoneHaveParent(theCurrentParent, inParentBone, inBones);
+ }
+
+ return theSuccess;
+}
+
+/*
+====================
+StudioSetupBones
+
+====================
+*/
+void CStudioModelRenderer::StudioSetupBones ( void )
+{
+ int i;
+ double f;
+
+ mstudiobone_t *pbones;
+ mstudioseqdesc_t *pseqdesc;
+ mstudioanim_t *panim;
+
+ static float pos[MAXSTUDIOBONES][3];
+ static vec4_t q[MAXSTUDIOBONES];
+ float bonematrix[3][4];
+
+ static float pos2[MAXSTUDIOBONES][3];
+ static vec4_t q2[MAXSTUDIOBONES];
+ static float pos3[MAXSTUDIOBONES][3];
+ static vec4_t q3[MAXSTUDIOBONES];
+ static float pos4[MAXSTUDIOBONES][3];
+ static vec4_t q4[MAXSTUDIOBONES];
+
+ if (m_pCurrentEntity->curstate.sequence >= m_pStudioHeader->numseq)
+ {
+ m_pCurrentEntity->curstate.sequence = 0;
+ }
+ else if (m_pCurrentEntity->curstate.sequence < 0)
+ {
+ m_pCurrentEntity->curstate.sequence = 0;
+ }
+
+ pseqdesc = (mstudioseqdesc_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqindex) + m_pCurrentEntity->curstate.sequence;
+
+ f = StudioEstimateFrame( pseqdesc );
+
+ if (m_pCurrentEntity->latched.prevframe > f)
+ {
+ //Con_DPrintf("%f %f\n", m_pCurrentEntity->prevframe, f );
+ }
+
+ panim = StudioGetAnim( m_pRenderModel, pseqdesc );
+ StudioCalcRotations( pos, q, pseqdesc, panim, f );
+
+ if (pseqdesc->numblends > 1)
+ {
+ float s;
+ float dadt;
+
+ panim += m_pStudioHeader->numbones;
+ StudioCalcRotations( pos2, q2, pseqdesc, panim, f );
+
+ dadt = StudioEstimateInterpolant();
+ s = (m_pCurrentEntity->curstate.blending[0] * dadt + m_pCurrentEntity->latched.prevblending[0] * (1.0 - dadt)) / 255.0;
+
+ StudioSlerpBones( q, pos, q2, pos2, s );
+
+ if (pseqdesc->numblends == 4)
+ {
+ panim += m_pStudioHeader->numbones;
+ StudioCalcRotations( pos3, q3, pseqdesc, panim, f );
+
+ panim += m_pStudioHeader->numbones;
+ StudioCalcRotations( pos4, q4, pseqdesc, panim, f );
+
+ s = (m_pCurrentEntity->curstate.blending[0] * dadt + m_pCurrentEntity->latched.prevblending[0] * (1.0 - dadt)) / 255.0;
+ StudioSlerpBones( q3, pos3, q4, pos4, s );
+
+ s = (m_pCurrentEntity->curstate.blending[1] * dadt + m_pCurrentEntity->latched.prevblending[1] * (1.0 - dadt)) / 255.0;
+ StudioSlerpBones( q, pos, q3, pos3, s );
+ }
+ }
+
+ if (m_fDoInterp &&
+ m_pCurrentEntity->latched.sequencetime &&
+ ( m_pCurrentEntity->latched.sequencetime + 0.2 > m_clTime ) &&
+ ( m_pCurrentEntity->latched.prevsequence < m_pStudioHeader->numseq ))
+ {
+ // blend from last sequence
+ static float pos1b[MAXSTUDIOBONES][3];
+ static vec4_t q1b[MAXSTUDIOBONES];
+ float s;
+
+ pseqdesc = (mstudioseqdesc_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqindex) + m_pCurrentEntity->latched.prevsequence;
+ panim = StudioGetAnim( m_pRenderModel, pseqdesc );
+ // clip prevframe
+ StudioCalcRotations( pos1b, q1b, pseqdesc, panim, m_pCurrentEntity->latched.prevframe );
+
+ if (pseqdesc->numblends > 1)
+ {
+ panim += m_pStudioHeader->numbones;
+ StudioCalcRotations( pos2, q2, pseqdesc, panim, m_pCurrentEntity->latched.prevframe );
+
+ s = (m_pCurrentEntity->latched.prevseqblending[0]) / 255.0;
+ StudioSlerpBones( q1b, pos1b, q2, pos2, s );
+
+ if (pseqdesc->numblends == 4)
+ {
+ panim += m_pStudioHeader->numbones;
+ StudioCalcRotations( pos3, q3, pseqdesc, panim, m_pCurrentEntity->latched.prevframe );
+
+ panim += m_pStudioHeader->numbones;
+ StudioCalcRotations( pos4, q4, pseqdesc, panim, m_pCurrentEntity->latched.prevframe );
+
+ s = (m_pCurrentEntity->latched.prevseqblending[0]) / 255.0;
+ StudioSlerpBones( q3, pos3, q4, pos4, s );
+
+ s = (m_pCurrentEntity->latched.prevseqblending[1]) / 255.0;
+ StudioSlerpBones( q1b, pos1b, q3, pos3, s );
+ }
+ }
+
+ s = 1.0 - (m_clTime - m_pCurrentEntity->latched.sequencetime) / 0.2;
+ StudioSlerpBones( q, pos, q1b, pos1b, s );
+ }
+ else
+ {
+ //Con_DPrintf("prevframe = %4.2f\n", f);
+ m_pCurrentEntity->latched.prevframe = f;
+ }
+
+ pbones = (mstudiobone_t *)((byte *)m_pStudioHeader + m_pStudioHeader->boneindex);
+
+ // calc gait animation
+ if (m_pPlayerInfo && (m_pPlayerInfo->gaitsequence != 0) && (m_pPlayerInfo->gaitsequence != 255))
+ {
+ m_pPlayerInfo->gaitsequence = max(min(m_pPlayerInfo->gaitsequence, m_pStudioHeader->numseq-1), 0);
+
+// // Trim sequences within range (not sure why this is out of range though)
+// int theIndex = min(max(0, m_pStudioHeader->seqindex), m_pStudioHeader->numseq - 1);
+// if(theIndex != m_pStudioHeader->seqindex)
+// {
+// m_pStudioHeader->seqindex = theIndex;
+// m_pPlayerInfo->gaitsequence = 0;
+// }
+
+ pseqdesc = (mstudioseqdesc_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqindex) + m_pPlayerInfo->gaitsequence;
+
+ panim = StudioGetAnim( m_pRenderModel, pseqdesc );
+ StudioCalcRotations( pos2, q2, pseqdesc, panim, m_pPlayerInfo->gaitframe );
+
+// Valve way
+// for (i = 0; i < m_pStudioHeader->numbones; i++)
+// {
+// if (strcmp( pbones[i].name, "Bip01 Spine") == 0)
+// break;
+// memcpy( pos[i], pos2[i], sizeof( pos[i] ));
+// memcpy( q[i], q2[i], sizeof( q[i] ));
+// }
+
+// NS way
+ // Look up parent bone that defines the boundary for gaitsequence
+ int theNumParents = 0;
+ int theParents[MAXSTUDIOBONES];
+ memset(theParents, -1, sizeof(int)*MAXSTUDIOBONES);
+
+ for (i = 0; i < m_pStudioHeader->numbones; i++)
+ {
+ // Must contain "Thigh"
+ if(strstr(pbones[i].name, "Thigh"))
+ {
+ theParents[theNumParents++] = i;
+ }
+ }
+ // If this is firing, it means a model has a gaitsequence set but doesn't have a bone that defines which bones are used for that gaitsequence
+ //ASSERT(theNumParents > 0);
+
+ // If there aren't any thighs, assume that the old HL way was used
+ if(theNumParents > 0)
+ {
+ int theNumBonesWithThisParent = 0;
+ int theBonesWithParent[MAXSTUDIOBONES];
+
+ // For each bone
+ for(i = 0; i < m_pStudioHeader->numbones; i++)
+ {
+ for(int j = 0; j < theNumParents; j++)
+ {
+ // Does bone have this parent bone?
+ int theParent = theParents[j];
+ //if(/*(i == theParent) ||*/ GetDoesBoneHaveParent(i, theParent, pbones))
+ char* theBoneName = pbones[i].name;
+ if(!strcmp(theBoneName, "Bip01") || (!strcmp(theBoneName, "Bip01 Pelvis")) || (i == theParent) || GetDoesBoneHaveParent(i, theParent, pbones))
+ {
+ // If so, add it to the list and increment num bones
+ theBonesWithParent[theNumBonesWithThisParent++] = i;
+ break;
+ }
+ }
+ }
+
+ for(int j = 0; j < theNumBonesWithThisParent; j++)
+ {
+ int i = theBonesWithParent[j];
+
+ // If the bone is in this list, use that bones data (gaitsequence) instead of the existing data (sequence)
+ memcpy( pos[i], pos2[i], sizeof( pos[i] ));
+ memcpy( q[i], q2[i], sizeof( q[i] ));
+ }
+ }
+ else
+ {
+ for (i = 0; i < m_pStudioHeader->numbones; i++)
+ {
+ if (strcmp( pbones[i].name, "Bip01 Spine") == 0)
+ break;
+ memcpy( pos[i], pos2[i], sizeof( pos[i] ));
+ memcpy( q[i], q2[i], sizeof( q[i] ));
+ }
+ }
+
+ //gEngfuncs.Con_Printf("gait: %d, frame: %f\n", m_pPlayerInfo->gaitsequence, m_pPlayerInfo->gaitframe);
+ }
+
+
+ for (i = 0; i < m_pStudioHeader->numbones; i++)
+ {
+ QuaternionMatrix( q[i], bonematrix );
+
+ bonematrix[0][3] = pos[i][0];
+ bonematrix[1][3] = pos[i][1];
+ bonematrix[2][3] = pos[i][2];
+
+ if (pbones[i].parent == -1)
+ {
+ if ( IEngineStudio.IsHardware() )
+ {
+ ConcatTransforms ((*m_protationmatrix), bonematrix, (*m_pbonetransform)[i]);
+ // MatrixCopy should be faster...
+ //ConcatTransforms ((*m_protationmatrix), bonematrix, (*m_plighttransform)[i]);
+ MatrixCopy( (*m_pbonetransform)[i], (*m_plighttransform)[i] );
+ }
+ else
+ {
+ ConcatTransforms ((*m_paliastransform), bonematrix, (*m_pbonetransform)[i]);
+ ConcatTransforms ((*m_protationmatrix), bonematrix, (*m_plighttransform)[i]);
+ }
+
+ // Apply client-side effects to the transformation matrix
+ StudioFxTransform( m_pCurrentEntity, (*m_pbonetransform)[i] );
+ }
+ else
+ {
+ ConcatTransforms ((*m_pbonetransform)[pbones[i].parent], bonematrix, (*m_pbonetransform)[i]);
+ ConcatTransforms ((*m_plighttransform)[pbones[i].parent], bonematrix, (*m_plighttransform)[i]);
+ }
+ }
+}
+
+
+/*
+====================
+StudioSaveBones
+
+====================
+*/
+void CStudioModelRenderer::StudioSaveBones( void )
+{
+ int i;
+
+ mstudiobone_t *pbones;
+ pbones = (mstudiobone_t *)((byte *)m_pStudioHeader + m_pStudioHeader->boneindex);
+
+ m_nCachedBones = m_pStudioHeader->numbones;
+
+ for (i = 0; i < m_pStudioHeader->numbones; i++)
+ {
+ strcpy( m_nCachedBoneNames[i], pbones[i].name );
+ MatrixCopy( (*m_pbonetransform)[i], m_rgCachedBoneTransform[i] );
+ MatrixCopy( (*m_plighttransform)[i], m_rgCachedLightTransform[i] );
+ }
+}
+
+
+/*
+====================
+StudioMergeBones
+
+====================
+*/
+void CStudioModelRenderer::StudioMergeBones ( model_t *m_pSubModel )
+{
+ int i, j;
+ double f;
+ int do_hunt = true;
+
+ mstudiobone_t *pbones;
+ mstudioseqdesc_t *pseqdesc;
+ mstudioanim_t *panim;
+
+ static float pos[MAXSTUDIOBONES][3];
+ float bonematrix[3][4];
+ static vec4_t q[MAXSTUDIOBONES];
+
+ if (m_pCurrentEntity->curstate.sequence >= m_pStudioHeader->numseq)
+ {
+ m_pCurrentEntity->curstate.sequence = 0;
+ }
+
+ pseqdesc = (mstudioseqdesc_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqindex) + m_pCurrentEntity->curstate.sequence;
+
+ f = StudioEstimateFrame( pseqdesc );
+
+ if (m_pCurrentEntity->latched.prevframe > f)
+ {
+ //Con_DPrintf("%f %f\n", m_pCurrentEntity->prevframe, f );
+ }
+
+ panim = StudioGetAnim( m_pSubModel, pseqdesc );
+ StudioCalcRotations( pos, q, pseqdesc, panim, f );
+
+ pbones = (mstudiobone_t *)((byte *)m_pStudioHeader + m_pStudioHeader->boneindex);
+
+
+ for (i = 0; i < m_pStudioHeader->numbones; i++)
+ {
+ for (j = 0; j < m_nCachedBones; j++)
+ {
+ if (stricmp(pbones[i].name, m_nCachedBoneNames[j]) == 0)
+ {
+ MatrixCopy( m_rgCachedBoneTransform[j], (*m_pbonetransform)[i] );
+ MatrixCopy( m_rgCachedLightTransform[j], (*m_plighttransform)[i] );
+ break;
+ }
+ }
+ if (j >= m_nCachedBones)
+ {
+ QuaternionMatrix( q[i], bonematrix );
+
+ bonematrix[0][3] = pos[i][0];
+ bonematrix[1][3] = pos[i][1];
+ bonematrix[2][3] = pos[i][2];
+
+ if (pbones[i].parent == -1)
+ {
+ if ( IEngineStudio.IsHardware() )
+ {
+ ConcatTransforms ((*m_protationmatrix), bonematrix, (*m_pbonetransform)[i]);
+ // MatrixCopy should be faster...
+ //ConcatTransforms ((*m_protationmatrix), bonematrix, (*m_plighttransform)[i]);
+ MatrixCopy( (*m_pbonetransform)[i], (*m_plighttransform)[i] );
+ }
+ else
+ {
+ ConcatTransforms ((*m_paliastransform), bonematrix, (*m_pbonetransform)[i]);
+ ConcatTransforms ((*m_protationmatrix), bonematrix, (*m_plighttransform)[i]);
+ }
+
+ // Apply client-side effects to the transformation matrix
+ StudioFxTransform( m_pCurrentEntity, (*m_pbonetransform)[i] );
+ }
+ else
+ {
+ ConcatTransforms ((*m_pbonetransform)[pbones[i].parent], bonematrix, (*m_pbonetransform)[i]);
+ ConcatTransforms ((*m_plighttransform)[pbones[i].parent], bonematrix, (*m_plighttransform)[i]);
+ }
+ }
+ }
+}
+
+/*
+====================
+StudioDrawModel
+
+====================
+*/
+int CStudioModelRenderer::StudioDrawModel( int flags )
+{
+ alight_t lighting;
+ vec3_t dir;
+
+ m_pCurrentEntity = IEngineStudio.GetCurrentEntity();
+ IEngineStudio.GetTimes( &m_nFrameCount, &m_clTime, &m_clOldTime );
+ IEngineStudio.GetViewInfo( m_vRenderOrigin, m_vUp, m_vRight, m_vNormal );
+ IEngineStudio.GetAliasScale( &m_fSoftwareXScale, &m_fSoftwareYScale );
+
+ // Horrible hack for preventing visual artifacts while being digested
+ if(gHUD.GetIsBeingDigested())
+ {
+ return 0;
+ }
+
+ /*
+ // Now render eyebeam if model is marine //
+ // If player is a marine
+ if(m_pCurrentEntity->curstate.iuser3 == AVH_USER3_MARINE_PLAYER)
+ {
+ // Get eyepiece attachment
+ vec3_t theEyepieceOrigin;
+ VectorCopy(m_pCurrentEntity->attachment[2], theEyepieceOrigin);
+
+ // Build this line
+
+ // Run a traceline along this line until it hits
+
+ // Get endpoint
+
+ // Draw red additive light along this line
+ //gEngfuncs.pEfxAPI->R_RocketTrail();
+ }
+ */
+
+ if (m_pCurrentEntity->curstate.renderfx == kRenderFxDeadPlayer)
+ {
+ entity_state_t deadplayer;
+
+ int result;
+ int save_interp;
+
+ if (m_pCurrentEntity->curstate.renderamt <= 0 || m_pCurrentEntity->curstate.renderamt > gEngfuncs.GetMaxClients() )
+ return 0;
+
+ // get copy of player
+ deadplayer = *(IEngineStudio.GetPlayerState( m_pCurrentEntity->curstate.renderamt - 1 )); //cl.frames[cl.parsecount & CL_UPDATE_MASK].playerstate[m_pCurrentEntity->curstate.renderamt-1];
+
+ // clear weapon, movement state
+ deadplayer.number = m_pCurrentEntity->curstate.renderamt;
+ deadplayer.weaponmodel = 0;
+ deadplayer.gaitsequence = 0;
+
+ deadplayer.movetype = MOVETYPE_NONE;
+ VectorCopy( m_pCurrentEntity->curstate.angles, deadplayer.angles );
+ VectorCopy( m_pCurrentEntity->curstate.origin, deadplayer.origin );
+
+ save_interp = m_fDoInterp;
+ m_fDoInterp = 0;
+
+ // draw as though it were a player
+ result = StudioDrawPlayer( flags, &deadplayer );
+
+ m_fDoInterp = save_interp;
+ return result;
+ }
+
+ m_pRenderModel = m_pCurrentEntity->model;
+ m_pStudioHeader = (studiohdr_t *)IEngineStudio.Mod_Extradata (m_pRenderModel);
+ IEngineStudio.StudioSetHeader( m_pStudioHeader );
+ IEngineStudio.SetRenderModel( m_pRenderModel );
+
+ StudioSetUpTransform( 0 );
+
+ if (flags & STUDIO_RENDER)
+ {
+ // see if the bounding box lets us trivially reject, also sets
+ if (!IEngineStudio.StudioCheckBBox ())
+ return 0;
+
+ (*m_pModelsDrawn)++;
+ (*m_pStudioModelCount)++; // render data cache cookie
+
+ if (m_pStudioHeader->numbodyparts == 0)
+ return 1;
+ }
+
+ if (m_pCurrentEntity->curstate.movetype == MOVETYPE_FOLLOW)
+ {
+ StudioMergeBones( m_pRenderModel );
+ }
+ else
+ {
+ StudioSetupBones( );
+ }
+ StudioSaveBones( );
+
+ if (flags & STUDIO_EVENTS)
+ {
+ StudioCalcAttachments( );
+ IEngineStudio.StudioClientEvents( );
+ // copy attachments into global entity array
+ if ( m_pCurrentEntity->index > 0 )
+ {
+ cl_entity_t *ent = gEngfuncs.GetEntityByIndex( m_pCurrentEntity->index );
+
+ memcpy( ent->attachment, m_pCurrentEntity->attachment, sizeof( vec3_t ) * 4 );
+ }
+ }
+
+ if (flags & STUDIO_RENDER)
+ {
+ lighting.plightvec = dir;
+ IEngineStudio.StudioDynamicLight(m_pCurrentEntity, &lighting );
+
+ IEngineStudio.StudioEntityLight( &lighting );
+
+ // model and frame independant
+ IEngineStudio.StudioSetupLighting (&lighting);
+
+ // get remap colors
+ m_nTopColor = m_pCurrentEntity->curstate.colormap & 0xFF;
+ m_nBottomColor = (m_pCurrentEntity->curstate.colormap & 0xFF00) >> 8;
+
+ IEngineStudio.StudioSetRemapColors( m_nTopColor, m_nBottomColor );
+
+ StudioRenderModel();
+
+ // If this is the local player's view model, hook into HUD
+ char theModelName[MAX_MODEL_NAME];
+ strcpy(theModelName, this->m_pCurrentEntity->model->name);
+
+ gHUD.PostModelRender(theModelName);
+ }
+
+ return 1;
+}
+
+/*
+====================
+StudioEstimateGait
+
+====================
+*/
+void CStudioModelRenderer::StudioEstimateGait( entity_state_t *pplayer )
+{
+ float dt;
+ vec3_t est_velocity;
+
+ dt = (m_clTime - m_clOldTime);
+ if (dt < 0)
+ dt = 0;
+ else if (dt > 1.0)
+ dt = 1;
+
+ if (dt == 0 || m_pPlayerInfo->renderframe == m_nFrameCount)
+ {
+ m_flGaitMovement = 0;
+ return;
+ }
+
+ // VectorAdd( pplayer->velocity, pplayer->prediction_error, est_velocity );
+ if ( m_fGaitEstimation )
+ {
+ VectorSubtract( m_pCurrentEntity->origin, m_pPlayerInfo->prevgaitorigin, est_velocity );
+ VectorCopy( m_pCurrentEntity->origin, m_pPlayerInfo->prevgaitorigin );
+ m_flGaitMovement = Length( est_velocity );
+ if (dt <= 0 || m_flGaitMovement / dt < 5)
+ {
+ m_flGaitMovement = 0;
+ est_velocity[0] = 0;
+ est_velocity[1] = 0;
+ }
+ }
+ else
+ {
+ VectorCopy( pplayer->velocity, est_velocity );
+ m_flGaitMovement = Length( est_velocity ) * dt;
+ }
+
+ if (est_velocity[1] == 0 && est_velocity[0] == 0)
+ {
+ float flYawDiff = m_pCurrentEntity->angles[YAW] - m_pPlayerInfo->gaityaw;
+ flYawDiff = flYawDiff - (int)(flYawDiff / 360) * 360;
+ if (flYawDiff > 180)
+ flYawDiff -= 360;
+ if (flYawDiff < -180)
+ flYawDiff += 360;
+
+ if (dt < 0.25)
+ flYawDiff *= dt * 4;
+ else
+ flYawDiff *= dt;
+
+ m_pPlayerInfo->gaityaw += flYawDiff;
+ m_pPlayerInfo->gaityaw = m_pPlayerInfo->gaityaw - (int)(m_pPlayerInfo->gaityaw / 360) * 360;
+
+ m_flGaitMovement = 0;
+ }
+ else
+ {
+ m_pPlayerInfo->gaityaw = (atan2(est_velocity[1], est_velocity[0]) * 180 / M_PI);
+ if (m_pPlayerInfo->gaityaw > 180)
+ m_pPlayerInfo->gaityaw = 180;
+ if (m_pPlayerInfo->gaityaw < -180)
+ m_pPlayerInfo->gaityaw = -180;
+ }
+
+}
+
+/*
+====================
+StudioProcessGait
+
+====================
+*/
+void CStudioModelRenderer::StudioProcessGait( entity_state_t *pplayer )
+{
+ mstudioseqdesc_t *pseqdesc;
+ float dt;
+ int iBlend;
+ float flYaw; // view direction relative to movement
+
+ m_pCurrentEntity->curstate.sequence = max(min(m_pCurrentEntity->curstate.sequence, m_pStudioHeader->numseq-1), 0);
+
+ pseqdesc = (mstudioseqdesc_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqindex) + m_pCurrentEntity->curstate.sequence;
+
+ StudioPlayerBlend( pseqdesc, &iBlend, &m_pCurrentEntity->angles[PITCH] );
+
+ m_pCurrentEntity->latched.prevangles[PITCH] = m_pCurrentEntity->angles[PITCH];
+ m_pCurrentEntity->curstate.blending[0] = iBlend;
+ m_pCurrentEntity->latched.prevblending[0] = m_pCurrentEntity->curstate.blending[0];
+ m_pCurrentEntity->latched.prevseqblending[0] = m_pCurrentEntity->curstate.blending[0];
+
+ // Con_DPrintf("%f %d\n", m_pCurrentEntity->angles[PITCH], m_pCurrentEntity->blending[0] );
+
+ dt = (m_clTime - m_clOldTime);
+ if (dt < 0)
+ dt = 0;
+ else if (dt > 1.0)
+ dt = 1;
+
+ StudioEstimateGait( pplayer );
+
+ // Con_DPrintf("%f %f\n", m_pCurrentEntity->angles[YAW], m_pPlayerInfo->gaityaw );
+
+ // calc side to side turning
+ flYaw = m_pCurrentEntity->angles[YAW] - m_pPlayerInfo->gaityaw;
+ flYaw = flYaw - (int)(flYaw / 360) * 360;
+ if (flYaw < -180)
+ flYaw = flYaw + 360;
+ if (flYaw > 180)
+ flYaw = flYaw - 360;
+
+ if (flYaw > 120)
+ {
+ m_pPlayerInfo->gaityaw = m_pPlayerInfo->gaityaw - 180;
+ m_flGaitMovement = -m_flGaitMovement;
+ flYaw = flYaw - 180;
+ }
+ else if (flYaw < -120)
+ {
+ m_pPlayerInfo->gaityaw = m_pPlayerInfo->gaityaw + 180;
+ m_flGaitMovement = -m_flGaitMovement;
+ flYaw = flYaw + 180;
+ }
+
+ // adjust torso
+ m_pCurrentEntity->curstate.controller[0] = ((flYaw / 4.0) + 30) / (60.0 / 255.0);
+ m_pCurrentEntity->curstate.controller[1] = ((flYaw / 4.0) + 30) / (60.0 / 255.0);
+ m_pCurrentEntity->curstate.controller[2] = ((flYaw / 4.0) + 30) / (60.0 / 255.0);
+ m_pCurrentEntity->curstate.controller[3] = ((flYaw / 4.0) + 30) / (60.0 / 255.0);
+ m_pCurrentEntity->latched.prevcontroller[0] = m_pCurrentEntity->curstate.controller[0];
+ m_pCurrentEntity->latched.prevcontroller[1] = m_pCurrentEntity->curstate.controller[1];
+ m_pCurrentEntity->latched.prevcontroller[2] = m_pCurrentEntity->curstate.controller[2];
+ m_pCurrentEntity->latched.prevcontroller[3] = m_pCurrentEntity->curstate.controller[3];
+
+ m_pCurrentEntity->angles[YAW] = m_pPlayerInfo->gaityaw;
+ if (m_pCurrentEntity->angles[YAW] < -0)
+ m_pCurrentEntity->angles[YAW] += 360;
+ m_pCurrentEntity->latched.prevangles[YAW] = m_pCurrentEntity->angles[YAW];
+
+ pplayer->gaitsequence = max(min(pplayer->gaitsequence, m_pStudioHeader->numseq-1), 0);
+
+ pseqdesc = (mstudioseqdesc_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqindex) + pplayer->gaitsequence;
+
+ // calc gait frame
+ if (pseqdesc->linearmovement[0] > 0)
+ {
+ m_pPlayerInfo->gaitframe += (m_flGaitMovement / pseqdesc->linearmovement[0]) * pseqdesc->numframes;
+ }
+ else
+ {
+ m_pPlayerInfo->gaitframe += pseqdesc->fps * dt;
+ }
+
+ // do modulo
+ m_pPlayerInfo->gaitframe = m_pPlayerInfo->gaitframe - (int)(m_pPlayerInfo->gaitframe / pseqdesc->numframes) * pseqdesc->numframes;
+ if (m_pPlayerInfo->gaitframe < 0)
+ m_pPlayerInfo->gaitframe += pseqdesc->numframes;
+}
+
+/*
+====================
+StudioDrawPlayer
+
+====================
+*/
+int CStudioModelRenderer::StudioDrawPlayer( int flags, entity_state_t *pplayer )
+{
+ alight_t lighting;
+ vec3_t dir;
+
+ m_pCurrentEntity = IEngineStudio.GetCurrentEntity();
+ IEngineStudio.GetTimes( &m_nFrameCount, &m_clTime, &m_clOldTime );
+ IEngineStudio.GetViewInfo( m_vRenderOrigin, m_vUp, m_vRight, m_vNormal );
+ IEngineStudio.GetAliasScale( &m_fSoftwareXScale, &m_fSoftwareYScale );
+
+ // Horrible hack for preventing visual artifacts while being digested
+ if(gHUD.GetIsBeingDigested())
+ {
+ return 0;
+ }
+
+ // Con_DPrintf("DrawPlayer %d\n", m_pCurrentEntity->blending[0] );
+
+ // Con_DPrintf("DrawPlayer %d %d (%d)\n", m_nFrameCount, pplayer->player_index, m_pCurrentEntity->curstate.sequence );
+
+ // Con_DPrintf("Player %.2f %.2f %.2f\n", pplayer->velocity[0], pplayer->velocity[1], pplayer->velocity[2] );
+
+ m_nPlayerIndex = pplayer->number - 1;
+
+ if (m_nPlayerIndex < 0 || m_nPlayerIndex >= gEngfuncs.GetMaxClients())
+ return 0;
+
+ //m_pRenderModel = IEngineStudio.SetupPlayerModel( m_nPlayerIndex );
+ m_pRenderModel = m_pCurrentEntity->model;
+ if (m_pRenderModel == NULL)
+ return 0;
+
+ m_pStudioHeader = (studiohdr_t *)IEngineStudio.Mod_Extradata (m_pRenderModel);
+ IEngineStudio.StudioSetHeader( m_pStudioHeader );
+ IEngineStudio.SetRenderModel( m_pRenderModel );
+
+ if (pplayer->gaitsequence)
+ {
+ vec3_t orig_angles;
+ m_pPlayerInfo = IEngineStudio.PlayerInfo( m_nPlayerIndex );
+
+ VectorCopy( m_pCurrentEntity->angles, orig_angles );
+
+ StudioProcessGait( pplayer );
+
+ m_pPlayerInfo->gaitsequence = pplayer->gaitsequence;
+ m_pPlayerInfo = NULL;
+
+ StudioSetUpTransform( 0 );
+ VectorCopy( orig_angles, m_pCurrentEntity->angles );
+ }
+ else
+ {
+ m_pCurrentEntity->curstate.controller[0] = 127;
+ m_pCurrentEntity->curstate.controller[1] = 127;
+ m_pCurrentEntity->curstate.controller[2] = 127;
+ m_pCurrentEntity->curstate.controller[3] = 127;
+ m_pCurrentEntity->latched.prevcontroller[0] = m_pCurrentEntity->curstate.controller[0];
+ m_pCurrentEntity->latched.prevcontroller[1] = m_pCurrentEntity->curstate.controller[1];
+ m_pCurrentEntity->latched.prevcontroller[2] = m_pCurrentEntity->curstate.controller[2];
+ m_pCurrentEntity->latched.prevcontroller[3] = m_pCurrentEntity->curstate.controller[3];
+
+ m_pPlayerInfo = IEngineStudio.PlayerInfo( m_nPlayerIndex );
+ m_pPlayerInfo->gaitsequence = 0;
+
+ StudioSetUpTransform( 0 );
+ }
+
+ if (flags & STUDIO_RENDER)
+ {
+ // see if the bounding box lets us trivially reject, also sets
+ if (!IEngineStudio.StudioCheckBBox ())
+ return 0;
+
+ (*m_pModelsDrawn)++;
+ (*m_pStudioModelCount)++; // render data cache cookie
+
+ if (m_pStudioHeader->numbodyparts == 0)
+ return 1;
+ }
+
+ m_pPlayerInfo = IEngineStudio.PlayerInfo( m_nPlayerIndex );
+ StudioSetupBones( );
+ StudioSaveBones( );
+ m_pPlayerInfo->renderframe = m_nFrameCount;
+
+ m_pPlayerInfo = NULL;
+
+ if (flags & STUDIO_EVENTS)
+ {
+ StudioCalcAttachments( );
+ IEngineStudio.StudioClientEvents( );
+ // copy attachments into global entity array
+ if ( m_pCurrentEntity->index > 0 )
+ {
+ cl_entity_t *ent = gEngfuncs.GetEntityByIndex( m_pCurrentEntity->index );
+
+ memcpy( ent->attachment, m_pCurrentEntity->attachment, sizeof( vec3_t ) * 4 );
+ }
+ }
+
+ if (flags & STUDIO_RENDER)
+ {
+ /*
+ if (m_pCvarHiModels->value && m_pRenderModel != m_pCurrentEntity->model )
+ {
+ // show highest resolution multiplayer model
+ m_pCurrentEntity->curstate.body = 255;
+ }
+ */
+
+ lighting.plightvec = dir;
+ IEngineStudio.StudioDynamicLight(m_pCurrentEntity, &lighting );
+
+ IEngineStudio.StudioEntityLight( &lighting );
+
+ // model and frame independant
+ IEngineStudio.StudioSetupLighting (&lighting);
+
+ m_pPlayerInfo = IEngineStudio.PlayerInfo( m_nPlayerIndex );
+
+ // get remap colors
+ m_nTopColor = m_pPlayerInfo->topcolor;
+ m_nBottomColor = m_pPlayerInfo->bottomcolor;
+ if (m_nTopColor < 0)
+ m_nTopColor = 0;
+ if (m_nTopColor > 360)
+ m_nTopColor = 360;
+ if (m_nBottomColor < 0)
+ m_nBottomColor = 0;
+ if (m_nBottomColor > 360)
+ m_nBottomColor = 360;
+
+ IEngineStudio.StudioSetRemapColors( m_nTopColor, m_nBottomColor );
+
+ StudioRenderModel( );
+ m_pPlayerInfo = NULL;
+
+ if (pplayer->weaponmodel)
+ {
+ cl_entity_t saveent = *m_pCurrentEntity;
+
+ model_t *pweaponmodel = IEngineStudio.GetModelByIndex( pplayer->weaponmodel );
+
+ m_pStudioHeader = (studiohdr_t *)IEngineStudio.Mod_Extradata (pweaponmodel);
+ IEngineStudio.StudioSetHeader( m_pStudioHeader );
+
+ StudioMergeBones( pweaponmodel);
+
+ IEngineStudio.StudioSetupLighting (&lighting);
+
+ StudioRenderModel( );
+
+ StudioCalcAttachments( );
+
+ *m_pCurrentEntity = saveent;
+ }
+ }
+
+ return 1;
+}
+
+/*
+====================
+StudioCalcAttachments
+
+====================
+*/
+void CStudioModelRenderer::StudioCalcAttachments( void )
+{
+ int i;
+ mstudioattachment_t *pattachment;
+
+ if ( m_pStudioHeader->numattachments > 4 )
+ {
+ gEngfuncs.Con_DPrintf( "Too many attachments on %s\n", m_pCurrentEntity->model->name );
+ exit( -1 );
+ }
+
+ // calculate attachment points
+ pattachment = (mstudioattachment_t *)((byte *)m_pStudioHeader + m_pStudioHeader->attachmentindex);
+ for (i = 0; i < m_pStudioHeader->numattachments; i++)
+ {
+ VectorTransform( pattachment[i].org, (*m_plighttransform)[pattachment[i].bone], m_pCurrentEntity->attachment[i] );
+ }
+}
+
+/*
+====================
+StudioRenderModel
+
+====================
+*/
+void CStudioModelRenderer::StudioRenderModel( void )
+{
+ IEngineStudio.SetChromeOrigin();
+ IEngineStudio.SetForceFaceFlags( 0 );
+
+ if ( m_pCurrentEntity->curstate.renderfx == kRenderFxGlowShell )
+ {
+ m_pCurrentEntity->curstate.renderfx = kRenderFxNone;
+ StudioRenderFinal( );
+
+ if ( !IEngineStudio.IsHardware() )
+ {
+ gEngfuncs.pTriAPI->RenderMode( kRenderTransAdd );
+ }
+
+ IEngineStudio.SetForceFaceFlags( STUDIO_NF_CHROME );
+
+ gEngfuncs.pTriAPI->SpriteTexture( m_pChromeSprite, 0 );
+ m_pCurrentEntity->curstate.renderfx = kRenderFxGlowShell;
+
+ StudioRenderFinal( );
+ if ( !IEngineStudio.IsHardware() )
+ {
+ gEngfuncs.pTriAPI->RenderMode( kRenderNormal );
+ }
+ }
+ else
+ {
+ StudioRenderFinal( );
+ }
+}
+
+/*
+====================
+StudioRenderFinal_Software
+
+====================
+*/
+void CStudioModelRenderer::StudioRenderFinal_Software( void )
+{
+ int i;
+
+ // Note, rendermode set here has effect in SW
+ IEngineStudio.SetupRenderer( 0 );
+
+ // Put this in here?
+ //int theRenderMode = GetRenderModeForModelName(rendermode, m_pSubModel[i].name);
+
+ if (m_pCvarDrawEntities->value == 2)
+ {
+ IEngineStudio.StudioDrawBones( );
+ }
+ else if (m_pCvarDrawEntities->value == 3)
+ {
+ IEngineStudio.StudioDrawHulls( );
+ }
+ else
+ {
+ for (i=0 ; i < m_pStudioHeader->numbodyparts ; i++)
+ {
+ IEngineStudio.StudioSetupModel( i, (void **)&m_pBodyPart, (void **)&m_pSubModel );
+ IEngineStudio.StudioDrawPoints( );
+ }
+ }
+
+ if (m_pCvarDrawEntities->value == 4)
+ {
+ gEngfuncs.pTriAPI->RenderMode( kRenderTransAdd );
+ IEngineStudio.StudioDrawHulls( );
+ gEngfuncs.pTriAPI->RenderMode( kRenderNormal );
+ }
+
+ if (m_pCvarDrawEntities->value == 5)
+ {
+ IEngineStudio.StudioDrawAbsBBox( );
+ }
+
+ IEngineStudio.RestoreRenderer();
+}
+
+/*
+====================
+StudioRenderFinal_Hardware
+
+ ====================
+*/
+void CStudioModelRenderer::StudioRenderFinal_Hardware( void )
+{
+ int i;
+ int rendermode;
+
+ rendermode = IEngineStudio.GetForceFaceFlags() ? kRenderTransAdd : m_pCurrentEntity->curstate.rendermode;
+ IEngineStudio.SetupRenderer( rendermode );
+
+ if (m_pCvarDrawEntities->value == 2)
+ {
+ IEngineStudio.StudioDrawBones();
+ }
+ else if (m_pCvarDrawEntities->value == 3)
+ {
+ IEngineStudio.StudioDrawHulls();
+ }
+ else
+ {
+ for (i=0 ; i < m_pStudioHeader->numbodyparts ; i++)
+ {
+ IEngineStudio.StudioSetupModel( i, (void **)&m_pBodyPart, (void **)&m_pSubModel );
+
+ if (m_fDoInterp)
+ {
+ // interpolation messes up bounding boxes.
+ m_pCurrentEntity->trivial_accept = 0;
+ }
+
+ IEngineStudio.GL_SetRenderMode(rendermode);
+
+// mstudiobodyparts_t* pbodypart = (mstudiobodyparts_t *)((byte *)m_pStudioHeader + m_pStudioHeader->bodypartindex) + i;
+//
+// //int index = m_bodynum / pbodypart->base;
+// //index = index % pbodypart->nummodels;
+//
+// mstudiomodel_t* theModel = (mstudiomodel_t *)((byte *)m_pStudioHeader + pbodypart->modelindex);// + index;
+// ASSERT(theModel);
+//
+// int theModelRenderMode = rendermode;//GetRenderModeForModelName(rendermode, theModel->name);
+//
+// // This could be dangerous...how to find out?
+// //IEngineStudio.SetupRenderer( theModelRenderMode );
+//
+// IEngineStudio.GL_SetRenderMode( theModelRenderMode );
+
+ IEngineStudio.StudioDrawPoints();
+ IEngineStudio.GL_StudioDrawShadow();
+ }
+ }
+
+ if ( m_pCvarDrawEntities->value == 4 )
+ {
+ gEngfuncs.pTriAPI->RenderMode( kRenderTransAdd );
+ IEngineStudio.StudioDrawHulls( );
+ gEngfuncs.pTriAPI->RenderMode( kRenderNormal );
+ }
+
+ if (m_pCvarDrawEntities->value == 5)
+ {
+ IEngineStudio.StudioDrawAbsBBox( );
+ }
+
+ IEngineStudio.RestoreRenderer();
+}
+
+/*
+====================
+StudioRenderFinal
+
+====================
+*/
+void CStudioModelRenderer::StudioRenderFinal(void)
+{
+ if ( IEngineStudio.IsHardware() )
+ {
+ StudioRenderFinal_Hardware();
+ }
+ else
+ {
+ StudioRenderFinal_Software();
+ }
+}
+
diff --git a/main/source/cl_dll/StudioModelRenderer.h b/main/source/cl_dll/StudioModelRenderer.h
index 0220d448..fae3a8ee 100644
--- a/main/source/cl_dll/StudioModelRenderer.h
+++ b/main/source/cl_dll/StudioModelRenderer.h
@@ -1,182 +1,182 @@
-#if !defined ( STUDIOMODELRENDERER_H )
-#define STUDIOMODELRENDERER_H
-#if defined( _WIN32 )
-#pragma once
-#endif
-
-/*
-====================
-CStudioModelRenderer
-
-====================
-*/
-class CStudioModelRenderer
-{
-public:
- // Construction/Destruction
- CStudioModelRenderer( void );
- virtual ~CStudioModelRenderer( void );
-
- // Initialization
- virtual void Init( void );
-
-public:
- // Public Interfaces
- virtual int StudioDrawModel ( int flags );
- virtual int StudioDrawPlayer ( int flags, struct entity_state_s *pplayer );
-
-public:
- // Local interfaces
- //
-
- // Look up animation data for sequence
- virtual mstudioanim_t *StudioGetAnim ( model_t *m_pSubModel, mstudioseqdesc_t *pseqdesc );
-
- // Interpolate model position and angles and set up matrices
- virtual void StudioSetUpTransform (int trivial_accept);
-
- // Set up model bone positions
- virtual void StudioSetupBones ( void );
-
- // Find final attachment points
- virtual void StudioCalcAttachments ( void );
-
- // Save bone matrices and names
- virtual void StudioSaveBones( void );
-
- // Merge cached bones with current bones for model
- virtual void StudioMergeBones ( model_t *m_pSubModel );
-
- // Determine interpolation fraction
- virtual float StudioEstimateInterpolant( void );
-
- // Determine current frame for rendering
- virtual float StudioEstimateFrame ( mstudioseqdesc_t *pseqdesc );
-
- // Apply special effects to transform matrix
- virtual void StudioFxTransform( cl_entity_t *ent, float transform[3][4] );
-
- // Spherical interpolation of bones
- virtual void StudioSlerpBones ( vec4_t q1[], float pos1[][3], vec4_t q2[], float pos2[][3], float s );
-
- // Compute bone adjustments ( bone controllers )
- virtual void StudioCalcBoneAdj ( float dadt, float *adj, const byte *pcontroller1, const byte *pcontroller2, byte mouthopen );
-
- // Get bone quaternions
- virtual void StudioCalcBoneQuaterion ( int frame, float s, mstudiobone_t *pbone, mstudioanim_t *panim, float *adj, float *q );
-
- // Get bone positions
- virtual void StudioCalcBonePosition ( int frame, float s, mstudiobone_t *pbone, mstudioanim_t *panim, float *adj, float *pos );
-
- // Compute rotations
- virtual void StudioCalcRotations ( float pos[][3], vec4_t *q, mstudioseqdesc_t *pseqdesc, mstudioanim_t *panim, float f );
-
- // Send bones and verts to renderer
- virtual void StudioRenderModel ( void );
-
- // Finalize rendering
- virtual void StudioRenderFinal (void);
-
- // GL&D3D vs. Software renderer finishing functions
- virtual void StudioRenderFinal_Software ( void );
- virtual void StudioRenderFinal_Hardware ( void );
-
- // Player specific data
- // Determine pitch and blending amounts for players
- virtual void StudioPlayerBlend ( mstudioseqdesc_t *pseqdesc, int *pBlend, float *pPitch );
-
- // Estimate gait frame for player
- virtual void StudioEstimateGait ( entity_state_t *pplayer );
-
- // Process movement of player
- virtual void StudioProcessGait ( entity_state_t *pplayer );
-
-public:
-
- // Client clock
- double m_clTime;
- // Old Client clock
- double m_clOldTime;
-
- // Do interpolation?
- int m_fDoInterp;
- // Do gait estimation?
- int m_fGaitEstimation;
-
- // Current render frame #
- int m_nFrameCount;
-
- // Cvars that studio model code needs to reference
- //
- // Use high quality models?
- cvar_t *m_pCvarHiModels;
- // Developer debug output desired?
- cvar_t *m_pCvarDeveloper;
- // Draw entities bone hit boxes, etc?
- cvar_t *m_pCvarDrawEntities;
-
- // The entity which we are currently rendering.
- cl_entity_t *m_pCurrentEntity;
-
- // The model for the entity being rendered
- model_t *m_pRenderModel;
-
- // Player info for current player, if drawing a player
- player_info_t *m_pPlayerInfo;
-
- // The index of the player being drawn
- int m_nPlayerIndex;
-
- // The player's gait movement
- float m_flGaitMovement;
-
- // Pointer to header block for studio model data
- studiohdr_t *m_pStudioHeader;
-
- // Pointers to current body part and submodel
- mstudiobodyparts_t *m_pBodyPart;
- mstudiomodel_t *m_pSubModel;
-
- // Palette substition for top and bottom of model
- int m_nTopColor;
- int m_nBottomColor;
-
- //
- // Sprite model used for drawing studio model chrome
- model_t *m_pChromeSprite;
-
- // Caching
- // Number of bones in bone cache
- int m_nCachedBones;
- // Names of cached bones
- char m_nCachedBoneNames[ MAXSTUDIOBONES ][ 32 ];
- // Cached bone & light transformation matrices
- float m_rgCachedBoneTransform [ MAXSTUDIOBONES ][ 3 ][ 4 ];
- float m_rgCachedLightTransform[ MAXSTUDIOBONES ][ 3 ][ 4 ];
-
- // Software renderer scale factors
- float m_fSoftwareXScale, m_fSoftwareYScale;
-
- // Current view vectors and render origin
- float m_vUp[ 3 ];
- float m_vRight[ 3 ];
- float m_vNormal[ 3 ];
-
- float m_vRenderOrigin[ 3 ];
-
- // Model render counters ( from engine )
- int *m_pStudioModelCount;
- int *m_pModelsDrawn;
-
- // Matrices
- // Model to world transformation
- float (*m_protationmatrix)[ 3 ][ 4 ];
- // Model to view transformation
- float (*m_paliastransform)[ 3 ][ 4 ];
-
- // Concatenated bone and light transforms
- float (*m_pbonetransform) [ MAXSTUDIOBONES ][ 3 ][ 4 ];
- float (*m_plighttransform)[ MAXSTUDIOBONES ][ 3 ][ 4 ];
-};
-
+#if !defined ( STUDIOMODELRENDERER_H )
+#define STUDIOMODELRENDERER_H
+#if defined( _WIN32 )
+#pragma once
+#endif
+
+/*
+====================
+CStudioModelRenderer
+
+====================
+*/
+class CStudioModelRenderer
+{
+public:
+ // Construction/Destruction
+ CStudioModelRenderer( void );
+ virtual ~CStudioModelRenderer( void );
+
+ // Initialization
+ virtual void Init( void );
+
+public:
+ // Public Interfaces
+ virtual int StudioDrawModel ( int flags );
+ virtual int StudioDrawPlayer ( int flags, struct entity_state_s *pplayer );
+
+public:
+ // Local interfaces
+ //
+
+ // Look up animation data for sequence
+ virtual mstudioanim_t *StudioGetAnim ( model_t *m_pSubModel, mstudioseqdesc_t *pseqdesc );
+
+ // Interpolate model position and angles and set up matrices
+ virtual void StudioSetUpTransform (int trivial_accept);
+
+ // Set up model bone positions
+ virtual void StudioSetupBones ( void );
+
+ // Find final attachment points
+ virtual void StudioCalcAttachments ( void );
+
+ // Save bone matrices and names
+ virtual void StudioSaveBones( void );
+
+ // Merge cached bones with current bones for model
+ virtual void StudioMergeBones ( model_t *m_pSubModel );
+
+ // Determine interpolation fraction
+ virtual float StudioEstimateInterpolant( void );
+
+ // Determine current frame for rendering
+ virtual float StudioEstimateFrame ( mstudioseqdesc_t *pseqdesc );
+
+ // Apply special effects to transform matrix
+ virtual void StudioFxTransform( cl_entity_t *ent, float transform[3][4] );
+
+ // Spherical interpolation of bones
+ virtual void StudioSlerpBones ( vec4_t q1[], float pos1[][3], vec4_t q2[], float pos2[][3], float s );
+
+ // Compute bone adjustments ( bone controllers )
+ virtual void StudioCalcBoneAdj ( float dadt, float *adj, const byte *pcontroller1, const byte *pcontroller2, byte mouthopen );
+
+ // Get bone quaternions
+ virtual void StudioCalcBoneQuaterion ( int frame, float s, mstudiobone_t *pbone, mstudioanim_t *panim, float *adj, float *q );
+
+ // Get bone positions
+ virtual void StudioCalcBonePosition ( int frame, float s, mstudiobone_t *pbone, mstudioanim_t *panim, float *adj, float *pos );
+
+ // Compute rotations
+ virtual void StudioCalcRotations ( float pos[][3], vec4_t *q, mstudioseqdesc_t *pseqdesc, mstudioanim_t *panim, float f );
+
+ // Send bones and verts to renderer
+ virtual void StudioRenderModel ( void );
+
+ // Finalize rendering
+ virtual void StudioRenderFinal (void);
+
+ // GL&D3D vs. Software renderer finishing functions
+ virtual void StudioRenderFinal_Software ( void );
+ virtual void StudioRenderFinal_Hardware ( void );
+
+ // Player specific data
+ // Determine pitch and blending amounts for players
+ virtual void StudioPlayerBlend ( mstudioseqdesc_t *pseqdesc, int *pBlend, float *pPitch );
+
+ // Estimate gait frame for player
+ virtual void StudioEstimateGait ( entity_state_t *pplayer );
+
+ // Process movement of player
+ virtual void StudioProcessGait ( entity_state_t *pplayer );
+
+public:
+
+ // Client clock
+ double m_clTime;
+ // Old Client clock
+ double m_clOldTime;
+
+ // Do interpolation?
+ int m_fDoInterp;
+ // Do gait estimation?
+ int m_fGaitEstimation;
+
+ // Current render frame #
+ int m_nFrameCount;
+
+ // Cvars that studio model code needs to reference
+ //
+ // Use high quality models?
+ cvar_t *m_pCvarHiModels;
+ // Developer debug output desired?
+ cvar_t *m_pCvarDeveloper;
+ // Draw entities bone hit boxes, etc?
+ cvar_t *m_pCvarDrawEntities;
+
+ // The entity which we are currently rendering.
+ cl_entity_t *m_pCurrentEntity;
+
+ // The model for the entity being rendered
+ model_t *m_pRenderModel;
+
+ // Player info for current player, if drawing a player
+ player_info_t *m_pPlayerInfo;
+
+ // The index of the player being drawn
+ int m_nPlayerIndex;
+
+ // The player's gait movement
+ float m_flGaitMovement;
+
+ // Pointer to header block for studio model data
+ studiohdr_t *m_pStudioHeader;
+
+ // Pointers to current body part and submodel
+ mstudiobodyparts_t *m_pBodyPart;
+ mstudiomodel_t *m_pSubModel;
+
+ // Palette substition for top and bottom of model
+ int m_nTopColor;
+ int m_nBottomColor;
+
+ //
+ // Sprite model used for drawing studio model chrome
+ model_t *m_pChromeSprite;
+
+ // Caching
+ // Number of bones in bone cache
+ int m_nCachedBones;
+ // Names of cached bones
+ char m_nCachedBoneNames[ MAXSTUDIOBONES ][ 32 ];
+ // Cached bone & light transformation matrices
+ float m_rgCachedBoneTransform [ MAXSTUDIOBONES ][ 3 ][ 4 ];
+ float m_rgCachedLightTransform[ MAXSTUDIOBONES ][ 3 ][ 4 ];
+
+ // Software renderer scale factors
+ float m_fSoftwareXScale, m_fSoftwareYScale;
+
+ // Current view vectors and render origin
+ float m_vUp[ 3 ];
+ float m_vRight[ 3 ];
+ float m_vNormal[ 3 ];
+
+ float m_vRenderOrigin[ 3 ];
+
+ // Model render counters ( from engine )
+ int *m_pStudioModelCount;
+ int *m_pModelsDrawn;
+
+ // Matrices
+ // Model to world transformation
+ float (*m_protationmatrix)[ 3 ][ 4 ];
+ // Model to view transformation
+ float (*m_paliastransform)[ 3 ][ 4 ];
+
+ // Concatenated bone and light transforms
+ float (*m_pbonetransform) [ MAXSTUDIOBONES ][ 3 ][ 4 ];
+ float (*m_plighttransform)[ MAXSTUDIOBONES ][ 3 ][ 4 ];
+};
+
#endif // STUDIOMODELRENDERER_H
\ No newline at end of file
diff --git a/main/source/cl_dll/ammo.cpp b/main/source/cl_dll/ammo.cpp
index e8c33dec..9d8af707 100644
--- a/main/source/cl_dll/ammo.cpp
+++ b/main/source/cl_dll/ammo.cpp
@@ -1,1461 +1,1461 @@
-/***
-*
-* Copyright (c) 1999, Valve LLC. All rights reserved.
-*
-* This product contains software technology licensed from Id
-* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
-* All Rights Reserved.
-*
-* Use, distribution, and modification of this source code and/or resulting
-* object code is restricted to non-commercial enhancements to products from
-* Valve LLC. All other use, distribution, or modification is prohibited
-* without written permission from Valve LLC.
-*
-****/
-//
-// Ammo.cpp
-//
-// implementation of CHudAmmo class
-//
-
-#include "hud.h"
-#include "cl_util.h"
-
-#include
-#include
-
-#include "ammohistory.h"
-#include "vgui_TeamFortressViewport.h"
-#include "mod/AvHClientVariables.h"
-#include "mod/AvHSharedUtil.h"
-#include "mod/AvHScrollHandler.h"
-#include "mod/AvHNetworkMessages.h"
-
-WEAPON *gpActiveSel; // NULL means off, 1 means just the menu bar, otherwise
- // this points to the active weapon menu item
-WEAPON *gpLastSel; // Last weapon menu selection
-
-bool HUD_GetWeaponEnabled(int inID);
-client_sprite_t *GetSpriteList(client_sprite_t *pList, const char *psz, int iRes, int iCount);
-
-WeaponsResource gWR;
-
-int g_weaponselect = 0;
-
-extern bool gCanMove;
-
-void IN_AttackDownForced(void);
-void IN_AttackUpForced(void);
-void IN_Attack2Down(void);
-void IN_Attack2Up(void);
-void IN_ReloadDown();
-void IN_ReloadUp();
-bool CheckInAttack(void);
-
-//Equivalent to DECLARE_COMMAND(lastinv,LastInv) except we use gWR instead of gHud
-void __CmdFunc_LastInv(void)
-{ gWR.UserCmd_LastInv(); }
-
-// +movement
-void __CmdFunc_MovementOn(void)
-{ gWR.UserCmd_MovementOn(); }
-void __CmdFunc_MovementOff(void)
-{ gWR.UserCmd_MovementOff(); }
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-WeaponsResource::WeaponsResource(void) : lastWeapon(NULL), iOldWeaponBits(0) {}
-WeaponsResource::~WeaponsResource(void) {}
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-void WeaponsResource::Init( void )
-{
- memset( rgWeapons, 0, sizeof(WEAPON)*MAX_WEAPONS );
- Reset();
- HOOK_COMMAND("lastinv", LastInv);
- // +movement
- HOOK_COMMAND("+movement", MovementOn);
- HOOK_COMMAND("-movement", MovementOff);
-}
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-void WeaponsResource::Reset( void )
-{
- lastWeapon = NULL;
- iOldWeaponBits = 0;
- memset( rgSlots, 0, sizeof(WEAPON*)*MAX_WEAPON_SLOTS*MAX_WEAPON_POSITIONS );
- memset( riAmmo, 0, sizeof(int)*MAX_AMMO_TYPES );
-}
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-void WeaponsResource :: LoadAllWeaponSprites( void )
-{
- int customCrosshairs=CVAR_GET_FLOAT(kvCustomCrosshair);
- for (int i = 0; i < MAX_WEAPONS; i++)
- {
- if ( rgWeapons[i].iId )
- LoadWeaponSprites( &rgWeapons[i], customCrosshairs );
- }
-}
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-inline void LoadWeaponSprite( client_sprite_t* ptr, HSPRITE& sprite, wrect_t& bounds )
-{
- if( ptr )
- {
- string name( "sprites/" );
- name.append( ptr->szSprite );
- name.append( ".spr" );
- sprite = SPR_Load(name.c_str());
- bounds = ptr->rc;
- }
- else
- {
- sprite = NULL;
- }
-}
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-void WeaponsResource :: LoadWeaponSprites( WEAPON *pWeapon, int custom )
-{
- if ( custom < 0 || custom > 4 )
- custom=1;
-
- int resolutions[6] = { 320, 640, 800, 1024, 1280, 1600};
- const int numRes=6;
- int i=0, j=0, iRes=320;
- int screenWidth=ScreenWidth();
-
- for ( j=0; j < numRes; j++ ) {
- if ( screenWidth == resolutions[j] ) {
- iRes=resolutions[j];
- break;
- }
- if ( j > 0 && screenWidth > resolutions[j-1] && screenWidth < resolutions[j] ) {
- iRes=resolutions[j-1];
- break;
- }
- }
-
- char sz[128];
-
- if ( !pWeapon )
- return;
-
- memset( &pWeapon->rcCrosshair, 0, sizeof(wrect_t) );
- memset( &pWeapon->rcActive, 0, sizeof(wrect_t) );
- memset( &pWeapon->rcInactive, 0, sizeof(wrect_t) );
- memset( &pWeapon->rcAmmo, 0, sizeof(wrect_t) );
- memset( &pWeapon->rcAmmo2, 0, sizeof(wrect_t) );
- pWeapon->hCrosshair =0;
- pWeapon->hInactive = 0;
- pWeapon->hActive = 0;
- pWeapon->hAmmo = 0;
- pWeapon->hAmmo2 = 0;
-
- sprintf(sz, "sprites/%s.txt", pWeapon->szName);
- client_sprite_t *pList = SPR_GetList(sz, &i);
-
- if (!pList)
- {
- ASSERT(pList);
- return;
- }
-
- char crosshairName[32];
- sprintf(crosshairName, "crosshair_%d", custom);
- for ( j=numRes-1; j>=0; j-- ) {
- if ( resolutions[j] <= iRes ) {
- if( pWeapon->hCrosshair == NULL )
- LoadWeaponSprite( GetSpriteList( pList, crosshairName, resolutions[j], i ), pWeapon->hCrosshair, pWeapon->rcCrosshair );
- if( pWeapon->hCrosshair == NULL && custom != 0 )
- LoadWeaponSprite( GetSpriteList( pList, "crosshair_0", resolutions[j], i ), pWeapon->hCrosshair, pWeapon->rcCrosshair );
-
-
- if( pWeapon->hInactive == NULL )
- LoadWeaponSprite( GetSpriteList( pList, "weapon", resolutions[j], i ), pWeapon->hInactive, pWeapon->rcInactive );
-
- if( pWeapon->hActive == NULL )
- LoadWeaponSprite( GetSpriteList( pList, "weapon_s", resolutions[j], i ), pWeapon->hActive, pWeapon->rcActive );
-
- if( pWeapon->hAmmo == NULL )
- LoadWeaponSprite( GetSpriteList( pList, "ammo", resolutions[j], i ), pWeapon->hAmmo, pWeapon->rcAmmo );
-
- if( pWeapon->hAmmo2 == NULL )
- LoadWeaponSprite( GetSpriteList( pList, "ammo2", resolutions[j], i ), pWeapon->hAmmo2, pWeapon->rcAmmo2 );
- }
- }
-
- if( pWeapon->hActive || pWeapon->hInactive || pWeapon->hAmmo || pWeapon->hAmmo2 )
- { gHR.iHistoryGap = max( gHR.iHistoryGap, pWeapon->rcActive.bottom - pWeapon->rcActive.top ); }
-}
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-WEAPON* WeaponsResource::GetWeapon( int iId )
-{
- if( iId < 0 || iId >= MAX_WEAPONS ) { return NULL; }
- return rgWeapons[iId].iId ? &rgWeapons[iId] : NULL;
-}
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-WEAPON* WeaponsResource::GetWeaponSlot( int slot, int pos ) { return rgSlots[slot][pos]; }
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-WEAPON* WeaponsResource::GetFirstPos( int iSlot )
-{
- WEAPON *returnVal = NULL;
- ASSERT( iSlot < MAX_WEAPON_SLOTS && iSlot >= 0 );
-
- for( int counter = 0; counter < MAX_WEAPON_POSITIONS; ++counter )
- {
- if( this->IsSelectable(rgSlots[iSlot][counter]) )
- {
- returnVal = rgSlots[iSlot][counter];
- break;
- }
- }
-
- return returnVal;
-}
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-WEAPON* WeaponsResource::GetNextActivePos( int iSlot, int iSlotPos )
-{
- WEAPON* returnVal = NULL;
- ASSERT( iSlot < MAX_WEAPON_SLOTS && iSlot >= 0 );
- ASSERT( iSlotPos >= 0 );
-
- for( int counter = iSlotPos+1; counter < MAX_WEAPON_POSITIONS; ++counter )
- {
- if( this->IsSelectable(rgSlots[iSlot][counter]) )
- {
- returnVal = rgSlots[iSlot][counter];
- break;
- }
- }
-
- return returnVal;
-}
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-bool WeaponsResource::IsEnabled(WEAPON* p)
-{
- if( p == NULL ) { return false; }
- return HUD_GetWeaponEnabled(p->iId) && this->HasAmmo(p);
-}
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-bool WeaponsResource::IsSelectable(WEAPON* p)
-{
- if( p == NULL ) { return false; }
- return HUD_GetWeaponEnabled(p->iId);
-}
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-bool WeaponsResource::HasAmmo( WEAPON* p )
-{
- if( p == NULL) { return false; }
- //note : if max ammo capacity is -1, this has always returned true in spite of not
- // having actual ammo -- KGP
- return (p->iAmmoType == -1) || (p->iMax1 == -1) || p->iClip > 0 || CountAmmo(p->iAmmoType)
- || CountAmmo(p->iAmmo2Type) || (p->iFlags & WEAPON_FLAGS_SELECTIONEMPTY );
-}
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-int WeaponsResource::CountAmmo( int iId )
-{
- ASSERT( iId < MAX_AMMO_TYPES );
- if( iId < 0 ) return 0;
- return riAmmo[iId];
-}
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-int WeaponsResource::GetAmmo( int iId )
-{
- ASSERT( iId < MAX_AMMO_TYPES && iId > -1 );
- return riAmmo[iId];
-}
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-void WeaponsResource::SetAmmo( int iId, int iCount )
-{
- ASSERT( iId < MAX_AMMO_TYPES && iId > -1 );
- riAmmo[iId] = iCount;
-}
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-HSPRITE* WeaponsResource::GetAmmoPicFromWeapon( int iAmmoId, wrect_t& rect )
-{
- for ( int i = 0; i < MAX_WEAPONS; i++ )
- {
- if ( rgWeapons[i].iAmmoType == iAmmoId )
- {
- rect = rgWeapons[i].rcAmmo;
- return &rgWeapons[i].hAmmo;
- }
- else if ( rgWeapons[i].iAmmo2Type == iAmmoId )
- {
- rect = rgWeapons[i].rcAmmo2;
- return &rgWeapons[i].hAmmo2;
- }
- }
-
- return NULL;
-}
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-void WeaponsResource::AddWeapon( WEAPON *wp )
-{
- int customCrosshairs=CVAR_GET_FLOAT(kvCustomCrosshair);
- rgWeapons[ wp->iId ] = *wp;
- LoadWeaponSprites( &rgWeapons[ wp->iId ], customCrosshairs);
-}
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-void WeaponsResource::PickupWeapon( WEAPON *wp )
-{
- rgSlots[ wp->iSlot ][ wp->iSlotPos ] = wp;
-}
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-void WeaponsResource::DropWeapon( WEAPON *wp )
-{
- rgSlots[ wp->iSlot ][ wp->iSlotPos ] = NULL;
- if(lastWeapon == wp) //dropped last weapon, remove it from the list
- { lastWeapon = NULL; }
-}
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-void WeaponsResource::DropAllWeapons( void )
-{
- for ( int i = 0; i < MAX_WEAPONS; i++ )
- {
- if ( rgWeapons[i].iId )
- DropWeapon( &rgWeapons[i] );
- }
-}
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-void WeaponsResource::UserCmd_LastInv(void)
-{
- if(this->IsSelectable(this->lastWeapon))
- {
- this->SetCurrentWeapon(lastWeapon);
- // : 764
- //const char* theSound = AvHSHUGetCommonSoundName(gHUD.GetIsAlien(), WEAPON_SOUND_HUD_ON);
- //gHUD.PlayHUDSound(theSound, kHUDSoundVolume);
- }
-}
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-void WeaponsResource::UserCmd_MovementOn()
-{
- // Find out which weapon we want to trigger
- AvHUser3 theUser3 = gHUD.GetHUDUser3();
- int wID = -1;
- switch(theUser3)
- {
- case AVH_USER3_ALIEN_PLAYER1:
- wID = AVH_ABILITY_LEAP;
- break;
- case AVH_USER3_ALIEN_PLAYER3:
- // TODO: Add flap
- break;
- case AVH_USER3_ALIEN_PLAYER4:
- wID = AVH_WEAPON_BLINK;
- break;
- case AVH_USER3_ALIEN_PLAYER5:
- wID = AVH_ABILITY_CHARGE;
- break;
- default:
- IN_ReloadDown();
- return;
- }
-
- if (wID > -1)
- {
- // Fetch the needed movement weapon
- WEAPON *p = this->GetWeapon(wID);
- if (p != NULL && this->IsSelectable(p))
- {
- // Send activation of ability asap
- IN_Attack2Down();
- }
- }
-}
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-void WeaponsResource::UserCmd_MovementOff()
-{
- // Ensure that we're not activating any weapons when selected
- IN_Attack2Up();
- IN_ReloadUp();
-}
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-void WeaponsResource::SetValidWeapon(void)
-{
- WEAPON* p = this->GetFirstPos(0); //alien attack 1 or primary marine weapon
- if(gHUD.GetIsAlien())
- {
- this->SetCurrentWeapon(p);
- }
- else
- {
- if(this->IsSelectable(p) && this->HasAmmo(p))
- {
- this->SetCurrentWeapon(p);
- }
- else
- {
- p = this->GetFirstPos(1); //pistol slot
- if(this->IsSelectable(p) && this->HasAmmo(p))
- {
- this->SetCurrentWeapon(p);
- }
- else
- {
- p = this->GetFirstPos(2); //knife slot
- this->SetCurrentWeapon(p);
- }
- }
- }
-}
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-void WeaponsResource::SetCurrentWeapon(WEAPON* newWeapon)
-{
- WEAPON* currentWeapon = this->GetWeapon(gHUD.GetCurrentWeaponID());
- // : 497 - Because weapon state can get out of sync, we should allow this even if the weapons are the same
- // && newWeapon != currentWeapon
- if( newWeapon != NULL )
- {
- if( newWeapon != currentWeapon )
- { lastWeapon = currentWeapon; }
- ServerCmd(newWeapon->szName);
- g_weaponselect = newWeapon->iId;
- }
-}
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-void WeaponsResource :: SelectSlot( int iSlot, int fAdvance, int iDirection )
-{
- if ( gHUD.m_Menu.m_fMenuDisplayed && (fAdvance == FALSE) && (iDirection == 1) )
- { // menu is overriding slot use commands
- gHUD.m_Menu.SelectMenuItem( iSlot + 1 ); // slots are one off the key numbers
- return;
- }
-
- if ( iSlot >= MAX_WEAPON_SLOTS )
- return;
-
- if ( gHUD.m_fPlayerDead || gHUD.m_iHideHUDDisplay & ( HIDEHUD_WEAPONS | HIDEHUD_ALL ) )
- return;
-
- if (!(gHUD.m_iWeaponBits & (1<<(WEAPON_SUIT)) )) //require suit
- return;
-
- if ( ! ( gHUD.m_iWeaponBits & ~(1<<(WEAPON_SUIT)) )) //require something besides suit
- return;
-
- WEAPON *p = NULL;
- bool fastSwitch = CVAR_GET_FLOAT( "hud_fastswitch" ) != 0;
- if ((gpActiveSel == NULL) || (gpActiveSel == (WEAPON *)1) || (iSlot != gpActiveSel->iSlot))
- {
- p = GetFirstPos(iSlot);
- const char* theSound = AvHSHUGetCommonSoundName(gHUD.GetIsAlien(), WEAPON_SOUND_HUD_ON);
- gHUD.PlayHUDSound(theSound, kHUDSoundVolume);
-
- if (this->IsSelectable(p) && fastSwitch) //check to see if we can use fastSwitch
- {
- WEAPON *p2 = GetNextActivePos( p->iSlot, p->iSlotPos );
- if (!this->IsSelectable(p2)) //only one target in the bucket
- {
- this->SetCurrentWeapon(p);
- return;
- }
- }
- }
- else
- {
- const char* theSound = AvHSHUGetCommonSoundName(gHUD.GetIsAlien(), WEAPON_SOUND_MOVE_SELECT);
- gHUD.PlayHUDSound(theSound, kHUDSoundVolume);
-
- if ( gpActiveSel )
- p = GetNextActivePos( gpActiveSel->iSlot, gpActiveSel->iSlotPos );
- if ( !p )
- p = GetFirstPos( iSlot );
- }
-
- if (!this->IsSelectable(p)) // no valid selection found
- {
- // if fastSwitch is on, ignore, else turn on the menu
- if ( !fastSwitch ) {
- gpActiveSel = (WEAPON *)1;
- }
- else {
- gpActiveSel = NULL;
- }
- }
- else
- {
- gpActiveSel = p;
- }
-}
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-int giBucketHeight, giBucketWidth, giABHeight, giABWidth; // Ammo Bar width and height
-
-HSPRITE ghsprBuckets; // Sprite for top row of weapons menu
-
-DECLARE_MESSAGE(m_Ammo, CurWeapon ); // Current weapon and clip
-DECLARE_MESSAGE(m_Ammo, WeaponList); // new weapon type
-DECLARE_MESSAGE(m_Ammo, AmmoX); // update known ammo type's count
-DECLARE_MESSAGE(m_Ammo, AmmoPickup); // flashes an ammo pickup record
-DECLARE_MESSAGE(m_Ammo, WeapPickup); // flashes a weapon pickup record
-DECLARE_MESSAGE(m_Ammo, HideWeapon); // hides the weapon, ammo, and crosshair displays temporarily
-DECLARE_MESSAGE(m_Ammo, ItemPickup);
-
-DECLARE_COMMAND(m_Ammo, Slot1);
-DECLARE_COMMAND(m_Ammo, Slot2);
-DECLARE_COMMAND(m_Ammo, Slot3);
-DECLARE_COMMAND(m_Ammo, Slot4);
-DECLARE_COMMAND(m_Ammo, Slot5);
-DECLARE_COMMAND(m_Ammo, Slot6);
-DECLARE_COMMAND(m_Ammo, Slot7);
-DECLARE_COMMAND(m_Ammo, Slot8);
-DECLARE_COMMAND(m_Ammo, Slot9);
-DECLARE_COMMAND(m_Ammo, Slot10);
-DECLARE_COMMAND(m_Ammo, Close);
-DECLARE_COMMAND(m_Ammo, NextWeapon);
-DECLARE_COMMAND(m_Ammo, PrevWeapon);
-
-// width of ammo fonts
-#define AMMO_SMALL_WIDTH 10
-#define AMMO_LARGE_WIDTH 20
-
-#define HISTORY_DRAW_TIME "5"
-
-int CHudAmmo::Init(void)
-{
- gHUD.AddHudElem(this);
-
- HOOK_MESSAGE(CurWeapon);
- HOOK_MESSAGE(WeaponList);
- HOOK_MESSAGE(AmmoPickup);
- HOOK_MESSAGE(WeapPickup);
- HOOK_MESSAGE(ItemPickup);
- HOOK_MESSAGE(HideWeapon);
- HOOK_MESSAGE(AmmoX);
-
- HOOK_COMMAND("slot1", Slot1);
- HOOK_COMMAND("slot2", Slot2);
- HOOK_COMMAND("slot3", Slot3);
- HOOK_COMMAND("slot4", Slot4);
- HOOK_COMMAND("slot5", Slot5);
- HOOK_COMMAND("slot6", Slot6);
- HOOK_COMMAND("slot7", Slot7);
- HOOK_COMMAND("slot8", Slot8);
- HOOK_COMMAND("slot9", Slot9);
- HOOK_COMMAND("slot10", Slot10);
- HOOK_COMMAND("cancelselect", Close);
- HOOK_COMMAND("invnext", NextWeapon);
- HOOK_COMMAND("invprev", PrevWeapon);
-
- Reset();
-
- CVAR_CREATE( "hud_drawhistory_time", HISTORY_DRAW_TIME, 0 );
- CVAR_CREATE( "hud_fastswitch", "0", FCVAR_ARCHIVE ); // controls whether or not weapons can be selected in one keypress
-
- m_iFlags |= HUD_ACTIVE; //!!!
-
- gWR.Init();
- gHR.Init();
-
- return 1;
-};
-
-void CHudAmmo::Reset(void)
-{
- m_fFade = 0;
- m_iFlags |= HUD_ACTIVE; //!!!
-
- gpActiveSel = NULL;
- gHUD.m_iHideHUDDisplay = 0;
-
- gWR.Reset();
- gHR.Reset();
-
- m_customCrosshair=0;
- // VidInit();
-
-}
-
-int CHudAmmo::VidInit(void)
-{
- // Load sprites for buckets (top row of weapon menu)
- m_HUD_bucket0 = gHUD.GetSpriteIndex( "bucket1" );
- m_HUD_selection = gHUD.GetSpriteIndex( "selection" );
-
- ghsprBuckets = gHUD.GetSprite(m_HUD_bucket0);
- giBucketWidth = gHUD.GetSpriteRect(m_HUD_bucket0).right - gHUD.GetSpriteRect(m_HUD_bucket0).left;
- giBucketHeight = gHUD.GetSpriteRect(m_HUD_bucket0).bottom - gHUD.GetSpriteRect(m_HUD_bucket0).top;
-
- gHR.iHistoryGap = max( gHR.iHistoryGap, gHUD.GetSpriteRect(m_HUD_bucket0).bottom - gHUD.GetSpriteRect(m_HUD_bucket0).top);
-
- // If we've already loaded weapons, let's get new sprites
- gWR.LoadAllWeaponSprites();
-
- if (ScreenWidth() >= 640)
- {
- giABWidth = 20;
- giABHeight = 4;
- }
- else
- {
- giABWidth = 10;
- giABHeight = 2;
- }
-
- return 1;
-}
-
-//
-// Think:
-// Used for selection of weapon menu item.
-//
-
-void CHudAmmo::Think(void)
-{
- if ( gHUD.m_fPlayerDead )
- return;
-
- if ( gHUD.m_iWeaponBits != gWR.iOldWeaponBits )
- {
- gWR.iOldWeaponBits = gHUD.m_iWeaponBits;
- bool droppedCurrent = false;
-
- for (int i = MAX_WEAPONS-1; i > 0; i-- )
- {
- WEAPON *p = gWR.GetWeapon(i);
-
- if ( p )
- {
- if ( gHUD.m_iWeaponBits & ( 1 << p->iId ) )
- gWR.PickupWeapon( p );
- else
- gWR.DropWeapon( p );
- }
- }
- }
- if ( (int)CVAR_GET_FLOAT(kvCustomCrosshair) != m_customCrosshair ) {
- m_customCrosshair=(int)CVAR_GET_FLOAT(kvCustomCrosshair);
- for ( int i=0; i < MAX_WEAPONS; i++ ) {
- WEAPON *weapon = gWR.GetWeapon(i);
- if ( weapon ) {
- gWR.LoadWeaponSprites(weapon, m_customCrosshair);
- if ( gHUD.GetHUDPlayMode() != PLAYMODE_READYROOM && gHUD.GetCurrentWeaponID() == weapon->iId ) {
- gHUD.SetCurrentCrosshair(weapon->hCrosshair, weapon->rcCrosshair, 255, 255, 255);
- }
- }
- }
-
- }
-
- if(gHUD.GetIsAlien()) //check for hive death causing loss of current weapon
- {
- WEAPON* currentWeapon = gWR.GetWeapon(gHUD.GetCurrentWeaponID());
- if(!gWR.IsSelectable(currentWeapon)) //current weapon isn't valid
- {
- gWR.SetValidWeapon(); //get best option
- }
- }
-
- if (!gpActiveSel)
- return;
-
- // has the player selected one?
- if (gHUD.m_iKeyBits & IN_ATTACK)
- {
- if (gpActiveSel != (WEAPON *)1)
- {
- gWR.SetCurrentWeapon(gpActiveSel);
- }
-
- gpLastSel = gpActiveSel;
- gpActiveSel = NULL;
- gHUD.m_iKeyBits &= ~IN_ATTACK;
-
- const char* theSound = AvHSHUGetCommonSoundName(gHUD.GetIsAlien(), WEAPON_SOUND_SELECT);
- gHUD.PlayHUDSound(theSound, kHUDSoundVolume);
- }
-}
-
-
-//------------------------------------------------------------------------
-// Message Handlers
-//------------------------------------------------------------------------
-
-//
-// AmmoX -- Update the count of a known type of ammo
-//
-int CHudAmmo::MsgFunc_AmmoX(const char *pszName, int iSize, void *pbuf)
-{
- int iIndex, iCount;
- NetMsg_AmmoX( pbuf, iSize, iIndex, iCount );
- gWR.SetAmmo( iIndex, abs(iCount) );
-
- return 1;
-}
-
-int CHudAmmo::MsgFunc_AmmoPickup( const char *pszName, int iSize, void *pbuf )
-{
- int iIndex, iCount;
- NetMsg_AmmoPickup( pbuf, iSize, iIndex, iCount );
-
- // Add ammo to the history
- gHR.AddToHistory( HISTSLOT_AMMO, iIndex, abs(iCount) );
-
- return 1;
-}
-
-int CHudAmmo::MsgFunc_WeapPickup( const char *pszName, int iSize, void *pbuf )
-{
- int iIndex;
- NetMsg_WeapPickup( pbuf, iSize, iIndex );
-
- // Add the weapon to the history
- gHR.AddToHistory( HISTSLOT_WEAP, iIndex );
-
- return 1;
-}
-
-int CHudAmmo::MsgFunc_ItemPickup( const char *pszName, int iSize, void *pbuf )
-{
- string szName;
- NetMsg_ItemPickup( pbuf, iSize, szName );
-
- // Add the weapon to the history
- gHR.AddToHistory( HISTSLOT_ITEM, szName.c_str() );
-
- return 1;
-}
-
-
-int CHudAmmo::MsgFunc_HideWeapon( const char *pszName, int iSize, void *pbuf )
-{
- NetMsg_HideWeapon( pbuf, iSize, gHUD.m_iHideHUDDisplay );
-
- if (gEngfuncs.IsSpectateOnly())
- return 1;
- if ( gHUD.m_iHideHUDDisplay & ( HIDEHUD_WEAPONS | HIDEHUD_ALL ) )
- {
- static wrect_t nullrc;
- gpActiveSel = NULL;
- gHUD.SetCurrentCrosshair( 0, nullrc, 0, 0, 0 );
- }
- else
- {
- if ( m_pWeapon )
- gHUD.SetCurrentCrosshair( m_pWeapon->hCrosshair, m_pWeapon->rcCrosshair, 255, 255, 255 );
- }
-
- return 1;
-}
-
-//
-// CurWeapon: Update hud state with the current weapon and clip count. Ammo
-// counts are updated with AmmoX. Server assures that the Weapon ammo type
-// numbers match a real ammo type.
-//
-int CHudAmmo::MsgFunc_CurWeapon(const char *pszName, int iSize, void *pbuf )
-{
- static wrect_t nullrc;
-
- int iState, iId, iClip;
- NetMsg_CurWeapon( pbuf, iSize, iState, iId, iClip );
-
- if ( iId < 1 ) //signal kills crosshairs if this condition is met...
- {
- gHUD.SetCurrentCrosshair(0, nullrc, 0, 0, 0);
- return 0;
- }
-
- if ( g_iUser1 != OBS_IN_EYE )
- {
- if ( iId == -1 && iClip == -1 ) //this conditional is never true due to iId < 1 check above!
- {
- gHUD.m_fPlayerDead = TRUE;
- gpActiveSel = NULL;
- return 1;
- }
-
- gHUD.m_fPlayerDead = FALSE;
- }
-
- WEAPON *pWeapon = gWR.GetWeapon( iId );
- if( pWeapon == NULL ) //don't have the weapon described in our resource list
- { return 0; }
-
- bool bOnTarget = (iState & WEAPON_ON_TARGET) != 0; //used to track autoaim state
- bool bIsCurrent = (iState & WEAPON_IS_CURRENT) != 0;
- pWeapon->iEnabled = (iState & WEAPON_IS_ENABLED) != 0 ? TRUE : FALSE;
- pWeapon->iClip = abs(iClip);
-
- // Ensure that movement is enabled/disabled according to weapons
- if (iId == 22 || iId == 11 || iId == 21)
- {
- gCanMove = pWeapon->iEnabled;
- }
-
- if( !bIsCurrent )
- { return 1; }
-
- m_pWeapon = pWeapon;
-
- if ( !(gHUD.m_iHideHUDDisplay & ( HIDEHUD_WEAPONS | HIDEHUD_ALL )) )
- {
- gHUD.SetCurrentCrosshair(m_pWeapon->hCrosshair, m_pWeapon->rcCrosshair, 255, 255, 255);
-
-/* if ( gHUD.m_iFOV >= 90 )
- { // normal crosshairs
- if (bOnTarget && m_pWeapon->hAutoaim)
- gHUD.SetCurrentCrosshair(m_pWeapon->hAutoaim, m_pWeapon->rcAutoaim, 255, 255, 255);
- else
- gHUD.SetCurrentCrosshair(m_pWeapon->hCrosshair, m_pWeapon->rcCrosshair, 255, 255, 255);
- }
- else
- { // zoomed crosshairs
- if (bOnTarget && m_pWeapon->hZoomedAutoaim)
- gHUD.SetCurrentCrosshair(m_pWeapon->hZoomedAutoaim, m_pWeapon->rcZoomedAutoaim, 255, 255, 255);
- else
- gHUD.SetCurrentCrosshair(m_pWeapon->hZoomedCrosshair, m_pWeapon->rcZoomedCrosshair, 255, 255, 255);
- }*/
- }
-
- m_fFade = 200.0f; //!!!
- m_iFlags |= HUD_ACTIVE;
-
- return 1;
-}
-
-//
-// WeaponList -- Tells the hud about a new weapon type.
-//
-int CHudAmmo::MsgFunc_WeaponList(const char *pszName, int iSize, void *pbuf )
-{
- WeaponList weapon_data;
- NetMsg_WeaponList( pbuf, iSize, weapon_data );
-
- WEAPON Weapon;
- memset( &Weapon, 0, sizeof(WEAPON) );
-
- strcpy( Weapon.szName, weapon_data.weapon_name.c_str() );
- Weapon.iAmmoType = weapon_data.ammo1_type;
- Weapon.iMax1 = weapon_data.ammo1_max_amnt == 255 ? -1 : weapon_data.ammo1_max_amnt;
- Weapon.iAmmo2Type = weapon_data.ammo2_type;
- Weapon.iMax2 = weapon_data.ammo2_max_amnt == 255 ? -1 : weapon_data.ammo2_max_amnt;
- Weapon.iSlot = weapon_data.bucket;
- Weapon.iSlotPos = weapon_data.bucket_pos;
- Weapon.iId = weapon_data.bit_index;
- Weapon.iFlags = weapon_data.flags;
- Weapon.iClip = 0;
- // : 497 - default value for enable state
- Weapon.iEnabled = 0;
-
- gWR.AddWeapon( &Weapon );
- return 1;
-}
-
-//------------------------------------------------------------------------
-// Command Handlers
-//------------------------------------------------------------------------
-// Slot button pressed
-void CHudAmmo::SlotInput( int iSlot )
-{
- // Let the Viewport use it first, for menus
- if ( gViewPort && gViewPort->SlotInput( iSlot ) )
- return;
-
- gWR.SelectSlot( iSlot, FALSE, 1 );
-}
-
-void CHudAmmo::UserCmd_Slot1(void)
-{
- SlotInput( 0 );
-}
-
-void CHudAmmo::UserCmd_Slot2(void)
-{
- SlotInput( 1 );
-}
-
-void CHudAmmo::UserCmd_Slot3(void)
-{
- SlotInput( 2 );
-}
-
-void CHudAmmo::UserCmd_Slot4(void)
-{
- SlotInput( 3 );
-}
-
-void CHudAmmo::UserCmd_Slot5(void)
-{
- SlotInput( 4 );
-}
-
-void CHudAmmo::UserCmd_Slot6(void)
-{
- SlotInput( 5 );
-}
-
-void CHudAmmo::UserCmd_Slot7(void)
-{
- SlotInput( 6 );
-}
-
-void CHudAmmo::UserCmd_Slot8(void)
-{
- SlotInput( 7 );
-}
-
-void CHudAmmo::UserCmd_Slot9(void)
-{
- SlotInput( 8 );
-}
-
-void CHudAmmo::UserCmd_Slot10(void)
-{
- SlotInput( 9 );
-}
-
-void CHudAmmo::UserCmd_Close(void)
-{
- if (gpActiveSel)
- {
- gpLastSel = gpActiveSel;
- gpActiveSel = NULL;
-
- const char* theSound = AvHSHUGetCommonSoundName(gHUD.GetIsAlien(), WEAPON_SOUND_HUD_OFF);
- gHUD.PlayHUDSound(theSound, kHUDSoundVolume);
- }
-}
-
-
-// Selects the next item in the weapon menu
-void CHudAmmo::UserCmd_NextWeapon(void)
-{
- if(gHUD.GetInTopDownMode())
- {
- AvHScrollHandler::ScrollHeightUp();
- }
-
- if ( gHUD.m_fPlayerDead || (gHUD.m_iHideHUDDisplay & (HIDEHUD_WEAPONS | HIDEHUD_ALL)) )
- return;
-
- if ( !gpActiveSel || gpActiveSel == (WEAPON*)1 )
- gpActiveSel = m_pWeapon;
-
- int pos = 0;
- int slot = 0;
- if ( gpActiveSel )
- {
- pos = gpActiveSel->iSlotPos + 1;
- slot = gpActiveSel->iSlot;
- }
-
- for ( int loop = 0; loop <= 1; loop++ )
- {
- for ( ; slot < MAX_WEAPON_SLOTS; slot++ )
- {
- for ( ; pos < MAX_WEAPON_POSITIONS; pos++ )
- {
- WEAPON *wsp = gWR.GetWeaponSlot( slot, pos );
-
- if (gWR.IsSelectable(wsp))
- {
- gpActiveSel = wsp;
- return;
- }
- }
-
- pos = 0;
- }
-
- slot = 0; // start looking from the first slot again
- }
-
- gpActiveSel = NULL;
-}
-
-// Selects the previous item in the menu
-void CHudAmmo::UserCmd_PrevWeapon(void)
-{
- if(gHUD.GetInTopDownMode())
- {
- AvHScrollHandler::ScrollHeightDown();
- }
-
- if ( gHUD.m_fPlayerDead || (gHUD.m_iHideHUDDisplay & (HIDEHUD_WEAPONS | HIDEHUD_ALL)) )
- return;
-
- if ( !gpActiveSel || gpActiveSel == (WEAPON*)1 )
- gpActiveSel = m_pWeapon;
-
- int pos = MAX_WEAPON_POSITIONS-1;
- int slot = MAX_WEAPON_SLOTS-1;
- if ( gpActiveSel )
- {
- pos = gpActiveSel->iSlotPos - 1;
- slot = gpActiveSel->iSlot;
- }
-
- for ( int loop = 0; loop <= 1; loop++ )
- {
- for ( ; slot >= 0; slot-- )
- {
- for ( ; pos >= 0; pos-- )
- {
- WEAPON *wsp = gWR.GetWeaponSlot( slot, pos );
-
- if (gWR.IsSelectable(wsp))
- {
- gpActiveSel = wsp;
- return;
- }
- }
-
- pos = MAX_WEAPON_POSITIONS-1;
- }
-
- slot = MAX_WEAPON_SLOTS-1;
- }
-
- gpActiveSel = NULL;
-}
-
-void CHudAmmo::SetCurrentClip(int inClip)
-{
- if(this->m_pWeapon)
- {
- this->m_pWeapon->iClip = inClip;
- }
-}
-
-//-------------------------------------------------------------------------
-// Drawing code
-//-------------------------------------------------------------------------
-
-int CHudAmmo::Draw(float flTime)
-{
- int a, x, y, r, g, b;
- int AmmoWidth;
-
- if (!(gHUD.m_iWeaponBits & (1<<(WEAPON_SUIT)) ))
- return 1;
-
- if (/*!gHUD.GetIsAlive() ||*/ (gHUD.m_iHideHUDDisplay & ( HIDEHUD_WEAPONS | HIDEHUD_ALL )) )
- return 1;
-
- // Draw Weapon Menu
- DrawWList(flTime);
-
- // Draw ammo pickup history
- gHR.DrawAmmoHistory( flTime );
-
- if (!(m_iFlags & HUD_ACTIVE))
- return 0;
-
- if (!m_pWeapon)
- return 0;
-
- WEAPON *pw = m_pWeapon; // shorthand
-
- // SPR_Draw Ammo
- if ((pw->iAmmoType < 0) && (pw->iAmmo2Type < 0))
- return 0;
-
-
- int iFlags = DHN_DRAWZERO; // draw 0 values
-
- AmmoWidth = gHUD.GetSpriteRect(gHUD.m_HUD_number_0).right - gHUD.GetSpriteRect(gHUD.m_HUD_number_0).left;
-
- a = (int) max( MIN_ALPHA, m_fFade );
-
- if (m_fFade > 0)
- m_fFade -= (gHUD.m_flTimeDelta * 20);
-
- gHUD.GetPrimaryHudColor(r, g, b);
-
- ScaleColors(r, g, b, a );
-
- int theViewport[4];
- gHUD.GetViewport(theViewport);
-
- // Does this weapon have a clip?
- y = theViewport[1] + theViewport[3] - gHUD.m_iFontHeight - gHUD.m_iFontHeight/2;
-
- // Does weapon have any ammo at all?
- if (m_pWeapon->iAmmoType > 0)
- {
- int iIconWidth = m_pWeapon->rcAmmo.right - m_pWeapon->rcAmmo.left;
-
- if (pw->iClip >= 0)
- {
- // room for the number and the '|' and the current ammo
-
- x = theViewport[0] + theViewport[2] - (8 * AmmoWidth) - iIconWidth;
- x = gHUD.DrawHudNumber(x, y, iFlags | DHN_3DIGITS, pw->iClip, r, g, b);
-
- wrect_t rc;
- rc.top = 0;
- rc.left = 0;
- rc.right = AmmoWidth;
- rc.bottom = 100;
-
- int iBarWidth = AmmoWidth/10;
-
- x += AmmoWidth/2;
-
- gHUD.GetPrimaryHudColor(r, g, b);
-
- // draw the | bar
- FillRGBA(x, y, iBarWidth, gHUD.m_iFontHeight, r, g, b, a);
-
- x += iBarWidth + AmmoWidth/2;;
-
- // GL Seems to need this
- ScaleColors(r, g, b, a );
- x = gHUD.DrawHudNumber(x, y, iFlags | DHN_3DIGITS, gWR.CountAmmo(pw->iAmmoType), r, g, b);
-
-
- }
- else
- {
- // SPR_Draw a bullets only line
- x = theViewport[0] + theViewport[2] - 4 * AmmoWidth - iIconWidth;
- x = gHUD.DrawHudNumber(x, y, iFlags | DHN_3DIGITS, gWR.CountAmmo(pw->iAmmoType), r, g, b);
- }
-
- // Draw the ammo Icon
- int iOffset = (m_pWeapon->rcAmmo.bottom - m_pWeapon->rcAmmo.top)/8;
- SPR_Set(m_pWeapon->hAmmo, r, g, b);
- SPR_DrawAdditive(0, x, y - iOffset, &m_pWeapon->rcAmmo);
- }
-
- // Does weapon have seconday ammo?
- if (pw->iAmmo2Type > 0)
- {
- int iIconWidth = m_pWeapon->rcAmmo2.right - m_pWeapon->rcAmmo2.left;
-
- // Do we have secondary ammo?
- if ((pw->iAmmo2Type != 0) && (gWR.CountAmmo(pw->iAmmo2Type) > 0))
- {
- y -= gHUD.m_iFontHeight + gHUD.m_iFontHeight/4;
- x = theViewport[0] + theViewport[2] - 4 * AmmoWidth - iIconWidth;
- x = gHUD.DrawHudNumber(x, y, iFlags|DHN_3DIGITS, gWR.CountAmmo(pw->iAmmo2Type), r, g, b);
-
- // Draw the ammo Icon
- SPR_Set(m_pWeapon->hAmmo2, r, g, b);
- int iOffset = (m_pWeapon->rcAmmo2.bottom - m_pWeapon->rcAmmo2.top)/8;
- SPR_DrawAdditive(0, x, y - iOffset, &m_pWeapon->rcAmmo2);
- }
- }
- return 1;
-}
-
-
-//
-// Draws the ammo bar on the hud
-//
-int DrawBar(int x, int y, int width, int height, float f)
-{
- int r, g, b;
-
- if (f < 0)
- f = 0;
- if (f > 1)
- f = 1;
-
- if (f)
- {
- int w = f * width;
-
- // Always show at least one pixel if we have ammo.
- if (w <= 0)
- w = 1;
- UnpackRGB(r, g, b, RGB_GREENISH);
- FillRGBA(x, y, w, height, r, g, b, 255);
- x += w;
- width -= w;
- }
-
- gHUD.GetPrimaryHudColor(r, g, b);
- FillRGBA(x, y, width, height, r, g, b, 128);
-
- return (x + width);
-}
-
-
-
-void DrawAmmoBar(WEAPON *p, int x, int y, int width, int height)
-{
- if ( !p )
- return;
-
- if (p->iAmmoType != -1)
- {
- if (!gWR.CountAmmo(p->iAmmoType))
- return;
-
- float f = (float)gWR.CountAmmo(p->iAmmoType)/(float)p->iMax1;
-
- x = DrawBar(x, y, width, height, f);
-
-
- // Do we have secondary ammo too?
-
- if (p->iAmmo2Type != -1)
- {
- f = (float)gWR.CountAmmo(p->iAmmo2Type)/(float)p->iMax2;
-
- x += 5; //!!!
-
- DrawBar(x, y, width, height, f);
- }
- }
-}
-
-
-
-
-//
-// Draw Weapon Menu
-//
-int CHudAmmo::DrawWList(float flTime)
-{
- int r,g,b,x,y,a,i;
-
- if ( !gpActiveSel )
- {
- gHUD.SetSelectingWeaponID(-1);
- return 0;
- }
-
- int iActiveSlot;
-
- if ( gpActiveSel == (WEAPON *)1 )
- iActiveSlot = -1; // current slot has no weapons
- else
- iActiveSlot = gpActiveSel->iSlot;
-
- x = 10; //!!!
- y = 10; //!!!
-
-
- // Ensure that there are available choices in the active slot
- if ( iActiveSlot > 0 )
- {
- if ( !gWR.GetFirstPos( iActiveSlot ) )
- {
- gpActiveSel = (WEAPON *)1;
- iActiveSlot = -1;
- }
- }
-
- // Draw top line
- for ( i = 0; i < MAX_WEAPON_SLOTS; i++ )
- {
- int iWidth;
-
- gHUD.GetPrimaryHudColor(r, g, b);
-
- if ( iActiveSlot == i )
- a = 255;
- else
- a = 192;
-
- ScaleColors(r, g, b, 255);
- SPR_Set(gHUD.GetSprite(m_HUD_bucket0 + i), r, g, b );
-
- // make active slot wide enough to accomodate gun pictures
- if ( i == iActiveSlot )
- {
- WEAPON *p = gWR.GetFirstPos(iActiveSlot);
- if ( p )
- iWidth = p->rcActive.right - p->rcActive.left;
- else
- iWidth = giBucketWidth;
- }
- else
- iWidth = giBucketWidth;
-
- SPR_DrawAdditive(0, x, y, &gHUD.GetSpriteRect(m_HUD_bucket0 + i));
-
- x += iWidth + 5;
- }
-
-
- a = 128; //!!!
- x = 10;
-
- // Draw all of the buckets
- for (i = 0; i < MAX_WEAPON_SLOTS; i++)
- {
- y = giBucketHeight + 10;
-
- // If this is the active slot, draw the bigger pictures,
- // otherwise just draw boxes
- if ( i == iActiveSlot )
- {
- WEAPON *p = gWR.GetFirstPos( i );
- int iWidth = giBucketWidth;
- if ( p )
- iWidth = p->rcActive.right - p->rcActive.left;
-
- for ( int iPos = 0; iPos < MAX_WEAPON_POSITIONS; iPos++ )
- {
- p = gWR.GetWeaponSlot( i, iPos );
-
- if ( !p || !p->iId )
- continue;
-
- // Preserve red/yellow depending on whether it has ammo or not
- if(!gWR.IsEnabled(p))
- {
- UnpackRGB(r,g,b, RGB_REDISH);
- ScaleColors(r, g, b, 128);
- }
- else
- {
- gHUD.GetPrimaryHudColor(r, g, b);
- ScaleColors(r, g, b, 192);
- }
-
- if ( gpActiveSel == p )
- {
- SPR_Set(p->hActive, r, g, b );
- SPR_DrawAdditive(0, x, y, &p->rcActive);
-
- SPR_Set(gHUD.GetSprite(m_HUD_selection), r, g, b );
- SPR_DrawAdditive(0, x, y, &gHUD.GetSpriteRect(m_HUD_selection));
-
- // Lookup iID for helptext
- gHUD.SetSelectingWeaponID(p->iId, r, g, b);
- }
- else
- {
- // Draw Weapon if Red if no ammo
-
- //if (gWR.IsSelectable(p))
- // ScaleColors(r, g, b, 192);
- //else
- //{
- // UnpackRGB(r,g,b, RGB_REDISH);
- // ScaleColors(r, g, b, 128);
- //}
-
- SPR_Set( p->hInactive, r, g, b );
- SPR_DrawAdditive( 0, x, y, &p->rcInactive );
- }
-
- // Draw Ammo Bar
-
- DrawAmmoBar(p, x + giABWidth/2, y, giABWidth, giABHeight);
-
- y += p->rcActive.bottom - p->rcActive.top + 5;
- }
-
- x += iWidth + 5;
-
- }
- else
- {
- // Draw Row of weapons.
- gHUD.GetPrimaryHudColor(r, g, b);
-
- for ( int iPos = 0; iPos < MAX_WEAPON_POSITIONS; iPos++ )
- {
- WEAPON *p = gWR.GetWeaponSlot( i, iPos );
-
- if ( !p || !p->iId )
- continue;
-
- if ( gWR.IsEnabled(p) )
- {
- gHUD.GetPrimaryHudColor(r, g, b);
- a = 128;
- }
- else
- {
- UnpackRGB(r,g,b, RGB_REDISH);
- a = 96;
- }
-
- FillRGBA( x, y, giBucketWidth, giBucketHeight, r, g, b, a );
-
- y += giBucketHeight + 5;
- }
-
- x += giBucketWidth + 5;
- }
- }
-
- return 1;
-
-}
-
-
-/* =================================
- GetSpriteList
-
-Finds and returns the matching
-sprite name 'psz' and resolution 'iRes'
-in the given sprite list 'pList'
-iCount is the number of items in the pList
-================================= */
-client_sprite_t *GetSpriteList(client_sprite_t *pList, const char *psz, int iRes, int iCount)
-{
- if (!pList)
- return NULL;
-
- int i = iCount;
- client_sprite_t *p = pList;
-
- while(i--)
- {
- if ((!strcmp(psz, p->szName)) && (p->iRes == iRes))
- return p;
- p++;
- }
-
- return NULL;
-}
+/***
+*
+* Copyright (c) 1999, Valve LLC. All rights reserved.
+*
+* This product contains software technology licensed from Id
+* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
+* All Rights Reserved.
+*
+* Use, distribution, and modification of this source code and/or resulting
+* object code is restricted to non-commercial enhancements to products from
+* Valve LLC. All other use, distribution, or modification is prohibited
+* without written permission from Valve LLC.
+*
+****/
+//
+// Ammo.cpp
+//
+// implementation of CHudAmmo class
+//
+
+#include "hud.h"
+#include "cl_util.h"
+
+#include
+#include
+
+#include "ammohistory.h"
+#include "vgui_TeamFortressViewport.h"
+#include "mod/AvHClientVariables.h"
+#include "mod/AvHSharedUtil.h"
+#include "mod/AvHScrollHandler.h"
+#include "mod/AvHNetworkMessages.h"
+
+WEAPON *gpActiveSel; // NULL means off, 1 means just the menu bar, otherwise
+ // this points to the active weapon menu item
+WEAPON *gpLastSel; // Last weapon menu selection
+
+bool HUD_GetWeaponEnabled(int inID);
+client_sprite_t *GetSpriteList(client_sprite_t *pList, const char *psz, int iRes, int iCount);
+
+WeaponsResource gWR;
+
+int g_weaponselect = 0;
+
+extern bool gCanMove;
+
+void IN_AttackDownForced(void);
+void IN_AttackUpForced(void);
+void IN_Attack2Down(void);
+void IN_Attack2Up(void);
+void IN_ReloadDown();
+void IN_ReloadUp();
+bool CheckInAttack(void);
+
+//Equivalent to DECLARE_COMMAND(lastinv,LastInv) except we use gWR instead of gHud
+void __CmdFunc_LastInv(void)
+{ gWR.UserCmd_LastInv(); }
+
+// +movement
+void __CmdFunc_MovementOn(void)
+{ gWR.UserCmd_MovementOn(); }
+void __CmdFunc_MovementOff(void)
+{ gWR.UserCmd_MovementOff(); }
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+WeaponsResource::WeaponsResource(void) : lastWeapon(NULL), iOldWeaponBits(0) {}
+WeaponsResource::~WeaponsResource(void) {}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+void WeaponsResource::Init( void )
+{
+ memset( rgWeapons, 0, sizeof(WEAPON)*MAX_WEAPONS );
+ Reset();
+ HOOK_COMMAND("lastinv", LastInv);
+ // +movement
+ HOOK_COMMAND("+movement", MovementOn);
+ HOOK_COMMAND("-movement", MovementOff);
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+void WeaponsResource::Reset( void )
+{
+ lastWeapon = NULL;
+ iOldWeaponBits = 0;
+ memset( rgSlots, 0, sizeof(WEAPON*)*MAX_WEAPON_SLOTS*MAX_WEAPON_POSITIONS );
+ memset( riAmmo, 0, sizeof(int)*MAX_AMMO_TYPES );
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+void WeaponsResource :: LoadAllWeaponSprites( void )
+{
+ int customCrosshairs=CVAR_GET_FLOAT(kvCustomCrosshair);
+ for (int i = 0; i < MAX_WEAPONS; i++)
+ {
+ if ( rgWeapons[i].iId )
+ LoadWeaponSprites( &rgWeapons[i], customCrosshairs );
+ }
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+inline void LoadWeaponSprite( client_sprite_t* ptr, HSPRITE& sprite, wrect_t& bounds )
+{
+ if( ptr )
+ {
+ string name( "sprites/" );
+ name.append( ptr->szSprite );
+ name.append( ".spr" );
+ sprite = SPR_Load(name.c_str());
+ bounds = ptr->rc;
+ }
+ else
+ {
+ sprite = NULL;
+ }
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+void WeaponsResource :: LoadWeaponSprites( WEAPON *pWeapon, int custom )
+{
+ if ( custom < 0 || custom > 4 )
+ custom=1;
+
+ int resolutions[6] = { 320, 640, 800, 1024, 1280, 1600};
+ const int numRes=6;
+ int i=0, j=0, iRes=320;
+ int screenWidth=ScreenWidth();
+
+ for ( j=0; j < numRes; j++ ) {
+ if ( screenWidth == resolutions[j] ) {
+ iRes=resolutions[j];
+ break;
+ }
+ if ( j > 0 && screenWidth > resolutions[j-1] && screenWidth < resolutions[j] ) {
+ iRes=resolutions[j-1];
+ break;
+ }
+ }
+
+ char sz[128];
+
+ if ( !pWeapon )
+ return;
+
+ memset( &pWeapon->rcCrosshair, 0, sizeof(wrect_t) );
+ memset( &pWeapon->rcActive, 0, sizeof(wrect_t) );
+ memset( &pWeapon->rcInactive, 0, sizeof(wrect_t) );
+ memset( &pWeapon->rcAmmo, 0, sizeof(wrect_t) );
+ memset( &pWeapon->rcAmmo2, 0, sizeof(wrect_t) );
+ pWeapon->hCrosshair =0;
+ pWeapon->hInactive = 0;
+ pWeapon->hActive = 0;
+ pWeapon->hAmmo = 0;
+ pWeapon->hAmmo2 = 0;
+
+ sprintf(sz, "sprites/%s.txt", pWeapon->szName);
+ client_sprite_t *pList = SPR_GetList(sz, &i);
+
+ if (!pList)
+ {
+ ASSERT(pList);
+ return;
+ }
+
+ char crosshairName[32];
+ sprintf(crosshairName, "crosshair_%d", custom);
+ for ( j=numRes-1; j>=0; j-- ) {
+ if ( resolutions[j] <= iRes ) {
+ if( pWeapon->hCrosshair == NULL )
+ LoadWeaponSprite( GetSpriteList( pList, crosshairName, resolutions[j], i ), pWeapon->hCrosshair, pWeapon->rcCrosshair );
+ if( pWeapon->hCrosshair == NULL && custom != 0 )
+ LoadWeaponSprite( GetSpriteList( pList, "crosshair_0", resolutions[j], i ), pWeapon->hCrosshair, pWeapon->rcCrosshair );
+
+
+ if( pWeapon->hInactive == NULL )
+ LoadWeaponSprite( GetSpriteList( pList, "weapon", resolutions[j], i ), pWeapon->hInactive, pWeapon->rcInactive );
+
+ if( pWeapon->hActive == NULL )
+ LoadWeaponSprite( GetSpriteList( pList, "weapon_s", resolutions[j], i ), pWeapon->hActive, pWeapon->rcActive );
+
+ if( pWeapon->hAmmo == NULL )
+ LoadWeaponSprite( GetSpriteList( pList, "ammo", resolutions[j], i ), pWeapon->hAmmo, pWeapon->rcAmmo );
+
+ if( pWeapon->hAmmo2 == NULL )
+ LoadWeaponSprite( GetSpriteList( pList, "ammo2", resolutions[j], i ), pWeapon->hAmmo2, pWeapon->rcAmmo2 );
+ }
+ }
+
+ if( pWeapon->hActive || pWeapon->hInactive || pWeapon->hAmmo || pWeapon->hAmmo2 )
+ { gHR.iHistoryGap = max( gHR.iHistoryGap, pWeapon->rcActive.bottom - pWeapon->rcActive.top ); }
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+WEAPON* WeaponsResource::GetWeapon( int iId )
+{
+ if( iId < 0 || iId >= MAX_WEAPONS ) { return NULL; }
+ return rgWeapons[iId].iId ? &rgWeapons[iId] : NULL;
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+WEAPON* WeaponsResource::GetWeaponSlot( int slot, int pos ) { return rgSlots[slot][pos]; }
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+WEAPON* WeaponsResource::GetFirstPos( int iSlot )
+{
+ WEAPON *returnVal = NULL;
+ ASSERT( iSlot < MAX_WEAPON_SLOTS && iSlot >= 0 );
+
+ for( int counter = 0; counter < MAX_WEAPON_POSITIONS; ++counter )
+ {
+ if( this->IsSelectable(rgSlots[iSlot][counter]) )
+ {
+ returnVal = rgSlots[iSlot][counter];
+ break;
+ }
+ }
+
+ return returnVal;
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+WEAPON* WeaponsResource::GetNextActivePos( int iSlot, int iSlotPos )
+{
+ WEAPON* returnVal = NULL;
+ ASSERT( iSlot < MAX_WEAPON_SLOTS && iSlot >= 0 );
+ ASSERT( iSlotPos >= 0 );
+
+ for( int counter = iSlotPos+1; counter < MAX_WEAPON_POSITIONS; ++counter )
+ {
+ if( this->IsSelectable(rgSlots[iSlot][counter]) )
+ {
+ returnVal = rgSlots[iSlot][counter];
+ break;
+ }
+ }
+
+ return returnVal;
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+bool WeaponsResource::IsEnabled(WEAPON* p)
+{
+ if( p == NULL ) { return false; }
+ return HUD_GetWeaponEnabled(p->iId) && this->HasAmmo(p);
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+bool WeaponsResource::IsSelectable(WEAPON* p)
+{
+ if( p == NULL ) { return false; }
+ return HUD_GetWeaponEnabled(p->iId);
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+bool WeaponsResource::HasAmmo( WEAPON* p )
+{
+ if( p == NULL) { return false; }
+ //note : if max ammo capacity is -1, this has always returned true in spite of not
+ // having actual ammo -- KGP
+ return (p->iAmmoType == -1) || (p->iMax1 == -1) || p->iClip > 0 || CountAmmo(p->iAmmoType)
+ || CountAmmo(p->iAmmo2Type) || (p->iFlags & WEAPON_FLAGS_SELECTIONEMPTY );
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+int WeaponsResource::CountAmmo( int iId )
+{
+ ASSERT( iId < MAX_AMMO_TYPES );
+ if( iId < 0 ) return 0;
+ return riAmmo[iId];
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+int WeaponsResource::GetAmmo( int iId )
+{
+ ASSERT( iId < MAX_AMMO_TYPES && iId > -1 );
+ return riAmmo[iId];
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+void WeaponsResource::SetAmmo( int iId, int iCount )
+{
+ ASSERT( iId < MAX_AMMO_TYPES && iId > -1 );
+ riAmmo[iId] = iCount;
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+HSPRITE* WeaponsResource::GetAmmoPicFromWeapon( int iAmmoId, wrect_t& rect )
+{
+ for ( int i = 0; i < MAX_WEAPONS; i++ )
+ {
+ if ( rgWeapons[i].iAmmoType == iAmmoId )
+ {
+ rect = rgWeapons[i].rcAmmo;
+ return &rgWeapons[i].hAmmo;
+ }
+ else if ( rgWeapons[i].iAmmo2Type == iAmmoId )
+ {
+ rect = rgWeapons[i].rcAmmo2;
+ return &rgWeapons[i].hAmmo2;
+ }
+ }
+
+ return NULL;
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+void WeaponsResource::AddWeapon( WEAPON *wp )
+{
+ int customCrosshairs=CVAR_GET_FLOAT(kvCustomCrosshair);
+ rgWeapons[ wp->iId ] = *wp;
+ LoadWeaponSprites( &rgWeapons[ wp->iId ], customCrosshairs);
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+void WeaponsResource::PickupWeapon( WEAPON *wp )
+{
+ rgSlots[ wp->iSlot ][ wp->iSlotPos ] = wp;
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+void WeaponsResource::DropWeapon( WEAPON *wp )
+{
+ rgSlots[ wp->iSlot ][ wp->iSlotPos ] = NULL;
+ if(lastWeapon == wp) //dropped last weapon, remove it from the list
+ { lastWeapon = NULL; }
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+void WeaponsResource::DropAllWeapons( void )
+{
+ for ( int i = 0; i < MAX_WEAPONS; i++ )
+ {
+ if ( rgWeapons[i].iId )
+ DropWeapon( &rgWeapons[i] );
+ }
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+void WeaponsResource::UserCmd_LastInv(void)
+{
+ if(this->IsSelectable(this->lastWeapon))
+ {
+ this->SetCurrentWeapon(lastWeapon);
+ // : 764
+ //const char* theSound = AvHSHUGetCommonSoundName(gHUD.GetIsAlien(), WEAPON_SOUND_HUD_ON);
+ //gHUD.PlayHUDSound(theSound, kHUDSoundVolume);
+ }
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+void WeaponsResource::UserCmd_MovementOn()
+{
+ // Find out which weapon we want to trigger
+ AvHUser3 theUser3 = gHUD.GetHUDUser3();
+ int wID = -1;
+ switch(theUser3)
+ {
+ case AVH_USER3_ALIEN_PLAYER1:
+ wID = AVH_ABILITY_LEAP;
+ break;
+ case AVH_USER3_ALIEN_PLAYER3:
+ // TODO: Add flap
+ break;
+ case AVH_USER3_ALIEN_PLAYER4:
+ wID = AVH_WEAPON_BLINK;
+ break;
+ case AVH_USER3_ALIEN_PLAYER5:
+ wID = AVH_ABILITY_CHARGE;
+ break;
+ default:
+ IN_ReloadDown();
+ return;
+ }
+
+ if (wID > -1)
+ {
+ // Fetch the needed movement weapon
+ WEAPON *p = this->GetWeapon(wID);
+ if (p != NULL && this->IsSelectable(p))
+ {
+ // Send activation of ability asap
+ IN_Attack2Down();
+ }
+ }
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+void WeaponsResource::UserCmd_MovementOff()
+{
+ // Ensure that we're not activating any weapons when selected
+ IN_Attack2Up();
+ IN_ReloadUp();
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+void WeaponsResource::SetValidWeapon(void)
+{
+ WEAPON* p = this->GetFirstPos(0); //alien attack 1 or primary marine weapon
+ if(gHUD.GetIsAlien())
+ {
+ this->SetCurrentWeapon(p);
+ }
+ else
+ {
+ if(this->IsSelectable(p) && this->HasAmmo(p))
+ {
+ this->SetCurrentWeapon(p);
+ }
+ else
+ {
+ p = this->GetFirstPos(1); //pistol slot
+ if(this->IsSelectable(p) && this->HasAmmo(p))
+ {
+ this->SetCurrentWeapon(p);
+ }
+ else
+ {
+ p = this->GetFirstPos(2); //knife slot
+ this->SetCurrentWeapon(p);
+ }
+ }
+ }
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+void WeaponsResource::SetCurrentWeapon(WEAPON* newWeapon)
+{
+ WEAPON* currentWeapon = this->GetWeapon(gHUD.GetCurrentWeaponID());
+ // : 497 - Because weapon state can get out of sync, we should allow this even if the weapons are the same
+ // && newWeapon != currentWeapon
+ if( newWeapon != NULL )
+ {
+ if( newWeapon != currentWeapon )
+ { lastWeapon = currentWeapon; }
+ ServerCmd(newWeapon->szName);
+ g_weaponselect = newWeapon->iId;
+ }
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+void WeaponsResource :: SelectSlot( int iSlot, int fAdvance, int iDirection )
+{
+ if ( gHUD.m_Menu.m_fMenuDisplayed && (fAdvance == FALSE) && (iDirection == 1) )
+ { // menu is overriding slot use commands
+ gHUD.m_Menu.SelectMenuItem( iSlot + 1 ); // slots are one off the key numbers
+ return;
+ }
+
+ if ( iSlot >= MAX_WEAPON_SLOTS )
+ return;
+
+ if ( gHUD.m_fPlayerDead || gHUD.m_iHideHUDDisplay & ( HIDEHUD_WEAPONS | HIDEHUD_ALL ) )
+ return;
+
+ if (!(gHUD.m_iWeaponBits & (1<<(WEAPON_SUIT)) )) //require suit
+ return;
+
+ if ( ! ( gHUD.m_iWeaponBits & ~(1<<(WEAPON_SUIT)) )) //require something besides suit
+ return;
+
+ WEAPON *p = NULL;
+ bool fastSwitch = CVAR_GET_FLOAT( "hud_fastswitch" ) != 0;
+ if ((gpActiveSel == NULL) || (gpActiveSel == (WEAPON *)1) || (iSlot != gpActiveSel->iSlot))
+ {
+ p = GetFirstPos(iSlot);
+ const char* theSound = AvHSHUGetCommonSoundName(gHUD.GetIsAlien(), WEAPON_SOUND_HUD_ON);
+ gHUD.PlayHUDSound(theSound, kHUDSoundVolume);
+
+ if (this->IsSelectable(p) && fastSwitch) //check to see if we can use fastSwitch
+ {
+ WEAPON *p2 = GetNextActivePos( p->iSlot, p->iSlotPos );
+ if (!this->IsSelectable(p2)) //only one target in the bucket
+ {
+ this->SetCurrentWeapon(p);
+ return;
+ }
+ }
+ }
+ else
+ {
+ const char* theSound = AvHSHUGetCommonSoundName(gHUD.GetIsAlien(), WEAPON_SOUND_MOVE_SELECT);
+ gHUD.PlayHUDSound(theSound, kHUDSoundVolume);
+
+ if ( gpActiveSel )
+ p = GetNextActivePos( gpActiveSel->iSlot, gpActiveSel->iSlotPos );
+ if ( !p )
+ p = GetFirstPos( iSlot );
+ }
+
+ if (!this->IsSelectable(p)) // no valid selection found
+ {
+ // if fastSwitch is on, ignore, else turn on the menu
+ if ( !fastSwitch ) {
+ gpActiveSel = (WEAPON *)1;
+ }
+ else {
+ gpActiveSel = NULL;
+ }
+ }
+ else
+ {
+ gpActiveSel = p;
+ }
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+int giBucketHeight, giBucketWidth, giABHeight, giABWidth; // Ammo Bar width and height
+
+HSPRITE ghsprBuckets; // Sprite for top row of weapons menu
+
+DECLARE_MESSAGE(m_Ammo, CurWeapon ); // Current weapon and clip
+DECLARE_MESSAGE(m_Ammo, WeaponList); // new weapon type
+DECLARE_MESSAGE(m_Ammo, AmmoX); // update known ammo type's count
+DECLARE_MESSAGE(m_Ammo, AmmoPickup); // flashes an ammo pickup record
+DECLARE_MESSAGE(m_Ammo, WeapPickup); // flashes a weapon pickup record
+DECLARE_MESSAGE(m_Ammo, HideWeapon); // hides the weapon, ammo, and crosshair displays temporarily
+DECLARE_MESSAGE(m_Ammo, ItemPickup);
+
+DECLARE_COMMAND(m_Ammo, Slot1);
+DECLARE_COMMAND(m_Ammo, Slot2);
+DECLARE_COMMAND(m_Ammo, Slot3);
+DECLARE_COMMAND(m_Ammo, Slot4);
+DECLARE_COMMAND(m_Ammo, Slot5);
+DECLARE_COMMAND(m_Ammo, Slot6);
+DECLARE_COMMAND(m_Ammo, Slot7);
+DECLARE_COMMAND(m_Ammo, Slot8);
+DECLARE_COMMAND(m_Ammo, Slot9);
+DECLARE_COMMAND(m_Ammo, Slot10);
+DECLARE_COMMAND(m_Ammo, Close);
+DECLARE_COMMAND(m_Ammo, NextWeapon);
+DECLARE_COMMAND(m_Ammo, PrevWeapon);
+
+// width of ammo fonts
+#define AMMO_SMALL_WIDTH 10
+#define AMMO_LARGE_WIDTH 20
+
+#define HISTORY_DRAW_TIME "5"
+
+int CHudAmmo::Init(void)
+{
+ gHUD.AddHudElem(this);
+
+ HOOK_MESSAGE(CurWeapon);
+ HOOK_MESSAGE(WeaponList);
+ HOOK_MESSAGE(AmmoPickup);
+ HOOK_MESSAGE(WeapPickup);
+ HOOK_MESSAGE(ItemPickup);
+ HOOK_MESSAGE(HideWeapon);
+ HOOK_MESSAGE(AmmoX);
+
+ HOOK_COMMAND("slot1", Slot1);
+ HOOK_COMMAND("slot2", Slot2);
+ HOOK_COMMAND("slot3", Slot3);
+ HOOK_COMMAND("slot4", Slot4);
+ HOOK_COMMAND("slot5", Slot5);
+ HOOK_COMMAND("slot6", Slot6);
+ HOOK_COMMAND("slot7", Slot7);
+ HOOK_COMMAND("slot8", Slot8);
+ HOOK_COMMAND("slot9", Slot9);
+ HOOK_COMMAND("slot10", Slot10);
+ HOOK_COMMAND("cancelselect", Close);
+ HOOK_COMMAND("invnext", NextWeapon);
+ HOOK_COMMAND("invprev", PrevWeapon);
+
+ Reset();
+
+ CVAR_CREATE( "hud_drawhistory_time", HISTORY_DRAW_TIME, 0 );
+ CVAR_CREATE( "hud_fastswitch", "0", FCVAR_ARCHIVE ); // controls whether or not weapons can be selected in one keypress
+
+ m_iFlags |= HUD_ACTIVE; //!!!
+
+ gWR.Init();
+ gHR.Init();
+
+ return 1;
+};
+
+void CHudAmmo::Reset(void)
+{
+ m_fFade = 0;
+ m_iFlags |= HUD_ACTIVE; //!!!
+
+ gpActiveSel = NULL;
+ gHUD.m_iHideHUDDisplay = 0;
+
+ gWR.Reset();
+ gHR.Reset();
+
+ m_customCrosshair=0;
+ // VidInit();
+
+}
+
+int CHudAmmo::VidInit(void)
+{
+ // Load sprites for buckets (top row of weapon menu)
+ m_HUD_bucket0 = gHUD.GetSpriteIndex( "bucket1" );
+ m_HUD_selection = gHUD.GetSpriteIndex( "selection" );
+
+ ghsprBuckets = gHUD.GetSprite(m_HUD_bucket0);
+ giBucketWidth = gHUD.GetSpriteRect(m_HUD_bucket0).right - gHUD.GetSpriteRect(m_HUD_bucket0).left;
+ giBucketHeight = gHUD.GetSpriteRect(m_HUD_bucket0).bottom - gHUD.GetSpriteRect(m_HUD_bucket0).top;
+
+ gHR.iHistoryGap = max( gHR.iHistoryGap, gHUD.GetSpriteRect(m_HUD_bucket0).bottom - gHUD.GetSpriteRect(m_HUD_bucket0).top);
+
+ // If we've already loaded weapons, let's get new sprites
+ gWR.LoadAllWeaponSprites();
+
+ if (ScreenWidth() >= 640)
+ {
+ giABWidth = 20;
+ giABHeight = 4;
+ }
+ else
+ {
+ giABWidth = 10;
+ giABHeight = 2;
+ }
+
+ return 1;
+}
+
+//
+// Think:
+// Used for selection of weapon menu item.
+//
+
+void CHudAmmo::Think(void)
+{
+ if ( gHUD.m_fPlayerDead )
+ return;
+
+ if ( gHUD.m_iWeaponBits != gWR.iOldWeaponBits )
+ {
+ gWR.iOldWeaponBits = gHUD.m_iWeaponBits;
+ bool droppedCurrent = false;
+
+ for (int i = MAX_WEAPONS-1; i > 0; i-- )
+ {
+ WEAPON *p = gWR.GetWeapon(i);
+
+ if ( p )
+ {
+ if ( gHUD.m_iWeaponBits & ( 1 << p->iId ) )
+ gWR.PickupWeapon( p );
+ else
+ gWR.DropWeapon( p );
+ }
+ }
+ }
+ if ( (int)CVAR_GET_FLOAT(kvCustomCrosshair) != m_customCrosshair ) {
+ m_customCrosshair=(int)CVAR_GET_FLOAT(kvCustomCrosshair);
+ for ( int i=0; i < MAX_WEAPONS; i++ ) {
+ WEAPON *weapon = gWR.GetWeapon(i);
+ if ( weapon ) {
+ gWR.LoadWeaponSprites(weapon, m_customCrosshair);
+ if ( gHUD.GetHUDPlayMode() != PLAYMODE_READYROOM && gHUD.GetCurrentWeaponID() == weapon->iId ) {
+ gHUD.SetCurrentCrosshair(weapon->hCrosshair, weapon->rcCrosshair, 255, 255, 255);
+ }
+ }
+ }
+
+ }
+
+ if(gHUD.GetIsAlien()) //check for hive death causing loss of current weapon
+ {
+ WEAPON* currentWeapon = gWR.GetWeapon(gHUD.GetCurrentWeaponID());
+ if(!gWR.IsSelectable(currentWeapon)) //current weapon isn't valid
+ {
+ gWR.SetValidWeapon(); //get best option
+ }
+ }
+
+ if (!gpActiveSel)
+ return;
+
+ // has the player selected one?
+ if (gHUD.m_iKeyBits & IN_ATTACK)
+ {
+ if (gpActiveSel != (WEAPON *)1)
+ {
+ gWR.SetCurrentWeapon(gpActiveSel);
+ }
+
+ gpLastSel = gpActiveSel;
+ gpActiveSel = NULL;
+ gHUD.m_iKeyBits &= ~IN_ATTACK;
+
+ const char* theSound = AvHSHUGetCommonSoundName(gHUD.GetIsAlien(), WEAPON_SOUND_SELECT);
+ gHUD.PlayHUDSound(theSound, kHUDSoundVolume);
+ }
+}
+
+
+//------------------------------------------------------------------------
+// Message Handlers
+//------------------------------------------------------------------------
+
+//
+// AmmoX -- Update the count of a known type of ammo
+//
+int CHudAmmo::MsgFunc_AmmoX(const char *pszName, int iSize, void *pbuf)
+{
+ int iIndex, iCount;
+ NetMsg_AmmoX( pbuf, iSize, iIndex, iCount );
+ gWR.SetAmmo( iIndex, abs(iCount) );
+
+ return 1;
+}
+
+int CHudAmmo::MsgFunc_AmmoPickup( const char *pszName, int iSize, void *pbuf )
+{
+ int iIndex, iCount;
+ NetMsg_AmmoPickup( pbuf, iSize, iIndex, iCount );
+
+ // Add ammo to the history
+ gHR.AddToHistory( HISTSLOT_AMMO, iIndex, abs(iCount) );
+
+ return 1;
+}
+
+int CHudAmmo::MsgFunc_WeapPickup( const char *pszName, int iSize, void *pbuf )
+{
+ int iIndex;
+ NetMsg_WeapPickup( pbuf, iSize, iIndex );
+
+ // Add the weapon to the history
+ gHR.AddToHistory( HISTSLOT_WEAP, iIndex );
+
+ return 1;
+}
+
+int CHudAmmo::MsgFunc_ItemPickup( const char *pszName, int iSize, void *pbuf )
+{
+ string szName;
+ NetMsg_ItemPickup( pbuf, iSize, szName );
+
+ // Add the weapon to the history
+ gHR.AddToHistory( HISTSLOT_ITEM, szName.c_str() );
+
+ return 1;
+}
+
+
+int CHudAmmo::MsgFunc_HideWeapon( const char *pszName, int iSize, void *pbuf )
+{
+ NetMsg_HideWeapon( pbuf, iSize, gHUD.m_iHideHUDDisplay );
+
+ if (gEngfuncs.IsSpectateOnly())
+ return 1;
+ if ( gHUD.m_iHideHUDDisplay & ( HIDEHUD_WEAPONS | HIDEHUD_ALL ) )
+ {
+ static wrect_t nullrc;
+ gpActiveSel = NULL;
+ gHUD.SetCurrentCrosshair( 0, nullrc, 0, 0, 0 );
+ }
+ else
+ {
+ if ( m_pWeapon )
+ gHUD.SetCurrentCrosshair( m_pWeapon->hCrosshair, m_pWeapon->rcCrosshair, 255, 255, 255 );
+ }
+
+ return 1;
+}
+
+//
+// CurWeapon: Update hud state with the current weapon and clip count. Ammo
+// counts are updated with AmmoX. Server assures that the Weapon ammo type
+// numbers match a real ammo type.
+//
+int CHudAmmo::MsgFunc_CurWeapon(const char *pszName, int iSize, void *pbuf )
+{
+ static wrect_t nullrc;
+
+ int iState, iId, iClip;
+ NetMsg_CurWeapon( pbuf, iSize, iState, iId, iClip );
+
+ if ( iId < 1 ) //signal kills crosshairs if this condition is met...
+ {
+ gHUD.SetCurrentCrosshair(0, nullrc, 0, 0, 0);
+ return 0;
+ }
+
+ if ( g_iUser1 != OBS_IN_EYE )
+ {
+ if ( iId == -1 && iClip == -1 ) //this conditional is never true due to iId < 1 check above!
+ {
+ gHUD.m_fPlayerDead = TRUE;
+ gpActiveSel = NULL;
+ return 1;
+ }
+
+ gHUD.m_fPlayerDead = FALSE;
+ }
+
+ WEAPON *pWeapon = gWR.GetWeapon( iId );
+ if( pWeapon == NULL ) //don't have the weapon described in our resource list
+ { return 0; }
+
+ bool bOnTarget = (iState & WEAPON_ON_TARGET) != 0; //used to track autoaim state
+ bool bIsCurrent = (iState & WEAPON_IS_CURRENT) != 0;
+ pWeapon->iEnabled = (iState & WEAPON_IS_ENABLED) != 0 ? TRUE : FALSE;
+ pWeapon->iClip = abs(iClip);
+
+ // Ensure that movement is enabled/disabled according to weapons
+ if (iId == 22 || iId == 11 || iId == 21)
+ {
+ gCanMove = pWeapon->iEnabled;
+ }
+
+ if( !bIsCurrent )
+ { return 1; }
+
+ m_pWeapon = pWeapon;
+
+ if ( !(gHUD.m_iHideHUDDisplay & ( HIDEHUD_WEAPONS | HIDEHUD_ALL )) )
+ {
+ gHUD.SetCurrentCrosshair(m_pWeapon->hCrosshair, m_pWeapon->rcCrosshair, 255, 255, 255);
+
+/* if ( gHUD.m_iFOV >= 90 )
+ { // normal crosshairs
+ if (bOnTarget && m_pWeapon->hAutoaim)
+ gHUD.SetCurrentCrosshair(m_pWeapon->hAutoaim, m_pWeapon->rcAutoaim, 255, 255, 255);
+ else
+ gHUD.SetCurrentCrosshair(m_pWeapon->hCrosshair, m_pWeapon->rcCrosshair, 255, 255, 255);
+ }
+ else
+ { // zoomed crosshairs
+ if (bOnTarget && m_pWeapon->hZoomedAutoaim)
+ gHUD.SetCurrentCrosshair(m_pWeapon->hZoomedAutoaim, m_pWeapon->rcZoomedAutoaim, 255, 255, 255);
+ else
+ gHUD.SetCurrentCrosshair(m_pWeapon->hZoomedCrosshair, m_pWeapon->rcZoomedCrosshair, 255, 255, 255);
+ }*/
+ }
+
+ m_fFade = 200.0f; //!!!
+ m_iFlags |= HUD_ACTIVE;
+
+ return 1;
+}
+
+//
+// WeaponList -- Tells the hud about a new weapon type.
+//
+int CHudAmmo::MsgFunc_WeaponList(const char *pszName, int iSize, void *pbuf )
+{
+ WeaponList weapon_data;
+ NetMsg_WeaponList( pbuf, iSize, weapon_data );
+
+ WEAPON Weapon;
+ memset( &Weapon, 0, sizeof(WEAPON) );
+
+ strcpy( Weapon.szName, weapon_data.weapon_name.c_str() );
+ Weapon.iAmmoType = weapon_data.ammo1_type;
+ Weapon.iMax1 = weapon_data.ammo1_max_amnt == 255 ? -1 : weapon_data.ammo1_max_amnt;
+ Weapon.iAmmo2Type = weapon_data.ammo2_type;
+ Weapon.iMax2 = weapon_data.ammo2_max_amnt == 255 ? -1 : weapon_data.ammo2_max_amnt;
+ Weapon.iSlot = weapon_data.bucket;
+ Weapon.iSlotPos = weapon_data.bucket_pos;
+ Weapon.iId = weapon_data.bit_index;
+ Weapon.iFlags = weapon_data.flags;
+ Weapon.iClip = 0;
+ // : 497 - default value for enable state
+ Weapon.iEnabled = 0;
+
+ gWR.AddWeapon( &Weapon );
+ return 1;
+}
+
+//------------------------------------------------------------------------
+// Command Handlers
+//------------------------------------------------------------------------
+// Slot button pressed
+void CHudAmmo::SlotInput( int iSlot )
+{
+ // Let the Viewport use it first, for menus
+ if ( gViewPort && gViewPort->SlotInput( iSlot ) )
+ return;
+
+ gWR.SelectSlot( iSlot, FALSE, 1 );
+}
+
+void CHudAmmo::UserCmd_Slot1(void)
+{
+ SlotInput( 0 );
+}
+
+void CHudAmmo::UserCmd_Slot2(void)
+{
+ SlotInput( 1 );
+}
+
+void CHudAmmo::UserCmd_Slot3(void)
+{
+ SlotInput( 2 );
+}
+
+void CHudAmmo::UserCmd_Slot4(void)
+{
+ SlotInput( 3 );
+}
+
+void CHudAmmo::UserCmd_Slot5(void)
+{
+ SlotInput( 4 );
+}
+
+void CHudAmmo::UserCmd_Slot6(void)
+{
+ SlotInput( 5 );
+}
+
+void CHudAmmo::UserCmd_Slot7(void)
+{
+ SlotInput( 6 );
+}
+
+void CHudAmmo::UserCmd_Slot8(void)
+{
+ SlotInput( 7 );
+}
+
+void CHudAmmo::UserCmd_Slot9(void)
+{
+ SlotInput( 8 );
+}
+
+void CHudAmmo::UserCmd_Slot10(void)
+{
+ SlotInput( 9 );
+}
+
+void CHudAmmo::UserCmd_Close(void)
+{
+ if (gpActiveSel)
+ {
+ gpLastSel = gpActiveSel;
+ gpActiveSel = NULL;
+
+ const char* theSound = AvHSHUGetCommonSoundName(gHUD.GetIsAlien(), WEAPON_SOUND_HUD_OFF);
+ gHUD.PlayHUDSound(theSound, kHUDSoundVolume);
+ }
+}
+
+
+// Selects the next item in the weapon menu
+void CHudAmmo::UserCmd_NextWeapon(void)
+{
+ if(gHUD.GetInTopDownMode())
+ {
+ AvHScrollHandler::ScrollHeightUp();
+ }
+
+ if ( gHUD.m_fPlayerDead || (gHUD.m_iHideHUDDisplay & (HIDEHUD_WEAPONS | HIDEHUD_ALL)) )
+ return;
+
+ if ( !gpActiveSel || gpActiveSel == (WEAPON*)1 )
+ gpActiveSel = m_pWeapon;
+
+ int pos = 0;
+ int slot = 0;
+ if ( gpActiveSel )
+ {
+ pos = gpActiveSel->iSlotPos + 1;
+ slot = gpActiveSel->iSlot;
+ }
+
+ for ( int loop = 0; loop <= 1; loop++ )
+ {
+ for ( ; slot < MAX_WEAPON_SLOTS; slot++ )
+ {
+ for ( ; pos < MAX_WEAPON_POSITIONS; pos++ )
+ {
+ WEAPON *wsp = gWR.GetWeaponSlot( slot, pos );
+
+ if (gWR.IsSelectable(wsp))
+ {
+ gpActiveSel = wsp;
+ return;
+ }
+ }
+
+ pos = 0;
+ }
+
+ slot = 0; // start looking from the first slot again
+ }
+
+ gpActiveSel = NULL;
+}
+
+// Selects the previous item in the menu
+void CHudAmmo::UserCmd_PrevWeapon(void)
+{
+ if(gHUD.GetInTopDownMode())
+ {
+ AvHScrollHandler::ScrollHeightDown();
+ }
+
+ if ( gHUD.m_fPlayerDead || (gHUD.m_iHideHUDDisplay & (HIDEHUD_WEAPONS | HIDEHUD_ALL)) )
+ return;
+
+ if ( !gpActiveSel || gpActiveSel == (WEAPON*)1 )
+ gpActiveSel = m_pWeapon;
+
+ int pos = MAX_WEAPON_POSITIONS-1;
+ int slot = MAX_WEAPON_SLOTS-1;
+ if ( gpActiveSel )
+ {
+ pos = gpActiveSel->iSlotPos - 1;
+ slot = gpActiveSel->iSlot;
+ }
+
+ for ( int loop = 0; loop <= 1; loop++ )
+ {
+ for ( ; slot >= 0; slot-- )
+ {
+ for ( ; pos >= 0; pos-- )
+ {
+ WEAPON *wsp = gWR.GetWeaponSlot( slot, pos );
+
+ if (gWR.IsSelectable(wsp))
+ {
+ gpActiveSel = wsp;
+ return;
+ }
+ }
+
+ pos = MAX_WEAPON_POSITIONS-1;
+ }
+
+ slot = MAX_WEAPON_SLOTS-1;
+ }
+
+ gpActiveSel = NULL;
+}
+
+void CHudAmmo::SetCurrentClip(int inClip)
+{
+ if(this->m_pWeapon)
+ {
+ this->m_pWeapon->iClip = inClip;
+ }
+}
+
+//-------------------------------------------------------------------------
+// Drawing code
+//-------------------------------------------------------------------------
+
+int CHudAmmo::Draw(float flTime)
+{
+ int a, x, y, r, g, b;
+ int AmmoWidth;
+
+ if (!(gHUD.m_iWeaponBits & (1<<(WEAPON_SUIT)) ))
+ return 1;
+
+ if (/*!gHUD.GetIsAlive() ||*/ (gHUD.m_iHideHUDDisplay & ( HIDEHUD_WEAPONS | HIDEHUD_ALL )) )
+ return 1;
+
+ // Draw Weapon Menu
+ DrawWList(flTime);
+
+ // Draw ammo pickup history
+ gHR.DrawAmmoHistory( flTime );
+
+ if (!(m_iFlags & HUD_ACTIVE))
+ return 0;
+
+ if (!m_pWeapon)
+ return 0;
+
+ WEAPON *pw = m_pWeapon; // shorthand
+
+ // SPR_Draw Ammo
+ if ((pw->iAmmoType < 0) && (pw->iAmmo2Type < 0))
+ return 0;
+
+
+ int iFlags = DHN_DRAWZERO; // draw 0 values
+
+ AmmoWidth = gHUD.GetSpriteRect(gHUD.m_HUD_number_0).right - gHUD.GetSpriteRect(gHUD.m_HUD_number_0).left;
+
+ a = (int) max( MIN_ALPHA, m_fFade );
+
+ if (m_fFade > 0)
+ m_fFade -= (gHUD.m_flTimeDelta * 20);
+
+ gHUD.GetPrimaryHudColor(r, g, b);
+
+ ScaleColors(r, g, b, a );
+
+ int theViewport[4];
+ gHUD.GetViewport(theViewport);
+
+ // Does this weapon have a clip?
+ y = theViewport[1] + theViewport[3] - gHUD.m_iFontHeight - gHUD.m_iFontHeight/2;
+
+ // Does weapon have any ammo at all?
+ if (m_pWeapon->iAmmoType > 0)
+ {
+ int iIconWidth = m_pWeapon->rcAmmo.right - m_pWeapon->rcAmmo.left;
+
+ if (pw->iClip >= 0)
+ {
+ // room for the number and the '|' and the current ammo
+
+ x = theViewport[0] + theViewport[2] - (8 * AmmoWidth) - iIconWidth;
+ x = gHUD.DrawHudNumber(x, y, iFlags | DHN_3DIGITS, pw->iClip, r, g, b);
+
+ wrect_t rc;
+ rc.top = 0;
+ rc.left = 0;
+ rc.right = AmmoWidth;
+ rc.bottom = 100;
+
+ int iBarWidth = AmmoWidth/10;
+
+ x += AmmoWidth/2;
+
+ gHUD.GetPrimaryHudColor(r, g, b);
+
+ // draw the | bar
+ FillRGBA(x, y, iBarWidth, gHUD.m_iFontHeight, r, g, b, a);
+
+ x += iBarWidth + AmmoWidth/2;;
+
+ // GL Seems to need this
+ ScaleColors(r, g, b, a );
+ x = gHUD.DrawHudNumber(x, y, iFlags | DHN_3DIGITS, gWR.CountAmmo(pw->iAmmoType), r, g, b);
+
+
+ }
+ else
+ {
+ // SPR_Draw a bullets only line
+ x = theViewport[0] + theViewport[2] - 4 * AmmoWidth - iIconWidth;
+ x = gHUD.DrawHudNumber(x, y, iFlags | DHN_3DIGITS, gWR.CountAmmo(pw->iAmmoType), r, g, b);
+ }
+
+ // Draw the ammo Icon
+ int iOffset = (m_pWeapon->rcAmmo.bottom - m_pWeapon->rcAmmo.top)/8;
+ SPR_Set(m_pWeapon->hAmmo, r, g, b);
+ SPR_DrawAdditive(0, x, y - iOffset, &m_pWeapon->rcAmmo);
+ }
+
+ // Does weapon have seconday ammo?
+ if (pw->iAmmo2Type > 0)
+ {
+ int iIconWidth = m_pWeapon->rcAmmo2.right - m_pWeapon->rcAmmo2.left;
+
+ // Do we have secondary ammo?
+ if ((pw->iAmmo2Type != 0) && (gWR.CountAmmo(pw->iAmmo2Type) > 0))
+ {
+ y -= gHUD.m_iFontHeight + gHUD.m_iFontHeight/4;
+ x = theViewport[0] + theViewport[2] - 4 * AmmoWidth - iIconWidth;
+ x = gHUD.DrawHudNumber(x, y, iFlags|DHN_3DIGITS, gWR.CountAmmo(pw->iAmmo2Type), r, g, b);
+
+ // Draw the ammo Icon
+ SPR_Set(m_pWeapon->hAmmo2, r, g, b);
+ int iOffset = (m_pWeapon->rcAmmo2.bottom - m_pWeapon->rcAmmo2.top)/8;
+ SPR_DrawAdditive(0, x, y - iOffset, &m_pWeapon->rcAmmo2);
+ }
+ }
+ return 1;
+}
+
+
+//
+// Draws the ammo bar on the hud
+//
+int DrawBar(int x, int y, int width, int height, float f)
+{
+ int r, g, b;
+
+ if (f < 0)
+ f = 0;
+ if (f > 1)
+ f = 1;
+
+ if (f)
+ {
+ int w = f * width;
+
+ // Always show at least one pixel if we have ammo.
+ if (w <= 0)
+ w = 1;
+ UnpackRGB(r, g, b, RGB_GREENISH);
+ FillRGBA(x, y, w, height, r, g, b, 255);
+ x += w;
+ width -= w;
+ }
+
+ gHUD.GetPrimaryHudColor(r, g, b);
+ FillRGBA(x, y, width, height, r, g, b, 128);
+
+ return (x + width);
+}
+
+
+
+void DrawAmmoBar(WEAPON *p, int x, int y, int width, int height)
+{
+ if ( !p )
+ return;
+
+ if (p->iAmmoType != -1)
+ {
+ if (!gWR.CountAmmo(p->iAmmoType))
+ return;
+
+ float f = (float)gWR.CountAmmo(p->iAmmoType)/(float)p->iMax1;
+
+ x = DrawBar(x, y, width, height, f);
+
+
+ // Do we have secondary ammo too?
+
+ if (p->iAmmo2Type != -1)
+ {
+ f = (float)gWR.CountAmmo(p->iAmmo2Type)/(float)p->iMax2;
+
+ x += 5; //!!!
+
+ DrawBar(x, y, width, height, f);
+ }
+ }
+}
+
+
+
+
+//
+// Draw Weapon Menu
+//
+int CHudAmmo::DrawWList(float flTime)
+{
+ int r,g,b,x,y,a,i;
+
+ if ( !gpActiveSel )
+ {
+ gHUD.SetSelectingWeaponID(-1);
+ return 0;
+ }
+
+ int iActiveSlot;
+
+ if ( gpActiveSel == (WEAPON *)1 )
+ iActiveSlot = -1; // current slot has no weapons
+ else
+ iActiveSlot = gpActiveSel->iSlot;
+
+ x = 10; //!!!
+ y = 10; //!!!
+
+
+ // Ensure that there are available choices in the active slot
+ if ( iActiveSlot > 0 )
+ {
+ if ( !gWR.GetFirstPos( iActiveSlot ) )
+ {
+ gpActiveSel = (WEAPON *)1;
+ iActiveSlot = -1;
+ }
+ }
+
+ // Draw top line
+ for ( i = 0; i < MAX_WEAPON_SLOTS; i++ )
+ {
+ int iWidth;
+
+ gHUD.GetPrimaryHudColor(r, g, b);
+
+ if ( iActiveSlot == i )
+ a = 255;
+ else
+ a = 192;
+
+ ScaleColors(r, g, b, 255);
+ SPR_Set(gHUD.GetSprite(m_HUD_bucket0 + i), r, g, b );
+
+ // make active slot wide enough to accomodate gun pictures
+ if ( i == iActiveSlot )
+ {
+ WEAPON *p = gWR.GetFirstPos(iActiveSlot);
+ if ( p )
+ iWidth = p->rcActive.right - p->rcActive.left;
+ else
+ iWidth = giBucketWidth;
+ }
+ else
+ iWidth = giBucketWidth;
+
+ SPR_DrawAdditive(0, x, y, &gHUD.GetSpriteRect(m_HUD_bucket0 + i));
+
+ x += iWidth + 5;
+ }
+
+
+ a = 128; //!!!
+ x = 10;
+
+ // Draw all of the buckets
+ for (i = 0; i < MAX_WEAPON_SLOTS; i++)
+ {
+ y = giBucketHeight + 10;
+
+ // If this is the active slot, draw the bigger pictures,
+ // otherwise just draw boxes
+ if ( i == iActiveSlot )
+ {
+ WEAPON *p = gWR.GetFirstPos( i );
+ int iWidth = giBucketWidth;
+ if ( p )
+ iWidth = p->rcActive.right - p->rcActive.left;
+
+ for ( int iPos = 0; iPos < MAX_WEAPON_POSITIONS; iPos++ )
+ {
+ p = gWR.GetWeaponSlot( i, iPos );
+
+ if ( !p || !p->iId )
+ continue;
+
+ // Preserve red/yellow depending on whether it has ammo or not
+ if(!gWR.IsEnabled(p))
+ {
+ UnpackRGB(r,g,b, RGB_REDISH);
+ ScaleColors(r, g, b, 128);
+ }
+ else
+ {
+ gHUD.GetPrimaryHudColor(r, g, b);
+ ScaleColors(r, g, b, 192);
+ }
+
+ if ( gpActiveSel == p )
+ {
+ SPR_Set(p->hActive, r, g, b );
+ SPR_DrawAdditive(0, x, y, &p->rcActive);
+
+ SPR_Set(gHUD.GetSprite(m_HUD_selection), r, g, b );
+ SPR_DrawAdditive(0, x, y, &gHUD.GetSpriteRect(m_HUD_selection));
+
+ // Lookup iID for helptext
+ gHUD.SetSelectingWeaponID(p->iId, r, g, b);
+ }
+ else
+ {
+ // Draw Weapon if Red if no ammo
+
+ //if (gWR.IsSelectable(p))
+ // ScaleColors(r, g, b, 192);
+ //else
+ //{
+ // UnpackRGB(r,g,b, RGB_REDISH);
+ // ScaleColors(r, g, b, 128);
+ //}
+
+ SPR_Set( p->hInactive, r, g, b );
+ SPR_DrawAdditive( 0, x, y, &p->rcInactive );
+ }
+
+ // Draw Ammo Bar
+
+ DrawAmmoBar(p, x + giABWidth/2, y, giABWidth, giABHeight);
+
+ y += p->rcActive.bottom - p->rcActive.top + 5;
+ }
+
+ x += iWidth + 5;
+
+ }
+ else
+ {
+ // Draw Row of weapons.
+ gHUD.GetPrimaryHudColor(r, g, b);
+
+ for ( int iPos = 0; iPos < MAX_WEAPON_POSITIONS; iPos++ )
+ {
+ WEAPON *p = gWR.GetWeaponSlot( i, iPos );
+
+ if ( !p || !p->iId )
+ continue;
+
+ if ( gWR.IsEnabled(p) )
+ {
+ gHUD.GetPrimaryHudColor(r, g, b);
+ a = 128;
+ }
+ else
+ {
+ UnpackRGB(r,g,b, RGB_REDISH);
+ a = 96;
+ }
+
+ FillRGBA( x, y, giBucketWidth, giBucketHeight, r, g, b, a );
+
+ y += giBucketHeight + 5;
+ }
+
+ x += giBucketWidth + 5;
+ }
+ }
+
+ return 1;
+
+}
+
+
+/* =================================
+ GetSpriteList
+
+Finds and returns the matching
+sprite name 'psz' and resolution 'iRes'
+in the given sprite list 'pList'
+iCount is the number of items in the pList
+================================= */
+client_sprite_t *GetSpriteList(client_sprite_t *pList, const char *psz, int iRes, int iCount)
+{
+ if (!pList)
+ return NULL;
+
+ int i = iCount;
+ client_sprite_t *p = pList;
+
+ while(i--)
+ {
+ if ((!strcmp(psz, p->szName)) && (p->iRes == iRes))
+ return p;
+ p++;
+ }
+
+ return NULL;
+}
diff --git a/main/source/cl_dll/ammo.h b/main/source/cl_dll/ammo.h
index 107c34ce..b5c3f221 100644
--- a/main/source/cl_dll/ammo.h
+++ b/main/source/cl_dll/ammo.h
@@ -1,64 +1,64 @@
-/***
-*
-* Copyright (c) 1999, Valve LLC. All rights reserved.
-*
-* This product contains software technology licensed from Id
-* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
-* All Rights Reserved.
-*
-* Use, distribution, and modification of this source code and/or resulting
-* object code is restricted to non-commercial enhancements to products from
-* Valve LLC. All other use, distribution, or modification is prohibited
-* without written permission from Valve LLC.
-*
-****/
-
-#ifndef __AMMO_H__
-#define __AMMO_H__
-
-#define MAX_WEAPON_NAME 128
-
-
-#define WEAPON_FLAGS_SELECTIONEMPTY 1
-
-struct WEAPON
-{
- char szName[MAX_WEAPON_NAME];
- int iAmmoType;
- int iAmmo2Type;
- int iMax1;
- int iMax2;
- int iSlot;
- int iSlotPos;
- int iFlags;
- int iId;
- int iClip;
- // : 497 - weapon enable state
- int iEnabled;
-
- int iCount; // # of itesm in plist
-
- HSPRITE hActive;
- wrect_t rcActive;
- HSPRITE hInactive;
- wrect_t rcInactive;
- HSPRITE hAmmo;
- wrect_t rcAmmo;
- HSPRITE hAmmo2;
- wrect_t rcAmmo2;
- HSPRITE hCrosshair;
- wrect_t rcCrosshair;
-
-/* HSPRITE hAutoaim;
- wrect_t rcAutoaim;
- HSPRITE hZoomedCrosshair;
- wrect_t rcZoomedCrosshair;
- HSPRITE hZoomedAutoaim;
- wrect_t rcZoomedAutoaim;
- */
-};
-
-typedef int AMMO;
-
-
+/***
+*
+* Copyright (c) 1999, Valve LLC. All rights reserved.
+*
+* This product contains software technology licensed from Id
+* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
+* All Rights Reserved.
+*
+* Use, distribution, and modification of this source code and/or resulting
+* object code is restricted to non-commercial enhancements to products from
+* Valve LLC. All other use, distribution, or modification is prohibited
+* without written permission from Valve LLC.
+*
+****/
+
+#ifndef __AMMO_H__
+#define __AMMO_H__
+
+#define MAX_WEAPON_NAME 128
+
+
+#define WEAPON_FLAGS_SELECTIONEMPTY 1
+
+struct WEAPON
+{
+ char szName[MAX_WEAPON_NAME];
+ int iAmmoType;
+ int iAmmo2Type;
+ int iMax1;
+ int iMax2;
+ int iSlot;
+ int iSlotPos;
+ int iFlags;
+ int iId;
+ int iClip;
+ // : 497 - weapon enable state
+ int iEnabled;
+
+ int iCount; // # of itesm in plist
+
+ HSPRITE hActive;
+ wrect_t rcActive;
+ HSPRITE hInactive;
+ wrect_t rcInactive;
+ HSPRITE hAmmo;
+ wrect_t rcAmmo;
+ HSPRITE hAmmo2;
+ wrect_t rcAmmo2;
+ HSPRITE hCrosshair;
+ wrect_t rcCrosshair;
+
+/* HSPRITE hAutoaim;
+ wrect_t rcAutoaim;
+ HSPRITE hZoomedCrosshair;
+ wrect_t rcZoomedCrosshair;
+ HSPRITE hZoomedAutoaim;
+ wrect_t rcZoomedAutoaim;
+ */
+};
+
+typedef int AMMO;
+
+
#endif
\ No newline at end of file
diff --git a/main/source/cl_dll/ammo_secondary.cpp b/main/source/cl_dll/ammo_secondary.cpp
index 56c84c14..ac554fa2 100644
--- a/main/source/cl_dll/ammo_secondary.cpp
+++ b/main/source/cl_dll/ammo_secondary.cpp
@@ -1,104 +1,104 @@
-/***
-*
-* Copyright (c) 1999, Valve LLC. All rights reserved.
-*
-* This product contains software technology licensed from Id
-* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
-* All Rights Reserved.
-*
-* Use, distribution, and modification of this source code and/or resulting
-* object code is restricted to non-commercial enhancements to products from
-* Valve LLC. All other use, distribution, or modification is prohibited
-* without written permission from Valve LLC.
-*
-****/
-//
-// ammo_secondary.cpp
-//
-// implementation of CHudAmmoSecondary class
-//
-
-#include "hud.h"
-#include "cl_util.h"
-#include
-#include
-
-int CHudAmmoSecondary :: Init( void )
-{
- gHUD.AddHudElem(this);
- m_HUD_ammoicon = 0;
-
- for ( int i = 0; i < MAX_SEC_AMMO_VALUES; i++ )
- m_iAmmoAmounts[i] = -1; // -1 means don't draw this value
-
- Reset();
-
- return 1;
-}
-
-void CHudAmmoSecondary :: Reset( void )
-{
- m_fFade = 0;
-}
-
-int CHudAmmoSecondary :: VidInit( void )
-{
- return 1;
-}
-
-int CHudAmmoSecondary :: Draw(float flTime)
-{
- if ( (gHUD.m_iHideHUDDisplay & ( HIDEHUD_WEAPONS | HIDEHUD_ALL )) )
- return 1;
-
- // draw secondary ammo icons above normal ammo readout
- int a, x, y, r, g, b, AmmoWidth;
- gHUD.GetPrimaryHudColor(r, g, b);
- a = (int) max( MIN_ALPHA, m_fFade );
- if (m_fFade > 0)
- m_fFade -= (gHUD.m_flTimeDelta * 20); // slowly lower alpha to fade out icons
- ScaleColors( r, g, b, a );
-
- AmmoWidth = gHUD.GetSpriteRect(gHUD.m_HUD_number_0).right - gHUD.GetSpriteRect(gHUD.m_HUD_number_0).left;
-
- y = ScreenHeight() - (gHUD.m_iFontHeight*4); // this is one font height higher than the weapon ammo values
- x = ScreenWidth() - AmmoWidth;
-
- if ( m_HUD_ammoicon )
- {
- // Draw the ammo icon
- x -= (gHUD.GetSpriteRect(m_HUD_ammoicon).right - gHUD.GetSpriteRect(m_HUD_ammoicon).left);
- y -= (gHUD.GetSpriteRect(m_HUD_ammoicon).top - gHUD.GetSpriteRect(m_HUD_ammoicon).bottom);
-
- SPR_Set( gHUD.GetSprite(m_HUD_ammoicon), r, g, b );
- SPR_DrawAdditive( 0, x, y, &gHUD.GetSpriteRect(m_HUD_ammoicon) );
- }
- else
- { // move the cursor by the '0' char instead, since we don't have an icon to work with
- x -= AmmoWidth;
- y -= (gHUD.GetSpriteRect(gHUD.m_HUD_number_0).top - gHUD.GetSpriteRect(gHUD.m_HUD_number_0).bottom);
- }
-
- // draw the ammo counts, in reverse order, from right to left
- for ( int i = MAX_SEC_AMMO_VALUES-1; i >= 0; i-- )
- {
- if ( m_iAmmoAmounts[i] < 0 )
- continue; // negative ammo amounts imply that they shouldn't be drawn
-
- // half a char gap between the ammo number and the previous pic
- x -= (AmmoWidth / 2);
-
- // draw the number, right-aligned
- x -= (gHUD.GetNumWidth( m_iAmmoAmounts[i], DHN_DRAWZERO ) * AmmoWidth);
- gHUD.DrawHudNumber( x, y, DHN_DRAWZERO, m_iAmmoAmounts[i], r, g, b );
-
- if ( i != 0 )
- {
- // draw the divider bar
- x -= (AmmoWidth / 2);
- FillRGBA(x, y, (AmmoWidth/10), gHUD.m_iFontHeight, r, g, b, a);
- }
- }
-
- return 1;
-}
+/***
+*
+* Copyright (c) 1999, Valve LLC. All rights reserved.
+*
+* This product contains software technology licensed from Id
+* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
+* All Rights Reserved.
+*
+* Use, distribution, and modification of this source code and/or resulting
+* object code is restricted to non-commercial enhancements to products from
+* Valve LLC. All other use, distribution, or modification is prohibited
+* without written permission from Valve LLC.
+*
+****/
+//
+// ammo_secondary.cpp
+//
+// implementation of CHudAmmoSecondary class
+//
+
+#include "hud.h"
+#include "cl_util.h"
+#include
+#include
+
+int CHudAmmoSecondary :: Init( void )
+{
+ gHUD.AddHudElem(this);
+ m_HUD_ammoicon = 0;
+
+ for ( int i = 0; i < MAX_SEC_AMMO_VALUES; i++ )
+ m_iAmmoAmounts[i] = -1; // -1 means don't draw this value
+
+ Reset();
+
+ return 1;
+}
+
+void CHudAmmoSecondary :: Reset( void )
+{
+ m_fFade = 0;
+}
+
+int CHudAmmoSecondary :: VidInit( void )
+{
+ return 1;
+}
+
+int CHudAmmoSecondary :: Draw(float flTime)
+{
+ if ( (gHUD.m_iHideHUDDisplay & ( HIDEHUD_WEAPONS | HIDEHUD_ALL )) )
+ return 1;
+
+ // draw secondary ammo icons above normal ammo readout
+ int a, x, y, r, g, b, AmmoWidth;
+ gHUD.GetPrimaryHudColor(r, g, b);
+ a = (int) max( MIN_ALPHA, m_fFade );
+ if (m_fFade > 0)
+ m_fFade -= (gHUD.m_flTimeDelta * 20); // slowly lower alpha to fade out icons
+ ScaleColors( r, g, b, a );
+
+ AmmoWidth = gHUD.GetSpriteRect(gHUD.m_HUD_number_0).right - gHUD.GetSpriteRect(gHUD.m_HUD_number_0).left;
+
+ y = ScreenHeight() - (gHUD.m_iFontHeight*4); // this is one font height higher than the weapon ammo values
+ x = ScreenWidth() - AmmoWidth;
+
+ if ( m_HUD_ammoicon )
+ {
+ // Draw the ammo icon
+ x -= (gHUD.GetSpriteRect(m_HUD_ammoicon).right - gHUD.GetSpriteRect(m_HUD_ammoicon).left);
+ y -= (gHUD.GetSpriteRect(m_HUD_ammoicon).top - gHUD.GetSpriteRect(m_HUD_ammoicon).bottom);
+
+ SPR_Set( gHUD.GetSprite(m_HUD_ammoicon), r, g, b );
+ SPR_DrawAdditive( 0, x, y, &gHUD.GetSpriteRect(m_HUD_ammoicon) );
+ }
+ else
+ { // move the cursor by the '0' char instead, since we don't have an icon to work with
+ x -= AmmoWidth;
+ y -= (gHUD.GetSpriteRect(gHUD.m_HUD_number_0).top - gHUD.GetSpriteRect(gHUD.m_HUD_number_0).bottom);
+ }
+
+ // draw the ammo counts, in reverse order, from right to left
+ for ( int i = MAX_SEC_AMMO_VALUES-1; i >= 0; i-- )
+ {
+ if ( m_iAmmoAmounts[i] < 0 )
+ continue; // negative ammo amounts imply that they shouldn't be drawn
+
+ // half a char gap between the ammo number and the previous pic
+ x -= (AmmoWidth / 2);
+
+ // draw the number, right-aligned
+ x -= (gHUD.GetNumWidth( m_iAmmoAmounts[i], DHN_DRAWZERO ) * AmmoWidth);
+ gHUD.DrawHudNumber( x, y, DHN_DRAWZERO, m_iAmmoAmounts[i], r, g, b );
+
+ if ( i != 0 )
+ {
+ // draw the divider bar
+ x -= (AmmoWidth / 2);
+ FillRGBA(x, y, (AmmoWidth/10), gHUD.m_iFontHeight, r, g, b, a);
+ }
+ }
+
+ return 1;
+}
diff --git a/main/source/cl_dll/ammohistory.cpp b/main/source/cl_dll/ammohistory.cpp
index 6382d7d6..541f0e04 100644
--- a/main/source/cl_dll/ammohistory.cpp
+++ b/main/source/cl_dll/ammohistory.cpp
@@ -1,173 +1,173 @@
-/***
-*
-* Copyright (c) 1999, Valve LLC. All rights reserved.
-*
-* This product contains software technology licensed from Id
-* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
-* All Rights Reserved.
-*
-* Use, distribution, and modification of this source code and/or resulting
-* object code is restricted to non-commercial enhancements to products from
-* Valve LLC. All other use, distribution, or modification is prohibited
-* without written permission from Valve LLC.
-*
-****/
-//
-// ammohistory.cpp
-//
-
-
-#include "hud.h"
-#include "cl_util.h"
-
-#include
-#include
-
-#include "ammohistory.h"
-
-HistoryResource gHR;
-
-#define AMMO_PICKUP_GAP (gHR.iHistoryGap+5)
-#define AMMO_PICKUP_PICK_HEIGHT (32 + (gHR.iHistoryGap * 2))
-#define AMMO_PICKUP_HEIGHT_MAX (ScreenHeight() - 100)
-
-#define MAX_ITEM_NAME 32
-int HISTORY_DRAW_TIME = 5;
-
-// keep a list of items
-struct ITEM_INFO
-{
- char szName[MAX_ITEM_NAME];
- HSPRITE spr;
- wrect_t rect;
-};
-
-void HistoryResource :: AddToHistory( int iType, int iId, int iCount )
-{
- if ( iType == HISTSLOT_AMMO && !iCount )
- return; // no amount, so don't add
-
- if ( (((AMMO_PICKUP_GAP * iCurrentHistorySlot) + AMMO_PICKUP_PICK_HEIGHT) > AMMO_PICKUP_HEIGHT_MAX) || (iCurrentHistorySlot >= MAX_HISTORY) )
- { // the pic would have to be drawn too high
- // so start from the bottom
- iCurrentHistorySlot = 0;
- }
-
- HIST_ITEM *freeslot = &rgAmmoHistory[iCurrentHistorySlot++]; // default to just writing to the first slot
- HISTORY_DRAW_TIME = CVAR_GET_FLOAT( "hud_drawhistory_time" );
-
- freeslot->type = iType;
- freeslot->iId = iId;
- freeslot->iCount = iCount;
- freeslot->DisplayTime = gHUD.m_flTime + HISTORY_DRAW_TIME;
-}
-
-void HistoryResource :: AddToHistory( int iType, const char *szName, int iCount )
-{
- if ( iType != HISTSLOT_ITEM )
- return;
-
- int i = gHUD.GetSpriteIndex( szName );
- if ( i == -1 )
- return; // unknown sprite name, don't add it to history
-
- return this->AddToHistory( iType, i, iCount );
-}
-
-void HistoryResource :: CheckClearHistory( void )
-{
- for ( int i = 0; i < MAX_HISTORY; i++ )
- {
- if ( rgAmmoHistory[i].type )
- return;
- }
-
- iCurrentHistorySlot = 0;
-}
-
-//
-// Draw Ammo pickup history
-//
-int HistoryResource :: DrawAmmoHistory( float flTime )
-{
- for ( int i = 0; i < MAX_HISTORY; i++ )
- {
- if ( rgAmmoHistory[i].type )
- {
- rgAmmoHistory[i].DisplayTime = min( rgAmmoHistory[i].DisplayTime, gHUD.m_flTime + HISTORY_DRAW_TIME );
-
- if ( rgAmmoHistory[i].DisplayTime <= flTime )
- { // pic drawing time has expired
- memset( &rgAmmoHistory[i], 0, sizeof(HIST_ITEM) );
- CheckClearHistory();
- }
- else if ( rgAmmoHistory[i].type == HISTSLOT_AMMO )
- {
- wrect_t rcPic;
- HSPRITE *spr = gWR.GetAmmoPicFromWeapon( rgAmmoHistory[i].iId, rcPic );
-
- int r, g, b;
- gHUD.GetPrimaryHudColor(r, g, b);
- float scale = (rgAmmoHistory[i].DisplayTime - flTime) * 80;
- ScaleColors(r, g, b, min(scale, 255) );
-
- // Draw the pic
- int ypos = ScreenHeight() - (AMMO_PICKUP_PICK_HEIGHT + (AMMO_PICKUP_GAP * i));
- int xpos = ScreenWidth() - 24;
- if ( spr && *spr ) // weapon isn't loaded yet so just don't draw the pic
- { // the dll has to make sure it has sent info the weapons you need
- SPR_Set( *spr, r, g, b );
- SPR_DrawAdditive( 0, xpos, ypos, &rcPic );
- }
-
- // Draw the number
- gHUD.DrawHudNumberString( xpos - 10, ypos, xpos - 100, rgAmmoHistory[i].iCount, r, g, b );
- }
- else if ( rgAmmoHistory[i].type == HISTSLOT_WEAP )
- {
- WEAPON *weap = gWR.GetWeapon( rgAmmoHistory[i].iId );
-
- if ( !weap )
- return 1; // we don't know about the weapon yet, so don't draw anything
-
- int r, g, b;
- gHUD.GetPrimaryHudColor(r, g, b);
-
- if ( !gWR.HasAmmo( weap ) )
- UnpackRGB(r,g,b, RGB_REDISH); // if the weapon doesn't have ammo, display it as red
-
- float scale = (rgAmmoHistory[i].DisplayTime - flTime) * 80;
- ScaleColors(r, g, b, min(scale, 255) );
-
- int ypos = ScreenHeight() - (AMMO_PICKUP_PICK_HEIGHT + (AMMO_PICKUP_GAP * i));
- int xpos = ScreenWidth() - (weap->rcInactive.right - weap->rcInactive.left);
- SPR_Set( weap->hInactive, r, g, b );
- SPR_DrawAdditive( 0, xpos, ypos, &weap->rcInactive );
- }
- else if ( rgAmmoHistory[i].type == HISTSLOT_ITEM )
- {
- int r, g, b;
-
- if ( !rgAmmoHistory[i].iId )
- continue; // sprite not loaded
-
- wrect_t rect = gHUD.GetSpriteRect( rgAmmoHistory[i].iId );
-
- gHUD.GetPrimaryHudColor(r, g, b);
- float scale = (rgAmmoHistory[i].DisplayTime - flTime) * 80;
- ScaleColors(r, g, b, min(scale, 255) );
-
- int ypos = ScreenHeight() - (AMMO_PICKUP_PICK_HEIGHT + (AMMO_PICKUP_GAP * i));
- int xpos = ScreenWidth() - (rect.right - rect.left) - 10;
-
- SPR_Set( gHUD.GetSprite( rgAmmoHistory[i].iId ), r, g, b );
- SPR_DrawAdditive( 0, xpos, ypos, &rect );
- }
- }
- }
-
-
- return 1;
-}
-
-
+/***
+*
+* Copyright (c) 1999, Valve LLC. All rights reserved.
+*
+* This product contains software technology licensed from Id
+* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
+* All Rights Reserved.
+*
+* Use, distribution, and modification of this source code and/or resulting
+* object code is restricted to non-commercial enhancements to products from
+* Valve LLC. All other use, distribution, or modification is prohibited
+* without written permission from Valve LLC.
+*
+****/
+//
+// ammohistory.cpp
+//
+
+
+#include "hud.h"
+#include "cl_util.h"
+
+#include
+#include
+
+#include "ammohistory.h"
+
+HistoryResource gHR;
+
+#define AMMO_PICKUP_GAP (gHR.iHistoryGap+5)
+#define AMMO_PICKUP_PICK_HEIGHT (32 + (gHR.iHistoryGap * 2))
+#define AMMO_PICKUP_HEIGHT_MAX (ScreenHeight() - 100)
+
+#define MAX_ITEM_NAME 32
+int HISTORY_DRAW_TIME = 5;
+
+// keep a list of items
+struct ITEM_INFO
+{
+ char szName[MAX_ITEM_NAME];
+ HSPRITE spr;
+ wrect_t rect;
+};
+
+void HistoryResource :: AddToHistory( int iType, int iId, int iCount )
+{
+ if ( iType == HISTSLOT_AMMO && !iCount )
+ return; // no amount, so don't add
+
+ if ( (((AMMO_PICKUP_GAP * iCurrentHistorySlot) + AMMO_PICKUP_PICK_HEIGHT) > AMMO_PICKUP_HEIGHT_MAX) || (iCurrentHistorySlot >= MAX_HISTORY) )
+ { // the pic would have to be drawn too high
+ // so start from the bottom
+ iCurrentHistorySlot = 0;
+ }
+
+ HIST_ITEM *freeslot = &rgAmmoHistory[iCurrentHistorySlot++]; // default to just writing to the first slot
+ HISTORY_DRAW_TIME = CVAR_GET_FLOAT( "hud_drawhistory_time" );
+
+ freeslot->type = iType;
+ freeslot->iId = iId;
+ freeslot->iCount = iCount;
+ freeslot->DisplayTime = gHUD.m_flTime + HISTORY_DRAW_TIME;
+}
+
+void HistoryResource :: AddToHistory( int iType, const char *szName, int iCount )
+{
+ if ( iType != HISTSLOT_ITEM )
+ return;
+
+ int i = gHUD.GetSpriteIndex( szName );
+ if ( i == -1 )
+ return; // unknown sprite name, don't add it to history
+
+ return this->AddToHistory( iType, i, iCount );
+}
+
+void HistoryResource :: CheckClearHistory( void )
+{
+ for ( int i = 0; i < MAX_HISTORY; i++ )
+ {
+ if ( rgAmmoHistory[i].type )
+ return;
+ }
+
+ iCurrentHistorySlot = 0;
+}
+
+//
+// Draw Ammo pickup history
+//
+int HistoryResource :: DrawAmmoHistory( float flTime )
+{
+ for ( int i = 0; i < MAX_HISTORY; i++ )
+ {
+ if ( rgAmmoHistory[i].type )
+ {
+ rgAmmoHistory[i].DisplayTime = min( rgAmmoHistory[i].DisplayTime, gHUD.m_flTime + HISTORY_DRAW_TIME );
+
+ if ( rgAmmoHistory[i].DisplayTime <= flTime )
+ { // pic drawing time has expired
+ memset( &rgAmmoHistory[i], 0, sizeof(HIST_ITEM) );
+ CheckClearHistory();
+ }
+ else if ( rgAmmoHistory[i].type == HISTSLOT_AMMO )
+ {
+ wrect_t rcPic;
+ HSPRITE *spr = gWR.GetAmmoPicFromWeapon( rgAmmoHistory[i].iId, rcPic );
+
+ int r, g, b;
+ gHUD.GetPrimaryHudColor(r, g, b);
+ float scale = (rgAmmoHistory[i].DisplayTime - flTime) * 80;
+ ScaleColors(r, g, b, min(scale, 255) );
+
+ // Draw the pic
+ int ypos = ScreenHeight() - (AMMO_PICKUP_PICK_HEIGHT + (AMMO_PICKUP_GAP * i));
+ int xpos = ScreenWidth() - 24;
+ if ( spr && *spr ) // weapon isn't loaded yet so just don't draw the pic
+ { // the dll has to make sure it has sent info the weapons you need
+ SPR_Set( *spr, r, g, b );
+ SPR_DrawAdditive( 0, xpos, ypos, &rcPic );
+ }
+
+ // Draw the number
+ gHUD.DrawHudNumberString( xpos - 10, ypos, xpos - 100, rgAmmoHistory[i].iCount, r, g, b );
+ }
+ else if ( rgAmmoHistory[i].type == HISTSLOT_WEAP )
+ {
+ WEAPON *weap = gWR.GetWeapon( rgAmmoHistory[i].iId );
+
+ if ( !weap )
+ return 1; // we don't know about the weapon yet, so don't draw anything
+
+ int r, g, b;
+ gHUD.GetPrimaryHudColor(r, g, b);
+
+ if ( !gWR.HasAmmo( weap ) )
+ UnpackRGB(r,g,b, RGB_REDISH); // if the weapon doesn't have ammo, display it as red
+
+ float scale = (rgAmmoHistory[i].DisplayTime - flTime) * 80;
+ ScaleColors(r, g, b, min(scale, 255) );
+
+ int ypos = ScreenHeight() - (AMMO_PICKUP_PICK_HEIGHT + (AMMO_PICKUP_GAP * i));
+ int xpos = ScreenWidth() - (weap->rcInactive.right - weap->rcInactive.left);
+ SPR_Set( weap->hInactive, r, g, b );
+ SPR_DrawAdditive( 0, xpos, ypos, &weap->rcInactive );
+ }
+ else if ( rgAmmoHistory[i].type == HISTSLOT_ITEM )
+ {
+ int r, g, b;
+
+ if ( !rgAmmoHistory[i].iId )
+ continue; // sprite not loaded
+
+ wrect_t rect = gHUD.GetSpriteRect( rgAmmoHistory[i].iId );
+
+ gHUD.GetPrimaryHudColor(r, g, b);
+ float scale = (rgAmmoHistory[i].DisplayTime - flTime) * 80;
+ ScaleColors(r, g, b, min(scale, 255) );
+
+ int ypos = ScreenHeight() - (AMMO_PICKUP_PICK_HEIGHT + (AMMO_PICKUP_GAP * i));
+ int xpos = ScreenWidth() - (rect.right - rect.left) - 10;
+
+ SPR_Set( gHUD.GetSprite( rgAmmoHistory[i].iId ), r, g, b );
+ SPR_DrawAdditive( 0, xpos, ypos, &rect );
+ }
+ }
+ }
+
+
+ return 1;
+}
+
+
diff --git a/main/source/cl_dll/ammohistory.h b/main/source/cl_dll/ammohistory.h
index fb42951c..661706db 100644
--- a/main/source/cl_dll/ammohistory.h
+++ b/main/source/cl_dll/ammohistory.h
@@ -1,129 +1,129 @@
-/***
-*
-* Copyright (c) 1999, Valve LLC. All rights reserved.
-*
-* This product contains software technology licensed from Id
-* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
-* All Rights Reserved.
-*
-* Use, distribution, and modification of this source code and/or resulting
-* object code is restricted to non-commercial enhancements to products from
-* Valve LLC. All other use, distribution, or modification is prohibited
-* without written permission from Valve LLC.
-*
-* Modified by Charles G. Cleveland
-*
-* $Workfile: ammohistory.h $
-* $Date: 2002/06/25 17:05:31 $
-*
-*-------------------------------------------------------------------------------
-* $Log: ammohistory.h,v $
-* Revision 1.3 2002/06/25 17:05:31 Flayra
-* - Weapon enabling/disabling works differently now
-*
-*===============================================================================
-****/
-//
-// ammohistory.h
-//
-
-// this is the max number of items in each bucket
-#define MAX_WEAPON_POSITIONS 10
-
-class WeaponsResource
-{
-public:
- WeaponsResource( void );
- ~WeaponsResource( void );
- void Init( void );
- void Reset( void );
-
- void LoadWeaponSprites( WEAPON* wp, int custom );
- void LoadAllWeaponSprites( void );
-
- WEAPON* GetWeapon( int iId );
- WEAPON* GetWeaponSlot( int slot, int pos );
- WEAPON* GetFirstPos( int iSlot );
- WEAPON* GetNextActivePos( int iSlot, int iSlotPos );
-
- bool IsEnabled( WEAPON *p );
- bool IsSelectable( WEAPON *p );
-
- bool HasAmmo( WEAPON *p );
- int CountAmmo( int iId );
- int GetAmmo( int iId );
- void SetAmmo( int iId, int iCount );
- HSPRITE* GetAmmoPicFromWeapon( int iAmmoId, wrect_t& rect ); //TODO: fix bass-ackwards arrangement and store sprites with ammo types
-
- void AddWeapon( WEAPON* wp );
- void PickupWeapon( WEAPON* wp );
- void DropWeapon( WEAPON* wp );
- void DropAllWeapons( void );
-
- //CONSIDER: Should the selection functions be in the menu with the selection variables?
- void UserCmd_LastInv( void );
- void UserCmd_MovementOn( void );
- void UserCmd_MovementOff( void );
- void SetValidWeapon( void );
- void SetCurrentWeapon( WEAPON* wp );
- void SelectSlot( int iSlot, int fAdvance, int iDirection );
-
- friend CHudAmmo; //for iOldWeaponBits access
-private:
- WEAPON rgWeapons[MAX_WEAPONS]; // current weapon state
- WEAPON* rgSlots[MAX_WEAPON_SLOTS][MAX_WEAPON_POSITIONS]; // current weapon slot map
- WEAPON* lastWeapon; // client-side lastinv
-
- int riAmmo[MAX_AMMO_TYPES]; // current ammo counts
- int iOldWeaponBits;
-};
-
-extern WeaponsResource gWR;
-
-
-#define MAX_HISTORY 12
-enum {
- HISTSLOT_EMPTY,
- HISTSLOT_AMMO,
- HISTSLOT_WEAP,
- HISTSLOT_ITEM,
-};
-
-class HistoryResource
-{
-private:
- struct HIST_ITEM {
- int type;
- float DisplayTime; // the time at which this item should be removed from the history
- int iCount;
- int iId;
- };
-
- HIST_ITEM rgAmmoHistory[MAX_HISTORY];
-
-public:
-
- void Init( void )
- {
- Reset();
- }
-
- void Reset( void )
- {
- memset( rgAmmoHistory, 0, sizeof rgAmmoHistory );
- }
-
- int iHistoryGap;
- int iCurrentHistorySlot;
-
- void AddToHistory( int iType, int iId, int iCount = 0 );
- void AddToHistory( int iType, const char *szName, int iCount = 0 );
-
- void CheckClearHistory( void );
- int DrawAmmoHistory( float flTime );
-};
-
-extern HistoryResource gHR;
-
-
-
+/***
+*
+* Copyright (c) 1999, Valve LLC. All rights reserved.
+*
+* This product contains software technology licensed from Id
+* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
+* All Rights Reserved.
+*
+* Use, distribution, and modification of this source code and/or resulting
+* object code is restricted to non-commercial enhancements to products from
+* Valve LLC. All other use, distribution, or modification is prohibited
+* without written permission from Valve LLC.
+*
+* Modified by Charles G. Cleveland
+*
+* $Workfile: ammohistory.h $
+* $Date: 2002/06/25 17:05:31 $
+*
+*-------------------------------------------------------------------------------
+* $Log: ammohistory.h,v $
+* Revision 1.3 2002/06/25 17:05:31 Flayra
+* - Weapon enabling/disabling works differently now
+*
+*===============================================================================
+****/
+//
+// ammohistory.h
+//
+
+// this is the max number of items in each bucket
+#define MAX_WEAPON_POSITIONS 10
+
+class WeaponsResource
+{
+public:
+ WeaponsResource( void );
+ ~WeaponsResource( void );
+ void Init( void );
+ void Reset( void );
+
+ void LoadWeaponSprites( WEAPON* wp, int custom );
+ void LoadAllWeaponSprites( void );
+
+ WEAPON* GetWeapon( int iId );
+ WEAPON* GetWeaponSlot( int slot, int pos );
+ WEAPON* GetFirstPos( int iSlot );
+ WEAPON* GetNextActivePos( int iSlot, int iSlotPos );
+
+ bool IsEnabled( WEAPON *p );
+ bool IsSelectable( WEAPON *p );
+
+ bool HasAmmo( WEAPON *p );
+ int CountAmmo( int iId );
+ int GetAmmo( int iId );
+ void SetAmmo( int iId, int iCount );
+ HSPRITE* GetAmmoPicFromWeapon( int iAmmoId, wrect_t& rect ); //TODO: fix bass-ackwards arrangement and store sprites with ammo types
+
+ void AddWeapon( WEAPON* wp );
+ void PickupWeapon( WEAPON* wp );
+ void DropWeapon( WEAPON* wp );
+ void DropAllWeapons( void );
+
+ //CONSIDER: Should the selection functions be in the menu with the selection variables?
+ void UserCmd_LastInv( void );
+ void UserCmd_MovementOn( void );
+ void UserCmd_MovementOff( void );
+ void SetValidWeapon( void );
+ void SetCurrentWeapon( WEAPON* wp );
+ void SelectSlot( int iSlot, int fAdvance, int iDirection );
+
+ friend CHudAmmo; //for iOldWeaponBits access
+private:
+ WEAPON rgWeapons[MAX_WEAPONS]; // current weapon state
+ WEAPON* rgSlots[MAX_WEAPON_SLOTS][MAX_WEAPON_POSITIONS]; // current weapon slot map
+ WEAPON* lastWeapon; // client-side lastinv
+
+ int riAmmo[MAX_AMMO_TYPES]; // current ammo counts
+ int iOldWeaponBits;
+};
+
+extern WeaponsResource gWR;
+
+
+#define MAX_HISTORY 12
+enum {
+ HISTSLOT_EMPTY,
+ HISTSLOT_AMMO,
+ HISTSLOT_WEAP,
+ HISTSLOT_ITEM,
+};
+
+class HistoryResource
+{
+private:
+ struct HIST_ITEM {
+ int type;
+ float DisplayTime; // the time at which this item should be removed from the history
+ int iCount;
+ int iId;
+ };
+
+ HIST_ITEM rgAmmoHistory[MAX_HISTORY];
+
+public:
+
+ void Init( void )
+ {
+ Reset();
+ }
+
+ void Reset( void )
+ {
+ memset( rgAmmoHistory, 0, sizeof rgAmmoHistory );
+ }
+
+ int iHistoryGap;
+ int iCurrentHistorySlot;
+
+ void AddToHistory( int iType, int iId, int iCount = 0 );
+ void AddToHistory( int iType, const char *szName, int iCount = 0 );
+
+ void CheckClearHistory( void );
+ int DrawAmmoHistory( float flTime );
+};
+
+extern HistoryResource gHR;
+
+
+
diff --git a/main/source/cl_dll/battery.cpp b/main/source/cl_dll/battery.cpp
index 6d0ac04c..990c829c 100644
--- a/main/source/cl_dll/battery.cpp
+++ b/main/source/cl_dll/battery.cpp
@@ -1,156 +1,156 @@
-/***
-*
-* Copyright (c) 1999, Valve LLC. All rights reserved.
-*
-* This product contains software technology licensed from Id
-* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
-* All Rights Reserved.
-*
-* Use, distribution, and modification of this source code and/or resulting
-* object code is restricted to non-commercial enhancements to products from
-* Valve LLC. All other use, distribution, or modification is prohibited
-* without written permission from Valve LLC.
-*
-****/
-//
-// battery.cpp
-//
-// implementation of CHudBattery class
-//
-
-#include "hud.h"
-#include "cl_util.h"
-
-#include
-#include
-#include "AvHPlayerUpgrade.h"
-#include "AvHHudConstants.h"
-#include "AvHNetworkMessages.h"
-
-DECLARE_MESSAGE(m_Battery, Battery)
-
-int CHudBattery::Init(void)
-{
- m_iBat = 0;
- m_fFade = 0;
- m_iFlags = 0;
-
- HOOK_MESSAGE(Battery);
-
- gHUD.AddHudElem(this);
-
- return 1;
-};
-
-
-int CHudBattery::VidInit(void)
-{
- int HUD_suit_empty = gHUD.GetSpriteIndex( "suit_empty" );
- int HUD_suit_full = gHUD.GetSpriteIndex( "suit_full" );
-
- m_hSprite1 = m_hSprite2 = 0; // delaying get sprite handles until we know the sprites are loaded
- m_prc1 = &gHUD.GetSpriteRect( HUD_suit_empty );
- m_prc2 = &gHUD.GetSpriteRect( HUD_suit_full );
- m_iHeight = m_prc2->bottom - m_prc1->top;
- m_fFade = 0;
- return 1;
-};
-
-int CHudBattery:: MsgFunc_Battery(const char *pszName, int iSize, void *pbuf )
-{
- m_iFlags |= HUD_ACTIVE;
-
-
- int x;
- NetMsg_Battery( pbuf, iSize, x );
-
- if (x != m_iBat)
- {
- // We're sent the health of the player we're observing as if it were our own
- m_fFade = FADE_TIME;
- m_iBat = x;
- }
-
- return 1;
-}
-
-
-int CHudBattery::Draw(float flTime)
-{
-
- if ( gHUD.m_iHideHUDDisplay & HIDEHUD_HEALTH )
- return 1;
-
- int r, g, b, x, y, a;
- wrect_t rc;
-
- rc = *m_prc2;
-
- int theMaxArmor = gHUD.GetHUDMaxArmor();
- float theScalar = 1.0f/theMaxArmor;
-
- rc.top += m_iHeight * ((float)(theMaxArmor-(min(theMaxArmor, m_iBat))) * theScalar); // battery can go from 0 to 100 so * 0.01 goes from 0 to 1
-
- gHUD.GetPrimaryHudColor(r, g, b);
-
- if (!(gHUD.m_iWeaponBits & (1<<(WEAPON_SUIT)) ))
- return 1;
-
- // Has health changed? Flash the health #
- if (m_fFade)
- {
- if (m_fFade > FADE_TIME)
- m_fFade = FADE_TIME;
-
- m_fFade -= (gHUD.m_flTimeDelta * 20);
- if (m_fFade <= 0)
- {
- a = 128;
- m_fFade = 0;
- }
-
- // Fade the health number back to dim
-
- a = MIN_ALPHA + (m_fFade/FADE_TIME) * 128;
-
- }
- else
- a = MIN_ALPHA;
-
- ScaleColors(r, g, b, a );
-
- int iOffset = (m_prc1->bottom - m_prc1->top)/6;
-
- int theInset = 0;
- if(gHUD.GetIsAlien())
- {
- theInset = ScreenWidth()*kResourceEnergyBarWidth;
- }
-
- int theViewport[4];
- gHUD.GetViewport(theViewport);
-
- y = theViewport[1] + theViewport[3] - gHUD.m_iFontHeight - gHUD.m_iFontHeight / 2;
- x = theViewport[0] + theInset + kArmorLeftInset*ScreenWidth();
-
- // make sure we have the right sprite handles
- if ( !m_hSprite1 )
- m_hSprite1 = gHUD.GetSprite( gHUD.GetSpriteIndex( "suit_empty" ) );
- if ( !m_hSprite2 )
- m_hSprite2 = gHUD.GetSprite( gHUD.GetSpriteIndex( "suit_full" ) );
-
- SPR_Set(m_hSprite1, r, g, b );
- SPR_DrawAdditive( 0, x, y - iOffset, m_prc1);
-
- if (rc.bottom > rc.top)
- {
- SPR_Set(m_hSprite2, r, g, b );
- SPR_DrawAdditive( 0, x, y - iOffset + (rc.top - m_prc2->top), &rc);
- }
-
- x += (m_prc1->right - m_prc1->left);
- x = gHUD.DrawHudNumber(x, y, DHN_3DIGITS | DHN_DRAWZERO, m_iBat, r, g, b);
-
- return 1;
-
-}
+/***
+*
+* Copyright (c) 1999, Valve LLC. All rights reserved.
+*
+* This product contains software technology licensed from Id
+* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
+* All Rights Reserved.
+*
+* Use, distribution, and modification of this source code and/or resulting
+* object code is restricted to non-commercial enhancements to products from
+* Valve LLC. All other use, distribution, or modification is prohibited
+* without written permission from Valve LLC.
+*
+****/
+//
+// battery.cpp
+//
+// implementation of CHudBattery class
+//
+
+#include "hud.h"
+#include "cl_util.h"
+
+#include
+#include
+#include "AvHPlayerUpgrade.h"
+#include "AvHHudConstants.h"
+#include "AvHNetworkMessages.h"
+
+DECLARE_MESSAGE(m_Battery, Battery)
+
+int CHudBattery::Init(void)
+{
+ m_iBat = 0;
+ m_fFade = 0;
+ m_iFlags = 0;
+
+ HOOK_MESSAGE(Battery);
+
+ gHUD.AddHudElem(this);
+
+ return 1;
+};
+
+
+int CHudBattery::VidInit(void)
+{
+ int HUD_suit_empty = gHUD.GetSpriteIndex( "suit_empty" );
+ int HUD_suit_full = gHUD.GetSpriteIndex( "suit_full" );
+
+ m_hSprite1 = m_hSprite2 = 0; // delaying get sprite handles until we know the sprites are loaded
+ m_prc1 = &gHUD.GetSpriteRect( HUD_suit_empty );
+ m_prc2 = &gHUD.GetSpriteRect( HUD_suit_full );
+ m_iHeight = m_prc2->bottom - m_prc1->top;
+ m_fFade = 0;
+ return 1;
+};
+
+int CHudBattery:: MsgFunc_Battery(const char *pszName, int iSize, void *pbuf )
+{
+ m_iFlags |= HUD_ACTIVE;
+
+
+ int x;
+ NetMsg_Battery( pbuf, iSize, x );
+
+ if (x != m_iBat)
+ {
+ // We're sent the health of the player we're observing as if it were our own
+ m_fFade = FADE_TIME;
+ m_iBat = x;
+ }
+
+ return 1;
+}
+
+
+int CHudBattery::Draw(float flTime)
+{
+
+ if ( gHUD.m_iHideHUDDisplay & HIDEHUD_HEALTH )
+ return 1;
+
+ int r, g, b, x, y, a;
+ wrect_t rc;
+
+ rc = *m_prc2;
+
+ int theMaxArmor = gHUD.GetHUDMaxArmor();
+ float theScalar = 1.0f/theMaxArmor;
+
+ rc.top += m_iHeight * ((float)(theMaxArmor-(min(theMaxArmor, m_iBat))) * theScalar); // battery can go from 0 to 100 so * 0.01 goes from 0 to 1
+
+ gHUD.GetPrimaryHudColor(r, g, b);
+
+ if (!(gHUD.m_iWeaponBits & (1<<(WEAPON_SUIT)) ))
+ return 1;
+
+ // Has health changed? Flash the health #
+ if (m_fFade)
+ {
+ if (m_fFade > FADE_TIME)
+ m_fFade = FADE_TIME;
+
+ m_fFade -= (gHUD.m_flTimeDelta * 20);
+ if (m_fFade <= 0)
+ {
+ a = 128;
+ m_fFade = 0;
+ }
+
+ // Fade the health number back to dim
+
+ a = MIN_ALPHA + (m_fFade/FADE_TIME) * 128;
+
+ }
+ else
+ a = MIN_ALPHA;
+
+ ScaleColors(r, g, b, a );
+
+ int iOffset = (m_prc1->bottom - m_prc1->top)/6;
+
+ int theInset = 0;
+ if(gHUD.GetIsAlien())
+ {
+ theInset = ScreenWidth()*kResourceEnergyBarWidth;
+ }
+
+ int theViewport[4];
+ gHUD.GetViewport(theViewport);
+
+ y = theViewport[1] + theViewport[3] - gHUD.m_iFontHeight - gHUD.m_iFontHeight / 2;
+ x = theViewport[0] + theInset + kArmorLeftInset*ScreenWidth();
+
+ // make sure we have the right sprite handles
+ if ( !m_hSprite1 )
+ m_hSprite1 = gHUD.GetSprite( gHUD.GetSpriteIndex( "suit_empty" ) );
+ if ( !m_hSprite2 )
+ m_hSprite2 = gHUD.GetSprite( gHUD.GetSpriteIndex( "suit_full" ) );
+
+ SPR_Set(m_hSprite1, r, g, b );
+ SPR_DrawAdditive( 0, x, y - iOffset, m_prc1);
+
+ if (rc.bottom > rc.top)
+ {
+ SPR_Set(m_hSprite2, r, g, b );
+ SPR_DrawAdditive( 0, x, y - iOffset + (rc.top - m_prc2->top), &rc);
+ }
+
+ x += (m_prc1->right - m_prc1->left);
+ x = gHUD.DrawHudNumber(x, y, DHN_3DIGITS | DHN_DRAWZERO, m_iBat, r, g, b);
+
+ return 1;
+
+}
diff --git a/main/source/cl_dll/camera.h b/main/source/cl_dll/camera.h
index 7b7cd017..0cf4beef 100644
--- a/main/source/cl_dll/camera.h
+++ b/main/source/cl_dll/camera.h
@@ -1,17 +1,17 @@
-// Camera.h -- defines and such for a 3rd person camera
-// NOTE: must include quakedef.h first
-
-#ifndef _CAMERA_H_
-#define _CAMEA_H_
-
-// pitch, yaw, dist
-extern vec3_t cam_ofs;
-// Using third person camera
-extern int cam_thirdperson;
-
-void CAM_Init( void );
-void CAM_ClearStates( void );
-void CAM_StartMouseMove(void);
-void CAM_EndMouseMove(void);
-
-#endif // _CAMERA_H_
+// Camera.h -- defines and such for a 3rd person camera
+// NOTE: must include quakedef.h first
+
+#ifndef _CAMERA_H_
+#define _CAMEA_H_
+
+// pitch, yaw, dist
+extern vec3_t cam_ofs;
+// Using third person camera
+extern int cam_thirdperson;
+
+void CAM_Init( void );
+void CAM_ClearStates( void );
+void CAM_StartMouseMove(void);
+void CAM_EndMouseMove(void);
+
+#endif // _CAMERA_H_
diff --git a/main/source/cl_dll/cdll_int.cpp b/main/source/cl_dll/cdll_int.cpp
index 69ed67ab..8881398d 100644
--- a/main/source/cl_dll/cdll_int.cpp
+++ b/main/source/cl_dll/cdll_int.cpp
@@ -1,463 +1,463 @@
-/***
-*
-* Copyright (c) 1999, Valve LLC. All rights reserved.
-*
-* This product contains software technology licensed from Id
-* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
-* All Rights Reserved.
-*
-* Use, distribution, and modification of this source code and/or resulting
-* object code is restricted to non-commercial enhancements to products from
-* Valve LLC. All other use, distribution, or modification is prohibited
-* without written permission from Valve LLC.
-*
-****/
-//
-// cdll_int.c
-//
-// this implementation handles the linking of the engine to the DLL
-//
-
-#include "hud.h"
-#include "cl_util.h"
-#include "netadr.h"
-#undef INTERFACE_H
-#include "../common/interface.h"
-#include "vgui_SchemeManager.h"
-#include
-/*
-extern "C"
-{
-#include "pm_shared.h"
-}*/
-#include "pm_shared.h"
-
-#include
-#include "hud_servers.h"
-#include "vgui_int.h"
-
-#include "AvHHud.h"
-#include "AvHUIFactory.h"
-#include "AvHParticleSystemManager.h"
-#include "AvHHulls.h"
-#include "interface.h"
-//#include "itrackeruser.h"
-
-#ifdef _WIN32
-#include "winsani_in.h"
-#include
-#include "winsani_out.h"
-#endif
-#include "Exports.h"
-#
-#include "tri.h"
-#include "vgui_TeamFortressViewport.h"
-#include "interface.h"
-
-#include "APIProxy.h"
-//#include "cl_dll/Exports.h"
-
-cl_enginefunc_t gEngfuncs;
-
-// Instead of using default Half-life HUD, use more flexible one I've added
-//CHud gHUD;
-//UIHud gHUD("StratHL/ui.txt", new AvHUIFactory());
-AvHHud gHUD((string(getModDirectory()) + "/ui.txt").c_str(), new AvHUIFactory());
-
-TeamFortressViewport *gViewPort = NULL;
-
-HINTERFACEMODULE g_hTrackerModule = NULL;
-//ITrackerUser *g_pTrackerUser = NULL;
-
-void InitInput (void);
-void EV_HookEvents( void );
-void IN_Commands( void );
-
-/*
-================================
-HUD_GetHullBounds
-
- Engine calls this to enumerate player collision hulls, for prediction. Return 0 if the hullnumber doesn't exist.
-================================
-*/
-int CL_DLLEXPORT HUD_GetHullBounds( int hullnumber, float *mins, float *maxs )
-{
-// RecClGetHullBounds(hullnumber, mins, maxs);
-
- int iret = 0;
-
- switch ( hullnumber )
- {
- case 0: // Human and level 4 alien, crouched level 5
- HULL0_MIN.CopyToArray(mins);
- HULL0_MAX.CopyToArray(maxs);
- iret = 1;
- break;
-
- case 1: // Crouched human, level 2 alien, level 3, crouched level 3 and 4
- HULL1_MIN.CopyToArray(mins);
- HULL1_MAX.CopyToArray(maxs);
- iret = 1;
- break;
-
- case 2: // Point based hull
- HULL2_MIN.CopyToArray(mins);
- HULL2_MAX.CopyToArray(maxs);
- iret = 1;
- break;
-
- case 3: // Huge alien
- HULL3_MIN.CopyToArray(mins);
- HULL3_MAX.CopyToArray(maxs);
- iret = 1;
- break;
- }
-
- return iret;
-}
-
-/*
-================================
-HUD_ConnectionlessPacket
-
- Return 1 if the packet is valid. Set response_buffer_size if you want to send a response packet. Incoming, it holds the max
- size of the response_buffer, so you must zero it out if you choose not to respond.
-================================
-*/
-int CL_DLLEXPORT HUD_ConnectionlessPacket( const struct netadr_s *net_from, const char *args, char *response_buffer, int *response_buffer_size )
-{
- //RecClConnectionlessPacket(net_from, args, response_buffer, response_buffer_size);
-
- // Parse stuff from args
- int max_buffer_size = *response_buffer_size;
-
- // Zero it out since we aren't going to respond.
- // If we wanted to response, we'd write data into response_buffer
- *response_buffer_size = 0;
-
- // Since we don't listen for anything here, just respond that it's a bogus message
- // If we didn't reject the message, we'd return 1 for success instead.
- return 0;
-}
-
-void CL_DLLEXPORT HUD_PlayerMoveInit( struct playermove_s *ppmove )
-{
- //RecClClientMoveInit(ppmove);
-
- PM_Init( ppmove );
-}
-
-char CL_DLLEXPORT HUD_PlayerMoveTexture( char *name )
-{
-// RecClClientTextureType(name);
-
- return PM_FindTextureType( name );
-}
-
-void CL_DLLEXPORT HUD_PlayerMove( struct playermove_s *ppmove, int server )
-{
- //RecClClientMove(ppmove, server);
-
- PM_Move( ppmove, server );
-}
-
-int CL_DLLEXPORT Initialize( cl_enginefunc_t *pEnginefuncs, int iVersion )
-{
- gEngfuncs = *pEnginefuncs;
-
- //RecClInitialize(pEnginefuncs, iVersion);
-
- if (iVersion != CLDLL_INTERFACE_VERSION)
- return 0;
-
- memcpy(&gEngfuncs, pEnginefuncs, sizeof(cl_enginefunc_t));
-
- EV_HookEvents();
- gHUD.InitExploitPrevention();
-
- return 1;
-}
-
-
-/*
-==========================
- HUD_VidInit
-
-Called when the game initializes
-and whenever the vid_mode is changed
-so the HUD can reinitialize itself.
-==========================
-*/
-
-int CL_DLLEXPORT HUD_VidInit( void )
-{
- gHUD.InitExploitPrevention();
-// RecClHudVidInit();
- gHUD.VidInit();
-
- VGui_Startup();
-
- return 1;
-}
-
-/*
-==========================
-HUD_Init
-
- Called whenever the client connects
- to a server. Reinitializes all
- the hud variables.
- ==========================
-*/
-
-void CL_DLLEXPORT HUD_Init( void )
-{
-// RecClHudInit();
- InitInput();
- gHUD.Init();
- Scheme_Init();
-}
-
-/*
-void UIDrawVariableBarSpriteHoles(int inSprite, int inX, int inY, float inPercentage)
-{
- // Assumes that frame 0 is the empty sprite, frame 1 is full sprite
- const int kEmptyFrame = 0;
- const int kFullFrame = 1;
-
- int theSpriteWidth = SPR_Width(inSprite, kFullFrame);
- int theSpriteHeight = SPR_Height(inSprite, kFullFrame);
-
- int theColorComponent = 255;
-
- // Draw empty sprite
- SPR_Set(inSprite, theColorComponent, theColorComponent, theColorComponent);
- SPR_DrawHoles(kEmptyFrame, inX, inY, NULL);
-
- // Draw secondary level if specified, at half brightness
- int theFilledHeight = theSpriteHeight*inPercentage;
- theFilledHeight = theSpriteHeight*inPercentage;
-
- // Draw partially full sprite. Enable scissor so it's not all drawn.
- SPR_EnableScissor(inX, inY + (theSpriteHeight - theFilledHeight), theSpriteWidth, theFilledHeight);
-
- SPR_Set(inSprite, theColorComponent, theColorComponent, theColorComponent);
- SPR_DrawHoles(kFullFrame, inX, inY, NULL);
-
- SPR_DisableScissor();
-}
-*/
-// Demonstrates black lines around the edge of sprites (both using tri API and SPR_* calls)
-// Demonstrates scissor not working properly
-
-/*
-==========================
-HUD_Redraw
-
- called every screen frame to
- redraw the HUD.
- ===========================
-*/
-
-int CL_DLLEXPORT HUD_Redraw( float time, int intermission )
-{
-// RecClHudRedraw(time, intermission);
-
- gHUD.Redraw( time, intermission );
-
- //Direct3DTest();
-
- //SoftwareTest();
-
- return 1;
-}
-
-
-/*
-==========================
- HUD_UpdateClientData
-
-called every time shared client
-dll/engine data gets changed,
-and gives the cdll a chance
-to modify the data.
-
-returns 1 if anything has been changed, 0 otherwise.
-==========================
-*/
-
-int CL_DLLEXPORT HUD_UpdateClientData(client_data_t *pcldata, float flTime )
-{
-// RecClHudUpdateClientData(pcldata, flTime);
-
- IN_Commands();
-
- return gHUD.UpdateClientData(pcldata, flTime );
-}
-
-/*
-==========================
- HUD_Reset
-
-Called at start and end of demos to restore to "non"HUD state.
-==========================
-*/
-
-void CL_DLLEXPORT HUD_Reset( void )
-{
-// RecClHudReset();
-
- gHUD.VidInit();
- AvHParticleSystemManager::Instance()->Reset();
-}
-
-/*
-==========================
-HUD_Frame
-
- Called by engine every frame that client .dll is loaded
- ==========================
-*/
-
-void CL_DLLEXPORT HUD_Frame( double time )
-{
-// RecClHudFrame(time);
-
- ServersThink( time );
-
- GetClientVoiceMgr()->Frame(time);
-}
-
-
-/*
-==========================
-HUD_VoiceStatus
-
- Called when a player starts or stops talking.
- ==========================
-*/
-
-void CL_DLLEXPORT HUD_VoiceStatus(int entindex, qboolean bTalking)
-{
-// RecClVoiceStatus(entindex, bTalking);
-
- GetClientVoiceMgr()->UpdateSpeakerStatus(entindex, bTalking);
-}
-
-/*
-==========================
-HUD_DirectorEvent
-
- Called when a director event message was received
- ==========================
-*/
-
-void CL_DLLEXPORT HUD_DirectorMessage( int iSize, void *pbuf )
-{
-// RecClDirectorMessage(iSize, pbuf);
- gHUD.m_Spectator.DirectorMessage( iSize, pbuf );
-}
-
-
-
-cldll_func_dst_t *g_pcldstAddrs;
-
-extern "C" void CL_DLLEXPORT F(void *pv)
-{
- cldll_func_t *pcldll_func = (cldll_func_t *)pv;
-
- // Hack!
- g_pcldstAddrs = ((cldll_func_dst_t *)pcldll_func->pHudVidInitFunc);
-
- cldll_func_t cldll_func =
- {
- Initialize,
- HUD_Init,
- HUD_VidInit,
- HUD_Redraw,
- HUD_UpdateClientData,
- HUD_Reset,
- HUD_PlayerMove,
- HUD_PlayerMoveInit,
- HUD_PlayerMoveTexture,
- IN_ActivateMouse,
- IN_DeactivateMouse,
- IN_MouseEvent,
- IN_ClearStates,
- IN_Accumulate,
- CL_CreateMove,
- CL_IsThirdPerson,
- CL_CameraOffset,
- KB_Find,
- CAM_Think,
- V_CalcRefdef,
- HUD_AddEntity,
- HUD_CreateEntities,
- HUD_DrawNormalTriangles,
- HUD_DrawTransparentTriangles,
- HUD_StudioEvent,
- HUD_PostRunCmd,
- HUD_Shutdown,
- HUD_TxferLocalOverrides,
- HUD_ProcessPlayerState,
- HUD_TxferPredictionData,
- Demo_ReadBuffer,
- HUD_ConnectionlessPacket,
- HUD_GetHullBounds,
- HUD_Frame,
- HUD_Key_Event,
- HUD_TempEntUpdate,
- HUD_GetUserEntity,
- HUD_VoiceStatus,
- HUD_DirectorMessage,
- HUD_GetStudioModelInterface,
- //HUD_ChatInputPosition,
- };
-
- *pcldll_func = cldll_func;
-}
-
-#include "cl_dll/IGameClientExports.h"
-
-//-----------------------------------------------------------------------------
-// Purpose: Exports functions that are used by the gameUI for UI dialogs
-//-----------------------------------------------------------------------------
-class CClientExports : public IGameClientExports
-{
-public:
- // returns the name of the server the user is connected to, if any
- virtual const char *GetServerHostName()
- {
- /*if (gViewPortInterface)
- {
- return gViewPortInterface->GetServerName();
- }*/
- return "";
- }
-
- // ingame voice manipulation
- virtual bool IsPlayerGameVoiceMuted(int playerIndex)
- {
- if (GetClientVoiceMgr())
- return GetClientVoiceMgr()->IsPlayerBlocked(playerIndex);
- return false;
- }
-
- virtual void MutePlayerGameVoice(int playerIndex)
- {
- if (GetClientVoiceMgr())
- {
- GetClientVoiceMgr()->SetPlayerBlockedState(playerIndex, true);
- }
- }
-
- virtual void UnmutePlayerGameVoice(int playerIndex)
- {
- if (GetClientVoiceMgr())
- {
- GetClientVoiceMgr()->SetPlayerBlockedState(playerIndex, false);
- }
- }
-};
-
-EXPOSE_SINGLE_INTERFACE(CClientExports, IGameClientExports, GAMECLIENTEXPORTS_INTERFACE_VERSION);
+/***
+*
+* Copyright (c) 1999, Valve LLC. All rights reserved.
+*
+* This product contains software technology licensed from Id
+* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
+* All Rights Reserved.
+*
+* Use, distribution, and modification of this source code and/or resulting
+* object code is restricted to non-commercial enhancements to products from
+* Valve LLC. All other use, distribution, or modification is prohibited
+* without written permission from Valve LLC.
+*
+****/
+//
+// cdll_int.c
+//
+// this implementation handles the linking of the engine to the DLL
+//
+
+#include "hud.h"
+#include "cl_util.h"
+#include "netadr.h"
+#undef INTERFACE_H
+#include "../common/interface.h"
+#include "vgui_SchemeManager.h"
+#include
+/*
+extern "C"
+{
+#include "pm_shared.h"
+}*/
+#include "pm_shared.h"
+
+#include
+#include "hud_servers.h"
+#include "vgui_int.h"
+
+#include "AvHHud.h"
+#include "AvHUIFactory.h"
+#include "AvHParticleSystemManager.h"
+#include "AvHHulls.h"
+#include "interface.h"
+//#include "itrackeruser.h"
+
+#ifdef _WIN32
+#include "winsani_in.h"
+#include
+#include "winsani_out.h"
+#endif
+#include "Exports.h"
+#
+#include "tri.h"
+#include "vgui_TeamFortressViewport.h"
+#include "interface.h"
+
+#include "APIProxy.h"
+//#include "cl_dll/Exports.h"
+
+cl_enginefunc_t gEngfuncs;
+
+// Instead of using default Half-life HUD, use more flexible one I've added
+//CHud gHUD;
+//UIHud gHUD("StratHL/ui.txt", new AvHUIFactory());
+AvHHud gHUD((string(getModDirectory()) + "/ui.txt").c_str(), new AvHUIFactory());
+
+TeamFortressViewport *gViewPort = NULL;
+
+HINTERFACEMODULE g_hTrackerModule = NULL;
+//ITrackerUser *g_pTrackerUser = NULL;
+
+void InitInput (void);
+void EV_HookEvents( void );
+void IN_Commands( void );
+
+/*
+================================
+HUD_GetHullBounds
+
+ Engine calls this to enumerate player collision hulls, for prediction. Return 0 if the hullnumber doesn't exist.
+================================
+*/
+int CL_DLLEXPORT HUD_GetHullBounds( int hullnumber, float *mins, float *maxs )
+{
+// RecClGetHullBounds(hullnumber, mins, maxs);
+
+ int iret = 0;
+
+ switch ( hullnumber )
+ {
+ case 0: // Human and level 4 alien, crouched level 5
+ HULL0_MIN.CopyToArray(mins);
+ HULL0_MAX.CopyToArray(maxs);
+ iret = 1;
+ break;
+
+ case 1: // Crouched human, level 2 alien, level 3, crouched level 3 and 4
+ HULL1_MIN.CopyToArray(mins);
+ HULL1_MAX.CopyToArray(maxs);
+ iret = 1;
+ break;
+
+ case 2: // Point based hull
+ HULL2_MIN.CopyToArray(mins);
+ HULL2_MAX.CopyToArray(maxs);
+ iret = 1;
+ break;
+
+ case 3: // Huge alien
+ HULL3_MIN.CopyToArray(mins);
+ HULL3_MAX.CopyToArray(maxs);
+ iret = 1;
+ break;
+ }
+
+ return iret;
+}
+
+/*
+================================
+HUD_ConnectionlessPacket
+
+ Return 1 if the packet is valid. Set response_buffer_size if you want to send a response packet. Incoming, it holds the max
+ size of the response_buffer, so you must zero it out if you choose not to respond.
+================================
+*/
+int CL_DLLEXPORT HUD_ConnectionlessPacket( const struct netadr_s *net_from, const char *args, char *response_buffer, int *response_buffer_size )
+{
+ //RecClConnectionlessPacket(net_from, args, response_buffer, response_buffer_size);
+
+ // Parse stuff from args
+ int max_buffer_size = *response_buffer_size;
+
+ // Zero it out since we aren't going to respond.
+ // If we wanted to response, we'd write data into response_buffer
+ *response_buffer_size = 0;
+
+ // Since we don't listen for anything here, just respond that it's a bogus message
+ // If we didn't reject the message, we'd return 1 for success instead.
+ return 0;
+}
+
+void CL_DLLEXPORT HUD_PlayerMoveInit( struct playermove_s *ppmove )
+{
+ //RecClClientMoveInit(ppmove);
+
+ PM_Init( ppmove );
+}
+
+char CL_DLLEXPORT HUD_PlayerMoveTexture( char *name )
+{
+// RecClClientTextureType(name);
+
+ return PM_FindTextureType( name );
+}
+
+void CL_DLLEXPORT HUD_PlayerMove( struct playermove_s *ppmove, int server )
+{
+ //RecClClientMove(ppmove, server);
+
+ PM_Move( ppmove, server );
+}
+
+int CL_DLLEXPORT Initialize( cl_enginefunc_t *pEnginefuncs, int iVersion )
+{
+ gEngfuncs = *pEnginefuncs;
+
+ //RecClInitialize(pEnginefuncs, iVersion);
+
+ if (iVersion != CLDLL_INTERFACE_VERSION)
+ return 0;
+
+ memcpy(&gEngfuncs, pEnginefuncs, sizeof(cl_enginefunc_t));
+
+ EV_HookEvents();
+ gHUD.InitExploitPrevention();
+
+ return 1;
+}
+
+
+/*
+==========================
+ HUD_VidInit
+
+Called when the game initializes
+and whenever the vid_mode is changed
+so the HUD can reinitialize itself.
+==========================
+*/
+
+int CL_DLLEXPORT HUD_VidInit( void )
+{
+ gHUD.InitExploitPrevention();
+// RecClHudVidInit();
+ gHUD.VidInit();
+
+ VGui_Startup();
+
+ return 1;
+}
+
+/*
+==========================
+HUD_Init
+
+ Called whenever the client connects
+ to a server. Reinitializes all
+ the hud variables.
+ ==========================
+*/
+
+void CL_DLLEXPORT HUD_Init( void )
+{
+// RecClHudInit();
+ InitInput();
+ gHUD.Init();
+ Scheme_Init();
+}
+
+/*
+void UIDrawVariableBarSpriteHoles(int inSprite, int inX, int inY, float inPercentage)
+{
+ // Assumes that frame 0 is the empty sprite, frame 1 is full sprite
+ const int kEmptyFrame = 0;
+ const int kFullFrame = 1;
+
+ int theSpriteWidth = SPR_Width(inSprite, kFullFrame);
+ int theSpriteHeight = SPR_Height(inSprite, kFullFrame);
+
+ int theColorComponent = 255;
+
+ // Draw empty sprite
+ SPR_Set(inSprite, theColorComponent, theColorComponent, theColorComponent);
+ SPR_DrawHoles(kEmptyFrame, inX, inY, NULL);
+
+ // Draw secondary level if specified, at half brightness
+ int theFilledHeight = theSpriteHeight*inPercentage;
+ theFilledHeight = theSpriteHeight*inPercentage;
+
+ // Draw partially full sprite. Enable scissor so it's not all drawn.
+ SPR_EnableScissor(inX, inY + (theSpriteHeight - theFilledHeight), theSpriteWidth, theFilledHeight);
+
+ SPR_Set(inSprite, theColorComponent, theColorComponent, theColorComponent);
+ SPR_DrawHoles(kFullFrame, inX, inY, NULL);
+
+ SPR_DisableScissor();
+}
+*/
+// Demonstrates black lines around the edge of sprites (both using tri API and SPR_* calls)
+// Demonstrates scissor not working properly
+
+/*
+==========================
+HUD_Redraw
+
+ called every screen frame to
+ redraw the HUD.
+ ===========================
+*/
+
+int CL_DLLEXPORT HUD_Redraw( float time, int intermission )
+{
+// RecClHudRedraw(time, intermission);
+
+ gHUD.Redraw( time, intermission );
+
+ //Direct3DTest();
+
+ //SoftwareTest();
+
+ return 1;
+}
+
+
+/*
+==========================
+ HUD_UpdateClientData
+
+called every time shared client
+dll/engine data gets changed,
+and gives the cdll a chance
+to modify the data.
+
+returns 1 if anything has been changed, 0 otherwise.
+==========================
+*/
+
+int CL_DLLEXPORT HUD_UpdateClientData(client_data_t *pcldata, float flTime )
+{
+// RecClHudUpdateClientData(pcldata, flTime);
+
+ IN_Commands();
+
+ return gHUD.UpdateClientData(pcldata, flTime );
+}
+
+/*
+==========================
+ HUD_Reset
+
+Called at start and end of demos to restore to "non"HUD state.
+==========================
+*/
+
+void CL_DLLEXPORT HUD_Reset( void )
+{
+// RecClHudReset();
+
+ gHUD.VidInit();
+ AvHParticleSystemManager::Instance()->Reset();
+}
+
+/*
+==========================
+HUD_Frame
+
+ Called by engine every frame that client .dll is loaded
+ ==========================
+*/
+
+void CL_DLLEXPORT HUD_Frame( double time )
+{
+// RecClHudFrame(time);
+
+ ServersThink( time );
+
+ GetClientVoiceMgr()->Frame(time);
+}
+
+
+/*
+==========================
+HUD_VoiceStatus
+
+ Called when a player starts or stops talking.
+ ==========================
+*/
+
+void CL_DLLEXPORT HUD_VoiceStatus(int entindex, qboolean bTalking)
+{
+// RecClVoiceStatus(entindex, bTalking);
+
+ GetClientVoiceMgr()->UpdateSpeakerStatus(entindex, bTalking);
+}
+
+/*
+==========================
+HUD_DirectorEvent
+
+ Called when a director event message was received
+ ==========================
+*/
+
+void CL_DLLEXPORT HUD_DirectorMessage( int iSize, void *pbuf )
+{
+// RecClDirectorMessage(iSize, pbuf);
+ gHUD.m_Spectator.DirectorMessage( iSize, pbuf );
+}
+
+
+
+cldll_func_dst_t *g_pcldstAddrs;
+
+extern "C" void CL_DLLEXPORT F(void *pv)
+{
+ cldll_func_t *pcldll_func = (cldll_func_t *)pv;
+
+ // Hack!
+ g_pcldstAddrs = ((cldll_func_dst_t *)pcldll_func->pHudVidInitFunc);
+
+ cldll_func_t cldll_func =
+ {
+ Initialize,
+ HUD_Init,
+ HUD_VidInit,
+ HUD_Redraw,
+ HUD_UpdateClientData,
+ HUD_Reset,
+ HUD_PlayerMove,
+ HUD_PlayerMoveInit,
+ HUD_PlayerMoveTexture,
+ IN_ActivateMouse,
+ IN_DeactivateMouse,
+ IN_MouseEvent,
+ IN_ClearStates,
+ IN_Accumulate,
+ CL_CreateMove,
+ CL_IsThirdPerson,
+ CL_CameraOffset,
+ KB_Find,
+ CAM_Think,
+ V_CalcRefdef,
+ HUD_AddEntity,
+ HUD_CreateEntities,
+ HUD_DrawNormalTriangles,
+ HUD_DrawTransparentTriangles,
+ HUD_StudioEvent,
+ HUD_PostRunCmd,
+ HUD_Shutdown,
+ HUD_TxferLocalOverrides,
+ HUD_ProcessPlayerState,
+ HUD_TxferPredictionData,
+ Demo_ReadBuffer,
+ HUD_ConnectionlessPacket,
+ HUD_GetHullBounds,
+ HUD_Frame,
+ HUD_Key_Event,
+ HUD_TempEntUpdate,
+ HUD_GetUserEntity,
+ HUD_VoiceStatus,
+ HUD_DirectorMessage,
+ HUD_GetStudioModelInterface,
+ //HUD_ChatInputPosition,
+ };
+
+ *pcldll_func = cldll_func;
+}
+
+#include "cl_dll/IGameClientExports.h"
+
+//-----------------------------------------------------------------------------
+// Purpose: Exports functions that are used by the gameUI for UI dialogs
+//-----------------------------------------------------------------------------
+class CClientExports : public IGameClientExports
+{
+public:
+ // returns the name of the server the user is connected to, if any
+ virtual const char *GetServerHostName()
+ {
+ /*if (gViewPortInterface)
+ {
+ return gViewPortInterface->GetServerName();
+ }*/
+ return "";
+ }
+
+ // ingame voice manipulation
+ virtual bool IsPlayerGameVoiceMuted(int playerIndex)
+ {
+ if (GetClientVoiceMgr())
+ return GetClientVoiceMgr()->IsPlayerBlocked(playerIndex);
+ return false;
+ }
+
+ virtual void MutePlayerGameVoice(int playerIndex)
+ {
+ if (GetClientVoiceMgr())
+ {
+ GetClientVoiceMgr()->SetPlayerBlockedState(playerIndex, true);
+ }
+ }
+
+ virtual void UnmutePlayerGameVoice(int playerIndex)
+ {
+ if (GetClientVoiceMgr())
+ {
+ GetClientVoiceMgr()->SetPlayerBlockedState(playerIndex, false);
+ }
+ }
+};
+
+EXPOSE_SINGLE_INTERFACE(CClientExports, IGameClientExports, GAMECLIENTEXPORTS_INTERFACE_VERSION);
diff --git a/main/source/cl_dll/chud.h b/main/source/cl_dll/chud.h
index 87fc1214..b349e857 100644
--- a/main/source/cl_dll/chud.h
+++ b/main/source/cl_dll/chud.h
@@ -1,121 +1,121 @@
-#ifndef CHUD_H
-#define CHUD_H
-
-#include "chudmisc.h"
-#include "hud_spectator.h"
-#include "AvHFont.h"
-
-
-class CHud
-{
-private:
- HUDLIST *m_pHudList;
- HSPRITE m_hsprLogo;
- int m_iLogo;
- client_sprite_t *m_pSpriteList;
- int m_iSpriteCount;
- int m_iSpriteCountAllRes;
- float m_flMouseSensitivity;
-
-public:
-
- HSPRITE m_hsprCursor;
- float m_flTime; // the current client time
- float m_fOldTime; // the time at which the HUD was last redrawn
- double m_flTimeDelta; // the difference between flTime and fOldTime
- Vector m_vecOrigin;
- Vector m_vecAngles;
- int m_iKeyBits;
- int m_iHideHUDDisplay;
- int m_iFOV;
- int m_iRes;
- cvar_t *m_pCvarStealMouse;
- cvar_t *m_pCvarDraw;
-
- int m_iFontHeight;
- int DrawHudNumber(int x, int y, int iFlags, int iNumber, int r, int g, int b );
- int DrawHudStringCentered(int x, int y, int iMaxX, const char *szString, int r, int g, int b );
- int DrawHudString(int x, int y, int iMaxX, const char *szString, int r, int g, int b );
- int GetHudStringHeight();
- int GetHudStringWidth(const char* szIt);
- int DrawHudStringReverse( int xpos, int ypos, int iMinX, char *szString, int r, int g, int b );
- int DrawHudNumberString( int xpos, int ypos, int iMinX, int iNumber, int r, int g, int b );
- int GetNumWidth(int iNumber, int iFlags);
-
-private:
- // the memory for these arrays are allocated in the first call to CHud::VidInit(), when the hud.txt and associated sprites are loaded.
- // freed in ~CHud()
- HSPRITE *m_rghSprites; /*[HUD_SPRITE_COUNT]*/ // the sprites loaded from hud.txt
- wrect_t *m_rgrcRects; /*[HUD_SPRITE_COUNT]*/
- char *m_rgszSpriteNames; /*[HUD_SPRITE_COUNT][MAX_SPRITE_NAME_LENGTH]*/
-
- struct cvar_s *default_fov;
-
-
-public:
- HSPRITE GetSprite( int index )
- {
- return (index < 0) ? 0 : m_rghSprites[index];
- }
-
- wrect_t& GetSpriteRect( int index )
- {
- return m_rgrcRects[index];
- }
-
-
- int GetSpriteIndex( const char *SpriteName ); // gets a sprite index, for use in the m_rghSprites[] array
-
- CHudAmmo m_Ammo;
- CHudHealth m_Health;
- CHudSpectator m_Spectator;
- CHudGeiger m_Geiger;
- CHudBattery m_Battery;
- CHudTrain m_Train;
- CHudFlashlight m_Flash;
- CHudMessage m_Message;
- CHudStatusBar m_StatusBar;
- CHudDeathNotice m_DeathNotice;
- CHudSayText m_SayText;
- CHudMenu m_Menu;
- CHudAmmoSecondary m_AmmoSecondary;
- CHudTextMessage m_TextMessage;
- CHudStatusIcons m_StatusIcons;
-
- AvHFont mFont;
- AvHFont mSmallFont;
-
- void Init( void );
- void VidInit( void );
- void Think(void);
- int Redraw( float flTime, int intermission );
- int UpdateClientData( client_data_t *cdata, float time );
-
- CHud() : m_iSpriteCount(0), m_pHudList(NULL) {}
- ~CHud(); // destructor, frees allocated memory
-
- // user messages
- int _cdecl MsgFunc_ResetHUD(const char *pszName, int iSize, void *pbuf);
- void _cdecl MsgFunc_InitHUD( const char *pszName, int iSize, void *pbuf );
- void _cdecl MsgFunc_ViewMode( const char *pszName, int iSize, void *pbuf );
- int _cdecl MsgFunc_SetFOV(const char *pszName, int iSize, void *pbuf);
-
- // Screen information
- SCREENINFO m_scrinfo;
-
- int m_iWeaponBits;
- int m_fPlayerDead;
- int m_iIntermission;
-
- // sprite indexes
- int m_HUD_number_0;
-
- void AddHudElem(CHudBase *p);
-
- float GetSensitivity();
-
-};
-
-
-
-#endif
+#ifndef CHUD_H
+#define CHUD_H
+
+#include "chudmisc.h"
+#include "hud_spectator.h"
+#include "AvHFont.h"
+
+
+class CHud
+{
+private:
+ HUDLIST *m_pHudList;
+ HSPRITE m_hsprLogo;
+ int m_iLogo;
+ client_sprite_t *m_pSpriteList;
+ int m_iSpriteCount;
+ int m_iSpriteCountAllRes;
+ float m_flMouseSensitivity;
+
+public:
+
+ HSPRITE m_hsprCursor;
+ float m_flTime; // the current client time
+ float m_fOldTime; // the time at which the HUD was last redrawn
+ double m_flTimeDelta; // the difference between flTime and fOldTime
+ Vector m_vecOrigin;
+ Vector m_vecAngles;
+ int m_iKeyBits;
+ int m_iHideHUDDisplay;
+ int m_iFOV;
+ int m_iRes;
+ cvar_t *m_pCvarStealMouse;
+ cvar_t *m_pCvarDraw;
+
+ int m_iFontHeight;
+ int DrawHudNumber(int x, int y, int iFlags, int iNumber, int r, int g, int b );
+ int DrawHudStringCentered(int x, int y, int iMaxX, const char *szString, int r, int g, int b );
+ int DrawHudString(int x, int y, int iMaxX, const char *szString, int r, int g, int b );
+ int GetHudStringHeight();
+ int GetHudStringWidth(const char* szIt);
+ int DrawHudStringReverse( int xpos, int ypos, int iMinX, char *szString, int r, int g, int b );
+ int DrawHudNumberString( int xpos, int ypos, int iMinX, int iNumber, int r, int g, int b );
+ int GetNumWidth(int iNumber, int iFlags);
+
+private:
+ // the memory for these arrays are allocated in the first call to CHud::VidInit(), when the hud.txt and associated sprites are loaded.
+ // freed in ~CHud()
+ HSPRITE *m_rghSprites; /*[HUD_SPRITE_COUNT]*/ // the sprites loaded from hud.txt
+ wrect_t *m_rgrcRects; /*[HUD_SPRITE_COUNT]*/
+ char *m_rgszSpriteNames; /*[HUD_SPRITE_COUNT][MAX_SPRITE_NAME_LENGTH]*/
+
+ struct cvar_s *default_fov;
+
+
+public:
+ HSPRITE GetSprite( int index )
+ {
+ return (index < 0) ? 0 : m_rghSprites[index];
+ }
+
+ wrect_t& GetSpriteRect( int index )
+ {
+ return m_rgrcRects[index];
+ }
+
+
+ int GetSpriteIndex( const char *SpriteName ); // gets a sprite index, for use in the m_rghSprites[] array
+
+ CHudAmmo m_Ammo;
+ CHudHealth m_Health;
+ CHudSpectator m_Spectator;
+ CHudGeiger m_Geiger;
+ CHudBattery m_Battery;
+ CHudTrain m_Train;
+ CHudFlashlight m_Flash;
+ CHudMessage m_Message;
+ CHudStatusBar m_StatusBar;
+ CHudDeathNotice m_DeathNotice;
+ CHudSayText m_SayText;
+ CHudMenu m_Menu;
+ CHudAmmoSecondary m_AmmoSecondary;
+ CHudTextMessage m_TextMessage;
+ CHudStatusIcons m_StatusIcons;
+
+ AvHFont mFont;
+ AvHFont mSmallFont;
+
+ void Init( void );
+ void VidInit( void );
+ void Think(void);
+ int Redraw( float flTime, int intermission );
+ int UpdateClientData( client_data_t *cdata, float time );
+
+ CHud() : m_iSpriteCount(0), m_pHudList(NULL) {}
+ ~CHud(); // destructor, frees allocated memory
+
+ // user messages
+ int _cdecl MsgFunc_ResetHUD(const char *pszName, int iSize, void *pbuf);
+ void _cdecl MsgFunc_InitHUD( const char *pszName, int iSize, void *pbuf );
+ void _cdecl MsgFunc_ViewMode( const char *pszName, int iSize, void *pbuf );
+ int _cdecl MsgFunc_SetFOV(const char *pszName, int iSize, void *pbuf);
+
+ // Screen information
+ SCREENINFO m_scrinfo;
+
+ int m_iWeaponBits;
+ int m_fPlayerDead;
+ int m_iIntermission;
+
+ // sprite indexes
+ int m_HUD_number_0;
+
+ void AddHudElem(CHudBase *p);
+
+ float GetSensitivity();
+
+};
+
+
+
+#endif
diff --git a/main/source/cl_dll/chudmisc.h b/main/source/cl_dll/chudmisc.h
index 45423139..a5c7b1e2 100644
--- a/main/source/cl_dll/chudmisc.h
+++ b/main/source/cl_dll/chudmisc.h
@@ -1,506 +1,506 @@
-#ifndef CHUDMISC_H
-#define CHUDMISC_H
-
-#define RGB_YELLOWISH 0x00FFA000 //255,160,0
-#define RGB_REDISH 0x00FF1010 //255,160,0
-#define RGB_GREENISH 0x0000A000 //0,160,0
-#define RGB_MARINE_BLUE 0x000099FF //0 153 255
-#define RGB_MARINE_SELECTED 0x006EE6FF //110, 230, 255
-#define RGB_MARINE_PARASITED 0x00E3F03D //227, 240, 61
-
-
-#ifndef _WIN32
-#define _cdecl
-#else
-#undef _cdecl
-#endif
-
-#include "wrect.h"
-#include "cl_dll.h"
-#include "ammo.h"
-#include "teamconst.h"
-
-#define DHN_DRAWZERO 1
-#define DHN_2DIGITS 2
-#define DHN_3DIGITS 4
-#define MIN_ALPHA 100
-
-#define HUDELEM_ACTIVE 1
-
-typedef struct {
- int x, y;
-} POSITION;
-
-typedef struct {
- unsigned char r,g,b,a;
-} RGBA;
-
-typedef struct cvar_s cvar_t;
-
-
-#define HUD_ACTIVE 1
-#define HUD_INTERMISSION 2
-
-#define MAX_PLAYER_NAME_LENGTH 32
-
-#define MAX_MOTD_LENGTH 1536
-
-//
-//-----------------------------------------------------
-//
-class CHudBase
-{
-public:
- POSITION m_pos;
- int m_type;
- int m_iFlags; // active, moving,
- virtual ~CHudBase() {}
- virtual int Init( void ) {return 0;}
- virtual int VidInit( void ) {return 0;}
- virtual int Draw(float flTime) {return 0;}
- virtual void Think(void) {return;}
- virtual void Reset(void) {return;}
- virtual void InitHUDData( void ) {} // called every time a server is connected to
-
-};
-
-struct HUDLIST {
- CHudBase *p;
- HUDLIST *pNext;
-};
-
-
-
-//
-//-----------------------------------------------------
-//
-#include "voice_status.h"
-#include "hud_spectator.h"
-
-
-//
-//-----------------------------------------------------
-//
-class CHudAmmo: public CHudBase
-{
-public:
- int Init( void );
- int VidInit( void );
- int Draw(float flTime);
- void Think(void);
- void Reset(void);
- int DrawWList(float flTime);
- int MsgFunc_CurWeapon(const char *pszName, int iSize, void *pbuf);
- int MsgFunc_WeaponList(const char *pszName, int iSize, void *pbuf);
- int MsgFunc_AmmoX(const char *pszName, int iSize, void *pbuf);
- int MsgFunc_AmmoPickup( const char *pszName, int iSize, void *pbuf );
- int MsgFunc_WeapPickup( const char *pszName, int iSize, void *pbuf );
- int MsgFunc_ItemPickup( const char *pszName, int iSize, void *pbuf );
- int MsgFunc_HideWeapon( const char *pszName, int iSize, void *pbuf );
-
- void SlotInput( int iSlot );
- void _cdecl UserCmd_Slot1( void );
- void _cdecl UserCmd_Slot2( void );
- void _cdecl UserCmd_Slot3( void );
- void _cdecl UserCmd_Slot4( void );
- void _cdecl UserCmd_Slot5( void );
- void _cdecl UserCmd_Slot6( void );
- void _cdecl UserCmd_Slot7( void );
- void _cdecl UserCmd_Slot8( void );
- void _cdecl UserCmd_Slot9( void );
- void _cdecl UserCmd_Slot10( void );
- void _cdecl UserCmd_Close( void );
- void _cdecl UserCmd_NextWeapon( void );
- void _cdecl UserCmd_PrevWeapon( void );
-
- void SetCurrentClip(int inClip);
-private:
- float m_fFade;
- RGBA m_rgba;
- WEAPON *m_pWeapon;
- int m_HUD_bucket0;
- int m_HUD_selection;
- int m_customCrosshair;
-
-};
-
-
-
-//
-//-----------------------------------------------------
-//
-class CHudAmmoSecondary: public CHudBase
-{
-public:
- int Init( void );
- int VidInit( void );
- void Reset( void );
- int Draw(float flTime);
-
- int MsgFunc_SecAmmoVal( const char *pszName, int iSize, void *pbuf );
- int MsgFunc_SecAmmoIcon( const char *pszName, int iSize, void *pbuf );
-
-private:
- enum {
- MAX_SEC_AMMO_VALUES = 4
- };
-
- int m_HUD_ammoicon; // sprite indices
- int m_iAmmoAmounts[MAX_SEC_AMMO_VALUES];
- float m_fFade;
-};
-
-
-#include "health.h"
-
-
-#define FADE_TIME 100
-
-
-
-
-//
-//-----------------------------------------------------
-//
-class CHudGeiger: public CHudBase
-{
-public:
- int Init( void );
- int VidInit( void );
- int Draw(float flTime);
- int MsgFunc_Geiger(const char *pszName, int iSize, void *pbuf);
-
-private:
- int m_iGeigerRange;
-
-};
-
-//
-//-----------------------------------------------------
-//
-class CHudTrain: public CHudBase
-{
-public:
- int Init( void );
- int VidInit( void );
- int Draw(float flTime);
- int MsgFunc_Train(const char *pszName, int iSize, void *pbuf);
-
-private:
- HSPRITE m_hSprite;
- int m_iPos;
-
-};
-
-//
-//-----------------------------------------------------
-//
-class CHudStatusBar : public CHudBase
-{
-public:
- int Init( void );
- int VidInit( void );
- int Draw( float flTime );
- const char* GetStatusString() const;
- void Reset( void );
- void ParseStatusString( int line_num );
-
- int MsgFunc_StatusText( const char *pszName, int iSize, void *pbuf );
- int MsgFunc_StatusValue( const char *pszName, int iSize, void *pbuf );
-
-protected:
- void ReparseStringIfNeeded();
-
- enum {
- MAX_STATUSTEXT_LENGTH = 128,
- MAX_STATUSBAR_VALUES = 8,
- MAX_STATUSBAR_LINES = 2,
- };
-
- char m_szStatusText[MAX_STATUSBAR_LINES][MAX_STATUSTEXT_LENGTH]; // a text string describing how the status bar is to be drawn
- char m_szStatusBar[MAX_STATUSBAR_LINES][MAX_STATUSTEXT_LENGTH]; // the constructed bar that is drawn
- int m_iStatusValues[MAX_STATUSBAR_VALUES]; // an array of values for use in the status bar
-
- int m_bReparseString; // set to TRUE whenever the m_szStatusBar needs to be recalculated
-
- // an array of colors...one color for each line
- float *m_pflNameColors[MAX_STATUSBAR_LINES];
-};
-
-class ScoreboardIcon;
-// : 0001073
-#define CUSTOM_ICON_LENGTH 32
-
-struct extra_player_info_t
-{
- short score;
- short lastScore;
- float timeOfLastScoreChange;
- short frags;
- short deaths;
- short playerclass;
- short extra;
- short auth;
- short teamnumber;
- char teamname[MAX_TEAM_NAME];
- char customicon[CUSTOM_ICON_LENGTH + 3]; //last 3 characters is the color.
- short health;
- ScoreboardIcon* icon;
-};
-
-struct team_info_t
-{
- char name[MAX_TEAM_NAME];
- short score;
- short frags;
- short deaths;
- short ping;
- short packetloss;
- short ownteam;
- short players;
- int already_drawn;
- int scores_overriden;
- int teamnumber;
-};
-
-extern hud_player_info_t g_PlayerInfoList[MAX_PLAYERS+1]; // player info from the engine
-extern extra_player_info_t g_PlayerExtraInfo[MAX_PLAYERS+1]; // additional player info sent directly to the client dll
-extern team_info_t g_TeamInfo[MAX_TEAMS+1];
-extern int g_IsSpectator[MAX_PLAYERS+1];
-
-
-//
-//-----------------------------------------------------
-//
-class CHudDeathNotice : public CHudBase
-{
-public:
- int Init( void );
- void InitHUDData( void );
- int VidInit( void );
- int Draw( float flTime );
- int MsgFunc_DeathMsg( const char *pszName, int iSize, void *pbuf );
-
-private:
- int m_HUD_d_skull; // sprite index of skull icon
-};
-
-
-//
-//-----------------------------------------------------
-//
-class CHudMenu : public CHudBase
-{
-public:
- int Init( void );
- void InitHUDData( void );
- int VidInit( void );
- void Reset( void );
- int Draw( float flTime );
- int MsgFunc_ShowMenu( const char *pszName, int iSize, void *pbuf );
-
- void SelectMenuItem( int menu_item );
-
- int m_fMenuDisplayed;
- int m_bitsValidSlots;
- float m_flShutoffTime;
- int m_fWaitingForMore;
-};
-
-
-//
-//-----------------------------------------------------
-//
-class CHudSayText : public CHudBase
-{
-public:
- int Init( void );
- void InitHUDData( void );
- int VidInit( void );
- int Draw( float flTime );
- int MsgFunc_SayText( const char *pszName, int iSize, void *pbuf );
- void SayTextPrint( const char *pszBuf, int iBufSize, int clientIndex = -1 );
- void EnsureTextFitsInOneLineAndWrapIfHaveTo( int line );
-friend class CHud;
-friend class CHudSpectator;
-
-private:
-
- struct cvar_s * m_HUD_saytext;
- struct cvar_s * m_HUD_saytext_time;
-};
-
-
-//
-//-----------------------------------------------------
-//
-class CHudBattery: public CHudBase
-{
-public:
- int Init( void );
- int VidInit( void );
- int Draw(float flTime);
- int MsgFunc_Battery(const char *pszName, int iSize, void *pbuf );
-
-private:
- HSPRITE m_hSprite1;
- HSPRITE m_hSprite2;
- wrect_t *m_prc1;
- wrect_t *m_prc2;
- int m_iBat;
- float m_fFade;
- int m_iHeight; // width of the battery innards
-};
-
-
-
-//
-//-----------------------------------------------------
-//
-class CHudFlashlight: public CHudBase
-{
-public:
- int Init( void );
- int VidInit( void );
- int Draw(float flTime);
- void Reset( void );
- int MsgFunc_Flashlight(const char *pszName, int iSize, void *pbuf );
- int MsgFunc_FlashBat(const char *pszName, int iSize, void *pbuf );
-
-private:
- HSPRITE m_hSprite1;
- HSPRITE m_hSprite2;
- HSPRITE m_hBeam;
- wrect_t *m_prc1;
- wrect_t *m_prc2;
- wrect_t *m_prcBeam;
- float m_flBat;
- int m_iBat;
- int m_fOn;
- float m_fFade;
- int m_iWidth; // width of the battery innards
-};
-
-
-//
-//-----------------------------------------------------
-//
-const int maxHUDMessages = 16;
-struct message_parms_t
-{
- client_textmessage_t *pMessage;
- float time;
- int x, y;
- int totalWidth, totalHeight;
- int width;
- int lines;
- int lineLength;
- int length;
- int r, g, b;
- int text;
- int fadeBlend;
- float charTime;
- float fadeTime;
-};
-
-
-//
-//-----------------------------------------------------
-//
-class CHudTextMessage: public CHudBase
-{
-public:
- int Init( void );
- static char *LocaliseTextString( const char *msg, char *dst_buffer, int buffer_size );
- static char *BufferedLocaliseTextString( const char *msg );
- char *LookupString( const char *msg_name, int *msg_dest = NULL );
- int MsgFunc_TextMsg(const char *pszName, int iSize, void *pbuf);
-};
-
-
-//
-//-----------------------------------------------------
-//
-
-class CHudMessage: public CHudBase
-{
-public:
- int Init( void );
- int VidInit( void );
- int Draw(float flTime);
- int MsgFunc_HudText(const char *pszName, int iSize, void *pbuf);
- int MsgFunc_HudText2(const char *pszName, int iSize, void *pbuf);
- int MsgFunc_GameTitle(const char *pszName, int iSize, void *pbuf);
-
- float FadeBlend( float fadein, float fadeout, float hold, float localTime );
- int XPosition( float x, int width, int lineWidth );
- int YPosition( float y, int height );
-
- void MessageAddPlayerID(const char* pName, bool inEnemy);
-
- void MessageAdd( const char *pName, float time );
- bool MessageRemove( const char *pName );
- void MessageDrawScan( client_textmessage_t *pMessage, float time );
- void MessageScanStart( void );
- void MessageScanNextChar( void );
- void Reset( void );
-
-private:
- bool DrawMessage(client_textmessage_t* inMessage, float inStartTime, float inCurrentTime);
- void SetPlayerIDPosition();
-
- client_textmessage_t *m_pMessages[maxHUDMessages];
- float m_startTime[maxHUDMessages];
- message_parms_t m_parms;
- float m_gameTitleTime;
- client_textmessage_t *m_pGameTitle;
-
- client_textmessage_t mPlayerIDMessage;
- float mPlayerIDTime;
- char* mPlayerID;
-
- int m_HUD_title_life;
- int m_HUD_title_half;
-};
-
-//
-//-----------------------------------------------------
-//
-#define MAX_SPRITE_NAME_LENGTH 24
-
-class CHudStatusIcons: public CHudBase
-{
-public:
- int Init( void );
- int VidInit( void );
- void Reset( void );
- int Draw(float flTime);
-
- enum {
- MAX_ICONSPRITENAME_LENGTH = MAX_SPRITE_NAME_LENGTH,
- MAX_ICONSPRITES = 4,
- };
-
-
- //had to make these public so CHud could access them (to enable concussion icon)
- //could use a friend declaration instead...
- void EnableIcon( char *pszIconName, unsigned char red, unsigned char green, unsigned char blue );
- void DisableIcon( char *pszIconName );
-
-private:
-
- typedef struct
- {
- char szSpriteName[MAX_ICONSPRITENAME_LENGTH];
- HSPRITE spr;
- wrect_t rc;
- unsigned char r, g, b;
- } icon_sprite_t;
-
- icon_sprite_t m_IconList[MAX_ICONSPRITES];
-
-};
-
-typedef struct cvar_s cvar_t;
-
-#endif
+#ifndef CHUDMISC_H
+#define CHUDMISC_H
+
+#define RGB_YELLOWISH 0x00FFA000 //255,160,0
+#define RGB_REDISH 0x00FF1010 //255,160,0
+#define RGB_GREENISH 0x0000A000 //0,160,0
+#define RGB_MARINE_BLUE 0x000099FF //0 153 255
+#define RGB_MARINE_SELECTED 0x006EE6FF //110, 230, 255
+#define RGB_MARINE_PARASITED 0x00E3F03D //227, 240, 61
+
+
+#ifndef _WIN32
+#define _cdecl
+#else
+#undef _cdecl
+#endif
+
+#include "wrect.h"
+#include "cl_dll.h"
+#include "ammo.h"
+#include "teamconst.h"
+
+#define DHN_DRAWZERO 1
+#define DHN_2DIGITS 2
+#define DHN_3DIGITS 4
+#define MIN_ALPHA 100
+
+#define HUDELEM_ACTIVE 1
+
+typedef struct {
+ int x, y;
+} POSITION;
+
+typedef struct {
+ unsigned char r,g,b,a;
+} RGBA;
+
+typedef struct cvar_s cvar_t;
+
+
+#define HUD_ACTIVE 1
+#define HUD_INTERMISSION 2
+
+#define MAX_PLAYER_NAME_LENGTH 32
+
+#define MAX_MOTD_LENGTH 1536
+
+//
+//-----------------------------------------------------
+//
+class CHudBase
+{
+public:
+ POSITION m_pos;
+ int m_type;
+ int m_iFlags; // active, moving,
+ virtual ~CHudBase() {}
+ virtual int Init( void ) {return 0;}
+ virtual int VidInit( void ) {return 0;}
+ virtual int Draw(float flTime) {return 0;}
+ virtual void Think(void) {return;}
+ virtual void Reset(void) {return;}
+ virtual void InitHUDData( void ) {} // called every time a server is connected to
+
+};
+
+struct HUDLIST {
+ CHudBase *p;
+ HUDLIST *pNext;
+};
+
+
+
+//
+//-----------------------------------------------------
+//
+#include "voice_status.h"
+#include "hud_spectator.h"
+
+
+//
+//-----------------------------------------------------
+//
+class CHudAmmo: public CHudBase
+{
+public:
+ int Init( void );
+ int VidInit( void );
+ int Draw(float flTime);
+ void Think(void);
+ void Reset(void);
+ int DrawWList(float flTime);
+ int MsgFunc_CurWeapon(const char *pszName, int iSize, void *pbuf);
+ int MsgFunc_WeaponList(const char *pszName, int iSize, void *pbuf);
+ int MsgFunc_AmmoX(const char *pszName, int iSize, void *pbuf);
+ int MsgFunc_AmmoPickup( const char *pszName, int iSize, void *pbuf );
+ int MsgFunc_WeapPickup( const char *pszName, int iSize, void *pbuf );
+ int MsgFunc_ItemPickup( const char *pszName, int iSize, void *pbuf );
+ int MsgFunc_HideWeapon( const char *pszName, int iSize, void *pbuf );
+
+ void SlotInput( int iSlot );
+ void _cdecl UserCmd_Slot1( void );
+ void _cdecl UserCmd_Slot2( void );
+ void _cdecl UserCmd_Slot3( void );
+ void _cdecl UserCmd_Slot4( void );
+ void _cdecl UserCmd_Slot5( void );
+ void _cdecl UserCmd_Slot6( void );
+ void _cdecl UserCmd_Slot7( void );
+ void _cdecl UserCmd_Slot8( void );
+ void _cdecl UserCmd_Slot9( void );
+ void _cdecl UserCmd_Slot10( void );
+ void _cdecl UserCmd_Close( void );
+ void _cdecl UserCmd_NextWeapon( void );
+ void _cdecl UserCmd_PrevWeapon( void );
+
+ void SetCurrentClip(int inClip);
+private:
+ float m_fFade;
+ RGBA m_rgba;
+ WEAPON *m_pWeapon;
+ int m_HUD_bucket0;
+ int m_HUD_selection;
+ int m_customCrosshair;
+
+};
+
+
+
+//
+//-----------------------------------------------------
+//
+class CHudAmmoSecondary: public CHudBase
+{
+public:
+ int Init( void );
+ int VidInit( void );
+ void Reset( void );
+ int Draw(float flTime);
+
+ int MsgFunc_SecAmmoVal( const char *pszName, int iSize, void *pbuf );
+ int MsgFunc_SecAmmoIcon( const char *pszName, int iSize, void *pbuf );
+
+private:
+ enum {
+ MAX_SEC_AMMO_VALUES = 4
+ };
+
+ int m_HUD_ammoicon; // sprite indices
+ int m_iAmmoAmounts[MAX_SEC_AMMO_VALUES];
+ float m_fFade;
+};
+
+
+#include "health.h"
+
+
+#define FADE_TIME 100
+
+
+
+
+//
+//-----------------------------------------------------
+//
+class CHudGeiger: public CHudBase
+{
+public:
+ int Init( void );
+ int VidInit( void );
+ int Draw(float flTime);
+ int MsgFunc_Geiger(const char *pszName, int iSize, void *pbuf);
+
+private:
+ int m_iGeigerRange;
+
+};
+
+//
+//-----------------------------------------------------
+//
+class CHudTrain: public CHudBase
+{
+public:
+ int Init( void );
+ int VidInit( void );
+ int Draw(float flTime);
+ int MsgFunc_Train(const char *pszName, int iSize, void *pbuf);
+
+private:
+ HSPRITE m_hSprite;
+ int m_iPos;
+
+};
+
+//
+//-----------------------------------------------------
+//
+class CHudStatusBar : public CHudBase
+{
+public:
+ int Init( void );
+ int VidInit( void );
+ int Draw( float flTime );
+ const char* GetStatusString() const;
+ void Reset( void );
+ void ParseStatusString( int line_num );
+
+ int MsgFunc_StatusText( const char *pszName, int iSize, void *pbuf );
+ int MsgFunc_StatusValue( const char *pszName, int iSize, void *pbuf );
+
+protected:
+ void ReparseStringIfNeeded();
+
+ enum {
+ MAX_STATUSTEXT_LENGTH = 128,
+ MAX_STATUSBAR_VALUES = 8,
+ MAX_STATUSBAR_LINES = 2,
+ };
+
+ char m_szStatusText[MAX_STATUSBAR_LINES][MAX_STATUSTEXT_LENGTH]; // a text string describing how the status bar is to be drawn
+ char m_szStatusBar[MAX_STATUSBAR_LINES][MAX_STATUSTEXT_LENGTH]; // the constructed bar that is drawn
+ int m_iStatusValues[MAX_STATUSBAR_VALUES]; // an array of values for use in the status bar
+
+ int m_bReparseString; // set to TRUE whenever the m_szStatusBar needs to be recalculated
+
+ // an array of colors...one color for each line
+ float *m_pflNameColors[MAX_STATUSBAR_LINES];
+};
+
+class ScoreboardIcon;
+// : 0001073
+#define CUSTOM_ICON_LENGTH 32
+
+struct extra_player_info_t
+{
+ short score;
+ short lastScore;
+ float timeOfLastScoreChange;
+ short frags;
+ short deaths;
+ short playerclass;
+ short extra;
+ short auth;
+ short teamnumber;
+ char teamname[MAX_TEAM_NAME];
+ char customicon[CUSTOM_ICON_LENGTH + 3]; //last 3 characters is the color.
+ short health;
+ ScoreboardIcon* icon;
+};
+
+struct team_info_t
+{
+ char name[MAX_TEAM_NAME];
+ short score;
+ short frags;
+ short deaths;
+ short ping;
+ short packetloss;
+ short ownteam;
+ short players;
+ int already_drawn;
+ int scores_overriden;
+ int teamnumber;
+};
+
+extern hud_player_info_t g_PlayerInfoList[MAX_PLAYERS+1]; // player info from the engine
+extern extra_player_info_t g_PlayerExtraInfo[MAX_PLAYERS+1]; // additional player info sent directly to the client dll
+extern team_info_t g_TeamInfo[MAX_TEAMS+1];
+extern int g_IsSpectator[MAX_PLAYERS+1];
+
+
+//
+//-----------------------------------------------------
+//
+class CHudDeathNotice : public CHudBase
+{
+public:
+ int Init( void );
+ void InitHUDData( void );
+ int VidInit( void );
+ int Draw( float flTime );
+ int MsgFunc_DeathMsg( const char *pszName, int iSize, void *pbuf );
+
+private:
+ int m_HUD_d_skull; // sprite index of skull icon
+};
+
+
+//
+//-----------------------------------------------------
+//
+class CHudMenu : public CHudBase
+{
+public:
+ int Init( void );
+ void InitHUDData( void );
+ int VidInit( void );
+ void Reset( void );
+ int Draw( float flTime );
+ int MsgFunc_ShowMenu( const char *pszName, int iSize, void *pbuf );
+
+ void SelectMenuItem( int menu_item );
+
+ int m_fMenuDisplayed;
+ int m_bitsValidSlots;
+ float m_flShutoffTime;
+ int m_fWaitingForMore;
+};
+
+
+//
+//-----------------------------------------------------
+//
+class CHudSayText : public CHudBase
+{
+public:
+ int Init( void );
+ void InitHUDData( void );
+ int VidInit( void );
+ int Draw( float flTime );
+ int MsgFunc_SayText( const char *pszName, int iSize, void *pbuf );
+ void SayTextPrint( const char *pszBuf, int iBufSize, int clientIndex = -1 );
+ void EnsureTextFitsInOneLineAndWrapIfHaveTo( int line );
+friend class CHud;
+friend class CHudSpectator;
+
+private:
+
+ struct cvar_s * m_HUD_saytext;
+ struct cvar_s * m_HUD_saytext_time;
+};
+
+
+//
+//-----------------------------------------------------
+//
+class CHudBattery: public CHudBase
+{
+public:
+ int Init( void );
+ int VidInit( void );
+ int Draw(float flTime);
+ int MsgFunc_Battery(const char *pszName, int iSize, void *pbuf );
+
+private:
+ HSPRITE m_hSprite1;
+ HSPRITE m_hSprite2;
+ wrect_t *m_prc1;
+ wrect_t *m_prc2;
+ int m_iBat;
+ float m_fFade;
+ int m_iHeight; // width of the battery innards
+};
+
+
+
+//
+//-----------------------------------------------------
+//
+class CHudFlashlight: public CHudBase
+{
+public:
+ int Init( void );
+ int VidInit( void );
+ int Draw(float flTime);
+ void Reset( void );
+ int MsgFunc_Flashlight(const char *pszName, int iSize, void *pbuf );
+ int MsgFunc_FlashBat(const char *pszName, int iSize, void *pbuf );
+
+private:
+ HSPRITE m_hSprite1;
+ HSPRITE m_hSprite2;
+ HSPRITE m_hBeam;
+ wrect_t *m_prc1;
+ wrect_t *m_prc2;
+ wrect_t *m_prcBeam;
+ float m_flBat;
+ int m_iBat;
+ int m_fOn;
+ float m_fFade;
+ int m_iWidth; // width of the battery innards
+};
+
+
+//
+//-----------------------------------------------------
+//
+const int maxHUDMessages = 16;
+struct message_parms_t
+{
+ client_textmessage_t *pMessage;
+ float time;
+ int x, y;
+ int totalWidth, totalHeight;
+ int width;
+ int lines;
+ int lineLength;
+ int length;
+ int r, g, b;
+ int text;
+ int fadeBlend;
+ float charTime;
+ float fadeTime;
+};
+
+
+//
+//-----------------------------------------------------
+//
+class CHudTextMessage: public CHudBase
+{
+public:
+ int Init( void );
+ static char *LocaliseTextString( const char *msg, char *dst_buffer, int buffer_size );
+ static char *BufferedLocaliseTextString( const char *msg );
+ char *LookupString( const char *msg_name, int *msg_dest = NULL );
+ int MsgFunc_TextMsg(const char *pszName, int iSize, void *pbuf);
+};
+
+
+//
+//-----------------------------------------------------
+//
+
+class CHudMessage: public CHudBase
+{
+public:
+ int Init( void );
+ int VidInit( void );
+ int Draw(float flTime);
+ int MsgFunc_HudText(const char *pszName, int iSize, void *pbuf);
+ int MsgFunc_HudText2(const char *pszName, int iSize, void *pbuf);
+ int MsgFunc_GameTitle(const char *pszName, int iSize, void *pbuf);
+
+ float FadeBlend( float fadein, float fadeout, float hold, float localTime );
+ int XPosition( float x, int width, int lineWidth );
+ int YPosition( float y, int height );
+
+ void MessageAddPlayerID(const char* pName, bool inEnemy);
+
+ void MessageAdd( const char *pName, float time );
+ bool MessageRemove( const char *pName );
+ void MessageDrawScan( client_textmessage_t *pMessage, float time );
+ void MessageScanStart( void );
+ void MessageScanNextChar( void );
+ void Reset( void );
+
+private:
+ bool DrawMessage(client_textmessage_t* inMessage, float inStartTime, float inCurrentTime);
+ void SetPlayerIDPosition();
+
+ client_textmessage_t *m_pMessages[maxHUDMessages];
+ float m_startTime[maxHUDMessages];
+ message_parms_t m_parms;
+ float m_gameTitleTime;
+ client_textmessage_t *m_pGameTitle;
+
+ client_textmessage_t mPlayerIDMessage;
+ float mPlayerIDTime;
+ char* mPlayerID;
+
+ int m_HUD_title_life;
+ int m_HUD_title_half;
+};
+
+//
+//-----------------------------------------------------
+//
+#define MAX_SPRITE_NAME_LENGTH 24
+
+class CHudStatusIcons: public CHudBase
+{
+public:
+ int Init( void );
+ int VidInit( void );
+ void Reset( void );
+ int Draw(float flTime);
+
+ enum {
+ MAX_ICONSPRITENAME_LENGTH = MAX_SPRITE_NAME_LENGTH,
+ MAX_ICONSPRITES = 4,
+ };
+
+
+ //had to make these public so CHud could access them (to enable concussion icon)
+ //could use a friend declaration instead...
+ void EnableIcon( char *pszIconName, unsigned char red, unsigned char green, unsigned char blue );
+ void DisableIcon( char *pszIconName );
+
+private:
+
+ typedef struct
+ {
+ char szSpriteName[MAX_ICONSPRITENAME_LENGTH];
+ HSPRITE spr;
+ wrect_t rc;
+ unsigned char r, g, b;
+ } icon_sprite_t;
+
+ icon_sprite_t m_IconList[MAX_ICONSPRITES];
+
+};
+
+typedef struct cvar_s cvar_t;
+
+#endif
diff --git a/main/source/cl_dll/cl_dll.h b/main/source/cl_dll/cl_dll.h
index 20234309..cd9be37e 100644
--- a/main/source/cl_dll/cl_dll.h
+++ b/main/source/cl_dll/cl_dll.h
@@ -1,36 +1,36 @@
-/***
-*
+/***
+*
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
-*
-* This product contains software technology licensed from Id
-* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
-* All Rights Reserved.
-*
-* Use, distribution, and modification of this source code and/or resulting
-* object code is restricted to non-commercial enhancements to products from
-* Valve LLC. All other use, distribution, or modification is prohibited
-* without written permission from Valve LLC.
-*
-****/
-//
-// cl_dll.h
-//
-
-// 4-23-98 JOHN
-
-//
-// This DLL is linked by the client when they first initialize.
-// This DLL is responsible for the following tasks:
-// - Loading the HUD graphics upon initialization
-// - Drawing the HUD graphics every frame
-// - Handling the custum HUD-update packets
-//
-typedef unsigned char byte;
-typedef unsigned short word;
-typedef float vec_t;
-typedef int (*pfnUserMsgHook)(const char *pszName, int iSize, void *pbuf);
-
-#include "util_vector.h"
+*
+* This product contains software technology licensed from Id
+* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
+* All Rights Reserved.
+*
+* Use, distribution, and modification of this source code and/or resulting
+* object code is restricted to non-commercial enhancements to products from
+* Valve LLC. All other use, distribution, or modification is prohibited
+* without written permission from Valve LLC.
+*
+****/
+//
+// cl_dll.h
+//
+
+// 4-23-98 JOHN
+
+//
+// This DLL is linked by the client when they first initialize.
+// This DLL is responsible for the following tasks:
+// - Loading the HUD graphics upon initialization
+// - Drawing the HUD graphics every frame
+// - Handling the custum HUD-update packets
+//
+typedef unsigned char byte;
+typedef unsigned short word;
+typedef float vec_t;
+typedef int (*pfnUserMsgHook)(const char *pszName, int iSize, void *pbuf);
+
+#include "util_vector.h"
#ifdef _WIN32
#ifndef EXPORT
#define EXPORT _declspec( dllexport )
@@ -38,8 +38,8 @@ typedef int (*pfnUserMsgHook)(const char *pszName, int iSize, void *pbuf);
#else
#define EXPORT __attribute__ ((visibility("default")))
#endif
-
-#include "../engine/cdll_int.h"
-#include "../dlls/cdll_dll.h"
-
-extern cl_enginefunc_t gEngfuncs;
+
+#include "../engine/cdll_int.h"
+#include "../dlls/cdll_dll.h"
+
+extern cl_enginefunc_t gEngfuncs;
diff --git a/main/source/cl_dll/cl_dll.vcproj b/main/source/cl_dll/cl_dll.vcproj
index 8edd1490..ee1db282 100644
--- a/main/source/cl_dll/cl_dll.vcproj
+++ b/main/source/cl_dll/cl_dll.vcproj
@@ -1,5955 +1,5955 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/main/source/cl_dll/cl_dll.vcxproj b/main/source/cl_dll/cl_dll.vcxproj
index 8c33951d..c5cf7613 100644
--- a/main/source/cl_dll/cl_dll.vcxproj
+++ b/main/source/cl_dll/cl_dll.vcxproj
@@ -1,933 +1,936 @@
-
-
-
-
- Playtest
- Win32
-
-
-
- cl_dll.dll
- cl_dll
-
-
-
-
-
-
-
- DynamicLibrary
- false
- false
- MultiByte
-
-
-
-
-
-
-
-
-
- <_ProjectFileVersion>10.0.30319.1
- .\release
- $(Configuration)\
- $(TargetPath)%3b*.obj%3b*.ilk%3b*.pdb%3b*.tlb%3b*.tli%3b*.tlh%3b*.tmp%3b*.rsp%3b*.bat
- false
- client
-
-
-
- MaxSpeed
- OnlyExplicitInline
- false
- $(SolutionDir);$(SolutionDir)\particles;$(SolutionDir)\includes\lpng1251;$(SolutionDir)\includes\zlib-1.2.8;$(SolutionDir)\includes\fmod\inc;$(SolutionDir)\includes\vgui\include;../public;../common;../external;../pm_shared;../game_shared;../mod;../util;../ui;../engine;../cl_dll;../dlls
- NDEBUG;WIN32;_WINDOWS;AVH_CLIENT;USE_OLDAUTH
- true
- true
-
-
-
-
- $(IntDir)
- $(IntDir)
- $(IntDir)
- Level2
- false
- true
- Default
- true
- true
- 4996
- true
- MultiThreaded
- Neither
-
-
- particles.lib;vgui.lib;zlib.lib;libpng.lib;wsock32.lib;sdl2.lib;%(AdditionalDependencies)
- true
- $(SolutionDir)\particles\WIN32_Release;$(SolutionDir)\includes\lpng1251;$(SolutionDir)\includes\zlib-1.2.8;$(SolutionDir)\includes\vgui\lib\win32_vc6;$(SolutionDir)\lib\public;%(AdditionalLibraryDirectories)
-
-
-
-
-
-
- Windows
- $(IntDir)cl_dll.lib
- MachineX86
- false
- false
-
-
- /NODEFAULTLIB:LIBCMT %(AdditionalOptions)
-
-
- NDEBUG;%(PreprocessorDefinitions)
- true
- true
- Win32
- .\Release/cl_dll.tlb
-
-
-
-
- NDEBUG;%(PreprocessorDefinitions)
- 0x0409
-
-
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- true
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
-
- $(IntDir)%(Filename)1.obj
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
-
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
- MaxSpeed
- %(AdditionalIncludeDirectories)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+ Playtest
+ Win32
+
+
+
+ cl_dll.dll
+ cl_dll
+
+
+
+
+ {665C1DAF-9248-E06F-4E5C-A664BAFDE9D8}
+ 8.1
+
+
+
+ DynamicLibrary
+ false
+ false
+ MultiByte
+ v100
+
+
+
+
+
+
+
+
+
+ <_ProjectFileVersion>10.0.30319.1
+ .\release
+ $(Configuration)\
+ $(TargetPath)%3b*.obj%3b*.ilk%3b*.pdb%3b*.tlb%3b*.tli%3b*.tlh%3b*.tmp%3b*.rsp%3b*.bat
+ false
+ client
+
+
+
+ MaxSpeed
+ OnlyExplicitInline
+ false
+ $(SolutionDir);$(SolutionDir)\particles;$(SolutionDir)\includes\lpng1251;$(SolutionDir)\includes\zlib-1.2.8;$(SolutionDir)\includes\fmod\inc;$(SolutionDir)\includes\vgui\include;../public;../common;../external;../pm_shared;../game_shared;../mod;../util;../ui;../engine;../cl_dll;../dlls
+ NDEBUG;WIN32;_WINDOWS;AVH_CLIENT;USE_OLDAUTH
+ true
+ true
+
+
+
+
+ $(IntDir)
+ $(IntDir)
+ $(IntDir)
+ Level2
+ false
+ true
+ Default
+ true
+ true
+ 4996
+ true
+ MultiThreaded
+ Neither
+
+
+ particles.lib;vgui.lib;zlib.lib;libpng.lib;wsock32.lib;sdl2.lib;%(AdditionalDependencies)
+ true
+ $(SolutionDir)\particles\WIN32_Release;$(SolutionDir)\includes\lpng1251;$(SolutionDir)\includes\zlib-1.2.8;$(SolutionDir)\includes\vgui\lib\win32_vc6;$(SolutionDir)\lib\public;%(AdditionalLibraryDirectories)
+
+
+
+
+
+
+ Windows
+ $(IntDir)cl_dll.lib
+ MachineX86
+ false
+ false
+
+
+ /NODEFAULTLIB:LIBCMT %(AdditionalOptions)
+
+
+ NDEBUG;%(PreprocessorDefinitions)
+ true
+ true
+ Win32
+ .\Release/cl_dll.tlb
+
+
+
+
+ NDEBUG;%(PreprocessorDefinitions)
+ 0x0409
+
+
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ true
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+
+ $(IntDir)%(Filename)1.obj
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/main/source/cl_dll/cl_dll.vcxproj.filters b/main/source/cl_dll/cl_dll.vcxproj.filters
index dadc783e..4bc1e2e5 100644
--- a/main/source/cl_dll/cl_dll.vcxproj.filters
+++ b/main/source/cl_dll/cl_dll.vcxproj.filters
@@ -1,1047 +1,1047 @@
-
-
-
-
- {8d8b30a6-88bc-40e0-a19e-4b6793dd4988}
- cpp;c;cxx;rc;def;r;odl;idl;hpj;bat;for;f90
-
-
- {fb6cdf05-b5ad-4bd2-bbbb-93bb6db841c9}
- *.CPP
-
-
- {5fee03ab-1230-4f5c-8522-aeb53d4dee1f}
-
-
- {c75d025a-22cc-477c-b3a6-c2fb5fa71216}
- h;hpp;hxx;hm;inl;fi;fd
-
-
- {1203e87c-5c0d-49d2-a172-f6f1220ace14}
-
-
- {c54cbc98-aca6-4fc8-8a66-d0e55b966dcc}
-
-
- {5e6638f7-791c-4391-ae1a-963a434292ca}
-
-
- {0831440c-bcbe-4824-a97a-25473dcc0340}
-
-
- {ad5bbb2c-1092-4ba3-ab5b-fdfa0a33f1f5}
-
-
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files\hl
-
-
- Source Files\hl
-
-
- Source Files\hl
-
-
- Source Files\hl
-
-
- Source Files\hl
-
-
- Source Files\hl
-
-
- Source Files\client-side weapons
-
-
- Source Files\client-side weapons
-
-
- Source Files\client-side weapons
-
-
- Source Files\client-side weapons
-
-
- Source Files\client-side weapons
-
-
- Source Files\client-side weapons
-
-
- Source Files\client-side weapons
-
-
- Source Files\client-side weapons
-
-
- Source Files\client-side weapons
-
-
- Source Files\client-side weapons
-
-
- Source Files\client-side weapons
-
-
- Source Files\client-side weapons
-
-
- Source Files\client-side weapons
-
-
- Source Files\client-side weapons
-
-
- Source Files\client-side weapons
-
-
- Source Files\client-side weapons
-
-
- Source Files\client-side weapons
-
-
- Source Files\client-side weapons
-
-
- Source Files\client-side weapons
-
-
- Source Files\client-side weapons
-
-
- Source Files\client-side weapons
-
-
- Source Files\client-side weapons
-
-
- Source Files\client-side weapons
-
-
- Source Files\client-side weapons
-
-
- Source Files\client-side weapons
-
-
- Source Files\client-side weapons
-
-
- Source Files\client-side weapons
-
-
- Source Files\client-side weapons
-
-
- Source Files\client-side weapons
-
-
- Source Files\client-side weapons
-
-
- Source Files\client-side weapons
-
-
- Source Files\client-side weapons
-
-
- ui
-
-
- ui
-
-
- ui
-
-
- ui
-
-
- ui
-
-
- ui
-
-
- ui
-
-
- ui
-
-
- ui
-
-
- ui
-
-
- ui
-
-
- ui
-
-
- ui
-
-
- ui
-
-
- ui
-
-
- ui
-
-
- ui
-
-
- ui
-
-
- ui
-
-
- ui
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod\particles
-
-
- mod\particles
-
-
- mod\particles
-
-
- mod\particles
-
-
- mod\particles
-
-
- util
-
-
- util
-
-
- util
-
-
- util
-
-
- util
-
-
- util
-
-
- util
-
-
- util
-
-
- util
-
-
- util
-
-
- textrep
-
-
- textrep
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
-
-
- Source Files\client-side weapons
-
-
- Source Files\client-side weapons
-
-
- Source Files\client-side weapons
-
-
- Source Files\client-side weapons
-
-
- Source Files\client-side weapons
-
-
- Source Files\client-side weapons
-
-
- Source Files\client-side weapons
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- ui
-
-
- ui
-
-
- ui
-
-
- ui
-
-
- ui
-
-
- ui
-
-
- ui
-
-
- ui
-
-
- ui
-
-
- ui
-
-
- ui
-
-
- ui
-
-
- ui
-
-
- ui
-
-
- ui
-
-
- ui
-
-
- ui
-
-
- ui
-
-
- ui
-
-
- ui
-
-
- ui
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod
-
-
- mod\particles
-
-
- mod\particles
-
-
- mod\particles
-
-
- mod\particles
-
-
- mod\particles
-
-
- util
-
-
- util
-
-
- util
-
-
- util
-
-
- util
-
-
- util
-
-
- util
-
-
- util
-
-
- util
-
-
- util
-
-
- util
-
-
- util
-
-
- util
-
-
- textrep
-
-
- textrep
-
-
- textrep
-
-
- textrep
-
-
-
-
-
+
+
+
+
+ {8d8b30a6-88bc-40e0-a19e-4b6793dd4988}
+ cpp;c;cxx;rc;def;r;odl;idl;hpj;bat;for;f90
+
+
+ {fb6cdf05-b5ad-4bd2-bbbb-93bb6db841c9}
+ *.CPP
+
+
+ {5fee03ab-1230-4f5c-8522-aeb53d4dee1f}
+
+
+ {c75d025a-22cc-477c-b3a6-c2fb5fa71216}
+ h;hpp;hxx;hm;inl;fi;fd
+
+
+ {1203e87c-5c0d-49d2-a172-f6f1220ace14}
+
+
+ {c54cbc98-aca6-4fc8-8a66-d0e55b966dcc}
+
+
+ {5e6638f7-791c-4391-ae1a-963a434292ca}
+
+
+ {0831440c-bcbe-4824-a97a-25473dcc0340}
+
+
+ {ad5bbb2c-1092-4ba3-ab5b-fdfa0a33f1f5}
+
+
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files\hl
+
+
+ Source Files\hl
+
+
+ Source Files\hl
+
+
+ Source Files\hl
+
+
+ Source Files\hl
+
+
+ Source Files\hl
+
+
+ Source Files\client-side weapons
+
+
+ Source Files\client-side weapons
+
+
+ Source Files\client-side weapons
+
+
+ Source Files\client-side weapons
+
+
+ Source Files\client-side weapons
+
+
+ Source Files\client-side weapons
+
+
+ Source Files\client-side weapons
+
+
+ Source Files\client-side weapons
+
+
+ Source Files\client-side weapons
+
+
+ Source Files\client-side weapons
+
+
+ Source Files\client-side weapons
+
+
+ Source Files\client-side weapons
+
+
+ Source Files\client-side weapons
+
+
+ Source Files\client-side weapons
+
+
+ Source Files\client-side weapons
+
+
+ Source Files\client-side weapons
+
+
+ Source Files\client-side weapons
+
+
+ Source Files\client-side weapons
+
+
+ Source Files\client-side weapons
+
+
+ Source Files\client-side weapons
+
+
+ Source Files\client-side weapons
+
+
+ Source Files\client-side weapons
+
+
+ Source Files\client-side weapons
+
+
+ Source Files\client-side weapons
+
+
+ Source Files\client-side weapons
+
+
+ Source Files\client-side weapons
+
+
+ Source Files\client-side weapons
+
+
+ Source Files\client-side weapons
+
+
+ Source Files\client-side weapons
+
+
+ Source Files\client-side weapons
+
+
+ Source Files\client-side weapons
+
+
+ Source Files\client-side weapons
+
+
+ ui
+
+
+ ui
+
+
+ ui
+
+
+ ui
+
+
+ ui
+
+
+ ui
+
+
+ ui
+
+
+ ui
+
+
+ ui
+
+
+ ui
+
+
+ ui
+
+
+ ui
+
+
+ ui
+
+
+ ui
+
+
+ ui
+
+
+ ui
+
+
+ ui
+
+
+ ui
+
+
+ ui
+
+
+ ui
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod\particles
+
+
+ mod\particles
+
+
+ mod\particles
+
+
+ mod\particles
+
+
+ mod\particles
+
+
+ util
+
+
+ util
+
+
+ util
+
+
+ util
+
+
+ util
+
+
+ util
+
+
+ util
+
+
+ util
+
+
+ util
+
+
+ util
+
+
+ textrep
+
+
+ textrep
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+
+
+ Source Files\client-side weapons
+
+
+ Source Files\client-side weapons
+
+
+ Source Files\client-side weapons
+
+
+ Source Files\client-side weapons
+
+
+ Source Files\client-side weapons
+
+
+ Source Files\client-side weapons
+
+
+ Source Files\client-side weapons
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ ui
+
+
+ ui
+
+
+ ui
+
+
+ ui
+
+
+ ui
+
+
+ ui
+
+
+ ui
+
+
+ ui
+
+
+ ui
+
+
+ ui
+
+
+ ui
+
+
+ ui
+
+
+ ui
+
+
+ ui
+
+
+ ui
+
+
+ ui
+
+
+ ui
+
+
+ ui
+
+
+ ui
+
+
+ ui
+
+
+ ui
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod
+
+
+ mod\particles
+
+
+ mod\particles
+
+
+ mod\particles
+
+
+ mod\particles
+
+
+ mod\particles
+
+
+ util
+
+
+ util
+
+
+ util
+
+
+ util
+
+
+ util
+
+
+ util
+
+
+ util
+
+
+ util
+
+
+ util
+
+
+ util
+
+
+ util
+
+
+ util
+
+
+ util
+
+
+ textrep
+
+
+ textrep
+
+
+ textrep
+
+
+ textrep
+
+
+
+
+
\ No newline at end of file
diff --git a/main/source/cl_dll/cl_dll.vcxproj.user b/main/source/cl_dll/cl_dll.vcxproj.user
index f392fbec..14cbff20 100644
--- a/main/source/cl_dll/cl_dll.vcxproj.user
+++ b/main/source/cl_dll/cl_dll.vcxproj.user
@@ -1,11 +1,11 @@
-
-
-
- ..\..\..\..\..\..\..\Program Files %28x86%29\Steam\SteamApps\common\Half-Life\hl.exe
- WindowsLocalDebugger
- -allowdebug -dev -steam -game ns
- ..\..
- false
- Auto
-
+
+
+
+ ..\..\..\..\..\..\..\Program Files %28x86%29\Steam\SteamApps\common\Half-Life\hl.exe
+ WindowsLocalDebugger
+ -allowdebug -dev -steam -game ns
+ ..\..
+ false
+ Auto
+
\ No newline at end of file
diff --git a/main/source/cl_dll/cl_util.cpp b/main/source/cl_dll/cl_util.cpp
index 0a77c5d6..78b1d3f9 100644
--- a/main/source/cl_dll/cl_util.cpp
+++ b/main/source/cl_dll/cl_util.cpp
@@ -1,64 +1,64 @@
-#include "hud.h"
-#include "cl_dll/cl_util.h"
-
-float gTextR = 1;
-float gTextG = 1;
-float gTextB = 1;
-
-void DrawSetTextColor(float r, float g, float b )
-{
- gTextR = r;
- gTextG = g;
- gTextB = b;
- gEngfuncs.pfnDrawSetTextColor(r, g, b);
-}
-
-int DrawConsoleString( int x, int y, const char *string )
-{
- //return gEngfuncs.pfnDrawConsoleString( x, y, (char*) string );
-
- if (string[0] == 2)
- {
- ++string;
- }
-
- int result = gHUD.GetSmallFont().DrawString(x, y, string, gTextR * 255, gTextG * 255, gTextB * 255, kRenderTransAdd);
- DrawSetTextColor(1, 1, 1);
-
- return result;
-
-}
-
-void GetConsoleStringSize( const char *string, int *width, int *height )
-{
-
- //gEngfuncs.pfnDrawConsoleStringLen( string, width, height );
-
- if (string[0] == 2)
- {
- ++string;
- }
-
- *width = gHUD.GetSmallFont().GetStringWidth(string);
- *height = gHUD.GetSmallFont().GetStringHeight();
-
-}
-
-int ConsoleStringLen( const char *string )
-{
- int _width, _height;
- GetConsoleStringSize( string, &_width, &_height );
- return _width;
-}
-
-void ConsolePrint( const char *string )
-{
- // TODO Max: implement this
- gEngfuncs.pfnConsolePrint( string );
-}
-
-void CenterPrint( const char *string )
-{
- // TODO Max: implement this
- gEngfuncs.pfnCenterPrint( string );
+#include "hud.h"
+#include "cl_dll/cl_util.h"
+
+float gTextR = 1;
+float gTextG = 1;
+float gTextB = 1;
+
+void DrawSetTextColor(float r, float g, float b )
+{
+ gTextR = r;
+ gTextG = g;
+ gTextB = b;
+ gEngfuncs.pfnDrawSetTextColor(r, g, b);
+}
+
+int DrawConsoleString( int x, int y, const char *string )
+{
+ //return gEngfuncs.pfnDrawConsoleString( x, y, (char*) string );
+
+ if (string[0] == 2)
+ {
+ ++string;
+ }
+
+ int result = gHUD.GetSmallFont().DrawString(x, y, string, gTextR * 255, gTextG * 255, gTextB * 255, kRenderTransAdd);
+ DrawSetTextColor(1, 1, 1);
+
+ return result;
+
+}
+
+void GetConsoleStringSize( const char *string, int *width, int *height )
+{
+
+ //gEngfuncs.pfnDrawConsoleStringLen( string, width, height );
+
+ if (string[0] == 2)
+ {
+ ++string;
+ }
+
+ *width = gHUD.GetSmallFont().GetStringWidth(string);
+ *height = gHUD.GetSmallFont().GetStringHeight();
+
+}
+
+int ConsoleStringLen( const char *string )
+{
+ int _width, _height;
+ GetConsoleStringSize( string, &_width, &_height );
+ return _width;
+}
+
+void ConsolePrint( const char *string )
+{
+ // TODO Max: implement this
+ gEngfuncs.pfnConsolePrint( string );
+}
+
+void CenterPrint( const char *string )
+{
+ // TODO Max: implement this
+ gEngfuncs.pfnCenterPrint( string );
}
\ No newline at end of file
diff --git a/main/source/cl_dll/cl_util.h b/main/source/cl_dll/cl_util.h
index 7e8190f1..ad6fe1c9 100644
--- a/main/source/cl_dll/cl_util.h
+++ b/main/source/cl_dll/cl_util.h
@@ -1,150 +1,150 @@
-/***
-*
-* Copyright (c) 1999, Valve LLC. All rights reserved.
-*
-* This product contains software technology licensed from Id
-* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
-* All Rights Reserved.
-*
-* Use, distribution, and modification of this source code and/or resulting
-* object code is restricted to non-commercial enhancements to products from
-* Valve LLC. All other use, distribution, or modification is prohibited
-* without written permission from Valve LLC.
-*
-****/
-//
-// cl_util.h
-//
-#ifndef CL_UTIL_H
-#define CL_UTIL_H
-
-#include "cvardef.h"
-#include "vector_util.h"
-#include "VGUI_Panel.h"
-#include "../types.h"
-#include "cl_dll.h"
-#include "hud.h"
-
-#ifndef TRUE
-#define TRUE 1
-#define FALSE 0
-#endif
-
-#include // for safe_sprintf()
-#include // "
-#include // "
-// Macros to hook function calls into the HUD object
-#define HOOK_MESSAGE(x) gEngfuncs.pfnHookUserMsg(#x, __MsgFunc_##x );
-
-#define DECLARE_MESSAGE(y, x) int __MsgFunc_##x(const char *pszName, int iSize, void *pbuf) \
- { \
- return gHUD.y.MsgFunc_##x(pszName, iSize, pbuf ); \
- }
-
-
-#define HOOK_COMMAND(x, y) gEngfuncs.pfnAddCommand( x, __CmdFunc_##y );
-#define DECLARE_COMMAND(y, x) void __CmdFunc_##x( void ) \
- { \
- gHUD.y.UserCmd_##x( ); \
- }
-
-inline float CVAR_GET_FLOAT( const char *x ) { return gEngfuncs.pfnGetCvarFloat( (char*)x ); }
-inline char* CVAR_GET_STRING( const char *x ) { return gEngfuncs.pfnGetCvarString( (char*)x ); }
-inline struct cvar_s *CVAR_CREATE( const char *cv, const char *val, const int flags ) { return gEngfuncs.pfnRegisterVariable( (char*)cv, (char*)val, flags ); }
-
-#define SPR_Load (*gEngfuncs.pfnSPR_Load)
-//HSPRITE SPR_Load(const char* inSpriteName);
-#define SPR_Set (*gEngfuncs.pfnSPR_Set)
-#define SPR_Frames (*gEngfuncs.pfnSPR_Frames)
-#define SPR_GetList (*gEngfuncs.pfnSPR_GetList)
-
-// SPR_Draw draws a the current sprite as solid
-#define SPR_Draw (*gEngfuncs.pfnSPR_Draw)
-// SPR_DrawHoles draws the current sprites, with color index255 not drawn (transparent)
-#define SPR_DrawHoles (*gEngfuncs.pfnSPR_DrawHoles)
-// SPR_DrawAdditive adds the sprites RGB values to the background (additive transulency)
-#define SPR_DrawAdditive (*gEngfuncs.pfnSPR_DrawAdditive)
-
-// SPR_EnableScissor sets a clipping rect for HUD sprites. (0,0) is the top-left hand corner of the screen.
-#define SPR_EnableScissor (*gEngfuncs.pfnSPR_EnableScissor)
-// SPR_DisableScissor disables the clipping rect
-#define SPR_DisableScissor (*gEngfuncs.pfnSPR_DisableScissor)
-
-void CreatePickingRay( int mousex, int mousey, Vector& outVecPickingRay);
-
-//
-#define FillRGBA (*gEngfuncs.pfnFillRGBA)
-
-int ScreenHeight();
-int ScreenWidth();
-
-// Use this to set any co-ords in 640x480 space
-#define XRES(x) ((int)(float(x) * ((float)ScreenWidth() / 640.0f) + 0.5f))
-#define YRES(y) ((int)(float(y) * ((float)ScreenHeight() / 480.0f) + 0.5f))
-
-// use this to project world coordinates to screen coordinates
-#define XPROJECT(x) ( (1.0f+(x))*ScreenWidth()*0.5f )
-#define YPROJECT(y) ( (1.0f-(y))*ScreenHeight()*0.5f )
-
-#define GetScreenInfo (*gEngfuncs.pfnGetScreenInfo)
-#define ServerCmd (*gEngfuncs.pfnServerCmd)
-#define ClientCmd (*gEngfuncs.pfnClientCmd)
-#define SetCrosshair (*gEngfuncs.pfnSetCrosshair)
-#define AngleVectors (*gEngfuncs.pfnAngleVectors)
-
-
-// Gets the height & width of a sprite, at the specified frame
-inline int SPR_Height( HSPRITE x, int f ) { return gEngfuncs.pfnSPR_Height(x, f); }
-inline int SPR_Width( HSPRITE x, int f ) { return gEngfuncs.pfnSPR_Width(x, f); }
-
-inline client_textmessage_t *TextMessageGet( const char *pName ) { return gEngfuncs.pfnTextMessageGet( pName ); }
-inline int TextMessageDrawChar( int x, int y, int number, int r, int g, int b )
-{
- return gEngfuncs.pfnDrawCharacter( x, y, number, r, g, b );
-}
-
-void DrawSetTextColor(float r, float g, float b );
-
-
-int DrawConsoleString( int x, int y, const char *string );
-
-void GetConsoleStringSize( const char *string, int *width, int *height );
-int ConsoleStringLen( const char *string );
-
-void ConsolePrint( const char *string );
-void CenterPrint( const char *string );
-
-// returns the players name of entity no.
-#define GetPlayerInfo (*gEngfuncs.pfnGetPlayerInfo)
-
-// sound functions
-//inline void PlaySound( char *szSound, float vol ) { gEngfuncs.pfnPlaySoundByName( szSound, vol ); }
-//inline void PlaySound( int iSound, float vol ) { gEngfuncs.pfnPlaySoundByIndex( iSound, vol ); }
-
-#define max(a,b) (((a) > (b)) ? (a) : (b))
-#define min(a,b) (((a) < (b)) ? (a) : (b))
-#define fabs(x) ((x) > 0 ? (x) : 0 - (x))
-
-void ScaleColors( int &r, int &g, int &b, int a );
-
-// disable 'possible loss of data converting float to int' warning message
-#pragma warning( disable: 4244 )
-// disable 'truncation from 'const double' to 'float' warning message
-#pragma warning( disable: 4305 )
-
-inline void UnpackRGB(int &r, int &g, int &b, unsigned long ulRGB)\
-{\
- r = (ulRGB & 0xFF0000) >>16;\
- g = (ulRGB & 0xFF00) >> 8;\
- b = ulRGB & 0xFF;\
-}
-
-void FillRGBAClipped(vgui::Panel* inPanel, int inStartX, int inStartY, int inWidth, int inHeight, int r, int g, int b, int a);
-
-HSPRITE LoadSprite(const char *pszName);
-
-//bool LocalizeString(const char* inMessage, char* outBuffer, int inBufferSize);
-bool LocalizeString(const char* inMessage, string& outputString);
-
-
-#endif
+/***
+*
+* Copyright (c) 1999, Valve LLC. All rights reserved.
+*
+* This product contains software technology licensed from Id
+* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
+* All Rights Reserved.
+*
+* Use, distribution, and modification of this source code and/or resulting
+* object code is restricted to non-commercial enhancements to products from
+* Valve LLC. All other use, distribution, or modification is prohibited
+* without written permission from Valve LLC.
+*
+****/
+//
+// cl_util.h
+//
+#ifndef CL_UTIL_H
+#define CL_UTIL_H
+
+#include "cvardef.h"
+#include "vector_util.h"
+#include "VGUI_Panel.h"
+#include "../types.h"
+#include "cl_dll.h"
+#include "hud.h"
+
+#ifndef TRUE
+#define TRUE 1
+#define FALSE 0
+#endif
+
+#include // for safe_sprintf()
+#include // "
+#include // "
+// Macros to hook function calls into the HUD object
+#define HOOK_MESSAGE(x) gEngfuncs.pfnHookUserMsg(#x, __MsgFunc_##x );
+
+#define DECLARE_MESSAGE(y, x) int __MsgFunc_##x(const char *pszName, int iSize, void *pbuf) \
+ { \
+ return gHUD.y.MsgFunc_##x(pszName, iSize, pbuf ); \
+ }
+
+
+#define HOOK_COMMAND(x, y) gEngfuncs.pfnAddCommand( x, __CmdFunc_##y );
+#define DECLARE_COMMAND(y, x) void __CmdFunc_##x( void ) \
+ { \
+ gHUD.y.UserCmd_##x( ); \
+ }
+
+inline float CVAR_GET_FLOAT( const char *x ) { return gEngfuncs.pfnGetCvarFloat( (char*)x ); }
+inline char* CVAR_GET_STRING( const char *x ) { return gEngfuncs.pfnGetCvarString( (char*)x ); }
+inline struct cvar_s *CVAR_CREATE( const char *cv, const char *val, const int flags ) { return gEngfuncs.pfnRegisterVariable( (char*)cv, (char*)val, flags ); }
+
+#define SPR_Load (*gEngfuncs.pfnSPR_Load)
+//HSPRITE SPR_Load(const char* inSpriteName);
+#define SPR_Set (*gEngfuncs.pfnSPR_Set)
+#define SPR_Frames (*gEngfuncs.pfnSPR_Frames)
+#define SPR_GetList (*gEngfuncs.pfnSPR_GetList)
+
+// SPR_Draw draws a the current sprite as solid
+#define SPR_Draw (*gEngfuncs.pfnSPR_Draw)
+// SPR_DrawHoles draws the current sprites, with color index255 not drawn (transparent)
+#define SPR_DrawHoles (*gEngfuncs.pfnSPR_DrawHoles)
+// SPR_DrawAdditive adds the sprites RGB values to the background (additive transulency)
+#define SPR_DrawAdditive (*gEngfuncs.pfnSPR_DrawAdditive)
+
+// SPR_EnableScissor sets a clipping rect for HUD sprites. (0,0) is the top-left hand corner of the screen.
+#define SPR_EnableScissor (*gEngfuncs.pfnSPR_EnableScissor)
+// SPR_DisableScissor disables the clipping rect
+#define SPR_DisableScissor (*gEngfuncs.pfnSPR_DisableScissor)
+
+void CreatePickingRay( int mousex, int mousey, Vector& outVecPickingRay);
+
+//
+#define FillRGBA (*gEngfuncs.pfnFillRGBA)
+
+int ScreenHeight();
+int ScreenWidth();
+
+// Use this to set any co-ords in 640x480 space
+#define XRES(x) ((int)(float(x) * ((float)ScreenWidth() / 640.0f) + 0.5f))
+#define YRES(y) ((int)(float(y) * ((float)ScreenHeight() / 480.0f) + 0.5f))
+
+// use this to project world coordinates to screen coordinates
+#define XPROJECT(x) ( (1.0f+(x))*ScreenWidth()*0.5f )
+#define YPROJECT(y) ( (1.0f-(y))*ScreenHeight()*0.5f )
+
+#define GetScreenInfo (*gEngfuncs.pfnGetScreenInfo)
+#define ServerCmd (*gEngfuncs.pfnServerCmd)
+#define ClientCmd (*gEngfuncs.pfnClientCmd)
+#define SetCrosshair (*gEngfuncs.pfnSetCrosshair)
+#define AngleVectors (*gEngfuncs.pfnAngleVectors)
+
+
+// Gets the height & width of a sprite, at the specified frame
+inline int SPR_Height( HSPRITE x, int f ) { return gEngfuncs.pfnSPR_Height(x, f); }
+inline int SPR_Width( HSPRITE x, int f ) { return gEngfuncs.pfnSPR_Width(x, f); }
+
+inline client_textmessage_t *TextMessageGet( const char *pName ) { return gEngfuncs.pfnTextMessageGet( pName ); }
+inline int TextMessageDrawChar( int x, int y, int number, int r, int g, int b )
+{
+ return gEngfuncs.pfnDrawCharacter( x, y, number, r, g, b );
+}
+
+void DrawSetTextColor(float r, float g, float b );
+
+
+int DrawConsoleString( int x, int y, const char *string );
+
+void GetConsoleStringSize( const char *string, int *width, int *height );
+int ConsoleStringLen( const char *string );
+
+void ConsolePrint( const char *string );
+void CenterPrint( const char *string );
+
+// returns the players name of entity no.
+#define GetPlayerInfo (*gEngfuncs.pfnGetPlayerInfo)
+
+// sound functions
+//inline void PlaySound( char *szSound, float vol ) { gEngfuncs.pfnPlaySoundByName( szSound, vol ); }
+//inline void PlaySound( int iSound, float vol ) { gEngfuncs.pfnPlaySoundByIndex( iSound, vol ); }
+
+#define max(a,b) (((a) > (b)) ? (a) : (b))
+#define min(a,b) (((a) < (b)) ? (a) : (b))
+#define fabs(x) ((x) > 0 ? (x) : 0 - (x))
+
+void ScaleColors( int &r, int &g, int &b, int a );
+
+// disable 'possible loss of data converting float to int' warning message
+#pragma warning( disable: 4244 )
+// disable 'truncation from 'const double' to 'float' warning message
+#pragma warning( disable: 4305 )
+
+inline void UnpackRGB(int &r, int &g, int &b, unsigned long ulRGB)\
+{\
+ r = (ulRGB & 0xFF0000) >>16;\
+ g = (ulRGB & 0xFF00) >> 8;\
+ b = ulRGB & 0xFF;\
+}
+
+void FillRGBAClipped(vgui::Panel* inPanel, int inStartX, int inStartY, int inWidth, int inHeight, int r, int g, int b, int a);
+
+HSPRITE LoadSprite(const char *pszName);
+
+//bool LocalizeString(const char* inMessage, char* outBuffer, int inBufferSize);
+bool LocalizeString(const char* inMessage, string& outputString);
+
+
+#endif
diff --git a/main/source/cl_dll/cl_util.h~ b/main/source/cl_dll/cl_util.h~
deleted file mode 100644
index 21d0232b..00000000
--- a/main/source/cl_dll/cl_util.h~
+++ /dev/null
@@ -1,150 +0,0 @@
-/***
-*
-* Copyright (c) 1999, Valve LLC. All rights reserved.
-*
-* This product contains software technology licensed from Id
-* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
-* All Rights Reserved.
-*
-* Use, distribution, and modification of this source code and/or resulting
-* object code is restricted to non-commercial enhancements to products from
-* Valve LLC. All other use, distribution, or modification is prohibited
-* without written permission from Valve LLC.
-*
-****/
-//
-// cl_util.h
-//
-#ifndef CL_UTIL_H
-#define CL_UTIL_H
-
-#include "cvardef.h"
-#include "vector_util.h"
-#include "VGUI_Panel.h"
-#include "types.h"
-#include "cl_dll.h"
-#include "hud.h"
-
-#ifndef TRUE
-#define TRUE 1
-#define FALSE 0
-#endif
-
-#include // for safe_sprintf()
-#include // "
-#include // "
-// Macros to hook function calls into the HUD object
-#define HOOK_MESSAGE(x) gEngfuncs.pfnHookUserMsg(#x, __MsgFunc_##x );
-
-#define DECLARE_MESSAGE(y, x) int __MsgFunc_##x(const char *pszName, int iSize, void *pbuf) \
- { \
- return gHUD.y.MsgFunc_##x(pszName, iSize, pbuf ); \
- }
-
-
-#define HOOK_COMMAND(x, y) gEngfuncs.pfnAddCommand( x, __CmdFunc_##y );
-#define DECLARE_COMMAND(y, x) void __CmdFunc_##x( void ) \
- { \
- gHUD.y.UserCmd_##x( ); \
- }
-
-inline float CVAR_GET_FLOAT( const char *x ) { return gEngfuncs.pfnGetCvarFloat( (char*)x ); }
-inline char* CVAR_GET_STRING( const char *x ) { return gEngfuncs.pfnGetCvarString( (char*)x ); }
-inline struct cvar_s *CVAR_CREATE( const char *cv, const char *val, const int flags ) { return gEngfuncs.pfnRegisterVariable( (char*)cv, (char*)val, flags ); }
-
-#define SPR_Load (*gEngfuncs.pfnSPR_Load)
-//HSPRITE SPR_Load(const char* inSpriteName);
-#define SPR_Set (*gEngfuncs.pfnSPR_Set)
-#define SPR_Frames (*gEngfuncs.pfnSPR_Frames)
-#define SPR_GetList (*gEngfuncs.pfnSPR_GetList)
-
-// SPR_Draw draws a the current sprite as solid
-#define SPR_Draw (*gEngfuncs.pfnSPR_Draw)
-// SPR_DrawHoles draws the current sprites, with color index255 not drawn (transparent)
-#define SPR_DrawHoles (*gEngfuncs.pfnSPR_DrawHoles)
-// SPR_DrawAdditive adds the sprites RGB values to the background (additive transulency)
-#define SPR_DrawAdditive (*gEngfuncs.pfnSPR_DrawAdditive)
-
-// SPR_EnableScissor sets a clipping rect for HUD sprites. (0,0) is the top-left hand corner of the screen.
-#define SPR_EnableScissor (*gEngfuncs.pfnSPR_EnableScissor)
-// SPR_DisableScissor disables the clipping rect
-#define SPR_DisableScissor (*gEngfuncs.pfnSPR_DisableScissor)
-
-void CreatePickingRay( int mousex, int mousey, Vector& outVecPickingRay);
-
-//
-#define FillRGBA (*gEngfuncs.pfnFillRGBA)
-
-int ScreenHeight();
-int ScreenWidth();
-
-// Use this to set any co-ords in 640x480 space
-#define XRES(x) ((int)(float(x) * ((float)ScreenWidth() / 640.0f) + 0.5f))
-#define YRES(y) ((int)(float(y) * ((float)ScreenHeight() / 480.0f) + 0.5f))
-
-// use this to project world coordinates to screen coordinates
-#define XPROJECT(x) ( (1.0f+(x))*ScreenWidth()*0.5f )
-#define YPROJECT(y) ( (1.0f-(y))*ScreenHeight()*0.5f )
-
-#define GetScreenInfo (*gEngfuncs.pfnGetScreenInfo)
-#define ServerCmd (*gEngfuncs.pfnServerCmd)
-#define ClientCmd (*gEngfuncs.pfnClientCmd)
-#define SetCrosshair (*gEngfuncs.pfnSetCrosshair)
-#define AngleVectors (*gEngfuncs.pfnAngleVectors)
-
-
-// Gets the height & width of a sprite, at the specified frame
-inline int SPR_Height( HSPRITE x, int f ) { return gEngfuncs.pfnSPR_Height(x, f); }
-inline int SPR_Width( HSPRITE x, int f ) { return gEngfuncs.pfnSPR_Width(x, f); }
-
-inline client_textmessage_t *TextMessageGet( const char *pName ) { return gEngfuncs.pfnTextMessageGet( pName ); }
-inline int TextMessageDrawChar( int x, int y, int number, int r, int g, int b )
-{
- return gEngfuncs.pfnDrawCharacter( x, y, number, r, g, b );
-}
-
-void DrawSetTextColor(float r, float g, float b );
-
-
-int DrawConsoleString( int x, int y, const char *string );
-
-void GetConsoleStringSize( const char *string, int *width, int *height );
-int ConsoleStringLen( const char *string );
-
-void ConsolePrint( const char *string );
-void CenterPrint( const char *string );
-
-// returns the players name of entity no.
-#define GetPlayerInfo (*gEngfuncs.pfnGetPlayerInfo)
-
-// sound functions
-//inline void PlaySound( char *szSound, float vol ) { gEngfuncs.pfnPlaySoundByName( szSound, vol ); }
-//inline void PlaySound( int iSound, float vol ) { gEngfuncs.pfnPlaySoundByIndex( iSound, vol ); }
-
-#define max(a,b) (((a) > (b)) ? (a) : (b))
-#define min(a,b) (((a) < (b)) ? (a) : (b))
-#define fabs(x) ((x) > 0 ? (x) : 0 - (x))
-
-void ScaleColors( int &r, int &g, int &b, int a );
-
-// disable 'possible loss of data converting float to int' warning message
-#pragma warning( disable: 4244 )
-// disable 'truncation from 'const double' to 'float' warning message
-#pragma warning( disable: 4305 )
-
-inline void UnpackRGB(int &r, int &g, int &b, unsigned long ulRGB)\
-{\
- r = (ulRGB & 0xFF0000) >>16;\
- g = (ulRGB & 0xFF00) >> 8;\
- b = ulRGB & 0xFF;\
-}
-
-void FillRGBAClipped(vgui::Panel* inPanel, int inStartX, int inStartY, int inWidth, int inHeight, int r, int g, int b, int a);
-
-HSPRITE LoadSprite(const char *pszName);
-
-//bool LocalizeString(const char* inMessage, char* outBuffer, int inBufferSize);
-bool LocalizeString(const char* inMessage, string& outputString);
-
-
-#endif
diff --git a/main/source/cl_dll/com_weapons.cpp b/main/source/cl_dll/com_weapons.cpp
index 4048ab97..d801e341 100644
--- a/main/source/cl_dll/com_weapons.cpp
+++ b/main/source/cl_dll/com_weapons.cpp
@@ -1,278 +1,278 @@
-/***
-*
-* Copyright (c) 1999, Valve LLC. All rights reserved.
-*
-* This product contains software technology licensed from Id
-* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
-* All Rights Reserved.
-*
-* Use, distribution, and modification of this source code and/or resulting
-* object code is restricted to non-commercial enhancements to products from
-* Valve LLC. All other use, distribution, or modification is prohibited
-* without written permission from Valve LLC.
-*
-****/
-
-// Com_Weapons.cpp
-// Shared weapons common/shared functions
-#include
-#include "hud.h"
-#include "cl_util.h"
-#include "com_weapons.h"
-
-#include "common/const.h"
-#include "common/entity_state.h"
-#include "common/r_efx.h"
-
-// g_runfuncs is true if this is the first time we've "predicated" a particular movement/firing
-// command. If it is 1, then we should play events/sounds etc., otherwise, we just will be
-// updating state info, but not firing events
-int g_runfuncs = 0;
-
-// During our weapon prediction processing, we'll need to reference some data that is part of
-// the final state passed into the postthink functionality. We'll set this pointer and then
-// reset it to NULL as appropriate
-struct local_state_s *g_finalstate = NULL;
-
-/*
-====================
-COM_Log
-
-Log debug messages to file ( appends )
-====================
-*/
-void COM_Log( char *pszFile, char *fmt, ...)
-{
- va_list argptr;
- char string[1024];
- FILE *fp;
- char *pfilename;
-
- if ( !pszFile )
- {
- pfilename = "c:\\hllog.txt";
- }
- else
- {
- pfilename = pszFile;
- }
-
+/***
+*
+* Copyright (c) 1999, Valve LLC. All rights reserved.
+*
+* This product contains software technology licensed from Id
+* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
+* All Rights Reserved.
+*
+* Use, distribution, and modification of this source code and/or resulting
+* object code is restricted to non-commercial enhancements to products from
+* Valve LLC. All other use, distribution, or modification is prohibited
+* without written permission from Valve LLC.
+*
+****/
+
+// Com_Weapons.cpp
+// Shared weapons common/shared functions
+#include
+#include "hud.h"
+#include "cl_util.h"
+#include "com_weapons.h"
+
+#include "common/const.h"
+#include "common/entity_state.h"
+#include "common/r_efx.h"
+
+// g_runfuncs is true if this is the first time we've "predicated" a particular movement/firing
+// command. If it is 1, then we should play events/sounds etc., otherwise, we just will be
+// updating state info, but not firing events
+int g_runfuncs = 0;
+
+// During our weapon prediction processing, we'll need to reference some data that is part of
+// the final state passed into the postthink functionality. We'll set this pointer and then
+// reset it to NULL as appropriate
+struct local_state_s *g_finalstate = NULL;
+
+/*
+====================
+COM_Log
+
+Log debug messages to file ( appends )
+====================
+*/
+void COM_Log( char *pszFile, char *fmt, ...)
+{
+ va_list argptr;
+ char string[1024];
+ FILE *fp;
+ char *pfilename;
+
+ if ( !pszFile )
+ {
+ pfilename = "c:\\hllog.txt";
+ }
+ else
+ {
+ pfilename = pszFile;
+ }
+
va_start (argptr,fmt);
vsprintf (string, fmt,argptr);
- va_end (argptr);
-
- fp = fopen( pfilename, "a+t");
- if (fp)
- {
- fprintf(fp, "%s", string);
- fclose(fp);
- }
-}
-
-// remember the current animation for the view model, in case we get out of sync with
-// server.
-static int g_currentanim;
-
-/*
-=====================
-HUD_SendWeaponAnim
-
-Change weapon model animation
-=====================
-*/
-void HUD_SendWeaponAnim( int iAnim, int body, int force )
-{
- if(iAnim >= 0)
- {
- // Don't actually change it.
- if ( !g_runfuncs && !force )
- return;
-
- g_currentanim = iAnim;
-
- // Tell animation system new info
- gEngfuncs.pfnWeaponAnim( iAnim, body );
- }
-}
-
-/*
-=====================
-HUD_GetWeaponAnim
-
-Retrieve current predicted weapon animation
-=====================
-*/
-int HUD_GetWeaponAnim( void )
-{
- return g_currentanim;
-}
-
-/*
-=====================
-HUD_PlaySound
-
-Play a sound, if we are seeing this command for the first time
-=====================
-*/
-void HUD_PlaySound( char *sound, float volume )
-{
- if ( !g_runfuncs || !g_finalstate )
- return;
-
- gEngfuncs.pfnPlaySoundByNameAtLocation( sound, volume, (float *)&g_finalstate->playerstate.origin );
-}
-
-/*
-=====================
-HUD_PlaybackEvent
-
-Directly queue up an event on the client
-=====================
-*/
-void HUD_PlaybackEvent( int flags, const edict_t *pInvoker, unsigned short eventindex, float delay,
- float *origin, float *angles, float fparam1, float fparam2, int iparam1, int iparam2, int bparam1, int bparam2 )
-{
- vec3_t org;
- vec3_t ang;
-
- if ( !g_runfuncs || !g_finalstate )
- return;
-
- // Weapon prediction events are assumed to occur at the player's origin
- org = g_finalstate->playerstate.origin;
- ang = v_angles;
- gEngfuncs.pfnPlaybackEvent( flags, pInvoker, eventindex, delay, (float *)&org, (float *)&ang, fparam1, fparam2, iparam1, iparam2, bparam1, bparam2 );
-}
-
-/*
-=====================
-HUD_SetMaxSpeed
-
-=====================
-*/
-void HUD_SetMaxSpeed( const edict_t *ed, float speed )
-{
-}
-
-
-/*
-=====================
-UTIL_WeaponTimeBase
-
-Always 0.0 on client, even if not predicting weapons ( won't get called
- in that case )
-=====================
-*/
-float UTIL_WeaponTimeBase( void )
-{
- return 0.0;
-}
-
-static unsigned int glSeed = 0;
-
-unsigned int seed_table[ 256 ] =
-{
- 28985, 27138, 26457, 9451, 17764, 10909, 28790, 8716, 6361, 4853, 17798, 21977, 19643, 20662, 10834, 20103,
- 27067, 28634, 18623, 25849, 8576, 26234, 23887, 18228, 32587, 4836, 3306, 1811, 3035, 24559, 18399, 315,
- 26766, 907, 24102, 12370, 9674, 2972, 10472, 16492, 22683, 11529, 27968, 30406, 13213, 2319, 23620, 16823,
- 10013, 23772, 21567, 1251, 19579, 20313, 18241, 30130, 8402, 20807, 27354, 7169, 21211, 17293, 5410, 19223,
- 10255, 22480, 27388, 9946, 15628, 24389, 17308, 2370, 9530, 31683, 25927, 23567, 11694, 26397, 32602, 15031,
- 18255, 17582, 1422, 28835, 23607, 12597, 20602, 10138, 5212, 1252, 10074, 23166, 19823, 31667, 5902, 24630,
- 18948, 14330, 14950, 8939, 23540, 21311, 22428, 22391, 3583, 29004, 30498, 18714, 4278, 2437, 22430, 3439,
- 28313, 23161, 25396, 13471, 19324, 15287, 2563, 18901, 13103, 16867, 9714, 14322, 15197, 26889, 19372, 26241,
- 31925, 14640, 11497, 8941, 10056, 6451, 28656, 10737, 13874, 17356, 8281, 25937, 1661, 4850, 7448, 12744,
- 21826, 5477, 10167, 16705, 26897, 8839, 30947, 27978, 27283, 24685, 32298, 3525, 12398, 28726, 9475, 10208,
- 617, 13467, 22287, 2376, 6097, 26312, 2974, 9114, 21787, 28010, 4725, 15387, 3274, 10762, 31695, 17320,
- 18324, 12441, 16801, 27376, 22464, 7500, 5666, 18144, 15314, 31914, 31627, 6495, 5226, 31203, 2331, 4668,
- 12650, 18275, 351, 7268, 31319, 30119, 7600, 2905, 13826, 11343, 13053, 15583, 30055, 31093, 5067, 761,
- 9685, 11070, 21369, 27155, 3663, 26542, 20169, 12161, 15411, 30401, 7580, 31784, 8985, 29367, 20989, 14203,
- 29694, 21167, 10337, 1706, 28578, 887, 3373, 19477, 14382, 675, 7033, 15111, 26138, 12252, 30996, 21409,
- 25678, 18555, 13256, 23316, 22407, 16727, 991, 9236, 5373, 29402, 6117, 15241, 27715, 19291, 19888, 19847
-};
-
-unsigned int U_Random( void )
-{
- glSeed *= 69069;
- glSeed += seed_table[ glSeed & 0xff ];
-
- return ( ++glSeed & 0x0fffffff );
-}
-
-void U_Srand( unsigned int seed )
-{
- glSeed = seed_table[ seed & 0xff ];
-}
-
-/*
-=====================
-UTIL_SharedRandomLong
-=====================
-*/
-int UTIL_SharedRandomLong( unsigned int seed, int low, int high )
-{
- unsigned int range;
-
- U_Srand( (int)seed + low + high );
-
- range = high - low + 1;
- if ( !(range - 1) )
- {
- return low;
- }
- else
- {
- int offset;
- int rnum;
-
- rnum = U_Random();
-
- offset = rnum % range;
-
- return (low + offset);
- }
-}
-
-/*
-=====================
-UTIL_SharedRandomFloat
-=====================
-*/
-float UTIL_SharedRandomFloat( unsigned int seed, float low, float high )
-{
-
- U_Srand( (int)seed + *(int *)&low + *(int *)&high );
-
- U_Random();
- U_Random();
-
- float range = high - low;
- if ( !range )
- {
- return low;
- }
- else
- {
- int tensixrand;
- float offset;
-
- tensixrand = U_Random() & 65535;
-
- offset = (float)tensixrand / 65536.0;
-
- return (low + offset * range );
- }
-}
-
-/*
-======================
-stub_*
-
-stub functions for such things as precaching. So we don't have to modify weapons code that
- is compiled into both game and client .dlls.
-======================
-*/
-int stub_PrecacheModel ( char* s ) { return 0; }
-int stub_PrecacheSound ( char* s ) { return 0; }
-unsigned short stub_PrecacheEvent ( int type, const char *s ) { return 0; }
+ va_end (argptr);
+
+ fp = fopen( pfilename, "a+t");
+ if (fp)
+ {
+ fprintf(fp, "%s", string);
+ fclose(fp);
+ }
+}
+
+// remember the current animation for the view model, in case we get out of sync with
+// server.
+static int g_currentanim;
+
+/*
+=====================
+HUD_SendWeaponAnim
+
+Change weapon model animation
+=====================
+*/
+void HUD_SendWeaponAnim( int iAnim, int body, int force )
+{
+ if(iAnim >= 0)
+ {
+ // Don't actually change it.
+ if ( !g_runfuncs && !force )
+ return;
+
+ g_currentanim = iAnim;
+
+ // Tell animation system new info
+ gEngfuncs.pfnWeaponAnim( iAnim, body );
+ }
+}
+
+/*
+=====================
+HUD_GetWeaponAnim
+
+Retrieve current predicted weapon animation
+=====================
+*/
+int HUD_GetWeaponAnim( void )
+{
+ return g_currentanim;
+}
+
+/*
+=====================
+HUD_PlaySound
+
+Play a sound, if we are seeing this command for the first time
+=====================
+*/
+void HUD_PlaySound( char *sound, float volume )
+{
+ if ( !g_runfuncs || !g_finalstate )
+ return;
+
+ gEngfuncs.pfnPlaySoundByNameAtLocation( sound, volume, (float *)&g_finalstate->playerstate.origin );
+}
+
+/*
+=====================
+HUD_PlaybackEvent
+
+Directly queue up an event on the client
+=====================
+*/
+void HUD_PlaybackEvent( int flags, const edict_t *pInvoker, unsigned short eventindex, float delay,
+ float *origin, float *angles, float fparam1, float fparam2, int iparam1, int iparam2, int bparam1, int bparam2 )
+{
+ vec3_t org;
+ vec3_t ang;
+
+ if ( !g_runfuncs || !g_finalstate )
+ return;
+
+ // Weapon prediction events are assumed to occur at the player's origin
+ org = g_finalstate->playerstate.origin;
+ ang = v_angles;
+ gEngfuncs.pfnPlaybackEvent( flags, pInvoker, eventindex, delay, (float *)&org, (float *)&ang, fparam1, fparam2, iparam1, iparam2, bparam1, bparam2 );
+}
+
+/*
+=====================
+HUD_SetMaxSpeed
+
+=====================
+*/
+void HUD_SetMaxSpeed( const edict_t *ed, float speed )
+{
+}
+
+
+/*
+=====================
+UTIL_WeaponTimeBase
+
+Always 0.0 on client, even if not predicting weapons ( won't get called
+ in that case )
+=====================
+*/
+float UTIL_WeaponTimeBase( void )
+{
+ return 0.0;
+}
+
+static unsigned int glSeed = 0;
+
+unsigned int seed_table[ 256 ] =
+{
+ 28985, 27138, 26457, 9451, 17764, 10909, 28790, 8716, 6361, 4853, 17798, 21977, 19643, 20662, 10834, 20103,
+ 27067, 28634, 18623, 25849, 8576, 26234, 23887, 18228, 32587, 4836, 3306, 1811, 3035, 24559, 18399, 315,
+ 26766, 907, 24102, 12370, 9674, 2972, 10472, 16492, 22683, 11529, 27968, 30406, 13213, 2319, 23620, 16823,
+ 10013, 23772, 21567, 1251, 19579, 20313, 18241, 30130, 8402, 20807, 27354, 7169, 21211, 17293, 5410, 19223,
+ 10255, 22480, 27388, 9946, 15628, 24389, 17308, 2370, 9530, 31683, 25927, 23567, 11694, 26397, 32602, 15031,
+ 18255, 17582, 1422, 28835, 23607, 12597, 20602, 10138, 5212, 1252, 10074, 23166, 19823, 31667, 5902, 24630,
+ 18948, 14330, 14950, 8939, 23540, 21311, 22428, 22391, 3583, 29004, 30498, 18714, 4278, 2437, 22430, 3439,
+ 28313, 23161, 25396, 13471, 19324, 15287, 2563, 18901, 13103, 16867, 9714, 14322, 15197, 26889, 19372, 26241,
+ 31925, 14640, 11497, 8941, 10056, 6451, 28656, 10737, 13874, 17356, 8281, 25937, 1661, 4850, 7448, 12744,
+ 21826, 5477, 10167, 16705, 26897, 8839, 30947, 27978, 27283, 24685, 32298, 3525, 12398, 28726, 9475, 10208,
+ 617, 13467, 22287, 2376, 6097, 26312, 2974, 9114, 21787, 28010, 4725, 15387, 3274, 10762, 31695, 17320,
+ 18324, 12441, 16801, 27376, 22464, 7500, 5666, 18144, 15314, 31914, 31627, 6495, 5226, 31203, 2331, 4668,
+ 12650, 18275, 351, 7268, 31319, 30119, 7600, 2905, 13826, 11343, 13053, 15583, 30055, 31093, 5067, 761,
+ 9685, 11070, 21369, 27155, 3663, 26542, 20169, 12161, 15411, 30401, 7580, 31784, 8985, 29367, 20989, 14203,
+ 29694, 21167, 10337, 1706, 28578, 887, 3373, 19477, 14382, 675, 7033, 15111, 26138, 12252, 30996, 21409,
+ 25678, 18555, 13256, 23316, 22407, 16727, 991, 9236, 5373, 29402, 6117, 15241, 27715, 19291, 19888, 19847
+};
+
+unsigned int U_Random( void )
+{
+ glSeed *= 69069;
+ glSeed += seed_table[ glSeed & 0xff ];
+
+ return ( ++glSeed & 0x0fffffff );
+}
+
+void U_Srand( unsigned int seed )
+{
+ glSeed = seed_table[ seed & 0xff ];
+}
+
+/*
+=====================
+UTIL_SharedRandomLong
+=====================
+*/
+int UTIL_SharedRandomLong( unsigned int seed, int low, int high )
+{
+ unsigned int range;
+
+ U_Srand( (int)seed + low + high );
+
+ range = high - low + 1;
+ if ( !(range - 1) )
+ {
+ return low;
+ }
+ else
+ {
+ int offset;
+ int rnum;
+
+ rnum = U_Random();
+
+ offset = rnum % range;
+
+ return (low + offset);
+ }
+}
+
+/*
+=====================
+UTIL_SharedRandomFloat
+=====================
+*/
+float UTIL_SharedRandomFloat( unsigned int seed, float low, float high )
+{
+
+ U_Srand( (int)seed + *(int *)&low + *(int *)&high );
+
+ U_Random();
+ U_Random();
+
+ float range = high - low;
+ if ( !range )
+ {
+ return low;
+ }
+ else
+ {
+ int tensixrand;
+ float offset;
+
+ tensixrand = U_Random() & 65535;
+
+ offset = (float)tensixrand / 65536.0;
+
+ return (low + offset * range );
+ }
+}
+
+/*
+======================
+stub_*
+
+stub functions for such things as precaching. So we don't have to modify weapons code that
+ is compiled into both game and client .dlls.
+======================
+*/
+int stub_PrecacheModel ( char* s ) { return 0; }
+int stub_PrecacheSound ( char* s ) { return 0; }
+unsigned short stub_PrecacheEvent ( int type, const char *s ) { return 0; }
const char *stub_NameForFunction ( uint32 function ) { return "func"; }
-void stub_SetModel ( edict_t *e, const char *m ) {}
+void stub_SetModel ( edict_t *e, const char *m ) {}
diff --git a/main/source/cl_dll/com_weapons.h b/main/source/cl_dll/com_weapons.h
index e7eafb15..797a4602 100644
--- a/main/source/cl_dll/com_weapons.h
+++ b/main/source/cl_dll/com_weapons.h
@@ -1,49 +1,49 @@
-//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============
-//
-// Purpose:
-//
-// $NoKeywords: $
-//=============================================================================
-
-// com_weapons.h
-// Shared weapons common function prototypes
-#if !defined( COM_WEAPONSH )
-#define COM_WEAPONSH
-#ifdef _WIN32
-#pragma once
-#endif
-
-#include "hud_iface.h"
-
-// TODO: Remove this? Insert this?
-//extern "C"
-//{
-// void DLLEXPORT HUD_PostRunCmd( struct local_state_s *from, struct local_state_s *to, struct usercmd_s *cmd, int runfuncs, double time, unsigned int random_seed );
-//}
-
-void COM_Log( char *pszFile, char *fmt, ...);
-int CL_IsDead( void );
-
-float UTIL_SharedRandomFloat( unsigned int seed, float low, float high );
-int UTIL_SharedRandomLong( unsigned int seed, int low, int high );
-
-int HUD_GetWeaponAnim( void );
-void HUD_SendWeaponAnim( int iAnim, int body, int force );
-void HUD_PlaySound( char *sound, float volume );
-void HUD_PlaybackEvent( int flags, const struct edict_s *pInvoker, unsigned short eventindex, float delay, float *origin, float *angles, float fparam1, float fparam2, int iparam1, int iparam2, int bparam1, int bparam2 );
-void HUD_SetMaxSpeed( const struct edict_s *ed, float speed );
-int stub_PrecacheModel( char* s );
-int stub_PrecacheSound( char* s );
-unsigned short stub_PrecacheEvent( int type, const char *s );
-const char *stub_NameForFunction ( uint32 function );
-void stub_SetModel ( struct edict_s *e, const char *m );
-
-
-extern cvar_t *cl_lw;
-
-extern int g_runfuncs;
-extern vec3_t v_angles;
-extern float g_lastFOV;
-extern struct local_state_s *g_finalstate;
-
+//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================
+
+// com_weapons.h
+// Shared weapons common function prototypes
+#if !defined( COM_WEAPONSH )
+#define COM_WEAPONSH
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "hud_iface.h"
+
+// TODO: Remove this? Insert this?
+//extern "C"
+//{
+// void DLLEXPORT HUD_PostRunCmd( struct local_state_s *from, struct local_state_s *to, struct usercmd_s *cmd, int runfuncs, double time, unsigned int random_seed );
+//}
+
+void COM_Log( char *pszFile, char *fmt, ...);
+int CL_IsDead( void );
+
+float UTIL_SharedRandomFloat( unsigned int seed, float low, float high );
+int UTIL_SharedRandomLong( unsigned int seed, int low, int high );
+
+int HUD_GetWeaponAnim( void );
+void HUD_SendWeaponAnim( int iAnim, int body, int force );
+void HUD_PlaySound( char *sound, float volume );
+void HUD_PlaybackEvent( int flags, const struct edict_s *pInvoker, unsigned short eventindex, float delay, float *origin, float *angles, float fparam1, float fparam2, int iparam1, int iparam2, int bparam1, int bparam2 );
+void HUD_SetMaxSpeed( const struct edict_s *ed, float speed );
+int stub_PrecacheModel( char* s );
+int stub_PrecacheSound( char* s );
+unsigned short stub_PrecacheEvent( int type, const char *s );
+const char *stub_NameForFunction ( uint32 function );
+void stub_SetModel ( struct edict_s *e, const char *m );
+
+
+extern cvar_t *cl_lw;
+
+extern int g_runfuncs;
+extern vec3_t v_angles;
+extern float g_lastFOV;
+extern struct local_state_s *g_finalstate;
+
#endif
\ No newline at end of file
diff --git a/main/source/cl_dll/death.cpp b/main/source/cl_dll/death.cpp
index 02bba8f7..cf08a57c 100644
--- a/main/source/cl_dll/death.cpp
+++ b/main/source/cl_dll/death.cpp
@@ -1,322 +1,322 @@
-/***
-*
-* Copyright (c) 1999, Valve LLC. All rights reserved.
-*
-* This product contains software technology licensed from Id
-* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
-* All Rights Reserved.
-*
-* Use, distribution, and modification of this source code and/or resulting
-* object code is restricted to non-commercial enhancements to products from
-* Valve LLC. All other use, distribution, or modification is prohibited
-* without written permission from Valve LLC.
-*
-****/
-//
-// death notice
-//
-#include "hud.h"
-#include "cl_util.h"
-
-#include
-#include
-
-#include "vgui_TeamFortressViewport.h"
-#include "mod/AvHHudConstants.h"
-#include "pm_shared/pm_shared.h"
-#include "mod/AvHNetworkMessages.h"
-
-DECLARE_MESSAGE( m_DeathNotice, DeathMsg );
-
-struct DeathNoticeItem {
- char szKiller[MAX_PLAYER_NAME_LENGTH*2];
- char szVictim[MAX_PLAYER_NAME_LENGTH*2];
- int iId; // the index number of the associated sprite
- int iSuicide;
- int iTeamKill;
- int iNonPlayerKill;
- float flDisplayTime;
- float *KillerColor;
- float *VictimColor;
-};
-
-#define MAX_DEATHNOTICES 4
-static int DEATHNOTICE_DISPLAY_TIME = 6;
-
-#define DEATHNOTICE_TOP 20
-
-DeathNoticeItem rgDeathNoticeList[ MAX_DEATHNOTICES + 1 ];
-
-// Changing these? Change them in vgui_TeamFortressViewport::iTeamColors as well
-float g_ColorWhite[3] = { 1.0, 1.0f, 1.0 };
-float g_ColorBlue[3] = { .49, .65, .82 };
-float g_ColorOrange[3] = { 1.0, .66, 0.0 };
-float g_ColorGreen[3] = { .56, .84, .55 };
-float g_ColorRed[3] = { .78, .35, .27 };
-
-float g_ColorYellow[3] = { 1.0, .96, .39 };
-
-float* GetClientColor(int clientIndex)
-{
- int theTeamNumber = g_PlayerExtraInfo[clientIndex].teamnumber;
- return kFTeamColors[theTeamNumber];
-}
-
-int CHudDeathNotice :: Init( void )
-{
- gHUD.AddHudElem( this );
-
- HOOK_MESSAGE( DeathMsg );
-
- CVAR_CREATE( "hud_deathnotice_time", "6", 0 );
-
- return 1;
-}
-
-
-void CHudDeathNotice :: InitHUDData( void )
-{
- memset( rgDeathNoticeList, 0, sizeof(rgDeathNoticeList) );
-}
-
-
-int CHudDeathNotice :: VidInit( void )
-{
- m_HUD_d_skull = gHUD.GetSpriteIndex( "d_skull" );
-
- return 1;
-}
-
-int CHudDeathNotice :: Draw( float flTime )
-{
- int x, y, r, g, b;
-
- for ( int i = 0; i < MAX_DEATHNOTICES; i++ )
- {
- if ( rgDeathNoticeList[i].iId == 0 )
- break; // we've gone through them all
-
- if ( rgDeathNoticeList[i].flDisplayTime < flTime )
- {
- // display time has expired, remove the current item from the list
- memmove( &rgDeathNoticeList[i], &rgDeathNoticeList[i+1], sizeof(DeathNoticeItem) * (MAX_DEATHNOTICES - i) );
- i--; // continue on the next item; stop the counter getting incremented
- continue;
- }
-
- rgDeathNoticeList[i].flDisplayTime = min( rgDeathNoticeList[i].flDisplayTime, gHUD.m_flTime + DEATHNOTICE_DISPLAY_TIME );
-
- // Only draw if the viewport will let me
- if ( gViewPort && gViewPort->AllowedToPrintText() )
- {
- // Draw the death notice
- //y = DEATHNOTICE_TOP + (20 * i); //!!!
- int theBaseY = DEATHNOTICE_TOP;
-
- // Bring down death messages when in top down or when we're drawing letter box
- if(gHUD.m_Spectator.IsInOverviewMode())
- {
- // No HUD elements to compensate for
- }
- else if(gHUD.GetInTopDownMode())
- {
- theBaseY = .10*ScreenHeight();
- }
- else if(gHUD.GetIsMarine())
- {
- theBaseY = .26*ScreenHeight();
- }
- else if(gHUD.GetIsAlien())
- {
- theBaseY = kHiveNormScreenY*ScreenHeight() + (kMaxHives-1)*((kHiveNormScreenHeight + kHiveNormScreenVerticalSpacing)*ScreenHeight());
- }
-
- // Lower death messages more when spectating so they don't overlap (due to letterbox)
- if(g_iUser1 != OBS_NONE)
- {
- theBaseY += .06*ScreenHeight();
- }
-
- y = theBaseY + (20 * i); //!!!
-
- int id = (rgDeathNoticeList[i].iId == -1) ? m_HUD_d_skull : rgDeathNoticeList[i].iId;
- x = ScreenWidth() - ConsoleStringLen(rgDeathNoticeList[i].szVictim) - (gHUD.GetSpriteRect(id).right - gHUD.GetSpriteRect(id).left);
-
- if ( !rgDeathNoticeList[i].iSuicide )
- {
- x -= (5 + ConsoleStringLen( rgDeathNoticeList[i].szKiller ) );
-
- // Draw killers name
- if ( rgDeathNoticeList[i].KillerColor )
- DrawSetTextColor( rgDeathNoticeList[i].KillerColor[0], rgDeathNoticeList[i].KillerColor[1], rgDeathNoticeList[i].KillerColor[2] );
- x = 5 + DrawConsoleString( x, y, rgDeathNoticeList[i].szKiller );
- }
-
- r = 255; g = 80; b = 0;
- if ( rgDeathNoticeList[i].iTeamKill )
- {
- r = 10; g = 240; b = 10; // display it in sickly green
- }
-
- // Draw death weapon
- SPR_Set( gHUD.GetSprite(id), r, g, b );
- SPR_DrawAdditive( 0, x, y, &gHUD.GetSpriteRect(id) );
-
- x += (gHUD.GetSpriteRect(id).right - gHUD.GetSpriteRect(id).left);
-
- // Draw victims name (if it was a player that was killed)
- if (rgDeathNoticeList[i].iNonPlayerKill == FALSE)
- {
- if ( rgDeathNoticeList[i].VictimColor )
- DrawSetTextColor( rgDeathNoticeList[i].VictimColor[0], rgDeathNoticeList[i].VictimColor[1], rgDeathNoticeList[i].VictimColor[2] );
- x = DrawConsoleString( x, y, rgDeathNoticeList[i].szVictim );
- }
- }
- }
-
- return 1;
-}
-
-// This message handler may be better off elsewhere
-int CHudDeathNotice :: MsgFunc_DeathMsg( const char *pszName, int iSize, void *pbuf )
-{
- m_iFlags |= HUD_ACTIVE;
-
- int killer, victim;
- string killed_with;
- NetMsg_DeathMsg( pbuf, iSize, killer, victim, killed_with );
-
- if (gViewPort)
- gViewPort->DeathMsg( killer, victim );
-
- gHUD.m_Spectator.DeathMessage(victim);
- int i;
- for ( i = 0; i < MAX_DEATHNOTICES; i++ )
- {
- if ( rgDeathNoticeList[i].iId == 0 )
- break;
- }
- if ( i == MAX_DEATHNOTICES )
- { // move the rest of the list forward to make room for this item
- memmove( rgDeathNoticeList, rgDeathNoticeList+1, sizeof(DeathNoticeItem) * MAX_DEATHNOTICES );
- i = MAX_DEATHNOTICES - 1;
- }
-
- if (gViewPort)
- gViewPort->GetAllPlayersInfo();
-
- // Get the Killer's name
- char *killer_name = g_PlayerInfoList[ killer ].name;
- if ( !killer_name )
- {
- killer_name = "";
- rgDeathNoticeList[i].szKiller[0] = 0;
- }
- else
- {
- rgDeathNoticeList[i].KillerColor = GetClientColor( killer);
- strncpy( rgDeathNoticeList[i].szKiller, killer_name, MAX_PLAYER_NAME_LENGTH );
- rgDeathNoticeList[i].szKiller[MAX_PLAYER_NAME_LENGTH-1] = 0;
- }
-
- // Get the Victim's name
- char *victim_name = NULL;
- // If victim is -1, the killer killed a specific, non-player object (like a sentrygun)
- if ( ((char)victim) != -1 )
- victim_name = g_PlayerInfoList[ victim ].name;
- if ( !victim_name )
- {
- victim_name = "";
- rgDeathNoticeList[i].szVictim[0] = 0;
- }
- else
- {
- rgDeathNoticeList[i].VictimColor = GetClientColor(victim);
- strncpy( rgDeathNoticeList[i].szVictim, victim_name, MAX_PLAYER_NAME_LENGTH );
- rgDeathNoticeList[i].szVictim[MAX_PLAYER_NAME_LENGTH-1] = 0;
- }
-
- // Is it a non-player object kill?
- if ( ((char)victim) == -1 )
- {
- rgDeathNoticeList[i].iNonPlayerKill = TRUE;
-
- // Store the object's name in the Victim slot (skip the d_ bit)
- strcpy( rgDeathNoticeList[i].szVictim, killed_with.c_str()+2 );
- }
- else
- {
- if ( killer == victim || killer == 0 )
- rgDeathNoticeList[i].iSuicide = TRUE;
-
- if ( !strcmp( killed_with.c_str(), "d_teammate" ) )
- rgDeathNoticeList[i].iTeamKill = TRUE;
- }
-
- // Find the sprite in the list
- char killed_with_spritename[32];
- sprintf(killed_with_spritename, "d_%s", killed_with.c_str());
- int spr = gHUD.GetSpriteIndex( killed_with_spritename );
-
- rgDeathNoticeList[i].iId = spr;
-
- DEATHNOTICE_DISPLAY_TIME = CVAR_GET_FLOAT( "hud_deathnotice_time" );
- rgDeathNoticeList[i].flDisplayTime = gHUD.m_flTime + DEATHNOTICE_DISPLAY_TIME;
-
- if (rgDeathNoticeList[i].iNonPlayerKill)
- {
- ConsolePrint( rgDeathNoticeList[i].szKiller );
- ConsolePrint( " killed a " );
- ConsolePrint( rgDeathNoticeList[i].szVictim );
- ConsolePrint( "\n" );
- }
- else
- {
- // record the death notice in the console
- if ( rgDeathNoticeList[i].iSuicide )
- {
- ConsolePrint( rgDeathNoticeList[i].szVictim );
-
- if ( !strcmp( killed_with.c_str(), "world" ) )
- {
- ConsolePrint( " died" );
- }
- else
- {
- ConsolePrint( " killed self" );
- }
- }
- else if ( rgDeathNoticeList[i].iTeamKill )
- {
- ConsolePrint( rgDeathNoticeList[i].szKiller );
- ConsolePrint( " killed his teammate " );
- ConsolePrint( rgDeathNoticeList[i].szVictim );
- }
- else
- {
- ConsolePrint( rgDeathNoticeList[i].szKiller );
- ConsolePrint( " killed " );
- ConsolePrint( rgDeathNoticeList[i].szVictim );
- }
-
- if ( !killed_with.empty() && killed_with != "world" && !rgDeathNoticeList[i].iTeamKill )
- {
- ConsolePrint( " with " );
-
- // replace the code names with the 'real' names
- if ( killed_with == "d_egon" )
- killed_with = "d_gluon gun";
- if ( killed_with == "gauss" )
- killed_with = "d_tau cannon";
- ConsolePrint( killed_with.c_str()); // skip over the "d_" part
- }
-
- ConsolePrint( "\n" );
- }
-
- return 1;
-}
-
-
-
-
+/***
+*
+* Copyright (c) 1999, Valve LLC. All rights reserved.
+*
+* This product contains software technology licensed from Id
+* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
+* All Rights Reserved.
+*
+* Use, distribution, and modification of this source code and/or resulting
+* object code is restricted to non-commercial enhancements to products from
+* Valve LLC. All other use, distribution, or modification is prohibited
+* without written permission from Valve LLC.
+*
+****/
+//
+// death notice
+//
+#include "hud.h"
+#include "cl_util.h"
+
+#include
+#include
+
+#include "vgui_TeamFortressViewport.h"
+#include "mod/AvHHudConstants.h"
+#include "pm_shared/pm_shared.h"
+#include "mod/AvHNetworkMessages.h"
+
+DECLARE_MESSAGE( m_DeathNotice, DeathMsg );
+
+struct DeathNoticeItem {
+ char szKiller[MAX_PLAYER_NAME_LENGTH*2];
+ char szVictim[MAX_PLAYER_NAME_LENGTH*2];
+ int iId; // the index number of the associated sprite
+ int iSuicide;
+ int iTeamKill;
+ int iNonPlayerKill;
+ float flDisplayTime;
+ float *KillerColor;
+ float *VictimColor;
+};
+
+#define MAX_DEATHNOTICES 4
+static int DEATHNOTICE_DISPLAY_TIME = 6;
+
+#define DEATHNOTICE_TOP 20
+
+DeathNoticeItem rgDeathNoticeList[ MAX_DEATHNOTICES + 1 ];
+
+// Changing these? Change them in vgui_TeamFortressViewport::iTeamColors as well
+float g_ColorWhite[3] = { 1.0, 1.0f, 1.0 };
+float g_ColorBlue[3] = { .49, .65, .82 };
+float g_ColorOrange[3] = { 1.0, .66, 0.0 };
+float g_ColorGreen[3] = { .56, .84, .55 };
+float g_ColorRed[3] = { .78, .35, .27 };
+
+float g_ColorYellow[3] = { 1.0, .96, .39 };
+
+float* GetClientColor(int clientIndex)
+{
+ int theTeamNumber = g_PlayerExtraInfo[clientIndex].teamnumber;
+ return kFTeamColors[theTeamNumber];
+}
+
+int CHudDeathNotice :: Init( void )
+{
+ gHUD.AddHudElem( this );
+
+ HOOK_MESSAGE( DeathMsg );
+
+ CVAR_CREATE( "hud_deathnotice_time", "6", 0 );
+
+ return 1;
+}
+
+
+void CHudDeathNotice :: InitHUDData( void )
+{
+ memset( rgDeathNoticeList, 0, sizeof(rgDeathNoticeList) );
+}
+
+
+int CHudDeathNotice :: VidInit( void )
+{
+ m_HUD_d_skull = gHUD.GetSpriteIndex( "d_skull" );
+
+ return 1;
+}
+
+int CHudDeathNotice :: Draw( float flTime )
+{
+ int x, y, r, g, b;
+
+ for ( int i = 0; i < MAX_DEATHNOTICES; i++ )
+ {
+ if ( rgDeathNoticeList[i].iId == 0 )
+ break; // we've gone through them all
+
+ if ( rgDeathNoticeList[i].flDisplayTime < flTime )
+ {
+ // display time has expired, remove the current item from the list
+ memmove( &rgDeathNoticeList[i], &rgDeathNoticeList[i+1], sizeof(DeathNoticeItem) * (MAX_DEATHNOTICES - i) );
+ i--; // continue on the next item; stop the counter getting incremented
+ continue;
+ }
+
+ rgDeathNoticeList[i].flDisplayTime = min( rgDeathNoticeList[i].flDisplayTime, gHUD.m_flTime + DEATHNOTICE_DISPLAY_TIME );
+
+ // Only draw if the viewport will let me
+ if ( gViewPort && gViewPort->AllowedToPrintText() )
+ {
+ // Draw the death notice
+ //y = DEATHNOTICE_TOP + (20 * i); //!!!
+ int theBaseY = DEATHNOTICE_TOP;
+
+ // Bring down death messages when in top down or when we're drawing letter box
+ if(gHUD.m_Spectator.IsInOverviewMode())
+ {
+ // No HUD elements to compensate for
+ }
+ else if(gHUD.GetInTopDownMode())
+ {
+ theBaseY = .10*ScreenHeight();
+ }
+ else if(gHUD.GetIsMarine())
+ {
+ theBaseY = .26*ScreenHeight();
+ }
+ else if(gHUD.GetIsAlien())
+ {
+ theBaseY = kHiveNormScreenY*ScreenHeight() + (kMaxHives-1)*((kHiveNormScreenHeight + kHiveNormScreenVerticalSpacing)*ScreenHeight());
+ }
+
+ // Lower death messages more when spectating so they don't overlap (due to letterbox)
+ if(g_iUser1 != OBS_NONE)
+ {
+ theBaseY += .06*ScreenHeight();
+ }
+
+ y = theBaseY + (20 * i); //!!!
+
+ int id = (rgDeathNoticeList[i].iId == -1) ? m_HUD_d_skull : rgDeathNoticeList[i].iId;
+ x = ScreenWidth() - ConsoleStringLen(rgDeathNoticeList[i].szVictim) - (gHUD.GetSpriteRect(id).right - gHUD.GetSpriteRect(id).left);
+
+ if ( !rgDeathNoticeList[i].iSuicide )
+ {
+ x -= (5 + ConsoleStringLen( rgDeathNoticeList[i].szKiller ) );
+
+ // Draw killers name
+ if ( rgDeathNoticeList[i].KillerColor )
+ DrawSetTextColor( rgDeathNoticeList[i].KillerColor[0], rgDeathNoticeList[i].KillerColor[1], rgDeathNoticeList[i].KillerColor[2] );
+ x = 5 + DrawConsoleString( x, y, rgDeathNoticeList[i].szKiller );
+ }
+
+ r = 255; g = 80; b = 0;
+ if ( rgDeathNoticeList[i].iTeamKill )
+ {
+ r = 10; g = 240; b = 10; // display it in sickly green
+ }
+
+ // Draw death weapon
+ SPR_Set( gHUD.GetSprite(id), r, g, b );
+ SPR_DrawAdditive( 0, x, y, &gHUD.GetSpriteRect(id) );
+
+ x += (gHUD.GetSpriteRect(id).right - gHUD.GetSpriteRect(id).left);
+
+ // Draw victims name (if it was a player that was killed)
+ if (rgDeathNoticeList[i].iNonPlayerKill == FALSE)
+ {
+ if ( rgDeathNoticeList[i].VictimColor )
+ DrawSetTextColor( rgDeathNoticeList[i].VictimColor[0], rgDeathNoticeList[i].VictimColor[1], rgDeathNoticeList[i].VictimColor[2] );
+ x = DrawConsoleString( x, y, rgDeathNoticeList[i].szVictim );
+ }
+ }
+ }
+
+ return 1;
+}
+
+// This message handler may be better off elsewhere
+int CHudDeathNotice :: MsgFunc_DeathMsg( const char *pszName, int iSize, void *pbuf )
+{
+ m_iFlags |= HUD_ACTIVE;
+
+ int killer, victim;
+ string killed_with;
+ NetMsg_DeathMsg( pbuf, iSize, killer, victim, killed_with );
+
+ if (gViewPort)
+ gViewPort->DeathMsg( killer, victim );
+
+ gHUD.m_Spectator.DeathMessage(victim);
+ int i;
+ for ( i = 0; i < MAX_DEATHNOTICES; i++ )
+ {
+ if ( rgDeathNoticeList[i].iId == 0 )
+ break;
+ }
+ if ( i == MAX_DEATHNOTICES )
+ { // move the rest of the list forward to make room for this item
+ memmove( rgDeathNoticeList, rgDeathNoticeList+1, sizeof(DeathNoticeItem) * MAX_DEATHNOTICES );
+ i = MAX_DEATHNOTICES - 1;
+ }
+
+ if (gViewPort)
+ gViewPort->GetAllPlayersInfo();
+
+ // Get the Killer's name
+ char *killer_name = g_PlayerInfoList[ killer ].name;
+ if ( !killer_name )
+ {
+ killer_name = "";
+ rgDeathNoticeList[i].szKiller[0] = 0;
+ }
+ else
+ {
+ rgDeathNoticeList[i].KillerColor = GetClientColor( killer);
+ strncpy( rgDeathNoticeList[i].szKiller, killer_name, MAX_PLAYER_NAME_LENGTH );
+ rgDeathNoticeList[i].szKiller[MAX_PLAYER_NAME_LENGTH-1] = 0;
+ }
+
+ // Get the Victim's name
+ char *victim_name = NULL;
+ // If victim is -1, the killer killed a specific, non-player object (like a sentrygun)
+ if ( ((char)victim) != -1 )
+ victim_name = g_PlayerInfoList[ victim ].name;
+ if ( !victim_name )
+ {
+ victim_name = "";
+ rgDeathNoticeList[i].szVictim[0] = 0;
+ }
+ else
+ {
+ rgDeathNoticeList[i].VictimColor = GetClientColor(victim);
+ strncpy( rgDeathNoticeList[i].szVictim, victim_name, MAX_PLAYER_NAME_LENGTH );
+ rgDeathNoticeList[i].szVictim[MAX_PLAYER_NAME_LENGTH-1] = 0;
+ }
+
+ // Is it a non-player object kill?
+ if ( ((char)victim) == -1 )
+ {
+ rgDeathNoticeList[i].iNonPlayerKill = TRUE;
+
+ // Store the object's name in the Victim slot (skip the d_ bit)
+ strcpy( rgDeathNoticeList[i].szVictim, killed_with.c_str()+2 );
+ }
+ else
+ {
+ if ( killer == victim || killer == 0 )
+ rgDeathNoticeList[i].iSuicide = TRUE;
+
+ if ( !strcmp( killed_with.c_str(), "d_teammate" ) )
+ rgDeathNoticeList[i].iTeamKill = TRUE;
+ }
+
+ // Find the sprite in the list
+ char killed_with_spritename[32];
+ sprintf(killed_with_spritename, "d_%s", killed_with.c_str());
+ int spr = gHUD.GetSpriteIndex( killed_with_spritename );
+
+ rgDeathNoticeList[i].iId = spr;
+
+ DEATHNOTICE_DISPLAY_TIME = CVAR_GET_FLOAT( "hud_deathnotice_time" );
+ rgDeathNoticeList[i].flDisplayTime = gHUD.m_flTime + DEATHNOTICE_DISPLAY_TIME;
+
+ if (rgDeathNoticeList[i].iNonPlayerKill)
+ {
+ ConsolePrint( rgDeathNoticeList[i].szKiller );
+ ConsolePrint( " killed a " );
+ ConsolePrint( rgDeathNoticeList[i].szVictim );
+ ConsolePrint( "\n" );
+ }
+ else
+ {
+ // record the death notice in the console
+ if ( rgDeathNoticeList[i].iSuicide )
+ {
+ ConsolePrint( rgDeathNoticeList[i].szVictim );
+
+ if ( !strcmp( killed_with.c_str(), "world" ) )
+ {
+ ConsolePrint( " died" );
+ }
+ else
+ {
+ ConsolePrint( " killed self" );
+ }
+ }
+ else if ( rgDeathNoticeList[i].iTeamKill )
+ {
+ ConsolePrint( rgDeathNoticeList[i].szKiller );
+ ConsolePrint( " killed his teammate " );
+ ConsolePrint( rgDeathNoticeList[i].szVictim );
+ }
+ else
+ {
+ ConsolePrint( rgDeathNoticeList[i].szKiller );
+ ConsolePrint( " killed " );
+ ConsolePrint( rgDeathNoticeList[i].szVictim );
+ }
+
+ if ( !killed_with.empty() && killed_with != "world" && !rgDeathNoticeList[i].iTeamKill )
+ {
+ ConsolePrint( " with " );
+
+ // replace the code names with the 'real' names
+ if ( killed_with == "d_egon" )
+ killed_with = "d_gluon gun";
+ if ( killed_with == "gauss" )
+ killed_with = "d_tau cannon";
+ ConsolePrint( killed_with.c_str()); // skip over the "d_" part
+ }
+
+ ConsolePrint( "\n" );
+ }
+
+ return 1;
+}
+
+
+
+
diff --git a/main/source/cl_dll/demo.cpp b/main/source/cl_dll/demo.cpp
index a8d73f59..53e3c3a9 100644
--- a/main/source/cl_dll/demo.cpp
+++ b/main/source/cl_dll/demo.cpp
@@ -1,274 +1,274 @@
-/***
-*
-* Copyright (c) 1999, Valve LLC. All rights reserved.
-*
-* This product contains software technology licensed from Id
-* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
-* All Rights Reserved.
-*
-* Use, distribution, and modification of this source code and/or resulting
-* object code is restricted to non-commercial enhancements to products from
-* Valve LLC. All other use, distribution, or modification is prohibited
-* without written permission from Valve LLC.
-*
-****/
-#include "hud.h"
-#include "cl_util.h"
-#include "demo.h"
-#include "common/demo_api.h"
-#include
-
-#include "engine/APIProxy.h"
-#include "Exports.h"
-#include "mod/AvHParticleTemplateClient.h"
-#include "cl_dll/view.h"
-
-extern AvHParticleTemplateListClient gParticleTemplateList;
-
-int g_demosniper = 0;
-int g_demosniperdamage = 0;
-float g_demosniperorg[3];
-float g_demosniperangles[3];
-float g_demozoom;
-vec3_t gPlaybackViewOrigin;
-
-int ScorePanel_InitializeDemoPlayback(int inSize, unsigned char* inBuffer);
-void ScorePanel_InitializeDemoRecording();
-
-float gNormMouseX = 0;
-float gNormMouseY = 0;
-
-// FIXME: There should be buffer helper functions to avoid all of the *(int *)& crap.
-
-void Demo_WriteByte(int inType, unsigned char inByte)
-{
- Demo_WriteBuffer(inType, sizeof(unsigned char), &inByte);
-}
-
-void Demo_WriteVector(int inType, vec3_t inVector)
-{
- float theFloatArray[3];
-
- theFloatArray[0] = inVector.x;
- theFloatArray[1] = inVector.y;
- theFloatArray[2] = inVector.z;
-
- Demo_WriteBuffer(inType, 3*sizeof(float), (unsigned char*)theFloatArray);
-}
-
-void Demo_WriteFloat(int inType, float inFloat)
-{
- Demo_WriteBuffer(inType, sizeof(float), (unsigned char*)&inFloat);
-}
-
-void Demo_WriteInt(int inType, int inInt)
-{
- Demo_WriteBuffer(inType, sizeof(int), (unsigned char*)&inInt);
-}
-
-/*
-=====================
-Demo_WriteBuffer
-
-Write some data to the demo stream
-=====================
-*/
-void Demo_WriteBuffer( int type, int size, unsigned char *buffer )
-{
- int pos = 0;
- unsigned char buf[ 32 * 1024 ];
- *( int * )&buf[pos] = type;
- pos+=sizeof( int );
-
- memcpy( &buf[pos], buffer, size );
-
- // Write full buffer out
- gEngfuncs.pDemoAPI->WriteBuffer( size + sizeof( int ), buf );
-}
-
-/*
-=====================
-Demo_ReadBuffer
-
-Engine wants us to parse some data from the demo stream
-=====================
-*/
-void CL_DLLEXPORT Demo_ReadBuffer( int size, unsigned char *buffer )
-{
-// RecClReadDemoBuffer(size, buffer);
-
- int type;
- int i = 0;
- bool theMouseVisibility = false;
- int particleIndex=0;
-
- type = *( int * )buffer;
- i += sizeof( int );
- switch ( type )
- {
- case TYPE_SNIPERDOT:
- g_demosniper = *(int * )&buffer[ i ];
- i += sizeof( int );
-
- if ( g_demosniper )
- {
- g_demosniperdamage = *( int * )&buffer[ i ];
- i += sizeof( int );
-
- g_demosniperangles[ 0 ] = *(float *)&buffer[i];
- i += sizeof( float );
- g_demosniperangles[ 1 ] = *(float *)&buffer[i];
- i += sizeof( float );
- g_demosniperangles[ 2 ] = *(float *)&buffer[i];
- i += sizeof( float );
- g_demosniperorg[ 0 ] = *(float *)&buffer[i];
- i += sizeof( float );
- g_demosniperorg[ 1 ] = *(float *)&buffer[i];
- i += sizeof( float );
- g_demosniperorg[ 2 ] = *(float *)&buffer[i];
- i += sizeof( float );
- }
- break;
- case TYPE_ZOOM:
- g_demozoom = *(float * )&buffer[ i ];
- i += sizeof( float );
- break;
-
- case TYPE_BASESTATE:
- i += gHUD.InitializeDemoPlayback(size, (unsigned char *)&buffer[i]);
- break;
-
- case TYPE_MOUSEVIS:
- //theMouseVisibility = *(unsigned char * )&buffer[ i ];
- //gHUD.GetManager().SetMouseVisibility(theMouseVisibility);
- i += sizeof(unsigned char);
- break;
-
- case TYPE_MOUSEX:
- //gNormMouseX = *(float * )&buffer[ i ];
- i += sizeof( float );
- break;
-
- case TYPE_MOUSEY:
- //gNormMouseY = *(float * )&buffer[ i ];
- i += sizeof( float );
- break;
-
- case TYPE_VIEWANGLES:
- v_angles[0] = *(float * )&buffer[ i ];
- i += sizeof( float );
-
- v_angles[1] = *(float * )&buffer[ i ];
- i += sizeof( float );
-
- v_angles[2] = *(float * )&buffer[ i ];
- i += sizeof( float );
- break;
-
- case TYPE_VIEWORIGIN:
- v_origin[0] = *(float * )&buffer[ i ];
- i += sizeof( float );
-
- v_origin[1] = *(float * )&buffer[ i ];
- i += sizeof( float );
-
- v_origin[2] = *(float * )&buffer[ i ];
- i += sizeof( float );
- break;
-
- case TYPE_PARTICLES:
- i += gParticleTemplateList.InitializeDemoPlayback(size, (unsigned char*)&buffer[i], particleIndex++);
- break;
-
- case TYPE_BASESTATE2:
- i += gHUD.InitializeDemoPlayback2(size, (unsigned char *)&buffer[i]);
- break;
-
- case TYPE_PLAYERINFO:
- i += ScorePanel_InitializeDemoPlayback(size, (unsigned char *)&buffer[i]);
- break;
-
- case TYPE_WEAPONINFO:
- i += gHUD.InitializeWeaponInfoPlayback(size, (unsigned char *)&buffer[i]);
- break;
-
- default:
- gEngfuncs.Con_DPrintf( "Unknown demo buffer type, skipping.\n" );
- break;
- }
-}
-
-// Returns num bytes needed to save/restore a string
-int GetDataSize(const string& inString)
-{
- // String length
- int theSize = sizeof(int);
-
- // String data
- theSize += (int)inString.length();
-
- return theSize;
-}
-
-void LoadData(void* inBuffer, const unsigned char* inData, int inSizeToCopy, int& inSizeVariable)
-{
- memcpy(inBuffer, inData + inSizeVariable, inSizeToCopy);
- inSizeVariable += inSizeToCopy;
-}
-
-void LoadStringData(string& outString, const unsigned char* inData, int& inBytesRead)
-{
- // Read in string length (could be 0)
- int theStringLength = 0;
- memcpy(&theStringLength, inData + inBytesRead, sizeof(int));
- inBytesRead += sizeof(int);
-
- // Read in string, if greater then 0
- if(theStringLength > 0)
- {
- char* theStringData = new char[theStringLength+1];
- memcpy(theStringData, inData + inBytesRead, theStringLength);
- theStringData[theStringLength] = '\0';
- inBytesRead += theStringLength;
-
- outString = string(theStringData);
-
- delete [] theStringData;
- theStringData = NULL;
- }
-}
-
-void LoadVectorData(float* outData, const unsigned char* inData, int& inBytesRead)
-{
- int theSize = 3*sizeof(float);
- memcpy(outData, inData + inBytesRead, theSize);
- inBytesRead += theSize;
-}
-
-void SaveData(unsigned char* inBuffer, const void* inData, int inSizeToCopy, int& inSizeVariable)
-{
- memcpy(inBuffer + inSizeVariable, inData, inSizeToCopy);
- inSizeVariable += inSizeToCopy;
-}
-
-// Save out string, works for empty strings
-void SaveStringData(unsigned char* inBuffer, const string& inString, int& inSizeVariable)
-{
- int theStringLength = (int)inString.length();
-
- // Write out string length
- memcpy(inBuffer + inSizeVariable, &theStringLength, sizeof(int));
- inSizeVariable += sizeof(int);
-
- // Write out string data, if any
- memcpy(inBuffer + inSizeVariable, inString.c_str(), theStringLength);
- inSizeVariable += theStringLength;
-}
-
-void SaveVectorData(unsigned char* inBuffer, float* inData, int& inSizeVariable)
-{
- int theLength = 3*sizeof(float);
-
- memcpy(inBuffer + inSizeVariable, inData, theLength);
- inSizeVariable += theLength;
-}
+/***
+*
+* Copyright (c) 1999, Valve LLC. All rights reserved.
+*
+* This product contains software technology licensed from Id
+* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
+* All Rights Reserved.
+*
+* Use, distribution, and modification of this source code and/or resulting
+* object code is restricted to non-commercial enhancements to products from
+* Valve LLC. All other use, distribution, or modification is prohibited
+* without written permission from Valve LLC.
+*
+****/
+#include "hud.h"
+#include "cl_util.h"
+#include "demo.h"
+#include "common/demo_api.h"
+#include
+
+#include "engine/APIProxy.h"
+#include "Exports.h"
+#include "mod/AvHParticleTemplateClient.h"
+#include "cl_dll/view.h"
+
+extern AvHParticleTemplateListClient gParticleTemplateList;
+
+int g_demosniper = 0;
+int g_demosniperdamage = 0;
+float g_demosniperorg[3];
+float g_demosniperangles[3];
+float g_demozoom;
+vec3_t gPlaybackViewOrigin;
+
+int ScorePanel_InitializeDemoPlayback(int inSize, unsigned char* inBuffer);
+void ScorePanel_InitializeDemoRecording();
+
+float gNormMouseX = 0;
+float gNormMouseY = 0;
+
+// FIXME: There should be buffer helper functions to avoid all of the *(int *)& crap.
+
+void Demo_WriteByte(int inType, unsigned char inByte)
+{
+ Demo_WriteBuffer(inType, sizeof(unsigned char), &inByte);
+}
+
+void Demo_WriteVector(int inType, vec3_t inVector)
+{
+ float theFloatArray[3];
+
+ theFloatArray[0] = inVector.x;
+ theFloatArray[1] = inVector.y;
+ theFloatArray[2] = inVector.z;
+
+ Demo_WriteBuffer(inType, 3*sizeof(float), (unsigned char*)theFloatArray);
+}
+
+void Demo_WriteFloat(int inType, float inFloat)
+{
+ Demo_WriteBuffer(inType, sizeof(float), (unsigned char*)&inFloat);
+}
+
+void Demo_WriteInt(int inType, int inInt)
+{
+ Demo_WriteBuffer(inType, sizeof(int), (unsigned char*)&inInt);
+}
+
+/*
+=====================
+Demo_WriteBuffer
+
+Write some data to the demo stream
+=====================
+*/
+void Demo_WriteBuffer( int type, int size, unsigned char *buffer )
+{
+ int pos = 0;
+ unsigned char buf[ 32 * 1024 ];
+ *( int * )&buf[pos] = type;
+ pos+=sizeof( int );
+
+ memcpy( &buf[pos], buffer, size );
+
+ // Write full buffer out
+ gEngfuncs.pDemoAPI->WriteBuffer( size + sizeof( int ), buf );
+}
+
+/*
+=====================
+Demo_ReadBuffer
+
+Engine wants us to parse some data from the demo stream
+=====================
+*/
+void CL_DLLEXPORT Demo_ReadBuffer( int size, unsigned char *buffer )
+{
+// RecClReadDemoBuffer(size, buffer);
+
+ int type;
+ int i = 0;
+ bool theMouseVisibility = false;
+ int particleIndex=0;
+
+ type = *( int * )buffer;
+ i += sizeof( int );
+ switch ( type )
+ {
+ case TYPE_SNIPERDOT:
+ g_demosniper = *(int * )&buffer[ i ];
+ i += sizeof( int );
+
+ if ( g_demosniper )
+ {
+ g_demosniperdamage = *( int * )&buffer[ i ];
+ i += sizeof( int );
+
+ g_demosniperangles[ 0 ] = *(float *)&buffer[i];
+ i += sizeof( float );
+ g_demosniperangles[ 1 ] = *(float *)&buffer[i];
+ i += sizeof( float );
+ g_demosniperangles[ 2 ] = *(float *)&buffer[i];
+ i += sizeof( float );
+ g_demosniperorg[ 0 ] = *(float *)&buffer[i];
+ i += sizeof( float );
+ g_demosniperorg[ 1 ] = *(float *)&buffer[i];
+ i += sizeof( float );
+ g_demosniperorg[ 2 ] = *(float *)&buffer[i];
+ i += sizeof( float );
+ }
+ break;
+ case TYPE_ZOOM:
+ g_demozoom = *(float * )&buffer[ i ];
+ i += sizeof( float );
+ break;
+
+ case TYPE_BASESTATE:
+ i += gHUD.InitializeDemoPlayback(size, (unsigned char *)&buffer[i]);
+ break;
+
+ case TYPE_MOUSEVIS:
+ //theMouseVisibility = *(unsigned char * )&buffer[ i ];
+ //gHUD.GetManager().SetMouseVisibility(theMouseVisibility);
+ i += sizeof(unsigned char);
+ break;
+
+ case TYPE_MOUSEX:
+ //gNormMouseX = *(float * )&buffer[ i ];
+ i += sizeof( float );
+ break;
+
+ case TYPE_MOUSEY:
+ //gNormMouseY = *(float * )&buffer[ i ];
+ i += sizeof( float );
+ break;
+
+ case TYPE_VIEWANGLES:
+ v_angles[0] = *(float * )&buffer[ i ];
+ i += sizeof( float );
+
+ v_angles[1] = *(float * )&buffer[ i ];
+ i += sizeof( float );
+
+ v_angles[2] = *(float * )&buffer[ i ];
+ i += sizeof( float );
+ break;
+
+ case TYPE_VIEWORIGIN:
+ v_origin[0] = *(float * )&buffer[ i ];
+ i += sizeof( float );
+
+ v_origin[1] = *(float * )&buffer[ i ];
+ i += sizeof( float );
+
+ v_origin[2] = *(float * )&buffer[ i ];
+ i += sizeof( float );
+ break;
+
+ case TYPE_PARTICLES:
+ i += gParticleTemplateList.InitializeDemoPlayback(size, (unsigned char*)&buffer[i], particleIndex++);
+ break;
+
+ case TYPE_BASESTATE2:
+ i += gHUD.InitializeDemoPlayback2(size, (unsigned char *)&buffer[i]);
+ break;
+
+ case TYPE_PLAYERINFO:
+ i += ScorePanel_InitializeDemoPlayback(size, (unsigned char *)&buffer[i]);
+ break;
+
+ case TYPE_WEAPONINFO:
+ i += gHUD.InitializeWeaponInfoPlayback(size, (unsigned char *)&buffer[i]);
+ break;
+
+ default:
+ gEngfuncs.Con_DPrintf( "Unknown demo buffer type, skipping.\n" );
+ break;
+ }
+}
+
+// Returns num bytes needed to save/restore a string
+int GetDataSize(const string& inString)
+{
+ // String length
+ int theSize = sizeof(int);
+
+ // String data
+ theSize += (int)inString.length();
+
+ return theSize;
+}
+
+void LoadData(void* inBuffer, const unsigned char* inData, int inSizeToCopy, int& inSizeVariable)
+{
+ memcpy(inBuffer, inData + inSizeVariable, inSizeToCopy);
+ inSizeVariable += inSizeToCopy;
+}
+
+void LoadStringData(string& outString, const unsigned char* inData, int& inBytesRead)
+{
+ // Read in string length (could be 0)
+ int theStringLength = 0;
+ memcpy(&theStringLength, inData + inBytesRead, sizeof(int));
+ inBytesRead += sizeof(int);
+
+ // Read in string, if greater then 0
+ if(theStringLength > 0)
+ {
+ char* theStringData = new char[theStringLength+1];
+ memcpy(theStringData, inData + inBytesRead, theStringLength);
+ theStringData[theStringLength] = '\0';
+ inBytesRead += theStringLength;
+
+ outString = string(theStringData);
+
+ delete [] theStringData;
+ theStringData = NULL;
+ }
+}
+
+void LoadVectorData(float* outData, const unsigned char* inData, int& inBytesRead)
+{
+ int theSize = 3*sizeof(float);
+ memcpy(outData, inData + inBytesRead, theSize);
+ inBytesRead += theSize;
+}
+
+void SaveData(unsigned char* inBuffer, const void* inData, int inSizeToCopy, int& inSizeVariable)
+{
+ memcpy(inBuffer + inSizeVariable, inData, inSizeToCopy);
+ inSizeVariable += inSizeToCopy;
+}
+
+// Save out string, works for empty strings
+void SaveStringData(unsigned char* inBuffer, const string& inString, int& inSizeVariable)
+{
+ int theStringLength = (int)inString.length();
+
+ // Write out string length
+ memcpy(inBuffer + inSizeVariable, &theStringLength, sizeof(int));
+ inSizeVariable += sizeof(int);
+
+ // Write out string data, if any
+ memcpy(inBuffer + inSizeVariable, inString.c_str(), theStringLength);
+ inSizeVariable += theStringLength;
+}
+
+void SaveVectorData(unsigned char* inBuffer, float* inData, int& inSizeVariable)
+{
+ int theLength = 3*sizeof(float);
+
+ memcpy(inBuffer + inSizeVariable, inData, theLength);
+ inSizeVariable += theLength;
+}
diff --git a/main/source/cl_dll/demo.h b/main/source/cl_dll/demo.h
index 6ca80533..e19fc732 100644
--- a/main/source/cl_dll/demo.h
+++ b/main/source/cl_dll/demo.h
@@ -1,56 +1,56 @@
-#if !defined( DEMOH )
-#define DEMOH
-#pragma once
-
-// Types of demo messages we can write/parse
-enum
-{
- TYPE_SNIPERDOT = 0,
- TYPE_ZOOM,
-
- TYPE_BASESTATE,
- TYPE_MOUSEVIS,
- TYPE_MOUSEX,
- TYPE_MOUSEY,
- TYPE_VIEWORIGIN,
- TYPE_VIEWANGLES,
- TYPE_PARTICLES,
-
- // More base state that wasn't originally saved (made a separate type for backwards-compatibility)
- TYPE_BASESTATE2,
- TYPE_PLAYERINFO,
- TYPE_WEAPONINFO,
-};
-
-void Demo_WriteVector(int inType, vec3_t inVector);
-void Demo_WriteByte(int inType, unsigned char inByte);
-void Demo_WriteFloat(int inType, float inFloat);
-void Demo_WriteInt(int inType, int inInt);
-void Demo_WriteBuffer( int type, int size, unsigned char *buffer );
-#define LOAD_DATA(x) LoadData(&x, inBuffer, sizeof(x), theBytesRead);
-#define SAVE_DATA(x) SaveData(theCharArray, &x, sizeof(x), theCounter);
-
-int GetDataSize(const string& inString);
-
-void LoadData(void* inBuffer, const unsigned char* inData, int inSizeToCopy, int& inSizeVariable);
-void LoadStringData(string& outString, const unsigned char* inData, int& inBytesRead);
-void LoadVectorData(float* outData, const unsigned char* inData, int& inBytesRead);
-
-void SaveData(unsigned char* inBuffer, const void* inData, int inSizeToCopy, int& inSizeVariable);
-void SaveStringData(unsigned char* inBuffer, const string& inString, int& inSizeVariable);
-void SaveVectorData(unsigned char* inBuffer, float* inData, int& inSizeVariable);
-
-extern int g_demosniper;
-extern int g_demosniperdamage;
-extern float g_demosniperorg[3];
-extern float g_demosniperangles[3];
-extern float g_demozoom;
-
-extern float gNormMouseX;
-extern float gNormMouseY;
-
-extern int gVisibleMouse;
-extern vec3_t v_angles;
-extern vec3_t v_origin;
-
+#if !defined( DEMOH )
+#define DEMOH
+#pragma once
+
+// Types of demo messages we can write/parse
+enum
+{
+ TYPE_SNIPERDOT = 0,
+ TYPE_ZOOM,
+
+ TYPE_BASESTATE,
+ TYPE_MOUSEVIS,
+ TYPE_MOUSEX,
+ TYPE_MOUSEY,
+ TYPE_VIEWORIGIN,
+ TYPE_VIEWANGLES,
+ TYPE_PARTICLES,
+
+ // More base state that wasn't originally saved (made a separate type for backwards-compatibility)
+ TYPE_BASESTATE2,
+ TYPE_PLAYERINFO,
+ TYPE_WEAPONINFO,
+};
+
+void Demo_WriteVector(int inType, vec3_t inVector);
+void Demo_WriteByte(int inType, unsigned char inByte);
+void Demo_WriteFloat(int inType, float inFloat);
+void Demo_WriteInt(int inType, int inInt);
+void Demo_WriteBuffer( int type, int size, unsigned char *buffer );
+#define LOAD_DATA(x) LoadData(&x, inBuffer, sizeof(x), theBytesRead);
+#define SAVE_DATA(x) SaveData(theCharArray, &x, sizeof(x), theCounter);
+
+int GetDataSize(const string& inString);
+
+void LoadData(void* inBuffer, const unsigned char* inData, int inSizeToCopy, int& inSizeVariable);
+void LoadStringData(string& outString, const unsigned char* inData, int& inBytesRead);
+void LoadVectorData(float* outData, const unsigned char* inData, int& inBytesRead);
+
+void SaveData(unsigned char* inBuffer, const void* inData, int inSizeToCopy, int& inSizeVariable);
+void SaveStringData(unsigned char* inBuffer, const string& inString, int& inSizeVariable);
+void SaveVectorData(unsigned char* inBuffer, float* inData, int& inSizeVariable);
+
+extern int g_demosniper;
+extern int g_demosniperdamage;
+extern float g_demosniperorg[3];
+extern float g_demosniperangles[3];
+extern float g_demozoom;
+
+extern float gNormMouseX;
+extern float gNormMouseY;
+
+extern int gVisibleMouse;
+extern vec3_t v_angles;
+extern vec3_t v_origin;
+
#endif
\ No newline at end of file
diff --git a/main/source/cl_dll/entity.cpp b/main/source/cl_dll/entity.cpp
index d4940a25..d8ecd30f 100644
--- a/main/source/cl_dll/entity.cpp
+++ b/main/source/cl_dll/entity.cpp
@@ -1,1043 +1,1043 @@
-// Client side entity management functions
-
-#include
-
-#include "hud.h"
-#include "cl_util.h"
-#include "common/const.h"
-#include "common/entity_types.h"
-#include "common/studio_event.h" // def. of mstudioevent_t
-#include "common/r_efx.h"
-#include "common/event_api.h"
-#include "pm_shared/pm_defs.h"
-#include "common/pmtrace.h"
-#include "pm_shared/pm_shared.h"
-#include "mod/AvHParticleSystemManager.h"
-#include "mod/AvHSpecials.h"
-
-#include "engine/APIProxy.h"
-#include "Exports.h"
-
-void Game_AddObjects( void );
-
-extern vec3_t v_origin;
-double gClientTimeLastUpdate;
-int g_iAlive = 1;
-
-bool gTempEntClearAllFlag = false;
-
-/*
-========================
-HUD_AddEntity
- Return 0 to filter entity from visible list for rendering
-========================
-*/
-int CL_DLLEXPORT HUD_AddEntity( int type, struct cl_entity_s *ent, const char *modelname )
-{
-// RecClAddEntity(type, ent, modelname);
-
- gHUD.ClientProcessEntity(&ent->curstate);
-
- // Particle entities have a model so they will be forced through this function,
- // but we don't want to draw them.
- int theSpecialState = ent->curstate.iuser3;
- if( (theSpecialState == AVH_USER3_PARTICLE_ON) ||
- (theSpecialState == AVH_USER3_PARTICLE_OFF) ||
- (theSpecialState == AVH_USER3_AUDIO_ON) ||
- (theSpecialState == AVH_USER3_AUDIO_OFF) ||
- (theSpecialState == AVH_USER3_NOBUILD))
- {
- return 0;
- }
-
- switch ( type )
- {
- case ET_NORMAL:
- case ET_PLAYER:
- case ET_BEAM:
- case ET_TEMPENTITY:
- case ET_FRAGMENTED:
- default:
- break;
- }
-
- if ( g_iUser1 == OBS_IN_EYE && ent->index == g_iUser2 )
- {
- // Don't draw the player we are following in eye
- return 0;
- }
-
- return 1;
-
-}
-
-/*
-=========================
-HUD_TxferLocalOverrides
-
-The server sends us our origin with extra precision as part of the clientdata structure, not during the normal
-playerstate update in entity_state_t. In order for these overrides to eventually get to the appropriate playerstate
-structure, we need to copy them into the state structure at this point.
-=========================
-*/
-void CL_DLLEXPORT HUD_TxferLocalOverrides( struct entity_state_s *state, const struct clientdata_s *client )
-{
-// RecClTxferLocalOverrides(state, client);
-
- VectorCopy( client->origin, state->origin );
-
- // Spectator
- state->iuser1 = client->iuser1;
- state->iuser2 = client->iuser2;
- state->iuser3 = client->iuser3;
- state->iuser4 = client->iuser4;
-
- state->fuser1 = client->fuser1;
- state->fuser2 = client->fuser2;
- state->fuser3 = client->fuser3;
- state->fuser4 = client->fuser4;
-
- state->vuser1 = client->vuser1;
- //state->vuser2 = client->vuser2;
- //state->vuser3 = client->vuser3;
- state->vuser4 = client->vuser4;
-}
-
-/*
-=========================
-HUD_ProcessPlayerState
-
-We have received entity_state_t for this player over the network. We need to copy appropriate fields to the
-playerstate structure
-=========================
-*/
-void CL_DLLEXPORT HUD_ProcessPlayerState( struct entity_state_s *dst, const struct entity_state_s *src )
-{
-// RecClProcessPlayerState(dst, src);
-
- // Copy in network data
- VectorCopy( src->origin, dst->origin );
- VectorCopy( src->angles, dst->angles );
-
- VectorCopy( src->velocity, dst->velocity );
-
- dst->frame = src->frame;
- dst->modelindex = src->modelindex;
- dst->skin = src->skin;
- dst->effects = src->effects;
- dst->weaponmodel = src->weaponmodel;
- dst->movetype = src->movetype;
- dst->sequence = src->sequence;
- dst->animtime = src->animtime;
-
- dst->solid = src->solid;
-
- dst->rendermode = src->rendermode;
- dst->renderamt = src->renderamt;
- dst->rendercolor.r = src->rendercolor.r;
- dst->rendercolor.g = src->rendercolor.g;
- dst->rendercolor.b = src->rendercolor.b;
- dst->renderfx = src->renderfx;
-
- dst->framerate = src->framerate;
- dst->body = src->body;
-
- memcpy( &dst->controller[0], &src->controller[0], 4 * sizeof( byte ) );
- memcpy( &dst->blending[0], &src->blending[0], 2 * sizeof( byte ) );
-
- VectorCopy( src->basevelocity, dst->basevelocity );
-
- dst->friction = src->friction;
- dst->gravity = src->gravity;
- dst->gaitsequence = src->gaitsequence;
- dst->spectator = src->spectator;
- dst->usehull = src->usehull;
- dst->playerclass = src->playerclass;
- dst->team = src->team;
- dst->colormap = src->colormap;
-
- // Save off some data so other areas of the Client DLL can get to it
- cl_entity_t *player = gEngfuncs.GetLocalPlayer(); // Get the local player's index
- if ( dst->number == player->index )
- {
- g_iPlayerClass = dst->playerclass;
- g_iTeamNumber = dst->team;
-
- g_iUser1 = src->iuser1;
- g_iUser2 = src->iuser2;
- g_iUser3 = src->iuser3;
-
- }
-
- // AvH
- // Copy special movement mode...is this needed?
- dst->iuser1 = src->iuser1;
- dst->iuser2 = src->iuser2;
- dst->iuser3 = src->iuser3;
- dst->iuser4 = src->iuser4;
-
- dst->fuser1 = src->fuser1;
- dst->fuser2 = src->fuser2;
- dst->fuser3 = src->fuser3;
- dst->fuser4 = src->fuser4;
-
- dst->vuser1 = src->vuser1;
- //dst->vuser2 = src->vuser2;
- //dst->vuser3 = src->vuser3;
- dst->vuser4 = src->vuser4;
-}
-
-/*
-=========================
-HUD_TxferPredictionData
-
-Because we can predict an arbitrary number of frames before the server responds with an update, we need to be able to copy client side prediction data in
- from the state that the server ack'd receiving, which can be anywhere along the predicted frame path ( i.e., we could predict 20 frames into the future and the server ack's
- up through 10 of those frames, so we need to copy persistent client-side only state from the 10th predicted frame to the slot the server
- update is occupying.
-=========================
-*/
-void CL_DLLEXPORT HUD_TxferPredictionData ( struct entity_state_s *ps, const struct entity_state_s *pps, struct clientdata_s *pcd, const struct clientdata_s *ppcd, struct weapon_data_s *wd, const struct weapon_data_s *pwd )
-{
-// RecClTxferPredictionData(ps, pps, pcd, ppcd, wd, pwd);
-
- ps->oldbuttons = pps->oldbuttons;
- ps->flFallVelocity = pps->flFallVelocity;
- ps->iStepLeft = pps->iStepLeft;
- ps->playerclass = pps->playerclass;
-
- pcd->viewmodel = ppcd->viewmodel;
- pcd->m_iId = ppcd->m_iId;
- pcd->ammo_shells = ppcd->ammo_shells;
- pcd->ammo_nails = ppcd->ammo_nails;
- pcd->ammo_cells = ppcd->ammo_cells;
- pcd->ammo_rockets = ppcd->ammo_rockets;
- pcd->m_flNextAttack = ppcd->m_flNextAttack;
- pcd->fov = ppcd->fov;
- pcd->weaponanim = ppcd->weaponanim;
- pcd->tfstate = ppcd->tfstate;
- pcd->maxspeed = ppcd->maxspeed;
-
- pcd->deadflag = ppcd->deadflag;
-
- // Spectating or not dead == get control over view angles.
- g_iAlive = ( ppcd->iuser1 || ( pcd->deadflag == DEAD_NO ) ) ? 1 : 0;
-
- // Spectator
- pcd->iuser1 = ppcd->iuser1;
- pcd->iuser2 = ppcd->iuser2;
- pcd->iuser3 = ppcd->iuser3;
- pcd->iuser4 = ppcd->iuser4;
-
- pcd->fuser1 = ppcd->fuser1;
- pcd->fuser2 = ppcd->fuser2;
- pcd->fuser3 = ppcd->fuser3;
- pcd->fuser4 = ppcd->fuser4;
-
- if( gEngfuncs.IsSpectateOnly() )
- {
- // in specator mode we tell the engine who we want to spectate and how
- // iuser3 is not used for duck prevention (since the spectator can't duck at all)
- pcd->iuser1 = g_iUser1; // observer mode
- pcd->iuser2 = g_iUser2; // first target
- pcd->iuser3 = g_iUser3; // second target
-
- }
-
- VectorCopy( ppcd->vuser1, pcd->vuser1 );
- //VectorCopy( ppcd->vuser2, pcd->vuser2 );
- //VectorCopy( ppcd->vuser3, pcd->vuser3 );
- VectorCopy( ppcd->vuser4, pcd->vuser4 );
-
- memcpy( wd, pwd, 32 * sizeof( weapon_data_t ) );
-}
-
-/*
-//#define TEST_IT
-#if defined( TEST_IT )
-
-cl_entity_t mymodel[9];
-
-void MoveModel( void )
-{
- cl_entity_t *player;
- int i, j;
- int modelindex;
- struct model_s *mod;
-
- // Load it up with some bogus data
- player = gEngfuncs.GetLocalPlayer();
- if ( !player )
- return;
-
- mod = gEngfuncs.CL_LoadModel( "models/sentry3.mdl", &modelindex );
- for ( i = 0; i < 3; i++ )
- {
- for ( j = 0; j < 3; j++ )
- {
- // Don't draw over ourself...
- if ( ( i == 1 ) && ( j == 1 ) )
- continue;
-
- mymodel[ i * 3 + j ] = *player;
-
- mymodel[ i * 3 + j ].player = 0;
-
- mymodel[ i * 3 + j ].model = mod;
- mymodel[ i * 3 + j ].curstate.modelindex = modelindex;
-
- // Move it out a bit
- mymodel[ i * 3 + j ].origin[0] = player->origin[0] + 50 * ( 1 - i );
- mymodel[ i * 3 + j ].origin[1] = player->origin[1] + 50 * ( 1 - j );
-
- gEngfuncs.CL_CreateVisibleEntity( ET_NORMAL, &mymodel[i*3+j] );
- }
- }
-
-}
-
-#endif
-*/
-//#define TRACE_TEST
-#if defined( TRACE_TEST )
-
-extern int hitent;
-
-cl_entity_t hit;
-
-void TraceModel( void )
-{
- cl_entity_t *ent;
-
- if ( hitent <= 0 )
- return;
-
- // Load it up with some bogus data
- ent = gEngfuncs.GetEntityByIndex( hitent );
- if ( !ent )
- return;
-
- hit = *ent;
- //hit.curstate.rendermode = kRenderTransTexture;
- //hit.curstate.renderfx = kRenderFxGlowShell;
- //hit.curstate.renderamt = 100;
-
- hit.origin[2] += 40;
-
- gEngfuncs.CL_CreateVisibleEntity( ET_NORMAL, &hit );
-}
-
-#endif
-
-
-/*
-void ParticleCallback( struct particle_s *particle, float frametime )
-{
- int i;
-
- for ( i = 0; i < 3; i++ )
- {
- particle->org[ i ] += particle->vel[ i ] * frametime;
- }
-}
-
-cvar_t *color = NULL;
-void Particles( void )
-{
- static float lasttime;
- float curtime;
-
- curtime = gEngfuncs.GetClientTime();
-
- if ( ( curtime - lasttime ) < 2.0 )
- return;
-
- if ( !color )
- {
- color = gEngfuncs.pfnRegisterVariable ( "color","255 0 0", 0 );
- }
-
- lasttime = curtime;
-
- // Create a few particles
- particle_t *p;
- int i, j;
-
- for ( i = 0; i < 1000; i++ )
- {
- int r, g, b;
- p = gEngfuncs.pEfxAPI->R_AllocParticle( ParticleCallback );
- if ( !p )
- break;
-
- for ( j = 0; j < 3; j++ )
- {
- p->org[ j ] = v_origin[ j ] + gEngfuncs.pfnRandomFloat( -32.0, 32.0 );;
- p->vel[ j ] = gEngfuncs.pfnRandomFloat( -100.0, 100.0 );
- }
-
- if ( color )
- {
- sscanf( color->string, "%i %i %i", &r, &g, &b );
- }
- else
- {
- r = 192;
- g = 0;
- b = 0;
- }
-
- p->color = gEngfuncs.pEfxAPI->R_LookupColor( r, g, b );
- gEngfuncs.pEfxAPI->R_GetPackedColor( &p->packedColor, p->color );
-
- // p->die is set to current time so all you have to do is add an additional time to it
- p->die += 3.0;
- }
-}
-*/
-
-/*
-void TempEntCallback ( struct tempent_s *ent, float frametime, float currenttime )
-{
- int i;
-
- for ( i = 0; i < 3; i++ )
- {
- ent->entity.curstate.origin[ i ] += ent->entity.baseline.origin[ i ] * frametime;
- }
-}
-
-void TempEnts( void )
-{
- static float lasttime;
- float curtime;
-
- curtime = gEngfuncs.GetClientTime();
-
- if ( ( curtime - lasttime ) < 10.0 )
- return;
-
- lasttime = curtime;
-
- TEMPENTITY *p;
- int i, j;
- struct model_s *mod;
- vec3_t origin;
- int index;
-
- mod = gEngfuncs.CL_LoadModel( "sprites/laserdot.spr", &index );
-
- for ( i = 0; i < 100; i++ )
- {
- for ( j = 0; j < 3; j++ )
- {
- origin[ j ] = v_origin[ j ];
- if ( j != 2 )
- {
- origin[ j ] += 75;
- }
- }
-
- p = gEngfuncs.pEfxAPI->CL_TentEntAllocCustom( (float *)&origin, mod, 0, TempEntCallback );
- if ( !p )
- break;
-
- for ( j = 0; j < 3; j++ )
- {
- p->entity.curstate.origin[ j ] = origin[ j ];
-
- // Store velocity in baseline origin
- p->entity.baseline.origin[ j ] = gEngfuncs.pfnRandomFloat( -100, 100 );
- }
-
- // p->die is set to current time so all you have to do is add an additional time to it
- p->die += 10.0;
- }
-}
-*/
-
-#if defined( BEAM_TEST )
-// Note can't index beam[ 0 ] in Beam callback, so don't use that index
-// Room for 1 beam ( 0 can't be used )
-static cl_entity_t beams[ 2 ];
-
-void BeamEndModel( void )
-{
- cl_entity_t *player, *model;
- int modelindex;
- struct model_s *mod;
-
- // Load it up with some bogus data
- player = gEngfuncs.GetLocalPlayer();
- if ( !player )
- return;
-
- mod = gEngfuncs.CL_LoadModel( "models/sentry3.mdl", &modelindex );
- if ( !mod )
- return;
-
- // Slot 1
- model = &beams[ 1 ];
-
- *model = *player;
- model->player = 0;
- model->model = mod;
- model->curstate.modelindex = modelindex;
-
- // Move it out a bit
- model->origin[0] = player->origin[0] - 100;
- model->origin[1] = player->origin[1];
-
- model->attachment[0] = model->origin;
- model->attachment[1] = model->origin;
- model->attachment[2] = model->origin;
- model->attachment[3] = model->origin;
-
- gEngfuncs.CL_CreateVisibleEntity( ET_NORMAL, model );
-}
-
-void Beams( void )
-{
- static float lasttime;
- float curtime;
- struct model_s *mod;
- int index;
-
- BeamEndModel();
-
- curtime = gEngfuncs.GetClientTime();
- float end[ 3 ];
-
- if ( ( curtime - lasttime ) < 10.0 )
- return;
-
- mod = gEngfuncs.CL_LoadModel( "sprites/laserbeam.spr", &index );
- if ( !mod )
- return;
-
- lasttime = curtime;
-
- end [ 0 ] = v_origin.x + 100;
- end [ 1 ] = v_origin.y + 100;
- end [ 2 ] = v_origin.z;
-
- BEAM *p1;
- p1 = gEngfuncs.pEfxAPI->R_BeamEntPoint( -1, end, index,
- 10.0, 2.0, 0.3, 1.0, 5.0, 0.0, 1.0, 1.0, 1.0, 1.0 );
-}
-#endif
-
-/*
-=========================
-HUD_CreateEntities
-
-Gives us a chance to add additional entities to the render this frame
-=========================
-*/
-void CL_DLLEXPORT HUD_CreateEntities( void )
-{
-// RecClCreateEntities();
-
- // e.g., create a persistent cl_entity_t somewhere.
- // Load an appropriate model into it ( gEngfuncs.CL_LoadModel )
- // Call gEngfuncs.CL_CreateVisibleEntity to add it to the visedicts list
-/*
-#if defined( TEST_IT )
- MoveModel();
-#endif
-*/
-#if defined( TRACE_TEST )
- TraceModel();
-#endif
-
-/*
- Particles();
-*/
-/*
- TempEnts();
-*/
-
-#if defined( BEAM_TEST )
- Beams();
-#endif
-
- // Add in any game specific objects
- Game_AddObjects();
-
- GetClientVoiceMgr()->CreateEntities();
-}
-
-/*
-=========================
-HUD_StudioEvent
-
-The entity's studio model description indicated an event was
-fired during this frame, handle the event by it's tag ( e.g., muzzleflash, sound )
-=========================
-*/
-void CL_DLLEXPORT HUD_StudioEvent( const struct mstudioevent_s *event, const struct cl_entity_s *entity )
-{
-// RecClStudioEvent(event, entity);
-
- switch( event->event )
- {
- case 5001:
- gEngfuncs.pEfxAPI->R_MuzzleFlash( (float *)&entity->attachment[0], atoi( event->options) );
- break;
- case 5011:
- gEngfuncs.pEfxAPI->R_MuzzleFlash( (float *)&entity->attachment[1], atoi( event->options) );
- break;
- case 5021:
- gEngfuncs.pEfxAPI->R_MuzzleFlash( (float *)&entity->attachment[2], atoi( event->options) );
- break;
- case 5031:
- gEngfuncs.pEfxAPI->R_MuzzleFlash( (float *)&entity->attachment[3], atoi( event->options) );
- break;
- case 5002:
- gEngfuncs.pEfxAPI->R_SparkEffect( (float *)&entity->attachment[0], atoi( event->options), -100, 100 );
- break;
- // Client side sound
- case 5004:
- gEngfuncs.pfnPlaySoundByNameAtLocation( (char *)event->options, 1.0, (float *)&entity->attachment[0] );
- break;
-
- // Particles!
- case 7000:
- AvHParticleSystemManager::Instance()->CreateParticleSystem(string(event->options), entity->attachment[0]);
- break;
-
- case 7010:
- AvHParticleSystemManager::Instance()->CreateParticleSystem(string(event->options), entity->attachment[1]);
- break;
-
- case 7020:
- AvHParticleSystemManager::Instance()->CreateParticleSystem(string(event->options), entity->attachment[2]);
- break;
-
- case 7030:
- AvHParticleSystemManager::Instance()->CreateParticleSystem(string(event->options), entity->attachment[3]);
- break;
-
- default:
- break;
- }
-}
-
-/*
-=================
-CL_UpdateTEnts
-
-Simulation and cleanup of temporary entities
-=================
-*/
-void CL_DLLEXPORT HUD_TempEntUpdate (
- double frametime, // Simulation time
- double client_time, // Absolute time on client
- double cl_gravity, // True gravity on client
- TEMPENTITY **ppTempEntFree, // List of freed temporary ents
- TEMPENTITY **ppTempEntActive, // List
- int ( *Callback_AddVisibleEntity )( cl_entity_t *pEntity ),
- void ( *Callback_TempEntPlaySound )( TEMPENTITY *pTemp, float damp ) )
-{
-// RecClTempEntUpdate(frametime, client_time, cl_gravity, ppTempEntFree, ppTempEntActive, Callback_AddVisibleEntity, Callback_TempEntPlaySound);
-
- static int gTempEntFrame = 0;
- int i;
- TEMPENTITY *pTemp, *pnext, *pprev;
- float freq, gravity, gravitySlow, life, fastFreq;
-
- // don't simulate when we're paused
- if(gClientTimeLastUpdate != client_time)
- {
- gClientTimeLastUpdate = client_time;
-
- // Nothing to simulate
- if ( *ppTempEntActive )
- {
- // in order to have tents collide with players, we have to run the player prediction code so
- // that the client has the player list. We run this code once when we detect any COLLIDEALL
- // tent, then set this BOOL to true so the code doesn't get run again if there's more than
- // one COLLIDEALL ent for this update. (often are).
- gEngfuncs.pEventAPI->EV_SetUpPlayerPrediction( false, true );
-
- // Store off the old count
- gEngfuncs.pEventAPI->EV_PushPMStates();
-
- // Now add in all of the players.
- gEngfuncs.pEventAPI->EV_SetSolidPlayers ( -1 );
-
- // !!!BUGBUG -- This needs to be time based
- gTempEntFrame = (gTempEntFrame+1) & 31;
-
- pTemp = *ppTempEntActive;
-
- bool theIsDone = false;
-
- // !!! Don't simulate while paused.... This is sort of a hack, revisit.
- if ( frametime <= 0 )
- {
- while ( pTemp )
- {
- if ( !(pTemp->flags & FTENT_NOMODEL ) )
- {
- Callback_AddVisibleEntity( &pTemp->entity );
- }
- pTemp = pTemp->next;
- }
- //goto finish;
-
- theIsDone = true;
- }
-
- if(!theIsDone)
- {
- pprev = NULL;
- freq = client_time * 0.01;
- fastFreq = client_time * 5.5;
- gravity = -frametime * cl_gravity;
- gravitySlow = gravity * 0.5;
-
- while ( pTemp )
- {
- int active;
-
- active = 1;
-
- life = pTemp->die - client_time;
- pnext = pTemp->next;
- if ( life < 0 )
- {
- if ( pTemp->flags & FTENT_FADEOUT )
- {
- if (pTemp->entity.curstate.rendermode == kRenderNormal)
- pTemp->entity.curstate.rendermode = kRenderTransTexture;
- pTemp->entity.curstate.renderamt = pTemp->entity.baseline.renderamt * ( 1 + life * pTemp->fadeSpeed );
- if ( pTemp->entity.curstate.renderamt <= 0 )
- active = 0;
-
- }
- else
- active = 0;
- }
- if ( !active ) // Kill it
- {
- pTemp->next = *ppTempEntFree;
- *ppTempEntFree = pTemp;
- if ( !pprev ) // Deleting at head of list
- *ppTempEntActive = pnext;
- else
- pprev->next = pnext;
- }
- else
- {
- pprev = pTemp;
-
- VectorCopy( pTemp->entity.origin, pTemp->entity.prevstate.origin );
-
- if ( pTemp->flags & FTENT_SPARKSHOWER )
- {
- // Adjust speed if it's time
- // Scale is next think time
- if ( client_time > pTemp->entity.baseline.scale )
- {
- // Show Sparks
- gEngfuncs.pEfxAPI->R_SparkEffect( pTemp->entity.origin, 8, -200, 200 );
-
- // Reduce life
- pTemp->entity.baseline.framerate -= 0.1;
-
- if ( pTemp->entity.baseline.framerate <= 0.0 )
- {
- pTemp->die = client_time;
- }
- else
- {
- // So it will die no matter what
- pTemp->die = client_time + 0.5;
-
- // Next think
- pTemp->entity.baseline.scale = client_time + 0.1;
- }
- }
- }
- else if ( pTemp->flags & FTENT_PLYRATTACHMENT )
- {
- cl_entity_t *pClient;
-
- pClient = gEngfuncs.GetEntityByIndex( pTemp->clientIndex );
-
- VectorAdd( pClient->origin, pTemp->tentOffset, pTemp->entity.origin );
- }
- else if ( pTemp->flags & FTENT_SINEWAVE )
- {
- pTemp->x += pTemp->entity.baseline.origin[0] * frametime;
- pTemp->y += pTemp->entity.baseline.origin[1] * frametime;
-
- pTemp->entity.origin[0] = pTemp->x + sin( pTemp->entity.baseline.origin[2] + client_time * pTemp->entity.prevstate.frame ) * (10*pTemp->entity.curstate.framerate);
- pTemp->entity.origin[1] = pTemp->y + sin( pTemp->entity.baseline.origin[2] + fastFreq + 0.7 ) * (8*pTemp->entity.curstate.framerate);
- pTemp->entity.origin[2] += pTemp->entity.baseline.origin[2] * frametime;
- }
- else if ( pTemp->flags & FTENT_SPIRAL )
- {
- float s, c;
- s = sin( pTemp->entity.baseline.origin[2] + fastFreq );
- c = cos( pTemp->entity.baseline.origin[2] + fastFreq );
-#pragma warning(push)
-#pragma warning(disable: 311)
- pTemp->entity.origin[0] += pTemp->entity.baseline.origin[0] * frametime + 8 * sin( client_time * 20 + (int)pTemp );
- pTemp->entity.origin[1] += pTemp->entity.baseline.origin[1] * frametime + 4 * sin( client_time * 30 + (int)pTemp );
- pTemp->entity.origin[2] += pTemp->entity.baseline.origin[2] * frametime;
-#pragma warning(pop)
- }
-
- else
- {
- for ( i = 0; i < 3; i++ )
- pTemp->entity.origin[i] += pTemp->entity.baseline.origin[i] * frametime;
- }
-
- if ( pTemp->flags & FTENT_SPRANIMATE )
- {
- pTemp->entity.curstate.frame += frametime * pTemp->entity.curstate.framerate;
- if ( pTemp->entity.curstate.frame >= pTemp->frameMax )
- {
- pTemp->entity.curstate.frame = pTemp->entity.curstate.frame - (int)(pTemp->entity.curstate.frame);
-
- if ( !(pTemp->flags & FTENT_SPRANIMATELOOP) )
- {
- // this animating sprite isn't set to loop, so destroy it.
- pTemp->die = client_time;
- pTemp = pnext;
- continue;
- }
- }
- }
- else if ( pTemp->flags & FTENT_SPRCYCLE )
- {
- pTemp->entity.curstate.frame += frametime * 10;
- if ( pTemp->entity.curstate.frame >= pTemp->frameMax )
- {
- pTemp->entity.curstate.frame = pTemp->entity.curstate.frame - (int)(pTemp->entity.curstate.frame);
- }
- }
- // Experiment
-#if 0
- if ( pTemp->flags & FTENT_SCALE )
- pTemp->entity.curstate.framerate += 20.0 * (frametime / pTemp->entity.curstate.framerate);
-#endif
-
- if ( pTemp->flags & FTENT_ROTATE )
- {
- pTemp->entity.angles[0] += pTemp->entity.baseline.angles[0] * frametime;
- pTemp->entity.angles[1] += pTemp->entity.baseline.angles[1] * frametime;
- pTemp->entity.angles[2] += pTemp->entity.baseline.angles[2] * frametime;
-
- VectorCopy( pTemp->entity.angles, pTemp->entity.latched.prevangles );
- }
-
- if ( pTemp->flags & (FTENT_COLLIDEALL | FTENT_COLLIDEWORLD) )
- {
- vec3_t traceNormal;
- float traceFraction = 1;
-
- if ( pTemp->flags & FTENT_COLLIDEALL )
- {
- pmtrace_t pmtrace;
- physent_t *pe;
-
- gEngfuncs.pEventAPI->EV_SetTraceHull( 2 );
-
- gEngfuncs.pEventAPI->EV_PlayerTrace( pTemp->entity.prevstate.origin, pTemp->entity.origin, PM_STUDIO_BOX, -1, &pmtrace );
-
-
- if ( pmtrace.fraction != 1 )
- {
- pe = gEngfuncs.pEventAPI->EV_GetPhysent( pmtrace.ent );
-
- if ( !pmtrace.ent || ( pe->info != pTemp->clientIndex ) )
- {
- traceFraction = pmtrace.fraction;
- VectorCopy( pmtrace.plane.normal, traceNormal );
-
- if ( pTemp->hitcallback )
- {
- (*pTemp->hitcallback)( pTemp, &pmtrace );
- }
- }
- }
- }
- else if ( pTemp->flags & FTENT_COLLIDEWORLD )
- {
- pmtrace_t pmtrace;
-
- gEngfuncs.pEventAPI->EV_SetTraceHull( 2 );
-
- gEngfuncs.pEventAPI->EV_PlayerTrace( pTemp->entity.prevstate.origin, pTemp->entity.origin, PM_STUDIO_BOX | PM_WORLD_ONLY, -1, &pmtrace );
-
- if ( pmtrace.fraction != 1 )
- {
- traceFraction = pmtrace.fraction;
- VectorCopy( pmtrace.plane.normal, traceNormal );
-
- if ( pTemp->flags & FTENT_SPARKSHOWER )
- {
- // Chop spark speeds a bit more
- //
- VectorScale( pTemp->entity.baseline.origin, 0.6, pTemp->entity.baseline.origin );
-
- if ( Length( pTemp->entity.baseline.origin ) < 10 )
- {
- pTemp->entity.baseline.framerate = 0.0;
- }
- }
-
- if ( pTemp->hitcallback )
- {
- (*pTemp->hitcallback)( pTemp, &pmtrace );
- }
- }
- }
-
- if ( traceFraction != 1 ) // Decent collision now, and damping works
- {
- float proj, damp;
-
- // Place at contact point
- VectorMA( pTemp->entity.prevstate.origin, traceFraction*frametime, pTemp->entity.baseline.origin, pTemp->entity.origin );
- // Damp velocity
- damp = pTemp->bounceFactor;
- if ( pTemp->flags & (FTENT_GRAVITY|FTENT_SLOWGRAVITY) )
- {
- damp *= 0.5;
- if ( traceNormal[2] > 0.9 ) // Hit floor?
- {
- if ( pTemp->entity.baseline.origin[2] <= 0 && pTemp->entity.baseline.origin[2] >= gravity*3 )
- {
- damp = 0; // Stop
- pTemp->flags &= ~(FTENT_ROTATE|FTENT_GRAVITY|FTENT_SLOWGRAVITY|FTENT_COLLIDEWORLD|FTENT_SMOKETRAIL);
- pTemp->entity.angles[0] = 0;
- pTemp->entity.angles[2] = 0;
- }
- }
- }
-
- if (pTemp->hitSound)
- {
- Callback_TempEntPlaySound(pTemp, damp);
- }
-
- if (pTemp->flags & FTENT_COLLIDEKILL)
- {
- // die on impact
- pTemp->flags &= ~FTENT_FADEOUT;
- pTemp->die = client_time;
- }
- else
- {
- // Reflect velocity
- if ( damp != 0 )
- {
- proj = DotProduct( pTemp->entity.baseline.origin, traceNormal );
- VectorMA( pTemp->entity.baseline.origin, -proj*2, traceNormal, pTemp->entity.baseline.origin );
- // Reflect rotation (fake)
-
- pTemp->entity.angles[1] = -pTemp->entity.angles[1];
- }
-
- if ( damp != 1 )
- {
-
- VectorScale( pTemp->entity.baseline.origin, damp, pTemp->entity.baseline.origin );
- VectorScale( pTemp->entity.angles, 0.9, pTemp->entity.angles );
- }
- }
- }
- }
-
-
- if ( (pTemp->flags & FTENT_FLICKER) && gTempEntFrame == pTemp->entity.curstate.effects )
- {
- dlight_t *dl = gEngfuncs.pEfxAPI->CL_AllocDlight (0);
- VectorCopy (pTemp->entity.origin, dl->origin);
- dl->radius = 60;
- dl->color.r = 255;
- dl->color.g = 120;
- dl->color.b = 0;
- dl->die = client_time + 0.01;
- }
-
- if ( pTemp->flags & FTENT_SMOKETRAIL )
- {
- gEngfuncs.pEfxAPI->R_RocketTrail (pTemp->entity.prevstate.origin, pTemp->entity.origin, 1);
- }
-
- if ( pTemp->flags & FTENT_GRAVITY )
- pTemp->entity.baseline.origin[2] += gravity;
- else if ( pTemp->flags & FTENT_SLOWGRAVITY )
- pTemp->entity.baseline.origin[2] += gravitySlow;
-
- if ( pTemp->flags & FTENT_CLIENTCUSTOM )
- {
- if ( pTemp->callback )
- {
- ( *pTemp->callback )( pTemp, frametime, client_time );
- }
- }
-
- // Cull to PVS (not frustum cull, just PVS)
- if ( !(pTemp->flags & FTENT_NOMODEL ) )
- {
- if ( !Callback_AddVisibleEntity( &pTemp->entity ) )
- {
- if ( !(pTemp->flags & FTENT_PERSIST) )
- {
- pTemp->die = client_time; // If we can't draw it this frame, just dump it.
- pTemp->flags &= ~FTENT_FADEOUT; // Don't fade out, just die
- }
- }
- }
- }
- pTemp = pnext;
- }
- }
-
- // Restore state info
- gEngfuncs.pEventAPI->EV_PopPMStates();
- }
- }
-
-//finish:
-// // Restore state info
-// gEngfuncs.pEventAPI->EV_PopPMStates();
-}
-
-/*
-=================
-HUD_GetUserEntity
-
-If you specify negative numbers for beam start and end point entities, then
- the engine will call back into this function requesting a pointer to a cl_entity_t
- object that describes the entity to attach the beam onto.
-
-Indices must start at 1, not zero.
-=================
-*/
-cl_entity_t CL_DLLEXPORT *HUD_GetUserEntity( int index )
-{
-// RecClGetUserEntity(index);
-
-#if defined( BEAM_TEST )
- // None by default, you would return a valic pointer if you create a client side
- // beam and attach it to a client side entity.
- if ( index > 0 && index <= 1 )
- {
- return &beams[ index ];
- }
- else
- {
- return NULL;
- }
-#else
- return NULL;
-#endif
-}
+// Client side entity management functions
+
+#include
+
+#include "hud.h"
+#include "cl_util.h"
+#include "common/const.h"
+#include "common/entity_types.h"
+#include "common/studio_event.h" // def. of mstudioevent_t
+#include "common/r_efx.h"
+#include "common/event_api.h"
+#include "pm_shared/pm_defs.h"
+#include "common/pmtrace.h"
+#include "pm_shared/pm_shared.h"
+#include "mod/AvHParticleSystemManager.h"
+#include "mod/AvHSpecials.h"
+
+#include "engine/APIProxy.h"
+#include "Exports.h"
+
+void Game_AddObjects( void );
+
+extern vec3_t v_origin;
+double gClientTimeLastUpdate;
+int g_iAlive = 1;
+
+bool gTempEntClearAllFlag = false;
+
+/*
+========================
+HUD_AddEntity
+ Return 0 to filter entity from visible list for rendering
+========================
+*/
+int CL_DLLEXPORT HUD_AddEntity( int type, struct cl_entity_s *ent, const char *modelname )
+{
+// RecClAddEntity(type, ent, modelname);
+
+ gHUD.ClientProcessEntity(&ent->curstate);
+
+ // Particle entities have a model so they will be forced through this function,
+ // but we don't want to draw them.
+ int theSpecialState = ent->curstate.iuser3;
+ if( (theSpecialState == AVH_USER3_PARTICLE_ON) ||
+ (theSpecialState == AVH_USER3_PARTICLE_OFF) ||
+ (theSpecialState == AVH_USER3_AUDIO_ON) ||
+ (theSpecialState == AVH_USER3_AUDIO_OFF) ||
+ (theSpecialState == AVH_USER3_NOBUILD))
+ {
+ return 0;
+ }
+
+ switch ( type )
+ {
+ case ET_NORMAL:
+ case ET_PLAYER:
+ case ET_BEAM:
+ case ET_TEMPENTITY:
+ case ET_FRAGMENTED:
+ default:
+ break;
+ }
+
+ if ( g_iUser1 == OBS_IN_EYE && ent->index == g_iUser2 )
+ {
+ // Don't draw the player we are following in eye
+ return 0;
+ }
+
+ return 1;
+
+}
+
+/*
+=========================
+HUD_TxferLocalOverrides
+
+The server sends us our origin with extra precision as part of the clientdata structure, not during the normal
+playerstate update in entity_state_t. In order for these overrides to eventually get to the appropriate playerstate
+structure, we need to copy them into the state structure at this point.
+=========================
+*/
+void CL_DLLEXPORT HUD_TxferLocalOverrides( struct entity_state_s *state, const struct clientdata_s *client )
+{
+// RecClTxferLocalOverrides(state, client);
+
+ VectorCopy( client->origin, state->origin );
+
+ // Spectator
+ state->iuser1 = client->iuser1;
+ state->iuser2 = client->iuser2;
+ state->iuser3 = client->iuser3;
+ state->iuser4 = client->iuser4;
+
+ state->fuser1 = client->fuser1;
+ state->fuser2 = client->fuser2;
+ state->fuser3 = client->fuser3;
+ state->fuser4 = client->fuser4;
+
+ state->vuser1 = client->vuser1;
+ //state->vuser2 = client->vuser2;
+ //state->vuser3 = client->vuser3;
+ state->vuser4 = client->vuser4;
+}
+
+/*
+=========================
+HUD_ProcessPlayerState
+
+We have received entity_state_t for this player over the network. We need to copy appropriate fields to the
+playerstate structure
+=========================
+*/
+void CL_DLLEXPORT HUD_ProcessPlayerState( struct entity_state_s *dst, const struct entity_state_s *src )
+{
+// RecClProcessPlayerState(dst, src);
+
+ // Copy in network data
+ VectorCopy( src->origin, dst->origin );
+ VectorCopy( src->angles, dst->angles );
+
+ VectorCopy( src->velocity, dst->velocity );
+
+ dst->frame = src->frame;
+ dst->modelindex = src->modelindex;
+ dst->skin = src->skin;
+ dst->effects = src->effects;
+ dst->weaponmodel = src->weaponmodel;
+ dst->movetype = src->movetype;
+ dst->sequence = src->sequence;
+ dst->animtime = src->animtime;
+
+ dst->solid = src->solid;
+
+ dst->rendermode = src->rendermode;
+ dst->renderamt = src->renderamt;
+ dst->rendercolor.r = src->rendercolor.r;
+ dst->rendercolor.g = src->rendercolor.g;
+ dst->rendercolor.b = src->rendercolor.b;
+ dst->renderfx = src->renderfx;
+
+ dst->framerate = src->framerate;
+ dst->body = src->body;
+
+ memcpy( &dst->controller[0], &src->controller[0], 4 * sizeof( byte ) );
+ memcpy( &dst->blending[0], &src->blending[0], 2 * sizeof( byte ) );
+
+ VectorCopy( src->basevelocity, dst->basevelocity );
+
+ dst->friction = src->friction;
+ dst->gravity = src->gravity;
+ dst->gaitsequence = src->gaitsequence;
+ dst->spectator = src->spectator;
+ dst->usehull = src->usehull;
+ dst->playerclass = src->playerclass;
+ dst->team = src->team;
+ dst->colormap = src->colormap;
+
+ // Save off some data so other areas of the Client DLL can get to it
+ cl_entity_t *player = gEngfuncs.GetLocalPlayer(); // Get the local player's index
+ if ( dst->number == player->index )
+ {
+ g_iPlayerClass = dst->playerclass;
+ g_iTeamNumber = dst->team;
+
+ g_iUser1 = src->iuser1;
+ g_iUser2 = src->iuser2;
+ g_iUser3 = src->iuser3;
+
+ }
+
+ // AvH
+ // Copy special movement mode...is this needed?
+ dst->iuser1 = src->iuser1;
+ dst->iuser2 = src->iuser2;
+ dst->iuser3 = src->iuser3;
+ dst->iuser4 = src->iuser4;
+
+ dst->fuser1 = src->fuser1;
+ dst->fuser2 = src->fuser2;
+ dst->fuser3 = src->fuser3;
+ dst->fuser4 = src->fuser4;
+
+ dst->vuser1 = src->vuser1;
+ //dst->vuser2 = src->vuser2;
+ //dst->vuser3 = src->vuser3;
+ dst->vuser4 = src->vuser4;
+}
+
+/*
+=========================
+HUD_TxferPredictionData
+
+Because we can predict an arbitrary number of frames before the server responds with an update, we need to be able to copy client side prediction data in
+ from the state that the server ack'd receiving, which can be anywhere along the predicted frame path ( i.e., we could predict 20 frames into the future and the server ack's
+ up through 10 of those frames, so we need to copy persistent client-side only state from the 10th predicted frame to the slot the server
+ update is occupying.
+=========================
+*/
+void CL_DLLEXPORT HUD_TxferPredictionData ( struct entity_state_s *ps, const struct entity_state_s *pps, struct clientdata_s *pcd, const struct clientdata_s *ppcd, struct weapon_data_s *wd, const struct weapon_data_s *pwd )
+{
+// RecClTxferPredictionData(ps, pps, pcd, ppcd, wd, pwd);
+
+ ps->oldbuttons = pps->oldbuttons;
+ ps->flFallVelocity = pps->flFallVelocity;
+ ps->iStepLeft = pps->iStepLeft;
+ ps->playerclass = pps->playerclass;
+
+ pcd->viewmodel = ppcd->viewmodel;
+ pcd->m_iId = ppcd->m_iId;
+ pcd->ammo_shells = ppcd->ammo_shells;
+ pcd->ammo_nails = ppcd->ammo_nails;
+ pcd->ammo_cells = ppcd->ammo_cells;
+ pcd->ammo_rockets = ppcd->ammo_rockets;
+ pcd->m_flNextAttack = ppcd->m_flNextAttack;
+ pcd->fov = ppcd->fov;
+ pcd->weaponanim = ppcd->weaponanim;
+ pcd->tfstate = ppcd->tfstate;
+ pcd->maxspeed = ppcd->maxspeed;
+
+ pcd->deadflag = ppcd->deadflag;
+
+ // Spectating or not dead == get control over view angles.
+ g_iAlive = ( ppcd->iuser1 || ( pcd->deadflag == DEAD_NO ) ) ? 1 : 0;
+
+ // Spectator
+ pcd->iuser1 = ppcd->iuser1;
+ pcd->iuser2 = ppcd->iuser2;
+ pcd->iuser3 = ppcd->iuser3;
+ pcd->iuser4 = ppcd->iuser4;
+
+ pcd->fuser1 = ppcd->fuser1;
+ pcd->fuser2 = ppcd->fuser2;
+ pcd->fuser3 = ppcd->fuser3;
+ pcd->fuser4 = ppcd->fuser4;
+
+ if( gEngfuncs.IsSpectateOnly() )
+ {
+ // in specator mode we tell the engine who we want to spectate and how
+ // iuser3 is not used for duck prevention (since the spectator can't duck at all)
+ pcd->iuser1 = g_iUser1; // observer mode
+ pcd->iuser2 = g_iUser2; // first target
+ pcd->iuser3 = g_iUser3; // second target
+
+ }
+
+ VectorCopy( ppcd->vuser1, pcd->vuser1 );
+ //VectorCopy( ppcd->vuser2, pcd->vuser2 );
+ //VectorCopy( ppcd->vuser3, pcd->vuser3 );
+ VectorCopy( ppcd->vuser4, pcd->vuser4 );
+
+ memcpy( wd, pwd, 32 * sizeof( weapon_data_t ) );
+}
+
+/*
+//#define TEST_IT
+#if defined( TEST_IT )
+
+cl_entity_t mymodel[9];
+
+void MoveModel( void )
+{
+ cl_entity_t *player;
+ int i, j;
+ int modelindex;
+ struct model_s *mod;
+
+ // Load it up with some bogus data
+ player = gEngfuncs.GetLocalPlayer();
+ if ( !player )
+ return;
+
+ mod = gEngfuncs.CL_LoadModel( "models/sentry3.mdl", &modelindex );
+ for ( i = 0; i < 3; i++ )
+ {
+ for ( j = 0; j < 3; j++ )
+ {
+ // Don't draw over ourself...
+ if ( ( i == 1 ) && ( j == 1 ) )
+ continue;
+
+ mymodel[ i * 3 + j ] = *player;
+
+ mymodel[ i * 3 + j ].player = 0;
+
+ mymodel[ i * 3 + j ].model = mod;
+ mymodel[ i * 3 + j ].curstate.modelindex = modelindex;
+
+ // Move it out a bit
+ mymodel[ i * 3 + j ].origin[0] = player->origin[0] + 50 * ( 1 - i );
+ mymodel[ i * 3 + j ].origin[1] = player->origin[1] + 50 * ( 1 - j );
+
+ gEngfuncs.CL_CreateVisibleEntity( ET_NORMAL, &mymodel[i*3+j] );
+ }
+ }
+
+}
+
+#endif
+*/
+//#define TRACE_TEST
+#if defined( TRACE_TEST )
+
+extern int hitent;
+
+cl_entity_t hit;
+
+void TraceModel( void )
+{
+ cl_entity_t *ent;
+
+ if ( hitent <= 0 )
+ return;
+
+ // Load it up with some bogus data
+ ent = gEngfuncs.GetEntityByIndex( hitent );
+ if ( !ent )
+ return;
+
+ hit = *ent;
+ //hit.curstate.rendermode = kRenderTransTexture;
+ //hit.curstate.renderfx = kRenderFxGlowShell;
+ //hit.curstate.renderamt = 100;
+
+ hit.origin[2] += 40;
+
+ gEngfuncs.CL_CreateVisibleEntity( ET_NORMAL, &hit );
+}
+
+#endif
+
+
+/*
+void ParticleCallback( struct particle_s *particle, float frametime )
+{
+ int i;
+
+ for ( i = 0; i < 3; i++ )
+ {
+ particle->org[ i ] += particle->vel[ i ] * frametime;
+ }
+}
+
+cvar_t *color = NULL;
+void Particles( void )
+{
+ static float lasttime;
+ float curtime;
+
+ curtime = gEngfuncs.GetClientTime();
+
+ if ( ( curtime - lasttime ) < 2.0 )
+ return;
+
+ if ( !color )
+ {
+ color = gEngfuncs.pfnRegisterVariable ( "color","255 0 0", 0 );
+ }
+
+ lasttime = curtime;
+
+ // Create a few particles
+ particle_t *p;
+ int i, j;
+
+ for ( i = 0; i < 1000; i++ )
+ {
+ int r, g, b;
+ p = gEngfuncs.pEfxAPI->R_AllocParticle( ParticleCallback );
+ if ( !p )
+ break;
+
+ for ( j = 0; j < 3; j++ )
+ {
+ p->org[ j ] = v_origin[ j ] + gEngfuncs.pfnRandomFloat( -32.0, 32.0 );;
+ p->vel[ j ] = gEngfuncs.pfnRandomFloat( -100.0, 100.0 );
+ }
+
+ if ( color )
+ {
+ sscanf( color->string, "%i %i %i", &r, &g, &b );
+ }
+ else
+ {
+ r = 192;
+ g = 0;
+ b = 0;
+ }
+
+ p->color = gEngfuncs.pEfxAPI->R_LookupColor( r, g, b );
+ gEngfuncs.pEfxAPI->R_GetPackedColor( &p->packedColor, p->color );
+
+ // p->die is set to current time so all you have to do is add an additional time to it
+ p->die += 3.0;
+ }
+}
+*/
+
+/*
+void TempEntCallback ( struct tempent_s *ent, float frametime, float currenttime )
+{
+ int i;
+
+ for ( i = 0; i < 3; i++ )
+ {
+ ent->entity.curstate.origin[ i ] += ent->entity.baseline.origin[ i ] * frametime;
+ }
+}
+
+void TempEnts( void )
+{
+ static float lasttime;
+ float curtime;
+
+ curtime = gEngfuncs.GetClientTime();
+
+ if ( ( curtime - lasttime ) < 10.0 )
+ return;
+
+ lasttime = curtime;
+
+ TEMPENTITY *p;
+ int i, j;
+ struct model_s *mod;
+ vec3_t origin;
+ int index;
+
+ mod = gEngfuncs.CL_LoadModel( "sprites/laserdot.spr", &index );
+
+ for ( i = 0; i < 100; i++ )
+ {
+ for ( j = 0; j < 3; j++ )
+ {
+ origin[ j ] = v_origin[ j ];
+ if ( j != 2 )
+ {
+ origin[ j ] += 75;
+ }
+ }
+
+ p = gEngfuncs.pEfxAPI->CL_TentEntAllocCustom( (float *)&origin, mod, 0, TempEntCallback );
+ if ( !p )
+ break;
+
+ for ( j = 0; j < 3; j++ )
+ {
+ p->entity.curstate.origin[ j ] = origin[ j ];
+
+ // Store velocity in baseline origin
+ p->entity.baseline.origin[ j ] = gEngfuncs.pfnRandomFloat( -100, 100 );
+ }
+
+ // p->die is set to current time so all you have to do is add an additional time to it
+ p->die += 10.0;
+ }
+}
+*/
+
+#if defined( BEAM_TEST )
+// Note can't index beam[ 0 ] in Beam callback, so don't use that index
+// Room for 1 beam ( 0 can't be used )
+static cl_entity_t beams[ 2 ];
+
+void BeamEndModel( void )
+{
+ cl_entity_t *player, *model;
+ int modelindex;
+ struct model_s *mod;
+
+ // Load it up with some bogus data
+ player = gEngfuncs.GetLocalPlayer();
+ if ( !player )
+ return;
+
+ mod = gEngfuncs.CL_LoadModel( "models/sentry3.mdl", &modelindex );
+ if ( !mod )
+ return;
+
+ // Slot 1
+ model = &beams[ 1 ];
+
+ *model = *player;
+ model->player = 0;
+ model->model = mod;
+ model->curstate.modelindex = modelindex;
+
+ // Move it out a bit
+ model->origin[0] = player->origin[0] - 100;
+ model->origin[1] = player->origin[1];
+
+ model->attachment[0] = model->origin;
+ model->attachment[1] = model->origin;
+ model->attachment[2] = model->origin;
+ model->attachment[3] = model->origin;
+
+ gEngfuncs.CL_CreateVisibleEntity( ET_NORMAL, model );
+}
+
+void Beams( void )
+{
+ static float lasttime;
+ float curtime;
+ struct model_s *mod;
+ int index;
+
+ BeamEndModel();
+
+ curtime = gEngfuncs.GetClientTime();
+ float end[ 3 ];
+
+ if ( ( curtime - lasttime ) < 10.0 )
+ return;
+
+ mod = gEngfuncs.CL_LoadModel( "sprites/laserbeam.spr", &index );
+ if ( !mod )
+ return;
+
+ lasttime = curtime;
+
+ end [ 0 ] = v_origin.x + 100;
+ end [ 1 ] = v_origin.y + 100;
+ end [ 2 ] = v_origin.z;
+
+ BEAM *p1;
+ p1 = gEngfuncs.pEfxAPI->R_BeamEntPoint( -1, end, index,
+ 10.0, 2.0, 0.3, 1.0, 5.0, 0.0, 1.0, 1.0, 1.0, 1.0 );
+}
+#endif
+
+/*
+=========================
+HUD_CreateEntities
+
+Gives us a chance to add additional entities to the render this frame
+=========================
+*/
+void CL_DLLEXPORT HUD_CreateEntities( void )
+{
+// RecClCreateEntities();
+
+ // e.g., create a persistent cl_entity_t somewhere.
+ // Load an appropriate model into it ( gEngfuncs.CL_LoadModel )
+ // Call gEngfuncs.CL_CreateVisibleEntity to add it to the visedicts list
+/*
+#if defined( TEST_IT )
+ MoveModel();
+#endif
+*/
+#if defined( TRACE_TEST )
+ TraceModel();
+#endif
+
+/*
+ Particles();
+*/
+/*
+ TempEnts();
+*/
+
+#if defined( BEAM_TEST )
+ Beams();
+#endif
+
+ // Add in any game specific objects
+ Game_AddObjects();
+
+ GetClientVoiceMgr()->CreateEntities();
+}
+
+/*
+=========================
+HUD_StudioEvent
+
+The entity's studio model description indicated an event was
+fired during this frame, handle the event by it's tag ( e.g., muzzleflash, sound )
+=========================
+*/
+void CL_DLLEXPORT HUD_StudioEvent( const struct mstudioevent_s *event, const struct cl_entity_s *entity )
+{
+// RecClStudioEvent(event, entity);
+
+ switch( event->event )
+ {
+ case 5001:
+ gEngfuncs.pEfxAPI->R_MuzzleFlash( (float *)&entity->attachment[0], atoi( event->options) );
+ break;
+ case 5011:
+ gEngfuncs.pEfxAPI->R_MuzzleFlash( (float *)&entity->attachment[1], atoi( event->options) );
+ break;
+ case 5021:
+ gEngfuncs.pEfxAPI->R_MuzzleFlash( (float *)&entity->attachment[2], atoi( event->options) );
+ break;
+ case 5031:
+ gEngfuncs.pEfxAPI->R_MuzzleFlash( (float *)&entity->attachment[3], atoi( event->options) );
+ break;
+ case 5002:
+ gEngfuncs.pEfxAPI->R_SparkEffect( (float *)&entity->attachment[0], atoi( event->options), -100, 100 );
+ break;
+ // Client side sound
+ case 5004:
+ gEngfuncs.pfnPlaySoundByNameAtLocation( (char *)event->options, 1.0, (float *)&entity->attachment[0] );
+ break;
+
+ // Particles!
+ case 7000:
+ AvHParticleSystemManager::Instance()->CreateParticleSystem(string(event->options), entity->attachment[0]);
+ break;
+
+ case 7010:
+ AvHParticleSystemManager::Instance()->CreateParticleSystem(string(event->options), entity->attachment[1]);
+ break;
+
+ case 7020:
+ AvHParticleSystemManager::Instance()->CreateParticleSystem(string(event->options), entity->attachment[2]);
+ break;
+
+ case 7030:
+ AvHParticleSystemManager::Instance()->CreateParticleSystem(string(event->options), entity->attachment[3]);
+ break;
+
+ default:
+ break;
+ }
+}
+
+/*
+=================
+CL_UpdateTEnts
+
+Simulation and cleanup of temporary entities
+=================
+*/
+void CL_DLLEXPORT HUD_TempEntUpdate (
+ double frametime, // Simulation time
+ double client_time, // Absolute time on client
+ double cl_gravity, // True gravity on client
+ TEMPENTITY **ppTempEntFree, // List of freed temporary ents
+ TEMPENTITY **ppTempEntActive, // List
+ int ( *Callback_AddVisibleEntity )( cl_entity_t *pEntity ),
+ void ( *Callback_TempEntPlaySound )( TEMPENTITY *pTemp, float damp ) )
+{
+// RecClTempEntUpdate(frametime, client_time, cl_gravity, ppTempEntFree, ppTempEntActive, Callback_AddVisibleEntity, Callback_TempEntPlaySound);
+
+ static int gTempEntFrame = 0;
+ int i;
+ TEMPENTITY *pTemp, *pnext, *pprev;
+ float freq, gravity, gravitySlow, life, fastFreq;
+
+ // don't simulate when we're paused
+ if(gClientTimeLastUpdate != client_time)
+ {
+ gClientTimeLastUpdate = client_time;
+
+ // Nothing to simulate
+ if ( *ppTempEntActive )
+ {
+ // in order to have tents collide with players, we have to run the player prediction code so
+ // that the client has the player list. We run this code once when we detect any COLLIDEALL
+ // tent, then set this BOOL to true so the code doesn't get run again if there's more than
+ // one COLLIDEALL ent for this update. (often are).
+ gEngfuncs.pEventAPI->EV_SetUpPlayerPrediction( false, true );
+
+ // Store off the old count
+ gEngfuncs.pEventAPI->EV_PushPMStates();
+
+ // Now add in all of the players.
+ gEngfuncs.pEventAPI->EV_SetSolidPlayers ( -1 );
+
+ // !!!BUGBUG -- This needs to be time based
+ gTempEntFrame = (gTempEntFrame+1) & 31;
+
+ pTemp = *ppTempEntActive;
+
+ bool theIsDone = false;
+
+ // !!! Don't simulate while paused.... This is sort of a hack, revisit.
+ if ( frametime <= 0 )
+ {
+ while ( pTemp )
+ {
+ if ( !(pTemp->flags & FTENT_NOMODEL ) )
+ {
+ Callback_AddVisibleEntity( &pTemp->entity );
+ }
+ pTemp = pTemp->next;
+ }
+ //goto finish;
+
+ theIsDone = true;
+ }
+
+ if(!theIsDone)
+ {
+ pprev = NULL;
+ freq = client_time * 0.01;
+ fastFreq = client_time * 5.5;
+ gravity = -frametime * cl_gravity;
+ gravitySlow = gravity * 0.5;
+
+ while ( pTemp )
+ {
+ int active;
+
+ active = 1;
+
+ life = pTemp->die - client_time;
+ pnext = pTemp->next;
+ if ( life < 0 )
+ {
+ if ( pTemp->flags & FTENT_FADEOUT )
+ {
+ if (pTemp->entity.curstate.rendermode == kRenderNormal)
+ pTemp->entity.curstate.rendermode = kRenderTransTexture;
+ pTemp->entity.curstate.renderamt = pTemp->entity.baseline.renderamt * ( 1 + life * pTemp->fadeSpeed );
+ if ( pTemp->entity.curstate.renderamt <= 0 )
+ active = 0;
+
+ }
+ else
+ active = 0;
+ }
+ if ( !active ) // Kill it
+ {
+ pTemp->next = *ppTempEntFree;
+ *ppTempEntFree = pTemp;
+ if ( !pprev ) // Deleting at head of list
+ *ppTempEntActive = pnext;
+ else
+ pprev->next = pnext;
+ }
+ else
+ {
+ pprev = pTemp;
+
+ VectorCopy( pTemp->entity.origin, pTemp->entity.prevstate.origin );
+
+ if ( pTemp->flags & FTENT_SPARKSHOWER )
+ {
+ // Adjust speed if it's time
+ // Scale is next think time
+ if ( client_time > pTemp->entity.baseline.scale )
+ {
+ // Show Sparks
+ gEngfuncs.pEfxAPI->R_SparkEffect( pTemp->entity.origin, 8, -200, 200 );
+
+ // Reduce life
+ pTemp->entity.baseline.framerate -= 0.1;
+
+ if ( pTemp->entity.baseline.framerate <= 0.0 )
+ {
+ pTemp->die = client_time;
+ }
+ else
+ {
+ // So it will die no matter what
+ pTemp->die = client_time + 0.5;
+
+ // Next think
+ pTemp->entity.baseline.scale = client_time + 0.1;
+ }
+ }
+ }
+ else if ( pTemp->flags & FTENT_PLYRATTACHMENT )
+ {
+ cl_entity_t *pClient;
+
+ pClient = gEngfuncs.GetEntityByIndex( pTemp->clientIndex );
+
+ VectorAdd( pClient->origin, pTemp->tentOffset, pTemp->entity.origin );
+ }
+ else if ( pTemp->flags & FTENT_SINEWAVE )
+ {
+ pTemp->x += pTemp->entity.baseline.origin[0] * frametime;
+ pTemp->y += pTemp->entity.baseline.origin[1] * frametime;
+
+ pTemp->entity.origin[0] = pTemp->x + sin( pTemp->entity.baseline.origin[2] + client_time * pTemp->entity.prevstate.frame ) * (10*pTemp->entity.curstate.framerate);
+ pTemp->entity.origin[1] = pTemp->y + sin( pTemp->entity.baseline.origin[2] + fastFreq + 0.7 ) * (8*pTemp->entity.curstate.framerate);
+ pTemp->entity.origin[2] += pTemp->entity.baseline.origin[2] * frametime;
+ }
+ else if ( pTemp->flags & FTENT_SPIRAL )
+ {
+ float s, c;
+ s = sin( pTemp->entity.baseline.origin[2] + fastFreq );
+ c = cos( pTemp->entity.baseline.origin[2] + fastFreq );
+#pragma warning(push)
+#pragma warning(disable: 311)
+ pTemp->entity.origin[0] += pTemp->entity.baseline.origin[0] * frametime + 8 * sin( client_time * 20 + (int)pTemp );
+ pTemp->entity.origin[1] += pTemp->entity.baseline.origin[1] * frametime + 4 * sin( client_time * 30 + (int)pTemp );
+ pTemp->entity.origin[2] += pTemp->entity.baseline.origin[2] * frametime;
+#pragma warning(pop)
+ }
+
+ else
+ {
+ for ( i = 0; i < 3; i++ )
+ pTemp->entity.origin[i] += pTemp->entity.baseline.origin[i] * frametime;
+ }
+
+ if ( pTemp->flags & FTENT_SPRANIMATE )
+ {
+ pTemp->entity.curstate.frame += frametime * pTemp->entity.curstate.framerate;
+ if ( pTemp->entity.curstate.frame >= pTemp->frameMax )
+ {
+ pTemp->entity.curstate.frame = pTemp->entity.curstate.frame - (int)(pTemp->entity.curstate.frame);
+
+ if ( !(pTemp->flags & FTENT_SPRANIMATELOOP) )
+ {
+ // this animating sprite isn't set to loop, so destroy it.
+ pTemp->die = client_time;
+ pTemp = pnext;
+ continue;
+ }
+ }
+ }
+ else if ( pTemp->flags & FTENT_SPRCYCLE )
+ {
+ pTemp->entity.curstate.frame += frametime * 10;
+ if ( pTemp->entity.curstate.frame >= pTemp->frameMax )
+ {
+ pTemp->entity.curstate.frame = pTemp->entity.curstate.frame - (int)(pTemp->entity.curstate.frame);
+ }
+ }
+ // Experiment
+#if 0
+ if ( pTemp->flags & FTENT_SCALE )
+ pTemp->entity.curstate.framerate += 20.0 * (frametime / pTemp->entity.curstate.framerate);
+#endif
+
+ if ( pTemp->flags & FTENT_ROTATE )
+ {
+ pTemp->entity.angles[0] += pTemp->entity.baseline.angles[0] * frametime;
+ pTemp->entity.angles[1] += pTemp->entity.baseline.angles[1] * frametime;
+ pTemp->entity.angles[2] += pTemp->entity.baseline.angles[2] * frametime;
+
+ VectorCopy( pTemp->entity.angles, pTemp->entity.latched.prevangles );
+ }
+
+ if ( pTemp->flags & (FTENT_COLLIDEALL | FTENT_COLLIDEWORLD) )
+ {
+ vec3_t traceNormal;
+ float traceFraction = 1;
+
+ if ( pTemp->flags & FTENT_COLLIDEALL )
+ {
+ pmtrace_t pmtrace;
+ physent_t *pe;
+
+ gEngfuncs.pEventAPI->EV_SetTraceHull( 2 );
+
+ gEngfuncs.pEventAPI->EV_PlayerTrace( pTemp->entity.prevstate.origin, pTemp->entity.origin, PM_STUDIO_BOX, -1, &pmtrace );
+
+
+ if ( pmtrace.fraction != 1 )
+ {
+ pe = gEngfuncs.pEventAPI->EV_GetPhysent( pmtrace.ent );
+
+ if ( !pmtrace.ent || ( pe->info != pTemp->clientIndex ) )
+ {
+ traceFraction = pmtrace.fraction;
+ VectorCopy( pmtrace.plane.normal, traceNormal );
+
+ if ( pTemp->hitcallback )
+ {
+ (*pTemp->hitcallback)( pTemp, &pmtrace );
+ }
+ }
+ }
+ }
+ else if ( pTemp->flags & FTENT_COLLIDEWORLD )
+ {
+ pmtrace_t pmtrace;
+
+ gEngfuncs.pEventAPI->EV_SetTraceHull( 2 );
+
+ gEngfuncs.pEventAPI->EV_PlayerTrace( pTemp->entity.prevstate.origin, pTemp->entity.origin, PM_STUDIO_BOX | PM_WORLD_ONLY, -1, &pmtrace );
+
+ if ( pmtrace.fraction != 1 )
+ {
+ traceFraction = pmtrace.fraction;
+ VectorCopy( pmtrace.plane.normal, traceNormal );
+
+ if ( pTemp->flags & FTENT_SPARKSHOWER )
+ {
+ // Chop spark speeds a bit more
+ //
+ VectorScale( pTemp->entity.baseline.origin, 0.6, pTemp->entity.baseline.origin );
+
+ if ( Length( pTemp->entity.baseline.origin ) < 10 )
+ {
+ pTemp->entity.baseline.framerate = 0.0;
+ }
+ }
+
+ if ( pTemp->hitcallback )
+ {
+ (*pTemp->hitcallback)( pTemp, &pmtrace );
+ }
+ }
+ }
+
+ if ( traceFraction != 1 ) // Decent collision now, and damping works
+ {
+ float proj, damp;
+
+ // Place at contact point
+ VectorMA( pTemp->entity.prevstate.origin, traceFraction*frametime, pTemp->entity.baseline.origin, pTemp->entity.origin );
+ // Damp velocity
+ damp = pTemp->bounceFactor;
+ if ( pTemp->flags & (FTENT_GRAVITY|FTENT_SLOWGRAVITY) )
+ {
+ damp *= 0.5;
+ if ( traceNormal[2] > 0.9 ) // Hit floor?
+ {
+ if ( pTemp->entity.baseline.origin[2] <= 0 && pTemp->entity.baseline.origin[2] >= gravity*3 )
+ {
+ damp = 0; // Stop
+ pTemp->flags &= ~(FTENT_ROTATE|FTENT_GRAVITY|FTENT_SLOWGRAVITY|FTENT_COLLIDEWORLD|FTENT_SMOKETRAIL);
+ pTemp->entity.angles[0] = 0;
+ pTemp->entity.angles[2] = 0;
+ }
+ }
+ }
+
+ if (pTemp->hitSound)
+ {
+ Callback_TempEntPlaySound(pTemp, damp);
+ }
+
+ if (pTemp->flags & FTENT_COLLIDEKILL)
+ {
+ // die on impact
+ pTemp->flags &= ~FTENT_FADEOUT;
+ pTemp->die = client_time;
+ }
+ else
+ {
+ // Reflect velocity
+ if ( damp != 0 )
+ {
+ proj = DotProduct( pTemp->entity.baseline.origin, traceNormal );
+ VectorMA( pTemp->entity.baseline.origin, -proj*2, traceNormal, pTemp->entity.baseline.origin );
+ // Reflect rotation (fake)
+
+ pTemp->entity.angles[1] = -pTemp->entity.angles[1];
+ }
+
+ if ( damp != 1 )
+ {
+
+ VectorScale( pTemp->entity.baseline.origin, damp, pTemp->entity.baseline.origin );
+ VectorScale( pTemp->entity.angles, 0.9, pTemp->entity.angles );
+ }
+ }
+ }
+ }
+
+
+ if ( (pTemp->flags & FTENT_FLICKER) && gTempEntFrame == pTemp->entity.curstate.effects )
+ {
+ dlight_t *dl = gEngfuncs.pEfxAPI->CL_AllocDlight (0);
+ VectorCopy (pTemp->entity.origin, dl->origin);
+ dl->radius = 60;
+ dl->color.r = 255;
+ dl->color.g = 120;
+ dl->color.b = 0;
+ dl->die = client_time + 0.01;
+ }
+
+ if ( pTemp->flags & FTENT_SMOKETRAIL )
+ {
+ gEngfuncs.pEfxAPI->R_RocketTrail (pTemp->entity.prevstate.origin, pTemp->entity.origin, 1);
+ }
+
+ if ( pTemp->flags & FTENT_GRAVITY )
+ pTemp->entity.baseline.origin[2] += gravity;
+ else if ( pTemp->flags & FTENT_SLOWGRAVITY )
+ pTemp->entity.baseline.origin[2] += gravitySlow;
+
+ if ( pTemp->flags & FTENT_CLIENTCUSTOM )
+ {
+ if ( pTemp->callback )
+ {
+ ( *pTemp->callback )( pTemp, frametime, client_time );
+ }
+ }
+
+ // Cull to PVS (not frustum cull, just PVS)
+ if ( !(pTemp->flags & FTENT_NOMODEL ) )
+ {
+ if ( !Callback_AddVisibleEntity( &pTemp->entity ) )
+ {
+ if ( !(pTemp->flags & FTENT_PERSIST) )
+ {
+ pTemp->die = client_time; // If we can't draw it this frame, just dump it.
+ pTemp->flags &= ~FTENT_FADEOUT; // Don't fade out, just die
+ }
+ }
+ }
+ }
+ pTemp = pnext;
+ }
+ }
+
+ // Restore state info
+ gEngfuncs.pEventAPI->EV_PopPMStates();
+ }
+ }
+
+//finish:
+// // Restore state info
+// gEngfuncs.pEventAPI->EV_PopPMStates();
+}
+
+/*
+=================
+HUD_GetUserEntity
+
+If you specify negative numbers for beam start and end point entities, then
+ the engine will call back into this function requesting a pointer to a cl_entity_t
+ object that describes the entity to attach the beam onto.
+
+Indices must start at 1, not zero.
+=================
+*/
+cl_entity_t CL_DLLEXPORT *HUD_GetUserEntity( int index )
+{
+// RecClGetUserEntity(index);
+
+#if defined( BEAM_TEST )
+ // None by default, you would return a valic pointer if you create a client side
+ // beam and attach it to a client side entity.
+ if ( index > 0 && index <= 1 )
+ {
+ return &beams[ index ];
+ }
+ else
+ {
+ return NULL;
+ }
+#else
+ return NULL;
+#endif
+}
diff --git a/main/source/cl_dll/ev_common.cpp b/main/source/cl_dll/ev_common.cpp
index 5c441364..fe96a28c 100644
--- a/main/source/cl_dll/ev_common.cpp
+++ b/main/source/cl_dll/ev_common.cpp
@@ -1,225 +1,225 @@
-/***
-*
-* Copyright (c) 1999, Valve LLC. All rights reserved.
-*
-* This product contains software technology licensed from Id
-* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
-* All Rights Reserved.
-*
-* Use, distribution, and modification of this source code and/or resulting
-* object code is restricted to non-commercial enhancements to products from
-* Valve LLC. All other use, distribution, or modification is prohibited
-* without written permission from Valve LLC.
-*
-****/
-// shared event functions
-#include "hud.h"
-#include "cl_util.h"
-#include "common/const.h"
-#include "common/entity_state.h"
-#include "common/cl_entity.h"
-
-#include "common/r_efx.h"
-
-#include "eventscripts.h"
-#include "common/event_api.h"
-#include "pm_shared/pm_shared.h"
-
-#define IS_FIRSTPERSON_SPEC ( g_iUser1 == OBS_IN_EYE)
-/*
-=================
-GetEntity
-
-Return's the requested cl_entity_t
-=================
-*/
-struct cl_entity_s *GetEntity( int idx )
-{
- return gEngfuncs.GetEntityByIndex( idx );
-}
-
-/*
-=================
-GetViewEntity
-
-Return's the current weapon/view model
-=================
-*/
-struct cl_entity_s *GetViewEntity( void )
-{
- return gEngfuncs.GetViewModel();
-}
-
-physent_t* GetPhysEntity(int inPhysIndex)
-{
- return gEngfuncs.pEventAPI->EV_GetPhysent( inPhysIndex );
-}
-
-void DoCenterPrint(char* inString)
-{
- CenterPrint(inString);
-}
-
-
-/*
-=================
-EV_CreateTracer
-
-Creates a tracer effect
-=================
-*/
-void EV_CreateTracer( float *start, float *end )
-{
- gEngfuncs.pEfxAPI->R_TracerEffect( start, end );
-}
-
-/*
-=================
-EV_IsPlayer
-
-Is the entity's index in the player range?
-=================
-*/
-qboolean EV_IsPlayer( int idx )
-{
- if ( idx >= 1 && idx <= gEngfuncs.GetMaxClients() )
- return true;
-
- return false;
-}
-
-/*
-=================
-EV_IsLocal
-
-Is the entity == the local player
-=================
-*/
-qboolean EV_IsLocal( int idx )
-{
- // check if we are in some way in first person spec mode
- if ( IS_FIRSTPERSON_SPEC )
- return (g_iUser2 == idx);
- else
- return gEngfuncs.pEventAPI->EV_IsLocal( idx - 1 ) ? true : false;
-}
-
-qboolean EV_IsSpec( int idx )
-{
- // check if we are in some way in first person spec mode
- if ( IS_FIRSTPERSON_SPEC )
- return (g_iUser2 == idx);
- else
- return false;
-}
-
-/*
-=================
-EV_GetGunPosition
-
-Figure out the height of the gun
-=================
-*/
-void EV_GetGunPosition( event_args_t *args, float *pos, float *origin )
-{
- int idx;
- vec3_t view_ofs;
-
- idx = args->entindex;
-
- VectorClear( view_ofs );
- view_ofs[2] = DEFAULT_VIEWHEIGHT;
-
- if ( EV_IsPlayer( idx ) )
- {
- // in spec mode use entity viewheigh, not own
- if ( EV_IsLocal( idx ) && !IS_FIRSTPERSON_SPEC )
- {
- // Grab predicted result for local player
- gEngfuncs.pEventAPI->EV_LocalPlayerViewheight( view_ofs );
- }
- else if ( args->ducking == 1 )
- {
- view_ofs[2] = VEC_DUCK_VIEW;
- }
- }
-
- VectorAdd( origin, view_ofs, pos );
-}
-
-/*
-=================
-EV_EjectBrass
-
-Bullet shell casings
-=================
-*/
-void EV_EjectBrass( float *origin, float *velocity, float rotation, int model, int soundtype )
-{
- vec3_t endpos;
- VectorClear( endpos );
- endpos[1] = rotation;
- gEngfuncs.pEfxAPI->R_TempModel( origin, velocity, endpos, 2.5, model, soundtype );
-}
-
-/*
-=================
-EV_GetDefaultShellInfo
-
-Determine where to eject shells from
-=================
-*/
-void EV_GetDefaultShellInfo( event_args_t *args, float *origin, float *velocity, float *ShellVelocity, float *ShellOrigin, float *forward, float *right, float *up, float forwardScale, float upScale, float rightScale )
-{
- int i;
- vec3_t view_ofs;
- float fR, fU;
-
- int idx;
-
- idx = args->entindex;
-
- VectorClear( view_ofs );
- view_ofs[2] = DEFAULT_VIEWHEIGHT;
-
- if ( EV_IsPlayer( idx ) )
- {
- if ( EV_IsLocal( idx ) )
- {
- gEngfuncs.pEventAPI->EV_LocalPlayerViewheight( view_ofs );
- }
- else if ( args->ducking == 1 )
- {
- view_ofs[2] = VEC_DUCK_VIEW;
- }
- }
-
- fR = gEngfuncs.pfnRandomFloat( 50, 70 );
- fU = gEngfuncs.pfnRandomFloat( 100, 150 );
-
- for ( i = 0; i < 3; i++ )
- {
- ShellVelocity[i] = velocity[i] + right[i] * fR + up[i] * fU + forward[i] * 25;
- ShellOrigin[i] = origin[i] + view_ofs[i] + up[i] * upScale + forward[i] * forwardScale + right[i] * rightScale;
- }
-}
-
-/*
-=================
-EV_MuzzleFlash
-
-Flag weapon/view model for muzzle flash
-=================
-*/
-void EV_MuzzleFlash( void )
-{
- // Add muzzle flash to current weapon model
- cl_entity_t *ent = GetViewEntity();
- if ( !ent )
- {
- return;
- }
-
- // Or in the muzzle flash
- ent->curstate.effects |= EF_MUZZLEFLASH;
+/***
+*
+* Copyright (c) 1999, Valve LLC. All rights reserved.
+*
+* This product contains software technology licensed from Id
+* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
+* All Rights Reserved.
+*
+* Use, distribution, and modification of this source code and/or resulting
+* object code is restricted to non-commercial enhancements to products from
+* Valve LLC. All other use, distribution, or modification is prohibited
+* without written permission from Valve LLC.
+*
+****/
+// shared event functions
+#include "hud.h"
+#include "cl_util.h"
+#include "common/const.h"
+#include "common/entity_state.h"
+#include "common/cl_entity.h"
+
+#include "common/r_efx.h"
+
+#include "eventscripts.h"
+#include "common/event_api.h"
+#include "pm_shared/pm_shared.h"
+
+#define IS_FIRSTPERSON_SPEC ( g_iUser1 == OBS_IN_EYE)
+/*
+=================
+GetEntity
+
+Return's the requested cl_entity_t
+=================
+*/
+struct cl_entity_s *GetEntity( int idx )
+{
+ return gEngfuncs.GetEntityByIndex( idx );
+}
+
+/*
+=================
+GetViewEntity
+
+Return's the current weapon/view model
+=================
+*/
+struct cl_entity_s *GetViewEntity( void )
+{
+ return gEngfuncs.GetViewModel();
+}
+
+physent_t* GetPhysEntity(int inPhysIndex)
+{
+ return gEngfuncs.pEventAPI->EV_GetPhysent( inPhysIndex );
+}
+
+void DoCenterPrint(char* inString)
+{
+ CenterPrint(inString);
+}
+
+
+/*
+=================
+EV_CreateTracer
+
+Creates a tracer effect
+=================
+*/
+void EV_CreateTracer( float *start, float *end )
+{
+ gEngfuncs.pEfxAPI->R_TracerEffect( start, end );
+}
+
+/*
+=================
+EV_IsPlayer
+
+Is the entity's index in the player range?
+=================
+*/
+qboolean EV_IsPlayer( int idx )
+{
+ if ( idx >= 1 && idx <= gEngfuncs.GetMaxClients() )
+ return true;
+
+ return false;
+}
+
+/*
+=================
+EV_IsLocal
+
+Is the entity == the local player
+=================
+*/
+qboolean EV_IsLocal( int idx )
+{
+ // check if we are in some way in first person spec mode
+ if ( IS_FIRSTPERSON_SPEC )
+ return (g_iUser2 == idx);
+ else
+ return gEngfuncs.pEventAPI->EV_IsLocal( idx - 1 ) ? true : false;
+}
+
+qboolean EV_IsSpec( int idx )
+{
+ // check if we are in some way in first person spec mode
+ if ( IS_FIRSTPERSON_SPEC )
+ return (g_iUser2 == idx);
+ else
+ return false;
+}
+
+/*
+=================
+EV_GetGunPosition
+
+Figure out the height of the gun
+=================
+*/
+void EV_GetGunPosition( event_args_t *args, float *pos, float *origin )
+{
+ int idx;
+ vec3_t view_ofs;
+
+ idx = args->entindex;
+
+ VectorClear( view_ofs );
+ view_ofs[2] = DEFAULT_VIEWHEIGHT;
+
+ if ( EV_IsPlayer( idx ) )
+ {
+ // in spec mode use entity viewheigh, not own
+ if ( EV_IsLocal( idx ) && !IS_FIRSTPERSON_SPEC )
+ {
+ // Grab predicted result for local player
+ gEngfuncs.pEventAPI->EV_LocalPlayerViewheight( view_ofs );
+ }
+ else if ( args->ducking == 1 )
+ {
+ view_ofs[2] = VEC_DUCK_VIEW;
+ }
+ }
+
+ VectorAdd( origin, view_ofs, pos );
+}
+
+/*
+=================
+EV_EjectBrass
+
+Bullet shell casings
+=================
+*/
+void EV_EjectBrass( float *origin, float *velocity, float rotation, int model, int soundtype )
+{
+ vec3_t endpos;
+ VectorClear( endpos );
+ endpos[1] = rotation;
+ gEngfuncs.pEfxAPI->R_TempModel( origin, velocity, endpos, 2.5, model, soundtype );
+}
+
+/*
+=================
+EV_GetDefaultShellInfo
+
+Determine where to eject shells from
+=================
+*/
+void EV_GetDefaultShellInfo( event_args_t *args, float *origin, float *velocity, float *ShellVelocity, float *ShellOrigin, float *forward, float *right, float *up, float forwardScale, float upScale, float rightScale )
+{
+ int i;
+ vec3_t view_ofs;
+ float fR, fU;
+
+ int idx;
+
+ idx = args->entindex;
+
+ VectorClear( view_ofs );
+ view_ofs[2] = DEFAULT_VIEWHEIGHT;
+
+ if ( EV_IsPlayer( idx ) )
+ {
+ if ( EV_IsLocal( idx ) )
+ {
+ gEngfuncs.pEventAPI->EV_LocalPlayerViewheight( view_ofs );
+ }
+ else if ( args->ducking == 1 )
+ {
+ view_ofs[2] = VEC_DUCK_VIEW;
+ }
+ }
+
+ fR = gEngfuncs.pfnRandomFloat( 50, 70 );
+ fU = gEngfuncs.pfnRandomFloat( 100, 150 );
+
+ for ( i = 0; i < 3; i++ )
+ {
+ ShellVelocity[i] = velocity[i] + right[i] * fR + up[i] * fU + forward[i] * 25;
+ ShellOrigin[i] = origin[i] + view_ofs[i] + up[i] * upScale + forward[i] * forwardScale + right[i] * rightScale;
+ }
+}
+
+/*
+=================
+EV_MuzzleFlash
+
+Flag weapon/view model for muzzle flash
+=================
+*/
+void EV_MuzzleFlash( void )
+{
+ // Add muzzle flash to current weapon model
+ cl_entity_t *ent = GetViewEntity();
+ if ( !ent )
+ {
+ return;
+ }
+
+ // Or in the muzzle flash
+ ent->curstate.effects |= EF_MUZZLEFLASH;
}
\ No newline at end of file
diff --git a/main/source/cl_dll/ev_hldm.cpp b/main/source/cl_dll/ev_hldm.cpp
index dae39ff6..a53f931a 100644
--- a/main/source/cl_dll/ev_hldm.cpp
+++ b/main/source/cl_dll/ev_hldm.cpp
@@ -1,1971 +1,1971 @@
-/***
-*
-* Copyright (c) 1999, Valve LLC. All rights reserved.
-*
-* This product contains software technology licensed from Id
-* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
-* All Rights Reserved.
-*
-* Use, distribution, and modification of this source code and/or resulting
-* object code is restricted to non-commercial enhancements to products from
-* Valve LLC. All other use, distribution, or modification is prohibited
-* without written permission from Valve LLC.
-*
-****/
-//#include "hud.h"
-#include "mod/AvHHud.h"
-#include "cl_util.h"
-#include "common/const.h"
-#include "common/entity_state.h"
-#include "common/cl_entity.h"
-#include "common/entity_types.h"
-#include "common/usercmd.h"
-#include "pm_shared/pm_defs.h"
-#include "pm_shared/pm_materials.h"
-
-#include "eventscripts.h"
-#include "ev_hldm.h"
-
-#include "common/r_efx.h"
-#include "common/event_api.h"
-#include "common/event_args.h"
-#include "in_defs.h"
-#include "mod/AvHBasePlayerWeaponConstants.h"
-#include "mod/AvHMarineWeaponConstants.h"
-#include "mod/AvHAlienWeaponConstants.h"
-#include
-
-static int tracerCount[ 32 ];
-extern AvHHud gHUD;
-
-#include "r_studioint.h"
-#include "common/com_model.h"
-
-extern engine_studio_api_t IEngineStudio;
-
-//extern "C" char PM_FindTextureType( char *name );
-char PM_FindTextureType( char *name );
-
-void V_PunchAxis( int axis, float punch );
-void VectorAngles( const float *forward, float *angles );
-Vector UTIL_GetRandomSpreadDir(unsigned int inSeed, int inShotNumber, const Vector& inBaseDirection, const Vector& inRight, const Vector& inUp, const Vector& inSpread);
-
-extern "C"
-{
-
-// HLDM
-void EV_FireGlock1( struct event_args_s *args );
-void EV_FireGlock2( struct event_args_s *args );
-void EV_FireShotGunSingle( struct event_args_s *args );
-void EV_FireShotGunDouble( struct event_args_s *args );
-void EV_FireMP5( struct event_args_s *args );
-void EV_FireMP52( struct event_args_s *args );
-void EV_FirePython( struct event_args_s *args );
-void EV_FireGauss( struct event_args_s *args );
-void EV_SpinGauss( struct event_args_s *args );
-void EV_Crowbar( struct event_args_s *args );
-void EV_FireCrossbow( struct event_args_s *args );
-void EV_FireCrossbow2( struct event_args_s *args );
-void EV_FireRpg( struct event_args_s *args );
-void EV_EgonFire( struct event_args_s *args );
-void EV_EgonStop( struct event_args_s *args );
-void EV_HornetGunFire( struct event_args_s *args );
-void EV_TripmineFire( struct event_args_s *args );
-void EV_SnarkFire( struct event_args_s *args );
-
-
-void EV_TrainPitchAdjust( struct event_args_s *args );
-}
-
-#define VECTOR_CONE_1DEGREES Vector( 0.00873, 0.00873, 0.00873 )
-#define VECTOR_CONE_2DEGREES Vector( 0.01745, 0.01745, 0.01745 )
-#define VECTOR_CONE_3DEGREES Vector( 0.02618, 0.02618, 0.02618 )
-#define VECTOR_CONE_4DEGREES Vector( 0.03490, 0.03490, 0.03490 )
-#define VECTOR_CONE_5DEGREES Vector( 0.04362, 0.04362, 0.04362 )
-#define VECTOR_CONE_6DEGREES Vector( 0.05234, 0.05234, 0.05234 )
-#define VECTOR_CONE_7DEGREES Vector( 0.06105, 0.06105, 0.06105 )
-#define VECTOR_CONE_8DEGREES Vector( 0.06976, 0.06976, 0.06976 )
-#define VECTOR_CONE_9DEGREES Vector( 0.07846, 0.07846, 0.07846 )
-#define VECTOR_CONE_10DEGREES Vector( 0.08716, 0.08716, 0.08716 )
-#define VECTOR_CONE_15DEGREES Vector( 0.13053, 0.13053, 0.13053 )
-#define VECTOR_CONE_20DEGREES Vector( 0.17365, 0.17365, 0.17365 )
-
-// play a strike sound based on the texture that was hit by the attack traceline. VecSrc/VecEnd are the
-// original traceline endpoints used by the attacker, iBulletType is the type of bullet that hit the texture.
-// returns volume of strike instrument (crowbar) to play
-float EV_HLDM_PlayTextureSound( int idx, pmtrace_t *ptr, float *vecSrc, float *vecEnd, int iBulletType, int inSoundProbability)
-{
- // hit the world, try to play sound based on texture material type
- char chTextureType = CHAR_TEX_CONCRETE;
- float fvol;
- float fvolbar = 0.0f;
- char *rgsz[4];
- int cnt;
- float fattn = ATTN_NORM;
- int entity;
- char *pTextureName;
- char texname[ 64 ];
- char szbuffer[ 64 ];
-
- if(gEngfuncs.pfnRandomLong(1, inSoundProbability) == 1)
- {
-
- entity = gEngfuncs.pEventAPI->EV_IndexFromTrace( ptr );
-
- // FIXME check if playtexture sounds movevar is set
- //
-
- chTextureType = 0;
-
- // Player
- if ( entity >= 1 && entity <= gEngfuncs.GetMaxClients() )
- {
- // hit body
- chTextureType = CHAR_TEX_FLESH;
- }
- else if ( entity == 0 )
- {
- // get texture from entity or world (world is ent(0))
- pTextureName = (char *)gEngfuncs.pEventAPI->EV_TraceTexture( ptr->ent, vecSrc, vecEnd );
-
- if ( pTextureName )
- {
- strcpy( texname, pTextureName );
- pTextureName = texname;
-
- // strip leading '-0' or '+0~' or '{' or '!'
- if (*pTextureName == '-' || *pTextureName == '+')
- {
- pTextureName += 2;
- }
-
- if (*pTextureName == '{' || *pTextureName == '!' || *pTextureName == '~' || *pTextureName == ' ')
- {
- pTextureName++;
- }
-
- // '}}'
- strcpy( szbuffer, pTextureName );
- szbuffer[ CBTEXTURENAMEMAX - 1 ] = 0;
-
- // get texture type
- chTextureType = PM_FindTextureType( szbuffer );
- }
- }
-
- switch (chTextureType)
- {
- default:
- case CHAR_TEX_CONCRETE: fvol = 0.3; fvolbar = 0.6;
- rgsz[0] = "weapons/ric_conc-1.wav";
- rgsz[1] = "weapons/ric_conc-2.wav";
- cnt = 2;
- break;
- case CHAR_TEX_METAL: fvol = 0.3; fvolbar = 0.3;
- rgsz[0] = "weapons/ric_metal-1.wav";
- rgsz[1] = "weapons/ric_metal-2.wav";
- cnt = 2;
- break;
- case CHAR_TEX_DIRT: fvol = 0.9; fvolbar = 0.1;
- rgsz[0] = "player/pl_dirt1.wav";
- rgsz[1] = "player/pl_dirt2.wav";
- rgsz[2] = "player/pl_dirt3.wav";
- cnt = 3;
- break;
- case CHAR_TEX_VENT: fvol = 0.5; fvolbar = 0.3;
- rgsz[0] = "player/pl_duct1.wav";
- rgsz[1] = "player/pl_duct1.wav";
- cnt = 2;
- break;
- case CHAR_TEX_GRATE: fvol = 0.9; fvolbar = 0.5;
- rgsz[0] = "player/pl_grate1.wav";
- rgsz[1] = "player/pl_grate4.wav";
- cnt = 2;
- break;
- case CHAR_TEX_TILE: fvol = 0.8; fvolbar = 0.2;
- rgsz[0] = "player/pl_tile1.wav";
- rgsz[1] = "player/pl_tile3.wav";
- rgsz[2] = "player/pl_tile2.wav";
- rgsz[3] = "player/pl_tile4.wav";
- cnt = 4;
- break;
- case CHAR_TEX_SLOSH: fvol = 0.9; fvolbar = 0.0;
- rgsz[0] = "player/pl_slosh1.wav";
- rgsz[1] = "player/pl_slosh3.wav";
- rgsz[2] = "player/pl_slosh2.wav";
- rgsz[3] = "player/pl_slosh4.wav";
- cnt = 4;
- break;
- case CHAR_TEX_WOOD: fvol = 0.9; fvolbar = 0.2;
- rgsz[0] = "debris/wood1.wav";
- rgsz[1] = "debris/wood2.wav";
- rgsz[2] = "debris/wood3.wav";
- cnt = 3;
- break;
- case CHAR_TEX_GLASS:
- case CHAR_TEX_COMPUTER:
- fvol = 0.8; fvolbar = 0.2;
- rgsz[0] = "debris/glass1.wav";
- rgsz[1] = "debris/glass2.wav";
- rgsz[2] = "debris/glass3.wav";
- cnt = 3;
- break;
- case CHAR_TEX_FLESH:
- if (iBulletType == BULLET_PLAYER_CROWBAR)
- return 0.0; // crowbar already makes this sound
- fvol = 1.0; fvolbar = 0.2;
- rgsz[0] = "weapons/bullet_hit1.wav";
- rgsz[1] = "weapons/bullet_hit2.wav";
- fattn = 1.0;
- cnt = 2;
- break;
- }
-
- if(iBulletType == BULLET_MONSTER_9MM)
- {
- fvol = 0.3;
- fvolbar = 0.6;
- rgsz[0] = "weapons/a_ric1.wav";
- rgsz[1] = "weapons/a_ric2.wav";
- rgsz[2] = "weapons/a_ric3.wav";
- cnt = 3;
- }
-
- // play material hit sound
- gEngfuncs.pEventAPI->EV_PlaySound( 0, ptr->endpos, CHAN_STATIC, rgsz[gEngfuncs.pfnRandomLong(0,cnt-1)], fvol, fattn, 0, 96 + gEngfuncs.pfnRandomLong(0,0xf) );
- }
-
- return fvolbar;
-}
-
-char *EV_HLDM_DamageDecal( physent_t *pe )
-{
- static char decalname[ 32 ];
- int idx;
-
- if ( pe->classnumber == 1 )
- {
- idx = gEngfuncs.pfnRandomLong( 0, 2 );
- sprintf( decalname, "{break%i", idx + 1 );
- }
- else if ( pe->rendermode != kRenderNormal )
- {
- sprintf( decalname, "{bproof1" );
- }
- else
- {
- idx = gEngfuncs.pfnRandomLong( 0, 4 );
- sprintf( decalname, "{shot%i", idx + 1 );
- }
- return decalname;
-}
-
-void EV_HLDM_GunshotDecalTrace( pmtrace_t *pTrace, char *decalName, int inChanceOfSound)
-{
- int iRand;
- physent_t *pe;
-
- gEngfuncs.pEfxAPI->R_BulletImpactParticles( pTrace->endpos );
-
- iRand = gEngfuncs.pfnRandomLong(1, inChanceOfSound);
- if ( iRand == 1)// not every bullet makes a sound.
- {
- const float kRicochetVolume = .2f;
- int theRandomSound = gEngfuncs.pfnRandomLong(0, 4);
- switch(theRandomSound)
- {
- case 0: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "weapons/ric1.wav", kRicochetVolume, ATTN_NORM, 0, PITCH_NORM ); break;
- case 1: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "weapons/ric2.wav", kRicochetVolume, ATTN_NORM, 0, PITCH_NORM ); break;
- case 2: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "weapons/ric3.wav", kRicochetVolume, ATTN_NORM, 0, PITCH_NORM ); break;
- case 3: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "weapons/ric4.wav", kRicochetVolume, ATTN_NORM, 0, PITCH_NORM ); break;
- case 4: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "weapons/ric5.wav", kRicochetVolume, ATTN_NORM, 0, PITCH_NORM ); break;
- }
- }
-
- pe = gEngfuncs.pEventAPI->EV_GetPhysent( pTrace->ent );
-
- // Only decal brush models such as the world etc.
- if ( decalName && decalName[0] && pe && ( pe->solid == SOLID_BSP || pe->movetype == MOVETYPE_PUSHSTEP ) )
- {
- if ( CVAR_GET_FLOAT( "r_decals" ) )
- {
- gEngfuncs.pEfxAPI->R_DecalShoot(
- gEngfuncs.pEfxAPI->Draw_DecalIndex( gEngfuncs.pEfxAPI->Draw_DecalIndexFromName( decalName ) ),
- gEngfuncs.pEventAPI->EV_IndexFromTrace( pTrace ), 0, pTrace->endpos, 0 );
- }
- }
-}
-
-void EV_HLDM_DecalGunshot( pmtrace_t *pTrace, int iBulletType, int inSoundProbability)
-{
- physent_t *pe;
-
- pe = gEngfuncs.pEventAPI->EV_GetPhysent( pTrace->ent );
-
- if ( pe && pe->solid == SOLID_BSP )
- {
- EV_HLDM_GunshotDecalTrace( pTrace, EV_HLDM_DamageDecal( pe ), inSoundProbability);
- }
-}
-
-int EV_HLDM_CheckTracer( int idx, float *vecSrc, float *end, float *forward, float *right, int iBulletType, int iTracerFreq, int *tracerCount )
-{
- int tracer = 0;
- int i;
- qboolean player = idx >= 1 && idx <= gEngfuncs.GetMaxClients() ? true : false;
-
- if ( iTracerFreq != 0 && ( (*tracerCount)++ % iTracerFreq) == 0 )
- {
- vec3_t vecTracerSrc;
-
- if ( player )
- {
- vec3_t offset( 0, 0, -4 );
-
- // adjust tracer position for player
- for ( i = 0; i < 3; i++ )
- {
- vecTracerSrc[ i ] = vecSrc[ i ] + offset[ i ] + right[ i ] * 2 + forward[ i ] * 16;
- }
- }
- else
- {
- VectorCopy( vecSrc, vecTracerSrc );
- }
-
- if ( iTracerFreq != 1 ) // guns that always trace also always decal
- tracer = 1;
-
- switch( iBulletType )
- {
- case BULLET_PLAYER_MP5:
- case BULLET_MONSTER_MP5:
- case BULLET_MONSTER_9MM:
- case BULLET_MONSTER_12MM:
- default:
- EV_CreateTracer( vecTracerSrc, end );
- break;
- }
- }
-
- return tracer;
-}
-
-
-/*
-================
-FireBullets
-
-Go to the trouble of combining multiple pellets into a single damage call.
-================
-*/
-//void EV_HLDM_FireBullets( int idx, float *forward, float *right, float *up, int cShots, float *vecSrc, float *vecDirShooting, float flDistance, int iBulletType, int iTracerFreq, int *tracerCount, float flSpreadX, float flSpreadY )
-//{
-// int i;
-// int iShot;
-// int tracer;
-//
-// // Store off the old count
-// gEngfuncs.pEventAPI->EV_PushPMStates();
-//
-// gEngfuncs.pEventAPI->EV_SetUpPlayerPrediction(false, true);
-//
-// // Now add in all of the players.
-// gEngfuncs.pEventAPI->EV_SetSolidPlayers ( idx - 1 );
-//
-// gEngfuncs.pEventAPI->EV_SetTraceHull( 2 );
-//
-// for ( iShot = 1; iShot <= cShots; iShot++ )
-// {
-// vec3_t vecDir, vecEnd;
-//
-// float x, y, z;
-// //We randomize for the Shotgun.
-// if ( iBulletType == BULLET_PLAYER_BUCKSHOT )
-// {
-// do {
-// x = gEngfuncs.pfnRandomFloat(-0.5,0.5) + gEngfuncs.pfnRandomFloat(-0.5,0.5);
-// y = gEngfuncs.pfnRandomFloat(-0.5,0.5) + gEngfuncs.pfnRandomFloat(-0.5,0.5);
-// z = x*x+y*y;
-// } while (z > 1);
-//
-// for ( i = 0 ; i < 3; i++ )
-// {
-// vecDir[i] = vecDirShooting[i] + x * flSpreadX * right[ i ] + y * flSpreadY * up [ i ];
-// vecEnd[i] = vecSrc[ i ] + flDistance * vecDir[ i ];
-// }
-// }//But other guns already have their spread randomized in the synched spread.
-// else
-// {
-//
-// for ( i = 0 ; i < 3; i++ )
-// {
-// vecDir[i] = vecDirShooting[i] + flSpreadX * right[ i ] + flSpreadY * up [ i ];
-// vecEnd[i] = vecSrc[ i ] + flDistance * vecDir[ i ];
-// }
-// }
-//
-// // For debugging
-// //gEngfuncs.pEfxAPI->R_TracerEffect(vecSrc, vecEnd);
-//
-// pmtrace_t tr;
-// gEngfuncs.pEventAPI->EV_PlayerTrace( vecSrc, vecEnd, PM_STUDIO_BOX, -1, &tr );
-//
-// //gEngfuncs.pEfxAPI->R_BulletImpactParticles(tr.endpos);
-//
-// tracer = EV_HLDM_CheckTracer( idx, vecSrc, tr.endpos, forward, right, iBulletType, iTracerFreq, tracerCount );
-//
-// physent_t *pe = gEngfuncs.pEventAPI->EV_GetPhysent( tr.ent );
-// bool thePlayBulletHitEffect = /*true;//*/!tr.inwater && pe && !pe->player;
-//
-// // do damage, paint decals
-// if ( tr.fraction != 1.0 )
-// {
-// switch(iBulletType)
-// {
-// default:
-// case BULLET_PLAYER_9MM:
-//
-// //EV_HLDM_PlayTextureSound( idx, &tr, vecSrc, vecEnd, iBulletType );
-// EV_HLDM_DecalGunshot( &tr, iBulletType );
-//
-// break;
-// case BULLET_PLAYER_MP5:
-//
-// if ( !tracer )
-// {
-// //EV_HLDM_PlayTextureSound( idx, &tr, vecSrc, vecEnd, iBulletType );
-// EV_HLDM_DecalGunshot( &tr, iBulletType );
-//
-// // Only play weapon effects if we hit the
-// if(thePlayBulletHitEffect)
-// {
-// //int theSprite = gEngfuncs.pEventAPI->EV_FindModelIndex(kGenericWallpuff);
-// //TEMPENTITY* theTempEntity = gEngfuncs.pEfxAPI->R_TempSprite(tr.endpos, vec3_origin, .6f, theSprite, kRenderGlow, kRenderFxNoDissipation, .5, 1.0, FTENT_COLLIDEALL | FTENT_SPRANIMATE | FTENT_SPRANIMATELOOP | FTENT_PERSIST);
-// //theTempEntity->entity.curstate.framerate = 30;
-//
-// gEngfuncs.pEfxAPI->R_SparkEffect(tr.endpos, 6, 10, 100);
-// }
-// }
-// break;
-// case BULLET_PLAYER_BUCKSHOT:
-// if ( !tracer )
-// {
-// EV_HLDM_DecalGunshot( &tr, iBulletType );
-//
-// // Add cool shotgun effect here
-// //gEngfuncs.pEfxAPI->R_RocketTrail(vecSrc, tr.endpos, 1);
-// gEngfuncs.pEfxAPI->R_BulletImpactParticles(tr.endpos);
-//
-// //if(thePlayBulletHitEffect)
-// //{
-// // int theSprite = gEngfuncs.pEventAPI->EV_FindModelIndex(kGenericWallpuff);
-// // TEMPENTITY* theTempEntity = gEngfuncs.pEfxAPI->R_TempSprite(tr.endpos, vec3_origin, 1.0f, theSprite, kRenderGlow, kRenderFxNoDissipation, .5, 1.0, FTENT_COLLIDEALL | FTENT_SPRANIMATE | FTENT_SPRANIMATELOOP | FTENT_PERSIST);
-// // theTempEntity->entity.curstate.framerate = 30;
-// //}
-//
-// gEngfuncs.pEfxAPI->R_SparkEffect(tr.endpos, 5, 100, 200);
-// }
-// break;
-// case BULLET_PLAYER_357:
-// if ( !tracer )
-// {
-// //EV_HLDM_PlayTextureSound( idx, &tr, vecSrc, vecEnd, iBulletType );
-// EV_HLDM_DecalGunshot( &tr, iBulletType );
-//
-// if(thePlayBulletHitEffect)
-// {
-// // Make the smoke stick out of the target or wall just a little bit to avoid crappy sprite-in-wall effect
-// Vector theEndPos = tr.endpos - 20*vecDir;
-// int theSprite = gEngfuncs.pEventAPI->EV_FindModelIndex(kGenericWallpuff);
-// Vector theUp(0, 0, 30);
-// TEMPENTITY* theTempEntity = gEngfuncs.pEfxAPI->R_TempSprite(theEndPos, theUp, .3f, theSprite, kRenderTransAdd, kRenderFxFadeSlow, .3, 0.6, FTENT_COLLIDEALL | FTENT_SPRANIMATE | FTENT_SPRANIMATELOOP | FTENT_PERSIST);
-// if(theTempEntity)
-// {
-// theTempEntity->entity.curstate.framerate = 50;
-// }
-//
-// //// Create rising area of smoke above gun wielder
-// //if(gEngfuncs.pfnRandomLong(0, 3) == 0)
-// //{
-// // vec3_t theSource;
-// // VectorCopy(vecSrc, theSource);
-// // theSource.z += 60;
-// // theSource.z += 60;
-// //
-// // theTempEntity = gEngfuncs.pEfxAPI->R_TempSprite(vecSrc, vec3_origin, 1.0f, theSprite, kRenderGlow, kRenderFxNoDissipation, .3, 3.0, FTENT_COLLIDEALL | FTENT_SPRANIMATE | FTENT_SPRANIMATELOOP | FTENT_PERSIST);
-// // theTempEntity->entity.curstate.framerate = 30;
-// //}
-//
-// // TODO: Add more here like splinters of wall and plaster
-// gEngfuncs.pEfxAPI->R_SparkEffect(tr.endpos, 12, 100, 200);
-// }
-// }
-// break;
-// case BULLET_MONSTER_9MM:
-// break;
-// }
-// }
-// }
-//
-// gEngfuncs.pEventAPI->EV_PopPMStates();
-//}
-
-/*
-================
-EV_HLDM_FireBulletsPlayer
-
-Client-side prediction friendly version of EV_HLDM_FireBullets
-================
-*/
-void EV_HLDM_FireBulletsPlayer( int idx, float *forward, float *right, float *up, int cShots, float *vecSrc, float *vecDirShooting, float flDistance, int iBulletType, int iTracerFreq, int *tracerCount, Vector inSpread, int inRandomSeed)
-{
-// int i;
- int iShot;
- int tracer;
-
- // Store off the old count
- gEngfuncs.pEventAPI->EV_PushPMStates();
-
- gEngfuncs.pEventAPI->EV_SetUpPlayerPrediction(false, true);
-
- // Now add in all of the players.
- gEngfuncs.pEventAPI->EV_SetSolidPlayers ( idx - 1 );
-
- gEngfuncs.pEventAPI->EV_SetTraceHull( 2 );
-
- for ( iShot = 1; iShot <= cShots; iShot++ )
- {
- vec3_t vecDir, vecEnd;
-
-// float x, y, z;
-// //We randomize for the Shotgun.
-// if ( iBulletType == BULLET_PLAYER_BUCKSHOT )
-// {
-// do {
-// x = gEngfuncs.pfnRandomFloat(-0.5,0.5) + gEngfuncs.pfnRandomFloat(-0.5,0.5);
-// y = gEngfuncs.pfnRandomFloat(-0.5,0.5) + gEngfuncs.pfnRandomFloat(-0.5,0.5);
-// z = x*x+y*y;
-// } while (z > 1);
-//
-// for ( i = 0 ; i < 3; i++ )
-// {
-// vecDir[i] = vecDirShooting[i] + x * flSpreadX * right[ i ] + y * flSpreadY * up [ i ];
-// vecEnd[i] = vecSrc[ i ] + flDistance * vecDir[ i ];
-// }
-// }//But other guns already have their spread randomized in the synched spread.
-// else
-// {
-
- //for ( i = 0 ; i < 3; i++ )
- //{
- // vecDir[i] = vecDirShooting[i] + flSpreadX * right[ i ] + flSpreadY * up [ i ];
- // vecEnd[i] = vecSrc[ i ] + flDistance * vecDir[ i ];
- //}
- vecDir = UTIL_GetRandomSpreadDir(inRandomSeed, iShot, vecDirShooting, right, up, inSpread);
- VectorMA(vecSrc, flDistance, vecDir, vecEnd);
- //vecEnd = vecSrc + flDistance*vecDir;
-// }
-
- // For debugging
- //gEngfuncs.pEfxAPI->R_TracerEffect(vecSrc, vecEnd);
-
- pmtrace_t tr;
- gEngfuncs.pEventAPI->EV_PlayerTrace( vecSrc, vecEnd, PM_STUDIO_BOX, -1, &tr );
-
- //gEngfuncs.pEfxAPI->R_BulletImpactParticles(tr.endpos);
-
- tracer = EV_HLDM_CheckTracer( idx, vecSrc, tr.endpos, forward, right, iBulletType, iTracerFreq, tracerCount );
-
- physent_t *pe = gEngfuncs.pEventAPI->EV_GetPhysent( tr.ent );
- bool thePlayBulletHitEffect = /*true;//*/!tr.inwater && pe && !pe->player;
- int theSoundProbability = 2;
-
- // do damage, paint decals
- if ( tr.fraction != 1.0 )
- {
- switch(iBulletType)
- {
- default:
- case BULLET_PLAYER_9MM:
- EV_HLDM_PlayTextureSound( idx, &tr, vecSrc, vecEnd, iBulletType, theSoundProbability);
- EV_HLDM_DecalGunshot( &tr, iBulletType, theSoundProbability);
- break;
-
- case BULLET_PLAYER_MP5:
-
- if ( !tracer )
- {
- EV_HLDM_PlayTextureSound( idx, &tr, vecSrc, vecEnd, iBulletType, theSoundProbability);
-
- theSoundProbability = 8;
- EV_HLDM_DecalGunshot( &tr, iBulletType, theSoundProbability);
-
- // Only play weapon effects if we hit the
- if(thePlayBulletHitEffect)
- {
- // Make the smoke stick out of the target or wall just a little bit to avoid crappy sprite-in-wall effect
- Vector theEndPos = tr.endpos - 20*vecDir;
- int theSprite = gEngfuncs.pEventAPI->EV_FindModelIndex(kGenericWallpuff);
- Vector theUp(0, 0, 30);
- TEMPENTITY* theTempEntity = gEngfuncs.pEfxAPI->R_TempSprite(theEndPos, theUp, .3f, theSprite, kRenderTransAdd, kRenderFxFadeSlow, .1, 0.6, FTENT_COLLIDEALL | FTENT_SPRANIMATE | FTENT_SPRANIMATELOOP | FTENT_PERSIST);
- if(theTempEntity)
- {
- theTempEntity->entity.curstate.framerate = 50;
- }
-
- gEngfuncs.pEfxAPI->R_SparkEffect(tr.endpos, 6, 10, 100);
- }
- }
- break;
- case BULLET_PLAYER_BUCKSHOT:
- if ( !tracer )
- {
- theSoundProbability = BALANCE_VAR(kSGBulletsPerShot)/2;
- EV_HLDM_PlayTextureSound( idx, &tr, vecSrc, vecEnd, iBulletType, theSoundProbability);
-
- theSoundProbability = BALANCE_VAR(kSGBulletsPerShot)/2;
- EV_HLDM_DecalGunshot( &tr, iBulletType, theSoundProbability);
-
- if(thePlayBulletHitEffect)
- {
- // Add cool shotgun effect here
- //gEngfuncs.pEfxAPI->R_RocketTrail(vecSrc, tr.endpos, 1);
- gEngfuncs.pEfxAPI->R_BulletImpactParticles(tr.endpos);
-
- //if(thePlayBulletHitEffect)
- //{
- // int theSprite = gEngfuncs.pEventAPI->EV_FindModelIndex(kGenericWallpuff);
- // TEMPENTITY* theTempEntity = gEngfuncs.pEfxAPI->R_TempSprite(tr.endpos, vec3_origin, 1.0f, theSprite, kRenderGlow, kRenderFxNoDissipation, .5, 1.0, FTENT_COLLIDEALL | FTENT_SPRANIMATE | FTENT_SPRANIMATELOOP | FTENT_PERSIST);
- // theTempEntity->entity.curstate.framerate = 30;
- //}
-
- gEngfuncs.pEfxAPI->R_SparkEffect(tr.endpos, 5, 100, 200);
- }
- }
- break;
- case BULLET_PLAYER_357:
- if ( !tracer )
- {
- theSoundProbability = 1;
- EV_HLDM_PlayTextureSound( idx, &tr, vecSrc, vecEnd, iBulletType, theSoundProbability);
- EV_HLDM_DecalGunshot( &tr, iBulletType, theSoundProbability);
-
- if(thePlayBulletHitEffect)
- {
- // Make the smoke stick out of the target or wall just a little bit to avoid crappy sprite-in-wall effect
- Vector theEndPos = tr.endpos - 20*vecDir;
- int theSprite = gEngfuncs.pEventAPI->EV_FindModelIndex(kGenericWallpuff);
- Vector theUp(0, 0, 30);
- TEMPENTITY* theTempEntity = gEngfuncs.pEfxAPI->R_TempSprite(theEndPos, theUp, .3f, theSprite, kRenderTransAdd, kRenderFxFadeSlow, .15, 0.6, FTENT_COLLIDEALL | FTENT_SPRANIMATE | FTENT_SPRANIMATELOOP | FTENT_PERSIST);
- if(theTempEntity)
- {
- theTempEntity->entity.curstate.framerate = 50;
- }
-
- //// Create rising area of smoke above gun wielder
- //if(gEngfuncs.pfnRandomLong(0, 3) == 0)
- //{
- // vec3_t theSource;
- // VectorCopy(vecSrc, theSource);
- // theSource.z += 60;
- // theSource.z += 60;
- //
- // theTempEntity = gEngfuncs.pEfxAPI->R_TempSprite(vecSrc, vec3_origin, 1.0f, theSprite, kRenderGlow, kRenderFxNoDissipation, .3, 3.0, FTENT_COLLIDEALL | FTENT_SPRANIMATE | FTENT_SPRANIMATELOOP | FTENT_PERSIST);
- // theTempEntity->entity.curstate.framerate = 30;
- //}
-
- // TODO: Add more here like splinters of wall and plaster
- gEngfuncs.pEfxAPI->R_SparkEffect(tr.endpos, 12, 100, 200);
- }
- }
- break;
- case BULLET_MONSTER_9MM:
- if(!tracer)
- {
- EV_HLDM_PlayTextureSound( idx, &tr, vecSrc, vecEnd, iBulletType, theSoundProbability);
- //EV_HLDM_DecalGunshot( &tr, iBulletType, theSoundProbability);
-
- // Only play weapon effects if we hit the
- if(thePlayBulletHitEffect)
- {
- int theSprite = gEngfuncs.pEventAPI->EV_FindModelIndex(kSpikeGunHitSprite);
- TEMPENTITY* theTempEntity = gEngfuncs.pEfxAPI->R_TempSprite(tr.endpos, vec3_origin, .6f, theSprite, kRenderTransAdd, kRenderFxNoDissipation, .5f, .4f, FTENT_COLLIDEALL | FTENT_SPRANIMATE | FTENT_SPRANIMATELOOP | FTENT_PERSIST);
- if(theTempEntity)
- {
- theTempEntity->entity.curstate.framerate = 30;
- }
- }
- }
- break;
- }
- }
- }
-
- gEngfuncs.pEventAPI->EV_PopPMStates();
-}
-
-
-
-//======================
-// GLOCK START
-//======================
-//void EV_FireGlock1( event_args_t *args )
-//{
-// int idx;
-// vec3_t origin;
-// vec3_t angles;
-// vec3_t velocity;
-// int empty;
-//
-// vec3_t ShellVelocity;
-// vec3_t ShellOrigin;
-// int shell;
-// vec3_t vecSrc, vecAiming;
-// vec3_t up, right, forward;
-//
-// idx = args->entindex;
-// VectorCopy( args->origin, origin );
-// VectorCopy( args->angles, angles );
-// VectorCopy( args->velocity, velocity );
-//
-// empty = args->bparam1;
-// AngleVectors( angles, forward, right, up );
-//
-// shell = gEngfuncs.pEventAPI->EV_FindModelIndex ("models/shell.mdl");// brass shell
-//
-// if ( EV_IsLocal( idx ) )
-// {
-// EV_MuzzleFlash();
-// gEngfuncs.pEventAPI->EV_WeaponAnimation( empty ? GLOCK_SHOOT_EMPTY : GLOCK_SHOOT, 2 );
-//
-// V_PunchAxis( 0, -2.0 );
-// }
-//
-// EV_GetDefaultShellInfo( args, origin, velocity, ShellVelocity, ShellOrigin, forward, right, up, 20, -12, 4 );
-//
-// EV_EjectBrass ( ShellOrigin, ShellVelocity, angles[ YAW ], shell, TE_BOUNCE_SHELL );
-//
-// gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/pl_gun3.wav", gEngfuncs.pfnRandomFloat(0.92, 1.0), ATTN_NORM, 0, 98 + gEngfuncs.pfnRandomLong( 0, 3 ) );
-//
-// EV_GetGunPosition( args, vecSrc, origin );
-//
-// VectorCopy( forward, vecAiming );
-//
-// EV_HLDM_FireBullets( idx, forward, right, up, 1, vecSrc, vecAiming, 8192, BULLET_PLAYER_9MM, 0, 0, args->fparam1, args->fparam2);
-//}
-
-//void EV_FireGlock2( event_args_t *args )
-//{
-// int idx;
-// vec3_t origin;
-// vec3_t angles;
-// vec3_t velocity;
-//
-// vec3_t ShellVelocity;
-// vec3_t ShellOrigin;
-// int shell;
-// vec3_t vecSrc, vecAiming;
-// vec3_t vecSpread;
-// vec3_t up, right, forward;
-//
-// idx = args->entindex;
-// VectorCopy( args->origin, origin );
-// VectorCopy( args->angles, angles );
-// VectorCopy( args->velocity, velocity );
-//
-// AngleVectors( angles, forward, right, up );
-//
-// shell = gEngfuncs.pEventAPI->EV_FindModelIndex ("models/shell.mdl");// brass shell
-//
-// if ( EV_IsLocal( idx ) )
-// {
-// // Add muzzle flash to current weapon model
-// EV_MuzzleFlash();
-// gEngfuncs.pEventAPI->EV_WeaponAnimation( GLOCK_SHOOT, 2 );
-//
-// V_PunchAxis( 0, -2.0 );
-// }
-//
-// EV_GetDefaultShellInfo( args, origin, velocity, ShellVelocity, ShellOrigin, forward, right, up, 20, -12, 4 );
-//
-// EV_EjectBrass ( ShellOrigin, ShellVelocity, angles[ YAW ], shell, TE_BOUNCE_SHELL );
-//
-// gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/pl_gun3.wav", gEngfuncs.pfnRandomFloat(0.92, 1.0), ATTN_NORM, 0, 98 + gEngfuncs.pfnRandomLong( 0, 3 ) );
-//
-// EV_GetGunPosition( args, vecSrc, origin );
-//
-// VectorCopy( forward, vecAiming );
-//
-// EV_HLDM_FireBullets( idx, forward, right, up, 1, vecSrc, vecAiming, 8192, BULLET_PLAYER_9MM, 0, &tracerCount[idx-1], args->fparam1, args->fparam2 );
-//
-//}
-//======================
-// GLOCK END
-//======================
-
-//======================
-// SHOTGUN START
-//======================
-//void EV_FireShotGunDouble( event_args_t *args )
-//{
-// int idx;
-// vec3_t origin;
-// vec3_t angles;
-// vec3_t velocity;
-//
-// int j;
-// vec3_t ShellVelocity;
-// vec3_t ShellOrigin;
-// int shell;
-// vec3_t vecSrc, vecAiming;
-// vec3_t vecSpread;
-// vec3_t up, right, forward;
-// float flSpread = 0.01;
-//
-// idx = args->entindex;
-// VectorCopy( args->origin, origin );
-// VectorCopy( args->angles, angles );
-// VectorCopy( args->velocity, velocity );
-//
-// AngleVectors( angles, forward, right, up );
-//
-// shell = gEngfuncs.pEventAPI->EV_FindModelIndex ("models/shotgunshell.mdl");// brass shell
-//
-// if ( EV_IsLocal( idx ) )
-// {
-// // Add muzzle flash to current weapon model
-// EV_MuzzleFlash();
-// gEngfuncs.pEventAPI->EV_WeaponAnimation( SHOTGUN_FIRE2, 2 );
-// V_PunchAxis( 0, -10.0 );
-// }
-//
-// for ( j = 0; j < 2; j++ )
-// {
-// EV_GetDefaultShellInfo( args, origin, velocity, ShellVelocity, ShellOrigin, forward, right, up, 32, -12, 6 );
-//
-// EV_EjectBrass ( ShellOrigin, ShellVelocity, angles[ YAW ], shell, TE_BOUNCE_SHOTSHELL );
-// }
-//
-// gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/dbarrel1.wav", gEngfuncs.pfnRandomFloat(0.98, 1.0), ATTN_NORM, 0, 85 + gEngfuncs.pfnRandomLong( 0, 0x1f ) );
-//
-// EV_GetGunPosition( args, vecSrc, origin );
-// VectorCopy( forward, vecAiming );
-//
-// if ( gEngfuncs.GetMaxClients() > 1 )
-// {
-// EV_HLDM_FireBullets( idx, forward, right, up, 8, vecSrc, vecAiming, 2048, BULLET_PLAYER_BUCKSHOT, 0, &tracerCount[idx-1], 0.17365, 0.04362 );
-// }
-// else
-// {
-// EV_HLDM_FireBullets( idx, forward, right, up, 12, vecSrc, vecAiming, 2048, BULLET_PLAYER_BUCKSHOT, 0, &tracerCount[idx-1], 0.08716, 0.08716 );
-// }
-//
-// if ( EV_IsLocal( idx ) )
-// {
-// V_PunchAxis( 0, -10.0 );
-// }
-//}
-
-//void EV_FireShotGunSingle( event_args_t *args )
-//{
-// int idx;
-// vec3_t origin;
-// vec3_t angles;
-// vec3_t velocity;
-//
-// vec3_t ShellVelocity;
-// vec3_t ShellOrigin;
-// int shell;
-// vec3_t vecSrc, vecAiming;
-// vec3_t vecSpread;
-// vec3_t up, right, forward;
-// float flSpread = 0.01;
-//
-// idx = args->entindex;
-// VectorCopy( args->origin, origin );
-// VectorCopy( args->angles, angles );
-// VectorCopy( args->velocity, velocity );
-//
-// AngleVectors( angles, forward, right, up );
-//
-// shell = gEngfuncs.pEventAPI->EV_FindModelIndex ("models/shotgunshell.mdl");// brass shell
-//
-// if ( EV_IsLocal( idx ) )
-// {
-// // Add muzzle flash to current weapon model
-// EV_MuzzleFlash();
-// gEngfuncs.pEventAPI->EV_WeaponAnimation( SHOTGUN_FIRE, 2 );
-//
-// V_PunchAxis( 0, -5.0 );
-// }
-//
-// EV_GetDefaultShellInfo( args, origin, velocity, ShellVelocity, ShellOrigin, forward, right, up, 32, -12, 6 );
-//
-// EV_EjectBrass ( ShellOrigin, ShellVelocity, angles[ YAW ], shell, TE_BOUNCE_SHOTSHELL );
-//
-// gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/sbarrel1.wav", gEngfuncs.pfnRandomFloat(0.95, 1.0), ATTN_NORM, 0, 93 + gEngfuncs.pfnRandomLong( 0, 0x1f ) );
-//
-// EV_GetGunPosition( args, vecSrc, origin );
-// VectorCopy( forward, vecAiming );
-//
-// if ( gEngfuncs.GetMaxClients() > 1 )
-// {
-// EV_HLDM_FireBullets( idx, forward, right, up, 4, vecSrc, vecAiming, 2048, BULLET_PLAYER_BUCKSHOT, 0, &tracerCount[idx-1], 0.08716, 0.04362 );
-// }
-// else
-// {
-// EV_HLDM_FireBullets( idx, forward, right, up, 6, vecSrc, vecAiming, 2048, BULLET_PLAYER_BUCKSHOT, 0, &tracerCount[idx-1], 0.08716, 0.08716 );
-// }
-//}
-//======================
-// SHOTGUN END
-//======================
-
-//======================
-// MP5 START
-//======================
-//void EV_FireMP5( event_args_t *args )
-//{
-// int idx;
-// vec3_t origin;
-// vec3_t angles;
-// vec3_t velocity;
-//
-// vec3_t ShellVelocity;
-// vec3_t ShellOrigin;
-// int shell;
-// vec3_t vecSrc, vecAiming;
-// vec3_t up, right, forward;
-// float flSpread = 0.01;
-//
-// idx = args->entindex;
-// VectorCopy( args->origin, origin );
-// VectorCopy( args->angles, angles );
-// VectorCopy( args->velocity, velocity );
-//
-// AngleVectors( angles, forward, right, up );
-//
-// shell = gEngfuncs.pEventAPI->EV_FindModelIndex ("models/shell.mdl");// brass shell
-//
-// if ( EV_IsLocal( idx ) )
-// {
-// // Add muzzle flash to current weapon model
-// EV_MuzzleFlash();
-// gEngfuncs.pEventAPI->EV_WeaponAnimation( MG_FIRE1 + gEngfuncs.pfnRandomLong(0,2), 2 );
-// }
-//
-// EV_GetDefaultShellInfo( args, origin, velocity, ShellVelocity, ShellOrigin, forward, right, up, 20, -12, 4 );
-//
-// EV_EjectBrass ( ShellOrigin, ShellVelocity, angles[ YAW ], shell, TE_BOUNCE_SHELL );
-//
-// switch( gEngfuncs.pfnRandomLong( 0, 1 ) )
-// {
-// case 0:
-// gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/hks1.wav", 1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ) );
-// break;
-// case 1:
-// gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/hks2.wav", 1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ) );
-// break;
-// }
-//
-// EV_GetGunPosition( args, vecSrc, origin );
-// VectorCopy( forward, vecAiming );
-//
-// if ( gEngfuncs.GetMaxClients() > 1 )
-// {
-// EV_HLDM_FireBullets( idx, forward, right, up, 1, vecSrc, vecAiming, 8192, BULLET_PLAYER_MP5, 2, &tracerCount[idx-1], args->fparam1, args->fparam2 );
-// }
-// else
-// {
-// EV_HLDM_FireBullets( idx, forward, right, up, 1, vecSrc, vecAiming, 8192, BULLET_PLAYER_MP5, 2, &tracerCount[idx-1], args->fparam1, args->fparam2 );
-// }
-//}
-
-// We only predict the animation and sound
-// The grenade is still launched from the server.
-//void EV_FireMP52( event_args_t *args )
-//{
-// int idx;
-// vec3_t origin;
-//
-// idx = args->entindex;
-// VectorCopy( args->origin, origin );
-//
-// if ( EV_IsLocal( idx ) )
-// {
-// // NOTE: Put this back in if needed <<< cgc >>>
-// //gEngfuncs.pEventAPI->EV_WeaponAnimation( MP5_LAUNCH, 2 );
-// //V_PunchAxis( 0, -10 );
-// }
-//
-// switch( gEngfuncs.pfnRandomLong( 0, 1 ) )
-// {
-// case 0:
-// gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/glauncher.wav", 1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ) );
-// break;
-// case 1:
-// gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/glauncher2.wav", 1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ) );
-// break;
-// }
-//}
-//======================
-// MP5 END
-//======================
-
-//======================
-// PHYTON START
-// ( .357 )
-//======================
-//void EV_FirePython( event_args_t *args )
-//{
-// int idx;
-// vec3_t origin;
-// vec3_t angles;
-// vec3_t velocity;
-//
-// vec3_t vecSrc, vecAiming;
-// vec3_t up, right, forward;
-// float flSpread = 0.01;
-//
-// idx = args->entindex;
-// VectorCopy( args->origin, origin );
-// VectorCopy( args->angles, angles );
-// VectorCopy( args->velocity, velocity );
-//
-// AngleVectors( angles, forward, right, up );
-//
-// if ( EV_IsLocal( idx ) )
-// {
-// // Python uses different body in multiplayer versus single player
-// int multiplayer = gEngfuncs.GetMaxClients() == 1 ? 0 : 1;
-//
-// // Add muzzle flash to current weapon model
-// EV_MuzzleFlash();
-// gEngfuncs.pEventAPI->EV_WeaponAnimation( PYTHON_FIRE1, multiplayer ? 1 : 0 );
-//
-// V_PunchAxis( 0, -10.0 );
-// }
-//
-// switch( gEngfuncs.pfnRandomLong( 0, 1 ) )
-// {
-// case 0:
-// gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/357_shot1.wav", gEngfuncs.pfnRandomFloat(0.8, 0.9), ATTN_NORM, 0, PITCH_NORM );
-// break;
-// case 1:
-// gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/357_shot2.wav", gEngfuncs.pfnRandomFloat(0.8, 0.9), ATTN_NORM, 0, PITCH_NORM );
-// break;
-// }
-//
-// EV_GetGunPosition( args, vecSrc, origin );
-//
-// VectorCopy( forward, vecAiming );
-//
-// EV_HLDM_FireBullets( idx, forward, right, up, 1, vecSrc, vecAiming, 8192, BULLET_PLAYER_357, 0, 0, args->fparam1, args->fparam2 );
-//}
-//======================
-// PHYTON END
-// ( .357 )
-//======================
-
-//======================
-// GAUSS START
-//======================
-#define SND_CHANGE_PITCH (1<<7) // duplicated in protocol.h change sound pitch
-
-void EV_SpinGauss( event_args_t *args )
-{
- int idx;
- vec3_t origin;
- vec3_t angles;
- vec3_t velocity;
- int iSoundState = 0;
-
- int pitch;
-
- idx = args->entindex;
- VectorCopy( args->origin, origin );
- VectorCopy( args->angles, angles );
- VectorCopy( args->velocity, velocity );
-
- pitch = args->iparam1;
-
- iSoundState = args->bparam1 ? SND_CHANGE_PITCH : 0;
-
- gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "ambience/pulsemachine.wav", 1.0, ATTN_NORM, iSoundState, pitch );
-}
-
-/*
-==============================
-EV_StopPreviousGauss
-
-==============================
-*/
-void EV_StopPreviousGauss( int idx )
-{
- // Make sure we don't have a gauss spin event in the queue for this guy
- gEngfuncs.pEventAPI->EV_KillEvents( idx, "events/gaussspin.sc" );
- gEngfuncs.pEventAPI->EV_StopSound( idx, CHAN_WEAPON, "ambience/pulsemachine.wav" );
-}
-
-void EV_FireGauss( event_args_t *args )
-{
- int idx;
- vec3_t origin;
- vec3_t angles;
- vec3_t velocity;
- float flDamage = args->fparam1;
- int primaryfire = args->bparam1;
-
- int m_fPrimaryFire = args->bparam1;
- int m_iWeaponVolume = GAUSS_PRIMARY_FIRE_VOLUME;
- vec3_t vecSrc;
- vec3_t vecDest;
- edict_t *pentIgnore;
- pmtrace_t tr, beam_tr;
- float flMaxFrac = 1.0;
- int nTotal = 0;
- int fHasPunched = 0;
- int fFirstBeam = 1;
- int nMaxHits = 10;
- physent_t *pEntity;
- int m_iBeam, m_iGlow, m_iBalls;
- vec3_t up, right, forward;
-
- idx = args->entindex;
- VectorCopy( args->origin, origin );
- VectorCopy( args->angles, angles );
- VectorCopy( args->velocity, velocity );
-
- if ( args->bparam2 )
- {
- EV_StopPreviousGauss( idx );
- return;
- }
-
-// Con_Printf( "Firing gauss with %f\n", flDamage );
- EV_GetGunPosition( args, vecSrc, origin );
-
- m_iBeam = gEngfuncs.pEventAPI->EV_FindModelIndex( "sprites/smoke.spr" );
- m_iBalls = m_iGlow = gEngfuncs.pEventAPI->EV_FindModelIndex( "sprites/hotglow.spr" );
-
- AngleVectors( angles, forward, right, up );
-
- VectorMA( vecSrc, 8192, forward, vecDest );
-
- if ( EV_IsLocal( idx ) )
- {
- V_PunchAxis( 0, -2.0 );
- gEngfuncs.pEventAPI->EV_WeaponAnimation( GAUSS_FIRE2, 2 );
- }
-
- gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/gauss2.wav", 0.5 + flDamage * (1.0 / 400.0), ATTN_NORM, 0, 85 + gEngfuncs.pfnRandomLong( 0, 0x1f ) );
-
- while (flDamage > 10 && nMaxHits > 0)
- {
- nMaxHits--;
-
- gEngfuncs.pEventAPI->EV_SetUpPlayerPrediction( false, true );
-
- // Store off the old count
- gEngfuncs.pEventAPI->EV_PushPMStates();
-
- // Now add in all of the players.
- gEngfuncs.pEventAPI->EV_SetSolidPlayers ( idx - 1 );
-
- gEngfuncs.pEventAPI->EV_SetTraceHull( 2 );
- gEngfuncs.pEventAPI->EV_PlayerTrace( vecSrc, vecDest, PM_STUDIO_BOX, -1, &tr );
-
- gEngfuncs.pEventAPI->EV_PopPMStates();
-
- if ( tr.allsolid )
- break;
-
- if (fFirstBeam)
- {
- if ( EV_IsLocal( idx ) )
- {
- // Add muzzle flash to current weapon model
- EV_MuzzleFlash();
- }
- fFirstBeam = 0;
-
- gEngfuncs.pEfxAPI->R_BeamEntPoint(
- idx | 0x1000,
- tr.endpos,
- m_iBeam,
- 0.1,
- m_fPrimaryFire ? 1.0 : 2.5,
- 0.0,
- m_fPrimaryFire ? 128.0 : flDamage,
- 0,
- 0,
- 0,
- m_fPrimaryFire ? 255 : 255,
- m_fPrimaryFire ? 128 : 255,
- m_fPrimaryFire ? 0 : 255
- );
- }
- else
- {
- gEngfuncs.pEfxAPI->R_BeamPoints( vecSrc,
- tr.endpos,
- m_iBeam,
- 0.1,
- m_fPrimaryFire ? 1.0 : 2.5,
- 0.0,
- m_fPrimaryFire ? 128.0 : flDamage,
- 0,
- 0,
- 0,
- m_fPrimaryFire ? 255 : 255,
- m_fPrimaryFire ? 128 : 255,
- m_fPrimaryFire ? 0 : 255
- );
- }
-
- pEntity = gEngfuncs.pEventAPI->EV_GetPhysent( tr.ent );
- if ( pEntity == NULL )
- break;
-
- if ( pEntity->solid == SOLID_BSP )
- {
- float n;
-
- pentIgnore = NULL;
-
- n = -DotProduct( tr.plane.normal, forward );
-
- if (n < 0.5) // 60 degrees
- {
- // ALERT( at_console, "reflect %f\n", n );
- // reflect
- vec3_t r;
-
- VectorMA( forward, 2.0 * n, tr.plane.normal, r );
-
- flMaxFrac = flMaxFrac - tr.fraction;
-
- VectorCopy( r, forward );
-
- VectorMA( tr.endpos, 8.0, forward, vecSrc );
- VectorMA( vecSrc, 8192.0, forward, vecDest );
-
- gEngfuncs.pEfxAPI->R_TempSprite( tr.endpos, vec3_origin, 0.2, m_iGlow, kRenderGlow, kRenderFxNoDissipation, flDamage * n / 255.0, flDamage * n * 0.5 * 0.1, FTENT_FADEOUT );
-
- vec3_t fwd;
- VectorAdd( tr.endpos, tr.plane.normal, fwd );
-
- gEngfuncs.pEfxAPI->R_Sprite_Trail( TE_SPRITETRAIL, tr.endpos, fwd, m_iBalls, 3, 0.1, gEngfuncs.pfnRandomFloat( 10, 20 ) / 100.0, 100,
- 255, 100 );
-
- // lose energy
- if ( n == 0 )
- {
- n = 0.1;
- }
-
- flDamage = flDamage * (1 - n);
-
- }
- else
- {
- // tunnel
- EV_HLDM_DecalGunshot( &tr, BULLET_MONSTER_12MM );
-
- gEngfuncs.pEfxAPI->R_TempSprite( tr.endpos, vec3_origin, 1.0, m_iGlow, kRenderGlow, kRenderFxNoDissipation, flDamage / 255.0, 6.0, FTENT_FADEOUT );
-
- // limit it to one hole punch
- if (fHasPunched)
- {
- break;
- }
- fHasPunched = 1;
-
- // try punching through wall if secondary attack (primary is incapable of breaking through)
- if ( !m_fPrimaryFire )
- {
- vec3_t start;
-
- VectorMA( tr.endpos, 8.0, forward, start );
-
- // Store off the old count
- gEngfuncs.pEventAPI->EV_PushPMStates();
-
- // Now add in all of the players.
- gEngfuncs.pEventAPI->EV_SetSolidPlayers ( idx - 1 );
-
- gEngfuncs.pEventAPI->EV_SetTraceHull( 2 );
- gEngfuncs.pEventAPI->EV_PlayerTrace( start, vecDest, PM_STUDIO_BOX, -1, &beam_tr );
-
- if ( !beam_tr.allsolid )
- {
- vec3_t delta;
- float n;
-
- // trace backwards to find exit point
-
- gEngfuncs.pEventAPI->EV_PlayerTrace( beam_tr.endpos, tr.endpos, PM_STUDIO_BOX, -1, &beam_tr );
-
- VectorSubtract( beam_tr.endpos, tr.endpos, delta );
-
- n = Length( delta );
-
- if (n < flDamage)
- {
- if (n == 0)
- n = 1;
- flDamage -= n;
-
- // absorption balls
- {
- vec3_t fwd;
- VectorSubtract( tr.endpos, forward, fwd );
- gEngfuncs.pEfxAPI->R_Sprite_Trail( TE_SPRITETRAIL, tr.endpos, fwd, m_iBalls, 3, 0.1, gEngfuncs.pfnRandomFloat( 10, 20 ) / 100.0, 100,
- 255, 100 );
- }
-
- //////////////////////////////////// WHAT TO DO HERE
- // CSoundEnt::InsertSound ( bits_SOUND_COMBAT, pev->origin, NORMAL_EXPLOSION_VOLUME, 3.0 );
-
- EV_HLDM_DecalGunshot( &beam_tr, BULLET_MONSTER_12MM );
-
- gEngfuncs.pEfxAPI->R_TempSprite( beam_tr.endpos, vec3_origin, 0.1, m_iGlow, kRenderGlow, kRenderFxNoDissipation, flDamage / 255.0, 6.0, FTENT_FADEOUT );
-
- // balls
- {
- vec3_t fwd;
- VectorSubtract( beam_tr.endpos, forward, fwd );
- gEngfuncs.pEfxAPI->R_Sprite_Trail( TE_SPRITETRAIL, beam_tr.endpos, fwd, m_iBalls, (int)(flDamage * 0.3), 0.1, gEngfuncs.pfnRandomFloat( 10, 20 ) / 100.0, 200,
- 255, 40 );
- }
-
- VectorAdd( beam_tr.endpos, forward, vecSrc );
- }
- }
- else
- {
- flDamage = 0;
- }
-
- gEngfuncs.pEventAPI->EV_PopPMStates();
- }
- else
- {
- if ( m_fPrimaryFire )
- {
- // slug doesn't punch through ever with primary
- // fire, so leave a little glowy bit and make some balls
- gEngfuncs.pEfxAPI->R_TempSprite( tr.endpos, vec3_origin, 0.2, m_iGlow, kRenderGlow, kRenderFxNoDissipation, 200.0 / 255.0, 0.3, FTENT_FADEOUT );
-
- {
- vec3_t fwd;
- VectorAdd( tr.endpos, tr.plane.normal, fwd );
- gEngfuncs.pEfxAPI->R_Sprite_Trail( TE_SPRITETRAIL, tr.endpos, fwd, m_iBalls, 8, 0.6, gEngfuncs.pfnRandomFloat( 10, 20 ) / 100.0, 100,
- 255, 200 );
- }
- }
-
- flDamage = 0;
- }
- }
- }
- else
- {
- VectorAdd( tr.endpos, forward, vecSrc );
- }
- }
-}
-//======================
-// GAUSS END
-//======================
-
-//======================
-// CROWBAR START
-//======================
-
-enum crowbar_e {
- CROWBAR_IDLE = 0,
- CROWBAR_DRAW,
- CROWBAR_HOLSTER,
- CROWBAR_ATTACK1HIT,
- CROWBAR_ATTACK1MISS,
- CROWBAR_ATTACK2MISS,
- CROWBAR_ATTACK2HIT,
- CROWBAR_ATTACK3MISS,
- CROWBAR_ATTACK3HIT
-};
-
-int g_iSwing;
-
-//Only predict the miss sounds, hit sounds are still played
-//server side, so players don't get the wrong idea.
-void EV_Crowbar( event_args_t *args )
-{
- int idx;
- vec3_t origin;
- vec3_t angles;
- vec3_t velocity;
-
- idx = args->entindex;
- VectorCopy( args->origin, origin );
-
- //Play Swing sound
- gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/cbar_miss1.wav", 1, ATTN_NORM, 0, PITCH_NORM);
-
- if ( EV_IsLocal( idx ) )
- {
- gEngfuncs.pEventAPI->EV_WeaponAnimation( CROWBAR_ATTACK1MISS, 1 );
-
- switch( (g_iSwing++) % 3 )
- {
- case 0:
- gEngfuncs.pEventAPI->EV_WeaponAnimation ( CROWBAR_ATTACK1MISS, 1 ); break;
- case 1:
- gEngfuncs.pEventAPI->EV_WeaponAnimation ( CROWBAR_ATTACK2MISS, 1 ); break;
- case 2:
- gEngfuncs.pEventAPI->EV_WeaponAnimation ( CROWBAR_ATTACK3MISS, 1 ); break;
- }
- }
-}
-//======================
-// CROWBAR END
-//======================
-
-//======================
-// CROSSBOW END
-//======================
-enum crossbow_e {
- CROSSBOW_IDLE1 = 0, // full
- CROSSBOW_IDLE2, // empty
- CROSSBOW_FIDGET1, // full
- CROSSBOW_FIDGET2, // empty
- CROSSBOW_FIRE1, // full
- CROSSBOW_FIRE2, // reload
- CROSSBOW_FIRE3, // empty
- CROSSBOW_RELOAD, // from empty
- CROSSBOW_DRAW1, // full
- CROSSBOW_DRAW2, // empty
- CROSSBOW_HOLSTER1, // full
- CROSSBOW_HOLSTER2, // empty
-};
-
-//=====================
-// EV_BoltCallback
-// This function is used to correct the origin and angles
-// of the bolt, so it looks like it's stuck on the wall.
-//=====================
-void EV_BoltCallback ( struct tempent_s *ent, float frametime, float currenttime )
-{
- ent->entity.origin = ent->entity.baseline.vuser1;
- ent->entity.angles = ent->entity.baseline.vuser2;
-}
-
-void EV_FireCrossbow2( event_args_t *args )
-{
- vec3_t vecSrc, vecEnd;
- vec3_t up, right, forward;
- pmtrace_t tr;
-
- int idx;
- vec3_t origin;
- vec3_t angles;
- vec3_t velocity;
-
- idx = args->entindex;
- VectorCopy( args->origin, origin );
- VectorCopy( args->angles, angles );
-
- VectorCopy( args->velocity, velocity );
-
- AngleVectors( angles, forward, right, up );
-
- EV_GetGunPosition( args, vecSrc, origin );
-
- VectorMA( vecSrc, 8192, forward, vecEnd );
-
- gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/xbow_fire1.wav", 1, ATTN_NORM, 0, 93 + gEngfuncs.pfnRandomLong(0,0xF) );
- gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_ITEM, "weapons/xbow_reload1.wav", gEngfuncs.pfnRandomFloat(0.95, 1.0), ATTN_NORM, 0, 93 + gEngfuncs.pfnRandomLong(0,0xF) );
-
- if ( EV_IsLocal( idx ) )
- {
- if ( args->iparam1 )
- gEngfuncs.pEventAPI->EV_WeaponAnimation( CROSSBOW_FIRE1, 1 );
- else if ( args->iparam2 )
- gEngfuncs.pEventAPI->EV_WeaponAnimation( CROSSBOW_FIRE3, 1 );
- }
-
- // Store off the old count
- gEngfuncs.pEventAPI->EV_PushPMStates();
-
- // Now add in all of the players.
- gEngfuncs.pEventAPI->EV_SetSolidPlayers ( idx - 1 );
- gEngfuncs.pEventAPI->EV_SetTraceHull( 2 );
- gEngfuncs.pEventAPI->EV_PlayerTrace( vecSrc, vecEnd, PM_STUDIO_BOX, -1, &tr );
-
- //We hit something
- if ( tr.fraction < 1.0 )
- {
- physent_t *pe = gEngfuncs.pEventAPI->EV_GetPhysent( tr.ent );
-
- //Not the world, let's assume we hit something organic ( dog, cat, uncle joe, etc ).
- if ( pe->solid != SOLID_BSP )
- {
- switch( gEngfuncs.pfnRandomLong(0,1) )
- {
- case 0:
- gEngfuncs.pEventAPI->EV_PlaySound( idx, tr.endpos, CHAN_BODY, "weapons/xbow_hitbod1.wav", 1, ATTN_NORM, 0, PITCH_NORM ); break;
- case 1:
- gEngfuncs.pEventAPI->EV_PlaySound( idx, tr.endpos, CHAN_BODY, "weapons/xbow_hitbod2.wav", 1, ATTN_NORM, 0, PITCH_NORM ); break;
- }
- }
- //Stick to world but don't stick to glass, it might break and leave the bolt floating. It can still stick to other non-transparent breakables though.
- else if ( pe->rendermode == kRenderNormal )
- {
- gEngfuncs.pEventAPI->EV_PlaySound( 0, tr.endpos, CHAN_BODY, "weapons/xbow_hit1.wav", gEngfuncs.pfnRandomFloat(0.95, 1.0), ATTN_NORM, 0, PITCH_NORM );
-
- //Not underwater, do some sparks...
- if ( gEngfuncs.PM_PointContents( tr.endpos, NULL ) != CONTENTS_WATER)
- gEngfuncs.pEfxAPI->R_SparkShower( tr.endpos );
-
- vec3_t vBoltAngles;
- int iModelIndex = gEngfuncs.pEventAPI->EV_FindModelIndex( "models/crossbow_bolt.mdl" );
-
- VectorAngles( forward, vBoltAngles );
-
- TEMPENTITY *bolt = gEngfuncs.pEfxAPI->R_TempModel( tr.endpos - forward * 10, Vector( 0, 0, 0), vBoltAngles , 5, iModelIndex, TE_BOUNCE_NULL );
-
- if ( bolt )
- {
- bolt->flags |= ( FTENT_CLIENTCUSTOM ); //So it calls the callback function.
- bolt->entity.baseline.vuser1 = tr.endpos - forward * 10; // Pull out a little bit
- bolt->entity.baseline.vuser2 = vBoltAngles; //Look forward!
- bolt->callback = EV_BoltCallback; //So we can set the angles and origin back. (Stick the bolt to the wall)
- }
- }
- }
-
- gEngfuncs.pEventAPI->EV_PopPMStates();
-}
-
-//TODO: Fully predict the fliying bolt.
-void EV_FireCrossbow( event_args_t *args )
-{
- int idx;
- vec3_t origin;
-
- idx = args->entindex;
- VectorCopy( args->origin, origin );
-
- gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/xbow_fire1.wav", 1, ATTN_NORM, 0, 93 + gEngfuncs.pfnRandomLong(0,0xF) );
- gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_ITEM, "weapons/xbow_reload1.wav", gEngfuncs.pfnRandomFloat(0.95, 1.0), ATTN_NORM, 0, 93 + gEngfuncs.pfnRandomLong(0,0xF) );
-
- //Only play the weapon anims if I shot it.
- if ( EV_IsLocal( idx ) )
- {
- if ( args->iparam1 )
- gEngfuncs.pEventAPI->EV_WeaponAnimation( CROSSBOW_FIRE1, 1 );
- else if ( args->iparam2 )
- gEngfuncs.pEventAPI->EV_WeaponAnimation( CROSSBOW_FIRE3, 1 );
-
- V_PunchAxis( 0, -2.0 );
- }
-}
-//======================
-// CROSSBOW END
-//======================
-
-//======================
-// RPG START
-//======================
-enum rpg_e {
- RPG_IDLE = 0,
- RPG_FIDGET,
- RPG_RELOAD, // to reload
- RPG_FIRE2, // to empty
- RPG_HOLSTER1, // loaded
- RPG_DRAW1, // loaded
- RPG_HOLSTER2, // unloaded
- RPG_DRAW_UL, // unloaded
- RPG_IDLE_UL, // unloaded idle
- RPG_FIDGET_UL, // unloaded fidget
-};
-
-void EV_FireRpg( event_args_t *args )
-{
- int idx;
- vec3_t origin;
-
- idx = args->entindex;
- VectorCopy( args->origin, origin );
-
- gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/rocketfire1.wav", 0.9, ATTN_NORM, 0, PITCH_NORM );
- gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_ITEM, "weapons/glauncher.wav", 0.7, ATTN_NORM, 0, PITCH_NORM );
-
- //Only play the weapon anims if I shot it.
- if ( EV_IsLocal( idx ) )
- {
- gEngfuncs.pEventAPI->EV_WeaponAnimation( RPG_FIRE2, 1 );
-
- V_PunchAxis( 0, -5.0 );
- }
-}
-//======================
-// RPG END
-//======================
-
-//======================
-// EGON END
-//======================
-enum egon_e {
- EGON_IDLE1 = 0,
- EGON_FIDGET1,
- EGON_ALTFIREON,
- EGON_ALTFIRECYCLE,
- EGON_ALTFIREOFF,
- EGON_FIRE1,
- EGON_FIRE2,
- EGON_FIRE3,
- EGON_FIRE4,
- EGON_DRAW,
- EGON_HOLSTER
-};
-
-int g_fireAnims1[] = { EGON_FIRE1, EGON_FIRE2, EGON_FIRE3, EGON_FIRE4 };
-int g_fireAnims2[] = { EGON_ALTFIRECYCLE };
-
-enum EGON_FIRESTATE { FIRE_OFF, FIRE_CHARGE };
-enum EGON_FIREMODE { FIRE_NARROW, FIRE_WIDE};
-
-#define EGON_PRIMARY_VOLUME 450
-#define EGON_BEAM_SPRITE "sprites/xbeam1.spr"
-#define EGON_FLARE_SPRITE "sprites/XSpark1.spr"
-#define EGON_SOUND_OFF "weapons/egon_off1.wav"
-#define EGON_SOUND_RUN "weapons/egon_run3.wav"
-#define EGON_SOUND_STARTUP "weapons/egon_windup2.wav"
-
-//@2014
-#ifdef ARRAYSIZE
-#undef ARRAYSIZE
-#endif
-
-#define ARRAYSIZE(p) (sizeof(p)/sizeof(p[0]))
-
-BEAM *pBeam;
-BEAM *pBeam2;
-
-void EV_EgonFire( event_args_t *args )
-{
- int idx, iFireState, iFireMode;
- vec3_t origin;
-
- idx = args->entindex;
- VectorCopy( args->origin, origin );
- iFireState = args->iparam1;
- iFireMode = args->iparam2;
- int iStartup = args->bparam1;
-
-
- if ( iStartup )
- {
- if ( iFireMode == FIRE_WIDE )
- gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, EGON_SOUND_STARTUP, 0.98, ATTN_NORM, 0, 125 );
- else
- gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, EGON_SOUND_STARTUP, 0.9, ATTN_NORM, 0, 100 );
- }
- else
- {
- if ( iFireMode == FIRE_WIDE )
- gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_STATIC, EGON_SOUND_RUN, 0.98, ATTN_NORM, 0, 125 );
- else
- gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_STATIC, EGON_SOUND_RUN, 0.9, ATTN_NORM, 0, 100 );
- }
-
- //Only play the weapon anims if I shot it.
- if ( EV_IsLocal( idx ) )
- gEngfuncs.pEventAPI->EV_WeaponAnimation ( g_fireAnims1[ gEngfuncs.pfnRandomLong( 0, 3 ) ], 1 );
-
- if ( iStartup == 1 && EV_IsLocal( idx ) && !pBeam && !pBeam2 )
- {
- vec3_t vecSrc, vecEnd, origin, angles, forward, right, up;
- pmtrace_t tr;
-
- cl_entity_t *pl = gEngfuncs.GetEntityByIndex( idx );
-
- if ( pl )
- {
- VectorCopy( gHUD.m_vecAngles, angles );
-
- AngleVectors( angles, forward, right, up );
-
- EV_GetGunPosition( args, vecSrc, pl->origin );
-
- VectorMA( vecSrc, 2048, forward, vecEnd );
-
- gEngfuncs.pEventAPI->EV_SetUpPlayerPrediction( false, true );
-
- // Store off the old count
- gEngfuncs.pEventAPI->EV_PushPMStates();
-
- // Now add in all of the players.
- gEngfuncs.pEventAPI->EV_SetSolidPlayers ( idx - 1 );
-
- gEngfuncs.pEventAPI->EV_SetTraceHull( 2 );
- gEngfuncs.pEventAPI->EV_PlayerTrace( vecSrc, vecEnd, PM_STUDIO_BOX, -1, &tr );
-
- gEngfuncs.pEventAPI->EV_PopPMStates();
-
- int iBeamModelIndex = gEngfuncs.pEventAPI->EV_FindModelIndex( EGON_BEAM_SPRITE );
-
- float r = 50.0f;
- float g = 50.0f;
- float b = 125.0f;
-
- if ( IEngineStudio.IsHardware() )
- {
- r /= 100.0f;
- g /= 100.0f;
- }
-
-
- pBeam = gEngfuncs.pEfxAPI->R_BeamEntPoint ( idx | 0x1000, tr.endpos, iBeamModelIndex, 99999, 3.5, 0.2, 0.7, 55, 0, 0, r, g, b );
-
- if ( pBeam )
- pBeam->flags |= ( FBEAM_SINENOISE );
-
- pBeam2 = gEngfuncs.pEfxAPI->R_BeamEntPoint ( idx | 0x1000, tr.endpos, iBeamModelIndex, 99999, 5.0, 0.08, 0.7, 25, 0, 0, r, g, b );
- }
- }
-}
-
-void EV_EgonStop( event_args_t *args )
-{
- int idx;
- vec3_t origin;
-
- idx = args->entindex;
- VectorCopy ( args->origin, origin );
-
- gEngfuncs.pEventAPI->EV_StopSound( idx, CHAN_STATIC, EGON_SOUND_RUN );
-
- if ( args->iparam1 )
- gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, EGON_SOUND_OFF, 0.98, ATTN_NORM, 0, 100 );
-
- if ( EV_IsLocal( idx ) )
- {
- if ( pBeam )
- {
- pBeam->die = 0.0;
- pBeam = NULL;
- }
-
-
- if ( pBeam2 )
- {
- pBeam2->die = 0.0;
- pBeam2 = NULL;
- }
- }
-}
-//======================
-// EGON END
-//======================
-
-//======================
-// HORNET START
-//======================
-enum hgun_e {
- HGUN_IDLE1 = 0,
- HGUN_FIDGETSWAY,
- HGUN_FIDGETSHAKE,
- HGUN_DOWN,
- HGUN_UP,
- HGUN_SHOOT
-};
-
-void EV_HornetGunFire( event_args_t *args )
-{
- int idx, iFireMode;
- vec3_t origin, angles, vecSrc, forward, right, up;
-
- idx = args->entindex;
- VectorCopy( args->origin, origin );
- VectorCopy( args->angles, angles );
- iFireMode = args->iparam1;
-
- //Only play the weapon anims if I shot it.
- if ( EV_IsLocal( idx ) )
- {
- V_PunchAxis( 0, gEngfuncs.pfnRandomLong ( 0, 2 ) );
- gEngfuncs.pEventAPI->EV_WeaponAnimation ( HGUN_SHOOT, 1 );
- }
-
- switch ( gEngfuncs.pfnRandomLong ( 0 , 2 ) )
- {
- case 0: gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "agrunt/ag_fire1.wav", 1, ATTN_NORM, 0, 100 ); break;
- case 1: gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "agrunt/ag_fire2.wav", 1, ATTN_NORM, 0, 100 ); break;
- case 2: gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "agrunt/ag_fire3.wav", 1, ATTN_NORM, 0, 100 ); break;
- }
-}
-//======================
-// HORNET END
-//======================
-
-//======================
-// TRIPMINE START
-//======================
-enum tripmine_e {
- TRIPMINE_IDLE1 = 0,
- TRIPMINE_IDLE2,
- TRIPMINE_ARM1,
- TRIPMINE_ARM2,
- TRIPMINE_FIDGET,
- TRIPMINE_HOLSTER,
- TRIPMINE_DRAW,
- TRIPMINE_WORLD,
- TRIPMINE_GROUND,
-};
-
-//We only check if it's possible to put a trip mine
-//and if it is, then we play the animation. Server still places it.
-void EV_TripmineFire( event_args_t *args )
-{
- int idx;
- vec3_t vecSrc, angles, view_ofs, forward;
- pmtrace_t tr;
-
- idx = args->entindex;
- VectorCopy( args->origin, vecSrc );
- VectorCopy( args->angles, angles );
-
- AngleVectors ( angles, forward, NULL, NULL );
-
- if ( !EV_IsLocal ( idx ) )
- return;
-
- // Grab predicted result for local player
- gEngfuncs.pEventAPI->EV_LocalPlayerViewheight( view_ofs );
-
- vecSrc = vecSrc + view_ofs;
-
- // Store off the old count
- gEngfuncs.pEventAPI->EV_PushPMStates();
-
- // Now add in all of the players.
- gEngfuncs.pEventAPI->EV_SetSolidPlayers ( idx - 1 );
- gEngfuncs.pEventAPI->EV_SetTraceHull( 2 );
- gEngfuncs.pEventAPI->EV_PlayerTrace( vecSrc, vecSrc + forward * 128, PM_NORMAL, -1, &tr );
-
- //Hit something solid
- if ( tr.fraction < 1.0 )
- gEngfuncs.pEventAPI->EV_WeaponAnimation ( TRIPMINE_DRAW, 0 );
-
- gEngfuncs.pEventAPI->EV_PopPMStates();
-}
-//======================
-// TRIPMINE END
-//======================
-
-//======================
-// SQUEAK START
-//======================
-enum squeak_e {
- SQUEAK_IDLE1 = 0,
- SQUEAK_FIDGETFIT,
- SQUEAK_FIDGETNIP,
- SQUEAK_DOWN,
- SQUEAK_UP,
- SQUEAK_THROW
-};
-
-#define VEC_HULL_MIN Vector(-16, -16, -36)
-#define VEC_DUCK_HULL_MIN Vector(-16, -16, -18 )
-
-void EV_SnarkFire( event_args_t *args )
-{
- int idx;
- vec3_t vecSrc, angles, view_ofs, forward;
- pmtrace_t tr;
-
- idx = args->entindex;
- VectorCopy( args->origin, vecSrc );
- VectorCopy( args->angles, angles );
-
- AngleVectors ( angles, forward, NULL, NULL );
-
- if ( !EV_IsLocal ( idx ) )
- return;
-
- if ( args->ducking )
- vecSrc = vecSrc - ( VEC_HULL_MIN - VEC_DUCK_HULL_MIN );
-
- // Store off the old count
- gEngfuncs.pEventAPI->EV_PushPMStates();
-
- // Now add in all of the players.
- gEngfuncs.pEventAPI->EV_SetSolidPlayers ( idx - 1 );
- gEngfuncs.pEventAPI->EV_SetTraceHull( 2 );
- gEngfuncs.pEventAPI->EV_PlayerTrace( vecSrc + forward * 20, vecSrc + forward * 64, PM_NORMAL, -1, &tr );
-
- //Find space to drop the thing.
- if ( tr.allsolid == 0 && tr.startsolid == 0 && tr.fraction > 0.25 )
- gEngfuncs.pEventAPI->EV_WeaponAnimation ( SQUEAK_THROW, 0 );
-
- gEngfuncs.pEventAPI->EV_PopPMStates();
-}
-//======================
-// SQUEAK END
-//======================
-
-void EV_TrainPitchAdjust( event_args_t *args )
-{
- int idx;
- vec3_t origin;
-
- unsigned short us_params;
- int noise;
- float m_flVolume;
- int pitch;
- int stop;
-
- char sz[ 256 ];
-
- idx = args->entindex;
-
- VectorCopy( args->origin, origin );
-
- us_params = (unsigned short)args->iparam1;
- stop = args->bparam1;
-
- m_flVolume = (float)(us_params & 0x003f)/40.0;
- noise = (int)(((us_params) >> 12 ) & 0x0007);
- pitch = (int)( 10.0 * (float)( ( us_params >> 6 ) & 0x003f ) );
-
- switch ( noise )
- {
- case 1: strcpy( sz, "plats/ttrain1.wav"); break;
- case 2: strcpy( sz, "plats/ttrain2.wav"); break;
- case 3: strcpy( sz, "plats/ttrain3.wav"); break;
- case 4: strcpy( sz, "plats/ttrain4.wav"); break;
- case 5: strcpy( sz, "plats/ttrain6.wav"); break;
- case 6: strcpy( sz, "plats/ttrain7.wav"); break;
- default:
- // no sound
- strcpy( sz, "" );
- return;
- }
-
- if ( stop )
- {
- gEngfuncs.pEventAPI->EV_StopSound( idx, CHAN_STATIC, sz );
- }
- else
- {
- gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_STATIC, sz, m_flVolume, ATTN_NORM, SND_CHANGE_PITCH, pitch );
- }
-}
-
-int EV_TFC_IsAllyTeam( int iTeam1, int iTeam2 )
-{
- return 0;
-}
+/***
+*
+* Copyright (c) 1999, Valve LLC. All rights reserved.
+*
+* This product contains software technology licensed from Id
+* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
+* All Rights Reserved.
+*
+* Use, distribution, and modification of this source code and/or resulting
+* object code is restricted to non-commercial enhancements to products from
+* Valve LLC. All other use, distribution, or modification is prohibited
+* without written permission from Valve LLC.
+*
+****/
+//#include "hud.h"
+#include "mod/AvHHud.h"
+#include "cl_util.h"
+#include "common/const.h"
+#include "common/entity_state.h"
+#include "common/cl_entity.h"
+#include "common/entity_types.h"
+#include "common/usercmd.h"
+#include "pm_shared/pm_defs.h"
+#include "pm_shared/pm_materials.h"
+
+#include "eventscripts.h"
+#include "ev_hldm.h"
+
+#include "common/r_efx.h"
+#include "common/event_api.h"
+#include "common/event_args.h"
+#include "in_defs.h"
+#include "mod/AvHBasePlayerWeaponConstants.h"
+#include "mod/AvHMarineWeaponConstants.h"
+#include "mod/AvHAlienWeaponConstants.h"
+#include
+
+static int tracerCount[ 32 ];
+extern AvHHud gHUD;
+
+#include "r_studioint.h"
+#include "common/com_model.h"
+
+extern engine_studio_api_t IEngineStudio;
+
+//extern "C" char PM_FindTextureType( char *name );
+char PM_FindTextureType( char *name );
+
+void V_PunchAxis( int axis, float punch );
+void VectorAngles( const float *forward, float *angles );
+Vector UTIL_GetRandomSpreadDir(unsigned int inSeed, int inShotNumber, const Vector& inBaseDirection, const Vector& inRight, const Vector& inUp, const Vector& inSpread);
+
+extern "C"
+{
+
+// HLDM
+void EV_FireGlock1( struct event_args_s *args );
+void EV_FireGlock2( struct event_args_s *args );
+void EV_FireShotGunSingle( struct event_args_s *args );
+void EV_FireShotGunDouble( struct event_args_s *args );
+void EV_FireMP5( struct event_args_s *args );
+void EV_FireMP52( struct event_args_s *args );
+void EV_FirePython( struct event_args_s *args );
+void EV_FireGauss( struct event_args_s *args );
+void EV_SpinGauss( struct event_args_s *args );
+void EV_Crowbar( struct event_args_s *args );
+void EV_FireCrossbow( struct event_args_s *args );
+void EV_FireCrossbow2( struct event_args_s *args );
+void EV_FireRpg( struct event_args_s *args );
+void EV_EgonFire( struct event_args_s *args );
+void EV_EgonStop( struct event_args_s *args );
+void EV_HornetGunFire( struct event_args_s *args );
+void EV_TripmineFire( struct event_args_s *args );
+void EV_SnarkFire( struct event_args_s *args );
+
+
+void EV_TrainPitchAdjust( struct event_args_s *args );
+}
+
+#define VECTOR_CONE_1DEGREES Vector( 0.00873, 0.00873, 0.00873 )
+#define VECTOR_CONE_2DEGREES Vector( 0.01745, 0.01745, 0.01745 )
+#define VECTOR_CONE_3DEGREES Vector( 0.02618, 0.02618, 0.02618 )
+#define VECTOR_CONE_4DEGREES Vector( 0.03490, 0.03490, 0.03490 )
+#define VECTOR_CONE_5DEGREES Vector( 0.04362, 0.04362, 0.04362 )
+#define VECTOR_CONE_6DEGREES Vector( 0.05234, 0.05234, 0.05234 )
+#define VECTOR_CONE_7DEGREES Vector( 0.06105, 0.06105, 0.06105 )
+#define VECTOR_CONE_8DEGREES Vector( 0.06976, 0.06976, 0.06976 )
+#define VECTOR_CONE_9DEGREES Vector( 0.07846, 0.07846, 0.07846 )
+#define VECTOR_CONE_10DEGREES Vector( 0.08716, 0.08716, 0.08716 )
+#define VECTOR_CONE_15DEGREES Vector( 0.13053, 0.13053, 0.13053 )
+#define VECTOR_CONE_20DEGREES Vector( 0.17365, 0.17365, 0.17365 )
+
+// play a strike sound based on the texture that was hit by the attack traceline. VecSrc/VecEnd are the
+// original traceline endpoints used by the attacker, iBulletType is the type of bullet that hit the texture.
+// returns volume of strike instrument (crowbar) to play
+float EV_HLDM_PlayTextureSound( int idx, pmtrace_t *ptr, float *vecSrc, float *vecEnd, int iBulletType, int inSoundProbability)
+{
+ // hit the world, try to play sound based on texture material type
+ char chTextureType = CHAR_TEX_CONCRETE;
+ float fvol;
+ float fvolbar = 0.0f;
+ char *rgsz[4];
+ int cnt;
+ float fattn = ATTN_NORM;
+ int entity;
+ char *pTextureName;
+ char texname[ 64 ];
+ char szbuffer[ 64 ];
+
+ if(gEngfuncs.pfnRandomLong(1, inSoundProbability) == 1)
+ {
+
+ entity = gEngfuncs.pEventAPI->EV_IndexFromTrace( ptr );
+
+ // FIXME check if playtexture sounds movevar is set
+ //
+
+ chTextureType = 0;
+
+ // Player
+ if ( entity >= 1 && entity <= gEngfuncs.GetMaxClients() )
+ {
+ // hit body
+ chTextureType = CHAR_TEX_FLESH;
+ }
+ else if ( entity == 0 )
+ {
+ // get texture from entity or world (world is ent(0))
+ pTextureName = (char *)gEngfuncs.pEventAPI->EV_TraceTexture( ptr->ent, vecSrc, vecEnd );
+
+ if ( pTextureName )
+ {
+ strcpy( texname, pTextureName );
+ pTextureName = texname;
+
+ // strip leading '-0' or '+0~' or '{' or '!'
+ if (*pTextureName == '-' || *pTextureName == '+')
+ {
+ pTextureName += 2;
+ }
+
+ if (*pTextureName == '{' || *pTextureName == '!' || *pTextureName == '~' || *pTextureName == ' ')
+ {
+ pTextureName++;
+ }
+
+ // '}}'
+ strcpy( szbuffer, pTextureName );
+ szbuffer[ CBTEXTURENAMEMAX - 1 ] = 0;
+
+ // get texture type
+ chTextureType = PM_FindTextureType( szbuffer );
+ }
+ }
+
+ switch (chTextureType)
+ {
+ default:
+ case CHAR_TEX_CONCRETE: fvol = 0.3; fvolbar = 0.6;
+ rgsz[0] = "weapons/ric_conc-1.wav";
+ rgsz[1] = "weapons/ric_conc-2.wav";
+ cnt = 2;
+ break;
+ case CHAR_TEX_METAL: fvol = 0.3; fvolbar = 0.3;
+ rgsz[0] = "weapons/ric_metal-1.wav";
+ rgsz[1] = "weapons/ric_metal-2.wav";
+ cnt = 2;
+ break;
+ case CHAR_TEX_DIRT: fvol = 0.9; fvolbar = 0.1;
+ rgsz[0] = "player/pl_dirt1.wav";
+ rgsz[1] = "player/pl_dirt2.wav";
+ rgsz[2] = "player/pl_dirt3.wav";
+ cnt = 3;
+ break;
+ case CHAR_TEX_VENT: fvol = 0.5; fvolbar = 0.3;
+ rgsz[0] = "player/pl_duct1.wav";
+ rgsz[1] = "player/pl_duct1.wav";
+ cnt = 2;
+ break;
+ case CHAR_TEX_GRATE: fvol = 0.9; fvolbar = 0.5;
+ rgsz[0] = "player/pl_grate1.wav";
+ rgsz[1] = "player/pl_grate4.wav";
+ cnt = 2;
+ break;
+ case CHAR_TEX_TILE: fvol = 0.8; fvolbar = 0.2;
+ rgsz[0] = "player/pl_tile1.wav";
+ rgsz[1] = "player/pl_tile3.wav";
+ rgsz[2] = "player/pl_tile2.wav";
+ rgsz[3] = "player/pl_tile4.wav";
+ cnt = 4;
+ break;
+ case CHAR_TEX_SLOSH: fvol = 0.9; fvolbar = 0.0;
+ rgsz[0] = "player/pl_slosh1.wav";
+ rgsz[1] = "player/pl_slosh3.wav";
+ rgsz[2] = "player/pl_slosh2.wav";
+ rgsz[3] = "player/pl_slosh4.wav";
+ cnt = 4;
+ break;
+ case CHAR_TEX_WOOD: fvol = 0.9; fvolbar = 0.2;
+ rgsz[0] = "debris/wood1.wav";
+ rgsz[1] = "debris/wood2.wav";
+ rgsz[2] = "debris/wood3.wav";
+ cnt = 3;
+ break;
+ case CHAR_TEX_GLASS:
+ case CHAR_TEX_COMPUTER:
+ fvol = 0.8; fvolbar = 0.2;
+ rgsz[0] = "debris/glass1.wav";
+ rgsz[1] = "debris/glass2.wav";
+ rgsz[2] = "debris/glass3.wav";
+ cnt = 3;
+ break;
+ case CHAR_TEX_FLESH:
+ if (iBulletType == BULLET_PLAYER_CROWBAR)
+ return 0.0; // crowbar already makes this sound
+ fvol = 1.0; fvolbar = 0.2;
+ rgsz[0] = "weapons/bullet_hit1.wav";
+ rgsz[1] = "weapons/bullet_hit2.wav";
+ fattn = 1.0;
+ cnt = 2;
+ break;
+ }
+
+ if(iBulletType == BULLET_MONSTER_9MM)
+ {
+ fvol = 0.3;
+ fvolbar = 0.6;
+ rgsz[0] = "weapons/a_ric1.wav";
+ rgsz[1] = "weapons/a_ric2.wav";
+ rgsz[2] = "weapons/a_ric3.wav";
+ cnt = 3;
+ }
+
+ // play material hit sound
+ gEngfuncs.pEventAPI->EV_PlaySound( 0, ptr->endpos, CHAN_STATIC, rgsz[gEngfuncs.pfnRandomLong(0,cnt-1)], fvol, fattn, 0, 96 + gEngfuncs.pfnRandomLong(0,0xf) );
+ }
+
+ return fvolbar;
+}
+
+char *EV_HLDM_DamageDecal( physent_t *pe )
+{
+ static char decalname[ 32 ];
+ int idx;
+
+ if ( pe->classnumber == 1 )
+ {
+ idx = gEngfuncs.pfnRandomLong( 0, 2 );
+ sprintf( decalname, "{break%i", idx + 1 );
+ }
+ else if ( pe->rendermode != kRenderNormal )
+ {
+ sprintf( decalname, "{bproof1" );
+ }
+ else
+ {
+ idx = gEngfuncs.pfnRandomLong( 0, 4 );
+ sprintf( decalname, "{shot%i", idx + 1 );
+ }
+ return decalname;
+}
+
+void EV_HLDM_GunshotDecalTrace( pmtrace_t *pTrace, char *decalName, int inChanceOfSound)
+{
+ int iRand;
+ physent_t *pe;
+
+ gEngfuncs.pEfxAPI->R_BulletImpactParticles( pTrace->endpos );
+
+ iRand = gEngfuncs.pfnRandomLong(1, inChanceOfSound);
+ if ( iRand == 1)// not every bullet makes a sound.
+ {
+ const float kRicochetVolume = .2f;
+ int theRandomSound = gEngfuncs.pfnRandomLong(0, 4);
+ switch(theRandomSound)
+ {
+ case 0: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "weapons/ric1.wav", kRicochetVolume, ATTN_NORM, 0, PITCH_NORM ); break;
+ case 1: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "weapons/ric2.wav", kRicochetVolume, ATTN_NORM, 0, PITCH_NORM ); break;
+ case 2: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "weapons/ric3.wav", kRicochetVolume, ATTN_NORM, 0, PITCH_NORM ); break;
+ case 3: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "weapons/ric4.wav", kRicochetVolume, ATTN_NORM, 0, PITCH_NORM ); break;
+ case 4: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "weapons/ric5.wav", kRicochetVolume, ATTN_NORM, 0, PITCH_NORM ); break;
+ }
+ }
+
+ pe = gEngfuncs.pEventAPI->EV_GetPhysent( pTrace->ent );
+
+ // Only decal brush models such as the world etc.
+ if ( decalName && decalName[0] && pe && ( pe->solid == SOLID_BSP || pe->movetype == MOVETYPE_PUSHSTEP ) )
+ {
+ if ( CVAR_GET_FLOAT( "r_decals" ) )
+ {
+ gEngfuncs.pEfxAPI->R_DecalShoot(
+ gEngfuncs.pEfxAPI->Draw_DecalIndex( gEngfuncs.pEfxAPI->Draw_DecalIndexFromName( decalName ) ),
+ gEngfuncs.pEventAPI->EV_IndexFromTrace( pTrace ), 0, pTrace->endpos, 0 );
+ }
+ }
+}
+
+void EV_HLDM_DecalGunshot( pmtrace_t *pTrace, int iBulletType, int inSoundProbability)
+{
+ physent_t *pe;
+
+ pe = gEngfuncs.pEventAPI->EV_GetPhysent( pTrace->ent );
+
+ if ( pe && pe->solid == SOLID_BSP )
+ {
+ EV_HLDM_GunshotDecalTrace( pTrace, EV_HLDM_DamageDecal( pe ), inSoundProbability);
+ }
+}
+
+int EV_HLDM_CheckTracer( int idx, float *vecSrc, float *end, float *forward, float *right, int iBulletType, int iTracerFreq, int *tracerCount )
+{
+ int tracer = 0;
+ int i;
+ qboolean player = idx >= 1 && idx <= gEngfuncs.GetMaxClients() ? true : false;
+
+ if ( iTracerFreq != 0 && ( (*tracerCount)++ % iTracerFreq) == 0 )
+ {
+ vec3_t vecTracerSrc;
+
+ if ( player )
+ {
+ vec3_t offset( 0, 0, -4 );
+
+ // adjust tracer position for player
+ for ( i = 0; i < 3; i++ )
+ {
+ vecTracerSrc[ i ] = vecSrc[ i ] + offset[ i ] + right[ i ] * 2 + forward[ i ] * 16;
+ }
+ }
+ else
+ {
+ VectorCopy( vecSrc, vecTracerSrc );
+ }
+
+ if ( iTracerFreq != 1 ) // guns that always trace also always decal
+ tracer = 1;
+
+ switch( iBulletType )
+ {
+ case BULLET_PLAYER_MP5:
+ case BULLET_MONSTER_MP5:
+ case BULLET_MONSTER_9MM:
+ case BULLET_MONSTER_12MM:
+ default:
+ EV_CreateTracer( vecTracerSrc, end );
+ break;
+ }
+ }
+
+ return tracer;
+}
+
+
+/*
+================
+FireBullets
+
+Go to the trouble of combining multiple pellets into a single damage call.
+================
+*/
+//void EV_HLDM_FireBullets( int idx, float *forward, float *right, float *up, int cShots, float *vecSrc, float *vecDirShooting, float flDistance, int iBulletType, int iTracerFreq, int *tracerCount, float flSpreadX, float flSpreadY )
+//{
+// int i;
+// int iShot;
+// int tracer;
+//
+// // Store off the old count
+// gEngfuncs.pEventAPI->EV_PushPMStates();
+//
+// gEngfuncs.pEventAPI->EV_SetUpPlayerPrediction(false, true);
+//
+// // Now add in all of the players.
+// gEngfuncs.pEventAPI->EV_SetSolidPlayers ( idx - 1 );
+//
+// gEngfuncs.pEventAPI->EV_SetTraceHull( 2 );
+//
+// for ( iShot = 1; iShot <= cShots; iShot++ )
+// {
+// vec3_t vecDir, vecEnd;
+//
+// float x, y, z;
+// //We randomize for the Shotgun.
+// if ( iBulletType == BULLET_PLAYER_BUCKSHOT )
+// {
+// do {
+// x = gEngfuncs.pfnRandomFloat(-0.5,0.5) + gEngfuncs.pfnRandomFloat(-0.5,0.5);
+// y = gEngfuncs.pfnRandomFloat(-0.5,0.5) + gEngfuncs.pfnRandomFloat(-0.5,0.5);
+// z = x*x+y*y;
+// } while (z > 1);
+//
+// for ( i = 0 ; i < 3; i++ )
+// {
+// vecDir[i] = vecDirShooting[i] + x * flSpreadX * right[ i ] + y * flSpreadY * up [ i ];
+// vecEnd[i] = vecSrc[ i ] + flDistance * vecDir[ i ];
+// }
+// }//But other guns already have their spread randomized in the synched spread.
+// else
+// {
+//
+// for ( i = 0 ; i < 3; i++ )
+// {
+// vecDir[i] = vecDirShooting[i] + flSpreadX * right[ i ] + flSpreadY * up [ i ];
+// vecEnd[i] = vecSrc[ i ] + flDistance * vecDir[ i ];
+// }
+// }
+//
+// // For debugging
+// //gEngfuncs.pEfxAPI->R_TracerEffect(vecSrc, vecEnd);
+//
+// pmtrace_t tr;
+// gEngfuncs.pEventAPI->EV_PlayerTrace( vecSrc, vecEnd, PM_STUDIO_BOX, -1, &tr );
+//
+// //gEngfuncs.pEfxAPI->R_BulletImpactParticles(tr.endpos);
+//
+// tracer = EV_HLDM_CheckTracer( idx, vecSrc, tr.endpos, forward, right, iBulletType, iTracerFreq, tracerCount );
+//
+// physent_t *pe = gEngfuncs.pEventAPI->EV_GetPhysent( tr.ent );
+// bool thePlayBulletHitEffect = /*true;//*/!tr.inwater && pe && !pe->player;
+//
+// // do damage, paint decals
+// if ( tr.fraction != 1.0 )
+// {
+// switch(iBulletType)
+// {
+// default:
+// case BULLET_PLAYER_9MM:
+//
+// //EV_HLDM_PlayTextureSound( idx, &tr, vecSrc, vecEnd, iBulletType );
+// EV_HLDM_DecalGunshot( &tr, iBulletType );
+//
+// break;
+// case BULLET_PLAYER_MP5:
+//
+// if ( !tracer )
+// {
+// //EV_HLDM_PlayTextureSound( idx, &tr, vecSrc, vecEnd, iBulletType );
+// EV_HLDM_DecalGunshot( &tr, iBulletType );
+//
+// // Only play weapon effects if we hit the
+// if(thePlayBulletHitEffect)
+// {
+// //int theSprite = gEngfuncs.pEventAPI->EV_FindModelIndex(kGenericWallpuff);
+// //TEMPENTITY* theTempEntity = gEngfuncs.pEfxAPI->R_TempSprite(tr.endpos, vec3_origin, .6f, theSprite, kRenderGlow, kRenderFxNoDissipation, .5, 1.0, FTENT_COLLIDEALL | FTENT_SPRANIMATE | FTENT_SPRANIMATELOOP | FTENT_PERSIST);
+// //theTempEntity->entity.curstate.framerate = 30;
+//
+// gEngfuncs.pEfxAPI->R_SparkEffect(tr.endpos, 6, 10, 100);
+// }
+// }
+// break;
+// case BULLET_PLAYER_BUCKSHOT:
+// if ( !tracer )
+// {
+// EV_HLDM_DecalGunshot( &tr, iBulletType );
+//
+// // Add cool shotgun effect here
+// //gEngfuncs.pEfxAPI->R_RocketTrail(vecSrc, tr.endpos, 1);
+// gEngfuncs.pEfxAPI->R_BulletImpactParticles(tr.endpos);
+//
+// //if(thePlayBulletHitEffect)
+// //{
+// // int theSprite = gEngfuncs.pEventAPI->EV_FindModelIndex(kGenericWallpuff);
+// // TEMPENTITY* theTempEntity = gEngfuncs.pEfxAPI->R_TempSprite(tr.endpos, vec3_origin, 1.0f, theSprite, kRenderGlow, kRenderFxNoDissipation, .5, 1.0, FTENT_COLLIDEALL | FTENT_SPRANIMATE | FTENT_SPRANIMATELOOP | FTENT_PERSIST);
+// // theTempEntity->entity.curstate.framerate = 30;
+// //}
+//
+// gEngfuncs.pEfxAPI->R_SparkEffect(tr.endpos, 5, 100, 200);
+// }
+// break;
+// case BULLET_PLAYER_357:
+// if ( !tracer )
+// {
+// //EV_HLDM_PlayTextureSound( idx, &tr, vecSrc, vecEnd, iBulletType );
+// EV_HLDM_DecalGunshot( &tr, iBulletType );
+//
+// if(thePlayBulletHitEffect)
+// {
+// // Make the smoke stick out of the target or wall just a little bit to avoid crappy sprite-in-wall effect
+// Vector theEndPos = tr.endpos - 20*vecDir;
+// int theSprite = gEngfuncs.pEventAPI->EV_FindModelIndex(kGenericWallpuff);
+// Vector theUp(0, 0, 30);
+// TEMPENTITY* theTempEntity = gEngfuncs.pEfxAPI->R_TempSprite(theEndPos, theUp, .3f, theSprite, kRenderTransAdd, kRenderFxFadeSlow, .3, 0.6, FTENT_COLLIDEALL | FTENT_SPRANIMATE | FTENT_SPRANIMATELOOP | FTENT_PERSIST);
+// if(theTempEntity)
+// {
+// theTempEntity->entity.curstate.framerate = 50;
+// }
+//
+// //// Create rising area of smoke above gun wielder
+// //if(gEngfuncs.pfnRandomLong(0, 3) == 0)
+// //{
+// // vec3_t theSource;
+// // VectorCopy(vecSrc, theSource);
+// // theSource.z += 60;
+// // theSource.z += 60;
+// //
+// // theTempEntity = gEngfuncs.pEfxAPI->R_TempSprite(vecSrc, vec3_origin, 1.0f, theSprite, kRenderGlow, kRenderFxNoDissipation, .3, 3.0, FTENT_COLLIDEALL | FTENT_SPRANIMATE | FTENT_SPRANIMATELOOP | FTENT_PERSIST);
+// // theTempEntity->entity.curstate.framerate = 30;
+// //}
+//
+// // TODO: Add more here like splinters of wall and plaster
+// gEngfuncs.pEfxAPI->R_SparkEffect(tr.endpos, 12, 100, 200);
+// }
+// }
+// break;
+// case BULLET_MONSTER_9MM:
+// break;
+// }
+// }
+// }
+//
+// gEngfuncs.pEventAPI->EV_PopPMStates();
+//}
+
+/*
+================
+EV_HLDM_FireBulletsPlayer
+
+Client-side prediction friendly version of EV_HLDM_FireBullets
+================
+*/
+void EV_HLDM_FireBulletsPlayer( int idx, float *forward, float *right, float *up, int cShots, float *vecSrc, float *vecDirShooting, float flDistance, int iBulletType, int iTracerFreq, int *tracerCount, Vector inSpread, int inRandomSeed)
+{
+// int i;
+ int iShot;
+ int tracer;
+
+ // Store off the old count
+ gEngfuncs.pEventAPI->EV_PushPMStates();
+
+ gEngfuncs.pEventAPI->EV_SetUpPlayerPrediction(false, true);
+
+ // Now add in all of the players.
+ gEngfuncs.pEventAPI->EV_SetSolidPlayers ( idx - 1 );
+
+ gEngfuncs.pEventAPI->EV_SetTraceHull( 2 );
+
+ for ( iShot = 1; iShot <= cShots; iShot++ )
+ {
+ vec3_t vecDir, vecEnd;
+
+// float x, y, z;
+// //We randomize for the Shotgun.
+// if ( iBulletType == BULLET_PLAYER_BUCKSHOT )
+// {
+// do {
+// x = gEngfuncs.pfnRandomFloat(-0.5,0.5) + gEngfuncs.pfnRandomFloat(-0.5,0.5);
+// y = gEngfuncs.pfnRandomFloat(-0.5,0.5) + gEngfuncs.pfnRandomFloat(-0.5,0.5);
+// z = x*x+y*y;
+// } while (z > 1);
+//
+// for ( i = 0 ; i < 3; i++ )
+// {
+// vecDir[i] = vecDirShooting[i] + x * flSpreadX * right[ i ] + y * flSpreadY * up [ i ];
+// vecEnd[i] = vecSrc[ i ] + flDistance * vecDir[ i ];
+// }
+// }//But other guns already have their spread randomized in the synched spread.
+// else
+// {
+
+ //for ( i = 0 ; i < 3; i++ )
+ //{
+ // vecDir[i] = vecDirShooting[i] + flSpreadX * right[ i ] + flSpreadY * up [ i ];
+ // vecEnd[i] = vecSrc[ i ] + flDistance * vecDir[ i ];
+ //}
+ vecDir = UTIL_GetRandomSpreadDir(inRandomSeed, iShot, vecDirShooting, right, up, inSpread);
+ VectorMA(vecSrc, flDistance, vecDir, vecEnd);
+ //vecEnd = vecSrc + flDistance*vecDir;
+// }
+
+ // For debugging
+ //gEngfuncs.pEfxAPI->R_TracerEffect(vecSrc, vecEnd);
+
+ pmtrace_t tr;
+ gEngfuncs.pEventAPI->EV_PlayerTrace( vecSrc, vecEnd, PM_STUDIO_BOX, -1, &tr );
+
+ //gEngfuncs.pEfxAPI->R_BulletImpactParticles(tr.endpos);
+
+ tracer = EV_HLDM_CheckTracer( idx, vecSrc, tr.endpos, forward, right, iBulletType, iTracerFreq, tracerCount );
+
+ physent_t *pe = gEngfuncs.pEventAPI->EV_GetPhysent( tr.ent );
+ bool thePlayBulletHitEffect = /*true;//*/!tr.inwater && pe && !pe->player;
+ int theSoundProbability = 2;
+
+ // do damage, paint decals
+ if ( tr.fraction != 1.0 )
+ {
+ switch(iBulletType)
+ {
+ default:
+ case BULLET_PLAYER_9MM:
+ EV_HLDM_PlayTextureSound( idx, &tr, vecSrc, vecEnd, iBulletType, theSoundProbability);
+ EV_HLDM_DecalGunshot( &tr, iBulletType, theSoundProbability);
+ break;
+
+ case BULLET_PLAYER_MP5:
+
+ if ( !tracer )
+ {
+ EV_HLDM_PlayTextureSound( idx, &tr, vecSrc, vecEnd, iBulletType, theSoundProbability);
+
+ theSoundProbability = 8;
+ EV_HLDM_DecalGunshot( &tr, iBulletType, theSoundProbability);
+
+ // Only play weapon effects if we hit the
+ if(thePlayBulletHitEffect)
+ {
+ // Make the smoke stick out of the target or wall just a little bit to avoid crappy sprite-in-wall effect
+ Vector theEndPos = tr.endpos - 20*vecDir;
+ int theSprite = gEngfuncs.pEventAPI->EV_FindModelIndex(kGenericWallpuff);
+ Vector theUp(0, 0, 30);
+ TEMPENTITY* theTempEntity = gEngfuncs.pEfxAPI->R_TempSprite(theEndPos, theUp, .3f, theSprite, kRenderTransAdd, kRenderFxFadeSlow, .1, 0.6, FTENT_COLLIDEALL | FTENT_SPRANIMATE | FTENT_SPRANIMATELOOP | FTENT_PERSIST);
+ if(theTempEntity)
+ {
+ theTempEntity->entity.curstate.framerate = 50;
+ }
+
+ gEngfuncs.pEfxAPI->R_SparkEffect(tr.endpos, 6, 10, 100);
+ }
+ }
+ break;
+ case BULLET_PLAYER_BUCKSHOT:
+ if ( !tracer )
+ {
+ theSoundProbability = BALANCE_VAR(kSGBulletsPerShot)/2;
+ EV_HLDM_PlayTextureSound( idx, &tr, vecSrc, vecEnd, iBulletType, theSoundProbability);
+
+ theSoundProbability = BALANCE_VAR(kSGBulletsPerShot)/2;
+ EV_HLDM_DecalGunshot( &tr, iBulletType, theSoundProbability);
+
+ if(thePlayBulletHitEffect)
+ {
+ // Add cool shotgun effect here
+ //gEngfuncs.pEfxAPI->R_RocketTrail(vecSrc, tr.endpos, 1);
+ gEngfuncs.pEfxAPI->R_BulletImpactParticles(tr.endpos);
+
+ //if(thePlayBulletHitEffect)
+ //{
+ // int theSprite = gEngfuncs.pEventAPI->EV_FindModelIndex(kGenericWallpuff);
+ // TEMPENTITY* theTempEntity = gEngfuncs.pEfxAPI->R_TempSprite(tr.endpos, vec3_origin, 1.0f, theSprite, kRenderGlow, kRenderFxNoDissipation, .5, 1.0, FTENT_COLLIDEALL | FTENT_SPRANIMATE | FTENT_SPRANIMATELOOP | FTENT_PERSIST);
+ // theTempEntity->entity.curstate.framerate = 30;
+ //}
+
+ gEngfuncs.pEfxAPI->R_SparkEffect(tr.endpos, 5, 100, 200);
+ }
+ }
+ break;
+ case BULLET_PLAYER_357:
+ if ( !tracer )
+ {
+ theSoundProbability = 1;
+ EV_HLDM_PlayTextureSound( idx, &tr, vecSrc, vecEnd, iBulletType, theSoundProbability);
+ EV_HLDM_DecalGunshot( &tr, iBulletType, theSoundProbability);
+
+ if(thePlayBulletHitEffect)
+ {
+ // Make the smoke stick out of the target or wall just a little bit to avoid crappy sprite-in-wall effect
+ Vector theEndPos = tr.endpos - 20*vecDir;
+ int theSprite = gEngfuncs.pEventAPI->EV_FindModelIndex(kGenericWallpuff);
+ Vector theUp(0, 0, 30);
+ TEMPENTITY* theTempEntity = gEngfuncs.pEfxAPI->R_TempSprite(theEndPos, theUp, .3f, theSprite, kRenderTransAdd, kRenderFxFadeSlow, .15, 0.6, FTENT_COLLIDEALL | FTENT_SPRANIMATE | FTENT_SPRANIMATELOOP | FTENT_PERSIST);
+ if(theTempEntity)
+ {
+ theTempEntity->entity.curstate.framerate = 50;
+ }
+
+ //// Create rising area of smoke above gun wielder
+ //if(gEngfuncs.pfnRandomLong(0, 3) == 0)
+ //{
+ // vec3_t theSource;
+ // VectorCopy(vecSrc, theSource);
+ // theSource.z += 60;
+ // theSource.z += 60;
+ //
+ // theTempEntity = gEngfuncs.pEfxAPI->R_TempSprite(vecSrc, vec3_origin, 1.0f, theSprite, kRenderGlow, kRenderFxNoDissipation, .3, 3.0, FTENT_COLLIDEALL | FTENT_SPRANIMATE | FTENT_SPRANIMATELOOP | FTENT_PERSIST);
+ // theTempEntity->entity.curstate.framerate = 30;
+ //}
+
+ // TODO: Add more here like splinters of wall and plaster
+ gEngfuncs.pEfxAPI->R_SparkEffect(tr.endpos, 12, 100, 200);
+ }
+ }
+ break;
+ case BULLET_MONSTER_9MM:
+ if(!tracer)
+ {
+ EV_HLDM_PlayTextureSound( idx, &tr, vecSrc, vecEnd, iBulletType, theSoundProbability);
+ //EV_HLDM_DecalGunshot( &tr, iBulletType, theSoundProbability);
+
+ // Only play weapon effects if we hit the
+ if(thePlayBulletHitEffect)
+ {
+ int theSprite = gEngfuncs.pEventAPI->EV_FindModelIndex(kSpikeGunHitSprite);
+ TEMPENTITY* theTempEntity = gEngfuncs.pEfxAPI->R_TempSprite(tr.endpos, vec3_origin, .6f, theSprite, kRenderTransAdd, kRenderFxNoDissipation, .5f, .4f, FTENT_COLLIDEALL | FTENT_SPRANIMATE | FTENT_SPRANIMATELOOP | FTENT_PERSIST);
+ if(theTempEntity)
+ {
+ theTempEntity->entity.curstate.framerate = 30;
+ }
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ gEngfuncs.pEventAPI->EV_PopPMStates();
+}
+
+
+
+//======================
+// GLOCK START
+//======================
+//void EV_FireGlock1( event_args_t *args )
+//{
+// int idx;
+// vec3_t origin;
+// vec3_t angles;
+// vec3_t velocity;
+// int empty;
+//
+// vec3_t ShellVelocity;
+// vec3_t ShellOrigin;
+// int shell;
+// vec3_t vecSrc, vecAiming;
+// vec3_t up, right, forward;
+//
+// idx = args->entindex;
+// VectorCopy( args->origin, origin );
+// VectorCopy( args->angles, angles );
+// VectorCopy( args->velocity, velocity );
+//
+// empty = args->bparam1;
+// AngleVectors( angles, forward, right, up );
+//
+// shell = gEngfuncs.pEventAPI->EV_FindModelIndex ("models/shell.mdl");// brass shell
+//
+// if ( EV_IsLocal( idx ) )
+// {
+// EV_MuzzleFlash();
+// gEngfuncs.pEventAPI->EV_WeaponAnimation( empty ? GLOCK_SHOOT_EMPTY : GLOCK_SHOOT, 2 );
+//
+// V_PunchAxis( 0, -2.0 );
+// }
+//
+// EV_GetDefaultShellInfo( args, origin, velocity, ShellVelocity, ShellOrigin, forward, right, up, 20, -12, 4 );
+//
+// EV_EjectBrass ( ShellOrigin, ShellVelocity, angles[ YAW ], shell, TE_BOUNCE_SHELL );
+//
+// gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/pl_gun3.wav", gEngfuncs.pfnRandomFloat(0.92, 1.0), ATTN_NORM, 0, 98 + gEngfuncs.pfnRandomLong( 0, 3 ) );
+//
+// EV_GetGunPosition( args, vecSrc, origin );
+//
+// VectorCopy( forward, vecAiming );
+//
+// EV_HLDM_FireBullets( idx, forward, right, up, 1, vecSrc, vecAiming, 8192, BULLET_PLAYER_9MM, 0, 0, args->fparam1, args->fparam2);
+//}
+
+//void EV_FireGlock2( event_args_t *args )
+//{
+// int idx;
+// vec3_t origin;
+// vec3_t angles;
+// vec3_t velocity;
+//
+// vec3_t ShellVelocity;
+// vec3_t ShellOrigin;
+// int shell;
+// vec3_t vecSrc, vecAiming;
+// vec3_t vecSpread;
+// vec3_t up, right, forward;
+//
+// idx = args->entindex;
+// VectorCopy( args->origin, origin );
+// VectorCopy( args->angles, angles );
+// VectorCopy( args->velocity, velocity );
+//
+// AngleVectors( angles, forward, right, up );
+//
+// shell = gEngfuncs.pEventAPI->EV_FindModelIndex ("models/shell.mdl");// brass shell
+//
+// if ( EV_IsLocal( idx ) )
+// {
+// // Add muzzle flash to current weapon model
+// EV_MuzzleFlash();
+// gEngfuncs.pEventAPI->EV_WeaponAnimation( GLOCK_SHOOT, 2 );
+//
+// V_PunchAxis( 0, -2.0 );
+// }
+//
+// EV_GetDefaultShellInfo( args, origin, velocity, ShellVelocity, ShellOrigin, forward, right, up, 20, -12, 4 );
+//
+// EV_EjectBrass ( ShellOrigin, ShellVelocity, angles[ YAW ], shell, TE_BOUNCE_SHELL );
+//
+// gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/pl_gun3.wav", gEngfuncs.pfnRandomFloat(0.92, 1.0), ATTN_NORM, 0, 98 + gEngfuncs.pfnRandomLong( 0, 3 ) );
+//
+// EV_GetGunPosition( args, vecSrc, origin );
+//
+// VectorCopy( forward, vecAiming );
+//
+// EV_HLDM_FireBullets( idx, forward, right, up, 1, vecSrc, vecAiming, 8192, BULLET_PLAYER_9MM, 0, &tracerCount[idx-1], args->fparam1, args->fparam2 );
+//
+//}
+//======================
+// GLOCK END
+//======================
+
+//======================
+// SHOTGUN START
+//======================
+//void EV_FireShotGunDouble( event_args_t *args )
+//{
+// int idx;
+// vec3_t origin;
+// vec3_t angles;
+// vec3_t velocity;
+//
+// int j;
+// vec3_t ShellVelocity;
+// vec3_t ShellOrigin;
+// int shell;
+// vec3_t vecSrc, vecAiming;
+// vec3_t vecSpread;
+// vec3_t up, right, forward;
+// float flSpread = 0.01;
+//
+// idx = args->entindex;
+// VectorCopy( args->origin, origin );
+// VectorCopy( args->angles, angles );
+// VectorCopy( args->velocity, velocity );
+//
+// AngleVectors( angles, forward, right, up );
+//
+// shell = gEngfuncs.pEventAPI->EV_FindModelIndex ("models/shotgunshell.mdl");// brass shell
+//
+// if ( EV_IsLocal( idx ) )
+// {
+// // Add muzzle flash to current weapon model
+// EV_MuzzleFlash();
+// gEngfuncs.pEventAPI->EV_WeaponAnimation( SHOTGUN_FIRE2, 2 );
+// V_PunchAxis( 0, -10.0 );
+// }
+//
+// for ( j = 0; j < 2; j++ )
+// {
+// EV_GetDefaultShellInfo( args, origin, velocity, ShellVelocity, ShellOrigin, forward, right, up, 32, -12, 6 );
+//
+// EV_EjectBrass ( ShellOrigin, ShellVelocity, angles[ YAW ], shell, TE_BOUNCE_SHOTSHELL );
+// }
+//
+// gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/dbarrel1.wav", gEngfuncs.pfnRandomFloat(0.98, 1.0), ATTN_NORM, 0, 85 + gEngfuncs.pfnRandomLong( 0, 0x1f ) );
+//
+// EV_GetGunPosition( args, vecSrc, origin );
+// VectorCopy( forward, vecAiming );
+//
+// if ( gEngfuncs.GetMaxClients() > 1 )
+// {
+// EV_HLDM_FireBullets( idx, forward, right, up, 8, vecSrc, vecAiming, 2048, BULLET_PLAYER_BUCKSHOT, 0, &tracerCount[idx-1], 0.17365, 0.04362 );
+// }
+// else
+// {
+// EV_HLDM_FireBullets( idx, forward, right, up, 12, vecSrc, vecAiming, 2048, BULLET_PLAYER_BUCKSHOT, 0, &tracerCount[idx-1], 0.08716, 0.08716 );
+// }
+//
+// if ( EV_IsLocal( idx ) )
+// {
+// V_PunchAxis( 0, -10.0 );
+// }
+//}
+
+//void EV_FireShotGunSingle( event_args_t *args )
+//{
+// int idx;
+// vec3_t origin;
+// vec3_t angles;
+// vec3_t velocity;
+//
+// vec3_t ShellVelocity;
+// vec3_t ShellOrigin;
+// int shell;
+// vec3_t vecSrc, vecAiming;
+// vec3_t vecSpread;
+// vec3_t up, right, forward;
+// float flSpread = 0.01;
+//
+// idx = args->entindex;
+// VectorCopy( args->origin, origin );
+// VectorCopy( args->angles, angles );
+// VectorCopy( args->velocity, velocity );
+//
+// AngleVectors( angles, forward, right, up );
+//
+// shell = gEngfuncs.pEventAPI->EV_FindModelIndex ("models/shotgunshell.mdl");// brass shell
+//
+// if ( EV_IsLocal( idx ) )
+// {
+// // Add muzzle flash to current weapon model
+// EV_MuzzleFlash();
+// gEngfuncs.pEventAPI->EV_WeaponAnimation( SHOTGUN_FIRE, 2 );
+//
+// V_PunchAxis( 0, -5.0 );
+// }
+//
+// EV_GetDefaultShellInfo( args, origin, velocity, ShellVelocity, ShellOrigin, forward, right, up, 32, -12, 6 );
+//
+// EV_EjectBrass ( ShellOrigin, ShellVelocity, angles[ YAW ], shell, TE_BOUNCE_SHOTSHELL );
+//
+// gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/sbarrel1.wav", gEngfuncs.pfnRandomFloat(0.95, 1.0), ATTN_NORM, 0, 93 + gEngfuncs.pfnRandomLong( 0, 0x1f ) );
+//
+// EV_GetGunPosition( args, vecSrc, origin );
+// VectorCopy( forward, vecAiming );
+//
+// if ( gEngfuncs.GetMaxClients() > 1 )
+// {
+// EV_HLDM_FireBullets( idx, forward, right, up, 4, vecSrc, vecAiming, 2048, BULLET_PLAYER_BUCKSHOT, 0, &tracerCount[idx-1], 0.08716, 0.04362 );
+// }
+// else
+// {
+// EV_HLDM_FireBullets( idx, forward, right, up, 6, vecSrc, vecAiming, 2048, BULLET_PLAYER_BUCKSHOT, 0, &tracerCount[idx-1], 0.08716, 0.08716 );
+// }
+//}
+//======================
+// SHOTGUN END
+//======================
+
+//======================
+// MP5 START
+//======================
+//void EV_FireMP5( event_args_t *args )
+//{
+// int idx;
+// vec3_t origin;
+// vec3_t angles;
+// vec3_t velocity;
+//
+// vec3_t ShellVelocity;
+// vec3_t ShellOrigin;
+// int shell;
+// vec3_t vecSrc, vecAiming;
+// vec3_t up, right, forward;
+// float flSpread = 0.01;
+//
+// idx = args->entindex;
+// VectorCopy( args->origin, origin );
+// VectorCopy( args->angles, angles );
+// VectorCopy( args->velocity, velocity );
+//
+// AngleVectors( angles, forward, right, up );
+//
+// shell = gEngfuncs.pEventAPI->EV_FindModelIndex ("models/shell.mdl");// brass shell
+//
+// if ( EV_IsLocal( idx ) )
+// {
+// // Add muzzle flash to current weapon model
+// EV_MuzzleFlash();
+// gEngfuncs.pEventAPI->EV_WeaponAnimation( MG_FIRE1 + gEngfuncs.pfnRandomLong(0,2), 2 );
+// }
+//
+// EV_GetDefaultShellInfo( args, origin, velocity, ShellVelocity, ShellOrigin, forward, right, up, 20, -12, 4 );
+//
+// EV_EjectBrass ( ShellOrigin, ShellVelocity, angles[ YAW ], shell, TE_BOUNCE_SHELL );
+//
+// switch( gEngfuncs.pfnRandomLong( 0, 1 ) )
+// {
+// case 0:
+// gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/hks1.wav", 1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ) );
+// break;
+// case 1:
+// gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/hks2.wav", 1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ) );
+// break;
+// }
+//
+// EV_GetGunPosition( args, vecSrc, origin );
+// VectorCopy( forward, vecAiming );
+//
+// if ( gEngfuncs.GetMaxClients() > 1 )
+// {
+// EV_HLDM_FireBullets( idx, forward, right, up, 1, vecSrc, vecAiming, 8192, BULLET_PLAYER_MP5, 2, &tracerCount[idx-1], args->fparam1, args->fparam2 );
+// }
+// else
+// {
+// EV_HLDM_FireBullets( idx, forward, right, up, 1, vecSrc, vecAiming, 8192, BULLET_PLAYER_MP5, 2, &tracerCount[idx-1], args->fparam1, args->fparam2 );
+// }
+//}
+
+// We only predict the animation and sound
+// The grenade is still launched from the server.
+//void EV_FireMP52( event_args_t *args )
+//{
+// int idx;
+// vec3_t origin;
+//
+// idx = args->entindex;
+// VectorCopy( args->origin, origin );
+//
+// if ( EV_IsLocal( idx ) )
+// {
+// // NOTE: Put this back in if needed <<< cgc >>>
+// //gEngfuncs.pEventAPI->EV_WeaponAnimation( MP5_LAUNCH, 2 );
+// //V_PunchAxis( 0, -10 );
+// }
+//
+// switch( gEngfuncs.pfnRandomLong( 0, 1 ) )
+// {
+// case 0:
+// gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/glauncher.wav", 1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ) );
+// break;
+// case 1:
+// gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/glauncher2.wav", 1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ) );
+// break;
+// }
+//}
+//======================
+// MP5 END
+//======================
+
+//======================
+// PHYTON START
+// ( .357 )
+//======================
+//void EV_FirePython( event_args_t *args )
+//{
+// int idx;
+// vec3_t origin;
+// vec3_t angles;
+// vec3_t velocity;
+//
+// vec3_t vecSrc, vecAiming;
+// vec3_t up, right, forward;
+// float flSpread = 0.01;
+//
+// idx = args->entindex;
+// VectorCopy( args->origin, origin );
+// VectorCopy( args->angles, angles );
+// VectorCopy( args->velocity, velocity );
+//
+// AngleVectors( angles, forward, right, up );
+//
+// if ( EV_IsLocal( idx ) )
+// {
+// // Python uses different body in multiplayer versus single player
+// int multiplayer = gEngfuncs.GetMaxClients() == 1 ? 0 : 1;
+//
+// // Add muzzle flash to current weapon model
+// EV_MuzzleFlash();
+// gEngfuncs.pEventAPI->EV_WeaponAnimation( PYTHON_FIRE1, multiplayer ? 1 : 0 );
+//
+// V_PunchAxis( 0, -10.0 );
+// }
+//
+// switch( gEngfuncs.pfnRandomLong( 0, 1 ) )
+// {
+// case 0:
+// gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/357_shot1.wav", gEngfuncs.pfnRandomFloat(0.8, 0.9), ATTN_NORM, 0, PITCH_NORM );
+// break;
+// case 1:
+// gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/357_shot2.wav", gEngfuncs.pfnRandomFloat(0.8, 0.9), ATTN_NORM, 0, PITCH_NORM );
+// break;
+// }
+//
+// EV_GetGunPosition( args, vecSrc, origin );
+//
+// VectorCopy( forward, vecAiming );
+//
+// EV_HLDM_FireBullets( idx, forward, right, up, 1, vecSrc, vecAiming, 8192, BULLET_PLAYER_357, 0, 0, args->fparam1, args->fparam2 );
+//}
+//======================
+// PHYTON END
+// ( .357 )
+//======================
+
+//======================
+// GAUSS START
+//======================
+#define SND_CHANGE_PITCH (1<<7) // duplicated in protocol.h change sound pitch
+
+void EV_SpinGauss( event_args_t *args )
+{
+ int idx;
+ vec3_t origin;
+ vec3_t angles;
+ vec3_t velocity;
+ int iSoundState = 0;
+
+ int pitch;
+
+ idx = args->entindex;
+ VectorCopy( args->origin, origin );
+ VectorCopy( args->angles, angles );
+ VectorCopy( args->velocity, velocity );
+
+ pitch = args->iparam1;
+
+ iSoundState = args->bparam1 ? SND_CHANGE_PITCH : 0;
+
+ gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "ambience/pulsemachine.wav", 1.0, ATTN_NORM, iSoundState, pitch );
+}
+
+/*
+==============================
+EV_StopPreviousGauss
+
+==============================
+*/
+void EV_StopPreviousGauss( int idx )
+{
+ // Make sure we don't have a gauss spin event in the queue for this guy
+ gEngfuncs.pEventAPI->EV_KillEvents( idx, "events/gaussspin.sc" );
+ gEngfuncs.pEventAPI->EV_StopSound( idx, CHAN_WEAPON, "ambience/pulsemachine.wav" );
+}
+
+void EV_FireGauss( event_args_t *args )
+{
+ int idx;
+ vec3_t origin;
+ vec3_t angles;
+ vec3_t velocity;
+ float flDamage = args->fparam1;
+ int primaryfire = args->bparam1;
+
+ int m_fPrimaryFire = args->bparam1;
+ int m_iWeaponVolume = GAUSS_PRIMARY_FIRE_VOLUME;
+ vec3_t vecSrc;
+ vec3_t vecDest;
+ edict_t *pentIgnore;
+ pmtrace_t tr, beam_tr;
+ float flMaxFrac = 1.0;
+ int nTotal = 0;
+ int fHasPunched = 0;
+ int fFirstBeam = 1;
+ int nMaxHits = 10;
+ physent_t *pEntity;
+ int m_iBeam, m_iGlow, m_iBalls;
+ vec3_t up, right, forward;
+
+ idx = args->entindex;
+ VectorCopy( args->origin, origin );
+ VectorCopy( args->angles, angles );
+ VectorCopy( args->velocity, velocity );
+
+ if ( args->bparam2 )
+ {
+ EV_StopPreviousGauss( idx );
+ return;
+ }
+
+// Con_Printf( "Firing gauss with %f\n", flDamage );
+ EV_GetGunPosition( args, vecSrc, origin );
+
+ m_iBeam = gEngfuncs.pEventAPI->EV_FindModelIndex( "sprites/smoke.spr" );
+ m_iBalls = m_iGlow = gEngfuncs.pEventAPI->EV_FindModelIndex( "sprites/hotglow.spr" );
+
+ AngleVectors( angles, forward, right, up );
+
+ VectorMA( vecSrc, 8192, forward, vecDest );
+
+ if ( EV_IsLocal( idx ) )
+ {
+ V_PunchAxis( 0, -2.0 );
+ gEngfuncs.pEventAPI->EV_WeaponAnimation( GAUSS_FIRE2, 2 );
+ }
+
+ gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/gauss2.wav", 0.5 + flDamage * (1.0 / 400.0), ATTN_NORM, 0, 85 + gEngfuncs.pfnRandomLong( 0, 0x1f ) );
+
+ while (flDamage > 10 && nMaxHits > 0)
+ {
+ nMaxHits--;
+
+ gEngfuncs.pEventAPI->EV_SetUpPlayerPrediction( false, true );
+
+ // Store off the old count
+ gEngfuncs.pEventAPI->EV_PushPMStates();
+
+ // Now add in all of the players.
+ gEngfuncs.pEventAPI->EV_SetSolidPlayers ( idx - 1 );
+
+ gEngfuncs.pEventAPI->EV_SetTraceHull( 2 );
+ gEngfuncs.pEventAPI->EV_PlayerTrace( vecSrc, vecDest, PM_STUDIO_BOX, -1, &tr );
+
+ gEngfuncs.pEventAPI->EV_PopPMStates();
+
+ if ( tr.allsolid )
+ break;
+
+ if (fFirstBeam)
+ {
+ if ( EV_IsLocal( idx ) )
+ {
+ // Add muzzle flash to current weapon model
+ EV_MuzzleFlash();
+ }
+ fFirstBeam = 0;
+
+ gEngfuncs.pEfxAPI->R_BeamEntPoint(
+ idx | 0x1000,
+ tr.endpos,
+ m_iBeam,
+ 0.1,
+ m_fPrimaryFire ? 1.0 : 2.5,
+ 0.0,
+ m_fPrimaryFire ? 128.0 : flDamage,
+ 0,
+ 0,
+ 0,
+ m_fPrimaryFire ? 255 : 255,
+ m_fPrimaryFire ? 128 : 255,
+ m_fPrimaryFire ? 0 : 255
+ );
+ }
+ else
+ {
+ gEngfuncs.pEfxAPI->R_BeamPoints( vecSrc,
+ tr.endpos,
+ m_iBeam,
+ 0.1,
+ m_fPrimaryFire ? 1.0 : 2.5,
+ 0.0,
+ m_fPrimaryFire ? 128.0 : flDamage,
+ 0,
+ 0,
+ 0,
+ m_fPrimaryFire ? 255 : 255,
+ m_fPrimaryFire ? 128 : 255,
+ m_fPrimaryFire ? 0 : 255
+ );
+ }
+
+ pEntity = gEngfuncs.pEventAPI->EV_GetPhysent( tr.ent );
+ if ( pEntity == NULL )
+ break;
+
+ if ( pEntity->solid == SOLID_BSP )
+ {
+ float n;
+
+ pentIgnore = NULL;
+
+ n = -DotProduct( tr.plane.normal, forward );
+
+ if (n < 0.5) // 60 degrees
+ {
+ // ALERT( at_console, "reflect %f\n", n );
+ // reflect
+ vec3_t r;
+
+ VectorMA( forward, 2.0 * n, tr.plane.normal, r );
+
+ flMaxFrac = flMaxFrac - tr.fraction;
+
+ VectorCopy( r, forward );
+
+ VectorMA( tr.endpos, 8.0, forward, vecSrc );
+ VectorMA( vecSrc, 8192.0, forward, vecDest );
+
+ gEngfuncs.pEfxAPI->R_TempSprite( tr.endpos, vec3_origin, 0.2, m_iGlow, kRenderGlow, kRenderFxNoDissipation, flDamage * n / 255.0, flDamage * n * 0.5 * 0.1, FTENT_FADEOUT );
+
+ vec3_t fwd;
+ VectorAdd( tr.endpos, tr.plane.normal, fwd );
+
+ gEngfuncs.pEfxAPI->R_Sprite_Trail( TE_SPRITETRAIL, tr.endpos, fwd, m_iBalls, 3, 0.1, gEngfuncs.pfnRandomFloat( 10, 20 ) / 100.0, 100,
+ 255, 100 );
+
+ // lose energy
+ if ( n == 0 )
+ {
+ n = 0.1;
+ }
+
+ flDamage = flDamage * (1 - n);
+
+ }
+ else
+ {
+ // tunnel
+ EV_HLDM_DecalGunshot( &tr, BULLET_MONSTER_12MM );
+
+ gEngfuncs.pEfxAPI->R_TempSprite( tr.endpos, vec3_origin, 1.0, m_iGlow, kRenderGlow, kRenderFxNoDissipation, flDamage / 255.0, 6.0, FTENT_FADEOUT );
+
+ // limit it to one hole punch
+ if (fHasPunched)
+ {
+ break;
+ }
+ fHasPunched = 1;
+
+ // try punching through wall if secondary attack (primary is incapable of breaking through)
+ if ( !m_fPrimaryFire )
+ {
+ vec3_t start;
+
+ VectorMA( tr.endpos, 8.0, forward, start );
+
+ // Store off the old count
+ gEngfuncs.pEventAPI->EV_PushPMStates();
+
+ // Now add in all of the players.
+ gEngfuncs.pEventAPI->EV_SetSolidPlayers ( idx - 1 );
+
+ gEngfuncs.pEventAPI->EV_SetTraceHull( 2 );
+ gEngfuncs.pEventAPI->EV_PlayerTrace( start, vecDest, PM_STUDIO_BOX, -1, &beam_tr );
+
+ if ( !beam_tr.allsolid )
+ {
+ vec3_t delta;
+ float n;
+
+ // trace backwards to find exit point
+
+ gEngfuncs.pEventAPI->EV_PlayerTrace( beam_tr.endpos, tr.endpos, PM_STUDIO_BOX, -1, &beam_tr );
+
+ VectorSubtract( beam_tr.endpos, tr.endpos, delta );
+
+ n = Length( delta );
+
+ if (n < flDamage)
+ {
+ if (n == 0)
+ n = 1;
+ flDamage -= n;
+
+ // absorption balls
+ {
+ vec3_t fwd;
+ VectorSubtract( tr.endpos, forward, fwd );
+ gEngfuncs.pEfxAPI->R_Sprite_Trail( TE_SPRITETRAIL, tr.endpos, fwd, m_iBalls, 3, 0.1, gEngfuncs.pfnRandomFloat( 10, 20 ) / 100.0, 100,
+ 255, 100 );
+ }
+
+ //////////////////////////////////// WHAT TO DO HERE
+ // CSoundEnt::InsertSound ( bits_SOUND_COMBAT, pev->origin, NORMAL_EXPLOSION_VOLUME, 3.0 );
+
+ EV_HLDM_DecalGunshot( &beam_tr, BULLET_MONSTER_12MM );
+
+ gEngfuncs.pEfxAPI->R_TempSprite( beam_tr.endpos, vec3_origin, 0.1, m_iGlow, kRenderGlow, kRenderFxNoDissipation, flDamage / 255.0, 6.0, FTENT_FADEOUT );
+
+ // balls
+ {
+ vec3_t fwd;
+ VectorSubtract( beam_tr.endpos, forward, fwd );
+ gEngfuncs.pEfxAPI->R_Sprite_Trail( TE_SPRITETRAIL, beam_tr.endpos, fwd, m_iBalls, (int)(flDamage * 0.3), 0.1, gEngfuncs.pfnRandomFloat( 10, 20 ) / 100.0, 200,
+ 255, 40 );
+ }
+
+ VectorAdd( beam_tr.endpos, forward, vecSrc );
+ }
+ }
+ else
+ {
+ flDamage = 0;
+ }
+
+ gEngfuncs.pEventAPI->EV_PopPMStates();
+ }
+ else
+ {
+ if ( m_fPrimaryFire )
+ {
+ // slug doesn't punch through ever with primary
+ // fire, so leave a little glowy bit and make some balls
+ gEngfuncs.pEfxAPI->R_TempSprite( tr.endpos, vec3_origin, 0.2, m_iGlow, kRenderGlow, kRenderFxNoDissipation, 200.0 / 255.0, 0.3, FTENT_FADEOUT );
+
+ {
+ vec3_t fwd;
+ VectorAdd( tr.endpos, tr.plane.normal, fwd );
+ gEngfuncs.pEfxAPI->R_Sprite_Trail( TE_SPRITETRAIL, tr.endpos, fwd, m_iBalls, 8, 0.6, gEngfuncs.pfnRandomFloat( 10, 20 ) / 100.0, 100,
+ 255, 200 );
+ }
+ }
+
+ flDamage = 0;
+ }
+ }
+ }
+ else
+ {
+ VectorAdd( tr.endpos, forward, vecSrc );
+ }
+ }
+}
+//======================
+// GAUSS END
+//======================
+
+//======================
+// CROWBAR START
+//======================
+
+enum crowbar_e {
+ CROWBAR_IDLE = 0,
+ CROWBAR_DRAW,
+ CROWBAR_HOLSTER,
+ CROWBAR_ATTACK1HIT,
+ CROWBAR_ATTACK1MISS,
+ CROWBAR_ATTACK2MISS,
+ CROWBAR_ATTACK2HIT,
+ CROWBAR_ATTACK3MISS,
+ CROWBAR_ATTACK3HIT
+};
+
+int g_iSwing;
+
+//Only predict the miss sounds, hit sounds are still played
+//server side, so players don't get the wrong idea.
+void EV_Crowbar( event_args_t *args )
+{
+ int idx;
+ vec3_t origin;
+ vec3_t angles;
+ vec3_t velocity;
+
+ idx = args->entindex;
+ VectorCopy( args->origin, origin );
+
+ //Play Swing sound
+ gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/cbar_miss1.wav", 1, ATTN_NORM, 0, PITCH_NORM);
+
+ if ( EV_IsLocal( idx ) )
+ {
+ gEngfuncs.pEventAPI->EV_WeaponAnimation( CROWBAR_ATTACK1MISS, 1 );
+
+ switch( (g_iSwing++) % 3 )
+ {
+ case 0:
+ gEngfuncs.pEventAPI->EV_WeaponAnimation ( CROWBAR_ATTACK1MISS, 1 ); break;
+ case 1:
+ gEngfuncs.pEventAPI->EV_WeaponAnimation ( CROWBAR_ATTACK2MISS, 1 ); break;
+ case 2:
+ gEngfuncs.pEventAPI->EV_WeaponAnimation ( CROWBAR_ATTACK3MISS, 1 ); break;
+ }
+ }
+}
+//======================
+// CROWBAR END
+//======================
+
+//======================
+// CROSSBOW END
+//======================
+enum crossbow_e {
+ CROSSBOW_IDLE1 = 0, // full
+ CROSSBOW_IDLE2, // empty
+ CROSSBOW_FIDGET1, // full
+ CROSSBOW_FIDGET2, // empty
+ CROSSBOW_FIRE1, // full
+ CROSSBOW_FIRE2, // reload
+ CROSSBOW_FIRE3, // empty
+ CROSSBOW_RELOAD, // from empty
+ CROSSBOW_DRAW1, // full
+ CROSSBOW_DRAW2, // empty
+ CROSSBOW_HOLSTER1, // full
+ CROSSBOW_HOLSTER2, // empty
+};
+
+//=====================
+// EV_BoltCallback
+// This function is used to correct the origin and angles
+// of the bolt, so it looks like it's stuck on the wall.
+//=====================
+void EV_BoltCallback ( struct tempent_s *ent, float frametime, float currenttime )
+{
+ ent->entity.origin = ent->entity.baseline.vuser1;
+ ent->entity.angles = ent->entity.baseline.vuser2;
+}
+
+void EV_FireCrossbow2( event_args_t *args )
+{
+ vec3_t vecSrc, vecEnd;
+ vec3_t up, right, forward;
+ pmtrace_t tr;
+
+ int idx;
+ vec3_t origin;
+ vec3_t angles;
+ vec3_t velocity;
+
+ idx = args->entindex;
+ VectorCopy( args->origin, origin );
+ VectorCopy( args->angles, angles );
+
+ VectorCopy( args->velocity, velocity );
+
+ AngleVectors( angles, forward, right, up );
+
+ EV_GetGunPosition( args, vecSrc, origin );
+
+ VectorMA( vecSrc, 8192, forward, vecEnd );
+
+ gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/xbow_fire1.wav", 1, ATTN_NORM, 0, 93 + gEngfuncs.pfnRandomLong(0,0xF) );
+ gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_ITEM, "weapons/xbow_reload1.wav", gEngfuncs.pfnRandomFloat(0.95, 1.0), ATTN_NORM, 0, 93 + gEngfuncs.pfnRandomLong(0,0xF) );
+
+ if ( EV_IsLocal( idx ) )
+ {
+ if ( args->iparam1 )
+ gEngfuncs.pEventAPI->EV_WeaponAnimation( CROSSBOW_FIRE1, 1 );
+ else if ( args->iparam2 )
+ gEngfuncs.pEventAPI->EV_WeaponAnimation( CROSSBOW_FIRE3, 1 );
+ }
+
+ // Store off the old count
+ gEngfuncs.pEventAPI->EV_PushPMStates();
+
+ // Now add in all of the players.
+ gEngfuncs.pEventAPI->EV_SetSolidPlayers ( idx - 1 );
+ gEngfuncs.pEventAPI->EV_SetTraceHull( 2 );
+ gEngfuncs.pEventAPI->EV_PlayerTrace( vecSrc, vecEnd, PM_STUDIO_BOX, -1, &tr );
+
+ //We hit something
+ if ( tr.fraction < 1.0 )
+ {
+ physent_t *pe = gEngfuncs.pEventAPI->EV_GetPhysent( tr.ent );
+
+ //Not the world, let's assume we hit something organic ( dog, cat, uncle joe, etc ).
+ if ( pe->solid != SOLID_BSP )
+ {
+ switch( gEngfuncs.pfnRandomLong(0,1) )
+ {
+ case 0:
+ gEngfuncs.pEventAPI->EV_PlaySound( idx, tr.endpos, CHAN_BODY, "weapons/xbow_hitbod1.wav", 1, ATTN_NORM, 0, PITCH_NORM ); break;
+ case 1:
+ gEngfuncs.pEventAPI->EV_PlaySound( idx, tr.endpos, CHAN_BODY, "weapons/xbow_hitbod2.wav", 1, ATTN_NORM, 0, PITCH_NORM ); break;
+ }
+ }
+ //Stick to world but don't stick to glass, it might break and leave the bolt floating. It can still stick to other non-transparent breakables though.
+ else if ( pe->rendermode == kRenderNormal )
+ {
+ gEngfuncs.pEventAPI->EV_PlaySound( 0, tr.endpos, CHAN_BODY, "weapons/xbow_hit1.wav", gEngfuncs.pfnRandomFloat(0.95, 1.0), ATTN_NORM, 0, PITCH_NORM );
+
+ //Not underwater, do some sparks...
+ if ( gEngfuncs.PM_PointContents( tr.endpos, NULL ) != CONTENTS_WATER)
+ gEngfuncs.pEfxAPI->R_SparkShower( tr.endpos );
+
+ vec3_t vBoltAngles;
+ int iModelIndex = gEngfuncs.pEventAPI->EV_FindModelIndex( "models/crossbow_bolt.mdl" );
+
+ VectorAngles( forward, vBoltAngles );
+
+ TEMPENTITY *bolt = gEngfuncs.pEfxAPI->R_TempModel( tr.endpos - forward * 10, Vector( 0, 0, 0), vBoltAngles , 5, iModelIndex, TE_BOUNCE_NULL );
+
+ if ( bolt )
+ {
+ bolt->flags |= ( FTENT_CLIENTCUSTOM ); //So it calls the callback function.
+ bolt->entity.baseline.vuser1 = tr.endpos - forward * 10; // Pull out a little bit
+ bolt->entity.baseline.vuser2 = vBoltAngles; //Look forward!
+ bolt->callback = EV_BoltCallback; //So we can set the angles and origin back. (Stick the bolt to the wall)
+ }
+ }
+ }
+
+ gEngfuncs.pEventAPI->EV_PopPMStates();
+}
+
+//TODO: Fully predict the fliying bolt.
+void EV_FireCrossbow( event_args_t *args )
+{
+ int idx;
+ vec3_t origin;
+
+ idx = args->entindex;
+ VectorCopy( args->origin, origin );
+
+ gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/xbow_fire1.wav", 1, ATTN_NORM, 0, 93 + gEngfuncs.pfnRandomLong(0,0xF) );
+ gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_ITEM, "weapons/xbow_reload1.wav", gEngfuncs.pfnRandomFloat(0.95, 1.0), ATTN_NORM, 0, 93 + gEngfuncs.pfnRandomLong(0,0xF) );
+
+ //Only play the weapon anims if I shot it.
+ if ( EV_IsLocal( idx ) )
+ {
+ if ( args->iparam1 )
+ gEngfuncs.pEventAPI->EV_WeaponAnimation( CROSSBOW_FIRE1, 1 );
+ else if ( args->iparam2 )
+ gEngfuncs.pEventAPI->EV_WeaponAnimation( CROSSBOW_FIRE3, 1 );
+
+ V_PunchAxis( 0, -2.0 );
+ }
+}
+//======================
+// CROSSBOW END
+//======================
+
+//======================
+// RPG START
+//======================
+enum rpg_e {
+ RPG_IDLE = 0,
+ RPG_FIDGET,
+ RPG_RELOAD, // to reload
+ RPG_FIRE2, // to empty
+ RPG_HOLSTER1, // loaded
+ RPG_DRAW1, // loaded
+ RPG_HOLSTER2, // unloaded
+ RPG_DRAW_UL, // unloaded
+ RPG_IDLE_UL, // unloaded idle
+ RPG_FIDGET_UL, // unloaded fidget
+};
+
+void EV_FireRpg( event_args_t *args )
+{
+ int idx;
+ vec3_t origin;
+
+ idx = args->entindex;
+ VectorCopy( args->origin, origin );
+
+ gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/rocketfire1.wav", 0.9, ATTN_NORM, 0, PITCH_NORM );
+ gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_ITEM, "weapons/glauncher.wav", 0.7, ATTN_NORM, 0, PITCH_NORM );
+
+ //Only play the weapon anims if I shot it.
+ if ( EV_IsLocal( idx ) )
+ {
+ gEngfuncs.pEventAPI->EV_WeaponAnimation( RPG_FIRE2, 1 );
+
+ V_PunchAxis( 0, -5.0 );
+ }
+}
+//======================
+// RPG END
+//======================
+
+//======================
+// EGON END
+//======================
+enum egon_e {
+ EGON_IDLE1 = 0,
+ EGON_FIDGET1,
+ EGON_ALTFIREON,
+ EGON_ALTFIRECYCLE,
+ EGON_ALTFIREOFF,
+ EGON_FIRE1,
+ EGON_FIRE2,
+ EGON_FIRE3,
+ EGON_FIRE4,
+ EGON_DRAW,
+ EGON_HOLSTER
+};
+
+int g_fireAnims1[] = { EGON_FIRE1, EGON_FIRE2, EGON_FIRE3, EGON_FIRE4 };
+int g_fireAnims2[] = { EGON_ALTFIRECYCLE };
+
+enum EGON_FIRESTATE { FIRE_OFF, FIRE_CHARGE };
+enum EGON_FIREMODE { FIRE_NARROW, FIRE_WIDE};
+
+#define EGON_PRIMARY_VOLUME 450
+#define EGON_BEAM_SPRITE "sprites/xbeam1.spr"
+#define EGON_FLARE_SPRITE "sprites/XSpark1.spr"
+#define EGON_SOUND_OFF "weapons/egon_off1.wav"
+#define EGON_SOUND_RUN "weapons/egon_run3.wav"
+#define EGON_SOUND_STARTUP "weapons/egon_windup2.wav"
+
+//@2014
+#ifdef ARRAYSIZE
+#undef ARRAYSIZE
+#endif
+
+#define ARRAYSIZE(p) (sizeof(p)/sizeof(p[0]))
+
+BEAM *pBeam;
+BEAM *pBeam2;
+
+void EV_EgonFire( event_args_t *args )
+{
+ int idx, iFireState, iFireMode;
+ vec3_t origin;
+
+ idx = args->entindex;
+ VectorCopy( args->origin, origin );
+ iFireState = args->iparam1;
+ iFireMode = args->iparam2;
+ int iStartup = args->bparam1;
+
+
+ if ( iStartup )
+ {
+ if ( iFireMode == FIRE_WIDE )
+ gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, EGON_SOUND_STARTUP, 0.98, ATTN_NORM, 0, 125 );
+ else
+ gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, EGON_SOUND_STARTUP, 0.9, ATTN_NORM, 0, 100 );
+ }
+ else
+ {
+ if ( iFireMode == FIRE_WIDE )
+ gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_STATIC, EGON_SOUND_RUN, 0.98, ATTN_NORM, 0, 125 );
+ else
+ gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_STATIC, EGON_SOUND_RUN, 0.9, ATTN_NORM, 0, 100 );
+ }
+
+ //Only play the weapon anims if I shot it.
+ if ( EV_IsLocal( idx ) )
+ gEngfuncs.pEventAPI->EV_WeaponAnimation ( g_fireAnims1[ gEngfuncs.pfnRandomLong( 0, 3 ) ], 1 );
+
+ if ( iStartup == 1 && EV_IsLocal( idx ) && !pBeam && !pBeam2 )
+ {
+ vec3_t vecSrc, vecEnd, origin, angles, forward, right, up;
+ pmtrace_t tr;
+
+ cl_entity_t *pl = gEngfuncs.GetEntityByIndex( idx );
+
+ if ( pl )
+ {
+ VectorCopy( gHUD.m_vecAngles, angles );
+
+ AngleVectors( angles, forward, right, up );
+
+ EV_GetGunPosition( args, vecSrc, pl->origin );
+
+ VectorMA( vecSrc, 2048, forward, vecEnd );
+
+ gEngfuncs.pEventAPI->EV_SetUpPlayerPrediction( false, true );
+
+ // Store off the old count
+ gEngfuncs.pEventAPI->EV_PushPMStates();
+
+ // Now add in all of the players.
+ gEngfuncs.pEventAPI->EV_SetSolidPlayers ( idx - 1 );
+
+ gEngfuncs.pEventAPI->EV_SetTraceHull( 2 );
+ gEngfuncs.pEventAPI->EV_PlayerTrace( vecSrc, vecEnd, PM_STUDIO_BOX, -1, &tr );
+
+ gEngfuncs.pEventAPI->EV_PopPMStates();
+
+ int iBeamModelIndex = gEngfuncs.pEventAPI->EV_FindModelIndex( EGON_BEAM_SPRITE );
+
+ float r = 50.0f;
+ float g = 50.0f;
+ float b = 125.0f;
+
+ if ( IEngineStudio.IsHardware() )
+ {
+ r /= 100.0f;
+ g /= 100.0f;
+ }
+
+
+ pBeam = gEngfuncs.pEfxAPI->R_BeamEntPoint ( idx | 0x1000, tr.endpos, iBeamModelIndex, 99999, 3.5, 0.2, 0.7, 55, 0, 0, r, g, b );
+
+ if ( pBeam )
+ pBeam->flags |= ( FBEAM_SINENOISE );
+
+ pBeam2 = gEngfuncs.pEfxAPI->R_BeamEntPoint ( idx | 0x1000, tr.endpos, iBeamModelIndex, 99999, 5.0, 0.08, 0.7, 25, 0, 0, r, g, b );
+ }
+ }
+}
+
+void EV_EgonStop( event_args_t *args )
+{
+ int idx;
+ vec3_t origin;
+
+ idx = args->entindex;
+ VectorCopy ( args->origin, origin );
+
+ gEngfuncs.pEventAPI->EV_StopSound( idx, CHAN_STATIC, EGON_SOUND_RUN );
+
+ if ( args->iparam1 )
+ gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, EGON_SOUND_OFF, 0.98, ATTN_NORM, 0, 100 );
+
+ if ( EV_IsLocal( idx ) )
+ {
+ if ( pBeam )
+ {
+ pBeam->die = 0.0;
+ pBeam = NULL;
+ }
+
+
+ if ( pBeam2 )
+ {
+ pBeam2->die = 0.0;
+ pBeam2 = NULL;
+ }
+ }
+}
+//======================
+// EGON END
+//======================
+
+//======================
+// HORNET START
+//======================
+enum hgun_e {
+ HGUN_IDLE1 = 0,
+ HGUN_FIDGETSWAY,
+ HGUN_FIDGETSHAKE,
+ HGUN_DOWN,
+ HGUN_UP,
+ HGUN_SHOOT
+};
+
+void EV_HornetGunFire( event_args_t *args )
+{
+ int idx, iFireMode;
+ vec3_t origin, angles, vecSrc, forward, right, up;
+
+ idx = args->entindex;
+ VectorCopy( args->origin, origin );
+ VectorCopy( args->angles, angles );
+ iFireMode = args->iparam1;
+
+ //Only play the weapon anims if I shot it.
+ if ( EV_IsLocal( idx ) )
+ {
+ V_PunchAxis( 0, gEngfuncs.pfnRandomLong ( 0, 2 ) );
+ gEngfuncs.pEventAPI->EV_WeaponAnimation ( HGUN_SHOOT, 1 );
+ }
+
+ switch ( gEngfuncs.pfnRandomLong ( 0 , 2 ) )
+ {
+ case 0: gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "agrunt/ag_fire1.wav", 1, ATTN_NORM, 0, 100 ); break;
+ case 1: gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "agrunt/ag_fire2.wav", 1, ATTN_NORM, 0, 100 ); break;
+ case 2: gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "agrunt/ag_fire3.wav", 1, ATTN_NORM, 0, 100 ); break;
+ }
+}
+//======================
+// HORNET END
+//======================
+
+//======================
+// TRIPMINE START
+//======================
+enum tripmine_e {
+ TRIPMINE_IDLE1 = 0,
+ TRIPMINE_IDLE2,
+ TRIPMINE_ARM1,
+ TRIPMINE_ARM2,
+ TRIPMINE_FIDGET,
+ TRIPMINE_HOLSTER,
+ TRIPMINE_DRAW,
+ TRIPMINE_WORLD,
+ TRIPMINE_GROUND,
+};
+
+//We only check if it's possible to put a trip mine
+//and if it is, then we play the animation. Server still places it.
+void EV_TripmineFire( event_args_t *args )
+{
+ int idx;
+ vec3_t vecSrc, angles, view_ofs, forward;
+ pmtrace_t tr;
+
+ idx = args->entindex;
+ VectorCopy( args->origin, vecSrc );
+ VectorCopy( args->angles, angles );
+
+ AngleVectors ( angles, forward, NULL, NULL );
+
+ if ( !EV_IsLocal ( idx ) )
+ return;
+
+ // Grab predicted result for local player
+ gEngfuncs.pEventAPI->EV_LocalPlayerViewheight( view_ofs );
+
+ vecSrc = vecSrc + view_ofs;
+
+ // Store off the old count
+ gEngfuncs.pEventAPI->EV_PushPMStates();
+
+ // Now add in all of the players.
+ gEngfuncs.pEventAPI->EV_SetSolidPlayers ( idx - 1 );
+ gEngfuncs.pEventAPI->EV_SetTraceHull( 2 );
+ gEngfuncs.pEventAPI->EV_PlayerTrace( vecSrc, vecSrc + forward * 128, PM_NORMAL, -1, &tr );
+
+ //Hit something solid
+ if ( tr.fraction < 1.0 )
+ gEngfuncs.pEventAPI->EV_WeaponAnimation ( TRIPMINE_DRAW, 0 );
+
+ gEngfuncs.pEventAPI->EV_PopPMStates();
+}
+//======================
+// TRIPMINE END
+//======================
+
+//======================
+// SQUEAK START
+//======================
+enum squeak_e {
+ SQUEAK_IDLE1 = 0,
+ SQUEAK_FIDGETFIT,
+ SQUEAK_FIDGETNIP,
+ SQUEAK_DOWN,
+ SQUEAK_UP,
+ SQUEAK_THROW
+};
+
+#define VEC_HULL_MIN Vector(-16, -16, -36)
+#define VEC_DUCK_HULL_MIN Vector(-16, -16, -18 )
+
+void EV_SnarkFire( event_args_t *args )
+{
+ int idx;
+ vec3_t vecSrc, angles, view_ofs, forward;
+ pmtrace_t tr;
+
+ idx = args->entindex;
+ VectorCopy( args->origin, vecSrc );
+ VectorCopy( args->angles, angles );
+
+ AngleVectors ( angles, forward, NULL, NULL );
+
+ if ( !EV_IsLocal ( idx ) )
+ return;
+
+ if ( args->ducking )
+ vecSrc = vecSrc - ( VEC_HULL_MIN - VEC_DUCK_HULL_MIN );
+
+ // Store off the old count
+ gEngfuncs.pEventAPI->EV_PushPMStates();
+
+ // Now add in all of the players.
+ gEngfuncs.pEventAPI->EV_SetSolidPlayers ( idx - 1 );
+ gEngfuncs.pEventAPI->EV_SetTraceHull( 2 );
+ gEngfuncs.pEventAPI->EV_PlayerTrace( vecSrc + forward * 20, vecSrc + forward * 64, PM_NORMAL, -1, &tr );
+
+ //Find space to drop the thing.
+ if ( tr.allsolid == 0 && tr.startsolid == 0 && tr.fraction > 0.25 )
+ gEngfuncs.pEventAPI->EV_WeaponAnimation ( SQUEAK_THROW, 0 );
+
+ gEngfuncs.pEventAPI->EV_PopPMStates();
+}
+//======================
+// SQUEAK END
+//======================
+
+void EV_TrainPitchAdjust( event_args_t *args )
+{
+ int idx;
+ vec3_t origin;
+
+ unsigned short us_params;
+ int noise;
+ float m_flVolume;
+ int pitch;
+ int stop;
+
+ char sz[ 256 ];
+
+ idx = args->entindex;
+
+ VectorCopy( args->origin, origin );
+
+ us_params = (unsigned short)args->iparam1;
+ stop = args->bparam1;
+
+ m_flVolume = (float)(us_params & 0x003f)/40.0;
+ noise = (int)(((us_params) >> 12 ) & 0x0007);
+ pitch = (int)( 10.0 * (float)( ( us_params >> 6 ) & 0x003f ) );
+
+ switch ( noise )
+ {
+ case 1: strcpy( sz, "plats/ttrain1.wav"); break;
+ case 2: strcpy( sz, "plats/ttrain2.wav"); break;
+ case 3: strcpy( sz, "plats/ttrain3.wav"); break;
+ case 4: strcpy( sz, "plats/ttrain4.wav"); break;
+ case 5: strcpy( sz, "plats/ttrain6.wav"); break;
+ case 6: strcpy( sz, "plats/ttrain7.wav"); break;
+ default:
+ // no sound
+ strcpy( sz, "" );
+ return;
+ }
+
+ if ( stop )
+ {
+ gEngfuncs.pEventAPI->EV_StopSound( idx, CHAN_STATIC, sz );
+ }
+ else
+ {
+ gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_STATIC, sz, m_flVolume, ATTN_NORM, SND_CHANGE_PITCH, pitch );
+ }
+}
+
+int EV_TFC_IsAllyTeam( int iTeam1, int iTeam2 )
+{
+ return 0;
+}
diff --git a/main/source/cl_dll/ev_hldm.h b/main/source/cl_dll/ev_hldm.h
index eaf13adc..1b63ac91 100644
--- a/main/source/cl_dll/ev_hldm.h
+++ b/main/source/cl_dll/ev_hldm.h
@@ -1,73 +1,73 @@
-#if !defined ( EV_HLDMH )
-#define EV_HLDMH
-
-#include "common/bullettypes.h"
-
-enum glock_e {
- GLOCK_IDLE1 = 0,
- GLOCK_IDLE2,
- GLOCK_IDLE3,
- GLOCK_SHOOT,
- GLOCK_SHOOT_EMPTY,
- GLOCK_RELOAD,
- GLOCK_RELOAD_NOT_EMPTY,
- GLOCK_DRAW,
- GLOCK_HOLSTER,
- GLOCK_ADD_SILENCER
-};
-
-enum shotgun_e {
- SHOTGUN_IDLE = 0,
- SHOTGUN_FIRE,
- SHOTGUN_FIRE2,
- SHOTGUN_RELOAD,
- SHOTGUN_PUMP,
- SHOTGUN_START_RELOAD,
- SHOTGUN_DRAW,
- SHOTGUN_HOLSTER,
- SHOTGUN_IDLE4,
- SHOTGUN_IDLE_DEEP
-};
-
-//enum mp5_e
-enum avhmg_e
-{
- MG_LONGIDLE = 0,
- MG_IDLE1,
- MG_LAUNCH,
- MG_RELOAD,
- MG_DEPLOY,
- MG_FIRE1,
- MG_FIRE2,
- MG_FIRE3,
-};
-
-enum python_e {
- PYTHON_IDLE1 = 0,
- PYTHON_FIDGET,
- PYTHON_FIRE1,
- PYTHON_RELOAD,
- PYTHON_HOLSTER,
- PYTHON_DRAW,
- PYTHON_IDLE2,
- PYTHON_IDLE3
-};
-
-#define GAUSS_PRIMARY_CHARGE_VOLUME 256// how loud gauss is while charging
-#define GAUSS_PRIMARY_FIRE_VOLUME 450// how loud gauss is when discharged
-
-enum gauss_e {
- GAUSS_IDLE = 0,
- GAUSS_IDLE2,
- GAUSS_FIDGET,
- GAUSS_SPINUP,
- GAUSS_SPIN,
- GAUSS_FIRE,
- GAUSS_FIRE2,
- GAUSS_HOLSTER,
- GAUSS_DRAW
-};
-
-#include "common/hldm.h"
-
+#if !defined ( EV_HLDMH )
+#define EV_HLDMH
+
+#include "common/bullettypes.h"
+
+enum glock_e {
+ GLOCK_IDLE1 = 0,
+ GLOCK_IDLE2,
+ GLOCK_IDLE3,
+ GLOCK_SHOOT,
+ GLOCK_SHOOT_EMPTY,
+ GLOCK_RELOAD,
+ GLOCK_RELOAD_NOT_EMPTY,
+ GLOCK_DRAW,
+ GLOCK_HOLSTER,
+ GLOCK_ADD_SILENCER
+};
+
+enum shotgun_e {
+ SHOTGUN_IDLE = 0,
+ SHOTGUN_FIRE,
+ SHOTGUN_FIRE2,
+ SHOTGUN_RELOAD,
+ SHOTGUN_PUMP,
+ SHOTGUN_START_RELOAD,
+ SHOTGUN_DRAW,
+ SHOTGUN_HOLSTER,
+ SHOTGUN_IDLE4,
+ SHOTGUN_IDLE_DEEP
+};
+
+//enum mp5_e
+enum avhmg_e
+{
+ MG_LONGIDLE = 0,
+ MG_IDLE1,
+ MG_LAUNCH,
+ MG_RELOAD,
+ MG_DEPLOY,
+ MG_FIRE1,
+ MG_FIRE2,
+ MG_FIRE3,
+};
+
+enum python_e {
+ PYTHON_IDLE1 = 0,
+ PYTHON_FIDGET,
+ PYTHON_FIRE1,
+ PYTHON_RELOAD,
+ PYTHON_HOLSTER,
+ PYTHON_DRAW,
+ PYTHON_IDLE2,
+ PYTHON_IDLE3
+};
+
+#define GAUSS_PRIMARY_CHARGE_VOLUME 256// how loud gauss is while charging
+#define GAUSS_PRIMARY_FIRE_VOLUME 450// how loud gauss is when discharged
+
+enum gauss_e {
+ GAUSS_IDLE = 0,
+ GAUSS_IDLE2,
+ GAUSS_FIDGET,
+ GAUSS_SPINUP,
+ GAUSS_SPIN,
+ GAUSS_FIRE,
+ GAUSS_FIRE2,
+ GAUSS_HOLSTER,
+ GAUSS_DRAW
+};
+
+#include "common/hldm.h"
+
#endif // EV_HLDMH
\ No newline at end of file
diff --git a/main/source/cl_dll/events.cpp b/main/source/cl_dll/events.cpp
index 60061f1f..7a9284d0 100644
--- a/main/source/cl_dll/events.cpp
+++ b/main/source/cl_dll/events.cpp
@@ -1,16 +1,16 @@
-#include "hud.h"
-#include "cl_util.h"
-
-void Game_HookEvents( void );
-
-/*
-===================
-EV_HookEvents
-
-See if game specific code wants to hook any events.
-===================
-*/
-void EV_HookEvents( void )
-{
- Game_HookEvents();
+#include "hud.h"
+#include "cl_util.h"
+
+void Game_HookEvents( void );
+
+/*
+===================
+EV_HookEvents
+
+See if game specific code wants to hook any events.
+===================
+*/
+void EV_HookEvents( void )
+{
+ Game_HookEvents();
}
\ No newline at end of file
diff --git a/main/source/cl_dll/eventscripts.h b/main/source/cl_dll/eventscripts.h
index b99929da..4d80bcf1 100644
--- a/main/source/cl_dll/eventscripts.h
+++ b/main/source/cl_dll/eventscripts.h
@@ -1,34 +1,34 @@
-// eventscripts.h
-#if !defined ( EVENTSCRIPTSH )
-#define EVENTSCRIPTSH
-
-#include "common/const.h"
-
-// defaults for clientinfo messages
-#define DEFAULT_VIEWHEIGHT 28
-
-#ifndef VEC_DUCK_VIEW
-#define VEC_DUCK_VIEW 12
-#endif
-
-#define FTENT_FADEOUT 0x00000080
-
-#include "common/damagetypes.h"
-#include "pm_shared/pm_defs.h"
-
-// Some of these are HL/TFC specific?
-void EV_EjectBrass( float *origin, float *velocity, float rotation, int model, int soundtype );
-void EV_GetGunPosition( struct event_args_s *args, float *pos, float *origin );
-void EV_GetDefaultShellInfo( struct event_args_s *args, float *origin, float *velocity, float *ShellVelocity, float *ShellOrigin, float *forward, float *right, float *up, float forwardScale, float upScale, float rightScale );
-qboolean EV_IsLocal( int idx );
-qboolean EV_IsSpec( int idx );
-qboolean EV_IsPlayer( int idx );
-void EV_CreateTracer( float *start, float *end );
-
-struct cl_entity_s *GetEntity( int idx );
-struct cl_entity_s *GetViewEntity( void );
-physent_t* GetPhysEntity(int inPhysIndex);
-void DoCenterPrint(char* inString);
-void EV_MuzzleFlash( void );
-
-#endif // EVENTSCRIPTSH
+// eventscripts.h
+#if !defined ( EVENTSCRIPTSH )
+#define EVENTSCRIPTSH
+
+#include "common/const.h"
+
+// defaults for clientinfo messages
+#define DEFAULT_VIEWHEIGHT 28
+
+#ifndef VEC_DUCK_VIEW
+#define VEC_DUCK_VIEW 12
+#endif
+
+#define FTENT_FADEOUT 0x00000080
+
+#include "common/damagetypes.h"
+#include "pm_shared/pm_defs.h"
+
+// Some of these are HL/TFC specific?
+void EV_EjectBrass( float *origin, float *velocity, float rotation, int model, int soundtype );
+void EV_GetGunPosition( struct event_args_s *args, float *pos, float *origin );
+void EV_GetDefaultShellInfo( struct event_args_s *args, float *origin, float *velocity, float *ShellVelocity, float *ShellOrigin, float *forward, float *right, float *up, float forwardScale, float upScale, float rightScale );
+qboolean EV_IsLocal( int idx );
+qboolean EV_IsSpec( int idx );
+qboolean EV_IsPlayer( int idx );
+void EV_CreateTracer( float *start, float *end );
+
+struct cl_entity_s *GetEntity( int idx );
+struct cl_entity_s *GetViewEntity( void );
+physent_t* GetPhysEntity(int inPhysIndex);
+void DoCenterPrint(char* inString);
+void EV_MuzzleFlash( void );
+
+#endif // EVENTSCRIPTSH
diff --git a/main/source/cl_dll/flashlight.cpp b/main/source/cl_dll/flashlight.cpp
index cf51fc1b..17ed25e7 100644
--- a/main/source/cl_dll/flashlight.cpp
+++ b/main/source/cl_dll/flashlight.cpp
@@ -1,140 +1,140 @@
-/***
-*
-* Copyright (c) 1999, Valve LLC. All rights reserved.
-*
-* This product contains software technology licensed from Id
-* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
-* All Rights Reserved.
-*
-* Use, distribution, and modification of this source code and/or resulting
-* object code is restricted to non-commercial enhancements to products from
-* Valve LLC. All other use, distribution, or modification is prohibited
-* without written permission from Valve LLC.
-*
-****/
-//
-// flashlight.cpp
-//
-// implementation of CHudFlashlight class
-//
-
-#include "hud.h"
-#include "cl_util.h"
-#include "mod/AvHNetworkMessages.h"
-
-#include
-#include
-
-
-
-DECLARE_MESSAGE(m_Flash, FlashBat)
-DECLARE_MESSAGE(m_Flash, Flashlight)
-
-#define BAT_NAME "sprites/%d_Flashlight.spr"
-
-int CHudFlashlight::Init(void)
-{
- m_fFade = 0;
- m_fOn = 0;
-
- HOOK_MESSAGE(Flashlight);
- HOOK_MESSAGE(FlashBat);
-
- m_iFlags |= HUD_ACTIVE;
-
- //gHUD.AddHudElem(this);
-
- return 1;
-};
-
-void CHudFlashlight::Reset(void)
-{
- m_fFade = 0;
- m_fOn = 0;
-}
-
-int CHudFlashlight::VidInit(void)
-{
- int HUD_flash_empty = gHUD.GetSpriteIndex( "flash_empty" );
- int HUD_flash_full = gHUD.GetSpriteIndex( "flash_full" );
- int HUD_flash_beam = gHUD.GetSpriteIndex( "flash_beam" );
-
- m_hSprite1 = gHUD.GetSprite(HUD_flash_empty);
- m_hSprite2 = gHUD.GetSprite(HUD_flash_full);
- m_hBeam = gHUD.GetSprite(HUD_flash_beam);
- m_prc1 = &gHUD.GetSpriteRect(HUD_flash_empty);
- m_prc2 = &gHUD.GetSpriteRect(HUD_flash_full);
- m_prcBeam = &gHUD.GetSpriteRect(HUD_flash_beam);
- m_iWidth = m_prc2->right - m_prc2->left;
-
- return 1;
-};
-
-int CHudFlashlight:: MsgFunc_FlashBat(const char *pszName, int iSize, void *pbuf )
-{
- //this message is a lame duck in NS
- return 0;
-}
-
-int CHudFlashlight:: MsgFunc_Flashlight(const char *pszName, int iSize, void *pbuf )
-{
- NetMsg_Flashlight( pbuf, iSize, m_fOn, m_iBat );
- m_flBat = ((float)m_iBat)/100.0;
- return 1;
-}
-
-int CHudFlashlight::Draw(float flTime)
-{
- if ( gHUD.m_iHideHUDDisplay & ( HIDEHUD_FLASHLIGHT | HIDEHUD_ALL ) )
- return 1;
-
- int r, g, b, x, y, a;
- wrect_t rc;
-
- if (!(gHUD.m_iWeaponBits & (1<<(WEAPON_SUIT)) ))
- return 1;
-
- if (m_fOn)
- a = 225;
- else
- a = MIN_ALPHA;
-
- if (m_flBat < 0.20)
- UnpackRGB(r,g,b, RGB_REDISH);
- else
- {
- gHUD.GetPrimaryHudColor(r, g, b);
- }
-
- ScaleColors(r, g, b, a);
-
- y = (m_prc1->bottom - m_prc2->top)/2;
- x = ScreenWidth() - m_iWidth - m_iWidth/2 ;
-
- // Draw the flashlight casing
- SPR_Set(m_hSprite1, r, g, b );
- SPR_DrawAdditive( 0, x, y, m_prc1);
-
- if ( m_fOn )
- { // draw the flashlight beam
- x = ScreenWidth() - m_iWidth/2;
-
- SPR_Set( m_hBeam, r, g, b );
- SPR_DrawAdditive( 0, x, y, m_prcBeam );
- }
-
- // draw the flashlight energy level
- x = ScreenWidth() - m_iWidth - m_iWidth/2 ;
- int iOffset = m_iWidth * (1.0 - m_flBat);
- if (iOffset < m_iWidth)
- {
- rc = *m_prc2;
- rc.left += iOffset;
-
- SPR_Set(m_hSprite2, r, g, b );
- SPR_DrawAdditive( 0, x + iOffset, y, &rc);
- }
-
-
- return 1;
+/***
+*
+* Copyright (c) 1999, Valve LLC. All rights reserved.
+*
+* This product contains software technology licensed from Id
+* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
+* All Rights Reserved.
+*
+* Use, distribution, and modification of this source code and/or resulting
+* object code is restricted to non-commercial enhancements to products from
+* Valve LLC. All other use, distribution, or modification is prohibited
+* without written permission from Valve LLC.
+*
+****/
+//
+// flashlight.cpp
+//
+// implementation of CHudFlashlight class
+//
+
+#include "hud.h"
+#include "cl_util.h"
+#include "mod/AvHNetworkMessages.h"
+
+#include
+#include
+
+
+
+DECLARE_MESSAGE(m_Flash, FlashBat)
+DECLARE_MESSAGE(m_Flash, Flashlight)
+
+#define BAT_NAME "sprites/%d_Flashlight.spr"
+
+int CHudFlashlight::Init(void)
+{
+ m_fFade = 0;
+ m_fOn = 0;
+
+ HOOK_MESSAGE(Flashlight);
+ HOOK_MESSAGE(FlashBat);
+
+ m_iFlags |= HUD_ACTIVE;
+
+ //gHUD.AddHudElem(this);
+
+ return 1;
+};
+
+void CHudFlashlight::Reset(void)
+{
+ m_fFade = 0;
+ m_fOn = 0;
+}
+
+int CHudFlashlight::VidInit(void)
+{
+ int HUD_flash_empty = gHUD.GetSpriteIndex( "flash_empty" );
+ int HUD_flash_full = gHUD.GetSpriteIndex( "flash_full" );
+ int HUD_flash_beam = gHUD.GetSpriteIndex( "flash_beam" );
+
+ m_hSprite1 = gHUD.GetSprite(HUD_flash_empty);
+ m_hSprite2 = gHUD.GetSprite(HUD_flash_full);
+ m_hBeam = gHUD.GetSprite(HUD_flash_beam);
+ m_prc1 = &gHUD.GetSpriteRect(HUD_flash_empty);
+ m_prc2 = &gHUD.GetSpriteRect(HUD_flash_full);
+ m_prcBeam = &gHUD.GetSpriteRect(HUD_flash_beam);
+ m_iWidth = m_prc2->right - m_prc2->left;
+
+ return 1;
+};
+
+int CHudFlashlight:: MsgFunc_FlashBat(const char *pszName, int iSize, void *pbuf )
+{
+ //this message is a lame duck in NS
+ return 0;
+}
+
+int CHudFlashlight:: MsgFunc_Flashlight(const char *pszName, int iSize, void *pbuf )
+{
+ NetMsg_Flashlight( pbuf, iSize, m_fOn, m_iBat );
+ m_flBat = ((float)m_iBat)/100.0;
+ return 1;
+}
+
+int CHudFlashlight::Draw(float flTime)
+{
+ if ( gHUD.m_iHideHUDDisplay & ( HIDEHUD_FLASHLIGHT | HIDEHUD_ALL ) )
+ return 1;
+
+ int r, g, b, x, y, a;
+ wrect_t rc;
+
+ if (!(gHUD.m_iWeaponBits & (1<<(WEAPON_SUIT)) ))
+ return 1;
+
+ if (m_fOn)
+ a = 225;
+ else
+ a = MIN_ALPHA;
+
+ if (m_flBat < 0.20)
+ UnpackRGB(r,g,b, RGB_REDISH);
+ else
+ {
+ gHUD.GetPrimaryHudColor(r, g, b);
+ }
+
+ ScaleColors(r, g, b, a);
+
+ y = (m_prc1->bottom - m_prc2->top)/2;
+ x = ScreenWidth() - m_iWidth - m_iWidth/2 ;
+
+ // Draw the flashlight casing
+ SPR_Set(m_hSprite1, r, g, b );
+ SPR_DrawAdditive( 0, x, y, m_prc1);
+
+ if ( m_fOn )
+ { // draw the flashlight beam
+ x = ScreenWidth() - m_iWidth/2;
+
+ SPR_Set( m_hBeam, r, g, b );
+ SPR_DrawAdditive( 0, x, y, m_prcBeam );
+ }
+
+ // draw the flashlight energy level
+ x = ScreenWidth() - m_iWidth - m_iWidth/2 ;
+ int iOffset = m_iWidth * (1.0 - m_flBat);
+ if (iOffset < m_iWidth)
+ {
+ rc = *m_prc2;
+ rc.left += iOffset;
+
+ SPR_Set(m_hSprite2, r, g, b );
+ SPR_DrawAdditive( 0, x + iOffset, y, &rc);
+ }
+
+
+ return 1;
}
\ No newline at end of file
diff --git a/main/source/cl_dll/geiger.cpp b/main/source/cl_dll/geiger.cpp
index 3085fd1f..20337cb2 100644
--- a/main/source/cl_dll/geiger.cpp
+++ b/main/source/cl_dll/geiger.cpp
@@ -1,63 +1,63 @@
-/***
-*
-* Copyright (c) 1999, Valve LLC. All rights reserved.
-*
-* This product contains software technology licensed from Id
-* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
-* All Rights Reserved.
-*
-* Use, distribution, and modification of this source code and/or resulting
-* object code is restricted to non-commercial enhancements to products from
-* Valve LLC. All other use, distribution, or modification is prohibited
-* without written permission from Valve LLC.
-*
-****/
-//
-// Geiger.cpp
-//
-// implementation of CHudAmmo class
-//
-
-#include "hud.h"
-#include "cl_util.h"
-#include
-#include
-#include
-
-#include "mod/AvHNetworkMessages.h"
-
-DECLARE_MESSAGE(m_Geiger, Geiger )
-
-int CHudGeiger::Init(void)
-{
- HOOK_MESSAGE( Geiger );
-
- m_iGeigerRange = 0;
- m_iFlags = 0;
-
- //gHUD.AddHudElem(this);
-
- srand( (unsigned)time( NULL ) );
-
- return 1;
-};
-
-int CHudGeiger::VidInit(void)
-{
- return 1;
-};
-
-int CHudGeiger::MsgFunc_Geiger(const char *pszName, int iSize, void *pbuf)
-{
- //update geiger data
- NetMsg_GeigerRange( pbuf, iSize, m_iGeigerRange );
- m_iGeigerRange <<= 2;
- m_iFlags |= HUD_ACTIVE;
-
- return 1;
-}
-
-int CHudGeiger::Draw (float flTime)
-{
- return 1;
-}
+/***
+*
+* Copyright (c) 1999, Valve LLC. All rights reserved.
+*
+* This product contains software technology licensed from Id
+* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
+* All Rights Reserved.
+*
+* Use, distribution, and modification of this source code and/or resulting
+* object code is restricted to non-commercial enhancements to products from
+* Valve LLC. All other use, distribution, or modification is prohibited
+* without written permission from Valve LLC.
+*
+****/
+//
+// Geiger.cpp
+//
+// implementation of CHudAmmo class
+//
+
+#include "hud.h"
+#include "cl_util.h"
+#include
+#include
+#include
+
+#include "mod/AvHNetworkMessages.h"
+
+DECLARE_MESSAGE(m_Geiger, Geiger )
+
+int CHudGeiger::Init(void)
+{
+ HOOK_MESSAGE( Geiger );
+
+ m_iGeigerRange = 0;
+ m_iFlags = 0;
+
+ //gHUD.AddHudElem(this);
+
+ srand( (unsigned)time( NULL ) );
+
+ return 1;
+};
+
+int CHudGeiger::VidInit(void)
+{
+ return 1;
+};
+
+int CHudGeiger::MsgFunc_Geiger(const char *pszName, int iSize, void *pbuf)
+{
+ //update geiger data
+ NetMsg_GeigerRange( pbuf, iSize, m_iGeigerRange );
+ m_iGeigerRange <<= 2;
+ m_iFlags |= HUD_ACTIVE;
+
+ return 1;
+}
+
+int CHudGeiger::Draw (float flTime)
+{
+ return 1;
+}
diff --git a/main/source/cl_dll/health.cpp b/main/source/cl_dll/health.cpp
index 75aabfc9..b0eb2ca5 100644
--- a/main/source/cl_dll/health.cpp
+++ b/main/source/cl_dll/health.cpp
@@ -1,487 +1,487 @@
-/***
-*
-* Copyright (c) 1999, Valve LLC. All rights reserved.
-*
-* This product contains software technology licensed from Id
-* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
-* All Rights Reserved.
-*
-* Use, distribution, and modification of this source code and/or resulting
-* object code is restricted to non-commercial enhancements to products from
-* Valve LLC. All other use, distribution, or modification is prohibited
-* without written permission from Valve LLC.
-*
-****/
-//
-// Health.cpp
-//
-// implementation of CHudHealth class
-//
-
-#include "stdio.h"
-#include "stdlib.h"
-#include "math.h"
-
-#include "hud.h"
-#include "cl_util.h"
-#include
-#include "mod/AvHHudConstants.h"
-#include "mod/AvHPlayerUpgrade.h"
-#include "mod/AvHNetworkMessages.h"
-
-DECLARE_MESSAGE(m_Health, Health )
-DECLARE_MESSAGE(m_Health, Damage )
-
-#define PAIN_NAME "sprites/%d_pain.spr"
-#define DAMAGE_NAME "sprites/%d_dmg.spr"
-
-int giDmgHeight, giDmgWidth;
-
-int giDmgFlags[NUM_DMG_TYPES] =
-{
- DMG_POISON,
- DMG_ACID,
- DMG_FREEZE|DMG_SLOWFREEZE,
- DMG_DROWN,
- DMG_BURN|DMG_SLOWBURN,
- DMG_NERVEGAS,
- DMG_RADIATION,
- DMG_SHOCK,
- DMG_CALTROP,
- DMG_TRANQ,
- DMG_CONCUSS,
- DMG_HALLUC
-};
-
-int CHudHealth::Init(void)
-{
- HOOK_MESSAGE(Health);
- HOOK_MESSAGE(Damage);
- //HOOK_MESSAGE(ClCorpse);
-
- m_iHealth = 100;
- m_fFade = 0;
- m_iFlags = 0;
- m_bitsDamage = 0;
- m_fAttackFront = m_fAttackRear = m_fAttackRight = m_fAttackLeft = 0;
- giDmgHeight = 0;
- giDmgWidth = 0;
-
- memset(m_dmg, 0, sizeof(DAMAGE_IMAGE) * NUM_DMG_TYPES);
-
-
- gHUD.AddHudElem(this);
- return 1;
-}
-
-void CHudHealth::Reset( void )
-{
- // make sure the pain compass is cleared when the player respawns
- m_fAttackFront = m_fAttackRear = m_fAttackRight = m_fAttackLeft = 0;
-
-
- // force all the flashing damage icons to expire
- m_bitsDamage = 0;
- for ( int i = 0; i < NUM_DMG_TYPES; i++ )
- {
- m_dmg[i].fExpire = 0;
- }
-}
-
-int CHudHealth::VidInit(void)
-{
- m_hSprite = 0;
-
- m_HUD_dmg_bio = gHUD.GetSpriteIndex( "dmg_bio" ) + 1;
- m_HUD_cross = gHUD.GetSpriteIndex( "cross" );
-
- giDmgHeight = gHUD.GetSpriteRect(m_HUD_dmg_bio).right - gHUD.GetSpriteRect(m_HUD_dmg_bio).left;
- giDmgWidth = gHUD.GetSpriteRect(m_HUD_dmg_bio).bottom - gHUD.GetSpriteRect(m_HUD_dmg_bio).top;
- return 1;
-}
-
-int CHudHealth:: MsgFunc_Health(const char *pszName, int iSize, void *pbuf )
-{
- int x;
- NetMsg_Health( pbuf, iSize, x );
-
- // TODO: update local health data
- m_iFlags |= HUD_ACTIVE;
-
- // Only update the fade if we've changed health
- if (x != m_iHealth)
- {
- // We're sent the health of the player we're observing as if it were our own
- m_fFade = FADE_TIME;
- m_iHealth = x;
- }
-
- return 2;
-}
-
-
-int CHudHealth:: MsgFunc_Damage(const char *pszName, int iSize, void *pbuf )
-{
- int armor, damageTaken;
- long bitsDamage;
- float origin[3];
- NetMsg_Damage( pbuf, iSize, armor, damageTaken, bitsDamage, origin );
-
- vec3_t vecFrom;
-
- for ( int i = 0 ; i < 3 ; i++)
- vecFrom[i] = origin[i];
-
- UpdateTiles(gHUD.m_flTime, bitsDamage);
-
- // Actually took damage?
- if ( damageTaken > 0 || armor > 0 )
- CalcDamageDirection(vecFrom);
-
- return 1;
-}
-
-
-// Returns back a color from the
-// Green <-> Yellow <-> Red ramp
-void CHudHealth::GetPainColor( int &r, int &g, int &b )
-{
- int theMaxHealth = gHUD.GetHUDMaxHealth();
-
- if (m_iHealth > theMaxHealth/4)
- {
- gHUD.GetPrimaryHudColor(r, g, b);
- }
- else
- {
- r = 250;
- g = 0;
- b = 0;
- }
-}
-
-int CHudHealth::Draw(float flTime)
-{
- int r, g, b;
- int a = 0, x, y;
- int HealthWidth;
-
- if ( /*!gHUD.GetIsAlive() ||*/ (gHUD.m_iHideHUDDisplay & HIDEHUD_HEALTH) /*|| gEngfuncs.IsSpectateOnly()*/ )
- return 1;
-
- if ( !m_hSprite )
- m_hSprite = LoadSprite(PAIN_NAME);
-
- // Has health changed? Flash the health #
- if (m_fFade)
- {
- m_fFade -= (gHUD.m_flTimeDelta * 20);
- if (m_fFade <= 0)
- {
- a = MIN_ALPHA;
- m_fFade = 0;
- }
-
- // Fade the health number back to dim
-
- a = MIN_ALPHA + (m_fFade/FADE_TIME) * 128;
-
- }
- else
- a = MIN_ALPHA;
-
- // Potentially se upgrades and health of spectator target
- int theUpgrades = gHUD.GetHUDUpgrades();
-
- // If health is getting low, make it bright red
- int theMaxHealth = gHUD.GetHUDMaxHealth();
- if (m_iHealth <= theMaxHealth/10)
- {
- a = 255;
- }
-
- GetPainColor( r, g, b );
- ScaleColors(r, g, b, a );
-
- int theViewport[4];
- gHUD.GetViewport(theViewport);
-
- // Only draw health if we have the suit.
- if (gHUD.m_iWeaponBits & (1<<(WEAPON_SUIT)))
- {
- HealthWidth = gHUD.GetSpriteRect(gHUD.m_HUD_number_0).right - gHUD.GetSpriteRect(gHUD.m_HUD_number_0).left;
- int CrossWidth = gHUD.GetSpriteRect(m_HUD_cross).right - gHUD.GetSpriteRect(m_HUD_cross).left;
-
- y = theViewport[1] + theViewport[3] - gHUD.m_iFontHeight - gHUD.m_iFontHeight / 2;
-
- x = theViewport[0] + CrossWidth /2;
-
- int theInset = 0;
- if(gHUD.GetIsAlien() && !gHUD.GetIsCombatMode())
- {
- theInset = ScreenWidth()*kResourceEnergyBarWidth;
- }
- x += theInset;// + kHealthLeftInset*ScreenWidth;
-
- SPR_Set(gHUD.GetSprite(m_HUD_cross), r, g, b);
- SPR_DrawAdditive(0, x, y, &gHUD.GetSpriteRect(m_HUD_cross));
-
- x += CrossWidth + HealthWidth / 2;
-
- x = gHUD.DrawHudNumber(x, y, DHN_3DIGITS | DHN_DRAWZERO, m_iHealth, r, g, b);
-
- x += HealthWidth/2;
-
- gHUD.GetPrimaryHudColor(r, g, b);
-
- int iHeight = gHUD.m_iFontHeight;
- int iWidth = HealthWidth/10;
- FillRGBA(x, y, iWidth, iHeight, r, g, b, a);
- }
-
- DrawDamage(flTime);
- return DrawPain(flTime);
-}
-
-void CHudHealth::CalcDamageDirection(vec3_t vecFrom)
-{
- vec3_t forward, right, up;
- float side, front;
- vec3_t vecOrigin, vecAngles;
-
- if (!vecFrom[0] && !vecFrom[1] && !vecFrom[2])
- {
- m_fAttackFront = m_fAttackRear = m_fAttackRight = m_fAttackLeft = 0;
- return;
- }
-
-
- memcpy(vecOrigin, gHUD.m_vecOrigin, sizeof(vec3_t));
- memcpy(vecAngles, gHUD.m_vecAngles, sizeof(vec3_t));
-
-
- VectorSubtract (vecFrom, vecOrigin, vecFrom);
-
- float flDistToTarget = vecFrom.Length();
-
- vecFrom = vecFrom.Normalize();
- AngleVectors (vecAngles, forward, right, up);
-
- front = DotProduct (vecFrom, right);
- side = DotProduct (vecFrom, forward);
-
- if (flDistToTarget <= 50)
- {
- m_fAttackFront = m_fAttackRear = m_fAttackRight = m_fAttackLeft = 1;
- }
- else
- {
- if (side > 0)
- {
- if (side > 0.3)
- m_fAttackFront = max(m_fAttackFront, side);
- }
- else
- {
- float f = fabs(side);
- if (f > 0.3)
- m_fAttackRear = max(m_fAttackRear, f);
- }
-
- if (front > 0)
- {
- if (front > 0.3)
- m_fAttackRight = max(m_fAttackRight, front);
- }
- else
- {
- float f = fabs(front);
- if (f > 0.3)
- m_fAttackLeft = max(m_fAttackLeft, f);
- }
- }
-}
-
-int CHudHealth::DrawPain(float flTime)
-{
- if (!(m_fAttackFront || m_fAttackRear || m_fAttackLeft || m_fAttackRight))
- return 1;
-
- int r, g, b;
- int x, y, a, shade;
-
- // TODO: get the shift value of the health
- a = 255; // max brightness until then
-
- float fFade = gHUD.m_flTimeDelta * 2;
-
- // SPR_Draw top
- if (m_fAttackFront > 0.4)
- {
- GetPainColor(r,g,b);
- shade = a * max( m_fAttackFront, 0.5 );
- ScaleColors(r, g, b, shade);
- SPR_Set(m_hSprite, r, g, b );
-
- x = ScreenWidth()/2 - SPR_Width(m_hSprite, 0)/2;
- y = ScreenHeight()/2 - SPR_Height(m_hSprite,0) * 3;
- SPR_DrawAdditive(0, x, y, NULL);
- m_fAttackFront = max( 0, m_fAttackFront - fFade );
- } else
- m_fAttackFront = 0;
-
- if (m_fAttackRight > 0.4)
- {
- GetPainColor(r,g,b);
- shade = a * max( m_fAttackRight, 0.5 );
- ScaleColors(r, g, b, shade);
- SPR_Set(m_hSprite, r, g, b );
-
- x = ScreenWidth()/2 + SPR_Width(m_hSprite, 1) * 2;
- y = ScreenHeight()/2 - SPR_Height(m_hSprite,1)/2;
- SPR_DrawAdditive(1, x, y, NULL);
- m_fAttackRight = max( 0, m_fAttackRight - fFade );
- } else
- m_fAttackRight = 0;
-
- if (m_fAttackRear > 0.4)
- {
- GetPainColor(r,g,b);
- shade = a * max( m_fAttackRear, 0.5 );
- ScaleColors(r, g, b, shade);
- SPR_Set(m_hSprite, r, g, b );
-
- x = ScreenWidth()/2 - SPR_Width(m_hSprite, 2)/2;
- y = ScreenHeight()/2 + SPR_Height(m_hSprite,2) * 2;
- SPR_DrawAdditive(2, x, y, NULL);
- m_fAttackRear = max( 0, m_fAttackRear - fFade );
- } else
- m_fAttackRear = 0;
-
- if (m_fAttackLeft > 0.4)
- {
- GetPainColor(r,g,b);
- shade = a * max( m_fAttackLeft, 0.5 );
- ScaleColors(r, g, b, shade);
- SPR_Set(m_hSprite, r, g, b );
-
- x = ScreenWidth()/2 - SPR_Width(m_hSprite, 3) * 3;
- y = ScreenHeight()/2 - SPR_Height(m_hSprite,3)/2;
- SPR_DrawAdditive(3, x, y, NULL);
-
- m_fAttackLeft = max( 0, m_fAttackLeft - fFade );
- } else
- m_fAttackLeft = 0;
-
- return 1;
-}
-
-int CHudHealth::DrawDamage(float flTime)
-{
- int r, g, b, a;
- DAMAGE_IMAGE *pdmg;
-
- if (!m_bitsDamage)
- return 1;
-
- gHUD.GetPrimaryHudColor(r, g, b);
- a = (int)( fabs(sin(flTime*2)) * 256.0);
-
- ScaleColors(r, g, b, a);
-
- // Draw all the items
- int i;
- for (i = 0; i < NUM_DMG_TYPES; i++)
- {
- if (m_bitsDamage & giDmgFlags[i])
- {
- pdmg = &m_dmg[i];
- SPR_Set(gHUD.GetSprite(m_HUD_dmg_bio + i), r, g, b );
- SPR_DrawAdditive(0, pdmg->x, pdmg->y, &gHUD.GetSpriteRect(m_HUD_dmg_bio + i));
- }
- }
-
-
- // check for bits that should be expired
- for ( i = 0; i < NUM_DMG_TYPES; i++ )
- {
- DAMAGE_IMAGE *pdmg = &m_dmg[i];
-
- if ( m_bitsDamage & giDmgFlags[i] )
- {
- pdmg->fExpire = min( flTime + DMG_IMAGE_LIFE, pdmg->fExpire );
-
- if ( pdmg->fExpire <= flTime // when the time has expired
- && a < 40 ) // and the flash is at the low point of the cycle
- {
- pdmg->fExpire = 0;
-
- int y = pdmg->y;
- pdmg->x = pdmg->y = 0;
-
- // move everyone above down
- for (int j = 0; j < NUM_DMG_TYPES; j++)
- {
- pdmg = &m_dmg[j];
- if ((pdmg->y) && (pdmg->y < y))
- pdmg->y += giDmgHeight;
-
- }
-
- m_bitsDamage &= ~giDmgFlags[i]; // clear the bits
- }
- }
- }
-
- return 1;
-}
-
-
-void CHudHealth::UpdateTiles(float flTime, long bitsDamage)
-{
- DAMAGE_IMAGE *pdmg;
-
- // Which types are new?
- long bitsOn = ~m_bitsDamage & bitsDamage;
-
- for (int i = 0; i < NUM_DMG_TYPES; i++)
- {
- pdmg = &m_dmg[i];
-
- // Is this one already on?
- if (m_bitsDamage & giDmgFlags[i])
- {
- pdmg->fExpire = flTime + DMG_IMAGE_LIFE; // extend the duration
- if (!pdmg->fBaseline)
- pdmg->fBaseline = flTime;
- }
-
- // Are we just turning it on?
- if (bitsOn & giDmgFlags[i])
- {
- // put this one at the bottom
- pdmg->x = giDmgWidth/8;
- pdmg->y = ScreenHeight() - giDmgHeight * 2;
- pdmg->fExpire=flTime + DMG_IMAGE_LIFE;
-
- // move everyone else up
- for (int j = 0; j < NUM_DMG_TYPES; j++)
- {
- if (j == i)
- continue;
-
- pdmg = &m_dmg[j];
- if (pdmg->y)
- pdmg->y -= giDmgHeight;
-
- }
- pdmg = &m_dmg[i];
- }
- }
-
- // damage bits are only turned on here; they are turned off when the draw time has expired (in DrawDamage())
- m_bitsDamage |= bitsDamage;
-}
-
-
-void CreateCorpse ( Vector vOrigin, Vector vAngles, const char *pModel, float flAnimTime, int iSequence, int iBody );
+/***
+*
+* Copyright (c) 1999, Valve LLC. All rights reserved.
+*
+* This product contains software technology licensed from Id
+* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
+* All Rights Reserved.
+*
+* Use, distribution, and modification of this source code and/or resulting
+* object code is restricted to non-commercial enhancements to products from
+* Valve LLC. All other use, distribution, or modification is prohibited
+* without written permission from Valve LLC.
+*
+****/
+//
+// Health.cpp
+//
+// implementation of CHudHealth class
+//
+
+#include "stdio.h"
+#include "stdlib.h"
+#include "math.h"
+
+#include "hud.h"
+#include "cl_util.h"
+#include
+#include "mod/AvHHudConstants.h"
+#include "mod/AvHPlayerUpgrade.h"
+#include "mod/AvHNetworkMessages.h"
+
+DECLARE_MESSAGE(m_Health, Health )
+DECLARE_MESSAGE(m_Health, Damage )
+
+#define PAIN_NAME "sprites/%d_pain.spr"
+#define DAMAGE_NAME "sprites/%d_dmg.spr"
+
+int giDmgHeight, giDmgWidth;
+
+int giDmgFlags[NUM_DMG_TYPES] =
+{
+ DMG_POISON,
+ DMG_ACID,
+ DMG_FREEZE|DMG_SLOWFREEZE,
+ DMG_DROWN,
+ DMG_BURN|DMG_SLOWBURN,
+ DMG_NERVEGAS,
+ DMG_RADIATION,
+ DMG_SHOCK,
+ DMG_CALTROP,
+ DMG_TRANQ,
+ DMG_CONCUSS,
+ DMG_HALLUC
+};
+
+int CHudHealth::Init(void)
+{
+ HOOK_MESSAGE(Health);
+ HOOK_MESSAGE(Damage);
+ //HOOK_MESSAGE(ClCorpse);
+
+ m_iHealth = 100;
+ m_fFade = 0;
+ m_iFlags = 0;
+ m_bitsDamage = 0;
+ m_fAttackFront = m_fAttackRear = m_fAttackRight = m_fAttackLeft = 0;
+ giDmgHeight = 0;
+ giDmgWidth = 0;
+
+ memset(m_dmg, 0, sizeof(DAMAGE_IMAGE) * NUM_DMG_TYPES);
+
+
+ gHUD.AddHudElem(this);
+ return 1;
+}
+
+void CHudHealth::Reset( void )
+{
+ // make sure the pain compass is cleared when the player respawns
+ m_fAttackFront = m_fAttackRear = m_fAttackRight = m_fAttackLeft = 0;
+
+
+ // force all the flashing damage icons to expire
+ m_bitsDamage = 0;
+ for ( int i = 0; i < NUM_DMG_TYPES; i++ )
+ {
+ m_dmg[i].fExpire = 0;
+ }
+}
+
+int CHudHealth::VidInit(void)
+{
+ m_hSprite = 0;
+
+ m_HUD_dmg_bio = gHUD.GetSpriteIndex( "dmg_bio" ) + 1;
+ m_HUD_cross = gHUD.GetSpriteIndex( "cross" );
+
+ giDmgHeight = gHUD.GetSpriteRect(m_HUD_dmg_bio).right - gHUD.GetSpriteRect(m_HUD_dmg_bio).left;
+ giDmgWidth = gHUD.GetSpriteRect(m_HUD_dmg_bio).bottom - gHUD.GetSpriteRect(m_HUD_dmg_bio).top;
+ return 1;
+}
+
+int CHudHealth:: MsgFunc_Health(const char *pszName, int iSize, void *pbuf )
+{
+ int x;
+ NetMsg_Health( pbuf, iSize, x );
+
+ // TODO: update local health data
+ m_iFlags |= HUD_ACTIVE;
+
+ // Only update the fade if we've changed health
+ if (x != m_iHealth)
+ {
+ // We're sent the health of the player we're observing as if it were our own
+ m_fFade = FADE_TIME;
+ m_iHealth = x;
+ }
+
+ return 2;
+}
+
+
+int CHudHealth:: MsgFunc_Damage(const char *pszName, int iSize, void *pbuf )
+{
+ int armor, damageTaken;
+ long bitsDamage;
+ float origin[3];
+ NetMsg_Damage( pbuf, iSize, armor, damageTaken, bitsDamage, origin );
+
+ vec3_t vecFrom;
+
+ for ( int i = 0 ; i < 3 ; i++)
+ vecFrom[i] = origin[i];
+
+ UpdateTiles(gHUD.m_flTime, bitsDamage);
+
+ // Actually took damage?
+ if ( damageTaken > 0 || armor > 0 )
+ CalcDamageDirection(vecFrom);
+
+ return 1;
+}
+
+
+// Returns back a color from the
+// Green <-> Yellow <-> Red ramp
+void CHudHealth::GetPainColor( int &r, int &g, int &b )
+{
+ int theMaxHealth = gHUD.GetHUDMaxHealth();
+
+ if (m_iHealth > theMaxHealth/4)
+ {
+ gHUD.GetPrimaryHudColor(r, g, b);
+ }
+ else
+ {
+ r = 250;
+ g = 0;
+ b = 0;
+ }
+}
+
+int CHudHealth::Draw(float flTime)
+{
+ int r, g, b;
+ int a = 0, x, y;
+ int HealthWidth;
+
+ if ( /*!gHUD.GetIsAlive() ||*/ (gHUD.m_iHideHUDDisplay & HIDEHUD_HEALTH) /*|| gEngfuncs.IsSpectateOnly()*/ )
+ return 1;
+
+ if ( !m_hSprite )
+ m_hSprite = LoadSprite(PAIN_NAME);
+
+ // Has health changed? Flash the health #
+ if (m_fFade)
+ {
+ m_fFade -= (gHUD.m_flTimeDelta * 20);
+ if (m_fFade <= 0)
+ {
+ a = MIN_ALPHA;
+ m_fFade = 0;
+ }
+
+ // Fade the health number back to dim
+
+ a = MIN_ALPHA + (m_fFade/FADE_TIME) * 128;
+
+ }
+ else
+ a = MIN_ALPHA;
+
+ // Potentially se upgrades and health of spectator target
+ int theUpgrades = gHUD.GetHUDUpgrades();
+
+ // If health is getting low, make it bright red
+ int theMaxHealth = gHUD.GetHUDMaxHealth();
+ if (m_iHealth <= theMaxHealth/10)
+ {
+ a = 255;
+ }
+
+ GetPainColor( r, g, b );
+ ScaleColors(r, g, b, a );
+
+ int theViewport[4];
+ gHUD.GetViewport(theViewport);
+
+ // Only draw health if we have the suit.
+ if (gHUD.m_iWeaponBits & (1<<(WEAPON_SUIT)))
+ {
+ HealthWidth = gHUD.GetSpriteRect(gHUD.m_HUD_number_0).right - gHUD.GetSpriteRect(gHUD.m_HUD_number_0).left;
+ int CrossWidth = gHUD.GetSpriteRect(m_HUD_cross).right - gHUD.GetSpriteRect(m_HUD_cross).left;
+
+ y = theViewport[1] + theViewport[3] - gHUD.m_iFontHeight - gHUD.m_iFontHeight / 2;
+
+ x = theViewport[0] + CrossWidth /2;
+
+ int theInset = 0;
+ if(gHUD.GetIsAlien() && !gHUD.GetIsCombatMode())
+ {
+ theInset = ScreenWidth()*kResourceEnergyBarWidth;
+ }
+ x += theInset;// + kHealthLeftInset*ScreenWidth;
+
+ SPR_Set(gHUD.GetSprite(m_HUD_cross), r, g, b);
+ SPR_DrawAdditive(0, x, y, &gHUD.GetSpriteRect(m_HUD_cross));
+
+ x += CrossWidth + HealthWidth / 2;
+
+ x = gHUD.DrawHudNumber(x, y, DHN_3DIGITS | DHN_DRAWZERO, m_iHealth, r, g, b);
+
+ x += HealthWidth/2;
+
+ gHUD.GetPrimaryHudColor(r, g, b);
+
+ int iHeight = gHUD.m_iFontHeight;
+ int iWidth = HealthWidth/10;
+ FillRGBA(x, y, iWidth, iHeight, r, g, b, a);
+ }
+
+ DrawDamage(flTime);
+ return DrawPain(flTime);
+}
+
+void CHudHealth::CalcDamageDirection(vec3_t vecFrom)
+{
+ vec3_t forward, right, up;
+ float side, front;
+ vec3_t vecOrigin, vecAngles;
+
+ if (!vecFrom[0] && !vecFrom[1] && !vecFrom[2])
+ {
+ m_fAttackFront = m_fAttackRear = m_fAttackRight = m_fAttackLeft = 0;
+ return;
+ }
+
+
+ memcpy(vecOrigin, gHUD.m_vecOrigin, sizeof(vec3_t));
+ memcpy(vecAngles, gHUD.m_vecAngles, sizeof(vec3_t));
+
+
+ VectorSubtract (vecFrom, vecOrigin, vecFrom);
+
+ float flDistToTarget = vecFrom.Length();
+
+ vecFrom = vecFrom.Normalize();
+ AngleVectors (vecAngles, forward, right, up);
+
+ front = DotProduct (vecFrom, right);
+ side = DotProduct (vecFrom, forward);
+
+ if (flDistToTarget <= 50)
+ {
+ m_fAttackFront = m_fAttackRear = m_fAttackRight = m_fAttackLeft = 1;
+ }
+ else
+ {
+ if (side > 0)
+ {
+ if (side > 0.3)
+ m_fAttackFront = max(m_fAttackFront, side);
+ }
+ else
+ {
+ float f = fabs(side);
+ if (f > 0.3)
+ m_fAttackRear = max(m_fAttackRear, f);
+ }
+
+ if (front > 0)
+ {
+ if (front > 0.3)
+ m_fAttackRight = max(m_fAttackRight, front);
+ }
+ else
+ {
+ float f = fabs(front);
+ if (f > 0.3)
+ m_fAttackLeft = max(m_fAttackLeft, f);
+ }
+ }
+}
+
+int CHudHealth::DrawPain(float flTime)
+{
+ if (!(m_fAttackFront || m_fAttackRear || m_fAttackLeft || m_fAttackRight))
+ return 1;
+
+ int r, g, b;
+ int x, y, a, shade;
+
+ // TODO: get the shift value of the health
+ a = 255; // max brightness until then
+
+ float fFade = gHUD.m_flTimeDelta * 2;
+
+ // SPR_Draw top
+ if (m_fAttackFront > 0.4)
+ {
+ GetPainColor(r,g,b);
+ shade = a * max( m_fAttackFront, 0.5 );
+ ScaleColors(r, g, b, shade);
+ SPR_Set(m_hSprite, r, g, b );
+
+ x = ScreenWidth()/2 - SPR_Width(m_hSprite, 0)/2;
+ y = ScreenHeight()/2 - SPR_Height(m_hSprite,0) * 3;
+ SPR_DrawAdditive(0, x, y, NULL);
+ m_fAttackFront = max( 0, m_fAttackFront - fFade );
+ } else
+ m_fAttackFront = 0;
+
+ if (m_fAttackRight > 0.4)
+ {
+ GetPainColor(r,g,b);
+ shade = a * max( m_fAttackRight, 0.5 );
+ ScaleColors(r, g, b, shade);
+ SPR_Set(m_hSprite, r, g, b );
+
+ x = ScreenWidth()/2 + SPR_Width(m_hSprite, 1) * 2;
+ y = ScreenHeight()/2 - SPR_Height(m_hSprite,1)/2;
+ SPR_DrawAdditive(1, x, y, NULL);
+ m_fAttackRight = max( 0, m_fAttackRight - fFade );
+ } else
+ m_fAttackRight = 0;
+
+ if (m_fAttackRear > 0.4)
+ {
+ GetPainColor(r,g,b);
+ shade = a * max( m_fAttackRear, 0.5 );
+ ScaleColors(r, g, b, shade);
+ SPR_Set(m_hSprite, r, g, b );
+
+ x = ScreenWidth()/2 - SPR_Width(m_hSprite, 2)/2;
+ y = ScreenHeight()/2 + SPR_Height(m_hSprite,2) * 2;
+ SPR_DrawAdditive(2, x, y, NULL);
+ m_fAttackRear = max( 0, m_fAttackRear - fFade );
+ } else
+ m_fAttackRear = 0;
+
+ if (m_fAttackLeft > 0.4)
+ {
+ GetPainColor(r,g,b);
+ shade = a * max( m_fAttackLeft, 0.5 );
+ ScaleColors(r, g, b, shade);
+ SPR_Set(m_hSprite, r, g, b );
+
+ x = ScreenWidth()/2 - SPR_Width(m_hSprite, 3) * 3;
+ y = ScreenHeight()/2 - SPR_Height(m_hSprite,3)/2;
+ SPR_DrawAdditive(3, x, y, NULL);
+
+ m_fAttackLeft = max( 0, m_fAttackLeft - fFade );
+ } else
+ m_fAttackLeft = 0;
+
+ return 1;
+}
+
+int CHudHealth::DrawDamage(float flTime)
+{
+ int r, g, b, a;
+ DAMAGE_IMAGE *pdmg;
+
+ if (!m_bitsDamage)
+ return 1;
+
+ gHUD.GetPrimaryHudColor(r, g, b);
+ a = (int)( fabs(sin(flTime*2)) * 256.0);
+
+ ScaleColors(r, g, b, a);
+
+ // Draw all the items
+ int i;
+ for (i = 0; i < NUM_DMG_TYPES; i++)
+ {
+ if (m_bitsDamage & giDmgFlags[i])
+ {
+ pdmg = &m_dmg[i];
+ SPR_Set(gHUD.GetSprite(m_HUD_dmg_bio + i), r, g, b );
+ SPR_DrawAdditive(0, pdmg->x, pdmg->y, &gHUD.GetSpriteRect(m_HUD_dmg_bio + i));
+ }
+ }
+
+
+ // check for bits that should be expired
+ for ( i = 0; i < NUM_DMG_TYPES; i++ )
+ {
+ DAMAGE_IMAGE *pdmg = &m_dmg[i];
+
+ if ( m_bitsDamage & giDmgFlags[i] )
+ {
+ pdmg->fExpire = min( flTime + DMG_IMAGE_LIFE, pdmg->fExpire );
+
+ if ( pdmg->fExpire <= flTime // when the time has expired
+ && a < 40 ) // and the flash is at the low point of the cycle
+ {
+ pdmg->fExpire = 0;
+
+ int y = pdmg->y;
+ pdmg->x = pdmg->y = 0;
+
+ // move everyone above down
+ for (int j = 0; j < NUM_DMG_TYPES; j++)
+ {
+ pdmg = &m_dmg[j];
+ if ((pdmg->y) && (pdmg->y < y))
+ pdmg->y += giDmgHeight;
+
+ }
+
+ m_bitsDamage &= ~giDmgFlags[i]; // clear the bits
+ }
+ }
+ }
+
+ return 1;
+}
+
+
+void CHudHealth::UpdateTiles(float flTime, long bitsDamage)
+{
+ DAMAGE_IMAGE *pdmg;
+
+ // Which types are new?
+ long bitsOn = ~m_bitsDamage & bitsDamage;
+
+ for (int i = 0; i < NUM_DMG_TYPES; i++)
+ {
+ pdmg = &m_dmg[i];
+
+ // Is this one already on?
+ if (m_bitsDamage & giDmgFlags[i])
+ {
+ pdmg->fExpire = flTime + DMG_IMAGE_LIFE; // extend the duration
+ if (!pdmg->fBaseline)
+ pdmg->fBaseline = flTime;
+ }
+
+ // Are we just turning it on?
+ if (bitsOn & giDmgFlags[i])
+ {
+ // put this one at the bottom
+ pdmg->x = giDmgWidth/8;
+ pdmg->y = ScreenHeight() - giDmgHeight * 2;
+ pdmg->fExpire=flTime + DMG_IMAGE_LIFE;
+
+ // move everyone else up
+ for (int j = 0; j < NUM_DMG_TYPES; j++)
+ {
+ if (j == i)
+ continue;
+
+ pdmg = &m_dmg[j];
+ if (pdmg->y)
+ pdmg->y -= giDmgHeight;
+
+ }
+ pdmg = &m_dmg[i];
+ }
+ }
+
+ // damage bits are only turned on here; they are turned off when the draw time has expired (in DrawDamage())
+ m_bitsDamage |= bitsDamage;
+}
+
+
+void CreateCorpse ( Vector vOrigin, Vector vAngles, const char *pModel, float flAnimTime, int iSequence, int iBody );
diff --git a/main/source/cl_dll/health.h b/main/source/cl_dll/health.h
index c108b0be..737089d4 100644
--- a/main/source/cl_dll/health.h
+++ b/main/source/cl_dll/health.h
@@ -1,117 +1,117 @@
-/***
-*
-* Copyright (c) 1999, Valve LLC. All rights reserved.
-*
-* This product contains software technology licensed from Id
-* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
-* All Rights Reserved.
-*
-* Use, distribution, and modification of this source code and/or resulting
-* object code is restricted to non-commercial enhancements to products from
-* Valve LLC. All other use, distribution, or modification is prohibited
-* without written permission from Valve LLC.
-*
-****/
-
-#ifndef HEALTH_H
-#define HEALTH_H
-
-#define DMG_IMAGE_LIFE 2 // seconds that image is up
-
-#define DMG_IMAGE_POISON 0
-#define DMG_IMAGE_ACID 1
-#define DMG_IMAGE_COLD 2
-#define DMG_IMAGE_DROWN 3
-#define DMG_IMAGE_BURN 4
-#define DMG_IMAGE_NERVE 5
-#define DMG_IMAGE_RAD 6
-#define DMG_IMAGE_SHOCK 7
-//tf defines
-#define DMG_IMAGE_CALTROP 8
-#define DMG_IMAGE_TRANQ 9
-#define DMG_IMAGE_CONCUSS 10
-#define DMG_IMAGE_HALLUC 11
-#define NUM_DMG_TYPES 12
-// instant damage
-
-//// time-based damage
-////mask off TF-specific stuff too
-//#define DMG_TIMEBASED (~(0xff003fff)) // mask for time-based damage
-//
-//
-//#define DMG_DROWN (1 << 14) // Drowning
-//#define DMG_FIRSTTIMEBASED DMG_DROWN
-//
-//#define DMG_PARALYZE (1 << 15) // slows affected creature down
-//#define DMG_NERVEGAS (1 << 16) // nerve toxins, very bad
-//#define DMG_POISON (1 << 17) // blood poisioning
-//#define DMG_RADIATION (1 << 18) // radiation exposure
-//#define DMG_DROWNRECOVER (1 << 19) // drowning recovery
-//#define DMG_ACID (1 << 20) // toxic chemicals or acid burns
-//#define DMG_SLOWBURN (1 << 21) // in an oven
-//#define DMG_SLOWFREEZE (1 << 22) // in a subzero freezer
-//#define DMG_MORTAR (1 << 23) // Hit by air raid (done to distinguish grenade from mortar)
-//
-////TF ADDITIONS
-//#define DMG_IGNITE (1 << 24) // Players hit by this begin to burn
-//#define DMG_RADIUS_MAX (1 << 25) // Radius damage with this flag doesn't decrease over distance
-//#define DMG_RADIUS_QUAKE (1 << 26) // Radius damage is done like Quake. 1/2 damage at 1/2 radius.
-//#define DMG_IGNOREARMOR (1 << 27) // Damage ignores target's armor
-//#define DMG_AIMED (1 << 28) // Does Hit location damage
-//#define DMG_WALLPIERCING (1 << 29) // Blast Damages ents through walls
-//
-//#define DMG_CALTROP (1<<30)
-//#define DMG_HALLUC (1<<31)
-#include "damagetypes.h"
-
-// TF Healing Additions for TakeHealth
-#define DMG_IGNORE_MAXHEALTH DMG_IGNITE
-// TF Redefines since we never use the originals
-#define DMG_NAIL DMG_SLASH
-#define DMG_NOT_SELF DMG_FREEZE
-
-
-#define DMG_TRANQ DMG_MORTAR
-#define DMG_CONCUSS DMG_SONIC
-
-
-
-typedef struct
-{
- float fExpire;
- float fBaseline;
- int x, y;
-} DAMAGE_IMAGE;
-
-//
-//-----------------------------------------------------
-//
-class CHudHealth: public CHudBase
-{
-public:
- virtual int Init( void );
- virtual int VidInit( void );
- virtual int Draw(float fTime);
- virtual void Reset( void );
- int MsgFunc_Health(const char *pszName, int iSize, void *pbuf);
- int MsgFunc_Damage(const char *pszName, int iSize, void *pbuf);
- int m_iHealth;
- int m_HUD_dmg_bio;
- int m_HUD_cross;
- float m_fAttackFront, m_fAttackRear, m_fAttackLeft, m_fAttackRight;
- void GetPainColor( int &r, int &g, int &b );
- float m_fFade;
-
-private:
- HSPRITE m_hSprite;
- HSPRITE m_hDamage;
-
- DAMAGE_IMAGE m_dmg[NUM_DMG_TYPES];
- int m_bitsDamage;
- int DrawPain(float fTime);
- int DrawDamage(float fTime);
- void CalcDamageDirection(vec3_t vecFrom);
- void UpdateTiles(float fTime, long bits);
-};
-
-#endif
+/***
+*
+* Copyright (c) 1999, Valve LLC. All rights reserved.
+*
+* This product contains software technology licensed from Id
+* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
+* All Rights Reserved.
+*
+* Use, distribution, and modification of this source code and/or resulting
+* object code is restricted to non-commercial enhancements to products from
+* Valve LLC. All other use, distribution, or modification is prohibited
+* without written permission from Valve LLC.
+*
+****/
+
+#ifndef HEALTH_H
+#define HEALTH_H
+
+#define DMG_IMAGE_LIFE 2 // seconds that image is up
+
+#define DMG_IMAGE_POISON 0
+#define DMG_IMAGE_ACID 1
+#define DMG_IMAGE_COLD 2
+#define DMG_IMAGE_DROWN 3
+#define DMG_IMAGE_BURN 4
+#define DMG_IMAGE_NERVE 5
+#define DMG_IMAGE_RAD 6
+#define DMG_IMAGE_SHOCK 7
+//tf defines
+#define DMG_IMAGE_CALTROP 8
+#define DMG_IMAGE_TRANQ 9
+#define DMG_IMAGE_CONCUSS 10
+#define DMG_IMAGE_HALLUC 11
+#define NUM_DMG_TYPES 12
+// instant damage
+
+//// time-based damage
+////mask off TF-specific stuff too
+//#define DMG_TIMEBASED (~(0xff003fff)) // mask for time-based damage
+//
+//
+//#define DMG_DROWN (1 << 14) // Drowning
+//#define DMG_FIRSTTIMEBASED DMG_DROWN
+//
+//#define DMG_PARALYZE (1 << 15) // slows affected creature down
+//#define DMG_NERVEGAS (1 << 16) // nerve toxins, very bad
+//#define DMG_POISON (1 << 17) // blood poisioning
+//#define DMG_RADIATION (1 << 18) // radiation exposure
+//#define DMG_DROWNRECOVER (1 << 19) // drowning recovery
+//#define DMG_ACID (1 << 20) // toxic chemicals or acid burns
+//#define DMG_SLOWBURN (1 << 21) // in an oven
+//#define DMG_SLOWFREEZE (1 << 22) // in a subzero freezer
+//#define DMG_MORTAR (1 << 23) // Hit by air raid (done to distinguish grenade from mortar)
+//
+////TF ADDITIONS
+//#define DMG_IGNITE (1 << 24) // Players hit by this begin to burn
+//#define DMG_RADIUS_MAX (1 << 25) // Radius damage with this flag doesn't decrease over distance
+//#define DMG_RADIUS_QUAKE (1 << 26) // Radius damage is done like Quake. 1/2 damage at 1/2 radius.
+//#define DMG_IGNOREARMOR (1 << 27) // Damage ignores target's armor
+//#define DMG_AIMED (1 << 28) // Does Hit location damage
+//#define DMG_WALLPIERCING (1 << 29) // Blast Damages ents through walls
+//
+//#define DMG_CALTROP (1<<30)
+//#define DMG_HALLUC (1<<31)
+#include "damagetypes.h"
+
+// TF Healing Additions for TakeHealth
+#define DMG_IGNORE_MAXHEALTH DMG_IGNITE
+// TF Redefines since we never use the originals
+#define DMG_NAIL DMG_SLASH
+#define DMG_NOT_SELF DMG_FREEZE
+
+
+#define DMG_TRANQ DMG_MORTAR
+#define DMG_CONCUSS DMG_SONIC
+
+
+
+typedef struct
+{
+ float fExpire;
+ float fBaseline;
+ int x, y;
+} DAMAGE_IMAGE;
+
+//
+//-----------------------------------------------------
+//
+class CHudHealth: public CHudBase
+{
+public:
+ virtual int Init( void );
+ virtual int VidInit( void );
+ virtual int Draw(float fTime);
+ virtual void Reset( void );
+ int MsgFunc_Health(const char *pszName, int iSize, void *pbuf);
+ int MsgFunc_Damage(const char *pszName, int iSize, void *pbuf);
+ int m_iHealth;
+ int m_HUD_dmg_bio;
+ int m_HUD_cross;
+ float m_fAttackFront, m_fAttackRear, m_fAttackLeft, m_fAttackRight;
+ void GetPainColor( int &r, int &g, int &b );
+ float m_fFade;
+
+private:
+ HSPRITE m_hSprite;
+ HSPRITE m_hDamage;
+
+ DAMAGE_IMAGE m_dmg[NUM_DMG_TYPES];
+ int m_bitsDamage;
+ int DrawPain(float fTime);
+ int DrawDamage(float fTime);
+ void CalcDamageDirection(vec3_t vecFrom);
+ void UpdateTiles(float fTime, long bits);
+};
+
+#endif
diff --git a/main/source/cl_dll/hl/hl_baseentity.cpp b/main/source/cl_dll/hl/hl_baseentity.cpp
index ab07154a..bd979c41 100644
--- a/main/source/cl_dll/hl/hl_baseentity.cpp
+++ b/main/source/cl_dll/hl/hl_baseentity.cpp
@@ -1,290 +1,290 @@
-/***
-*
-* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
-*
-* This product contains software technology licensed from Id
-* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
-* All Rights Reserved.
-*
-* Use, distribution, and modification of this source code and/or resulting
-* object code is restricted to non-commercial enhancements to products from
-* Valve LLC. All other use, distribution, or modification is prohibited
-* without written permission from Valve LLC.
-*
-****/
-
-/*
-==========================
-This file contains "stubs" of class member implementations so that we can predict certain
- weapons client side. From time to time you might find that you need to implement part of the
- these functions. If so, cut it from here, paste it in hl_weapons.cpp or somewhere else and
- add in the functionality you need.
-==========================
-*/
-#include "extdll.h"
-#include "util.h"
-#include "cbase.h"
-#include "player.h"
-#include "weapons.h"
-#include "nodes.h"
-#include "soundent.h"
-#include "skill.h"
-
-// Globals used by game logic
-const Vector g_vecZero = Vector( 0, 0, 0 );
-enginefuncs_t g_engfuncs;
-globalvars_t *gpGlobals;
-
-ItemInfo CBasePlayerItem::ItemInfoArray[MAX_WEAPONS];
-
-void EMIT_SOUND_DYN(edict_t *entity, int channel, const char *sample, float volume, float attenuation, int flags, int pitch) { }
-
-// CBaseEntity Stubs
-int CBaseEntity :: TakeHealth( float flHealth, int bitsDamageType ) { return 1; }
-int CBaseEntity :: TakeDamage( entvars_t* pevInflictor, entvars_t* pevAttacker, float flDamage, int bitsDamageType ) { return 1; }
-CBaseEntity *CBaseEntity::GetNextTarget( void ) { return NULL; }
-int CBaseEntity::Save( CSave &save ) { return 1; }
-int CBaseEntity::Restore( CRestore &restore ) { return 1; }
-void CBaseEntity::SetObjectCollisionBox( void ) { }
-int CBaseEntity :: Intersects( CBaseEntity *pOther ) { return 0; }
-void CBaseEntity :: MakeDormant( void ) { }
-int CBaseEntity :: IsDormant( void ) { return 0; }
-BOOL CBaseEntity :: IsInWorld( void ) { return TRUE; }
-int CBaseEntity::ShouldToggle( USE_TYPE useType, BOOL currentState ) { return 0; }
-int CBaseEntity :: DamageDecal( int bitsDamageType ) { return -1; }
-CBaseEntity * CBaseEntity::Create( const char *szName, const Vector &vecOrigin, const Vector &vecAngles, edict_t *pentOwner ) { return NULL; }
-void CBaseEntity::SUB_Remove( void ) { }
-void CBaseEntity::AddChecksum(Checksum& inChecksum) {}
-void CBaseEntity::UpdateOnRemove() {}
-
-// CBaseDelay Stubs
-void CBaseDelay :: KeyValue( struct KeyValueData_s * ) { }
-int CBaseDelay::Restore( class CRestore & ) { return 1; }
-int CBaseDelay::Save( class CSave & ) { return 1; }
-
-// CBaseAnimating Stubs
-int CBaseAnimating::Restore( class CRestore & ) { return 1; }
-int CBaseAnimating::Save( class CSave & ) { return 1; }
-
-// DEBUG Stubs
-edict_t *DBG_EntOfVars( const entvars_t *pev ) { return NULL; }
-
-// UTIL_* Stubs
-void UTIL_PrecacheOther( const char *szClassname ) { }
-void UTIL_BloodDrips( const Vector &origin, const Vector &direction, int color, int amount ) { }
-void UTIL_DecalTrace( TraceResult *pTrace, int decalNumber ) { }
-void UTIL_GunshotDecalTrace( TraceResult *pTrace, int decalNumber ) { }
-void UTIL_MakeVectors( const Vector &vecAngles ) { }
-BOOL UTIL_IsValidEntity( edict_t *pent ) { return TRUE; }
-void UTIL_SetOrigin( entvars_t *, const Vector &org ) { }
-BOOL UTIL_GetNextBestWeapon( CBasePlayer *pPlayer, CBasePlayerItem *pCurrentWeapon ) { return TRUE; }
-void UTIL_LogPrintf(char *,...) { }
-void UTIL_ClientPrintAll( int,char const *,char const *,char const *,char const *,char const *) { }
-void ClientPrint( entvars_t *client, int msg_dest, const char *msg_name, const char *param1, const char *param2, const char *param3, const char *param4 ) { }
-
-// CBaseToggle Stubs
-int CBaseToggle::Restore( class CRestore & ) { return 1; }
-int CBaseToggle::Save( class CSave & ) { return 1; }
-void CBaseToggle :: KeyValue( struct KeyValueData_s * ) { }
-void CBaseToggle::SaveDataForReset() {}
-void CBaseToggle::ResetEntity() {}
-
-// CGrenade Stubs
-void CGrenade::BounceSound( void ) { }
-void CGrenade::Explode( Vector, Vector ) { }
-void CGrenade::Explode( TraceResult *, int ) { }
-void CGrenade::Killed( entvars_t *, int ) { }
-void CGrenade::Spawn( void ) { }
-CGrenade * CGrenade:: ShootTimed( entvars_t *pevOwner, Vector vecStart, Vector vecVelocity, float time ){ return 0; }
-CGrenade *CGrenade::ShootContact( entvars_t *pevOwner, Vector vecStart, Vector vecVelocity ){ return 0; }
-void CGrenade::DetonateUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ){ }
-void CGrenade::SetDamageType(int inDamageType) {} //@linux otherwise it says undefined symbol
-
-void UTIL_Remove( CBaseEntity *pEntity ){ }
-struct skilldata_t gSkillData;
-void UTIL_SetSize( entvars_t *pev, const Vector &vecMin, const Vector &vecMax ){ }
-CBaseEntity *UTIL_FindEntityInSphere( CBaseEntity *pStartEntity, const Vector &vecCenter, float flRadius ){ return 0;}
-
-Vector UTIL_VecToAngles( const Vector &vec ){ return 0; }
-CSprite *CSprite::SpriteCreate( const char *pSpriteName, const Vector &origin, BOOL animate ) { return 0; }
-void CBeam::PointEntInit( const Vector &start, int endIndex ) { }
-CBeam *CBeam::BeamCreate( const char *pSpriteName, int width ) { return NULL; }
-void CSprite::Expand( float scaleSpeed, float fadeSpeed ) { }
-
-
-CBaseEntity* CBaseMonster :: CheckTraceHullAttack( float flDist, float& ioDamage, int iDmgType ) { return NULL; }
-int CBaseMonster::GetHull() const { return head_hull; }
-void CBaseMonster :: Look ( int iDistance ) { }
-float CBaseAnimating :: StudioFrameAdvance ( float flInterval ) { return 0.0; }
-int CBaseMonster::IRelationship ( CBaseEntity *pTarget ) { return 0; }
-CBaseEntity *CBaseMonster :: BestVisibleEnemy ( void ) { return NULL; }
-BOOL CBaseMonster :: FInViewCone ( CBaseEntity *pEntity ) { return FALSE; }
-BOOL CBaseMonster :: FInViewCone ( Vector *pOrigin ) { return FALSE; }
-BOOL CBaseEntity :: FVisible ( CBaseEntity *pEntity ) { return FALSE; }
-BOOL CBaseEntity :: FVisible ( const Vector &vecOrigin ) { return FALSE; }
-void CBaseMonster :: MakeIdealYaw( Vector vecTarget ) { }
-float CBaseMonster::ChangeYaw ( int yawSpeed ) { return 0; }
-int CBaseAnimating :: LookupActivity ( int activity ) { return 0; }
-int CBaseAnimating :: LookupActivityHeaviest ( int activity ) { return 0; }
-int CBaseAnimating :: LookupSequence ( const char *label, int queue ) { return 0; }
-void CBaseAnimating :: ResetSequenceInfo ( ) { }
-BOOL CBaseAnimating :: GetSequenceFlags( ) { return FALSE; }
-void CBaseAnimating :: DispatchAnimEvents ( float flInterval ) { }
-float CBaseAnimating :: SetBoneController ( int iController, float flValue ) { return 0.0; }
-void CBaseAnimating :: InitBoneControllers ( void ) { }
-float CBaseAnimating :: SetBlending ( int iBlender, float flValue ) { return 0; }
-void CBaseAnimating :: GetBonePosition ( int iBone, Vector &origin, Vector &angles ) { }
-void CBaseAnimating :: GetAttachment ( int iAttachment, Vector &origin, Vector &angles ) { }
-int CBaseAnimating :: FindTransition( int iEndingSequence, int iGoalSequence, int *piDir ) { return -1; }
-void CBaseAnimating :: GetAutomovement( Vector &origin, Vector &angles, float flInterval ) { }
-void CBaseAnimating :: SetBodygroup( int iGroup, int iValue ) { }
-int CBaseAnimating :: GetBodygroup( int iGroup ) { return 0; }
-void CBaseEntity::TraceAttack(entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType) { }
-void CBaseEntity::FireBullets(ULONG cShots, Vector vecSrc, Vector vecDirShooting, Vector vecSpread, float flDistance, int iBulletType, int iTracerFreq, int iDamage, entvars_t *pevAttacker, int inDamageType ) { }
-void CBaseEntity :: TraceBleed( float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType ) { }
-void CBaseMonster :: MakeDamageBloodDecal ( int cCount, float flNoise, TraceResult *ptr, const Vector &vecDir ) { }
-void CBaseMonster::ReportAIState( void ) { }
-void CBaseMonster :: KeyValue( KeyValueData *pkvd ) { }
-BOOL CBaseMonster :: FCheckAITrigger ( void ) { return FALSE; }
-void CBaseMonster::CorpseFallThink( void ) { }
-void CBaseMonster :: MonsterInitDead( void ) { }
-void CBaseMonster :: TraceAttack( entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType) { }
-BOOL CBaseMonster :: ShouldFadeOnDeath( void ) { return FALSE; }
-void CBaseMonster :: RadiusDamage(entvars_t* pevInflictor, entvars_t* pevAttacker, float flDamage, int iClassIgnore, int bitsDamageType ) { }
-void CBaseMonster :: RadiusDamage( Vector vecSrc, entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int iClassIgnore, int bitsDamageType ) { }
-void CBaseMonster::FadeMonster( void ) { }
-void CBaseMonster :: GibMonster( void ) { }
-BOOL CBaseMonster :: HasHumanGibs( void ) { return FALSE; }
-BOOL CBaseMonster :: HasAlienGibs( void ) { return FALSE; }
-Activity CBaseMonster :: GetDeathActivity ( void ) { return ACT_DIE_HEADSHOT; }
-void CBaseMonster::BecomeDead( void ) {}
-void CBaseMonster :: Killed( entvars_t *pevAttacker, int iGib ) {}
-int CBaseMonster :: TakeHealth (float flHealth, int bitsDamageType) { return 0; }
-int CBaseMonster :: TakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType ) { return 0; }
-
-int TrainSpeed(int iSpeed, int iMax) { return 0; }
-void CBasePlayer :: DeathSound( void ) { }
-int CBasePlayer :: TakeHealth( float flHealth, int bitsDamageType ) { return 0; }
-void CBasePlayer :: TabulateAmmo() { }
-void CBasePlayer :: TraceAttack( entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType) { }
-int CBasePlayer :: TakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType ) { return 0; }
-void CBasePlayer::PackDeadPlayerItems( void ) { }
-void CBasePlayer::RemoveAllItems( BOOL removeSuit ) { }
-void CBasePlayer::SetAnimation( PLAYER_ANIM playerAnim ) { }
-void CBasePlayer::WaterMove() { }
-void CBasePlayer :: InitPlayerFromSpawn(edict_t* inSpawn) {}
-BOOL CBasePlayer::IsOnLadder( void ) { return FALSE; }
-BOOL CBasePlayer::IsAlive() const { return FALSE; }
-BOOL CBasePlayer::IsAlive(bool) const { return FALSE; }
-void CBasePlayer::PlayerDeathThink(void) { }
-void CBasePlayer::StartDeathCam( void ) { }
-void CBasePlayer::StartObserver( Vector vecPosition, Vector vecViewAngle ) { }
-void CBasePlayer::StopObserver() { }
-void CBasePlayer::PlayerUse ( void ) { }
-void CBasePlayer::Jump() { }
-void CBasePlayer::Duck( ) { }
-int CBasePlayer::Classify ( void ) { return 0; }
-void CBasePlayer::PreThink(void) { }
-void CBasePlayer::CheckTimeBasedDamage() { }
-void CBasePlayer :: UpdateGeigerCounter( void ) { }
-void CBasePlayer::CheckSuitUpdate() { }
-void CBasePlayer::SetSuitUpdate(char *name, int fgroup, int iNoRepeatTime) { }
-void CBasePlayer :: UpdatePlayerSound ( void ) { }
-void CBasePlayer::PostThink() { }
-void CBasePlayer::EffectivePlayerClassChanged() {}
-void CBasePlayer::NeedsTeamUpdate() {}
-void CBasePlayer::SendTeamUpdate() {}
-void CBasePlayer::Suicide() {}
-void CBasePlayer :: Precache( void ) { }
-int CBasePlayer::Save( CSave &save ) { return 0; }
-void CBasePlayer::RenewItems(void) { }
-int CBasePlayer::Restore( CRestore &restore ) { return 0; }
-void CBasePlayer::SelectNextItem( int iItem ) { }
-BOOL CBasePlayer::HasWeapons( void ) { return FALSE; }
-void CBasePlayer::SelectPrevItem( int iItem ) { }
-CBaseEntity *FindEntityForward( CBaseEntity *pMe ) { return NULL; }
-void CBasePlayer::ForceClientDllUpdate( void ) { }
-void CBasePlayer::ImpulseCommands( ) { }
-void CBasePlayer::CheatImpulseCommands( int iImpulse ) { }
-int CBasePlayer::AddPlayerItem( CBasePlayerItem *pItem ) { return FALSE; }
-int CBasePlayer::RemovePlayerItem( CBasePlayerItem *pItem ) { return FALSE; }
-void CBasePlayer::ItemPreFrame() { }
-void CBasePlayer::ItemPostFrame() { }
-int CBasePlayer::AmmoInventory( int iAmmoIndex ) { return -1; }
-int CBasePlayer::GetAmmoIndex(const char *psz) { return -1; }
-int CBasePlayer::GetMaxWalkSpeed() const { return 220; }
-void CBasePlayer::SendAmmoUpdate(void) { }
-void CBasePlayer::SendWeaponUpdate() {}
-void CBasePlayer :: UpdateClientData( void ) { }
-BOOL CBasePlayer :: FBecomeProne ( void ) { return TRUE; }
-void CBasePlayer :: BarnacleVictimBitten ( entvars_t *pevBarnacle ) { }
-void CBasePlayer :: BarnacleVictimReleased ( void ) { }
-int CBasePlayer :: Illumination( void ) { return 0; }
-void CBasePlayer :: EnableControl(BOOL fControl) { }
-Vector CBasePlayer :: GetAutoaimVector( float flDelta ) { return g_vecZero; }
-Vector CBasePlayer :: AutoaimDeflection( Vector &vecSrc, float flDist, float flDelta ) { return g_vecZero; }
-void CBasePlayer :: ResetAutoaim( ) { }
-void CBasePlayer :: SetCustomDecalFrames( int nFrames ) { }
-int CBasePlayer :: GetCustomDecalFrames( void ) { return -1; }
-void CBasePlayer::DropPlayerItem ( char *pszItemName ) { }
-BOOL CBasePlayer::HasPlayerItem( CBasePlayerItem *pCheckItem ) { return FALSE; }
-BOOL CBasePlayer :: SwitchWeapon( CBasePlayerItem *pWeapon ) { return FALSE; }
-Vector CBasePlayer :: GetGunPosition( void ) { return g_vecZero; }
-char *CBasePlayer::TeamID( void ) { return ""; }
-void CBasePlayer::SetTeamID(const char* inTeamID) {};
-int CBasePlayer :: GiveAmmo( int iCount, char *szName, int iMax ) { return 0; }
-void CBasePlayer::AddPoints( int score, BOOL bAllowNegativeScore ) { }
-void CBasePlayer::AddPointsToTeam( int score, BOOL bAllowNegativeScore ) { }
-void CBasePlayer::GiveNamedItem(const char* szName, bool inSendMessage) { }
-
-void ClearMultiDamage(void) { }
-void ApplyMultiDamage(entvars_t *pevInflictor, entvars_t *pevAttacker ) { }
-void AddMultiDamage( entvars_t *pevInflictor, CBaseEntity *pEntity, float flDamage, int bitsDamageType) { }
-void SpawnBlood(Vector vecSpot, int bloodColor, float flDamage) { }
-int DamageDecal( CBaseEntity *pEntity, int bitsDamageType ) { return 0; }
-void DecalGunshot( TraceResult *pTrace, int iBulletType ) { }
-void EjectBrass ( const Vector &vecOrigin, const Vector &vecVelocity, float rotation, int model, int soundtype ) { }
-void AddAmmoNameToAmmoRegistry( const char *szAmmoname ) { }
-
-BOOL CBasePlayerItem::CanDeploy( void ) { return TRUE; }
-BOOL CBasePlayerItem::CanHolster( void ) { return TRUE; }
-BOOL CBasePlayerItem::Deploy( ) { return TRUE; }
-BOOL CBasePlayerItem::IsUseable( void ) { return TRUE; }
-void CBasePlayerItem::Spawn() {}
-
-int CBasePlayerItem::Restore( class CRestore & ) { return 1; }
-int CBasePlayerItem::Save( class CSave & ) { return 1; }
-int CBasePlayerWeapon::Restore( class CRestore & ) { return 1; }
-int CBasePlayerWeapon::Save( class CSave & ) { return 1; }
-void CBasePlayerItem :: SetObjectCollisionBox( void ) { }
-void CBasePlayerItem :: FallInit( void ) { }
-void CBasePlayerItem::FallThink ( void ) { }
-void CBasePlayerItem::Materialize( void ) { }
-void CBasePlayerItem::AttemptToMaterialize( void ) { }
-void CBasePlayerItem :: CheckRespawn ( void ) { }
-CBaseEntity* CBasePlayerItem::Respawn( void ) { return NULL; }
-void CBasePlayerItem::DefaultTouch( CBaseEntity *pOther ) { }
-void CBasePlayerItem::DestroyItem( void ) { }
-void CBasePlayerItem::VirtualDestroyItem( void ) { }
-int CBasePlayerItem::AddToPlayer( CBasePlayer *pPlayer ) { return TRUE; }
-void CBasePlayerItem::Drop( void ) { }
-void CBasePlayerItem::Kill( void ) { }
-void CBasePlayerItem::Holster( int skiplocal ) { }
-void CBasePlayerItem::AttachToPlayer ( CBasePlayer *pPlayer ) { }
-int CBasePlayerWeapon::AddDuplicate( CBasePlayerItem *pOriginal ) { return 0; }
-int CBasePlayerWeapon::AddToPlayer( CBasePlayer *pPlayer ) { return FALSE; }
-int CBasePlayerWeapon::UpdateClientData( CBasePlayer *pPlayer ) { return 0; }
-BOOL CBasePlayerWeapon :: AddPrimaryAmmo( int iCount, char *szName, int iMaxClip, int iMaxCarry ) { return TRUE; }
-BOOL CBasePlayerWeapon :: AddSecondaryAmmo( int iCount, char *szName, int iMax ) { return TRUE; }
-BOOL CBasePlayerWeapon :: IsUseable( void ) { return TRUE; }
-int CBasePlayerWeapon::PrimaryAmmoIndex( void ) { return -1; }
-int CBasePlayerWeapon::SecondaryAmmoIndex( void ) { return -1; }
-void CBasePlayerAmmo::Spawn( void ) { }
-CBaseEntity* CBasePlayerAmmo::Respawn( void ) { return this; }
-void CBasePlayerAmmo::Materialize( void ) { }
-void CBasePlayerAmmo :: DefaultTouch( CBaseEntity *pOther ) { }
-int CBasePlayerWeapon::ExtractAmmo( CBasePlayerWeapon *pWeapon ) { return 0; }
-int CBasePlayerWeapon::ExtractClipAmmo( CBasePlayerWeapon *pWeapon ) { return 0; }
-void CBasePlayerWeapon::RetireWeapon( void ) { }
-void CSoundEnt::InsertSound ( int iType, const Vector &vecOrigin, int iVolume, float flDuration ) {}
-void RadiusDamage( Vector vecSrc, entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, float flRadius, int iClassIgnore, int bitsDamageType ){}
+/***
+*
+* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
+*
+* This product contains software technology licensed from Id
+* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
+* All Rights Reserved.
+*
+* Use, distribution, and modification of this source code and/or resulting
+* object code is restricted to non-commercial enhancements to products from
+* Valve LLC. All other use, distribution, or modification is prohibited
+* without written permission from Valve LLC.
+*
+****/
+
+/*
+==========================
+This file contains "stubs" of class member implementations so that we can predict certain
+ weapons client side. From time to time you might find that you need to implement part of the
+ these functions. If so, cut it from here, paste it in hl_weapons.cpp or somewhere else and
+ add in the functionality you need.
+==========================
+*/
+#include "extdll.h"
+#include "util.h"
+#include "cbase.h"
+#include "player.h"
+#include "weapons.h"
+#include "nodes.h"
+#include "soundent.h"
+#include "skill.h"
+
+// Globals used by game logic
+const Vector g_vecZero = Vector( 0, 0, 0 );
+enginefuncs_t g_engfuncs;
+globalvars_t *gpGlobals;
+
+ItemInfo CBasePlayerItem::ItemInfoArray[MAX_WEAPONS];
+
+void EMIT_SOUND_DYN(edict_t *entity, int channel, const char *sample, float volume, float attenuation, int flags, int pitch) { }
+
+// CBaseEntity Stubs
+int CBaseEntity :: TakeHealth( float flHealth, int bitsDamageType ) { return 1; }
+int CBaseEntity :: TakeDamage( entvars_t* pevInflictor, entvars_t* pevAttacker, float flDamage, int bitsDamageType ) { return 1; }
+CBaseEntity *CBaseEntity::GetNextTarget( void ) { return NULL; }
+int CBaseEntity::Save( CSave &save ) { return 1; }
+int CBaseEntity::Restore( CRestore &restore ) { return 1; }
+void CBaseEntity::SetObjectCollisionBox( void ) { }
+int CBaseEntity :: Intersects( CBaseEntity *pOther ) { return 0; }
+void CBaseEntity :: MakeDormant( void ) { }
+int CBaseEntity :: IsDormant( void ) { return 0; }
+BOOL CBaseEntity :: IsInWorld( void ) { return TRUE; }
+int CBaseEntity::ShouldToggle( USE_TYPE useType, BOOL currentState ) { return 0; }
+int CBaseEntity :: DamageDecal( int bitsDamageType ) { return -1; }
+CBaseEntity * CBaseEntity::Create( const char *szName, const Vector &vecOrigin, const Vector &vecAngles, edict_t *pentOwner ) { return NULL; }
+void CBaseEntity::SUB_Remove( void ) { }
+void CBaseEntity::AddChecksum(Checksum& inChecksum) {}
+void CBaseEntity::UpdateOnRemove() {}
+
+// CBaseDelay Stubs
+void CBaseDelay :: KeyValue( struct KeyValueData_s * ) { }
+int CBaseDelay::Restore( class CRestore & ) { return 1; }
+int CBaseDelay::Save( class CSave & ) { return 1; }
+
+// CBaseAnimating Stubs
+int CBaseAnimating::Restore( class CRestore & ) { return 1; }
+int CBaseAnimating::Save( class CSave & ) { return 1; }
+
+// DEBUG Stubs
+edict_t *DBG_EntOfVars( const entvars_t *pev ) { return NULL; }
+
+// UTIL_* Stubs
+void UTIL_PrecacheOther( const char *szClassname ) { }
+void UTIL_BloodDrips( const Vector &origin, const Vector &direction, int color, int amount ) { }
+void UTIL_DecalTrace( TraceResult *pTrace, int decalNumber ) { }
+void UTIL_GunshotDecalTrace( TraceResult *pTrace, int decalNumber ) { }
+void UTIL_MakeVectors( const Vector &vecAngles ) { }
+BOOL UTIL_IsValidEntity( edict_t *pent ) { return TRUE; }
+void UTIL_SetOrigin( entvars_t *, const Vector &org ) { }
+BOOL UTIL_GetNextBestWeapon( CBasePlayer *pPlayer, CBasePlayerItem *pCurrentWeapon ) { return TRUE; }
+void UTIL_LogPrintf(char *,...) { }
+void UTIL_ClientPrintAll( int,char const *,char const *,char const *,char const *,char const *) { }
+void ClientPrint( entvars_t *client, int msg_dest, const char *msg_name, const char *param1, const char *param2, const char *param3, const char *param4 ) { }
+
+// CBaseToggle Stubs
+int CBaseToggle::Restore( class CRestore & ) { return 1; }
+int CBaseToggle::Save( class CSave & ) { return 1; }
+void CBaseToggle :: KeyValue( struct KeyValueData_s * ) { }
+void CBaseToggle::SaveDataForReset() {}
+void CBaseToggle::ResetEntity() {}
+
+// CGrenade Stubs
+void CGrenade::BounceSound( void ) { }
+void CGrenade::Explode( Vector, Vector ) { }
+void CGrenade::Explode( TraceResult *, int ) { }
+void CGrenade::Killed( entvars_t *, int ) { }
+void CGrenade::Spawn( void ) { }
+CGrenade * CGrenade:: ShootTimed( entvars_t *pevOwner, Vector vecStart, Vector vecVelocity, float time ){ return 0; }
+CGrenade *CGrenade::ShootContact( entvars_t *pevOwner, Vector vecStart, Vector vecVelocity ){ return 0; }
+void CGrenade::DetonateUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ){ }
+void CGrenade::SetDamageType(int inDamageType) {} //@linux otherwise it says undefined symbol
+
+void UTIL_Remove( CBaseEntity *pEntity ){ }
+struct skilldata_t gSkillData;
+void UTIL_SetSize( entvars_t *pev, const Vector &vecMin, const Vector &vecMax ){ }
+CBaseEntity *UTIL_FindEntityInSphere( CBaseEntity *pStartEntity, const Vector &vecCenter, float flRadius ){ return 0;}
+
+Vector UTIL_VecToAngles( const Vector &vec ){ return 0; }
+CSprite *CSprite::SpriteCreate( const char *pSpriteName, const Vector &origin, BOOL animate ) { return 0; }
+void CBeam::PointEntInit( const Vector &start, int endIndex ) { }
+CBeam *CBeam::BeamCreate( const char *pSpriteName, int width ) { return NULL; }
+void CSprite::Expand( float scaleSpeed, float fadeSpeed ) { }
+
+
+CBaseEntity* CBaseMonster :: CheckTraceHullAttack( float flDist, float& ioDamage, int iDmgType ) { return NULL; }
+int CBaseMonster::GetHull() const { return head_hull; }
+void CBaseMonster :: Look ( int iDistance ) { }
+float CBaseAnimating :: StudioFrameAdvance ( float flInterval ) { return 0.0; }
+int CBaseMonster::IRelationship ( CBaseEntity *pTarget ) { return 0; }
+CBaseEntity *CBaseMonster :: BestVisibleEnemy ( void ) { return NULL; }
+BOOL CBaseMonster :: FInViewCone ( CBaseEntity *pEntity ) { return FALSE; }
+BOOL CBaseMonster :: FInViewCone ( Vector *pOrigin ) { return FALSE; }
+BOOL CBaseEntity :: FVisible ( CBaseEntity *pEntity ) { return FALSE; }
+BOOL CBaseEntity :: FVisible ( const Vector &vecOrigin ) { return FALSE; }
+void CBaseMonster :: MakeIdealYaw( Vector vecTarget ) { }
+float CBaseMonster::ChangeYaw ( int yawSpeed ) { return 0; }
+int CBaseAnimating :: LookupActivity ( int activity ) { return 0; }
+int CBaseAnimating :: LookupActivityHeaviest ( int activity ) { return 0; }
+int CBaseAnimating :: LookupSequence ( const char *label, int queue ) { return 0; }
+void CBaseAnimating :: ResetSequenceInfo ( ) { }
+BOOL CBaseAnimating :: GetSequenceFlags( ) { return FALSE; }
+void CBaseAnimating :: DispatchAnimEvents ( float flInterval ) { }
+float CBaseAnimating :: SetBoneController ( int iController, float flValue ) { return 0.0; }
+void CBaseAnimating :: InitBoneControllers ( void ) { }
+float CBaseAnimating :: SetBlending ( int iBlender, float flValue ) { return 0; }
+void CBaseAnimating :: GetBonePosition ( int iBone, Vector &origin, Vector &angles ) { }
+void CBaseAnimating :: GetAttachment ( int iAttachment, Vector &origin, Vector &angles ) { }
+int CBaseAnimating :: FindTransition( int iEndingSequence, int iGoalSequence, int *piDir ) { return -1; }
+void CBaseAnimating :: GetAutomovement( Vector &origin, Vector &angles, float flInterval ) { }
+void CBaseAnimating :: SetBodygroup( int iGroup, int iValue ) { }
+int CBaseAnimating :: GetBodygroup( int iGroup ) { return 0; }
+void CBaseEntity::TraceAttack(entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType) { }
+void CBaseEntity::FireBullets(ULONG cShots, Vector vecSrc, Vector vecDirShooting, Vector vecSpread, float flDistance, int iBulletType, int iTracerFreq, int iDamage, entvars_t *pevAttacker, int inDamageType ) { }
+void CBaseEntity :: TraceBleed( float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType ) { }
+void CBaseMonster :: MakeDamageBloodDecal ( int cCount, float flNoise, TraceResult *ptr, const Vector &vecDir ) { }
+void CBaseMonster::ReportAIState( void ) { }
+void CBaseMonster :: KeyValue( KeyValueData *pkvd ) { }
+BOOL CBaseMonster :: FCheckAITrigger ( void ) { return FALSE; }
+void CBaseMonster::CorpseFallThink( void ) { }
+void CBaseMonster :: MonsterInitDead( void ) { }
+void CBaseMonster :: TraceAttack( entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType) { }
+BOOL CBaseMonster :: ShouldFadeOnDeath( void ) { return FALSE; }
+void CBaseMonster :: RadiusDamage(entvars_t* pevInflictor, entvars_t* pevAttacker, float flDamage, int iClassIgnore, int bitsDamageType ) { }
+void CBaseMonster :: RadiusDamage( Vector vecSrc, entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int iClassIgnore, int bitsDamageType ) { }
+void CBaseMonster::FadeMonster( void ) { }
+void CBaseMonster :: GibMonster( void ) { }
+BOOL CBaseMonster :: HasHumanGibs( void ) { return FALSE; }
+BOOL CBaseMonster :: HasAlienGibs( void ) { return FALSE; }
+Activity CBaseMonster :: GetDeathActivity ( void ) { return ACT_DIE_HEADSHOT; }
+void CBaseMonster::BecomeDead( void ) {}
+void CBaseMonster :: Killed( entvars_t *pevAttacker, int iGib ) {}
+int CBaseMonster :: TakeHealth (float flHealth, int bitsDamageType) { return 0; }
+int CBaseMonster :: TakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType ) { return 0; }
+
+int TrainSpeed(int iSpeed, int iMax) { return 0; }
+void CBasePlayer :: DeathSound( void ) { }
+int CBasePlayer :: TakeHealth( float flHealth, int bitsDamageType ) { return 0; }
+void CBasePlayer :: TabulateAmmo() { }
+void CBasePlayer :: TraceAttack( entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType) { }
+int CBasePlayer :: TakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType ) { return 0; }
+void CBasePlayer::PackDeadPlayerItems( void ) { }
+void CBasePlayer::RemoveAllItems( BOOL removeSuit ) { }
+void CBasePlayer::SetAnimation( PLAYER_ANIM playerAnim ) { }
+void CBasePlayer::WaterMove() { }
+void CBasePlayer :: InitPlayerFromSpawn(edict_t* inSpawn) {}
+BOOL CBasePlayer::IsOnLadder( void ) { return FALSE; }
+BOOL CBasePlayer::IsAlive() const { return FALSE; }
+BOOL CBasePlayer::IsAlive(bool) const { return FALSE; }
+void CBasePlayer::PlayerDeathThink(void) { }
+void CBasePlayer::StartDeathCam( void ) { }
+void CBasePlayer::StartObserver( Vector vecPosition, Vector vecViewAngle ) { }
+void CBasePlayer::StopObserver() { }
+void CBasePlayer::PlayerUse ( void ) { }
+void CBasePlayer::Jump() { }
+void CBasePlayer::Duck( ) { }
+int CBasePlayer::Classify ( void ) { return 0; }
+void CBasePlayer::PreThink(void) { }
+void CBasePlayer::CheckTimeBasedDamage() { }
+void CBasePlayer :: UpdateGeigerCounter( void ) { }
+void CBasePlayer::CheckSuitUpdate() { }
+void CBasePlayer::SetSuitUpdate(char *name, int fgroup, int iNoRepeatTime) { }
+void CBasePlayer :: UpdatePlayerSound ( void ) { }
+void CBasePlayer::PostThink() { }
+void CBasePlayer::EffectivePlayerClassChanged() {}
+void CBasePlayer::NeedsTeamUpdate() {}
+void CBasePlayer::SendTeamUpdate() {}
+void CBasePlayer::Suicide() {}
+void CBasePlayer :: Precache( void ) { }
+int CBasePlayer::Save( CSave &save ) { return 0; }
+void CBasePlayer::RenewItems(void) { }
+int CBasePlayer::Restore( CRestore &restore ) { return 0; }
+void CBasePlayer::SelectNextItem( int iItem ) { }
+BOOL CBasePlayer::HasWeapons( void ) { return FALSE; }
+void CBasePlayer::SelectPrevItem( int iItem ) { }
+CBaseEntity *FindEntityForward( CBaseEntity *pMe ) { return NULL; }
+void CBasePlayer::ForceClientDllUpdate( void ) { }
+void CBasePlayer::ImpulseCommands( ) { }
+void CBasePlayer::CheatImpulseCommands( int iImpulse ) { }
+int CBasePlayer::AddPlayerItem( CBasePlayerItem *pItem ) { return FALSE; }
+int CBasePlayer::RemovePlayerItem( CBasePlayerItem *pItem ) { return FALSE; }
+void CBasePlayer::ItemPreFrame() { }
+void CBasePlayer::ItemPostFrame() { }
+int CBasePlayer::AmmoInventory( int iAmmoIndex ) { return -1; }
+int CBasePlayer::GetAmmoIndex(const char *psz) { return -1; }
+int CBasePlayer::GetMaxWalkSpeed() const { return 220; }
+void CBasePlayer::SendAmmoUpdate(void) { }
+void CBasePlayer::SendWeaponUpdate() {}
+void CBasePlayer :: UpdateClientData( void ) { }
+BOOL CBasePlayer :: FBecomeProne ( void ) { return TRUE; }
+void CBasePlayer :: BarnacleVictimBitten ( entvars_t *pevBarnacle ) { }
+void CBasePlayer :: BarnacleVictimReleased ( void ) { }
+int CBasePlayer :: Illumination( void ) { return 0; }
+void CBasePlayer :: EnableControl(BOOL fControl) { }
+Vector CBasePlayer :: GetAutoaimVector( float flDelta ) { return g_vecZero; }
+Vector CBasePlayer :: AutoaimDeflection( Vector &vecSrc, float flDist, float flDelta ) { return g_vecZero; }
+void CBasePlayer :: ResetAutoaim( ) { }
+void CBasePlayer :: SetCustomDecalFrames( int nFrames ) { }
+int CBasePlayer :: GetCustomDecalFrames( void ) { return -1; }
+void CBasePlayer::DropPlayerItem ( char *pszItemName ) { }
+BOOL CBasePlayer::HasPlayerItem( CBasePlayerItem *pCheckItem ) { return FALSE; }
+BOOL CBasePlayer :: SwitchWeapon( CBasePlayerItem *pWeapon ) { return FALSE; }
+Vector CBasePlayer :: GetGunPosition( void ) { return g_vecZero; }
+char *CBasePlayer::TeamID( void ) { return ""; }
+void CBasePlayer::SetTeamID(const char* inTeamID) {};
+int CBasePlayer :: GiveAmmo( int iCount, char *szName, int iMax ) { return 0; }
+void CBasePlayer::AddPoints( int score, BOOL bAllowNegativeScore ) { }
+void CBasePlayer::AddPointsToTeam( int score, BOOL bAllowNegativeScore ) { }
+void CBasePlayer::GiveNamedItem(const char* szName, bool inSendMessage) { }
+
+void ClearMultiDamage(void) { }
+void ApplyMultiDamage(entvars_t *pevInflictor, entvars_t *pevAttacker ) { }
+void AddMultiDamage( entvars_t *pevInflictor, CBaseEntity *pEntity, float flDamage, int bitsDamageType) { }
+void SpawnBlood(Vector vecSpot, int bloodColor, float flDamage) { }
+int DamageDecal( CBaseEntity *pEntity, int bitsDamageType ) { return 0; }
+void DecalGunshot( TraceResult *pTrace, int iBulletType ) { }
+void EjectBrass ( const Vector &vecOrigin, const Vector &vecVelocity, float rotation, int model, int soundtype ) { }
+void AddAmmoNameToAmmoRegistry( const char *szAmmoname ) { }
+
+BOOL CBasePlayerItem::CanDeploy( void ) { return TRUE; }
+BOOL CBasePlayerItem::CanHolster( void ) { return TRUE; }
+BOOL CBasePlayerItem::Deploy( ) { return TRUE; }
+BOOL CBasePlayerItem::IsUseable( void ) { return TRUE; }
+void CBasePlayerItem::Spawn() {}
+
+int CBasePlayerItem::Restore( class CRestore & ) { return 1; }
+int CBasePlayerItem::Save( class CSave & ) { return 1; }
+int CBasePlayerWeapon::Restore( class CRestore & ) { return 1; }
+int CBasePlayerWeapon::Save( class CSave & ) { return 1; }
+void CBasePlayerItem :: SetObjectCollisionBox( void ) { }
+void CBasePlayerItem :: FallInit( void ) { }
+void CBasePlayerItem::FallThink ( void ) { }
+void CBasePlayerItem::Materialize( void ) { }
+void CBasePlayerItem::AttemptToMaterialize( void ) { }
+void CBasePlayerItem :: CheckRespawn ( void ) { }
+CBaseEntity* CBasePlayerItem::Respawn( void ) { return NULL; }
+void CBasePlayerItem::DefaultTouch( CBaseEntity *pOther ) { }
+void CBasePlayerItem::DestroyItem( void ) { }
+void CBasePlayerItem::VirtualDestroyItem( void ) { }
+int CBasePlayerItem::AddToPlayer( CBasePlayer *pPlayer ) { return TRUE; }
+void CBasePlayerItem::Drop( void ) { }
+void CBasePlayerItem::Kill( void ) { }
+void CBasePlayerItem::Holster( int skiplocal ) { }
+void CBasePlayerItem::AttachToPlayer ( CBasePlayer *pPlayer ) { }
+int CBasePlayerWeapon::AddDuplicate( CBasePlayerItem *pOriginal ) { return 0; }
+int CBasePlayerWeapon::AddToPlayer( CBasePlayer *pPlayer ) { return FALSE; }
+int CBasePlayerWeapon::UpdateClientData( CBasePlayer *pPlayer ) { return 0; }
+BOOL CBasePlayerWeapon :: AddPrimaryAmmo( int iCount, char *szName, int iMaxClip, int iMaxCarry ) { return TRUE; }
+BOOL CBasePlayerWeapon :: AddSecondaryAmmo( int iCount, char *szName, int iMax ) { return TRUE; }
+BOOL CBasePlayerWeapon :: IsUseable( void ) { return TRUE; }
+int CBasePlayerWeapon::PrimaryAmmoIndex( void ) { return -1; }
+int CBasePlayerWeapon::SecondaryAmmoIndex( void ) { return -1; }
+void CBasePlayerAmmo::Spawn( void ) { }
+CBaseEntity* CBasePlayerAmmo::Respawn( void ) { return this; }
+void CBasePlayerAmmo::Materialize( void ) { }
+void CBasePlayerAmmo :: DefaultTouch( CBaseEntity *pOther ) { }
+int CBasePlayerWeapon::ExtractAmmo( CBasePlayerWeapon *pWeapon ) { return 0; }
+int CBasePlayerWeapon::ExtractClipAmmo( CBasePlayerWeapon *pWeapon ) { return 0; }
+void CBasePlayerWeapon::RetireWeapon( void ) { }
+void CSoundEnt::InsertSound ( int iType, const Vector &vecOrigin, int iVolume, float flDuration ) {}
+void RadiusDamage( Vector vecSrc, entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, float flRadius, int iClassIgnore, int bitsDamageType ){}
diff --git a/main/source/cl_dll/hl/hl_events.cpp b/main/source/cl_dll/hl/hl_events.cpp
index fa599625..92ecf363 100644
--- a/main/source/cl_dll/hl/hl_events.cpp
+++ b/main/source/cl_dll/hl/hl_events.cpp
@@ -1,98 +1,98 @@
-/***
-*
-* Copyright (c) 1999, Valve LLC. All rights reserved.
-*
-* This product contains software technology licensed from Id
-* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
-* All Rights Reserved.
-*
-* Use, distribution, and modification of this source code and/or resulting
-* object code is restricted to non-commercial enhancements to products from
-* Valve LLC. All other use, distribution, or modification is prohibited
-* without written permission from Valve LLC.
-*
-****/
-#include "../hud.h"
-#include "../cl_util.h"
-#include "event_api.h"
-#include "mod/AvHMarineWeaponConstants.h"
-#include "mod/AvHAlienWeaponConstants.h"
-
-extern "C"
-{
-// HLDM
-void EV_FireGlock1( struct event_args_s *args );
-void EV_FireGlock2( struct event_args_s *args );
-void EV_FireShotGunSingle( struct event_args_s *args );
-void EV_FireShotGunDouble( struct event_args_s *args );
-void EV_FireMP5( struct event_args_s *args );
-void EV_FireMP52( struct event_args_s *args );
-void EV_FirePython( struct event_args_s *args );
-void EV_FireGauss( struct event_args_s *args );
-void EV_SpinGauss( struct event_args_s *args );
-void EV_Crowbar( struct event_args_s *args );
-void EV_FireCrossbow( struct event_args_s *args );
-void EV_FireCrossbow2( struct event_args_s *args );
-void EV_FireRpg( struct event_args_s *args );
-void EV_EgonFire( struct event_args_s *args );
-void EV_EgonStop( struct event_args_s *args );
-void EV_HornetGunFire( struct event_args_s *args );
-void EV_TripmineFire( struct event_args_s *args );
-void EV_SnarkFire( struct event_args_s *args );
-
-
-
-void EV_TrainPitchAdjust( struct event_args_s *args );
-}
-
-/*
-======================
-Game_HookEvents
-
-Associate script file name with callback functions. Callback's must be extern "C" so
- the engine doesn't get confused about name mangling stuff. Note that the format is
- always the same. Of course, a clever mod team could actually embed parameters, behavior
- into the actual .sc files and create a .sc file parser and hook their functionality through
- that.. i.e., a scripting system.
-
-That was what we were going to do, but we ran out of time...oh well.
-======================
-*/
-
-#define AVH_HOOK_EVENT(s) gEngfuncs.pfnHookEvent("events/"#s".dsc", EV_#s)
-
-void Game_HookEvents( void )
-{
-// gEngfuncs.pfnHookEvent( "events/glock1.sc", EV_FireGlock1 );
-// gEngfuncs.pfnHookEvent( "events/glock2.sc", EV_FireGlock2 );
-// gEngfuncs.pfnHookEvent( "events/shotgun1.sc", EV_FireShotGunSingle );
-// gEngfuncs.pfnHookEvent( "events/shotgun2.sc", EV_FireShotGunDouble );
-// gEngfuncs.pfnHookEvent( "events/mp5.sc", EV_FireMP5 );
-// gEngfuncs.pfnHookEvent( "events/python.sc", EV_FirePython );
-// gEngfuncs.pfnHookEvent( "events/gauss.sc", EV_FireGauss );
-// gEngfuncs.pfnHookEvent( "events/gaussspin.sc", EV_SpinGauss );
-// gEngfuncs.pfnHookEvent( "events/train.sc", EV_TrainPitchAdjust );
-
-// AVH_HOOK_EVENT(kMGEventName);
-
-// gEngfuncs.pfnHookEvent("events/train.sc", EV_TrainPitchAdjust);
-// gEngfuncs.pfnHookEvent( "events/glock1.sc", EV_FireGlock1 );
-// gEngfuncs.pfnHookEvent( "events/glock2.sc", EV_FireGlock2 );
-// gEngfuncs.pfnHookEvent( "events/shotgun1.sc", EV_FireShotGunSingle );
-// gEngfuncs.pfnHookEvent( "events/shotgun2.sc", EV_FireShotGunDouble );
-// gEngfuncs.pfnHookEvent( "events/mp5.sc", EV_FireMP5 );
-// gEngfuncs.pfnHookEvent( "events/mp52.sc", EV_FireMP52 );
-// gEngfuncs.pfnHookEvent( "events/python.sc", EV_FirePython );
-// gEngfuncs.pfnHookEvent( "events/gauss.sc", EV_FireGauss );
-// gEngfuncs.pfnHookEvent( "events/gaussspin.sc", EV_SpinGauss );
-// gEngfuncs.pfnHookEvent( "events/train.sc", EV_TrainPitchAdjust );
-// gEngfuncs.pfnHookEvent( "events/crowbar.sc", EV_Crowbar );
-// gEngfuncs.pfnHookEvent( "events/crossbow1.sc", EV_FireCrossbow );
-// gEngfuncs.pfnHookEvent( "events/crossbow2.sc", EV_FireCrossbow2 );
-// gEngfuncs.pfnHookEvent( "events/rpg.sc", EV_FireRpg );
-// gEngfuncs.pfnHookEvent( "events/egon_fire.sc", EV_EgonFire );
-// gEngfuncs.pfnHookEvent( "events/egon_stop.sc", EV_EgonStop );
-// gEngfuncs.pfnHookEvent( "events/firehornet.sc", EV_HornetGunFire );
-// gEngfuncs.pfnHookEvent( "events/tripfire.sc", EV_TripmineFire );
-// gEngfuncs.pfnHookEvent( "events/snarkfire.sc", EV_SnarkFire );
-}
+/***
+*
+* Copyright (c) 1999, Valve LLC. All rights reserved.
+*
+* This product contains software technology licensed from Id
+* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
+* All Rights Reserved.
+*
+* Use, distribution, and modification of this source code and/or resulting
+* object code is restricted to non-commercial enhancements to products from
+* Valve LLC. All other use, distribution, or modification is prohibited
+* without written permission from Valve LLC.
+*
+****/
+#include "../hud.h"
+#include "../cl_util.h"
+#include "event_api.h"
+#include "mod/AvHMarineWeaponConstants.h"
+#include "mod/AvHAlienWeaponConstants.h"
+
+extern "C"
+{
+// HLDM
+void EV_FireGlock1( struct event_args_s *args );
+void EV_FireGlock2( struct event_args_s *args );
+void EV_FireShotGunSingle( struct event_args_s *args );
+void EV_FireShotGunDouble( struct event_args_s *args );
+void EV_FireMP5( struct event_args_s *args );
+void EV_FireMP52( struct event_args_s *args );
+void EV_FirePython( struct event_args_s *args );
+void EV_FireGauss( struct event_args_s *args );
+void EV_SpinGauss( struct event_args_s *args );
+void EV_Crowbar( struct event_args_s *args );
+void EV_FireCrossbow( struct event_args_s *args );
+void EV_FireCrossbow2( struct event_args_s *args );
+void EV_FireRpg( struct event_args_s *args );
+void EV_EgonFire( struct event_args_s *args );
+void EV_EgonStop( struct event_args_s *args );
+void EV_HornetGunFire( struct event_args_s *args );
+void EV_TripmineFire( struct event_args_s *args );
+void EV_SnarkFire( struct event_args_s *args );
+
+
+
+void EV_TrainPitchAdjust( struct event_args_s *args );
+}
+
+/*
+======================
+Game_HookEvents
+
+Associate script file name with callback functions. Callback's must be extern "C" so
+ the engine doesn't get confused about name mangling stuff. Note that the format is
+ always the same. Of course, a clever mod team could actually embed parameters, behavior
+ into the actual .sc files and create a .sc file parser and hook their functionality through
+ that.. i.e., a scripting system.
+
+That was what we were going to do, but we ran out of time...oh well.
+======================
+*/
+
+#define AVH_HOOK_EVENT(s) gEngfuncs.pfnHookEvent("events/"#s".dsc", EV_#s)
+
+void Game_HookEvents( void )
+{
+// gEngfuncs.pfnHookEvent( "events/glock1.sc", EV_FireGlock1 );
+// gEngfuncs.pfnHookEvent( "events/glock2.sc", EV_FireGlock2 );
+// gEngfuncs.pfnHookEvent( "events/shotgun1.sc", EV_FireShotGunSingle );
+// gEngfuncs.pfnHookEvent( "events/shotgun2.sc", EV_FireShotGunDouble );
+// gEngfuncs.pfnHookEvent( "events/mp5.sc", EV_FireMP5 );
+// gEngfuncs.pfnHookEvent( "events/python.sc", EV_FirePython );
+// gEngfuncs.pfnHookEvent( "events/gauss.sc", EV_FireGauss );
+// gEngfuncs.pfnHookEvent( "events/gaussspin.sc", EV_SpinGauss );
+// gEngfuncs.pfnHookEvent( "events/train.sc", EV_TrainPitchAdjust );
+
+// AVH_HOOK_EVENT(kMGEventName);
+
+// gEngfuncs.pfnHookEvent("events/train.sc", EV_TrainPitchAdjust);
+// gEngfuncs.pfnHookEvent( "events/glock1.sc", EV_FireGlock1 );
+// gEngfuncs.pfnHookEvent( "events/glock2.sc", EV_FireGlock2 );
+// gEngfuncs.pfnHookEvent( "events/shotgun1.sc", EV_FireShotGunSingle );
+// gEngfuncs.pfnHookEvent( "events/shotgun2.sc", EV_FireShotGunDouble );
+// gEngfuncs.pfnHookEvent( "events/mp5.sc", EV_FireMP5 );
+// gEngfuncs.pfnHookEvent( "events/mp52.sc", EV_FireMP52 );
+// gEngfuncs.pfnHookEvent( "events/python.sc", EV_FirePython );
+// gEngfuncs.pfnHookEvent( "events/gauss.sc", EV_FireGauss );
+// gEngfuncs.pfnHookEvent( "events/gaussspin.sc", EV_SpinGauss );
+// gEngfuncs.pfnHookEvent( "events/train.sc", EV_TrainPitchAdjust );
+// gEngfuncs.pfnHookEvent( "events/crowbar.sc", EV_Crowbar );
+// gEngfuncs.pfnHookEvent( "events/crossbow1.sc", EV_FireCrossbow );
+// gEngfuncs.pfnHookEvent( "events/crossbow2.sc", EV_FireCrossbow2 );
+// gEngfuncs.pfnHookEvent( "events/rpg.sc", EV_FireRpg );
+// gEngfuncs.pfnHookEvent( "events/egon_fire.sc", EV_EgonFire );
+// gEngfuncs.pfnHookEvent( "events/egon_stop.sc", EV_EgonStop );
+// gEngfuncs.pfnHookEvent( "events/firehornet.sc", EV_HornetGunFire );
+// gEngfuncs.pfnHookEvent( "events/tripfire.sc", EV_TripmineFire );
+// gEngfuncs.pfnHookEvent( "events/snarkfire.sc", EV_SnarkFire );
+}
diff --git a/main/source/cl_dll/hl/hl_objects.cpp b/main/source/cl_dll/hl/hl_objects.cpp
index e84762b8..bb832135 100644
--- a/main/source/cl_dll/hl/hl_objects.cpp
+++ b/main/source/cl_dll/hl/hl_objects.cpp
@@ -1,89 +1,89 @@
-/***
-*
-* Copyright (c) 1999, Valve LLC. All rights reserved.
-*
-* This product contains software technology licensed from Id
-* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
-* All Rights Reserved.
-*
-* Use, distribution, and modification of this source code and/or resulting
-* object code is restricted to non-commercial enhancements to products from
-* Valve LLC. All other use, distribution, or modification is prohibited
-* without written permission from Valve LLC.
-*
-****/
-#include "../hud.h"
-#include "../cl_util.h"
-#include "../demo.h"
-
-#include "demo_api.h"
-#include "const.h"
-#include "entity_state.h"
-#include "cl_entity.h"
-
-#include "pm_defs.h"
-#include "event_api.h"
-#include "entity_types.h"
-#include "r_efx.h"
-
-extern BEAM *pBeam;
-extern BEAM *pBeam2;
-void HUD_GetLastOrg( float *org );
-
-void UpdateBeams ( void )
-{
- vec3_t forward, vecSrc, vecEnd, origin, angles, right, up;
- vec3_t view_ofs;
- pmtrace_t tr;
- cl_entity_t *pthisplayer = gEngfuncs.GetLocalPlayer();
- int idx = pthisplayer->index;
-
- // Get our exact viewangles from engine
- gEngfuncs.GetViewAngles( (float *)angles );
-
- // Determine our last predicted origin
- HUD_GetLastOrg( (float *)&origin );
-
- AngleVectors( angles, forward, right, up );
-
- VectorCopy( origin, vecSrc );
- VectorMA( vecSrc, 2048, forward, vecEnd );
-
- gEngfuncs.pEventAPI->EV_SetUpPlayerPrediction( false, true );
-
- // Store off the old count
- gEngfuncs.pEventAPI->EV_PushPMStates();
-
- // Now add in all of the players.
- gEngfuncs.pEventAPI->EV_SetSolidPlayers ( idx - 1 );
-
- gEngfuncs.pEventAPI->EV_SetTraceHull( 2 );
- gEngfuncs.pEventAPI->EV_PlayerTrace( vecSrc, vecEnd, PM_STUDIO_BOX, -1, &tr );
-
- gEngfuncs.pEventAPI->EV_PopPMStates();
-
- if ( pBeam )
- {
- pBeam->target = tr.endpos;
- pBeam->die = gEngfuncs.GetClientTime() + 0.1; // We keep it alive just a little bit forward in the future, just in case.
- }
-
- if ( pBeam2 )
- {
- pBeam2->target = tr.endpos;
- pBeam2->die = gEngfuncs.GetClientTime() + 0.1; // We keep it alive just a little bit forward in the future, just in case.
- }
-}
-
-/*
-=====================
-Game_AddObjects
-
-Add game specific, client-side objects here
-=====================
-*/
-void Game_AddObjects( void )
-{
- if ( pBeam && pBeam2 )
- UpdateBeams();
-}
+/***
+*
+* Copyright (c) 1999, Valve LLC. All rights reserved.
+*
+* This product contains software technology licensed from Id
+* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
+* All Rights Reserved.
+*
+* Use, distribution, and modification of this source code and/or resulting
+* object code is restricted to non-commercial enhancements to products from
+* Valve LLC. All other use, distribution, or modification is prohibited
+* without written permission from Valve LLC.
+*
+****/
+#include "../hud.h"
+#include "../cl_util.h"
+#include "../demo.h"
+
+#include "demo_api.h"
+#include "const.h"
+#include "entity_state.h"
+#include "cl_entity.h"
+
+#include "pm_defs.h"
+#include "event_api.h"
+#include "entity_types.h"
+#include "r_efx.h"
+
+extern BEAM *pBeam;
+extern BEAM *pBeam2;
+void HUD_GetLastOrg( float *org );
+
+void UpdateBeams ( void )
+{
+ vec3_t forward, vecSrc, vecEnd, origin, angles, right, up;
+ vec3_t view_ofs;
+ pmtrace_t tr;
+ cl_entity_t *pthisplayer = gEngfuncs.GetLocalPlayer();
+ int idx = pthisplayer->index;
+
+ // Get our exact viewangles from engine
+ gEngfuncs.GetViewAngles( (float *)angles );
+
+ // Determine our last predicted origin
+ HUD_GetLastOrg( (float *)&origin );
+
+ AngleVectors( angles, forward, right, up );
+
+ VectorCopy( origin, vecSrc );
+ VectorMA( vecSrc, 2048, forward, vecEnd );
+
+ gEngfuncs.pEventAPI->EV_SetUpPlayerPrediction( false, true );
+
+ // Store off the old count
+ gEngfuncs.pEventAPI->EV_PushPMStates();
+
+ // Now add in all of the players.
+ gEngfuncs.pEventAPI->EV_SetSolidPlayers ( idx - 1 );
+
+ gEngfuncs.pEventAPI->EV_SetTraceHull( 2 );
+ gEngfuncs.pEventAPI->EV_PlayerTrace( vecSrc, vecEnd, PM_STUDIO_BOX, -1, &tr );
+
+ gEngfuncs.pEventAPI->EV_PopPMStates();
+
+ if ( pBeam )
+ {
+ pBeam->target = tr.endpos;
+ pBeam->die = gEngfuncs.GetClientTime() + 0.1; // We keep it alive just a little bit forward in the future, just in case.
+ }
+
+ if ( pBeam2 )
+ {
+ pBeam2->target = tr.endpos;
+ pBeam2->die = gEngfuncs.GetClientTime() + 0.1; // We keep it alive just a little bit forward in the future, just in case.
+ }
+}
+
+/*
+=====================
+Game_AddObjects
+
+Add game specific, client-side objects here
+=====================
+*/
+void Game_AddObjects( void )
+{
+ if ( pBeam && pBeam2 )
+ UpdateBeams();
+}
diff --git a/main/source/cl_dll/hl/hl_weapons.cpp b/main/source/cl_dll/hl/hl_weapons.cpp
index 25d00835..f6283e59 100644
--- a/main/source/cl_dll/hl/hl_weapons.cpp
+++ b/main/source/cl_dll/hl/hl_weapons.cpp
@@ -1,1537 +1,1537 @@
-/***
-*
-* Copyright (c) 1999, Valve LLC. All rights reserved.
-*
-* This product contains software technology licensed from Id
-* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
-* All Rights Reserved.
-*
-* Use, distribution, and modification of this source code and/or resulting
-* object code is restricted to non-commercial enhancements to products from
-* Valve LLC. All other use, distribution, or modification is prohibited
-* without written permission from Valve LLC.
-*
-* Modified by Charlie Cleveland:
-*
-* $Workfile: hl_weapons.cpp $
-* $Date: 2002/10/24 21:11:52 $
-*
-* -------------------------------------------------------------------------------
-* $Log: hl_weapons.cpp,v $
-* Revision 1.31 2002/10/24 21:11:52 Flayra
-* - Updated jetpack effect because it was really buggy this old way
-*
-* Revision 1.30 2002/10/16 02:12:10 Flayra
-* - Valve anti-cheat integrated!
-*
-* Revision 1.29 2002/10/16 00:36:40 Flayra
-* - Removed blink fail
-*
-* Revision 1.28 2002/08/31 18:01:59 Flayra
-* - Work at VALVe
-*
-* Revision 1.27 2002/07/08 16:09:03 Flayra
-* - Removed unneeded code here, so random numbers were generated properly on both client and server
-*
-* Revision 1.26 2002/07/01 20:56:31 Flayra
-* - Added babbler gun
-*
-* Revision 1.25 2002/06/25 17:03:01 Flayra
-* - Removed old weapons, added new weapons, fixed mines, iuser3 enables and disables weapons
-*
-* ===============================================================================
-****/
-#include "../hud.h"
-#include "../cl_util.h"
-#include "common/const.h"
-#include "common/entity_state.h"
-#include "common/cl_entity.h"
-#include "../demo.h"
-#include "common/usercmd.h"
-#include "common/event_flags.h"
-#include "common/event_api.h"
-#include "cl_dll/com_weapons.h"
-#include "cl_dll/ammo.h"
-#include "cl_dll/ammohistory.h"
-#include "dlls/extdll.h"
-#include "dlls/util.h"
-#include "dlls/cbase.h"
-#include "dlls/monsters.h"
-#include "dlls/weapons.h"
-#include "dlls/nodes.h"
-#include "dlls/player.h"
-#include "mod/AvHEvents.h"
-
-#include "common/usercmd.h"
-#include "common/entity_state.h"
-#include "common/demo_api.h"
-#include "pm_shared/pm_defs.h"
-#include "common/event_api.h"
-#include "common/r_efx.h"
-
-#include "../hud_iface.h"
-#include "../com_weapons.h"
-
-#include "mod/AvHMarineWeapons.h"
-#include "mod/AvHSpecials.h"
-#include "mod/AvHAlienWeapons.h"
-#include "mod/AvHAlienAbilities.h"
-#include "mod/AvHAlienWeaponConstants.h"
-#include "mod/AvHAlienAbilityConstants.h"
-#include "mod/AvHMovementUtil.h"
-
-#include "engine/APIProxy.h"
-#include "../Exports.h"
-
-extern globalvars_t *gpGlobals;
-extern bool gIsJetpacking;
-
-// Pool of client side entities/entvars_t
-static entvars_t ev[ 32 ];
-static int num_ents = 0;
-
-// The entity we'll use to represent the local client
-static CBasePlayer player;
-
-// Local version of game .dll global variables ( time, etc. )
-static globalvars_t Globals;
-
-static CBasePlayerWeapon *g_pWpns[ 32 ];
-
-bool CheckInAttack2(void);
-
-vec3_t previousorigin;
-
-// HLDM Weapon placeholder entities.
-//CGlock g_Glock;
-
-// NS weapons
-AvHKnife gKnife;
-AvHMachineGun gMachineGun;
-AvHPistol gPistol;
-AvHSonicGun gSonicGun;
-AvHHeavyMachineGun gHeavyMachineGun;
-AvHGrenadeGun gGrenadeGun;
-AvHGrenade gGrenade;
-AvHWelder gWelder;
-AvHMine gMine;
-AvHSpitGun gSpitGun;
-AvHClaws gClaws;
-AvHSpore gSpores;
-AvHBite gBite;
-AvHBite2 gBite2;
-AvHSpikeGun gSpikeGun;
-AvHSwipe gSwipe;
-AvHWebSpinner gWebSpinner;
-AvHPrimalScream gPrimalScream;
-AvHParasiteGun gParasite;
-AvHUmbraGun gUmbra;
-AvHBlinkGun gBlink;
-AvHDivineWind gDivineWind;
-//AvHParalysisGun gParalysisGun;
-AvHBileBombGun gBileBomb;
-AvHAcidRocketGun gAcidRocket;
-AvHHealingSpray gHealingSpray;
-AvHMetabolize gMetabolize;
-AvHDevour gDevour;
-AvHStomp gStomp;
-
-// Alien abilities
-AvHLeap gLeap;
-AvHCharge gCharge;
-
-// Jetpack events
-int gJetpackEventID;
-//int gWallJumpEventID;
-//int gFlightEventID;
-int gTeleportEventID;
-int gPhaseInEventID;
-int gSiegeHitEventID;
-int gSiegeViewHitEventID;
-int gCommanderPointsAwardedEventID;
-int gBlinkEffectSuccessEventID;
-
-//bool gPlayingJetpack = false;
-//CGlock g_Glock;
-//CCrowbar g_Crowbar;
-//CPython g_Python;
-//CMP5 g_Mp5;
-//CCrossbow g_Crossbow;
-//CShotgun g_Shotgun;
-//CRpg g_Rpg;
-//CGauss g_Gauss;
-//CEgon g_Egon;
-//CHgun g_HGun;
-//CHandGrenade g_HandGren;
-//CSatchel g_Satchel;
-//CTripmine g_Tripmine;
-//CSqueak g_Snark;
-
-/*
-======================
-AlertMessage
-
-Print debug messages to console
-======================
-*/
-void AlertMessage( ALERT_TYPE atype, char *szFmt, ... )
-{
- va_list argptr;
- static char string[1024];
-
- va_start (argptr, szFmt);
-#ifdef WIN32
- //overflow protection in MS version of function...
- _vsnprintf( string, 1023, szFmt, argptr );
-#else
- vsprintf (string, szFmt,argptr);
-#endif
- va_end (argptr);
-
- gEngfuncs.Con_Printf( "cl: " );
- gEngfuncs.Con_Printf( string );
-}
-
-// Client-side effects for jetpack
-void CheckJetpack()
-{
- // if local player is jetpacking, play effects immediately
-// if(gIsJetpacking && !gPlayingJetpack)
-// {
-// cl_entity_t* thePlayer;
-// thePlayer = gEngfuncs.GetLocalPlayer();
-// ASSERT(thePlayer);
-//
-// // Play event locally, server will tell everyone else to play event
-// gEngfuncs.pEventAPI->EV_PlaybackEvent(0, NULL, gJetpackEventID, 0, thePlayer->origin, (float *)&g_vecZero, 0.0, 0.0, /*theWeaponIndex*/ 0, 0, 0, 0 );
-//
-// //gPlayingJetpack = true;
-// }
- // Check to turn it off too (in case there's a network anomaly or the game resets or something, just trying to be safe)
- //else if(!gIsJetpacking && (gPlayingJetpack))
- //{
- // gEngfuncs.pEventAPI->EV_PlaybackEvent(0, NULL, gEndJetpackEventID, 0, (float *)&g_vecZero, (float *)&g_vecZero, 0.0, 0.0, /*theWeaponIndex*/ 0, 0, 0, 0 );
- //
- // gPlayingJetpack = false;
- //}
-}
-
-//Returns if it's multiplayer.
-//Mostly used by the client side weapons.
-bool bIsMultiplayer ( void )
-{
- return gEngfuncs.GetMaxClients() == 1 ? 0 : 1;
-}
-//Just loads a v_ model.
-void LoadVModel ( char *szViewModel, CBasePlayer *m_pPlayer )
-{
- gEngfuncs.CL_LoadModel( szViewModel, &m_pPlayer->pev->viewmodel );
-}
-
-/*
-=====================
-HUD_PrepEntity
-
-Links the raw entity to an entvars_s holder. If a player is passed in as the owner, then
-we set up the m_pPlayer field.
-=====================
-*/
-void HUD_PrepEntity( CBaseEntity *pEntity, CBasePlayer *pWeaponOwner )
-{
- typedef vector IDListType;
- static IDListType sIDList;
-
- memset( &ev[ num_ents ], 0, sizeof( entvars_t ) );
- pEntity->pev = &ev[ num_ents++ ];
-
- pEntity->Precache();
- pEntity->Spawn();
-
- if ( pWeaponOwner )
- {
- ItemInfo info;
-
- ((CBasePlayerWeapon *)pEntity)->m_pPlayer = pWeaponOwner;
-
- ((CBasePlayerWeapon *)pEntity)->GetItemInfo( &info );
-
- // ASSERT that a weapon with this id isn't in the list
- int theNewID = info.iId;
- IDListType::iterator theIter = std::find(sIDList.begin(), sIDList.end(), theNewID);
- ASSERT(theIter == sIDList.end());
-
- // Insert id into our list
- sIDList.push_back(theNewID);
-
- g_pWpns[ theNewID ] = (CBasePlayerWeapon *)pEntity;
- }
-}
-
-/*
-=====================
-CBaseEntity :: Killed
-
-If weapons code "kills" an entity, just set its effects to EF_NODRAW
-=====================
-*/
-void CBaseEntity :: Killed( entvars_t *pevAttacker, int iGib )
-{
- pev->effects |= EF_NODRAW;
-}
-
-/*
-=====================
-CBasePlayerWeapon :: DefaultReload
-=====================
-*/
-BOOL CBasePlayerWeapon :: DefaultReload( int iClipSize, int iAnim, float fDelay, int body )
-{
-
- if (m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] <= 0)
- return FALSE;
-
- int j = min(iClipSize - m_iClip, m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]);
-
- if (j == 0)
- return FALSE;
-
- m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + fDelay;
-
- //!!UNDONE -- reload sound goes here !!!
- //SendWeaponAnim( iAnim, UseDecrement(), body );
-
- m_fInReload = TRUE;
-
- m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + kDeployIdleInterval;
- return TRUE;
-}
-
-/*
-=====================
-CBasePlayerWeapon :: CanDeploy
-=====================
-*/
-BOOL CBasePlayerWeapon :: CanDeploy( void )
-{
- BOOL bHasAmmo = 0;
-
- if ( !pszAmmo1() )
- {
- // this weapon doesn't use ammo, can always deploy.
- return TRUE;
- }
-
- if ( pszAmmo1() )
- {
- bHasAmmo |= (m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] != 0);
- }
- if ( pszAmmo2() )
- {
- bHasAmmo |= (m_pPlayer->m_rgAmmo[m_iSecondaryAmmoType] != 0);
- }
- if (m_iClip > 0)
- {
- bHasAmmo |= 1;
- }
- if (!bHasAmmo)
- {
- return FALSE;
- }
-
- return TRUE;
-}
-
-/*
-=====================
-CBasePlayerWeapon :: DefaultDeploy
-
-=====================
-*/
-BOOL CBasePlayerWeapon :: DefaultDeploy( char *szViewModel, char *szWeaponModel, int iAnim, char *szAnimExt, int skiplocal, int body )
-{
- if ( !CanDeploy() )
- return FALSE;
-
- gEngfuncs.CL_LoadModel( szViewModel, &m_pPlayer->pev->viewmodel );
-
- SendWeaponAnim( iAnim, skiplocal, body );
-
- m_pPlayer->m_flNextAttack = this->GetDeployTime();
- m_flTimeWeaponIdle = this->GetDeployTime() + kDeployIdleInterval;
- return TRUE;
-}
-
-/*
-=====================
-CBasePlayerWeapon :: PlayEmptySound
-
-=====================
-*/
-BOOL CBasePlayerWeapon :: PlayEmptySound( void )
-{
- if (m_iPlayEmptySound)
- {
- HUD_PlaySound( "weapons/357_cock1.wav", 0.8 );
- m_iPlayEmptySound = 0;
- return 0;
- }
- return 0;
-}
-
-/*
-=====================
-CBasePlayerWeapon :: ResetEmptySound
-
-=====================
-*/
-void CBasePlayerWeapon :: ResetEmptySound( void )
-{
- m_iPlayEmptySound = 1;
-}
-
-/*
-=====================
-CBasePlayerWeapon::Holster
-
-Put away weapon
-=====================
-*/
-void CBasePlayerWeapon::Holster( int skiplocal /* = 0 */ )
-{
- m_fInReload = FALSE; // cancel any reload in progress.
- m_pPlayer->pev->viewmodel = 0;
-}
-
-/*
-=====================
-CBasePlayerWeapon::SendWeaponAnim
-
-Animate weapon model
-=====================
-*/
-void CBasePlayerWeapon::SendWeaponAnim( int iAnim, int skiplocal, int body )
-{
- m_pPlayer->pev->weaponanim = iAnim;
-
- HUD_SendWeaponAnim( iAnim, body, 0 );
-}
-
-/*
-=====================
-CBaseEntity::FireBulletsPlayer
-
-Only produces random numbers to match the server ones.
-=====================
-*/
-Vector CBaseEntity::FireBulletsPlayer ( ULONG cShots, Vector vecSrc, Vector vecDirShooting, Vector vecSpread, float flDistance, int iBulletType, int iTracerFreq, int iDamage, entvars_t *pevAttacker, int shared_rand )
-{
- //float x, y, z;
- Vector theShotDirection;
-
- theShotDirection.x = theShotDirection.y = theShotDirection.z = 0;
-
-// for ( ULONG iShot = 1; iShot <= cShots; iShot++ )
-// {
-// if ( pevAttacker == NULL )
-// {
-// // get circular gaussian spread
-// do {
-// x = RANDOM_FLOAT(-0.5, 0.5) + RANDOM_FLOAT(-0.5, 0.5);
-// y = RANDOM_FLOAT(-0.5, 0.5) + RANDOM_FLOAT(-0.5, 0.5);
-// z = x*x+y*y;
-// } while (z > 1);
-// }
-// else
-// {
-// //Use player's random seed.
-// // get circular gaussian spread
-// x = UTIL_SharedRandomFloat( shared_rand + iShot, -0.5, 0.5 ) + UTIL_SharedRandomFloat( shared_rand + ( 1 + iShot ) , -0.5, 0.5 );
-// y = UTIL_SharedRandomFloat( shared_rand + ( 2 + iShot ), -0.5, 0.5 ) + UTIL_SharedRandomFloat( shared_rand + ( 3 + iShot ), -0.5, 0.5 );
-// z = x * x + y * y;
-// }
-//
-// UTIL_GetRandomSpreadDir(shared_rand, iShot, vecDirShooting)
-// }
-
-// return Vector ( (float)(x * vecSpread.x), (float)(y * vecSpread.y), 0.0f );
- return theShotDirection;
-}
-
-
-bool GetCanUseWeapon()
-{
- // This mirrors the functionality of AvHPlayer::GetCanUseWeapon.
- return !gHUD.GetIsInTopDownMode() && !gHUD.GetIsBeingDigested() && !gHUD.GetIsEnsnared() && !gHUD.GetIsStunned() && gEngfuncs.GetViewModel() != NULL;
-}
-
-/*
-=====================
-CBasePlayerWeapon::ItemPostFrame
-
-Handles weapon firing, reloading, etc.
-=====================
-*/
-void CBasePlayerWeapon::ItemPostFrame( void )
-{
- // Hack initialization
- if (this->m_flLastAnimationPlayed >= 3.0f * BALANCE_VAR(kLeapROF) + gpGlobals->time)
- this->m_flLastAnimationPlayed = 0.0f;
-
- if ((m_fInReload) && (m_pPlayer->m_flNextAttack <= 0.0))
- {
-///////////////////////////////////////////////////////////////////////////////////////////////////////
-// Put code in here to predict reloads (ie, have the ammo on screen update before we get a response) //
-///////////////////////////////////////////////////////////////////////////////////////////////////////
-//#if 0 // FIXME, need ammo on client to make this work right
-// // complete the reload.
-// int j = min( iMaxClip() - m_iClip, m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]);
-//
-// // Add them to the clip
-// m_iClip += j;
-// m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] -= j;
-//#else
-// m_iClip += 10;
-//#endif
- m_fInReload = FALSE;
- }
-
- // Properly propagate the end animation
- if (this->PrevAttack2Status == true && !(m_pPlayer->pev->button & IN_ATTACK2))
- {
- switch (gHUD.GetCurrentWeaponID())
- {
- case AVH_WEAPON_SWIPE:
- this->SendWeaponAnim(12);
- break;
- case AVH_WEAPON_ACIDROCKET:
- this->SendWeaponAnim(8);
- break;
- case AVH_WEAPON_CLAWS:
- this->SendWeaponAnim(9);
- break;
- case AVH_WEAPON_STOMP:
- this->SendWeaponAnim(8);
- break;
- case AVH_WEAPON_DEVOUR:
- this->SendWeaponAnim(11);
- break;
- }
- }
-
- if ( (m_pPlayer->pev->button & IN_ATTACK) && !(m_pPlayer->pev->button & IN_ATTACK2) && (m_flNextPrimaryAttack <= 0.0) )
- {
- if (GetCanUseWeapon())
- {
- if ( (m_iClip == 0 && pszAmmo1()) ||
- (iMaxClip() == -1 && !m_pPlayer->m_rgAmmo[PrimaryAmmoIndex()] ) )
- {
- m_fFireOnEmpty = TRUE;
- }
-
-
- if ((gHUD.GetHUDUser3() == AVH_USER3_ALIEN_PLAYER1)
- && (gHUD.GetCurrentWeaponID() == AVH_ABILITY_LEAP)
- && (this->m_flLastAnimationPlayed + (float)BALANCE_VAR(kLeapROF) <= gpGlobals->time))
- {
- // : 0001151 predict energy too
- AvHAlienWeapon* theWeapon = dynamic_cast(g_pWpns[AVH_ABILITY_LEAP]);
- if ( theWeapon && theWeapon->IsUseable() ) {
- float theVolumeScalar = 1.0f;
- cl_entity_t *player = gEngfuncs.GetLocalPlayer();
- int theSilenceLevel = AvHGetAlienUpgradeLevel(player->curstate.iuser4, MASK_UPGRADE_6);
- switch(theSilenceLevel)
- {
- case 1:
- theVolumeScalar = (float)BALANCE_VAR(kSilenceLevel1Volume);
- break;
- case 2:
- theVolumeScalar = (float)BALANCE_VAR(kSilenceLevel2Volume);
- break;
- case 3:
- theVolumeScalar = (float)BALANCE_VAR(kSilenceLevel3Volume);
- break;
- }
- HUD_PlaySound( kLeapSound, theVolumeScalar);
- AvHMUDeductAlienEnergy(m_pPlayer->pev->fuser3, theWeapon->GetEnergyForAttack() );
- gEngfuncs.pEventAPI->EV_WeaponAnimation(3, 2);
- this->m_flLastAnimationPlayed = gpGlobals->time;
- }
- }
- //#ifdef AVH_CLIENT
- //if((m_iClip == 0) && ?
- //#endif
- PrimaryAttack();
- //return;
- }
- }
- // +movement: Rewritten to allow us to use +attack2 for movement abilities
- else if ((m_pPlayer->pev->button & IN_ATTACK2) && (gHUD.GetIsAlien()))
- {
- //m_flNextSecondaryAttack
- // Find out what kind of special movement we are using, and execute the animation for it
- if (this->PrevAttack2Status == false)
- {
- bool enabled=false;
- // : 0001151 predict energy too
- AvHAlienWeapon *theWeapon = dynamic_cast(g_pWpns[AVH_ABILITY_LEAP]);
- if ( theWeapon )
- enabled=theWeapon->IsUseable();
-
- switch (gHUD.GetHUDUser3())
- {
- case AVH_USER3_ALIEN_PLAYER1:
-
- if (enabled && (this->m_flLastAnimationPlayed + (float)BALANCE_VAR(kLeapROF) <= gpGlobals->time))
- {
- float theVolumeScalar = 1.0f;
- cl_entity_t *player = gEngfuncs.GetLocalPlayer();
- int theSilenceLevel = AvHGetAlienUpgradeLevel(player->curstate.iuser4, MASK_UPGRADE_6);
- switch(theSilenceLevel)
- {
- case 1:
- theVolumeScalar = (float)BALANCE_VAR(kSilenceLevel1Volume);
- break;
- case 2:
- theVolumeScalar = (float)BALANCE_VAR(kSilenceLevel2Volume);
- break;
- case 3:
- theVolumeScalar = (float)BALANCE_VAR(kSilenceLevel3Volume);
- break;
- }
- HUD_PlaySound( kLeapSound, theVolumeScalar);
- AvHMUDeductAlienEnergy(m_pPlayer->pev->fuser3, theWeapon->GetEnergyForAttack() );
- this->SendWeaponAnim(3);
- this->m_flLastAnimationPlayed = gpGlobals->time;
- }
- break;
- case AVH_USER3_ALIEN_PLAYER4:
- switch (gHUD.GetCurrentWeaponID())
- {
- case AVH_WEAPON_SWIPE:
- this->SendWeaponAnim(9);
- break;
- case AVH_WEAPON_ACIDROCKET:
- this->SendWeaponAnim(11);
- break;
- }
- break;
- case AVH_USER3_ALIEN_PLAYER5:
- switch (gHUD.GetCurrentWeaponID())
- {
- case AVH_WEAPON_CLAWS:
- this->SendWeaponAnim(5);
- break;
- case AVH_WEAPON_DEVOUR:
- this->SendWeaponAnim(18);
- break;
- case AVH_WEAPON_STOMP:
- this->SendWeaponAnim(15);
- break;
- }
- break;
- }
- }
-
- if ((gHUD.GetHUDUser3() == AVH_USER3_ALIEN_PLAYER1)
- && (this->m_flLastAnimationPlayed + BALANCE_VAR(kLeapROF) < gpGlobals->time))
- this->PrevAttack2Status = false;
- else
- this->PrevAttack2Status = true;
-
- return;
-// if (GetCanUseWeapon())
-// {
-// PrimaryAttack();
-// }
- }
- else if ( m_pPlayer->pev->button & IN_RELOAD && iMaxClip() != WEAPON_NOCLIP && !m_fInReload )
- {
- if (GetCanUseWeapon())
- {
- // reload when reload is pressed, or if no buttons are down and weapon is empty.
- Reload();
- }
- }
- // +movement: Removed case for +attack2
- else if ( !(m_pPlayer->pev->button & (IN_ATTACK /*|IN_ATTACK2 */) ) )
- {
- if (GetCanUseWeapon())
- {
-
- // no fire buttons down
-
- m_fFireOnEmpty = FALSE;
-
- // weapon is useable. Reload if empty and weapon has waited as long as it has to after firing
- if ( m_iClip == 0 && !(iFlags() & ITEM_FLAG_NOAUTORELOAD) && m_flNextPrimaryAttack < 0.0 )
- {
- // << CGC >> Only reload if we have more ammo to reload with
- if(m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] > 0)
- {
- Reload();
- return;
- }
- }
-
- WeaponIdle( );
- }
- this->PrevAttack2Status = false;
- return;
- }
-
- this->PrevAttack2Status = false;
-
- // catch all
- if ( ShouldWeaponIdle() )
- {
- WeaponIdle();
- }
-}
-
-/*
-=====================
-CBasePlayer::SelectItem
-
- Switch weapons
-=====================
-*/
-void CBasePlayer::SelectItem(const char *pstr)
-{
- if (!pstr)
- return;
-
- CBasePlayerItem *pItem = NULL;
-
- if (!pItem)
- return;
-
-
- if (pItem == m_pActiveItem)
- return;
-
- if (m_pActiveItem)
- m_pActiveItem->Holster( );
-
- m_pLastItem = m_pActiveItem;
- m_pActiveItem = pItem;
-
- if (m_pActiveItem)
- {
- m_pActiveItem->Deploy( );
- }
-}
-
-/*
-=====================
-CBasePlayer::SelectLastItem
-
-=====================
-*/
-void CBasePlayer::SelectLastItem(void)
-{
- if (!m_pLastItem)
- {
- return;
- }
-
- if ( m_pActiveItem && !m_pActiveItem->CanHolster() )
- {
- return;
- }
-
- if (m_pActiveItem)
- m_pActiveItem->Holster( );
-
- CBasePlayerItem *pTemp = m_pActiveItem;
- m_pActiveItem = m_pLastItem;
- m_pLastItem = pTemp;
- m_pActiveItem->Deploy( );
-}
-
-/*
-=====================
-CBasePlayer::Killed
-
-=====================
-*/
-void CBasePlayer::Killed( entvars_t *pevAttacker, int iGib )
-{
- // Holster weapon immediately, to allow it to cleanup
- if ( m_pActiveItem )
- m_pActiveItem->Holster( );
-}
-
-/*
-=====================
-CBasePlayer::Spawn
-
-=====================
-*/
-void CBasePlayer::Spawn( void )
-{
- if (m_pActiveItem)
- m_pActiveItem->Deploy( );
-
-// this->m_flLastAnimationPlayed = gpGlobals->time;
-}
-
-/*
-=====================
-UTIL_TraceLine
-
-Don't actually trace, but act like the trace didn't hit anything.
-=====================
-*/
-void UTIL_TraceLine( const Vector &vecStart, const Vector &vecEnd, IGNORE_MONSTERS igmon, edict_t *pentIgnore, TraceResult *ptr )
-{
- memset( ptr, 0, sizeof( *ptr ) );
- ptr->flFraction = 1.0;
-}
-
-/*
-=====================
-UTIL_ParticleBox
-
-For debugging, draw a box around a player made out of particles
-=====================
-*/
-void UTIL_ParticleBox( CBasePlayer *player, float *mins, float *maxs, float life, unsigned char r, unsigned char g, unsigned char b )
-{
- int i;
- vec3_t mmin, mmax;
-
- for ( i = 0; i < 3; i++ )
- {
- mmin[ i ] = player->pev->origin[ i ] + mins[ i ];
- mmax[ i ] = player->pev->origin[ i ] + maxs[ i ];
- }
-
- gEngfuncs.pEfxAPI->R_ParticleBox( (float *)&mmin, (float *)&mmax, 5.0, 0, 255, 0 );
-}
-
-/*
-=====================
-UTIL_ParticleBoxes
-
-For debugging, draw boxes for other collidable players
-=====================
-*/
-void UTIL_ParticleBoxes( void )
-{
- int idx;
- physent_t *pe;
- cl_entity_t *player;
- vec3_t mins, maxs;
-
- gEngfuncs.pEventAPI->EV_SetUpPlayerPrediction( false, true );
-
- // Store off the old count
- gEngfuncs.pEventAPI->EV_PushPMStates();
-
- player = gEngfuncs.GetLocalPlayer();
- // Now add in all of the players.
- gEngfuncs.pEventAPI->EV_SetSolidPlayers ( player->index - 1 );
-
- for ( idx = 1; idx < 100; idx++ )
- {
- pe = gEngfuncs.pEventAPI->EV_GetPhysent( idx );
- if ( !pe )
- break;
-
- if ( pe->info >= 1 && pe->info <= gEngfuncs.GetMaxClients() )
- {
- mins = pe->origin + pe->mins;
- maxs = pe->origin + pe->maxs;
-
- gEngfuncs.pEfxAPI->R_ParticleBox( (float *)&mins, (float *)&maxs, 0, 0, 255, 2.0 );
- }
- }
-
- gEngfuncs.pEventAPI->EV_PopPMStates();
-}
-
-/*
-=====================
-UTIL_ParticleLine
-
-For debugging, draw a line made out of particles
-=====================
-*/
-void UTIL_ParticleLine( CBasePlayer *player, float *start, float *end, float life, unsigned char r, unsigned char g, unsigned char b )
-{
- gEngfuncs.pEfxAPI->R_ParticleLine( start, end, r, g, b, life );
-}
-
-/*
-=====================
-CBasePlayerWeapon::PrintState
-
-For debugging, print out state variables to log file
-=====================
-*/
-void CBasePlayerWeapon::PrintState( void )
-{
- COM_Log( "c:\\hl.log", "%.4f ", gpGlobals->time );
- COM_Log( "c:\\hl.log", "%.4f ", m_pPlayer->m_flNextAttack );
- COM_Log( "c:\\hl.log", "%.4f ", m_flNextPrimaryAttack );
- COM_Log( "c:\\hl.log", "%.4f ", m_flTimeWeaponIdle - gpGlobals->time);
- COM_Log( "c:\\hl.log", "%i ", m_iClip );
- COM_Log( "c:\\hl.log", "\r\n");
-}
-
-/*
-=====================
-HUD_InitClientWeapons
-
-Set up weapons, player and functions needed to run weapons code client-side.
-=====================
-*/
-void HUD_InitClientWeapons( void )
-{
- static int initialized = 0;
- if ( initialized )
- return;
-
- initialized = 1;
-
- // Set up pointer ( dummy object )
- gpGlobals = &Globals;
-
- // Fill in current time ( probably not needed )
- gpGlobals->time = gEngfuncs.GetClientTime();
-
- // Fake functions
- g_engfuncs.pfnPrecacheModel = stub_PrecacheModel;
- g_engfuncs.pfnPrecacheSound = stub_PrecacheSound;
- g_engfuncs.pfnPrecacheEvent = stub_PrecacheEvent;
- g_engfuncs.pfnNameForFunction = stub_NameForFunction;
- g_engfuncs.pfnSetModel = stub_SetModel;
- g_engfuncs.pfnSetClientMaxspeed = HUD_SetMaxSpeed;
-
- // Handled locally
- g_engfuncs.pfnPlaybackEvent = HUD_PlaybackEvent;
- g_engfuncs.pfnAlertMessage = AlertMessage;
-
- // Pass through to engine
- g_engfuncs.pfnPrecacheEvent = gEngfuncs.pfnPrecacheEvent;
- g_engfuncs.pfnRandomFloat = gEngfuncs.pfnRandomFloat;
- g_engfuncs.pfnRandomLong = gEngfuncs.pfnRandomLong;
-
- // Allocate a slot for the local player
- HUD_PrepEntity( &player , NULL );
-
-
- // Allocate slot(s) for each weapon that we are going to be predicting
- //HUD_PrepEntity( &g_Glock, &player );
- HUD_PrepEntity( &gKnife, &player);
- HUD_PrepEntity( &gMachineGun, &player);
- HUD_PrepEntity( &gPistol, &player);
- HUD_PrepEntity( &gSonicGun, &player);
- HUD_PrepEntity( &gHeavyMachineGun, &player);
- HUD_PrepEntity( &gGrenadeGun, &player);
- HUD_PrepEntity( &gGrenade, &player);
- HUD_PrepEntity( &gWelder, &player);
- HUD_PrepEntity( &gMine, &player);
- HUD_PrepEntity( &gSpitGun, &player);
- HUD_PrepEntity( &gClaws, &player);
- HUD_PrepEntity( &gSpores, &player);
- HUD_PrepEntity( &gSpikeGun, &player);
- HUD_PrepEntity( &gBite, &player);
- HUD_PrepEntity( &gBite2, &player);
- HUD_PrepEntity( &gSwipe, &player);
- HUD_PrepEntity( &gWebSpinner, &player);
- HUD_PrepEntity( &gPrimalScream, &player);
- //HUD_PrepEntity( &gParalysisGun, &player);
-
- HUD_PrepEntity( &gBlink, &player);
- HUD_PrepEntity( &gParasite, &player);
- HUD_PrepEntity( &gUmbra, &player);
- HUD_PrepEntity( &gDivineWind, &player);
- HUD_PrepEntity( &gBileBomb, &player);
- HUD_PrepEntity( &gAcidRocket, &player);
- HUD_PrepEntity( &gHealingSpray, &player);
- HUD_PrepEntity( &gMetabolize, &player);
- HUD_PrepEntity( &gStomp, &player);
- HUD_PrepEntity( &gDevour, &player);
-
- HUD_PrepEntity( &gLeap, &player);
- HUD_PrepEntity( &gCharge, &player);
-
- gJetpackEventID = PRECACHE_EVENT(1, kJetpackEvent);
- //gWallJumpEventID = PRECACHE_EVENT(1, kWallJumpEvent);
- //gFlightEventID = PRECACHE_EVENT(1, kFlightEvent);
- gTeleportEventID = PRECACHE_EVENT(1, kTeleportEvent);
- gPhaseInEventID = PRECACHE_EVENT(1, kPhaseInEvent);
- gSiegeHitEventID = PRECACHE_EVENT(1, kSiegeHitEvent);
- gSiegeViewHitEventID = PRECACHE_EVENT(1, kSiegeViewHitEvent);
- gCommanderPointsAwardedEventID = PRECACHE_EVENT(1, kCommanderPointsAwardedEvent);
- gBlinkEffectSuccessEventID = PRECACHE_EVENT(1, kBlinkEffectSuccessEventName);
-}
-
-/*
-=====================
-HUD_GetLastOrg
-
-Retruns the last position that we stored for egon beam endpoint.
-=====================
-*/
-void HUD_GetLastOrg( float *org )
-{
- int i;
-
- // Return last origin
- for ( i = 0; i < 3; i++ )
- {
- org[i] = previousorigin[i];
- }
-}
-
-/*
-=====================
-HUD_SetLastOrg
-
-Remember our exact predicted origin so we can draw the egon to the right position.
-=====================
-*/
-void HUD_SetLastOrg( void )
-{
- int i;
-
- // Offset final origin by view_offset
- for ( i = 0; i < 3; i++ )
- {
- previousorigin[i] = g_finalstate->playerstate.origin[i] + g_finalstate->client.view_ofs[ i ];
- }
-}
-
-
-CBasePlayerWeapon* HUD_GetWeaponForID(int inID)
-{
- CBasePlayerWeapon* pWeapon = NULL;
-
- switch(inID)
- {
-// case WEAPON_GLOCK:
-// pWeapon = &g_Glock;
-// break;
- case AVH_WEAPON_KNIFE:
- pWeapon = &gKnife;
- break;
- case AVH_WEAPON_MG:
- pWeapon = &gMachineGun;
- break;
- case AVH_WEAPON_PISTOL:
- pWeapon = &gPistol;
- break;
- case AVH_WEAPON_SONIC:
- pWeapon = &gSonicGun;
- break;
- case AVH_WEAPON_HMG:
- pWeapon = &gHeavyMachineGun;
- break;
- case AVH_WEAPON_GRENADE_GUN:
- pWeapon = &gGrenadeGun;
- break;
- case AVH_WEAPON_GRENADE:
- pWeapon = &gGrenade;
- break;
- case AVH_WEAPON_WELDER:
- pWeapon = &gWelder;
- break;
- case AVH_WEAPON_MINE:
- pWeapon = &gMine;
- break;
- case AVH_WEAPON_SPIT:
- pWeapon = &gSpitGun;
- break;
- case AVH_WEAPON_CLAWS:
- pWeapon = &gClaws;
- break;
- case AVH_WEAPON_SPORES:
- pWeapon = &gSpores;
- break;
- case AVH_WEAPON_SPIKE:
- pWeapon = &gSpikeGun;
- break;
- case AVH_WEAPON_BITE:
- pWeapon = &gBite;
- break;
- case AVH_WEAPON_BITE2:
- pWeapon = &gBite2;
- break;
- case AVH_WEAPON_SWIPE:
- pWeapon = &gSwipe;
- break;
- case AVH_WEAPON_WEBSPINNER:
- pWeapon = &gWebSpinner;
- break;
- case AVH_WEAPON_PRIMALSCREAM:
- pWeapon = &gPrimalScream;
- break;
- case AVH_WEAPON_PARASITE:
- pWeapon = &gParasite;
- break;
- case AVH_WEAPON_UMBRA:
- pWeapon = &gUmbra;
- break;
- case AVH_WEAPON_BLINK:
- pWeapon = &gBlink;
- break;
- case AVH_WEAPON_DIVINEWIND:
- pWeapon = &gDivineWind;
- break;
-// case AVH_WEAPON_PARALYSIS:
-// pWeapon = &gParalysisGun;
-// break;
- case AVH_WEAPON_BILEBOMB:
- pWeapon = &gBileBomb;
- break;
- case AVH_WEAPON_ACIDROCKET:
- pWeapon = &gAcidRocket;
- break;
- case AVH_WEAPON_HEALINGSPRAY:
- pWeapon = &gHealingSpray;
- break;
- case AVH_WEAPON_METABOLIZE:
- pWeapon = &gMetabolize;
- break;
- case AVH_WEAPON_STOMP:
- pWeapon = &gStomp;
- break;
- case AVH_WEAPON_DEVOUR:
- pWeapon = &gDevour;
- break;
-
- // Abilities
- case AVH_ABILITY_LEAP:
- pWeapon = &gLeap;
- break;
- case AVH_ABILITY_CHARGE:
- pWeapon = &gCharge;
- break;
- }
-
- return pWeapon;
-}
-
-
-bool HUD_GetWeaponEnabled(int inID)
-{
- ASSERT(inID >= 0);
- ASSERT(inID < 32);
-
- // : 497 - use the enabled state in the associated WEAPON instead of the CBasePlayerWeapon's iuser3
- bool theWeaponEnabled = false;
- CBasePlayerWeapon* theWeapon = g_pWpns[inID];
- if(theWeapon)
- {
- ItemInfo theItemInfo;
- theWeapon->GetItemInfo(&theItemInfo);
- WEAPON *pWeapon = gWR.GetWeapon( theItemInfo.iId );
- if ( pWeapon != 0 ) {
- theWeaponEnabled = (pWeapon->iEnabled == 1);
- }
- }
-
- return theWeaponEnabled;
-}
-
-/*
-=====================
-HUD_WeaponsPostThink
-
-Run Weapon firing code on client
-=====================
-*/
-void HUD_WeaponsPostThink( local_state_s *from, local_state_s *to, usercmd_t *cmd, double time, unsigned int random_seed )
-{
- int i;
- int buttonsChanged;
- CBasePlayerWeapon* pCurrent = NULL;
- weapon_data_t nulldata, *pfrom, *pto;
- static int lasthealth;
-
- memset( &nulldata, 0, sizeof( nulldata ) );
-
- HUD_InitClientWeapons();
-
- // Get current clock
- gpGlobals->time = time;
-
- // Fill in data based on selected weapon
- // FIXME, make this a method in each weapon? where you pass in an entity_state_t *?
- // Store pointer to our destination entity_state_t so we can get our origin, etc. from it
- CBasePlayerWeapon* pWeapon = HUD_GetWeaponForID(from->client.m_iId);
-
- // for setting up events on the client
- g_finalstate = to;
-
- // If we are running events/etc. go ahead and see if we
- // managed to die between last frame and this one
- // If so, run the appropriate player killed or spawn function
- if ( g_runfuncs )
- {
- if ( to->client.health <= 0 && lasthealth > 0 )
- {
- player.Killed( NULL, 0 );
-
- }
- else if ( to->client.health > 0 && lasthealth <= 0 )
- {
- player.Spawn();
- }
-
- lasthealth = to->client.health;
- }
-
- // We are not predicting the current weapon, just bow out here.
- if ( !pWeapon )
- return;
-
- for ( i = 0; i < 32; i++ )
- {
- pCurrent = g_pWpns[ i ];
- if ( !pCurrent )
- {
- continue;
- }
-
- pfrom = &from->weapondata[ i ];
-
- pCurrent->m_fInReload = pfrom->m_fInReload;
- pCurrent->m_fInSpecialReload = pfrom->m_fInSpecialReload;
-// pCurrent->m_flPumpTime = pfrom->m_flPumpTime;
- pCurrent->m_iClip = pfrom->m_iClip;
- pCurrent->m_flNextPrimaryAttack = pfrom->m_flNextPrimaryAttack;
- pCurrent->m_flNextSecondaryAttack = pfrom->m_flNextSecondaryAttack;
- pCurrent->m_flTimeWeaponIdle = pfrom->m_flTimeWeaponIdle;
- if(pWeapon && (pWeapon->m_iId == pfrom->m_iId))
- {
- // Predict clip
- gHUD.m_Ammo.SetCurrentClip(pfrom->m_iClip);
-
- AvHBasePlayerWeapon* theWeapon = dynamic_cast(pWeapon);
- if(theWeapon)
- {
- gHUD.SetCurrentWeaponData(pWeapon->m_iId, theWeapon->GetEnabledState());
- }
-
- //gHUD.SetClientDebugCSP(pfrom, from->client.m_flNextAttack);
- }
-
- // Tell HUD what energy level is needed to use weapon, so alien HUD can indicate this
- float theEnergyLevel = 0.0f;
- AvHMUGetEnergyCost((AvHWeaponID)(pWeapon->m_iId), theEnergyLevel);
- gHUD.SetCurrentUseableEnergyLevel(theEnergyLevel);
-
-// New SDK stuff...needed?
-// pCurrent->pev->fuser1 = pfrom->fuser1;
- pCurrent->m_flStartThrow = pfrom->fuser2;
- pCurrent->m_flReleaseThrow = pfrom->fuser3;
-// pCurrent->m_chargeReady = pfrom->iuser1;
-// pCurrent->m_fInAttack = pfrom->iuser2;
- pCurrent->pev->iuser3 = pfrom->iuser3;
-
-// pCurrent->m_iSecondaryAmmoType = (int)from->client.vuser3[2];
- pCurrent->m_iPrimaryAmmoType = (int)from->client.vuser4[0];
-// player.m_rgAmmo[ pCurrent->m_iPrimaryAmmoType ] = (int)from->client.vuser4[1];
-// player.m_rgAmmo[ pCurrent->m_iSecondaryAmmoType ] = (int)from->client.vuser4[2];
- }
-
- // For random weapon events, use this seed to seed random # generator
- player.random_seed = random_seed;
-
- // Get old buttons from previous state.
- player.m_afButtonLast = from->playerstate.oldbuttons;
-
- // Which buttsons chave changed
- buttonsChanged = (player.m_afButtonLast ^ cmd->buttons); // These buttons have changed this frame
-
- // Debounced button codes for pressed/released
- // The changed ones still down are "pressed"
- player.m_afButtonPressed = buttonsChanged & cmd->buttons;
- // The ones not down are "released"
- player.m_afButtonReleased = buttonsChanged & (~cmd->buttons);
-
- // Set player variables that weapons code might check/alter
- player.pev->button = cmd->buttons;
-
- player.pev->velocity = from->client.velocity;
- player.pev->flags = from->client.flags;
-
- player.pev->deadflag = from->client.deadflag;
- player.pev->waterlevel = from->client.waterlevel;
- player.pev->maxspeed = from->client.maxspeed;
- player.pev->fov = from->client.fov;
- player.pev->weaponanim = from->client.weaponanim;
- player.pev->viewmodel = from->client.viewmodel;
- player.m_flNextAttack = from->client.m_flNextAttack;
- //player.m_flNextAmmoBurn = from->client.fuser2;
- //player.m_flAmmoStartCharge = from->client.fuser3;
-
- // Removed this because NS uses vuser1 and vuser2 (and the HL weapons aren't used)
- ////Stores all our ammo info, so the client side weapons can use them.
- //player.ammo_9mm = (int)from->client.vuser1[0];
- //player.ammo_357 = (int)from->client.vuser1[1];
- //player.ammo_argrens = (int)from->client.vuser1[2];
- //player.ammo_bolts = (int)from->client.ammo_nails; //is an int anyways...
- //player.ammo_buckshot = (int)from->client.ammo_shells;
- //player.ammo_uranium = (int)from->client.ammo_cells;
- //player.ammo_hornets = (int)from->client.vuser2[0];
- //player.ammo_rockets = (int)from->client.ammo_rockets;
-
-
- // Point to current weapon object
- if ( from->client.m_iId )
- {
- player.m_pActiveItem = g_pWpns[ from->client.m_iId ];
- }
-
- if ( player.m_pActiveItem->m_iId == WEAPON_RPG )
- {
- ( ( CRpg * )player.m_pActiveItem)->m_fSpotActive = (int)from->client.vuser2[ 1 ];
- ( ( CRpg * )player.m_pActiveItem)->m_cActiveRockets = (int)from->client.vuser2[ 2 ];
- }
-
- // Don't go firing anything if we have died.
- // Or if we don't have a weapon model deployed
- if ( ( player.pev->deadflag != ( DEAD_DISCARDBODY + 1 ) ) && !CL_IsDead() && player.pev->viewmodel && !g_iUser1 )
- {
-
- if ( player.m_flNextAttack <= 0 )
- {
- pWeapon->ItemPostFrame();
- }
-// if ( g_runfuncs )
-// {
-// pWeapon->PrintState();
-// }
- }
-
- // Assume that we are not going to switch weapons
- to->client.m_iId = from->client.m_iId;
-
- // Now see if we issued a changeweapon command ( and we're not dead )
- if ( cmd->weaponselect && ( player.pev->deadflag != ( DEAD_DISCARDBODY + 1 ) ) )
- {
- // Switched to a different weapon?
- if ( from->weapondata[ cmd->weaponselect ].m_iId == cmd->weaponselect )
- {
- ASSERT(cmd->weaponselect >= 0);
- ASSERT(cmd->weaponselect < 32);
-
- CBasePlayerWeapon *pNew = g_pWpns[ cmd->weaponselect ];
- if ( pNew && ( pNew != pWeapon ) && player.m_pActiveItem && player.m_pActiveItem->CanHolster())
- {
- // Put away old weapon
- if (player.m_pActiveItem)
- player.m_pActiveItem->Holster( );
-
- player.m_pLastItem = player.m_pActiveItem;
- player.m_pActiveItem = pNew;
-
- // Deploy new weapon
- if (player.m_pActiveItem)
- {
- player.m_pActiveItem->Deploy( );
- }
-
- // Update weapon id so we can predict things correctly.
- to->client.m_iId = cmd->weaponselect;
- }
- }
- }
-
- // Copy in results of prediction code
- to->client.viewmodel = player.pev->viewmodel;
- to->client.fov = player.pev->fov;
- to->client.weaponanim = player.pev->weaponanim;
- to->client.m_flNextAttack = player.m_flNextAttack;
- //to->client.fuser2 = player.m_flNextAmmoBurn;
- //to->client.fuser3 = player.m_flAmmoStartCharge;
- to->client.maxspeed = player.pev->maxspeed;
-
-// Removed this because NS uses vuser1 and vuser2 (and the HL weapons aren't used)
-// //HL Weapons
-// to->client.vuser1[0] = player.ammo_9mm;
-// to->client.vuser1[1] = player.ammo_357;
-// to->client.vuser1[2] = player.ammo_argrens;
-//
-// to->client.ammo_nails = player.ammo_bolts;
-// to->client.ammo_shells = player.ammo_buckshot;
-// to->client.ammo_cells = player.ammo_uranium;
-// to->client.vuser2[0] = player.ammo_hornets;
-// to->client.ammo_rockets = player.ammo_rockets;
-
- if ( player.m_pActiveItem->m_iId == WEAPON_RPG )
- {
- from->client.vuser2[ 1 ] = ( ( CRpg * )player.m_pActiveItem)->m_fSpotActive;
- from->client.vuser2[ 2 ] = ( ( CRpg * )player.m_pActiveItem)->m_cActiveRockets;
- }
-
- // Make sure that weapon animation matches what the game .dll is telling us
- // over the wire ( fixes some animation glitches )
- // Ensure that the fade and onos won't get these, to play the blink and charge animations correctly
- bool noRun = (to->client.iuser3 == AVH_USER3_ALIEN_PLAYER4) || (to->client.iuser3 == AVH_USER3_ALIEN_PLAYER5);
- if (g_runfuncs && ( HUD_GetWeaponAnim() != to->client.weaponanim ) && !(CheckInAttack2()) && !noRun)
- {
- int body = 2;
-
- //Pop the model to body 0.
- //if ( pWeapon == &g_Tripmine )
- // body = 0;
-
- // Force a fixed anim down to viewmodel
- HUD_SendWeaponAnim( to->client.weaponanim, body, 1 );
- }
-
- for ( i = 0; i < 32; i++ )
- {
- pCurrent = g_pWpns[ i ];
-
- pto = &to->weapondata[ i ];
-
- if ( !pCurrent )
- {
- memset( pto, 0, sizeof( weapon_data_t ) );
- continue;
- }
-
- pto->m_fInReload = pCurrent->m_fInReload;
- pto->m_fInSpecialReload = pCurrent->m_fInSpecialReload;
-// pto->m_flPumpTime = pCurrent->m_flPumpTime;
- pto->m_iClip = pCurrent->m_iClip;
- pto->m_flNextPrimaryAttack = pCurrent->m_flNextPrimaryAttack;
- pto->m_flNextSecondaryAttack = pCurrent->m_flNextSecondaryAttack;
- pto->m_flTimeWeaponIdle = pCurrent->m_flTimeWeaponIdle;
-// pto->fuser1 = pCurrent->pev->fuser1;
-// pto->fuser2 = pCurrent->m_flStartThrow;
-// pto->fuser3 = pCurrent->m_flReleaseThrow;
-// pto->iuser1 = pCurrent->m_chargeReady;
-// pto->iuser2 = pCurrent->m_fInAttack;
- pto->iuser3 = pCurrent->pev->iuser3;
-
- // Decrement weapon counters, server does this at same time ( during post think, after doing everything else )
- pto->m_flNextReload -= cmd->msec / 1000.0;
- pto->m_fNextAimBonus -= cmd->msec / 1000.0;
- pto->m_flNextPrimaryAttack -= cmd->msec / 1000.0;
- pto->m_flNextSecondaryAttack -= cmd->msec / 1000.0;
- pto->m_flTimeWeaponIdle -= cmd->msec / 1000.0;
- pto->fuser1 -= cmd->msec / 1000.0;
-
- to->client.vuser3[2] = pCurrent->m_iSecondaryAmmoType;
- to->client.vuser4 = pCurrent->pev->vuser4;
-// to->client.vuser4[0] = pCurrent->m_iPrimaryAmmoType;
-// to->client.vuser4[1] = player.m_rgAmmo[ pCurrent->m_iPrimaryAmmoType ];
-// to->client.vuser4[2] = player.m_rgAmmo[ pCurrent->m_iSecondaryAmmoType ];
-
-/* if ( pto->m_flPumpTime != -9999 )
- {
- pto->m_flPumpTime -= cmd->msec / 1000.0;
- if ( pto->m_flPumpTime < -0.001 )
- pto->m_flPumpTime = -0.001;
- }*/
-
- if ( pto->m_fNextAimBonus < -1.0 )
- {
- pto->m_fNextAimBonus = -1.0;
- }
-
- if ( pto->m_flNextPrimaryAttack < -1.0 )
- {
- pto->m_flNextPrimaryAttack = -1.0;
- }
-
- if ( pto->m_flNextSecondaryAttack < -0.001 )
- {
- pto->m_flNextSecondaryAttack = -0.001;
- }
-
- if ( pto->m_flTimeWeaponIdle < -0.001 )
- {
- pto->m_flTimeWeaponIdle = -0.001;
- }
-
- if ( pto->m_flNextReload < -0.001 )
- {
- pto->m_flNextReload = -0.001;
- }
-
- if ( pto->fuser1 < -0.001 )
- {
- pto->fuser1 = -0.001;
- }
- }
-
- // m_flNextAttack is now part of the weapons, but is part of the player instead
- to->client.m_flNextAttack -= cmd->msec / 1000.0;
- if ( to->client.m_flNextAttack < -0.001 )
- {
- to->client.m_flNextAttack = -0.001;
- }
-
- to->client.fuser2 -= cmd->msec / 1000.0;
- if ( to->client.fuser2 < -0.001 )
- {
- to->client.fuser2 = -0.001;
- }
-
- to->client.fuser3 -= cmd->msec / 1000.0;
- if ( to->client.fuser3 < -0.001 )
- {
- to->client.fuser3 = -0.001;
- }
-
- // Store off the last position from the predicted state.
- HUD_SetLastOrg();
-
- // Wipe it so we can't use it after this frame
- g_finalstate = NULL;
-}
-
-
-/*
-=====================
-HUD_PostRunCmd
-
-Client calls this during prediction, after it has moved the player and updated any info changed into to->
-time is the current client clock based on prediction
-cmd is the command that caused the movement, etc
-runfuncs is 1 if this is the first time we've predicted this command. If so, sounds and effects should play, otherwise, they should
-be ignored
-=====================
-*/
-void CL_DLLEXPORT HUD_PostRunCmd( struct local_state_s *from, struct local_state_s *to, struct usercmd_s *cmd, int runfuncs, double time, unsigned int random_seed )
-{
-// RecClPostRunCmd(from, to, cmd, runfuncs, time, random_seed);
-
- g_runfuncs = runfuncs;
-
- if ( cl_lw && cl_lw->value )
- {
- HUD_WeaponsPostThink( from, to, cmd, time, random_seed );
- }
- else
- {
- to->client.fov = g_lastFOV;
- }
-
- // Check to see whether too play local jetpack effects
- if(runfuncs)
- {
- static int sLastTime = 0;
- float theTimePassed = time - sLastTime;
-
- //CheckJetpack();
-
- //UpdateJetpackLights();
-
- sLastTime = time;
- }
-
- // All games can use FOV state
- g_lastFOV = to->client.fov;
-}
-
-
-
+/***
+*
+* Copyright (c) 1999, Valve LLC. All rights reserved.
+*
+* This product contains software technology licensed from Id
+* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
+* All Rights Reserved.
+*
+* Use, distribution, and modification of this source code and/or resulting
+* object code is restricted to non-commercial enhancements to products from
+* Valve LLC. All other use, distribution, or modification is prohibited
+* without written permission from Valve LLC.
+*
+* Modified by Charlie Cleveland:
+*
+* $Workfile: hl_weapons.cpp $
+* $Date: 2002/10/24 21:11:52 $
+*
+* -------------------------------------------------------------------------------
+* $Log: hl_weapons.cpp,v $
+* Revision 1.31 2002/10/24 21:11:52 Flayra
+* - Updated jetpack effect because it was really buggy this old way
+*
+* Revision 1.30 2002/10/16 02:12:10 Flayra
+* - Valve anti-cheat integrated!
+*
+* Revision 1.29 2002/10/16 00:36:40 Flayra
+* - Removed blink fail
+*
+* Revision 1.28 2002/08/31 18:01:59 Flayra
+* - Work at VALVe
+*
+* Revision 1.27 2002/07/08 16:09:03 Flayra
+* - Removed unneeded code here, so random numbers were generated properly on both client and server
+*
+* Revision 1.26 2002/07/01 20:56:31 Flayra
+* - Added babbler gun
+*
+* Revision 1.25 2002/06/25 17:03:01 Flayra
+* - Removed old weapons, added new weapons, fixed mines, iuser3 enables and disables weapons
+*
+* ===============================================================================
+****/
+#include "../hud.h"
+#include "../cl_util.h"
+#include "common/const.h"
+#include "common/entity_state.h"
+#include "common/cl_entity.h"
+#include "../demo.h"
+#include "common/usercmd.h"
+#include "common/event_flags.h"
+#include "common/event_api.h"
+#include "cl_dll/com_weapons.h"
+#include "cl_dll/ammo.h"
+#include "cl_dll/ammohistory.h"
+#include "dlls/extdll.h"
+#include "dlls/util.h"
+#include "dlls/cbase.h"
+#include "dlls/monsters.h"
+#include "dlls/weapons.h"
+#include "dlls/nodes.h"
+#include "dlls/player.h"
+#include "mod/AvHEvents.h"
+
+#include "common/usercmd.h"
+#include "common/entity_state.h"
+#include "common/demo_api.h"
+#include "pm_shared/pm_defs.h"
+#include "common/event_api.h"
+#include "common/r_efx.h"
+
+#include "../hud_iface.h"
+#include "../com_weapons.h"
+
+#include "mod/AvHMarineWeapons.h"
+#include "mod/AvHSpecials.h"
+#include "mod/AvHAlienWeapons.h"
+#include "mod/AvHAlienAbilities.h"
+#include "mod/AvHAlienWeaponConstants.h"
+#include "mod/AvHAlienAbilityConstants.h"
+#include "mod/AvHMovementUtil.h"
+
+#include "engine/APIProxy.h"
+#include "../Exports.h"
+
+extern globalvars_t *gpGlobals;
+extern bool gIsJetpacking;
+
+// Pool of client side entities/entvars_t
+static entvars_t ev[ 32 ];
+static int num_ents = 0;
+
+// The entity we'll use to represent the local client
+static CBasePlayer player;
+
+// Local version of game .dll global variables ( time, etc. )
+static globalvars_t Globals;
+
+static CBasePlayerWeapon *g_pWpns[ 32 ];
+
+bool CheckInAttack2(void);
+
+vec3_t previousorigin;
+
+// HLDM Weapon placeholder entities.
+//CGlock g_Glock;
+
+// NS weapons
+AvHKnife gKnife;
+AvHMachineGun gMachineGun;
+AvHPistol gPistol;
+AvHSonicGun gSonicGun;
+AvHHeavyMachineGun gHeavyMachineGun;
+AvHGrenadeGun gGrenadeGun;
+AvHGrenade gGrenade;
+AvHWelder gWelder;
+AvHMine gMine;
+AvHSpitGun gSpitGun;
+AvHClaws gClaws;
+AvHSpore gSpores;
+AvHBite gBite;
+AvHBite2 gBite2;
+AvHSpikeGun gSpikeGun;
+AvHSwipe gSwipe;
+AvHWebSpinner gWebSpinner;
+AvHPrimalScream gPrimalScream;
+AvHParasiteGun gParasite;
+AvHUmbraGun gUmbra;
+AvHBlinkGun gBlink;
+AvHDivineWind gDivineWind;
+//AvHParalysisGun gParalysisGun;
+AvHBileBombGun gBileBomb;
+AvHAcidRocketGun gAcidRocket;
+AvHHealingSpray gHealingSpray;
+AvHMetabolize gMetabolize;
+AvHDevour gDevour;
+AvHStomp gStomp;
+
+// Alien abilities
+AvHLeap gLeap;
+AvHCharge gCharge;
+
+// Jetpack events
+int gJetpackEventID;
+//int gWallJumpEventID;
+//int gFlightEventID;
+int gTeleportEventID;
+int gPhaseInEventID;
+int gSiegeHitEventID;
+int gSiegeViewHitEventID;
+int gCommanderPointsAwardedEventID;
+int gBlinkEffectSuccessEventID;
+
+//bool gPlayingJetpack = false;
+//CGlock g_Glock;
+//CCrowbar g_Crowbar;
+//CPython g_Python;
+//CMP5 g_Mp5;
+//CCrossbow g_Crossbow;
+//CShotgun g_Shotgun;
+//CRpg g_Rpg;
+//CGauss g_Gauss;
+//CEgon g_Egon;
+//CHgun g_HGun;
+//CHandGrenade g_HandGren;
+//CSatchel g_Satchel;
+//CTripmine g_Tripmine;
+//CSqueak g_Snark;
+
+/*
+======================
+AlertMessage
+
+Print debug messages to console
+======================
+*/
+void AlertMessage( ALERT_TYPE atype, char *szFmt, ... )
+{
+ va_list argptr;
+ static char string[1024];
+
+ va_start (argptr, szFmt);
+#ifdef WIN32
+ //overflow protection in MS version of function...
+ _vsnprintf( string, 1023, szFmt, argptr );
+#else
+ vsprintf (string, szFmt,argptr);
+#endif
+ va_end (argptr);
+
+ gEngfuncs.Con_Printf( "cl: " );
+ gEngfuncs.Con_Printf( string );
+}
+
+// Client-side effects for jetpack
+void CheckJetpack()
+{
+ // if local player is jetpacking, play effects immediately
+// if(gIsJetpacking && !gPlayingJetpack)
+// {
+// cl_entity_t* thePlayer;
+// thePlayer = gEngfuncs.GetLocalPlayer();
+// ASSERT(thePlayer);
+//
+// // Play event locally, server will tell everyone else to play event
+// gEngfuncs.pEventAPI->EV_PlaybackEvent(0, NULL, gJetpackEventID, 0, thePlayer->origin, (float *)&g_vecZero, 0.0, 0.0, /*theWeaponIndex*/ 0, 0, 0, 0 );
+//
+// //gPlayingJetpack = true;
+// }
+ // Check to turn it off too (in case there's a network anomaly or the game resets or something, just trying to be safe)
+ //else if(!gIsJetpacking && (gPlayingJetpack))
+ //{
+ // gEngfuncs.pEventAPI->EV_PlaybackEvent(0, NULL, gEndJetpackEventID, 0, (float *)&g_vecZero, (float *)&g_vecZero, 0.0, 0.0, /*theWeaponIndex*/ 0, 0, 0, 0 );
+ //
+ // gPlayingJetpack = false;
+ //}
+}
+
+//Returns if it's multiplayer.
+//Mostly used by the client side weapons.
+bool bIsMultiplayer ( void )
+{
+ return gEngfuncs.GetMaxClients() == 1 ? 0 : 1;
+}
+//Just loads a v_ model.
+void LoadVModel ( char *szViewModel, CBasePlayer *m_pPlayer )
+{
+ gEngfuncs.CL_LoadModel( szViewModel, &m_pPlayer->pev->viewmodel );
+}
+
+/*
+=====================
+HUD_PrepEntity
+
+Links the raw entity to an entvars_s holder. If a player is passed in as the owner, then
+we set up the m_pPlayer field.
+=====================
+*/
+void HUD_PrepEntity( CBaseEntity *pEntity, CBasePlayer *pWeaponOwner )
+{
+ typedef vector IDListType;
+ static IDListType sIDList;
+
+ memset( &ev[ num_ents ], 0, sizeof( entvars_t ) );
+ pEntity->pev = &ev[ num_ents++ ];
+
+ pEntity->Precache();
+ pEntity->Spawn();
+
+ if ( pWeaponOwner )
+ {
+ ItemInfo info;
+
+ ((CBasePlayerWeapon *)pEntity)->m_pPlayer = pWeaponOwner;
+
+ ((CBasePlayerWeapon *)pEntity)->GetItemInfo( &info );
+
+ // ASSERT that a weapon with this id isn't in the list
+ int theNewID = info.iId;
+ IDListType::iterator theIter = std::find(sIDList.begin(), sIDList.end(), theNewID);
+ ASSERT(theIter == sIDList.end());
+
+ // Insert id into our list
+ sIDList.push_back(theNewID);
+
+ g_pWpns[ theNewID ] = (CBasePlayerWeapon *)pEntity;
+ }
+}
+
+/*
+=====================
+CBaseEntity :: Killed
+
+If weapons code "kills" an entity, just set its effects to EF_NODRAW
+=====================
+*/
+void CBaseEntity :: Killed( entvars_t *pevAttacker, int iGib )
+{
+ pev->effects |= EF_NODRAW;
+}
+
+/*
+=====================
+CBasePlayerWeapon :: DefaultReload
+=====================
+*/
+BOOL CBasePlayerWeapon :: DefaultReload( int iClipSize, int iAnim, float fDelay, int body )
+{
+
+ if (m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] <= 0)
+ return FALSE;
+
+ int j = min(iClipSize - m_iClip, m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]);
+
+ if (j == 0)
+ return FALSE;
+
+ m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + fDelay;
+
+ //!!UNDONE -- reload sound goes here !!!
+ //SendWeaponAnim( iAnim, UseDecrement(), body );
+
+ m_fInReload = TRUE;
+
+ m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + kDeployIdleInterval;
+ return TRUE;
+}
+
+/*
+=====================
+CBasePlayerWeapon :: CanDeploy
+=====================
+*/
+BOOL CBasePlayerWeapon :: CanDeploy( void )
+{
+ BOOL bHasAmmo = 0;
+
+ if ( !pszAmmo1() )
+ {
+ // this weapon doesn't use ammo, can always deploy.
+ return TRUE;
+ }
+
+ if ( pszAmmo1() )
+ {
+ bHasAmmo |= (m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] != 0);
+ }
+ if ( pszAmmo2() )
+ {
+ bHasAmmo |= (m_pPlayer->m_rgAmmo[m_iSecondaryAmmoType] != 0);
+ }
+ if (m_iClip > 0)
+ {
+ bHasAmmo |= 1;
+ }
+ if (!bHasAmmo)
+ {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/*
+=====================
+CBasePlayerWeapon :: DefaultDeploy
+
+=====================
+*/
+BOOL CBasePlayerWeapon :: DefaultDeploy( char *szViewModel, char *szWeaponModel, int iAnim, char *szAnimExt, int skiplocal, int body )
+{
+ if ( !CanDeploy() )
+ return FALSE;
+
+ gEngfuncs.CL_LoadModel( szViewModel, &m_pPlayer->pev->viewmodel );
+
+ SendWeaponAnim( iAnim, skiplocal, body );
+
+ m_pPlayer->m_flNextAttack = this->GetDeployTime();
+ m_flTimeWeaponIdle = this->GetDeployTime() + kDeployIdleInterval;
+ return TRUE;
+}
+
+/*
+=====================
+CBasePlayerWeapon :: PlayEmptySound
+
+=====================
+*/
+BOOL CBasePlayerWeapon :: PlayEmptySound( void )
+{
+ if (m_iPlayEmptySound)
+ {
+ HUD_PlaySound( "weapons/357_cock1.wav", 0.8 );
+ m_iPlayEmptySound = 0;
+ return 0;
+ }
+ return 0;
+}
+
+/*
+=====================
+CBasePlayerWeapon :: ResetEmptySound
+
+=====================
+*/
+void CBasePlayerWeapon :: ResetEmptySound( void )
+{
+ m_iPlayEmptySound = 1;
+}
+
+/*
+=====================
+CBasePlayerWeapon::Holster
+
+Put away weapon
+=====================
+*/
+void CBasePlayerWeapon::Holster( int skiplocal /* = 0 */ )
+{
+ m_fInReload = FALSE; // cancel any reload in progress.
+ m_pPlayer->pev->viewmodel = 0;
+}
+
+/*
+=====================
+CBasePlayerWeapon::SendWeaponAnim
+
+Animate weapon model
+=====================
+*/
+void CBasePlayerWeapon::SendWeaponAnim( int iAnim, int skiplocal, int body )
+{
+ m_pPlayer->pev->weaponanim = iAnim;
+
+ HUD_SendWeaponAnim( iAnim, body, 0 );
+}
+
+/*
+=====================
+CBaseEntity::FireBulletsPlayer
+
+Only produces random numbers to match the server ones.
+=====================
+*/
+Vector CBaseEntity::FireBulletsPlayer ( ULONG cShots, Vector vecSrc, Vector vecDirShooting, Vector vecSpread, float flDistance, int iBulletType, int iTracerFreq, int iDamage, entvars_t *pevAttacker, int shared_rand )
+{
+ //float x, y, z;
+ Vector theShotDirection;
+
+ theShotDirection.x = theShotDirection.y = theShotDirection.z = 0;
+
+// for ( ULONG iShot = 1; iShot <= cShots; iShot++ )
+// {
+// if ( pevAttacker == NULL )
+// {
+// // get circular gaussian spread
+// do {
+// x = RANDOM_FLOAT(-0.5, 0.5) + RANDOM_FLOAT(-0.5, 0.5);
+// y = RANDOM_FLOAT(-0.5, 0.5) + RANDOM_FLOAT(-0.5, 0.5);
+// z = x*x+y*y;
+// } while (z > 1);
+// }
+// else
+// {
+// //Use player's random seed.
+// // get circular gaussian spread
+// x = UTIL_SharedRandomFloat( shared_rand + iShot, -0.5, 0.5 ) + UTIL_SharedRandomFloat( shared_rand + ( 1 + iShot ) , -0.5, 0.5 );
+// y = UTIL_SharedRandomFloat( shared_rand + ( 2 + iShot ), -0.5, 0.5 ) + UTIL_SharedRandomFloat( shared_rand + ( 3 + iShot ), -0.5, 0.5 );
+// z = x * x + y * y;
+// }
+//
+// UTIL_GetRandomSpreadDir(shared_rand, iShot, vecDirShooting)
+// }
+
+// return Vector ( (float)(x * vecSpread.x), (float)(y * vecSpread.y), 0.0f );
+ return theShotDirection;
+}
+
+
+bool GetCanUseWeapon()
+{
+ // This mirrors the functionality of AvHPlayer::GetCanUseWeapon.
+ return !gHUD.GetIsInTopDownMode() && !gHUD.GetIsBeingDigested() && !gHUD.GetIsEnsnared() && !gHUD.GetIsStunned() && gEngfuncs.GetViewModel() != NULL;
+}
+
+/*
+=====================
+CBasePlayerWeapon::ItemPostFrame
+
+Handles weapon firing, reloading, etc.
+=====================
+*/
+void CBasePlayerWeapon::ItemPostFrame( void )
+{
+ // Hack initialization
+ if (this->m_flLastAnimationPlayed >= 3.0f * BALANCE_VAR(kLeapROF) + gpGlobals->time)
+ this->m_flLastAnimationPlayed = 0.0f;
+
+ if ((m_fInReload) && (m_pPlayer->m_flNextAttack <= 0.0))
+ {
+///////////////////////////////////////////////////////////////////////////////////////////////////////
+// Put code in here to predict reloads (ie, have the ammo on screen update before we get a response) //
+///////////////////////////////////////////////////////////////////////////////////////////////////////
+//#if 0 // FIXME, need ammo on client to make this work right
+// // complete the reload.
+// int j = min( iMaxClip() - m_iClip, m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]);
+//
+// // Add them to the clip
+// m_iClip += j;
+// m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] -= j;
+//#else
+// m_iClip += 10;
+//#endif
+ m_fInReload = FALSE;
+ }
+
+ // Properly propagate the end animation
+ if (this->PrevAttack2Status == true && !(m_pPlayer->pev->button & IN_ATTACK2))
+ {
+ switch (gHUD.GetCurrentWeaponID())
+ {
+ case AVH_WEAPON_SWIPE:
+ this->SendWeaponAnim(12);
+ break;
+ case AVH_WEAPON_ACIDROCKET:
+ this->SendWeaponAnim(8);
+ break;
+ case AVH_WEAPON_CLAWS:
+ this->SendWeaponAnim(9);
+ break;
+ case AVH_WEAPON_STOMP:
+ this->SendWeaponAnim(8);
+ break;
+ case AVH_WEAPON_DEVOUR:
+ this->SendWeaponAnim(11);
+ break;
+ }
+ }
+
+ if ( (m_pPlayer->pev->button & IN_ATTACK) && !(m_pPlayer->pev->button & IN_ATTACK2) && (m_flNextPrimaryAttack <= 0.0) )
+ {
+ if (GetCanUseWeapon())
+ {
+ if ( (m_iClip == 0 && pszAmmo1()) ||
+ (iMaxClip() == -1 && !m_pPlayer->m_rgAmmo[PrimaryAmmoIndex()] ) )
+ {
+ m_fFireOnEmpty = TRUE;
+ }
+
+
+ if ((gHUD.GetHUDUser3() == AVH_USER3_ALIEN_PLAYER1)
+ && (gHUD.GetCurrentWeaponID() == AVH_ABILITY_LEAP)
+ && (this->m_flLastAnimationPlayed + (float)BALANCE_VAR(kLeapROF) <= gpGlobals->time))
+ {
+ // : 0001151 predict energy too
+ AvHAlienWeapon* theWeapon = dynamic_cast(g_pWpns[AVH_ABILITY_LEAP]);
+ if ( theWeapon && theWeapon->IsUseable() ) {
+ float theVolumeScalar = 1.0f;
+ cl_entity_t *player = gEngfuncs.GetLocalPlayer();
+ int theSilenceLevel = AvHGetAlienUpgradeLevel(player->curstate.iuser4, MASK_UPGRADE_6);
+ switch(theSilenceLevel)
+ {
+ case 1:
+ theVolumeScalar = (float)BALANCE_VAR(kSilenceLevel1Volume);
+ break;
+ case 2:
+ theVolumeScalar = (float)BALANCE_VAR(kSilenceLevel2Volume);
+ break;
+ case 3:
+ theVolumeScalar = (float)BALANCE_VAR(kSilenceLevel3Volume);
+ break;
+ }
+ HUD_PlaySound( kLeapSound, theVolumeScalar);
+ AvHMUDeductAlienEnergy(m_pPlayer->pev->fuser3, theWeapon->GetEnergyForAttack() );
+ gEngfuncs.pEventAPI->EV_WeaponAnimation(3, 2);
+ this->m_flLastAnimationPlayed = gpGlobals->time;
+ }
+ }
+ //#ifdef AVH_CLIENT
+ //if((m_iClip == 0) && ?
+ //#endif
+ PrimaryAttack();
+ //return;
+ }
+ }
+ // +movement: Rewritten to allow us to use +attack2 for movement abilities
+ else if ((m_pPlayer->pev->button & IN_ATTACK2) && (gHUD.GetIsAlien()))
+ {
+ //m_flNextSecondaryAttack
+ // Find out what kind of special movement we are using, and execute the animation for it
+ if (this->PrevAttack2Status == false)
+ {
+ bool enabled=false;
+ // : 0001151 predict energy too
+ AvHAlienWeapon *theWeapon = dynamic_cast(g_pWpns[AVH_ABILITY_LEAP]);
+ if ( theWeapon )
+ enabled=theWeapon->IsUseable();
+
+ switch (gHUD.GetHUDUser3())
+ {
+ case AVH_USER3_ALIEN_PLAYER1:
+
+ if (enabled && (this->m_flLastAnimationPlayed + (float)BALANCE_VAR(kLeapROF) <= gpGlobals->time))
+ {
+ float theVolumeScalar = 1.0f;
+ cl_entity_t *player = gEngfuncs.GetLocalPlayer();
+ int theSilenceLevel = AvHGetAlienUpgradeLevel(player->curstate.iuser4, MASK_UPGRADE_6);
+ switch(theSilenceLevel)
+ {
+ case 1:
+ theVolumeScalar = (float)BALANCE_VAR(kSilenceLevel1Volume);
+ break;
+ case 2:
+ theVolumeScalar = (float)BALANCE_VAR(kSilenceLevel2Volume);
+ break;
+ case 3:
+ theVolumeScalar = (float)BALANCE_VAR(kSilenceLevel3Volume);
+ break;
+ }
+ HUD_PlaySound( kLeapSound, theVolumeScalar);
+ AvHMUDeductAlienEnergy(m_pPlayer->pev->fuser3, theWeapon->GetEnergyForAttack() );
+ this->SendWeaponAnim(3);
+ this->m_flLastAnimationPlayed = gpGlobals->time;
+ }
+ break;
+ case AVH_USER3_ALIEN_PLAYER4:
+ switch (gHUD.GetCurrentWeaponID())
+ {
+ case AVH_WEAPON_SWIPE:
+ this->SendWeaponAnim(9);
+ break;
+ case AVH_WEAPON_ACIDROCKET:
+ this->SendWeaponAnim(11);
+ break;
+ }
+ break;
+ case AVH_USER3_ALIEN_PLAYER5:
+ switch (gHUD.GetCurrentWeaponID())
+ {
+ case AVH_WEAPON_CLAWS:
+ this->SendWeaponAnim(5);
+ break;
+ case AVH_WEAPON_DEVOUR:
+ this->SendWeaponAnim(18);
+ break;
+ case AVH_WEAPON_STOMP:
+ this->SendWeaponAnim(15);
+ break;
+ }
+ break;
+ }
+ }
+
+ if ((gHUD.GetHUDUser3() == AVH_USER3_ALIEN_PLAYER1)
+ && (this->m_flLastAnimationPlayed + BALANCE_VAR(kLeapROF) < gpGlobals->time))
+ this->PrevAttack2Status = false;
+ else
+ this->PrevAttack2Status = true;
+
+ return;
+// if (GetCanUseWeapon())
+// {
+// PrimaryAttack();
+// }
+ }
+ else if ( m_pPlayer->pev->button & IN_RELOAD && iMaxClip() != WEAPON_NOCLIP && !m_fInReload )
+ {
+ if (GetCanUseWeapon())
+ {
+ // reload when reload is pressed, or if no buttons are down and weapon is empty.
+ Reload();
+ }
+ }
+ // +movement: Removed case for +attack2
+ else if ( !(m_pPlayer->pev->button & (IN_ATTACK /*|IN_ATTACK2 */) ) )
+ {
+ if (GetCanUseWeapon())
+ {
+
+ // no fire buttons down
+
+ m_fFireOnEmpty = FALSE;
+
+ // weapon is useable. Reload if empty and weapon has waited as long as it has to after firing
+ if ( m_iClip == 0 && !(iFlags() & ITEM_FLAG_NOAUTORELOAD) && m_flNextPrimaryAttack < 0.0 )
+ {
+ // << CGC >> Only reload if we have more ammo to reload with
+ if(m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] > 0)
+ {
+ Reload();
+ return;
+ }
+ }
+
+ WeaponIdle( );
+ }
+ this->PrevAttack2Status = false;
+ return;
+ }
+
+ this->PrevAttack2Status = false;
+
+ // catch all
+ if ( ShouldWeaponIdle() )
+ {
+ WeaponIdle();
+ }
+}
+
+/*
+=====================
+CBasePlayer::SelectItem
+
+ Switch weapons
+=====================
+*/
+void CBasePlayer::SelectItem(const char *pstr)
+{
+ if (!pstr)
+ return;
+
+ CBasePlayerItem *pItem = NULL;
+
+ if (!pItem)
+ return;
+
+
+ if (pItem == m_pActiveItem)
+ return;
+
+ if (m_pActiveItem)
+ m_pActiveItem->Holster( );
+
+ m_pLastItem = m_pActiveItem;
+ m_pActiveItem = pItem;
+
+ if (m_pActiveItem)
+ {
+ m_pActiveItem->Deploy( );
+ }
+}
+
+/*
+=====================
+CBasePlayer::SelectLastItem
+
+=====================
+*/
+void CBasePlayer::SelectLastItem(void)
+{
+ if (!m_pLastItem)
+ {
+ return;
+ }
+
+ if ( m_pActiveItem && !m_pActiveItem->CanHolster() )
+ {
+ return;
+ }
+
+ if (m_pActiveItem)
+ m_pActiveItem->Holster( );
+
+ CBasePlayerItem *pTemp = m_pActiveItem;
+ m_pActiveItem = m_pLastItem;
+ m_pLastItem = pTemp;
+ m_pActiveItem->Deploy( );
+}
+
+/*
+=====================
+CBasePlayer::Killed
+
+=====================
+*/
+void CBasePlayer::Killed( entvars_t *pevAttacker, int iGib )
+{
+ // Holster weapon immediately, to allow it to cleanup
+ if ( m_pActiveItem )
+ m_pActiveItem->Holster( );
+}
+
+/*
+=====================
+CBasePlayer::Spawn
+
+=====================
+*/
+void CBasePlayer::Spawn( void )
+{
+ if (m_pActiveItem)
+ m_pActiveItem->Deploy( );
+
+// this->m_flLastAnimationPlayed = gpGlobals->time;
+}
+
+/*
+=====================
+UTIL_TraceLine
+
+Don't actually trace, but act like the trace didn't hit anything.
+=====================
+*/
+void UTIL_TraceLine( const Vector &vecStart, const Vector &vecEnd, IGNORE_MONSTERS igmon, edict_t *pentIgnore, TraceResult *ptr )
+{
+ memset( ptr, 0, sizeof( *ptr ) );
+ ptr->flFraction = 1.0;
+}
+
+/*
+=====================
+UTIL_ParticleBox
+
+For debugging, draw a box around a player made out of particles
+=====================
+*/
+void UTIL_ParticleBox( CBasePlayer *player, float *mins, float *maxs, float life, unsigned char r, unsigned char g, unsigned char b )
+{
+ int i;
+ vec3_t mmin, mmax;
+
+ for ( i = 0; i < 3; i++ )
+ {
+ mmin[ i ] = player->pev->origin[ i ] + mins[ i ];
+ mmax[ i ] = player->pev->origin[ i ] + maxs[ i ];
+ }
+
+ gEngfuncs.pEfxAPI->R_ParticleBox( (float *)&mmin, (float *)&mmax, 5.0, 0, 255, 0 );
+}
+
+/*
+=====================
+UTIL_ParticleBoxes
+
+For debugging, draw boxes for other collidable players
+=====================
+*/
+void UTIL_ParticleBoxes( void )
+{
+ int idx;
+ physent_t *pe;
+ cl_entity_t *player;
+ vec3_t mins, maxs;
+
+ gEngfuncs.pEventAPI->EV_SetUpPlayerPrediction( false, true );
+
+ // Store off the old count
+ gEngfuncs.pEventAPI->EV_PushPMStates();
+
+ player = gEngfuncs.GetLocalPlayer();
+ // Now add in all of the players.
+ gEngfuncs.pEventAPI->EV_SetSolidPlayers ( player->index - 1 );
+
+ for ( idx = 1; idx < 100; idx++ )
+ {
+ pe = gEngfuncs.pEventAPI->EV_GetPhysent( idx );
+ if ( !pe )
+ break;
+
+ if ( pe->info >= 1 && pe->info <= gEngfuncs.GetMaxClients() )
+ {
+ mins = pe->origin + pe->mins;
+ maxs = pe->origin + pe->maxs;
+
+ gEngfuncs.pEfxAPI->R_ParticleBox( (float *)&mins, (float *)&maxs, 0, 0, 255, 2.0 );
+ }
+ }
+
+ gEngfuncs.pEventAPI->EV_PopPMStates();
+}
+
+/*
+=====================
+UTIL_ParticleLine
+
+For debugging, draw a line made out of particles
+=====================
+*/
+void UTIL_ParticleLine( CBasePlayer *player, float *start, float *end, float life, unsigned char r, unsigned char g, unsigned char b )
+{
+ gEngfuncs.pEfxAPI->R_ParticleLine( start, end, r, g, b, life );
+}
+
+/*
+=====================
+CBasePlayerWeapon::PrintState
+
+For debugging, print out state variables to log file
+=====================
+*/
+void CBasePlayerWeapon::PrintState( void )
+{
+ COM_Log( "c:\\hl.log", "%.4f ", gpGlobals->time );
+ COM_Log( "c:\\hl.log", "%.4f ", m_pPlayer->m_flNextAttack );
+ COM_Log( "c:\\hl.log", "%.4f ", m_flNextPrimaryAttack );
+ COM_Log( "c:\\hl.log", "%.4f ", m_flTimeWeaponIdle - gpGlobals->time);
+ COM_Log( "c:\\hl.log", "%i ", m_iClip );
+ COM_Log( "c:\\hl.log", "\r\n");
+}
+
+/*
+=====================
+HUD_InitClientWeapons
+
+Set up weapons, player and functions needed to run weapons code client-side.
+=====================
+*/
+void HUD_InitClientWeapons( void )
+{
+ static int initialized = 0;
+ if ( initialized )
+ return;
+
+ initialized = 1;
+
+ // Set up pointer ( dummy object )
+ gpGlobals = &Globals;
+
+ // Fill in current time ( probably not needed )
+ gpGlobals->time = gEngfuncs.GetClientTime();
+
+ // Fake functions
+ g_engfuncs.pfnPrecacheModel = stub_PrecacheModel;
+ g_engfuncs.pfnPrecacheSound = stub_PrecacheSound;
+ g_engfuncs.pfnPrecacheEvent = stub_PrecacheEvent;
+ g_engfuncs.pfnNameForFunction = stub_NameForFunction;
+ g_engfuncs.pfnSetModel = stub_SetModel;
+ g_engfuncs.pfnSetClientMaxspeed = HUD_SetMaxSpeed;
+
+ // Handled locally
+ g_engfuncs.pfnPlaybackEvent = HUD_PlaybackEvent;
+ g_engfuncs.pfnAlertMessage = AlertMessage;
+
+ // Pass through to engine
+ g_engfuncs.pfnPrecacheEvent = gEngfuncs.pfnPrecacheEvent;
+ g_engfuncs.pfnRandomFloat = gEngfuncs.pfnRandomFloat;
+ g_engfuncs.pfnRandomLong = gEngfuncs.pfnRandomLong;
+
+ // Allocate a slot for the local player
+ HUD_PrepEntity( &player , NULL );
+
+
+ // Allocate slot(s) for each weapon that we are going to be predicting
+ //HUD_PrepEntity( &g_Glock, &player );
+ HUD_PrepEntity( &gKnife, &player);
+ HUD_PrepEntity( &gMachineGun, &player);
+ HUD_PrepEntity( &gPistol, &player);
+ HUD_PrepEntity( &gSonicGun, &player);
+ HUD_PrepEntity( &gHeavyMachineGun, &player);
+ HUD_PrepEntity( &gGrenadeGun, &player);
+ HUD_PrepEntity( &gGrenade, &player);
+ HUD_PrepEntity( &gWelder, &player);
+ HUD_PrepEntity( &gMine, &player);
+ HUD_PrepEntity( &gSpitGun, &player);
+ HUD_PrepEntity( &gClaws, &player);
+ HUD_PrepEntity( &gSpores, &player);
+ HUD_PrepEntity( &gSpikeGun, &player);
+ HUD_PrepEntity( &gBite, &player);
+ HUD_PrepEntity( &gBite2, &player);
+ HUD_PrepEntity( &gSwipe, &player);
+ HUD_PrepEntity( &gWebSpinner, &player);
+ HUD_PrepEntity( &gPrimalScream, &player);
+ //HUD_PrepEntity( &gParalysisGun, &player);
+
+ HUD_PrepEntity( &gBlink, &player);
+ HUD_PrepEntity( &gParasite, &player);
+ HUD_PrepEntity( &gUmbra, &player);
+ HUD_PrepEntity( &gDivineWind, &player);
+ HUD_PrepEntity( &gBileBomb, &player);
+ HUD_PrepEntity( &gAcidRocket, &player);
+ HUD_PrepEntity( &gHealingSpray, &player);
+ HUD_PrepEntity( &gMetabolize, &player);
+ HUD_PrepEntity( &gStomp, &player);
+ HUD_PrepEntity( &gDevour, &player);
+
+ HUD_PrepEntity( &gLeap, &player);
+ HUD_PrepEntity( &gCharge, &player);
+
+ gJetpackEventID = PRECACHE_EVENT(1, kJetpackEvent);
+ //gWallJumpEventID = PRECACHE_EVENT(1, kWallJumpEvent);
+ //gFlightEventID = PRECACHE_EVENT(1, kFlightEvent);
+ gTeleportEventID = PRECACHE_EVENT(1, kTeleportEvent);
+ gPhaseInEventID = PRECACHE_EVENT(1, kPhaseInEvent);
+ gSiegeHitEventID = PRECACHE_EVENT(1, kSiegeHitEvent);
+ gSiegeViewHitEventID = PRECACHE_EVENT(1, kSiegeViewHitEvent);
+ gCommanderPointsAwardedEventID = PRECACHE_EVENT(1, kCommanderPointsAwardedEvent);
+ gBlinkEffectSuccessEventID = PRECACHE_EVENT(1, kBlinkEffectSuccessEventName);
+}
+
+/*
+=====================
+HUD_GetLastOrg
+
+Retruns the last position that we stored for egon beam endpoint.
+=====================
+*/
+void HUD_GetLastOrg( float *org )
+{
+ int i;
+
+ // Return last origin
+ for ( i = 0; i < 3; i++ )
+ {
+ org[i] = previousorigin[i];
+ }
+}
+
+/*
+=====================
+HUD_SetLastOrg
+
+Remember our exact predicted origin so we can draw the egon to the right position.
+=====================
+*/
+void HUD_SetLastOrg( void )
+{
+ int i;
+
+ // Offset final origin by view_offset
+ for ( i = 0; i < 3; i++ )
+ {
+ previousorigin[i] = g_finalstate->playerstate.origin[i] + g_finalstate->client.view_ofs[ i ];
+ }
+}
+
+
+CBasePlayerWeapon* HUD_GetWeaponForID(int inID)
+{
+ CBasePlayerWeapon* pWeapon = NULL;
+
+ switch(inID)
+ {
+// case WEAPON_GLOCK:
+// pWeapon = &g_Glock;
+// break;
+ case AVH_WEAPON_KNIFE:
+ pWeapon = &gKnife;
+ break;
+ case AVH_WEAPON_MG:
+ pWeapon = &gMachineGun;
+ break;
+ case AVH_WEAPON_PISTOL:
+ pWeapon = &gPistol;
+ break;
+ case AVH_WEAPON_SONIC:
+ pWeapon = &gSonicGun;
+ break;
+ case AVH_WEAPON_HMG:
+ pWeapon = &gHeavyMachineGun;
+ break;
+ case AVH_WEAPON_GRENADE_GUN:
+ pWeapon = &gGrenadeGun;
+ break;
+ case AVH_WEAPON_GRENADE:
+ pWeapon = &gGrenade;
+ break;
+ case AVH_WEAPON_WELDER:
+ pWeapon = &gWelder;
+ break;
+ case AVH_WEAPON_MINE:
+ pWeapon = &gMine;
+ break;
+ case AVH_WEAPON_SPIT:
+ pWeapon = &gSpitGun;
+ break;
+ case AVH_WEAPON_CLAWS:
+ pWeapon = &gClaws;
+ break;
+ case AVH_WEAPON_SPORES:
+ pWeapon = &gSpores;
+ break;
+ case AVH_WEAPON_SPIKE:
+ pWeapon = &gSpikeGun;
+ break;
+ case AVH_WEAPON_BITE:
+ pWeapon = &gBite;
+ break;
+ case AVH_WEAPON_BITE2:
+ pWeapon = &gBite2;
+ break;
+ case AVH_WEAPON_SWIPE:
+ pWeapon = &gSwipe;
+ break;
+ case AVH_WEAPON_WEBSPINNER:
+ pWeapon = &gWebSpinner;
+ break;
+ case AVH_WEAPON_PRIMALSCREAM:
+ pWeapon = &gPrimalScream;
+ break;
+ case AVH_WEAPON_PARASITE:
+ pWeapon = &gParasite;
+ break;
+ case AVH_WEAPON_UMBRA:
+ pWeapon = &gUmbra;
+ break;
+ case AVH_WEAPON_BLINK:
+ pWeapon = &gBlink;
+ break;
+ case AVH_WEAPON_DIVINEWIND:
+ pWeapon = &gDivineWind;
+ break;
+// case AVH_WEAPON_PARALYSIS:
+// pWeapon = &gParalysisGun;
+// break;
+ case AVH_WEAPON_BILEBOMB:
+ pWeapon = &gBileBomb;
+ break;
+ case AVH_WEAPON_ACIDROCKET:
+ pWeapon = &gAcidRocket;
+ break;
+ case AVH_WEAPON_HEALINGSPRAY:
+ pWeapon = &gHealingSpray;
+ break;
+ case AVH_WEAPON_METABOLIZE:
+ pWeapon = &gMetabolize;
+ break;
+ case AVH_WEAPON_STOMP:
+ pWeapon = &gStomp;
+ break;
+ case AVH_WEAPON_DEVOUR:
+ pWeapon = &gDevour;
+ break;
+
+ // Abilities
+ case AVH_ABILITY_LEAP:
+ pWeapon = &gLeap;
+ break;
+ case AVH_ABILITY_CHARGE:
+ pWeapon = &gCharge;
+ break;
+ }
+
+ return pWeapon;
+}
+
+
+bool HUD_GetWeaponEnabled(int inID)
+{
+ ASSERT(inID >= 0);
+ ASSERT(inID < 32);
+
+ // : 497 - use the enabled state in the associated WEAPON instead of the CBasePlayerWeapon's iuser3
+ bool theWeaponEnabled = false;
+ CBasePlayerWeapon* theWeapon = g_pWpns[inID];
+ if(theWeapon)
+ {
+ ItemInfo theItemInfo;
+ theWeapon->GetItemInfo(&theItemInfo);
+ WEAPON *pWeapon = gWR.GetWeapon( theItemInfo.iId );
+ if ( pWeapon != 0 ) {
+ theWeaponEnabled = (pWeapon->iEnabled == 1);
+ }
+ }
+
+ return theWeaponEnabled;
+}
+
+/*
+=====================
+HUD_WeaponsPostThink
+
+Run Weapon firing code on client
+=====================
+*/
+void HUD_WeaponsPostThink( local_state_s *from, local_state_s *to, usercmd_t *cmd, double time, unsigned int random_seed )
+{
+ int i;
+ int buttonsChanged;
+ CBasePlayerWeapon* pCurrent = NULL;
+ weapon_data_t nulldata, *pfrom, *pto;
+ static int lasthealth;
+
+ memset( &nulldata, 0, sizeof( nulldata ) );
+
+ HUD_InitClientWeapons();
+
+ // Get current clock
+ gpGlobals->time = time;
+
+ // Fill in data based on selected weapon
+ // FIXME, make this a method in each weapon? where you pass in an entity_state_t *?
+ // Store pointer to our destination entity_state_t so we can get our origin, etc. from it
+ CBasePlayerWeapon* pWeapon = HUD_GetWeaponForID(from->client.m_iId);
+
+ // for setting up events on the client
+ g_finalstate = to;
+
+ // If we are running events/etc. go ahead and see if we
+ // managed to die between last frame and this one
+ // If so, run the appropriate player killed or spawn function
+ if ( g_runfuncs )
+ {
+ if ( to->client.health <= 0 && lasthealth > 0 )
+ {
+ player.Killed( NULL, 0 );
+
+ }
+ else if ( to->client.health > 0 && lasthealth <= 0 )
+ {
+ player.Spawn();
+ }
+
+ lasthealth = to->client.health;
+ }
+
+ // We are not predicting the current weapon, just bow out here.
+ if ( !pWeapon )
+ return;
+
+ for ( i = 0; i < 32; i++ )
+ {
+ pCurrent = g_pWpns[ i ];
+ if ( !pCurrent )
+ {
+ continue;
+ }
+
+ pfrom = &from->weapondata[ i ];
+
+ pCurrent->m_fInReload = pfrom->m_fInReload;
+ pCurrent->m_fInSpecialReload = pfrom->m_fInSpecialReload;
+// pCurrent->m_flPumpTime = pfrom->m_flPumpTime;
+ pCurrent->m_iClip = pfrom->m_iClip;
+ pCurrent->m_flNextPrimaryAttack = pfrom->m_flNextPrimaryAttack;
+ pCurrent->m_flNextSecondaryAttack = pfrom->m_flNextSecondaryAttack;
+ pCurrent->m_flTimeWeaponIdle = pfrom->m_flTimeWeaponIdle;
+ if(pWeapon && (pWeapon->m_iId == pfrom->m_iId))
+ {
+ // Predict clip
+ gHUD.m_Ammo.SetCurrentClip(pfrom->m_iClip);
+
+ AvHBasePlayerWeapon* theWeapon = dynamic_cast(pWeapon);
+ if(theWeapon)
+ {
+ gHUD.SetCurrentWeaponData(pWeapon->m_iId, theWeapon->GetEnabledState());
+ }
+
+ //gHUD.SetClientDebugCSP(pfrom, from->client.m_flNextAttack);
+ }
+
+ // Tell HUD what energy level is needed to use weapon, so alien HUD can indicate this
+ float theEnergyLevel = 0.0f;
+ AvHMUGetEnergyCost((AvHWeaponID)(pWeapon->m_iId), theEnergyLevel);
+ gHUD.SetCurrentUseableEnergyLevel(theEnergyLevel);
+
+// New SDK stuff...needed?
+// pCurrent->pev->fuser1 = pfrom->fuser1;
+ pCurrent->m_flStartThrow = pfrom->fuser2;
+ pCurrent->m_flReleaseThrow = pfrom->fuser3;
+// pCurrent->m_chargeReady = pfrom->iuser1;
+// pCurrent->m_fInAttack = pfrom->iuser2;
+ pCurrent->pev->iuser3 = pfrom->iuser3;
+
+// pCurrent->m_iSecondaryAmmoType = (int)from->client.vuser3[2];
+ pCurrent->m_iPrimaryAmmoType = (int)from->client.vuser4[0];
+// player.m_rgAmmo[ pCurrent->m_iPrimaryAmmoType ] = (int)from->client.vuser4[1];
+// player.m_rgAmmo[ pCurrent->m_iSecondaryAmmoType ] = (int)from->client.vuser4[2];
+ }
+
+ // For random weapon events, use this seed to seed random # generator
+ player.random_seed = random_seed;
+
+ // Get old buttons from previous state.
+ player.m_afButtonLast = from->playerstate.oldbuttons;
+
+ // Which buttsons chave changed
+ buttonsChanged = (player.m_afButtonLast ^ cmd->buttons); // These buttons have changed this frame
+
+ // Debounced button codes for pressed/released
+ // The changed ones still down are "pressed"
+ player.m_afButtonPressed = buttonsChanged & cmd->buttons;
+ // The ones not down are "released"
+ player.m_afButtonReleased = buttonsChanged & (~cmd->buttons);
+
+ // Set player variables that weapons code might check/alter
+ player.pev->button = cmd->buttons;
+
+ player.pev->velocity = from->client.velocity;
+ player.pev->flags = from->client.flags;
+
+ player.pev->deadflag = from->client.deadflag;
+ player.pev->waterlevel = from->client.waterlevel;
+ player.pev->maxspeed = from->client.maxspeed;
+ player.pev->fov = from->client.fov;
+ player.pev->weaponanim = from->client.weaponanim;
+ player.pev->viewmodel = from->client.viewmodel;
+ player.m_flNextAttack = from->client.m_flNextAttack;
+ //player.m_flNextAmmoBurn = from->client.fuser2;
+ //player.m_flAmmoStartCharge = from->client.fuser3;
+
+ // Removed this because NS uses vuser1 and vuser2 (and the HL weapons aren't used)
+ ////Stores all our ammo info, so the client side weapons can use them.
+ //player.ammo_9mm = (int)from->client.vuser1[0];
+ //player.ammo_357 = (int)from->client.vuser1[1];
+ //player.ammo_argrens = (int)from->client.vuser1[2];
+ //player.ammo_bolts = (int)from->client.ammo_nails; //is an int anyways...
+ //player.ammo_buckshot = (int)from->client.ammo_shells;
+ //player.ammo_uranium = (int)from->client.ammo_cells;
+ //player.ammo_hornets = (int)from->client.vuser2[0];
+ //player.ammo_rockets = (int)from->client.ammo_rockets;
+
+
+ // Point to current weapon object
+ if ( from->client.m_iId )
+ {
+ player.m_pActiveItem = g_pWpns[ from->client.m_iId ];
+ }
+
+ if ( player.m_pActiveItem->m_iId == WEAPON_RPG )
+ {
+ ( ( CRpg * )player.m_pActiveItem)->m_fSpotActive = (int)from->client.vuser2[ 1 ];
+ ( ( CRpg * )player.m_pActiveItem)->m_cActiveRockets = (int)from->client.vuser2[ 2 ];
+ }
+
+ // Don't go firing anything if we have died.
+ // Or if we don't have a weapon model deployed
+ if ( ( player.pev->deadflag != ( DEAD_DISCARDBODY + 1 ) ) && !CL_IsDead() && player.pev->viewmodel && !g_iUser1 )
+ {
+
+ if ( player.m_flNextAttack <= 0 )
+ {
+ pWeapon->ItemPostFrame();
+ }
+// if ( g_runfuncs )
+// {
+// pWeapon->PrintState();
+// }
+ }
+
+ // Assume that we are not going to switch weapons
+ to->client.m_iId = from->client.m_iId;
+
+ // Now see if we issued a changeweapon command ( and we're not dead )
+ if ( cmd->weaponselect && ( player.pev->deadflag != ( DEAD_DISCARDBODY + 1 ) ) )
+ {
+ // Switched to a different weapon?
+ if ( from->weapondata[ cmd->weaponselect ].m_iId == cmd->weaponselect )
+ {
+ ASSERT(cmd->weaponselect >= 0);
+ ASSERT(cmd->weaponselect < 32);
+
+ CBasePlayerWeapon *pNew = g_pWpns[ cmd->weaponselect ];
+ if ( pNew && ( pNew != pWeapon ) && player.m_pActiveItem && player.m_pActiveItem->CanHolster())
+ {
+ // Put away old weapon
+ if (player.m_pActiveItem)
+ player.m_pActiveItem->Holster( );
+
+ player.m_pLastItem = player.m_pActiveItem;
+ player.m_pActiveItem = pNew;
+
+ // Deploy new weapon
+ if (player.m_pActiveItem)
+ {
+ player.m_pActiveItem->Deploy( );
+ }
+
+ // Update weapon id so we can predict things correctly.
+ to->client.m_iId = cmd->weaponselect;
+ }
+ }
+ }
+
+ // Copy in results of prediction code
+ to->client.viewmodel = player.pev->viewmodel;
+ to->client.fov = player.pev->fov;
+ to->client.weaponanim = player.pev->weaponanim;
+ to->client.m_flNextAttack = player.m_flNextAttack;
+ //to->client.fuser2 = player.m_flNextAmmoBurn;
+ //to->client.fuser3 = player.m_flAmmoStartCharge;
+ to->client.maxspeed = player.pev->maxspeed;
+
+// Removed this because NS uses vuser1 and vuser2 (and the HL weapons aren't used)
+// //HL Weapons
+// to->client.vuser1[0] = player.ammo_9mm;
+// to->client.vuser1[1] = player.ammo_357;
+// to->client.vuser1[2] = player.ammo_argrens;
+//
+// to->client.ammo_nails = player.ammo_bolts;
+// to->client.ammo_shells = player.ammo_buckshot;
+// to->client.ammo_cells = player.ammo_uranium;
+// to->client.vuser2[0] = player.ammo_hornets;
+// to->client.ammo_rockets = player.ammo_rockets;
+
+ if ( player.m_pActiveItem->m_iId == WEAPON_RPG )
+ {
+ from->client.vuser2[ 1 ] = ( ( CRpg * )player.m_pActiveItem)->m_fSpotActive;
+ from->client.vuser2[ 2 ] = ( ( CRpg * )player.m_pActiveItem)->m_cActiveRockets;
+ }
+
+ // Make sure that weapon animation matches what the game .dll is telling us
+ // over the wire ( fixes some animation glitches )
+ // Ensure that the fade and onos won't get these, to play the blink and charge animations correctly
+ bool noRun = (to->client.iuser3 == AVH_USER3_ALIEN_PLAYER4) || (to->client.iuser3 == AVH_USER3_ALIEN_PLAYER5);
+ if (g_runfuncs && ( HUD_GetWeaponAnim() != to->client.weaponanim ) && !(CheckInAttack2()) && !noRun)
+ {
+ int body = 2;
+
+ //Pop the model to body 0.
+ //if ( pWeapon == &g_Tripmine )
+ // body = 0;
+
+ // Force a fixed anim down to viewmodel
+ HUD_SendWeaponAnim( to->client.weaponanim, body, 1 );
+ }
+
+ for ( i = 0; i < 32; i++ )
+ {
+ pCurrent = g_pWpns[ i ];
+
+ pto = &to->weapondata[ i ];
+
+ if ( !pCurrent )
+ {
+ memset( pto, 0, sizeof( weapon_data_t ) );
+ continue;
+ }
+
+ pto->m_fInReload = pCurrent->m_fInReload;
+ pto->m_fInSpecialReload = pCurrent->m_fInSpecialReload;
+// pto->m_flPumpTime = pCurrent->m_flPumpTime;
+ pto->m_iClip = pCurrent->m_iClip;
+ pto->m_flNextPrimaryAttack = pCurrent->m_flNextPrimaryAttack;
+ pto->m_flNextSecondaryAttack = pCurrent->m_flNextSecondaryAttack;
+ pto->m_flTimeWeaponIdle = pCurrent->m_flTimeWeaponIdle;
+// pto->fuser1 = pCurrent->pev->fuser1;
+// pto->fuser2 = pCurrent->m_flStartThrow;
+// pto->fuser3 = pCurrent->m_flReleaseThrow;
+// pto->iuser1 = pCurrent->m_chargeReady;
+// pto->iuser2 = pCurrent->m_fInAttack;
+ pto->iuser3 = pCurrent->pev->iuser3;
+
+ // Decrement weapon counters, server does this at same time ( during post think, after doing everything else )
+ pto->m_flNextReload -= cmd->msec / 1000.0;
+ pto->m_fNextAimBonus -= cmd->msec / 1000.0;
+ pto->m_flNextPrimaryAttack -= cmd->msec / 1000.0;
+ pto->m_flNextSecondaryAttack -= cmd->msec / 1000.0;
+ pto->m_flTimeWeaponIdle -= cmd->msec / 1000.0;
+ pto->fuser1 -= cmd->msec / 1000.0;
+
+ to->client.vuser3[2] = pCurrent->m_iSecondaryAmmoType;
+ to->client.vuser4 = pCurrent->pev->vuser4;
+// to->client.vuser4[0] = pCurrent->m_iPrimaryAmmoType;
+// to->client.vuser4[1] = player.m_rgAmmo[ pCurrent->m_iPrimaryAmmoType ];
+// to->client.vuser4[2] = player.m_rgAmmo[ pCurrent->m_iSecondaryAmmoType ];
+
+/* if ( pto->m_flPumpTime != -9999 )
+ {
+ pto->m_flPumpTime -= cmd->msec / 1000.0;
+ if ( pto->m_flPumpTime < -0.001 )
+ pto->m_flPumpTime = -0.001;
+ }*/
+
+ if ( pto->m_fNextAimBonus < -1.0 )
+ {
+ pto->m_fNextAimBonus = -1.0;
+ }
+
+ if ( pto->m_flNextPrimaryAttack < -1.0 )
+ {
+ pto->m_flNextPrimaryAttack = -1.0;
+ }
+
+ if ( pto->m_flNextSecondaryAttack < -0.001 )
+ {
+ pto->m_flNextSecondaryAttack = -0.001;
+ }
+
+ if ( pto->m_flTimeWeaponIdle < -0.001 )
+ {
+ pto->m_flTimeWeaponIdle = -0.001;
+ }
+
+ if ( pto->m_flNextReload < -0.001 )
+ {
+ pto->m_flNextReload = -0.001;
+ }
+
+ if ( pto->fuser1 < -0.001 )
+ {
+ pto->fuser1 = -0.001;
+ }
+ }
+
+ // m_flNextAttack is now part of the weapons, but is part of the player instead
+ to->client.m_flNextAttack -= cmd->msec / 1000.0;
+ if ( to->client.m_flNextAttack < -0.001 )
+ {
+ to->client.m_flNextAttack = -0.001;
+ }
+
+ to->client.fuser2 -= cmd->msec / 1000.0;
+ if ( to->client.fuser2 < -0.001 )
+ {
+ to->client.fuser2 = -0.001;
+ }
+
+ to->client.fuser3 -= cmd->msec / 1000.0;
+ if ( to->client.fuser3 < -0.001 )
+ {
+ to->client.fuser3 = -0.001;
+ }
+
+ // Store off the last position from the predicted state.
+ HUD_SetLastOrg();
+
+ // Wipe it so we can't use it after this frame
+ g_finalstate = NULL;
+}
+
+
+/*
+=====================
+HUD_PostRunCmd
+
+Client calls this during prediction, after it has moved the player and updated any info changed into to->
+time is the current client clock based on prediction
+cmd is the command that caused the movement, etc
+runfuncs is 1 if this is the first time we've predicted this command. If so, sounds and effects should play, otherwise, they should
+be ignored
+=====================
+*/
+void CL_DLLEXPORT HUD_PostRunCmd( struct local_state_s *from, struct local_state_s *to, struct usercmd_s *cmd, int runfuncs, double time, unsigned int random_seed )
+{
+// RecClPostRunCmd(from, to, cmd, runfuncs, time, random_seed);
+
+ g_runfuncs = runfuncs;
+
+ if ( cl_lw && cl_lw->value )
+ {
+ HUD_WeaponsPostThink( from, to, cmd, time, random_seed );
+ }
+ else
+ {
+ to->client.fov = g_lastFOV;
+ }
+
+ // Check to see whether too play local jetpack effects
+ if(runfuncs)
+ {
+ static int sLastTime = 0;
+ float theTimePassed = time - sLastTime;
+
+ //CheckJetpack();
+
+ //UpdateJetpackLights();
+
+ sLastTime = time;
+ }
+
+ // All games can use FOV state
+ g_lastFOV = to->client.fov;
+}
+
+
+
diff --git a/main/source/cl_dll/hud.cpp b/main/source/cl_dll/hud.cpp
index 39e527e8..8a71d72f 100644
--- a/main/source/cl_dll/hud.cpp
+++ b/main/source/cl_dll/hud.cpp
@@ -1,588 +1,588 @@
-/***
-*
-* Copyright (c) 1999, Valve LLC. All rights reserved.
-*
-* This product contains software technology licensed from Id
-* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
-* All Rights Reserved.
-*
-* Use, distribution, and modification of this source code and/or resulting
-* object code is restricted to non-commercial enhancements to products from
-* Valve LLC. All other use, distribution, or modification is prohibited
-* without written permission from Valve LLC.
-*
-****/
-//
-// hud.cpp
-//
-// implementation of CHud class
-//
-
-#include "hud.h"
-#include "cl_util.h"
-#include
-#include
-#include "hud_servers.h"
-#include "vgui_TeamFortressViewport.h"
-#include "vgui_int.h"
-
-#include "demo.h"
-#include "common/demo_api.h"
-#include "ui/UIComponent.h"
-#include "vgui_ScorePanel.h"
-
-#include "mod/AvHNetworkMessages.h"
-#include "ui/ChatPanel.h"
-#include "mod/AvHClientVariables.h"
-// : duck toggle
-bool g_bDuckToggled;
-// :
-
-class CHLVoiceStatusHelper : public IVoiceStatusHelper
-{
-public:
- virtual void GetPlayerTextColor(int entindex, int color[3])
- {
- color[0] = color[1] = color[2] = 255;
-
- if( entindex >= 0 && entindex < sizeof(g_PlayerExtraInfo)/sizeof(g_PlayerExtraInfo[0]) )
- {
- int iTeam = g_PlayerExtraInfo[entindex].teamnumber;
-
- if ( iTeam < 0 )
- {
- iTeam = 0;
- }
-
- iTeam = iTeam % iNumberOfTeamColors;
-
- color[0] = kTeamColors[iTeam][0];
- color[1] = kTeamColors[iTeam][1];
- color[2] = kTeamColors[iTeam][2];
-
- // Draw commander voice differently
- short thePlayerClass = g_PlayerExtraInfo[entindex].playerclass;
- switch(thePlayerClass)
- {
- case PLAYERCLASS_COMMANDER:
- color[0] = color[1] = color[2] = 255;
- break;
- }
- }
- }
-
- virtual void UpdateCursorState()
- {
- gViewPort->UpdateCursorState();
- }
-
- virtual int GetAckIconHeight()
- {
- return ScreenHeight() - gHUD.m_iFontHeight*3 - 6;
- }
-
- virtual bool CanShowSpeakerLabels()
- {
- if( gViewPort && gViewPort->m_pScoreBoard )
- return !gViewPort->m_pScoreBoard->isVisible();
- else
- return false;
- }
-};
-static CHLVoiceStatusHelper g_VoiceStatusHelper;
-
-
-extern client_sprite_t *GetSpriteList(client_sprite_t *pList, const char *psz, int iRes, int iCount);
-//CImageLabel* gTestLabel = NULL;
-//extern Label* gTestLabel;
-
-extern cvar_t *sensitivity;
-cvar_t *cl_lw = NULL;
-
-void ShutdownInput (void);
-
-int __MsgFunc_ResetHUD(const char *pszName, int iSize, void *pbuf)
-{
- return gHUD.MsgFunc_ResetHUD(pszName, iSize, pbuf );
-}
-
-int __MsgFunc_InitHUD(const char *pszName, int iSize, void *pbuf)
-{
- gHUD.MsgFunc_InitHUD( pszName, iSize, pbuf );
- return 0;
-}
-
-int __MsgFunc_ViewMode(const char *pszName, int iSize, void *pbuf)
-{
- gHUD.MsgFunc_ViewMode( pszName, iSize, pbuf );
- return 1;
-}
-
-int __MsgFunc_SetFOV(const char *pszName, int iSize, void *pbuf)
-{
- return gHUD.MsgFunc_SetFOV( pszName, iSize, pbuf );
-}
-
-int __MsgFunc_TeamNames(const char *pszName, int iSize, void *pbuf)
-{
- if (gViewPort)
- return gViewPort->MsgFunc_TeamNames( pszName, iSize, pbuf );
- return 0;
-}
-
-int __MsgFunc_MOTD(const char *pszName, int iSize, void *pbuf)
-{
- if (gViewPort)
- return gViewPort->MsgFunc_MOTD( pszName, iSize, pbuf );
- return 0;
-}
-
-int __MsgFunc_ServerName(const char *pszName, int iSize, void *pbuf)
-{
- if (gViewPort)
- return gViewPort->MsgFunc_ServerName( pszName, iSize, pbuf );
- return 0;
-}
-
-int __MsgFunc_ScoreInfo(const char *pszName, int iSize, void *pbuf)
-{
- if (gViewPort)
- return gViewPort->MsgFunc_ScoreInfo( pszName, iSize, pbuf );
- return 0;
-}
-
-int __MsgFunc_TeamScore(const char *pszName, int iSize, void *pbuf)
-{
- if (gViewPort)
- return gViewPort->MsgFunc_TeamScore( pszName, iSize, pbuf );
- return 0;
-}
-
-int __MsgFunc_TeamInfo(const char *pszName, int iSize, void *pbuf)
-{
- if (gViewPort)
- return gViewPort->MsgFunc_TeamInfo( pszName, iSize, pbuf );
- return 0;
-}
-
-void __CmdFunc_SpecialDummy(void) {}
-
-void __CmdFunc_ClRateDummy(void) { }
-
-// This is called every time the DLL is loaded
-void CHud :: Init( void )
-{
- HOOK_MESSAGE( ResetHUD );
- HOOK_MESSAGE( InitHUD );
- HOOK_MESSAGE( ViewMode );
- HOOK_MESSAGE( SetFOV );
-
- HOOK_COMMAND( "special", SpecialDummy);
- HOOK_COMMAND( "_special", SpecialDummy); //prevent abuse
-
- HOOK_COMMAND( "cl_rate", ClRateDummy);
-
- HOOK_MESSAGE( TeamNames );
- HOOK_MESSAGE( MOTD );
- HOOK_MESSAGE( ServerName );
- HOOK_MESSAGE( ScoreInfo );
- HOOK_MESSAGE( TeamScore );
- HOOK_MESSAGE( TeamInfo );
-
- CVAR_CREATE( "hud_classautokill", "1", FCVAR_ARCHIVE | FCVAR_USERINFO ); // controls whether or not to suicide immediately on TF class switch
- CVAR_CREATE( "hud_takesshots", "0", FCVAR_ARCHIVE ); // controls whether or not to automatically take screenshots at the end of a round
-
-#ifdef DEBUG
- CVAR_CREATE( "hud_hideview", "0", FCVAR_ARCHIVE );
-#endif
-
- m_iLogo = 0;
- m_iFOV = 0;
-
- // : duck toggle
- g_bDuckToggled = false;
- // :
-
- CVAR_CREATE( "zoom_sensitivity_ratio", "1.2", 0 );
- default_fov = CVAR_CREATE( "default_fov", "90", 0 );
- m_pCvarStealMouse = CVAR_CREATE( "hud_capturemouse", "1", FCVAR_ARCHIVE );
- m_pCvarDraw = CVAR_CREATE( "hud_draw", "1", FCVAR_ARCHIVE );
- cl_lw = gEngfuncs.pfnGetCvarPointer( "cl_lw" );
-
- CVAR_CREATE( "cl_showspeed", "0", 0);
- CVAR_CREATE( kvLabelMaps, "1", FCVAR_ARCHIVE);
- CVAR_CREATE( kvGammaRamp, "1", FCVAR_ARCHIVE);
- CVAR_CREATE( kvCustomCrosshair, "1", FCVAR_ARCHIVE);
- CVAR_CREATE( kvHudMapZoom, "3", FCVAR_ARCHIVE);
- CVAR_CREATE( kvLabelHivesight, "1", FCVAR_ARCHIVE);
- CVAR_CREATE( "cl_iconr", "0", FCVAR_ARCHIVE);
- CVAR_CREATE( "cl_icong", "149", FCVAR_ARCHIVE);
- CVAR_CREATE( "cl_iconb", "221", FCVAR_ARCHIVE);
-
- m_pSpriteList = NULL;
-
- // Clear any old HUD list
- if ( m_pHudList )
- {
- HUDLIST *pList;
- while ( m_pHudList )
- {
- pList = m_pHudList;
- m_pHudList = m_pHudList->pNext;
- free( pList );
- }
- m_pHudList = NULL;
- }
-
- // In case we get messages before the first update -- time will be valid
- m_flTime = 1.0;
-
- m_Ammo.Init();
- m_Health.Init();
- m_Spectator.Init();
- m_SayText.Init();
- m_Geiger.Init();
- m_Train.Init();
- m_Battery.Init();
- m_Flash.Init();
- m_Message.Init();
- m_StatusBar.Init();
- m_DeathNotice.Init();
- m_AmmoSecondary.Init();
- m_TextMessage.Init();
- m_StatusIcons.Init();
-
- m_Spectator.m_chatEnabled = (m_SayText.m_HUD_saytext->value!=0);
-
- GetClientVoiceMgr()->Init(&g_VoiceStatusHelper, (vgui::Panel**)&gViewPort);
-
- m_Menu.Init();
-
- ServersInit();
-
- MsgFunc_ResetHUD(0, 0, NULL );
-}
-
-// CHud destructor
-// cleans up memory allocated for m_rg* arrays
-CHud :: ~CHud()
-{
- delete [] m_rghSprites;
- delete [] m_rgrcRects;
- delete [] m_rgszSpriteNames;
-
- if ( m_pHudList )
- {
- HUDLIST *pList;
- while ( m_pHudList )
- {
- pList = m_pHudList;
- m_pHudList = m_pHudList->pNext;
- free( pList );
- }
- m_pHudList = NULL;
- }
-
- ServersShutdown();
-}
-
-// GetSpriteIndex()
-// searches through the sprite list loaded from hud.txt for a name matching SpriteName
-// returns an index into the gHUD.m_rghSprites[] array
-// returns 0 if sprite not found
-int CHud :: GetSpriteIndex( const char *SpriteName )
-{
- // look through the loaded sprite name list for SpriteName
- for ( int i = 0; i < m_iSpriteCount; i++ )
- {
- if ( strncmp( SpriteName, m_rgszSpriteNames + (i * MAX_SPRITE_NAME_LENGTH), MAX_SPRITE_NAME_LENGTH ) == 0 )
- return i;
- }
-
- return -1; // invalid sprite
-}
-
-void CHud :: VidInit( void )
-{
- m_scrinfo.iSize = sizeof(m_scrinfo);
- GetScreenInfo(&m_scrinfo);
-
- // The NS viewport isn't set up yet
- int theViewPort[4];
- theViewPort[0] = theViewPort[1] = 0;
- theViewPort[2] = this->m_scrinfo.iWidth;
- theViewPort[3] = this->m_scrinfo.iHeight;
-
- gHUD.SetViewport(theViewPort);
-
- mFont.Load("sprites/font_arial");
- mSmallFont.Load("sprites/font_arialsmall");
-
- // ----------
- // Load Sprites
- // ---------
-// m_hsprFont = LoadSprite("sprites/%d_font.spr");
-
- m_hsprLogo = 0;
- m_hsprCursor = 0;
-
- if (ScreenWidth() < 640)
- m_iRes = 320;
- else
- m_iRes = 640;
-
- // Only load this once
- if ( !m_pSpriteList )
- {
- // we need to load the hud.txt, and all sprites within
- m_pSpriteList = SPR_GetList("sprites/hud.txt", &m_iSpriteCountAllRes);
-
- if (m_pSpriteList)
- {
- // count the number of sprites of the appropriate res
- m_iSpriteCount = 0;
- client_sprite_t *p = m_pSpriteList;
- int j;
- for ( j = 0; j < m_iSpriteCountAllRes; j++ )
- {
- if ( p->iRes == m_iRes )
- m_iSpriteCount++;
- p++;
- }
-
- // allocated memory for sprite handle arrays
- m_rghSprites = new HSPRITE[m_iSpriteCount];
- m_rgrcRects = new wrect_t[m_iSpriteCount];
- m_rgszSpriteNames = new char[m_iSpriteCount * MAX_SPRITE_NAME_LENGTH];
-
- p = m_pSpriteList;
- int index = 0;
- for ( j = 0; j < m_iSpriteCountAllRes; j++ )
- {
- if ( p->iRes == m_iRes )
- {
- char sz[256];
- sprintf(sz, "sprites/%s.spr", p->szSprite);
- m_rghSprites[index] = SPR_Load(sz);
- m_rgrcRects[index] = p->rc;
- strncpy( &m_rgszSpriteNames[index * MAX_SPRITE_NAME_LENGTH], p->szName, MAX_SPRITE_NAME_LENGTH );
-
- index++;
- }
-
- p++;
- }
- }
- }
- else
- {
- // we have already have loaded the sprite reference from hud.txt, but
- // we need to make sure all the sprites have been loaded (we've gone through a transition, or loaded a save game)
- client_sprite_t *p = m_pSpriteList;
- int index = 0;
- for ( int j = 0; j < m_iSpriteCountAllRes; j++ )
- {
- if ( p->iRes == m_iRes )
- {
- char sz[256];
- sprintf( sz, "sprites/%s.spr", p->szSprite );
- m_rghSprites[index] = SPR_Load(sz);
- index++;
- }
-
- p++;
- }
- }
-
- // assumption: number_1, number_2, etc, are all listed and loaded sequentially
- m_HUD_number_0 = GetSpriteIndex( "number_0" );
-
- m_iFontHeight = m_rgrcRects[m_HUD_number_0].bottom - m_rgrcRects[m_HUD_number_0].top;
-
- m_Ammo.VidInit();
- m_Health.VidInit();
- m_Spectator.VidInit();
- m_Geiger.VidInit();
- m_Train.VidInit();
- m_Battery.VidInit();
- m_Flash.VidInit();
- m_Message.VidInit();
- m_StatusBar.VidInit();
- m_DeathNotice.VidInit();
- m_SayText.VidInit();
- m_Menu.VidInit();
- m_AmmoSecondary.VidInit();
- m_TextMessage.VidInit();
- m_StatusIcons.VidInit();
- GetClientVoiceMgr()->VidInit();
-}
-
-float g_lastFOV = 0.0;
-
-/*
-============
-COM_FileBase
-============
-*/
-// Extracts the base name of a file (no path, no extension, assumes '/' as path separator)
-void COM_FileBase ( const char *in, char *out)
-{
- int len, start, end;
-
- len = (int)strlen( in );
-
- // scan backward for '.'
- end = len - 1;
- while ( end && in[end] != '.' && in[end] != '/' && in[end] != '\\' )
- end--;
-
- if ( in[end] != '.' ) // no '.', copy to end
- end = len-1;
- else
- end--; // Found ',', copy to left of '.'
-
-
- // Scan backward for '/'
- start = len-1;
- while ( start >= 0 && in[start] != '/' && in[start] != '\\' )
- start--;
-
- if ( in[start] != '/' && in[start] != '\\' )
- start = 0;
- else
- start++;
-
- // Length of new sting
- len = end - start + 1;
-
- // Copy partial string
- strncpy( out, &in[start], len );
- // Terminate it
- out[len] = 0;
-}
-
-/*
-=================
-HUD_IsGame
-
-=================
-*/
-int HUD_IsGame( const char *game )
-{
- const char *gamedir;
- char gd[ 1024 ];
-
- gamedir = gEngfuncs.pfnGetGameDirectory();
- if ( gamedir && gamedir[0] )
- {
- COM_FileBase( gamedir, gd );
- if ( !stricmp( gd, game ) )
- return 1;
- }
- return 0;
-}
-
-/*
-=====================
-HUD_GetFOV
-
-Returns last FOV
-=====================
-*/
-float HUD_GetFOV( void )
-{
- if ( gEngfuncs.pDemoAPI->IsRecording() )
- {
- // Write it
- int i = 0;
- unsigned char buf[ 100 ];
-
- // Active
- *( float * )&buf[ i ] = g_lastFOV;
- i += sizeof( float );
-
- Demo_WriteBuffer( TYPE_ZOOM, i, buf );
- }
-
- if ( gEngfuncs.pDemoAPI->IsPlayingback() )
- {
- g_lastFOV = g_demozoom;
- }
- return g_lastFOV;
-}
-
-int CHud::MsgFunc_SetFOV(const char *pszName, int iSize, void *pbuf)
-{
- int newfov;
- NetMsg_SetFOV( pbuf, iSize, newfov );
- int def_fov = CVAR_GET_FLOAT( "default_fov" );
-
- //Weapon prediction already takes care of changing the fog. ( g_lastFOV ).
- if ( cl_lw && cl_lw->value )
- return 1;
-
- g_lastFOV = newfov;
-
- if ( newfov == 0 )
- {
- m_iFOV = def_fov;
- }
- else
- {
- m_iFOV = newfov;
- }
-
- // the clients fov is actually set in the client data update section of the hud
-
- // Set a new sensitivity
- if ( m_iFOV == def_fov )
- {
- // reset to saved sensitivity
- m_flMouseSensitivity = 0;
- }
- else
- {
- // set a new sensitivity that is proportional to the change from the FOV default
- m_flMouseSensitivity = sensitivity->value * ((float)newfov / (float)def_fov) * CVAR_GET_FLOAT("zoom_sensitivity_ratio");
- }
-
- return 1;
-}
-
-
-void CHud::AddHudElem(CHudBase *phudelem)
-{
- HUDLIST *pdl, *ptemp;
-
-//phudelem->Think();
-
- if (!phudelem)
- return;
-
- pdl = (HUDLIST *)malloc(sizeof(HUDLIST));
- if (!pdl)
- return;
-
- memset(pdl, 0, sizeof(HUDLIST));
- pdl->p = phudelem;
-
- if (!m_pHudList)
- {
- m_pHudList = pdl;
- return;
- }
-
- ptemp = m_pHudList;
-
- while (ptemp->pNext)
- ptemp = ptemp->pNext;
-
- ptemp->pNext = pdl;
-}
-
-float CHud::GetSensitivity( void )
-{
- return m_flMouseSensitivity;
-}
-
-
+/***
+*
+* Copyright (c) 1999, Valve LLC. All rights reserved.
+*
+* This product contains software technology licensed from Id
+* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
+* All Rights Reserved.
+*
+* Use, distribution, and modification of this source code and/or resulting
+* object code is restricted to non-commercial enhancements to products from
+* Valve LLC. All other use, distribution, or modification is prohibited
+* without written permission from Valve LLC.
+*
+****/
+//
+// hud.cpp
+//
+// implementation of CHud class
+//
+
+#include "hud.h"
+#include "cl_util.h"
+#include
+#include
+#include "hud_servers.h"
+#include "vgui_TeamFortressViewport.h"
+#include "vgui_int.h"
+
+#include "demo.h"
+#include "common/demo_api.h"
+#include "ui/UIComponent.h"
+#include "vgui_ScorePanel.h"
+
+#include "mod/AvHNetworkMessages.h"
+#include "ui/ChatPanel.h"
+#include "mod/AvHClientVariables.h"
+// : duck toggle
+bool g_bDuckToggled;
+// :
+
+class CHLVoiceStatusHelper : public IVoiceStatusHelper
+{
+public:
+ virtual void GetPlayerTextColor(int entindex, int color[3])
+ {
+ color[0] = color[1] = color[2] = 255;
+
+ if( entindex >= 0 && entindex < sizeof(g_PlayerExtraInfo)/sizeof(g_PlayerExtraInfo[0]) )
+ {
+ int iTeam = g_PlayerExtraInfo[entindex].teamnumber;
+
+ if ( iTeam < 0 )
+ {
+ iTeam = 0;
+ }
+
+ iTeam = iTeam % iNumberOfTeamColors;
+
+ color[0] = kTeamColors[iTeam][0];
+ color[1] = kTeamColors[iTeam][1];
+ color[2] = kTeamColors[iTeam][2];
+
+ // Draw commander voice differently
+ short thePlayerClass = g_PlayerExtraInfo[entindex].playerclass;
+ switch(thePlayerClass)
+ {
+ case PLAYERCLASS_COMMANDER:
+ color[0] = color[1] = color[2] = 255;
+ break;
+ }
+ }
+ }
+
+ virtual void UpdateCursorState()
+ {
+ gViewPort->UpdateCursorState();
+ }
+
+ virtual int GetAckIconHeight()
+ {
+ return ScreenHeight() - gHUD.m_iFontHeight*3 - 6;
+ }
+
+ virtual bool CanShowSpeakerLabels()
+ {
+ if( gViewPort && gViewPort->m_pScoreBoard )
+ return !gViewPort->m_pScoreBoard->isVisible();
+ else
+ return false;
+ }
+};
+static CHLVoiceStatusHelper g_VoiceStatusHelper;
+
+
+extern client_sprite_t *GetSpriteList(client_sprite_t *pList, const char *psz, int iRes, int iCount);
+//CImageLabel* gTestLabel = NULL;
+//extern Label* gTestLabel;
+
+extern cvar_t *sensitivity;
+cvar_t *cl_lw = NULL;
+
+void ShutdownInput (void);
+
+int __MsgFunc_ResetHUD(const char *pszName, int iSize, void *pbuf)
+{
+ return gHUD.MsgFunc_ResetHUD(pszName, iSize, pbuf );
+}
+
+int __MsgFunc_InitHUD(const char *pszName, int iSize, void *pbuf)
+{
+ gHUD.MsgFunc_InitHUD( pszName, iSize, pbuf );
+ return 0;
+}
+
+int __MsgFunc_ViewMode(const char *pszName, int iSize, void *pbuf)
+{
+ gHUD.MsgFunc_ViewMode( pszName, iSize, pbuf );
+ return 1;
+}
+
+int __MsgFunc_SetFOV(const char *pszName, int iSize, void *pbuf)
+{
+ return gHUD.MsgFunc_SetFOV( pszName, iSize, pbuf );
+}
+
+int __MsgFunc_TeamNames(const char *pszName, int iSize, void *pbuf)
+{
+ if (gViewPort)
+ return gViewPort->MsgFunc_TeamNames( pszName, iSize, pbuf );
+ return 0;
+}
+
+int __MsgFunc_MOTD(const char *pszName, int iSize, void *pbuf)
+{
+ if (gViewPort)
+ return gViewPort->MsgFunc_MOTD( pszName, iSize, pbuf );
+ return 0;
+}
+
+int __MsgFunc_ServerName(const char *pszName, int iSize, void *pbuf)
+{
+ if (gViewPort)
+ return gViewPort->MsgFunc_ServerName( pszName, iSize, pbuf );
+ return 0;
+}
+
+int __MsgFunc_ScoreInfo(const char *pszName, int iSize, void *pbuf)
+{
+ if (gViewPort)
+ return gViewPort->MsgFunc_ScoreInfo( pszName, iSize, pbuf );
+ return 0;
+}
+
+int __MsgFunc_TeamScore(const char *pszName, int iSize, void *pbuf)
+{
+ if (gViewPort)
+ return gViewPort->MsgFunc_TeamScore( pszName, iSize, pbuf );
+ return 0;
+}
+
+int __MsgFunc_TeamInfo(const char *pszName, int iSize, void *pbuf)
+{
+ if (gViewPort)
+ return gViewPort->MsgFunc_TeamInfo( pszName, iSize, pbuf );
+ return 0;
+}
+
+void __CmdFunc_SpecialDummy(void) {}
+
+void __CmdFunc_ClRateDummy(void) { }
+
+// This is called every time the DLL is loaded
+void CHud :: Init( void )
+{
+ HOOK_MESSAGE( ResetHUD );
+ HOOK_MESSAGE( InitHUD );
+ HOOK_MESSAGE( ViewMode );
+ HOOK_MESSAGE( SetFOV );
+
+ HOOK_COMMAND( "special", SpecialDummy);
+ HOOK_COMMAND( "_special", SpecialDummy); //prevent abuse
+
+ HOOK_COMMAND( "cl_rate", ClRateDummy);
+
+ HOOK_MESSAGE( TeamNames );
+ HOOK_MESSAGE( MOTD );
+ HOOK_MESSAGE( ServerName );
+ HOOK_MESSAGE( ScoreInfo );
+ HOOK_MESSAGE( TeamScore );
+ HOOK_MESSAGE( TeamInfo );
+
+ CVAR_CREATE( "hud_classautokill", "1", FCVAR_ARCHIVE | FCVAR_USERINFO ); // controls whether or not to suicide immediately on TF class switch
+ CVAR_CREATE( "hud_takesshots", "0", FCVAR_ARCHIVE ); // controls whether or not to automatically take screenshots at the end of a round
+
+#ifdef DEBUG
+ CVAR_CREATE( "hud_hideview", "0", FCVAR_ARCHIVE );
+#endif
+
+ m_iLogo = 0;
+ m_iFOV = 0;
+
+ // : duck toggle
+ g_bDuckToggled = false;
+ // :
+
+ CVAR_CREATE( "zoom_sensitivity_ratio", "1.2", 0 );
+ default_fov = CVAR_CREATE( "default_fov", "90", 0 );
+ m_pCvarStealMouse = CVAR_CREATE( "hud_capturemouse", "1", FCVAR_ARCHIVE );
+ m_pCvarDraw = CVAR_CREATE( "hud_draw", "1", FCVAR_ARCHIVE );
+ cl_lw = gEngfuncs.pfnGetCvarPointer( "cl_lw" );
+
+ CVAR_CREATE( "cl_showspeed", "0", 0);
+ CVAR_CREATE( kvLabelMaps, "1", FCVAR_ARCHIVE);
+ CVAR_CREATE( kvGammaRamp, "1", FCVAR_ARCHIVE);
+ CVAR_CREATE( kvCustomCrosshair, "1", FCVAR_ARCHIVE);
+ CVAR_CREATE( kvHudMapZoom, "3", FCVAR_ARCHIVE);
+ CVAR_CREATE( kvLabelHivesight, "1", FCVAR_ARCHIVE);
+ CVAR_CREATE( "cl_iconr", "0", FCVAR_ARCHIVE);
+ CVAR_CREATE( "cl_icong", "149", FCVAR_ARCHIVE);
+ CVAR_CREATE( "cl_iconb", "221", FCVAR_ARCHIVE);
+
+ m_pSpriteList = NULL;
+
+ // Clear any old HUD list
+ if ( m_pHudList )
+ {
+ HUDLIST *pList;
+ while ( m_pHudList )
+ {
+ pList = m_pHudList;
+ m_pHudList = m_pHudList->pNext;
+ free( pList );
+ }
+ m_pHudList = NULL;
+ }
+
+ // In case we get messages before the first update -- time will be valid
+ m_flTime = 1.0;
+
+ m_Ammo.Init();
+ m_Health.Init();
+ m_Spectator.Init();
+ m_SayText.Init();
+ m_Geiger.Init();
+ m_Train.Init();
+ m_Battery.Init();
+ m_Flash.Init();
+ m_Message.Init();
+ m_StatusBar.Init();
+ m_DeathNotice.Init();
+ m_AmmoSecondary.Init();
+ m_TextMessage.Init();
+ m_StatusIcons.Init();
+
+ m_Spectator.m_chatEnabled = (m_SayText.m_HUD_saytext->value!=0);
+
+ GetClientVoiceMgr()->Init(&g_VoiceStatusHelper, (vgui::Panel**)&gViewPort);
+
+ m_Menu.Init();
+
+ ServersInit();
+
+ MsgFunc_ResetHUD(0, 0, NULL );
+}
+
+// CHud destructor
+// cleans up memory allocated for m_rg* arrays
+CHud :: ~CHud()
+{
+ delete [] m_rghSprites;
+ delete [] m_rgrcRects;
+ delete [] m_rgszSpriteNames;
+
+ if ( m_pHudList )
+ {
+ HUDLIST *pList;
+ while ( m_pHudList )
+ {
+ pList = m_pHudList;
+ m_pHudList = m_pHudList->pNext;
+ free( pList );
+ }
+ m_pHudList = NULL;
+ }
+
+ ServersShutdown();
+}
+
+// GetSpriteIndex()
+// searches through the sprite list loaded from hud.txt for a name matching SpriteName
+// returns an index into the gHUD.m_rghSprites[] array
+// returns 0 if sprite not found
+int CHud :: GetSpriteIndex( const char *SpriteName )
+{
+ // look through the loaded sprite name list for SpriteName
+ for ( int i = 0; i < m_iSpriteCount; i++ )
+ {
+ if ( strncmp( SpriteName, m_rgszSpriteNames + (i * MAX_SPRITE_NAME_LENGTH), MAX_SPRITE_NAME_LENGTH ) == 0 )
+ return i;
+ }
+
+ return -1; // invalid sprite
+}
+
+void CHud :: VidInit( void )
+{
+ m_scrinfo.iSize = sizeof(m_scrinfo);
+ GetScreenInfo(&m_scrinfo);
+
+ // The NS viewport isn't set up yet
+ int theViewPort[4];
+ theViewPort[0] = theViewPort[1] = 0;
+ theViewPort[2] = this->m_scrinfo.iWidth;
+ theViewPort[3] = this->m_scrinfo.iHeight;
+
+ gHUD.SetViewport(theViewPort);
+
+ mFont.Load("sprites/font_arial");
+ mSmallFont.Load("sprites/font_arialsmall");
+
+ // ----------
+ // Load Sprites
+ // ---------
+// m_hsprFont = LoadSprite("sprites/%d_font.spr");
+
+ m_hsprLogo = 0;
+ m_hsprCursor = 0;
+
+ if (ScreenWidth() < 640)
+ m_iRes = 320;
+ else
+ m_iRes = 640;
+
+ // Only load this once
+ if ( !m_pSpriteList )
+ {
+ // we need to load the hud.txt, and all sprites within
+ m_pSpriteList = SPR_GetList("sprites/hud.txt", &m_iSpriteCountAllRes);
+
+ if (m_pSpriteList)
+ {
+ // count the number of sprites of the appropriate res
+ m_iSpriteCount = 0;
+ client_sprite_t *p = m_pSpriteList;
+ int j;
+ for ( j = 0; j < m_iSpriteCountAllRes; j++ )
+ {
+ if ( p->iRes == m_iRes )
+ m_iSpriteCount++;
+ p++;
+ }
+
+ // allocated memory for sprite handle arrays
+ m_rghSprites = new HSPRITE[m_iSpriteCount];
+ m_rgrcRects = new wrect_t[m_iSpriteCount];
+ m_rgszSpriteNames = new char[m_iSpriteCount * MAX_SPRITE_NAME_LENGTH];
+
+ p = m_pSpriteList;
+ int index = 0;
+ for ( j = 0; j < m_iSpriteCountAllRes; j++ )
+ {
+ if ( p->iRes == m_iRes )
+ {
+ char sz[256];
+ sprintf(sz, "sprites/%s.spr", p->szSprite);
+ m_rghSprites[index] = SPR_Load(sz);
+ m_rgrcRects[index] = p->rc;
+ strncpy( &m_rgszSpriteNames[index * MAX_SPRITE_NAME_LENGTH], p->szName, MAX_SPRITE_NAME_LENGTH );
+
+ index++;
+ }
+
+ p++;
+ }
+ }
+ }
+ else
+ {
+ // we have already have loaded the sprite reference from hud.txt, but
+ // we need to make sure all the sprites have been loaded (we've gone through a transition, or loaded a save game)
+ client_sprite_t *p = m_pSpriteList;
+ int index = 0;
+ for ( int j = 0; j < m_iSpriteCountAllRes; j++ )
+ {
+ if ( p->iRes == m_iRes )
+ {
+ char sz[256];
+ sprintf( sz, "sprites/%s.spr", p->szSprite );
+ m_rghSprites[index] = SPR_Load(sz);
+ index++;
+ }
+
+ p++;
+ }
+ }
+
+ // assumption: number_1, number_2, etc, are all listed and loaded sequentially
+ m_HUD_number_0 = GetSpriteIndex( "number_0" );
+
+ m_iFontHeight = m_rgrcRects[m_HUD_number_0].bottom - m_rgrcRects[m_HUD_number_0].top;
+
+ m_Ammo.VidInit();
+ m_Health.VidInit();
+ m_Spectator.VidInit();
+ m_Geiger.VidInit();
+ m_Train.VidInit();
+ m_Battery.VidInit();
+ m_Flash.VidInit();
+ m_Message.VidInit();
+ m_StatusBar.VidInit();
+ m_DeathNotice.VidInit();
+ m_SayText.VidInit();
+ m_Menu.VidInit();
+ m_AmmoSecondary.VidInit();
+ m_TextMessage.VidInit();
+ m_StatusIcons.VidInit();
+ GetClientVoiceMgr()->VidInit();
+}
+
+float g_lastFOV = 0.0;
+
+/*
+============
+COM_FileBase
+============
+*/
+// Extracts the base name of a file (no path, no extension, assumes '/' as path separator)
+void COM_FileBase ( const char *in, char *out)
+{
+ int len, start, end;
+
+ len = (int)strlen( in );
+
+ // scan backward for '.'
+ end = len - 1;
+ while ( end && in[end] != '.' && in[end] != '/' && in[end] != '\\' )
+ end--;
+
+ if ( in[end] != '.' ) // no '.', copy to end
+ end = len-1;
+ else
+ end--; // Found ',', copy to left of '.'
+
+
+ // Scan backward for '/'
+ start = len-1;
+ while ( start >= 0 && in[start] != '/' && in[start] != '\\' )
+ start--;
+
+ if ( in[start] != '/' && in[start] != '\\' )
+ start = 0;
+ else
+ start++;
+
+ // Length of new sting
+ len = end - start + 1;
+
+ // Copy partial string
+ strncpy( out, &in[start], len );
+ // Terminate it
+ out[len] = 0;
+}
+
+/*
+=================
+HUD_IsGame
+
+=================
+*/
+int HUD_IsGame( const char *game )
+{
+ const char *gamedir;
+ char gd[ 1024 ];
+
+ gamedir = gEngfuncs.pfnGetGameDirectory();
+ if ( gamedir && gamedir[0] )
+ {
+ COM_FileBase( gamedir, gd );
+ if ( !stricmp( gd, game ) )
+ return 1;
+ }
+ return 0;
+}
+
+/*
+=====================
+HUD_GetFOV
+
+Returns last FOV
+=====================
+*/
+float HUD_GetFOV( void )
+{
+ if ( gEngfuncs.pDemoAPI->IsRecording() )
+ {
+ // Write it
+ int i = 0;
+ unsigned char buf[ 100 ];
+
+ // Active
+ *( float * )&buf[ i ] = g_lastFOV;
+ i += sizeof( float );
+
+ Demo_WriteBuffer( TYPE_ZOOM, i, buf );
+ }
+
+ if ( gEngfuncs.pDemoAPI->IsPlayingback() )
+ {
+ g_lastFOV = g_demozoom;
+ }
+ return g_lastFOV;
+}
+
+int CHud::MsgFunc_SetFOV(const char *pszName, int iSize, void *pbuf)
+{
+ int newfov;
+ NetMsg_SetFOV( pbuf, iSize, newfov );
+ int def_fov = CVAR_GET_FLOAT( "default_fov" );
+
+ //Weapon prediction already takes care of changing the fog. ( g_lastFOV ).
+ if ( cl_lw && cl_lw->value )
+ return 1;
+
+ g_lastFOV = newfov;
+
+ if ( newfov == 0 )
+ {
+ m_iFOV = def_fov;
+ }
+ else
+ {
+ m_iFOV = newfov;
+ }
+
+ // the clients fov is actually set in the client data update section of the hud
+
+ // Set a new sensitivity
+ if ( m_iFOV == def_fov )
+ {
+ // reset to saved sensitivity
+ m_flMouseSensitivity = 0;
+ }
+ else
+ {
+ // set a new sensitivity that is proportional to the change from the FOV default
+ m_flMouseSensitivity = sensitivity->value * ((float)newfov / (float)def_fov) * CVAR_GET_FLOAT("zoom_sensitivity_ratio");
+ }
+
+ return 1;
+}
+
+
+void CHud::AddHudElem(CHudBase *phudelem)
+{
+ HUDLIST *pdl, *ptemp;
+
+//phudelem->Think();
+
+ if (!phudelem)
+ return;
+
+ pdl = (HUDLIST *)malloc(sizeof(HUDLIST));
+ if (!pdl)
+ return;
+
+ memset(pdl, 0, sizeof(HUDLIST));
+ pdl->p = phudelem;
+
+ if (!m_pHudList)
+ {
+ m_pHudList = pdl;
+ return;
+ }
+
+ ptemp = m_pHudList;
+
+ while (ptemp->pNext)
+ ptemp = ptemp->pNext;
+
+ ptemp->pNext = pdl;
+}
+
+float CHud::GetSensitivity( void )
+{
+ return m_flMouseSensitivity;
+}
+
+
diff --git a/main/source/cl_dll/hud.h b/main/source/cl_dll/hud.h
index aab293ba..bc2500d8 100644
--- a/main/source/cl_dll/hud.h
+++ b/main/source/cl_dll/hud.h
@@ -1,86 +1,86 @@
-/***
-*
-* Copyright (c) 1999, Valve LLC. All rights reserved.
-*
-* This product contains software technology licensed from Id
-* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
-* All Rights Reserved.
-*
-* Use, distribution, and modification of this source code and/or resulting
-* object code is restricted to non-commercial enhancements to products from
-* Valve LLC. All other use, distribution, or modification is prohibited
-* without written permission from Valve LLC.
-*
-****/
-//
-// hud.h
-//
-// class CHud declaration
-//
-// CHud handles the message, calculation, and drawing the HUD
-//
-
-#ifndef HL_HUD_H
-#define HL_HUD_H
-
-#include "chud.h"
-
-class TeamFortressViewport;
-
-class AvHHud;
-#include "AvHHud.h"
-extern AvHHud gHUD;
-
-#include "wrect.h"
-#include "cl_dll.h"
-#include "ammo.h"
-#include "chudmisc.h"
-
-#include "voice_status.h"
-#include "hud_spectator.h"
-
-/*
-class CHudScoreboard: public CHudBase
-{
-public:
- int Init( void );
- void InitHUDData( void );
- int VidInit( void );
- int Draw( float flTime );
- int DrawPlayers( int xoffset, float listslot, int nameoffset = 0, char *team = NULL ); // returns the ypos where it finishes drawing
- void UserCmd_ShowScores( void );
- void UserCmd_HideScores( void );
- int MsgFunc_ScoreInfo( const char *pszName, int iSize, void *pbuf );
- int MsgFunc_TeamInfo( const char *pszName, int iSize, void *pbuf );
- int MsgFunc_TeamScore( const char *pszName, int iSize, void *pbuf );
- void DeathMsg( int killer, int victim );
-
- int m_iNumTeams;
-
- int m_iLastKilledBy;
- int m_fLastKillTime;
- int m_iPlayerNum;
- int m_iShowscoresHeld;
-
- void GetAllPlayersInfo( void );
-private:
- struct cvar_s *cl_showpacketloss;
-
-};
-*/
-
-//
-//-----------------------------------------------------
-//
-
-#include "chud.h"
-
-extern TeamFortressViewport *gViewPort;
-
-extern int g_iPlayerClass;
-extern int g_iTeamNumber;
-extern int g_iUser1;
-extern int g_iUser2;
-extern int g_iUser3;
-
-#endif
+/***
+*
+* Copyright (c) 1999, Valve LLC. All rights reserved.
+*
+* This product contains software technology licensed from Id
+* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
+* All Rights Reserved.
+*
+* Use, distribution, and modification of this source code and/or resulting
+* object code is restricted to non-commercial enhancements to products from
+* Valve LLC. All other use, distribution, or modification is prohibited
+* without written permission from Valve LLC.
+*
+****/
+//
+// hud.h
+//
+// class CHud declaration
+//
+// CHud handles the message, calculation, and drawing the HUD
+//
+
+#ifndef HL_HUD_H
+#define HL_HUD_H
+
+#include "chud.h"
+
+class TeamFortressViewport;
+
+class AvHHud;
+#include "AvHHud.h"
+extern AvHHud gHUD;
+
+#include "wrect.h"
+#include "cl_dll.h"
+#include "ammo.h"
+#include "chudmisc.h"
+
+#include "voice_status.h"
+#include "hud_spectator.h"
+
+/*
+class CHudScoreboard: public CHudBase
+{
+public:
+ int Init( void );
+ void InitHUDData( void );
+ int VidInit( void );
+ int Draw( float flTime );
+ int DrawPlayers( int xoffset, float listslot, int nameoffset = 0, char *team = NULL ); // returns the ypos where it finishes drawing
+ void UserCmd_ShowScores( void );
+ void UserCmd_HideScores( void );
+ int MsgFunc_ScoreInfo( const char *pszName, int iSize, void *pbuf );
+ int MsgFunc_TeamInfo( const char *pszName, int iSize, void *pbuf );
+ int MsgFunc_TeamScore( const char *pszName, int iSize, void *pbuf );
+ void DeathMsg( int killer, int victim );
+
+ int m_iNumTeams;
+
+ int m_iLastKilledBy;
+ int m_fLastKillTime;
+ int m_iPlayerNum;
+ int m_iShowscoresHeld;
+
+ void GetAllPlayersInfo( void );
+private:
+ struct cvar_s *cl_showpacketloss;
+
+};
+*/
+
+//
+//-----------------------------------------------------
+//
+
+#include "chud.h"
+
+extern TeamFortressViewport *gViewPort;
+
+extern int g_iPlayerClass;
+extern int g_iTeamNumber;
+extern int g_iUser1;
+extern int g_iUser2;
+extern int g_iUser3;
+
+#endif
diff --git a/main/source/cl_dll/hud_iface.h b/main/source/cl_dll/hud_iface.h
index c763c8bb..d7fbc1ce 100644
--- a/main/source/cl_dll/hud_iface.h
+++ b/main/source/cl_dll/hud_iface.h
@@ -1,14 +1,14 @@
-#if !defined( HUD_IFACEH )
-#define HUD_IFACEH
-#pragma once
-
-#ifndef EXPORT
-#define EXPORT _declspec( dllexport )
-#endif
-
-typedef int (*pfnUserMsgHook)(const char *pszName, int iSize, void *pbuf);
-#include "wrect.h"
-#include "../engine/cdll_int.h"
-extern cl_enginefunc_t gEngfuncs;
-
+#if !defined( HUD_IFACEH )
+#define HUD_IFACEH
+#pragma once
+
+#ifndef EXPORT
+#define EXPORT _declspec( dllexport )
+#endif
+
+typedef int (*pfnUserMsgHook)(const char *pszName, int iSize, void *pbuf);
+#include "wrect.h"
+#include "../engine/cdll_int.h"
+extern cl_enginefunc_t gEngfuncs;
+
#endif
\ No newline at end of file
diff --git a/main/source/cl_dll/hud_msg.cpp b/main/source/cl_dll/hud_msg.cpp
index dbe710a2..35580e9a 100644
--- a/main/source/cl_dll/hud_msg.cpp
+++ b/main/source/cl_dll/hud_msg.cpp
@@ -1,77 +1,77 @@
-/***
-*
-* Copyright (c) 1999, Valve LLC. All rights reserved.
-*
-* This product contains software technology licensed from Id
-* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
-* All Rights Reserved.
-*
-* Use, distribution, and modification of this source code and/or resulting
-* object code is restricted to non-commercial enhancements to products from
-* Valve LLC. All other use, distribution, or modification is prohibited
-* without written permission from Valve LLC.
-*
-****/
-//
-// hud_msg.cpp
-//
-
-#include "hud.h"
-#include "cl_util.h"
-#include "common/r_efx.h"
-#include "mod/AvHNetworkMessages.h"
-
-// : duck toggle
-extern bool g_bDuckToggled;
-// :
-
-#define MAX_CLIENTS 32
-
-#if !defined( _TFC )
-extern BEAM *pBeam;
-extern BEAM *pBeam2;
-#endif
-/// USER-DEFINED SERVER MESSAGE HANDLERS
-
-int CHud :: MsgFunc_ResetHUD(const char *pszName, int iSize, void *pbuf )
-{
- NetMsg_ResetHUD( pbuf, iSize );
-
- // clear all hud data
- HUDLIST *pList = m_pHudList;
-
- while ( pList )
- {
- if ( pList->p )
- pList->p->Reset();
- pList = pList->pNext;
- }
-
- // reset sensitivity
- m_flMouseSensitivity = 0;
-
- // : duck toggle
- g_bDuckToggled = false;
- // :
-
- return 0;
-}
-
-void CAM_ToFirstPerson(void);
-void CHud :: MsgFunc_ViewMode( const char *pszName, int iSize, void *pbuf )
-{
- CAM_ToFirstPerson();
-}
-
-void CHud :: MsgFunc_InitHUD( const char *pszName, int iSize, void *pbuf )
-{
- // prepare all hud data
- HUDLIST *pList = m_pHudList;
-
- while (pList)
- {
- if ( pList->p )
- pList->p->InitHUDData();
- pList = pList->pNext;
- }
-}
+/***
+*
+* Copyright (c) 1999, Valve LLC. All rights reserved.
+*
+* This product contains software technology licensed from Id
+* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
+* All Rights Reserved.
+*
+* Use, distribution, and modification of this source code and/or resulting
+* object code is restricted to non-commercial enhancements to products from
+* Valve LLC. All other use, distribution, or modification is prohibited
+* without written permission from Valve LLC.
+*
+****/
+//
+// hud_msg.cpp
+//
+
+#include "hud.h"
+#include "cl_util.h"
+#include "common/r_efx.h"
+#include "mod/AvHNetworkMessages.h"
+
+// : duck toggle
+extern bool g_bDuckToggled;
+// :
+
+#define MAX_CLIENTS 32
+
+#if !defined( _TFC )
+extern BEAM *pBeam;
+extern BEAM *pBeam2;
+#endif
+/// USER-DEFINED SERVER MESSAGE HANDLERS
+
+int CHud :: MsgFunc_ResetHUD(const char *pszName, int iSize, void *pbuf )
+{
+ NetMsg_ResetHUD( pbuf, iSize );
+
+ // clear all hud data
+ HUDLIST *pList = m_pHudList;
+
+ while ( pList )
+ {
+ if ( pList->p )
+ pList->p->Reset();
+ pList = pList->pNext;
+ }
+
+ // reset sensitivity
+ m_flMouseSensitivity = 0;
+
+ // : duck toggle
+ g_bDuckToggled = false;
+ // :
+
+ return 0;
+}
+
+void CAM_ToFirstPerson(void);
+void CHud :: MsgFunc_ViewMode( const char *pszName, int iSize, void *pbuf )
+{
+ CAM_ToFirstPerson();
+}
+
+void CHud :: MsgFunc_InitHUD( const char *pszName, int iSize, void *pbuf )
+{
+ // prepare all hud data
+ HUDLIST *pList = m_pHudList;
+
+ while (pList)
+ {
+ if ( pList->p )
+ pList->p->InitHUDData();
+ pList = pList->pNext;
+ }
+}
diff --git a/main/source/cl_dll/hud_redraw.cpp b/main/source/cl_dll/hud_redraw.cpp
index ad3065a1..db8cf6c7 100644
--- a/main/source/cl_dll/hud_redraw.cpp
+++ b/main/source/cl_dll/hud_redraw.cpp
@@ -1,411 +1,411 @@
-/***
-*
-* Copyright (c) 1999, Valve LLC. All rights reserved.
-*
-* This product contains software technology licensed from Id
-* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
-* All Rights Reserved.
-*
-* Use, distribution, and modification of this source code and/or resulting
-* object code is restricted to non-commercial enhancements to products from
-* Valve LLC. All other use, distribution, or modification is prohibited
-* without written permission from Valve LLC.
-*
-****/
-//
-// hud_redraw.cpp
-//
-#include
-#include "hud.h"
-#include "cl_util.h"
-#include "mod/AvHFont.h"
-
-#include "vgui_TeamFortressViewport.h"
-
-#define MAX_LOGO_FRAMES 56
-
-int grgLogoFrame[MAX_LOGO_FRAMES] =
-{
- 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 13, 13, 13, 13, 13, 12, 11, 10, 9, 8, 14, 15,
- 16, 17, 18, 19, 20, 20, 20, 20, 20, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
- 29, 29, 29, 29, 29, 28, 27, 26, 25, 24, 30, 31
-};
-
-
-extern int g_iVisibleMouse;
-
-float HUD_GetFOV( void );
-
-extern cvar_t *sensitivity;
-extern cvar_t *cl_forcedefaultfov;
-
-// Think
-void CHud::Think(void)
-{
- int newfov;
- HUDLIST *pList = m_pHudList;
-
- while (pList)
- {
- if (pList->p->m_iFlags & HUD_ACTIVE)
- pList->p->Think();
- pList = pList->pNext;
- }
-
- newfov = HUD_GetFOV();
- if ( newfov == 0 )
- {
- m_iFOV = default_fov->value;
- }
- else
- {
- m_iFOV = newfov;
- }
-
- if(cl_forcedefaultfov->value)
- {
- m_iFOV = 90;
- }
-
- // the clients fov is actually set in the client data update section of the hud
-
- // Set a new sensitivity
- if ( m_iFOV == default_fov->value )
- {
- // reset to saved sensitivity
- m_flMouseSensitivity = 0;
- }
- else
- {
- // set a new sensitivity that is proportional to the change from the FOV default
- m_flMouseSensitivity = sensitivity->value * ((float)newfov / (float)default_fov->value) * CVAR_GET_FLOAT("zoom_sensitivity_ratio");
- }
-
- // think about default fov
- if ( m_iFOV == 0 )
- { // only let players adjust up in fov, and only if they are not overriden by something else
- m_iFOV = max( default_fov->value, 90 );
- }
-}
-
-// Redraw
-// step through the local data, placing the appropriate graphics & text as appropriate
-// returns 1 if they've changed, 0 otherwise
-int CHud :: Redraw( float flTime, int intermission )
-{
- m_fOldTime = m_flTime; // save time of previous redraw
- m_flTime = flTime;
- m_flTimeDelta = (double)m_flTime - m_fOldTime;
- static int m_flShotTime = 0;
-
- // Clock was reset, reset delta
- if ( m_flTimeDelta < 0 )
- m_flTimeDelta = 0;
-
- // Bring up the scoreboard during intermission
- if (gViewPort)
- {
- if ( m_iIntermission && !intermission )
- {
- // Have to do this here so the scoreboard goes away
- m_iIntermission = intermission;
- gViewPort->HideCommandMenu();
- gViewPort->HideScoreBoard();
- gViewPort->UpdateSpectatorPanel();
- }
- else if ( !m_iIntermission && intermission )
- {
- m_iIntermission = intermission;
- gViewPort->HideCommandMenu();
- gViewPort->HideVGUIMenu();
- gViewPort->ShowScoreBoard();
- gViewPort->UpdateSpectatorPanel();
-
- // Take a screenshot if the client's got the cvar set
- if ( CVAR_GET_FLOAT( "hud_takesshots" ) != 0 )
- m_flShotTime = flTime + 1.0; // Take a screenshot in a second
- }
- }
-
- if (m_flShotTime && m_flShotTime < flTime)
- {
- gEngfuncs.pfnClientCmd("snapshot\n");
- m_flShotTime = 0;
- }
-
- m_iIntermission = intermission;
-
- // if no redrawing is necessary
- // return 0;
-
-
- if ( m_pCvarDraw->value)
- {
- HUDLIST *pList = m_pHudList;
-
- while (pList)
- {
- if ( !intermission )
- {
- if ( (pList->p->m_iFlags & HUD_ACTIVE) && (!(m_iHideHUDDisplay & HIDEHUD_CHAT) && !(m_iHideHUDDisplay & HIDEHUD_ALL)) )
- pList->p->Draw(flTime);
- }
- else
- { // it's an intermission, so only draw hud elements that are set to draw during intermissions
- if ( pList->p->m_iFlags & HUD_INTERMISSION )
- pList->p->Draw( flTime );
- }
-
- pList = pList->pNext;
- }
- }
-
- // are we in demo mode? do we need to draw the logo in the top corner?
- if (m_iLogo)
- {
- int x, y, i;
-
- if (m_hsprLogo == 0)
- m_hsprLogo = LoadSprite("sprites/%d_logo.spr");
-
- SPR_Set(m_hsprLogo, 250, 250, 250 );
-
- x = SPR_Width(m_hsprLogo, 0);
- x = ScreenWidth() - x;
- y = SPR_Height(m_hsprLogo, 0)/2;
-
- // Draw the logo at 20 fps
- int iFrame = (int)(flTime * 20) % MAX_LOGO_FRAMES;
- i = grgLogoFrame[iFrame] - 1;
-
- SPR_DrawAdditive(i, x, y, NULL);
- }
-
- /*
- if ( g_iVisibleMouse )
- {
- void IN_GetMousePos( int *mx, int *my );
- int mx, my;
-
- IN_GetMousePos( &mx, &my );
-
- if (m_hsprCursor == 0)
- {
- char sz[256];
- sprintf( sz, "sprites/cursor.spr" );
- m_hsprCursor = SPR_Load( sz );
- }
-
- SPR_Set(m_hsprCursor, 250, 250, 250 );
-
- // Draw the logo at 20 fps
- SPR_DrawAdditive( 0, mx, my, NULL );
- }
- */
-
- return 1;
-}
-
-void ScaleColors( int &r, int &g, int &b, int a )
-{
- float x = (float)a / 255;
- r = (int)(r * x);
- g = (int)(g * x);
- b = (int)(b * x);
-}
-
-int CHud::GetHudStringHeight()
-{
-
- /*
- int theHeight = 0;
- theHeight = gHUD.m_scrinfo.iCharHeight;
- return theHeight;
- */
-
- return mFont.GetStringHeight();
-
-}
-
-int CHud::GetHudStringWidth(const char* szIt)
-{
- /*
- int theWidth = 0;
-
- // draw the string until we hit the null character or a newline character
- for ( ; *szIt != 0 && *szIt != '\n'; szIt++ )
- {
- theWidth += gHUD.m_scrinfo.charWidths[ *szIt ];
- }
-
- return theWidth;
- */
-
- return mFont.GetStringWidth(szIt);
-
-}
-
-int CHud::DrawHudStringCentered(int x, int y, int iMaxX, const char *szString, int r, int g, int b )
-{
- int theStringWidth = this->GetHudStringWidth(szString);
- return this->DrawHudString(x - theStringWidth/2, y, iMaxX, szString, r, g, b);
-}
-
-int CHud :: DrawHudString(int xpos, int ypos, int iMaxX, const char *szIt, int r, int g, int b )
-{
- /*
- // Try to prevent software-mode crash
- int theStringHeight = this->GetHudStringHeight();
-
- if((ypos + theStringHeight) < ScreenHeight())
- {
- // draw the string until we hit the null character or a newline character
- for ( ; *szIt != 0 && *szIt != '\n'; szIt++ )
- {
- int next = xpos + gHUD.m_scrinfo.charWidths[ *szIt ]; // variable-width fonts look cool
- if ( next > iMaxX )
- return xpos;
-
- TextMessageDrawChar( xpos, ypos, *szIt, r, g, b );
- xpos = next;
- }
- }
-
- return xpos;
- */
-
- return mFont.DrawString(xpos, ypos, szIt, r, g, b);
-
-}
-
-int CHud :: DrawHudNumberString( int xpos, int ypos, int iMinX, int iNumber, int r, int g, int b )
-{
- char szString[32];
- sprintf( szString, "%d", iNumber );
- return DrawHudStringReverse( xpos, ypos, iMinX, szString, r, g, b );
-
-}
-
-// draws a string from right to left (right-aligned)
-int CHud :: DrawHudStringReverse( int xpos, int ypos, int iMinX, char *szString, int r, int g, int b )
-{
-
- /*
- // find the end of the string
- for ( char *szIt = szString; *szIt != 0; szIt++ )
- { // we should count the length?
- }
-
- // iterate throug the string in reverse
- for ( szIt--; szIt != (szString-1); szIt-- )
- {
- int next = xpos - gHUD.m_scrinfo.charWidths[ *szIt ]; // variable-width fonts look cool
- if ( next < iMinX )
- return xpos;
- xpos = next;
-
- TextMessageDrawChar( xpos, ypos, *szIt, r, g, b );
- }
-
- return xpos;
- */
-
- return mFont.DrawStringReverse(xpos, ypos, szString, r, g, b);
-
-}
-
-int CHud :: DrawHudNumber( int x, int y, int iFlags, int iNumber, int r, int g, int b)
-{
- int iWidth = GetSpriteRect(m_HUD_number_0).right - GetSpriteRect(m_HUD_number_0).left;
- int k;
-
- if (iNumber > 0)
- {
- // SPR_Draw 100's
- if (iNumber >= 100)
- {
- k = iNumber/100;
- SPR_Set(GetSprite(m_HUD_number_0 + k), r, g, b );
- SPR_DrawAdditive( 0, x, y, &GetSpriteRect(m_HUD_number_0 + k));
- x += iWidth;
- }
- else if (iFlags & (DHN_3DIGITS))
- {
- //SPR_DrawAdditive( 0, x, y, &rc );
- x += iWidth;
- }
-
- // SPR_Draw 10's
- if (iNumber >= 10)
- {
- k = (iNumber % 100)/10;
- SPR_Set(GetSprite(m_HUD_number_0 + k), r, g, b );
- SPR_DrawAdditive( 0, x, y, &GetSpriteRect(m_HUD_number_0 + k));
- x += iWidth;
- }
- else if (iFlags & (DHN_3DIGITS | DHN_2DIGITS))
- {
- //SPR_DrawAdditive( 0, x, y, &rc );
- x += iWidth;
- }
-
- // SPR_Draw ones
- k = iNumber % 10;
- SPR_Set(GetSprite(m_HUD_number_0 + k), r, g, b );
- SPR_DrawAdditive(0, x, y, &GetSpriteRect(m_HUD_number_0 + k));
- x += iWidth;
- }
- else if (iFlags & DHN_DRAWZERO)
- {
- SPR_Set(GetSprite(m_HUD_number_0), r, g, b );
-
- // SPR_Draw 100's
- if (iFlags & (DHN_3DIGITS))
- {
- //SPR_DrawAdditive( 0, x, y, &rc );
- x += iWidth;
- }
-
- if (iFlags & (DHN_3DIGITS | DHN_2DIGITS))
- {
- //SPR_DrawAdditive( 0, x, y, &rc );
- x += iWidth;
- }
-
- // SPR_Draw ones
-
- SPR_DrawAdditive( 0, x, y, &GetSpriteRect(m_HUD_number_0));
- x += iWidth;
- }
-
- return x;
-}
-
-
-int CHud::GetNumWidth( int iNumber, int iFlags )
-{
- if (iFlags & (DHN_3DIGITS))
- return 3;
-
- if (iFlags & (DHN_2DIGITS))
- return 2;
-
- if (iNumber <= 0)
- {
- if (iFlags & (DHN_DRAWZERO))
- return 1;
- else
- return 0;
- }
-
- if (iNumber < 10)
- return 1;
-
- if (iNumber < 100)
- return 2;
-
- return 3;
-
-}
-
-
+/***
+*
+* Copyright (c) 1999, Valve LLC. All rights reserved.
+*
+* This product contains software technology licensed from Id
+* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
+* All Rights Reserved.
+*
+* Use, distribution, and modification of this source code and/or resulting
+* object code is restricted to non-commercial enhancements to products from
+* Valve LLC. All other use, distribution, or modification is prohibited
+* without written permission from Valve LLC.
+*
+****/
+//
+// hud_redraw.cpp
+//
+#include
+#include "hud.h"
+#include "cl_util.h"
+#include "mod/AvHFont.h"
+
+#include "vgui_TeamFortressViewport.h"
+
+#define MAX_LOGO_FRAMES 56
+
+int grgLogoFrame[MAX_LOGO_FRAMES] =
+{
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 13, 13, 13, 13, 13, 12, 11, 10, 9, 8, 14, 15,
+ 16, 17, 18, 19, 20, 20, 20, 20, 20, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 29, 29, 29, 29, 29, 28, 27, 26, 25, 24, 30, 31
+};
+
+
+extern int g_iVisibleMouse;
+
+float HUD_GetFOV( void );
+
+extern cvar_t *sensitivity;
+extern cvar_t *cl_forcedefaultfov;
+
+// Think
+void CHud::Think(void)
+{
+ int newfov;
+ HUDLIST *pList = m_pHudList;
+
+ while (pList)
+ {
+ if (pList->p->m_iFlags & HUD_ACTIVE)
+ pList->p->Think();
+ pList = pList->pNext;
+ }
+
+ newfov = HUD_GetFOV();
+ if ( newfov == 0 )
+ {
+ m_iFOV = default_fov->value;
+ }
+ else
+ {
+ m_iFOV = newfov;
+ }
+
+ if(cl_forcedefaultfov->value)
+ {
+ m_iFOV = 90;
+ }
+
+ // the clients fov is actually set in the client data update section of the hud
+
+ // Set a new sensitivity
+ if ( m_iFOV == default_fov->value )
+ {
+ // reset to saved sensitivity
+ m_flMouseSensitivity = 0;
+ }
+ else
+ {
+ // set a new sensitivity that is proportional to the change from the FOV default
+ m_flMouseSensitivity = sensitivity->value * ((float)newfov / (float)default_fov->value) * CVAR_GET_FLOAT("zoom_sensitivity_ratio");
+ }
+
+ // think about default fov
+ if ( m_iFOV == 0 )
+ { // only let players adjust up in fov, and only if they are not overriden by something else
+ m_iFOV = max( default_fov->value, 90 );
+ }
+}
+
+// Redraw
+// step through the local data, placing the appropriate graphics & text as appropriate
+// returns 1 if they've changed, 0 otherwise
+int CHud :: Redraw( float flTime, int intermission )
+{
+ m_fOldTime = m_flTime; // save time of previous redraw
+ m_flTime = flTime;
+ m_flTimeDelta = (double)m_flTime - m_fOldTime;
+ static int m_flShotTime = 0;
+
+ // Clock was reset, reset delta
+ if ( m_flTimeDelta < 0 )
+ m_flTimeDelta = 0;
+
+ // Bring up the scoreboard during intermission
+ if (gViewPort)
+ {
+ if ( m_iIntermission && !intermission )
+ {
+ // Have to do this here so the scoreboard goes away
+ m_iIntermission = intermission;
+ gViewPort->HideCommandMenu();
+ gViewPort->HideScoreBoard();
+ gViewPort->UpdateSpectatorPanel();
+ }
+ else if ( !m_iIntermission && intermission )
+ {
+ m_iIntermission = intermission;
+ gViewPort->HideCommandMenu();
+ gViewPort->HideVGUIMenu();
+ gViewPort->ShowScoreBoard();
+ gViewPort->UpdateSpectatorPanel();
+
+ // Take a screenshot if the client's got the cvar set
+ if ( CVAR_GET_FLOAT( "hud_takesshots" ) != 0 )
+ m_flShotTime = flTime + 1.0; // Take a screenshot in a second
+ }
+ }
+
+ if (m_flShotTime && m_flShotTime < flTime)
+ {
+ gEngfuncs.pfnClientCmd("snapshot\n");
+ m_flShotTime = 0;
+ }
+
+ m_iIntermission = intermission;
+
+ // if no redrawing is necessary
+ // return 0;
+
+
+ if ( m_pCvarDraw->value)
+ {
+ HUDLIST *pList = m_pHudList;
+
+ while (pList)
+ {
+ if ( !intermission )
+ {
+ if ( (pList->p->m_iFlags & HUD_ACTIVE) && (!(m_iHideHUDDisplay & HIDEHUD_CHAT) && !(m_iHideHUDDisplay & HIDEHUD_ALL)) )
+ pList->p->Draw(flTime);
+ }
+ else
+ { // it's an intermission, so only draw hud elements that are set to draw during intermissions
+ if ( pList->p->m_iFlags & HUD_INTERMISSION )
+ pList->p->Draw( flTime );
+ }
+
+ pList = pList->pNext;
+ }
+ }
+
+ // are we in demo mode? do we need to draw the logo in the top corner?
+ if (m_iLogo)
+ {
+ int x, y, i;
+
+ if (m_hsprLogo == 0)
+ m_hsprLogo = LoadSprite("sprites/%d_logo.spr");
+
+ SPR_Set(m_hsprLogo, 250, 250, 250 );
+
+ x = SPR_Width(m_hsprLogo, 0);
+ x = ScreenWidth() - x;
+ y = SPR_Height(m_hsprLogo, 0)/2;
+
+ // Draw the logo at 20 fps
+ int iFrame = (int)(flTime * 20) % MAX_LOGO_FRAMES;
+ i = grgLogoFrame[iFrame] - 1;
+
+ SPR_DrawAdditive(i, x, y, NULL);
+ }
+
+ /*
+ if ( g_iVisibleMouse )
+ {
+ void IN_GetMousePos( int *mx, int *my );
+ int mx, my;
+
+ IN_GetMousePos( &mx, &my );
+
+ if (m_hsprCursor == 0)
+ {
+ char sz[256];
+ sprintf( sz, "sprites/cursor.spr" );
+ m_hsprCursor = SPR_Load( sz );
+ }
+
+ SPR_Set(m_hsprCursor, 250, 250, 250 );
+
+ // Draw the logo at 20 fps
+ SPR_DrawAdditive( 0, mx, my, NULL );
+ }
+ */
+
+ return 1;
+}
+
+void ScaleColors( int &r, int &g, int &b, int a )
+{
+ float x = (float)a / 255;
+ r = (int)(r * x);
+ g = (int)(g * x);
+ b = (int)(b * x);
+}
+
+int CHud::GetHudStringHeight()
+{
+
+ /*
+ int theHeight = 0;
+ theHeight = gHUD.m_scrinfo.iCharHeight;
+ return theHeight;
+ */
+
+ return mFont.GetStringHeight();
+
+}
+
+int CHud::GetHudStringWidth(const char* szIt)
+{
+ /*
+ int theWidth = 0;
+
+ // draw the string until we hit the null character or a newline character
+ for ( ; *szIt != 0 && *szIt != '\n'; szIt++ )
+ {
+ theWidth += gHUD.m_scrinfo.charWidths[ *szIt ];
+ }
+
+ return theWidth;
+ */
+
+ return mFont.GetStringWidth(szIt);
+
+}
+
+int CHud::DrawHudStringCentered(int x, int y, int iMaxX, const char *szString, int r, int g, int b )
+{
+ int theStringWidth = this->GetHudStringWidth(szString);
+ return this->DrawHudString(x - theStringWidth/2, y, iMaxX, szString, r, g, b);
+}
+
+int CHud :: DrawHudString(int xpos, int ypos, int iMaxX, const char *szIt, int r, int g, int b )
+{
+ /*
+ // Try to prevent software-mode crash
+ int theStringHeight = this->GetHudStringHeight();
+
+ if((ypos + theStringHeight) < ScreenHeight())
+ {
+ // draw the string until we hit the null character or a newline character
+ for ( ; *szIt != 0 && *szIt != '\n'; szIt++ )
+ {
+ int next = xpos + gHUD.m_scrinfo.charWidths[ *szIt ]; // variable-width fonts look cool
+ if ( next > iMaxX )
+ return xpos;
+
+ TextMessageDrawChar( xpos, ypos, *szIt, r, g, b );
+ xpos = next;
+ }
+ }
+
+ return xpos;
+ */
+
+ return mFont.DrawString(xpos, ypos, szIt, r, g, b);
+
+}
+
+int CHud :: DrawHudNumberString( int xpos, int ypos, int iMinX, int iNumber, int r, int g, int b )
+{
+ char szString[32];
+ sprintf( szString, "%d", iNumber );
+ return DrawHudStringReverse( xpos, ypos, iMinX, szString, r, g, b );
+
+}
+
+// draws a string from right to left (right-aligned)
+int CHud :: DrawHudStringReverse( int xpos, int ypos, int iMinX, char *szString, int r, int g, int b )
+{
+
+ /*
+ // find the end of the string
+ for ( char *szIt = szString; *szIt != 0; szIt++ )
+ { // we should count the length?
+ }
+
+ // iterate throug the string in reverse
+ for ( szIt--; szIt != (szString-1); szIt-- )
+ {
+ int next = xpos - gHUD.m_scrinfo.charWidths[ *szIt ]; // variable-width fonts look cool
+ if ( next < iMinX )
+ return xpos;
+ xpos = next;
+
+ TextMessageDrawChar( xpos, ypos, *szIt, r, g, b );
+ }
+
+ return xpos;
+ */
+
+ return mFont.DrawStringReverse(xpos, ypos, szString, r, g, b);
+
+}
+
+int CHud :: DrawHudNumber( int x, int y, int iFlags, int iNumber, int r, int g, int b)
+{
+ int iWidth = GetSpriteRect(m_HUD_number_0).right - GetSpriteRect(m_HUD_number_0).left;
+ int k;
+
+ if (iNumber > 0)
+ {
+ // SPR_Draw 100's
+ if (iNumber >= 100)
+ {
+ k = iNumber/100;
+ SPR_Set(GetSprite(m_HUD_number_0 + k), r, g, b );
+ SPR_DrawAdditive( 0, x, y, &GetSpriteRect(m_HUD_number_0 + k));
+ x += iWidth;
+ }
+ else if (iFlags & (DHN_3DIGITS))
+ {
+ //SPR_DrawAdditive( 0, x, y, &rc );
+ x += iWidth;
+ }
+
+ // SPR_Draw 10's
+ if (iNumber >= 10)
+ {
+ k = (iNumber % 100)/10;
+ SPR_Set(GetSprite(m_HUD_number_0 + k), r, g, b );
+ SPR_DrawAdditive( 0, x, y, &GetSpriteRect(m_HUD_number_0 + k));
+ x += iWidth;
+ }
+ else if (iFlags & (DHN_3DIGITS | DHN_2DIGITS))
+ {
+ //SPR_DrawAdditive( 0, x, y, &rc );
+ x += iWidth;
+ }
+
+ // SPR_Draw ones
+ k = iNumber % 10;
+ SPR_Set(GetSprite(m_HUD_number_0 + k), r, g, b );
+ SPR_DrawAdditive(0, x, y, &GetSpriteRect(m_HUD_number_0 + k));
+ x += iWidth;
+ }
+ else if (iFlags & DHN_DRAWZERO)
+ {
+ SPR_Set(GetSprite(m_HUD_number_0), r, g, b );
+
+ // SPR_Draw 100's
+ if (iFlags & (DHN_3DIGITS))
+ {
+ //SPR_DrawAdditive( 0, x, y, &rc );
+ x += iWidth;
+ }
+
+ if (iFlags & (DHN_3DIGITS | DHN_2DIGITS))
+ {
+ //SPR_DrawAdditive( 0, x, y, &rc );
+ x += iWidth;
+ }
+
+ // SPR_Draw ones
+
+ SPR_DrawAdditive( 0, x, y, &GetSpriteRect(m_HUD_number_0));
+ x += iWidth;
+ }
+
+ return x;
+}
+
+
+int CHud::GetNumWidth( int iNumber, int iFlags )
+{
+ if (iFlags & (DHN_3DIGITS))
+ return 3;
+
+ if (iFlags & (DHN_2DIGITS))
+ return 2;
+
+ if (iNumber <= 0)
+ {
+ if (iFlags & (DHN_DRAWZERO))
+ return 1;
+ else
+ return 0;
+ }
+
+ if (iNumber < 10)
+ return 1;
+
+ if (iNumber < 100)
+ return 2;
+
+ return 3;
+
+}
+
+
diff --git a/main/source/cl_dll/hud_servers.cpp b/main/source/cl_dll/hud_servers.cpp
index 561290fe..c5ec3cb7 100644
--- a/main/source/cl_dll/hud_servers.cpp
+++ b/main/source/cl_dll/hud_servers.cpp
@@ -1,1228 +1,1228 @@
-// hud_servers.cpp
-#include "hud.h"
-#include "cl_util.h"
-#include "hud_servers_priv.h"
-#include "hud_servers.h"
-#include "common/net_api.h"
-#include
- #ifdef _WIN32
-#include "winsani_in.h"
-#include
-#include "winsani_out.h"
-#else
-#include
-#endif
-static int context_id;
-
-// Default master server address in case we can't read any from woncomm.lst file
-#define VALVE_MASTER_ADDRESS "half-life.east.won.net"
-#define PORT_MASTER 27010
-#define PORT_SERVER 27015
-
-// File where we really should look for master servers
-#define MASTER_PARSE_FILE "woncomm.lst"
-
-#define MAX_QUERIES 20
-
-#define NET_API gEngfuncs.pNetAPI
-
-static CHudServers *g_pServers = NULL;
-
-/*
-===================
-ListResponse
-
-Callback from engine
-===================
-*/
-void NET_CALLBACK ListResponse( struct net_response_s *response )
-{
- if ( g_pServers )
- {
- g_pServers->ListResponse( response );
- }
-}
-
-/*
-===================
-ServerResponse
-
-Callback from engine
-===================
-*/
-void NET_CALLBACK ServerResponse( struct net_response_s *response )
-{
- if ( g_pServers )
- {
- g_pServers->ServerResponse( response );
- }
-}
-
-/*
-===================
-PingResponse
-
-Callback from engine
-===================
-*/
-void NET_CALLBACK PingResponse( struct net_response_s *response )
-{
- if ( g_pServers )
- {
- g_pServers->PingResponse( response );
- }
-}
-
-/*
-===================
-RulesResponse
-
-Callback from engine
-===================
-*/
-void NET_CALLBACK RulesResponse( struct net_response_s *response )
-{
- if ( g_pServers )
- {
- g_pServers->RulesResponse( response );
- }
-}
-/*
-===================
-PlayersResponse
-
-Callback from engine
-===================
-*/
-void NET_CALLBACK PlayersResponse( struct net_response_s *response )
-{
- if ( g_pServers )
- {
- g_pServers->PlayersResponse( response );
- }
-}
-/*
-===================
-ListResponse
-
-===================
-*/
-void CHudServers::ListResponse( struct net_response_s *response )
-{
- request_t *list;
- request_t *p;
- int c = 0;
-
- if ( !( response->error == NET_SUCCESS ) )
- return;
-
- if ( response->type != NETAPI_REQUEST_SERVERLIST )
- return;
-
- if ( response->response )
- {
- list = ( request_t * ) response->response;
- while ( list )
- {
- c++;
-
- //if ( c < 40 )
- {
- // Copy from parsed stuff
- p = new request_t;
- p->context = -1;
- p->remote_address = list->remote_address;
- p->next = m_pServerList;
- m_pServerList = p;
- }
-
- // Move on
- list = list->next;
- }
- }
-
- gEngfuncs.Con_Printf( "got list\n" );
-
- m_nQuerying = 1;
- m_nActiveQueries = 0;
-}
-
-/*
-===================
-ServerResponse
-
-===================
-*/
-void CHudServers::ServerResponse( struct net_response_s *response )
-{
- char *szresponse;
- request_t *p;
- server_t *browser;
- int len;
- char sz[ 32 ];
-
- // Remove from active list
- p = FindRequest( response->context, m_pActiveList );
- if ( p )
- {
- RemoveServerFromList( &m_pActiveList, p );
- m_nActiveQueries--;
- }
-
- if ( response->error != NET_SUCCESS )
- return;
-
- switch ( response->type )
- {
- case NETAPI_REQUEST_DETAILS:
- if ( response->response )
- {
- szresponse = (char *)response->response;
- len = (int)strlen( szresponse ) + 100 + 1;
- sprintf( sz, "%i", (int)( 1000.0 * response->ping ) );
-
- browser = new server_t;
- browser->remote_address = response->remote_address;
- browser->info = new char[ len ];
- browser->ping = (int)( 1000.0 * response->ping );
- strcpy( browser->info, szresponse );
-
- NET_API->SetValueForKey( browser->info, "address", gEngfuncs.pNetAPI->AdrToString( &response->remote_address ), len );
- NET_API->SetValueForKey( browser->info, "ping", sz, len );
-
- AddServer( &m_pServers, browser );
- }
- break;
- default:
- break;
- }
-}
-
-/*
-===================
-PingResponse
-
-===================
-*/
-void CHudServers::PingResponse( struct net_response_s *response )
-{
- char sz[ 32 ];
-
- if ( response->error != NET_SUCCESS )
- return;
-
- switch ( response->type )
- {
- case NETAPI_REQUEST_PING:
- sprintf( sz, "%.2f", 1000.0 * response->ping );
-
- gEngfuncs.Con_Printf( "ping == %s\n", sz );
- break;
- default:
- break;
- }
-}
-
-/*
-===================
-RulesResponse
-
-===================
-*/
-void CHudServers::RulesResponse( struct net_response_s *response )
-{
- char *szresponse;
-
- if ( response->error != NET_SUCCESS )
- return;
-
- switch ( response->type )
- {
- case NETAPI_REQUEST_RULES:
- if ( response->response )
- {
- szresponse = (char *)response->response;
-
- gEngfuncs.Con_Printf( "rules %s\n", szresponse );
- }
- break;
- default:
- break;
- }
-}
-
-/*
-===================
-PlayersResponse
-
-===================
-*/
-void CHudServers::PlayersResponse( struct net_response_s *response )
-{
- char *szresponse;
-
- if ( response->error != NET_SUCCESS )
- return;
-
- switch ( response->type )
- {
- case NETAPI_REQUEST_PLAYERS:
- if ( response->response )
- {
- szresponse = (char *)response->response;
-
- gEngfuncs.Con_Printf( "players %s\n", szresponse );
- }
- break;
- default:
- break;
- }
-}
-
-/*
-===================
-CompareServers
-
-Return 1 if p1 is "less than" p2, 0 otherwise
-===================
-*/
-int CHudServers::CompareServers( server_t *p1, server_t *p2 )
-{
- const char *n1, *n2;
-
- if ( p1->ping < p2->ping )
- return 1;
-
- if ( p1->ping == p2->ping )
- {
- // Pings equal, sort by second key: hostname
- if ( p1->info && p2->info )
- {
- n1 = NET_API->ValueForKey( p1->info, "hostname" );
- n2 = NET_API->ValueForKey( p2->info, "hostname" );
-
- if ( n1 && n2 )
- {
- if ( stricmp( n1, n2 ) < 0 )
- return 1;
- }
- }
- }
-
- return 0;
-}
-
-/*
-===================
-AddServer
-
-===================
-*/
-void CHudServers::AddServer( server_t **ppList, server_t *p )
-{
-server_t *list;
-
- if ( !ppList || ! p )
- return;
-
- m_nServerCount++;
-
- // What sort key? Ping?
- list = *ppList;
-
- // Head of list?
- if ( !list )
- {
- p->next = NULL;
- *ppList = p;
- return;
- }
-
- // Put on head of list
- if ( CompareServers( p, list ) )
- {
- p->next = *ppList;
- *ppList = p;
- }
- else
- {
- while ( list->next )
- {
- // Insert before list next
- if ( CompareServers( p, list->next ) )
- {
- p->next = list->next->next;
- list->next = p;
- return;
- }
-
- list = list->next;
- }
-
- // Just add at end
- p->next = NULL;
- list->next = p;
- }
-}
-
-/*
-===================
-Think
-
-===================
-*/
-void CHudServers::Think( double time )
-{
- m_fElapsed += time;
-
- if ( !m_nRequesting )
- return;
-
- if ( !m_nQuerying )
- return;
-
- QueryThink();
-
- if ( ServerListSize() > 0 )
- return;
-
- m_dStarted = 0.0;
- m_nRequesting = 0;
- m_nDone = 0;
- m_nQuerying = 0;
- m_nActiveQueries = 0;
-}
-
-/*
-===================
-QueryThink
-
-===================
-*/
-void CHudServers::QueryThink( void )
-{
- request_t *p;
-
- if ( !m_nRequesting || m_nDone )
- return;
-
- if ( !m_nQuerying )
- return;
-
- if ( m_nActiveQueries > MAX_QUERIES )
- return;
-
- // Nothing left
- if ( !m_pServerList )
- return;
-
- while ( 1 )
- {
- p = m_pServerList;
-
- // No more in list?
- if ( !p )
- break;
-
- // Move to next
- m_pServerList = m_pServerList->next;
-
- // Setup context_id
- p->context = context_id;
-
- // Start up query on this one
- NET_API->SendRequest( context_id++, NETAPI_REQUEST_DETAILS, 0, 2.0, &p->remote_address, ::ServerResponse );
-
- // Increment active list
- m_nActiveQueries++;
-
- // Add to active list
- p->next = m_pActiveList;
- m_pActiveList = p;
-
- // Too many active?
- if ( m_nActiveQueries > MAX_QUERIES )
- break;
- }
-}
-
-/*
-==================
-ServerListSize
-
-# of servers in active query and in pending to be queried lists
-==================
-*/
-int CHudServers::ServerListSize( void )
-{
- int c = 0;
- request_t *p;
-
- p = m_pServerList;
- while ( p )
- {
- c++;
- p = p->next;
- }
-
- p = m_pActiveList;
- while ( p )
- {
- c++;
- p = p->next;
- }
-
- return c;
-}
-
-/*
-===================
-FindRequest
-
-Look up a request by context id
-===================
-*/
-CHudServers::request_t *CHudServers::FindRequest( int context, request_t *pList )
-{
- request_t *p;
- p = pList;
- while ( p )
- {
- if ( context == p->context )
- return p;
-
- p = p->next;
- }
- return NULL;
-}
-
-/*
-===================
-RemoveServerFromList
-
-Remote, but don't delete, item from *ppList
-===================
-*/
-void CHudServers::RemoveServerFromList( request_t **ppList, request_t *item )
-{
- request_t *p, *n;
- request_t *newlist = NULL;
-
- if ( !ppList )
- return;
-
- p = *ppList;
- while ( p )
- {
- n = p->next;
- if ( p != item )
- {
- p->next = newlist;
- newlist = p;
- }
- p = n;
- }
- *ppList = newlist;
-}
-
-/*
-===================
-ClearRequestList
-
-===================
-*/
-void CHudServers::ClearRequestList( request_t **ppList )
-{
- request_t *p, *n;
-
- if ( !ppList )
- return;
-
- p = *ppList;
- while ( p )
- {
- n = p->next;
- delete p;
- p = n;
- }
- *ppList = NULL;
-}
-
-/*
-===================
-ClearServerList
-
-===================
-*/
-void CHudServers::ClearServerList( server_t **ppList )
-{
- server_t *p, *n;
-
- if ( !ppList )
- return;
-
- p = *ppList;
- while ( p )
- {
- n = p->next;
- delete[] p->info;
- delete p;
- p = n;
- }
- *ppList = NULL;
-}
-
-int CompareField( CHudServers::server_t *p1, CHudServers::server_t *p2, const char *fieldname, int iSortOrder )
-{
- const char *sz1, *sz2;
- float fv1, fv2;
-
- sz1 = NET_API->ValueForKey( p1->info, fieldname );
- sz2 = NET_API->ValueForKey( p2->info, fieldname );
-
- fv1 = atof( sz1 );
- fv2 = atof( sz2 );
-
- if ( fv1 && fv2 )
- {
- if ( fv1 > fv2 )
- return iSortOrder;
- else if ( fv1 < fv2 )
- return -iSortOrder;
- else
- return 0;
- }
-
- // String compare
- return stricmp( sz1, sz2 );
-}
-
-int ServerListCompareFunc( CHudServers::server_t *p1, CHudServers::server_t *p2, const char *fieldname )
-{
- if (!p1 || !p2) // No meaningful comparison
- return 0;
-
- int iSortOrder = 1;
-
- int retval = 0;
-
- retval = CompareField( p1, p2, fieldname, iSortOrder );
-
- return retval;
-}
-
-static char g_fieldname[ 256 ];
-int __cdecl FnServerCompare(const void *elem1, const void *elem2 )
-{
- CHudServers::server_t *list1, *list2;
-
- list1 = *(CHudServers::server_t **)elem1;
- list2 = *(CHudServers::server_t **)elem2;
-
- return ServerListCompareFunc( list1, list2, g_fieldname );
-}
-
-void CHudServers::SortServers( const char *fieldname )
-{
- server_t *p;
- // Create a list
- if ( !m_pServers )
- return;
-
- strcpy( g_fieldname, fieldname );
-
- int i;
- int c = 0;
-
- p = m_pServers;
- while ( p )
- {
- c++;
- p = p->next;
- }
-
- server_t **pSortArray;
-
- pSortArray = new server_t *[ c ];
- memset( pSortArray, 0, c * sizeof( server_t * ) );
-
- // Now copy the list into the pSortArray:
- p = m_pServers;
- i = 0;
- while ( p )
- {
- pSortArray[ i++ ] = p;
- p = p->next;
- }
-
- // Now do that actual sorting.
- size_t nCount = c;
- size_t nSize = sizeof( server_t * );
-
- qsort(
- pSortArray,
- (size_t)nCount,
- (size_t)nSize,
- FnServerCompare
- );
-
- // Now rebuild the list.
- m_pServers = pSortArray[0];
- for ( i = 0; i < c - 1; i++ )
- {
- pSortArray[ i ]->next = pSortArray[ i + 1 ];
- }
- pSortArray[ c - 1 ]->next = NULL;
-
- // Clean Up.
- delete[] pSortArray;
-}
-
-/*
-===================
-GetServer
-
-Return particular server
-===================
-*/
-CHudServers::server_t *CHudServers::GetServer( int server )
-{
- int c = 0;
- server_t *p;
-
- p = m_pServers;
- while ( p )
- {
- if ( c == server )
- return p;
-
- c++;
- p = p->next;
- }
- return NULL;
-}
-
-/*
-===================
-GetServerInfo
-
-Return info ( key/value ) string for particular server
-===================
-*/
-char *CHudServers::GetServerInfo( int server )
-{
- server_t *p = GetServer( server );
- if ( p )
- {
- return p->info;
- }
- return NULL;
-}
-
-/*
-===================
-CancelRequest
-
-Kill all pending requests in engine
-===================
-*/
-void CHudServers::CancelRequest( void )
-{
- m_nRequesting = 0;
- m_nQuerying = 0;
- m_nDone = 1;
-
- NET_API->CancelAllRequests();
-}
-
-/*
-==================
-LoadMasterAddresses
-
-Loads the master server addresses from file and into the passed in array
-==================
-*/
-int CHudServers::LoadMasterAddresses( int maxservers, int *count, netadr_t *padr )
-{
- int i;
- char szMaster[ 256 ];
- char szMasterFile[256];
- char *pbuffer = NULL;
- char *pstart = NULL ;
- netadr_t adr;
- char szAdr[64];
- int nPort;
- int nCount = 0;
- bool bIgnore;
- int nDefaultPort;
-
- // Assume default master and master file
- strcpy( szMaster, VALVE_MASTER_ADDRESS ); // IP:PORT string
- strcpy( szMasterFile, MASTER_PARSE_FILE );
-
- // See if there is a command line override
- i = gEngfuncs.CheckParm( "-comm", &pstart );
- if ( i && pstart )
- {
- strcpy (szMasterFile, pstart );
- }
-
- // Read them in from proper file
- pbuffer = (char *)gEngfuncs.COM_LoadFile( szMasterFile, 5, NULL ); // Use malloc
- if ( !pbuffer )
- {
- goto finish_master;
- }
-
- pstart = pbuffer;
-
- while ( nCount < maxservers )
- {
- pstart = gEngfuncs.COM_ParseFile( pstart, m_szToken );
-
- if ( strlen(m_szToken) <= 0)
- break;
-
- bIgnore = true;
-
- if ( !stricmp( m_szToken, "Master" ) )
- {
- nDefaultPort = PORT_MASTER;
- bIgnore = FALSE;
- }
-
- // Now parse all addresses between { }
- pstart = gEngfuncs.COM_ParseFile( pstart, m_szToken );
- if ( strlen(m_szToken) <= 0 )
- break;
-
- if ( stricmp ( m_szToken, "{" ) )
- break;
-
- // Parse addresses until we get to "}"
- while ( nCount < maxservers )
- {
- char base[256];
-
- // Now parse all addresses between { }
- pstart = gEngfuncs.COM_ParseFile( pstart, m_szToken );
-
- if (strlen(m_szToken) <= 0)
- break;
-
- if ( !stricmp ( m_szToken, "}" ) )
- break;
-
- sprintf( base, "%s", m_szToken );
-
- pstart = gEngfuncs.COM_ParseFile( pstart, m_szToken );
-
- if (strlen(m_szToken) <= 0)
- break;
-
- if ( stricmp( m_szToken, ":" ) )
- break;
-
- pstart = gEngfuncs.COM_ParseFile( pstart, m_szToken );
-
- if (strlen(m_szToken) <= 0)
- break;
-
- nPort = atoi ( m_szToken );
- if ( !nPort )
- nPort = nDefaultPort;
-
- sprintf( szAdr, "%s:%i", base, nPort );
-
- // Can we resolve it any better
- if ( !NET_API->StringToAdr( szAdr, &adr ) )
- bIgnore = true;
-
- if ( !bIgnore )
- {
- padr[ nCount++ ] = adr;
- }
- }
- }
-
-finish_master:
- if ( !nCount )
- {
- sprintf( szMaster, VALVE_MASTER_ADDRESS ); // IP:PORT string
-
- // Convert to netadr_t
- if ( NET_API->StringToAdr ( szMaster, &adr ) )
- {
-
- padr[ nCount++ ] = adr;
- }
- }
-
- *count = nCount;
-
- if ( pbuffer )
- {
- gEngfuncs.COM_FreeFile( pbuffer );
- }
-
- return ( nCount > 0 ) ? 1 : 0;
-}
-
-/*
-===================
-RequestList
-
-Request list of game servers from master
-===================
-*/
-void CHudServers::RequestList( void )
-{
- m_nRequesting = 1;
- m_nDone = 0;
- m_dStarted = m_fElapsed;
-
- int count = 0;
- netadr_t adr;
-
- if ( !LoadMasterAddresses( 1, &count, &adr ) )
- {
- gEngfuncs.Con_DPrintf( "SendRequest: Unable to read master server addresses\n" );
- return;
- }
-
- ClearRequestList( &m_pActiveList );
- ClearRequestList( &m_pServerList );
- ClearServerList( &m_pServers );
-
- m_nServerCount = 0;
-
- // Make sure networking system has started.
- NET_API->InitNetworking();
-
- // Kill off left overs if any
- NET_API->CancelAllRequests();
-
- // Request Server List from master
- NET_API->SendRequest( context_id++, NETAPI_REQUEST_SERVERLIST, 0, 5.0, &adr, ::ListResponse );
-}
-
-void CHudServers::RequestBroadcastList( int clearpending )
-{
- m_nRequesting = 1;
- m_nDone = 0;
- m_dStarted = m_fElapsed;
-
- netadr_t adr;
- memset( &adr, 0, sizeof( adr ) );
-
- if ( clearpending )
- {
- ClearRequestList( &m_pActiveList );
- ClearRequestList( &m_pServerList );
- ClearServerList( &m_pServers );
-
- m_nServerCount = 0;
- }
-
- // Make sure to byte swap server if necessary ( using "host" to "net" conversion
- adr.port = htons( PORT_SERVER );
-
- // Make sure networking system has started.
- NET_API->InitNetworking();
-
- if ( clearpending )
- {
- // Kill off left overs if any
- NET_API->CancelAllRequests();
- }
-
- adr.type = NA_BROADCAST;
-
- // Request Servers from LAN via IP
- NET_API->SendRequest( context_id++, NETAPI_REQUEST_DETAILS, FNETAPI_MULTIPLE_RESPONSE, 5.0, &adr, ::ServerResponse );
-
- adr.type = NA_BROADCAST_IPX;
-
- // Request Servers from LAN via IPX ( if supported )
- NET_API->SendRequest( context_id++, NETAPI_REQUEST_DETAILS, FNETAPI_MULTIPLE_RESPONSE, 5.0, &adr, ::ServerResponse );
-}
-
-void CHudServers::ServerPing( int server )
-{
- server_t *p;
-
- p = GetServer( server );
- if ( !p )
- return;
-
- // Make sure networking system has started.
- NET_API->InitNetworking();
-
- // Request Server List from master
- NET_API->SendRequest( context_id++, NETAPI_REQUEST_PING, 0, 5.0, &p->remote_address, ::PingResponse );
-}
-
-void CHudServers::ServerRules( int server )
-{
- server_t *p;
-
- p = GetServer( server );
- if ( !p )
- return;
-
- // Make sure networking system has started.
- NET_API->InitNetworking();
-
- // Request Server List from master
- NET_API->SendRequest( context_id++, NETAPI_REQUEST_RULES, 0, 5.0, &p->remote_address, ::RulesResponse );
-}
-
-void CHudServers::ServerPlayers( int server )
-{
- server_t *p;
-
- p = GetServer( server );
- if ( !p )
- return;
-
- // Make sure networking system has started.
- NET_API->InitNetworking();
-
- // Request Server List from master
- NET_API->SendRequest( context_id++, NETAPI_REQUEST_PLAYERS, 0, 5.0, &p->remote_address, ::PlayersResponse );
-}
-
-int CHudServers::isQuerying()
-{
- return m_nRequesting ? 1 : 0;
-}
-
-
-/*
-===================
-GetServerCount
-
-Return number of servers in browser list
-===================
-*/
-int CHudServers::GetServerCount( void )
-{
- return m_nServerCount;
-}
-
-/*
-===================
-CHudServers
-
-===================
-*/
-CHudServers::CHudServers( void )
-{
- m_nRequesting = 0;
- m_dStarted = 0.0;
- m_nDone = 0;
- m_pServerList = NULL;
- m_pServers = NULL;
- m_pActiveList = NULL;
- m_nQuerying = 0;
- m_nActiveQueries = 0;
-
- m_fElapsed = 0.0;
-
-
- m_pPingRequest = NULL;
- m_pRulesRequest = NULL;
- m_pPlayersRequest = NULL;
-}
-
-/*
-===================
-~CHudServers
-
-===================
-*/
-CHudServers::~CHudServers( void )
-{
- ClearRequestList( &m_pActiveList );
- ClearRequestList( &m_pServerList );
- ClearServerList( &m_pServers );
-
- m_nServerCount = 0;
-
- if ( m_pPingRequest )
- {
- delete m_pPingRequest;
- m_pPingRequest = NULL;
-
- }
-
- if ( m_pRulesRequest )
- {
- delete m_pRulesRequest;
- m_pRulesRequest = NULL;
- }
-
- if ( m_pPlayersRequest )
- {
- delete m_pPlayersRequest;
- m_pPlayersRequest = NULL;
- }
-}
-
-///////////////////////////////
-//
-// PUBLIC APIs
-//
-///////////////////////////////
-
-/*
-===================
-ServersGetCount
-
-===================
-*/
-int ServersGetCount( void )
-{
- if ( g_pServers )
- {
- return g_pServers->GetServerCount();
- }
- return 0;
-}
-
-int ServersIsQuerying( void )
-{
- if ( g_pServers )
- {
- return g_pServers->isQuerying();
- }
- return 0;
-}
-
-/*
-===================
-ServersGetInfo
-
-===================
-*/
-const char *ServersGetInfo( int server )
-{
- if ( g_pServers )
- {
- return g_pServers->GetServerInfo( server );
- }
-
- return NULL;
-}
-
-void SortServers( const char *fieldname )
-{
- if ( g_pServers )
- {
- g_pServers->SortServers( fieldname );
- }
-}
-
-/*
-===================
-ServersShutdown
-
-===================
-*/
-void ServersShutdown( void )
-{
- if ( g_pServers )
- {
- delete g_pServers;
- g_pServers = NULL;
- }
-}
-
-/*
-===================
-ServersInit
-
-===================
-*/
-void ServersInit( void )
-{
- // Kill any previous instance
- ServersShutdown();
-
- g_pServers = new CHudServers();
-}
-
-/*
-===================
-ServersThink
-
-===================
-*/
-void ServersThink( double time )
-{
- if ( g_pServers )
- {
- g_pServers->Think( time );
- }
-}
-
-/*
-===================
-ServersCancel
-
-===================
-*/
-void ServersCancel( void )
-{
- if ( g_pServers )
- {
- g_pServers->CancelRequest();
- }
-}
-
-// Requests
-/*
-===================
-ServersList
-
-===================
-*/
-void ServersList( void )
-{
- if ( g_pServers )
- {
- g_pServers->RequestList();
- }
-}
-
-void BroadcastServersList( int clearpending )
-{
- if ( g_pServers )
- {
- g_pServers->RequestBroadcastList( clearpending );
- }
-}
-
-void ServerPing( int server )
-{
- if ( g_pServers )
- {
- g_pServers->ServerPing( server );
- }
-}
-
-void ServerRules( int server )
-{
- if ( g_pServers )
- {
- g_pServers->ServerRules( server );
- }
-}
-
-void ServerPlayers( int server )
-{
- if ( g_pServers )
- {
- g_pServers->ServerPlayers( server );
- }
-}
+// hud_servers.cpp
+#include "hud.h"
+#include "cl_util.h"
+#include "hud_servers_priv.h"
+#include "hud_servers.h"
+#include "common/net_api.h"
+#include
+ #ifdef _WIN32
+#include "winsani_in.h"
+#include
+#include "winsani_out.h"
+#else
+#include
+#endif
+static int context_id;
+
+// Default master server address in case we can't read any from woncomm.lst file
+#define VALVE_MASTER_ADDRESS "half-life.east.won.net"
+#define PORT_MASTER 27010
+#define PORT_SERVER 27015
+
+// File where we really should look for master servers
+#define MASTER_PARSE_FILE "woncomm.lst"
+
+#define MAX_QUERIES 20
+
+#define NET_API gEngfuncs.pNetAPI
+
+static CHudServers *g_pServers = NULL;
+
+/*
+===================
+ListResponse
+
+Callback from engine
+===================
+*/
+void NET_CALLBACK ListResponse( struct net_response_s *response )
+{
+ if ( g_pServers )
+ {
+ g_pServers->ListResponse( response );
+ }
+}
+
+/*
+===================
+ServerResponse
+
+Callback from engine
+===================
+*/
+void NET_CALLBACK ServerResponse( struct net_response_s *response )
+{
+ if ( g_pServers )
+ {
+ g_pServers->ServerResponse( response );
+ }
+}
+
+/*
+===================
+PingResponse
+
+Callback from engine
+===================
+*/
+void NET_CALLBACK PingResponse( struct net_response_s *response )
+{
+ if ( g_pServers )
+ {
+ g_pServers->PingResponse( response );
+ }
+}
+
+/*
+===================
+RulesResponse
+
+Callback from engine
+===================
+*/
+void NET_CALLBACK RulesResponse( struct net_response_s *response )
+{
+ if ( g_pServers )
+ {
+ g_pServers->RulesResponse( response );
+ }
+}
+/*
+===================
+PlayersResponse
+
+Callback from engine
+===================
+*/
+void NET_CALLBACK PlayersResponse( struct net_response_s *response )
+{
+ if ( g_pServers )
+ {
+ g_pServers->PlayersResponse( response );
+ }
+}
+/*
+===================
+ListResponse
+
+===================
+*/
+void CHudServers::ListResponse( struct net_response_s *response )
+{
+ request_t *list;
+ request_t *p;
+ int c = 0;
+
+ if ( !( response->error == NET_SUCCESS ) )
+ return;
+
+ if ( response->type != NETAPI_REQUEST_SERVERLIST )
+ return;
+
+ if ( response->response )
+ {
+ list = ( request_t * ) response->response;
+ while ( list )
+ {
+ c++;
+
+ //if ( c < 40 )
+ {
+ // Copy from parsed stuff
+ p = new request_t;
+ p->context = -1;
+ p->remote_address = list->remote_address;
+ p->next = m_pServerList;
+ m_pServerList = p;
+ }
+
+ // Move on
+ list = list->next;
+ }
+ }
+
+ gEngfuncs.Con_Printf( "got list\n" );
+
+ m_nQuerying = 1;
+ m_nActiveQueries = 0;
+}
+
+/*
+===================
+ServerResponse
+
+===================
+*/
+void CHudServers::ServerResponse( struct net_response_s *response )
+{
+ char *szresponse;
+ request_t *p;
+ server_t *browser;
+ int len;
+ char sz[ 32 ];
+
+ // Remove from active list
+ p = FindRequest( response->context, m_pActiveList );
+ if ( p )
+ {
+ RemoveServerFromList( &m_pActiveList, p );
+ m_nActiveQueries--;
+ }
+
+ if ( response->error != NET_SUCCESS )
+ return;
+
+ switch ( response->type )
+ {
+ case NETAPI_REQUEST_DETAILS:
+ if ( response->response )
+ {
+ szresponse = (char *)response->response;
+ len = (int)strlen( szresponse ) + 100 + 1;
+ sprintf( sz, "%i", (int)( 1000.0 * response->ping ) );
+
+ browser = new server_t;
+ browser->remote_address = response->remote_address;
+ browser->info = new char[ len ];
+ browser->ping = (int)( 1000.0 * response->ping );
+ strcpy( browser->info, szresponse );
+
+ NET_API->SetValueForKey( browser->info, "address", gEngfuncs.pNetAPI->AdrToString( &response->remote_address ), len );
+ NET_API->SetValueForKey( browser->info, "ping", sz, len );
+
+ AddServer( &m_pServers, browser );
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+/*
+===================
+PingResponse
+
+===================
+*/
+void CHudServers::PingResponse( struct net_response_s *response )
+{
+ char sz[ 32 ];
+
+ if ( response->error != NET_SUCCESS )
+ return;
+
+ switch ( response->type )
+ {
+ case NETAPI_REQUEST_PING:
+ sprintf( sz, "%.2f", 1000.0 * response->ping );
+
+ gEngfuncs.Con_Printf( "ping == %s\n", sz );
+ break;
+ default:
+ break;
+ }
+}
+
+/*
+===================
+RulesResponse
+
+===================
+*/
+void CHudServers::RulesResponse( struct net_response_s *response )
+{
+ char *szresponse;
+
+ if ( response->error != NET_SUCCESS )
+ return;
+
+ switch ( response->type )
+ {
+ case NETAPI_REQUEST_RULES:
+ if ( response->response )
+ {
+ szresponse = (char *)response->response;
+
+ gEngfuncs.Con_Printf( "rules %s\n", szresponse );
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+/*
+===================
+PlayersResponse
+
+===================
+*/
+void CHudServers::PlayersResponse( struct net_response_s *response )
+{
+ char *szresponse;
+
+ if ( response->error != NET_SUCCESS )
+ return;
+
+ switch ( response->type )
+ {
+ case NETAPI_REQUEST_PLAYERS:
+ if ( response->response )
+ {
+ szresponse = (char *)response->response;
+
+ gEngfuncs.Con_Printf( "players %s\n", szresponse );
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+/*
+===================
+CompareServers
+
+Return 1 if p1 is "less than" p2, 0 otherwise
+===================
+*/
+int CHudServers::CompareServers( server_t *p1, server_t *p2 )
+{
+ const char *n1, *n2;
+
+ if ( p1->ping < p2->ping )
+ return 1;
+
+ if ( p1->ping == p2->ping )
+ {
+ // Pings equal, sort by second key: hostname
+ if ( p1->info && p2->info )
+ {
+ n1 = NET_API->ValueForKey( p1->info, "hostname" );
+ n2 = NET_API->ValueForKey( p2->info, "hostname" );
+
+ if ( n1 && n2 )
+ {
+ if ( stricmp( n1, n2 ) < 0 )
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+/*
+===================
+AddServer
+
+===================
+*/
+void CHudServers::AddServer( server_t **ppList, server_t *p )
+{
+server_t *list;
+
+ if ( !ppList || ! p )
+ return;
+
+ m_nServerCount++;
+
+ // What sort key? Ping?
+ list = *ppList;
+
+ // Head of list?
+ if ( !list )
+ {
+ p->next = NULL;
+ *ppList = p;
+ return;
+ }
+
+ // Put on head of list
+ if ( CompareServers( p, list ) )
+ {
+ p->next = *ppList;
+ *ppList = p;
+ }
+ else
+ {
+ while ( list->next )
+ {
+ // Insert before list next
+ if ( CompareServers( p, list->next ) )
+ {
+ p->next = list->next->next;
+ list->next = p;
+ return;
+ }
+
+ list = list->next;
+ }
+
+ // Just add at end
+ p->next = NULL;
+ list->next = p;
+ }
+}
+
+/*
+===================
+Think
+
+===================
+*/
+void CHudServers::Think( double time )
+{
+ m_fElapsed += time;
+
+ if ( !m_nRequesting )
+ return;
+
+ if ( !m_nQuerying )
+ return;
+
+ QueryThink();
+
+ if ( ServerListSize() > 0 )
+ return;
+
+ m_dStarted = 0.0;
+ m_nRequesting = 0;
+ m_nDone = 0;
+ m_nQuerying = 0;
+ m_nActiveQueries = 0;
+}
+
+/*
+===================
+QueryThink
+
+===================
+*/
+void CHudServers::QueryThink( void )
+{
+ request_t *p;
+
+ if ( !m_nRequesting || m_nDone )
+ return;
+
+ if ( !m_nQuerying )
+ return;
+
+ if ( m_nActiveQueries > MAX_QUERIES )
+ return;
+
+ // Nothing left
+ if ( !m_pServerList )
+ return;
+
+ while ( 1 )
+ {
+ p = m_pServerList;
+
+ // No more in list?
+ if ( !p )
+ break;
+
+ // Move to next
+ m_pServerList = m_pServerList->next;
+
+ // Setup context_id
+ p->context = context_id;
+
+ // Start up query on this one
+ NET_API->SendRequest( context_id++, NETAPI_REQUEST_DETAILS, 0, 2.0, &p->remote_address, ::ServerResponse );
+
+ // Increment active list
+ m_nActiveQueries++;
+
+ // Add to active list
+ p->next = m_pActiveList;
+ m_pActiveList = p;
+
+ // Too many active?
+ if ( m_nActiveQueries > MAX_QUERIES )
+ break;
+ }
+}
+
+/*
+==================
+ServerListSize
+
+# of servers in active query and in pending to be queried lists
+==================
+*/
+int CHudServers::ServerListSize( void )
+{
+ int c = 0;
+ request_t *p;
+
+ p = m_pServerList;
+ while ( p )
+ {
+ c++;
+ p = p->next;
+ }
+
+ p = m_pActiveList;
+ while ( p )
+ {
+ c++;
+ p = p->next;
+ }
+
+ return c;
+}
+
+/*
+===================
+FindRequest
+
+Look up a request by context id
+===================
+*/
+CHudServers::request_t *CHudServers::FindRequest( int context, request_t *pList )
+{
+ request_t *p;
+ p = pList;
+ while ( p )
+ {
+ if ( context == p->context )
+ return p;
+
+ p = p->next;
+ }
+ return NULL;
+}
+
+/*
+===================
+RemoveServerFromList
+
+Remote, but don't delete, item from *ppList
+===================
+*/
+void CHudServers::RemoveServerFromList( request_t **ppList, request_t *item )
+{
+ request_t *p, *n;
+ request_t *newlist = NULL;
+
+ if ( !ppList )
+ return;
+
+ p = *ppList;
+ while ( p )
+ {
+ n = p->next;
+ if ( p != item )
+ {
+ p->next = newlist;
+ newlist = p;
+ }
+ p = n;
+ }
+ *ppList = newlist;
+}
+
+/*
+===================
+ClearRequestList
+
+===================
+*/
+void CHudServers::ClearRequestList( request_t **ppList )
+{
+ request_t *p, *n;
+
+ if ( !ppList )
+ return;
+
+ p = *ppList;
+ while ( p )
+ {
+ n = p->next;
+ delete p;
+ p = n;
+ }
+ *ppList = NULL;
+}
+
+/*
+===================
+ClearServerList
+
+===================
+*/
+void CHudServers::ClearServerList( server_t **ppList )
+{
+ server_t *p, *n;
+
+ if ( !ppList )
+ return;
+
+ p = *ppList;
+ while ( p )
+ {
+ n = p->next;
+ delete[] p->info;
+ delete p;
+ p = n;
+ }
+ *ppList = NULL;
+}
+
+int CompareField( CHudServers::server_t *p1, CHudServers::server_t *p2, const char *fieldname, int iSortOrder )
+{
+ const char *sz1, *sz2;
+ float fv1, fv2;
+
+ sz1 = NET_API->ValueForKey( p1->info, fieldname );
+ sz2 = NET_API->ValueForKey( p2->info, fieldname );
+
+ fv1 = atof( sz1 );
+ fv2 = atof( sz2 );
+
+ if ( fv1 && fv2 )
+ {
+ if ( fv1 > fv2 )
+ return iSortOrder;
+ else if ( fv1 < fv2 )
+ return -iSortOrder;
+ else
+ return 0;
+ }
+
+ // String compare
+ return stricmp( sz1, sz2 );
+}
+
+int ServerListCompareFunc( CHudServers::server_t *p1, CHudServers::server_t *p2, const char *fieldname )
+{
+ if (!p1 || !p2) // No meaningful comparison
+ return 0;
+
+ int iSortOrder = 1;
+
+ int retval = 0;
+
+ retval = CompareField( p1, p2, fieldname, iSortOrder );
+
+ return retval;
+}
+
+static char g_fieldname[ 256 ];
+int __cdecl FnServerCompare(const void *elem1, const void *elem2 )
+{
+ CHudServers::server_t *list1, *list2;
+
+ list1 = *(CHudServers::server_t **)elem1;
+ list2 = *(CHudServers::server_t **)elem2;
+
+ return ServerListCompareFunc( list1, list2, g_fieldname );
+}
+
+void CHudServers::SortServers( const char *fieldname )
+{
+ server_t *p;
+ // Create a list
+ if ( !m_pServers )
+ return;
+
+ strcpy( g_fieldname, fieldname );
+
+ int i;
+ int c = 0;
+
+ p = m_pServers;
+ while ( p )
+ {
+ c++;
+ p = p->next;
+ }
+
+ server_t **pSortArray;
+
+ pSortArray = new server_t *[ c ];
+ memset( pSortArray, 0, c * sizeof( server_t * ) );
+
+ // Now copy the list into the pSortArray:
+ p = m_pServers;
+ i = 0;
+ while ( p )
+ {
+ pSortArray[ i++ ] = p;
+ p = p->next;
+ }
+
+ // Now do that actual sorting.
+ size_t nCount = c;
+ size_t nSize = sizeof( server_t * );
+
+ qsort(
+ pSortArray,
+ (size_t)nCount,
+ (size_t)nSize,
+ FnServerCompare
+ );
+
+ // Now rebuild the list.
+ m_pServers = pSortArray[0];
+ for ( i = 0; i < c - 1; i++ )
+ {
+ pSortArray[ i ]->next = pSortArray[ i + 1 ];
+ }
+ pSortArray[ c - 1 ]->next = NULL;
+
+ // Clean Up.
+ delete[] pSortArray;
+}
+
+/*
+===================
+GetServer
+
+Return particular server
+===================
+*/
+CHudServers::server_t *CHudServers::GetServer( int server )
+{
+ int c = 0;
+ server_t *p;
+
+ p = m_pServers;
+ while ( p )
+ {
+ if ( c == server )
+ return p;
+
+ c++;
+ p = p->next;
+ }
+ return NULL;
+}
+
+/*
+===================
+GetServerInfo
+
+Return info ( key/value ) string for particular server
+===================
+*/
+char *CHudServers::GetServerInfo( int server )
+{
+ server_t *p = GetServer( server );
+ if ( p )
+ {
+ return p->info;
+ }
+ return NULL;
+}
+
+/*
+===================
+CancelRequest
+
+Kill all pending requests in engine
+===================
+*/
+void CHudServers::CancelRequest( void )
+{
+ m_nRequesting = 0;
+ m_nQuerying = 0;
+ m_nDone = 1;
+
+ NET_API->CancelAllRequests();
+}
+
+/*
+==================
+LoadMasterAddresses
+
+Loads the master server addresses from file and into the passed in array
+==================
+*/
+int CHudServers::LoadMasterAddresses( int maxservers, int *count, netadr_t *padr )
+{
+ int i;
+ char szMaster[ 256 ];
+ char szMasterFile[256];
+ char *pbuffer = NULL;
+ char *pstart = NULL ;
+ netadr_t adr;
+ char szAdr[64];
+ int nPort;
+ int nCount = 0;
+ bool bIgnore;
+ int nDefaultPort;
+
+ // Assume default master and master file
+ strcpy( szMaster, VALVE_MASTER_ADDRESS ); // IP:PORT string
+ strcpy( szMasterFile, MASTER_PARSE_FILE );
+
+ // See if there is a command line override
+ i = gEngfuncs.CheckParm( "-comm", &pstart );
+ if ( i && pstart )
+ {
+ strcpy (szMasterFile, pstart );
+ }
+
+ // Read them in from proper file
+ pbuffer = (char *)gEngfuncs.COM_LoadFile( szMasterFile, 5, NULL ); // Use malloc
+ if ( !pbuffer )
+ {
+ goto finish_master;
+ }
+
+ pstart = pbuffer;
+
+ while ( nCount < maxservers )
+ {
+ pstart = gEngfuncs.COM_ParseFile( pstart, m_szToken );
+
+ if ( strlen(m_szToken) <= 0)
+ break;
+
+ bIgnore = true;
+
+ if ( !stricmp( m_szToken, "Master" ) )
+ {
+ nDefaultPort = PORT_MASTER;
+ bIgnore = FALSE;
+ }
+
+ // Now parse all addresses between { }
+ pstart = gEngfuncs.COM_ParseFile( pstart, m_szToken );
+ if ( strlen(m_szToken) <= 0 )
+ break;
+
+ if ( stricmp ( m_szToken, "{" ) )
+ break;
+
+ // Parse addresses until we get to "}"
+ while ( nCount < maxservers )
+ {
+ char base[256];
+
+ // Now parse all addresses between { }
+ pstart = gEngfuncs.COM_ParseFile( pstart, m_szToken );
+
+ if (strlen(m_szToken) <= 0)
+ break;
+
+ if ( !stricmp ( m_szToken, "}" ) )
+ break;
+
+ sprintf( base, "%s", m_szToken );
+
+ pstart = gEngfuncs.COM_ParseFile( pstart, m_szToken );
+
+ if (strlen(m_szToken) <= 0)
+ break;
+
+ if ( stricmp( m_szToken, ":" ) )
+ break;
+
+ pstart = gEngfuncs.COM_ParseFile( pstart, m_szToken );
+
+ if (strlen(m_szToken) <= 0)
+ break;
+
+ nPort = atoi ( m_szToken );
+ if ( !nPort )
+ nPort = nDefaultPort;
+
+ sprintf( szAdr, "%s:%i", base, nPort );
+
+ // Can we resolve it any better
+ if ( !NET_API->StringToAdr( szAdr, &adr ) )
+ bIgnore = true;
+
+ if ( !bIgnore )
+ {
+ padr[ nCount++ ] = adr;
+ }
+ }
+ }
+
+finish_master:
+ if ( !nCount )
+ {
+ sprintf( szMaster, VALVE_MASTER_ADDRESS ); // IP:PORT string
+
+ // Convert to netadr_t
+ if ( NET_API->StringToAdr ( szMaster, &adr ) )
+ {
+
+ padr[ nCount++ ] = adr;
+ }
+ }
+
+ *count = nCount;
+
+ if ( pbuffer )
+ {
+ gEngfuncs.COM_FreeFile( pbuffer );
+ }
+
+ return ( nCount > 0 ) ? 1 : 0;
+}
+
+/*
+===================
+RequestList
+
+Request list of game servers from master
+===================
+*/
+void CHudServers::RequestList( void )
+{
+ m_nRequesting = 1;
+ m_nDone = 0;
+ m_dStarted = m_fElapsed;
+
+ int count = 0;
+ netadr_t adr;
+
+ if ( !LoadMasterAddresses( 1, &count, &adr ) )
+ {
+ gEngfuncs.Con_DPrintf( "SendRequest: Unable to read master server addresses\n" );
+ return;
+ }
+
+ ClearRequestList( &m_pActiveList );
+ ClearRequestList( &m_pServerList );
+ ClearServerList( &m_pServers );
+
+ m_nServerCount = 0;
+
+ // Make sure networking system has started.
+ NET_API->InitNetworking();
+
+ // Kill off left overs if any
+ NET_API->CancelAllRequests();
+
+ // Request Server List from master
+ NET_API->SendRequest( context_id++, NETAPI_REQUEST_SERVERLIST, 0, 5.0, &adr, ::ListResponse );
+}
+
+void CHudServers::RequestBroadcastList( int clearpending )
+{
+ m_nRequesting = 1;
+ m_nDone = 0;
+ m_dStarted = m_fElapsed;
+
+ netadr_t adr;
+ memset( &adr, 0, sizeof( adr ) );
+
+ if ( clearpending )
+ {
+ ClearRequestList( &m_pActiveList );
+ ClearRequestList( &m_pServerList );
+ ClearServerList( &m_pServers );
+
+ m_nServerCount = 0;
+ }
+
+ // Make sure to byte swap server if necessary ( using "host" to "net" conversion
+ adr.port = htons( PORT_SERVER );
+
+ // Make sure networking system has started.
+ NET_API->InitNetworking();
+
+ if ( clearpending )
+ {
+ // Kill off left overs if any
+ NET_API->CancelAllRequests();
+ }
+
+ adr.type = NA_BROADCAST;
+
+ // Request Servers from LAN via IP
+ NET_API->SendRequest( context_id++, NETAPI_REQUEST_DETAILS, FNETAPI_MULTIPLE_RESPONSE, 5.0, &adr, ::ServerResponse );
+
+ adr.type = NA_BROADCAST_IPX;
+
+ // Request Servers from LAN via IPX ( if supported )
+ NET_API->SendRequest( context_id++, NETAPI_REQUEST_DETAILS, FNETAPI_MULTIPLE_RESPONSE, 5.0, &adr, ::ServerResponse );
+}
+
+void CHudServers::ServerPing( int server )
+{
+ server_t *p;
+
+ p = GetServer( server );
+ if ( !p )
+ return;
+
+ // Make sure networking system has started.
+ NET_API->InitNetworking();
+
+ // Request Server List from master
+ NET_API->SendRequest( context_id++, NETAPI_REQUEST_PING, 0, 5.0, &p->remote_address, ::PingResponse );
+}
+
+void CHudServers::ServerRules( int server )
+{
+ server_t *p;
+
+ p = GetServer( server );
+ if ( !p )
+ return;
+
+ // Make sure networking system has started.
+ NET_API->InitNetworking();
+
+ // Request Server List from master
+ NET_API->SendRequest( context_id++, NETAPI_REQUEST_RULES, 0, 5.0, &p->remote_address, ::RulesResponse );
+}
+
+void CHudServers::ServerPlayers( int server )
+{
+ server_t *p;
+
+ p = GetServer( server );
+ if ( !p )
+ return;
+
+ // Make sure networking system has started.
+ NET_API->InitNetworking();
+
+ // Request Server List from master
+ NET_API->SendRequest( context_id++, NETAPI_REQUEST_PLAYERS, 0, 5.0, &p->remote_address, ::PlayersResponse );
+}
+
+int CHudServers::isQuerying()
+{
+ return m_nRequesting ? 1 : 0;
+}
+
+
+/*
+===================
+GetServerCount
+
+Return number of servers in browser list
+===================
+*/
+int CHudServers::GetServerCount( void )
+{
+ return m_nServerCount;
+}
+
+/*
+===================
+CHudServers
+
+===================
+*/
+CHudServers::CHudServers( void )
+{
+ m_nRequesting = 0;
+ m_dStarted = 0.0;
+ m_nDone = 0;
+ m_pServerList = NULL;
+ m_pServers = NULL;
+ m_pActiveList = NULL;
+ m_nQuerying = 0;
+ m_nActiveQueries = 0;
+
+ m_fElapsed = 0.0;
+
+
+ m_pPingRequest = NULL;
+ m_pRulesRequest = NULL;
+ m_pPlayersRequest = NULL;
+}
+
+/*
+===================
+~CHudServers
+
+===================
+*/
+CHudServers::~CHudServers( void )
+{
+ ClearRequestList( &m_pActiveList );
+ ClearRequestList( &m_pServerList );
+ ClearServerList( &m_pServers );
+
+ m_nServerCount = 0;
+
+ if ( m_pPingRequest )
+ {
+ delete m_pPingRequest;
+ m_pPingRequest = NULL;
+
+ }
+
+ if ( m_pRulesRequest )
+ {
+ delete m_pRulesRequest;
+ m_pRulesRequest = NULL;
+ }
+
+ if ( m_pPlayersRequest )
+ {
+ delete m_pPlayersRequest;
+ m_pPlayersRequest = NULL;
+ }
+}
+
+///////////////////////////////
+//
+// PUBLIC APIs
+//
+///////////////////////////////
+
+/*
+===================
+ServersGetCount
+
+===================
+*/
+int ServersGetCount( void )
+{
+ if ( g_pServers )
+ {
+ return g_pServers->GetServerCount();
+ }
+ return 0;
+}
+
+int ServersIsQuerying( void )
+{
+ if ( g_pServers )
+ {
+ return g_pServers->isQuerying();
+ }
+ return 0;
+}
+
+/*
+===================
+ServersGetInfo
+
+===================
+*/
+const char *ServersGetInfo( int server )
+{
+ if ( g_pServers )
+ {
+ return g_pServers->GetServerInfo( server );
+ }
+
+ return NULL;
+}
+
+void SortServers( const char *fieldname )
+{
+ if ( g_pServers )
+ {
+ g_pServers->SortServers( fieldname );
+ }
+}
+
+/*
+===================
+ServersShutdown
+
+===================
+*/
+void ServersShutdown( void )
+{
+ if ( g_pServers )
+ {
+ delete g_pServers;
+ g_pServers = NULL;
+ }
+}
+
+/*
+===================
+ServersInit
+
+===================
+*/
+void ServersInit( void )
+{
+ // Kill any previous instance
+ ServersShutdown();
+
+ g_pServers = new CHudServers();
+}
+
+/*
+===================
+ServersThink
+
+===================
+*/
+void ServersThink( double time )
+{
+ if ( g_pServers )
+ {
+ g_pServers->Think( time );
+ }
+}
+
+/*
+===================
+ServersCancel
+
+===================
+*/
+void ServersCancel( void )
+{
+ if ( g_pServers )
+ {
+ g_pServers->CancelRequest();
+ }
+}
+
+// Requests
+/*
+===================
+ServersList
+
+===================
+*/
+void ServersList( void )
+{
+ if ( g_pServers )
+ {
+ g_pServers->RequestList();
+ }
+}
+
+void BroadcastServersList( int clearpending )
+{
+ if ( g_pServers )
+ {
+ g_pServers->RequestBroadcastList( clearpending );
+ }
+}
+
+void ServerPing( int server )
+{
+ if ( g_pServers )
+ {
+ g_pServers->ServerPing( server );
+ }
+}
+
+void ServerRules( int server )
+{
+ if ( g_pServers )
+ {
+ g_pServers->ServerRules( server );
+ }
+}
+
+void ServerPlayers( int server )
+{
+ if ( g_pServers )
+ {
+ g_pServers->ServerPlayers( server );
+ }
+}
diff --git a/main/source/cl_dll/hud_servers.h b/main/source/cl_dll/hud_servers.h
index cb8a725b..577b5551 100644
--- a/main/source/cl_dll/hud_servers.h
+++ b/main/source/cl_dll/hud_servers.h
@@ -1,34 +1,34 @@
-#if !defined( HUD_SERVERSH )
-#define HUD_SERVERSH
-#pragma once
-
-#define NET_CALLBACK /* */
-
-// Dispatchers
-void NET_CALLBACK ListResponse( struct net_response_s *response );
-void NET_CALLBACK ServerResponse( struct net_response_s *response );
-void NET_CALLBACK PingResponse( struct net_response_s *response );
-void NET_CALLBACK RulesResponse( struct net_response_s *response );
-void NET_CALLBACK PlayersResponse( struct net_response_s *response );
-
-void ServersInit( void );
-void ServersShutdown( void );
-void ServersThink( double time );
-void ServersCancel( void );
-
-// Get list and get server info from each
-void ServersList( void );
-
-// Query for IP / IPX LAN servers
-void BroadcastServersList( int clearpending );
-
-void ServerPing( int server );
-void ServerRules( int server );
-void ServerPlayers( int server );
-
-int ServersGetCount( void );
-const char *ServersGetInfo( int server );
-int ServersIsQuerying( void );
-void SortServers( const char *fieldname );
-
+#if !defined( HUD_SERVERSH )
+#define HUD_SERVERSH
+#pragma once
+
+#define NET_CALLBACK /* */
+
+// Dispatchers
+void NET_CALLBACK ListResponse( struct net_response_s *response );
+void NET_CALLBACK ServerResponse( struct net_response_s *response );
+void NET_CALLBACK PingResponse( struct net_response_s *response );
+void NET_CALLBACK RulesResponse( struct net_response_s *response );
+void NET_CALLBACK PlayersResponse( struct net_response_s *response );
+
+void ServersInit( void );
+void ServersShutdown( void );
+void ServersThink( double time );
+void ServersCancel( void );
+
+// Get list and get server info from each
+void ServersList( void );
+
+// Query for IP / IPX LAN servers
+void BroadcastServersList( int clearpending );
+
+void ServerPing( int server );
+void ServerRules( int server );
+void ServerPlayers( int server );
+
+int ServersGetCount( void );
+const char *ServersGetInfo( int server );
+int ServersIsQuerying( void );
+void SortServers( const char *fieldname );
+
#endif // HUD_SERVERSH
\ No newline at end of file
diff --git a/main/source/cl_dll/hud_servers_priv.h b/main/source/cl_dll/hud_servers_priv.h
index ed71367d..0fb41c13 100644
--- a/main/source/cl_dll/hud_servers_priv.h
+++ b/main/source/cl_dll/hud_servers_priv.h
@@ -1,91 +1,91 @@
-#if !defined( HUD_SERVERS_PRIVH )
-#define HUD_SERVERS_PRIVH
-#pragma once
-
-#include "common/netadr.h"
-
-class CHudServers
-{
-public:
- typedef struct request_s
- {
- struct request_s *next;
- netadr_t remote_address;
- int context;
- } request_t;
-
- typedef struct server_s
- {
- struct server_s *next;
- netadr_t remote_address;
- char *info;
- int ping;
- } server_t;
-
- CHudServers();
- ~CHudServers();
-
- void Think( double time );
- void QueryThink( void );
- int isQuerying( void );
-
- int LoadMasterAddresses( int maxservers, int *count, netadr_t *padr );
-
- void RequestList( void );
- void RequestBroadcastList( int clearpending );
-
- void ServerPing( int server );
- void ServerRules( int server );
- void ServerPlayers( int server );
-
- void CancelRequest( void );
-
- int CompareServers( server_t *p1, server_t *p2 );
-
- void ClearServerList( server_t **ppList );
- void ClearRequestList( request_t **ppList );
-
- void AddServer( server_t **ppList, server_t *p );
-
- void RemoveServerFromList( request_t **ppList, request_t *item );
-
- request_t *FindRequest( int context, request_t *pList );
-
- int ServerListSize( void );
- char *GetServerInfo( int server );
- int GetServerCount( void );
- void SortServers( const char *fieldname );
-
- void ListResponse( struct net_response_s *response );
- void ServerResponse( struct net_response_s *response );
- void PingResponse( struct net_response_s *response );
- void RulesResponse( struct net_response_s *response );
- void PlayersResponse( struct net_response_s *response );
-private:
-
- server_t *GetServer( int server );
-
- //
- char m_szToken[ 1024 ];
- int m_nRequesting;
- int m_nDone;
-
- double m_dStarted;
-
- request_t *m_pServerList;
- request_t *m_pActiveList;
-
- server_t *m_pServers;
-
- int m_nServerCount;
-
- int m_nActiveQueries;
- int m_nQuerying;
- double m_fElapsed;
-
- request_t *m_pPingRequest;
- request_t *m_pRulesRequest;
- request_t *m_pPlayersRequest;
-};
-
+#if !defined( HUD_SERVERS_PRIVH )
+#define HUD_SERVERS_PRIVH
+#pragma once
+
+#include "common/netadr.h"
+
+class CHudServers
+{
+public:
+ typedef struct request_s
+ {
+ struct request_s *next;
+ netadr_t remote_address;
+ int context;
+ } request_t;
+
+ typedef struct server_s
+ {
+ struct server_s *next;
+ netadr_t remote_address;
+ char *info;
+ int ping;
+ } server_t;
+
+ CHudServers();
+ ~CHudServers();
+
+ void Think( double time );
+ void QueryThink( void );
+ int isQuerying( void );
+
+ int LoadMasterAddresses( int maxservers, int *count, netadr_t *padr );
+
+ void RequestList( void );
+ void RequestBroadcastList( int clearpending );
+
+ void ServerPing( int server );
+ void ServerRules( int server );
+ void ServerPlayers( int server );
+
+ void CancelRequest( void );
+
+ int CompareServers( server_t *p1, server_t *p2 );
+
+ void ClearServerList( server_t **ppList );
+ void ClearRequestList( request_t **ppList );
+
+ void AddServer( server_t **ppList, server_t *p );
+
+ void RemoveServerFromList( request_t **ppList, request_t *item );
+
+ request_t *FindRequest( int context, request_t *pList );
+
+ int ServerListSize( void );
+ char *GetServerInfo( int server );
+ int GetServerCount( void );
+ void SortServers( const char *fieldname );
+
+ void ListResponse( struct net_response_s *response );
+ void ServerResponse( struct net_response_s *response );
+ void PingResponse( struct net_response_s *response );
+ void RulesResponse( struct net_response_s *response );
+ void PlayersResponse( struct net_response_s *response );
+private:
+
+ server_t *GetServer( int server );
+
+ //
+ char m_szToken[ 1024 ];
+ int m_nRequesting;
+ int m_nDone;
+
+ double m_dStarted;
+
+ request_t *m_pServerList;
+ request_t *m_pActiveList;
+
+ server_t *m_pServers;
+
+ int m_nServerCount;
+
+ int m_nActiveQueries;
+ int m_nQuerying;
+ double m_fElapsed;
+
+ request_t *m_pPingRequest;
+ request_t *m_pRulesRequest;
+ request_t *m_pPlayersRequest;
+};
+
#endif // HUD_SERVERS_PRIVH
\ No newline at end of file
diff --git a/main/source/cl_dll/hud_spectator.cpp b/main/source/cl_dll/hud_spectator.cpp
index 5ce8fb4f..391a0657 100644
--- a/main/source/cl_dll/hud_spectator.cpp
+++ b/main/source/cl_dll/hud_spectator.cpp
@@ -1,1953 +1,1953 @@
-//========= Copyright � 1996-2002, Valve LLC, All rights reserved. ============
-//
-// Purpose:
-//
-// $NoKeywords: $
-//=============================================================================
-
-#include "hud.h"
-#include "cl_util.h"
-#include "common/cl_entity.h"
-#include "common/triangleapi.h"
-#include "vgui_TeamFortressViewport.h"
-#include "vgui_SpectatorPanel.h"
-#include "common/hltv.h"
-
-#include "pm_shared/pm_shared.h"
-#include "pm_shared/pm_defs.h"
-#include "common/pmtrace.h"
-#include "common/entity_types.h"
-
-// these are included for the math functions
-#include "common/com_model.h"
-#include "common/demo_api.h"
-#include "common/event_api.h"
-#include "studio_util.h"
-#include "common/screenfade.h"
-#include "util/STLUtil.h"
-#include "mod/AvHTitles.h"
-#include "mod/AvHSprites.h"
-
-#pragma warning(disable: 4244)
-
-extern int iJumpSpectator;
-extern float vJumpOrigin[3];
-extern float vJumpAngles[3];
-
-extern void V_GetInEyePos(int entity, float * origin, float * angles );
-extern void V_ResetChaseCam();
-extern void V_GetChasePos(int target, float * cl_angles, float * origin, float * angles);
-extern void VectorAngles( const float *forward, float *angles );
-extern "C" void NormalizeAngles( float *angles );
-extern float * GetClientColor( int clientIndex );
-
-extern vec3_t v_origin; // last view origin
-extern vec3_t v_angles; // last view angle
-extern vec3_t v_cl_angles; // last client/mouse angle
-extern vec3_t v_sim_org; // last sim origin
-
-void SpectatorMode(void)
-{
-
- if ( gEngfuncs.Cmd_Argc() <= 1 )
- {
- gEngfuncs.Con_Printf( "usage: spec_mode \n" );
- return;
- }
-
- // SetModes() will decide if command is executed on server or local
- if ( gEngfuncs.Cmd_Argc() == 2 )
- gHUD.m_Spectator.SetMode( atoi( gEngfuncs.Cmd_Argv(1) ));
-
- //else if ( gEngfuncs.Cmd_Argc() == 3 )
- // gHUD.m_Spectator.SetMode( atoi( gEngfuncs.Cmd_Argv(1) ), atoi( gEngfuncs.Cmd_Argv(2) ) );
-}
-
-void SpectatorSpray(void)
-{
- vec3_t forward;
- char string[128];
-
- if ( !gEngfuncs.IsSpectateOnly() )
- return;
-
- AngleVectors(v_angles,forward,NULL,NULL);
- VectorScale(forward, 128, forward);
- VectorAdd(forward, v_origin, forward);
- pmtrace_t * trace = gEngfuncs.PM_TraceLine( v_origin, forward, PM_TRACELINE_PHYSENTSONLY, 2, -1 );
- if ( trace->fraction != 1.0 )
- {
- sprintf(string, "drc_spray %.2f %.2f %.2f %i",
- trace->endpos[0], trace->endpos[1], trace->endpos[2], trace->ent );
- gEngfuncs.pfnServerCmd(string);
- }
-
-}
-void SpectatorHelp(void)
-{
- if ( gViewPort )
- {
- gViewPort->ShowVGUIMenu( MENU_SPECHELP );
- }
- else
- {
- char *text = CHudTextMessage::BufferedLocaliseTextString( "#Spec_Help_Text" );
-
- if ( text )
- {
- while ( *text )
- {
- if ( *text != 13 )
- gEngfuncs.Con_Printf( "%c", *text );
- text++;
- }
- }
- }
-}
-
-void SpectatorMenu( void )
-{
- if ( gEngfuncs.Cmd_Argc() <= 1 )
- {
- gEngfuncs.Con_Printf( "usage: spec_menu <0|1>\n" );
- return;
- }
-
- gViewPort->m_pSpectatorPanel->ShowMenu( atoi( gEngfuncs.Cmd_Argv(1))!=0 );
-}
-
-void ToggleScores( void )
-{
- if ( gViewPort )
- {
- if (gViewPort->IsScoreBoardVisible() )
- {
- gViewPort->HideScoreBoard();
- }
- else
- {
- gViewPort->ShowScoreBoard();
- }
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-int CHudSpectator::Init()
-{
- gHUD.AddHudElem(this);
-
- m_iFlags |= HUD_ACTIVE;
- m_flNextObserverInput = 0.0f;
- m_zoomDelta = 0.0f;
- m_moveDelta = 0.0f;
- iJumpSpectator = 0;
-
- memset( &m_OverviewData, 0, sizeof(m_OverviewData));
- memset( &m_OverviewEntities, 0, sizeof(m_OverviewEntities));
- m_lastPrimaryObject = m_lastSecondaryObject = 0;
-
- gEngfuncs.pfnAddCommand ("spec_mode", SpectatorMode );
- gEngfuncs.pfnAddCommand ("spec_decal", SpectatorSpray );
- gEngfuncs.pfnAddCommand ("spec_help", SpectatorHelp );
- gEngfuncs.pfnAddCommand ("spec_menu", SpectatorMenu );
- gEngfuncs.pfnAddCommand ("togglescores", ToggleScores );
-
- m_drawnames = gEngfuncs.pfnRegisterVariable("spec_drawnames","1",0);
- m_drawcone = gEngfuncs.pfnRegisterVariable("spec_drawcone","1",0);
- m_drawstatus = gEngfuncs.pfnRegisterVariable("spec_drawstatus","1",0);
- m_autoDirector = gEngfuncs.pfnRegisterVariable("spec_autodirector","1",0);
-
- // Removed by mmcguire.
- m_overviewMode = false;
- //m_overview = gEngfuncs.pfnRegisterVariable("spec_overview","1",0);
- //m_pip = gEngfuncs.pfnRegisterVariable("spec_pip","1",0);
-
- if ( !m_drawnames || !m_drawcone || !m_drawstatus || !m_autoDirector /*|| !m_pip*/)
- {
- gEngfuncs.Con_Printf("ERROR! Couldn't register all spectator variables.\n");
- return 0;
- }
-
- return 1;
-}
-
-
-//-----------------------------------------------------------------------------
-// UTIL_StringToVector originally from ..\dlls\util.cpp, slightly changed
-//-----------------------------------------------------------------------------
-
-void UTIL_StringToVector( float * pVector, const char *pString )
-{
- char *pstr, *pfront, tempString[128];
- int j;
-
- strcpy( tempString, pString );
- pstr = pfront = tempString;
-
- for ( j = 0; j < 3; j++ )
- {
- pVector[j] = atof( pfront );
-
- while ( *pstr && *pstr != ' ' )
- pstr++;
- if (!*pstr)
- break;
- pstr++;
- pfront = pstr;
- }
-
- if (j < 2)
- {
- for (j = j+1;j < 3; j++)
- pVector[j] = 0;
- }
-}
-
-int UTIL_FindEntityInMap(char * name, float * origin, float * angle)
-{
- int n,found = 0;
- char keyname[256];
- char token[1024];
-
- cl_entity_t * pEnt = gEngfuncs.GetEntityByIndex( 0 ); // get world model
-
- if ( !pEnt ) return 0;
-
- if ( !pEnt->model ) return 0;
-
- char * data = pEnt->model->entities;
-
- while (data)
- {
- data = gEngfuncs.COM_ParseFile(data, token);
-
- if ( (token[0] == '}') || (token[0]==0) )
- break;
-
- if (!data)
- {
- gEngfuncs.Con_DPrintf("UTIL_FindEntityInMap: EOF without closing brace\n");
- return 0;
- }
-
- if (token[0] != '{')
- {
- gEngfuncs.Con_DPrintf("UTIL_FindEntityInMap: expected {\n");
- return 0;
- }
-
- // we parse the first { now parse entities properties
-
- while ( 1 )
- {
- // parse key
- data = gEngfuncs.COM_ParseFile(data, token);
- if (token[0] == '}')
- break; // finish parsing this entity
-
- if (!data)
- {
- gEngfuncs.Con_DPrintf("UTIL_FindEntityInMap: EOF without closing brace\n");
- return 0;
- };
-
- strcpy (keyname, token);
-
- // another hack to fix keynames with trailing spaces
- n = (int)strlen(keyname);
- while (n && keyname[n-1] == ' ')
- {
- keyname[n-1] = 0;
- n--;
- }
-
- // parse value
- data = gEngfuncs.COM_ParseFile(data, token);
- if (!data)
- {
- gEngfuncs.Con_DPrintf("UTIL_FindEntityInMap: EOF without closing brace\n");
- return 0;
- };
-
- if (token[0] == '}')
- {
- gEngfuncs.Con_DPrintf("UTIL_FindEntityInMap: closing brace without data");
- return 0;
- }
-
- if (!strcmp(keyname,"classname"))
- {
- if (!strcmp(token, name ))
- {
- found = 1; // thats our entity
- }
- };
-
- if( !strcmp( keyname, "angle" ) )
- {
- float y = atof( token );
-
- if (y >= 0)
- {
- angle[0] = 0.0f;
- angle[1] = y;
- }
- else if ((int)y == -1)
- {
- angle[0] = -90.0f;
- angle[1] = 0.0f;;
- }
- else
- {
- angle[0] = 90.0f;
- angle[1] = 0.0f;
- }
-
- angle[2] = 0.0f;
- }
-
- if( !strcmp( keyname, "angles" ) )
- {
- UTIL_StringToVector(angle, token);
- }
-
- if (!strcmp(keyname,"origin"))
- {
- UTIL_StringToVector(origin, token);
-
- };
-
- } // while (1)
-
- if (found)
- return 1;
-
- }
-
- return 0; // we search all entities, but didn't found the correct
-
-}
-
-//-----------------------------------------------------------------------------
-// SetSpectatorStartPosition():
-// Get valid map position and 'beam' spectator to this position
-//-----------------------------------------------------------------------------
-
-void CHudSpectator::SetSpectatorStartPosition()
-{
- // search for info_player start
- if ( UTIL_FindEntityInMap( "trigger_camera", m_cameraOrigin, m_cameraAngles ) )
- iJumpSpectator = 1;
-
- else if ( UTIL_FindEntityInMap( "info_player_start", m_cameraOrigin, m_cameraAngles ) )
- iJumpSpectator = 1;
-
- else if ( UTIL_FindEntityInMap( "info_player_deathmatch", m_cameraOrigin, m_cameraAngles ) )
- iJumpSpectator = 1;
-
- else if ( UTIL_FindEntityInMap( "info_player_coop", m_cameraOrigin, m_cameraAngles ) )
- iJumpSpectator = 1;
- else
- {
- // jump to 0,0,0 if no better position was found
- VectorCopy(vec3_origin, m_cameraOrigin);
- VectorCopy(vec3_origin, m_cameraAngles);
- }
-
- VectorCopy(m_cameraOrigin, vJumpOrigin);
- VectorCopy(m_cameraAngles, vJumpAngles);
-
- iJumpSpectator = 1; // jump anyway
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Loads new icons
-//-----------------------------------------------------------------------------
-int CHudSpectator::VidInit()
-{
- m_hsprPlayerMarine = SPR_Load("sprites/iplayerm.spr");
- m_hsprPlayerAlien = SPR_Load("sprites/iplayera.spr");
- m_hsprPlayerDead = SPR_Load("sprites/iplayerdead.spr");
- m_hsprUnkownMap = SPR_Load("sprites/tile.spr");
- //m_hsprBeam = SPR_Load("sprites/laserbeam.spr");
- //m_hsprCamera = SPR_Load("sprites/camera.spr");
- m_hCrosshair = SPR_Load("sprites/crosshairs.spr");
- m_hsprWhite = SPR_Load(kWhiteSprite);
-
- return 1;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-// Input : flTime -
-// intermission -
-//-----------------------------------------------------------------------------
-int CHudSpectator::Draw(float flTime)
-{
-
- // draw only in spectator mode
- if ( !g_iUser1 )
- return 0;
-// string error;
-// gHUD.Update( flTime, error);
-
- // Removed by mmcguire.
- /*
- // if user pressed zoom, aplly changes
- if ( (m_zoomDelta != 0.0f) && ( g_iUser1 == OBS_MAP_FREE ) )
- {
- m_mapZoom += m_zoomDelta;
-
- if ( m_mapZoom > 3.0f )
- m_mapZoom = 3.0f;
-
- if ( m_mapZoom < 0.5f )
- m_mapZoom = 0.5f;
- }
-
- // if user moves in map mode, change map origin
- if ( (m_moveDelta != 0.0f) && (g_iUser1 != OBS_ROAMING) )
- {
- vec3_t right;
- AngleVectors(v_angles, NULL, right, NULL);
- VectorNormalize(right);
- VectorScale(right, m_moveDelta, right );
-
- VectorAdd( m_mapOrigin, right, m_mapOrigin )
-
- }
- */
-
- //DrawOverviewMap();
-
-/*
- if (!IsInOverviewMode())
- {
- return 0;
- }
-
- if (m_hsprWhite != NULL)
- {
-
- float bgColor[] = { 0.1, 0.1, 0.1, 1 };
- float borderColor[] = { 1, 1, 1, 1 };
-
- gEngfuncs.pTriAPI->RenderMode(kRenderNormal);
- gEngfuncs.pTriAPI->CullFace(TRI_NONE);
-
- gEngfuncs.pTriAPI->SpriteTexture((struct model_s*)(gEngfuncs.GetSpritePointer(m_hsprWhite)), 0);
-
- float gammaScale = 1.0f / gHUD.GetGammaSlope();
-
- // Draw the border on the overview map and the inset view.
-
- gEngfuncs.pTriAPI->RenderMode(kRenderNormal);
- gEngfuncs.pTriAPI->CullFace(TRI_NONE);
-
- gEngfuncs.pTriAPI->SpriteTexture((struct model_s*)(gEngfuncs.GetSpritePointer(m_hsprWhite)), 0);
- gEngfuncs.pTriAPI->Color4f(gammaScale * borderColor[0], gammaScale * borderColor[1], gammaScale * borderColor[2], borderColor[3]);
-
- gEngfuncs.pTriAPI->Begin(TRI_LINES);
-
- int insetX1 = XRES(m_OverviewData.insetWindowX);
- int insetY1 = YRES(m_OverviewData.insetWindowY);
- int insetX2 = insetX1 + XRES(m_OverviewData.insetWindowWidth);
- int insetY2 = insetY1 + YRES(m_OverviewData.insetWindowHeight);
-
- gEngfuncs.pTriAPI->Vertex3f(insetX1, insetY1, 1);
- gEngfuncs.pTriAPI->Vertex3f(insetX2, insetY1, 1);
-
- gEngfuncs.pTriAPI->Vertex3f(insetX2, insetY1, 1);
- gEngfuncs.pTriAPI->Vertex3f(insetX2, insetY2, 1);
-
- gEngfuncs.pTriAPI->Vertex3f(insetX2, insetY2, 1);
- gEngfuncs.pTriAPI->Vertex3f(insetX1, insetY2, 1);
-
- gEngfuncs.pTriAPI->Vertex3f(insetX1, insetY2, 1);
- gEngfuncs.pTriAPI->Vertex3f(insetX1, insetY1, 1);
-
- gEngfuncs.pTriAPI->End();
-
- }*/
-
-
-
- /*
- // Only draw the icon names only if map mode is in Main Mode
- if ( g_iUser1 < OBS_MAP_FREE )
- return 1;
-
- if ( !m_drawnames->value )
- return 1;
-
- // make sure we have player info
- gViewPort->GetAllPlayersInfo();
- */
-
- return 1;
-
-}
-
-bool CHudSpectator::IsInOverviewMode() const
-{
- return g_iUser1 && m_overviewMode && gHUD.GetIsNSMode();
-}
-
-void CHudSpectator::SetOverviewMode(bool overviewMode)
-{
- m_overviewMode = overviewMode;
-}
-
-void CHudSpectator::DrawOverviewMap()
-{
-
- // draw only in spectator mode
- if (!IsInOverviewMode())
- {
- return;
- }
-
- AvHOverviewMap& theOverviewMap = gHUD.GetOverviewMap();
-
- AvHOverviewMap::DrawInfo theDrawInfo;
-
- theDrawInfo.mX = XRES(m_OverviewData.insetWindowX + m_OverviewData.insetWindowWidth + 4);
- theDrawInfo.mY = YRES(SPECTATOR_PANEL_HEIGHT + 4);
- theDrawInfo.mWidth = ScreenWidth() - theDrawInfo.mX - XRES(4);
- theDrawInfo.mHeight = ScreenHeight() - YRES(SPECTATOR_PANEL_HEIGHT + 4) - theDrawInfo.mY;
- theDrawInfo.mZoomScale = 1.0f;
- AvHMapExtents theMapExtents;
- theOverviewMap.GetMapExtents(theMapExtents);
-
- theDrawInfo.mFullScreen = true;
-
- float worldWidth = theMapExtents.GetMaxMapX() - theMapExtents.GetMinMapX();
- float worldHeight = theMapExtents.GetMaxMapY() - theMapExtents.GetMinMapY();
-
- float xScale;
- float yScale;
-
- float aspect1 = worldWidth / worldHeight;
- float aspect2 = ((float)theDrawInfo.mWidth) / theDrawInfo.mHeight;
-
- if (aspect1 > aspect2)
- {
- xScale = 1;
- yScale = 1 / aspect2;
- }
- else
- {
- xScale = aspect2;
- yScale = 1;
- }
-
- float centerX = (theMapExtents.GetMinMapX() + theMapExtents.GetMaxMapX()) / 2;
- float centerY = (theMapExtents.GetMinMapY() + theMapExtents.GetMaxMapY()) / 2;
-
- theDrawInfo.mViewWorldMinX = centerX - worldWidth * xScale * 0.5;
- theDrawInfo.mViewWorldMinY = centerY - worldHeight * yScale * 0.5;
- theDrawInfo.mViewWorldMaxX = centerX + worldWidth * xScale * 0.5;
- theDrawInfo.mViewWorldMaxY = centerY + worldHeight * yScale * 0.5;
-
- if (m_hsprWhite != NULL)
- {
-
- float bgColor[] = { 0.1, 0.1, 0.1, 1 };
- float borderColor[] = { 1, 1, 1, 1 };
-
- gEngfuncs.pTriAPI->RenderMode(kRenderNormal);
- gEngfuncs.pTriAPI->CullFace(TRI_NONE);
-
- gEngfuncs.pTriAPI->SpriteTexture((struct model_s*)(gEngfuncs.GetSpritePointer(m_hsprWhite)), 0);
- float gammaScale = 1.0f / gHUD.GetGammaSlope();
-
- // Draw the background.
-
- gEngfuncs.pTriAPI->Color4f(gammaScale * bgColor[0], gammaScale * bgColor[1], gammaScale * bgColor[2], bgColor[3]);
-
- gEngfuncs.pTriAPI->Begin(TRI_QUADS);
-
- gEngfuncs.pTriAPI->Vertex3f(theDrawInfo.mX, theDrawInfo.mY, 1);
- gEngfuncs.pTriAPI->Vertex3f(theDrawInfo.mX, theDrawInfo.mY + theDrawInfo.mHeight, 1);
- gEngfuncs.pTriAPI->Vertex3f(theDrawInfo.mX + theDrawInfo.mWidth, theDrawInfo.mY + theDrawInfo.mHeight, 1);
- gEngfuncs.pTriAPI->Vertex3f(theDrawInfo.mX + theDrawInfo.mWidth, theDrawInfo.mY, 1);
-
- gEngfuncs.pTriAPI->End();
-
- // Draw the overview map.
-
- theOverviewMap.Draw(theDrawInfo);
-
- // Draw the border on the overview map and the inset view.
-
- gEngfuncs.pTriAPI->RenderMode(kRenderNormal);
- gEngfuncs.pTriAPI->CullFace(TRI_NONE);
-
- gEngfuncs.pTriAPI->SpriteTexture((struct model_s*)(gEngfuncs.GetSpritePointer(m_hsprWhite)), 0);
- gEngfuncs.pTriAPI->Color4f(gammaScale * borderColor[0], gammaScale * borderColor[1], gammaScale * borderColor[2], borderColor[3]);
-
- gEngfuncs.pTriAPI->Begin(TRI_LINES);
-
- gEngfuncs.pTriAPI->Vertex3f(theDrawInfo.mX, theDrawInfo.mY, 1);
- gEngfuncs.pTriAPI->Vertex3f(theDrawInfo.mX, theDrawInfo.mY + theDrawInfo.mHeight, 1);
-
- gEngfuncs.pTriAPI->Vertex3f(theDrawInfo.mX, theDrawInfo.mY + theDrawInfo.mHeight, 1);
- gEngfuncs.pTriAPI->Vertex3f(theDrawInfo.mX + theDrawInfo.mWidth, theDrawInfo.mY + theDrawInfo.mHeight, 1);
-
- gEngfuncs.pTriAPI->Vertex3f(theDrawInfo.mX + theDrawInfo.mWidth, theDrawInfo.mY + theDrawInfo.mHeight, 1);
- gEngfuncs.pTriAPI->Vertex3f(theDrawInfo.mX + theDrawInfo.mWidth, theDrawInfo.mY, 1);
-
- gEngfuncs.pTriAPI->Vertex3f(theDrawInfo.mX + theDrawInfo.mWidth, theDrawInfo.mY, 1);
- gEngfuncs.pTriAPI->Vertex3f(theDrawInfo.mX, theDrawInfo.mY, 1);
-
- int insetX1 = XRES(m_OverviewData.insetWindowX);
- int insetY1 = YRES(m_OverviewData.insetWindowY);
- int insetX2 = insetX1 + XRES(m_OverviewData.insetWindowWidth);
- int insetY2 = insetY1 + YRES(m_OverviewData.insetWindowHeight);
-
- gEngfuncs.pTriAPI->Vertex3f(insetX1, insetY1, 1);
- gEngfuncs.pTriAPI->Vertex3f(insetX2, insetY1, 1);
-
- gEngfuncs.pTriAPI->Vertex3f(insetX2, insetY1, 1);
- gEngfuncs.pTriAPI->Vertex3f(insetX2, insetY2, 1);
-
- gEngfuncs.pTriAPI->Vertex3f(insetX2, insetY2, 1);
- gEngfuncs.pTriAPI->Vertex3f(insetX1, insetY2, 1);
-
- gEngfuncs.pTriAPI->Vertex3f(insetX1, insetY2, 1);
- gEngfuncs.pTriAPI->Vertex3f(insetX1, insetY1, 1);
-
- gEngfuncs.pTriAPI->End();
-
- }
-
-
-}
-
-#include "parsemsg.h"
-void CHudSpectator::DirectorMessage( int iSize, void *pbuf )
-{
- float value;
- char * string;
-
- BEGIN_READ( pbuf, iSize );
-
- int cmd = READ_BYTE();
-
- switch ( cmd ) // director command byte
- {
- case DRC_CMD_START :
- // now we have to do some things clientside, since the proxy doesn't know our mod
- g_iPlayerClass = 0;
- g_iTeamNumber = 0;
-
- // fake a InitHUD & ResetHUD message
- gHUD.MsgFunc_InitHUD(NULL,0, NULL);
- gHUD.MsgFunc_ResetHUD(NULL, 0, NULL);
-
- break;
-
- case DRC_CMD_EVENT :
- m_lastPrimaryObject = READ_WORD();
- m_lastSecondaryObject = READ_WORD();
- m_iObserverFlags = READ_LONG();
-
- if ( m_autoDirector->value )
- {
- if ( (g_iUser2 != m_lastPrimaryObject) || (g_iUser3 != m_lastSecondaryObject) )
- V_ResetChaseCam();
-
- g_iUser2 = m_lastPrimaryObject;
- g_iUser3 = m_lastSecondaryObject;
- }
-
- break;
-
- case DRC_CMD_MODE :
- if ( m_autoDirector->value )
- {
- SetMode( READ_BYTE());
- }
- break;
-
- case DRC_CMD_CAMERA :
- if ( m_autoDirector->value )
- {
- vJumpOrigin[0] = READ_COORD(); // position
- vJumpOrigin[1] = READ_COORD();
- vJumpOrigin[2] = READ_COORD();
-
- vJumpAngles[0] = READ_COORD(); // view angle
- vJumpAngles[1] = READ_COORD();
- vJumpAngles[2] = READ_COORD();
-
- gEngfuncs.SetViewAngles( vJumpAngles );
-
- iJumpSpectator = 1;
- }
- break;
-
- case DRC_CMD_MESSAGE:
- {
- client_textmessage_t * msg = &m_HUDMessages[m_lastHudMessage];
-
- msg->effect = READ_BYTE(); // effect
-
- UnpackRGB( (int&)msg->r1, (int&)msg->g1, (int&)msg->b1, READ_LONG() ); // color
- msg->r2 = msg->r1;
- msg->g2 = msg->g1;
- msg->b2 = msg->b1;
- msg->a2 = msg->a1 = 0xFF; // not transparent
-
- msg->x = READ_FLOAT(); // x pos
- msg->y = READ_FLOAT(); // y pos
-
- msg->fadein = READ_FLOAT(); // fadein
- msg->fadeout = READ_FLOAT(); // fadeout
- msg->holdtime = READ_FLOAT(); // holdtime
- msg->fxtime = READ_FLOAT(); // fxtime;
-
- strncpy( m_HUDMessageText[m_lastHudMessage], READ_STRING(), 128 );
- m_HUDMessageText[m_lastHudMessage][127]=0; // text
-
- msg->pMessage = m_HUDMessageText[m_lastHudMessage];
- msg->pName = "HUD_MESSAGE";
-
- gHUD.m_Message.MessageAdd( msg->pName, gHUD.m_flTime);
-
- m_lastHudMessage++;
- m_lastHudMessage %= MAX_SPEC_HUD_MESSAGES;
-
- }
-
- break;
-
- case DRC_CMD_SOUND :
- string = READ_STRING();
- value = READ_FLOAT();
-
- gEngfuncs.pEventAPI->EV_PlaySound(0, v_origin, CHAN_BODY, string, value, ATTN_NORM, 0, PITCH_NORM );
-
- break;
-
- case DRC_CMD_TIMESCALE :
- value = READ_FLOAT();
- break;
-
-
-
- case DRC_CMD_STATUS:
- READ_LONG(); // total number of spectator slots
- m_iSpectatorNumber = READ_LONG(); // total number of spectator
- READ_WORD(); // total number of relay proxies
-
- gViewPort->UpdateSpectatorPanel();
- break;
-
- case DRC_CMD_BANNER:
- // gEngfuncs.Con_DPrintf("GUI: Banner %s\n",READ_STRING() ); // name of banner tga eg gfx/temp/7454562234563475.tga
- gViewPort->m_pSpectatorPanel->m_TopBanner->LoadImage( READ_STRING() );
- gViewPort->UpdateSpectatorPanel();
- break;
-
- case DRC_CMD_FADE:
- break;
-
- case DRC_CMD_STUFFTEXT:
- ClientCmd( READ_STRING() );
- break;
-
- default : gEngfuncs.Con_DPrintf("CHudSpectator::DirectorMessage: unknown command %i.\n", cmd );
- }
-}
-
-void CHudSpectator::FindNextPlayer(bool bReverse)
-{
- // MOD AUTHORS: Modify the logic of this function if you want to restrict the observer to watching
- // only a subset of the players. e.g. Make it check the target's team.
-
- int iStart;
- cl_entity_t * pEnt = NULL;
-
- // if we are NOT in HLTV mode, spectator targets are set on server
- if ( !gEngfuncs.IsSpectateOnly() )
- {
- char cmdstring[32];
- // forward command to server
- sprintf(cmdstring,"follownext %i",bReverse?1:0);
- gEngfuncs.pfnServerCmd(cmdstring);
- return;
- }
-
- if ( g_iUser2 )
- iStart = g_iUser2;
- else
- iStart = 1;
-
- g_iUser2 = 0;
-
- int iCurrent = iStart;
-
- int iDir = bReverse ? -1 : 1;
-
- // make sure we have player info
- gViewPort->GetAllPlayersInfo();
-
-
- do
- {
- iCurrent += iDir;
-
- // Loop through the clients
- if (iCurrent > MAX_PLAYERS)
- iCurrent = 1;
- if (iCurrent < 1)
- iCurrent = MAX_PLAYERS;
-
- pEnt = gEngfuncs.GetEntityByIndex( iCurrent );
-
- if ( !IsActivePlayer( pEnt ) )
- continue;
-
- // MOD AUTHORS: Add checks on target here.
-
- g_iUser2 = iCurrent;
- break;
-
- } while ( iCurrent != iStart );
-
- // Did we find a target?
- if ( !g_iUser2 )
- {
- gEngfuncs.Con_DPrintf( "No observer targets.\n" );
- // take save camera position
- VectorCopy(m_cameraOrigin, vJumpOrigin);
- VectorCopy(m_cameraAngles, vJumpAngles);
- }
- else
- {
- // use new entity position for roaming
- VectorCopy ( pEnt->origin, vJumpOrigin );
- VectorCopy ( pEnt->angles, vJumpAngles );
- }
- iJumpSpectator = 1;
-}
-
-void CHudSpectator::HandleButtonsDown( int ButtonPressed )
-{
- if ( !gViewPort )
- return;
-
- //Not in intermission.
- if ( gHUD.m_iIntermission )
- return;
-
- if ( !g_iUser1 )
- return; // dont do anything if not in spectator mode
-
- // don't handle buttons during normal demo playback
- if ( gEngfuncs.pDemoAPI->IsPlayingback() && !gEngfuncs.IsSpectateOnly() )
- return;
-
- int theNewMainMode = g_iUser1;
-
- // Jump changes main window modes
- if ( ButtonPressed & IN_JUMP )
- {
- bool theFirstPerson = (g_iUser1 == OBS_IN_EYE);
- bool theInOverviewMode = gHUD.m_Spectator.IsInOverviewMode();
-
- // NS
- if(gHUD.GetIsNSMode())
- {
- // First-person full -> chase camera full -> firstperson with overview -> chase camera with overview
- if(theFirstPerson && !theInOverviewMode)
- {
- gHUD.m_Spectator.SetMode(OBS_CHASE_LOCKED);
- //gHUD.m_Spectator.SetOverviewMode(false);
- }
- else if(!theFirstPerson && !theInOverviewMode)
- {
- gHUD.m_Spectator.SetMode(OBS_IN_EYE);
- gHUD.m_Spectator.SetOverviewMode(true);
- }
- else if(theFirstPerson && theInOverviewMode)
- {
- gHUD.m_Spectator.SetMode(OBS_CHASE_LOCKED);
- //gHUD.m_Spectator.SetOverviewMode(true);
- }
- else if(!theFirstPerson && theInOverviewMode)
- {
- gHUD.m_Spectator.SetMode(OBS_IN_EYE);
- gHUD.m_Spectator.SetOverviewMode(false);
- }
- }
- // Combat
- else
- {
- // First-person full -> chase camera full
- if(theFirstPerson)
- {
- gHUD.m_Spectator.SetMode(OBS_CHASE_LOCKED);
- gHUD.m_Spectator.SetOverviewMode(false);
- }
- else
- {
- gHUD.m_Spectator.SetMode(OBS_IN_EYE);
- gHUD.m_Spectator.SetOverviewMode(false);
- }
- }
- }
-
- //g_iUser1 = theNewMainMode;
-
- // Attack moves to the next player
- if ( ButtonPressed & (IN_MOVELEFT | IN_MOVERIGHT) )
- {
- FindNextPlayer( (ButtonPressed & IN_MOVELEFT) ? true:false );
-
-// if ( g_iUser1 == OBS_ROAMING )
-// {
-// gEngfuncs.SetViewAngles( vJumpAngles );
-// iJumpSpectator = 1;
-//
-// }
-
- // lease directed mode if player want to see another player
- m_autoDirector->value = 0.0f;
- }
-
-/*
- double time = gEngfuncs.GetClientTime();
-
- int newMainMode = g_iUser1;
- int newInsetMode = m_pip->value;
-
- // gEngfuncs.Con_Printf(" HandleButtons:%i\n", ButtonPressed );
- if ( !gViewPort )
- return;
-
- //Not in intermission.
- if ( gHUD.m_iIntermission )
- return;
-
- if ( !g_iUser1 )
- return; // dont do anything if not in spectator mode
-
- // don't handle buttons during normal demo playback
- if ( gEngfuncs.pDemoAPI->IsPlayingback() && !gEngfuncs.IsSpectateOnly() )
- return;
- // Slow down mouse clicks.
- if ( m_flNextObserverInput > time )
- return;
-
- // enable spectator screen
- if ( ButtonPressed & IN_DUCK )
- {
- gViewPort->m_pSpectatorPanel->ShowMenu(!gViewPort->m_pSpectatorPanel->m_menuVisible);
- }
-
- // 'Use' changes inset window mode
- if ( ButtonPressed & IN_USE )
- {
- newInsetMode = ToggleInset(true);
- }
-
- // if not in HLTV mode, buttons are handled server side
- if ( gEngfuncs.IsSpectateOnly() )
- {
- // changing target or chase mode not in overviewmode without inset window
-
- // Jump changes main window modes
- if ( ButtonPressed & IN_JUMP )
- {
- if ( g_iUser1 == OBS_CHASE_LOCKED )
- newMainMode = OBS_CHASE_FREE;
-
- else if ( g_iUser1 == OBS_CHASE_FREE )
- newMainMode = OBS_IN_EYE;
-
- else if ( g_iUser1 == OBS_IN_EYE )
- newMainMode = OBS_ROAMING;
-
- else if ( g_iUser1 == OBS_ROAMING )
- newMainMode = OBS_MAP_FREE;
-
- else if ( g_iUser1 == OBS_MAP_FREE )
- newMainMode = OBS_MAP_CHASE;
-
- else
- newMainMode = OBS_CHASE_FREE; // don't use OBS_CHASE_LOCKED anymore
- }
-
- // Attack moves to the next player
- if ( ButtonPressed & (IN_ATTACK | IN_ATTACK2) )
- {
- FindNextPlayer( (ButtonPressed & IN_ATTACK2) ? true:false );
-
- if ( g_iUser1 == OBS_ROAMING )
- {
- gEngfuncs.SetViewAngles( vJumpAngles );
- iJumpSpectator = 1;
-
- }
- // lease directed mode if player want to see another player
- m_autoDirector->value = 0.0f;
- }
- }
-
- SetModes(newMainMode, newInsetMode);
-
- if ( g_iUser1 == OBS_MAP_FREE )
- {
- if ( ButtonPressed & IN_FORWARD )
- m_zoomDelta = 0.01f;
-
- if ( ButtonPressed & IN_BACK )
- m_zoomDelta = -0.01f;
-
- if ( ButtonPressed & IN_MOVELEFT )
- m_moveDelta = -12.0f;
-
- if ( ButtonPressed & IN_MOVERIGHT )
- m_moveDelta = 12.0f;
- }
-
- m_flNextObserverInput = time + 0.2;
-*/
-
-}
-
-void CHudSpectator::HandleButtonsUp( int ButtonPressed )
-{
- if ( !gViewPort )
- return;
-
- if ( !gViewPort->m_pSpectatorPanel->isVisible() )
- return; // dont do anything if not in spectator mode
-
- if ( ButtonPressed & (IN_FORWARD | IN_BACK) )
- m_zoomDelta = 0.0f;
-
- if ( ButtonPressed & (IN_MOVELEFT | IN_MOVERIGHT) )
- m_moveDelta = 0.0f;
-}
-
-void CHudSpectator::SetMode(int iNewMainMode)
-{
- // if value == -1 keep old value
- if ( iNewMainMode == -1 )
- iNewMainMode = g_iUser1;
-
- // main modes ettings will override inset window settings
- if ( iNewMainMode != g_iUser1 )
- {
- // if we are NOT in HLTV mode, main spectator mode is set on server
- if ( !gEngfuncs.IsSpectateOnly() )
- {
- char cmdstring[32];
- // forward command to server
- sprintf(cmdstring,"specmode %i",iNewMainMode );
- gEngfuncs.pfnServerCmd(cmdstring);
- return;
- }
- else
- {
- if ( !g_iUser2 && (iNewMainMode !=OBS_ROAMING ) ) // make sure we have a target
- {
- // choose last Director object if still available
- if ( IsActivePlayer( gEngfuncs.GetEntityByIndex( m_lastPrimaryObject ) ) )
- {
- g_iUser2 = m_lastPrimaryObject;
- g_iUser3 = m_lastSecondaryObject;
- }
- else
- {
- FindNextPlayer(false); // find any target
- }
- }
-
- switch ( iNewMainMode )
- {
- case OBS_CHASE_LOCKED:
- g_iUser1 = OBS_CHASE_LOCKED;
- break;
-
- case OBS_CHASE_FREE:
- g_iUser1 = OBS_CHASE_FREE;
- break;
-
- case OBS_ROAMING : // jump to current vJumpOrigin/angle
- g_iUser1 = OBS_ROAMING;
- if ( g_iUser2 )
- {
- V_GetChasePos( g_iUser2, v_cl_angles, vJumpOrigin, vJumpAngles );
- gEngfuncs.SetViewAngles( vJumpAngles );
- iJumpSpectator = 1;
- }
- break;
-
- case OBS_IN_EYE:
- g_iUser1 = OBS_IN_EYE;
- break;
-
- /*
- case OBS_MAP_FREE : g_iUser1 = OBS_MAP_FREE;
- // reset user values
- m_mapZoom = m_OverviewData.zoom;
- m_mapOrigin = m_OverviewData.origin;
- break;
-
- case OBS_MAP_CHASE : g_iUser1 = OBS_MAP_CHASE;
- // reset user values
- m_mapZoom = m_OverviewData.zoom;
- m_mapOrigin = m_OverviewData.origin;
- break;
- */
- }
-
- if ( (g_iUser1 == OBS_IN_EYE) || (g_iUser1 == OBS_ROAMING) )
- {
- m_crosshairRect.left = 24;
- m_crosshairRect.top = 0;
- m_crosshairRect.right = 48;
- m_crosshairRect.bottom = 24;
-
- gHUD.SetCurrentCrosshair( m_hCrosshair, m_crosshairRect, 255, 255, 255 );
- }
- else
- {
- memset( &m_crosshairRect,0,sizeof(m_crosshairRect) );
- gHUD.SetCurrentCrosshair( 0, m_crosshairRect, 0, 0, 0 );
- }
-
- //char string[128];
- //sprintf(string, "#Spec_Mode%d", g_iUser1 );
- //sprintf(string, "%c%s", HUD_PRINTCENTER, CHudTextMessage::BufferedLocaliseTextString( string ));
- //gHUD.m_TextMessage.MsgFunc_TextMsg(NULL, strlen(string)+1, string );
- }
- }
-
- gViewPort->UpdateSpectatorPanel();
-}
-
-bool CHudSpectator::IsActivePlayer(cl_entity_t * ent)
-{
- return ( ent &&
- ent->player &&
- ent->curstate.solid != SOLID_NOT &&
- ent != gEngfuncs.GetLocalPlayer() &&
- g_PlayerInfoList[ent->index].name != NULL
- );
-}
-
-
-bool CHudSpectator::ParseOverviewFile( )
-{
- //char filename[255];
- //char levelname[255];
- //char token[1024];
- //float height;
-
- char *pfile = NULL;
-
- memset( &m_OverviewData, 0, sizeof(m_OverviewData));
-
- // fill in standrd values
- m_OverviewData.insetWindowX = 4; // upper left corner
- m_OverviewData.insetWindowY = 4 + SPECTATOR_PANEL_HEIGHT;
- m_OverviewData.insetWindowHeight = 180;
- m_OverviewData.insetWindowWidth = 240;
- m_OverviewData.origin[0] = 0.0f;
- m_OverviewData.origin[1] = 0.0f;
- m_OverviewData.origin[2] = 0.0f;
- m_OverviewData.zoom = 1.0f;
- m_OverviewData.layers = 0;
- m_OverviewData.layersHeights[0] = 0.0f;
- strcpy( m_OverviewData.map, gEngfuncs.pfnGetLevelName() );
-
- if ( strlen( m_OverviewData.map ) == 0 )
- return false; // not active yet
-
- /*
- strcpy(levelname, m_OverviewData.map + 5);
- levelname[strlen(levelname)-4] = 0;
-
- sprintf(filename, "overviews/%s.txt", levelname );
-
- pfile = (char *)gEngfuncs.COM_LoadFile( filename, 5, NULL);
-
- if (!pfile)
- {
- gEngfuncs.Con_Printf("Couldn't open file %s. Using default values for overiew mode.\n", filename );
- return false;
- }
-
- while (true)
- {
- pfile = gEngfuncs.COM_ParseFile(pfile, token);
-
- if (!pfile)
- break;
-
- if ( !stricmp( token, "global" ) )
- {
- // parse the global data
- pfile = gEngfuncs.COM_ParseFile(pfile, token);
- if ( stricmp( token, "{" ) )
- {
- gEngfuncs.Con_Printf("Error parsing overview file %s. (expected { )\n", filename );
- return false;
- }
-
- pfile = gEngfuncs.COM_ParseFile(pfile,token);
-
- while (stricmp( token, "}") )
- {
- if ( !stricmp( token, "zoom" ) )
- {
- pfile = gEngfuncs.COM_ParseFile(pfile,token);
- m_OverviewData.zoom = atof( token );
- }
- else if ( !stricmp( token, "origin" ) )
- {
- pfile = gEngfuncs.COM_ParseFile(pfile, token);
- m_OverviewData.origin[0] = atof( token );
- pfile = gEngfuncs.COM_ParseFile(pfile,token);
- m_OverviewData.origin[1] = atof( token );
- pfile = gEngfuncs.COM_ParseFile(pfile, token);
- m_OverviewData.origin[2] = atof( token );
- }
- else if ( !stricmp( token, "rotated" ) )
- {
- pfile = gEngfuncs.COM_ParseFile(pfile,token);
- m_OverviewData.rotated = atoi( token );
- }
- else if ( !stricmp( token, "inset" ) )
- {
-
- // Removed by mmcguire.
- // This isn't supported anymore.
- pfile = gEngfuncs.COM_ParseFile(pfile,token);
- //m_OverviewData.insetWindowX = atof( token );
- pfile = gEngfuncs.COM_ParseFile(pfile,token);
- //m_OverviewData.insetWindowY = atof( token );
- pfile = gEngfuncs.COM_ParseFile(pfile,token);
- //m_OverviewData.insetWindowWidth = atof( token );
- pfile = gEngfuncs.COM_ParseFile(pfile,token);
- //m_OverviewData.insetWindowHeight = atof( token );
-
- }
- else
- {
- gEngfuncs.Con_Printf("Error parsing overview file %s. (%s unkown)\n", filename, token );
- return false;
- }
-
- pfile = gEngfuncs.COM_ParseFile(pfile,token); // parse next token
-
- }
- }
- else if ( !stricmp( token, "layer" ) )
- {
- // parse a layer data
-
- if ( m_OverviewData.layers == OVERVIEW_MAX_LAYERS )
- {
- gEngfuncs.Con_Printf("Error parsing overview file %s. ( too many layers )\n", filename );
- return false;
- }
-
- pfile = gEngfuncs.COM_ParseFile(pfile,token);
-
-
- if ( stricmp( token, "{" ) )
- {
- gEngfuncs.Con_Printf("Error parsing overview file %s. (expected { )\n", filename );
- return false;
- }
-
- pfile = gEngfuncs.COM_ParseFile(pfile,token);
-
- while (stricmp( token, "}") )
- {
- if ( !stricmp( token, "image" ) )
- {
- pfile = gEngfuncs.COM_ParseFile(pfile,token);
- strcpy(m_OverviewData.layersImages[ m_OverviewData.layers ], token);
-
-
- }
- else if ( !stricmp( token, "height" ) )
- {
- pfile = gEngfuncs.COM_ParseFile(pfile,token);
- height = atof(token);
- m_OverviewData.layersHeights[ m_OverviewData.layers ] = height;
- }
- else
- {
- gEngfuncs.Con_Printf("Error parsing overview file %s. (%s unkown)\n", filename, token );
- return false;
- }
-
- pfile = gEngfuncs.COM_ParseFile(pfile,token); // parse next token
- }
-
- m_OverviewData.layers++;
-
- }
- }
-
- gEngfuncs.COM_FreeFile( pfile );
- */
-
- m_mapZoom = m_OverviewData.zoom;
- m_mapOrigin = m_OverviewData.origin;
-
- return true;
-
-}
-
-void CHudSpectator::LoadMapSprites()
-{
- // right now only support for one map layer
- if (m_OverviewData.layers > 0 )
- {
- m_MapSprite = gEngfuncs.LoadMapSprite( m_OverviewData.layersImages[0] );
- }
- else
- m_MapSprite = NULL; // the standard "unkown map" sprite will be used instead
-}
-
-void CHudSpectator::DrawOverviewLayer()
-{
- float screenaspect, xs, ys, xStep, yStep, x,y,z;
- int ix,iy,i,xTiles,yTiles,frame;
-
- qboolean hasMapImage = m_MapSprite?TRUE:FALSE;
- model_t * dummySprite = (struct model_s *)gEngfuncs.GetSpritePointer( m_hsprUnkownMap);
-
- if ( hasMapImage)
- {
- i = m_MapSprite->numframes / (4*3);
- i = sqrt((float)i);
- xTiles = i*4;
- yTiles = i*3;
- }
- else
- {
- xTiles = 8;
- yTiles = 6;
- }
-
-
- screenaspect = 4.0f/3.0f;
-
-
- xs = m_OverviewData.origin[0];
- ys = m_OverviewData.origin[1];
- z = ( 90.0f - v_angles[0] ) / 90.0f;
- z *= m_OverviewData.layersHeights[0]; // gOverviewData.z_min - 32;
-
- // i = r_overviewTexture + ( layer*OVERVIEW_X_TILES*OVERVIEW_Y_TILES );
-
- gEngfuncs.pTriAPI->RenderMode( kRenderTransTexture );
- gEngfuncs.pTriAPI->CullFace( TRI_NONE );
- gEngfuncs.pTriAPI->Color4f( 1.0, 1.0, 1.0, 1.0 );
-
- frame = 0;
-
-
- // rotated view ?
- if ( m_OverviewData.rotated )
- {
- xStep = (2*4096.0f / m_OverviewData.zoom ) / xTiles;
- yStep = -(2*4096.0f / (m_OverviewData.zoom* screenaspect) ) / yTiles;
-
- y = ys + (4096.0f / (m_OverviewData.zoom * screenaspect));
-
- for (iy = 0; iy < yTiles; iy++)
- {
- x = xs - (4096.0f / (m_OverviewData.zoom));
-
- for (ix = 0; ix < xTiles; ix++)
- {
- if (hasMapImage)
- gEngfuncs.pTriAPI->SpriteTexture( m_MapSprite, frame );
- else
- gEngfuncs.pTriAPI->SpriteTexture( dummySprite, 0 );
-
- gEngfuncs.pTriAPI->Begin( TRI_QUADS );
- gEngfuncs.pTriAPI->TexCoord2f( 0, 0 );
- gEngfuncs.pTriAPI->Vertex3f (x, y, z);
-
- gEngfuncs.pTriAPI->TexCoord2f( 1, 0 );
- gEngfuncs.pTriAPI->Vertex3f (x+xStep ,y, z);
-
- gEngfuncs.pTriAPI->TexCoord2f( 1, 1 );
- gEngfuncs.pTriAPI->Vertex3f (x+xStep, y+yStep, z);
-
- gEngfuncs.pTriAPI->TexCoord2f( 0, 1 );
- gEngfuncs.pTriAPI->Vertex3f (x, y+yStep, z);
- gEngfuncs.pTriAPI->End();
-
- frame++;
- x+= xStep;
- }
-
- y+=yStep;
- }
- }
- else
- {
- xStep = -(2*4096.0f / m_OverviewData.zoom ) / xTiles;
- yStep = -(2*4096.0f / (m_OverviewData.zoom* screenaspect) ) / yTiles;
-
-
- x = xs + (4096.0f / (m_OverviewData.zoom * screenaspect ));
-
-
-
- for (ix = 0; ix < yTiles; ix++)
- {
-
- y = ys + (4096.0f / (m_OverviewData.zoom));
-
- for (iy = 0; iy < xTiles; iy++)
- {
- if (hasMapImage)
- gEngfuncs.pTriAPI->SpriteTexture( m_MapSprite, frame );
- else
- gEngfuncs.pTriAPI->SpriteTexture( dummySprite, 0 );
-
- gEngfuncs.pTriAPI->Begin( TRI_QUADS );
- gEngfuncs.pTriAPI->TexCoord2f( 0, 0 );
- gEngfuncs.pTriAPI->Vertex3f (x, y, z);
-
- gEngfuncs.pTriAPI->TexCoord2f( 0, 1 );
- gEngfuncs.pTriAPI->Vertex3f (x+xStep ,y, z);
-
- gEngfuncs.pTriAPI->TexCoord2f( 1, 1 );
- gEngfuncs.pTriAPI->Vertex3f (x+xStep, y+yStep, z);
-
- gEngfuncs.pTriAPI->TexCoord2f( 1, 0 );
- gEngfuncs.pTriAPI->Vertex3f (x, y+yStep, z);
- gEngfuncs.pTriAPI->End();
-
- frame++;
-
- y+=yStep;
- }
-
- x+= xStep;
-
- }
- }
-}
-
-void CHudSpectator::DrawOverviewEntities()
-{
- /*
- int i,ir,ig,ib;
- struct model_s *hSpriteModel;
- vec3_t origin, angles, point, forward, right, left, up, world, screen, offset;
- float x,y,z, r,g,b, sizeScale = 4.0f;
- cl_entity_t * ent;
- float rmatrix[3][4]; // transformation matrix
-
- float zScale = (90.0f - v_angles[0] ) / 90.0f;
-
-
- z = m_OverviewData.layersHeights[0] * zScale;
- // get yellow/brown HUD color
- //UnpackRGB(ir,ig,ib, RGB_YELLOWISH);
- gHUD.GetPrimaryHudColor(ir, ig, ib);
- r = (float)ir/255.0f;
- g = (float)ig/255.0f;
- b = (float)ib/255.0f;
-
- gEngfuncs.pTriAPI->CullFace( TRI_NONE );
-
- for (i=0; i < MAX_PLAYERS; i++ )
- m_vPlayerPos[i][2] = -1; // mark as invisible
-
- // draw all players
-
- float depthOffset = 0;
-
- for (i=MAX_OVERVIEW_ENTITIES - 1; i >= 0; i--)
- {
- if ( !m_OverviewEntities[i].hSprite )
- continue;
-
- hSpriteModel = (struct model_s *)gEngfuncs.GetSpritePointer( m_OverviewEntities[i].hSprite );
- ent = m_OverviewEntities[i].entity;
-
- int theSpriteFrame = m_OverviewEntities[i].mFrame;
- gEngfuncs.pTriAPI->SpriteTexture( hSpriteModel, theSpriteFrame);
-
- gEngfuncs.pTriAPI->RenderMode( kRenderTransAdd);
-
- // see R_DrawSpriteModel
- // draws players sprite
-
- AngleVectors(ent->angles, right, up, NULL );
-
- VectorCopy(ent->origin,origin);
-
- // Set origin of blip to just above map height, so blips are all drawn on map
- origin.z = m_OverviewData.layersHeights[0] + kOverviewEntityZHeight + depthOffset;
-
- gEngfuncs.pTriAPI->Begin( TRI_QUADS );
-
- float gammaSlope = gHUD.GetGammaSlope();
-
- gEngfuncs.pTriAPI->Color4f(
- m_OverviewEntities[i].mColorR / gammaSlope,
- m_OverviewEntities[i].mColorG / gammaSlope,
- m_OverviewEntities[i].mColorB / gammaSlope,
- 1);
-
- gEngfuncs.pTriAPI->TexCoord2f (1, 0);
- VectorMA (origin, 16.0f * sizeScale, up, point);
- VectorMA (point, 16.0f * sizeScale, right, point);
- point[2] *= zScale;
- gEngfuncs.pTriAPI->Vertex3fv (point);
-
- gEngfuncs.pTriAPI->TexCoord2f (0, 0);
-
- VectorMA (origin, 16.0f * sizeScale, up, point);
- VectorMA (point, -16.0f * sizeScale, right, point);
- point[2] *= zScale;
- gEngfuncs.pTriAPI->Vertex3fv (point);
-
- gEngfuncs.pTriAPI->TexCoord2f (0,1);
- VectorMA (origin, -16.0f * sizeScale, up, point);
- VectorMA (point, -16.0f * sizeScale, right, point);
- point[2] *= zScale;
- gEngfuncs.pTriAPI->Vertex3fv (point);
-
- gEngfuncs.pTriAPI->TexCoord2f (1,1);
- VectorMA (origin, -16.0f * sizeScale, up, point);
- VectorMA (point, 16.0f * sizeScale, right, point);
- point[2] *= zScale;
- gEngfuncs.pTriAPI->Vertex3fv (point);
-
- gEngfuncs.pTriAPI->End ();
-
-
- if ( !ent->player)
- continue;
- // draw line under player icons
- origin[2] *= zScale;
-
- gEngfuncs.pTriAPI->RenderMode( kRenderTransAdd );
-
- hSpriteModel = (struct model_s *)gEngfuncs.GetSpritePointer( m_hsprBeam );
- gEngfuncs.pTriAPI->SpriteTexture( hSpriteModel, 0 );
-
- gEngfuncs.pTriAPI->Color4f(r, g, b, 0.3);
-
- gEngfuncs.pTriAPI->Begin ( TRI_QUADS );
- gEngfuncs.pTriAPI->TexCoord2f (1, 0);
- gEngfuncs.pTriAPI->Vertex3f (origin[0]+4, origin[1]+4, origin[2]-zScale);
- gEngfuncs.pTriAPI->TexCoord2f (0, 0);
- gEngfuncs.pTriAPI->Vertex3f (origin[0]-4, origin[1]-4, origin[2]-zScale);
- gEngfuncs.pTriAPI->TexCoord2f (0, 1);
- gEngfuncs.pTriAPI->Vertex3f (origin[0]-4, origin[1]-4,z);
- gEngfuncs.pTriAPI->TexCoord2f (1, 1);
- gEngfuncs.pTriAPI->Vertex3f (origin[0]+4, origin[1]+4,z);
- gEngfuncs.pTriAPI->End ();
-
- gEngfuncs.pTriAPI->Begin ( TRI_QUADS );
- gEngfuncs.pTriAPI->TexCoord2f (1, 0);
- gEngfuncs.pTriAPI->Vertex3f (origin[0]-4, origin[1]+4, origin[2]-zScale);
- gEngfuncs.pTriAPI->TexCoord2f (0, 0);
- gEngfuncs.pTriAPI->Vertex3f (origin[0]+4, origin[1]-4, origin[2]-zScale);
- gEngfuncs.pTriAPI->TexCoord2f (0, 1);
- gEngfuncs.pTriAPI->Vertex3f (origin[0]+4, origin[1]-4,z);
- gEngfuncs.pTriAPI->TexCoord2f (1, 1);
- gEngfuncs.pTriAPI->Vertex3f (origin[0]-4, origin[1]+4,z);
- gEngfuncs.pTriAPI->End ();
-
- // calculate screen position for name and infromation in hud::draw()
- if ( gEngfuncs.pTriAPI->WorldToScreen(origin,screen) )
- continue; // object is behind viewer
-
- screen[0] = XPROJECT(screen[0]);
- screen[1] = YPROJECT(screen[1]);
- screen[2] = 0.0f;
-
- // calculate some offset under the icon
- origin[0]+=32.0f;
- origin[1]+=32.0f;
-
- gEngfuncs.pTriAPI->WorldToScreen(origin,offset);
-
- offset[0] = XPROJECT(offset[0]);
- offset[1] = YPROJECT(offset[1]);
- offset[2] = 0.0f;
-
- VectorSubtract(offset, screen, offset );
-
- int playerNum = ent->index - 1;
-
- m_vPlayerPos[playerNum][0] = screen[0];
- m_vPlayerPos[playerNum][1] = screen[1] + Length(offset);
- m_vPlayerPos[playerNum][2] = 1; // mark player as visible
-
-
- }
-
- if ( !m_pip || !m_drawcone->value )
- return;
-
- // get current camera position and angle
-
- if ( m_pip == INSET_IN_EYE || g_iUser1 == OBS_IN_EYE )
- {
- V_GetInEyePos( g_iUser2, origin, angles );
- }
- else if ( m_pip == INSET_CHASE_FREE || g_iUser1 == OBS_CHASE_FREE )
- {
- V_GetChasePos( g_iUser2, v_cl_angles, origin, angles );
- }
- else if ( g_iUser1 == OBS_ROAMING )
- {
- VectorCopy( v_sim_org, origin );
- VectorCopy( v_cl_angles, angles );
- }
- else
- V_GetChasePos( g_iUser2, NULL, origin, angles );
-
-
- // draw camera sprite
-
- x = origin[0];
- y = origin[1];
- z = origin[2];
-
- // Set origin of cone to just above map height, so blips are all drawn on map
- z = m_OverviewData.layersHeights[0] + kOverviewEntityZHeight;
-
- angles[0] = 0; // always show horizontal camera sprite
-
- hSpriteModel = (struct model_s *)gEngfuncs.GetSpritePointer( m_hsprCamera );
- gEngfuncs.pTriAPI->RenderMode( kRenderTransAdd );
- gEngfuncs.pTriAPI->SpriteTexture( hSpriteModel, 0 );
-
-
- gEngfuncs.pTriAPI->Color4f( r, g, b, 1.0 );
-
- AngleVectors(angles, forward, NULL, NULL );
- VectorScale (forward, 512.0f, forward);
-
- offset[0] = 0.0f;
- offset[1] = 45.0f;
- offset[2] = 0.0f;
-
- AngleMatrix(offset, rmatrix );
- VectorTransform(forward, rmatrix , right );
-
- offset[1]= -45.0f;
- AngleMatrix(offset, rmatrix );
- VectorTransform(forward, rmatrix , left );
-
- gEngfuncs.pTriAPI->Begin (TRI_TRIANGLES);
- gEngfuncs.pTriAPI->TexCoord2f( 0, 0 );
- gEngfuncs.pTriAPI->Vertex3f (x+right[0], y+right[1], (z+right[2]) * zScale);
-
- gEngfuncs.pTriAPI->TexCoord2f( 0, 1 );
- gEngfuncs.pTriAPI->Vertex3f (x, y, z * zScale);
-
- gEngfuncs.pTriAPI->TexCoord2f( 1, 1 );
- gEngfuncs.pTriAPI->Vertex3f (x+left[0], y+left[1], (z+left[2]) * zScale);
- gEngfuncs.pTriAPI->End ();
- */
-
-}
-
-
-
-void CHudSpectator::DrawOverview()
-{
- /*
- // draw only in sepctator mode
- if ( !g_iUser1 )
- return;
-
- // Only draw the overview if Map Mode is selected for this view
- if ( m_iDrawCycle == 0 && ( (g_iUser1 != OBS_MAP_FREE) && (g_iUser1 != OBS_MAP_CHASE) ) )
- return;
-
- if ( m_iDrawCycle == 1 && m_pip->value < INSET_MAP_FREE )
- return;
-
- DrawOverviewLayer();
- DrawOverviewEntities();
- CheckOverviewEntities();
- */
-
-}
-
-
-
-void CHudSpectator::CheckOverviewEntities()
-{
- double time = gEngfuncs.GetClientTime();
-
- // removes old entities from list
- for ( int i = 0; i< MAX_OVERVIEW_ENTITIES; i++ )
- {
- // remove entity from list if it is too old
- if ( m_OverviewEntities[i].killTime < time )
- {
- memset( &m_OverviewEntities[i], 0, sizeof (overviewEntity_t) );
- }
- }
-}
-
-bool CHudSpectator::AddOverviewEntity( int type, struct cl_entity_s *ent, const char *modelname)
-{
- HSPRITE hSprite = 0;
- double duration = -1.0f; // duration -1 means show it only this frame;
- int theFrame = 0;
- bool theSuccess = false;
- int theRenderMode;
-
- if ( ent )
- {
-
- if (ent->curstate.solid != SOLID_NOT)
- {
- gHUD.GetSpriteForUser3(AvHUser3(ent->curstate.iuser3), hSprite, theFrame, theRenderMode);
- }
-
- /*
- if ( type == ET_PLAYER )
- {
- if ( ent->curstate.solid != SOLID_NOT)
- {
- int thePlayerClass = g_PlayerExtraInfo[ent->index].playerclass;
- switch(thePlayerClass)
- {
- case PLAYERCLASS_ALIVE_MARINE:
- hSprite = this->m_hsprPlayerMarine;
- theFrame = 0;
- break;
- case PLAYERCLASS_ALIVE_HEAVY_MARINE:
- hSprite = this->m_hsprPlayerMarine;
- theFrame = 1;
- break;
- case PLAYERCLASS_COMMANDER:
- hSprite = this->m_hsprPlayerMarine;
- theFrame = 2;
- break;
- case PLAYERCLASS_ALIVE_LEVEL1:
- hSprite = this->m_hsprPlayerAlien;
- theFrame = 0;
- break;
- case PLAYERCLASS_ALIVE_LEVEL2:
- hSprite = this->m_hsprPlayerAlien;
- theFrame = 1;
- break;
- case PLAYERCLASS_ALIVE_LEVEL3:
- hSprite = this->m_hsprPlayerAlien;
- theFrame = 2;
- break;
- case PLAYERCLASS_ALIVE_LEVEL4:
- hSprite = this->m_hsprPlayerAlien;
- theFrame = 3;
- break;
- case PLAYERCLASS_ALIVE_LEVEL5:
- hSprite = this->m_hsprPlayerAlien;
- theFrame = 4;
- break;
- case PLAYERCLASS_ALIVE_GESTATING:
- hSprite = this->m_hsprPlayerAlien;
- theFrame = 5;
- break;
-
- case PLAYERCLASS_ALIVE_DIGESTING:
- break;
- }
- }
- else
- {
- // it's an spectator
- }
- }
- else if (type == ET_NORMAL)
- {
- // Now help icons
- if(hSprite == 0)
- {
- AvHUser3 theUser3 = AvHUser3(ent->curstate.iuser3);
- theFrame = gHUD.GetHelpIconFrameFromUser3(theUser3);
- if(theFrame != -1)
- {
- hSprite = gHUD.GetHelpSprite();
- }
- }
- }
- */
- }
-
- if(hSprite > 0)
- {
-
- int theTeam = ent->curstate.team;
-
- float theR = kFTeamColors[theTeam][0];
- float theG = kFTeamColors[theTeam][1];
- float theB = kFTeamColors[theTeam][2];
-
- theSuccess = AddOverviewEntityToList(hSprite, ent, gEngfuncs.GetClientTime() + duration, theFrame, theRenderMode, theR, theG, theB);
-
- }
-
- return theSuccess;
-}
-
-void CHudSpectator::DeathMessage(int victim)
-{
- // find out where the victim is
- cl_entity_t *pl = gEngfuncs.GetEntityByIndex(victim);
-
- if (pl && pl->player)
- AddOverviewEntityToList(m_hsprPlayerDead, pl, gEngfuncs.GetClientTime() + 2.0f, 0, kRenderTransTexture, 1, 1, 1);
-}
-
-bool CHudSpectator::AddOverviewEntityToList(HSPRITE sprite, cl_entity_t *ent, double killTime, int inFrame, int inRenderMode, float r, float g, float b)
-{
- for ( int i = 0; i< MAX_OVERVIEW_ENTITIES; i++ )
- {
- // find empty entity slot
- if ( m_OverviewEntities[i].entity == NULL)
- {
- m_OverviewEntities[i].entity = ent;
- m_OverviewEntities[i].hSprite = sprite;
- m_OverviewEntities[i].killTime = killTime;
- m_OverviewEntities[i].mFrame = inFrame;
- m_OverviewEntities[i].mRenderMode = inRenderMode;
- m_OverviewEntities[i].mColorR = r;
- m_OverviewEntities[i].mColorG = g;
- m_OverviewEntities[i].mColorB = b;
- return true;
- }
- }
-
- return false; // maximum overview entities reached
-}
-void CHudSpectator::CheckSettings()
-{
- // disallow same inset mode as main mode:
-
- //m_pip->value = floor(m_pip->value);
-
- // Removed by mmcguire.
- /*
- if ( ( g_iUser1 < OBS_MAP_FREE ) && ( m_pip->value == INSET_CHASE_LOCKED || m_pip->value == INSET_IN_EYE ) )
- {
- // otherwise both would show in World picures
- m_pip->value = INSET_OFF;
- }
-
- // disble in intermission screen
- if ( gHUD.m_iIntermission )
- m_pip->value = INSET_OFF;
- */
-
- // check chat mode
- if ( m_chatEnabled != (gHUD.m_SayText.m_HUD_saytext->value!=0) )
- {
- // hud_saytext changed
- m_chatEnabled = (gHUD.m_SayText.m_HUD_saytext->value!=0);
-
- if ( gEngfuncs.IsSpectateOnly() )
- {
- // tell proxy our new chat mode
- char chatcmd[32];
- sprintf(chatcmd, "ignoremsg %i", m_chatEnabled?0:1 );
- gEngfuncs.pfnServerCmd(chatcmd);
- }
- }
-
- // HL/TFC has no oberserver corsshair, so set it client side
- if ( g_iUser1 == OBS_IN_EYE )
- {
- m_crosshairRect.left = 24;
- m_crosshairRect.top = 0;
- m_crosshairRect.right = 48;
- m_crosshairRect.bottom = 24;
-
- gHUD.SetCurrentCrosshair( m_hCrosshair, m_crosshairRect, 255, 255, 255 );
- }
- else
- {
- memset( &m_crosshairRect,0,sizeof(m_crosshairRect) );
- gHUD.SetCurrentCrosshair( 0, m_crosshairRect, 0, 0, 0 );
- }
-
- // Removed by mmcguire.
- /*
- // if we are a real player on server don't allow inset window
- // in First Person mode since this is our resticted forcecamera mode 2
- // team number 3 = SPECTATOR see player.h
-
- if ( ( (g_iTeamNumber == 1) || (g_iTeamNumber == 2)) && (g_iUser1 == OBS_IN_EYE) )
- m_pip->value = INSET_OFF;
- */
-
- // draw small border around inset view, adjust upper black bar
- //gViewPort->m_pSpectatorPanel->EnableInsetView( m_pip->value != INSET_OFF );
- gViewPort->m_pSpectatorPanel->EnableInsetView( IsInOverviewMode() );
-
-}
-
-
-void CHudSpectator::Reset()
-{
- // Reset HUD
- if ( strcmp( m_OverviewData.map, gEngfuncs.pfnGetLevelName() ) )
- {
- // update level overview if level changed
- ParseOverviewFile();
- LoadMapSprites();
- }
-
- memset( &m_OverviewEntities, 0, sizeof(m_OverviewEntities));
-
- SetSpectatorStartPosition();
-}
-
-void CHudSpectator::InitHUDData()
-{
- gHUD.InitHUDData();
- m_lastPrimaryObject = m_lastSecondaryObject = 0;
- m_flNextObserverInput = 0.0f;
- m_lastHudMessage = 0;
- m_iSpectatorNumber = 0;
- iJumpSpectator = 0;
- g_iUser1 = g_iUser2 = 0;
-
- memset( &m_OverviewData, 0, sizeof(m_OverviewData));
- memset( &m_OverviewEntities, 0, sizeof(m_OverviewEntities));
-
- if ( gEngfuncs.IsSpectateOnly() || gEngfuncs.pDemoAPI->IsPlayingback() )
- m_autoDirector->value = 1.0f;
- else
- m_autoDirector->value = 0.0f;
-
- Reset();
-
- SetMode( OBS_CHASE_FREE);
-
- g_iUser2 = 0; // fake not target until first camera command
-
- // reset HUD FOV
- gHUD.m_iFOV = CVAR_GET_FLOAT("default_fov");
-}
-
+//========= Copyright � 1996-2002, Valve LLC, All rights reserved. ============
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================
+
+#include "hud.h"
+#include "cl_util.h"
+#include "common/cl_entity.h"
+#include "common/triangleapi.h"
+#include "vgui_TeamFortressViewport.h"
+#include "vgui_SpectatorPanel.h"
+#include "common/hltv.h"
+
+#include "pm_shared/pm_shared.h"
+#include "pm_shared/pm_defs.h"
+#include "common/pmtrace.h"
+#include "common/entity_types.h"
+
+// these are included for the math functions
+#include "common/com_model.h"
+#include "common/demo_api.h"
+#include "common/event_api.h"
+#include "studio_util.h"
+#include "common/screenfade.h"
+#include "util/STLUtil.h"
+#include "mod/AvHTitles.h"
+#include "mod/AvHSprites.h"
+
+#pragma warning(disable: 4244)
+
+extern int iJumpSpectator;
+extern float vJumpOrigin[3];
+extern float vJumpAngles[3];
+
+extern void V_GetInEyePos(int entity, float * origin, float * angles );
+extern void V_ResetChaseCam();
+extern void V_GetChasePos(int target, float * cl_angles, float * origin, float * angles);
+extern void VectorAngles( const float *forward, float *angles );
+extern "C" void NormalizeAngles( float *angles );
+extern float * GetClientColor( int clientIndex );
+
+extern vec3_t v_origin; // last view origin
+extern vec3_t v_angles; // last view angle
+extern vec3_t v_cl_angles; // last client/mouse angle
+extern vec3_t v_sim_org; // last sim origin
+
+void SpectatorMode(void)
+{
+
+ if ( gEngfuncs.Cmd_Argc() <= 1 )
+ {
+ gEngfuncs.Con_Printf( "usage: spec_mode \n" );
+ return;
+ }
+
+ // SetModes() will decide if command is executed on server or local
+ if ( gEngfuncs.Cmd_Argc() == 2 )
+ gHUD.m_Spectator.SetMode( atoi( gEngfuncs.Cmd_Argv(1) ));
+
+ //else if ( gEngfuncs.Cmd_Argc() == 3 )
+ // gHUD.m_Spectator.SetMode( atoi( gEngfuncs.Cmd_Argv(1) ), atoi( gEngfuncs.Cmd_Argv(2) ) );
+}
+
+void SpectatorSpray(void)
+{
+ vec3_t forward;
+ char string[128];
+
+ if ( !gEngfuncs.IsSpectateOnly() )
+ return;
+
+ AngleVectors(v_angles,forward,NULL,NULL);
+ VectorScale(forward, 128, forward);
+ VectorAdd(forward, v_origin, forward);
+ pmtrace_t * trace = gEngfuncs.PM_TraceLine( v_origin, forward, PM_TRACELINE_PHYSENTSONLY, 2, -1 );
+ if ( trace->fraction != 1.0 )
+ {
+ sprintf(string, "drc_spray %.2f %.2f %.2f %i",
+ trace->endpos[0], trace->endpos[1], trace->endpos[2], trace->ent );
+ gEngfuncs.pfnServerCmd(string);
+ }
+
+}
+void SpectatorHelp(void)
+{
+ if ( gViewPort )
+ {
+ gViewPort->ShowVGUIMenu( MENU_SPECHELP );
+ }
+ else
+ {
+ char *text = CHudTextMessage::BufferedLocaliseTextString( "#Spec_Help_Text" );
+
+ if ( text )
+ {
+ while ( *text )
+ {
+ if ( *text != 13 )
+ gEngfuncs.Con_Printf( "%c", *text );
+ text++;
+ }
+ }
+ }
+}
+
+void SpectatorMenu( void )
+{
+ if ( gEngfuncs.Cmd_Argc() <= 1 )
+ {
+ gEngfuncs.Con_Printf( "usage: spec_menu <0|1>\n" );
+ return;
+ }
+
+ gViewPort->m_pSpectatorPanel->ShowMenu( atoi( gEngfuncs.Cmd_Argv(1))!=0 );
+}
+
+void ToggleScores( void )
+{
+ if ( gViewPort )
+ {
+ if (gViewPort->IsScoreBoardVisible() )
+ {
+ gViewPort->HideScoreBoard();
+ }
+ else
+ {
+ gViewPort->ShowScoreBoard();
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+int CHudSpectator::Init()
+{
+ gHUD.AddHudElem(this);
+
+ m_iFlags |= HUD_ACTIVE;
+ m_flNextObserverInput = 0.0f;
+ m_zoomDelta = 0.0f;
+ m_moveDelta = 0.0f;
+ iJumpSpectator = 0;
+
+ memset( &m_OverviewData, 0, sizeof(m_OverviewData));
+ memset( &m_OverviewEntities, 0, sizeof(m_OverviewEntities));
+ m_lastPrimaryObject = m_lastSecondaryObject = 0;
+
+ gEngfuncs.pfnAddCommand ("spec_mode", SpectatorMode );
+ gEngfuncs.pfnAddCommand ("spec_decal", SpectatorSpray );
+ gEngfuncs.pfnAddCommand ("spec_help", SpectatorHelp );
+ gEngfuncs.pfnAddCommand ("spec_menu", SpectatorMenu );
+ gEngfuncs.pfnAddCommand ("togglescores", ToggleScores );
+
+ m_drawnames = gEngfuncs.pfnRegisterVariable("spec_drawnames","1",0);
+ m_drawcone = gEngfuncs.pfnRegisterVariable("spec_drawcone","1",0);
+ m_drawstatus = gEngfuncs.pfnRegisterVariable("spec_drawstatus","1",0);
+ m_autoDirector = gEngfuncs.pfnRegisterVariable("spec_autodirector","1",0);
+
+ // Removed by mmcguire.
+ m_overviewMode = false;
+ //m_overview = gEngfuncs.pfnRegisterVariable("spec_overview","1",0);
+ //m_pip = gEngfuncs.pfnRegisterVariable("spec_pip","1",0);
+
+ if ( !m_drawnames || !m_drawcone || !m_drawstatus || !m_autoDirector /*|| !m_pip*/)
+ {
+ gEngfuncs.Con_Printf("ERROR! Couldn't register all spectator variables.\n");
+ return 0;
+ }
+
+ return 1;
+}
+
+
+//-----------------------------------------------------------------------------
+// UTIL_StringToVector originally from ..\dlls\util.cpp, slightly changed
+//-----------------------------------------------------------------------------
+
+void UTIL_StringToVector( float * pVector, const char *pString )
+{
+ char *pstr, *pfront, tempString[128];
+ int j;
+
+ strcpy( tempString, pString );
+ pstr = pfront = tempString;
+
+ for ( j = 0; j < 3; j++ )
+ {
+ pVector[j] = atof( pfront );
+
+ while ( *pstr && *pstr != ' ' )
+ pstr++;
+ if (!*pstr)
+ break;
+ pstr++;
+ pfront = pstr;
+ }
+
+ if (j < 2)
+ {
+ for (j = j+1;j < 3; j++)
+ pVector[j] = 0;
+ }
+}
+
+int UTIL_FindEntityInMap(char * name, float * origin, float * angle)
+{
+ int n,found = 0;
+ char keyname[256];
+ char token[1024];
+
+ cl_entity_t * pEnt = gEngfuncs.GetEntityByIndex( 0 ); // get world model
+
+ if ( !pEnt ) return 0;
+
+ if ( !pEnt->model ) return 0;
+
+ char * data = pEnt->model->entities;
+
+ while (data)
+ {
+ data = gEngfuncs.COM_ParseFile(data, token);
+
+ if ( (token[0] == '}') || (token[0]==0) )
+ break;
+
+ if (!data)
+ {
+ gEngfuncs.Con_DPrintf("UTIL_FindEntityInMap: EOF without closing brace\n");
+ return 0;
+ }
+
+ if (token[0] != '{')
+ {
+ gEngfuncs.Con_DPrintf("UTIL_FindEntityInMap: expected {\n");
+ return 0;
+ }
+
+ // we parse the first { now parse entities properties
+
+ while ( 1 )
+ {
+ // parse key
+ data = gEngfuncs.COM_ParseFile(data, token);
+ if (token[0] == '}')
+ break; // finish parsing this entity
+
+ if (!data)
+ {
+ gEngfuncs.Con_DPrintf("UTIL_FindEntityInMap: EOF without closing brace\n");
+ return 0;
+ };
+
+ strcpy (keyname, token);
+
+ // another hack to fix keynames with trailing spaces
+ n = (int)strlen(keyname);
+ while (n && keyname[n-1] == ' ')
+ {
+ keyname[n-1] = 0;
+ n--;
+ }
+
+ // parse value
+ data = gEngfuncs.COM_ParseFile(data, token);
+ if (!data)
+ {
+ gEngfuncs.Con_DPrintf("UTIL_FindEntityInMap: EOF without closing brace\n");
+ return 0;
+ };
+
+ if (token[0] == '}')
+ {
+ gEngfuncs.Con_DPrintf("UTIL_FindEntityInMap: closing brace without data");
+ return 0;
+ }
+
+ if (!strcmp(keyname,"classname"))
+ {
+ if (!strcmp(token, name ))
+ {
+ found = 1; // thats our entity
+ }
+ };
+
+ if( !strcmp( keyname, "angle" ) )
+ {
+ float y = atof( token );
+
+ if (y >= 0)
+ {
+ angle[0] = 0.0f;
+ angle[1] = y;
+ }
+ else if ((int)y == -1)
+ {
+ angle[0] = -90.0f;
+ angle[1] = 0.0f;;
+ }
+ else
+ {
+ angle[0] = 90.0f;
+ angle[1] = 0.0f;
+ }
+
+ angle[2] = 0.0f;
+ }
+
+ if( !strcmp( keyname, "angles" ) )
+ {
+ UTIL_StringToVector(angle, token);
+ }
+
+ if (!strcmp(keyname,"origin"))
+ {
+ UTIL_StringToVector(origin, token);
+
+ };
+
+ } // while (1)
+
+ if (found)
+ return 1;
+
+ }
+
+ return 0; // we search all entities, but didn't found the correct
+
+}
+
+//-----------------------------------------------------------------------------
+// SetSpectatorStartPosition():
+// Get valid map position and 'beam' spectator to this position
+//-----------------------------------------------------------------------------
+
+void CHudSpectator::SetSpectatorStartPosition()
+{
+ // search for info_player start
+ if ( UTIL_FindEntityInMap( "trigger_camera", m_cameraOrigin, m_cameraAngles ) )
+ iJumpSpectator = 1;
+
+ else if ( UTIL_FindEntityInMap( "info_player_start", m_cameraOrigin, m_cameraAngles ) )
+ iJumpSpectator = 1;
+
+ else if ( UTIL_FindEntityInMap( "info_player_deathmatch", m_cameraOrigin, m_cameraAngles ) )
+ iJumpSpectator = 1;
+
+ else if ( UTIL_FindEntityInMap( "info_player_coop", m_cameraOrigin, m_cameraAngles ) )
+ iJumpSpectator = 1;
+ else
+ {
+ // jump to 0,0,0 if no better position was found
+ VectorCopy(vec3_origin, m_cameraOrigin);
+ VectorCopy(vec3_origin, m_cameraAngles);
+ }
+
+ VectorCopy(m_cameraOrigin, vJumpOrigin);
+ VectorCopy(m_cameraAngles, vJumpAngles);
+
+ iJumpSpectator = 1; // jump anyway
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Loads new icons
+//-----------------------------------------------------------------------------
+int CHudSpectator::VidInit()
+{
+ m_hsprPlayerMarine = SPR_Load("sprites/iplayerm.spr");
+ m_hsprPlayerAlien = SPR_Load("sprites/iplayera.spr");
+ m_hsprPlayerDead = SPR_Load("sprites/iplayerdead.spr");
+ m_hsprUnkownMap = SPR_Load("sprites/tile.spr");
+ //m_hsprBeam = SPR_Load("sprites/laserbeam.spr");
+ //m_hsprCamera = SPR_Load("sprites/camera.spr");
+ m_hCrosshair = SPR_Load("sprites/crosshairs.spr");
+ m_hsprWhite = SPR_Load(kWhiteSprite);
+
+ return 1;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : flTime -
+// intermission -
+//-----------------------------------------------------------------------------
+int CHudSpectator::Draw(float flTime)
+{
+
+ // draw only in spectator mode
+ if ( !g_iUser1 )
+ return 0;
+// string error;
+// gHUD.Update( flTime, error);
+
+ // Removed by mmcguire.
+ /*
+ // if user pressed zoom, aplly changes
+ if ( (m_zoomDelta != 0.0f) && ( g_iUser1 == OBS_MAP_FREE ) )
+ {
+ m_mapZoom += m_zoomDelta;
+
+ if ( m_mapZoom > 3.0f )
+ m_mapZoom = 3.0f;
+
+ if ( m_mapZoom < 0.5f )
+ m_mapZoom = 0.5f;
+ }
+
+ // if user moves in map mode, change map origin
+ if ( (m_moveDelta != 0.0f) && (g_iUser1 != OBS_ROAMING) )
+ {
+ vec3_t right;
+ AngleVectors(v_angles, NULL, right, NULL);
+ VectorNormalize(right);
+ VectorScale(right, m_moveDelta, right );
+
+ VectorAdd( m_mapOrigin, right, m_mapOrigin )
+
+ }
+ */
+
+ //DrawOverviewMap();
+
+/*
+ if (!IsInOverviewMode())
+ {
+ return 0;
+ }
+
+ if (m_hsprWhite != NULL)
+ {
+
+ float bgColor[] = { 0.1, 0.1, 0.1, 1 };
+ float borderColor[] = { 1, 1, 1, 1 };
+
+ gEngfuncs.pTriAPI->RenderMode(kRenderNormal);
+ gEngfuncs.pTriAPI->CullFace(TRI_NONE);
+
+ gEngfuncs.pTriAPI->SpriteTexture((struct model_s*)(gEngfuncs.GetSpritePointer(m_hsprWhite)), 0);
+
+ float gammaScale = 1.0f / gHUD.GetGammaSlope();
+
+ // Draw the border on the overview map and the inset view.
+
+ gEngfuncs.pTriAPI->RenderMode(kRenderNormal);
+ gEngfuncs.pTriAPI->CullFace(TRI_NONE);
+
+ gEngfuncs.pTriAPI->SpriteTexture((struct model_s*)(gEngfuncs.GetSpritePointer(m_hsprWhite)), 0);
+ gEngfuncs.pTriAPI->Color4f(gammaScale * borderColor[0], gammaScale * borderColor[1], gammaScale * borderColor[2], borderColor[3]);
+
+ gEngfuncs.pTriAPI->Begin(TRI_LINES);
+
+ int insetX1 = XRES(m_OverviewData.insetWindowX);
+ int insetY1 = YRES(m_OverviewData.insetWindowY);
+ int insetX2 = insetX1 + XRES(m_OverviewData.insetWindowWidth);
+ int insetY2 = insetY1 + YRES(m_OverviewData.insetWindowHeight);
+
+ gEngfuncs.pTriAPI->Vertex3f(insetX1, insetY1, 1);
+ gEngfuncs.pTriAPI->Vertex3f(insetX2, insetY1, 1);
+
+ gEngfuncs.pTriAPI->Vertex3f(insetX2, insetY1, 1);
+ gEngfuncs.pTriAPI->Vertex3f(insetX2, insetY2, 1);
+
+ gEngfuncs.pTriAPI->Vertex3f(insetX2, insetY2, 1);
+ gEngfuncs.pTriAPI->Vertex3f(insetX1, insetY2, 1);
+
+ gEngfuncs.pTriAPI->Vertex3f(insetX1, insetY2, 1);
+ gEngfuncs.pTriAPI->Vertex3f(insetX1, insetY1, 1);
+
+ gEngfuncs.pTriAPI->End();
+
+ }*/
+
+
+
+ /*
+ // Only draw the icon names only if map mode is in Main Mode
+ if ( g_iUser1 < OBS_MAP_FREE )
+ return 1;
+
+ if ( !m_drawnames->value )
+ return 1;
+
+ // make sure we have player info
+ gViewPort->GetAllPlayersInfo();
+ */
+
+ return 1;
+
+}
+
+bool CHudSpectator::IsInOverviewMode() const
+{
+ return g_iUser1 && m_overviewMode && gHUD.GetIsNSMode();
+}
+
+void CHudSpectator::SetOverviewMode(bool overviewMode)
+{
+ m_overviewMode = overviewMode;
+}
+
+void CHudSpectator::DrawOverviewMap()
+{
+
+ // draw only in spectator mode
+ if (!IsInOverviewMode())
+ {
+ return;
+ }
+
+ AvHOverviewMap& theOverviewMap = gHUD.GetOverviewMap();
+
+ AvHOverviewMap::DrawInfo theDrawInfo;
+
+ theDrawInfo.mX = XRES(m_OverviewData.insetWindowX + m_OverviewData.insetWindowWidth + 4);
+ theDrawInfo.mY = YRES(SPECTATOR_PANEL_HEIGHT + 4);
+ theDrawInfo.mWidth = ScreenWidth() - theDrawInfo.mX - XRES(4);
+ theDrawInfo.mHeight = ScreenHeight() - YRES(SPECTATOR_PANEL_HEIGHT + 4) - theDrawInfo.mY;
+ theDrawInfo.mZoomScale = 1.0f;
+ AvHMapExtents theMapExtents;
+ theOverviewMap.GetMapExtents(theMapExtents);
+
+ theDrawInfo.mFullScreen = true;
+
+ float worldWidth = theMapExtents.GetMaxMapX() - theMapExtents.GetMinMapX();
+ float worldHeight = theMapExtents.GetMaxMapY() - theMapExtents.GetMinMapY();
+
+ float xScale;
+ float yScale;
+
+ float aspect1 = worldWidth / worldHeight;
+ float aspect2 = ((float)theDrawInfo.mWidth) / theDrawInfo.mHeight;
+
+ if (aspect1 > aspect2)
+ {
+ xScale = 1;
+ yScale = 1 / aspect2;
+ }
+ else
+ {
+ xScale = aspect2;
+ yScale = 1;
+ }
+
+ float centerX = (theMapExtents.GetMinMapX() + theMapExtents.GetMaxMapX()) / 2;
+ float centerY = (theMapExtents.GetMinMapY() + theMapExtents.GetMaxMapY()) / 2;
+
+ theDrawInfo.mViewWorldMinX = centerX - worldWidth * xScale * 0.5;
+ theDrawInfo.mViewWorldMinY = centerY - worldHeight * yScale * 0.5;
+ theDrawInfo.mViewWorldMaxX = centerX + worldWidth * xScale * 0.5;
+ theDrawInfo.mViewWorldMaxY = centerY + worldHeight * yScale * 0.5;
+
+ if (m_hsprWhite != NULL)
+ {
+
+ float bgColor[] = { 0.1, 0.1, 0.1, 1 };
+ float borderColor[] = { 1, 1, 1, 1 };
+
+ gEngfuncs.pTriAPI->RenderMode(kRenderNormal);
+ gEngfuncs.pTriAPI->CullFace(TRI_NONE);
+
+ gEngfuncs.pTriAPI->SpriteTexture((struct model_s*)(gEngfuncs.GetSpritePointer(m_hsprWhite)), 0);
+ float gammaScale = 1.0f / gHUD.GetGammaSlope();
+
+ // Draw the background.
+
+ gEngfuncs.pTriAPI->Color4f(gammaScale * bgColor[0], gammaScale * bgColor[1], gammaScale * bgColor[2], bgColor[3]);
+
+ gEngfuncs.pTriAPI->Begin(TRI_QUADS);
+
+ gEngfuncs.pTriAPI->Vertex3f(theDrawInfo.mX, theDrawInfo.mY, 1);
+ gEngfuncs.pTriAPI->Vertex3f(theDrawInfo.mX, theDrawInfo.mY + theDrawInfo.mHeight, 1);
+ gEngfuncs.pTriAPI->Vertex3f(theDrawInfo.mX + theDrawInfo.mWidth, theDrawInfo.mY + theDrawInfo.mHeight, 1);
+ gEngfuncs.pTriAPI->Vertex3f(theDrawInfo.mX + theDrawInfo.mWidth, theDrawInfo.mY, 1);
+
+ gEngfuncs.pTriAPI->End();
+
+ // Draw the overview map.
+
+ theOverviewMap.Draw(theDrawInfo);
+
+ // Draw the border on the overview map and the inset view.
+
+ gEngfuncs.pTriAPI->RenderMode(kRenderNormal);
+ gEngfuncs.pTriAPI->CullFace(TRI_NONE);
+
+ gEngfuncs.pTriAPI->SpriteTexture((struct model_s*)(gEngfuncs.GetSpritePointer(m_hsprWhite)), 0);
+ gEngfuncs.pTriAPI->Color4f(gammaScale * borderColor[0], gammaScale * borderColor[1], gammaScale * borderColor[2], borderColor[3]);
+
+ gEngfuncs.pTriAPI->Begin(TRI_LINES);
+
+ gEngfuncs.pTriAPI->Vertex3f(theDrawInfo.mX, theDrawInfo.mY, 1);
+ gEngfuncs.pTriAPI->Vertex3f(theDrawInfo.mX, theDrawInfo.mY + theDrawInfo.mHeight, 1);
+
+ gEngfuncs.pTriAPI->Vertex3f(theDrawInfo.mX, theDrawInfo.mY + theDrawInfo.mHeight, 1);
+ gEngfuncs.pTriAPI->Vertex3f(theDrawInfo.mX + theDrawInfo.mWidth, theDrawInfo.mY + theDrawInfo.mHeight, 1);
+
+ gEngfuncs.pTriAPI->Vertex3f(theDrawInfo.mX + theDrawInfo.mWidth, theDrawInfo.mY + theDrawInfo.mHeight, 1);
+ gEngfuncs.pTriAPI->Vertex3f(theDrawInfo.mX + theDrawInfo.mWidth, theDrawInfo.mY, 1);
+
+ gEngfuncs.pTriAPI->Vertex3f(theDrawInfo.mX + theDrawInfo.mWidth, theDrawInfo.mY, 1);
+ gEngfuncs.pTriAPI->Vertex3f(theDrawInfo.mX, theDrawInfo.mY, 1);
+
+ int insetX1 = XRES(m_OverviewData.insetWindowX);
+ int insetY1 = YRES(m_OverviewData.insetWindowY);
+ int insetX2 = insetX1 + XRES(m_OverviewData.insetWindowWidth);
+ int insetY2 = insetY1 + YRES(m_OverviewData.insetWindowHeight);
+
+ gEngfuncs.pTriAPI->Vertex3f(insetX1, insetY1, 1);
+ gEngfuncs.pTriAPI->Vertex3f(insetX2, insetY1, 1);
+
+ gEngfuncs.pTriAPI->Vertex3f(insetX2, insetY1, 1);
+ gEngfuncs.pTriAPI->Vertex3f(insetX2, insetY2, 1);
+
+ gEngfuncs.pTriAPI->Vertex3f(insetX2, insetY2, 1);
+ gEngfuncs.pTriAPI->Vertex3f(insetX1, insetY2, 1);
+
+ gEngfuncs.pTriAPI->Vertex3f(insetX1, insetY2, 1);
+ gEngfuncs.pTriAPI->Vertex3f(insetX1, insetY1, 1);
+
+ gEngfuncs.pTriAPI->End();
+
+ }
+
+
+}
+
+#include "parsemsg.h"
+void CHudSpectator::DirectorMessage( int iSize, void *pbuf )
+{
+ float value;
+ char * string;
+
+ BEGIN_READ( pbuf, iSize );
+
+ int cmd = READ_BYTE();
+
+ switch ( cmd ) // director command byte
+ {
+ case DRC_CMD_START :
+ // now we have to do some things clientside, since the proxy doesn't know our mod
+ g_iPlayerClass = 0;
+ g_iTeamNumber = 0;
+
+ // fake a InitHUD & ResetHUD message
+ gHUD.MsgFunc_InitHUD(NULL,0, NULL);
+ gHUD.MsgFunc_ResetHUD(NULL, 0, NULL);
+
+ break;
+
+ case DRC_CMD_EVENT :
+ m_lastPrimaryObject = READ_WORD();
+ m_lastSecondaryObject = READ_WORD();
+ m_iObserverFlags = READ_LONG();
+
+ if ( m_autoDirector->value )
+ {
+ if ( (g_iUser2 != m_lastPrimaryObject) || (g_iUser3 != m_lastSecondaryObject) )
+ V_ResetChaseCam();
+
+ g_iUser2 = m_lastPrimaryObject;
+ g_iUser3 = m_lastSecondaryObject;
+ }
+
+ break;
+
+ case DRC_CMD_MODE :
+ if ( m_autoDirector->value )
+ {
+ SetMode( READ_BYTE());
+ }
+ break;
+
+ case DRC_CMD_CAMERA :
+ if ( m_autoDirector->value )
+ {
+ vJumpOrigin[0] = READ_COORD(); // position
+ vJumpOrigin[1] = READ_COORD();
+ vJumpOrigin[2] = READ_COORD();
+
+ vJumpAngles[0] = READ_COORD(); // view angle
+ vJumpAngles[1] = READ_COORD();
+ vJumpAngles[2] = READ_COORD();
+
+ gEngfuncs.SetViewAngles( vJumpAngles );
+
+ iJumpSpectator = 1;
+ }
+ break;
+
+ case DRC_CMD_MESSAGE:
+ {
+ client_textmessage_t * msg = &m_HUDMessages[m_lastHudMessage];
+
+ msg->effect = READ_BYTE(); // effect
+
+ UnpackRGB( (int&)msg->r1, (int&)msg->g1, (int&)msg->b1, READ_LONG() ); // color
+ msg->r2 = msg->r1;
+ msg->g2 = msg->g1;
+ msg->b2 = msg->b1;
+ msg->a2 = msg->a1 = 0xFF; // not transparent
+
+ msg->x = READ_FLOAT(); // x pos
+ msg->y = READ_FLOAT(); // y pos
+
+ msg->fadein = READ_FLOAT(); // fadein
+ msg->fadeout = READ_FLOAT(); // fadeout
+ msg->holdtime = READ_FLOAT(); // holdtime
+ msg->fxtime = READ_FLOAT(); // fxtime;
+
+ strncpy( m_HUDMessageText[m_lastHudMessage], READ_STRING(), 128 );
+ m_HUDMessageText[m_lastHudMessage][127]=0; // text
+
+ msg->pMessage = m_HUDMessageText[m_lastHudMessage];
+ msg->pName = "HUD_MESSAGE";
+
+ gHUD.m_Message.MessageAdd( msg->pName, gHUD.m_flTime);
+
+ m_lastHudMessage++;
+ m_lastHudMessage %= MAX_SPEC_HUD_MESSAGES;
+
+ }
+
+ break;
+
+ case DRC_CMD_SOUND :
+ string = READ_STRING();
+ value = READ_FLOAT();
+
+ gEngfuncs.pEventAPI->EV_PlaySound(0, v_origin, CHAN_BODY, string, value, ATTN_NORM, 0, PITCH_NORM );
+
+ break;
+
+ case DRC_CMD_TIMESCALE :
+ value = READ_FLOAT();
+ break;
+
+
+
+ case DRC_CMD_STATUS:
+ READ_LONG(); // total number of spectator slots
+ m_iSpectatorNumber = READ_LONG(); // total number of spectator
+ READ_WORD(); // total number of relay proxies
+
+ gViewPort->UpdateSpectatorPanel();
+ break;
+
+ case DRC_CMD_BANNER:
+ // gEngfuncs.Con_DPrintf("GUI: Banner %s\n",READ_STRING() ); // name of banner tga eg gfx/temp/7454562234563475.tga
+ gViewPort->m_pSpectatorPanel->m_TopBanner->LoadImage( READ_STRING() );
+ gViewPort->UpdateSpectatorPanel();
+ break;
+
+ case DRC_CMD_FADE:
+ break;
+
+ case DRC_CMD_STUFFTEXT:
+ ClientCmd( READ_STRING() );
+ break;
+
+ default : gEngfuncs.Con_DPrintf("CHudSpectator::DirectorMessage: unknown command %i.\n", cmd );
+ }
+}
+
+void CHudSpectator::FindNextPlayer(bool bReverse)
+{
+ // MOD AUTHORS: Modify the logic of this function if you want to restrict the observer to watching
+ // only a subset of the players. e.g. Make it check the target's team.
+
+ int iStart;
+ cl_entity_t * pEnt = NULL;
+
+ // if we are NOT in HLTV mode, spectator targets are set on server
+ if ( !gEngfuncs.IsSpectateOnly() )
+ {
+ char cmdstring[32];
+ // forward command to server
+ sprintf(cmdstring,"follownext %i",bReverse?1:0);
+ gEngfuncs.pfnServerCmd(cmdstring);
+ return;
+ }
+
+ if ( g_iUser2 )
+ iStart = g_iUser2;
+ else
+ iStart = 1;
+
+ g_iUser2 = 0;
+
+ int iCurrent = iStart;
+
+ int iDir = bReverse ? -1 : 1;
+
+ // make sure we have player info
+ gViewPort->GetAllPlayersInfo();
+
+
+ do
+ {
+ iCurrent += iDir;
+
+ // Loop through the clients
+ if (iCurrent > MAX_PLAYERS)
+ iCurrent = 1;
+ if (iCurrent < 1)
+ iCurrent = MAX_PLAYERS;
+
+ pEnt = gEngfuncs.GetEntityByIndex( iCurrent );
+
+ if ( !IsActivePlayer( pEnt ) )
+ continue;
+
+ // MOD AUTHORS: Add checks on target here.
+
+ g_iUser2 = iCurrent;
+ break;
+
+ } while ( iCurrent != iStart );
+
+ // Did we find a target?
+ if ( !g_iUser2 )
+ {
+ gEngfuncs.Con_DPrintf( "No observer targets.\n" );
+ // take save camera position
+ VectorCopy(m_cameraOrigin, vJumpOrigin);
+ VectorCopy(m_cameraAngles, vJumpAngles);
+ }
+ else
+ {
+ // use new entity position for roaming
+ VectorCopy ( pEnt->origin, vJumpOrigin );
+ VectorCopy ( pEnt->angles, vJumpAngles );
+ }
+ iJumpSpectator = 1;
+}
+
+void CHudSpectator::HandleButtonsDown( int ButtonPressed )
+{
+ if ( !gViewPort )
+ return;
+
+ //Not in intermission.
+ if ( gHUD.m_iIntermission )
+ return;
+
+ if ( !g_iUser1 )
+ return; // dont do anything if not in spectator mode
+
+ // don't handle buttons during normal demo playback
+ if ( gEngfuncs.pDemoAPI->IsPlayingback() && !gEngfuncs.IsSpectateOnly() )
+ return;
+
+ int theNewMainMode = g_iUser1;
+
+ // Jump changes main window modes
+ if ( ButtonPressed & IN_JUMP )
+ {
+ bool theFirstPerson = (g_iUser1 == OBS_IN_EYE);
+ bool theInOverviewMode = gHUD.m_Spectator.IsInOverviewMode();
+
+ // NS
+ if(gHUD.GetIsNSMode())
+ {
+ // First-person full -> chase camera full -> firstperson with overview -> chase camera with overview
+ if(theFirstPerson && !theInOverviewMode)
+ {
+ gHUD.m_Spectator.SetMode(OBS_CHASE_LOCKED);
+ //gHUD.m_Spectator.SetOverviewMode(false);
+ }
+ else if(!theFirstPerson && !theInOverviewMode)
+ {
+ gHUD.m_Spectator.SetMode(OBS_IN_EYE);
+ gHUD.m_Spectator.SetOverviewMode(true);
+ }
+ else if(theFirstPerson && theInOverviewMode)
+ {
+ gHUD.m_Spectator.SetMode(OBS_CHASE_LOCKED);
+ //gHUD.m_Spectator.SetOverviewMode(true);
+ }
+ else if(!theFirstPerson && theInOverviewMode)
+ {
+ gHUD.m_Spectator.SetMode(OBS_IN_EYE);
+ gHUD.m_Spectator.SetOverviewMode(false);
+ }
+ }
+ // Combat
+ else
+ {
+ // First-person full -> chase camera full
+ if(theFirstPerson)
+ {
+ gHUD.m_Spectator.SetMode(OBS_CHASE_LOCKED);
+ gHUD.m_Spectator.SetOverviewMode(false);
+ }
+ else
+ {
+ gHUD.m_Spectator.SetMode(OBS_IN_EYE);
+ gHUD.m_Spectator.SetOverviewMode(false);
+ }
+ }
+ }
+
+ //g_iUser1 = theNewMainMode;
+
+ // Attack moves to the next player
+ if ( ButtonPressed & (IN_MOVELEFT | IN_MOVERIGHT) )
+ {
+ FindNextPlayer( (ButtonPressed & IN_MOVELEFT) ? true:false );
+
+// if ( g_iUser1 == OBS_ROAMING )
+// {
+// gEngfuncs.SetViewAngles( vJumpAngles );
+// iJumpSpectator = 1;
+//
+// }
+
+ // lease directed mode if player want to see another player
+ m_autoDirector->value = 0.0f;
+ }
+
+/*
+ double time = gEngfuncs.GetClientTime();
+
+ int newMainMode = g_iUser1;
+ int newInsetMode = m_pip->value;
+
+ // gEngfuncs.Con_Printf(" HandleButtons:%i\n", ButtonPressed );
+ if ( !gViewPort )
+ return;
+
+ //Not in intermission.
+ if ( gHUD.m_iIntermission )
+ return;
+
+ if ( !g_iUser1 )
+ return; // dont do anything if not in spectator mode
+
+ // don't handle buttons during normal demo playback
+ if ( gEngfuncs.pDemoAPI->IsPlayingback() && !gEngfuncs.IsSpectateOnly() )
+ return;
+ // Slow down mouse clicks.
+ if ( m_flNextObserverInput > time )
+ return;
+
+ // enable spectator screen
+ if ( ButtonPressed & IN_DUCK )
+ {
+ gViewPort->m_pSpectatorPanel->ShowMenu(!gViewPort->m_pSpectatorPanel->m_menuVisible);
+ }
+
+ // 'Use' changes inset window mode
+ if ( ButtonPressed & IN_USE )
+ {
+ newInsetMode = ToggleInset(true);
+ }
+
+ // if not in HLTV mode, buttons are handled server side
+ if ( gEngfuncs.IsSpectateOnly() )
+ {
+ // changing target or chase mode not in overviewmode without inset window
+
+ // Jump changes main window modes
+ if ( ButtonPressed & IN_JUMP )
+ {
+ if ( g_iUser1 == OBS_CHASE_LOCKED )
+ newMainMode = OBS_CHASE_FREE;
+
+ else if ( g_iUser1 == OBS_CHASE_FREE )
+ newMainMode = OBS_IN_EYE;
+
+ else if ( g_iUser1 == OBS_IN_EYE )
+ newMainMode = OBS_ROAMING;
+
+ else if ( g_iUser1 == OBS_ROAMING )
+ newMainMode = OBS_MAP_FREE;
+
+ else if ( g_iUser1 == OBS_MAP_FREE )
+ newMainMode = OBS_MAP_CHASE;
+
+ else
+ newMainMode = OBS_CHASE_FREE; // don't use OBS_CHASE_LOCKED anymore
+ }
+
+ // Attack moves to the next player
+ if ( ButtonPressed & (IN_ATTACK | IN_ATTACK2) )
+ {
+ FindNextPlayer( (ButtonPressed & IN_ATTACK2) ? true:false );
+
+ if ( g_iUser1 == OBS_ROAMING )
+ {
+ gEngfuncs.SetViewAngles( vJumpAngles );
+ iJumpSpectator = 1;
+
+ }
+ // lease directed mode if player want to see another player
+ m_autoDirector->value = 0.0f;
+ }
+ }
+
+ SetModes(newMainMode, newInsetMode);
+
+ if ( g_iUser1 == OBS_MAP_FREE )
+ {
+ if ( ButtonPressed & IN_FORWARD )
+ m_zoomDelta = 0.01f;
+
+ if ( ButtonPressed & IN_BACK )
+ m_zoomDelta = -0.01f;
+
+ if ( ButtonPressed & IN_MOVELEFT )
+ m_moveDelta = -12.0f;
+
+ if ( ButtonPressed & IN_MOVERIGHT )
+ m_moveDelta = 12.0f;
+ }
+
+ m_flNextObserverInput = time + 0.2;
+*/
+
+}
+
+void CHudSpectator::HandleButtonsUp( int ButtonPressed )
+{
+ if ( !gViewPort )
+ return;
+
+ if ( !gViewPort->m_pSpectatorPanel->isVisible() )
+ return; // dont do anything if not in spectator mode
+
+ if ( ButtonPressed & (IN_FORWARD | IN_BACK) )
+ m_zoomDelta = 0.0f;
+
+ if ( ButtonPressed & (IN_MOVELEFT | IN_MOVERIGHT) )
+ m_moveDelta = 0.0f;
+}
+
+void CHudSpectator::SetMode(int iNewMainMode)
+{
+ // if value == -1 keep old value
+ if ( iNewMainMode == -1 )
+ iNewMainMode = g_iUser1;
+
+ // main modes ettings will override inset window settings
+ if ( iNewMainMode != g_iUser1 )
+ {
+ // if we are NOT in HLTV mode, main spectator mode is set on server
+ if ( !gEngfuncs.IsSpectateOnly() )
+ {
+ char cmdstring[32];
+ // forward command to server
+ sprintf(cmdstring,"specmode %i",iNewMainMode );
+ gEngfuncs.pfnServerCmd(cmdstring);
+ return;
+ }
+ else
+ {
+ if ( !g_iUser2 && (iNewMainMode !=OBS_ROAMING ) ) // make sure we have a target
+ {
+ // choose last Director object if still available
+ if ( IsActivePlayer( gEngfuncs.GetEntityByIndex( m_lastPrimaryObject ) ) )
+ {
+ g_iUser2 = m_lastPrimaryObject;
+ g_iUser3 = m_lastSecondaryObject;
+ }
+ else
+ {
+ FindNextPlayer(false); // find any target
+ }
+ }
+
+ switch ( iNewMainMode )
+ {
+ case OBS_CHASE_LOCKED:
+ g_iUser1 = OBS_CHASE_LOCKED;
+ break;
+
+ case OBS_CHASE_FREE:
+ g_iUser1 = OBS_CHASE_FREE;
+ break;
+
+ case OBS_ROAMING : // jump to current vJumpOrigin/angle
+ g_iUser1 = OBS_ROAMING;
+ if ( g_iUser2 )
+ {
+ V_GetChasePos( g_iUser2, v_cl_angles, vJumpOrigin, vJumpAngles );
+ gEngfuncs.SetViewAngles( vJumpAngles );
+ iJumpSpectator = 1;
+ }
+ break;
+
+ case OBS_IN_EYE:
+ g_iUser1 = OBS_IN_EYE;
+ break;
+
+ /*
+ case OBS_MAP_FREE : g_iUser1 = OBS_MAP_FREE;
+ // reset user values
+ m_mapZoom = m_OverviewData.zoom;
+ m_mapOrigin = m_OverviewData.origin;
+ break;
+
+ case OBS_MAP_CHASE : g_iUser1 = OBS_MAP_CHASE;
+ // reset user values
+ m_mapZoom = m_OverviewData.zoom;
+ m_mapOrigin = m_OverviewData.origin;
+ break;
+ */
+ }
+
+ if ( (g_iUser1 == OBS_IN_EYE) || (g_iUser1 == OBS_ROAMING) )
+ {
+ m_crosshairRect.left = 24;
+ m_crosshairRect.top = 0;
+ m_crosshairRect.right = 48;
+ m_crosshairRect.bottom = 24;
+
+ gHUD.SetCurrentCrosshair( m_hCrosshair, m_crosshairRect, 255, 255, 255 );
+ }
+ else
+ {
+ memset( &m_crosshairRect,0,sizeof(m_crosshairRect) );
+ gHUD.SetCurrentCrosshair( 0, m_crosshairRect, 0, 0, 0 );
+ }
+
+ //char string[128];
+ //sprintf(string, "#Spec_Mode%d", g_iUser1 );
+ //sprintf(string, "%c%s", HUD_PRINTCENTER, CHudTextMessage::BufferedLocaliseTextString( string ));
+ //gHUD.m_TextMessage.MsgFunc_TextMsg(NULL, strlen(string)+1, string );
+ }
+ }
+
+ gViewPort->UpdateSpectatorPanel();
+}
+
+bool CHudSpectator::IsActivePlayer(cl_entity_t * ent)
+{
+ return ( ent &&
+ ent->player &&
+ ent->curstate.solid != SOLID_NOT &&
+ ent != gEngfuncs.GetLocalPlayer() &&
+ g_PlayerInfoList[ent->index].name != NULL
+ );
+}
+
+
+bool CHudSpectator::ParseOverviewFile( )
+{
+ //char filename[255];
+ //char levelname[255];
+ //char token[1024];
+ //float height;
+
+ char *pfile = NULL;
+
+ memset( &m_OverviewData, 0, sizeof(m_OverviewData));
+
+ // fill in standrd values
+ m_OverviewData.insetWindowX = 4; // upper left corner
+ m_OverviewData.insetWindowY = 4 + SPECTATOR_PANEL_HEIGHT;
+ m_OverviewData.insetWindowHeight = 180;
+ m_OverviewData.insetWindowWidth = 240;
+ m_OverviewData.origin[0] = 0.0f;
+ m_OverviewData.origin[1] = 0.0f;
+ m_OverviewData.origin[2] = 0.0f;
+ m_OverviewData.zoom = 1.0f;
+ m_OverviewData.layers = 0;
+ m_OverviewData.layersHeights[0] = 0.0f;
+ strcpy( m_OverviewData.map, gEngfuncs.pfnGetLevelName() );
+
+ if ( strlen( m_OverviewData.map ) == 0 )
+ return false; // not active yet
+
+ /*
+ strcpy(levelname, m_OverviewData.map + 5);
+ levelname[strlen(levelname)-4] = 0;
+
+ sprintf(filename, "overviews/%s.txt", levelname );
+
+ pfile = (char *)gEngfuncs.COM_LoadFile( filename, 5, NULL);
+
+ if (!pfile)
+ {
+ gEngfuncs.Con_Printf("Couldn't open file %s. Using default values for overiew mode.\n", filename );
+ return false;
+ }
+
+ while (true)
+ {
+ pfile = gEngfuncs.COM_ParseFile(pfile, token);
+
+ if (!pfile)
+ break;
+
+ if ( !stricmp( token, "global" ) )
+ {
+ // parse the global data
+ pfile = gEngfuncs.COM_ParseFile(pfile, token);
+ if ( stricmp( token, "{" ) )
+ {
+ gEngfuncs.Con_Printf("Error parsing overview file %s. (expected { )\n", filename );
+ return false;
+ }
+
+ pfile = gEngfuncs.COM_ParseFile(pfile,token);
+
+ while (stricmp( token, "}") )
+ {
+ if ( !stricmp( token, "zoom" ) )
+ {
+ pfile = gEngfuncs.COM_ParseFile(pfile,token);
+ m_OverviewData.zoom = atof( token );
+ }
+ else if ( !stricmp( token, "origin" ) )
+ {
+ pfile = gEngfuncs.COM_ParseFile(pfile, token);
+ m_OverviewData.origin[0] = atof( token );
+ pfile = gEngfuncs.COM_ParseFile(pfile,token);
+ m_OverviewData.origin[1] = atof( token );
+ pfile = gEngfuncs.COM_ParseFile(pfile, token);
+ m_OverviewData.origin[2] = atof( token );
+ }
+ else if ( !stricmp( token, "rotated" ) )
+ {
+ pfile = gEngfuncs.COM_ParseFile(pfile,token);
+ m_OverviewData.rotated = atoi( token );
+ }
+ else if ( !stricmp( token, "inset" ) )
+ {
+
+ // Removed by mmcguire.
+ // This isn't supported anymore.
+ pfile = gEngfuncs.COM_ParseFile(pfile,token);
+ //m_OverviewData.insetWindowX = atof( token );
+ pfile = gEngfuncs.COM_ParseFile(pfile,token);
+ //m_OverviewData.insetWindowY = atof( token );
+ pfile = gEngfuncs.COM_ParseFile(pfile,token);
+ //m_OverviewData.insetWindowWidth = atof( token );
+ pfile = gEngfuncs.COM_ParseFile(pfile,token);
+ //m_OverviewData.insetWindowHeight = atof( token );
+
+ }
+ else
+ {
+ gEngfuncs.Con_Printf("Error parsing overview file %s. (%s unkown)\n", filename, token );
+ return false;
+ }
+
+ pfile = gEngfuncs.COM_ParseFile(pfile,token); // parse next token
+
+ }
+ }
+ else if ( !stricmp( token, "layer" ) )
+ {
+ // parse a layer data
+
+ if ( m_OverviewData.layers == OVERVIEW_MAX_LAYERS )
+ {
+ gEngfuncs.Con_Printf("Error parsing overview file %s. ( too many layers )\n", filename );
+ return false;
+ }
+
+ pfile = gEngfuncs.COM_ParseFile(pfile,token);
+
+
+ if ( stricmp( token, "{" ) )
+ {
+ gEngfuncs.Con_Printf("Error parsing overview file %s. (expected { )\n", filename );
+ return false;
+ }
+
+ pfile = gEngfuncs.COM_ParseFile(pfile,token);
+
+ while (stricmp( token, "}") )
+ {
+ if ( !stricmp( token, "image" ) )
+ {
+ pfile = gEngfuncs.COM_ParseFile(pfile,token);
+ strcpy(m_OverviewData.layersImages[ m_OverviewData.layers ], token);
+
+
+ }
+ else if ( !stricmp( token, "height" ) )
+ {
+ pfile = gEngfuncs.COM_ParseFile(pfile,token);
+ height = atof(token);
+ m_OverviewData.layersHeights[ m_OverviewData.layers ] = height;
+ }
+ else
+ {
+ gEngfuncs.Con_Printf("Error parsing overview file %s. (%s unkown)\n", filename, token );
+ return false;
+ }
+
+ pfile = gEngfuncs.COM_ParseFile(pfile,token); // parse next token
+ }
+
+ m_OverviewData.layers++;
+
+ }
+ }
+
+ gEngfuncs.COM_FreeFile( pfile );
+ */
+
+ m_mapZoom = m_OverviewData.zoom;
+ m_mapOrigin = m_OverviewData.origin;
+
+ return true;
+
+}
+
+void CHudSpectator::LoadMapSprites()
+{
+ // right now only support for one map layer
+ if (m_OverviewData.layers > 0 )
+ {
+ m_MapSprite = gEngfuncs.LoadMapSprite( m_OverviewData.layersImages[0] );
+ }
+ else
+ m_MapSprite = NULL; // the standard "unkown map" sprite will be used instead
+}
+
+void CHudSpectator::DrawOverviewLayer()
+{
+ float screenaspect, xs, ys, xStep, yStep, x,y,z;
+ int ix,iy,i,xTiles,yTiles,frame;
+
+ qboolean hasMapImage = m_MapSprite?TRUE:FALSE;
+ model_t * dummySprite = (struct model_s *)gEngfuncs.GetSpritePointer( m_hsprUnkownMap);
+
+ if ( hasMapImage)
+ {
+ i = m_MapSprite->numframes / (4*3);
+ i = sqrt((float)i);
+ xTiles = i*4;
+ yTiles = i*3;
+ }
+ else
+ {
+ xTiles = 8;
+ yTiles = 6;
+ }
+
+
+ screenaspect = 4.0f/3.0f;
+
+
+ xs = m_OverviewData.origin[0];
+ ys = m_OverviewData.origin[1];
+ z = ( 90.0f - v_angles[0] ) / 90.0f;
+ z *= m_OverviewData.layersHeights[0]; // gOverviewData.z_min - 32;
+
+ // i = r_overviewTexture + ( layer*OVERVIEW_X_TILES*OVERVIEW_Y_TILES );
+
+ gEngfuncs.pTriAPI->RenderMode( kRenderTransTexture );
+ gEngfuncs.pTriAPI->CullFace( TRI_NONE );
+ gEngfuncs.pTriAPI->Color4f( 1.0, 1.0, 1.0, 1.0 );
+
+ frame = 0;
+
+
+ // rotated view ?
+ if ( m_OverviewData.rotated )
+ {
+ xStep = (2*4096.0f / m_OverviewData.zoom ) / xTiles;
+ yStep = -(2*4096.0f / (m_OverviewData.zoom* screenaspect) ) / yTiles;
+
+ y = ys + (4096.0f / (m_OverviewData.zoom * screenaspect));
+
+ for (iy = 0; iy < yTiles; iy++)
+ {
+ x = xs - (4096.0f / (m_OverviewData.zoom));
+
+ for (ix = 0; ix < xTiles; ix++)
+ {
+ if (hasMapImage)
+ gEngfuncs.pTriAPI->SpriteTexture( m_MapSprite, frame );
+ else
+ gEngfuncs.pTriAPI->SpriteTexture( dummySprite, 0 );
+
+ gEngfuncs.pTriAPI->Begin( TRI_QUADS );
+ gEngfuncs.pTriAPI->TexCoord2f( 0, 0 );
+ gEngfuncs.pTriAPI->Vertex3f (x, y, z);
+
+ gEngfuncs.pTriAPI->TexCoord2f( 1, 0 );
+ gEngfuncs.pTriAPI->Vertex3f (x+xStep ,y, z);
+
+ gEngfuncs.pTriAPI->TexCoord2f( 1, 1 );
+ gEngfuncs.pTriAPI->Vertex3f (x+xStep, y+yStep, z);
+
+ gEngfuncs.pTriAPI->TexCoord2f( 0, 1 );
+ gEngfuncs.pTriAPI->Vertex3f (x, y+yStep, z);
+ gEngfuncs.pTriAPI->End();
+
+ frame++;
+ x+= xStep;
+ }
+
+ y+=yStep;
+ }
+ }
+ else
+ {
+ xStep = -(2*4096.0f / m_OverviewData.zoom ) / xTiles;
+ yStep = -(2*4096.0f / (m_OverviewData.zoom* screenaspect) ) / yTiles;
+
+
+ x = xs + (4096.0f / (m_OverviewData.zoom * screenaspect ));
+
+
+
+ for (ix = 0; ix < yTiles; ix++)
+ {
+
+ y = ys + (4096.0f / (m_OverviewData.zoom));
+
+ for (iy = 0; iy < xTiles; iy++)
+ {
+ if (hasMapImage)
+ gEngfuncs.pTriAPI->SpriteTexture( m_MapSprite, frame );
+ else
+ gEngfuncs.pTriAPI->SpriteTexture( dummySprite, 0 );
+
+ gEngfuncs.pTriAPI->Begin( TRI_QUADS );
+ gEngfuncs.pTriAPI->TexCoord2f( 0, 0 );
+ gEngfuncs.pTriAPI->Vertex3f (x, y, z);
+
+ gEngfuncs.pTriAPI->TexCoord2f( 0, 1 );
+ gEngfuncs.pTriAPI->Vertex3f (x+xStep ,y, z);
+
+ gEngfuncs.pTriAPI->TexCoord2f( 1, 1 );
+ gEngfuncs.pTriAPI->Vertex3f (x+xStep, y+yStep, z);
+
+ gEngfuncs.pTriAPI->TexCoord2f( 1, 0 );
+ gEngfuncs.pTriAPI->Vertex3f (x, y+yStep, z);
+ gEngfuncs.pTriAPI->End();
+
+ frame++;
+
+ y+=yStep;
+ }
+
+ x+= xStep;
+
+ }
+ }
+}
+
+void CHudSpectator::DrawOverviewEntities()
+{
+ /*
+ int i,ir,ig,ib;
+ struct model_s *hSpriteModel;
+ vec3_t origin, angles, point, forward, right, left, up, world, screen, offset;
+ float x,y,z, r,g,b, sizeScale = 4.0f;
+ cl_entity_t * ent;
+ float rmatrix[3][4]; // transformation matrix
+
+ float zScale = (90.0f - v_angles[0] ) / 90.0f;
+
+
+ z = m_OverviewData.layersHeights[0] * zScale;
+ // get yellow/brown HUD color
+ //UnpackRGB(ir,ig,ib, RGB_YELLOWISH);
+ gHUD.GetPrimaryHudColor(ir, ig, ib);
+ r = (float)ir/255.0f;
+ g = (float)ig/255.0f;
+ b = (float)ib/255.0f;
+
+ gEngfuncs.pTriAPI->CullFace( TRI_NONE );
+
+ for (i=0; i < MAX_PLAYERS; i++ )
+ m_vPlayerPos[i][2] = -1; // mark as invisible
+
+ // draw all players
+
+ float depthOffset = 0;
+
+ for (i=MAX_OVERVIEW_ENTITIES - 1; i >= 0; i--)
+ {
+ if ( !m_OverviewEntities[i].hSprite )
+ continue;
+
+ hSpriteModel = (struct model_s *)gEngfuncs.GetSpritePointer( m_OverviewEntities[i].hSprite );
+ ent = m_OverviewEntities[i].entity;
+
+ int theSpriteFrame = m_OverviewEntities[i].mFrame;
+ gEngfuncs.pTriAPI->SpriteTexture( hSpriteModel, theSpriteFrame);
+
+ gEngfuncs.pTriAPI->RenderMode( kRenderTransAdd);
+
+ // see R_DrawSpriteModel
+ // draws players sprite
+
+ AngleVectors(ent->angles, right, up, NULL );
+
+ VectorCopy(ent->origin,origin);
+
+ // Set origin of blip to just above map height, so blips are all drawn on map
+ origin.z = m_OverviewData.layersHeights[0] + kOverviewEntityZHeight + depthOffset;
+
+ gEngfuncs.pTriAPI->Begin( TRI_QUADS );
+
+ float gammaSlope = gHUD.GetGammaSlope();
+
+ gEngfuncs.pTriAPI->Color4f(
+ m_OverviewEntities[i].mColorR / gammaSlope,
+ m_OverviewEntities[i].mColorG / gammaSlope,
+ m_OverviewEntities[i].mColorB / gammaSlope,
+ 1);
+
+ gEngfuncs.pTriAPI->TexCoord2f (1, 0);
+ VectorMA (origin, 16.0f * sizeScale, up, point);
+ VectorMA (point, 16.0f * sizeScale, right, point);
+ point[2] *= zScale;
+ gEngfuncs.pTriAPI->Vertex3fv (point);
+
+ gEngfuncs.pTriAPI->TexCoord2f (0, 0);
+
+ VectorMA (origin, 16.0f * sizeScale, up, point);
+ VectorMA (point, -16.0f * sizeScale, right, point);
+ point[2] *= zScale;
+ gEngfuncs.pTriAPI->Vertex3fv (point);
+
+ gEngfuncs.pTriAPI->TexCoord2f (0,1);
+ VectorMA (origin, -16.0f * sizeScale, up, point);
+ VectorMA (point, -16.0f * sizeScale, right, point);
+ point[2] *= zScale;
+ gEngfuncs.pTriAPI->Vertex3fv (point);
+
+ gEngfuncs.pTriAPI->TexCoord2f (1,1);
+ VectorMA (origin, -16.0f * sizeScale, up, point);
+ VectorMA (point, 16.0f * sizeScale, right, point);
+ point[2] *= zScale;
+ gEngfuncs.pTriAPI->Vertex3fv (point);
+
+ gEngfuncs.pTriAPI->End ();
+
+
+ if ( !ent->player)
+ continue;
+ // draw line under player icons
+ origin[2] *= zScale;
+
+ gEngfuncs.pTriAPI->RenderMode( kRenderTransAdd );
+
+ hSpriteModel = (struct model_s *)gEngfuncs.GetSpritePointer( m_hsprBeam );
+ gEngfuncs.pTriAPI->SpriteTexture( hSpriteModel, 0 );
+
+ gEngfuncs.pTriAPI->Color4f(r, g, b, 0.3);
+
+ gEngfuncs.pTriAPI->Begin ( TRI_QUADS );
+ gEngfuncs.pTriAPI->TexCoord2f (1, 0);
+ gEngfuncs.pTriAPI->Vertex3f (origin[0]+4, origin[1]+4, origin[2]-zScale);
+ gEngfuncs.pTriAPI->TexCoord2f (0, 0);
+ gEngfuncs.pTriAPI->Vertex3f (origin[0]-4, origin[1]-4, origin[2]-zScale);
+ gEngfuncs.pTriAPI->TexCoord2f (0, 1);
+ gEngfuncs.pTriAPI->Vertex3f (origin[0]-4, origin[1]-4,z);
+ gEngfuncs.pTriAPI->TexCoord2f (1, 1);
+ gEngfuncs.pTriAPI->Vertex3f (origin[0]+4, origin[1]+4,z);
+ gEngfuncs.pTriAPI->End ();
+
+ gEngfuncs.pTriAPI->Begin ( TRI_QUADS );
+ gEngfuncs.pTriAPI->TexCoord2f (1, 0);
+ gEngfuncs.pTriAPI->Vertex3f (origin[0]-4, origin[1]+4, origin[2]-zScale);
+ gEngfuncs.pTriAPI->TexCoord2f (0, 0);
+ gEngfuncs.pTriAPI->Vertex3f (origin[0]+4, origin[1]-4, origin[2]-zScale);
+ gEngfuncs.pTriAPI->TexCoord2f (0, 1);
+ gEngfuncs.pTriAPI->Vertex3f (origin[0]+4, origin[1]-4,z);
+ gEngfuncs.pTriAPI->TexCoord2f (1, 1);
+ gEngfuncs.pTriAPI->Vertex3f (origin[0]-4, origin[1]+4,z);
+ gEngfuncs.pTriAPI->End ();
+
+ // calculate screen position for name and infromation in hud::draw()
+ if ( gEngfuncs.pTriAPI->WorldToScreen(origin,screen) )
+ continue; // object is behind viewer
+
+ screen[0] = XPROJECT(screen[0]);
+ screen[1] = YPROJECT(screen[1]);
+ screen[2] = 0.0f;
+
+ // calculate some offset under the icon
+ origin[0]+=32.0f;
+ origin[1]+=32.0f;
+
+ gEngfuncs.pTriAPI->WorldToScreen(origin,offset);
+
+ offset[0] = XPROJECT(offset[0]);
+ offset[1] = YPROJECT(offset[1]);
+ offset[2] = 0.0f;
+
+ VectorSubtract(offset, screen, offset );
+
+ int playerNum = ent->index - 1;
+
+ m_vPlayerPos[playerNum][0] = screen[0];
+ m_vPlayerPos[playerNum][1] = screen[1] + Length(offset);
+ m_vPlayerPos[playerNum][2] = 1; // mark player as visible
+
+
+ }
+
+ if ( !m_pip || !m_drawcone->value )
+ return;
+
+ // get current camera position and angle
+
+ if ( m_pip == INSET_IN_EYE || g_iUser1 == OBS_IN_EYE )
+ {
+ V_GetInEyePos( g_iUser2, origin, angles );
+ }
+ else if ( m_pip == INSET_CHASE_FREE || g_iUser1 == OBS_CHASE_FREE )
+ {
+ V_GetChasePos( g_iUser2, v_cl_angles, origin, angles );
+ }
+ else if ( g_iUser1 == OBS_ROAMING )
+ {
+ VectorCopy( v_sim_org, origin );
+ VectorCopy( v_cl_angles, angles );
+ }
+ else
+ V_GetChasePos( g_iUser2, NULL, origin, angles );
+
+
+ // draw camera sprite
+
+ x = origin[0];
+ y = origin[1];
+ z = origin[2];
+
+ // Set origin of cone to just above map height, so blips are all drawn on map
+ z = m_OverviewData.layersHeights[0] + kOverviewEntityZHeight;
+
+ angles[0] = 0; // always show horizontal camera sprite
+
+ hSpriteModel = (struct model_s *)gEngfuncs.GetSpritePointer( m_hsprCamera );
+ gEngfuncs.pTriAPI->RenderMode( kRenderTransAdd );
+ gEngfuncs.pTriAPI->SpriteTexture( hSpriteModel, 0 );
+
+
+ gEngfuncs.pTriAPI->Color4f( r, g, b, 1.0 );
+
+ AngleVectors(angles, forward, NULL, NULL );
+ VectorScale (forward, 512.0f, forward);
+
+ offset[0] = 0.0f;
+ offset[1] = 45.0f;
+ offset[2] = 0.0f;
+
+ AngleMatrix(offset, rmatrix );
+ VectorTransform(forward, rmatrix , right );
+
+ offset[1]= -45.0f;
+ AngleMatrix(offset, rmatrix );
+ VectorTransform(forward, rmatrix , left );
+
+ gEngfuncs.pTriAPI->Begin (TRI_TRIANGLES);
+ gEngfuncs.pTriAPI->TexCoord2f( 0, 0 );
+ gEngfuncs.pTriAPI->Vertex3f (x+right[0], y+right[1], (z+right[2]) * zScale);
+
+ gEngfuncs.pTriAPI->TexCoord2f( 0, 1 );
+ gEngfuncs.pTriAPI->Vertex3f (x, y, z * zScale);
+
+ gEngfuncs.pTriAPI->TexCoord2f( 1, 1 );
+ gEngfuncs.pTriAPI->Vertex3f (x+left[0], y+left[1], (z+left[2]) * zScale);
+ gEngfuncs.pTriAPI->End ();
+ */
+
+}
+
+
+
+void CHudSpectator::DrawOverview()
+{
+ /*
+ // draw only in sepctator mode
+ if ( !g_iUser1 )
+ return;
+
+ // Only draw the overview if Map Mode is selected for this view
+ if ( m_iDrawCycle == 0 && ( (g_iUser1 != OBS_MAP_FREE) && (g_iUser1 != OBS_MAP_CHASE) ) )
+ return;
+
+ if ( m_iDrawCycle == 1 && m_pip->value < INSET_MAP_FREE )
+ return;
+
+ DrawOverviewLayer();
+ DrawOverviewEntities();
+ CheckOverviewEntities();
+ */
+
+}
+
+
+
+void CHudSpectator::CheckOverviewEntities()
+{
+ double time = gEngfuncs.GetClientTime();
+
+ // removes old entities from list
+ for ( int i = 0; i< MAX_OVERVIEW_ENTITIES; i++ )
+ {
+ // remove entity from list if it is too old
+ if ( m_OverviewEntities[i].killTime < time )
+ {
+ memset( &m_OverviewEntities[i], 0, sizeof (overviewEntity_t) );
+ }
+ }
+}
+
+bool CHudSpectator::AddOverviewEntity( int type, struct cl_entity_s *ent, const char *modelname)
+{
+ HSPRITE hSprite = 0;
+ double duration = -1.0f; // duration -1 means show it only this frame;
+ int theFrame = 0;
+ bool theSuccess = false;
+ int theRenderMode;
+
+ if ( ent )
+ {
+
+ if (ent->curstate.solid != SOLID_NOT)
+ {
+ gHUD.GetSpriteForUser3(AvHUser3(ent->curstate.iuser3), hSprite, theFrame, theRenderMode);
+ }
+
+ /*
+ if ( type == ET_PLAYER )
+ {
+ if ( ent->curstate.solid != SOLID_NOT)
+ {
+ int thePlayerClass = g_PlayerExtraInfo[ent->index].playerclass;
+ switch(thePlayerClass)
+ {
+ case PLAYERCLASS_ALIVE_MARINE:
+ hSprite = this->m_hsprPlayerMarine;
+ theFrame = 0;
+ break;
+ case PLAYERCLASS_ALIVE_HEAVY_MARINE:
+ hSprite = this->m_hsprPlayerMarine;
+ theFrame = 1;
+ break;
+ case PLAYERCLASS_COMMANDER:
+ hSprite = this->m_hsprPlayerMarine;
+ theFrame = 2;
+ break;
+ case PLAYERCLASS_ALIVE_LEVEL1:
+ hSprite = this->m_hsprPlayerAlien;
+ theFrame = 0;
+ break;
+ case PLAYERCLASS_ALIVE_LEVEL2:
+ hSprite = this->m_hsprPlayerAlien;
+ theFrame = 1;
+ break;
+ case PLAYERCLASS_ALIVE_LEVEL3:
+ hSprite = this->m_hsprPlayerAlien;
+ theFrame = 2;
+ break;
+ case PLAYERCLASS_ALIVE_LEVEL4:
+ hSprite = this->m_hsprPlayerAlien;
+ theFrame = 3;
+ break;
+ case PLAYERCLASS_ALIVE_LEVEL5:
+ hSprite = this->m_hsprPlayerAlien;
+ theFrame = 4;
+ break;
+ case PLAYERCLASS_ALIVE_GESTATING:
+ hSprite = this->m_hsprPlayerAlien;
+ theFrame = 5;
+ break;
+
+ case PLAYERCLASS_ALIVE_DIGESTING:
+ break;
+ }
+ }
+ else
+ {
+ // it's an spectator
+ }
+ }
+ else if (type == ET_NORMAL)
+ {
+ // Now help icons
+ if(hSprite == 0)
+ {
+ AvHUser3 theUser3 = AvHUser3(ent->curstate.iuser3);
+ theFrame = gHUD.GetHelpIconFrameFromUser3(theUser3);
+ if(theFrame != -1)
+ {
+ hSprite = gHUD.GetHelpSprite();
+ }
+ }
+ }
+ */
+ }
+
+ if(hSprite > 0)
+ {
+
+ int theTeam = ent->curstate.team;
+
+ float theR = kFTeamColors[theTeam][0];
+ float theG = kFTeamColors[theTeam][1];
+ float theB = kFTeamColors[theTeam][2];
+
+ theSuccess = AddOverviewEntityToList(hSprite, ent, gEngfuncs.GetClientTime() + duration, theFrame, theRenderMode, theR, theG, theB);
+
+ }
+
+ return theSuccess;
+}
+
+void CHudSpectator::DeathMessage(int victim)
+{
+ // find out where the victim is
+ cl_entity_t *pl = gEngfuncs.GetEntityByIndex(victim);
+
+ if (pl && pl->player)
+ AddOverviewEntityToList(m_hsprPlayerDead, pl, gEngfuncs.GetClientTime() + 2.0f, 0, kRenderTransTexture, 1, 1, 1);
+}
+
+bool CHudSpectator::AddOverviewEntityToList(HSPRITE sprite, cl_entity_t *ent, double killTime, int inFrame, int inRenderMode, float r, float g, float b)
+{
+ for ( int i = 0; i< MAX_OVERVIEW_ENTITIES; i++ )
+ {
+ // find empty entity slot
+ if ( m_OverviewEntities[i].entity == NULL)
+ {
+ m_OverviewEntities[i].entity = ent;
+ m_OverviewEntities[i].hSprite = sprite;
+ m_OverviewEntities[i].killTime = killTime;
+ m_OverviewEntities[i].mFrame = inFrame;
+ m_OverviewEntities[i].mRenderMode = inRenderMode;
+ m_OverviewEntities[i].mColorR = r;
+ m_OverviewEntities[i].mColorG = g;
+ m_OverviewEntities[i].mColorB = b;
+ return true;
+ }
+ }
+
+ return false; // maximum overview entities reached
+}
+void CHudSpectator::CheckSettings()
+{
+ // disallow same inset mode as main mode:
+
+ //m_pip->value = floor(m_pip->value);
+
+ // Removed by mmcguire.
+ /*
+ if ( ( g_iUser1 < OBS_MAP_FREE ) && ( m_pip->value == INSET_CHASE_LOCKED || m_pip->value == INSET_IN_EYE ) )
+ {
+ // otherwise both would show in World picures
+ m_pip->value = INSET_OFF;
+ }
+
+ // disble in intermission screen
+ if ( gHUD.m_iIntermission )
+ m_pip->value = INSET_OFF;
+ */
+
+ // check chat mode
+ if ( m_chatEnabled != (gHUD.m_SayText.m_HUD_saytext->value!=0) )
+ {
+ // hud_saytext changed
+ m_chatEnabled = (gHUD.m_SayText.m_HUD_saytext->value!=0);
+
+ if ( gEngfuncs.IsSpectateOnly() )
+ {
+ // tell proxy our new chat mode
+ char chatcmd[32];
+ sprintf(chatcmd, "ignoremsg %i", m_chatEnabled?0:1 );
+ gEngfuncs.pfnServerCmd(chatcmd);
+ }
+ }
+
+ // HL/TFC has no oberserver corsshair, so set it client side
+ if ( g_iUser1 == OBS_IN_EYE )
+ {
+ m_crosshairRect.left = 24;
+ m_crosshairRect.top = 0;
+ m_crosshairRect.right = 48;
+ m_crosshairRect.bottom = 24;
+
+ gHUD.SetCurrentCrosshair( m_hCrosshair, m_crosshairRect, 255, 255, 255 );
+ }
+ else
+ {
+ memset( &m_crosshairRect,0,sizeof(m_crosshairRect) );
+ gHUD.SetCurrentCrosshair( 0, m_crosshairRect, 0, 0, 0 );
+ }
+
+ // Removed by mmcguire.
+ /*
+ // if we are a real player on server don't allow inset window
+ // in First Person mode since this is our resticted forcecamera mode 2
+ // team number 3 = SPECTATOR see player.h
+
+ if ( ( (g_iTeamNumber == 1) || (g_iTeamNumber == 2)) && (g_iUser1 == OBS_IN_EYE) )
+ m_pip->value = INSET_OFF;
+ */
+
+ // draw small border around inset view, adjust upper black bar
+ //gViewPort->m_pSpectatorPanel->EnableInsetView( m_pip->value != INSET_OFF );
+ gViewPort->m_pSpectatorPanel->EnableInsetView( IsInOverviewMode() );
+
+}
+
+
+void CHudSpectator::Reset()
+{
+ // Reset HUD
+ if ( strcmp( m_OverviewData.map, gEngfuncs.pfnGetLevelName() ) )
+ {
+ // update level overview if level changed
+ ParseOverviewFile();
+ LoadMapSprites();
+ }
+
+ memset( &m_OverviewEntities, 0, sizeof(m_OverviewEntities));
+
+ SetSpectatorStartPosition();
+}
+
+void CHudSpectator::InitHUDData()
+{
+ gHUD.InitHUDData();
+ m_lastPrimaryObject = m_lastSecondaryObject = 0;
+ m_flNextObserverInput = 0.0f;
+ m_lastHudMessage = 0;
+ m_iSpectatorNumber = 0;
+ iJumpSpectator = 0;
+ g_iUser1 = g_iUser2 = 0;
+
+ memset( &m_OverviewData, 0, sizeof(m_OverviewData));
+ memset( &m_OverviewEntities, 0, sizeof(m_OverviewEntities));
+
+ if ( gEngfuncs.IsSpectateOnly() || gEngfuncs.pDemoAPI->IsPlayingback() )
+ m_autoDirector->value = 1.0f;
+ else
+ m_autoDirector->value = 0.0f;
+
+ Reset();
+
+ SetMode( OBS_CHASE_FREE);
+
+ g_iUser2 = 0; // fake not target until first camera command
+
+ // reset HUD FOV
+ gHUD.m_iFOV = CVAR_GET_FLOAT("default_fov");
+}
+
diff --git a/main/source/cl_dll/hud_spectator.cpp~ b/main/source/cl_dll/hud_spectator.cpp~
deleted file mode 100644
index ade1937b..00000000
--- a/main/source/cl_dll/hud_spectator.cpp~
+++ /dev/null
@@ -1,1957 +0,0 @@
-//========= Copyright � 1996-2002, Valve LLC, All rights reserved. ============
-//
-// Purpose:
-//
-// $NoKeywords: $
-//=============================================================================
-
-#include "hud.h"
-#include "cl_util.h"
-#include "common/cl_entity.h"
-#include "common/triangleapi.h"
-#include "vgui_TeamFortressViewport.h"
-#include "vgui_SpectatorPanel.h"
-#include "common/hltv.h"
-
-#include "pm_shared/pm_shared.h"
-#include "pm_shared/pm_defs.h"
-#include "common/pmtrace.h"
-#include "common/entity_types.h"
-
-// these are included for the math functions
-#include "common/com_model.h"
-#include "common/demo_api.h"
-#include "common/event_api.h"
-#include "studio_util.h"
-#include "common/screenfade.h"
-#include "util/STLUtil.h"
-#include "mod/AvHTitles.h"
-#include "mod/AvHSprites.h"
-
-#pragma warning(disable: 4244)
-
-extern int iJumpSpectator;
-extern float vJumpOrigin[3];
-extern float vJumpAngles[3];
-
-extern void V_GetInEyePos(int entity, float * origin, float * angles );
-extern void V_ResetChaseCam();
-extern void V_GetChasePos(int target, float * cl_angles, float * origin, float * angles);
-extern void VectorAngles( const float *forward, float *angles );
-extern "C" void NormalizeAngles( float *angles );
-extern float * GetClientColor( int clientIndex );
-
-extern vec3_t v_origin; // last view origin
-extern vec3_t v_angles; // last view angle
-extern vec3_t v_cl_angles; // last client/mouse angle
-extern vec3_t v_sim_org; // last sim origin
-
-void SpectatorMode(void)
-{
-
- if ( gEngfuncs.Cmd_Argc() <= 1 )
- {
- gEngfuncs.Con_Printf( "usage: spec_mode \n" );
- return;
- }
-
- // SetModes() will decide if command is executed on server or local
- if ( gEngfuncs.Cmd_Argc() == 2 )
- gHUD.m_Spectator.SetMode( atoi( gEngfuncs.Cmd_Argv(1) ));
-
- //else if ( gEngfuncs.Cmd_Argc() == 3 )
- // gHUD.m_Spectator.SetMode( atoi( gEngfuncs.Cmd_Argv(1) ), atoi( gEngfuncs.Cmd_Argv(2) ) );
-}
-
-void SpectatorSpray(void)
-{
- vec3_t forward;
- char string[128];
-
- if ( !gEngfuncs.IsSpectateOnly() )
- return;
-
- AngleVectors(v_angles,forward,NULL,NULL);
- VectorScale(forward, 128, forward);
- VectorAdd(forward, v_origin, forward);
- pmtrace_t * trace = gEngfuncs.PM_TraceLine( v_origin, forward, PM_TRACELINE_PHYSENTSONLY, 2, -1 );
- if ( trace->fraction != 1.0 )
- {
- sprintf(string, "drc_spray %.2f %.2f %.2f %i",
- trace->endpos[0], trace->endpos[1], trace->endpos[2], trace->ent );
- gEngfuncs.pfnServerCmd(string);
- }
-
-}
-void SpectatorHelp(void)
-{
- if ( gViewPort )
- {
- gViewPort->ShowVGUIMenu( MENU_SPECHELP );
- }
- else
- {
- char *text = CHudTextMessage::BufferedLocaliseTextString( "#Spec_Help_Text" );
-
- if ( text )
- {
- while ( *text )
- {
- if ( *text != 13 )
- gEngfuncs.Con_Printf( "%c", *text );
- text++;
- }
- }
- }
-}
-
-void SpectatorMenu( void )
-{
- if ( gEngfuncs.Cmd_Argc() <= 1 )
- {
- gEngfuncs.Con_Printf( "usage: spec_menu <0|1>\n" );
- return;
- }
-
- gViewPort->m_pSpectatorPanel->ShowMenu( atoi( gEngfuncs.Cmd_Argv(1))!=0 );
-}
-
-void ToggleScores( void )
-{
- if ( gViewPort )
- {
- if (gViewPort->IsScoreBoardVisible() )
- {
- gViewPort->HideScoreBoard();
- }
- else
- {
- gViewPort->ShowScoreBoard();
- }
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-int CHudSpectator::Init()
-{
- gHUD.AddHudElem(this);
-
- m_iFlags |= HUD_ACTIVE;
- m_flNextObserverInput = 0.0f;
- m_zoomDelta = 0.0f;
- m_moveDelta = 0.0f;
- iJumpSpectator = 0;
-
- memset( &m_OverviewData, 0, sizeof(m_OverviewData));
- memset( &m_OverviewEntities, 0, sizeof(m_OverviewEntities));
- m_lastPrimaryObject = m_lastSecondaryObject = 0;
-
- gEngfuncs.pfnAddCommand ("spec_mode", SpectatorMode );
- gEngfuncs.pfnAddCommand ("spec_decal", SpectatorSpray );
- gEngfuncs.pfnAddCommand ("spec_help", SpectatorHelp );
- gEngfuncs.pfnAddCommand ("spec_menu", SpectatorMenu );
- gEngfuncs.pfnAddCommand ("togglescores", ToggleScores );
-
- m_drawnames = gEngfuncs.pfnRegisterVariable("spec_drawnames","1",0);
- m_drawcone = gEngfuncs.pfnRegisterVariable("spec_drawcone","1",0);
- m_drawstatus = gEngfuncs.pfnRegisterVariable("spec_drawstatus","1",0);
- m_autoDirector = gEngfuncs.pfnRegisterVariable("spec_autodirector","1",0);
-
- // Removed by mmcguire.
- m_overviewMode = false;
- //m_overview = gEngfuncs.pfnRegisterVariable("spec_overview","1",0);
- //m_pip = gEngfuncs.pfnRegisterVariable("spec_pip","1",0);
-
- if ( !m_drawnames || !m_drawcone || !m_drawstatus || !m_autoDirector /*|| !m_pip*/)
- {
- gEngfuncs.Con_Printf("ERROR! Couldn't register all spectator variables.\n");
- return 0;
- }
-
- return 1;
-}
-
-
-//-----------------------------------------------------------------------------
-// UTIL_StringToVector originally from ..\dlls\util.cpp, slightly changed
-//-----------------------------------------------------------------------------
-
-void UTIL_StringToVector( float * pVector, const char *pString )
-{
- char *pstr, *pfront, tempString[128];
- int j;
-
- strcpy( tempString, pString );
- pstr = pfront = tempString;
-
- for ( j = 0; j < 3; j++ )
- {
- pVector[j] = atof( pfront );
-
- while ( *pstr && *pstr != ' ' )
- pstr++;
- if (!*pstr)
- break;
- pstr++;
- pfront = pstr;
- }
-
- if (j < 2)
- {
- for (j = j+1;j < 3; j++)
- pVector[j] = 0;
- }
-}
-
-int UTIL_FindEntityInMap(char * name, float * origin, float * angle)
-{
- int n,found = 0;
- char keyname[256];
- char token[1024];
-
- cl_entity_t * pEnt = gEngfuncs.GetEntityByIndex( 0 ); // get world model
-
- if ( !pEnt ) return 0;
-
- if ( !pEnt->model ) return 0;
-
- char * data = pEnt->model->entities;
-
- while (data)
- {
- data = gEngfuncs.COM_ParseFile(data, token);
-
- if ( (token[0] == '}') || (token[0]==0) )
- break;
-
- if (!data)
- {
- gEngfuncs.Con_DPrintf("UTIL_FindEntityInMap: EOF without closing brace\n");
- return 0;
- }
-
- if (token[0] != '{')
- {
- gEngfuncs.Con_DPrintf("UTIL_FindEntityInMap: expected {\n");
- return 0;
- }
-
- // we parse the first { now parse entities properties
-
- while ( 1 )
- {
- // parse key
- data = gEngfuncs.COM_ParseFile(data, token);
- if (token[0] == '}')
- break; // finish parsing this entity
-
- if (!data)
- {
- gEngfuncs.Con_DPrintf("UTIL_FindEntityInMap: EOF without closing brace\n");
- return 0;
- };
-
- strcpy (keyname, token);
-
- // another hack to fix keynames with trailing spaces
- n = (int)strlen(keyname);
- while (n && keyname[n-1] == ' ')
- {
- keyname[n-1] = 0;
- n--;
- }
-
- // parse value
- data = gEngfuncs.COM_ParseFile(data, token);
- if (!data)
- {
- gEngfuncs.Con_DPrintf("UTIL_FindEntityInMap: EOF without closing brace\n");
- return 0;
- };
-
- if (token[0] == '}')
- {
- gEngfuncs.Con_DPrintf("UTIL_FindEntityInMap: closing brace without data");
- return 0;
- }
-
- if (!strcmp(keyname,"classname"))
- {
- if (!strcmp(token, name ))
- {
- found = 1; // thats our entity
- }
- };
-
- if( !strcmp( keyname, "angle" ) )
- {
- float y = atof( token );
-
- if (y >= 0)
- {
- angle[0] = 0.0f;
- angle[1] = y;
- }
- else if ((int)y == -1)
- {
- angle[0] = -90.0f;
- angle[1] = 0.0f;;
- }
- else
- {
- angle[0] = 90.0f;
- angle[1] = 0.0f;
- }
-
- angle[2] = 0.0f;
- }
-
- if( !strcmp( keyname, "angles" ) )
- {
- UTIL_StringToVector(angle, token);
- }
-
- if (!strcmp(keyname,"origin"))
- {
- UTIL_StringToVector(origin, token);
-
- };
-
- } // while (1)
-
- if (found)
- return 1;
-
- }
-
- return 0; // we search all entities, but didn't found the correct
-
-}
-
-//-----------------------------------------------------------------------------
-// SetSpectatorStartPosition():
-// Get valid map position and 'beam' spectator to this position
-//-----------------------------------------------------------------------------
-
-void CHudSpectator::SetSpectatorStartPosition()
-{
- // search for info_player start
- if ( UTIL_FindEntityInMap( "trigger_camera", m_cameraOrigin, m_cameraAngles ) )
- iJumpSpectator = 1;
-
- else if ( UTIL_FindEntityInMap( "info_player_start", m_cameraOrigin, m_cameraAngles ) )
- iJumpSpectator = 1;
-
- else if ( UTIL_FindEntityInMap( "info_player_deathmatch", m_cameraOrigin, m_cameraAngles ) )
- iJumpSpectator = 1;
-
- else if ( UTIL_FindEntityInMap( "info_player_coop", m_cameraOrigin, m_cameraAngles ) )
- iJumpSpectator = 1;
- else
- {
- // jump to 0,0,0 if no better position was found
- VectorCopy(vec3_origin, m_cameraOrigin);
- VectorCopy(vec3_origin, m_cameraAngles);
- }
-
- VectorCopy(m_cameraOrigin, vJumpOrigin);
- VectorCopy(m_cameraAngles, vJumpAngles);
-
- iJumpSpectator = 1; // jump anyway
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Loads new icons
-//-----------------------------------------------------------------------------
-int CHudSpectator::VidInit()
-{
- m_hsprPlayerMarine = SPR_Load("sprites/iplayerm.spr");
- m_hsprPlayerAlien = SPR_Load("sprites/iplayera.spr");
- m_hsprPlayerDead = SPR_Load("sprites/iplayerdead.spr");
- m_hsprUnkownMap = SPR_Load("sprites/tile.spr");
- //m_hsprBeam = SPR_Load("sprites/laserbeam.spr");
- //m_hsprCamera = SPR_Load("sprites/camera.spr");
- m_hCrosshair = SPR_Load("sprites/crosshairs.spr");
- m_hsprWhite = SPR_Load(kWhiteSprite);
-
- return 1;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-// Input : flTime -
-// intermission -
-//-----------------------------------------------------------------------------
-int CHudSpectator::Draw(float flTime)
-{
-
- // draw only in spectator mode
- if ( !g_iUser1 )
- return 0;
-// string error;
-// gHUD.Update( flTime, error);
-
- // Removed by mmcguire.
- /*
- // if user pressed zoom, aplly changes
- if ( (m_zoomDelta != 0.0f) && ( g_iUser1 == OBS_MAP_FREE ) )
- {
- m_mapZoom += m_zoomDelta;
-
- if ( m_mapZoom > 3.0f )
- m_mapZoom = 3.0f;
-
- if ( m_mapZoom < 0.5f )
- m_mapZoom = 0.5f;
- }
-
- // if user moves in map mode, change map origin
- if ( (m_moveDelta != 0.0f) && (g_iUser1 != OBS_ROAMING) )
- {
- vec3_t right;
- AngleVectors(v_angles, NULL, right, NULL);
- VectorNormalize(right);
- VectorScale(right, m_moveDelta, right );
-
- VectorAdd( m_mapOrigin, right, m_mapOrigin )
-
- }
- */
-
- //DrawOverviewMap();
-
-/*
- if (!IsInOverviewMode())
- {
- return 0;
- }
-
- if (m_hsprWhite != NULL)
- {
-
- float bgColor[] = { 0.1, 0.1, 0.1, 1 };
- float borderColor[] = { 1, 1, 1, 1 };
-
- gEngfuncs.pTriAPI->RenderMode(kRenderNormal);
- gEngfuncs.pTriAPI->CullFace(TRI_NONE);
-
- gEngfuncs.pTriAPI->SpriteTexture((struct model_s*)(gEngfuncs.GetSpritePointer(m_hsprWhite)), 0);
-
- float gammaScale = 1.0f / gHUD.GetGammaSlope();
-
- // Draw the border on the overview map and the inset view.
-
- gEngfuncs.pTriAPI->RenderMode(kRenderNormal);
- gEngfuncs.pTriAPI->CullFace(TRI_NONE);
-
- gEngfuncs.pTriAPI->SpriteTexture((struct model_s*)(gEngfuncs.GetSpritePointer(m_hsprWhite)), 0);
- gEngfuncs.pTriAPI->Color4f(gammaScale * borderColor[0], gammaScale * borderColor[1], gammaScale * borderColor[2], borderColor[3]);
-
- gEngfuncs.pTriAPI->Begin(TRI_LINES);
-
- int insetX1 = XRES(m_OverviewData.insetWindowX);
- int insetY1 = YRES(m_OverviewData.insetWindowY);
- int insetX2 = insetX1 + XRES(m_OverviewData.insetWindowWidth);
- int insetY2 = insetY1 + YRES(m_OverviewData.insetWindowHeight);
-
- gEngfuncs.pTriAPI->Vertex3f(insetX1, insetY1, 1);
- gEngfuncs.pTriAPI->Vertex3f(insetX2, insetY1, 1);
-
- gEngfuncs.pTriAPI->Vertex3f(insetX2, insetY1, 1);
- gEngfuncs.pTriAPI->Vertex3f(insetX2, insetY2, 1);
-
- gEngfuncs.pTriAPI->Vertex3f(insetX2, insetY2, 1);
- gEngfuncs.pTriAPI->Vertex3f(insetX1, insetY2, 1);
-
- gEngfuncs.pTriAPI->Vertex3f(insetX1, insetY2, 1);
- gEngfuncs.pTriAPI->Vertex3f(insetX1, insetY1, 1);
-
- gEngfuncs.pTriAPI->End();
-
- }*/
-
-
-
- /*
- // Only draw the icon names only if map mode is in Main Mode
- if ( g_iUser1 < OBS_MAP_FREE )
- return 1;
-
- if ( !m_drawnames->value )
- return 1;
-
- // make sure we have player info
- gViewPort->GetAllPlayersInfo();
- */
-
- return 1;
-
-}
-
-bool CHudSpectator::IsInOverviewMode() const
-{
- return g_iUser1 && m_overviewMode && gHUD.GetIsNSMode();
-}
-
-void CHudSpectator::SetOverviewMode(bool overviewMode)
-{
- m_overviewMode = overviewMode;
-}
-
-void CHudSpectator::DrawOverviewMap()
-{
-
- // draw only in spectator mode
- if (!IsInOverviewMode())
- {
- return;
- }
-
- AvHOverviewMap& theOverviewMap = gHUD.GetOverviewMap();
-
- AvHOverviewMap::DrawInfo theDrawInfo;
-
- theDrawInfo.mX = XRES(m_OverviewData.insetWindowX + m_OverviewData.insetWindowWidth + 4);
- theDrawInfo.mY = YRES(SPECTATOR_PANEL_HEIGHT + 4);
- theDrawInfo.mWidth = ScreenWidth() - theDrawInfo.mX - XRES(4);
- theDrawInfo.mHeight = ScreenHeight() - YRES(SPECTATOR_PANEL_HEIGHT + 4) - theDrawInfo.mY;
- theDrawInfo.mZoomScale = 1.0f;
- AvHMapExtents theMapExtents;
- theOverviewMap.GetMapExtents(theMapExtents);
-
- theDrawInfo.mFullScreen = true;
-
- float worldWidth = theMapExtents.GetMaxMapX() - theMapExtents.GetMinMapX();
- float worldHeight = theMapExtents.GetMaxMapY() - theMapExtents.GetMinMapY();
-
- float xScale;
- float yScale;
-
- float aspect1 = worldWidth / worldHeight;
- float aspect2 = ((float)theDrawInfo.mWidth) / theDrawInfo.mHeight;
-
- if (aspect1 > aspect2)
- {
- xScale = 1;
- yScale = 1 / aspect2;
- }
- else
- {
- xScale = aspect2;
- yScale = 1;
- }
-
- float centerX = (theMapExtents.GetMinMapX() + theMapExtents.GetMaxMapX()) / 2;
- float centerY = (theMapExtents.GetMinMapY() + theMapExtents.GetMaxMapY()) / 2;
-
- theDrawInfo.mViewWorldMinX = centerX - worldWidth * xScale * 0.5;
- theDrawInfo.mViewWorldMinY = centerY - worldHeight * yScale * 0.5;
- theDrawInfo.mViewWorldMaxX = centerX + worldWidth * xScale * 0.5;
- theDrawInfo.mViewWorldMaxY = centerY + worldHeight * yScale * 0.5;
-
- if (m_hsprWhite != NULL)
- {
-
- float bgColor[] = { 0.1, 0.1, 0.1, 1 };
- float borderColor[] = { 1, 1, 1, 1 };
-
- gEngfuncs.pTriAPI->RenderMode(kRenderNormal);
- gEngfuncs.pTriAPI->CullFace(TRI_NONE);
-
- gEngfuncs.pTriAPI->SpriteTexture((struct model_s*)(gEngfuncs.GetSpritePointer(m_hsprWhite)), 0);
- #ifdef _WIN32
- float gammaScale = 1.0f / gHUD.GetGammaSlope();
- #else
- float gammaScale = 1.0f;
- #endif
-
- // Draw the background.
-
- gEngfuncs.pTriAPI->Color4f(gammaScale * bgColor[0], gammaScale * bgColor[1], gammaScale * bgColor[2], bgColor[3]);
-
- gEngfuncs.pTriAPI->Begin(TRI_QUADS);
-
- gEngfuncs.pTriAPI->Vertex3f(theDrawInfo.mX, theDrawInfo.mY, 1);
- gEngfuncs.pTriAPI->Vertex3f(theDrawInfo.mX, theDrawInfo.mY + theDrawInfo.mHeight, 1);
- gEngfuncs.pTriAPI->Vertex3f(theDrawInfo.mX + theDrawInfo.mWidth, theDrawInfo.mY + theDrawInfo.mHeight, 1);
- gEngfuncs.pTriAPI->Vertex3f(theDrawInfo.mX + theDrawInfo.mWidth, theDrawInfo.mY, 1);
-
- gEngfuncs.pTriAPI->End();
-
- // Draw the overview map.
-
- theOverviewMap.Draw(theDrawInfo);
-
- // Draw the border on the overview map and the inset view.
-
- gEngfuncs.pTriAPI->RenderMode(kRenderNormal);
- gEngfuncs.pTriAPI->CullFace(TRI_NONE);
-
- gEngfuncs.pTriAPI->SpriteTexture((struct model_s*)(gEngfuncs.GetSpritePointer(m_hsprWhite)), 0);
- gEngfuncs.pTriAPI->Color4f(gammaScale * borderColor[0], gammaScale * borderColor[1], gammaScale * borderColor[2], borderColor[3]);
-
- gEngfuncs.pTriAPI->Begin(TRI_LINES);
-
- gEngfuncs.pTriAPI->Vertex3f(theDrawInfo.mX, theDrawInfo.mY, 1);
- gEngfuncs.pTriAPI->Vertex3f(theDrawInfo.mX, theDrawInfo.mY + theDrawInfo.mHeight, 1);
-
- gEngfuncs.pTriAPI->Vertex3f(theDrawInfo.mX, theDrawInfo.mY + theDrawInfo.mHeight, 1);
- gEngfuncs.pTriAPI->Vertex3f(theDrawInfo.mX + theDrawInfo.mWidth, theDrawInfo.mY + theDrawInfo.mHeight, 1);
-
- gEngfuncs.pTriAPI->Vertex3f(theDrawInfo.mX + theDrawInfo.mWidth, theDrawInfo.mY + theDrawInfo.mHeight, 1);
- gEngfuncs.pTriAPI->Vertex3f(theDrawInfo.mX + theDrawInfo.mWidth, theDrawInfo.mY, 1);
-
- gEngfuncs.pTriAPI->Vertex3f(theDrawInfo.mX + theDrawInfo.mWidth, theDrawInfo.mY, 1);
- gEngfuncs.pTriAPI->Vertex3f(theDrawInfo.mX, theDrawInfo.mY, 1);
-
- int insetX1 = XRES(m_OverviewData.insetWindowX);
- int insetY1 = YRES(m_OverviewData.insetWindowY);
- int insetX2 = insetX1 + XRES(m_OverviewData.insetWindowWidth);
- int insetY2 = insetY1 + YRES(m_OverviewData.insetWindowHeight);
-
- gEngfuncs.pTriAPI->Vertex3f(insetX1, insetY1, 1);
- gEngfuncs.pTriAPI->Vertex3f(insetX2, insetY1, 1);
-
- gEngfuncs.pTriAPI->Vertex3f(insetX2, insetY1, 1);
- gEngfuncs.pTriAPI->Vertex3f(insetX2, insetY2, 1);
-
- gEngfuncs.pTriAPI->Vertex3f(insetX2, insetY2, 1);
- gEngfuncs.pTriAPI->Vertex3f(insetX1, insetY2, 1);
-
- gEngfuncs.pTriAPI->Vertex3f(insetX1, insetY2, 1);
- gEngfuncs.pTriAPI->Vertex3f(insetX1, insetY1, 1);
-
- gEngfuncs.pTriAPI->End();
-
- }
-
-
-}
-
-#include "parsemsg.h"
-void CHudSpectator::DirectorMessage( int iSize, void *pbuf )
-{
- float value;
- char * string;
-
- BEGIN_READ( pbuf, iSize );
-
- int cmd = READ_BYTE();
-
- switch ( cmd ) // director command byte
- {
- case DRC_CMD_START :
- // now we have to do some things clientside, since the proxy doesn't know our mod
- g_iPlayerClass = 0;
- g_iTeamNumber = 0;
-
- // fake a InitHUD & ResetHUD message
- gHUD.MsgFunc_InitHUD(NULL,0, NULL);
- gHUD.MsgFunc_ResetHUD(NULL, 0, NULL);
-
- break;
-
- case DRC_CMD_EVENT :
- m_lastPrimaryObject = READ_WORD();
- m_lastSecondaryObject = READ_WORD();
- m_iObserverFlags = READ_LONG();
-
- if ( m_autoDirector->value )
- {
- if ( (g_iUser2 != m_lastPrimaryObject) || (g_iUser3 != m_lastSecondaryObject) )
- V_ResetChaseCam();
-
- g_iUser2 = m_lastPrimaryObject;
- g_iUser3 = m_lastSecondaryObject;
- }
-
- break;
-
- case DRC_CMD_MODE :
- if ( m_autoDirector->value )
- {
- SetMode( READ_BYTE());
- }
- break;
-
- case DRC_CMD_CAMERA :
- if ( m_autoDirector->value )
- {
- vJumpOrigin[0] = READ_COORD(); // position
- vJumpOrigin[1] = READ_COORD();
- vJumpOrigin[2] = READ_COORD();
-
- vJumpAngles[0] = READ_COORD(); // view angle
- vJumpAngles[1] = READ_COORD();
- vJumpAngles[2] = READ_COORD();
-
- gEngfuncs.SetViewAngles( vJumpAngles );
-
- iJumpSpectator = 1;
- }
- break;
-
- case DRC_CMD_MESSAGE:
- {
- client_textmessage_t * msg = &m_HUDMessages[m_lastHudMessage];
-
- msg->effect = READ_BYTE(); // effect
-
- UnpackRGB( (int&)msg->r1, (int&)msg->g1, (int&)msg->b1, READ_LONG() ); // color
- msg->r2 = msg->r1;
- msg->g2 = msg->g1;
- msg->b2 = msg->b1;
- msg->a2 = msg->a1 = 0xFF; // not transparent
-
- msg->x = READ_FLOAT(); // x pos
- msg->y = READ_FLOAT(); // y pos
-
- msg->fadein = READ_FLOAT(); // fadein
- msg->fadeout = READ_FLOAT(); // fadeout
- msg->holdtime = READ_FLOAT(); // holdtime
- msg->fxtime = READ_FLOAT(); // fxtime;
-
- strncpy( m_HUDMessageText[m_lastHudMessage], READ_STRING(), 128 );
- m_HUDMessageText[m_lastHudMessage][127]=0; // text
-
- msg->pMessage = m_HUDMessageText[m_lastHudMessage];
- msg->pName = "HUD_MESSAGE";
-
- gHUD.m_Message.MessageAdd( msg->pName, gHUD.m_flTime);
-
- m_lastHudMessage++;
- m_lastHudMessage %= MAX_SPEC_HUD_MESSAGES;
-
- }
-
- break;
-
- case DRC_CMD_SOUND :
- string = READ_STRING();
- value = READ_FLOAT();
-
- gEngfuncs.pEventAPI->EV_PlaySound(0, v_origin, CHAN_BODY, string, value, ATTN_NORM, 0, PITCH_NORM );
-
- break;
-
- case DRC_CMD_TIMESCALE :
- value = READ_FLOAT();
- break;
-
-
-
- case DRC_CMD_STATUS:
- READ_LONG(); // total number of spectator slots
- m_iSpectatorNumber = READ_LONG(); // total number of spectator
- READ_WORD(); // total number of relay proxies
-
- gViewPort->UpdateSpectatorPanel();
- break;
-
- case DRC_CMD_BANNER:
- // gEngfuncs.Con_DPrintf("GUI: Banner %s\n",READ_STRING() ); // name of banner tga eg gfx/temp/7454562234563475.tga
- gViewPort->m_pSpectatorPanel->m_TopBanner->LoadImage( READ_STRING() );
- gViewPort->UpdateSpectatorPanel();
- break;
-
- case DRC_CMD_FADE:
- break;
-
- case DRC_CMD_STUFFTEXT:
- ClientCmd( READ_STRING() );
- break;
-
- default : gEngfuncs.Con_DPrintf("CHudSpectator::DirectorMessage: unknown command %i.\n", cmd );
- }
-}
-
-void CHudSpectator::FindNextPlayer(bool bReverse)
-{
- // MOD AUTHORS: Modify the logic of this function if you want to restrict the observer to watching
- // only a subset of the players. e.g. Make it check the target's team.
-
- int iStart;
- cl_entity_t * pEnt = NULL;
-
- // if we are NOT in HLTV mode, spectator targets are set on server
- if ( !gEngfuncs.IsSpectateOnly() )
- {
- char cmdstring[32];
- // forward command to server
- sprintf(cmdstring,"follownext %i",bReverse?1:0);
- gEngfuncs.pfnServerCmd(cmdstring);
- return;
- }
-
- if ( g_iUser2 )
- iStart = g_iUser2;
- else
- iStart = 1;
-
- g_iUser2 = 0;
-
- int iCurrent = iStart;
-
- int iDir = bReverse ? -1 : 1;
-
- // make sure we have player info
- gViewPort->GetAllPlayersInfo();
-
-
- do
- {
- iCurrent += iDir;
-
- // Loop through the clients
- if (iCurrent > MAX_PLAYERS)
- iCurrent = 1;
- if (iCurrent < 1)
- iCurrent = MAX_PLAYERS;
-
- pEnt = gEngfuncs.GetEntityByIndex( iCurrent );
-
- if ( !IsActivePlayer( pEnt ) )
- continue;
-
- // MOD AUTHORS: Add checks on target here.
-
- g_iUser2 = iCurrent;
- break;
-
- } while ( iCurrent != iStart );
-
- // Did we find a target?
- if ( !g_iUser2 )
- {
- gEngfuncs.Con_DPrintf( "No observer targets.\n" );
- // take save camera position
- VectorCopy(m_cameraOrigin, vJumpOrigin);
- VectorCopy(m_cameraAngles, vJumpAngles);
- }
- else
- {
- // use new entity position for roaming
- VectorCopy ( pEnt->origin, vJumpOrigin );
- VectorCopy ( pEnt->angles, vJumpAngles );
- }
- iJumpSpectator = 1;
-}
-
-void CHudSpectator::HandleButtonsDown( int ButtonPressed )
-{
- if ( !gViewPort )
- return;
-
- //Not in intermission.
- if ( gHUD.m_iIntermission )
- return;
-
- if ( !g_iUser1 )
- return; // dont do anything if not in spectator mode
-
- // don't handle buttons during normal demo playback
- if ( gEngfuncs.pDemoAPI->IsPlayingback() && !gEngfuncs.IsSpectateOnly() )
- return;
-
- int theNewMainMode = g_iUser1;
-
- // Jump changes main window modes
- if ( ButtonPressed & IN_JUMP )
- {
- bool theFirstPerson = (g_iUser1 == OBS_IN_EYE);
- bool theInOverviewMode = gHUD.m_Spectator.IsInOverviewMode();
-
- // NS
- if(gHUD.GetIsNSMode())
- {
- // First-person full -> chase camera full -> firstperson with overview -> chase camera with overview
- if(theFirstPerson && !theInOverviewMode)
- {
- gHUD.m_Spectator.SetMode(OBS_CHASE_LOCKED);
- //gHUD.m_Spectator.SetOverviewMode(false);
- }
- else if(!theFirstPerson && !theInOverviewMode)
- {
- gHUD.m_Spectator.SetMode(OBS_IN_EYE);
- gHUD.m_Spectator.SetOverviewMode(true);
- }
- else if(theFirstPerson && theInOverviewMode)
- {
- gHUD.m_Spectator.SetMode(OBS_CHASE_LOCKED);
- //gHUD.m_Spectator.SetOverviewMode(true);
- }
- else if(!theFirstPerson && theInOverviewMode)
- {
- gHUD.m_Spectator.SetMode(OBS_IN_EYE);
- gHUD.m_Spectator.SetOverviewMode(false);
- }
- }
- // Combat
- else
- {
- // First-person full -> chase camera full
- if(theFirstPerson)
- {
- gHUD.m_Spectator.SetMode(OBS_CHASE_LOCKED);
- gHUD.m_Spectator.SetOverviewMode(false);
- }
- else
- {
- gHUD.m_Spectator.SetMode(OBS_IN_EYE);
- gHUD.m_Spectator.SetOverviewMode(false);
- }
- }
- }
-
- //g_iUser1 = theNewMainMode;
-
- // Attack moves to the next player
- if ( ButtonPressed & (IN_MOVELEFT | IN_MOVERIGHT) )
- {
- FindNextPlayer( (ButtonPressed & IN_MOVELEFT) ? true:false );
-
-// if ( g_iUser1 == OBS_ROAMING )
-// {
-// gEngfuncs.SetViewAngles( vJumpAngles );
-// iJumpSpectator = 1;
-//
-// }
-
- // lease directed mode if player want to see another player
- m_autoDirector->value = 0.0f;
- }
-
-/*
- double time = gEngfuncs.GetClientTime();
-
- int newMainMode = g_iUser1;
- int newInsetMode = m_pip->value;
-
- // gEngfuncs.Con_Printf(" HandleButtons:%i\n", ButtonPressed );
- if ( !gViewPort )
- return;
-
- //Not in intermission.
- if ( gHUD.m_iIntermission )
- return;
-
- if ( !g_iUser1 )
- return; // dont do anything if not in spectator mode
-
- // don't handle buttons during normal demo playback
- if ( gEngfuncs.pDemoAPI->IsPlayingback() && !gEngfuncs.IsSpectateOnly() )
- return;
- // Slow down mouse clicks.
- if ( m_flNextObserverInput > time )
- return;
-
- // enable spectator screen
- if ( ButtonPressed & IN_DUCK )
- {
- gViewPort->m_pSpectatorPanel->ShowMenu(!gViewPort->m_pSpectatorPanel->m_menuVisible);
- }
-
- // 'Use' changes inset window mode
- if ( ButtonPressed & IN_USE )
- {
- newInsetMode = ToggleInset(true);
- }
-
- // if not in HLTV mode, buttons are handled server side
- if ( gEngfuncs.IsSpectateOnly() )
- {
- // changing target or chase mode not in overviewmode without inset window
-
- // Jump changes main window modes
- if ( ButtonPressed & IN_JUMP )
- {
- if ( g_iUser1 == OBS_CHASE_LOCKED )
- newMainMode = OBS_CHASE_FREE;
-
- else if ( g_iUser1 == OBS_CHASE_FREE )
- newMainMode = OBS_IN_EYE;
-
- else if ( g_iUser1 == OBS_IN_EYE )
- newMainMode = OBS_ROAMING;
-
- else if ( g_iUser1 == OBS_ROAMING )
- newMainMode = OBS_MAP_FREE;
-
- else if ( g_iUser1 == OBS_MAP_FREE )
- newMainMode = OBS_MAP_CHASE;
-
- else
- newMainMode = OBS_CHASE_FREE; // don't use OBS_CHASE_LOCKED anymore
- }
-
- // Attack moves to the next player
- if ( ButtonPressed & (IN_ATTACK | IN_ATTACK2) )
- {
- FindNextPlayer( (ButtonPressed & IN_ATTACK2) ? true:false );
-
- if ( g_iUser1 == OBS_ROAMING )
- {
- gEngfuncs.SetViewAngles( vJumpAngles );
- iJumpSpectator = 1;
-
- }
- // lease directed mode if player want to see another player
- m_autoDirector->value = 0.0f;
- }
- }
-
- SetModes(newMainMode, newInsetMode);
-
- if ( g_iUser1 == OBS_MAP_FREE )
- {
- if ( ButtonPressed & IN_FORWARD )
- m_zoomDelta = 0.01f;
-
- if ( ButtonPressed & IN_BACK )
- m_zoomDelta = -0.01f;
-
- if ( ButtonPressed & IN_MOVELEFT )
- m_moveDelta = -12.0f;
-
- if ( ButtonPressed & IN_MOVERIGHT )
- m_moveDelta = 12.0f;
- }
-
- m_flNextObserverInput = time + 0.2;
-*/
-
-}
-
-void CHudSpectator::HandleButtonsUp( int ButtonPressed )
-{
- if ( !gViewPort )
- return;
-
- if ( !gViewPort->m_pSpectatorPanel->isVisible() )
- return; // dont do anything if not in spectator mode
-
- if ( ButtonPressed & (IN_FORWARD | IN_BACK) )
- m_zoomDelta = 0.0f;
-
- if ( ButtonPressed & (IN_MOVELEFT | IN_MOVERIGHT) )
- m_moveDelta = 0.0f;
-}
-
-void CHudSpectator::SetMode(int iNewMainMode)
-{
- // if value == -1 keep old value
- if ( iNewMainMode == -1 )
- iNewMainMode = g_iUser1;
-
- // main modes ettings will override inset window settings
- if ( iNewMainMode != g_iUser1 )
- {
- // if we are NOT in HLTV mode, main spectator mode is set on server
- if ( !gEngfuncs.IsSpectateOnly() )
- {
- char cmdstring[32];
- // forward command to server
- sprintf(cmdstring,"specmode %i",iNewMainMode );
- gEngfuncs.pfnServerCmd(cmdstring);
- return;
- }
- else
- {
- if ( !g_iUser2 && (iNewMainMode !=OBS_ROAMING ) ) // make sure we have a target
- {
- // choose last Director object if still available
- if ( IsActivePlayer( gEngfuncs.GetEntityByIndex( m_lastPrimaryObject ) ) )
- {
- g_iUser2 = m_lastPrimaryObject;
- g_iUser3 = m_lastSecondaryObject;
- }
- else
- {
- FindNextPlayer(false); // find any target
- }
- }
-
- switch ( iNewMainMode )
- {
- case OBS_CHASE_LOCKED:
- g_iUser1 = OBS_CHASE_LOCKED;
- break;
-
- case OBS_CHASE_FREE:
- g_iUser1 = OBS_CHASE_FREE;
- break;
-
- case OBS_ROAMING : // jump to current vJumpOrigin/angle
- g_iUser1 = OBS_ROAMING;
- if ( g_iUser2 )
- {
- V_GetChasePos( g_iUser2, v_cl_angles, vJumpOrigin, vJumpAngles );
- gEngfuncs.SetViewAngles( vJumpAngles );
- iJumpSpectator = 1;
- }
- break;
-
- case OBS_IN_EYE:
- g_iUser1 = OBS_IN_EYE;
- break;
-
- /*
- case OBS_MAP_FREE : g_iUser1 = OBS_MAP_FREE;
- // reset user values
- m_mapZoom = m_OverviewData.zoom;
- m_mapOrigin = m_OverviewData.origin;
- break;
-
- case OBS_MAP_CHASE : g_iUser1 = OBS_MAP_CHASE;
- // reset user values
- m_mapZoom = m_OverviewData.zoom;
- m_mapOrigin = m_OverviewData.origin;
- break;
- */
- }
-
- if ( (g_iUser1 == OBS_IN_EYE) || (g_iUser1 == OBS_ROAMING) )
- {
- m_crosshairRect.left = 24;
- m_crosshairRect.top = 0;
- m_crosshairRect.right = 48;
- m_crosshairRect.bottom = 24;
-
- gHUD.SetCurrentCrosshair( m_hCrosshair, m_crosshairRect, 255, 255, 255 );
- }
- else
- {
- memset( &m_crosshairRect,0,sizeof(m_crosshairRect) );
- gHUD.SetCurrentCrosshair( 0, m_crosshairRect, 0, 0, 0 );
- }
-
- //char string[128];
- //sprintf(string, "#Spec_Mode%d", g_iUser1 );
- //sprintf(string, "%c%s", HUD_PRINTCENTER, CHudTextMessage::BufferedLocaliseTextString( string ));
- //gHUD.m_TextMessage.MsgFunc_TextMsg(NULL, strlen(string)+1, string );
- }
- }
-
- gViewPort->UpdateSpectatorPanel();
-}
-
-bool CHudSpectator::IsActivePlayer(cl_entity_t * ent)
-{
- return ( ent &&
- ent->player &&
- ent->curstate.solid != SOLID_NOT &&
- ent != gEngfuncs.GetLocalPlayer() &&
- g_PlayerInfoList[ent->index].name != NULL
- );
-}
-
-
-bool CHudSpectator::ParseOverviewFile( )
-{
- //char filename[255];
- //char levelname[255];
- //char token[1024];
- //float height;
-
- char *pfile = NULL;
-
- memset( &m_OverviewData, 0, sizeof(m_OverviewData));
-
- // fill in standrd values
- m_OverviewData.insetWindowX = 4; // upper left corner
- m_OverviewData.insetWindowY = 4 + SPECTATOR_PANEL_HEIGHT;
- m_OverviewData.insetWindowHeight = 180;
- m_OverviewData.insetWindowWidth = 240;
- m_OverviewData.origin[0] = 0.0f;
- m_OverviewData.origin[1] = 0.0f;
- m_OverviewData.origin[2] = 0.0f;
- m_OverviewData.zoom = 1.0f;
- m_OverviewData.layers = 0;
- m_OverviewData.layersHeights[0] = 0.0f;
- strcpy( m_OverviewData.map, gEngfuncs.pfnGetLevelName() );
-
- if ( strlen( m_OverviewData.map ) == 0 )
- return false; // not active yet
-
- /*
- strcpy(levelname, m_OverviewData.map + 5);
- levelname[strlen(levelname)-4] = 0;
-
- sprintf(filename, "overviews/%s.txt", levelname );
-
- pfile = (char *)gEngfuncs.COM_LoadFile( filename, 5, NULL);
-
- if (!pfile)
- {
- gEngfuncs.Con_Printf("Couldn't open file %s. Using default values for overiew mode.\n", filename );
- return false;
- }
-
- while (true)
- {
- pfile = gEngfuncs.COM_ParseFile(pfile, token);
-
- if (!pfile)
- break;
-
- if ( !stricmp( token, "global" ) )
- {
- // parse the global data
- pfile = gEngfuncs.COM_ParseFile(pfile, token);
- if ( stricmp( token, "{" ) )
- {
- gEngfuncs.Con_Printf("Error parsing overview file %s. (expected { )\n", filename );
- return false;
- }
-
- pfile = gEngfuncs.COM_ParseFile(pfile,token);
-
- while (stricmp( token, "}") )
- {
- if ( !stricmp( token, "zoom" ) )
- {
- pfile = gEngfuncs.COM_ParseFile(pfile,token);
- m_OverviewData.zoom = atof( token );
- }
- else if ( !stricmp( token, "origin" ) )
- {
- pfile = gEngfuncs.COM_ParseFile(pfile, token);
- m_OverviewData.origin[0] = atof( token );
- pfile = gEngfuncs.COM_ParseFile(pfile,token);
- m_OverviewData.origin[1] = atof( token );
- pfile = gEngfuncs.COM_ParseFile(pfile, token);
- m_OverviewData.origin[2] = atof( token );
- }
- else if ( !stricmp( token, "rotated" ) )
- {
- pfile = gEngfuncs.COM_ParseFile(pfile,token);
- m_OverviewData.rotated = atoi( token );
- }
- else if ( !stricmp( token, "inset" ) )
- {
-
- // Removed by mmcguire.
- // This isn't supported anymore.
- pfile = gEngfuncs.COM_ParseFile(pfile,token);
- //m_OverviewData.insetWindowX = atof( token );
- pfile = gEngfuncs.COM_ParseFile(pfile,token);
- //m_OverviewData.insetWindowY = atof( token );
- pfile = gEngfuncs.COM_ParseFile(pfile,token);
- //m_OverviewData.insetWindowWidth = atof( token );
- pfile = gEngfuncs.COM_ParseFile(pfile,token);
- //m_OverviewData.insetWindowHeight = atof( token );
-
- }
- else
- {
- gEngfuncs.Con_Printf("Error parsing overview file %s. (%s unkown)\n", filename, token );
- return false;
- }
-
- pfile = gEngfuncs.COM_ParseFile(pfile,token); // parse next token
-
- }
- }
- else if ( !stricmp( token, "layer" ) )
- {
- // parse a layer data
-
- if ( m_OverviewData.layers == OVERVIEW_MAX_LAYERS )
- {
- gEngfuncs.Con_Printf("Error parsing overview file %s. ( too many layers )\n", filename );
- return false;
- }
-
- pfile = gEngfuncs.COM_ParseFile(pfile,token);
-
-
- if ( stricmp( token, "{" ) )
- {
- gEngfuncs.Con_Printf("Error parsing overview file %s. (expected { )\n", filename );
- return false;
- }
-
- pfile = gEngfuncs.COM_ParseFile(pfile,token);
-
- while (stricmp( token, "}") )
- {
- if ( !stricmp( token, "image" ) )
- {
- pfile = gEngfuncs.COM_ParseFile(pfile,token);
- strcpy(m_OverviewData.layersImages[ m_OverviewData.layers ], token);
-
-
- }
- else if ( !stricmp( token, "height" ) )
- {
- pfile = gEngfuncs.COM_ParseFile(pfile,token);
- height = atof(token);
- m_OverviewData.layersHeights[ m_OverviewData.layers ] = height;
- }
- else
- {
- gEngfuncs.Con_Printf("Error parsing overview file %s. (%s unkown)\n", filename, token );
- return false;
- }
-
- pfile = gEngfuncs.COM_ParseFile(pfile,token); // parse next token
- }
-
- m_OverviewData.layers++;
-
- }
- }
-
- gEngfuncs.COM_FreeFile( pfile );
- */
-
- m_mapZoom = m_OverviewData.zoom;
- m_mapOrigin = m_OverviewData.origin;
-
- return true;
-
-}
-
-void CHudSpectator::LoadMapSprites()
-{
- // right now only support for one map layer
- if (m_OverviewData.layers > 0 )
- {
- m_MapSprite = gEngfuncs.LoadMapSprite( m_OverviewData.layersImages[0] );
- }
- else
- m_MapSprite = NULL; // the standard "unkown map" sprite will be used instead
-}
-
-void CHudSpectator::DrawOverviewLayer()
-{
- float screenaspect, xs, ys, xStep, yStep, x,y,z;
- int ix,iy,i,xTiles,yTiles,frame;
-
- qboolean hasMapImage = m_MapSprite?TRUE:FALSE;
- model_t * dummySprite = (struct model_s *)gEngfuncs.GetSpritePointer( m_hsprUnkownMap);
-
- if ( hasMapImage)
- {
- i = m_MapSprite->numframes / (4*3);
- i = sqrt((float)i);
- xTiles = i*4;
- yTiles = i*3;
- }
- else
- {
- xTiles = 8;
- yTiles = 6;
- }
-
-
- screenaspect = 4.0f/3.0f;
-
-
- xs = m_OverviewData.origin[0];
- ys = m_OverviewData.origin[1];
- z = ( 90.0f - v_angles[0] ) / 90.0f;
- z *= m_OverviewData.layersHeights[0]; // gOverviewData.z_min - 32;
-
- // i = r_overviewTexture + ( layer*OVERVIEW_X_TILES*OVERVIEW_Y_TILES );
-
- gEngfuncs.pTriAPI->RenderMode( kRenderTransTexture );
- gEngfuncs.pTriAPI->CullFace( TRI_NONE );
- gEngfuncs.pTriAPI->Color4f( 1.0, 1.0, 1.0, 1.0 );
-
- frame = 0;
-
-
- // rotated view ?
- if ( m_OverviewData.rotated )
- {
- xStep = (2*4096.0f / m_OverviewData.zoom ) / xTiles;
- yStep = -(2*4096.0f / (m_OverviewData.zoom* screenaspect) ) / yTiles;
-
- y = ys + (4096.0f / (m_OverviewData.zoom * screenaspect));
-
- for (iy = 0; iy < yTiles; iy++)
- {
- x = xs - (4096.0f / (m_OverviewData.zoom));
-
- for (ix = 0; ix < xTiles; ix++)
- {
- if (hasMapImage)
- gEngfuncs.pTriAPI->SpriteTexture( m_MapSprite, frame );
- else
- gEngfuncs.pTriAPI->SpriteTexture( dummySprite, 0 );
-
- gEngfuncs.pTriAPI->Begin( TRI_QUADS );
- gEngfuncs.pTriAPI->TexCoord2f( 0, 0 );
- gEngfuncs.pTriAPI->Vertex3f (x, y, z);
-
- gEngfuncs.pTriAPI->TexCoord2f( 1, 0 );
- gEngfuncs.pTriAPI->Vertex3f (x+xStep ,y, z);
-
- gEngfuncs.pTriAPI->TexCoord2f( 1, 1 );
- gEngfuncs.pTriAPI->Vertex3f (x+xStep, y+yStep, z);
-
- gEngfuncs.pTriAPI->TexCoord2f( 0, 1 );
- gEngfuncs.pTriAPI->Vertex3f (x, y+yStep, z);
- gEngfuncs.pTriAPI->End();
-
- frame++;
- x+= xStep;
- }
-
- y+=yStep;
- }
- }
- else
- {
- xStep = -(2*4096.0f / m_OverviewData.zoom ) / xTiles;
- yStep = -(2*4096.0f / (m_OverviewData.zoom* screenaspect) ) / yTiles;
-
-
- x = xs + (4096.0f / (m_OverviewData.zoom * screenaspect ));
-
-
-
- for (ix = 0; ix < yTiles; ix++)
- {
-
- y = ys + (4096.0f / (m_OverviewData.zoom));
-
- for (iy = 0; iy < xTiles; iy++)
- {
- if (hasMapImage)
- gEngfuncs.pTriAPI->SpriteTexture( m_MapSprite, frame );
- else
- gEngfuncs.pTriAPI->SpriteTexture( dummySprite, 0 );
-
- gEngfuncs.pTriAPI->Begin( TRI_QUADS );
- gEngfuncs.pTriAPI->TexCoord2f( 0, 0 );
- gEngfuncs.pTriAPI->Vertex3f (x, y, z);
-
- gEngfuncs.pTriAPI->TexCoord2f( 0, 1 );
- gEngfuncs.pTriAPI->Vertex3f (x+xStep ,y, z);
-
- gEngfuncs.pTriAPI->TexCoord2f( 1, 1 );
- gEngfuncs.pTriAPI->Vertex3f (x+xStep, y+yStep, z);
-
- gEngfuncs.pTriAPI->TexCoord2f( 1, 0 );
- gEngfuncs.pTriAPI->Vertex3f (x, y+yStep, z);
- gEngfuncs.pTriAPI->End();
-
- frame++;
-
- y+=yStep;
- }
-
- x+= xStep;
-
- }
- }
-}
-
-void CHudSpectator::DrawOverviewEntities()
-{
- /*
- int i,ir,ig,ib;
- struct model_s *hSpriteModel;
- vec3_t origin, angles, point, forward, right, left, up, world, screen, offset;
- float x,y,z, r,g,b, sizeScale = 4.0f;
- cl_entity_t * ent;
- float rmatrix[3][4]; // transformation matrix
-
- float zScale = (90.0f - v_angles[0] ) / 90.0f;
-
-
- z = m_OverviewData.layersHeights[0] * zScale;
- // get yellow/brown HUD color
- //UnpackRGB(ir,ig,ib, RGB_YELLOWISH);
- gHUD.GetPrimaryHudColor(ir, ig, ib);
- r = (float)ir/255.0f;
- g = (float)ig/255.0f;
- b = (float)ib/255.0f;
-
- gEngfuncs.pTriAPI->CullFace( TRI_NONE );
-
- for (i=0; i < MAX_PLAYERS; i++ )
- m_vPlayerPos[i][2] = -1; // mark as invisible
-
- // draw all players
-
- float depthOffset = 0;
-
- for (i=MAX_OVERVIEW_ENTITIES - 1; i >= 0; i--)
- {
- if ( !m_OverviewEntities[i].hSprite )
- continue;
-
- hSpriteModel = (struct model_s *)gEngfuncs.GetSpritePointer( m_OverviewEntities[i].hSprite );
- ent = m_OverviewEntities[i].entity;
-
- int theSpriteFrame = m_OverviewEntities[i].mFrame;
- gEngfuncs.pTriAPI->SpriteTexture( hSpriteModel, theSpriteFrame);
-
- gEngfuncs.pTriAPI->RenderMode( kRenderTransAdd);
-
- // see R_DrawSpriteModel
- // draws players sprite
-
- AngleVectors(ent->angles, right, up, NULL );
-
- VectorCopy(ent->origin,origin);
-
- // Set origin of blip to just above map height, so blips are all drawn on map
- origin.z = m_OverviewData.layersHeights[0] + kOverviewEntityZHeight + depthOffset;
-
- gEngfuncs.pTriAPI->Begin( TRI_QUADS );
-
- float gammaSlope = gHUD.GetGammaSlope();
-
- gEngfuncs.pTriAPI->Color4f(
- m_OverviewEntities[i].mColorR / gammaSlope,
- m_OverviewEntities[i].mColorG / gammaSlope,
- m_OverviewEntities[i].mColorB / gammaSlope,
- 1);
-
- gEngfuncs.pTriAPI->TexCoord2f (1, 0);
- VectorMA (origin, 16.0f * sizeScale, up, point);
- VectorMA (point, 16.0f * sizeScale, right, point);
- point[2] *= zScale;
- gEngfuncs.pTriAPI->Vertex3fv (point);
-
- gEngfuncs.pTriAPI->TexCoord2f (0, 0);
-
- VectorMA (origin, 16.0f * sizeScale, up, point);
- VectorMA (point, -16.0f * sizeScale, right, point);
- point[2] *= zScale;
- gEngfuncs.pTriAPI->Vertex3fv (point);
-
- gEngfuncs.pTriAPI->TexCoord2f (0,1);
- VectorMA (origin, -16.0f * sizeScale, up, point);
- VectorMA (point, -16.0f * sizeScale, right, point);
- point[2] *= zScale;
- gEngfuncs.pTriAPI->Vertex3fv (point);
-
- gEngfuncs.pTriAPI->TexCoord2f (1,1);
- VectorMA (origin, -16.0f * sizeScale, up, point);
- VectorMA (point, 16.0f * sizeScale, right, point);
- point[2] *= zScale;
- gEngfuncs.pTriAPI->Vertex3fv (point);
-
- gEngfuncs.pTriAPI->End ();
-
-
- if ( !ent->player)
- continue;
- // draw line under player icons
- origin[2] *= zScale;
-
- gEngfuncs.pTriAPI->RenderMode( kRenderTransAdd );
-
- hSpriteModel = (struct model_s *)gEngfuncs.GetSpritePointer( m_hsprBeam );
- gEngfuncs.pTriAPI->SpriteTexture( hSpriteModel, 0 );
-
- gEngfuncs.pTriAPI->Color4f(r, g, b, 0.3);
-
- gEngfuncs.pTriAPI->Begin ( TRI_QUADS );
- gEngfuncs.pTriAPI->TexCoord2f (1, 0);
- gEngfuncs.pTriAPI->Vertex3f (origin[0]+4, origin[1]+4, origin[2]-zScale);
- gEngfuncs.pTriAPI->TexCoord2f (0, 0);
- gEngfuncs.pTriAPI->Vertex3f (origin[0]-4, origin[1]-4, origin[2]-zScale);
- gEngfuncs.pTriAPI->TexCoord2f (0, 1);
- gEngfuncs.pTriAPI->Vertex3f (origin[0]-4, origin[1]-4,z);
- gEngfuncs.pTriAPI->TexCoord2f (1, 1);
- gEngfuncs.pTriAPI->Vertex3f (origin[0]+4, origin[1]+4,z);
- gEngfuncs.pTriAPI->End ();
-
- gEngfuncs.pTriAPI->Begin ( TRI_QUADS );
- gEngfuncs.pTriAPI->TexCoord2f (1, 0);
- gEngfuncs.pTriAPI->Vertex3f (origin[0]-4, origin[1]+4, origin[2]-zScale);
- gEngfuncs.pTriAPI->TexCoord2f (0, 0);
- gEngfuncs.pTriAPI->Vertex3f (origin[0]+4, origin[1]-4, origin[2]-zScale);
- gEngfuncs.pTriAPI->TexCoord2f (0, 1);
- gEngfuncs.pTriAPI->Vertex3f (origin[0]+4, origin[1]-4,z);
- gEngfuncs.pTriAPI->TexCoord2f (1, 1);
- gEngfuncs.pTriAPI->Vertex3f (origin[0]-4, origin[1]+4,z);
- gEngfuncs.pTriAPI->End ();
-
- // calculate screen position for name and infromation in hud::draw()
- if ( gEngfuncs.pTriAPI->WorldToScreen(origin,screen) )
- continue; // object is behind viewer
-
- screen[0] = XPROJECT(screen[0]);
- screen[1] = YPROJECT(screen[1]);
- screen[2] = 0.0f;
-
- // calculate some offset under the icon
- origin[0]+=32.0f;
- origin[1]+=32.0f;
-
- gEngfuncs.pTriAPI->WorldToScreen(origin,offset);
-
- offset[0] = XPROJECT(offset[0]);
- offset[1] = YPROJECT(offset[1]);
- offset[2] = 0.0f;
-
- VectorSubtract(offset, screen, offset );
-
- int playerNum = ent->index - 1;
-
- m_vPlayerPos[playerNum][0] = screen[0];
- m_vPlayerPos[playerNum][1] = screen[1] + Length(offset);
- m_vPlayerPos[playerNum][2] = 1; // mark player as visible
-
-
- }
-
- if ( !m_pip || !m_drawcone->value )
- return;
-
- // get current camera position and angle
-
- if ( m_pip == INSET_IN_EYE || g_iUser1 == OBS_IN_EYE )
- {
- V_GetInEyePos( g_iUser2, origin, angles );
- }
- else if ( m_pip == INSET_CHASE_FREE || g_iUser1 == OBS_CHASE_FREE )
- {
- V_GetChasePos( g_iUser2, v_cl_angles, origin, angles );
- }
- else if ( g_iUser1 == OBS_ROAMING )
- {
- VectorCopy( v_sim_org, origin );
- VectorCopy( v_cl_angles, angles );
- }
- else
- V_GetChasePos( g_iUser2, NULL, origin, angles );
-
-
- // draw camera sprite
-
- x = origin[0];
- y = origin[1];
- z = origin[2];
-
- // Set origin of cone to just above map height, so blips are all drawn on map
- z = m_OverviewData.layersHeights[0] + kOverviewEntityZHeight;
-
- angles[0] = 0; // always show horizontal camera sprite
-
- hSpriteModel = (struct model_s *)gEngfuncs.GetSpritePointer( m_hsprCamera );
- gEngfuncs.pTriAPI->RenderMode( kRenderTransAdd );
- gEngfuncs.pTriAPI->SpriteTexture( hSpriteModel, 0 );
-
-
- gEngfuncs.pTriAPI->Color4f( r, g, b, 1.0 );
-
- AngleVectors(angles, forward, NULL, NULL );
- VectorScale (forward, 512.0f, forward);
-
- offset[0] = 0.0f;
- offset[1] = 45.0f;
- offset[2] = 0.0f;
-
- AngleMatrix(offset, rmatrix );
- VectorTransform(forward, rmatrix , right );
-
- offset[1]= -45.0f;
- AngleMatrix(offset, rmatrix );
- VectorTransform(forward, rmatrix , left );
-
- gEngfuncs.pTriAPI->Begin (TRI_TRIANGLES);
- gEngfuncs.pTriAPI->TexCoord2f( 0, 0 );
- gEngfuncs.pTriAPI->Vertex3f (x+right[0], y+right[1], (z+right[2]) * zScale);
-
- gEngfuncs.pTriAPI->TexCoord2f( 0, 1 );
- gEngfuncs.pTriAPI->Vertex3f (x, y, z * zScale);
-
- gEngfuncs.pTriAPI->TexCoord2f( 1, 1 );
- gEngfuncs.pTriAPI->Vertex3f (x+left[0], y+left[1], (z+left[2]) * zScale);
- gEngfuncs.pTriAPI->End ();
- */
-
-}
-
-
-
-void CHudSpectator::DrawOverview()
-{
- /*
- // draw only in sepctator mode
- if ( !g_iUser1 )
- return;
-
- // Only draw the overview if Map Mode is selected for this view
- if ( m_iDrawCycle == 0 && ( (g_iUser1 != OBS_MAP_FREE) && (g_iUser1 != OBS_MAP_CHASE) ) )
- return;
-
- if ( m_iDrawCycle == 1 && m_pip->value < INSET_MAP_FREE )
- return;
-
- DrawOverviewLayer();
- DrawOverviewEntities();
- CheckOverviewEntities();
- */
-
-}
-
-
-
-void CHudSpectator::CheckOverviewEntities()
-{
- double time = gEngfuncs.GetClientTime();
-
- // removes old entities from list
- for ( int i = 0; i< MAX_OVERVIEW_ENTITIES; i++ )
- {
- // remove entity from list if it is too old
- if ( m_OverviewEntities[i].killTime < time )
- {
- memset( &m_OverviewEntities[i], 0, sizeof (overviewEntity_t) );
- }
- }
-}
-
-bool CHudSpectator::AddOverviewEntity( int type, struct cl_entity_s *ent, const char *modelname)
-{
- HSPRITE hSprite = 0;
- double duration = -1.0f; // duration -1 means show it only this frame;
- int theFrame = 0;
- bool theSuccess = false;
- int theRenderMode;
-
- if ( ent )
- {
-
- if (ent->curstate.solid != SOLID_NOT)
- {
- gHUD.GetSpriteForUser3(AvHUser3(ent->curstate.iuser3), hSprite, theFrame, theRenderMode);
- }
-
- /*
- if ( type == ET_PLAYER )
- {
- if ( ent->curstate.solid != SOLID_NOT)
- {
- int thePlayerClass = g_PlayerExtraInfo[ent->index].playerclass;
- switch(thePlayerClass)
- {
- case PLAYERCLASS_ALIVE_MARINE:
- hSprite = this->m_hsprPlayerMarine;
- theFrame = 0;
- break;
- case PLAYERCLASS_ALIVE_HEAVY_MARINE:
- hSprite = this->m_hsprPlayerMarine;
- theFrame = 1;
- break;
- case PLAYERCLASS_COMMANDER:
- hSprite = this->m_hsprPlayerMarine;
- theFrame = 2;
- break;
- case PLAYERCLASS_ALIVE_LEVEL1:
- hSprite = this->m_hsprPlayerAlien;
- theFrame = 0;
- break;
- case PLAYERCLASS_ALIVE_LEVEL2:
- hSprite = this->m_hsprPlayerAlien;
- theFrame = 1;
- break;
- case PLAYERCLASS_ALIVE_LEVEL3:
- hSprite = this->m_hsprPlayerAlien;
- theFrame = 2;
- break;
- case PLAYERCLASS_ALIVE_LEVEL4:
- hSprite = this->m_hsprPlayerAlien;
- theFrame = 3;
- break;
- case PLAYERCLASS_ALIVE_LEVEL5:
- hSprite = this->m_hsprPlayerAlien;
- theFrame = 4;
- break;
- case PLAYERCLASS_ALIVE_GESTATING:
- hSprite = this->m_hsprPlayerAlien;
- theFrame = 5;
- break;
-
- case PLAYERCLASS_ALIVE_DIGESTING:
- break;
- }
- }
- else
- {
- // it's an spectator
- }
- }
- else if (type == ET_NORMAL)
- {
- // Now help icons
- if(hSprite == 0)
- {
- AvHUser3 theUser3 = AvHUser3(ent->curstate.iuser3);
- theFrame = gHUD.GetHelpIconFrameFromUser3(theUser3);
- if(theFrame != -1)
- {
- hSprite = gHUD.GetHelpSprite();
- }
- }
- }
- */
- }
-
- if(hSprite > 0)
- {
-
- int theTeam = ent->curstate.team;
-
- float theR = kFTeamColors[theTeam][0];
- float theG = kFTeamColors[theTeam][1];
- float theB = kFTeamColors[theTeam][2];
-
- theSuccess = AddOverviewEntityToList(hSprite, ent, gEngfuncs.GetClientTime() + duration, theFrame, theRenderMode, theR, theG, theB);
-
- }
-
- return theSuccess;
-}
-
-void CHudSpectator::DeathMessage(int victim)
-{
- // find out where the victim is
- cl_entity_t *pl = gEngfuncs.GetEntityByIndex(victim);
-
- if (pl && pl->player)
- AddOverviewEntityToList(m_hsprPlayerDead, pl, gEngfuncs.GetClientTime() + 2.0f, 0, kRenderTransTexture, 1, 1, 1);
-}
-
-bool CHudSpectator::AddOverviewEntityToList(HSPRITE sprite, cl_entity_t *ent, double killTime, int inFrame, int inRenderMode, float r, float g, float b)
-{
- for ( int i = 0; i< MAX_OVERVIEW_ENTITIES; i++ )
- {
- // find empty entity slot
- if ( m_OverviewEntities[i].entity == NULL)
- {
- m_OverviewEntities[i].entity = ent;
- m_OverviewEntities[i].hSprite = sprite;
- m_OverviewEntities[i].killTime = killTime;
- m_OverviewEntities[i].mFrame = inFrame;
- m_OverviewEntities[i].mRenderMode = inRenderMode;
- m_OverviewEntities[i].mColorR = r;
- m_OverviewEntities[i].mColorG = g;
- m_OverviewEntities[i].mColorB = b;
- return true;
- }
- }
-
- return false; // maximum overview entities reached
-}
-void CHudSpectator::CheckSettings()
-{
- // disallow same inset mode as main mode:
-
- //m_pip->value = floor(m_pip->value);
-
- // Removed by mmcguire.
- /*
- if ( ( g_iUser1 < OBS_MAP_FREE ) && ( m_pip->value == INSET_CHASE_LOCKED || m_pip->value == INSET_IN_EYE ) )
- {
- // otherwise both would show in World picures
- m_pip->value = INSET_OFF;
- }
-
- // disble in intermission screen
- if ( gHUD.m_iIntermission )
- m_pip->value = INSET_OFF;
- */
-
- // check chat mode
- if ( m_chatEnabled != (gHUD.m_SayText.m_HUD_saytext->value!=0) )
- {
- // hud_saytext changed
- m_chatEnabled = (gHUD.m_SayText.m_HUD_saytext->value!=0);
-
- if ( gEngfuncs.IsSpectateOnly() )
- {
- // tell proxy our new chat mode
- char chatcmd[32];
- sprintf(chatcmd, "ignoremsg %i", m_chatEnabled?0:1 );
- gEngfuncs.pfnServerCmd(chatcmd);
- }
- }
-
- // HL/TFC has no oberserver corsshair, so set it client side
- if ( g_iUser1 == OBS_IN_EYE )
- {
- m_crosshairRect.left = 24;
- m_crosshairRect.top = 0;
- m_crosshairRect.right = 48;
- m_crosshairRect.bottom = 24;
-
- gHUD.SetCurrentCrosshair( m_hCrosshair, m_crosshairRect, 255, 255, 255 );
- }
- else
- {
- memset( &m_crosshairRect,0,sizeof(m_crosshairRect) );
- gHUD.SetCurrentCrosshair( 0, m_crosshairRect, 0, 0, 0 );
- }
-
- // Removed by mmcguire.
- /*
- // if we are a real player on server don't allow inset window
- // in First Person mode since this is our resticted forcecamera mode 2
- // team number 3 = SPECTATOR see player.h
-
- if ( ( (g_iTeamNumber == 1) || (g_iTeamNumber == 2)) && (g_iUser1 == OBS_IN_EYE) )
- m_pip->value = INSET_OFF;
- */
-
- // draw small border around inset view, adjust upper black bar
- //gViewPort->m_pSpectatorPanel->EnableInsetView( m_pip->value != INSET_OFF );
- gViewPort->m_pSpectatorPanel->EnableInsetView( IsInOverviewMode() );
-
-}
-
-
-void CHudSpectator::Reset()
-{
- // Reset HUD
- if ( strcmp( m_OverviewData.map, gEngfuncs.pfnGetLevelName() ) )
- {
- // update level overview if level changed
- ParseOverviewFile();
- LoadMapSprites();
- }
-
- memset( &m_OverviewEntities, 0, sizeof(m_OverviewEntities));
-
- SetSpectatorStartPosition();
-}
-
-void CHudSpectator::InitHUDData()
-{
- gHUD.InitHUDData();
- m_lastPrimaryObject = m_lastSecondaryObject = 0;
- m_flNextObserverInput = 0.0f;
- m_lastHudMessage = 0;
- m_iSpectatorNumber = 0;
- iJumpSpectator = 0;
- g_iUser1 = g_iUser2 = 0;
-
- memset( &m_OverviewData, 0, sizeof(m_OverviewData));
- memset( &m_OverviewEntities, 0, sizeof(m_OverviewEntities));
-
- if ( gEngfuncs.IsSpectateOnly() || gEngfuncs.pDemoAPI->IsPlayingback() )
- m_autoDirector->value = 1.0f;
- else
- m_autoDirector->value = 0.0f;
-
- Reset();
-
- SetMode( OBS_CHASE_FREE);
-
- g_iUser2 = 0; // fake not target until first camera command
-
- // reset HUD FOV
- gHUD.m_iFOV = CVAR_GET_FLOAT("default_fov");
-}
-
diff --git a/main/source/cl_dll/hud_spectator.h b/main/source/cl_dll/hud_spectator.h
index 91816a17..d15e4062 100644
--- a/main/source/cl_dll/hud_spectator.h
+++ b/main/source/cl_dll/hud_spectator.h
@@ -1,143 +1,143 @@
-//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============
-//
-// Purpose:
-//
-// $NoKeywords: $
-//=============================================================================
-
-#ifndef SPECTATOR_H
-#define SPECTATOR_H
-#pragma once
-
-#include "cl_entity.h"
-
-// Removed by mmcguire.
-/*
-#define INSET_OFF 0
-#define INSET_CHASE_LOCKED 1
-#define INSET_IN_EYE 2
-*/
-
-#define MAX_SPEC_HUD_MESSAGES 8
-
-
-
-#define OVERVIEW_TILE_SIZE 128 // don't change this
-#define OVERVIEW_MAX_LAYERS 1
-
-//-----------------------------------------------------------------------------
-// Purpose: Handles the drawing of the spectator stuff (camera & top-down map and all the things on it )
-//-----------------------------------------------------------------------------
-
-typedef struct overviewInfo_s {
- char map[64]; // cl.levelname or empty
- vec3_t origin; // center of map
- float zoom; // zoom of map images
- int layers; // how may layers do we have
- float layersHeights[OVERVIEW_MAX_LAYERS];
- char layersImages[OVERVIEW_MAX_LAYERS][255];
- qboolean rotated; // are map images rotated (90 degrees) ?
-
- int insetWindowX;
- int insetWindowY;
- int insetWindowHeight;
- int insetWindowWidth;
-} overviewInfo_t;
-
-typedef struct overviewEntity_s {
-
- HSPRITE hSprite;
- struct cl_entity_s * entity;
- double killTime;
- int mFrame;
- int mRenderMode;
- float mColorR;
- float mColorG;
- float mColorB;
-} overviewEntity_t;
-
-#define MAX_OVERVIEW_ENTITIES 256
-const int kOverviewEntityZHeight = 100;
-
-class CHudSpectator : public CHudBase
-{
-public:
- void Reset();
- void CheckSettings();
- void InitHUDData( void );
- bool AddOverviewEntityToList( HSPRITE sprite, cl_entity_t * ent, double killTime, int inFrame, int inRenderMode, float r, float g, float b);
- void DeathMessage(int victim);
- bool AddOverviewEntity( int type, struct cl_entity_s *ent, const char *modelname );
- void CheckOverviewEntities();
- void DrawOverview();
- void DrawOverviewEntities();
- void GetMapPosition( float * returnvec );
- void DrawOverviewLayer();
- void LoadMapSprites();
- bool ParseOverviewFile();
- bool IsActivePlayer(cl_entity_t * ent);
- void SetMode(int iMainMode);
- void HandleButtonsDown(int ButtonPressed);
- void HandleButtonsUp(int ButtonPressed);
- void FindNextPlayer( bool bReverse );
- void DirectorMessage( int iSize, void *pbuf );
- void SetSpectatorStartPosition();
- int Init();
- int VidInit();
-
- bool IsInOverviewMode() const;
- void SetOverviewMode(bool overviewMode);
-
- int Draw(float flTime);
- void DrawOverviewMap();
-
- int m_iDrawCycle;
- client_textmessage_t m_HUDMessages[MAX_SPEC_HUD_MESSAGES];
- char m_HUDMessageText[MAX_SPEC_HUD_MESSAGES][128];
- int m_lastHudMessage;
- overviewInfo_t m_OverviewData;
- overviewEntity_t m_OverviewEntities[MAX_OVERVIEW_ENTITIES];
- int m_iObserverFlags;
- int m_iSpectatorNumber;
-
- float m_mapZoom; // zoom the user currently uses
- vec3_t m_mapOrigin; // origin where user rotates around
- cvar_t * m_drawnames;
- cvar_t * m_drawcone;
- cvar_t * m_drawstatus;
- cvar_t * m_autoDirector;
-
- // Removed by mmcguire.
- bool m_overviewMode;
- //cvar_t * m_overview;
- //cvar_t * m_pip;
-
-
- qboolean m_chatEnabled;
-
- vec3_t m_cameraOrigin; // a help camera
- vec3_t m_cameraAngles; // and it's angles
-
-private:
- vec3_t m_vPlayerPos[MAX_PLAYERS];
- HSPRITE m_hsprPlayerMarine;
- HSPRITE m_hsprPlayerAlien;
- HSPRITE m_hsprCamera;
- HSPRITE m_hsprPlayerDead;
- HSPRITE m_hsprViewcone;
- HSPRITE m_hsprUnkownMap;
- HSPRITE m_hsprBeam;
- HSPRITE m_hCrosshair;
- HSPRITE m_hsprWhite;
-
- wrect_t m_crosshairRect;
-
- struct model_s * m_MapSprite; // each layer image is saved in one sprite, where each tile is a sprite frame
- float m_flNextObserverInput;
- float m_zoomDelta;
- float m_moveDelta;
- int m_lastPrimaryObject;
- int m_lastSecondaryObject;
-};
-
-#endif // SPECTATOR_H
+//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================
+
+#ifndef SPECTATOR_H
+#define SPECTATOR_H
+#pragma once
+
+#include "cl_entity.h"
+
+// Removed by mmcguire.
+/*
+#define INSET_OFF 0
+#define INSET_CHASE_LOCKED 1
+#define INSET_IN_EYE 2
+*/
+
+#define MAX_SPEC_HUD_MESSAGES 8
+
+
+
+#define OVERVIEW_TILE_SIZE 128 // don't change this
+#define OVERVIEW_MAX_LAYERS 1
+
+//-----------------------------------------------------------------------------
+// Purpose: Handles the drawing of the spectator stuff (camera & top-down map and all the things on it )
+//-----------------------------------------------------------------------------
+
+typedef struct overviewInfo_s {
+ char map[64]; // cl.levelname or empty
+ vec3_t origin; // center of map
+ float zoom; // zoom of map images
+ int layers; // how may layers do we have
+ float layersHeights[OVERVIEW_MAX_LAYERS];
+ char layersImages[OVERVIEW_MAX_LAYERS][255];
+ qboolean rotated; // are map images rotated (90 degrees) ?
+
+ int insetWindowX;
+ int insetWindowY;
+ int insetWindowHeight;
+ int insetWindowWidth;
+} overviewInfo_t;
+
+typedef struct overviewEntity_s {
+
+ HSPRITE hSprite;
+ struct cl_entity_s * entity;
+ double killTime;
+ int mFrame;
+ int mRenderMode;
+ float mColorR;
+ float mColorG;
+ float mColorB;
+} overviewEntity_t;
+
+#define MAX_OVERVIEW_ENTITIES 256
+const int kOverviewEntityZHeight = 100;
+
+class CHudSpectator : public CHudBase
+{
+public:
+ void Reset();
+ void CheckSettings();
+ void InitHUDData( void );
+ bool AddOverviewEntityToList( HSPRITE sprite, cl_entity_t * ent, double killTime, int inFrame, int inRenderMode, float r, float g, float b);
+ void DeathMessage(int victim);
+ bool AddOverviewEntity( int type, struct cl_entity_s *ent, const char *modelname );
+ void CheckOverviewEntities();
+ void DrawOverview();
+ void DrawOverviewEntities();
+ void GetMapPosition( float * returnvec );
+ void DrawOverviewLayer();
+ void LoadMapSprites();
+ bool ParseOverviewFile();
+ bool IsActivePlayer(cl_entity_t * ent);
+ void SetMode(int iMainMode);
+ void HandleButtonsDown(int ButtonPressed);
+ void HandleButtonsUp(int ButtonPressed);
+ void FindNextPlayer( bool bReverse );
+ void DirectorMessage( int iSize, void *pbuf );
+ void SetSpectatorStartPosition();
+ int Init();
+ int VidInit();
+
+ bool IsInOverviewMode() const;
+ void SetOverviewMode(bool overviewMode);
+
+ int Draw(float flTime);
+ void DrawOverviewMap();
+
+ int m_iDrawCycle;
+ client_textmessage_t m_HUDMessages[MAX_SPEC_HUD_MESSAGES];
+ char m_HUDMessageText[MAX_SPEC_HUD_MESSAGES][128];
+ int m_lastHudMessage;
+ overviewInfo_t m_OverviewData;
+ overviewEntity_t m_OverviewEntities[MAX_OVERVIEW_ENTITIES];
+ int m_iObserverFlags;
+ int m_iSpectatorNumber;
+
+ float m_mapZoom; // zoom the user currently uses
+ vec3_t m_mapOrigin; // origin where user rotates around
+ cvar_t * m_drawnames;
+ cvar_t * m_drawcone;
+ cvar_t * m_drawstatus;
+ cvar_t * m_autoDirector;
+
+ // Removed by mmcguire.
+ bool m_overviewMode;
+ //cvar_t * m_overview;
+ //cvar_t * m_pip;
+
+
+ qboolean m_chatEnabled;
+
+ vec3_t m_cameraOrigin; // a help camera
+ vec3_t m_cameraAngles; // and it's angles
+
+private:
+ vec3_t m_vPlayerPos[MAX_PLAYERS];
+ HSPRITE m_hsprPlayerMarine;
+ HSPRITE m_hsprPlayerAlien;
+ HSPRITE m_hsprCamera;
+ HSPRITE m_hsprPlayerDead;
+ HSPRITE m_hsprViewcone;
+ HSPRITE m_hsprUnkownMap;
+ HSPRITE m_hsprBeam;
+ HSPRITE m_hCrosshair;
+ HSPRITE m_hsprWhite;
+
+ wrect_t m_crosshairRect;
+
+ struct model_s * m_MapSprite; // each layer image is saved in one sprite, where each tile is a sprite frame
+ float m_flNextObserverInput;
+ float m_zoomDelta;
+ float m_moveDelta;
+ int m_lastPrimaryObject;
+ int m_lastSecondaryObject;
+};
+
+#endif // SPECTATOR_H
diff --git a/main/source/cl_dll/hud_update.cpp b/main/source/cl_dll/hud_update.cpp
index 7210fc28..18e2cb82 100644
--- a/main/source/cl_dll/hud_update.cpp
+++ b/main/source/cl_dll/hud_update.cpp
@@ -1,52 +1,102 @@
-/***
-*
-* Copyright (c) 1999, Valve LLC. All rights reserved.
-*
-* This product contains software technology licensed from Id
-* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
-* All Rights Reserved.
-*
-* Use, distribution, and modification of this source code and/or resulting
-* object code is restricted to non-commercial enhancements to products from
-* Valve LLC. All other use, distribution, or modification is prohibited
-* without written permission from Valve LLC.
-*
-****/
-//
-// hud_update.cpp
-//
-
-#include
-#include "hud.h"
-#include "cl_util.h"
-#include
-#include
-
-int CL_ButtonBits( int );
-void CL_ResetButtonBits( int bits );
-
-extern float v_idlescale;
-float in_fov;
-extern void HUD_SetCmdBits( int bits );
-
-int CHud::UpdateClientData(client_data_t *cdata, float time)
-{
- memcpy(m_vecOrigin, cdata->origin, sizeof(vec3_t));
- memcpy(m_vecAngles, cdata->viewangles, sizeof(vec3_t));
-
- m_iKeyBits = CL_ButtonBits( 0 );
- m_iWeaponBits = cdata->iWeaponBits;
-
- in_fov = cdata->fov;
-
- Think();
-
- cdata->fov = m_iFOV;
-
- CL_ResetButtonBits( m_iKeyBits );
-
- // return 1 if in anything in the client_data struct has been changed, 0 otherwise
- return 1;
-}
-
-
+/***
+*
+* Copyright (c) 1999, Valve LLC. All rights reserved.
+*
+* This product contains software technology licensed from Id
+* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
+* All Rights Reserved.
+*
+* Use, distribution, and modification of this source code and/or resulting
+* object code is restricted to non-commercial enhancements to products from
+* Valve LLC. All other use, distribution, or modification is prohibited
+* without written permission from Valve LLC.
+*
+****/
+//
+// hud_update.cpp
+//
+
+#include
+#include "hud.h"
+#include "cl_util.h"
+#include
+#include
+
+int CL_ButtonBits( int );
+void CL_ResetButtonBits( int bits );
+
+extern float v_idlescale;
+float in_fov;
+extern void HUD_SetCmdBits( int bits );
+
+int CHud::UpdateClientData(client_data_t *cdata, float time)
+{
+ memcpy(m_vecOrigin, cdata->origin, sizeof(vec3_t));
+ memcpy(m_vecAngles, cdata->viewangles, sizeof(vec3_t));
+
+ m_iKeyBits = CL_ButtonBits( 0 );
+ m_iWeaponBits = cdata->iWeaponBits;
+
+ in_fov = cdata->fov;
+
+ Think();
+
+ //cdata->fov = m_iFOV;
+
+ float width = ScreenWidth();
+ float height = ScreenHeight();
+
+ //horizontal+ widescreen view correction - engine uses vertical-
+ //starts with hacked in commander view fix where commander fov was changed to 106 so the black background beind the map is fully rendered - remove that section and change comm fov back to 90 if fixed
+ if (gHUD.GetIsInTopDownMode())
+ {
+ float commFOV;
+
+ commFOV = atanf(tan(m_iFOV * M_PI / 360) * 0.5625 * width / height) * 360 / M_PI;
+
+ //clamp
+ if (commFOV > 107)
+ {
+ commFOV = 106;
+ }
+ else if (commFOV < 90)
+ {
+ commFOV = 90;
+ }
+
+ cdata->fov = commFOV;
+ }
+ else
+ {
+ float newFOV;
+
+ newFOV = atanf(tan(m_iFOV * M_PI / 360) * 0.75 * width / height) * 360 / M_PI;
+
+ //clamp for game balance
+ if (m_iFOV == 105 && newFOV > 121)
+ {
+ newFOV = 120;
+ }
+ else if (m_iFOV == 100 && newFOV > 117)
+ {
+ newFOV = 116;
+ }
+ else if (m_iFOV == 90 && newFOV > 107)
+ {
+ newFOV = 106;
+ }
+ else if (newFOV < 90)
+ {
+ newFOV = 90;
+ }
+
+ cdata->fov = newFOV;
+ }
+
+ CL_ResetButtonBits( m_iKeyBits );
+
+ // return 1 if in anything in the client_data struct has been changed, 0 otherwise
+ return 1;
+}
+
+
diff --git a/main/source/cl_dll/in_defs.h b/main/source/cl_dll/in_defs.h
index 60d99feb..00b4da58 100644
--- a/main/source/cl_dll/in_defs.h
+++ b/main/source/cl_dll/in_defs.h
@@ -1,12 +1,12 @@
-#if !defined( IN_DEFSH )
-#define IN_DEFSH
-#pragma once
-
-// up / down
-#define PITCH 0
-// left / right
-#define YAW 1
-// fall over
-#define ROLL 2
-
+#if !defined( IN_DEFSH )
+#define IN_DEFSH
+#pragma once
+
+// up / down
+#define PITCH 0
+// left / right
+#define YAW 1
+// fall over
+#define ROLL 2
+
#endif
\ No newline at end of file
diff --git a/main/source/cl_dll/input.cpp b/main/source/cl_dll/input.cpp
index 9a49979f..9c3bd65c 100644
--- a/main/source/cl_dll/input.cpp
+++ b/main/source/cl_dll/input.cpp
@@ -1,1576 +1,1576 @@
-//======== (C) Copyright 2002 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:
-//
-// $Workfile: input.cpp $
-// $Date: 2002/10/16 02:12:21 $
-//
-//-------------------------------------------------------------------------------
-// $Log: input.cpp,v $
-// Revision 1.28 2002/10/16 02:12:21 Flayra
-// - Valve anti-cheat integrated!
-//
-// Revision 1.27 2002/08/09 00:13:04 Flayra
-// - Removed explicitly allowing specific commands. I can't remember why this was needed, but it doesn't appear to be anymore.
-//
-// Revision 1.26 2002/08/02 21:39:03 Flayra
-// - Refactored variable names
-//
-// Revision 1.25 2002/07/08 16:13:31 Flayra
-// - Fixed bug where command was able to switch weapons via mousewheel (bug #239)
-//
-//===============================================================================
-// cl.input.c -- builds an intended movement command to send to the server
-
-//xxxxxx Move bob and pitch drifting code here and other stuff from view if needed
-
-// Quake is a trademark of Id Software, Inc., (c) 1996 Id Software, Inc. All
-// rights reserved.
-#include "hud.h"
-#include "cl_util.h"
-#include "camera.h"
-extern "C"
-{
-#include "kbutton.h"
-}
-#include "cvardef.h"
-#include "usercmd.h"
-#include "const.h"
-#include "camera.h"
-#include "in_defs.h"
-#include "view.h"
-#include "bench.h"
-#include
-#include
-#include "engine/keydefs.h"
-#include "Exports.h"
-
-#include "vgui_TeamFortressViewport.h"
-#include "mod/AvHServerVariables.h"// should we go ahead and just make a SharedVariables.h instead?
-#include "mod/AvHClientVariables.h"
-#include "mod/AvHMessage.h"
-#include "winsani_in.h"
-#include "fmod.h"
-#include "winsani_out.h"
-#include "mod/AvHScriptManager.h"
-#include "mod/AvHScrollHandler.h"
-#include "mod/AvHCommanderModeHandler.h"
-#include "util/Mat3.h"
-
-#include "engine/APIProxy.h"
-#include "Exports.h"
-
-// : duck toggle
-extern bool g_bDuckToggled;
-// :
-
-extern int g_iAlive;
-
-extern int g_weaponselect;
-extern cl_enginefunc_t gEngfuncs;
-bool gResetViewAngles = false;
-vec3_t gViewAngles;
-extern AvHCommanderModeHandler gCommanderHandler;
-
-///////////////////////////////
-// Begin Max's Code
-///////////////////////////////
-
-float gPlayerAngles[3] = { 0, 0, 0 };
-float gTargetPlayerAngles[3] = { 0, 0, 0 };
-float gWorldViewAngles[3] = { 0, 0, 0 };
-
-///////////////////////////////
-// End Max's Code
-///////////////////////////////
-
-// Defined in pm_math.c
-//extern "C" float anglemod( float a );
-float anglemod( float a );
-
-void IN_Init (void);
-void IN_Move ( float frametime, usercmd_t *cmd);
-void IN_Shutdown( void );
-void V_Init( void );
-void VectorAngles( const float *forward, float *angles );
-int CL_ButtonBits( int );
-
-// xxx need client dll function to get and clear impuse
-extern cvar_t *in_joystick;
-
-int in_impulse = 0;
-int in_cancel = 0;
-
-cvar_t *m_pitch;
-cvar_t *m_yaw;
-cvar_t *m_forward;
-cvar_t *m_side;
-
-cvar_t *lookstrafe;
-cvar_t *lookspring;
-cvar_t *cl_pitchup;
-cvar_t *cl_pitchdown;
-cvar_t *cl_upspeed;
-cvar_t *cl_forwardspeed;
-cvar_t *cl_backspeed;
-cvar_t *cl_sidespeed;
-cvar_t *cl_movespeedkey;
-cvar_t *cl_yawspeed;
-cvar_t *cl_pitchspeed;
-cvar_t *cl_anglespeedkey;
-cvar_t *cl_vsmoothing;
-cvar_t *cl_autohelp;
-cvar_t *cl_centerentityid;
-cvar_t *cl_musicenabled;
-cvar_t *cl_musicdelay;
-cvar_t *cl_musicvolume;
-cvar_t *cl_musicdir;
-cvar_t *cl_quickselecttime;
-cvar_t *cl_highdetail;
-cvar_t *cl_cmhotkeys;
-cvar_t *cl_forcedefaultfov;
-cvar_t *cl_dynamiclights;
-cvar_t *cl_buildmessages;
-cvar_t *cl_particleinfo;
-
-/*
-===============================================================================
-
-KEY BUTTONS
-
-Continuous button event tracking is complicated by the fact that two different
-input sources (say, mouse button 1 and the control key) can both press the
-same button, but the button should only be released when both of the
-pressing key have been released.
-
-When a key event issues a button command (+forward, +attack, etc), it appends
-its key number as a parameter to the command so it can be matched up with
-the release.
-
-state bit 0 is the current state of the key
-state bit 1 is edge triggered on the up to down transition
-state bit 2 is edge triggered on the down to up transition
-
-===============================================================================
-*/
-
-
-kbutton_t in_mlook;
-kbutton_t in_klook;
-kbutton_t in_jlook;
-kbutton_t in_left;
-kbutton_t in_right;
-kbutton_t in_forward;
-kbutton_t in_back;
-kbutton_t in_lookup;
-kbutton_t in_lookdown;
-kbutton_t in_moveleft;
-kbutton_t in_moveright;
-kbutton_t in_strafe;
-kbutton_t in_speed;
-kbutton_t in_use;
-kbutton_t in_jump;
-kbutton_t in_attack;
-kbutton_t in_attack2;
-kbutton_t in_up;
-kbutton_t in_down;
-kbutton_t in_duck;
-kbutton_t in_reload;
-kbutton_t in_alt1;
-kbutton_t in_score;
-kbutton_t in_break;
-kbutton_t in_graph; // Display the netgraph
-
-typedef struct kblist_s
-{
- struct kblist_s *next;
- kbutton_t *pkey;
- char name[32];
-} kblist_t;
-
-kblist_t *g_kbkeys = NULL;
-
-vector< pair > g_PrevCmds;
-
-/*
-============
-KB_ConvertString
-
-Removes references to +use and replaces them with the keyname in the output string. If
- a binding is unfound, then the original text is retained.
-NOTE: Only works for text with +word in it.
-============
-*/
-int KB_ConvertString( char *in, char **ppout )
-{
- char sz[ 4096 ];
- char binding[ 64 ];
- char *p;
- char *pOut;
- char *pEnd;
- const char *pBinding;
-
- if ( !ppout )
- return 0;
-
- *ppout = NULL;
- p = in;
- pOut = sz;
- while ( *p )
- {
- if ( *p == '+' )
- {
- pEnd = binding;
- while ( *p && ( isalnum( *p ) || ( pEnd == binding ) ) && ( ( pEnd - binding ) < 63 ) )
- {
- *pEnd++ = *p++;
- }
-
- *pEnd = '\0';
-
- pBinding = NULL;
- if ( strlen( binding + 1 ) > 0 )
- {
- // See if there is a binding for binding?
- pBinding = gEngfuncs.Key_LookupBinding( binding + 1 );
- }
-
- if ( pBinding )
- {
- *pOut++ = '[';
- pEnd = (char *)pBinding;
- }
- else
- {
- pEnd = binding;
- }
-
- while ( *pEnd )
- {
- *pOut++ = *pEnd++;
- }
-
- if ( pBinding )
- {
- *pOut++ = ']';
- }
- }
- else
- {
- *pOut++ = *p++;
- }
- }
-
- *pOut = '\0';
-
- pOut = ( char * )malloc( strlen( sz ) + 1 );
- strcpy( pOut, sz );
- *ppout = pOut;
-
- return 1;
-}
-
-/*
-============
-KB_Find
-
-Allows the engine to get a kbutton_t directly ( so it can check +mlook state, etc ) for saving out to .cfg files
-============
-*/
-struct kbutton_s CL_DLLEXPORT *KB_Find( const char *name )
-{
-// RecClFindKey(name);
-
- kblist_t *p;
- p = g_kbkeys;
- while ( p )
- {
- if ( !stricmp( name, p->name ) )
- return p->pkey;
-
- p = p->next;
- }
- return NULL;
-}
-
-/*
-============
-KB_Add
-
-Add a kbutton_t * to the list of pointers the engine can retrieve via KB_Find
-============
-*/
-void KB_Add( const char *name, kbutton_t *pkb )
-{
- kblist_t *p;
- kbutton_t *kb;
-
- kb = KB_Find( name );
-
- if ( kb )
- return;
-
- p = ( kblist_t * )malloc( sizeof( kblist_t ) );
- memset( p, 0, sizeof( *p ) );
-
- strcpy( p->name, name );
- p->pkey = pkb;
-
- p->next = g_kbkeys;
- g_kbkeys = p;
-}
-
-/*
-============
-KB_Init
-
-Add kbutton_t definitions that the engine can query if needed
-============
-*/
-void KB_Init( void )
-{
- g_kbkeys = NULL;
-
- KB_Add( "in_graph", &in_graph );
- KB_Add( "in_mlook", &in_mlook );
- KB_Add( "in_jlook", &in_jlook );
-}
-
-/*
-============
-KB_Shutdown
-
-Clear kblist
-============
-*/
-void KB_Shutdown( void )
-{
- kblist_t *p, *n;
- p = g_kbkeys;
- while ( p )
- {
- n = p->next;
- free( p );
- p = n;
- }
- g_kbkeys = NULL;
-}
-
-/*
-============
-KeyDown
-============
-*/
-void KeyDown (kbutton_t *b)
-{
- int k;
- char *c;
-
- c = gEngfuncs.Cmd_Argv(1);
- if (c[0])
- k = atoi(c);
- else
- k = -1; // typed manually at the console for continuous down
-
- int theBlockScripts = (int)gHUD.GetServerVariableFloat(kvBlockScripts);
-
- char *pCmd = gEngfuncs.Cmd_Argv(0);
-
- if(theBlockScripts && pCmd)
- {
- bool bFound = false;
-
- //Check thier last few commands (this prevents false positives if a player is hits several keys real fast)
- for (int i = 0; i < g_PrevCmds.size(); i++)
- {
- //Check both the key pressed and the command it executed.
- if(k == g_PrevCmds[i].first && !strcmp(pCmd, g_PrevCmds[i].second.c_str()))
- {
- bFound = true;
- break;
- }
- }
-
-
- if(!bFound
- && strcmp(pCmd, "+mlook")
- && strcmp(pCmd, "+jlook")
- && strcmp(pCmd, "+showscores")
- && strcmp(pCmd, "+use"))
- {
- gEngfuncs.pfnCenterPrint("Scripting is not allowed on this server.");
- b->down[0] = b->down[1] = 0;
- b->state = 4; // impulse up
- return;
- }
- }
-
- if (k == b->down[0] || k == b->down[1])
- return; // repeating key
-
- if (!b->down[0])
- b->down[0] = k;
- else if (!b->down[1])
- b->down[1] = k;
- else
- {
- gEngfuncs.Con_DPrintf ("Three keys down for a button '%c' '%c' '%c'!\n", b->down[0], b->down[1], c);
- return;
- }
-
- if (b->state & 1)
- return; // still down
- b->state |= 1 + 2; // down + impulse down
-}
-
-/*
-============
-KeyDownForced
-============
-*/
-void KeyDownForced (kbutton_t *b)
-{
- b->down[0] = 0;
- b->down[1] = 0;
-
- if (b->state & 1)
- return; // still down
- b->state |= 1 + 2; // down + impulse down
-}
-
-/*
-============
-KeyUp
-============
-*/
-void KeyUp (kbutton_t *b)
-{
- int k;
- char *c;
-
- c = gEngfuncs.Cmd_Argv(1);
- if (c[0])
- k = atoi(c);
- else
- { // typed manually at the console, assume for unsticking, so clear all
- b->down[0] = b->down[1] = 0;
- b->state = 4; // impulse up
- return;
- }
-
- if (b->down[0] == k)
- b->down[0] = 0;
- else if (b->down[1] == k)
- b->down[1] = 0;
- else
- return; // key up without coresponding down (menu pass through)
- if (b->down[0] || b->down[1])
- {
- //Con_Printf ("Keys down for button: '%c' '%c' '%c' (%d,%d,%d)!\n", b->down[0], b->down[1], c, b->down[0], b->down[1], c);
- return; // some other key is still holding it down
- }
-
- if (!(b->state & 1))
- return; // still up (this should not happen)
-
- b->state &= ~1; // now up
- b->state |= 4; // impulse up
-}
-
-/*
-============
-KeyUpForced
-============
-*/
-void KeyUpForced (kbutton_t *b)
-{
- b->state &= ~1; // now up
- b->state |= 4; // impulse up
-}
-
-bool AvHContainsBlockedCommands(const char* inInput)
-{
- if (inInput == NULL)
- {
- return false;
- }
-
- const char* kBlockedCommand[] =
- {
- "exec",
- "wait",
- "special",
- "_special"
- };
-
- // Check for a ; indicating multiple commands.
-
- if (strchr(inInput, ';') != NULL)
- {
- return true;
- }
-
- // Check if any of the blocked commands are being used.
-
- const char* theCommandEnd = strpbrk(inInput, " \t");
-
- int theCommandLength;
-
- if (theCommandEnd == NULL)
- {
- theCommandLength = (int)strlen(inInput);
- }
- else
- {
- theCommandLength = theCommandEnd - inInput;
- }
-
- for (int i = 0; i < sizeof(kBlockedCommand) / sizeof(const char*); ++i)
- {
- if ((int)strlen(kBlockedCommand[i]) == theCommandLength &&
- strncmp(inInput, kBlockedCommand[i], theCommandLength) == 0)
- {
- return true;
- }
- }
- return false;
-}
-
-/*
-============
-HUD_Key_Event
-
-Return 1 to allow engine to process the key, otherwise, act on it as needed
-============
-*/
-int CL_DLLEXPORT HUD_Key_Event( int down, int keynum, const char *pszCurrentBinding )
-{
-// RecClKeyEvent(down, keynum, pszCurrentBinding);
-
- // Check to see if the event has any outlawed commands in it.
- float theBlockScripts = gHUD.GetServerVariableFloat(kvBlockScripts);
-
- if (theBlockScripts && AvHContainsBlockedCommands(pszCurrentBinding))
- {
- if(down)//: only show when going down.
- gEngfuncs.pfnCenterPrint("Scripting is not allowed on this server.\n");
- return 0;
- }
-
- if(pszCurrentBinding)
- {
- if(g_PrevCmds.size() >= 5)
- g_PrevCmds.erase(g_PrevCmds.begin());//remove the oldest command
-
- g_PrevCmds.push_back(make_pair(keynum, (string)pszCurrentBinding));
- }
-
- int theProcessKeyBinding = 1;
-
-// char theKeyBinding[256] = "none";
-// if(pszCurrentBinding)
-// {
-// sprintf(theKeyBinding, pszCurrentBinding);
-// }
-//
-// char theMessage[512];
-// sprintf(theMessage, "%s (down: %d, keynum %d)", theKeyBinding, down, keynum);
-// CenterPrint(theMessage);
-
- if(gViewPort /*&& gViewPort->IsOptionsMenuVisible()*/)
- {
-
- theProcessKeyBinding = gViewPort->KeyInput(down, keynum, pszCurrentBinding);
-
- if(pszCurrentBinding && (!strcmp(pszCurrentBinding, "toggleconsole") || !strcmp(pszCurrentBinding, "cancelselect")))
- {
- theProcessKeyBinding = 1;
- }
- }
-
-
- // Process topdown commands with precedence first
- if(theProcessKeyBinding && gHUD.GetInTopDownMode())
- {
- if((keynum != 0) && down/*&& pszCurrentBinding*/)
- {
- AvHMessageID theMessageID = gHUD.HotKeyHit(keynum);
- if((theMessageID != MESSAGE_NULL) || (keynum == K_ESCAPE))
- {
- // If ESC or cancel was hit, cancel ghost building
- if((keynum == K_ESCAPE) || (theMessageID == MESSAGE_CANCEL))
- {
- gHUD.SetGhostBuildingMode(MESSAGE_NULL);
- }
-
- theProcessKeyBinding = 0;
- }
- }
- }
-
- if(theProcessKeyBinding)
- {
- // Process only a couple keybindings in top down mode
-// if(!gHUD.GetInTopDownMode() || (pszCurrentBinding &&
-//
-// // Misc. commands
-// (!strcmp(pszCurrentBinding, "toggleconsole") || !strcmp(pszCurrentBinding, "cancelselect") || !strcmp(pszCurrentBinding, "+showscores") || !strcmp(pszCurrentBinding, "-showscores") || !strcmp(pszCurrentBinding, "messagemode") || !strcmp(pszCurrentBinding, "messagemode2") || !strcmp(pszCurrentBinding, "snapshot") || !strcmp(pszCurrentBinding, "screenshot") || !strcmp(pszCurrentBinding, "+jump") || !strcmp(pszCurrentBinding, "addbot") || !strcmp(pszCurrentBinding, "+voicerecord") || !strcmp(pszCurrentBinding, "-voicerecord") ||
-//
-// // Movement commands
-// !strcmp(pszCurrentBinding, "testevent") /*|| !strcmp(pszCurrentBinding, "invnext") || !strcmp(pszCurrentBinding, "invprev")*/ || !strcmp(pszCurrentBinding, "+moveleft") || !strcmp(pszCurrentBinding, "-moveleft") || !strcmp(pszCurrentBinding, "+moveright") || !strcmp(pszCurrentBinding, "-moveright") || !strcmp(pszCurrentBinding, "+moveup") || !strcmp(pszCurrentBinding, "-moveup") || !strcmp(pszCurrentBinding, "+movedown") || !strcmp(pszCurrentBinding, "-movedown") ||
-//
-// // For selecting groups
-// !strcmp(pszCurrentBinding, "slot1") || !strcmp(pszCurrentBinding, "slot2") || !strcmp(pszCurrentBinding, "slot3") || !strcmp(pszCurrentBinding, "slot4") || !strcmp(pszCurrentBinding, "slot5") ||
-//
-// // For creating groups
-// !strcmp(pszCurrentBinding, "+duck") || !strcmp(pszCurrentBinding, "-duck") ||
-//
-// // For testing ease
-// !strcmp(pszCurrentBinding, "givepoints")
-//
-// )))
-// {
- if (gViewPort)
- theProcessKeyBinding = gViewPort->KeyInput(down, keynum, pszCurrentBinding);
-
-// // Don't
-// if(!strcmp(pszCurrentBinding, "+jump") && gHUD.GetInTopDownMode())
-// {
-// gHUD.GotoAlert();
-// }
-
-// }
- }
-
- return theProcessKeyBinding;
-}
-
-void IN_BreakDown( void ) { KeyDown( &in_break );};
-void IN_BreakUp( void ) { KeyUp( &in_break ); };
-void IN_KLookDown (void) {KeyDown(&in_klook);}
-void IN_KLookUp (void) {KeyUp(&in_klook);}
-void IN_JLookDown (void) {KeyDown(&in_jlook);}
-void IN_JLookUp (void) {KeyUp(&in_jlook);}
-void IN_MLookDown (void) {KeyDown(&in_mlook);}
-void IN_UpDown(void) {KeyDown(&in_up);}
-void IN_UpUp(void) {KeyUp(&in_up);}
-void IN_DownDown(void) {KeyDown(&in_down);}
-void IN_DownUp(void) {KeyUp(&in_down);}
-void IN_LeftDown(void) {KeyDown(&in_left);}
-void IN_LeftUp(void) {KeyUp(&in_left);}
-void IN_RightDown(void) {KeyDown(&in_right);}
-void IN_RightUp(void) {KeyUp(&in_right);}
-
-void IN_ForwardDown(void)
-{
- KeyDown(&in_forward);
- gHUD.m_Spectator.HandleButtonsDown( IN_FORWARD );
-}
-
-void IN_ForwardUp(void)
-{
- KeyUp(&in_forward);
- gHUD.m_Spectator.HandleButtonsUp( IN_FORWARD );
-}
-
-void IN_BackDown(void)
-{
- KeyDown(&in_back);
- gHUD.m_Spectator.HandleButtonsDown( IN_BACK );
-}
-
-void IN_BackUp(void)
-{
- KeyUp(&in_back);
- gHUD.m_Spectator.HandleButtonsUp( IN_BACK );
-}
-void IN_LookupDown(void) {KeyDown(&in_lookup);}
-void IN_LookupUp(void) {KeyUp(&in_lookup);}
-void IN_LookdownDown(void) {KeyDown(&in_lookdown);}
-void IN_LookdownUp(void) {KeyUp(&in_lookdown);}
-void IN_MoveleftDown(void)
-{
- KeyDown(&in_moveleft);
- gHUD.m_Spectator.HandleButtonsDown( IN_MOVELEFT );
-}
-
-void IN_MoveleftUp(void)
-{
- KeyUp(&in_moveleft);
- gHUD.m_Spectator.HandleButtonsUp( IN_MOVELEFT );
-}
-
-void IN_MoverightDown(void)
-{
- KeyDown(&in_moveright);
- gHUD.m_Spectator.HandleButtonsDown( IN_MOVERIGHT );
-}
-
-void IN_MoverightUp(void)
-{
- KeyUp(&in_moveright);
- gHUD.m_Spectator.HandleButtonsUp( IN_MOVERIGHT );
-}
-void IN_SpeedDown(void) {KeyDown(&in_speed);}
-void IN_SpeedUp(void) {KeyUp(&in_speed);}
-void IN_StrafeDown(void) {KeyDown(&in_strafe);}
-void IN_StrafeUp(void) {KeyUp(&in_strafe);}
-
-// needs capture by hud/vgui also
-extern void __CmdFunc_InputPlayerSpecial(void);
-void IN_Attack2Down(void) {KeyDownForced(&in_attack2);}
-void IN_Attack2Up(void) {KeyUpForced(&in_attack2);}
-void IN_UseDown (void)
-{
- KeyDown(&in_use);
- gHUD.m_Spectator.HandleButtonsDown( IN_USE );
-}
-void IN_UseUp (void) {KeyUp(&in_use);}
-void IN_JumpDown (void)
-{
- KeyDown(&in_jump);
- gHUD.m_Spectator.HandleButtonsDown( IN_JUMP );
-
-}
-
-void IN_JumpUp (void)
-{
- KeyUp(&in_jump);
- gHUD.m_Spectator.HandleButtonsUp( IN_JUMP );
-}
-
-void IN_DuckDown(void)
-{
- KeyDown(&in_duck);
- gHUD.m_Spectator.HandleButtonsDown( IN_DUCK );
-}
-
-void IN_DuckUp(void) {KeyUp(&in_duck);}
-// : duck toggle
-void IN_DuckToggle(void)
-{
- g_bDuckToggled = !g_bDuckToggled;
-}
-// :
-void IN_ReloadDown(void) {KeyDownForced(&in_reload);}
-void IN_ReloadUp(void) {KeyUpForced(&in_reload);}
-void IN_Alt1Down(void) {KeyDown(&in_alt1);}
-void IN_Alt1Up(void) {KeyUp(&in_alt1);}
-void IN_GraphDown(void) {KeyDown(&in_graph);}
-void IN_GraphUp(void) {KeyUp(&in_graph);}
-
-void IN_AttackDown(void)
-{
- KeyDown( &in_attack );
- gHUD.m_Spectator.HandleButtonsDown( IN_ATTACK );
-}
-
-void IN_AttackUp(void)
-{
- KeyUp( &in_attack );
- in_cancel = 0;
- IN_Attack2Up();
-}
-
-void IN_AttackDownForced(void)
-{
- KeyDownForced( &in_attack );
-}
-
-void IN_AttackUpForced(void)
-{
- KeyUpForced( &in_attack );
-}
-
-// Special handling
-void IN_Cancel(void)
-{
- in_cancel = 1;
-}
-
-bool CheckInAttack(void)
-{
- return (in_attack.state & 1 || in_attack2.state & 1);
-}
-
-bool CheckInAttack2(void)
-{
- return (in_attack2.state & 1);
-}
-
-void IN_Impulse (void)
-{
- //char msg[1024];
- //sprintf(msg, "in_impulse=%s\n", gEngfuncs.Cmd_Argv(1));
- //CenterPrint(msg);
-
- in_impulse = atoi( gEngfuncs.Cmd_Argv(1) );
-}
-
-void IN_ScoreDown(void)
-{
- KeyDown(&in_score);
- if ( gViewPort )
- {
- gViewPort->ShowScoreBoard();
- }
-}
-
-void IN_ScoreUp(void)
-{
- KeyUp(&in_score);
- if ( gViewPort )
- {
- gViewPort->HideScoreBoard();
- }
-}
-
-void IN_MLookUp (void)
-{
- KeyUp( &in_mlook );
- if ( !( in_mlook.state & 1 ) && lookspring->value )
- {
- V_StartPitchDrift();
- }
-}
-
-/*
-===============
-CL_KeyState
-
-Returns 0.25 if a key was pressed and released during the frame,
-0.5 if it was pressed and held
-0 if held then released, and
-1.0 if held for the entire time
-===============
-*/
-float CL_KeyState (kbutton_t *key)
-{
- float val = 0.0;
- int impulsedown, impulseup, down;
-
- impulsedown = key->state & 2;
- impulseup = key->state & 4;
- down = key->state & 1;
-
- if ( impulsedown && !impulseup )
- {
- // pressed and held this frame?
- val = down ? 0.5 : 0.0;
- }
-
- if ( impulseup && !impulsedown )
- {
- // released this frame?
- val = down ? 0.0 : 0.0;
- }
-
- if ( !impulsedown && !impulseup )
- {
- // held the entire frame?
- val = down ? 1.0 : 0.0;
- }
-
- if ( impulsedown && impulseup )
- {
- if ( down )
- {
- // released and re-pressed this frame
- val = 0.75;
- }
- else
- {
- // pressed and released this frame
- val = 0.25;
- }
- }
-
- // clear impulses
- key->state &= 1;
- return val;
-}
-
-/*
-================
-CL_AdjustAngles
-
-Moves the local angle positions
-================
-*/
-void CL_AdjustAngles ( float frametime, float *viewangles )
-{
- float speed;
- float up, down;
-
- if (in_speed.state & 1)
- {
- speed = frametime * cl_anglespeedkey->value;
- }
- else
- {
- speed = frametime;
- }
-
- if (!(in_strafe.state & 1))
- {
- viewangles[YAW] -= speed*cl_yawspeed->value*CL_KeyState (&in_right);
- viewangles[YAW] += speed*cl_yawspeed->value*CL_KeyState (&in_left);
- viewangles[YAW] = anglemod(viewangles[YAW]);
- }
- if (in_klook.state & 1)
- {
- V_StopPitchDrift ();
- viewangles[PITCH] -= speed*cl_pitchspeed->value * CL_KeyState (&in_forward);
- viewangles[PITCH] += speed*cl_pitchspeed->value * CL_KeyState (&in_back);
- }
-
- up = CL_KeyState (&in_lookup);
- down = CL_KeyState(&in_lookdown);
-
- viewangles[PITCH] -= speed*cl_pitchspeed->value * up;
- viewangles[PITCH] += speed*cl_pitchspeed->value * down;
-
- if (up || down)
- V_StopPitchDrift ();
-
- if (viewangles[PITCH] > cl_pitchdown->value)
- viewangles[PITCH] = cl_pitchdown->value;
- if (viewangles[PITCH] < -cl_pitchup->value)
- viewangles[PITCH] = -cl_pitchup->value;
-
- if (viewangles[ROLL] > 50)
- viewangles[ROLL] = 50;
- if (viewangles[ROLL] < -50)
- viewangles[ROLL] = -50;
-}
-
-/*
-================
-CL_CreateMove
-
-Send the intended movement message to the server
-if active == 1 then we are 1) not playing back demos ( where our commands are ignored ) and
-2 ) we have finished signing on to server
-================
-*/
-void CL_DLLEXPORT CL_CreateMove ( float frametime, struct usercmd_s *cmd, int active )
-{
- //RecClCL_CreateMove(frametime, cmd, active);
- //@linux Commander overview needs to be fixed!
- float spd;
- vec3_t viewangles;
- static vec3_t oldangles;
-
- if ( active && (!gViewPort || !gViewPort->IsOptionsMenuVisible()) /*&& !gHUD.GetShowingMap()*/)
- {
- int theButtonState = CL_ButtonBits(1);
- //memset( viewangles, 0, sizeof( vec3_t ) );
- //viewangles[ 0 ] = viewangles[ 1 ] = viewangles[ 2 ] = 0.0;
- //gEngfuncs.GetViewAngles( (float *)viewangles );
-
- //CL_AdjustAngles ( frametime, viewangles );
-
- memset (cmd, 0, sizeof(*cmd));
- //@ linux void IN_Move ( float frametime, usercmd_t *cmd)
- float theRotationDeltas[3] = {0,0,0}; //{90,0,90} --> top down --> viewangles[YAW]
- float theTranslationDeltas[3] = {0,0,0}; //--> cmd->sidemove
-
- IN_Move ( frametime, cmd );
-
- if(gResetViewAngles)
- {
- VectorCopy(gViewAngles,viewangles);
- gResetViewAngles = false;
- }
- else
- {
- gEngfuncs.GetViewAngles( (float *)viewangles );
- }
- VectorAdd(viewangles,theRotationDeltas,viewangles);
- CL_AdjustAngles ( frametime, viewangles );
-
- gEngfuncs.SetViewAngles( (float *)viewangles );
- VectorCopy (viewangles,gWorldViewAngles);
-
- // If we're in topdown mode
- bool theProcessedMove = false;
- bool theIsSendingSpecialEvent = false;
- bool theOverrideImpulse = false;
- float theWorldX, theWorldY;
- int theScriptImpulse = 0;
-
- AvHMessageID theAlienAbility = MESSAGE_NULL;
- AvHMessageID theGroupMessage = MESSAGE_NULL;
-
- //int theUpgradeVar = gEngfuncs.GetLocalPlayer()->curstate.iuser4;
- //bool theIsParalyzed = GetHasUpgrade(theUpgradeVar, PLAYER_PARALYZED);
- if(AvHScriptManager::Instance()->GetClientMove(theButtonState, theScriptImpulse))
- {
- if(theScriptImpulse)
- {
- theOverrideImpulse = true;
- }
- //theProcessedMove = true;
-
- // TODO: Pass theButtonState to override all CL_KeyState() calls
- }
- else if(gHUD.GetInTopDownMode())
- {
- cmd->upmove = cmd->sidemove = cmd->forwardmove = 0;
-
- // If a button was JUST pressed or released
- vec3_t theMouseNormPos;
- AvHMessageID theTechEvent = MESSAGE_NULL;
- if(gCommanderHandler.GetMoveToWorldPosition(theWorldX, theWorldY))
- {
- // Commander wants to scroll to an area of the mini-map
- cmd->impulse = COMMANDER_MOVETO;
- cmd->upmove = theWorldX/kWorldPosNetworkConstant;
- cmd->sidemove = theWorldY/kWorldPosNetworkConstant;
- gCommanderHandler.ClearMoveToPosition();
- gHUD.ClearTrackingEntity();
-
- theIsSendingSpecialEvent = true;
- theProcessedMove = true;
- }
- else if(gCommanderHandler.GetDefaultOrderPosition(theWorldX, theWorldY))
- {
- // Commander wants to scroll to an area of the mini-map
- cmd->impulse = COMMANDER_DEFAULTORDER;
- cmd->upmove = theWorldX/kWorldPosNetworkConstant;
- cmd->sidemove = theWorldY/kWorldPosNetworkConstant;
- gCommanderHandler.ClearDefaultOrderPosition();
- gHUD.ClearTrackingEntity();
-
- theIsSendingSpecialEvent = true;
- theProcessedMove = true;
- }
- else if(gHUD.GetAndClearTechEvent(theTechEvent))
- {
- cmd->impulse = theTechEvent;
- theProcessedMove = true;
- theIsSendingSpecialEvent = true;
- gHUD.ClearTrackingEntity();
-
- }
- // else scroll
- else
- {
- // Scroll the view if the HUD tells us to, otherwise use normal key presses
- int theScrollX = 0, theScrollY = 0, theScrollZ = 0;
- gHUD.GetAndClearTopDownScrollAmount(theScrollX, theScrollY, theScrollZ);
-
- if(theScrollX || theScrollY || theScrollZ)
- {
- // Commander move speed
- float kCommanderMoveSpeed = 1000;
- cmd->upmove += kCommanderMoveSpeed * theScrollY;
- cmd->sidemove += kCommanderMoveSpeed * theScrollX;
- cmd->forwardmove += kCommanderMoveSpeed * theScrollZ;
-
- cmd->impulse = COMMANDER_SCROLL;
- theOverrideImpulse = true;
-
- gHUD.ClearTrackingEntity();
-
- //theIsSendingSpecialEvent = true;
- theProcessedMove = true;
- }
- else if(gHUD.GetAndClearGroupEvent(theGroupMessage))
- {
- cmd->impulse = theGroupMessage;
- theIsSendingSpecialEvent = true;
- theProcessedMove = true;
-
- gHUD.SetLastHotkeySelectionEvent(theGroupMessage);
- }
-// else if(gHUD.GetTrackingEntity() > 0)
-// {
-// int theTrackingEntity = gHUD.GetTrackingEntity();
-// cmd->upmove = theTrackingEntity*kHotKeyNetworkFactor;
-// cmd->impulse = COMMANDER_TRACKENTITY;
-//
-// theIsSendingSpecialEvent = true;
-// theProcessedMove = true;
-// }
- else if(in_impulse != 0)
- {
- bool theProcessImpulse = false;
- switch(in_impulse)
- {
- case COMMANDER_SELECTALL:
- case COMMANDER_NEXTIDLE:
- case COMMANDER_NEXTAMMO:
- case COMMANDER_NEXTHEALTH:
- theProcessImpulse = true;
- break;
- }
-
- if(theProcessImpulse)
- {
- cmd->impulse = in_impulse;
- in_impulse = 0;
-
- theProcessedMove = true;
- theIsSendingSpecialEvent = true;
- }
- }
-
- if(!theProcessedMove && gHUD.GetAndClearSelectionEvent(theMouseNormPos, theTechEvent))
- {
- // Store world position x,y in upmove,sidemove
- cmd->upmove = theMouseNormPos.x*kSelectionNetworkConstant;
- cmd->sidemove = theMouseNormPos.y*kSelectionNetworkConstant;
- cmd->forwardmove = theMouseNormPos.z*kSelectionNetworkConstant;
-
- // Set impulse indicating this
- //cmd->impulse = COMMANDER_MOUSECOORD;
-
- // This could be COMMANDER_MOUSECOORD or BUILD_TURRET or one of the other BUILD_ events
- // They are all sent the same way
- cmd->impulse = theTechEvent;
-
- // Order mode isn't currently used but may be in the future
- //cmd->weaponselect = gHUD.GetOrderMode();
-
- // Set buttons. Attack gets turned off when we're in mouse mode (apparently)
- // so we need to set the buttons manually
- cmd->buttons = theButtonState;
- if(gHUD.GetMouseOneDown())
- {
- cmd->buttons |= IN_ATTACK;
- }
- if(gHUD.GetMouseTwoDown())
- {
- cmd->buttons |= IN_ATTACK2;
- }
-
- gHUD.ClearTrackingEntity();
-
- theIsSendingSpecialEvent = true;
- theProcessedMove = true;
- }
- }
- }
- else if(gHUD.GetAndClearAlienAbility(theAlienAbility))
- {
- cmd->impulse = theAlienAbility;
-
- // Added by mmcguire.
- // 255 signifies that the impulse came from us and not from the console.
- cmd->weaponselect = 255;
-
- theProcessedMove = true;
- theIsSendingSpecialEvent = true;
-
- }
-
- // else process move normally
- if(!theProcessedMove)
- {
- if ( in_strafe.state & 1 )
- {
- cmd->sidemove += cl_sidespeed->value * CL_KeyState (&in_right);
- cmd->sidemove -= cl_sidespeed->value * CL_KeyState (&in_left);
- }
-
- cmd->sidemove += cl_sidespeed->value * CL_KeyState (&in_moveright);
- cmd->sidemove -= cl_sidespeed->value * CL_KeyState (&in_moveleft);
-
- cmd->upmove += cl_upspeed->value * CL_KeyState (&in_up);
- cmd->upmove -= cl_upspeed->value * CL_KeyState (&in_down);
-
- if ( !(in_klook.state & 1 ) )
- {
- cmd->forwardmove += cl_forwardspeed->value * CL_KeyState (&in_forward);
- cmd->forwardmove -= cl_backspeed->value * CL_KeyState (&in_back);
- }
- }
-
- if(!theIsSendingSpecialEvent)
- {
- // adjust for speed key
- if ( in_speed.state & 1 )
- {
- cmd->forwardmove *= cl_movespeedkey->value;
- cmd->sidemove *= cl_movespeedkey->value;
- cmd->upmove *= cl_movespeedkey->value;
- }
-
- // clip to maxspeed
- spd = gEngfuncs.GetClientMaxspeed();
-
- if ( spd != 0.0 )
- {
- // scale the 3 speeds so that the total velocity is not > cl.maxspeed
- float fmov = sqrt( (cmd->forwardmove*cmd->forwardmove) + (cmd->sidemove*cmd->sidemove) + (cmd->upmove*cmd->upmove) );
-
- if ( fmov > spd )
- {
- float fratio = spd / fmov;
- cmd->forwardmove *= fratio;
- cmd->sidemove *= fratio;
- cmd->upmove *= fratio;
- }
- }
-
- // Allow mice and other controllers to add their inputs
- IN_Move ( frametime, cmd );
-
- if(!theOverrideImpulse)
- {
- cmd->impulse = in_impulse;
- in_impulse = 0;
- }
-
- cmd->weaponselect = g_weaponselect;
- g_weaponselect = 0;
-
- //
- // set button and flag bits
- //
- cmd->buttons = theButtonState;
-
- // If they're in a modal dialog, or we're stunned, ignore the attack button.
- int theLocalUpgrades = gHUD.GetLocalUpgrades();
- if( GetClientVoiceMgr()->IsInSquelchMode() )
- {
- cmd->buttons &= ~IN_ATTACK;
- }
-
- // Using joystick?
- if ( in_joystick->value )
- {
- if ( cmd->forwardmove > 0 )
- {
- cmd->buttons |= IN_FORWARD;
- }
- else if ( cmd->forwardmove < 0 )
- {
- cmd->buttons |= IN_BACK;
- }
- }
- }
- }
-
- gEngfuncs.GetViewAngles( (float *)viewangles );
- // Set current view angles.
-
- // Set current view angles but not if frozen (this still allows you to rotate in first-person, but player model won't change)
- int theUser4 = gHUD.GetLocalUpgrades();
- bool theIsFrozen = GetHasUpgrade(theUser4, MASK_PLAYER_STUNNED) || GetHasUpgrade(theUser4, MASK_ALIEN_EMBRYO);
-
- if ( g_iAlive && !theIsFrozen)
- {
- VectorCopy( viewangles, cmd->viewangles );
- VectorCopy( viewangles, oldangles );
- }
- else
- {
- VectorCopy( oldangles, cmd->viewangles );
- }
-
- //Bench_SetViewAngles( 1, (float *)&cmd->viewangles, frametime, cmd );
-}
-
-/*
-============
-CL_IsDead
-
-Returns 1 if health is <= 0
-============
-*/
-int CL_IsDead( void )
-{
- return ( gHUD.m_Health.m_iHealth <= 0 ) ? 1 : 0;
-}
-
-/*
-============
-CL_ButtonBits
-
-Returns appropriate button info for keyboard and mouse state
-Set bResetState to 1 to clear old state info
-============
-*/
-int CL_ButtonBits( int bResetState )
-{
- int bits = 0;
-
- if ( in_attack.state & 3 )
- {
- bits |= IN_ATTACK;
- }
-
- if ( in_speed.state & 3 )
- {
- bits |= IN_WALK;
- }
-
- // : duck toggle
- if ( g_bDuckToggled )
- {
- if (!(in_duck.state & 3))
- {
- bits |= IN_DUCK;
- }
- }
- else if (in_duck.state & 3)
- {
- bits |= IN_DUCK;
- }
- // :
-
- if (in_jump.state & 3)
- {
- bits |= IN_JUMP;
- }
-
- if ( in_forward.state & 3 )
- {
- bits |= IN_FORWARD;
- }
-
- if (in_back.state & 3)
- {
- bits |= IN_BACK;
- }
-
- if (in_use.state & 3)
- {
- bits |= IN_USE;
- }
-
- if (in_cancel)
- {
- bits |= IN_CANCEL;
- }
-
- if ( in_left.state & 3 )
- {
- bits |= IN_LEFT;
- }
-
- if (in_right.state & 3)
- {
- bits |= IN_RIGHT;
- }
-
- if ( in_moveleft.state & 3 )
- {
- bits |= IN_MOVELEFT;
- }
-
- if (in_moveright.state & 3)
- {
- bits |= IN_MOVERIGHT;
- }
-
- if (in_attack2.state & 3)
- {
- bits |= IN_ATTACK2;
- }
-
- if (in_reload.state & 3)
- {
- bits |= IN_RELOAD;
- }
-
- if (in_alt1.state & 3)
- {
- bits |= IN_ALT1;
- }
-
- if ( in_score.state & 3 )
- {
- bits |= IN_SCORE;
- }
-
- // Dead or in intermission? Shore scoreboard, too
- if ( CL_IsDead() || gHUD.m_iIntermission )
- {
- bits |= IN_SCORE;
- }
-
- if ( bResetState )
- {
- in_attack.state &= ~2;
- in_speed.state &= ~2;
- in_duck.state &= ~2;
- in_jump.state &= ~2;
- in_forward.state &= ~2;
- in_back.state &= ~2;
- in_use.state &= ~2;
- in_left.state &= ~2;
- in_right.state &= ~2;
- in_moveleft.state &= ~2;
- in_moveright.state &= ~2;
- in_attack2.state &= ~2;
- in_reload.state &= ~2;
- in_alt1.state &= ~2;
- in_score.state &= ~2;
- }
-
- return bits;
-}
-
-/*
-============
-CL_ResetButtonBits
-
-============
-*/
-void CL_ResetButtonBits( int bits )
-{
- int bitsNew = CL_ButtonBits( 0 ) ^ bits;
-
- // Has the attack button been changed
- if ( bitsNew & IN_ATTACK )
- {
- // Was it pressed? or let go?
- if ( bits & IN_ATTACK )
- {
- KeyDown( &in_attack );
- }
- else
- {
- // totally clear state
- in_attack.state &= ~7;
- in_attack2.state &= ~7;
- }
- }
-}
-
-/*
-============
-InitInput
-============
-*/
-void InitInput (void)
-{
- gEngfuncs.pfnAddCommand ("+moveup",IN_UpDown);
- gEngfuncs.pfnAddCommand ("-moveup",IN_UpUp);
- gEngfuncs.pfnAddCommand ("+movedown",IN_DownDown);
- gEngfuncs.pfnAddCommand ("-movedown",IN_DownUp);
- gEngfuncs.pfnAddCommand ("+left",IN_LeftDown);
- gEngfuncs.pfnAddCommand ("-left",IN_LeftUp);
- gEngfuncs.pfnAddCommand ("+right",IN_RightDown);
- gEngfuncs.pfnAddCommand ("-right",IN_RightUp);
- gEngfuncs.pfnAddCommand ("+forward",IN_ForwardDown);
- gEngfuncs.pfnAddCommand ("-forward",IN_ForwardUp);
- gEngfuncs.pfnAddCommand ("+back",IN_BackDown);
- gEngfuncs.pfnAddCommand ("-back",IN_BackUp);
- gEngfuncs.pfnAddCommand ("+lookup", IN_LookupDown);
- gEngfuncs.pfnAddCommand ("-lookup", IN_LookupUp);
- gEngfuncs.pfnAddCommand ("+lookdown", IN_LookdownDown);
- gEngfuncs.pfnAddCommand ("-lookdown", IN_LookdownUp);
- gEngfuncs.pfnAddCommand ("+strafe", IN_StrafeDown);
- gEngfuncs.pfnAddCommand ("-strafe", IN_StrafeUp);
- gEngfuncs.pfnAddCommand ("+moveleft", IN_MoveleftDown);
- gEngfuncs.pfnAddCommand ("-moveleft", IN_MoveleftUp);
- gEngfuncs.pfnAddCommand ("+moveright", IN_MoverightDown);
- gEngfuncs.pfnAddCommand ("-moveright", IN_MoverightUp);
- gEngfuncs.pfnAddCommand ("+speed", IN_SpeedDown);
- gEngfuncs.pfnAddCommand ("-speed", IN_SpeedUp);
- gEngfuncs.pfnAddCommand ("+attack", IN_AttackDown);
- gEngfuncs.pfnAddCommand ("-attack", IN_AttackUp);
- //gEngfuncs.pfnAddCommand ("+movement", IN_Attack2Down);
- //gEngfuncs.pfnAddCommand ("-movement", IN_Attack2Up);
- gEngfuncs.pfnAddCommand ("+use", IN_UseDown);
- gEngfuncs.pfnAddCommand ("-use", IN_UseUp);
- gEngfuncs.pfnAddCommand ("+jump", IN_JumpDown);
- gEngfuncs.pfnAddCommand ("-jump", IN_JumpUp);
- gEngfuncs.pfnAddCommand ("impulse", IN_Impulse);
- gEngfuncs.pfnAddCommand ("+klook", IN_KLookDown);
- gEngfuncs.pfnAddCommand ("-klook", IN_KLookUp);
- gEngfuncs.pfnAddCommand ("+mlook", IN_MLookDown);
- gEngfuncs.pfnAddCommand ("-mlook", IN_MLookUp);
- gEngfuncs.pfnAddCommand ("+jlook", IN_JLookDown);
- gEngfuncs.pfnAddCommand ("-jlook", IN_JLookUp);
- gEngfuncs.pfnAddCommand ("+duck", IN_DuckDown);
- gEngfuncs.pfnAddCommand ("-duck", IN_DuckUp);
- // : duck toggle
- gEngfuncs.pfnAddCommand ("toggleduck", IN_DuckToggle);
- // :
- gEngfuncs.pfnAddCommand ("+reload", IN_ReloadDown);
- gEngfuncs.pfnAddCommand ("-reload", IN_ReloadUp);
- gEngfuncs.pfnAddCommand ("+alt1", IN_Alt1Down);
- gEngfuncs.pfnAddCommand ("-alt1", IN_Alt1Up);
- gEngfuncs.pfnAddCommand ("+score", IN_ScoreDown);
- gEngfuncs.pfnAddCommand ("-score", IN_ScoreUp);
- gEngfuncs.pfnAddCommand ("+showscores", IN_ScoreDown);
- gEngfuncs.pfnAddCommand ("-showscores", IN_ScoreUp);
- gEngfuncs.pfnAddCommand ("+graph", IN_GraphDown);
- gEngfuncs.pfnAddCommand ("-graph", IN_GraphUp);
- gEngfuncs.pfnAddCommand ("+break",IN_BreakDown);
- gEngfuncs.pfnAddCommand ("-break",IN_BreakUp);
-
- lookstrafe = gEngfuncs.pfnRegisterVariable ( "lookstrafe", "0", FCVAR_ARCHIVE );
- lookspring = gEngfuncs.pfnRegisterVariable ( "lookspring", "0", FCVAR_ARCHIVE );
- cl_anglespeedkey = gEngfuncs.pfnRegisterVariable ( "cl_anglespeedkey", "0.67", 0 );
- cl_yawspeed = gEngfuncs.pfnRegisterVariable ( "cl_yawspeed", "210", 0 );
- cl_pitchspeed = gEngfuncs.pfnRegisterVariable ( "cl_pitchspeed", "225", 0 );
- cl_upspeed = gEngfuncs.pfnRegisterVariable ( "cl_upspeed", "320", 0 );
- cl_forwardspeed = gEngfuncs.pfnRegisterVariable ( "cl_forwardspeed", "400", FCVAR_ARCHIVE );
- cl_backspeed = gEngfuncs.pfnRegisterVariable ( "cl_backspeed", "400", FCVAR_ARCHIVE );
- cl_sidespeed = gEngfuncs.pfnRegisterVariable ( "cl_sidespeed", "400", 0 );
- cl_movespeedkey = gEngfuncs.pfnRegisterVariable ( "cl_movespeedkey", "0.3", 0 );
- cl_pitchup = gEngfuncs.pfnRegisterVariable ( "cl_pitchup", "89", 0 );
- cl_pitchdown = gEngfuncs.pfnRegisterVariable ( "cl_pitchdown", "89", 0 );
-
- cl_vsmoothing = gEngfuncs.pfnRegisterVariable ( "cl_vsmoothing", "0.05", FCVAR_ARCHIVE );
-
- m_pitch = gEngfuncs.pfnRegisterVariable ( "m_pitch","0.022", FCVAR_ARCHIVE );
- m_yaw = gEngfuncs.pfnRegisterVariable ( "m_yaw","0.022", FCVAR_ARCHIVE );
- m_forward = gEngfuncs.pfnRegisterVariable ( "m_forward","1", FCVAR_ARCHIVE );
- m_side = gEngfuncs.pfnRegisterVariable ( "m_side","0.8", FCVAR_ARCHIVE );
-
- cl_autohelp = gEngfuncs.pfnRegisterVariable ( kvAutoHelp, "1.0", FCVAR_ARCHIVE );
- cl_centerentityid = gEngfuncs.pfnRegisterVariable ( kvCenterEntityID, "0.0", FCVAR_ARCHIVE );
- cl_musicenabled = gEngfuncs.pfnRegisterVariable ( kvMusicEnabled, "1.0", FCVAR_ARCHIVE );
- cl_musicvolume = gEngfuncs.pfnRegisterVariable ( kvMusicVolume, "155", FCVAR_ARCHIVE );
- cl_musicdir = gEngfuncs.pfnRegisterVariable ( kvMusicDirectory, "", FCVAR_ARCHIVE);
- cl_musicdelay = gEngfuncs.pfnRegisterVariable ( kvMusicDelay, "90", FCVAR_ARCHIVE);
- cl_forcedefaultfov = gEngfuncs.pfnRegisterVariable ( kvForceDefaultFOV, "0", FCVAR_ARCHIVE );
- cl_dynamiclights = gEngfuncs.pfnRegisterVariable ( kvDynamicLights, "1", FCVAR_ARCHIVE );
- cl_buildmessages = gEngfuncs.pfnRegisterVariable ( kvBuildMessages, "1", FCVAR_ARCHIVE);
- cl_quickselecttime = gEngfuncs.pfnRegisterVariable ( kvQuickSelectTime, ".15", FCVAR_ARCHIVE );
- cl_highdetail = gEngfuncs.pfnRegisterVariable ( kvHighDetail, "1", FCVAR_ARCHIVE );
- cl_cmhotkeys = gEngfuncs.pfnRegisterVariable ( kvCMHotkeys, "qwerasdfzxcv", FCVAR_ARCHIVE );
- cl_forcedefaultfov = gEngfuncs.pfnRegisterVariable ( kvForceDefaultFOV, "0", FCVAR_ARCHIVE );
- cl_particleinfo = gEngfuncs.pfnRegisterVariable ( kvParticleInfo, "0", FCVAR_ARCHIVE );
-
- // Initialize third person camera controls.
- CAM_Init();
- // Initialize inputs
- IN_Init();
- // Initialize keyboard
- KB_Init();
- // Initialize view system
- V_Init();
-}
-
-/*
-============
-ShutdownInput
-============
-*/
-void ShutdownInput (void)
-{
- IN_Shutdown();
- KB_Shutdown();
-}
-#include "interface.h"
-void CL_DLLEXPORT HUD_Shutdown( void )
-{
-// RecClShutdown();
-
- ShutdownInput();
-
- gHUD.Shutdown();
-}
+//======== (C) Copyright 2002 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:
+//
+// $Workfile: input.cpp $
+// $Date: 2002/10/16 02:12:21 $
+//
+//-------------------------------------------------------------------------------
+// $Log: input.cpp,v $
+// Revision 1.28 2002/10/16 02:12:21 Flayra
+// - Valve anti-cheat integrated!
+//
+// Revision 1.27 2002/08/09 00:13:04 Flayra
+// - Removed explicitly allowing specific commands. I can't remember why this was needed, but it doesn't appear to be anymore.
+//
+// Revision 1.26 2002/08/02 21:39:03 Flayra
+// - Refactored variable names
+//
+// Revision 1.25 2002/07/08 16:13:31 Flayra
+// - Fixed bug where command was able to switch weapons via mousewheel (bug #239)
+//
+//===============================================================================
+// cl.input.c -- builds an intended movement command to send to the server
+
+//xxxxxx Move bob and pitch drifting code here and other stuff from view if needed
+
+// Quake is a trademark of Id Software, Inc., (c) 1996 Id Software, Inc. All
+// rights reserved.
+#include "hud.h"
+#include "cl_util.h"
+#include "camera.h"
+extern "C"
+{
+#include "kbutton.h"
+}
+#include "cvardef.h"
+#include "usercmd.h"
+#include "const.h"
+#include "camera.h"
+#include "in_defs.h"
+#include "view.h"
+#include "bench.h"
+#include
+#include
+#include "engine/keydefs.h"
+#include "Exports.h"
+
+#include "vgui_TeamFortressViewport.h"
+#include "mod/AvHServerVariables.h"// should we go ahead and just make a SharedVariables.h instead?
+#include "mod/AvHClientVariables.h"
+#include "mod/AvHMessage.h"
+#include "winsani_in.h"
+#include "fmod.h"
+#include "winsani_out.h"
+#include "mod/AvHScriptManager.h"
+#include "mod/AvHScrollHandler.h"
+#include "mod/AvHCommanderModeHandler.h"
+#include "util/Mat3.h"
+
+#include "engine/APIProxy.h"
+#include "Exports.h"
+
+// : duck toggle
+extern bool g_bDuckToggled;
+// :
+
+extern int g_iAlive;
+
+extern int g_weaponselect;
+extern cl_enginefunc_t gEngfuncs;
+bool gResetViewAngles = false;
+vec3_t gViewAngles;
+extern AvHCommanderModeHandler gCommanderHandler;
+
+///////////////////////////////
+// Begin Max's Code
+///////////////////////////////
+
+float gPlayerAngles[3] = { 0, 0, 0 };
+float gTargetPlayerAngles[3] = { 0, 0, 0 };
+float gWorldViewAngles[3] = { 0, 0, 0 };
+
+///////////////////////////////
+// End Max's Code
+///////////////////////////////
+
+// Defined in pm_math.c
+//extern "C" float anglemod( float a );
+float anglemod( float a );
+
+void IN_Init (void);
+void IN_Move ( float frametime, usercmd_t *cmd);
+void IN_Shutdown( void );
+void V_Init( void );
+void VectorAngles( const float *forward, float *angles );
+int CL_ButtonBits( int );
+
+// xxx need client dll function to get and clear impuse
+extern cvar_t *in_joystick;
+
+int in_impulse = 0;
+int in_cancel = 0;
+
+cvar_t *m_pitch;
+cvar_t *m_yaw;
+cvar_t *m_forward;
+cvar_t *m_side;
+
+cvar_t *lookstrafe;
+cvar_t *lookspring;
+cvar_t *cl_pitchup;
+cvar_t *cl_pitchdown;
+cvar_t *cl_upspeed;
+cvar_t *cl_forwardspeed;
+cvar_t *cl_backspeed;
+cvar_t *cl_sidespeed;
+cvar_t *cl_movespeedkey;
+cvar_t *cl_yawspeed;
+cvar_t *cl_pitchspeed;
+cvar_t *cl_anglespeedkey;
+cvar_t *cl_vsmoothing;
+cvar_t *cl_autohelp;
+cvar_t *cl_centerentityid;
+cvar_t *cl_musicenabled;
+cvar_t *cl_musicdelay;
+cvar_t *cl_musicvolume;
+cvar_t *cl_musicdir;
+cvar_t *cl_quickselecttime;
+cvar_t *cl_highdetail;
+cvar_t *cl_cmhotkeys;
+cvar_t *cl_forcedefaultfov;
+cvar_t *cl_dynamiclights;
+cvar_t *cl_buildmessages;
+cvar_t *cl_particleinfo;
+
+/*
+===============================================================================
+
+KEY BUTTONS
+
+Continuous button event tracking is complicated by the fact that two different
+input sources (say, mouse button 1 and the control key) can both press the
+same button, but the button should only be released when both of the
+pressing key have been released.
+
+When a key event issues a button command (+forward, +attack, etc), it appends
+its key number as a parameter to the command so it can be matched up with
+the release.
+
+state bit 0 is the current state of the key
+state bit 1 is edge triggered on the up to down transition
+state bit 2 is edge triggered on the down to up transition
+
+===============================================================================
+*/
+
+
+kbutton_t in_mlook;
+kbutton_t in_klook;
+kbutton_t in_jlook;
+kbutton_t in_left;
+kbutton_t in_right;
+kbutton_t in_forward;
+kbutton_t in_back;
+kbutton_t in_lookup;
+kbutton_t in_lookdown;
+kbutton_t in_moveleft;
+kbutton_t in_moveright;
+kbutton_t in_strafe;
+kbutton_t in_speed;
+kbutton_t in_use;
+kbutton_t in_jump;
+kbutton_t in_attack;
+kbutton_t in_attack2;
+kbutton_t in_up;
+kbutton_t in_down;
+kbutton_t in_duck;
+kbutton_t in_reload;
+kbutton_t in_alt1;
+kbutton_t in_score;
+kbutton_t in_break;
+kbutton_t in_graph; // Display the netgraph
+
+typedef struct kblist_s
+{
+ struct kblist_s *next;
+ kbutton_t *pkey;
+ char name[32];
+} kblist_t;
+
+kblist_t *g_kbkeys = NULL;
+
+vector< pair > g_PrevCmds;
+
+/*
+============
+KB_ConvertString
+
+Removes references to +use and replaces them with the keyname in the output string. If
+ a binding is unfound, then the original text is retained.
+NOTE: Only works for text with +word in it.
+============
+*/
+int KB_ConvertString( char *in, char **ppout )
+{
+ char sz[ 4096 ];
+ char binding[ 64 ];
+ char *p;
+ char *pOut;
+ char *pEnd;
+ const char *pBinding;
+
+ if ( !ppout )
+ return 0;
+
+ *ppout = NULL;
+ p = in;
+ pOut = sz;
+ while ( *p )
+ {
+ if ( *p == '+' )
+ {
+ pEnd = binding;
+ while ( *p && ( isalnum( *p ) || ( pEnd == binding ) ) && ( ( pEnd - binding ) < 63 ) )
+ {
+ *pEnd++ = *p++;
+ }
+
+ *pEnd = '\0';
+
+ pBinding = NULL;
+ if ( strlen( binding + 1 ) > 0 )
+ {
+ // See if there is a binding for binding?
+ pBinding = gEngfuncs.Key_LookupBinding( binding + 1 );
+ }
+
+ if ( pBinding )
+ {
+ *pOut++ = '[';
+ pEnd = (char *)pBinding;
+ }
+ else
+ {
+ pEnd = binding;
+ }
+
+ while ( *pEnd )
+ {
+ *pOut++ = *pEnd++;
+ }
+
+ if ( pBinding )
+ {
+ *pOut++ = ']';
+ }
+ }
+ else
+ {
+ *pOut++ = *p++;
+ }
+ }
+
+ *pOut = '\0';
+
+ pOut = ( char * )malloc( strlen( sz ) + 1 );
+ strcpy( pOut, sz );
+ *ppout = pOut;
+
+ return 1;
+}
+
+/*
+============
+KB_Find
+
+Allows the engine to get a kbutton_t directly ( so it can check +mlook state, etc ) for saving out to .cfg files
+============
+*/
+struct kbutton_s CL_DLLEXPORT *KB_Find( const char *name )
+{
+// RecClFindKey(name);
+
+ kblist_t *p;
+ p = g_kbkeys;
+ while ( p )
+ {
+ if ( !stricmp( name, p->name ) )
+ return p->pkey;
+
+ p = p->next;
+ }
+ return NULL;
+}
+
+/*
+============
+KB_Add
+
+Add a kbutton_t * to the list of pointers the engine can retrieve via KB_Find
+============
+*/
+void KB_Add( const char *name, kbutton_t *pkb )
+{
+ kblist_t *p;
+ kbutton_t *kb;
+
+ kb = KB_Find( name );
+
+ if ( kb )
+ return;
+
+ p = ( kblist_t * )malloc( sizeof( kblist_t ) );
+ memset( p, 0, sizeof( *p ) );
+
+ strcpy( p->name, name );
+ p->pkey = pkb;
+
+ p->next = g_kbkeys;
+ g_kbkeys = p;
+}
+
+/*
+============
+KB_Init
+
+Add kbutton_t definitions that the engine can query if needed
+============
+*/
+void KB_Init( void )
+{
+ g_kbkeys = NULL;
+
+ KB_Add( "in_graph", &in_graph );
+ KB_Add( "in_mlook", &in_mlook );
+ KB_Add( "in_jlook", &in_jlook );
+}
+
+/*
+============
+KB_Shutdown
+
+Clear kblist
+============
+*/
+void KB_Shutdown( void )
+{
+ kblist_t *p, *n;
+ p = g_kbkeys;
+ while ( p )
+ {
+ n = p->next;
+ free( p );
+ p = n;
+ }
+ g_kbkeys = NULL;
+}
+
+/*
+============
+KeyDown
+============
+*/
+void KeyDown (kbutton_t *b)
+{
+ int k;
+ char *c;
+
+ c = gEngfuncs.Cmd_Argv(1);
+ if (c[0])
+ k = atoi(c);
+ else
+ k = -1; // typed manually at the console for continuous down
+
+ int theBlockScripts = (int)gHUD.GetServerVariableFloat(kvBlockScripts);
+
+ char *pCmd = gEngfuncs.Cmd_Argv(0);
+
+ if(theBlockScripts && pCmd)
+ {
+ bool bFound = false;
+
+ //Check thier last few commands (this prevents false positives if a player is hits several keys real fast)
+ for (int i = 0; i < g_PrevCmds.size(); i++)
+ {
+ //Check both the key pressed and the command it executed.
+ if(k == g_PrevCmds[i].first && !strcmp(pCmd, g_PrevCmds[i].second.c_str()))
+ {
+ bFound = true;
+ break;
+ }
+ }
+
+
+ if(!bFound
+ && strcmp(pCmd, "+mlook")
+ && strcmp(pCmd, "+jlook")
+ && strcmp(pCmd, "+showscores")
+ && strcmp(pCmd, "+use"))
+ {
+ gEngfuncs.pfnCenterPrint("Scripting is not allowed on this server.");
+ b->down[0] = b->down[1] = 0;
+ b->state = 4; // impulse up
+ return;
+ }
+ }
+
+ if (k == b->down[0] || k == b->down[1])
+ return; // repeating key
+
+ if (!b->down[0])
+ b->down[0] = k;
+ else if (!b->down[1])
+ b->down[1] = k;
+ else
+ {
+ gEngfuncs.Con_DPrintf ("Three keys down for a button '%c' '%c' '%c'!\n", b->down[0], b->down[1], c);
+ return;
+ }
+
+ if (b->state & 1)
+ return; // still down
+ b->state |= 1 + 2; // down + impulse down
+}
+
+/*
+============
+KeyDownForced
+============
+*/
+void KeyDownForced (kbutton_t *b)
+{
+ b->down[0] = 0;
+ b->down[1] = 0;
+
+ if (b->state & 1)
+ return; // still down
+ b->state |= 1 + 2; // down + impulse down
+}
+
+/*
+============
+KeyUp
+============
+*/
+void KeyUp (kbutton_t *b)
+{
+ int k;
+ char *c;
+
+ c = gEngfuncs.Cmd_Argv(1);
+ if (c[0])
+ k = atoi(c);
+ else
+ { // typed manually at the console, assume for unsticking, so clear all
+ b->down[0] = b->down[1] = 0;
+ b->state = 4; // impulse up
+ return;
+ }
+
+ if (b->down[0] == k)
+ b->down[0] = 0;
+ else if (b->down[1] == k)
+ b->down[1] = 0;
+ else
+ return; // key up without coresponding down (menu pass through)
+ if (b->down[0] || b->down[1])
+ {
+ //Con_Printf ("Keys down for button: '%c' '%c' '%c' (%d,%d,%d)!\n", b->down[0], b->down[1], c, b->down[0], b->down[1], c);
+ return; // some other key is still holding it down
+ }
+
+ if (!(b->state & 1))
+ return; // still up (this should not happen)
+
+ b->state &= ~1; // now up
+ b->state |= 4; // impulse up
+}
+
+/*
+============
+KeyUpForced
+============
+*/
+void KeyUpForced (kbutton_t *b)
+{
+ b->state &= ~1; // now up
+ b->state |= 4; // impulse up
+}
+
+bool AvHContainsBlockedCommands(const char* inInput)
+{
+ if (inInput == NULL)
+ {
+ return false;
+ }
+
+ const char* kBlockedCommand[] =
+ {
+ "exec",
+ "wait",
+ "special",
+ "_special"
+ };
+
+ // Check for a ; indicating multiple commands.
+
+ if (strchr(inInput, ';') != NULL)
+ {
+ return true;
+ }
+
+ // Check if any of the blocked commands are being used.
+
+ const char* theCommandEnd = strpbrk(inInput, " \t");
+
+ int theCommandLength;
+
+ if (theCommandEnd == NULL)
+ {
+ theCommandLength = (int)strlen(inInput);
+ }
+ else
+ {
+ theCommandLength = theCommandEnd - inInput;
+ }
+
+ for (int i = 0; i < sizeof(kBlockedCommand) / sizeof(const char*); ++i)
+ {
+ if ((int)strlen(kBlockedCommand[i]) == theCommandLength &&
+ strncmp(inInput, kBlockedCommand[i], theCommandLength) == 0)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+/*
+============
+HUD_Key_Event
+
+Return 1 to allow engine to process the key, otherwise, act on it as needed
+============
+*/
+int CL_DLLEXPORT HUD_Key_Event( int down, int keynum, const char *pszCurrentBinding )
+{
+// RecClKeyEvent(down, keynum, pszCurrentBinding);
+
+ // Check to see if the event has any outlawed commands in it.
+ float theBlockScripts = gHUD.GetServerVariableFloat(kvBlockScripts);
+
+ if (theBlockScripts && AvHContainsBlockedCommands(pszCurrentBinding))
+ {
+ if(down)//: only show when going down.
+ gEngfuncs.pfnCenterPrint("Scripting is not allowed on this server.\n");
+ return 0;
+ }
+
+ if(pszCurrentBinding)
+ {
+ if(g_PrevCmds.size() >= 5)
+ g_PrevCmds.erase(g_PrevCmds.begin());//remove the oldest command
+
+ g_PrevCmds.push_back(make_pair(keynum, (string)pszCurrentBinding));
+ }
+
+ int theProcessKeyBinding = 1;
+
+// char theKeyBinding[256] = "none";
+// if(pszCurrentBinding)
+// {
+// sprintf(theKeyBinding, pszCurrentBinding);
+// }
+//
+// char theMessage[512];
+// sprintf(theMessage, "%s (down: %d, keynum %d)", theKeyBinding, down, keynum);
+// CenterPrint(theMessage);
+
+ if(gViewPort /*&& gViewPort->IsOptionsMenuVisible()*/)
+ {
+
+ theProcessKeyBinding = gViewPort->KeyInput(down, keynum, pszCurrentBinding);
+
+ if(pszCurrentBinding && (!strcmp(pszCurrentBinding, "toggleconsole") || !strcmp(pszCurrentBinding, "cancelselect")))
+ {
+ theProcessKeyBinding = 1;
+ }
+ }
+
+
+ // Process topdown commands with precedence first
+ if(theProcessKeyBinding && gHUD.GetInTopDownMode())
+ {
+ if((keynum != 0) && down/*&& pszCurrentBinding*/)
+ {
+ AvHMessageID theMessageID = gHUD.HotKeyHit(keynum);
+ if((theMessageID != MESSAGE_NULL) || (keynum == K_ESCAPE))
+ {
+ // If ESC or cancel was hit, cancel ghost building
+ if((keynum == K_ESCAPE) || (theMessageID == MESSAGE_CANCEL))
+ {
+ gHUD.SetGhostBuildingMode(MESSAGE_NULL);
+ }
+
+ theProcessKeyBinding = 0;
+ }
+ }
+ }
+
+ if(theProcessKeyBinding)
+ {
+ // Process only a couple keybindings in top down mode
+// if(!gHUD.GetInTopDownMode() || (pszCurrentBinding &&
+//
+// // Misc. commands
+// (!strcmp(pszCurrentBinding, "toggleconsole") || !strcmp(pszCurrentBinding, "cancelselect") || !strcmp(pszCurrentBinding, "+showscores") || !strcmp(pszCurrentBinding, "-showscores") || !strcmp(pszCurrentBinding, "messagemode") || !strcmp(pszCurrentBinding, "messagemode2") || !strcmp(pszCurrentBinding, "snapshot") || !strcmp(pszCurrentBinding, "screenshot") || !strcmp(pszCurrentBinding, "+jump") || !strcmp(pszCurrentBinding, "addbot") || !strcmp(pszCurrentBinding, "+voicerecord") || !strcmp(pszCurrentBinding, "-voicerecord") ||
+//
+// // Movement commands
+// !strcmp(pszCurrentBinding, "testevent") /*|| !strcmp(pszCurrentBinding, "invnext") || !strcmp(pszCurrentBinding, "invprev")*/ || !strcmp(pszCurrentBinding, "+moveleft") || !strcmp(pszCurrentBinding, "-moveleft") || !strcmp(pszCurrentBinding, "+moveright") || !strcmp(pszCurrentBinding, "-moveright") || !strcmp(pszCurrentBinding, "+moveup") || !strcmp(pszCurrentBinding, "-moveup") || !strcmp(pszCurrentBinding, "+movedown") || !strcmp(pszCurrentBinding, "-movedown") ||
+//
+// // For selecting groups
+// !strcmp(pszCurrentBinding, "slot1") || !strcmp(pszCurrentBinding, "slot2") || !strcmp(pszCurrentBinding, "slot3") || !strcmp(pszCurrentBinding, "slot4") || !strcmp(pszCurrentBinding, "slot5") ||
+//
+// // For creating groups
+// !strcmp(pszCurrentBinding, "+duck") || !strcmp(pszCurrentBinding, "-duck") ||
+//
+// // For testing ease
+// !strcmp(pszCurrentBinding, "givepoints")
+//
+// )))
+// {
+ if (gViewPort)
+ theProcessKeyBinding = gViewPort->KeyInput(down, keynum, pszCurrentBinding);
+
+// // Don't
+// if(!strcmp(pszCurrentBinding, "+jump") && gHUD.GetInTopDownMode())
+// {
+// gHUD.GotoAlert();
+// }
+
+// }
+ }
+
+ return theProcessKeyBinding;
+}
+
+void IN_BreakDown( void ) { KeyDown( &in_break );};
+void IN_BreakUp( void ) { KeyUp( &in_break ); };
+void IN_KLookDown (void) {KeyDown(&in_klook);}
+void IN_KLookUp (void) {KeyUp(&in_klook);}
+void IN_JLookDown (void) {KeyDown(&in_jlook);}
+void IN_JLookUp (void) {KeyUp(&in_jlook);}
+void IN_MLookDown (void) {KeyDown(&in_mlook);}
+void IN_UpDown(void) {KeyDown(&in_up);}
+void IN_UpUp(void) {KeyUp(&in_up);}
+void IN_DownDown(void) {KeyDown(&in_down);}
+void IN_DownUp(void) {KeyUp(&in_down);}
+void IN_LeftDown(void) {KeyDown(&in_left);}
+void IN_LeftUp(void) {KeyUp(&in_left);}
+void IN_RightDown(void) {KeyDown(&in_right);}
+void IN_RightUp(void) {KeyUp(&in_right);}
+
+void IN_ForwardDown(void)
+{
+ KeyDown(&in_forward);
+ gHUD.m_Spectator.HandleButtonsDown( IN_FORWARD );
+}
+
+void IN_ForwardUp(void)
+{
+ KeyUp(&in_forward);
+ gHUD.m_Spectator.HandleButtonsUp( IN_FORWARD );
+}
+
+void IN_BackDown(void)
+{
+ KeyDown(&in_back);
+ gHUD.m_Spectator.HandleButtonsDown( IN_BACK );
+}
+
+void IN_BackUp(void)
+{
+ KeyUp(&in_back);
+ gHUD.m_Spectator.HandleButtonsUp( IN_BACK );
+}
+void IN_LookupDown(void) {KeyDown(&in_lookup);}
+void IN_LookupUp(void) {KeyUp(&in_lookup);}
+void IN_LookdownDown(void) {KeyDown(&in_lookdown);}
+void IN_LookdownUp(void) {KeyUp(&in_lookdown);}
+void IN_MoveleftDown(void)
+{
+ KeyDown(&in_moveleft);
+ gHUD.m_Spectator.HandleButtonsDown( IN_MOVELEFT );
+}
+
+void IN_MoveleftUp(void)
+{
+ KeyUp(&in_moveleft);
+ gHUD.m_Spectator.HandleButtonsUp( IN_MOVELEFT );
+}
+
+void IN_MoverightDown(void)
+{
+ KeyDown(&in_moveright);
+ gHUD.m_Spectator.HandleButtonsDown( IN_MOVERIGHT );
+}
+
+void IN_MoverightUp(void)
+{
+ KeyUp(&in_moveright);
+ gHUD.m_Spectator.HandleButtonsUp( IN_MOVERIGHT );
+}
+void IN_SpeedDown(void) {KeyDown(&in_speed);}
+void IN_SpeedUp(void) {KeyUp(&in_speed);}
+void IN_StrafeDown(void) {KeyDown(&in_strafe);}
+void IN_StrafeUp(void) {KeyUp(&in_strafe);}
+
+// needs capture by hud/vgui also
+extern void __CmdFunc_InputPlayerSpecial(void);
+void IN_Attack2Down(void) {KeyDownForced(&in_attack2);}
+void IN_Attack2Up(void) {KeyUpForced(&in_attack2);}
+void IN_UseDown (void)
+{
+ KeyDown(&in_use);
+ gHUD.m_Spectator.HandleButtonsDown( IN_USE );
+}
+void IN_UseUp (void) {KeyUp(&in_use);}
+void IN_JumpDown (void)
+{
+ KeyDown(&in_jump);
+ gHUD.m_Spectator.HandleButtonsDown( IN_JUMP );
+
+}
+
+void IN_JumpUp (void)
+{
+ KeyUp(&in_jump);
+ gHUD.m_Spectator.HandleButtonsUp( IN_JUMP );
+}
+
+void IN_DuckDown(void)
+{
+ KeyDown(&in_duck);
+ gHUD.m_Spectator.HandleButtonsDown( IN_DUCK );
+}
+
+void IN_DuckUp(void) {KeyUp(&in_duck);}
+// : duck toggle
+void IN_DuckToggle(void)
+{
+ g_bDuckToggled = !g_bDuckToggled;
+}
+// :
+void IN_ReloadDown(void) {KeyDownForced(&in_reload);}
+void IN_ReloadUp(void) {KeyUpForced(&in_reload);}
+void IN_Alt1Down(void) {KeyDown(&in_alt1);}
+void IN_Alt1Up(void) {KeyUp(&in_alt1);}
+void IN_GraphDown(void) {KeyDown(&in_graph);}
+void IN_GraphUp(void) {KeyUp(&in_graph);}
+
+void IN_AttackDown(void)
+{
+ KeyDown( &in_attack );
+ gHUD.m_Spectator.HandleButtonsDown( IN_ATTACK );
+}
+
+void IN_AttackUp(void)
+{
+ KeyUp( &in_attack );
+ in_cancel = 0;
+ IN_Attack2Up();
+}
+
+void IN_AttackDownForced(void)
+{
+ KeyDownForced( &in_attack );
+}
+
+void IN_AttackUpForced(void)
+{
+ KeyUpForced( &in_attack );
+}
+
+// Special handling
+void IN_Cancel(void)
+{
+ in_cancel = 1;
+}
+
+bool CheckInAttack(void)
+{
+ return (in_attack.state & 1 || in_attack2.state & 1);
+}
+
+bool CheckInAttack2(void)
+{
+ return (in_attack2.state & 1);
+}
+
+void IN_Impulse (void)
+{
+ //char msg[1024];
+ //sprintf(msg, "in_impulse=%s\n", gEngfuncs.Cmd_Argv(1));
+ //CenterPrint(msg);
+
+ in_impulse = atoi( gEngfuncs.Cmd_Argv(1) );
+}
+
+void IN_ScoreDown(void)
+{
+ KeyDown(&in_score);
+ if ( gViewPort )
+ {
+ gViewPort->ShowScoreBoard();
+ }
+}
+
+void IN_ScoreUp(void)
+{
+ KeyUp(&in_score);
+ if ( gViewPort )
+ {
+ gViewPort->HideScoreBoard();
+ }
+}
+
+void IN_MLookUp (void)
+{
+ KeyUp( &in_mlook );
+ if ( !( in_mlook.state & 1 ) && lookspring->value )
+ {
+ V_StartPitchDrift();
+ }
+}
+
+/*
+===============
+CL_KeyState
+
+Returns 0.25 if a key was pressed and released during the frame,
+0.5 if it was pressed and held
+0 if held then released, and
+1.0 if held for the entire time
+===============
+*/
+float CL_KeyState (kbutton_t *key)
+{
+ float val = 0.0;
+ int impulsedown, impulseup, down;
+
+ impulsedown = key->state & 2;
+ impulseup = key->state & 4;
+ down = key->state & 1;
+
+ if ( impulsedown && !impulseup )
+ {
+ // pressed and held this frame?
+ val = down ? 0.5 : 0.0;
+ }
+
+ if ( impulseup && !impulsedown )
+ {
+ // released this frame?
+ val = down ? 0.0 : 0.0;
+ }
+
+ if ( !impulsedown && !impulseup )
+ {
+ // held the entire frame?
+ val = down ? 1.0 : 0.0;
+ }
+
+ if ( impulsedown && impulseup )
+ {
+ if ( down )
+ {
+ // released and re-pressed this frame
+ val = 0.75;
+ }
+ else
+ {
+ // pressed and released this frame
+ val = 0.25;
+ }
+ }
+
+ // clear impulses
+ key->state &= 1;
+ return val;
+}
+
+/*
+================
+CL_AdjustAngles
+
+Moves the local angle positions
+================
+*/
+void CL_AdjustAngles ( float frametime, float *viewangles )
+{
+ float speed;
+ float up, down;
+
+ if (in_speed.state & 1)
+ {
+ speed = frametime * cl_anglespeedkey->value;
+ }
+ else
+ {
+ speed = frametime;
+ }
+
+ if (!(in_strafe.state & 1))
+ {
+ viewangles[YAW] -= speed*cl_yawspeed->value*CL_KeyState (&in_right);
+ viewangles[YAW] += speed*cl_yawspeed->value*CL_KeyState (&in_left);
+ viewangles[YAW] = anglemod(viewangles[YAW]);
+ }
+ if (in_klook.state & 1)
+ {
+ V_StopPitchDrift ();
+ viewangles[PITCH] -= speed*cl_pitchspeed->value * CL_KeyState (&in_forward);
+ viewangles[PITCH] += speed*cl_pitchspeed->value * CL_KeyState (&in_back);
+ }
+
+ up = CL_KeyState (&in_lookup);
+ down = CL_KeyState(&in_lookdown);
+
+ viewangles[PITCH] -= speed*cl_pitchspeed->value * up;
+ viewangles[PITCH] += speed*cl_pitchspeed->value * down;
+
+ if (up || down)
+ V_StopPitchDrift ();
+
+ if (viewangles[PITCH] > cl_pitchdown->value)
+ viewangles[PITCH] = cl_pitchdown->value;
+ if (viewangles[PITCH] < -cl_pitchup->value)
+ viewangles[PITCH] = -cl_pitchup->value;
+
+ if (viewangles[ROLL] > 50)
+ viewangles[ROLL] = 50;
+ if (viewangles[ROLL] < -50)
+ viewangles[ROLL] = -50;
+}
+
+/*
+================
+CL_CreateMove
+
+Send the intended movement message to the server
+if active == 1 then we are 1) not playing back demos ( where our commands are ignored ) and
+2 ) we have finished signing on to server
+================
+*/
+void CL_DLLEXPORT CL_CreateMove ( float frametime, struct usercmd_s *cmd, int active )
+{
+ //RecClCL_CreateMove(frametime, cmd, active);
+ //@linux Commander overview needs to be fixed!
+ float spd;
+ vec3_t viewangles;
+ static vec3_t oldangles;
+
+ if ( active && (!gViewPort || !gViewPort->IsOptionsMenuVisible()) /*&& !gHUD.GetShowingMap()*/)
+ {
+ int theButtonState = CL_ButtonBits(1);
+ //memset( viewangles, 0, sizeof( vec3_t ) );
+ //viewangles[ 0 ] = viewangles[ 1 ] = viewangles[ 2 ] = 0.0;
+ //gEngfuncs.GetViewAngles( (float *)viewangles );
+
+ //CL_AdjustAngles ( frametime, viewangles );
+
+ memset (cmd, 0, sizeof(*cmd));
+ //@ linux void IN_Move ( float frametime, usercmd_t *cmd)
+ float theRotationDeltas[3] = {0,0,0}; //{90,0,90} --> top down --> viewangles[YAW]
+ float theTranslationDeltas[3] = {0,0,0}; //--> cmd->sidemove
+
+ IN_Move ( frametime, cmd );
+
+ if(gResetViewAngles)
+ {
+ VectorCopy(gViewAngles,viewangles);
+ gResetViewAngles = false;
+ }
+ else
+ {
+ gEngfuncs.GetViewAngles( (float *)viewangles );
+ }
+ VectorAdd(viewangles,theRotationDeltas,viewangles);
+ CL_AdjustAngles ( frametime, viewangles );
+
+ gEngfuncs.SetViewAngles( (float *)viewangles );
+ VectorCopy (viewangles,gWorldViewAngles);
+
+ // If we're in topdown mode
+ bool theProcessedMove = false;
+ bool theIsSendingSpecialEvent = false;
+ bool theOverrideImpulse = false;
+ float theWorldX, theWorldY;
+ int theScriptImpulse = 0;
+
+ AvHMessageID theAlienAbility = MESSAGE_NULL;
+ AvHMessageID theGroupMessage = MESSAGE_NULL;
+
+ //int theUpgradeVar = gEngfuncs.GetLocalPlayer()->curstate.iuser4;
+ //bool theIsParalyzed = GetHasUpgrade(theUpgradeVar, PLAYER_PARALYZED);
+ if(AvHScriptManager::Instance()->GetClientMove(theButtonState, theScriptImpulse))
+ {
+ if(theScriptImpulse)
+ {
+ theOverrideImpulse = true;
+ }
+ //theProcessedMove = true;
+
+ // TODO: Pass theButtonState to override all CL_KeyState() calls
+ }
+ else if(gHUD.GetInTopDownMode())
+ {
+ cmd->upmove = cmd->sidemove = cmd->forwardmove = 0;
+
+ // If a button was JUST pressed or released
+ vec3_t theMouseNormPos;
+ AvHMessageID theTechEvent = MESSAGE_NULL;
+ if(gCommanderHandler.GetMoveToWorldPosition(theWorldX, theWorldY))
+ {
+ // Commander wants to scroll to an area of the mini-map
+ cmd->impulse = COMMANDER_MOVETO;
+ cmd->upmove = theWorldX/kWorldPosNetworkConstant;
+ cmd->sidemove = theWorldY/kWorldPosNetworkConstant;
+ gCommanderHandler.ClearMoveToPosition();
+ gHUD.ClearTrackingEntity();
+
+ theIsSendingSpecialEvent = true;
+ theProcessedMove = true;
+ }
+ else if(gCommanderHandler.GetDefaultOrderPosition(theWorldX, theWorldY))
+ {
+ // Commander wants to scroll to an area of the mini-map
+ cmd->impulse = COMMANDER_DEFAULTORDER;
+ cmd->upmove = theWorldX/kWorldPosNetworkConstant;
+ cmd->sidemove = theWorldY/kWorldPosNetworkConstant;
+ gCommanderHandler.ClearDefaultOrderPosition();
+ gHUD.ClearTrackingEntity();
+
+ theIsSendingSpecialEvent = true;
+ theProcessedMove = true;
+ }
+ else if(gHUD.GetAndClearTechEvent(theTechEvent))
+ {
+ cmd->impulse = theTechEvent;
+ theProcessedMove = true;
+ theIsSendingSpecialEvent = true;
+ gHUD.ClearTrackingEntity();
+
+ }
+ // else scroll
+ else
+ {
+ // Scroll the view if the HUD tells us to, otherwise use normal key presses
+ int theScrollX = 0, theScrollY = 0, theScrollZ = 0;
+ gHUD.GetAndClearTopDownScrollAmount(theScrollX, theScrollY, theScrollZ);
+
+ if(theScrollX || theScrollY || theScrollZ)
+ {
+ // Commander move speed
+ float kCommanderMoveSpeed = 1000;
+ cmd->upmove += kCommanderMoveSpeed * theScrollY;
+ cmd->sidemove += kCommanderMoveSpeed * theScrollX;
+ cmd->forwardmove += kCommanderMoveSpeed * theScrollZ;
+
+ cmd->impulse = COMMANDER_SCROLL;
+ theOverrideImpulse = true;
+
+ gHUD.ClearTrackingEntity();
+
+ //theIsSendingSpecialEvent = true;
+ theProcessedMove = true;
+ }
+ else if(gHUD.GetAndClearGroupEvent(theGroupMessage))
+ {
+ cmd->impulse = theGroupMessage;
+ theIsSendingSpecialEvent = true;
+ theProcessedMove = true;
+
+ gHUD.SetLastHotkeySelectionEvent(theGroupMessage);
+ }
+// else if(gHUD.GetTrackingEntity() > 0)
+// {
+// int theTrackingEntity = gHUD.GetTrackingEntity();
+// cmd->upmove = theTrackingEntity*kHotKeyNetworkFactor;
+// cmd->impulse = COMMANDER_TRACKENTITY;
+//
+// theIsSendingSpecialEvent = true;
+// theProcessedMove = true;
+// }
+ else if(in_impulse != 0)
+ {
+ bool theProcessImpulse = false;
+ switch(in_impulse)
+ {
+ case COMMANDER_SELECTALL:
+ case COMMANDER_NEXTIDLE:
+ case COMMANDER_NEXTAMMO:
+ case COMMANDER_NEXTHEALTH:
+ theProcessImpulse = true;
+ break;
+ }
+
+ if(theProcessImpulse)
+ {
+ cmd->impulse = in_impulse;
+ in_impulse = 0;
+
+ theProcessedMove = true;
+ theIsSendingSpecialEvent = true;
+ }
+ }
+
+ if(!theProcessedMove && gHUD.GetAndClearSelectionEvent(theMouseNormPos, theTechEvent))
+ {
+ // Store world position x,y in upmove,sidemove
+ cmd->upmove = theMouseNormPos.x*kSelectionNetworkConstant;
+ cmd->sidemove = theMouseNormPos.y*kSelectionNetworkConstant;
+ cmd->forwardmove = theMouseNormPos.z*kSelectionNetworkConstant;
+
+ // Set impulse indicating this
+ //cmd->impulse = COMMANDER_MOUSECOORD;
+
+ // This could be COMMANDER_MOUSECOORD or BUILD_TURRET or one of the other BUILD_ events
+ // They are all sent the same way
+ cmd->impulse = theTechEvent;
+
+ // Order mode isn't currently used but may be in the future
+ //cmd->weaponselect = gHUD.GetOrderMode();
+
+ // Set buttons. Attack gets turned off when we're in mouse mode (apparently)
+ // so we need to set the buttons manually
+ cmd->buttons = theButtonState;
+ if(gHUD.GetMouseOneDown())
+ {
+ cmd->buttons |= IN_ATTACK;
+ }
+ if(gHUD.GetMouseTwoDown())
+ {
+ cmd->buttons |= IN_ATTACK2;
+ }
+
+ gHUD.ClearTrackingEntity();
+
+ theIsSendingSpecialEvent = true;
+ theProcessedMove = true;
+ }
+ }
+ }
+ else if(gHUD.GetAndClearAlienAbility(theAlienAbility))
+ {
+ cmd->impulse = theAlienAbility;
+
+ // Added by mmcguire.
+ // 255 signifies that the impulse came from us and not from the console.
+ cmd->weaponselect = 255;
+
+ theProcessedMove = true;
+ theIsSendingSpecialEvent = true;
+
+ }
+
+ // else process move normally
+ if(!theProcessedMove)
+ {
+ if ( in_strafe.state & 1 )
+ {
+ cmd->sidemove += cl_sidespeed->value * CL_KeyState (&in_right);
+ cmd->sidemove -= cl_sidespeed->value * CL_KeyState (&in_left);
+ }
+
+ cmd->sidemove += cl_sidespeed->value * CL_KeyState (&in_moveright);
+ cmd->sidemove -= cl_sidespeed->value * CL_KeyState (&in_moveleft);
+
+ cmd->upmove += cl_upspeed->value * CL_KeyState (&in_up);
+ cmd->upmove -= cl_upspeed->value * CL_KeyState (&in_down);
+
+ if ( !(in_klook.state & 1 ) )
+ {
+ cmd->forwardmove += cl_forwardspeed->value * CL_KeyState (&in_forward);
+ cmd->forwardmove -= cl_backspeed->value * CL_KeyState (&in_back);
+ }
+ }
+
+ if(!theIsSendingSpecialEvent)
+ {
+ // adjust for speed key
+ if ( in_speed.state & 1 )
+ {
+ cmd->forwardmove *= cl_movespeedkey->value;
+ cmd->sidemove *= cl_movespeedkey->value;
+ cmd->upmove *= cl_movespeedkey->value;
+ }
+
+ // clip to maxspeed
+ spd = gEngfuncs.GetClientMaxspeed();
+
+ if ( spd != 0.0 )
+ {
+ // scale the 3 speeds so that the total velocity is not > cl.maxspeed
+ float fmov = sqrt( (cmd->forwardmove*cmd->forwardmove) + (cmd->sidemove*cmd->sidemove) + (cmd->upmove*cmd->upmove) );
+
+ if ( fmov > spd )
+ {
+ float fratio = spd / fmov;
+ cmd->forwardmove *= fratio;
+ cmd->sidemove *= fratio;
+ cmd->upmove *= fratio;
+ }
+ }
+
+ // Allow mice and other controllers to add their inputs
+ IN_Move ( frametime, cmd );
+
+ if(!theOverrideImpulse)
+ {
+ cmd->impulse = in_impulse;
+ in_impulse = 0;
+ }
+
+ cmd->weaponselect = g_weaponselect;
+ g_weaponselect = 0;
+
+ //
+ // set button and flag bits
+ //
+ cmd->buttons = theButtonState;
+
+ // If they're in a modal dialog, or we're stunned, ignore the attack button.
+ int theLocalUpgrades = gHUD.GetLocalUpgrades();
+ if( GetClientVoiceMgr()->IsInSquelchMode() )
+ {
+ cmd->buttons &= ~IN_ATTACK;
+ }
+
+ // Using joystick?
+ if ( in_joystick->value )
+ {
+ if ( cmd->forwardmove > 0 )
+ {
+ cmd->buttons |= IN_FORWARD;
+ }
+ else if ( cmd->forwardmove < 0 )
+ {
+ cmd->buttons |= IN_BACK;
+ }
+ }
+ }
+ }
+
+ gEngfuncs.GetViewAngles( (float *)viewangles );
+ // Set current view angles.
+
+ // Set current view angles but not if frozen (this still allows you to rotate in first-person, but player model won't change)
+ int theUser4 = gHUD.GetLocalUpgrades();
+ bool theIsFrozen = GetHasUpgrade(theUser4, MASK_PLAYER_STUNNED) || GetHasUpgrade(theUser4, MASK_ALIEN_EMBRYO);
+
+ if ( g_iAlive && !theIsFrozen)
+ {
+ VectorCopy( viewangles, cmd->viewangles );
+ VectorCopy( viewangles, oldangles );
+ }
+ else
+ {
+ VectorCopy( oldangles, cmd->viewangles );
+ }
+
+ //Bench_SetViewAngles( 1, (float *)&cmd->viewangles, frametime, cmd );
+}
+
+/*
+============
+CL_IsDead
+
+Returns 1 if health is <= 0
+============
+*/
+int CL_IsDead( void )
+{
+ return ( gHUD.m_Health.m_iHealth <= 0 ) ? 1 : 0;
+}
+
+/*
+============
+CL_ButtonBits
+
+Returns appropriate button info for keyboard and mouse state
+Set bResetState to 1 to clear old state info
+============
+*/
+int CL_ButtonBits( int bResetState )
+{
+ int bits = 0;
+
+ if ( in_attack.state & 3 )
+ {
+ bits |= IN_ATTACK;
+ }
+
+ if ( in_speed.state & 3 )
+ {
+ bits |= IN_WALK;
+ }
+
+ // : duck toggle
+ if ( g_bDuckToggled )
+ {
+ if (!(in_duck.state & 3))
+ {
+ bits |= IN_DUCK;
+ }
+ }
+ else if (in_duck.state & 3)
+ {
+ bits |= IN_DUCK;
+ }
+ // :
+
+ if (in_jump.state & 3)
+ {
+ bits |= IN_JUMP;
+ }
+
+ if ( in_forward.state & 3 )
+ {
+ bits |= IN_FORWARD;
+ }
+
+ if (in_back.state & 3)
+ {
+ bits |= IN_BACK;
+ }
+
+ if (in_use.state & 3)
+ {
+ bits |= IN_USE;
+ }
+
+ if (in_cancel)
+ {
+ bits |= IN_CANCEL;
+ }
+
+ if ( in_left.state & 3 )
+ {
+ bits |= IN_LEFT;
+ }
+
+ if (in_right.state & 3)
+ {
+ bits |= IN_RIGHT;
+ }
+
+ if ( in_moveleft.state & 3 )
+ {
+ bits |= IN_MOVELEFT;
+ }
+
+ if (in_moveright.state & 3)
+ {
+ bits |= IN_MOVERIGHT;
+ }
+
+ if (in_attack2.state & 3)
+ {
+ bits |= IN_ATTACK2;
+ }
+
+ if (in_reload.state & 3)
+ {
+ bits |= IN_RELOAD;
+ }
+
+ if (in_alt1.state & 3)
+ {
+ bits |= IN_ALT1;
+ }
+
+ if ( in_score.state & 3 )
+ {
+ bits |= IN_SCORE;
+ }
+
+ // Dead or in intermission? Shore scoreboard, too
+ if ( CL_IsDead() || gHUD.m_iIntermission )
+ {
+ bits |= IN_SCORE;
+ }
+
+ if ( bResetState )
+ {
+ in_attack.state &= ~2;
+ in_speed.state &= ~2;
+ in_duck.state &= ~2;
+ in_jump.state &= ~2;
+ in_forward.state &= ~2;
+ in_back.state &= ~2;
+ in_use.state &= ~2;
+ in_left.state &= ~2;
+ in_right.state &= ~2;
+ in_moveleft.state &= ~2;
+ in_moveright.state &= ~2;
+ in_attack2.state &= ~2;
+ in_reload.state &= ~2;
+ in_alt1.state &= ~2;
+ in_score.state &= ~2;
+ }
+
+ return bits;
+}
+
+/*
+============
+CL_ResetButtonBits
+
+============
+*/
+void CL_ResetButtonBits( int bits )
+{
+ int bitsNew = CL_ButtonBits( 0 ) ^ bits;
+
+ // Has the attack button been changed
+ if ( bitsNew & IN_ATTACK )
+ {
+ // Was it pressed? or let go?
+ if ( bits & IN_ATTACK )
+ {
+ KeyDown( &in_attack );
+ }
+ else
+ {
+ // totally clear state
+ in_attack.state &= ~7;
+ in_attack2.state &= ~7;
+ }
+ }
+}
+
+/*
+============
+InitInput
+============
+*/
+void InitInput (void)
+{
+ gEngfuncs.pfnAddCommand ("+moveup",IN_UpDown);
+ gEngfuncs.pfnAddCommand ("-moveup",IN_UpUp);
+ gEngfuncs.pfnAddCommand ("+movedown",IN_DownDown);
+ gEngfuncs.pfnAddCommand ("-movedown",IN_DownUp);
+ gEngfuncs.pfnAddCommand ("+left",IN_LeftDown);
+ gEngfuncs.pfnAddCommand ("-left",IN_LeftUp);
+ gEngfuncs.pfnAddCommand ("+right",IN_RightDown);
+ gEngfuncs.pfnAddCommand ("-right",IN_RightUp);
+ gEngfuncs.pfnAddCommand ("+forward",IN_ForwardDown);
+ gEngfuncs.pfnAddCommand ("-forward",IN_ForwardUp);
+ gEngfuncs.pfnAddCommand ("+back",IN_BackDown);
+ gEngfuncs.pfnAddCommand ("-back",IN_BackUp);
+ gEngfuncs.pfnAddCommand ("+lookup", IN_LookupDown);
+ gEngfuncs.pfnAddCommand ("-lookup", IN_LookupUp);
+ gEngfuncs.pfnAddCommand ("+lookdown", IN_LookdownDown);
+ gEngfuncs.pfnAddCommand ("-lookdown", IN_LookdownUp);
+ gEngfuncs.pfnAddCommand ("+strafe", IN_StrafeDown);
+ gEngfuncs.pfnAddCommand ("-strafe", IN_StrafeUp);
+ gEngfuncs.pfnAddCommand ("+moveleft", IN_MoveleftDown);
+ gEngfuncs.pfnAddCommand ("-moveleft", IN_MoveleftUp);
+ gEngfuncs.pfnAddCommand ("+moveright", IN_MoverightDown);
+ gEngfuncs.pfnAddCommand ("-moveright", IN_MoverightUp);
+ gEngfuncs.pfnAddCommand ("+speed", IN_SpeedDown);
+ gEngfuncs.pfnAddCommand ("-speed", IN_SpeedUp);
+ gEngfuncs.pfnAddCommand ("+attack", IN_AttackDown);
+ gEngfuncs.pfnAddCommand ("-attack", IN_AttackUp);
+ //gEngfuncs.pfnAddCommand ("+movement", IN_Attack2Down);
+ //gEngfuncs.pfnAddCommand ("-movement", IN_Attack2Up);
+ gEngfuncs.pfnAddCommand ("+use", IN_UseDown);
+ gEngfuncs.pfnAddCommand ("-use", IN_UseUp);
+ gEngfuncs.pfnAddCommand ("+jump", IN_JumpDown);
+ gEngfuncs.pfnAddCommand ("-jump", IN_JumpUp);
+ gEngfuncs.pfnAddCommand ("impulse", IN_Impulse);
+ gEngfuncs.pfnAddCommand ("+klook", IN_KLookDown);
+ gEngfuncs.pfnAddCommand ("-klook", IN_KLookUp);
+ gEngfuncs.pfnAddCommand ("+mlook", IN_MLookDown);
+ gEngfuncs.pfnAddCommand ("-mlook", IN_MLookUp);
+ gEngfuncs.pfnAddCommand ("+jlook", IN_JLookDown);
+ gEngfuncs.pfnAddCommand ("-jlook", IN_JLookUp);
+ gEngfuncs.pfnAddCommand ("+duck", IN_DuckDown);
+ gEngfuncs.pfnAddCommand ("-duck", IN_DuckUp);
+ // : duck toggle
+ gEngfuncs.pfnAddCommand ("toggleduck", IN_DuckToggle);
+ // :
+ gEngfuncs.pfnAddCommand ("+reload", IN_ReloadDown);
+ gEngfuncs.pfnAddCommand ("-reload", IN_ReloadUp);
+ gEngfuncs.pfnAddCommand ("+alt1", IN_Alt1Down);
+ gEngfuncs.pfnAddCommand ("-alt1", IN_Alt1Up);
+ gEngfuncs.pfnAddCommand ("+score", IN_ScoreDown);
+ gEngfuncs.pfnAddCommand ("-score", IN_ScoreUp);
+ gEngfuncs.pfnAddCommand ("+showscores", IN_ScoreDown);
+ gEngfuncs.pfnAddCommand ("-showscores", IN_ScoreUp);
+ gEngfuncs.pfnAddCommand ("+graph", IN_GraphDown);
+ gEngfuncs.pfnAddCommand ("-graph", IN_GraphUp);
+ gEngfuncs.pfnAddCommand ("+break",IN_BreakDown);
+ gEngfuncs.pfnAddCommand ("-break",IN_BreakUp);
+
+ lookstrafe = gEngfuncs.pfnRegisterVariable ( "lookstrafe", "0", FCVAR_ARCHIVE );
+ lookspring = gEngfuncs.pfnRegisterVariable ( "lookspring", "0", FCVAR_ARCHIVE );
+ cl_anglespeedkey = gEngfuncs.pfnRegisterVariable ( "cl_anglespeedkey", "0.67", 0 );
+ cl_yawspeed = gEngfuncs.pfnRegisterVariable ( "cl_yawspeed", "210", 0 );
+ cl_pitchspeed = gEngfuncs.pfnRegisterVariable ( "cl_pitchspeed", "225", 0 );
+ cl_upspeed = gEngfuncs.pfnRegisterVariable ( "cl_upspeed", "320", 0 );
+ cl_forwardspeed = gEngfuncs.pfnRegisterVariable ( "cl_forwardspeed", "400", FCVAR_ARCHIVE );
+ cl_backspeed = gEngfuncs.pfnRegisterVariable ( "cl_backspeed", "400", FCVAR_ARCHIVE );
+ cl_sidespeed = gEngfuncs.pfnRegisterVariable ( "cl_sidespeed", "400", 0 );
+ cl_movespeedkey = gEngfuncs.pfnRegisterVariable ( "cl_movespeedkey", "0.3", 0 );
+ cl_pitchup = gEngfuncs.pfnRegisterVariable ( "cl_pitchup", "89", 0 );
+ cl_pitchdown = gEngfuncs.pfnRegisterVariable ( "cl_pitchdown", "89", 0 );
+
+ cl_vsmoothing = gEngfuncs.pfnRegisterVariable ( "cl_vsmoothing", "0.05", FCVAR_ARCHIVE );
+
+ m_pitch = gEngfuncs.pfnRegisterVariable ( "m_pitch","0.022", FCVAR_ARCHIVE );
+ m_yaw = gEngfuncs.pfnRegisterVariable ( "m_yaw","0.022", FCVAR_ARCHIVE );
+ m_forward = gEngfuncs.pfnRegisterVariable ( "m_forward","1", FCVAR_ARCHIVE );
+ m_side = gEngfuncs.pfnRegisterVariable ( "m_side","0.8", FCVAR_ARCHIVE );
+
+ cl_autohelp = gEngfuncs.pfnRegisterVariable ( kvAutoHelp, "1.0", FCVAR_ARCHIVE );
+ cl_centerentityid = gEngfuncs.pfnRegisterVariable ( kvCenterEntityID, "0.0", FCVAR_ARCHIVE );
+ cl_musicenabled = gEngfuncs.pfnRegisterVariable ( kvMusicEnabled, "1.0", FCVAR_ARCHIVE );
+ cl_musicvolume = gEngfuncs.pfnRegisterVariable ( kvMusicVolume, "155", FCVAR_ARCHIVE );
+ cl_musicdir = gEngfuncs.pfnRegisterVariable ( kvMusicDirectory, "", FCVAR_ARCHIVE);
+ cl_musicdelay = gEngfuncs.pfnRegisterVariable ( kvMusicDelay, "90", FCVAR_ARCHIVE);
+ cl_forcedefaultfov = gEngfuncs.pfnRegisterVariable ( kvForceDefaultFOV, "0", FCVAR_ARCHIVE );
+ cl_dynamiclights = gEngfuncs.pfnRegisterVariable ( kvDynamicLights, "1", FCVAR_ARCHIVE );
+ cl_buildmessages = gEngfuncs.pfnRegisterVariable ( kvBuildMessages, "1", FCVAR_ARCHIVE);
+ cl_quickselecttime = gEngfuncs.pfnRegisterVariable ( kvQuickSelectTime, ".15", FCVAR_ARCHIVE );
+ cl_highdetail = gEngfuncs.pfnRegisterVariable ( kvHighDetail, "1", FCVAR_ARCHIVE );
+ cl_cmhotkeys = gEngfuncs.pfnRegisterVariable ( kvCMHotkeys, "qwerasdfzxcv", FCVAR_ARCHIVE );
+ cl_forcedefaultfov = gEngfuncs.pfnRegisterVariable ( kvForceDefaultFOV, "0", FCVAR_ARCHIVE );
+ cl_particleinfo = gEngfuncs.pfnRegisterVariable ( kvParticleInfo, "0", FCVAR_ARCHIVE );
+
+ // Initialize third person camera controls.
+ CAM_Init();
+ // Initialize inputs
+ IN_Init();
+ // Initialize keyboard
+ KB_Init();
+ // Initialize view system
+ V_Init();
+}
+
+/*
+============
+ShutdownInput
+============
+*/
+void ShutdownInput (void)
+{
+ IN_Shutdown();
+ KB_Shutdown();
+}
+#include "interface.h"
+void CL_DLLEXPORT HUD_Shutdown( void )
+{
+// RecClShutdown();
+
+ ShutdownInput();
+
+ gHUD.Shutdown();
+}
diff --git a/main/source/cl_dll/kbutton.h b/main/source/cl_dll/kbutton.h
index c3a7c138..cb306770 100644
--- a/main/source/cl_dll/kbutton.h
+++ b/main/source/cl_dll/kbutton.h
@@ -1,11 +1,11 @@
-#if !defined( KBUTTONH )
-#define KBUTTONH
-#pragma once
-
-typedef struct kbutton_s
-{
- int down[2]; // key nums holding it down
- int state; // low bit is down state
-} kbutton_t;
-
+#if !defined( KBUTTONH )
+#define KBUTTONH
+#pragma once
+
+typedef struct kbutton_s
+{
+ int down[2]; // key nums holding it down
+ int state; // low bit is down state
+} kbutton_t;
+
#endif // !KBUTTONH
\ No newline at end of file
diff --git a/main/source/cl_dll/menu.cpp b/main/source/cl_dll/menu.cpp
index 47e846b5..4ebe7d0c 100644
--- a/main/source/cl_dll/menu.cpp
+++ b/main/source/cl_dll/menu.cpp
@@ -1,186 +1,186 @@
-/***
-*
-* Copyright (c) 1999, Valve LLC. All rights reserved.
-*
-* This product contains software technology licensed from Id
-* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
-* All Rights Reserved.
-*
-* Use, distribution, and modification of this source code and/or resulting
-* object code is restricted to non-commercial enhancements to products from
-* Valve LLC. All other use, distribution, or modification is prohibited
-* without written permission from Valve LLC.
-*
-****/
-//
-// menu.cpp
-//
-// generic menu handler
-//
-#include "hud.h"
-#include "cl_util.h"
-#include "mod/AvHNetworkMessages.h"
-
-#include
-#include
-
-#include "vgui_TeamFortressViewport.h"
-
-#define MAX_MENU_STRING 512
-char g_szMenuString[MAX_MENU_STRING];
-char g_szPrelocalisedMenuString[MAX_MENU_STRING];
-
-int KB_ConvertString( char *in, char **ppout );
-
-DECLARE_MESSAGE( m_Menu, ShowMenu );
-
-int CHudMenu :: Init( void )
-{
- gHUD.AddHudElem( this );
-
- HOOK_MESSAGE( ShowMenu );
-
- InitHUDData();
-
- return 1;
-}
-
-void CHudMenu :: InitHUDData( void )
-{
- m_fMenuDisplayed = 0;
- m_bitsValidSlots = 0;
- Reset();
-}
-
-void CHudMenu :: Reset( void )
-{
- g_szPrelocalisedMenuString[0] = 0;
- m_fWaitingForMore = FALSE;
-}
-
-int CHudMenu :: VidInit( void )
-{
- return 1;
-}
-
-int CHudMenu :: Draw( float flTime )
-{
- // check for if menu is set to disappear
- if ( m_flShutoffTime > 0 )
- {
- if ( m_flShutoffTime <= gHUD.m_flTime )
- { // times up, shutoff
- m_fMenuDisplayed = 0;
- m_iFlags &= ~HUD_ACTIVE;
- return 1;
- }
- }
-
- // don't draw the menu if the scoreboard is being shown
- if ( gViewPort && gViewPort->IsScoreBoardVisible() )
- return 1;
-
- // draw the menu, along the left-hand side of the screen
-
- // count the number of newlines
- int nlc = 0,i = 0;
- for ( i = 0; i < MAX_MENU_STRING && g_szMenuString[i] != '\0'; i++ )
- {
- if ( g_szMenuString[i] == '\n' )
- nlc++;
- }
-
- // center it
- int y = (ScreenHeight()/2) - ((nlc/2)*12) - 40; // make sure it is above the say text
- int x = 20;
-
- i = 0;
- while ( i < MAX_MENU_STRING && g_szMenuString[i] != '\0' )
- {
- gHUD.DrawHudString( x, y, 320, g_szMenuString + i, 255, 255, 255 );
- y += 12;
-
- while ( i < MAX_MENU_STRING && g_szMenuString[i] != '\0' && g_szMenuString[i] != '\n' )
- i++;
- if ( g_szMenuString[i] == '\n' )
- i++;
- }
-
- return 1;
-}
-
-// selects an item from the menu
-void CHudMenu :: SelectMenuItem( int menu_item )
-{
- // if menu_item is in a valid slot, send a menuselect command to the server
- if ( (menu_item > 0) && (m_bitsValidSlots & (1 << (menu_item-1))) )
- {
- char szbuf[32];
- sprintf( szbuf, "menuselect %d\n", menu_item );
- ClientCmd( szbuf );
-
- // remove the menu
- m_fMenuDisplayed = 0;
- m_iFlags &= ~HUD_ACTIVE;
- }
-}
-
-
-// Message handler for ShowMenu message
-// takes four values:
-// short: a bitfield of keys that are valid input
-// char : the duration, in seconds, the menu should stay up. -1 means is stays until something is chosen.
-// byte : a boolean, TRUE if there is more string yet to be received before displaying the menu, FALSE if it's the last string
-// string: menu string to display
-// if this message is never received, then scores will simply be the combined totals of the players.
-int CHudMenu :: MsgFunc_ShowMenu( const char *pszName, int iSize, void *pbuf )
-{
- char *temp = NULL;
-
- int DisplayTime, NeedMore;
- string content;
-
- NetMsg_ShowMenu( pbuf, iSize, m_bitsValidSlots, DisplayTime, NeedMore, content );
-
- if ( DisplayTime > 0 )
- m_flShutoffTime = DisplayTime + gHUD.m_flTime;
- else
- m_flShutoffTime = -1;
-
- if ( m_bitsValidSlots )
- {
- if ( !m_fWaitingForMore ) // this is the start of a new menu
- {
- strncpy( g_szPrelocalisedMenuString, content.c_str(), MAX_MENU_STRING );
- }
- else
- { // append to the current menu string
- strncat( g_szPrelocalisedMenuString, content.c_str(), MAX_MENU_STRING - strlen(g_szPrelocalisedMenuString) );
- }
- g_szPrelocalisedMenuString[MAX_MENU_STRING-1] = 0; // ensure null termination (strncat/strncpy does not)
-
- if ( !NeedMore )
- { // we have the whole string, so we can localise it now
- strcpy( g_szMenuString, gHUD.m_TextMessage.BufferedLocaliseTextString( g_szPrelocalisedMenuString ) );
-
- // Swap in characters
- if ( KB_ConvertString( g_szMenuString, &temp ) )
- {
- strcpy( g_szMenuString, temp );
- free( temp );
- }
- }
-
- m_fMenuDisplayed = 1;
- m_iFlags |= HUD_ACTIVE;
- }
- else
- {
- m_fMenuDisplayed = 0; // no valid slots means that the menu should be turned off
- m_iFlags &= ~HUD_ACTIVE;
- }
-
- m_fWaitingForMore = NeedMore;
-
- return 1;
-}
+/***
+*
+* Copyright (c) 1999, Valve LLC. All rights reserved.
+*
+* This product contains software technology licensed from Id
+* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
+* All Rights Reserved.
+*
+* Use, distribution, and modification of this source code and/or resulting
+* object code is restricted to non-commercial enhancements to products from
+* Valve LLC. All other use, distribution, or modification is prohibited
+* without written permission from Valve LLC.
+*
+****/
+//
+// menu.cpp
+//
+// generic menu handler
+//
+#include "hud.h"
+#include "cl_util.h"
+#include "mod/AvHNetworkMessages.h"
+
+#include
+#include
+
+#include "vgui_TeamFortressViewport.h"
+
+#define MAX_MENU_STRING 512
+char g_szMenuString[MAX_MENU_STRING];
+char g_szPrelocalisedMenuString[MAX_MENU_STRING];
+
+int KB_ConvertString( char *in, char **ppout );
+
+DECLARE_MESSAGE( m_Menu, ShowMenu );
+
+int CHudMenu :: Init( void )
+{
+ gHUD.AddHudElem( this );
+
+ HOOK_MESSAGE( ShowMenu );
+
+ InitHUDData();
+
+ return 1;
+}
+
+void CHudMenu :: InitHUDData( void )
+{
+ m_fMenuDisplayed = 0;
+ m_bitsValidSlots = 0;
+ Reset();
+}
+
+void CHudMenu :: Reset( void )
+{
+ g_szPrelocalisedMenuString[0] = 0;
+ m_fWaitingForMore = FALSE;
+}
+
+int CHudMenu :: VidInit( void )
+{
+ return 1;
+}
+
+int CHudMenu :: Draw( float flTime )
+{
+ // check for if menu is set to disappear
+ if ( m_flShutoffTime > 0 )
+ {
+ if ( m_flShutoffTime <= gHUD.m_flTime )
+ { // times up, shutoff
+ m_fMenuDisplayed = 0;
+ m_iFlags &= ~HUD_ACTIVE;
+ return 1;
+ }
+ }
+
+ // don't draw the menu if the scoreboard is being shown
+ if ( gViewPort && gViewPort->IsScoreBoardVisible() )
+ return 1;
+
+ // draw the menu, along the left-hand side of the screen
+
+ // count the number of newlines
+ int nlc = 0,i = 0;
+ for ( i = 0; i < MAX_MENU_STRING && g_szMenuString[i] != '\0'; i++ )
+ {
+ if ( g_szMenuString[i] == '\n' )
+ nlc++;
+ }
+
+ // center it
+ int y = (ScreenHeight()/2) - ((nlc/2)*12) - 40; // make sure it is above the say text
+ int x = 20;
+
+ i = 0;
+ while ( i < MAX_MENU_STRING && g_szMenuString[i] != '\0' )
+ {
+ gHUD.DrawHudString( x, y, 320, g_szMenuString + i, 255, 255, 255 );
+ y += 12;
+
+ while ( i < MAX_MENU_STRING && g_szMenuString[i] != '\0' && g_szMenuString[i] != '\n' )
+ i++;
+ if ( g_szMenuString[i] == '\n' )
+ i++;
+ }
+
+ return 1;
+}
+
+// selects an item from the menu
+void CHudMenu :: SelectMenuItem( int menu_item )
+{
+ // if menu_item is in a valid slot, send a menuselect command to the server
+ if ( (menu_item > 0) && (m_bitsValidSlots & (1 << (menu_item-1))) )
+ {
+ char szbuf[32];
+ sprintf( szbuf, "menuselect %d\n", menu_item );
+ ClientCmd( szbuf );
+
+ // remove the menu
+ m_fMenuDisplayed = 0;
+ m_iFlags &= ~HUD_ACTIVE;
+ }
+}
+
+
+// Message handler for ShowMenu message
+// takes four values:
+// short: a bitfield of keys that are valid input
+// char : the duration, in seconds, the menu should stay up. -1 means is stays until something is chosen.
+// byte : a boolean, TRUE if there is more string yet to be received before displaying the menu, FALSE if it's the last string
+// string: menu string to display
+// if this message is never received, then scores will simply be the combined totals of the players.
+int CHudMenu :: MsgFunc_ShowMenu( const char *pszName, int iSize, void *pbuf )
+{
+ char *temp = NULL;
+
+ int DisplayTime, NeedMore;
+ string content;
+
+ NetMsg_ShowMenu( pbuf, iSize, m_bitsValidSlots, DisplayTime, NeedMore, content );
+
+ if ( DisplayTime > 0 )
+ m_flShutoffTime = DisplayTime + gHUD.m_flTime;
+ else
+ m_flShutoffTime = -1;
+
+ if ( m_bitsValidSlots )
+ {
+ if ( !m_fWaitingForMore ) // this is the start of a new menu
+ {
+ strncpy( g_szPrelocalisedMenuString, content.c_str(), MAX_MENU_STRING );
+ }
+ else
+ { // append to the current menu string
+ strncat( g_szPrelocalisedMenuString, content.c_str(), MAX_MENU_STRING - strlen(g_szPrelocalisedMenuString) );
+ }
+ g_szPrelocalisedMenuString[MAX_MENU_STRING-1] = 0; // ensure null termination (strncat/strncpy does not)
+
+ if ( !NeedMore )
+ { // we have the whole string, so we can localise it now
+ strcpy( g_szMenuString, gHUD.m_TextMessage.BufferedLocaliseTextString( g_szPrelocalisedMenuString ) );
+
+ // Swap in characters
+ if ( KB_ConvertString( g_szMenuString, &temp ) )
+ {
+ strcpy( g_szMenuString, temp );
+ free( temp );
+ }
+ }
+
+ m_fMenuDisplayed = 1;
+ m_iFlags |= HUD_ACTIVE;
+ }
+ else
+ {
+ m_fMenuDisplayed = 0; // no valid slots means that the menu should be turned off
+ m_iFlags &= ~HUD_ACTIVE;
+ }
+
+ m_fWaitingForMore = NeedMore;
+
+ return 1;
+}
diff --git a/main/source/cl_dll/message.cpp b/main/source/cl_dll/message.cpp
index c158a0eb..de264534 100644
--- a/main/source/cl_dll/message.cpp
+++ b/main/source/cl_dll/message.cpp
@@ -1,717 +1,717 @@
-/***
-*
-* Copyright (c) 1999, Valve LLC. All rights reserved.
-*
-* This product contains software technology licensed from Id
-* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
-* All Rights Reserved.
-*
-* Use, distribution, and modification of this source code and/or resulting
-* object code is restricted to non-commercial enhancements to products from
-* Valve LLC. All other use, distribution, or modification is prohibited
-* without written permission from Valve LLC.
-*
-****/
-//
-// Message.cpp
-//
-// implementation of CHudMessage class
-//
-
-#include "hud.h"
-#include "cl_util.h"
-#include
-#include
-#include "mod/AvHClientVariables.h"
-#include "mod/AvHNetworkMessages.h"
-
-DECLARE_MESSAGE( m_Message, HudText )
-DECLARE_MESSAGE( m_Message, HudText2 )
-DECLARE_MESSAGE( m_Message, GameTitle )
-
-// 1 Global client_textmessage_t for custom messages that aren't in the titles.txt
-client_textmessage_t g_pCustomMessage;
-char *g_pCustomName = "Custom";
-char g_pCustomText[1024];
-
-int CHudMessage::Init(void)
-{
- HOOK_MESSAGE( HudText );
- HOOK_MESSAGE( HudText2 );
- HOOK_MESSAGE( GameTitle );
-
- gHUD.AddHudElem(this);
-
- Reset();
-
- return 1;
-};
-
-int CHudMessage::VidInit( void )
-{
- m_HUD_title_half = gHUD.GetSpriteIndex( "title_half" );
- m_HUD_title_life = gHUD.GetSpriteIndex( "title_life" );
-
- return 1;
-};
-
-const int kDefaultRComp = 25;
-const int kDefaultGComp = 255;
-const int kDefaultBComp = 25;
-
-const int kEnemyRComp = 255;
-const int kEnemyGComp = 25;
-const int kEnemyBComp = 25;
-
-void CHudMessage::Reset( void )
-{
- memset( m_pMessages, 0, sizeof( m_pMessages[0] ) * maxHUDMessages );
- memset( m_startTime, 0, sizeof( m_startTime[0] ) * maxHUDMessages );
-
- m_gameTitleTime = 0;
- m_pGameTitle = NULL;
-
- // Player id stuff
- this->mPlayerIDTime = 0;
- this->mPlayerID = NULL;
-
- this->mPlayerIDMessage.effect = 1;
- this->mPlayerIDMessage.r1 = kDefaultRComp;
- this->mPlayerIDMessage.g1 = kDefaultGComp;
- this->mPlayerIDMessage.b1 = kDefaultBComp;
- this->mPlayerIDMessage.a1 = 255;
-
- this->mPlayerIDMessage.g2 = 255;
- this->mPlayerIDMessage.r2 = this->mPlayerIDMessage.b2 = 25;
- this->mPlayerIDMessage.a2 = 255;
-
- this->SetPlayerIDPosition();
-
- this->mPlayerIDMessage.fadein = 0.04;
- this->mPlayerIDMessage.fadeout = 0.5;
- this->mPlayerIDMessage.fxtime = 0.25;
- this->mPlayerIDMessage.holdtime = 5;
- this->mPlayerIDMessage.pName = NULL;
- this->mPlayerIDMessage.pMessage = NULL;
-}
-
-void CHudMessage::SetPlayerIDPosition()
-{
- if(gEngfuncs.pfnGetCvarFloat(kvCenterEntityID) || gHUD.GetInTopDownMode())
- {
- this->mPlayerIDMessage.x = -1; // Centered
- this->mPlayerIDMessage.y = -1; // Centered
- }
- else
- {
- this->mPlayerIDMessage.x = .3;
- this->mPlayerIDMessage.y = .9;
- }
-}
-
-float CHudMessage::FadeBlend( float fadein, float fadeout, float hold, float localTime )
-{
- float fadeTime = fadein + hold;
- float fadeBlend;
-
- if ( localTime < 0 )
- return 0;
-
- if ( localTime < fadein )
- {
- fadeBlend = 1 - ((fadein - localTime) / fadein);
- }
- else if ( localTime > fadeTime )
- {
- if ( fadeout > 0 )
- fadeBlend = 1 - ((localTime - fadeTime) / fadeout);
- else
- fadeBlend = 0;
- }
- else
- fadeBlend = 1;
-
- return fadeBlend;
-}
-
-
-int CHudMessage::XPosition( float x, int width, int totalWidth )
-{
- int xPos;
-
- if ( x == -1 )
- {
- xPos = (ScreenWidth() - width) / 2;
- }
- else
- {
- if ( x < 0 )
- xPos = (1.0 + x) * ScreenWidth() - totalWidth; // Alight right
- else
- xPos = x * ScreenWidth();
- }
-
- if ( xPos + width > ScreenWidth() )
- xPos = ScreenWidth() - width;
- else if ( xPos < 0 )
- xPos = 0;
-
- return xPos;
-}
-
-
-int CHudMessage::YPosition( float y, int height )
-{
- int yPos;
-
- if ( y == -1 ) // Centered?
- yPos = (ScreenHeight() - height) * 0.5;
- else
- {
- // Alight bottom?
- if ( y < 0 )
- yPos = (1.0 + y) * ScreenHeight() - height; // Alight bottom
- else // align top
- yPos = y * ScreenHeight();
- }
-
- if ( yPos + height > ScreenHeight() )
- yPos = ScreenHeight() - height;
- else if ( yPos < 0 )
- yPos = 0;
-
- return yPos;
-}
-
-
-void CHudMessage::MessageScanNextChar( void )
-{
- int srcRed, srcGreen, srcBlue, destRed, destGreen, destBlue;
- int blend;
-
- srcRed = m_parms.pMessage->r1;
- srcGreen = m_parms.pMessage->g1;
- srcBlue = m_parms.pMessage->b1;
- blend = 0; // Pure source
-
- switch( m_parms.pMessage->effect )
- {
- // Fade-in / Fade-out
- case 0:
- case 1:
- destRed = destGreen = destBlue = 0;
- blend = m_parms.fadeBlend;
- break;
-
- case 2:
- m_parms.charTime += m_parms.pMessage->fadein;
- if ( m_parms.charTime > m_parms.time )
- {
- srcRed = srcGreen = srcBlue = 0;
- blend = 0; // pure source
- }
- else
- {
- float deltaTime = m_parms.time - m_parms.charTime;
-
- destRed = destGreen = destBlue = 0;
- if ( m_parms.time > m_parms.fadeTime )
- {
- blend = m_parms.fadeBlend;
- }
- else if ( deltaTime > m_parms.pMessage->fxtime )
- blend = 0; // pure dest
- else
- {
- destRed = m_parms.pMessage->r2;
- destGreen = m_parms.pMessage->g2;
- destBlue = m_parms.pMessage->b2;
- blend = 255 - (deltaTime * (1.0/m_parms.pMessage->fxtime) * 255.0 + 0.5);
- }
- }
- break;
- }
- if ( blend >= 255 )
- {
- m_parms.r = destRed;
- m_parms.g = destGreen;
- m_parms.b = destBlue;
- }
- else if ( blend <= 0 )
- {
- m_parms.r = srcRed;
- m_parms.g = srcGreen;
- m_parms.b = srcBlue;
- }
- else
- {
- m_parms.r = ((srcRed * (255-blend)) + (destRed * blend)) >> 8;
- m_parms.g = ((srcGreen * (255-blend)) + (destGreen * blend)) >> 8;
- m_parms.b = ((srcBlue * (255-blend)) + (destBlue * blend)) >> 8;
- }
-
- if ( m_parms.pMessage->effect == 1 && m_parms.charTime != 0 )
- {
- if ( m_parms.x >= 0 && m_parms.y >= 0 && (m_parms.x + gHUD.m_scrinfo.charWidths[ m_parms.text ]) <= ScreenWidth() )
- TextMessageDrawChar( m_parms.x, m_parms.y, m_parms.text, m_parms.pMessage->r2, m_parms.pMessage->g2, m_parms.pMessage->b2 );
- }
-}
-
-
-void CHudMessage::MessageScanStart( void )
-{
- switch( m_parms.pMessage->effect )
- {
- // Fade-in / out with flicker
- case 1:
- case 0:
- m_parms.fadeTime = m_parms.pMessage->fadein + m_parms.pMessage->holdtime;
-
-
- if ( m_parms.time < m_parms.pMessage->fadein )
- {
- m_parms.fadeBlend = ((m_parms.pMessage->fadein - m_parms.time) * (1.0/m_parms.pMessage->fadein) * 255);
- }
- else if ( m_parms.time > m_parms.fadeTime )
- {
- if ( m_parms.pMessage->fadeout > 0 )
- m_parms.fadeBlend = (((m_parms.time - m_parms.fadeTime) / m_parms.pMessage->fadeout) * 255);
- else
- m_parms.fadeBlend = 255; // Pure dest (off)
- }
- else
- m_parms.fadeBlend = 0; // Pure source (on)
- m_parms.charTime = 0;
-
- if ( m_parms.pMessage->effect == 1 && (rand()%100) < 10 )
- m_parms.charTime = 1;
- break;
-
- case 2:
- m_parms.fadeTime = (m_parms.pMessage->fadein * m_parms.length) + m_parms.pMessage->holdtime;
-
- if ( m_parms.time > m_parms.fadeTime && m_parms.pMessage->fadeout > 0 )
- m_parms.fadeBlend = (((m_parms.time - m_parms.fadeTime) / m_parms.pMessage->fadeout) * 255);
- else
- m_parms.fadeBlend = 0;
- break;
- }
-}
-
-
-void CHudMessage::MessageDrawScan( client_textmessage_t *pMessage, float time )
-{
- int i, j, length, width;
- const char *pText;
- //unsigned char line[80];
- unsigned char line[256];
-
- pText = pMessage->pMessage;
- ASSERT(pText != NULL);
-
- // Count lines
- m_parms.lines = 1;
- m_parms.time = time;
- m_parms.pMessage = pMessage;
- length = 0;
- width = 0;
- m_parms.totalWidth = 0;
- while ( *pText )
- {
- if ( *pText == '\n' )
- {
- m_parms.lines++;
- if ( width > m_parms.totalWidth )
- m_parms.totalWidth = width;
- width = 0;
- }
- else
- width += gHUD.m_scrinfo.charWidths[*pText];
- pText++;
- length++;
- }
- m_parms.length = length;
- m_parms.totalHeight = (m_parms.lines * gHUD.m_scrinfo.iCharHeight);
-
-
- m_parms.y = YPosition( pMessage->y, m_parms.totalHeight );
- pText = pMessage->pMessage;
-
- m_parms.charTime = 0;
-
- MessageScanStart();
-
- for ( i = 0; i < m_parms.lines; i++ )
- {
- m_parms.lineLength = 0;
- m_parms.width = 0;
- while ( *pText && *pText != '\n' )
- {
- unsigned char c = *pText;
- line[m_parms.lineLength] = c;
- m_parms.width += gHUD.m_scrinfo.charWidths[c];
- m_parms.lineLength++;
- pText++;
- }
- pText++; // Skip LF
- line[m_parms.lineLength] = 0;
-
- m_parms.x = XPosition( pMessage->x, m_parms.width, m_parms.totalWidth );
-
- for ( j = 0; j < m_parms.lineLength; j++ )
- {
- m_parms.text = line[j];
- int next = m_parms.x + gHUD.m_scrinfo.charWidths[ m_parms.text ];
- MessageScanNextChar();
-
- if ( m_parms.x >= 0 && m_parms.y >= 0 && next <= ScreenWidth() )
- TextMessageDrawChar( m_parms.x, m_parms.y, m_parms.text, m_parms.r, m_parms.g, m_parms.b );
- m_parms.x = next;
- }
-
- m_parms.y += gHUD.m_scrinfo.iCharHeight;
- }
-}
-
-
-int CHudMessage::Draw( float fTime )
-{
- int i, drawn;
- client_textmessage_t *pMessage;
-
- drawn = 0;
-
- if ( m_gameTitleTime > 0 )
- {
- float localTime = gHUD.m_flTime - m_gameTitleTime;
- float brightness;
-
- // Maybe timer isn't set yet
- if ( m_gameTitleTime > gHUD.m_flTime )
- m_gameTitleTime = gHUD.m_flTime;
-
- if ( localTime > (m_pGameTitle->fadein + m_pGameTitle->holdtime + m_pGameTitle->fadeout) )
- m_gameTitleTime = 0;
- else
- {
- brightness = FadeBlend( m_pGameTitle->fadein, m_pGameTitle->fadeout, m_pGameTitle->holdtime, localTime );
-
- int halfWidth = gHUD.GetSpriteRect(m_HUD_title_half).right - gHUD.GetSpriteRect(m_HUD_title_half).left;
- int fullWidth = halfWidth + gHUD.GetSpriteRect(m_HUD_title_life).right - gHUD.GetSpriteRect(m_HUD_title_life).left;
- int fullHeight = gHUD.GetSpriteRect(m_HUD_title_half).bottom - gHUD.GetSpriteRect(m_HUD_title_half).top;
-
- int x = XPosition( m_pGameTitle->x, fullWidth, fullWidth );
- int y = YPosition( m_pGameTitle->y, fullHeight );
-
-
- SPR_Set( gHUD.GetSprite(m_HUD_title_half), brightness * m_pGameTitle->r1, brightness * m_pGameTitle->g1, brightness * m_pGameTitle->b1 );
- SPR_DrawAdditive( 0, x, y, &gHUD.GetSpriteRect(m_HUD_title_half) );
-
- SPR_Set( gHUD.GetSprite(m_HUD_title_life), brightness * m_pGameTitle->r1, brightness * m_pGameTitle->g1, brightness * m_pGameTitle->b1 );
- SPR_DrawAdditive( 0, x + halfWidth, y, &gHUD.GetSpriteRect(m_HUD_title_life) );
-
- drawn++;
- }
- }
-
- // Draw player id
-// if(this->mPlayerIDTime > 0)
-// {
-// float localTime = gHUD.m_flTime - this->mPlayerIDTime;
-// //float brightness;
-//
-// // Maybe timer isn't set yet
-// if ( this->mPlayerIDTime > gHUD.m_flTime )
-// this->mPlayerIDTime = gHUD.m_flTime;
-//
-// if ( localTime > (this->mPlayerIDMessage.fadein + this->mPlayerIDMessage.holdtime + this->mPlayerIDMessage.fadeout) )
-// {
-// this->mPlayerIDTime = 0;
-// this->mPlayerIDMessage.pName = NULL;
-// this->mPlayerIDMessage.pMessage = NULL;
-// }
-// else
-// {
-// drawn++;
-// }
-// }
-
- // Fixup level transitions
- for ( i = 0; i < maxHUDMessages; i++ )
- {
- // Assume m_parms.time contains last time
- if ( m_pMessages[i] )
- {
- pMessage = m_pMessages[i];
- if ( m_startTime[i] > gHUD.m_flTime )
- m_startTime[i] = gHUD.m_flTime + m_parms.time - m_startTime[i] + 0.2; // Server takes 0.2 seconds to spawn, adjust for this
- }
- }
-
- for ( i = 0; i < maxHUDMessages; i++ )
- {
- client_textmessage_t* theMessage = this->m_pMessages[i];
- if(theMessage)
- {
- if(this->DrawMessage(theMessage, this->m_startTime[i], fTime))
- {
- drawn++;
- }
- else
- {
- // The message is over
- this->m_pMessages[i] = NULL;
- }
- }
- }
-
- if(this->DrawMessage(&this->mPlayerIDMessage, this->mPlayerIDTime, fTime))
- {
- drawn++;
- }
- else
- {
- this->mPlayerIDMessage.pName = NULL;
- this->mPlayerIDMessage.pMessage = NULL;
- }
-
-
- // Remember the time -- to fix up level transitions
- m_parms.time = gHUD.m_flTime;
- // Don't call until we get another message
- if ( !drawn )
- m_iFlags &= ~HUD_ACTIVE;
-
- return 1;
-}
-
-bool CHudMessage::DrawMessage(client_textmessage_t* inMessage, float inStartTime, float inCurrentTime)
-{
- ASSERT(inMessage);
- bool theDrewMessage = false;
-
- if(inMessage->pMessage)
- {
- float endTime;
-
- // This is when the message is over
- switch( inMessage->effect )
- {
- case 0:
- case 1:
- endTime = inStartTime + inMessage->fadein + inMessage->fadeout + inMessage->holdtime;
- break;
-
- // Fade in is per character in scanning messages
- case 2:
- endTime = inStartTime + (inMessage->fadein * strlen( inMessage->pMessage )) + inMessage->fadeout + inMessage->holdtime;
- break;
- }
-
- if ( inCurrentTime <= endTime )
- {
- float messageTime = inCurrentTime - inStartTime;
-
- // Draw the message
- // effect 0 is fade in/fade out
- // effect 1 is flickery credits
- // effect 2 is write out (training room)
- MessageDrawScan( inMessage, messageTime );
- theDrewMessage = true;
- }
- }
-
- return theDrewMessage;
-}
-
-void CHudMessage::MessageAdd( const char *pName, float time )
-{
- int i,j;
- client_textmessage_t *tempMessage;
-
- for ( i = 0; i < maxHUDMessages; i++ )
- {
- if ( !m_pMessages[i] )
- {
- // Trim off a leading # if it's there
- if ( pName[0] == '#' )
- tempMessage = TextMessageGet( pName+1 );
- else
- tempMessage = TextMessageGet( pName );
- // If we couldnt find it in the titles.txt, just create it
- if ( !tempMessage )
- {
- g_pCustomMessage.effect = 2;
- g_pCustomMessage.r1 = g_pCustomMessage.g1 = g_pCustomMessage.b1 = g_pCustomMessage.a1 = 100;
- g_pCustomMessage.r2 = 240;
- g_pCustomMessage.g2 = 110;
- g_pCustomMessage.b2 = 0;
- g_pCustomMessage.a2 = 0;
- g_pCustomMessage.x = -1; // Centered
- g_pCustomMessage.y = 0.7;
- g_pCustomMessage.fadein = 0.01;
- g_pCustomMessage.fadeout = 1.5;
- g_pCustomMessage.fxtime = 0.25;
- g_pCustomMessage.holdtime = 5;
- g_pCustomMessage.pName = g_pCustomName;
- strcpy( g_pCustomText, pName );
- g_pCustomMessage.pMessage = g_pCustomText;
-
- tempMessage = &g_pCustomMessage;
- }
-
- for ( j = 0; j < maxHUDMessages; j++ )
- {
- if ( m_pMessages[j] )
- {
- // is this message already in the list
- if ( !strcmp( tempMessage->pMessage, m_pMessages[j]->pMessage ) )
- {
- return;
- }
-
- // get rid of any other messages in same location (only one displays at a time)
- if ( fabs( tempMessage->y - m_pMessages[j]->y ) < 0.0001 )
- {
- if ( fabs( tempMessage->x - m_pMessages[j]->x ) < 0.0001 )
- {
- m_pMessages[j] = NULL;
- }
- }
- }
- }
-
- m_pMessages[i] = tempMessage;
- m_startTime[i] = time;
- return;
- }
- }
-}
-
-void CHudMessage::MessageAddPlayerID(const char* inName, bool inEnemy)
-{
- // If we're already drawing this, extend the time
- //if(inName && this->mPlayerIDMessage.pMessage && !strcmp(inName, this->mPlayerIDMessage.pMessage))
- //{
- // //this->mPlayerIDMessage.holdtime =
- //}
- //else
- //{
- // else add this message
- this->mPlayerIDMessage.pMessage = inName;
-
- //strcpy( g_pCustomText, pName );
- //this->mPlayerIDMessage.pMessage = g_pCustomText;
- this->mPlayerIDTime = gHUD.m_flTime;
-
- // Set color depending on if friend or enemy
- if(inEnemy)
- {
- this->mPlayerIDMessage.r1 = kEnemyRComp;
- this->mPlayerIDMessage.g1 = kEnemyGComp;
- this->mPlayerIDMessage.b1 = kEnemyBComp;
- }
- else
- {
- this->mPlayerIDMessage.r1 = kDefaultRComp;
- this->mPlayerIDMessage.g1 = kDefaultGComp;
- this->mPlayerIDMessage.b1 = kDefaultBComp;
- }
-
- this->SetPlayerIDPosition();
-
- // Turn on drawing
- if(inName)
- {
- if ( !(m_iFlags & HUD_ACTIVE) )
- m_iFlags |= HUD_ACTIVE;
- }
-
- //}
-}
-
-bool CHudMessage::MessageRemove(const char *pName)
-{
- const char* theMessage = pName;
- bool theSuccess = false;
- bool theNeedsTranslation = (pName[0] == '#');
-
- // Trim off a leading # if it's there
- if(theNeedsTranslation)
- {
- client_textmessage_t* tempMessage = TextMessageGet(pName + 1);
- if(tempMessage)
- {
- theMessage = tempMessage->pMessage;
- }
- }
-
- if(theMessage)
- {
- for (int j = 0; j < maxHUDMessages; j++ )
- {
- if ( m_pMessages[j] )
- {
- // is this message already in the list
- if (!strcmp(theMessage, m_pMessages[j]->pMessage))
- {
- m_startTime[j] = -1;
- theSuccess = true;
- }
- }
- }
- }
- return theSuccess;
-}
-
-int CHudMessage::MsgFunc_HudText( const char *pszName, int iSize, void *pbuf )
-{
- string content;
-
- NetMsg_HudText( pbuf, iSize, content );
- MessageAdd( content.c_str(), gHUD.m_flTime );
-
- // Remember the time -- to fix up level transitions
- m_parms.time = gHUD.m_flTime;
-
- // Turn on drawing
- if ( !(m_iFlags & HUD_ACTIVE) )
- m_iFlags |= HUD_ACTIVE;
-
- return 1;
-}
-
-int CHudMessage::MsgFunc_HudText2( const char *pszName, int iSize, void *pbuf )
-{
- string content;
- int flags;
- NetMsg_HudText2( pbuf, iSize, content, flags );
-
- switch (flags)
- {
- case 2:
- gHUD.SetCenterText(content.c_str());
- break;
- default:
- bool theIsAutoHelp = (flags & 1) != 0;
- gHUD.AddTooltip(content.c_str(), theIsAutoHelp);
- break;
- }
-
- return 2;
-}
-
-int CHudMessage::MsgFunc_GameTitle( const char *pszName, int iSize, void *pbuf )
-{
- m_pGameTitle = TextMessageGet( "GAMETITLE" );
- if ( m_pGameTitle != NULL )
- {
- m_gameTitleTime = gHUD.m_flTime;
-
- // Turn on drawing
- if ( !(m_iFlags & HUD_ACTIVE) )
- m_iFlags |= HUD_ACTIVE;
- }
-
- return 1;
-}
+/***
+*
+* Copyright (c) 1999, Valve LLC. All rights reserved.
+*
+* This product contains software technology licensed from Id
+* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
+* All Rights Reserved.
+*
+* Use, distribution, and modification of this source code and/or resulting
+* object code is restricted to non-commercial enhancements to products from
+* Valve LLC. All other use, distribution, or modification is prohibited
+* without written permission from Valve LLC.
+*
+****/
+//
+// Message.cpp
+//
+// implementation of CHudMessage class
+//
+
+#include "hud.h"
+#include "cl_util.h"
+#include
+#include
+#include "mod/AvHClientVariables.h"
+#include "mod/AvHNetworkMessages.h"
+
+DECLARE_MESSAGE( m_Message, HudText )
+DECLARE_MESSAGE( m_Message, HudText2 )
+DECLARE_MESSAGE( m_Message, GameTitle )
+
+// 1 Global client_textmessage_t for custom messages that aren't in the titles.txt
+client_textmessage_t g_pCustomMessage;
+char *g_pCustomName = "Custom";
+char g_pCustomText[1024];
+
+int CHudMessage::Init(void)
+{
+ HOOK_MESSAGE( HudText );
+ HOOK_MESSAGE( HudText2 );
+ HOOK_MESSAGE( GameTitle );
+
+ gHUD.AddHudElem(this);
+
+ Reset();
+
+ return 1;
+};
+
+int CHudMessage::VidInit( void )
+{
+ m_HUD_title_half = gHUD.GetSpriteIndex( "title_half" );
+ m_HUD_title_life = gHUD.GetSpriteIndex( "title_life" );
+
+ return 1;
+};
+
+const int kDefaultRComp = 25;
+const int kDefaultGComp = 255;
+const int kDefaultBComp = 25;
+
+const int kEnemyRComp = 255;
+const int kEnemyGComp = 25;
+const int kEnemyBComp = 25;
+
+void CHudMessage::Reset( void )
+{
+ memset( m_pMessages, 0, sizeof( m_pMessages[0] ) * maxHUDMessages );
+ memset( m_startTime, 0, sizeof( m_startTime[0] ) * maxHUDMessages );
+
+ m_gameTitleTime = 0;
+ m_pGameTitle = NULL;
+
+ // Player id stuff
+ this->mPlayerIDTime = 0;
+ this->mPlayerID = NULL;
+
+ this->mPlayerIDMessage.effect = 1;
+ this->mPlayerIDMessage.r1 = kDefaultRComp;
+ this->mPlayerIDMessage.g1 = kDefaultGComp;
+ this->mPlayerIDMessage.b1 = kDefaultBComp;
+ this->mPlayerIDMessage.a1 = 255;
+
+ this->mPlayerIDMessage.g2 = 255;
+ this->mPlayerIDMessage.r2 = this->mPlayerIDMessage.b2 = 25;
+ this->mPlayerIDMessage.a2 = 255;
+
+ this->SetPlayerIDPosition();
+
+ this->mPlayerIDMessage.fadein = 0.04;
+ this->mPlayerIDMessage.fadeout = 0.5;
+ this->mPlayerIDMessage.fxtime = 0.25;
+ this->mPlayerIDMessage.holdtime = 5;
+ this->mPlayerIDMessage.pName = NULL;
+ this->mPlayerIDMessage.pMessage = NULL;
+}
+
+void CHudMessage::SetPlayerIDPosition()
+{
+ if(gEngfuncs.pfnGetCvarFloat(kvCenterEntityID) || gHUD.GetInTopDownMode())
+ {
+ this->mPlayerIDMessage.x = -1; // Centered
+ this->mPlayerIDMessage.y = -1; // Centered
+ }
+ else
+ {
+ this->mPlayerIDMessage.x = .3;
+ this->mPlayerIDMessage.y = .9;
+ }
+}
+
+float CHudMessage::FadeBlend( float fadein, float fadeout, float hold, float localTime )
+{
+ float fadeTime = fadein + hold;
+ float fadeBlend;
+
+ if ( localTime < 0 )
+ return 0;
+
+ if ( localTime < fadein )
+ {
+ fadeBlend = 1 - ((fadein - localTime) / fadein);
+ }
+ else if ( localTime > fadeTime )
+ {
+ if ( fadeout > 0 )
+ fadeBlend = 1 - ((localTime - fadeTime) / fadeout);
+ else
+ fadeBlend = 0;
+ }
+ else
+ fadeBlend = 1;
+
+ return fadeBlend;
+}
+
+
+int CHudMessage::XPosition( float x, int width, int totalWidth )
+{
+ int xPos;
+
+ if ( x == -1 )
+ {
+ xPos = (ScreenWidth() - width) / 2;
+ }
+ else
+ {
+ if ( x < 0 )
+ xPos = (1.0 + x) * ScreenWidth() - totalWidth; // Alight right
+ else
+ xPos = x * ScreenWidth();
+ }
+
+ if ( xPos + width > ScreenWidth() )
+ xPos = ScreenWidth() - width;
+ else if ( xPos < 0 )
+ xPos = 0;
+
+ return xPos;
+}
+
+
+int CHudMessage::YPosition( float y, int height )
+{
+ int yPos;
+
+ if ( y == -1 ) // Centered?
+ yPos = (ScreenHeight() - height) * 0.5;
+ else
+ {
+ // Alight bottom?
+ if ( y < 0 )
+ yPos = (1.0 + y) * ScreenHeight() - height; // Alight bottom
+ else // align top
+ yPos = y * ScreenHeight();
+ }
+
+ if ( yPos + height > ScreenHeight() )
+ yPos = ScreenHeight() - height;
+ else if ( yPos < 0 )
+ yPos = 0;
+
+ return yPos;
+}
+
+
+void CHudMessage::MessageScanNextChar( void )
+{
+ int srcRed, srcGreen, srcBlue, destRed, destGreen, destBlue;
+ int blend;
+
+ srcRed = m_parms.pMessage->r1;
+ srcGreen = m_parms.pMessage->g1;
+ srcBlue = m_parms.pMessage->b1;
+ blend = 0; // Pure source
+
+ switch( m_parms.pMessage->effect )
+ {
+ // Fade-in / Fade-out
+ case 0:
+ case 1:
+ destRed = destGreen = destBlue = 0;
+ blend = m_parms.fadeBlend;
+ break;
+
+ case 2:
+ m_parms.charTime += m_parms.pMessage->fadein;
+ if ( m_parms.charTime > m_parms.time )
+ {
+ srcRed = srcGreen = srcBlue = 0;
+ blend = 0; // pure source
+ }
+ else
+ {
+ float deltaTime = m_parms.time - m_parms.charTime;
+
+ destRed = destGreen = destBlue = 0;
+ if ( m_parms.time > m_parms.fadeTime )
+ {
+ blend = m_parms.fadeBlend;
+ }
+ else if ( deltaTime > m_parms.pMessage->fxtime )
+ blend = 0; // pure dest
+ else
+ {
+ destRed = m_parms.pMessage->r2;
+ destGreen = m_parms.pMessage->g2;
+ destBlue = m_parms.pMessage->b2;
+ blend = 255 - (deltaTime * (1.0/m_parms.pMessage->fxtime) * 255.0 + 0.5);
+ }
+ }
+ break;
+ }
+ if ( blend >= 255 )
+ {
+ m_parms.r = destRed;
+ m_parms.g = destGreen;
+ m_parms.b = destBlue;
+ }
+ else if ( blend <= 0 )
+ {
+ m_parms.r = srcRed;
+ m_parms.g = srcGreen;
+ m_parms.b = srcBlue;
+ }
+ else
+ {
+ m_parms.r = ((srcRed * (255-blend)) + (destRed * blend)) >> 8;
+ m_parms.g = ((srcGreen * (255-blend)) + (destGreen * blend)) >> 8;
+ m_parms.b = ((srcBlue * (255-blend)) + (destBlue * blend)) >> 8;
+ }
+
+ if ( m_parms.pMessage->effect == 1 && m_parms.charTime != 0 )
+ {
+ if ( m_parms.x >= 0 && m_parms.y >= 0 && (m_parms.x + gHUD.m_scrinfo.charWidths[ m_parms.text ]) <= ScreenWidth() )
+ TextMessageDrawChar( m_parms.x, m_parms.y, m_parms.text, m_parms.pMessage->r2, m_parms.pMessage->g2, m_parms.pMessage->b2 );
+ }
+}
+
+
+void CHudMessage::MessageScanStart( void )
+{
+ switch( m_parms.pMessage->effect )
+ {
+ // Fade-in / out with flicker
+ case 1:
+ case 0:
+ m_parms.fadeTime = m_parms.pMessage->fadein + m_parms.pMessage->holdtime;
+
+
+ if ( m_parms.time < m_parms.pMessage->fadein )
+ {
+ m_parms.fadeBlend = ((m_parms.pMessage->fadein - m_parms.time) * (1.0/m_parms.pMessage->fadein) * 255);
+ }
+ else if ( m_parms.time > m_parms.fadeTime )
+ {
+ if ( m_parms.pMessage->fadeout > 0 )
+ m_parms.fadeBlend = (((m_parms.time - m_parms.fadeTime) / m_parms.pMessage->fadeout) * 255);
+ else
+ m_parms.fadeBlend = 255; // Pure dest (off)
+ }
+ else
+ m_parms.fadeBlend = 0; // Pure source (on)
+ m_parms.charTime = 0;
+
+ if ( m_parms.pMessage->effect == 1 && (rand()%100) < 10 )
+ m_parms.charTime = 1;
+ break;
+
+ case 2:
+ m_parms.fadeTime = (m_parms.pMessage->fadein * m_parms.length) + m_parms.pMessage->holdtime;
+
+ if ( m_parms.time > m_parms.fadeTime && m_parms.pMessage->fadeout > 0 )
+ m_parms.fadeBlend = (((m_parms.time - m_parms.fadeTime) / m_parms.pMessage->fadeout) * 255);
+ else
+ m_parms.fadeBlend = 0;
+ break;
+ }
+}
+
+
+void CHudMessage::MessageDrawScan( client_textmessage_t *pMessage, float time )
+{
+ int i, j, length, width;
+ const char *pText;
+ //unsigned char line[80];
+ unsigned char line[256];
+
+ pText = pMessage->pMessage;
+ ASSERT(pText != NULL);
+
+ // Count lines
+ m_parms.lines = 1;
+ m_parms.time = time;
+ m_parms.pMessage = pMessage;
+ length = 0;
+ width = 0;
+ m_parms.totalWidth = 0;
+ while ( *pText )
+ {
+ if ( *pText == '\n' )
+ {
+ m_parms.lines++;
+ if ( width > m_parms.totalWidth )
+ m_parms.totalWidth = width;
+ width = 0;
+ }
+ else
+ width += gHUD.m_scrinfo.charWidths[*pText];
+ pText++;
+ length++;
+ }
+ m_parms.length = length;
+ m_parms.totalHeight = (m_parms.lines * gHUD.m_scrinfo.iCharHeight);
+
+
+ m_parms.y = YPosition( pMessage->y, m_parms.totalHeight );
+ pText = pMessage->pMessage;
+
+ m_parms.charTime = 0;
+
+ MessageScanStart();
+
+ for ( i = 0; i < m_parms.lines; i++ )
+ {
+ m_parms.lineLength = 0;
+ m_parms.width = 0;
+ while ( *pText && *pText != '\n' )
+ {
+ unsigned char c = *pText;
+ line[m_parms.lineLength] = c;
+ m_parms.width += gHUD.m_scrinfo.charWidths[c];
+ m_parms.lineLength++;
+ pText++;
+ }
+ pText++; // Skip LF
+ line[m_parms.lineLength] = 0;
+
+ m_parms.x = XPosition( pMessage->x, m_parms.width, m_parms.totalWidth );
+
+ for ( j = 0; j < m_parms.lineLength; j++ )
+ {
+ m_parms.text = line[j];
+ int next = m_parms.x + gHUD.m_scrinfo.charWidths[ m_parms.text ];
+ MessageScanNextChar();
+
+ if ( m_parms.x >= 0 && m_parms.y >= 0 && next <= ScreenWidth() )
+ TextMessageDrawChar( m_parms.x, m_parms.y, m_parms.text, m_parms.r, m_parms.g, m_parms.b );
+ m_parms.x = next;
+ }
+
+ m_parms.y += gHUD.m_scrinfo.iCharHeight;
+ }
+}
+
+
+int CHudMessage::Draw( float fTime )
+{
+ int i, drawn;
+ client_textmessage_t *pMessage;
+
+ drawn = 0;
+
+ if ( m_gameTitleTime > 0 )
+ {
+ float localTime = gHUD.m_flTime - m_gameTitleTime;
+ float brightness;
+
+ // Maybe timer isn't set yet
+ if ( m_gameTitleTime > gHUD.m_flTime )
+ m_gameTitleTime = gHUD.m_flTime;
+
+ if ( localTime > (m_pGameTitle->fadein + m_pGameTitle->holdtime + m_pGameTitle->fadeout) )
+ m_gameTitleTime = 0;
+ else
+ {
+ brightness = FadeBlend( m_pGameTitle->fadein, m_pGameTitle->fadeout, m_pGameTitle->holdtime, localTime );
+
+ int halfWidth = gHUD.GetSpriteRect(m_HUD_title_half).right - gHUD.GetSpriteRect(m_HUD_title_half).left;
+ int fullWidth = halfWidth + gHUD.GetSpriteRect(m_HUD_title_life).right - gHUD.GetSpriteRect(m_HUD_title_life).left;
+ int fullHeight = gHUD.GetSpriteRect(m_HUD_title_half).bottom - gHUD.GetSpriteRect(m_HUD_title_half).top;
+
+ int x = XPosition( m_pGameTitle->x, fullWidth, fullWidth );
+ int y = YPosition( m_pGameTitle->y, fullHeight );
+
+
+ SPR_Set( gHUD.GetSprite(m_HUD_title_half), brightness * m_pGameTitle->r1, brightness * m_pGameTitle->g1, brightness * m_pGameTitle->b1 );
+ SPR_DrawAdditive( 0, x, y, &gHUD.GetSpriteRect(m_HUD_title_half) );
+
+ SPR_Set( gHUD.GetSprite(m_HUD_title_life), brightness * m_pGameTitle->r1, brightness * m_pGameTitle->g1, brightness * m_pGameTitle->b1 );
+ SPR_DrawAdditive( 0, x + halfWidth, y, &gHUD.GetSpriteRect(m_HUD_title_life) );
+
+ drawn++;
+ }
+ }
+
+ // Draw player id
+// if(this->mPlayerIDTime > 0)
+// {
+// float localTime = gHUD.m_flTime - this->mPlayerIDTime;
+// //float brightness;
+//
+// // Maybe timer isn't set yet
+// if ( this->mPlayerIDTime > gHUD.m_flTime )
+// this->mPlayerIDTime = gHUD.m_flTime;
+//
+// if ( localTime > (this->mPlayerIDMessage.fadein + this->mPlayerIDMessage.holdtime + this->mPlayerIDMessage.fadeout) )
+// {
+// this->mPlayerIDTime = 0;
+// this->mPlayerIDMessage.pName = NULL;
+// this->mPlayerIDMessage.pMessage = NULL;
+// }
+// else
+// {
+// drawn++;
+// }
+// }
+
+ // Fixup level transitions
+ for ( i = 0; i < maxHUDMessages; i++ )
+ {
+ // Assume m_parms.time contains last time
+ if ( m_pMessages[i] )
+ {
+ pMessage = m_pMessages[i];
+ if ( m_startTime[i] > gHUD.m_flTime )
+ m_startTime[i] = gHUD.m_flTime + m_parms.time - m_startTime[i] + 0.2; // Server takes 0.2 seconds to spawn, adjust for this
+ }
+ }
+
+ for ( i = 0; i < maxHUDMessages; i++ )
+ {
+ client_textmessage_t* theMessage = this->m_pMessages[i];
+ if(theMessage)
+ {
+ if(this->DrawMessage(theMessage, this->m_startTime[i], fTime))
+ {
+ drawn++;
+ }
+ else
+ {
+ // The message is over
+ this->m_pMessages[i] = NULL;
+ }
+ }
+ }
+
+ if(this->DrawMessage(&this->mPlayerIDMessage, this->mPlayerIDTime, fTime))
+ {
+ drawn++;
+ }
+ else
+ {
+ this->mPlayerIDMessage.pName = NULL;
+ this->mPlayerIDMessage.pMessage = NULL;
+ }
+
+
+ // Remember the time -- to fix up level transitions
+ m_parms.time = gHUD.m_flTime;
+ // Don't call until we get another message
+ if ( !drawn )
+ m_iFlags &= ~HUD_ACTIVE;
+
+ return 1;
+}
+
+bool CHudMessage::DrawMessage(client_textmessage_t* inMessage, float inStartTime, float inCurrentTime)
+{
+ ASSERT(inMessage);
+ bool theDrewMessage = false;
+
+ if(inMessage->pMessage)
+ {
+ float endTime;
+
+ // This is when the message is over
+ switch( inMessage->effect )
+ {
+ case 0:
+ case 1:
+ endTime = inStartTime + inMessage->fadein + inMessage->fadeout + inMessage->holdtime;
+ break;
+
+ // Fade in is per character in scanning messages
+ case 2:
+ endTime = inStartTime + (inMessage->fadein * strlen( inMessage->pMessage )) + inMessage->fadeout + inMessage->holdtime;
+ break;
+ }
+
+ if ( inCurrentTime <= endTime )
+ {
+ float messageTime = inCurrentTime - inStartTime;
+
+ // Draw the message
+ // effect 0 is fade in/fade out
+ // effect 1 is flickery credits
+ // effect 2 is write out (training room)
+ MessageDrawScan( inMessage, messageTime );
+ theDrewMessage = true;
+ }
+ }
+
+ return theDrewMessage;
+}
+
+void CHudMessage::MessageAdd( const char *pName, float time )
+{
+ int i,j;
+ client_textmessage_t *tempMessage;
+
+ for ( i = 0; i < maxHUDMessages; i++ )
+ {
+ if ( !m_pMessages[i] )
+ {
+ // Trim off a leading # if it's there
+ if ( pName[0] == '#' )
+ tempMessage = TextMessageGet( pName+1 );
+ else
+ tempMessage = TextMessageGet( pName );
+ // If we couldnt find it in the titles.txt, just create it
+ if ( !tempMessage )
+ {
+ g_pCustomMessage.effect = 2;
+ g_pCustomMessage.r1 = g_pCustomMessage.g1 = g_pCustomMessage.b1 = g_pCustomMessage.a1 = 100;
+ g_pCustomMessage.r2 = 240;
+ g_pCustomMessage.g2 = 110;
+ g_pCustomMessage.b2 = 0;
+ g_pCustomMessage.a2 = 0;
+ g_pCustomMessage.x = -1; // Centered
+ g_pCustomMessage.y = 0.7;
+ g_pCustomMessage.fadein = 0.01;
+ g_pCustomMessage.fadeout = 1.5;
+ g_pCustomMessage.fxtime = 0.25;
+ g_pCustomMessage.holdtime = 5;
+ g_pCustomMessage.pName = g_pCustomName;
+ strcpy( g_pCustomText, pName );
+ g_pCustomMessage.pMessage = g_pCustomText;
+
+ tempMessage = &g_pCustomMessage;
+ }
+
+ for ( j = 0; j < maxHUDMessages; j++ )
+ {
+ if ( m_pMessages[j] )
+ {
+ // is this message already in the list
+ if ( !strcmp( tempMessage->pMessage, m_pMessages[j]->pMessage ) )
+ {
+ return;
+ }
+
+ // get rid of any other messages in same location (only one displays at a time)
+ if ( fabs( tempMessage->y - m_pMessages[j]->y ) < 0.0001 )
+ {
+ if ( fabs( tempMessage->x - m_pMessages[j]->x ) < 0.0001 )
+ {
+ m_pMessages[j] = NULL;
+ }
+ }
+ }
+ }
+
+ m_pMessages[i] = tempMessage;
+ m_startTime[i] = time;
+ return;
+ }
+ }
+}
+
+void CHudMessage::MessageAddPlayerID(const char* inName, bool inEnemy)
+{
+ // If we're already drawing this, extend the time
+ //if(inName && this->mPlayerIDMessage.pMessage && !strcmp(inName, this->mPlayerIDMessage.pMessage))
+ //{
+ // //this->mPlayerIDMessage.holdtime =
+ //}
+ //else
+ //{
+ // else add this message
+ this->mPlayerIDMessage.pMessage = inName;
+
+ //strcpy( g_pCustomText, pName );
+ //this->mPlayerIDMessage.pMessage = g_pCustomText;
+ this->mPlayerIDTime = gHUD.m_flTime;
+
+ // Set color depending on if friend or enemy
+ if(inEnemy)
+ {
+ this->mPlayerIDMessage.r1 = kEnemyRComp;
+ this->mPlayerIDMessage.g1 = kEnemyGComp;
+ this->mPlayerIDMessage.b1 = kEnemyBComp;
+ }
+ else
+ {
+ this->mPlayerIDMessage.r1 = kDefaultRComp;
+ this->mPlayerIDMessage.g1 = kDefaultGComp;
+ this->mPlayerIDMessage.b1 = kDefaultBComp;
+ }
+
+ this->SetPlayerIDPosition();
+
+ // Turn on drawing
+ if(inName)
+ {
+ if ( !(m_iFlags & HUD_ACTIVE) )
+ m_iFlags |= HUD_ACTIVE;
+ }
+
+ //}
+}
+
+bool CHudMessage::MessageRemove(const char *pName)
+{
+ const char* theMessage = pName;
+ bool theSuccess = false;
+ bool theNeedsTranslation = (pName[0] == '#');
+
+ // Trim off a leading # if it's there
+ if(theNeedsTranslation)
+ {
+ client_textmessage_t* tempMessage = TextMessageGet(pName + 1);
+ if(tempMessage)
+ {
+ theMessage = tempMessage->pMessage;
+ }
+ }
+
+ if(theMessage)
+ {
+ for (int j = 0; j < maxHUDMessages; j++ )
+ {
+ if ( m_pMessages[j] )
+ {
+ // is this message already in the list
+ if (!strcmp(theMessage, m_pMessages[j]->pMessage))
+ {
+ m_startTime[j] = -1;
+ theSuccess = true;
+ }
+ }
+ }
+ }
+ return theSuccess;
+}
+
+int CHudMessage::MsgFunc_HudText( const char *pszName, int iSize, void *pbuf )
+{
+ string content;
+
+ NetMsg_HudText( pbuf, iSize, content );
+ MessageAdd( content.c_str(), gHUD.m_flTime );
+
+ // Remember the time -- to fix up level transitions
+ m_parms.time = gHUD.m_flTime;
+
+ // Turn on drawing
+ if ( !(m_iFlags & HUD_ACTIVE) )
+ m_iFlags |= HUD_ACTIVE;
+
+ return 1;
+}
+
+int CHudMessage::MsgFunc_HudText2( const char *pszName, int iSize, void *pbuf )
+{
+ string content;
+ int flags;
+ NetMsg_HudText2( pbuf, iSize, content, flags );
+
+ switch (flags)
+ {
+ case 2:
+ gHUD.SetCenterText(content.c_str());
+ break;
+ default:
+ bool theIsAutoHelp = (flags & 1) != 0;
+ gHUD.AddTooltip(content.c_str(), theIsAutoHelp);
+ break;
+ }
+
+ return 2;
+}
+
+int CHudMessage::MsgFunc_GameTitle( const char *pszName, int iSize, void *pbuf )
+{
+ m_pGameTitle = TextMessageGet( "GAMETITLE" );
+ if ( m_pGameTitle != NULL )
+ {
+ m_gameTitleTime = gHUD.m_flTime;
+
+ // Turn on drawing
+ if ( !(m_iFlags & HUD_ACTIVE) )
+ m_iFlags |= HUD_ACTIVE;
+ }
+
+ return 1;
+}
diff --git a/main/source/cl_dll/overview.cpp b/main/source/cl_dll/overview.cpp
index 5b519f84..25157310 100644
--- a/main/source/cl_dll/overview.cpp
+++ b/main/source/cl_dll/overview.cpp
@@ -1,163 +1,163 @@
-//========= Copyright © 1996-2001, Valve LLC, All rights reserved. ============
-//
-// Purpose:
-//
-// $NoKeywords: $
-//=============================================================================
-
-#include "hud.h"
-#include "cl_util.h"
-#include "cl_entity.h"
-#include "triangleapi.h"
-#include "vgui_TeamFortressViewport.h"
-
-// these are included for the math functions
-#include "com_model.h"
-#include "studio_util.h"
-
-#include "MathUtil.h"
-#include "chudmisc.h"
-
-#pragma warning(disable: 4244)
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-int CHudOverview::Init()
-{
- gHUD.AddHudElem(this);
-
- m_iFlags |= HUD_ACTIVE;
-
- return 1;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Loads new icons
-//-----------------------------------------------------------------------------
-int CHudOverview::VidInit()
-{
- m_hsprPlayer = gEngfuncs.pfnSPR_Load("sprites/ring.spr");
- m_hsprViewcone = gEngfuncs.pfnSPR_Load("sprites/camera.spr");
-
- return 1;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-// Input : flTime -
-// intermission -
-//-----------------------------------------------------------------------------
-int CHudOverview::Draw(float flTime)
-{
- // only draw in overview mode
- if (!gEngfuncs.Overview_GetOverviewState())
- return 1;
-
- // make sure we have player info
- gViewPort->GetAllPlayersInfo();
-
- // calculate player size on the overview
- int x1, y1, x2, y2;
- float v0[3]={0,0,0}, v1[3]={64,64,0};
- gEngfuncs.Overview_WorldToScreen(v0, &x1, &y1);
- gEngfuncs.Overview_WorldToScreen(v1, &x2, &y2);
- float scale = abs(x2 - x1);
-
- // loop through all the players and draw them on the map
- for (int i = 1; i <= MAX_PLAYERS; i++)
- {
- cl_entity_t *pl = gEngfuncs.GetEntityByIndex(i);
-
- if (pl && pl->player && pl->curstate.health > 0 && pl->curstate.solid != SOLID_NOT)
- {
- int x, y, z = 0;
- float v[3]={pl->origin[0], pl->origin[1], 0};
- gEngfuncs.Overview_WorldToScreen(v, &x, &y);
-
- // hack in some team colors
- float r, g, bc;
- if (g_PlayerExtraInfo[i].teamnumber == 1)
- {
- r = 0.0f; g = 0.0f; bc = 1.0f;
- }
- else if (g_PlayerExtraInfo[i].teamnumber == 2)
- {
- r = 1.0f; g = 0.0f; bc = 0.0f;
- }
- else
- {
- // just use the default orange color if the team isn't set
- r = 1.0f; g = 0.7f; bc = 0.0f;
- }
-
- // set the current texture
- gEngfuncs.pTriAPI->SpriteTexture((struct model_s *)gEngfuncs.GetSpritePointer(m_hsprPlayer), 0);
-
- // additive render mode
- gEngfuncs.pTriAPI->RenderMode(kRenderTransAdd);
-
- // no culling
- gEngfuncs.pTriAPI->CullFace(TRI_NONE);
-
- // draw a square
- gEngfuncs.pTriAPI->Begin(TRI_QUADS);
-
- // set the color to be that of the team
- gEngfuncs.pTriAPI->Color4f(r, g, bc, 1.0f);
-
- // calculate rotational matrix
- vec3_t a, b, angles;
- float rmatrix[3][4]; // transformation matrix
- VectorCopy(pl->angles, angles);
- angles[0] = 0.0f;
- angles[1] += 90.f;
- angles[1] = -angles[1];
- angles[2] = 0.0f;
- AngleMatrix(angles, rmatrix);
- a[2] = 0;
-
- a[0] = -scale; a[1] = -scale;
- VectorTransform(a, rmatrix , b );
- gEngfuncs.pTriAPI->TexCoord2f( 0, 0 );
- gEngfuncs.pTriAPI->Vertex3f(x + b[0], y + b[1], z);
-
- a[0]=-scale; a[1] = scale;
- VectorTransform(a, rmatrix , b );
- gEngfuncs.pTriAPI->TexCoord2f( 0, 1 );
- gEngfuncs.pTriAPI->Vertex3f (x + b[0], y + b[1], z);
-
- a[0]=scale; a[1] = scale;
- VectorTransform(a, rmatrix , b );
- gEngfuncs.pTriAPI->TexCoord2f( 1, 1 );
- gEngfuncs.pTriAPI->Vertex3f (x + b[0], y + b[1], z);
-
- a[0]=scale; a[1] = -scale;
- VectorTransform(a, rmatrix , b );
- gEngfuncs.pTriAPI->TexCoord2f( 1, 0 );
- gEngfuncs.pTriAPI->Vertex3f (x + b[0], y + b[1], z);
-
- // finish up
- gEngfuncs.pTriAPI->End();
- gEngfuncs.pTriAPI->RenderMode( kRenderNormal );
-
- // draw the players name and health underneath
- char string[256];
- sprintf(string, "%s (%i%%)", g_PlayerInfoList[i].name, pl->curstate.health);
- DrawConsoleString(x, y + (1.1 * scale), string);
- }
- }
-
- return 1;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: called every time a server is connected to
-//-----------------------------------------------------------------------------
-void CHudOverview::InitHUDData()
-{
-// this block would force the spectator view to be on
-// gEngfuncs.Overview_SetDrawOverview( 1 );
-// gEngfuncs.Overview_SetDrawInset( 0 );
-}
-
+//========= Copyright © 1996-2001, Valve LLC, All rights reserved. ============
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================
+
+#include "hud.h"
+#include "cl_util.h"
+#include "cl_entity.h"
+#include "triangleapi.h"
+#include "vgui_TeamFortressViewport.h"
+
+// these are included for the math functions
+#include "com_model.h"
+#include "studio_util.h"
+
+#include "MathUtil.h"
+#include "chudmisc.h"
+
+#pragma warning(disable: 4244)
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+int CHudOverview::Init()
+{
+ gHUD.AddHudElem(this);
+
+ m_iFlags |= HUD_ACTIVE;
+
+ return 1;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Loads new icons
+//-----------------------------------------------------------------------------
+int CHudOverview::VidInit()
+{
+ m_hsprPlayer = gEngfuncs.pfnSPR_Load("sprites/ring.spr");
+ m_hsprViewcone = gEngfuncs.pfnSPR_Load("sprites/camera.spr");
+
+ return 1;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : flTime -
+// intermission -
+//-----------------------------------------------------------------------------
+int CHudOverview::Draw(float flTime)
+{
+ // only draw in overview mode
+ if (!gEngfuncs.Overview_GetOverviewState())
+ return 1;
+
+ // make sure we have player info
+ gViewPort->GetAllPlayersInfo();
+
+ // calculate player size on the overview
+ int x1, y1, x2, y2;
+ float v0[3]={0,0,0}, v1[3]={64,64,0};
+ gEngfuncs.Overview_WorldToScreen(v0, &x1, &y1);
+ gEngfuncs.Overview_WorldToScreen(v1, &x2, &y2);
+ float scale = abs(x2 - x1);
+
+ // loop through all the players and draw them on the map
+ for (int i = 1; i <= MAX_PLAYERS; i++)
+ {
+ cl_entity_t *pl = gEngfuncs.GetEntityByIndex(i);
+
+ if (pl && pl->player && pl->curstate.health > 0 && pl->curstate.solid != SOLID_NOT)
+ {
+ int x, y, z = 0;
+ float v[3]={pl->origin[0], pl->origin[1], 0};
+ gEngfuncs.Overview_WorldToScreen(v, &x, &y);
+
+ // hack in some team colors
+ float r, g, bc;
+ if (g_PlayerExtraInfo[i].teamnumber == 1)
+ {
+ r = 0.0f; g = 0.0f; bc = 1.0f;
+ }
+ else if (g_PlayerExtraInfo[i].teamnumber == 2)
+ {
+ r = 1.0f; g = 0.0f; bc = 0.0f;
+ }
+ else
+ {
+ // just use the default orange color if the team isn't set
+ r = 1.0f; g = 0.7f; bc = 0.0f;
+ }
+
+ // set the current texture
+ gEngfuncs.pTriAPI->SpriteTexture((struct model_s *)gEngfuncs.GetSpritePointer(m_hsprPlayer), 0);
+
+ // additive render mode
+ gEngfuncs.pTriAPI->RenderMode(kRenderTransAdd);
+
+ // no culling
+ gEngfuncs.pTriAPI->CullFace(TRI_NONE);
+
+ // draw a square
+ gEngfuncs.pTriAPI->Begin(TRI_QUADS);
+
+ // set the color to be that of the team
+ gEngfuncs.pTriAPI->Color4f(r, g, bc, 1.0f);
+
+ // calculate rotational matrix
+ vec3_t a, b, angles;
+ float rmatrix[3][4]; // transformation matrix
+ VectorCopy(pl->angles, angles);
+ angles[0] = 0.0f;
+ angles[1] += 90.f;
+ angles[1] = -angles[1];
+ angles[2] = 0.0f;
+ AngleMatrix(angles, rmatrix);
+ a[2] = 0;
+
+ a[0] = -scale; a[1] = -scale;
+ VectorTransform(a, rmatrix , b );
+ gEngfuncs.pTriAPI->TexCoord2f( 0, 0 );
+ gEngfuncs.pTriAPI->Vertex3f(x + b[0], y + b[1], z);
+
+ a[0]=-scale; a[1] = scale;
+ VectorTransform(a, rmatrix , b );
+ gEngfuncs.pTriAPI->TexCoord2f( 0, 1 );
+ gEngfuncs.pTriAPI->Vertex3f (x + b[0], y + b[1], z);
+
+ a[0]=scale; a[1] = scale;
+ VectorTransform(a, rmatrix , b );
+ gEngfuncs.pTriAPI->TexCoord2f( 1, 1 );
+ gEngfuncs.pTriAPI->Vertex3f (x + b[0], y + b[1], z);
+
+ a[0]=scale; a[1] = -scale;
+ VectorTransform(a, rmatrix , b );
+ gEngfuncs.pTriAPI->TexCoord2f( 1, 0 );
+ gEngfuncs.pTriAPI->Vertex3f (x + b[0], y + b[1], z);
+
+ // finish up
+ gEngfuncs.pTriAPI->End();
+ gEngfuncs.pTriAPI->RenderMode( kRenderNormal );
+
+ // draw the players name and health underneath
+ char string[256];
+ sprintf(string, "%s (%i%%)", g_PlayerInfoList[i].name, pl->curstate.health);
+ DrawConsoleString(x, y + (1.1 * scale), string);
+ }
+ }
+
+ return 1;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: called every time a server is connected to
+//-----------------------------------------------------------------------------
+void CHudOverview::InitHUDData()
+{
+// this block would force the spectator view to be on
+// gEngfuncs.Overview_SetDrawOverview( 1 );
+// gEngfuncs.Overview_SetDrawInset( 0 );
+}
+
diff --git a/main/source/cl_dll/overview.h b/main/source/cl_dll/overview.h
index 40e13d27..b4fdbc6b 100644
--- a/main/source/cl_dll/overview.h
+++ b/main/source/cl_dll/overview.h
@@ -1,30 +1,30 @@
-//========= Copyright © 1996-2001, Valve LLC, All rights reserved. ============
-//
-// Purpose:
-//
-// $NoKeywords: $
-//=============================================================================
-
-#ifndef OVERVIEW_H
-#define OVERVIEW_H
-#pragma once
-
-//-----------------------------------------------------------------------------
-// Purpose: Handles the drawing of the top-down map and all the things on it
-//-----------------------------------------------------------------------------
-class CHudOverview : public CHudBase
-{
-public:
- int Init();
- int VidInit();
-
- int Draw(float flTime);
- void InitHUDData( void );
-
-private:
- HSPRITE m_hsprPlayer;
- HSPRITE m_hsprViewcone;
-};
-
-
-#endif // OVERVIEW_H
+//========= Copyright © 1996-2001, Valve LLC, All rights reserved. ============
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================
+
+#ifndef OVERVIEW_H
+#define OVERVIEW_H
+#pragma once
+
+//-----------------------------------------------------------------------------
+// Purpose: Handles the drawing of the top-down map and all the things on it
+//-----------------------------------------------------------------------------
+class CHudOverview : public CHudBase
+{
+public:
+ int Init();
+ int VidInit();
+
+ int Draw(float flTime);
+ void InitHUDData( void );
+
+private:
+ HSPRITE m_hsprPlayer;
+ HSPRITE m_hsprViewcone;
+};
+
+
+#endif // OVERVIEW_H
diff --git a/main/source/cl_dll/parsemsg.cpp b/main/source/cl_dll/parsemsg.cpp
index d7070de5..871140a9 100644
--- a/main/source/cl_dll/parsemsg.cpp
+++ b/main/source/cl_dll/parsemsg.cpp
@@ -1,166 +1,166 @@
-/***
-*
-* Copyright (c) 1999, Valve LLC. All rights reserved.
-*
-* This product contains software technology licensed from Id
-* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
-* All Rights Reserved.
-*
-* Use, distribution, and modification of this source code and/or resulting
-* object code is restricted to non-commercial enhancements to products from
-* Valve LLC. All other use, distribution, or modification is prohibited
-* without written permission from Valve LLC.
-*
-****/
-//
-// parsemsg.cpp
-//
-typedef unsigned char byte;
-#define true 1
-
-static byte *gpBuf;
-static int giSize;
-static int giRead;
-static int giBadRead;
-
-void BEGIN_READ( void *buf, int size )
-{
- giRead = 0;
- giBadRead = 0;
- giSize = size;
- gpBuf = (byte*)buf;
-}
-
-
-int READ_CHAR( void )
-{
- int c;
-
- if (giRead + 1 > giSize)
- {
- giBadRead = true;
- return -1;
- }
-
- c = (signed char)gpBuf[giRead];
- giRead++;
-
- return c;
-}
-
-int READ_BYTE( void )
-{
- int c;
-
- if (giRead+1 > giSize)
- {
- giBadRead = true;
- return -1;
- }
-
- c = (unsigned char)gpBuf[giRead];
- giRead++;
-
- return c;
-}
-
-int READ_SHORT( void )
-{
- int c;
-
- if (giRead+2 > giSize)
- {
- giBadRead = true;
- return -1;
- }
-
- c = (short)( gpBuf[giRead] + ( gpBuf[giRead+1] << 8 ) );
-
- giRead += 2;
-
- return c;
-}
-
-int READ_WORD( void )
-{
- return READ_SHORT();
-}
-
-
-int READ_LONG( void )
-{
- int c;
-
- if (giRead+4 > giSize)
- {
- giBadRead = true;
- return -1;
- }
-
- c = gpBuf[giRead] + (gpBuf[giRead + 1] << 8) + (gpBuf[giRead + 2] << 16) + (gpBuf[giRead + 3] << 24);
-
- giRead += 4;
-
- return c;
-}
-
-float READ_FLOAT( void )
-{
- union
- {
- byte b[4];
- float f;
- int l;
- } dat;
-
- dat.b[0] = gpBuf[giRead];
- dat.b[1] = gpBuf[giRead+1];
- dat.b[2] = gpBuf[giRead+2];
- dat.b[3] = gpBuf[giRead+3];
- giRead += 4;
-
-// dat.l = LittleLong (dat.l);
-
- return dat.f;
-}
-
-char* READ_STRING( void )
-{
- static char string[2048];
- int l,c;
-
- string[0] = 0;
-
- l = 0;
- do
- {
- if ( giRead+1 > giSize )
- break; // no more characters
-
- c = READ_CHAR();
- if (c == -1 || c == 0)
- break;
- string[l] = c;
- l++;
- } while (l < sizeof(string)-1);
-
- string[l] = 0;
-
- return string;
-}
-
-float READ_COORD( void )
-{
- return (float)(READ_SHORT() * (1.0/8));
-}
-
-float READ_ANGLE( void )
-{
- return (float)(READ_CHAR() * (360.0/256));
-}
-
-float READ_HIRESANGLE( void )
-{
- return (float)(READ_SHORT() * (360.0/65536));
-}
-
+/***
+*
+* Copyright (c) 1999, Valve LLC. All rights reserved.
+*
+* This product contains software technology licensed from Id
+* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
+* All Rights Reserved.
+*
+* Use, distribution, and modification of this source code and/or resulting
+* object code is restricted to non-commercial enhancements to products from
+* Valve LLC. All other use, distribution, or modification is prohibited
+* without written permission from Valve LLC.
+*
+****/
+//
+// parsemsg.cpp
+//
+typedef unsigned char byte;
+#define true 1
+
+static byte *gpBuf;
+static int giSize;
+static int giRead;
+static int giBadRead;
+
+void BEGIN_READ( void *buf, int size )
+{
+ giRead = 0;
+ giBadRead = 0;
+ giSize = size;
+ gpBuf = (byte*)buf;
+}
+
+
+int READ_CHAR( void )
+{
+ int c;
+
+ if (giRead + 1 > giSize)
+ {
+ giBadRead = true;
+ return -1;
+ }
+
+ c = (signed char)gpBuf[giRead];
+ giRead++;
+
+ return c;
+}
+
+int READ_BYTE( void )
+{
+ int c;
+
+ if (giRead+1 > giSize)
+ {
+ giBadRead = true;
+ return -1;
+ }
+
+ c = (unsigned char)gpBuf[giRead];
+ giRead++;
+
+ return c;
+}
+
+int READ_SHORT( void )
+{
+ int c;
+
+ if (giRead+2 > giSize)
+ {
+ giBadRead = true;
+ return -1;
+ }
+
+ c = (short)( gpBuf[giRead] + ( gpBuf[giRead+1] << 8 ) );
+
+ giRead += 2;
+
+ return c;
+}
+
+int READ_WORD( void )
+{
+ return READ_SHORT();
+}
+
+
+int READ_LONG( void )
+{
+ int c;
+
+ if (giRead+4 > giSize)
+ {
+ giBadRead = true;
+ return -1;
+ }
+
+ c = gpBuf[giRead] + (gpBuf[giRead + 1] << 8) + (gpBuf[giRead + 2] << 16) + (gpBuf[giRead + 3] << 24);
+
+ giRead += 4;
+
+ return c;
+}
+
+float READ_FLOAT( void )
+{
+ union
+ {
+ byte b[4];
+ float f;
+ int l;
+ } dat;
+
+ dat.b[0] = gpBuf[giRead];
+ dat.b[1] = gpBuf[giRead+1];
+ dat.b[2] = gpBuf[giRead+2];
+ dat.b[3] = gpBuf[giRead+3];
+ giRead += 4;
+
+// dat.l = LittleLong (dat.l);
+
+ return dat.f;
+}
+
+char* READ_STRING( void )
+{
+ static char string[2048];
+ int l,c;
+
+ string[0] = 0;
+
+ l = 0;
+ do
+ {
+ if ( giRead+1 > giSize )
+ break; // no more characters
+
+ c = READ_CHAR();
+ if (c == -1 || c == 0)
+ break;
+ string[l] = c;
+ l++;
+ } while (l < sizeof(string)-1);
+
+ string[l] = 0;
+
+ return string;
+}
+
+float READ_COORD( void )
+{
+ return (float)(READ_SHORT() * (1.0/8));
+}
+
+float READ_ANGLE( void )
+{
+ return (float)(READ_CHAR() * (360.0/256));
+}
+
+float READ_HIRESANGLE( void )
+{
+ return (float)(READ_SHORT() * (360.0/65536));
+}
+
diff --git a/main/source/cl_dll/parsemsg.h b/main/source/cl_dll/parsemsg.h
index 382ac58a..d586facf 100644
--- a/main/source/cl_dll/parsemsg.h
+++ b/main/source/cl_dll/parsemsg.h
@@ -1,40 +1,40 @@
-/***
-*
-* Copyright (c) 1999, Valve LLC. All rights reserved.
-*
-* This product contains software technology licensed from Id
-* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
-* All Rights Reserved.
-*
-* Use, distribution, and modification of this source code and/or resulting
-* object code is restricted to non-commercial enhancements to products from
-* Valve LLC. All other use, distribution, or modification is prohibited
-* without written permission from Valve LLC.
-*
-****/
-//
-// parsemsg.h
-//
-
-//#define ASSERT( x )
-
-void BEGIN_READ( void *buf, int size );
-int READ_CHAR( void );
-int READ_BYTE( void );
-int READ_SHORT( void );
-int READ_WORD( void );
-int READ_LONG( void );
-float READ_FLOAT( void );
-char* READ_STRING( void );
-float READ_COORD( void );
-float READ_ANGLE( void );
-float READ_HIRESANGLE( void );
-
-
-
-
-
-
-
-
-
+/***
+*
+* Copyright (c) 1999, Valve LLC. All rights reserved.
+*
+* This product contains software technology licensed from Id
+* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
+* All Rights Reserved.
+*
+* Use, distribution, and modification of this source code and/or resulting
+* object code is restricted to non-commercial enhancements to products from
+* Valve LLC. All other use, distribution, or modification is prohibited
+* without written permission from Valve LLC.
+*
+****/
+//
+// parsemsg.h
+//
+
+//#define ASSERT( x )
+
+void BEGIN_READ( void *buf, int size );
+int READ_CHAR( void );
+int READ_BYTE( void );
+int READ_SHORT( void );
+int READ_WORD( void );
+int READ_LONG( void );
+float READ_FLOAT( void );
+char* READ_STRING( void );
+float READ_COORD( void );
+float READ_ANGLE( void );
+float READ_HIRESANGLE( void );
+
+
+
+
+
+
+
+
+
diff --git a/main/source/cl_dll/r_studioint.h b/main/source/cl_dll/r_studioint.h
index 973ae182..1ff470cf 100644
--- a/main/source/cl_dll/r_studioint.h
+++ b/main/source/cl_dll/r_studioint.h
@@ -1,108 +1,108 @@
-#if !defined( R_STUDIOINT_H )
-#define R_STUDIOINT_H
-#if defined( _WIN32 )
-#pragma once
-#endif
-
-#define STUDIO_INTERFACE_VERSION 1
-
-typedef struct engine_studio_api_s
-{
- // Allocate number*size bytes and zero it
- void *( *Mem_Calloc ) ( int number, size_t size );
- // Check to see if pointer is in the cache
- void *( *Cache_Check ) ( struct cache_user_s *c );
- // Load file into cache ( can be swapped out on demand )
- void ( *LoadCacheFile ) ( char *path, struct cache_user_s *cu );
- // Retrieve model pointer for the named model
- struct model_s *( *Mod_ForName ) ( const char *name, int crash_if_missing );
- // Retrieve pointer to studio model data block from a model
- void *( *Mod_Extradata ) ( struct model_s *mod );
- // Retrieve indexed model from client side model precache list
- struct model_s *( *GetModelByIndex ) ( int index );
- // Get entity that is set for rendering
- struct cl_entity_s * ( *GetCurrentEntity ) ( void );
- // Get referenced player_info_t
- struct player_info_s *( *PlayerInfo ) ( int index );
- // Get most recently received player state data from network system
- struct entity_state_s *( *GetPlayerState ) ( int index );
- // Get viewentity
- struct cl_entity_s * ( *GetViewEntity ) ( void );
- // Get current frame count, and last two timestampes on client
- void ( *GetTimes ) ( int *framecount, double *current, double *old );
- // Get a pointer to a cvar by name
- struct cvar_s *( *GetCvar ) ( const char *name );
- // Get current render origin and view vectors ( up, right and vpn )
- void ( *GetViewInfo ) ( float *origin, float *upv, float *rightv, float *vpnv );
- // Get sprite model used for applying chrome effect
- struct model_s *( *GetChromeSprite ) ( void );
- // Get model counters so we can incement instrumentation
- void ( *GetModelCounters ) ( int **s, int **a );
- // Get software scaling coefficients
- void ( *GetAliasScale ) ( float *x, float *y );
-
- // Get bone, light, alias, and rotation matrices
- float ****( *StudioGetBoneTransform ) ( void );
- float ****( *StudioGetLightTransform )( void );
- float ***( *StudioGetAliasTransform ) ( void );
- float ***( *StudioGetRotationMatrix ) ( void );
-
- // Set up body part, and get submodel pointers
- void ( *StudioSetupModel ) ( int bodypart, void **ppbodypart, void **ppsubmodel );
- // Check if entity's bbox is in the view frustum
- int ( *StudioCheckBBox ) ( void );
- // Apply lighting effects to model
- void ( *StudioDynamicLight ) ( struct cl_entity_s *ent, struct alight_s *plight );
- void ( *StudioEntityLight ) ( struct alight_s *plight );
- void ( *StudioSetupLighting ) ( struct alight_s *plighting );
-
- // Draw mesh vertices
- void ( *StudioDrawPoints ) ( void );
-
- // Draw hulls around bones
- void ( *StudioDrawHulls ) ( void );
- // Draw bbox around studio models
- void ( *StudioDrawAbsBBox ) ( void );
- // Draws bones
- void ( *StudioDrawBones ) ( void );
- // Loads in appropriate texture for model
- void ( *StudioSetupSkin ) ( void *ptexturehdr, int index );
- // Sets up for remapped colors
- void ( *StudioSetRemapColors ) ( int top, int bottom );
- // Set's player model and returns model pointer
- struct model_s *( *SetupPlayerModel ) ( int index );
- // Fires any events embedded in animation
- void ( *StudioClientEvents ) ( void );
- // Retrieve/set forced render effects flags
- int ( *GetForceFaceFlags ) ( void );
- void ( *SetForceFaceFlags ) ( int flags );
- // Tell engine the value of the studio model header
- void ( *StudioSetHeader ) ( void *header );
- // Tell engine which model_t * is being renderered
- void ( *SetRenderModel ) ( struct model_s *model );
-
- // Final state setup and restore for rendering
- void ( *SetupRenderer ) ( int rendermode );
- void ( *RestoreRenderer ) ( void );
-
- // Set render origin for applying chrome effect
- void ( *SetChromeOrigin ) ( void );
-
- // True if using D3D/OpenGL
- int ( *IsHardware ) ( void );
-
- // Only called by hardware interface
- void ( *GL_StudioDrawShadow ) ( void );
- void ( *GL_SetRenderMode ) ( int mode );
-} engine_studio_api_t;
-
-typedef struct r_studio_interface_s
-{
- int version;
- int ( *StudioDrawModel ) ( int flags );
- int ( *StudioDrawPlayer ) ( int flags, struct entity_state_s *pplayer );
-} r_studio_interface_t;
-
-extern r_studio_interface_t *pStudioAPI;
-
+#if !defined( R_STUDIOINT_H )
+#define R_STUDIOINT_H
+#if defined( _WIN32 )
+#pragma once
+#endif
+
+#define STUDIO_INTERFACE_VERSION 1
+
+typedef struct engine_studio_api_s
+{
+ // Allocate number*size bytes and zero it
+ void *( *Mem_Calloc ) ( int number, size_t size );
+ // Check to see if pointer is in the cache
+ void *( *Cache_Check ) ( struct cache_user_s *c );
+ // Load file into cache ( can be swapped out on demand )
+ void ( *LoadCacheFile ) ( char *path, struct cache_user_s *cu );
+ // Retrieve model pointer for the named model
+ struct model_s *( *Mod_ForName ) ( const char *name, int crash_if_missing );
+ // Retrieve pointer to studio model data block from a model
+ void *( *Mod_Extradata ) ( struct model_s *mod );
+ // Retrieve indexed model from client side model precache list
+ struct model_s *( *GetModelByIndex ) ( int index );
+ // Get entity that is set for rendering
+ struct cl_entity_s * ( *GetCurrentEntity ) ( void );
+ // Get referenced player_info_t
+ struct player_info_s *( *PlayerInfo ) ( int index );
+ // Get most recently received player state data from network system
+ struct entity_state_s *( *GetPlayerState ) ( int index );
+ // Get viewentity
+ struct cl_entity_s * ( *GetViewEntity ) ( void );
+ // Get current frame count, and last two timestampes on client
+ void ( *GetTimes ) ( int *framecount, double *current, double *old );
+ // Get a pointer to a cvar by name
+ struct cvar_s *( *GetCvar ) ( const char *name );
+ // Get current render origin and view vectors ( up, right and vpn )
+ void ( *GetViewInfo ) ( float *origin, float *upv, float *rightv, float *vpnv );
+ // Get sprite model used for applying chrome effect
+ struct model_s *( *GetChromeSprite ) ( void );
+ // Get model counters so we can incement instrumentation
+ void ( *GetModelCounters ) ( int **s, int **a );
+ // Get software scaling coefficients
+ void ( *GetAliasScale ) ( float *x, float *y );
+
+ // Get bone, light, alias, and rotation matrices
+ float ****( *StudioGetBoneTransform ) ( void );
+ float ****( *StudioGetLightTransform )( void );
+ float ***( *StudioGetAliasTransform ) ( void );
+ float ***( *StudioGetRotationMatrix ) ( void );
+
+ // Set up body part, and get submodel pointers
+ void ( *StudioSetupModel ) ( int bodypart, void **ppbodypart, void **ppsubmodel );
+ // Check if entity's bbox is in the view frustum
+ int ( *StudioCheckBBox ) ( void );
+ // Apply lighting effects to model
+ void ( *StudioDynamicLight ) ( struct cl_entity_s *ent, struct alight_s *plight );
+ void ( *StudioEntityLight ) ( struct alight_s *plight );
+ void ( *StudioSetupLighting ) ( struct alight_s *plighting );
+
+ // Draw mesh vertices
+ void ( *StudioDrawPoints ) ( void );
+
+ // Draw hulls around bones
+ void ( *StudioDrawHulls ) ( void );
+ // Draw bbox around studio models
+ void ( *StudioDrawAbsBBox ) ( void );
+ // Draws bones
+ void ( *StudioDrawBones ) ( void );
+ // Loads in appropriate texture for model
+ void ( *StudioSetupSkin ) ( void *ptexturehdr, int index );
+ // Sets up for remapped colors
+ void ( *StudioSetRemapColors ) ( int top, int bottom );
+ // Set's player model and returns model pointer
+ struct model_s *( *SetupPlayerModel ) ( int index );
+ // Fires any events embedded in animation
+ void ( *StudioClientEvents ) ( void );
+ // Retrieve/set forced render effects flags
+ int ( *GetForceFaceFlags ) ( void );
+ void ( *SetForceFaceFlags ) ( int flags );
+ // Tell engine the value of the studio model header
+ void ( *StudioSetHeader ) ( void *header );
+ // Tell engine which model_t * is being renderered
+ void ( *SetRenderModel ) ( struct model_s *model );
+
+ // Final state setup and restore for rendering
+ void ( *SetupRenderer ) ( int rendermode );
+ void ( *RestoreRenderer ) ( void );
+
+ // Set render origin for applying chrome effect
+ void ( *SetChromeOrigin ) ( void );
+
+ // True if using D3D/OpenGL
+ int ( *IsHardware ) ( void );
+
+ // Only called by hardware interface
+ void ( *GL_StudioDrawShadow ) ( void );
+ void ( *GL_SetRenderMode ) ( int mode );
+} engine_studio_api_t;
+
+typedef struct r_studio_interface_s
+{
+ int version;
+ int ( *StudioDrawModel ) ( int flags );
+ int ( *StudioDrawPlayer ) ( int flags, struct entity_state_s *pplayer );
+} r_studio_interface_t;
+
+extern r_studio_interface_t *pStudioAPI;
+
#endif // R_STUDIOINT_H
\ No newline at end of file
diff --git a/main/source/cl_dll/saytext.cpp b/main/source/cl_dll/saytext.cpp
index db8abb30..973d2b14 100644
--- a/main/source/cl_dll/saytext.cpp
+++ b/main/source/cl_dll/saytext.cpp
@@ -1,379 +1,379 @@
-/***
-*
-* Copyright (c) 1999, Valve LLC. All rights reserved.
-*
-* This product contains software technology licensed from Id
-* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
-* All Rights Reserved.
-*
-* Use, distribution, and modification of this source code and/or resulting
-* object code is restricted to non-commercial enhancements to products from
-* Valve LLC. All other use, distribution, or modification is prohibited
-* without written permission from Valve LLC.
-*
-****/
-//
-// saytext.cpp
-//
-// implementation of CHudSayText class
-//
-
-#include "hud.h"
-#include "cl_util.h"
-#include "mod/AvHNetworkMessages.h"
-
-#include
-#include
-
-#include "vgui_TeamFortressViewport.h"
-#include "mod/AvHClientUtil.h"
-#include "ui/ChatPanel.h"
-
-float* GetClientColor(int clientIndex);
-
-#define MAX_LINES 5
-#define MAX_CHARS_PER_LINE 256 /* it can be less than this, depending on char size */
-
-// allow 20 pixels on either side of the text
-#define MAX_LINE_WIDTH ( ScreenWidth() - 40 )
-#define LINE_START 10
-static float SCROLL_SPEED = 5;
-
-static char g_szLineBuffer[ MAX_LINES + 1 ][ MAX_CHARS_PER_LINE ];
-static float *g_pflNameColors[ MAX_LINES + 1 ];
-static int g_iNameLengths[ MAX_LINES + 1 ];
-static float flScrollTime = 0; // the time at which the lines next scroll up
-
-static int Y_START = 0;
-static int line_height = 0;
-
-DECLARE_MESSAGE( m_SayText, SayText );
-
-int CHudSayText :: Init( void )
-{
- gHUD.AddHudElem( this );
-
- HOOK_MESSAGE( SayText );
-
- InitHUDData();
-
- m_HUD_saytext = gEngfuncs.pfnRegisterVariable( "hud_saytext", "1", 0 );
- m_HUD_saytext_time = gEngfuncs.pfnRegisterVariable( "hud_saytext_time", "5", 0 );
-
- m_iFlags |= HUD_INTERMISSION; // is always drawn during an intermission
-
- return 1;
-}
-
-
-void CHudSayText :: InitHUDData( void )
-{
- memset( g_szLineBuffer, 0, sizeof g_szLineBuffer );
- memset( g_pflNameColors, 0, sizeof g_pflNameColors );
- memset( g_iNameLengths, 0, sizeof g_iNameLengths );
-}
-
-int CHudSayText :: VidInit( void )
-{
- return 1;
-}
-
-
-int ScrollTextUp( void )
-{
- ConsolePrint( g_szLineBuffer[0] ); // move the first line into the console buffer
- g_szLineBuffer[MAX_LINES][0] = 0;
- memmove( g_szLineBuffer[0], g_szLineBuffer[1], sizeof(g_szLineBuffer) - sizeof(g_szLineBuffer[0]) ); // overwrite the first line
- memmove( &g_pflNameColors[0], &g_pflNameColors[1], sizeof(g_pflNameColors) - sizeof(g_pflNameColors[0]) );
- memmove( &g_iNameLengths[0], &g_iNameLengths[1], sizeof(g_iNameLengths) - sizeof(g_iNameLengths[0]) );
- g_szLineBuffer[MAX_LINES-1][0] = 0;
-
- if ( g_szLineBuffer[0][0] == ' ' ) // also scroll up following lines
- {
- g_szLineBuffer[0][0] = 2;
- return 1 + ScrollTextUp();
- }
-
- return 1;
-}
-
-int CHudSayText :: Draw( float flTime )
-{
- int y = Y_START;
-
- if ( ( gViewPort && gViewPort->AllowedToPrintText() == FALSE) || !m_HUD_saytext->value )
- return 1;
-
- // make sure the scrolltime is within reasonable bounds, to guard against the clock being reset
- flScrollTime = min( flScrollTime, flTime + m_HUD_saytext_time->value );
-
- // make sure the scrolltime is within reasonable bounds, to guard against the clock being reset
- flScrollTime = min( flScrollTime, flTime + m_HUD_saytext_time->value );
-
- if ( flScrollTime <= flTime )
- {
- if ( *g_szLineBuffer[0] )
- {
- flScrollTime = flTime + m_HUD_saytext_time->value;
- // push the console up
- ScrollTextUp();
- }
- else
- { // buffer is empty, just disable drawing of this section
- m_iFlags &= ~HUD_ACTIVE;
- }
- }
-
- for ( int i = 0; i < MAX_LINES; i++ )
- {
- if ( *g_szLineBuffer[i] )
- {
- if ( *g_szLineBuffer[i] == 2 && g_pflNameColors[i] )
- {
- // it's a saytext string
- static char buf[MAX_PLAYER_NAME_LENGTH+32];
-
- // draw the first x characters in the player color
- strncpy( buf, g_szLineBuffer[i], min(g_iNameLengths[i], MAX_PLAYER_NAME_LENGTH+32) );
- buf[ min(g_iNameLengths[i], MAX_PLAYER_NAME_LENGTH+31) ] = 0;
- DrawSetTextColor( g_pflNameColors[i][0], g_pflNameColors[i][1], g_pflNameColors[i][2] );
-
- // If we're an alien, move chat over a bit so it doesn't overlap energy bar
- int theDrawX = LINE_START;
- //if(gHUD.GetIsAlien())
- //{
- // theDrawX += .07f*ScreenWidth;
- //}
- int x = DrawConsoleString(theDrawX, y, buf );
-
- // color is reset after each string draw
- DrawConsoleString( x, y, g_szLineBuffer[i] + g_iNameLengths[i] );
- }
- else
- {
- // normal draw
- DrawConsoleString( LINE_START, y, g_szLineBuffer[i] );
- }
- }
-
- y += line_height;
- }
-
-
- return 1;
-}
-
-int CHudSayText :: MsgFunc_SayText( const char *pszName, int iSize, void *pbuf )
-{
-
- int client_index;
- string content, location;
- NetMsg_SayText( pbuf, iSize, client_index, content, location );
-
- string theTranslatedLocation;
- if(LocalizeString(location.c_str(), theTranslatedLocation))
- {
- // If player is on our team, add location
- cl_entity_s* theEntity = gEngfuncs.GetEntityByIndex(client_index);
- cl_entity_s* theLocalPlayer = gEngfuncs.GetLocalPlayer();
-
- if(theEntity && theLocalPlayer && (theEntity->curstate.team == theLocalPlayer->curstate.team))
- {
- // Search for first : so we can insert location
- int theColonIndex = (int)content.find_first_of(":");
- if((theColonIndex > 0) && (theColonIndex < (int)content.length()))
- {
- AvHCUTrimExtraneousLocationText(theTranslatedLocation);
-
- // Insert location
- string theNewMessage = content.substr(0, theColonIndex);
- theNewMessage += " (";
-
- theNewMessage += theTranslatedLocation;
- theNewMessage += ")";
- theNewMessage += content.substr(theColonIndex);
-
- // Replace the message with new one
- content = theNewMessage;
- }
- }
- }
-
- SayTextPrint(content.c_str(), (int)content.length(), client_index );
-
- return 1;
-}
-
-void CHudSayText :: SayTextPrint( const char *pszBuf, int iBufSize, int clientIndex )
-{
- if ( gViewPort && gViewPort->AllowedToPrintText() == FALSE )
- {
- // Print it straight to the console
- ConsolePrint( pszBuf );
- return;
- }
-
- // find an empty string slot
- int i = 0;
- for ( i = 0; i < MAX_LINES; i++ )
- {
- if ( ! *g_szLineBuffer[i] )
- break;
- }
- if ( i == MAX_LINES )
- {
- // force scroll buffer up
- ScrollTextUp();
- i = MAX_LINES - 1;
- }
-
- g_iNameLengths[i] = 0;
- g_pflNameColors[i] = NULL;
-
- // if it's a say message, search for the players name in the string
- if ( *pszBuf == 2 && clientIndex > 0 )
- {
- GetPlayerInfo( clientIndex, &g_PlayerInfoList[clientIndex] );
- const char *pName = g_PlayerInfoList[clientIndex].name;
-
- if ( pName )
- {
- const char *nameInString = strstr( pszBuf, pName );
-
- if ( nameInString )
- {
- g_iNameLengths[i] = (int)strlen( pName ) + (nameInString - pszBuf);
- g_pflNameColors[i] = GetClientColor(clientIndex);
- }
- }
- }
-
- // : 0001087
- // don't strip last character ( often resulted in no carriage returns in the log )
- strncpy( g_szLineBuffer[i], pszBuf, min(iBufSize, MAX_CHARS_PER_LINE-1) );
-
- // make sure the text fits in one line
- EnsureTextFitsInOneLineAndWrapIfHaveTo( i );
-
- // Set scroll time
- if ( i == 0 )
- {
- flScrollTime = gHUD.m_flTime + m_HUD_saytext_time->value;
- }
-
- m_iFlags |= HUD_ACTIVE;
- //PlaySound( "misc/talk.wav", 1 );
- gHUD.PlayHUDSound("misc/talk.wav", 1);
-
- Y_START = ScreenHeight()*.7f;
- /* @linux no chat panel
- ChatPanel* theChatPanel = gViewPort->GetChatPanel();
-
- if (theChatPanel != NULL)
- {
-
- int theX;
- int theY;
- int theWidth;
- int theHeight;
-
- gViewPort->GetChatPanel()->getPos(theX, theY);
- gViewPort->GetChatPanel()->getSize(theWidth, theHeight);
-
- //Y_START = theY + theHeight + 5; //: this is too high imo.
- //KGP: then move the viewport
- Y_START = theY + theHeight + 5;
- }
- */
-}
-
-void CHudSayText :: EnsureTextFitsInOneLineAndWrapIfHaveTo( int line )
-{
- int line_width = 0;
- GetConsoleStringSize( g_szLineBuffer[line], &line_width, &line_height );
-
- if ( (line_width + LINE_START) > MAX_LINE_WIDTH )
- { // string is too long to fit on line
- // scan the string until we find what word is too long, and wrap the end of the sentence after the word
- int length = LINE_START;
- int tmp_len = 0;
- char *last_break = NULL;
- for ( char *x = g_szLineBuffer[line]; *x != 0; x++ )
- {
- // check for a color change, if so skip past it
- if ( x[0] == '/' && x[1] == '(' )
- {
- x += 2;
- // skip forward until past mode specifier
- while ( *x != 0 && *x != ')' )
- x++;
-
- if ( *x != 0 )
- x++;
-
- if ( *x == 0 )
- break;
- }
-
- char buf[2];
- buf[1] = 0;
-
- if ( *x == ' ' && x != g_szLineBuffer[line] ) // store each line break, except for the very first character
- last_break = x;
-
- buf[0] = *x; // get the length of the current character
- GetConsoleStringSize( buf, &tmp_len, &line_height );
- length += tmp_len;
-
- if ( length > MAX_LINE_WIDTH )
- { // needs to be broken up
- if ( !last_break )
- last_break = x-1;
-
- x = last_break;
-
- // find an empty string slot
- int j;
- do
- {
- for ( j = 0; j < MAX_LINES; j++ )
- {
- if ( ! *g_szLineBuffer[j] )
- break;
- }
- if ( j == MAX_LINES )
- {
- // need to make more room to display text, scroll stuff up then fix the pointers
- int linesmoved = ScrollTextUp();
- line -= linesmoved;
- last_break = last_break - (sizeof(g_szLineBuffer[0]) * linesmoved);
- }
- }
- while ( j == MAX_LINES );
-
- // copy remaining string into next buffer, making sure it starts with a space character
- if ( (char)*last_break == (char)' ' )
- {
- int linelen = (int)strlen(g_szLineBuffer[j]);
- int remaininglen = (int)strlen(last_break);
-
- if ( (linelen - remaininglen) <= MAX_CHARS_PER_LINE )
- strcat( g_szLineBuffer[j], last_break );
- }
- else
- {
- if ( (strlen(g_szLineBuffer[j]) - strlen(last_break) - 2) < MAX_CHARS_PER_LINE )
- {
- strcat( g_szLineBuffer[j], " " );
- strcat( g_szLineBuffer[j], last_break );
- }
- }
-
- *last_break = 0; // cut off the last string
-
- EnsureTextFitsInOneLineAndWrapIfHaveTo( j );
- break;
- }
- }
- }
+/***
+*
+* Copyright (c) 1999, Valve LLC. All rights reserved.
+*
+* This product contains software technology licensed from Id
+* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
+* All Rights Reserved.
+*
+* Use, distribution, and modification of this source code and/or resulting
+* object code is restricted to non-commercial enhancements to products from
+* Valve LLC. All other use, distribution, or modification is prohibited
+* without written permission from Valve LLC.
+*
+****/
+//
+// saytext.cpp
+//
+// implementation of CHudSayText class
+//
+
+#include "hud.h"
+#include "cl_util.h"
+#include "mod/AvHNetworkMessages.h"
+
+#include
+#include
+
+#include "vgui_TeamFortressViewport.h"
+#include "mod/AvHClientUtil.h"
+#include "ui/ChatPanel.h"
+
+float* GetClientColor(int clientIndex);
+
+#define MAX_LINES 5
+#define MAX_CHARS_PER_LINE 256 /* it can be less than this, depending on char size */
+
+// allow 20 pixels on either side of the text
+#define MAX_LINE_WIDTH ( ScreenWidth() - 40 )
+#define LINE_START 10
+static float SCROLL_SPEED = 5;
+
+static char g_szLineBuffer[ MAX_LINES + 1 ][ MAX_CHARS_PER_LINE ];
+static float *g_pflNameColors[ MAX_LINES + 1 ];
+static int g_iNameLengths[ MAX_LINES + 1 ];
+static float flScrollTime = 0; // the time at which the lines next scroll up
+
+static int Y_START = 0;
+static int line_height = 0;
+
+DECLARE_MESSAGE( m_SayText, SayText );
+
+int CHudSayText :: Init( void )
+{
+ gHUD.AddHudElem( this );
+
+ HOOK_MESSAGE( SayText );
+
+ InitHUDData();
+
+ m_HUD_saytext = gEngfuncs.pfnRegisterVariable( "hud_saytext", "1", 0 );
+ m_HUD_saytext_time = gEngfuncs.pfnRegisterVariable( "hud_saytext_time", "5", 0 );
+
+ m_iFlags |= HUD_INTERMISSION; // is always drawn during an intermission
+
+ return 1;
+}
+
+
+void CHudSayText :: InitHUDData( void )
+{
+ memset( g_szLineBuffer, 0, sizeof g_szLineBuffer );
+ memset( g_pflNameColors, 0, sizeof g_pflNameColors );
+ memset( g_iNameLengths, 0, sizeof g_iNameLengths );
+}
+
+int CHudSayText :: VidInit( void )
+{
+ return 1;
+}
+
+
+int ScrollTextUp( void )
+{
+ ConsolePrint( g_szLineBuffer[0] ); // move the first line into the console buffer
+ g_szLineBuffer[MAX_LINES][0] = 0;
+ memmove( g_szLineBuffer[0], g_szLineBuffer[1], sizeof(g_szLineBuffer) - sizeof(g_szLineBuffer[0]) ); // overwrite the first line
+ memmove( &g_pflNameColors[0], &g_pflNameColors[1], sizeof(g_pflNameColors) - sizeof(g_pflNameColors[0]) );
+ memmove( &g_iNameLengths[0], &g_iNameLengths[1], sizeof(g_iNameLengths) - sizeof(g_iNameLengths[0]) );
+ g_szLineBuffer[MAX_LINES-1][0] = 0;
+
+ if ( g_szLineBuffer[0][0] == ' ' ) // also scroll up following lines
+ {
+ g_szLineBuffer[0][0] = 2;
+ return 1 + ScrollTextUp();
+ }
+
+ return 1;
+}
+
+int CHudSayText :: Draw( float flTime )
+{
+ int y = Y_START;
+
+ if ( ( gViewPort && gViewPort->AllowedToPrintText() == FALSE) || !m_HUD_saytext->value )
+ return 1;
+
+ // make sure the scrolltime is within reasonable bounds, to guard against the clock being reset
+ flScrollTime = min( flScrollTime, flTime + m_HUD_saytext_time->value );
+
+ // make sure the scrolltime is within reasonable bounds, to guard against the clock being reset
+ flScrollTime = min( flScrollTime, flTime + m_HUD_saytext_time->value );
+
+ if ( flScrollTime <= flTime )
+ {
+ if ( *g_szLineBuffer[0] )
+ {
+ flScrollTime = flTime + m_HUD_saytext_time->value;
+ // push the console up
+ ScrollTextUp();
+ }
+ else
+ { // buffer is empty, just disable drawing of this section
+ m_iFlags &= ~HUD_ACTIVE;
+ }
+ }
+
+ for ( int i = 0; i < MAX_LINES; i++ )
+ {
+ if ( *g_szLineBuffer[i] )
+ {
+ if ( *g_szLineBuffer[i] == 2 && g_pflNameColors[i] )
+ {
+ // it's a saytext string
+ static char buf[MAX_PLAYER_NAME_LENGTH+32];
+
+ // draw the first x characters in the player color
+ strncpy( buf, g_szLineBuffer[i], min(g_iNameLengths[i], MAX_PLAYER_NAME_LENGTH+32) );
+ buf[ min(g_iNameLengths[i], MAX_PLAYER_NAME_LENGTH+31) ] = 0;
+ DrawSetTextColor( g_pflNameColors[i][0], g_pflNameColors[i][1], g_pflNameColors[i][2] );
+
+ // If we're an alien, move chat over a bit so it doesn't overlap energy bar
+ int theDrawX = LINE_START;
+ //if(gHUD.GetIsAlien())
+ //{
+ // theDrawX += .07f*ScreenWidth;
+ //}
+ int x = DrawConsoleString(theDrawX, y, buf );
+
+ // color is reset after each string draw
+ DrawConsoleString( x, y, g_szLineBuffer[i] + g_iNameLengths[i] );
+ }
+ else
+ {
+ // normal draw
+ DrawConsoleString( LINE_START, y, g_szLineBuffer[i] );
+ }
+ }
+
+ y += line_height;
+ }
+
+
+ return 1;
+}
+
+int CHudSayText :: MsgFunc_SayText( const char *pszName, int iSize, void *pbuf )
+{
+
+ int client_index;
+ string content, location;
+ NetMsg_SayText( pbuf, iSize, client_index, content, location );
+
+ string theTranslatedLocation;
+ if(LocalizeString(location.c_str(), theTranslatedLocation))
+ {
+ // If player is on our team, add location
+ cl_entity_s* theEntity = gEngfuncs.GetEntityByIndex(client_index);
+ cl_entity_s* theLocalPlayer = gEngfuncs.GetLocalPlayer();
+
+ if(theEntity && theLocalPlayer && (theEntity->curstate.team == theLocalPlayer->curstate.team))
+ {
+ // Search for first : so we can insert location
+ int theColonIndex = (int)content.find_first_of(":");
+ if((theColonIndex > 0) && (theColonIndex < (int)content.length()))
+ {
+ AvHCUTrimExtraneousLocationText(theTranslatedLocation);
+
+ // Insert location
+ string theNewMessage = content.substr(0, theColonIndex);
+ theNewMessage += " (";
+
+ theNewMessage += theTranslatedLocation;
+ theNewMessage += ")";
+ theNewMessage += content.substr(theColonIndex);
+
+ // Replace the message with new one
+ content = theNewMessage;
+ }
+ }
+ }
+
+ SayTextPrint(content.c_str(), (int)content.length(), client_index );
+
+ return 1;
+}
+
+void CHudSayText :: SayTextPrint( const char *pszBuf, int iBufSize, int clientIndex )
+{
+ if ( gViewPort && gViewPort->AllowedToPrintText() == FALSE )
+ {
+ // Print it straight to the console
+ ConsolePrint( pszBuf );
+ return;
+ }
+
+ // find an empty string slot
+ int i = 0;
+ for ( i = 0; i < MAX_LINES; i++ )
+ {
+ if ( ! *g_szLineBuffer[i] )
+ break;
+ }
+ if ( i == MAX_LINES )
+ {
+ // force scroll buffer up
+ ScrollTextUp();
+ i = MAX_LINES - 1;
+ }
+
+ g_iNameLengths[i] = 0;
+ g_pflNameColors[i] = NULL;
+
+ // if it's a say message, search for the players name in the string
+ if ( *pszBuf == 2 && clientIndex > 0 )
+ {
+ GetPlayerInfo( clientIndex, &g_PlayerInfoList[clientIndex] );
+ const char *pName = g_PlayerInfoList[clientIndex].name;
+
+ if ( pName )
+ {
+ const char *nameInString = strstr( pszBuf, pName );
+
+ if ( nameInString )
+ {
+ g_iNameLengths[i] = (int)strlen( pName ) + (nameInString - pszBuf);
+ g_pflNameColors[i] = GetClientColor(clientIndex);
+ }
+ }
+ }
+
+ // : 0001087
+ // don't strip last character ( often resulted in no carriage returns in the log )
+ strncpy( g_szLineBuffer[i], pszBuf, min(iBufSize, MAX_CHARS_PER_LINE-1) );
+
+ // make sure the text fits in one line
+ EnsureTextFitsInOneLineAndWrapIfHaveTo( i );
+
+ // Set scroll time
+ if ( i == 0 )
+ {
+ flScrollTime = gHUD.m_flTime + m_HUD_saytext_time->value;
+ }
+
+ m_iFlags |= HUD_ACTIVE;
+ //PlaySound( "misc/talk.wav", 1 );
+ gHUD.PlayHUDSound("misc/talk.wav", 1);
+
+ Y_START = ScreenHeight()*.7f;
+
+ ChatPanel* theChatPanel = gViewPort->GetChatPanel();
+
+ if (theChatPanel != NULL)
+ {
+
+ int theX;
+ int theY;
+ int theWidth;
+ int theHeight;
+
+ gViewPort->GetChatPanel()->getPos(theX, theY);
+ gViewPort->GetChatPanel()->getSize(theWidth, theHeight);
+
+ //Y_START = theY + theHeight + 5; //: this is too high imo.
+ //KGP: then move the viewport
+ Y_START = theY + theHeight + 5;
+ }
+
+}
+
+void CHudSayText :: EnsureTextFitsInOneLineAndWrapIfHaveTo( int line )
+{
+ int line_width = 0;
+ GetConsoleStringSize( g_szLineBuffer[line], &line_width, &line_height );
+
+ if ( (line_width + LINE_START) > MAX_LINE_WIDTH )
+ { // string is too long to fit on line
+ // scan the string until we find what word is too long, and wrap the end of the sentence after the word
+ int length = LINE_START;
+ int tmp_len = 0;
+ char *last_break = NULL;
+ for ( char *x = g_szLineBuffer[line]; *x != 0; x++ )
+ {
+ // check for a color change, if so skip past it
+ if ( x[0] == '/' && x[1] == '(' )
+ {
+ x += 2;
+ // skip forward until past mode specifier
+ while ( *x != 0 && *x != ')' )
+ x++;
+
+ if ( *x != 0 )
+ x++;
+
+ if ( *x == 0 )
+ break;
+ }
+
+ char buf[2];
+ buf[1] = 0;
+
+ if ( *x == ' ' && x != g_szLineBuffer[line] ) // store each line break, except for the very first character
+ last_break = x;
+
+ buf[0] = *x; // get the length of the current character
+ GetConsoleStringSize( buf, &tmp_len, &line_height );
+ length += tmp_len;
+
+ if ( length > MAX_LINE_WIDTH )
+ { // needs to be broken up
+ if ( !last_break )
+ last_break = x-1;
+
+ x = last_break;
+
+ // find an empty string slot
+ int j;
+ do
+ {
+ for ( j = 0; j < MAX_LINES; j++ )
+ {
+ if ( ! *g_szLineBuffer[j] )
+ break;
+ }
+ if ( j == MAX_LINES )
+ {
+ // need to make more room to display text, scroll stuff up then fix the pointers
+ int linesmoved = ScrollTextUp();
+ line -= linesmoved;
+ last_break = last_break - (sizeof(g_szLineBuffer[0]) * linesmoved);
+ }
+ }
+ while ( j == MAX_LINES );
+
+ // copy remaining string into next buffer, making sure it starts with a space character
+ if ( (char)*last_break == (char)' ' )
+ {
+ int linelen = (int)strlen(g_szLineBuffer[j]);
+ int remaininglen = (int)strlen(last_break);
+
+ if ( (linelen - remaininglen) <= MAX_CHARS_PER_LINE )
+ strcat( g_szLineBuffer[j], last_break );
+ }
+ else
+ {
+ if ( (strlen(g_szLineBuffer[j]) - strlen(last_break) - 2) < MAX_CHARS_PER_LINE )
+ {
+ strcat( g_szLineBuffer[j], " " );
+ strcat( g_szLineBuffer[j], last_break );
+ }
+ }
+
+ *last_break = 0; // cut off the last string
+
+ EnsureTextFitsInOneLineAndWrapIfHaveTo( j );
+ break;
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/main/source/cl_dll/soundsystem.cpp b/main/source/cl_dll/soundsystem.cpp
index f04fa695..6c2fd194 100644
--- a/main/source/cl_dll/soundsystem.cpp
+++ b/main/source/cl_dll/soundsystem.cpp
@@ -1,168 +1,168 @@
-//======== (C) Copyright 1999, 2000 Valve, L.L.C. All rights reserved. ========
-//
-// The copyright to the contents herein is the property of Valve, L.L.C.
-// The contents may be used and/or copied only with the written permission of
-// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
-// the agreement/contract under which the contents have been supplied.
-//
-// Purpose:
-//
-// $Workfile: $
-// $Date: 2001/09/13 22:28:00 $
-//
-//-----------------------------------------------------------------------------
-// $Log: soundsystem.cpp,v $
-// Revision 1.2 2001/09/13 22:28:00 Charlie
-// - Updated NS with new Half-life 1108 patch in preparation for voice support and spectator mode
-//
-// Revision 1.1.2.1 2001/09/13 14:42:29 Charlie
-// - HL1108
-//
-//
-// $NoKeywords: $
-//=============================================================================
-#include
-#include
-#include
-#include "r_studioint.h"
-
-extern engine_studio_api_t IEngineStudio;
-
-#define RENDERTYPE_UNDEFINED 0
-#define RENDERTYPE_SOFTWARE 1
-#define RENDERTYPE_HARDWARE 2
-
-#define ENGINE_LAUNCHER_API_VERSION 1
-
-LPDIRECTSOUND lpDS = NULL;
-LPDIRECTSOUNDBUFFER lpDSBuf = NULL;
-LPHWAVEOUT lpHW = NULL;
-
-static HMODULE hEngine = 0;
-
-typedef struct engine_api_s
-{
- int version;
- int rendertype;
- int size;
-
- // Functions
- void ( *unused1 ) ( void );
- void ( *unused2 ) ( void );
- void ( *unused3 ) ( void );
- void ( *unused4 ) ( void );
- void ( *unused5 ) ( void );
- void ( *unused6 ) ( void );
- void ( *unused7 ) ( void );
- void ( *unused8 ) ( void );
- void ( *unused9 ) ( void );
- void ( *unused10 ) ( void );
- void ( *unused11 ) ( void );
- void ( *unused12 ) ( void );
- void ( *unused13 ) ( void );
- void ( *unused14 ) ( void );
- void ( *unused15 ) ( void );
- void ( *unused16 ) ( void );
- void ( *unused17 ) ( void );
- void ( *unused18 ) ( void );
- void ( *unused19 ) ( void );
- void ( *unused20 ) ( void );
- void ( *unused21 ) ( void );
- void ( *unused22 ) ( void );
- void ( *unused23 ) ( void );
- void ( *unused24 ) ( void );
- void ( *unused25 ) ( void );
- void ( *unused26 ) ( void );
- void ( *unused27 ) ( void );
- void ( *unused28 ) ( void );
- void ( *unused29 ) ( void );
- void ( *unused30 ) ( void );
- void ( *unused31 ) ( void );
- void ( *unused32 ) ( void );
- void ( *unused33 ) ( void );
- void ( *unused34 ) ( void );
-
- void ( *S_GetDSPointer ) ( struct IDirectSound **lpDS, struct IDirectSoundBuffer **lpDSBuf );
- void *( *S_GetWAVPointer ) ( void );
-
- void ( *unused35 ) ( void );
- void ( *unused36 ) ( void );
- void ( *unused37 ) ( void );
- void ( *unused38 ) ( void );
- void ( *unused39 ) ( void );
- void ( *unused40 ) ( void );
- void ( *unused41 ) ( void );
- void ( *unused42 ) ( void );
- void ( *unused43 ) ( void );
- void ( *unused44 ) ( void );
- void ( *unused45 ) ( void );
- void ( *unused46 ) ( void );
- void ( *unused47 ) ( void );
- void ( *unused48 ) ( void );
- void ( *unused49 ) ( void );
- void ( *unused50 ) ( void );
- void ( *unused51 ) ( void );
- void ( *unused52 ) ( void );
- void ( *unused53 ) ( void );
- void ( *unused54 ) ( void );
- void ( *unused55 ) ( void );
-} engine_api_t;
-
-static engine_api_t engineapi;
-
-typedef int (*engine_api_func)( int version, int size, struct engine_api_s *api );
-
-//-----------------------------------------------------------------------------
-// Purpose: Get launcher/engine interface from engine module
-// Input : hMod -
-// Output : int
-//-----------------------------------------------------------------------------
-int Eng_LoadFunctions( HMODULE hMod )
-{
- engine_api_func pfnEngineAPI;
-
- pfnEngineAPI = ( engine_api_func )GetProcAddress( hMod, "Sys_EngineAPI" );
- if ( !pfnEngineAPI )
- return 0;
-
- if ( !(*pfnEngineAPI)( ENGINE_LAUNCHER_API_VERSION, sizeof( engine_api_t ), &engineapi ) )
- return 0;
-
- // All is okay
- return 1;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Load proper engine .dll and get pointer to either DSound and primary buffer or HWAVEOUT ( NT 4.0, e.g. )
-//-----------------------------------------------------------------------------
-void LoadSoundAPIs( void )
-{
- hEngine = ::LoadLibrary( IEngineStudio.IsHardware() ? "hw.dll" : "sw.dll" );
- if ( hEngine )
- {
- if ( Eng_LoadFunctions( hEngine ) )
- {
- if ( engineapi.S_GetDSPointer && engineapi.S_GetWAVPointer )
- {
- engineapi.S_GetDSPointer(&lpDS, &lpDSBuf);
- lpHW = (HWAVEOUT FAR *)engineapi.S_GetWAVPointer();
- }
- }
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Close engine library, release sound pointers
-//-----------------------------------------------------------------------------
-void ShutdownSoundAPIs( void )
-{
- if( hEngine )
- {
- FreeLibrary( hEngine );
- hEngine = 0;
- }
-
- lpDS = 0;
- lpDSBuf = 0;
- lpHW = 0;
-}
+//======== (C) Copyright 1999, 2000 Valve, L.L.C. All rights reserved. ========
+//
+// The copyright to the contents herein is the property of Valve, L.L.C.
+// The contents may be used and/or copied only with the written permission of
+// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
+// the agreement/contract under which the contents have been supplied.
+//
+// Purpose:
+//
+// $Workfile: $
+// $Date: 2001/09/13 22:28:00 $
+//
+//-----------------------------------------------------------------------------
+// $Log: soundsystem.cpp,v $
+// Revision 1.2 2001/09/13 22:28:00 Charlie
+// - Updated NS with new Half-life 1108 patch in preparation for voice support and spectator mode
+//
+// Revision 1.1.2.1 2001/09/13 14:42:29 Charlie
+// - HL1108
+//
+//
+// $NoKeywords: $
+//=============================================================================
+#include
+#include
+#include
+#include "r_studioint.h"
+
+extern engine_studio_api_t IEngineStudio;
+
+#define RENDERTYPE_UNDEFINED 0
+#define RENDERTYPE_SOFTWARE 1
+#define RENDERTYPE_HARDWARE 2
+
+#define ENGINE_LAUNCHER_API_VERSION 1
+
+LPDIRECTSOUND lpDS = NULL;
+LPDIRECTSOUNDBUFFER lpDSBuf = NULL;
+LPHWAVEOUT lpHW = NULL;
+
+static HMODULE hEngine = 0;
+
+typedef struct engine_api_s
+{
+ int version;
+ int rendertype;
+ int size;
+
+ // Functions
+ void ( *unused1 ) ( void );
+ void ( *unused2 ) ( void );
+ void ( *unused3 ) ( void );
+ void ( *unused4 ) ( void );
+ void ( *unused5 ) ( void );
+ void ( *unused6 ) ( void );
+ void ( *unused7 ) ( void );
+ void ( *unused8 ) ( void );
+ void ( *unused9 ) ( void );
+ void ( *unused10 ) ( void );
+ void ( *unused11 ) ( void );
+ void ( *unused12 ) ( void );
+ void ( *unused13 ) ( void );
+ void ( *unused14 ) ( void );
+ void ( *unused15 ) ( void );
+ void ( *unused16 ) ( void );
+ void ( *unused17 ) ( void );
+ void ( *unused18 ) ( void );
+ void ( *unused19 ) ( void );
+ void ( *unused20 ) ( void );
+ void ( *unused21 ) ( void );
+ void ( *unused22 ) ( void );
+ void ( *unused23 ) ( void );
+ void ( *unused24 ) ( void );
+ void ( *unused25 ) ( void );
+ void ( *unused26 ) ( void );
+ void ( *unused27 ) ( void );
+ void ( *unused28 ) ( void );
+ void ( *unused29 ) ( void );
+ void ( *unused30 ) ( void );
+ void ( *unused31 ) ( void );
+ void ( *unused32 ) ( void );
+ void ( *unused33 ) ( void );
+ void ( *unused34 ) ( void );
+
+ void ( *S_GetDSPointer ) ( struct IDirectSound **lpDS, struct IDirectSoundBuffer **lpDSBuf );
+ void *( *S_GetWAVPointer ) ( void );
+
+ void ( *unused35 ) ( void );
+ void ( *unused36 ) ( void );
+ void ( *unused37 ) ( void );
+ void ( *unused38 ) ( void );
+ void ( *unused39 ) ( void );
+ void ( *unused40 ) ( void );
+ void ( *unused41 ) ( void );
+ void ( *unused42 ) ( void );
+ void ( *unused43 ) ( void );
+ void ( *unused44 ) ( void );
+ void ( *unused45 ) ( void );
+ void ( *unused46 ) ( void );
+ void ( *unused47 ) ( void );
+ void ( *unused48 ) ( void );
+ void ( *unused49 ) ( void );
+ void ( *unused50 ) ( void );
+ void ( *unused51 ) ( void );
+ void ( *unused52 ) ( void );
+ void ( *unused53 ) ( void );
+ void ( *unused54 ) ( void );
+ void ( *unused55 ) ( void );
+} engine_api_t;
+
+static engine_api_t engineapi;
+
+typedef int (*engine_api_func)( int version, int size, struct engine_api_s *api );
+
+//-----------------------------------------------------------------------------
+// Purpose: Get launcher/engine interface from engine module
+// Input : hMod -
+// Output : int
+//-----------------------------------------------------------------------------
+int Eng_LoadFunctions( HMODULE hMod )
+{
+ engine_api_func pfnEngineAPI;
+
+ pfnEngineAPI = ( engine_api_func )GetProcAddress( hMod, "Sys_EngineAPI" );
+ if ( !pfnEngineAPI )
+ return 0;
+
+ if ( !(*pfnEngineAPI)( ENGINE_LAUNCHER_API_VERSION, sizeof( engine_api_t ), &engineapi ) )
+ return 0;
+
+ // All is okay
+ return 1;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Load proper engine .dll and get pointer to either DSound and primary buffer or HWAVEOUT ( NT 4.0, e.g. )
+//-----------------------------------------------------------------------------
+void LoadSoundAPIs( void )
+{
+ hEngine = ::LoadLibrary( IEngineStudio.IsHardware() ? "hw.dll" : "sw.dll" );
+ if ( hEngine )
+ {
+ if ( Eng_LoadFunctions( hEngine ) )
+ {
+ if ( engineapi.S_GetDSPointer && engineapi.S_GetWAVPointer )
+ {
+ engineapi.S_GetDSPointer(&lpDS, &lpDSBuf);
+ lpHW = (HWAVEOUT FAR *)engineapi.S_GetWAVPointer();
+ }
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Close engine library, release sound pointers
+//-----------------------------------------------------------------------------
+void ShutdownSoundAPIs( void )
+{
+ if( hEngine )
+ {
+ FreeLibrary( hEngine );
+ hEngine = 0;
+ }
+
+ lpDS = 0;
+ lpDSBuf = 0;
+ lpHW = 0;
+}
diff --git a/main/source/cl_dll/status_icons.cpp b/main/source/cl_dll/status_icons.cpp
index 17a7eba0..423a3e3a 100644
--- a/main/source/cl_dll/status_icons.cpp
+++ b/main/source/cl_dll/status_icons.cpp
@@ -1,129 +1,129 @@
-/***
-*
-* Copyright (c) 1999, Valve LLC. All rights reserved.
-*
-* This product contains software technology licensed from Id
-* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
-* All Rights Reserved.
-*
-* Use, distribution, and modification of this source code and/or resulting
-* object code is restricted to non-commercial enhancements to products from
-* Valve LLC. All other use, distribution, or modification is prohibited
-* without written permission from Valve LLC.
-*
-****/
-//
-// status_icons.cpp
-//
-#include "hud.h"
-#include "cl_util.h"
-#include "common/const.h"
-#include "common/entity_state.h"
-#include "common/cl_entity.h"
-#include
-#include
-#include "common/event_api.h"
-
-int CHudStatusIcons::Init( void )
-{
- gHUD.AddHudElem( this );
-
- Reset();
-
- return 1;
-}
-
-int CHudStatusIcons::VidInit( void )
-{
-
- return 1;
-}
-
-void CHudStatusIcons::Reset( void )
-{
- memset( m_IconList, 0, sizeof m_IconList );
- m_iFlags &= ~HUD_ACTIVE;
-}
-
-// Draw status icons along the left-hand side of the screen
-int CHudStatusIcons::Draw( float flTime )
-{
- if (gEngfuncs.IsSpectateOnly())
- return 1;
- // find starting position to draw from, along right-hand side of screen
- int x = 5;
- int y = ScreenHeight() / 2;
-
- // loop through icon list, and draw any valid icons drawing up from the middle of screen
- for ( int i = 0; i < MAX_ICONSPRITES; i++ )
- {
- if ( m_IconList[i].spr )
- {
- y -= ( m_IconList[i].rc.bottom - m_IconList[i].rc.top ) + 5;
-
- SPR_Set( m_IconList[i].spr, m_IconList[i].r, m_IconList[i].g, m_IconList[i].b );
- SPR_DrawAdditive( 0, x, y, &m_IconList[i].rc );
- }
- }
-
- return 1;
-}
-
-// add the icon to the icon list, and set it's drawing color
-void CHudStatusIcons::EnableIcon( char *pszIconName, unsigned char red, unsigned char green, unsigned char blue )
-{
- // check to see if the sprite is in the current list
- int i = 0;
- for ( i = 0; i < MAX_ICONSPRITES; i++ )
- {
- if ( !stricmp( m_IconList[i].szSpriteName, pszIconName ) )
- break;
- }
-
- if ( i == MAX_ICONSPRITES )
- {
- // icon not in list, so find an empty slot to add to
- for ( i = 0; i < MAX_ICONSPRITES; i++ )
- {
- if ( !m_IconList[i].spr )
- break;
- }
- }
-
- // if we've run out of space in the list, overwrite the first icon
- if ( i == MAX_ICONSPRITES )
- {
- i = 0;
- }
-
- // Load the sprite and add it to the list
- // the sprite must be listed in hud.txt
- int spr_index = gHUD.GetSpriteIndex( pszIconName );
- m_IconList[i].spr = gHUD.GetSprite( spr_index );
- m_IconList[i].rc = gHUD.GetSpriteRect( spr_index );
- m_IconList[i].r = red;
- m_IconList[i].g = green;
- m_IconList[i].b = blue;
- strcpy( m_IconList[i].szSpriteName, pszIconName );
-
- // Hack: Play Timer sound when a grenade icon is played (in 0.8 seconds)
- if ( strstr(m_IconList[i].szSpriteName, "grenade") )
- {
- cl_entity_t *pthisplayer = gEngfuncs.GetLocalPlayer();
- gEngfuncs.pEventAPI->EV_PlaySound( pthisplayer->index, pthisplayer->origin, CHAN_STATIC, "weapons/timer.wav", 1.0, ATTN_NORM, 0, PITCH_NORM );
- }
-}
-
-void CHudStatusIcons::DisableIcon( char *pszIconName )
-{
- // find the sprite is in the current list
- for ( int i = 0; i < MAX_ICONSPRITES; i++ )
- {
- if ( !stricmp( m_IconList[i].szSpriteName, pszIconName ) )
- {
- // clear the item from the list
- memset( &m_IconList[i], 0, sizeof(icon_sprite_t) );
- return;
- }
- }
-}
+/***
+*
+* Copyright (c) 1999, Valve LLC. All rights reserved.
+*
+* This product contains software technology licensed from Id
+* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
+* All Rights Reserved.
+*
+* Use, distribution, and modification of this source code and/or resulting
+* object code is restricted to non-commercial enhancements to products from
+* Valve LLC. All other use, distribution, or modification is prohibited
+* without written permission from Valve LLC.
+*
+****/
+//
+// status_icons.cpp
+//
+#include "hud.h"
+#include "cl_util.h"
+#include "common/const.h"
+#include "common/entity_state.h"
+#include "common/cl_entity.h"
+#include
+#include
+#include "common/event_api.h"
+
+int CHudStatusIcons::Init( void )
+{
+ gHUD.AddHudElem( this );
+
+ Reset();
+
+ return 1;
+}
+
+int CHudStatusIcons::VidInit( void )
+{
+
+ return 1;
+}
+
+void CHudStatusIcons::Reset( void )
+{
+ memset( m_IconList, 0, sizeof m_IconList );
+ m_iFlags &= ~HUD_ACTIVE;
+}
+
+// Draw status icons along the left-hand side of the screen
+int CHudStatusIcons::Draw( float flTime )
+{
+ if (gEngfuncs.IsSpectateOnly())
+ return 1;
+ // find starting position to draw from, along right-hand side of screen
+ int x = 5;
+ int y = ScreenHeight() / 2;
+
+ // loop through icon list, and draw any valid icons drawing up from the middle of screen
+ for ( int i = 0; i < MAX_ICONSPRITES; i++ )
+ {
+ if ( m_IconList[i].spr )
+ {
+ y -= ( m_IconList[i].rc.bottom - m_IconList[i].rc.top ) + 5;
+
+ SPR_Set( m_IconList[i].spr, m_IconList[i].r, m_IconList[i].g, m_IconList[i].b );
+ SPR_DrawAdditive( 0, x, y, &m_IconList[i].rc );
+ }
+ }
+
+ return 1;
+}
+
+// add the icon to the icon list, and set it's drawing color
+void CHudStatusIcons::EnableIcon( char *pszIconName, unsigned char red, unsigned char green, unsigned char blue )
+{
+ // check to see if the sprite is in the current list
+ int i = 0;
+ for ( i = 0; i < MAX_ICONSPRITES; i++ )
+ {
+ if ( !stricmp( m_IconList[i].szSpriteName, pszIconName ) )
+ break;
+ }
+
+ if ( i == MAX_ICONSPRITES )
+ {
+ // icon not in list, so find an empty slot to add to
+ for ( i = 0; i < MAX_ICONSPRITES; i++ )
+ {
+ if ( !m_IconList[i].spr )
+ break;
+ }
+ }
+
+ // if we've run out of space in the list, overwrite the first icon
+ if ( i == MAX_ICONSPRITES )
+ {
+ i = 0;
+ }
+
+ // Load the sprite and add it to the list
+ // the sprite must be listed in hud.txt
+ int spr_index = gHUD.GetSpriteIndex( pszIconName );
+ m_IconList[i].spr = gHUD.GetSprite( spr_index );
+ m_IconList[i].rc = gHUD.GetSpriteRect( spr_index );
+ m_IconList[i].r = red;
+ m_IconList[i].g = green;
+ m_IconList[i].b = blue;
+ strcpy( m_IconList[i].szSpriteName, pszIconName );
+
+ // Hack: Play Timer sound when a grenade icon is played (in 0.8 seconds)
+ if ( strstr(m_IconList[i].szSpriteName, "grenade") )
+ {
+ cl_entity_t *pthisplayer = gEngfuncs.GetLocalPlayer();
+ gEngfuncs.pEventAPI->EV_PlaySound( pthisplayer->index, pthisplayer->origin, CHAN_STATIC, "weapons/timer.wav", 1.0, ATTN_NORM, 0, PITCH_NORM );
+ }
+}
+
+void CHudStatusIcons::DisableIcon( char *pszIconName )
+{
+ // find the sprite is in the current list
+ for ( int i = 0; i < MAX_ICONSPRITES; i++ )
+ {
+ if ( !stricmp( m_IconList[i].szSpriteName, pszIconName ) )
+ {
+ // clear the item from the list
+ memset( &m_IconList[i], 0, sizeof(icon_sprite_t) );
+ return;
+ }
+ }
+}
diff --git a/main/source/cl_dll/statusbar.cpp b/main/source/cl_dll/statusbar.cpp
index 63cdff5a..03a2f6c5 100644
--- a/main/source/cl_dll/statusbar.cpp
+++ b/main/source/cl_dll/statusbar.cpp
@@ -1,300 +1,300 @@
-/***
-*
-* Copyright (c) 1999, Valve LLC. All rights reserved.
-*
-* This product contains software technology licensed from Id
-* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
-* All Rights Reserved.
-*
-* Use, distribution, and modification of this source code and/or resulting
-* object code is restricted to non-commercial enhancements to products from
-* Valve LLC. All other use, distribution, or modification is prohibited
-* without written permission from Valve LLC.
-*
-****/
-//
-// statusbar.cpp
-//
-// generic text status bar, set by game dll
-// runs across bottom of screen
-//
-
-#include "hud.h"
-#include "cl_util.h"
-#include "mod/AvHNetworkMessages.h"
-
-#include
-#include
-
-DECLARE_MESSAGE( m_StatusBar, StatusText );
-DECLARE_MESSAGE( m_StatusBar, StatusValue );
-
-#define STATUSBAR_ID_LINE 1
-
-float *GetClientColor( int clientIndex );
-extern float g_ColorYellow[3];
-
-int CHudStatusBar :: Init( void )
-{
- //gHUD.AddHudElem( this );
-
- HOOK_MESSAGE( StatusText );
- HOOK_MESSAGE( StatusValue );
-
- Reset();
-
- CVAR_CREATE( "hud_centerid", "0", FCVAR_ARCHIVE );
-
- return 1;
-}
-
-int CHudStatusBar :: VidInit( void )
-{
- // Load sprites here
-
- return 1;
-}
-
-void CHudStatusBar :: Reset( void )
-{
- int i = 0;
-
- m_iFlags &= ~HUD_ACTIVE; // start out inactive
- for ( i = 0; i < MAX_STATUSBAR_LINES; i++ )
- {
- m_szStatusText[i][0] = 0;
- m_iStatusValues[i] = -1;
- }
-
- //memset( m_iStatusValues, 0, sizeof m_iStatusValues );
-
- m_iStatusValues[0] = 1; // 0 is the special index, which always returns true
-
- // reset our colors for the status bar lines (yellow is default)
- for ( i = 0; i < MAX_STATUSBAR_LINES; i++ )
- m_pflNameColors[i] = g_ColorYellow;
-}
-
-const char* CHudStatusBar::GetStatusString() const
-{
- static char kStatusString[1024];
-
- memset(kStatusString, 0, 1024);
-
- for(int i = 0; i < MAX_STATUSBAR_LINES; i++)
- {
- const char* theCurrentString = m_szStatusBar[i];
- if(strlen(theCurrentString) > 0)
- {
- strcat(kStatusString, theCurrentString);
- }
- }
-
- return kStatusString;
-}
-
-void CHudStatusBar :: ParseStatusString( int line_num )
-{
- // localise string first
- char szBuffer[MAX_STATUSTEXT_LENGTH];
- memset( szBuffer, 0, sizeof szBuffer );
- gHUD.m_TextMessage.LocaliseTextString( m_szStatusText[line_num], szBuffer, MAX_STATUSTEXT_LENGTH );
-
- // parse m_szStatusText & m_iStatusValues into m_szStatusBar
- memset( m_szStatusBar[line_num], 0, MAX_STATUSTEXT_LENGTH );
- char *src = szBuffer;
- char *dst = m_szStatusBar[line_num];
-
- char *src_start = src, *dst_start = dst;
-
- while ( *src != 0 )
- {
- while ( *src == '\n' )
- src++; // skip over any newlines
-
- if ( ((src - src_start) >= MAX_STATUSTEXT_LENGTH) || ((dst - dst_start) >= MAX_STATUSTEXT_LENGTH) )
- break;
-
- int index = atoi( src );
- // should we draw this line?
- if ( (index >= 0 && index < MAX_STATUSBAR_VALUES) && (m_iStatusValues[index] != -1))
- { // parse this line and append result to the status bar
- while ( *src >= '0' && *src <= '9' )
- src++;
-
- if ( *src == '\n' || *src == 0 )
- continue; // no more left in this text line
-
- // copy the text, char by char, until we hit a % or a \n
- while ( *src != '\n' && *src != 0 )
- {
- if ( *src != '%' )
- { // just copy the character
- *dst = *src;
- dst++, src++;
- }
- else
- {
- // get the descriptor
- char valtype = *(++src); // move over %
-
- // if it's a %, draw a % sign
- if ( valtype == '%' )
- {
- *dst = valtype;
- dst++, src++;
- continue;
- }
-
- // move over descriptor, then get and move over the index
- index = atoi( ++src );
- while ( *src >= '0' && *src <= '9' )
- src++;
-
- if ( index >= 0 && index < MAX_STATUSBAR_VALUES )
- {
- int indexval = m_iStatusValues[index];
-
- // get the string to substitute in place of the %XX
- char szRepString[MAX_PLAYER_NAME_LENGTH];
- switch ( valtype )
- {
- case 'p': // player name
- GetPlayerInfo( indexval, &g_PlayerInfoList[indexval] );
- if ( g_PlayerInfoList[indexval].name != NULL )
- {
- strncpy( szRepString, g_PlayerInfoList[indexval].name, MAX_PLAYER_NAME_LENGTH );
- m_pflNameColors[line_num] = GetClientColor( indexval );
- }
- else
- {
- strcpy( szRepString, "******" );
- }
-
- break;
- case 'i': // number
- sprintf( szRepString, "%d", indexval );
- break;
- default:
- szRepString[0] = 0;
- }
-
- for ( char *cp = szRepString; *cp != 0 && ((dst - dst_start) < MAX_STATUSTEXT_LENGTH); cp++, dst++ )
- *dst = *cp;
- }
- }
- }
- }
- else
- {
- // skip to next line of text
- while ( *src != 0 && *src != '\n' )
- src++;
- }
- }
-}
-
-void CHudStatusBar::ReparseStringIfNeeded()
-{
- if ( m_bReparseString )
- {
- for ( int i = 0; i < MAX_STATUSBAR_LINES; i++ )
- {
- m_pflNameColors[i] = g_ColorYellow;
- ParseStatusString( i );
- }
- m_bReparseString = FALSE;
- }
-
-}
-
-int CHudStatusBar :: Draw( float fTime )
-{
-
- this->ReparseStringIfNeeded();
-
- // Draw the status bar lines
- for ( int i = 0; i < MAX_STATUSBAR_LINES; i++ )
- {
- int TextHeight, TextWidth;
- GetConsoleStringSize( m_szStatusBar[i], &TextWidth, &TextHeight );
-
- int Y_START;
- if ( ScreenHeight() >= 480 )
- Y_START = ScreenHeight() - 55;
- else
- Y_START = ScreenHeight() - 45;
-
- int x = 5;
- int y = Y_START - ( TextHeight * i ); // draw along bottom of screen
-
- // let user set status ID bar centering
- if ( (i == STATUSBAR_ID_LINE) && CVAR_GET_FLOAT("hud_centerid") )
- {
- x = max( 0, max(2, (ScreenWidth() - TextWidth)) / 2 );
- y = (ScreenHeight() / 2) + (TextHeight*CVAR_GET_FLOAT("hud_centerid"));
- }
-
- if ( m_pflNameColors[i] )
- DrawSetTextColor( m_pflNameColors[i][0], m_pflNameColors[i][1], m_pflNameColors[i][2] );
-
- DrawConsoleString( x, y, m_szStatusBar[i] );
- }
-
- return 1;
-}
-
-// Message handler for StatusText message
-// accepts two values:
-// byte: line number of status bar text
-// string: status bar text
-// this string describes how the status bar should be drawn
-// a semi-regular expression:
-// ( slotnum ([a..z] [%pX] [%iX])*)*
-// where slotnum is an index into the Value table (see below)
-// if slotnum is 0, the string is always drawn
-// if StatusValue[slotnum] != 0, the following string is drawn, upto the next newline - otherwise the text is skipped upto next newline
-// %pX, where X is an integer, will substitute a player name here, getting the player index from StatusValue[X]
-// %iX, where X is an integer, will substitute a number here, getting the number from StatusValue[X]
-int CHudStatusBar :: MsgFunc_StatusText( const char *pszName, int iSize, void *pbuf )
-{
- int location;
- string content;
- NetMsg_StatusText( pbuf, iSize, location, content );
-
- if ( location < 0 || location >= MAX_STATUSBAR_LINES )
- return 1;
-
- strncpy( m_szStatusText[location], content.c_str(), MAX_STATUSTEXT_LENGTH );
- m_szStatusText[location][MAX_STATUSTEXT_LENGTH-1] = 0; // ensure it's null terminated ( strncpy() won't null terminate if read string too long)
-
- if ( m_szStatusText[0] == 0 )
- m_iFlags &= ~HUD_ACTIVE;
- else
- m_iFlags |= HUD_ACTIVE; // we have status text, so turn on the status bar
-
- m_bReparseString = TRUE;
- this->ReparseStringIfNeeded();
-
- return 1;
-}
-
-// Message handler for StatusText message
-// accepts two values:
-// byte: index into the status value array
-// short: value to store
-int CHudStatusBar :: MsgFunc_StatusValue( const char *pszName, int iSize, void *pbuf )
-{
- int location, state;
- NetMsg_StatusValue( pbuf, iSize, location, state );
-
- if ( location < 1 || location >= MAX_STATUSBAR_VALUES )
- return 1; // index out of range
-
- m_iStatusValues[location] = state;
-
- m_bReparseString = TRUE;
- this->ReparseStringIfNeeded();
-
- return 1;
+/***
+*
+* Copyright (c) 1999, Valve LLC. All rights reserved.
+*
+* This product contains software technology licensed from Id
+* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
+* All Rights Reserved.
+*
+* Use, distribution, and modification of this source code and/or resulting
+* object code is restricted to non-commercial enhancements to products from
+* Valve LLC. All other use, distribution, or modification is prohibited
+* without written permission from Valve LLC.
+*
+****/
+//
+// statusbar.cpp
+//
+// generic text status bar, set by game dll
+// runs across bottom of screen
+//
+
+#include "hud.h"
+#include "cl_util.h"
+#include "mod/AvHNetworkMessages.h"
+
+#include
+#include
+
+DECLARE_MESSAGE( m_StatusBar, StatusText );
+DECLARE_MESSAGE( m_StatusBar, StatusValue );
+
+#define STATUSBAR_ID_LINE 1
+
+float *GetClientColor( int clientIndex );
+extern float g_ColorYellow[3];
+
+int CHudStatusBar :: Init( void )
+{
+ //gHUD.AddHudElem( this );
+
+ HOOK_MESSAGE( StatusText );
+ HOOK_MESSAGE( StatusValue );
+
+ Reset();
+
+ CVAR_CREATE( "hud_centerid", "0", FCVAR_ARCHIVE );
+
+ return 1;
+}
+
+int CHudStatusBar :: VidInit( void )
+{
+ // Load sprites here
+
+ return 1;
+}
+
+void CHudStatusBar :: Reset( void )
+{
+ int i = 0;
+
+ m_iFlags &= ~HUD_ACTIVE; // start out inactive
+ for ( i = 0; i < MAX_STATUSBAR_LINES; i++ )
+ {
+ m_szStatusText[i][0] = 0;
+ m_iStatusValues[i] = -1;
+ }
+
+ //memset( m_iStatusValues, 0, sizeof m_iStatusValues );
+
+ m_iStatusValues[0] = 1; // 0 is the special index, which always returns true
+
+ // reset our colors for the status bar lines (yellow is default)
+ for ( i = 0; i < MAX_STATUSBAR_LINES; i++ )
+ m_pflNameColors[i] = g_ColorYellow;
+}
+
+const char* CHudStatusBar::GetStatusString() const
+{
+ static char kStatusString[1024];
+
+ memset(kStatusString, 0, 1024);
+
+ for(int i = 0; i < MAX_STATUSBAR_LINES; i++)
+ {
+ const char* theCurrentString = m_szStatusBar[i];
+ if(strlen(theCurrentString) > 0)
+ {
+ strcat(kStatusString, theCurrentString);
+ }
+ }
+
+ return kStatusString;
+}
+
+void CHudStatusBar :: ParseStatusString( int line_num )
+{
+ // localise string first
+ char szBuffer[MAX_STATUSTEXT_LENGTH];
+ memset( szBuffer, 0, sizeof szBuffer );
+ gHUD.m_TextMessage.LocaliseTextString( m_szStatusText[line_num], szBuffer, MAX_STATUSTEXT_LENGTH );
+
+ // parse m_szStatusText & m_iStatusValues into m_szStatusBar
+ memset( m_szStatusBar[line_num], 0, MAX_STATUSTEXT_LENGTH );
+ char *src = szBuffer;
+ char *dst = m_szStatusBar[line_num];
+
+ char *src_start = src, *dst_start = dst;
+
+ while ( *src != 0 )
+ {
+ while ( *src == '\n' )
+ src++; // skip over any newlines
+
+ if ( ((src - src_start) >= MAX_STATUSTEXT_LENGTH) || ((dst - dst_start) >= MAX_STATUSTEXT_LENGTH) )
+ break;
+
+ int index = atoi( src );
+ // should we draw this line?
+ if ( (index >= 0 && index < MAX_STATUSBAR_VALUES) && (m_iStatusValues[index] != -1))
+ { // parse this line and append result to the status bar
+ while ( *src >= '0' && *src <= '9' )
+ src++;
+
+ if ( *src == '\n' || *src == 0 )
+ continue; // no more left in this text line
+
+ // copy the text, char by char, until we hit a % or a \n
+ while ( *src != '\n' && *src != 0 )
+ {
+ if ( *src != '%' )
+ { // just copy the character
+ *dst = *src;
+ dst++, src++;
+ }
+ else
+ {
+ // get the descriptor
+ char valtype = *(++src); // move over %
+
+ // if it's a %, draw a % sign
+ if ( valtype == '%' )
+ {
+ *dst = valtype;
+ dst++, src++;
+ continue;
+ }
+
+ // move over descriptor, then get and move over the index
+ index = atoi( ++src );
+ while ( *src >= '0' && *src <= '9' )
+ src++;
+
+ if ( index >= 0 && index < MAX_STATUSBAR_VALUES )
+ {
+ int indexval = m_iStatusValues[index];
+
+ // get the string to substitute in place of the %XX
+ char szRepString[MAX_PLAYER_NAME_LENGTH];
+ switch ( valtype )
+ {
+ case 'p': // player name
+ GetPlayerInfo( indexval, &g_PlayerInfoList[indexval] );
+ if ( g_PlayerInfoList[indexval].name != NULL )
+ {
+ strncpy( szRepString, g_PlayerInfoList[indexval].name, MAX_PLAYER_NAME_LENGTH );
+ m_pflNameColors[line_num] = GetClientColor( indexval );
+ }
+ else
+ {
+ strcpy( szRepString, "******" );
+ }
+
+ break;
+ case 'i': // number
+ sprintf( szRepString, "%d", indexval );
+ break;
+ default:
+ szRepString[0] = 0;
+ }
+
+ for ( char *cp = szRepString; *cp != 0 && ((dst - dst_start) < MAX_STATUSTEXT_LENGTH); cp++, dst++ )
+ *dst = *cp;
+ }
+ }
+ }
+ }
+ else
+ {
+ // skip to next line of text
+ while ( *src != 0 && *src != '\n' )
+ src++;
+ }
+ }
+}
+
+void CHudStatusBar::ReparseStringIfNeeded()
+{
+ if ( m_bReparseString )
+ {
+ for ( int i = 0; i < MAX_STATUSBAR_LINES; i++ )
+ {
+ m_pflNameColors[i] = g_ColorYellow;
+ ParseStatusString( i );
+ }
+ m_bReparseString = FALSE;
+ }
+
+}
+
+int CHudStatusBar :: Draw( float fTime )
+{
+
+ this->ReparseStringIfNeeded();
+
+ // Draw the status bar lines
+ for ( int i = 0; i < MAX_STATUSBAR_LINES; i++ )
+ {
+ int TextHeight, TextWidth;
+ GetConsoleStringSize( m_szStatusBar[i], &TextWidth, &TextHeight );
+
+ int Y_START;
+ if ( ScreenHeight() >= 480 )
+ Y_START = ScreenHeight() - 55;
+ else
+ Y_START = ScreenHeight() - 45;
+
+ int x = 5;
+ int y = Y_START - ( TextHeight * i ); // draw along bottom of screen
+
+ // let user set status ID bar centering
+ if ( (i == STATUSBAR_ID_LINE) && CVAR_GET_FLOAT("hud_centerid") )
+ {
+ x = max( 0, max(2, (ScreenWidth() - TextWidth)) / 2 );
+ y = (ScreenHeight() / 2) + (TextHeight*CVAR_GET_FLOAT("hud_centerid"));
+ }
+
+ if ( m_pflNameColors[i] )
+ DrawSetTextColor( m_pflNameColors[i][0], m_pflNameColors[i][1], m_pflNameColors[i][2] );
+
+ DrawConsoleString( x, y, m_szStatusBar[i] );
+ }
+
+ return 1;
+}
+
+// Message handler for StatusText message
+// accepts two values:
+// byte: line number of status bar text
+// string: status bar text
+// this string describes how the status bar should be drawn
+// a semi-regular expression:
+// ( slotnum ([a..z] [%pX] [%iX])*)*
+// where slotnum is an index into the Value table (see below)
+// if slotnum is 0, the string is always drawn
+// if StatusValue[slotnum] != 0, the following string is drawn, upto the next newline - otherwise the text is skipped upto next newline
+// %pX, where X is an integer, will substitute a player name here, getting the player index from StatusValue[X]
+// %iX, where X is an integer, will substitute a number here, getting the number from StatusValue[X]
+int CHudStatusBar :: MsgFunc_StatusText( const char *pszName, int iSize, void *pbuf )
+{
+ int location;
+ string content;
+ NetMsg_StatusText( pbuf, iSize, location, content );
+
+ if ( location < 0 || location >= MAX_STATUSBAR_LINES )
+ return 1;
+
+ strncpy( m_szStatusText[location], content.c_str(), MAX_STATUSTEXT_LENGTH );
+ m_szStatusText[location][MAX_STATUSTEXT_LENGTH-1] = 0; // ensure it's null terminated ( strncpy() won't null terminate if read string too long)
+
+ if ( m_szStatusText[0] == 0 )
+ m_iFlags &= ~HUD_ACTIVE;
+ else
+ m_iFlags |= HUD_ACTIVE; // we have status text, so turn on the status bar
+
+ m_bReparseString = TRUE;
+ this->ReparseStringIfNeeded();
+
+ return 1;
+}
+
+// Message handler for StatusText message
+// accepts two values:
+// byte: index into the status value array
+// short: value to store
+int CHudStatusBar :: MsgFunc_StatusValue( const char *pszName, int iSize, void *pbuf )
+{
+ int location, state;
+ NetMsg_StatusValue( pbuf, iSize, location, state );
+
+ if ( location < 1 || location >= MAX_STATUSBAR_VALUES )
+ return 1; // index out of range
+
+ m_iStatusValues[location] = state;
+
+ m_bReparseString = TRUE;
+ this->ReparseStringIfNeeded();
+
+ return 1;
}
\ No newline at end of file
diff --git a/main/source/cl_dll/steam_appid.txt b/main/source/cl_dll/steam_appid.txt
index 356ea80c..2bbd69c2 100644
--- a/main/source/cl_dll/steam_appid.txt
+++ b/main/source/cl_dll/steam_appid.txt
@@ -1 +1 @@
-70
+70
diff --git a/main/source/cl_dll/studio_util.cpp b/main/source/cl_dll/studio_util.cpp
index 64d6cd27..5235b324 100644
--- a/main/source/cl_dll/studio_util.cpp
+++ b/main/source/cl_dll/studio_util.cpp
@@ -1,245 +1,245 @@
-#include
-#include "hud.h"
-#include "cl_util.h"
-#include "common/const.h"
-#include "common/com_model.h"
-#include "studio_util.h"
-
-/*
-====================
-AngleMatrix
-
-====================
-*/
-
-void AngleMatrix (const float *angles, float (*matrix)[4] )
-{
- float angle;
- float sr, sp, sy, cr, cp, cy;
-
- angle = angles[YAW] * (M_PI*2 / 360);
- sy = sin(angle);
- cy = cos(angle);
- angle = angles[PITCH] * (M_PI*2 / 360);
- sp = sin(angle);
- cp = cos(angle);
- angle = angles[ROLL] * (M_PI*2 / 360);
- sr = sin(angle);
- cr = cos(angle);
-
- // matrix = (YAW * PITCH) * ROLL
- matrix[0][0] = cp*cy;
- matrix[1][0] = cp*sy;
- matrix[2][0] = -sp;
- matrix[0][1] = sr*sp*cy+cr*-sy;
- matrix[1][1] = sr*sp*sy+cr*cy;
- matrix[2][1] = sr*cp;
- matrix[0][2] = (cr*sp*cy+-sr*-sy);
- matrix[1][2] = (cr*sp*sy+-sr*cy);
- matrix[2][2] = cr*cp;
- matrix[0][3] = 0.0;
- matrix[1][3] = 0.0;
- matrix[2][3] = 0.0;
-}
-
-/*
-====================
-VectorCompare
-
-====================
-*/
-int VectorCompare (const float *v1, const float *v2)
-{
- int i;
-
- for (i=0 ; i<3 ; i++)
- if (v1[i] != v2[i])
- return 0;
-
- return 1;
-}
-
-/*
-====================
-CrossProduct
-
-====================
-*/
-void CrossProduct (const float *v1, const float *v2, float *cross)
-{
- cross[0] = v1[1]*v2[2] - v1[2]*v2[1];
- cross[1] = v1[2]*v2[0] - v1[0]*v2[2];
- cross[2] = v1[0]*v2[1] - v1[1]*v2[0];
-}
-
-/*
-====================
-VectorTransform
-
-====================
-*/
-void VectorTransform (const float *in1, float in2[3][4], float *out)
-{
- out[0] = DotProduct(in1, in2[0]) + in2[0][3];
- out[1] = DotProduct(in1, in2[1]) + in2[1][3];
- out[2] = DotProduct(in1, in2[2]) + in2[2][3];
-}
-
-/*
-================
-ConcatTransforms
-
-================
-*/
-void ConcatTransforms (float in1[3][4], float in2[3][4], float out[3][4])
-{
- out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] +
- in1[0][2] * in2[2][0];
- out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] +
- in1[0][2] * in2[2][1];
- out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] +
- in1[0][2] * in2[2][2];
- out[0][3] = in1[0][0] * in2[0][3] + in1[0][1] * in2[1][3] +
- in1[0][2] * in2[2][3] + in1[0][3];
- out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] +
- in1[1][2] * in2[2][0];
- out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] +
- in1[1][2] * in2[2][1];
- out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] +
- in1[1][2] * in2[2][2];
- out[1][3] = in1[1][0] * in2[0][3] + in1[1][1] * in2[1][3] +
- in1[1][2] * in2[2][3] + in1[1][3];
- out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] +
- in1[2][2] * in2[2][0];
- out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] +
- in1[2][2] * in2[2][1];
- out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] +
- in1[2][2] * in2[2][2];
- out[2][3] = in1[2][0] * in2[0][3] + in1[2][1] * in2[1][3] +
- in1[2][2] * in2[2][3] + in1[2][3];
-}
-
-// angles index are not the same as ROLL, PITCH, YAW
-
-/*
-====================
-AngleQuaternion
-
-====================
-*/
-void AngleQuaternion( float *angles, vec4_t quaternion )
-{
- float angle;
- float sr, sp, sy, cr, cp, cy;
-
- // FIXME: rescale the inputs to 1/2 angle
- angle = angles[2] * 0.5;
- sy = sin(angle);
- cy = cos(angle);
- angle = angles[1] * 0.5;
- sp = sin(angle);
- cp = cos(angle);
- angle = angles[0] * 0.5;
- sr = sin(angle);
- cr = cos(angle);
-
- quaternion[0] = sr*cp*cy-cr*sp*sy; // X
- quaternion[1] = cr*sp*cy+sr*cp*sy; // Y
- quaternion[2] = cr*cp*sy-sr*sp*cy; // Z
- quaternion[3] = cr*cp*cy+sr*sp*sy; // W
-}
-
-/*
-====================
-QuaternionSlerp
-
-====================
-*/
-void QuaternionSlerp( vec4_t p, vec4_t q, float t, vec4_t qt )
-{
- int i;
- float omega, cosom, sinom, sclp, sclq;
-
- // decide if one of the quaternions is backwards
- float a = 0;
- float b = 0;
-
- for (i = 0; i < 4; i++)
- {
- a += (p[i]-q[i])*(p[i]-q[i]);
- b += (p[i]+q[i])*(p[i]+q[i]);
- }
- if (a > b)
- {
- for (i = 0; i < 4; i++)
- {
- q[i] = -q[i];
- }
- }
-
- cosom = p[0]*q[0] + p[1]*q[1] + p[2]*q[2] + p[3]*q[3];
-
- if ((1.0 + cosom) > 0.000001)
- {
- if ((1.0 - cosom) > 0.000001)
- {
- omega = acos( cosom );
- sinom = sin( omega );
- sclp = sin( (1.0 - t)*omega) / sinom;
- sclq = sin( t*omega ) / sinom;
- }
- else
- {
- sclp = 1.0 - t;
- sclq = t;
- }
- for (i = 0; i < 4; i++) {
- qt[i] = sclp * p[i] + sclq * q[i];
- }
- }
- else
- {
- qt[0] = -q[1];
- qt[1] = q[0];
- qt[2] = -q[3];
- qt[3] = q[2];
- sclp = sin( (1.0 - t) * (0.5 * M_PI));
- sclq = sin( t * (0.5 * M_PI));
- for (i = 0; i < 3; i++)
- {
- qt[i] = sclp * p[i] + sclq * qt[i];
- }
- }
-}
-
-/*
-====================
-QuaternionMatrix
-
-====================
-*/
-void QuaternionMatrix( vec4_t quaternion, float (*matrix)[4] )
-{
- matrix[0][0] = 1.0 - 2.0 * quaternion[1] * quaternion[1] - 2.0 * quaternion[2] * quaternion[2];
- matrix[1][0] = 2.0 * quaternion[0] * quaternion[1] + 2.0 * quaternion[3] * quaternion[2];
- matrix[2][0] = 2.0 * quaternion[0] * quaternion[2] - 2.0 * quaternion[3] * quaternion[1];
-
- matrix[0][1] = 2.0 * quaternion[0] * quaternion[1] - 2.0 * quaternion[3] * quaternion[2];
- matrix[1][1] = 1.0 - 2.0 * quaternion[0] * quaternion[0] - 2.0 * quaternion[2] * quaternion[2];
- matrix[2][1] = 2.0 * quaternion[1] * quaternion[2] + 2.0 * quaternion[3] * quaternion[0];
-
- matrix[0][2] = 2.0 * quaternion[0] * quaternion[2] + 2.0 * quaternion[3] * quaternion[1];
- matrix[1][2] = 2.0 * quaternion[1] * quaternion[2] - 2.0 * quaternion[3] * quaternion[0];
- matrix[2][2] = 1.0 - 2.0 * quaternion[0] * quaternion[0] - 2.0 * quaternion[1] * quaternion[1];
-}
-
-/*
-====================
-MatrixCopy
-
-====================
-*/
-void MatrixCopy( float in[3][4], float out[3][4] )
-{
- memcpy( out, in, sizeof( float ) * 3 * 4 );
-}
+#include
+#include "hud.h"
+#include "cl_util.h"
+#include "common/const.h"
+#include "common/com_model.h"
+#include "studio_util.h"
+
+/*
+====================
+AngleMatrix
+
+====================
+*/ #ifdef WIN32
+
+void AngleMatrix (const float *angles, float (*matrix)[4] )
+{
+ float angle;
+ float sr, sp, sy, cr, cp, cy;
+
+ angle = angles[YAW] * (M_PI*2 / 360);
+ sy = sin(angle);
+ cy = cos(angle);
+ angle = angles[PITCH] * (M_PI*2 / 360);
+ sp = sin(angle);
+ cp = cos(angle);
+ angle = angles[ROLL] * (M_PI*2 / 360);
+ sr = sin(angle);
+ cr = cos(angle);
+
+ // matrix = (YAW * PITCH) * ROLL
+ matrix[0][0] = cp*cy;
+ matrix[1][0] = cp*sy;
+ matrix[2][0] = -sp;
+ matrix[0][1] = sr*sp*cy+cr*-sy;
+ matrix[1][1] = sr*sp*sy+cr*cy;
+ matrix[2][1] = sr*cp;
+ matrix[0][2] = (cr*sp*cy+-sr*-sy);
+ matrix[1][2] = (cr*sp*sy+-sr*cy);
+ matrix[2][2] = cr*cp;
+ matrix[0][3] = 0.0;
+ matrix[1][3] = 0.0;
+ matrix[2][3] = 0.0;
+}
+#endif
+/*
+====================
+VectorCompare
+
+====================
+*/ #ifdef WIN32
+int VectorCompare (const float *v1, const float *v2)
+{
+ int i;
+
+ for (i=0 ; i<3 ; i++)
+ if (v1[i] != v2[i])
+ return 0;
+
+ return 1;
+}
+#endif
+/*
+====================
+CrossProduct
+
+====================
+*/ #ifdef WIN32
+void CrossProduct (const float *v1, const float *v2, float *cross)
+{
+ cross[0] = v1[1]*v2[2] - v1[2]*v2[1];
+ cross[1] = v1[2]*v2[0] - v1[0]*v2[2];
+ cross[2] = v1[0]*v2[1] - v1[1]*v2[0];
+}
+#endif
+/*
+====================
+VectorTransform
+
+====================
+*/
+void VectorTransform (const float *in1, float in2[3][4], float *out)
+{
+ out[0] = DotProduct(in1, in2[0]) + in2[0][3];
+ out[1] = DotProduct(in1, in2[1]) + in2[1][3];
+ out[2] = DotProduct(in1, in2[2]) + in2[2][3];
+}
+
+/*
+================
+ConcatTransforms
+
+================
+*/
+void ConcatTransforms (float in1[3][4], float in2[3][4], float out[3][4])
+{
+ out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] +
+ in1[0][2] * in2[2][0];
+ out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] +
+ in1[0][2] * in2[2][1];
+ out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] +
+ in1[0][2] * in2[2][2];
+ out[0][3] = in1[0][0] * in2[0][3] + in1[0][1] * in2[1][3] +
+ in1[0][2] * in2[2][3] + in1[0][3];
+ out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] +
+ in1[1][2] * in2[2][0];
+ out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] +
+ in1[1][2] * in2[2][1];
+ out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] +
+ in1[1][2] * in2[2][2];
+ out[1][3] = in1[1][0] * in2[0][3] + in1[1][1] * in2[1][3] +
+ in1[1][2] * in2[2][3] + in1[1][3];
+ out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] +
+ in1[2][2] * in2[2][0];
+ out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] +
+ in1[2][2] * in2[2][1];
+ out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] +
+ in1[2][2] * in2[2][2];
+ out[2][3] = in1[2][0] * in2[0][3] + in1[2][1] * in2[1][3] +
+ in1[2][2] * in2[2][3] + in1[2][3];
+}
+
+// angles index are not the same as ROLL, PITCH, YAW
+
+/*
+====================
+AngleQuaternion
+
+====================
+*/
+void AngleQuaternion( float *angles, vec4_t quaternion )
+{
+ float angle;
+ float sr, sp, sy, cr, cp, cy;
+
+ // FIXME: rescale the inputs to 1/2 angle
+ angle = angles[2] * 0.5;
+ sy = sin(angle);
+ cy = cos(angle);
+ angle = angles[1] * 0.5;
+ sp = sin(angle);
+ cp = cos(angle);
+ angle = angles[0] * 0.5;
+ sr = sin(angle);
+ cr = cos(angle);
+
+ quaternion[0] = sr*cp*cy-cr*sp*sy; // X
+ quaternion[1] = cr*sp*cy+sr*cp*sy; // Y
+ quaternion[2] = cr*cp*sy-sr*sp*cy; // Z
+ quaternion[3] = cr*cp*cy+sr*sp*sy; // W
+}
+
+/*
+====================
+QuaternionSlerp
+
+====================
+*/
+void QuaternionSlerp( vec4_t p, vec4_t q, float t, vec4_t qt )
+{
+ int i;
+ float omega, cosom, sinom, sclp, sclq;
+
+ // decide if one of the quaternions is backwards
+ float a = 0;
+ float b = 0;
+
+ for (i = 0; i < 4; i++)
+ {
+ a += (p[i]-q[i])*(p[i]-q[i]);
+ b += (p[i]+q[i])*(p[i]+q[i]);
+ }
+ if (a > b)
+ {
+ for (i = 0; i < 4; i++)
+ {
+ q[i] = -q[i];
+ }
+ }
+
+ cosom = p[0]*q[0] + p[1]*q[1] + p[2]*q[2] + p[3]*q[3];
+
+ if ((1.0 + cosom) > 0.000001)
+ {
+ if ((1.0 - cosom) > 0.000001)
+ {
+ omega = acos( cosom );
+ sinom = sin( omega );
+ sclp = sin( (1.0 - t)*omega) / sinom;
+ sclq = sin( t*omega ) / sinom;
+ }
+ else
+ {
+ sclp = 1.0 - t;
+ sclq = t;
+ }
+ for (i = 0; i < 4; i++) {
+ qt[i] = sclp * p[i] + sclq * q[i];
+ }
+ }
+ else
+ {
+ qt[0] = -q[1];
+ qt[1] = q[0];
+ qt[2] = -q[3];
+ qt[3] = q[2];
+ sclp = sin( (1.0 - t) * (0.5 * M_PI));
+ sclq = sin( t * (0.5 * M_PI));
+ for (i = 0; i < 3; i++)
+ {
+ qt[i] = sclp * p[i] + sclq * qt[i];
+ }
+ }
+}
+
+/*
+====================
+QuaternionMatrix
+
+====================
+*/
+void QuaternionMatrix( vec4_t quaternion, float (*matrix)[4] )
+{
+ matrix[0][0] = 1.0 - 2.0 * quaternion[1] * quaternion[1] - 2.0 * quaternion[2] * quaternion[2];
+ matrix[1][0] = 2.0 * quaternion[0] * quaternion[1] + 2.0 * quaternion[3] * quaternion[2];
+ matrix[2][0] = 2.0 * quaternion[0] * quaternion[2] - 2.0 * quaternion[3] * quaternion[1];
+
+ matrix[0][1] = 2.0 * quaternion[0] * quaternion[1] - 2.0 * quaternion[3] * quaternion[2];
+ matrix[1][1] = 1.0 - 2.0 * quaternion[0] * quaternion[0] - 2.0 * quaternion[2] * quaternion[2];
+ matrix[2][1] = 2.0 * quaternion[1] * quaternion[2] + 2.0 * quaternion[3] * quaternion[0];
+
+ matrix[0][2] = 2.0 * quaternion[0] * quaternion[2] + 2.0 * quaternion[3] * quaternion[1];
+ matrix[1][2] = 2.0 * quaternion[1] * quaternion[2] - 2.0 * quaternion[3] * quaternion[0];
+ matrix[2][2] = 1.0 - 2.0 * quaternion[0] * quaternion[0] - 2.0 * quaternion[1] * quaternion[1];
+}
+
+/*
+====================
+MatrixCopy
+
+====================
+*/
+void MatrixCopy( float in[3][4], float out[3][4] )
+{
+ memcpy( out, in, sizeof( float ) * 3 * 4 );
+}
diff --git a/main/source/cl_dll/studio_util.h b/main/source/cl_dll/studio_util.h
index 7e303d5e..53f611fc 100644
--- a/main/source/cl_dll/studio_util.h
+++ b/main/source/cl_dll/studio_util.h
@@ -1,32 +1,32 @@
-#if !defined( STUDIO_UTIL_H )
-#define STUDIO_UTIL_H
-#if defined( WIN32 )
-#pragma once
-#endif
-
-#ifndef M_PI
-#define M_PI 3.14159265358979323846 // matches value in gcc v2 math.h
-#endif
-
-#ifndef PITCH
-// MOVEMENT INFO
-// up / down
-#define PITCH 0
-// left / right
-#define YAW 1
-// fall over
-#define ROLL 2
-#endif
-
-#define FDotProduct( a, b ) (fabs((a[0])*(b[0])) + fabs((a[1])*(b[1])) + fabs((a[2])*(b[2])))
-void AngleMatrix (const float *angles, float (*matrix)[4] );
-int VectorCompare (const float *v1, const float *v2);
-void CrossProduct (const float *v1, const float *v2, float *cross);
-void VectorTransform (const float *in1, float in2[3][4], float *out);
-void ConcatTransforms (float in1[3][4], float in2[3][4], float out[3][4]);
-void MatrixCopy( float in[3][4], float out[3][4] );
-void QuaternionMatrix( vec4_t quaternion, float (*matrix)[4] );
-void QuaternionSlerp( vec4_t p, vec4_t q, float t, vec4_t qt );
-void AngleQuaternion( float *angles, vec4_t quaternion );
-
-#endif // STUDIO_UTIL_H
+#if !defined( STUDIO_UTIL_H )
+#define STUDIO_UTIL_H
+#if defined( WIN32 )
+#pragma once
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846 // matches value in gcc v2 math.h
+#endif
+
+#ifndef PITCH
+// MOVEMENT INFO
+// up / down
+#define PITCH 0
+// left / right
+#define YAW 1
+// fall over
+#define ROLL 2
+#endif
+
+#define FDotProduct( a, b ) (fabs((a[0])*(b[0])) + fabs((a[1])*(b[1])) + fabs((a[2])*(b[2])))
+void AngleMatrix (const float *angles, float (*matrix)[4] );
+int VectorCompare (const float *v1, const float *v2);
+void CrossProduct (const float *v1, const float *v2, float *cross);
+void VectorTransform (const float *in1, float in2[3][4], float *out);
+void ConcatTransforms (float in1[3][4], float in2[3][4], float out[3][4]);
+void MatrixCopy( float in[3][4], float out[3][4] );
+void QuaternionMatrix( vec4_t quaternion, float (*matrix)[4] );
+void QuaternionSlerp( vec4_t p, vec4_t q, float t, vec4_t qt );
+void AngleQuaternion( float *angles, vec4_t quaternion );
+
+#endif // STUDIO_UTIL_H
diff --git a/main/source/cl_dll/text_message.cpp b/main/source/cl_dll/text_message.cpp
index 5502b0a6..704f40bb 100644
--- a/main/source/cl_dll/text_message.cpp
+++ b/main/source/cl_dll/text_message.cpp
@@ -1,215 +1,215 @@
-/***
-*
-* Copyright (c) 1999, Valve LLC. All rights reserved.
-*
-* This product contains software technology licensed from Id
-* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
-* All Rights Reserved.
-*
-* Use, distribution, and modification of this source code and/or resulting
-* object code is restricted to non-commercial enhancements to products from
-* Valve LLC. All other use, distribution, or modification is prohibited
-* without written permission from Valve LLC.
-*
-****/
-//
-// text_message.cpp
-//
-// implementation of CHudTextMessage class
-//
-// this class routes messages through titles.txt for localisation
-//
-
-#include "hud.h"
-#include "cl_util.h"
-#include
-#include
-#include "mod/AvHNetworkMessages.h"
-
-#include "vgui_TeamFortressViewport.h"
-
-DECLARE_MESSAGE( m_TextMessage, TextMsg );
-
-int CHudTextMessage::Init(void)
-{
- HOOK_MESSAGE( TextMsg );
-
- gHUD.AddHudElem( this );
-
- Reset();
-
- return 1;
-};
-
-// Searches through the string for any msg names (indicated by a '#')
-// any found are looked up in titles.txt and the new message substituted
-// the new value is pushed into dst_buffer
-char *CHudTextMessage::LocaliseTextString( const char *msg, char *dst_buffer, int buffer_size )
-{
- char *dst = dst_buffer;
- for ( char *src = (char*)msg; *src != 0 && buffer_size > 0; buffer_size-- )
- {
- if ( *src == '#' )
- {
- // cut msg name out of string
- static char word_buf[255];
- char *wdst = word_buf, *word_start = src;
- for ( ++src ; (*src >= 'A' && *src <= 'z') || (*src >= '0' && *src <= '9'); wdst++, src++ )
- {
- *wdst = *src;
- }
- *wdst = 0;
-
- // lookup msg name in titles.txt
- client_textmessage_t *clmsg = TextMessageGet( word_buf );
- if ( !clmsg || !(clmsg->pMessage) )
- {
- src = word_start;
- *dst = *src;
- dst++, src++;
- continue;
- }
-
- // copy string into message over the msg name
- for ( char *wsrc = (char*)clmsg->pMessage; *wsrc != 0; wsrc++, dst++ )
- {
- *dst = *wsrc;
- }
- *dst = 0;
- }
- else
- {
- *dst = *src;
- dst++, src++;
- *dst = 0;
- }
- }
-
- dst_buffer[buffer_size-1] = 0; // ensure null termination
- return dst_buffer;
-}
-
-// As above, but with a local static buffer
-char *CHudTextMessage::BufferedLocaliseTextString( const char *msg )
-{
- static char dst_buffer[1024];
- LocaliseTextString( msg, dst_buffer, 1024 );
- return dst_buffer;
-}
-
-// Simplified version of LocaliseTextString; assumes string is only one word
-char *CHudTextMessage::LookupString( const char *msg, int *msg_dest )
-{
- if ( !msg )
- return "";
-
- // '#' character indicates this is a reference to a string in titles.txt, and not the string itself
- if ( msg[0] == '#' )
- {
- // this is a message name, so look up the real message
- client_textmessage_t *clmsg = TextMessageGet( msg+1 );
-
- if ( !clmsg || !(clmsg->pMessage) )
- return (char*)msg; // lookup failed, so return the original string
-
- if ( msg_dest )
- {
- // check to see if titles.txt info overrides msg destination
- // if clmsg->effect is less than 0, then clmsg->effect holds -1 * message_destination
- if ( clmsg->effect < 0 ) //
- *msg_dest = -clmsg->effect;
- }
-
- return (char*)clmsg->pMessage;
- }
- else
- { // nothing special about this message, so just return the same string
- return (char*)msg;
- }
-}
-
-void StripEndNewlineFromString( char *str )
-{
- int s = (int)strlen( str ) - 1;
- if ( str[s] == '\n' || str[s] == '\r' )
- str[s] = 0;
-}
-
-// converts all '\r' characters to '\n', so that the engine can deal with the properly
-// returns a pointer to str
-char* ConvertCRtoNL( char *str )
-{
- for ( char *ch = str; *ch != 0; ch++ )
- if ( *ch == '\r' )
- *ch = '\n';
- return str;
-}
-
-// Message handler for text messages
-// displays a string, looking them up from the titles.txt file, which can be localised
-// parameters:
-// byte: message direction ( HUD_PRINTCONSOLE, HUD_PRINTNOTIFY, HUD_PRINTCENTER, HUD_PRINTTALK )
-// string: message
-// optional parameters:
-// string: message parameter 1
-// string: message parameter 2
-// string: message parameter 3
-// string: message parameter 4
-// any string that starts with the character '#' is a message name, and is used to look up the real message in titles.txt
-// the next (optional) one to four strings are parameters for that string (which can also be message names if they begin with '#')
-int CHudTextMessage::MsgFunc_TextMsg( const char *pszName, int iSize, void *pbuf )
-{
- int destination;
- StringList message;
- NetMsg_TextMsg( pbuf, iSize, destination, message );
-
- if ( gViewPort && gViewPort->AllowedToPrintText() == FALSE )
- return 1;
-
- while( message.size() < 5 )
- { message.push_back( string("") ); }
- char psz[1024];
-
- char* origin = psz;
- if( destination == HUD_PRINTNOTIFY )
- {
- psz[0] = 1;
- origin = psz + 1;
- }
-
- // Ensure that message[0] does not contain exessive %'s, max 4x%s, all other %'s removed.
- size_t lastpos = 0; size_t pos; int count = 0;
- while(true)
- {
- pos = message[0].find("%", lastpos);
-
- if (pos == string::npos)
- break;
-
- if ((message[0].substr(pos + 1, 1) == "s") && (count < 4))
- count++;
- else
- message[0].replace(pos, 1, " ");
-
- lastpos = pos + 1;
- }
-
- sprintf( origin, message[0].c_str(), message[1].c_str(), message[2].c_str(), message[3].c_str(), message[4].c_str() );
- ConvertCRtoNL(psz);
-
- switch ( destination )
- {
- case HUD_PRINTNOTIFY:
- case HUD_PRINTCONSOLE:
- ConsolePrint(psz);
- break;
- case HUD_PRINTCENTER:
- CenterPrint(psz);
- break;
- case HUD_PRINTTALK:
- gHUD.m_SayText.SayTextPrint(psz, 1024);
- break;
- }
-
- return 1;
-}
+/***
+*
+* Copyright (c) 1999, Valve LLC. All rights reserved.
+*
+* This product contains software technology licensed from Id
+* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
+* All Rights Reserved.
+*
+* Use, distribution, and modification of this source code and/or resulting
+* object code is restricted to non-commercial enhancements to products from
+* Valve LLC. All other use, distribution, or modification is prohibited
+* without written permission from Valve LLC.
+*
+****/
+//
+// text_message.cpp
+//
+// implementation of CHudTextMessage class
+//
+// this class routes messages through titles.txt for localisation
+//
+
+#include "hud.h"
+#include "cl_util.h"
+#include
+#include
+#include "mod/AvHNetworkMessages.h"
+
+#include "vgui_TeamFortressViewport.h"
+
+DECLARE_MESSAGE( m_TextMessage, TextMsg );
+
+int CHudTextMessage::Init(void)
+{
+ HOOK_MESSAGE( TextMsg );
+
+ gHUD.AddHudElem( this );
+
+ Reset();
+
+ return 1;
+};
+
+// Searches through the string for any msg names (indicated by a '#')
+// any found are looked up in titles.txt and the new message substituted
+// the new value is pushed into dst_buffer
+char *CHudTextMessage::LocaliseTextString( const char *msg, char *dst_buffer, int buffer_size )
+{
+ char *dst = dst_buffer;
+ for ( char *src = (char*)msg; *src != 0 && buffer_size > 0; buffer_size-- )
+ {
+ if ( *src == '#' )
+ {
+ // cut msg name out of string
+ static char word_buf[255];
+ char *wdst = word_buf, *word_start = src;
+ for ( ++src ; (*src >= 'A' && *src <= 'z') || (*src >= '0' && *src <= '9'); wdst++, src++ )
+ {
+ *wdst = *src;
+ }
+ *wdst = 0;
+
+ // lookup msg name in titles.txt
+ client_textmessage_t *clmsg = TextMessageGet( word_buf );
+ if ( !clmsg || !(clmsg->pMessage) )
+ {
+ src = word_start;
+ *dst = *src;
+ dst++, src++;
+ continue;
+ }
+
+ // copy string into message over the msg name
+ for ( char *wsrc = (char*)clmsg->pMessage; *wsrc != 0; wsrc++, dst++ )
+ {
+ *dst = *wsrc;
+ }
+ *dst = 0;
+ }
+ else
+ {
+ *dst = *src;
+ dst++, src++;
+ *dst = 0;
+ }
+ }
+
+ dst_buffer[buffer_size-1] = 0; // ensure null termination
+ return dst_buffer;
+}
+
+// As above, but with a local static buffer
+char *CHudTextMessage::BufferedLocaliseTextString( const char *msg )
+{
+ static char dst_buffer[1024];
+ LocaliseTextString( msg, dst_buffer, 1024 );
+ return dst_buffer;
+}
+
+// Simplified version of LocaliseTextString; assumes string is only one word
+char *CHudTextMessage::LookupString( const char *msg, int *msg_dest )
+{
+ if ( !msg )
+ return "";
+
+ // '#' character indicates this is a reference to a string in titles.txt, and not the string itself
+ if ( msg[0] == '#' )
+ {
+ // this is a message name, so look up the real message
+ client_textmessage_t *clmsg = TextMessageGet( msg+1 );
+
+ if ( !clmsg || !(clmsg->pMessage) )
+ return (char*)msg; // lookup failed, so return the original string
+
+ if ( msg_dest )
+ {
+ // check to see if titles.txt info overrides msg destination
+ // if clmsg->effect is less than 0, then clmsg->effect holds -1 * message_destination
+ if ( clmsg->effect < 0 ) //
+ *msg_dest = -clmsg->effect;
+ }
+
+ return (char*)clmsg->pMessage;
+ }
+ else
+ { // nothing special about this message, so just return the same string
+ return (char*)msg;
+ }
+}
+
+void StripEndNewlineFromString( char *str )
+{
+ int s = (int)strlen( str ) - 1;
+ if ( str[s] == '\n' || str[s] == '\r' )
+ str[s] = 0;
+}
+
+// converts all '\r' characters to '\n', so that the engine can deal with the properly
+// returns a pointer to str
+char* ConvertCRtoNL( char *str )
+{
+ for ( char *ch = str; *ch != 0; ch++ )
+ if ( *ch == '\r' )
+ *ch = '\n';
+ return str;
+}
+
+// Message handler for text messages
+// displays a string, looking them up from the titles.txt file, which can be localised
+// parameters:
+// byte: message direction ( HUD_PRINTCONSOLE, HUD_PRINTNOTIFY, HUD_PRINTCENTER, HUD_PRINTTALK )
+// string: message
+// optional parameters:
+// string: message parameter 1
+// string: message parameter 2
+// string: message parameter 3
+// string: message parameter 4
+// any string that starts with the character '#' is a message name, and is used to look up the real message in titles.txt
+// the next (optional) one to four strings are parameters for that string (which can also be message names if they begin with '#')
+int CHudTextMessage::MsgFunc_TextMsg( const char *pszName, int iSize, void *pbuf )
+{
+ int destination;
+ StringList message;
+ NetMsg_TextMsg( pbuf, iSize, destination, message );
+
+ if ( gViewPort && gViewPort->AllowedToPrintText() == FALSE )
+ return 1;
+
+ while( message.size() < 5 )
+ { message.push_back( string("") ); }
+ char psz[1024];
+
+ char* origin = psz;
+ if( destination == HUD_PRINTNOTIFY )
+ {
+ psz[0] = 1;
+ origin = psz + 1;
+ }
+
+ // Ensure that message[0] does not contain exessive %'s, max 4x%s, all other %'s removed.
+ size_t lastpos = 0; size_t pos; int count = 0;
+ while(true)
+ {
+ pos = message[0].find("%", lastpos);
+
+ if (pos == string::npos)
+ break;
+
+ if ((message[0].substr(pos + 1, 1) == "s") && (count < 4))
+ count++;
+ else
+ message[0].replace(pos, 1, " ");
+
+ lastpos = pos + 1;
+ }
+
+ sprintf( origin, message[0].c_str(), message[1].c_str(), message[2].c_str(), message[3].c_str(), message[4].c_str() );
+ ConvertCRtoNL(psz);
+
+ switch ( destination )
+ {
+ case HUD_PRINTNOTIFY:
+ case HUD_PRINTCONSOLE:
+ ConsolePrint(psz);
+ break;
+ case HUD_PRINTCENTER:
+ CenterPrint(psz);
+ break;
+ case HUD_PRINTTALK:
+ gHUD.m_SayText.SayTextPrint(psz, 1024);
+ break;
+ }
+
+ return 1;
+}
diff --git a/main/source/cl_dll/tf_defs.h b/main/source/cl_dll/tf_defs.h
index 2e0ead56..c3a0c154 100644
--- a/main/source/cl_dll/tf_defs.h
+++ b/main/source/cl_dll/tf_defs.h
@@ -1,1387 +1,1387 @@
-/***
-*
-* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
-*
-* This product contains software technology licensed from Id
-* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
-* All Rights Reserved.
-*
-****/
-
-#ifndef __TF_DEFS_H
-#define __TF_DEFS_H
-
-//===========================================================================
-// OLD OPTIONS.QC
-//===========================================================================
-#define DEFAULT_AUTOZOOM FALSE
-#define WEINER_SNIPER // autoaiming for sniper rifle
-#define FLAME_MAXWORLDNUM 20 // maximum number of flames in the world. DO NOT PUT BELOW 20.
-
-//#define MAX_WORLD_PIPEBOMBS 15 // This is divided between teams - this is the most you should have on a net server
-#define MAX_PLAYER_PIPEBOMBS 8 // maximum number of pipebombs any 1 player can have active
-#define MAX_PLAYER_AMMOBOXES 3 // maximum number of ammoboxes any 1 player can have active
-
-//#define MAX_WORLD_FLARES 9 // This is the total number of flares allowed in the world at one time
-//#define MAX_WORLD_AMMOBOXES 20 // This is divided between teams - this is the most you should have on a net server
-#define GR_TYPE_MIRV_NO 4 // Number of Mirvs a Mirv Grenade breaks into
-#define GR_TYPE_NAPALM_NO 8 // Number of flames napalm grenade breaks into (unused if net server)
-#define MEDIKIT_IS_BIOWEAPON // Medikit acts as a bioweapon against enemies
-
-#define TEAM_HELP_RATE 60 // used only if teamplay bit 64 (help team with lower score) is set.
- // 60 is a mild setting, and won't make too much difference
- // increasing it _decreases_ the amount of help the losing team gets
- // Minimum setting is 1, which would really help the losing team
-
-#define DISPLAY_CLASS_HELP TRUE // Change this to #OFF if you don't want the class help to
- // appear whenever a player connects
-#define NEVER_TEAMFRAGS FALSE // teamfrags options always off
-#define ALWAYS_TEAMFRAGS FALSE // teamfrags options always on
-#define CHECK_SPEEDS TRUE // makes sure players aren't moving too fast
-#define SNIPER_RIFLE_RELOAD_TIME 1.5 // seconds
-
-#define MAPBRIEFING_MAXTEXTLENGTH 512
-#define PLAYER_PUSH_VELOCITY 50 // Players push teammates if they're moving under this speed
-
-// Debug Options
-//#define MAP_DEBUG // Debug for Map code. I suggest running in a hi-res
- // mode and/or piping the output from the server to a file.
-#ifdef MAP_DEBUG
- #define MDEBUG(x) x
-#else
- #define MDEBUG(x)
-#endif
-//#define VERBOSE // Verbose Debugging on/off
-
-//===========================================================================
-// OLD QUAKE Defs
-//===========================================================================
-// items
-#define IT_AXE 4096
-#define IT_SHOTGUN 1
-#define IT_SUPER_SHOTGUN 2
-#define IT_NAILGUN 4
-#define IT_SUPER_NAILGUN 8
-#define IT_GRENADE_LAUNCHER 16
-#define IT_ROCKET_LAUNCHER 32
-#define IT_LIGHTNING 64
-#define IT_EXTRA_WEAPON 128
-
-#define IT_SHELLS 256
-#define IT_NAILS 512
-#define IT_ROCKETS 1024
-#define IT_CELLS 2048
-
-#define IT_ARMOR1 8192
-#define IT_ARMOR2 16384
-#define IT_ARMOR3 32768
-#define IT_SUPERHEALTH 65536
-
-#define IT_KEY1 131072
-#define IT_KEY2 262144
-
-#define IT_INVISIBILITY 524288
-#define IT_INVULNERABILITY 1048576
-#define IT_SUIT 2097152
-#define IT_QUAD 4194304
-#define IT_HOOK 8388608
-
-#define IT_KEY3 16777216 // Stomp invisibility
-#define IT_KEY4 33554432 // Stomp invulnerability
-
-//===========================================================================
-// TEAMFORTRESS Defs
-//===========================================================================
-// TeamFortress State Flags
-#define TFSTATE_GRENPRIMED 1 // Whether the player has a primed grenade
-#define TFSTATE_RELOADING 2 // Whether the player is reloading
-#define TFSTATE_ALTKILL 4 // #TRUE if killed with a weapon not in self.weapon: NOT USED ANYMORE
-#define TFSTATE_RANDOMPC 8 // Whether Playerclass is random, new one each respawn
-#define TFSTATE_INFECTED 16 // set when player is infected by the bioweapon
-#define TFSTATE_INVINCIBLE 32 // Player has permanent Invincibility (Usually by GoalItem)
-#define TFSTATE_INVISIBLE 64 // Player has permanent Invisibility (Usually by GoalItem)
-#define TFSTATE_QUAD 128 // Player has permanent Quad Damage (Usually by GoalItem)
-#define TFSTATE_RADSUIT 256 // Player has permanent Radsuit (Usually by GoalItem)
-#define TFSTATE_BURNING 512 // Is on fire
-#define TFSTATE_GRENTHROWING 1024 // is throwing a grenade
-#define TFSTATE_AIMING 2048 // is using the laser sight
-#define TFSTATE_ZOOMOFF 4096 // doesn't want the FOV changed when zooming
-#define TFSTATE_RESPAWN_READY 8192 // is waiting for respawn, and has pressed fire
-#define TFSTATE_HALLUCINATING 16384 // set when player is hallucinating
-#define TFSTATE_TRANQUILISED 32768 // set when player is tranquilised
-#define TFSTATE_CANT_MOVE 65536 // set when player is setting a detpack
-#define TFSTATE_RESET_FLAMETIME 131072 // set when the player has to have his flames increased in health
-
-// Defines used by TF_T_Damage (see combat.qc)
-#define TF_TD_IGNOREARMOUR 1 // Bypasses the armour of the target
-#define TF_TD_NOTTEAM 2 // Doesn't damage a team member (indicates direct fire weapon)
-#define TF_TD_NOTSELF 4 // Doesn't damage self
-
-#define TF_TD_OTHER 0 // Ignore armorclass
-#define TF_TD_SHOT 1 // Bullet damage
-#define TF_TD_NAIL 2 // Nail damage
-#define TF_TD_EXPLOSION 4 // Explosion damage
-#define TF_TD_ELECTRICITY 8 // Electric damage
-#define TF_TD_FIRE 16 // Fire damage
-#define TF_TD_NOSOUND 256 // Special damage. Makes no sound/painframe, etc
-
-/*==================================================*/
-/* Toggleable Game Settings */
-/*==================================================*/
-#define TF_RESPAWNDELAY1 5 // seconds of waiting before player can respawn
-#define TF_RESPAWNDELAY2 10 // seconds of waiting before player can respawn
-#define TF_RESPAWNDELAY3 20 // seconds of waiting before player can respawn
-
-#define TEAMPLAY_NORMAL 1
-#define TEAMPLAY_HALFDIRECT 2
-#define TEAMPLAY_NODIRECT 4
-#define TEAMPLAY_HALFEXPLOSIVE 8
-#define TEAMPLAY_NOEXPLOSIVE 16
-#define TEAMPLAY_LESSPLAYERSHELP 32
-#define TEAMPLAY_LESSSCOREHELP 64
-#define TEAMPLAY_HALFDIRECTARMOR 128
-#define TEAMPLAY_NODIRECTARMOR 256
-#define TEAMPLAY_HALFEXPARMOR 512
-#define TEAMPLAY_NOEXPARMOR 1024
-#define TEAMPLAY_HALFDIRMIRROR 2048
-#define TEAMPLAY_FULLDIRMIRROR 4096
-#define TEAMPLAY_HALFEXPMIRROR 8192
-#define TEAMPLAY_FULLEXPMIRROR 16384
-
-#define TEAMPLAY_TEAMDAMAGE (TEAMPLAY_NODIRECT | TEAMPLAY_HALFDIRECT | TEAMPLAY_HALFEXPLOSIVE | TEAMPLAY_NOEXPLOSIVE)
-// FortressMap stuff
-#define TEAM1_CIVILIANS 1
-#define TEAM2_CIVILIANS 2
-#define TEAM3_CIVILIANS 4
-#define TEAM4_CIVILIANS 8
-
-// Defines for the playerclass
-#define PC_UNDEFINED 0
-
-#define PC_SCOUT 1
-#define PC_SNIPER 2
-#define PC_SOLDIER 3
-#define PC_DEMOMAN 4
-#define PC_MEDIC 5
-#define PC_HVYWEAP 6
-#define PC_PYRO 7
-#define PC_SPY 8
-#define PC_ENGINEER 9
-
-// Insert new class definitions here
-
-// PC_RANDOM _MUST_ be the third last class
-#define PC_RANDOM 10 // Random playerclass
-#define PC_CIVILIAN 11 // Civilians are a special class. They cannot
- // be chosen by players, only enforced by maps
-#define PC_LASTCLASS 12 // Use this as the high-boundary for any loops
- // through the playerclass.
-
-#define SENTRY_COLOR 10 // will be in the PC_RANDOM slot for team colors
-// These are just for the scanner
-#define SCAN_SENTRY 13
-#define SCAN_GOALITEM 14
-
-// Values returned by CheckArea
-enum
-{
- CAREA_CLEAR,
- CAREA_BLOCKED,
- CAREA_NOBUILD
-};
-
-/*==================================================*/
-/* Impulse Defines */
-/*==================================================*/
-// Alias check to see whether they already have the aliases
-#define TF_ALIAS_CHECK 13
-
-// CTF Support Impulses
-#define HOOK_IMP1 22
-#define FLAG_INFO 23
-#define HOOK_IMP2 39
-
-// Axe
-#define AXE_IMP 40
-
-// Camera Impulse
-#define TF_CAM_TARGET 50
-#define TF_CAM_ZOOM 51
-#define TF_CAM_ANGLE 52
-#define TF_CAM_VEC 53
-#define TF_CAM_PROJECTILE 54
-#define TF_CAM_PROJECTILE_Z 55
-#define TF_CAM_REVANGLE 56
-#define TF_CAM_OFFSET 57
-#define TF_CAM_DROP 58
-#define TF_CAM_FADETOBLACK 59
-#define TF_CAM_FADEFROMBLACK 60
-#define TF_CAM_FADETOWHITE 61
-#define TF_CAM_FADEFROMWHITE 62
-
-// Last Weapon impulse
-#define TF_LAST_WEAPON 69
-
-// Status Bar Resolution Settings. Same as CTF to maintain ease of use.
-#define TF_STATUSBAR_RES_START 71
-#define TF_STATUSBAR_RES_END 81
-
-// Clan Messages
-#define TF_MESSAGE_1 82
-#define TF_MESSAGE_2 83
-#define TF_MESSAGE_3 84
-#define TF_MESSAGE_4 85
-#define TF_MESSAGE_5 86
-
-#define TF_CHANGE_CLASS 99 // Bring up the Class Change menu
-
-// Added to PC_??? to get impulse to use if this clashes with your
-// own impulses, just change this value, not the PC_??
-#define TF_CHANGEPC 100
-// The next few impulses are all the class selections
-//PC_SCOUT 101
-//PC_SNIPER 102
-//PC_SOLDIER 103
-//PC_DEMOMAN 104
-//PC_MEDIC 105
-//PC_HVYWEAP 106
-//PC_PYRO 107
-//PC_RANDOM 108
-//PC_CIVILIAN 109 // Cannot be used
-//PC_SPY 110
-//PC_ENGINEER 111
-
-// Help impulses
-#define TF_DISPLAYLOCATION 118
-#define TF_STATUS_QUERY 119
-
-#define TF_HELP_MAP 131
-
-// Information impulses
-#define TF_INVENTORY 135
-#define TF_SHOWTF 136
-#define TF_SHOWLEGALCLASSES 137
-
-// Team Impulses
-#define TF_TEAM_1 140 // Join Team 1
-#define TF_TEAM_2 141 // Join Team 2
-#define TF_TEAM_3 142 // Join Team 3
-#define TF_TEAM_4 143 // Join Team 4
-#define TF_TEAM_CLASSES 144 // Impulse to display team classes
-#define TF_TEAM_SCORES 145 // Impulse to display team scores
-#define TF_TEAM_LIST 146 // Impulse to display the players in each team.
-
-// Grenade Impulses
-#define TF_GRENADE_1 150 // Prime grenade type 1
-#define TF_GRENADE_2 151 // Prime grenade type 2
-#define TF_GRENADE_T 152 // Throw primed grenade
-
-// Impulses for new items
-//#define TF_SCAN 159 // Scanner Pre-Impulse
-#define TF_AUTO_SCAN 159 // Scanner On/Off
-#define TF_SCAN_ENEMY 160 // Impulses to toggle scanning of enemies
-#define TF_SCAN_FRIENDLY 161 // Impulses to toggle scanning of friendlies
-//#define TF_SCAN_10 162 // Scan using 10 enery (1 cell)
-#define TF_SCAN_SOUND 162 // Scanner sounds on/off
-#define TF_SCAN_30 163 // Scan using 30 energy (2 cells)
-#define TF_SCAN_100 164 // Scan using 100 energy (5 cells)
-#define TF_DETPACK_5 165 // Detpack set to 5 seconds
-#define TF_DETPACK_20 166 // Detpack set to 20 seconds
-#define TF_DETPACK_50 167 // Detpack set to 50 seconds
-#define TF_DETPACK 168 // Detpack Pre-Impulse
-#define TF_DETPACK_STOP 169 // Impulse to stop setting detpack
-#define TF_PB_DETONATE 170 // Detonate Pipebombs
-
-// Special skill
-#define TF_SPECIAL_SKILL 171
-
-// Ammo Drop impulse
-#define TF_DROP_AMMO 172
-
-// Reload impulse
-#define TF_RELOAD 173
-
-// auto-zoom toggle
-#define TF_AUTOZOOM 174
-
-// drop/pass commands
-#define TF_DROPKEY 175
-
-// Select Medikit
-#define TF_MEDIKIT 176
-
-// Spy Impulses
-#define TF_SPY_SPY 177 // On net, go invisible, on LAN, change skin/color
-#define TF_SPY_DIE 178 // Feign Death
-
-// Engineer Impulses
-#define TF_ENGINEER_BUILD 179
-#define TF_ENGINEER_SANDBAG 180
-
-// Medic
-#define TF_MEDIC_HELPME 181
-
-// Status bar
-#define TF_STATUSBAR_ON 182
-#define TF_STATUSBAR_OFF 183
-
-// Discard impulse
-#define TF_DISCARD 184
-
-// ID Player impulse
-#define TF_ID 185
-
-// Clan Battle impulses
-#define TF_SHOWIDS 186
-
-// More Engineer Impulses
-#define TF_ENGINEER_DETDISP 187
-#define TF_ENGINEER_DETSENT 188
-
-// Admin Commands
-#define TF_ADMIN_DEAL_CYCLE 189
-#define TF_ADMIN_KICK 190
-#define TF_ADMIN_BAN 191
-#define TF_ADMIN_COUNTPLAYERS 192
-#define TF_ADMIN_CEASEFIRE 193
-
-// Drop Goal Items
-#define TF_DROPGOALITEMS 194
-
-// More Admin Commands
-#define TF_ADMIN_NEXT 195
-
-// More Engineer Impulses
-#define TF_ENGINEER_DETEXIT 196
-#define TF_ENGINEER_DETENTRANCE 197
-
-// Yet MORE Admin Commands
-#define TF_ADMIN_LISTIPS 198
-
-// Silent Spy Feign
-#define TF_SPY_SILENTDIE 199
-
-
-/*==================================================*/
-/*==================================================*/
-#define TEAM1_COLOR 150
-#define TEAM2_COLOR 250
-#define TEAM3_COLOR 45
-#define TEAM4_COLOR 100
-
-/*==================================================*/
-/* Defines for the ENGINEER's Building ability */
-/*==================================================*/
-// Ammo costs
-#define AMMO_COST_SHELLS 2 // Metal needed to make 1 shell
-#define AMMO_COST_NAILS 1
-#define AMMO_COST_ROCKETS 2
-#define AMMO_COST_CELLS 2
-
-// Building types
-#define BUILD_DISPENSER 1
-#define BUILD_SENTRYGUN 2
-#define BUILD_MORTAR 3
-#define BUILD_TELEPORTER_ENTRANCE 4
-#define BUILD_TELEPORTER_EXIT 5
-
-// Building metal costs
-#define BUILD_COST_DISPENSER 100 // Metal needed to built
-#define BUILD_COST_SENTRYGUN 130
-#define BUILD_COST_MORTAR 150
-#define BUILD_COST_TELEPORTER 125
-
-#define BUILD_COST_SANDBAG 20 // Built with a separate alias
-
-// Building times
-#define BUILD_TIME_DISPENSER 2 // seconds to build
-#define BUILD_TIME_SENTRYGUN 5
-#define BUILD_TIME_MORTAR 5
-#define BUILD_TIME_TELEPORTER 4
-
-// Building health levels
-#define BUILD_HEALTH_DISPENSER 150 // Health of the building
-#define BUILD_HEALTH_SENTRYGUN 150
-#define BUILD_HEALTH_MORTAR 200
-#define BUILD_HEALTH_TELEPORTER 80
-
-// Dispenser's maximum carrying capability
-#define BUILD_DISPENSER_MAX_SHELLS 400
-#define BUILD_DISPENSER_MAX_NAILS 600
-#define BUILD_DISPENSER_MAX_ROCKETS 300
-#define BUILD_DISPENSER_MAX_CELLS 400
-#define BUILD_DISPENSER_MAX_ARMOR 500
-
-// Build state sent down to client
-#define BS_BUILDING (1<<0)
-#define BS_HAS_DISPENSER (1<<1)
-#define BS_HAS_SENTRYGUN (1<<2)
-#define BS_CANB_DISPENSER (1<<3)
-#define BS_CANB_SENTRYGUN (1<<4)
-/*==================================================*/
-/* Ammo quantities for dropping & dispenser use */
-/*==================================================*/
-#define DROP_SHELLS 20
-#define DROP_NAILS 20
-#define DROP_ROCKETS 10
-#define DROP_CELLS 10
-#define DROP_ARMOR 40
-
-/*==================================================*/
-/* Team Defines */
-/*==================================================*/
-#define TM_MAX_NO 4 // Max number of teams. Simply changing this value isn't enough.
- // A new global to hold new team colors is needed, and more flags
- // in the spawnpoint spawnflags may need to be used.
- // Basically, don't change this unless you know what you're doing :)
-
-/*==================================================*/
-/* New Weapon Defines */
-/*==================================================*/
-#define WEAP_HOOK 1
-#define WEAP_BIOWEAPON 2
-#define WEAP_MEDIKIT 4
-#define WEAP_SPANNER 8
-#define WEAP_AXE 16
-#define WEAP_SNIPER_RIFLE 32
-#define WEAP_AUTO_RIFLE 64
-#define WEAP_SHOTGUN 128
-#define WEAP_SUPER_SHOTGUN 256
-#define WEAP_NAILGUN 512
-#define WEAP_SUPER_NAILGUN 1024
-#define WEAP_GRENADE_LAUNCHER 2048
-#define WEAP_FLAMETHROWER 4096
-#define WEAP_ROCKET_LAUNCHER 8192
-#define WEAP_INCENDIARY 16384
-#define WEAP_ASSAULT_CANNON 32768
-#define WEAP_LIGHTNING 65536
-#define WEAP_DETPACK 131072
-#define WEAP_TRANQ 262144
-#define WEAP_LASER 524288
-// still room for 12 more weapons
-// but we can remove some by giving the weapons
-// a weapon mode (like the rifle)
-
-// HL-compatible weapon numbers
-#define WEAPON_HOOK 1
-#define WEAPON_BIOWEAPON (WEAPON_HOOK+1)
-#define WEAPON_MEDIKIT (WEAPON_HOOK+2)
-#define WEAPON_SPANNER (WEAPON_HOOK+3)
-#define WEAPON_AXE (WEAPON_HOOK+4)
-#define WEAPON_SNIPER_RIFLE (WEAPON_HOOK+5)
-#define WEAPON_AUTO_RIFLE (WEAPON_HOOK+6)
-#define WEAPON_TF_SHOTGUN (WEAPON_HOOK+7)
-#define WEAPON_SUPER_SHOTGUN (WEAPON_HOOK+8)
-#define WEAPON_NAILGUN (WEAPON_HOOK+9)
-#define WEAPON_SUPER_NAILGUN (WEAPON_HOOK+10)
-#define WEAPON_GRENADE_LAUNCHER (WEAPON_HOOK+11)
-#define WEAPON_FLAMETHROWER (WEAPON_HOOK+12)
-#define WEAPON_ROCKET_LAUNCHER (WEAPON_HOOK+13)
-#define WEAPON_INCENDIARY (WEAPON_HOOK+14)
-#define WEAPON_ASSAULT_CANNON (WEAPON_HOOK+16)
-#define WEAPON_LIGHTNING (WEAPON_HOOK+17)
-#define WEAPON_DETPACK (WEAPON_HOOK+18)
-#define WEAPON_TRANQ (WEAPON_HOOK+19)
-#define WEAPON_LASER (WEAPON_HOOK+20)
-#define WEAPON_PIPEBOMB_LAUNCHER (WEAPON_HOOK+21)
-#define WEAPON_KNIFE (WEAPON_HOOK+22)
-#define WEAPON_BENCHMARK (WEAPON_HOOK+23)
-
-/*==================================================*/
-/* New Weapon Related Defines */
-/*==================================================*/
-// shots per reload
-#define RE_SHOTGUN 8
-#define RE_SUPER_SHOTGUN 16 // 8 shots
-#define RE_GRENADE_LAUNCHER 6
-#define RE_ROCKET_LAUNCHER 4
-
-// reload times
-#define RE_SHOTGUN_TIME 2
-#define RE_SUPER_SHOTGUN_TIME 3
-#define RE_GRENADE_LAUNCHER_TIME 4
-#define RE_ROCKET_LAUNCHER_TIME 5
-
-// Maximum velocity you can move and fire the Sniper Rifle
-#define WEAP_SNIPER_RIFLE_MAX_MOVE 50
-
-// Medikit
-#define WEAP_MEDIKIT_HEAL 200 // Amount medikit heals per hit
-#define WEAP_MEDIKIT_OVERHEAL 50 // Amount of superhealth over max_health the medikit will dispense
-
-// Spanner
-#define WEAP_SPANNER_REPAIR 10
-
-// Detpack
-#define WEAP_DETPACK_DISARMTIME 3 // Time it takes to disarm a Detpack
-#define WEAP_DETPACK_SETTIME 3 // Time it takes to set a Detpack
-#define WEAP_DETPACK_SIZE 700 // Explosion Size
-#define WEAP_DETPACK_GOAL_SIZE 1500 // Explosion Size for goal triggering
-#define WEAP_DETPACK_BITS_NO 12 // Bits that detpack explodes into
-
-// Tranquiliser Gun
-#define TRANQ_TIME 15
-
-// Grenades
-#define GR_PRIMETIME 3
-#define GR_CALTROP_PRIME 0.5
-#define GR_TYPE_NONE 0
-#define GR_TYPE_NORMAL 1
-#define GR_TYPE_CONCUSSION 2
-#define GR_TYPE_NAIL 3
-#define GR_TYPE_MIRV 4
-#define GR_TYPE_NAPALM 5
-//#define GR_TYPE_FLARE 6
-#define GR_TYPE_GAS 7
-#define GR_TYPE_EMP 8
-#define GR_TYPE_CALTROP 9
-//#define GR_TYPE_FLASH 10
-
-// Defines for WeaponMode
-#define GL_NORMAL 0
-#define GL_PIPEBOMB 1
-
-// Defines for OLD Concussion Grenade
-#define GR_OLD_CONCUSS_TIME 5
-#define GR_OLD_CONCUSS_DEC 20
-
-// Defines for Concussion Grenade
-#define GR_CONCUSS_TIME 0.25
-#define GR_CONCUSS_DEC 10
-#define MEDIUM_PING 150
-#define HIGH_PING 200
-
-// Defines for the Gas Grenade
-#define GR_HALLU_TIME 0.3
-#define GR_OLD_HALLU_TIME 0.5
-#define GR_HALLU_DEC 2.5
-
-// Defines for the BioInfection
-#define BIO_JUMP_RADIUS 128 // The distance the bioinfection can jump between players
-
-/*==================================================*/
-/* New Items */
-/*==================================================*/
-#define NIT_SCANNER 1
-
-#define NIT_SILVER_DOOR_OPENED #IT_KEY1 // 131072
-#define NIT_GOLD_DOOR_OPENED #IT_KEY2 // 262144
-
-/*==================================================*/
-/* New Item Flags */
-/*==================================================*/
-#define NIT_SCANNER_ENEMY 1 // Detect enemies
-#define NIT_SCANNER_FRIENDLY 2 // Detect friendlies (team members)
-#define NIT_SCANNER_SOUND 4 // Motion detection. Only report moving entities.
-
-/*==================================================*/
-/* New Item Related Defines */
-/*==================================================*/
-#define NIT_SCANNER_POWER 25 // The amount of power spent on a scan with the scanner
- // is multiplied by this to get the scanrange.
-#define NIT_SCANNER_MAXCELL 50 // The maximum number of cells than can be used in one scan
-#define NIT_SCANNER_MIN_MOVEMENT 50 // The minimum velocity an entity must have to be detected
- // by scanners that only detect movement
-
-/*==================================================*/
-/* Variables used for New Weapons and Reloading */
-/*==================================================*/
-// Armor Classes : Bitfields. Use the "armorclass" of armor for the Armor Type.
-#define AT_SAVESHOT 1 // Kevlar : Reduces bullet damage by 15%
-#define AT_SAVENAIL 2 // Wood :) : Reduces nail damage by 15%
-#define AT_SAVEEXPLOSION 4 // Blast : Reduces explosion damage by 15%
-#define AT_SAVEELECTRICITY 8 // Shock : Reduces electricity damage by 15%
-#define AT_SAVEFIRE 16 // Asbestos : Reduces fire damage by 15%
-
-/*==========================================================================*/
-/* TEAMFORTRESS CLASS DETAILS */
-/*==========================================================================*/
-// Class Details for SCOUT
-#define PC_SCOUT_SKIN 4 // Skin for this class when Classkin is on.
-#define PC_SCOUT_MAXHEALTH 75 // Maximum Health Level
-#define PC_SCOUT_MAXSPEED 400 // Maximum movement speed
-#define PC_SCOUT_MAXSTRAFESPEED 400 // Maximum strafing movement speed
-#define PC_SCOUT_MAXARMOR 50 // Maximum Armor Level, of any armor class
-#define PC_SCOUT_INITARMOR 25 // Armor level when respawned
-#define PC_SCOUT_MAXARMORTYPE 0.3 // Maximum level of Armor absorption
-#define PC_SCOUT_INITARMORTYPE 0.3 // Absorption Level of armor when respawned
-#define PC_SCOUT_ARMORCLASSES 3 // #AT_SAVESHOT | #AT_SAVENAIL <-Armor Classes allowed for this class
-#define PC_SCOUT_INITARMORCLASS 0 // Armorclass worn when respawned
-#define PC_SCOUT_WEAPONS WEAP_AXE | WEAP_SHOTGUN | WEAP_NAILGUN
-#define PC_SCOUT_MAXAMMO_SHOT 50 // Maximum amount of shot ammo this class can carry
-#define PC_SCOUT_MAXAMMO_NAIL 200 // Maximum amount of nail ammo this class can carry
-#define PC_SCOUT_MAXAMMO_CELL 100 // Maximum amount of cell ammo this class can carry
-#define PC_SCOUT_MAXAMMO_ROCKET 25 // Maximum amount of rocket ammo this class can carry
-#define PC_SCOUT_INITAMMO_SHOT 25 // Amount of shot ammo this class has when respawned
-#define PC_SCOUT_INITAMMO_NAIL 100 // Amount of nail ammo this class has when respawned
-#define PC_SCOUT_INITAMMO_CELL 50 // Amount of cell ammo this class has when respawned
-#define PC_SCOUT_INITAMMO_ROCKET 0 // Amount of rocket ammo this class has when respawned
-#define PC_SCOUT_GRENADE_TYPE_1 GR_TYPE_CALTROP // <- 1st Type of Grenade this class has
-#define PC_SCOUT_GRENADE_TYPE_2 GR_TYPE_CONCUSSION // <- 2nd Type of Grenade this class has
-#define PC_SCOUT_GRENADE_INIT_1 2 // Number of grenades of Type 1 this class has when respawned
-#define PC_SCOUT_GRENADE_INIT_2 3 // Number of grenades of Type 2 this class has when respawned
-#define PC_SCOUT_TF_ITEMS NIT_SCANNER // <- TeamFortress Items this class has
-
-#define PC_SCOUT_MOTION_MIN_I 0.5 // < Short range
-#define PC_SCOUT_MOTION_MIN_MOVE 50 // Minimum vlen of player velocity to be picked up by motion detector
-#define PC_SCOUT_SCAN_TIME 2 // # of seconds between each scan pulse
-#define PC_SCOUT_SCAN_RANGE 100 // Default scanner range
-#define PC_SCOUT_SCAN_COST 2 // Default scanner cell useage per scan
-
-// Class Details for SNIPER
-#define PC_SNIPER_SKIN 5
-#define PC_SNIPER_MAXHEALTH 90
-#define PC_SNIPER_MAXSPEED 300
-#define PC_SNIPER_MAXSTRAFESPEED 300
-#define PC_SNIPER_MAXARMOR 50
-#define PC_SNIPER_INITARMOR 0
-#define PC_SNIPER_MAXARMORTYPE 0.3
-#define PC_SNIPER_INITARMORTYPE 0.3
-#define PC_SNIPER_ARMORCLASSES 3 // #AT_SAVESHOT | #AT_SAVENAIL
-#define PC_SNIPER_INITARMORCLASS 0
-#define PC_SNIPER_WEAPONS WEAP_SNIPER_RIFLE | WEAP_AUTO_RIFLE | WEAP_AXE | WEAP_NAILGUN
-#define PC_SNIPER_MAXAMMO_SHOT 75
-#define PC_SNIPER_MAXAMMO_NAIL 100
-#define PC_SNIPER_MAXAMMO_CELL 50
-#define PC_SNIPER_MAXAMMO_ROCKET 25
-#define PC_SNIPER_INITAMMO_SHOT 60
-#define PC_SNIPER_INITAMMO_NAIL 50
-#define PC_SNIPER_INITAMMO_CELL 0
-#define PC_SNIPER_INITAMMO_ROCKET 0
-#define PC_SNIPER_GRENADE_TYPE_1 GR_TYPE_NORMAL
-#define PC_SNIPER_GRENADE_TYPE_2 GR_TYPE_NONE
-#define PC_SNIPER_GRENADE_INIT_1 2
-#define PC_SNIPER_GRENADE_INIT_2 0
-#define PC_SNIPER_TF_ITEMS 0
-
-// Class Details for SOLDIER
-#define PC_SOLDIER_SKIN 6
-#define PC_SOLDIER_MAXHEALTH 100
-#define PC_SOLDIER_MAXSPEED 240
-#define PC_SOLDIER_MAXSTRAFESPEED 240
-#define PC_SOLDIER_MAXARMOR 200
-#define PC_SOLDIER_INITARMOR 100
-#define PC_SOLDIER_MAXARMORTYPE 0.8
-#define PC_SOLDIER_INITARMORTYPE 0.8
-#define PC_SOLDIER_ARMORCLASSES 31 // ALL
-#define PC_SOLDIER_INITARMORCLASS 0
-#define PC_SOLDIER_WEAPONS WEAP_AXE | WEAP_SHOTGUN | WEAP_SUPER_SHOTGUN | WEAP_ROCKET_LAUNCHER
-#define PC_SOLDIER_MAXAMMO_SHOT 100
-#define PC_SOLDIER_MAXAMMO_NAIL 100
-#define PC_SOLDIER_MAXAMMO_CELL 50
-#define PC_SOLDIER_MAXAMMO_ROCKET 50
-#define PC_SOLDIER_INITAMMO_SHOT 50
-#define PC_SOLDIER_INITAMMO_NAIL 0
-#define PC_SOLDIER_INITAMMO_CELL 0
-#define PC_SOLDIER_INITAMMO_ROCKET 10
-#define PC_SOLDIER_GRENADE_TYPE_1 GR_TYPE_NORMAL
-#define PC_SOLDIER_GRENADE_TYPE_2 GR_TYPE_NAIL
-#define PC_SOLDIER_GRENADE_INIT_1 2
-#define PC_SOLDIER_GRENADE_INIT_2 1
-#define PC_SOLDIER_TF_ITEMS 0
-
-#define MAX_NAIL_GRENS 2 // Can only have 2 Nail grens active
-#define MAX_NAPALM_GRENS 2 // Can only have 2 Napalm grens active
-#define MAX_GAS_GRENS 2 // Can only have 2 Gas grenades active
-#define MAX_MIRV_GRENS 2 // Can only have 2 Mirv's
-#define MAX_CONCUSSION_GRENS 3
-#define MAX_CALTROP_CANS 3
-
-// Class Details for DEMOLITION MAN
-#define PC_DEMOMAN_SKIN 1
-#define PC_DEMOMAN_MAXHEALTH 90
-#define PC_DEMOMAN_MAXSPEED 280
-#define PC_DEMOMAN_MAXSTRAFESPEED 280
-#define PC_DEMOMAN_MAXARMOR 120
-#define PC_DEMOMAN_INITARMOR 50
-#define PC_DEMOMAN_MAXARMORTYPE 0.6
-#define PC_DEMOMAN_INITARMORTYPE 0.6
-#define PC_DEMOMAN_ARMORCLASSES 31 // ALL
-#define PC_DEMOMAN_INITARMORCLASS 0
-#define PC_DEMOMAN_WEAPONS WEAP_AXE | WEAP_SHOTGUN | WEAP_GRENADE_LAUNCHER | WEAP_DETPACK
-#define PC_DEMOMAN_MAXAMMO_SHOT 75
-#define PC_DEMOMAN_MAXAMMO_NAIL 50
-#define PC_DEMOMAN_MAXAMMO_CELL 50
-#define PC_DEMOMAN_MAXAMMO_ROCKET 50
-#define PC_DEMOMAN_MAXAMMO_DETPACK 1
-#define PC_DEMOMAN_INITAMMO_SHOT 30
-#define PC_DEMOMAN_INITAMMO_NAIL 0
-#define PC_DEMOMAN_INITAMMO_CELL 0
-#define PC_DEMOMAN_INITAMMO_ROCKET 20
-#define PC_DEMOMAN_INITAMMO_DETPACK 1
-#define PC_DEMOMAN_GRENADE_TYPE_1 GR_TYPE_NORMAL
-#define PC_DEMOMAN_GRENADE_TYPE_2 GR_TYPE_MIRV
-#define PC_DEMOMAN_GRENADE_INIT_1 2
-#define PC_DEMOMAN_GRENADE_INIT_2 2
-#define PC_DEMOMAN_TF_ITEMS 0
-
-// Class Details for COMBAT MEDIC
-#define PC_MEDIC_SKIN 3
-#define PC_MEDIC_MAXHEALTH 90
-#define PC_MEDIC_MAXSPEED 320
-#define PC_MEDIC_MAXSTRAFESPEED 320
-#define PC_MEDIC_MAXARMOR 100
-#define PC_MEDIC_INITARMOR 50
-#define PC_MEDIC_MAXARMORTYPE 0.6
-#define PC_MEDIC_INITARMORTYPE 0.3
-#define PC_MEDIC_ARMORCLASSES 11 // ALL except EXPLOSION
-#define PC_MEDIC_INITARMORCLASS 0
-#define PC_MEDIC_WEAPONS WEAP_BIOWEAPON | WEAP_MEDIKIT | WEAP_SHOTGUN | WEAP_SUPER_SHOTGUN | WEAP_SUPER_NAILGUN
-#define PC_MEDIC_MAXAMMO_SHOT 75
-#define PC_MEDIC_MAXAMMO_NAIL 150
-#define PC_MEDIC_MAXAMMO_CELL 50
-#define PC_MEDIC_MAXAMMO_ROCKET 25
-#define PC_MEDIC_MAXAMMO_MEDIKIT 100
-#define PC_MEDIC_INITAMMO_SHOT 50
-#define PC_MEDIC_INITAMMO_NAIL 50
-#define PC_MEDIC_INITAMMO_CELL 0
-#define PC_MEDIC_INITAMMO_ROCKET 0
-#define PC_MEDIC_INITAMMO_MEDIKIT 50
-#define PC_MEDIC_GRENADE_TYPE_1 GR_TYPE_NORMAL
-#define PC_MEDIC_GRENADE_TYPE_2 GR_TYPE_CONCUSSION
-#define PC_MEDIC_GRENADE_INIT_1 2
-#define PC_MEDIC_GRENADE_INIT_2 2
-#define PC_MEDIC_TF_ITEMS 0
-#define PC_MEDIC_REGEN_TIME 3 // Number of seconds between each regen.
-#define PC_MEDIC_REGEN_AMOUNT 2 // Amount of health regenerated each regen.
-
-// Class Details for HVYWEAP
-#define PC_HVYWEAP_SKIN 2
-#define PC_HVYWEAP_MAXHEALTH 100
-#define PC_HVYWEAP_MAXSPEED 230
-#define PC_HVYWEAP_MAXSTRAFESPEED 230
-#define PC_HVYWEAP_MAXARMOR 300
-#define PC_HVYWEAP_INITARMOR 150
-#define PC_HVYWEAP_MAXARMORTYPE 0.8
-#define PC_HVYWEAP_INITARMORTYPE 0.8
-#define PC_HVYWEAP_ARMORCLASSES 31 // ALL
-#define PC_HVYWEAP_INITARMORCLASS 0
-#define PC_HVYWEAP_WEAPONS WEAP_ASSAULT_CANNON | WEAP_AXE | WEAP_SHOTGUN | WEAP_SUPER_SHOTGUN
-#define PC_HVYWEAP_MAXAMMO_SHOT 200
-#define PC_HVYWEAP_MAXAMMO_NAIL 200
-#define PC_HVYWEAP_MAXAMMO_CELL 50
-#define PC_HVYWEAP_MAXAMMO_ROCKET 25
-#define PC_HVYWEAP_INITAMMO_SHOT 200
-#define PC_HVYWEAP_INITAMMO_NAIL 0
-#define PC_HVYWEAP_INITAMMO_CELL 30
-#define PC_HVYWEAP_INITAMMO_ROCKET 0
-#define PC_HVYWEAP_GRENADE_TYPE_1 GR_TYPE_NORMAL
-#define PC_HVYWEAP_GRENADE_TYPE_2 GR_TYPE_MIRV
-#define PC_HVYWEAP_GRENADE_INIT_1 2
-#define PC_HVYWEAP_GRENADE_INIT_2 1
-#define PC_HVYWEAP_TF_ITEMS 0
-#define PC_HVYWEAP_CELL_USAGE 7 // Amount of cells spent to power up assault cannon
-
-
-
-// Class Details for PYRO
-#define PC_PYRO_SKIN 21
-#define PC_PYRO_MAXHEALTH 100
-#define PC_PYRO_MAXSPEED 300
-#define PC_PYRO_MAXSTRAFESPEED 300
-#define PC_PYRO_MAXARMOR 150
-#define PC_PYRO_INITARMOR 50
-#define PC_PYRO_MAXARMORTYPE 0.6
-#define PC_PYRO_INITARMORTYPE 0.6
-#define PC_PYRO_ARMORCLASSES 27 // ALL except EXPLOSION
-#define PC_PYRO_INITARMORCLASS 16 // #AT_SAVEFIRE
-#define PC_PYRO_WEAPONS WEAP_INCENDIARY | WEAP_FLAMETHROWER | WEAP_AXE | WEAP_SHOTGUN
-#define PC_PYRO_MAXAMMO_SHOT 40
-#define PC_PYRO_MAXAMMO_NAIL 50
-#define PC_PYRO_MAXAMMO_CELL 200
-#define PC_PYRO_MAXAMMO_ROCKET 20
-#define PC_PYRO_INITAMMO_SHOT 20
-#define PC_PYRO_INITAMMO_NAIL 0
-#define PC_PYRO_INITAMMO_CELL 120
-#define PC_PYRO_INITAMMO_ROCKET 5
-#define PC_PYRO_GRENADE_TYPE_1 GR_TYPE_NORMAL
-#define PC_PYRO_GRENADE_TYPE_2 GR_TYPE_NAPALM
-#define PC_PYRO_GRENADE_INIT_1 2
-#define PC_PYRO_GRENADE_INIT_2 4
-#define PC_PYRO_TF_ITEMS 0
-#define PC_PYRO_ROCKET_USAGE 3 // Number of rockets per incendiary cannon shot
-
-// Class Details for SPY
-#define PC_SPY_SKIN 22
-#define PC_SPY_MAXHEALTH 90
-#define PC_SPY_MAXSPEED 300
-#define PC_SPY_MAXSTRAFESPEED 300
-#define PC_SPY_MAXARMOR 100
-#define PC_SPY_INITARMOR 25
-#define PC_SPY_MAXARMORTYPE 0.6 // Was 0.3
-#define PC_SPY_INITARMORTYPE 0.6 // Was 0.3
-#define PC_SPY_ARMORCLASSES 27 // ALL except EXPLOSION
-#define PC_SPY_INITARMORCLASS 0
-#define PC_SPY_WEAPONS WEAP_AXE | WEAP_TRANQ | WEAP_SUPER_SHOTGUN | WEAP_NAILGUN
-#define PC_SPY_MAXAMMO_SHOT 40
-#define PC_SPY_MAXAMMO_NAIL 100
-#define PC_SPY_MAXAMMO_CELL 30
-#define PC_SPY_MAXAMMO_ROCKET 15
-#define PC_SPY_INITAMMO_SHOT 40
-#define PC_SPY_INITAMMO_NAIL 50
-#define PC_SPY_INITAMMO_CELL 10
-#define PC_SPY_INITAMMO_ROCKET 0
-#define PC_SPY_GRENADE_TYPE_1 GR_TYPE_NORMAL
-#define PC_SPY_GRENADE_TYPE_2 GR_TYPE_GAS
-#define PC_SPY_GRENADE_INIT_1 2
-#define PC_SPY_GRENADE_INIT_2 2
-#define PC_SPY_TF_ITEMS 0
-#define PC_SPY_CELL_REGEN_TIME 5
-#define PC_SPY_CELL_REGEN_AMOUNT 1
-#define PC_SPY_CELL_USAGE 3 // Amount of cells spent while invisible
-#define PC_SPY_GO_UNDERCOVER_TIME 4 // Time it takes to go undercover
-
-// Class Details for ENGINEER
-#define PC_ENGINEER_SKIN 22 // Not used anymore
-#define PC_ENGINEER_MAXHEALTH 80
-#define PC_ENGINEER_MAXSPEED 300
-#define PC_ENGINEER_MAXSTRAFESPEED 300
-#define PC_ENGINEER_MAXARMOR 50
-#define PC_ENGINEER_INITARMOR 25
-#define PC_ENGINEER_MAXARMORTYPE 0.6
-#define PC_ENGINEER_INITARMORTYPE 0.3
-#define PC_ENGINEER_ARMORCLASSES 31 // ALL
-#define PC_ENGINEER_INITARMORCLASS 0
-#define PC_ENGINEER_WEAPONS WEAP_SPANNER | WEAP_LASER | WEAP_SUPER_SHOTGUN
-#define PC_ENGINEER_MAXAMMO_SHOT 50
-#define PC_ENGINEER_MAXAMMO_NAIL 50
-#define PC_ENGINEER_MAXAMMO_CELL 200 // synonymous with metal
-#define PC_ENGINEER_MAXAMMO_ROCKET 30
-#define PC_ENGINEER_INITAMMO_SHOT 20
-#define PC_ENGINEER_INITAMMO_NAIL 25
-#define PC_ENGINEER_INITAMMO_CELL 100 // synonymous with metal
-#define PC_ENGINEER_INITAMMO_ROCKET 0
-#define PC_ENGINEER_GRENADE_TYPE_1 GR_TYPE_NORMAL
-#define PC_ENGINEER_GRENADE_TYPE_2 GR_TYPE_EMP
-#define PC_ENGINEER_GRENADE_INIT_1 2
-#define PC_ENGINEER_GRENADE_INIT_2 2
-#define PC_ENGINEER_TF_ITEMS 0
-
-// Class Details for CIVILIAN
-#define PC_CIVILIAN_SKIN 22
-#define PC_CIVILIAN_MAXHEALTH 50
-#define PC_CIVILIAN_MAXSPEED 240
-#define PC_CIVILIAN_MAXSTRAFESPEED 240
-#define PC_CIVILIAN_MAXARMOR 0
-#define PC_CIVILIAN_INITARMOR 0
-#define PC_CIVILIAN_MAXARMORTYPE 0
-#define PC_CIVILIAN_INITARMORTYPE 0
-#define PC_CIVILIAN_ARMORCLASSES 0
-#define PC_CIVILIAN_INITARMORCLASS 0
-#define PC_CIVILIAN_WEAPONS WEAP_AXE
-#define PC_CIVILIAN_MAXAMMO_SHOT 0
-#define PC_CIVILIAN_MAXAMMO_NAIL 0
-#define PC_CIVILIAN_MAXAMMO_CELL 0
-#define PC_CIVILIAN_MAXAMMO_ROCKET 0
-#define PC_CIVILIAN_INITAMMO_SHOT 0
-#define PC_CIVILIAN_INITAMMO_NAIL 0
-#define PC_CIVILIAN_INITAMMO_CELL 0
-#define PC_CIVILIAN_INITAMMO_ROCKET 0
-#define PC_CIVILIAN_GRENADE_TYPE_1 0
-#define PC_CIVILIAN_GRENADE_TYPE_2 0
-#define PC_CIVILIAN_GRENADE_INIT_1 0
-#define PC_CIVILIAN_GRENADE_INIT_2 0
-#define PC_CIVILIAN_TF_ITEMS 0
-
-
-/*==========================================================================*/
-/* TEAMFORTRESS GOALS */
-/*==========================================================================*/
-// For all these defines, see the tfortmap.txt that came with the zip
-// for complete descriptions.
-// Defines for Goal Activation types : goal_activation (in goals)
-#define TFGA_TOUCH 1 // Activated when touched
-#define TFGA_TOUCH_DETPACK 2 // Activated when touched by a detpack explosion
-#define TFGA_REVERSE_AP 4 // Activated when AP details are _not_ met
-#define TFGA_SPANNER 8 // Activated when hit by an engineer's spanner
-#define TFGA_DROPTOGROUND 2048 // Drop to Ground when spawning
-
-// Defines for Goal Effects types : goal_effect
-#define TFGE_AP 1 // AP is affected. Default.
-#define TFGE_AP_TEAM 2 // All of the AP's team.
-#define TFGE_NOT_AP_TEAM 4 // All except AP's team.
-#define TFGE_NOT_AP 8 // All except AP.
-#define TFGE_WALL 16 // If set, walls stop the Radius effects
-#define TFGE_SAME_ENVIRONMENT 32 // If set, players in a different environment to the Goal are not affected
-#define TFGE_TIMER_CHECK_AP 64 // If set, Timer Goals check their critera for all players fitting their effects
-
-// Defines for Goal Result types : goal_result
-#define TFGR_SINGLE 1 // Goal can only be activated once
-#define TFGR_ADD_BONUSES 2 // Any Goals activated by this one give their bonuses
-#define TFGR_ENDGAME 4 // Goal fires Intermission, displays scores, and ends level
-#define TFGR_NO_ITEM_RESULTS 8 // GoalItems given by this Goal don't do results
-#define TFGR_REMOVE_DISGUISE 16 // Prevent/Remove undercover from any Spy
-#define TFGR_FORCE_RESPAWN 32 // Forces the player to teleport to a respawn point
-#define TFGR_DESTROY_BUILDINGS 64 // Destroys this player's buildings, if anys
-
-// Defines for Goal Group Result types : goal_group
-// None!
-// But I'm leaving this variable in there, since it's fairly likely
-// that some will show up sometime.
-
-// Defines for Goal Item types, : goal_activation (in items)
-#define TFGI_GLOW 1 // Players carrying this GoalItem will glow
-#define TFGI_SLOW 2 // Players carrying this GoalItem will move at half-speed
-#define TFGI_DROP 4 // Players dying with this item will drop it
-#define TFGI_RETURN_DROP 8 // Return if a player with it dies
-#define TFGI_RETURN_GOAL 16 // Return if a player with it has it removed by a goal's activation
-#define TFGI_RETURN_REMOVE 32 // Return if it is removed by TFGI_REMOVE
-#define TFGI_REVERSE_AP 64 // Only pickup if the player _doesn't_ match AP Details
-#define TFGI_REMOVE 128 // Remove if left untouched for 2 minutes after being dropped
-#define TFGI_KEEP 256 // Players keep this item even when they die
-#define TFGI_ITEMGLOWS 512 // Item glows when on the ground
-#define TFGI_DONTREMOVERES 1024 // Don't remove results when the item is removed
-#define TFGI_DROPTOGROUND 2048 // Drop To Ground when spawning
-#define TFGI_CANBEDROPPED 4096 // Can be voluntarily dropped by players
-#define TFGI_SOLID 8192 // Is solid... blocks bullets, etc
-
-// Defines for methods of GoalItem returning
-#define GI_RET_DROP_DEAD 0 // Dropped by a dead player
-#define GI_RET_DROP_LIVING 1 // Dropped by a living player
-#define GI_RET_GOAL 2 // Returned by a Goal
-#define GI_RET_TIME 3 // Returned due to timeout
-
-// Defines for TeamSpawnpoints : goal_activation (in teamspawns)
-#define TFSP_MULTIPLEITEMS 1 // Give out the GoalItem multiple times
-#define TFSP_MULTIPLEMSGS 2 // Display the message multiple times
-
-// Defines for TeamSpawnpoints : goal_effects (in teamspawns)
-#define TFSP_REMOVESELF 1 // Remove itself after being spawned on
-
-// Defines for Goal States
-#define TFGS_ACTIVE 1
-#define TFGS_INACTIVE 2
-#define TFGS_REMOVED 3
-#define TFGS_DELAYED 4
-
-// Defines for GoalItem Removing from Player Methods
-#define GI_DROP_PLAYERDEATH 0 // Dropped by a dying player
-#define GI_DROP_REMOVEGOAL 1 // Removed by a Goal
-#define GI_DROP_PLAYERDROP 2 // Dropped by a player
-
-// Legal Playerclass Handling
-#define TF_ILL_SCOUT 1
-#define TF_ILL_SNIPER 2
-#define TF_ILL_SOLDIER 4
-#define TF_ILL_DEMOMAN 8
-#define TF_ILL_MEDIC 16
-#define TF_ILL_HVYWEP 32
-#define TF_ILL_PYRO 64
-#define TF_ILL_RANDOMPC 128
-#define TF_ILL_SPY 256
-#define TF_ILL_ENGINEER 512
-
-// Addition classes
-#define CLASS_TFGOAL 128
-#define CLASS_TFGOAL_TIMER 129
-#define CLASS_TFGOAL_ITEM 130
-#define CLASS_TFSPAWN 131
-
-/*==========================================================================*/
-/* Flamethrower */
-/*==========================================================================*/
-#define FLAME_PLYRMAXTIME 5.0 // lifetime in seconds of a flame on a player
-#define FLAME_MAXBURNTIME 8 // lifetime in seconds of a flame on the world (big ones)
-#define NAPALM_MAXBURNTIME 20 // lifetime in seconds of flame from a napalm grenade
-#define FLAME_MAXPLYRFLAMES 4 // maximum number of flames on a player
-#define FLAME_NUMLIGHTS 1 // maximum number of light flame
-#define FLAME_BURNRATIO 0.3 // the chance of a flame not 'sticking'
-#define GR_TYPE_FLAMES_NO 15 // number of flames spawned when a grenade explode
-#define FLAME_DAMAGE_TIME 1 // Interval between damage burns from flames
-#define FLAME_EFFECT_TIME 0.2 // frequency at which we display flame effects.
-#define FLAME_THINK_TIME 0.1 // Seconds between times the flame checks burn
-#define PER_FLAME_DAMAGE 2 // Damage taken per second per flame by burning players
-
-/*==================================================*/
-/* CTF Support defines */
-/*==================================================*/
-#define CTF_FLAG1 1
-#define CTF_FLAG2 2
-#define CTF_DROPOFF1 3
-#define CTF_DROPOFF2 4
-#define CTF_SCORE1 5
-#define CTF_SCORE2 6
-
-//.float hook_out;
-
-/*==================================================*/
-/* Camera defines */
-/*==================================================*/
-/*
-float live_camera;
-.float camdist;
-.vector camangle;
-.entity camera_list;
-*/
-
-/*==================================================*/
-/* QuakeWorld defines */
-/*==================================================*/
-/*
-float already_chosen_map;
-
-// grappling hook variables
-.entity hook;
-.float on_hook;
-.float fire_held_down;// flag - TRUE if player is still holding down the
- // fire button after throwing a hook.
-*/
-/*==================================================*/
-/* Server Settings */
-/*==================================================*/
-// Admin modes
-#define ADMIN_MODE_NONE 0
-#define ADMIN_MODE_DEAL 1
-
-/*==================================================*/
-/* Death Message defines */
-/*==================================================*/
-#define DMSG_SHOTGUN 1
-#define DMSG_SSHOTGUN 2
-#define DMSG_NAILGUN 3
-#define DMSG_SNAILGUN 4
-#define DMSG_GRENADEL 5
-#define DMSG_ROCKETL 6
-#define DMSG_LIGHTNING 7
-#define DMSG_GREN_HAND 8
-#define DMSG_GREN_NAIL 9
-#define DMSG_GREN_MIRV 10
-#define DMSG_GREN_PIPE 11
-#define DMSG_DETPACK 12
-#define DMSG_BIOWEAPON 13
-#define DMSG_BIOWEAPON_ATT 14
-#define DMSG_FLAME 15
-#define DMSG_DETPACK_DIS 16
-#define DMSG_AXE 17
-#define DMSG_SNIPERRIFLE 18
-#define DMSG_AUTORIFLE 19
-#define DMSG_ASSAULTCANNON 20
-#define DMSG_HOOK 21
-#define DMSG_BACKSTAB 22
-#define DMSG_MEDIKIT 23
-#define DMSG_GREN_GAS 24
-#define DMSG_TRANQ 25
-#define DMSG_LASERBOLT 26
-#define DMSG_SENTRYGUN_BULLET 27
-#define DMSG_SNIPERLEGSHOT 28
-#define DMSG_SNIPERHEADSHOT 29
-#define DMSG_GREN_EMP 30
-#define DMSG_GREN_EMP_AMMO 31
-#define DMSG_SPANNER 32
-#define DMSG_INCENDIARY 33
-#define DMSG_SENTRYGUN_ROCKET 34
-#define DMSG_GREN_FLASH 35
-#define DMSG_TRIGGER 36
-#define DMSG_MIRROR 37
-#define DMSG_SENTRYDEATH 38
-#define DMSG_DISPENSERDEATH 39
-#define DMSG_GREN_AIRPIPE 40
-#define DMSG_CALTROP 41
-
-/*==================================================*/
-// TOGGLEFLAGS
-/*==================================================*/
-// Some of the toggleflags aren't used anymore, but the bits are still
-// there to provide compatability with old maps
-#define TFLAG_CLASS_PERSIST (1 << 0) // Persistent Classes Bit
-#define TFLAG_CHEATCHECK (1 << 1) // Cheatchecking Bit
-#define TFLAG_RESPAWNDELAY (1 << 2) // RespawnDelay bit
-//#define TFLAG_UN (1 << 3) // NOT USED ANYMORE
-#define TFLAG_OLD_GRENS (1 << 3) // Use old concussion grenade and flash grenade
-#define TFLAG_UN2 (1 << 4) // NOT USED ANYMORE
-#define TFLAG_UN3 (1 << 5) // NOT USED ANYMORE
-#define TFLAG_UN4 (1 << 6) // NOT USED ANYMORE: Was Autoteam. CVAR tfc_autoteam used now.
-#define TFLAG_TEAMFRAGS (1 << 7) // Individual Frags, or Frags = TeamScore
-#define TFLAG_FIRSTENTRY (1 << 8) // Used to determine the first time toggleflags is set
- // In a map. Cannot be toggled by players.
-#define TFLAG_SPYINVIS (1 << 9) // Spy invisible only
-#define TFLAG_GRAPPLE (1 << 10) // Grapple on/off
-//#define TFLAG_FULLTEAMSCORE (1 << 11) // Each Team's score is TeamScore + Frags
-#define TFLAG_FLAGEMULATION (1 << 12) // Flag emulation on for old TF maps
-#define TFLAG_USE_STANDARD (1 << 13) // Use the TF War standard for Flag emulation
-
-#define TFLAG_FRAGSCORING (1 << 14) // Use frag scoring only
-
-/*======================*/
-// Menu stuff //
-/*======================*/
-
-#define MENU_DEFAULT 1
-#define MENU_TEAM 2
-#define MENU_CLASS 3
-#define MENU_MAPBRIEFING 4
-#define MENU_INTRO 5
-#define MENU_CLASSHELP 6
-#define MENU_CLASSHELP2 7
-#define MENU_REPEATHELP 8
-
-#define MENU_SPECHELP 9
-
-
-#define MENU_SPY 12
-#define MENU_SPY_SKIN 13
-#define MENU_SPY_COLOR 14
-#define MENU_ENGINEER 15
-#define MENU_ENGINEER_FIX_DISPENSER 16
-#define MENU_ENGINEER_FIX_SENTRYGUN 17
-#define MENU_ENGINEER_FIX_MORTAR 18
-#define MENU_DISPENSER 19
-#define MENU_CLASS_CHANGE 20
-#define MENU_TEAM_CHANGE 21
-
-#define MENU_REFRESH_RATE 25
-
-#define MENU_VOICETWEAK 50
-
-//============================
-// Timer Types
-#define TF_TIMER_ANY 0
-#define TF_TIMER_CONCUSSION 1
-#define TF_TIMER_INFECTION 2
-#define TF_TIMER_HALLUCINATION 3
-#define TF_TIMER_TRANQUILISATION 4
-#define TF_TIMER_ROTHEALTH 5
-#define TF_TIMER_REGENERATION 6
-#define TF_TIMER_GRENPRIME 7
-#define TF_TIMER_CELLREGENERATION 8
-#define TF_TIMER_DETPACKSET 9
-#define TF_TIMER_DETPACKDISARM 10
-#define TF_TIMER_BUILD 11
-#define TF_TIMER_CHECKBUILDDISTANCE 12
-#define TF_TIMER_DISGUISE 13
-#define TF_TIMER_DISPENSERREFILL 14
-
-// Non Player timers
-#define TF_TIMER_RETURNITEM 100
-#define TF_TIMER_DELAYEDGOAL 101
-#define TF_TIMER_ENDROUND 102
-
-//============================
-// Teamscore printing
-#define TS_PRINT_SHORT 1
-#define TS_PRINT_LONG 2
-#define TS_PRINT_LONG_TO_ALL 3
-
-#ifndef TF_DEFS_ONLY
-typedef struct
-{
- int topColor;
- int bottomColor;
-} team_color_t;
-/*==================================================*/
-/* GLOBAL VARIABLES */
-/*==================================================*/
-// FortressMap stuff
-extern float number_of_teams; // number of teams supported by the map
-extern int illegalclasses[5]; // Illegal playerclasses for all teams
-extern int civilianteams; // Bitfield holding Civilian teams
-extern Vector rgbcolors[5]; // RGB colors for each of the 4 teams
-
-extern team_color_t teamcolors[5][PC_LASTCLASS]; // Colors for each of the 4 teams
-extern int teamscores[5]; // Goal Score of each team
-extern int g_iOrderedTeams[5]; // Teams ordered into order of winners->losers
-extern int teamfrags[5]; // Total Frags for each team
-extern int teamlives[5]; // Number of lives each team's players have
-extern int teammaxplayers[5]; // Max number of players allowed in each team
-extern float teamadvantage[5]; // only used if the teamplay equalisation bits are set
- // stores the damage ratio players take/give
-extern int teamallies[5]; // Keeps track of which teams are allied
-extern string_t team_names[5];
-
-extern BOOL CTF_Map;
-extern BOOL birthday;
-extern BOOL christmas;
-
-extern float num_world_flames;
-
-// Clan Battle stuff
-extern float clan_scores_dumped;
-extern float cb_prematch_time;
-extern float fOldPrematch;
-extern float fOldCeaseFire;
-extern float cb_ceasefire_time;
-extern float last_id;
-extern float spy_off;
-extern float old_grens;
-extern float flagem_checked;
-extern float flNextEqualisationCalc;
-extern BOOL cease_fire;
-extern BOOL no_cease_fire_text;
-extern BOOL initial_cease_fire;
-extern BOOL last_cease_fire;
-// Autokick stuff
-extern float autokick_kills;
-
-extern float deathmsg; // Global, which is set before every T_Damage, to indicate
- // the death message that should be used.
-
-extern char *sTeamSpawnNames[];
-extern char *sClassNames[];
-extern char *sNewClassModelFiles[];
-extern char *sOldClassModelFiles[];
-extern char *sClassModels[];
-extern char *sClassCfgs[];
-extern char *sGrenadeNames[];
-extern string_t team_menu_string;
-
-extern int toggleflags; // toggleable flags
-
-extern BOOL g_bFirstClient;
-
-extern float g_fNextPrematchAlert;
-
-typedef struct
-{
- int ip;
- edict_t *pEdict;
-} ip_storage_t;
-
-extern ip_storage_t g_IpStorage[32];
-
-class CGhost;
-/*==========================================================================*/
-BOOL ClassIsRestricted(float tno, int pc);
-char* GetTeamName(int tno);
-int TeamFortress_GetNoPlayers();
-void DestroyBuilding(CBaseEntity *eng, char *bld);
-void teamsprint( int tno, CBaseEntity *ignore, int msg_dest, const char *st, const char *param1 = NULL, const char *param2 = NULL, const char *param3 = NULL );
-float anglemod( float v );
-
-// Team Funcs
-BOOL TeamFortress_TeamIsCivilian(float tno);
-void TeamFortress_TeamShowScores(BOOL bLong, CBasePlayer *pPlayer);
-BOOL TeamFortress_TeamPutPlayerInTeam();
-void TeamFortress_TeamSetColor(int tno);
-void TeamFortress_TeamIncreaseScore(int tno, int scoretoadd);
-int TeamFortress_TeamGetScoreFrags(int tno);
-int TeamFortress_TeamGetNoPlayers(int tno);
-float TeamEqualiseDamage(CBaseEntity *targ, CBaseEntity *attacker, float damage);
-BOOL IsSpawnPointValid( Vector &pos );
-BOOL TeamFortress_SortTeams( void );
-void DumpClanScores( void );
-void CalculateTeamEqualiser();
-
-// mapscript funcs
-void ParseTFServerSettings();
-void ParseTFMapSettings();
-CBaseEntity* Finditem(int ino);
-CBaseEntity* Findgoal(int gno);
-CBaseEntity* Findteamspawn(int gno);
-void RemoveGoal(CBaseEntity *Goal);
-void tfgoalitem_GiveToPlayer(CBaseEntity *Item, CBasePlayer *AP, CBaseEntity *Goal);
-void dremove( CBaseEntity *te );
-void tfgoalitem_RemoveFromPlayer(CBaseEntity *Item, CBasePlayer *AP, int iMethod);
-void tfgoalitem_drop(CBaseEntity *Item, BOOL PAlive, CBasePlayer *P);
-void DisplayItemStatus(CBaseEntity *Goal, CBasePlayer *Player, CBaseEntity *Item);
-void tfgoalitem_checkgoalreturn(CBaseEntity *Item);
-void DoGoalWork(CBaseEntity *Goal, CBasePlayer *AP);
-void DoResults(CBaseEntity *Goal, CBasePlayer *AP, BOOL bAddBonuses);
-void DoGroupWork(CBaseEntity *Goal, CBasePlayer *AP);
-// hooks into the mapscript for all entities
-BOOL ActivateDoResults(CBaseEntity *Goal, CBasePlayer *AP, CBaseEntity *ActivatingGoal);
-BOOL ActivationSucceeded(CBaseEntity *Goal, CBasePlayer *AP, CBaseEntity *ActivatingGoal);
-
-// prematch & ceasefire
-void Display_Prematch();
-void Check_Ceasefire();
-
-// admin
-void KickPlayer( CBaseEntity *pTarget );
-void BanPlayer( CBaseEntity *pTarget );
-CGhost *FindGhost( int iGhostID );
-int GetBattleID( edict_t *pEntity );
-
-extern cvar_t tfc_spam_penalty1;// the initial gag penalty for a spammer (seconds)
-extern cvar_t tfc_spam_penalty2;// incremental gag penalty (seconds) for each time gagged spammer continues to speak.
-extern cvar_t tfc_spam_limit; // at this many points, gag the spammer
-extern cvar_t tfc_clanbattle, tfc_clanbattle_prematch, tfc_prematch, tfc_clanbattle_ceasefire, tfc_balance_teams, tfc_balance_scores;
-extern cvar_t tfc_clanbattle_locked, tfc_birthday, tfc_autokick_kills, tfc_fragscoring, tfc_autokick_time, tfc_adminpwd;
-extern cvar_t weaponstay, footsteps, flashlight, aimcrosshair, falldamage, teamplay;
-extern cvar_t allow_spectators;
-
-/*==========================================================================*/
-class CTFFlame : public CBaseMonster
-{
-public:
- void Spawn( void );
- void Precache( void );
- void EXPORT FlameThink( void );
- static CTFFlame *FlameSpawn( CBaseEntity *pOwner, CBaseEntity *pTarget );
- void FlameDestroy( void );
-
- float m_flNextDamageTime;
-};
-
-/*==========================================================================*/
-// MAPSCRIPT CLASSES
-class CTFGoal : public CBaseAnimating
-{
-public:
- void Spawn( void );
- void StartGoal( void );
- void EXPORT PlaceGoal( void );
- void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
- int Classify ( void ) { return CLASS_TFGOAL; }
-
- void SetObjectCollisionBox( void );
-};
-
-class CTFGoalItem : public CTFGoal
-{
-public:
- void Spawn( void );
- void StartItem( void );
- void EXPORT PlaceItem( void );
- int Classify ( void ) { return CLASS_TFGOAL_ITEM; }
-
- float m_flDroppedAt;
-};
-
-class CTFTimerGoal : public CTFGoal
-{
-public:
- void Spawn( void );
- int Classify ( void ) { return CLASS_TFGOAL_TIMER; }
-};
-
-class CTFSpawn : public CBaseEntity
-{
-public:
- void Spawn( void );
- void Activate( void );
- int Classify ( void ) { return CLASS_TFSPAWN; }
- BOOL CheckTeam( int iTeamNo );
- EHANDLE m_pTeamCheck;
-};
-
-class CTFDetect : public CBaseEntity
-{
-public:
- void Spawn( void );
- int Classify ( void ) { return CLASS_TFGOAL; }
-};
-
-class CTelefragDeath : public CBaseEntity
-{
-public:
- void Spawn( void );
- void EXPORT DeathTouch( CBaseEntity *pOther );
-};
-
-class CTeamCheck : public CBaseDelay
-{
-public:
- void Spawn( void );
- void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
- BOOL TeamMatches( int iTeam );
-};
-class CTeamSet : public CBaseDelay
-{
-public:
- void Spawn( void );
- void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
-};
-#endif // TF_DEFS_ONLY
-#endif // __TF_DEFS_H
-
-
+/***
+*
+* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
+*
+* This product contains software technology licensed from Id
+* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
+* All Rights Reserved.
+*
+****/
+
+#ifndef __TF_DEFS_H
+#define __TF_DEFS_H
+
+//===========================================================================
+// OLD OPTIONS.QC
+//===========================================================================
+#define DEFAULT_AUTOZOOM FALSE
+#define WEINER_SNIPER // autoaiming for sniper rifle
+#define FLAME_MAXWORLDNUM 20 // maximum number of flames in the world. DO NOT PUT BELOW 20.
+
+//#define MAX_WORLD_PIPEBOMBS 15 // This is divided between teams - this is the most you should have on a net server
+#define MAX_PLAYER_PIPEBOMBS 8 // maximum number of pipebombs any 1 player can have active
+#define MAX_PLAYER_AMMOBOXES 3 // maximum number of ammoboxes any 1 player can have active
+
+//#define MAX_WORLD_FLARES 9 // This is the total number of flares allowed in the world at one time
+//#define MAX_WORLD_AMMOBOXES 20 // This is divided between teams - this is the most you should have on a net server
+#define GR_TYPE_MIRV_NO 4 // Number of Mirvs a Mirv Grenade breaks into
+#define GR_TYPE_NAPALM_NO 8 // Number of flames napalm grenade breaks into (unused if net server)
+#define MEDIKIT_IS_BIOWEAPON // Medikit acts as a bioweapon against enemies
+
+#define TEAM_HELP_RATE 60 // used only if teamplay bit 64 (help team with lower score) is set.
+ // 60 is a mild setting, and won't make too much difference
+ // increasing it _decreases_ the amount of help the losing team gets
+ // Minimum setting is 1, which would really help the losing team
+
+#define DISPLAY_CLASS_HELP TRUE // Change this to #OFF if you don't want the class help to
+ // appear whenever a player connects
+#define NEVER_TEAMFRAGS FALSE // teamfrags options always off
+#define ALWAYS_TEAMFRAGS FALSE // teamfrags options always on
+#define CHECK_SPEEDS TRUE // makes sure players aren't moving too fast
+#define SNIPER_RIFLE_RELOAD_TIME 1.5 // seconds
+
+#define MAPBRIEFING_MAXTEXTLENGTH 512
+#define PLAYER_PUSH_VELOCITY 50 // Players push teammates if they're moving under this speed
+
+// Debug Options
+//#define MAP_DEBUG // Debug for Map code. I suggest running in a hi-res
+ // mode and/or piping the output from the server to a file.
+#ifdef MAP_DEBUG
+ #define MDEBUG(x) x
+#else
+ #define MDEBUG(x)
+#endif
+//#define VERBOSE // Verbose Debugging on/off
+
+//===========================================================================
+// OLD QUAKE Defs
+//===========================================================================
+// items
+#define IT_AXE 4096
+#define IT_SHOTGUN 1
+#define IT_SUPER_SHOTGUN 2
+#define IT_NAILGUN 4
+#define IT_SUPER_NAILGUN 8
+#define IT_GRENADE_LAUNCHER 16
+#define IT_ROCKET_LAUNCHER 32
+#define IT_LIGHTNING 64
+#define IT_EXTRA_WEAPON 128
+
+#define IT_SHELLS 256
+#define IT_NAILS 512
+#define IT_ROCKETS 1024
+#define IT_CELLS 2048
+
+#define IT_ARMOR1 8192
+#define IT_ARMOR2 16384
+#define IT_ARMOR3 32768
+#define IT_SUPERHEALTH 65536
+
+#define IT_KEY1 131072
+#define IT_KEY2 262144
+
+#define IT_INVISIBILITY 524288
+#define IT_INVULNERABILITY 1048576
+#define IT_SUIT 2097152
+#define IT_QUAD 4194304
+#define IT_HOOK 8388608
+
+#define IT_KEY3 16777216 // Stomp invisibility
+#define IT_KEY4 33554432 // Stomp invulnerability
+
+//===========================================================================
+// TEAMFORTRESS Defs
+//===========================================================================
+// TeamFortress State Flags
+#define TFSTATE_GRENPRIMED 1 // Whether the player has a primed grenade
+#define TFSTATE_RELOADING 2 // Whether the player is reloading
+#define TFSTATE_ALTKILL 4 // #TRUE if killed with a weapon not in self.weapon: NOT USED ANYMORE
+#define TFSTATE_RANDOMPC 8 // Whether Playerclass is random, new one each respawn
+#define TFSTATE_INFECTED 16 // set when player is infected by the bioweapon
+#define TFSTATE_INVINCIBLE 32 // Player has permanent Invincibility (Usually by GoalItem)
+#define TFSTATE_INVISIBLE 64 // Player has permanent Invisibility (Usually by GoalItem)
+#define TFSTATE_QUAD 128 // Player has permanent Quad Damage (Usually by GoalItem)
+#define TFSTATE_RADSUIT 256 // Player has permanent Radsuit (Usually by GoalItem)
+#define TFSTATE_BURNING 512 // Is on fire
+#define TFSTATE_GRENTHROWING 1024 // is throwing a grenade
+#define TFSTATE_AIMING 2048 // is using the laser sight
+#define TFSTATE_ZOOMOFF 4096 // doesn't want the FOV changed when zooming
+#define TFSTATE_RESPAWN_READY 8192 // is waiting for respawn, and has pressed fire
+#define TFSTATE_HALLUCINATING 16384 // set when player is hallucinating
+#define TFSTATE_TRANQUILISED 32768 // set when player is tranquilised
+#define TFSTATE_CANT_MOVE 65536 // set when player is setting a detpack
+#define TFSTATE_RESET_FLAMETIME 131072 // set when the player has to have his flames increased in health
+
+// Defines used by TF_T_Damage (see combat.qc)
+#define TF_TD_IGNOREARMOUR 1 // Bypasses the armour of the target
+#define TF_TD_NOTTEAM 2 // Doesn't damage a team member (indicates direct fire weapon)
+#define TF_TD_NOTSELF 4 // Doesn't damage self
+
+#define TF_TD_OTHER 0 // Ignore armorclass
+#define TF_TD_SHOT 1 // Bullet damage
+#define TF_TD_NAIL 2 // Nail damage
+#define TF_TD_EXPLOSION 4 // Explosion damage
+#define TF_TD_ELECTRICITY 8 // Electric damage
+#define TF_TD_FIRE 16 // Fire damage
+#define TF_TD_NOSOUND 256 // Special damage. Makes no sound/painframe, etc
+
+/*==================================================*/
+/* Toggleable Game Settings */
+/*==================================================*/
+#define TF_RESPAWNDELAY1 5 // seconds of waiting before player can respawn
+#define TF_RESPAWNDELAY2 10 // seconds of waiting before player can respawn
+#define TF_RESPAWNDELAY3 20 // seconds of waiting before player can respawn
+
+#define TEAMPLAY_NORMAL 1
+#define TEAMPLAY_HALFDIRECT 2
+#define TEAMPLAY_NODIRECT 4
+#define TEAMPLAY_HALFEXPLOSIVE 8
+#define TEAMPLAY_NOEXPLOSIVE 16
+#define TEAMPLAY_LESSPLAYERSHELP 32
+#define TEAMPLAY_LESSSCOREHELP 64
+#define TEAMPLAY_HALFDIRECTARMOR 128
+#define TEAMPLAY_NODIRECTARMOR 256
+#define TEAMPLAY_HALFEXPARMOR 512
+#define TEAMPLAY_NOEXPARMOR 1024
+#define TEAMPLAY_HALFDIRMIRROR 2048
+#define TEAMPLAY_FULLDIRMIRROR 4096
+#define TEAMPLAY_HALFEXPMIRROR 8192
+#define TEAMPLAY_FULLEXPMIRROR 16384
+
+#define TEAMPLAY_TEAMDAMAGE (TEAMPLAY_NODIRECT | TEAMPLAY_HALFDIRECT | TEAMPLAY_HALFEXPLOSIVE | TEAMPLAY_NOEXPLOSIVE)
+// FortressMap stuff
+#define TEAM1_CIVILIANS 1
+#define TEAM2_CIVILIANS 2
+#define TEAM3_CIVILIANS 4
+#define TEAM4_CIVILIANS 8
+
+// Defines for the playerclass
+#define PC_UNDEFINED 0
+
+#define PC_SCOUT 1
+#define PC_SNIPER 2
+#define PC_SOLDIER 3
+#define PC_DEMOMAN 4
+#define PC_MEDIC 5
+#define PC_HVYWEAP 6
+#define PC_PYRO 7
+#define PC_SPY 8
+#define PC_ENGINEER 9
+
+// Insert new class definitions here
+
+// PC_RANDOM _MUST_ be the third last class
+#define PC_RANDOM 10 // Random playerclass
+#define PC_CIVILIAN 11 // Civilians are a special class. They cannot
+ // be chosen by players, only enforced by maps
+#define PC_LASTCLASS 12 // Use this as the high-boundary for any loops
+ // through the playerclass.
+
+#define SENTRY_COLOR 10 // will be in the PC_RANDOM slot for team colors
+// These are just for the scanner
+#define SCAN_SENTRY 13
+#define SCAN_GOALITEM 14
+
+// Values returned by CheckArea
+enum
+{
+ CAREA_CLEAR,
+ CAREA_BLOCKED,
+ CAREA_NOBUILD
+};
+
+/*==================================================*/
+/* Impulse Defines */
+/*==================================================*/
+// Alias check to see whether they already have the aliases
+#define TF_ALIAS_CHECK 13
+
+// CTF Support Impulses
+#define HOOK_IMP1 22
+#define FLAG_INFO 23
+#define HOOK_IMP2 39
+
+// Axe
+#define AXE_IMP 40
+
+// Camera Impulse
+#define TF_CAM_TARGET 50
+#define TF_CAM_ZOOM 51
+#define TF_CAM_ANGLE 52
+#define TF_CAM_VEC 53
+#define TF_CAM_PROJECTILE 54
+#define TF_CAM_PROJECTILE_Z 55
+#define TF_CAM_REVANGLE 56
+#define TF_CAM_OFFSET 57
+#define TF_CAM_DROP 58
+#define TF_CAM_FADETOBLACK 59
+#define TF_CAM_FADEFROMBLACK 60
+#define TF_CAM_FADETOWHITE 61
+#define TF_CAM_FADEFROMWHITE 62
+
+// Last Weapon impulse
+#define TF_LAST_WEAPON 69
+
+// Status Bar Resolution Settings. Same as CTF to maintain ease of use.
+#define TF_STATUSBAR_RES_START 71
+#define TF_STATUSBAR_RES_END 81
+
+// Clan Messages
+#define TF_MESSAGE_1 82
+#define TF_MESSAGE_2 83
+#define TF_MESSAGE_3 84
+#define TF_MESSAGE_4 85
+#define TF_MESSAGE_5 86
+
+#define TF_CHANGE_CLASS 99 // Bring up the Class Change menu
+
+// Added to PC_??? to get impulse to use if this clashes with your
+// own impulses, just change this value, not the PC_??
+#define TF_CHANGEPC 100
+// The next few impulses are all the class selections
+//PC_SCOUT 101
+//PC_SNIPER 102
+//PC_SOLDIER 103
+//PC_DEMOMAN 104
+//PC_MEDIC 105
+//PC_HVYWEAP 106
+//PC_PYRO 107
+//PC_RANDOM 108
+//PC_CIVILIAN 109 // Cannot be used
+//PC_SPY 110
+//PC_ENGINEER 111
+
+// Help impulses
+#define TF_DISPLAYLOCATION 118
+#define TF_STATUS_QUERY 119
+
+#define TF_HELP_MAP 131
+
+// Information impulses
+#define TF_INVENTORY 135
+#define TF_SHOWTF 136
+#define TF_SHOWLEGALCLASSES 137
+
+// Team Impulses
+#define TF_TEAM_1 140 // Join Team 1
+#define TF_TEAM_2 141 // Join Team 2
+#define TF_TEAM_3 142 // Join Team 3
+#define TF_TEAM_4 143 // Join Team 4
+#define TF_TEAM_CLASSES 144 // Impulse to display team classes
+#define TF_TEAM_SCORES 145 // Impulse to display team scores
+#define TF_TEAM_LIST 146 // Impulse to display the players in each team.
+
+// Grenade Impulses
+#define TF_GRENADE_1 150 // Prime grenade type 1
+#define TF_GRENADE_2 151 // Prime grenade type 2
+#define TF_GRENADE_T 152 // Throw primed grenade
+
+// Impulses for new items
+//#define TF_SCAN 159 // Scanner Pre-Impulse
+#define TF_AUTO_SCAN 159 // Scanner On/Off
+#define TF_SCAN_ENEMY 160 // Impulses to toggle scanning of enemies
+#define TF_SCAN_FRIENDLY 161 // Impulses to toggle scanning of friendlies
+//#define TF_SCAN_10 162 // Scan using 10 enery (1 cell)
+#define TF_SCAN_SOUND 162 // Scanner sounds on/off
+#define TF_SCAN_30 163 // Scan using 30 energy (2 cells)
+#define TF_SCAN_100 164 // Scan using 100 energy (5 cells)
+#define TF_DETPACK_5 165 // Detpack set to 5 seconds
+#define TF_DETPACK_20 166 // Detpack set to 20 seconds
+#define TF_DETPACK_50 167 // Detpack set to 50 seconds
+#define TF_DETPACK 168 // Detpack Pre-Impulse
+#define TF_DETPACK_STOP 169 // Impulse to stop setting detpack
+#define TF_PB_DETONATE 170 // Detonate Pipebombs
+
+// Special skill
+#define TF_SPECIAL_SKILL 171
+
+// Ammo Drop impulse
+#define TF_DROP_AMMO 172
+
+// Reload impulse
+#define TF_RELOAD 173
+
+// auto-zoom toggle
+#define TF_AUTOZOOM 174
+
+// drop/pass commands
+#define TF_DROPKEY 175
+
+// Select Medikit
+#define TF_MEDIKIT 176
+
+// Spy Impulses
+#define TF_SPY_SPY 177 // On net, go invisible, on LAN, change skin/color
+#define TF_SPY_DIE 178 // Feign Death
+
+// Engineer Impulses
+#define TF_ENGINEER_BUILD 179
+#define TF_ENGINEER_SANDBAG 180
+
+// Medic
+#define TF_MEDIC_HELPME 181
+
+// Status bar
+#define TF_STATUSBAR_ON 182
+#define TF_STATUSBAR_OFF 183
+
+// Discard impulse
+#define TF_DISCARD 184
+
+// ID Player impulse
+#define TF_ID 185
+
+// Clan Battle impulses
+#define TF_SHOWIDS 186
+
+// More Engineer Impulses
+#define TF_ENGINEER_DETDISP 187
+#define TF_ENGINEER_DETSENT 188
+
+// Admin Commands
+#define TF_ADMIN_DEAL_CYCLE 189
+#define TF_ADMIN_KICK 190
+#define TF_ADMIN_BAN 191
+#define TF_ADMIN_COUNTPLAYERS 192
+#define TF_ADMIN_CEASEFIRE 193
+
+// Drop Goal Items
+#define TF_DROPGOALITEMS 194
+
+// More Admin Commands
+#define TF_ADMIN_NEXT 195
+
+// More Engineer Impulses
+#define TF_ENGINEER_DETEXIT 196
+#define TF_ENGINEER_DETENTRANCE 197
+
+// Yet MORE Admin Commands
+#define TF_ADMIN_LISTIPS 198
+
+// Silent Spy Feign
+#define TF_SPY_SILENTDIE 199
+
+
+/*==================================================*/
+/*==================================================*/
+#define TEAM1_COLOR 150
+#define TEAM2_COLOR 250
+#define TEAM3_COLOR 45
+#define TEAM4_COLOR 100
+
+/*==================================================*/
+/* Defines for the ENGINEER's Building ability */
+/*==================================================*/
+// Ammo costs
+#define AMMO_COST_SHELLS 2 // Metal needed to make 1 shell
+#define AMMO_COST_NAILS 1
+#define AMMO_COST_ROCKETS 2
+#define AMMO_COST_CELLS 2
+
+// Building types
+#define BUILD_DISPENSER 1
+#define BUILD_SENTRYGUN 2
+#define BUILD_MORTAR 3
+#define BUILD_TELEPORTER_ENTRANCE 4
+#define BUILD_TELEPORTER_EXIT 5
+
+// Building metal costs
+#define BUILD_COST_DISPENSER 100 // Metal needed to built
+#define BUILD_COST_SENTRYGUN 130
+#define BUILD_COST_MORTAR 150
+#define BUILD_COST_TELEPORTER 125
+
+#define BUILD_COST_SANDBAG 20 // Built with a separate alias
+
+// Building times
+#define BUILD_TIME_DISPENSER 2 // seconds to build
+#define BUILD_TIME_SENTRYGUN 5
+#define BUILD_TIME_MORTAR 5
+#define BUILD_TIME_TELEPORTER 4
+
+// Building health levels
+#define BUILD_HEALTH_DISPENSER 150 // Health of the building
+#define BUILD_HEALTH_SENTRYGUN 150
+#define BUILD_HEALTH_MORTAR 200
+#define BUILD_HEALTH_TELEPORTER 80
+
+// Dispenser's maximum carrying capability
+#define BUILD_DISPENSER_MAX_SHELLS 400
+#define BUILD_DISPENSER_MAX_NAILS 600
+#define BUILD_DISPENSER_MAX_ROCKETS 300
+#define BUILD_DISPENSER_MAX_CELLS 400
+#define BUILD_DISPENSER_MAX_ARMOR 500
+
+// Build state sent down to client
+#define BS_BUILDING (1<<0)
+#define BS_HAS_DISPENSER (1<<1)
+#define BS_HAS_SENTRYGUN (1<<2)
+#define BS_CANB_DISPENSER (1<<3)
+#define BS_CANB_SENTRYGUN (1<<4)
+/*==================================================*/
+/* Ammo quantities for dropping & dispenser use */
+/*==================================================*/
+#define DROP_SHELLS 20
+#define DROP_NAILS 20
+#define DROP_ROCKETS 10
+#define DROP_CELLS 10
+#define DROP_ARMOR 40
+
+/*==================================================*/
+/* Team Defines */
+/*==================================================*/
+#define TM_MAX_NO 4 // Max number of teams. Simply changing this value isn't enough.
+ // A new global to hold new team colors is needed, and more flags
+ // in the spawnpoint spawnflags may need to be used.
+ // Basically, don't change this unless you know what you're doing :)
+
+/*==================================================*/
+/* New Weapon Defines */
+/*==================================================*/
+#define WEAP_HOOK 1
+#define WEAP_BIOWEAPON 2
+#define WEAP_MEDIKIT 4
+#define WEAP_SPANNER 8
+#define WEAP_AXE 16
+#define WEAP_SNIPER_RIFLE 32
+#define WEAP_AUTO_RIFLE 64
+#define WEAP_SHOTGUN 128
+#define WEAP_SUPER_SHOTGUN 256
+#define WEAP_NAILGUN 512
+#define WEAP_SUPER_NAILGUN 1024
+#define WEAP_GRENADE_LAUNCHER 2048
+#define WEAP_FLAMETHROWER 4096
+#define WEAP_ROCKET_LAUNCHER 8192
+#define WEAP_INCENDIARY 16384
+#define WEAP_ASSAULT_CANNON 32768
+#define WEAP_LIGHTNING 65536
+#define WEAP_DETPACK 131072
+#define WEAP_TRANQ 262144
+#define WEAP_LASER 524288
+// still room for 12 more weapons
+// but we can remove some by giving the weapons
+// a weapon mode (like the rifle)
+
+// HL-compatible weapon numbers
+#define WEAPON_HOOK 1
+#define WEAPON_BIOWEAPON (WEAPON_HOOK+1)
+#define WEAPON_MEDIKIT (WEAPON_HOOK+2)
+#define WEAPON_SPANNER (WEAPON_HOOK+3)
+#define WEAPON_AXE (WEAPON_HOOK+4)
+#define WEAPON_SNIPER_RIFLE (WEAPON_HOOK+5)
+#define WEAPON_AUTO_RIFLE (WEAPON_HOOK+6)
+#define WEAPON_TF_SHOTGUN (WEAPON_HOOK+7)
+#define WEAPON_SUPER_SHOTGUN (WEAPON_HOOK+8)
+#define WEAPON_NAILGUN (WEAPON_HOOK+9)
+#define WEAPON_SUPER_NAILGUN (WEAPON_HOOK+10)
+#define WEAPON_GRENADE_LAUNCHER (WEAPON_HOOK+11)
+#define WEAPON_FLAMETHROWER (WEAPON_HOOK+12)
+#define WEAPON_ROCKET_LAUNCHER (WEAPON_HOOK+13)
+#define WEAPON_INCENDIARY (WEAPON_HOOK+14)
+#define WEAPON_ASSAULT_CANNON (WEAPON_HOOK+16)
+#define WEAPON_LIGHTNING (WEAPON_HOOK+17)
+#define WEAPON_DETPACK (WEAPON_HOOK+18)
+#define WEAPON_TRANQ (WEAPON_HOOK+19)
+#define WEAPON_LASER (WEAPON_HOOK+20)
+#define WEAPON_PIPEBOMB_LAUNCHER (WEAPON_HOOK+21)
+#define WEAPON_KNIFE (WEAPON_HOOK+22)
+#define WEAPON_BENCHMARK (WEAPON_HOOK+23)
+
+/*==================================================*/
+/* New Weapon Related Defines */
+/*==================================================*/
+// shots per reload
+#define RE_SHOTGUN 8
+#define RE_SUPER_SHOTGUN 16 // 8 shots
+#define RE_GRENADE_LAUNCHER 6
+#define RE_ROCKET_LAUNCHER 4
+
+// reload times
+#define RE_SHOTGUN_TIME 2
+#define RE_SUPER_SHOTGUN_TIME 3
+#define RE_GRENADE_LAUNCHER_TIME 4
+#define RE_ROCKET_LAUNCHER_TIME 5
+
+// Maximum velocity you can move and fire the Sniper Rifle
+#define WEAP_SNIPER_RIFLE_MAX_MOVE 50
+
+// Medikit
+#define WEAP_MEDIKIT_HEAL 200 // Amount medikit heals per hit
+#define WEAP_MEDIKIT_OVERHEAL 50 // Amount of superhealth over max_health the medikit will dispense
+
+// Spanner
+#define WEAP_SPANNER_REPAIR 10
+
+// Detpack
+#define WEAP_DETPACK_DISARMTIME 3 // Time it takes to disarm a Detpack
+#define WEAP_DETPACK_SETTIME 3 // Time it takes to set a Detpack
+#define WEAP_DETPACK_SIZE 700 // Explosion Size
+#define WEAP_DETPACK_GOAL_SIZE 1500 // Explosion Size for goal triggering
+#define WEAP_DETPACK_BITS_NO 12 // Bits that detpack explodes into
+
+// Tranquiliser Gun
+#define TRANQ_TIME 15
+
+// Grenades
+#define GR_PRIMETIME 3
+#define GR_CALTROP_PRIME 0.5
+#define GR_TYPE_NONE 0
+#define GR_TYPE_NORMAL 1
+#define GR_TYPE_CONCUSSION 2
+#define GR_TYPE_NAIL 3
+#define GR_TYPE_MIRV 4
+#define GR_TYPE_NAPALM 5
+//#define GR_TYPE_FLARE 6
+#define GR_TYPE_GAS 7
+#define GR_TYPE_EMP 8
+#define GR_TYPE_CALTROP 9
+//#define GR_TYPE_FLASH 10
+
+// Defines for WeaponMode
+#define GL_NORMAL 0
+#define GL_PIPEBOMB 1
+
+// Defines for OLD Concussion Grenade
+#define GR_OLD_CONCUSS_TIME 5
+#define GR_OLD_CONCUSS_DEC 20
+
+// Defines for Concussion Grenade
+#define GR_CONCUSS_TIME 0.25
+#define GR_CONCUSS_DEC 10
+#define MEDIUM_PING 150
+#define HIGH_PING 200
+
+// Defines for the Gas Grenade
+#define GR_HALLU_TIME 0.3
+#define GR_OLD_HALLU_TIME 0.5
+#define GR_HALLU_DEC 2.5
+
+// Defines for the BioInfection
+#define BIO_JUMP_RADIUS 128 // The distance the bioinfection can jump between players
+
+/*==================================================*/
+/* New Items */
+/*==================================================*/
+#define NIT_SCANNER 1
+
+#define NIT_SILVER_DOOR_OPENED #IT_KEY1 // 131072
+#define NIT_GOLD_DOOR_OPENED #IT_KEY2 // 262144
+
+/*==================================================*/
+/* New Item Flags */
+/*==================================================*/
+#define NIT_SCANNER_ENEMY 1 // Detect enemies
+#define NIT_SCANNER_FRIENDLY 2 // Detect friendlies (team members)
+#define NIT_SCANNER_SOUND 4 // Motion detection. Only report moving entities.
+
+/*==================================================*/
+/* New Item Related Defines */
+/*==================================================*/
+#define NIT_SCANNER_POWER 25 // The amount of power spent on a scan with the scanner
+ // is multiplied by this to get the scanrange.
+#define NIT_SCANNER_MAXCELL 50 // The maximum number of cells than can be used in one scan
+#define NIT_SCANNER_MIN_MOVEMENT 50 // The minimum velocity an entity must have to be detected
+ // by scanners that only detect movement
+
+/*==================================================*/
+/* Variables used for New Weapons and Reloading */
+/*==================================================*/
+// Armor Classes : Bitfields. Use the "armorclass" of armor for the Armor Type.
+#define AT_SAVESHOT 1 // Kevlar : Reduces bullet damage by 15%
+#define AT_SAVENAIL 2 // Wood :) : Reduces nail damage by 15%
+#define AT_SAVEEXPLOSION 4 // Blast : Reduces explosion damage by 15%
+#define AT_SAVEELECTRICITY 8 // Shock : Reduces electricity damage by 15%
+#define AT_SAVEFIRE 16 // Asbestos : Reduces fire damage by 15%
+
+/*==========================================================================*/
+/* TEAMFORTRESS CLASS DETAILS */
+/*==========================================================================*/
+// Class Details for SCOUT
+#define PC_SCOUT_SKIN 4 // Skin for this class when Classkin is on.
+#define PC_SCOUT_MAXHEALTH 75 // Maximum Health Level
+#define PC_SCOUT_MAXSPEED 400 // Maximum movement speed
+#define PC_SCOUT_MAXSTRAFESPEED 400 // Maximum strafing movement speed
+#define PC_SCOUT_MAXARMOR 50 // Maximum Armor Level, of any armor class
+#define PC_SCOUT_INITARMOR 25 // Armor level when respawned
+#define PC_SCOUT_MAXARMORTYPE 0.3 // Maximum level of Armor absorption
+#define PC_SCOUT_INITARMORTYPE 0.3 // Absorption Level of armor when respawned
+#define PC_SCOUT_ARMORCLASSES 3 // #AT_SAVESHOT | #AT_SAVENAIL <-Armor Classes allowed for this class
+#define PC_SCOUT_INITARMORCLASS 0 // Armorclass worn when respawned
+#define PC_SCOUT_WEAPONS WEAP_AXE | WEAP_SHOTGUN | WEAP_NAILGUN
+#define PC_SCOUT_MAXAMMO_SHOT 50 // Maximum amount of shot ammo this class can carry
+#define PC_SCOUT_MAXAMMO_NAIL 200 // Maximum amount of nail ammo this class can carry
+#define PC_SCOUT_MAXAMMO_CELL 100 // Maximum amount of cell ammo this class can carry
+#define PC_SCOUT_MAXAMMO_ROCKET 25 // Maximum amount of rocket ammo this class can carry
+#define PC_SCOUT_INITAMMO_SHOT 25 // Amount of shot ammo this class has when respawned
+#define PC_SCOUT_INITAMMO_NAIL 100 // Amount of nail ammo this class has when respawned
+#define PC_SCOUT_INITAMMO_CELL 50 // Amount of cell ammo this class has when respawned
+#define PC_SCOUT_INITAMMO_ROCKET 0 // Amount of rocket ammo this class has when respawned
+#define PC_SCOUT_GRENADE_TYPE_1 GR_TYPE_CALTROP // <- 1st Type of Grenade this class has
+#define PC_SCOUT_GRENADE_TYPE_2 GR_TYPE_CONCUSSION // <- 2nd Type of Grenade this class has
+#define PC_SCOUT_GRENADE_INIT_1 2 // Number of grenades of Type 1 this class has when respawned
+#define PC_SCOUT_GRENADE_INIT_2 3 // Number of grenades of Type 2 this class has when respawned
+#define PC_SCOUT_TF_ITEMS NIT_SCANNER // <- TeamFortress Items this class has
+
+#define PC_SCOUT_MOTION_MIN_I 0.5 // < Short range
+#define PC_SCOUT_MOTION_MIN_MOVE 50 // Minimum vlen of player velocity to be picked up by motion detector
+#define PC_SCOUT_SCAN_TIME 2 // # of seconds between each scan pulse
+#define PC_SCOUT_SCAN_RANGE 100 // Default scanner range
+#define PC_SCOUT_SCAN_COST 2 // Default scanner cell useage per scan
+
+// Class Details for SNIPER
+#define PC_SNIPER_SKIN 5
+#define PC_SNIPER_MAXHEALTH 90
+#define PC_SNIPER_MAXSPEED 300
+#define PC_SNIPER_MAXSTRAFESPEED 300
+#define PC_SNIPER_MAXARMOR 50
+#define PC_SNIPER_INITARMOR 0
+#define PC_SNIPER_MAXARMORTYPE 0.3
+#define PC_SNIPER_INITARMORTYPE 0.3
+#define PC_SNIPER_ARMORCLASSES 3 // #AT_SAVESHOT | #AT_SAVENAIL
+#define PC_SNIPER_INITARMORCLASS 0
+#define PC_SNIPER_WEAPONS WEAP_SNIPER_RIFLE | WEAP_AUTO_RIFLE | WEAP_AXE | WEAP_NAILGUN
+#define PC_SNIPER_MAXAMMO_SHOT 75
+#define PC_SNIPER_MAXAMMO_NAIL 100
+#define PC_SNIPER_MAXAMMO_CELL 50
+#define PC_SNIPER_MAXAMMO_ROCKET 25
+#define PC_SNIPER_INITAMMO_SHOT 60
+#define PC_SNIPER_INITAMMO_NAIL 50
+#define PC_SNIPER_INITAMMO_CELL 0
+#define PC_SNIPER_INITAMMO_ROCKET 0
+#define PC_SNIPER_GRENADE_TYPE_1 GR_TYPE_NORMAL
+#define PC_SNIPER_GRENADE_TYPE_2 GR_TYPE_NONE
+#define PC_SNIPER_GRENADE_INIT_1 2
+#define PC_SNIPER_GRENADE_INIT_2 0
+#define PC_SNIPER_TF_ITEMS 0
+
+// Class Details for SOLDIER
+#define PC_SOLDIER_SKIN 6
+#define PC_SOLDIER_MAXHEALTH 100
+#define PC_SOLDIER_MAXSPEED 240
+#define PC_SOLDIER_MAXSTRAFESPEED 240
+#define PC_SOLDIER_MAXARMOR 200
+#define PC_SOLDIER_INITARMOR 100
+#define PC_SOLDIER_MAXARMORTYPE 0.8
+#define PC_SOLDIER_INITARMORTYPE 0.8
+#define PC_SOLDIER_ARMORCLASSES 31 // ALL
+#define PC_SOLDIER_INITARMORCLASS 0
+#define PC_SOLDIER_WEAPONS WEAP_AXE | WEAP_SHOTGUN | WEAP_SUPER_SHOTGUN | WEAP_ROCKET_LAUNCHER
+#define PC_SOLDIER_MAXAMMO_SHOT 100
+#define PC_SOLDIER_MAXAMMO_NAIL 100
+#define PC_SOLDIER_MAXAMMO_CELL 50
+#define PC_SOLDIER_MAXAMMO_ROCKET 50
+#define PC_SOLDIER_INITAMMO_SHOT 50
+#define PC_SOLDIER_INITAMMO_NAIL 0
+#define PC_SOLDIER_INITAMMO_CELL 0
+#define PC_SOLDIER_INITAMMO_ROCKET 10
+#define PC_SOLDIER_GRENADE_TYPE_1 GR_TYPE_NORMAL
+#define PC_SOLDIER_GRENADE_TYPE_2 GR_TYPE_NAIL
+#define PC_SOLDIER_GRENADE_INIT_1 2
+#define PC_SOLDIER_GRENADE_INIT_2 1
+#define PC_SOLDIER_TF_ITEMS 0
+
+#define MAX_NAIL_GRENS 2 // Can only have 2 Nail grens active
+#define MAX_NAPALM_GRENS 2 // Can only have 2 Napalm grens active
+#define MAX_GAS_GRENS 2 // Can only have 2 Gas grenades active
+#define MAX_MIRV_GRENS 2 // Can only have 2 Mirv's
+#define MAX_CONCUSSION_GRENS 3
+#define MAX_CALTROP_CANS 3
+
+// Class Details for DEMOLITION MAN
+#define PC_DEMOMAN_SKIN 1
+#define PC_DEMOMAN_MAXHEALTH 90
+#define PC_DEMOMAN_MAXSPEED 280
+#define PC_DEMOMAN_MAXSTRAFESPEED 280
+#define PC_DEMOMAN_MAXARMOR 120
+#define PC_DEMOMAN_INITARMOR 50
+#define PC_DEMOMAN_MAXARMORTYPE 0.6
+#define PC_DEMOMAN_INITARMORTYPE 0.6
+#define PC_DEMOMAN_ARMORCLASSES 31 // ALL
+#define PC_DEMOMAN_INITARMORCLASS 0
+#define PC_DEMOMAN_WEAPONS WEAP_AXE | WEAP_SHOTGUN | WEAP_GRENADE_LAUNCHER | WEAP_DETPACK
+#define PC_DEMOMAN_MAXAMMO_SHOT 75
+#define PC_DEMOMAN_MAXAMMO_NAIL 50
+#define PC_DEMOMAN_MAXAMMO_CELL 50
+#define PC_DEMOMAN_MAXAMMO_ROCKET 50
+#define PC_DEMOMAN_MAXAMMO_DETPACK 1
+#define PC_DEMOMAN_INITAMMO_SHOT 30
+#define PC_DEMOMAN_INITAMMO_NAIL 0
+#define PC_DEMOMAN_INITAMMO_CELL 0
+#define PC_DEMOMAN_INITAMMO_ROCKET 20
+#define PC_DEMOMAN_INITAMMO_DETPACK 1
+#define PC_DEMOMAN_GRENADE_TYPE_1 GR_TYPE_NORMAL
+#define PC_DEMOMAN_GRENADE_TYPE_2 GR_TYPE_MIRV
+#define PC_DEMOMAN_GRENADE_INIT_1 2
+#define PC_DEMOMAN_GRENADE_INIT_2 2
+#define PC_DEMOMAN_TF_ITEMS 0
+
+// Class Details for COMBAT MEDIC
+#define PC_MEDIC_SKIN 3
+#define PC_MEDIC_MAXHEALTH 90
+#define PC_MEDIC_MAXSPEED 320
+#define PC_MEDIC_MAXSTRAFESPEED 320
+#define PC_MEDIC_MAXARMOR 100
+#define PC_MEDIC_INITARMOR 50
+#define PC_MEDIC_MAXARMORTYPE 0.6
+#define PC_MEDIC_INITARMORTYPE 0.3
+#define PC_MEDIC_ARMORCLASSES 11 // ALL except EXPLOSION
+#define PC_MEDIC_INITARMORCLASS 0
+#define PC_MEDIC_WEAPONS WEAP_BIOWEAPON | WEAP_MEDIKIT | WEAP_SHOTGUN | WEAP_SUPER_SHOTGUN | WEAP_SUPER_NAILGUN
+#define PC_MEDIC_MAXAMMO_SHOT 75
+#define PC_MEDIC_MAXAMMO_NAIL 150
+#define PC_MEDIC_MAXAMMO_CELL 50
+#define PC_MEDIC_MAXAMMO_ROCKET 25
+#define PC_MEDIC_MAXAMMO_MEDIKIT 100
+#define PC_MEDIC_INITAMMO_SHOT 50
+#define PC_MEDIC_INITAMMO_NAIL 50
+#define PC_MEDIC_INITAMMO_CELL 0
+#define PC_MEDIC_INITAMMO_ROCKET 0
+#define PC_MEDIC_INITAMMO_MEDIKIT 50
+#define PC_MEDIC_GRENADE_TYPE_1 GR_TYPE_NORMAL
+#define PC_MEDIC_GRENADE_TYPE_2 GR_TYPE_CONCUSSION
+#define PC_MEDIC_GRENADE_INIT_1 2
+#define PC_MEDIC_GRENADE_INIT_2 2
+#define PC_MEDIC_TF_ITEMS 0
+#define PC_MEDIC_REGEN_TIME 3 // Number of seconds between each regen.
+#define PC_MEDIC_REGEN_AMOUNT 2 // Amount of health regenerated each regen.
+
+// Class Details for HVYWEAP
+#define PC_HVYWEAP_SKIN 2
+#define PC_HVYWEAP_MAXHEALTH 100
+#define PC_HVYWEAP_MAXSPEED 230
+#define PC_HVYWEAP_MAXSTRAFESPEED 230
+#define PC_HVYWEAP_MAXARMOR 300
+#define PC_HVYWEAP_INITARMOR 150
+#define PC_HVYWEAP_MAXARMORTYPE 0.8
+#define PC_HVYWEAP_INITARMORTYPE 0.8
+#define PC_HVYWEAP_ARMORCLASSES 31 // ALL
+#define PC_HVYWEAP_INITARMORCLASS 0
+#define PC_HVYWEAP_WEAPONS WEAP_ASSAULT_CANNON | WEAP_AXE | WEAP_SHOTGUN | WEAP_SUPER_SHOTGUN
+#define PC_HVYWEAP_MAXAMMO_SHOT 200
+#define PC_HVYWEAP_MAXAMMO_NAIL 200
+#define PC_HVYWEAP_MAXAMMO_CELL 50
+#define PC_HVYWEAP_MAXAMMO_ROCKET 25
+#define PC_HVYWEAP_INITAMMO_SHOT 200
+#define PC_HVYWEAP_INITAMMO_NAIL 0
+#define PC_HVYWEAP_INITAMMO_CELL 30
+#define PC_HVYWEAP_INITAMMO_ROCKET 0
+#define PC_HVYWEAP_GRENADE_TYPE_1 GR_TYPE_NORMAL
+#define PC_HVYWEAP_GRENADE_TYPE_2 GR_TYPE_MIRV
+#define PC_HVYWEAP_GRENADE_INIT_1 2
+#define PC_HVYWEAP_GRENADE_INIT_2 1
+#define PC_HVYWEAP_TF_ITEMS 0
+#define PC_HVYWEAP_CELL_USAGE 7 // Amount of cells spent to power up assault cannon
+
+
+
+// Class Details for PYRO
+#define PC_PYRO_SKIN 21
+#define PC_PYRO_MAXHEALTH 100
+#define PC_PYRO_MAXSPEED 300
+#define PC_PYRO_MAXSTRAFESPEED 300
+#define PC_PYRO_MAXARMOR 150
+#define PC_PYRO_INITARMOR 50
+#define PC_PYRO_MAXARMORTYPE 0.6
+#define PC_PYRO_INITARMORTYPE 0.6
+#define PC_PYRO_ARMORCLASSES 27 // ALL except EXPLOSION
+#define PC_PYRO_INITARMORCLASS 16 // #AT_SAVEFIRE
+#define PC_PYRO_WEAPONS WEAP_INCENDIARY | WEAP_FLAMETHROWER | WEAP_AXE | WEAP_SHOTGUN
+#define PC_PYRO_MAXAMMO_SHOT 40
+#define PC_PYRO_MAXAMMO_NAIL 50
+#define PC_PYRO_MAXAMMO_CELL 200
+#define PC_PYRO_MAXAMMO_ROCKET 20
+#define PC_PYRO_INITAMMO_SHOT 20
+#define PC_PYRO_INITAMMO_NAIL 0
+#define PC_PYRO_INITAMMO_CELL 120
+#define PC_PYRO_INITAMMO_ROCKET 5
+#define PC_PYRO_GRENADE_TYPE_1 GR_TYPE_NORMAL
+#define PC_PYRO_GRENADE_TYPE_2 GR_TYPE_NAPALM
+#define PC_PYRO_GRENADE_INIT_1 2
+#define PC_PYRO_GRENADE_INIT_2 4
+#define PC_PYRO_TF_ITEMS 0
+#define PC_PYRO_ROCKET_USAGE 3 // Number of rockets per incendiary cannon shot
+
+// Class Details for SPY
+#define PC_SPY_SKIN 22
+#define PC_SPY_MAXHEALTH 90
+#define PC_SPY_MAXSPEED 300
+#define PC_SPY_MAXSTRAFESPEED 300
+#define PC_SPY_MAXARMOR 100
+#define PC_SPY_INITARMOR 25
+#define PC_SPY_MAXARMORTYPE 0.6 // Was 0.3
+#define PC_SPY_INITARMORTYPE 0.6 // Was 0.3
+#define PC_SPY_ARMORCLASSES 27 // ALL except EXPLOSION
+#define PC_SPY_INITARMORCLASS 0
+#define PC_SPY_WEAPONS WEAP_AXE | WEAP_TRANQ | WEAP_SUPER_SHOTGUN | WEAP_NAILGUN
+#define PC_SPY_MAXAMMO_SHOT 40
+#define PC_SPY_MAXAMMO_NAIL 100
+#define PC_SPY_MAXAMMO_CELL 30
+#define PC_SPY_MAXAMMO_ROCKET 15
+#define PC_SPY_INITAMMO_SHOT 40
+#define PC_SPY_INITAMMO_NAIL 50
+#define PC_SPY_INITAMMO_CELL 10
+#define PC_SPY_INITAMMO_ROCKET 0
+#define PC_SPY_GRENADE_TYPE_1 GR_TYPE_NORMAL
+#define PC_SPY_GRENADE_TYPE_2 GR_TYPE_GAS
+#define PC_SPY_GRENADE_INIT_1 2
+#define PC_SPY_GRENADE_INIT_2 2
+#define PC_SPY_TF_ITEMS 0
+#define PC_SPY_CELL_REGEN_TIME 5
+#define PC_SPY_CELL_REGEN_AMOUNT 1
+#define PC_SPY_CELL_USAGE 3 // Amount of cells spent while invisible
+#define PC_SPY_GO_UNDERCOVER_TIME 4 // Time it takes to go undercover
+
+// Class Details for ENGINEER
+#define PC_ENGINEER_SKIN 22 // Not used anymore
+#define PC_ENGINEER_MAXHEALTH 80
+#define PC_ENGINEER_MAXSPEED 300
+#define PC_ENGINEER_MAXSTRAFESPEED 300
+#define PC_ENGINEER_MAXARMOR 50
+#define PC_ENGINEER_INITARMOR 25
+#define PC_ENGINEER_MAXARMORTYPE 0.6
+#define PC_ENGINEER_INITARMORTYPE 0.3
+#define PC_ENGINEER_ARMORCLASSES 31 // ALL
+#define PC_ENGINEER_INITARMORCLASS 0
+#define PC_ENGINEER_WEAPONS WEAP_SPANNER | WEAP_LASER | WEAP_SUPER_SHOTGUN
+#define PC_ENGINEER_MAXAMMO_SHOT 50
+#define PC_ENGINEER_MAXAMMO_NAIL 50
+#define PC_ENGINEER_MAXAMMO_CELL 200 // synonymous with metal
+#define PC_ENGINEER_MAXAMMO_ROCKET 30
+#define PC_ENGINEER_INITAMMO_SHOT 20
+#define PC_ENGINEER_INITAMMO_NAIL 25
+#define PC_ENGINEER_INITAMMO_CELL 100 // synonymous with metal
+#define PC_ENGINEER_INITAMMO_ROCKET 0
+#define PC_ENGINEER_GRENADE_TYPE_1 GR_TYPE_NORMAL
+#define PC_ENGINEER_GRENADE_TYPE_2 GR_TYPE_EMP
+#define PC_ENGINEER_GRENADE_INIT_1 2
+#define PC_ENGINEER_GRENADE_INIT_2 2
+#define PC_ENGINEER_TF_ITEMS 0
+
+// Class Details for CIVILIAN
+#define PC_CIVILIAN_SKIN 22
+#define PC_CIVILIAN_MAXHEALTH 50
+#define PC_CIVILIAN_MAXSPEED 240
+#define PC_CIVILIAN_MAXSTRAFESPEED 240
+#define PC_CIVILIAN_MAXARMOR 0
+#define PC_CIVILIAN_INITARMOR 0
+#define PC_CIVILIAN_MAXARMORTYPE 0
+#define PC_CIVILIAN_INITARMORTYPE 0
+#define PC_CIVILIAN_ARMORCLASSES 0
+#define PC_CIVILIAN_INITARMORCLASS 0
+#define PC_CIVILIAN_WEAPONS WEAP_AXE
+#define PC_CIVILIAN_MAXAMMO_SHOT 0
+#define PC_CIVILIAN_MAXAMMO_NAIL 0
+#define PC_CIVILIAN_MAXAMMO_CELL 0
+#define PC_CIVILIAN_MAXAMMO_ROCKET 0
+#define PC_CIVILIAN_INITAMMO_SHOT 0
+#define PC_CIVILIAN_INITAMMO_NAIL 0
+#define PC_CIVILIAN_INITAMMO_CELL 0
+#define PC_CIVILIAN_INITAMMO_ROCKET 0
+#define PC_CIVILIAN_GRENADE_TYPE_1 0
+#define PC_CIVILIAN_GRENADE_TYPE_2 0
+#define PC_CIVILIAN_GRENADE_INIT_1 0
+#define PC_CIVILIAN_GRENADE_INIT_2 0
+#define PC_CIVILIAN_TF_ITEMS 0
+
+
+/*==========================================================================*/
+/* TEAMFORTRESS GOALS */
+/*==========================================================================*/
+// For all these defines, see the tfortmap.txt that came with the zip
+// for complete descriptions.
+// Defines for Goal Activation types : goal_activation (in goals)
+#define TFGA_TOUCH 1 // Activated when touched
+#define TFGA_TOUCH_DETPACK 2 // Activated when touched by a detpack explosion
+#define TFGA_REVERSE_AP 4 // Activated when AP details are _not_ met
+#define TFGA_SPANNER 8 // Activated when hit by an engineer's spanner
+#define TFGA_DROPTOGROUND 2048 // Drop to Ground when spawning
+
+// Defines for Goal Effects types : goal_effect
+#define TFGE_AP 1 // AP is affected. Default.
+#define TFGE_AP_TEAM 2 // All of the AP's team.
+#define TFGE_NOT_AP_TEAM 4 // All except AP's team.
+#define TFGE_NOT_AP 8 // All except AP.
+#define TFGE_WALL 16 // If set, walls stop the Radius effects
+#define TFGE_SAME_ENVIRONMENT 32 // If set, players in a different environment to the Goal are not affected
+#define TFGE_TIMER_CHECK_AP 64 // If set, Timer Goals check their critera for all players fitting their effects
+
+// Defines for Goal Result types : goal_result
+#define TFGR_SINGLE 1 // Goal can only be activated once
+#define TFGR_ADD_BONUSES 2 // Any Goals activated by this one give their bonuses
+#define TFGR_ENDGAME 4 // Goal fires Intermission, displays scores, and ends level
+#define TFGR_NO_ITEM_RESULTS 8 // GoalItems given by this Goal don't do results
+#define TFGR_REMOVE_DISGUISE 16 // Prevent/Remove undercover from any Spy
+#define TFGR_FORCE_RESPAWN 32 // Forces the player to teleport to a respawn point
+#define TFGR_DESTROY_BUILDINGS 64 // Destroys this player's buildings, if anys
+
+// Defines for Goal Group Result types : goal_group
+// None!
+// But I'm leaving this variable in there, since it's fairly likely
+// that some will show up sometime.
+
+// Defines for Goal Item types, : goal_activation (in items)
+#define TFGI_GLOW 1 // Players carrying this GoalItem will glow
+#define TFGI_SLOW 2 // Players carrying this GoalItem will move at half-speed
+#define TFGI_DROP 4 // Players dying with this item will drop it
+#define TFGI_RETURN_DROP 8 // Return if a player with it dies
+#define TFGI_RETURN_GOAL 16 // Return if a player with it has it removed by a goal's activation
+#define TFGI_RETURN_REMOVE 32 // Return if it is removed by TFGI_REMOVE
+#define TFGI_REVERSE_AP 64 // Only pickup if the player _doesn't_ match AP Details
+#define TFGI_REMOVE 128 // Remove if left untouched for 2 minutes after being dropped
+#define TFGI_KEEP 256 // Players keep this item even when they die
+#define TFGI_ITEMGLOWS 512 // Item glows when on the ground
+#define TFGI_DONTREMOVERES 1024 // Don't remove results when the item is removed
+#define TFGI_DROPTOGROUND 2048 // Drop To Ground when spawning
+#define TFGI_CANBEDROPPED 4096 // Can be voluntarily dropped by players
+#define TFGI_SOLID 8192 // Is solid... blocks bullets, etc
+
+// Defines for methods of GoalItem returning
+#define GI_RET_DROP_DEAD 0 // Dropped by a dead player
+#define GI_RET_DROP_LIVING 1 // Dropped by a living player
+#define GI_RET_GOAL 2 // Returned by a Goal
+#define GI_RET_TIME 3 // Returned due to timeout
+
+// Defines for TeamSpawnpoints : goal_activation (in teamspawns)
+#define TFSP_MULTIPLEITEMS 1 // Give out the GoalItem multiple times
+#define TFSP_MULTIPLEMSGS 2 // Display the message multiple times
+
+// Defines for TeamSpawnpoints : goal_effects (in teamspawns)
+#define TFSP_REMOVESELF 1 // Remove itself after being spawned on
+
+// Defines for Goal States
+#define TFGS_ACTIVE 1
+#define TFGS_INACTIVE 2
+#define TFGS_REMOVED 3
+#define TFGS_DELAYED 4
+
+// Defines for GoalItem Removing from Player Methods
+#define GI_DROP_PLAYERDEATH 0 // Dropped by a dying player
+#define GI_DROP_REMOVEGOAL 1 // Removed by a Goal
+#define GI_DROP_PLAYERDROP 2 // Dropped by a player
+
+// Legal Playerclass Handling
+#define TF_ILL_SCOUT 1
+#define TF_ILL_SNIPER 2
+#define TF_ILL_SOLDIER 4
+#define TF_ILL_DEMOMAN 8
+#define TF_ILL_MEDIC 16
+#define TF_ILL_HVYWEP 32
+#define TF_ILL_PYRO 64
+#define TF_ILL_RANDOMPC 128
+#define TF_ILL_SPY 256
+#define TF_ILL_ENGINEER 512
+
+// Addition classes
+#define CLASS_TFGOAL 128
+#define CLASS_TFGOAL_TIMER 129
+#define CLASS_TFGOAL_ITEM 130
+#define CLASS_TFSPAWN 131
+
+/*==========================================================================*/
+/* Flamethrower */
+/*==========================================================================*/
+#define FLAME_PLYRMAXTIME 5.0 // lifetime in seconds of a flame on a player
+#define FLAME_MAXBURNTIME 8 // lifetime in seconds of a flame on the world (big ones)
+#define NAPALM_MAXBURNTIME 20 // lifetime in seconds of flame from a napalm grenade
+#define FLAME_MAXPLYRFLAMES 4 // maximum number of flames on a player
+#define FLAME_NUMLIGHTS 1 // maximum number of light flame
+#define FLAME_BURNRATIO 0.3 // the chance of a flame not 'sticking'
+#define GR_TYPE_FLAMES_NO 15 // number of flames spawned when a grenade explode
+#define FLAME_DAMAGE_TIME 1 // Interval between damage burns from flames
+#define FLAME_EFFECT_TIME 0.2 // frequency at which we display flame effects.
+#define FLAME_THINK_TIME 0.1 // Seconds between times the flame checks burn
+#define PER_FLAME_DAMAGE 2 // Damage taken per second per flame by burning players
+
+/*==================================================*/
+/* CTF Support defines */
+/*==================================================*/
+#define CTF_FLAG1 1
+#define CTF_FLAG2 2
+#define CTF_DROPOFF1 3
+#define CTF_DROPOFF2 4
+#define CTF_SCORE1 5
+#define CTF_SCORE2 6
+
+//.float hook_out;
+
+/*==================================================*/
+/* Camera defines */
+/*==================================================*/
+/*
+float live_camera;
+.float camdist;
+.vector camangle;
+.entity camera_list;
+*/
+
+/*==================================================*/
+/* QuakeWorld defines */
+/*==================================================*/
+/*
+float already_chosen_map;
+
+// grappling hook variables
+.entity hook;
+.float on_hook;
+.float fire_held_down;// flag - TRUE if player is still holding down the
+ // fire button after throwing a hook.
+*/
+/*==================================================*/
+/* Server Settings */
+/*==================================================*/
+// Admin modes
+#define ADMIN_MODE_NONE 0
+#define ADMIN_MODE_DEAL 1
+
+/*==================================================*/
+/* Death Message defines */
+/*==================================================*/
+#define DMSG_SHOTGUN 1
+#define DMSG_SSHOTGUN 2
+#define DMSG_NAILGUN 3
+#define DMSG_SNAILGUN 4
+#define DMSG_GRENADEL 5
+#define DMSG_ROCKETL 6
+#define DMSG_LIGHTNING 7
+#define DMSG_GREN_HAND 8
+#define DMSG_GREN_NAIL 9
+#define DMSG_GREN_MIRV 10
+#define DMSG_GREN_PIPE 11
+#define DMSG_DETPACK 12
+#define DMSG_BIOWEAPON 13
+#define DMSG_BIOWEAPON_ATT 14
+#define DMSG_FLAME 15
+#define DMSG_DETPACK_DIS 16
+#define DMSG_AXE 17
+#define DMSG_SNIPERRIFLE 18
+#define DMSG_AUTORIFLE 19
+#define DMSG_ASSAULTCANNON 20
+#define DMSG_HOOK 21
+#define DMSG_BACKSTAB 22
+#define DMSG_MEDIKIT 23
+#define DMSG_GREN_GAS 24
+#define DMSG_TRANQ 25
+#define DMSG_LASERBOLT 26
+#define DMSG_SENTRYGUN_BULLET 27
+#define DMSG_SNIPERLEGSHOT 28
+#define DMSG_SNIPERHEADSHOT 29
+#define DMSG_GREN_EMP 30
+#define DMSG_GREN_EMP_AMMO 31
+#define DMSG_SPANNER 32
+#define DMSG_INCENDIARY 33
+#define DMSG_SENTRYGUN_ROCKET 34
+#define DMSG_GREN_FLASH 35
+#define DMSG_TRIGGER 36
+#define DMSG_MIRROR 37
+#define DMSG_SENTRYDEATH 38
+#define DMSG_DISPENSERDEATH 39
+#define DMSG_GREN_AIRPIPE 40
+#define DMSG_CALTROP 41
+
+/*==================================================*/
+// TOGGLEFLAGS
+/*==================================================*/
+// Some of the toggleflags aren't used anymore, but the bits are still
+// there to provide compatability with old maps
+#define TFLAG_CLASS_PERSIST (1 << 0) // Persistent Classes Bit
+#define TFLAG_CHEATCHECK (1 << 1) // Cheatchecking Bit
+#define TFLAG_RESPAWNDELAY (1 << 2) // RespawnDelay bit
+//#define TFLAG_UN (1 << 3) // NOT USED ANYMORE
+#define TFLAG_OLD_GRENS (1 << 3) // Use old concussion grenade and flash grenade
+#define TFLAG_UN2 (1 << 4) // NOT USED ANYMORE
+#define TFLAG_UN3 (1 << 5) // NOT USED ANYMORE
+#define TFLAG_UN4 (1 << 6) // NOT USED ANYMORE: Was Autoteam. CVAR tfc_autoteam used now.
+#define TFLAG_TEAMFRAGS (1 << 7) // Individual Frags, or Frags = TeamScore
+#define TFLAG_FIRSTENTRY (1 << 8) // Used to determine the first time toggleflags is set
+ // In a map. Cannot be toggled by players.
+#define TFLAG_SPYINVIS (1 << 9) // Spy invisible only
+#define TFLAG_GRAPPLE (1 << 10) // Grapple on/off
+//#define TFLAG_FULLTEAMSCORE (1 << 11) // Each Team's score is TeamScore + Frags
+#define TFLAG_FLAGEMULATION (1 << 12) // Flag emulation on for old TF maps
+#define TFLAG_USE_STANDARD (1 << 13) // Use the TF War standard for Flag emulation
+
+#define TFLAG_FRAGSCORING (1 << 14) // Use frag scoring only
+
+/*======================*/
+// Menu stuff //
+/*======================*/
+
+#define MENU_DEFAULT 1
+#define MENU_TEAM 2
+#define MENU_CLASS 3
+#define MENU_MAPBRIEFING 4
+#define MENU_INTRO 5
+#define MENU_CLASSHELP 6
+#define MENU_CLASSHELP2 7
+#define MENU_REPEATHELP 8
+
+#define MENU_SPECHELP 9
+
+
+#define MENU_SPY 12
+#define MENU_SPY_SKIN 13
+#define MENU_SPY_COLOR 14
+#define MENU_ENGINEER 15
+#define MENU_ENGINEER_FIX_DISPENSER 16
+#define MENU_ENGINEER_FIX_SENTRYGUN 17
+#define MENU_ENGINEER_FIX_MORTAR 18
+#define MENU_DISPENSER 19
+#define MENU_CLASS_CHANGE 20
+#define MENU_TEAM_CHANGE 21
+
+#define MENU_REFRESH_RATE 25
+
+#define MENU_VOICETWEAK 50
+
+//============================
+// Timer Types
+#define TF_TIMER_ANY 0
+#define TF_TIMER_CONCUSSION 1
+#define TF_TIMER_INFECTION 2
+#define TF_TIMER_HALLUCINATION 3
+#define TF_TIMER_TRANQUILISATION 4
+#define TF_TIMER_ROTHEALTH 5
+#define TF_TIMER_REGENERATION 6
+#define TF_TIMER_GRENPRIME 7
+#define TF_TIMER_CELLREGENERATION 8
+#define TF_TIMER_DETPACKSET 9
+#define TF_TIMER_DETPACKDISARM 10
+#define TF_TIMER_BUILD 11
+#define TF_TIMER_CHECKBUILDDISTANCE 12
+#define TF_TIMER_DISGUISE 13
+#define TF_TIMER_DISPENSERREFILL 14
+
+// Non Player timers
+#define TF_TIMER_RETURNITEM 100
+#define TF_TIMER_DELAYEDGOAL 101
+#define TF_TIMER_ENDROUND 102
+
+//============================
+// Teamscore printing
+#define TS_PRINT_SHORT 1
+#define TS_PRINT_LONG 2
+#define TS_PRINT_LONG_TO_ALL 3
+
+#ifndef TF_DEFS_ONLY
+typedef struct
+{
+ int topColor;
+ int bottomColor;
+} team_color_t;
+/*==================================================*/
+/* GLOBAL VARIABLES */
+/*==================================================*/
+// FortressMap stuff
+extern float number_of_teams; // number of teams supported by the map
+extern int illegalclasses[5]; // Illegal playerclasses for all teams
+extern int civilianteams; // Bitfield holding Civilian teams
+extern Vector rgbcolors[5]; // RGB colors for each of the 4 teams
+
+extern team_color_t teamcolors[5][PC_LASTCLASS]; // Colors for each of the 4 teams
+extern int teamscores[5]; // Goal Score of each team
+extern int g_iOrderedTeams[5]; // Teams ordered into order of winners->losers
+extern int teamfrags[5]; // Total Frags for each team
+extern int teamlives[5]; // Number of lives each team's players have
+extern int teammaxplayers[5]; // Max number of players allowed in each team
+extern float teamadvantage[5]; // only used if the teamplay equalisation bits are set
+ // stores the damage ratio players take/give
+extern int teamallies[5]; // Keeps track of which teams are allied
+extern string_t team_names[5];
+
+extern BOOL CTF_Map;
+extern BOOL birthday;
+extern BOOL christmas;
+
+extern float num_world_flames;
+
+// Clan Battle stuff
+extern float clan_scores_dumped;
+extern float cb_prematch_time;
+extern float fOldPrematch;
+extern float fOldCeaseFire;
+extern float cb_ceasefire_time;
+extern float last_id;
+extern float spy_off;
+extern float old_grens;
+extern float flagem_checked;
+extern float flNextEqualisationCalc;
+extern BOOL cease_fire;
+extern BOOL no_cease_fire_text;
+extern BOOL initial_cease_fire;
+extern BOOL last_cease_fire;
+// Autokick stuff
+extern float autokick_kills;
+
+extern float deathmsg; // Global, which is set before every T_Damage, to indicate
+ // the death message that should be used.
+
+extern char *sTeamSpawnNames[];
+extern char *sClassNames[];
+extern char *sNewClassModelFiles[];
+extern char *sOldClassModelFiles[];
+extern char *sClassModels[];
+extern char *sClassCfgs[];
+extern char *sGrenadeNames[];
+extern string_t team_menu_string;
+
+extern int toggleflags; // toggleable flags
+
+extern BOOL g_bFirstClient;
+
+extern float g_fNextPrematchAlert;
+
+typedef struct
+{
+ int ip;
+ edict_t *pEdict;
+} ip_storage_t;
+
+extern ip_storage_t g_IpStorage[32];
+
+class CGhost;
+/*==========================================================================*/
+BOOL ClassIsRestricted(float tno, int pc);
+char* GetTeamName(int tno);
+int TeamFortress_GetNoPlayers();
+void DestroyBuilding(CBaseEntity *eng, char *bld);
+void teamsprint( int tno, CBaseEntity *ignore, int msg_dest, const char *st, const char *param1 = NULL, const char *param2 = NULL, const char *param3 = NULL );
+float anglemod( float v );
+
+// Team Funcs
+BOOL TeamFortress_TeamIsCivilian(float tno);
+void TeamFortress_TeamShowScores(BOOL bLong, CBasePlayer *pPlayer);
+BOOL TeamFortress_TeamPutPlayerInTeam();
+void TeamFortress_TeamSetColor(int tno);
+void TeamFortress_TeamIncreaseScore(int tno, int scoretoadd);
+int TeamFortress_TeamGetScoreFrags(int tno);
+int TeamFortress_TeamGetNoPlayers(int tno);
+float TeamEqualiseDamage(CBaseEntity *targ, CBaseEntity *attacker, float damage);
+BOOL IsSpawnPointValid( Vector &pos );
+BOOL TeamFortress_SortTeams( void );
+void DumpClanScores( void );
+void CalculateTeamEqualiser();
+
+// mapscript funcs
+void ParseTFServerSettings();
+void ParseTFMapSettings();
+CBaseEntity* Finditem(int ino);
+CBaseEntity* Findgoal(int gno);
+CBaseEntity* Findteamspawn(int gno);
+void RemoveGoal(CBaseEntity *Goal);
+void tfgoalitem_GiveToPlayer(CBaseEntity *Item, CBasePlayer *AP, CBaseEntity *Goal);
+void dremove( CBaseEntity *te );
+void tfgoalitem_RemoveFromPlayer(CBaseEntity *Item, CBasePlayer *AP, int iMethod);
+void tfgoalitem_drop(CBaseEntity *Item, BOOL PAlive, CBasePlayer *P);
+void DisplayItemStatus(CBaseEntity *Goal, CBasePlayer *Player, CBaseEntity *Item);
+void tfgoalitem_checkgoalreturn(CBaseEntity *Item);
+void DoGoalWork(CBaseEntity *Goal, CBasePlayer *AP);
+void DoResults(CBaseEntity *Goal, CBasePlayer *AP, BOOL bAddBonuses);
+void DoGroupWork(CBaseEntity *Goal, CBasePlayer *AP);
+// hooks into the mapscript for all entities
+BOOL ActivateDoResults(CBaseEntity *Goal, CBasePlayer *AP, CBaseEntity *ActivatingGoal);
+BOOL ActivationSucceeded(CBaseEntity *Goal, CBasePlayer *AP, CBaseEntity *ActivatingGoal);
+
+// prematch & ceasefire
+void Display_Prematch();
+void Check_Ceasefire();
+
+// admin
+void KickPlayer( CBaseEntity *pTarget );
+void BanPlayer( CBaseEntity *pTarget );
+CGhost *FindGhost( int iGhostID );
+int GetBattleID( edict_t *pEntity );
+
+extern cvar_t tfc_spam_penalty1;// the initial gag penalty for a spammer (seconds)
+extern cvar_t tfc_spam_penalty2;// incremental gag penalty (seconds) for each time gagged spammer continues to speak.
+extern cvar_t tfc_spam_limit; // at this many points, gag the spammer
+extern cvar_t tfc_clanbattle, tfc_clanbattle_prematch, tfc_prematch, tfc_clanbattle_ceasefire, tfc_balance_teams, tfc_balance_scores;
+extern cvar_t tfc_clanbattle_locked, tfc_birthday, tfc_autokick_kills, tfc_fragscoring, tfc_autokick_time, tfc_adminpwd;
+extern cvar_t weaponstay, footsteps, flashlight, aimcrosshair, falldamage, teamplay;
+extern cvar_t allow_spectators;
+
+/*==========================================================================*/
+class CTFFlame : public CBaseMonster
+{
+public:
+ void Spawn( void );
+ void Precache( void );
+ void EXPORT FlameThink( void );
+ static CTFFlame *FlameSpawn( CBaseEntity *pOwner, CBaseEntity *pTarget );
+ void FlameDestroy( void );
+
+ float m_flNextDamageTime;
+};
+
+/*==========================================================================*/
+// MAPSCRIPT CLASSES
+class CTFGoal : public CBaseAnimating
+{
+public:
+ void Spawn( void );
+ void StartGoal( void );
+ void EXPORT PlaceGoal( void );
+ void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
+ int Classify ( void ) { return CLASS_TFGOAL; }
+
+ void SetObjectCollisionBox( void );
+};
+
+class CTFGoalItem : public CTFGoal
+{
+public:
+ void Spawn( void );
+ void StartItem( void );
+ void EXPORT PlaceItem( void );
+ int Classify ( void ) { return CLASS_TFGOAL_ITEM; }
+
+ float m_flDroppedAt;
+};
+
+class CTFTimerGoal : public CTFGoal
+{
+public:
+ void Spawn( void );
+ int Classify ( void ) { return CLASS_TFGOAL_TIMER; }
+};
+
+class CTFSpawn : public CBaseEntity
+{
+public:
+ void Spawn( void );
+ void Activate( void );
+ int Classify ( void ) { return CLASS_TFSPAWN; }
+ BOOL CheckTeam( int iTeamNo );
+ EHANDLE m_pTeamCheck;
+};
+
+class CTFDetect : public CBaseEntity
+{
+public:
+ void Spawn( void );
+ int Classify ( void ) { return CLASS_TFGOAL; }
+};
+
+class CTelefragDeath : public CBaseEntity
+{
+public:
+ void Spawn( void );
+ void EXPORT DeathTouch( CBaseEntity *pOther );
+};
+
+class CTeamCheck : public CBaseDelay
+{
+public:
+ void Spawn( void );
+ void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
+ BOOL TeamMatches( int iTeam );
+};
+class CTeamSet : public CBaseDelay
+{
+public:
+ void Spawn( void );
+ void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
+};
+#endif // TF_DEFS_ONLY
+#endif // __TF_DEFS_H
+
+
diff --git a/main/source/cl_dll/train.cpp b/main/source/cl_dll/train.cpp
index fc80daa8..0d68134f 100644
--- a/main/source/cl_dll/train.cpp
+++ b/main/source/cl_dll/train.cpp
@@ -1,83 +1,83 @@
-/***
-*
-* Copyright (c) 1999, Valve LLC. All rights reserved.
-*
-* This product contains software technology licensed from Id
-* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
-* All Rights Reserved.
-*
-* Use, distribution, and modification of this source code and/or resulting
-* object code is restricted to non-commercial enhancements to products from
-* Valve LLC. All other use, distribution, or modification is prohibited
-* without written permission from Valve LLC.
-*
-****/
-//
-// Train.cpp
-//
-// implementation of CHudAmmo class
-//
-
-#include "hud.h"
-#include "cl_util.h"
-#include
-#include
-#include "mod/AvHNetworkMessages.h"
-
-DECLARE_MESSAGE(m_Train, Train )
-
-
-int CHudTrain::Init(void)
-{
- HOOK_MESSAGE( Train );
-
- m_iPos = 0;
- m_iFlags = 0;
- //gHUD.AddHudElem(this);
-
- return 1;
-};
-
-int CHudTrain::VidInit(void)
-{
- m_hSprite = 0;
-
- return 1;
-};
-
-int CHudTrain::Draw(float fTime)
-{
- if ( !m_hSprite )
- m_hSprite = LoadSprite("sprites/%d_train.spr");
-
- if (m_iPos)
- {
- int r, g, b, x, y;
-
- gHUD.GetPrimaryHudColor(r, g, b);
- SPR_Set(m_hSprite, r, g, b );
-
- // This should show up to the right and part way up the armor number
- y = ScreenHeight() - SPR_Height(m_hSprite,0) - gHUD.m_iFontHeight;
- x = ScreenWidth()/3 + SPR_Width(m_hSprite,0)/4;
-
- SPR_DrawAdditive( m_iPos - 1, x, y, NULL);
-
- }
-
- return 1;
-}
-
-
-int CHudTrain::MsgFunc_Train(const char *pszName, int iSize, void *pbuf)
-{
- int state;
- NetMsg_Train( pbuf, iSize, state );
-
- if (state)
- m_iFlags |= HUD_ACTIVE;
- else
- m_iFlags &= ~HUD_ACTIVE;
-
- return 1;
-}
+/***
+*
+* Copyright (c) 1999, Valve LLC. All rights reserved.
+*
+* This product contains software technology licensed from Id
+* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
+* All Rights Reserved.
+*
+* Use, distribution, and modification of this source code and/or resulting
+* object code is restricted to non-commercial enhancements to products from
+* Valve LLC. All other use, distribution, or modification is prohibited
+* without written permission from Valve LLC.
+*
+****/
+//
+// Train.cpp
+//
+// implementation of CHudAmmo class
+//
+
+#include "hud.h"
+#include "cl_util.h"
+#include
+#include
+#include "mod/AvHNetworkMessages.h"
+
+DECLARE_MESSAGE(m_Train, Train )
+
+
+int CHudTrain::Init(void)
+{
+ HOOK_MESSAGE( Train );
+
+ m_iPos = 0;
+ m_iFlags = 0;
+ //gHUD.AddHudElem(this);
+
+ return 1;
+};
+
+int CHudTrain::VidInit(void)
+{
+ m_hSprite = 0;
+
+ return 1;
+};
+
+int CHudTrain::Draw(float fTime)
+{
+ if ( !m_hSprite )
+ m_hSprite = LoadSprite("sprites/%d_train.spr");
+
+ if (m_iPos)
+ {
+ int r, g, b, x, y;
+
+ gHUD.GetPrimaryHudColor(r, g, b);
+ SPR_Set(m_hSprite, r, g, b );
+
+ // This should show up to the right and part way up the armor number
+ y = ScreenHeight() - SPR_Height(m_hSprite,0) - gHUD.m_iFontHeight;
+ x = ScreenWidth()/3 + SPR_Width(m_hSprite,0)/4;
+
+ SPR_DrawAdditive( m_iPos - 1, x, y, NULL);
+
+ }
+
+ return 1;
+}
+
+
+int CHudTrain::MsgFunc_Train(const char *pszName, int iSize, void *pbuf)
+{
+ int state;
+ NetMsg_Train( pbuf, iSize, state );
+
+ if (state)
+ m_iFlags |= HUD_ACTIVE;
+ else
+ m_iFlags &= ~HUD_ACTIVE;
+
+ return 1;
+}
diff --git a/main/source/cl_dll/tri.cpp b/main/source/cl_dll/tri.cpp
index 43cd7987..6571e32c 100644
--- a/main/source/cl_dll/tri.cpp
+++ b/main/source/cl_dll/tri.cpp
@@ -1,447 +1,447 @@
-// Triangle rendering, if any
-
-#include "hud.h"
-#include "cl_util.h"
-#include "cl_dll/in_defs.h"
-#include "cl_dll/demo.h"
-
-// Triangle rendering apis are in gEngfuncs.pTriAPI
-
-#include "common/const.h"
-#include "common/entity_state.h"
-#include "common/cl_entity.h"
-#include "common/triangleapi.h"
-#include "engine/APIProxy.h"
-#include "Exports.h"
-#include
-#include
-#include "mod/AvHParticleSystemManager.h"
-
-#include "pm_shared/pm_defs.h"
-#include "pm_shared/pm_shared.h"
-#include "pm_shared/pm_movevars.h"
-#include "mod/AvHEvents.h"
-#include "mod/AvHScriptManager.h"
-#include "mod/AvHClientVariables.h"
-
-#include "common/com_model.h"
-#include "mod/CollisionUtil.h"
-
-
-extern playermove_t *pmove;
-
-extern vec3_t v_origin;
-extern vec3_t gLastCommanderViewpoint;
-
-// A fountain
-/*
-=================
-Draw_Triangles
-
- Example routine. Draws a sprite offset from the player origin.
- =================
-*/
-//void Draw_Triangles( void )
-//{
-// cl_entity_t *player;
-// vec3_t org;
-//
-// // Load it up with some bogus data
-// player = gEngfuncs.GetLocalPlayer();
-// if ( !player )
-// return;
-//
-// org = player->origin;
-//
-// org.x += 0;
-// org.y += 0;
-//
-// pVector theView(player->angles.x, player->angles.y, player->angles.z);
-// theView.normalize();
-// pVector theUp(0.0f, 0.0f, 1.0f);
-// pVector theBase(org.x, org.y, org.z);
-//
-// // Do what the particles do.
-// ComputeParticles(theBase);
-//
-// // Create a triangle, sigh
-// //gEngfuncs.pTriAPI->RenderMode( kRenderNormal );
-// gEngfuncs.pTriAPI->CullFace( TRI_NONE );
-//
-// gEngfuncs.pTriAPI->Brightness( 1 );
-//
-// if (gHUD.m_hsprCursor == 0)
-// {
-// char sz[256];
-// //sprintf( sz, "sprites/cursor.spr" );
-// //sprintf( sz, "sprites/myrain.spr" );
-// sprintf( sz, "sprites/haze2.spr" );
-// gHUD.m_hsprCursor = SPR_Load( sz );
-// }
-//
-// if ( !gEngfuncs.pTriAPI->SpriteTexture( (struct model_s *)gEngfuncs.GetSpritePointer( gHUD.m_hsprCursor ), 0 ))
-// {
-// return;
-// }
-//
-// gEngfuncs.pTriAPI->RenderMode( kRenderTransAdd );
-// gEngfuncs.pTriAPI->Color4f(1.0f, 1.0f, 1.0f, .5f);
-// gEngfuncs.pTriAPI->CullFace( TRI_NONE );
-// DrawGroupTriSplat(theView, theUp, 70, true, true, true);
-//
-// //// Create a triangle, sigh
-// //gEngfuncs.pTriAPI->RenderMode( kRenderNormal );
-// //
-// //gEngfuncs.pTriAPI->Begin( TRI_QUADS );
-// //// Overload p->color with index into tracer palette, p->packedColor with brightness
-// //gEngfuncs.pTriAPI->Color4f( 1.0, 1.0, 1.0, 1.0 );
-// //// UNDONE: This gouraud shading causes tracers to disappear on some cards (permedia2)
-// //gEngfuncs.pTriAPI->Brightness( 1 );
-// //gEngfuncs.pTriAPI->TexCoord2f( 0, 0 );
-// //gEngfuncs.pTriAPI->Vertex3f( org.x, org.y, org.z );
-// //
-// //gEngfuncs.pTriAPI->Brightness( 1 );
-// //gEngfuncs.pTriAPI->TexCoord2f( 0, 1 );
-// //gEngfuncs.pTriAPI->Vertex3f( org.x, org.y + 50, org.z );
-// //
-// //gEngfuncs.pTriAPI->Brightness( 1 );
-// //gEngfuncs.pTriAPI->TexCoord2f( 1, 1 );
-// //gEngfuncs.pTriAPI->Vertex3f( org.x + 50, org.y + 50, org.z );
-// //
-// //gEngfuncs.pTriAPI->Brightness( 1 );
-// //gEngfuncs.pTriAPI->TexCoord2f( 1, 0 );
-// //gEngfuncs.pTriAPI->Vertex3f( org.x + 50, org.y, org.z );
-//
-//
-// gEngfuncs.pTriAPI->End();
-// gEngfuncs.pTriAPI->RenderMode( kRenderNormal );
-//}
-
-//#endif
-
-void AngleMatrix (const vec3_t angles, float (*matrix)[4] )
-{
- float angle;
- float sr, sp, sy, cr, cp, cy;
-
- angle = angles[2] * (M_PI*2 / 360);
- sy = sin(angle);
- cy = cos(angle);
- angle = angles[1] * (M_PI*2 / 360);
- sp = sin(angle);
- cp = cos(angle);
- angle = angles[0] * (M_PI*2 / 360);
- sr = sin(angle);
- cr = cos(angle);
-
- // matrix = (Z * Y) * X
- matrix[0][0] = cp*cy;
- matrix[1][0] = cp*sy;
- matrix[2][0] = -sp;
- matrix[0][1] = sr*sp*cy+cr*-sy;
- matrix[1][1] = sr*sp*sy+cr*cy;
- matrix[2][1] = sr*cp;
- matrix[0][2] = (cr*sp*cy+-sr*-sy);
- matrix[1][2] = (cr*sp*sy+-sr*cy);
- matrix[2][2] = cr*cp;
- matrix[0][3] = 0.0;
- matrix[1][3] = 0.0;
- matrix[2][3] = 0.0;
-}
-
-void VectorRotate (const vec3_t in1, const float in2[3][4], vec3_t& out)
-{
- out[0] = DotProduct(in1, in2[0]);
- out[1] = DotProduct(in1, in2[1]);
- out[2] = DotProduct(in1, in2[2]);
-}
-
-/*
-=================
-HUD_DrawNormalTriangles
-
- Non-transparent triangles-- add them here
- =================
-*/
-void CL_DLLEXPORT HUD_DrawNormalTriangles( void )
-{
-// RecClDrawNormalTriangles();
-
- // pVector theView;
- // cl_entity_t* thePlayer;
- //
- // thePlayer = gEngfuncs.GetLocalPlayer();
- // if(thePlayer)
- // {
- // pVector theView(thePlayer->angles.x, thePlayer->angles.y, thePlayer->angles.z);
- // theView.normalize();
- //
- // //AvHParticleSystemManager::Instance()->Draw(theView);
- // static int theAngle = 0;
- // //static HSPRITE theSprite = 0;
- // DrawCircleOnGroundAtPoint(thePlayer->origin, 6, theAngle++, 100, .5f, .5f, 1.0f, .5f);
- // }
-
- gHUD.PreRenderFrame();
-
- //gHUD.m_Spectator.DrawOverview();
-
-#if defined( TEST_IT )
- // Draw_Triangles();
-#endif
-}
-
-
-void DrawHitBox(const OBBox& inBox)
-{
-
- HSPRITE sprite = SPR_Load("sprites/white.spr");
-
- vec3_t theBoxPoint[8];
-
- for (int i = 0; i < 8; ++i)
- {
-
- vec3_t xAmount;
- vec3_t yAmount;
- vec3_t zAmount;
-
- if (i & 1)
- {
- VectorScale(inBox.mAxis[0], inBox.mExtents[0], xAmount);
- }
- else
- {
- VectorScale(inBox.mAxis[0], -inBox.mExtents[0], xAmount);
- }
-
- if (i & 2)
- {
- VectorScale(inBox.mAxis[1], inBox.mExtents[1], yAmount);
- }
- else
- {
- VectorScale(inBox.mAxis[1], -inBox.mExtents[1], yAmount);
- }
-
- if (i & 4)
- {
- VectorScale(inBox.mAxis[2], inBox.mExtents[2], zAmount);
- }
- else
- {
- VectorScale(inBox.mAxis[2], -inBox.mExtents[2], zAmount);
- }
-
- VectorAdd(inBox.mOrigin, xAmount, theBoxPoint[i]);
- VectorAdd(theBoxPoint[i], yAmount, theBoxPoint[i]);
- VectorAdd(theBoxPoint[i], zAmount, theBoxPoint[i]);
-
- }
-
- struct model_s* spritePtr = (struct model_s*)(gEngfuncs.GetSpritePointer(sprite));
- gEngfuncs.pTriAPI->SpriteTexture(spritePtr, 0);
-
- gEngfuncs.pTriAPI->Begin(TRI_LINES);
-
- gEngfuncs.pTriAPI->Color4f(1, 1, 1, 1);
-
- // Bottom.
-
- gEngfuncs.pTriAPI->Vertex3fv(theBoxPoint[0]);
- gEngfuncs.pTriAPI->Vertex3fv(theBoxPoint[1]);
-
- gEngfuncs.pTriAPI->Vertex3fv(theBoxPoint[1]);
- gEngfuncs.pTriAPI->Vertex3fv(theBoxPoint[3]);
-
- gEngfuncs.pTriAPI->Vertex3fv(theBoxPoint[3]);
- gEngfuncs.pTriAPI->Vertex3fv(theBoxPoint[2]);
-
- gEngfuncs.pTriAPI->Vertex3fv(theBoxPoint[2]);
- gEngfuncs.pTriAPI->Vertex3fv(theBoxPoint[0]);
-
- // Top.
-
- gEngfuncs.pTriAPI->Vertex3fv(theBoxPoint[4]);
- gEngfuncs.pTriAPI->Vertex3fv(theBoxPoint[6]);
-
- gEngfuncs.pTriAPI->Vertex3fv(theBoxPoint[6]);
- gEngfuncs.pTriAPI->Vertex3fv(theBoxPoint[7]);
-
- gEngfuncs.pTriAPI->Vertex3fv(theBoxPoint[7]);
- gEngfuncs.pTriAPI->Vertex3fv(theBoxPoint[5]);
-
- gEngfuncs.pTriAPI->Vertex3fv(theBoxPoint[5]);
- gEngfuncs.pTriAPI->Vertex3fv(theBoxPoint[4]);
-
- // Sides.
-
- gEngfuncs.pTriAPI->Vertex3fv(theBoxPoint[0]);
- gEngfuncs.pTriAPI->Vertex3fv(theBoxPoint[4]);
-
- gEngfuncs.pTriAPI->Vertex3fv(theBoxPoint[2]);
- gEngfuncs.pTriAPI->Vertex3fv(theBoxPoint[6]);
-
- gEngfuncs.pTriAPI->Vertex3fv(theBoxPoint[3]);
- gEngfuncs.pTriAPI->Vertex3fv(theBoxPoint[7]);
-
- gEngfuncs.pTriAPI->Vertex3fv(theBoxPoint[1]);
- gEngfuncs.pTriAPI->Vertex3fv(theBoxPoint[5]);
-
- gEngfuncs.pTriAPI->End();
-
-}
-
-
-void DrawHitBoxes()
-{
-
- extern int cam_thirdperson;
-
- for (int j = 1; j < 512; ++j)
- {
-
- cl_entity_t* entity = gEngfuncs.GetEntityByIndex(j);
-
- if (entity == gEngfuncs.GetLocalPlayer() && !cam_thirdperson)
- {
- continue;
- }
-
- if (entity->curstate.effects & EF_NODRAW)
- {
- continue;
- }
-
- if (entity != NULL && entity->model != NULL && entity->model->type == mod_studio)
- {
-
- int theEntityIndex = j;
-
- OBBox theBox[256];
- int theNumBoxes;
-
- NS_GetHitBoxesForEntity(theEntityIndex, 256, theBox, theNumBoxes, gEngfuncs.GetClientTime());
-
- for (int i = 0; i < theNumBoxes; ++i)
- {
- DrawHitBox(theBox[i]);
- }
-
- }
-
- }
-
-}
-
-
-
-/*
-
- =================
- HUD_DrawTransparentTriangles
-
- Render any triangles with transparent rendermode needs here
- =================
-*/
-void CL_DLLEXPORT HUD_DrawTransparentTriangles( void )
-{
-// RecClDrawTransparentTriangles();
-
- cl_entity_t* thePlayer;
-
- if (gHUD.GetParticlesVisible() && gHUD.GetSafeForSpriteDrawing())
- {
- // get local player
- thePlayer = gEngfuncs.GetLocalPlayer();
- if(thePlayer)
- {
- //pVector theView(thePlayer->angles.x, thePlayer->angles.y, thePlayer->angles.z);
- //pVector theView(viewangles[0], viewangles[1], viewangles[2]);
- //theView.normalize();
-
- vec3_t angles, up, right, forward;
- // gEngfuncs.pfnAngleVectors(thePlayer->angles, forward, right, up);
-
- // This view doesn't take pitch into account. Pitch is stored in x. While yaw goes from -180 to 180,
- // pitch goes from -10 (looking up) to 10 (looking down). Alter forward[YAW} (forward[0]) so
- // the particles can billboard themselves correctly.
-
- // float thePitch = thePlayer->angles[PITCH];
- // float theNormAngle = thePitch/-10.0f;
- // int theAngle = theNormAngle*90;
- // //float theYaw = thePlayer->angles[YAW];
- //
- // vec3_t theRotationAngles;
- // theRotationAngles[0] = theAngle;
- // theRotationAngles[1] = 0;
- // theRotationAngles[2] = 0;
- //
- // float theMatrix[3][4];
- // AngleMatrix(theRotationAngles, theMatrix);
- //
- // vec3_t theOut;
- // VectorRotate(forward, theMatrix, theOut);
- // pVector theRealView(theOut[0], theOut[1], theOut[2]);
-
- pVector theRealView;
- gEngfuncs.pfnAngleVectors(v_angles, forward, right, up);
-
- theRealView.x = forward[0];
- theRealView.y = forward[1];
- theRealView.z = forward[2];
-
- // Disable fog
- float theFogColor[3];
- theFogColor[0] = theFogColor[1] = theFogColor[2] = 0.0f;
- gEngfuncs.pTriAPI->Fog(theFogColor, 0, 0, 0);
-
- // Draw particles via tri API, without z-buffering, unless we're debugging
- //if(cl_particleinfo->value == 0)
- //{
- AvHParticleSystemManager::Instance()->Draw(theRealView);
- //}
-
- //DrawOrdersForPlayers(gHUD.GetDrawPlayerOrders());
-
- //DrawRangeIndicator();
-
- //DrawBlips(theRealView);
-
- //DrawMarineLights(theRealView);
-
- AvHScriptManager::Instance()->DrawTransparent();
-
- //DrawDebugEffects();
-
- //static int theAngle = 0;
- //DrawCircleOnGroundAtPoint(thePlayer->origin, 6, theAngle++, 100, 1.0f, 1.0f, 1.0f, .2f);
- }
-
- // Draw the hitboxes for all of the objects.
-
- // Assumes that the only time players don't have view models is when they are commanding, gestating, cocooned
- // or when they aren't playing. See the end of StudioModelRenderer::StudioDrawModel().
- //if((gHUD.GetRole() == ROLE_COMMANDER) || (gHUD.GetRole() == ROLE_GESTATING) || (gHUD.GetRole() == ROLE_COCOONED) || (gHUD.GetPlayMode() != PLAYMODE_PLAYING))
- cl_entity_t* theViewEntity = gEngfuncs.GetViewModel();
- if(!theViewEntity || !theViewEntity->model)
- {
- // This should always be rendered with the commander viewpoint
-// vec3_t theCurrentOrigin = v_origin;
-//
-// if(gHUD.GetInTopDownMode())
-// {
-// v_origin = gLastCommanderViewpoint;
-// }
-
- gHUD.RenderNoZBuffering();
-
-// if(gHUD.GetInTopDownMode())
-// {
-// v_origin = theCurrentOrigin;
-// }
- }
-
- gHUD.PostRenderFrame();
- }
-}
+// Triangle rendering, if any
+
+#include "hud.h"
+#include "cl_util.h"
+#include "cl_dll/in_defs.h"
+#include "cl_dll/demo.h"
+
+// Triangle rendering apis are in gEngfuncs.pTriAPI
+
+#include "common/const.h"
+#include "common/entity_state.h"
+#include "common/cl_entity.h"
+#include "common/triangleapi.h"
+#include "engine/APIProxy.h"
+#include "Exports.h"
+#include
+#include
+#include "mod/AvHParticleSystemManager.h"
+
+#include "pm_shared/pm_defs.h"
+#include "pm_shared/pm_shared.h"
+#include "pm_shared/pm_movevars.h"
+#include "mod/AvHEvents.h"
+#include "mod/AvHScriptManager.h"
+#include "mod/AvHClientVariables.h"
+
+#include "common/com_model.h"
+#include "mod/CollisionUtil.h"
+
+
+extern playermove_t *pmove;
+
+extern vec3_t v_origin;
+extern vec3_t gLastCommanderViewpoint;
+
+// A fountain
+/*
+=================
+Draw_Triangles
+
+ Example routine. Draws a sprite offset from the player origin.
+ =================
+*/
+//void Draw_Triangles( void )
+//{
+// cl_entity_t *player;
+// vec3_t org;
+//
+// // Load it up with some bogus data
+// player = gEngfuncs.GetLocalPlayer();
+// if ( !player )
+// return;
+//
+// org = player->origin;
+//
+// org.x += 0;
+// org.y += 0;
+//
+// pVector theView(player->angles.x, player->angles.y, player->angles.z);
+// theView.normalize();
+// pVector theUp(0.0f, 0.0f, 1.0f);
+// pVector theBase(org.x, org.y, org.z);
+//
+// // Do what the particles do.
+// ComputeParticles(theBase);
+//
+// // Create a triangle, sigh
+// //gEngfuncs.pTriAPI->RenderMode( kRenderNormal );
+// gEngfuncs.pTriAPI->CullFace( TRI_NONE );
+//
+// gEngfuncs.pTriAPI->Brightness( 1 );
+//
+// if (gHUD.m_hsprCursor == 0)
+// {
+// char sz[256];
+// //sprintf( sz, "sprites/cursor.spr" );
+// //sprintf( sz, "sprites/myrain.spr" );
+// sprintf( sz, "sprites/haze2.spr" );
+// gHUD.m_hsprCursor = SPR_Load( sz );
+// }
+//
+// if ( !gEngfuncs.pTriAPI->SpriteTexture( (struct model_s *)gEngfuncs.GetSpritePointer( gHUD.m_hsprCursor ), 0 ))
+// {
+// return;
+// }
+//
+// gEngfuncs.pTriAPI->RenderMode( kRenderTransAdd );
+// gEngfuncs.pTriAPI->Color4f(1.0f, 1.0f, 1.0f, .5f);
+// gEngfuncs.pTriAPI->CullFace( TRI_NONE );
+// DrawGroupTriSplat(theView, theUp, 70, true, true, true);
+//
+// //// Create a triangle, sigh
+// //gEngfuncs.pTriAPI->RenderMode( kRenderNormal );
+// //
+// //gEngfuncs.pTriAPI->Begin( TRI_QUADS );
+// //// Overload p->color with index into tracer palette, p->packedColor with brightness
+// //gEngfuncs.pTriAPI->Color4f( 1.0, 1.0, 1.0, 1.0 );
+// //// UNDONE: This gouraud shading causes tracers to disappear on some cards (permedia2)
+// //gEngfuncs.pTriAPI->Brightness( 1 );
+// //gEngfuncs.pTriAPI->TexCoord2f( 0, 0 );
+// //gEngfuncs.pTriAPI->Vertex3f( org.x, org.y, org.z );
+// //
+// //gEngfuncs.pTriAPI->Brightness( 1 );
+// //gEngfuncs.pTriAPI->TexCoord2f( 0, 1 );
+// //gEngfuncs.pTriAPI->Vertex3f( org.x, org.y + 50, org.z );
+// //
+// //gEngfuncs.pTriAPI->Brightness( 1 );
+// //gEngfuncs.pTriAPI->TexCoord2f( 1, 1 );
+// //gEngfuncs.pTriAPI->Vertex3f( org.x + 50, org.y + 50, org.z );
+// //
+// //gEngfuncs.pTriAPI->Brightness( 1 );
+// //gEngfuncs.pTriAPI->TexCoord2f( 1, 0 );
+// //gEngfuncs.pTriAPI->Vertex3f( org.x + 50, org.y, org.z );
+//
+//
+// gEngfuncs.pTriAPI->End();
+// gEngfuncs.pTriAPI->RenderMode( kRenderNormal );
+//}
+
+//#endif
+
+void AngleMatrix (const vec3_t angles, float (*matrix)[4] )
+{
+ float angle;
+ float sr, sp, sy, cr, cp, cy;
+
+ angle = angles[2] * (M_PI*2 / 360);
+ sy = sin(angle);
+ cy = cos(angle);
+ angle = angles[1] * (M_PI*2 / 360);
+ sp = sin(angle);
+ cp = cos(angle);
+ angle = angles[0] * (M_PI*2 / 360);
+ sr = sin(angle);
+ cr = cos(angle);
+
+ // matrix = (Z * Y) * X
+ matrix[0][0] = cp*cy;
+ matrix[1][0] = cp*sy;
+ matrix[2][0] = -sp;
+ matrix[0][1] = sr*sp*cy+cr*-sy;
+ matrix[1][1] = sr*sp*sy+cr*cy;
+ matrix[2][1] = sr*cp;
+ matrix[0][2] = (cr*sp*cy+-sr*-sy);
+ matrix[1][2] = (cr*sp*sy+-sr*cy);
+ matrix[2][2] = cr*cp;
+ matrix[0][3] = 0.0;
+ matrix[1][3] = 0.0;
+ matrix[2][3] = 0.0;
+}
+
+void VectorRotate (const vec3_t in1, const float in2[3][4], vec3_t& out)
+{
+ out[0] = DotProduct(in1, in2[0]);
+ out[1] = DotProduct(in1, in2[1]);
+ out[2] = DotProduct(in1, in2[2]);
+}
+
+/*
+=================
+HUD_DrawNormalTriangles
+
+ Non-transparent triangles-- add them here
+ =================
+*/
+void CL_DLLEXPORT HUD_DrawNormalTriangles( void )
+{
+// RecClDrawNormalTriangles();
+
+ // pVector theView;
+ // cl_entity_t* thePlayer;
+ //
+ // thePlayer = gEngfuncs.GetLocalPlayer();
+ // if(thePlayer)
+ // {
+ // pVector theView(thePlayer->angles.x, thePlayer->angles.y, thePlayer->angles.z);
+ // theView.normalize();
+ //
+ // //AvHParticleSystemManager::Instance()->Draw(theView);
+ // static int theAngle = 0;
+ // //static HSPRITE theSprite = 0;
+ // DrawCircleOnGroundAtPoint(thePlayer->origin, 6, theAngle++, 100, .5f, .5f, 1.0f, .5f);
+ // }
+
+ gHUD.PreRenderFrame();
+
+ //gHUD.m_Spectator.DrawOverview();
+
+#if defined( TEST_IT )
+ // Draw_Triangles();
+#endif
+}
+
+
+void DrawHitBox(const OBBox& inBox)
+{
+
+ HSPRITE sprite = SPR_Load("sprites/white.spr");
+
+ vec3_t theBoxPoint[8];
+
+ for (int i = 0; i < 8; ++i)
+ {
+
+ vec3_t xAmount;
+ vec3_t yAmount;
+ vec3_t zAmount;
+
+ if (i & 1)
+ {
+ VectorScale(inBox.mAxis[0], inBox.mExtents[0], xAmount);
+ }
+ else
+ {
+ VectorScale(inBox.mAxis[0], -inBox.mExtents[0], xAmount);
+ }
+
+ if (i & 2)
+ {
+ VectorScale(inBox.mAxis[1], inBox.mExtents[1], yAmount);
+ }
+ else
+ {
+ VectorScale(inBox.mAxis[1], -inBox.mExtents[1], yAmount);
+ }
+
+ if (i & 4)
+ {
+ VectorScale(inBox.mAxis[2], inBox.mExtents[2], zAmount);
+ }
+ else
+ {
+ VectorScale(inBox.mAxis[2], -inBox.mExtents[2], zAmount);
+ }
+
+ VectorAdd(inBox.mOrigin, xAmount, theBoxPoint[i]);
+ VectorAdd(theBoxPoint[i], yAmount, theBoxPoint[i]);
+ VectorAdd(theBoxPoint[i], zAmount, theBoxPoint[i]);
+
+ }
+
+ struct model_s* spritePtr = (struct model_s*)(gEngfuncs.GetSpritePointer(sprite));
+ gEngfuncs.pTriAPI->SpriteTexture(spritePtr, 0);
+
+ gEngfuncs.pTriAPI->Begin(TRI_LINES);
+
+ gEngfuncs.pTriAPI->Color4f(1, 1, 1, 1);
+
+ // Bottom.
+
+ gEngfuncs.pTriAPI->Vertex3fv(theBoxPoint[0]);
+ gEngfuncs.pTriAPI->Vertex3fv(theBoxPoint[1]);
+
+ gEngfuncs.pTriAPI->Vertex3fv(theBoxPoint[1]);
+ gEngfuncs.pTriAPI->Vertex3fv(theBoxPoint[3]);
+
+ gEngfuncs.pTriAPI->Vertex3fv(theBoxPoint[3]);
+ gEngfuncs.pTriAPI->Vertex3fv(theBoxPoint[2]);
+
+ gEngfuncs.pTriAPI->Vertex3fv(theBoxPoint[2]);
+ gEngfuncs.pTriAPI->Vertex3fv(theBoxPoint[0]);
+
+ // Top.
+
+ gEngfuncs.pTriAPI->Vertex3fv(theBoxPoint[4]);
+ gEngfuncs.pTriAPI->Vertex3fv(theBoxPoint[6]);
+
+ gEngfuncs.pTriAPI->Vertex3fv(theBoxPoint[6]);
+ gEngfuncs.pTriAPI->Vertex3fv(theBoxPoint[7]);
+
+ gEngfuncs.pTriAPI->Vertex3fv(theBoxPoint[7]);
+ gEngfuncs.pTriAPI->Vertex3fv(theBoxPoint[5]);
+
+ gEngfuncs.pTriAPI->Vertex3fv(theBoxPoint[5]);
+ gEngfuncs.pTriAPI->Vertex3fv(theBoxPoint[4]);
+
+ // Sides.
+
+ gEngfuncs.pTriAPI->Vertex3fv(theBoxPoint[0]);
+ gEngfuncs.pTriAPI->Vertex3fv(theBoxPoint[4]);
+
+ gEngfuncs.pTriAPI->Vertex3fv(theBoxPoint[2]);
+ gEngfuncs.pTriAPI->Vertex3fv(theBoxPoint[6]);
+
+ gEngfuncs.pTriAPI->Vertex3fv(theBoxPoint[3]);
+ gEngfuncs.pTriAPI->Vertex3fv(theBoxPoint[7]);
+
+ gEngfuncs.pTriAPI->Vertex3fv(theBoxPoint[1]);
+ gEngfuncs.pTriAPI->Vertex3fv(theBoxPoint[5]);
+
+ gEngfuncs.pTriAPI->End();
+
+}
+
+
+void DrawHitBoxes()
+{
+
+ extern int cam_thirdperson;
+
+ for (int j = 1; j < 512; ++j)
+ {
+
+ cl_entity_t* entity = gEngfuncs.GetEntityByIndex(j);
+
+ if (entity == gEngfuncs.GetLocalPlayer() && !cam_thirdperson)
+ {
+ continue;
+ }
+
+ if (entity->curstate.effects & EF_NODRAW)
+ {
+ continue;
+ }
+
+ if (entity != NULL && entity->model != NULL && entity->model->type == mod_studio)
+ {
+
+ int theEntityIndex = j;
+
+ OBBox theBox[256];
+ int theNumBoxes;
+
+ NS_GetHitBoxesForEntity(theEntityIndex, 256, theBox, theNumBoxes, gEngfuncs.GetClientTime());
+
+ for (int i = 0; i < theNumBoxes; ++i)
+ {
+ DrawHitBox(theBox[i]);
+ }
+
+ }
+
+ }
+
+}
+
+
+
+/*
+
+ =================
+ HUD_DrawTransparentTriangles
+
+ Render any triangles with transparent rendermode needs here
+ =================
+*/
+void CL_DLLEXPORT HUD_DrawTransparentTriangles( void )
+{
+// RecClDrawTransparentTriangles();
+
+ cl_entity_t* thePlayer;
+
+ if (gHUD.GetParticlesVisible() && gHUD.GetSafeForSpriteDrawing())
+ {
+ // get local player
+ thePlayer = gEngfuncs.GetLocalPlayer();
+ if(thePlayer)
+ {
+ //pVector theView(thePlayer->angles.x, thePlayer->angles.y, thePlayer->angles.z);
+ //pVector theView(viewangles[0], viewangles[1], viewangles[2]);
+ //theView.normalize();
+
+ vec3_t angles, up, right, forward;
+ // gEngfuncs.pfnAngleVectors(thePlayer->angles, forward, right, up);
+
+ // This view doesn't take pitch into account. Pitch is stored in x. While yaw goes from -180 to 180,
+ // pitch goes from -10 (looking up) to 10 (looking down). Alter forward[YAW} (forward[0]) so
+ // the particles can billboard themselves correctly.
+
+ // float thePitch = thePlayer->angles[PITCH];
+ // float theNormAngle = thePitch/-10.0f;
+ // int theAngle = theNormAngle*90;
+ // //float theYaw = thePlayer->angles[YAW];
+ //
+ // vec3_t theRotationAngles;
+ // theRotationAngles[0] = theAngle;
+ // theRotationAngles[1] = 0;
+ // theRotationAngles[2] = 0;
+ //
+ // float theMatrix[3][4];
+ // AngleMatrix(theRotationAngles, theMatrix);
+ //
+ // vec3_t theOut;
+ // VectorRotate(forward, theMatrix, theOut);
+ // pVector theRealView(theOut[0], theOut[1], theOut[2]);
+
+ pVector theRealView;
+ gEngfuncs.pfnAngleVectors(v_angles, forward, right, up);
+
+ theRealView.x = forward[0];
+ theRealView.y = forward[1];
+ theRealView.z = forward[2];
+
+ // Disable fog
+ float theFogColor[3];
+ theFogColor[0] = theFogColor[1] = theFogColor[2] = 0.0f;
+ gEngfuncs.pTriAPI->Fog(theFogColor, 0, 0, 0);
+
+ // Draw particles via tri API, without z-buffering, unless we're debugging
+ //if(cl_particleinfo->value == 0)
+ //{
+ AvHParticleSystemManager::Instance()->Draw(theRealView);
+ //}
+
+ //DrawOrdersForPlayers(gHUD.GetDrawPlayerOrders());
+
+ //DrawRangeIndicator();
+
+ //DrawBlips(theRealView);
+
+ //DrawMarineLights(theRealView);
+
+ AvHScriptManager::Instance()->DrawTransparent();
+
+ //DrawDebugEffects();
+
+ //static int theAngle = 0;
+ //DrawCircleOnGroundAtPoint(thePlayer->origin, 6, theAngle++, 100, 1.0f, 1.0f, 1.0f, .2f);
+ }
+
+ // Draw the hitboxes for all of the objects.
+
+ // Assumes that the only time players don't have view models is when they are commanding, gestating, cocooned
+ // or when they aren't playing. See the end of StudioModelRenderer::StudioDrawModel().
+ //if((gHUD.GetRole() == ROLE_COMMANDER) || (gHUD.GetRole() == ROLE_GESTATING) || (gHUD.GetRole() == ROLE_COCOONED) || (gHUD.GetPlayMode() != PLAYMODE_PLAYING))
+ cl_entity_t* theViewEntity = gEngfuncs.GetViewModel();
+ if(!theViewEntity || !theViewEntity->model)
+ {
+ // This should always be rendered with the commander viewpoint
+// vec3_t theCurrentOrigin = v_origin;
+//
+// if(gHUD.GetInTopDownMode())
+// {
+// v_origin = gLastCommanderViewpoint;
+// }
+
+ gHUD.RenderNoZBuffering();
+
+// if(gHUD.GetInTopDownMode())
+// {
+// v_origin = theCurrentOrigin;
+// }
+ }
+
+ gHUD.PostRenderFrame();
+ }
+}
diff --git a/main/source/cl_dll/util.cpp b/main/source/cl_dll/util.cpp
index de340e9f..80b9c7b5 100644
--- a/main/source/cl_dll/util.cpp
+++ b/main/source/cl_dll/util.cpp
@@ -1,314 +1,314 @@
-/***
-*
-* Copyright (c) 1999, Valve LLC. All rights reserved.
-*
-* This product contains software technology licensed from Id
-* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
-* All Rights Reserved.
-*
-* Use, distribution, and modification of this source code and/or resulting
-* object code is restricted to non-commercial enhancements to products from
-* Valve LLC. All other use, distribution, or modification is prohibited
-* without written permission from Valve LLC.
-*
-****/
-//
-// util.cpp
-//
-// implementation of class-less helper functions
-//
-
-#include "stdio.h"
-#include "stdlib.h"
-#include "math.h"
-
-#include "hud.h"
-#include "cl_util.h"
-#include "common/cl_entity.h"
-#include
-#ifndef M_PI
-#define M_PI 3.14159265358979323846 // matches value in gcc v2 math.h
-#endif
-
-#include "pm_shared/pm_defs.h"
-#include "pm_shared/pm_shared.h"
-#include "pm_shared/pm_movevars.h"
-extern playermove_t *pmove;
-
-extern float HUD_GetFOV( void );
-vec3_t vec3_origin( 0, 0, 0 );
-extern vec3_t v_angles;
-//double sqrt(double x);
-//
-//float Length(const float *v)
-//{
-// int i;
-// float length;
-//
-// length = 0;
-// for (i=0 ; i< 3 ; i++)
-// length += v[i]*v[i];
-// length = sqrt (length); // FIXME
-//
-// return length;
-//}
-//
-//void VectorAngles( const float *forward, float *angles )
-//{
-// float tmp, yaw, pitch;
-//
-// if (forward[1] == 0 && forward[0] == 0)
-// {
-// yaw = 0;
-// if (forward[2] > 0)
-// pitch = 90;
-// else
-// pitch = 270;
-// }
-// else
-// {
-// yaw = (atan2(forward[1], forward[0]) * 180 / M_PI);
-// if (yaw < 0)
-// yaw += 360;
-//
-// tmp = sqrt (forward[0]*forward[0] + forward[1]*forward[1]);
-// pitch = (atan2(forward[2], tmp) * 180 / M_PI);
-// if (pitch < 0)
-// pitch += 360;
-// }
-//
-// angles[0] = pitch;
-// angles[1] = yaw;
-// angles[2] = 0;
-//}
-//
-//float VectorNormalize (float *v)
-//{
-// float length, ilength;
-//
-// length = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
-// length = sqrt (length); // FIXME
-//
-// if (length)
-// {
-// ilength = 1/length;
-// v[0] *= ilength;
-// v[1] *= ilength;
-// v[2] *= ilength;
-// }
-//
-// return length;
-//
-//}
-//
-//void VectorInverse ( float *v )
-//{
-// v[0] = -v[0];
-// v[1] = -v[1];
-// v[2] = -v[2];
-//}
-//
-//void VectorScale (const float *in, float scale, float *out)
-//{
-// out[0] = in[0]*scale;
-// out[1] = in[1]*scale;
-// out[2] = in[2]*scale;
-//}
-//
-//void VectorMA (const float *veca, float scale, const float *vecb, float *vecc)
-//{
-// vecc[0] = veca[0] + scale*vecb[0];
-// vecc[1] = veca[1] + scale*vecb[1];
-// vecc[2] = veca[2] + scale*vecb[2];
-//}
-
-int ScreenHeight()
-{
- // CGC: Replace code when ready to fix overview map
- //int theViewport[4];
- //gHUD.GetViewport(theViewport);
- //return theViewport[3];
- return gHUD.m_scrinfo.iHeight;
-}
-
-// ScreenWidth returns the width of the screen, in pixels
-//#define ScreenWidth ( int theViewport[4]; gHUD.GetViewport(theViewport); return theViewport[2]; )
-int ScreenWidth()
-{
- //int theViewport[4];
- //gHUD.GetViewport(theViewport);
- //return theViewport[2];
- return gHUD.m_scrinfo.iWidth;
-}
-
-/*
-HSPRITE SPR_Load(const char* inSpriteName)
-{
- HSPRITE theSpriteHandle = gEngfuncs.pfnSPR_Load(inSpriteName);
-
- // Check for "Can't allocate 128 HUD sprites" crash
- ASSERT(theSpriteHandle < 128);
-
- return theSpriteHandle;
-}*/
-
-//-----------------------------------------------------------------------------
-// Purpose:
-// Given a field of view and mouse/screen positions as well as the current
-// render origin and angles, returns a unit vector through the mouse position
-// that can be used to trace into the world under the mouse click pixel.
-// Input : fov -
-// mousex -
-// mousey -
-// screenwidth -
-// screenheight -
-// vecRenderAngles -
-// c_x -
-// vpn -
-// vup -
-// 360.0 -
-//-----------------------------------------------------------------------------
-void CreatePickingRay( int mousex, int mousey, Vector& outVecPickingRay )
-{
- float dx, dy;
- float c_x, c_y;
- float dist;
- Vector vpn, vup, vright;
-
-// char gDebugMessage[256];
-
- float fovDegrees = gHUD.m_iFOV;
-
- //cl_entity_s* theLocalEntity = gEngfuncs.GetLocalPlayer();
- //Vector vecRenderOrigin = theLocalEntity->origin;
- //Vector vecRenderAngles = theLocalEntity->angles;
- //Vector vecRenderAngles;
- vec3_t vecRenderAngles;
- //gEngfuncs.GetViewAngles((float*)vecRenderAngles);
- VectorCopy(v_angles, vecRenderAngles);
-
- //vec3_t theForward, theRight, theUp;
- //AngleVectors(v_angles, theForward, theRight, theUp);
-
- //ASSERT(v_angles.x == vecRenderAngles.x);
- //ASSERT(v_angles.y == vecRenderAngles.y);
- //ASSERT(v_angles.z == vecRenderAngles.z);
-
- c_x = ScreenWidth() / 2;
- c_y = ScreenHeight() / 2;
-
-
- dx = (float)mousex - c_x;
- // Invert Y
- dy = c_y - (float)mousey;
-
-// sprintf(gDebugMessage, "inMouseX/Y: %d/%d, dx/dy = %d/%d", (int)mousex, (int)mousey, (int)dx, (int)dy);
-// CenterPrint(gDebugMessage);
-
- // Convert view plane distance
- dist = c_x / tan( M_PI * fovDegrees / 360.0 );
-
-
- // Decompose view angles
- AngleVectors( vecRenderAngles, vpn, vright, vup );
-
-
- // Offset forward by view plane distance, and then by pixel offsets
- outVecPickingRay = vpn * dist + vright * ( dx ) + vup * ( dy );
-
- //sprintf(gDebugMessage, "outVecPickingRay: %.0f, %.0f, %.0f", outVecPickingRay.x, outVecPickingRay.y, outVecPickingRay.z);
- //CenterPrint(gDebugMessage);
-
- // Convert to unit vector
- VectorNormalize( outVecPickingRay );
-}
-
-void FillRGBAClipped(vgui::Panel* inPanel, int inStartX, int inStartY, int inWidth, int inHeight, int r, int g, int b, int a)
-{
- int thePanelXPos, thePanelYPos;
- inPanel->getPos(thePanelXPos, thePanelYPos);
-
- int thePanelWidth, thePanelHeight;
- inPanel->getSize(thePanelWidth, thePanelHeight);
-
- // Clip starting point
- inStartX = min(max(0, inStartX), thePanelWidth-1);
- inStartY = min(max(0, inStartY), thePanelHeight-1);
-
- // Clip width if it goes too far
- ASSERT(inWidth >= 0);
- ASSERT(inHeight >= 0);
-
- if(inStartX + inWidth >= thePanelWidth)
- {
- inWidth = max(0, thePanelWidth - inStartX);
- }
- if(inStartY + inHeight >= thePanelHeight)
- {
- inHeight = max(0, thePanelHeight - inStartY);
- }
-
- // Now we can draw
- FillRGBA(inStartX, inStartY, inWidth, inHeight, r, g, b, a);
-
-}
-
-
-HSPRITE LoadSprite(const char *pszName)
-{
- int i;
- char sz[256];
-
- if (ScreenWidth() < 640)
- i = 320;
- else
- i = 640;
-
- sprintf(sz, pszName, i);
-
- return SPR_Load(sz);
-}
-
-bool LocalizeString(const char* inMessage, string& outputString)
-{
- #define kMaxLocalizedStringLength 1024
-
- bool theSuccess = false;
- char theInputString[kMaxLocalizedStringLength];
- char theOutputString[kMaxLocalizedStringLength];
-
- // Don't localize empty strings
- if(strcmp(inMessage, ""))
- {
- if(*inMessage != '#')
- {
- sprintf(theInputString, "#%s", inMessage);
- }
- else
- {
- sprintf(theInputString, "%s", inMessage);
- }
-
- if((CHudTextMessage::LocaliseTextString(theInputString, theOutputString, kMaxLocalizedStringLength) != NULL))
- {
- outputString = theOutputString;
-
- if(theOutputString[0] != '#')
- {
- theSuccess = true;
- }
- else
- {
- string theTempString = theOutputString;
- theTempString = theTempString.substr(1, theTempString.length());
- outputString = theTempString;
- }
- }
- else
- {
- outputString = string("err: ") + theInputString;
- }
- }
-
- return theSuccess;
-}
+/***
+*
+* Copyright (c) 1999, Valve LLC. All rights reserved.
+*
+* This product contains software technology licensed from Id
+* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
+* All Rights Reserved.
+*
+* Use, distribution, and modification of this source code and/or resulting
+* object code is restricted to non-commercial enhancements to products from
+* Valve LLC. All other use, distribution, or modification is prohibited
+* without written permission from Valve LLC.
+*
+****/
+//
+// util.cpp
+//
+// implementation of class-less helper functions
+//
+
+#include "stdio.h"
+#include "stdlib.h"
+#include "math.h"
+
+#include "hud.h"
+#include "cl_util.h"
+#include "common/cl_entity.h"
+#include
+#ifndef M_PI
+#define M_PI 3.14159265358979323846 // matches value in gcc v2 math.h
+#endif
+
+#include "pm_shared/pm_defs.h"
+#include "pm_shared/pm_shared.h"
+#include "pm_shared/pm_movevars.h"
+extern playermove_t *pmove;
+
+extern float HUD_GetFOV( void );
+vec3_t vec3_origin( 0, 0, 0 );
+extern vec3_t v_angles;
+//double sqrt(double x);
+//
+//float Length(const float *v)
+//{
+// int i;
+// float length;
+//
+// length = 0;
+// for (i=0 ; i< 3 ; i++)
+// length += v[i]*v[i];
+// length = sqrt (length); // FIXME
+//
+// return length;
+//}
+//
+//void VectorAngles( const float *forward, float *angles )
+//{
+// float tmp, yaw, pitch;
+//
+// if (forward[1] == 0 && forward[0] == 0)
+// {
+// yaw = 0;
+// if (forward[2] > 0)
+// pitch = 90;
+// else
+// pitch = 270;
+// }
+// else
+// {
+// yaw = (atan2(forward[1], forward[0]) * 180 / M_PI);
+// if (yaw < 0)
+// yaw += 360;
+//
+// tmp = sqrt (forward[0]*forward[0] + forward[1]*forward[1]);
+// pitch = (atan2(forward[2], tmp) * 180 / M_PI);
+// if (pitch < 0)
+// pitch += 360;
+// }
+//
+// angles[0] = pitch;
+// angles[1] = yaw;
+// angles[2] = 0;
+//}
+//
+//float VectorNormalize (float *v)
+//{
+// float length, ilength;
+//
+// length = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
+// length = sqrt (length); // FIXME
+//
+// if (length)
+// {
+// ilength = 1/length;
+// v[0] *= ilength;
+// v[1] *= ilength;
+// v[2] *= ilength;
+// }
+//
+// return length;
+//
+//}
+//
+//void VectorInverse ( float *v )
+//{
+// v[0] = -v[0];
+// v[1] = -v[1];
+// v[2] = -v[2];
+//}
+//
+//void VectorScale (const float *in, float scale, float *out)
+//{
+// out[0] = in[0]*scale;
+// out[1] = in[1]*scale;
+// out[2] = in[2]*scale;
+//}
+//
+//void VectorMA (const float *veca, float scale, const float *vecb, float *vecc)
+//{
+// vecc[0] = veca[0] + scale*vecb[0];
+// vecc[1] = veca[1] + scale*vecb[1];
+// vecc[2] = veca[2] + scale*vecb[2];
+//}
+
+int ScreenHeight()
+{
+ // CGC: Replace code when ready to fix overview map
+ //int theViewport[4];
+ //gHUD.GetViewport(theViewport);
+ //return theViewport[3];
+ return gHUD.m_scrinfo.iHeight;
+}
+
+// ScreenWidth returns the width of the screen, in pixels
+//#define ScreenWidth ( int theViewport[4]; gHUD.GetViewport(theViewport); return theViewport[2]; )
+int ScreenWidth()
+{
+ //int theViewport[4];
+ //gHUD.GetViewport(theViewport);
+ //return theViewport[2];
+ return gHUD.m_scrinfo.iWidth;
+}
+
+/*
+HSPRITE SPR_Load(const char* inSpriteName)
+{
+ HSPRITE theSpriteHandle = gEngfuncs.pfnSPR_Load(inSpriteName);
+
+ // Check for "Can't allocate 128 HUD sprites" crash
+ ASSERT(theSpriteHandle < 128);
+
+ return theSpriteHandle;
+}*/
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Given a field of view and mouse/screen positions as well as the current
+// render origin and angles, returns a unit vector through the mouse position
+// that can be used to trace into the world under the mouse click pixel.
+// Input : fov -
+// mousex -
+// mousey -
+// screenwidth -
+// screenheight -
+// vecRenderAngles -
+// c_x -
+// vpn -
+// vup -
+// 360.0 -
+//-----------------------------------------------------------------------------
+void CreatePickingRay( int mousex, int mousey, Vector& outVecPickingRay )
+{
+ float dx, dy;
+ float c_x, c_y;
+ float dist;
+ Vector vpn, vup, vright;
+
+// char gDebugMessage[256];
+
+ float fovDegrees = gHUD.m_iFOV;
+
+ //cl_entity_s* theLocalEntity = gEngfuncs.GetLocalPlayer();
+ //Vector vecRenderOrigin = theLocalEntity->origin;
+ //Vector vecRenderAngles = theLocalEntity->angles;
+ //Vector vecRenderAngles;
+ vec3_t vecRenderAngles;
+ //gEngfuncs.GetViewAngles((float*)vecRenderAngles);
+ VectorCopy(v_angles, vecRenderAngles);
+
+ //vec3_t theForward, theRight, theUp;
+ //AngleVectors(v_angles, theForward, theRight, theUp);
+
+ //ASSERT(v_angles.x == vecRenderAngles.x);
+ //ASSERT(v_angles.y == vecRenderAngles.y);
+ //ASSERT(v_angles.z == vecRenderAngles.z);
+
+ c_x = ScreenWidth() / 2;
+ c_y = ScreenHeight() / 2;
+
+
+ dx = (float)mousex - c_x;
+ // Invert Y
+ dy = c_y - (float)mousey;
+
+// sprintf(gDebugMessage, "inMouseX/Y: %d/%d, dx/dy = %d/%d", (int)mousex, (int)mousey, (int)dx, (int)dy);
+// CenterPrint(gDebugMessage);
+
+ // Convert view plane distance
+ dist = c_x / tan( M_PI * fovDegrees / 360.0 );
+
+
+ // Decompose view angles
+ AngleVectors( vecRenderAngles, vpn, vright, vup );
+
+
+ // Offset forward by view plane distance, and then by pixel offsets
+ outVecPickingRay = vpn * dist + vright * ( dx ) + vup * ( dy );
+
+ //sprintf(gDebugMessage, "outVecPickingRay: %.0f, %.0f, %.0f", outVecPickingRay.x, outVecPickingRay.y, outVecPickingRay.z);
+ //CenterPrint(gDebugMessage);
+
+ // Convert to unit vector
+ VectorNormalize( outVecPickingRay );
+}
+
+void FillRGBAClipped(vgui::Panel* inPanel, int inStartX, int inStartY, int inWidth, int inHeight, int r, int g, int b, int a)
+{
+ int thePanelXPos, thePanelYPos;
+ inPanel->getPos(thePanelXPos, thePanelYPos);
+
+ int thePanelWidth, thePanelHeight;
+ inPanel->getSize(thePanelWidth, thePanelHeight);
+
+ // Clip starting point
+ inStartX = min(max(0, inStartX), thePanelWidth-1);
+ inStartY = min(max(0, inStartY), thePanelHeight-1);
+
+ // Clip width if it goes too far
+ ASSERT(inWidth >= 0);
+ ASSERT(inHeight >= 0);
+
+ if(inStartX + inWidth >= thePanelWidth)
+ {
+ inWidth = max(0, thePanelWidth - inStartX);
+ }
+ if(inStartY + inHeight >= thePanelHeight)
+ {
+ inHeight = max(0, thePanelHeight - inStartY);
+ }
+
+ // Now we can draw
+ FillRGBA(inStartX, inStartY, inWidth, inHeight, r, g, b, a);
+
+}
+
+
+HSPRITE LoadSprite(const char *pszName)
+{
+ int i;
+ char sz[256];
+
+ if (ScreenWidth() < 640)
+ i = 320;
+ else
+ i = 640;
+
+ sprintf(sz, pszName, i);
+
+ return SPR_Load(sz);
+}
+
+bool LocalizeString(const char* inMessage, string& outputString)
+{
+ #define kMaxLocalizedStringLength 1024
+
+ bool theSuccess = false;
+ char theInputString[kMaxLocalizedStringLength];
+ char theOutputString[kMaxLocalizedStringLength];
+
+ // Don't localize empty strings
+ if(strcmp(inMessage, ""))
+ {
+ if(*inMessage != '#')
+ {
+ sprintf(theInputString, "#%s", inMessage);
+ }
+ else
+ {
+ sprintf(theInputString, "%s", inMessage);
+ }
+
+ if((CHudTextMessage::LocaliseTextString(theInputString, theOutputString, kMaxLocalizedStringLength) != NULL))
+ {
+ outputString = theOutputString;
+
+ if(theOutputString[0] != '#')
+ {
+ theSuccess = true;
+ }
+ else
+ {
+ string theTempString = theOutputString;
+ theTempString = theTempString.substr(1, theTempString.length());
+ outputString = theTempString;
+ }
+ }
+ else
+ {
+ outputString = string("err: ") + theInputString;
+ }
+ }
+
+ return theSuccess;
+}
diff --git a/main/source/cl_dll/util_vector.h b/main/source/cl_dll/util_vector.h
index 4554257c..4d99fe1e 100644
--- a/main/source/cl_dll/util_vector.h
+++ b/main/source/cl_dll/util_vector.h
@@ -1,39 +1,39 @@
-/***
-*
-* Copyright (c) 1999, Valve LLC. All rights reserved.
-*
-* This product contains software technology licensed from Id
-* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
-* All Rights Reserved.
-*
-* Use, distribution, and modification of this source code and/or resulting
-* object code is restricted to non-commercial enhancements to products from
-* Valve LLC. All other use, distribution, or modification is prohibited
-* without written permission from Valve LLC.
-*
-****/
-// Vector.h
-// A subset of the extdll.h in the project HL Entity DLL
-//
-#ifndef UTIL_VECTOR_H
-#define UTIL_VECTOR_H
-
-// Misc C-runtime library headers
-#include "stdio.h"
-#include "stdlib.h"
-#include "math.h"
-
-
-// Header file containing definition of globalvars_t and entvars_t
-typedef unsigned int func_t; //
-typedef unsigned int string_t; // from engine's pr_comp.h;
-typedef float vec_t; // needed before including progdefs.h
-
-#include "vectorclasses.h"
-
-#ifndef THEVECTOR3T
-#define THEVECTOR3T
-#define vec3_t Vector
-#endif
-
-#endif
+/***
+*
+* Copyright (c) 1999, Valve LLC. All rights reserved.
+*
+* This product contains software technology licensed from Id
+* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
+* All Rights Reserved.
+*
+* Use, distribution, and modification of this source code and/or resulting
+* object code is restricted to non-commercial enhancements to products from
+* Valve LLC. All other use, distribution, or modification is prohibited
+* without written permission from Valve LLC.
+*
+****/
+// Vector.h
+// A subset of the extdll.h in the project HL Entity DLL
+//
+#ifndef UTIL_VECTOR_H
+#define UTIL_VECTOR_H
+
+// Misc C-runtime library headers
+#include "stdio.h"
+#include "stdlib.h"
+#include "math.h"
+
+
+// Header file containing definition of globalvars_t and entvars_t
+typedef unsigned int func_t; //
+typedef unsigned int string_t; // from engine's pr_comp.h;
+typedef float vec_t; // needed before including progdefs.h
+
+#include "vectorclasses.h"
+
+#ifndef THEVECTOR3T
+#define THEVECTOR3T
+#define vec3_t Vector
+#endif
+
+#endif
diff --git a/main/source/cl_dll/vgui_ClassMenu.cpp b/main/source/cl_dll/vgui_ClassMenu.cpp
index 9dd29115..42f05967 100644
--- a/main/source/cl_dll/vgui_ClassMenu.cpp
+++ b/main/source/cl_dll/vgui_ClassMenu.cpp
@@ -1,440 +1,440 @@
-//=========== (C) Copyright 1999 Valve, L.L.C. All rights reserved. ===========
-//
-// The copyright to the contents herein is the property of Valve, L.L.C.
-// The contents may be used and/or copied only with the written permission of
-// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
-// the agreement/contract under which the contents have been supplied.
-//
-// Purpose: TFC Class Menu
-//
-// $Workfile: $
-// $Date: 2002/07/08 16:15:13 $
-//
-//-----------------------------------------------------------------------------
-// $Log: vgui_ClassMenu.cpp,v $
-// Revision 1.3 2002/07/08 16:15:13 Flayra
-// - Refactored team color management
-//
-// Revision 1.2 2001/09/13 22:28:00 Charlie
-// - Updated NS with new Half-life 1108 patch in preparation for voice support and spectator mode
-//
-// Revision 1.1.1.1.2.1 2001/09/13 14:42:29 Charlie
-// - HL1108
-//
-//
-// $NoKeywords: $
-//=============================================================================
-
-#include "VGUI_Font.h"
-#include
-
-#include "hud.h"
-#include "cl_util.h"
-#include "camera.h"
-#include "kbutton.h"
-#include "common/cvardef.h"
-#include "common/usercmd.h"
-#include "common/const.h"
-#include "camera.h"
-#include "in_defs.h"
-
-#include "vgui_int.h"
-#include "vgui_TeamFortressViewport.h"
-#include "vgui_ServerBrowser.h"
-
-// Class Menu Dimensions
-#define CLASSMENU_TITLE_X XRES(40)
-#define CLASSMENU_TITLE_Y YRES(32)
-#define CLASSMENU_TOPLEFT_BUTTON_X XRES(40)
-#define CLASSMENU_TOPLEFT_BUTTON_Y YRES(80)
-#define CLASSMENU_BUTTON_SIZE_X XRES(124)
-#define CLASSMENU_BUTTON_SIZE_Y YRES(24)
-#define CLASSMENU_BUTTON_SPACER_Y YRES(8)
-#define CLASSMENU_WINDOW_X XRES(176)
-#define CLASSMENU_WINDOW_Y YRES(80)
-#define CLASSMENU_WINDOW_SIZE_X XRES(424)
-#define CLASSMENU_WINDOW_SIZE_Y YRES(312)
-#define CLASSMENU_WINDOW_TEXT_X XRES(150)
-#define CLASSMENU_WINDOW_TEXT_Y YRES(80)
-#define CLASSMENU_WINDOW_NAME_X XRES(150)
-#define CLASSMENU_WINDOW_NAME_Y YRES(8)
-#define CLASSMENU_WINDOW_PLAYERS_Y YRES(42)
-
-// Creation
-CClassMenuPanel::CClassMenuPanel(int iTrans, int iRemoveMe, int x,int y,int wide,int tall) : CMenuPanel(iTrans, iRemoveMe, x,y,wide,tall)
-{
- // don't show class graphics at below 640x480 resolution
- bool bShowClassGraphic = true;
- if ( ScreenWidth() < 640 )
- {
- bShowClassGraphic = false;
- }
-
- memset( m_pClassImages, 0, sizeof(m_pClassImages) );
-
- // Get the scheme used for the Titles
- CSchemeManager *pSchemes = gViewPort->GetSchemeManager();
-
- // schemes
- SchemeHandle_t hTitleScheme = pSchemes->getSchemeHandle( "Title Font" );
- SchemeHandle_t hClassWindowText = pSchemes->getSchemeHandle( "Briefing Text" );
-
- // color schemes
- int r, g, b, a;
-
- // Create the title
- Label *pLabel = new Label( "", CLASSMENU_TITLE_X, CLASSMENU_TITLE_Y );
- pLabel->setParent( this );
- pLabel->setFont( pSchemes->getFont(hTitleScheme) );
- pSchemes->getFgColor( hTitleScheme, r, g, b, a );
- pLabel->setFgColor( r, g, b, a );
- pSchemes->getBgColor( hTitleScheme, r, g, b, a );
- pLabel->setBgColor( r, g, b, a );
- pLabel->setContentAlignment( vgui::Label::a_west );
- pLabel->setText(gHUD.m_TextMessage.BufferedLocaliseTextString("#Title_SelectYourClass"));
-
- // Create the Scroll panel
- m_pScrollPanel = new CTFScrollPanel( CLASSMENU_WINDOW_X, CLASSMENU_WINDOW_Y, CLASSMENU_WINDOW_SIZE_X, CLASSMENU_WINDOW_SIZE_Y );
- m_pScrollPanel->setParent(this);
- //force the scrollbars on, so after the validate clientClip will be smaller
- m_pScrollPanel->setScrollBarAutoVisible(false, false);
- m_pScrollPanel->setScrollBarVisible(true, true);
- m_pScrollPanel->setBorder( new LineBorder( Color(255 * 0.7,170 * 0.7,0,0) ) );
- m_pScrollPanel->validate();
-
- int clientWide=m_pScrollPanel->getClient()->getWide();
-
- //turn scrollpanel back into auto show scrollbar mode and validate
- m_pScrollPanel->setScrollBarAutoVisible(false,true);
- m_pScrollPanel->setScrollBarVisible(false,false);
- m_pScrollPanel->validate();
-
- // Create the Class buttons
- for (int i = 0; i <= PC_RANDOM; i++)
- {
- char sz[256];
- int iYPos = CLASSMENU_TOPLEFT_BUTTON_Y + ( (CLASSMENU_BUTTON_SIZE_Y + CLASSMENU_BUTTON_SPACER_Y) * i );
-
- ActionSignal *pASignal = new CMenuHandler_StringCommandClassSelect( sTFClassSelection[i], true );
-
- // Class button
- sprintf(sz, "%s", CHudTextMessage::BufferedLocaliseTextString( sLocalisedClasses[i] ) );
- m_pButtons[i] = new ClassButton( i, sz, CLASSMENU_TOPLEFT_BUTTON_X, iYPos, CLASSMENU_BUTTON_SIZE_X, CLASSMENU_BUTTON_SIZE_Y, true);
- // RandomPC uses '0'
- if ( i >= 1 && i <= 9 )
- {
- sprintf(sz,"%d",i);
- }
- else
- {
- sprintf(sz,"0");
- }
- m_pButtons[i]->setBoundKey( sz[0] );
- m_pButtons[i]->setContentAlignment( vgui::Label::a_west );
- m_pButtons[i]->addActionSignal( pASignal );
- m_pButtons[i]->addInputSignal( new CHandler_MenuButtonOver(this, i) );
- m_pButtons[i]->setParent( this );
-
- // Create the Class Info Window
- //m_pClassInfoPanel[i] = new CTransparentPanel( 255, CLASSMENU_WINDOW_X, CLASSMENU_WINDOW_Y, CLASSMENU_WINDOW_SIZE_X, CLASSMENU_WINDOW_SIZE_Y );
- m_pClassInfoPanel[i] = new CTransparentPanel( 255, 0, 0, clientWide, CLASSMENU_WINDOW_SIZE_Y );
- m_pClassInfoPanel[i]->setParent( m_pScrollPanel->getClient() );
- //m_pClassInfoPanel[i]->setVisible( false );
-
- // don't show class pic in lower resolutions
- int textOffs = XRES(8);
-
- if ( bShowClassGraphic )
- {
- textOffs = CLASSMENU_WINDOW_NAME_X;
- }
-
- // Create the Class Name Label
- sprintf(sz, "#Title_%s", sTFClassSelection[i]);
- char* localName=CHudTextMessage::BufferedLocaliseTextString( sz );
- Label *pNameLabel = new Label( "", textOffs, CLASSMENU_WINDOW_NAME_Y );
- pNameLabel->setFont( pSchemes->getFont(hTitleScheme) );
- pNameLabel->setParent( m_pClassInfoPanel[i] );
- pSchemes->getFgColor( hTitleScheme, r, g, b, a );
- pNameLabel->setFgColor( r, g, b, a );
- pSchemes->getBgColor( hTitleScheme, r, g, b, a );
- pNameLabel->setBgColor( r, g, b, a );
- pNameLabel->setContentAlignment( vgui::Label::a_west );
- //pNameLabel->setBorder(new LineBorder());
- pNameLabel->setText(localName);
-
- // Create the Class Image
- if ( bShowClassGraphic )
- {
- for ( int team = 0; team < 2; team++ )
- {
- if ( team == 1 )
- {
- sprintf( sz, "%sred", sTFClassSelection[i] );
- }
- else
- {
- sprintf( sz, "%sblue", sTFClassSelection[i] );
- }
-
- m_pClassImages[team][i] = new CImageLabel( sz, 0, 0, CLASSMENU_WINDOW_TEXT_X, CLASSMENU_WINDOW_TEXT_Y );
-
- CImageLabel *pLabel = m_pClassImages[team][i];
- pLabel->setParent( m_pClassInfoPanel[i] );
- //pLabel->setBorder(new LineBorder());
-
- if ( team != 1 )
- {
- pLabel->setVisible( false );
- }
-
- // Reposition it based upon it's size
- int xOut, yOut;
- pNameLabel->getTextSize( xOut, yOut );
- pLabel->setPos( (CLASSMENU_WINDOW_TEXT_X - pLabel->getWide()) / 2, yOut /2 );
- }
- }
-
- // Create the Player count string
- gHUD.m_TextMessage.LocaliseTextString( "#Title_CurrentlyOnYourTeam", m_sPlayersOnTeamString, STRLENMAX_PLAYERSONTEAM );
- m_pPlayers[i] = new Label( "", textOffs, CLASSMENU_WINDOW_PLAYERS_Y );
- m_pPlayers[i]->setParent( m_pClassInfoPanel[i] );
- m_pPlayers[i]->setBgColor( 0, 0, 0, 255 );
- m_pPlayers[i]->setContentAlignment( vgui::Label::a_west );
- m_pPlayers[i]->setFont( pSchemes->getFont(hClassWindowText) );
-
- // Open up the Class Briefing File
- sprintf(sz, "classes/short_%s.txt", sTFClassSelection[i]);
- char *cText = "Class Description not available.";
- char *pfile = (char *)gEngfuncs.COM_LoadFile( sz, 5, NULL );
- if (pfile)
- {
- cText = pfile;
- }
-
- // Create the Text info window
- TextPanel *pTextWindow = new TextPanel(cText, textOffs, CLASSMENU_WINDOW_TEXT_Y, (CLASSMENU_WINDOW_SIZE_X - textOffs)-5, CLASSMENU_WINDOW_SIZE_Y - CLASSMENU_WINDOW_TEXT_Y);
- pTextWindow->setParent( m_pClassInfoPanel[i] );
- pTextWindow->setFont( pSchemes->getFont(hClassWindowText) );
- pSchemes->getFgColor( hClassWindowText, r, g, b, a );
- pTextWindow->setFgColor( r, g, b, a );
- pSchemes->getBgColor( hClassWindowText, r, g, b, a );
- pTextWindow->setBgColor( r, g, b, a );
-
- // Resize the Info panel to fit it all
- int wide,tall;
- pTextWindow->getTextImage()->getTextSizeWrapped( wide,tall);
- pTextWindow->setSize(wide,tall);
-
- int xx,yy;
- pTextWindow->getPos(xx,yy);
- int maxX=xx+wide;
- int maxY=yy+tall;
-
- //check to see if the image goes lower than the text
- //just use the red teams [0] images
- if(m_pClassImages[0][i]!=null)
- {
- m_pClassImages[0][i]->getPos(xx,yy);
- if((yy+m_pClassImages[0][i]->getTall())>maxY)
- {
- maxY=yy+m_pClassImages[0][i]->getTall();
- }
- }
-
- m_pClassInfoPanel[i]->setSize( maxX , maxY );
- if (pfile) gEngfuncs.COM_FreeFile( pfile );
- //m_pClassInfoPanel[i]->setBorder(new LineBorder());
-
- }
-
- // Create the Cancel button
- m_pCancelButton = new CommandButton( gHUD.m_TextMessage.BufferedLocaliseTextString( "#Menu_Cancel" ), CLASSMENU_TOPLEFT_BUTTON_X, 0, CLASSMENU_BUTTON_SIZE_X, CLASSMENU_BUTTON_SIZE_Y);
- m_pCancelButton->setParent( this );
- m_pCancelButton->addActionSignal( new CMenuHandler_TextWindow(HIDE_TEXTWINDOW) );
-
- m_iCurrentInfo = 0;
-
-}
-
-
-// Update
-void CClassMenuPanel::Update()
-{
- // Don't allow the player to join a team if they're not in a team
- if (!g_iTeamNumber)
- return;
-
- int iYPos = CLASSMENU_TOPLEFT_BUTTON_Y;
-
- // Cycle through the rest of the buttons
- for (int i = 0; i <= PC_RANDOM; i++)
- {
- bool bCivilian = (gViewPort->GetValidClasses(g_iTeamNumber) == -1);
-
- if ( bCivilian )
- {
- // If this team can only be civilians, only the civilian button's visible
- if (i == 0)
- {
- m_pButtons[0]->setVisible( true );
- SetActiveInfo( 0 );
- iYPos += CLASSMENU_BUTTON_SIZE_Y + CLASSMENU_BUTTON_SPACER_Y;
- }
- else
- {
- m_pButtons[i]->setVisible( false );
- }
- }
- else
- {
- if ( m_pButtons[i]->IsNotValid() || i == 0 )
- {
- m_pButtons[i]->setVisible( false );
- }
- else
- {
- m_pButtons[i]->setVisible( true );
- m_pButtons[i]->setPos( CLASSMENU_TOPLEFT_BUTTON_X, iYPos );
- iYPos += CLASSMENU_BUTTON_SIZE_Y + CLASSMENU_BUTTON_SPACER_Y;
-
- // Start with the first option up
- if (!m_iCurrentInfo)
- SetActiveInfo( i );
- }
- }
-
- // Now count the number of teammembers of this class
- int iTotal = 0;
- for ( int j = 1; j <= MAX_PLAYERS; j++ )
- {
- if ( g_PlayerInfoList[j].name == NULL )
- continue; // empty player slot, skip
- if ( g_PlayerExtraInfo[j].teamname[0] == 0 )
- continue; // skip over players who are not in a team
- if ( g_PlayerInfoList[j].thisplayer )
- continue; // skip this player
- if ( g_PlayerExtraInfo[j].teamnumber != g_iTeamNumber )
- continue; // skip over players in other teams
-
- // If this team is forced to be civilians, just count the number of teammates
- if ( g_PlayerExtraInfo[j].playerclass != i && !bCivilian )
- continue;
-
- iTotal++;
- }
-
- char sz[256];
- sprintf(sz, m_sPlayersOnTeamString, iTotal);
- m_pPlayers[i]->setText( sz );
-
- // Set the text color to the teamcolor
- m_pPlayers[i]->setFgColor( kTeamColors[g_iTeamNumber % iNumberOfTeamColors][0],
- kTeamColors[g_iTeamNumber % iNumberOfTeamColors][1],
- kTeamColors[g_iTeamNumber % iNumberOfTeamColors][2],
- 0 );
-
- // set the graphic to be the team pick
- for ( int team = 0; team < MAX_TEAMS; team++ )
- {
- // unset all the other images
- if ( m_pClassImages[team][i] )
- {
- m_pClassImages[team][i]->setVisible( false );
- }
-
- // set the current team image
- if ( m_pClassImages[g_iTeamNumber-1][i] != NULL )
- {
- m_pClassImages[g_iTeamNumber-1][i]->setVisible( true );
- }
- else if ( m_pClassImages[0][i] )
- {
- m_pClassImages[0][i]->setVisible( true );
- }
- }
- }
-
- // If the player already has a class, make the cancel button visible
- if ( g_iPlayerClass )
- {
- m_pCancelButton->setPos( CLASSMENU_TOPLEFT_BUTTON_X, iYPos );
- m_pCancelButton->setVisible( true );
- }
- else
- {
- m_pCancelButton->setVisible( false );
- }
-}
-
-//======================================
-// Key inputs for the Class Menu
-bool CClassMenuPanel::SlotInput( int iSlot )
-{
- if ( (iSlot < 0) || (iSlot > 9) )
- return false;
- if ( !m_pButtons[ iSlot ] )
- return false;
-
- // Is the button pushable? (0 is special case)
- if (iSlot == 0)
- {
- // Selects Civilian and RandomPC
- if ( gViewPort->GetValidClasses(g_iTeamNumber) == -1 )
- {
- m_pButtons[ 0 ]->fireActionSignal();
- return true;
- }
-
- // Select RandomPC
- iSlot = 10;
- }
-
- if ( !(m_pButtons[ iSlot ]->IsNotValid()) )
- {
- m_pButtons[ iSlot ]->fireActionSignal();
- return true;
- }
-
- return false;
-}
-
-//======================================
-// Update the Class menu before opening it
-void CClassMenuPanel::Open( void )
-{
- Update();
- CMenuPanel::Open();
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Called each time a new level is started.
-//-----------------------------------------------------------------------------
-void CClassMenuPanel::Initialize( void )
-{
- setVisible( false );
- m_pScrollPanel->setScrollValue( 0, 0 );
-}
-
-//======================================
-// Mouse is over a class button, bring up the class info
-void CClassMenuPanel::SetActiveInfo( int iInput )
-{
- // Remove all the Info panels and bring up the specified one
- for (int i = 0; i <= PC_RANDOM; i++)
- {
- m_pButtons[i]->setArmed( false );
- m_pClassInfoPanel[i]->setVisible( false );
- }
-
- if ( iInput > PC_RANDOM || iInput < 0 )
- iInput = 0;
-
- m_pButtons[iInput]->setArmed( true );
- m_pClassInfoPanel[iInput]->setVisible( true );
- m_iCurrentInfo = iInput;
-
- m_pScrollPanel->setScrollValue(0,0);
- m_pScrollPanel->validate();
-}
-
+//=========== (C) Copyright 1999 Valve, L.L.C. All rights reserved. ===========
+//
+// The copyright to the contents herein is the property of Valve, L.L.C.
+// The contents may be used and/or copied only with the written permission of
+// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
+// the agreement/contract under which the contents have been supplied.
+//
+// Purpose: TFC Class Menu
+//
+// $Workfile: $
+// $Date: 2002/07/08 16:15:13 $
+//
+//-----------------------------------------------------------------------------
+// $Log: vgui_ClassMenu.cpp,v $
+// Revision 1.3 2002/07/08 16:15:13 Flayra
+// - Refactored team color management
+//
+// Revision 1.2 2001/09/13 22:28:00 Charlie
+// - Updated NS with new Half-life 1108 patch in preparation for voice support and spectator mode
+//
+// Revision 1.1.1.1.2.1 2001/09/13 14:42:29 Charlie
+// - HL1108
+//
+//
+// $NoKeywords: $
+//=============================================================================
+
+#include "VGUI_Font.h"
+#include
+
+#include "hud.h"
+#include "cl_util.h"
+#include "camera.h"
+#include "kbutton.h"
+#include "common/cvardef.h"
+#include "common/usercmd.h"
+#include "common/const.h"
+#include "camera.h"
+#include "in_defs.h"
+
+#include "vgui_int.h"
+#include "vgui_TeamFortressViewport.h"
+#include "vgui_ServerBrowser.h"
+
+// Class Menu Dimensions
+#define CLASSMENU_TITLE_X XRES(40)
+#define CLASSMENU_TITLE_Y YRES(32)
+#define CLASSMENU_TOPLEFT_BUTTON_X XRES(40)
+#define CLASSMENU_TOPLEFT_BUTTON_Y YRES(80)
+#define CLASSMENU_BUTTON_SIZE_X XRES(124)
+#define CLASSMENU_BUTTON_SIZE_Y YRES(24)
+#define CLASSMENU_BUTTON_SPACER_Y YRES(8)
+#define CLASSMENU_WINDOW_X XRES(176)
+#define CLASSMENU_WINDOW_Y YRES(80)
+#define CLASSMENU_WINDOW_SIZE_X XRES(424)
+#define CLASSMENU_WINDOW_SIZE_Y YRES(312)
+#define CLASSMENU_WINDOW_TEXT_X XRES(150)
+#define CLASSMENU_WINDOW_TEXT_Y YRES(80)
+#define CLASSMENU_WINDOW_NAME_X XRES(150)
+#define CLASSMENU_WINDOW_NAME_Y YRES(8)
+#define CLASSMENU_WINDOW_PLAYERS_Y YRES(42)
+
+// Creation
+CClassMenuPanel::CClassMenuPanel(int iTrans, int iRemoveMe, int x,int y,int wide,int tall) : CMenuPanel(iTrans, iRemoveMe, x,y,wide,tall)
+{
+ // don't show class graphics at below 640x480 resolution
+ bool bShowClassGraphic = true;
+ if ( ScreenWidth() < 640 )
+ {
+ bShowClassGraphic = false;
+ }
+
+ memset( m_pClassImages, 0, sizeof(m_pClassImages) );
+
+ // Get the scheme used for the Titles
+ CSchemeManager *pSchemes = gViewPort->GetSchemeManager();
+
+ // schemes
+ SchemeHandle_t hTitleScheme = pSchemes->getSchemeHandle( "Title Font" );
+ SchemeHandle_t hClassWindowText = pSchemes->getSchemeHandle( "Briefing Text" );
+
+ // color schemes
+ int r, g, b, a;
+
+ // Create the title
+ Label *pLabel = new Label( "", CLASSMENU_TITLE_X, CLASSMENU_TITLE_Y );
+ pLabel->setParent( this );
+ pLabel->setFont( pSchemes->getFont(hTitleScheme) );
+ pSchemes->getFgColor( hTitleScheme, r, g, b, a );
+ pLabel->setFgColor( r, g, b, a );
+ pSchemes->getBgColor( hTitleScheme, r, g, b, a );
+ pLabel->setBgColor( r, g, b, a );
+ pLabel->setContentAlignment( vgui::Label::a_west );
+ pLabel->setText(gHUD.m_TextMessage.BufferedLocaliseTextString("#Title_SelectYourClass"));
+
+ // Create the Scroll panel
+ m_pScrollPanel = new CTFScrollPanel( CLASSMENU_WINDOW_X, CLASSMENU_WINDOW_Y, CLASSMENU_WINDOW_SIZE_X, CLASSMENU_WINDOW_SIZE_Y );
+ m_pScrollPanel->setParent(this);
+ //force the scrollbars on, so after the validate clientClip will be smaller
+ m_pScrollPanel->setScrollBarAutoVisible(false, false);
+ m_pScrollPanel->setScrollBarVisible(true, true);
+ m_pScrollPanel->setBorder( new LineBorder( Color(255 * 0.7,170 * 0.7,0,0) ) );
+ m_pScrollPanel->validate();
+
+ int clientWide=m_pScrollPanel->getClient()->getWide();
+
+ //turn scrollpanel back into auto show scrollbar mode and validate
+ m_pScrollPanel->setScrollBarAutoVisible(false,true);
+ m_pScrollPanel->setScrollBarVisible(false,false);
+ m_pScrollPanel->validate();
+
+ // Create the Class buttons
+ for (int i = 0; i <= PC_RANDOM; i++)
+ {
+ char sz[256];
+ int iYPos = CLASSMENU_TOPLEFT_BUTTON_Y + ( (CLASSMENU_BUTTON_SIZE_Y + CLASSMENU_BUTTON_SPACER_Y) * i );
+
+ ActionSignal *pASignal = new CMenuHandler_StringCommandClassSelect( sTFClassSelection[i], true );
+
+ // Class button
+ sprintf(sz, "%s", CHudTextMessage::BufferedLocaliseTextString( sLocalisedClasses[i] ) );
+ m_pButtons[i] = new ClassButton( i, sz, CLASSMENU_TOPLEFT_BUTTON_X, iYPos, CLASSMENU_BUTTON_SIZE_X, CLASSMENU_BUTTON_SIZE_Y, true);
+ // RandomPC uses '0'
+ if ( i >= 1 && i <= 9 )
+ {
+ sprintf(sz,"%d",i);
+ }
+ else
+ {
+ sprintf(sz,"0");
+ }
+ m_pButtons[i]->setBoundKey( sz[0] );
+ m_pButtons[i]->setContentAlignment( vgui::Label::a_west );
+ m_pButtons[i]->addActionSignal( pASignal );
+ m_pButtons[i]->addInputSignal( new CHandler_MenuButtonOver(this, i) );
+ m_pButtons[i]->setParent( this );
+
+ // Create the Class Info Window
+ //m_pClassInfoPanel[i] = new CTransparentPanel( 255, CLASSMENU_WINDOW_X, CLASSMENU_WINDOW_Y, CLASSMENU_WINDOW_SIZE_X, CLASSMENU_WINDOW_SIZE_Y );
+ m_pClassInfoPanel[i] = new CTransparentPanel( 255, 0, 0, clientWide, CLASSMENU_WINDOW_SIZE_Y );
+ m_pClassInfoPanel[i]->setParent( m_pScrollPanel->getClient() );
+ //m_pClassInfoPanel[i]->setVisible( false );
+
+ // don't show class pic in lower resolutions
+ int textOffs = XRES(8);
+
+ if ( bShowClassGraphic )
+ {
+ textOffs = CLASSMENU_WINDOW_NAME_X;
+ }
+
+ // Create the Class Name Label
+ sprintf(sz, "#Title_%s", sTFClassSelection[i]);
+ char* localName=CHudTextMessage::BufferedLocaliseTextString( sz );
+ Label *pNameLabel = new Label( "", textOffs, CLASSMENU_WINDOW_NAME_Y );
+ pNameLabel->setFont( pSchemes->getFont(hTitleScheme) );
+ pNameLabel->setParent( m_pClassInfoPanel[i] );
+ pSchemes->getFgColor( hTitleScheme, r, g, b, a );
+ pNameLabel->setFgColor( r, g, b, a );
+ pSchemes->getBgColor( hTitleScheme, r, g, b, a );
+ pNameLabel->setBgColor( r, g, b, a );
+ pNameLabel->setContentAlignment( vgui::Label::a_west );
+ //pNameLabel->setBorder(new LineBorder());
+ pNameLabel->setText(localName);
+
+ // Create the Class Image
+ if ( bShowClassGraphic )
+ {
+ for ( int team = 0; team < 2; team++ )
+ {
+ if ( team == 1 )
+ {
+ sprintf( sz, "%sred", sTFClassSelection[i] );
+ }
+ else
+ {
+ sprintf( sz, "%sblue", sTFClassSelection[i] );
+ }
+
+ m_pClassImages[team][i] = new CImageLabel( sz, 0, 0, CLASSMENU_WINDOW_TEXT_X, CLASSMENU_WINDOW_TEXT_Y );
+
+ CImageLabel *pLabel = m_pClassImages[team][i];
+ pLabel->setParent( m_pClassInfoPanel[i] );
+ //pLabel->setBorder(new LineBorder());
+
+ if ( team != 1 )
+ {
+ pLabel->setVisible( false );
+ }
+
+ // Reposition it based upon it's size
+ int xOut, yOut;
+ pNameLabel->getTextSize( xOut, yOut );
+ pLabel->setPos( (CLASSMENU_WINDOW_TEXT_X - pLabel->getWide()) / 2, yOut /2 );
+ }
+ }
+
+ // Create the Player count string
+ gHUD.m_TextMessage.LocaliseTextString( "#Title_CurrentlyOnYourTeam", m_sPlayersOnTeamString, STRLENMAX_PLAYERSONTEAM );
+ m_pPlayers[i] = new Label( "", textOffs, CLASSMENU_WINDOW_PLAYERS_Y );
+ m_pPlayers[i]->setParent( m_pClassInfoPanel[i] );
+ m_pPlayers[i]->setBgColor( 0, 0, 0, 255 );
+ m_pPlayers[i]->setContentAlignment( vgui::Label::a_west );
+ m_pPlayers[i]->setFont( pSchemes->getFont(hClassWindowText) );
+
+ // Open up the Class Briefing File
+ sprintf(sz, "classes/short_%s.txt", sTFClassSelection[i]);
+ char *cText = "Class Description not available.";
+ char *pfile = (char *)gEngfuncs.COM_LoadFile( sz, 5, NULL );
+ if (pfile)
+ {
+ cText = pfile;
+ }
+
+ // Create the Text info window
+ TextPanel *pTextWindow = new TextPanel(cText, textOffs, CLASSMENU_WINDOW_TEXT_Y, (CLASSMENU_WINDOW_SIZE_X - textOffs)-5, CLASSMENU_WINDOW_SIZE_Y - CLASSMENU_WINDOW_TEXT_Y);
+ pTextWindow->setParent( m_pClassInfoPanel[i] );
+ pTextWindow->setFont( pSchemes->getFont(hClassWindowText) );
+ pSchemes->getFgColor( hClassWindowText, r, g, b, a );
+ pTextWindow->setFgColor( r, g, b, a );
+ pSchemes->getBgColor( hClassWindowText, r, g, b, a );
+ pTextWindow->setBgColor( r, g, b, a );
+
+ // Resize the Info panel to fit it all
+ int wide,tall;
+ pTextWindow->getTextImage()->getTextSizeWrapped( wide,tall);
+ pTextWindow->setSize(wide,tall);
+
+ int xx,yy;
+ pTextWindow->getPos(xx,yy);
+ int maxX=xx+wide;
+ int maxY=yy+tall;
+
+ //check to see if the image goes lower than the text
+ //just use the red teams [0] images
+ if(m_pClassImages[0][i]!=null)
+ {
+ m_pClassImages[0][i]->getPos(xx,yy);
+ if((yy+m_pClassImages[0][i]->getTall())>maxY)
+ {
+ maxY=yy+m_pClassImages[0][i]->getTall();
+ }
+ }
+
+ m_pClassInfoPanel[i]->setSize( maxX , maxY );
+ if (pfile) gEngfuncs.COM_FreeFile( pfile );
+ //m_pClassInfoPanel[i]->setBorder(new LineBorder());
+
+ }
+
+ // Create the Cancel button
+ m_pCancelButton = new CommandButton( gHUD.m_TextMessage.BufferedLocaliseTextString( "#Menu_Cancel" ), CLASSMENU_TOPLEFT_BUTTON_X, 0, CLASSMENU_BUTTON_SIZE_X, CLASSMENU_BUTTON_SIZE_Y);
+ m_pCancelButton->setParent( this );
+ m_pCancelButton->addActionSignal( new CMenuHandler_TextWindow(HIDE_TEXTWINDOW) );
+
+ m_iCurrentInfo = 0;
+
+}
+
+
+// Update
+void CClassMenuPanel::Update()
+{
+ // Don't allow the player to join a team if they're not in a team
+ if (!g_iTeamNumber)
+ return;
+
+ int iYPos = CLASSMENU_TOPLEFT_BUTTON_Y;
+
+ // Cycle through the rest of the buttons
+ for (int i = 0; i <= PC_RANDOM; i++)
+ {
+ bool bCivilian = (gViewPort->GetValidClasses(g_iTeamNumber) == -1);
+
+ if ( bCivilian )
+ {
+ // If this team can only be civilians, only the civilian button's visible
+ if (i == 0)
+ {
+ m_pButtons[0]->setVisible( true );
+ SetActiveInfo( 0 );
+ iYPos += CLASSMENU_BUTTON_SIZE_Y + CLASSMENU_BUTTON_SPACER_Y;
+ }
+ else
+ {
+ m_pButtons[i]->setVisible( false );
+ }
+ }
+ else
+ {
+ if ( m_pButtons[i]->IsNotValid() || i == 0 )
+ {
+ m_pButtons[i]->setVisible( false );
+ }
+ else
+ {
+ m_pButtons[i]->setVisible( true );
+ m_pButtons[i]->setPos( CLASSMENU_TOPLEFT_BUTTON_X, iYPos );
+ iYPos += CLASSMENU_BUTTON_SIZE_Y + CLASSMENU_BUTTON_SPACER_Y;
+
+ // Start with the first option up
+ if (!m_iCurrentInfo)
+ SetActiveInfo( i );
+ }
+ }
+
+ // Now count the number of teammembers of this class
+ int iTotal = 0;
+ for ( int j = 1; j <= MAX_PLAYERS; j++ )
+ {
+ if ( g_PlayerInfoList[j].name == NULL )
+ continue; // empty player slot, skip
+ if ( g_PlayerExtraInfo[j].teamname[0] == 0 )
+ continue; // skip over players who are not in a team
+ if ( g_PlayerInfoList[j].thisplayer )
+ continue; // skip this player
+ if ( g_PlayerExtraInfo[j].teamnumber != g_iTeamNumber )
+ continue; // skip over players in other teams
+
+ // If this team is forced to be civilians, just count the number of teammates
+ if ( g_PlayerExtraInfo[j].playerclass != i && !bCivilian )
+ continue;
+
+ iTotal++;
+ }
+
+ char sz[256];
+ sprintf(sz, m_sPlayersOnTeamString, iTotal);
+ m_pPlayers[i]->setText( sz );
+
+ // Set the text color to the teamcolor
+ m_pPlayers[i]->setFgColor( kTeamColors[g_iTeamNumber % iNumberOfTeamColors][0],
+ kTeamColors[g_iTeamNumber % iNumberOfTeamColors][1],
+ kTeamColors[g_iTeamNumber % iNumberOfTeamColors][2],
+ 0 );
+
+ // set the graphic to be the team pick
+ for ( int team = 0; team < MAX_TEAMS; team++ )
+ {
+ // unset all the other images
+ if ( m_pClassImages[team][i] )
+ {
+ m_pClassImages[team][i]->setVisible( false );
+ }
+
+ // set the current team image
+ if ( m_pClassImages[g_iTeamNumber-1][i] != NULL )
+ {
+ m_pClassImages[g_iTeamNumber-1][i]->setVisible( true );
+ }
+ else if ( m_pClassImages[0][i] )
+ {
+ m_pClassImages[0][i]->setVisible( true );
+ }
+ }
+ }
+
+ // If the player already has a class, make the cancel button visible
+ if ( g_iPlayerClass )
+ {
+ m_pCancelButton->setPos( CLASSMENU_TOPLEFT_BUTTON_X, iYPos );
+ m_pCancelButton->setVisible( true );
+ }
+ else
+ {
+ m_pCancelButton->setVisible( false );
+ }
+}
+
+//======================================
+// Key inputs for the Class Menu
+bool CClassMenuPanel::SlotInput( int iSlot )
+{
+ if ( (iSlot < 0) || (iSlot > 9) )
+ return false;
+ if ( !m_pButtons[ iSlot ] )
+ return false;
+
+ // Is the button pushable? (0 is special case)
+ if (iSlot == 0)
+ {
+ // Selects Civilian and RandomPC
+ if ( gViewPort->GetValidClasses(g_iTeamNumber) == -1 )
+ {
+ m_pButtons[ 0 ]->fireActionSignal();
+ return true;
+ }
+
+ // Select RandomPC
+ iSlot = 10;
+ }
+
+ if ( !(m_pButtons[ iSlot ]->IsNotValid()) )
+ {
+ m_pButtons[ iSlot ]->fireActionSignal();
+ return true;
+ }
+
+ return false;
+}
+
+//======================================
+// Update the Class menu before opening it
+void CClassMenuPanel::Open( void )
+{
+ Update();
+ CMenuPanel::Open();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Called each time a new level is started.
+//-----------------------------------------------------------------------------
+void CClassMenuPanel::Initialize( void )
+{
+ setVisible( false );
+ m_pScrollPanel->setScrollValue( 0, 0 );
+}
+
+//======================================
+// Mouse is over a class button, bring up the class info
+void CClassMenuPanel::SetActiveInfo( int iInput )
+{
+ // Remove all the Info panels and bring up the specified one
+ for (int i = 0; i <= PC_RANDOM; i++)
+ {
+ m_pButtons[i]->setArmed( false );
+ m_pClassInfoPanel[i]->setVisible( false );
+ }
+
+ if ( iInput > PC_RANDOM || iInput < 0 )
+ iInput = 0;
+
+ m_pButtons[iInput]->setArmed( true );
+ m_pClassInfoPanel[iInput]->setVisible( true );
+ m_iCurrentInfo = iInput;
+
+ m_pScrollPanel->setScrollValue(0,0);
+ m_pScrollPanel->validate();
+}
+
diff --git a/main/source/cl_dll/vgui_ConsolePanel.cpp b/main/source/cl_dll/vgui_ConsolePanel.cpp
index bb8f9cff..172ec1fa 100644
--- a/main/source/cl_dll/vgui_ConsolePanel.cpp
+++ b/main/source/cl_dll/vgui_ConsolePanel.cpp
@@ -1,95 +1,95 @@
-
-#include"vgui_ConsolePanel.h"
-#include"hud.h"
-#include
-#include
-#include
-#include
-#include
-
-using namespace vgui;
-
-
-namespace
-{
-
-class Handler : public ActionSignal
-{
-private:
-
- ConsolePanel* _consolePanel;
-
-public:
-
- Handler(ConsolePanel* consolePanel)
- {
- _consolePanel=consolePanel;
- }
-
-public:
-
- virtual void actionPerformed(Panel* panel)
- {
- _consolePanel->doExecCommand();
- }
-
-};
-
-}
-
-
-
-ConsolePanel::ConsolePanel(int x,int y,int wide,int tall) : Panel(x,y,wide,tall)
-{
- setBorder(new EtchedBorder());
-
- _textGrid=new TextGrid(80,21,5,5,200,100);
- _textGrid->setBorder(new LoweredBorder());
- _textGrid->setParent(this);
-
- _textEntry=new TextEntry("",5,5,200,20);
- _textEntry->setParent(this);
- _textEntry->addActionSignal(new Handler(this));
-}
-
-int ConsolePanel::print(const char* text)
-{
- return _textGrid->printf("%s",text);
-}
-
-int ConsolePanel::vprintf(const char* format,va_list argList)
-{
- return _textGrid->vprintf(format,argList);
-}
-
-int ConsolePanel::printf(const char* format,...)
-{
- va_list argList;
- va_start(argList,format);
- int ret=vprintf(format,argList);
- va_end(argList);
- return ret;
-}
-
-void ConsolePanel::doExecCommand()
-{
- char buf[2048];
- _textEntry->getText(0,buf,2048);
- _textEntry->setText(null,0);
- gEngfuncs.pfnClientCmd(buf);
-}
-
-void ConsolePanel::setSize(int wide,int tall)
-{
- Panel::setSize(wide,tall);
-
- getPaintSize(wide,tall);
-
- _textGrid->setBounds(5,5,wide-10,tall-35);
- _textEntry->setBounds(5,tall-25,wide-10,20);
-}
-
-
-
-
-
+
+#include"vgui_ConsolePanel.h"
+#include"hud.h"
+#include
+#include
+#include
+#include
+#include
+
+using namespace vgui;
+
+
+namespace
+{
+
+class Handler : public ActionSignal
+{
+private:
+
+ ConsolePanel* _consolePanel;
+
+public:
+
+ Handler(ConsolePanel* consolePanel)
+ {
+ _consolePanel=consolePanel;
+ }
+
+public:
+
+ virtual void actionPerformed(Panel* panel)
+ {
+ _consolePanel->doExecCommand();
+ }
+
+};
+
+}
+
+
+
+ConsolePanel::ConsolePanel(int x,int y,int wide,int tall) : Panel(x,y,wide,tall)
+{
+ setBorder(new EtchedBorder());
+
+ _textGrid=new TextGrid(80,21,5,5,200,100);
+ _textGrid->setBorder(new LoweredBorder());
+ _textGrid->setParent(this);
+
+ _textEntry=new TextEntry("",5,5,200,20);
+ _textEntry->setParent(this);
+ _textEntry->addActionSignal(new Handler(this));
+}
+
+int ConsolePanel::print(const char* text)
+{
+ return _textGrid->printf("%s",text);
+}
+
+int ConsolePanel::vprintf(const char* format,va_list argList)
+{
+ return _textGrid->vprintf(format,argList);
+}
+
+int ConsolePanel::printf(const char* format,...)
+{
+ va_list argList;
+ va_start(argList,format);
+ int ret=vprintf(format,argList);
+ va_end(argList);
+ return ret;
+}
+
+void ConsolePanel::doExecCommand()
+{
+ char buf[2048];
+ _textEntry->getText(0,buf,2048);
+ _textEntry->setText(null,0);
+ gEngfuncs.pfnClientCmd(buf);
+}
+
+void ConsolePanel::setSize(int wide,int tall)
+{
+ Panel::setSize(wide,tall);
+
+ getPaintSize(wide,tall);
+
+ _textGrid->setBounds(5,5,wide-10,tall-35);
+ _textEntry->setBounds(5,tall-25,wide-10,20);
+}
+
+
+
+
+
diff --git a/main/source/cl_dll/vgui_ConsolePanel.h b/main/source/cl_dll/vgui_ConsolePanel.h
index 8edfc035..7e545e76 100644
--- a/main/source/cl_dll/vgui_ConsolePanel.h
+++ b/main/source/cl_dll/vgui_ConsolePanel.h
@@ -1,32 +1,32 @@
-
-#ifndef CONSOLEPANEL_H
-#define CONSOLEPANEL_H
-
-#include
-#include
-
-namespace vgui
-{
-class TextGrid;
-class TextEntry;
-}
-
-
-class ConsolePanel : public vgui::Panel
-{
-private:
- vgui::TextGrid* _textGrid;
- vgui::TextEntry* _textEntry;
-public:
- ConsolePanel(int x,int y,int wide,int tall);
-public:
- virtual void setSize(int wide,int tall);
- virtual int print(const char* text);
- virtual int vprintf(const char* format,va_list argList);
- virtual int printf(const char* format,...);
- virtual void doExecCommand();
-};
-
-
-
+
+#ifndef CONSOLEPANEL_H
+#define CONSOLEPANEL_H
+
+#include
+#include
+
+namespace vgui
+{
+class TextGrid;
+class TextEntry;
+}
+
+
+class ConsolePanel : public vgui::Panel
+{
+private:
+ vgui::TextGrid* _textGrid;
+ vgui::TextEntry* _textEntry;
+public:
+ ConsolePanel(int x,int y,int wide,int tall);
+public:
+ virtual void setSize(int wide,int tall);
+ virtual int print(const char* text);
+ virtual int vprintf(const char* format,va_list argList);
+ virtual int printf(const char* format,...);
+ virtual void doExecCommand();
+};
+
+
+
#endif
\ No newline at end of file
diff --git a/main/source/cl_dll/vgui_ControlConfigPanel.cpp b/main/source/cl_dll/vgui_ControlConfigPanel.cpp
index 777f4a85..ea8cf16c 100644
--- a/main/source/cl_dll/vgui_ControlConfigPanel.cpp
+++ b/main/source/cl_dll/vgui_ControlConfigPanel.cpp
@@ -1,206 +1,206 @@
-
-#include
-#include"vgui_ControlConfigPanel.h"
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-using namespace vgui;
-
-namespace
-{
-class FooTablePanel : public TablePanel
-{
-private:
- Label* _label;
- TextEntry* _textEntry;
- ControlConfigPanel* _controlConfigPanel;
-public:
- FooTablePanel(ControlConfigPanel* controlConfigPanel,int x,int y,int wide,int tall,int columnCount) : TablePanel(x,y,wide,tall,columnCount)
- {
- _controlConfigPanel=controlConfigPanel;
- _label=new Label("You are a dumb monkey",0,0,100,20);
- _label->setBgColor(Scheme::sc_primary3);
- _label->setFgColor(Scheme::sc_primary1);
- _label->setFont(Scheme::sf_primary3);
-
- _textEntry=new TextEntry("",0,0,100,20);
- //_textEntry->setFont(Scheme::sf_primary3);
- }
-public:
- virtual int getRowCount()
- {
- return _controlConfigPanel->GetCVarCount();
- }
- virtual int getCellTall(int row)
- {
- return 12;
- }
- virtual Panel* getCellRenderer(int column,int row,bool columnSelected,bool rowSelected,bool cellSelected)
- {
- char cvar[128],desc[128],bind[128],bindAlt[128];
- _controlConfigPanel->GetCVar(row,cvar,128,desc,128);
-
- if(cellSelected)
- {
- _label->setBgColor(Scheme::sc_primary1);
- _label->setFgColor(Scheme::sc_primary3);
- }
- else
- if(rowSelected)
- {
- _label->setBgColor(Scheme::sc_primary2);
- _label->setFgColor(Scheme::sc_primary1);
- }
- else
- {
- _label->setBgColor(Scheme::sc_primary3);
- _label->setFgColor(Scheme::sc_primary1);
- }
-
- switch(column)
- {
- case 0:
- {
- _label->setText(desc);
- _label->setContentAlignment(Label::a_west);
- break;
- }
- case 1:
- {
- _controlConfigPanel->GetCVarBind(cvar,bind,128,bindAlt,128);
- _label->setText(bind);
- _label->setContentAlignment(Label::a_center);
- break;
- }
- case 2:
- {
- _controlConfigPanel->GetCVarBind(cvar,bind,128,bindAlt,128);
- _label->setText(bindAlt);
- _label->setContentAlignment(Label::a_center);
- break;
- }
- default:
- {
- _label->setText("");
- break;
- }
- }
-
- return _label;
- }
- virtual Panel* startCellEditing(int column,int row)
- {
- _textEntry->setText("Goat",(int)strlen("Goat"));
- _textEntry->requestFocus();
- return _textEntry;
- }
-};
-}
-
-ControlConfigPanel::ControlConfigPanel(int x,int y,int wide,int tall) : Panel(x,y,wide,tall)
-{
- setPaintBorderEnabled(false);
- setPaintBackgroundEnabled(false);
- setPaintEnabled(false);
-
- _actionLabel=new Label("Action");
- _actionLabel->setBgColor(Scheme::sc_primary3);
- _actionLabel->setFgColor(Scheme::sc_primary3);
-
- _keyButtonLabel=new Label("Key / Button");
- _keyButtonLabel->setBgColor(Scheme::sc_primary3);
- _keyButtonLabel->setFgColor(Scheme::sc_primary3);
-
- _alternateLabel=new Label("Alternate");
- _alternateLabel->setBgColor(Scheme::sc_primary3);
- _alternateLabel->setFgColor(Scheme::sc_primary3);
-
- _headerPanel=new HeaderPanel(0,0,wide,20);
- _headerPanel->setParent(this);
-
- _headerPanel->addSectionPanel(_actionLabel);
- _headerPanel->addSectionPanel(_keyButtonLabel);
- _headerPanel->addSectionPanel(_alternateLabel);
-
- _headerPanel->setSliderPos( 0, wide/2 );
- _headerPanel->setSliderPos( 1, (wide/2) + (wide/4) );
- _headerPanel->setSliderPos( 2, wide );
-
- _scrollPanel=new ScrollPanel(0,20,wide,tall-20);
- _scrollPanel->setParent(this);
- _scrollPanel->setPaintBorderEnabled(false);
- _scrollPanel->setPaintBackgroundEnabled(false);
- _scrollPanel->setPaintEnabled(false);
- _scrollPanel->getClient()->setPaintBorderEnabled(false);
- _scrollPanel->getClient()->setPaintBackgroundEnabled(false);
- _scrollPanel->getClient()->setPaintEnabled(false);
- _scrollPanel->setScrollBarVisible(false,true);
-
- _tablePanel=new FooTablePanel(this,0,0,_scrollPanel->getClient()->getWide(),800, 3);
- _tablePanel->setParent(_scrollPanel->getClient());
- _tablePanel->setHeaderPanel(_headerPanel);
- _tablePanel->setBgColor(Color(200,0,0,255));
- _tablePanel->setFgColor(Color(Scheme::sc_primary2));
- _tablePanel->setGridVisible(true,true);
- _tablePanel->setGridSize(1,1);
-}
-
-void ControlConfigPanel::AddCVar(const char* cvar,const char* desc)
-{
- _cvarDar.addElement(vgui_strdup(cvar));
- _descDar.addElement(vgui_strdup(desc));
-}
-
-int ControlConfigPanel::GetCVarCount()
-{
- return _cvarDar.getCount();
-}
-
-void ControlConfigPanel::GetCVar(int index,char* cvar,int cvarLen,char* desc,int descLen)
-{
- vgui_strcpy(cvar,cvarLen,_cvarDar[index]);
- vgui_strcpy(desc,descLen,_descDar[index]);
-}
-
-void ControlConfigPanel::AddCVarFromInputStream(InputStream* is)
-{
- if(is==null)
- {
- return;
- }
-
- DataInputStream dis(is);
-
- bool success;
-
- while(1)
- {
- char buf[256],cvar[128],desc[128];
- dis.readLine(buf,256,success);
- if(!success)
- {
- break;
- }
- if(sscanf(buf,"\"%[^\"]\" \"%[^\"]\"",cvar,desc)==2)
- {
- AddCVar(cvar,desc);
- }
- }
-}
-
-void ControlConfigPanel::GetCVarBind(const char* cvar,char* bind,int bindLen,char* bindAlt,int bindAltLen)
-{
- sprintf(bind,"%s : Bind",cvar);
- sprintf(bindAlt,"%s : BindAlt",cvar);
-}
-
-void ControlConfigPanel::SetCVarBind(const char* cvar,const char* bind,const char* bindAlt)
-{
-}
-
+
+#include
+#include"vgui_ControlConfigPanel.h"
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+using namespace vgui;
+
+namespace
+{
+class FooTablePanel : public TablePanel
+{
+private:
+ Label* _label;
+ TextEntry* _textEntry;
+ ControlConfigPanel* _controlConfigPanel;
+public:
+ FooTablePanel(ControlConfigPanel* controlConfigPanel,int x,int y,int wide,int tall,int columnCount) : TablePanel(x,y,wide,tall,columnCount)
+ {
+ _controlConfigPanel=controlConfigPanel;
+ _label=new Label("You are a dumb monkey",0,0,100,20);
+ _label->setBgColor(Scheme::sc_primary3);
+ _label->setFgColor(Scheme::sc_primary1);
+ _label->setFont(Scheme::sf_primary3);
+
+ _textEntry=new TextEntry("",0,0,100,20);
+ //_textEntry->setFont(Scheme::sf_primary3);
+ }
+public:
+ virtual int getRowCount()
+ {
+ return _controlConfigPanel->GetCVarCount();
+ }
+ virtual int getCellTall(int row)
+ {
+ return 12;
+ }
+ virtual Panel* getCellRenderer(int column,int row,bool columnSelected,bool rowSelected,bool cellSelected)
+ {
+ char cvar[128],desc[128],bind[128],bindAlt[128];
+ _controlConfigPanel->GetCVar(row,cvar,128,desc,128);
+
+ if(cellSelected)
+ {
+ _label->setBgColor(Scheme::sc_primary1);
+ _label->setFgColor(Scheme::sc_primary3);
+ }
+ else
+ if(rowSelected)
+ {
+ _label->setBgColor(Scheme::sc_primary2);
+ _label->setFgColor(Scheme::sc_primary1);
+ }
+ else
+ {
+ _label->setBgColor(Scheme::sc_primary3);
+ _label->setFgColor(Scheme::sc_primary1);
+ }
+
+ switch(column)
+ {
+ case 0:
+ {
+ _label->setText(desc);
+ _label->setContentAlignment(Label::a_west);
+ break;
+ }
+ case 1:
+ {
+ _controlConfigPanel->GetCVarBind(cvar,bind,128,bindAlt,128);
+ _label->setText(bind);
+ _label->setContentAlignment(Label::a_center);
+ break;
+ }
+ case 2:
+ {
+ _controlConfigPanel->GetCVarBind(cvar,bind,128,bindAlt,128);
+ _label->setText(bindAlt);
+ _label->setContentAlignment(Label::a_center);
+ break;
+ }
+ default:
+ {
+ _label->setText("");
+ break;
+ }
+ }
+
+ return _label;
+ }
+ virtual Panel* startCellEditing(int column,int row)
+ {
+ _textEntry->setText("Goat",(int)strlen("Goat"));
+ _textEntry->requestFocus();
+ return _textEntry;
+ }
+};
+}
+
+ControlConfigPanel::ControlConfigPanel(int x,int y,int wide,int tall) : Panel(x,y,wide,tall)
+{
+ setPaintBorderEnabled(false);
+ setPaintBackgroundEnabled(false);
+ setPaintEnabled(false);
+
+ _actionLabel=new Label("Action");
+ _actionLabel->setBgColor(Scheme::sc_primary3);
+ _actionLabel->setFgColor(Scheme::sc_primary3);
+
+ _keyButtonLabel=new Label("Key / Button");
+ _keyButtonLabel->setBgColor(Scheme::sc_primary3);
+ _keyButtonLabel->setFgColor(Scheme::sc_primary3);
+
+ _alternateLabel=new Label("Alternate");
+ _alternateLabel->setBgColor(Scheme::sc_primary3);
+ _alternateLabel->setFgColor(Scheme::sc_primary3);
+
+ _headerPanel=new HeaderPanel(0,0,wide,20);
+ _headerPanel->setParent(this);
+
+ _headerPanel->addSectionPanel(_actionLabel);
+ _headerPanel->addSectionPanel(_keyButtonLabel);
+ _headerPanel->addSectionPanel(_alternateLabel);
+
+ _headerPanel->setSliderPos( 0, wide/2 );
+ _headerPanel->setSliderPos( 1, (wide/2) + (wide/4) );
+ _headerPanel->setSliderPos( 2, wide );
+
+ _scrollPanel=new ScrollPanel(0,20,wide,tall-20);
+ _scrollPanel->setParent(this);
+ _scrollPanel->setPaintBorderEnabled(false);
+ _scrollPanel->setPaintBackgroundEnabled(false);
+ _scrollPanel->setPaintEnabled(false);
+ _scrollPanel->getClient()->setPaintBorderEnabled(false);
+ _scrollPanel->getClient()->setPaintBackgroundEnabled(false);
+ _scrollPanel->getClient()->setPaintEnabled(false);
+ _scrollPanel->setScrollBarVisible(false,true);
+
+ _tablePanel=new FooTablePanel(this,0,0,_scrollPanel->getClient()->getWide(),800, 3);
+ _tablePanel->setParent(_scrollPanel->getClient());
+ _tablePanel->setHeaderPanel(_headerPanel);
+ _tablePanel->setBgColor(Color(200,0,0,255));
+ _tablePanel->setFgColor(Color(Scheme::sc_primary2));
+ _tablePanel->setGridVisible(true,true);
+ _tablePanel->setGridSize(1,1);
+}
+
+void ControlConfigPanel::AddCVar(const char* cvar,const char* desc)
+{
+ _cvarDar.addElement(vgui_strdup(cvar));
+ _descDar.addElement(vgui_strdup(desc));
+}
+
+int ControlConfigPanel::GetCVarCount()
+{
+ return _cvarDar.getCount();
+}
+
+void ControlConfigPanel::GetCVar(int index,char* cvar,int cvarLen,char* desc,int descLen)
+{
+ vgui_strcpy(cvar,cvarLen,_cvarDar[index]);
+ vgui_strcpy(desc,descLen,_descDar[index]);
+}
+
+void ControlConfigPanel::AddCVarFromInputStream(InputStream* is)
+{
+ if(is==null)
+ {
+ return;
+ }
+
+ DataInputStream dis(is);
+
+ bool success;
+
+ while(1)
+ {
+ char buf[256],cvar[128],desc[128];
+ dis.readLine(buf,256,success);
+ if(!success)
+ {
+ break;
+ }
+ if(sscanf(buf,"\"%[^\"]\" \"%[^\"]\"",cvar,desc)==2)
+ {
+ AddCVar(cvar,desc);
+ }
+ }
+}
+
+void ControlConfigPanel::GetCVarBind(const char* cvar,char* bind,int bindLen,char* bindAlt,int bindAltLen)
+{
+ sprintf(bind,"%s : Bind",cvar);
+ sprintf(bindAlt,"%s : BindAlt",cvar);
+}
+
+void ControlConfigPanel::SetCVarBind(const char* cvar,const char* bind,const char* bindAlt)
+{
+}
+
diff --git a/main/source/cl_dll/vgui_ControlConfigPanel.h b/main/source/cl_dll/vgui_ControlConfigPanel.h
index 9a5a41f5..1c362c4a 100644
--- a/main/source/cl_dll/vgui_ControlConfigPanel.h
+++ b/main/source/cl_dll/vgui_ControlConfigPanel.h
@@ -1,41 +1,41 @@
-
-#ifndef CONTROLCONFIGPANEL_H
-#define CONTROLCONFIGPANEL_H
-
-#include
-#include
-
-namespace vgui
-{
-class HeaderPanel;
-class TablePanel;
-class ScrollPanel;
-class InputStream;
-class Label;
-}
-
-class ControlConfigPanel : public vgui::Panel
-{
-private:
- vgui::HeaderPanel* _headerPanel;
- vgui::TablePanel* _tablePanel;
- vgui::ScrollPanel* _scrollPanel;
- vgui::Dar _cvarDar;
- vgui::Dar _descDar;
- vgui::Label* _actionLabel;
- vgui::Label* _keyButtonLabel;
- vgui::Label* _alternateLabel;
-public:
- ControlConfigPanel(int x,int y,int wide,int tall);
-public:
- void AddCVar(const char* cvar,const char* desc);
- void AddCVarFromInputStream(vgui::InputStream* is);
- int GetCVarCount();
- void GetCVar(int index,char* cvar,int cvarLen,char* desc,int descLen);
- void GetCVarBind(const char* cvar,char* bind,int bindLen,char* bindAlt,int bindAltLen);
- void SetCVarBind(const char* cvar,const char* bind,const char* bindAlt);
-};
-
-
-
+
+#ifndef CONTROLCONFIGPANEL_H
+#define CONTROLCONFIGPANEL_H
+
+#include
+#include
+
+namespace vgui
+{
+class HeaderPanel;
+class TablePanel;
+class ScrollPanel;
+class InputStream;
+class Label;
+}
+
+class ControlConfigPanel : public vgui::Panel
+{
+private:
+ vgui::HeaderPanel* _headerPanel;
+ vgui::TablePanel* _tablePanel;
+ vgui::ScrollPanel* _scrollPanel;
+ vgui::Dar _cvarDar;
+ vgui::Dar _descDar;
+ vgui::Label* _actionLabel;
+ vgui::Label* _keyButtonLabel;
+ vgui::Label* _alternateLabel;
+public:
+ ControlConfigPanel(int x,int y,int wide,int tall);
+public:
+ void AddCVar(const char* cvar,const char* desc);
+ void AddCVarFromInputStream(vgui::InputStream* is);
+ int GetCVarCount();
+ void GetCVar(int index,char* cvar,int cvarLen,char* desc,int descLen);
+ void GetCVarBind(const char* cvar,char* bind,int bindLen,char* bindAlt,int bindAltLen);
+ void SetCVarBind(const char* cvar,const char* bind,const char* bindAlt);
+};
+
+
+
#endif
\ No newline at end of file
diff --git a/main/source/cl_dll/vgui_CustomObjects.cpp b/main/source/cl_dll/vgui_CustomObjects.cpp
index 00013010..5454a40e 100644
--- a/main/source/cl_dll/vgui_CustomObjects.cpp
+++ b/main/source/cl_dll/vgui_CustomObjects.cpp
@@ -1,539 +1,539 @@
-//=========== (C) Copyright 1996-2002 Valve, L.L.C. All rights reserved. ===========
-//
-// The copyright to the contents herein is the property of Valve, L.L.C.
-// The contents may be used and/or copied only with the written permission of
-// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
-// the agreement/contract under which the contents have been supplied.
-//
-// Purpose: Contains implementation of various VGUI-derived objects
-//
-// $Workfile: $
-// $Date: 2001/09/13 22:28:00 $
-//
-//-----------------------------------------------------------------------------
-// $Log: vgui_CustomObjects.cpp,v $
-// Revision 1.2 2001/09/13 22:28:00 Charlie
-// - Updated NS with new Half-life 1108 patch in preparation for voice support and spectator mode
-//
-// Revision 1.1.1.1.2.1 2001/09/13 14:42:29 Charlie
-// - HL1108
-//
-//
-// $NoKeywords: $
-//=============================================================================
-
-#include "VGUI_Font.h"
-
-#include "hud.h"
-#include "cl_util.h"
-#include "camera.h"
-#include "kbutton.h"
-#include "common/cvardef.h"
-#include "common/usercmd.h"
-#include "common/const.h"
-#include "camera.h"
-#include "in_defs.h"
-
-#include "vgui_int.h"
-#include "vgui_TeamFortressViewport.h"
-#include "vgui_ServerBrowser.h"
-#include "../game_shared/vgui_loadtga.h"
-
-// Arrow filenames
-char *sArrowFilenames[] =
-{
- "arrowup",
- "arrowdn",
- "arrowlt",
- "arrowrt",
-};
-
-// Get the name of TGA file, without a gamedir
-char *GetTGANameForRes(const char *pszName)
-{
- int i;
- char sz[256];
- static char gd[256];
- if (ScreenWidth() < 640)
- i = 320;
- else
- i = 640;
- sprintf(sz, pszName, i);
- sprintf(gd, "gfx/vgui/%s.tga", sz);
- return gd;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Loads a .tga file and returns a pointer to the VGUI tga object
-//-----------------------------------------------------------------------------
-BitmapTGA *LoadTGAForRes( const char* pImageName )
-{
- BitmapTGA *pTGA;
-
- char sz[256];
- sprintf(sz, "%%d_%s", pImageName);
- pTGA = vgui_LoadTGA(GetTGANameForRes(sz));
-
- return pTGA;
-}
-
-//===========================================================
-// All TFC Hud buttons are derived from this one.
-CommandButton::CommandButton( const char* text,int x,int y,int wide,int tall, bool bNoHighlight) : Button("",x,y,wide,tall)
-{
- m_iPlayerClass = 0;
- m_bNoHighlight = bNoHighlight;
- m_bFlat = false;
- Init();
- setText( text );
-}
-
-CommandButton::CommandButton( int iPlayerClass, const char* text,int x,int y,int wide,int tall, bool bFlat) : Button("",x,y,wide,tall)
-{
- m_iPlayerClass = iPlayerClass;
- m_bNoHighlight = false;
- m_bFlat = bFlat;
- Init();
- setText( text );
-}
-CommandButton::CommandButton(const char *text, int x, int y, int wide, int tall, bool bNoHighlight, bool bFlat) : Button("",x,y,wide,tall)
-{
- m_iPlayerClass = 0;
- m_bFlat = bFlat;
- m_bNoHighlight = bNoHighlight;
- Init();
- setText( text );
-}
-
-void CommandButton::Init( void )
-{
- m_pSubMenu = NULL;
- m_pSubLabel = NULL;
- m_pParentMenu = NULL;
-
- // Set text color to orange
- setFgColor(Scheme::sc_primary1);
-
- // left align
- setContentAlignment( vgui::Label::a_west );
-
- // Add the Highlight signal
- if (!m_bNoHighlight)
- addInputSignal( new CHandler_CommandButtonHighlight(this) );
-
- // not bound to any button yet
- m_cBoundKey = 0;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Prepends the button text with the current bound key
-// if no bound key, then a clear space ' ' instead
-//-----------------------------------------------------------------------------
-void CommandButton::RecalculateText( void )
-{
- char szBuf[128];
-
- if ( m_cBoundKey != 0 )
- {
- if ( m_cBoundKey == (char)255 )
- {
- strcpy( szBuf, m_sMainText );
- }
- else
- {
- sprintf( szBuf, " %c %s", m_cBoundKey, m_sMainText );
- }
- szBuf[MAX_BUTTON_SIZE-1] = 0;
- }
- else
- {
- // just draw a space if no key bound
- sprintf( szBuf, " %s", m_sMainText );
- szBuf[MAX_BUTTON_SIZE-1] = 0;
- }
-
- Button::setText( szBuf );
-}
-
-void CommandButton::setText( const char *text )
-{
- strncpy( m_sMainText, text, MAX_BUTTON_SIZE );
- m_sMainText[MAX_BUTTON_SIZE-1] = 0;
-
- RecalculateText();
-}
-
-void CommandButton::setBoundKey( char boundKey )
-{
- m_cBoundKey = boundKey;
- RecalculateText();
-}
-
-char CommandButton::getBoundKey( void )
-{
- return m_cBoundKey;
-}
-
-void CommandButton::AddSubMenu( CCommandMenu *pNewMenu )
-{
- m_pSubMenu = pNewMenu;
-
- // Prevent this button from being pushed
- setMouseClickEnabled( MOUSE_LEFT, false );
-}
-
-void CommandButton::UpdateSubMenus( int iAdjustment )
-{
- if ( m_pSubMenu )
- m_pSubMenu->RecalculatePositions( iAdjustment );
-}
-
-void CommandButton::paint()
-{
- // Make the sub label paint the same as the button
- if ( m_pSubLabel )
- {
- if ( isSelected() )
- m_pSubLabel->PushDown();
- else
- m_pSubLabel->PushUp();
- }
-
- // draw armed button text in white
- if ( isArmed() )
- {
- setFgColor( Scheme::sc_secondary2 );
- }
- else
- {
- setFgColor( Scheme::sc_primary1 );
- }
-
- Button::paint();
-}
-
-void CommandButton::paintBackground()
-{
- if ( m_bFlat )
- {
- if ( isArmed() )
- {
- // Orange Border
- drawSetColor( Scheme::sc_secondary1 );
- drawOutlinedRect(0,0,_size[0],_size[1]);
- }
- }
- else
- {
- if ( isArmed() )
- {
- // Orange highlight background
- drawSetColor( Scheme::sc_primary2 );
- drawFilledRect(0,0,_size[0],_size[1]);
- }
-
- // Orange Border
- drawSetColor( Scheme::sc_secondary1 );
- drawOutlinedRect(0,0,_size[0],_size[1]);
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Highlights the current button, and all it's parent menus
-//-----------------------------------------------------------------------------
-void CommandButton::cursorEntered( void )
-{
- // unarm all the other buttons in this menu
- CCommandMenu *containingMenu = getParentMenu();
- if ( containingMenu )
- {
- containingMenu->ClearButtonsOfArmedState();
-
- // make all our higher buttons armed
- CCommandMenu *pCParent = containingMenu->GetParentMenu();
- if ( pCParent )
- {
- CommandButton *pParentButton = pCParent->FindButtonWithSubmenu( containingMenu );
-
- pParentButton->cursorEntered();
- }
- }
-
- // arm ourselves
- setArmed( true );
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-void CommandButton::cursorExited( void )
-{
- // only clear ourselves if we have do not have a containing menu
- // only stay armed if we have a sub menu
- // the buttons only unarm themselves when another button is armed instead
- if ( !getParentMenu() || !GetSubMenu() )
- {
- setArmed( false );
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Returns the command menu that the button is part of, if any
-// Output : CCommandMenu *
-//-----------------------------------------------------------------------------
-CCommandMenu *CommandButton::getParentMenu( void )
-{
- return m_pParentMenu;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Sets the menu that contains this button
-// Input : *pParentMenu -
-//-----------------------------------------------------------------------------
-void CommandButton::setParentMenu( CCommandMenu *pParentMenu )
-{
- m_pParentMenu = pParentMenu;
-}
-
-
-//===========================================================
-int ClassButton::IsNotValid()
-{
- // If this is the main ChangeClass button, remove it if the player's only able to be civilians
- if ( m_iPlayerClass == -1 )
- {
- if (gViewPort->GetValidClasses(g_iTeamNumber) == -1)
- return true;
-
- return false;
- }
-
- // Is it an illegal class?
- if ((gViewPort->GetValidClasses(0) & sTFValidClassInts[ m_iPlayerClass ]) || (gViewPort->GetValidClasses(g_iTeamNumber) & sTFValidClassInts[ m_iPlayerClass ]))
- return true;
-
- // Only check current class if they've got autokill on
- bool bAutoKill = CVAR_GET_FLOAT( "hud_classautokill" ) != 0;
- if ( bAutoKill )
- {
- // Is it the player's current class?
- if ( (gViewPort->IsRandomPC() && m_iPlayerClass == PC_RANDOM) || (!gViewPort->IsRandomPC() && (m_iPlayerClass == g_iPlayerClass)) )
- return true;
- }
-
- return false;
-}
-
-//===========================================================
-// Button with Class image beneath it
-CImageLabel::CImageLabel( const char* pImageName,int x,int y ) : Label( "", x,y )
-{
- setContentFitted(true);
- m_pTGA = LoadTGAForRes(pImageName);
- setImage( m_pTGA );
-}
-
-CImageLabel::CImageLabel( const char* pImageName,int x,int y,int wide,int tall ) : Label( "", x,y,wide,tall )
-{
- setContentFitted(true);
- m_pTGA = LoadTGAForRes(pImageName);
- setImage( m_pTGA );
-}
-
-//===========================================================
-// Image size
-int CImageLabel::getImageWide( void )
-{
- if( m_pTGA )
- {
- int iXSize, iYSize;
- m_pTGA->getSize( iXSize, iYSize );
- return iXSize;
- }
- else
- {
- return 1;
- }
-}
-
-int CImageLabel::getImageTall( void )
-{
- if( m_pTGA )
- {
- int iXSize, iYSize;
- m_pTGA->getSize( iXSize, iYSize );
- return iYSize;
- }
- else
- {
- return 1;
- }
-}
-
-void CImageLabel::LoadImage(const char * pImageName)
-{
- if ( m_pTGA )
- delete m_pTGA;
-
- // Load the Image
- m_pTGA = LoadTGAForRes(pImageName);
-
- if ( m_pTGA == NULL )
- {
- // we didn't find a matching image file for this resolution
- // try to load file resolution independent
-
- char sz[256];
- sprintf(sz, "%s/%s",gEngfuncs.pfnGetGameDirectory(), pImageName );
- FileInputStream* fis = new FileInputStream( sz, false );
- m_pTGA = new BitmapTGA(fis,true);
- fis->close();
- }
-
- if ( m_pTGA == NULL )
- return; // unable to load image
-
- int w,t;
-
- m_pTGA->getSize( w, t );
-
- setSize( XRES (w),YRES (t) );
- setImage( m_pTGA );
-}
-//===========================================================
-// Various overloaded paint functions for Custom VGUI objects
-void CCommandMenu::paintBackground()
-{
- // Transparent black background
-
- if ( m_iSpectCmdMenu )
- drawSetColor( 0, 0, 0, 64 );
- else
- drawSetColor(Scheme::sc_primary3);
-
- drawFilledRect(0,0,_size[0],_size[1]);
-}
-
-//=================================================================================
-// CUSTOM SCROLLPANEL
-//=================================================================================
-CTFScrollButton::CTFScrollButton(int iArrow, const char* text,int x,int y,int wide,int tall) : CommandButton(text,x,y,wide,tall)
-{
- // Set text color to orange
- setFgColor(Scheme::sc_primary1);
-
- // Load in the arrow
- m_pTGA = LoadTGAForRes( sArrowFilenames[iArrow] );
- setImage( m_pTGA );
-
- // Highlight signal
- InputSignal *pISignal = new CHandler_CommandButtonHighlight(this);
- addInputSignal(pISignal);
-}
-
-void CTFScrollButton::paint( void )
-{
- if (!m_pTGA)
- return;
-
- // draw armed button text in white
- if ( isArmed() )
- {
- m_pTGA->setColor( Color(255,255,255, 0) );
- }
- else
- {
- m_pTGA->setColor( Color(255,255,255, 128) );
- }
-
- m_pTGA->doPaint(this);
-}
-
-void CTFScrollButton::paintBackground( void )
-{
-/*
- if ( isArmed() )
- {
- // Orange highlight background
- drawSetColor( Scheme::sc_primary2 );
- drawFilledRect(0,0,_size[0],_size[1]);
- }
-
- // Orange Border
- drawSetColor( Scheme::sc_secondary1 );
- drawOutlinedRect(0,0,_size[0]-1,_size[1]);
-*/
-}
-
-void CTFSlider::paintBackground( void )
-{
- int wide,tall,nobx,noby;
- getPaintSize(wide,tall);
- getNobPos(nobx,noby);
-
- // Border
- drawSetColor( Scheme::sc_secondary1 );
- drawOutlinedRect( 0,0,wide,tall );
-
- if( isVertical() )
- {
- // Nob Fill
- drawSetColor( Scheme::sc_primary2 );
- drawFilledRect( 0,nobx,wide,noby );
-
- // Nob Outline
- drawSetColor( Scheme::sc_primary1 );
- drawOutlinedRect( 0,nobx,wide,noby );
- }
- else
- {
- // Nob Fill
- drawSetColor( Scheme::sc_primary2 );
- drawFilledRect( nobx,0,noby,tall );
-
- // Nob Outline
- drawSetColor( Scheme::sc_primary1 );
- drawOutlinedRect( nobx,0,noby,tall );
- }
-}
-
-CTFScrollPanel::CTFScrollPanel(int x,int y,int wide,int tall) : ScrollPanel(x,y,wide,tall)
-{
- ScrollBar *pScrollBar = getVerticalScrollBar();
- pScrollBar->setButton( new CTFScrollButton( ARROW_UP, "", 0,0,16,16 ), 0 );
- pScrollBar->setButton( new CTFScrollButton( ARROW_DOWN, "", 0,0,16,16 ), 1 );
- pScrollBar->setSlider( new CTFSlider(0,wide-1,wide,(tall-(wide*2))+2,true) );
- pScrollBar->setPaintBorderEnabled(false);
- pScrollBar->setPaintBackgroundEnabled(false);
- pScrollBar->setPaintEnabled(false);
-
- pScrollBar = getHorizontalScrollBar();
- pScrollBar->setButton( new CTFScrollButton( ARROW_LEFT, "", 0,0,16,16 ), 0 );
- pScrollBar->setButton( new CTFScrollButton( ARROW_RIGHT, "", 0,0,16,16 ), 1 );
- pScrollBar->setSlider( new CTFSlider(tall,0,wide-(tall*2),tall,false) );
- pScrollBar->setPaintBorderEnabled(false);
- pScrollBar->setPaintBackgroundEnabled(false);
- pScrollBar->setPaintEnabled(false);
-}
-
-
-//=================================================================================
-// CUSTOM HANDLERS
-//=================================================================================
-void CHandler_MenuButtonOver::cursorEntered(Panel *panel)
-{
- if ( gViewPort && m_pMenuPanel )
- {
- m_pMenuPanel->SetActiveInfo( m_iButton );
- }
-}
-
-void CMenuHandler_StringCommandClassSelect::actionPerformed(Panel* panel)
-{
- CMenuHandler_StringCommand::actionPerformed( panel );
-
- bool bAutoKill = CVAR_GET_FLOAT( "hud_classautokill" ) != 0;
- if ( bAutoKill && g_iPlayerClass != 0 )
- gEngfuncs.pfnClientCmd("kill");
-}
-
+//=========== (C) Copyright 1996-2002 Valve, L.L.C. All rights reserved. ===========
+//
+// The copyright to the contents herein is the property of Valve, L.L.C.
+// The contents may be used and/or copied only with the written permission of
+// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
+// the agreement/contract under which the contents have been supplied.
+//
+// Purpose: Contains implementation of various VGUI-derived objects
+//
+// $Workfile: $
+// $Date: 2001/09/13 22:28:00 $
+//
+//-----------------------------------------------------------------------------
+// $Log: vgui_CustomObjects.cpp,v $
+// Revision 1.2 2001/09/13 22:28:00 Charlie
+// - Updated NS with new Half-life 1108 patch in preparation for voice support and spectator mode
+//
+// Revision 1.1.1.1.2.1 2001/09/13 14:42:29 Charlie
+// - HL1108
+//
+//
+// $NoKeywords: $
+//=============================================================================
+
+#include "VGUI_Font.h"
+
+#include "hud.h"
+#include "cl_util.h"
+#include "camera.h"
+#include "kbutton.h"
+#include "common/cvardef.h"
+#include "common/usercmd.h"
+#include "common/const.h"
+#include "camera.h"
+#include "in_defs.h"
+
+#include "vgui_int.h"
+#include "vgui_TeamFortressViewport.h"
+#include "vgui_ServerBrowser.h"
+#include "../game_shared/vgui_loadtga.h"
+
+// Arrow filenames
+char *sArrowFilenames[] =
+{
+ "arrowup",
+ "arrowdn",
+ "arrowlt",
+ "arrowrt",
+};
+
+// Get the name of TGA file, without a gamedir
+char *GetTGANameForRes(const char *pszName)
+{
+ int i;
+ char sz[256];
+ static char gd[256];
+ if (ScreenWidth() < 640)
+ i = 320;
+ else
+ i = 640;
+ sprintf(sz, pszName, i);
+ sprintf(gd, "gfx/vgui/%s.tga", sz);
+ return gd;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Loads a .tga file and returns a pointer to the VGUI tga object
+//-----------------------------------------------------------------------------
+BitmapTGA *LoadTGAForRes( const char* pImageName )
+{
+ BitmapTGA *pTGA;
+
+ char sz[256];
+ sprintf(sz, "%%d_%s", pImageName);
+ pTGA = vgui_LoadTGA(GetTGANameForRes(sz));
+
+ return pTGA;
+}
+
+//===========================================================
+// All TFC Hud buttons are derived from this one.
+CommandButton::CommandButton( const char* text,int x,int y,int wide,int tall, bool bNoHighlight) : Button("",x,y,wide,tall)
+{
+ m_iPlayerClass = 0;
+ m_bNoHighlight = bNoHighlight;
+ m_bFlat = false;
+ Init();
+ setText( text );
+}
+
+CommandButton::CommandButton( int iPlayerClass, const char* text,int x,int y,int wide,int tall, bool bFlat) : Button("",x,y,wide,tall)
+{
+ m_iPlayerClass = iPlayerClass;
+ m_bNoHighlight = false;
+ m_bFlat = bFlat;
+ Init();
+ setText( text );
+}
+CommandButton::CommandButton(const char *text, int x, int y, int wide, int tall, bool bNoHighlight, bool bFlat) : Button("",x,y,wide,tall)
+{
+ m_iPlayerClass = 0;
+ m_bFlat = bFlat;
+ m_bNoHighlight = bNoHighlight;
+ Init();
+ setText( text );
+}
+
+void CommandButton::Init( void )
+{
+ m_pSubMenu = NULL;
+ m_pSubLabel = NULL;
+ m_pParentMenu = NULL;
+
+ // Set text color to orange
+ setFgColor(Scheme::sc_primary1);
+
+ // left align
+ setContentAlignment( vgui::Label::a_west );
+
+ // Add the Highlight signal
+ if (!m_bNoHighlight)
+ addInputSignal( new CHandler_CommandButtonHighlight(this) );
+
+ // not bound to any button yet
+ m_cBoundKey = 0;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Prepends the button text with the current bound key
+// if no bound key, then a clear space ' ' instead
+//-----------------------------------------------------------------------------
+void CommandButton::RecalculateText( void )
+{
+ char szBuf[128];
+
+ if ( m_cBoundKey != 0 )
+ {
+ if ( m_cBoundKey == (char)255 )
+ {
+ strcpy( szBuf, m_sMainText );
+ }
+ else
+ {
+ sprintf( szBuf, " %c %s", m_cBoundKey, m_sMainText );
+ }
+ szBuf[MAX_BUTTON_SIZE-1] = 0;
+ }
+ else
+ {
+ // just draw a space if no key bound
+ sprintf( szBuf, " %s", m_sMainText );
+ szBuf[MAX_BUTTON_SIZE-1] = 0;
+ }
+
+ Button::setText( szBuf );
+}
+
+void CommandButton::setText( const char *text )
+{
+ strncpy( m_sMainText, text, MAX_BUTTON_SIZE );
+ m_sMainText[MAX_BUTTON_SIZE-1] = 0;
+
+ RecalculateText();
+}
+
+void CommandButton::setBoundKey( char boundKey )
+{
+ m_cBoundKey = boundKey;
+ RecalculateText();
+}
+
+char CommandButton::getBoundKey( void )
+{
+ return m_cBoundKey;
+}
+
+void CommandButton::AddSubMenu( CCommandMenu *pNewMenu )
+{
+ m_pSubMenu = pNewMenu;
+
+ // Prevent this button from being pushed
+ setMouseClickEnabled( MOUSE_LEFT, false );
+}
+
+void CommandButton::UpdateSubMenus( int iAdjustment )
+{
+ if ( m_pSubMenu )
+ m_pSubMenu->RecalculatePositions( iAdjustment );
+}
+
+void CommandButton::paint()
+{
+ // Make the sub label paint the same as the button
+ if ( m_pSubLabel )
+ {
+ if ( isSelected() )
+ m_pSubLabel->PushDown();
+ else
+ m_pSubLabel->PushUp();
+ }
+
+ // draw armed button text in white
+ if ( isArmed() )
+ {
+ setFgColor( Scheme::sc_secondary2 );
+ }
+ else
+ {
+ setFgColor( Scheme::sc_primary1 );
+ }
+
+ Button::paint();
+}
+
+void CommandButton::paintBackground()
+{
+ if ( m_bFlat )
+ {
+ if ( isArmed() )
+ {
+ // Orange Border
+ drawSetColor( Scheme::sc_secondary1 );
+ drawOutlinedRect(0,0,_size[0],_size[1]);
+ }
+ }
+ else
+ {
+ if ( isArmed() )
+ {
+ // Orange highlight background
+ drawSetColor( Scheme::sc_primary2 );
+ drawFilledRect(0,0,_size[0],_size[1]);
+ }
+
+ // Orange Border
+ drawSetColor( Scheme::sc_secondary1 );
+ drawOutlinedRect(0,0,_size[0],_size[1]);
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Highlights the current button, and all it's parent menus
+//-----------------------------------------------------------------------------
+void CommandButton::cursorEntered( void )
+{
+ // unarm all the other buttons in this menu
+ CCommandMenu *containingMenu = getParentMenu();
+ if ( containingMenu )
+ {
+ containingMenu->ClearButtonsOfArmedState();
+
+ // make all our higher buttons armed
+ CCommandMenu *pCParent = containingMenu->GetParentMenu();
+ if ( pCParent )
+ {
+ CommandButton *pParentButton = pCParent->FindButtonWithSubmenu( containingMenu );
+
+ pParentButton->cursorEntered();
+ }
+ }
+
+ // arm ourselves
+ setArmed( true );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CommandButton::cursorExited( void )
+{
+ // only clear ourselves if we have do not have a containing menu
+ // only stay armed if we have a sub menu
+ // the buttons only unarm themselves when another button is armed instead
+ if ( !getParentMenu() || !GetSubMenu() )
+ {
+ setArmed( false );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Returns the command menu that the button is part of, if any
+// Output : CCommandMenu *
+//-----------------------------------------------------------------------------
+CCommandMenu *CommandButton::getParentMenu( void )
+{
+ return m_pParentMenu;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Sets the menu that contains this button
+// Input : *pParentMenu -
+//-----------------------------------------------------------------------------
+void CommandButton::setParentMenu( CCommandMenu *pParentMenu )
+{
+ m_pParentMenu = pParentMenu;
+}
+
+
+//===========================================================
+int ClassButton::IsNotValid()
+{
+ // If this is the main ChangeClass button, remove it if the player's only able to be civilians
+ if ( m_iPlayerClass == -1 )
+ {
+ if (gViewPort->GetValidClasses(g_iTeamNumber) == -1)
+ return true;
+
+ return false;
+ }
+
+ // Is it an illegal class?
+ if ((gViewPort->GetValidClasses(0) & sTFValidClassInts[ m_iPlayerClass ]) || (gViewPort->GetValidClasses(g_iTeamNumber) & sTFValidClassInts[ m_iPlayerClass ]))
+ return true;
+
+ // Only check current class if they've got autokill on
+ bool bAutoKill = CVAR_GET_FLOAT( "hud_classautokill" ) != 0;
+ if ( bAutoKill )
+ {
+ // Is it the player's current class?
+ if ( (gViewPort->IsRandomPC() && m_iPlayerClass == PC_RANDOM) || (!gViewPort->IsRandomPC() && (m_iPlayerClass == g_iPlayerClass)) )
+ return true;
+ }
+
+ return false;
+}
+
+//===========================================================
+// Button with Class image beneath it
+CImageLabel::CImageLabel( const char* pImageName,int x,int y ) : Label( "", x,y )
+{
+ setContentFitted(true);
+ m_pTGA = LoadTGAForRes(pImageName);
+ setImage( m_pTGA );
+}
+
+CImageLabel::CImageLabel( const char* pImageName,int x,int y,int wide,int tall ) : Label( "", x,y,wide,tall )
+{
+ setContentFitted(true);
+ m_pTGA = LoadTGAForRes(pImageName);
+ setImage( m_pTGA );
+}
+
+//===========================================================
+// Image size
+int CImageLabel::getImageWide( void )
+{
+ if( m_pTGA )
+ {
+ int iXSize, iYSize;
+ m_pTGA->getSize( iXSize, iYSize );
+ return iXSize;
+ }
+ else
+ {
+ return 1;
+ }
+}
+
+int CImageLabel::getImageTall( void )
+{
+ if( m_pTGA )
+ {
+ int iXSize, iYSize;
+ m_pTGA->getSize( iXSize, iYSize );
+ return iYSize;
+ }
+ else
+ {
+ return 1;
+ }
+}
+
+void CImageLabel::LoadImage(const char * pImageName)
+{
+ if ( m_pTGA )
+ delete m_pTGA;
+
+ // Load the Image
+ m_pTGA = LoadTGAForRes(pImageName);
+
+ if ( m_pTGA == NULL )
+ {
+ // we didn't find a matching image file for this resolution
+ // try to load file resolution independent
+
+ char sz[256];
+ sprintf(sz, "%s/%s",gEngfuncs.pfnGetGameDirectory(), pImageName );
+ FileInputStream* fis = new FileInputStream( sz, false );
+ m_pTGA = new BitmapTGA(fis,true);
+ fis->close();
+ }
+
+ if ( m_pTGA == NULL )
+ return; // unable to load image
+
+ int w,t;
+
+ m_pTGA->getSize( w, t );
+
+ setSize( XRES (w),YRES (t) );
+ setImage( m_pTGA );
+}
+//===========================================================
+// Various overloaded paint functions for Custom VGUI objects
+void CCommandMenu::paintBackground()
+{
+ // Transparent black background
+
+ if ( m_iSpectCmdMenu )
+ drawSetColor( 0, 0, 0, 64 );
+ else
+ drawSetColor(Scheme::sc_primary3);
+
+ drawFilledRect(0,0,_size[0],_size[1]);
+}
+
+//=================================================================================
+// CUSTOM SCROLLPANEL
+//=================================================================================
+CTFScrollButton::CTFScrollButton(int iArrow, const char* text,int x,int y,int wide,int tall) : CommandButton(text,x,y,wide,tall)
+{
+ // Set text color to orange
+ setFgColor(Scheme::sc_primary1);
+
+ // Load in the arrow
+ m_pTGA = LoadTGAForRes( sArrowFilenames[iArrow] );
+ setImage( m_pTGA );
+
+ // Highlight signal
+ InputSignal *pISignal = new CHandler_CommandButtonHighlight(this);
+ addInputSignal(pISignal);
+}
+
+void CTFScrollButton::paint( void )
+{
+ if (!m_pTGA)
+ return;
+
+ // draw armed button text in white
+ if ( isArmed() )
+ {
+ m_pTGA->setColor( Color(255,255,255, 0) );
+ }
+ else
+ {
+ m_pTGA->setColor( Color(255,255,255, 128) );
+ }
+
+ m_pTGA->doPaint(this);
+}
+
+void CTFScrollButton::paintBackground( void )
+{
+/*
+ if ( isArmed() )
+ {
+ // Orange highlight background
+ drawSetColor( Scheme::sc_primary2 );
+ drawFilledRect(0,0,_size[0],_size[1]);
+ }
+
+ // Orange Border
+ drawSetColor( Scheme::sc_secondary1 );
+ drawOutlinedRect(0,0,_size[0]-1,_size[1]);
+*/
+}
+
+void CTFSlider::paintBackground( void )
+{
+ int wide,tall,nobx,noby;
+ getPaintSize(wide,tall);
+ getNobPos(nobx,noby);
+
+ // Border
+ drawSetColor( Scheme::sc_secondary1 );
+ drawOutlinedRect( 0,0,wide,tall );
+
+ if( isVertical() )
+ {
+ // Nob Fill
+ drawSetColor( Scheme::sc_primary2 );
+ drawFilledRect( 0,nobx,wide,noby );
+
+ // Nob Outline
+ drawSetColor( Scheme::sc_primary1 );
+ drawOutlinedRect( 0,nobx,wide,noby );
+ }
+ else
+ {
+ // Nob Fill
+ drawSetColor( Scheme::sc_primary2 );
+ drawFilledRect( nobx,0,noby,tall );
+
+ // Nob Outline
+ drawSetColor( Scheme::sc_primary1 );
+ drawOutlinedRect( nobx,0,noby,tall );
+ }
+}
+
+CTFScrollPanel::CTFScrollPanel(int x,int y,int wide,int tall) : ScrollPanel(x,y,wide,tall)
+{
+ ScrollBar *pScrollBar = getVerticalScrollBar();
+ pScrollBar->setButton( new CTFScrollButton( ARROW_UP, "", 0,0,16,16 ), 0 );
+ pScrollBar->setButton( new CTFScrollButton( ARROW_DOWN, "", 0,0,16,16 ), 1 );
+ pScrollBar->setSlider( new CTFSlider(0,wide-1,wide,(tall-(wide*2))+2,true) );
+ pScrollBar->setPaintBorderEnabled(false);
+ pScrollBar->setPaintBackgroundEnabled(false);
+ pScrollBar->setPaintEnabled(false);
+
+ pScrollBar = getHorizontalScrollBar();
+ pScrollBar->setButton( new CTFScrollButton( ARROW_LEFT, "", 0,0,16,16 ), 0 );
+ pScrollBar->setButton( new CTFScrollButton( ARROW_RIGHT, "", 0,0,16,16 ), 1 );
+ pScrollBar->setSlider( new CTFSlider(tall,0,wide-(tall*2),tall,false) );
+ pScrollBar->setPaintBorderEnabled(false);
+ pScrollBar->setPaintBackgroundEnabled(false);
+ pScrollBar->setPaintEnabled(false);
+}
+
+
+//=================================================================================
+// CUSTOM HANDLERS
+//=================================================================================
+void CHandler_MenuButtonOver::cursorEntered(Panel *panel)
+{
+ if ( gViewPort && m_pMenuPanel )
+ {
+ m_pMenuPanel->SetActiveInfo( m_iButton );
+ }
+}
+
+void CMenuHandler_StringCommandClassSelect::actionPerformed(Panel* panel)
+{
+ CMenuHandler_StringCommand::actionPerformed( panel );
+
+ bool bAutoKill = CVAR_GET_FLOAT( "hud_classautokill" ) != 0;
+ if ( bAutoKill && g_iPlayerClass != 0 )
+ gEngfuncs.pfnClientCmd("kill");
+}
+
diff --git a/main/source/cl_dll/vgui_MOTDWindow.cpp b/main/source/cl_dll/vgui_MOTDWindow.cpp
index 1f45af30..8658a060 100644
--- a/main/source/cl_dll/vgui_MOTDWindow.cpp
+++ b/main/source/cl_dll/vgui_MOTDWindow.cpp
@@ -1,168 +1,168 @@
-//=========== (C) Copyright 1999 Valve, L.L.C. All rights reserved. ===========
-//
-// The copyright to the contents herein is the property of Valve, L.L.C.
-// The contents may be used and/or copied only with the written permission of
-// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
-// the agreement/contract under which the contents have been supplied.
-//
-// Purpose:
-//
-// $Workfile: $
-// $Date: 2001/09/13 22:28:00 $
-//
-//-----------------------------------------------------------------------------
-// $Log: vgui_MOTDWindow.cpp,v $
-// Revision 1.3 2001/09/13 22:28:00 Charlie
-// - Updated NS with new Half-life 1108 patch in preparation for voice support and spectator mode
-//
-// Revision 1.2 2001/04/09 19:31:35 charlie
-// - Quick hacky tests to try out menus for team/class picking...yuck
-// Revision 1.1.1.1.2.1 2001/09/13 14:42:29 Charlie
-// - HL1108
-//
-// Revision 1.1.1.1 2000/06/17 14:12:45 charlie
-// Final version of new HL SDK. May not compile.
-// Previous versions of my MSVC project files and utility .bat files.
-// This is my starting point; there is no mod-specific code in here.
-//
-//
-// $NoKeywords: $
-//=============================================================================
-
-#include "VGUI_Font.h"
-#include "VGUI_ScrollPanel.h"
-#include "VGUI_TextImage.h"
-
-#include
-
-#include "hud.h"
-#include "cl_util.h"
-#include "camera.h"
-#include "kbutton.h"
-#include "common/const.h"
-
-#include "vgui_int.h"
-#include "vgui_TeamFortressViewport.h"
-#include "vgui_ServerBrowser.h"
-
-#define MOTD_TITLE_X XRES(16)
-#define MOTD_TITLE_Y YRES(16)
-
-#define MOTD_WINDOW_X XRES(112)
-#define MOTD_WINDOW_Y YRES(80)
-#define MOTD_WINDOW_SIZE_X XRES(424)
-#define MOTD_WINDOW_SIZE_Y YRES(312)
-
-//-----------------------------------------------------------------------------
-// Purpose: Displays the MOTD and basic server information
-//-----------------------------------------------------------------------------
-class CMessageWindowPanel : public CMenuPanel
-{
-public:
- CMessageWindowPanel( const char *szMOTD, const char *szTitle, int iShadeFullScreen, int iRemoveMe, int x, int y, int wide, int tall );
-
-private:
- CTransparentPanel *m_pBackgroundPanel;
-
-};
-
-//-----------------------------------------------------------------------------
-// Purpose: Creates a new CMessageWindowPanel
-// Output : CMenuPanel - interface to the panel
-//-----------------------------------------------------------------------------
-CMenuPanel *CMessageWindowPanel_Create( const char *szMOTD, const char *szTitle, int iShadeFullscreen, int iRemoveMe, int x, int y, int wide, int tall )
-{
- return new CMessageWindowPanel( szMOTD, szTitle, iShadeFullscreen, iRemoveMe, x, y, wide, tall );
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Constructs a message panel
-//-----------------------------------------------------------------------------
-CMessageWindowPanel::CMessageWindowPanel( const char *szMOTD, const char *szTitle, int iShadeFullscreen, int iRemoveMe, int x, int y, int wide, int tall ) : CMenuPanel( iShadeFullscreen ? 100 : 255, iRemoveMe, x, y, wide, tall )
-{
- // Get the scheme used for the Titles
- CSchemeManager *pSchemes = gViewPort->GetSchemeManager();
-
- // schemes
- SchemeHandle_t hTitleScheme = pSchemes->getSchemeHandle( "Title Font" );
- SchemeHandle_t hMOTDText = pSchemes->getSchemeHandle( "Briefing Text" );
-
- // color schemes
- int r, g, b, a;
-
- // Create the window
- m_pBackgroundPanel = new CTransparentPanel( iShadeFullscreen ? 255 : 100, MOTD_WINDOW_X, MOTD_WINDOW_Y, MOTD_WINDOW_SIZE_X, MOTD_WINDOW_SIZE_Y );
- m_pBackgroundPanel->setParent( this );
- m_pBackgroundPanel->setBorder( new LineBorder( Color(255 * 0.7,170 * 0.7,0,0)) );
- m_pBackgroundPanel->setVisible( true );
-
- int iXSize,iYSize,iXPos,iYPos;
- m_pBackgroundPanel->getPos( iXPos,iYPos );
- m_pBackgroundPanel->getSize( iXSize,iYSize );
-
- // Create the title
- Label *pLabel = new Label( "", iXPos + MOTD_TITLE_X, iYPos + MOTD_TITLE_Y );
- pLabel->setParent( this );
- pLabel->setFont( pSchemes->getFont(hTitleScheme) );
- pLabel->setFont( Scheme::sf_primary1 );
-
- pSchemes->getFgColor( hTitleScheme, r, g, b, a );
- pLabel->setFgColor( r, g, b, a );
- pLabel->setFgColor( Scheme::sc_primary1 );
- pSchemes->getBgColor( hTitleScheme, r, g, b, a );
- pLabel->setBgColor( r, g, b, a );
- pLabel->setContentAlignment( vgui::Label::a_west );
- pLabel->setText(szTitle);
-
- // Create the Scroll panel
- ScrollPanel *pScrollPanel = new CTFScrollPanel( iXPos + XRES(16), iYPos + MOTD_TITLE_Y*2 + YRES(16), iXSize - XRES(32), iYSize - (YRES(48) + BUTTON_SIZE_Y*2) );
- pScrollPanel->setParent(this);
-
- //force the scrollbars on so clientClip will take them in account after the validate
- pScrollPanel->setScrollBarAutoVisible(false, false);
- pScrollPanel->setScrollBarVisible(true, true);
- pScrollPanel->validate();
-
- // Create the text panel
- TextPanel *pText = new TextPanel( "", 0,0, 64,64);
- pText->setParent( pScrollPanel->getClient() );
-
- // get the font and colors from the scheme
- pText->setFont( pSchemes->getFont(hMOTDText) );
- pSchemes->getFgColor( hMOTDText, r, g, b, a );
- pText->setFgColor( r, g, b, a );
- pSchemes->getBgColor( hMOTDText, r, g, b, a );
- pText->setBgColor( r, g, b, a );
- pText->setText(szMOTD);
-
- // Get the total size of the MOTD text and resize the text panel
- int iScrollSizeX, iScrollSizeY;
-
- // First, set the size so that the client's wdith is correct at least because the
- // width is critical for getting the "wrapped" size right.
- // You'll see a horizontal scroll bar if there is a single word that won't wrap in the
- // specified width.
- pText->getTextImage()->setSize(pScrollPanel->getClientClip()->getWide(), pScrollPanel->getClientClip()->getTall());
- pText->getTextImage()->getTextSizeWrapped( iScrollSizeX, iScrollSizeY );
-
- // Now resize the textpanel to fit the scrolled size
- pText->setSize( iScrollSizeX , iScrollSizeY );
-
- //turn the scrollbars back into automode
- pScrollPanel->setScrollBarAutoVisible(true, true);
- pScrollPanel->setScrollBarVisible(false, false);
-
- pScrollPanel->validate();
-
- CommandButton *pButton = new CommandButton( CHudTextMessage::BufferedLocaliseTextString( "#Menu_OK" ), iXPos + XRES(16), iYPos + iYSize - YRES(16) - BUTTON_SIZE_Y, CMENU_SIZE_X, BUTTON_SIZE_Y);
- pButton->addActionSignal(new CMenuHandler_TextWindow(HIDE_TEXTWINDOW));
- pButton->addActionSignal(new CMenuHandler_TextWindow(SHOW_CLASSDESC));
- pButton->setParent(this);
-
-}
-
-
-
-
-
-
+//=========== (C) Copyright 1999 Valve, L.L.C. All rights reserved. ===========
+//
+// The copyright to the contents herein is the property of Valve, L.L.C.
+// The contents may be used and/or copied only with the written permission of
+// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
+// the agreement/contract under which the contents have been supplied.
+//
+// Purpose:
+//
+// $Workfile: $
+// $Date: 2001/09/13 22:28:00 $
+//
+//-----------------------------------------------------------------------------
+// $Log: vgui_MOTDWindow.cpp,v $
+// Revision 1.3 2001/09/13 22:28:00 Charlie
+// - Updated NS with new Half-life 1108 patch in preparation for voice support and spectator mode
+//
+// Revision 1.2 2001/04/09 19:31:35 charlie
+// - Quick hacky tests to try out menus for team/class picking...yuck
+// Revision 1.1.1.1.2.1 2001/09/13 14:42:29 Charlie
+// - HL1108
+//
+// Revision 1.1.1.1 2000/06/17 14:12:45 charlie
+// Final version of new HL SDK. May not compile.
+// Previous versions of my MSVC project files and utility .bat files.
+// This is my starting point; there is no mod-specific code in here.
+//
+//
+// $NoKeywords: $
+//=============================================================================
+
+#include "VGUI_Font.h"
+#include "VGUI_ScrollPanel.h"
+#include "VGUI_TextImage.h"
+
+#include
+
+#include "hud.h"
+#include "cl_util.h"
+#include "camera.h"
+#include "kbutton.h"
+#include "common/const.h"
+
+#include "vgui_int.h"
+#include "vgui_TeamFortressViewport.h"
+#include "vgui_ServerBrowser.h"
+
+#define MOTD_TITLE_X XRES(16)
+#define MOTD_TITLE_Y YRES(16)
+
+#define MOTD_WINDOW_X XRES(112)
+#define MOTD_WINDOW_Y YRES(80)
+#define MOTD_WINDOW_SIZE_X XRES(424)
+#define MOTD_WINDOW_SIZE_Y YRES(312)
+
+//-----------------------------------------------------------------------------
+// Purpose: Displays the MOTD and basic server information
+//-----------------------------------------------------------------------------
+class CMessageWindowPanel : public CMenuPanel
+{
+public:
+ CMessageWindowPanel( const char *szMOTD, const char *szTitle, int iShadeFullScreen, int iRemoveMe, int x, int y, int wide, int tall );
+
+private:
+ CTransparentPanel *m_pBackgroundPanel;
+
+};
+
+//-----------------------------------------------------------------------------
+// Purpose: Creates a new CMessageWindowPanel
+// Output : CMenuPanel - interface to the panel
+//-----------------------------------------------------------------------------
+CMenuPanel *CMessageWindowPanel_Create( const char *szMOTD, const char *szTitle, int iShadeFullscreen, int iRemoveMe, int x, int y, int wide, int tall )
+{
+ return new CMessageWindowPanel( szMOTD, szTitle, iShadeFullscreen, iRemoveMe, x, y, wide, tall );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Constructs a message panel
+//-----------------------------------------------------------------------------
+CMessageWindowPanel::CMessageWindowPanel( const char *szMOTD, const char *szTitle, int iShadeFullscreen, int iRemoveMe, int x, int y, int wide, int tall ) : CMenuPanel( iShadeFullscreen ? 100 : 255, iRemoveMe, x, y, wide, tall )
+{
+ // Get the scheme used for the Titles
+ CSchemeManager *pSchemes = gViewPort->GetSchemeManager();
+
+ // schemes
+ SchemeHandle_t hTitleScheme = pSchemes->getSchemeHandle( "Title Font" );
+ SchemeHandle_t hMOTDText = pSchemes->getSchemeHandle( "Briefing Text" );
+
+ // color schemes
+ int r, g, b, a;
+
+ // Create the window
+ m_pBackgroundPanel = new CTransparentPanel( iShadeFullscreen ? 255 : 100, MOTD_WINDOW_X, MOTD_WINDOW_Y, MOTD_WINDOW_SIZE_X, MOTD_WINDOW_SIZE_Y );
+ m_pBackgroundPanel->setParent( this );
+ m_pBackgroundPanel->setBorder( new LineBorder( Color(255 * 0.7,170 * 0.7,0,0)) );
+ m_pBackgroundPanel->setVisible( true );
+
+ int iXSize,iYSize,iXPos,iYPos;
+ m_pBackgroundPanel->getPos( iXPos,iYPos );
+ m_pBackgroundPanel->getSize( iXSize,iYSize );
+
+ // Create the title
+ Label *pLabel = new Label( "", iXPos + MOTD_TITLE_X, iYPos + MOTD_TITLE_Y );
+ pLabel->setParent( this );
+ pLabel->setFont( pSchemes->getFont(hTitleScheme) );
+ pLabel->setFont( Scheme::sf_primary1 );
+
+ pSchemes->getFgColor( hTitleScheme, r, g, b, a );
+ pLabel->setFgColor( r, g, b, a );
+ pLabel->setFgColor( Scheme::sc_primary1 );
+ pSchemes->getBgColor( hTitleScheme, r, g, b, a );
+ pLabel->setBgColor( r, g, b, a );
+ pLabel->setContentAlignment( vgui::Label::a_west );
+ pLabel->setText(szTitle);
+
+ // Create the Scroll panel
+ ScrollPanel *pScrollPanel = new CTFScrollPanel( iXPos + XRES(16), iYPos + MOTD_TITLE_Y*2 + YRES(16), iXSize - XRES(32), iYSize - (YRES(48) + BUTTON_SIZE_Y*2) );
+ pScrollPanel->setParent(this);
+
+ //force the scrollbars on so clientClip will take them in account after the validate
+ pScrollPanel->setScrollBarAutoVisible(false, false);
+ pScrollPanel->setScrollBarVisible(true, true);
+ pScrollPanel->validate();
+
+ // Create the text panel
+ TextPanel *pText = new TextPanel( "", 0,0, 64,64);
+ pText->setParent( pScrollPanel->getClient() );
+
+ // get the font and colors from the scheme
+ pText->setFont( pSchemes->getFont(hMOTDText) );
+ pSchemes->getFgColor( hMOTDText, r, g, b, a );
+ pText->setFgColor( r, g, b, a );
+ pSchemes->getBgColor( hMOTDText, r, g, b, a );
+ pText->setBgColor( r, g, b, a );
+ pText->setText(szMOTD);
+
+ // Get the total size of the MOTD text and resize the text panel
+ int iScrollSizeX, iScrollSizeY;
+
+ // First, set the size so that the client's wdith is correct at least because the
+ // width is critical for getting the "wrapped" size right.
+ // You'll see a horizontal scroll bar if there is a single word that won't wrap in the
+ // specified width.
+ pText->getTextImage()->setSize(pScrollPanel->getClientClip()->getWide(), pScrollPanel->getClientClip()->getTall());
+ pText->getTextImage()->getTextSizeWrapped( iScrollSizeX, iScrollSizeY );
+
+ // Now resize the textpanel to fit the scrolled size
+ pText->setSize( iScrollSizeX , iScrollSizeY );
+
+ //turn the scrollbars back into automode
+ pScrollPanel->setScrollBarAutoVisible(true, true);
+ pScrollPanel->setScrollBarVisible(false, false);
+
+ pScrollPanel->validate();
+
+ CommandButton *pButton = new CommandButton( CHudTextMessage::BufferedLocaliseTextString( "#Menu_OK" ), iXPos + XRES(16), iYPos + iYSize - YRES(16) - BUTTON_SIZE_Y, CMENU_SIZE_X, BUTTON_SIZE_Y);
+ pButton->addActionSignal(new CMenuHandler_TextWindow(HIDE_TEXTWINDOW));
+ pButton->addActionSignal(new CMenuHandler_TextWindow(SHOW_CLASSDESC));
+ pButton->setParent(this);
+
+}
+
+
+
+
+
+
diff --git a/main/source/cl_dll/vgui_SchemeManager.cpp b/main/source/cl_dll/vgui_SchemeManager.cpp
index 3c175ba1..4a7abd42 100644
--- a/main/source/cl_dll/vgui_SchemeManager.cpp
+++ b/main/source/cl_dll/vgui_SchemeManager.cpp
@@ -1,560 +1,572 @@
-//=========== (C) Copyright 1996-2002 Valve, L.L.C. All rights reserved. ===========
-//
-// The copyright to the contents herein is the property of Valve, L.L.C.
-// The contents may be used and/or copied only with the written permission of
-// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
-// the agreement/contract under which the contents have been supplied.
-//
-// Purpose:
-//
-// $Workfile: $
-// $Date: 2001/09/13 15:01:48 $
-//
-//-----------------------------------------------------------------------------
-// $Log: vgui_SchemeManager.cpp,v $
-// Revision 1.3 2001/09/13 15:01:48 Charlie
-// - Merging with 1108
-//
-// Revision 1.2 2001/09/12 16:34:26 Charlie
-// - Slightly better error checking
-// Revision 1.1.1.1.2.2 2001/09/13 14:42:30 Charlie
-// - HL1108
-//
-// Revision 1.1.1.1 2000/06/17 14:12:45 charlie
-// Final version of new HL SDK. May not compile.
-// Previous versions of my MSVC project files and utility .bat files.
-// This is my starting point; there is no mod-specific code in here.
-//
-//
-// $NoKeywords: $
-//=============================================================================
-
-#include "hud.h"
-#include "vgui_SchemeManager.h"
-#include "common/cvardef.h"
-
-#include
-
-
-cvar_t *g_CV_BitmapFonts;
-
-
-void Scheme_Init()
-{
- g_CV_BitmapFonts = gEngfuncs.pfnRegisterVariable("bitmapfonts", "1", 0);
-}
-
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Scheme managers data container
-//-----------------------------------------------------------------------------
-class CSchemeManager::CScheme
-{
-public:
- enum {
- SCHEME_NAME_LENGTH = 32,
- FONT_NAME_LENGTH = 48,
- FONT_FILENAME_LENGTH = 64,
- };
-
- // name
- char schemeName[SCHEME_NAME_LENGTH];
-
- // font
- char fontName[FONT_NAME_LENGTH];
-
- int fontSize;
- int fontWeight;
-
- vgui::Font *font;
- int ownFontPointer; // true if the font is ours to delete
-
- // scheme
- byte fgColor[4];
- byte bgColor[4];
- byte armedFgColor[4];
- byte armedBgColor[4];
- byte mousedownFgColor[4];
- byte mousedownBgColor[4];
- byte borderColor[4];
-
- // construction/destruction
- CScheme();
- ~CScheme();
-};
-
-CSchemeManager::CScheme::CScheme()
-{
- schemeName[0] = 0;
- fontName[0] = 0;
- fontSize = 0;
- fontWeight = 0;
- font = NULL;
- ownFontPointer = false;
-}
-
-CSchemeManager::CScheme::~CScheme()
-{
- // only delete our font pointer if we own it
- if ( ownFontPointer )
- {
- delete font;
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: resolution information
-// !! needs to be shared out
-//-----------------------------------------------------------------------------
-static int g_ResArray[] =
-{
- 320,
- 400,
- 512,
- 640,
- 800,
- 1024,
- 1152,
- 1280,
- 1600
-};
-static int g_NumReses = sizeof(g_ResArray) / sizeof(int);
-
-static byte *LoadFileByResolution( const char *filePrefix, int xRes, const char *filePostfix )
-{
- // find our resolution in the res array
- int resNum = g_NumReses - 1;
- while ( g_ResArray[resNum] > xRes )
- {
- resNum--;
-
- if ( resNum < 0 )
- return NULL;
- }
-
- // try open the file
- byte *pFile = NULL;
- while ( 1 )
- {
-
- // try load
- char fname[256];
- sprintf( fname, "%s%d%s", filePrefix, g_ResArray[resNum], filePostfix );
- pFile = gEngfuncs.COM_LoadFile( fname, 5, NULL );
-
- if ( pFile )
- break;
-
- if ( resNum == 0 )
- return NULL;
-
- resNum--;
- };
-
- return pFile;
-}
-
-static void ParseRGBAFromString( byte colorArray[4], const char *colorVector )
-{
- int r, g, b, a;
- sscanf( colorVector, "%d %d %d %d", &r, &g, &b, &a );
- colorArray[0] = r;
- colorArray[1] = g;
- colorArray[2] = b;
- colorArray[3] = a;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: initializes the scheme manager
-// loading the scheme files for the current resolution
-// Input : xRes -
-// yRes - dimensions of output window
-//-----------------------------------------------------------------------------
-CSchemeManager::CSchemeManager( int xRes, int yRes )
-{
- // basic setup
- m_pSchemeList = NULL;
- m_iNumSchemes = 0;
-
- // find the closest matching scheme file to our resolution
- char token[1024];
- char *pFile = (char*)LoadFileByResolution( "", xRes, "_textscheme.txt" );
- m_xRes = xRes;
-
- char *pFileStart = pFile;
-
- byte *pFontData;
- int fontFileLength;
- char fontFilename[512];
-
- //
- // Read the scheme descriptions from the text file, into a temporary array
- // format is simply:
- // =
- //
- // a of "SchemeName" signals a new scheme is being described
- //
-
- const static int numTmpSchemes = 64;
- static CScheme tmpSchemes[numTmpSchemes];
- memset( tmpSchemes, 0, sizeof(tmpSchemes) );
- int currentScheme = -1;
- CScheme *pScheme = NULL;
-
- if ( !pFile )
- {
- gEngfuncs.Con_DPrintf( "Unable to find *_textscheme.txt\n");
- goto buildDefaultFont;
- }
-
- // record what has been entered so we can create defaults from the different values
- bool hasFgColor, hasBgColor, hasArmedFgColor, hasArmedBgColor, hasMouseDownFgColor, hasMouseDownBgColor;
-
- pFile = gEngfuncs.COM_ParseFile( pFile, token );
- while ( strlen(token) > 0 && (currentScheme < numTmpSchemes) )
- {
- // get the paramName name
- static const int tokenSize = 64;
- char paramName[tokenSize], paramValue[tokenSize];
-
- strncpy( paramName, token, tokenSize );
- paramName[tokenSize-1] = 0; // ensure null termination
-
- // get the '=' character
- pFile = gEngfuncs.COM_ParseFile( pFile, token );
- if ( stricmp( token, "=" ) )
- {
- if ( currentScheme < 0 )
- {
- gEngfuncs.Con_Printf( "error parsing font scheme text file at file start - expected '=', found '%s''\n", token );
- }
- else
- {
- gEngfuncs.Con_Printf( "error parsing font scheme text file at scheme '%s' - expected '=', found '%s''\n", tmpSchemes[currentScheme].schemeName, token );
- }
- break;
- }
-
- // get paramValue
- pFile = gEngfuncs.COM_ParseFile( pFile, token );
- strncpy( paramValue, token, tokenSize );
- paramValue[tokenSize-1] = 0; // ensure null termination
-
- // is this a new scheme?
- if ( !stricmp(paramName, "SchemeName") )
- {
- // setup the defaults for the current scheme
- if ( pScheme )
- {
- // foreground color defaults (normal -> armed -> mouse down)
- if ( !hasFgColor )
- {
- pScheme->fgColor[0] = pScheme->fgColor[1] = pScheme->fgColor[2] = pScheme->fgColor[3] = 255;
- }
- if ( !hasArmedFgColor )
- {
- memcpy( pScheme->armedFgColor, pScheme->fgColor, sizeof(pScheme->armedFgColor) );
- }
- if ( !hasMouseDownFgColor )
- {
- memcpy( pScheme->mousedownFgColor, pScheme->armedFgColor, sizeof(pScheme->mousedownFgColor) );
- }
-
- // background color (normal -> armed -> mouse down)
- if ( !hasBgColor )
- {
- pScheme->bgColor[0] = pScheme->bgColor[1] = pScheme->bgColor[2] = pScheme->bgColor[3] = 0;
- }
- if ( !hasArmedBgColor )
- {
- memcpy( pScheme->armedBgColor, pScheme->bgColor, sizeof(pScheme->armedBgColor) );
- }
- if ( !hasMouseDownBgColor )
- {
- memcpy( pScheme->mousedownBgColor, pScheme->armedBgColor, sizeof(pScheme->mousedownBgColor) );
- }
-
- // font size
- if ( !pScheme->fontSize )
- {
- pScheme->fontSize = 17;
- }
- if ( !pScheme->fontName[0] )
- {
- strcpy( pScheme->fontName, "Arial" );
- }
- }
-
- // create the new scheme
- currentScheme++;
- pScheme = &tmpSchemes[currentScheme];
- hasFgColor = hasBgColor = hasArmedFgColor = hasArmedBgColor = hasMouseDownFgColor = hasMouseDownBgColor = false;
-
- strncpy( pScheme->schemeName, paramValue, CScheme::SCHEME_NAME_LENGTH );
- pScheme->schemeName[CScheme::SCHEME_NAME_LENGTH-1] = '\0'; // ensure null termination of string
- }
-
- if ( !pScheme )
- {
- gEngfuncs.Con_Printf( "font scheme text file MUST start with a 'SchemeName'\n");
- break;
- }
-
- // pull the data out into the scheme
- if ( !stricmp(paramName, "FontName") )
- {
- strncpy( pScheme->fontName, paramValue, CScheme::FONT_NAME_LENGTH );
- pScheme->fontName[CScheme::FONT_NAME_LENGTH-1] = 0;
- }
- else if ( !stricmp(paramName, "FontSize") )
- {
- pScheme->fontSize = atoi( paramValue );
- }
- else if ( !stricmp(paramName, "FontWeight") )
- {
- pScheme->fontWeight = atoi( paramValue );
- }
- else if ( !stricmp(paramName, "FgColor") )
- {
- ParseRGBAFromString( pScheme->fgColor, paramValue );
- hasFgColor = true;
- }
- else if ( !stricmp(paramName, "BgColor") )
- {
- ParseRGBAFromString( pScheme->bgColor, paramValue );
- hasBgColor = true;
- }
- else if ( !stricmp(paramName, "FgColorArmed") )
- {
- ParseRGBAFromString( pScheme->armedFgColor, paramValue );
- hasArmedFgColor = true;
- }
- else if ( !stricmp(paramName, "BgColorArmed") )
- {
- ParseRGBAFromString( pScheme->armedBgColor, paramValue );
- hasArmedBgColor = true;
- }
- else if ( !stricmp(paramName, "FgColorMousedown") )
- {
- ParseRGBAFromString( pScheme->mousedownFgColor, paramValue );
- hasMouseDownFgColor = true;
- }
- else if ( !stricmp(paramName, "BgColorMousedown") )
- {
- ParseRGBAFromString( pScheme->mousedownBgColor, paramValue );
- hasMouseDownBgColor = true;
- }
- else if ( !stricmp(paramName, "BorderColor") )
- {
- ParseRGBAFromString( pScheme->borderColor, paramValue );
- hasMouseDownBgColor = true;
- }
-
- // get the new token last, so we now if the loop needs to be continued or not
- pFile = gEngfuncs.COM_ParseFile( pFile, token );
- }
-
- // free the file
- gEngfuncs.COM_FreeFile( pFileStart );
-
-
-buildDefaultFont:
-
- // make sure we have at least 1 valid font
- if ( currentScheme < 0 )
- {
- currentScheme = 0;
- strcpy( tmpSchemes[0].schemeName, "Default Scheme" );
- strcpy( tmpSchemes[0].fontName, "Arial" );
- tmpSchemes[0].fontSize = 0;
- tmpSchemes[0].fgColor[0] = tmpSchemes[0].fgColor[1] = tmpSchemes[0].fgColor[2] = tmpSchemes[0].fgColor[3] = 255;
- tmpSchemes[0].armedFgColor[0] = tmpSchemes[0].armedFgColor[1] = tmpSchemes[0].armedFgColor[2] = tmpSchemes[0].armedFgColor[3] = 255;
- tmpSchemes[0].mousedownFgColor[0] = tmpSchemes[0].mousedownFgColor[1] = tmpSchemes[0].mousedownFgColor[2] = tmpSchemes[0].mousedownFgColor[3] = 255;
- }
-
- // we have the full list of schemes in the tmpSchemes array
- // now allocate the correct sized list
- m_iNumSchemes = currentScheme + 1; // 0-based index
- m_pSchemeList = new CScheme[ m_iNumSchemes ];
-
- // copy in the data
- memcpy( m_pSchemeList, tmpSchemes, sizeof(CScheme) * m_iNumSchemes );
-
- // create the fonts
- for ( int i = 0; i < m_iNumSchemes; i++ )
- {
- m_pSchemeList[i].font = NULL;
-
- // see if the current font values exist in a previously loaded font
- for ( int j = 0; j < i; j++ )
- {
- // check if the font name, size, and weight are the same
- if ( !stricmp(m_pSchemeList[i].fontName, m_pSchemeList[j].fontName)
- && m_pSchemeList[i].fontSize == m_pSchemeList[j].fontSize
- && m_pSchemeList[i].fontWeight == m_pSchemeList[j].fontWeight )
- {
- // copy the pointer, but mark i as not owning it
- m_pSchemeList[i].font = m_pSchemeList[j].font;
- m_pSchemeList[i].ownFontPointer = false;
- }
- }
-
- // if we haven't found the font already, load it ourselves
- if ( !m_pSchemeList[i].font )
- {
- fontFileLength = -1;
- pFontData = NULL;
-
- if(g_CV_BitmapFonts && g_CV_BitmapFonts->value)
- {
- sprintf(fontFilename, "gfx\\vgui\\fonts\\%d_%s.tga", m_xRes, m_pSchemeList[i].schemeName);
- pFontData = gEngfuncs.COM_LoadFile( fontFilename, 5, &fontFileLength );
- if(!pFontData)
- gEngfuncs.Con_Printf("Missing bitmap font: %s\n", fontFilename);
- }
-
- m_pSchemeList[i].font = new vgui::Font(
- m_pSchemeList[i].fontName,
- pFontData,
- fontFileLength,
- m_pSchemeList[i].fontSize,
- 0,
- 0,
- m_pSchemeList[i].fontWeight,
- false,
- false,
- false,
- false);
-
- m_pSchemeList[i].ownFontPointer = true;
- }
-
- // fix up alpha values; VGUI uses 1-A (A=0 being solid, A=255 transparent)
- m_pSchemeList[i].fgColor[3] = 255 - m_pSchemeList[i].fgColor[3];
- m_pSchemeList[i].bgColor[3] = 255 - m_pSchemeList[i].bgColor[3];
- m_pSchemeList[i].armedFgColor[3] = 255 - m_pSchemeList[i].armedFgColor[3];
- m_pSchemeList[i].armedBgColor[3] = 255 - m_pSchemeList[i].armedBgColor[3];
- m_pSchemeList[i].mousedownFgColor[3] = 255 - m_pSchemeList[i].mousedownFgColor[3];
- m_pSchemeList[i].mousedownBgColor[3] = 255 - m_pSchemeList[i].mousedownBgColor[3];
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: frees all the memory used by the scheme manager
-//-----------------------------------------------------------------------------
-CSchemeManager::~CSchemeManager()
-{
- delete [] m_pSchemeList;
- m_iNumSchemes = 0;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Finds a scheme in the list, by name
-// Input : char *schemeName - string name of the scheme
-// Output : SchemeHandle_t handle to the scheme
-//-----------------------------------------------------------------------------
-SchemeHandle_t CSchemeManager::getSchemeHandle( const char *schemeName )
-{
- // iterate through the list
- for ( int i = 0; i < m_iNumSchemes; i++ )
- {
- if ( !stricmp(schemeName, m_pSchemeList[i].schemeName) )
- return i;
- }
-
- return 0;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: always returns a valid scheme handle
-// Input : schemeHandle -
-// Output : CScheme
-//-----------------------------------------------------------------------------
-CSchemeManager::CScheme *CSchemeManager::getSafeScheme( SchemeHandle_t schemeHandle )
-{
- ASSERT(schemeHandle >= 0);
- ASSERT(schemeHandle < m_iNumSchemes);
-
- if ( schemeHandle < m_iNumSchemes )
- return m_pSchemeList + schemeHandle;
-
- return m_pSchemeList;
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Returns the schemes pointer to a font
-// Input : schemeHandle -
-// Output : vgui::Font
-//-----------------------------------------------------------------------------
-vgui::Font *CSchemeManager::getFont( SchemeHandle_t schemeHandle )
-{
- return getSafeScheme( schemeHandle )->font;
-}
-
-void CSchemeManager::getFgColor( SchemeHandle_t schemeHandle, int &r, int &g, int &b, int &a )
-{
- CScheme *pScheme = getSafeScheme( schemeHandle );
- r = pScheme->fgColor[0];
- g = pScheme->fgColor[1];
- b = pScheme->fgColor[2];
- a = pScheme->fgColor[3];
-}
-
-void CSchemeManager::getBgColor( SchemeHandle_t schemeHandle, int &r, int &g, int &b, int &a )
-{
- CScheme *pScheme = getSafeScheme( schemeHandle );
- r = pScheme->bgColor[0];
- g = pScheme->bgColor[1];
- b = pScheme->bgColor[2];
- a = pScheme->bgColor[3];
-}
-
-void CSchemeManager::getFgArmedColor( SchemeHandle_t schemeHandle, int &r, int &g, int &b, int &a )
-{
- CScheme *pScheme = getSafeScheme( schemeHandle );
- r = pScheme->armedFgColor[0];
- g = pScheme->armedFgColor[1];
- b = pScheme->armedFgColor[2];
- a = pScheme->armedFgColor[3];
-}
-
-void CSchemeManager::getBgArmedColor( SchemeHandle_t schemeHandle, int &r, int &g, int &b, int &a )
-{
- CScheme *pScheme = getSafeScheme( schemeHandle );
- r = pScheme->armedBgColor[0];
- g = pScheme->armedBgColor[1];
- b = pScheme->armedBgColor[2];
- a = pScheme->armedBgColor[3];
-}
-
-void CSchemeManager::getFgMousedownColor( SchemeHandle_t schemeHandle, int &r, int &g, int &b, int &a )
-{
- CScheme *pScheme = getSafeScheme( schemeHandle );
- r = pScheme->mousedownFgColor[0];
- g = pScheme->mousedownFgColor[1];
- b = pScheme->mousedownFgColor[2];
- a = pScheme->mousedownFgColor[3];
-}
-
-void CSchemeManager::getBgMousedownColor( SchemeHandle_t schemeHandle, int &r, int &g, int &b, int &a )
-{
- CScheme *pScheme = getSafeScheme( schemeHandle );
- r = pScheme->mousedownBgColor[0];
- g = pScheme->mousedownBgColor[1];
- b = pScheme->mousedownBgColor[2];
- a = pScheme->mousedownBgColor[3];
-}
-
-void CSchemeManager::getBorderColor( SchemeHandle_t schemeHandle, int &r, int &g, int &b, int &a )
-{
- CScheme *pScheme = getSafeScheme( schemeHandle );
- r = pScheme->borderColor[0];
- g = pScheme->borderColor[1];
- b = pScheme->borderColor[2];
- a = pScheme->borderColor[3];
-}
-
-
-
+//=========== (C) Copyright 1996-2002 Valve, L.L.C. All rights reserved. ===========
+//
+// The copyright to the contents herein is the property of Valve, L.L.C.
+// The contents may be used and/or copied only with the written permission of
+// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
+// the agreement/contract under which the contents have been supplied.
+//
+// Purpose:
+//
+// $Workfile: $
+// $Date: 2001/09/13 15:01:48 $
+//
+//-----------------------------------------------------------------------------
+// $Log: vgui_SchemeManager.cpp,v $
+// Revision 1.3 2001/09/13 15:01:48 Charlie
+// - Merging with 1108
+//
+// Revision 1.2 2001/09/12 16:34:26 Charlie
+// - Slightly better error checking
+// Revision 1.1.1.1.2.2 2001/09/13 14:42:30 Charlie
+// - HL1108
+//
+// Revision 1.1.1.1 2000/06/17 14:12:45 charlie
+// Final version of new HL SDK. May not compile.
+// Previous versions of my MSVC project files and utility .bat files.
+// This is my starting point; there is no mod-specific code in here.
+//
+//
+// $NoKeywords: $
+//=============================================================================
+
+#include "hud.h"
+#include "vgui_SchemeManager.h"
+#include "common/cvardef.h"
+
+#include
+
+
+cvar_t *g_CV_BitmapFonts;
+
+
+void Scheme_Init()
+{
+ g_CV_BitmapFonts = gEngfuncs.pfnRegisterVariable("bitmapfonts", "1", 0);
+}
+
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Scheme managers data container
+//-----------------------------------------------------------------------------
+class CSchemeManager::CScheme
+{
+public:
+ enum {
+ SCHEME_NAME_LENGTH = 32,
+ FONT_NAME_LENGTH = 48,
+ FONT_FILENAME_LENGTH = 64,
+ };
+
+ // name
+ char schemeName[SCHEME_NAME_LENGTH];
+
+ // font
+ char fontName[FONT_NAME_LENGTH];
+
+ int fontSize;
+ int fontWeight;
+
+ vgui::Font *font;
+ int ownFontPointer; // true if the font is ours to delete
+
+ // scheme
+ byte fgColor[4];
+ byte bgColor[4];
+ byte armedFgColor[4];
+ byte armedBgColor[4];
+ byte mousedownFgColor[4];
+ byte mousedownBgColor[4];
+ byte borderColor[4];
+
+ // construction/destruction
+ CScheme();
+ ~CScheme();
+};
+
+CSchemeManager::CScheme::CScheme()
+{
+ schemeName[0] = 0;
+ fontName[0] = 0;
+ fontSize = 0;
+ fontWeight = 0;
+ font = NULL;
+ ownFontPointer = false;
+}
+
+CSchemeManager::CScheme::~CScheme()
+{
+ // only delete our font pointer if we own it
+ if ( ownFontPointer )
+ {
+ delete font;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: resolution information
+// !! needs to be shared out
+//-----------------------------------------------------------------------------
+static int g_ResArray[] =
+{
+ 320,
+ 400,
+ 512,
+ 640,
+ 800,
+ 1024,
+ 1152,
+ 1280,
+ 1600
+};
+static int g_NumReses = sizeof(g_ResArray) / sizeof(int);
+
+static byte *LoadFileByResolution( const char *filePrefix, int xRes, const char *filePostfix )
+{
+ // find our resolution in the res array
+ int resNum = g_NumReses - 1;
+ while ( g_ResArray[resNum] > xRes )
+ {
+ resNum--;
+
+ if ( resNum < 0 )
+ return NULL;
+ }
+
+ // try open the file
+ byte *pFile = NULL;
+ while ( 1 )
+ {
+
+ // try load
+ char fname[256];
+ sprintf( fname, "%s%d%s", filePrefix, g_ResArray[resNum], filePostfix );
+ pFile = gEngfuncs.COM_LoadFile( fname, 5, NULL );
+
+ if ( pFile )
+ break;
+
+ if ( resNum == 0 )
+ return NULL;
+
+ resNum--;
+ };
+
+ return pFile;
+}
+
+static void ParseRGBAFromString( byte colorArray[4], const char *colorVector )
+{
+ int r, g, b, a;
+ sscanf( colorVector, "%d %d %d %d", &r, &g, &b, &a );
+ colorArray[0] = r;
+ colorArray[1] = g;
+ colorArray[2] = b;
+ colorArray[3] = a;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: initializes the scheme manager
+// loading the scheme files for the current resolution
+// Input : xRes -
+// yRes - dimensions of output window
+//-----------------------------------------------------------------------------
+CSchemeManager::CSchemeManager( int xRes, int yRes )
+{
+ // basic setup
+ m_pSchemeList = NULL;
+ m_iNumSchemes = 0;
+
+ // find the closest matching scheme file to our resolution
+ char token[1024];
+ char *pFile = (char*)LoadFileByResolution( "", xRes, "_textscheme.txt" );
+ m_xRes = xRes;
+
+ char *pFileStart = pFile;
+
+ byte *pFontData;
+ int fontFileLength;
+ char fontFilename[512];
+
+ //
+ // Read the scheme descriptions from the text file, into a temporary array
+ // format is simply:
+ // =
+ //
+ // a