seta hud_panel_notify_time 10 "time that a new entry stays until it fades out"
seta hud_panel_notify_fadetime 3 "fade out time"
+seta hud_panel_modicons_dom_layout 1 "3 possible layouts: 0) only icons; 1) icons and percentage of average pps (points per second); 2) icons and average pps"
+
seta hud_panel_timer_increment 0 "show elapsed time instead of remaining time"
seta hud_panel_radar_scale 4096 "distance you can see on the team radar"
string race_status_name;
float race_myrank;
+// DOM
+float dom_total_pps;
+float dom_pps_red;
+float dom_pps_blue;
+float dom_pps_yellow;
+float dom_pps_pink;
+
// Nexball
float nb_pb_period;
}
}
+void Net_ReadDom()
+{
+ if (dom_total_pps == 0)
+ dom_total_pps = ReadShort() / 100.0;
+ dom_pps_red = ReadShort() / 100.0;
+ dom_pps_blue = ReadShort() / 100.0;
+ //if dom_pps_yellow/dom_pps_pink was negative the first time we read it,
+ //it means the relative team doesn't exist and we don't have to read its value anymore
+ if (dom_pps_yellow >= 0)
+ dom_pps_yellow = ReadShort() / 100.0;
+ if (dom_pps_pink >= 0)
+ dom_pps_pink = ReadShort() / 100.0;
+}
+
void Net_ReadSpawn()
{
zoomin_effect = 1;
Net_ReadRace();
bHandled = true;
break;
+ case TE_CSQC_DOM:
+ Net_ReadDom();
+ bHandled = true;
+ break;
case TE_CSQC_SPAWN:
Net_ReadSpawn();
bHandled = true;
drawfont = hud_font;
}
+void DrawDomItem(vector myPos, vector mySize, float aspect_ratio, float layout, float i)
+{
+ float dom_pps, dom_pps_ratio;
+ string pic;
+ vector color;
+ switch(i)
+ {
+ case 0:
+ dom_pps = dom_pps_red;
+ pic = "dom_icon_red";
+ color = '1 0 0';
+ break;
+ case 1:
+ dom_pps = dom_pps_blue;
+ pic = "dom_icon_blue";
+ color = '0 0 1';
+ break;
+ case 2:
+ dom_pps = dom_pps_yellow;
+ pic = "dom_icon_yellow";
+ color = '1 1 0';
+ break;
+ case 3:
+ dom_pps = dom_pps_pink;
+ pic = "dom_icon_pink";
+ color = '1 0 1';
+ }
+ dom_pps_ratio = dom_pps / dom_total_pps;
+
+ if(mySize_x/mySize_y > aspect_ratio)
+ {
+ i = aspect_ratio * mySize_y;
+ myPos_x = myPos_x + (mySize_x - i) / 2;
+ mySize_x = i;
+ }
+ else
+ {
+ i = 1/aspect_ratio * mySize_x;
+ myPos_y = myPos_y + (mySize_y - i) / 2;
+ mySize_y = i;
+ }
+
+ if (layout) // show text too
+ {
+ //draw the text
+ color *= 0.5 + dom_pps_ratio * (1 - 0.5); // half saturated color at min, full saturated at max
+ if (layout == 2) // average pps
+ drawstring_aspect(myPos + eX * mySize_y, ftos_decimals(dom_pps, 2), eX * (2/3) * mySize_x + eY * mySize_y, color, panel_fg_alpha, DRAWFLAG_NORMAL);
+ else // percentage of average pps
+ drawstring_aspect(myPos + eX * mySize_y, strcat( ftos(floor(dom_pps_ratio*100 + 0.5)), "%" ), eX * (2/3) * mySize_x + eY * mySize_y, color, panel_fg_alpha, DRAWFLAG_NORMAL);
+ }
+
+ //draw the icon
+ drawpic_aspect_skin(myPos, pic, '1 1 0' * mySize_y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+ if (dom_pps > 0)
+ {
+ drawsetcliparea(myPos_x, myPos_y + mySize_y * (1 - dom_pps_ratio), mySize_y, mySize_y * dom_pps_ratio);
+ drawpic_aspect_skin(myPos, strcat(pic, "-highlighted"), '1 1 0' * mySize_y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+ drawresetcliparea();
+ }
+}
+
+void HUD_Mod_Dom(vector myPos, vector mySize)
+{
+ mod_active = 1; // required in each mod function that always shows something
+ entity tm;
+ float teams_count;
+ for(tm = teams.sort_next; tm; tm = tm.sort_next)
+ if(tm.team != COLOR_SPECTATOR)
+ ++teams_count;
+
+ float layout = cvar("hud_panel_modicons_dom_layout");
+ float rows, columns, aspect_ratio;
+ rows = mySize_y/mySize_x;
+ aspect_ratio = (layout) ? 3 : 1;
+ rows = bound(1, floor((sqrt((4 * aspect_ratio * teams_count + rows) * rows) + rows + 0.5) / 2), teams_count);
+ columns = ceil(teams_count/rows);
+
+ drawfont = hud_bigfont;
+ int i;
+ float row, column;
+ for(i=0; i<teams_count; ++i)
+ {
+ vector pos, size;
+ pos = myPos + eX * column * mySize_x*(1/columns) + eY * row * mySize_y*(1/rows);
+ size = eX * mySize_x*(1/columns) + eY * mySize_y*(1/rows);
+
+ DrawDomItem(pos, size, aspect_ratio, layout, i);
+
+ ++row;
+ if(row >= rows)
+ {
+ row = 0;
+ ++column;
+ }
+ }
+ drawfont = hud_font;
+}
+
float mod_prev; // previous state of mod_active to check for a change
float mod_alpha;
float mod_change; // "time" when mod_active changed
if(!autocvar__hud_configure)
{
if(!autocvar_hud_panel_modicons) return;
- if (gametype != GAME_CTF && gametype != GAME_KEYHUNT && gametype != GAME_NEXBALL && gametype != GAME_CTS && gametype != GAME_RACE && gametype != GAME_CA && gametype != GAME_FREEZETAG && gametype != GAME_KEEPAWAY) return;
+ if (gametype != GAME_CTF && gametype != GAME_KEYHUNT && gametype != GAME_NEXBALL && gametype != GAME_CTS && gametype != GAME_RACE && gametype != GAME_CA && gametype != GAME_FREEZETAG && gametype != GAME_KEEPAWAY && gametype != GAME_DOMINATION) return;
}
else
hud_configure_active_panel = HUD_PANEL_MODICONS;
HUD_Mod_Race(pos, mySize);
else if(gametype == GAME_CA || gametype == GAME_FREEZETAG)
HUD_Mod_CA(pos, mySize);
+ else if(gametype == GAME_DOMINATION)
+ HUD_Mod_Dom(pos, mySize);
else if(gametype == GAME_KEEPAWAY)
HUD_Mod_Keepaway(pos, mySize);
}
const float TE_CSQC_CAMPINGRIFLE_SCOPE = 115;
const float TE_CSQC_NEX_SCOPE = 116;
const float TE_CSQC_CR_MAXBULLETS = 117;
+const float TE_CSQC_DOM = 119;
const float RACE_NET_CHECKPOINT_HIT_QUALIFYING = 0; // byte checkpoint, short time, short recordtime, string recordholder
const float RACE_NET_CHECKPOINT_CLEAR = 1;
string ColoredTeamName(float t);
void DecodeLevelParms (void);
//void dom_player_join_team(entity pl);
+void send_CSQC_dom_all();
void ClientConnect (void)
{
float t;
else if(autocvar_sv_teamnagger && !(autocvar_bot_vs_human && (c3==-1 && c4==-1)) && !g_ca) // teamnagger is currently bad for ca
send_CSQC_teamnagger();
+ if (g_domination)
+ send_CSQC_dom_all();
send_CSQC_cr_maxbullets(self);
CheatInitClient();
.entity sprite;
.float captime;
+// pps: points per second
+float dom_total_pps;
+float dom_pps_red;
+float dom_pps_blue;
+float dom_pps_yellow;
+float dom_pps_pink;
+void send_CSQC_dom_state()
+{
+ WriteByte(MSG_ALL, SVC_TEMPENTITY);
+ WriteByte(MSG_ALL, TE_CSQC_DOM);
+ WriteShort(MSG_ALL, dom_pps_red * 100.0);
+ WriteShort(MSG_ALL, dom_pps_blue * 100.0);
+ if (c3 >= 0) WriteShort(MSG_ALL, dom_pps_yellow * 100.0);
+ if (c4 >= 0) WriteShort(MSG_ALL, dom_pps_pink * 100.0);
+}
+//Must be called ONLY when a client connects to send total pps and state
+//If yellow/pink team doesn't exist sends a negative dom_pps_yellow/dom_pps_pink
+//to let know the client to not read these values anymore
+void send_CSQC_dom_all()
+{
+ WriteByte(MSG_ALL, SVC_TEMPENTITY);
+ WriteByte(MSG_ALL, TE_CSQC_DOM);
+ WriteShort(MSG_ALL, dom_total_pps * 100.0);
+ WriteShort(MSG_ALL, dom_pps_red * 100.0);
+ WriteShort(MSG_ALL, dom_pps_blue * 100.0);
+ WriteShort(MSG_ALL, dom_pps_yellow * 100.0);
+ WriteShort(MSG_ALL, dom_pps_pink * 100.0);
+}
+
void() dom_controlpoint_setup;
void LogDom(string mode, float team_before, entity actor)
self.delay = old_delay;
self.team = old_team;
+ switch(self.team)
+ {
+ // "fix" pps when slightly under 0 because of approximation errors
+ case COLOR_TEAM1:
+ dom_pps_red -= (points/wait_time);
+ if (dom_pps_red < 0) dom_pps_red = 0;
+ break;
+ case COLOR_TEAM2:
+ dom_pps_blue -= (points/wait_time);
+ if (dom_pps_blue < 0) dom_pps_blue = 0;
+ break;
+ case COLOR_TEAM3:
+ dom_pps_yellow -= (points/wait_time);
+ if (dom_pps_yellow < 0) dom_pps_yellow = 0;
+ break;
+ case COLOR_TEAM4:
+ dom_pps_pink -= (points/wait_time);
+ if (dom_pps_pink < 0) dom_pps_pink = 0;
+ }
+
switch(self.goalentity.team)
{
+ // "fix" pps when slightly over dom_total_pps because of approximation errors
case COLOR_TEAM1:
+ dom_pps_red += (points/wait_time);
+ if (dom_pps_red > dom_total_pps) dom_pps_red = dom_total_pps;
WaypointSprite_UpdateSprites(self.sprite, "dom-red", "", "");
break;
case COLOR_TEAM2:
+ dom_pps_blue += (points/wait_time);
+ if (dom_pps_blue > dom_total_pps) dom_pps_blue = dom_total_pps;
WaypointSprite_UpdateSprites(self.sprite, "dom-blue", "", "");
break;
case COLOR_TEAM3:
+ dom_pps_yellow += (points/wait_time);
+ if (dom_pps_yellow > dom_total_pps) dom_pps_yellow = dom_total_pps;
WaypointSprite_UpdateSprites(self.sprite, "dom-yellow", "", "");
break;
case COLOR_TEAM4:
+ dom_pps_pink += (points/wait_time);
+ if (dom_pps_pink > dom_total_pps) dom_pps_pink = dom_total_pps;
WaypointSprite_UpdateSprites(self.sprite, "dom-pink", "", "");
- break;
}
+
+ send_CSQC_dom_state();
+
WaypointSprite_UpdateTeamRadar(self.sprite, RADARICON_DOMPOINT, colormapPaletteColor(self.goalentity.team - 1, 0));
WaypointSprite_Ping(self.sprite);
if(!self.message)
self.message = " has captured a control point";
- if(!self.DOMPOINTFRAGS)
+ if(self.DOMPOINTFRAGS <= 0)
self.DOMPOINTFRAGS = 1;
- if(!self.wait)
+ if(self.wait <= 0)
self.wait = 5;
+ float points, waittime;
+ if (g_domination_point_rate)
+ points = g_domination_point_rate;
+ else
+ points = self.frags;
+ if (g_domination_point_amt)
+ waittime = g_domination_point_amt;
+ else
+ waittime = self.wait;
+
+ dom_total_pps += points/waittime;
+
if(!self.t_width)
self.t_width = 0.02; // frame animation rate
if(!self.t_length)
}
}
}
+ if (c3 == -1) dom_pps_yellow = -1;
+ if (c4 == -1) dom_pps_pink = -1;
ScoreRules_dom();
};
precache_model("models/domination/dom_unclaimed.md3");
precache_sound("domination/claim.wav");
InitializeEntity(world, dom_delayedinit, INITPRIO_GAMETYPE);
+
+ g_domination_point_rate = cvar("g_domination_point_rate");
+ g_domination_point_amt = cvar("g_domination_point_amt");
};