2004-08-23 00:15:46 +00:00
/*
teamplay . c
Teamplay enhancements
Copyright ( C ) 2000 - 2001 Anton Gavrilov
This program is free software ; you can redistribute it and / or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation ; either version 2
of the License , or ( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE .
See the GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to :
Free Software Foundation , Inc .
59 Temple Place - Suite 330
Boston , MA 02111 - 1307 , USA
*/
//Hacked by spike.
//things to fix:
//TP_SearchForMsgTriggers: should only allow safe commands. work out what the meaning of safe commands is.
2005-02-28 07:16:19 +00:00
# include "quakedef.h"
2004-08-23 00:15:46 +00:00
2004-09-20 23:25:38 +00:00
//#include "version.h"
2004-08-23 00:15:46 +00:00
# include "sound.h"
//#include "pmove.h"
# include <time.h>
2004-09-20 23:25:38 +00:00
# include <ctype.h>
2004-08-23 00:15:46 +00:00
typedef qboolean qbool ;
# define SP 0
# define Com_Printf Con_Printf
# define strlcpy Q_strncpyz
2006-05-17 23:01:06 +00:00
# define strlcat Q_strncatz
2020-04-19 01:23:32 +00:00
# define Q_stricmp strcasecmp
# define Q_strnicmp strncasecmp
2004-08-23 00:15:46 +00:00
2005-04-26 16:04:12 +00:00
extern int cl_spikeindex , cl_playerindex , cl_h_playerindex , cl_flagindex , cl_rocketindex , cl_grenadeindex , cl_gib1index , cl_gib2index , cl_gib3index ;
2017-09-21 12:22:16 +00:00
extern cvar_t v_viewheight , dpcompat_console ;
2005-04-26 16:04:12 +00:00
trace_t PM_TraceLine ( vec3_t start , vec3_t end ) ;
# define ISDEAD(i) ( (i) >= 41 && (i) <= 102 )
qboolean suppress ;
//note: csqc obsoletes and even breaks much of this stuff.
//cl.simorg is no longer valid, cl.viewangles isn't terribly valid either.
2004-09-20 23:25:38 +00:00
/*#define isalpha(x) (((x) >= 'a' && (x) <= 'z') || ((x) >= 'A' && (x) <= 'Z'))
2004-08-23 00:15:46 +00:00
# define isdigit(x) ((x) >= '0' && (x) <= '9')
# define isxdigit(x) (isdigit(x) || ((x) >= 'a' && (x) <= 'f'))
2004-09-20 23:25:38 +00:00
*/
2004-08-23 00:15:46 +00:00
# define Q_rint(f) ((int)((f)+0.5))
2006-04-12 00:17:02 +00:00
// callbacks used for TP cvars
2019-09-17 19:49:39 +00:00
# ifdef QWSKINS
2015-04-21 04:12:00 +00:00
static void QDECL TP_SkinCvar_Callback ( struct cvar_s * var , char * oldvalue ) ;
2019-09-17 19:49:39 +00:00
static void QDECL TP_TeamColor_CB ( struct cvar_s * var , char * oldvalue ) ;
static void QDECL TP_EnemyColor_CB ( struct cvar_s * var , char * oldvalue ) ;
Too many changes, sorry.
Change revision displays, use the SVN commit date instead of using __DATE__ (when there's no local changes). This should allow reproducible builds.
Added s_al_disable cvar, to block openal and all the various problems people have had with it, without having to name an explicit fallback (which would vary by system).
Add mastervolume cvar (for ss).
Add r_shadows 2 (aka fake shadows - for ss).
Add scr_loadingscreen_aspect -1 setting, to disable levelshots entirely, also disables the progress bar (for ss).
Better support for some effectinfo hacks (for ss).
Added dpcompat_nocsqcwarnings (because of lazy+buggy mods like ss).
Rework the dpcsqc versions of project+unproject builtins for better compat (for ss).
Added dpcompat_csqcinputeventtypes to block unexpected csqc input events (for ss).
Better compat with DP's loadfont console command (for ss).
Added dpcompat_smallerfonts cvar to replicate a DP bug (for ss).
Detect dp's m_draw extension, to work around it (for ss).
Cvar dpcompat_ignoremodificationtimes added. A value of 0 favour the most recently modified file, 1 will use DP-like alphabetically sorted preferences (for ss).
loadfont builtin can now accept outline=1 in the sizes arg for slightly more readable fonts.
Fix bbox calcs for rotated entities, fix needed for r_ignorenetpvs 0.
Hackily parse emoji.json to provide :poop: etc suggestions.
Skip prediction entirely when there's no local entity info. This fixes stair-smoothing in xonotic.
screenshot_cubemap will now capture half-float images when saving to ktx or dds files.
Fix support for xcf files larger than 4gb, mostly to avoid compiler warnings.
Fixed size of gfx/loading.lmp when replacement textures are used.
Added mipmap support for rg8 and l8a8 textures.
r_hdr_framebuffer cvar updated to support format names instead of random negative numbers. Description updated to name some interesting ones.
Perform autoupdate _checks_ ONLY with explicit user confirmation (actual updating already needed user confirmation, but this extra step should reduce the chances of us getting wrongly accused of exfiltrating user data if we're run in a sandbox - we ONLY ever included the updating engine's version in the checks, though there's nothing we can do to avoid sending the user's router's IP).
Removed the 'summon satan all over your harddrive' quit message, in case paranoid security researchers are idiots and don't bother doing actual research.
Removed the triptohell.info and fte.triptohell.info certificates, they really need to stop being self-signed. The updates domain is still self-signed for autoupdates.
Video drivers are now able to report supported video resolutions, visible to menuqc. Currently only works with SDL2 builds.
Added setmousepos builtin. Should work with glx+win32 build.
VF_SKYROOM_CAMERA can now accept an extra two args, setviewprop(VF_SKYROOM_CAMERA, org, axis, degrees).
Removed v_skyroom_origin+v_skyroom_orientation cvars in favour just v_skyroom, which should make it behave more like the 'fog' command (used when csqc isn't overriding).
Added R_EndPolygonRibbon builtin to make it faster+easier to generate textured ribbon/cable/etc wide lines (for TW).
sdl: Fix up sys_sdl.c's file enumeration to support wildcards in directories.
edit command now displays end1.bin/end2.bin correctly, because we can.
Finally add support for f_modified - though ruleset_allow_larger_models and ruleset_allow_overlong_sounds generally make it redundant.
Fix threading race condition in sha1 lookups.
Updated f_ruleset to include the same extra flags reported by ezquake.
A mod's default.fmf file can now contain an eg 'mainconfig config.cfg' line (to explicitly set the main config saved with cfg_save_auto 1 etc).
fmf: basegame steam:GameName/GameDir can be used to try to load a mod directory from an installed steam game. The resulting gamedir will be read-only.
HOMEDIR CHANGE: use homedirs only if the basedir cannot be written or a homedir already exists, which should further reduce the probability of microsoft randomly uploading our data to their cloud (but mostly because its annoying to never know where your data is written).
Fixed buf_cvarlist, should work in xonotic now, and without segfaults.
Added an extra arg to URI_Get_Callback calls - the response size, also changed the tempstring to contain all bytes of the response, you need to be careful about nulls though.
Try to work around nvidia's forced-panning bug on x11 when changing video modes. This might screw with other programs.
sdl: support custom icons.
sdl: support choosing a specific display.
Added some documentation to menuqc builtins.
menusys: use outlines for slightly more readable fonts.
menusys: switch vid_width and vid_height combos into a single video mode combo to set both according to reported video modes.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5581 fc73d0e0-1445-4013-8a0c-d673dee63da5
2019-11-20 03:09:50 +00:00
//cvar_t enemyforceskins = CVARD("enemyforceskins", "0", "0: Read the skin as-is.\n1: Use the player's name instead of their skin setting.\n2: Use their userid (probably too unreliable).3: Use a per-team player index.\n");
//cvar_t teamforceskins = CVARD("enemyforceskins", "0", "0: Read the skin as-is.\n1: Use the player's name instead of their skin setting.\n2: Use their userid (probably too unreliable).3: Use a per-team player index.\n");
2019-09-17 19:49:39 +00:00
# define TP_SKIN_CVARS \
TP_CVARAC ( cl_teamskin , " " , teamskin , TP_SkinCvar_Callback ) ; \
TP_CVARAC ( cl_enemyskin , " " , enemyskin , TP_SkinCvar_Callback ) ; \
TP_CVARC ( enemycolor , " off " , TP_EnemyColor_CB ) ; \
TP_CVARC ( teamcolor , " off " , TP_TeamColor_CB ) ;
# else
# define TP_SKIN_CVARS
# endif
2020-04-19 01:23:32 +00:00
# ifdef QUAKESTATS
# define TP_NAME_CVARS \
2005-02-28 07:16:19 +00:00
TP_CVAR ( tp_name_none , " " ) ; \
TP_CVAR ( tp_name_axe , " axe " ) ; \
TP_CVAR ( tp_name_sg , " sg " ) ; \
TP_CVAR ( tp_name_ssg , " ssg " ) ; \
TP_CVAR ( tp_name_ng , " ng " ) ; \
TP_CVAR ( tp_name_sng , " sng " ) ; \
TP_CVAR ( tp_name_gl , " gl " ) ; \
TP_CVAR ( tp_name_rl , " rl " ) ; \
TP_CVAR ( tp_name_lg , " lg " ) ; \
TP_CVAR ( tp_name_ra , " ra " ) ; \
TP_CVAR ( tp_name_ya , " ya " ) ; \
TP_CVAR ( tp_name_ga , " ga " ) ; \
TP_CVAR ( tp_name_quad , " quad " ) ; \
TP_CVAR ( tp_name_pent , " pent " ) ; \
TP_CVAR ( tp_name_ring , " ring " ) ; \
TP_CVAR ( tp_name_suit , " suit " ) ; \
TP_CVAR ( tp_name_shells , " shells " ) ; \
TP_CVAR ( tp_name_nails , " nails " ) ; \
TP_CVAR ( tp_name_rockets , " rockets " ) ; \
TP_CVAR ( tp_name_cells , " cells " ) ; \
TP_CVAR ( tp_name_mh , " mega " ) ; \
TP_CVAR ( tp_name_health , " health " ) ; \
TP_CVAR ( tp_name_backpack , " pack " ) ; \
TP_CVAR ( tp_name_flag , " flag " ) ; \
TP_CVAR ( tp_name_nothing , " nothing " ) ; \
TP_CVAR ( tp_name_at , " at " ) ; \
TP_CVAR ( tp_need_ra , " 50 " ) ; \
TP_CVAR ( tp_need_ya , " 50 " ) ; \
TP_CVAR ( tp_need_ga , " 50 " ) ; \
TP_CVAR ( tp_need_health , " 50 " ) ; \
TP_CVAR ( tp_need_weapon , " 35687 " ) ; \
TP_CVAR ( tp_need_rl , " 1 " ) ; \
TP_CVAR ( tp_need_rockets , " 5 " ) ; \
TP_CVAR ( tp_need_cells , " 20 " ) ; \
TP_CVAR ( tp_need_nails , " 40 " ) ; \
TP_CVAR ( tp_need_shells , " 10 " ) ; \
2005-04-26 16:04:12 +00:00
TP_CVAR ( tp_name_disp , " dispenser " ) ; \
TP_CVAR ( tp_name_sentry , " sentry gun " ) ; \
TP_CVAR ( tp_name_rune_1 , " resistance rune " ) ; \
TP_CVAR ( tp_name_rune_2 , " strength rune " ) ; \
TP_CVAR ( tp_name_rune_3 , " haste rune " ) ; \
TP_CVAR ( tp_name_rune_4 , " regeneration rune " ) ; \
\
TP_CVAR ( tp_name_status_red , " $R " ) ; \
TP_CVAR ( tp_name_status_green , " $G " ) ; \
TP_CVAR ( tp_name_status_yellow , " $Y " ) ; \
TP_CVAR ( tp_name_status_blue , " $B " ) ; \
\
TP_CVAR ( tp_name_armortype_ga , " g " ) ; \
TP_CVAR ( tp_name_armortype_ya , " y " ) ; \
TP_CVAR ( tp_name_armortype_ra , " r " ) ; \
TP_CVAR ( tp_name_armor , " armor " ) ; \
TP_CVAR ( tp_name_weapon , " weapon " ) ; \
TP_CVAR ( tp_weapon_order , " 78654321 " ) ; \
\
TP_CVAR ( tp_name_quaded , " quaded " ) ; \
TP_CVAR ( tp_name_pented , " pented " ) ; \
TP_CVAR ( tp_name_separator , " / " ) ; \
\
TP_CVAR ( tp_name_enemy , " enemy " ) ; \
TP_CVAR ( tp_name_teammate , " " ) ; \
2005-05-13 10:42:48 +00:00
TP_CVAR ( tp_name_eyes , " eyes " ) ; \
\
2011-06-07 23:54:58 +00:00
TP_CVAR ( loc_name_separator , " - " ) ; \
2005-05-13 10:42:48 +00:00
TP_CVAR ( loc_name_ssg , " ssg " ) ; \
TP_CVAR ( loc_name_ng , " ng " ) ; \
TP_CVAR ( loc_name_sng , " sng " ) ; \
TP_CVAR ( loc_name_gl , " gl " ) ; \
TP_CVAR ( loc_name_rl , " rl " ) ; \
TP_CVAR ( loc_name_lg , " lg " ) ; \
TP_CVAR ( loc_name_ga , " ga " ) ; \
TP_CVAR ( loc_name_ya , " ya " ) ; \
TP_CVAR ( loc_name_ra , " ra " ) ; \
2024-04-06 19:19:16 +00:00
TP_CVAR ( loc_name_mh , " mh " ) ; \
2005-05-13 10:42:48 +00:00
TP_CVAR ( loc_name_quad , " quad " ) ; \
TP_CVAR ( loc_name_pent , " pent " ) ; \
TP_CVAR ( loc_name_ring , " ring " ) ; \
2020-04-19 01:23:32 +00:00
TP_CVAR ( loc_name_suit , " suit " ) ;
# else
# define TP_NAME_CVARS
# endif
//a list of all the cvars
//this is down to the fact that I keep defining them but forgetting to register. :/
# define TP_CVARS \
TP_SKIN_CVARS \
TP_NAME_CVARS \
TP_CVAR ( cl_fakename , " " ) ; \
TP_CVAR ( cl_parseSay , " 1 " ) ; \
TP_CVAR ( cl_parseFunChars , " 1 " ) ; \
TP_CVAR ( cl_triggers , " 1 " ) ; \
TP_CVAR ( tp_autostatus , " " ) ; /* things which will not always change, but are useful */ \
TP_CVAR ( tp_forceTriggers , " 0 " ) ; \
TP_CVAR ( tp_loadlocs , " 1 " ) ; \
TP_CVAR ( tp_soundtrigger , " ~ " ) ; \
\
TP_CVAR ( tp_name_someplace , " someplace " )
2005-02-28 07:16:19 +00:00
//create the globals for all the TP cvars.
2010-07-11 02:22:39 +00:00
# define TP_CVAR(name,def) cvar_t name = CVAR(#name, def)
# define TP_CVARC(name,def,call) cvar_t name = CVARC(#name, def, call)
2015-04-14 23:12:17 +00:00
# define TP_CVARAC(name,def,name2,call) cvar_t name = CVARAFC(#name, def, #name2, 0, call)
2005-02-28 07:16:19 +00:00
TP_CVARS ;
# undef TP_CVAR
2006-04-12 00:17:02 +00:00
# undef TP_CVARC
2015-04-14 23:12:17 +00:00
# undef TP_CVARAC
2004-08-23 00:15:46 +00:00
extern cvar_t host_mapname ;
2020-04-19 01:23:32 +00:00
# define MAX_LOC_NAME 48
# ifdef QUAKESTATS
2004-09-30 22:25:55 +00:00
static void TP_FindModelNumbers ( void ) ;
static void TP_FindPoint ( void ) ;
2004-08-23 00:15:46 +00:00
// this structure is cleared after entering a new map
typedef struct tvars_s {
2008-11-09 22:29:28 +00:00
char autoteamstatus [ 256 ] ;
float autoteamstatus_time ;
2004-08-23 00:15:46 +00:00
int health ;
int items ;
int olditems ;
int stat_framecounts [ MAX_CL_STATS ] ;
int activeweapon ;
float respawntrigger_time ;
float deathtrigger_time ;
float f_version_reply_time ;
char lastdeathloc [ MAX_LOC_NAME ] ;
char tookname [ 32 ] ;
char tookloc [ MAX_LOC_NAME ] ;
float tooktime ;
int pointframe ; // cls.framecount for which point* vars are valid
char pointname [ 32 ] ;
vec3_t pointorg ;
char pointloc [ MAX_LOC_NAME ] ;
2005-02-28 07:16:19 +00:00
int droppedweapon ;
2011-05-15 13:23:13 +00:00
char lastdroploc [ MAX_LOC_NAME ] ;
2005-04-26 16:04:12 +00:00
int last_numenemies ;
int numenemies ;
int last_numfriendlies ;
int numfriendlies ;
int enemy_powerups ;
float enemy_powerups_time ;
float lastdrop_time ;
2020-04-19 01:23:32 +00:00
char lasttrigger_match [ 256 ] ;
2005-04-26 16:04:12 +00:00
enum {
POINT_TYPE_ENEMY ,
POINT_TYPE_TEAMMATE ,
POINT_TYPE_POWERUP ,
POINT_TYPE_ITEM
} pointtype ;
float pointtime ;
2004-08-23 00:15:46 +00:00
} tvars_t ;
2020-04-19 01:23:32 +00:00
static tvars_t vars ;
# endif
2004-08-23 00:15:46 +00:00
2005-04-26 16:04:12 +00:00
typedef struct item_vis_s {
vec3_t vieworg ;
vec3_t forward ;
vec3_t right ;
vec3_t up ;
vec3_t entorg ;
float radius ;
2011-05-15 13:23:13 +00:00
vec3_t dir ;
float dist ;
2005-04-26 16:04:12 +00:00
} item_vis_t ;
# define TP_TOOK_EXPIRE_TIME 15
# define TP_POINT_EXPIRE_TIME TP_TOOK_EXPIRE_TIME
2004-08-23 00:15:46 +00:00
//===========================================================================
// TRIGGERS
//===========================================================================
2015-06-16 23:53:58 +00:00
void TP_ExecTrigger ( char * s , qboolean indemos )
2004-08-23 00:15:46 +00:00
{
char * astr ;
2015-06-16 23:53:58 +00:00
if ( ! cl_triggers . value )
return ;
if ( ! indemos & & cls . demoplayback )
2004-08-23 00:15:46 +00:00
return ;
astr = Cmd_AliasExist ( s , RESTRICT_LOCAL ) ;
if ( astr )
{
char * p ;
qbool quote = false ;
for ( p = astr ; * p ; p + + )
{
if ( * p = = ' " ' )
quote = ! quote ;
if ( ! quote & & * p = = ' ; ' )
{
// more than one command, add it to the command buffer
Cbuf_AddText ( astr , RESTRICT_LOCAL ) ;
Cbuf_AddText ( " \n " , RESTRICT_LOCAL ) ;
return ;
}
}
// a single line, so execute it right away
Cmd_ExecuteString ( astr , RESTRICT_LOCAL ) ;
return ;
}
}
2020-04-19 01:23:32 +00:00
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
HELPER FUNCTIONS
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
static int TP_CountPlayers ( void )
{
int i , count ;
count = 0 ;
for ( i = 0 ; i < cl . allocated_client_slots ; i + + ) {
if ( cl . players [ i ] . name [ 0 ] & & ! cl . players [ i ] . spectator )
count + + ;
}
return count ;
}
static char * TP_PlayerTeam ( void )
{
return cl . players [ cl . playerview [ SP ] . playernum ] . team ;
}
static char * TP_EnemyTeam ( void )
{
int i ;
static char enemyteam [ MAX_INFO_KEY ] ;
char * myteam = TP_PlayerTeam ( ) ;
for ( i = 0 ; i < cl . allocated_client_slots ; i + + ) {
if ( cl . players [ i ] . name [ 0 ] & & ! cl . players [ i ] . spectator )
{
strcpy ( enemyteam , cl . players [ i ] . team ) ;
if ( strcmp ( myteam , cl . players [ i ] . team ) ! = 0 )
return enemyteam ;
}
}
return " " ;
}
static char * TP_PlayerName ( void )
{
return cl . players [ cl . playerview [ SP ] . playernum ] . name ;
}
static char * TP_EnemyName ( void )
{
int i ;
char * myname ;
static char enemyname [ MAX_SCOREBOARDNAME ] ;
myname = TP_PlayerName ( ) ;
for ( i = 0 ; i < cl . allocated_client_slots ; i + + ) {
if ( cl . players [ i ] . name [ 0 ] & & ! cl . players [ i ] . spectator )
{
strcpy ( enemyname , cl . players [ i ] . name ) ;
if ( ! strcmp ( enemyname , myname ) )
return enemyname ;
}
}
return " " ;
}
static char * TP_MapName ( void )
{
return host_mapname . string ;
}
char * TP_GenerateDemoName ( void )
{
if ( cl . playerview [ SP ] . spectator )
{ // FIXME: if tracking a player, use his name
return va ( " spec_%s_%s " ,
TP_PlayerName ( ) ,
TP_MapName ( ) ) ;
}
else
{ // guess game type and write demo name
int i = TP_CountPlayers ( ) ;
if ( cl . teamplay & & i > = 3 )
{ // Teamplay
return va ( " %s_%s_vs_%s_%s " ,
TP_PlayerName ( ) ,
TP_PlayerTeam ( ) ,
TP_EnemyTeam ( ) ,
TP_MapName ( ) ) ;
}
else
{
if ( i = = 2 )
{ // Duel
return va ( " %s_vs_%s_%s " ,
TP_PlayerName ( ) ,
TP_EnemyName ( ) ,
TP_MapName ( ) ) ;
}
else if ( i > 2 )
{ // FFA
return va ( " %s_ffa_%s " ,
TP_PlayerName ( ) ,
TP_MapName ( ) ) ;
}
else
{ // one player
return va ( " %s_%s " ,
TP_PlayerName ( ) ,
TP_MapName ( ) ) ;
}
}
}
}
2004-08-23 00:15:46 +00:00
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
MACRO FUNCTIONS
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
# define MAX_MACRO_VALUE 256
static char macro_buf [ MAX_MACRO_VALUE ] = " " ;
2020-04-19 01:23:32 +00:00
# ifdef QUAKESTATS
2004-08-23 00:15:46 +00:00
// buffer-size-safe helper functions
2004-09-30 22:25:55 +00:00
//static void MacroBuf_strcat (char *str) {
// strlcat (macro_buf, str, sizeof(macro_buf));
//}
static void MacroBuf_strcat_with_separator ( char * str ) {
2004-08-23 00:15:46 +00:00
if ( macro_buf [ 0 ] )
2007-10-14 18:38:44 +00:00
strlcat ( macro_buf , tp_name_separator . string , sizeof ( macro_buf ) ) ;
2004-08-23 00:15:46 +00:00
strlcat ( macro_buf , str , sizeof ( macro_buf ) ) ;
}
2016-07-15 12:26:24 +00:00
# endif
2004-08-23 00:15:46 +00:00
2004-09-30 22:25:55 +00:00
static char * Macro_Latency ( void )
2004-08-23 00:15:46 +00:00
{
sprintf ( macro_buf , " %i " , Q_rint ( cls . latency * 1000 ) ) ;
return macro_buf ;
}
2007-08-23 21:25:18 +00:00
static char * Macro_Gamedir ( void )
{
extern char gamedirfile [ ] ;
Q_snprintfz ( macro_buf , sizeof ( macro_buf ) , " %s " , gamedirfile ) ;
return macro_buf ;
}
2015-09-01 04:45:15 +00:00
# ifdef QUAKESTATS
2004-09-30 22:25:55 +00:00
static char * Macro_Health ( void )
2004-08-23 00:15:46 +00:00
{
2012-07-05 19:42:36 +00:00
sprintf ( macro_buf , " %i " , cl . playerview [ SP ] . stats [ STAT_HEALTH ] ) ;
2004-08-23 00:15:46 +00:00
return macro_buf ;
}
2004-09-30 22:25:55 +00:00
static char * Macro_Armor ( void )
2004-08-23 00:15:46 +00:00
{
2012-07-05 19:42:36 +00:00
sprintf ( macro_buf , " %i " , cl . playerview [ SP ] . stats [ STAT_ARMOR ] ) ;
2004-08-23 00:15:46 +00:00
return macro_buf ;
}
2004-09-30 22:25:55 +00:00
static char * Macro_Shells ( void )
2004-08-23 00:15:46 +00:00
{
2012-07-05 19:42:36 +00:00
sprintf ( macro_buf , " %i " , cl . playerview [ SP ] . stats [ STAT_SHELLS ] ) ;
2004-08-23 00:15:46 +00:00
return macro_buf ;
}
2004-09-30 22:25:55 +00:00
static char * Macro_Nails ( void )
2004-08-23 00:15:46 +00:00
{
2012-07-05 19:42:36 +00:00
sprintf ( macro_buf , " %i " , cl . playerview [ SP ] . stats [ STAT_NAILS ] ) ;
2004-08-23 00:15:46 +00:00
return macro_buf ;
}
2004-09-30 22:25:55 +00:00
static char * Macro_Rockets ( void )
2004-08-23 00:15:46 +00:00
{
2012-07-05 19:42:36 +00:00
sprintf ( macro_buf , " %i " , cl . playerview [ SP ] . stats [ STAT_ROCKETS ] ) ;
2004-08-23 00:15:46 +00:00
return macro_buf ;
}
2004-09-30 22:25:55 +00:00
static char * Macro_Cells ( void )
2004-08-23 00:15:46 +00:00
{
2012-07-05 19:42:36 +00:00
sprintf ( macro_buf , " %i " , cl . playerview [ SP ] . stats [ STAT_CELLS ] ) ;
2004-08-23 00:15:46 +00:00
return macro_buf ;
}
2004-09-30 22:25:55 +00:00
static char * Macro_Ammo ( void )
2004-08-23 00:15:46 +00:00
{
2012-07-05 19:42:36 +00:00
sprintf ( macro_buf , " %i " , cl . playerview [ SP ] . stats [ STAT_AMMO ] ) ;
2004-08-23 00:15:46 +00:00
return macro_buf ;
}
2005-02-28 07:16:19 +00:00
static char * Weapon_NumToString ( int wnum )
2004-08-23 00:15:46 +00:00
{
2005-02-28 07:16:19 +00:00
switch ( wnum )
2004-08-23 00:15:46 +00:00
{
2005-02-28 07:16:19 +00:00
case IT_AXE : return tp_name_axe . string ;
case IT_SHOTGUN : return tp_name_sg . string ;
case IT_SUPER_SHOTGUN : return tp_name_ssg . string ;
case IT_NAILGUN : return tp_name_ng . string ;
case IT_SUPER_NAILGUN : return tp_name_sng . string ;
case IT_GRENADE_LAUNCHER : return tp_name_gl . string ;
case IT_ROCKET_LAUNCHER : return tp_name_rl . string ;
case IT_LIGHTNING : return tp_name_lg . string ;
default : return tp_name_none . string ;
2004-08-23 00:15:46 +00:00
}
}
2005-02-28 07:16:19 +00:00
static char * Macro_Weapon ( void )
{
2012-07-05 19:42:36 +00:00
return Weapon_NumToString ( cl . playerview [ SP ] . stats [ STAT_ACTIVEWEAPON ] ) ;
2005-02-28 07:16:19 +00:00
}
static char * Macro_DroppedWeapon ( void )
{
return Weapon_NumToString ( vars . droppedweapon ) ;
}
2011-05-15 13:23:13 +00:00
static char * Macro_Weapons ( void ) {
2004-08-23 00:15:46 +00:00
macro_buf [ 0 ] = 0 ;
2012-07-05 19:42:36 +00:00
if ( cl . playerview [ SP ] . stats [ STAT_ITEMS ] & IT_LIGHTNING )
2005-02-28 07:16:19 +00:00
strcpy ( macro_buf , tp_name_lg . string ) ;
2012-07-05 19:42:36 +00:00
if ( cl . playerview [ SP ] . stats [ STAT_ITEMS ] & IT_ROCKET_LAUNCHER )
2005-02-28 07:16:19 +00:00
MacroBuf_strcat_with_separator ( tp_name_rl . string ) ;
2012-07-05 19:42:36 +00:00
if ( cl . playerview [ SP ] . stats [ STAT_ITEMS ] & IT_GRENADE_LAUNCHER )
2005-02-28 07:16:19 +00:00
MacroBuf_strcat_with_separator ( tp_name_gl . string ) ;
2012-07-05 19:42:36 +00:00
if ( cl . playerview [ SP ] . stats [ STAT_ITEMS ] & IT_SUPER_NAILGUN )
2005-02-28 07:16:19 +00:00
MacroBuf_strcat_with_separator ( tp_name_sng . string ) ;
2012-07-05 19:42:36 +00:00
if ( cl . playerview [ SP ] . stats [ STAT_ITEMS ] & IT_NAILGUN )
2005-02-28 07:16:19 +00:00
MacroBuf_strcat_with_separator ( tp_name_ng . string ) ;
2012-07-05 19:42:36 +00:00
if ( cl . playerview [ SP ] . stats [ STAT_ITEMS ] & IT_SUPER_SHOTGUN )
2005-02-28 07:16:19 +00:00
MacroBuf_strcat_with_separator ( tp_name_ssg . string ) ;
2012-07-05 19:42:36 +00:00
if ( cl . playerview [ SP ] . stats [ STAT_ITEMS ] & IT_SHOTGUN )
2005-02-28 07:16:19 +00:00
MacroBuf_strcat_with_separator ( tp_name_sg . string ) ;
2012-07-05 19:42:36 +00:00
if ( cl . playerview [ SP ] . stats [ STAT_ITEMS ] & IT_AXE )
2005-02-28 07:16:19 +00:00
MacroBuf_strcat_with_separator ( tp_name_axe . string ) ;
2011-05-15 13:23:13 +00:00
// if (!macro_buf[0])
2004-08-23 00:15:46 +00:00
// strlcpy(macro_buf, tp_name_none.string, sizeof(macro_buf));
return macro_buf ;
}
2004-09-30 22:25:55 +00:00
static char * Macro_WeaponAndAmmo ( void )
2004-08-23 00:15:46 +00:00
{
char buf [ sizeof ( macro_buf ) ] ;
Q_snprintfz ( buf , sizeof ( buf ) , " %s:%s " , Macro_Weapon ( ) , Macro_Ammo ( ) ) ;
strcpy ( macro_buf , buf ) ;
return macro_buf ;
}
2004-09-30 22:25:55 +00:00
static char * Macro_WeaponNum ( void )
2004-08-23 00:15:46 +00:00
{
2012-07-05 19:42:36 +00:00
switch ( cl . playerview [ SP ] . stats [ STAT_ACTIVEWEAPON ] )
2004-08-23 00:15:46 +00:00
{
case IT_AXE : return " 1 " ;
case IT_SHOTGUN : return " 2 " ;
case IT_SUPER_SHOTGUN : return " 3 " ;
case IT_NAILGUN : return " 4 " ;
case IT_SUPER_NAILGUN : return " 5 " ;
case IT_GRENADE_LAUNCHER : return " 6 " ;
case IT_ROCKET_LAUNCHER : return " 7 " ;
case IT_LIGHTNING : return " 8 " ;
default :
return " 0 " ;
}
}
2004-09-30 22:25:55 +00:00
static int _Macro_BestWeapon ( void )
2004-08-23 00:15:46 +00:00
{
2005-04-26 16:04:12 +00:00
int i ;
2011-05-15 13:23:13 +00:00
char * t [ ] = { tp_weapon_order . string , " 78654321 " , NULL } , * * s ;
2005-04-26 16:04:12 +00:00
for ( s = t ; * s ; s + + )
{
for ( i = 0 ; i < strlen ( * s ) ; i + + )
{
switch ( ( * s ) [ i ] ) {
2012-07-05 19:42:36 +00:00
case ' 1 ' : if ( cl . playerview [ SP ] . stats [ STAT_ITEMS ] & IT_AXE ) return IT_AXE ; break ;
case ' 2 ' : if ( cl . playerview [ SP ] . stats [ STAT_ITEMS ] & IT_SHOTGUN ) return IT_SHOTGUN ; break ;
case ' 3 ' : if ( cl . playerview [ SP ] . stats [ STAT_ITEMS ] & IT_SUPER_SHOTGUN ) return IT_SUPER_SHOTGUN ; break ;
case ' 4 ' : if ( cl . playerview [ SP ] . stats [ STAT_ITEMS ] & IT_NAILGUN ) return IT_NAILGUN ; break ;
case ' 5 ' : if ( cl . playerview [ SP ] . stats [ STAT_ITEMS ] & IT_SUPER_NAILGUN ) return IT_SUPER_NAILGUN ; break ;
case ' 6 ' : if ( cl . playerview [ SP ] . stats [ STAT_ITEMS ] & IT_GRENADE_LAUNCHER ) return IT_GRENADE_LAUNCHER ; break ;
case ' 7 ' : if ( cl . playerview [ SP ] . stats [ STAT_ITEMS ] & IT_ROCKET_LAUNCHER ) return IT_ROCKET_LAUNCHER ; break ;
case ' 8 ' : if ( cl . playerview [ SP ] . stats [ STAT_ITEMS ] & IT_LIGHTNING ) return IT_LIGHTNING ; break ;
2005-04-26 16:04:12 +00:00
}
}
}
return 0 ;
2004-08-23 00:15:46 +00:00
}
2004-09-30 22:25:55 +00:00
static char * Macro_BestWeapon ( void )
2004-08-23 00:15:46 +00:00
{
2005-02-28 07:16:19 +00:00
return Weapon_NumToString ( _Macro_BestWeapon ( ) ) ;
2004-08-23 00:15:46 +00:00
}
2004-09-30 22:25:55 +00:00
static char * Macro_BestAmmo ( void )
2004-08-23 00:15:46 +00:00
{
switch ( _Macro_BestWeapon ( ) )
{
2011-05-15 13:23:13 +00:00
case IT_SHOTGUN : case IT_SUPER_SHOTGUN :
2012-07-05 19:42:36 +00:00
sprintf ( macro_buf , " %i " , cl . playerview [ SP ] . stats [ STAT_SHELLS ] ) ;
2004-08-23 00:15:46 +00:00
return macro_buf ;
case IT_NAILGUN : case IT_SUPER_NAILGUN :
2012-07-05 19:42:36 +00:00
sprintf ( macro_buf , " %i " , cl . playerview [ SP ] . stats [ STAT_NAILS ] ) ;
2004-08-23 00:15:46 +00:00
return macro_buf ;
case IT_GRENADE_LAUNCHER : case IT_ROCKET_LAUNCHER :
2012-07-05 19:42:36 +00:00
sprintf ( macro_buf , " %i " , cl . playerview [ SP ] . stats [ STAT_ROCKETS ] ) ;
2004-08-23 00:15:46 +00:00
return macro_buf ;
case IT_LIGHTNING :
2012-07-05 19:42:36 +00:00
sprintf ( macro_buf , " %i " , cl . playerview [ SP ] . stats [ STAT_CELLS ] ) ;
2004-08-23 00:15:46 +00:00
return macro_buf ;
default :
return " 0 " ;
}
}
// needed for %b parsing
2004-09-30 22:25:55 +00:00
static char * Macro_BestWeaponAndAmmo ( void )
2004-08-23 00:15:46 +00:00
{
char buf [ MAX_MACRO_VALUE ] ;
2011-07-22 15:11:35 +00:00
Q_snprintfz ( buf , sizeof ( buf ) , " %s:%s " , Macro_BestWeapon ( ) , Macro_BestAmmo ( ) ) ;
2004-08-23 00:15:46 +00:00
strcpy ( macro_buf , buf ) ;
return macro_buf ;
}
2004-09-30 22:25:55 +00:00
static char * Macro_ArmorType ( void )
2004-08-23 00:15:46 +00:00
{
2012-07-05 19:42:36 +00:00
if ( cl . playerview [ SP ] . stats [ STAT_ITEMS ] & IT_ARMOR1 )
2005-04-26 16:04:12 +00:00
return tp_name_armortype_ga . string ;
2012-07-05 19:42:36 +00:00
else if ( cl . playerview [ SP ] . stats [ STAT_ITEMS ] & IT_ARMOR2 )
2005-04-26 16:04:12 +00:00
return tp_name_armortype_ya . string ;
2012-07-05 19:42:36 +00:00
else if ( cl . playerview [ SP ] . stats [ STAT_ITEMS ] & IT_ARMOR3 )
2005-04-26 16:04:12 +00:00
return tp_name_armortype_ra . string ;
2004-08-23 00:15:46 +00:00
else
2005-04-26 16:04:12 +00:00
return tp_name_none . string ; // no armor at all
2004-08-23 00:15:46 +00:00
}
2004-09-30 22:25:55 +00:00
static char * Macro_Powerups ( void )
2004-08-23 00:15:46 +00:00
{
int effects ;
macro_buf [ 0 ] = 0 ;
2012-07-05 19:42:36 +00:00
if ( cl . playerview [ SP ] . stats [ STAT_ITEMS ] & IT_QUAD )
2007-10-14 18:38:44 +00:00
MacroBuf_strcat_with_separator ( tp_name_quad . string ) ;
2004-08-23 00:15:46 +00:00
2012-07-05 19:42:36 +00:00
if ( cl . playerview [ SP ] . stats [ STAT_ITEMS ] & IT_INVULNERABILITY )
2007-10-14 18:38:44 +00:00
MacroBuf_strcat_with_separator ( tp_name_pent . string ) ;
2004-08-23 00:15:46 +00:00
2012-07-05 19:42:36 +00:00
if ( cl . playerview [ SP ] . stats [ STAT_ITEMS ] & IT_INVISIBILITY )
2007-10-14 18:38:44 +00:00
MacroBuf_strcat_with_separator ( tp_name_ring . string ) ;
2004-08-23 00:15:46 +00:00
2013-06-23 02:17:02 +00:00
effects = cl . inframes [ cl . parsecount & UPDATE_MASK ] . playerstate [ cl . playerview [ SP ] . playernum ] . effects ;
2005-04-16 16:21:27 +00:00
if ( ( effects & ( QWEF_FLAG1 | QWEF_FLAG2 ) ) | | // CTF
2012-07-05 19:42:36 +00:00
( cl . teamfortress & & cl . playerview [ SP ] . stats [ STAT_ITEMS ] & ( IT_KEY1 | IT_KEY2 ) ) ) // TF
2007-10-14 18:38:44 +00:00
MacroBuf_strcat_with_separator ( tp_name_flag . string ) ;
2004-08-23 00:15:46 +00:00
return macro_buf ;
}
2015-09-01 04:45:15 +00:00
# endif
2004-08-23 00:15:46 +00:00
2004-09-30 22:25:55 +00:00
static char * Macro_Location ( void )
2004-08-23 00:15:46 +00:00
{
2012-07-05 19:42:36 +00:00
return TP_LocationName ( cl . playerview [ SP ] . simorg ) ;
2004-08-23 00:15:46 +00:00
}
2020-04-19 01:23:32 +00:00
# ifdef QUAKESTATS
2004-09-30 22:25:55 +00:00
static char * Macro_LastDeath ( void )
2004-08-23 00:15:46 +00:00
{
if ( vars . deathtrigger_time )
return vars . lastdeathloc ;
else
return tp_name_someplace . string ;
}
2005-04-26 16:04:12 +00:00
static char * Macro_Last_Location ( void )
2004-08-23 00:15:46 +00:00
{
if ( vars . deathtrigger_time & & realtime - vars . deathtrigger_time < = 5 )
return vars . lastdeathloc ;
return Macro_Location ( ) ;
}
// returns the last item picked up
2004-09-30 22:25:55 +00:00
static char * Macro_Took ( void )
2004-08-23 00:15:46 +00:00
{
if ( ! vars . tooktime | | realtime > vars . tooktime + 20 )
strlcpy ( macro_buf , tp_name_nothing . string , sizeof ( macro_buf ) ) ;
else
strcpy ( macro_buf , vars . tookname ) ;
return macro_buf ;
}
// returns location of the last item picked up
2004-09-30 22:25:55 +00:00
static char * Macro_TookLoc ( void )
2004-08-23 00:15:46 +00:00
{
if ( ! vars . tooktime | | realtime > vars . tooktime + 20 )
strlcpy ( macro_buf , tp_name_someplace . string , sizeof ( macro_buf ) ) ;
else
strcpy ( macro_buf , vars . tookloc ) ;
return macro_buf ;
}
// %i macro - last item picked up in "name at location" style
2004-09-30 22:25:55 +00:00
static char * Macro_TookAtLoc ( void )
2004-08-23 00:15:46 +00:00
{
if ( ! vars . tooktime | | realtime > vars . tooktime + 20 )
strncpy ( macro_buf , tp_name_nothing . string , sizeof ( macro_buf ) - 1 ) ;
else
{
strlcpy ( macro_buf , va ( " %s %s %s " , vars . tookname ,
tp_name_at . string , vars . tookloc ) , sizeof ( macro_buf ) ) ;
}
return macro_buf ;
}
// pointing calculations are CPU expensive, so the results are cached
// in vars.pointname & vars.pointloc
2004-09-30 22:25:55 +00:00
static char * Macro_PointName ( void )
2004-08-23 00:15:46 +00:00
{
if ( cls . framecount ! = vars . pointframe )
TP_FindPoint ( ) ;
return vars . pointname ;
}
2004-09-30 22:25:55 +00:00
static char * Macro_PointLocation ( void )
2004-08-23 00:15:46 +00:00
{
if ( cls . framecount ! = vars . pointframe )
TP_FindPoint ( ) ;
if ( vars . pointloc [ 0 ] )
return vars . pointloc ;
else {
strlcpy ( macro_buf , tp_name_someplace . string , sizeof ( macro_buf ) ) ;
return macro_buf ;
}
}
2004-09-30 22:25:55 +00:00
static char * Macro_PointNameAtLocation ( void )
2004-08-23 00:15:46 +00:00
{
if ( cls . framecount ! = vars . pointframe )
TP_FindPoint ( ) ;
if ( vars . pointloc [ 0 ] )
return va ( " %s %s %s " , vars . pointname , tp_name_at . string , vars . pointloc ) ;
else
return vars . pointname ;
}
2020-04-19 01:23:32 +00:00
2004-09-30 22:25:55 +00:00
static char * Macro_Need ( void )
2004-08-23 00:15:46 +00:00
{
int i , weapon ;
char * needammo = NULL ;
macro_buf [ 0 ] = 0 ;
// check armor
2012-07-05 19:42:36 +00:00
if ( ( ( cl . playerview [ SP ] . stats [ STAT_ITEMS ] & IT_ARMOR1 ) & & cl . playerview [ SP ] . stats [ STAT_ARMOR ] < tp_need_ga . value )
| | ( ( cl . playerview [ SP ] . stats [ STAT_ITEMS ] & IT_ARMOR2 ) & & cl . playerview [ SP ] . stats [ STAT_ARMOR ] < tp_need_ya . value )
| | ( ( cl . playerview [ SP ] . stats [ STAT_ITEMS ] & IT_ARMOR3 ) & & cl . playerview [ SP ] . stats [ STAT_ARMOR ] < tp_need_ra . value )
| | ( ! ( cl . playerview [ SP ] . stats [ STAT_ITEMS ] & ( IT_ARMOR1 | IT_ARMOR2 | IT_ARMOR3 ) )
2004-08-23 00:15:46 +00:00
& & ( tp_need_ga . value | | tp_need_ya . value | | tp_need_ra . value ) ) )
2005-04-26 16:04:12 +00:00
strcpy ( macro_buf , tp_name_armor . string ) ;
2004-08-23 00:15:46 +00:00
// check health
2012-07-05 19:42:36 +00:00
if ( tp_need_health . value & & cl . playerview [ SP ] . stats [ STAT_HEALTH ] < tp_need_health . value ) {
2005-04-26 16:04:12 +00:00
MacroBuf_strcat_with_separator ( tp_name_health . string ) ;
2004-08-23 00:15:46 +00:00
}
if ( cl . teamfortress )
{
// in TF, we have all weapons from the start,
// and ammo is checked differently
2012-07-05 19:42:36 +00:00
if ( cl . playerview [ SP ] . stats [ STAT_ROCKETS ] < tp_need_rockets . value )
2005-04-26 16:04:12 +00:00
MacroBuf_strcat_with_separator ( tp_name_rockets . string ) ;
2012-07-05 19:42:36 +00:00
if ( cl . playerview [ SP ] . stats [ STAT_SHELLS ] < tp_need_shells . value )
2005-04-26 16:04:12 +00:00
MacroBuf_strcat_with_separator ( tp_name_shells . string ) ;
2012-07-05 19:42:36 +00:00
if ( cl . playerview [ SP ] . stats [ STAT_NAILS ] < tp_need_nails . value )
2005-04-26 16:04:12 +00:00
MacroBuf_strcat_with_separator ( tp_name_nails . string ) ;
2012-07-05 19:42:36 +00:00
if ( cl . playerview [ SP ] . stats [ STAT_CELLS ] < tp_need_cells . value )
2005-04-26 16:04:12 +00:00
MacroBuf_strcat_with_separator ( tp_name_cells . string ) ;
2004-08-23 00:15:46 +00:00
goto done ;
}
// check weapon
weapon = 0 ;
for ( i = strlen ( tp_need_weapon . string ) - 1 ; i > = 0 ; i - - ) {
switch ( tp_need_weapon . string [ i ] ) {
2012-07-05 19:42:36 +00:00
case ' 2 ' : if ( cl . playerview [ SP ] . stats [ STAT_ITEMS ] & IT_SHOTGUN ) weapon = 2 ; break ;
case ' 3 ' : if ( cl . playerview [ SP ] . stats [ STAT_ITEMS ] & IT_SUPER_SHOTGUN ) weapon = 3 ; break ;
case ' 4 ' : if ( cl . playerview [ SP ] . stats [ STAT_ITEMS ] & IT_NAILGUN ) weapon = 4 ; break ;
case ' 5 ' : if ( cl . playerview [ SP ] . stats [ STAT_ITEMS ] & IT_SUPER_NAILGUN ) weapon = 5 ; break ;
case ' 6 ' : if ( cl . playerview [ SP ] . stats [ STAT_ITEMS ] & IT_GRENADE_LAUNCHER ) weapon = 6 ; break ;
case ' 7 ' : if ( cl . playerview [ SP ] . stats [ STAT_ITEMS ] & IT_ROCKET_LAUNCHER ) weapon = 7 ; break ;
case ' 8 ' : if ( cl . playerview [ SP ] . stats [ STAT_ITEMS ] & IT_LIGHTNING ) weapon = 8 ; break ;
2004-08-23 00:15:46 +00:00
}
if ( weapon )
break ;
}
if ( ! weapon ) {
2005-04-26 16:04:12 +00:00
MacroBuf_strcat_with_separator ( tp_name_weapon . string ) ;
2004-08-23 00:15:46 +00:00
} else {
2012-07-05 19:42:36 +00:00
if ( tp_need_rl . value & & ! ( cl . playerview [ SP ] . stats [ STAT_ITEMS ] & IT_ROCKET_LAUNCHER ) ) {
2005-04-26 16:04:12 +00:00
MacroBuf_strcat_with_separator ( tp_name_rl . string ) ;
2004-08-23 00:15:46 +00:00
}
switch ( weapon ) {
2012-07-05 19:42:36 +00:00
case 2 : case 3 : if ( cl . playerview [ SP ] . stats [ STAT_SHELLS ] < tp_need_shells . value ) needammo = tp_name_shells . string ; break ;
case 4 : case 5 : if ( cl . playerview [ SP ] . stats [ STAT_NAILS ] < tp_need_nails . value ) needammo = tp_name_nails . string ; break ;
case 6 : case 7 : if ( cl . playerview [ SP ] . stats [ STAT_ROCKETS ] < tp_need_rockets . value ) needammo = tp_name_rockets . string ; break ;
case 8 : if ( cl . playerview [ SP ] . stats [ STAT_CELLS ] < tp_need_cells . value ) needammo = tp_name_cells . string ; break ;
2004-08-23 00:15:46 +00:00
}
if ( needammo ) {
MacroBuf_strcat_with_separator ( needammo ) ;
}
}
done :
if ( ! macro_buf [ 0 ] )
strcpy ( macro_buf , " nothing " ) ;
return macro_buf ;
}
2005-04-26 16:04:12 +00:00
static char * Skin_To_TFSkin ( char * myskin )
2004-08-23 00:15:46 +00:00
{
2017-05-28 15:42:32 +00:00
playerview_t * pv = & cl . playerview [ SP ] ;
if ( ! cl . teamfortress | | pv - > spectator | | Q_strncasecmp ( myskin , " tf_ " , 3 ) )
2005-04-26 16:04:12 +00:00
{
Q_strncpyz ( macro_buf , myskin , sizeof ( macro_buf ) ) ;
}
2004-08-23 00:15:46 +00:00
else
{
2005-04-26 16:04:12 +00:00
if ( ! Q_strcasecmp ( myskin , " tf_demo " ) )
Q_strncpyz ( macro_buf , " demoman " , sizeof ( macro_buf ) ) ;
else if ( ! Q_strcasecmp ( myskin , " tf_eng " ) )
Q_strncpyz ( macro_buf , " engineer " , sizeof ( macro_buf ) ) ;
else if ( ! Q_strcasecmp ( myskin , " tf_snipe " ) )
Q_strncpyz ( macro_buf , " sniper " , sizeof ( macro_buf ) ) ;
else if ( ! Q_strcasecmp ( myskin , " tf_sold " ) )
Q_strncpyz ( macro_buf , " soldier " , sizeof ( macro_buf ) ) ;
2004-08-23 00:15:46 +00:00
else
2005-04-26 16:04:12 +00:00
Q_strncpyz ( macro_buf , myskin + 3 , sizeof ( macro_buf ) ) ;
2004-08-23 00:15:46 +00:00
}
return macro_buf ;
}
2005-04-26 16:04:12 +00:00
static char * Macro_TF_Skin ( void )
{
2018-07-05 16:21:44 +00:00
return Skin_To_TFSkin ( InfoBuf_ValueForKey ( & cl . players [ cl . playerview [ SP ] . playernum ] . userinfo , " skin " ) ) ;
2005-04-26 16:04:12 +00:00
}
2004-10-10 06:32:29 +00:00
//Spike: added these:
2021-04-14 05:21:04 +00:00
static char * Macro_Team ( void )
{
infobuf_t * info ;
int seat = SP ;
//read the userinfo's team from the server instead of our local/private cvar/userinfo, if we can.
if ( cl . players [ cl . playerview [ seat ] . playernum ] . userinfovalid )
info = & cl . players [ cl . playerview [ seat ] . playernum ] . userinfo ;
else //just use the userinfo (which should mirror the cvar - fixme: splitscreen...)
info = & cls . userinfo [ seat ] ;
return InfoBuf_ValueForKey ( info , " team " ) ;
}
2004-10-10 06:32:29 +00:00
static char * Macro_ConnectionType ( void )
{
2017-05-28 15:42:32 +00:00
playerview_t * pv = & cl . playerview [ SP ] ;
2004-10-10 06:32:29 +00:00
if ( ! cls . state )
return " disconnected " ;
2017-05-28 15:42:32 +00:00
if ( pv - > spectator )
2004-10-10 06:32:29 +00:00
return " spectator " ;
return " connected " ;
}
static char * Macro_demoplayback ( void )
{
switch ( cls . demoplayback )
{
case DPB_NONE :
return " 0 " ;
case DPB_QUAKEWORLD :
return " qwdplayback " ;
case DPB_MVD :
return " mvdplayback " ;
2004-10-26 23:05:19 +00:00
# ifdef NQPROT
2004-10-10 06:32:29 +00:00
case DPB_NETQUAKE :
return " demplayback " ;
2004-10-26 23:05:19 +00:00
# endif
# ifdef Q2CLIENT
2004-10-10 06:32:29 +00:00
case DPB_QUAKE2 :
return " dm2playback " ;
2004-10-26 23:05:19 +00:00
# endif
2018-09-23 19:35:24 +00:00
2004-10-10 06:32:29 +00:00
//gcc will warn if we add annother playback and forget here, otherwise I'd use a default.
2018-09-23 19:35:24 +00:00
case DPB_EZTV :
break ;
2004-10-10 06:32:29 +00:00
}
return " 1 " ; //unknown.
}
2005-02-06 02:47:36 +00:00
static char * Macro_Match_Name ( void )
{
int i ;
i = TP_CountPlayers ( ) ;
if ( cl . teamplay & & i > = 3 )
{ // Teamplay
return va ( " %s %s vs %s - %s " ,
TP_PlayerName ( ) ,
TP_PlayerTeam ( ) ,
TP_EnemyTeam ( ) ,
TP_MapName ( ) ) ;
}
else
{
if ( i = = 2 )
{ // Duel
return va ( " %s vs %s - %s " ,
TP_PlayerName ( ) ,
TP_EnemyName ( ) ,
TP_MapName ( ) ) ;
}
else if ( i > 2 )
{ // FFA
return va ( " %s ffa - %s " ,
2011-05-15 13:23:13 +00:00
TP_PlayerName ( ) ,
2005-02-06 02:47:36 +00:00
TP_MapName ( ) ) ;
}
else
{ // one player
return va ( " %s - %s " ,
TP_PlayerName ( ) ,
TP_MapName ( ) ) ;
}
}
}
//$matchtype
//duel,2on2,4on4,ffa,etc...
static char * Macro_Match_Type ( void )
{
int i ;
i = TP_CountPlayers ( ) ;
if ( cl . teamplay & & i > = 3 )
{
if ( i > = 6 )
return " 4on4 " ;
return " 2on2 " ;
}
if ( i = = 2 )
return " duel " ;
if ( i = = 1 )
return " single " ;
if ( i = = 0 )
return " empty " ;
return " ffa " ;
}
2005-04-26 16:04:12 +00:00
static char * Macro_Point_LED ( void )
{
TP_FindPoint ( ) ;
if ( vars . pointtype = = POINT_TYPE_ENEMY )
return tp_name_status_red . string ;
else if ( vars . pointtype = = POINT_TYPE_TEAMMATE )
return tp_name_status_green . string ;
else if ( vars . pointtype = = POINT_TYPE_POWERUP )
return tp_name_status_yellow . string ;
else // POINT_TYPE_ITEM
return tp_name_status_blue . string ;
return macro_buf ;
}
static char * Macro_MyStatus_LED ( void )
{
int count ;
float save_need_rl ;
char * s , * save_separator ;
static char separator [ ] = { ' / ' , ' \0 ' } ;
save_need_rl = tp_need_rl . value ;
save_separator = tp_name_separator . string ;
tp_need_rl . value = 0 ;
tp_name_separator . string = separator ;
s = Macro_Need ( ) ;
tp_need_rl . value = save_need_rl ;
tp_name_separator . string = save_separator ;
if ( ! strcmp ( s , tp_name_nothing . string ) ) {
count = 0 ;
} else {
for ( count = 1 ; * s ; s + + )
if ( * s = = separator [ 0 ] )
count + + ;
2011-05-15 13:23:13 +00:00
}
2005-04-26 16:04:12 +00:00
if ( count = = 0 )
Q_snprintfz ( macro_buf , sizeof ( macro_buf ) , " %s " , tp_name_status_green . string ) ;
else if ( count < = 1 )
Q_snprintfz ( macro_buf , sizeof ( macro_buf ) , " %s " , tp_name_status_yellow . string ) ;
else
2011-05-15 13:23:13 +00:00
Q_snprintfz ( macro_buf , sizeof ( macro_buf ) , " %s " , tp_name_status_red . string ) ;
2005-04-26 16:04:12 +00:00
return macro_buf ;
}
static void CountNearbyPlayers ( qboolean dead )
{
int i ;
player_state_t * state ;
player_info_t * info ;
static int lastframecount = - 1 ;
2017-05-28 15:42:32 +00:00
playerview_t * pv = & cl . playerview [ SP ] ;
2005-04-26 16:04:12 +00:00
if ( cls . framecount = = lastframecount )
return ;
lastframecount = cls . framecount ;
vars . numenemies = vars . numfriendlies = 0 ;
2017-05-28 15:42:32 +00:00
if ( ! pv - > spectator & & ! dead )
2005-04-26 16:04:12 +00:00
vars . numfriendlies + + ;
if ( ! cl . oldparsecount | | ! cl . parsecount | | cls . state < ca_active )
return ;
2013-03-12 22:53:23 +00:00
state = cl . inframes [ cl . oldparsecount & UPDATE_MASK ] . playerstate ;
2005-04-26 16:04:12 +00:00
info = cl . players ;
2013-10-29 17:38:22 +00:00
for ( i = 0 ; i < cl . allocated_client_slots ; i + + , info + + , state + + ) {
2017-05-28 15:42:32 +00:00
if ( i ! = pv - > playernum & & state - > messagenum = = cl . oldparsecount & & ! info - > spectator & & ! ISDEAD ( state - > frame ) ) {
2005-04-26 16:04:12 +00:00
if ( cl . teamplay & & ! strcmp ( info - > team , TP_PlayerTeam ( ) ) )
vars . numfriendlies + + ;
else
vars . numenemies + + ;
}
}
}
static char * Macro_CountNearbyEnemyPlayers ( void )
{
2009-11-04 21:16:50 +00:00
if ( ! ruleset_allow_playercount . ival )
2007-09-22 18:09:12 +00:00
return " " ;
2005-04-26 16:04:12 +00:00
CountNearbyPlayers ( false ) ;
sprintf ( macro_buf , " \xff z%d \xff " , vars . numenemies ) ;
suppress = true ;
return macro_buf ;
}
static char * Macro_Count_Last_NearbyEnemyPlayers ( void )
{
2009-11-04 21:16:50 +00:00
if ( ! ruleset_allow_playercount . ival )
2007-09-22 18:09:12 +00:00
return " " ;
2005-04-26 16:04:12 +00:00
if ( vars . deathtrigger_time & & realtime - vars . deathtrigger_time < = 5 )
{
sprintf ( macro_buf , " \xff z%d \xff " , vars . last_numenemies ) ;
}
else
{
CountNearbyPlayers ( false ) ;
sprintf ( macro_buf , " \xff z%d \xff " , vars . numenemies ) ;
}
suppress = true ;
return macro_buf ;
}
static char * Macro_CountNearbyFriendlyPlayers ( void )
{
2009-11-04 21:16:50 +00:00
if ( ! ruleset_allow_playercount . ival )
2007-09-22 18:09:12 +00:00
return " " ;
2005-04-26 16:04:12 +00:00
CountNearbyPlayers ( false ) ;
sprintf ( macro_buf , " \xff z%d \xff " , vars . numfriendlies ) ;
suppress = true ;
return macro_buf ;
}
static char * Macro_Count_Last_NearbyFriendlyPlayers ( void )
{
2009-11-04 21:16:50 +00:00
if ( ! ruleset_allow_playercount . ival )
2007-09-22 18:09:12 +00:00
return " " ;
2005-04-26 16:04:12 +00:00
if ( vars . deathtrigger_time & & realtime - vars . deathtrigger_time < = 5 )
{
sprintf ( macro_buf , " \xff z%d \xff " , vars . last_numfriendlies ) ;
}
else
{
CountNearbyPlayers ( false ) ;
sprintf ( macro_buf , " \xff z%d \xff " , vars . numfriendlies ) ;
}
suppress = true ;
return macro_buf ;
}
static char * Macro_EnemyStatus_LED ( void )
{
CountNearbyPlayers ( false ) ;
if ( vars . numenemies = = 0 )
Q_snprintfz ( macro_buf , sizeof ( macro_buf ) , " \xff l%s \xff " , tp_name_status_green . string ) ;
else if ( vars . numenemies < = vars . numfriendlies )
Q_snprintfz ( macro_buf , sizeof ( macro_buf ) , " \xff l%s \xff " , tp_name_status_yellow . string ) ;
else
Q_snprintfz ( macro_buf , sizeof ( macro_buf ) , " \xff l%s \xff " , tp_name_status_red . string ) ;
suppress = true ;
return macro_buf ;
}
static char * Macro_LastPointAtLoc ( void )
{
if ( ! vars . pointtime | | realtime - vars . pointtime > TP_POINT_EXPIRE_TIME )
Q_strncpyz ( macro_buf , tp_name_nothing . string , sizeof ( macro_buf ) ) ;
else
2011-05-15 13:23:13 +00:00
Q_snprintfz ( macro_buf , sizeof ( macro_buf ) , " %s %s %s " , vars . pointname , tp_name_at . string , vars . pointloc [ 0 ] ? vars . pointloc : Macro_Location ( ) ) ;
2005-04-26 16:04:12 +00:00
return macro_buf ;
}
static char * Macro_LastTookOrPointed ( void )
{
if ( vars . tooktime & & vars . tooktime > vars . pointtime & & realtime - vars . tooktime < 5 )
return Macro_TookAtLoc ( ) ;
else if ( vars . pointtime & & vars . tooktime < = vars . pointtime & & realtime - vars . pointtime < 5 )
return Macro_LastPointAtLoc ( ) ;
Q_snprintfz ( macro_buf , sizeof ( macro_buf ) , " %s %s %s " , tp_name_nothing . string , tp_name_at . string , tp_name_someplace . string ) ;
return macro_buf ;
}
# define TP_PENT 1
# define TP_QUAD 2
# define TP_RING 4
static char * Macro_LastSeenPowerup ( void )
{
/* if (!vars.enemy_powerups_time || realtime - vars.enemy_powerups_time > 5)
{
Q_strncpyz ( macro_buf , tp_name_quad . string , sizeof ( macro_buf ) ) ;
}
else */
{
macro_buf [ 0 ] = 0 ;
if ( vars . enemy_powerups & TP_QUAD )
2005-04-27 09:10:03 +00:00
Q_strncatz2 ( macro_buf , tp_name_quad . string ) ;
2005-04-26 16:04:12 +00:00
if ( vars . enemy_powerups & TP_PENT )
{
2011-05-15 13:23:13 +00:00
if ( macro_buf [ 0 ] )
2005-04-27 09:10:03 +00:00
Q_strncatz2 ( macro_buf , tp_name_separator . string ) ;
Q_strncatz2 ( macro_buf , tp_name_pent . string ) ;
2005-04-26 16:04:12 +00:00
}
if ( vars . enemy_powerups & TP_RING )
{
2011-05-15 13:23:13 +00:00
if ( macro_buf [ 0 ] )
2005-04-27 09:10:03 +00:00
Q_strncatz2 ( macro_buf , tp_name_separator . string ) ;
Q_strncatz2 ( macro_buf , tp_name_ring . string ) ;
2005-04-26 16:04:12 +00:00
}
}
return macro_buf ;
}
2020-04-19 01:23:32 +00:00
static char * Macro_LastDrop ( void )
2005-04-26 16:04:12 +00:00
{
if ( vars . lastdrop_time )
return vars . lastdroploc ;
else
return tp_name_someplace . string ;
}
2020-04-19 01:23:32 +00:00
static char * Macro_LastDropTime ( void )
2005-04-26 16:04:12 +00:00
{
if ( vars . lastdrop_time )
Q_snprintfz ( macro_buf , 32 , " %d " , ( int ) ( realtime - vars . lastdrop_time ) ) ;
else
Q_snprintfz ( macro_buf , 32 , " %d " , - 1 ) ;
return macro_buf ;
}
2020-04-19 01:23:32 +00:00
static char * Macro_CombinedHealth ( void )
2005-09-14 04:11:56 +00:00
{
float h ;
float t , a , m ;
//total health = health+armour*armourfrac
//however,you're dead if health drops below 0 rather than the entire equation.
2012-07-05 19:42:36 +00:00
if ( cl . playerview [ SP ] . stats [ STAT_ITEMS ] & IT_ARMOR1 )
2005-09-14 04:11:56 +00:00
t = 0.3 ;
2012-07-05 19:42:36 +00:00
else if ( cl . playerview [ SP ] . stats [ STAT_ITEMS ] & IT_ARMOR2 )
2005-09-14 04:11:56 +00:00
t = 0.6 ;
2012-07-05 19:42:36 +00:00
else if ( cl . playerview [ SP ] . stats [ STAT_ITEMS ] & IT_ARMOR3 )
2005-09-14 04:11:56 +00:00
t = 0.8 ;
else
t = 0 ;
2012-07-05 19:42:36 +00:00
a = cl . playerview [ SP ] . stats [ STAT_ARMOR ] ;
h = cl . playerview [ SP ] . stats [ STAT_HEALTH ] ;
2005-09-14 04:11:56 +00:00
//work out the max useful armour
//this will under-exagurate, due to usage of ceil based on damage
m = h / ( 1 - t ) ;
2014-03-30 08:55:06 +00:00
if ( m < 0 )
a = 0 ;
else if ( m < a )
2005-09-14 04:11:56 +00:00
a = m ;
h = h + a ;
Q_snprintfz ( macro_buf , 32 , " %d " , ( int ) h ) ;
return macro_buf ;
}
2020-04-19 01:23:32 +00:00
static char * Macro_Coloured_Armour ( void )
2015-08-28 03:13:45 +00:00
{
if ( cl . playerview [ SP ] . stats [ STAT_ITEMS ] & IT_ARMOR3 )
return " {^s^xe00%%a^r} " ;
else if ( cl . playerview [ SP ] . stats [ STAT_ITEMS ] & IT_ARMOR2 )
return " {^s^xff0%%a^r} " ;
else if ( cl . playerview [ SP ] . stats [ STAT_ITEMS ] & IT_ARMOR1 )
return " {^s^x0b0%%a^r} " ;
else
return " {0} " ;
}
2020-04-19 01:23:32 +00:00
static char * Macro_Coloured_Powerups ( void )
2015-08-28 03:13:45 +00:00
{
char * quad , * pent , * ring ;
quad = ( cl . playerview [ SP ] . stats [ STAT_ITEMS ] & IT_QUAD ) ? va ( " ^x03f%s " , tp_name_quad . string ) : " " ;
pent = ( cl . playerview [ SP ] . stats [ STAT_ITEMS ] & IT_INVULNERABILITY ) ? va ( " ^xe00%s " , tp_name_pent . string ) : " " ;
ring = ( cl . playerview [ SP ] . stats [ STAT_ITEMS ] & IT_INVISIBILITY ) ? va ( " ^xff0%s " , tp_name_ring . string ) : " " ;
if ( * quad | | * pent | | * ring )
{
Q_snprintfz ( macro_buf , 32 , " {^s%s%s%s^r} " , quad , pent , ring ) ;
return macro_buf ;
}
else
return " " ;
}
2020-04-19 01:23:32 +00:00
static char * Macro_Coloured_Short_Powerups ( void )
2015-08-28 03:13:45 +00:00
{
char * quad , * pent , * ring ;
quad = ( cl . playerview [ SP ] . stats [ STAT_ITEMS ] & IT_QUAD ) ? " ^x03fq " : " " ;
pent = ( cl . playerview [ SP ] . stats [ STAT_ITEMS ] & IT_INVULNERABILITY ) ? " ^xe00p " : " " ;
ring = ( cl . playerview [ SP ] . stats [ STAT_ITEMS ] & IT_INVISIBILITY ) ? " ^xff0r " : " " ;
if ( * quad | | * pent | | * ring )
{
Q_snprintfz ( macro_buf , 32 , " {^s%s%s%s^r} " , quad , pent , ring ) ;
return macro_buf ;
}
else
return " " ;
}
2020-04-19 01:23:32 +00:00
static char * Macro_Match_Status ( void )
2015-08-28 03:13:45 +00:00
{
2020-04-19 01:23:32 +00:00
if ( cls . state = = ca_disconnected )
return " disconnected " ;
if ( cls . state < ca_active )
return " connecting " ;
switch ( cl . matchstate )
{
case MATCH_DONTKNOW :
case MATCH_INPROGRESS :
default :
return " normal " ;
case MATCH_COUNTDOWN :
return " countdown " ;
case MATCH_STANDBY :
return " standby " ;
}
2015-08-28 03:13:45 +00:00
}
2020-04-19 01:23:32 +00:00
/*static char *Macro_LastIP(void)
2021-04-14 05:21:04 +00:00
{ //report the last ip that someone said in chat. requires making guesses about what's an ip or not. can't handle hostnames properly
2015-08-28 03:13:45 +00:00
return " --- " ;
}
2020-04-19 01:23:32 +00:00
static char * Macro_MP3Info ( void )
{ //for people trying to be cool but really just annoying everyone
2015-08-28 03:13:45 +00:00
return " --- " ;
}
2020-04-19 01:23:32 +00:00
*/
static char * Macro_LastTrigger_Match ( void )
{ //returns the last line that triggered a msg_trigger
return vars . lasttrigger_match ;
2015-08-28 03:13:45 +00:00
}
2015-09-01 04:45:15 +00:00
# endif
2015-08-28 03:13:45 +00:00
2005-04-26 16:04:12 +00:00
/*
2004-10-10 06:32:29 +00:00
$ matchname
you can use to get the name of the match
manually ( echo $ matchname ) .
Example : a matchname might be
" [clan]quaker - [4on4_myclan_vs_someclan] - [dm3] " or whatever .
$ matchstatus
( " disconnected " , " standby " or " normal " ) . This can be
used for detecting prewar / prematch on ktpro / oztf servers .
$ mp3info
Evaluates to " author - title " .
Examples :
if you bind space " say listening to $mp3info "
then hitting space will say something like
" listening to disturbed - rise " .
bind x " if disturbed isin $mp3info then say dde music is cool "
$ triggermatch
$ triggermatch is the last chat message that exec ' d a msg_trigger .
*/
//Spike: added end.
2004-09-30 22:25:55 +00:00
static void TP_InitMacros ( void )
2004-08-23 00:15:46 +00:00
{
2005-02-28 07:16:19 +00:00
Cmd_AddMacro ( " latency " , Macro_Latency , false ) ;
2020-04-19 01:23:32 +00:00
Cmd_AddMacro ( " location " , Macro_Location , false ) ;
2015-09-01 04:45:15 +00:00
# ifdef QUAKESTATS
2005-02-28 07:16:19 +00:00
Cmd_AddMacro ( " health " , Macro_Health , true ) ;
Cmd_AddMacro ( " armortype " , Macro_ArmorType , true ) ;
Cmd_AddMacro ( " armor " , Macro_Armor , true ) ;
Cmd_AddMacro ( " shells " , Macro_Shells , true ) ;
Cmd_AddMacro ( " nails " , Macro_Nails , true ) ;
Cmd_AddMacro ( " rockets " , Macro_Rockets , true ) ;
Cmd_AddMacro ( " cells " , Macro_Cells , true ) ;
Cmd_AddMacro ( " weaponnum " , Macro_WeaponNum , true ) ;
Cmd_AddMacro ( " weapons " , Macro_Weapons , true ) ;
Cmd_AddMacro ( " weapon " , Macro_Weapon , true ) ;
Cmd_AddMacro ( " ammo " , Macro_Ammo , true ) ;
Cmd_AddMacro ( " bestweapon " , Macro_BestWeapon , true ) ;
Cmd_AddMacro ( " bestammo " , Macro_BestAmmo , true ) ;
Cmd_AddMacro ( " powerups " , Macro_Powerups , true ) ;
2015-09-01 04:45:15 +00:00
Cmd_AddMacro ( " droppedweapon " , Macro_DroppedWeapon , true ) ;
2020-04-19 01:23:32 +00:00
Cmd_AddMacro ( " tf_skin " , Macro_TF_Skin , true ) ;
2021-04-14 05:21:04 +00:00
Cmd_AddMacro ( " team " , Macro_Team , true ) ; //confusing
2020-04-19 01:23:32 +00:00
2005-02-28 07:16:19 +00:00
Cmd_AddMacro ( " deathloc " , Macro_LastDeath , true ) ;
Cmd_AddMacro ( " tookatloc " , Macro_TookAtLoc , true ) ;
Cmd_AddMacro ( " tookloc " , Macro_TookLoc , true ) ;
Cmd_AddMacro ( " took " , Macro_Took , true ) ;
2004-10-10 06:32:29 +00:00
//ones added by Spike, for fuhquake compatability
2005-02-28 07:16:19 +00:00
Cmd_AddMacro ( " connectiontype " , Macro_ConnectionType , false ) ;
Cmd_AddMacro ( " demoplayback " , Macro_demoplayback , false ) ;
Cmd_AddMacro ( " point " , Macro_PointName , true ) ;
Cmd_AddMacro ( " pointatloc " , Macro_PointNameAtLocation , true ) ;
Cmd_AddMacro ( " pointloc " , Macro_PointLocation , true ) ;
Cmd_AddMacro ( " matchname " , Macro_Match_Name , false ) ;
Cmd_AddMacro ( " matchtype " , Macro_Match_Type , false ) ;
2015-09-01 04:45:15 +00:00
Cmd_AddMacro ( " need " , Macro_Need , true ) ;
2005-04-26 16:04:12 +00:00
Cmd_AddMacro ( " ledstatus " , Macro_MyStatus_LED , true ) ;
2015-09-01 04:45:15 +00:00
Cmd_AddMacro ( " ledpoint " , Macro_Point_LED , true ) ;
2005-04-26 16:04:12 +00:00
Cmd_AddMacro ( " droploc " , Macro_LastDrop , true ) ;
Cmd_AddMacro ( " droptime " , Macro_LastDropTime , true ) ;
2020-04-19 01:23:32 +00:00
Cmd_AddMacro ( " matchstatus " , Macro_Match_Status , false ) ;
Cmd_AddMacro ( " triggermatch " , Macro_LastTrigger_Match , false ) ;
# endif
2015-09-01 04:45:15 +00:00
// Cmd_AddMacro("mp3info", Macro_MP3Info, false);
2005-09-14 04:11:56 +00:00
2006-02-27 00:42:25 +00:00
//new, fte only (at least when first implemented)
2015-09-01 04:45:15 +00:00
# ifdef QUAKESTATS
2005-09-14 04:11:56 +00:00
Cmd_AddMacro ( " chealth " , Macro_CombinedHealth , true ) ;
2015-09-01 04:45:15 +00:00
# endif
2007-08-23 21:25:18 +00:00
//added for ezquake compatability
2015-09-01 04:45:15 +00:00
// Cmd_AddMacro("lastip", Macro_LastIP, false);
2007-08-23 21:25:18 +00:00
Cmd_AddMacro ( " ping " , Macro_Latency , false ) ;
2015-09-01 04:45:15 +00:00
# ifdef QUAKESTATS
2015-08-28 03:13:45 +00:00
Cmd_AddMacro ( " colored_armor " , Macro_Coloured_Armour , true ) ; //*shudder*
Cmd_AddMacro ( " colored_powerups " , Macro_Coloured_Powerups , true ) ;
Cmd_AddMacro ( " colored_short_powerups " , Macro_Coloured_Short_Powerups , true ) ;
2007-08-23 21:25:18 +00:00
Cmd_AddMacro ( " lastloc " , Macro_Last_Location , true ) ;
Cmd_AddMacro ( " lastpowerup " , Macro_LastSeenPowerup , true ) ;
2020-04-19 01:23:32 +00:00
# endif
Cmd_AddMacro ( " gamedir " , Macro_Gamedir , false ) ;
2004-08-23 00:15:46 +00:00
}
# define MAX_MACRO_STRING 1024
/*
= = = = = = = = = = = = =
TP_ParseMacroString
Parses % a - like expressions
= = = = = = = = = = = = =
*/
2004-09-30 22:25:55 +00:00
static char * TP_ParseMacroString ( char * s )
2004-08-23 00:15:46 +00:00
{
static char buf [ MAX_MACRO_STRING ] ;
int i = 0 ;
char * macro_string ;
2009-11-04 21:16:50 +00:00
if ( ! cl_parseSay . ival )
2004-08-23 00:15:46 +00:00
return s ;
while ( * s & & i < MAX_MACRO_STRING - 1 )
{
// check %[P], etc
if ( * s = = ' % ' & & s [ 1 ] = = ' [ ' & & s [ 2 ] & & s [ 3 ] = = ' ] ' )
{
2016-10-22 07:06:51 +00:00
# ifdef QUAKESTATS
2004-08-23 00:15:46 +00:00
static char mbuf [ MAX_MACRO_VALUE ] ;
2016-10-22 07:06:51 +00:00
# endif
2004-08-23 00:15:46 +00:00
switch ( s [ 2 ] ) {
2015-09-01 04:45:15 +00:00
# ifdef QUAKESTATS
2004-08-23 00:15:46 +00:00
case ' a ' :
macro_string = Macro_ArmorType ( ) ;
if ( ! macro_string [ 0 ] )
macro_string = " a " ;
2012-07-05 19:42:36 +00:00
if ( cl . playerview [ SP ] . stats [ STAT_ARMOR ] < 30 )
Q_snprintfz ( mbuf , sizeof ( mbuf ) , " \x10 %s:%i \x11 " , macro_string , cl . playerview [ SP ] . stats [ STAT_ARMOR ] ) ;
2004-08-23 00:15:46 +00:00
else
2012-07-05 19:42:36 +00:00
Q_snprintfz ( mbuf , sizeof ( mbuf ) , " %s:%i " , macro_string , cl . playerview [ SP ] . stats [ STAT_ARMOR ] ) ;
2004-08-23 00:15:46 +00:00
macro_string = mbuf ;
break ;
2011-05-15 13:23:13 +00:00
2004-08-23 00:15:46 +00:00
case ' h ' :
2012-07-05 19:42:36 +00:00
if ( cl . playerview [ SP ] . stats [ STAT_HEALTH ] > = 50 )
Q_snprintfz ( macro_buf , sizeof ( macro_buf ) , " %i " , cl . playerview [ SP ] . stats [ STAT_HEALTH ] ) ;
2004-08-23 00:15:46 +00:00
else
2012-07-05 19:42:36 +00:00
Q_snprintfz ( macro_buf , sizeof ( macro_buf ) , " \x10 %i \x11 " , cl . playerview [ SP ] . stats [ STAT_HEALTH ] ) ;
2004-08-23 00:15:46 +00:00
macro_string = macro_buf ;
break ;
2011-05-15 13:23:13 +00:00
2004-08-23 00:15:46 +00:00
case ' p ' :
case ' P ' :
macro_string = Macro_Powerups ( ) ;
if ( macro_string [ 0 ] )
2011-07-22 15:11:35 +00:00
Q_snprintfz ( mbuf , sizeof ( mbuf ) , " \x10 %s \x11 " , macro_string ) ;
2004-08-23 00:15:46 +00:00
else
mbuf [ 0 ] = 0 ;
macro_string = mbuf ;
break ;
2015-09-01 04:45:15 +00:00
# endif
2004-08-23 00:15:46 +00:00
// todo: %[w], %[b]
2011-05-15 13:23:13 +00:00
2004-08-23 00:15:46 +00:00
default :
buf [ i + + ] = * s + + ;
continue ;
}
if ( i + strlen ( macro_string ) > = MAX_MACRO_STRING - 1 )
Sys_Error ( " TP_ParseMacroString: macro string length > MAX_MACRO_STRING) " ) ;
strcpy ( & buf [ i ] , macro_string ) ;
i + = strlen ( macro_string ) ;
s + = 4 ; // skip %[<char>]
continue ;
}
2011-05-15 13:23:13 +00:00
2004-08-23 00:15:46 +00:00
// check %a, etc
if ( * s = = ' % ' )
{
switch ( s [ 1 ] )
{
2015-09-01 04:45:15 +00:00
# ifdef QUAKESTATS
2005-04-26 16:04:12 +00:00
case ' a ' : macro_string = Macro_Armor ( ) ; break ;
case ' A ' : macro_string = Macro_ArmorType ( ) ; break ;
case ' b ' : macro_string = Macro_BestWeaponAndAmmo ( ) ; break ;
case ' c ' : macro_string = Macro_Cells ( ) ; break ;
case ' d ' : macro_string = Macro_LastDeath ( ) ; break ;
2015-06-16 23:53:58 +00:00
// case 'D':
2005-04-26 16:04:12 +00:00
case ' h ' : macro_string = Macro_Health ( ) ; break ;
case ' i ' : macro_string = Macro_TookAtLoc ( ) ; break ;
case ' j ' : macro_string = Macro_LastPointAtLoc ( ) ; break ;
case ' k ' : macro_string = Macro_LastTookOrPointed ( ) ; break ;
case ' L ' : macro_string = Macro_Last_Location ( ) ; break ;
2020-04-19 01:23:32 +00:00
# endif
case ' l ' : macro_string = Macro_Location ( ) ; break ;
# ifdef QUAKESTATS
2005-04-26 16:04:12 +00:00
case ' m ' : macro_string = Macro_LastTookOrPointed ( ) ; break ;
2011-05-15 13:23:13 +00:00
2005-04-26 16:04:12 +00:00
case ' o ' : macro_string = Macro_CountNearbyFriendlyPlayers ( ) ; break ;
case ' e ' : macro_string = Macro_CountNearbyEnemyPlayers ( ) ; break ;
case ' O ' : macro_string = Macro_Count_Last_NearbyFriendlyPlayers ( ) ; break ;
case ' E ' : macro_string = Macro_Count_Last_NearbyEnemyPlayers ( ) ; break ;
2011-05-15 13:23:13 +00:00
case ' P ' :
2005-04-26 16:04:12 +00:00
case ' p ' : macro_string = Macro_Powerups ( ) ; break ;
2011-05-15 13:23:13 +00:00
case ' q ' : macro_string = Macro_LastSeenPowerup ( ) ; break ;
2005-04-26 16:04:12 +00:00
// case 'r': macro_string = Macro_LastReportedLoc(); break;
2011-05-15 13:23:13 +00:00
case ' s ' : macro_string = Macro_EnemyStatus_LED ( ) ; break ;
case ' S ' : macro_string = Macro_TF_Skin ( ) ; break ;
2005-04-26 16:04:12 +00:00
case ' t ' : macro_string = Macro_PointNameAtLocation ( ) ; break ;
case ' u ' : macro_string = Macro_Need ( ) ; break ;
case ' w ' : macro_string = Macro_WeaponAndAmmo ( ) ; break ;
case ' x ' : macro_string = Macro_PointName ( ) ; break ;
case ' X ' : macro_string = Macro_Took ( ) ; break ;
case ' y ' : macro_string = Macro_PointLocation ( ) ; break ;
case ' Y ' : macro_string = Macro_TookLoc ( ) ; break ;
2020-04-19 01:23:32 +00:00
# endif
2012-12-15 19:20:33 +00:00
case ' n ' : //vicinity
case ' N ' : //hides from you
case ' g ' : //bonus timers.
case ' C ' : //colour
case ' z ' : //nearest waypoint (looking)
case ' Z ' : //nearest waypoint (moving)
2011-05-15 13:23:13 +00:00
default :
2004-08-23 00:15:46 +00:00
buf [ i + + ] = * s + + ;
continue ;
}
if ( i + strlen ( macro_string ) > = MAX_MACRO_STRING - 1 )
Sys_Error ( " TP_ParseMacroString: macro string length > MAX_MACRO_STRING) " ) ;
strcpy ( & buf [ i ] , macro_string ) ;
i + = strlen ( macro_string ) ;
s + = 2 ; // skip % and letter
continue ;
}
buf [ i + + ] = * s + + ;
}
buf [ i ] = 0 ;
return buf ;
}
/*
= = = = = = = = = = = = = =
TP_ParseFunChars
Doesn ' t check for overflows , so strlen ( s ) should be < MAX_MACRO_STRING
= = = = = = = = = = = = = =
*/
2017-12-09 21:22:46 +00:00
char * TP_ParseFunChars ( char * s )
2004-08-23 00:15:46 +00:00
{
static char buf [ MAX_MACRO_STRING ] ;
char * out = buf ;
int c ;
2009-11-04 21:16:50 +00:00
if ( ! cl_parseFunChars . ival )
2004-08-23 00:15:46 +00:00
return s ;
while ( * s ) {
if ( * s = = ' $ ' & & s [ 1 ] = = ' x ' ) {
int i ;
// check for $x10, $x8a, etc
c = tolower ( ( int ) ( unsigned char ) s [ 2 ] ) ;
if ( isdigit ( c ) )
i = ( c - ( int ) ' 0 ' ) < < 4 ;
else if ( isxdigit ( c ) )
i = ( c - ( int ) ' a ' + 10 ) < < 4 ;
else goto skip ;
c = tolower ( ( int ) ( unsigned char ) s [ 3 ] ) ;
if ( isdigit ( c ) )
i + = ( c - ( int ) ' 0 ' ) ;
else if ( isxdigit ( c ) )
i + = ( c - ( int ) ' a ' + 10 ) ;
else goto skip ;
if ( ! i )
i = ( int ) ' ' ;
* out + + = ( char ) i ;
s + = 4 ;
continue ;
}
if ( * s = = ' $ ' & & s [ 1 ] ) {
c = 0 ;
switch ( s [ 1 ] ) {
case ' \\ ' : c = 0x0D ; break ;
case ' : ' : c = 0x0A ; break ;
case ' [ ' : c = 0x10 ; break ;
case ' ] ' : c = 0x11 ; break ;
case ' G ' : c = 0x86 ; break ;
case ' R ' : c = 0x87 ; break ;
case ' Y ' : c = 0x88 ; break ;
case ' B ' : c = 0x89 ; break ;
case ' ( ' : c = 0x80 ; break ;
case ' = ' : c = 0x81 ; break ;
case ' ) ' : c = 0x82 ; break ;
case ' a ' : c = 0x83 ; break ;
case ' < ' : c = 0x1d ; break ;
case ' - ' : c = 0x1e ; break ;
case ' > ' : c = 0x1f ; break ;
case ' , ' : c = 0x1c ; break ;
case ' . ' : c = 0x9c ; break ;
case ' b ' : c = 0x8b ; break ;
case ' c ' :
case ' d ' : c = 0x8d ; break ;
case ' $ ' : c = ' $ ' ; break ;
case ' ^ ' : c = ' ^ ' ; break ;
}
if ( isdigit ( ( int ) ( unsigned char ) s [ 1 ] ) )
c = s [ 1 ] - ( int ) ' 0 ' + 0x12 ;
if ( c ) {
* out + + = ( char ) c ;
s + = 2 ;
continue ;
}
}
2011-05-15 13:23:13 +00:00
skip :
2004-08-23 00:15:46 +00:00
* out + + = * s + + ;
}
* out = 0 ;
return buf ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
PROXY . LOC FILES
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
typedef struct locdata_s {
2012-12-15 19:20:33 +00:00
vec3_t min ;
vec3_t max ;
2004-08-23 00:15:46 +00:00
char name [ MAX_LOC_NAME ] ;
} locdata_t ;
2020-04-19 01:23:32 +00:00
static locdata_t * locdata ; // FIXME: allocate dynamically?
static size_t loc_numentries ;
static size_t loc_maxentries ;
2004-08-23 00:15:46 +00:00
2004-09-30 22:25:55 +00:00
static void TP_LoadLocFile ( char * filename , qbool quiet )
2004-08-23 00:15:46 +00:00
{
char fullpath [ MAX_QPATH ] ;
char * buf , * p ;
char line [ 1024 ] ;
int i , argc ;
int errorcount = 0 ;
locdata_t * loc ;
2012-12-15 19:20:33 +00:00
char * comma , * space ;
2004-08-23 00:15:46 +00:00
if ( ! * filename )
return ;
Q_snprintfz ( fullpath , sizeof ( fullpath ) - 4 , " locs/%s " , filename ) ;
2006-03-11 03:12:10 +00:00
COM_DefaultExtension ( fullpath , " .loc " , sizeof ( fullpath ) ) ;
2004-08-23 00:15:46 +00:00
2018-07-05 16:21:44 +00:00
buf = ( char * ) COM_LoadTempFile ( fullpath , 0 , NULL ) ;
2012-12-15 19:20:33 +00:00
if ( ! buf )
{
2004-08-23 00:15:46 +00:00
if ( ! quiet )
Com_Printf ( " Could not load %s \n " , fullpath ) ;
return ;
}
loc_numentries = 0 ;
// parse the file
// we rely on the fact that FS_Load*File always appends a 0 at the end
p = buf ;
2012-12-15 19:20:33 +00:00
while ( 1 )
{
2004-08-23 00:15:46 +00:00
if ( ! * p )
break ; // end of file
// get a line out
2012-12-15 19:20:33 +00:00
for ( i = 0 ; i < sizeof ( line ) - 1 ; )
{
2004-08-23 00:15:46 +00:00
char c = * p + + ;
if ( ! c | | c = = 10 )
break ;
if ( c ! = 13 )
line [ i + + ] = c ;
}
line [ i ] = 0 ;
2012-12-15 19:20:33 +00:00
comma = strchr ( line , ' , ' ) ;
space = strchr ( line , ' ' ) ;
2004-08-23 00:15:46 +00:00
2012-12-15 19:20:33 +00:00
if ( comma & & ( comma < space | | ! space ) )
{
vec3_t min , max ;
min [ 0 ] = strtod ( line , & comma ) ;
if ( * comma + + = = ' , ' )
{
while ( * comma = = ' ' | | * comma = = ' \t ' )
comma + + ;
min [ 1 ] = strtod ( comma , & comma ) ;
if ( * comma + + = = ' , ' )
{
while ( * comma = = ' ' | | * comma = = ' \t ' )
comma + + ;
min [ 2 ] = strtod ( comma , & comma ) ;
if ( * comma + + = = ' , ' )
{
while ( * comma = = ' ' | | * comma = = ' \t ' )
comma + + ;
max [ 0 ] = strtod ( comma , & comma ) ;
if ( * comma + + = = ' , ' )
{
while ( * comma = = ' ' | | * comma = = ' \t ' )
comma + + ;
max [ 1 ] = strtod ( comma , & comma ) ;
if ( * comma + + = = ' , ' )
{
while ( * comma = = ' ' | | * comma = = ' \t ' )
comma + + ;
max [ 2 ] = strtod ( comma , & comma ) ;
if ( * comma + + = = ' , ' )
{
2020-04-19 01:23:32 +00:00
if ( loc_numentries = = loc_maxentries )
Z_ReallocElements ( ( void * * ) & locdata , & loc_maxentries , loc_numentries + 64 , sizeof ( * locdata ) ) ;
2012-12-15 19:20:33 +00:00
loc = & locdata [ loc_numentries ] ;
loc_numentries + + ;
while ( * comma = = ' ' | | * comma = = ' \t ' )
comma + + ;
if ( * comma = = ' \" ' )
COM_ParseOut ( comma , loc - > name , sizeof ( loc - > name ) ) ;
else
Q_strncpyz ( loc - > name , comma , sizeof ( loc - > name ) ) ;
for ( i = 0 ; i < 3 ; i + + )
{
if ( min [ i ] > max [ i ] )
{
loc - > min [ i ] = max [ i ] ;
loc - > max [ i ] = min [ i ] ;
}
else
{
loc - > min [ i ] = min [ i ] ;
loc - > max [ i ] = max [ i ] ;
}
}
}
}
}
}
}
}
2004-08-23 00:15:46 +00:00
errorcount + + ;
}
2012-12-15 19:20:33 +00:00
else
{
Cmd_TokenizeString ( line , true , false ) ;
2004-08-23 00:15:46 +00:00
2012-12-15 19:20:33 +00:00
argc = Cmd_Argc ( ) ;
if ( ! argc )
continue ;
2004-08-23 00:15:46 +00:00
2012-12-15 19:20:33 +00:00
if ( argc < 4 )
{
errorcount + + ;
continue ;
}
if ( atoi ( Cmd_Argv ( 0 ) ) = = 0 & & Cmd_Argv ( 0 ) [ 0 ] ! = ' 0 ' )
{
// first token is not a number
errorcount + + ;
continue ;
}
2020-04-19 01:23:32 +00:00
if ( loc_numentries = = loc_maxentries )
Z_ReallocElements ( ( void * * ) & locdata , & loc_maxentries , loc_numentries + 64 , sizeof ( * locdata ) ) ;
2012-12-15 19:20:33 +00:00
loc = & locdata [ loc_numentries ] ;
loc_numentries + + ;
2004-08-23 00:15:46 +00:00
2012-12-15 19:20:33 +00:00
for ( i = 0 ; i < 3 ; i + + )
loc - > min [ i ] = loc - > max [ i ] = atoi ( Cmd_Argv ( i ) ) / 8.0 ;
2004-08-23 00:15:46 +00:00
2012-12-15 19:20:33 +00:00
loc - > name [ 0 ] = 0 ;
for ( i = 3 ; i < argc ; i + + )
{
if ( i ! = 3 )
2020-04-19 01:23:32 +00:00
Q_strncatz ( loc - > name , " " , sizeof ( loc - > name ) ) ;
Q_strncatz ( loc - > name , Cmd_Argv ( i ) , sizeof ( loc - > name ) ) ;
2012-12-15 19:20:33 +00:00
}
2004-08-23 00:15:46 +00:00
}
}
if ( ! quiet )
2020-04-19 01:23:32 +00:00
Com_Printf ( " Loaded %s (%lu points) \n " , fullpath , ( unsigned long ) loc_numentries ) ;
2004-08-23 00:15:46 +00:00
}
2004-09-30 22:25:55 +00:00
static void TP_LoadLocFile_f ( void )
2004-08-23 00:15:46 +00:00
{
if ( Cmd_Argc ( ) ! = 2 )
{
Com_Printf ( " loadloc <filename> : load a loc file \n " ) ;
return ;
}
TP_LoadLocFile ( Cmd_Argv ( 1 ) , false ) ;
}
2019-09-04 07:59:40 +00:00
char * TP_LocationName ( const vec3_t location )
2004-08-23 00:15:46 +00:00
{
2012-12-15 19:20:33 +00:00
int i , j , minnum ;
2004-08-23 00:15:46 +00:00
float dist , mindist ;
vec3_t vec ;
static qbool recursive ;
2005-04-26 16:04:12 +00:00
static char buf [ MAX_LOC_NAME ] ;
2015-09-18 20:30:10 +00:00
int level ;
2011-05-15 13:23:13 +00:00
2004-08-23 00:15:46 +00:00
if ( ! loc_numentries | | ( cls . state ! = ca_active ) )
return tp_name_someplace . string ;
if ( recursive )
return " " ;
minnum = 0 ;
mindist = 9999999 ;
2012-12-15 19:20:33 +00:00
for ( i = 0 ; i < loc_numentries ; i + + )
{
//clip the point to the box, to find the nearest point within it.
for ( j = 0 ; j < 3 ; j + + )
vec [ j ] = bound ( locdata [ i ] . min [ j ] , location [ j ] , locdata [ i ] . max [ j ] ) ;
VectorSubtract ( location , vec , vec ) ;
2004-08-23 00:15:46 +00:00
dist = VectorLength ( vec ) ;
2012-12-15 19:20:33 +00:00
if ( dist < mindist )
{
2004-08-23 00:15:46 +00:00
minnum = i ;
mindist = dist ;
2012-12-15 19:20:33 +00:00
//break out if we're actually inside it, to always favour the first.
if ( dist < 0.01 )
break ;
2004-08-23 00:15:46 +00:00
}
}
recursive = true ;
2015-09-18 20:30:10 +00:00
level = Cmd_ExecLevel ;
2023-03-15 01:29:30 +00:00
Cmd_ExpandString ( locdata [ minnum ] . name , buf , sizeof ( buf ) , & level , false , true , false ) ;
2004-08-23 00:15:46 +00:00
recursive = false ;
return buf ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
MESSAGE TRIGGERS
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
// FIXME, we don't provide a way to remove triggers
// allocated heap memory is not freed when the engine shuts down
typedef struct msg_trigger_s {
char name [ 32 ] ;
char string [ 64 ] ;
int level ;
struct msg_trigger_s * next ;
} msg_trigger_t ;
static msg_trigger_t * msg_triggers ;
2004-09-30 22:25:55 +00:00
static msg_trigger_t * TP_FindTrigger ( char * name )
2004-08-23 00:15:46 +00:00
{
msg_trigger_t * t ;
for ( t = msg_triggers ; t ; t = t - > next )
if ( ! strcmp ( t - > name , name ) )
return t ;
return NULL ;
}
2004-09-30 22:25:55 +00:00
static void TP_MsgTrigger_f ( void )
2004-08-23 00:15:46 +00:00
{
int c ;
char * name ;
msg_trigger_t * trig ;
2019-12-10 14:50:47 +00:00
if ( Cmd_IsInsecure ( ) )
return ;
2004-08-23 00:15:46 +00:00
c = Cmd_Argc ( ) ;
if ( c > 5 ) {
Com_Printf ( " msg_trigger <trigger name> \" string \" [-l <level>] \n " ) ;
return ;
}
if ( c = = 1 ) {
if ( ! msg_triggers )
Com_Printf ( " no triggers defined \n " ) ;
else
for ( trig = msg_triggers ; trig ; trig = trig - > next )
Com_Printf ( " %s : \" %s \" \n " , trig - > name , trig - > string ) ;
return ;
}
name = Cmd_Argv ( 1 ) ;
if ( strlen ( name ) > 31 ) {
Com_Printf ( " trigger name too long \n " ) ;
return ;
}
if ( c = = 2 ) {
trig = TP_FindTrigger ( name ) ;
if ( trig )
Com_Printf ( " %s: \" %s \" \n " , trig - > name , trig - > string ) ;
else
Com_Printf ( " trigger \" %s \" not found \n " , name ) ;
return ;
}
if ( c > = 3 ) {
2021-04-14 05:21:04 +00:00
if ( strlen ( Cmd_Argv ( 2 ) ) > = countof ( trig - > string ) ) {
2004-08-23 00:15:46 +00:00
Com_Printf ( " trigger string too long \n " ) ;
return ;
}
2011-05-15 13:23:13 +00:00
2004-08-23 00:15:46 +00:00
trig = TP_FindTrigger ( name ) ;
if ( ! trig ) {
// allocate new trigger
trig = Z_Malloc ( sizeof ( msg_trigger_t ) ) ;
trig - > next = msg_triggers ;
msg_triggers = trig ;
strcpy ( trig - > name , name ) ; // safe (length checked earlier)
trig - > level = PRINT_HIGH ;
}
strcpy ( trig - > string , Cmd_Argv ( 2 ) ) ; // safe (length checked earlier)
if ( c = = 5 & & ! Q_stricmp ( Cmd_Argv ( 3 ) , " -l " ) ) {
if ( ! strcmp ( Cmd_Argv ( 4 ) , " t " ) )
trig - > level = 4 ;
else {
trig - > level = Q_atoi ( Cmd_Argv ( 4 ) ) ;
if ( ( unsigned ) trig - > level > PRINT_CHAT )
trig - > level = PRINT_HIGH ;
}
}
}
}
void TP_SearchForMsgTriggers ( char * s , int level )
{
msg_trigger_t * t ;
char * string ;
if ( cls . demoplayback )
return ;
2021-04-14 05:21:04 +00:00
if ( ! ruleset_allow_triggers . ival )
return ;
2004-08-23 00:15:46 +00:00
for ( t = msg_triggers ; t ; t = t - > next )
if ( ( t - > level = = level | | ( t - > level = = 3 & & level = = 4 ) )
& & t - > string [ 0 ] & & strstr ( s , t - > string ) )
{
if ( level = = PRINT_CHAT & & (
2017-01-24 10:27:39 +00:00
strstr ( s , " _version " ) | | strstr ( s , " _system " ) | |
strstr ( s , " _speed " ) | | strstr ( s , " _modified " ) | | strstr ( s , " _ruleset " ) ) )
2004-08-23 00:15:46 +00:00
continue ; // don't let llamas fake proxy replies
string = Cmd_AliasExist ( t - > name , RESTRICT_LOCAL ) ;
if ( string )
{
2020-04-19 01:23:32 +00:00
# ifdef QUAKESTATS
Q_strncpyz ( vars . lasttrigger_match , s , sizeof ( vars . lasttrigger_match ) ) ;
# endif
2004-08-23 00:15:46 +00:00
Cbuf_AddText ( string , RESTRICT_LOCAL ) ;
2005-09-05 00:08:12 +00:00
Cbuf_AddText ( " \n " , RESTRICT_LOCAL ) ;
2004-08-23 00:15:46 +00:00
// Cbuf_ExecuteLevel (RESTRICT_LOCAL);
}
else
Com_Printf ( " trigger \" %s \" has no matching alias \n " , t - > name ) ;
}
}
2018-03-04 14:41:16 +00:00
# ifdef QWSKINS
2004-08-23 00:15:46 +00:00
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
TEAMCOLOR & ENEMYCOLOR
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
2008-06-01 22:06:22 +00:00
unsigned int cl_teamtopcolor = ~ 0 ;
unsigned int cl_teambottomcolor = ~ 0 ;
unsigned int cl_enemytopcolor = ~ 0 ;
unsigned int cl_enemybottomcolor = ~ 0 ;
static unsigned int TP_ForceColour ( char * col )
{
float rgb [ 3 ] ;
unsigned int bitval ;
if ( ! strcmp ( col , " off " ) )
return ~ 0 ;
if ( ! strncmp ( col , " 0x " , 2 ) )
{
2008-06-05 07:45:34 +00:00
if ( strlen ( col + 2 ) = = 3 )
{
bitval = strtoul ( col + 2 , NULL , 16 ) ;
bitval = ( ( bitval & 0xf00 ) < < 12 ) | ( ( bitval & 0x0f0 ) < < 8 ) | ( ( bitval & 0x00f ) < < 4 ) ;
bitval | = 0x01000000 ;
}
else
bitval = 0x01000000 | strtoul ( col + 2 , NULL , 16 ) ;
if ( bitval = = ~ 0 )
bitval = 0x01ffffff ;
return bitval ;
}
if ( ! strncmp ( col , " x " , 1 ) )
{
if ( strlen ( col + 1 ) = = 3 )
{
bitval = strtoul ( col + 1 , NULL , 16 ) ;
bitval = ( ( bitval & 0xf00 ) < < 12 ) | ( ( bitval & 0x0f0 ) < < 8 ) | ( ( bitval & 0x00f ) < < 4 )
| ( ( bitval & 0xf00 ) < < 8 ) | ( ( bitval & 0x0f0 ) < < 4 ) | ( ( bitval & 0x00f ) < < 0 ) ;
bitval | = 0x01000000 ;
}
else
bitval = 0x01000000 | strtoul ( col + 1 , NULL , 16 ) ;
2008-06-01 22:06:22 +00:00
if ( bitval = = ~ 0 )
bitval = 0x01ffffff ;
return bitval ;
}
if ( strchr ( col , ' ' ) )
{
SCR_StringToRGB ( col , rgb , 1 ) ;
bitval = ( ( unsigned char ) rgb [ 0 ] < < 0 ) | ( ( unsigned char ) rgb [ 1 ] < < 8 ) | ( ( unsigned char ) rgb [ 2 ] < < 16 ) | ( 0xff < < 24 ) ;
if ( bitval = = ~ 0 )
bitval = 0x01ffffff ;
return bitval ;
}
return atoi ( col ) ;
}
2004-08-23 00:15:46 +00:00
2008-06-05 07:45:34 +00:00
colourised_t * TP_FindColours ( char * name )
{
colourised_t * col ;
for ( col = cls . colourised ; col ; col = col - > next )
{
if ( ! strncmp ( col - > name , name , sizeof ( col - > name ) - 1 ) )
{
return col ;
}
}
return NULL ;
}
static void TP_Colourise_f ( void )
{
int i ;
unsigned char * topstr , * botstr ;
colourised_t * col , * last ;
if ( Cmd_Argc ( ) = = 1 )
{
return ;
}
col = TP_FindColours ( Cmd_Argv ( 1 ) ) ;
if ( Cmd_Argc ( ) = = 2 )
{
if ( col )
{
if ( col = = cls . colourised )
cls . colourised = col - > next ;
else
{
for ( last = cls . colourised ; last ; last = last - > next )
{
if ( last - > next = = col )
{
last - > next = col - > next ;
break ;
}
}
}
Z_Free ( col ) ;
}
}
else
{
if ( ! col )
{
col = Z_Malloc ( sizeof ( * col ) ) ;
col - > next = cls . colourised ;
cls . colourised = col ;
Q_strncpyz ( col - > name , Cmd_Argv ( 1 ) , sizeof ( col - > skin ) ) ;
}
topstr = Cmd_Argv ( 2 ) ;
botstr = strchr ( topstr , ' . ' ) ;
if ( botstr )
* botstr + + = ' \0 ' ;
else
botstr = topstr ;
col - > topcolour = TP_ForceColour ( topstr ) ;
col - > bottomcolour = TP_ForceColour ( botstr ) ;
Q_strncpyz ( col - > skin , Cmd_Argv ( 3 ) , sizeof ( col - > skin ) ) ;
}
Skin_FlushPlayers ( ) ;
2013-10-29 17:38:22 +00:00
for ( i = 0 ; i < cl . allocated_client_slots ; i + + )
2008-06-05 07:45:34 +00:00
{
cl . players [ i ] . colourised = TP_FindColours ( cl . players [ i ] . name ) ;
CL_NewTranslation ( i ) ;
}
}
2019-09-17 19:49:39 +00:00
static void TP_TeamColor_CB ( struct cvar_s * var , char * oldvalue )
2004-08-23 00:15:46 +00:00
{
2008-06-01 22:06:22 +00:00
unsigned int top , bottom ;
2004-08-23 00:15:46 +00:00
int i ;
2019-09-17 19:49:39 +00:00
char * n = COM_Parse ( var - > string ) ;
top = TP_ForceColour ( com_token ) ;
COM_Parse ( n ) ;
if ( ! * com_token )
2008-06-01 22:06:22 +00:00
bottom = top ;
2004-08-23 00:15:46 +00:00
else {
2019-09-17 19:49:39 +00:00
bottom = TP_ForceColour ( com_token ) ;
2004-08-23 00:15:46 +00:00
}
2011-05-15 13:23:13 +00:00
2019-09-17 19:49:39 +00:00
cl_teamtopcolor = top ;
cl_teambottomcolor = bottom ;
2004-08-23 00:15:46 +00:00
2019-09-17 19:49:39 +00:00
if ( qrenderer ! = QR_NONE ) //make sure we have the renderer initialised...
for ( i = 0 ; i < cl . allocated_client_slots ; i + + )
CL_NewTranslation ( i ) ;
2004-08-23 00:15:46 +00:00
}
2019-09-17 19:49:39 +00:00
static void TP_EnemyColor_CB ( struct cvar_s * var , char * oldvalue )
2004-08-23 00:15:46 +00:00
{
2008-06-01 22:06:22 +00:00
unsigned int top , bottom ;
2004-08-23 00:15:46 +00:00
int i ;
2019-09-17 19:49:39 +00:00
char * n = COM_Parse ( var - > string ) ;
top = TP_ForceColour ( com_token ) ;
COM_Parse ( n ) ;
if ( ! * com_token )
2008-06-01 22:06:22 +00:00
bottom = top ;
2004-08-23 00:15:46 +00:00
else {
2019-09-17 19:49:39 +00:00
bottom = TP_ForceColour ( com_token ) ;
2004-08-23 00:15:46 +00:00
}
2019-09-17 19:49:39 +00:00
cl_enemytopcolor = top ;
cl_enemybottomcolor = bottom ;
2004-08-23 00:15:46 +00:00
2019-09-17 19:49:39 +00:00
if ( qrenderer ! = QR_NONE ) //make sure we have the renderer initialised...
for ( i = 0 ; i < cl . allocated_client_slots ; i + + )
CL_NewTranslation ( i ) ;
2004-08-23 00:15:46 +00:00
}
2019-09-17 19:49:39 +00:00
static void QDECL TP_SkinCvar_Callback ( struct cvar_s * var , char * oldvalue )
{
Skin_FlushPlayers ( ) ;
}
2018-03-04 14:41:16 +00:00
# endif
2004-08-23 00:15:46 +00:00
//===================================================================
void TP_NewMap ( void )
{
static char last_map [ MAX_QPATH ] ;
2016-08-25 00:12:14 +00:00
char locname [ MAX_QPATH ] ;
2004-08-23 00:15:46 +00:00
2020-04-19 01:23:32 +00:00
# ifdef QUAKESTATS
2004-08-23 00:15:46 +00:00
memset ( & vars , 0 , sizeof ( vars ) ) ;
TP_FindModelNumbers ( ) ;
2020-04-19 01:23:32 +00:00
# endif
2004-08-23 00:15:46 +00:00
// FIXME, just try to load the loc file no matter what?
if ( strcmp ( host_mapname . string , last_map ) )
{ // map name has changed
loc_numentries = 0 ; // clear loc file
2015-06-30 14:05:45 +00:00
if ( tp_loadlocs . value & & cl . allocated_client_slots > 1 ) // && !cls.demoplayback)
2006-04-05 21:52:22 +00:00
{
2004-08-23 00:15:46 +00:00
Q_snprintfz ( locname , sizeof ( locname ) , " %s.loc " , host_mapname . string ) ;
TP_LoadLocFile ( locname , true ) ;
2006-04-05 21:52:22 +00:00
strlcpy ( last_map , host_mapname . string , sizeof ( last_map ) ) ;
2004-08-23 00:15:46 +00:00
}
2006-04-05 21:52:22 +00:00
else
strlcpy ( last_map , " " , sizeof ( last_map ) ) ;
2004-08-23 00:15:46 +00:00
}
2020-04-19 01:23:32 +00:00
# ifdef QUAKESTATS
2008-11-09 22:29:28 +00:00
TP_UpdateAutoStatus ( ) ;
2020-04-19 01:23:32 +00:00
# endif
2015-06-16 23:53:58 +00:00
TP_ExecTrigger ( " f_newmap " , false ) ;
2004-08-23 00:15:46 +00:00
}
/*
= = = = = = = = = = = = = = = = = = = = = =
TP_CategorizeMessage
returns a combination of these values :
2005-09-08 08:10:06 +00:00
0 - - unknown
2004-08-23 00:15:46 +00:00
1 - - normal
2 - - team message
4 - - spectator
2005-09-07 14:55:25 +00:00
16 - - faked or serverside
2004-08-23 00:15:46 +00:00
Note that sometimes we can ' t be sure who really sent the message ,
e . g . when there ' s a player " unnamed " in your team and " (unnamed) "
in the enemy team . The result will be 3 ( 1 + 2 )
Never returns 2 if we are a spectator .
2005-09-07 14:55:25 +00:00
Now additionally returns player info ( NULL if no player detected )
2004-08-23 00:15:46 +00:00
= = = = = = = = = = = = = = = = = = = = = =
*/
2005-09-07 14:55:25 +00:00
int TP_CategorizeMessage ( char * s , int * offset , player_info_t * * plr )
2004-08-23 00:15:46 +00:00
{
int i , msglen , len ;
int flags ;
player_info_t * player ;
char * name ;
2017-05-28 15:42:32 +00:00
playerview_t * pv = & cl . playerview [ SP ] ;
2004-08-23 00:15:46 +00:00
2015-04-14 23:12:17 +00:00
* offset = 0 ;
* plr = NULL ;
2005-09-08 08:10:06 +00:00
flags = TPM_UNKNOWN ;
2004-08-23 00:15:46 +00:00
msglen = strlen ( s ) ;
if ( ! msglen )
2005-09-08 08:10:06 +00:00
return TPM_UNKNOWN ;
2004-08-23 00:15:46 +00:00
2015-04-14 23:12:17 +00:00
if ( ( s [ 0 ] = = ' ^ ' & & s [ 1 ] = = ' [ ' ) | | ( s [ 0 ] = = ' ( ' & & s [ 1 ] = = ' ^ ' & & s [ 2 ] = = ' [ ' ) )
2004-08-23 00:15:46 +00:00
{
2015-04-14 23:12:17 +00:00
char * end , * info ;
i = 0 ;
for ( info = s ; * info ; )
{
if ( info [ 0 ] = = ' ^ ' & & info [ 1 ] = = ' ] ' )
break ;
if ( * info = = ' \\ ' )
break ;
if ( info [ 0 ] = = ' ^ ' & & info [ 1 ] = = ' ^ ' )
info + = 2 ;
else
info + + ;
}
for ( end = info ; * end ; )
{
if ( end [ 0 ] = = ' ^ ' & & end [ 1 ] = = ' ] ' )
{
* end = 0 ;
info = Info_ValueForKey ( info , " player " ) ;
if ( * info )
i = atoi ( info ) + 1 ;
* end = ' ^ ' ;
break ;
}
if ( end [ 0 ] = = ' ^ ' & & end [ 1 ] = = ' ^ ' )
end + = 2 ;
else
end + + ;
}
if ( ! * end | | i < 1 | | i > cl . allocated_client_slots )
return TPM_UNKNOWN ;
if ( * s = = ' ( ' )
{
if ( end [ 2 ] ! = ' ) ' )
return TPM_UNKNOWN ;
end + = 3 ;
}
else
end + = 2 ;
if ( * end + + ! = ' : ' )
return TPM_UNKNOWN ;
if ( * end + + ! = ' ' )
return TPM_UNKNOWN ;
* plr = player = & cl . players [ i - 1 ] ;
* offset = end - s ;
if ( * s = = ' ( ' )
flags = TPM_TEAM ;
else
2004-08-23 00:15:46 +00:00
{
if ( player - > spectator )
2005-09-08 08:10:06 +00:00
flags | = TPM_SPECTATOR ;
2004-08-23 00:15:46 +00:00
else
2005-09-08 08:10:06 +00:00
flags | = TPM_NORMAL ;
2004-08-23 00:15:46 +00:00
}
2015-04-14 23:12:17 +00:00
}
else
{
for ( i = 0 , player = cl . players ; i < cl . allocated_client_slots ; i + + , player + + )
2004-08-23 00:15:46 +00:00
{
2015-04-14 23:12:17 +00:00
name = player - > name ;
if ( ! ( * name ) )
continue ;
len = strlen ( name ) ;
// check messagemode1
if ( len + 2 < = msglen & & s [ len ] = = ' : ' & & s [ len + 1 ] = = ' ' & &
! strncmp ( name , s , len ) )
2011-05-15 13:23:13 +00:00
{
2015-04-14 23:12:17 +00:00
if ( player - > spectator )
flags | = TPM_SPECTATOR ;
else
flags | = TPM_NORMAL ;
* offset = len + 2 ;
* plr = player ;
2008-11-09 22:29:28 +00:00
}
2015-04-14 23:12:17 +00:00
// check messagemode2
else if ( s [ 0 ] = = ' ( ' & & len + 4 < = msglen & &
! strncmp ( s + len + 1 , " ): " , 3 ) & &
! strncmp ( name , s + 1 , len ) )
2008-11-09 22:29:28 +00:00
{
2015-04-14 23:12:17 +00:00
// no team messages in teamplay 0, except for our own
2017-05-28 15:42:32 +00:00
if ( pv - > spectator )
2008-11-09 22:29:28 +00:00
{
2017-05-28 15:42:32 +00:00
unsigned int track = Cam_TrackNum ( pv ) ;
2015-04-14 23:12:17 +00:00
if ( i = = track | | ( cl . teamplay & &
! strcmp ( cl . players [ track ] . team , player - > team ) ) )
{
flags | = TPM_OBSERVEDTEAM ;
}
}
else
{
2017-05-28 15:42:32 +00:00
if ( i = = pv - > playernum | | ( cl . teamplay & &
! strcmp ( cl . players [ pv - > playernum ] . team , player - > team ) ) )
2015-04-14 23:12:17 +00:00
{
flags | = TPM_TEAM ;
}
2008-11-09 22:29:28 +00:00
}
2005-09-07 14:55:25 +00:00
2015-04-14 23:12:17 +00:00
* offset = len + 4 ;
* plr = player ;
}
2005-09-07 14:55:25 +00:00
}
2015-06-14 01:28:01 +00:00
// if (i == cl.allocated_client_slots)
// return flags;
}
/*
if ( ! flags ) // search for fake/non player
2005-09-07 14:55:25 +00:00
{
2006-03-04 20:43:48 +00:00
if ( ( name = strstr ( s , " : " ) ) ) // use name as temp
2005-09-07 14:55:25 +00:00
{
* offset = ( name - s ) + 2 ;
2005-09-08 08:10:06 +00:00
flags = TPM_FAKED ;
2009-03-03 01:52:30 +00:00
if ( msglen > 4 & & * s = = ' ( ' & & s [ - 1 ] = = ' ) ' )
flags | = TPM_TEAM ;
2004-08-23 00:15:46 +00:00
}
}
2015-06-14 01:28:01 +00:00
*/
2004-08-23 00:15:46 +00:00
2015-06-18 22:11:30 +00:00
if ( ! flags )
{
char * qtv = NULL ;
2016-07-12 00:40:13 +00:00
if ( ! strncmp ( s , " #0:qtv_say:# " , 12 ) )
{
qtv = s + 11 ;
flags = TPM_QTV | TPM_SPECTATOR ;
}
else if ( ! strncmp ( s , " #0:qtv_say_game:# " , 17 ) )
2015-06-18 22:11:30 +00:00
{
qtv = s + 16 ;
flags = TPM_QTV | TPM_SPECTATOR ;
}
else if ( ! strncmp ( s , " #0:qtv_say_team_game:# " , 22 ) )
{
qtv = s + 21 ;
flags = TPM_QTV | TPM_TEAM | TPM_SPECTATOR ;
}
if ( flags )
{
* offset = ( qtv - s ) ;
for ( ; ; )
{
char * sub = qtv ;
if ( * sub = = ' # ' )
{
strtoul ( sub + 1 , & sub , 10 ) ;
if ( * sub + + = = ' : ' )
{
qtv = strstr ( sub , " : " ) ;
if ( qtv )
{
* offset = ( sub - s ) ;
qtv + = 2 ;
continue ;
}
}
}
break ;
}
}
}
2004-08-23 00:15:46 +00:00
return flags ;
}
2020-04-19 01:23:32 +00:00
# ifdef QUAKESTATS
2004-08-23 00:15:46 +00:00
//===================================================================
// Pickup triggers
//
// symbolic names used in tp_took, tp_pickup, tp_point commands
2005-04-26 16:04:12 +00:00
char * pknames [ ] = { " quad " , " pent " , " ring " , " suit " , " ra " , " ya " , " ga " ,
2004-08-23 00:15:46 +00:00
" mh " , " health " , " lg " , " rl " , " gl " , " sng " , " ng " , " ssg " , " pack " ,
2011-05-15 13:23:13 +00:00
" cells " , " rockets " , " nails " , " shells " , " flag " ,
2005-04-26 16:04:12 +00:00
" teammate " , " enemy " , " eyes " , " sentry " , " disp " , " runes " } ;
# define it_quad (1 << 0)
# define it_pent (1 << 1)
# define it_ring (1 << 2)
# define it_suit (1 << 3)
# define it_ra (1 << 4)
# define it_ya (1 << 5)
# define it_ga (1 << 6)
# define it_mh (1 << 7)
# define it_health (1 << 8)
# define it_lg (1 << 9)
# define it_rl (1 << 10)
# define it_gl (1 << 11)
# define it_sng (1 << 12)
# define it_ng (1 << 13)
# define it_ssg (1 << 14)
# define it_pack (1 << 15)
# define it_cells (1 << 16)
# define it_rockets (1 << 17)
# define it_nails (1 << 18)
# define it_shells (1 << 19)
# define it_flag (1 << 20)
# define it_teammate (1 << 21)
# define it_enemy (1 << 22)
# define it_eyes (1 << 23)
# define it_sentry (1 << 24)
# define it_disp (1 << 25)
# define it_runes (1 << 26)
# define NUM_ITEMFLAGS 27
2004-08-23 00:15:46 +00:00
# define it_powerups (it_quad|it_pent|it_ring)
# define it_weapons (it_lg|it_rl|it_gl|it_sng|it_ng|it_ssg)
# define it_armor (it_ra|it_ya|it_ga)
# define it_ammo (it_cells|it_rockets|it_nails|it_shells)
2005-04-26 16:04:12 +00:00
# define it_players (it_teammate|it_enemy|it_eyes)
2004-08-23 00:15:46 +00:00
# define default_pkflags (it_powerups|it_suit|it_armor|it_weapons|it_mh| \
it_rockets | it_pack | it_flag )
2005-04-26 16:04:12 +00:00
# define default_tookflags (it_powerups|it_ra|it_ya|it_lg|it_rl|it_mh|it_flag)
2004-08-23 00:15:46 +00:00
# define default_pointflags (it_powerups|it_suit|it_armor|it_mh| \
2005-04-26 16:04:12 +00:00
it_lg | it_rl | it_gl | it_sng | it_rockets | it_pack | it_flag | it_players )
2004-08-23 00:15:46 +00:00
2005-04-26 16:04:12 +00:00
int pkflags = default_pkflags ;
int tookflags = default_tookflags ;
int pointflags = default_pointflags ;
2004-08-23 00:15:46 +00:00
2005-04-26 16:04:12 +00:00
static void FlagCommand ( int * flags , int defaultflags ) {
int i , j , c , flag ;
char * p , str [ 255 ] = { 0 } ;
qboolean removeflag = false ;
2004-08-23 00:15:46 +00:00
c = Cmd_Argc ( ) ;
2005-04-26 16:04:12 +00:00
if ( c = = 1 ) {
2004-08-23 00:15:46 +00:00
if ( ! * flags )
2005-04-26 16:04:12 +00:00
strcpy ( str , " none " ) ;
for ( i = 0 ; i < NUM_ITEMFLAGS ; i + + )
if ( * flags & ( 1 < < i ) ) {
2004-08-23 00:15:46 +00:00
if ( * str )
2020-04-19 01:23:32 +00:00
Q_strncatz ( str , " " , sizeof ( str ) ) ;
Q_strncatz ( str , pknames [ i ] , sizeof ( str ) ) ;
2004-08-23 00:15:46 +00:00
}
Com_Printf ( " %s \n " , str ) ;
return ;
}
2005-04-26 16:04:12 +00:00
if ( c = = 2 & & ! Q_strcasecmp ( Cmd_Argv ( 1 ) , " none " ) ) {
* flags = 0 ;
return ;
}
2004-08-23 00:15:46 +00:00
if ( * Cmd_Argv ( 1 ) ! = ' + ' & & * Cmd_Argv ( 1 ) ! = ' - ' )
* flags = 0 ;
2005-04-26 16:04:12 +00:00
for ( i = 1 ; i < c ; i + + ) {
2004-08-23 00:15:46 +00:00
p = Cmd_Argv ( i ) ;
if ( * p = = ' + ' ) {
removeflag = false ;
p + + ;
} else if ( * p = = ' - ' ) {
removeflag = true ;
p + + ;
}
flag = 0 ;
for ( j = 0 ; j < NUM_ITEMFLAGS ; j + + ) {
2005-04-26 16:04:12 +00:00
if ( ! Q_strncasecmp ( p , pknames [ j ] , 3 ) ) {
2004-08-23 00:15:46 +00:00
flag = 1 < < j ;
break ;
}
}
if ( ! flag ) {
2005-04-26 16:04:12 +00:00
if ( ! Q_strcasecmp ( p , " armor " ) )
flag = it_armor ;
else if ( ! Q_strcasecmp ( p , " weapons " ) )
flag = it_weapons ;
else if ( ! Q_strcasecmp ( p , " powerups " ) )
flag = it_powerups ;
else if ( ! Q_strcasecmp ( p , " ammo " ) )
flag = it_ammo ;
else if ( ! Q_strcasecmp ( p , " players " ) )
flag = it_players ;
else if ( ! Q_strcasecmp ( p , " default " ) )
2004-08-23 00:15:46 +00:00
flag = defaultflags ;
2005-04-26 16:04:12 +00:00
else if ( ! Q_strcasecmp ( p , " all " ) )
2004-08-23 00:15:46 +00:00
flag = ( 1 < < NUM_ITEMFLAGS ) - 1 ;
}
2011-05-15 13:23:13 +00:00
2005-04-26 16:04:12 +00:00
if ( flags ! = & pointflags )
flag & = ~ ( it_sentry | it_disp | it_players ) ;
2004-08-23 00:15:46 +00:00
if ( removeflag )
* flags & = ~ flag ;
else
* flags | = flag ;
}
}
2004-09-30 22:25:55 +00:00
static void TP_Took_f ( void )
2004-08-23 00:15:46 +00:00
{
FlagCommand ( & tookflags , default_tookflags ) ;
}
void TP_Pickup_f ( void )
{
FlagCommand ( & pkflags , default_pkflags ) ;
}
2004-09-30 22:25:55 +00:00
static void TP_Point_f ( void )
2004-08-23 00:15:46 +00:00
{
FlagCommand ( & pointflags , default_pointflags ) ;
}
/*
// FIXME: maybe use sound indexes so we don't have to make strcmp's
// every time?
# define S_LOCK4 1 // weapons/lock4.wav
# define S_PKUP 2 // weapons/pkup.wav
# define S_HEALTH25 3 // items/health1.wav
# define S_HEALTH15 4 // items/r_item1.wav
# define S_MHEALTH 5 // items/r_item2.wav
# define S_DAMAGE 6 // items/damage.wav
# define S_EYES 7 // items/inv1.wav
# define S_PENT 8 // items/protect.wav
# define S_ARMOR 9 // items/armor1.wav
static char * tp_soundnames [ ] =
{
" weapons/lock4.wav " ,
" weapons/pkup.wav " ,
" items/health1.wav " ,
" items/r_item1.wav " ,
" items/r_item2.wav " ,
" items/damage.wav " ,
" items/inv1.wav " ,
" items/protect.wav "
" items/armor1.wav "
} ;
# define TP_NUMSOUNDS (sizeof(tp_soundnames) / sizeof(tp_soundnames[0]))
int sound_numbers [ MAX_SOUNDS ] ;
void TP_FindSoundNumbers ( void )
{
int i , j ;
char * s ;
for ( i = 0 ; i < MAX_SOUNDS ; i + + )
{
s = & cl . sound_name [ i ] ;
for ( j = 0 ; j < TP_NUMSOUNDS ; j + + )
. . .
}
}
*/
typedef struct {
int itemflag ;
cvar_t * cvar ;
char * modelname ;
vec3_t offset ; // offset of model graphics center
float radius ; // model graphics radius
2015-08-07 17:49:49 +00:00
float respawntime ; // automatic respawn timer for mvds.
2004-08-23 00:15:46 +00:00
int flags ; // TODO: "NOPICKUP" (disp), "TEAMENEMY" (flag, disp)
} item_t ;
2004-09-30 22:25:55 +00:00
static item_t tp_items [ ] = {
2004-08-23 00:15:46 +00:00
{ it_quad , & tp_name_quad , " progs/quaddama.mdl " ,
2015-08-07 17:49:49 +00:00
{ 0 , 0 , 24 } , 25 , 60
2004-08-23 00:15:46 +00:00
} ,
{ it_pent , & tp_name_pent , " progs/invulner.mdl " ,
2015-08-07 17:49:49 +00:00
{ 0 , 0 , 22 } , 25 , 5 * 60
2004-08-23 00:15:46 +00:00
} ,
{ it_ring , & tp_name_ring , " progs/invisibl.mdl " ,
2015-08-07 17:49:49 +00:00
{ 0 , 0 , 16 } , 12 , 5 * 60
2004-08-23 00:15:46 +00:00
} ,
{ it_suit , & tp_name_suit , " progs/suit.mdl " ,
2015-08-07 17:49:49 +00:00
{ 0 , 0 , 24 } , 20 , 60
2004-08-23 00:15:46 +00:00
} ,
{ it_lg , & tp_name_lg , " progs/g_light.mdl " ,
2015-08-07 17:49:49 +00:00
{ 0 , 0 , 30 } , 20 , 30
2004-08-23 00:15:46 +00:00
} ,
{ it_rl , & tp_name_rl , " progs/g_rock2.mdl " ,
2015-08-07 17:49:49 +00:00
{ 0 , 0 , 30 } , 20 , 30
2004-08-23 00:15:46 +00:00
} ,
{ it_gl , & tp_name_gl , " progs/g_rock.mdl " ,
2015-08-07 17:49:49 +00:00
{ 0 , 0 , 30 } , 20 , 30
2004-08-23 00:15:46 +00:00
} ,
{ it_sng , & tp_name_sng , " progs/g_nail2.mdl " ,
2015-08-07 17:49:49 +00:00
{ 0 , 0 , 30 } , 20 , 30
2004-08-23 00:15:46 +00:00
} ,
{ it_ng , & tp_name_ng , " progs/g_nail.mdl " ,
2015-08-07 17:49:49 +00:00
{ 0 , 0 , 30 } , 20 , 30
2004-08-23 00:15:46 +00:00
} ,
{ it_ssg , & tp_name_ssg , " progs/g_shot.mdl " ,
2015-08-07 17:49:49 +00:00
{ 0 , 0 , 30 } , 20 , 30
2004-08-23 00:15:46 +00:00
} ,
{ it_cells , & tp_name_cells , " maps/b_batt0.bsp " ,
2015-08-07 17:49:49 +00:00
{ 16 , 16 , 24 } , 18 , 30
2004-08-23 00:15:46 +00:00
} ,
{ it_cells , & tp_name_cells , " maps/b_batt1.bsp " ,
2015-08-07 17:49:49 +00:00
{ 16 , 16 , 24 } , 18 , 30
2004-08-23 00:15:46 +00:00
} ,
{ it_rockets , & tp_name_rockets , " maps/b_rock0.bsp " ,
2015-08-07 17:49:49 +00:00
{ 8 , 8 , 20 } , 18 , 30
2004-08-23 00:15:46 +00:00
} ,
{ it_rockets , & tp_name_rockets , " maps/b_rock1.bsp " ,
2015-08-07 17:49:49 +00:00
{ 16 , 8 , 20 } , 18 , 30
2004-08-23 00:15:46 +00:00
} ,
{ it_nails , & tp_name_nails , " maps/b_nail0.bsp " ,
2015-08-07 17:49:49 +00:00
{ 16 , 16 , 10 } , 18 , 30
2004-08-23 00:15:46 +00:00
} ,
{ it_nails , & tp_name_nails , " maps/b_nail1.bsp " ,
2015-08-07 17:49:49 +00:00
{ 16 , 16 , 10 } , 18 , 30
2004-08-23 00:15:46 +00:00
} ,
{ it_shells , & tp_name_shells , " maps/b_shell0.bsp " ,
2015-08-07 17:49:49 +00:00
{ 16 , 16 , 10 } , 18 , 30
2004-08-23 00:15:46 +00:00
} ,
{ it_shells , & tp_name_shells , " maps/b_shell1.bsp " ,
2015-08-07 17:49:49 +00:00
{ 16 , 16 , 10 } , 18 , 30
2004-08-23 00:15:46 +00:00
} ,
{ it_health , & tp_name_health , " maps/b_bh10.bsp " ,
2015-08-07 17:49:49 +00:00
{ 16 , 16 , 8 } , 18 , 20
2004-08-23 00:15:46 +00:00
} ,
{ it_health , & tp_name_health , " maps/b_bh25.bsp " ,
2015-08-07 17:49:49 +00:00
{ 16 , 16 , 8 } , 18 , 20
2004-08-23 00:15:46 +00:00
} ,
{ it_mh , & tp_name_mh , " maps/b_bh100.bsp " ,
2015-08-07 17:49:49 +00:00
{ 16 , 16 , 14 } , 20 , 0
2004-08-23 00:15:46 +00:00
} ,
{ it_pack , & tp_name_backpack , " progs/backpack.mdl " ,
2015-08-07 17:49:49 +00:00
{ 0 , 0 , 18 } , 18 , 0
2004-08-23 00:15:46 +00:00
} ,
{ it_flag , & tp_name_flag , " progs/tf_flag.mdl " ,
2015-08-07 17:49:49 +00:00
{ 0 , 0 , 14 } , 25 , 0
2004-08-23 00:15:46 +00:00
} ,
{ it_flag , & tp_name_flag , " progs/tf_stan.mdl " ,
2015-08-07 17:49:49 +00:00
{ 0 , 0 , 45 } , 40 , 0
2004-08-23 00:15:46 +00:00
} ,
2020-04-19 01:23:32 +00:00
{ it_ra | it_ya | it_ga , & tp_name_armor , " progs/armor.mdl " , //generic armour, used only when the skin number if invalid for the other types.
2015-08-07 17:49:49 +00:00
{ 0 , 0 , 24 } , 22 , 0
} ,
{ it_ga , & tp_name_ga , " progs/armor.mdl " ,
{ 0 , 0 , 24 } , 22 , 20
} ,
{ it_ya , & tp_name_ya , " progs/armor.mdl " ,
{ 0 , 0 , 24 } , 22 , 20
} ,
{ it_ra , & tp_name_ra , " progs/armor.mdl " ,
{ 0 , 0 , 24 } , 22 , 20
2005-02-28 07:16:19 +00:00
} ,
{ it_flag , & tp_name_flag , " progs/w_g_key.mdl " ,
2015-08-07 17:49:49 +00:00
{ 0 , 0 , 20 } , 18 , 0
2005-02-28 07:16:19 +00:00
} ,
{ it_flag , & tp_name_flag , " progs/w_s_key.mdl " ,
2015-08-07 17:49:49 +00:00
{ 0 , 0 , 20 } , 18 , 0
2005-02-28 07:16:19 +00:00
} ,
{ it_flag , & tp_name_flag , " progs/m_g_key.mdl " ,
2015-08-07 17:49:49 +00:00
{ 0 , 0 , 20 } , 18 , 0
2005-02-28 07:16:19 +00:00
} ,
{ it_flag , & tp_name_flag , " progs/m_s_key.mdl " ,
2015-08-07 17:49:49 +00:00
{ 0 , 0 , 20 } , 18 , 0
2005-02-28 07:16:19 +00:00
} ,
{ it_flag , & tp_name_flag , " progs/b_s_key.mdl " ,
2015-08-07 17:49:49 +00:00
{ 0 , 0 , 20 } , 18 , 0
2005-02-28 07:16:19 +00:00
} ,
{ it_flag , & tp_name_flag , " progs/b_g_key.mdl " ,
2015-08-07 17:49:49 +00:00
{ 0 , 0 , 20 } , 18 , 0
2005-02-28 07:16:19 +00:00
} ,
{ it_flag , & tp_name_flag , " progs/flag.mdl " ,
2015-08-07 17:49:49 +00:00
{ 0 , 0 , 14 } , 25 , 0
2005-02-28 07:16:19 +00:00
} ,
{ it_runes , & tp_name_rune_1 , " progs/end1.mdl " ,
2015-08-07 17:49:49 +00:00
{ 0 , 0 , 20 } , 18 , 0
2005-02-28 07:16:19 +00:00
} ,
{ it_runes , & tp_name_rune_2 , " progs/end2.mdl " ,
2015-08-07 17:49:49 +00:00
{ 0 , 0 , 20 } , 18 , 0
2005-02-28 07:16:19 +00:00
} ,
{ it_runes , & tp_name_rune_3 , " progs/end3.mdl " ,
2015-08-07 17:49:49 +00:00
{ 0 , 0 , 20 } , 18 , 0
2005-02-28 07:16:19 +00:00
} ,
{ it_runes , & tp_name_rune_4 , " progs/end4.mdl " ,
2015-08-07 17:49:49 +00:00
{ 0 , 0 , 20 } , 18 , 0
2005-02-28 07:16:19 +00:00
} ,
{ it_sentry , & tp_name_sentry , " progs/turrgun.mdl " ,
2015-08-07 17:49:49 +00:00
{ 0 , 0 , 23 } , 25 , 0
2005-02-28 07:16:19 +00:00
} ,
{ it_disp , & tp_name_disp , " progs/disp.mdl " ,
2015-08-07 17:49:49 +00:00
{ 0 , 0 , 24 } , 25 , 0
2004-08-23 00:15:46 +00:00
}
} ;
# define NUMITEMS (sizeof(tp_items) / sizeof(tp_items[0]))
2014-09-17 03:04:08 +00:00
static item_t * model2item [ MAX_PRECACHE_MODELS ] ;
2004-08-23 00:15:46 +00:00
2004-09-30 22:25:55 +00:00
static void TP_FindModelNumbers ( void )
2004-08-23 00:15:46 +00:00
{
int i , j ;
char * s ;
item_t * item ;
2014-09-17 03:04:08 +00:00
for ( i = 0 ; i < MAX_PRECACHE_MODELS ; i + + ) {
2004-08-23 00:15:46 +00:00
model2item [ i ] = NULL ;
s = cl . model_name [ i ] ;
if ( ! s )
continue ;
for ( j = 0 , item = tp_items ; j < NUMITEMS ; j + + , item + + )
if ( ! strcmp ( s , item - > modelname ) )
2015-08-28 03:13:45 +00:00
{
2004-08-23 00:15:46 +00:00
model2item [ i ] = item ;
2015-08-28 03:13:45 +00:00
break ;
}
2004-08-23 00:15:46 +00:00
}
}
// on success, result is non-zero
// on failure, result is zero
// for armors, returns skinnum+1 on success
2015-08-07 17:49:49 +00:00
static int FindNearestItem ( vec3_t org , int flags , item_t * * pitem )
2004-08-23 00:15:46 +00:00
{
2013-03-12 22:53:23 +00:00
inframe_t * frame ;
2004-08-23 00:15:46 +00:00
packet_entities_t * pak ;
entity_state_t * ent ;
int i = 0 , bestidx = 0 , bestskin = 0 ;
float bestdist = 0.0 , dist = 0.0 ;
2015-08-07 17:49:49 +00:00
vec3_t v ;
2004-08-23 00:15:46 +00:00
item_t * item ;
2015-08-07 17:49:49 +00:00
entity_state_t * baseline ;
2004-08-23 00:15:46 +00:00
2011-05-15 13:23:13 +00:00
// look in previous frame
2013-03-12 22:53:23 +00:00
frame = & cl . inframes [ cl . oldvalidsequence & UPDATE_MASK ] ;
2004-08-23 00:15:46 +00:00
pak = & frame - > packet_entities ;
bestdist = 100.0f ;
bestidx = 0 ;
* pitem = NULL ;
for ( i = 0 , ent = pak - > entities ; i < pak - > num_entities ; i + + , ent + + )
{
item = model2item [ ent - > modelindex ] ;
if ( ! item )
continue ;
if ( ! ( item - > itemflag & flags ) )
continue ;
VectorCopy ( ent - > origin , v ) ;
VectorSubtract ( v , org , v ) ;
VectorAdd ( v , item - > offset , v ) ;
dist = VectorLength ( v ) ;
// Com_Printf ("%s %f\n", item->modelname, dist);
if ( dist < = bestdist ) {
bestdist = dist ;
2015-08-07 17:49:49 +00:00
bestidx = ent - > number ;
2004-08-23 00:15:46 +00:00
bestskin = ent - > skinnum ;
* pitem = item ;
}
}
2015-08-07 17:49:49 +00:00
if ( ! bestidx )
for ( i = 1 ; i < cl_baselines_count ; i + + )
{
baseline = & cl_baselines [ i ] ;
item = model2item [ baseline - > modelindex ] ;
if ( ! item )
continue ;
if ( ! ( item - > itemflag & flags ) )
continue ;
VectorCopy ( baseline - > origin , v ) ;
VectorSubtract ( v , org , v ) ;
VectorAdd ( v , item - > offset , v ) ;
dist = VectorLength ( v ) ;
// Com_Printf ("%s %f\n", item->modelname, dist);
if ( dist < = bestdist ) {
bestdist = dist ;
bestidx = i ;
bestskin = baseline - > skinnum ;
* pitem = item ;
}
}
2004-08-23 00:15:46 +00:00
if ( bestidx & & ( * pitem ) - > itemflag = = it_armor )
2015-08-07 17:49:49 +00:00
if ( bestskin > = 0 & & bestskin < = 3 )
* pitem + = bestskin + 1 ;
2004-08-23 00:15:46 +00:00
return bestidx ;
}
static int CountTeammates ( void )
{
int i , count ;
player_info_t * player ;
char * myteam ;
2009-11-04 21:16:50 +00:00
if ( tp_forceTriggers . ival )
2004-08-23 00:15:46 +00:00
return 1 ;
if ( ! cl . teamplay )
return 0 ;
count = 0 ;
2013-06-23 02:17:02 +00:00
myteam = cl . players [ cl . playerview [ SP ] . playernum ] . team ;
2013-10-29 17:38:22 +00:00
for ( i = 0 , player = cl . players ; i < cl . allocated_client_slots ; i + + , player + + ) {
2013-06-23 02:17:02 +00:00
if ( player - > name [ 0 ] & & ! player - > spectator & & ( i ! = cl . playerview [ SP ] . playernum )
2004-08-23 00:15:46 +00:00
& & ! strcmp ( player - > team , myteam ) )
count + + ;
}
return count ;
}
2005-04-26 16:04:12 +00:00
static qboolean CheckTrigger ( void )
2004-08-23 00:15:46 +00:00
{
2005-04-26 16:04:12 +00:00
int i , count ;
player_info_t * player ;
char * myteam ;
2017-05-28 15:42:32 +00:00
playerview_t * pv = & cl . playerview [ SP ] ;
2004-08-23 00:15:46 +00:00
2017-05-28 15:42:32 +00:00
if ( pv - > spectator )
2005-04-26 16:04:12 +00:00
return false ;
2004-08-23 00:15:46 +00:00
2009-11-04 21:16:50 +00:00
if ( tp_forceTriggers . ival )
2005-04-26 16:04:12 +00:00
return true ;
2004-08-23 00:15:46 +00:00
2005-04-26 16:04:12 +00:00
if ( ! cl . teamplay )
return false ;
count = 0 ;
2017-05-28 15:42:32 +00:00
myteam = cl . players [ pv - > playernum ] . team ;
2013-10-29 17:38:22 +00:00
for ( i = 0 , player = cl . players ; i < cl . allocated_client_slots ; i + + , player + + ) {
2017-05-28 15:42:32 +00:00
if ( player - > name [ 0 ] & & ! player - > spectator & & i ! = pv - > playernum & & ! strcmp ( player - > team , myteam ) )
2005-04-26 16:04:12 +00:00
count + + ;
2004-08-23 00:15:46 +00:00
}
2005-04-26 16:04:12 +00:00
return count ;
}
2015-08-07 17:49:49 +00:00
static void ExecTookTrigger_ ( char * s , int flag , vec3_t org )
2005-04-26 16:04:12 +00:00
{
int pkflags_dmm , tookflags_dmm ;
2004-08-23 00:15:46 +00:00
2005-04-26 16:04:12 +00:00
pkflags_dmm = pkflags ;
tookflags_dmm = tookflags ;
2011-05-15 13:23:13 +00:00
2005-04-26 16:04:12 +00:00
if ( ! cl . teamfortress & & cl . deathmatch > = 1 & & cl . deathmatch < = 4 ) {
if ( cl . deathmatch = = 4 ) {
pkflags_dmm & = ~ ( it_ammo | it_weapons ) ;
tookflags_dmm & = ~ ( it_ammo | it_weapons ) ;
2004-08-23 00:15:46 +00:00
}
}
2005-04-26 16:04:12 +00:00
if ( ! ( ( pkflags_dmm | tookflags_dmm ) & flag ) )
return ;
2004-08-23 00:15:46 +00:00
2005-04-26 16:04:12 +00:00
vars . tooktime = realtime ;
strncpy ( vars . tookname , s , sizeof ( vars . tookname ) - 1 ) ;
strncpy ( vars . tookloc , TP_LocationName ( org ) , sizeof ( vars . tookloc ) - 1 ) ;
if ( ( tookflags_dmm & flag ) & & CheckTrigger ( ) )
2015-06-16 23:53:58 +00:00
TP_ExecTrigger ( " f_took " , false ) ;
2004-08-23 00:15:46 +00:00
}
2015-08-07 17:49:49 +00:00
/*
void TP_GetSimpleItemTexture ( )
{
}
*/
static void TP_ItemTaken ( char * s , int flag , vec3_t org , int entnum , item_t * item , int seat )
{
if ( seat = = 0 )
ExecTookTrigger_ ( s , flag , org ) ;
/* if (entnum < cl_baselines_count && cl_baselines[entnum].modelindex && item && item->respawntime && (cl.spectator || cls.demoplayback))
{
struct itemtimer_s * timer = Z_Malloc ( sizeof ( * timer ) ) ;
timer - > next = cl . itemtimers ;
cl . itemtimers = timer ;
timer - > origin [ 0 ] = cl_baselines [ entnum ] . origin [ 0 ] + item - > offset [ 0 ] ;
timer - > origin [ 1 ] = cl_baselines [ entnum ] . origin [ 1 ] + item - > offset [ 1 ] ;
timer - > origin [ 2 ] = cl_baselines [ entnum ] . origin [ 2 ] ;
timer - > start = cl . time ;
timer - > duration = item - > respawntime ;
timer - > end = cl . time + item - > respawntime ;
timer - > radius = item - > radius ;
timer - > entnum = entnum ;
}
*/
}
2005-04-26 16:04:12 +00:00
void TP_ParsePlayerInfo ( player_state_t * oldstate , player_state_t * state , player_info_t * info )
{
2017-05-28 15:42:32 +00:00
playerview_t * pv = & cl . playerview [ SP ] ;
2005-04-26 16:04:12 +00:00
// if (TP_NeedRefreshSkins())
// {
// if ((state->effects & (EF_BLUE|EF_RED) ) != (oldstate->effects & (EF_BLUE|EF_RED)))
// TP_RefreshSkin(info - cl.players);
// }
2017-05-28 15:42:32 +00:00
if ( ! pv - > spectator & & cl . teamplay & & strcmp ( info - > team , TP_PlayerTeam ( ) ) )
2005-04-26 16:04:12 +00:00
{
qboolean eyes ;
eyes = state - > modelindex & & cl . model_precache [ state - > modelindex ] & & ! strcmp ( cl . model_precache [ state - > modelindex ] - > name , " progs/eyes.mdl " ) ;
2007-07-23 18:52:11 +00:00
if ( state - > effects & ( EF_BLUE | EF_RED ) | | eyes )
2005-04-26 16:04:12 +00:00
{
2007-07-23 18:52:11 +00:00
vars . enemy_powerups = 0 ;
vars . enemy_powerups_time = realtime ;
if ( state - > effects & EF_BLUE )
vars . enemy_powerups | = TP_QUAD ;
if ( state - > effects & EF_RED )
vars . enemy_powerups | = TP_PENT ;
if ( eyes )
vars . enemy_powerups | = TP_RING ;
}
}
2017-05-28 15:42:32 +00:00
if ( ! pv - > spectator & & ! cl . teamfortress & & info - cl . players = = pv - > playernum )
2005-04-26 16:04:12 +00:00
{
if ( ( state - > effects & ( QWEF_FLAG1 | QWEF_FLAG2 ) ) & & ! ( oldstate - > effects & ( QWEF_FLAG1 | QWEF_FLAG2 ) ) )
{
2017-05-28 15:42:32 +00:00
ExecTookTrigger_ ( tp_name_flag . string , it_flag , cl . inframes [ cl . validsequence & UPDATE_MASK ] . playerstate [ pv - > playernum ] . origin ) ;
2005-04-26 16:04:12 +00:00
}
else if ( ! ( state - > effects & ( QWEF_FLAG1 | QWEF_FLAG2 ) ) & & ( oldstate - > effects & ( QWEF_FLAG1 | QWEF_FLAG2 ) ) )
{
vars . lastdrop_time = realtime ;
strcpy ( vars . lastdroploc , Macro_Location ( ) ) ;
}
}
}
2004-08-23 00:15:46 +00:00
2015-08-07 17:49:49 +00:00
void TP_CheckPickupSound ( char * s , vec3_t org , int seat )
2004-08-23 00:15:46 +00:00
{
2015-08-07 17:49:49 +00:00
int entnum ;
item_t * item ;
2017-05-28 15:42:32 +00:00
playerview_t * pv = & cl . playerview [ seat ] ;
2015-08-07 17:49:49 +00:00
//if we're spectating, we don't want to do any actual triggers, so pretend it was someone else.
2017-05-28 15:42:32 +00:00
if ( pv - > spectator )
2015-08-07 17:49:49 +00:00
seat = - 1 ;
//FIXME: on items/itembk2.wav kill relevant item timer.
2004-08-23 00:15:46 +00:00
if ( ! strcmp ( s , " items/damage.wav " ) )
2015-08-07 17:49:49 +00:00
{
entnum = FindNearestItem ( org , it_quad , & item ) ;
TP_ItemTaken ( tp_name_quad . string , it_quad , org , entnum , item , seat ) ;
}
2004-08-23 00:15:46 +00:00
else if ( ! strcmp ( s , " items/protect.wav " ) )
2015-08-07 17:49:49 +00:00
{
entnum = FindNearestItem ( org , it_pent , & item ) ;
TP_ItemTaken ( tp_name_pent . string , it_pent , org , entnum , item , seat ) ;
}
2004-08-23 00:15:46 +00:00
else if ( ! strcmp ( s , " items/inv1.wav " ) )
2015-08-07 17:49:49 +00:00
{
entnum = FindNearestItem ( org , it_ring , & item ) ;
TP_ItemTaken ( tp_name_ring . string , it_ring , org , entnum , item , seat ) ;
}
2004-08-23 00:15:46 +00:00
else if ( ! strcmp ( s , " items/suit.wav " ) )
2015-08-07 17:49:49 +00:00
{
entnum = FindNearestItem ( org , it_suit , & item ) ;
TP_ItemTaken ( tp_name_suit . string , it_suit , org , entnum , item , seat ) ;
}
2004-08-23 00:15:46 +00:00
else if ( ! strcmp ( s , " items/health1.wav " ) | |
! strcmp ( s , " items/r_item1.wav " ) )
2015-08-07 17:49:49 +00:00
{
entnum = FindNearestItem ( org , it_health , & item ) ;
TP_ItemTaken ( tp_name_health . string , it_health , org , entnum , item , seat ) ;
}
2004-08-23 00:15:46 +00:00
else if ( ! strcmp ( s , " items/r_item2.wav " ) )
2015-08-07 17:49:49 +00:00
{
entnum = FindNearestItem ( org , it_mh , & item ) ;
TP_ItemTaken ( tp_name_mh . string , it_mh , org , entnum , item , seat ) ;
}
2004-08-23 00:15:46 +00:00
else
goto more ;
return ;
more :
if ( ! cl . validsequence | | ! cl . oldvalidsequence )
return ;
// weapons
if ( ! strcmp ( s , " weapons/pkup.wav " ) )
{
2015-08-07 17:49:49 +00:00
entnum = FindNearestItem ( org , it_weapons , & item ) ;
if ( item )
TP_ItemTaken ( item - > cvar - > string , item - > itemflag , org , entnum , item , seat ) ;
else if ( seat > = 0 )
2007-07-23 18:52:11 +00:00
{
2004-08-23 00:15:46 +00:00
// we don't know what entity caused the sound, try to guess...
2007-07-23 18:52:11 +00:00
if ( vars . stat_framecounts [ STAT_ITEMS ] = = cls . framecount )
{
2004-08-23 00:15:46 +00:00
if ( vars . items & ~ vars . olditems & IT_LIGHTNING )
2017-05-28 15:42:32 +00:00
TP_ItemTaken ( tp_name_lg . string , it_lg , pv - > simorg , entnum , item , seat ) ;
2004-08-23 00:15:46 +00:00
else if ( vars . items & ~ vars . olditems & IT_ROCKET_LAUNCHER )
2017-05-28 15:42:32 +00:00
TP_ItemTaken ( tp_name_rl . string , it_rl , pv - > simorg , entnum , item , seat ) ;
2004-08-23 00:15:46 +00:00
else if ( vars . items & ~ vars . olditems & IT_GRENADE_LAUNCHER )
2017-05-28 15:42:32 +00:00
TP_ItemTaken ( tp_name_gl . string , it_gl , pv - > simorg , entnum , item , seat ) ;
2004-08-23 00:15:46 +00:00
else if ( vars . items & ~ vars . olditems & IT_SUPER_NAILGUN )
2017-05-28 15:42:32 +00:00
TP_ItemTaken ( tp_name_sng . string , it_sng , pv - > simorg , entnum , item , seat ) ;
2004-08-23 00:15:46 +00:00
else if ( vars . items & ~ vars . olditems & IT_NAILGUN )
2017-05-28 15:42:32 +00:00
TP_ItemTaken ( tp_name_ng . string , it_ng , pv - > simorg , entnum , item , seat ) ;
2004-08-23 00:15:46 +00:00
else if ( vars . items & ~ vars . olditems & IT_SUPER_SHOTGUN )
2017-05-28 15:42:32 +00:00
TP_ItemTaken ( tp_name_ssg . string , it_ssg , pv - > simorg , entnum , item , seat ) ;
2004-08-23 00:15:46 +00:00
}
}
return ;
}
// armor
2007-07-23 18:52:11 +00:00
if ( ! strcmp ( s , " items/armor1.wav " ) )
{
2004-08-23 00:15:46 +00:00
item_t * item ;
qbool armor_updated ;
armor_updated = ( vars . stat_framecounts [ STAT_ARMOR ] = = cls . framecount ) ;
2015-08-07 17:49:49 +00:00
entnum = FindNearestItem ( org , it_armor , & item ) ;
if ( item )
TP_ItemTaken ( item - > cvar - > string , item - > itemflag , org , entnum , item , seat ) ;
else if ( seat > = 0 )
{
2017-05-28 15:42:32 +00:00
if ( armor_updated & & pv - > stats [ STAT_ARMOR ] = = 100 )
2015-08-07 17:49:49 +00:00
TP_ItemTaken ( tp_name_ga . string , it_ga , org , entnum , NULL , seat ) ;
2017-05-28 15:42:32 +00:00
else if ( armor_updated & & pv - > stats [ STAT_ARMOR ] = = 150 )
2015-08-07 17:49:49 +00:00
TP_ItemTaken ( tp_name_ya . string , it_ya , org , entnum , NULL , seat ) ;
2017-05-28 15:42:32 +00:00
else if ( armor_updated & & pv - > stats [ STAT_ARMOR ] = = 200 )
2015-08-07 17:49:49 +00:00
TP_ItemTaken ( tp_name_ra . string , it_ra , org , entnum , NULL , seat ) ;
}
2004-08-23 00:15:46 +00:00
return ;
}
// backpack or ammo
if ( ! strcmp ( s , " weapons/lock4.wav " ) )
{
item_t * item ;
2015-08-07 17:49:49 +00:00
entnum = FindNearestItem ( org , it_ammo | it_pack | it_runes , & item ) ;
2015-08-10 18:28:23 +00:00
if ( ! item )
2004-08-23 00:15:46 +00:00
return ;
2015-08-07 17:49:49 +00:00
TP_ItemTaken ( item - > cvar - > string , item - > itemflag , org , entnum , item , seat ) ;
2004-08-23 00:15:46 +00:00
}
}
2009-11-04 21:16:50 +00:00
qboolean R_CullSphere ( vec3_t org , float radius ) ;
2015-08-28 03:13:45 +00:00
static qboolean TP_IsItemVisible ( item_vis_t * visitem ) //BE sure that pmove.skipent is set correctly first
2007-07-23 18:52:11 +00:00
{
2005-04-26 16:04:12 +00:00
vec3_t end , v ;
trace_t trace ;
2004-08-23 00:15:46 +00:00
2005-04-26 16:04:12 +00:00
if ( visitem - > dist < = visitem - > radius )
return true ;
2009-11-04 21:16:50 +00:00
if ( R_CullSphere ( visitem - > entorg , visitem - > radius ) )
return false ;
2005-04-26 16:04:12 +00:00
VectorNegate ( visitem - > dir , v ) ;
VectorNormalize ( v ) ;
VectorMA ( visitem - > entorg , visitem - > radius , v , end ) ;
trace = PM_TraceLine ( visitem - > vieworg , end ) ;
if ( trace . fraction = = 1 )
return true ;
VectorMA ( visitem - > entorg , visitem - > radius , visitem - > right , end ) ;
VectorSubtract ( visitem - > vieworg , end , v ) ;
VectorNormalize ( v ) ;
VectorMA ( end , visitem - > radius , v , end ) ;
trace = PM_TraceLine ( visitem - > vieworg , end ) ;
if ( trace . fraction = = 1 )
return true ;
VectorMA ( visitem - > entorg , - visitem - > radius , visitem - > right , end ) ;
VectorSubtract ( visitem - > vieworg , end , v ) ;
VectorNormalize ( v ) ;
VectorMA ( end , visitem - > radius , v , end ) ;
trace = PM_TraceLine ( visitem - > vieworg , end ) ;
if ( trace . fraction = = 1 )
return true ;
VectorMA ( visitem - > entorg , visitem - > radius , visitem - > up , end ) ;
VectorSubtract ( visitem - > vieworg , end , v ) ;
VectorNormalize ( v ) ;
VectorMA ( end , visitem - > radius , v , end ) ;
trace = PM_TraceLine ( visitem - > vieworg , end ) ;
if ( trace . fraction = = 1 )
return true ;
// use half the radius, otherwise it's possible to see through floor in some places
VectorMA ( visitem - > entorg , - visitem - > radius / 2 , visitem - > up , end ) ;
VectorSubtract ( visitem - > vieworg , end , v ) ;
VectorNormalize ( v ) ;
VectorMA ( end , visitem - > radius , v , end ) ;
trace = PM_TraceLine ( visitem - > vieworg , end ) ;
if ( trace . fraction = = 1 )
return true ;
return false ;
}
2009-07-17 22:28:16 +00:00
//checks to see if a point at org the size of a player is visible or not
qboolean TP_IsPlayerVisible ( vec3_t origin )
{
item_vis_t visitem ;
VectorCopy ( vpn , visitem . forward ) ;
VectorCopy ( vright , visitem . right ) ;
VectorCopy ( vup , visitem . up ) ;
VectorCopy ( r_origin , visitem . vieworg ) ;
VectorCopy ( origin , visitem . entorg ) ;
visitem . entorg [ 2 ] + = 27 ;
VectorSubtract ( visitem . entorg , visitem . vieworg , visitem . dir ) ;
visitem . dist = DotProduct ( visitem . dir , visitem . forward ) ;
visitem . radius = 25 ;
return TP_IsItemVisible ( & visitem ) ;
}
2007-07-23 18:52:11 +00:00
static float TP_RankPoint ( item_vis_t * visitem )
{
2005-04-26 16:04:12 +00:00
vec3_t v2 , v3 ;
float miss ;
if ( visitem - > dist < 10 )
return - 1 ;
VectorScale ( visitem - > forward , visitem - > dist , v2 ) ;
VectorSubtract ( v2 , visitem - > dir , v3 ) ;
miss = VectorLength ( v3 ) ;
if ( miss > 300 )
return - 1 ;
if ( miss > visitem - > dist * 1.7 )
return - 1 ; // over 60 degrees off
return ( visitem - > dist < 3000.0 / 8.0 ) ? miss * ( visitem - > dist * 8.0 * 0.0002f + 0.3f ) : miss ;
}
2007-07-23 18:52:11 +00:00
static char * Utils_TF_ColorToTeam_Failsafe ( int color )
{
2005-04-26 16:04:12 +00:00
int i , j , teamcounts [ 8 ] , numteamsseen = 0 , best = - 1 ;
char * teams [ MAX_CLIENTS ] ;
memset ( teams , 0 , sizeof ( teams ) ) ;
memset ( teamcounts , 0 , sizeof ( teamcounts ) ) ;
2013-10-29 17:38:22 +00:00
for ( i = 0 ; i < cl . allocated_client_slots ; i + + )
2007-07-23 18:52:11 +00:00
{
2005-04-26 16:04:12 +00:00
if ( ! cl . players [ i ] . name [ 0 ] | | cl . players [ i ] . spectator )
continue ;
2007-07-23 18:52:11 +00:00
if ( cl . players [ i ] . rbottomcolor ! = color )
2005-04-26 16:04:12 +00:00
continue ;
2007-07-23 18:52:11 +00:00
for ( j = 0 ; j < numteamsseen ; j + + )
{
2005-04-26 16:04:12 +00:00
if ( ! strcmp ( cl . players [ i ] . team , teams [ j ] ) )
break ;
}
2007-07-23 18:52:11 +00:00
if ( j = = numteamsseen )
{
2005-04-26 16:04:12 +00:00
teams [ numteamsseen ] = cl . players [ i ] . team ;
teamcounts [ numteamsseen ] = 1 ;
numteamsseen + + ;
2007-07-23 18:52:11 +00:00
}
else
{
2005-04-26 16:04:12 +00:00
teamcounts [ j ] + + ;
}
}
2007-07-23 18:52:11 +00:00
for ( i = 0 ; i < numteamsseen ; i + + )
{
2005-04-26 16:04:12 +00:00
if ( best = = - 1 | | teamcounts [ i ] > teamcounts [ best ] )
best = i ;
}
return ( best = = - 1 ) ? " " : teams [ best ] ;
}
2020-04-19 01:23:32 +00:00
static char * Utils_TF_ColorToTeam ( int color )
2007-07-23 18:52:11 +00:00
{
2005-04-26 16:04:12 +00:00
char * s ;
2007-07-23 18:52:11 +00:00
switch ( color )
{
2005-04-26 16:04:12 +00:00
case 13 :
2018-07-05 16:21:44 +00:00
if ( * ( s = InfoBuf_ValueForKey ( & cl . serverinfo , " team1 " ) ) | | * ( s = InfoBuf_ValueForKey ( & cl . serverinfo , " t1 " ) ) )
2005-04-26 16:04:12 +00:00
return s ;
break ;
case 4 :
2018-07-05 16:21:44 +00:00
if ( * ( s = InfoBuf_ValueForKey ( & cl . serverinfo , " team2 " ) ) | | * ( s = InfoBuf_ValueForKey ( & cl . serverinfo , " t2 " ) ) )
2005-04-26 16:04:12 +00:00
return s ;
break ;
case 12 :
2018-07-05 16:21:44 +00:00
if ( * ( s = InfoBuf_ValueForKey ( & cl . serverinfo , " team3 " ) ) | | * ( s = InfoBuf_ValueForKey ( & cl . serverinfo , " t3 " ) ) )
2005-04-26 16:04:12 +00:00
return s ;
break ;
case 11 :
2018-07-05 16:21:44 +00:00
if ( * ( s = InfoBuf_ValueForKey ( & cl . serverinfo , " team4 " ) ) | | * ( s = InfoBuf_ValueForKey ( & cl . serverinfo , " t4 " ) ) )
2005-04-26 16:04:12 +00:00
return s ;
break ;
default :
return " " ;
}
return Utils_TF_ColorToTeam_Failsafe ( color ) ;
}
2007-07-23 18:52:11 +00:00
static void TP_FindPoint ( void )
{
2005-04-26 16:04:12 +00:00
packet_entities_t * pak ;
entity_state_t * ent ;
int i , j , pointflags_dmm ;
float best = - 1 , rank ;
entity_state_t * bestent = NULL ;
vec3_t ang ;
item_t * item , * bestitem = NULL ;
player_state_t * state , * beststate = NULL ;
player_info_t * info , * bestinfo = NULL ;
item_vis_t visitem ;
extern cvar_t v_viewheight ;
2015-08-28 03:13:45 +00:00
int oldskip = pmove . skipent ;
2017-05-28 15:42:32 +00:00
playerview_t * pv = & cl . playerview [ SP ] ;
2005-04-26 16:04:12 +00:00
if ( vars . pointtime = = realtime )
return ;
2004-08-23 00:15:46 +00:00
if ( ! cl . validsequence )
goto nothing ;
2017-05-28 15:42:32 +00:00
pmove . skipent = pv - > viewentity ;
2015-08-28 03:13:45 +00:00
2017-05-28 15:42:32 +00:00
ang [ 0 ] = pv - > viewangles [ 0 ] ; ang [ 1 ] = pv - > viewangles [ 1 ] ; ang [ 2 ] = 0 ;
2005-04-26 16:04:12 +00:00
AngleVectors ( ang , visitem . forward , visitem . right , visitem . up ) ;
2017-05-28 15:42:32 +00:00
VectorCopy ( pv - > simorg , visitem . vieworg ) ;
2005-04-26 16:04:12 +00:00
visitem . vieworg [ 2 ] + = 22 + ( v_viewheight . value ? bound ( - 7 , v_viewheight . value , 4 ) : 0 ) ;
2004-08-23 00:15:46 +00:00
2005-04-26 16:04:12 +00:00
pointflags_dmm = pointflags ;
2007-07-23 18:52:11 +00:00
if ( ! cl . teamfortress & & cl . deathmatch > = 1 & & cl . deathmatch < = 4 )
{
2005-04-26 16:04:12 +00:00
if ( cl . deathmatch = = 4 )
pointflags_dmm & = ~ it_ammo ;
if ( cl . deathmatch ! = 1 )
pointflags_dmm & = ~ it_weapons ;
}
2004-08-23 00:15:46 +00:00
2013-03-12 22:53:23 +00:00
pak = & cl . inframes [ cl . validsequence & UPDATE_MASK ] . packet_entities ;
2007-07-23 18:52:11 +00:00
for ( i = 0 , ent = pak - > entities ; i < pak - > num_entities ; i + + , ent + + )
{
2004-08-23 00:15:46 +00:00
item = model2item [ ent - > modelindex ] ;
2005-04-26 16:04:12 +00:00
if ( ! item | | ! ( item - > itemflag & pointflags_dmm ) )
2004-08-23 00:15:46 +00:00
continue ;
// special check for armors
2007-07-23 18:52:11 +00:00
if ( item - > itemflag = = ( it_ra | it_ya | it_ga ) )
{
2015-08-28 03:13:45 +00:00
item + = 1 + bound ( 0 , ent - > skinnum , 2 ) ;
if ( ! ( item - > itemflag & pointflags_dmm ) )
continue ;
2004-08-23 00:15:46 +00:00
}
2005-04-26 16:04:12 +00:00
VectorAdd ( ent - > origin , item - > offset , visitem . entorg ) ;
VectorSubtract ( visitem . entorg , visitem . vieworg , visitem . dir ) ;
visitem . dist = DotProduct ( visitem . dir , visitem . forward ) ;
visitem . radius = ent - > effects & ( EF_BLUE | EF_RED | EF_DIMLIGHT | EF_BRIGHTLIGHT ) ? 200 : item - > radius ;
2004-08-23 00:15:46 +00:00
2005-04-26 16:04:12 +00:00
if ( ( rank = TP_RankPoint ( & visitem ) ) < 0 )
2004-08-23 00:15:46 +00:00
continue ;
2005-04-26 16:04:12 +00:00
// check if we can actually see the object
2007-07-23 18:52:11 +00:00
if ( ( rank < best | | best < 0 ) & & TP_IsItemVisible ( & visitem ) )
{
2004-08-23 00:15:46 +00:00
best = rank ;
bestent = ent ;
bestitem = item ;
}
}
2013-03-12 22:53:23 +00:00
state = cl . inframes [ cl . parsecount & UPDATE_MASK ] . playerstate ;
2005-04-26 16:04:12 +00:00
info = cl . players ;
2013-10-29 17:38:22 +00:00
for ( j = 0 ; j < cl . allocated_client_slots ; j + + , info + + , state + + )
2007-07-23 18:52:11 +00:00
{
2017-05-28 15:42:32 +00:00
if ( state - > messagenum ! = cl . parsecount | | j = = pv - > playernum | | info - > spectator )
2005-04-26 16:04:12 +00:00
continue ;
if (
2006-03-04 20:43:48 +00:00
( state - > modelindex = = cl_playerindex & & ISDEAD ( state - > frame ) ) | |
2005-04-26 16:04:12 +00:00
state - > modelindex = = cl_h_playerindex
)
continue ;
VectorCopy ( state - > origin , visitem . entorg ) ;
visitem . entorg [ 2 ] + = 30 ;
VectorSubtract ( visitem . entorg , visitem . vieworg , visitem . dir ) ;
visitem . dist = DotProduct ( visitem . dir , visitem . forward ) ;
visitem . radius = ( state - > effects & ( EF_BLUE | EF_RED | EF_DIMLIGHT | EF_BRIGHTLIGHT ) ) ? 200 : 27 ;
if ( ( rank = TP_RankPoint ( & visitem ) ) < 0 )
continue ;
// check if we can actually see the object
2007-07-23 18:52:11 +00:00
if ( ( rank < best | | best < 0 ) & & TP_IsItemVisible ( & visitem ) )
{
2005-04-26 16:04:12 +00:00
qboolean teammate , eyes = false ;
eyes = state - > modelindex & & cl . model_precache [ state - > modelindex ] & & ! strcmp ( cl . model_precache [ state - > modelindex ] - > name , " progs/eyes.mdl " ) ;
teammate = ! ! ( cl . teamplay & & ! strcmp ( info - > team , TP_PlayerTeam ( ) ) ) ;
if ( eyes & & ! ( pointflags_dmm & it_eyes ) )
continue ;
else if ( teammate & & ! ( pointflags_dmm & it_teammate ) )
continue ;
else if ( ! ( pointflags_dmm & it_enemy ) )
continue ;
best = rank ;
bestinfo = info ;
beststate = state ;
}
}
2007-07-23 18:52:11 +00:00
if ( best > = 0 & & bestinfo )
{
2005-04-26 16:04:12 +00:00
qboolean teammate , eyes ;
char * name , buf [ 256 ] = { 0 } ;
eyes = beststate - > modelindex & & cl . model_precache [ beststate - > modelindex ] & & ! strcmp ( cl . model_precache [ beststate - > modelindex ] - > name , " progs/eyes.mdl " ) ;
2007-07-23 18:52:11 +00:00
if ( cl . teamfortress )
{
teammate = ! strcmp ( Utils_TF_ColorToTeam ( bestinfo - > rbottomcolor ) , TP_PlayerTeam ( ) ) ;
2005-04-26 16:04:12 +00:00
if ( eyes )
name = tp_name_eyes . string ; //duck on 2night2
2017-05-28 15:42:32 +00:00
else if ( pv - > spectator )
2005-04-26 16:04:12 +00:00
name = bestinfo - > name ;
else if ( teammate )
name = tp_name_teammate . string [ 0 ] ? tp_name_teammate . string : " teammate " ;
else
name = tp_name_enemy . string ;
if ( ! eyes )
2018-07-05 16:21:44 +00:00
name = va ( " %s%s%s " , name , name [ 0 ] ? " " : " " , Skin_To_TFSkin ( InfoBuf_ValueForKey ( & bestinfo - > userinfo , " skin " ) ) ) ;
2007-07-23 18:52:11 +00:00
}
else
{
2005-04-26 16:04:12 +00:00
teammate = ! ! ( cl . teamplay & & ! strcmp ( bestinfo - > team , TP_PlayerTeam ( ) ) ) ;
if ( eyes )
name = tp_name_eyes . string ;
2017-05-28 15:42:32 +00:00
else if ( pv - > spectator | | ( teammate & & ! tp_name_teammate . string [ 0 ] ) )
2005-04-26 16:04:12 +00:00
name = bestinfo - > name ;
else
name = teammate ? tp_name_teammate . string : tp_name_enemy . string ;
}
if ( beststate - > effects & EF_BLUE )
2005-04-27 09:10:03 +00:00
Q_strncatz2 ( buf , tp_name_quaded . string ) ;
2005-04-26 16:04:12 +00:00
if ( beststate - > effects & EF_RED )
2005-04-27 09:10:03 +00:00
Q_strncatz2 ( buf , va ( " %s%s " , buf [ 0 ] ? " " : " " , tp_name_pented . string ) ) ;
Q_strncatz2 ( buf , va ( " %s%s " , buf [ 0 ] ? " " : " " , name ) ) ;
2005-04-26 16:04:12 +00:00
Q_strncpyz ( vars . pointname , buf , sizeof ( vars . pointname ) ) ;
Q_strncpyz ( vars . pointloc , TP_LocationName ( beststate - > origin ) , sizeof ( vars . pointloc ) ) ;
vars . pointtype = ( teammate & & ! eyes ) ? POINT_TYPE_TEAMMATE : POINT_TYPE_ENEMY ;
2007-07-23 18:52:11 +00:00
}
else if ( best > = 0 )
{
2004-08-23 00:15:46 +00:00
char * p ;
2005-04-26 16:04:12 +00:00
2007-07-23 18:52:11 +00:00
if ( ! bestitem - > cvar )
{
2015-08-28 03:13:45 +00:00
p = tp_name_nothing . string ;
2007-07-23 18:52:11 +00:00
}
else
{
2004-08-23 00:15:46 +00:00
p = bestitem - > cvar - > string ;
2005-04-26 16:04:12 +00:00
}
2004-08-23 00:15:46 +00:00
2005-04-26 16:04:12 +00:00
vars . pointtype = ( bestitem - > itemflag & ( it_powerups | it_flag ) ) ? POINT_TYPE_POWERUP : POINT_TYPE_ITEM ;
Q_strncpyz ( vars . pointname , p , sizeof ( vars . pointname ) ) ;
Q_strncpyz ( vars . pointloc , TP_LocationName ( bestent - > origin ) , sizeof ( vars . pointloc ) ) ;
2004-08-23 00:15:46 +00:00
}
2007-07-23 18:52:11 +00:00
else
{
2004-08-23 00:15:46 +00:00
nothing :
2005-04-26 16:04:12 +00:00
Q_strncpyz ( vars . pointname , tp_name_nothing . string , sizeof ( vars . pointname ) ) ;
2004-08-23 00:15:46 +00:00
vars . pointloc [ 0 ] = 0 ;
2005-04-26 16:04:12 +00:00
vars . pointtype = POINT_TYPE_ITEM ;
2004-08-23 00:15:46 +00:00
}
2005-04-26 16:04:12 +00:00
vars . pointtime = realtime ;
2015-08-28 03:13:45 +00:00
pmove . skipent = oldskip ;
2004-08-23 00:15:46 +00:00
}
2008-11-09 22:29:28 +00:00
void TP_UpdateAutoStatus ( void )
{
char newstatusbuf [ sizeof ( vars . autoteamstatus ) ] ;
char * newstatus ;
2015-09-18 20:30:10 +00:00
int level ;
2017-05-28 15:42:32 +00:00
playerview_t * pv = & cl . playerview [ SP ] ;
2008-11-09 22:29:28 +00:00
2009-11-04 21:16:50 +00:00
if ( vars . autoteamstatus_time > realtime | | ! * tp_autostatus . string )
2008-11-09 22:29:28 +00:00
return ;
2009-03-03 01:52:30 +00:00
vars . autoteamstatus_time = realtime + 3 ;
2008-11-09 22:29:28 +00:00
2015-09-18 20:30:10 +00:00
level = tp_autostatus . restriction ;
2023-03-15 01:29:30 +00:00
newstatus = Cmd_ExpandString ( tp_autostatus . string , newstatusbuf , sizeof ( newstatusbuf ) , & level , false , true , true ) ;
2008-11-09 22:29:28 +00:00
newstatus = TP_ParseMacroString ( newstatus ) ;
if ( ! strcmp ( newstatus , vars . autoteamstatus ) )
return ;
if ( ! * vars . autoteamstatus & & ! vars . health )
{
if ( cls . state ! = ca_active )
strcpy ( vars . autoteamstatus , newstatus ) ;
return ; //don't start it with a death (stops spamming of locations when we originally connect, before spawning)
}
strcpy ( vars . autoteamstatus , newstatus ) ;
if ( strchr ( tp_autostatus . string , ' ; ' ) )
return ; //don't take risks
if ( tp_autostatus . latched_string )
return ;
2017-05-28 15:42:32 +00:00
if ( pv - > spectator ) //don't spam as spectators, that's just silly
2008-11-09 22:29:28 +00:00
return ;
if ( ! cl . teamplay ) //don't spam in deathmatch, that's just pointless
return ;
//the tp code will reexpand it as part of the say team
Cbuf_AddText ( va ( " say_team $ \\ %s \n " , tp_autostatus . string ) , RESTRICT_LOCAL ) ;
}
2004-08-23 00:15:46 +00:00
void TP_StatChanged ( int stat , int value )
{
2017-05-28 15:42:32 +00:00
playerview_t * pv = & cl . playerview [ SP ] ;
2016-07-15 12:26:24 +00:00
int i ;
2004-08-23 00:15:46 +00:00
if ( stat = = STAT_HEALTH )
{
2005-02-28 07:16:19 +00:00
if ( value > 0 )
{
if ( vars . health < = 0 )
{
2004-08-23 00:15:46 +00:00
// we just respawned
vars . respawntrigger_time = realtime ;
2017-05-28 15:42:32 +00:00
if ( ! pv - > spectator & & CountTeammates ( ) )
2015-06-16 23:53:58 +00:00
TP_ExecTrigger ( " f_respawn " , false ) ;
2004-08-23 00:15:46 +00:00
}
}
2008-11-09 22:29:28 +00:00
else if ( vars . health > 0 )
2005-02-28 07:16:19 +00:00
{ // We have just died
2017-05-28 15:42:32 +00:00
vars . droppedweapon = pv - > stats [ STAT_ACTIVEWEAPON ] ;
2005-02-28 07:16:19 +00:00
2004-08-23 00:15:46 +00:00
vars . deathtrigger_time = realtime ;
strcpy ( vars . lastdeathloc , Macro_Location ( ) ) ;
2005-02-28 07:16:19 +00:00
2005-04-26 16:04:12 +00:00
CountNearbyPlayers ( true ) ;
vars . last_numenemies = vars . numenemies ;
vars . last_numfriendlies = vars . numfriendlies ;
2017-05-28 15:42:32 +00:00
if ( ! pv - > spectator & & CountTeammates ( ) )
2005-02-28 07:16:19 +00:00
{
2017-05-28 15:42:32 +00:00
if ( cl . teamfortress & & ( pv - > stats [ STAT_ITEMS ] & ( IT_KEY1 | IT_KEY2 ) )
2004-08-23 00:15:46 +00:00
& & Cmd_AliasExist ( " f_flagdeath " , RESTRICT_LOCAL ) )
2015-06-16 23:53:58 +00:00
TP_ExecTrigger ( " f_flagdeath " , false ) ;
2004-08-23 00:15:46 +00:00
else
2015-06-16 23:53:58 +00:00
TP_ExecTrigger ( " f_death " , false ) ;
2004-08-23 00:15:46 +00:00
}
}
vars . health = value ;
}
else if ( stat = = STAT_ITEMS )
{
i = value & ~ vars . items ;
if ( i & ( IT_KEY1 | IT_KEY2 ) ) {
2017-05-28 15:42:32 +00:00
if ( cl . teamfortress & & ! pv - > spectator )
2005-07-16 00:53:08 +00:00
{
2015-08-07 17:49:49 +00:00
ExecTookTrigger_ ( tp_name_flag . string , it_flag ,
2017-05-28 15:42:32 +00:00
cl . inframes [ cl . validsequence & UPDATE_MASK ] . playerstate [ pv - > playernum ] . origin ) ;
2005-07-16 00:53:08 +00:00
}
}
2011-05-15 13:23:13 +00:00
2017-05-28 15:42:32 +00:00
if ( ! pv - > spectator & & cl . teamfortress & & ~ value & vars . items & ( IT_KEY1 | IT_KEY2 ) )
2005-07-16 00:53:08 +00:00
{
vars . lastdrop_time = realtime ;
strcpy ( vars . lastdroploc , Macro_Location ( ) ) ;
2004-08-23 00:15:46 +00:00
}
vars . olditems = vars . items ;
vars . items = value ;
}
else if ( stat = = STAT_ACTIVEWEAPON )
{
2017-05-28 15:42:32 +00:00
if ( pv - > stats [ STAT_ACTIVEWEAPON ] ! = vars . activeweapon )
2015-06-16 23:53:58 +00:00
TP_ExecTrigger ( " f_weaponchange " , false ) ;
2017-05-28 15:42:32 +00:00
vars . activeweapon = pv - > stats [ STAT_ACTIVEWEAPON ] ;
2004-08-23 00:15:46 +00:00
}
vars . stat_framecounts [ stat ] = cls . framecount ;
2008-11-09 22:29:28 +00:00
TP_UpdateAutoStatus ( ) ;
2004-08-23 00:15:46 +00:00
}
2020-04-19 01:23:32 +00:00
# endif
2004-08-23 00:15:46 +00:00
/*
= = = = = = = = = = = = = = = = = = = = = =
TP_CheckSoundTrigger
Find and execute sound triggers .
A sound trigger must be terminated by either a CR or LF .
Returns true if a sound was found and played
= = = = = = = = = = = = = = = = = = = = = =
*/
qbool TP_CheckSoundTrigger ( char * str )
{
int i , j ;
int start , length ;
2016-08-25 00:12:14 +00:00
char soundname [ MAX_QPATH ] ;
2004-08-23 00:15:46 +00:00
2005-10-10 02:18:11 +00:00
if ( ! * str )
return false ;
2004-08-23 00:15:46 +00:00
if ( ! tp_soundtrigger . string [ 0 ] )
return false ;
for ( i = strlen ( str ) - 1 ; i ; i - - )
{
if ( str [ i ] ! = 0x0A & & str [ i ] ! = 0x0D )
continue ;
for ( j = i - 1 ; j > = 0 ; j - - )
{
// quick check for chars that cannot be used
// as sound triggers but might be part of a file name
if ( isalpha ( ( int ) ( unsigned char ) str [ j ] ) | |
isdigit ( ( int ) ( unsigned char ) str [ j ] ) )
continue ; // file name or chat
if ( strchr ( tp_soundtrigger . string , str [ j ] ) )
{
// this might be a sound trigger
start = j + 1 ;
length = i - start ;
if ( ! length )
break ;
if ( length > = MAX_QPATH )
break ;
strlcpy ( soundname , str + start , length + 1 ) ;
if ( strstr ( soundname , " .. " ) )
break ; // no thank you
// clean up the message
strcpy ( str + j , str + i ) ;
2009-04-01 22:03:56 +00:00
if ( ! S_HaveOutput ( ) )
2004-08-23 00:15:46 +00:00
return false ;
2006-03-11 03:12:10 +00:00
COM_DefaultExtension ( soundname , " .wav " , sizeof ( soundname ) ) ;
2004-08-23 00:15:46 +00:00
// make sure we have it on disk (FIXME)
2015-10-11 11:34:58 +00:00
if ( ! FS_FLocateFile ( va ( " sound/%s " , soundname ) , FSLF_IFFOUND , NULL ) )
2004-08-23 00:15:46 +00:00
return false ;
// now play the sound
S_LocalSound ( soundname ) ;
return true ;
}
if ( str [ j ] < = ' ' | | strchr ( " \" &'*,:;<>? \\ | \x7f " , str [ j ] ) )
break ; // we don't allow these in a file name
}
}
return false ;
}
2020-04-19 01:23:32 +00:00
# define MAX_FILTERS 8
2004-08-23 00:15:46 +00:00
# define MAX_FILTER_LENGTH 4
2020-04-19 01:23:32 +00:00
static char filter_strings [ MAX_FILTERS ] [ MAX_FILTER_LENGTH + 1 ] ;
2004-09-30 22:25:55 +00:00
static int num_filters = 0 ;
2004-08-23 00:15:46 +00:00
/*
= = = = = = = = = = = = = = = = = = = = = =
TP_FilterMessage
returns false if the message shouldn ' t be printed
matching filters are stripped from the message
= = = = = = = = = = = = = = = = = = = = = =
*/
qbool TP_FilterMessage ( char * s )
{
int i , j , len , maxlen ;
if ( ! num_filters )
return true ;
len = strlen ( s ) ;
if ( len < 2 | | s [ len - 1 ] ! = ' \n ' | | s [ len - 2 ] = = ' # ' )
return true ;
maxlen = MAX_FILTER_LENGTH + 1 ;
for ( i = len - 2 ; i > = 0 & & maxlen > 0 ; i - - , maxlen - - ) {
if ( s [ i ] = = ' ' )
return true ;
if ( s [ i ] = = ' # ' )
break ;
}
if ( i < 0 | | ! maxlen )
return true ; // no filter at all
s [ len - 1 ] = 0 ; // so that strcmp works properly
for ( j = 0 ; j < num_filters ; j + + )
if ( ! strcmp ( s + i + 1 , filter_strings [ j ] ) )
{
// strip the filter from message
if ( i & & s [ i - 1 ] = = ' ' )
{ // there's a space just before the filter, remove it
2011-05-15 13:23:13 +00:00
// so that soundtriggers like ^blah #att work
2004-08-23 00:15:46 +00:00
s [ i - 1 ] = ' \n ' ;
s [ i ] = 0 ;
} else {
s [ i ] = ' \n ' ;
s [ i + 1 ] = 0 ;
}
return true ;
}
s [ len - 1 ] = ' \n ' ;
return false ; // this message is not for us, don't print it
}
2004-09-30 22:25:55 +00:00
static void TP_MsgFilter_f ( void )
2004-08-23 00:15:46 +00:00
{
int c , i ;
char * s ;
c = Cmd_Argc ( ) ;
if ( c = = 1 ) {
if ( ! num_filters ) {
Com_Printf ( " No filters defined \n " ) ;
return ;
}
for ( i = 0 ; i < num_filters ; i + + )
Com_Printf ( " %s#%s " , i ? " " : " " , filter_strings [ i ] ) ;
Com_Printf ( " \n " ) ;
return ;
}
if ( c = = 2 & & ( Cmd_Argv ( 1 ) [ 0 ] = = 0 | | ! strcmp ( Cmd_Argv ( 1 ) , " clear " ) ) ) {
num_filters = 0 ;
return ;
}
num_filters = 0 ;
for ( i = 1 ; i < c ; i + + ) {
s = Cmd_Argv ( i ) ;
if ( * s ! = ' # ' ) {
Com_Printf ( " A filter must start with \" # \" \n " ) ;
return ;
}
if ( strchr ( s + 1 , ' ' ) ) {
Com_Printf ( " A filter may not contain spaces \n " ) ;
return ;
}
strlcpy ( filter_strings [ num_filters ] , s + 1 , sizeof ( filter_strings [ 0 ] ) ) ;
num_filters + + ;
2020-04-19 01:23:32 +00:00
if ( num_filters > = countof ( filter_strings ) )
2004-08-23 00:15:46 +00:00
break ;
}
}
void TP_Init ( void )
{
# define TEAMPLAYVARS "Teamplay Variables"
2005-02-28 07:16:19 +00:00
//register all the TeamPlay cvars.
# define TP_CVAR(name,def) Cvar_Register (&name, TEAMPLAYVARS);
2006-04-12 00:17:02 +00:00
# define TP_CVARC(name,def,callback) Cvar_Register (&name, TEAMPLAYVARS);
2015-04-14 23:12:17 +00:00
# define TP_CVARAC(name,def,name2,callback) Cvar_Register (&name, TEAMPLAYVARS);
2005-02-28 07:16:19 +00:00
TP_CVARS ;
# undef TP_CVAR
2006-04-12 00:17:02 +00:00
# undef TP_CVARC
2015-04-14 23:12:17 +00:00
# undef TP_CVARAC
2005-02-28 07:16:19 +00:00
2004-08-23 00:15:46 +00:00
Cmd_AddCommand ( " loadloc " , TP_LoadLocFile_f ) ;
Cmd_AddCommand ( " filter " , TP_MsgFilter_f ) ;
Cmd_AddCommand ( " msg_trigger " , TP_MsgTrigger_f ) ;
2018-03-04 14:41:16 +00:00
# ifdef QWSKINS
2008-06-05 07:45:34 +00:00
Cmd_AddCommand ( " colourise " , TP_Colourise_f ) ; //uk
Cmd_AddCommand ( " colorize " , TP_Colourise_f ) ; //us
//Cmd_AddCommand ("colorise", TP_Colourise_f); //piss off both.
2018-03-04 14:41:16 +00:00
# endif
2020-04-19 01:23:32 +00:00
# ifdef QUAKESTATS
2018-03-04 14:41:16 +00:00
Cmd_AddCommand ( " tp_took " , TP_Took_f ) ;
Cmd_AddCommand ( " tp_pickup " , TP_Pickup_f ) ;
Cmd_AddCommand ( " tp_point " , TP_Point_f ) ;
2020-04-19 01:23:32 +00:00
# endif
2008-06-05 07:45:34 +00:00
2004-09-20 23:25:38 +00:00
TP_InitMacros ( ) ;
}
2005-04-26 16:04:12 +00:00
qboolean TP_SuppressMessage ( char * buf ) {
char * s ;
2020-04-19 01:23:32 +00:00
unsigned int seat ;
if ( cls . demoplayback )
return false ;
2004-09-20 23:25:38 +00:00
2005-04-26 16:04:12 +00:00
for ( s = buf ; * s & & * s ! = 0x7f ; s + + )
;
2004-09-20 23:25:38 +00:00
2005-04-26 16:04:12 +00:00
if ( * s = = 0x7f & & * ( s + 1 ) = = ' ! ' ) {
* s + + = ' \n ' ;
* s + + = 0 ;
2004-09-20 23:25:38 +00:00
2020-04-19 01:23:32 +00:00
for ( seat = 0 ; seat < cl . splitclients ; seat + + )
if ( ! cl . playerview [ seat ] . spectator & & * s - ' A ' = = cl . playerview [ seat ] . playernum )
return true ;
2005-04-26 16:04:12 +00:00
}
return false ;
}
2004-09-20 23:25:38 +00:00
2015-04-14 23:12:17 +00:00
void CL_PrintChat ( player_info_t * plr , char * msg , int plrflags ) ;
2005-09-21 01:21:35 +00:00
2005-07-16 00:53:08 +00:00
void CL_Say ( qboolean team , char * extra )
2004-09-20 23:25:38 +00:00
{
extern cvar_t cl_fakename ;
2005-04-26 16:04:12 +00:00
char text [ 2048 ] , sendtext [ 2048 ] , * s ;
2020-04-19 01:23:32 +00:00
playerview_t * pv = & cl . playerview [ CL_TargettedSplit ( false ) ] ;
2004-09-20 23:25:38 +00:00
if ( Cmd_Argc ( ) < 2 )
{
if ( team )
Con_Printf ( " %s <text>: send a team message \n " , Cmd_Argv ( 0 ) ) ;
return ;
}
if ( cls . state = = ca_disconnected )
{
2020-08-13 08:39:48 +00:00
Con_TPrintf ( " Can't \" %s \" , not connected \n " , Cmd_Argv ( 0 ) ) ;
2004-09-20 23:25:38 +00:00
return ;
}
2005-04-26 16:04:12 +00:00
suppress = false ;
2004-09-20 23:25:38 +00:00
s = TP_ParseMacroString ( Cmd_Args ( ) ) ;
2013-03-12 22:44:00 +00:00
Q_strncpyz ( text , TP_ParseFunChars ( s ) , sizeof ( text ) ) ;
2004-09-20 23:25:38 +00:00
sendtext [ 0 ] = 0 ;
2017-05-28 15:42:32 +00:00
if ( team & & ! pv - > spectator & & cl_fakename . string [ 0 ] & &
2004-09-20 23:25:38 +00:00
! strchr ( s , ' \x0d ' ) /* explicit $\ in message overrides cl_fakename */ )
{
char buf [ 1024 ] ;
2015-09-18 20:30:10 +00:00
int level = Cmd_ExecLevel ;
2023-03-15 01:29:30 +00:00
Cmd_ExpandString ( cl_fakename . string , buf , sizeof ( buf ) , & level , false , true , true ) ;
2004-09-20 23:25:38 +00:00
strcpy ( buf , TP_ParseMacroString ( buf ) ) ;
2013-03-12 22:44:00 +00:00
Q_snprintfz ( sendtext , sizeof ( sendtext ) , " \x0d %s: " , TP_ParseFunChars ( buf ) ) ;
2004-09-20 23:25:38 +00:00
}
strlcat ( sendtext , text , sizeof ( sendtext ) ) ;
2005-04-26 16:04:12 +00:00
if ( suppress )
{
//print it locally:
char * d ;
for ( s = sendtext , d = text ; * s ; s + + , d + + )
{
if ( * s = = ' \xff ' ) //text that is hidden to us
{ //
s + + ;
* d + + = ' ^ ' ;
2006-02-11 02:09:43 +00:00
* d + + = ' s ' ;
* d + + = ' ^ ' ;
* d + + = ' & ' ;
* d + + = ' 4 ' ;
* d + + = ' 0 ' ;
2005-04-26 16:04:12 +00:00
if ( * s = = ' z ' )
* d + + = ' x ' ;
else
2017-12-09 22:10:51 +00:00
* d + + = ( char ) 139 ;
2005-04-26 16:04:12 +00:00
* d + + = ' ^ ' ;
2006-02-11 02:09:43 +00:00
* d + + = ' r ' ;
2005-04-26 16:04:12 +00:00
d - - ;
while ( * s ! = ' \xff ' )
{
if ( ! * s )
break ;
s + + ;
}
if ( ! * s )
break ;
}
else
* d = * s ;
}
2006-02-11 02:09:43 +00:00
* d + + = ' \n ' ;
2005-04-26 16:04:12 +00:00
* d = ' \0 ' ;
2005-09-08 08:10:06 +00:00
{
int plrflags = 0 ;
if ( team )
plrflags | = 2 ;
2017-05-28 15:42:32 +00:00
CL_PrintChat ( & cl . players [ pv - > playernum ] , text , plrflags ) ;
2005-09-08 08:10:06 +00:00
}
2011-05-15 13:23:13 +00:00
2005-04-26 16:04:12 +00:00
//strip out the extra markup
for ( s = sendtext , d = sendtext ; * s ; s + + , d + + )
{
if ( * s = = ' \xff ' ) //text that is hidden to us
{ //
s + + ;
if ( * s = = ' z ' )
s + + ;
while ( * s ! = ' \xff ' )
{
if ( ! * s )
break ;
* d + + = * s + + ;
}
if ( ! * s )
break ;
d - - ;
}
2011-05-15 13:23:13 +00:00
2005-04-26 16:04:12 +00:00
else
* d = * s ;
}
* d = ' \0 ' ;
//mark the message so that we ignore it when we get the echo.
2017-05-28 15:42:32 +00:00
strlcat ( sendtext , va ( " \x7f !%c " , ' A ' + pv - > playernum ) , sizeof ( sendtext ) ) ;
2005-04-26 16:04:12 +00:00
}
2011-05-15 13:23:13 +00:00
2023-08-19 02:14:09 +00:00
# ifdef Q2CLIENT
if ( cls . netchan . remote_address . prot = = NP_KEXLAN & & NET_GetConnectionCertificate ( cls . sockets , & cls . netchan . remote_address , QCERT_LOBBYSENDCHAT , sendtext , strlen ( sendtext ) ) > 0 )
return ;
# endif
2004-12-24 08:45:56 +00:00
# ifdef Q3CLIENT
2005-06-04 04:20:20 +00:00
if ( cls . protocol = = CP_QUAKE3 )
2022-03-08 05:31:34 +00:00
q3 - > cl . SendClientCommand ( " %s %s%s " , team ? " say_team " : " say " , extra ? extra : " " , sendtext ) ;
2005-04-26 16:04:12 +00:00
else
2004-12-24 08:45:56 +00:00
# endif
2014-02-07 08:38:40 +00:00
{
int split = CL_TargettedSplit ( true ) ;
2016-07-12 00:40:13 +00:00
if ( split > = cl . splitclients )
return ;
2017-09-21 12:22:16 +00:00
//messagemode always adds quotes. the console command never did.
//the server is expected to use Cmd_Args and to strip first+last chars if the first is a quote. this is annoying and clumsy for mods to parse.
2019-04-16 22:40:05 +00:00
# ifdef HAVE_LEGACY
2022-01-16 18:41:44 +00:00
if ( ! dpcompat_console . ival & & ! cls . qex )
2021-07-17 15:10:10 +00:00
CL_SendSeatClientCommand ( true , split , " %s \" %s%s \" " , team ? " say_team " : " say " , extra ? extra : " " , sendtext ) ;
2017-09-21 12:22:16 +00:00
else
# endif
2021-07-17 15:10:10 +00:00
CL_SendSeatClientCommand ( true , split , " %s %s%s " , team ? " say_team " : " say " , extra ? extra : " " , sendtext ) ;
2014-02-07 08:38:40 +00:00
}
2004-09-20 23:25:38 +00:00
}
void CL_Say_f ( void )
{
2006-01-13 06:27:18 +00:00
# ifndef CLIENTONLY
2006-01-10 18:50:06 +00:00
if ( isDedicated )
SV_ConSay_f ( ) ;
else
2006-01-13 06:27:18 +00:00
# endif
2006-01-10 18:50:06 +00:00
CL_Say ( false , NULL ) ;
2004-11-17 18:02:19 +00:00
}
void CL_SayMe_f ( void )
{
CL_Say ( false , " /me " ) ;
2004-09-20 23:25:38 +00:00
}
void CL_SayTeam_f ( void )
{
2020-04-19 01:23:32 +00:00
# ifdef QUAKESTATS
2008-11-09 22:29:28 +00:00
vars . autoteamstatus_time = realtime + 3 ;
2020-04-19 01:23:32 +00:00
# endif
2004-11-17 18:02:19 +00:00
CL_Say ( true , NULL ) ;
2004-08-23 00:15:46 +00:00
}
2015-09-01 04:45:15 +00:00
2018-03-04 14:41:16 +00:00
qboolean TP_SoundTrigger ( char * message ) //if there is a trigger there, play it. Return true if we found one, stripping off the file (it's neater that way).
{
char * strip ;
char * lineend = NULL ;
char soundname [ 128 ] ;
int filter = 0 ;
2004-09-20 23:25:38 +00:00
2018-03-04 14:41:16 +00:00
for ( strip = message + strlen ( message ) - 1 ; * strip & & strip > = message ; strip - - )
{
if ( * strip = = ' # ' )
filter + + ;
if ( * strip = = ' : ' )
break ; //if someone says just one word, we can take any tidles in their name to be a voice command
if ( * strip = = ' \n ' )
lineend = strip ;
else if ( * strip < = ' ' )
{
if ( filter = = 0 | | filter = = 1 ) //allow one space in front of a filter.
{
filter + + ;
continue ;
}
break ;
}
else if ( * strip = = ' ~ ' )
{
//looks like a trigger, whoopie!
if ( lineend - strip > sizeof ( soundname ) - 1 )
{
Con_Printf ( " Sound trigger's file-name was too long \n " ) ;
return false ;
}
Q_strncpyz ( soundname , strip + 1 , lineend - strip ) ;
memmove ( strip , lineend , strlen ( lineend ) + 1 ) ;
2004-09-20 23:25:38 +00:00
2018-03-04 14:41:16 +00:00
Cbuf_AddText ( va ( " play %s \n " , soundname ) , RESTRICT_LOCAL ) ;
return true ;
}
}
return false ;
}