cl_decals 1
cl_decals_models 0
cl_decals_time 4
-cl_particles_quality 1
+cl_particles 1
+cl_particles_quality 1.0
cl_damageeffect 1
cl_spawn_point_particles 1
cl_playerdetailreduction 0.5
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_decals_time 2
+cl_particles 1
cl_particles_quality 0.4
cl_damageeffect 0
cl_spawn_point_particles 0
cl_decals 1
cl_decals_models 0
cl_decals_time 2
-cl_particles_quality 1
+cl_particles 1
+cl_particles_quality 0.8
cl_damageeffect 0
cl_spawn_point_particles 0
cl_playerdetailreduction 1
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_time 2
-cl_particles_quality 1
+cl_particles 1
+cl_particles_quality 1.0
cl_damageeffect 1
cl_spawn_point_particles 1
cl_playerdetailreduction 1
cl_decals 0
cl_decals_models 0
cl_decals_time 2
+cl_particles 1
cl_particles_quality 0.4
cl_damageeffect 0
cl_spawn_point_particles 0
cl_decals 1
cl_decals_models 1
cl_decals_time 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_time 10
-cl_particles_quality 1
-cl_damageeffect 1
+cl_particles 1
+cl_particles_quality 1.0
+cl_damageeffect 2
cl_spawn_point_particles 1
cl_playerdetailreduction 0
gl_flashblend 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'
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'
//registercommand("hud_configure");
//registercommand("hud_save");
//registercommand("menu_action");
-
+
ConsoleCommand_macro_init();
registercvar("hud_usecsqc", "1");
turrets_precache();
Tuba_Precache();
CSQCPlayer_Precache();
-
+
if(autocvar_cl_reticle)
{
if(autocvar_cl_reticle_item_normal) { precache_pic("gfx/reticle_normal"); }
if(autocvar_cl_reticle_item_nex) { precache_pic("gfx/reticle_nex"); }
}
-
+
get_mi_min_max_texcoords(1); // try the CLEVER way first
minimapname = strcat("gfx/", mi_shortname, "_radar.tga");
shortmapname = mi_shortname;
spn_origin_x = ReadShort();
spn_origin_y = ReadShort();
spn_origin_z = ReadShort();
-
+
if(is_new)
{
self.origin = spn_origin;
}
}
else { self.cnt = particleeffectnum("spawn_point_neutral"); }
-
+
self.draw = Spawn_Draw;
}
}
// this way the server can disable the sending of
// spawn origin or such to clients if wanted.
float entnum = ReadByte();
-
+
if(entnum)
{
self.origin_x = ReadShort();
}
}
}
-
+
// local spawn actions
if(is_new && (!entnum || (entnum == player_localentnum)))
{
button_zoom = FALSE;
}
}
-
+
//print(sprintf("Ent_ReadSpawnEvent(is_new = %d); origin = %s, entnum = %d, localentnum = %d\n", is_new, vtos(self.origin), entnum, player_localentnum));
}
case ENT_CLIENT_GAUNTLET: Ent_ReadHook(bIsNewEntity, ENT_CLIENT_GAUNTLET); break;
case ENT_CLIENT_ACCURACY: Ent_ReadAccuracy(); break;
case ENT_CLIENT_AUXILIARYXHAIR: Net_AuXair2(bIsNewEntity); break;
- case ENT_CLIENT_TURRET: ent_turret(); break;
+ case ENT_CLIENT_TURRET: ent_turret(); break;
case ENT_CLIENT_MODEL: CSQCModel_Read(bIsNewEntity); break;
- case ENT_CLIENT_ITEM: ItemRead(bIsNewEntity); break;
+ case ENT_CLIENT_ITEM: ItemRead(bIsNewEntity); break;
case ENT_CLIENT_BUMBLE_RAYGUN: bumble_raygun_read(bIsNewEntity); break;
case ENT_CLIENT_SPAWNPOINT: Ent_ReadSpawnPoint(bIsNewEntity); break;
case ENT_CLIENT_SPAWNEVENT: Ent_ReadSpawnEvent(bIsNewEntity); break;
float autocvar_hud_panel_weapons_timeout_effect;
float autocvar_hud_panel_weapons_timeout_fadebgmin;
float autocvar_hud_panel_weapons_timeout_fadefgmin;
-var float autocvar_hud_panel_weapons_timeout_speed_in = 0.25;
+var float autocvar_hud_panel_weapons_timeout_speed_in = 0.25;
var float autocvar_hud_panel_weapons_timeout_speed_out = 0.75;
float autocvar_hud_progressbar_alpha;
float autocvar_hud_showbinds;
../warpzonelib/common.qh
../warpzonelib/client.qh
+../common/playerstats.qh
../common/teams.qh
../common/util.qh
../common/test.qh
../common/test.qc
../common/util.qc
+../common/playerstats.qc
../common/notifications.qc
../common/command/markup.qc
../common/command/rpn.qc
--- /dev/null
+#ifdef SVQC
+
+float playerstats_db;
+string teamstats_last;
+string playerstats_last;
+string events_last;
+.float playerstats_addedglobalinfo;
+.string playerstats_id;
+
+void PlayerStats_Init() // initiated before InitGameplayMode so that scores are added properly
+{
+ string uri;
+ playerstats_db = -1;
+ playerstats_waitforme = TRUE;
+ uri = autocvar_g_playerstats_uri;
+ if(uri == "")
+ return;
+ playerstats_db = db_create();
+ if(playerstats_db >= 0)
+ playerstats_waitforme = FALSE; // must wait for it at match end
+
+ serverflags |= SERVERFLAG_PLAYERSTATS;
+
+ PlayerStats_AddEvent(PLAYERSTATS_ALIVETIME);
+ PlayerStats_AddEvent(PLAYERSTATS_AVGLATENCY);
+ PlayerStats_AddEvent(PLAYERSTATS_WINS);
+ PlayerStats_AddEvent(PLAYERSTATS_MATCHES);
+ PlayerStats_AddEvent(PLAYERSTATS_JOINS);
+ PlayerStats_AddEvent(PLAYERSTATS_SCOREBOARD_VALID);
+ PlayerStats_AddEvent(PLAYERSTATS_SCOREBOARD_POS);
+ PlayerStats_AddEvent(PLAYERSTATS_RANK);
+
+ // accuracy stats
+ entity w;
+ float i;
+ for(i = WEP_FIRST; i <= WEP_LAST; ++i)
+ {
+ w = get_weaponinfo(i);
+
+ PlayerStats_AddEvent(strcat("acc-", w.netname, "-hit"));
+ PlayerStats_AddEvent(strcat("acc-", w.netname, "-fired"));
+
+ PlayerStats_AddEvent(strcat("acc-", w.netname, "-cnt-hit"));
+ PlayerStats_AddEvent(strcat("acc-", w.netname, "-cnt-fired"));
+
+ PlayerStats_AddEvent(strcat("acc-", w.netname, "-frags"));
+ }
+
+ PlayerStats_AddEvent(PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_3);
+ PlayerStats_AddEvent(PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_5);
+ PlayerStats_AddEvent(PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_10);
+ PlayerStats_AddEvent(PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_15);
+ PlayerStats_AddEvent(PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_20);
+ PlayerStats_AddEvent(PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_25);
+ PlayerStats_AddEvent(PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_30);
+ PlayerStats_AddEvent(PLAYERSTATS_ACHIEVEMENT_BOTLIKE);
+ PlayerStats_AddEvent(PLAYERSTATS_ACHIEVEMENT_FIRSTBLOOD);
+ PlayerStats_AddEvent(PLAYERSTATS_ACHIEVEMENT_FIRSTVICTIM);
+}
+
+void PlayerStats_AddPlayer(entity e)
+{
+ string s;
+
+ if(playerstats_db < 0)
+ return;
+ if(e.playerstats_id)
+ return;
+
+ 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);
+
+ string key;
+ key = sprintf("%s:*", e.playerstats_id);
+
+ string p;
+ p = db_get(playerstats_db, key);
+ if(p == "")
+ {
+ if(playerstats_last)
+ {
+ db_put(playerstats_db, key, playerstats_last);
+ strunzone(playerstats_last);
+ }
+ else
+ db_put(playerstats_db, key, "#");
+ playerstats_last = strzone(e.playerstats_id);
+ }
+}
+
+void PlayerStats_AddTeam(float t)
+{
+ if(playerstats_db < 0)
+ return;
+
+ string key;
+ key = sprintf("%d", t);
+
+ string p;
+ p = db_get(playerstats_db, key);
+ if(p == "")
+ {
+ if(teamstats_last)
+ {
+ db_put(playerstats_db, key, teamstats_last);
+ strunzone(teamstats_last);
+ }
+ else
+ db_put(playerstats_db, key, "#");
+ teamstats_last = strzone(key);
+ }
+}
+
+void PlayerStats_AddEvent(string event_id)
+{
+ if(playerstats_db < 0)
+ return;
+
+ string key;
+ key = sprintf("*:%s", event_id);
+
+ string p;
+ p = db_get(playerstats_db, key);
+ if(p == "")
+ {
+ if(events_last)
+ {
+ db_put(playerstats_db, key, events_last);
+ strunzone(events_last);
+ }
+ else
+ db_put(playerstats_db, key, "#");
+ events_last = strzone(event_id);
+ }
+}
+
+float PlayerStats_Event(entity e, string event_id, float value)
+{
+ if((e.playerstats_id == "") || playerstats_db < 0)
+ return 0;
+
+ string key;
+ float val;
+ key = sprintf("%s:%s", e.playerstats_id, event_id);
+ val = stof(db_get(playerstats_db, key));
+ val += value;
+ db_put(playerstats_db, key, ftos(val));
+ return val;
+}
+
+float PlayerStats_TeamScore(float t, string event_id, float value)
+{
+ if(playerstats_db < 0)
+ return 0;
+
+ string key;
+ float val;
+ key = sprintf("team#%d:%s", t, event_id);
+ val = stof(db_get(playerstats_db, key));
+ val += value;
+ db_put(playerstats_db, key, ftos(val));
+ return val;
+}
+
+/*
+ format spec:
+
+ A collection of lines of the format <key> SPACE <value> NEWLINE, where
+ <key> is always a single character.
+
+ The following keys are defined:
+
+ 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
+ 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!)
+ n: nickname of the player (optional)
+ t: team ID
+ i: player index
+ 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
+
+ Response format (not used yet): see https://gist.github.com/4284222
+*/
+
+void PlayerStats_ready(entity fh, entity pass, float status)
+{
+ string t, tn;
+ string p, pn;
+ string e, en;
+ string nn, tt;
+ string s;
+
+ switch(status)
+ {
+ case URL_READY_CANWRITE:
+ url_fputs(fh, "V 8\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)));
+ if(teamplay)
+ {
+ for(t = teamstats_last; (tn = db_get(playerstats_db, sprintf("%d", stof(t)))) != ""; t = tn)
+ {
+ url_fputs(fh, sprintf("Q team#%s\n", t));
+ for(e = events_last; (en = db_get(playerstats_db, sprintf("*:%s", e))) != ""; e = en)
+ {
+ float v;
+ v = stof(db_get(playerstats_db, sprintf("team#%d:%s", stof(t), e)));
+ if(v != 0)
+ url_fputs(fh, sprintf("e %s %g\n", e, v));
+ }
+ }
+ }
+ for(p = playerstats_last; (pn = db_get(playerstats_db, sprintf("%s:*", p))) != ""; p = pn)
+ {
+ url_fputs(fh, sprintf("P %s\n", p));
+ nn = db_get(playerstats_db, sprintf("%s:_playerid", p));
+ if(nn != "")
+ url_fputs(fh, sprintf("i %s\n", nn));
+ nn = db_get(playerstats_db, sprintf("%s:_netname", p));
+ if(nn != "")
+ url_fputs(fh, sprintf("n %s\n", nn));
+ if(teamplay)
+ {
+ tt = db_get(playerstats_db, sprintf("%s:_team", p));
+ url_fputs(fh, sprintf("t %s\n", tt));
+ }
+ for(e = events_last; (en = db_get(playerstats_db, sprintf("*:%s", e))) != ""; e = en)
+ {
+ float v;
+ v = stof(db_get(playerstats_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;
+ 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_waitforme = TRUE;
+ db_close(playerstats_db);
+ playerstats_db = -1;
+ break;
+ case URL_READY_ERROR:
+ default:
+ print("Player stats writing failed: ", ftos(status), "\n");
+ playerstats_waitforme = TRUE;
+ if(playerstats_db >= 0)
+ {
+ db_close(playerstats_db);
+ playerstats_db = -1;
+ }
+ break;
+ }
+}
+
+//#NO AUTOCVARS START
+void PlayerStats_Shutdown()
+{
+ string uri;
+
+ if(playerstats_db < 0)
+ return;
+
+ uri = autocvar_g_playerstats_uri;
+ if(uri != "")
+ {
+ playerstats_waitforme = FALSE;
+ url_multi_fopen(uri, FILE_APPEND, PlayerStats_ready, world);
+ }
+ else
+ {
+ playerstats_waitforme = TRUE;
+ db_close(playerstats_db);
+ playerstats_db = -1;
+ }
+}
+//#NO AUTOCVARS END
+
+void PlayerStats_Accuracy(entity p)
+{
+ entity a, w;
+ a = p.accuracy;
+ float i;
+
+ for(i = WEP_FIRST; i <= WEP_LAST; ++i)
+ {
+ w = get_weaponinfo(i);
+
+ PlayerStats_Event(p, strcat("acc-", w.netname, "-hit"), a.(accuracy_hit[i-1]));
+ PlayerStats_Event(p, strcat("acc-", w.netname, "-fired"), a.(accuracy_fired[i-1]));
+
+ PlayerStats_Event(p, strcat("acc-", w.netname, "-cnt-hit"), a.(accuracy_cnt_hit[i-1]));
+ PlayerStats_Event(p, strcat("acc-", w.netname, "-cnt-fired"), a.(accuracy_cnt_fired[i-1]));
+
+ PlayerStats_Event(p, strcat("acc-", w.netname, "-frags"), a.(accuracy_frags[i-1]));
+ }
+ //backtrace(strcat("adding player stat accuracy for ", p.netname, ".\n"));
+}
+
+void PlayerStats_AddGlobalInfo(entity p)
+{
+ if(playerstats_db < 0)
+ return;
+ if((p.playerstats_id == "") || playerstats_db < 0)
+ return;
+ p.playerstats_addedglobalinfo = TRUE;
+
+ // add global info!
+ if(p.alivetime)
+ {
+ PlayerStats_Event(p, PLAYERSTATS_ALIVETIME, time - p.alivetime);
+ p.alivetime = 0;
+ }
+
+ db_put(playerstats_db, sprintf("%s:_playerid", p.playerstats_id), ftos(p.playerid));
+
+ if(p.cvar_cl_allow_uid2name == 1 || IS_BOT_CLIENT(p))
+ db_put(playerstats_db, sprintf("%s:_netname", p.playerstats_id), p.netname);
+
+ if(teamplay)
+ db_put(playerstats_db, sprintf("%s:_team", p.playerstats_id), ftos(p.team));
+
+ if(stof(db_get(playerstats_db, sprintf("%d:%s", p.playerstats_id, PLAYERSTATS_ALIVETIME))) > 0)
+ PlayerStats_Event(p, PLAYERSTATS_JOINS, 1);
+
+ PlayerStats_Accuracy(p);
+
+ if(IS_REAL_CLIENT(p))
+ {
+ if(p.latency_cnt)
+ {
+ float latency = (p.latency_sum / p.latency_cnt);
+ if(latency) { PlayerStats_Event(p, PLAYERSTATS_AVGLATENCY, latency); }
+ }
+ }
+
+ strunzone(p.playerstats_id);
+ p.playerstats_id = string_null;
+}
+
+.float scoreboard_pos;
+void PlayerStats_EndMatch(float finished)
+{
+ entity p;
+ PlayerScore_Sort(score_dummyfield, 0, 0, 0);
+ PlayerScore_Sort(scoreboard_pos, 1, 1, 1);
+ if(teamplay)
+ PlayerScore_TeamStats();
+ FOR_EACH_CLIENT(p)
+ {
+ // add personal score rank
+ PlayerStats_Event(p, PLAYERSTATS_RANK, p.score_dummyfield);
+
+ if(!p.scoreboard_pos)
+ continue;
+
+ // scoreboard is valid!
+ PlayerStats_Event(p, PLAYERSTATS_SCOREBOARD_VALID, 1);
+
+ // add scoreboard position
+ PlayerStats_Event(p, PLAYERSTATS_SCOREBOARD_POS, p.scoreboard_pos);
+
+ // add scoreboard data
+ PlayerScore_PlayerStats(p);
+
+ // if the match ended normally, add winning info
+ if(finished)
+ {
+ PlayerStats_Event(p, PLAYERSTATS_WINS, p.winning);
+ PlayerStats_Event(p, PLAYERSTATS_MATCHES, 1);
+ }
+ }
+}
+
+#endif // SVQC
+
+
+
+
+//// WIP -zykure /////////////////////////////////////////////////////
+
+
+
+
+float playerinfo_db;
+string playerinfo_last;
+string playerinfo_events_last;
+.float playerid;
+
+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 = string_null, value = string_null, data = string_null;
+
+ 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);
+ }
+ else if (n == 4)
+ {
+ key = argv(0);
+ value = argv(1);
+ data = argv(2);
+ }
+ else
+ continue;
+
+ if (data == "")
+ continue;
+
+ if (key == "#")
+ // comment
+ continue;
+ else if (key == "V")
+ // version
+ PlayerInfo_AddItem(p, "_version", data);
+ else if (key == "R")
+ // watermark
+ PlayerInfo_AddItem(p, "_release", data);
+ else if (key == "T")
+ // timestamp
+ PlayerInfo_AddItem(p, "_time", data);
+ else if (key == "S")
+ // stats page URL
+ PlayerInfo_AddItem(p, "_statsurl", data);
+ else if (key == "P")
+ // player hashkey
+ PlayerInfo_AddItem(p, "_hashkey", data);
+ else if (key == "n")
+ // player nick
+ PlayerInfo_AddItem(p, "_playernick", data);
+ else if (key == "i")
+ // xonstats id
+ 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 = playerinfo_uri; // FIXME
+ 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 = 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_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 = playerinfo_uri; // FIXME
+ if(uri != "" && crypto_getmyidstatus(0) > 0)
+ {
+ entity p = spawn();
+ p.playerid = 0; // TODO: okay to use -1 for local player? or does local player already has an entity in MENUQC?
+ 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
+
+// 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
+
+void PlayerStats_Accuracy(entity p);
+
+// call this whenever a player leaves
+void PlayerStats_AddGlobalInfo(entity p);
+
+// call this at the end of the match
+void PlayerStats_EndMatch(float finished);
+
+#endif //SVQC
+
+
+
+
+//// WIP -zykure /////////////////////////////////////////////////////
+
+
+const string playerinfo_uri = "http://localhost:6543"; // FIXME
+
+string PlayerInfo_GetItem(entity e, string item_id);
+string PlayerInfo_GetItemLocal(string item_id);
+
+void PlayerInfo_Init();
+#ifdef SVQC
+void PlayerInfo_Basic(entity p);
+#endif
+#ifdef MENUQC
+void PlayerInfo_Details();
+#endif
+#ifdef CSQC
+//void PlayerInfo_Details();
+#endif
float dist_point_line(vector p, vector l0, vector ldir)
{
ldir = normalize(ldir);
-
+
// remove the component in line direction
p = p - (p * ldir) * ldir;
{
float fh, i, n;
fh = fopen(pFilename, FILE_WRITE);
- if(fh < 0)
+ if(fh < 0)
{
print(strcat("^1Can't write DB to ", pFilename));
return;
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;
valstr = TIME_ENCODED_TOSTRING(pValue);
else
valstr = ftos(pValue);
-
+
return valstr;
}
neworder = strcat(neworder, ftos(w), " ");
}
}
-
+
return substring(neworder, 0, strlen(neworder) - 1);
}
neworder = "";
for(i = 0; i < n; ++i)
neworder = strcat(neworder, mapfunc(argv(i)), " ");
-
+
return substring(neworder, 0, strlen(neworder) - 1);
}
}
return substring(s, 0, strlen(s) - 1);
}
-
+
return order;
}
hsv_y = 0;
else
hsv_y = 1 - mi/ma;
-
+
return hsv;
}
ma = max(rgb_x, rgb_y, rgb_z);
hsl_x = rgb_mi_ma_to_hue(rgb, mi, ma);
-
+
hsl_z = 0.5 * (mi + ma);
if(mi == ma)
hsl_y = 0;
hsl_y = (ma - mi) / (2*hsl_z);
else // if(hsl_z > 0.5)
hsl_y = (ma - mi) / (2 - 2*hsl_z);
-
+
return hsl;
}
maminusmi = hsl_y * 2 * hsl_z;
else
maminusmi = hsl_y * (2 - 2 * hsl_z);
-
+
// hsl_z = 0.5 * mi + 0.5 * ma
// maminusmi = - mi + ma
mi = hsl_z - 0.5 * maminusmi;
// terminate, as the range still halves each time - but nevertheless, it is
// guaranteed that it finds ONE valid cutoff place (where "left" is in
// range, and "right" is outside).
-
+
// terencehill: the following code detects truncated ^xrgb tags (e.g. ^x or ^x4)
// and decrease left on the basis of the chars detected of the truncated tag
// Even if the ^xrgb tag is not complete/correct, left is decreased
}
}
}
-
+
return left;
}
// terminate, as the range still halves each time - but nevertheless, it is
// guaranteed that it finds ONE valid cutoff place (where "left" is in
// range, and "right" is outside).
-
+
// terencehill: the following code detects truncated ^xrgb tags (e.g. ^x or ^x4)
// and decrease left on the basis of the chars detected of the truncated tag
// Even if the ^xrgb tag is not complete/correct, left is decreased
}
}
}
-
+
return left;
}
string s;
s = getWrappedLine_remaining;
-
+
if(w <= 0)
{
getWrappedLine_remaining = string_null;
string s;
s = getWrappedLine_remaining;
-
+
if(w <= 0)
{
getWrappedLine_remaining = string_null;
case "true":
case "on":
return TRUE;
-
+
case "no":
case "false":
case "off":
return FALSE;
-
+
default: return stof(input);
}
}
/*
// if this is the case, the possible zeros of the first derivative are outside
// 0..1
- We can calculate this condition as condition
+ We can calculate this condition as condition
if(se <= 3)
return TRUE;
*/
string CCR(string input)
{
// See the autocvar declarations in util.qh for default values
-
+
// foreground/normal colors
- input = strreplace("^F1", strcat("^", autocvar_hud_colorset_foreground_1), input);
- input = strreplace("^F2", strcat("^", autocvar_hud_colorset_foreground_2), input);
- input = strreplace("^F3", strcat("^", autocvar_hud_colorset_foreground_3), input);
- input = strreplace("^F4", strcat("^", autocvar_hud_colorset_foreground_4), input);
+ input = strreplace("^F1", strcat("^", autocvar_hud_colorset_foreground_1), input);
+ input = strreplace("^F2", strcat("^", autocvar_hud_colorset_foreground_2), input);
+ input = strreplace("^F3", strcat("^", autocvar_hud_colorset_foreground_3), input);
+ input = strreplace("^F4", strcat("^", autocvar_hud_colorset_foreground_4), input);
// "kill" colors
input = strreplace("^K1", strcat("^", autocvar_hud_colorset_kill_1), input);
// modulo function
#ifndef MENUQC
-float mod(float a, float b) { return a - (floor(a / b) * b); }
+float mod(float a, float b) { return a - (floor(a / b) * b); }
#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);
#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_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_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_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/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/colorpicker.c"
#include "xonotic/colorpicker_string.c"
#include "xonotic/cvarlist.c"
#include "xonotic/dialog_hudpanel_physics.c"
#include "xonotic/dialog_hudpanel_centerprint.c"
#include "xonotic/slider_picmip.c"
+#include "xonotic/dialog_settings_game_notification.c"
+#include "xonotic/dialog_multiplayer_media_demo_democonfirm.c"
+#include "xonotic/slider_particles.c"
return;
}
+ if(argv(0) == "debugstats")
+ {
+ PlayerInfo_Init();
+ PlayerInfo_Details();
+ return;
+ }
+
print(_("Invalid command. For a list of supported commands, try menu_cmd help.\n"));
}
}
void draw_Text(vector theOrigin, string theText, vector theSize, vector theColor, float theAlpha, float ICanHasKallerz)
{
- if(theSize_x <= 0 || theSize_y <= 0)
- error("Drawing zero size text?\n");
+ if(theSize_x <= 0 || theSize_y <= 0) {
+ dprint("Drawing zero size text?\n");
+ return;
+ }
//float wi;
//wi = draw_TextWidth(theText, ICanHasKallerz, theSize);
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);
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)
{
float menuMouseMode;
float conwidth_s, conheight_s, vidwidth_s, vidheight_s, vidpixelheight_s,
- realconwidth, realconheight, screenconwidth, screenconheight;
+ realconwidth, realconheight;
void m_sync()
{
m_hide();
cvar_set("_menu_initialized", "1");
}
+
+ PlayerInfo_Details();
}
const float MENU_ASPECT = 1.25; // 1280x1024
-const float MENU_MINHEIGHT = 600;
void draw_reset_cropped()
{
- draw_reset(screenconwidth, screenconheight, 0.5 * (realconwidth - screenconwidth), 0.5 * (realconheight - screenconheight));
+ draw_reset(conwidth, conheight, 0.5 * (realconwidth - conwidth), 0.5 * (realconheight - conheight));
}
void draw_reset_full()
{
conwidth = realconwidth;
conheight = realconwidth / MENU_ASPECT;
}
- screenconwidth = conwidth;
- screenconheight = conheight;
- if(conwidth < MENU_MINHEIGHT * MENU_ASPECT)
- {
- conheight *= MENU_MINHEIGHT * MENU_ASPECT / conwidth;
- conwidth = MENU_MINHEIGHT * MENU_ASPECT;
- }
- if(conheight < MENU_MINHEIGHT)
- {
- conwidth *= MENU_MINHEIGHT / conheight;
- conheight = MENU_MINHEIGHT;
- }
if(main)
{
if(conwidth_s != conwidth || conheight_s != conheight)
v = pos + avoidplus;
if(m_testtooltipbox(v))
return TRUE;
-
+
// bottom center
v_x = pos_x - menuTooltipSize_x * 0.5;
if(m_testtooltipbox(v))
v_x = pos_x - menuTooltipSize_x * 0.5;
if(m_testtooltipbox(v))
return TRUE;
-
+
// top right
v_x = pos_x + avoidplus_x;
if(m_testtooltipbox(v))
return TRUE;
-
+
return FALSE;
}
entity m_findtooltipitem(entity root, vector pos)
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
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, gameTypeChangeNotify, void(entity))
ATTRIB(XonoticServerCreateTab, title, string, _("Create"))
ATTRIB(XonoticServerCreateTab, intendedWidth, float, 0.9)
- ATTRIB(XonoticServerCreateTab, rows, float, 22)
+ ATTRIB(XonoticServerCreateTab, rows, float, 23)
ATTRIB(XonoticServerCreateTab, columns, float, 6.2) // added extra .2 for center space
ATTRIB(XonoticServerCreateTab, mapListBox, entity, NULL)
{
entity e, e0;
+ me.TR(me);
me.TR(me);
me.TD(me, 1, 3, e = makeXonoticTextLabel(0, _("Game type:")));
me.TR(me);
e.onClickEntity = main.advancedDialog;
main.advancedDialog.refilterEntity = me.mapListBox;
- me.gotoRC(me, 0, 3.2); me.setFirstColumn(me, me.currentColumn);
+ me.gotoRC(me, 1, 3.2); me.setFirstColumn(me, me.currentColumn);
me.mapListBox = makeXonoticMapList();
me.TD(me, 1, 3, e = makeXonoticTextLabel(0, _("Map list:")));
makeCallback(e, me.mapListBox, me.mapListBox.refilterCallback);
me.TR(me);
- me.TD(me, me.rows - 4, 3, me.mapListBox);
+ me.TD(me, me.rows - 5, 3, me.mapListBox);
me.gotoRC(me, me.rows - 3, 3.5);
me.TDempty(me, 0.25);
me.TD(me, 1, 1.125, e = makeXonoticButton(_("Select all"), '0 0 0'));
+++ /dev/null
-#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")
+ENDCLASS(XonoticDemoBrowserTab)
+entity makeXonoticDemoBrowserTab();
+void Demo_Confirm(entity me, entity btn);
+#endif
+
+#ifdef IMPLEMENTATION
+void DemoConfirm_Check_Gamestatus(entity me, entity btn)
+{
+ if not(gamestatus & (GAME_CONNECTED | GAME_ISSERVER)) // we're not in a match, lets watch the demo
+ {
+ //TimeDemo_Click;
+ //StartDemo_Click;
+ return;
+ }
+ else // already in a match, player has to confirm
+ {
+ Demo_Confirm(me, btn);
+ }
+}
+
+entity makeXonoticDemoBrowserTab()
+{
+ entity me;
+ me = spawnXonoticDemoBrowserTab();
+ me.configureDialog(me);
+ return me;
+}
+void XonoticDemoBrowserTab_fill(entity me)
+{
+ entity e, dlist;
+
+ me.TR(me);
+ me.TD(me, 1, 4, e = makeXonoticCheckBox(0, "cl_autodemo", _("Automatically record demos while playing")));
+ me.TR(me);
+ me.TR(me);
+ me.TD(me, 1, 0.5, e = makeXonoticTextLabel(0, _("Filter:")));
+ me.TD(me, 1, 6, e = makeXonoticInputBox(0, string_null));
+ dlist = makeXonoticDemoList();
+ e.onChange = DemoList_Filter_Change;
+ e.onChangeEntity = dlist;
+ dlist.controlledTextbox = e;
+
+ me.TR(me);
+ me.TD(me, me.rows - 4, me.columns, dlist);
+
+ me.gotoRC(me, me.rows - 1, 0);
+ me.TD(me, 1, me.columns / 2, e = makeXonoticButton(_("Timedemo"), '0 0 0'));
+ e.onClick = DemoConfirm_Check_Gamestatus;
+ e.onClickEntity = dlist;
+ me.TD(me, 1, me.columns / 2, e = makeXonoticButton(ZCTX(_("DEMO^Play")), '0 0 0'));
+ e.onClick = DemoConfirm_Check_Gamestatus;
+ e.onClickEntity = dlist;
+}
+#endif
--- /dev/null
+#ifdef INTERFACE
+CLASS(XonoticDemoConfirmDialog) EXTENDS(XonoticDialog)
+ METHOD(XonoticDemoConfirmDialog, fill, void(entity))
+ ATTRIB(XonoticDemoConfirmDialog, title, string, _("Disconnect"))
+ ATTRIB(XonoticDemoConfirmDialog, color, vector, SKINCOLOR_DIALOG_HUDCONFIRM)
+ ATTRIB(XonoticDemoConfirmDialog, intendedWidth, float, 0.5)
+ ATTRIB(XonoticDemoConfirmDialog, rows, float, 4)
+ ATTRIB(XonoticDemoConfirmDialog, columns, float, 2)
+ENDCLASS(XonoticDemoConfirmDialog)
+#endif
+
+#ifdef IMPLEMENTATION
+void Demo_Confirm(entity me, entity btn)
+{
+ if not(gamestatus & (GAME_CONNECTED | GAME_ISSERVER))
+ //me.onClick = TimeDemo_Click;
+ me.onClick = StartDemo_Click;
+ else
+ localcmd("togglemenu 0\n");
+}
+
+void XonoticDemoConfirmDialog_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 = Demo_Confirm;
+ e.onClickEntity = me;
+ 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.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.TR(me);
+ me.TD(me, slist_height, 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 not(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
\ No newline at end of file
+++ /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 not(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.2) // added extra .2 for center space
+ ATTRIB(XonoticProfileTab, playerNameLabel, entity, NULL)
+ ATTRIB(XonoticProfileTab, playerNameLabelAlpha, float, 0)
+ENDCLASS(XonoticProfileTab)
+entity makeXonoticProfileTab();
+#endif
+
+#ifdef IMPLEMENTATION
+entity makeXonoticProfileTab()
+{
+ entity me;
+ me = spawnXonoticProfileTab();
+ me.configureDialog(me);
+ return me;
+}
+void XonoticProfileTab_draw(entity me)
+{
+ if(cvar_string("_cl_name") == "Player")
+ me.playerNameLabel.alpha = ((mod(time * 2, 2) < 1) ? 1 : 0);
+ else
+ me.playerNameLabel.alpha = me.playerNameLabelAlpha;
+ SUPER(XonoticProfileTab).draw(me);
+}
+void XonoticProfileTab_fill(entity me)
+{
+ entity e, pms, label, box;
+ float i;
+
+ me.TR(me);
+ me.TR(me);
+ me.TD(me, 1, 0.5, me.playerNameLabel = makeXonoticTextLabel(0, _("Name:")));
+ me.playerNameLabelAlpha = me.playerNameLabel.alpha;
+ me.TD(me, 1, 2.5, label = makeXonoticTextLabel(0, string_null));
+ label.allowCut = 1;
+ label.allowColors = 1;
+ label.alpha = 1;
+ me.TR(me);
+ me.TD(me, 1, 3.0, box = makeXonoticInputBox(1, "_cl_name"));
+ box.forbiddenCharacters = "\r\n\\\"$"; // don't care, isn't getting saved
+ box.maxLength = -127; // negative means encoded length in bytes
+ box.saveImmediately = 1;
+ box.enableClearButton = 0;
+ label.textEntity = box;
+ me.TR(me);
+ me.TD(me, 5, 1, e = makeXonoticColorpicker(box));
+ me.TD(me, 5, 2, e = makeXonoticCharmap(box));
+ me.TR(me);
+ me.TR(me);
+ me.TR(me);
+ me.TR(me);
+ me.TR(me);
+
+ // Statistic Stuff -Debugger
+ me.TR(me);
+ me.TDempty(me, 0.5);
+ me.TD(me, 1, 2, e = makeXonoticTextLabel(0.5, _("Player Statistics:")));
+ me.TR(me);
+ me.TR(me);
+ me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Join time:")));
+ me.TR(me);
+ me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Total playing time:")));
+ me.TR(me);
+ me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Last played:")));
+ me.TR(me);
+ me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Games played:")));
+ me.TR(me);
+ me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Win / Losses:")));
+ me.TR(me);
+ me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Kills / Deaths:")));
+ me.TR(me);
+ me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("CTF elo:")));
+ me.TR(me);
+ me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("DM elo:")));
+ me.TR(me);
+ me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("TDM elo:")));
+ me.TR(me);
+ me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("DUEL elo:")));
+ me.TR(me);
+
+
+ me.gotoRC(me, 1, 3.2); me.setFirstColumn(me, me.currentColumn);
+ me.TDempty(me, 1);
+ me.TD(me, 1, 3, e = makeXonoticTextLabel(0.5, _("Model:")));
+ me.TR(me);
+ pms = makeXonoticPlayerModelSelector();
+ me.TD(me, 1, 0.3, e = makeXonoticButton("<<", '0 0 0'));
+ e.onClick = PlayerModelSelector_Prev_Click;
+ e.onClickEntity = pms;
+ me.TD(me, 13, 2.4, pms);
+ me.TD(me, 1, 0.3, e = makeXonoticButton(">>", '0 0 0'));
+ e.onClick = PlayerModelSelector_Next_Click;
+ e.onClickEntity = pms;
+
+ me.gotoRC(me, 15, 3.533); me.setFirstColumn(me, me.currentColumn);
+ me.TR(me);
+ me.TD(me, 1, 1, e = makeXonoticTextLabel(0.5, _("Glowing color:")));
+ for(i = 0; i < 15; ++i)
+ {
+ if(mod(i, 5) == 0)
+ me.TR(me);
+ me.TDNoMargin(me, 1, 0.2, e = makeXonoticColorButton(1, 0, i), '0 1 0');
+ }
+ me.gotoRC(me, 15, 4.866); me.setFirstColumn(me, me.currentColumn);
+ me.TR(me);
+ me.TD(me, 1, 1, e = makeXonoticTextLabel(0.5, _("Detail color:")));
+ for(i = 0; i < 15; ++i)
+ {
+ if(mod(i, 5) == 0)
+ me.TR(me);
+ me.TDNoMargin(me, 1, 0.2, e = makeXonoticColorButton(2, 1, i), '0 1 0');
+ }
+
+ /*
+ // crosshair_enabled: 0 = no crosshair options, 1 = no crosshair selection, but everything else enabled, 2 = all crosshair options enabled
+ // FIXME: In the future, perhaps make one global crosshair_type cvar which has 0 for disabled, 1 for custom, 2 for per weapon, etc?
+ me.gotoRC(me, 0, 3.2); me.setFirstColumn(me, me.currentColumn);
+ me.TD(me, 1, 3, e = makeXonoticRadioButton(3, "crosshair_enabled", "0", _("No crosshair")));
+ me.TR(me);
+ me.TD(me, 1, 3, e = makeXonoticRadioButton(3, "crosshair_per_weapon", string_null, _("Per weapon crosshair")));
+ makeMulti(e, "crosshair_enabled");
+ me.TR(me);
+ me.TD(me, 1, 3, e = makeXonoticRadioButton(3, "crosshair_enabled", "2", _("Custom crosshair")));
+ me.TR(me);
+ me.TDempty(me, 0.1);
+ for(i = 1; i <= 14; ++i) {
+ me.TDNoMargin(me, 1, 2 / 14, e = makeXonoticCrosshairButton(4, i), '1 1 0');
+ setDependentAND(e, "crosshair_per_weapon", 0, 0, "crosshair_enabled", 1, 2);
+ }
+ // show a larger preview of the selected crosshair
+ me.TDempty(me, 0.1);
+ me.TDNoMargin(me, 3, 0.8, e = makeXonoticCrosshairButton(7, -1), '1 1 0'); // crosshair -1 makes this a preview
+ setDependentAND(e, "crosshair_per_weapon", 0, 0, "crosshair_enabled", 1, 2);
+ me.TR(me);
+ me.TDempty(me, 0.1);
+ for(i = 15; i <= 28; ++i) {
+ me.TDNoMargin(me, 1, 2 / 14, e = makeXonoticCrosshairButton(4, i), '1 1 0');
+ setDependentAND(e, "crosshair_per_weapon", 0, 0, "crosshair_enabled", 1, 2);
+ }
+ me.TR(me);
+ me.TR(me);
+ me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Crosshair size:")));
+ setDependent(e, "crosshair_enabled", 1, 2);
+ me.TD(me, 1, 2, e = makeXonoticSlider(0.1, 1.0, 0.01, "crosshair_size"));
+ setDependent(e, "crosshair_enabled", 1, 2);
+ me.TR(me);
+ me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Crosshair alpha:")));
+ setDependent(e, "crosshair_enabled", 1, 2);
+ me.TD(me, 1, 2, e = makeXonoticSlider(0, 1, 0.1, "crosshair_alpha"));
+ setDependent(e, "crosshair_enabled", 1, 2);
+ me.TR(me);
+ me.TR(me);
+ me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Crosshair color:")));
+ setDependent(e, "crosshair_enabled", 1, 2);
+ me.TD(me, 1, 1, e = makeXonoticRadioButton(5, "crosshair_color_special", "1", _("Per weapon")));
+ setDependent(e, "crosshair_enabled", 1, 2);
+ me.TD(me, 1, 1, e = makeXonoticRadioButton(5, "crosshair_color_special", "2", _("By health")));
+ setDependent(e, "crosshair_enabled", 1, 2);
+ me.TR(me);
+ me.TDempty(me, 0.1);
+ me.TD(me, 1, 0.9, e = makeXonoticRadioButton(5, "crosshair_color_special", "0", _("Custom")));
+ setDependent(e, "crosshair_enabled", 1, 2);
+ me.TD(me, 2, 2, e = makeXonoticColorpickerString("crosshair_color", "crosshair_color"));
+ setDependentAND(e, "crosshair_color_special", 0, 0, "crosshair_enabled", 1, 2);
+ me.TR(me);
+ me.TR(me);
+ me.TR(me);
+ me.TDempty(me, 0.5);
+ me.TD(me, 1, 2, e = makeXonoticButton(_("Other crosshair settings"), '0 0 0'));
+ e.onClick = DialogOpenButton_Click;
+ e.onClickEntity = main.crosshairDialog;
+ setDependent(e, "crosshair_enabled", 1, 2);
+ // TODO: show status of crosshair dot and hittest and pickups and such here with text
+ me.TR(me);
+ me.TR(me);
+ me.TDempty(me, 0.5);
+ me.TD(me, 1, 2, e = makeXonoticButton(_("Model settings"), '0 0 0'));
+ e.onClick = DialogOpenButton_Click;
+ e.onClickEntity = main.modelDialog;
+ // TODO: show csqc model settings like forcemyplayer and deglowing/ghosting bodies with text here
+ me.TR(me);
+ me.TDempty(me, 0.5);
+ me.TD(me, 1, 2, e = makeXonoticButton(_("View settings"), '0 0 0'));
+ e.onClick = DialogOpenButton_Click;
+ e.onClickEntity = main.viewDialog;
+ // TODO: show fov and other settings with text here
+ me.TR(me);
+ me.TDempty(me, 0.5);
+ me.TD(me, 1, 2, e = makeXonoticButton(_("Weapon settings"), '0 0 0'));
+ e.onClick = DialogOpenButton_Click;
+ e.onClickEntity = main.weaponsDialog;
+ // I don't really think this is useful as is, and especially it doesn't look very clean...
+ // In the future, if ALL of these buttons had some information, then it would be justified/clean
+ //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
void XonoticSettingsDialog_fill(entity me)
{
entity mc;
- mc = makeXonoticTabController(me.rows - 2);
+ mc = makeXonoticTabController(me.rows - 3);
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.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.TR(me);
- me.TD(me, me.rows - 2, me.columns, mc);
+ me.TR(me);
+ me.TD(me, me.rows - 3, 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, 16)
ATTRIB(XonoticAudioSettingsTab, columns, float, 6.2) // added extra .2 for center space
ENDCLASS(XonoticAudioSettingsTab)
entity makeXonoticAudioSettingsTab();
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, 16)
ATTRIB(XonoticEffectsSettingsTab, columns, float, 6.2) // added extra .2 for center space
ENDCLASS(XonoticEffectsSettingsTab)
entity makeXonoticEffectsSettingsTab();
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.TD(me, 1, 3, e = makeXonoticRadioButton(1, "r_coronas", "0", _("No dynamic lighting")));
me.TD(me, 1, 2, s);
me.TR(me);
me.TR(me);
- me.TD(me, 1, 1, e = makeXonoticCheckBox(0, "cl_decals", _("Decals")));
- me.TD(me, 1, 2, e = makeXonoticCheckBox(0, "cl_decals_models", _("Decals on models")));
- setDependent(e, "cl_decals", 1, 1);
- me.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.TD(me, 1, 1, e = makeXonoticCheckBox(0, "cl_particles", _("Particles")));
+ me.TD(me, 1, 2, e = makeXonoticCheckBox(0, "cl_spawn_point_particles", _("Spawnpoint effects")));
+ makeMulti(e, "cl_spawn_event_particles");
+ setDependent(e, "cl_particles", 1, 1);
me.TR(me);
me.TDempty(me, 0.2);
- me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Time:")));
- setDependent(e, "cl_decals", 1, 1);
- me.TD(me, 1, 2, e = makeXonoticSlider(1, 20, 1, "cl_decals_time"));
- setDependent(e, "cl_decals", 1, 1);
-
+ me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Quality:")));
+ setDependent(e, "cl_particles", 1, 1);
+ me.TD(me, 1, 2, e = makeXonoticParticlesSlider());
+ setDependent(e, "cl_particles", 1, 1);
+
me.gotoRC(me, me.rows - 1, 0);
me.TD(me, 1, me.columns, makeXonoticCommandButton(_("Apply immediately"), '0 0 0', "vid_restart", COMMANDBUTTON_APPLY));
}
--- /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, 16)
+ ATTRIB(XonoticGameSettingsTab, columns, float, 6)
+ENDCLASS(XonoticGameSettingsTab)
+entity makeXonoticGameSettingsTab();
+#endif
+
+#ifdef IMPLEMENTATION
+entity makeXonoticGameSettingsTab()
+{
+ entity me;
+ me = spawnXonoticGameSettingsTab();
+ me.configureDialog(me);
+ return me;
+}
+
+void XonoticGameSettingsTab_fill(entity me)
+{
+ entity e;
+
+
+ me.TR(me);
+ me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "cl_gentle", _("Disable gore effects and harsh language"))); // also set sv_gentle
+
+ me.gotoRC(me, 2, 3); me.setFirstColumn(me, me.currentColumn);
+ me.TDempty(me, 0.5);
+ me.TD(me, 1, 2, e = makeXonoticButton(_("Crosshair"), '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.TDempty(me, 0.5);
+ me.TD(me, 1, 2, e = makeXonoticButton(_("HUD"), '0 0 0'));
+ e.onClick = DialogOpenButton_Click;
+ e.onClickEntity = main.hudDialog;
+ // TODO: show hud config name with text here
+ me.TR(me);
+ me.TDempty(me, 0.5);
+ me.TD(me, 1, 2, e = makeXonoticButton(_("Notification"), '0 0 0'));
+ e.onClick = DialogOpenButton_Click;
+ e.onClickEntity = main.notificationDialog;
+ // TODO: Show all the notification stuff here
+ me.TR(me);
+ me.TDempty(me, 0.5);
+ me.TD(me, 1, 2, e = makeXonoticButton(_("Playermodel"), '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"), '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"), '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.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));
+
+
+
+ me.gotoRC(me, me.rows - 1, 0);
+ me.TD(me, 1, me.columns, makeXonoticCommandButton(_("Apply immediately"), '0 0 0', "sendcvar cl_gentle; sendcvar cl_allow_uidtracking; sendcvar cl_allow_uid2name;", 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 not(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
\ No newline at end of file
--- /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 not(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(XonoticNotificationDialog) EXTENDS(XonoticDialog)
+ METHOD(XonoticNotificationDialog, toString, string(entity))
+ METHOD(XonoticNotificationDialog, fill, void(entity))
+ METHOD(XonoticNotificationDialog, showNotify, void(entity))
+ ATTRIB(XonoticNotificationDialog, title, string, _("Notification settings"))
+ ATTRIB(XonoticNotificationDialog, color, vector, SKINCOLOR_DIALOG_MODEL)
+ ATTRIB(XonoticNotificationDialog, intendedWidth, float, 0.6)
+ ATTRIB(XonoticNotificationDialog, rows, float, 19)
+ ATTRIB(XonoticNotificationDialog, columns, float, 3)
+ENDCLASS(XonoticNotificationDialog)
+#endif
+
+#ifdef IMPLEMENTATION
+void XonoticNotificationDialog_showNotify(entity me)
+{
+ loadAllCvars(me);
+}
+string XonoticNotificationDialog_toString(entity me)
+{
+ return "hi"; // TODO: show csqc model settings like forcemyplayer and deglowing/ghosting bodies with text here
+}
+void XonoticNotificationDialog_fill(entity me)
+{
+ entity e;
+
+ // General settings for the player
+ me.TR(me);
+ me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("General Settings:")));
+
+ me.TR(me);
+ me.TDempty(me, 0.1);
+ me.TD(me, 1, 2, e = makeXonoticCheckBox(0, "notification_allow_chatboxprint", _("Print all notifications into the chatbox")));
+ me.TR(me);
+ me.TDempty(me, 0.1);
+ me.TD(me, 1, 2, e = makeXonoticTextLabel(0, _("Notice connecting players:")));
+ me.TR(me);
+ me.TDempty(me, 0.3);
+ me.TD(me, 1, 3, e = makeXonoticTextSlider("notification_INFO_QUIT_DISCONNECT"));
+ //makeMulti(me, "notification_INFO_QUIT_KICK_IDLING notification_INFO_QUIT_KICK_SPECTATING notification_INFO_JOIN_PLAY notification_INFO_JOIN_CONNECT_TEAM_BLUE notification_INFO_JOIN_CONNECT_TEAM_PINK notification_INFO_JOIN_CONNECT_TEAM_RED notification_INFO_JOIN_CONNECT_TEAM_YELLOW");
+ e.addValue(e, ZCTX(_("off")), "0");
+ e.addValue(e, ZCTX(_("only console")), "1");
+ e.addValue(e, ZCTX(_("console & chat")), "2");
+ e.configureXonoticTextSliderValues(e);
+ me.TR(me);
+ me.TDempty(me, 0.1);
+ me.TD(me, 1, 2, e = makeXonoticCheckBox(0, "notification_ITEM_WEAPON_DONTHAVE", _("Item notifications")));
+ me.TR(me);
+ me.TDempty(me, 0.1);
+ me.TD(me, 1, 2, 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");
+ me.TR(me);
+ me.TDempty(me, 0.1);
+ me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "notification_frag_verbose", _("Additional information on frags")));
+ me.TR(me);
+ me.TR(me);
+
+ // Gamemode specific notifications
+ me.TD(me, 1, 2, e = makeXonoticTextLabel(0, _("Gamemode notifications:")));
+ me.TR(me);
+ me.TDempty(me, 0.1);
+ me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "notification_CENTER_ARENA_BEGIN", _("Centerprint for gamemode notifications")));
+ //makeMulti(me, "notification_CENTER_ARENA_NEEDPLAYER notification_CENTER_ARENA_ROUNDSTART notification_CENTER_ASSAULT_ATTACKING notification_CENTER_ASSAULT_DEFENDING notification_CENTER_CTF_PICKUP_BLUE notification_CENTER_CTF_PICKUP_ENEMY notification_CENTER_CTF_PICKUP_RED notification_CENTER_CTF_PICKUP_TEAM notification_CENTER_FREEZETAG_FREEZE notification_CENTER_FREEZETAG_FROZEN notification_CENTER_FREEZETAG_REVIVE notification_CENTER_FREEZETAG_REVIVED notification_CENTER_FREEZETAG_ROUND_WIN_BLUE notification_CENTER_FREEZETAG_ROUND_WIN_PINK notification_CENTER_FREEZETAG_ROUND_WIN_RED notification_CENTER_FREEZETAG_ROUND_WIN_YELLOW notification_CENTER_FREEZETAG_SELF notification_CENTER_FREEZETAG_SPAWN_LATE notification_CENTER_KEEPAWAY_DROPPED notification_CENTER_KEEPAWAY_PICKUP notification_CENTER_KEEPAWAY_WARN notification_CENTER_KEYHUNT_HELP notification_CENTER_KEYHUNT_INTERFERE_BLUE notification_CENTER_KEYHUNT_INTERFERE_PINK notification_CENTER_KEYHUNT_INTERFERE_RED notification_CENTER_KEYHUNT_INTERFERE_YELLOW notification_CENTER_KEYHUNT_MEET notification_CENTER_KEYHUNT_SCAN notification_CENTER_KEYHUNT_START_BLUE notification_CENTER_KEYHUNT_START_PINK notification_CENTER_KEYHUNT_START_RED notification_CENTER_KEYHUNT_START_YELLOW notification_CENTER_KEYHUNT_WAIT notification_CENTER_LMS_CAMPCHECK");
+ me.TR(me);
+ me.TDempty(me, 0.1);
+ me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "notification_ctf_capture_verbose", _("Additional information on flag captures")));
+ me.TR(me);
+
+ // Information on killingsprees
+ me.TR(me);
+ me.TD(me, 1, 2, e = makeXonoticTextLabel(0, _("Information on killingsprees:")));
+ me.TR(me);
+ me.TDempty(me, 0.1);
+ me.TD(me, 1, 2, e = makeXonoticCheckBox(0, "notification_show_sprees", _("Print information on sprees")));
+ me.TR(me);
+ me.TDempty(me, 0.1);
+ me.TD(me, 1, 2, e = makeXonoticTextLabel(0, _("Show spree information:")));
+ me.TR(me);
+ me.TDempty(me, 0.3);
+ me.TD(me, 1, 3, e = makeXonoticTextSlider("notification_show_sprees_info"));
+ e.addValue(e, ZCTX(_("off")), "0");
+ e.addValue(e, ZCTX(_("target")), "1");
+ e.addValue(e, ZCTX(_("attacker")), "2");
+ e.addValue(e, ZCTX(_("target & attacker")), "3");
+ e.configureXonoticTextSliderValues(e);
+ me.TR(me);
+ me.TDempty(me, 0.1);
+ me.TD(me, 1, 2, e = makeXonoticCheckBox(0, "notification_show_sprees_info_newline", _("Print spree information in a new line")));
+
+ // Close this dialog
+ 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
\ No newline at end of file
--- /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
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, 16)
ATTRIB(XonoticInputSettingsTab, columns, float, 6.2) // added extra .2 for center space
ENDCLASS(XonoticInputSettingsTab)
entity makeXonoticInputSettingsTab();
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, 16)
ATTRIB(XonoticMiscSettingsTab, columns, float, 6.2)
ENDCLASS(XonoticMiscSettingsTab)
entity makeXonoticMiscSettingsTab();
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.TR(me);
me.TR(me);
me.TDempty(me, 0.2);
METHOD(XonoticUserSettingsTab, fill, void(entity))
ATTRIB(XonoticUserSettingsTab, title, string, _("User"))
ATTRIB(XonoticUserSettingsTab, intendedWidth, float, 0.9)
- ATTRIB(XonoticUserSettingsTab, rows, float, 17)
+ ATTRIB(XonoticUserSettingsTab, rows, float, 16)
ATTRIB(XonoticUserSettingsTab, columns, float, 5)
ENDCLASS(XonoticUserSettingsTab)
entity makeXonoticUserSettingsTab();
me.TD(me, 1, 2.8, e = makeXonoticCheckBox(0, "cl_allow_uid2name", _("Allow player statistics to use your nickname")));
setDependent(e, "cl_allow_uidtracking", 1, 1);
- me.gotoRC(me, me.rows - 3, 2.6);
+ me.gotoRC(me, me.rows - 2, 2.6);
me.TD(me, 1, 2, makeXonoticCommandButton(_("Apply immediately"), '0 0 0', "sendcvar cl_gentle; sendcvar cl_allow_uidtracking; sendcvar cl_allow_uid2name;", COMMANDBUTTON_APPLY));
}
METHOD(XonoticVideoSettingsTab, fill, void(entity))
ATTRIB(XonoticVideoSettingsTab, title, string, _("Video"))
ATTRIB(XonoticVideoSettingsTab, intendedWidth, float, 0.9)
- ATTRIB(XonoticVideoSettingsTab, rows, float, 17)
+ ATTRIB(XonoticVideoSettingsTab, rows, float, 16)
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);
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, mainNexposee, entity, NULL)
ATTRIB(MainWindow, fadedAlpha, float, SKINALPHA_BEHIND)
ATTRIB(MainWindow, dialogToShow, entity, NULL)
+ ATTRIB(MainWindow, notificationDialog, entity, NULL)
+ ATTRIB(MainWindow, democonfirmDialog, entity, NULL)
ENDCLASS(MainWindow)
#endif
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.democonfirmDialog = i = spawnXonoticDemoConfirmDialog();
+ i.configureDialog(i);
+ me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
+
// dialogs used by multiplayer/create
me.mapInfoDialog = i = spawnXonoticMapInfoDialog();
i.configureDialog(i);
me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
+ me.notificationDialog = i = spawnXonoticNotificationDialog();
+ i.configureDialog(i);
+ me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
// mutator dialogs
i = spawnXonoticSandboxToolsDialog();
--- /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);
+ s = substring(s, 12, strlen(s) - 12 - 4); // screenshots/, .<ext>
+ 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)
+ bufstr_add(me.listScreenshot, search_getfilename(list, i), 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, 0);
+}
+
+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/", me.screenshotName(me,me.selectedItem)));
+}
+
+void XonoticScreenshotList_startScreenshot(entity me)
+{
+ me.screenshotViewerDialog.loadScreenshot(me.screenshotViewerDialog, strcat("/screenshots/", 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/", 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
f = 1;
c = c * f; // fteqcc fail
- cvar_set("vid_conwidth", ftos(rint(c_x)));
- cvar_set("vid_conheight", ftos(rint(c_y)));
+ c_x = rint(c_x);
+ c_y = rint(c_y);
+
+ if (c_x != cvar("vid_conwidth") || c_y != cvar("vid_conheight"))
+ {
+ cvar_set("vid_conwidth", ftos(c_x));
+ cvar_set("vid_conheight", ftos(c_y));
+ localcmd("\nr_restart\n");
+ }
+
XonoticResolutionSlider_DataHasChanged = TRUE;
}
entity makeXonoticResolutionSlider()
if(me.nValues == 0)
{
me.addResolution(me, 640, 480, 1); // pc res
+#if 0
me.addResolution(me, 720, 480, 1.125); // DVD NTSC 4:3
me.addResolution(me, 720, 576, 0.9375); // DVD PAL 4:3
me.addResolution(me, 720, 480, 0.84375); // DVD NTSC 16:9
me.addResolution(me, 720, 576, 0.703125); // DVD PAL 16:9
+#endif
me.addResolution(me, 800, 480, 1); // 480p at 1:1 pixel aspect
me.addResolution(me, 800, 600, 1); // pc res
me.addResolution(me, 1024, 600, 1); // notebook res
MUTATOR_CALLHOOK(MakePlayerObserver);
Portal_ClearAll(self);
-
+
if(self.alivetime)
{
if(!warmup_stage)
}
if(self.vehicle)
- vehicles_exit(VHEF_RELESE);
+ vehicles_exit(VHEF_RELESE);
WaypointSprite_PlayerDead();
accuracy_resend(self);
self.spectatortime = time;
-
+
self.classname = "observer";
self.iscreature = FALSE;
self.teleportable = TELEPORT_SIMPLE;
//stuffcmd(self, "chase_active 0");
//stuffcmd(self, "set viewsize $tmpviewsize \n");
-
+
target_voicescript_clear(self);
// reset fields the weapons may use
if(!self.killindicator_teamchange)
{
self.vehicle_health = -1;
- Damage(self, self, self, 1 , DEATH_KILL, self.origin, '0 0 0');
+ Damage(self, self, self, 1 , DEATH_KILL, self.origin, '0 0 0');
}
}
if(gameover) return;
if(self.player_blocked) return;
if(self.freezetag_frozen) return;
-
+
ClientKill_TeamChange(0);
}
player_count = 0;
}
+ PlayerInfo_Basic(self);
PlayerScore_Attach(self);
ClientData_Attach();
accuracy_init(self);
if(autocvar_sv_eventlog)
GameLogEcho(strcat(":part:", ftos(self.playerid)));
-
+
Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_QUIT_DISCONNECT, self.netname);
MUTATOR_CALLHOOK(ClientDisconnect);
self.superweapons_finished = 0;
}
}
-
+
if(autocvar_g_nodepthtestplayers)
self.effects = self.effects | EF_NODEPTHTEST;
setorigin(self, spectatee.origin);
setsize(self, spectatee.mins, spectatee.maxs);
SetZoomState(spectatee.zoomstate);
-
+
anticheat_spectatecopy(spectatee);
self.hud = spectatee.hud;
if(spectatee.vehicle)
self.vehicle_reload2 = spectatee.vehicle_reload2;
msg_entity = self;
-
+
WriteByte (MSG_ONE, SVC_SETVIEWANGLES);
WriteAngle(MSG_ONE, spectatee.v_angle_x);
WriteAngle(MSG_ONE, spectatee.v_angle_y);
WriteAngle(MSG_ONE, spectatee.v_angle_z);
//WriteByte (MSG_ONE, SVC_SETVIEW);
- // WriteEntity(MSG_ONE, self);
+ // WriteEntity(MSG_ONE, self);
//makevectors(spectatee.v_angle);
- //setorigin(self, spectatee.origin - v_forward * 400 + v_up * 300);*/
+ //setorigin(self, spectatee.origin - v_forward * 400 + v_up * 300);*/
}
}
float SpectateUpdate() {
if(!self.enemy)
- return 0;
+ return 0;
if (self == self.enemy)
return 0;
if (start.team == self.team) {
return start;
}
-
+
other = start;
// continue from current player
while(other && other.team != self.team) {
other = find(other, classname, "player");
}
-
+
if (!other) {
// restart from begining
other = find(other, classname, "player");
other = find(other, classname, "player");
}
}
-
+
return other;
}
vehicles_exit(VHEF_NORMAL);
return;
}
-
+
// a use key was pressed; call handlers
MUTATOR_CALLHOOK(PlayerUseKey);
}
if(frametime)
player_anim();
button_pressed = (self.BUTTON_ATCK || self.BUTTON_JUMP || self.BUTTON_ATCK2 || self.BUTTON_HOOK || self.BUTTON_USE);
-
+
if (self.deadflag == DEAD_DYING)
{
if(self.respawn_flags & RESPAWN_FORCE)
if(frametime)
player_anim();
-
+
// secret status
secrets_setstatus();
-
+
self.dmg_team = max(0, self.dmg_team - autocvar_g_teamdamage_resetspeed * frametime);
//self.angles_y=self.v_angle_y + 90; // temp
return; // intermission or finale
GetPressedKeys();
}
-
+
#ifdef TETRIS
}
#endif
float maxclients;
// flag set on worldspawn so that the code knows if it is dedicated or not
-float server_is_dedicated;
+float server_is_dedicated;
// Fields
.float target_random;
.float trigger_reverse;
-// Nexball
+// Nexball
.entity ballcarried; // Also used for keepaway
.float metertime;
float g_nexball_meter_period;
.float last_pickup;
-.float hit_time;
-.float typehit_time;
+.float hit_time;
+.float typehit_time;
.float stat_leadlimit;
#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;
d = 0; // weapon is set a few lines later
else
d = (i == WEP_LASER || i == WEP_SHOTGUN);
-
+
if(g_grappling_hook) // if possible, redirect off-hand hook to on-hand hook
d |= (i == WEP_HOOK);
if(weaponinfo.spawnflags & WEP_FLAG_MUTATORBLOCKED) // never default mutator blocked guns
d = 0;
var float t = cvar(strcat(cvarprefix, weaponinfo.netname));
-
+
//print(strcat("want_weapon: ", weaponinfo.netname, " - d: ", ftos(d), ", t: ", ftos(t), ". \n"));
-
+
// bit order in t:
// 1: want or not
// 2: is default?
// load mutators
#define CHECK_MUTATOR_ADD(mut_cvar,mut_name,dependence) \
{ if(cvar(mut_cvar) && dependence) { MUTATOR_ADD(mut_name); } }
-
+
CHECK_MUTATOR_ADD("g_dodging", mutator_dodging, 1);
CHECK_MUTATOR_ADD("g_spawn_near_teammate", mutator_spawn_near_teammate, 1);
CHECK_MUTATOR_ADD("g_physical_items", mutator_physical_items, 1);
CHECK_MUTATOR_ADD("g_nades", mutator_nades, 1);
CHECK_MUTATOR_ADD("g_sandbox", sandbox, 1);
CHECK_MUTATOR_ADD("g_campcheck", mutator_campcheck, 1);
-
+
#undef CHECK_MUTATOR_ADD
-
+
if(cvar("sv_allow_fullbright"))
serverflags |= SERVERFLAG_ALLOW_FULLBRIGHT;
g_bugrigs_speed_ref = cvar("g_bugrigs_speed_ref");
g_bugrigs_speed_pow = cvar("g_bugrigs_speed_pow");
g_bugrigs_steer = cvar("g_bugrigs_steer");
-
+
g_minstagib = cvar("g_minstagib");
sv_clones = cvar("sv_clones");
db_put(ServerProgsDB, strcat("uid2name", myuid), "");
}
}
-
+
if(s == "")
s = "^1Unregistered Player";
return s;
+++ /dev/null
-float playerstats_db;
-string teamstats_last;
-string playerstats_last;
-string events_last;
-.float playerstats_addedglobalinfo;
-.string playerstats_id;
-
-void PlayerStats_Init() // initiated before InitGameplayMode so that scores are added properly
-{
- string uri;
- playerstats_db = -1;
- playerstats_waitforme = TRUE;
- uri = autocvar_g_playerstats_uri;
- if(uri == "")
- return;
- playerstats_db = db_create();
- if(playerstats_db >= 0)
- playerstats_waitforme = FALSE; // must wait for it at match end
-
- serverflags |= SERVERFLAG_PLAYERSTATS;
-
- PlayerStats_AddEvent(PLAYERSTATS_ALIVETIME);
- PlayerStats_AddEvent(PLAYERSTATS_AVGLATENCY);
- PlayerStats_AddEvent(PLAYERSTATS_WINS);
- PlayerStats_AddEvent(PLAYERSTATS_MATCHES);
- PlayerStats_AddEvent(PLAYERSTATS_JOINS);
- PlayerStats_AddEvent(PLAYERSTATS_SCOREBOARD_VALID);
- PlayerStats_AddEvent(PLAYERSTATS_SCOREBOARD_POS);
- PlayerStats_AddEvent(PLAYERSTATS_RANK);
-
- // accuracy stats
- entity w;
- float i;
- for(i = WEP_FIRST; i <= WEP_LAST; ++i)
- {
- w = get_weaponinfo(i);
-
- PlayerStats_AddEvent(strcat("acc-", w.netname, "-hit"));
- PlayerStats_AddEvent(strcat("acc-", w.netname, "-fired"));
-
- PlayerStats_AddEvent(strcat("acc-", w.netname, "-cnt-hit"));
- PlayerStats_AddEvent(strcat("acc-", w.netname, "-cnt-fired"));
-
- PlayerStats_AddEvent(strcat("acc-", w.netname, "-frags"));
- }
-
- PlayerStats_AddEvent(PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_3);
- PlayerStats_AddEvent(PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_5);
- PlayerStats_AddEvent(PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_10);
- PlayerStats_AddEvent(PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_15);
- PlayerStats_AddEvent(PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_20);
- PlayerStats_AddEvent(PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_25);
- PlayerStats_AddEvent(PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_30);
- PlayerStats_AddEvent(PLAYERSTATS_ACHIEVEMENT_BOTLIKE);
- PlayerStats_AddEvent(PLAYERSTATS_ACHIEVEMENT_FIRSTBLOOD);
- PlayerStats_AddEvent(PLAYERSTATS_ACHIEVEMENT_FIRSTVICTIM);
-}
-
-void PlayerStats_AddPlayer(entity e)
-{
- string s;
-
- if(playerstats_db < 0)
- return;
- if(e.playerstats_id)
- return;
-
- 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);
-
- string key;
- key = sprintf("%s:*", e.playerstats_id);
-
- string p;
- p = db_get(playerstats_db, key);
- if(p == "")
- {
- if(playerstats_last)
- {
- db_put(playerstats_db, key, playerstats_last);
- strunzone(playerstats_last);
- }
- else
- db_put(playerstats_db, key, "#");
- playerstats_last = strzone(e.playerstats_id);
- }
-}
-
-void PlayerStats_AddTeam(float t)
-{
- if(playerstats_db < 0)
- return;
-
- string key;
- key = sprintf("%d", t);
-
- string p;
- p = db_get(playerstats_db, key);
- if(p == "")
- {
- if(teamstats_last)
- {
- db_put(playerstats_db, key, teamstats_last);
- strunzone(teamstats_last);
- }
- else
- db_put(playerstats_db, key, "#");
- teamstats_last = strzone(key);
- }
-}
-
-void PlayerStats_AddEvent(string event_id)
-{
- if(playerstats_db < 0)
- return;
-
- string key;
- key = sprintf("*:%s", event_id);
-
- string p;
- p = db_get(playerstats_db, key);
- if(p == "")
- {
- if(events_last)
- {
- db_put(playerstats_db, key, events_last);
- strunzone(events_last);
- }
- else
- db_put(playerstats_db, key, "#");
- events_last = strzone(event_id);
- }
-}
-
-float PlayerStats_Event(entity e, string event_id, float value)
-{
- if((e.playerstats_id == "") || playerstats_db < 0)
- return 0;
-
- string key;
- float val;
- key = sprintf("%s:%s", e.playerstats_id, event_id);
- val = stof(db_get(playerstats_db, key));
- val += value;
- db_put(playerstats_db, key, ftos(val));
- return val;
-}
-
-float PlayerStats_TeamScore(float t, string event_id, float value)
-{
- if(playerstats_db < 0)
- return 0;
-
- string key;
- float val;
- key = sprintf("team#%d:%s", t, event_id);
- val = stof(db_get(playerstats_db, key));
- val += value;
- db_put(playerstats_db, key, ftos(val));
- return val;
-}
-
-/*
- format spec:
-
- A collection of lines of the format <key> SPACE <value> NEWLINE, where
- <key> is always a single character.
-
- The following keys are defined:
-
- 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
- T: time at which the game ended
- 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
- 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!)
- n: nickname of the player (optional)
- t: team ID
- i: player index
- 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
-
- Response format (not used yet): see https://gist.github.com/4284222
-*/
-
-void PlayerStats_ready(entity fh, entity pass, float status)
-{
- string t, tn;
- string p, pn;
- string e, en;
- string nn, tt;
- string s;
-
- switch(status)
- {
- case URL_READY_CANWRITE:
- url_fputs(fh, "V 7\n");
-#ifdef WATERMARK
- url_fputs(fh, sprintf("R %s\n", WATERMARK));
-#endif
- url_fputs(fh, sprintf("T %s.%06d\n", strftime(FALSE, "%s"), floor(random() * 1000000)));
- 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)));
- if(teamplay)
- {
- for(t = teamstats_last; (tn = db_get(playerstats_db, sprintf("%d", stof(t)))) != ""; t = tn)
- {
- url_fputs(fh, sprintf("Q team#%s\n", t));
- for(e = events_last; (en = db_get(playerstats_db, sprintf("*:%s", e))) != ""; e = en)
- {
- float v;
- v = stof(db_get(playerstats_db, sprintf("team#%d:%s", stof(t), e)));
- if(v != 0)
- url_fputs(fh, sprintf("e %s %g\n", e, v));
- }
- }
- }
- for(p = playerstats_last; (pn = db_get(playerstats_db, sprintf("%s:*", p))) != ""; p = pn)
- {
- url_fputs(fh, sprintf("P %s\n", p));
- nn = db_get(playerstats_db, sprintf("%s:_playerid", p));
- if(nn != "")
- url_fputs(fh, sprintf("i %s\n", nn));
- nn = db_get(playerstats_db, sprintf("%s:_netname", p));
- if(nn != "")
- url_fputs(fh, sprintf("n %s\n", nn));
- if(teamplay)
- {
- tt = db_get(playerstats_db, sprintf("%s:_team", p));
- url_fputs(fh, sprintf("t %s\n", tt));
- }
- for(e = events_last; (en = db_get(playerstats_db, sprintf("*:%s", e))) != ""; e = en)
- {
- float v;
- v = stof(db_get(playerstats_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;
- 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_waitforme = TRUE;
- db_close(playerstats_db);
- playerstats_db = -1;
- break;
- case URL_READY_ERROR:
- default:
- print("Player stats writing failed: ", ftos(status), "\n");
- playerstats_waitforme = TRUE;
- if(playerstats_db >= 0)
- {
- db_close(playerstats_db);
- playerstats_db = -1;
- }
- break;
- }
-}
-
-//#NO AUTOCVARS START
-void PlayerStats_Shutdown()
-{
- string uri;
-
- if(playerstats_db < 0)
- return;
-
- uri = autocvar_g_playerstats_uri;
- if(uri != "")
- {
- playerstats_waitforme = FALSE;
- url_multi_fopen(uri, FILE_APPEND, PlayerStats_ready, world);
- }
- else
- {
- playerstats_waitforme = TRUE;
- db_close(playerstats_db);
- playerstats_db = -1;
- }
-}
-//#NO AUTOCVARS END
-
-void PlayerStats_Accuracy(entity p)
-{
- entity a, w;
- a = p.accuracy;
- float i;
-
- for(i = WEP_FIRST; i <= WEP_LAST; ++i)
- {
- w = get_weaponinfo(i);
-
- PlayerStats_Event(p, strcat("acc-", w.netname, "-hit"), a.(accuracy_hit[i-1]));
- PlayerStats_Event(p, strcat("acc-", w.netname, "-fired"), a.(accuracy_fired[i-1]));
-
- PlayerStats_Event(p, strcat("acc-", w.netname, "-cnt-hit"), a.(accuracy_cnt_hit[i-1]));
- PlayerStats_Event(p, strcat("acc-", w.netname, "-cnt-fired"), a.(accuracy_cnt_fired[i-1]));
-
- PlayerStats_Event(p, strcat("acc-", w.netname, "-frags"), a.(accuracy_frags[i-1]));
- }
- //backtrace(strcat("adding player stat accuracy for ", p.netname, ".\n"));
-}
-
-void PlayerStats_AddGlobalInfo(entity p)
-{
- if(playerstats_db < 0)
- return;
- if((p.playerstats_id == "") || playerstats_db < 0)
- return;
- p.playerstats_addedglobalinfo = TRUE;
-
- // add global info!
- if(p.alivetime)
- {
- PlayerStats_Event(p, PLAYERSTATS_ALIVETIME, time - p.alivetime);
- p.alivetime = 0;
- }
-
- db_put(playerstats_db, sprintf("%s:_playerid", p.playerstats_id), ftos(p.playerid));
-
- if(p.cvar_cl_allow_uid2name == 1 || IS_BOT_CLIENT(p))
- db_put(playerstats_db, sprintf("%s:_netname", p.playerstats_id), p.netname);
-
- if(teamplay)
- db_put(playerstats_db, sprintf("%s:_team", p.playerstats_id), ftos(p.team));
-
- if(stof(db_get(playerstats_db, sprintf("%d:%s", p.playerstats_id, PLAYERSTATS_ALIVETIME))) > 0)
- PlayerStats_Event(p, PLAYERSTATS_JOINS, 1);
-
- PlayerStats_Accuracy(p);
-
- if(IS_REAL_CLIENT(p))
- {
- if(p.latency_cnt)
- {
- float latency = (p.latency_sum / p.latency_cnt);
- if(latency) { PlayerStats_Event(p, PLAYERSTATS_AVGLATENCY, latency); }
- }
- }
-
- strunzone(p.playerstats_id);
- p.playerstats_id = string_null;
-}
-
-.float scoreboard_pos;
-void PlayerStats_EndMatch(float finished)
-{
- entity p;
- PlayerScore_Sort(score_dummyfield, 0, 0, 0);
- PlayerScore_Sort(scoreboard_pos, 1, 1, 1);
- if(teamplay)
- PlayerScore_TeamStats();
- FOR_EACH_CLIENT(p)
- {
- // add personal score rank
- PlayerStats_Event(p, PLAYERSTATS_RANK, p.score_dummyfield);
-
- if(!p.scoreboard_pos)
- continue;
-
- // scoreboard is valid!
- PlayerStats_Event(p, PLAYERSTATS_SCOREBOARD_VALID, 1);
-
- // add scoreboard position
- PlayerStats_Event(p, PLAYERSTATS_SCOREBOARD_POS, p.scoreboard_pos);
-
- // add scoreboard data
- PlayerScore_PlayerStats(p);
-
- // if the match ended normally, add winning info
- if(finished)
- {
- PlayerStats_Event(p, PLAYERSTATS_WINS, p.winning);
- PlayerStats_Event(p, PLAYERSTATS_MATCHES, 1);
- }
- }
-}
+++ /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);
mutators/gamemode_domination.qh
mutators/gamemode_keyhunt.qh // TODO fix this
mutators/gamemode_keepaway.qh
-mutators/gamemode_nexball.qh
+mutators/gamemode_nexball.qh
mutators/gamemode_lms.qh
mutators/mutator_dodging.qh
mutators/mutator_nades.qh
anticheat.qh
cheats.qh
-playerstats.qh
+../common/playerstats.qh
portals.qh
anticheat.qc
cheats.qc
-playerstats.qc
+../common/playerstats.qc
round_handler.qc