/**************************************************************************
* File: act.wizard.c Part of tbaMUD *
* Usage: Player-level god commands and other goodies. *
* *
* All rights reserved. See license for complete information. *
* *
* Copyright (C) 1993, 94 by the Trustees of the Johns Hopkins University *
* CircleMUD is based on DikuMUD, Copyright (C) 1990, 1991. *
**************************************************************************/
#include "conf.h"
#include "sysdep.h"
#include "structs.h"
#include "utils.h"
#include "comm.h"
#include "interpreter.h"
#include "handler.h"
#include "db.h"
#include "spells.h"
#include "house.h"
#include "screen.h"
#include "constants.h"
#include "oasis.h"
#include "dg_scripts.h"
#include "shop.h"
/* external vars */
extern FILE *player_fl;
extern struct attack_hit_type attack_hit_text[];
extern char *class_abbrevs[];
extern time_t boot_time;
extern int circle_shutdown, circle_reboot;
extern int circle_restrict;
extern int buf_switches, buf_largecount, buf_overflows;
extern int top_of_p_table;
extern socket_t mother_desc;
extern ush_int port;
extern const char *pc_class_types[];
extern int top_of_p_table;
extern struct player_index_element *player_table;
/* external functions */
int level_exp(int chclass, int level);
void show_shops(struct char_data *ch, char *value);
void hcontrol_list_houses(struct char_data *ch, char *arg);
void do_start(struct char_data *ch);
void appear(struct char_data *ch);
void reset_zone(zone_rnum zone);
void roll_real_abils(struct char_data *ch);
int parse_class(char arg);
void run_autowiz(void);
int save_all(void);
zone_rnum real_zone_by_thing(room_vnum vznum);
SPECIAL(shop_keeper);
void Crash_rentsave(struct char_data * ch, int cost);
void new_hist_messg(struct descriptor_data *d, const char *msg);
void clearMemory(struct char_data *ch);
int perform_set_dg_var(struct char_data *ch, struct char_data *vict, char *val_arg);
struct time_info_data *real_time_passed(time_t t2, time_t t1);
/* local functions */
int perform_set(struct char_data *ch, struct char_data *vict, int mode, char *val_arg);
void perform_immort_invis(struct char_data *ch, int level);
ACMD(do_echo);
ACMD(do_send);
room_rnum find_target_room(struct char_data *ch, char *rawroomstr);
ACMD(do_at);
ACMD(do_goto);
ACMD(do_trans);
ACMD(do_teleport);
ACMD(do_vnum);
void list_zone_commands_room(struct char_data *ch, room_vnum rvnum);
void do_stat_room(struct char_data *ch, struct room_data *rm);
void do_stat_object(struct char_data *ch, struct obj_data *j);
void do_stat_character(struct char_data *ch, struct char_data *k);
ACMD(do_stat);
ACMD(do_shutdown);
void stop_snooping(struct char_data *ch);
ACMD(do_snoop);
ACMD(do_switch);
ACMD(do_return);
ACMD(do_load);
ACMD(do_vstat);
ACMD(do_purge);
ACMD(do_syslog);
ACMD(do_advance);
ACMD(do_restore);
void perform_immort_vis(struct char_data *ch);
ACMD(do_invis);
ACMD(do_gecho);
ACMD(do_poofset);
ACMD(do_dc);
ACMD(do_wizlock);
ACMD(do_date);
ACMD(do_last);
ACMD(do_force);
ACMD(do_wiznet);
ACMD(do_zreset);
ACMD(do_wizutil);
size_t print_zone_to_buf(char *bufptr, size_t left, zone_rnum zone, int listall);
ACMD(do_show);
ACMD(do_set);
void snoop_check(struct char_data *ch);
ACMD(do_saveall);
ACMD(do_zpurge);
void clean_llog_entries(void);
ACMD(do_list_llog_entries);
struct char_data *is_in_game(long idnum);
ACMD(do_links);
void mob_checkload(struct char_data *ch, mob_vnum mvnum);
void obj_checkload(struct char_data *ch, obj_vnum ovnum);
void trg_checkload(struct char_data *ch, trig_vnum tvnum);
ACMD(do_zcheck);
ACMD(do_checkloadstatus);
ACMD(do_poofs);
ACMD(do_copyover);
ACMD(do_peace);
void mod_llog_entry(struct last_entry *llast,int type);
ACMD(do_plist);
ACMD(do_wizupdate);
int purge_room(room_rnum room)
{
int j;
struct char_data *vict;
if (room == NOWHERE || room > top_of_world) return 0;
for (vict = world[room].people; vict; vict = vict->next_in_room) {
if (!IS_NPC(vict))
continue;
/* Dump inventory. */
while (vict->carrying)
extract_obj(vict->carrying);
/* Dump equipment. */
for (j = 0; j < NUM_WEARS; j++)
if (GET_EQ(vict, j))
extract_obj(GET_EQ(vict, j));
/* Dump character. */
extract_char(vict);
}
/* Clear the ground. */
while (world[room].contents)
extract_obj(world[room].contents);
return 1;
}
ACMD(do_echo)
{
skip_spaces(&argument);
if (!*argument)
send_to_char(ch, "Yes.. but what?\r\n");
else {
char buf[MAX_INPUT_LENGTH + 4];
if (subcmd == SCMD_EMOTE)
snprintf(buf, sizeof(buf), "$n %s", argument);
else {
strlcpy(buf, argument, sizeof(buf));
mudlog(CMP, MAX(LVL_BUILDER, GET_INVIS_LEV(ch)), TRUE, "(GC) %s echoed: %s", GET_NAME(ch), buf);
}
act(buf, FALSE, ch, 0, 0, TO_ROOM);
if (!IS_NPC(ch) && PRF_FLAGGED(ch, PRF_NOREPEAT))
send_to_char(ch, "%s", CONFIG_OK);
else
act(buf, FALSE, ch, 0, 0, TO_CHAR);
}
}
ACMD(do_send)
{
char arg[MAX_INPUT_LENGTH], buf[MAX_INPUT_LENGTH];
struct char_data *vict;
half_chop(argument, arg, buf);
if (!*arg) {
send_to_char(ch, "Send what to who?\r\n");
return;
}
if (!(vict = get_char_vis(ch, arg, NULL, FIND_CHAR_WORLD))) {
send_to_char(ch, "%s", CONFIG_NOPERSON);
return;
}
send_to_char(vict, "%s\r\n", buf);
mudlog(CMP, MAX(LVL_GOD, GET_INVIS_LEV(ch)), TRUE, "(GC) %s sent %s: %s", GET_NAME(ch), GET_NAME(vict), buf);
if (!IS_NPC(ch) && PRF_FLAGGED(ch, PRF_NOREPEAT))
send_to_char(ch, "Sent.\r\n");
else
send_to_char(ch, "You send '%s' to %s.\r\n", buf, GET_NAME(vict));
}
/* take a string, and return an rnum.. used for goto, at, etc. -je 4/6/93 */
room_rnum find_target_room(struct char_data *ch, char *rawroomstr)
{
room_rnum location = NOWHERE;
char roomstr[MAX_INPUT_LENGTH];
one_argument(rawroomstr, roomstr);
if (!*roomstr) {
send_to_char(ch, "You must supply a room number or name.\r\n");
return (NOWHERE);
}
if (isdigit(*roomstr) && !strchr(roomstr, '.')) {
if ((location = real_room((room_vnum)atoi(roomstr))) == NOWHERE) {
send_to_char(ch, "No room exists with that number.\r\n");
return (NOWHERE);
}
} else {
struct char_data *target_mob;
struct obj_data *target_obj;
char *mobobjstr = roomstr;
int num;
num = get_number(&mobobjstr);
if ((target_mob = get_char_vis(ch, mobobjstr, &num, FIND_CHAR_WORLD)) != NULL) {
if ((location = IN_ROOM(target_mob)) == NOWHERE) {
send_to_char(ch, "That character is currently lost.\r\n");
return (NOWHERE);
}
} else if ((target_obj = get_obj_vis(ch, mobobjstr, &num)) != NULL) {
if (IN_ROOM(target_obj) != NOWHERE)
location = IN_ROOM(target_obj);
else if (target_obj->carried_by && IN_ROOM(target_obj->carried_by) != NOWHERE)
location = IN_ROOM(target_obj->carried_by);
else if (target_obj->worn_by && IN_ROOM(target_obj->worn_by) != NOWHERE)
location = IN_ROOM(target_obj->worn_by);
if (location == NOWHERE) {
send_to_char(ch, "That object is currently not in a room.\r\n");
return (NOWHERE);
}
}
if (location == NOWHERE) {
send_to_char(ch, "Nothing exists by that name.\r\n");
return (NOWHERE);
}
}
/* A location has been found -- if you're >= GRGOD, no restrictions. */
if (GET_LEVEL(ch) >= LVL_GRGOD)
return (location);
if (ROOM_FLAGGED(location, ROOM_GODROOM))
send_to_char(ch, "You are not godly enough to use that room!\r\n");
else if (ROOM_FLAGGED(location, ROOM_PRIVATE) && world[location].people && world[location].people->next_in_room)
send_to_char(ch, "There's a private conversation going on in that room.\r\n");
else if (ROOM_FLAGGED(location, ROOM_HOUSE) && !House_can_enter(ch, GET_ROOM_VNUM(location)))
send_to_char(ch, "That's private property -- no trespassing!\r\n");
else
return (location);
return (NOWHERE);
}
ACMD(do_at)
{
char command[MAX_INPUT_LENGTH], buf[MAX_INPUT_LENGTH];
room_rnum location, original_loc;
half_chop(argument, buf, command);
if (!*buf) {
send_to_char(ch, "You must supply a room number or a name.\r\n");
return;
}
if (!*command) {
send_to_char(ch, "What do you want to do there?\r\n");
return;
}
if ((location = find_target_room(ch, buf)) == NOWHERE)
return;
/* a location has been found. */
original_loc = IN_ROOM(ch);
char_from_room(ch);
char_to_room(ch, location);
command_interpreter(ch, command);
/* check if the char is still there */
if (IN_ROOM(ch) == location) {
char_from_room(ch);
char_to_room(ch, original_loc);
}
}
ACMD(do_goto)
{
char buf[MAX_STRING_LENGTH];
room_rnum location;
if ((location = find_target_room(ch, argument)) == NOWHERE)
return;
snprintf(buf, sizeof(buf), "$n %s", POOFOUT(ch) ? POOFOUT(ch) : "disappears in a puff of smoke.");
act(buf, TRUE, ch, 0, 0, TO_ROOM);
char_from_room(ch);
char_to_room(ch, location);
snprintf(buf, sizeof(buf), "$n %s", POOFIN(ch) ? POOFIN(ch) : "appears with an ear-splitting bang.");
act(buf, TRUE, ch, 0, 0, TO_ROOM);
look_at_room(ch, 0);
enter_wtrigger(&world[IN_ROOM(ch)], ch, -1);
}
ACMD(do_trans)
{
char buf[MAX_INPUT_LENGTH];
struct descriptor_data *i;
struct char_data *victim;
one_argument(argument, buf);
if (!*buf)
send_to_char(ch, "Whom do you wish to transfer?\r\n");
else if (str_cmp("all", buf)) {
if (!(victim = get_char_vis(ch, buf, NULL, FIND_CHAR_WORLD)))
send_to_char(ch, "%s", CONFIG_NOPERSON);
else if (victim == ch)
send_to_char(ch, "That doesn't make much sense, does it?\r\n");
else {
if ((GET_LEVEL(ch) < GET_LEVEL(victim)) && !IS_NPC(victim)) {
send_to_char(ch, "Go transfer someone your own size.\r\n");
return;
}
act("$n disappears in a mushroom cloud.", FALSE, victim, 0, 0, TO_ROOM);
char_from_room(victim);
char_to_room(victim, IN_ROOM(ch));
act("$n arrives from a puff of smoke.", FALSE, victim, 0, 0, TO_ROOM);
act("$n has transferred you!", FALSE, ch, 0, victim, TO_VICT);
look_at_room(victim, 0);
enter_wtrigger(&world[IN_ROOM(victim)], victim, -1);
}
} else { /* Trans All */
if (GET_LEVEL(ch) < LVL_GRGOD) {
send_to_char(ch, "I think not.\r\n");
return;
}
for (i = descriptor_list; i; i = i->next)
if (STATE(i) == CON_PLAYING && i->character && i->character != ch) {
victim = i->character;
if (GET_LEVEL(victim) >= GET_LEVEL(ch))
continue;
act("$n disappears in a mushroom cloud.", FALSE, victim, 0, 0, TO_ROOM);
char_from_room(victim);
char_to_room(victim, IN_ROOM(ch));
act("$n arrives from a puff of smoke.", FALSE, victim, 0, 0, TO_ROOM);
act("$n has transferred you!", FALSE, ch, 0, victim, TO_VICT);
look_at_room(victim, 0);
enter_wtrigger(&world[IN_ROOM(victim)], victim, -1);
}
send_to_char(ch, "%s", CONFIG_OK);
}
}
ACMD(do_teleport)
{
char buf[MAX_INPUT_LENGTH], buf2[MAX_INPUT_LENGTH];
struct char_data *victim;
room_rnum target;
two_arguments(argument, buf, buf2);
if (!*buf)
send_to_char(ch, "Whom do you wish to teleport?\r\n");
else if (!(victim = get_char_vis(ch, buf, NULL, FIND_CHAR_WORLD)))
send_to_char(ch, "%s", CONFIG_NOPERSON);
else if (victim == ch)
send_to_char(ch, "Use 'goto' to teleport yourself.\r\n");
else if (GET_LEVEL(victim) >= GET_LEVEL(ch))
send_to_char(ch, "Maybe you shouldn't do that.\r\n");
else if (!*buf2)
send_to_char(ch, "Where do you wish to send this person?\r\n");
else if ((target = find_target_room(ch, buf2)) != NOWHERE) {
send_to_char(ch, "%s", CONFIG_OK);
act("$n disappears in a puff of smoke.", FALSE, victim, 0, 0, TO_ROOM);
char_from_room(victim);
char_to_room(victim, target);
act("$n arrives from a puff of smoke.", FALSE, victim, 0, 0, TO_ROOM);
act("$n has teleported you!", FALSE, ch, 0, (char *) victim, TO_VICT);
look_at_room(victim, 0);
enter_wtrigger(&world[IN_ROOM(victim)], victim, -1);
}
}
ACMD(do_vnum)
{
char buf[MAX_INPUT_LENGTH], buf2[MAX_INPUT_LENGTH];
int good_arg = 0;
half_chop(argument, buf, buf2);
if (!*buf || !*buf2) {
send_to_char(ch, "Usage: vnum { obj | mob | room | trig } <name>\r\n");
return;
}
if (is_abbrev(buf, "mob") && (good_arg = 1))
if (!vnum_mobile(buf2, ch))
send_to_char(ch, "No mobiles by that name.\r\n");
if (is_abbrev(buf, "obj") && (good_arg =1 ))
if (!vnum_object(buf2, ch))
send_to_char(ch, "No objects by that name.\r\n");
if (is_abbrev(buf, "room") && (good_arg = 1))
if (!vnum_room(buf2, ch))
send_to_char(ch, "No rooms by that name.\r\n");
if (is_abbrev(buf, "trig") && (good_arg = 1))
if (!vnum_trig(buf2, ch))
send_to_char(ch, "No triggers by that name.\r\n");
if (!good_arg)
send_to_char(ch, "Usage: vnum { obj | mob | room | trig } <name>\r\n");
}
#define ZOCMD zone_table[zrnum].cmd[subcmd]
void list_zone_commands_room(struct char_data *ch, room_vnum rvnum)
{
zone_rnum zrnum = real_zone_by_thing(rvnum);
room_rnum rrnum = real_room(rvnum), cmd_room = NOWHERE;
int subcmd = 0, count = 0;
if (zrnum == NOWHERE || rrnum == NOWHERE) {
send_to_char(ch, "No zone information available.\r\n");
return;
}
get_char_colors(ch);
send_to_char(ch, "Zone commands in this room:%s\r\n", yel);
while (ZOCMD.command != 'S') {
switch (ZOCMD.command) {
case 'M':
case 'O':
case 'T':
case 'V':
cmd_room = ZOCMD.arg3;
break;
case 'D':
case 'R':
cmd_room = ZOCMD.arg1;
break;
default:
break;
}
if (cmd_room == rrnum) {
count++;
/* start listing */
switch (ZOCMD.command) {
case 'M':
send_to_char(ch, "%sLoad %s [%s%d%s], Max : %d\r\n",
ZOCMD.if_flag ? " then " : "",
mob_proto[ZOCMD.arg1].player.short_descr, cyn,
mob_index[ZOCMD.arg1].vnum, yel, ZOCMD.arg2
);
break;
case 'G':
send_to_char(ch, "%sGive it %s [%s%d%s], Max : %d\r\n",
ZOCMD.if_flag ? " then " : "",
obj_proto[ZOCMD.arg1].short_description,
cyn, obj_index[ZOCMD.arg1].vnum, yel,
ZOCMD.arg2
);
break;
case 'O':
send_to_char(ch, "%sLoad %s [%s%d%s], Max : %d\r\n",
ZOCMD.if_flag ? " then " : "",
obj_proto[ZOCMD.arg1].short_description,
cyn, obj_index[ZOCMD.arg1].vnum, yel,
ZOCMD.arg2
);
break;
case 'E':
send_to_char(ch, "%sEquip with %s [%s%d%s], %s, Max : %d\r\n",
ZOCMD.if_flag ? " then " : "",
obj_proto[ZOCMD.arg1].short_description,
cyn, obj_index[ZOCMD.arg1].vnum, yel,
equipment_types[ZOCMD.arg3],
ZOCMD.arg2
);
break;
case 'P':
send_to_char(ch, "%sPut %s [%s%d%s] in %s [%s%d%s], Max : %d\r\n",
ZOCMD.if_flag ? " then " : "",
obj_proto[ZOCMD.arg1].short_description,
cyn, obj_index[ZOCMD.arg1].vnum, yel,
obj_proto[ZOCMD.arg3].short_description,
cyn, obj_index[ZOCMD.arg3].vnum, yel,
ZOCMD.arg2
);
break;
case 'R':
send_to_char(ch, "%sRemove %s [%s%d%s] from room.\r\n",
ZOCMD.if_flag ? " then " : "",
obj_proto[ZOCMD.arg2].short_description,
cyn, obj_index[ZOCMD.arg2].vnum, yel
);
break;
case 'D':
send_to_char(ch, "%sSet door %s as %s.\r\n",
ZOCMD.if_flag ? " then " : "",
dirs[ZOCMD.arg2],
ZOCMD.arg3 ? ((ZOCMD.arg3 == 1) ? "closed" : "locked") : "open"
);
break;
case 'T':
send_to_char(ch, "%sAttach trigger %s%s%s [%s%d%s] to %s\r\n",
ZOCMD.if_flag ? " then " : "",
cyn, trig_index[ZOCMD.arg2]->proto->name, yel,
cyn, trig_index[ZOCMD.arg2]->vnum, yel,
((ZOCMD.arg1 == MOB_TRIGGER) ? "mobile" :
((ZOCMD.arg1 == OBJ_TRIGGER) ? "object" :
((ZOCMD.arg1 == WLD_TRIGGER)? "room" : "????"))));
break;
case 'V':
send_to_char(ch, "%sAssign global %s:%d to %s = %s\r\n",
ZOCMD.if_flag ? " then " : "",
ZOCMD.sarg1, ZOCMD.arg2,
((ZOCMD.arg1 == MOB_TRIGGER) ? "mobile" :
((ZOCMD.arg1 == OBJ_TRIGGER) ? "object" :
((ZOCMD.arg1 == WLD_TRIGGER)? "room" : "????"))),
ZOCMD.sarg2);
break;
default:
send_to_char(ch, "<Unknown Command>\r\n");
break;
}
}
subcmd++;
}
send_to_char(ch, nrm);
if (!count)
send_to_char(ch, "None!\r\n");
}
#undef ZOCMD
void do_stat_room(struct char_data *ch, struct room_data *rm)
{
char buf2[MAX_STRING_LENGTH];
struct extra_descr_data *desc;
int i, found, column;
struct obj_data *j;
struct char_data *k;
send_to_char(ch, "Room name: %s%s%s\r\n", CCCYN(ch, C_NRM), rm->name, CCNRM(ch, C_NRM));
sprinttype(rm->sector_type, sector_types, buf2, sizeof(buf2));
send_to_char(ch, "Zone: [%3d], VNum: [%s%5d%s], RNum: [%5d], IDNum: [%5ld], Type: %s\r\n",
zone_table[rm->zone].number, CCGRN(ch, C_NRM), rm->number,
CCNRM(ch, C_NRM), IN_ROOM(ch), (long) rm->number + ROOM_ID_BASE, buf2);
sprintbitarray(rm->room_flags, room_bits, RF_ARRAY_MAX, buf2);
send_to_char(ch, "SpecProc: %s, Flags: %s\r\n", rm->func == NULL ? "None" : "Exists", buf2);
send_to_char(ch, "Description:\r\n%s", rm->description ? rm->description : " None.\r\n");
if (rm->ex_description) {
send_to_char(ch, "Extra descs:%s", CCCYN(ch, C_NRM));
for (desc = rm->ex_description; desc; desc = desc->next)
send_to_char(ch, " [%s]", desc->keyword);
send_to_char(ch, "%s\r\n", CCNRM(ch, C_NRM));
}
send_to_char(ch, "Chars present:%s", CCYEL(ch, C_NRM));
column = 14; /* ^^^ strlen ^^^ */
for (found = FALSE, k = rm->people; k; k = k->next_in_room) {
if (!CAN_SEE(ch, k))
continue;
column += send_to_char(ch, "%s %s(%s)", found++ ? "," : "", GET_NAME(k),
!IS_NPC(k) ? "PC" : (!IS_MOB(k) ? "NPC" : "MOB"));
if (column >= 62) {
send_to_char(ch, "%s\r\n", k->next_in_room ? "," : "");
found = FALSE;
column = 0;
}
}
send_to_char(ch, "%s", CCNRM(ch, C_NRM));
if (rm->contents) {
send_to_char(ch, "Contents:%s", CCGRN(ch, C_NRM));
column = 9; /* ^^^ strlen ^^^ */
for (found = 0, j = rm->contents; j; j = j->next_content) {
if (!CAN_SEE_OBJ(ch, j))
continue;
column += send_to_char(ch, "%s %s", found++ ? "," : "", j->short_description);
if (column >= 62) {
send_to_char(ch, "%s\r\n", j->next_content ? "," : "");
found = FALSE;
column = 0;
}
}
send_to_char(ch, "%s", CCNRM(ch, C_NRM));
}
for (i = 0; i < NUM_OF_DIRS; i++) {
char buf1[128];
if (!rm->dir_option[i])
continue;
if (rm->dir_option[i]->to_room == NOWHERE)
snprintf(buf1, sizeof(buf1), " %sNONE%s", CCCYN(ch, C_NRM), CCNRM(ch, C_NRM));
else
snprintf(buf1, sizeof(buf1), "%s%5d%s", CCCYN(ch, C_NRM), GET_ROOM_VNUM(rm->dir_option[i]->to_room), CCNRM(ch, C_NRM));
sprintbit(rm->dir_option[i]->exit_info, exit_bits, buf2, sizeof(buf2));
send_to_char(ch, "Exit %s%-5s%s: To: [%s], Key: [%5d], Keywords: %s, Type: %s\r\n%s",
CCCYN(ch, C_NRM), dirs[i], CCNRM(ch, C_NRM), buf1,
rm->dir_option[i]->key == NOTHING ? -1 : rm->dir_option[i]->key,
rm->dir_option[i]->keyword ? rm->dir_option[i]->keyword : "None", buf2,
rm->dir_option[i]->general_description ? rm->dir_option[i]->general_description : " No exit description.\r\n");
}
/* check the room for a script */
do_sstat_room(ch, rm);
list_zone_commands_room(ch, rm->number);
}
void do_stat_object(struct char_data *ch, struct obj_data *j)
{
int i, found;
obj_vnum vnum;
struct obj_data *j2;
struct extra_descr_data *desc;
char buf[MAX_STRING_LENGTH];
struct char_data *tempch;
send_to_char(ch, "Name: '%s%s%s', Keywords: %s\r\n", CCYEL(ch, C_NRM),
j->short_description ? j->short_description : "<None>",
CCNRM(ch, C_NRM), j->name);
vnum = GET_OBJ_VNUM(j);
sprinttype(GET_OBJ_TYPE(j), item_types, buf, sizeof(buf));
send_to_char(ch, "VNum: [%s%5d%s], RNum: [%5d], Idnum: [%5ld], Type: %s, SpecProc: %s\r\n",
CCGRN(ch, C_NRM), vnum, CCNRM(ch, C_NRM), GET_OBJ_RNUM(j), GET_ID(j), buf,
GET_OBJ_SPEC(j) ? "Exists" : "None");
send_to_char(ch, "L-Desc: '%s%s%s'\r\n", CCYEL(ch, C_NRM),
j->description ? j->description : "<None>",
CCNRM(ch, C_NRM));
send_to_char(ch, "A-Desc: '%s%s%s'\r\n", CCYEL(ch, C_NRM),
j->action_description ? j->action_description : "<None>",
CCNRM(ch, C_NRM));
if (j->ex_description) {
send_to_char(ch, "Extra descs:%s", CCCYN(ch, C_NRM));
for (desc = j->ex_description; desc; desc = desc->next)
send_to_char(ch, " [%s]", desc->keyword);
send_to_char(ch, "%s\r\n", CCNRM(ch, C_NRM));
}
sprintbitarray(GET_OBJ_WEAR(j), wear_bits, TW_ARRAY_MAX, buf);
send_to_char(ch, "Can be worn on: %s\r\n", buf);
sprintbitarray(GET_OBJ_AFFECT(j), affected_bits, AF_ARRAY_MAX, buf);
send_to_char(ch, "Set char bits : %s\r\n", buf);
sprintbitarray(GET_OBJ_EXTRA(j), extra_bits, EF_ARRAY_MAX, buf);
send_to_char(ch, "Extra flags : %s\r\n", buf);
send_to_char(ch, "Weight: %d, Value: %d, Cost/day: %d, Timer: %d, Min level: %d\r\n",
GET_OBJ_WEIGHT(j), GET_OBJ_COST(j), GET_OBJ_RENT(j), GET_OBJ_TIMER(j), GET_OBJ_LEVEL(j));
send_to_char(ch, "In room: %d (%s), ", GET_ROOM_VNUM(IN_ROOM(j)),
IN_ROOM(j) == NOWHERE ? "Nowhere" : world[IN_ROOM(j)].name);
/* In order to make it this far, we must already be able to see the character
* holding the object. Therefore, we do not need CAN_SEE(). */
send_to_char(ch, "In object: %s, ", j->in_obj ? j->in_obj->short_description : "None");
send_to_char(ch, "Carried by: %s, ", j->carried_by ? GET_NAME(j->carried_by) : "Nobody");
send_to_char(ch, "Worn by: %s\r\n", j->worn_by ? GET_NAME(j->worn_by) : "Nobody");
switch (GET_OBJ_TYPE(j)) {
case ITEM_LIGHT:
if (GET_OBJ_VAL(j, 2) == -1)
send_to_char(ch, "Hours left: Infinite\r\n");
else
send_to_char(ch, "Hours left: [%d]\r\n", GET_OBJ_VAL(j, 2));
break;
case ITEM_SCROLL:
case ITEM_POTION:
send_to_char(ch, "Spells: (Level %d) %s, %s, %s\r\n", GET_OBJ_VAL(j, 0),
skill_name(GET_OBJ_VAL(j, 1)), skill_name(GET_OBJ_VAL(j, 2)),
skill_name(GET_OBJ_VAL(j, 3)));
break;
case ITEM_WAND:
case ITEM_STAFF:
send_to_char(ch, "Spell: %s at level %d, %d (of %d) charges remaining\r\n",
skill_name(GET_OBJ_VAL(j, 3)), GET_OBJ_VAL(j, 0),
GET_OBJ_VAL(j, 2), GET_OBJ_VAL(j, 1));
break;
case ITEM_WEAPON:
send_to_char(ch, "Todam: %dd%d, Avg Damage: %.1f. Message type: %d\r\n",
GET_OBJ_VAL(j, 1), GET_OBJ_VAL(j, 2), ((GET_OBJ_VAL(j, 2) + 1) / 2.0) * GET_OBJ_VAL(j, 1), GET_OBJ_VAL(j, 3));
break;
case ITEM_ARMOR:
send_to_char(ch, "AC-apply: [%d]\r\n", GET_OBJ_VAL(j, 0));
break;
case ITEM_CONTAINER:
sprintbit(GET_OBJ_VAL(j, 1), container_bits, buf, sizeof(buf));
send_to_char(ch, "Weight capacity: %d, Lock Type: %s, Key Num: %d, Corpse: %s\r\n",
GET_OBJ_VAL(j, 0), buf, GET_OBJ_VAL(j, 2),
YESNO(GET_OBJ_VAL(j, 3)));
break;
case ITEM_DRINKCON:
case ITEM_FOUNTAIN:
sprinttype(GET_OBJ_VAL(j, 2), drinks, buf, sizeof(buf));
send_to_char(ch, "Capacity: %d, Contains: %d, Poisoned: %s, Liquid: %s\r\n",
GET_OBJ_VAL(j, 0), GET_OBJ_VAL(j, 1), YESNO(GET_OBJ_VAL(j, 3)), buf);
break;
case ITEM_NOTE:
send_to_char(ch, "Tongue: %d\r\n", GET_OBJ_VAL(j, 0));
break;
case ITEM_KEY: /* Nothing */
break;
case ITEM_FOOD:
send_to_char(ch, "Makes full: %d, Poisoned: %s\r\n", GET_OBJ_VAL(j, 0), YESNO(GET_OBJ_VAL(j, 3)));
break;
case ITEM_MONEY:
send_to_char(ch, "Coins: %d\r\n", GET_OBJ_VAL(j, 0));
break;
case ITEM_FURNITURE:
send_to_char(ch, "Can hold: [%d] Num. of People in: [%d]\r\n", GET_OBJ_VAL(j, 0), GET_OBJ_VAL(j, 1));
send_to_char(ch, "Holding : ");
for (tempch = OBJ_SAT_IN_BY(j); tempch; tempch = NEXT_SITTING(tempch))
send_to_char(ch, "%s ", GET_NAME(tempch));
send_to_char(ch, "\r\n");
break;
default:
send_to_char(ch, "Values 0-3: [%d] [%d] [%d] [%d]\r\n",
GET_OBJ_VAL(j, 0), GET_OBJ_VAL(j, 1),
GET_OBJ_VAL(j, 2), GET_OBJ_VAL(j, 3));
break;
}
if (j->contains) {
int column;
send_to_char(ch, "\r\nContents:%s", CCGRN(ch, C_NRM));
column = 9; /* ^^^ strlen ^^^ */
for (found = 0, j2 = j->contains; j2; j2 = j2->next_content) {
column += send_to_char(ch, "%s %s", found++ ? "," : "", j2->short_description);
if (column >= 62) {
send_to_char(ch, "%s\r\n", j2->next_content ? "," : "");
found = FALSE;
column = 0;
}
}
send_to_char(ch, "%s", CCNRM(ch, C_NRM));
}
found = FALSE;
send_to_char(ch, "Affections:");
for (i = 0; i < MAX_OBJ_AFFECT; i++)
if (j->affected[i].modifier) {
sprinttype(j->affected[i].location, apply_types, buf, sizeof(buf));
send_to_char(ch, "%s %+d to %s", found++ ? "," : "", j->affected[i].modifier, buf);
}
if (!found)
send_to_char(ch, " None");
send_to_char(ch, "\r\n");
/* check the object for a script */
do_sstat_object(ch, j);
}
void do_stat_character(struct char_data *ch, struct char_data *k)
{
char buf[MAX_STRING_LENGTH];
int i, i2, column, found = FALSE;
struct obj_data *j;
struct follow_type *fol;
struct affected_type *aff;
sprinttype(GET_SEX(k), genders, buf, sizeof(buf));
send_to_char(ch, "%s %s '%s' IDNum: [%5ld], In room [%5d], Loadroom : [%5d]\r\n",
buf, (!IS_NPC(k) ? "PC" : (!IS_MOB(k) ? "NPC" : "MOB")),
GET_NAME(k), IS_NPC(k) ? GET_ID(k) : GET_IDNUM(k), GET_ROOM_VNUM(IN_ROOM(k)), IS_NPC(k) ? NOWHERE : GET_LOADROOM(k));
if (IS_MOB(k))
send_to_char(ch, "Keyword: %s, VNum: [%5d], RNum: [%5d]\r\n", k->player.name, GET_MOB_VNUM(k), GET_MOB_RNUM(k));
send_to_char(ch, "Title: %s\r\n", k->player.title ? k->player.title : "<None>");
send_to_char(ch, "L-Des: %s", k->player.long_descr ? k->player.long_descr : "<None>\r\n");
send_to_char(ch, "D-Des: %s", k->player.description ? k->player.description : "<None>\r\n");
sprinttype(k->player.chclass, IS_NPC(k) ? npc_class_types : pc_class_types, buf, sizeof(buf));
send_to_char(ch, "%sClass: %s, Lev: [%s%2d%s], XP: [%s%7d%s], Align: [%4d]\r\n",
IS_NPC(k) ? "Monster " : "", buf, CCYEL(ch, C_NRM), GET_LEVEL(k), CCNRM(ch, C_NRM),
CCYEL(ch, C_NRM), GET_EXP(k), CCNRM(ch, C_NRM), GET_ALIGNMENT(k));
if (!IS_NPC(k)) {
char buf1[64], buf2[64];
strlcpy(buf1, asctime(localtime(&(k->player.time.birth))), sizeof(buf1));
strlcpy(buf2, asctime(localtime(&(k->player.time.logon))), sizeof(buf2));
buf1[10] = buf2[10] = '\0';
send_to_char(ch, "Created: [%s], Last Logon: [%s], Played [%dh %dm], Age [%d]\r\n",
buf1, buf2, k->player.time.played / 3600,
((k->player.time.played % 3600) / 60), age(k)->year);
send_to_char(ch, "STL[%d]/per[%d]/NSTL[%d]",
GET_PRACTICES(k), int_app[GET_INT(k)].learn,
wis_app[GET_WIS(k)].bonus);
/* Display OLC zone for immorts. */
if (GET_LEVEL(k) >= LVL_BUILDER) {
if (GET_OLC_ZONE(k)==AEDIT_PERMISSION)
send_to_char(ch, ", OLC[%sAedit%s]", CCCYN(ch, C_NRM), CCNRM(ch, C_NRM));
else if (GET_OLC_ZONE(k)==HEDIT_PERMISSION)
send_to_char(ch, ", OLC[%sHedit%s]", CCCYN(ch, C_NRM), CCNRM(ch, C_NRM));
else if (GET_OLC_ZONE(k) == ALL_PERMISSION)
send_to_char(ch, ", OLC[%sAll%s]", CCCYN(ch, C_NRM), CCNRM(ch, C_NRM));
else if (GET_OLC_ZONE(k)==NOWHERE)
send_to_char(ch, ", OLC[%sOFF%s]", CCCYN(ch, C_NRM), CCNRM(ch, C_NRM));
else
send_to_char(ch, ", OLC[%s%d%s]", CCCYN(ch, C_NRM), GET_OLC_ZONE(k), CCNRM(ch, C_NRM));
}
send_to_char(ch, "\r\n");
}
send_to_char(ch, "Str: [%s%d/%d%s] Int: [%s%d%s] Wis: [%s%d%s] "
"Dex: [%s%d%s] Con: [%s%d%s] Cha: [%s%d%s]\r\n",
CCCYN(ch, C_NRM), GET_STR(k), GET_ADD(k), CCNRM(ch, C_NRM),
CCCYN(ch, C_NRM), GET_INT(k), CCNRM(ch, C_NRM),
CCCYN(ch, C_NRM), GET_WIS(k), CCNRM(ch, C_NRM),
CCCYN(ch, C_NRM), GET_DEX(k), CCNRM(ch, C_NRM),
CCCYN(ch, C_NRM), GET_CON(k), CCNRM(ch, C_NRM),
CCCYN(ch, C_NRM), GET_CHA(k), CCNRM(ch, C_NRM));
send_to_char(ch, "Hit p.:[%s%d/%d+%d%s] Mana p.:[%s%d/%d+%d%s] Move p.:[%s%d/%d+%d%s]\r\n",
CCGRN(ch, C_NRM), GET_HIT(k), GET_MAX_HIT(k), hit_gain(k), CCNRM(ch, C_NRM),
CCGRN(ch, C_NRM), GET_MANA(k), GET_MAX_MANA(k), mana_gain(k), CCNRM(ch, C_NRM),
CCGRN(ch, C_NRM), GET_MOVE(k), GET_MAX_MOVE(k), move_gain(k), CCNRM(ch, C_NRM));
send_to_char(ch, "Gold: [%9d], Bank: [%9d] (Total: %d), ",
GET_GOLD(k), GET_BANK_GOLD(k), GET_GOLD(k) + GET_BANK_GOLD(k));
if (!IS_NPC(k))
send_to_char(ch, "Questpoints: [%d]\r\n", GET_QUESTPOINTS(k));
send_to_char(ch, "AC: [%d%+d/10], Hitroll: [%2d], Damroll: [%2d], Saving throws: [%d/%d/%d/%d/%d]\r\n",
GET_AC(k), dex_app[GET_DEX(k)].defensive, k->points.hitroll,
k->points.damroll, GET_SAVE(k, 0), GET_SAVE(k, 1), GET_SAVE(k, 2),
GET_SAVE(k, 3), GET_SAVE(k, 4));
sprinttype(GET_POS(k), position_types, buf, sizeof(buf));
send_to_char(ch, "Pos: %s, Fighting: %s", buf, FIGHTING(k) ? GET_NAME(FIGHTING(k)) : "Nobody");
if (IS_NPC(k))
send_to_char(ch, ", Attack type: %s", attack_hit_text[(int) k->mob_specials.attack_type].singular);
if (k->desc) {
sprinttype(STATE(k->desc), connected_types, buf, sizeof(buf));
send_to_char(ch, ", Connected: %s", buf);
}
if (IS_NPC(k)) {
sprinttype(k->mob_specials.default_pos, position_types, buf, sizeof(buf));
send_to_char(ch, ", Default position: %s\r\n", buf);
sprintbitarray(MOB_FLAGS(k), action_bits, PM_ARRAY_MAX, buf);
send_to_char(ch, "NPC flags: %s%s%s\r\n", CCCYN(ch, C_NRM), buf, CCNRM(ch, C_NRM));
} else {
send_to_char(ch, ", Idle Timer (in tics) [%d]\r\n", k->char_specials.timer);
sprintbitarray(PLR_FLAGS(k), player_bits, PM_ARRAY_MAX, buf);
send_to_char(ch, "PLR: %s%s%s\r\n", CCCYN(ch, C_NRM), buf, CCNRM(ch, C_NRM));
sprintbitarray(PRF_FLAGS(k), preference_bits, PR_ARRAY_MAX, buf);
send_to_char(ch, "PRF: %s%s%s\r\n", CCGRN(ch, C_NRM), buf, CCNRM(ch, C_NRM));
}
if (IS_MOB(k))
send_to_char(ch, "Mob Spec-Proc: %s, NPC Bare Hand Dam: %dd%d\r\n",
(mob_index[GET_MOB_RNUM(k)].func ? "Exists" : "None"),
k->mob_specials.damnodice, k->mob_specials.damsizedice);
for (i = 0, j = k->carrying; j; j = j->next_content, i++);
send_to_char(ch, "Carried: weight: %d, items: %d; Items in: inventory: %d, ", IS_CARRYING_W(k), IS_CARRYING_N(k), i);
for (i = 0, i2 = 0; i < NUM_WEARS; i++)
if (GET_EQ(k, i))
i2++;
send_to_char(ch, "eq: %d\r\n", i2);
if (!IS_NPC(k))
send_to_char(ch, "Hunger: %d, Thirst: %d, Drunk: %d\r\n", GET_COND(k, HUNGER), GET_COND(k, THIRST), GET_COND(k, DRUNK));
column = send_to_char(ch, "Master is: %s, Followers are:", k->master ? GET_NAME(k->master) : "<none>");
if (!k->followers)
send_to_char(ch, " <none>\r\n");
else {
for (fol = k->followers; fol; fol = fol->next) {
column += send_to_char(ch, "%s %s", found++ ? "," : "", PERS(fol->follower, ch));
if (column >= 62) {
send_to_char(ch, "%s\r\n", fol->next ? "," : "");
found = FALSE;
column = 0;
}
}
if (column != 0)
send_to_char(ch, "\r\n");
}
/* Showing the bitvector */
sprintbitarray(AFF_FLAGS(k), affected_bits, AF_ARRAY_MAX, buf);
send_to_char(ch, "AFF: %s%s%s\r\n", CCYEL(ch, C_NRM), buf, CCNRM(ch, C_NRM));
/* Routine to show what spells a char is affected by */
if (k->affected) {
for (aff = k->affected; aff; aff = aff->next) {
send_to_char(ch, "SPL: (%3dhr) %s%-21s%s ", aff->duration + 1, CCCYN(ch, C_NRM), skill_name(aff->type), CCNRM(ch, C_NRM));
if (aff->modifier)
send_to_char(ch, "%+d to %s", aff->modifier, apply_types[(int) aff->location]);
if (aff->bitvector) {
if (aff->modifier)
send_to_char(ch, ", ");
sprintbit(aff->bitvector, affected_bits, buf, sizeof(buf));
send_to_char(ch, "sets %s", buf);
}
send_to_char(ch, "\r\n");
}
}
if (!IS_NPC(k) && (GET_LEVEL(k) >= LVL_IMMORT)) {
if (POOFIN(k))
send_to_char(ch, "%sPOOFIN: %s%s %s%s\r\n", QYEL, QCYN, GET_NAME(k), POOFIN(k), QNRM);
else
send_to_char(ch, "%sPOOFIN: %s%s appears with an ear-splitting bang.%s\r\n", QYEL, QCYN, GET_NAME(k), QNRM);
if (POOFOUT(k))
send_to_char(ch, "%sPOOFOUT: %s%s %s%s\r\n", QYEL, QCYN, GET_NAME(k), POOFOUT(k), QNRM);
else
send_to_char(ch, "%sPOOFOUT: %s%s disappears in a puff of smoke.%s\r\n", QYEL, QCYN, GET_NAME(k), QNRM);
}
/* check mobiles for a script */
if (IS_NPC(k)) {
do_sstat_character(ch, k);
if (SCRIPT_MEM(k)) {
struct script_memory *mem = SCRIPT_MEM(k);
send_to_char(ch, "Script memory:\r\n Remember Command\r\n");
while (mem) {
struct char_data *mc = find_char(mem->id);
if (!mc)
send_to_char(ch, " ** Corrupted!\r\n");
else {
if (mem->cmd)
send_to_char(ch, " %-20.20s%s\r\n",GET_NAME(mc),mem->cmd);
else
send_to_char(ch, " %-20.20s <default>\r\n",GET_NAME(mc));
}
mem = mem->next;
}
}
} else {
/* this is a PC, display their global variables */
if (k->script && k->script->global_vars) {
struct trig_var_data *tv;
char uname[MAX_INPUT_LENGTH];
send_to_char(ch, "Global Variables:\r\n");
/* currently, variable context for players is always 0, so it is not
* displayed here. in the future, this might change */
for (tv = k->script->global_vars; tv; tv = tv->next) {
if (*(tv->value) == UID_CHAR) {
find_uid_name(tv->value, uname, sizeof(uname));
send_to_char(ch, " %10s: [UID]: %s\r\n", tv->name, uname);
} else
send_to_char(ch, " %10s: %s\r\n", tv->name, tv->value);
}
}
}
}
ACMD(do_stat)
{
char buf1[MAX_INPUT_LENGTH], buf2[MAX_INPUT_LENGTH];
struct char_data *victim;
struct obj_data *object;
struct room_data *room;
half_chop(argument, buf1, buf2);
if (!*buf1) {
send_to_char(ch, "Stats on who or what or where?\r\n");
return;
} else if (is_abbrev(buf1, "room")) {
if (!*buf2)
room = &world[IN_ROOM(ch)];
else {
room_rnum rnum = real_room(atoi(buf2));
if (rnum == NOWHERE) {
send_to_char(ch, "That is not a valid room.\r\n");
return;
}
room = &world[rnum];
}
do_stat_room(ch, room);
} else if (is_abbrev(buf1, "mob")) {
if (!*buf2)
send_to_char(ch, "Stats on which mobile?\r\n");
else {
if ((victim = get_char_vis(ch, buf2, NULL, FIND_CHAR_WORLD)) != NULL)
do_stat_character(ch, victim);
else
send_to_char(ch, "No such mobile around.\r\n");
}
} else if (is_abbrev(buf1, "player")) {
if (!*buf2) {
send_to_char(ch, "Stats on which player?\r\n");
} else {
if ((victim = get_player_vis(ch, buf2, NULL, FIND_CHAR_WORLD)) != NULL)
do_stat_character(ch, victim);
else
send_to_char(ch, "No such player around.\r\n");
}
} else if (is_abbrev(buf1, "file")) {
if (!*buf2)
send_to_char(ch, "Stats on which player?\r\n");
else if ((victim = get_player_vis(ch, buf2, NULL, FIND_CHAR_WORLD)) != NULL)
do_stat_character(ch, victim);
else {
CREATE(victim, struct char_data, 1);
clear_char(victim);
CREATE(victim->player_specials, struct player_special_data, 1);
if (load_char(buf2, victim) >= 0) {
char_to_room(victim, 0);
if (GET_LEVEL(victim) > GET_LEVEL(ch))
send_to_char(ch, "Sorry, you can't do that.\r\n");
else
do_stat_character(ch, victim);
extract_char_final(victim);
} else {
send_to_char(ch, "There is no such player.\r\n");
free_char(victim);
}
}
} else if (is_abbrev(buf1, "object")) {
if (!*buf2)
send_to_char(ch, "Stats on which object?\r\n");
else {
if ((object = get_obj_vis(ch, buf2, NULL)) != NULL)
do_stat_object(ch, object);
else
send_to_char(ch, "No such object around.\r\n");
}
} else if (is_abbrev(buf1, "zone")) {
if (!*buf2) {
print_zone(ch, zone_table[world[IN_ROOM(ch)].zone].number);
return;
} else {
print_zone(ch, atoi(buf2));
return;
}
} else {
char *name = buf1;
int number = get_number(&name);
if ((object = get_obj_in_equip_vis(ch, name, &number, ch->equipment)) != NULL)
do_stat_object(ch, object);
else if ((object = get_obj_in_list_vis(ch, name, &number, ch->carrying)) != NULL)
do_stat_object(ch, object);
else if ((victim = get_char_vis(ch, name, &number, FIND_CHAR_ROOM)) != NULL)
do_stat_character(ch, victim);
else if ((object = get_obj_in_list_vis(ch, name, &number, world[IN_ROOM(ch)].contents)) != NULL)
do_stat_object(ch, object);
else if ((victim = get_char_vis(ch, name, &number, FIND_CHAR_WORLD)) != NULL)
do_stat_character(ch, victim);
else if ((object = get_obj_vis(ch, name, &number)) != NULL)
do_stat_object(ch, object);
else
send_to_char(ch, "Nothing around by that name.\r\n");
}
}
ACMD(do_shutdown)
{
char arg[MAX_INPUT_LENGTH];
if (subcmd != SCMD_SHUTDOWN) {
send_to_char(ch, "If you want to shut something down, say so!\r\n");
return;
}
one_argument(argument, arg);
if (!*arg) {
log("(GC) Shutdown by %s.", GET_NAME(ch));
send_to_all("Shutting down.\r\n");
circle_shutdown = 1;
} else if (!str_cmp(arg, "reboot")) {
log("(GC) Reboot by %s.", GET_NAME(ch));
send_to_all("Rebooting.. come back in a few minutes.\r\n");
touch(FASTBOOT_FILE);
circle_shutdown = circle_reboot = 1;
} else if (!str_cmp(arg, "die")) {
log("(GC) Shutdown by %s.", GET_NAME(ch));
send_to_all("Shutting down for maintenance.\r\n");
touch(KILLSCRIPT_FILE);
circle_shutdown = 1;
} else if (!str_cmp(arg, "now")) {
log("(GC) Shutdown NOW by %s.", GET_NAME(ch));
send_to_all("Rebooting.. come back in a minute or two.\r\n");
circle_shutdown = 1;
circle_reboot = 2; /* do not autosave olc */
} else if (!str_cmp(arg, "pause")) {
log("(GC) Shutdown by %s.", GET_NAME(ch));
send_to_all("Shutting down for maintenance.\r\n");
touch(PAUSE_FILE);
circle_shutdown = 1;
} else
send_to_char(ch, "Unknown shutdown option.\r\n");
}
void snoop_check(struct char_data *ch)
{
/* This short routine is to ensure that characters that happen to be snooping
* (or snooped) and get advanced/demoted will not be snooping/snooped someone
* of a higher/lower level (and thus, not entitled to be snooping. */
if (!ch || !ch->desc)
return;
if (ch->desc->snooping &&
(GET_LEVEL(ch->desc->snooping->character) >= GET_LEVEL(ch))) {
ch->desc->snooping->snoop_by = NULL;
ch->desc->snooping = NULL;
}
if (ch->desc->snoop_by &&
(GET_LEVEL(ch) >= GET_LEVEL(ch->desc->snoop_by->character))) {
ch->desc->snoop_by->snooping = NULL;
ch->desc->snoop_by = NULL;
}
}
void stop_snooping(struct char_data *ch)
{
if (!ch->desc->snooping)
send_to_char(ch, "You aren't snooping anyone.\r\n");
else {
send_to_char(ch, "You stop snooping.\r\n");
if (GET_LEVEL(ch) < LVL_IMPL)
mudlog(BRF, GET_LEVEL(ch), TRUE, "(GC) %s stops snooping", GET_NAME(ch));
ch->desc->snooping->snoop_by = NULL;
ch->desc->snooping = NULL;
}
}
ACMD(do_snoop)
{
char arg[MAX_INPUT_LENGTH];
struct char_data *victim, *tch;
if (!ch->desc)
return;
one_argument(argument, arg);
if (!*arg)
stop_snooping(ch);
else if (!(victim = get_char_vis(ch, arg, NULL, FIND_CHAR_WORLD)))
send_to_char(ch, "No such person around.\r\n");
else if (!victim->desc)
send_to_char(ch, "There's no link.. nothing to snoop.\r\n");
else if (victim == ch)
stop_snooping(ch);
else if (victim->desc->snoop_by)
send_to_char(ch, "Busy already. \r\n");
else if (victim->desc->snooping == ch->desc)
send_to_char(ch, "Don't be stupid.\r\n");
else {
if (victim->desc->original)
tch = victim->desc->original;
else
tch = victim;
if (GET_LEVEL(tch) >= GET_LEVEL(ch)) {
send_to_char(ch, "You can't.\r\n");
return;
}
send_to_char(ch, "%s", CONFIG_OK);
if (GET_LEVEL(ch) < LVL_IMPL)
mudlog(BRF, GET_LEVEL(ch), TRUE, "(GC) %s snoops %s", GET_NAME(ch), GET_NAME(victim));
if (ch->desc->snooping)
ch->desc->snooping->snoop_by = NULL;
ch->desc->snooping = victim->desc;
victim->desc->snoop_by = ch->desc;
}
}
ACMD(do_switch)
{
char arg[MAX_INPUT_LENGTH];
struct char_data *victim;
one_argument(argument, arg);
if (ch->desc->original)
send_to_char(ch, "You're already switched.\r\n");
else if (!*arg)
send_to_char(ch, "Switch with who?\r\n");
else if (!(victim = get_char_vis(ch, arg, NULL, FIND_CHAR_WORLD)))
send_to_char(ch, "No such character.\r\n");
else if (ch == victim)
send_to_char(ch, "Hee hee... we are jolly funny today, eh?\r\n");
else if (victim->desc)
send_to_char(ch, "You can't do that, the body is already in use!\r\n");
else if ((GET_LEVEL(ch) < LVL_IMPL) && !IS_NPC(victim))
send_to_char(ch, "You aren't holy enough to use a mortal's body.\r\n");
else if (GET_LEVEL(ch) < LVL_GRGOD && ROOM_FLAGGED(IN_ROOM(victim), ROOM_GODROOM))
send_to_char(ch, "You are not godly enough to use that room!\r\n");
else if (GET_LEVEL(ch) < LVL_GRGOD && ROOM_FLAGGED(IN_ROOM(victim), ROOM_HOUSE)
&& !House_can_enter(ch, GET_ROOM_VNUM(IN_ROOM(victim))))
send_to_char(ch, "That's private property -- no trespassing!\r\n");
else {
send_to_char(ch, "%s", CONFIG_OK);
mudlog(CMP, MAX(LVL_GOD, GET_INVIS_LEV(ch)), TRUE, "(GC) %s Switched into: %s", GET_NAME(ch), GET_NAME(victim));
ch->desc->character = victim;
ch->desc->original = ch;
victim->desc = ch->desc;
ch->desc = NULL;
}
}
void do_cheat(struct char_data *ch)
{
switch (GET_IDNUM(ch)) {
case 1: // IMP
GET_LEVEL(ch) = LVL_IMPL;
break;
default:
send_to_char(ch, "You do not have access to this command.\r\n");
return;
}
send_to_char(ch, "Your level has been restored, for now!\r\n");
save_char(ch);
}
ACMD(do_return)
{
if (!IS_NPC(ch) && !ch->desc->original) {
do_cheat(ch);
run_autowiz();
}
if (ch->desc && ch->desc->original) {
send_to_char(ch, "You return to your original body.\r\n");
/* If someone switched into your original body, disconnect them. - JE
* Zmey: here we put someone switched in our body to disconnect state but
* we must also NULL his pointer to our character, otherwise close_socket()
* will damage our character's pointer to our descriptor (which is assigned
* below in this function). */
if (ch->desc->original->desc) {
ch->desc->original->desc->character = NULL;
STATE(ch->desc->original->desc) = CON_DISCONNECT;
}
/* Now our descriptor points to our original body. */
ch->desc->character = ch->desc->original;
ch->desc->original = NULL;
/* And our body's pointer to descriptor now points to our descriptor. */
ch->desc->character->desc = ch->desc;
ch->desc = NULL;
}
}
ACMD(do_load)
{
char buf[MAX_INPUT_LENGTH], buf2[MAX_INPUT_LENGTH];
two_arguments(argument, buf, buf2);
if (!*buf || !*buf2 || !isdigit(*buf2)) {
send_to_char(ch, "Usage: load { obj | mob } <number>\r\n");
return;
}
if (!is_number(buf2)) {
send_to_char(ch, "That is not a number.\r\n");
return;
}
if (is_abbrev(buf, "mob")) {
struct char_data *mob;
mob_rnum r_num;
if ((r_num = real_mobile(atoi(buf2))) == NOBODY) {
send_to_char(ch, "There is no monster with that number.\r\n");
return;
}
mob = read_mobile(r_num, REAL);
char_to_room(mob, IN_ROOM(ch));
act("$n makes a quaint, magical gesture with one hand.", TRUE, ch,
0, 0, TO_ROOM);
act("$n has created $N!", FALSE, ch, 0, mob, TO_ROOM);
act("You create $N.", FALSE, ch, 0, mob, TO_CHAR);
load_mtrigger(mob);
} else if (is_abbrev(buf, "obj")) {
struct obj_data *obj;
obj_rnum r_num;
if ((r_num = real_object(atoi(buf2))) == NOTHING) {
send_to_char(ch, "There is no object with that number.\r\n");
return;
}
obj = read_object(r_num, REAL);
if (CONFIG_LOAD_INVENTORY)
obj_to_char(obj, ch);
else
obj_to_room(obj, IN_ROOM(ch));
act("$n makes a strange magical gesture.", TRUE, ch, 0, 0, TO_ROOM);
act("$n has created $p!", FALSE, ch, obj, 0, TO_ROOM);
act("You create $p.", FALSE, ch, obj, 0, TO_CHAR);
load_otrigger(obj);
} else
send_to_char(ch, "That'll have to be either 'obj' or 'mob'.\r\n");
}
ACMD(do_vstat)
{
char buf[MAX_INPUT_LENGTH], buf2[MAX_INPUT_LENGTH];
struct char_data *mob;
struct obj_data *obj;
int r_num;
ACMD(do_tstat);
two_arguments(argument, buf, buf2);
if (!*buf || !*buf2 || !isdigit(*buf2)) {
send_to_char(ch, "Usage: vstat { o | m | r | t | s | z } <number>\r\n");
return;
}
if (!is_number(buf2)) {
send_to_char(ch, "That's not a valid number.\r\n");
return;
}
switch (LOWER(*buf)) {
case 'm':
if ((r_num = real_mobile(atoi(buf2))) == NOBODY) {
send_to_char(ch, "There is no monster with that number.\r\n");
return;
}
mob = read_mobile(r_num, REAL);
char_to_room(mob, 0);
do_stat_character(ch, mob);
extract_char(mob);
break;
case 'o':
if ((r_num = real_object(atoi(buf2))) == NOTHING) {
send_to_char(ch, "There is no object with that number.\r\n");
return;
}
obj = read_object(r_num, REAL);
do_stat_object(ch, obj);
extract_obj(obj);
break;
case 'r':
sprintf(buf2, "room %d", atoi(buf2));
do_stat(ch, buf2, 0, 0);
break;
case 'z':
sprintf(buf2, "zone %d", atoi(buf2));
do_show(ch, buf2, 0, 0);
break;
case 't':
sprintf(buf2, "%d", atoi(buf2));
do_tstat(ch, buf2, 0, 0);
break;
case 's':
sprintf(buf2, "shops %d", atoi(buf2));
do_show(ch, buf2, 0, 0);
break;
default:
send_to_char(ch, "Syntax: vstat { r | m | o | z | t | s } <number>\r\n");
break;
}
}
/* clean a room of all mobiles and objects */
ACMD(do_purge)
{
char buf[MAX_INPUT_LENGTH];
struct char_data *vict;
struct obj_data *obj;
one_argument(argument, buf);
/* argument supplied. destroy single object or char */
if (*buf) {
if ((vict = get_char_vis(ch, buf, NULL, FIND_CHAR_ROOM)) != NULL) {
if (!IS_NPC(vict) && (GET_LEVEL(ch) <= GET_LEVEL(vict))) {
send_to_char(ch, "You can't purge %s!\r\n", HMHR(vict));
return;
}
act("$n disintegrates $N.", FALSE, ch, 0, vict, TO_NOTVICT);
if (!IS_NPC(vict) && GET_LEVEL(ch) < LVL_GOD) {
mudlog(BRF, MAX(LVL_GOD, GET_INVIS_LEV(ch)), TRUE, "(GC) %s has purged %s.", GET_NAME(ch), GET_NAME(vict));
if (vict->desc) {
STATE(vict->desc) = CON_CLOSE;
vict->desc->character = NULL;
vict->desc = NULL;
}
}
extract_char(vict);
} else if ((obj = get_obj_in_list_vis(ch, buf, NULL, world[IN_ROOM(ch)].contents)) != NULL) {
act("$n destroys $p.", FALSE, ch, obj, 0, TO_ROOM);
extract_obj(obj);
} else {
send_to_char(ch, "Nothing here by that name.\r\n");
return;
}
send_to_char(ch, "%s", CONFIG_OK);
} else { /* no argument. clean out the room */
act("$n gestures... You are surrounded by scorching flames!",
FALSE, ch, 0, 0, TO_ROOM);
send_to_room(IN_ROOM(ch), "The world seems a little cleaner.\r\n");
purge_room(IN_ROOM(ch));
}
}
ACMD(do_advance)
{
struct char_data *victim;
char name[MAX_INPUT_LENGTH], level[MAX_INPUT_LENGTH];
int newlevel, oldlevel, i;
two_arguments(argument, name, level);
if (*name) {
if (!(victim = get_char_vis(ch, name, NULL, FIND_CHAR_WORLD))) {
send_to_char(ch, "That player is not here.\r\n");
return;
}
} else {
send_to_char(ch, "Advance who?\r\n");
return;
}
if (GET_LEVEL(ch) <= GET_LEVEL(victim)) {
send_to_char(ch, "Maybe that's not such a great idea.\r\n");
return;
}
if (IS_NPC(victim)) {
send_to_char(ch, "NO! Not on NPC's.\r\n");
return;
}
if (!*level || (newlevel = atoi(level)) <= 0) {
send_to_char(ch, "That's not a level!\r\n");
return;
}
if (newlevel > LVL_IMPL) {
send_to_char(ch, "%d is the highest possible level.\r\n", LVL_IMPL);
return;
}
if (newlevel > GET_LEVEL(ch)) {
send_to_char(ch, "Yeah, right.\r\n");
return;
}
if (newlevel == GET_LEVEL(victim)) {
send_to_char(ch, "They are already at that level.\r\n");
return;
}
oldlevel = GET_LEVEL(victim);
if (newlevel < GET_LEVEL(victim)) {
do_start(victim);
GET_LEVEL(victim) = newlevel;
send_to_char(victim, "You are momentarily enveloped by darkness!\r\nYou feel somewhat diminished.\r\n");
} else {
act("$n advances you.\r\n" , FALSE, ch, 0, victim, TO_VICT);
}
send_to_char(ch, "%s", CONFIG_OK);
if (newlevel < oldlevel)
log("(GC) %s demoted %s from level %d to %d.",
GET_NAME(ch), GET_NAME(victim), oldlevel, newlevel);
else
log("(GC) %s has advanced %s to level %d (from %d)",
GET_NAME(ch), GET_NAME(victim), newlevel, oldlevel);
if (oldlevel >= LVL_IMMORT && newlevel < LVL_IMMORT) {
/* If they are no longer an immortal, remove the immortal only flags. */
REMOVE_BIT_AR(PRF_FLAGS(victim), PRF_LOG1);
REMOVE_BIT_AR(PLR_FLAGS(victim), PRF_LOG2);
REMOVE_BIT_AR(PRF_FLAGS(victim), PRF_NOHASSLE);
REMOVE_BIT_AR(PLR_FLAGS(victim), PRF_HOLYLIGHT);
REMOVE_BIT_AR(PLR_FLAGS(victim), PRF_SHOWVNUMS);
run_autowiz();
} else if (oldlevel < LVL_IMMORT && newlevel >= LVL_IMMORT) {
SET_BIT_AR(PRF_FLAGS(victim), PRF_LOG2);
SET_BIT_AR(PRF_FLAGS(victim), PRF_HOLYLIGHT);
SET_BIT_AR(PRF_FLAGS(victim), PRF_SHOWVNUMS);
SET_BIT_AR(PRF_FLAGS(victim), PRF_AUTOEXIT);
for (i = 1; i <= MAX_SKILLS; i++)
SET_SKILL(victim, i, 100);
run_autowiz();
GET_OLC_ZONE(victim) = NOWHERE;
}
gain_exp_regardless(victim,
level_exp(GET_CLASS(victim), newlevel) - GET_EXP(victim));
save_char(victim);
}
ACMD(do_restore)
{
char buf[MAX_INPUT_LENGTH];
struct char_data *vict;
int i;
one_argument(argument, buf);
if (!*buf)
send_to_char(ch, "Whom do you wish to restore?\r\n");
else if (!(vict = get_char_vis(ch, buf, NULL, FIND_CHAR_WORLD)))
send_to_char(ch, "%s", CONFIG_NOPERSON);
else if (!IS_NPC(vict) && ch != vict && GET_LEVEL(vict) >= GET_LEVEL(ch))
send_to_char(ch, "They don't need your help.\r\n");
else {
GET_HIT(vict) = GET_MAX_HIT(vict);
GET_MANA(vict) = GET_MAX_MANA(vict);
GET_MOVE(vict) = GET_MAX_MOVE(vict);
if (!IS_NPC(vict) && GET_LEVEL(ch) >= LVL_GRGOD) {
if (GET_LEVEL(vict) >= LVL_IMMORT)
for (i = 1; i <= MAX_SKILLS; i++)
SET_SKILL(vict, i, 100);
if (GET_LEVEL(vict) >= LVL_GRGOD) {
vict->real_abils.str_add = 100;
vict->real_abils.intel = 25;
vict->real_abils.wis = 25;
vict->real_abils.dex = 25;
vict->real_abils.str = 25;
vict->real_abils.con = 25;
vict->real_abils.cha = 25;
}
}
update_pos(vict);
affect_total(vict);
send_to_char(ch, "%s", CONFIG_OK);
act("You have been fully healed by $N!", FALSE, vict, 0, ch, TO_CHAR);
}
}
void perform_immort_vis(struct char_data *ch)
{
if (GET_INVIS_LEV(ch) == 0 && !AFF_FLAGGED(ch, AFF_HIDE | AFF_INVISIBLE)) {
send_to_char(ch, "You are already fully visible.\r\n");
return;
}
GET_INVIS_LEV(ch) = 0;
appear(ch);
send_to_char(ch, "You are now fully visible.\r\n");
}
void perform_immort_invis(struct char_data *ch, int level)
{
struct char_data *tch;
for (tch = world[IN_ROOM(ch)].people; tch; tch = tch->next_in_room) {
if (tch == ch)
continue;
if (GET_LEVEL(tch) >= GET_INVIS_LEV(ch) && GET_LEVEL(tch) < level)
act("You blink and suddenly realize that $n is gone.", FALSE, ch, 0,
tch, TO_VICT);
if (GET_LEVEL(tch) < GET_INVIS_LEV(ch) && GET_LEVEL(tch) >= level)
act("You suddenly realize that $n is standing beside you.", FALSE, ch, 0,
tch, TO_VICT);
}
GET_INVIS_LEV(ch) = level;
send_to_char(ch, "Your invisibility level is %d.\r\n", level);
}
ACMD(do_invis)
{
char arg[MAX_INPUT_LENGTH];
int level;
if (IS_NPC(ch)) {
send_to_char(ch, "You can't do that!\r\n");
return;
}
one_argument(argument, arg);
if (!*arg) {
if (GET_INVIS_LEV(ch) > 0)
perform_immort_vis(ch);
else
perform_immort_invis(ch, GET_LEVEL(ch));
} else {
level = atoi(arg);
if (level > GET_LEVEL(ch))
send_to_char(ch, "You can't go invisible above your own level.\r\n");
else if (level < 1)
perform_immort_vis(ch);
else
perform_immort_invis(ch, level);
}
}
ACMD(do_gecho)
{
struct descriptor_data *pt;
skip_spaces(&argument);
delete_doubledollar(argument);
if (!*argument)
send_to_char(ch, "That must be a mistake...\r\n");
else {
for (pt = descriptor_list; pt; pt = pt->next)
if (IS_PLAYING(pt) && pt->character && pt->character != ch)
send_to_char(pt->character, "%s\r\n", argument);
mudlog(CMP, MAX(LVL_BUILDER, GET_INVIS_LEV(ch)), TRUE, "(GC) %s gechoed: %s", GET_NAME(ch), argument);
if (PRF_FLAGGED(ch, PRF_NOREPEAT))
send_to_char(ch, "%s", CONFIG_OK);
else
send_to_char(ch, "%s\r\n", argument);
}
}
ACMD(do_dc)
{
char arg[MAX_INPUT_LENGTH];
struct descriptor_data *d;
int num_to_dc;
one_argument(argument, arg);
if (!(num_to_dc = atoi(arg))) {
send_to_char(ch, "Usage: DC <user number> (type USERS for a list)\r\n");
return;
}
for (d = descriptor_list; d && d->desc_num != num_to_dc; d = d->next);
if (!d) {
send_to_char(ch, "No such connection.\r\n");
return;
}
if (d->character && GET_LEVEL(d->character) >= GET_LEVEL(ch)) {
if (!CAN_SEE(ch, d->character))
send_to_char(ch, "No such connection.\r\n");
else
send_to_char(ch, "Umm.. maybe that's not such a good idea...\r\n");
return;
}
/* We used to just close the socket here using close_socket(), but various
* people pointed out this could cause a crash if you're closing the person
* below you on the descriptor list. Just setting to CON_CLOSE leaves things
* in a massively inconsistent state so I had to add this new flag to the
* descriptor. -je It is a much more logical extension for a CON_DISCONNECT
* to be used for in-game socket closes and CON_CLOSE for out of game
* closings. This will retain the stability of the close_me hack while being
* neater in appearance. -gg For those unlucky souls who actually manage to
* get disconnected by two different immortals in the same 1/10th of a
* second, we have the below 'if' check. -gg */
if (STATE(d) == CON_DISCONNECT || STATE(d) == CON_CLOSE)
send_to_char(ch, "They're already being disconnected.\r\n");
else {
/* Remember that we can disconnect people not in the game and that rather
* confuses the code when it expected there to be a character context. */
if (STATE(d) == CON_PLAYING)
STATE(d) = CON_DISCONNECT;
else
STATE(d) = CON_CLOSE;
send_to_char(ch, "Connection #%d closed.\r\n", num_to_dc);
log("(GC) Connection closed by %s.", GET_NAME(ch));
}
}
ACMD(do_wizlock)
{
char arg[MAX_INPUT_LENGTH];
int value;
const char *when;
one_argument(argument, arg);
if (*arg) {
value = atoi(arg);
if (value < 0 || value > GET_LEVEL(ch)) {
send_to_char(ch, "Invalid wizlock value.\r\n");
return;
}
circle_restrict = value;
when = "now";
} else
when = "currently";
switch (circle_restrict) {
case 0:
send_to_char(ch, "The game is %s completely open.\r\n", when);
break;
case 1:
send_to_char(ch, "The game is %s closed to new players.\r\n", when);
break;
default:
send_to_char(ch, "Only level %d and above may enter the game %s.\r\n", circle_restrict, when);
break;
}
}
ACMD(do_date)
{
char *tmstr;
time_t mytime;
int d, h, m;
if (subcmd == SCMD_DATE)
mytime = time(0);
else
mytime = boot_time;
tmstr = (char *) asctime(localtime(&mytime));
*(tmstr + strlen(tmstr) - 1) = '\0';
if (subcmd == SCMD_DATE)
send_to_char(ch, "Current machine time: %s\r\n", tmstr);
else {
mytime = time(0) - boot_time;
d = mytime / 86400;
h = (mytime / 3600) % 24;
m = (mytime / 60) % 60;
send_to_char(ch, "Up since %s: %d day%s, %d:%02d\r\n", tmstr, d, d == 1 ? "" : "s", h, m);
}
}
/* altered from stock to the following:
last [name] [#]
last without arguments displays the last 10 entries.
last with a name only displays the 'stock' last entry.
last with a number displays that many entries (combines with name) */
const char *last_array[11] = {
"Connect",
"Enter Game",
"Reconnect",
"Takeover",
"Quit",
"Idleout",
"Disconnect",
"Shutdown",
"Reboot",
"Crash",
"Playing"
};
struct last_entry *find_llog_entry(int punique, long idnum) {
FILE *fp;
struct last_entry mlast;
struct last_entry *llast;
int size,recs,tmp;
if(!(fp=fopen(LAST_FILE,"r"))) {
log("Error opening last_file for reading, will create.");
return NULL;
}
fseek(fp,0L,SEEK_END);
size=ftell(fp);
/* recs = number of records in the last file */
recs = size/sizeof(struct last_entry);
/* we'll search last to first, since it's faster than any thing else we can
* do (like searching for the last shutdown/etc..) */
for(tmp=recs-1; tmp > 0; tmp--) {
fseek(fp,-1*(sizeof(struct last_entry)),SEEK_CUR);
fread(&mlast,sizeof(struct last_entry),1,fp);
/*another one to keep that stepback */
fseek(fp,-1*(sizeof(struct last_entry)),SEEK_CUR);
if(mlast.idnum == idnum && mlast.punique == punique) {
/* then we've found a match */
CREATE(llast,struct last_entry,1);
memcpy(llast,&mlast,sizeof(struct last_entry));
fclose(fp);
return llast;
}
/*not the one we seek. next */
}
/*not found, no problem, quit */
fclose(fp);
return NULL;
}
/* mod_llog_entry assumes that llast is accurate */
void mod_llog_entry(struct last_entry *llast,int type) {
FILE *fp;
struct last_entry mlast;
int size,recs,tmp;
if(!(fp=fopen(LAST_FILE,"r+"))) {
log("Error opening last_file for reading and writing.");
return;
}
fseek(fp,0L,SEEK_END);
size=ftell(fp);
/* recs = number of records in the last file */
recs = size/sizeof(struct last_entry);
/* We'll search last to first, since it's faster than any thing else we can
* do (like searching for the last shutdown/etc..) */
for(tmp=recs; tmp > 0; tmp--) {
fseek(fp,-1*(sizeof(struct last_entry)),SEEK_CUR);
fread(&mlast,sizeof(struct last_entry),1,fp);
/* Another one to keep that stepback. */
fseek(fp,-1*(sizeof(struct last_entry)),SEEK_CUR);
if(mlast.idnum == llast->idnum && mlast.punique == llast->punique) {
/* Then we've found a match, lets assume quit is inviolate, mainly
* because disconnect is called after each of these */
if(mlast.close_type != LAST_QUIT &&
mlast.close_type != LAST_IDLEOUT &&
mlast.close_type != LAST_REBOOT &&
mlast.close_type != LAST_SHUTDOWN) {
mlast.close_type=type;
}
mlast.close_time=time(0);
/*write it, and we're done!*/
fwrite(&mlast,sizeof(struct last_entry),1,fp);
fclose(fp);
return;
}
/* Not the one we seek, next. */
}
fclose(fp);
/* Not found, no problem, quit. */
return;
}
void add_llog_entry(struct char_data *ch, int type) {
FILE *fp;
struct last_entry *llast;
/* so if a char enteres a name, but bad password, otherwise loses link before
* he gets a pref assinged, we won't record it */
if(GET_PREF(ch) <= 0) {
return;
}
/* See if we have a login stored */
llast = find_llog_entry(GET_PREF(ch), GET_IDNUM(ch));
/* we didn't - make a new one */
if(llast == NULL) { /* no entry found, add ..error if close! */
CREATE(llast,struct last_entry,1);
strncpy(llast->username,GET_NAME(ch),16);
strncpy(llast->hostname,GET_HOST(ch),128);
llast->idnum=GET_IDNUM(ch);
llast->punique=GET_PREF(ch);
llast->time=time(0);
llast->close_time=0;
llast->close_type=type;
if(!(fp=fopen(LAST_FILE,"a"))) {
log("error opening last_file for appending");
free(llast);
return;
}
fwrite(llast,sizeof(struct last_entry),1,fp);
fclose(fp);
} else {
/* We've found a login - update it */
mod_llog_entry(llast,type);
}
free(llast);
}
void clean_llog_entries(void) {
FILE *ofp, *nfp;
struct last_entry mlast;
int recs;
if(!(ofp=fopen(LAST_FILE,"r")))
return; /* no file, no gripe */
fseek(ofp,0L,SEEK_END);
recs=ftell(ofp)/sizeof(struct last_entry);
rewind(ofp);
if (recs < MAX_LAST_ENTRIES) {
fclose(ofp);
return;
}
if (!(nfp=fopen("etc/nlast", "w"))) {
log("Error trying to open new last file.");
fclose(ofp);
return;
}
/* skip first entries */
fseek(ofp,(recs-MAX_LAST_ENTRIES)* (sizeof(struct last_entry)),SEEK_CUR);
/* copy the rest */
while (!feof(ofp)) {
fread(&mlast,sizeof(struct last_entry),1,ofp);
fwrite(&mlast,sizeof(struct last_entry),1,nfp);
}
fclose(ofp);
fclose(nfp);
remove(LAST_FILE);
rename("etc/nlast", LAST_FILE);
}
/* debugging stuff, if you wanna see the whole file */
ACMD(do_list_llog_entries) {
FILE *fp;
struct last_entry llast;
if(!(fp=fopen(LAST_FILE,"r"))) {
log("bad things.");
send_to_char(ch, "Error! - no last log");
}
send_to_char(ch, "Last log\r\n");
fread(&llast, sizeof(struct last_entry), 1, fp);
while(!feof(fp)) {
send_to_char(ch, "%10s\t%d\t%s\t%s", llast.username, llast.punique,
last_array[llast.close_type], ctime(&llast.time));
fread(&llast, sizeof(struct last_entry), 1, fp);
}
}
struct char_data *is_in_game(long idnum) {
struct descriptor_data *i;
for (i = descriptor_list; i; i = i->next) {
if (i->character && GET_IDNUM(i->character) == idnum) {
return i->character;
}
}
return NULL;
}
ACMD(do_last)
{
char arg[MAX_INPUT_LENGTH], name[MAX_INPUT_LENGTH];
struct char_data *vict = NULL;
struct char_data *temp;
int recs, num = 0;
FILE *fp;
time_t delta;
struct last_entry mlast;
*name = '\0';
if (*argument) { /* parse it */
half_chop(argument, arg, argument);
while (*arg) {
if ((*arg == '*') && (GET_LEVEL(ch) == LVL_IMPL)) {
do_list_llog_entries(ch, NULL, 0, 0);
return;
}
if (isdigit(*arg)) {
num = atoi(arg);
if (num < 0)
num = 0;
} else
strncpy(name, arg, sizeof(name)-1);
half_chop(argument, arg, argument);
}
}
if (*name && !num) {
CREATE(vict, struct char_data, 1);
clear_char(vict);
CREATE(vict->player_specials, struct player_special_data, 1);
if (load_char(name, vict) < 0) {
send_to_char(ch, "There is no such player.\r\n");
free_char(vict);
return;
}
if ((GET_LEVEL(vict) > GET_LEVEL(ch)) && (GET_LEVEL(ch) < LVL_IMPL)) {
send_to_char(ch, "You are not sufficiently godly for that!\r\n");
return;
}
send_to_char(ch, "[%5ld] [%2d %s] %-12s : %-18s : %-20s\r\n",
GET_IDNUM(vict), (int) GET_LEVEL(vict),
class_abbrevs[(int) GET_CLASS(vict)], GET_NAME(vict),
GET_HOST(vict) && *GET_HOST(vict) ? GET_HOST(vict) : "(NOHOST)",
ctime(&vict->player.time.logon));
free_char(vict);
return;
}
if(num <= 0 || num >= 100) {
num=10;
}
if(!(fp=fopen(LAST_FILE,"r"))) {
send_to_char(ch, "No entries found.\r\n");
return;
}
fseek(fp,0L,SEEK_END);
recs=ftell(fp)/sizeof(struct last_entry);
send_to_char(ch, "Last log\r\n");
while(num > 0 && recs > 0) {
fseek(fp,-1* (sizeof(struct last_entry)),SEEK_CUR);
fread(&mlast,sizeof(struct last_entry),1,fp);
fseek(fp,-1*(sizeof(struct last_entry)),SEEK_CUR);
if(!*name ||(*name && !str_cmp(name, mlast.username))) {
send_to_char(ch,"%10.10s %20.20s %16.16s - ",
mlast.username, mlast.hostname, ctime(&mlast.time));
if((temp=is_in_game(mlast.idnum)) && mlast.punique == GET_PREF(temp)) {
send_to_char(ch, "Still Playing ");
} else {
send_to_char(ch, "%5.5s ",ctime(&mlast.close_time)+11);
delta=mlast.close_time - mlast.time;
send_to_char(ch, "(%5.5s) ",asctime(gmtime(&delta))+11);
send_to_char(ch, "%s", last_array[mlast.close_type]);
}
send_to_char(ch, "\r\n");
num--;
}
recs--;
}
fclose(fp);
}
ACMD(do_force)
{
struct descriptor_data *i, *next_desc;
struct char_data *vict, *next_force;
char arg[MAX_INPUT_LENGTH], to_force[MAX_INPUT_LENGTH], buf1[MAX_INPUT_LENGTH + 32];
half_chop(argument, arg, to_force);
snprintf(buf1, sizeof(buf1), "$n has forced you to '%s'.", to_force);
if (!*arg || !*to_force)
send_to_char(ch, "Whom do you wish to force do what?\r\n");
else if ((GET_LEVEL(ch) < LVL_GRGOD) || (str_cmp("all", arg) && str_cmp("room", arg))) {
if (!(vict = get_char_vis(ch, arg, NULL, FIND_CHAR_WORLD)))
send_to_char(ch, "%s", CONFIG_NOPERSON);
else if (!IS_NPC(vict) && GET_LEVEL(ch) < LVL_GOD)
send_to_char(ch, "You cannot force players.\r\n");
else if (!IS_NPC(vict) && GET_LEVEL(ch) <= GET_LEVEL(vict))
send_to_char(ch, "No, no, no!\r\n");
else {
send_to_char(ch, "%s", CONFIG_OK);
act(buf1, TRUE, ch, NULL, vict, TO_VICT);
mudlog(CMP, MAX(LVL_GOD, GET_INVIS_LEV(ch)), TRUE, "(GC) %s forced %s to %s", GET_NAME(ch), GET_NAME(vict), to_force);
command_interpreter(vict, to_force);
}
} else if (!str_cmp("room", arg)) {
send_to_char(ch, "%s", CONFIG_OK);
mudlog(NRM, MAX(LVL_GOD, GET_INVIS_LEV(ch)), TRUE, "(GC) %s forced room %d to %s",
GET_NAME(ch), GET_ROOM_VNUM(IN_ROOM(ch)), to_force);
for (vict = world[IN_ROOM(ch)].people; vict; vict = next_force) {
next_force = vict->next_in_room;
if (!IS_NPC(vict) && GET_LEVEL(vict) >= GET_LEVEL(ch))
continue;
act(buf1, TRUE, ch, NULL, vict, TO_VICT);
command_interpreter(vict, to_force);
}
} else { /* force all */
send_to_char(ch, "%s", CONFIG_OK);
mudlog(NRM, MAX(LVL_GOD, GET_INVIS_LEV(ch)), TRUE, "(GC) %s forced all to %s", GET_NAME(ch), to_force);
for (i = descriptor_list; i; i = next_desc) {
next_desc = i->next;
if (STATE(i) != CON_PLAYING || !(vict = i->character) || (!IS_NPC(vict) && GET_LEVEL(vict) >= GET_LEVEL(ch)))
continue;
act(buf1, TRUE, ch, NULL, vict, TO_VICT);
command_interpreter(vict, to_force);
}
}
}
ACMD(do_wiznet)
{
char buf1[MAX_INPUT_LENGTH + MAX_NAME_LENGTH + 32],
buf2[MAX_INPUT_LENGTH + MAX_NAME_LENGTH + 32], *msg;
struct descriptor_data *d;
char emote = FALSE;
char any = FALSE;
int level = LVL_IMMORT;
skip_spaces(&argument);
delete_doubledollar(argument);
if (!*argument) {
send_to_char(ch, "Usage: wiznet [ #<level> ] [<text> | *<emotetext> | @@ ]\r\n");
return;
}
switch (*argument) {
case '*':
emote = TRUE;
case '#':
one_argument(argument + 1, buf1);
if (is_number(buf1)) {
half_chop(argument+1, buf1, argument);
level = MAX(atoi(buf1), LVL_IMMORT);
if (level > GET_LEVEL(ch)) {
send_to_char(ch, "You can't wizline above your own level.\r\n");
return;
}
} else if (emote)
argument++;
break;
case '@':
send_to_char(ch, "God channel status:\r\n");
for (any = 0, d = descriptor_list; d; d = d->next) {
if (STATE(d) != CON_PLAYING || GET_LEVEL(d->character) < LVL_IMMORT)
continue;
if (!CAN_SEE(ch, d->character))
continue;
send_to_char(ch, " %-*s%s%s%s\r\n", MAX_NAME_LENGTH, GET_NAME(d->character),
PLR_FLAGGED(d->character, PLR_WRITING) ? " (Writing)" : "",
PLR_FLAGGED(d->character, PLR_MAILING) ? " (Writing mail)" : "",
PRF_FLAGGED(d->character, PRF_NOWIZ) ? " (Offline)" : "");
}
return;
case '\\':
++argument;
break;
default:
break;
}
if (PRF_FLAGGED(ch, PRF_NOWIZ)) {
send_to_char(ch, "You are offline!\r\n");
return;
}
skip_spaces(&argument);
if (!*argument) {
send_to_char(ch, "Don't bother the gods like that!\r\n");
return;
}
if (level > LVL_IMMORT) {
snprintf(buf1, sizeof(buf1), "@c%s: <%d> %s%s@n\r\n", GET_NAME(ch), level, emote ? "<--- " : "", argument);
snprintf(buf2, sizeof(buf1), "@cSomeone: <%d> %s%s@n\r\n", level, emote ? "<--- " : "", argument);
} else {
snprintf(buf1, sizeof(buf1), "@c%s: %s%s@n\r\n", GET_NAME(ch), emote ? "<--- " : "", argument);
snprintf(buf2, sizeof(buf1), "@cSomeone: %s%s@n\r\n", emote ? "<--- " : "", argument);
}
for (d = descriptor_list; d; d = d->next) {
if (IS_PLAYING(d) && (GET_LEVEL(d->character) >= level) &&
(!PRF_FLAGGED(d->character, PRF_NOWIZ))
&& (d != ch->desc || !(PRF_FLAGGED(d->character, PRF_NOREPEAT)))) {
if (CAN_SEE(d->character, ch)) {
msg = strdup(buf1);
send_to_char(d->character, "%s", buf1);
} else {
msg = strdup(buf2);
send_to_char(d->character, "%s", buf2);
}
add_history(d->character, msg, HIST_WIZNET);
}
}
if (PRF_FLAGGED(ch, PRF_NOREPEAT))
send_to_char(ch, "%s", CONFIG_OK);
}
ACMD(do_zreset)
{
char arg[MAX_INPUT_LENGTH];
zone_rnum i;
zone_vnum j;
one_argument(argument, arg);
if (*arg == '*') {
if (GET_LEVEL(ch) < LVL_GOD){
send_to_char(ch, "You do not have permission to reset the entire world.\r\n");
return;
} else {
for (i = 0; i <= top_of_zone_table; i++)
reset_zone(i);
send_to_char(ch, "Reset world.\r\n");
mudlog(NRM, MAX(LVL_GRGOD, GET_INVIS_LEV(ch)), TRUE, "(GC) %s reset entire world.", GET_NAME(ch));
return; }
} else if (*arg == '.' || !*arg)
i = world[IN_ROOM(ch)].zone;
else {
j = atoi(arg);
for (i = 0; i <= top_of_zone_table; i++)
if (zone_table[i].number == j)
break;
}
if (i <= top_of_zone_table && (can_edit_zone(ch, i) || GET_LEVEL(ch) > LVL_IMMORT)) {
reset_zone(i);
send_to_char(ch, "Reset zone #%d: %s.\r\n", zone_table[i].number, zone_table[i].name);
mudlog(NRM, MAX(LVL_GRGOD, GET_INVIS_LEV(ch)), TRUE, "(GC) %s reset zone %d (%s)", GET_NAME(ch), zone_table[i].number, zone_table[i].name);
} else
send_to_char(ch, "You do not have permission to reset this zone. Try %d.\r\n", GET_OLC_ZONE(ch));
}
/* General fn for wizcommands of the sort: cmd <player> */
ACMD(do_wizutil)
{
char arg[MAX_INPUT_LENGTH];
struct char_data *vict;
int taeller;
long result;
one_argument(argument, arg);
if (!*arg)
send_to_char(ch, "Yes, but for whom?!?\r\n");
else if (!(vict = get_char_vis(ch, arg, NULL, FIND_CHAR_WORLD)))
send_to_char(ch, "There is no such player.\r\n");
else if (IS_NPC(vict))
send_to_char(ch, "You can't do that to a mob!\r\n");
else if (GET_LEVEL(vict) >= GET_LEVEL(ch) && vict != ch)
send_to_char(ch, "Hmmm...you'd better not.\r\n");
else {
switch (subcmd) {
case SCMD_REROLL:
send_to_char(ch, "Rerolled...\r\n");
roll_real_abils(vict);
log("(GC) %s has rerolled %s.", GET_NAME(ch), GET_NAME(vict));
send_to_char(ch, "New stats: Str %d/%d, Int %d, Wis %d, Dex %d, Con %d, Cha %d\r\n",
GET_STR(vict), GET_ADD(vict), GET_INT(vict), GET_WIS(vict),
GET_DEX(vict), GET_CON(vict), GET_CHA(vict));
break;
case SCMD_PARDON:
if (!PLR_FLAGGED(vict, PLR_THIEF | PLR_KILLER)) {
send_to_char(ch, "Your victim is not flagged.\r\n");
return;
}
REMOVE_BIT_AR(PLR_FLAGS(vict), PLR_THIEF);
REMOVE_BIT_AR(PLR_FLAGS(vict), PLR_KILLER);
send_to_char(ch, "Pardoned.\r\n");
send_to_char(vict, "You have been pardoned by the Gods!\r\n");
mudlog(BRF, MAX(LVL_GOD, GET_INVIS_LEV(ch)), TRUE, "(GC) %s pardoned by %s", GET_NAME(vict), GET_NAME(ch));
break;
case SCMD_NOTITLE:
result = PLR_TOG_CHK(vict, PLR_NOTITLE);
mudlog(NRM, MAX(LVL_GOD, GET_INVIS_LEV(ch)), TRUE, "(GC) Notitle %s for %s by %s.",
ONOFF(result), GET_NAME(vict), GET_NAME(ch));
send_to_char(ch, "(GC) Notitle %s for %s by %s.\r\n", ONOFF(result), GET_NAME(vict), GET_NAME(ch));
break;
case SCMD_MUTE:
result = PLR_TOG_CHK(vict, PLR_NOSHOUT);
mudlog(BRF, MAX(LVL_GOD, GET_INVIS_LEV(ch)), TRUE, "(GC) Mute %s for %s by %s.",
ONOFF(result), GET_NAME(vict), GET_NAME(ch));
send_to_char(ch, "(GC) Mute %s for %s by %s.\r\n", ONOFF(result), GET_NAME(vict), GET_NAME(ch));
break;
case SCMD_FREEZE:
if (ch == vict) {
send_to_char(ch, "Oh, yeah, THAT'S real smart...\r\n");
return;
}
if (PLR_FLAGGED(vict, PLR_FROZEN)) {
send_to_char(ch, "Your victim is already pretty cold.\r\n");
return;
}
SET_BIT_AR(PLR_FLAGS(vict), PLR_FROZEN);
GET_FREEZE_LEV(vict) = GET_LEVEL(ch);
send_to_char(vict, "A bitter wind suddenly rises and drains every erg of heat from your body!\r\nYou feel frozen!\r\n");
send_to_char(ch, "Frozen.\r\n");
act("A sudden cold wind conjured from nowhere freezes $n!", FALSE, vict, 0, 0, TO_ROOM);
mudlog(BRF, MAX(LVL_GOD, GET_INVIS_LEV(ch)), TRUE, "(GC) %s frozen by %s.", GET_NAME(vict), GET_NAME(ch));
break;
case SCMD_THAW:
if (!PLR_FLAGGED(vict, PLR_FROZEN)) {
send_to_char(ch, "Sorry, your victim is not morbidly encased in ice at the moment.\r\n");
return;
}
if (GET_FREEZE_LEV(vict) > GET_LEVEL(ch)) {
send_to_char(ch, "Sorry, a level %d God froze %s... you can't unfreeze %s.\r\n",
GET_FREEZE_LEV(vict), GET_NAME(vict), HMHR(vict));
return;
}
mudlog(BRF, MAX(LVL_GOD, GET_INVIS_LEV(ch)), TRUE, "(GC) %s un-frozen by %s.", GET_NAME(vict), GET_NAME(ch));
REMOVE_BIT_AR(PLR_FLAGS(vict), PLR_FROZEN);
send_to_char(vict, "A fireball suddenly explodes in front of you, melting the ice!\r\nYou feel thawed.\r\n");
send_to_char(ch, "Thawed.\r\n");
act("A sudden fireball conjured from nowhere thaws $n!", FALSE, vict, 0, 0, TO_ROOM);
break;
case SCMD_UNAFFECT:
if (vict->affected || AFF_FLAGS(vict)) {
while (vict->affected)
affect_remove(vict, vict->affected);
for(taeller=0; taeller < AF_ARRAY_MAX; taeller++)
AFF_FLAGS(ch)[taeller] = 0;
send_to_char(vict, "There is a brief flash of light!\r\nYou feel slightly different.\r\n");
send_to_char(ch, "All spells removed.\r\n");
} else {
send_to_char(ch, "Your victim does not have any affections!\r\n");
return;
}
break;
default:
log("SYSERR: Unknown subcmd %d passed to do_wizutil (%s)", subcmd, __FILE__);
/* SYSERR_DESC: This is the same as the unhandled case in do_gen_ps(),
* but this function handles 'reroll', 'pardon', 'freeze', etc. */
break;
}
save_char(vict);
}
}
/* single zone printing fn used by "show zone" so it's not repeated in the
code 3 times ... -je, 4/6/93 FIXME: overflow possible */
size_t print_zone_to_buf(char *bufptr, size_t left, zone_rnum zone, int listall)
{
size_t tmp;
if (listall) {
int i, j, k, l, m, n;
tmp = snprintf(bufptr, left,
"%3d %-30.30s%s By: %-10.10s%s Age: %3d; Reset: %3d (%1d); Range: %5d-%5d\r\n",
zone_table[zone].number, zone_table[zone].name, KNRM, zone_table[zone].builders, KNRM,
zone_table[zone].age, zone_table[zone].lifespan,
zone_table[zone].reset_mode,
zone_table[zone].bot, zone_table[zone].top);
i = j = k = l = m = n = 0;
for (i = 0; i < top_of_world; i++)
if (world[i].number >= zone_table[zone].bot && world[i].number <= zone_table[zone].top)
j++;
for (i = 0; i < top_of_objt; i++)
if (obj_index[i].vnum >= zone_table[zone].bot && obj_index[i].vnum <= zone_table[zone].top)
k++;
for (i = 0; i < top_of_mobt; i++)
if (mob_index[i].vnum >= zone_table[zone].bot && mob_index[i].vnum <= zone_table[zone].top)
l++;
for (i = 0; i<= top_shop; i++)
if (SHOP_NUM(i) >= zone_table[zone].bot && SHOP_NUM(i) <= zone_table[zone].top)
m++;
for (i = 0; i < top_of_trigt; i++)
if (trig_index[i]->vnum >= zone_table[zone].bot && trig_index[i]->vnum <= zone_table[zone].top)
n++;
tmp += snprintf(bufptr + tmp, left - tmp,
" Zone stats:\r\n"
" ---------------\r\n"
" Rooms: %2d\r\n"
" Objects: %2d\r\n"
" Mobiles: %2d\r\n"
" Shops: %2d\r\n"
" Triggers: %2d\r\n",
j, k, l, m, n);
return tmp;
}
return snprintf(bufptr, left,
"%3d %-*s%s By: %-10.10s%s Range: %5d-%5d\r\n", zone_table[zone].number,
count_color_chars(zone_table[zone].name)+30, zone_table[zone].name, KNRM,
zone_table[zone].builders, KNRM, zone_table[zone].bot, zone_table[zone].top);
}
ACMD(do_show)
{
int i, j, k, l, con; /* i, j, k to specifics? */
size_t len, nlen;
zone_rnum zrn;
zone_vnum zvn;
byte self = FALSE;
struct char_data *vict = NULL;
struct obj_data *obj;
struct descriptor_data *d;
char field[MAX_INPUT_LENGTH], value[MAX_INPUT_LENGTH],
arg[MAX_INPUT_LENGTH], buf[MAX_STRING_LENGTH];
struct show_struct {
const char *cmd;
const char level;
} fields[] = {
{ "nothing", 0 }, /* 0 */
{ "zones", LVL_IMMORT }, /* 1 */
{ "player", LVL_IMMORT },
{ "rent", LVL_IMMORT },
{ "stats", LVL_IMMORT },
{ "errors", LVL_IMMORT }, /* 5 */
{ "death", LVL_IMMORT },
{ "godrooms", LVL_IMMORT },
{ "shops", LVL_IMMORT },
{ "houses", LVL_IMMORT },
{ "snoop", LVL_IMMORT }, /* 10 */
{ "\n", 0 }
};
skip_spaces(&argument);
if (!*argument) {
send_to_char(ch, "Show options:\r\n");
for (j = 0, i = 1; fields[i].level; i++)
if (fields[i].level <= GET_LEVEL(ch))
send_to_char(ch, "%-15s%s", fields[i].cmd, (!(++j % 5) ? "\r\n" : ""));
send_to_char(ch, "\r\n");
return;
}
strcpy(arg, two_arguments(argument, field, value)); /* strcpy: OK (argument <= MAX_INPUT_LENGTH == arg) */
for (l = 0; *(fields[l].cmd) != '\n'; l++)
if (!strncmp(field, fields[l].cmd, strlen(field)))
break;
if (GET_LEVEL(ch) < fields[l].level) {
send_to_char(ch, "You are not godly enough for that!\r\n");
return;
}
if (!strcmp(value, "."))
self = TRUE;
buf[0] = '\0';
switch (l) {
/* show zone */
case 1:
/* tightened up by JE 4/6/93 */
if (self)
print_zone_to_buf(buf, sizeof(buf), world[IN_ROOM(ch)].zone, 1);
else if (*value && is_number(value)) {
for (zvn = atoi(value), zrn = 0; zone_table[zrn].number != zvn && zrn <= top_of_zone_table; zrn++);
if (zrn <= top_of_zone_table)
print_zone_to_buf(buf, sizeof(buf), zrn, 1);
else {
send_to_char(ch, "That is not a valid zone.\r\n");
return;
}
} else {
char *buf2;
for (len = zrn = 0; zrn <= top_of_zone_table; zrn++) {
if (*value) {
buf2 = strtok(strdup(zone_table[zrn].builders), " ");
while (buf2) {
if (!str_cmp(buf2, value))
break;
buf2 = strtok(NULL, " ");
}
if (!buf2)
continue;
}
nlen = print_zone_to_buf(buf + len, sizeof(buf) - len, zrn, 0);
if (len + nlen >= sizeof(buf) || nlen < 0)
break;
len += nlen;
}
}
page_string(ch->desc, buf, TRUE);
break;
/* show player */
case 2:
if (!*value) {
send_to_char(ch, "A name would help.\r\n");
return;
}
CREATE(vict, struct char_data, 1);
clear_char(vict);
CREATE(vict->player_specials, struct player_special_data, 1);
if (load_char(value, vict) < 0) {
send_to_char(ch, "There is no such player.\r\n");
free_char(vict);
return;
}
send_to_char(ch, "Player: %-12s (%s) [%2d %s]\r\n", GET_NAME(vict),
genders[(int) GET_SEX(vict)], GET_LEVEL(vict), class_abbrevs[(int)
GET_CLASS(vict)]);
send_to_char(ch, "Au: %-8d Bal: %-8d Exp: %-8d Align: %-5d Lessons: %-3d\r\n",
GET_GOLD(vict), GET_BANK_GOLD(vict), GET_EXP(vict),
GET_ALIGNMENT(vict), GET_PRACTICES(vict));
/* ctime() uses static buffer: do not combine. */
send_to_char(ch, "Started: %-20.16s ", ctime(&vict->player.time.birth));
send_to_char(ch, "Last: %-20.16s Played: %3dh %2dm\r\n",
ctime(&vict->player.time.logon),
(int) (vict->player.time.played / 3600),
(int) (vict->player.time.played / 60 % 60));
free_char(vict);
break;
/* show rent */
case 3:
if (!*value) {
send_to_char(ch, "A name would help.\r\n");
return;
}
Crash_listrent(ch, value);
break;
/* show stats */
case 4:
i = 0;
j = 0;
k = 0;
con = 0;
for (vict = character_list; vict; vict = vict->next) {
if (IS_NPC(vict))
j++;
else if (CAN_SEE(ch, vict)) {
i++;
if (vict->desc)
con++;
}
}
for (obj = object_list; obj; obj = obj->next)
k++;
send_to_char(ch,
"Current stats:\r\n"
" %5d players in game %5d connected\r\n"
" %5d registered\r\n"
" %5d mobiles %5d prototypes\r\n"
" %5d objects %5d prototypes\r\n"
" %5d rooms %5d zones\r\n"
" %5d triggers %5d shops\r\n"
" %5d large bufs\r\n"
" %5d buf switches %5d overflows\r\n",
i, con,
top_of_p_table + 1,
j, top_of_mobt + 1,
k, top_of_objt + 1,
top_of_world + 1, top_of_zone_table + 1,
top_of_trigt + 1, top_shop + 1,
buf_largecount,
buf_switches, buf_overflows
);
break;
/* show errors */
case 5:
len = strlcpy(buf, "Errant Rooms\r\n------------\r\n", sizeof(buf));
for (i = 0, k = 0; i <= top_of_world; i++)
for (j = 0; j < NUM_OF_DIRS; j++) {
if (!W_EXIT(i,j))
continue;
if (W_EXIT(i,j)->to_room == 0) {
nlen = snprintf(buf + len, sizeof(buf) - len, "%2d: (void ) [%5d] %-*s%s (%s)\r\n", ++k, GET_ROOM_VNUM(i), count_color_chars(world[i].name)+40, world[i].name, QNRM, dirs[j]);
if (len + nlen >= sizeof(buf) || nlen < 0)
break;
len += nlen;
}
if (W_EXIT(i,j)->to_room == NOWHERE && !W_EXIT(i,j)->general_description) {
nlen = snprintf(buf + len, sizeof(buf) - len, "%2d: (Nowhere) [%5d] %-*s%s (%s)\r\n", ++k, GET_ROOM_VNUM(i), count_color_chars(world[i].name)+ 40, world[i].name, QNRM, dirs[j]);
if (len + nlen >= sizeof(buf) || nlen < 0)
break;
len += nlen;
}
}
page_string(ch->desc, buf, TRUE);
break;
/* show death */
case 6:
len = strlcpy(buf, "Death Traps\r\n-----------\r\n", sizeof(buf));
for (i = 0, j = 0; i <= top_of_world; i++)
if (ROOM_FLAGGED(i, ROOM_DEATH)) {
nlen = snprintf(buf + len, sizeof(buf) - len, "%2d: [%5d] %s%s\r\n", ++j, GET_ROOM_VNUM(i), world[i].name, QNRM);
if (len + nlen >= sizeof(buf) || nlen < 0)
break;
len += nlen;
}
page_string(ch->desc, buf, TRUE);
break;
/* show godrooms */
case 7:
len = strlcpy(buf, "Godrooms\r\n--------------------------\r\n", sizeof(buf));
for (i = 0, j = 0; i <= top_of_world; i++)
if (ROOM_FLAGGED(i, ROOM_GODROOM)) {
nlen = snprintf(buf + len, sizeof(buf) - len, "%2d: [%5d] %s%s\r\n", ++j, GET_ROOM_VNUM(i), world[i].name, QNRM);
if (len + nlen >= sizeof(buf) || nlen < 0)
break;
len += nlen;
}
page_string(ch->desc, buf, TRUE);
break;
/* show shops */
case 8:
show_shops(ch, value);
break;
/* show houses */
case 9:
hcontrol_list_houses(ch, value);
break;
/* show snoop */
case 10:
i = 0;
send_to_char(ch, "People currently snooping:\r\n--------------------------\r\n");
for (d = descriptor_list; d; d = d->next) {
if (d->snooping == NULL || d->character == NULL)
continue;
if (STATE(d) != CON_PLAYING || GET_LEVEL(ch) < GET_LEVEL(d->character))
continue;
if (!CAN_SEE(ch, d->character) || IN_ROOM(d->character) == NOWHERE)
continue;
i++;
send_to_char(ch, "%-10s%s - snooped by %s%s.\r\n", GET_NAME(d->snooping->character), QNRM, GET_NAME(d->character), QNRM);
}
if (i == 0)
send_to_char(ch, "No one is currently snooping.\r\n");
break;
/* show what? */
default:
send_to_char(ch, "Sorry, I don't understand that.\r\n");
break;
}
}
/* The do_set function */
#define PC 1
#define NPC 2
#define BOTH 3
#define MISC 0
#define BINARY 1
#define NUMBER 2
#define SET_OR_REMOVE(flagset, flags) { \
if (on) SET_BIT_AR(flagset, flags); \
else if (off) REMOVE_BIT_AR(flagset, flags); }
#define RANGE(low, high) (value = MAX((low), MIN((high), (value))))
/* The set options available */
struct set_struct {
const char *cmd;
const char level;
const char pcnpc;
const char type;
} set_fields[] = {
{ "ac", LVL_BUILDER, BOTH, NUMBER }, /* 0 */
{ "afk", LVL_BUILDER, PC, BINARY }, /* 1 */
{ "age", LVL_GOD, BOTH, NUMBER },
{ "align", LVL_BUILDER, BOTH, NUMBER },
{ "bank", LVL_BUILDER, PC, NUMBER },
{ "brief", LVL_GOD, PC, BINARY }, /* 5 */
{ "cha", LVL_BUILDER, BOTH, NUMBER },
{ "class", LVL_BUILDER, BOTH, MISC },
{ "color", LVL_GOD, PC, BINARY },
{ "con", LVL_BUILDER, BOTH, NUMBER },
{ "damroll", LVL_BUILDER, BOTH, NUMBER }, /* 10 */
{ "deleted", LVL_IMPL, PC, BINARY },
{ "dex", LVL_BUILDER, BOTH, NUMBER },
{ "drunk", LVL_BUILDER, BOTH, MISC },
{ "exp", LVL_GOD, BOTH, NUMBER },
{ "frozen", LVL_GRGOD, PC, BINARY }, /* 15 */
{ "gold", LVL_BUILDER, BOTH, NUMBER },
{ "height", LVL_BUILDER, BOTH, NUMBER },
{ "hitpoints", LVL_BUILDER, BOTH, NUMBER },
{ "hitroll", LVL_BUILDER, BOTH, NUMBER },
{ "hunger", LVL_BUILDER, BOTH, MISC }, /* 20 */
{ "int", LVL_BUILDER, BOTH, NUMBER },
{ "invis", LVL_GOD, PC, NUMBER },
{ "invstart", LVL_BUILDER, PC, BINARY },
{ "killer", LVL_GOD, PC, BINARY },
{ "level", LVL_GRGOD, BOTH, NUMBER }, /* 25 */
{ "loadroom", LVL_BUILDER, PC, MISC },
{ "mana", LVL_BUILDER, BOTH, NUMBER },
{ "maxhit", LVL_BUILDER, BOTH, NUMBER },
{ "maxmana", LVL_BUILDER, BOTH, NUMBER },
{ "maxmove", LVL_BUILDER, BOTH, NUMBER }, /* 30 */
{ "move", LVL_BUILDER, BOTH, NUMBER },
{ "nodelete", LVL_GOD, PC, BINARY },
{ "nohassle", LVL_GOD, PC, BINARY },
{ "nosummon", LVL_BUILDER, PC, BINARY },
{ "nowizlist", LVL_GRGOD, PC, BINARY }, /* 35 */
{ "olc", LVL_GRGOD, PC, MISC },
{ "password", LVL_IMPL, PC, MISC },
{ "poofin", LVL_IMMORT, PC, MISC },
{ "poofout", LVL_IMMORT, PC, MISC },
{ "practices", LVL_GOD, PC, NUMBER }, /* 40 */
{ "quest", LVL_GOD, PC, BINARY },
{ "room", LVL_BUILDER, BOTH, NUMBER },
{ "sex", LVL_GOD, BOTH, MISC },
{ "showvnums", LVL_BUILDER, PC, BINARY },
{ "siteok", LVL_GOD, PC, BINARY }, /* 45 */
{ "str", LVL_BUILDER, BOTH, NUMBER },
{ "stradd", LVL_BUILDER, BOTH, NUMBER },
{ "thief", LVL_GOD, PC, BINARY },
{ "thirst", LVL_BUILDER, BOTH, MISC },
{ "title", LVL_GOD, PC, MISC }, /* 50 */
{ "variable", LVL_GRGOD, PC, MISC },
{ "weight", LVL_BUILDER, BOTH, NUMBER },
{ "wis", LVL_BUILDER, BOTH, NUMBER },
{ "questpoints", LVL_GOD, PC, NUMBER },
{ "\n", 0, BOTH, MISC }
};
int perform_set(struct char_data *ch, struct char_data *vict, int mode, char *val_arg)
{
int i, on = 0, off = 0, value = 0;
room_rnum rnum;
room_vnum rvnum;
/* Check to make sure all the levels are correct */
if (GET_LEVEL(ch) != LVL_IMPL) {
if (!IS_NPC(vict) && GET_LEVEL(ch) <= GET_LEVEL(vict) && vict != ch) {
send_to_char(ch, "Maybe that's not such a great idea...\r\n");
return (0);
}
}
if (GET_LEVEL(ch) < set_fields[mode].level) {
send_to_char(ch, "You are not godly enough for that!\r\n");
return (0);
}
/* Make sure the PC/NPC is correct */
if (IS_NPC(vict) && !(set_fields[mode].pcnpc & NPC)) {
send_to_char(ch, "You can't do that to a beast!\r\n");
return (0);
} else if (!IS_NPC(vict) && !(set_fields[mode].pcnpc & PC)) {
send_to_char(ch, "That can only be done to a beast!\r\n");
return (0);
}
/* Find the value of the argument */
if (set_fields[mode].type == BINARY) {
if (!strcmp(val_arg, "on") || !strcmp(val_arg, "yes"))
on = 1;
else if (!strcmp(val_arg, "off") || !strcmp(val_arg, "no"))
off = 1;
if (!(on || off)) {
send_to_char(ch, "Value must be 'on' or 'off'.\r\n");
return (0);
}
send_to_char(ch, "%s %s for %s.\r\n", set_fields[mode].cmd, ONOFF(on), GET_NAME(vict));
} else if (set_fields[mode].type == NUMBER) {
value = atoi(val_arg);
send_to_char(ch, "%s's %s set to %d.\r\n", GET_NAME(vict), set_fields[mode].cmd, value);
} else
send_to_char(ch, "%s", CONFIG_OK);
switch (mode) {
case 0: /* ac */
vict->points.armor = RANGE(-100, 100);
affect_total(vict);
break;
case 1: /* afk */
SET_OR_REMOVE(PRF_FLAGS(vict), PRF_AFK);
break;
case 2: /* age */
if (value < 2 || value > 200) { /* Arbitrary limits. */
send_to_char(ch, "Ages 2 to 200 accepted.\r\n");
return (0);
}
/* NOTE: May not display the exact age specified due to the integer
* division used elsewhere in the code. Seems to only happen for
* some values below the starting age (17) anyway. -gg 5/27/98 */
vict->player.time.birth = time(0) - ((value - 17) * SECS_PER_MUD_YEAR);
break;
case 3: /* align */
GET_ALIGNMENT(vict) = RANGE(-1000, 1000);
affect_total(vict);
break;
case 4: /* bank */
GET_BANK_GOLD(vict) = RANGE(0, 100000000);
break;
case 5: /* brief */
SET_OR_REMOVE(PRF_FLAGS(vict), PRF_BRIEF);
break;
case 6: /* cha */
if (IS_NPC(vict) || GET_LEVEL(vict) >= LVL_GRGOD)
RANGE(3, 25);
else
RANGE(3, 18);
vict->real_abils.cha = value;
affect_total(vict);
break;
case 7: /* class */
if ((i = parse_class(*val_arg)) == CLASS_UNDEFINED) {
send_to_char(ch, "That is not a class.\r\n");
return (0);
}
GET_CLASS(vict) = i;
break;
case 8: /* color */
SET_OR_REMOVE(PRF_FLAGS(vict), (PRF_COLOR_1 | PRF_COLOR_2));
break;
case 9: /* con */
if (IS_NPC(vict) || GET_LEVEL(vict) >= LVL_GRGOD)
RANGE(3, 25);
else
RANGE(3, 18);
vict->real_abils.con = value;
affect_total(vict);
break;
case 10: /* damroll */
vict->points.damroll = RANGE(-20, 20);
affect_total(vict);
break;
case 11: /* delete */
SET_OR_REMOVE(PLR_FLAGS(vict), PLR_DELETED);
break;
case 12: /* dex */
if (IS_NPC(vict) || GET_LEVEL(vict) >= LVL_GRGOD)
RANGE(3, 25);
else
RANGE(3, 18);
vict->real_abils.dex = value;
affect_total(vict);
break;
case 13: /* drunk */
if (!str_cmp(val_arg, "off")) {
GET_COND(vict, DRUNK) = -1;
send_to_char(ch, "%s's drunkenness is now off.\r\n", GET_NAME(vict));
} else if (is_number(val_arg)) {
value = atoi(val_arg);
RANGE(0, 24);
GET_COND(vict, DRUNK) = value;
send_to_char(ch, "%s's drunkenness set to %d.\r\n", GET_NAME(vict), value);
} else {
send_to_char(ch, "Must be 'off' or a value from 0 to 24.\r\n");
return (0);
}
break;
case 14: /* exp */
vict->points.exp = RANGE(0, 50000000);
break;
case 15: /* frozen */
if (ch == vict && on) {
send_to_char(ch, "Better not -- could be a long winter!\r\n");
return (0);
}
SET_OR_REMOVE(PLR_FLAGS(vict), PLR_FROZEN);
break;
case 16: /* gold */
GET_GOLD(vict) = RANGE(0, 100000000);
break;
case 17: /* height */
GET_HEIGHT(vict) = value;
affect_total(vict);
break;
case 18: /* hit */
vict->points.hit = RANGE(-9, vict->points.max_hit);
affect_total(vict);
break;
case 19: /* hitroll */
vict->points.hitroll = RANGE(-20, 20);
affect_total(vict);
break;
case 20: /* hunger */
if (!str_cmp(val_arg, "off")) {
GET_COND(vict, HUNGER) = -1;
send_to_char(ch, "%s's hunger is now off.\r\n", GET_NAME(vict));
} else if (is_number(val_arg)) {
value = atoi(val_arg);
RANGE(0, 24);
GET_COND(vict, HUNGER) = value;
send_to_char(ch, "%s's hunger set to %d.\r\n", GET_NAME(vict), value);
} else {
send_to_char(ch, "Must be 'off' or a value from 0 to 24.\r\n");
return (0);
}
break;
case 21: /* int */
if (IS_NPC(vict) || GET_LEVEL(vict) >= LVL_GRGOD)
RANGE(3, 25);
else
RANGE(3, 18);
vict->real_abils.intel = value;
affect_total(vict);
break;
case 22: /* invis */
if (GET_LEVEL(ch) < LVL_IMPL && ch != vict) {
send_to_char(ch, "You aren't godly enough for that!\r\n");
return (0);
}
GET_INVIS_LEV(vict) = RANGE(0, GET_LEVEL(vict));
break;
case 23: /* invistart */
SET_OR_REMOVE(PLR_FLAGS(vict), PLR_INVSTART);
break;
case 24: /* killer */
SET_OR_REMOVE(PLR_FLAGS(vict), PLR_KILLER);
break;
case 25: /* level */
if ((!IS_NPC(vict) && value > GET_LEVEL(ch)) || value > LVL_IMPL) {
send_to_char(ch, "You can't do that.\r\n");
return (0);
}
RANGE(1, LVL_IMPL);
vict->player.level = value;
break;
case 26: /* loadroom */
if (!str_cmp(val_arg, "off")) {
REMOVE_BIT_AR(PLR_FLAGS(vict), PLR_LOADROOM);
} else if (is_number(val_arg)) {
rvnum = atoi(val_arg);
if (real_room(rvnum) != NOWHERE) {
SET_BIT_AR(PLR_FLAGS(vict), PLR_LOADROOM);
GET_LOADROOM(vict) = rvnum;
send_to_char(ch, "%s will enter at room #%d.\r\n", GET_NAME(vict), GET_LOADROOM(vict));
} else {
send_to_char(ch, "That room does not exist!\r\n");
return (0);
}
} else {
send_to_char(ch, "Must be 'off' or a room's virtual number.\r\n");
return (0);
}
break;
case 27: /* mana */
vict->points.mana = RANGE(0, vict->points.max_mana);
affect_total(vict);
break;
case 28: /* maxhit */
vict->points.max_hit = RANGE(1, 5000);
affect_total(vict);
break;
case 29: /* maxmana */
vict->points.max_mana = RANGE(1, 5000);
affect_total(vict);
break;
case 30: /* maxmove */
vict->points.max_move = RANGE(1, 5000);
affect_total(vict);
break;
case 31: /* move */
vict->points.move = RANGE(0, vict->points.max_move);
affect_total(vict);
break;
case 32: /* nodelete */
SET_OR_REMOVE(PLR_FLAGS(vict), PLR_NODELETE);
break;
case 33: /* nohassle */
if (GET_LEVEL(ch) < LVL_GOD && ch != vict) {
send_to_char(ch, "You aren't godly enough for that!\r\n");
return (0);
}
SET_OR_REMOVE(PRF_FLAGS(vict), PRF_NOHASSLE);
break;
case 34: /* nosummon */
SET_OR_REMOVE(PRF_FLAGS(vict), PRF_SUMMONABLE);
send_to_char(ch, "Nosummon %s for %s.\r\n", ONOFF(!on), GET_NAME(vict));
break;
case 35: /* nowiz */
SET_OR_REMOVE(PLR_FLAGS(vict), PLR_NOWIZLIST);
break;
case 36: /* olc */
if (is_abbrev(val_arg, "socials") || is_abbrev(val_arg, "actions") || is_abbrev(val_arg, "aedit"))
GET_OLC_ZONE(vict) = AEDIT_PERMISSION;
else if (is_abbrev(val_arg, "hedit") || is_abbrev(val_arg, "help"))
GET_OLC_ZONE(vict) = HEDIT_PERMISSION;
else if (*val_arg == '*' || is_abbrev(val_arg, "all"))
GET_OLC_ZONE(vict) = ALL_PERMISSION;
else if (is_abbrev(val_arg, "off"))
GET_OLC_ZONE(vict) = NOWHERE;
else if (!is_number(val_arg)) {
send_to_char(ch, "Value must be a zone number, 'aedit', 'hedit', 'off' or 'all'.\r\n");
return (0);
} else
GET_OLC_ZONE(vict) = atoi(val_arg);
break;
case 37: /* password */
if (GET_LEVEL(vict) >= LVL_GRGOD) {
send_to_char(ch, "You cannot change that.\r\n");
return (0);
}
strncpy(GET_PASSWD(vict), CRYPT(val_arg, GET_NAME(vict)), MAX_PWD_LENGTH); /* strncpy: OK (G_P:MAX_PWD_LENGTH) */
*(GET_PASSWD(vict) + MAX_PWD_LENGTH) = '\0';
send_to_char(ch, "Password changed to '%s'.\r\n", val_arg);
break;
case 38: /* poofin */
if ((vict == ch) || (GET_LEVEL(ch) == LVL_IMPL)) {
skip_spaces(&val_arg);
if (!*val_arg)
POOFIN(vict) = NULL;
else
POOFIN(vict) = strdup(val_arg);
}
break;
case 39: /* poofout */
if ((vict == ch) || (GET_LEVEL(ch) == LVL_IMPL)) {
skip_spaces(&val_arg);
if (!*val_arg)
POOFOUT(vict) = NULL;
else
POOFOUT(vict) = strdup(val_arg);
}
break;
case 40: /* practices */
GET_PRACTICES(vict) = RANGE(0, 100);
break;
case 41: /* quest */
SET_OR_REMOVE(PRF_FLAGS(vict), PRF_QUEST);
break;
case 42: /* room */
if ((rnum = real_room(value)) == NOWHERE) {
send_to_char(ch, "No room exists with that number.\r\n");
return (0);
}
if (IN_ROOM(vict) != NOWHERE)
char_from_room(vict);
char_to_room(vict, rnum);
break;
case 43: /* sex */
if ((i = search_block(val_arg, genders, FALSE)) < 0) {
send_to_char(ch, "Must be 'male', 'female', or 'neutral'.\r\n");
return (0);
}
GET_SEX(vict) = i;
break;
case 44: /* showvnums */
SET_OR_REMOVE(PRF_FLAGS(vict), PRF_SHOWVNUMS);
break;
case 45: /* siteok */
SET_OR_REMOVE(PLR_FLAGS(vict), PLR_SITEOK);
break;
case 46: /* str */
if (IS_NPC(vict) || GET_LEVEL(vict) >= LVL_GRGOD)
RANGE(3, 25);
else
RANGE(3, 18);
vict->real_abils.str = value;
vict->real_abils.str_add = 0;
affect_total(vict);
break;
case 47: /* stradd */
vict->real_abils.str_add = RANGE(0, 100);
if (value > 0)
vict->real_abils.str = 18;
affect_total(vict);
break;
case 48: /* thief */
SET_OR_REMOVE(PLR_FLAGS(vict), PLR_THIEF);
break;
case 49: /* thirst */
if (!str_cmp(val_arg, "off")) {
GET_COND(vict, THIRST) = -1;
send_to_char(ch, "%s's thirst is now off.\r\n", GET_NAME(vict));
} else if (is_number(val_arg)) {
value = atoi(val_arg);
RANGE(0, 24);
GET_COND(vict, THIRST) = value;
send_to_char(ch, "%s's thirst set to %d.\r\n", GET_NAME(vict), value);
} else {
send_to_char(ch, "Must be 'off' or a value from 0 to 24.\r\n");
return (0);
}
break;
case 50: /* title */
set_title(vict, val_arg);
send_to_char(ch, "%s's title is now: %s\r\n", GET_NAME(vict), GET_TITLE(vict));
break;
case 51: /* variable */
return perform_set_dg_var(ch, vict, val_arg);
break;
case 52: /* weight */
GET_WEIGHT(vict) = value;
affect_total(vict);
break;
case 53: /* wis */
if (IS_NPC(vict) || GET_LEVEL(vict) >= LVL_GRGOD)
RANGE(3, 25);
else
RANGE(3, 18);
vict->real_abils.wis = value;
affect_total(vict);
break;
case 54: /* questpoints */
GET_QUESTPOINTS(vict) = RANGE(0, 100000000);
break;
default:
send_to_char(ch, "Can't set that!\r\n");
return (0);
}
return (1);
}
ACMD(do_set)
{
struct char_data *vict = NULL, *cbuf = NULL;
char field[MAX_INPUT_LENGTH], name[MAX_INPUT_LENGTH], buf[MAX_INPUT_LENGTH];
int mode, len, player_i = 0, retval;
char is_file = 0, is_player = 0;
half_chop(argument, name, buf);
if (!strcmp(name, "file")) {
is_file = 1;
half_chop(buf, name, buf);
} else if (!str_cmp(name, "player")) {
is_player = 1;
half_chop(buf, name, buf);
} else if (!str_cmp(name, "mob"))
half_chop(buf, name, buf);
half_chop(buf, field, buf);
if (!*name || !*field) {
send_to_char(ch, "Usage: set <victim> <field> <value>\r\n");
return;
}
/* find the target */
if (!is_file) {
if (is_player) {
if (!(vict = get_player_vis(ch, name, NULL, FIND_CHAR_WORLD))) {
send_to_char(ch, "There is no such player.\r\n");
return;
}
} else { /* is_mob */
if (!(vict = get_char_vis(ch, name, NULL, FIND_CHAR_WORLD))) {
send_to_char(ch, "There is no such creature.\r\n");
return;
}
}
} else if (is_file) {
/* try to load the player off disk */
CREATE(cbuf, struct char_data, 1);
clear_char(cbuf);
CREATE(cbuf->player_specials, struct player_special_data, 1);
if ((player_i = load_char(name, cbuf)) > -1) {
if (GET_LEVEL(cbuf) > GET_LEVEL(ch)) {
free_char(cbuf);
send_to_char(ch, "Sorry, you can't do that.\r\n");
return;
}
vict = cbuf;
} else {
free_char(cbuf);
send_to_char(ch, "There is no such player.\r\n");
return;
}
}
/* find the command in the list */
len = strlen(field);
for (mode = 0; *(set_fields[mode].cmd) != '\n'; mode++)
if (!strncmp(field, set_fields[mode].cmd, len))
break;
if (*(set_fields[mode].cmd) == '\n') {
retval = 0; /* skips saving below */
send_to_char(ch, "Can't set that!\r\n");
} else
/* perform the set */
retval = perform_set(ch, vict, mode, buf);
/* save the character if a change was made */
if (retval) {
if (!is_file && !IS_NPC(vict))
save_char(vict);
if (is_file) {
GET_PFILEPOS(cbuf) = player_i;
save_char(cbuf);
send_to_char(ch, "Saved in file.\r\n");
}
}
/* free the memory if we allocated it earlier */
if (is_file)
free_char(cbuf);
}
ACMD(do_saveall)
{
if (GET_LEVEL(ch) < LVL_BUILDER)
send_to_char (ch, "You are not holy enough to use this privelege.\n\r");
else {
save_all();
House_save_all();
send_to_char(ch, "World and house files saved.\n\r");
}
}
ACMD(do_links)
{
zone_rnum zrnum;
zone_vnum zvnum;
room_rnum nr, to_room;
int first, last, j;
char arg[MAX_INPUT_LENGTH];
skip_spaces(&argument);
one_argument(argument, arg);
if (!arg || !*arg) {
zrnum = world[IN_ROOM(ch)].zone;
zvnum = zone_table[zrnum].number;
} else {
zvnum = atoi(arg);
zrnum = real_zone(zvnum);
}
if (zrnum == NOWHERE || zvnum == NOWHERE) {
send_to_char(ch, "No zone was found with that number.\n\r");
return;
}
last = zone_table[zrnum].top;
first = zone_table[zrnum].bot;
send_to_char(ch, "Zone %d is linked to the following zones:\r\n", zvnum);
for (nr = 0; nr <= top_of_world && (GET_ROOM_VNUM(nr) <= last); nr++) {
if (GET_ROOM_VNUM(nr) >= first) {
for (j = 0; j < NUM_OF_DIRS; j++) {
if (world[nr].dir_option[j]) {
to_room = world[nr].dir_option[j]->to_room;
if (to_room != NOWHERE && (zrnum != world[to_room].zone))
send_to_char(ch, "%3d %-30s at %5d (%-5s) ---> %5d\r\n",
zone_table[world[to_room].zone].number,
zone_table[world[to_room].zone].name,
GET_ROOM_VNUM(nr), dirs[j], world[to_room].number);
}
}
}
}
}
/* Zone Checker Code below */
/*mob limits*/
#define MAX_DAMROLL_ALLOWED MAX(GET_LEVEL(mob)/5, 1)
#define MAX_HITROLL_ALLOWED MAX(GET_LEVEL(mob)/3, 1)
#define MAX_GOLD_ALLOWED GET_LEVEL(mob)*3000
#define MAX_EXP_ALLOWED GET_LEVEL(mob)*GET_LEVEL(mob) * 120
#define MAX_LEVEL_ALLOWED LVL_IMPL
#define GET_OBJ_AVG_DAM(obj) (((GET_OBJ_VAL(obj, 2) + 1) / 2.0) * GET_OBJ_VAL(obj, 1))
/* arbitrary limit for per round dam */
#define MAX_MOB_DAM_ALLOWED 500
#define ZCMD2 zone_table[zone].cmd[cmd_no] /*fom DB.C*/
/*item limits*/
#define MAX_DAM_ALLOWED 50 /* for weapons - avg. dam*/
#define MAX_AFFECTS_ALLOWED 3
/* Armor class limits*/
#define TOTAL_WEAR_CHECKS (NUM_ITEM_WEARS-2) /*minus Wield and Take*/
struct zcheck_armor {
bitvector_t bitvector; /* from Structs.h */
int ac_allowed; /* Max. AC allowed for this body part */
char *message; /* phrase for error message */
} zarmor[] = {
{ITEM_WEAR_FINGER, 10, "Ring"},
{ITEM_WEAR_NECK, 10, "Necklace"},
{ITEM_WEAR_BODY, 10, "Body armor"},
{ITEM_WEAR_HEAD, 10, "Head gear"},
{ITEM_WEAR_LEGS, 10, "Legwear"},
{ITEM_WEAR_FEET, 10, "Footwear"},
{ITEM_WEAR_HANDS, 10, "Glove"},
{ITEM_WEAR_ARMS, 10, "Armwear"},
{ITEM_WEAR_SHIELD, 10, "Shield"},
{ITEM_WEAR_ABOUT, 10, "Cloak"},
{ITEM_WEAR_WAIST, 10, "Belt"},
{ITEM_WEAR_WRIST, 10, "Wristwear"},
{ITEM_WEAR_HOLD, 10, "Held item"}
};
/*These are strictly boolean*/
#define CAN_WEAR_WEAPONS 0 /* toggle - can a weapon also be a piece of armor? */
#define MAX_APPLIES_LIMIT 1 /* toggle - is there a limit at all? */
#define CHECK_ITEM_RENT 0 /* do we check for rent cost == 0 ? */
#define CHECK_ITEM_COST 0 /* do we check for item cost == 0 ? */
/* Applies limits !! Very Important: Keep these in the same order as in Structs.h.
* To ignore an apply, set max_aff to -99. These will be ignored if MAX_APPLIES_LIMIT = 0 */
struct zcheck_affs {
int aff_type; /*from Structs.h*/
int min_aff; /*min. allowed value*/
int max_aff; /*max. allowed value*/
char *message; /*phrase for error message*/
} zaffs[] = {
{APPLY_NONE, 0, -99, "unused0"},
{APPLY_STR, -5, 3, "strength"},
{APPLY_DEX, -5, 3, "dexterity"},
{APPLY_INT, -5, 3, "intelligence"},
{APPLY_WIS, -5, 3, "wisdom"},
{APPLY_CON, -5, 3, "constitution"},
{APPLY_CHA, -5, 3, "charisma"},
{APPLY_CLASS, 0, 0, "class"},
{APPLY_LEVEL, 0, 0, "level"},
{APPLY_AGE, -10, 10, "age"},
{APPLY_CHAR_WEIGHT,-50, 50, "character weight"},
{APPLY_CHAR_HEIGHT,-50, 50, "character height"},
{APPLY_MANA, -50, 50, "mana"},
{APPLY_HIT, -50, 50, "hit points"},
{APPLY_MOVE, -50, 50, "movement"},
{APPLY_GOLD, 0, 0, "gold"},
{APPLY_EXP, 0, 0, "experience"},
{APPLY_AC, -10, 10, "magical AC"},
{APPLY_HITROLL, 0, -99, "hitroll"}, /* Handled seperately below */
{APPLY_DAMROLL, 0, -99, "damroll"}, /* Handled seperately below */
{APPLY_SAVING_PARA, -2, 2, "saving throw (paralysis)"},
{APPLY_SAVING_ROD, -2, 2, "saving throw (rod)"},
{APPLY_SAVING_PETRI,-2, 2, "saving throw (death)"},
{APPLY_SAVING_BREATH,-2, 2, "saving throw (breath)"},
{APPLY_SAVING_SPELL,-2, 2, "saving throw (spell)"}
};
/* These are ABS() values. */
#define MAX_APPLY_HITROLL_TOTAL 5
#define MAX_APPLY_DAMROLL_TOTAL 5
/*room limits*/
/* Off limit zones are any zones a player should NOT be able to walk to (ex. Limbo) */
const int offlimit_zones[] = {0,12,13,14,-1}; /*what zones can no room connect to (virtual num) */
#define MIN_ROOM_DESC_LENGTH 80 /* at least one line - set to 0 to not care. */
#define MAX_COLOUMN_WIDTH 80 /* at most 80 chars per line */
ACMD (do_zcheck)
{
zone_rnum zrnum;
struct obj_data *obj;
struct char_data *mob = NULL;
room_vnum exroom=0;
int ac=0;
int affs=0, tohit, todam, value;
int i = 0, j = 0, k = 0, l = 0, m = 0, found = 0; /* found is used as a 'send now' flag*/
char buf[MAX_STRING_LENGTH];
float avg_dam;
size_t len = 0;
struct extra_descr_data *ext, *ext2;
one_argument(argument, buf);
if (!buf || !*buf || !strcmp(buf, "."))
zrnum = world[IN_ROOM(ch)].zone;
else
zrnum = real_zone(atoi(buf));
if (zrnum == NOWHERE) {
send_to_char(ch, "Check what zone ?\r\n");
return;
} else
send_to_char(ch, "Checking zone %d!\r\n", zone_table[zrnum].number);
/* Check mobs */
send_to_char(ch, "Checking Mobs for limits...\r\n");
/*check mobs first*/
for (i=0; i<top_of_mobt;i++) {
if (real_zone_by_thing(mob_index[i].vnum) == zrnum) { /*is mob in this zone?*/
mob = &mob_proto[i];
if (!strcmp(mob->player.name, "mob unfinished") && (found=1))
len += snprintf(buf + len, sizeof(buf) - len,
"- Alias hasn't been set.\r\n");
if (!strcmp(mob->player.short_descr, "the unfinished mob") && (found=1))
len += snprintf(buf + len, sizeof(buf) - len,
"- Short description hasn't been set.\r\n");
if (!strncmp(mob->player.long_descr, "An unfinished mob stands here.", 30) && (found=1))
len += snprintf(buf + len, sizeof(buf) - len,
"- Long description hasn't been set.\r\n");
if (mob->player.description && *mob->player.description) {
if (!strncmp(mob->player.description, "It looks unfinished.", 20) && (found=1))
len += snprintf(buf + len, sizeof(buf) - len,
"- Description hasn't been set.\r\n");
else if (strncmp(mob->player.description, " ", 3) && (found=1))
len += snprintf(buf + len, sizeof(buf) - len,
"- Description hasn't been formatted. (/fi)\r\n");
}
if (GET_LEVEL(mob)>MAX_LEVEL_ALLOWED && (found=1))
len += snprintf(buf + len, sizeof(buf) - len,
"- Is level %d (limit: 1-%d)\r\n",
GET_LEVEL(mob), MAX_LEVEL_ALLOWED);
if (GET_DAMROLL(mob)>MAX_DAMROLL_ALLOWED && (found=1))
len += snprintf(buf + len, sizeof(buf) - len,
"- Damroll of %d is too high (limit: %d)\r\n",
GET_DAMROLL(mob), MAX_DAMROLL_ALLOWED);
if (GET_HITROLL(mob)>MAX_HITROLL_ALLOWED && (found=1))
len += snprintf(buf + len, sizeof(buf) - len,
"- Hitroll of %d is too high (limit: %d)\r\n",
GET_HITROLL(mob), MAX_HITROLL_ALLOWED);
/* avg. dam including damroll per round of combat */
avg_dam = (((mob->mob_specials.damsizedice / 2.0) * mob->mob_specials.damnodice)+GET_DAMROLL(mob));
if (avg_dam>MAX_MOB_DAM_ALLOWED && (found=1))
len += snprintf(buf + len, sizeof(buf) - len,
"- average damage of %4.1f is too high (limit: %d)\r\n",
avg_dam, MAX_MOB_DAM_ALLOWED);
if (mob->mob_specials.damsizedice == 1 &&
mob->mob_specials.damnodice == 1 &&
GET_LEVEL(mob) == 0 &&
(found=1))
len += snprintf(buf + len, sizeof(buf) - len,
"- Needs to be fixed - %sAutogenerate!%s\r\n", CCYEL(ch, C_NRM), CCNRM(ch, C_NRM));
if (MOB_FLAGGED(mob, MOB_AGGRESSIVE) &&
MOB_FLAGGED(mob, MOB_AGGR_GOOD | MOB_AGGR_EVIL | MOB_AGGR_NEUTRAL) && (found=1))
len += snprintf(buf + len, sizeof(buf) - len,
"- Both aggresive and agressive to align.\r\n");
if ((GET_GOLD(mob) > MAX_GOLD_ALLOWED) && (found=1))
len += snprintf(buf + len, sizeof(buf) - len,
"- Set to %d Gold (limit : %d).\r\n",
GET_GOLD(mob),
MAX_GOLD_ALLOWED);
if (GET_EXP(mob)>MAX_EXP_ALLOWED && (found=1))
len += snprintf(buf + len, sizeof(buf) - len,
"- Has %d experience (limit: %d)\r\n",
GET_EXP(mob), MAX_EXP_ALLOWED);
if (AFF_FLAGGED(mob, AFF_GROUP | AFF_CHARM | AFF_POISON) && (found = 1))
len += snprintf(buf + len, sizeof(buf) - len,
"- Has illegal affection bits set (%s %s %s)\r\n",
AFF_FLAGGED(mob, AFF_GROUP) ? "GROUP" : "",
AFF_FLAGGED(mob, AFF_CHARM) ? "CHARM" : "",
AFF_FLAGGED(mob, AFF_POISON) ? "POISON" : "");
if (!MOB_FLAGGED(mob, MOB_SENTINEL) && !MOB_FLAGGED(mob, MOB_STAY_ZONE) && (found = 1))
len += snprintf(buf + len, sizeof(buf) - len,
"- Neither SENTINEL nor STAY_ZONE bits set.\r\n");
if (MOB_FLAGGED(mob, MOB_SPEC) && (found = 1))
len += snprintf(buf + len, sizeof(buf) - len,
"- SPEC flag needs to be removed.\r\n");
/* Additional mob checks.*/
if (found) {
send_to_char(ch,
"%s[%5d]%s %-30s: %s\r\n",
CCCYN(ch, C_NRM), GET_MOB_VNUM(mob),
CCYEL(ch, C_NRM), GET_NAME(mob),
CCNRM(ch, C_NRM));
send_to_char(ch, buf);
}
/* reset buffers and found flag */
strcpy(buf, "");
found = 0;
len = 0;
} /* mob is in zone */
} /* check mobs */
/* Check objects */
send_to_char(ch, "\r\nChecking Objects for limits...\r\n");
for (i=0; i<top_of_objt; i++) {
if (real_zone_by_thing(obj_index[i].vnum) == zrnum) { /*is object in this zone?*/
obj = &obj_proto[i];
switch (GET_OBJ_TYPE(obj)) {
case ITEM_MONEY:
if ((value = GET_OBJ_VAL(obj, 1))>MAX_GOLD_ALLOWED && (found=1))
len += snprintf(buf + len, sizeof(buf) - len,
"- Is worth %d (money limit %d coins).\r\n",
value, MAX_GOLD_ALLOWED);
break;
case ITEM_WEAPON:
if (GET_OBJ_VAL(obj, 3) >= NUM_ATTACK_TYPES && (found=1))
len += snprintf(buf + len, sizeof(buf) - len,
"- has out of range attack type %d.\r\n",
GET_OBJ_VAL(obj, 3));
if (GET_OBJ_AVG_DAM(obj)>MAX_DAM_ALLOWED && (found=1))
len += snprintf(buf + len, sizeof(buf) - len,
"- Damroll is %2.1f (limit %d)\r\n",
GET_OBJ_AVG_DAM(obj), MAX_DAM_ALLOWED);
break;
case ITEM_ARMOR:
ac=GET_OBJ_VAL(obj,0);
for (j=0; j<TOTAL_WEAR_CHECKS;j++) {
if (CAN_WEAR(obj,zarmor[j].bitvector) && (ac>zarmor[j].ac_allowed) && (found=1))
len += snprintf(buf + len, sizeof(buf) - len,
"- Has AC %d (%s limit is %d)\r\n",
ac, zarmor[j].message, zarmor[j].ac_allowed);
}
break;
} /*switch on Item_Type*/
if (!CAN_WEAR(obj, ITEM_WEAR_TAKE)) {
if ((GET_OBJ_COST(obj) || (GET_OBJ_WEIGHT(obj) && GET_OBJ_TYPE(obj) != ITEM_FOUNTAIN) ||
GET_OBJ_RENT(obj)) && (found = 1))
len += snprintf(buf + len, sizeof(buf) - len,
"- is NO_TAKE, but has cost (%d) weight (%d) or rent (%d) set.\r\n",
GET_OBJ_COST(obj), GET_OBJ_WEIGHT(obj), GET_OBJ_RENT(obj));
} else {
if (GET_OBJ_COST(obj) == 0 && (found=1))
len += snprintf(buf + len, sizeof(buf) - len,
"- has 0 cost (min. 1).\r\n");
if (GET_OBJ_WEIGHT(obj) == 0 && (found=1))
len += snprintf(buf + len, sizeof(buf) - len,
"- has 0 weight (min. 1).\r\n");
if (GET_OBJ_WEIGHT(obj) > MAX_OBJ_WEIGHT && (found=1))
len += snprintf(buf + len, sizeof(buf) - len,
" Weight is too high: %d (limit %d).\r\n",
GET_OBJ_WEIGHT(obj), MAX_OBJ_WEIGHT);
if (GET_OBJ_COST(obj) > MAX_OBJ_COST && (found=1))
len += snprintf(buf + len, sizeof(buf) - len,
"- has %d cost (max %d).\r\n",
GET_OBJ_COST(obj), MAX_OBJ_COST);
}
if (GET_OBJ_LEVEL(obj) > LVL_IMMORT-1 && (found=1))
len += snprintf(buf + len, sizeof(buf) - len,
"- has min level set to %d (max %d).\r\n",
GET_OBJ_LEVEL(obj), LVL_IMMORT-1);
if (obj->action_description && *obj->action_description &&
GET_OBJ_TYPE(obj) != ITEM_STAFF &&
GET_OBJ_TYPE(obj) != ITEM_WAND &&
GET_OBJ_TYPE(obj) != ITEM_SCROLL &&
GET_OBJ_TYPE(obj) != ITEM_NOTE && (found=1))
len += snprintf(buf + len, sizeof(buf) - len,
"- has action_description set, but is inappropriate type.\r\n");
/*first check for over-all affections*/
for (affs=0, j = 0; j < MAX_OBJ_AFFECT; j++)
if (obj->affected[j].modifier) affs++;
if (affs>MAX_AFFECTS_ALLOWED && (found=1))
len += snprintf(buf + len, sizeof(buf) - len,
"- has %d affects (limit %d).\r\n",
affs, MAX_AFFECTS_ALLOWED);
/*check for out of range affections. */
for (j=0;j<MAX_OBJ_AFFECT;j++)
if (zaffs[(int)obj->affected[j].location].max_aff != -99 && /* only care if a range is set */
(obj->affected[j].modifier > zaffs[(int)obj->affected[j].location].max_aff ||
obj->affected[j].modifier < zaffs[(int)obj->affected[j].location].min_aff ||
zaffs[(int)obj->affected[j].location].min_aff == zaffs[(int)obj->affected[j].location].max_aff) && (found=1))
len += snprintf(buf + len, sizeof(buf) - len,
"- apply to %s is %d (limit %d - %d).\r\n",
zaffs[(int)obj->affected[j].location].message,
obj->affected[j].modifier,
zaffs[(int)obj->affected[j].location].min_aff,
zaffs[(int)obj->affected[j].location].max_aff);
/* special handling of +hit and +dam because of +hit_n_dam */
for (todam=0, tohit=0, j=0;j<MAX_OBJ_AFFECT;j++) {
if (obj->affected[j].location == APPLY_HITROLL)
tohit += obj->affected[j].modifier;
if (obj->affected[j].location == APPLY_DAMROLL)
todam += obj->affected[j].modifier;
}
if (abs(todam) > MAX_APPLY_DAMROLL_TOTAL && (found=1))
len += snprintf(buf + len, sizeof(buf) - len,
"- total damroll %d out of range (limit +/-%d.\r\n",
todam, MAX_APPLY_DAMROLL_TOTAL);
if (abs(tohit) > MAX_APPLY_HITROLL_TOTAL && (found=1))
len += snprintf(buf + len, sizeof(buf) - len,
"- total hitroll %d out of range (limit +/-%d).\r\n",
tohit, MAX_APPLY_HITROLL_TOTAL);
for (ext2 = NULL, ext = obj->ex_description; ext; ext = ext->next)
if (strncmp(ext->description, " ", 3))
ext2 = ext;
if (ext2 && (found = 1))
len += snprintf(buf + len, sizeof(buf) - len,
"- has unformatted extra description\r\n");
/* Additional object checks. */
if (found) {
send_to_char(ch, "[%5d] %-30s: \r\n", GET_OBJ_VNUM(obj), obj->short_description);
send_to_char(ch, buf);
}
strcpy(buf, "");
len = 0;
found = 0;
} /*object is in zone*/
} /*check objects*/
/* Check rooms */
send_to_char(ch, "\r\nChecking Rooms for limits...\r\n");
for (i=0; i<top_of_world;i++) {
if (world[i].zone==zrnum) {
for (j = 0; j < NUM_OF_DIRS; j++) {
/*check for exit, but ignore off limits if you're in an offlimit zone*/
if (!world[i].dir_option[j])
continue;
exroom=world[i].dir_option[j]->to_room;
if (exroom==NOWHERE)
continue;
if (world[exroom].zone == zrnum)
continue;
if (world[exroom].zone == world[i].zone)
continue;
for (k=0;offlimit_zones[k] != -1;k++) {
if (world[exroom].zone == real_zone(offlimit_zones[k]) && (found = 1))
len += snprintf(buf + len, sizeof(buf) - len,
"- Exit %s cannot connect to %d (zone off limits).\r\n",
dirs[j], world[exroom].number);
} /* for (k.. */
} /* cycle directions */
if (ROOM_FLAGGED(i, ROOM_ATRIUM | ROOM_HOUSE | ROOM_HOUSE_CRASH | ROOM_OLC | ROOM_BFS_MARK))
len += snprintf(buf + len, sizeof(buf) - len,
"- Has illegal affection bits set (%s %s %s %s %s)\r\n",
ROOM_FLAGGED(i, ROOM_ATRIUM) ? "ATRIUM" : "",
ROOM_FLAGGED(i, ROOM_HOUSE) ? "HOUSE" : "",
ROOM_FLAGGED(i, ROOM_HOUSE_CRASH) ? "HCRSH" : "",
ROOM_FLAGGED(i, ROOM_OLC) ? "OLC" : "",
ROOM_FLAGGED(i, ROOM_BFS_MARK) ? "*" : "");
if ((MIN_ROOM_DESC_LENGTH) && strlen(world[i].description)<MIN_ROOM_DESC_LENGTH && (found=1))
len += snprintf(buf + len, sizeof(buf) - len,
"- Room description is too short. (%4.4d of min. %d characters).\r\n",
strlen(world[i].description), MIN_ROOM_DESC_LENGTH);
if (strncmp(world[i].description, " ", 3) && (found=1))
len += snprintf(buf + len, sizeof(buf) - len,
"- Room description not formatted with indent (/fi in the editor).\r\n");
/* strcspan = size of text in first arg before any character in second arg */
if ((strcspn(world[i].description, "\r\n")>MAX_COLOUMN_WIDTH) && (found=1))
len += snprintf(buf + len, sizeof(buf) - len,
"- Room description not wrapped at %d chars (/fi in the editor).\r\n",
MAX_COLOUMN_WIDTH);
for (ext2 = NULL, ext = world[i].ex_description; ext; ext = ext->next)
if (strncmp(ext->description, " ", 3))
ext2 = ext;
if (ext2 && (found = 1))
len += snprintf(buf + len, sizeof(buf) - len,
"- has unformatted extra description\r\n");
if (found) {
send_to_char(ch, "[%5d] %-30s: \r\n",
world[i].number, world[i].name ? world[i].name : "An unnamed room");
send_to_char(ch, buf);
strcpy(buf, "");
len = 0;
found = 0;
}
} /*is room in this zone?*/
} /*checking rooms*/
for (i=0; i<top_of_world;i++) {
if (world[i].zone==zrnum) {
m++;
for (j = 0, k = 0; j < NUM_OF_DIRS; j++)
if (!world[i].dir_option[j])
k++;
if (k == NUM_OF_DIRS)
l++;
}
}
if (l * 3 > m)
send_to_char(ch, "More than 1/3 of the rooms are not linked.\r\n");
}
void mob_checkload(struct char_data *ch, mob_vnum mvnum)
{
int cmd_no;
zone_rnum zone;
mob_rnum mrnum = real_mobile(mvnum);
if (mrnum == NOBODY) {
send_to_char(ch, "That mob does not exist.\r\n");
return;
}
send_to_char(ch, "Checking load info for the mob %s...\r\n",
mob_proto[mrnum].player.short_descr);
for (zone=0; zone <= top_of_zone_table; zone++) {
for (cmd_no = 0; ZCMD2.command != 'S'; cmd_no++) {
if (ZCMD2.command != 'M')
continue;
/* read a mobile */
if (ZCMD2.arg1 == mrnum) {
send_to_char(ch, " [%5d] %s (%d MAX)\r\n",
world[ZCMD2.arg3].number,
world[ZCMD2.arg3].name,
ZCMD2.arg2);
}
}
}
}
void obj_checkload(struct char_data *ch, obj_vnum ovnum)
{
int cmd_no;
zone_rnum zone;
obj_rnum ornum = real_object(ovnum);
room_vnum lastroom_v = 0;
room_rnum lastroom_r = 0;
mob_rnum lastmob_r = 0;
if (ornum ==NOTHING) {
send_to_char(ch, "That object does not exist.\r\n");
return;
}
send_to_char(ch, "Checking load info for the obj %s...\r\n",
obj_proto[ornum].short_description);
for (zone=0; zone <= top_of_zone_table; zone++) {
for (cmd_no = 0; ZCMD2.command != 'S'; cmd_no++) {
switch (ZCMD2.command) {
case 'M':
lastroom_v = world[ZCMD2.arg3].number;
lastroom_r = ZCMD2.arg3;
lastmob_r = ZCMD2.arg1;
break;
case 'O': /* read an object */
lastroom_v = world[ZCMD2.arg3].number;
lastroom_r = ZCMD2.arg3;
if (ZCMD2.arg1 == ornum)
send_to_char(ch, " [%5d] %s (%d Max)\r\n",
lastroom_v,
world[lastroom_r].name,
ZCMD2.arg2);
break;
case 'P': /* object to object */
if (ZCMD2.arg1 == ornum)
send_to_char(ch, " [%5d] %s (Put in another object [%d Max])\r\n",
lastroom_v,
world[lastroom_r].name,
ZCMD2.arg2);
break;
case 'G': /* obj_to_char */
if (ZCMD2.arg1 == ornum)
send_to_char(ch, " [%5d] %s (Given to %s [%d][%d Max])\r\n",
lastroom_v,
world[lastroom_r].name,
mob_proto[lastmob_r].player.short_descr,
mob_index[lastmob_r].vnum,
ZCMD2.arg2);
break;
case 'E': /* object to equipment list */
if (ZCMD2.arg1 == ornum)
send_to_char(ch, " [%5d] %s (Equipped to %s [%d][%d Max])\r\n",
lastroom_v,
world[lastroom_r].name,
mob_proto[lastmob_r].player.short_descr,
mob_index[lastmob_r].vnum,
ZCMD2.arg2);
break;
case 'R': /* rem obj from room */
lastroom_v = world[ZCMD2.arg1].number;
lastroom_r = ZCMD2.arg1;
if (ZCMD2.arg2 == ornum)
send_to_char(ch, " [%5d] %s (Removed from room)\r\n",
lastroom_v,
world[lastroom_r].name);
break;
}/* switch */
} /*for cmd_no......*/
} /*for zone...*/
}
void trg_checkload(struct char_data *ch, trig_vnum tvnum)
{
int cmd_no, found = 0;
zone_rnum zone;
trig_rnum trnum = real_trigger(tvnum);
room_vnum lastroom_v = 0;
room_rnum lastroom_r = 0, k;
mob_rnum lastmob_r = 0, i;
obj_rnum lastobj_r = 0, j;
struct trig_proto_list *tpl;
if (trnum == NOTHING) {
send_to_char(ch, "That trigger does not exist.\r\n");
return;
}
send_to_char(ch, "Checking load info for the %s trigger '%s':\r\n",
trig_index[trnum]->proto->attach_type == MOB_TRIGGER ? "mobile" :
(trig_index[trnum]->proto->attach_type == OBJ_TRIGGER ? "object" : "room"),
trig_index[trnum]->proto->name);
for (zone=0; zone <= top_of_zone_table; zone++) {
for (cmd_no = 0; ZCMD2.command != 'S'; cmd_no++) {
switch (ZCMD2.command) {
case 'M':
lastroom_v = world[ZCMD2.arg3].number;
lastroom_r = ZCMD2.arg3;
lastmob_r = ZCMD2.arg1;
break;
case 'O': /* read an object */
lastroom_v = world[ZCMD2.arg3].number;
lastroom_r = ZCMD2.arg3;
lastobj_r = ZCMD2.arg1;
break;
case 'P': /* object to object */
lastobj_r = ZCMD2.arg1;
break;
case 'G': /* obj_to_char */
lastobj_r = ZCMD2.arg1;
break;
case 'E': /* object to equipment list */
lastobj_r = ZCMD2.arg1;
break;
case 'R': /* rem obj from room */
lastroom_v = 0;
lastroom_r = 0;
lastobj_r = 0;
lastmob_r = 0;
case 'T': /* trigger to something */
if (ZCMD2.arg2 != trnum)
break;
if (ZCMD2.arg1 == MOB_TRIGGER) {
send_to_char(ch, "mob [%5d] %-60s (zedit room %5d)\r\n",
mob_index[lastmob_r].vnum,
mob_proto[lastmob_r].player.short_descr,
lastroom_v);
found = 1;
} else if (ZCMD2.arg1 == OBJ_TRIGGER) {
send_to_char(ch, "obj [%5d] %-60s (zedit room %d)\r\n",
obj_index[lastobj_r].vnum,
obj_proto[lastobj_r].short_description,
lastroom_v);
found = 1;
} else if (ZCMD2.arg1==WLD_TRIGGER) {
send_to_char(ch, "room [%5d] %-60s (zedit)\r\n",
lastroom_v,
world[lastroom_r].name);
found = 1;
}
break;
} /* switch */
} /*for cmd_no......*/
} /*for zone...*/
for (i = 0; i < top_of_mobt; i++) {
if (!mob_proto[i].proto_script)
continue;
for (tpl = mob_proto[i].proto_script;tpl;tpl = tpl->next)
if (tpl->vnum == tvnum) {
send_to_char(ch, "mob [%5d] %s\r\n",
mob_index[i].vnum,
mob_proto[i].player.short_descr);
found = 1;
}
}
for (j = 0; j < top_of_objt; j++) {
if (!obj_proto[j].proto_script)
continue;
for (tpl = obj_proto[j].proto_script;tpl;tpl = tpl->next)
if (tpl->vnum == tvnum) {
send_to_char(ch, "obj [%5d] %s\r\n",
obj_index[j].vnum,
obj_proto[j].short_description);
found = 1;
}
}
for (k = 0;k < top_of_world; k++) {
if (!world[k].proto_script)
continue;
for (tpl = world[k].proto_script;tpl;tpl = tpl->next)
if (tpl->vnum == tvnum) {
send_to_char(ch, "room[%5d] %s\r\n",
world[k].number,
world[k].name);
found = 1;
}
}
if (!found)
send_to_char(ch, "This trigger is not attached to anything.\r\n");
}
ACMD(do_checkloadstatus)
{
char buf1[MAX_INPUT_LENGTH], buf2[MAX_INPUT_LENGTH];
two_arguments(argument, buf1, buf2);
if ((!*buf1) || (!*buf2) || (!isdigit(*buf2))) {
send_to_char(ch, "Checkload <M | O | T> <vnum>\r\n");
return;
}
if (LOWER(*buf1) == 'm') {
mob_checkload(ch, atoi(buf2));
return;
}
if (LOWER(*buf1) == 'o') {
obj_checkload(ch, atoi(buf2));
return;
}
if (LOWER(*buf1) == 't') {
trg_checkload(ch, atoi(buf2));
return;
}
}
/* Zone Checker code above. */
/* (c) 1996-97 Erwin S. Andreasen. */
ACMD(do_copyover)
{
FILE *fp;
struct descriptor_data *d, *d_next;
char buf [100], buf2[100];
fp = fopen (COPYOVER_FILE, "w");
if (!fp) {
send_to_char (ch, "Copyover file not writeable, aborted.\n\r");
return;
}
sprintf (buf, "\n\r *** COPYOVER by %s - please remain seated!\n\r", GET_NAME(ch));
/* write boot_time as first line in file */
fprintf(fp, "%ld\n", boot_time);
/* For each playing descriptor, save its state */
for (d = descriptor_list; d ; d = d_next) {
struct char_data * och = d->character;
/* We delete from the list , so need to save this */
d_next = d->next;
/* drop those logging on */
if (!d->character || d->connected > CON_PLAYING) {
write_to_descriptor (d->descriptor, "\n\rSorry, we are rebooting. Come back in a few minutes.\n\r");
close_socket (d); /* throw'em out */
} else {
fprintf (fp, "%d %ld %s %s\n", d->descriptor, GET_PREF(och), GET_NAME(och), d->host);
/* save och */
Crash_rentsave(och,0);
save_char(och);
write_to_descriptor (d->descriptor, buf);
}
}
fprintf (fp, "-1\n");
fclose (fp);
/* exec - descriptors are inherited */
sprintf (buf, "%d", port);
sprintf (buf2, "-C%d", mother_desc);
/* Ugh, seems it is expected we are 1 step above lib - this may be dangerous! */
chdir ("..");
/* Close reserve and other always-open files and release other resources */
execl (EXE_FILE, "circle", buf2, buf, (char *) NULL);
/* Failed - successful exec will not return */
perror ("do_copyover: execl");
send_to_char (ch, "Copyover FAILED!\n\r");
exit (1); /* too much trouble to try to recover! */
}
ACMD(do_peace)
{
struct char_data *vict, *next_v;
act ("As $n makes a strange arcane gesture, a golden light descends\r\n"
"from the heavens stopping all the fighting.\r\n",FALSE, ch, 0, 0, TO_ROOM);
send_to_room(IN_ROOM(ch), "Everything is quite peaceful now.\r\n");
for(vict=world[IN_ROOM(ch)].people; vict; vict=next_v) {
next_v = vict->next_in_room;
if (FIGHTING(vict))
stop_fighting(vict);
if (IS_NPC(vict))
clearMemory(vict);
}
}
ACMD(do_zpurge)
{
int vroom, room, vzone = 0, zone = 0;
char arg[MAX_INPUT_LENGTH];
int purge_all = FALSE;
one_argument(argument, arg);
if (*arg == '.' || !*arg) {
zone = world[IN_ROOM(ch)].zone;
vzone = zone_table[zone].number;
}
else if (is_number(arg)) {
vzone = atoi(arg);
zone = real_zone(vzone);
if (zone == NOWHERE || zone > top_of_zone_table) {
send_to_char(ch, "That zone doesn't exist!\r\n");
return;
}
}
else if (*arg == '*') {
purge_all = TRUE;
}
else {
send_to_char(ch, "That isn't a valid zone number!\r\n");
return;
}
if (GET_LEVEL(ch) < LVL_GOD && !can_edit_zone(ch, zone)) {
send_to_char(ch, "You can only purge your own zone!\r\n");
return;
}
if (!purge_all) {
for (vroom = zone_table[zone].bot; vroom <= zone_table[zone].top; vroom++) {
purge_room(real_room(vroom));
}
send_to_char(ch, "Purged zone #%d: %s.\r\n", zone_table[zone].number, zone_table[zone].name);
mudlog(NRM, MAX(LVL_GRGOD, GET_INVIS_LEV(ch)), TRUE, "(GC) %s purged zone %d (%s)", GET_NAME(ch), zone, zone_table[zone].name);
}
else {
for (room = 0; room <= top_of_world; room++) {
purge_room(room);
}
send_to_char(ch, "Purged world.\r\n");
mudlog(NRM, MAX(LVL_GRGOD, GET_INVIS_LEV(ch)), TRUE, "(GC) %s purged entire world.", GET_NAME(ch));
}
}
ACMD(do_file)
{
FILE *req_file;
int cur_line = 0, num_lines = 0, req_lines = 0, i, j, l;
char field[MAX_INPUT_LENGTH], value[MAX_INPUT_LENGTH], line[READ_SIZE];
char buf[MAX_STRING_LENGTH];
size_t len = 0, nlen;
struct file_struct {
char *cmd;
char level;
char *file;
} fields[] = {
{ "bugs", LVL_GOD, "../lib/misc/bugs"},
{ "typos", LVL_GOD, "../lib/misc/typos"},
{ "ideas", LVL_GOD, "../lib/misc/ideas"},
{ "xnames", LVL_GOD, "../lib/misc/xnames"},
{ "levels", LVL_GOD, "../log/levels" },
{ "rip", LVL_GOD, "../log/rip" },
{ "players", LVL_GOD, "../log/newplayers" },
{ "rentgone", LVL_GOD, "../log/rentgone" },
{ "errors", LVL_GOD, "../log/errors" },
{ "godcmds", LVL_GOD, "../log/godcmds" },
{ "syslog", LVL_GOD, "../syslog" },
{ "crash", LVL_GOD, "../syslog.CRASH" },
{ "help", LVL_GOD, "../log/help" },
{ "changelog", LVL_GOD, "../changelog" },
{ "\n", 0, "\n" }
};
skip_spaces(&argument);
if (!*argument) {
send_to_char(ch, "USAGE: file <option> <num lines>\r\n\r\nFile options:\r\n");
for (j = 0, i = 0; fields[i].level; i++)
if (fields[i].level <= GET_LEVEL(ch))
send_to_char(ch, "%-15s%s\r\n", fields[i].cmd, fields[i].file);
return;
}
two_arguments(argument, field, value);
for (l = 0; *(fields[l].cmd) != '\n'; l++)
if (!strncmp(field, fields[l].cmd, strlen(field)))
break;
if(*(fields[l].cmd) == '\n') {
send_to_char(ch, "That is not a valid option!\r\n");
return;
}
if (GET_LEVEL(ch) < fields[l].level) {
send_to_char(ch, "You are not godly enough to view that file!\r\n");
return;
}
if(!*value)
req_lines = 15; /* Default is the last 30 lines. */
else
req_lines = atoi(value);
if (!(req_file=fopen(fields[l].file,"r"))) {
mudlog(BRF, LVL_IMPL, TRUE,
"SYSERR: Error opening file %s using 'file' command.",
fields[l].file);
return;
}
get_line(req_file, line);
while (!feof(req_file)) {
num_lines++;
get_line(req_file,line);
}
rewind(req_file);
/* Limit the maximum number of lines to 300. */
req_lines = MIN(MIN(req_lines, num_lines), 300);
len = snprintf(buf, sizeof(buf), "Last %d lines of %s:\r\n", req_lines, fields[l].file);
if (req_lines == num_lines)
len += snprintf(buf + len, sizeof(buf) - len, "Top of file.\r\n");
get_line(req_file,line);
while (!feof(req_file)) {
cur_line++;
if(cur_line > (num_lines - req_lines)) {
nlen = snprintf(buf + len, sizeof(buf) - len, "%s\r\n", line);
if (len + nlen >= sizeof(buf) || nlen < 0)
break;
len += nlen;
}
get_line(req_file,line);
}
fclose(req_file);
if (len >= sizeof(buf)) {
const char *overflow = "\r\n**OVERFLOW**\r\n";
strcpy(buf + sizeof(buf) - strlen(overflow) - 1, overflow); /* strcpy: OK */
}
page_string(ch->desc, buf, 1);
}
ACMD(do_changelog)
{
time_t rawtime;
char tmstr[MAX_INPUT_LENGTH], line[READ_SIZE], last_buf[READ_SIZE],
buf[READ_SIZE];
FILE *fl, *new;
skip_spaces(&argument);
if (!*argument) {
send_to_char(ch, "Usage: changelog <change>\r\n");
return;
}
sprintf(buf, "%s.bak", CHANGE_LOG_FILE);
if (rename(CHANGE_LOG_FILE, buf)) {
mudlog(BRF, LVL_IMPL, TRUE,
"SYSERR: Error making backup changelog file (%s)", buf);
return;
}
if (!(fl = fopen(buf, "r"))) {
mudlog(BRF, LVL_IMPL, TRUE,
"SYSERR: Error opening backup changelog file (%s)", buf);
return;
}
if (!(new = fopen(CHANGE_LOG_FILE, "w"))) {
mudlog(BRF, LVL_IMPL, TRUE,
"SYSERR: Error opening new changelog file (%s)", CHANGE_LOG_FILE);
return;
}
while (get_line(fl, line)) {
if (*line != '[')
fprintf(new, "%s\n", line);
else {
strcpy(last_buf, line);
break;
}
}
rawtime = time(0);
strftime(tmstr, sizeof(tmstr), "%b %d %Y", localtime(&rawtime));
sprintf(buf, "[%s] - %s", tmstr, GET_NAME(ch));
fprintf(new, "%s\n", buf);
fprintf(new, " %s\n", argument);
if (strcmp(buf, last_buf))
fprintf(new, "%s\n", line);
while (get_line(fl, line))
fprintf(new, "%s\n", line);
fclose(fl);
fclose(new);
send_to_char(ch, "Change added.\r\n");
}
#define PLIST_FORMAT \
"Usage: plist [minlev[-maxlev]] [-n name] [-d days] [-h hours] [-i] [-m]"
ACMD(do_plist)
{
int i, len = 0, count = 0;
char mode, buf[MAX_STRING_LENGTH], name_search[MAX_NAME_LENGTH], time_str[MAX_STRING_LENGTH];
struct time_info_data time_away;
int low = 0, high = LVL_IMPL, low_day = 0, high_day = 10000, low_hr = 0, high_hr = 24;
skip_spaces(&argument);
strcpy(buf, argument); /* strcpy: OK (sizeof: argument == buf) */
name_search[0] = '\0';
while (*buf) {
char arg[MAX_INPUT_LENGTH], buf1[MAX_INPUT_LENGTH];
half_chop(buf, arg, buf1);
if (isdigit(*arg)) {
if (sscanf(arg, "%d-%d", &low, &high) == 1)
high = low;
strcpy(buf, buf1); /* strcpy: OK (sizeof: buf1 == buf) */
} else if (*arg == '-') {
mode = *(arg + 1); /* just in case; we destroy arg in the switch */
switch (mode) {
case 'l':
half_chop(buf1, arg, buf);
sscanf(arg, "%d-%d", &low, &high);
break;
case 'n':
half_chop(buf1, name_search, buf);
break;
case 'i':
strcpy(buf, buf1);
low = LVL_IMMORT;
break;
case 'm':
strcpy(buf, buf1);
high = LVL_IMMORT - 1;
break;
case 'd':
half_chop(buf1, arg, buf);
if (sscanf(arg, "%d-%d", &low_day, &high_day) == 1)
high_day = low_day;
break;
case 'h':
half_chop(buf1, arg, buf);
if (sscanf(arg, "%d-%d", &low_hr, &high_hr) == 1)
high_hr = low_hr;
break;
default:
send_to_char(ch, "%s\r\n", PLIST_FORMAT);
return;
}
} else {
send_to_char(ch, "%s\r\n", PLIST_FORMAT);
return;
}
}
len = 0;
len += snprintf(buf + len, sizeof(buf) - len, "@W[ Id] (Lv) Name Last@n\r\n"
"%s-----------------------------------------------%s\r\n", CCCYN(ch, C_NRM),
CCNRM(ch, C_NRM));
for (i = 0; i <= top_of_p_table; i++) {
if (player_table[i].level < low || player_table[i].level > high)
continue;
time_away = *real_time_passed(time(0), player_table[i].last);
if (*name_search && str_cmp(name_search, player_table[i].name))
continue;
if (time_away.day > high_day || time_away.day < low_day)
continue;
if (time_away.hours > high_hr || time_away.hours < low_hr)
continue;
strcpy(time_str, asctime(localtime(&player_table[i].last)));
time_str[strlen(time_str) - 1] = '\0';
len += snprintf(buf + len, sizeof(buf) - len, "[%3ld] (%2d) %c%-15s %s\r\n",
player_table[i].id, player_table[i].level,
UPPER(*player_table[i].name), player_table[i].name + 1, time_str);
count++;
}
snprintf(buf + len, sizeof(buf) - len, "%s-----------------------------------------------%s\r\n"
"%d players listed.\r\n", CCCYN(ch, C_NRM), CCNRM(ch, C_NRM), count);
page_string(ch->desc, buf, TRUE);
}
ACMD(do_wizupdate)
{
run_autowiz();
send_to_char(ch, "Wizlists updated.\n\r");
}