wait now correctly waits until the start of the next input frame (thus ensuring that -attack is delayed for long enough).

implemented hud_teaminfo_show ezhud element. _LOTS_ of hacks. ezhud needs updated engine.
fix issue with overly friendly prints.
handle svc_setinfo more gracefully, for the next time OMC makes a bug.
allow glsl to embed default values for float cvars, in case they're not already set. this can save some docs...
removed prints about "wad" "foo\", fixing a crash concerning just which print function to call.


git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4925 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2015-06-29 23:46:31 +00:00
parent ad9b98f73c
commit 365c11181c
17 changed files with 326 additions and 89 deletions

View file

@ -1714,6 +1714,8 @@ void CL_SendCmd (double frametime, qboolean mainloop)
} }
IN_Move (NULL, 0, frametime); IN_Move (NULL, 0, frametime);
Cbuf_Waited(); //its okay to stop waiting now
return; // sendcmds come from the demo return; // sendcmds come from the demo
} }
@ -1803,6 +1805,8 @@ void CL_SendCmd (double frametime, qboolean mainloop)
{ {
CL_BaseMove (&independantphysics[plnum], plnum, (msecstouse - independantphysics[plnum].msec), wantfps); CL_BaseMove (&independantphysics[plnum], plnum, (msecstouse - independantphysics[plnum].msec), wantfps);
CL_FinishMove(&independantphysics[plnum], msecstouse, plnum); CL_FinishMove(&independantphysics[plnum], msecstouse, plnum);
Cbuf_Waited(); //its okay to stop waiting now
} }
// if we are spectator, try autocam // if we are spectator, try autocam

View file

