seta hud_contents_water_color "0.4 0.3 0.3"
seta hud_shownames 1 "draw names and health/armor of nearby players"
-seta hud_shownames_enemies 2 "1 = draw names of enemies you point at, 2 = draw names of all enemies in view"
-seta hud_shownames_status 2 "1 = draw health/armor status of teammates, 2 = same as 1, but draw health/armor icons with a question mark on enemies in teamgames"
-seta hud_shownames_height 15 "height of icons"
+seta hud_shownames_enemies 2 "1 = draw names of enemies you point at (TODO), 2 = draw names of all enemies in view"
+seta hud_shownames_status 1 "1 = draw health/armor status of teammates"
+seta hud_shownames_statusbar_height 4 "height of status bar"
seta hud_shownames_aspect 8 "aspect ratio of total drawing area per name"
-seta hud_shownames_fontsize 13 "font size"
+seta hud_shownames_fontsize 12 "font size"
seta hud_shownames_decolorize 1 "1 = decolorize name in team games, 2 = decolorize always"
seta hud_shownames_alpha 0.7 "alpha"
seta hud_shownames_resize 1 "enable resizing of the names, then the size cvars will correspond to the maximum size"
seta hud_shownames_maxdistance 2500 "alpha/size is 0 at this distance"
seta hud_shownames_antioverlap 1 "if two tags get too close to each other, fade out the one further away from you"
seta hud_shownames_antioverlap_distance 125 "2d distance to other tag after which to fade out"
+seta hud_shownames_offset 52 "offset (along z-axis) tag from player origin by this many units"
// scoreboard
seta scoreboard_columns default
}
void Ent_ReadEntCS()
{
+ float sf;
InterpolateOrigin_Undo();
self.classname = "entcs_receiver";
- self.sv_entnum = ReadByte() - 1;
- self.origin_x = ReadShort();
- self.origin_y = ReadShort();
- self.origin_z = ReadShort();
- self.angles_y = ReadByte() * 360.0 / 256;
- self.angles_x = self.angles_z = 0;
+ sf = ReadByte();
+
+ if(sf & 1)
+ self.sv_entnum = ReadByte() - 1;
+ if(sf & 2)
+ {
+ self.origin_x = ReadShort();
+ self.origin_y = ReadShort();
+ self.origin_z = ReadShort();
+ }
+ if(sf & 4)
+ {
+ self.angles_y = ReadByte() * 360.0 / 256;
+ self.angles_x = self.angles_z = 0;
+ }
+
entcs_receiver[self.sv_entnum] = self;
self.entremove = Ent_RemoveEntCS;
// entity init, TODO can this be done only once somehow?
self.the_entnum = ReadByte(); // TODO: fixme to only send once somehow
self.draw2d = Draw_ShowNames;
+
//self.movetype = MOVETYPE_FLY; // movetype needed so we can traceline?
- self.mins = '-20 -20 -24';
- self.maxs = '20 20 45';
+ //self.mins = '-20 -20 -24';
+ //self.maxs = '20 20 45';
self.classname = "shownames_tag";
sf = ReadByte();
if(sf & 1)
{
- self.origin_x = ReadShort();
- self.origin_y = ReadShort();
- self.origin_z = ReadShort();
+ self.healthvalue = ReadByte() * 10;
}
if(sf & 2)
{
- self.healthvalue = ReadByte();
- }
- if(sf & 4)
- {
- self.armorvalue = ReadByte();
+ self.armorvalue = ReadByte() * 10;
}
if(sf & 128) // same team
CSQC_common_hud();
// crosshair goes VERY LAST
- if(!scoreboard_active && !camera_active && intermission != 2) {
+ if(!scoreboard_active && !camera_active && intermission != 2 && spectatee_status != -1) {
string wcross_style;
float wcross_alpha, wcross_resolution;
wcross_style = autocvar_crosshair;
float autocvar_hud_shownames;
float autocvar_hud_shownames_enemies;
float autocvar_hud_shownames_status;
-float autocvar_hud_shownames_height;
+float autocvar_hud_shownames_statusbar_height;
float autocvar_hud_shownames_aspect;
float autocvar_hud_shownames_fontsize;
float autocvar_hud_shownames_decolorize;
float autocvar_hud_shownames_maxdistance;
float autocvar_hud_shownames_antioverlap;
float autocvar_hud_shownames_antioverlap_distance;
+float autocvar_hud_shownames_offset;
string autocvar_hud_skin;
float autocvar_loddebug;
float autocvar_menu_mouse_speed;
#define SCOREPANEL_MAX_ENTRIES 6
#define SCOREPANEL_ASPECTRATIO 2
const float entries = bound(1, floor(SCOREPANEL_MAX_ENTRIES * mySize_y/mySize_x * SCOREPANEL_ASPECTRATIO), SCOREPANEL_MAX_ENTRIES);
- const float height = mySize_y/entries;
- const vector fontsize = '0.9 0.9 0' * height;
- pos_y += height * (1 - 0.9) / 2;
+ const vector fontsize = '1 1 0' * (mySize_y/entries);
vector rgb, score_color;
rgb = '1 1 1';
i, first_pl = 0;
if (autocvar__hud_configure)
{
+ float players_per_team;
if (team_count)
{
// show team scores in the first line
float score_size = mySize_x / team_count;
- for(tm = teams.sort_next; tm; tm = tm.sort_next) {
- if(tm.team == COLOR_SPECTATOR)
- continue;
- if (tm.team == myteam)
- HUD_Panel_DrawHighlight(pos - eY * (height * (1 - 0.9) / 2) + eX * score_size * i, eX * score_size + eY * height, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
- drawstring_aspect(pos + eX * score_size * i, ftos(123), eX * score_size + eY * fontsize_y, GetTeamRGB(tm.team) * 0.8, panel_fg_alpha, DRAWFLAG_NORMAL);
- ++i;
+ players_per_team = max(2, ceil((entries - 1) / team_count));
+ for(i=0; i<team_count; ++i) {
+ if (i == floor((entries - 2) / players_per_team) || (entries == 1 && i == 0))
+ HUD_Panel_DrawHighlight(pos + eX * score_size * i, eX * score_size + eY * fontsize_y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+ drawstring_aspect(pos + eX * score_size * i, ftos(175 - 23*i), eX * score_size + eY * fontsize_y, GetTeamRGB(ColorByTeam(i)) * 0.8, panel_fg_alpha, DRAWFLAG_NORMAL);
}
first_pl = 1;
- pos_y += height;
+ pos_y += fontsize_y;
}
score = 10 + SCOREPANEL_MAX_ENTRIES * 3;
for (i=first_pl; i<entries; ++i)
if (i == entries-1 && autocvar_hud_panel_score_rankings == 1)
{
rgb = '1 1 0';
- drawfill(pos - eY * (height * (1 - 0.9) / 2), eX * mySize_x + eY * height, rgb, highlight_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
+ drawfill(pos, eX * mySize_x + eY * fontsize_y, rgb, highlight_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
s = GetPlayerName(pl.sv_entnum);
score = 7;
}
}
if (team_count)
- score_color = GetTeamRGB(ColorByTeam(mod(i + 2, team_count))) * 0.8;
+ score_color = GetTeamRGB(ColorByTeam(floor((i - first_pl) / players_per_team))) * 0.8;
s = textShortenToWidth(s, name_size, fontsize, stringwidth_colors);
drawcolorcodedstring(pos + eX * (name_size - stringwidth(s, TRUE, fontsize)), s, fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
drawstring(pos + eX * (name_size + spacing_size), ftos(score), fontsize, score_color, panel_fg_alpha, DRAWFLAG_NORMAL);
- pos_y += height;
+ pos_y += fontsize_y;
}
return;
}
if(tm.team == COLOR_SPECTATOR)
continue;
if (tm.team == myteam)
- drawfill(pos - eY * (height * (1 - 0.9) / 2) + eX * score_size * i, eX * score_size + eY * height, '1 1 1', highlight_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
+ drawfill(pos + eX * score_size * i, eX * score_size + eY * fontsize_y, '1 1 1', highlight_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
drawstring_aspect(pos + eX * score_size * i, ftos(tm.(teamscores[ts_primary])), eX * score_size + eY * fontsize_y, GetTeamRGB(tm.team) * 0.8, panel_fg_alpha, DRAWFLAG_NORMAL);
++i;
}
first_pl = 1;
- pos_y += height;
+ pos_y += fontsize_y;
+ tm = teams.sort_next;
}
i = first_pl;
- for (pl = players.sort_next; pl && i<entries; pl = pl.sort_next, ++i)
+
+ do
+ for (pl = players.sort_next; pl && i<entries; pl = pl.sort_next)
{
- if (pl.team == COLOR_SPECTATOR)
+ if ((team_count && pl.team != tm.team) || pl.team == COLOR_SPECTATOR)
continue;
if (i == entries-1 && !me_printed && pl != me)
if (i == first_pl)
rgb = '0 1 0'; //first: green
me_printed = 1;
- drawfill(pos - eY * (height * (1 - 0.9) / 2), eX * mySize_x + eY * height, rgb, highlight_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
+ drawfill(pos, eX * mySize_x + eY * fontsize_y, rgb, highlight_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
}
if (team_count)
score_color = GetTeamRGB(pl.team) * 0.8;
s = textShortenToWidth(GetPlayerName(pl.sv_entnum), name_size, fontsize, stringwidth_colors);
drawcolorcodedstring(pos + eX * (name_size - stringwidth(s, TRUE, fontsize)), s, fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
drawstring(pos + eX * (name_size + spacing_size), ftos(pl.(scores[ps_primary])), fontsize, score_color, panel_fg_alpha, DRAWFLAG_NORMAL);
- pos_y += height;
+ pos_y += fontsize_y;
+ ++i;
}
+ while (i<entries && team_count && (tm = tm.sort_next) && (tm.team != COLOR_SPECTATOR || (tm = tm.sort_next)));
}
void HUD_Score(void)
fontsize = '0.20 0.20 0' * mySize_y;
float a;
- if(spectatee_status != 0)
- a = 1;
- else
- a = panel_fg_alpha;
+ a = panel_fg_alpha;
string s;
if(!autocvar__hud_configure)
{
if(spectatee_status && !intermission)
{
+ a = 1;
if(spectatee_status == -1)
s = _("^1Observing");
else
hud_fade_alpha = (1 - scoreboard_fade_alpha);
if(intermission == 2) // no hud during mapvote
+ {
+ if (autocvar__hud_configure) //force exit from hud config
+ {
+ if (menu_enabled)
+ {
+ menu_enabled = 0;
+ localcmd("togglemenu\n");
+ }
+ cvar_set("_hud_configure", "0");
+ }
hud_fade_alpha = 0;
+ }
else if(autocvar__menu_alpha == 0 && scoreboard_fade_alpha == 0)
hud_fade_alpha = 1;
if(!autocvar_hud_shownames)
return;
+ if(self.the_entnum == player_localentnum && !autocvar_chase_active)
+ return;
+
if(self.sameteam || (!self.sameteam && autocvar_hud_shownames_enemies))
{
- InterpolateOrigin_Do();
+ self.origin = getplayerorigin(self.the_entnum-1);
+ self.origin_z += autocvar_hud_shownames_offset;
if(!self.sameteam)
{
- traceline(self.origin, view_origin, 1, self);
-
/* WIP, why does trace_ent != self not work as intended here?
if(autocvar_hud_shownames_enemies != 2) // player has to point at enemy if so
{
if(trace_ent != self)
return;
}*/
+
+ traceline(self.origin, view_origin, 1, self);
}
vector o, eo;
o_z = 0;
vector myPos, mySize;
- mySize = (eX * autocvar_hud_shownames_aspect + eY) * autocvar_hud_shownames_height;
+ mySize = (eX * autocvar_hud_shownames_aspect + eY) * autocvar_hud_shownames_fontsize;
myPos = o - '0.5 0 0' * mySize_x - '0 1 0' * mySize_y;
// size scaling
myPos_x += 0.5 * (mySize_x / resize - mySize_x);
myPos_y += (mySize_y / resize - mySize_y);
- vector iconpos, iconsize; // these determine icon position/size, if any
vector namepos; // this is where the origin of the string
- float namesize; // total area where we can draw the string
+ float namewidth;
- iconpos = myPos;
+ namepos = myPos;
+ namewidth = mySize_x;
if(autocvar_hud_shownames_status && teamplay)
{
if(self.sameteam)
{
- iconsize = eX * 2 * mySize_y + eY * mySize_y;
- // "ghost" backgrounds
- drawpic_aspect_skin(iconpos, "health", '1 1 0' * iconsize_y, '0 0 0', a * 0.5, DRAWFLAG_NORMAL);
- drawpic_aspect_skin(iconpos + '0.5 0 0' * iconsize_x, "armor", '1 1 0' * iconsize_y, '0 0 0', a * 0.5, DRAWFLAG_NORMAL);
-
if(self.healthvalue > 0)
{
- drawsetcliparea(0, myPos_y + iconsize_y - iconsize_y * min(1, self.healthvalue/autocvar_hud_panel_healtharmor_maxhealth), vid_conwidth, myPos_y + iconsize_y);
- drawpic_aspect_skin(iconpos, "health", '1 1 0' * iconsize_y, '1 1 1', a, DRAWFLAG_NORMAL);
- }
+ HUD_Panel_DrawProgressBar(namepos + '0 1 0' * autocvar_hud_shownames_fontsize * resize, eX * 0.5 * mySize_x + eY * resize * autocvar_hud_shownames_statusbar_height, "nametag_statusbar", self.healthvalue/autocvar_hud_panel_healtharmor_maxhealth, 0, 1, '1 0 0', a, DRAWFLAG_NORMAL);
- if(self.armorvalue > 0)
- {
- drawsetcliparea(0, myPos_y + iconsize_y - iconsize_y * min(1, self.armorvalue/autocvar_hud_panel_healtharmor_maxarmor), vid_conwidth, myPos_y + iconsize_y);
- drawpic_aspect_skin(iconpos + '0.5 0 0' * iconsize_x, "armor", '1 1 0' * iconsize_y, '1 1 1', a, DRAWFLAG_NORMAL);
+ if(self.armorvalue > 0)
+ HUD_Panel_DrawProgressBar(namepos + '0 1 0' * autocvar_hud_shownames_fontsize * resize + eX * 0.5 * mySize_x, eX * 0.5 * mySize_x + eY * resize * autocvar_hud_shownames_statusbar_height, "nametag_statusbar", self.armorvalue/autocvar_hud_panel_healtharmor_maxarmor, 0, 0, '0 1 0', a, DRAWFLAG_NORMAL);
}
- drawresetcliparea();
- }
- else if(autocvar_hud_shownames_status == 2)
- {
- iconsize = eX * 2 * mySize_y + eY * mySize_y;
- drawpic_aspect_skin(iconpos, "health_unknown", '1 1 0' * iconsize_y, '0 0 0', a, DRAWFLAG_NORMAL);
- drawpic_aspect_skin(iconpos + '0.5 0 0' * iconsize_x, "armor_unknown", '1 1 0' * iconsize_y, '0 0 0', a, DRAWFLAG_NORMAL);
}
}
- namepos = myPos + eX * 2 * iconsize_y + eY * 0.5 * resize * (autocvar_hud_shownames_height - autocvar_hud_shownames_fontsize);
- namesize = mySize_x - 2 * iconsize_y;
-
string s;
s = GetPlayerName(self.the_entnum-1);
if((autocvar_hud_shownames_decolorize == 1 && teamplay) || autocvar_hud_shownames_decolorize == 2)
s = playername(s, GetPlayerColor(self.the_entnum-1));
drawfontscale = '1 1 0' * resize;
- s = textShortenToWidth(s, namesize, '1 1 0' * autocvar_hud_shownames_fontsize, stringwidth_colors);
+ s = textShortenToWidth(s, namewidth, '1 1 0' * autocvar_hud_shownames_fontsize, stringwidth_colors);
float width;
width = stringwidth(s, TRUE, '1 1 0' * autocvar_hud_shownames_fontsize);
- if (width != namesize)
- namepos_x += (namesize - width) / 2;
+ if (width != namewidth)
+ namepos_x += (namewidth - width) / 2;
drawcolorcodedstring(namepos, s, '1 1 0' * autocvar_hud_shownames_fontsize, a, DRAWFLAG_NORMAL);
drawfontscale = '1 1 0';
}
}
else
self.frags = FRAGS_SPECTATOR;
+
+ if(self.shownames)
+ remove(self.shownames);
}
void FixPlayermodel()
PutObserverInServer ();
}
+ if(!self.shownames)
+ {
+ self.shownames = spawn();
+ self.shownames.owner = self;
+ self.shownames.think = shownames_think;
+ self.shownames.nextthink = time;
+ Net_LinkEntity(self.shownames, FALSE, 0, SendEntity_ShowNames);
+ }
+
//if(g_ctf)
// ctf_playerchanged();
}
CheatInitClient();
PlayerStats_AddPlayer(self);
-
- self.shownames = spawn();
- self.shownames.owner = self;
- self.shownames.think = shownames_think;
- self.shownames.nextthink = time;
- self.shownames.customizeentityforclient = shownames_customize;
- Net_LinkEntity(self.shownames, FALSE, 0, SendEntity_ShowNames);
}
/*
=============
*/
.entity chatbubbleentity;
-.entity teambubbleentity;
void ReadyCount();
void ClientDisconnect (void)
{
if (self.chatbubbleentity)
remove (self.chatbubbleentity);
- if (self.teambubbleentity)
- remove (self.teambubbleentity);
-
if (self.killindicator)
remove (self.killindicator);
}
-void TeamBubbleThink()
-{
- self.nextthink = time;
- if (!self.owner.modelindex || self.owner.teambubbleentity != self)
- {
- if(self.owner) // but why can that ever be world?
- self.owner.teambubbleentity = world;
- remove(self);
- return;
- }
-// setorigin(self, self.owner.origin + '0 0 15' + self.owner.maxs_z * '0 0 1'); // bandwidth hog. setattachment does this now
- if (self.owner.BUTTON_CHAT || self.owner.deadflag || self.owner.killindicator)
- self.model = "";
- else
- self.model = self.mdl;
-
-};
-
-float TeamBubble_customizeentityforclient()
-{
- return (self.owner != other && self.owner.team == other.team && other.killcount > -666);
-}
-
-void UpdateTeamBubble()
-{
- if (!self.modelindex || !teams_matter)
- return;
- // spawn a teambubble entity if needed
- if (!self.teambubbleentity && teams_matter)
- {
- self.teambubbleentity = spawn();
- self.teambubbleentity.owner = self;
- self.teambubbleentity.exteriormodeltoclient = self;
- self.teambubbleentity.think = TeamBubbleThink;
- self.teambubbleentity.nextthink = time;
- setmodel(self.teambubbleentity, "models/misc/teambubble.spr"); // precision set below
-// setorigin(self.teambubbleentity, self.origin + '0 0 15' + self.maxs_z * '0 0 1');
- setorigin(self.teambubbleentity, '0 0 15' + self.maxs_z * '0 0 1');
- setattachment(self.teambubbleentity, self, ""); // sticks to moving player better, also conserves bandwidth
- self.teambubbleentity.mdl = self.teambubbleentity.model;
- self.teambubbleentity.model = self.teambubbleentity.mdl;
- self.teambubbleentity.customizeentityforclient = TeamBubble_customizeentityforclient;
- self.teambubbleentity.effects = EF_LOWPRECISION;
- }
-}
-
// LordHavoc: this hack will be removed when proper _pants/_shirt layers are
// added to the model skins
/*void UpdateColorModHack()
if(self.classname == "player") {
CheckRules_Player();
UpdateChatBubble();
- UpdateTeamBubble();
if (self.impulse)
ImpulseCommands();
if (intermission_running)
}
}
-// sendflags use: 1 = origin, 2 = health (0 or 1 for dead/alive on enemies), 4 = armor, 0x80 = same team (includes health)
+// sendflags use: 1 = health (value is 0 or 1 for dead/alive on enemies), 2 = armor, 0x80 = same team (includes health)
float SendEntity_ShowNames(entity to, float sendflags)
{
float the_health;
WriteByte(MSG_ENTITY, sendflags);
if(sendflags & 1)
- {
- WriteShort(MSG_ENTITY, rint(self.origin_x));
- WriteShort(MSG_ENTITY, rint(self.origin_y));
- WriteShort(MSG_ENTITY, rint(self.origin_z));
- }
- if(sendflags & 2)
{
WriteByte(MSG_ENTITY, the_health);
}
- if(sendflags & 4)
+ if(sendflags & 2)
{
WriteByte(MSG_ENTITY, self.armorvalue);
}
return TRUE;
}
-const vector SHOWNAMES_ORIGIN_OFFSET = '0 0 48';
void shownames_think()
{
- if(self.origin - SHOWNAMES_ORIGIN_OFFSET != self.owner.origin)
+ self.origin = self.owner.origin + '0 0 1' * 48;
+ if(self.health != max(0, ceil(self.owner.health/10)))
{
- setorigin(self, self.owner.origin + SHOWNAMES_ORIGIN_OFFSET);
+ self.health = max(0, ceil(self.owner.health/10));
self.SendFlags |= 1;
}
- if(self.health != max(0, floor(self.owner.health)) || self.armorvalue != max(0, floor(self.owner.armorvalue)))
+ if(self.armorvalue != max(0, ceil(self.owner.armorvalue/10)))
{
- self.health = max(0, floor(self.owner.health));
- self.armorvalue = max(0, floor(self.owner.armorvalue));
+ self.armorvalue = max(0, ceil(self.owner.armorvalue/10));
self.SendFlags |= 2;
}
- if(self.armorvalue != max(0, floor(self.owner.armorvalue)))
- {
- self.armorvalue = max(0, floor(self.owner.armorvalue));
- self.SendFlags |= 4;
- }
self.nextthink = time;
}
-float shownames_customize()
-{
- if(self.owner.classname == "player") // only send players, no spectators!
- if(self.owner != other) // no need to spam own coordinates
- if(vlen(other.origin - self.origin) < autocvar_sv_shownames_cull_distance) // distance cull
- if(self.owner.team == other.team || (self.owner.team != other.team && checkpvs(self.origin, other)))
- return TRUE;
-
- return FALSE;
-}
-
.float muted; // to be used by prvm_edictset server playernumber muted 1
float Say(entity source, float teamsay, entity privatesay, string msgin, float floodcontrol)
// message "": do not say, just test flood control
self.captime = time;
- FOR_EACH_PLAYER(head)
+ FOR_EACH_REALCLIENT(head)
set_dom_state(head);
};
entity o;
o = self.owner;
WriteByte(MSG_ENTITY, ENT_CLIENT_ENTCS);
- WriteByte(MSG_ENTITY, num_for_edict(o));
- WriteShort(MSG_ENTITY, o.origin_x);
- WriteShort(MSG_ENTITY, o.origin_y);
- WriteShort(MSG_ENTITY, o.origin_z);
- WriteByte(MSG_ENTITY, o.angles_y * 256.0 / 360);
+ WriteByte(MSG_ENTITY, sf);
+ if(sf & 1)
+ WriteByte(MSG_ENTITY, num_for_edict(o));
+ if(sf & 2)
+ {
+ WriteShort(MSG_ENTITY, o.origin_x);
+ WriteShort(MSG_ENTITY, o.origin_y);
+ WriteShort(MSG_ENTITY, o.origin_z);
+ }
+ if(sf & 4)
+ WriteByte(MSG_ENTITY, o.angles_y * 256.0 / 360);
return TRUE;
};
entity o;
o = self.owner;
- if(o.origin != self.origin || o.angles != self.angles)
+ if(o.origin != self.origin)
{
setorigin(self, o.origin);
+ self.SendFlags |= 2;
+ }
+ if(o.angles_y != self.angles_y)
+ {
self.angles = o.angles;
- self.SendFlags |= 1;
+ self.SendFlags |= 4;
}
};
{
// gamemode related things
precache_model ("models/misc/chatbubble.spr");
- precache_model ("models/misc/teambubble.spr");
if (g_runematch)
{
precache_model ("models/runematch/curse.mdl");