]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/server/command/cmd.qc
Merge branch 'terencehill/spectate_player' into 'master'
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / command / cmd.qc
index a5867dced827e3bcae9fb5f5151d14f063be81d5..ad9cab8e72301cbc7735ebea4a5e9b19c8bc4070 100644 (file)
@@ -121,7 +121,7 @@ void ClientCommand_clientversion(entity caller, int request, int argc)  // inter
                                        {
                                                // JoinBestTeam(caller, false, true);
                                        }
-                                       else if (teamplay && !autocvar_sv_spectate && !(caller.team_forced > 0))
+                                       else if (teamplay && !autocvar_sv_spectate && !(Player_GetForcedTeamIndex(caller) > 0))
                                        {
                                                TRANSMUTE(Observer, caller);  // really?
                                                stuffcmd(caller, "menu_showteamselect\n");
@@ -184,10 +184,12 @@ void ClientCommand_wpeditor(entity caller, int request, int argc)
                        {
                                if (argv(1) == "spawn")
                                {
+                                       string s = argv(2);
                                        if (!IS_PLAYER(caller))
                                                sprint(caller, "ERROR: this command works only if you are player\n");
                                        else
-                                               waypoint_spawn_fromeditor(caller);
+                                               waypoint_spawn_fromeditor(caller, (s == "crosshair"), (s == "jump"), (s == "crouch"), (s == "support"));
+                                       return;
                                }
                                else if (argv(1) == "remove")
                                {
@@ -195,6 +197,18 @@ void ClientCommand_wpeditor(entity caller, int request, int argc)
                                                sprint(caller, "ERROR: this command works only if you are player\n");
                                        else
                                                waypoint_remove_fromeditor(caller);
+                                       return;
+                               }
+                               else if (argv(1) == "hardwire")
+                               {
+                                       string s = argv(2);
+                                       waypoint_start_hardwiredlink(caller, (s == "crosshair"));
+                                       return;
+                               }
+                               else if (argv(1) == "lock")
+                               {
+                                       waypoint_lock(caller);
+                                       return;
                                }
                                else if (argv(1) == "unreachable")
                                {
@@ -202,13 +216,34 @@ void ClientCommand_wpeditor(entity caller, int request, int argc)
                                                sprint(caller, "ERROR: this command works only if you are player\n");
                                        else
                                                waypoint_unreachable(caller);
+                                       return;
                                }
                                else if (argv(1) == "saveall")
+                               {
                                        waypoint_saveall();
+                                       return;
+                               }
                                else if (argv(1) == "relinkall")
+                               {
                                        waypoint_schedulerelinkall();
-
-                               return;
+                                       return;
+                               }
+                               else if (argv(1) == "symaxis")
+                               {
+                                       if (argv(2) == "set" || argv(2) == "get")
+                                       {
+                                               waypoint_getSymmetricalAxis_cmd(caller, (argv(2) == "set"), 3);
+                                               return;
+                                       }
+                               }
+                               else if (argv(1) == "symorigin")
+                               {
+                                       if (argv(2) == "set" || argv(2) == "get")
+                                       {
+                                               waypoint_getSymmetricalOrigin_cmd(caller, (argv(2) == "set"), 3);
+                                               return;
+                                       }
+                               }
                        }
                }
 
