--- /dev/null
- // This alias allows for common commands to be executed, even on both
- // dedicated servers and normal clients. If dedicated, then it remains
- // as sv_cmd... If a normal client, then it is changed to menu_cmd.
- alias qc_cmd "sv_cmd $*"
-
+// =================================================================
+// Master config for managing various command aliases and settings
+// =================================================================
+
- alias cvar_changes "${cmd_prefix !} cvar_changes"
- alias cvar_purechanges "${cmd_prefix !} cvar_purechanges"
- alias info "${cmd_prefix !} info ${* ?}"
- alias ladder "${cmd_prefix !} ladder"
- alias lsmaps "${cmd_prefix !} lsmaps"
- alias lsnewmaps "${cmd_prefix !} lsnewmaps"
- alias maplist "${cmd_prefix !} maplist"
- alias rankings "${cmd_prefix !} rankings"
- alias records "${cmd_prefix !} records"
- alias teamstatus "${cmd_prefix !} teamstatus"
- alias time "${cmd_prefix !} time"
- alias timein "${cmd_prefix !} timein"
- alias timeout "${cmd_prefix !} timeout"
- alias vote "${cmd_prefix !} vote ${* ?}"
- alias who "${cmd_prefix !} who ${* ?}"
-
- alias g_hitplots_add "qc_cmd rpn /g_hitplots_individuals g_hitplots_individuals ${1 !} union def"
- alias g_hitplots_remove "qc_cmd rpn /g_hitplots_individuals g_hitplots_individuals ${1 !} difference def"
-
- alias g_maplist_add "qc_cmd maplist add ${* ?}"
- alias g_maplist_remove "qc_cmd maplist remove ${* ?}"
- alias g_maplist_putfirst "qc_cmd maplist remove ${* ?} ; qc_cmd maplist add ${* ?}"
- alias g_maplist_shufflenow "qc_cmd maplist shuffle"
- alias g_maplist_cleanup "qc_cmd maplist cleanup" // removes maps that don't exist from the map list
-
- alias addfav "qc_cmd addtolist net_slist_favorites ${* ?}"
- alias addvote "qc_cmd addtolist sv_vote_commands ${* ?}"
+// Execute commands based on whether it is dedicated a server or a client.
+alias "_detect_dedicated_$qport" "${* asis}"
+alias "_detect_dedicated_0" ""
+alias _if_dedicated "_detect_dedicated_$qport ${* asis}"
+alias if_client "${* asis}"
+alias if_dedicated "${* asis}"
+_if_dedicated alias if_client ""
+if_client alias if_dedicated ""
+
+if_client set cmd_prefix "cmd"
+if_dedicated set cmd_prefix "sv_cmd"
+
++if_dedicated "alias" qc_cmd_svmenu "sv_cmd $$*"
++if_client "alias" qc_cmd_svmenu "menu_cmd $$*"
++if_dedicated "alias" qc_cmd_svcl "sv_cmd $$*"
++if_client "alias" qc_cmd_svcl "cl_cmd $$*"
++if_dedicated "alias" qc_cmd_svcmd "sv_cmd $$*"
++if_client "alias" qc_cmd_svcmd "cmd $$*"
++
+
+// ========
+// common
+// ========
- set settemp_list 0
- set settemp_idx 0
- set _settemp_var UNUSED
- alias settemp "_settemp_var \"_settemp_x$settemp_idx\"; qc_cmd rpn /settemp_idx settemp_idx 1 add def; _settemp \"$1\" \"$2\""
- alias _settemp "settemp_list \"1 $1 $_settemp_var $settemp_list\"; set $_settemp_var \"${$1}\"; $1 \"$2\""
- alias settemp_restore "_settemp_restore_${settemp_list asis}"
- alias _settemp_restore_0 "set settemp_var 0; set settemp_list 0"
- alias _settemp_restore_1 "$1 \"${$2}\"; _settemp_restore_${3- asis}"
++alias cvar_changes "qc_cmd_svcmd cvar_changes"
++alias cvar_purechanges "qc_cmd_svcmd cvar_purechanges"
++alias info "qc_cmd_svcmd info ${* ?}"
++alias ladder "qc_cmd_svcmd ladder"
++alias lsmaps "qc_cmd_svcmd lsmaps"
++alias lsnewmaps "qc_cmd_svcmd lsnewmaps"
++alias maplist "qc_cmd_svcmd maplist"
++alias rankings "qc_cmd_svcmd rankings"
++alias records "qc_cmd_svcmd records"
++alias teamstatus "qc_cmd_svcmd teamstatus"
++alias time "qc_cmd_svcmd time"
++alias timein "qc_cmd_svcmd timein"
++alias timeout "qc_cmd_svcmd timeout"
++alias vote "qc_cmd_svcmd vote ${* ?}"
++alias who "qc_cmd_svcmd who ${* ?}"
++
++alias g_hitplots_add "qc_cmd_svmenu rpn /g_hitplots_individuals g_hitplots_individuals ${1 !} union def"
++alias g_hitplots_remove "qc_cmd_svmenu rpn /g_hitplots_individuals g_hitplots_individuals ${1 !} difference def"
++
++alias g_maplist_add "qc_cmd_svmenu maplist add ${* ?}"
++alias g_maplist_remove "qc_cmd_svmenu maplist remove ${* ?}"
++alias g_maplist_putfirst "qc_cmd_svmenu maplist remove ${* ?} ; qc_cmd maplist add ${* ?}"
++alias g_maplist_shufflenow "qc_cmd_svmenu maplist shuffle"
++alias g_maplist_cleanup "qc_cmd_svmenu maplist cleanup" // removes maps that don't exist from the map list
++
++alias addfav "qc_cmd_svmenu addtolist net_slist_favorites ${* ?}"
++alias addvote "qc_cmd_svmenu addtolist sv_vote_commands ${* ?}"
+
+
+// ========================
+// engine command aliases
+// ========================
+alias bsp "ls maps/*.bsp"
+alias chmap "changelevel ${* ?}"
+alias clearmap "disconnect"
+alias ply "playdemo $1"
+alias rec "record demos/${1 !}"
+alias sv_loadconfig "exec $serverconfig"
+alias sv_restart "say \"Server will restart at the end of the match, you will all be reconnected automatically. ${* ?} \"; quit_and_redirect self"
+alias tdem "timedemo $1"
+
+
+// ===============================================
+// menu_cmd (menu command) - menu/command/menu_cmd.qc
+// ===============================================
+alias menu_showteamselect "menu_cmd directmenu TeamSelect"
+alias menu_showhudexit "menu_cmd directmenu HUDExit"
+alias menu_showhudoptions "menu_cmd directpanelhudmenu ${* ?}"
+alias menu_showsandboxtools "menu_cmd directmenu SandboxTools"
+alias menu_showquitdialog "menu_cmd directmenu Quit"
+
+// command executed before loading a map by the menu
+// makes sure maxplayers is at least minplayers or bot_number + 1
+alias _menu_loadmap_prepare_maxpl "maxplayers $_menu_loadmap_maxplayers"
+alias menu_loadmap_prepare "disconnect; wait; g_campaign 0; menu_cmd rpn /_menu_loadmap_maxplayers menu_maxplayers minplayers bot_number 1 add max max def; _menu_loadmap_prepare_maxpl; g_maplist_shufflenow"
+
+
+// ==========================================================
+// cl_cmd (client local command) - client/command/cl_cmd.qc
+// ==========================================================
+// commented out commands are really only intended for internal use
+if_client alias blurtest "cl_cmd blurtest"
+if_client alias debugmodel "cl_cmd debugmodel ${* ?}"
+//if_client alias handlevote "cl_cmd handlevote ${* ?}"
+if_client alias hud "cl_cmd hud ${* ?}"
+if_client alias localprint "cl_cmd localprint ${* ?}"
+//if_client alias mv_download "cl_cmd mv_download ${* ?}"
+if_client alias sendcvar "cl_cmd sendcvar ${* ?}"
+//if_client alias settemp "cl_cmd settemp ${* ?}"
+
+// other aliases for local commands
+if_client alias hud_configure "cl_cmd hud configure"
+if_client alias hud_save "cl_cmd hud save ${* ?}"
+if_client alias radar "cl_cmd hud radar ${* ?}"
+if_client alias scoreboard_columns_help "cl_cmd hud scoreboard_columns_help"
+if_client alias scoreboard_columns_set "cl_cmd hud scoreboard_columns_set ${* ?}"
+
+// changes a cvar and reports it to the server (for the client to notify the server about changes)
+alias setreport "set \"$1\" \"$2\" ; sendcvar \"$1\""
+
+
+// ========================================================
+// cmd (client-to-server command) - server/command/cmd.qc
+// ========================================================
+set sv_clientcommand_antispam_time 1 "Amount of seconds after a command before another command can be called again without being considered spam. (Use -1 for no antispam limit)"
+set sv_clientcommand_antispam_count 8 "Amount of commands considered spam before commands are rejected."
+seta sv_status_privacy 1 "hide IP addresses from \"status\" and \"who\" replies shown to clients"
+seta cl_autoswitch 1 "automatically switch to newly picked up weapons if they are better than what you are carrying"
+
+// commented out commands are really only intended for internal use, or already have declaration in the engine
+alias autoswitch "cmd autoswitch ${* ?}"
+alias checkfail "cmd checkfail ${* ?}"
+alias clientversion "cmd clientversion ${* ?}"
+//alias getmapvotepic "cmd getmapvotepic ${* ?}"
+alias join "cmd join"
+alias ready "cmd ready"
+alias records "cmd records"
+alias reportcvar "cmd reportcvar ${* ?}"
+//alias say "cmd say ${* ?}" // engine already has this declared as a command
+//alias say_team "cmd say_team ${* ?}" // engine already has this declared as a command
+alias selectteam "cmd selectteam ${* ?}"
+alias sentcvar "cmd sentcvar ${* ?}"
+alias spectate "cmd spectate"
+alias suggestmap "cmd suggestmap ${* ?}"
+//alias tell "cmd tell ${* ?}" // engine already has this declared as a command
+alias voice "cmd voice ${* ?}"
+
+// other aliases for client-to-server commands
+alias autoswitch "set cl_autoswitch ${1 ?} ; cmd autoswitch ${1 ?}" // todo
+
+alias team_red "cmd selectteam red; cmd join"
+alias team_blue "cmd selectteam blue; cmd join"
+alias team_pink "cmd selectteam pink; cmd join"
+alias team_yellow "cmd selectteam yellow; cmd join"
+alias team_auto "cmd selectteam auto; cmd join"
+
+alias spec "spectate"
+
+// mutator aliases
+alias sandbox "cmd g_sandbox ${* ?}"
+
+
+// ============================================================
+// sv_cmd (server console command) - server/command/sv_cmd.qc
+// ============================================================
+alias adminmsg "sv_cmd adminmsg ${* ?}"
+alias allready "sv_cmd allready"
+alias allspec "sv_cmd allspec ${* ?}"
+alias anticheat "sv_cmd anticheat ${* ?}"
+alias bbox "sv_cmd bbox"
+alias bot_cmd "sv_cmd bot_cmd ${* ?}"
+alias cointoss "sv_cmd cointoss ${* ?}"
+alias database "sv_cmd database ${* ?}"
+alias defer_clear "sv_cmd defer_clear ${* ?}"
+alias defer_clear_all "sv_cmd defer_clear_all"
+alias delrec "sv_cmd delrec ${* ?}"
+alias effectindexdump "sv_cmd effectindexdump"
+alias extendmatchtime "sv_cmd extendmatchtime"
+alias find "sv_cmd find ${* ?}"
+alias gametype "sv_cmd gametype ${* ?}"
+alias gettaginfo "sv_cmd gettaginfo ${* ?}"
+alias gotomap "sv_cmd gotomap ${* ?}"
+alias lockteams "sv_cmd lockteams"
+alias make_mapinfo "sv_cmd make_mapinfo"
+alias modelbug "sv_cmd modelbug"
+alias moveplayer "sv_cmd moveplayer ${* ?}"
+alias nospectators "sv_cmd nospectators"
+alias onslaught_updatelinks "sv_cmd onslaught_updatelinks"
+alias playerdemo "sv_cmd playerdemo ${* ?}"
+alias printstats "sv_cmd printstats"
+alias radarmap "sv_cmd radarmap ${* ?}"
+alias reducematchtime "sv_cmd reducematchtime"
+alias setbots "sv_cmd setbots ${* ?}"
+alias shuffleteams "sv_cmd shuffleteams"
+alias stuffto "sv_cmd stuffto ${* ?}"
+alias trace "sv_cmd trace ${* ?}"
+alias unlockteams "sv_cmd unlockteams"
+alias warp "sv_cmd warp ${* ?}"
+
+// other aliases for server commands
+alias endmatch "timelimit -1"
+
+alias savedb "sv_cmd database save \"${1 ?}\""
+alias dumpdb "sv_cmd database dump \"${1 ?}\""
+alias loaddb "sv_cmd database load \"${1 ?}\""
+
+alias movetored "moveplayer ${1 ?} red"
+alias movetoblue "moveplayer ${1 ?} blue"
+alias movetopink "moveplayer ${1 ?} pink"
+alias movetoyellow "moveplayer ${1 ?} yellow"
+alias movetoauto "moveplayer ${1 ?} auto"
+
+
+// =======================================================
+// Aliases for settemp subsystem. Warning: Do not touch.
+// Usage: settemp variable value, next map resets it.
+// =======================================================
++alias settemp "qc_cmd_svcl settemp $$*"
++alias settemp_restore "qc_cmd_svcl settemp_restore"
+
+
+// ===================================
+// banning - server/command/ipban.qc
+// ===================================
+alias bans "sv_cmd bans"
+alias ban "sv_cmd ban ${* ?}" // usage: ban address(maybe incomplete, like 1.2.3) bantime(seconds)
+alias kickban "sv_cmd kickban ${* ?}" // usage: kickban # playerno bantime(seconds) masksize(bytes)
+alias unban "sv_cmd unban ${* ?}" // usage: unban 3 (number from bans)
+
+
+// =================================
+// voting - server/command/vote.qc
+// =================================
+set sv_vote_call 1 "Allow users to call a vote for the commands in sv_vote_commands"
+set sv_vote_change 1 "Allow voters to change their mind after already voting"
+set sv_vote_commands "restart fraglimit chmap gotomap nextmap endmatch reducematchtime extendmatchtime allready kick cointoss movetoauto" "these commands can be voted"
+set sv_vote_only_commands ""
+set sv_vote_master_commands "movetored movetoblue movetoyellow movetopink" "Commands which vote masters can execute by themselves" // maybe add kickban here (but then sv_vote_master 0)
+set sv_vote_master 1 "Allows the use of the vote master system"
+set sv_vote_master_callable 1 "When set, users can use \"vmaster\" to call a vote to become master of voting commands"
+set sv_vote_master_password "" "when set, users can use \"vlogin PASSWORD\" to log in as master"
+set sv_vote_master_playerlimit 2 "Minimum number of players needed for a player to be allowed to vote for master"
+set sv_vote_no_stops_vote 1 "Allow the vote caller to stop his own vote simply by voting no"
+set sv_vote_singlecount 0 "set to 1 to count votes once after timeout or to 0 to count with every vote"
+set sv_vote_timeout 30 "a vote will timeout after this many seconds"
+set sv_vote_wait 120 "a player can not call a vote again for this many seconds when his vote was not accepted"
+set sv_vote_stop 15 "a player can not call a vote again for this many seconds when he stopped this vote (e.g. to correct it)"
+set sv_vote_majority_factor 0.5 "What percentage of the PLAYERS constitute a majority? (Must be at least 0.5, recommended: 0.5)"
+set sv_vote_majority_factor_of_voted 0.5 "What percentage of the VOTERS constitute a majority too? (Must be at least 0.5, recommended: 0.5)"
+// when disabled, don't allow game type changes "note: set these two equal to JUST support simple majorities"
+set sv_vote_override_mostrecent 0
+
+alias vhelp "cmd vote help"
+alias vstatus "cmd vote status"
+alias vcall "cmd vote call ${* ?}"
+alias vstop "cmd vote stop"
+alias vmaster "cmd vote master"
+alias vlogin "cmd vote login ${* ?}"
+alias vdo "cmd vote do ${* ?}"
+alias vyes "cl_cmd handlevote yes"
+alias vno "cl_cmd handlevote no"
+alias vdontcare "cmd vote dontcare"
+alias vabstain "cmd vote abstain"
+
+alias vmap "vcall gotomap ${1 ?}"
+alias vnextmap "vcall nextmap ${1 ?}"
+alias vkick "vcall kick ${1 ?}"
+alias vkickban "vcall kickban ${1 ?}"
+alias vend "vcall endmatch"
+alias vdomap "vdo gotomap ${1 ?}"
+alias vdokick "vdo kick ${* ?}"
+alias vdokickban "vdo kickban ${* ?}"
+alias vdoend "vdo endmatch"
+
+// ======================
+// rcon server commands
+// ======================
+rcon_secure 1
+set rcon_restricted_commands "restart fraglimit chmap gotomap endmatch reducematchtime extendmatchtime allready kick kickban \"sv_cmd bans\" \"sv_cmd unban *\" status \"sv_cmd teamstatus\" movetoauto movetored movetoblue movetoyellow movetopink"
+
+// =============================
+// other miscellaneous aliases
+// =============================
+alias autoscreenshot "screenshot screenshots/autoscreenshot/${1 !}-${2 !}.jpg; echo \"^5A screenshot has been taken at request of the server.\""
+
--- /dev/null
- // Last updated: December 16th, 2011
+// ==============================================
+// CSQC client commands code, written by Samual
- }
++// Last updated: December 27th, 2011
+// ==============================================
+
++/*
+float cvar_clientsettemp(string tmp_cvar, string value)
+{
+ float created_saved_value;
+ entity e;
+
+ if not(tmp_cvar || value)
+ {
+ dprint("Error: Invalid usage of cvar_clientsettemp(string, string); !\n");
+ return FALSE;
+ }
+
+ for(e = world; (e = find(e, classname, "saved_cvar_value")); )
+ if(e.netname == tmp_cvar)
+ goto saved; // skip creation
+
+ // creating a new entity to keep track of this cvar
+ e = spawn();
+ e.classname = "saved_cvar_value";
+ e.netname = strzone(tmp_cvar);
+ e.message = strzone(cvar_string(tmp_cvar));
+ created_saved_value = TRUE;
+
+ // an entity for this cvar already exists
+ :saved
+
+ // update the cvar to the value given
+ cvar_set(tmp_cvar, value);
+
+ return created_saved_value;
+}
+
+float cvar_clientsettemp_restore()
+{
+ float i;
+ entity e;
+
+ for(e = world; (e = find(e, classname, "saved_cvar_value")); )
+ { cvar_set(e.netname, e.message); ++i; }
+
+ return i;
- float i = cvar_clientsettemp_restore();
++}*/
+
+void DrawDebugModel()
+{
+ if(time - floor(time) > 0.5)
+ {
+ PolyDrawModel(self);
+ self.drawmask = 0;
+ }
+ else
+ {
+ self.renderflags = 0;
+ self.drawmask = MASK_NORMAL;
+ }
+}
+
+
+// =======================
+// Command Sub-Functions
+// =======================
+
+void LocalCommand_blurtest(float request)
+{
+ // Simple command to work with postprocessing temporarily... possibly completely pointless, the glsl shader is used for a real feature now...
+ // Anyway, to enable it, just compile the client with -DBLURTEST and then you can use the command.
+
+ #ifdef BLURTEST
+ switch(request)
+ {
+ case CMD_REQUEST_COMMAND:
+ {
+ blurtest_time0 = time;
+ blurtest_time1 = time + stof(argv(1));
+ blurtest_radius = stof(argv(2));
+ blurtest_power = stof(argv(3));
+ print("Enabled blurtest\n");
+ return;
+ }
+
+ default:
+ case CMD_REQUEST_USAGE:
+ {
+ print("\nUsage:^3 cl_cmd blurtest\n");
+ print(" No arguments required.\n");
+ return;
+ }
+ }
+ #else
+ if(request)
+ {
+ print("Blurtest is not enabled on this client.\n");
+ return;
+ }
+ #endif
+}
+
+void LocalCommand_debugmodel(float request, float argc)
+{
+ switch(request)
+ {
+ case CMD_REQUEST_COMMAND:
+ {
+ string modelname = argv(1);
+ entity debugmodel_entity;
+
+ debugmodel_entity = spawn();
+ precache_model(modelname);
+ setmodel(debugmodel_entity, modelname);
+ setorigin(debugmodel_entity, view_origin);
+ debugmodel_entity.angles = view_angles;
+ debugmodel_entity.draw = DrawDebugModel;
+ debugmodel_entity.classname = "debugmodel";
+
+ return;
+ }
+
+ default:
+ case CMD_REQUEST_USAGE:
+ {
+ print("\nUsage:^3 cl_cmd debugmodel model\n");
+ print(" Where 'model' is a string of the model name to use for the debug model.\n");
+ return;
+ }
+ }
+}
+
+void LocalCommand_handlevote(float request, float argc)
+{
+ switch(request)
+ {
+ case CMD_REQUEST_COMMAND:
+ {
+ float vote_selection;
+ string vote_string;
+
+ if(InterpretBoolean(argv(1)))
+ {
+ vote_selection = 2;
+ vote_string = "yes";
+ }
+ else
+ {
+ vote_selection = 1;
+ vote_string = "no";
+ }
+
+ if(vote_selection)
+ {
+ if(uid2name_dialog) // handled by "uid2name" option
+ {
+ vote_active = 0;
+ vote_prev = 0;
+ vote_change = -9999;
+ localcmd(strcat("setreport cl_allow_uid2name ", ftos(vote_selection - 1), "\n"));
+ uid2name_dialog = 0;
+ }
+ else { localcmd(strcat("cmd vote ", vote_string, "\n")); }
+
+ return;
+ }
+ }
+
+ default:
+ print("Incorrect parameters for ^2handlevote^7\n");
+ case CMD_REQUEST_USAGE:
+ {
+ print("\nUsage:^3 cl_cmd handlevote vote\n");
+ print(" Where 'vote' is the selection for either the current poll or uid2name.\n");
+ return;
+ }
+ }
+}
+
+void LocalCommand_hud(float request, float argc)
+{
+ switch(request)
+ {
+ case CMD_REQUEST_COMMAND:
+ {
+ switch(argv(1))
+ {
+ case "configure":
+ {
+ cvar_set("_hud_configure", ftos(!autocvar__hud_configure));
+ return;
+ }
+
+ case "save":
+ {
+ if(argv(2))
+ {
+ HUD_Panel_ExportCfg(argv(2));
+ return;
+ }
+ else
+ {
+ break; // go to usage, we're missing the paramater needed here.
+ }
+ }
+
+ case "scoreboard_columns_set":
+ {
+ Cmd_HUD_SetFields(argc);
+ return;
+ }
+
+ case "scoreboard_columns_help":
+ {
+ Cmd_HUD_Help();
+ return;
+ }
+
+ case "radar":
+ {
+ hud_panel_radar_maximized = (argv(2) ? InterpretBoolean(argv(2)) : !hud_panel_radar_maximized);
+ return;
+ }
+ }
+ }
+
+ default:
+ print("Incorrect parameters for ^2hud^7\n");
+ case CMD_REQUEST_USAGE:
+ {
+ print("\nUsage:^3 cl_cmd hud action [configname | radartoggle | layout]\n");
+ print(" Where 'action' is the command to complete,\n");
+ print(" 'configname' is the name to save to for \"save\" action,\n");
+ print(" 'radartoggle' is to control hud_panel_radar_maximized for \"radar\" action,\n");
+ print(" and 'layout' is how to organize the scoreboard columns for the set action.\n");
+ print(" Full list of commands here: \"configure, save, scoreboard_columns_help, scoreboard_columns_set, radar.\"\n");
+ return;
+ }
+ }
+}
+
+void LocalCommand_localprint(float request, float argc)
+{
+ switch(request)
+ {
+ case CMD_REQUEST_COMMAND:
+ {
+ if(argv(1))
+ {
+ centerprint_hud(argv(1));
+ return;
+ }
+ }
+
+ default:
+ print("Incorrect parameters for ^2localprint^7\n");
+ case CMD_REQUEST_USAGE:
+ {
+ print("\nUsage:^3 cl_cmd localprint \"message\"\n");
+ print(" 'message' is the centerprint message to send to yourself.\n");
+ return;
+ }
+ }
+}
+
+void LocalCommand_mv_download(float request, float argc)
+{
+ switch(request)
+ {
+ case CMD_REQUEST_COMMAND:
+ {
+ Cmd_MapVote_MapDownload(argc);
+ return;
+ }
+
+ default:
+ case CMD_REQUEST_USAGE:
+ {
+ print("\nUsage:^3 cl_cmd mv_download mapid\n");
+ print(" Where 'mapid' is the id number of the map to request an image of on the map vote selection menu.\n");
+ return;
+ }
+ }
+}
+
+void LocalCommand_sendcvar(float request, float argc)
+{
+ switch(request)
+ {
+ case CMD_REQUEST_COMMAND:
+ {
+ // W_FixWeaponOrder will trash argv, so save what we need.
+ string thiscvar = strzone(argv(1));
+ string s = cvar_string(thiscvar);
+
+ if(thiscvar == "cl_weaponpriority")
+ s = W_FixWeaponOrder(W_NumberWeaponOrder(s), 1);
+ else if(substring(thiscvar, 0, 17) == "cl_weaponpriority" && strlen(thiscvar) == 18)
+ s = W_FixWeaponOrder(W_NumberWeaponOrder(s), 0);
+
+ localcmd("cmd sentcvar ", thiscvar, " \"", s, "\"\n");
+ strunzone(thiscvar);
+ return;
+ }
+
+ default:
+ case CMD_REQUEST_USAGE:
+ {
+ print("\nUsage:^3 cl_cmd sendcvar <cvar>\n");
+ print(" Where 'cvar' is the cvar plus arguments to send to the server.\n");
+ return;
+ }
+ }
+}
+
+void LocalCommand_settemp(float request, float argc)
+{
+ switch(request)
+ {
+ case CMD_REQUEST_COMMAND:
+ {
+ if((argv(1) == "restore") && argv(2))
+ {
- if(cvar_clientsettemp(argv(1), argv(2)))
++ float i = cvar_settemp_restore();
+
+ if(i)
+ dprint("Restored ", ftos(i), " temporary cvar settings to their original values.\n");
+ else
+ dprint("Nothing to restore.\n");
+
+ return;
+ }
+ else if(argc >= 3)
+ {
++ if(cvar_settemp(argv(1), argv(2)))
+ dprint("Creating new settemp tracker for ", argv(1), " and setting it to \"", argv(2), "\" temporarily.\n");
+ else
+ dprint("Already had a tracker for ", argv(1), ", updating it to \"", argv(2), "\".\n");
+
+ return;
+ }
+ }
+
+ default:
+ print("Incorrect parameters for ^2settemp^7\n");
+ case CMD_REQUEST_USAGE:
+ {
+ print("\nUsage:^3 cl_cmd settemp \"cvar\" | [restore]\n");
+ print(" Where 'cvar' is the cvar plus arguments to send to the server,\n");
+ print(" or 'restore' allows you to restore all of the original temporary cvar values.\n");
+ return;
+ }
+ }
+}
+
+/* use this when creating a new command, making sure to place it in alphabetical order... also,
+** ADD ALL NEW COMMANDS TO commands.cfg WITH PROPER ALIASES IN THE SAME FASHION!
+void LocalCommand_(float request)
+{
+ switch(request)
+ {
+ case CMD_REQUEST_COMMAND:
+ {
+
+ return;
+ }
+
+ default:
+ case CMD_REQUEST_USAGE:
+ {
+ print("\nUsage:^3 cl_cmd \n");
+ print(" No arguments required.\n");
+ return;
+ }
+ }
+}
+*/
+
+
+// ==================================
+// Macro system for client commands
+// ==================================
+
+// Do not hard code aliases for these, instead create them in commands.cfg... also: keep in alphabetical order, please ;)
+#define CLIENT_COMMANDS(request,arguments) \
+ CLIENT_COMMAND("blurtest", LocalCommand_blurtest(request), "Feature for testing blur postprocessing") \
+ CLIENT_COMMAND("debugmodel", LocalCommand_debugmodel(request, arguments), "Spawn a debug model manually") \
+ CLIENT_COMMAND("handlevote", LocalCommand_handlevote(request, arguments), "System to handle selecting a vote or option") \
+ CLIENT_COMMAND("hud", LocalCommand_hud(request, arguments), "Commands regarding/controlling the HUD system") \
+ CLIENT_COMMAND("localprint", LocalCommand_localprint(request, arguments), "Create your own centerprint sent to yourself") \
+ CLIENT_COMMAND("mv_download", LocalCommand_mv_download(request, arguments), "Retrieve mapshot picture from the server") \
+ CLIENT_COMMAND("sendcvar", LocalCommand_sendcvar(request, arguments), "Send a cvar to the server (like weaponpriority)") \
+ CLIENT_COMMAND("settemp", LocalCommand_settemp(request, arguments), "Temporarily set a value to a cvar which is restored by command or end of each match") \
+ /* nothing */
+
+void LocalCommand_macro_help()
+{
+ #define CLIENT_COMMAND(name,function,description) \
+ { print(" ^2", name, "^7: ", description, "\n"); }
+
+ CLIENT_COMMANDS(0, 0)
+ #undef CLIENT_COMMAND
+
+ return;
+}
+
+float LocalCommand_macro_command(float argc)
+{
+ #define CLIENT_COMMAND(name,function,description) \
+ { if(name == strtolower(argv(0))) { function; return TRUE; } }
+
+ CLIENT_COMMANDS(CMD_REQUEST_COMMAND, argc)
+ #undef CLIENT_COMMAND
+
+ return FALSE;
+}
+
+float LocalCommand_macro_usage(float argc)
+{
+ #define CLIENT_COMMAND(name,function,description) \
+ { if(name == strtolower(argv(1))) { function; return TRUE; } }
+
+ CLIENT_COMMANDS(CMD_REQUEST_USAGE, argc)
+ #undef CLIENT_COMMAND
+
+ return FALSE;
+}
+
+
+// =========================================
+// Main Function Called By Engine (cl_cmd)
+// =========================================
+// If this function exists, client code handles gamecommand instead of the engine code.
+
+void GameCommand(string command)
+{
+ float argc = tokenize_console(command);
+
+ // Guide for working with argc arguments by example:
+ // argc: 1 - 2 - 3 - 4
+ // argv: 0 - 1 - 2 - 3
+ // cmd vote - master - login - password
+
+ if(strtolower(argv(0)) == "help")
+ {
+ if(argc == 1)
+ {
+ print("\nUsage:^3 cl_cmd COMMAND...^7, where possible commands are:\n");
+ LocalCommand_macro_help();
+ GameCommand_Generic("help");
+ print("For help about specific commands, type cl_cmd help COMMAND\n");
+ return;
+ }
+ else if(LocalCommand_macro_usage(argc)) // Instead of trying to call a command, we're going to see detailed information about it
+ {
+ return;
+ }
+ }
+ else if(GameCommand_Generic(command))
+ {
+ return; // handled by common/command/generic.qc
+ }
+ else if(LocalCommand_macro_command(argc)) // continue as usual and scan for normal commands
+ {
+ return; // handled by one of the above LocalCommand_* functions
+ }
+
+ // nothing above caught the command, must be invalid
+ print(((command != "") ? strcat("Unknown client command \"", command, "\"") : "No command provided"), ". For a list of supported commands, try cl_cmd help.\n");
+
+ return;
+}
+
+
+// ===================================
+// Macro system for console commands
+// ===================================
+
+// These functions are here specifically to add special + - commands to the game, and are not really normal commands.
+// Please add client commands to the function above this, as this is only for special reasons.
+#define CONSOLE_COMMANDS_NORMAL \
+ CONSOLE_COMMAND("+showscores", { scoreboard_showscores = TRUE; }) \
+ CONSOLE_COMMAND("-showscores", { scoreboard_showscores = FALSE; }) \
+ CONSOLE_COMMAND("+showaccuracy", { scoreboard_showaccuracy = TRUE; }) \
+ CONSOLE_COMMAND("-showaccuracy", { scoreboard_showaccuracy = FALSE; }) \
+ /* nothing */
+
+#define CONSOLE_COMMANDS_MOVEMENT \
+ CONSOLE_COMMAND("+forward", { ++camera_direction_x; }) \
+ CONSOLE_COMMAND("-forward", { --camera_direction_x; }) \
+ CONSOLE_COMMAND("+back", { --camera_direction_x; }) \
+ CONSOLE_COMMAND("-back", { ++camera_direction_x; }) \
+ CONSOLE_COMMAND("+moveup", { ++camera_direction_z; }) \
+ CONSOLE_COMMAND("-moveup", { --camera_direction_z; }) \
+ CONSOLE_COMMAND("+movedown", { --camera_direction_z; }) \
+ CONSOLE_COMMAND("-movedown", { ++camera_direction_z; }) \
+ CONSOLE_COMMAND("+moveright", { --camera_direction_y; }) \
+ CONSOLE_COMMAND("-moveright", { ++camera_direction_y; }) \
+ CONSOLE_COMMAND("+moveleft", { ++camera_direction_y; }) \
+ CONSOLE_COMMAND("-moveleft", { --camera_direction_y; }) \
+ CONSOLE_COMMAND("+roll_right", { ++camera_roll; }) \
+ CONSOLE_COMMAND("-roll_right", { --camera_roll; }) \
+ CONSOLE_COMMAND("+roll_left", { --camera_roll; }) \
+ CONSOLE_COMMAND("-roll_left", { ++camera_roll; }) \
+ /* nothing */
+
+void ConsoleCommand_macro_init()
+{
+ // first init normal commands
+ #define CONSOLE_COMMAND(name,execution) \
+ { registercommand(name); }
+
+ CONSOLE_COMMANDS_NORMAL
+ #undef CONSOLE_COMMAND
+
+ // then init movement commands
+ #ifndef CAMERATEST
+ if(isdemo())
+ {
+ #endif
+ #define CONSOLE_COMMAND(name,execution) \
+ { registercommand(name); }
+
+ CONSOLE_COMMANDS_MOVEMENT
+ #undef CONSOLE_COMMAND
+ #ifndef CAMERATEST
+ }
+ #endif
+
+ return;
+}
+
+float ConsoleCommand_macro_normal(float argc)
+{
+ #define CONSOLE_COMMAND(name,execution) \
+ { if(name == strtolower(argv(0))) { { execution } return TRUE; } }
+
+ CONSOLE_COMMANDS_NORMAL
+ #undef CONSOLE_COMMAND
+
+ return FALSE;
+}
+
+float ConsoleCommand_macro_movement(float argc)
+{
+ if(camera_active)
+ {
+ #define CONSOLE_COMMAND(name,execution) \
+ { if(name == strtolower(argv(0))) { { execution } return TRUE; } }
+
+ CONSOLE_COMMANDS_MOVEMENT
+ #undef CONSOLE_COMMAND
+ }
+
+ return FALSE;
+}
+
+
+// ======================================================
+// Main Function Called By Engine (registered commands)
+// ======================================================
+// Used to parse commands in the console that have been registered with the "registercommand" function
+
+float CSQC_ConsoleCommand(string command)
+{
+ float argc = tokenize_console(command);
+
+ if(ConsoleCommand_macro_normal(argc))
+ {
+ return TRUE;
+ }
+ else if(ConsoleCommand_macro_movement(argc))
+ {
+ return TRUE;
+ }
+
+ // Return value should be 1 if CSQC handled the command, otherwise return 0 to have the engine handle it.
+
+ return FALSE;
+}
--- /dev/null
+#define MAX_RPN_STACK 16
+float rpn_db;
+float rpn_error;
+float rpn_sp;
+string rpn_stack[MAX_RPN_STACK];
+string rpn_pop() {
+ if(rpn_sp > 0) {
+ --rpn_sp;
+ return rpn_stack[rpn_sp];
+ } else {
+ print("rpn: stack underflow\n");
+ rpn_error = TRUE;
+ return "";
+ }
+}
+void rpn_push(string s) {
+ if(rpn_sp < MAX_RPN_STACK) {
+ rpn_stack[rpn_sp] = s;
+ ++rpn_sp;
+ } else {
+ print("rpn: stack overflow\n");
+ rpn_error = TRUE;
+ }
+}
+string rpn_get() {
+ if(rpn_sp > 0) {
+ return rpn_stack[rpn_sp - 1];
+ } else {
+ print("rpn: empty stack\n");
+ rpn_error = TRUE;
+ return "";
+ }
+}
+void rpn_set(string s) {
+ if(rpn_sp > 0) {
+ rpn_stack[rpn_sp - 1] = s;
+ } else {
+ print("rpn: empty stack\n");
+ rpn_error = TRUE;
+ }
+}
+float rpn_getf() { return stof(rpn_get()); }
+float rpn_popf() { return stof(rpn_pop()); }
+void rpn_pushf(float f) { return rpn_push(ftos(f)); }
+void rpn_setf(float f) { return rpn_set(ftos(f)); }
+
+#define NUM_MARKUPS 41
+float markup_init;
+string markup_from[NUM_MARKUPS];
+string markup_to[NUM_MARKUPS];
+void GameCommand_MarkupInit()
+{
+ float i;
+ if (markup_init)
+ return;
+ markup_init = 1;
+ i = 0;
+ markup_from[i] = "&alien"; markup_to[i] = "\x12"; ++i;
+ markup_from[i] = "&:-)"; markup_to[i] = "\x13"; ++i;
+ markup_from[i] = "&:-("; markup_to[i] = "\x14"; ++i;
+ markup_from[i] = "&x-P"; markup_to[i] = "\x15"; ++i;
+ markup_from[i] = "&:-/"; markup_to[i] = "\x16"; ++i;
+ markup_from[i] = "&:-D"; markup_to[i] = "\x17"; ++i;
+ markup_from[i] = "&<<"; markup_to[i] = "\x18"; ++i;
+ markup_from[i] = "&>>"; markup_to[i] = "\x19"; ++i;
+ markup_from[i] = "&dot"; markup_to[i] = "\x1a"; ++i;
+ markup_from[i] = "&^_"; markup_to[i] = "\x1b"; ++i;
+ markup_from[i] = "&ysplat"; markup_to[i] = "\x1c"; ++i;
+ markup_from[i] = "&-]"; markup_to[i] = "\x1d"; ++i;
+ markup_from[i] = "&--"; markup_to[i] = "\x1e"; ++i;
+ markup_from[i] = "&[-"; markup_to[i] = "\x1f"; ++i;
+ markup_from[i] = "&s<"; markup_to[i] = "\x2c"; ++i;
+ markup_from[i] = "&s>"; markup_to[i] = "\x2e"; ++i;
+ markup_from[i] = "&<-"; markup_to[i] = "\x7f"; ++i;
+ markup_from[i] = "&[="; markup_to[i] = "\x80"; ++i;
+ markup_from[i] = "&=="; markup_to[i] = "\x81"; ++i;
+ markup_from[i] = "&=]"; markup_to[i] = "\x82"; ++i;
+ markup_from[i] = "&r!"; markup_to[i] = "\x84"; ++i;
+ markup_from[i] = "&|o|"; markup_to[i] = "\x85"; ++i;
+ markup_from[i] = "&|u|"; markup_to[i] = "\x86"; ++i;
+ markup_from[i] = "&|i|"; markup_to[i] = "\x87"; ++i;
+ markup_from[i] = "&|c|"; markup_to[i] = "\x88"; ++i;
+ markup_from[i] = "&[c]"; markup_to[i] = "\x89"; ++i;
+ markup_from[i] = "&[n]"; markup_to[i] = "\x8a"; ++i;
+ markup_from[i] = "&[]"; markup_to[i] = "\x8b"; ++i;
+ markup_from[i] = "&r?"; markup_to[i] = "\x8c"; ++i;
+ markup_from[i] = "&|>"; markup_to[i] = "\x8d"; ++i;
+ markup_from[i] = "&splat0"; markup_to[i] = "\x8e"; ++i;
+ markup_from[i] = "&splat1"; markup_to[i] = "\x8f"; ++i;
+ markup_from[i] = "&[["; markup_to[i] = "\x90"; ++i;
+ markup_from[i] = "&]]"; markup_to[i] = "\x91"; ++i;
+ markup_from[i] = "&splat2"; markup_to[i] = "\x9a"; ++i;
+ markup_from[i] = "&)("; markup_to[i] = "\x9b"; ++i;
+ markup_from[i] = "&splat3"; markup_to[i] = "\x9c"; ++i;
+ markup_from[i] = "&(."; markup_to[i] = "\x9d"; ++i;
+ markup_from[i] = "&.."; markup_to[i] = "\x9e"; ++i;
+ markup_from[i] = "&.)"; markup_to[i] = "\x9f"; ++i;
+ markup_from[i] = "&<|"; markup_to[i] = "\xff"; ++i;
+}
+
+string GameCommand_Markup(string s2)
+{
+ float red, ccase, i, j;
+ string s, s3;
+
+ GameCommand_MarkupInit();
+
+ s = "";
+
+ red = 0;
+ ccase = 0;
+ for(i = 0; i < strlen(s2); ++i)
+ {
+ for(j = 0; j < NUM_MARKUPS; ++j)
+ {
+ s3 = substring(s2, i, strlen(markup_from[j]));
+ if (s3 == markup_from[j])
+ {
+ s = strcat(s, markup_to[j]);
+ i += strlen(markup_from[j]) - 1;
+ break;
+ }
+ }
+
+ if(j == NUM_MARKUPS)
+ {
+ if(substring(s2, i, 2) == "&&")
+ {
+ s = strcat(s, strconv(ccase, red, red, "&"));
+ ++i;
+ }
+ else if(substring(s2, i, 2) == "&d")
+ {
+ red = 2;
+ ccase = 0;
+ ++i;
+ }
+ else if(substring(s2, i, 2) == "&a")
+ {
+ red = 2;
+ ccase = 2;
+ ++i;
+ }
+ else if(substring(s2, i, 2) == "&n")
+ {
+ red = 0;
+ ccase = 0;
+ ++i;
+ }
+ else
+ s = strcat(s, strconv(ccase, red, red, substring(s2, i, 1)));
+ }
+ }
+
+ return s;
+}
+
+float GameCommand_Generic(string command)
+{
+ float argc;
+ float i, j, f, n;
+ vector rgb;
+ string s, s2, c;
+ argc = tokenize_console(command);
+ if(argv(0) == "help")
+ {
+ print(" rpn EXPRESSION... - a RPN calculator.\n");
+ print(" Operator description (x: string, s: set, f: float):\n");
+ print(" x pop -----------------------------> : removes the top\n");
+ print(" x dup -----------------------------> x x : duplicates the top\n");
+ print(" x x exch --------------------------> x x : swap the top two\n");
+ print(" /cvarname load --------------------> x : loads a cvar\n");
+ print(" /cvarname x def -------------------> : writes to a cvar\n");
+ print(" f f add|sub|mul|div|mod|max|min ---> f : adds/... two numbers\n");
+ print(" f f eq|ne|gt|ge|lt|le -------------> f : compares two numbers\n");
+ print(" f neg|abs|sgn|rand|floor|ceil------> f : negates/... a number\n");
+ print(" f f f bound -----------------------> f : bounds the middle number\n");
+ print(" f1 f2 b when ----------------------> f : f1 if b, f2 otherwise\n");
+ print(" s s union|intersection|difference -> s : set operations\n");
+ print(" s shuffle -------------------------> s : randomly arrange elements\n");
+ print(" /key /value put -------------------> : set a database key\n");
+ print(" /key get --------------------------> s : get a database value\n");
+ print(" x dbpush --------------------------> : pushes the top onto the database\n");
+ print(" dbpop|dbget -----------------------> x : removes/reads DB's top\n");
+ print(" dblen|dbat ------------------------> f : gets the DB's size/cursor pos\n");
+ print(" dbclr -----------------------------> : clear the DB\n");
+ print(" s dbsave|dbload--------------------> : save/load the DB to/from a file\n");
+ print(" x dbins ---------------------------> : moves the top into the DB\n");
+ print(" dbext|dbread ----------------------> x : extract/get from the DB's cursor\n");
+ print(" f dbmov|dbgoto --------------------> : move or set the DB's cursor\n");
+ print(" s localtime -----------------------> s : formats the current local time\n");
+ print(" s gmtime --------------------------> s : formats the current UTC time\n");
+ print(" time ------------------------------> f : seconds since VM start\n");
+ print(" s /MD4 digest ---------------------> s : MD4 digest\n");
+ print(" s /SHA256 digest ------------------> s : SHA256 digest\n");
+ print(" s /formatstring sprintf1s ---------> s : sprintf with 1 string (pad, cut)\n");
+ print(" Set operations operate on 'such''strings'.\n");
+ print(" Unknown tokens insert their cvar value.\n");
+ print(" maplist add map\n");
+ print(" maplist remove map\n");
+ print(" maplist shuffle\n");
+ print(" maplist cleanup\n");
+ print(" maplist maplist\n");
+ print(" maplist lsmaps\n");
+ print(" maplist lsnewmaps\n");
+ print(" addtolist variable addedvalue\n");
+ print(" records\n");
+ print(" rankings (map argument optional)\n");
++ print(" settemp cvar value\n");
++ print(" settemp_restore\n");
+ return TRUE;
+ }
+
+ if(argv(0) == "maplist")
+ {
+ if(argv(1) == "add" && argc == 3)
+ {
+ if (!fexists(strcat("maps/", argv(2), ".bsp")))
+ {
+ print("maplist: ERROR: ", argv(2), " does not exist!\n");
+ return TRUE;
+ }
+ if(cvar_string("g_maplist") == "")
+ cvar_set("g_maplist", argv(2));
+ else
+ cvar_set("g_maplist", strcat(argv(2), " ", cvar_string("g_maplist")));
+ return TRUE;
+ }
+ else if(argv(1) == "remove" && argc == 3)
+ {
+ s = argv(2);
+ n = tokenizebyseparator(cvar_string("g_maplist"), " ");
+ s2 = "";
+ for(i = 0; i < n; ++i)
+ if(argv(i) != s)
+ s2 = strcat(s2, " ", argv(i));
+ s2 = substring(s2, 1, strlen(s2) - 1);
+ cvar_set("g_maplist", s2);
+ return TRUE;
+ }
+ else if(argv(1) == "shuffle" && argc == 2)
+ {
+ cvar_set("g_maplist", shufflewords(cvar_string("g_maplist")));
+ return TRUE;
+ }
+ else if(argv(1) == "cleanup")
+ {
+ MapInfo_Enumerate();
+ MapInfo_FilterGametype(MapInfo_CurrentGametype(), MapInfo_CurrentFeatures(), MapInfo_RequiredFlags(), MapInfo_ForbiddenFlags(), 0);
+ n = tokenizebyseparator(cvar_string("g_maplist"), " ");
+ s2 = "";
+ for(i = 0; i < n; ++i)
+ if(MapInfo_CheckMap(argv(i)))
+ s2 = strcat(s2, " ", argv(i));
+ s2 = substring(s2, 1, strlen(s2) - 1);
+ cvar_set("g_maplist", s2);
+ return TRUE;
+ }
+ else if(argv(1) == "maplist") {
+ print(maplist_reply);
+ return TRUE;
+ }
+ else if(argv(1) == "lsmaps") {
+ print(lsmaps_reply);
+ return TRUE;
+ }
+ else if(argv(1) == "lsnewmaps") {
+ print(lsnewmaps_reply);
+ return TRUE;
+ }
+ }
+ else if(argc >= 3 && argv(0) == "red")
+ {
+ s = substring(command, argv_start_index(2), argv_end_index(-1) - argv_start_index(2));
+ localcmd(strcat(argv(1), " ", GameCommand_Markup(s)));
+ return TRUE;
+ }
+ else if(argc >= 3 && crc16(0, argv(0)) == 38566 && crc16(0, strcat(argv(0), argv(0), argv(0))) == 59830)
+ {
+ // other test case
+ s = strconv(2, 0, 0, substring(command, argv_start_index(2), argv_end_index(-1) - argv_start_index(2)));
+
+ n = floor(random() * 6 + 2);
+
+ s2 = "";
+ for(i = 0; i < n; ++i)
+ {
+ s2 = strcat(s2, "AH");
+ }
+
+ if(random() < 0.1)
+ s2 = strcat(substring(s2, 1, strlen(s2) - 1), "A");
+
+ if(s == "")
+ s = s2;
+ else
+ if(random() < 0.8)
+ s = strcat(s, " ", s2);
+ else
+ s = strcat(s2, " ", s);
+
+ s2 = substring(s, strlen(s) - 2, 2);
+ if(s2 == "AH" || s2 == "AY")
+ s = strcat(s, "))");
+ else
+ s = strcat(s, " ))");
+
+ if(random() < 0.1)
+ s = substring(s, 0, strlen(s) - 1);
+
+ if(random() < 0.1)
+ s = strconv(1, 0, 0, s);
+
+ localcmd(strcat(argv(1), " ", s));
+
+ return TRUE;
+ }
+ else if(argc >= 3 && crc16(0, argv(0)) == 3826 && crc16(0, strcat(argv(0), argv(0), argv(0))) == 55790)
+ {
+ // test case for terencehill's color codes
+ s = strdecolorize(substring(command, argv_start_index(2), argv_end_index(-1) - argv_start_index(2)));
+ s2 = "";
+
+ n = strlen(s);
+ j = ((6 * max(1, floor(strlen(s)/32 + random() * 2 - 1))) / n) * (1 - 2 * (random() > 0.5));
+ f = random() * 6;
+
+ for(i = 0; i < n; ++i)
+ {
+ c = substring(s, i, 1);
+
+ if(c == ";")
+ c = ":";
+ else if(c == "^")
+ {
+ c = "^^";
+ if(substring(s, i+1, 1) == "^")
+ ++i;
+ }
+
+ if(c != " ")
+ {
+ rgb = hsl_to_rgb('1 0 0' * (j * i + f) + '0 1 .5');
+ c = strcat(rgb_to_hexcolor(rgb), c);
+ }
+ s2 = strcat(s2, c);
+ }
+
+ localcmd(strcat(argv(1), " ", s2));
+
+ return TRUE;
+ }
+ else if(argv(0) == "rpn")
+ {
+ if(!rpn_db)
+ {
+ rpn_db = db_create();
+ db_put(rpn_db, "stack.pointer", "0");
+ db_put(rpn_db, "stack.pos", "-1");
+ }
+ if(argc >= 2)
+ {
+ float rpnpos;
+ string rpncmd;
+ float f2, f3;
+ rpn_sp = 0;
+ rpn_error = FALSE;
+ for(rpnpos = 1; rpnpos < argc; ++rpnpos)
+ {
+ rpncmd = argv(rpnpos);
+ f = strlen(rpncmd);
+ if(rpncmd == "") {
+ } else if(stof(substring(rpncmd, 0, 1)) > 0) {
+ rpn_push(rpncmd);
+ } else if(substring(rpncmd, 0, 1) == "0") {
+ rpn_push(rpncmd);
+ } else if(f >= 2 && substring(rpncmd, 0, 1) == "+") {
+ rpn_push(rpncmd);
+ } else if(f >= 2 && substring(rpncmd, 0, 1) == "-") {
+ rpn_push(rpncmd);
+ } else if(f >= 2 && substring(rpncmd, 0, 1) == "/") {
+ rpn_push(substring(rpncmd, 1, strlen(rpncmd) - 1));
+ } else if(rpncmd == "clear") {
+ rpn_sp = 0;
+ } else if(rpncmd == "def" || rpncmd == "=") {
+ s = rpn_pop();
+ s2 = rpn_pop();
+
+ if(s2 != "")
+ {
+#ifdef MENUQC
+ registercvar(s2, "", 0);
+#else
+ registercvar(s2, "");
+#endif
+ if(!rpn_error) // don't change cvars if a stack error had happened!
+ cvar_set(s2, s);
+ }
+ else
+ {
+ print("rpn: empty cvar name for 'def'\n");
+ rpn_error = TRUE;
+ }
+ } else if(rpncmd == "defs" || rpncmd == "@") {
+ s = "";
+ i = rpn_popf();
+ j = (i == 0);
+ while(rpn_sp > 1 && (j || i > 0))
+ {
+ s = strcat("/", rpn_pop(), " ", s);
+ --i;
+ }
+ s2 = rpn_pop();
+ if(s2 != "")
+ {
+#ifdef MENUQC
+ registercvar(s2, "", 0);
+#else
+ registercvar(s2, "");
+#endif
+ if(!rpn_error) // don't change cvars if a stack error had happened!
+ cvar_set(s2, s);
+ }
+ else
+ {
+ print("rpn: empty cvar name for 'defs'\n");
+ rpn_error = TRUE;
+ }
+ } else if(rpncmd == "load") {
+ rpn_set(cvar_string(rpn_get()));
+ } else if(rpncmd == "exch") {
+ s = rpn_pop();
+ s2 = rpn_get();
+ rpn_set(s);
+ rpn_push(s2);
+ } else if(rpncmd == "dup") {
+ rpn_push(rpn_get());
+ } else if(rpncmd == "pop") {
+ rpn_pop();
+ } else if(rpncmd == "add" || rpncmd == "+") {
+ f = rpn_popf();
+ rpn_setf(rpn_getf() + f);
+ } else if(rpncmd == "sub" || rpncmd == "-") {
+ f = rpn_popf();
+ rpn_setf(rpn_getf() - f);
+ } else if(rpncmd == "mul" || rpncmd == "*") {
+ f = rpn_popf();
+ rpn_setf(rpn_getf() * f);
+ } else if(rpncmd == "div" || rpncmd == "/") {
+ f = rpn_popf();
+ rpn_setf(rpn_getf() / f);
+ } else if(rpncmd == "mod" || rpncmd == "%") {
+ f = rpn_popf();
+ f2 = rpn_getf();
+ rpn_setf(f2 - f * floor(f2 / f));
+ } else if(rpncmd == "abs") {
+ rpn_setf(fabs(rpn_getf()));
+ } else if(rpncmd == "sgn") {
+ f = rpn_getf();
+ if(f < 0)
+ rpn_set("-1");
+ else if(f > 0)
+ rpn_set("1");
+ else
+ rpn_set("0");
+ } else if(rpncmd == "neg" || rpncmd == "~") {
+ rpn_setf(-rpn_getf());
+ } else if(rpncmd == "floor" || rpncmd == "f") {
+ rpn_setf(floor(rpn_getf()));
+ } else if(rpncmd == "ceil" || rpncmd == "c") {
+ rpn_setf(ceil(rpn_getf()));
+ } else if(rpncmd == "max") {
+ f = rpn_popf();
+ f2 = rpn_getf();
+ rpn_setf(max(f2, f));
+ } else if(rpncmd == "min") {
+ f = rpn_popf();
+ f2 = rpn_getf();
+ rpn_setf(min(f2, f));
+ } else if(rpncmd == "bound") {
+ f = rpn_popf();
+ f2 = rpn_popf();
+ f3 = rpn_getf();
+ rpn_setf(bound(f3, f2, f));
+ } else if(rpncmd == "when") {
+ f = rpn_popf();
+ f2 = rpn_popf();
+ f3 = rpn_getf();
+ if(f)
+ rpn_setf(f3);
+ else
+ rpn_setf(f2);
+ } else if(rpncmd == ">" || rpncmd == "gt") {
+ f = rpn_popf();
+ rpn_setf(rpn_getf() > f);
+ } else if(rpncmd == "<" || rpncmd == "lt") {
+ f = rpn_popf();
+ rpn_setf(rpn_getf() < f);
+ } else if(rpncmd == "==" || rpncmd == "eq") {
+ f = rpn_popf();
+ rpn_setf(rpn_getf() == f);
+ } else if(rpncmd == ">=" || rpncmd == "ge") {
+ f = rpn_popf();
+ rpn_setf(rpn_getf() >= f);
+ } else if(rpncmd == "<=" || rpncmd == "le") {
+ f = rpn_popf();
+ rpn_setf(rpn_getf() <= f);
+ } else if(rpncmd == "!=" || rpncmd == "ne") {
+ f = rpn_popf();
+ rpn_setf(rpn_getf() != f);
+ } else if(rpncmd == "rand") {
+ rpn_setf(ceil(random() * rpn_getf()) - 1);
+ } else if(rpncmd == "crc16") {
+ rpn_setf(crc16(FALSE, rpn_get()));
+ } else if(rpncmd == "put") {
+ s2 = rpn_pop();
+ if (!rpn_error)
+ {
+ s = rpn_pop();
+ if (!rpn_error)
+ db_put(rpn_db, s, s2);
+ }
+ } else if(rpncmd == "get") {
+ s = rpn_pop();
+ if (!rpn_error)
+ rpn_push(db_get(rpn_db, s));
+ } else if(rpncmd == "dbpush") {
+ s = rpn_pop();
+ if(!rpn_error)
+ {
+ i = stof(db_get(rpn_db, "stack.pointer"));
+ db_put(rpn_db, "stack.pointer", ftos(i+1));
+ db_put(rpn_db, strcat("stack.", ftos(i)), s);
+ }
+ if(!i)
+ db_put(rpn_db, "stack.pos", "0");
+ } else if(rpncmd == "dbpop") {
+ i = stof(db_get(rpn_db, "stack.pointer"));
+ if(i)
+ {
+ s = ftos(i-1);
+ db_put(rpn_db, "stack.pointer", s);
+ rpn_push(db_get(rpn_db, strcat("stack.", s)));
+ j = stof(db_get(rpn_db, "stack.pos"));
+ if(j >= i)
+ db_put(rpn_db, "stack.pos", ftos(i-2));
+ } else {
+ rpn_error = 1;
+ print("rpn: database underflow\n");
+ }
+ } else if(rpncmd == "dbget") {
+
+ i = stof(db_get(rpn_db, "stack.pointer"));
+ if(i)
+ {
+ rpn_push(db_get(rpn_db, strcat("stack.", ftos(i-1))));
+ } else {
+ rpn_error = 1;
+ print("rpn: database empty\n");
+ }
+ } else if(rpncmd == "dblen") {
+ rpn_push(db_get(rpn_db, "stack.pointer"));
+ } else if(rpncmd == "dbclr") {
+ db_close(rpn_db);
+ rpn_db = db_create();
+ db_put(rpn_db, "stack.pointer", "0");
+ db_put(rpn_db, "stack.pos", "-1");
+ } else if(rpncmd == "dbsave") {
+ s = rpn_pop();
+ if(!rpn_error)
+ db_save(rpn_db, s);
+ } else if(rpncmd == "dbload") {
+ s = rpn_pop();
+ if(!rpn_error)
+ {
+ db_close(rpn_db);
+ rpn_db = db_load(s);
+ }
+ } else if(rpncmd == "dbins") {
+ s = rpn_pop();
+ if(!rpn_error)
+ //if(rpn_sp > 0)
+ {
+ j = stof(db_get(rpn_db, "stack.pointer"));
+ i = stof(db_get(rpn_db, "stack.pos"));
+
+ if(i < 0)
+ {
+ i = 0;
+ db_put(rpn_db, "stack.pos", "0");
+ }
+
+ db_put(rpn_db, "stack.pointer", ftos(j+1));
+ for(--j; j >= i; --j)
+ {
+ db_put(rpn_db, strcat("stack.", ftos(j+1)),
+ db_get(rpn_db, (strcat("stack.", ftos(j))))
+ );
+ }
+ db_put(rpn_db, strcat("stack.", ftos(i)), s);
+ }
+ } else if(rpncmd == "dbext") {
+ j = stof(db_get(rpn_db, "stack.pointer"));
+ i = stof(db_get(rpn_db, "stack.pos"));
+ if(!j)
+ {
+ rpn_error = TRUE;
+ print("rpn: empty database\n");
+ } else {
+ --j;
+ rpn_push(db_get(rpn_db, strcat("stack.", ftos(i))));
+ db_put(rpn_db, "stack.pointer", ftos(j));
+ if(i == j)
+ {
+ db_put(rpn_db, "stack.pos", ftos(j-1));
+ } else {
+ while(i < j)
+ {
+ db_put(rpn_db, strcat("stack.", ftos(i)),
+ db_get(rpn_db, (strcat("stack.", ftos(i+1))))
+ );
+ ++i;
+ }
+ }
+ }
+ } else if(rpncmd == "dbread") {
+ s = db_get(rpn_db, "stack.pos");
+ if(stof(s) >= 0)
+ {
+ rpn_push(db_get(rpn_db, strcat("stack.", s)));
+ } else {
+ rpn_error = 1;
+ print("rpn: empty database\n");
+ }
+ } else if(rpncmd == "dbat") {
+ rpn_push(db_get(rpn_db, "stack.pos"));
+ } else if(rpncmd == "dbmov") {
+ j = stof(db_get(rpn_db, "stack.pointer"));
+ i = stof(db_get(rpn_db, "stack.pos"));
+ i += rpn_popf();
+ if(!rpn_error)
+ {
+ if(i < 0 || i >= j)
+ {
+ print("rpn: database cursor out of bounds\n");
+ rpn_error = TRUE;
+ }
+ if(!rpn_error)
+ {
+ db_put(rpn_db, "stack.pos", ftos(i));
+ }
+ }
+ } else if(rpncmd == "dbgoto") {
+ s = rpn_pop();
+ j = stof(db_get(rpn_db, "stack.pointer"));
+ if(!j)
+ {
+ rpn_error = TRUE;
+ print("rpn: empty database, cannot move cursor\n");
+ }
+ if(!rpn_error)
+ {
+ if(s == "end")
+ i = stof(db_get(rpn_db, "stack.pointer"))-1;
+ else if(s == "beg")
+ i = 0;
+ else
+ i = stof(s);
+
+ j = stof(db_get(rpn_db, "stack.pointer"));
+ if(i < 0 || i >= j)
+ {
+ print("rpn: database cursor destination out of bounds\n");
+ rpn_error = TRUE;
+ }
+ if(!rpn_error)
+ {
+ db_put(rpn_db, "stack.pos", ftos(i));
+ }
+ }
+ } else if(rpncmd == "union") {
+ // s s2 union
+ s2 = rpn_pop();
+ s = rpn_get();
+ f = tokenize_console(s);
+ f2 = tokenize_console(strcat(s, " ", s2));
+ // tokens 0..(f-1) represent s
+ // tokens f..f2 represent s2
+ // UNION: add all tokens to s that are in s2 but not in s
+ s = "";
+ for(i = 0; i < f; ++i)
+ s = strcat(s, " ", argv(i));
+ for(i = f; i < f2; ++i) {
+ for(j = 0; j < f; ++j)
+ if(argv(i) == argv(j))
+ goto skip_union;
+ s = strcat(s, " ", argv(i));
+:skip_union
+ }
+ if(substring(s, 0, 1) == " ")
+ s = substring(s, 1, 99999);
+ rpn_set(s);
+ tokenize_console(command);
+ } else if(rpncmd == "intersection") {
+ // s s2 intersection
+ s2 = rpn_pop();
+ s = rpn_get();
+ f = tokenize_console(s);
+ f2 = tokenize_console(strcat(s, " ", s2));
+ // tokens 0..(f-1) represent s
+ // tokens f..f2 represent s2
+ // INTERSECTION: keep only the tokens from s that are also in s2
+ s = "";
+ for(i = 0; i < f; ++i) {
+ for(j = f; j < f2; ++j)
+ if(argv(i) == argv(j))
+ {
+ s = strcat(s, " ", argv(i));
+ break;
+ }
+ }
+ if(substring(s, 0, 1) == " ")
+ s = substring(s, 1, 99999);
+ rpn_set(s);
+ tokenize_console(command);
+ } else if(rpncmd == "difference") {
+ // s s2 difference
+ s2 = rpn_pop();
+ s = rpn_get();
+ f = tokenize_console(s);
+ f2 = tokenize_console(strcat(s, " ", s2));
+ // tokens 0..(f-1) represent s
+ // tokens f..f2 represent s2
+ // DIFFERENCE: keep only the tokens from s that are not in s2
+ s = "";
+ for(i = 0; i < f; ++i) {
+ for(j = f; j < f2; ++j)
+ if(argv(i) == argv(j))
+ goto skip_difference;
+ s = strcat(s, " ", argv(i));
+:skip_difference
+ }
+ if(substring(s, 0, 1) == " ")
+ s = substring(s, 1, 99999);
+ rpn_set(s);
+ tokenize_console(command);
+ } else if(rpncmd == "shuffle") {
+ // s shuffle
+ s = rpn_get();
+ f = tokenize_console(s);
+
+ for(i = 0; i < f - 1; ++i) {
+ // move a random item from i..f-1 to position i
+ s = "";
+ f2 = floor(random() * (f - i) + i);
+ for(j = 0; j < i; ++j)
+ s = strcat(s, " ", argv(j));
+ s = strcat(s, " ", argv(f2));
+ for(j = i; j < f; ++j)
+ if(j != f2)
+ s = strcat(s, " ", argv(j));
+ f = tokenize_console(s);
+ }
+
+ if(substring(s, 0, 1) == " ")
+ s = substring(s, 1, 99999);
+ rpn_set(s);
+ tokenize_console(command);
+ } else if(rpncmd == "fexists_assert") {
+ s = rpn_pop();
+ if(!rpn_error)
+ {
+ if (!fexists(s))
+ {
+ print("rpn: ERROR: ", s, " does not exist!\n");
+ rpn_error = TRUE;
+ }
+ }
+ } else if(rpncmd == "fexists") {
+ s = rpn_get();
+ if(!rpn_error)
+ {
+ if (fexists(s))
+ rpn_setf(1);
+ else
+ rpn_setf(0);
+ }
+ } else if(rpncmd == "localtime") {
+ rpn_set(strftime(TRUE, rpn_get()));
+ } else if(rpncmd == "gmtime") {
+ rpn_set(strftime(FALSE, rpn_get()));
+ } else if(rpncmd == "time") {
+ rpn_pushf(time);
+ } else if(rpncmd == "digest") {
+ s = rpn_pop();
+ rpn_set(digest_hex(s, rpn_get()));
+ } else if(rpncmd == "sprintf1s") {
+ s = rpn_pop();
+ rpn_set(sprintf(s, rpn_get()));
+ } else {
+ rpn_push(cvar_string(rpncmd));
+ }
+ if(rpn_error)
+ break;
+ }
+ while(rpn_sp > 0)
+ {
+ s = rpn_pop();
+ print("rpn: still on stack: ", s, "\n");
+ }
+ return TRUE;
+ }
+ } else if(argv(0) == "addtolist") {
+ if(argc >= 2)
+ {
+ s = argv(1);
+ s2 = argv(2);
+ if(cvar_string(s) == "")
+ cvar_set(s, s2);
+ else {
+ n = tokenizebyseparator(cvar_string(s), " ");
+ for(i = 0; i < n; ++i)
+ if(argv(i) == s2)
+ return TRUE; // already in list
+ cvar_set(s, strcat(s2, " ", cvar_string(s)));
+ }
+ }
+ return TRUE;
+ }
+ else if(argv(0) == "records") {
+ print(records_reply);
+ return TRUE;
+ }
+ else if(argv(0) == "ladder") {
+ print(ladder_reply);
+ return TRUE;
+ }
+ else if(argv(0) == "rankings") {
+ print(rankings_reply);
+ return TRUE;
+#ifdef MENUQC
+ } else if(argv(0) == "cp") {
+ if(argc >= 2)
+ {
+ s = argv(1);
+ for(i = 2; i < argc; ++i)
+ s = strcat(s, " ", argv(i));
+ centerprint(unescape(s));
+ }
+ return TRUE;
+#endif
+ }
++ else if(argv(0) == "settemp") {
++ cvar_settemp(argv(1), argv(2));
++ return TRUE;
++ }
++ else if(argv(0) == "settemp_restore") {
++ cvar_settemp_restore();
++ return TRUE;
++ }
+
+ return FALSE;
+}
}
#endif
- #ifdef CSQC
- void cvar_settemp(string pKey, string pValue)
- {
- error("cvar_settemp called from CSQC - use cvar_clientsettemp instead!");
- }
- void cvar_settemp_restore()
- {
- error("cvar_settemp_restore called from CSQC - use cvar_clientsettemp instead!");
- }
- #else
- void cvar_settemp(string pKey, string pValue)
-void cvar_settemp(string cv, string val)
++float cvar_settemp(string tmp_cvar, string tmp_value)
{
- float i;
- string settemp_var;
- if(cvar_string(pKey) == pValue)
- return;
- i = cvar("settemp_idx");
- cvar_set("settemp_idx", ftos(i+1));
- settemp_var = strcat("_settemp_x", ftos(i));
- #ifdef MENUQC
- registercvar(settemp_var, "", 0);
- #else
- registercvar(settemp_var, "");
- #endif
- cvar_set("settemp_list", strcat("1 ", pKey, " ", settemp_var, " ", cvar_string("settemp_list")));
- cvar_set(settemp_var, cvar_string(pKey));
- cvar_set(pKey, pValue);
++ float created_saved_value;
+ entity e;
++
++ if not(tmp_cvar || tmp_value)
++ {
++ dprint("Error: Invalid usage of cvar_settemp(string, string); !\n");
++ return FALSE;
++ }
++
+ for(e = world; (e = find(e, classname, "saved_cvar_value")); )
- if(e.netname == cv)
- goto saved;
++ if(e.netname == tmp_cvar)
++ goto saved; // skip creation
++
++ // creating a new entity to keep track of this cvar
+ e = spawn();
+ e.classname = "saved_cvar_value";
- e.netname = strzone(cv);
- e.message = strzone(cvar_string(cv));
-:saved
- cvar_set(cv, val);
++ e.netname = strzone(tmp_cvar);
++ e.message = strzone(cvar_string(tmp_cvar));
++ created_saved_value = TRUE;
++
++ // an entity for this cvar already exists
++ :saved
++
++ // update the cvar to the value given
++ cvar_set(tmp_cvar, tmp_value);
++
++ return created_saved_value;
}
--void cvar_settemp_restore()
++float cvar_settemp_restore()
{
- // undo what cvar_settemp did
- float n, i;
- n = tokenize_console(cvar_string("settemp_list"));
- for(i = 0; i < n - 3; i += 3)
- cvar_set(argv(i + 1), cvar_string(argv(i + 2)));
- cvar_set("settemp_list", "0");
++ float i;
+ entity e;
+ while((e = find(world, classname, "saved_cvar_value")))
+ {
+ cvar_set(e.netname, e.message);
+ remove(e);
+ }
++
++ return i;
}
- #endif
float almost_equals(float a, float b)
{
return f;
}
- #ifdef CSQC
- entity ReadCSQCEntity()
- {
- float f;
- f = ReadShort();
- if(f == 0)
- return world;
- return findfloat(world, entnum, f);
- }
- #endif
-
+/*
+string strlimitedlen(string input, string truncation, float strip_colors, float limit)
+{
+ if(strlen((strip_colors ? strdecolorize(input) : input)) <= limit)
+ return input;
+ else
+ return strcat(substring(input, 0, (strlen(input) - strlen(truncation))), truncation);
+}*/
+
- #endif
+// escape the string to make it safe for consoles
+string MakeConsoleSafe(string input)
+{
+ input = strreplace("\n", "", input);
+ input = strreplace("\\", "\\\\", input);
+ input = strreplace("$", "$$", input);
+ input = strreplace("\"", "\\\"", input);
+ return input;
+}
+
+#ifndef MENUQC
+// get true/false value of a string with multiple different inputs
+float InterpretBoolean(string input)
+{
+ switch(strtolower(input))
+ {
+ case "yes":
+ case "true":
+ case "on":
+ return TRUE;
+
+ case "no":
+ case "false":
+ case "off":
+ return FALSE;
+
+ default: return stof(input);
+ }
+}
-
++#endif
++
+ #ifdef CSQC
+ entity ReadCSQCEntity()
+ {
+ float f;
+ f = ReadShort();
+ if(f == 0)
+ return world;
+ return findfloat(world, entnum, f);
+ }
+ #endif
-}
+ float shutdown_running;
+ #ifdef SVQC
+ void SV_Shutdown()
+ #endif
+ #ifdef CSQC
+ void CSQC_Shutdown()
+ #endif
+ #ifdef MENUQC
+ void m_shutdown()
+ #endif
+ {
+ if(shutdown_running)
+ {
+ print("Recursive shutdown detected! Only restoring cvars...\n");
+ }
+ else
+ {
+ shutdown_running = 1;
+ Shutdown();
+ }
+ cvar_settemp_restore(); // this must be done LAST, but in any case
++}
float cvar_value_issafe(string s);
--void cvar_settemp(string pKey, string pValue);
--void cvar_settemp_restore();
++float cvar_settemp(string pKey, string pValue);
++float cvar_settemp_restore();
#ifndef MENUQC
// modes: 0 = trust q3map2 (_mini images)
entity ReadCSQCEntity()
#endif
- #endif
+#ifndef MENUQC
+string strtolower(string s);
++#endif
++
++string MakeConsoleSafe(string input);
++
++#ifndef MENUQC
++float InterpretBoolean(string input);
++#endif
++
+ // generic shutdown handler
+ void Shutdown();
--- /dev/null
- void GameCommand_Init()
- {
- // make gg call menu QC theCommands
- localcmd("alias qc_cmd \"menu_cmd $*\"\n");
- }
-
+string _dumptree_space;
+void _dumptree_open(entity pass, entity me)
+{
+ string s;
+ s = me.toString(me);
+ if(s == "")
+ s = me.classname;
+ else
+ s = strcat(me.classname, ": ", s);
+ print(_dumptree_space, etos(me), " (", s, ")");
+ if(me.firstChild)
+ {
+ print(" {\n");
+ _dumptree_space = strcat(_dumptree_space, " ");
+ }
+ else
+ print("\n");
+}
+void _dumptree_close(entity pass, entity me)
+{
+ if(me.firstChild)
+ {
+ _dumptree_space = substring(_dumptree_space, 0, strlen(_dumptree_space) - 2);
+ print(_dumptree_space, "}\n");
+ }
+}
+
+float curl_uri_get_pos;
+float curl_uri_get_exec[URI_GET_CURL_END - URI_GET_CURL + 1];
+string curl_uri_get_cvar[URI_GET_CURL_END - URI_GET_CURL + 1];
+void Curl_URI_Get_Callback(float id, float status, string data)
+{
+ float i;
+ float do_exec;
+ string do_cvar;
+ i = id - URI_GET_CURL;
+ do_exec = curl_uri_get_exec[i];
+ do_cvar = curl_uri_get_cvar[i];
+ if(status != 0)
+ {
+ print(sprintf(_("error: status is %d\n"), status));
+ if(do_cvar)
+ strunzone(do_cvar);
+ return;
+ }
+ if(do_exec)
+ localcmd(data);
+ if(do_cvar)
+ {
+ cvar_set(do_cvar, data);
+ strunzone(do_cvar);
+ }
+ if(!do_exec && !do_cvar)
+ print(data);
+}
+
+void GameCommand(string theCommand)
+{
+ float argc;
+ argc = tokenize_console(theCommand);
+
+ if(argv(0) == "help" || argc == 0)
+ {
+ print(_("Usage: menu_cmd command..., where possible commands are:\n"));
+ print(_(" sync - reloads all cvars on the current menu page\n"));
+ print(_(" directmenu ITEM - select a menu item as main item\n"));
+ GameCommand_Generic("help");
+ return;
+ }
+
+ if(GameCommand_Generic(theCommand))
+ return;
+
+ if(argv(0) == "sync")
+ {
+ m_sync();
+ return;
+ }
+
+ if(argv(0) == "directmenu") if(argc == 2)
+ {
+ // switch to a menu item
+ if(!isdemo()) // don't allow this command in demos
+ m_goto(argv(1));
+ return;
+ }
+
+ if(argv(0) == "directpanelhudmenu")
+ {
+ // switch to a menu item
+ m_goto(strcat("HUD", argv(1)));
+ return;
+ }
+
+ if(argv(0) == "skinselect")
+ {
+ m_goto_skin_selector();
+ return;
+ }
+
+ if(argv(0) == "languageselect")
+ {
+ m_goto_language_selector();
+ return;
+ }
+
+ if(argv(0) == "videosettings")
+ {
+ m_goto_video_settings();
+ return;
+ }
+
+ if(argv(0) == "dumptree")
+ {
+ _dumptree_space = "";
+ depthfirst(main, parent, firstChild, nextSibling, _dumptree_open, _dumptree_close, NULL);
+ return;
+ }
+
+ if(argv(0) == "curl")
+ {
+ float do_exec;
+ string do_cvar;
+ float key;
+ float i, j;
+ string url;
+ float buf;
+ float r;
+
+ do_exec = FALSE;
+ do_cvar = string_null;
+ key = -1;
+
+ for(i = 1; i+1 < argc; ++i)
+ {
+ if(argv(i) == "--cvar" && i+2 < argc)
+ {
+ ++i;
+ do_cvar = strzone(argv(i));
+ continue;
+ }
+ if(argv(i) == "--exec")
+ {
+ do_exec = TRUE;
+ continue;
+ }
+ if(argv(i) == "--key" && i+2 < argc)
+ {
+ ++i;
+ key = stof(argv(i));
+ continue;
+ }
+ break;
+ }
+
+ // now, argv(i) is the URL
+ // following args may be POST parameters
+ url = argv(i);
+ ++i;
+ buf = buf_create();
+ j = 0;
+ for(; i+1 < argc; i += 2)
+ bufstr_set(buf, ++j, sprintf("%s=%s", uri_escape(argv(i)), uri_escape(argv(i+1))));
+ if(i < argc)
+ bufstr_set(buf, ++j, sprintf("submit=%s", uri_escape(argv(i))));
+
+ if(j == 0) // no args: GET
+ r = crypto_uri_postbuf(url, URI_GET_CURL + curl_uri_get_pos, string_null, string_null, -1, key);
+ else // with args: POST
+ r = crypto_uri_postbuf(url, URI_GET_CURL + curl_uri_get_pos, "application/x-www-form-urlencoded", "&", buf, key);
+
+ if(r)
+ {
+ curl_uri_get_exec[curl_uri_get_pos] = do_exec;
+ curl_uri_get_cvar[curl_uri_get_pos] = do_cvar;
+ curl_uri_get_pos = mod(curl_uri_get_pos + 1, URI_GET_CURL_END - URI_GET_CURL + 1);
+ }
+ else
+ print(_("error creating curl handle\n"));
+
+ buf_del(buf);
+
+ return;
+ }
+
+ print(_("Invalid command. For a list of supported commands, try menu_cmd help.\n"));
+}
--- /dev/null
- void GameCommand_Init();
+void GameCommand(string command);
campaign.qh
../common/campaign_common.qh
../common/mapinfo.qh
- ../common/util.qc
+command/common.qh
+command/ipban.qh
+command/radarmap.qh
+command/vote.qh
+command/cmd.qh
+command/sv_cmd.qh
+
accuracy.qh
csqcprojectile.qh
../common/csqcmodel_settings.qh