// hit testing/tracing for special effects for the crosshair
set g_trueaim_minrange 44 "TrueAim minimum range (TrueAim adjusts shots so they hit the crosshair point even though the gun is not at the screen center)"
-seta crosshair_hittest 1 "do a crosshair hit evaluation; also, the crosshair is scaled by the given number when aiming at an enemy, and blurred when aiming at a team mate"
+seta crosshair_hittest 1 "do a crosshair hit evaluation, applying effects from the _blur, _scale, and _showipact cvars"
seta crosshair_hittest_blur 1 "blur the crosshair if the shot is obstructed"
+seta crosshair_hittest_scale 1.25 "enlarge crosshair if aiming at an enemy, shrink crosshair if shot is obstructed or aiming at a teammate"
seta crosshair_hittest_showimpact 0 "move the crosshair to the actual impact location if obstructed"
// change color based on special case
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 100
-seta cl_velocityzoom 0 "velocity based zooming of fov, negative values zoom out"
+seta cl_velocityzoom_enabled 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"
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 1
+seta menu_slist_categories 0
seta menu_slist_categories_onlyifmultiple 1
seta menu_slist_purethreshold 0
seta menu_slist_modimpurity 0
cl_decals 1
cl_decals_models 0
cl_decals_fadetime 4
-cl_particles_quality 1
+cl_particles 1
+cl_particles_quality 1.0
cl_damageeffect 1
cl_spawn_point_particles 1
cl_playerdetailreduction 4
hud_powerup 0
r_depthfirst 2
r_drawdecals_drawdistance 500
-r_drawparticles_drawdistance 2000
+r_drawparticles_drawdistance 1500
r_glsl_deluxemapping 1
r_glsl_offsetmapping 0
r_glsl_offsetmapping_reliefmapping 0
cl_decals 1
cl_decals_models 0
+cl_particles 1
cl_decals_fadetime 2
cl_particles_quality 0.4
cl_damageeffect 0
cl_decals 1
cl_decals_models 0
cl_decals_fadetime 2
-cl_particles_quality 1
+cl_particles 1
+cl_particles_quality 0.8
cl_damageeffect 0
cl_spawn_point_particles 0
cl_playerdetailreduction 4
hud_powerup 0
r_depthfirst 0
r_drawdecals_drawdistance 300
-r_drawparticles_drawdistance 1000
+r_drawparticles_drawdistance 750
r_glsl_deluxemapping 0
r_glsl_offsetmapping 0
r_glsl_offsetmapping_reliefmapping 0
cl_decals 1
cl_decals_models 0
cl_decals_fadetime 2
-cl_particles_quality 1
+cl_particles 1
+cl_particles_quality 1.0
cl_damageeffect 1
cl_spawn_point_particles 1
cl_playerdetailreduction 4
cl_decals 0
cl_decals_models 0
+cl_particles 1
cl_decals_fadetime 2
cl_particles_quality 0.4
cl_damageeffect 0
cl_decals 1
cl_decals_models 1
cl_decals_fadetime 10
-cl_particles_quality 1
+cl_particles 1
+cl_particles_quality 1.0
cl_damageeffect 2
cl_spawn_point_particles 1
cl_playerdetailreduction 0
hud_powerup 0.5
r_depthfirst 2
r_drawdecals_drawdistance 500
-r_drawparticles_drawdistance 2000
+r_drawparticles_drawdistance 3000
r_glsl_deluxemapping 1
r_glsl_offsetmapping 1
r_glsl_offsetmapping_reliefmapping 1
cl_decals 1
cl_decals_models 0
cl_decals_fadetime 10
+cl_particles 1
cl_particles_quality 1
cl_damageeffect 1
cl_spawn_point_particles 1
// =================
// gamestart hooks
// =================
+seta cl_matchcount 0 // incremented by cl_hook_gameend and used by playerstats to know when to
alias _cl_hook_gamestart "set _cl_hook_gametype $1; _cl_hook_gamestart_stage2"
alias _cl_hook_gamestart_stage2 "cl_hook_gamestart_all; cl_hook_gamestart_${_cl_hook_gametype}"
alias cl_hook_gamestart_all
alias cl_hook_gamestart_ka
alias cl_hook_gamestart_ft
alias cl_hook_gamestart_inv
-alias cl_hook_gameend
+alias cl_hook_gameend "rpn /cl_matchcount dup load 1 + =" // increase match count every time a game ends
alias cl_hook_activeweapon
alias _sv_hook_gamestart "set _sv_hook_gametype $1; _sv_hook_gamestart_stage2"
// uses "border" images
// uses "closebutton" images
MARGIN_TOP 8
-MARGIN_BOTTOM 12
+MARGIN_BOTTOM 16
MARGIN_LEFT 16
MARGIN_RIGHT 16
MARGIN_COLUMNS 4
COLOR_SKINLIST_TITLE '1 1 1'
COLOR_SKINLIST_AUTHOR '0.6875 0.84375 1'
+// item: demo list
+COLOR_DEMOLIST_SUBDIR '0.5 0.5 0.5'
+
+// item: screenshot list
+COLOR_SCREENSHOTLIST_SUBDIR '0.5 0.5 0.5'
+
//------------------------------------------------------------------------------
// Images (colors multiplied to images)
//------------------------------------------------------------------------------
COLOR_DIALOG_CROSSHAIR '1 1 1'
COLOR_DIALOG_HUD '1 1 1'
COLOR_DIALOG_SERVERINFO '1 1 1'
+COLOR_DIALOG_SCREENSHOTVIEWER '1 1 1'
COLOR_DIALOG_CVARS '1 0 0'
COLOR_DIALOG_HUDCONFIRM '1 0 0'
// uses "border" images
// uses "closebutton" images
MARGIN_TOP 8
-MARGIN_BOTTOM 12
+MARGIN_BOTTOM 16
MARGIN_LEFT 16
MARGIN_RIGHT 16
MARGIN_COLUMNS 4
COLOR_SKINLIST_TITLE '1 1 1'
COLOR_SKINLIST_AUTHOR '0 0.375 0.75'
+// item: demo list
+COLOR_DEMOLIST_SUBDIR '0.5 0.5 0.5'
+
+// item: screenshot list
+COLOR_SCREENSHOTLIST_SUBDIR '0.5 0.5 0.5'
+
//------------------------------------------------------------------------------
// Images (colors multiplied to images)
//------------------------------------------------------------------------------
COLOR_DIALOG_CROSSHAIR '1 1 1'
COLOR_DIALOG_HUD '1 1 1'
COLOR_DIALOG_SERVERINFO '1 1 1'
+COLOR_DIALOG_SCREENSHOTVIEWER '1 1 1'
COLOR_DIALOG_CVARS '1 0 0'
COLOR_DIALOG_HUDCONFIRM '1 0 0'
COLOR_DIALOG_CROSSHAIR '1 1 1'
COLOR_DIALOG_HUD '1 1 1'
COLOR_DIALOG_SERVERINFO '1 1 1'
+COLOR_DIALOG_SCREENSHOTVIEWER '1 1 1'
COLOR_DIALOG_CVARS '1 0 0'
COLOR_DIALOG_HUDCONFIRM '1 0 0'
// uses "border" images
// uses "closebutton" images
MARGIN_TOP 8
-MARGIN_BOTTOM 12
+MARGIN_BOTTOM 16
MARGIN_LEFT 16
MARGIN_RIGHT 16
MARGIN_COLUMNS 4
COLOR_SKINLIST_TITLE '1 1 1'
COLOR_SKINLIST_AUTHOR '0.5 0.5 0.5'
+// item: demo list
+COLOR_DEMOLIST_SUBDIR '0.5 0.5 0.5'
+
+// item: screenshot list
+COLOR_SCREENSHOTLIST_SUBDIR '0.5 0.5 0.5'
+
// item: slider
// uses "slider" images
COLOR_SLIDER_N '1 1 1'
makevectors(view_angles);
- if(autocvar_cl_velocityzoom && autocvar_cl_velocityzoom_type) // _type = 0 disables velocity zoom too
+ if(autocvar_cl_velocityzoom_enabled && autocvar_cl_velocityzoom_type && autocvar_cl_velocityzoom_factor) // _type = 0 disables velocity zoom too
{
if(intermission) { curspeed = 0; }
else
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
}
// 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(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)
var float autocvar_cl_vehicle_spiderbot_cross_alpha = 0.6;
var float autocvar_cl_vehicle_spiderbot_cross_size = 1;
var float autocvar_cl_vehicles_hud_tactical = 1;
-float autocvar_cl_velocityzoom;
+float autocvar_cl_velocityzoom_enabled;
+float autocvar_cl_velocityzoom_factor;
var float autocvar_cl_velocityzoom_type = 3;
float autocvar_cl_velocityzoom_speed;
float autocvar_cl_velocityzoom_time;
float autocvar_crosshair_hitindication_speed;
float autocvar_crosshair_hittest;
float autocvar_crosshair_hittest_blur;
+var float autocvar_crosshair_hittest_scale = 1.25;
float autocvar_crosshair_hittest_showimpact;
float autocvar_crosshair_per_weapon;
float autocvar_crosshair_pickup;
../warpzonelib/common.qh
../warpzonelib/client.qh
+../common/playerstats.qh
../common/teams.qh
../common/util.qh
../common/nades.qh
../common/test.qc
../common/util.qc
+../common/playerstats.qc
../common/notifications.qc
../common/command/markup.qc
../common/command/rpn.qc
((output != "") ? sprintf(", %s", output) : ""));
}
+ return output;
+ }
+ case 3:
+ {
+ string output = "";
+
+ output = count_hours(tmp_hours);
+
+ if(tmp_weeks) { tmp_days += (tmp_weeks * 7); }
+ if(tmp_years) { tmp_days += (tmp_years * 365); }
+ if(tmp_days)
+ {
+ output = sprintf(
+ "%s%s",
+ count_days(tmp_days),
+ ((output != "") ? sprintf(", %s", output) : ""));
+ }
+
return output;
}
}
return "";
}
+float _MapInfo_GetTeamPlayBool(float t)
+{
+ entity e;
+ for(e = MapInfo_Type_first; e; e = e.enemy)
+ if(t == e.items)
+ return e.team;
+ return FALSE;
+}
+
void _MapInfo_Map_ApplyGametypeEx(string s, float pWantedType, float pThisType)
{
string sa, k, v;
.string netname; // game type name as in cvar (with g_ prefix)
.string mdl; // game type short name
.string message; // human readable name
+.float team; // does this gametype support teamplay?
.string model2; // game type defaults
.string gametype_description; // game type description
-#define REGISTER_GAMETYPE(hname,sname,g_name,NAME,defaults,gdescription) \
+#define REGISTER_GAMETYPE(hname,sname,g_name,NAME,gteamplay,defaults,gdescription) \
var float MAPINFO_TYPE_##NAME; \
var entity MapInfo_Type##g_name; \
void RegisterGametypes_##g_name() \
MapInfo_Type##g_name.netname = #g_name; \
MapInfo_Type##g_name.mdl = #sname; \
MapInfo_Type##g_name.message = hname; \
+ MapInfo_Type##g_name.team = gteamplay; \
MapInfo_Type##g_name.model2 = defaults; \
MapInfo_Type##g_name.gametype_description = gdescription; \
if(!MapInfo_Type_first) \
#define IS_GAMETYPE(NAME) \
(MapInfo_LoadedGametype == MAPINFO_TYPE_##NAME)
-REGISTER_GAMETYPE(_("Deathmatch"),dm,g_dm,DEATHMATCH,"timelimit=20 pointlimit=30 leadlimit=0",_("Kill all enemies"));
+REGISTER_GAMETYPE(_("Deathmatch"),dm,g_dm,DEATHMATCH,FALSE,"timelimit=20 pointlimit=30 leadlimit=0",_("Kill all enemies"));
#define g_dm IS_GAMETYPE(DEATHMATCH)
-REGISTER_GAMETYPE(_("Last Man Standing"),lms,g_lms,LMS,"timelimit=20 lives=9 leadlimit=0",_("Survive and kill until the enemies have no lives left"));
+REGISTER_GAMETYPE(_("Last Man Standing"),lms,g_lms,LMS,FALSE,"timelimit=20 lives=9 leadlimit=0",_("Survive and kill until the enemies have no lives left"));
#define g_lms IS_GAMETYPE(LMS)
-REGISTER_GAMETYPE(_("Race"),rc,g_race,RACE,"timelimit=20 qualifying_timelimit=5 laplimit=7 teamlaplimit=15 leadlimit=0",_("Race against other players to the finish line"));
+REGISTER_GAMETYPE(_("Race"),rc,g_race,RACE,FALSE,"timelimit=20 qualifying_timelimit=5 laplimit=7 teamlaplimit=15 leadlimit=0",_("Race against other players to the finish line"));
#define g_race IS_GAMETYPE(RACE)
-REGISTER_GAMETYPE(_("Race CTS"),cts,g_cts,CTS,"timelimit=20 skill=-1",_("Race for fastest time"));
+REGISTER_GAMETYPE(_("Race CTS"),cts,g_cts,CTS,FALSE,"timelimit=20 skill=-1",_("Race for fastest time"));
#define g_cts IS_GAMETYPE(CTS)
-REGISTER_GAMETYPE(_("Team Deathmatch"),tdm,g_tdm,TEAM_DEATHMATCH,"timelimit=20 pointlimit=50 teams=2 leadlimit=0",_("Kill all enemy teammates"));
+REGISTER_GAMETYPE(_("Team Deathmatch"),tdm,g_tdm,TEAM_DEATHMATCH,TRUE,"timelimit=20 pointlimit=50 teams=2 leadlimit=0",_("Kill all enemy teammates"));
#define g_tdm IS_GAMETYPE(TEAM_DEATHMATCH)
-REGISTER_GAMETYPE(_("Capture the Flag"),ctf,g_ctf,CTF,"timelimit=20 caplimit=10 leadlimit=0",_("Find and bring the enemy flag to your base to capture it"));
+REGISTER_GAMETYPE(_("Capture the Flag"),ctf,g_ctf,CTF,TRUE,"timelimit=20 caplimit=10 leadlimit=0",_("Find and bring the enemy flag to your base to capture it"));
#define g_ctf IS_GAMETYPE(CTF)
-REGISTER_GAMETYPE(_("Clan Arena"),ca,g_ca,CA,"timelimit=20 pointlimit=10 leadlimit=0",_("Kill all enemy teammates to win the round"));
+REGISTER_GAMETYPE(_("Clan Arena"),ca,g_ca,CA,TRUE,"timelimit=20 pointlimit=10 leadlimit=0",_("Kill all enemy teammates to win the round"));
#define g_ca IS_GAMETYPE(CA)
-REGISTER_GAMETYPE(_("Domination"),dom,g_domination,DOMINATION,"timelimit=20 pointlimit=200 teams=2 leadlimit=0",_("Capture all the control points to win"));
+REGISTER_GAMETYPE(_("Domination"),dom,g_domination,DOMINATION,TRUE,"timelimit=20 pointlimit=200 teams=2 leadlimit=0",_("Capture all the control points to win"));
#define g_domination IS_GAMETYPE(DOMINATION)
-REGISTER_GAMETYPE(_("Key Hunt"),kh,g_keyhunt,KEYHUNT,"timelimit=20 pointlimit=1000 teams=3 leadlimit=0",_("Gather all the keys to win the round"));
+REGISTER_GAMETYPE(_("Key Hunt"),kh,g_keyhunt,KEYHUNT,TRUE,"timelimit=20 pointlimit=1000 teams=3 leadlimit=0",_("Gather all the keys to win the round"));
#define g_keyhunt IS_GAMETYPE(KEYHUNT)
-REGISTER_GAMETYPE(_("Assault"),as,g_assault,ASSAULT,"timelimit=20",_("Destroy obstacles to find and destroy the enemy power core before time runs out"));
+REGISTER_GAMETYPE(_("Assault"),as,g_assault,ASSAULT,TRUE,"timelimit=20",_("Destroy obstacles to find and destroy the enemy power core before time runs out"));
#define g_assault IS_GAMETYPE(ASSAULT)
-REGISTER_GAMETYPE(_("Onslaught"),ons,g_onslaught,ONSLAUGHT,"timelimit=20",_("Capture control points to reach and destroy the enemy generator"));
+REGISTER_GAMETYPE(_("Onslaught"),ons,g_onslaught,ONSLAUGHT,TRUE,"timelimit=20",_("Capture control points to reach and destroy the enemy generator"));
#define g_onslaught IS_GAMETYPE(ONSLAUGHT)
-REGISTER_GAMETYPE(_("Nexball"),nb,g_nexball,NEXBALL,"timelimit=20 pointlimit=5 leadlimit=0",_("XonSports"));
+REGISTER_GAMETYPE(_("Nexball"),nb,g_nexball,NEXBALL,TRUE,"timelimit=20 pointlimit=5 leadlimit=0",_("XonSports"));
#define g_nexball IS_GAMETYPE(NEXBALL)
-REGISTER_GAMETYPE(_("Freeze Tag"),ft,g_freezetag,FREEZETAG,"timelimit=20 pointlimit=10 teams=2 leadlimit=0",_("Kill enemies to freeze them, stand next to teammates to revive them"));
+REGISTER_GAMETYPE(_("Freeze Tag"),ft,g_freezetag,FREEZETAG,TRUE,"timelimit=20 pointlimit=10 teams=2 leadlimit=0",_("Kill enemies to freeze them, stand next to teammates to revive them"));
#define g_freezetag IS_GAMETYPE(FREEZETAG)
-REGISTER_GAMETYPE(_("Keepaway"),ka,g_keepaway,KEEPAWAY,"timelimit=20 pointlimit=30",_("Hold the ball to get points for kills"));
+REGISTER_GAMETYPE(_("Keepaway"),ka,g_keepaway,KEEPAWAY,TRUE,"timelimit=20 pointlimit=30",_("Hold the ball to get points for kills"));
#define g_keepaway IS_GAMETYPE(KEEPAWAY)
-REGISTER_GAMETYPE(_("Invasion"),inv,g_invasion,INVASION,"pointlimit=50 teams=0",_("Survive against waves of monsters"));
+REGISTER_GAMETYPE(_("Invasion"),inv,g_invasion,INVASION,FALSE,"pointlimit=50 teams=0",_("Survive against waves of monsters"));
#define g_invasion IS_GAMETYPE(INVASION)
const float MAPINFO_FEATURE_WEAPONS = 1; // not defined for minstagib-only maps
// gets a gametype from a string
string _MapInfo_GetDefaultEx(float t);
+float _MapInfo_GetTeamPlayBool(float t);
float MapInfo_Type_FromString(string t);
string MapInfo_Type_Description(float t);
string MapInfo_Type_ToString(float t);
MSG_ANNCE_NOTIF(1, ANNCE_ACHIEVEMENT_AMAZING, CH_INFO, "amazing", VOL_BASEVOICE, ATTEN_NONE) \
MSG_ANNCE_NOTIF(1, ANNCE_ACHIEVEMENT_AWESOME, CH_INFO, "awesome", VOL_BASEVOICE, ATTEN_NONE) \
MSG_ANNCE_NOTIF(1, ANNCE_ACHIEVEMENT_BOTLIKE, CH_INFO, "botlike", VOL_BASEVOICE, ATTEN_NONE) \
- MSG_ANNCE_NOTIF(2, ANNCE_ACHIEVEMENT_ELECTROBITCH, CH_INFO, "electrobitch", VOL_BASEVOICE, ATTEN_NONE) \
+ MSG_ANNCE_NOTIF(1, ANNCE_ACHIEVEMENT_ELECTROBITCH, CH_INFO, "electrobitch", VOL_BASEVOICE, ATTEN_NONE) \
MSG_ANNCE_NOTIF(1, ANNCE_ACHIEVEMENT_IMPRESSIVE, CH_INFO, "impressive", VOL_BASEVOICE, ATTEN_NONE) \
MSG_ANNCE_NOTIF(1, ANNCE_ACHIEVEMENT_YODA, CH_INFO, "yoda", VOL_BASEVOICE, ATTEN_NONE) \
MSG_ANNCE_NOTIF(2, ANNCE_BEGIN, CH_INFO, "begin", VOL_BASEVOICE, ATTEN_NONE) \
--- /dev/null
+#ifdef SVQC
+void PlayerStats_Prematch(void)
+{
+ //foobar
+}
+
+void PlayerStats_GameReport_AddPlayer(entity e)
+{
+ if((PS_GR_OUT_DB < 0) || (e.playerstats_id)) { return; }
+
+ // set up player identification
+ string s = string_null;
+
+ if((e.crypto_idfp != "") && (e.cvar_cl_allow_uidtracking == 1))
+ { s = e.crypto_idfp; }
+ else if(IS_BOT_CLIENT(e))
+ { s = sprintf("bot#%g#%s", skill, e.cleanname); }
+
+ if((s == "") || find(world, playerstats_id, s)) // already have one of the ID - next one can't be tracked then!
+ {
+ if(IS_BOT_CLIENT(e))
+ { s = sprintf("bot#%d", e.playerid); }
+ else
+ { s = sprintf("player#%d", e.playerid); }
+ }
+
+ e.playerstats_id = strzone(s);
+
+ // now add the player to the database
+ string key = sprintf("%s:*", e.playerstats_id);
+ string p = db_get(PS_GR_OUT_DB, key);
+
+ if(p == "")
+ {
+ if(PS_GR_OUT_PL)
+ {
+ db_put(PS_GR_OUT_DB, key, PS_GR_OUT_PL);
+ strunzone(PS_GR_OUT_PL);
+ }
+ else { db_put(PS_GR_OUT_DB, key, "#"); }
+ PS_GR_OUT_PL = strzone(e.playerstats_id);
+ }
+}
+
+void PlayerStats_GameReport_AddTeam(float t)
+{
+ if(PS_GR_OUT_DB < 0) { return; }
+
+ string key = sprintf("%d", t);
+ string p = db_get(PS_GR_OUT_DB, key);
+
+ if(p == "")
+ {
+ if(PS_GR_OUT_TL)
+ {
+ db_put(PS_GR_OUT_DB, key, PS_GR_OUT_TL);
+ strunzone(PS_GR_OUT_TL);
+ }
+ else { db_put(PS_GR_OUT_DB, key, "#"); }
+ PS_GR_OUT_TL = strzone(key);
+ }
+}
+
+void PlayerStats_GameReport_AddEvent(string event_id)
+{
+ if(PS_GR_OUT_DB < 0) { return; }
+
+ string key = sprintf("*:%s", event_id);
+ string p = db_get(PS_GR_OUT_DB, key);
+
+ if(p == "")
+ {
+ if(PS_GR_OUT_EVL)
+ {
+ db_put(PS_GR_OUT_DB, key, PS_GR_OUT_EVL);
+ strunzone(PS_GR_OUT_EVL);
+ }
+ else { db_put(PS_GR_OUT_DB, key, "#"); }
+ PS_GR_OUT_EVL = strzone(event_id);
+ }
+}
+
+// referred to by PS_GR_P_ADDVAL and PS_GR_T_ADDVAL
+float PlayerStats_GameReport_Event(string prefix, string event_id, float value)
+{
+ if((prefix == "") || PS_GR_OUT_DB < 0) { return 0; }
+
+ string key = sprintf("%s:%s", prefix, event_id);
+ float val = stof(db_get(PS_GR_OUT_DB, key));
+ val += value;
+ db_put(PS_GR_OUT_DB, key, ftos(val));
+ return val;
+}
+
+void PlayerStats_GameReport_Accuracy(entity p)
+{
+ entity w;
+ float i;
+
+ for(i = WEP_FIRST; i <= WEP_LAST; ++i)
+ {
+ w = get_weaponinfo(i);
+
+ #define ACCMAC(suffix,field) \
+ PS_GR_P_ADDVAL(p, sprintf("acc-%s-%s", w.netname, suffix), p.accuracy.(field[i-1]));
+
+ ACCMAC("hit", accuracy_hit)
+ ACCMAC("fired", accuracy_fired)
+ ACCMAC("cnt-hit", accuracy_cnt_hit)
+ ACCMAC("cnt-fired", accuracy_cnt_fired)
+ ACCMAC("frags", accuracy_frags)
+
+ #undef ACCMAC
+ }
+}
+
+void PlayerStats_GameReport_FinalizePlayer(entity p)
+{
+ if((p.playerstats_id == "") || PS_GR_OUT_DB < 0) { return; }
+
+ // add global info!
+ if(p.alivetime)
+ {
+ PS_GR_P_ADDVAL(p, PLAYERSTATS_ALIVETIME, time - p.alivetime);
+ p.alivetime = 0;
+ }
+
+ db_put(PS_GR_OUT_DB, sprintf("%s:_playerid", p.playerstats_id), ftos(p.playerid));
+
+ if(p.cvar_cl_allow_uid2name == 1 || IS_BOT_CLIENT(p))
+ db_put(PS_GR_OUT_DB, sprintf("%s:_netname", p.playerstats_id), p.netname);
+
+ if(teamplay)
+ db_put(PS_GR_OUT_DB, sprintf("%s:_team", p.playerstats_id), ftos(p.team));
+
+ if(stof(db_get(PS_GR_OUT_DB, sprintf("%s:%s", p.playerstats_id, PLAYERSTATS_ALIVETIME))) > 0)
+ PS_GR_P_ADDVAL(p, PLAYERSTATS_JOINS, 1);
+
+ PlayerStats_GameReport_Accuracy(p);
+
+ if(IS_REAL_CLIENT(p))
+ {
+ if(p.latency_cnt)
+ {
+ float latency = (p.latency_sum / p.latency_cnt);
+ if(latency) { PS_GR_P_ADDVAL(p, PLAYERSTATS_AVGLATENCY, latency); }
+ }
+ }
+
+ strunzone(p.playerstats_id);
+ p.playerstats_id = string_null;
+}
+
+void PlayerStats_GameReport(float finished)
+{
+ if(PS_GR_OUT_DB < 0) { return; }
+
+ PlayerScore_Sort(score_dummyfield, 0, 0, 0);
+ PlayerScore_Sort(scoreboard_pos, 1, 1, 1);
+ if(teamplay) { PlayerScore_TeamStats(); }
+
+ entity p;
+ FOR_EACH_CLIENT(p)
+ {
+ // add personal score rank
+ PS_GR_P_ADDVAL(p, PLAYERSTATS_RANK, p.score_dummyfield);
+
+ // scoreboard data
+ if(p.scoreboard_pos)
+ {
+ // scoreboard is valid!
+ PS_GR_P_ADDVAL(p, PLAYERSTATS_SCOREBOARD_VALID, 1);
+
+ // add scoreboard position
+ PS_GR_P_ADDVAL(p, PLAYERSTATS_SCOREBOARD_POS, p.scoreboard_pos);
+
+ // add scoreboard data
+ PlayerScore_PlayerStats(p);
+
+ // if the match ended normally, add winning info
+ if(finished)
+ {
+ PS_GR_P_ADDVAL(p, PLAYERSTATS_WINS, p.winning);
+ PS_GR_P_ADDVAL(p, PLAYERSTATS_MATCHES, 1);
+ }
+ }
+
+ // collect final player information
+ PlayerStats_GameReport_FinalizePlayer(p);
+ }
+
+ if(autocvar_g_playerstats_gamereport_uri != "")
+ {
+ PlayerStats_GameReport_DelayMapVote = TRUE;
+ url_multi_fopen(
+ autocvar_g_playerstats_gamereport_uri,
+ FILE_APPEND,
+ PlayerStats_GameReport_Handler,
+ world
+ );
+ }
+ else
+ {
+ PlayerStats_GameReport_DelayMapVote = FALSE;
+ db_close(PS_GR_OUT_DB);
+ PS_GR_OUT_DB = -1;
+ }
+}
+
+void PlayerStats_GameReport_Init() // initiated before InitGameplayMode so that scores are added properly
+{
+ if(autocvar_g_playerstats_gamereport_uri == "") { return; }
+
+ PS_GR_OUT_DB = -1;
+ PS_GR_OUT_DB = db_create();
+
+ if(PS_GR_OUT_DB >= 0)
+ {
+ PlayerStats_GameReport_DelayMapVote = TRUE;
+
+ serverflags |= SERVERFLAG_PLAYERSTATS;
+
+ PlayerStats_GameReport_AddEvent(PLAYERSTATS_ALIVETIME);
+ PlayerStats_GameReport_AddEvent(PLAYERSTATS_AVGLATENCY);
+ PlayerStats_GameReport_AddEvent(PLAYERSTATS_WINS);
+ PlayerStats_GameReport_AddEvent(PLAYERSTATS_MATCHES);
+ PlayerStats_GameReport_AddEvent(PLAYERSTATS_JOINS);
+ PlayerStats_GameReport_AddEvent(PLAYERSTATS_SCOREBOARD_VALID);
+ PlayerStats_GameReport_AddEvent(PLAYERSTATS_SCOREBOARD_POS);
+ PlayerStats_GameReport_AddEvent(PLAYERSTATS_RANK);
+
+ // accuracy stats
+ entity w;
+ float i;
+ for(i = WEP_FIRST; i <= WEP_LAST; ++i)
+ {
+ w = get_weaponinfo(i);
+ PlayerStats_GameReport_AddEvent(strcat("acc-", w.netname, "-hit"));
+ PlayerStats_GameReport_AddEvent(strcat("acc-", w.netname, "-fired"));
+ PlayerStats_GameReport_AddEvent(strcat("acc-", w.netname, "-cnt-hit"));
+ PlayerStats_GameReport_AddEvent(strcat("acc-", w.netname, "-cnt-fired"));
+ PlayerStats_GameReport_AddEvent(strcat("acc-", w.netname, "-frags"));
+ }
+
+ PlayerStats_GameReport_AddEvent(PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_3);
+ PlayerStats_GameReport_AddEvent(PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_5);
+ PlayerStats_GameReport_AddEvent(PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_10);
+ PlayerStats_GameReport_AddEvent(PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_15);
+ PlayerStats_GameReport_AddEvent(PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_20);
+ PlayerStats_GameReport_AddEvent(PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_25);
+ PlayerStats_GameReport_AddEvent(PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_30);
+ PlayerStats_GameReport_AddEvent(PLAYERSTATS_ACHIEVEMENT_BOTLIKE);
+ PlayerStats_GameReport_AddEvent(PLAYERSTATS_ACHIEVEMENT_FIRSTBLOOD);
+ PlayerStats_GameReport_AddEvent(PLAYERSTATS_ACHIEVEMENT_FIRSTVICTIM);
+ }
+ else { PlayerStats_GameReport_DelayMapVote = FALSE; }
+}
+
+void PlayerStats_GameReport_Handler(entity fh, entity pass, float status)
+{
+ string t, tn;
+ string p, pn;
+ string e, en;
+ string nn, tt;
+ string s;
+
+ switch(status)
+ {
+ // ======================================
+ // -- OUTGOING GAME REPORT INFORMATION --
+ // ======================================
+ /* SPECIFICATIONS:
+ * V: format version (always a fixed number) - this MUST be the first line!
+ * #: comment (MUST be ignored by any parser)
+ * R: release information on the server
+ * G: game type
+ * O: mod name (icon request) as in server browser
+ * M: map name
+ * I: match ID (see "matchid" in g_world.qc)
+ * S: "hostname" of the server
+ * C: number of "unpure" cvar changes
+ * U: UDP port number of the server
+ * D: duration of the match
+ * L: "ladder" in which the server is participating in
+ * P: player ID of an existing player; this also sets the owner for all following "n", "e" and "t" lines (lower case!)
+ * Q: team number of an existing team (format: team#NN); this also sets the owner for all following "e" lines (lower case!)
+ * i: player index
+ * n: nickname of the player (optional)
+ * t: team ID
+ * e: followed by an event name, a space, and the event count/score
+ * event names can be:
+ * alivetime: total playing time of the player
+ * avglatency: average network latency compounded throughout the match
+ * wins: number of games won (can only be set if matches is set)
+ * matches: number of matches played to the end (not aborted by map switch)
+ * joins: number of matches joined (always 1 unless player never played during the match)
+ * scoreboardvalid: set to 1 if the player was there at the end of the match
+ * total-<scoreboardname>: total score of that scoreboard item
+ * scoreboard-<scoreboardname>: end-of-game score of that scoreboard item (can differ in non-team games)
+ * achievement-<achievementname>: achievement counters (their "count" is usually 1 if nonzero at all)
+ * kills-<index>: number of kills against the indexed player
+ * rank <number>: rank of player
+ * acc-<weapon netname>-hit: total damage dealt
+ * acc-<weapon netname>-fired: total damage that all fired projectiles *could* have dealt
+ * acc-<weapon netname>-cnt-hit: amount of shots that actually hit
+ * acc-<weapon netname>-cnt-fired: amount of fired shots
+ * acc-<weapon netname>-frags: amount of frags dealt by weapon
+ */
+ case URL_READY_CANWRITE:
+ {
+ url_fputs(fh, "V 9\n");
+ #ifdef WATERMARK
+ url_fputs(fh, sprintf("R %s\n", WATERMARK));
+ #endif
+ url_fputs(fh, sprintf("G %s\n", GetGametype()));
+ url_fputs(fh, sprintf("O %s\n", modname));
+ url_fputs(fh, sprintf("M %s\n", GetMapname()));
+ url_fputs(fh, sprintf("I %s\n", matchid));
+ url_fputs(fh, sprintf("S %s\n", cvar_string("hostname")));
+ url_fputs(fh, sprintf("C %d\n", cvar_purechanges_count));
+ url_fputs(fh, sprintf("U %d\n", cvar("port")));
+ url_fputs(fh, sprintf("D %f\n", max(0, time - game_starttime)));
+ url_fputs(fh, sprintf("L %s\n", autocvar_g_playerstats_gamereport_ladder));
+
+ // TEAMS
+ if(teamplay)
+ {
+ for(t = PS_GR_OUT_TL; (tn = db_get(PS_GR_OUT_DB, sprintf("%d", stof(t)))) != ""; t = tn)
+ {
+ // start team section
+ url_fputs(fh, sprintf("Q team#%s\n", t));
+
+ // output team events // todo: does this do unnecessary loops? perhaps we should do a separate "team_events_last" tracker..."
+ for(e = PS_GR_OUT_EVL; (en = db_get(PS_GR_OUT_DB, sprintf("*:%s", e))) != ""; e = en)
+ {
+ float v = stof(db_get(PS_GR_OUT_DB, sprintf("team#%d:%s", stof(t), e)));
+ if(v != 0) { url_fputs(fh, sprintf("e %s %g\n", e, v)); }
+ }
+ }
+ }
+
+ // PLAYERS
+ for(p = PS_GR_OUT_PL; (pn = db_get(PS_GR_OUT_DB, sprintf("%s:*", p))) != ""; p = pn)
+ {
+ // start player section
+ url_fputs(fh, sprintf("P %s\n", p));
+
+ // playerid/index (entity number for this server)
+ nn = db_get(PS_GR_OUT_DB, sprintf("%s:_playerid", p));
+ if(nn != "") { url_fputs(fh, sprintf("i %s\n", nn)); }
+
+ // player name
+ nn = db_get(PS_GR_OUT_DB, sprintf("%s:_netname", p));
+ if(nn != "") { url_fputs(fh, sprintf("n %s\n", nn)); }
+
+ // team identification number
+ if(teamplay)
+ {
+ tt = db_get(PS_GR_OUT_DB, sprintf("%s:_team", p));
+ url_fputs(fh, sprintf("t %s\n", tt));
+ }
+
+ // output player events
+ for(e = PS_GR_OUT_EVL; (en = db_get(PS_GR_OUT_DB, sprintf("*:%s", e))) != ""; e = en)
+ {
+ float v = stof(db_get(PS_GR_OUT_DB, sprintf("%s:%s", p, e)));
+ if(v != 0) { url_fputs(fh, sprintf("e %s %g\n", e, v)); }
+ }
+ }
+ url_fputs(fh, "\n");
+ url_fclose(fh);
+ break;
+ }
+
+ // ======================================
+ // -- INCOMING GAME REPORT INFORMATION --
+ // ======================================
+ /* SPECIFICATIONS:
+ * stuff
+ */
+ case URL_READY_CANREAD:
+ {
+ // url_fclose is processing, we got a response for writing the data
+ // this must come from HTTP
+ print("Got response from player stats server:\n");
+ while((s = url_fgets(fh))) { print(" ", s, "\n"); }
+ print("End of response.\n");
+ url_fclose(fh);
+ break;
+ }
+
+ case URL_READY_CLOSED:
+ {
+ // url_fclose has finished
+ print("Player stats written\n");
+ PlayerStats_GameReport_DelayMapVote = FALSE;
+ if(PS_GR_OUT_DB >= 0)
+ {
+ db_close(PS_GR_OUT_DB);
+ PS_GR_OUT_DB = -1;
+ }
+ break;
+ }
+
+ case URL_READY_ERROR:
+ default:
+ {
+ print("Player stats writing failed: ", ftos(status), "\n");
+ PlayerStats_GameReport_DelayMapVote = FALSE;
+ if(PS_GR_OUT_DB >= 0)
+ {
+ db_close(PS_GR_OUT_DB);
+ PS_GR_OUT_DB = -1;
+ }
+ break;
+ }
+ }
+}
+
+void PlayerStats_PlayerBasic(entity joiningplayer, float newrequest)
+{
+ // http://stats.xonotic.org/player/GgXRw6piDtFIbMArMuiAi8JG4tiin8VLjZgsKB60Uds=/elo.txt
+ if(autocvar_g_playerstats_playerbasic_uri != "")
+ {
+ string uri = autocvar_g_playerstats_playerbasic_uri;
+ if(joiningplayer.crypto_idfp != "")
+ {
+ // create the database if it doesn't already exist
+ if(PS_B_IN_DB < 0)
+ {
+ PS_B_IN_DB = -1;
+ PS_B_IN_DB = db_create();
+ }
+
+ // now request the information
+ uri = strcat(uri, "/player/", uri_escape(uri_escape(joiningplayer.crypto_idfp)), "/elo.txt");
+ print("Retrieving playerstats from URL: ", uri, "\n");
+ url_single_fopen(
+ uri,
+ FILE_APPEND,
+ PlayerStats_PlayerBasic_Handler,
+ joiningplayer
+ );
+
+ // set status appropriately // todo: check whether the player info exists in the database previously
+ if(newrequest)
+ {
+ // database still contains useful information, so don't clear it of a useful status
+ joiningplayer.playerstats_basicstatus = PS_B_STATUS_WAITING;
+ }
+ else
+ {
+ // database was previously empty or never hit received status for some reason
+ joiningplayer.playerstats_basicstatus = PS_B_STATUS_UPDATING;
+ }
+ }
+ }
+ else
+ {
+ // server has this disabled, kill the DB and set status to idle
+ if(PS_B_IN_DB >= 0)
+ {
+ entity player;
+
+ db_close(PS_B_IN_DB);
+ PS_B_IN_DB = -1;
+
+ FOR_EACH_REALCLIENT(player) { player.playerstats_basicstatus = PS_B_STATUS_IDLE; }
+ }
+ }
+}
+
+void PlayerStats_PlayerBasic_CheckUpdate(entity joiningplayer)
+{
+ // determine whether we should retrieve playerbasic information again
+
+ #if 0
+ printf("PlayerStats_PlayerBasic_CheckUpdate('%s'): %f\n",
+ joiningplayer.netname,
+ time
+ );
+ #endif
+
+ // TODO: check to see if this playerid is inside the database already somehow...
+ // for now we'll just check the field, but this won't work for players who disconnect and reconnect properly
+ // although maybe we should just submit another request ANYWAY?
+ if(!joiningplayer.playerstats_basicstatus)
+ {
+ PlayerStats_PlayerBasic(
+ joiningplayer,
+ (joiningplayer.playerstats_basicstatus == PS_B_STATUS_RECEIVED)
+ );
+ }
+}
+
+void PlayerStats_PlayerBasic_Handler(entity fh, entity p, float status)
+{
+ switch(status)
+ {
+ case URL_READY_CANWRITE:
+ {
+ print("-- Sending data to player stats server\n");
+ /*url_fputs(fh, "V 1\n");
+ #ifdef WATERMARK
+ url_fputs(fh, sprintf("R %s\n", WATERMARK));
+ #endif
+ url_fputs(fh, sprintf("l %s\n", cvar_string("_menu_prvm_language"))); // language
+ url_fputs(fh, sprintf("c %s\n", cvar_string("_menu_prvm_country"))); // country
+ url_fputs(fh, sprintf("g %s\n", cvar_string("_menu_prvm_gender"))); // gender
+ url_fputs(fh, sprintf("n %s\n", cvar_string("_cl_name"))); // name
+ url_fputs(fh, sprintf("m %s %s\n", cvar_string("_cl_playermodel"), cvar_string("_cl_playerskin"))); // model/skin
+ */url_fputs(fh, "\n");
+ url_fclose(fh);
+ break;
+ }
+
+ case URL_READY_CANREAD:
+ {
+ string s = "";
+ print("-- Got response from player stats server:\n");
+ //string gametype = string_null;
+ while((s = url_fgets(fh)))
+ {
+ print(" ", s, "\n");
+ /*
+ string key = "", value = "", data = "";
+
+ n = tokenizebyseparator(s, " "); // key (value) data
+ if (n == 1)
+ continue;
+ else if (n == 2)
+ {
+ key = argv(0);
+ data = argv(1);
+ }
+ else if (n >= 3)
+ {
+ key = argv(0);
+ value = argv(1);
+ data = argv(2);
+ }
+
+ if (data == "")
+ continue;
+
+ if (key == "#")
+ continue;
+ else if (key == "V")
+ PlayerInfo_AddItem(p, "_version", data);
+ else if (key == "R")
+ PlayerInfo_AddItem(p, "_release", data);
+ else if (key == "T")
+ PlayerInfo_AddItem(p, "_time", data);
+ else if (key == "S")
+ PlayerInfo_AddItem(p, "_statsurl", data);
+ else if (key == "P")
+ PlayerInfo_AddItem(p, "_hashkey", data);
+ else if (key == "n")
+ PlayerInfo_AddItem(p, "_playernick", data);
+ else if (key == "i")
+ PlayerInfo_AddItem(p, "_playerid", data);
+ else if (key == "G")
+ gametype = data;
+ else if (key == "e" && value != "")
+ {
+ if (gametype == "")
+ PlayerInfo_AddItem(p, value, data);
+ else
+ PlayerInfo_AddItem(p, sprintf("%s/%s", gametype, value), data);
+ }
+ else
+ continue;
+ */
+ }
+ print("-- End of response.\n");
+ url_fclose(fh);
+ break;
+ }
+ case URL_READY_CLOSED:
+ {
+ // url_fclose has finished
+ print("Player stats synchronized with server\n");
+ break;
+ }
+
+ case URL_READY_ERROR:
+ default:
+ {
+ print("Receiving player stats failed: ", ftos(status), "\n");
+ break;
+ }
+ }
+}
+#endif // SVQC
+
+#ifdef MENUQC
+
+
+#if 0 // reading the entire DB at once
+ string e = "", en = "";
+ float i = 0;
+ for(e = PS_D_IN_EVL; (en = db_get(PS_D_IN_DB, e)) != ""; e = en)
+ {
+ print(sprintf("%d:%s:%s\n", i, e, db_get(PS_D_IN_DB, sprintf("#%s", e))));
+ ++i;
+ }
+#endif
+
+void PlayerStats_PlayerDetail_AddItem(string event, string data)
+{
+ if(PS_D_IN_DB < 0) { return; }
+
+ // create a marker for the event so that we can access it later
+ string marker = sprintf("%s", event);
+ if(db_get(PS_D_IN_DB, marker) == "")
+ {
+ if(PS_D_IN_EVL)
+ {
+ db_put(PS_D_IN_DB, marker, PS_D_IN_EVL);
+ strunzone(PS_D_IN_EVL);
+ }
+ else { db_put(PS_D_IN_DB, marker, "#"); }
+ PS_D_IN_EVL = strzone(marker);
+ }
+
+ // now actually set the event data
+ db_put(PS_D_IN_DB, sprintf("#%s", event), data);
+ print("Added item ", sprintf("#%s", event), "=", data, " to PS_D_IN_DB\n");
+}
+
+void PlayerStats_PlayerDetail(void)
+{
+ // http://stats.xonotic.org/player/me
+ if((autocvar_g_playerstats_playerdetail_uri != "") && (crypto_getmyidstatus(0) > 0))
+ {
+ // create the database if it doesn't already exist
+ if(PS_D_IN_DB < 0)
+ {
+ PS_D_IN_DB = -1;
+ PS_D_IN_DB = db_create();
+ }
+
+ //uri = strcat(uri, "/player/", uri_escape(crypto_getmyidfp(0)));
+ print("Retrieving playerstats from URL: ", autocvar_g_playerstats_playerdetail_uri, "\n");
+ url_single_fopen(
+ autocvar_g_playerstats_playerdetail_uri,
+ FILE_APPEND,
+ PlayerStats_PlayerDetail_Handler,
+ world
+ );
+
+ PlayerStats_PlayerDetail_Status = PS_D_STATUS_WAITING;
+ }
+ else
+ {
+ // player has this disabled, kill the DB and set status to idle
+ if(PS_D_IN_DB >= 0)
+ {
+ db_close(PS_D_IN_DB);
+ PS_D_IN_DB = -1;
+ }
+
+ PlayerStats_PlayerDetail_Status = PS_D_STATUS_IDLE;
+ }
+}
+
+void PlayerStats_PlayerDetail_CheckUpdate(void)
+{
+ // determine whether we should retrieve playerdetail information again
+ float gamecount = cvar("cl_matchcount");
+
+ #if 0
+ printf("PlayerStats_PlayerDetail_CheckUpdate(): %f >= %f, %d > %d\n",
+ time,
+ PS_D_NEXTUPDATETIME,
+ PS_D_LASTGAMECOUNT,
+ gamecount
+ );
+ #endif
+
+ if(
+ (time >= PS_D_NEXTUPDATETIME)
+ ||
+ (gamecount > PS_D_LASTGAMECOUNT)
+ )
+ {
+ PlayerStats_PlayerDetail();
+ PS_D_NEXTUPDATETIME = (time + autocvar_g_playerstats_playerdetail_autoupdatetime);
+ PS_D_LASTGAMECOUNT = gamecount;
+ }
+}
+
+void PlayerStats_PlayerDetail_Handler(entity fh, entity unused, float status)
+{
+ switch(status)
+ {
+ case URL_READY_CANWRITE:
+ {
+ print("PlayerStats_PlayerDetail_Handler(): Sending data to player stats server...\n");
+ url_fputs(fh, "V 1\n");
+ #ifdef WATERMARK
+ url_fputs(fh, sprintf("R %s\n", WATERMARK));
+ #endif
+ url_fputs(fh, sprintf("l %s\n", cvar_string("_menu_prvm_language"))); // language
+ //url_fputs(fh, sprintf("c %s\n", cvar_string("_cl_country"))); // country
+ //url_fputs(fh, sprintf("g %s\n", cvar_string("_cl_gender"))); // gender
+ url_fputs(fh, sprintf("n %s\n", cvar_string("_cl_name"))); // name
+ url_fputs(fh, sprintf("m %s %s\n", cvar_string("_cl_playermodel"), cvar_string("_cl_playerskin"))); // model/skin
+ url_fputs(fh, "\n");
+ url_fclose(fh);
+ break;
+ }
+
+ case URL_READY_CANREAD:
+ {
+ //print("PlayerStats_PlayerDetail_Handler(): Got response from player stats server:\n");
+ string input = "";
+ string gametype = "overall";
+ while((input = url_fgets(fh)))
+ {
+ float count = tokenizebyseparator(input, " ");
+ string key = "", event = "", data = "";
+
+ if(argv(0) == "#") { continue; }
+
+ if(count == 2)
+ {
+ key = argv(0);
+ data = substring(input, argv_start_index(1), strlen(input) - argv_start_index(1));
+ }
+ else if(count >= 3)
+ {
+ key = argv(0);
+ event = argv(1);
+ data = substring(input, argv_start_index(2), strlen(input) - argv_start_index(2));
+ }
+ else { continue; }
+
+ switch(key)
+ {
+ // general info
+ case "V": PlayerStats_PlayerDetail_AddItem("version", data); break;
+ case "R": PlayerStats_PlayerDetail_AddItem("release", data); break;
+ case "T": PlayerStats_PlayerDetail_AddItem("time", data); break;
+
+ // player info
+ case "S": PlayerStats_PlayerDetail_AddItem("statsurl", data); break;
+ case "P": PlayerStats_PlayerDetail_AddItem("hashkey", data); break;
+ case "n": PlayerStats_PlayerDetail_AddItem("playernick", data); break;
+ case "i": PlayerStats_PlayerDetail_AddItem("playerid", data); break;
+
+ // other/event info
+ case "G": gametype = data; break;
+ case "e":
+ {
+ if(event != "" && data != "")
+ {
+ PlayerStats_PlayerDetail_AddItem(
+ sprintf(
+ "%s/%s",
+ gametype,
+ event
+ ),
+ data
+ );
+ }
+ break;
+ }
+
+ default:
+ {
+ print(sprintf(
+ "PlayerStats_PlayerDetail_Handler(): ERROR: "
+ "Key went unhandled? Is our version outdated?\n"
+ "PlayerStats_PlayerDetail_Handler(): "
+ "Key '%s', Event '%s', Data '%s'\n",
+ key,
+ event,
+ data
+ ));
+ break;
+ }
+ }
+
+ #if 0
+ print(sprintf(
+ "PlayerStats_PlayerDetail_Handler(): "
+ "Key '%s', Event '%s', Data '%s'\n",
+ key,
+ event,
+ data
+ ));
+ #endif
+ }
+ //print("PlayerStats_PlayerDetail_Handler(): End of response.\n");
+ url_fclose(fh);
+ PlayerStats_PlayerDetail_Status = PS_D_STATUS_RECEIVED;
+ statslist.getStats(statslist);
+ break;
+ }
+
+ case URL_READY_CLOSED:
+ {
+ // url_fclose has finished
+ print("PlayerStats_PlayerDetail_Handler(): Player stats synchronized with server.\n");
+ break;
+ }
+
+ case URL_READY_ERROR:
+ default:
+ {
+ print("PlayerStats_PlayerDetail_Handler(): Receiving player stats failed: ", ftos(status), "\n");
+ PlayerStats_PlayerDetail_Status = PS_D_STATUS_ERROR;
+ if(PS_D_IN_DB >= 0)
+ {
+ db_close(PS_D_IN_DB);
+ PS_D_IN_DB = -1;
+ }
+ break;
+ }
+ }
+}
+#endif
+
+/*
+void PlayerInfo_AddPlayer(entity e)
+{
+ if(playerinfo_db < 0)
+ return;
+
+ string key;
+ key = sprintf("#%d:*", e.playerid); // TODO: use hashkey instead?
+
+ string p;
+ p = db_get(playerinfo_db, key);
+ if(p == "")
+ {
+ if(playerinfo_last)
+ {
+ db_put(playerinfo_db, key, playerinfo_last);
+ strunzone(playerinfo_last);
+ }
+ else
+ db_put(playerinfo_db, key, "#");
+ playerinfo_last = strzone(ftos(e.playerid));
+ print(" Added player ", ftos(e.playerid), " to playerinfo_db\n");//DEBUG//
+ }
+}
+
+void PlayerInfo_AddItem(entity e, string item_id, string val)
+{
+ if(playerinfo_db < 0)
+ return;
+
+ string key;
+ key = sprintf("*:%s", item_id);
+
+ string p;
+ p = db_get(playerinfo_db, key);
+ if(p == "")
+ {
+ if(playerinfo_events_last)
+ {
+ db_put(playerinfo_db, key, playerinfo_events_last);
+ strunzone(playerinfo_events_last);
+ }
+ else
+ db_put(playerinfo_db, key, "#");
+ playerinfo_events_last = strzone(item_id);
+ }
+
+ key = sprintf("#%d:%s", e.playerid, item_id);
+ db_put(playerinfo_db, key, val);
+ print(" Added item ", key, "=", val, " to playerinfo_db\n");//DEBUG//
+}
+
+string PlayerInfo_GetItem(entity e, string item_id)
+{
+ if(playerinfo_db < 0)
+ return "";
+
+ string key;
+ key = sprintf("#%d:%s", e.playerid, item_id);
+ return db_get(playerinfo_db, key);
+}
+
+string PlayerInfo_GetItemLocal(string item_id)
+{
+ entity p = spawn();
+ p.playerid = 0;
+ return PlayerInfo_GetItem(p, item_id);
+}
+
+void PlayerInfo_ready(entity fh, entity p, float status)
+{
+ float n;
+ string s;
+
+ PlayerInfo_AddPlayer(p);
+
+ switch(status)
+ {
+ case URL_READY_CANWRITE:
+ print("-- Sending data to player stats server\n");
+ url_fputs(fh, "V 1\n");
+#ifdef WATERMARK
+ url_fputs(fh, sprintf("R %s\n", WATERMARK));
+#endif
+#ifdef MENUQC
+ url_fputs(fh, sprintf("l %s\n", cvar_string("_menu_prvm_language"))); // language
+ url_fputs(fh, sprintf("c %s\n", cvar_string("_menu_prvm_country"))); // country
+ url_fputs(fh, sprintf("g %s\n", cvar_string("_menu_prvm_gender"))); // gender
+ url_fputs(fh, sprintf("n %s\n", cvar_string("_cl_name"))); // name
+ url_fputs(fh, sprintf("m %s %s\n", cvar_string("_cl_playermodel"), cvar_string("_cl_playerskin"))); // model/skin
+#endif
+ url_fputs(fh, "\n");
+ url_fclose(fh);
+ break;
+ case URL_READY_CANREAD:
+ print("-- Got response from player stats server:\n");
+ string gametype = string_null;
+ while((s = url_fgets(fh)))
+ {
+ print(" ", s, "\n");
+
+ string key = "", value = "", data = "";
+
+ n = tokenizebyseparator(s, " "); // key (value) data
+ if (n == 1)
+ continue;
+ else if (n == 2)
+ {
+ key = argv(0);
+ data = argv(1);
+ }
+ else if (n >= 3)
+ {
+ key = argv(0);
+ value = argv(1);
+ data = argv(2);
+ }
+
+ if (data == "")
+ continue;
+
+ if (key == "#")
+ continue;
+ else if (key == "V")
+ PlayerInfo_AddItem(p, "_version", data);
+ else if (key == "R")
+ PlayerInfo_AddItem(p, "_release", data);
+ else if (key == "T")
+ PlayerInfo_AddItem(p, "_time", data);
+ else if (key == "S")
+ PlayerInfo_AddItem(p, "_statsurl", data);
+ else if (key == "P")
+ PlayerInfo_AddItem(p, "_hashkey", data);
+ else if (key == "n")
+ PlayerInfo_AddItem(p, "_playernick", data);
+ else if (key == "i")
+ PlayerInfo_AddItem(p, "_playerid", data);
+ else if (key == "G")
+ gametype = data;
+ else if (key == "e" && value != "")
+ {
+ if (gametype == "")
+ PlayerInfo_AddItem(p, value, data);
+ else
+ PlayerInfo_AddItem(p, sprintf("%s/%s", gametype, value), data);
+ }
+ else
+ continue;
+ }
+ print("-- End of response.\n");
+ url_fclose(fh);
+ break;
+ case URL_READY_CLOSED:
+ // url_fclose has finished
+ print("Player stats synchronized with server\n");
+ break;
+ case URL_READY_ERROR:
+ default:
+ print("Receiving player stats failed: ", ftos(status), "\n");
+ break;
+ }
+}
+
+void PlayerInfo_Init()
+{
+ playerinfo_db = -1;
+ playerinfo_db = db_create();
+}
+
+#ifdef SVQC
+void PlayerInfo_Basic(entity p)
+{
+ print("-- Getting basic PlayerInfo for player ",ftos(p.playerid)," (SVQC)\n");
+
+ if(playerinfo_db < 0)
+ return;
+
+ string uri;
+ uri = autocvar_g_playerinfo_uri;
+ if(uri != "" && p.crypto_idfp != "")
+ {
+ uri = strcat(uri, "/elo/", uri_escape(p.crypto_idfp));
+ print("Retrieving playerstats from URL: ", uri, "\n");
+ url_single_fopen(uri, FILE_READ, PlayerInfo_ready, p);
+ }
+}
+#endif
+
+#ifdef MENUQC
+void PlayerInfo_Details()
+{
+ print("-- Getting detailed PlayerInfo for local player (MENUQC)\n");
+
+ if(playerinfo_db < 0)
+ return;
+
+ string uri;
+ uri = autocvar_g_playerinfo_uri; // FIXME
+ if(uri != "" && crypto_getmyidstatus(0) > 0)
+ {
+ //uri = strcat(uri, "/player/", uri_escape(crypto_getmyidfp(0)));
+ uri = strcat(uri, "/player/me");
+ print("Retrieving playerstats from URL: ", uri, "\n");
+ url_single_fopen(uri, FILE_APPEND, PlayerInfo_ready, world);
+ }
+}
+#endif
+
+#ifdef CSQC
+/*
+ * FIXME - crypto_* builtin functions missing in CSQC (csprogsdefs.qc:885)
+void PlayerInfo_Details()
+{
+ print("-- Getting detailed PlayerInfo for local player (CSQC)\n");
+
+ if(playerinfo_db < 0)
+ return;
+
+ string uri;
+ uri = autocvar_g_playerinfo_uri; // FIXME
+ if(uri != "" && crypto_getmyidstatus(0) > 0)
+ {
+ uri = strcat(uri, "/player/", uri_escape(crypto_getmyidfp(0)));
+ print("Retrieving playerstats from URL: ", uri, "\n");
+ url_single_fopen(uri, FILE_READ, PlayerInfo_ready, p);
+ }
+}
+
+#endif
+*/
--- /dev/null
+#ifdef SVQC
+//float PS_PM_IN_DB; // playerstats_prematch_in_db // db for info COLLECTED at the beginning of a match
+float PS_GR_OUT_DB; // playerstats_gamereport_out_db // db of info SENT at the end of a match
+//float PS_GR_IN_DB; // playerstats_gamereport_in_db // db for info COLLECTED at the end of a match
+float PS_B_IN_DB; // playerstats_playerbasic_in_db // db for info COLLECTED for basic player info (ELO)
+#endif
+
+#ifdef MENUQC
+float PS_D_IN_DB; // playerstats_playerdetail_in_db // db for info COLLECTED for detailed player profile display
+#endif
+
+#ifdef SVQC
+//string PS_PM_IN_EVL; // playerstats_prematch_in_events_last
+string PS_GR_OUT_TL; // playerstats_gamereport_out_teams_last
+string PS_GR_OUT_PL; // playerstats_gamereport_out_players_las
+string PS_GR_OUT_EVL; // playerstats_gamereport_out_events_last
+//string PS_GR_IN_PL; // playerstats_gamereport_in_players_last
+//string PS_GR_IN_EVL; // playerstats_gamereport_in_events_last
+//string PS_B_IN_PL; // playerstats_playerbasic_in_players_last
+//string PS_B_IN_EVL; // playerstats_playerbasic_in_events_last
+#endif
+
+#ifdef MENUQC
+string PS_D_IN_EVL; // playerstats_playerdetail_in_events_last
+#endif
+
+#ifdef SVQC
+
+// time the player was alive and kicking
+const string PLAYERSTATS_ALIVETIME = "alivetime";
+const string PLAYERSTATS_AVGLATENCY = "avglatency";
+const string PLAYERSTATS_WINS = "wins";
+const string PLAYERSTATS_MATCHES = "matches";
+const string PLAYERSTATS_JOINS = "joins";
+const string PLAYERSTATS_SCOREBOARD_VALID = "scoreboardvalid";
+const string PLAYERSTATS_RANK = "rank";
+const string PLAYERSTATS_SCOREBOARD_POS = "scoreboardpos";
+
+const string PLAYERSTATS_TOTAL = "total-";
+const string PLAYERSTATS_SCOREBOARD = "scoreboard-";
+
+const string PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_3 = "achievement-kill-spree-3";
+const string PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_5 = "achievement-kill-spree-5";
+const string PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_10 = "achievement-kill-spree-10";
+const string PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_15 = "achievement-kill-spree-15";
+const string PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_20 = "achievement-kill-spree-20";
+const string PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_25 = "achievement-kill-spree-25";
+const string PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_30 = "achievement-kill-spree-30";
+const string PLAYERSTATS_ACHIEVEMENT_BOTLIKE = "achievement-botlike";
+const string PLAYERSTATS_ACHIEVEMENT_FIRSTBLOOD = "achievement-firstblood";
+const string PLAYERSTATS_ACHIEVEMENT_FIRSTVICTIM = "achievement-firstvictim";
+
+// delay map switch until this is set
+float PlayerStats_GameReport_DelayMapVote;
+
+// call at initialization
+void PlayerStats_GameReport_Init();
+
+// add a new player
+void PlayerStats_GameReport_AddPlayer(entity e);
+
+// add a new team
+void PlayerStats_GameReport_AddTeam(float t);
+
+// add a new event
+void PlayerStats_GameReport_AddEvent(string event_id);
+
+// call on each event to track, or at player disconnect OR match end for "global stuff"
+#define PS_GR_P_ADDVAL(ent,eventid,val) PlayerStats_GameReport_Event(ent.playerstats_id, eventid, val)
+#define PS_GR_T_ADDVAL(team,eventid,val) PlayerStats_GameReport_Event(sprintf("team#%d", team), eventid, val)
+float PlayerStats_GameReport_Event(string prefix, string event_id, float value);
+
+void PlayerStats_GameReport_Accuracy(entity p);
+
+// call this whenever a player leaves
+void PlayerStats_GameReport_FinalizePlayer(entity p);
+
+// call this at the end of the match
+void PlayerStats_GameReport(float finished);
+
+void PlayerStats_GameReport_Handler(entity fh, entity pass, float status);
+
+.string playerstats_id;
+
+//string autocvar_g_playerstats_uri;
+
+string autocvar_g_playerstats_gamereport_ladder;
+var string autocvar_g_playerstats_gamereport_uri = "http://stats.xonotic.org/stats/submit";
+
+#define PS_B_STATUS_ERROR -2
+#define PS_B_STATUS_IDLE -1
+#define PS_B_STATUS_WAITING 0
+#define PS_B_STATUS_RECEIVED 1
+#define PS_B_STATUS_UPDATING 2
+.float playerstats_basicstatus;
+var string autocvar_g_playerstats_playerbasic_uri = "http://stats.xonotic.org";
+
+void PlayerStats_PlayerBasic(entity joiningplayer, float newrequest);
+void PlayerStats_PlayerBasic_CheckUpdate(entity joiningplayer);
+void PlayerStats_PlayerBasic_Handler(entity fh, entity p, float status);
+#endif //SVQC
+#ifdef MENUQC
+float PS_D_NEXTUPDATETIME;
+float PS_D_LASTGAMECOUNT;
+#define PS_D_STATUS_ERROR -2
+#define PS_D_STATUS_IDLE -1
+#define PS_D_STATUS_WAITING 0
+#define PS_D_STATUS_RECEIVED 1
+var float PlayerStats_PlayerDetail_Status = PS_D_STATUS_IDLE;
+var string autocvar_g_playerstats_playerdetail_uri = "http://stats.xonotic.org/player/me";
+var float autocvar_g_playerstats_playerdetail_autoupdatetime = 1800; // automatically update every 30 minutes anyway
+void PlayerStats_PlayerDetail(void);
+void PlayerStats_PlayerDetail_CheckUpdate(void);
+void PlayerStats_PlayerDetail_Handler(entity fh, entity p, float status);
+#endif
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;
}
// todo: this sucks, lets find a better way to do backtraces?
-#ifndef MENUQC
void backtrace(string msg)
{
float dev, war;
cvar_set("developer", ftos(dev));
cvar_set("prvm_backtraceforwarnings", ftos(war));
}
-#endif
// color code replace, place inside of sprintf and parse the string
string CCR(string input)
#endif
#define TIME_TO_NTHS(t,n) floor((t) * (n) + 0.4)
+string format_time(float seconds);
string mmsss(float t);
string mmssss(float t);
#define fprintf(file, ...) fputs(file, sprintf(__VA_ARGS__))
#define bprintf(...) bprint(sprintf(__VA_ARGS__))
-#ifndef MENUQC
+//#ifndef MENUQC
void backtrace(string msg);
-#endif
+//#endif
// color code replace, place inside of sprintf and parse the string... defaults described as constants
// foreground/normal colors
#include "xonotic/dialog_settings_video.c"
#include "xonotic/dialog_settings_effects.c"
#include "xonotic/dialog_settings_audio.c"
+#include "xonotic/dialog_settings_game.c"
#include "xonotic/dialog_settings_user.c"
#include "xonotic/dialog_settings_user_languagewarning.c"
#include "xonotic/dialog_settings_misc.c"
#include "xonotic/dialog_multiplayer.c"
-#include "xonotic/dialog_multiplayer_playersetup.c"
+#include "xonotic/dialog_multiplayer_profile.c"
#include "xonotic/tabcontroller.c"
#include "xonotic/textlabel.c"
#include "xonotic/slider.c"
#include "xonotic/dialog_quit.c"
#include "xonotic/dialog_multiplayer_create.c"
#include "xonotic/dialog_multiplayer_create_mutators.c"
-#include "xonotic/dialog_multiplayer_create_advanced.c"
#include "xonotic/dialog_multiplayer_create_mapinfo.c"
#include "xonotic/gametypelist.c"
#include "xonotic/maplist.c"
#include "xonotic/dialog_singleplayer_winner.c"
#include "xonotic/dialog_credits.c"
#include "xonotic/credits.c"
-#include "xonotic/dialog_multiplayer_playersetup_crosshair.c"
-#include "xonotic/dialog_multiplayer_playersetup_hud.c"
-#include "xonotic/dialog_multiplayer_playersetup_hudconfirm.c"
-#include "xonotic/dialog_multiplayer_playersetup_model.c"
-#include "xonotic/dialog_multiplayer_playersetup_view.c"
-#include "xonotic/dialog_multiplayer_playersetup_weapons.c"
+#include "xonotic/dialog_settings_game_crosshair.c"
+#include "xonotic/dialog_settings_game_hud.c"
+#include "xonotic/dialog_settings_game_hudconfirm.c"
+#include "xonotic/dialog_settings_game_model.c"
+#include "xonotic/dialog_settings_game_messages.c"
+#include "xonotic/dialog_settings_game_view.c"
+#include "xonotic/dialog_settings_game_weapons.c"
#include "xonotic/weaponslist.c"
-#include "xonotic/dialog_multiplayer_demo.c"
+#include "xonotic/dialog_multiplayer_media.c"
+#include "xonotic/dialog_multiplayer_media_demo.c"
+#include "xonotic/dialog_multiplayer_media_demo_startconfirm.c"
+#include "xonotic/dialog_multiplayer_media_demo_timeconfirm.c"
#include "xonotic/demolist.c"
+#include "xonotic/screenshotimage.c"
+#include "xonotic/dialog_multiplayer_media_screenshot.c"
+#include "xonotic/dialog_multiplayer_media_screenshot_viewer.c"
+#include "xonotic/screenshotlist.c"
+#include "xonotic/statslist.c"
#include "xonotic/colorpicker.c"
#include "xonotic/colorpicker_string.c"
#include "xonotic/cvarlist.c"
#include "xonotic/dialog_hudpanel_centerprint.c"
#include "xonotic/dialog_hudpanel_buffs.c"
#include "xonotic/slider_picmip.c"
+#include "xonotic/slider_particles.c"
+#include "xonotic/slider_sbfadetime.c"
METHOD(Image, toString, string(entity))
METHOD(Image, resizeNotify, void(entity, vector, vector, vector, vector))
METHOD(Image, updateAspect, void(entity))
+ METHOD(Image, initZoom, void(entity))
+ METHOD(Image, setZoom, void(entity, float, float))
+ METHOD(Image, drag_setStartPos, float(entity, vector))
+ METHOD(Image, drag, float(entity, vector))
ATTRIB(Image, src, string, string_null)
ATTRIB(Image, color, vector, '1 1 1')
- ATTRIB(Image, forcedAspect, float, 0)
+ ATTRIB(Image, forcedAspect, float, 0) // special values: -1 keep image aspect ratio, -2 keep image size but bound to the containing box, -3 always keep image size
+ ATTRIB(Image, zoomBox, float, 0) // used by forcedAspect -2 when the image is larger than the containing box
+ ATTRIB(Image, zoomFactor, float, 1)
+ ATTRIB(Image, zoomOffset, vector, '0.5 0.5 0')
+ ATTRIB(Image, zoomSnapToTheBox, float, 1) // snap the zoomed in image to the box borders when zooming/dragging it
+ ATTRIB(Image, zoomTime, float, 0)
+ ATTRIB(Image, zoomLimitedByTheBox, float, 0) // forbids zoom if image would be larger than the containing box
+ ATTRIB(Image, zoomMax, float, 0)
+ ATTRIB(Image, start_zoomOffset, vector, '0 0 0')
+ ATTRIB(Image, start_coords, vector, '0 0 0')
ATTRIB(Image, imgOrigin, vector, '0 0 0')
ATTRIB(Image, imgSize, vector, '0 0 0')
ENDCLASS(Image)
{
me.src = path;
}
+void Image_initZoom(entity me)
+{
+ me.zoomOffset = '0.5 0.5 0';
+ me.zoomFactor = 1;
+ if (me.forcedAspect == -2)
+ me.zoomBox = -1; // calculate zoomBox at the first updateAspect call
+ if (me.zoomLimitedByTheBox)
+ me.zoomMax = -1; // calculate zoomMax at the first updateAspect call
+}
+
void Image_draw(entity me)
{
+ if(me.imgSize_x > 1 || me.imgSize_y > 1)
+ draw_SetClip();
draw_Picture(me.imgOrigin, me.src, me.imgSize, me.color, 1);
+ if(me.imgSize_x > 1 || me.imgSize_y > 1)
+ draw_ClearClip();
SUPER(Image).draw(me);
}
void Image_updateAspect(entity me)
{
- float asp;
+ float asp = 0;
if(me.size_x <= 0 || me.size_y <= 0)
return;
if(me.forcedAspect == 0)
}
else
{
+ vector sz = '0 0 0';
if(me.forcedAspect < 0)
{
- vector sz;
sz = draw_PictureSize(me.src);
+ if(sz_x <= 0 || sz_y <= 0)
+ {
+ // image is broken or doesn't exist, set the size for the placeholder image
+ sz_x = me.size_x;
+ sz_y = me.size_y;
+ }
asp = sz_x / sz_y;
}
else
asp = me.forcedAspect;
- if(me.size_x > asp * me.size_y)
+
+ if(me.forcedAspect <= -2)
+ {
+ me.imgSize_x = sz_x / me.size_x;
+ me.imgSize_y = sz_y / me.size_y;
+ if(me.zoomBox < 0 && (me.imgSize_x > 1 || me.imgSize_y > 1))
+ {
+ // image larger than the containing box, zoom it out to fit into the box
+ if(me.size_x > asp * me.size_y)
+ me.zoomBox = (me.size_y * asp / me.size_x) / me.imgSize_x;
+ else
+ me.zoomBox = (me.size_x / (asp * me.size_y)) / me.imgSize_y;
+ me.zoomFactor = me.zoomBox;
+ }
+ }
+ else
+ {
+ if(me.size_x > asp * me.size_y)
+ {
+ // x too large, so center x-wise
+ me.imgSize = eY + eX * (me.size_y * asp / me.size_x);
+ }
+ else
+ {
+ // y too large, so center y-wise
+ me.imgSize = eX + eY * (me.size_x / (asp * me.size_y));
+ }
+ }
+ }
+
+ if (me.zoomMax < 0)
+ {
+ if(me.zoomBox > 0)
+ me.zoomMax = me.zoomBox;
+ else
+ {
+ if(me.size_x > asp * me.size_y)
+ me.zoomMax = (me.size_y * asp / me.size_x) / me.imgSize_x;
+ else
+ me.zoomMax = (me.size_x / (asp * me.size_y)) / me.imgSize_y;
+ }
+ }
+
+ if (me.zoomMax > 0 && me.zoomFactor > me.zoomMax)
+ me.zoomFactor = me.zoomMax;
+ if (me.zoomFactor)
+ me.imgSize = me.imgSize * me.zoomFactor;
+
+ if(me.imgSize_x > 1 || me.imgSize_y > 1)
+ {
+ if(me.zoomSnapToTheBox)
+ {
+ if(me.imgSize_x > 1)
+ me.zoomOffset_x = bound(0.5/me.imgSize_x, me.zoomOffset_x, 1 - 0.5/me.imgSize_x);
+ else
+ me.zoomOffset_x = bound(1 - 0.5/me.imgSize_x, me.zoomOffset_x, 0.5/me.imgSize_x);
+
+ if(me.imgSize_y > 1)
+ me.zoomOffset_y = bound(0.5/me.imgSize_y, me.zoomOffset_y, 1 - 0.5/me.imgSize_y);
+ else
+ me.zoomOffset_y = bound(1 - 0.5/me.imgSize_y, me.zoomOffset_y, 0.5/me.imgSize_y);
+ }
+ else
+ {
+ me.zoomOffset_x = bound(0, me.zoomOffset_x, 1);
+ me.zoomOffset_y = bound(0, me.zoomOffset_y, 1);
+ }
+ }
+ else
+ me.zoomOffset = '0.5 0.5 0';
+
+ me.imgOrigin_x = 0.5 - me.zoomOffset_x * me.imgSize_x;
+ me.imgOrigin_y = 0.5 - me.zoomOffset_y * me.imgSize_y;
+}
+float Image_drag_setStartPos(entity me, vector coords)
+{
+ //if(me.imgSize_x > 1 || me.imgSize_y > 1) // check disabled: mousewheel zoom may start from a non-zoomed-in image
+ {
+ me.start_zoomOffset = me.zoomOffset;
+ me.start_coords = coords;
+ }
+ return 1;
+}
+float Image_drag(entity me, vector coords)
+{
+ if(me.imgSize_x > 1 || me.imgSize_y > 1)
+ {
+ me.zoomOffset_x = me.start_zoomOffset_x + (me.start_coords_x - coords_x) / me.imgSize_x;
+ me.zoomOffset_y = me.start_zoomOffset_y + (me.start_coords_y - coords_y) / me.imgSize_y;
+ me.updateAspect(me);
+ }
+ return 1;
+}
+void Image_setZoom(entity me, float z, float atMousePosition)
+{
+ float prev_zoomFactor;
+ prev_zoomFactor = me.zoomFactor;
+ if (z < 0) // multiply by the current zoomFactor (but can also snap to real dimensions or to box)
+ {
+ me.zoomFactor *= -z;
+ float realSize_in_the_middle, boxSize_in_the_middle;
+ realSize_in_the_middle = ((prev_zoomFactor - 1) * (me.zoomFactor - 1) < 0);
+ boxSize_in_the_middle = (me.zoomBox > 0 && (prev_zoomFactor - me.zoomBox) * (me.zoomFactor - me.zoomBox) < 0);
+ if (realSize_in_the_middle && boxSize_in_the_middle)
{
- // x too large, so center x-wise
- me.imgSize = eY + eX * (me.size_y * asp / me.size_x);
+ // snap to real dimensions or to box
+ if (prev_zoomFactor < me.zoomFactor)
+ me.zoomFactor = min(1, me.zoomBox);
+ else
+ me.zoomFactor = max(1, me.zoomBox);
}
+ else if (realSize_in_the_middle)
+ me.zoomFactor = 1; // snap to real dimensions
+ else if (boxSize_in_the_middle)
+ me.zoomFactor = me.zoomBox; // snap to box
+ }
+ else if (z == 0) // reset (no zoom)
+ {
+ if (me.zoomBox > 0)
+ me.zoomFactor = me.zoomBox;
else
+ me.zoomFactor = 1;
+ }
+ else // directly set
+ me.zoomFactor = z;
+ me.zoomFactor = bound(1/16, me.zoomFactor, 16);
+ if (me.zoomMax > 0 && me.zoomFactor > me.zoomMax)
+ me.zoomFactor = me.zoomMax;
+ if (prev_zoomFactor != me.zoomFactor)
+ {
+ me.zoomTime = time;
+ if (atMousePosition)
{
- // y too large, so center y-wise
- me.imgSize = eX + eY * (me.size_x / (asp * me.size_y));
+ me.zoomOffset_x = me.start_zoomOffset_x + (me.start_coords_x - 0.5) / me.imgSize_x;
+ me.zoomOffset_y = me.start_zoomOffset_y + (me.start_coords_y - 0.5) / me.imgSize_y;
+ // updateAspect will reset zoomOffset to '0.5 0.5 0' if
+ // with this zoomFactor the image will not be zoomed in
+ // (updateAspect will check the new values of imgSize).
}
- me.imgOrigin = '0.5 0.5 0' - 0.5 * me.imgSize;
}
+ me.updateAspect(me);
}
void Image_resizeNotify(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)
{
string TextSlider_valueToText(entity me, float val)
{
if(val >= me.nValues)
- return _("custom");
+ return _("Custom");
if(val < 0)
- return _("custom");
+ return _("Custom");
return me.(valueStrings[val]);
}
void TextSlider_setValueFromIdentifier(entity me, string id)
m_hide();
cvar_set("_menu_initialized", "1");
}
+
+ //PlayerInfo_Details();
+ PlayerStats_PlayerDetail_CheckUpdate();
}
const float MENU_ASPECT = 1.25; // 1280x1024
oo/base.h
+../common/playerstats.qh
../common/teams.qh
../common/constants.qh
../common/mapinfo.qh
../common/util.qc
../common/test.qc
+../common/playerstats.qc
../common/command/markup.qc
../common/command/rpn.qc
../common/command/generic.qc
SKINVECTOR(COLOR_DIALOG_HUD, '1 0.7 0.7');
SKINVECTOR(COLOR_DIALOG_SERVERINFO, '0.7 0.7 1');
SKINVECTOR(COLOR_DIALOG_CVARS, '1 0 0');
+ SKINVECTOR(COLOR_DIALOG_SCREENSHOTVIEWER, '0.7 0.7 1');
SKINVECTOR(COLOR_DIALOG_HUDCONFIRM, '1 0 0');
// nexposee positions of windows (they are the scale transformation
SKINVECTOR(COLOR_SKINLIST_TITLE, '1 1 1');
SKINVECTOR(COLOR_SKINLIST_AUTHOR, '0.4 0.4 0.7');
+ // item: demo list
+ SKINVECTOR(COLOR_DEMOLIST_SUBDIR, '0.5 0.5 0.5');
+
+ // item: screenshot list
+ SKINVECTOR(COLOR_SCREENSHOTLIST_SUBDIR, '0.5 0.5 0.5');
+
// item: slider
SKINSTRING(GFX_SLIDER, "slider");
SKINVECTOR(COLOR_SLIDER_N, '1 1 1');
ATTRIB(XonoticCheckBox, cvarName, string, string_null)
METHOD(XonoticCheckBox, loadCvars, void(entity))
METHOD(XonoticCheckBox, saveCvars, void(entity))
+ ATTRIB(XonoticCheckBox, sendCvars, float, 0)
ATTRIB(XonoticCheckBox, alpha, float, SKINALPHA_TEXT)
ATTRIB(XonoticCheckBox, disabledAlpha, float, SKINALPHA_DISABLED)
cvar_set(me.cvarName, ftos(me.yesValue));
else
cvar_set(me.cvarName, ftos(me.noValue));
+
+ CheckSendCvars(me, me.cvarName);
}
#endif
ATTRIB(XonoticCheckBoxString, cvarName, string, string_null)
METHOD(XonoticCheckBoxString, loadCvars, void(entity))
METHOD(XonoticCheckBoxString, saveCvars, void(entity))
+ ATTRIB(XonoticCheckBoxString, sendCvars, float, 0)
ATTRIB(XonoticCheckBoxString, alpha, float, SKINALPHA_TEXT)
ATTRIB(XonoticCheckBoxString, disabledAlpha, float, SKINALPHA_DISABLED)
cvar_set(me.cvarName, me.yesString);
else
cvar_set(me.cvarName, me.noString);
+
+ CheckSendCvars(me, me.cvarName);
}
#endif
METHOD(XonoticDemoList, drawListBoxItem, void(entity, float, vector, float))
METHOD(XonoticDemoList, getDemos, void(entity))
METHOD(XonoticDemoList, startDemo, void(entity))
+ METHOD(XonoticDemoList, timeDemo, void(entity))
METHOD(XonoticDemoList, demoName, string(entity, float))
METHOD(XonoticDemoList, clickListBoxItem, void(entity, float, vector))
METHOD(XonoticDemoList, keyDown, float(entity, float, float, float))
ATTRIB(XonoticDemoList, filterString, string, string_null)
ENDCLASS(XonoticDemoList)
+entity demolist; // for reference elsewhere
entity makeXonoticDemoList();
-void StartDemo_Click(entity btn, entity me);
-void TimeDemo_Click(entity btn, entity me);
+void DemoList_Refresh_Click(entity btn, entity me);
void DemoList_Filter_Change(entity box, entity me);
#endif
me.getDemos(me);
}
-string XonoticDemoList_demoName(entity me, float i )
+string XonoticDemoList_demoName(entity me, float i)
{
string s;
- s = search_getfilename(me.listDemo, i);
- s = substring(s, 6, strlen(s) - 6 - 4); // demos/, .dem
+ s = bufstr_get(me.listDemo, i);
+
+ if(substring(s, 0, 1) == "/")
+ s = substring(s, 1, strlen(s) - 1); // remove the first forward slash
+
return s;
}
-
-void XonoticDemoList_getDemos(entity me)
+// if subdir is TRUE look in subdirectories too (1 level)
+void getDemos_for_ext(entity me, string ext, float subdir)
{
string s;
-
+ if (subdir)
+ s="demos/*/";
+ else
+ s="demos/";
if(me.filterString)
- //subdirectory in filterString allowed
- s=strcat("demos/*", me.filterString, "*.dem");
+ s=strcat(s, me.filterString, ext);
else
- s="demos/*.dem";
-
- //dprint("Search demos with the pattern ", s, "\n");
- if(me.listDemo >= 0)
- search_end(me.listDemo);
+ s=strcat(s, "*", ext);
+
+ float list, i, n;
+ list = search_begin(s, FALSE, TRUE);
+ if(list >= 0)
+ {
+ n = search_getsize(list);
+ for(i = 0; i < n; ++i)
+ {
+ s = search_getfilename(list, i); // get initial full file name
+ s = substring(s, 6, (strlen(s) - 6 - 4)); // remove "demos/" prefix and ".dem" suffix
+ s = strdecolorize(s); // remove any pre-existing colors
+ if(subdir)
+ {
+ s = strreplace("/", "^7/", s); // clear colors at the forward slash
+ s = strcat("/", rgb_to_hexcolor(SKINCOLOR_DEMOLIST_SUBDIR), s); // add a forward slash for sorting, then color
+ bufstr_add(me.listDemo, s, TRUE);
+ }
+ else { bufstr_add(me.listDemo, s, TRUE); }
+ }
+ search_end(list);
+ }
- me.listDemo = search_begin(s, FALSE, TRUE);
+ if (subdir)
+ getDemos_for_ext(me, ext, FALSE);
+}
- if(me.listDemo < 0)
- me.nItems=0;
- else
- me.nItems=search_getsize(me.listDemo);
+void XonoticDemoList_getDemos(entity me)
+{
+ if (me.listDemo >= 0)
+ buf_del(me.listDemo);
+ me.listDemo = buf_create();
+ if (me.listDemo < 0)
+ {
+ me.nItems = 0;
+ return;
+ }
+ getDemos_for_ext(me, ".dem", TRUE);
+ me.nItems = buf_getsize(me.listDemo);
+ if(me.nItems > 0)
+ buf_sort(me.listDemo, 128, FALSE);
}
void XonoticDemoList_destroy(entity me)
{
- search_end(me.listDemo);
+ if(me.nItems > 0)
+ buf_del(me.listDemo);
}
void XonoticDemoList_resizeNotify(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)
s = me.demoName(me,i);
s = draw_TextShortenToWidth(s, me.columnNameSize, 0, me.realFontSize);
- draw_Text(me.realUpperMargin * eY + (me.columnNameOrigin + 0.00 * (me.columnNameSize - draw_TextWidth(s, 0, me.realFontSize))) * eX, s, me.realFontSize, SKINCOLOR_TEXT, SKINALPHA_TEXT, 0);
+ draw_Text(me.realUpperMargin * eY + (me.columnNameOrigin + 0.00 * (me.columnNameSize - draw_TextWidth(s, 0, me.realFontSize))) * eX, s, me.realFontSize, SKINCOLOR_TEXT, SKINALPHA_TEXT, 1);
}
void XonoticDemoList_showNotify(entity me)
me.getDemos(me);
}
+void DemoList_Refresh_Click(entity btn, entity me)
+{
+ me.getDemos(me);
+ me.setSelected(me, 0); //always select the first element after a list update
+}
+
void DemoList_Filter_Change(entity box, entity me)
{
if(me.filterString)
strunzone(me.filterString);
if(box.text != "")
- me.filterString = strzone(box.text);
+ {
+ if (strstrofs(box.text, "*", 0) >= 0 || strstrofs(box.text, "?", 0) >= 0)
+ me.filterString = strzone(box.text);
+ else
+ me.filterString = strzone(strcat("*", box.text, "*"));
+ }
else
me.filterString = string_null;
void XonoticDemoList_startDemo(entity me)
{
string s;
- s = me.demoName(me,me.selectedItem);
+ s = me.demoName(me, me.selectedItem);
+ s = strdecolorize(s);
+
localcmd("playdemo \"demos/", s, ".dem\" \nwait \ntogglemenu\n");
}
-void StartDemo_Click(entity btn, entity me)
+void XonoticDemoList_timeDemo(entity me)
{
- me.startDemo(me);
+ string s;
+ s = me.demoName(me, me.selectedItem);
+ s = strdecolorize(s);
+
+ localcmd("timedemo \"demos/", s, ".dem\" \nwait \ntogglemenu\n");
}
-void TimeDemo_Click(entity btn, entity me)
+void DemoConfirm_ListClick_Check_Gamestatus(entity me)
{
- string s;
- s = me.demoName(me,me.selectedItem);
- localcmd("timedemo \"demos/", s, ".dem\" \nwait \ntogglemenu\n");
+ if not(gamestatus & (GAME_CONNECTED | GAME_ISSERVER)) // we're not in a match, lets watch the demo
+ {
+ me.startDemo(me);
+ }
+ else // already in a match, player has to confirm
+ {
+ DialogOpenButton_Click_withCoords(
+ me,
+ main.demostartconfirmDialog,
+ boxToGlobal(eY * (me.selectedItem * me.itemHeight - me.scrollPos), me.origin, me.size),
+ boxToGlobalSize(eY * me.itemHeight + eX * (1 - me.controlWidth), me.size)
+ );
+ }
}
void XonoticDemoList_clickListBoxItem(entity me, float i, vector where)
{
// DOUBLE CLICK!
me.setSelected(me, i);
- me.startDemo(me);
+ DemoConfirm_ListClick_Check_Gamestatus(me);
}
me.lastClickedDemo = i;
me.lastClickedTime = time;
float XonoticDemoList_keyDown(entity me, float scan, float ascii, float shift)
{
- if(scan == K_ENTER || scan == K_KP_ENTER) {
- me.startDemo(me);
+ if(scan == K_ENTER || scan == K_KP_ENTER)
+ {
+ DemoConfirm_ListClick_Check_Gamestatus(me);
return 1;
}
else
+ {
return SUPER(XonoticDemoList).keyDown(me, scan, ascii, shift);
+ }
}
#endif
void XonoticMultiplayerDialog_fill(entity me)
{
entity mc, e;
- mc = makeXonoticTabController(me.rows - 2);
+ mc = makeXonoticTabController(me.rows - 1);
me.TR(me);
me.TD(me, 1, 1, e = mc.makeTabButton(mc, _("Servers"), makeXonoticServerListTab()));
me.TD(me, 1, 1, e = mc.makeTabButton(mc, _("Create"), makeXonoticServerCreateTab()));
- me.TD(me, 1, 1, e = mc.makeTabButton(mc, _("Demos"), makeXonoticDemoBrowserTab()));
- me.TD(me, 1, 1, e = mc.makeTabButton(mc, _("Player Setup"), makeXonoticPlayerSettingsTab()));
+ //me.TD(me, 1, 1, e = mc.makeTabButton(mc, _("Demos"), makeXonoticDemoBrowserTab()));
+ //me.TD(me, 1, 1, e = mc.makeTabButton(mc, _("Screenshots"), makeXonoticScreenshotBrowserTab()));
+ //me.TD(me, 1, 1, e = mc.makeTabButton(mc, _("Players"), makeXonoticDemoBrowserTab()));
+ me.TD(me, 1, 1, e = mc.makeTabButton(mc, _("Media"), makeXonoticMediaTab()));
+ me.TD(me, 1, 1, e = mc.makeTabButton(mc, _("Profile"), makeXonoticProfileTab()));
me.TR(me);
- me.TR(me);
- me.TD(me, me.rows - 2, me.columns, mc);
+ me.TD(me, me.rows - 1, me.columns, mc);
}
#endif
METHOD(XonoticServerCreateTab, gameTypeSelectNotify, 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, mapListBox, entity, NULL)
ATTRIB(XonoticServerCreateTab, sliderFraglimit, entity, NULL)
+ ATTRIB(XonoticServerCreateTab, sliderTeams, entity, NULL)
ATTRIB(XonoticServerCreateTab, sliderTimelimit, entity, NULL)
- ATTRIB(XonoticServerCreateTab, checkboxFraglimit, entity, NULL)
- ATTRIB(XonoticServerCreateTab, checkboxFraglimitMapinfo, entity, NULL)
+ ATTRIB(XonoticServerCreateTab, labelFraglimit, entity, NULL)
+ ATTRIB(XonoticServerCreateTab, labelTeams, entity, NULL)
ENDCLASS(XonoticServerCreateTab)
entity makeXonoticServerCreateTab();
#endif
#ifdef IMPLEMENTATION
+void GameType_ConfigureSliders(entity e, entity l, string pLabel, float pMin, float pMax, float pStep, string pCvar)
+{
+ if(pCvar == "")
+ {
+ e.configureXonoticTextSlider(e, string_null);
+ l.setText(l, pLabel);
+ e.disabled = l.disabled = TRUE;
+ }
+ else
+ {
+ e.configureXonoticTextSlider(e, pCvar);
+
+ // clear old values
+ float i;
+ for(i = 0; i <= e.nValues; ++i);
+ {
+ if(e.(valueStrings[i])) { strunzone(e.(valueStrings[i])); }
+ if(e.(valueIdentifiers[i])) { strunzone(e.(valueIdentifiers[i])); }
+ }
+ e.clearValues(e);
+
+ // set new values
+ e.addValue(e, strzone(_("Default")), strzone("-1"));
+ for(i = pMin; i <= pMax; i += pStep) { e.addValue(e, strzone(ftos(i)), strzone(ftos(i))); }
+ e.addValue(e, strzone(_("Unlimited")), strzone("0"));
+ e.configureXonoticTextSliderValues(e);
+
+ // set text field
+ l.setText(l, pLabel);
+ e.disabled = l.disabled = FALSE;
+ }
+}
+
entity makeXonoticServerCreateTab()
{
entity me;
{
entity e, e0;
+ me.gotoRC(me, 0.5, 0);
+ me.TD(me, 1, 3, e = makeXonoticTextLabel(0.5, _("Gametype")));
+ e.isBold = TRUE;
+ e.alpha = 0.5;
me.TR(me);
- me.TD(me, 1, 3, e = makeXonoticTextLabel(0, _("Game type:")));
- me.TR(me);
- me.TD(me, 8, 3, e = makeXonoticGametypeList());
- me.TR(me);
- me.TR(me);
- me.TR(me);
- me.TR(me);
- me.TR(me);
- me.TR(me);
- me.TR(me);
- me.TR(me);
- //me.TD(me, 1, 3, e = makeXonoticTextLabel(0, _("Match settings:"))); // pointless, overcrowds the dialog imo
- me.TR(me);
- me.sliderTimelimit = makeXonoticSlider(1.0, 60.0, 1, "timelimit_override");
- me.TD(me, 1, 1, e = makeXonoticSliderCheckBox(0, 1, me.sliderTimelimit, _("Time limit:")));
- me.TD(me, 1, 2, me.sliderTimelimit);
- me.TR(me);
- me.TDempty(me, 0.2);
- me.TD(me, 1, 2.8, e = makeXonoticSliderCheckBox(-1, 0, me.sliderTimelimit, _("Use map specified default")));
- me.TR(me);
- me.sliderFraglimit = makeXonoticSlider(1.0, 2000.0, 5, "fraglimit_override");
- me.TD(me, 1, 1, e = makeXonoticSliderCheckBox(0, 1, me.sliderFraglimit, _("Point limit:")));
- me.checkboxFraglimit = e;
- me.TD(me, 1, 2, me.sliderFraglimit);
+ me.TD(me, 10.5, 3, e = makeXonoticGametypeList());
+
+ me.gotoRC(me, 12.5, 0);
+ me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Time limit:")));
+ me.TD(me, 1, 2, e = makeXonoticTextSlider("timelimit_override"));
+ e.addValue(e, ZCTX(_("TIMLIM^Default")), "-1");
+ e.addValue(e, ZCTX(_("TIMLIM^1 minute")), "1");
+ e.addValue(e, ZCTX(_("TIMLIM^2 minutes")), "2");
+ e.addValue(e, ZCTX(_("TIMLIM^3 minutes")), "3");
+ e.addValue(e, ZCTX(_("TIMLIM^4 minutes")), "4");
+ e.addValue(e, ZCTX(_("TIMLIM^5 minutes")), "5");
+ e.addValue(e, ZCTX(_("TIMLIM^6 minutes")), "6");
+ e.addValue(e, ZCTX(_("TIMLIM^7 minutes")), "7");
+ e.addValue(e, ZCTX(_("TIMLIM^8 minutes")), "8");
+ e.addValue(e, ZCTX(_("TIMLIM^9 minutes")), "9");
+ e.addValue(e, ZCTX(_("TIMLIM^10 minutes")), "10");
+ e.addValue(e, ZCTX(_("TIMLIM^15 minutes")), "15");
+ e.addValue(e, ZCTX(_("TIMLIM^20 minutes")), "20");
+ e.addValue(e, ZCTX(_("TIMLIM^25 minutes")), "25");
+ e.addValue(e, ZCTX(_("TIMLIM^30 minutes")), "30");
+ e.addValue(e, ZCTX(_("TIMLIM^40 minutes")), "40");
+ e.addValue(e, ZCTX(_("TIMLIM^50 minutes")), "50");
+ e.addValue(e, ZCTX(_("TIMLIM^60 minutes")), "60");
+ e.addValue(e, ZCTX(_("TIMLIM^Infinite")), "0");
+ e.configureXonoticTextSliderValues(e);
me.TR(me);
- me.TDempty(me, 0.2);
- me.TD(me, 1, 2.8, e = makeXonoticSliderCheckBox(-1, 0, me.sliderFraglimit, _("Use map specified default")));
- me.checkboxFraglimitMapinfo = e;
+ me.TD(me, 1, 1, me.labelFraglimit = makeXonoticTextLabel(0, _("Frag limit:")));
+ me.TD(me, 1, 2, me.sliderFraglimit = makeXonoticTextSlider("fraglimit_override"));
+ GameType_ConfigureSliders(me.sliderFraglimit, me.labelFraglimit, _("Frag limit:"), 5, 100, 5, "fraglimit_override");
+
+ me.gotoRC(me, 15, 0);
+ me.TD(me, 1, 1, me.labelTeams = makeXonoticTextLabel(0, _("Teams:")));
+ me.TD(me, 1, 2, e = me.sliderTeams = makeXonoticTextSlider(string_null));
+ e.addValue(e, _("Default"), "0");
+ e.addValue(e, _("2 teams"), "2");
+ e.addValue(e, _("3 teams"), "3");
+ e.addValue(e, _("4 teams"), "4");
+ e.configureXonoticTextSliderValues(e);
me.TR(me);
me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Player slots:")));
me.TD(me, 1, 2, makeXonoticSlider(1, 32, 1, "menu_maxplayers"));
e.addValue(e, _("Godlike"), "10");
e.configureXonoticTextSliderValues(e);
setDependent(e, "bot_number", 0, -1);
- me.TR(me);
- me.TR(me);
- me.TD(me, 1, 1, e = makeXonoticButton(_("Mutators..."), '0 0 0'));
- e.onClick = DialogOpenButton_Click;
- e.onClickEntity = main.mutatorsDialog;
- main.mutatorsDialog.refilterEntity = me.mapListBox;
- me.TD(me, 1, 2, e0 = makeXonoticTextLabel(0, string_null));
+
+ me.gotoRC(me, me.rows - 3.5, 0);
+ me.TD(me, 1, 3, e0 = makeXonoticTextLabel(0.5, string_null));
e0.textEntity = main.mutatorsDialog;
e0.allowCut = 1;
+ //e0.allowWrap = 1;
me.TR(me);
me.TDempty(me, 0.5);
- me.TD(me, 1, 2, e = makeXonoticButton(_("Advanced settings..."), '0 0 0'));
+ me.TD(me, 1, 2, e = makeXonoticButton(_("Mutators"), '0 0 0'));
e.onClick = DialogOpenButton_Click;
- e.onClickEntity = main.advancedDialog;
- main.advancedDialog.refilterEntity = me.mapListBox;
+ e.onClickEntity = main.mutatorsDialog;
+ main.mutatorsDialog.refilterEntity = me.mapListBox;
- me.gotoRC(me, 0, 3.2); me.setFirstColumn(me, me.currentColumn);
+ me.gotoRC(me, 0.5, 3.2); me.setFirstColumn(me, me.currentColumn);
me.mapListBox = makeXonoticMapList();
- me.TD(me, 1, 3, e = makeXonoticTextLabel(0, _("Map list:")));
+ me.TD(me, 1, 3, e = makeXonoticTextLabel(0.5, _("Maplist")));
+ e.isBold = TRUE;
+ e.alpha = 0.5;
makeCallback(e, me.mapListBox, me.mapListBox.refilterCallback);
me.TR(me);
me.TD(me, me.rows - 4, 3, me.mapListBox);
- me.gotoRC(me, me.rows - 3, 3.5);
- me.TDempty(me, 0.25);
+ me.gotoRC(me, me.rows - 2.5, 3.2);
+ me.TDempty(me, 0.375);
me.TD(me, 1, 1.125, e = makeXonoticButton(_("Select all"), '0 0 0'));
e.onClick = MapList_All;
e.onClickEntity = me.mapListBox;
me.TD(me, 1, 1.125, e = makeXonoticButton(_("Select none"), '0 0 0'));
e.onClick = MapList_None;
e.onClickEntity = me.mapListBox;
- me.TDempty(me, 0.25);
me.gotoRC(me, me.rows - 1, 0);
me.TD(me, 1, me.columns, e = makeXonoticButton(_("Start Multiplayer!"), '0 0 0'));
me.gameTypeChangeNotify(me);
}
-void GameType_ConfigureSliders(entity e, entity l, entity l2, string pLabel, float pMin, float pMax, float pStep, string pCvar)
-{
- if(pCvar == "")
- {
- e.configureXonoticSlider(e, pMin, pMax, pStep, string_null);
- l.setText(l, pLabel);
- e.disabled = l.disabled = l2.disabled = TRUE;
- }
- else
- {
- e.configureXonoticSlider(e, pMin, pMax, pStep, pCvar);
- l.setText(l, pLabel);
- e.disabled = l.disabled = l2.disabled = FALSE;
- }
-}
-
void XonoticServerCreateTab_gameTypeChangeNotify(entity me)
{
// tell the map list to update
float gt;
- entity e, l, l2;
+ entity e, l;
gt = MapInfo_CurrentGametype();
e = me.sliderFraglimit;
- l = me.checkboxFraglimit;
- l2 = me.checkboxFraglimitMapinfo;
+ l = me.labelFraglimit;
+
switch(gt)
{
- case MAPINFO_TYPE_CTF: GameType_ConfigureSliders(e, l, l2, _("Capture limit:"), 1, 20, 1, "capturelimit_override"); break;
- case MAPINFO_TYPE_DOMINATION: GameType_ConfigureSliders(e, l, l2, _("Point limit:"), 50, 500, 10, "g_domination_point_limit"); break;
- case MAPINFO_TYPE_KEYHUNT: GameType_ConfigureSliders(e, l, l2, _("Point limit:"), 200, 1500, 50, "g_keyhunt_point_limit"); break;
- case MAPINFO_TYPE_LMS: GameType_ConfigureSliders(e, l, l2, _("Lives:"), 3, 50, 1, "g_lms_lives_override"); break;
- case MAPINFO_TYPE_RACE: GameType_ConfigureSliders(e, l, l2, _("Laps:"), 1, 25, 1, "g_race_laps_limit"); break;
- case MAPINFO_TYPE_NEXBALL: GameType_ConfigureSliders(e, l, l2, _("Goals:"), 1, 50, 1, "g_nexball_goallimit"); break;
- case MAPINFO_TYPE_ASSAULT: GameType_ConfigureSliders(e, l, l2, _("Point limit:"), 50, 500, 10, ""); break;
- case MAPINFO_TYPE_ONSLAUGHT: GameType_ConfigureSliders(e, l, l2, _("Point limit:"), 50, 500, 10, ""); break;
- case MAPINFO_TYPE_CTS: GameType_ConfigureSliders(e, l, l2, _("Point limit:"), 50, 500, 10, ""); break;
- case MAPINFO_TYPE_INVASION: GameType_ConfigureSliders(e, l, l2, _("Point limit:"), 5, 0, 5, ""); break;
- default: GameType_ConfigureSliders(e, l, l2, _("Frag limit:"), 5, 100, 5, "fraglimit_override"); break;
+ case MAPINFO_TYPE_CTF: GameType_ConfigureSliders(e, l, _("Capture limit:"), 1, 20, 1, "capturelimit_override"); break;
+ case MAPINFO_TYPE_DOMINATION: GameType_ConfigureSliders(e, l, _("Point limit:"), 50, 500, 10, "g_domination_point_limit"); break;
+ case MAPINFO_TYPE_KEYHUNT: GameType_ConfigureSliders(e, l, _("Point limit:"), 200, 1500, 50, "g_keyhunt_point_limit"); break;
+ case MAPINFO_TYPE_LMS: GameType_ConfigureSliders(e, l, _("Lives:"), 3, 50, 1, "g_lms_lives_override"); break;
+ case MAPINFO_TYPE_RACE: GameType_ConfigureSliders(e, l, _("Laps:"), 1, 25, 1, "g_race_laps_limit"); break;
+ case MAPINFO_TYPE_NEXBALL: GameType_ConfigureSliders(e, l, _("Goals:"), 1, 50, 1, "g_nexball_goallimit"); break;
+ case MAPINFO_TYPE_ASSAULT: GameType_ConfigureSliders(e, l, _("Point limit:"), 50, 500, 10, ""); break;
+ case MAPINFO_TYPE_ONSLAUGHT: GameType_ConfigureSliders(e, l, _("Point limit:"), 50, 500, 10, ""); break;
+ case MAPINFO_TYPE_CTS: GameType_ConfigureSliders(e, l, _("Point limit:"), 50, 500, 10, ""); break;
+ case MAPINFO_TYPE_INVASION: GameType_ConfigureSliders(e, l, _("Point limit:"), 5, 0, 5, ""); break;
+ default: GameType_ConfigureSliders(e, l, _("Frag limit:"), 5, 100, 5, "fraglimit_override"); break;
}
+
+ float x = FALSE;
+ e = me.sliderTeams;
+ switch(gt)
+ {
+ case MAPINFO_TYPE_CA: x = TRUE; e.configureXonoticTextSlider(e, "g_ca_teams_override"); break;
+ case MAPINFO_TYPE_DOMINATION: x = TRUE; e.configureXonoticTextSlider(e, "g_domination_teams_override"); break;
+ case MAPINFO_TYPE_FREEZETAG: x = TRUE; e.configureXonoticTextSlider(e, "g_freezetag_teams_override"); break;
+ case MAPINFO_TYPE_KEEPAWAY: x = TRUE; e.configureXonoticTextSlider(e, "g_keepaway_teams_override"); break;
+ case MAPINFO_TYPE_KEYHUNT: x = TRUE; e.configureXonoticTextSlider(e, "g_keyhunt_teams_override"); break;
+ case MAPINFO_TYPE_TEAM_DEATHMATCH: x = TRUE; e.configureXonoticTextSlider(e, "g_tdm_teams_override"); break;
+
+ default: x = FALSE; e.configureXonoticTextSlider(e, string_null); break;
+ }
+ e.configureXonoticTextSliderValues(e);
+ e.value = 0;
+ me.sliderTeams.disabled = me.labelTeams.disabled = !x;
+
me.mapListBox.refilter(me.mapListBox);
}
+++ /dev/null
-#ifdef INTERFACE
-CLASS(XonoticAdvancedDialog) EXTENDS(XonoticDialog)
- METHOD(XonoticAdvancedDialog, fill, void(entity))
- METHOD(XonoticAdvancedDialog, showNotify, void(entity))
- METHOD(XonoticAdvancedDialog, close, void(entity))
- ATTRIB(XonoticAdvancedDialog, title, string, _("Advanced server settings"))
- ATTRIB(XonoticAdvancedDialog, color, vector, SKINCOLOR_DIALOG_ADVANCED)
- ATTRIB(XonoticAdvancedDialog, intendedWidth, float, 0.5)
- ATTRIB(XonoticAdvancedDialog, rows, float, 17)
- ATTRIB(XonoticAdvancedDialog, columns, float, 3)
- ATTRIB(XonoticAdvancedDialog, refilterEntity, entity, NULL)
-ENDCLASS(XonoticAdvancedDialog)
-#endif
-
-#ifdef IMPLEMENTATION
-void XonoticAdvancedDialog_showNotify(entity me)
-{
- loadAllCvars(me);
-}
-
-void XonoticAdvancedDialog_fill(entity me)
-{
- entity e;
- me.TR(me);
- me.TD(me, 1, 3, makeXonoticTextLabel(0, _("Game settings:")));
- me.TR(me);
- me.TDempty(me, 0.2);
- me.TD(me, 1, 2.8, makeXonoticCheckBox(0, "sv_spectate", _("Allow spectating")));
- me.TR(me);
- me.TDempty(me, 0.2);
- me.TD(me, 1, 1.2, makeXonoticTextLabel(0, _("Spawn shield:")));
- me.TD(me, 1, 1.6, makeXonoticSlider(0, 15, 0.5, "g_spawnshieldtime"));
- me.TR(me);
- me.TR(me);
- me.TDempty(me, 0.2);
- me.TD(me, 1, 1.2, makeXonoticTextLabel(0, _("Game speed:")));
- me.TD(me, 1, 1.6, makeXonoticSlider(0.5, 2.0, 0.1, "slowmo"));
- me.TR(me);
- me.TR(me);
- me.TD(me, 1, 3, makeXonoticTextLabel(0, _("Teamplay settings:")));
- me.TR(me);
- me.TDempty(me, 0.2);
- me.TD(me, 1, 1.2, makeXonoticTextLabel(0, _("Friendly fire scale:")));
- me.TD(me, 1, 1.6, makeXonoticSlider(0, 1.0, 0.05, "g_friendlyfire"));
- me.TR(me);
- me.TDempty(me, 0.4);
- me.TD(me, 1, 2.6, makeXonoticCheckBox(0, "g_friendlyfire_virtual", _("Virtual friendly fire (effect only)")));
- me.TR(me);
- me.TDempty(me, 0.2);
- me.TD(me, 1, 1.2, makeXonoticTextLabel(0, _("Friendly fire penalty:")));
- me.TD(me, 1, 1.6, makeXonoticSlider(0, 1.0, 0.05, "g_mirrordamage"));
- me.TR(me);
- me.TDempty(me, 0.4);
- me.TD(me, 1, 2.6, makeXonoticCheckBox(0, "g_mirrordamage_virtual", _("Virtual penalty (effect only)")));
- me.TR(me);
- me.TDempty(me, 0.2);
- me.TD(me, 1, 1.2, makeXonoticTextLabel(0, _("Teams:")));
- me.TD(me, 1, 1.6, e = makeXonoticTextSlider("g_tdm_teams_override g_domination_teams_override g_ca_teams_override g_freezetag_teams_override g_keyhunt_teams_override"));
- e.addValue(e, "Default", "0");
- e.addValue(e, "2 teams", "2");
- e.addValue(e, "3 teams", "3");
- e.addValue(e, "4 teams", "4");
- e.configureXonoticTextSliderValues(e);
- me.TR(me);
- me.TR(me);
- me.TD(me, 1, 1, makeXonoticTextLabel(0, _("Map voting:")));
- me.TD(me, 1, 2, e = makeXonoticTextSlider("g_maplist_votable"));
- e.addValue(e, _("No voting"), "0");
- e.addValue(e, _("2 choices"), "2");
- e.addValue(e, _("3 choices"), "3");
- e.addValue(e, _("4 choices"), "4");
- e.addValue(e, _("5 choices"), "5");
- e.addValue(e, _("6 choices"), "6");
- e.addValue(e, _("7 choices"), "7");
- e.addValue(e, _("8 choices"), "8");
- e.addValue(e, _("9 choices"), "9");
- e.configureXonoticTextSliderValues(e);
- me.TR(me);
- me.TD(me, 1, 3, makeXonoticCheckBoxEx(0.5, 0, "sv_vote_simple_majority_factor", _("Simple majority wins vcall")));
-
- 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;
-}
-
-void XonoticAdvancedDialog_close(entity me)
-{
- if(me.refilterEntity)
- me.refilterEntity.refilter(me.refilterEntity);
- SUPER(XonoticAdvancedDialog).close(me);
-}
-#endif
ATTRIB(XonoticMapInfoDialog, title, string, _("Map Information"))
ATTRIB(XonoticMapInfoDialog, color, vector, SKINCOLOR_DIALOG_MAPINFO)
ATTRIB(XonoticMapInfoDialog, intendedWidth, float, 1.0)
- ATTRIB(XonoticMapInfoDialog, rows, float, 12)
+ ATTRIB(XonoticMapInfoDialog, rows, float, 11)
ATTRIB(XonoticMapInfoDialog, columns, float, 10)
ATTRIB(XonoticMapInfoDialog, previewImage, entity, NULL)
ATTRIB(XonoticMapInfoDialog, currentMapAuthor, string, string_null)
ATTRIB(XonoticMapInfoDialog, currentMapDescription, string, string_null)
ATTRIB(XonoticMapInfoDialog, currentMapPreviewImage, string, string_null)
- ATTRIB(XonoticMapInfoDialog, currentMapFeaturesText, string, string_null)
ENDCLASS(XonoticMapInfoDialog)
#endif
strunzone(me.currentMapAuthor);
strunzone(me.currentMapDescription);
strunzone(me.currentMapPreviewImage);
- strunzone(me.currentMapFeaturesText);
}
me.currentMapBSPName = strzone(MapInfo_Map_bspname);
me.currentMapTitle = strzone(strdecolorize(MapInfo_Map_title));
me.currentMapAuthor = strzone(strdecolorize(MapInfo_Map_author));
me.currentMapDescription = strzone(MapInfo_Map_description);
- me.currentMapFeaturesText = strzone((MapInfo_Map_supportedFeatures & MAPINFO_FEATURE_WEAPONS) ? _("Full item placement") : _("MinstaGib only"));
me.currentMapPreviewImage = strzone(strcat("/maps/", MapInfo_Map_bspname));
me.frame.setText(me.frame, me.currentMapBSPName);
me.titleLabel.setText(me.titleLabel, me.currentMapTitle);
me.authorLabel.setText(me.authorLabel, me.currentMapAuthor);
me.descriptionLabel.setText(me.descriptionLabel, me.currentMapDescription);
- me.featuresLabel.setText(me.featuresLabel, me.currentMapFeaturesText);
if(draw_PictureSize(me.currentMapPreviewImage) == '0 0 0')
me.previewImage.src = "nopreview_map";
else
e.colorL = SKINCOLOR_MAPLIST_AUTHOR;
e.allowCut = 1;
me.authorLabel = e;
- me.TR(me);
- me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Features:")));
- me.TD(me, 1, w-1, e = makeXonoticTextLabel(0, ""));
- e.allowCut = 1;
- me.featuresLabel = e;
me.TR(me);
me.TD(me, 1, w, e = makeXonoticTextLabel(0, _("Game types:")));
+++ /dev/null
-#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, 22)
- ATTRIB(XonoticDemoBrowserTab, columns, float, 4)
- ATTRIB(XonoticDemoBrowserTab, name, string, "DemoBrowser")
-ENDCLASS(XonoticDemoBrowserTab)
-entity makeXonoticDemoBrowserTab();
-#endif
-
-#ifdef IMPLEMENTATION
-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, 3.5, 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 = TimeDemo_Click;
- e.onClickEntity = dlist;
- me.TD(me, 1, me.columns / 2, e = makeXonoticButton(ZCTX(_("DEMO^Play")), '0 0 0'));
- e.onClick = StartDemo_Click;
- e.onClickEntity = dlist;
-}
-#endif
METHOD(XonoticServerListTab, fill, void(entity))
ATTRIB(XonoticServerListTab, title, string, _("Join"))
ATTRIB(XonoticServerListTab, intendedWidth, float, 0.9)
- ATTRIB(XonoticServerListTab, rows, float, 22)
+ ATTRIB(XonoticServerListTab, rows, float, 23)
ATTRIB(XonoticServerListTab, columns, float, 6.5)
ENDCLASS(XonoticServerListTab)
entity makeXonoticServerListTab();
slist = makeXonoticServerList();
- me.TR(me);
- me.TD(me, 1, 0.4, e = makeXonoticTextLabel(0, _("Filter:")));
- me.TD(me, 1, me.columns - 0.6 * 3 - 0.9 - 0.4, e = makeXonoticInputBox(0, string_null));
+ me.gotoRC(me, 0.5, 0);
+ me.TD(me, 1, 0.6, e = makeXonoticTextLabel(1, _("Filter:")));
+ me.TD(me, 1, 2.8, e = makeXonoticInputBox(0, string_null));
e.onChange = ServerList_Filter_Change;
e.onChangeEntity = slist;
slist.controlledTextbox = e;
+
+ me.gotoRC(me, 0.5, 3.6);
me.TD(me, 1, 0.9, e = makeXonoticCheckBox(0, "menu_slist_categories", ZCTX(_("SRVS^Categories"))));
e.onClickEntity = slist;
e.onClick = ServerList_Categories_Click;
e.onClick = ServerList_ShowFull_Click;
me.TD(me, 1, 0.6, e = makeXonoticCheckBox(0, "net_slist_pause", _("Pause")));
- me.TR(me);
+ me.gotoRC(me, 2, 0);
me.TD(me, 1, 1, slist.sortButton1 = makeXonoticButton(string_null, '0 0 0'));
me.TD(me, 1, 1, slist.sortButton2 = makeXonoticButton(string_null, '0 0 0'));
me.TD(me, 1, 1, slist.sortButton3 = makeXonoticButton(string_null, '0 0 0'));
me.TD(me, 1, 1, slist.sortButton4 = makeXonoticButton(string_null, '0 0 0'));
me.TD(me, 1, 1, slist.sortButton5 = makeXonoticButton(string_null, '0 0 0'));
me.TR(me);
- me.TD(me, me.rows - 4, me.columns, slist);
+ me.TD(me, me.rows - 5, me.columns, slist);
me.gotoRC(me, me.rows - 2, 0);
me.TD(me, 1, 0.6, e = makeXonoticTextLabel(0, _("Address:")));
--- /dev/null
+#ifdef INTERFACE
+CLASS(XonoticMediaTab) EXTENDS(XonoticTab)
+ METHOD(XonoticMediaTab, fill, void(entity))
+ ATTRIB(XonoticMediaTab, title, string, _("Demo"))
+ ATTRIB(XonoticMediaTab, intendedWidth, float, 0.9)
+ ATTRIB(XonoticMediaTab, rows, float, 23)
+ ATTRIB(XonoticMediaTab, columns, float, 2)
+ ATTRIB(XonoticMediaTab, name, string, "Media")
+ENDCLASS(XonoticMediaTab)
+entity makeXonoticMediaTab();
+#endif
+
+#ifdef IMPLEMENTATION
+entity makeXonoticMediaTab()
+{
+ entity me;
+ me = spawnXonoticMediaTab();
+ me.configureDialog(me);
+ return me;
+}
+void XonoticMediaTab_fill(entity me)
+{
+ entity mc, e;
+ mc = makeXonoticTabController(me.rows - 2);
+
+ me.gotoRC(me, 0.5, 0);
+ me.TD(me, 1, 1, e = mc.makeTabButton(mc, _("Demos"), makeXonoticDemoBrowserTab()));
+ me.TD(me, 1, 1, e = mc.makeTabButton(mc, _("Screenshots"), makeXonoticScreenshotBrowserTab()));
+
+ me.gotoRC(me, 3, 0);
+ me.TD(me, me.rows - 2, me.columns, mc);
+}
+#endif
--- /dev/null
+#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")
+ ATTRIB(XonoticDemoBrowserTab, democlicktype, float, 0)
+ENDCLASS(XonoticDemoBrowserTab)
+entity makeXonoticDemoBrowserTab();
+const float DMO_PLAY = 1;
+const float DMO_TIME = 2;
+#endif
+
+#ifdef IMPLEMENTATION
+void DemoConfirm_Check_Gamestatus(entity btn, entity me)
+{
+ if not(gamestatus & (GAME_CONNECTED | GAME_ISSERVER)) // we're not in a match, lets watch the demo
+ {
+ if(btn.democlicktype == DMO_PLAY)
+ { demolist.startDemo(demolist); }
+ else if(btn.democlicktype == DMO_TIME)
+ { demolist.timeDemo(demolist); }
+ }
+ else // already in a match, player has to confirm
+ {
+ if(btn.democlicktype == DMO_PLAY)
+ { DialogOpenButton_Click(btn, main.demostartconfirmDialog); }
+ else if(btn.democlicktype == DMO_TIME)
+ { DialogOpenButton_Click(btn, main.demotimeconfirmDialog); }
+ }
+}
+
+entity makeXonoticDemoBrowserTab()
+{
+ entity me;
+ me = spawnXonoticDemoBrowserTab();
+ me.configureDialog(me);
+ return me;
+}
+void XonoticDemoBrowserTab_fill(entity me)
+{
+ entity e;
+ demolist = makeXonoticDemoList();
+
+ me.TR(me);
+ me.TD(me, 1, 0.6, e = makeXonoticTextLabel(1, _("Filter:")));
+ me.TD(me, 1, 2.9, e = makeXonoticInputBox(0, string_null));
+ e.onChange = DemoList_Filter_Change;
+ e.onChangeEntity = demolist;
+ demolist.controlledTextbox = e;
+
+ me.gotoRC(me, 0, 3.7);
+ me.TD(me, 1, 1.5, e = makeXonoticCheckBox(0, "cl_autodemo", _("Auto record demos")));
+ me.TD(me, 1, 1, e = makeXonoticButton(_("Refresh"), '0 0 0'));
+ e.onClick = DemoList_Refresh_Click;
+ e.onClickEntity = demolist;
+
+ me.gotoRC(me, 1.5, 0);
+ me.TD(me, me.rows - 2.5, me.columns, demolist);
+
+ me.gotoRC(me, me.rows - 1, 0);
+ me.TD(me, 1, me.columns / 2, e = makeXonoticButton(_("Timedemo"), '0 0 0'));
+ e.democlicktype = DMO_TIME;
+ e.onClick = DemoConfirm_Check_Gamestatus;
+ e.onClickEntity = me; // demolist is global anyway
+ me.TD(me, 1, me.columns / 2, e = makeXonoticButton(ZCTX(_("DEMO^Play")), '0 0 0'));
+ e.democlicktype = DMO_PLAY;
+ e.onClick = DemoConfirm_Check_Gamestatus;
+ e.onClickEntity = me; // demolist is global anyway
+}
+#endif
--- /dev/null
+#ifdef INTERFACE
+CLASS(XonoticDemoStartConfirmDialog) EXTENDS(XonoticDialog)
+ METHOD(XonoticDemoStartConfirmDialog, fill, void(entity))
+ ATTRIB(XonoticDemoStartConfirmDialog, title, string, _("Disconnect"))
+ ATTRIB(XonoticDemoStartConfirmDialog, color, vector, SKINCOLOR_DIALOG_HUDCONFIRM)
+ ATTRIB(XonoticDemoStartConfirmDialog, intendedWidth, float, 0.5)
+ ATTRIB(XonoticDemoStartConfirmDialog, rows, float, 4)
+ ATTRIB(XonoticDemoStartConfirmDialog, columns, float, 2)
+ENDCLASS(XonoticDemoStartConfirmDialog)
+#endif
+
+#ifdef IMPLEMENTATION
+void Handle_StartDemo_Click(entity unused, entity me) { demolist.startDemo(demolist); }
+void XonoticDemoStartConfirmDialog_fill(entity me)
+{
+ entity e;
+
+ me.TR(me);
+ me.TD(me, 1, 2, e = makeXonoticTextLabel(0.5, _("Playing a demo will disconnect you from the current match.")));
+ me.TR(me);
+ me.TD(me, 1, 2, e = makeXonoticTextLabel(0.5, _("Do you really wish to disconnect now?")));
+ me.TR(me);
+ me.TR(me);
+ me.TD(me, 1, 1, e = makeXonoticButton(ZCTX(_("DMCNFRM^Yes")), '1 0 0'));
+ e.onClick = Handle_StartDemo_Click;
+ e.onClickEntity = demolist;
+ me.TD(me, 1, 1, e = makeXonoticButton(ZCTX(_("DMCNFRM^No")), '0 1 0'));
+ e.onClick = Dialog_Close;
+ e.onClickEntity = me;
+}
+#endif
--- /dev/null
+#ifdef INTERFACE
+CLASS(XonoticDemoTimeConfirmDialog) EXTENDS(XonoticDialog)
+ METHOD(XonoticDemoTimeConfirmDialog, fill, void(entity))
+ ATTRIB(XonoticDemoTimeConfirmDialog, title, string, _("Disconnect"))
+ ATTRIB(XonoticDemoTimeConfirmDialog, color, vector, SKINCOLOR_DIALOG_HUDCONFIRM)
+ ATTRIB(XonoticDemoTimeConfirmDialog, intendedWidth, float, 0.5)
+ ATTRIB(XonoticDemoTimeConfirmDialog, rows, float, 4)
+ ATTRIB(XonoticDemoTimeConfirmDialog, columns, float, 2)
+ENDCLASS(XonoticDemoTimeConfirmDialog)
+#endif
+
+#ifdef IMPLEMENTATION
+void Handle_TimeDemo_Click(entity unused, entity unused) { demolist.timeDemo(demolist); }
+void XonoticDemoTimeConfirmDialog_fill(entity me)
+{
+ entity e;
+
+ me.TR(me);
+ me.TD(me, 1, 2, e = makeXonoticTextLabel(0.5, _("Timing a demo will disconnect you from the current match.")));
+ me.TR(me);
+ me.TD(me, 1, 2, e = makeXonoticTextLabel(0.5, _("Do you really wish to disconnect now?")));
+ me.TR(me);
+ me.TR(me);
+ me.TD(me, 1, 1, e = makeXonoticButton(ZCTX(_("DMCNFRM^Yes")), '1 0 0'));
+ e.onClick = Handle_TimeDemo_Click;
+ e.onClickEntity = demolist;
+ me.TD(me, 1, 1, e = makeXonoticButton(ZCTX(_("DMCNFRM^No")), '0 1 0'));
+ e.onClick = Dialog_Close;
+ e.onClickEntity = me;
+}
+#endif
--- /dev/null
+#ifdef INTERFACE
+CLASS(XonoticScreenshotBrowserTab) EXTENDS(XonoticTab)
+ METHOD(XonoticScreenshotBrowserTab, fill, void(entity))
+ ATTRIB(XonoticScreenshotBrowserTab, title, string, "Screenshot")
+ ATTRIB(XonoticScreenshotBrowserTab, intendedWidth, float, 1)
+ ATTRIB(XonoticScreenshotBrowserTab, rows, float, 21)
+ ATTRIB(XonoticScreenshotBrowserTab, columns, float, 6.5)
+ ATTRIB(XonoticScreenshotBrowserTab, name, string, "ScreenshotBrowser")
+
+ METHOD(XonoticScreenshotBrowserTab, loadPreviewScreenshot, void(entity, string))
+ ATTRIB(XonoticScreenshotBrowserTab, screenshotImage, entity, NULL)
+ ATTRIB(XonoticScreenshotBrowserTab, currentScrPath, string, string_null)
+ENDCLASS(XonoticScreenshotBrowserTab)
+entity makeXonoticScreenshotBrowserTab();
+#endif
+
+#ifdef IMPLEMENTATION
+entity makeXonoticScreenshotBrowserTab()
+{
+ entity me;
+ me = spawnXonoticScreenshotBrowserTab();
+ me.configureDialog(me);
+ return me;
+}
+void XonoticScreenshotBrowserTab_loadPreviewScreenshot(entity me, string scrImage)
+{
+ if (me.currentScrPath == scrImage)
+ return;
+ if (me.currentScrPath)
+ strunzone(me.currentScrPath);
+ me.currentScrPath = strzone(scrImage);
+ me.screenshotImage.load(me.screenshotImage, me.currentScrPath);
+}
+void XonoticScreenshotBrowserTab_fill(entity me)
+{
+ entity e, slist;
+ slist = makeXonoticScreenshotList();
+ float slist_height = me.rows - 2;
+
+
+ me.TR(me);
+ me.TD(me, 1, 0.6, e = makeXonoticTextLabel(1, _("Filter:")));
+ me.TD(me, 1, 2.4, e = makeXonoticInputBox(0, string_null));
+ e.onChange = ScreenshotList_Filter_Would_Change;
+ e.onChangeEntity = slist;
+ slist.screenshotViewerDialog = main.screenshotViewerDialog;
+ main.screenshotViewerDialog.scrList = slist;
+
+ me.gotoRC(me, 0, 3.1);
+ me.TD(me, 1, 1.9, e = makeXonoticCheckBoxEx(2, 1, "cl_autoscreenshot", _("Auto screenshot scoreboard")));
+ me.TD(me, 1, 1, e = makeXonoticButton(_("Refresh"), '0 0 0'));
+ e.onClick = ScreenshotList_Refresh_Click;
+ e.onClickEntity = slist;
+
+ /*me.TR(me);
+ me.TD(me, 1, 0.5, e = makeXonoticTextLabel(0, "Filter:"));
+ me.TD(me, 1, me.columns - 1.5, e = makeXonoticInputBox(0, string_null));
+ e.onChange = ScreenshotList_Filter_Would_Change;
+ e.onChangeEntity = slist;
+ slist.screenshotViewerDialog = main.screenshotViewerDialog;
+ main.screenshotViewerDialog.scrList = slist;
+ me.TD(me, 1, 1, e = makeXonoticButton(_("Refresh"), '0 0 0'));
+ e.onClick = ScreenshotList_Refresh_Click;
+ e.onClickEntity = slist;*/
+
+ me.gotoRC(me, 1.5, 0);
+ me.TD(me, me.rows - 2.5, me.columns, slist);
+
+ me.gotoRC(me, slist_height + 1, 0);
+ me.TD(me, 1, me.columns, e = makeXonoticButton(_("Open in the viewer"), '0 0 0'));
+ e.onClick = StartScreenshot_Click;
+ e.onClickEntity = slist;
+/*
+ me.TR(me);
+ me.TD(me, me.rows - me.currentRow, me.columns, e = makeXonoticScreenshotImage());
+ e.showTitle = 0;
+ me.screenshotImage = e;
+ slist.screenshotPreview = e;
+ slist.screenshotBrowserDialog = me;
+*/
+}
+#endif
--- /dev/null
+#ifdef INTERFACE
+CLASS(XonoticScreenshotViewerDialog) EXTENDS(XonoticDialog)
+ METHOD(XonoticScreenshotViewerDialog, fill, void(entity))
+ METHOD(XonoticScreenshotViewerDialog, keyDown, float(entity, float, float, float))
+ METHOD(XonoticScreenshotViewerDialog, loadScreenshot, void(entity, string))
+ METHOD(XonoticScreenshotViewerDialog, close, void(entity))
+ ATTRIB(XonoticScreenshotViewerDialog, title, string, "Screenshot Viewer")
+ ATTRIB(XonoticScreenshotViewerDialog, name, string, "ScreenshotViewer")
+ ATTRIB(XonoticScreenshotViewerDialog, intendedWidth, float, 1)
+ ATTRIB(XonoticScreenshotViewerDialog, rows, float, 25)
+ ATTRIB(XonoticScreenshotViewerDialog, columns, float, 4)
+ ATTRIB(XonoticScreenshotViewerDialog, color, vector, SKINCOLOR_DIALOG_SCREENSHOTVIEWER)
+ ATTRIB(XonoticScreenshotViewerDialog, scrList, entity, NULL)
+ ATTRIB(XonoticScreenshotViewerDialog, screenshotImage, entity, NULL)
+ ATTRIB(XonoticScreenshotViewerDialog, slideShowButton, entity, NULL)
+ ATTRIB(XonoticScreenshotViewerDialog, currentScrPath, string, string_null)
+ENDCLASS(XonoticScreenshotViewerDialog)
+#endif
+
+#ifdef IMPLEMENTATION
+float music_playlist_index_backup;
+void XonoticScreenshotViewerDialog_loadScreenshot(entity me, string scrImage)
+{
+ // disable music as it can lag depending on image loading time
+ if(!cvar("menu_screenshotviewer_enablemusic"))
+ if(cvar("music_playlist_index") != 999) // if the playlist isn't paused
+ {
+ // pause music
+ if(cvar("music_playlist_index") != -1)
+ {
+ music_playlist_index_backup = cvar("music_playlist_index");
+ cvar_set("music_playlist_sampleposition0", "0");
+ cvar_set("music_playlist_index", "999");
+ }
+ else
+ localcmd("\ncd pause\n");
+ }
+
+ if (me.currentScrPath == scrImage)
+ return;
+ if (me.currentScrPath)
+ strunzone(me.currentScrPath);
+ me.currentScrPath = strzone(scrImage);
+ me.screenshotImage.load(me.screenshotImage, me.currentScrPath);
+ me.frame.setText(me.frame, me.screenshotImage.screenshotTitle);
+}
+void prevScreenshot_Click(entity btn, entity me)
+{
+ me.scrList.goScreenshot(me.scrList, -1);
+}
+void nextScreenshot_Click(entity btn, entity me)
+{
+ me.scrList.goScreenshot(me.scrList, +1);
+}
+void increaseZoom_Click(entity btn, entity me)
+{
+ me.screenshotImage.setZoom(me.screenshotImage, -2, FALSE);
+}
+void decreaseZoom_Click(entity btn, entity me)
+{
+ me.screenshotImage.setZoom(me.screenshotImage, -1/2, FALSE);
+}
+void resetZoom_Click(entity btn, entity me)
+{
+ me.screenshotImage.setZoom(me.screenshotImage, 0, FALSE);
+}
+void toggleSlideShow_Click(entity btn, entity me)
+{
+ if (me.slideShowButton.forcePressed)
+ {
+ me.scrList.stopSlideShow(me.scrList);
+ me.slideShowButton.forcePressed = 0;
+ }
+ else
+ {
+ me.scrList.startSlideShow(me.scrList);
+ me.slideShowButton.forcePressed = 1;
+ }
+}
+float XonoticScreenshotViewerDialog_keyDown(entity me, float key, float ascii, float shift)
+{
+ switch(key)
+ {
+ case K_KP_LEFTARROW:
+ case K_LEFTARROW:
+ me.scrList.goScreenshot(me.scrList, -1);
+ return 1;
+ case K_KP_RIGHTARROW:
+ case K_RIGHTARROW:
+ me.scrList.goScreenshot(me.scrList, +1);
+ return 1;
+ case K_KP_ENTER:
+ case K_ENTER:
+ case K_SPACE:
+ // we cannot use SPACE/ENTER directly, as in a dialog they are needed
+ // to press buttons while browsing with only the keyboard
+ if (shift & S_CTRL)
+ {
+ toggleSlideShow_Click(world, me);
+ return 1;
+ }
+ return SUPER(XonoticScreenshotViewerDialog).keyDown(me, key, ascii, shift);
+ default:
+ if (key == K_MWHEELUP || ascii == '+')
+ {
+ me.screenshotImage.setZoom(me.screenshotImage, -2, (key == K_MWHEELUP));
+ return 1;
+ }
+ else if (key == K_MWHEELDOWN || ascii == '-')
+ {
+ me.screenshotImage.setZoom(me.screenshotImage, -1/2, (key == K_MWHEELDOWN));
+ return 1;
+ }
+ if (me.scrList.keyDown(me.scrList, key, ascii, shift))
+ {
+ // keyDown has already changed the selected item
+ me.scrList.goScreenshot(me.scrList, 0);
+ return 1;
+ }
+ return SUPER(XonoticScreenshotViewerDialog).keyDown(me, key, ascii, shift);
+ }
+}
+void XonoticScreenshotViewerDialog_close(entity me)
+{
+ // resume music
+ if(!cvar("menu_screenshotviewer_enablemusic"))
+ if(cvar("music_playlist_index") == 999)
+ {
+ cvar_set("music_playlist_index", ftos(music_playlist_index_backup));
+ }
+ else
+ localcmd("\ncd resume\n");
+
+ me.scrList.stopSlideShow(me.scrList);
+ me.slideShowButton.forcePressed = 0;
+ SUPER(XonoticScreenshotViewerDialog).close(me);
+}
+void XonoticScreenshotViewerDialog_fill(entity me)
+{
+ entity e;
+ me.TR(me);
+ me.TD(me, me.rows - 1, me.columns, e = makeXonoticScreenshotImage());
+ e.showTitle = 0; // dialog title is enough
+ me.screenshotImage = e;
+ me.gotoRC(me, me.rows - 1, 0);
+ me.TDempty(me, 1/20 * me.columns);
+ me.TD(me, 1, 1/20 * me.columns, e = makeXonoticButton("-", '0 0 0'));
+ e.onClick = decreaseZoom_Click;
+ e.onClickEntity = me;
+ me.TD(me, 1, 1/20 * me.columns, e = makeXonoticButton("+", '0 0 0'));
+ e.onClick = increaseZoom_Click;
+ e.onClickEntity = me;
+ me.TD(me, 1, 2/20 * me.columns, e = makeXonoticButton(_("Reset"), '0 0 0'));
+ e.onClick = resetZoom_Click;
+ e.onClickEntity = me;
+
+ me.TDempty(me, 2/20 * me.columns);
+ me.TD(me, 1, 3/20 * me.columns, e = makeXonoticButton(_("Previous"), '0 0 0'));
+ e.onClick = prevScreenshot_Click;
+ e.onClickEntity = me;
+ me.TD(me, 1, 3/20 * me.columns, e = makeXonoticButton(_("Next"), '0 0 0'));
+ e.onClick = nextScreenshot_Click;
+ e.onClickEntity = me;
+
+ me.TDempty(me, 2/20 * me.columns);
+ me.TD(me, 1, 4/20 * me.columns, e = makeXonoticButton(_("Slide show"), '0 0 0'));
+ e.onClick = toggleSlideShow_Click;
+ e.onClickEntity = me;
+ me.slideShowButton = e;
+}
+#endif
+++ /dev/null
-#ifdef INTERFACE
-CLASS(XonoticPlayerSettingsTab) EXTENDS(XonoticTab)
- METHOD(XonoticPlayerSettingsTab, fill, void(entity))
- METHOD(XonoticPlayerSettingsTab, draw, void(entity))
- ATTRIB(XonoticPlayerSettingsTab, title, string, _("Player Setup"))
- ATTRIB(XonoticPlayerSettingsTab, intendedWidth, float, 0.9)
- ATTRIB(XonoticPlayerSettingsTab, rows, float, 22)
- ATTRIB(XonoticPlayerSettingsTab, columns, float, 6.2) // added extra .2 for center space
- ATTRIB(XonoticPlayerSettingsTab, playerNameLabel, entity, NULL)
- ATTRIB(XonoticPlayerSettingsTab, playerNameLabelAlpha, float, 0)
-ENDCLASS(XonoticPlayerSettingsTab)
-entity makeXonoticPlayerSettingsTab();
-#endif
-
-#ifdef IMPLEMENTATION
-entity makeXonoticPlayerSettingsTab()
-{
- entity me;
- me = spawnXonoticPlayerSettingsTab();
- me.configureDialog(me);
- return me;
-}
-void XonoticPlayerSettingsTab_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(XonoticPlayerSettingsTab).draw(me);
-}
-void XonoticPlayerSettingsTab_fill(entity me)
-{
- entity e, pms, label, box;
- float i;
-
- 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);
-
- me.TR(me);
- me.TDempty(me, 1);
- me.TD(me, 1, 2, e = makeXonoticTextLabel(0.5, _("Model:")));
- me.TR(me);
- me.TDempty(me, 1);
- pms = makeXonoticPlayerModelSelector();
- me.TD(me, 1, 0.3, e = makeXonoticButton("<<", '0 0 0'));
- e.onClick = PlayerModelSelector_Prev_Click;
- e.onClickEntity = pms;
- me.TD(me, me.rows - (me.currentRow + 2), 1.4, pms);
- me.TD(me, 1, 0.3, e = makeXonoticButton(">>", '0 0 0'));
- e.onClick = PlayerModelSelector_Next_Click;
- e.onClickEntity = pms;
- 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.TR(me);
- 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
- //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
+++ /dev/null
-#ifdef INTERFACE
-CLASS(XonoticCrosshairDialog) EXTENDS(XonoticDialog)
- METHOD(XonoticCrosshairDialog, toString, string(entity))
- METHOD(XonoticCrosshairDialog, fill, void(entity))
- METHOD(XonoticCrosshairDialog, showNotify, void(entity))
- ATTRIB(XonoticCrosshairDialog, title, string, _("Crosshair settings"))
- ATTRIB(XonoticCrosshairDialog, color, vector, SKINCOLOR_DIALOG_CROSSHAIR)
- ATTRIB(XonoticCrosshairDialog, intendedWidth, float, 0.5)
- ATTRIB(XonoticCrosshairDialog, rows, float, 18)
- ATTRIB(XonoticCrosshairDialog, columns, float, 3)
-ENDCLASS(XonoticCrosshairDialog)
-#endif
-
-#ifdef IMPLEMENTATION
-void XonoticCrosshairDialog_showNotify(entity me)
-{
- loadAllCvars(me);
-}
-string XonoticCrosshairDialog_toString(entity me)
-{
- return "hi"; // TODO: show status of crosshair dot and hittest and pickups and such here with text
-}
-void XonoticCrosshairDialog_fill(entity me)
-{
- entity e;
-
- me.TR(me);
- me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "crosshair_dot", _("Enable center crosshair dot")));
- setDependent(e, "crosshair_enabled", 1, 2);
- me.TR(me);
- me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Dot size:")));
- setDependentAND(e, "crosshair_dot", 1, 1, "crosshair_enabled", 1, 2);
- me.TD(me, 1, 2, e = makeXonoticSlider(0.2, 2, 0.1, "crosshair_dot_size"));
- setDependentAND(e, "crosshair_dot", 1, 1, "crosshair_enabled", 1, 2);
- me.TR(me);
- me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Dot alpha:")));
- setDependentAND(e, "crosshair_dot", 1, 1, "crosshair_enabled", 1, 2);
- me.TD(me, 1, 2, e = makeXonoticSlider(0.1, 1, 0.1, "crosshair_dot_alpha"));
- setDependentAND(e, "crosshair_dot", 1, 1, "crosshair_enabled", 1, 2);
- me.TR(me);
- me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Dot color:")));
- setDependentAND(e, "crosshair_dot", 1, 1, "crosshair_enabled", 1, 2);
- me.TD(me, 1, 2, e = makeXonoticRadioButton(1, "crosshair_dot_color_custom", "0", _("Use normal crosshair color")));
- setDependentAND(e, "crosshair_dot", 1, 1, "crosshair_enabled", 1, 2);
- me.TR(me);
- me.TDempty(me, 0.1);
- me.TD(me, 1, 0.8, e = makeXonoticRadioButton(1, "crosshair_dot_color_custom", "1", _("Custom")));
- setDependentAND(e, "crosshair_dot", 1, 1, "crosshair_enabled", 1, 2);
- me.TD(me, 2, 2, e = makeXonoticColorpickerString("crosshair_dot_color", "crosshair_dot_color"));
- setDependentAND3(e, "crosshair_dot", 1, 1, "crosshair_enabled", 1, 2, "crosshair_dot_color_custom", 1, 1);
- me.TR(me);
- me.TR(me);
- me.TR(me);
- me.TD(me, 1, 3, e = makeXonoticTextLabel(0, _("Crosshair animations:")));
- me.TR(me);
- me.TDempty(me, 0.2);
- me.TD(me, 1, 2.8, e = makeXonoticCheckBox(0, "crosshair_effect_scalefade", _("Smooth effects of crosshairs")));
- setDependent(e, "crosshair_enabled", 1, 2);
- me.TR(me);
- me.TDempty(me, 0.2);
- me.TD(me, 1, 2.8, e = makeXonoticCheckBox(0, "crosshair_ring", _("Use rings to indicate weapon status")));
- makeMulti(e, "crosshair_ring_reload");
- setDependent(e, "crosshair_enabled", 1, 2);
- me.TR(me);
- me.TR(me);
- me.TDempty(me, 0.2);
- me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Hit testing:")));
- me.TD(me, 1, 2, e = makeXonoticTextSlider("crosshair_hittest"));
- e.addValue(e, ZCTX(_("HTTST^Disabled")), "0");
- e.addValue(e, ZCTX(_("HTTST^TrueAim")), "1");
- e.addValue(e, ZCTX(_("HTTST^Enemies")), "1.25");
- e.configureXonoticTextSliderValues(e);
- setDependent(e, "crosshair_enabled", 1, 2);
- me.TR(me);
- me.TDempty(me, 0.2);
- me.TD(me, 1, 2.8, e = makeXonoticCheckBox(0, "crosshair_hittest_blur", _("Blur crosshair if the shot is obstructed")));
- setDependentAND(e, "crosshair_hittest", 1, 100, "crosshair_enabled", 1, 2);
- me.TR(me);
- me.TR(me);
- me.TDempty(me, 0.2);
- me.TD(me, 1, 2.8, e = makeXonoticCheckBoxEx(0.5, 0, "crosshair_hitindication", _("Animate when hitting an enemy")));
- setDependent(e, "crosshair_enabled", 1, 2);
- me.TR(me);
- me.TDempty(me, 0.2);
- me.TD(me, 1, 2.8, e = makeXonoticCheckBoxEx(0.25, 0, "crosshair_pickup", _("Animate when picking up an item")));
- setDependent(e, "crosshair_enabled", 1, 2);
-
- 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(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)
-{
- 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);
-
- 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;
- // 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
-#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(XonoticViewDialog) EXTENDS(XonoticDialog)
- METHOD(XonoticViewDialog, toString, string(entity))
- METHOD(XonoticViewDialog, fill, void(entity))
- METHOD(XonoticViewDialog, showNotify, void(entity))
- ATTRIB(XonoticViewDialog, title, string, _("View settings"))
- ATTRIB(XonoticViewDialog, color, vector, SKINCOLOR_DIALOG_VIEW)
- ATTRIB(XonoticViewDialog, intendedWidth, float, 0.9)
- ATTRIB(XonoticViewDialog, rows, float, 11)
- ATTRIB(XonoticViewDialog, columns, float, 6.2) // added extra .2 for center space
-ENDCLASS(XonoticViewDialog)
-#endif
-
-#ifdef IMPLEMENTATION
-void XonoticViewDialog_showNotify(entity me)
-{
- loadAllCvars(me);
-}
-string XonoticViewDialog_toString(entity me)
-{
- return "hi"; // TODO: show fov and other settings with text here
-}
-void XonoticViewDialog_fill(entity me)
-{
- entity e;
-
- me.TR(me);
- 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.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Zoom:")));
- me.TD(me, 1, 2, e = makeXonoticTextSlider("cl_reticle"));
- e.addValue(e, ZCTX(_("RETICLE^Fullscreen")), "0");
- e.addValue(e, ZCTX(_("RETICLE^With reticle")), "1");
- e.configureXonoticTextSliderValues(e);
- me.TR(me);
- me.TDempty(me, 0.2);
- me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, ZCTX(_("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, 0.8, e = makeXonoticTextLabel(0, ZCTX(_("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, 0.8, e = makeXonoticTextLabel(0, ZCTX(_("ZOOM^Sensitivity:"))));
- me.TD(me, 1, 2, e = makeXonoticSlider(0, 1, 0.1, "cl_zoomsensitivity"));
- me.TR(me);
- me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Velocity zoom:")));
- me.TD(me, 1, 2, e = makeXonoticTextSlider("cl_velocityzoom_type"));
- e.addValue(e, ZCTX(_("VZOOM^Disabled")), "0");
- e.addValue(e, ZCTX(_("VZOOM^Forward only")), "2");
- e.addValue(e, ZCTX(_("VZOOM^All directions")), "1");
- e.configureXonoticTextSliderValues(e);
- me.TR(me);
- me.TDempty(me, 0.2);
- me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, ZCTX(_("VZOOM^Speed"))));
- me.TD(me, 1, 2, e = makeXonoticSlider(-1, 1, 0.2, "cl_velocityzoom"));
- setDependent(e, "cl_velocityzoom_type", 1, 3);
- me.TR(me);
- me.TR(me);
- me.TD(me, 1, 3, e = makeXonoticCheckBox(1, "cl_clippedspectating", _("Allow passing through walls while spectating")));
-
- me.gotoRC(me, 0, 3.2); me.setFirstColumn(me, me.currentColumn);
- 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.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(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
--- /dev/null
+#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)
+ ATTRIB(XonoticProfileTab, columns, float, 6.1) // 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;
+
+ // ==============
+ // NAME SECTION
+ // ==============
+ me.gotoRC(me, 0.5, 0);
+ me.TD(me, 1, 3, me.playerNameLabel = makeXonoticTextLabel(0.5, _("Name")));
+ me.playerNameLabel.isBold = TRUE;
+ me.playerNameLabelAlpha = 0.5;
+
+ me.gotoRC(me, 1.5, 0);
+ me.TD(me, 1, 3, label = makeXonoticTextLabel(0.5, string_null));
+ label.allowCut = 1;
+ label.allowColors = 1;
+ label.alpha = 1;
+ label.isBold = TRUE;
+ label.fontSize = SKINFONTSIZE_TITLE;
+
+ me.gotoRC(me, 2.5, 0);
+ 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));
+
+ // ===============
+ // MODEL SECTION
+ // ===============
+ //me.gotoRC(me, 0.5, 3.1); me.setFirstColumn(me, me.currentColumn); // TOP RIGHT
+ //me.gotoRC(me, 9, 3.1); me.setFirstColumn(me, me.currentColumn); // BOTTOM RIGHT
+ me.gotoRC(me, 9, 0); me.setFirstColumn(me, me.currentColumn); // BOTTOM LEFT
+ me.TD(me, 1, 3, e = makeXonoticTextLabel(0.5, _("Model")));
+ e.isBold = TRUE;
+ e.alpha = 0.5;
+ me.TR(me);
+ //me.TDempty(me, 0); // MODEL LEFT, COLOR RIGHT
+ me.TDempty(me, 1); // MODEL RIGHT, COLOR LEFT
+ pms = makeXonoticPlayerModelSelector();
+ me.TD(me, 1, 0.3, e = makeXonoticButton("<<", '0 0 0'));
+ e.onClick = PlayerModelSelector_Prev_Click;
+ e.onClickEntity = pms;
+ me.TD(me, 11.5, 1.4, pms);
+ me.TD(me, 1, 0.3, e = makeXonoticButton(">>", '0 0 0'));
+ e.onClick = PlayerModelSelector_Next_Click;
+ e.onClickEntity = pms;
+
+ //me.setFirstColumn(me, me.currentColumn + 2); // MODEL LEFT, COLOR RIGHT
+ me.gotoRC(me, me.currentRow, 0); me.setFirstColumn(me, me.currentColumn); // MODEL RIGHT, COLOR LEFT
+ me.TR(me);
+ me.TD(me, 1, 1, e = makeXonoticTextLabel(0.5, _("Glowing color")));
+ e.isBold = TRUE;
+ e.alpha = 0.5;
+ 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.TR(me);
+ me.TR(me);
+ me.TD(me, 1, 1, e = makeXonoticTextLabel(0.5, _("Detail color")));
+ e.isBold = TRUE;
+ e.alpha = 0.5;
+ 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');
+ }
+
+ // ====================
+ // STATISTICS SECTION
+ // ====================
+ me.gotoRC(me, 0.5, 3.1); me.setFirstColumn(me, me.currentColumn); // TOP RIGHT
+ //me.gotoRC(me, 9, 3.1); me.setFirstColumn(me, me.currentColumn); // BOTTOM RIGHT
+ //me.gotoRC(me, 9, 0); me.setFirstColumn(me, me.currentColumn); // BOTTOM LEFT
+ me.TD(me, 1, 3, e = makeXonoticTextLabel(0.5, _("Statistics")));
+ e.isBold = TRUE;
+ e.alpha = 0.5;
+ me.TR(me);
+ me.TDempty(me, 0.25);
+ me.TD(me, 1, 2.5, e = makeXonoticCheckBox(0, "cl_allow_uidtracking", _("Allow player statistics to track your client")));
+ me.TR(me);
+ me.TDempty(me, 0.25);
+ me.TD(me, 1, 2.5, e = makeXonoticCheckBox(0, "cl_allow_uid2name", _("Allow player statistics to use your nickname")));
+ setDependent(e, "cl_allow_uidtracking", 1, 1);
+ me.gotoRC(me, 4, 3.1); // TOP RIGHT
+ //me.gotoRC(me, 12.5, 3.1); // BOTTOM RIGHT
+ //me.gotoRC(me, 12.5, 0); // BOTTOM LEFT
+ me.TDempty(me, 0.25);
+ me.TD(me, 9, 2.5, statslist = makeXonoticStatsList());
+ //setDependent(statslist, "cl_allow_uidtracking", 1, 1);
+
+ // =================
+ // COUNTRY SECTION
+ // =================
+ me.gotoRC(me, 16, 3.1); me.setFirstColumn(me, me.currentColumn); // BOTTOM SECTION, TOP POS
+ //me.gotoRC(me, 13.5, 3.1); me.setFirstColumn(me, me.currentColumn); // BOTTOM SECTION, TOP POS
+ //me.gotoRC(me, 0.5, 3.1); me.setFirstColumn(me, me.currentColumn); // TOP SECTION, TOP POS
+ me.TD(me, 1, 3, e = makeXonoticTextLabel(0.5, _("Country")));
+ e.isBold = TRUE;
+ e.alpha = 0.5;
+ me.TR(me);
+ me.TDempty(me, 0.5);
+ me.TD(me, 4.5, 2, e = makeXonoticLanguageList()); // todo: cl_country: create proper country list
+
+
+ // ================
+ // GENDER SECTION
+ // ================
+ me.gotoRC(me, 13.5, 3.1); me.setFirstColumn(me, me.currentColumn); // BOTTOM SECTION, TOP POS
+ //me.gotoRC(me, 19.5, 3.1); me.setFirstColumn(me, me.currentColumn); // BOTTOM SECTION, BOTTOM POS
+ //me.gotoRC(me, 6.5, 3.1); me.setFirstColumn(me, me.currentColumn); // TOP SECTION, BOTTOM POS
+ #if 0
+ me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Gender:")));
+ me.TD(me, 1, 2, e = makeXonoticTextSlider("cl_gender"));
+ e.addValue(e, ZCTX(_("GENDER^Undisclosed")), "0");
+ e.addValue(e, ZCTX(_("GENDER^Female")), "1");
+ e.addValue(e, ZCTX(_("GENDER^Male")), "2");
+ e.configureXonoticTextSliderValues(e);
+ #else
+ me.TD(me, 1, 3, e = makeXonoticTextLabel(0.5, _("Gender")));
+ e.isBold = TRUE;
+ e.alpha = 0.5;
+ me.TR(me);
+ #define GENDERWIDTH_OFFSET 0.25
+ #define GENDERWIDTH_LENGTH 2.5
+ #define GENDERWIDTH_ITEM (GENDERWIDTH_LENGTH / 3)
+ me.TDempty(me, GENDERWIDTH_OFFSET);
+ me.TD(me, 1, GENDERWIDTH_ITEM, e = makeXonoticRadioButton(3, "cl_gender", "2", _("Female")));
+ me.TD(me, 1, GENDERWIDTH_ITEM, e = makeXonoticRadioButton(3, "cl_gender", "1", _("Male")));
+ me.TD(me, 1, GENDERWIDTH_ITEM, e = makeXonoticRadioButton(3, "cl_gender", "0", _("Undisclosed")));
+ #endif
+
+ 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
ATTRIB(XonoticSettingsDialog, title, string, _("Settings"))
ATTRIB(XonoticSettingsDialog, color, vector, SKINCOLOR_DIALOG_SETTINGS)
ATTRIB(XonoticSettingsDialog, intendedWidth, float, 0.96)
- ATTRIB(XonoticSettingsDialog, rows, float, 19)
+ ATTRIB(XonoticSettingsDialog, rows, float, 17)
ATTRIB(XonoticSettingsDialog, columns, float, 6)
ENDCLASS(XonoticSettingsDialog)
#endif
void XonoticSettingsDialog_fill(entity me)
{
entity mc;
- mc = makeXonoticTabController(me.rows - 2);
+ mc = makeXonoticTabController(me.rows - 2.5);
me.TR(me);
- me.TD(me, 1, 1, mc.makeTabButton(mc, _("Input"), makeXonoticInputSettingsTab()));
- me.TD(me, 1, 1, mc.makeTabButton(mc, _("Video"), makeXonoticVideoSettingsTab()));
- me.TD(me, 1, 1, mc.makeTabButton(mc, _("Effects"), makeXonoticEffectsSettingsTab()));
- me.TD(me, 1, 1, mc.makeTabButton(mc, _("Audio"), makeXonoticAudioSettingsTab()));
- me.TD(me, 1, 1, mc.makeTabButton(mc, _("User"), makeXonoticUserSettingsTab()));
- me.TD(me, 1, 1, mc.makeTabButton(mc, _("Misc"), makeXonoticMiscSettingsTab()));
+ me.TD(me, 1, 2, mc.makeTabButton(mc, _("Video"), makeXonoticVideoSettingsTab()));
+ me.TD(me, 1, 2, mc.makeTabButton(mc, _("Effects"), makeXonoticEffectsSettingsTab()));
+ me.TD(me, 1, 2, mc.makeTabButton(mc, _("Audio"), makeXonoticAudioSettingsTab()));
me.TR(me);
- me.TR(me);
- me.TD(me, me.rows - 2, me.columns, mc);
+ me.TD(me, 1, 1.5, mc.makeTabButton(mc, _("Game"), makeXonoticGameSettingsTab()));
+ me.TD(me, 1, 1.5, mc.makeTabButton(mc, _("Input"), makeXonoticInputSettingsTab()));
+ me.TD(me, 1, 1.5, mc.makeTabButton(mc, _("User"), makeXonoticUserSettingsTab()));
+ me.TD(me, 1, 1.5, mc.makeTabButton(mc, _("Misc"), makeXonoticMiscSettingsTab()));
+ me.gotoRC(me, 2.5, 0);
+ me.TD(me, me.rows - 2.5, me.columns, mc);
}
#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, 14.5)
ATTRIB(XonoticAudioSettingsTab, columns, float, 6.2) // added extra .2 for center space
ENDCLASS(XonoticAudioSettingsTab)
entity makeXonoticAudioSettingsTab();
void XonoticAudioSettingsTab_fill(entity me)
{
- entity e, s, sl;
+ entity e, s;
me.TR(me);
s = makeXonoticDecibelsSlider(-40, 0, 0.4, "mastervolume");
e.addValue(e, _("7.1"), "8");
e.configureXonoticTextSliderValues(e);
me.TR(me);
- me.TD(me, 1, 1.2, e = makeXonoticCheckBox(0, "snd_swapstereo", _("Swap Stereo")));
+ me.TR(me);
+ me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "snd_swapstereo", _("Swap stereo output channels")));
setDependent(e, "snd_channels", 1.5, 0.5);
- me.TD(me, 1, 1.8, e = makeXonoticCheckBox(0, "snd_spatialization_control", _("Headphone friendly mode")));
+ me.TR(me);
+ me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "snd_spatialization_control", _("Headphone friendly mode")));
setDependent(e, "snd_channels", 1.5, 0.5);
me.TR(me);
me.TR(me);
me.TD(me, 1, 3, makeXonoticCheckBox(0, "cl_hitsound", _("Hit indication sound")));
+ e.sendCvars = TRUE;
me.TR(me);
me.TD(me, 1, 3, makeXonoticCheckBox(0, "con_chatsound", _("Chat message sound")));
me.TR(me);
e.addValue(e, ZCTX(_("WRN^Both")), "3");
e.configureXonoticTextSliderValues(e);
me.TR(me);
- me.TR(me);
- sl = makeXonoticSlider(0.15, 1, 0.05, "cl_autotaunt");
- sl.valueDisplayMultiplier = 100;
- sl.valueDigits = 0;
- me.TD(me, 1, 3, e = makeXonoticSliderCheckBox(0, 1, sl, _("Automatic taunts")));
- if(sl.value != e.savedValue)
- e.savedValue = 0.65; // default
- me.TR(me);
- me.TDempty(me, 0.2);
- me.TD(me, 1, 0.8, makeXonoticTextLabel(0, _("Frequency:")));
- me.TD(me, 1, 2, sl);
+ me.TD(me, 1, 1, makeXonoticTextLabel(0, _("Automatic taunts:")));
+ me.TD(me, 1, 2, e = makeXonoticTextSlider("cl_autotaunt"));
+ e.addValue(e, _("Never"), "0");
+ e.addValue(e, _("Sometimes"), "0.35");
+ e.addValue(e, _("Often"), "0.65");
+ e.addValue(e, _("Always"), "1");
+ e.configureXonoticTextSliderValues(e);
+ e.sendCvars = TRUE;
me.TR(me);
me.TR(me);
if(cvar("developer"))
me.TD(me, 1, 3, makeXonoticCheckBox(0, "showsound", _("Debug info about sounds")));
me.gotoRC(me, me.rows - 1, 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));
+ me.TD(me, 1, me.columns, makeXonoticCommandButton(_("Apply immediately"), '0 0 0', "snd_restart; snd_attenuation_method_${menu_snd_attenuation_method}", 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, 14.5)
ATTRIB(XonoticEffectsSettingsTab, columns, float, 6.2) // added extra .2 for center space
ENDCLASS(XonoticEffectsSettingsTab)
entity makeXonoticEffectsSettingsTab();
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.25, 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");
e.configureXonoticTextSliderValues(e);
me.TR(me);
me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Player detail:")));
- me.TD(me, 1, 2, e = makeXonoticSlider(4, 0, -0.1, "cl_playerdetailreduction"));
+ me.TD(me, 1, 2, e = makeXonoticTextSlider("cl_playerdetailreduction"));
+ e.addValue(e, ZCTX(_("PDET^Low")), "4");
+ e.addValue(e, ZCTX(_("PDET^Medium")), "3");
+ e.addValue(e, ZCTX(_("PDET^Normal")), "2");
+ e.addValue(e, ZCTX(_("PDET^Good")), "1");
+ e.addValue(e, ZCTX(_("PDET^Best")), "0");
+ e.configureXonoticTextSliderValues(e);
me.TR(me);
me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Texture resolution:")));
setDependent(e, "r_showsurfaces", 0, 0);
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.25, 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.TDempty(me, 0.2);
me.TD(me, 1, 2.8, e = makeXonoticCheckBox(0, "r_coronas_occlusionquery", _("Fade corona according to visibility")));
setDependent(e, "r_coronas", 1, 1);
- me.TR(me);
me.TR(me);
me.TD(me, 1, 1, e = makeXonoticCheckBox(0, "r_bloom", _("Bloom")));
me.TD(me, 1, 2, e = makeXonoticCheckBoxEx(0.5, 0, "hud_postprocessing_maxbluralpha", _("Extra postprocessing effects")));
e.savedValue = 0.4; // default
me.TD(me, 1, 2, s);
me.TR(me);
+ 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.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.TDempty(me, 0.2);
+ 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.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.TR(me);
me.TDempty(me, 0.2);
me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Time:")));
setDependent(e, "cl_decals", 1, 1);
--- /dev/null
+#ifdef INTERFACE
+CLASS(XonoticGameSettingsTab) EXTENDS(XonoticTab)
+ METHOD(XonoticGameSettingsTab, fill, void(entity))
+ ATTRIB(XonoticGameSettingsTab, title, string, _("Game"))
+ ATTRIB(XonoticGameSettingsTab, intendedWidth, float, 0.9)
+ ATTRIB(XonoticGameSettingsTab, rows, float, 14.5)
+ ATTRIB(XonoticGameSettingsTab, columns, float, 6.5)
+ENDCLASS(XonoticGameSettingsTab)
+entity makeXonoticGameSettingsTab();
+#endif
+
+#ifdef IMPLEMENTATION
+entity makeXonoticGameSettingsTab()
+{
+ entity me;
+ me = spawnXonoticGameSettingsTab();
+ me.configureDialog(me);
+ return me;
+}
+
+void XonoticGameSettingsTab_fill(entity me)
+{
+ entity mc;
+ mc = makeXonoticTabController(me.rows - 1.5);
+
+ me.TR(me);
+ me.TDempty(me, 0.25);
+ me.TD(me, 1, 1, mc.makeTabButton(mc, _("View"), makeXonoticGameViewSettingsTab()));
+ me.TD(me, 1, 1, mc.makeTabButton(mc, _("Crosshair"), makeXonoticGameCrosshairSettingsTab()));
+ me.TD(me, 1, 1, mc.makeTabButton(mc, _("HUD"), makeXonoticGameHUDSettingsTab()));
+ me.TD(me, 1, 1, mc.makeTabButton(mc, _("Messages"), makeXonoticGameMessageSettingsTab()));
+ me.TD(me, 1, 1, mc.makeTabButton(mc, _("Weapons"), makeXonoticGameWeaponsSettingsTab()));
+ me.TD(me, 1, 1, mc.makeTabButton(mc, _("Models"), makeXonoticGameModelSettingsTab()));
+
+ me.gotoRC(me, 1.5, 0);
+ me.TD(me, me.rows - 1.5, me.columns, mc);
+
+ /*
+
+ makeXonoticGameViewSettingsTab()));
+ makeXonoticGameGeneralSettingsTab()));
+ makeXonoticGameCrosshairSettingsTab()));
+
+ makeXonoticGameWeaponSettingsTab()));
+ l"), makeXonoticGamePlayermodelSettingsTab()));
+ makeXonoticGameHUDSettingsTab()));
+ on"), makeXonoticGameNotificationSettingsTab()));
+
+
+ me.TR(me);
+ me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "cl_gentle", _("Disable gore effects and harsh language"))); // also set sv_gentle
+ */
+}
+#endif
--- /dev/null
+#ifdef INTERFACE
+CLASS(XonoticGameCrosshairSettingsTab) EXTENDS(XonoticTab)
+ //METHOD(XonoticGameCrosshairSettingsTab, toString, string(entity))
+ METHOD(XonoticGameCrosshairSettingsTab, fill, void(entity))
+ METHOD(XonoticGameCrosshairSettingsTab, showNotify, void(entity))
+ ATTRIB(XonoticGameCrosshairSettingsTab, title, string, _("Crosshair"))
+ ATTRIB(XonoticGameCrosshairSettingsTab, intendedWidth, float, 0.9)
+ ATTRIB(XonoticGameCrosshairSettingsTab, rows, float, 13)
+ ATTRIB(XonoticGameCrosshairSettingsTab, columns, float, 6.2)
+ENDCLASS(XonoticGameCrosshairSettingsTab)
+entity makeXonoticGameCrosshairSettingsTab();
+#endif
+
+#ifdef IMPLEMENTATION
+void XonoticGameCrosshairSettingsTab_showNotify(entity me)
+{
+ loadAllCvars(me);
+}
+entity makeXonoticGameCrosshairSettingsTab()
+{
+ entity me;
+ me = spawnXonoticGameCrosshairSettingsTab();
+ me.configureDialog(me);
+ return me;
+}
+
+void XonoticGameCrosshairSettingsTab_fill(entity me)
+{
+ entity e;
+ float i;
+
+ // 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.TR(me); //me.gotoRC(me, 0, 3.2); me.setFirstColumn(me, me.currentColumn);
+ me.TD(me, 1, 1, e = makeXonoticRadioButton(3, "crosshair_enabled", "0", _("No crosshair")));
+ //me.TR(me);
+ me.TD(me, 1, 1, e = makeXonoticRadioButton(3, "crosshair_per_weapon", string_null, _("Per weapon")));
+ makeMulti(e, "crosshair_enabled");
+ //me.TR(me);
+ me.TD(me, 1, 1, e = makeXonoticRadioButton(3, "crosshair_enabled", "2", _("Custom")));
+ 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.TDempty(me, 0.1);
+ me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Crosshair size:")));
+ setDependent(e, "crosshair_enabled", 1, 2);
+ me.TD(me, 1, 1.9, e = makeXonoticSlider(0.1, 1.0, 0.01, "crosshair_size"));
+ setDependent(e, "crosshair_enabled", 1, 2);
+ me.TR(me);
+ me.TDempty(me, 0.1);
+ me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Crosshair alpha:")));
+ setDependent(e, "crosshair_enabled", 1, 2);
+ me.TD(me, 1, 1.9, e = makeXonoticSlider(0, 1, 0.1, "crosshair_alpha"));
+ setDependent(e, "crosshair_enabled", 1, 2);
+ me.TR(me);
+ me.TDempty(me, 0.1);
+ me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Crosshair color:")));
+ setDependent(e, "crosshair_enabled", 1, 2);
+ me.TD(me, 1, 0.9, 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.2);
+ me.TD(me, 1, 0.8, 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.1);
+ me.TD(me, 1, 2.9, e = makeXonoticCheckBox(0, "crosshair_ring", _("Use rings to indicate weapon status")));
+ makeMulti(e, "crosshair_ring_reload");
+ setDependent(e, "crosshair_enabled", 1, 2);
+ //me.TR(me);
+ // me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Ring size:")));
+ // setDependentAND(e, "crosshair_ring", 1, 1, "crosshair_enabled", 1, 2);
+ // me.TD(me, 1, 2, e = makeXonoticSlider(2, 4, 0.1, "crosshair_ring_size"));
+ // setDependentAND(e, "crosshair_ring", 1, 1, "crosshair_enabled", 1, 2);
+ me.TR(me);
+ me.TDempty(me, 0.3);
+ me.TD(me, 1, 0.9, e = makeXonoticTextLabel(0, _("Ring alpha:")));
+ setDependentAND(e, "crosshair_ring", 1, 1, "crosshair_enabled", 1, 2);
+ me.TD(me, 1, 1.8, e = makeXonoticSlider(0.1, 1, 0.1, "crosshair_ring_alpha"));
+ setDependentAND(e, "crosshair_ring", 1, 1, "crosshair_enabled", 1, 2);
+
+ me.gotoRC(me, 0, 3.2); me.setFirstColumn(me, me.currentColumn);
+ me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "crosshair_dot", _("Enable center crosshair dot")));
+ setDependent(e, "crosshair_enabled", 1, 2);
+ me.TR(me);
+ me.TDempty(me, 0.1);
+ me.TD(me, 1, 0.9, e = makeXonoticTextLabel(0, _("Dot size:")));
+ setDependentAND(e, "crosshair_dot", 1, 1, "crosshair_enabled", 1, 2);
+ me.TD(me, 1, 2, e = makeXonoticSlider(0.2, 2, 0.1, "crosshair_dot_size"));
+ setDependentAND(e, "crosshair_dot", 1, 1, "crosshair_enabled", 1, 2);
+ me.TR(me);
+ me.TDempty(me, 0.1);
+ me.TD(me, 1, 0.9, e = makeXonoticTextLabel(0, _("Dot alpha:")));
+ setDependentAND(e, "crosshair_dot", 1, 1, "crosshair_enabled", 1, 2);
+ me.TD(me, 1, 2, e = makeXonoticSlider(0.1, 1, 0.1, "crosshair_dot_alpha"));
+ setDependentAND(e, "crosshair_dot", 1, 1, "crosshair_enabled", 1, 2);
+ me.TR(me);
+ me.TDempty(me, 0.1);
+ me.TD(me, 1, 0.9, e = makeXonoticTextLabel(0, _("Dot color:")));
+ setDependentAND(e, "crosshair_dot", 1, 1, "crosshair_enabled", 1, 2);
+ me.TD(me, 1, 2, e = makeXonoticRadioButton(1, "crosshair_dot_color_custom", "0", _("Use normal crosshair color")));
+ setDependentAND(e, "crosshair_dot", 1, 1, "crosshair_enabled", 1, 2);
+ me.TR(me);
+ me.TDempty(me, 0.2);
+ me.TD(me, 1, 0.8, e = makeXonoticRadioButton(1, "crosshair_dot_color_custom", "1", _("Custom")));
+ setDependentAND(e, "crosshair_dot", 1, 1, "crosshair_enabled", 1, 2);
+ me.TD(me, 2, 2, e = makeXonoticColorpickerString("crosshair_dot_color", "crosshair_dot_color"));
+ setDependentAND3(e, "crosshair_dot", 1, 1, "crosshair_enabled", 1, 2, "crosshair_dot_color_custom", 1, 1);
+ me.TR(me);
+ me.TR(me);
+ me.TR(me);
+ me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "crosshair_effect_scalefade", _("Smooth effects of crosshairs")));
+ setDependent(e, "crosshair_enabled", 1, 2);
+ me.TR(me);
+ me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "crosshair_hittest_blur", _("Blur crosshair if the shot is obstructed")));
+ setDependentAND(e, "crosshair_hittest", 1, 100, "crosshair_enabled", 1, 2);
+ me.TR(me);
+ me.TD(me, 1, 3, e = makeXonoticCheckBoxEx(1.25, 0, "crosshair_hittest_scale", _("Enlarge crosshair if targeting an enemy")));
+ setDependentAND(e, "crosshair_hittest", 1, 100, "crosshair_enabled", 1, 2);
+ me.TR(me);
+ me.TD(me, 1, 3, e = makeXonoticCheckBoxEx(0.5, 0, "crosshair_hitindication", _("Animate crosshair when hitting an enemy")));
+ setDependent(e, "crosshair_enabled", 1, 2);
+ me.TR(me);
+ me.TD(me, 1, 3, e = makeXonoticCheckBoxEx(0.25, 0, "crosshair_pickup", _("Animate crosshair when picking up an item")));
+ setDependent(e, "crosshair_enabled", 1, 2);
+ /*me.TR(me);
+ me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Hit testing:")));
+ me.TD(me, 1, 2, e = makeXonoticTextSlider("crosshair_hittest"));
+ e.addValue(e, ZCTX(_("HTTST^Disabled")), "0");
+ e.addValue(e, ZCTX(_("HTTST^TrueAim")), "1");
+ e.addValue(e, ZCTX(_("HTTST^Enemies")), "1.25");
+ e.configureXonoticTextSliderValues(e);
+ setDependent(e, "crosshair_enabled", 1, 2);*/
+
+ /*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(XonoticGameHUDSettingsTab) EXTENDS(XonoticTab)
+ //METHOD(XonoticGameHUDSettingsTab, toString, string(entity))
+ METHOD(XonoticGameHUDSettingsTab, fill, void(entity))
+ METHOD(XonoticGameHUDSettingsTab, showNotify, void(entity))
+ ATTRIB(XonoticGameHUDSettingsTab, title, string, _("HUD"))
+ ATTRIB(XonoticGameHUDSettingsTab, intendedWidth, float, 0.9)
+ ATTRIB(XonoticGameHUDSettingsTab, rows, float, 13)
+ ATTRIB(XonoticGameHUDSettingsTab, columns, float, 6.2)
+ENDCLASS(XonoticGameHUDSettingsTab)
+entity makeXonoticGameHUDSettingsTab();
+void HUDSetup_Start(entity me, entity btn);
+#endif
+
+#ifdef IMPLEMENTATION
+void HUDSetup_Check_Gamestatus(entity me, entity btn)
+{
+ 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 XonoticGameHUDSettingsTab_showNotify(entity me)
+{
+ loadAllCvars(me);
+}
+entity makeXonoticGameHUDSettingsTab()
+{
+ entity me;
+ me = spawnXonoticGameHUDSettingsTab();
+ me.configureDialog(me);
+ return me;
+}
+
+void XonoticGameHUDSettingsTab_fill(entity me)
+{
+ entity e;
+
+ // todo:
+ // threshold: hud_damage_pain_threshold_lower_health
+ // scoreboard_alpha*
+
+ //me.gotoRC(me, 0, 3.2); me.setFirstColumn(me, me.currentColumn);
+ me.TR(me);
+ me.TD(me, 1, 3, e = makeXonoticTextLabel(0.5, _("Scoreboard")));
+ e.isBold = TRUE;
+ e.alpha = 0.5;
+ //me.TR(me);
+ // me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Alpha:")));
+ // me.TD(me, 1, 2, e = makeXonoticSlider(0, 1, 0.05, "scoreboard_alpha_bg"));
+ me.TR(me);
+ me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Fading speed:")));
+ me.TD(me, 1, 2, e = makeXonoticScoreboardFadeTimeSlider());
+ me.TR(me);
+ me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Side padding:")));
+ me.TD(me, 1, 2, e = makeXonoticSlider(0.05, 0.3, 0.01, "scoreboard_offset_left"));
+ makeMulti(e, "scoreboard_offset_right");
+
+ me.TR(me);
+ //me.TR(me);
+ me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "scoreboard_respawntime_decimals", _("Show decimals in respawn countdown")));
+ me.TR(me);
+ me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "scoreboard_accuracy", _("Show accuracy underneath scoreboard")));
+
+ me.TR(me);
+ me.TR(me);
+ me.TD(me, 1, 3, e = makeXonoticTextLabel(0.5, _("Waypoints")));
+ e.isBold = TRUE;
+ e.alpha = 0.5;
+ me.TR(me);
+ me.TD(me, 1, 3, e = makeXonoticCheckBox(1, "cl_hidewaypoints", _("Display waypoint markers for objectives on the map")));
+ 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, _("Fontsize:")));
+ setDependent(e, "cl_hidewaypoints", 0, 0);
+ me.TD(me, 1, 2, e = makeXonoticSlider(5, 16, 1, "g_waypointsprite_fontsize"));
+ 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);
+ //me.TR(me);
+ me.TDempty(me, 0.2);
+ me.TD(me, 1, 2.8, e = makeXonoticCheckBoxEx(0.25, 1, "g_waypointsprite_crosshairfadealpha", _("Fade when near the crosshair")));
+ setDependent(e, "cl_hidewaypoints", 0, 0);
+
+ #if 0
+ me.TR(me);
+ me.TD(me, 1, 3, e = makeXonoticTextLabel(0.5, _("Damage")));
+ e.isBold = TRUE;
+ e.alpha = 0.5;
+ me.TR(me);
+ me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Overlay:")));
+ me.TD(me, 1, 2, e = makeXonoticSlider(0, 1, 0.05, "hud_damage"));
+ me.TR(me);
+ me.TD(me, 1, 1, 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.TD(me, 1, 1, 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);
+ #endif
+
+ me.gotoRC(me, 0, 3.2); me.setFirstColumn(me, me.currentColumn);
+ me.TD(me, 1, 3, e = makeXonoticTextLabel(0.5, _("Player Names")));
+ e.isBold = TRUE;
+ e.alpha = 0.5;
+ 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, 0.8, e = makeXonoticTextLabel(0, _("Alpha:")));
+ setDependent(e, "hud_shownames", 1, 1);
+ me.TD(me, 1, 2, e = makeXonoticSlider(0.1, 1, 0.05, "hud_shownames_alpha"));
+ setDependent(e, "hud_shownames", 1, 1);
+ me.TR(me);
+ me.TDempty(me, 0.2);
+ me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Fontsize:")));
+ setDependent(e, "hud_shownames", 1, 1);
+ me.TD(me, 1, 2, e = makeXonoticSlider(5, 16, 1, "hud_shownames_fontsize"));
+ setDependent(e, "hud_shownames", 1, 1);
+ me.TR(me);
+ me.TDempty(me, 0.2);
+ me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Max distance:")));
+ setDependent(e, "hud_shownames", 1, 1);
+ me.TD(me, 1, 2, e = makeXonoticSlider(2000, 10000, 500, "hud_shownames_maxdistance"));
+ setDependent(e, "hud_shownames", 1, 1);
+ me.TR(me);
+ me.TDempty(me, 0.2);
+ me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Decolorize:")));
+ setDependent(e, "hud_shownames", 1, 1);
+ me.TD(me, 1, 2, e = makeXonoticTextSlider("hud_shownames_decolorize"));
+ e.addValue(e, ZCTX(_("Never")), "0");
+ e.addValue(e, ZCTX(_("Teamplay")), "1");
+ e.addValue(e, ZCTX(_("Always")), "2");
+ e.configureXonoticTextSliderValues(e);
+ setDependent(e, "hud_shownames", 1, 1);
+
+ me.TR(me);
+ //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")));
+ setDependent(e, "hud_shownames", 1, 1);
+ me.TR(me);
+ me.TDempty(me, 0.2);
+ me.TD(me, 1, 2.8, e = makeXonoticCheckBox(0, "hud_shownames_status", _("Display health and armor")));
+ setDependent(e, "hud_shownames", 1, 1);
+
+ me.TR(me);
+ me.TR(me);
+ me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Damage overlay:")));
+ me.TD(me, 1, 2, e = makeXonoticSlider(0, 1, 0.05, "hud_damage"));
+ 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;
+ // TODO: show hud config name with text here
+}
+#endif
--- /dev/null
+#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(XonoticGameMessageSettingsTab) EXTENDS(XonoticTab)
+ //METHOD(XonoticGameWeaponsSettingsTab, toString, string(entity))
+ METHOD(XonoticGameMessageSettingsTab, fill, void(entity))
+ METHOD(XonoticGameMessageSettingsTab, showNotify, void(entity))
+ ATTRIB(XonoticGameMessageSettingsTab, title, string, _("Messages"))
+ ATTRIB(XonoticGameMessageSettingsTab, intendedWidth, float, 0.9)
+ ATTRIB(XonoticGameMessageSettingsTab, rows, float, 13)
+ ATTRIB(XonoticGameMessageSettingsTab, columns, float, 6)
+ ATTRIB(XonoticGameMessageSettingsTab, weaponsList, entity, NULL)
+ENDCLASS(XonoticGameMessageSettingsTab)
+entity makeXonoticGameMessageSettingsTab();
+#endif
+
+#ifdef IMPLEMENTATION
+void XonoticGameMessageSettingsTab_showNotify(entity me)
+{
+ loadAllCvars(me);
+}
+entity makeXonoticGameMessageSettingsTab()
+{
+ entity me;
+ me = spawnXonoticGameMessageSettingsTab();
+ me.configureDialog(me);
+ return me;
+}
+
+void XonoticGameMessageSettingsTab_fill(entity me)
+{
+ entity e;
+
+ me.TR(me);
+ me.TD(me, 1, 3, e = makeXonoticTextLabel(0.5, _("Frag Information")));
+ e.isBold = TRUE;
+ e.alpha = 0.5;
+ me.TR(me);
+ me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "notification_show_sprees", _("Display information about killing sprees")));
+ me.TR(me);
+ me.TDempty(me, 0.2);
+ me.TD(me, 1, 2.8, e = makeXonoticCheckBox(0, "notification_show_sprees_info_specialonly", _("Only display sprees if they are achievements")));
+ makeMulti(e, "notification_show_sprees_center_specialonly");
+ setDependent(e, "notification_show_sprees", 1, 1);
+ me.TR(me);
+ me.TDempty(me, 0.2);
+ me.TD(me, 1, 2.8, e = makeXonoticCheckBox(0, "notification_show_sprees_center", _("Show spree information in centerprints")));
+ setDependent(e, "notification_show_sprees", 1, 1);
+ me.TR(me);
+ me.TDempty(me, 0.2);
+ me.TD(me, 1, 2.8, e = makeXonoticCheckBoxEx(3, 0, "notification_show_sprees_info", _("Show spree information in death messages")));
+ setDependent(e, "notification_show_sprees", 1, 1);
+ #if 0
+ me.TR(me);
+ me.TDempty(me, 0.1);
+ me.TD(me, 1, 0.9, e = makeXonoticTextLabel(0, _("Sprees in info messages:")));
+ setDependent(e, "notification_show_sprees", 1, 1);
+ me.TD(me, 1, 2, e = makeXonoticTextSlider("notification_show_sprees_info"));
+ e.addValue(e, ZCTX(_("Disabled")), "0");
+ e.addValue(e, ZCTX(_("Target")), "1");
+ e.addValue(e, ZCTX(_("Attacker")), "2");
+ e.addValue(e, ZCTX(_("Both")), "3");
+ e.configureXonoticTextSliderValues(e);
+ setDependent(e, "notification_show_sprees", 1, 1);
+ #endif
+ me.TR(me);
+ me.TDempty(me, 0.4);
+ me.TD(me, 1, 2.6, e = makeXonoticCheckBox(0, "notification_show_sprees_info_newline", _("Print on a seperate line")));
+ setDependent(e, "notification_show_sprees", 1, 1);
+ me.TR(me);
+ me.TD(me, 1, 3, e = makeXonoticCheckBoxEx(2, 1, "notification_CHOICE_FRAG", _("Add extra frag information to centerprint when available")));
+ makeMulti(e, "notification_CHOICE_FRAGGED notification_CHOICE_TYPEFRAG notification_CHOICE_TYPEFRAGGED");
+ e.sendCvars = TRUE;
+ me.TR(me);
+ me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "notification_show_location", _("Add frag location to death messages when available")));
+
+ me.gotoRC(me, 9, 0); me.setFirstColumn(me, me.currentColumn);
+ me.TD(me, 1, 3, e = makeXonoticTextLabel(0.5, _("Gamemode Settings")));
+ e.isBold = TRUE;
+ e.alpha = 0.5;
+ me.TR(me);
+ me.TD(me, 1, 3, e = makeXonoticCheckBoxEx(2, 1, "notification_CHOICE_CTF_CAPTURE_TIME_RED", _("Display capture times in Capture The Flag")));
+ makeMulti(e, "notification_CHOICE_CTF_CAPTURE_TIME_BLUE notification_CHOICE_CTF_CAPTURE_BROKEN_RED notification_CHOICE_CTF_CAPTURE_BROKEN_BLUE notification_CHOICE_CTF_CAPTURE_UNBROKEN_RED notification_CHOICE_CTF_CAPTURE_UNBROKEN_BLUE ");
+ e.sendCvars = TRUE;
+ me.TR(me);
+ me.TD(me, 1, 3, e = makeXonoticCheckBoxEx(2, 1, "notification_CHOICE_CTF_PICKUP_ENEMY", _("Display name of flag stealer in Capture The Flag")));
+ makeMulti(e, "notification_CHOICE_CTF_PICKUP_TEAM");
+ e.sendCvars = TRUE;
+
+ me.gotoRC(me, 0, 3.2); me.setFirstColumn(me, me.currentColumn);
+ me.TD(me, 1, 3, e = makeXonoticTextLabel(0.5, _("Other")));
+ e.isBold = TRUE;
+ e.alpha = 0.5;
+ me.TR(me);
+ me.TD(me, 1, 3, e = makeXonoticCheckBoxEx(4, 1, "con_notify", _("Display console messages in the top left corner")));
+ me.TR(me);
+ me.TD(me, 1, 3, e = makeXonoticCheckBoxEx(2, 1, "notification_allow_chatboxprint", _("Display all info messages in the chatbox")));
+ me.TR(me);
+ me.TD(me, 1, 3, e = makeXonoticCheckBoxEx(2, 1, "notification_INFO_QUIT_DISCONNECT", _("Display player statuses in the chatbox")));
+ makeMulti(e, "notification_INFO_QUIT_KICK_IDLING notification_INFO_JOIN_CONNECT_TEAM_BLUE notification_INFO_JOIN_CONNECT_TEAM_PINK notification_INFO_JOIN_CONNECT_TEAM_RED notification_INFO_JOIN_CONNECT_TEAM_YELLOW");
+ me.TR(me);
+ me.TR(me);
+ me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "notification_CENTER_POWERUP_INVISIBILITY", _("Powerup notifications")));
+ makeMulti(e, "notification_CENTER_POWERUP_SHIELD notification_CENTER_POWERUP_SPEED notification_CENTER_POWERUP_STRENGTH notification_CENTER_POWERDOWN_INVISIBILITY notification_CENTER_POWERDOWN_SHIELD notification_CENTER_POWERDOWN_SPEED notification_CENTER_POWERDOWN_STRENGTH notification_CENTER_SUPERWEAPON_BROKEN notification_CENTER_SUPERWEAPON_LOST notification_CENTER_SUPERWEAPON_PICKUP notification_INFO_POWERUP_INVISIBILITY notification_INFO_POWERUP_SHIELD notification_INFO_POWERUP_SPEED notification_INFO_POWERUP_STRENGTH");
+ me.TR(me);
+ me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "notification_CENTER_ITEM_WEAPON_DONTHAVE", _("Weapon centerprint notifications")));
+ makeMulti(e, "notification_CENTER_ITEM_WEAPON_DROP notification_CENTER_ITEM_WEAPON_GOT notification_CENTER_ITEM_WEAPON_NOAMMO notification_CENTER_ITEM_WEAPON_PRIMORSEC notification_CENTER_ITEM_WEAPON_UNAVAILABLE");
+ me.TR(me);
+ me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "notification_INFO_ITEM_WEAPON_DONTHAVE", _("Weapon info message notifications")));
+ makeMulti(e, "notification_INFO_ITEM_WEAPON_DROP notification_INFO_ITEM_WEAPON_GOT notification_INFO_ITEM_WEAPON_NOAMMO notification_INFO_ITEM_WEAPON_PRIMORSEC notification_INFO_ITEM_WEAPON_UNAVAILABLE");
+
+ me.gotoRC(me, 9, 3.2); me.setFirstColumn(me, me.currentColumn);
+ me.TD(me, 1, 3, e = makeXonoticTextLabel(0.5, _("Announcers")));
+ e.isBold = TRUE;
+ e.alpha = 0.5;
+ #if 0
+ // there's just not enough room for this, and it's not important enough to justify...
+ me.TR(me);
+ me.TD(me, 1, 3, e = makeXonoticCheckBoxEx(2, 0, "notification_ANNCE_NUM_RESPAWN_1", _("Respawn countdown sounds")));
+ makeMulti(e, "notification_ANNCE_NUM_RESPAWN_2 notification_ANNCE_NUM_RESPAWN_3 notification_ANNCE_NUM_RESPAWN_4 notification_ANNCE_NUM_RESPAWN_5 notification_ANNCE_NUM_RESPAWN_6 notification_ANNCE_NUM_RESPAWN_7 notification_ANNCE_NUM_RESPAWN_8 notification_ANNCE_NUM_RESPAWN_9 notification_ANNCE_NUM_RESPAWN_10");
+ #endif
+ me.TR(me);
+ me.TD(me, 1, 3, e = makeXonoticCheckBoxEx(1, 0, "notification_ANNCE_KILLSTREAK_03", _("Killstreak sounds")));
+ makeMulti(e, "notification_ANNCE_KILLSTREAK_05 notification_ANNCE_KILLSTREAK_10 notification_ANNCE_KILLSTREAK_15 notification_ANNCE_KILLSTREAK_20 notification_ANNCE_KILLSTREAK_25 notification_ANNCE_KILLSTREAK_30");
+ me.TR(me);
+ me.TD(me, 1, 3, e = makeXonoticCheckBoxEx(1, 0, "notification_ANNCE_ACHIEVEMENT_AIRSHOT", _("Achievement sounds")));
+ makeMulti(e, "notification_ANNCE_ACHIEVEMENT_AMAZING notification_ANNCE_ACHIEVEMENT_AWESOME notification_ANNCE_ACHIEVEMENT_BOTLIKE notification_ANNCE_ACHIEVEMENT_ELECTROBITCH notification_ANNCE_ACHIEVEMENT_IMPRESSIVE notification_ANNCE_ACHIEVEMENT_YODA");
+}
+#endif
--- /dev/null
+#ifdef INTERFACE
+CLASS(XonoticGameModelSettingsTab) EXTENDS(XonoticTab)
+ //METHOD(XonoticGameModelSettingsTab, toString, string(entity))
+ METHOD(XonoticGameModelSettingsTab, fill, void(entity))
+ METHOD(XonoticGameModelSettingsTab, showNotify, void(entity))
+ ATTRIB(XonoticGameModelSettingsTab, title, string, _("Model"))
+ ATTRIB(XonoticGameModelSettingsTab, intendedWidth, float, 0.9)
+ ATTRIB(XonoticGameModelSettingsTab, rows, float, 13)
+ ATTRIB(XonoticGameModelSettingsTab, columns, float, 5)
+ENDCLASS(XonoticGameModelSettingsTab)
+entity makeXonoticGameModelSettingsTab();
+#endif
+
+#ifdef IMPLEMENTATION
+void XonoticGameModelSettingsTab_showNotify(entity me)
+{
+ loadAllCvars(me);
+}
+entity makeXonoticGameModelSettingsTab()
+{
+ entity me;
+ me = spawnXonoticGameModelSettingsTab();
+ me.configureDialog(me);
+ return me;
+}
+
+void XonoticGameModelSettingsTab_fill(entity me)
+{
+ entity e;
+ //float i;
+
+ // Note that this is pretty terrible currently due to the lack of options for this tab...
+ // There is really not many other decent places for these options, additionally
+ // later I would like quite a few more options in this tab.
+
+ me.gotoRC(me, 0, 1); me.setFirstColumn(me, me.currentColumn);
+ me.TD(me, 1, 3, e = makeXonoticTextLabel(0.5, _("Items")));
+ e.isBold = TRUE;
+ e.alpha = 0.5;
+ me.TR(me);
+ me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "cl_simple_items", _("Use simple 2D images instead of item models")));
+ me.TR(me);
+ me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Unvailable alpha:")));
+ me.TD(me, 1, 2, e = makeXonoticSlider(0, 1, 0.1, "cl_ghost_items"));
+ me.TR(me);
+ me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Unavailable color:")));
+ me.TD(me, 1, 2, e = makeXonoticTextSlider("cl_ghost_items_color"));
+ e.addValue(e, ZCTX(_("GHOITEMS^Black")), "-1 -1 -1");
+ e.addValue(e, ZCTX(_("GHOITEMS^Dark")), "0.1 0.1 0.1");
+ e.addValue(e, ZCTX(_("GHOITEMS^Tinted")), "0.6 0.6 0.6");
+ e.addValue(e, ZCTX(_("GHOITEMS^Normal")), "1 1 1");
+ e.addValue(e, ZCTX(_("GHOITEMS^Blue")), "-1 -1 3");
+ e.configureXonoticTextSliderValues(e);
+ setDependent(e, "cl_ghost_items", 0.001, 1);
+
+ me.TR(me);
+ me.TR(me);
+ me.TD(me, 1, 3, e = makeXonoticTextLabel(0.5, _("Players")));
+ e.isBold = TRUE;
+ e.alpha = 0.5;
+ 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.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);
+}
+#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, 13)
+ 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 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 = makeXonoticCheckBox(0, "cl_eventchase_death", _("Slide to third person upon death")));
+ 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_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(1, "cl_clippedspectating", _("Allow passing through walls while spectating")));
+
+ 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_enabled", _("Velocity zoom")));
+ me.TD(me, 1, 2, e = makeXonoticCheckBoxEx(3, 1, "cl_velocityzoom_type", _("Forward movement only")));
+ setDependent(e, "cl_velocityzoom_enabled", 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_enabled", 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_enabled", 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(XonoticGameWeaponsSettingsTab) EXTENDS(XonoticTab)
+ //METHOD(XonoticGameWeaponsSettingsTab, toString, string(entity))
+ METHOD(XonoticGameWeaponsSettingsTab, fill, void(entity))
+ METHOD(XonoticGameWeaponsSettingsTab, showNotify, void(entity))
+ ATTRIB(XonoticGameWeaponsSettingsTab, title, string, _("Weapons"))
+ ATTRIB(XonoticGameWeaponsSettingsTab, intendedWidth, float, 0.9)
+ ATTRIB(XonoticGameWeaponsSettingsTab, rows, float, 13)
+ ATTRIB(XonoticGameWeaponsSettingsTab, columns, float, 6)
+ ATTRIB(XonoticGameWeaponsSettingsTab, weaponsList, entity, NULL)
+ENDCLASS(XonoticGameWeaponsSettingsTab)
+entity makeXonoticGameWeaponsSettingsTab();
+#endif
+
+#ifdef IMPLEMENTATION
+void XonoticGameWeaponsSettingsTab_showNotify(entity me)
+{
+ loadAllCvars(me);
+}
+entity makeXonoticGameWeaponsSettingsTab()
+{
+ entity me;
+ me = spawnXonoticGameWeaponsSettingsTab();
+ me.configureDialog(me);
+ return me;
+}
+
+void XonoticGameWeaponsSettingsTab_fill(entity me)
+{
+ entity e;
+
+ me.TR(me);
+ me.TDempty(me, 0.25);
+ me.TD(me, 1, 2.5, e = makeXonoticTextLabel(0.5, _("Weapon Priority List")));
+ e.isBold = TRUE;
+ e.alpha = 0.5;
+ me.TR(me);
+ me.TDempty(me, 0.25);
+ me.TD(me, 10, 2.5, e = me.weaponsList = makeXonoticWeaponsList());
+ me.gotoRC(me, 11, 0.25);
+ me.TD(me, 1, 1.25, e = makeXonoticButton(_("Up"), '0 0 0'));
+ e.onClick = WeaponsList_MoveUp_Click;
+ e.onClickEntity = me.weaponsList;
+ me.TD(me, 1, 1.25, e = makeXonoticButton(_("Down"), '0 0 0'));
+ e.onClick = WeaponsList_MoveDown_Click;
+ e.onClickEntity = me.weaponsList;
+
+ me.gotoRC(me, 0, 3); 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(1, "cl_weaponimpulsemode", _("Cycle through only usable weapon selections")));
+ me.TR(me);
+ me.TR(me);
+ me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "cl_autoswitch", _("Auto switch weapons on pickup")));
+ me.TR(me);
+ me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "cl_unpress_attack_on_weapon_switch", _("Release attack buttons when you switch weapons")));
+ 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);
+}
+#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, 14.5)
ATTRIB(XonoticInputSettingsTab, columns, float, 6.2) // added extra .2 for center space
ENDCLASS(XonoticInputSettingsTab)
entity makeXonoticInputSettingsTab();
me.configureDialog(me);
return me;
}
+
+void CheckBox_Click_Redisplay(entity me, entity checkbox)
+{
+ CheckBox_Click(me, checkbox);
+ cmd("\ndefer 0.2 \"togglemenu 1\"\n");
+ //m_display();
+}
void XonoticInputSettingsTab_fill(entity me)
{
entity e;
entity kb;
me.TR(me);
- me.TD(me, 1, 3, e = makeXonoticTextLabel(0, _("Key bindings:")));
+ me.TD(me, 1, 3, e = makeXonoticTextLabel(0.5, _("Key Bindings")));
+ e.isBold = TRUE;
+ e.alpha = 0.5;
me.TR(me);
- me.TD(me, me.rows - 4, 3, kb = makeXonoticKeyBinder());
- me.gotoRC(me, me.rows - 3, 0);
+ me.TD(me, me.rows - 2.5, 3, kb = makeXonoticKeyBinder());
+ me.gotoRC(me, me.rows - 1.5, 0);
me.TD(me, 1, 1, e = makeXonoticButton(_("Change key..."), '0 0 0'));
e.onClick = KeyBinder_Bind_Change;
e.onClickEntity = kb;
kb.clearButton = e;
me.gotoRC(me, 0, 3.2); me.setFirstColumn(me, me.currentColumn);
- me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "con_closeontoggleconsole", _("Pressing \"enter console\" key also closes it")));
+ me.TD(me, 1, 3, e = makeXonoticTextLabel(0.5, _("Mouse")));
+ e.isBold = TRUE;
+ e.alpha = 0.5;
me.TR(me);
- me.TD(me, 1, 3, e = makeXonoticCheckBox(1, "cl_movement_track_canjump", _("Automatically repeat jumping if holding jump")));
+ me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Sensitivity:")));
+ me.TD(me, 1, 2, e = makeXonoticSlider(1, 32, 0.2, "sensitivity"));
me.TR(me);
+ me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "m_filter", _("Smooth aiming")));
me.TR(me);
- if(cvar_type("joy_enable") & CVAR_TYPEFLAG_ENGINE)
- me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "joy_enable", _("Use joystick input")));
- else if(cvar_type("joystick") & CVAR_TYPEFLAG_ENGINE)
- me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "joystick", _("Use joystick input")));
+ me.TD(me, 1, 3, e = makeXonoticCheckBox(1.022, "m_pitch", _("Invert aiming")));
+ me.TR(me);
+ me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "menu_mouse_absolute", _("Use system mouse positioning")));
+ makeMulti(e, "hud_cursormode");
+ e.onClick = CheckBox_Click_Redisplay;
+ e.onClickEntity = e;
+ me.TR(me);
+ me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "m_accelerate", _("Enable built in mouse acceleration")));
+ me.TR(me);
+ if(cvar_type("vid_dgamouse") & CVAR_TYPEFLAG_ENGINE)
+ me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "vid_dgamouse", _("Disable system mouse acceleration")));
+ else if(cvar_type("apple_mouse_noaccel") & CVAR_TYPEFLAG_ENGINE)
+ me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "apple_mouse_noaccel", _("Disable system mouse acceleration")));
else
{
- me.TD(me, 1, 3, e = makeXonoticCheckBox(0, string_null, _("Use joystick input")));
+ me.TD(me, 1, 3, e = makeXonoticCheckBox(0, string_null, _("Disable system mouse acceleration")));
e.disabled = 1; // the option is never available in this case, just there for show
}
+
me.TR(me);
me.TR(me);
- me.TD(me, 1, 3, e = makeXonoticTextLabel(0, _("Mouse:")));
+ me.TD(me, 1, 3, e = makeXonoticTextLabel(0.5, _("Other")));
+ e.isBold = TRUE;
+ e.alpha = 0.5;
me.TR(me);
- me.TDempty(me, 0.2);
- me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Sensitivity:")));
- me.TD(me, 1, 2, e = makeXonoticSlider(1, 32, 0.2, "sensitivity"));
+ me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "con_closeontoggleconsole", _("Pressing \"enter console\" key also closes it")));
me.TR(me);
- me.TDempty(me, 0.2);
- me.TD(me, 1, 2.8, e = makeXonoticCheckBox(0, "m_filter", _("Smooth aiming")));
+ me.TD(me, 1, 3, e = makeXonoticCheckBox(1, "cl_movement_track_canjump", _("Automatically repeat jumping if holding jump")));
+ e.sendCvars = TRUE;
me.TR(me);
- me.TDempty(me, 0.2);
- me.TD(me, 1, 2.8, e = makeXonoticCheckBox(1.022, "m_pitch", _("Invert aiming")));
me.TR(me);
- me.TDempty(me, 0.2);
- if(cvar_type("vid_dgamouse") & CVAR_TYPEFLAG_ENGINE)
- me.TD(me, 1, 2.8, e = makeXonoticCheckBox(0, "vid_dgamouse", _("Disable system mouse acceleration")));
- else if(cvar_type("apple_mouse_noaccel") & CVAR_TYPEFLAG_ENGINE)
- me.TD(me, 1, 2.8, e = makeXonoticCheckBox(0, "apple_mouse_noaccel", _("Disable system mouse acceleration")));
+ if(cvar_type("joy_enable") & CVAR_TYPEFLAG_ENGINE)
+ {
+ me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "joy_enable", _("Use joystick input")));
+ setDependent(e, "joy_detected", 1, 10000000);
+ }
+ else if(cvar_type("joystick") & CVAR_TYPEFLAG_ENGINE)
+ {
+ me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "joystick", _("Use joystick input")));
+ setDependent(e, "joy_detected", 1, 10000000);
+ }
else
{
- me.TD(me, 1, 2.8, e = makeXonoticCheckBox(0, string_null, _("Disable system mouse acceleration")));
+ me.TD(me, 1, 3, e = makeXonoticCheckBox(0, string_null, _("Use joystick input")));
e.disabled = 1; // the option is never available in this case, just there for show
}
- 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.TD(me, 1, me.columns, makeXonoticCommandButton(_("Apply immediately"), '0 0 0', "sendcvar cl_movement_track_canjump", COMMANDBUTTON_APPLY));
}
#endif
METHOD(XonoticMiscSettingsTab, fill, void(entity))
ATTRIB(XonoticMiscSettingsTab, title, string, _("Misc"))
ATTRIB(XonoticMiscSettingsTab, intendedWidth, float, 0.9)
- ATTRIB(XonoticMiscSettingsTab, rows, float, 17)
+ ATTRIB(XonoticMiscSettingsTab, rows, float, 14.5)
ATTRIB(XonoticMiscSettingsTab, columns, float, 6.2)
ENDCLASS(XonoticMiscSettingsTab)
entity makeXonoticMiscSettingsTab();
//entity sk;
me.TR(me);
- me.TD(me, 1, 3, e = makeXonoticTextLabel(0, _("Network:")));
+ me.TD(me, 1, 3, e = makeXonoticTextLabel(0.5, _("Network")));
+ e.isBold = TRUE;
+ e.alpha = 0.5;
me.TR(me);
- me.TDempty(me, 0.2);
- me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Speed:")));
+ me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, _("Client UDP port:")));
+ me.TD(me, 1, 1.5, e = makeXonoticInputBox(0, "cl_port"));
+ me.TR(me);
+ me.TR(me);
+ me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Bandwidth:")));
me.TD(me, 1, 2, e = makeXonoticTextSlider("_cl_rate"));
e.addValue(e, _("56k"), "4000");
e.addValue(e, _("ISDN"), "7000");
e.addValue(e, _("Broadband"), "66666");
e.configureXonoticTextSliderValues(e);
me.TR(me);
- me.TDempty(me, 0.2);
- me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Input packets/s:")));
+ me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Input packets/s:")));
me.TD(me, 1, 2, e = makeXonoticSlider(20, 100, 5, "cl_netfps"));
me.TR(me);
- if(cvar("developer"))
- {
- me.TDempty(me, 0.2);
- me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Local latency:")));
- me.TD(me, 1, 2, e = makeXonoticSlider(0, 1000, 25, "cl_netlocalping"));
- }
+ me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Server queries/s:")));
+ me.TD(me, 1, 2, e = makeXonoticSlider(20, 100, 10, "net_slist_queriespersecond"));
me.TR(me);
- me.TDempty(me, 0.2);
- me.TD(me, 1, 1.8, e = makeXonoticTextLabel(0, _("Client UDP port:")));
- me.TD(me, 1, 1, e = makeXonoticInputBox(0, "cl_port"));
- e.enableClearButton = 0;
me.TR(me);
- me.TDempty(me, 0.2);
- if(cvar_type("crypto_aeslevel") & CVAR_TYPEFLAG_ENGINE)
- me.TD(me, 1, 2.8, e = makeXonoticCheckBoxEx(2, 1, "crypto_aeslevel", _("Use encryption (AES) when available")));
+ me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Downloads:")));
+ me.TD(me, 1, 2, e = makeXonoticSlider(1, 5, 1, "cl_curl_maxdownloads"));
me.TR(me);
+ me.TDempty(me, 0.1);
+ me.TD(me, 1, 0.9, e = makeXonoticTextLabel(0, _("Speed (kB/s):")));
+ me.TD(me, 1, 2, e = makeXonoticSlider(10, 2000, 50, "cl_curl_maxspeed"));
me.TR(me);
- me.TDempty(me, 0.2);
- me.TD(me, 1, 2.8, e = makeXonoticCheckBox(0, "shownetgraph", _("Show netgraph")));
+ if(cvar("developer"))
+ {
+ me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Local latency:")));
+ me.TD(me, 1, 2, e = makeXonoticSlider(0, 1000, 25, "cl_netlocalping"));
+ }
me.TR(me);
+ me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "shownetgraph", _("Show netgraph")));
me.TR(me);
- me.TDempty(me, 0.2);
- me.TD(me, 1, 2.8, e = makeXonoticCheckBox(0, "cl_movement", _("Client-side movement prediction")));
+ me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "cl_movement", _("Client-side movement prediction")));
me.TR(me);
- me.TDempty(me, 0.2);
- me.TD(me, 1, 2.8, e = makeXonoticCheckBox(0, "cl_movement_errorcompensation", _("Movement error compensation")));
+ me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "cl_movement_errorcompensation", _("Movement error compensation")));
setDependent(e, "cl_movement", 1, 1);
me.TR(me);
- me.TR(me);
- me.TD(me, 1, 3, e = makeXonoticTextLabel(0, _("Downloads:")));
- me.TR(me);
- me.TDempty(me, 0.2);
- me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Maximum:")));
- me.TD(me, 1, 2, e = makeXonoticSlider(1, 5, 1, "cl_curl_maxdownloads"));
- me.TR(me);
- me.TDempty(me, 0.2);
- me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Speed (kB/s):")));
- me.TD(me, 1, 2, e = makeXonoticSlider(10, 1500, 10, "cl_curl_maxspeed"));
- me.TR(me);
+ if(cvar_type("crypto_aeslevel") & CVAR_TYPEFLAG_ENGINE)
+ me.TD(me, 1, 3, e = makeXonoticCheckBoxEx(2, 1, "crypto_aeslevel", _("Use encryption (AES) when available"))); // TODO: move up
me.gotoRC(me, 0, 3.2); me.setFirstColumn(me, me.currentColumn);
- me.TD(me, 1, 3, e = makeXonoticTextLabel(0, _("Framerate:")));
+ me.TD(me, 1, 3, e = makeXonoticTextLabel(0.5, _("Framerate")));
+ e.isBold = TRUE;
+ e.alpha = 0.5;
me.TR(me);
- me.TDempty(me, 0.2);
- me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Maximum:")));
+ me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Maximum:")));
me.TD(me, 1, 2, e = makeXonoticTextSlider("cl_maxfps"));
e.addValue(e, ZCTX(_("MAXFPS^5 fps")), "5");
e.addValue(e, ZCTX(_("MAXFPS^10 fps")), "10");
e.addValue(e, ZCTX(_("MAXFPS^Unlimited")), "0");
e.configureXonoticTextSliderValues(e);
me.TR(me);
- me.TDempty(me, 0.2);
- me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Target:")));
+ me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Target:")));
me.TD(me, 1, 2, e = makeXonoticTextSlider("cl_minfps"));
e.addValue(e, ZCTX(_("TRGT^Disabled")), "0");
e.addValue(e, ZCTX(_("TRGT^30 fps")), "30");
e.addValue(e, ZCTX(_("TRGT^200 fps")), "200");
e.configureXonoticTextSliderValues(e);
me.TR(me);
- me.TDempty(me, 0.2);
- me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Idle limit:")));
+ me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Idle limit:")));
me.TD(me, 1, 2, e = makeXonoticTextSlider("cl_maxidlefps"));
e.addValue(e, ZCTX(_("IDLFPS^10 fps")), "10");
e.addValue(e, ZCTX(_("IDLFPS^20 fps")), "20");
e.configureXonoticTextSliderValues(e);
me.TR(me);
me.TR(me);
- me.TDempty(me, 0.2);
- me.TD(me, 1, 2.8, e = makeXonoticCheckBox(0, "showfps", _("Show frames per second")));
- me.TR(me);
- me.TDempty(me, 0.2);
- me.TD(me, 1, 2.8, e = makeXonoticCheckBox(0, "cl_maxfps_alwayssleep", _("Save processing time for other apps")));
+ me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "cl_maxfps_alwayssleep", _("Save processing time for other apps")));
setDependent(e, "cl_maxfps", 1, 1000);
me.TR(me);
+ me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "showfps", _("Show frames per second")));
+ me.TR(me);
+ me.TR(me);
+ me.TD(me, 1, 3, e = makeXonoticTextLabel(0.5, _("Other")));
+ e.isBold = TRUE;
+ e.alpha = 0.5;
me.TR(me);
me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Menu tooltips:")));
me.TD(me, 1, 2, e = makeXonoticTextSlider("menu_tooltips"));
e.addValue(e, ZCTX(_("TLTIP^Advanced")), "2");
e.configureXonoticTextSliderValues(e);
me.TR(me);
- me.TR(me);
- me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "showtime", _("Show current time")));
- me.TR(me);
- me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "showdate", _("Show current date")));
+ me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "showtime", _("Show current date and time")));
+ makeMulti(e, "showdate");
me.TR(me);
me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "developer", _("Enable developer mode")));
me.TR(me);
me.TD(me, 1, 2, e = makeXonoticButton(_("Advanced settings..."), '0 0 0'));
e.onClick = DialogOpenButton_Click;
e.onClickEntity = main.cvarsDialog;
- me.TR(me);
}
#endif
cvarlist.colorC =
SKINCOLOR_CVARLIST_CONTROLS;
+ // todo:
+ // add button which does cvar_resettodefaults_saveonly
+
me.TR(me);
me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Cvar filter:")));
me.TD(me, 1, me.columns - 1, e = makeXonoticInputBox(0, string_null));
METHOD(XonoticUserSettingsTab, fill, void(entity))
ATTRIB(XonoticUserSettingsTab, title, string, _("User"))
ATTRIB(XonoticUserSettingsTab, intendedWidth, float, 0.9)
- ATTRIB(XonoticUserSettingsTab, rows, float, 17)
- ATTRIB(XonoticUserSettingsTab, columns, float, 5)
+ ATTRIB(XonoticUserSettingsTab, rows, float, 14.5)
+ ATTRIB(XonoticUserSettingsTab, columns, float, 6)
ENDCLASS(XonoticUserSettingsTab)
entity makeXonoticUserSettingsTab();
#endif
entity sk;
me.TR(me);
- me.TD(me, 1, 2, e = makeXonoticTextLabel(0, _("Menu skins:")));
+ me.TDempty(me, 0.25);
+ me.TD(me, 1, 2.5, e = makeXonoticTextLabel(0.5, _("Menu Skins")));
+ e.isBold = TRUE;
+ e.alpha = 0.5;
me.TR(me);
- me.TD(me, me.rows - 2, 2, sk = makeXonoticSkinList());
- me.gotoRC(me, me.rows - 1, 0);
- me.TD(me, 1, 2, e = makeXonoticButton(_("Set skin"), '0 0 0'));
+ me.TDempty(me, 0.25);
+ me.TD(me, me.rows - 2.5, 2.5, sk = makeXonoticSkinList());
+ me.gotoRC(me, me.rows - 1.5, 0.25);
+ me.TD(me, 1, 2.5, e = makeXonoticButton(_("Set skin"), '0 0 0'));
e.onClick = SetSkin_Click;
e.onClickEntity = sk;
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, 6, 1.5, sk = makeXonoticLanguageList());
- me.TR(me);
- me.TR(me);
- me.TR(me);
- me.TR(me);
- me.TR(me);
+ me.gotoRC(me, 0, 3.75); me.setFirstColumn(me, me.currentColumn);
+ me.TD(me, 1, 1.5, e = makeXonoticTextLabel(0.5, _("Text Language")));
+ e.isBold = TRUE;
+ e.alpha = 0.5;
me.TR(me);
+ me.TD(me, 8, 1.5, sk = makeXonoticLanguageList());
+
+ me.gotoRC(me, 9, 3.75); me.setFirstColumn(me, me.currentColumn);
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_uidtracking", _("Allow player statistics to track your client")));
- 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, 11.5, 3.25); me.setFirstColumn(me, me.currentColumn);
+ me.TD(me, 1, 2.5, e = makeXonoticCheckBox(0, "cl_gentle", _("Disable gore effects and harsh language")));
+
+ //me.TR(me);
+ // me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Menu tooltips:")));
+ // me.TD(me, 1, 2, e = makeXonoticTextSlider("menu_tooltips"));
+ // e.addValue(e, ZCTX(_("TLTIP^Disabled")), "0");
+ // e.addValue(e, ZCTX(_("TLTIP^Standard")), "1");
+ // e.addValue(e, ZCTX(_("TLTIP^Advanced")), "2");
+ // e.configureXonoticTextSliderValues(e);
+ //me.TR(me);
+ // me.TD(me, 1, 2.8, e = makeXonoticCheckBox(0, "cl_allow_uidtracking", _("Allow player statistics to track your client"))); // TODO: move to profile tab
+ //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.TD(me, 1, 2, makeXonoticCommandButton(_("Apply immediately"), '0 0 0', "sendcvar cl_gentle; sendcvar cl_allow_uidtracking; sendcvar cl_allow_uid2name;", COMMANDBUTTON_APPLY));
+ //me.gotoRC(me, me.rows - 1, 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));
}
#endif
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, 14.5)
ATTRIB(XonoticVideoSettingsTab, columns, float, 6.2) // added extra .2 for center space
ATTRIB(XonoticVideoSettingsTab, name, string, "videosettings")
ENDCLASS(XonoticVideoSettingsTab)
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 = 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);
METHOD(XonoticGametypeList, keyDown, float(entity, float, float, float))
ATTRIB(XonoticGametypeList, realFontSize, vector, '0 0 0')
- ATTRIB(XonoticGametypeList, realUpperMargin1, float, 0)
- ATTRIB(XonoticGametypeList, realUpperMargin2, float, 0)
+ ATTRIB(XonoticGametypeList, realUpperMargin, float, 0)
ATTRIB(XonoticGametypeList, columnIconOrigin, float, 0)
ATTRIB(XonoticGametypeList, columnIconSize, float, 0)
ATTRIB(XonoticGametypeList, columnNameOrigin, float, 0)
draw_Picture(me.columnIconOrigin * eX, GameType_GetIcon(i), me.columnIconSize * eX + eY, '1 1 1', SKINALPHA_LISTBOX_SELECTED);
s = GameType_GetName(i);
+ draw_Text(me.realUpperMargin * eY + me.columnNameOrigin * eX, s, me.realFontSize, '1 1 1', SKINALPHA_TEXT, 0);
+
+ if(_MapInfo_GetTeamPlayBool(GameType_GetID(i)))
+ s = _("teamplay");
+ else
+ s = _("free for all");
+
draw_Text(me.realUpperMargin1 * eY + (me.columnNameOrigin + 0.5 * (me.columnNameSize - draw_TextWidth(s, 0, me.realFontSize))) * eX, s, me.realFontSize, SKINCOLOR_TEXT, SKINALPHA_TEXT, 0);
//s = GameType_GetTeams(i);
//draw_Text(me.realUpperMargin1 * eY + (me.columnNameOrigin + 1.00 * (me.columnNameSize - draw_TextWidth(s, 0, me.realFontSize))) * eX, s, me.realFontSize, SKINCOLOR_TEXT, SKINALPHA_TEXT, 0);
me.realFontSize_y = me.fontSize / (me.itemAbsSize_y = (absSize_y * me.itemHeight));
me.realFontSize_x = me.fontSize / (me.itemAbsSize_x = (absSize_x * (1 - me.controlWidth)));
- me.realUpperMargin1 = 0.5 * (1 - me.realFontSize_y);
- me.realUpperMargin2 = me.realUpperMargin1 + me.realFontSize_y;
+ me.realUpperMargin = 0.5 * (1 - me.realFontSize_y);
me.columnIconOrigin = 0;
me.columnIconSize = me.itemAbsSize_y / me.itemAbsSize_x;
- me.columnNameOrigin = me.columnIconOrigin + me.columnIconSize;
- me.columnNameSize = 1 - me.columnIconSize - 2 * me.realFontSize_x;
+ me.columnNameOrigin = me.columnIconOrigin + me.columnIconSize + (0.5 * me.realFontSize_x);
+ me.columnNameSize = 1 - me.columnIconSize - (1.5 * me.realFontSize_x);
}
float XonoticGametypeList_keyDown(entity me, float scan, float ascii, float shift)
ATTRIB(XonoticInputBox, cvarName, string, string_null)
METHOD(XonoticInputBox, loadCvars, void(entity))
METHOD(XonoticInputBox, saveCvars, void(entity))
+ ATTRIB(XonoticInputBox, sendCvars, float, 0)
METHOD(XonoticInputBox, keyDown, float(entity, float, float, float))
ATTRIB(XonoticInputBox, saveImmediately, float, 0)
if (!me.cvarName)
return;
cvar_set(me.cvarName, me.text);
+ CheckSendCvars(me, me.cvarName);
}
float XonoticInputBox_keyDown(entity me, float key, float ascii, float shift)
{
ATTRIB(MainWindow, firstRunDialog, entity, NULL)
ATTRIB(MainWindow, advancedDialog, entity, NULL)
ATTRIB(MainWindow, mutatorsDialog, entity, NULL)
- ATTRIB(MainWindow, weaponsDialog, entity, NULL)
ATTRIB(MainWindow, mapInfoDialog, entity, NULL)
ATTRIB(MainWindow, userbindEditDialog, entity, NULL)
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, languageWarningDialog, entity, NULL)
ATTRIB(MainWindow, mainNexposee, entity, NULL)
ATTRIB(MainWindow, fadedAlpha, float, SKINALPHA_BEHIND)
ATTRIB(MainWindow, dialogToShow, entity, NULL)
+ ATTRIB(MainWindow, demostartconfirmDialog, entity, NULL)
+ ATTRIB(MainWindow, demotimeconfirmDialog, entity, NULL)
ENDCLASS(MainWindow)
#endif
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);
i.configureDialog(i);
me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
+ me.hudconfirmDialog = i = spawnXonoticHUDConfirmDialog();
+ me.languageWarningDialog = i = spawnXonoticLanguageWarningDialog();
+ i.configureDialog(i);
+ me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
+
// dialog used by singleplayer
me.winnerDialog = i = spawnXonoticWinnerDialog();
me.serverInfoDialog = i = spawnXonoticServerInfoDialog();
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();
+
+ me.demostartconfirmDialog = i = spawnXonoticDemoStartConfirmDialog();
i.configureDialog(i);
me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
- me.mutatorsDialog = i = spawnXonoticMutatorsDialog();
+ me.demotimeconfirmDialog = i = spawnXonoticDemoTimeConfirmDialog();
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);
-
- 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();
+ // 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.weaponsDialog = i = spawnXonoticWeaponsDialog();
+ me.mutatorsDialog = i = spawnXonoticMutatorsDialog();
i.configureDialog(i);
me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
-
// mutator dialogs
i = spawnXonoticSandboxToolsDialog();
i.configureDialog(i);
--- /dev/null
+#ifdef INTERFACE
+CLASS(XonoticScreenshotImage) EXTENDS(XonoticImage)
+ METHOD(XonoticScreenshotImage, configureXonoticScreenshotImage, void(entity))
+ METHOD(XonoticScreenshotImage, load, void(entity, string))
+ METHOD(XonoticScreenshotImage, draw, void(entity))
+ ATTRIB(XonoticScreenshotImage, focusable, float, 1) // mousePress and mouseDrag work only if focusable is set
+ METHOD(XonoticScreenshotImage, mousePress, float(entity, vector))
+ METHOD(XonoticScreenshotImage, mouseDrag, float(entity, vector))
+ METHOD(XonoticScreenshotImage, mouseMove, float(entity, vector))
+ METHOD(XonoticScreenshotImage, resizeNotify, void(entity, vector, vector, vector, vector))
+ ATTRIB(XonoticScreenshotImage, realFontSize, vector, '0 0 0')
+ ATTRIB(XonoticScreenshotImage, fontSize, float, SKINFONTSIZE_NORMAL)
+ ATTRIB(XonoticScreenshotImage, showTitle, float, 1)
+ ATTRIB(XonoticScreenshotImage, screenshotTime, float, 0)
+ ATTRIB(XonoticScreenshotImage, screenshotTitle, string, string_null)
+ENDCLASS(XonoticScreenshotImage)
+entity makeXonoticScreenshotImage();
+#endif
+
+#ifdef IMPLEMENTATION
+entity makeXonoticScreenshotImage()
+{
+ entity me;
+ me = spawnXonoticScreenshotImage();
+ me.configureXonoticScreenshotImage(me);
+ return me;
+}
+
+void XonoticScreenshotImage_configureXonoticScreenshotImage(entity me)
+{
+ me.configureXonoticImage(me, string_null, -2);
+ me.zoomLimitedByTheBox = FALSE; // enable this to forbid enlarging the image more than the containing box (if making use of draw_SetClip is a too bad thing)
+ me.zoomSnapToTheBox = FALSE; // disabled: it's cooler
+}
+
+void XonoticScreenshotImage_load(entity me, string theImage)
+{
+ me.screenshotTime = time;
+ me.src = theImage;
+ if (me.screenshotTitle)
+ strunzone(me.screenshotTitle);
+ me.screenshotTitle = strzone(substring(me.src, 13, strlen(theImage) - 13)); //strip "/screenshots/"
+
+ me.initZoom(me); // this image may have a different size
+ me.setZoom(me, 0, 0);
+}
+
+float XonoticScreenshotImage_mousePress(entity me, vector coords)
+{
+ return me.drag_setStartPos(me, coords);
+}
+
+float XonoticScreenshotImage_mouseDrag(entity me, vector coords)
+{
+ return me.drag(me, coords);
+}
+
+float XonoticScreenshotImage_mouseMove(entity me, vector coords)
+{
+ return me.drag_setStartPos(me, coords);
+}
+
+void XonoticScreenshotImage_draw(entity me)
+{
+ if (me.src != "")
+ {
+ float theAlpha;
+ SUPER(XonoticScreenshotImage).draw(me);
+ if (me.showTitle && time < me.screenshotTime + 4) // 3 seconds at full alpha, 1 second fading out
+ {
+ theAlpha = (4 - (time - me.screenshotTime));
+ draw_CenterText('0.5 0 0', me.screenshotTitle, me.realFontSize, '1 1 1', theAlpha, FALSE);
+ }
+ if (time < me.zoomTime + 2) // 1 seconds at full alpha, 1 second fading out
+ {
+ string zoomString;
+ float z;
+ z = me.zoomFactor * 100;
+ if (z - floor(z) == 0)
+ zoomString = sprintf("%d%%", z);
+ else
+ zoomString = sprintf("%.2f%%", z);
+ theAlpha = (2 - (time - me.zoomTime));
+ draw_Text('0.05 0.95 0', zoomString, me.realFontSize, '1 1 1', theAlpha, FALSE);
+ }
+ }
+}
+
+void XonoticScreenshotImage_resizeNotify(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)
+{
+ SUPER(XonoticScreenshotImage).resizeNotify(me, relOrigin, relSize, absOrigin, absSize);
+ me.realFontSize_y = me.fontSize / absSize_y;
+ me.realFontSize_x = me.fontSize / absSize_x;
+}
+#endif
--- /dev/null
+#ifdef INTERFACE
+CLASS(XonoticScreenshotList) EXTENDS(XonoticListBox)
+ METHOD(XonoticScreenshotList, configureXonoticScreenshotList, void(entity))
+ ATTRIB(XonoticScreenshotList, rowsPerItem, float, 1)
+ METHOD(XonoticScreenshotList, resizeNotify, void(entity, vector, vector, vector, vector))
+ METHOD(XonoticScreenshotList, setSelected, void(entity, float))
+ METHOD(XonoticScreenshotList, draw, void(entity))
+ METHOD(XonoticScreenshotList, drawListBoxItem, void(entity, float, vector, float))
+ METHOD(XonoticScreenshotList, getScreenshots, void(entity))
+ METHOD(XonoticScreenshotList, previewScreenshot, void(entity))
+ METHOD(XonoticScreenshotList, startScreenshot, void(entity))
+ METHOD(XonoticScreenshotList, screenshotName, string(entity, float))
+ METHOD(XonoticScreenshotList, clickListBoxItem, void(entity, float, vector))
+ METHOD(XonoticScreenshotList, keyDown, float(entity, float, float, float))
+ METHOD(XonoticScreenshotList, destroy, void(entity))
+ METHOD(XonoticScreenshotList, showNotify, void(entity))
+ ATTRIB(XonoticScreenshotList, listScreenshot, float, -1)
+ ATTRIB(XonoticScreenshotList, realFontSize, vector, '0 0 0')
+ ATTRIB(XonoticScreenshotList, columnNameOrigin, float, 0)
+ ATTRIB(XonoticScreenshotList, columnNameSize, float, 0)
+ ATTRIB(XonoticScreenshotList, realUpperMargin, float, 0)
+ ATTRIB(XonoticScreenshotList, origin, vector, '0 0 0')
+ ATTRIB(XonoticScreenshotList, itemAbsSize, vector, '0 0 0')
+ ATTRIB(XonoticScreenshotList, lastClickedScreenshot, float, -1)
+ ATTRIB(XonoticScreenshotList, lastClickedTime, float, 0)
+ ATTRIB(XonoticScreenshotList, filterString, string, string_null)
+ ATTRIB(XonoticScreenshotList, filterBox, entity, NULL)
+ ATTRIB(XonoticScreenshotList, filterTime, float, 0)
+
+ ATTRIB(XonoticScreenshotList, newScreenshotTime, float, 0)
+ ATTRIB(XonoticScreenshotList, newSlideShowScreenshotTime, float, 0)
+ ATTRIB(XonoticScreenshotList, prevSelectedItem, float, 0)
+
+ ATTRIB(XonoticScreenshotList, screenshotBrowserDialog, entity, NULL)
+ ATTRIB(XonoticScreenshotList, screenshotPreview, entity, NULL)
+ ATTRIB(XonoticScreenshotList, screenshotViewerDialog, entity, NULL)
+ METHOD(XonoticScreenshotList, goScreenshot, void(entity, float))
+ METHOD(XonoticScreenshotList, startSlideShow, void(entity))
+ METHOD(XonoticScreenshotList, stopSlideShow, void(entity))
+ENDCLASS(XonoticScreenshotList)
+
+entity makeXonoticScreenshotList();
+void StartScreenshot_Click(entity btn, entity me);
+void ScreenshotList_Refresh_Click(entity btn, entity me);
+void ScreenshotList_Filter_Would_Change(entity box, entity me);
+void ScreenshotList_Filter_Change(entity box, entity me);
+#endif
+
+#ifdef IMPLEMENTATION
+
+entity makeXonoticScreenshotList()
+{
+ entity me;
+ me = spawnXonoticScreenshotList();
+ me.configureXonoticScreenshotList(me);
+ return me;
+}
+
+void XonoticScreenshotList_configureXonoticScreenshotList(entity me)
+{
+ me.configureXonoticListBox(me);
+ me.getScreenshots(me);
+}
+
+string XonoticScreenshotList_screenshotName(entity me, float i)
+{
+ string s;
+ s = bufstr_get(me.listScreenshot, i);
+
+ if(substring(s, 0, 1) == "/")
+ s = substring(s, 1, strlen(s) - 1); // remove the first forward slash
+
+ return s;
+}
+
+// if subdir is TRUE look in subdirectories too (1 level)
+void getScreenshots_for_ext(entity me, string ext, float subdir)
+{
+ string s;
+ if (subdir)
+ s="screenshots/*/";
+ else
+ s="screenshots/";
+ if(me.filterString)
+ s=strcat(s, me.filterString, ext);
+ else
+ s=strcat(s, "*", ext);
+
+ float list, i, n;
+ list = search_begin(s, FALSE, TRUE);
+ if(list >= 0)
+ {
+ n = search_getsize(list);
+ for(i = 0; i < n; ++i)
+ {
+ s = search_getfilename(list, i); // get initial full file name
+ s = substring(s, 12, (strlen(s) - 12 - 4)); // remove "screenshots/" prefix and ".<ext>" suffix
+ s = strdecolorize(s); // remove any pre-existing colors
+ if(subdir)
+ {
+ s = strreplace("/", "^7/", s); // clear colors at the forward slash
+ s = strcat("/", rgb_to_hexcolor(SKINCOLOR_SCREENSHOTLIST_SUBDIR), s); // add a forward slash for sorting, then color
+ bufstr_add(me.listScreenshot, s, TRUE);
+ }
+ else { bufstr_add(me.listScreenshot, s, TRUE); }
+ }
+ search_end(list);
+ }
+
+ if (subdir)
+ getScreenshots_for_ext(me, ext, FALSE);
+}
+
+void XonoticScreenshotList_getScreenshots(entity me)
+{
+ if (me.listScreenshot >= 0)
+ buf_del(me.listScreenshot);
+ me.listScreenshot = buf_create();
+ if (me.listScreenshot < 0)
+ {
+ me.nItems = 0;
+ return;
+ }
+ getScreenshots_for_ext(me, ".jpg", TRUE);
+ getScreenshots_for_ext(me, ".tga", TRUE);
+ getScreenshots_for_ext(me, ".png", TRUE);
+ me.nItems = buf_getsize(me.listScreenshot);
+ if(me.nItems > 0)
+ buf_sort(me.listScreenshot, 128, FALSE);
+}
+
+void XonoticScreenshotList_destroy(entity me)
+{
+ if(me.nItems > 0)
+ buf_del(me.listScreenshot);
+}
+
+void XonoticScreenshotList_resizeNotify(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)
+{
+ me.itemAbsSize = '0 0 0';
+ SUPER(XonoticScreenshotList).resizeNotify(me, relOrigin, relSize, absOrigin, absSize);
+
+ me.realFontSize_y = me.fontSize / (me.itemAbsSize_y = (absSize_y * me.itemHeight));
+ me.realFontSize_x = me.fontSize / (me.itemAbsSize_x = (absSize_x * (1 - me.controlWidth)));
+ me.realUpperMargin = 0.5 * (1 - me.realFontSize_y);
+
+ me.columnNameOrigin = me.realFontSize_x;
+ me.columnNameSize = 1 - 2 * me.realFontSize_x;
+}
+
+void XonoticScreenshotList_setSelected(entity me, float i)
+{
+ if (me.newSlideShowScreenshotTime)
+ me.startSlideShow(me);
+ me.prevSelectedItem = me.selectedItem;
+ SUPER(XonoticScreenshotList).setSelected(me, i);
+ if (me.pressed && me.selectedItem != me.prevSelectedItem)
+ {
+ // while dragging the scrollbar (or an item)
+ // for a smooth mouse movement do not load immediately the new selected images
+ me.newScreenshotTime = time + 0.22; // dragging an item we need a delay > 0.2 (from listbox: me.dragScrollTimer = time + 0.2;)
+ }
+ else if (time > me.newScreenshotTime)
+ {
+ me.newScreenshotTime = 0;
+ me.previewScreenshot(me); // load the preview on selection change
+ }
+}
+
+void XonoticScreenshotList_drawListBoxItem(entity me, float i, vector absSize, float isSelected)
+{
+ string s;
+ if(isSelected)
+ draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_SELECTED, SKINALPHA_LISTBOX_SELECTED);
+
+ s = me.screenshotName(me,i);
+ s = draw_TextShortenToWidth(s, me.columnNameSize, 0, me.realFontSize);
+ draw_Text(me.realUpperMargin * eY + (me.columnNameOrigin + 0.00 * (me.columnNameSize - draw_TextWidth(s, 0, me.realFontSize))) * eX, s, me.realFontSize, '1 1 1', SKINALPHA_TEXT, 1);
+}
+
+void XonoticScreenshotList_showNotify(entity me)
+{
+ me.getScreenshots(me);
+ me.previewScreenshot(me);
+}
+
+void ScreenshotList_Refresh_Click(entity btn, entity me)
+{
+ me.getScreenshots(me);
+ me.setSelected(me, 0); //always select the first element after a list update
+}
+
+void ScreenshotList_Filter_Change(entity box, entity me)
+{
+ if(me.filterString)
+ strunzone(me.filterString);
+
+ if(box.text != "")
+ {
+ if (strstrofs(box.text, "*", 0) >= 0 || strstrofs(box.text, "?", 0) >= 0)
+ me.filterString = strzone(box.text);
+ else
+ me.filterString = strzone(strcat("*", box.text, "*"));
+ }
+ else
+ me.filterString = string_null;
+
+ ScreenshotList_Refresh_Click(world, me);
+}
+
+void ScreenshotList_Filter_Would_Change(entity box, entity me)
+{
+ me.filterBox = box;
+ me.filterTime = time + 0.5;
+}
+
+void XonoticScreenshotList_draw(entity me)
+{
+ if (me.filterTime && time > me.filterTime)
+ {
+ ScreenshotList_Filter_Change(me.filterBox, me);
+ me.filterTime = 0;
+ }
+ if (me.newScreenshotTime && time > me.newScreenshotTime)
+ {
+ me.previewScreenshot(me);
+ me.newScreenshotTime = 0;
+ }
+ else if (me.newSlideShowScreenshotTime && time > me.newSlideShowScreenshotTime)
+ {
+ if (me.selectedItem == me.nItems - 1) //last screenshot?
+ {
+ // restart from the first screenshot
+ me.setSelected(me, 0);
+ me.goScreenshot(me, +0);
+ }
+ else
+ me.goScreenshot(me, +1);
+ }
+ SUPER(XonoticScreenshotList).draw(me);
+}
+
+void XonoticScreenshotList_startSlideShow(entity me)
+{
+ me.newSlideShowScreenshotTime = time + 3;
+}
+
+void XonoticScreenshotList_stopSlideShow(entity me)
+{
+ me.newSlideShowScreenshotTime = 0;
+}
+
+void XonoticScreenshotList_goScreenshot(entity me, float d)
+{
+ if(!me.screenshotViewerDialog)
+ return;
+ me.setSelected(me, me.selectedItem + d);
+ me.screenshotViewerDialog.loadScreenshot(me.screenshotViewerDialog, strcat("/screenshots/", strdecolorize(me.screenshotName(me,me.selectedItem))));
+}
+
+void XonoticScreenshotList_startScreenshot(entity me)
+{
+ me.screenshotViewerDialog.loadScreenshot(me.screenshotViewerDialog, strcat("/screenshots/", strdecolorize(me.screenshotName(me,me.selectedItem))));
+ // pop up screenshot
+ DialogOpenButton_Click_withCoords(NULL, me.screenshotViewerDialog, me.origin + eX * (me.columnNameOrigin * me.size_x) + eY * ((me.itemHeight * me.selectedItem - me.scrollPos) * me.size_y), eY * me.itemAbsSize_y + eX * (me.itemAbsSize_x * me.columnNameSize));
+}
+
+void XonoticScreenshotList_previewScreenshot(entity me)
+{
+ if(!me.screenshotBrowserDialog)
+ return;
+ if (me.nItems <= 0)
+ me.screenshotBrowserDialog.loadPreviewScreenshot(me.screenshotBrowserDialog, "");
+ else
+ me.screenshotBrowserDialog.loadPreviewScreenshot(me.screenshotBrowserDialog, strcat("/screenshots/", strdecolorize(me.screenshotName(me,me.selectedItem))));
+}
+
+void StartScreenshot_Click(entity btn, entity me)
+{
+ me.startScreenshot(me);
+}
+
+void XonoticScreenshotList_clickListBoxItem(entity me, float i, vector where)
+{
+ if(i == me.lastClickedScreenshot)
+ if(time < me.lastClickedTime + 0.3)
+ {
+ // DOUBLE CLICK!
+ // pop up screenshot
+ me.setSelected(me, i);
+ me.startScreenshot(me);
+ }
+ me.lastClickedScreenshot = i;
+ me.lastClickedTime = time;
+}
+
+float XonoticScreenshotList_keyDown(entity me, float scan, float ascii, float shift)
+{
+ if(scan == K_ENTER || scan == K_KP_ENTER) {
+ me.startScreenshot(me);
+ return 1;
+ }
+ if(scan == K_MWHEELUP || scan == K_MWHEELDOWN)
+ me.newScreenshotTime = time + 0.2;
+ return SUPER(XonoticScreenshotList).keyDown(me, scan, ascii, shift);
+}
+#endif
{
if (me.nItems != 0)
main.serverInfoDialog.loadServerInfo(main.serverInfoDialog, me.selectedItem);
- DialogOpenButton_Click(me, main.serverInfoDialog);
+
+ vector org = boxToGlobal(eY * (me.selectedItem * me.itemHeight - me.scrollPos), me.origin, me.size);
+ vector sz = boxToGlobalSize(eY * me.itemHeight + eX * (1 - me.controlWidth), me.size);
+ DialogOpenButton_Click_withCoords(me, main.serverInfoDialog, org, sz);
}
void XonoticServerList_clickListBoxItem(entity me, float i, vector where)
{
ATTRIB(XonoticSlider, cvarName, string, string_null)
METHOD(XonoticSlider, loadCvars, void(entity))
METHOD(XonoticSlider, saveCvars, void(entity))
+ ATTRIB(XonoticSlider, sendCvars, float, 0)
ATTRIB(XonoticSlider, alpha, float, SKINALPHA_TEXT)
ATTRIB(XonoticSlider, disabledAlpha, float, SKINALPHA_DISABLED)
return;
cvar_set(me.cvarName, ftos(me.value));
+
+ CheckSendCvars(me, me.cvarName);
}
#endif
--- /dev/null
+#ifdef INTERFACE
+CLASS(XonoticParticlesSlider) EXTENDS(XonoticTextSlider)
+ METHOD(XonoticParticlesSlider, configureXonoticParticlesSlider, void(entity))
+ METHOD(XonoticParticlesSlider, loadCvars, void(entity))
+ METHOD(XonoticParticlesSlider, saveCvars, void(entity))
+ENDCLASS(XonoticParticlesSlider)
+entity makeXonoticParticlesSlider();
+#endif
+
+#ifdef IMPLEMENTATION
+entity makeXonoticParticlesSlider()
+{
+ entity me;
+ me = spawnXonoticParticlesSlider();
+ me.configureXonoticParticlesSlider(me);
+ return me;
+}
+void XonoticParticlesSlider_configureXonoticParticlesSlider(entity me)
+{
+ me.configureXonoticTextSlider(me, "cl_particles_quality");
+ if(cvar("developer")) { me.addValue(me, ZCTX(_("PART^OMG")), "0.4 250 0"); }
+ me.addValue(me, ZCTX(_("PART^Low")), "0.4 500 0");
+ me.addValue(me, ZCTX(_("PART^Medium")), "0.8 750 0");
+ me.addValue(me, ZCTX(_("PART^Normal")), "1.0 1000 1");
+ me.addValue(me, ZCTX(_("PART^High")), "1.0 1500 1");
+ me.addValue(me, ZCTX(_("PART^Ultra")), "1.0 2000 2");
+ if(cvar("developer")) { me.addValue(me, ZCTX(_("PART^Ultimate")), "1.0 3000 2"); }
+ me.configureXonoticTextSliderValues(me);
+}
+void XonoticParticlesSlider_loadCvars(entity me)
+{
+ me.setValueFromIdentifier(me, sprintf("%s %s %s",
+ cvar_string("cl_particles_quality"),
+ cvar_string("r_drawparticles_drawdistance"),
+ cvar_string("cl_damageeffect")
+ ));
+}
+void XonoticParticlesSlider_saveCvars(entity me)
+{
+ if(me.value >= 0 || me.value < me.nValues)
+ {
+ tokenize_console(me.getIdentifier(me));
+ cvar_set("cl_particles_quality", argv(0));
+ cvar_set("r_drawparticles_drawdistance", argv(1));
+ cvar_set("cl_damageeffect", argv(2));
+ }
+}
+#endif
--- /dev/null
+#ifdef INTERFACE
+CLASS(XonoticScoreboardFadeTimeSlider) EXTENDS(XonoticTextSlider)
+ METHOD(XonoticScoreboardFadeTimeSlider, configureXonoticScoreboardFadeTimeSlider, void(entity))
+ METHOD(XonoticScoreboardFadeTimeSlider, loadCvars, void(entity))
+ METHOD(XonoticScoreboardFadeTimeSlider, saveCvars, void(entity))
+ENDCLASS(XonoticScoreboardFadeTimeSlider)
+entity makeXonoticScoreboardFadeTimeSlider();
+#endif
+
+#ifdef IMPLEMENTATION
+entity makeXonoticScoreboardFadeTimeSlider()
+{
+ entity me;
+ me = spawnXonoticScoreboardFadeTimeSlider();
+ me.configureXonoticScoreboardFadeTimeSlider(me);
+ return me;
+}
+void XonoticScoreboardFadeTimeSlider_configureXonoticScoreboardFadeTimeSlider(entity me)
+{
+ me.configureXonoticTextSlider(me, "scoreboard_fadeinspeed");
+ me.addValue(me, ZCTX(_("PART^Slow")), "5 2.5");
+ me.addValue(me, ZCTX(_("PART^Normal")), "10 5");
+ me.addValue(me, ZCTX(_("PART^Fast")), "15 7.5");
+ me.addValue(me, ZCTX(_("PART^Instant")), "0 0");
+ me.configureXonoticTextSliderValues(me);
+}
+void XonoticScoreboardFadeTimeSlider_loadCvars(entity me)
+{
+ me.setValueFromIdentifier(me, sprintf("%s %s",
+ cvar_string("scoreboard_fadeinspeed"),
+ cvar_string("scoreboard_fadeoutspeed")
+ ));
+}
+void XonoticScoreboardFadeTimeSlider_saveCvars(entity me)
+{
+ if(me.value >= 0 || me.value < me.nValues)
+ {
+ tokenize_console(me.getIdentifier(me));
+ cvar_set("scoreboard_fadeinspeed", argv(0));
+ cvar_set("scoreboard_fadeoutspeed", argv(1));
+ }
+}
+#endif
--- /dev/null
+#ifdef INTERFACE
+CLASS(XonoticStatsList) EXTENDS(XonoticListBox)
+ METHOD(XonoticStatsList, configureXonoticStatsList, void(entity))
+ ATTRIB(XonoticStatsList, rowsPerItem, float, 1.4)
+ METHOD(XonoticStatsList, resizeNotify, void(entity, vector, vector, vector, vector))
+ METHOD(XonoticStatsList, drawListBoxItem, void(entity, float, vector, float))
+ METHOD(XonoticStatsList, getStats, void(entity))
+ METHOD(XonoticStatsList, clickListBoxItem, void(entity, float, vector))
+ METHOD(XonoticStatsList, keyDown, float(entity, float, float, float))
+ METHOD(XonoticStatsList, destroy, void(entity))
+ METHOD(XonoticStatsList, showNotify, void(entity))
+
+ ATTRIB(XonoticStatsList, listStats, float, -1)
+ ATTRIB(XonoticStatsList, realFontSize, vector, '0 0 0')
+ ATTRIB(XonoticStatsList, realUpperMargin, float, 0)
+ ATTRIB(XonoticStatsList, columnNameOrigin, float, 0)
+ ATTRIB(XonoticStatsList, columnNameSize, float, 0)
+
+ ATTRIB(XonoticStatsList, lastClickedDemo, float, -1)
+ ATTRIB(XonoticStatsList, lastClickedTime, float, 0)
+ENDCLASS(XonoticStatsList)
+
+entity statslist; // for reference elsewhere
+entity makeXonoticStatsList();
+#endif
+
+#ifdef IMPLEMENTATION
+
+entity makeXonoticStatsList()
+{
+ entity me;
+ me = spawnXonoticStatsList();
+ me.configureXonoticStatsList(me);
+ return me;
+}
+
+void XonoticStatsList_configureXonoticStatsList(entity me)
+{
+ me.configureXonoticListBox(me);
+ me.getStats(me);
+}
+
+string XonoticStatsList_convertDate(string input)
+{
+ // 2013-12-21
+ // 0123456789
+ if(strlen(input) != 10)
+ return input;
+
+ string monthname = "";
+
+ switch(stof(substring(input, 5, 2)))
+ {
+ case 1: monthname = _("January"); break;
+ case 2: monthname = _("February"); break;
+ case 3: monthname = _("March"); break;
+ case 4: monthname = _("April"); break;
+ case 5: monthname = _("May"); break;
+ case 6: monthname = _("June"); break;
+ case 7: monthname = _("July"); break;
+ case 8: monthname = _("August"); break;
+ case 9: monthname = _("September"); break;
+ case 10: monthname = _("October"); break;
+ case 11: monthname = _("November"); break;
+ case 12: monthname = _("December"); break;
+ default: return input; // failed, why?
+ }
+
+ return sprintf(
+ "%s %s, %d",
+ monthname,
+ count_ordinal(stof(substring(input, 8, 2))),
+ stof(substring(input, 0, 4))
+ );
+}
+
+void XonoticStatsList_getStats(entity me)
+{
+ print("XonoticStatsList_getStats() at time: ", ftos(time), "\n");
+ // delete the old buffer if it exists
+ if(me.listStats >= 0)
+ buf_del(me.listStats);
+
+ // create the new buffer if we have a stats buffer
+ if(PS_D_IN_DB >= 0)
+ me.listStats = buf_create();
+
+ // now confirmation, if we didn't create a buffer then just return now
+ if(me.listStats < 0)
+ {
+ me.nItems = 0;
+ return;
+ }
+
+ float order = 0;
+ string e = "", en = "", data = "";
+
+ string outstr = ""; // NOTE: out string MUST use underscores for spaces here, we'll replace them later
+ string orderstr = "";
+
+ float out_total_matches = -1;
+ float out_total_wins = -1;
+ float out_total_losses = -1;
+
+ float out_total_kills = -1;
+ float out_total_deaths = -1;
+
+ for(e = PS_D_IN_EVL; (en = db_get(PS_D_IN_DB, e)) != ""; e = en)
+ {
+ order = 0;
+ outstr = "";
+ orderstr = "";
+ data = db_get(PS_D_IN_DB, sprintf("#%s", e));
+
+ // non-gamemode specific stuff
+ switch(e)
+ {
+ case "overall/joined_dt":
+ {
+ order = 1;
+ outstr = _("Joined:");
+ data = XonoticStatsList_convertDate(car(data));
+ break;
+ }
+ case "overall/last_seen_dt":
+ {
+ order = 1;
+ outstr = _("Last_Seen:");
+ data = XonoticStatsList_convertDate(car(data));
+ break;
+ }
+ case "overall/alivetime":
+ {
+ order = 1;
+ outstr = _("Time_Played:");
+ data = process_time(3, stof(data));
+ break;
+ }
+ case "overall/favorite-map":
+ {
+ order = 2;
+ outstr = _("Favorite_Map:");
+ data = car(data);
+ break;
+ }
+ case "overall/matches":
+ {
+ order = -1;
+ out_total_matches = stof(data);
+ break;
+ }
+ case "overall/wins":
+ {
+ order = -1;
+ out_total_wins = stof(data);
+ break;
+ }
+ case "overall/total-kills":
+ {
+ order = -1;
+ out_total_kills = stof(data);
+ break;
+ }
+ case "overall/total-deaths":
+ {
+ order = -1;
+ out_total_deaths = stof(data);
+ break;
+ }
+ }
+
+ if((order == -1) && (out_total_matches >= 0) && (out_total_wins >= 0))
+ {
+ bufstr_add(me.listStats, sprintf("003Matches: %d", out_total_matches), TRUE);
+
+ if(out_total_matches > 0) // don't show extra info if there are no matches played
+ {
+ out_total_losses = max(0, (out_total_matches - out_total_wins));
+ bufstr_add(me.listStats, sprintf("003Wins/Losses: %d/%d", out_total_wins, out_total_losses), TRUE);
+ bufstr_add(me.listStats, sprintf("004Win_Percentage: %d%%", ((out_total_wins / out_total_matches) * 100)), TRUE);
+ }
+
+ out_total_matches = -1;
+ out_total_wins = -1;
+ out_total_losses = -1;
+ continue;
+ }
+
+ if((order == -1) && (out_total_kills >= 0) && (out_total_deaths >= 0))
+ {
+ bufstr_add(me.listStats, sprintf("005Kills/Deaths: %d/%d", out_total_kills, out_total_deaths), TRUE);
+
+ // if there are no deaths, just show kill count
+ if(out_total_deaths > 0)
+ bufstr_add(me.listStats, sprintf("006Kill_Ratio: %.2f", (out_total_kills / out_total_deaths)), TRUE);
+ else
+ bufstr_add(me.listStats, sprintf("006Kill_Ratio: %.2f", out_total_kills), TRUE);
+
+ out_total_kills = -1;
+ out_total_deaths = -1;
+ continue;
+ }
+
+ // game mode specific stuff
+ if(order > 0)
+ {
+ orderstr = sprintf("%03d", order);
+ }
+ else
+ {
+ float dividerpos = strstrofs(e, "/", 0);
+
+ string gametype = substring(e, 0, dividerpos);
+ if(gametype == "overall") { continue; }
+
+ string event = substring(e, (dividerpos + 1), strlen(e) - (dividerpos + 1));
+
+ // if we are ranked, read these sets of possible options
+ if(stof(db_get(PS_D_IN_DB, sprintf("#%s/rank", gametype))))
+ {
+ switch(event)
+ {
+ case "matches":
+ {
+ order = 1;
+ outstr = sprintf(_("%s_Matches:"), strtoupper(gametype));
+ //data = sprintf(_("%d (unranked)"), data);
+ break;
+ }
+ case "elo":
+ {
+ order = 2;
+ outstr = sprintf(_("%s_ELO:"), strtoupper(gametype));
+ data = sprintf("%d", stof(data));
+ break;
+ }
+ case "rank":
+ {
+ order = 3;
+ outstr = sprintf(_("%s_Rank:"), strtoupper(gametype));
+ data = sprintf("%d", stof(data));
+ break;
+ }
+ case "percentile":
+ {
+ order = 4;
+ outstr = sprintf(_("%s_Percentile:"), strtoupper(gametype));
+ data = sprintf("%d%%", stof(data));
+ break;
+ }
+
+ #if 0
+ case "favorite-map":
+ {
+ order = 5;
+ outstr = sprintf(_("%s_Favorite_Map:"), strtoupper(gametype));
+ //data = sprintf(_("%d (unranked)"), data);
+ break;
+ }
+ #endif
+
+ default: continue; // nothing to see here
+ }
+
+ // now set up order for sorting later
+ orderstr = sprintf("%2.2s%d", gametype, order);
+ }
+ else if(event == "matches")
+ {
+ outstr = sprintf(_("%s_Matches:"), strtoupper(gametype));
+ data = sprintf(_("%d (unranked)"), stof(data));
+
+ // unranked game modes ALWAYS get put last
+ orderstr = "zzz";
+ }
+ else { continue; }
+ }
+
+ bufstr_add(me.listStats, sprintf("%s%s %s", orderstr, outstr, data), TRUE);
+ }
+
+ me.nItems = buf_getsize(me.listStats);
+ if(me.nItems > 0)
+ buf_sort(me.listStats, 128, FALSE);
+}
+
+void XonoticStatsList_destroy(entity me)
+{
+ if(me.nItems > 0)
+ buf_del(me.listStats);
+}
+
+void XonoticStatsList_resizeNotify(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)
+{
+ me.itemAbsSize = '0 0 0';
+ SUPER(XonoticStatsList).resizeNotify(me, relOrigin, relSize, absOrigin, absSize);
+
+ me.realFontSize_y = me.fontSize / (me.itemAbsSize_y = (absSize_y * me.itemHeight));
+ me.realFontSize_x = me.fontSize / (me.itemAbsSize_x = (absSize_x * (1 - me.controlWidth)));
+ me.realUpperMargin = 0.5 * (1 - me.realFontSize_y);
+
+#if 0
+ me.columnNameOrigin = me.realFontSize_x;
+ me.columnNameSize = 0.5 - me.realFontSize_x; // end halfway at maximum length
+ me.columnDataOrigin = me.columnNameOrigin + me.columnNameSize;
+ me.columnDataSize = 1 - me.columnNameSize - me.realFontSize_x; // fill the rest of the control
+#else
+ me.columnNameOrigin = me.realFontSize_x;
+ me.columnNameSize = 1 - 2 * me.realFontSize_x;
+#endif
+}
+
+void XonoticStatsList_drawListBoxItem(entity me, float i, vector absSize, float isSelected)
+{
+ if(isSelected)
+ draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_SELECTED, SKINALPHA_LISTBOX_SELECTED);
+
+ string data = bufstr_get(me.listStats, i);
+ string s = car(data);
+ string d = cdr(data);
+
+ s = substring(s, 3, strlen(s) - 3);
+ s = strreplace("_", " ", s);
+ s = draw_TextShortenToWidth(s, 0.5 * me.columnNameSize, 0, me.realFontSize);
+ draw_Text(me.realUpperMargin * eY + me.columnNameOrigin * eX, s, me.realFontSize, '1 1 1', SKINALPHA_TEXT, 1);
+
+ d = draw_TextShortenToWidth(d, me.columnNameSize - draw_TextWidth(s, 0, me.realFontSize), 0, me.realFontSize);
+ draw_Text(me.realUpperMargin * eY + (me.columnNameOrigin + 1 * (me.columnNameSize - draw_TextWidth(d, 0, me.realFontSize))) * eX, d, me.realFontSize, '1 1 1', SKINALPHA_TEXT, 1);
+}
+
+void XonoticStatsList_showNotify(entity me)
+{
+ PlayerStats_PlayerDetail_CheckUpdate();
+}
+
+void XonoticStatsList_clickListBoxItem(entity me, float i, vector where)
+{
+ if(i == me.lastClickedDemo)
+ if(time < me.lastClickedTime + 0.3)
+ {
+ // DOUBLE CLICK!
+ me.setSelected(me, i);
+ //DemoConfirm_ListClick_Check_Gamestatus(me);
+ }
+ me.lastClickedDemo = i;
+ me.lastClickedTime = time;
+}
+
+float XonoticStatsList_keyDown(entity me, float scan, float ascii, float shift)
+{
+ if(scan == K_ENTER || scan == K_KP_ENTER)
+ {
+ //DemoConfirm_ListClick_Check_Gamestatus(me);
+ return 1;
+ }
+ else
+ {
+ return SUPER(XonoticStatsList).keyDown(me, scan, ascii, shift);
+ }
+}
+#endif
+
ATTRIB(XonoticTextSlider, cvarName, string, string_null)
METHOD(XonoticTextSlider, loadCvars, void(entity))
METHOD(XonoticTextSlider, saveCvars, void(entity))
+ ATTRIB(XonoticTextSlider, sendCvars, float, 0)
ATTRIB(XonoticTextSlider, alpha, float, SKINALPHA_TEXT)
ATTRIB(XonoticTextSlider, disabledAlpha, float, SKINALPHA_DISABLED)
{
// this is a special case to allow spaces in the identifiers
cvar_set(argv(0), me.getIdentifier(me));
+ CheckSendCvars(me, argv(0));
}
else
{
if(m == n + 1)
{
for(i = 0; i < n; ++i)
+ {
cvar_set(argv(i), argv(n));
+ CheckSendCvars(me, argv(i));
+ }
}
else if(m == n * 2)
{
for(i = 0; i < n; ++i)
+ {
cvar_set(argv(i), argv(i + n));
+ CheckSendCvars(me, argv(i));
+ }
}
else
error("XonoticTextSlider: invalid identifier ", me.getIdentifier(me), " does not match cvar list ", me.cvarName);
cvar_set(substring(argv(i), 1, strlen(argv(i))), ((s == "0") ? "1" : "0"));
else
cvar_set(argv(i), s);
+
+ CheckSendCvars(me, argv(i));
}
}
void makeMulti(entity e, string otherCvars)
return "";
}
-/*string GameType_GetTeams(float cnt) // poor implementation, later something else could be done that's better?
-{
- float i = GameType_GetID(cnt);
- string s = _MapInfo_GetDefaultEx(i);
-
- if(i)
- {
- if(strstrofs(s, "teams", 0) >= 0)
- return _("teamplay");
- else
- return _("free for all");
- }
-
- return _("tuba for all");
-}*/
-
void dialog_hudpanel_common_notoggle(entity me, string panelname)
{
float i;
e.addValue(e, strzone(ftos_decimals(i - 5, 0)), strzone(ftos(i - 5)));
e.configureXonoticTextSliderValues(e);
}
+
+void CheckSendCvars(entity me, string cvarnamestring)
+{
+ if(me.sendCvars)
+ {
+ printf("Sending cvar: %s -> %s\n", cvarnamestring, cvar_string(cvarnamestring));
+ if(gamestatus & (GAME_CONNECTED | GAME_ISSERVER))
+ {
+ cmd(sprintf("\nsendcvar %s\n", cvarnamestring));
+ }
+ }
+}
float _Nex_ExtResponseSystem_PromotedServersNeedsRefresh;
string _Nex_ExtResponseSystem_RecommendedServers;
float _Nex_ExtResponseSystem_RecommendedServersNeedsRefresh;
+
+void CheckSendCvars(entity me, string cvarnamestring);
float autocvar_g_player_alpha;
float autocvar_g_player_brightness;
float autocvar_g_playerclip_collisions;
-string autocvar_g_playerstats_uri;
float autocvar_g_powerups;
float autocvar_g_projectiles_damage;
float autocvar_g_projectiles_keep_owner;
if(self.alivetime)
{
if(!warmup_stage)
- PlayerStats_Event(self, PLAYERSTATS_ALIVETIME, time - self.alivetime);
+ PS_GR_P_ADDVAL(self, PLAYERSTATS_ALIVETIME, time - self.alivetime);
self.alivetime = 0;
}
player_count = 0;
}
+ if(IS_REAL_CLIENT(self)) { PlayerStats_PlayerBasic_CheckUpdate(self); }
+
PlayerScore_Attach(self);
ClientData_Attach();
accuracy_init(self);
self.playerid = (playerid_last = playerid_last + 1);
- PlayerStats_AddEvent(sprintf("kills-%d", self.playerid));
+ PlayerStats_GameReport_AddEvent(sprintf("kills-%d", self.playerid));
if(IS_BOT_CLIENT(self))
- PlayerStats_AddPlayer(self);
+ PlayerStats_GameReport_AddPlayer(self);
if(autocvar_sv_eventlog)
GameLogEcho(strcat(":join:", ftos(self.playerid), ":", ftos(num_for_edict(self)), ":", ((IS_REAL_CLIENT(self)) ? self.netaddress : "bot"), ":", self.netname));
return;
}
- if(IS_PLAYER(self)) { pointparticles(particleeffectnum("spawn_event_neutral"), self.origin, '0 0 0', 1); }
+ PlayerStats_GameReport_FinalizePlayer(self);
- PlayerStats_AddGlobalInfo(self);
+ if(IS_PLAYER(self)) { pointparticles(particleeffectnum("spawn_event_neutral"), self.origin, '0 0 0', 1); }
CheatShutdownClient();
if(self.alivetime)
{
- PlayerStats_Event(self, PLAYERSTATS_ALIVETIME, time - self.alivetime);
+ PS_GR_P_ADDVAL(self, PLAYERSTATS_ALIVETIME, time - self.alivetime);
self.alivetime = 0;
}
{
tmp_player.alivetime = 0;
tmp_player.killcount = 0;
- PlayerStats_Event(tmp_player, PLAYERSTATS_ALIVETIME, -PlayerStats_Event(tmp_player, PLAYERSTATS_ALIVETIME, 0));
+ PS_GR_P_ADDVAL(tmp_player, PLAYERSTATS_ALIVETIME, -PS_GR_P_ADDVAL(tmp_player, PLAYERSTATS_ALIVETIME, 0));
}
restart_mapalreadyrestarted = 0; // reset this var, needed when cvar sv_ready_restart_repeatable is in use
#define MISSILE_IS_CONFUSABLE(m) ((m.missile_flags & MIF_GUIDED_CONFUSABLE) ? TRUE : FALSE)
#define MISSILE_IS_GUIDED(m) ((m.missile_flags & MIF_GUIDED_ALL) ? TRUE : FALSE)
#define MISSILE_IS_TRACKING(m) ((m.missile_flags & MIF_GUIDED_TRACKING) ? TRUE : FALSE)
+
+
+////
+
+.entity player_stats;
+//.float playerid;
+.string playernick;
+.float elos;
+.float ranks;
// regular frag
PlayerScore_Add(attacker, SP_KILLS, 1);
if(targ.playerid)
- PlayerStats_Event(attacker, sprintf("kills-%d", targ.playerid), 1);
+ PS_GR_P_ADDVAL(attacker, sprintf("kills-%d", targ.playerid), 1);
}
PlayerScore_Add(targ, SP_DEATHS, 1);
case counta: \
{ \
Send_Notification(NOTIF_ONE, attacker, MSG_ANNCE, ANNCE_KILLSTREAK_##countb); \
- PlayerStats_Event(attacker, PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_##counta, 1); \
+ PS_GR_P_ADDVAL(attacker, PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_##counta, 1); \
break; \
}
switch(attacker.killcount)
{
checkrules_firstblood = TRUE;
notif_firstblood = TRUE; // modify the current messages so that they too show firstblood information
- PlayerStats_Event(attacker, PLAYERSTATS_ACHIEVEMENT_FIRSTBLOOD, 1);
- PlayerStats_Event(targ, PLAYERSTATS_ACHIEVEMENT_FIRSTVICTIM, 1);
+ PS_GR_P_ADDVAL(attacker, PLAYERSTATS_ACHIEVEMENT_FIRSTBLOOD, 1);
+ PS_GR_P_ADDVAL(targ, PLAYERSTATS_ACHIEVEMENT_FIRSTVICTIM, 1);
// tell spree_inf and spree_cen that this is a first-blood and first-victim event
kill_count_to_attacker = -1;
if(PlayerScore_Add(targ, SP_SCORE, 0) == -5)
{
Send_Notification(NOTIF_ONE, targ, MSG_ANNCE, ANNCE_ACHIEVEMENT_BOTLIKE);
- PlayerStats_Event(attacker, PLAYERSTATS_ACHIEVEMENT_BOTLIKE, 1);
+ PS_GR_P_ADDVAL(attacker, PLAYERSTATS_ACHIEVEMENT_BOTLIKE, 1);
}
}
Map_MarkAsRecent(mapname);
- PlayerStats_Init(); // we need this to be initiated before InitGameplayMode
+ PlayerStats_GameReport_Init(); // we need this to be initiated before InitGameplayMode
precache_model ("null"); // we need this one before InitGameplayMode
InitGameplayMode();
DumpStats(TRUE);
// send statistics
- entity e;
- PlayerStats_EndMatch(1);
- FOR_EACH_CLIENT(e)
- PlayerStats_AddGlobalInfo(e);
- PlayerStats_Shutdown();
+ PlayerStats_GameReport(TRUE);
WeaponStats_Shutdown();
Kill_Notification(NOTIF_ALL, world, MSG_CENTER, 0); // kill all centerprints now
void Shutdown()
{
- entity e;
-
gameover = 2;
if(world_initialized > 0)
print("Saving persistent data...\n");
Ban_SaveBans();
- PlayerStats_EndMatch(0);
- FOR_EACH_CLIENT(e)
- PlayerStats_AddGlobalInfo(e);
- PlayerStats_Shutdown();
+ // playerstats with unfinished match
+ PlayerStats_GameReport(FALSE);
if(!cheatcount_total)
{
void MapVote_Start()
{
- if(mapvote_run)
- return;
+ // if mapvote is already running, don't do this initialization again
+ if(mapvote_run) { return; }
- // wait for stats to be sent first
- if(!playerstats_waitforme)
- return;
+ // don't start mapvote until after playerstats gamereport is sent
+ if(PlayerStats_GameReport_DelayMapVote) { return; }
MapInfo_Enumerate();
if(MapInfo_FilterGametype(MapInfo_CurrentGametype(), MapInfo_CurrentFeatures(), MapInfo_RequiredFlags(), MapInfo_ForbiddenFlags(), 1))
if (s == "cl_weaponpriority")
self.switchweapon = w_getbestweapon(self);
if (s == "cl_allow_uidtracking")
- PlayerStats_AddPlayer(self);
+ PlayerStats_GameReport_AddPlayer(self);
}
}
+++ /dev/null
-// time the player was alive and kicking
-const string PLAYERSTATS_ALIVETIME = "alivetime";
-const string PLAYERSTATS_AVGLATENCY = "avglatency";
-const string PLAYERSTATS_WINS = "wins";
-const string PLAYERSTATS_MATCHES = "matches";
-const string PLAYERSTATS_JOINS = "joins";
-const string PLAYERSTATS_SCOREBOARD_VALID = "scoreboardvalid";
-const string PLAYERSTATS_RANK = "rank";
-const string PLAYERSTATS_SCOREBOARD_POS = "scoreboardpos";
-
-const string PLAYERSTATS_TOTAL = "total-";
-const string PLAYERSTATS_SCOREBOARD = "scoreboard-";
-
-const string PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_3 = "achievement-kill-spree-3";
-const string PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_5 = "achievement-kill-spree-5";
-const string PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_10 = "achievement-kill-spree-10";
-const string PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_15 = "achievement-kill-spree-15";
-const string PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_20 = "achievement-kill-spree-20";
-const string PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_25 = "achievement-kill-spree-25";
-const string PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_30 = "achievement-kill-spree-30";
-const string PLAYERSTATS_ACHIEVEMENT_BOTLIKE = "achievement-botlike";
-const string PLAYERSTATS_ACHIEVEMENT_FIRSTBLOOD = "achievement-firstblood";
-const string PLAYERSTATS_ACHIEVEMENT_FIRSTVICTIM = "achievement-firstvictim";
-
-// delay map switch until this is set
-float playerstats_waitforme;
-
-// call at initialization
-void PlayerStats_Init();
-
-// add a new player
-void PlayerStats_AddPlayer(entity e);
-
-// add a new team
-void PlayerStats_AddTeam(float t);
-
-// add a new event
-void PlayerStats_AddEvent(string event_id);
-
-// call on each event to track, or at player disconnect OR match end for "global stuff"
-float PlayerStats_Event(entity e, string event_id, float value);
-
-// add a team score
-float PlayerStats_TeamScore(float t, string event_id, float value);
-
-// call at game over
-void PlayerStats_Shutdown(); // send stats to the server
-
-// call this whenever a player leaves
-void PlayerStats_AddGlobalInfo(entity p);
-
-// call this at the end of the match
-void PlayerStats_EndMatch(float finished);
anticheat.qh
cheats.qh
-playerstats.qh
+../common/playerstats.qh
portals.qh
anticheat.qc
cheats.qc
-playerstats.qc
+../common/playerstats.qc
round_handler.qc
Net_LinkEntity(ts, FALSE, 0, TeamScore_SendEntity);
teamscorekeepers[t - 1] = ts;
++teamscores_entities_count;
- PlayerStats_AddTeam(t);
+ PlayerStats_GameReport_AddTeam(t);
}
float TeamScore_AddToTeam(float t, float scorefield, float score)
}
if(label != "")
{
- PlayerStats_AddEvent(strcat(PLAYERSTATS_TOTAL, label));
- PlayerStats_AddEvent(strcat(PLAYERSTATS_SCOREBOARD, label));
+ PlayerStats_GameReport_AddEvent(strcat(PLAYERSTATS_TOTAL, label));
+ PlayerStats_GameReport_AddEvent(strcat(PLAYERSTATS_SCOREBOARD, label));
}
}
}
if(label != "")
{
- PlayerStats_AddEvent(strcat(PLAYERSTATS_TOTAL, label));
- PlayerStats_AddEvent(strcat(PLAYERSTATS_SCOREBOARD, label));
+ PlayerStats_GameReport_AddEvent(strcat(PLAYERSTATS_TOTAL, label));
+ PlayerStats_GameReport_AddEvent(strcat(PLAYERSTATS_SCOREBOARD, label));
}
}
if(scores_label[scorefield] != "")
s.SendFlags |= pow(2, scorefield);
if(!warmup_stage)
- PlayerStats_Event(s.owner, strcat(PLAYERSTATS_TOTAL, scores_label[scorefield]), score);
+ PS_GR_P_ADDVAL(s.owner, strcat(PLAYERSTATS_TOTAL, scores_label[scorefield]), score);
return (s.(scores[scorefield]) += score);
}
for(i = 0; i < MAX_SCORE; ++i)
if(s.(scores[i]) != 0)
if(scores_label[i] != "")
- PlayerStats_Event(s.owner, strcat(PLAYERSTATS_SCOREBOARD, scores_label[i]), s.(scores[i]));
+ PS_GR_P_ADDVAL(s.owner, strcat(PLAYERSTATS_SCOREBOARD, scores_label[i]), s.(scores[i]));
}
void PlayerScore_TeamStats(void)
if(sk.(teamscores[i]) != 0)
if(teamscores_label[i] != "")
// the +1 is important here!
- PlayerStats_TeamScore(t+1, strcat(PLAYERSTATS_SCOREBOARD, teamscores_label[i]), sk.(teamscores[i]));
+ PS_GR_T_ADDVAL(t+1, strcat(PLAYERSTATS_SCOREBOARD, teamscores_label[i]), sk.(teamscores[i]));
}
}
entity scores_initialized; // non-world when scores labels/rules have been set
.float scores[MAX_SCORE];
.float teamscores[MAX_TEAMSCORE];
+.float scoreboard_pos;
/**
* Attaches a PlayerScore entity to a player. Use that in ClientConnect.