From: Samual Date: Tue, 27 Dec 2011 20:25:20 +0000 (-0500) Subject: Merge remote branch 'origin/master' into samual/updatecommands X-Git-Tag: xonotic-v0.6.0~188^2~28^2~55 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=efab64ab443b4182a8dda35f0fb517eb78897ea0;p=xonotic%2Fxonotic-data.pk3dir.git Merge remote branch 'origin/master' into samual/updatecommands Conflicts: defaultXonotic.cfg qcsrc/client/Main.qc qcsrc/client/main.qh qcsrc/common/util.qc qcsrc/common/util.qh --- efab64ab443b4182a8dda35f0fb517eb78897ea0 diff --cc commands.cfg index 22acccd88,000000000..754b0b382 mode 100644,000000..100644 --- a/commands.cfg +++ b/commands.cfg @@@ -1,276 -1,0 +1,272 @@@ +// ================================================================= +// Master config for managing various command aliases and settings +// ================================================================= + - // 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 $*" - +// 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 +// ======== - 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 ${* ?}" ++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. +// ======================================================= - 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 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.\"" + diff --cc qcsrc/client/command/cl_cmd.qc index 0a1783eea,000000000..b7fdc3a00 mode 100644,000000..100644 --- a/qcsrc/client/command/cl_cmd.qc +++ b/qcsrc/client/command/cl_cmd.qc @@@ -1,579 -1,0 +1,580 @@@ +// ============================================== +// CSQC client commands code, written by Samual - // Last updated: December 16th, 2011 ++// 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; - } ++}*/ + +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 \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)) + { - float i = cvar_clientsettemp_restore(); ++ 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_clientsettemp(argv(1), argv(2))) ++ 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; +} diff --cc qcsrc/common/command/generic.qc index 9595ed5c2,000000000..1d21f0845 mode 100644,000000..100644 --- a/qcsrc/common/command/generic.qc +++ b/qcsrc/common/command/generic.qc @@@ -1,853 -1,0 +1,863 @@@ +#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; +} diff --cc qcsrc/common/util.qc index 72a93d4a7,f38b1156b..69fde0f99 --- a/qcsrc/common/util.qc +++ b/qcsrc/common/util.qc @@@ -863,45 -863,29 +863,49 @@@ void get_mi_min_max_texcoords(float mod } #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) { @@@ -2108,53 -2092,36 +2112,75 @@@ float lowestbit(float f return f; } +/* +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); +}*/ + - #ifdef CSQC - entity ReadCSQCEntity() - { - float f; - f = ReadShort(); - if(f == 0) - return world; - return findfloat(world, entnum, f); - } - #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 ++#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 -} ++} diff --cc qcsrc/common/util.qh index a37121881,470a826ed..5b5888ba8 --- a/qcsrc/common/util.qh +++ b/qcsrc/common/util.qh @@@ -89,8 -90,8 +90,8 @@@ string swapInPriorityList(string order 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) @@@ -275,6 -278,5 +278,15 @@@ float lowestbit(float f) entity ReadCSQCEntity() #endif +#ifndef MENUQC +string strtolower(string s); - #endif ++#endif ++ ++string MakeConsoleSafe(string input); ++ ++#ifndef MENUQC ++float InterpretBoolean(string input); ++#endif ++ + // generic shutdown handler + void Shutdown(); diff --cc qcsrc/menu/command/menu_cmd.qc index ea2e4034e,000000000..6a140f4fc mode 100644,000000..100644 --- a/qcsrc/menu/command/menu_cmd.qc +++ b/qcsrc/menu/command/menu_cmd.qc @@@ -1,193 -1,0 +1,187 @@@ - 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")); +} diff --cc qcsrc/menu/command/menu_cmd.qh index 33eb05371,000000000..7a18fe2de mode 100644,000000..100644 --- a/qcsrc/menu/command/menu_cmd.qh +++ b/qcsrc/menu/command/menu_cmd.qh @@@ -1,2 -1,0 +1,1 @@@ - void GameCommand_Init(); +void GameCommand(string command); diff --cc qcsrc/server/progs.src index 8bf3f0e1f,a1e9f9e30..d99b07891 --- a/qcsrc/server/progs.src +++ b/qcsrc/server/progs.src @@@ -36,15 -34,7 +36,14 @@@ vehicles/vehicles_def.q 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