@ -4663,19 +4663,22 @@ void CL_ParseSetInfo (void)
char value[MAX_QWMSGLEN]; char value[MAX_QWMSGLEN];
slot = MSG_ReadByte (); slot = MSG_ReadByte ();
if (slot >= MAX_CLIENTS)
Host_EndGame ("CL_ParseServerMessage: svc_setinfo > MAX_SCOREBOARD");
player = &cl.players[slot];
Q_strncpyz (key, MSG_ReadString(), sizeof(key)); Q_strncpyz (key, MSG_ReadString(), sizeof(key));
Q_strncpyz (value, MSG_ReadString(), sizeof(value)); Q_strncpyz (value, MSG_ReadString(), sizeof(value));
if (slot >= MAX_CLIENTS)
Con_Printf("INVALID SETINFO %i: %s=%s\n", slot, key, value);
else
{
player = &cl.players[slot];
Con_DPrintf("SETINFO %s: %s=%s\n", player->name, key, value); Con_DPrintf("SETINFO %s: %s=%s\n", player->name, key, value);
Info_SetValueForStarKey (player->userinfo, key, value, sizeof(player->userinfo)); Info_SetValueForStarKey (player->userinfo, key, value, sizeof(player->userinfo));
CL_ProcessUserInfo (slot, player); CL_ProcessUserInfo (slot, player);
}
} }
/* /*
@ -5691,6 +5694,32 @@ void CL_ParsePrint(char *msg, int level)
} }
void CL_ParseTeamInfo(void)
{
unsigned int pidx = atoi(Cmd_Argv(1));
vec3_t org =
{
atof(Cmd_Argv(2)),
atof(Cmd_Argv(3)),
atof(Cmd_Argv(4))
};
float health = atof(Cmd_Argv(5));
float armour = atof(Cmd_Argv(6));
unsigned int items = strtoul(Cmd_Argv(7), NULL, 0);
char *nick = Cmd_Argv(8);
if (pidx < cl.allocated_client_slots)
{
player_info_t *pl = &cl.players[pidx];
pl->tinfo.time = cl.time+5;
pl->tinfo.health = health;
pl->tinfo.armour = armour;
pl->tinfo.items = items;
VectorCopy(org, pl->tinfo.org);
Q_strncpyz(pl->tinfo.nick, nick, sizeof(pl->tinfo.nick));
}
}
char stufftext[4096]; char stufftext[4096];
void CL_ParseStuffCmd(char *msg, int destsplit) //this protects stuffcmds from network segregation. void CL_ParseStuffCmd(char *msg, int destsplit) //this protects stuffcmds from network segregation.
@ -5781,7 +5810,8 @@ void CL_ParseStuffCmd(char *msg, int destsplit) //this protects stuffcmds from n
else if (!strncmp(stufftext, "//tinfo ", 8)) else if (!strncmp(stufftext, "//tinfo ", 8))
{ {
Cmd_TokenizeString(stufftext+2, false, false); Cmd_TokenizeString(stufftext+2, false, false);
Plug_Command_f(); CL_ParseTeamInfo();
Plug_Command_f(); //FIXME: deprecate this call
} }
else if (!strncmp(stufftext, "//sn ", 5)) else if (!strncmp(stufftext, "//sn ", 5))
{ {

View file

@ -695,6 +695,95 @@ static qintptr_t VARGS Plug_GetLocationName(void *offset, quintptr_t mask, const
return VM_LONG(arg[1]); return VM_LONG(arg[1]);
} }
typedef struct
{
unsigned int client;
unsigned int items;
float armor;
float health;
vec3_t org;
char nick[16];
} teamplayerinfo_t;
static qintptr_t VARGS Plug_GetTeamInfo(void *offset, quintptr_t mask, const qintptr_t *arg)
{
teamplayerinfo_t *players = VM_POINTER(arg[0]);
size_t maxplayers = VM_LONG(arg[1]);
qboolean showenemies = VM_LONG(arg[2]);
qboolean showself = VM_LONG(arg[3]);
int count = 0;
int i;
int self;
lerpents_t *le;
player_info_t *pl;
if (VM_OOB(arg[0], maxplayers*sizeof(*players)))
return 0;
maxplayers = min(maxplayers, cl.allocated_client_slots);
Cvar_Get("ti", "1", CVAR_USERINFO, "Hacks because ktx sucks. Must be 1 in order to receive team information in ktx.");
self = cl.playerview[0].playernum;
if (cl.playerview[0].cam_state != CAM_FREECAM)
self = cl.playerview[0].cam_spec_track;
for (i = 0; i < cl.allocated_client_slots && maxplayers > 0; i++)
{
if (!*cl.players[i].name) //empty slot
continue;
if (cl.players[i].spectator) //shoo!
continue;
if (i == self && !showself)
continue;
if (!showenemies && strcmp(cl.players[i].team, cl.players[self].team))
continue;
players->client = i;
pl = &cl.players[i];
if (pl->tinfo.time > cl.time)
{ //mod is explicitly telling us this junk
players->items = pl->tinfo.items;
players->health = pl->tinfo.health;
players->armor = pl->tinfo.armour;
VectorCopy(pl->tinfo.org, players->org);
Q_strncpyz(players->nick, pl->tinfo.nick, sizeof(players->nick));
}
else if (i == self)
{ //oh hey look, its me.
players->items = cl.playerview[0].stats[STAT_ITEMS];
players->armor = cl.playerview[0].statsf[STAT_ARMOR];
players->health = cl.playerview[0].statsf[STAT_HEALTH];
Q_strncpyz(players->nick, "", sizeof(players->nick));
}
else
{ //scrape it from the mvd (assuming there is one...
players->items = cl.players[i].stats[STAT_ITEMS];
players->armor = cl.players[i].statsf[STAT_ARMOR];
players->health = cl.players[i].statsf[STAT_HEALTH];
Q_strncpyz(players->nick, "", sizeof(players->nick));
VectorClear(players->org);
}
//scrape origin from interpolation, if its more valid.
if (i+1 < cl.maxlerpents && cl.lerpentssequence && cl.lerpents[i+1].sequence == cl.lerpentssequence)
{
le = &cl.lerpents[i+1];
VectorCopy(le->origin, players->org);
}
else if (cl.lerpentssequence && cl.lerpplayers[i].sequence == cl.lerpentssequence)
{
le = &cl.lerpplayers[i];
VectorCopy(le->origin, players->org);
}
players++;
maxplayers--;
count++;
}
return VM_LONG(count);
}
static qintptr_t VARGS Plug_Con_SubPrint(void *offset, quintptr_t mask, const qintptr_t *arg) static qintptr_t VARGS Plug_Con_SubPrint(void *offset, quintptr_t mask, const qintptr_t *arg)
{ {
char *name = VM_POINTER(arg[0]); char *name = VM_POINTER(arg[0]);
@ -1058,6 +1147,7 @@ void Plug_Client_Init(void)
Plug_RegisterBuiltin("LocalSound", Plug_LocalSound, PLUG_BIF_NEEDSRENDERER); Plug_RegisterBuiltin("LocalSound", Plug_LocalSound, PLUG_BIF_NEEDSRENDERER);
Plug_RegisterBuiltin("SCR_CenterPrint", Plug_SCR_CenterPrint, PLUG_BIF_NEEDSRENDERER); Plug_RegisterBuiltin("SCR_CenterPrint", Plug_SCR_CenterPrint, PLUG_BIF_NEEDSRENDERER);
Plug_RegisterBuiltin("GetTeamInfo", Plug_GetTeamInfo, PLUG_BIF_NEEDSRENDERER);
Plug_RegisterBuiltin("GetLocationName", Plug_GetLocationName, PLUG_BIF_NEEDSRENDERER); Plug_RegisterBuiltin("GetLocationName", Plug_GetLocationName, PLUG_BIF_NEEDSRENDERER);
Plug_RegisterBuiltin("GetPlayerInfo", Plug_GetPlayerInfo, PLUG_BIF_NEEDSRENDERER); Plug_RegisterBuiltin("GetPlayerInfo", Plug_GetPlayerInfo, PLUG_BIF_NEEDSRENDERER);
Plug_RegisterBuiltin("LocalPlayerNumber", Plug_LocalPlayerNumber, PLUG_BIF_NEEDSRENDERER); Plug_RegisterBuiltin("LocalPlayerNumber", Plug_LocalPlayerNumber, PLUG_BIF_NEEDSRENDERER);

View file

@ -164,6 +164,16 @@ typedef struct player_info_s
int ping; int ping;
qbyte pl; qbyte pl;
struct
{
float time; //invalid if too old.
int health;
int armour;
unsigned int items;
vec3_t org;
char nick[8]; //kinda short, yes.
} tinfo;
qboolean ignored; qboolean ignored;
qboolean vignored; qboolean vignored;

View file

@ -153,6 +153,12 @@ struct {
} cmd_text[RESTRICT_MAX+3+MAX_SPLITS]; //max is local. } cmd_text[RESTRICT_MAX+3+MAX_SPLITS]; //max is local.
//RESTRICT_MAX+1 is the from sever buffer (max+2 is for second player...) //RESTRICT_MAX+1 is the from sever buffer (max+2 is for second player...)
void Cbuf_Waited(void)
{
//input packet was sent to server, its okay to continue executing stuff like -attack now
cmd_text[RESTRICT_LOCAL].waitattime = 0;
}
/* /*
============ ============
Cmd_Wait_f Cmd_Wait_f
@ -424,6 +430,15 @@ void Cbuf_Execute (void)
{ {
int level; int level;
#ifndef SERVERONLY
if (cmd_text[RESTRICT_LOCAL].waitattime && cls.state == ca_active)
{
//keep binds blocked until after the next input frame was sent to the server (at which point it will be cleared
//this ensures that wait and +attack etc works synchronously, as though your client never even supported network independance! yay... I guess.
cmd_text[RESTRICT_LOCAL].waitattime = realtime;
}
#endif
for (level = 0; level < sizeof(cmd_text)/sizeof(cmd_text[0]); level++) for (level = 0; level < sizeof(cmd_text)/sizeof(cmd_text[0]); level++)
if (cmd_text[level].buf.cursize) if (cmd_text[level].buf.cursize)
Cbuf_ExecuteLevel(level); Cbuf_ExecuteLevel(level);

View file

@ -34,6 +34,7 @@ The game starts with a Cbuf_AddText ("exec quake.rc\n"); Cbuf_Execute ();
*/ */
void Cbuf_Waited(void);
void Cbuf_Init (void); void Cbuf_Init (void);
// allocates an initial text buffer that will grow as needed // allocates an initial text buffer that will grow as needed

