seta cl_reticle_item_nex 1 "draw aiming reticle for the nex weapon's zoom, 0 disables and values between 0 and 1 change alpha"
seta cl_reticle_item_normal 1 "draw reticle when zooming with the zoom button, 0 disables and values between 0 and 1 change alpha"
fov 90
-seta cl_velocityzoom 0 "velocity based zooming of fov, negative values zoom out"
+seta cl_velocityzoom 0 "velocity based zooming of fov"
+seta cl_velocityzoom_factor 0 "factor of fov zooming (negative values zoom out)"
seta cl_velocityzoom_type 3 "how to factor in speed, 1 = all velocity in all directions, 2 = velocity only in forward direction (can be negative), 3 = velocity only in forward direction (limited to forward only)"
seta cl_velocityzoom_speed 1000 "target speed for fov factoring"
seta cl_velocityzoom_time 0.2 "time value for averaging speed values"
set g_spawnshieldtime 1 "number of seconds you are invincible after you spawned, this shield is lost after you fire"
set g_antilag 2 "AntiLag (0 = no AntiLag, 1 = verified client side hit scan, 2 = server side hit scan in the past, 3 = unverified client side hit scan)"
set g_antilag_nudge 0 "don't touch"
- set g_antilag_bullets 1 "Bullets AntiLag (0 = no AntiLag, 1 = server side hit scan in the past) - DO NOT TOUCH (severely changes weapon balance)"
set g_shootfromclient 2 "let client decide if it has the gun left or right; if set to 2, center handedness is allowed; see also cl_gunalign"
set g_shootfromeye 0 "shots are fired from your eye/crosshair; visual gun position can still be influenced by cl_gunalign 1 and 2"
set g_shootfromcenter 0 "weapon gets moved to the center, shots still come from the barrel of your weapon; visual gun position can still be influenced by cl_gunalign 1 and 2"
seta menu_slist_showempty 1 "show servers even if they are no empty and have no opponents to play against"
seta menu_slist_modfilter "" // set to either: !modname or modname. modname of = means "same as we are running now".
+// other serverlist cvars
+seta menu_slist_categories 0
+seta menu_slist_categories_onlyifmultiple 1
+seta menu_slist_purethreshold 0
+seta menu_slist_modimpurity 0
+seta menu_slist_recommendations 3
+seta menu_slist_recommendations_maxping 150
+seta menu_slist_recommendations_minfreeslots 1
+seta menu_slist_recommendations_minhumans 0
+seta menu_slist_recommendations_purethreshold -1
+
+// serverlist category override cvars
+seta menu_slist_categories_CAT_FAVORITED_override ""
+seta menu_slist_categories_CAT_RECOMMENDED_override ""
+seta menu_slist_categories_CAT_NORMAL_override ""
+seta menu_slist_categories_CAT_SERVERS_override "CAT_NORMAL"
+seta menu_slist_categories_CAT_XPM_override "CAT_NORMAL"
+seta menu_slist_categories_CAT_MODIFIED_override ""
+seta menu_slist_categories_CAT_OVERKILL_override ""
+seta menu_slist_categories_CAT_MINSTAGIB_override ""
+seta menu_slist_categories_CAT_DEFRAG_override ""
+
seta menu_weaponarena ""
seta menu_maxplayers 16 "maxplayers value when the menu starts a game"
r_cullentities_trace 0
// less "lagging" of other players, but also less PL tolerant... let's try this
- sv_clmovement_inputtimeout 0.04 // more than 1, less than 2 server frames
+ sv_clmovement_inputtimeout 0.066 // slightly less than 2 frames, so only one frame can be compensated
// exact gloss looks better, e.g. on g-23
r_shadow_glossexact 1
else if(autocvar_cl_spawnzoom && zoomin_effect)
{
float spawnzoomfactor = bound(1, autocvar_cl_spawnzoom_factor, 16);
-
- current_viewzoom += (autocvar_cl_spawnzoom_speed * (spawnzoomfactor - current_viewzoom) * drawframetime);
+
+ current_viewzoom += (autocvar_cl_spawnzoom_speed * (spawnzoomfactor - current_viewzoom) * drawframetime);
current_viewzoom = bound(1 / spawnzoomfactor, current_viewzoom, 1);
if(current_viewzoom == 1) { zoomin_effect = 0; }
}
setsensitivityscale(pow(current_viewzoom, 1 - zoomsensitivity));
else
setsensitivityscale(1);
-
+
makevectors(view_angles);
- if(autocvar_cl_velocityzoom && autocvar_cl_velocityzoom_type) // _type = 0 disables velocity zoom too
+ if(autocvar_cl_velocityzoom && autocvar_cl_velocityzoom_type && autocvar_cl_velocityzoom_factor) // _type = 0 disables velocity zoom too
{
if(intermission) { curspeed = 0; }
else
case 1: default: curspeed = vlen(v); break;
}
}
-
+
velocityzoom = bound(0, drawframetime / max(0.000000001, autocvar_cl_velocityzoom_time), 1); // speed at which the zoom adapts to player velocity
avgspeed = avgspeed * (1 - velocityzoom) + (curspeed / autocvar_cl_velocityzoom_speed) * velocityzoom;
- velocityzoom = exp(float2range11(avgspeed * -autocvar_cl_velocityzoom / 1) * 1);
+ velocityzoom = exp(float2range11(avgspeed * -autocvar_cl_velocityzoom_factor / 1) * 1);
-
+
//print(ftos(avgspeed), " avgspeed, ", ftos(curspeed), " curspeed, ", ftos(velocityzoom), " return\n"); // for debugging
}
else
drawstring('0 0 0', "", '1 1 0', '1 1 1', 0, 0);
if(autocvar_r_fakelight >= 2 || autocvar_r_fullbright)
- if not(serverflags & SERVERFLAG_ALLOW_FULLBRIGHT)
+ if (!(serverflags & SERVERFLAG_ALLOW_FULLBRIGHT))
{
// apply night vision effect
vector tc_00, tc_01, tc_10, tc_11;
R_PolygonVertex(autocvar_vid_conheight * '0 1 0', tc_01, rgb, a);
R_EndPolygon();
}
-
+
// Draw the aiming reticle for weapons that use it
// reticle_type is changed to the item we are zooming / aiming with, to decide which reticle to use
// It must be a persisted float for fading out to work properly (you let go of the zoom button for
reticle_type = 1; // normal zoom
else if((activeweapon == WEP_NEX) && button_attack2)
reticle_type = 2; // nex zoom
-
+
if(reticle_type && autocvar_cl_reticle)
{
if(autocvar_cl_reticle_stretch)
old_bluralpha = 0;
}
- // edge detection postprocess handling done second (used by hud_powerup)
+ // edge detection postprocess handling done second (used by hud_powerup)
float sharpen_intensity = 0, strength_finished = getstatf(STAT_STRENGTH_FINISHED), invincible_finished = getstatf(STAT_INVINCIBLE_FINISHED);
if (strength_finished - time > 0) { sharpen_intensity += (strength_finished - time); }
if (invincible_finished - time > 0) { sharpen_intensity += (invincible_finished - time); }
-
+
sharpen_intensity = bound(0, ((getstati(STAT_HEALTH) > 0) ? sharpen_intensity : 0), 5); // Check to see if player is alive (if not, set 0) - also bound to fade out starting at 5 seconds.
-
+
if(autocvar_hud_powerup && sharpen_intensity > 0)
{
if(sharpen_intensity != old_sharpen_intensity) // reduce cvar_set spam as much as possible
{
if(time - hit_time < MAX_TIME_DIFF) // don't play the sound if it's too old.
sound(world, CH_INFO, "misc/hit.wav", VOL_BASE, ATTEN_NONE);
-
+
nextsound_hit_time = time + autocvar_cl_hitsound_antispam_time;
}
typehit_time = getstatf(STAT_TYPEHIT_TIME);
- if(typehit_time > nextsound_typehit_time)
+ if(typehit_time > nextsound_typehit_time)
{
if(time - typehit_time < MAX_TIME_DIFF) // don't play the sound if it's too old.
sound(world, CH_INFO, "misc/typehit.wav", VOL_BASE, ATTEN_NONE);
-
+
nextsound_typehit_time = time + autocvar_cl_hitsound_antispam_time;
}
CSQC_common_hud();
// crosshair goes VERY LAST
- if(!scoreboard_active && !camera_active && intermission != 2 && spectatee_status != -1 && hud == HUD_NORMAL)
+ if(!scoreboard_active && !camera_active && intermission != 2 && spectatee_status != -1 && hud == HUD_NORMAL)
{
- if not(autocvar_crosshair_enabled) // main toggle for crosshair rendering
+ if (!autocvar_crosshair_enabled) // main toggle for crosshair rendering
return;
-
+
string wcross_style;
float wcross_alpha, wcross_resolution;
wcross_style = autocvar_crosshair;
// wcross_origin = '0.5 0 0' * vid_conwidth + '0 0.5 0' * vid_conheight;
wcross_origin = project_3d_to_2d(view_origin + MAX_SHOT_DISTANCE * view_forward);
wcross_origin_z = 0;
- if(autocvar_crosshair_hittest)
+
+ if(
+ autocvar_crosshair_hittest
+ &&
+ (
+ autocvar_crosshair_hittest_blur
+ ||
+ autocvar_crosshair_hittest_scale
+ ||
+ autocvar_crosshair_hittest_showimpact
+ )
+ )
{
vector wcross_oldorigin;
wcross_oldorigin = wcross_origin;
if(!autocvar_crosshair_hittest_showimpact)
wcross_origin = wcross_oldorigin;
}
- else
- shottype = SHOTTYPE_HITWORLD;
+ else { shottype = SHOTTYPE_HITWORLD; }
vector wcross_color = '0 0 0', wcross_size = '0 0 0';
string wcross_wep = "", wcross_name;
if(autocvar_crosshair_pickup)
{
float stat_pickup_time = getstatf(STAT_LAST_PICKUP);
-
+
if(pickup_crosshair_time < stat_pickup_time)
{
if(time - stat_pickup_time < MAX_TIME_DIFF) // don't trigger the animation if it's too old
pickup_crosshair_size = 1;
-
+
pickup_crosshair_time = stat_pickup_time;
}
if(autocvar_crosshair_hitindication)
{
vector hitindication_color = ((autocvar_crosshair_color_special == 1) ? stov(autocvar_crosshair_hitindication_per_weapon_color) : stov(autocvar_crosshair_hitindication_color));
-
+
if(hitindication_crosshair_time < hit_time)
{
if(time - hit_time < MAX_TIME_DIFF) // don't trigger the animation if it's too old
hitindication_crosshair_size = 1;
-
+
hitindication_crosshair_time = hit_time;
}
}
if(shottype == SHOTTYPE_HITENEMY)
- wcross_scale *= autocvar_crosshair_hittest; // is not queried if hittest is 0
+ wcross_scale *= autocvar_crosshair_hittest_scale; // is not queried if hittest is 0
if(shottype == SHOTTYPE_HITTEAM)
- wcross_scale /= autocvar_crosshair_hittest; // is not queried if hittest is 0
+ wcross_scale /= autocvar_crosshair_hittest_scale; // is not queried if hittest is 0
f = fabs(autocvar_crosshair_effect_time);
if(wcross_scale != wcross_scale_goal_prev || wcross_alpha != wcross_alpha_goal_prev || wcross_color != wcross_color_goal_prev)
// handle the values
if (autocvar_crosshair_ring && activeweapon == WEP_NEX && nex_charge && autocvar_crosshair_ring_nex) // ring around crosshair representing velocity-dependent damage for the nex
{
- if (nex_chargepool || use_nex_chargepool) {
- use_nex_chargepool = 1;
+ if (nex_chargepool || use_nex_chargepool) {
+ use_nex_chargepool = 1;
ring_inner_value = nex_chargepool;
- } else {
+ } else {
nex_charge_movingavg = (1 - autocvar_crosshair_ring_nex_currentcharge_movingavg_rate) * nex_charge_movingavg + autocvar_crosshair_ring_nex_currentcharge_movingavg_rate * nex_charge;
- ring_inner_value = bound(0, autocvar_crosshair_ring_nex_currentcharge_scale * (nex_charge - nex_charge_movingavg), 1);
+ ring_inner_value = bound(0, autocvar_crosshair_ring_nex_currentcharge_scale * (nex_charge - nex_charge_movingavg), 1);
}
ring_inner_alpha = autocvar_crosshair_ring_nex_inner_alpha;
ring_rgb = wcross_color;
ring_image = "gfx/crosshair_ring_nexgun.tga";
}
- else if (autocvar_crosshair_ring && activeweapon == WEP_MINE_LAYER && minelayer_maxmines && autocvar_crosshair_ring_minelayer)
+ else if (autocvar_crosshair_ring && activeweapon == WEP_MINE_LAYER && minelayer_maxmines && autocvar_crosshair_ring_minelayer)
{
ring_value = bound(0, getstati(STAT_LAYED_MINES) / minelayer_maxmines, 1); // if you later need to use the count of bullets in another place, then add a float for it. For now, no need to.
ring_alpha = autocvar_crosshair_ring_minelayer_alpha;
ring_image = "gfx/crosshair_ring.tga";
}
- if(autocvar_crosshair_ring_reload && weapon_clipsize) // forces there to be only an ammo ring
+ if(autocvar_crosshair_ring_reload && weapon_clipsize) // forces there to be only an ammo ring
{
ring_value = bound(0, weapon_clipload / weapon_clipsize, 1);
ring_scale = autocvar_crosshair_ring_reload_size;
if(autocvar_crosshair_effect_time > 0)
{
f = (time - wcross_name_changestarttime) / autocvar_crosshair_effect_time;
- if not(f < 1)
+ if (!(f < 1))
{
wcross_ring_prev = ((ring_image) ? TRUE : FALSE);
}
-
+
if(wcross_ring_prev)
{
if(f < 1)
{
vector wcross_color_old;
wcross_color_old = wcross_color;
-
+
if((autocvar_crosshair_dot_color_custom) && (autocvar_crosshair_dot_color != "0"))
wcross_color = stov(autocvar_crosshair_dot_color);
-
+
CROSSHAIR_DRAW(wcross_resolution * autocvar_crosshair_dot_size, "gfx/crosshairdot.tga", f * autocvar_crosshair_dot_alpha);
// FIXME why don't we use wcross_alpha here?cl_notice_run();
wcross_color = wcross_color_old;
if(autocvar__hud_configure)
HUD_Panel_Mouse();
-
+
if(hud && !intermission)
- {
+ {
if(hud == HUD_SPIDERBOT)
CSQC_SPIDER_HUD();
else if(hud == HUD_WAKIZASHI)
else if(hud == HUD_BUMBLEBEE_GUN)
CSQC_BUMBLE_GUN_HUD();
}
-
+
cl_notice_run();
-
+
// let's reset the view back to normal for the end
setproperty(VF_MIN, '0 0 0');
setproperty(VF_SIZE, '1 0 0' * w + '0 1 0' * h);
string fstrunzone(string s)
{
string sc;
- if not(s)
+ if (!s)
return s;
sc = strcat(s, "");
strunzone(s);
fclose(fh);
}
+string format_time(float seconds)
+{
+ float days, hours, minutes;
+ seconds = floor(seconds + 0.5);
+ days = floor(seconds / 864000);
+ seconds -= days * 864000;
+ hours = floor(seconds / 36000);
+ seconds -= hours * 36000;
+ minutes = floor(seconds / 600);
+ seconds -= minutes * 600;
+ if (days > 0)
+ return sprintf(_("%d days, %02d:%02d:%02d"), days, hours, minutes, seconds);
+ else
+ return sprintf(_("%02d:%02d:%02d"), hours, minutes, seconds);
+}
+
string mmsss(float tenths)
{
float minutes;
created_saved_value = 0;
- if not(tmp_cvar || tmp_value)
+ if (!(tmp_cvar || tmp_value))
{
dprint("Error: Invalid usage of cvar_settemp(string, string); !\n");
return 0;
if(strstrofs(strcat(",", pattern, ","), subpattern2, 0) < 0)
if(strstrofs(strcat(",", pattern, ","), subpattern3, 0) < 0)
{
- if not(subpattern4)
+ if (!subpattern4)
return 0;
if(strstrofs(strcat(",", pattern, ","), subpattern4, 0) < 0)
return 0;
error("fteqcc bug introduced with revision 3178 detected. Please upgrade fteqcc to a later revision, downgrade fteqcc to revision 3177, or pester Spike until he fixes it. You can set _allow_unacceptable_compiler_bugs 1 to skip this check, but expect stuff to be horribly broken then.");
string s = "";
- if not(s)
+ if (!s)
error("The empty string counts as false. We do not want that!");
}
}
get_model_parameters_fixbone = 0;
- if not(m)
+ if (!m)
return 1;
if(substring(m, -9, 5) == "_lod1" || substring(m, -9, 5) == "_lod2")
Therefore: there is an inflection point iff:
e outside (3 - s)/2 .. 3 - s*2
-
+
in other words, if (s,e) in triangle (1,1)(0,3)(0,1.5) or in triangle (1,1)(3,0)(1.5,0)
*/
}
switch(num)
{
case 10: return ANNCE_NUM_GAMESTART_10;
- case 9: return ANNCE_NUM_GAMESTART_9;
- case 8: return ANNCE_NUM_GAMESTART_8;
- case 7: return ANNCE_NUM_GAMESTART_7;
- case 6: return ANNCE_NUM_GAMESTART_6;
- case 5: return ANNCE_NUM_GAMESTART_5;
- case 4: return ANNCE_NUM_GAMESTART_4;
- case 3: return ANNCE_NUM_GAMESTART_3;
- case 2: return ANNCE_NUM_GAMESTART_2;
- case 1: return ANNCE_NUM_GAMESTART_1;
+ case 9: return ANNCE_NUM_GAMESTART_9;
+ case 8: return ANNCE_NUM_GAMESTART_8;
+ case 7: return ANNCE_NUM_GAMESTART_7;
+ case 6: return ANNCE_NUM_GAMESTART_6;
+ case 5: return ANNCE_NUM_GAMESTART_5;
+ case 4: return ANNCE_NUM_GAMESTART_4;
+ case 3: return ANNCE_NUM_GAMESTART_3;
+ case 2: return ANNCE_NUM_GAMESTART_2;
+ case 1: return ANNCE_NUM_GAMESTART_1;
}
break;
}
switch(num)
{
case 10: return ANNCE_NUM_IDLE_10;
- case 9: return ANNCE_NUM_IDLE_9;
- case 8: return ANNCE_NUM_IDLE_8;
- case 7: return ANNCE_NUM_IDLE_7;
- case 6: return ANNCE_NUM_IDLE_6;
- case 5: return ANNCE_NUM_IDLE_5;
- case 4: return ANNCE_NUM_IDLE_4;
- case 3: return ANNCE_NUM_IDLE_3;
- case 2: return ANNCE_NUM_IDLE_2;
- case 1: return ANNCE_NUM_IDLE_1;
+ case 9: return ANNCE_NUM_IDLE_9;
+ case 8: return ANNCE_NUM_IDLE_8;
+ case 7: return ANNCE_NUM_IDLE_7;
+ case 6: return ANNCE_NUM_IDLE_6;
+ case 5: return ANNCE_NUM_IDLE_5;
+ case 4: return ANNCE_NUM_IDLE_4;
+ case 3: return ANNCE_NUM_IDLE_3;
+ case 2: return ANNCE_NUM_IDLE_2;
+ case 1: return ANNCE_NUM_IDLE_1;
}
break;
}
switch(num)
{
case 10: return ANNCE_NUM_KILL_10;
- case 9: return ANNCE_NUM_KILL_9;
- case 8: return ANNCE_NUM_KILL_8;
- case 7: return ANNCE_NUM_KILL_7;
- case 6: return ANNCE_NUM_KILL_6;
- case 5: return ANNCE_NUM_KILL_5;
- case 4: return ANNCE_NUM_KILL_4;
- case 3: return ANNCE_NUM_KILL_3;
- case 2: return ANNCE_NUM_KILL_2;
- case 1: return ANNCE_NUM_KILL_1;
+ case 9: return ANNCE_NUM_KILL_9;
+ case 8: return ANNCE_NUM_KILL_8;
+ case 7: return ANNCE_NUM_KILL_7;
+ case 6: return ANNCE_NUM_KILL_6;
+ case 5: return ANNCE_NUM_KILL_5;
+ case 4: return ANNCE_NUM_KILL_4;
+ case 3: return ANNCE_NUM_KILL_3;
+ case 2: return ANNCE_NUM_KILL_2;
+ case 1: return ANNCE_NUM_KILL_1;
}
break;
}
switch(num)
{
case 10: return ANNCE_NUM_RESPAWN_10;
- case 9: return ANNCE_NUM_RESPAWN_9;
- case 8: return ANNCE_NUM_RESPAWN_8;
- case 7: return ANNCE_NUM_RESPAWN_7;
- case 6: return ANNCE_NUM_RESPAWN_6;
- case 5: return ANNCE_NUM_RESPAWN_5;
- case 4: return ANNCE_NUM_RESPAWN_4;
- case 3: return ANNCE_NUM_RESPAWN_3;
- case 2: return ANNCE_NUM_RESPAWN_2;
- case 1: return ANNCE_NUM_RESPAWN_1;
+ case 9: return ANNCE_NUM_RESPAWN_9;
+ case 8: return ANNCE_NUM_RESPAWN_8;
+ case 7: return ANNCE_NUM_RESPAWN_7;
+ case 6: return ANNCE_NUM_RESPAWN_6;
+ case 5: return ANNCE_NUM_RESPAWN_5;
+ case 4: return ANNCE_NUM_RESPAWN_4;
+ case 3: return ANNCE_NUM_RESPAWN_3;
+ case 2: return ANNCE_NUM_RESPAWN_2;
+ case 1: return ANNCE_NUM_RESPAWN_1;
}
break;
}
switch(num)
{
case 10: return ANNCE_NUM_ROUNDSTART_10;
- case 9: return ANNCE_NUM_ROUNDSTART_9;
- case 8: return ANNCE_NUM_ROUNDSTART_8;
- case 7: return ANNCE_NUM_ROUNDSTART_7;
- case 6: return ANNCE_NUM_ROUNDSTART_6;
- case 5: return ANNCE_NUM_ROUNDSTART_5;
- case 4: return ANNCE_NUM_ROUNDSTART_4;
- case 3: return ANNCE_NUM_ROUNDSTART_3;
- case 2: return ANNCE_NUM_ROUNDSTART_2;
- case 1: return ANNCE_NUM_ROUNDSTART_1;
+ case 9: return ANNCE_NUM_ROUNDSTART_9;
+ case 8: return ANNCE_NUM_ROUNDSTART_8;
+ case 7: return ANNCE_NUM_ROUNDSTART_7;
+ case 6: return ANNCE_NUM_ROUNDSTART_6;
+ case 5: return ANNCE_NUM_ROUNDSTART_5;
+ case 4: return ANNCE_NUM_ROUNDSTART_4;
+ case 3: return ANNCE_NUM_ROUNDSTART_3;
+ case 2: return ANNCE_NUM_ROUNDSTART_2;
+ case 1: return ANNCE_NUM_ROUNDSTART_1;
}
break;
}
switch(num)
{
case 10: return ANNCE_NUM_10;
- case 9: return ANNCE_NUM_9;
- case 8: return ANNCE_NUM_8;
- case 7: return ANNCE_NUM_7;
- case 6: return ANNCE_NUM_6;
- case 5: return ANNCE_NUM_5;
- case 4: return ANNCE_NUM_4;
- case 3: return ANNCE_NUM_3;
- case 2: return ANNCE_NUM_2;
- case 1: return ANNCE_NUM_1;
+ case 9: return ANNCE_NUM_9;
+ case 8: return ANNCE_NUM_8;
+ case 7: return ANNCE_NUM_7;
+ case 6: return ANNCE_NUM_6;
+ case 5: return ANNCE_NUM_5;
+ case 4: return ANNCE_NUM_4;
+ case 3: return ANNCE_NUM_3;
+ case 2: return ANNCE_NUM_2;
+ case 1: return ANNCE_NUM_1;
}
break;
}
void(float width, float height) m_draw;
void(float mode) m_toggle;
void() m_shutdown;
+// optional: float(float) m_gethostcachecategory;
/////////////////////////////////////////////////////////
// sys constants
float drawcolorcodedstring(vector position, string text, vector scale, float alpha, float flag) = #467;
vector drawcolorcodedstring2(vector position, string text, vector scale, vector rgb, float alpha, float flag) = #467;
-
+
float drawpic(vector position, string pic, vector size, vector rgb, float alpha, float flag) = #456;
float drawfill(vector position, vector size, vector rgb, float alpha, float flag) = #457;
void sethostcachemaskstring(float mask, float fld, string str, float op) = #616;
void sethostcachemasknumber(float mask, float fld, float num, float op) = #617;
void resorthostcache(void) = #618;
-void sethostcachesort(float fld, float descending) = #619;
-void refreshhostcache(void) = #620;
+float SLSF_DESCENDING = 1;
+float SLSF_FAVORITES = 2;
+float SLSF_CATEGORIES = 4;
+void sethostcachesort(float fld, float slsf) = #619;
+void refreshhostcache(...) = #620; // optional boolean argument "clear_list"
float gethostcachenumber(float fld, float hostnr) = #621;
float gethostcacheindexforkey(string key) = #622;
void addwantedhostcachekey(string key) = #623;
for(i = 0; ; ++i)
{
s = getgamedirinfo(i, GETGAMEDIRINFO_NAME);
- if not(s)
+ if (!s)
break;
dprint(s, ": ", getgamedirinfo(i, GETGAMEDIRINFO_DESCRIPTION));
}
CALL_ACCUMULATED_FUNCTION(RegisterWeapons);
CALL_ACCUMULATED_FUNCTION(RegisterGametypes);
+ RegisterSLCategories();
+
float ddsload = cvar("r_texture_dds_load");
float texcomp = cvar("gl_texturecompression");
updateCompression();
m_hide();
cvar_set("_menu_initialized", "1");
}
+
+ PlayerInfo_Details();
}
const float MENU_ASPECT = 1.25; // 1280x1024
for(e = NULL; (e = find(e, name, itemname)); )
if(e.classname != "vtbl")
break;
-
+
if((e) && (!e.requiresConnection || (gamestatus & (GAME_ISSERVER | GAME_CONNECTED))))
{
m_hide();
METHOD(XonoticServerCreateTab, gameTypeChangeNotify, void(entity))
ATTRIB(XonoticServerCreateTab, title, string, _("Create"))
ATTRIB(XonoticServerCreateTab, intendedWidth, float, 0.9)
- ATTRIB(XonoticServerCreateTab, rows, float, 22)
+ ATTRIB(XonoticServerCreateTab, rows, float, 23)
- ATTRIB(XonoticServerCreateTab, columns, float, 6.2) // added extra .2 for center space
+ ATTRIB(XonoticServerCreateTab, columns, float, 6.2) // added extra .2 for center space
ATTRIB(XonoticServerCreateTab, mapListBox, entity, NULL)
ATTRIB(XonoticServerCreateTab, sliderFraglimit, entity, NULL)
{
entity e, e0;
+ me.TR(me);
me.TR(me);
me.TD(me, 1, 3, e = makeXonoticTextLabel(0, _("Game type:")));
me.TR(me);
e.onClickEntity = main.advancedDialog;
main.advancedDialog.refilterEntity = me.mapListBox;
- me.gotoRC(me, 0, 3.2); me.setFirstColumn(me, me.currentColumn);
+ me.gotoRC(me, 1, 3.2); me.setFirstColumn(me, me.currentColumn);
me.mapListBox = makeXonoticMapList();
me.TD(me, 1, 3, e = makeXonoticTextLabel(0, _("Map list:")));
makeCallback(e, me.mapListBox, me.mapListBox.refilterCallback);
me.TR(me);
- me.TD(me, me.rows - 4, 3, me.mapListBox);
+ me.TD(me, me.rows - 5, 3, me.mapListBox);
me.gotoRC(me, me.rows - 3, 3.5);
me.TDempty(me, 0.25);
me.TD(me, 1, 1.125, e = makeXonoticButton(_("Select all"), '0 0 0'));
--- /dev/null
- ATTRIB(XonoticDemoBrowserTab, name, string, "DemoBrowser")
+#ifdef INTERFACE
+CLASS(XonoticDemoBrowserTab) EXTENDS(XonoticTab)
+ METHOD(XonoticDemoBrowserTab, fill, void(entity))
+ ATTRIB(XonoticDemoBrowserTab, title, string, _("Demo"))
+ ATTRIB(XonoticDemoBrowserTab, intendedWidth, float, 0.9)
+ ATTRIB(XonoticDemoBrowserTab, rows, float, 21)
+ ATTRIB(XonoticDemoBrowserTab, columns, float, 6.5)
-
++ ATTRIB(XonoticDemoBrowserTab, name, string, "DemoBrowser")
+ENDCLASS(XonoticDemoBrowserTab)
+entity makeXonoticDemoBrowserTab();
+void Demo_Confirm(entity me, entity btn);
+#endif
+
+#ifdef IMPLEMENTATION
+void DemoConfirm_Check_Gamestatus(entity me, entity btn)
+{
+ if not(gamestatus & (GAME_CONNECTED | GAME_ISSERVER)) // we're not in a match, lets watch the demo
+ {
+ //TimeDemo_Click;
+ //StartDemo_Click;
+ return;
+ }
+ else // already in a match, player has to confirm
+ {
+ Demo_Confirm(me, btn);
+ }
+}
+
+entity makeXonoticDemoBrowserTab()
+{
+ entity me;
+ me = spawnXonoticDemoBrowserTab();
+ me.configureDialog(me);
+ return me;
+}
+void XonoticDemoBrowserTab_fill(entity me)
+{
+ entity e, dlist;
+
+ me.TR(me);
+ me.TD(me, 1, 4, e = makeXonoticCheckBox(0, "cl_autodemo", _("Automatically record demos while playing")));
+ me.TR(me);
+ me.TR(me);
+ me.TD(me, 1, 0.5, e = makeXonoticTextLabel(0, _("Filter:")));
+ me.TD(me, 1, 6, e = makeXonoticInputBox(0, string_null));
+ dlist = makeXonoticDemoList();
+ e.onChange = DemoList_Filter_Change;
+ e.onChangeEntity = dlist;
+ dlist.controlledTextbox = e;
-
++
+ me.TR(me);
+ me.TD(me, me.rows - 4, me.columns, dlist);
++
+ me.gotoRC(me, me.rows - 1, 0);
+ me.TD(me, 1, me.columns / 2, e = makeXonoticButton(_("Timedemo"), '0 0 0'));
+ e.onClick = DemoConfirm_Check_Gamestatus;
+ e.onClickEntity = dlist;
+ me.TD(me, 1, me.columns / 2, e = makeXonoticButton(ZCTX(_("DEMO^Play")), '0 0 0'));
+ e.onClick = DemoConfirm_Check_Gamestatus;
+ e.onClickEntity = dlist;
+}
+#endif
--- /dev/null
- ATTRIB(XonoticProfileTab, columns, float, 6.2) // added extra .2 for center space
+#ifdef INTERFACE
+CLASS(XonoticProfileTab) EXTENDS(XonoticTab)
+ METHOD(XonoticProfileTab, fill, void(entity))
+ METHOD(XonoticProfileTab, draw, void(entity))
+ ATTRIB(XonoticProfileTab, title, string, _("Profile"))
+ ATTRIB(XonoticProfileTab, intendedWidth, float, 0.9)
+ ATTRIB(XonoticProfileTab, rows, float, 23)
- //me.TD(me, 1, 1, e0 = makeXonoticTextLabel(0, string_null));
++ ATTRIB(XonoticProfileTab, columns, float, 6.2) // added extra .2 for center space
+ ATTRIB(XonoticProfileTab, playerNameLabel, entity, NULL)
+ ATTRIB(XonoticProfileTab, playerNameLabelAlpha, float, 0)
+ENDCLASS(XonoticProfileTab)
+entity makeXonoticProfileTab();
+#endif
+
+#ifdef IMPLEMENTATION
+entity makeXonoticProfileTab()
+{
+ entity me;
+ me = spawnXonoticProfileTab();
+ me.configureDialog(me);
+ return me;
+}
+void XonoticProfileTab_draw(entity me)
+{
+ if(cvar_string("_cl_name") == "Player")
+ me.playerNameLabel.alpha = ((mod(time * 2, 2) < 1) ? 1 : 0);
+ else
+ me.playerNameLabel.alpha = me.playerNameLabelAlpha;
+ SUPER(XonoticProfileTab).draw(me);
+}
+void XonoticProfileTab_fill(entity me)
+{
+ entity e, pms, label, box;
+ float i;
+
+ me.TR(me);
+ me.TR(me);
+ me.TD(me, 1, 0.5, me.playerNameLabel = makeXonoticTextLabel(0, _("Name:")));
+ me.playerNameLabelAlpha = me.playerNameLabel.alpha;
+ me.TD(me, 1, 2.5, label = makeXonoticTextLabel(0, string_null));
+ label.allowCut = 1;
+ label.allowColors = 1;
+ label.alpha = 1;
+ me.TR(me);
+ me.TD(me, 1, 3.0, box = makeXonoticInputBox(1, "_cl_name"));
+ box.forbiddenCharacters = "\r\n\\\"$"; // don't care, isn't getting saved
+ box.maxLength = -127; // negative means encoded length in bytes
+ box.saveImmediately = 1;
+ box.enableClearButton = 0;
+ label.textEntity = box;
+ me.TR(me);
+ me.TD(me, 5, 1, e = makeXonoticColorpicker(box));
+ me.TD(me, 5, 2, e = makeXonoticCharmap(box));
+ me.TR(me);
+ me.TR(me);
+ me.TR(me);
+ me.TR(me);
+ me.TR(me);
+
+ // Statistic Stuff -Debugger
+ me.TR(me);
+ me.TDempty(me, 0.5);
+ me.TD(me, 1, 2, e = makeXonoticTextLabel(0.5, _("Player Statistics:")));
+ me.TR(me);
+ me.TR(me);
+ me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Join time:")));
+ me.TR(me);
+ me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Total playing time:")));
+ me.TR(me);
+ me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Last played:")));
+ me.TR(me);
+ me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Games played:")));
+ me.TR(me);
+ me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Win / Losses:")));
+ me.TR(me);
+ me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Kills / Deaths:")));
+ me.TR(me);
+ me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("CTF elo:")));
+ me.TR(me);
+ me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("DM elo:")));
+ me.TR(me);
+ me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("TDM elo:")));
+ me.TR(me);
+ me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("DUEL elo:")));
+ me.TR(me);
+
+
+ me.gotoRC(me, 1, 3.2); me.setFirstColumn(me, me.currentColumn);
+ me.TDempty(me, 1);
+ me.TD(me, 1, 3, e = makeXonoticTextLabel(0.5, _("Model:")));
+ me.TR(me);
+ pms = makeXonoticPlayerModelSelector();
+ me.TD(me, 1, 0.3, e = makeXonoticButton("<<", '0 0 0'));
+ e.onClick = PlayerModelSelector_Prev_Click;
+ e.onClickEntity = pms;
+ me.TD(me, 13, 2.4, pms);
+ me.TD(me, 1, 0.3, e = makeXonoticButton(">>", '0 0 0'));
+ e.onClick = PlayerModelSelector_Next_Click;
+ e.onClickEntity = pms;
+
+ me.gotoRC(me, 15, 3.533); me.setFirstColumn(me, me.currentColumn);
+ me.TR(me);
+ me.TD(me, 1, 1, e = makeXonoticTextLabel(0.5, _("Glowing color:")));
+ for(i = 0; i < 15; ++i)
+ {
+ if(mod(i, 5) == 0)
+ me.TR(me);
+ me.TDNoMargin(me, 1, 0.2, e = makeXonoticColorButton(1, 0, i), '0 1 0');
+ }
+ me.gotoRC(me, 15, 4.866); me.setFirstColumn(me, me.currentColumn);
+ me.TR(me);
+ me.TD(me, 1, 1, e = makeXonoticTextLabel(0.5, _("Detail color:")));
+ for(i = 0; i < 15; ++i)
+ {
+ if(mod(i, 5) == 0)
+ me.TR(me);
+ me.TDNoMargin(me, 1, 0.2, e = makeXonoticColorButton(2, 1, i), '0 1 0');
+ }
+
+ /*
+ // crosshair_enabled: 0 = no crosshair options, 1 = no crosshair selection, but everything else enabled, 2 = all crosshair options enabled
+ // FIXME: In the future, perhaps make one global crosshair_type cvar which has 0 for disabled, 1 for custom, 2 for per weapon, etc?
+ me.gotoRC(me, 0, 3.2); me.setFirstColumn(me, me.currentColumn);
+ me.TD(me, 1, 3, e = makeXonoticRadioButton(3, "crosshair_enabled", "0", _("No crosshair")));
+ me.TR(me);
+ me.TD(me, 1, 3, e = makeXonoticRadioButton(3, "crosshair_per_weapon", string_null, _("Per weapon crosshair")));
+ makeMulti(e, "crosshair_enabled");
+ me.TR(me);
+ me.TD(me, 1, 3, e = makeXonoticRadioButton(3, "crosshair_enabled", "2", _("Custom crosshair")));
+ me.TR(me);
+ me.TDempty(me, 0.1);
+ for(i = 1; i <= 14; ++i) {
+ me.TDNoMargin(me, 1, 2 / 14, e = makeXonoticCrosshairButton(4, i), '1 1 0');
+ setDependentAND(e, "crosshair_per_weapon", 0, 0, "crosshair_enabled", 1, 2);
+ }
+ // show a larger preview of the selected crosshair
+ me.TDempty(me, 0.1);
+ me.TDNoMargin(me, 3, 0.8, e = makeXonoticCrosshairButton(7, -1), '1 1 0'); // crosshair -1 makes this a preview
+ setDependentAND(e, "crosshair_per_weapon", 0, 0, "crosshair_enabled", 1, 2);
+ me.TR(me);
+ me.TDempty(me, 0.1);
+ for(i = 15; i <= 28; ++i) {
+ me.TDNoMargin(me, 1, 2 / 14, e = makeXonoticCrosshairButton(4, i), '1 1 0');
+ setDependentAND(e, "crosshair_per_weapon", 0, 0, "crosshair_enabled", 1, 2);
+ }
+ me.TR(me);
+ me.TR(me);
+ me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Crosshair size:")));
+ setDependent(e, "crosshair_enabled", 1, 2);
+ me.TD(me, 1, 2, e = makeXonoticSlider(0.1, 1.0, 0.01, "crosshair_size"));
+ setDependent(e, "crosshair_enabled", 1, 2);
+ me.TR(me);
+ me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Crosshair alpha:")));
+ setDependent(e, "crosshair_enabled", 1, 2);
+ me.TD(me, 1, 2, e = makeXonoticSlider(0, 1, 0.1, "crosshair_alpha"));
+ setDependent(e, "crosshair_enabled", 1, 2);
+ me.TR(me);
+ me.TR(me);
+ me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Crosshair color:")));
+ setDependent(e, "crosshair_enabled", 1, 2);
+ me.TD(me, 1, 1, e = makeXonoticRadioButton(5, "crosshair_color_special", "1", _("Per weapon")));
+ setDependent(e, "crosshair_enabled", 1, 2);
+ me.TD(me, 1, 1, e = makeXonoticRadioButton(5, "crosshair_color_special", "2", _("By health")));
+ setDependent(e, "crosshair_enabled", 1, 2);
+ me.TR(me);
+ me.TDempty(me, 0.1);
+ me.TD(me, 1, 0.9, e = makeXonoticRadioButton(5, "crosshair_color_special", "0", _("Custom")));
+ setDependent(e, "crosshair_enabled", 1, 2);
+ me.TD(me, 2, 2, e = makeXonoticColorpickerString("crosshair_color", "crosshair_color"));
+ setDependentAND(e, "crosshair_color_special", 0, 0, "crosshair_enabled", 1, 2);
+ me.TR(me);
+ me.TR(me);
+ me.TR(me);
+ me.TDempty(me, 0.5);
+ me.TD(me, 1, 2, e = makeXonoticButton(_("Other crosshair settings"), '0 0 0'));
+ e.onClick = DialogOpenButton_Click;
+ e.onClickEntity = main.crosshairDialog;
+ setDependent(e, "crosshair_enabled", 1, 2);
+ // TODO: show status of crosshair dot and hittest and pickups and such here with text
+ me.TR(me);
+ me.TR(me);
+ me.TDempty(me, 0.5);
+ me.TD(me, 1, 2, e = makeXonoticButton(_("Model settings"), '0 0 0'));
+ e.onClick = DialogOpenButton_Click;
+ e.onClickEntity = main.modelDialog;
+ // TODO: show csqc model settings like forcemyplayer and deglowing/ghosting bodies with text here
+ me.TR(me);
+ me.TDempty(me, 0.5);
+ me.TD(me, 1, 2, e = makeXonoticButton(_("View settings"), '0 0 0'));
+ e.onClick = DialogOpenButton_Click;
+ e.onClickEntity = main.viewDialog;
+ // TODO: show fov and other settings with text here
+ me.TR(me);
+ me.TDempty(me, 0.5);
+ me.TD(me, 1, 2, e = makeXonoticButton(_("Weapon settings"), '0 0 0'));
+ e.onClick = DialogOpenButton_Click;
+ e.onClickEntity = main.weaponsDialog;
+ // I don't really think this is useful as is, and especially it doesn't look very clean...
+ // In the future, if ALL of these buttons had some information, then it would be justified/clean
- // TODO: show hud config name with text here
++ //me.TD(me, 1, 1, e0 = makeXonoticTextLabel(0, string_null));
+ // e0.textEntity = main.weaponsDialog;
+ // e0.allowCut = 1;
+ me.TR(me);
+ me.TDempty(me, 0.5);
+ me.TD(me, 1, 2, e = makeXonoticButton(_("HUD settings"), '0 0 0'));
+ e.onClick = DialogOpenButton_Click;
+ e.onClickEntity = main.hudDialog;
++ // TODO: show hud config name with text here
+
+ */
+ me.gotoRC(me, me.rows - 1, 0);
+ me.TD(me, 1, me.columns, makeXonoticCommandButton(_("Apply immediately"), '0 0 0', "color -1 -1;name \"$_cl_name\";sendcvar cl_weaponpriority;sendcvar cl_autoswitch;sendcvar cl_forceplayermodels;sendcvar cl_forceplayermodelsfromxonotic;playermodel $_cl_playermodel;playerskin $_cl_playerskin", COMMANDBUTTON_APPLY));
+}
+#endif
METHOD(XonoticAudioSettingsTab, fill, void(entity))
ATTRIB(XonoticAudioSettingsTab, title, string, _("Audio"))
ATTRIB(XonoticAudioSettingsTab, intendedWidth, float, 0.9)
- ATTRIB(XonoticAudioSettingsTab, rows, float, 17)
+ ATTRIB(XonoticAudioSettingsTab, rows, float, 15.5)
- ATTRIB(XonoticAudioSettingsTab, columns, float, 6.2) // added extra .2 for center space
+ ATTRIB(XonoticAudioSettingsTab, columns, float, 6.2) // added extra .2 for center space
ENDCLASS(XonoticAudioSettingsTab)
entity makeXonoticAudioSettingsTab();
#endif
me.TD(me, 1, 3, makeXonoticCheckBox(0, "menu_snd_attenuation_method", _("New style sound attenuation")));
me.TR(me);
me.TD(me, 1, 3, makeXonoticCheckBox(0, "snd_mutewhenidle", _("Mute sounds when not active")));
-
+
me.gotoRC(me, 0, 3.2); me.setFirstColumn(me, me.currentColumn);
me.TD(me, 1, 1, makeXonoticTextLabel(0, _("Frequency:")));
me.TD(me, 1, 2, e = makeXonoticTextSlider("snd_speed"));
if(cvar("developer"))
me.TD(me, 1, 3, makeXonoticCheckBox(0, "showsound", _("Debug info about sounds")));
- me.gotoRC(me, me.rows - 1, 0);
+ me.gotoRC(me, me.rows - 1.25, 0);
me.TD(me, 1, me.columns, makeXonoticCommandButton(_("Apply immediately"), '0 0 0', "snd_restart; snd_attenuation_method_$menu_snd_attenuation_method; sendcvar cl_hitsound; sendcvar cl_autotaunt; sendcvar cl_voice_directional; sendcvar cl_voice_directional_taunt_attenuation", COMMANDBUTTON_APPLY));
}
#endif
METHOD(XonoticEffectsSettingsTab, fill, void(entity))
ATTRIB(XonoticEffectsSettingsTab, title, string, _("Effects"))
ATTRIB(XonoticEffectsSettingsTab, intendedWidth, float, 0.9)
- ATTRIB(XonoticEffectsSettingsTab, rows, float, 17)
+ ATTRIB(XonoticEffectsSettingsTab, rows, float, 15.5)
- ATTRIB(XonoticEffectsSettingsTab, columns, float, 6.2) // added extra .2 for center space
+ ATTRIB(XonoticEffectsSettingsTab, columns, float, 6.2) // added extra .2 for center space
ENDCLASS(XonoticEffectsSettingsTab)
entity makeXonoticEffectsSettingsTab();
float updateCompression();
if(cvar("developer"))
me.TD(me, 1, 5 / n, e = makeXonoticCommandButton(ZCTX(_("PRE^Ultimate")), '0.5 0 0', "exec effects-ultimate.cfg", 0));
- me.TR(me);
- me.TR(me);
+ me.gotoRC(me, 1.5, 0);
me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Geometry detail:")));
me.TD(me, 1, 2, e = makeXonoticTextSlider("r_subdivisions_tolerance"));
e.addValue(e, ZCTX(_("DET^Lowest")), "16");
setDependentAND(e, "vid_gl20", 1, 1, "r_water", 1, 1);
me.TR(me);
me.TR(me);
- me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Particles quality:")));
- me.TD(me, 1, 2, e = makeXonoticSlider(0.2, 1.0, 0.1, "cl_particles_quality"));
- me.TR(me);
- me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Particles distance:")));
- me.TD(me, 1, 2, e = makeXonoticSlider(500, 2000, 100, "r_drawparticles_drawdistance"));
+ me.TD(me, 1, 1, e = makeXonoticCheckBox(0, "cl_decals", _("Decals")));
+ me.TD(me, 1, 2, e = makeXonoticCheckBox(0, "cl_decals_models", _("Decals on models")));
+ setDependent(e, "cl_decals", 1, 1);
me.TR(me);
- me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Damage effects:")));
- me.TD(me, 1, 2, e = makeXonoticTextSlider("cl_damageeffect"));
- e.addValue(e, ZCTX(_("DMGPRTCLS^Disabled")), "0");
- e.addValue(e, ZCTX(_("DMGPRTCLS^Skeletal")), "1");
- e.addValue(e, ZCTX(_("DMGPRTCLS^All")), "2");
- e.configureXonoticTextSliderValues(e);
+ me.TDempty(me, 0.2);
+ me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Distance:")));
+ setDependent(e, "cl_decals", 1, 1);
+ me.TD(me, 1, 2, e = makeXonoticSlider(200, 500, 20, "r_drawdecals_drawdistance"));
+ setDependent(e, "cl_decals", 1, 1);
me.TR(me);
- me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "cl_spawn_point_particles", _("Particle effects for spawnpoints")));
- makeMulti(e, "cl_spawn_event_particles");
+ me.TDempty(me, 0.2);
+ me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Time:")));
+ setDependent(e, "cl_decals", 1, 1);
+ me.TD(me, 1, 2, e = makeXonoticSlider(1, 20, 1, "cl_decals_time"));
+ setDependent(e, "cl_decals", 1, 1);
- me.gotoRC(me, 2, 3.2); me.setFirstColumn(me, me.currentColumn);
+ me.gotoRC(me, 1.5, 3.2); me.setFirstColumn(me, me.currentColumn);
me.TD(me, 1, 3, e = makeXonoticRadioButton(1, "r_coronas", "0", _("No dynamic lighting")));
me.TR(me);
me.TD(me, 1, 3, e = makeXonoticRadioButton(1, "gl_flashblend", string_null, _("Fake corona lighting")));
me.TD(me, 1, 2, s);
me.TR(me);
me.TR(me);
- me.TD(me, 1, 1, e = makeXonoticCheckBox(0, "cl_decals", _("Decals")));
- me.TD(me, 1, 2, e = makeXonoticCheckBox(0, "cl_decals_models", _("Decals on models")));
- setDependent(e, "cl_decals", 1, 1);
+ me.TD(me, 1, 1, e = makeXonoticCheckBox(0, "cl_particles", _("Particles")));
+ me.TD(me, 1, 2, e = makeXonoticCheckBox(0, "cl_spawn_point_particles", _("Spawnpoint effects")));
+ makeMulti(e, "cl_spawn_event_particles");
+ setDependent(e, "cl_particles", 1, 1);
me.TR(me);
me.TDempty(me, 0.2);
- me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Distance:")));
- setDependent(e, "cl_decals", 1, 1);
- me.TD(me, 1, 2, e = makeXonoticSlider(200, 500, 20, "r_drawdecals_drawdistance"));
- setDependent(e, "cl_decals", 1, 1);
- me.TR(me);
- me.TDempty(me, 0.2);
- me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Time:")));
- setDependent(e, "cl_decals", 1, 1);
- me.TD(me, 1, 2, e = makeXonoticSlider(1, 20, 1, "cl_decals_time"));
- setDependent(e, "cl_decals", 1, 1);
+ me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Quality:")));
+ setDependent(e, "cl_particles", 1, 1);
+ me.TD(me, 1, 2, e = makeXonoticParticlesSlider());
+ setDependent(e, "cl_particles", 1, 1);
- me.gotoRC(me, me.rows - 1, 0);
+ me.gotoRC(me, me.rows - 1.25, 0);
me.TD(me, 1, me.columns, makeXonoticCommandButton(_("Apply immediately"), '0 0 0', "vid_restart", COMMANDBUTTON_APPLY));
}
#endif
--- /dev/null
- if not(gamestatus & (GAME_CONNECTED | GAME_ISSERVER)) // we're not in a match, ask the player if they want to start one anyway
+#ifdef INTERFACE
+CLASS(XonoticHUDDialog) EXTENDS(XonoticDialog)
+ METHOD(XonoticHUDDialog, toString, string(entity))
+ METHOD(XonoticHUDDialog, fill, void(entity))
+ METHOD(XonoticHUDDialog, showNotify, void(entity))
+ ATTRIB(XonoticHUDDialog, title, string, _("HUD settings"))
+ ATTRIB(XonoticHUDDialog, color, vector, SKINCOLOR_DIALOG_HUD)
+ ATTRIB(XonoticHUDDialog, intendedWidth, float, 0.5)
+ ATTRIB(XonoticHUDDialog, rows, float, 18)
+ ATTRIB(XonoticHUDDialog, columns, float, 3)
+ENDCLASS(XonoticHUDDialog)
+void HUDSetup_Start(entity me, entity btn);
+#endif
+
+#ifdef IMPLEMENTATION
+void HUDSetup_Check_Gamestatus(entity me, entity btn)
+{
- return "hi"; // TODO: show hud config name with text here
++ if(!(gamestatus & (GAME_CONNECTED | GAME_ISSERVER))) // we're not in a match, ask the player if they want to start one anyway
+ {
+ DialogOpenButton_Click(me, main.hudconfirmDialog);
+ }
+ else // already in a match, lets just cut to the point and open up the hud editor directly
+ {
+ HUDSetup_Start(me, btn);
+ }
+}
+void XonoticHUDDialog_showNotify(entity me)
+{
+ loadAllCvars(me);
+}
+string XonoticHUDDialog_toString(entity me)
+{
-
++ return "hi"; // TODO: show hud config name with text here
+}
+void XonoticHUDDialog_fill(entity me)
+{
+ entity e;
-
++
+ me.TR(me);
+ me.TD(me, 1, 3, e = makeXonoticTextLabel(0, _("Damage:")));
+ me.TR(me);
+ me.TDempty(me, 0.2);
+ me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Overlay:")));
+ me.TD(me, 1, 2, e = makeXonoticSlider(0, 1, 0.05, "hud_damage"));
+ me.TR(me);
+ me.TDempty(me, 0.2);
+ me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Factor:")));
+ setDependent(e, "hud_damage", 0.001, 100);
+ me.TD(me, 1, 2, e = makeXonoticSlider(0.025, 0.1, 0.025, "hud_damage_factor"));
+ setDependent(e, "hud_damage", 0.001, 100);
+ me.TR(me);
+ me.TDempty(me, 0.2);
+ me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Fade rate:")));
+ setDependent(e, "hud_damage", 0.001, 100);
+ me.TD(me, 1, 2, e = makeXonoticSlider(0.25, 1, 0.05, "hud_damage_fade_rate"));
+ setDependent(e, "hud_damage", 0.001, 100);
+ me.TR(me);
-
++
+ me.TR(me);
+ me.TD(me, 1, 3, e = makeXonoticCheckBox(1, "cl_hidewaypoints", _("Waypoints")));
+ me.TR(me);
+ me.TDempty(me, 0.2);
+ me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Scale:")));
+ setDependent(e, "cl_hidewaypoints", 0, 0);
+ me.TD(me, 1, 2, e = makeXonoticSlider(0.5, 1.5, 0.05, "g_waypointsprite_scale"));
+ setDependent(e, "cl_hidewaypoints", 0, 0);
+ me.TR(me);
+ me.TDempty(me, 0.2);
+ me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Alpha:")));
+ setDependent(e, "cl_hidewaypoints", 0, 0);
+ me.TD(me, 1, 2, e = makeXonoticSlider(0.1, 1, 0.05, "g_waypointsprite_alpha"));
+ setDependent(e, "cl_hidewaypoints", 0, 0);
+ me.TR(me);
+ me.TDempty(me, 0.2);
+ me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Edge offset:")));
+ setDependent(e, "cl_hidewaypoints", 0, 0);
+ me.TD(me, 1, 2, e = makeXonoticSlider(0, 0.3, 0.01, "g_waypointsprite_edgeoffset_bottom"));
+ makeMulti(e, "g_waypointsprite_edgeoffset_top g_waypointsprite_edgeoffset_left g_waypointsprite_edgeoffset_right");
+ setDependent(e, "cl_hidewaypoints", 0, 0);
+ me.TR(me);
- // TODO: show hud config name with text here
-
++
+ me.TR(me);
+ me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "hud_shownames", _("Show names above players")));
+ me.TR(me);
+ me.TDempty(me, 0.2);
+ me.TD(me, 1, 2.8, e = makeXonoticCheckBoxEx(25, 0, "hud_shownames_crosshairdistance", _("Only when near crosshair")));
+ me.TR(me);
+ me.TDempty(me, 0.2);
+ me.TD(me, 1, 2.8, e = makeXonoticCheckBox(0, "hud_shownames_status", _("Display health and armor")));
+ me.TR(me);
+ me.TR(me);
+ me.TDempty(me, 0.5);
+ me.TD(me, 1, 2, e = makeXonoticButton(_("Enter HUD editor"), '0 0 0'));
+ e.onClick = HUDSetup_Check_Gamestatus;
+ e.onClickEntity = me;
- #endif
++ // TODO: show hud config name with text here
++
+ me.gotoRC(me, me.rows - 1, 0);
+ me.TD(me, 1, me.columns, e = makeXonoticButton(_("OK"), '0 0 0'));
+ e.onClick = Dialog_Close;
+ e.onClickEntity = me;
+}
++#endif
--- /dev/null
- if not(gamestatus & (GAME_CONNECTED | GAME_ISSERVER))
+#ifdef INTERFACE
+CLASS(XonoticHUDConfirmDialog) EXTENDS(XonoticDialog)
+ METHOD(XonoticHUDConfirmDialog, fill, void(entity))
+ ATTRIB(XonoticHUDConfirmDialog, title, string, _("Enter HUD editor"))
+ ATTRIB(XonoticHUDConfirmDialog, color, vector, SKINCOLOR_DIALOG_HUDCONFIRM)
+ ATTRIB(XonoticHUDConfirmDialog, intendedWidth, float, 0.5)
+ ATTRIB(XonoticHUDConfirmDialog, rows, float, 4)
+ ATTRIB(XonoticHUDConfirmDialog, columns, float, 2)
+ENDCLASS(XonoticHUDConfirmDialog)
+#endif
+
+#ifdef IMPLEMENTATION
+void HUDSetup_Start(entity me, entity btn)
+{
-
++ if (!(gamestatus & (GAME_CONNECTED | GAME_ISSERVER)))
+ localcmd("map hudsetup/hudsetup", "\n");
+ else
+ localcmd("togglemenu 0\n");
++
+ localcmd("_hud_configure 1", "\n");
+}
+
+void XonoticHUDConfirmDialog_fill(entity me)
+{
+ entity e;
+
+ me.TR(me);
+ me.TD(me, 1, 2, e = makeXonoticTextLabel(0.5, _("In order for the HUD editor to show, you must first be in game.")));
+ me.TR(me);
+ me.TD(me, 1, 2, e = makeXonoticTextLabel(0.5, _("Do you wish to start a local game to set up the HUD?")));
+ me.TR(me);
+ me.TR(me);
+ me.TD(me, 1, 1, e = makeXonoticButton(ZCTX(_("HDCNFRM^Yes")), '1 0 0'));
+ e.onClick = HUDSetup_Start;
+ e.onClickEntity = me;
+ me.TD(me, 1, 1, e = makeXonoticButton(ZCTX(_("HDCNFRM^No")), '0 1 0'));
+ e.onClick = Dialog_Close;
+ e.onClickEntity = me;
+}
+#endif
--- /dev/null
-
+#ifdef INTERFACE
+CLASS(XonoticModelDialog) EXTENDS(XonoticDialog)
+ METHOD(XonoticModelDialog, toString, string(entity))
+ METHOD(XonoticModelDialog, fill, void(entity))
+ METHOD(XonoticModelDialog, showNotify, void(entity))
+ ATTRIB(XonoticModelDialog, title, string, _("Model settings"))
+ ATTRIB(XonoticModelDialog, color, vector, SKINCOLOR_DIALOG_MODEL)
+ ATTRIB(XonoticModelDialog, intendedWidth, float, 0.5)
+ ATTRIB(XonoticModelDialog, rows, float, 7)
+ ATTRIB(XonoticModelDialog, columns, float, 3)
+ENDCLASS(XonoticModelDialog)
+#endif
+
+#ifdef IMPLEMENTATION
+void XonoticModelDialog_showNotify(entity me)
+{
+ loadAllCvars(me);
+}
+string XonoticModelDialog_toString(entity me)
+{
+ return "hi"; // TODO: show csqc model settings like forcemyplayer and deglowing/ghosting bodies with text here
+}
+void XonoticModelDialog_fill(entity me)
+{
+ entity e;
-
++
+ me.TR(me);
+ me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Body fading:")));
+ me.TD(me, 1, 2, e = makeXonoticSlider(0, 2, 0.2, "cl_deathglow"));
+ me.TR(me);
+ me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Gibs:")));
+ me.TD(me, 1, 2, e = makeXonoticTextSlider("cl_nogibs"));
+ e.addValue(e, ZCTX(_("GIBS^None")), "1");
+ e.addValue(e, ZCTX(_("GIBS^Few")), "0.75");
+ e.addValue(e, ZCTX(_("GIBS^Many")), "0.5");
+ e.addValue(e, ZCTX(_("GIBS^Lots")), "0");
+ e.configureXonoticTextSliderValues(e);
+ setDependent(e, "cl_gentle", 0, 0);
+ me.TR(me);
+ me.TR(me);
+ me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "cl_forceplayermodels", _("Force player models to mine")));
+ me.TR(me);
+ me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "cl_forceplayercolors", _("Force player colors to mine")));
+ me.TR(me);
++
+ me.gotoRC(me, me.rows - 1, 0);
+ me.TD(me, 1, me.columns, e = makeXonoticButton(_("OK"), '0 0 0'));
+ e.onClick = Dialog_Close;
+ e.onClickEntity = me;
+}
+#endif
--- /dev/null
-
+#ifdef INTERFACE
+CLASS(XonoticGameViewSettingsTab) EXTENDS(XonoticTab)
+ //METHOD(XonoticGameCrosshairSettingsTab, toString, string(entity))
+ METHOD(XonoticGameViewSettingsTab, fill, void(entity))
+ METHOD(XonoticGameViewSettingsTab, showNotify, void(entity))
+ ATTRIB(XonoticGameViewSettingsTab, title, string, _("View"))
+ ATTRIB(XonoticGameViewSettingsTab, intendedWidth, float, 0.9)
+ ATTRIB(XonoticGameViewSettingsTab, rows, float, 14)
+ ATTRIB(XonoticGameViewSettingsTab, columns, float, 6.2)
+ENDCLASS(XonoticGameViewSettingsTab)
+entity makeXonoticGameViewSettingsTab();
+#endif
+
+#ifdef IMPLEMENTATION
+void XonoticGameViewSettingsTab_showNotify(entity me)
+{
+ loadAllCvars(me);
+}
+entity makeXonoticGameViewSettingsTab()
+{
+ entity me;
+ me = spawnXonoticGameViewSettingsTab();
+ me.configureDialog(me);
+ return me;
+}
+
+void clippedspectatingclick(entity me, entity checkbox)
+{
+ if(gamestatus & (GAME_CONNECTED | GAME_ISSERVER))
+ localcmd("sendcvar cl_clippedspectating\n");
+
+ CheckBox_Click(me, checkbox);
+}
+
+void XonoticGameViewSettingsTab_fill(entity me)
+{
+ entity e;
++
+ me.TR(me);
+ me.TD(me, 1, 3, e = makeXonoticRadioButton(1, "chase_active", "0", _("1st person perspective")));
+ makeMulti(e, "crosshair_hittest_showimpact");
+ me.TR(me);
+ me.TDempty(me, 0.2);
+ me.TD(me, 1, 2.8, e = makeXonoticCheckBoxEx(0.05, 0, "cl_bobfall", _("Smooth the view when landing from a jump")));
+ setDependent(e, "chase_active", -1, 0);
+ me.TR(me);
+ me.TDempty(me, 0.2);
+ me.TD(me, 1, 2.8, e = makeXonoticCheckBoxEx(0.05, 0, "cl_smoothviewheight", _("Smooth the view while crouching")));
+ setDependent(e, "chase_active", -1, 0);
+ me.TR(me);
+ me.TDempty(me, 0.2);
+ me.TD(me, 1, 2.8, e = makeXonoticCheckBoxEx(1, 0, "v_idlescale", _("View waving while idle")));
+ setDependent(e, "chase_active", -1, 0);
+ me.TR(me);
+ me.TDempty(me, 0.2);
+ me.TD(me, 1, 2.8, e = makeXonoticCheckBoxEx(0.01, 0, "cl_bob", _("View bobbing while walking around")));
+ makeMulti(e, "cl_bob2");
+ setDependent(e, "chase_active", -1, 0);
+ me.TR(me);
+ me.TR(me);
+ me.TD(me, 1, 3, e = makeXonoticRadioButton(1, "chase_active", "1", _("3rd person perspective")));
+ makeMulti(e, "crosshair_hittest_showimpact");
+ me.TR(me);
+ me.TDempty(me, 0.2);
+ me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Back distance")));
+ setDependent(e, "chase_active", 1, 1);
+ me.TD(me, 1, 2, e = makeXonoticSlider(10, 100, 1, "chase_back"));
+ setDependent(e, "chase_active", 1, 1);
+ me.TR(me);
+ me.TDempty(me, 0.2);
+ me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Up distance")));
+ setDependent(e, "chase_active", 1, 1);
+ me.TD(me, 1, 2, e = makeXonoticSlider(10, 50, 1, "chase_up"));
+ setDependent(e, "chase_active", 1, 1);
+ me.TR(me);
+ me.TR(me);
+ me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "cl_eventchase_death", _("Slide to third person perspective upon death")));
+ setDependent(e, "chase_active", -1, 0);
+ me.TR(me);
+ me.TD(me, 1, 3, e = makeXonoticCheckBox(1, "cl_clippedspectating", _("Allow passing through walls while spectating")));
+ e.onClick = clippedspectatingclick;
+ e.onClickEntity = e;
+ // todo: onclick, do sendcvar if connected
+
+ me.gotoRC(me, 0, 3.2); me.setFirstColumn(me, me.currentColumn);
+ me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Field of view:")));
+ me.TD(me, 1, 2, e = makeXonoticSlider(60, 130, 5, "fov"));
+ me.TR(me);
+ me.TR(me);
+ //me.TDempty(me, 0.2);
+ me.TD(me, 1, 1, e = makeXonoticTextLabel(0, ZCTX(_("ZOOM^Zoom factor:"))));
+ me.TD(me, 1, 2, e = makeXonoticSlider(2, 16, 0.5, "cl_zoomfactor"));
+ me.TR(me);
+ //me.TDempty(me, 0.2);
+ me.TD(me, 1, 1, e = makeXonoticTextLabel(0, ZCTX(_("ZOOM^Zoom speed:"))));
+ me.TD(me, 1, 2, e = makeXonoticTextSlider("cl_zoomspeed"));
+ e.addValue(e, "1", "1"); // Samual: for() loop doesn't work here, even though it would make sense.
+ e.addValue(e, "2", "2");
+ e.addValue(e, "3", "3");
+ e.addValue(e, "4", "4");
+ e.addValue(e, "5", "5");
+ e.addValue(e, "6", "6");
+ e.addValue(e, "7", "7");
+ e.addValue(e, "8", "8");
+ e.addValue(e, ZCTX(_("ZOOM^Instant")), "-1");
+ e.configureXonoticTextSliderValues(e);
+ me.TR(me);
+ //me.TDempty(me, 0.2);
+ me.TD(me, 1, 1, e = makeXonoticTextLabel(0, ZCTX(_("ZOOM^Zoom sensitivity:"))));
+ me.TD(me, 1, 2, e = makeXonoticSlider(0, 1, 0.1, "cl_zoomsensitivity"));
+ me.TR(me);
+ me.TR(me);
+ me.TD(me, 1, 1, e = makeXonoticCheckBox(0, "cl_velocityzoom", _("Velocity zoom")));
+ me.TD(me, 1, 2, e = makeXonoticCheckBoxEx(3, 1, "cl_velocityzoom_type", _("Forward movement only")));
+ setDependent(e, "cl_velocityzoom", 1, 1);
+ me.TR(me);
+ me.TDempty(me, 0.2);
+ me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, ZCTX(_("VZOOM^Factor"))));
+ setDependentAND(e, "cl_velocityzoom", 1, 1, "cl_velocityzoom_type", 1, 3);
+ me.TD(me, 1, 2, e = makeXonoticSlider(-1, 1, 0.1, "cl_velocityzoom_factor"));
+ setDependentAND(e, "cl_velocityzoom", 1, 1, "cl_velocityzoom_type", 1, 3);
+ me.TR(me);
+ me.TR(me);
+ //me.TDempty(me, 0.2);
+ me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "cl_reticle", _("Display reticle 2D overlay while zooming")));
+ me.TR(me);
+ //me.TDempty(me, 0.2);
+ me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "cl_unpress_zoom_on_death", _("Release zoom when you die or respawn")));
+ makeMulti(e, "cl_unpress_zoom_on_spawn");
+ me.TR(me);
+ //me.TDempty(me, 0.2);
+ me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "cl_unpress_zoom_on_weapon_switch", _("Release zoom when you switch weapons")));
+}
+#endif
--- /dev/null
-
+#ifdef INTERFACE
+CLASS(XonoticWeaponsDialog) EXTENDS(XonoticDialog)
+ METHOD(XonoticWeaponsDialog, toString, string(entity))
+ METHOD(XonoticWeaponsDialog, fill, void(entity))
+ METHOD(XonoticWeaponsDialog, showNotify, void(entity))
+ ATTRIB(XonoticWeaponsDialog, title, string, _("Weapon settings"))
+ ATTRIB(XonoticWeaponsDialog, color, vector, SKINCOLOR_DIALOG_WEAPONS)
+ ATTRIB(XonoticWeaponsDialog, intendedWidth, float, 0.7)
+ ATTRIB(XonoticWeaponsDialog, rows, float, 12)
+ ATTRIB(XonoticWeaponsDialog, columns, float, 5.2)
+ ATTRIB(XonoticWeaponsDialog, weaponsList, entity, NULL)
+ENDCLASS(XonoticWeaponsDialog)
+#endif
+
+#ifdef IMPLEMENTATION
+void XonoticWeaponsDialog_showNotify(entity me)
+{
+ loadAllCvars(me);
+}
+string XonoticWeaponsDialog_toString(entity me)
+{
+ return me.weaponsList.toString(me.weaponsList);
+}
+void XonoticWeaponsDialog_fill(entity me)
+{
+ entity e;
+
+ me.TR(me);
+ me.TD(me, 1, 2, makeXonoticTextLabel(0, _("Weapon priority list:")));
+ me.TR(me);
+ me.TD(me, 8, 2, e = me.weaponsList = makeXonoticWeaponsList());
+ me.gotoRC(me, 9, 0);
+ me.TD(me, 1, 1, e = makeXonoticButton(_("Up"), '0 0 0'));
+ e.onClick = WeaponsList_MoveUp_Click;
+ e.onClickEntity = me.weaponsList;
+ me.TD(me, 1, 1, e = makeXonoticButton(_("Down"), '0 0 0'));
+ e.onClick = WeaponsList_MoveDown_Click;
+ e.onClickEntity = me.weaponsList;
-
++
+ me.gotoRC(me, 0, 2.2); me.setFirstColumn(me, me.currentColumn);
+ me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "cl_weaponpriority_useforcycling", _("Use priority list for weapon cycling")));
+ me.TR(me);
+ me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "cl_autoswitch", _("Auto switch weapons on pickup")));
+ me.TR(me);
+ me.TR(me);
+ me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "r_drawviewmodel", _("Draw 1st person weapon model")));
+ me.TR(me);
+ me.TDempty(me, 0.2);
+ me.TD(me, 1, 0.9, e = makeXonoticRadioButton(1, "cl_gunalign", "4", _("Left align")));
+ setDependent(e, "r_drawviewmodel", 1, 1);
+ me.TD(me, 1, 0.9, e = makeXonoticRadioButton(1, "cl_gunalign", "1", _("Center")));
+ setDependent(e, "r_drawviewmodel", 1, 1);
+ me.TD(me, 1, 1.0, e = makeXonoticRadioButton(1, "cl_gunalign", "3", _("Right align")));
+ setDependent(e, "r_drawviewmodel", 1, 1);
+ me.TR(me);
+ me.TR(me);
+ me.TDempty(me, 0.2);
+ me.TD(me, 1, 2.8, e = makeXonoticCheckBox(0, "cl_followmodel", _("Gun model swaying")));
+ makeMulti(e, "cl_leanmodel");
+ setDependent(e, "r_drawviewmodel", 1, 1);
+ me.TR(me);
+ me.TDempty(me, 0.2);
+ me.TD(me, 1, 2.8, e = makeXonoticCheckBox(0, "cl_bobmodel", _("Gun model bobbing")));
+ setDependent(e, "r_drawviewmodel", 1, 1);
+ //me.TR(me);
+ //me.TR(me);
+ // me.TDempty(me, 0.2);
+ // me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, ZCTX(_("VWMDL^Scale"))));
+ // setDependent(e, "r_drawviewmodel", 1, 1);
+ // me.TD(me, 1, 2, e = makeXonoticSlider(0.1, 2, 0.1, "cl_viewmodel_scale"));
+ // setDependent(e, "r_drawviewmodel", 1, 1);
++
+ me.gotoRC(me, me.rows - 1, 0);
+ me.TD(me, 1, me.columns, e = makeXonoticButton(_("OK"), '0 0 0'));
+ e.onClick = Dialog_Close;
+ e.onClickEntity = me;
+}
+#endif
METHOD(XonoticInputSettingsTab, fill, void(entity))
ATTRIB(XonoticInputSettingsTab, title, string, _("Input"))
ATTRIB(XonoticInputSettingsTab, intendedWidth, float, 0.9)
- ATTRIB(XonoticInputSettingsTab, rows, float, 17)
+ ATTRIB(XonoticInputSettingsTab, rows, float, 15.5)
- ATTRIB(XonoticInputSettingsTab, columns, float, 6.2) // added extra .2 for center space
+ ATTRIB(XonoticInputSettingsTab, columns, float, 6.2) // added extra .2 for center space
ENDCLASS(XonoticInputSettingsTab)
entity makeXonoticInputSettingsTab();
#endif
me.TR(me);
me.TDempty(me, 0.2);
me.TD(me, 1, 2.8, e = makeXonoticCheckBox(0, "m_accelerate", _("Enable built in mouse acceleration")));
-
-
+
+
- me.gotoRC(me, me.rows - 1, 0);
+ me.gotoRC(me, me.rows - 1.25, 0);
me.TD(me, 1, me.columns, makeXonoticCommandButton(_("Apply immediately"), '0 0 0', "sendcvar cl_movement_track_canjump", COMMANDBUTTON_APPLY));
}
#endif
METHOD(XonoticUserSettingsTab, fill, void(entity))
ATTRIB(XonoticUserSettingsTab, title, string, _("User"))
ATTRIB(XonoticUserSettingsTab, intendedWidth, float, 0.9)
- ATTRIB(XonoticUserSettingsTab, rows, float, 17)
+ ATTRIB(XonoticUserSettingsTab, rows, float, 15.5)
ATTRIB(XonoticUserSettingsTab, columns, float, 5)
ENDCLASS(XonoticUserSettingsTab)
entity makeXonoticUserSettingsTab();
me.TR(me);
me.TD(me, 1, 2, e = makeXonoticTextLabel(0, _("Menu skins:")));
me.TR(me);
- me.TD(me, me.rows - 2, 2, sk = makeXonoticSkinList());
- me.gotoRC(me, me.rows - 1, 0);
+ me.TD(me, me.rows - 2.5, 2, sk = makeXonoticSkinList());
+ me.gotoRC(me, me.rows - 1.5, 0);
me.TD(me, 1, 2, e = makeXonoticButton(_("Set skin"), '0 0 0'));
e.onClick = SetSkin_Click;
e.onClickEntity = sk;
me.TD(me, 1, 1.5, e = makeXonoticButton(_("Set font"), '0 0 0'));
e.onClick = SetLanguage_Click;
e.onClickEntity = sk;*/
-
+
me.gotoRC(me, 0, 2.85); me.setFirstColumn(me, me.currentColumn);
me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Text language:")));
me.TR(me);
me.TD(me, 1, 1.5, e = makeXonoticButton(_("Set language"), '0 0 0'));
e.onClick = SetLanguage_Click;
e.onClickEntity = sk;
-
+
me.gotoRC(me, 9, 2.2); me.setFirstColumn(me, me.currentColumn);
me.TD(me, 1, 2.8, e = makeXonoticCheckBox(0, "cl_gentle", _("Disable gore effects and harsh language")));
me.TR(me);
me.TR(me);
me.TD(me, 1, 2.8, e = makeXonoticCheckBox(0, "cl_allow_uid2name", _("Allow player statistics to use your nickname")));
setDependent(e, "cl_allow_uidtracking", 1, 1);
-
+
- me.gotoRC(me, me.rows - 3, 2.6);
+ me.gotoRC(me, me.rows - 2, 2.6);
me.TD(me, 1, 2, makeXonoticCommandButton(_("Apply immediately"), '0 0 0', "sendcvar cl_gentle; sendcvar cl_allow_uidtracking; sendcvar cl_allow_uid2name;", COMMANDBUTTON_APPLY));
}
METHOD(XonoticVideoSettingsTab, fill, void(entity))
ATTRIB(XonoticVideoSettingsTab, title, string, _("Video"))
ATTRIB(XonoticVideoSettingsTab, intendedWidth, float, 0.9)
- ATTRIB(XonoticVideoSettingsTab, rows, float, 17)
+ ATTRIB(XonoticVideoSettingsTab, rows, float, 15.5)
- ATTRIB(XonoticVideoSettingsTab, columns, float, 6.2) // added extra .2 for center space
+ ATTRIB(XonoticVideoSettingsTab, columns, float, 6.2) // added extra .2 for center space
ATTRIB(XonoticVideoSettingsTab, name, string, "videosettings")
ENDCLASS(XonoticVideoSettingsTab)
entity makeXonoticVideoSettingsTab();
me.TR(me);
me.TD(me, 1, 1, e = makeXonoticCheckBox(0, "vid_fullscreen", _("Full screen")));
me.TD(me, 1, 2, e = makeXonoticCheckBox(0, "vid_vsync", _("Vertical Synchronization")));
-
+
me.TR(me);
+ if(cvar("developer"))
+ { me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "v_flipped", _("Flip view horizontally"))); }
me.TR(me);
me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Anisotropy:")));
me.TD(me, 1, 2, e = makeXonoticTextSlider("gl_texture_anisotropy"));
me.TR(me);
me.TD(me, 1, 3, e = makeXonoticCheckBoxEx(2, 0, "r_viewfbo", _("High-quality frame buffer")));
setDependent(e, "vid_samples", 1, 1);
-
+
me.TR(me);
me.TR(me);
me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Depth first:")));
me.TR(me);
me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "r_trippy", _("Trippy vertices (easter egg)")));
setDependent(e, "vid_gl20", 1, 1);
- me.TR(me);
- me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "v_flipped", _("Flip view horizontally")));
}
- me.gotoRC(me, me.rows - 1, 0);
+ me.gotoRC(me, me.rows - 1.25, 0);
me.TD(me, 1, me.columns, makeXonoticCommandButton(_("Apply immediately"), '0 0 0', "vid_width $_menu_vid_width; vid_height $_menu_vid_height; vid_pixelheight $_menu_vid_pixelheight; vid_desktopfullscreen $_menu_vid_desktopfullscreen; menu_cmd update_conwidths_before_vid_restart; vid_restart; menu_cmd sync", COMMANDBUTTON_APPLY));
}
#endif
ATTRIB(MainWindow, winnerDialog, entity, NULL)
ATTRIB(MainWindow, serverInfoDialog, entity, NULL)
ATTRIB(MainWindow, cvarsDialog, entity, NULL)
+ ATTRIB(MainWindow, screenshotViewerDialog, entity, NULL)
ATTRIB(MainWindow, viewDialog, entity, NULL)
ATTRIB(MainWindow, modelDialog, entity, NULL)
- ATTRIB(MainWindow, crosshairDialog, entity, NULL)
ATTRIB(MainWindow, hudDialog, entity, NULL)
ATTRIB(MainWindow, hudconfirmDialog, entity, NULL)
ATTRIB(MainWindow, mainNexposee, entity, NULL)
ATTRIB(MainWindow, fadedAlpha, float, SKINALPHA_BEHIND)
ATTRIB(MainWindow, dialogToShow, entity, NULL)
+ ATTRIB(MainWindow, notificationDialog, entity, NULL)
+ ATTRIB(MainWindow, democonfirmDialog, entity, NULL)
ENDCLASS(MainWindow)
#endif
me.firstRunDialog = i = spawnXonoticFirstRunDialog();
i.configureDialog(i);
me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
-
-
+
+
// hud_configure dialogs
i = spawnXonoticHUDExitDialog();
i.configureDialog(i);
me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
-
+
i = spawnXonoticHUDNotificationDialog();
i.configureDialog(i);
me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
-
+
i = spawnXonoticHUDAmmoDialog();
i.configureDialog(i);
me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
-
+
i = spawnXonoticHUDHealthArmorDialog();
i.configureDialog(i);
me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
-
+
i = spawnXonoticHUDChatDialog();
i.configureDialog(i);
me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
-
+
i = spawnXonoticHUDModIconsDialog();
i.configureDialog(i);
me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
-
+
i = spawnXonoticHUDPowerupsDialog();
i.configureDialog(i);
me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
-
+
i = spawnXonoticHUDPressedKeysDialog();
i.configureDialog(i);
me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
-
+
i = spawnXonoticHUDRaceTimerDialog();
i.configureDialog(i);
me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
-
+
i = spawnXonoticHUDRadarDialog();
i.configureDialog(i);
me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
-
+
i = spawnXonoticHUDScoreDialog();
i.configureDialog(i);
me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
-
+
i = spawnXonoticHUDTimerDialog();
i.configureDialog(i);
me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
-
+
i = spawnXonoticHUDVoteDialog();
i.configureDialog(i);
me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
-
+
i = spawnXonoticHUDWeaponsDialog();
i.configureDialog(i);
me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
i = spawnXonoticHUDInfoMessagesDialog();
i.configureDialog(i);
me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
-
+
i = spawnXonoticHUDPhysicsDialog();
i.configureDialog(i);
me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
+
+ me.screenshotViewerDialog = i = spawnXonoticScreenshotViewerDialog();
+ i.configureDialog(i);
+ me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
i = spawnXonoticHUDCenterprintDialog();
i.configureDialog(i);
me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
-
-
+
+
// dialogs used by settings
me.userbindEditDialog = i = spawnXonoticUserbindEditDialog();
i.configureDialog(i);
me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
-
+
me.cvarsDialog = i = spawnXonoticCvarsDialog();
i.configureDialog(i);
me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
-
-
+
+
// dialog used by singleplayer
me.winnerDialog = i = spawnXonoticWinnerDialog();
i.configureDialog(i);
me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
-
-
+
+
// dialog used by multiplayer/join
me.serverInfoDialog = i = spawnXonoticServerInfoDialog();
i.configureDialog(i);
me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
-
-
+
+ me.democonfirmDialog = i = spawnXonoticDemoConfirmDialog();
+ i.configureDialog(i);
+ me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
+
+
// dialogs used by multiplayer/create
me.mapInfoDialog = i = spawnXonoticMapInfoDialog();
i.configureDialog(i);
me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
-
+
me.advancedDialog = i = spawnXonoticAdvancedDialog();
i.configureDialog(i);
me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
me.mutatorsDialog = i = spawnXonoticMutatorsDialog();
i.configureDialog(i);
me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
-
-
- // dialogs used by multiplayer/player setup
- me.crosshairDialog = i = spawnXonoticCrosshairDialog();
- i.configureDialog(i);
- me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
-
+ // dialogs used by multiplayer/player setup
me.hudDialog = i = spawnXonoticHUDDialog();
i.configureDialog(i);
me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
me.hudconfirmDialog = i = spawnXonoticHUDConfirmDialog();
i.configureDialog(i);
me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
-
+
me.modelDialog = i = spawnXonoticModelDialog();
i.configureDialog(i);
me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
-
+
- me.viewDialog = i = spawnXonoticViewDialog();
+ me.weaponsDialog = i = spawnXonoticWeaponsDialog();
i.configureDialog(i);
me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
-
+
- me.weaponsDialog = i = spawnXonoticWeaponsDialog();
+ me.notificationDialog = i = spawnXonoticNotificationDialog();
i.configureDialog(i);
me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
+
// mutator dialogs
i = spawnXonoticSandboxToolsDialog();
i.configureDialog(i);
me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z * SKINALPHA_DIALOG_SANDBOXTOOLS);
-
-
+
+
// miscellaneous dialogs
i = spawnXonoticTeamSelectDialog();
i.configureDialog(i);
me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
-
-
+
+
// main dialogs/windows
me.mainNexposee = n = spawnXonoticNexposee();
/*
i.configureDialog(i);
n.addItemCentered(n, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
n.setNexposee(n, i, SKINPOSITION_DIALOG_SINGLEPLAYER, SKINALPHAS_MAINMENU_x, SKINALPHAS_MAINMENU_y);
-
+
i = spawnXonoticMultiplayerDialog();
i.configureDialog(i);
n.addItemCentered(n, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
n.addItemCentered(n, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
n.setNexposee(n, i, SKINPOSITION_DIALOG_QUIT, SKINALPHAS_MAINMENU_x, SKINALPHAS_MAINMENU_y);
n.pullNexposee(n, i, eY * (SKINHEIGHT_TITLE * SKINFONTSIZE_TITLE / conheight));
-
+
me.addItem(me, n, '0 0 0', '1 1 0', SKINALPHAS_MAINMENU_z);
me.moveItemAfter(me, n, NULL);
METHOD(XonoticServerList, clickListBoxItem, void(entity, float, vector))
METHOD(XonoticServerList, resizeNotify, void(entity, vector, vector, vector, vector))
METHOD(XonoticServerList, keyDown, float(entity, float, float, float))
+ METHOD(XonoticServerList, toggleFavorite, void(entity, string))
ATTRIB(XonoticServerList, iconsSizeFactor, float, 0.85)
ATTRIB(XonoticServerList, ipAddressBox, entity, NULL)
ATTRIB(XonoticServerList, favoriteButton, entity, NULL)
ATTRIB(XonoticServerList, nextRefreshTime, float, 0)
- METHOD(XonoticServerList, refreshServerList, void(entity, float)) // refresh mode: 0 = just reparametrize, 1 = send new requests, 2 = clear
+ METHOD(XonoticServerList, refreshServerList, void(entity, float)) // refresh mode: REFRESHSERVERLIST_*
ATTRIB(XonoticServerList, needsRefresh, float, 1)
METHOD(XonoticServerList, focusEnter, void(entity))
METHOD(XonoticServerList, positionSortButton, void(entity, entity, float, float, string, void(entity, entity)))
ATTRIB(XonoticServerList, seenIPv4, float, 0)
ATTRIB(XonoticServerList, seenIPv6, float, 0)
+ ATTRIB(XonoticServerList, categoriesHeight, float, 1.25)
+
+ METHOD(XonoticServerList, getTotalHeight, float(entity))
+ METHOD(XonoticServerList, getItemAtPos, float(entity, float))
+ METHOD(XonoticServerList, getItemStart, float(entity, float))
+ METHOD(XonoticServerList, getItemHeight, float(entity, float))
ENDCLASS(XonoticServerList)
entity makeXonoticServerList();
+#ifndef IMPLEMENTATION
+float autocvar_menu_slist_categories;
+float autocvar_menu_slist_categories_onlyifmultiple;
+float autocvar_menu_slist_purethreshold;
+float autocvar_menu_slist_modimpurity;
+float autocvar_menu_slist_recommendations;
+float autocvar_menu_slist_recommendations_maxping;
+float autocvar_menu_slist_recommendations_minfreeslots;
+float autocvar_menu_slist_recommendations_minhumans;
+float autocvar_menu_slist_recommendations_purethreshold;
+
+// server cache fields
+#define SLIST_FIELDS \
+ SLIST_FIELD(CNAME, "cname") \
+ SLIST_FIELD(PING, "ping") \
+ SLIST_FIELD(GAME, "game") \
+ SLIST_FIELD(MOD, "mod") \
+ SLIST_FIELD(MAP, "map") \
+ SLIST_FIELD(NAME, "name") \
+ SLIST_FIELD(MAXPLAYERS, "maxplayers") \
+ SLIST_FIELD(NUMPLAYERS, "numplayers") \
+ SLIST_FIELD(NUMHUMANS, "numhumans") \
+ SLIST_FIELD(NUMBOTS, "numbots") \
+ SLIST_FIELD(PROTOCOL, "protocol") \
+ SLIST_FIELD(FREESLOTS, "freeslots") \
+ SLIST_FIELD(PLAYERS, "players") \
+ SLIST_FIELD(QCSTATUS, "qcstatus") \
+ SLIST_FIELD(CATEGORY, "category") \
+ SLIST_FIELD(ISFAVORITE, "isfavorite")
+
+#define SLIST_FIELD(suffix,name) float SLIST_FIELD_##suffix;
+SLIST_FIELDS
+#undef SLIST_FIELD
+
+const float REFRESHSERVERLIST_RESORT = 0; // sort the server list again to update for changes to e.g. favorite status, categories
+const float REFRESHSERVERLIST_REFILTER = 1; // ..., also update filter and sort criteria
+const float REFRESHSERVERLIST_ASK = 2; // ..., also suggest querying servers now
+const float REFRESHSERVERLIST_RESET = 3; // ..., also clear the list first
+
+// function declarations
+float IsServerInList(string list, string srv);
+#define IsFavorite(srv) IsServerInList(cvar_string("net_slist_favorites"), srv)
+#define IsPromoted(srv) IsServerInList(_Nex_ExtResponseSystem_PromotedServers, srv)
+#define IsRecommended(srv) IsServerInList(_Nex_ExtResponseSystem_RecommendedServers, srv)
+
+entity RetrieveCategoryEnt(float catnum);
+
+float CheckCategoryOverride(float cat);
+float CheckCategoryForEntry(float entry);
+float m_gethostcachecategory(float entry) { return CheckCategoryOverride(CheckCategoryForEntry(entry)); }
+
+void RegisterSLCategories();
+
void ServerList_Connect_Click(entity btn, entity me);
+void ServerList_Categories_Click(entity box, entity me);
void ServerList_ShowEmpty_Click(entity box, entity me);
void ServerList_ShowFull_Click(entity box, entity me);
void ServerList_Filter_Change(entity box, entity me);
void ServerList_Info_Click(entity btn, entity me);
void ServerList_Update_favoriteButton(entity btn, entity me);
-#ifndef IMPLEMENTATION
-float SLIST_FIELD_CNAME;
-float SLIST_FIELD_PING;
-float SLIST_FIELD_GAME;
-float SLIST_FIELD_MOD;
-float SLIST_FIELD_MAP;
-float SLIST_FIELD_NAME;
-float SLIST_FIELD_MAXPLAYERS;
-float SLIST_FIELD_NUMPLAYERS;
-float SLIST_FIELD_NUMHUMANS;
-float SLIST_FIELD_NUMBOTS;
-float SLIST_FIELD_PROTOCOL;
-float SLIST_FIELD_FREESLOTS;
-float SLIST_FIELD_PLAYERS;
-float SLIST_FIELD_QCSTATUS;
-float SLIST_FIELD_ISFAVORITE;
-#endif
+// fields for category entities
+#define MAX_CATEGORIES 9
+#define CATEGORY_FIRST 1
+entity categories[MAX_CATEGORIES];
+float category_ent_count;
+.string cat_name;
+.string cat_string;
+.string cat_enoverride_string;
+.string cat_dioverride_string;
+.float cat_enoverride;
+.float cat_dioverride;
+
+// fields for drawing categories
+float category_name[MAX_CATEGORIES];
+float category_item[MAX_CATEGORIES];
+float category_draw_count;
+
+#define SLIST_CATEGORIES \
+ SLIST_CATEGORY(CAT_FAVORITED, "", "", ZCTX(_("SLCAT^Favorites"))) \
+ SLIST_CATEGORY(CAT_RECOMMENDED, "", "", ZCTX(_("SLCAT^Recommended"))) \
+ SLIST_CATEGORY(CAT_NORMAL, "", "CAT_SERVERS", ZCTX(_("SLCAT^Normal Servers"))) \
+ SLIST_CATEGORY(CAT_SERVERS, "CAT_NORMAL", "CAT_SERVERS", ZCTX(_("SLCAT^Servers"))) \
+ SLIST_CATEGORY(CAT_XPM, "CAT_NORMAL", "CAT_SERVERS", ZCTX(_("SLCAT^Competitive Mode"))) \
+ SLIST_CATEGORY(CAT_MODIFIED, "", "CAT_SERVERS", ZCTX(_("SLCAT^Modified Servers"))) \
+ SLIST_CATEGORY(CAT_OVERKILL, "", "CAT_SERVERS", ZCTX(_("SLCAT^Overkill Mode"))) \
+ SLIST_CATEGORY(CAT_MINSTAGIB, "", "CAT_SERVERS", ZCTX(_("SLCAT^MinstaGib Mode"))) \
+ SLIST_CATEGORY(CAT_DEFRAG, "", "CAT_SERVERS", ZCTX(_("SLCAT^Defrag Mode")))
+
+#define SLIST_CATEGORY_AUTOCVAR(name) autocvar_menu_slist_categories_##name##_override
+#define SLIST_CATEGORY(name,enoverride,dioverride,str) \
+ float name; \
+ var string SLIST_CATEGORY_AUTOCVAR(name) = enoverride;
+SLIST_CATEGORIES
+#undef SLIST_CATEGORY
#endif
-
+#endif
#ifdef IMPLEMENTATION
-void ServerList_UpdateFieldIDs()
+
+void RegisterSLCategories()
{
- SLIST_FIELD_CNAME = gethostcacheindexforkey( "cname" );
- SLIST_FIELD_PING = gethostcacheindexforkey( "ping" );
- SLIST_FIELD_GAME = gethostcacheindexforkey( "game" );
- SLIST_FIELD_MOD = gethostcacheindexforkey( "mod" );
- SLIST_FIELD_MAP = gethostcacheindexforkey( "map" );
- SLIST_FIELD_NAME = gethostcacheindexforkey( "name" );
- SLIST_FIELD_MAXPLAYERS = gethostcacheindexforkey( "maxplayers" );
- SLIST_FIELD_NUMPLAYERS = gethostcacheindexforkey( "numplayers" );
- SLIST_FIELD_NUMHUMANS = gethostcacheindexforkey( "numhumans" );
- SLIST_FIELD_NUMBOTS = gethostcacheindexforkey( "numbots" );
- SLIST_FIELD_PROTOCOL = gethostcacheindexforkey( "protocol" );
- SLIST_FIELD_FREESLOTS = gethostcacheindexforkey( "freeslots" );
- SLIST_FIELD_PLAYERS = gethostcacheindexforkey( "players" );
- SLIST_FIELD_QCSTATUS = gethostcacheindexforkey( "qcstatus" );
- SLIST_FIELD_ISFAVORITE = gethostcacheindexforkey( "isfavorite" );
-}
-
-float IsFavorite(string srv)
+ entity cat;
+ #define SLIST_CATEGORY(name,enoverride,dioverride,str) \
+ SET_FIELD_COUNT(name, CATEGORY_FIRST, category_ent_count) \
+ CHECK_MAX_COUNT(name, MAX_CATEGORIES, category_ent_count, "SLIST_CATEGORY") \
+ cat = spawn(); \
+ categories[name - 1] = cat; \
+ cat.classname = "slist_category"; \
+ cat.cat_name = strzone(#name); \
+ cat.cat_enoverride_string = strzone(SLIST_CATEGORY_AUTOCVAR(name)); \
+ cat.cat_dioverride_string = strzone(dioverride); \
+ cat.cat_string = strzone(str);
+ SLIST_CATEGORIES
+ #undef SLIST_CATEGORY
+
+ float i, x, catnum;
+ string s;
+
+ #define PROCESS_OVERRIDE(override_string,override_field) \
+ for(i = 0; i < category_ent_count; ++i) \
+ { \
+ s = categories[i].override_string; \
+ if((s != "") && (s != categories[i].cat_name)) \
+ { \
+ catnum = 0; \
+ for(x = 0; x < category_ent_count; ++x) \
+ { if(categories[x].cat_name == s) { \
+ catnum = (x+1); \
+ break; \
+ } } \
+ if(catnum) \
+ { \
+ strunzone(categories[i].override_string); \
+ categories[i].override_field = catnum; \
+ continue; \
+ } \
+ else \
+ { \
+ print(sprintf( \
+ "RegisterSLCategories(): Improper override '%s' for category '%s'!\n", \
+ s, \
+ categories[i].cat_name \
+ )); \
+ } \
+ } \
+ strunzone(categories[i].override_string); \
+ categories[i].override_field = 0; \
+ }
+ PROCESS_OVERRIDE(cat_enoverride_string, cat_enoverride)
+ PROCESS_OVERRIDE(cat_dioverride_string, cat_dioverride)
+ #undef PROCESS_OVERRIDE
+}
+
+// Supporting Functions
+entity RetrieveCategoryEnt(float catnum)
+{
+ if((catnum > 0) && (catnum <= category_ent_count))
+ {
+ return categories[catnum - 1];
+ }
+ else
+ {
+ error(sprintf("RetrieveCategoryEnt(%d): Improper category number!\n", catnum));
+ return world;
+ }
+}
+
+float IsServerInList(string list, string srv)
{
string p;
float i, n;
if(srv == "")
return FALSE;
p = crypto_getidfp(srv);
- n = tokenize_console(cvar_string("net_slist_favorites"));
+ n = tokenize_console(list);
for(i = 0; i < n; ++i)
{
if(substring(argv(i), 0, 1) != "[" && strlen(argv(i)) == 44 && strstrofs(argv(i), ".", 0) < 0)
return FALSE;
}
-void ToggleFavorite(string srv)
+float CheckCategoryOverride(float cat)
+{
+ entity catent = RetrieveCategoryEnt(cat);
+ if(catent)
+ {
+ float override = (autocvar_menu_slist_categories ? catent.cat_enoverride : catent.cat_dioverride);
+ if(override) { return override; }
+ else { return cat; }
+ }
+ else
+ {
+ error(sprintf("CheckCategoryOverride(%d): Improper category number!\n", cat));
+ return cat;
+ }
+}
+
+float CheckCategoryForEntry(float entry)
+{
+ string s, k, v, modtype = "";
+ float j, m, impure = 0, freeslots = 0, sflags = 0;
+ s = gethostcachestring(SLIST_FIELD_QCSTATUS, entry);
+ m = tokenizebyseparator(s, ":");
+
+ for(j = 2; j < m; ++j)
+ {
+ if(argv(j) == "") { break; }
+ k = substring(argv(j), 0, 1);
+ v = substring(argv(j), 1, -1);
+ switch(k)
+ {
+ case "P": { impure = stof(v); break; }
+ case "S": { freeslots = stof(v); break; }
+ case "F": { sflags = stof(v); break; }
+ case "M": { modtype = strtolower(v); break; }
+ }
+ }
+
+ if(modtype != "xonotic") { impure += autocvar_menu_slist_modimpurity; }
+
+ // check if this server is favorited
+ if(gethostcachenumber(SLIST_FIELD_ISFAVORITE, entry)) { return CAT_FAVORITED; }
+
+ // now check if it's recommended
+ if(autocvar_menu_slist_recommendations)
+ {
+ string cname = gethostcachestring(SLIST_FIELD_CNAME, entry);
+
+ if(IsPromoted(cname)) { return CAT_RECOMMENDED; }
+ else
+ {
+ float recommended = 0;
+ if(autocvar_menu_slist_recommendations & 1)
+ {
+ if(IsRecommended(cname)) { ++recommended; }
+ else { --recommended; }
+ }
+ if(autocvar_menu_slist_recommendations & 2)
+ {
+ if(
+ ///// check for minimum free slots
+ (freeslots >= autocvar_menu_slist_recommendations_minfreeslots)
+
+ && // check for purity requirement
+ (
+ (autocvar_menu_slist_recommendations_purethreshold < 0)
+ ||
+ (impure <= autocvar_menu_slist_recommendations_purethreshold)
+ )
+
+ && // check for minimum amount of humans
+ (
+ gethostcachenumber(SLIST_FIELD_NUMHUMANS, entry)
+ >=
+ autocvar_menu_slist_recommendations_minhumans
+ )
+
+ && // check for maximum latency
+ (
+ gethostcachenumber(SLIST_FIELD_PING, entry)
+ <=
+ autocvar_menu_slist_recommendations_maxping
+ )
+ )
+ { ++recommended; }
+ else
+ { --recommended; }
+ }
+ if(recommended > 0) { return CAT_RECOMMENDED; }
+ }
+ }
+
+ // if not favorited or recommended, check modname
+ if(modtype != "xonotic")
+ {
+ switch(modtype)
+ {
+ // old servers which don't report their mod name are considered modified now
+ case "": { return CAT_MODIFIED; }
+
+ case "xpm": { return CAT_XPM; }
+ case "minstagib": { return CAT_MINSTAGIB; }
+ case "overkill": { return CAT_OVERKILL; }
+ //case "nix": { return CAT_NIX; }
+ //case "newtoys": { return CAT_NEWTOYS; }
+
+ // "cts" is allowed as compat, xdf is replacement
+ case "cts":
+ case "xdf": { return CAT_DEFRAG; }
+
+ default: { dprint(sprintf("Found strange mod type: %s\n", modtype)); return CAT_MODIFIED; }
+ }
+ }
+
+ // must be normal or impure server
+ return ((impure > autocvar_menu_slist_purethreshold) ? CAT_MODIFIED : CAT_NORMAL);
+}
+
+void XonoticServerList_toggleFavorite(entity me, string srv)
{
string s, s0, s1, s2, srv_resolved, p;
float i, n, f;
f = 1;
--i;
}
-
+
if(!f)
{
s1 = "";
cvar_set("net_slist_favorites", strcat(s, s1, srv));
}
- resorthostcache();
+ me.refreshServerList(me, REFRESHSERVERLIST_RESORT);
}
void ServerList_Update_favoriteButton(entity btn, entity me)
{
- if(IsFavorite(me.ipAddressBox.text))
- me.favoriteButton.setText(me.favoriteButton, _("Remove"));
- else
- me.favoriteButton.setText(me.favoriteButton, _("Bookmark"));
+ me.favoriteButton.setText(me.favoriteButton,
+ (IsFavorite(me.ipAddressBox.text) ?
+ _("Remove") : _("Favorite")
+ )
+ );
}
entity makeXonoticServerList()
{
me.configureXonoticListBox(me);
- ServerList_UpdateFieldIDs();
+ // update field ID's
+ #define SLIST_FIELD(suffix,name) SLIST_FIELD_##suffix = gethostcacheindexforkey(name);
+ SLIST_FIELDS
+ #undef SLIST_FIELD
+ // clear list
me.nItems = 0;
}
void XonoticServerList_setSelected(entity me, float i)
}
void XonoticServerList_refreshServerList(entity me, float mode)
{
- // 0: just reparametrize
- // 1: also ask for new servers
- // 2: clear
//print("refresh of type ", ftos(mode), "\n");
- /* if(mode == 2) // borken
- {
- // clear list
- localcmd("net_slist\n");
- me.needsRefresh = 1; // net_slist kills sort order, so we need to restore it later
- }
- else */
+
+ if(mode >= REFRESHSERVERLIST_REFILTER)
{
- float m, o, i, n; // moin moin
+ float m, i, n;
+ float listflags = 0;
string s, typestr, modstr;
+
s = me.filterString;
m = strstrofs(s, ":", 0);
sethostcachemaskstring(++m, SLIST_FIELD_PLAYERS, s, SLIST_TEST_CONTAINS);
sethostcachemaskstring(++m, SLIST_FIELD_QCSTATUS, strcat(s, ":"), SLIST_TEST_STARTSWITH);
}
- o = 2; // favorites first
- if(me.currentSortOrder < 0)
- o |= 1; // descending
- sethostcachesort(me.currentSortField, o);
- resorthostcache();
- if(mode >= 1)
- refreshhostcache();
+
+ // sorting flags
+ //listflags |= SLSF_FAVORITES;
+ listflags |= SLSF_CATEGORIES;
+ if(me.currentSortOrder < 0) { listflags |= SLSF_DESCENDING; }
+ sethostcachesort(me.currentSortField, listflags);
}
+
+ resorthostcache();
+ if(mode >= REFRESHSERVERLIST_ASK)
+ refreshhostcache(mode >= REFRESHSERVERLIST_RESET);
}
void XonoticServerList_focusEnter(entity me)
{
return;
}
me.nextRefreshTime = time + 10;
- me.refreshServerList(me, 1);
+ me.refreshServerList(me, REFRESHSERVERLIST_ASK);
}
+
void XonoticServerList_draw(entity me)
{
float i, found, owned;
_Nex_ExtResponseSystem_BannedServersNeedsRefresh = 0;
}
+ if(_Nex_ExtResponseSystem_PromotedServersNeedsRefresh)
+ {
+ if(!me.needsRefresh)
+ me.needsRefresh = 3;
+ _Nex_ExtResponseSystem_PromotedServersNeedsRefresh = 0;
+ }
+
+ if(_Nex_ExtResponseSystem_RecommendedServersNeedsRefresh)
+ {
+ if(!me.needsRefresh)
+ me.needsRefresh = 3;
+ _Nex_ExtResponseSystem_RecommendedServersNeedsRefresh = 0;
+ }
+
if(me.currentSortField == -1)
{
me.setSortOrder(me, SLIST_FIELD_PING, +1);
- me.refreshServerList(me, 2);
+ me.refreshServerList(me, REFRESHSERVERLIST_RESET);
}
else if(me.needsRefresh == 1)
{
else if(me.needsRefresh == 2)
{
me.needsRefresh = 0;
- me.refreshServerList(me, 0);
+ me.refreshServerList(me, REFRESHSERVERLIST_REFILTER);
+ }
+ else if(me.needsRefresh == 3)
+ {
+ me.needsRefresh = 0;
+ me.refreshServerList(me, REFRESHSERVERLIST_RESORT);
}
owned = ((me.selectedServer == me.ipAddressBox.text) && (me.ipAddressBox.text != ""));
- me.nItems = gethostcachevalue(SLIST_HOSTCACHEVIEWCOUNT);
+ for(i = 0; i < category_draw_count; ++i) { category_name[i] = -1; category_item[i] = -1; }
+ category_draw_count = 0;
+
+ if(autocvar_menu_slist_categories >= 0) // if less than 0, don't even draw a category heading for favorites
+ {
+ float itemcount = gethostcachevalue(SLIST_HOSTCACHEVIEWCOUNT);
+ me.nItems = itemcount;
+
+ //float visible = floor(me.scrollPos / me.itemHeight);
+ // ^ unfortunately no such optimization can be made-- we must process through the
+ // entire list, otherwise there is no way to know which item is first in its category.
+
+ // binary search method suggested by div
+ float x;
+ float begin = 0;
+ for(x = 1; x <= category_ent_count; ++x) {
+ float first = begin;
+ float last = (itemcount - 1);
+ if (first > last) {
+ // List is empty.
+ break;
+ }
+ float catf = gethostcachenumber(SLIST_FIELD_CATEGORY, first);
+ float catl = gethostcachenumber(SLIST_FIELD_CATEGORY, last);
+ if (catf > x) {
+ // The first one is already > x.
+ // Therefore, category x does not exist.
+ // Higher numbered categories do exist though.
+ } else if (catl < x) {
+ // The last one is < x.
+ // Thus this category - and any following -
+ // don't exist.
+ break;
+ } else if (catf == x) {
+ // Starts at first. This breaks the loop
+ // invariant in the binary search and thus has
+ // to be handled separately.
+ if(gethostcachenumber(SLIST_FIELD_CATEGORY, first) != x)
+ error("Category mismatch I");
+ if(first > 0)
+ if(gethostcachenumber(SLIST_FIELD_CATEGORY, first - 1) == x)
+ error("Category mismatch II");
+ category_name[category_draw_count] = x;
+ category_item[category_draw_count] = first;
+ ++category_draw_count;
+ begin = first + 1;
+ } else {
+ // At this point, catf <= x < catl, thus
+ // catf < catl, thus first < last.
+ // INVARIANTS:
+ // last - first >= 1
+ // catf == gethostcachenumber(SLIST_FIELD_CATEGORY(first)
+ // catl == gethostcachenumber(SLIST_FIELD_CATEGORY(last)
+ // catf < x
+ // catl >= x
+ while (last - first > 1) {
+ float middle = floor((first + last) / 2);
+ // By loop condition, middle != first && middle != last.
+ float cat = gethostcachenumber(SLIST_FIELD_CATEGORY, middle);
+ if (cat >= x) {
+ last = middle;
+ catl = cat;
+ } else {
+ first = middle;
+ catf = cat;
+ }
+ }
+ if (catl == x) {
+ if(gethostcachenumber(SLIST_FIELD_CATEGORY, last) != x)
+ error("Category mismatch III");
+ if(last > 0)
+ if(gethostcachenumber(SLIST_FIELD_CATEGORY, last - 1) == x)
+ error("Category mismatch IV");
+ category_name[category_draw_count] = x;
+ category_item[category_draw_count] = last;
+ ++category_draw_count;
+ begin = last + 1; // already scanned through these, skip 'em
+ }
+ else
+ begin = last; // already scanned through these, skip 'em
+ }
+ }
+ if(autocvar_menu_slist_categories_onlyifmultiple && (category_draw_count == 1))
+ {
+ category_name[0] = -1;
+ category_item[0] = -1;
+ category_draw_count = 0;
+ me.nItems = itemcount;
+ }
+ }
+ else { me.nItems = gethostcachevalue(SLIST_HOSTCACHEVIEWCOUNT); }
me.connectButton.disabled = ((me.nItems == 0) && (me.ipAddressBox.text == ""));
me.infoButton.disabled = ((me.nItems == 0) || !owned);
if(me.selectedServer)
{
for(i = 0; i < me.nItems; ++i)
+ {
if(gethostcachestring(SLIST_FIELD_CNAME, i) == me.selectedServer)
{
if(i != me.selectedItem)
found = 1;
break;
}
+ }
}
if(!found)
+ {
if(me.nItems > 0)
{
if(me.selectedItem >= me.nItems)
strunzone(me.selectedServer);
me.selectedServer = strzone(gethostcachestring(SLIST_FIELD_CNAME, me.selectedItem));
}
-
+ }
+
if(owned)
{
if(me.selectedServer != me.ipAddressBox.text)
me.filterString = strzone(box.text);
else
me.filterString = string_null;
- me.refreshServerList(me, 0);
+ me.refreshServerList(me, REFRESHSERVERLIST_REFILTER);
+
+ me.ipAddressBox.setText(me.ipAddressBox, "");
+ me.ipAddressBox.cursorPos = 0;
+ me.ipAddressBoxFocused = -1;
+}
+void ServerList_Categories_Click(entity box, entity me)
+{
+ box.setChecked(box, autocvar_menu_slist_categories = !autocvar_menu_slist_categories);
+ me.refreshServerList(me, REFRESHSERVERLIST_RESORT);
me.ipAddressBox.setText(me.ipAddressBox, "");
me.ipAddressBox.cursorPos = 0;
void ServerList_ShowEmpty_Click(entity box, entity me)
{
box.setChecked(box, me.filterShowEmpty = !me.filterShowEmpty);
- me.refreshServerList(me, 0);
+ me.refreshServerList(me, REFRESHSERVERLIST_REFILTER);
me.ipAddressBox.setText(me.ipAddressBox, "");
me.ipAddressBox.cursorPos = 0;
void ServerList_ShowFull_Click(entity box, entity me)
{
box.setChecked(box, me.filterShowFull = !me.filterShowFull);
- me.refreshServerList(me, 0);
+ me.refreshServerList(me, REFRESHSERVERLIST_REFILTER);
me.ipAddressBox.setText(me.ipAddressBox, "");
me.ipAddressBox.cursorPos = 0;
if(me.selectedServer)
strunzone(me.selectedServer);
me.selectedServer = string_null;
- me.refreshServerList(me, 0);
+ me.refreshServerList(me, REFRESHSERVERLIST_REFILTER);
}
void XonoticServerList_positionSortButton(entity me, entity btn, float theOrigin, float theSize, string theTitle, void(entity, entity) theFunc)
{
}
void ServerList_Connect_Click(entity btn, entity me)
{
- if(me.ipAddressBox.text == "")
- localcmd("connect ", me.selectedServer, "\n");
- else
- localcmd("connect ", me.ipAddressBox.text, "\n");
+ localcmd(sprintf("connect %s\n",
+ ((me.ipAddressBox.text != "") ?
+ me.ipAddressBox.text : me.selectedServer
+ )
+ ));
}
void ServerList_Favorite_Click(entity btn, entity me)
{
ipstr = netaddress_resolve(me.ipAddressBox.text, 26000);
if(ipstr != "")
{
- ToggleFavorite(me.ipAddressBox.text);
+ me.toggleFavorite(me, me.ipAddressBox.text);
me.ipAddressBoxFocused = -1;
}
}
void ServerList_Info_Click(entity btn, entity me)
{
- main.serverInfoDialog.loadServerInfo(main.serverInfoDialog, me.selectedItem);
+ if (me.nItems != 0)
+ main.serverInfoDialog.loadServerInfo(main.serverInfoDialog, me.selectedItem);
DialogOpenButton_Click(me, main.serverInfoDialog);
}
void XonoticServerList_clickListBoxItem(entity me, float i, vector where)
float m, pure, freeslots, j, sflags;
string s, typestr, versionstr, k, v, modname;
+ //print(sprintf("time: %f, i: %d, item: %d, nitems: %d\n", time, i, item, me.nItems));
+
+ vector oldscale = draw_scale;
+ vector oldshift = draw_shift;
+#define SET_YRANGE(start,end) \
+ draw_scale = boxToGlobalSize(eX * 1 + eY * (end - start), oldscale); \
+ draw_shift = boxToGlobal(eY * start, oldshift, oldscale);
+
+ for (j = 0; j < category_draw_count; ++j) {
+ // Matches exactly the headings with increased height.
+ if (i == category_item[j])
+ break;
+ }
+
+ if (j < category_draw_count)
+ {
+ entity catent = RetrieveCategoryEnt(category_name[j]);
+ if(catent)
+ {
+ SET_YRANGE(
+ (me.categoriesHeight - 1) / (me.categoriesHeight + 1),
+ me.categoriesHeight / (me.categoriesHeight + 1)
+ );
+ draw_Text(
+ eY * me.realUpperMargin
+ +
+#if 0
+ eX * (me.columnNameOrigin + (me.columnNameSize - draw_TextWidth(catent.cat_string, 0, me.realFontSize)) * 0.5),
+ catent.cat_string,
+#else
+ eX * (me.columnNameOrigin),
+ strcat(catent.cat_string, ":"),
+#endif
+ me.realFontSize,
+ '1 1 1',
+ SKINALPHA_TEXT,
+ 0
+ );
+ SET_YRANGE(me.categoriesHeight / (me.categoriesHeight + 1), 1);
+ }
+ }
+
if(isSelected)
draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_SELECTED, SKINALPHA_LISTBOX_SELECTED);
theAlpha = SKINALPHA_SERVERLIST_FULL;
else if(freeslots == 0)
theAlpha = SKINALPHA_SERVERLIST_FULL; // g_maxplayers support
- else if not(gethostcachenumber(SLIST_FIELD_NUMHUMANS, i))
+ else if (!gethostcachenumber(SLIST_FIELD_NUMHUMANS, i))
theAlpha = SKINALPHA_SERVERLIST_EMPTY;
else
theAlpha = 1;
// 4: AES recommended and will be used
// 5: AES required
- {
- vector iconSize = '0 0 0';
- iconSize_y = me.realFontSize_y * me.iconsSizeFactor;
- iconSize_x = me.realFontSize_x * me.iconsSizeFactor;
-
- vector iconPos = '0 0 0';
- iconPos_x = (me.columnIconsSize - 3 * iconSize_x) * 0.5;
- iconPos_y = (1 - iconSize_y) * 0.5;
+ // --------------
+ // RENDER ICONS
+ // --------------
+ vector iconSize = '0 0 0';
+ iconSize_y = me.realFontSize_y * me.iconsSizeFactor;
+ iconSize_x = me.realFontSize_x * me.iconsSizeFactor;
- string n;
+ vector iconPos = '0 0 0';
+ iconPos_x = (me.columnIconsSize - 3 * iconSize_x) * 0.5;
+ iconPos_y = (1 - iconSize_y) * 0.5;
- if (!(me.seenIPv4 && me.seenIPv6))
- {
- iconPos_x += iconSize_x * 0.5;
- }
- else if(me.seenIPv4 && me.seenIPv6)
- {
- n = string_null;
- if(isv6)
- draw_PreloadPictureWithFlags(n = strcat(SKINGFX_SERVERLIST_ICON, "_ipv6"), 0); // PRECACHE_PIC_MIPMAP
- else if(isv4)
- draw_PreloadPictureWithFlags(n = strcat(SKINGFX_SERVERLIST_ICON, "_ipv4"), 0); // PRECACHE_PIC_MIPMAP
- if(n)
- draw_Picture(iconPos, n, iconSize, '1 1 1', 1);
- iconPos_x += iconSize_x;
- }
+ string n;
- if not(me.seenIPv4 && me.seenIPv6)
- if(q > 0)
- {
- draw_PreloadPictureWithFlags(n = strcat(SKINGFX_SERVERLIST_ICON, "_aeslevel", ftos(q)), 0); // PRECACHE_PIC_MIPMAP
++ if (!(me.seenIPv4 && me.seenIPv6))
+ {
+ iconPos_x += iconSize_x * 0.5;
+ }
+ else if(me.seenIPv4 && me.seenIPv6)
+ {
+ n = string_null;
+ if(isv6)
+ draw_PreloadPictureWithFlags(n = strcat(SKINGFX_SERVERLIST_ICON, "_ipv6"), 0); // PRECACHE_PIC_MIPMAP
+ else if(isv4)
+ draw_PreloadPictureWithFlags(n = strcat(SKINGFX_SERVERLIST_ICON, "_ipv4"), 0); // PRECACHE_PIC_MIPMAP
+ if(n)
draw_Picture(iconPos, n, iconSize, '1 1 1', 1);
- }
iconPos_x += iconSize_x;
+ }
- if(modname == "Xonotic")
- {
- if(pure == 0)
- {
- draw_PreloadPictureWithFlags(n = strcat(SKINGFX_SERVERLIST_ICON, "_pure1"), PRECACHE_PIC_MIPMAP);
- draw_Picture(iconPos, n, iconSize, '1 1 1', 1);
- }
- }
- else
- {
- draw_PreloadPictureWithFlags(n = strcat(SKINGFX_SERVERLIST_ICON, "_mod_", modname), PRECACHE_PIC_MIPMAP);
- if(draw_PictureSize(n) == '0 0 0')
- draw_PreloadPictureWithFlags(n = strcat(SKINGFX_SERVERLIST_ICON, "_mod_"), PRECACHE_PIC_MIPMAP);
- if(pure == 0)
- draw_Picture(iconPos, n, iconSize, '1 1 1', 1);
- else
- draw_Picture(iconPos, n, iconSize, '1 1 1', SKINALPHA_SERVERLIST_ICON_NONPURE);
- }
- iconPos_x += iconSize_x;
+ if(q > 0)
+ {
+ draw_PreloadPictureWithFlags(n = strcat(SKINGFX_SERVERLIST_ICON, "_aeslevel", ftos(q)), 0); // PRECACHE_PIC_MIPMAP
+ draw_Picture(iconPos, n, iconSize, '1 1 1', 1);
+ }
+ iconPos_x += iconSize_x;
- if(sflags >= 0 && (sflags & SERVERFLAG_PLAYERSTATS))
+ if(modname == "Xonotic")
+ {
+ if(pure == 0)
{
- draw_PreloadPictureWithFlags(n = strcat(SKINGFX_SERVERLIST_ICON, "_stats1"), 0); // PRECACHE_PIC_MIPMAP
+ draw_PreloadPictureWithFlags(n = strcat(SKINGFX_SERVERLIST_ICON, "_pure1"), PRECACHE_PIC_MIPMAP);
draw_Picture(iconPos, n, iconSize, '1 1 1', 1);
}
- iconPos_x += iconSize_x;
}
+ else
+ {
+ draw_PreloadPictureWithFlags(n = strcat(SKINGFX_SERVERLIST_ICON, "_mod_", modname), PRECACHE_PIC_MIPMAP);
+ if(draw_PictureSize(n) == '0 0 0')
+ draw_PreloadPictureWithFlags(n = strcat(SKINGFX_SERVERLIST_ICON, "_mod_"), PRECACHE_PIC_MIPMAP);
+ if(pure == 0)
+ draw_Picture(iconPos, n, iconSize, '1 1 1', 1);
+ else
+ draw_Picture(iconPos, n, iconSize, '1 1 1', SKINALPHA_SERVERLIST_ICON_NONPURE);
+ }
+ iconPos_x += iconSize_x;
+ if(sflags >= 0 && (sflags & SERVERFLAG_PLAYERSTATS))
+ {
+ draw_PreloadPictureWithFlags(n = strcat(SKINGFX_SERVERLIST_ICON, "_stats1"), 0); // PRECACHE_PIC_MIPMAP
+ draw_Picture(iconPos, n, iconSize, '1 1 1', 1);
+ }
+ iconPos_x += iconSize_x;
+
+ // --------------
+ // RENDER TEXT
+ // --------------
+
+ // ping
s = ftos(p);
draw_Text(me.realUpperMargin * eY + (me.columnPingOrigin + me.columnPingSize - draw_TextWidth(s, 0, me.realFontSize)) * eX, s, me.realFontSize, theColor, theAlpha, 0);
+
+ // server name
s = draw_TextShortenToWidth(gethostcachestring(SLIST_FIELD_NAME, i), me.columnNameSize, 0, me.realFontSize);
draw_Text(me.realUpperMargin * eY + me.columnNameOrigin * eX, s, me.realFontSize, theColor, theAlpha, 0);
+
+ // server map
s = draw_TextShortenToWidth(gethostcachestring(SLIST_FIELD_MAP, i), me.columnMapSize, 0, me.realFontSize);
draw_Text(me.realUpperMargin * eY + (me.columnMapOrigin + (me.columnMapSize - draw_TextWidth(s, 0, me.realFontSize)) * 0.5) * eX, s, me.realFontSize, theColor, theAlpha, 0);
+
+ // server gametype
s = draw_TextShortenToWidth(typestr, me.columnTypeSize, 0, me.realFontSize);
draw_Text(me.realUpperMargin * eY + (me.columnTypeOrigin + (me.columnTypeSize - draw_TextWidth(s, 0, me.realFontSize)) * 0.5) * eX, s, me.realFontSize, theColor, theAlpha, 0);
+
+ // server playercount
s = strcat(ftos(gethostcachenumber(SLIST_FIELD_NUMHUMANS, i)), "/", ftos(gethostcachenumber(SLIST_FIELD_MAXPLAYERS, i)));
draw_Text(me.realUpperMargin * eY + (me.columnPlayersOrigin + (me.columnPlayersSize - draw_TextWidth(s, 0, me.realFontSize)) * 0.5) * eX, s, me.realFontSize, theColor, theAlpha, 0);
}
float XonoticServerList_keyDown(entity me, float scan, float ascii, float shift)
{
- float i;
vector org, sz;
org = boxToGlobal(eY * (me.selectedItem * me.itemHeight - me.scrollPos), me.origin, me.size);
}
else if(scan == K_INS || scan == K_MOUSE3 || scan == K_KP_INS)
{
- i = me.selectedItem;
- if(i < me.nItems)
+ if(me.nItems != 0)
{
- ToggleFavorite(me.selectedServer);
+ me.toggleFavorite(me, me.selectedServer);
me.ipAddressBoxFocused = -1;
return 1;
}
else
return me.controlledTextbox.keyDown(me.controlledTextbox, scan, ascii, shift);
}
+
+float XonoticServerList_getTotalHeight(entity me) {
+ float num_normal_rows = me.nItems;
+ float num_headers = category_draw_count;
+ return me.itemHeight * (num_normal_rows + me.categoriesHeight * num_headers);
+}
+float XonoticServerList_getItemAtPos(entity me, float pos) {
+ pos = pos / me.itemHeight;
+ float i;
+ for (i = category_draw_count - 1; i >= 0; --i) {
+ float itemidx = category_item[i];
+ float itempos = i * me.categoriesHeight + category_item[i];
+ if (pos >= itempos + me.categoriesHeight + 1)
+ return itemidx + 1 + floor(pos - (itempos + me.categoriesHeight + 1));
+ if (pos >= itempos)
+ return itemidx;
+ }
+ // No category matches? Note that category 0 is... 0. Therefore no headings exist at all.
+ return floor(pos);
+}
+float XonoticServerList_getItemStart(entity me, float item) {
+ float i;
+ for (i = category_draw_count - 1; i >= 0; --i) {
+ float itemidx = category_item[i];
+ float itempos = i * me.categoriesHeight + category_item[i];
+ if (item >= itemidx + 1)
+ return (itempos + me.categoriesHeight + 1 + item - (itemidx + 1)) * me.itemHeight;
+ if (item >= itemidx)
+ return itempos * me.itemHeight;
+ }
+ // No category matches? Note that category 0 is... 0. Therefore no headings exist at all.
+ return item * me.itemHeight;
+}
+float XonoticServerList_getItemHeight(entity me, float item) {
+ float i;
+ for (i = 0; i < category_draw_count; ++i) {
+ // Matches exactly the headings with increased height.
+ if (item == category_item[i])
+ return me.itemHeight * (me.categoriesHeight + 1);
+ }
+ return me.itemHeight;
+}
+
#endif
}
}
+void DisableServerBackwardsCompatibility()
+{
+ cvar_set("gameversion_min", ftos(100 * floor(cvar("gameversion") / 100)));
+}
+
void UpdateNotification_URI_Get_Callback(float id, float status, string data)
{
float n;
else
n = tokenizebyseparator(data, "\n");
- if(n >= 1)
+ float i;
+ string s;
+
+ string un_version = "";
+ string un_download = "";
+ string un_url = "";
+ string un_bannedservers = "";
+ string un_emergency_pk3s = "";
+ string un_promoted = "";
+ string un_recommended = "";
+ string un_compatexpire = "";
+
+ for(i = 0; i < n; ++i)
{
- _Nex_ExtResponseSystem_UpdateTo = argv(0);
-
- if(vercmp(cvar_string("g_xonoticversion"), _Nex_ExtResponseSystem_UpdateTo) >= 0)
+ s = substring(argv(i), 2, -1);
+ if(s == "") { continue; } // ignore empty lines
+
+ switch(substring(argv(i), 0, 1))
{
- _Nex_ExtResponseSystem_UpdateTo = ""; // no update needed
- }
- else
- {
- // update needed
- if(n >= 2)
- print(sprintf(_("Update can be downloaded at:\n%s\n"), argv(1)));
- if(n >= 3)
- _Nex_ExtResponseSystem_UpdateToURL = strzone(argv(2));
+ #define APPEND_TO_STRING(list,sep,add) ((list) = (((list) != "") ? strcat(list, sep, add) : (add)))
+ case "V":
+ {
+ un_version = s;
+ break;
+ }
+ case "C":
+ {
+ un_compatexpire = s;
+ break;
+ }
+ case "D":
+ {
+ un_download = s;
+ break;
+ }
+ case "U":
+ {
+ un_url = s;
+ break;
+ }
+ case "B":
+ {
+ APPEND_TO_STRING(un_bannedservers, " ", s);
+ break;
+ }
+ case "E":
+ {
+ if(cvar("menu_updatecheck_getpacks"))
+ APPEND_TO_STRING(un_emergency_pk3s, " ", s);
+ break;
+ }
+ case "P":
+ {
+ APPEND_TO_STRING(un_promoted, " ", s);
+ break;
+ }
+ case "R":
+ {
+ APPEND_TO_STRING(un_recommended, " ", s);
+ break;
+ }
}
+ }
- _Nex_ExtResponseSystem_UpdateTo = strzone(_Nex_ExtResponseSystem_UpdateTo);
-
- if(n >= 4)
+ if(un_version != "")
+ {
+ if(vercmp(cvar_string("g_xonoticversion"), un_version) < 0)
{
- _Nex_ExtResponseSystem_BannedServers = strzone(argv(3));
- _Nex_ExtResponseSystem_BannedServersNeedsRefresh = 1;
+ // update needed
+ _Nex_ExtResponseSystem_UpdateTo = strzone(un_version);
+ if(un_download) { print(sprintf(_("Update can be downloaded at:\n%s\n"), un_download)); }
+ if(un_url) { _Nex_ExtResponseSystem_UpdateToURL = strzone(un_url); }
+ DisableServerBackwardsCompatibility();
}
-
- if(n >= 5)
+ else if(cvar_string("g_xonoticversion") == un_version)
{
- if(cvar("menu_updatecheck_getpacks"))
+ if(un_compatexpire != "")
{
- _Nex_ExtResponseSystem_Packs = strzone(argv(4));
- _Nex_ExtResponseSystem_PacksStep = 1;
+ string curdate = strftime(FALSE, "%Y%m%d%H%M%S");
+ if (strcmp(curdate, un_compatexpire) >= 0)
+ DisableServerBackwardsCompatibility();
}
}
}
+
+ if(un_emergency_pk3s != "")
+ {
+ _Nex_ExtResponseSystem_Packs = strzone(un_emergency_pk3s);
+ _Nex_ExtResponseSystem_PacksStep = 1;
+ }
+
+ if(un_promoted != "")
+ {
+ _Nex_ExtResponseSystem_PromotedServers = strzone(un_promoted);
+ _Nex_ExtResponseSystem_PromotedServersNeedsRefresh = 1;
+ }
+
+ if(un_recommended != "")
+ {
+ _Nex_ExtResponseSystem_RecommendedServers = strzone(un_recommended);
+ _Nex_ExtResponseSystem_RecommendedServersNeedsRefresh = 1;
+ }
}
// END OF URI SYSTEM ////////////////////////////////////////////////////////
// for privacy, munge the start count a little
startcnt = floor((floor(startcnt / 10) + random()) * 10);
- uri = sprintf("http://www.xonotic.org/dl/checkupdate.txt?version=%s&cnt=%d", uri_escape(cvar_string("g_xonoticversion")), startcnt);
-
-#ifdef CVAR_POPCON
- float cvar_handle, popcon_handle;
- float n, i, j;
- string k, s;
- cvar_handle = buf_create();
- buf_cvarlist(cvar_handle, "", "");
- n = buf_getsize(cvar_handle);
- popcon_handle = buf_create();
- for(i= 0, j = 0; i < n; ++i)
- {
- k = bufstr_get(cvar_handle, i);
- if(!(cvar_type(k) & CVAR_TYPEFLAG_SAVED))
- continue;
- s = sprintf("%s=%d", uri_escape(k), cvar_string(k) != cvar_defstring(k));
- bufstr_set(popcon_handle, j, s);
- ++j;
- }
- buf_del(cvar_handle);
- uri_postbuf(
- uri, URI_GET_UPDATENOTIFICATION,
- "application/x-www-form-urlencoded",
- "&",
- popcon_handle
- );
- buf_del(popcon_handle);
-#else
+ uri = sprintf("http://update.xonotic.org/checkupdate.txt?version=%s&cnt=%d", uri_escape(cvar_string("g_xonoticversion")), startcnt);
uri_get(uri, URI_GET_UPDATENOTIFICATION);
-#endif
}
}
boxA = '0.05 0.5 0' + 0.25 * sz_y * eY;
boxB = '0.95 0.5 0' + 1.25 * sz_y * eY;
draw_Fill(boxA, boxB - boxA, '1 1 1', 1);
-
+
boxA += sz * 0.1;
boxB -= sz * 0.1;
draw_Fill(boxA, boxB - boxA, '0.1 0.1 0.1', 1);
draw_CenterText(mid - 1 * line, l1, fs, '1 0 0', 1, 0);
draw_CenterText(mid - 0 * line, l2, fs, '0 0 1', 1, 0);
}
- if not(campaign_name_previous)
+ if (!campaign_name_previous)
campaign_name_previous = strzone(strcat(campaign_name, "x")); // force unequal
if(campaign_name == campaign_name_previous)
{
{
float i;
i = 0;
-
+
#define GAMETYPE(id) if(i++ == cnt) return id;
GAMETYPES
#undef GAMETYPE
unused_float = i;
-
+
return 0;
}
{
float i;
i = 0;
-
+
#define GAMETYPE(id) ++i;
GAMETYPES
#undef GAMETYPE
-
+
return i;
}
string GameType_GetName(float cnt)
{
float i = GameType_GetID(cnt);
-
+
if(i)
return MapInfo_Type_ToText(i);
-
+
return "";
}
string GameType_GetIcon(float cnt)
{
float i = GameType_GetID(cnt);
-
+
if(i)
return strcat("gametype_", MapInfo_Type_ToString(i));
-
+
return "";
}
{
float i = GameType_GetID(cnt);
string s = _MapInfo_GetDefaultEx(i);
-
+
if(i)
{
if(strstrofs(s, "teams", 0) >= 0)
else
return _("free for all");
}
-
+
return _("tuba for all");
}*/
WaypointSprite_PlayerDead();
- if not(g_ca) // don't reset teams when moving a ca player to the spectators
+ if (!g_ca) // don't reset teams when moving a ca player to the spectators
self.team = -1; // move this as it is needed to log the player spectating in eventlog
if(self.killcount != -666)
string s;
// NOTE: we do NOT check crypto_keyfp here, an unsigned ID is fine too for this
- if not(p.crypto_idfp)
+ if (!p.crypto_idfp)
return 0;
// this function allows abbreviated player IDs too!
player_count = 0;
}
+ PlayerInfo_Basic(self);
PlayerScore_Attach(self);
ClientData_Attach();
accuracy_init(self);
if(self.vehicle)
vehicles_exit(VHEF_RELESE);
- if not(IS_CLIENT(self))
+ if (!IS_CLIENT(self))
{
print("Warning: ClientDisconnect without ClientConnect\n");
return;
Fire_ApplyDamage(self);
Fire_ApplyEffect(self);
- if not(g_minstagib)
+ if (!g_minstagib)
{
if (self.items & IT_STRENGTH)
{
self.event_damage(self, self, 1, DEATH_ROT, self.origin, '0 0 0');
}
- if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
+ if (!(self.items & IT_UNLIMITED_WEAPON_AMMO))
self.ammo_fuel = CalcRotRegen(self.ammo_fuel, minf, autocvar_g_balance_fuel_regen, autocvar_g_balance_fuel_regenlinear, regen_mod * frametime * (time > self.pauseregen_finished) * ((self.items & IT_FUEL_REGEN) != 0), maxf, autocvar_g_balance_fuel_rot, autocvar_g_balance_fuel_rotlinear, rot_mod * frametime * (time > self.pauserotfuel_finished), limitf);
}
if (self == self.enemy)
return 0;
- if not(IS_PLAYER(self.enemy))
+ if (!IS_PLAYER(self.enemy))
return 0;
SpectateCopy(self.enemy);
{
// NOTE: chain order is from the highest to the lower entnum (unlike find)
other = findchain(classname, "player");
- if not(other) // no player
+ if (!other) // no player
return FALSE;
entity first = other;
do { other = other.chain; }
while(other && other.team != self.team);
- if not(other)
+ if (!other)
{
other = first;
while(other.team != self.team)
void PlayerUseKey()
{
- if not(IS_PLAYER(self))
+ if (!IS_PLAYER(self))
return;
if(self.vehicle)
if((g_cts || g_race) && self.cvar_cl_allow_uidtracking == 1 && self.cvar_cl_allow_uid2name == 1)
{
- if not(self.stored_netname)
+ if (!self.stored_netname)
self.stored_netname = strzone(uid2name(self.crypto_idfp));
if(self.stored_netname != self.netname)
{