@@ -217,7 +252,28 @@ void ClientCommand_wpeditor(entity caller, int request, int argc)
                case CMD_REQUEST_USAGE:
                {
                        sprint(caller, "\nUsage:^3 cmd wpeditor action\n");
-                       sprint(caller, "  Where 'action' can be: spawn, remove, unreachable, saveall, relinkall\n");
+                       sprint(caller, "  Where 'action' can be:\n");
+                       sprint(caller, "   ^5spawn^7: spawns a waypoint at player's position\n");
+                       sprint(caller, "   ^5remove^7: removes player's nearest waypoint\n");
+                       sprint(caller, "   ^5unreachable^7: reveals waypoints and items unreachable from the current position and spawnpoints without a nearest waypoint\n");
+                       sprint(caller, "   ^5saveall^7: saves all waypoints and links to file\n");
+                       sprint(caller, "   ^5relinkall^7: relinks all waypoints as if they were respawned\n");
+                       sprint(caller, "   ^5spawn crosshair^7: spawns a waypoint at crosshair's position\n");
+                       sprint(caller, "   ^7 in general useful to create special and hardwired links with ease from existing waypoints\n");
+                       sprint(caller, "   ^7 in particular it's the only way to create custom jumppad waypoints (spawn another waypoint to create destination))\n");
+                       sprint(caller, "   ^5spawn jump^7: spawns a jump waypoint (place it at least 60 qu before jump start, spawn another waypoint to create destination)\n");
+                       sprint(caller, "   ^5spawn crouch^7: spawns a crouch waypoint (it links only to very close waypoints)\n");
+                       sprint(caller, "   ^5spawn support^7: spawns a support waypoint (spawn another waypoint to create destination from which all incoming links are removed)\n");
+                       sprint(caller, "   ^7 useful to replace links to problematic jumppad/teleport waypoints\n");
+                       sprint(caller, "   ^5hardwire^7: marks the nearest waypoint as origin of a new hardwired link (spawn another waypoint over an existing one to create destination)\n");
+                       sprint(caller, "   ^5hardwire crosshair^7: marks the waypoint at crosshair instead of the nearest waypoint\n");
+                       sprint(caller, "   ^5lock^7: locks link display of the aimed waypoint (unlocks if no waypoint is found at crosshair's position)\n");
+                       sprint(caller, "   ^5symorigin get|set\n");
+                       sprint(caller, "   ^5symorigin get|set p1 p2 ... pX\n");
+                       sprint(caller, "   ^5symaxis get|set p1 p2\n");
+                       sprint(caller, "   ^7 where p1 p2 ... pX are positions (\"x y z\", z can be omitted) that you know are perfectly symmetrical"
+                                                               " so you can determine origin/axis of symmetry of maps without ctf flags or where flags aren't perfectly symmetrical\n");
+                       sprint(caller, "  See 'wpeditor_menu' for a selectable list of various commands and useful settings to edit waypoints.\n");
                        return;
                }
        }
@@ -247,6 +303,36 @@ void ClientCommand_join(entity caller, int request)
        }
 }
 