View file

@ -924,11 +924,6 @@ void Cvar_ForceCheatVars(qboolean semicheats, qboolean absolutecheats)
if (!(var->flags & (CVAR_CHEAT|CVAR_SEMICHEAT))) if (!(var->flags & (CVAR_CHEAT|CVAR_SEMICHEAT)))
continue; continue;
if (var->flags & CVAR_RULESETLATCH)
{
Con_Printf("Hello\n");
}
latch = var->latched_string; latch = var->latched_string;
var->latched_string = NULL; var->latched_string = NULL;
if (!latch) if (!latch)

View file

@ -1283,6 +1283,7 @@
PreprocessorDefinitions="_DEBUG;WIN32;_WINDOWS;SERVERONLY;MULTITHREAD" PreprocessorDefinitions="_DEBUG;WIN32;_WINDOWS;SERVERONLY;MULTITHREAD"
MinimalRebuild="true" MinimalRebuild="true"
BasicRuntimeChecks="3" BasicRuntimeChecks="3"
SmallerTypeCheck="true"
RuntimeLibrary="0" RuntimeLibrary="0"
EnableFunctionLevelLinking="true" EnableFunctionLevelLinking="true"
FloatingPointModel="2" FloatingPointModel="2"

View file

@ -1031,9 +1031,22 @@ static qboolean Shader_LoadPermutations(char *name, program_t *prog, char *scrip
{ {
cvar_t *var; cvar_t *var;
char namebuf[64]; char namebuf[64];
char valuebuf[64];
memcpy(namebuf, script, end - script); memcpy(namebuf, script, end - script);
namebuf[end - script] = 0; namebuf[end - script] = 0;
var = Cvar_Get(namebuf, "0", CVAR_SHADERSYSTEM, "GLSL Variables"); while (*end == ' ' || *end == '\t')
end++;
if (*end == '=')
{
script = ++end;
while (*end && *end != '\n' && *end != '\r' && end < script+sizeof(namebuf)-1)
end++;
memcpy(valuebuf, script, end - script);
valuebuf[end - script] = 0;
}
else
strcpy(valuebuf, "0");
var = Cvar_Get(namebuf, valuebuf, CVAR_SHADERSYSTEM, "GLSL Variables");
if (var) if (var)
permutationdefines[nummodifiers++] = Z_StrDup(va("#define %s %g\n", namebuf, var->value)); permutationdefines[nummodifiers++] = Z_StrDup(va("#define %s %g\n", namebuf, var->value));
} }

View file

@ -2294,6 +2294,7 @@ static void GLSlang_ProgAutoFields(program_t *prog, char **cvarnames, int *cvart
/*set cvar unirforms*/ /*set cvar unirforms*/
for (i = 0; cvarnames[i]; i++) for (i = 0; cvarnames[i]; i++)
{ {
char *tmpval;
if (prog->numparams == SHADER_PROGPARMS_MAX) if (prog->numparams == SHADER_PROGPARMS_MAX)
{ {
Con_Printf("Too many cvar paramters for program\n"); Con_Printf("Too many cvar paramters for program\n");
@ -2302,7 +2303,14 @@ static void GLSlang_ProgAutoFields(program_t *prog, char **cvarnames, int *cvart
for (p = 0; cvarnames[i][p] && (unsigned char)cvarnames[i][p] > 32 && p < sizeof(tmpname)-1; p++) for (p = 0; cvarnames[i][p] && (unsigned char)cvarnames[i][p] > 32 && p < sizeof(tmpname)-1; p++)
tmpname[p] = cvarnames[i][p]; tmpname[p] = cvarnames[i][p];
tmpname[p] = 0; tmpname[p] = 0;
cvar = Cvar_Get(tmpname, "0", CVAR_SHADERSYSTEM, "glsl cvars"); tmpval = strchr(tmpname, '=');
if (tmpval)
*tmpval++ = 0;
else
tmpval = "0";
while(p > 0 && (tmpname[p-1] == ' ' || tmpname[p-1] == '\t'))
tmpname[--p] = 0;
cvar = Cvar_Get(tmpname, tmpval, CVAR_SHADERSYSTEM, "glsl cvars");
if (!cvar) if (!cvar)
continue; continue;
cvar->flags |= CVAR_SHADERSYSTEM; cvar->flags |= CVAR_SHADERSYSTEM;

View file

@ -4,6 +4,8 @@
#include <ctype.h> #include <ctype.h>
//#include <sys/time.h> //#include <sys/time.h>
#undef progfuncs
#define PATHSEPERATOR '/' #define PATHSEPERATOR '/'
#ifndef QCC #ifndef QCC
@ -131,8 +133,8 @@ void QC_strlcat(char *dest, const char *src, size_t destsize)
dest += curlen; dest += curlen;
while(*src && ++curlen < destsize) while(*src && ++curlen < destsize)
*dest++ = *src++; *dest++ = *src++;
if (*src) // if (*src)
printf("QC_strlcpy: truncation\n"); // printf("QC_strlcpy: truncation\n");
*dest = 0; *dest = 0;
} }
void QC_strlcpy(char *dest, const char *src, size_t destsize) void QC_strlcpy(char *dest, const char *src, size_t destsize)
@ -142,8 +144,8 @@ void QC_strlcpy(char *dest, const char *src, size_t destsize)
return; //err return; //err
while(*src && ++curlen < destsize) while(*src && ++curlen < destsize)
*dest++ = *src++; *dest++ = *src++;
if (*src) // if (*src)
printf("QC_strlcpy: truncation\n"); // printf("QC_strlcpy: truncation\n");
*dest = 0; *dest = 0;
} }
void QC_strnlcpy(char *dest, const char *src, size_t srclen, size_t destsize) void QC_strnlcpy(char *dest, const char *src, size_t srclen, size_t destsize)
@ -153,8 +155,8 @@ void QC_strnlcpy(char *dest, const char *src, size_t srclen, size_t destsize)
return; //err return; //err
for(; *src && srclen > 0 && ++curlen < destsize; srclen--) for(; *src && srclen > 0 && ++curlen < destsize; srclen--)
*dest++ = *src++; *dest++ = *src++;
if (srclen) // if (srclen)
printf("QC_strlcpy: truncation\n"); // printf("QC_strlcpy: truncation\n");
*dest = 0; *dest = 0;
} }
@ -312,7 +314,7 @@ skipwhite:
} }
else if (c=='\0') else if (c=='\0')
{ {
printf("ERROR: Unterminated string\n"); // printf("ERROR: Unterminated string\n");
qcc_token[len] = 0; qcc_token[len] = 0;
return (char*)data; return (char*)data;
} }
@ -324,7 +326,7 @@ skipwhite:
//so \r\n terminates the string if the last char was an escaped quote, but not otherwise. //so \r\n terminates the string if the last char was an escaped quote, but not otherwise.
if (len > 0 && qcc_token[len-1] == '\"') if (len > 0 && qcc_token[len-1] == '\"')
{ {
printf("ERROR: new line in string\n"); // printf("ERROR: new line in string\n");
qcc_token[len] = 0; qcc_token[len] = 0;
return (char*)data; return (char*)data;
} }
@ -519,6 +521,7 @@ For abnormal program terminations
*/ */
void VARGS QCC_Error (int errortype, const char *error, ...) void VARGS QCC_Error (int errortype, const char *error, ...)
{ {
progfuncs_t *progfuncs = qccprogfuncs;
extern int numsourcefiles; extern int numsourcefiles;
va_list argptr; va_list argptr;
char msg[2048]; char msg[2048];
@ -877,6 +880,7 @@ int SafeSeek(int hand, int ofs, int mode)
} }
pbool SafeClose(int hand) pbool SafeClose(int hand)
{ {
progfuncs_t *progfuncs = qccprogfuncs;
pbool ret; pbool ret;
ret = externs->WriteFile(qccfile[hand].name, qccfile[hand].buff, qccfile[hand].maxofs); ret = externs->WriteFile(qccfile[hand].name, qccfile[hand].buff, qccfile[hand].maxofs);
// if (qccfile[hand].buffismalloc) // if (qccfile[hand].buffismalloc)
@ -1163,6 +1167,7 @@ char *QCC_SanitizeCharSet(char *mem, unsigned int *len, pbool *freeresult, int *
long QCC_LoadFile (char *filename, void **bufferptr) long QCC_LoadFile (char *filename, void **bufferptr)
{ {
progfuncs_t *progfuncs = qccprogfuncs;
char *mem; char *mem;
int check; int check;
int flen; int flen;
@ -1221,6 +1226,7 @@ long QCC_LoadFile (char *filename, void **bufferptr)
} }
void QCC_AddFile (char *filename) void QCC_AddFile (char *filename)
{ {
progfuncs_t *progfuncs = qccprogfuncs;
char *mem; char *mem;
int len; int len;
len = externs->FileSize(filename); len = externs->FileSize(filename);
@ -1241,6 +1247,7 @@ void QCC_AddFile (char *filename)
} }
void *FS_ReadToMem(char *filename, void *mem, int *len) void *FS_ReadToMem(char *filename, void *mem, int *len)
{ {
progfuncs_t *progfuncs = qccprogfuncs;
if (!mem) if (!mem)
{ {
*len = externs->FileSize(filename); *len = externs->FileSize(filename);
@ -1251,6 +1258,7 @@ void *FS_ReadToMem(char *filename, void *mem, int *len)
void FS_CloseFromMem(void *mem) void FS_CloseFromMem(void *mem)
{ {
progfuncs_t *progfuncs = qccprogfuncs;
externs->memfree(mem); externs->memfree(mem);
} }

View file

@ -6512,15 +6512,15 @@ static void QCBUILTIN PF_clientcommand (pubprogfuncs_t *prinst, struct globalvar
{ {
client_t *oldhostclient = host_client; client_t *oldhostclient = host_client;
edict_t *oldsvplayer = sv_player; edict_t *oldsvplayer = sv_player;
int i; unsigned int i;
//find client for this entity //find client for this entity
i = NUM_FOR_EDICT(prinst, G_EDICT(prinst, OFS_PARM0)) - 1; i = NUM_FOR_EDICT(prinst, G_EDICT(prinst, OFS_PARM0));
if (i < 0 || i >= sv.allocated_client_slots) if (i <= 0 || i > sv.allocated_client_slots)
PR_BIError(prinst, "PF_clientcommand: entity is not a client"); PR_BIError(prinst, "PF_clientcommand: entity is not a client");
else else
{ {
host_client = &svs.clients[i]; host_client = &svs.clients[i-1];
sv_player = host_client->edict; sv_player = host_client->edict;
if (host_client->state == cs_connected || host_client->state == cs_spawned) if (host_client->state == cs_connected || host_client->state == cs_spawned)
{ {

View file

@ -57,6 +57,12 @@ void Draw_TextBox (int x, int y, int width, int lines)
{ {
} }
char *TP_LocationName (vec3_t location)
{
static char locname[256];
pGetLocationName(location, locname, sizeof(locname));
return locname;
}
void Draw_SPic(float x, float y, mpic_t *pic, float scale) void Draw_SPic(float x, float y, mpic_t *pic, float scale)
@ -224,9 +230,35 @@ int Sbar_BottomColor(player_info_t *pi)
{ {
return Sbar_ColorForMap(pi->bottomcolour); return Sbar_ColorForMap(pi->bottomcolour);
} }
int dehex(char nib)
{
if (nib >= '0' && nib <= '9')
return nib - '0';
if (nib >= 'a' && nib <= 'f')
return nib - 'a' + 10;
if (nib >= 'A' && nib <= 'F')
return nib - 'A' + 10;
return 0;
}
char *TP_ParseFunChars(char *str, qbool chat) char *TP_ParseFunChars(char *str, qbool chat)
{ {
return str; static char resultbuf[1024];
char *out = resultbuf, *end = resultbuf+sizeof(resultbuf)-1;
while (out < end)
{
if (str[0] == '$' && str[1] == 'x' && str[2] && str[3])
{
*out++ = (dehex(str[2]) << 4) | dehex(str[3]);
str+=4;
}
else if (*str)
*out++ = *str++;
else
break;
}
*out = 0;
return resultbuf;
} }
char *TP_ItemName(unsigned int itbit) char *TP_ItemName(unsigned int itbit)
{ {
@ -633,6 +665,7 @@ qintptr_t Plug_Init(qintptr_t *args)
CHECKBUILTIN(Cvar_GetNVFDG); CHECKBUILTIN(Cvar_GetNVFDG);
if (BUILTINISVALID(Cvar_GetNVFDG) && if (BUILTINISVALID(Cvar_GetNVFDG) &&
BUILTINISVALID(Draw_ImageSize) && BUILTINISVALID(Draw_ImageSize) &&
BUILTINISVALID(GetTeamInfo) &&
Plug_Export("SbarBase", EZHud_Draw) && Plug_Export("SbarBase", EZHud_Draw) &&
Plug_Export("MenuEvent", EZHud_MenuEvent) && Plug_Export("MenuEvent", EZHud_MenuEvent) &&
Plug_Export("Tick", EZHud_Tick) && Plug_Export("Tick", EZHud_Tick) &&

View file

@ -5265,19 +5265,15 @@ static void SCR_HUD_DrawTeamHoldInfo(hud_t *hud)
} }
#endif #endif
#ifdef HAXX static int SCR_HudDrawTeamInfoPlayer(teamplayerinfo_t *ti_cl, int x, int y, int maxname, int maxloc, qbool width_only, hud_t *hud);
static int SCR_HudDrawTeamInfoPlayer(ti_player_t *ti_cl, int x, int y, int maxname, int maxloc, qbool width_only, hud_t *hud);
#endif
#ifdef HAXX #define FONTWIDTH 8
static void SCR_HUD_DrawTeamInfo(hud_t *hud) static void SCR_HUD_DrawTeamInfo(hud_t *hud)
{ {
int x, y, _y, width, height; int x, y, _y, width, height;
int i, j, k, slots[MAX_CLIENTS], slots_num, maxname, maxloc; int i, j, k, slots_num, maxname, maxloc;
char tmp[1024], *nick; char tmp[1024], *nick;
teamplayerinfo_t ti_clients[MAX_CLIENTS];
// Used for hud_teaminfo, data is collected in screen.c / scr_teaminfo
extern ti_player_t ti_clients[MAX_CLIENTS];
extern qbool hud_editor; extern qbool hud_editor;
@ -5302,45 +5298,29 @@ static void SCR_HUD_DrawTeamInfo(hud_t *hud)
} }
// Don't update hud item unless first view is beeing displayed // Don't update hud item unless first view is beeing displayed
if ( CURRVIEW != 1 && CURRVIEW != 0) // if ( CURRVIEW != 1 && CURRVIEW != 0)
return; // return;
if (cls.mvdplayback) slots_num = pGetTeamInfo(ti_clients, countof(ti_clients), hud_teaminfo_show_enemies->ival, hud_teaminfo_show_self->ival);
Update_TeamInfo();
// fill data we require to draw teaminfo // fill data we require to draw teaminfo
for ( maxloc = maxname = slots_num = i = 0; i < MAX_CLIENTS; i++ ) { for ( maxloc = maxname = i = 0; i < slots_num; i++ ) {
if ( !cl.players[i].name[0] || cl.players[i].spectator
|| !ti_clients[i].time || ti_clients[i].time + 5 < cl.time
)
continue;
// do not show enemy players unless it's MVD and user wishes to show them
if (VX_TrackerIsEnemy( i ) && (!cls.mvdplayback || !hud_teaminfo_show_enemies->integer))
continue;
// do not show tracked player to spectator
if ((cl.spectator && Cam_TrackNum() == i) && hud_teaminfo_show_self->integer == 0)
continue;
// dynamically guess max length of name/location // dynamically guess max length of name/location
nick = (ti_clients[i].nick[0] ? ti_clients[i].nick : cl.players[i].name); // we use nick or name nick = (ti_clients[i].nick[0] ? ti_clients[i].nick : cl.players[i].name); // we use nick or name
maxname = max(maxname, strlen(TP_ParseFunChars(nick, false))); maxname = max(maxname, strlen(TP_ParseFunChars(nick, false)));
strlcpy(tmp, TP_LocationName(ti_clients[i].org), sizeof(tmp)); strlcpy(tmp, TP_LocationName(ti_clients[i].org), sizeof(tmp));
maxloc = max(maxloc, strlen(TP_ParseFunChars(tmp, false))); maxloc = max(maxloc, strlen(TP_ParseFunChars(tmp, false)));
slots[slots_num++] = i;
} }
// well, better use fixed loc length // well, better use fixed loc length
maxloc = bound(0, hud_teaminfo_loc_width->integer, 100); maxloc = bound(0, hud_teaminfo_loc_width->ival, 100);
// limit name length // limit name length
maxname = bound(0, maxname, hud_teaminfo_name_width->integer); maxname = bound(0, maxname, hud_teaminfo_name_width->ival);
// this does't draw anything, just calculate width // this does't draw anything, just calculate width
width = FONTWIDTH * hud_teaminfo_scale->value * SCR_HudDrawTeamInfoPlayer(&ti_clients[0], 0, 0, maxname, maxloc, true, hud); width = FONTWIDTH * hud_teaminfo_scale->value * SCR_HudDrawTeamInfoPlayer(&ti_clients[0], 0, 0, maxname, maxloc, true, hud);
height = FONTWIDTH * hud_teaminfo_scale->value * (hud_teaminfo_show_enemies->integer?slots_num+n_teams:slots_num); height = FONTWIDTH * hud_teaminfo_scale->value * (hud_teaminfo_show_enemies->ival?slots_num+n_teams:slots_num);
if (hud_editor) if (hud_editor)
HUD_PrepareDraw(hud, width , FONTWIDTH, &x, &y); HUD_PrepareDraw(hud, width , FONTWIDTH, &x, &y);
@ -5359,7 +5339,7 @@ static void SCR_HUD_DrawTeamInfo(hud_t *hud)
// If multiple teams are displayed then sort the display and print team header on overlay // If multiple teams are displayed then sort the display and print team header on overlay
k=0; k=0;
if (hud_teaminfo_show_enemies->integer) if (hud_teaminfo_show_enemies->ival)
{ {
while (sorted_teams[k].name) while (sorted_teams[k].name)
{ {
@ -5369,10 +5349,10 @@ static void SCR_HUD_DrawTeamInfo(hud_t *hud)
_y += FONTWIDTH * hud_teaminfo_scale->value; _y += FONTWIDTH * hud_teaminfo_scale->value;
for ( j = 0; j < slots_num; j++ ) for ( j = 0; j < slots_num; j++ )
{ {
i = slots[j]; i = ti_clients[j].client;
if (!strcmp(cl.players[i].team,sorted_teams[k].name)) if (!strcmp(cl.players[i].team,sorted_teams[k].name))
{ {
SCR_HudDrawTeamInfoPlayer(&ti_clients[i], x, _y, maxname, maxloc, false, hud); SCR_HudDrawTeamInfoPlayer(&ti_clients[j], x, _y, maxname, maxloc, false, hud);
_y += FONTWIDTH * hud_teaminfo_scale->value; _y += FONTWIDTH * hud_teaminfo_scale->value;
} }
} }
@ -5382,22 +5362,61 @@ static void SCR_HUD_DrawTeamInfo(hud_t *hud)
else else
{ {
for ( j = 0; j < slots_num; j++ ) { for ( j = 0; j < slots_num; j++ ) {
i = slots[j]; SCR_HudDrawTeamInfoPlayer(&ti_clients[j], x, _y, maxname, maxloc, false, hud);
SCR_HudDrawTeamInfoPlayer(&ti_clients[i], x, _y, maxname, maxloc, false, hud);
_y += FONTWIDTH * hud_teaminfo_scale->value; _y += FONTWIDTH * hud_teaminfo_scale->value;
} }
} }
} }
#endif
qbool Has_Both_RL_and_LG (int flags) { return (flags & IT_ROCKET_LAUNCHER) && (flags & IT_LIGHTNING); } qbool Has_Both_RL_and_LG (int flags) { return (flags & IT_ROCKET_LAUNCHER) && (flags & IT_LIGHTNING); }
#ifdef HAXX #define FONTWIDTH 8
static int SCR_HudDrawTeamInfoPlayer(ti_player_t *ti_cl, int x, int y, int maxname, int maxloc, qbool width_only, hud_t *hud) void str_align_right (char *target, size_t size, const char *source, size_t length)
{
if (length > size - 1)
length = size - 1;
if (strlen(source) >= length) {
strlcpy(target, source, size);
target[length] = 0;
} else {
int i;
for (i = 0; i < length - strlen(source); i++) {
target[i] = ' ';
}
strlcpy(target + i, source, size - i);
}
}
int Player_GetTrackId(int uid)
{
return uid;
}
unsigned int BestWeaponFromStatItems(unsigned int items)
{
int i;
for (i = 1<<7; i; i>>=1)
{
if (items & i)
return i;
}
return 0;
}
mpic_t * SCR_GetWeaponIconByFlag (int flag)
{
int i, j;
for (i = 0, j = 1; i < 7; i++, j*=2)
{
if (flag == j)
return sb_weapons[0][i];
}
return NULL;
}
static int SCR_HudDrawTeamInfoPlayer(teamplayerinfo_t *ti_cl, int x, int y, int maxname, int maxloc, qbool width_only, hud_t *hud)
{ {
extern mpic_t * SCR_GetWeaponIconByFlag (int flag); extern mpic_t * SCR_GetWeaponIconByFlag (int flag);
extern cvar_t tp_name_rlg;
char *s, *loc, tmp[1024], tmp2[MAX_MACRO_STRING], *aclr; char *s, *loc, tmp[1024], tmp2[1024], *aclr;
int x_in = x; // save x int x_in = x; // save x
int i; int i;
mpic_t *pic; mpic_t *pic;
@ -5442,11 +5461,11 @@ static int SCR_HudDrawTeamInfoPlayer(ti_player_t *ti_cl, int x, int y, int maxna
break; break;
case 'w': // draw "best" weapon icon/name case 'w': // draw "best" weapon icon/name
switch (HUD_FindVar(hud, "weapon_style")->integer) { switch (HUD_FindVar(hud, "weapon_style")->ival) {
case 1: case 1:
if(!width_only) { if(!width_only) {
if (Has_Both_RL_and_LG(ti_cl->items)) { if (Has_Both_RL_and_LG(ti_cl->items)) {
char *weap_str = tp_name_rlg.string; char *weap_str = pCvar_GetNVFDG("tp_name_rlg", "rlg", 0, NULL, NULL)->string;
char weap_white_stripped[32]; char weap_white_stripped[32];
Util_SkipChars(weap_str, "{}", weap_white_stripped, 32); Util_SkipChars(weap_str, "{}", weap_white_stripped, 32);
Draw_ColoredString (x, y, weap_white_stripped, false); Draw_ColoredString (x, y, weap_white_stripped, false);
@ -5475,7 +5494,7 @@ static int SCR_HudDrawTeamInfoPlayer(ti_player_t *ti_cl, int x, int y, int maxna
case 'H': // draw health, padding with space on right side case 'H': // draw health, padding with space on right side
if(!width_only) { if(!width_only) {
snprintf(tmp, sizeof(tmp), (s[0] == 'h' ? "%s%3d" : "%s%-3d"), (ti_cl->health < HUD_FindVar(hud, "low_health")->integer ? "&cf00" : ""), ti_cl->health); snprintf(tmp, sizeof(tmp), (s[0] == 'h' ? "%s%3d" : "%s%-3d"), (ti_cl->health < HUD_FindVar(hud, "low_health")->ival ? "&cf00" : ""), (int)ti_cl->health);
Draw_SString (x, y, tmp, scale); Draw_SString (x, y, tmp, scale);
} }
x += 3 * FONTWIDTH * scale; x += 3 * FONTWIDTH * scale;
@ -5489,7 +5508,7 @@ static int SCR_HudDrawTeamInfoPlayer(ti_player_t *ti_cl, int x, int y, int maxna
// //
// different styles of armor // different styles of armor
// //
switch (HUD_FindVar(hud,"armor_style")->integer) { switch (HUD_FindVar(hud,"armor_style")->ival) {
case 1: // image prefixed armor value case 1: // image prefixed armor value
if(!width_only) { if(!width_only) {
if (ti_cl->items & IT_ARMOR3) if (ti_cl->items & IT_ARMOR3)
@ -5546,7 +5565,7 @@ static int SCR_HudDrawTeamInfoPlayer(ti_player_t *ti_cl, int x, int y, int maxna
} }
if(!width_only) { // value drawed no matter which style if(!width_only) { // value drawed no matter which style
snprintf(tmp, sizeof(tmp), (s[0] == 'a' ? "%s%3d" : "%s%-3d"), aclr, ti_cl->armor); snprintf(tmp, sizeof(tmp), (s[0] == 'a' ? "%s%3d" : "%s%-3d"), aclr, (int)ti_cl->armor);
Draw_SString (x, y, tmp, scale); Draw_SString (x, y, tmp, scale);
} }
x += 3 * FONTWIDTH * scale; x += 3 * FONTWIDTH * scale;
@ -5566,7 +5585,7 @@ static int SCR_HudDrawTeamInfoPlayer(ti_player_t *ti_cl, int x, int y, int maxna
break; break;
case 'p': // draw powerups case 'p': // draw powerups
switch (HUD_FindVar(hud, "powerup_style")->integer) { switch (HUD_FindVar(hud, "powerup_style")->ival) {
case 1: // quad/pent/ring image case 1: // quad/pent/ring image
if(!width_only) { if(!width_only) {
if (ti_cl->items & IT_QUAD) if (ti_cl->items & IT_QUAD)
@ -5658,7 +5677,6 @@ static int SCR_HudDrawTeamInfoPlayer(ti_player_t *ti_cl, int x, int y, int maxna
return (x - x_in) / (FONTWIDTH * scale); // return width return (x - x_in) / (FONTWIDTH * scale); // return width
} }
#endif
#ifdef HAXX #ifdef HAXX
void SCR_HUD_DrawItemsClock(hud_t *hud) void SCR_HUD_DrawItemsClock(hud_t *hud)
@ -8046,7 +8064,6 @@ void CommonDraw_Init(void)
"maxname", "16", "maxname", "16",
NULL); NULL);
#ifdef HAXX
HUD_Register("teaminfo", NULL, "Show information about your team in short form.", HUD_Register("teaminfo", NULL, "Show information about your team in short form.",
0, ca_active, 0, SCR_HUD_DrawTeamInfo, 0, ca_active, 0, SCR_HUD_DrawTeamInfo,
"0", "", "right", "center", "0", "0", "0.2", "20 20 20", NULL, "0", "", "right", "center", "0", "0", "0.2", "20 20 20", NULL,
@ -8062,7 +8079,6 @@ void CommonDraw_Init(void)
"scale","1", "scale","1",
"powerup_style","1", "powerup_style","1",
NULL); NULL);
#endif
HUD_Register("mp3_title", NULL, "Shows current mp3 playing.", HUD_Register("mp3_title", NULL, "Shows current mp3 playing.",
HUD_PLUSMINUS, ca_disconnected, 0, SCR_HUD_DrawMP3_Title, HUD_PLUSMINUS, ca_disconnected, 0, SCR_HUD_DrawMP3_Title,

View file

@ -155,6 +155,10 @@ BUILTIN(void, SetUserInfo, (const char *key, const char *value));
BUILTIN(void, GetLocationName, (const float *pos, char *buffer, int bufferlen)); BUILTIN(void, GetLocationName, (const float *pos, char *buffer, int bufferlen));
#undef ARGNAMES #undef ARGNAMES
#define ARGNAMES ,clients,maxclients,showenemies,showself
BUILTINR(int, GetTeamInfo, (teamplayerinfo_t *clients, unsigned int maxclients, int showenemies, int showself));
#undef ARGNAMES
#define ARGNAMES ,soundname #define ARGNAMES ,soundname
BUILTIN(void, LocalSound, (const char *soundname)); BUILTIN(void, LocalSound, (const char *soundname));
#undef ARGNAMES #undef ARGNAMES
@ -423,6 +427,7 @@ void Plug_InitStandardBuiltins(void)
CHECKBUILTIN(Menu_Control); CHECKBUILTIN(Menu_Control);
CHECKBUILTIN(Key_GetKeyCode); CHECKBUILTIN(Key_GetKeyCode);
CHECKBUILTIN(GetLocationName); CHECKBUILTIN(GetLocationName);
CHECKBUILTIN(GetTeamInfo);
CHECKBUILTIN(GetNetworkInfo); CHECKBUILTIN(GetNetworkInfo);
//drawing routines //drawing routines

View file

@ -233,7 +233,17 @@ EBUILTIN(int, GetLocalPlayerNumbers, (int firstseat, int numseats, int *playernu
EBUILTIN(void, GetServerInfo, (char *info, int infolen)); EBUILTIN(void, GetServerInfo, (char *info, int infolen));
EBUILTIN(void, SetUserInfo, (const char *key, const char *value)); EBUILTIN(void, SetUserInfo, (const char *key, const char *value));
EBUILTIN(void, GetLocationName, (const float *pos, char *buffer, int bufferlen)); EBUILTIN(void, GetLocationName, (const float *pos, char *buffer, int bufferlen));
EBUILTIN(void, GetLocationName, (const float *pos, char *buffer, int bufferlen));
typedef struct
{
unsigned int client;
unsigned int items;
float armor;
float health;
vec3_t org;
char nick[16];
} teamplayerinfo_t;
EBUILTIN(int, GetTeamInfo, (teamplayerinfo_t *clients, unsigned int maxclients, int showenemies, int showself));
typedef struct { typedef struct {
int seats; int seats;

View file

@ -15,6 +15,7 @@ int Q_vsnprintf(char *buffer, size_t maxlen, const char *format, va_list vargs)
int tokens=0; int tokens=0;
char *string; char *string;
char tempbuffer[64]; char tempbuffer[64];
char sign;
unsigned int _uint; unsigned int _uint;
int _int; int _int;
float _float; float _float;
@ -176,25 +177,22 @@ Con_Printf("%i bytes left\n", maxlen);
} }
if (_int < 0) if (_int < 0)
{ {
if (maxlen-- == 0) sign = '-';
{*buffer++='\0';return tokens;}
*buffer++ = '-';
_int *= -1; _int *= -1;
} }
else if (plus) else if (plus)
{ sign = '+';
if (maxlen-- == 0) else
{*buffer++='\0';return tokens;} sign = 0;
*buffer++ = '+';
}
i = sizeof(tempbuffer)-2; i = sizeof(tempbuffer)-2;
tempbuffer[sizeof(tempbuffer)-1] = '\0'; tempbuffer[sizeof(tempbuffer)-1] = '\0';
while(_int) while(_int)
{ {
tempbuffer[i] = _int%10 + '0'; tempbuffer[i--] = _int%10 + '0';
_int/=10; _int/=10;
i--;
} }
if (sign)
tempbuffer[i--] = sign;
string = tempbuffer+i+1; string = tempbuffer+i+1;
if (!*string) if (!*string)