//*****************************************************************************
//
// cmd_admin.c
//
// commands and procedures available only to admins.
//
//*****************************************************************************
#include "mud.h"
#include "world.h"
#include "inform.h"
#include "character.h"
#include "room.h"
#include "handler.h"
#include "utils.h"
#include "socket.h"
#include "save.h"
#include "storage.h"
//*****************************************************************************
// commands in cmd_admin.c
//*****************************************************************************
//
// Locks the game for anyone not a member of one of the user groups we specify.
COMMAND(cmd_lockdown) {
// no argument - check the current lockdown status
if(!*arg) {
if(!*mudsettingGetString("lockdown"))
send_to_char(ch, "Lockdown is currently turned off.\r\n");
else {
send_to_char(ch, "Current lockdown is to members not of: %s\r\n",
mudsettingGetString("lockdown"));
send_to_char(ch, "To turn off lockdown, use {clockdown off{n\r\n");
}
}
// turn lockdown off
else if(!strcasecmp(arg, "off")) {
send_to_char(ch, "Lockdown disabled.\r\n");
mudsettingSetString("lockdown", "");
}
// make sure we're not locking ourself out
else if(!bitIsSet(charGetUserGroups(ch), arg))
send_to_char(ch, "You cannot lock yourself out!\r\n");
// lock out anyone not in the groups we specify
else {
send_to_char(ch, "MUD locked down to everyone not in groups: %s\r\n", arg);
mudsettingSetString("lockdown", arg);
// kick out everyone who we've just locked out
LIST_ITERATOR *ch_i = newListIterator(mobile_list);
ITERATE_LIST(ch, ch_i) {
if(!charIsNPC(ch) && !bitIsSet(charGetUserGroups(ch), arg)) {
send_to_char(ch, "The mud has just been locked down to you.\r\n");
save_player(ch);
// and close the socket if we have one
if(charGetSocket(ch)) {
SOCKET_DATA *sock = charGetSocket(ch);
charSetSocket(ch, NULL);
socketSetChar(sock, NULL);
close_socket(sock, FALSE);
}
// do the extraction
extract_mobile(ch);
}
} deleteListIterator(ch_i);
}
}
//
// changes the number of pulses the mud experiences each second
COMMAND(cmd_pulserate) {
if(!*arg)
send_to_char(ch,"The mud currently has %d pulses per second.\r\n",
PULSES_PER_SECOND);
else {
int pulserate = atoi(arg);
if(pulserate == 0 || 1000 % pulserate != 0)
send_to_char(ch, "The number of pulses per second must divide 1000.\r\n");
else {
mudsettingSetInt("pulses_per_second", pulserate);
send_to_char(ch, "The mud's new pulse rate is %d pulses per second.\r\n",
PULSES_PER_SECOND);
}
}
}
//
// BOOM! Shut down the MUD
COMMAND(cmd_shutdown) {
shut_down = TRUE;
}
//
// Perform a command multiple times
COMMAND(cmd_repeat) {
int repeats = 0;
if(!parse_args(ch, TRUE, cmd, arg, "int string", &repeats, &arg))
return;
// make sure the integer is a valid number
if(repeats < 1)
send_to_char(ch, "Commands can only be repeated a positive number of time.\r\n");
else {
int i;
// now, do the repeating
for(i = 0; i < repeats; i++)
do_cmd(ch, arg, TRUE);
}
}
//
// tries to force the person to do something
void try_force(CHAR_DATA *ch, CHAR_DATA *vict, char *cmd) {
if(ch == vict)
send_to_char(ch, "Why don't you just try doing it?\r\n");
else if(!charHasMoreUserGroups(ch, vict))
send_to_char(ch, "But %s has just as many priviledges as you!\r\n",
charGetName(vict));
else {
send_to_char(ch, "You force %s to '%s'\r\n", charGetName(vict), cmd);
send_to_char(vict, "%s forces you to '%s'\r\n",
see_char_as(vict, ch), cmd);
do_cmd(vict, cmd, TRUE);
}
}
//
// force someone to execute a command
COMMAND(cmd_force) {
void *found = NULL;
bool multiple = FALSE;
if(!parse_args(ch, TRUE, cmd, arg, "ch.world.noself.multiple string",
&found, &multiple, &arg))
return;
// did we find a single character, or a list of characters?
if(multiple == FALSE)
try_force(ch, found, arg);
else {
LIST_ITERATOR *ch_i = newListIterator(found);
CHAR_DATA *one_ch = NULL;
ITERATE_LIST(one_ch, ch_i) {
try_force(ch, one_ch, arg);
} deleteListIterator(ch_i);
deleteList(found);
}
}
//
// Perform a command at another room or person
COMMAND(cmd_at) {
ROOM_DATA *room = NULL;
void *found = NULL;
int found_type = PARSE_NONE;
if(!parse_args(ch, TRUE, cmd, arg, "{ room ch.world.noself } string",
&found, &found_type, &arg))
return;
// figure out what room we're doing the command at
if(found_type == PARSE_ROOM)
room = found;
else // found_type == PARSE_CHAR
room = charGetRoom(found);
// transfer us over to the new room, do the command, then transfer back
ROOM_DATA *old_room = charGetRoom(ch);
char_from_room(ch);
char_to_room(ch, room);
do_cmd(ch, arg, TRUE);
char_from_room(ch);
char_to_room(ch, old_room);
}
//
// Go to a specific room, object, or character in the game. Rooms are referenced
// by vnum. Everything else is referenced by name.
// usage: goto <thing>
//
// examples:
// goto 100 go to room number 100
// goto jim go to an object/person named jim
COMMAND(cmd_goto) {
ROOM_DATA *room = NULL;
void *found = NULL;
int found_type = PARSE_NONE;
if(!parse_args(ch, TRUE, cmd, arg, "{ room ch.world.noself }",
&found, &found_type))
return;
// what did we find?
if(found_type == PARSE_ROOM)
room = found;
else // found_type == PARSE_CHAR
room = charGetRoom(found);
message(ch, NULL, NULL, NULL, TRUE, TO_ROOM,
"$n disappears in a puff of smoke.");
char_from_room(ch);
char_to_room(ch, room);
look_at_room(ch, room);
message(ch, NULL, NULL, NULL, TRUE, TO_ROOM,
"$n arrives in a puff of smoke.");
}
//
// ch transfers tgt to dest
void do_transfer(CHAR_DATA *ch, CHAR_DATA *tgt, ROOM_DATA *dest) {
if(dest == charGetRoom(tgt))
send_to_char(ch, "%s is already %s.\r\n", charGetName(tgt),
(charGetRoom(ch) == dest ? "here" : "there"));
else {
send_to_char(tgt, "%s has transferred you to %s!\r\n",
see_char_as(tgt, ch), roomGetName(dest));
message(tgt, NULL, NULL, NULL, TRUE, TO_ROOM,
"$n disappears in a puff of smoke.");
char_from_room(tgt);
char_to_room(tgt, dest);
look_at_room(tgt, dest);
message(tgt, NULL, NULL, NULL, TRUE, TO_ROOM,
"$n arrives in a puff of smoke.");
}
}
//
// The opposite of goto. Instead of moving to a specified location, it
// takes the target to the user.
// usage: transfer <player> [[to] room]
COMMAND(cmd_transfer) {
void *found = NULL;
bool multiple = FALSE;
ROOM_DATA *dest = NULL;
// if our arguments don't parse properly,
// parse_args will tell the person what is wrong
if(parse_args(ch, TRUE, cmd, arg,
"ch.world.multiple.noself | [to] room",
&found, &multiple, &dest)) {
// if we didn't supply a destination, use our current room
if(dest == NULL)
dest = charGetRoom(ch);
// if we have multiple people, we'll have to transfer them one by one
if(multiple == FALSE)
do_transfer(ch, found, dest);
else {
LIST_ITERATOR *tgt_i = newListIterator(found);
CHAR_DATA *tgt = NULL;
ITERATE_LIST(tgt, tgt_i) {
do_transfer(ch, found, dest);
} deleteListIterator(tgt_i);
// we also have to delete the list that we were given
deleteList(found);
}
}
}
//
// Perform a copyover
COMMAND(cmd_copyover) {
do_copyover(ch);
}
//
// show a list of all the PCs who are linkdead
COMMAND(cmd_linkdead) {
LIST_ITERATOR *ch_i = newListIterator(mobile_list);
CHAR_DATA *one_ch = NULL;
bool found = FALSE;
ITERATE_LIST(one_ch, ch_i) {
if (!(charIsNPC(one_ch) || charGetSocket(one_ch))) {
send_to_char(ch, "%s is linkdead.\r\n", charGetName(one_ch));
found = TRUE;
}
} deleteListIterator(ch_i);
if (!found)
send_to_char(ch, "Noone is currently linkdead.\r\n");
}