+void ClientCommand_kill(entity caller, int request)
+{
+       switch (request)
+       {
+               case CMD_REQUEST_COMMAND:
+               {
+                       if(IS_SPEC(caller) || IS_OBSERVER(caller))
+                               return; // no point warning about this, command does nothing
+
+                       if(GetResource(caller, RES_HEALTH) <= 0)
+                       {
+                               sprint(caller, "Can't die - you are already dead!\n");
+                               return;
+                       }
+
+                       ClientKill(caller);
+
+                       return;  // never fall through to usage
+               }
+
+               default:
+               case CMD_REQUEST_USAGE:
+               {
+                       sprint(caller, "\nUsage:^3 cmd kill\n");
+                       sprint(caller, "  No arguments required.\n");
+                       return;
+               }
+       }
+}
+
 void ClientCommand_physics(entity caller, int request, int argc)
 {
        switch (request)
@@ -269,7 +355,7 @@ void ClientCommand_physics(entity caller, int request, int argc)
 
                        if (Physics_Valid(command) || command == "default")
                        {
-                               stuffcmd(caller, strcat("\nseta cl_physics ", command, "\nsendcvar cl_physics\n"));
+                               stuffcmd(caller, strcat("\nseta cl_physics ", command, "\n"));
                                sprint(caller, strcat("^2Physics set successfully changed to ^3", command, "\n"));
                                return;
                        }
@@ -363,19 +449,7 @@ void ClientCommand_say_team(entity caller, int request, int argc, string command
                case CMD_REQUEST_COMMAND:
                {
                        if (argc >= 2)
-                       {
-                               string _classname = string_null;
-                               if (!IS_PLAYER(caller) && caller.caplayer)
-                               {
-                                       // CA: make work team chat for killed players
-                                       _classname = caller.classname;
-                                       caller.classname = STR_PLAYER;
-                               }
-
                                Say(caller, true, NULL, substring(command, argv_start_index(1), argv_end_index(-1) - argv_start_index(1)), 1);
-                               if (_classname)
-                                       caller.classname = _classname;
-                       }
                        return;  // never fall through to usage
                }
 
@@ -409,7 +483,7 @@ void ClientCommand_selectteam(entity caller, int request, int argc)
                                sprint(caller, "^7selectteam can only be used in teamgames\n");
                                return;
                        }
-                       if (caller.team_forced > 0)
+                       if (Player_GetForcedTeamIndex(caller) > 0)
                        {
                                sprint(caller, "^7selectteam can not be used as your team is forced\n");
                                return;
@@ -561,15 +635,22 @@ void ClientCommand_spectate(entity caller, int request)
                {
                        if (!intermission_running && IS_CLIENT(caller))
                        {
-                               if((IS_SPEC(caller) || IS_OBSERVER(caller)) && argv(1) != "")
+                               if(argv(1) != "")
                                {
-                                       entity client = GetFilteredEntity(argv(1));
-                                       int spec_accepted = VerifyClientEntity(client, false, false);
-                                       if(spec_accepted > 0 && IS_PLAYER(client))
+                                       if(IS_SPEC(caller) || IS_OBSERVER(caller))
                                        {
-                                               if(Spectate(caller, client))
-                                                       return; // fall back to regular handling
+                                               entity client = GetFilteredEntity(argv(1));
+                                               int spec_accepted = VerifyClientEntity(client, false, false);
+                                               if(spec_accepted > 0 && IS_PLAYER(client))
+                                               {
+                                                       Spectate(caller, client);
+                                               }
+                                               else
+                                                       sprint(caller, "can't spectate ", argv(1), "^7\n");
                                        }
+                                       else
+                                               sprint(caller, "cmd spectate client only works when you are spectator/observer\n");
+                                       return;
                                }
 
                                int mutator_returnvalue = MUTATOR_CALLHOOK(ClientCommand_Spectate, caller);
@@ -586,7 +667,7 @@ void ClientCommand_spectate(entity caller, int request)
                default:
                case CMD_REQUEST_USAGE:
                {
-                       sprint(caller, "\nUsage:^3 cmd spectate <client>\n");
+                       sprint(caller, "\nUsage:^3 cmd spectate [client]\n");
                        sprint(caller, "  Where 'client' can be the player to spectate.\n");
                        return;
                }
@@ -688,6 +769,18 @@ void ClientCommand_voice(entity caller, int request, int argc, string command)
                                        sprint(caller, sprintf("Invalid voice. Use one of: %s\n", allvoicesamples));
                                        return;
                                }
+                               if (IS_DEAD(caller))
+                               {
+                                       // don't warn the caller when trying to taunt while dead, just don't play any sounds!
+                                       // we still allow them to see warnings if it's invalid, so a dead player can find out the sounds in peace
+                                       return;
+                               }
+                               if (IS_SPEC(caller) || IS_OBSERVER(caller))
+                               {
+                                       // observers/spectators have no player model of their own to play taunts from
+                                       // again, allow them to see warnings
+                                       return;
+                               }
                                string msg = "";
                                if (argc >= 3)
                                        msg = substring(command, argv_start_index(2), argv_end_index(-1) - argv_start_index(2));
@@ -742,6 +835,7 @@ void ClientCommand_(entity caller, int request)
        CLIENT_COMMAND("autoswitch", ClientCommand_autoswitch(ent, request, arguments), "Whether or not to switch automatically when getting a better weapon") \
        CLIENT_COMMAND("clientversion", ClientCommand_clientversion(ent, request, arguments), "Release version of the game") \
        CLIENT_COMMAND("join", ClientCommand_join(ent, request), "Become a player in the game") \
+       CLIENT_COMMAND("kill", ClientCommand_kill(ent, request), "Become a member of the dead") \
        CLIENT_COMMAND("minigame", ClientCommand_minigame(ent, request, arguments, command), "Start a minigame") \
        CLIENT_COMMAND("mv_getpicture", ClientCommand_mv_getpicture(ent, request, arguments), "Retrieve mapshot picture from the server") \
        CLIENT_COMMAND("physics", ClientCommand_physics(ent, request, arguments), "Change physics set") \
@@ -835,6 +929,7 @@ void SV_ParseClientCommand(entity this, string command)
                case "prespawn": break;                            // handled by engine in host_cmd.c
                case "sentcvar": break;                            // handled by server in this file
                case "spawn": break;                               // handled by engine in host_cmd.c
+               case "color": case "topcolor": case "bottomcolor": if(teamplay) return; else break; // handled by engine in host_cmd.c
                case "c2s": Net_ClientCommand(this, command); return; // handled by net.qh
 
                default: