/* ************************************************************************ * File: utils.c EmpireMUD AD 1.0 * * Usage: various internal functions of a utility nature * * * * All rights reserved. See license.doc for complete information. * * * * Code base by Paul Clarke. EmpireMUD Project, a tbgMUD Production. * * Based upon CircleMUD 3.0, beta patch level 17, by Jeremy Elson. * * * * 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 "db.h" #include "comm.h" #include "handler.h" #include "interpreter.h" #include "skills.h" #include "empire.h" #include "vnums.h" extern struct time_data time_info; int last_action_rotation = 0; /* creates a random number in interval [from;to] */ int number(int from, int to) { unsigned long empire_random(); /* error checking in case people call number() incorrectly */ if (from > to) { int tmp = from; from = to; to = tmp; } return ((empire_random() % (to - from + 1)) + from); } /* simulates dice roll */ int dice(int number, int size) { unsigned long empire_random(); int sum = 0; if (size <= 0 || number <= 0) return (0); while (number-- > 0) sum += ((empire_random() % size) + 1); return (sum); } /* * simulates White Wolf 10-sided dice roll * It rolls num 10-sided dice and returns the number * of dice with results >= diff. diff is, by default, * max 10, min 2. Each result of 1 subtracts one * "success" so the function may return 0 or a negative * number */ int ww_dice(int num, int diff) { int result = 0; int i, n; for (i = 0; i < num; i++) if ((n = number(1, 13)) == 1) result -= 1; else if (((n) > 10 ? (n - 5) : (n)) >= MIN(10, MAX(2, diff))) result += 1; return (result); } char *CAP(char *txt) { *txt = UPPER(*txt); return (txt); } /* Create a duplicate of a string */ char *str_dup(const char *source) { char *new_z; CREATE(new_z, char, strlen(source) + 1); return (strcpy(new_z, source)); } /* * Strips \r\n from end of string. */ void prune_crlf(char *txt) { int i = strlen(txt) - 1; while (txt[i] == '\n' || txt[i] == '\r') txt[i--] = '\0'; } /* * str_cmp: a case-insensitive version of strcmp(). * Returns: 0 if equal, > 0 if arg1 > arg2, or < 0 if arg1 < arg2. * * Scan until strings are found different or we reach the end of both. */ int str_cmp(const char *arg1, const char *arg2) { int chk, i; if (arg1 == NULL || arg2 == NULL) { log("SYSERR: str_cmp() passed a NULL pointer, %p or %p.", arg1, arg2); return (0); } for (i = 0; arg1[i] || arg2[i]; i++) if ((chk = LOWER(arg1[i]) - LOWER(arg2[i])) != 0) return (chk); /* not equal */ return (0); } /* * strn_cmp: a case-insensitive version of strncmp(). * Returns: 0 if equal, > 0 if arg1 > arg2, or < 0 if arg1 < arg2. * * Scan until strings are found different, the end of both, or n is reached. */ int strn_cmp(const char *arg1, const char *arg2, int n) { int chk, i; if (arg1 == NULL || arg2 == NULL) { log("SYSERR: strn_cmp() passed a NULL pointer, %p or %p.", arg1, arg2); return (0); } for (i = 0; (arg1[i] || arg2[i]) && (n > 0); i++, n--) if ((chk = LOWER(arg1[i]) - LOWER(arg2[i])) != 0) return (chk); /* not equal */ return (0); } /* * str_str: a case-insensitive version of strstr(). * One note is that it doesn't return a pointer like strstr, just * 1 or 0 where 1 is found, 0 is not */ bool str_str(const char *arg1, const char *arg2) { char *new1, *new2; int i; if (!arg1 || !arg2 || !*arg1 || !*arg2) return 0; CREATE(new1, char, strlen(arg1) + 1); strncpy(new1, arg1, strlen(arg1)); CREATE(new2, char, strlen(arg2) + 1); strncpy(new2, arg2, strlen(arg2)); for (i = 0; i < strlen(new1); i++) new1[i] = LOWER(new1[i]); for (i = 0; i < strlen(new2); i++) new2[i] = LOWER(new2[i]); if (strstr(new1, new2)) return 1; return 0; } /* * New variable argument log() function. Works the same as the old for * previously written code but is very nice for new code. */ void basic_mud_log(const char *format, ...) { va_list args; time_t ct = time(0); char *time_s = asctime(localtime(&ct)); if (logfile == NULL) puts("SYSERR: Using log() before stream was initialized!"); if (format == NULL) format = "SYSERR: log() received a NULL format."; time_s[strlen(time_s) - 1] = '\0'; fprintf(logfile, "%-15.15s :: ", time_s + 4); va_start(args, format); vfprintf(logfile, format, args); va_end(args); fprintf(logfile, "\n"); fflush(logfile); } /* the "touch" command, essentially. */ int touch(const char *path) { FILE *fl; if (!(fl = fopen(path, "a"))) { log("SYSERR: %s: %s", path, strerror(errno)); return (-1); } else { fclose(fl); return (0); } } void syslog(int level, bool file, const char *str, ...) { char output[MAX_STRING_LENGTH]; Descr i; va_list tArgList; if (!str) return; va_start(tArgList, str); vsprintf(output, str, tArgList); if (file) log(output); for (i = descriptor_list; i; i = i->next) { if (STATE(i) != CON_PLAYING || IS_NPC(i->character)) /* switch */ continue; if (PLR_FLAGGED(i->character, PLR_WRITING)) continue; if (GET_LEVEL(i->character) < LVL_START_IMM) continue; if (GET_LEVEL(i->character) < level) continue; msg_to_char(i->character, "&2[ %s ]&0\r\n", output); } } void mortlog(Creature ch, const char *str, ...) { char output[MAX_STRING_LENGTH]; Descr i; va_list tArgList; if (!str) return; va_start(tArgList, str); vsprintf(output, str, tArgList); for (i = descriptor_list; i; i = i->next) { if (STATE(i) != CON_PLAYING || IS_NPC(i->character)) /* switch */ continue; if (PLR_FLAGGED(i->character, PLR_WRITING)) continue; if (!PRF_FLAGGED(i->character, PRF_MORTLOG)) continue; msg_to_char(i->character, "&6[ %s ]&0\r\n", output); } va_end(tArgList); } /* * If you don't have a 'const' array, just cast it as such. It's safer * to cast a non-const array as const than to cast a const one as non-const. * Doesn't really matter since this function doesn't change the array though. */ void sprintbit(bitvector_t bitvector, const char *names[], char *result, byte space) { long nr; *result = '\0'; for (nr = 0; bitvector; bitvector >>= 1) { if (IS_SET(bitvector, 1)) { if (*names[nr] != '\n') { strcat(result, names[nr]); if (space) strcat(result, " "); } else strcat(result, "UNDEFINED "); } if (*names[nr] != '\n') nr++; } if (!*result && space) strcpy(result, "NOBITS "); } void sprinttype(int type, const char *names[], char *result) { int nr = 0; while (type && *names[nr] != '\n') { type--; nr++; } if (*names[nr] != '\n') strcpy(result, names[nr]); else strcpy(result, "UNDEFINED"); } /* Calculate the REAL time passed over the last t2-t1 centuries (secs) */ struct time_info_data *real_time_passed(time_t t2, time_t t1) { long secs; static struct time_info_data now; secs = (long) (t2 - t1); now.hours = (secs / SECS_PER_REAL_HOUR) % 24; /* 0..23 hours */ secs -= SECS_PER_REAL_HOUR * now.hours; now.day = (secs / SECS_PER_REAL_DAY); /* 0..29 days */ /* secs -= SECS_PER_REAL_DAY * now.day; - Not used. */ now.month = -1; now.year = -1; return (&now); } /* Calculate the MUD time passed over the last t2-t1 centuries (secs) */ struct time_info_data *mud_time_passed(time_t t2, time_t t1) { long secs; static struct time_info_data now; secs = (long) (t2 - t1); now.hours = (secs / SECS_PER_MUD_HOUR) % 24; /* 0..23 hours */ secs -= SECS_PER_MUD_HOUR * now.hours; now.day = (secs / SECS_PER_MUD_DAY) % 30; /* 0..29 days */ secs -= SECS_PER_MUD_DAY * now.day; now.month = (secs / SECS_PER_MUD_MONTH) % 12; /* 0..11 months */ secs -= SECS_PER_MUD_MONTH * now.month; now.year = YEAR_ADD + (secs / SECS_PER_MUD_YEAR); /* YEAR_ADD..XX? years */ return (&now); } struct time_info_data *age(Creature ch) { static struct time_info_data player_age; player_age = *mud_time_passed(time(0), ch->player.time.birth); player_age.year += 17; /* All players start at 17 */ player_age.year -= YEAR_ADD; return (&player_age); } /* Check if making CH follow VICTIM will create an illegal */ /* Follow "Loop/circle" */ bool circle_follow(Creature ch, Creature victim) { Creature k; for (k = victim; k; k = k->master) { if (k == ch) return (TRUE); } return (FALSE); } /* Called when stop following persons, or stopping charm */ /* This will NOT do if a character quits/dies!! */ void stop_follower(Creature ch) { struct follow_type *j, *k; if (ch->master == NULL) return; act("You stop following $N.", FALSE, ch, 0, ch->master, TO_CHAR); act("$n stops following $N.", TRUE, ch, 0, ch->master, TO_NOTVICT); act("$n stops following you.", TRUE, ch, 0, ch->master, TO_VICT); if (ch->master->followers->follower == ch) { /* Head of follower-list? */ k = ch->master->followers; ch->master->followers = k->next; free(k); } else { /* locate follower who is not head of list */ for (k = ch->master->followers; k->next->follower != ch; k = k->next); j = k->next; k->next = j->next; free(j); } ch->master = NULL; REMOVE_BIT(AFF_FLAGS(ch), AFF_CHARM | AFF_PARTY); } /* Called when a character that follows/is followed dies */ void die_follower(Creature ch) { struct follow_type *j, *k; if (ch->master) stop_follower(ch); for (k = ch->followers; k; k = j) { j = k->next; stop_follower(k->follower); } } /* * Do NOT call this before having checked if a circle of followers * will arise. CH will follow leader */ void add_follower(Creature ch, Creature leader) { struct follow_type *k; if (ch->master) return; ch->master = leader; CREATE(k, struct follow_type, 1); k->follower = ch; k->next = leader->followers; leader->followers = k; act("You now follow $N.", FALSE, ch, 0, leader, TO_CHAR); if (CAN_SEE(leader, ch)) act("$n starts following you.", TRUE, ch, 0, leader, TO_VICT); act("$n starts to follow $N.", TRUE, ch, 0, leader, TO_NOTVICT); } /* * get_line reads the next non-blank line off of the input stream. * The newline character is removed from the input. Lines which begin * with '*' are considered to be comments. * * Returns the number of lines advanced in the file. */ int get_line(FILE *fl, char *buf) { char temp[256]; int lines = 0; do { fgets(temp, 256, fl); if (feof(fl)) return (0); lines++; } while (*temp == '*' || *temp == '\n'); temp[strlen(temp) - 1] = '\0'; strcpy(buf, temp); return (lines); } int get_filename(char *orig_name, char *filename, int mode) { const char *prefix, *middle, *suffix; char name[64], *ptr; if (orig_name == NULL || *orig_name == '\0' || filename == NULL) { log("SYSERR: NULL pointer or empty string passed to get_filename(), %p or %p.", orig_name, filename); return (0); } switch (mode) { case CRASH_FILE: prefix = LIB_PLROBJS; suffix = SUF_OBJS; break; case ALIAS_FILE: prefix = LIB_PLRALIAS; suffix = SUF_ALIAS; break; case ETEXT_FILE: prefix = LIB_PLRTEXT; suffix = SUF_TEXT; break; case REC_FILE: prefix = LIB_PLRREC; suffix = SUF_REC; break; case LORE_FILE: prefix = LIB_PLRLORE; suffix = SUF_LORE; break; default: return (0); } strcpy(name, orig_name); for (ptr = name; *ptr; ptr++) *ptr = LOWER(*ptr); if (LOWER(*name) <= 'e') middle = "A-E"; else if (LOWER(*name) <= 'j') middle = "F-J"; else if (LOWER(*name) <= 'o') middle = "K-O"; else if (LOWER(*name) <= 't') middle = "P-T"; else if (LOWER(*name) <= 'z') middle = "U-Z"; else middle = "ZZZ"; /* If your compiler gives you shit about <= '', use this switch: switch (LOWER(*name)) { case 'a': case 'b': case 'c': case 'd': case 'e': middle = "A-E"; break; case 'f': case 'g': case 'h': case 'i': case 'j': middle = "F-J"; break; case 'k': case 'l': case 'm': case 'n': case 'o': middle = "K-O"; break; case 'p': case 'q': case 'r': case 's': case 't': middle = "P-T"; break; case 'u': case 'v': case 'w': case 'x': case 'y': case 'z': middle = "U-Z"; break; default: middle = "ZZZ"; break; } */ sprintf(filename, "%s%s/%s.%s", prefix, middle, name, suffix); return (1); } int num_pc_in_room(Room room) { int i = 0; Creature ch; for (ch = room->people; ch != NULL; ch = ch->next_in_room) if (!IS_NPC(ch)) i++; return (i); } char *PERS(Creature ch, Creature vict, bool real) { static char output[MAX_INPUT_LENGTH]; if (!CAN_SEE(vict, ch)) return "someone"; if (!IS_NPC(ch) && GET_MORPH(ch) && !real) return morph_string(ch, MORPH_STRING_NAME); strcpy(output, GET_NAME(ch)); if (!IS_NPC(ch) && GET_LASTNAME(ch)) sprintf(output + strlen(output), " %s", GET_LASTNAME(ch)); return output; } int shift_room(int origin, int x, int y) { int o = origin; if (X_COORD(origin) + x < 0) o = origin + x + MAP_WIDTH; else if (X_COORD(origin) + x >= MAP_WIDTH) o = origin + x - MAP_WIDTH; else o = origin + x; if ((o + y * MAP_HEIGHT) >= MAP_SIZE) o = o + y * MAP_HEIGHT - MAP_SIZE; else if ((o + y * MAP_HEIGHT) < 0) o = o + y * MAP_HEIGHT + MAP_WIDTH * MAP_HEIGHT; else o = o + y * MAP_HEIGHT; if (o < 0) return 0; return o; } /* Return resources? */ void cancel_action(Creature ch) { void cancel_forging(Creature ch); void cancel_melting(Creature ch); switch (GET_ACTION(ch)) { case ACT_FORGING: cancel_forging(ch); break; case ACT_MILLING: obj_to_char(read_object(o_WHEAT, VIRTUAL), ch); break; case ACT_MELTING: cancel_melting(ch); break; case ACT_CRAFTING: obj_to_char(read_object(GET_ACTION_VNUM(ch, 0), VIRTUAL), ch); break; case ACT_SCRAPING: obj_to_char(read_object(o_TREE, VIRTUAL), ch); break; case ACT_CHIPPING: obj_to_char(read_object(GET_ACTION_VNUM(ch, 0), VIRTUAL), ch); break; } GET_ACTION(ch) = ACT_NONE; } void update_actions(void) { void finish_forging(Creature ch); void finish_melting(Creature ch); void process_dismantling(Creature ch, room_rnum room); void process_build(Creature ch, room_rnum room); void process_manufacturing(Creature ch); void cancel_forging(Creature ch); void embrace_char(Creature ch, Creature victim); extern Object make_corpse(Creature ch); extern const char *crops[]; extern const int dam_type[]; Descr d; Creature ch, c; Object obj = NULL, obj2 = NULL; int i, j, vnum = NOTHING, count; bool found = FALSE; last_action_rotation++; if (last_action_rotation > 4) last_action_rotation = 0; for (d = descriptor_list; d; d = d->next) { if (STATE(d) != CON_PLAYING || !(ch = d->character) || IS_NPC(ch) || GET_ACTION(ch) == ACT_NONE) continue; if ((GET_ACTION_ROOM(ch) != ch->in_room && GET_ACTION_ROOM(ch) != NOWHERE) || ((GET_FEEDING_FROM(ch) || GET_FED_ON_BY(ch)) && GET_ACTION(ch) != ACT_EMBRACE) || FIGHTING(ch) || GET_POS(ch) < POS_STANDING || IS_WRITING(ch)) { cancel_action(ch); continue; } if (GET_ACTION_ROTATION(ch) != last_action_rotation) continue; switch (GET_ACTION(ch)) { case ACT_BATHING: if (GET_DAYS_SINCE_BATHING(ch) > 0) { if (SECT(ch->in_room) == SECT_RIVER && !number(0, 2)) GET_DAYS_SINCE_BATHING(ch) -= 1; else if ((BUILDING_TYPE(ch->in_room) == BUILDING_BATHS || ROOM_TYPE(ch->in_room) == RTYPE_BATHS) && !number(0, 1)) GET_DAYS_SINCE_BATHING(ch) -= 1; } if (GET_DAYS_SINCE_BATHING(ch) == 0 && !IS_GOD(ch) && !IS_IMMORTAL(ch)) { msg_to_char(ch, "You finish bathing and climb out of the water to dry off.\r\n"); act("$n finishes bathing and climbs out of the water to dry off.", FALSE, ch, 0, 0, TO_ROOM); GET_ACTION(ch) = ACT_NONE; } else { switch(number(0, 2)) { case 0: msg_to_char(ch, "You wash yourself off...\r\n"); act("$n washes $mself carefully...", FALSE, ch, 0, 0, TO_ROOM); break; case 1: msg_to_char(ch, "You scrub your hair to get out any dirt and insects...\r\n"); act("$n scrubs $s hair to get out any dirt and insects...", FALSE, ch, 0, 0, TO_ROOM); break; case 2: msg_to_char(ch, "You swim through the water...\r\n"); act("$n swims through the water...", FALSE, ch, 0, 0, TO_ROOM); break; } } break; case ACT_EMBRACE: if (!GET_FEEDING_FROM(ch)) GET_ACTION(ch) = ACT_NONE; else if (GET_BLOOD(GET_FEEDING_FROM(ch)) <= 0) embrace_char(ch, GET_FEEDING_FROM(ch)); break; case ACT_DIGGING: vnum = NOTHING; if (GET_EQ(ch, WEAR_WIELD) && GET_OBJ_VNUM(GET_EQ(ch, WEAR_WIELD)) == f_SHOVEL) found = TRUE; else if (GET_EQ(ch, WEAR_HOLD) && GET_OBJ_VNUM(GET_EQ(ch, WEAR_HOLD)) == f_SHOVEL) found = TRUE; GET_ACTION_TIMER(ch) -= ww_dice(GET_STRENGTH(ch) + GET_ATHLETICS(ch) + found, 6); if (GET_ACTION_TIMER(ch) <= 0) { GET_ACTION(ch) = 0; if (vnum == NOTHING) for (i = 0; i < NUM_2D_DIRS; i++) if (SECT(real_shift(ch->in_room, shift_dir[i][0], shift_dir[i][1])) == SECT_RIVER) if (!number(0, 3)) { vnum = o_CLAY; break; } if (vnum == NOTHING) vnum = !number(0, 10) ? o_FLINT : o_ROCK; obj = read_object(vnum, VIRTUAL); if (IS_CARRYING_N(ch) >= CAN_CARRY_N(ch) || GET_OBJ_WEIGHT(obj) + IS_CARRYING_W(ch) > CAN_CARRY_W(ch)) obj_to_room(obj, ch->in_room); else obj_to_char(obj, ch); act("You pull $p from the ground!", FALSE, ch, obj, 0, TO_CHAR); act("$n pulls $p from the ground!", FALSE, ch, obj, 0, TO_ROOM); break; } send_to_char("You dig vigorously at the ground.\r\n", ch); act("$n digs vigorously at the ground.", FALSE, ch, 0, 0, TO_ROOM); break; case ACT_MORPHING: GET_ACTION_TIMER(ch) -= 1; if (GET_ACTION_TIMER(ch) <= 0) { sprintf(buf, "%s has become $n!", PERS(ch, ch, 0)); perform_morph(ch, (ubyte) GET_ACTION_VNUM(ch, 0)); act(buf, TRUE, ch, 0, 0, TO_ROOM); act("You have become $n!", FALSE, ch, 0, 0, TO_CHAR); GET_ACTION(ch) = ACT_NONE; } else { msg_to_char(ch, "Your body warps and distorts painfully!\r\n"); act("$n's body warps and distorts hideously!", TRUE, ch, 0, 0, TO_ROOM); } break; case ACT_GATHERING: send_to_char("You search the ground for sticks...\r\n", ch); act("$n searches around on the ground...", TRUE, ch, 0, 0, TO_ROOM); GET_ACTION_TIMER(ch) -= ww_dice(GET_PERCEPTION(ch) + GET_ALERTNESS(ch), 5 - SENSES_BONUS(ch)); if (GET_ACTION_TIMER(ch) <= 0) { if (SECT(ch->in_room) == SECT_FOREST_1 || SECT(ch->in_room) == SECT_FOREST_2 || SECT(ch->in_room) == SECT_FOREST_3 || SECT(ch->in_room) == SECT_FOREST_4 || (SECT(ch->in_room) == SECT_CROP && world[ch->in_room].type == CROP_FRUIT)) GET_ACTION_TIMER(ch) = number(5, 9); else GET_ACTION(ch) = ACT_NONE; obj = read_object(o_STICK, VIRTUAL); if (IS_CARRYING_N(ch) >= CAN_CARRY_N(ch) || GET_OBJ_WEIGHT(obj) + IS_CARRYING_W(ch) > CAN_CARRY_W(ch)) obj_to_room(obj, ch->in_room); else obj_to_char(obj, ch); act("You find $p!", FALSE, ch, obj, 0, TO_CHAR); act("$n finds $p!", TRUE, ch, obj, 0, TO_ROOM); break; } break; case ACT_PICKING: if (SECT(ch->in_room) == SECT_CROP && world[ch->in_room].type == CROP_FRUIT) { send_to_char("You search the trees for apples...\r\n", ch); act("$n searches the trees for apples...", TRUE, ch, 0, 0, TO_ROOM); } else { send_to_char("You search the ground for nice flowers...\r\n", ch); act("$n searches around the ground...", TRUE, ch, 0, 0, TO_ROOM); } GET_ACTION_TIMER(ch) -= ww_dice(GET_PERCEPTION(ch) + GET_ALERTNESS(ch), 5 - SENSES_BONUS(ch)); if (GET_ACTION_TIMER(ch) <= 0) { if (SECT(ch->in_room) == SECT_FIELD || (SECT(ch->in_room) == SECT_CROP && world[ch->in_room].type == CROP_FRUIT)) GET_ACTION_TIMER(ch) = number(5, 9); else GET_ACTION(ch) = ACT_NONE; if (SECT(ch->in_room) == SECT_CROP && world[ch->in_room].type == CROP_FRUIT) obj = read_object(o_APPLES, VIRTUAL); else obj = read_object(o_FLOWER, VIRTUAL); if (IS_CARRYING_N(ch) >= CAN_CARRY_N(ch) || GET_OBJ_WEIGHT(obj) + IS_CARRYING_W(ch) > CAN_CARRY_W(ch)) obj_to_room(obj, ch->in_room); else obj_to_char(obj, ch); act("You find $p!", FALSE, ch, obj, 0, TO_CHAR); act("$n finds $p!", TRUE, ch, obj, 0, TO_ROOM); break; } break; case ACT_CRAFTING: if ((!(obj = GET_EQ(ch, WEAR_WIELD)) || dam_type[GET_OBJ_VAL(obj, 2)] < DAM_LETHAL) && (obj || !(obj = GET_EQ(ch, WEAR_HOLD)) || dam_type[GET_OBJ_VAL(obj, 2)] < DAM_LETHAL)) { msg_to_char(ch, "You need to be using a sharp tool to scrape it.\r\n"); obj_to_char(read_object(GET_ACTION_VNUM(ch, 0), VIRTUAL), ch); GET_ACTION(ch) = ACT_NONE; break; } msg_to_char(ch, "You scrape at %s...\r\n", GET_OBJ_NAME_BY_PROTO(real_object(GET_ACTION_VNUM(ch, 0)))); GET_ACTION_TIMER(ch) -= ww_dice(GET_DEXTERITY(ch) + GET_CRAFTS(ch), 5); if (GET_ACTION_TIMER(ch) <= 0) { GET_ACTION(ch) = 0; obj_to_char((obj = read_object(GET_ACTION_VNUM(ch, 1), VIRTUAL)), ch); act("You craft $p!", FALSE, ch, obj, 0, TO_CHAR); act("$n crafts $p!", TRUE, ch, obj, 0, TO_ROOM); } break; case ACT_SCRAPING: if ((!(obj = GET_EQ(ch, WEAR_WIELD)) || dam_type[GET_OBJ_VAL(obj, 2)] < DAM_LETHAL) && (obj || !(obj = GET_EQ(ch, WEAR_HOLD)) || dam_type[GET_OBJ_VAL(obj, 2)] < DAM_LETHAL)) { msg_to_char(ch, "You need to be using a sharp tool to scrape it.\r\n"); obj_to_char(read_object(o_TREE, VIRTUAL), ch); GET_ACTION(ch) = ACT_NONE; break; } msg_to_char(ch, "You scrape at %s...\r\n", GET_OBJ_NAME_BY_PROTO(real_object(o_TREE))); GET_ACTION_TIMER(ch) -= 1; if (GET_ACTION_TIMER(ch) <= 0) { GET_ACTION(ch) = 0; obj_to_char((obj = read_object(o_LOG, VIRTUAL)), ch); for (i = 0; i < number(2, 5); i++) obj_to_char((obj2 = read_object(o_STICK, VIRTUAL)), ch); sprintf(buf, "You finish scraping off $p and manage to get $P (%dx)!", i); act(buf, FALSE, ch, obj, obj2, TO_CHAR); act("$n finishes scraping off $p!", TRUE, ch, obj, 0, TO_ROOM); } break; case ACT_CHIPPING: if ((!(obj = GET_EQ(ch, WEAR_WIELD)) || GET_OBJ_VAL(obj, 2) != TYPE_HAMMER) && (obj || !(obj = GET_EQ(ch, WEAR_HOLD)) || GET_OBJ_VAL(obj, 2) != TYPE_HAMMER)) { msg_to_char(ch, "You need to be using some kind of hammer to chip it.\r\n"); obj_to_char(read_object(GET_ACTION_VNUM(ch, 0), VIRTUAL), ch); GET_ACTION(ch) = ACT_NONE; break; } msg_to_char(ch, "You chip away at the piece of rock...\r\n"); GET_ACTION_TIMER(ch) -= ww_dice(GET_STRENGTH(ch) + GET_CRAFTS(ch), 5); if (GET_ACTION_TIMER(ch) <= 0) { GET_ACTION(ch) = 0; switch (GET_ACTION_VNUM(ch, 0)) { case o_ROCK: obj_to_char((obj = read_object(o_CHIPPED, VIRTUAL)), ch); msg_to_char(ch, "It splits open!\r\n"); break; case o_CHIPPED: obj_to_char((obj = read_object(o_HANDAXE, VIRTUAL)), ch); act("You have crafted $p!", FALSE, ch, obj, 0, TO_CHAR); break; case o_HANDAXE: obj_to_char((obj = read_object(o_SPEARHEAD, VIRTUAL)), ch); act("You have crafted $p!", FALSE, ch, obj, 0, TO_CHAR); break; } } break; case ACT_CHOPPING: for (count = 0; count < 1 + ATTACK_BONUS(ch) && GET_ACTION(ch) == ACT_CHOPPING; count++) { if (!GET_EQ(ch, WEAR_WIELD) || GET_OBJ_VAL(GET_EQ(ch, WEAR_WIELD), 2) != TYPE_SLICE) { send_to_char("You need to be using an axe to chop.\r\n", ch); GET_ACTION(ch) = ACT_NONE; break; } if ((i = ww_dice(GET_DEXTERITY(ch) + GET_MELEE(ch), 6)) > 0) { GET_BUILD_VALUE(ch->in_room) -= (ww_dice(GET_STRENGTH(ch) + GET_OBJ_VAL(GET_EQ(ch, WEAR_WIELD), 1) + i, 6) + GET_POTENCE(ch)); act("You swing $p hard into the tree!", FALSE, ch, GET_EQ(ch, WEAR_WIELD), 0, TO_CHAR); act("$n swings $p hard into the tree!", FALSE, ch, GET_EQ(ch, WEAR_WIELD), 0, TO_ROOM); } else { act("You swing $p, but miss the tree!", FALSE, ch, GET_EQ(ch, WEAR_WIELD), 0, TO_CHAR); act("$n swings $p, but misses the tree!", FALSE, ch, GET_EQ(ch, WEAR_WIELD), 0, TO_ROOM); } if (GET_BUILD_VALUE(ch->in_room) > 0) continue; GET_BUILD_VALUE(ch->in_room) = 0; for (c = world[ch->in_room].people; c; c = c->next_in_room) if (!IS_NPC(c) && GET_ACTION(c) == ACT_CHOPPING) GET_ACTION(c) = ACT_NONE; obj_to_room(read_object(o_TREE, VIRTUAL), ch->in_room); SECT(ch->in_room)--; if (SECT(ch->in_room) < SECT_FIELD) { SECT(ch->in_room) = SECT_FIELD; act("With a loud crack, it falls to the ground and the area is depleted!", FALSE, ch, 0, 0, TO_CHAR); act("With a loud crack, it falls to the ground and the area is depleted!", FALSE, ch, 0, 0, TO_ROOM); } else { act("With a loud crack, it falls to the ground!", FALSE, ch, 0, 0, TO_CHAR); act("With a loud crack, it falls to the ground!", FALSE, ch, 0, 0, TO_ROOM); } if (world[ch->in_room].type2 && SECT(ch->in_room) == SECT_FIELD) { SECT(ch->in_room) = SECT_DESERT; world[ch->in_room].type2 = 0; } } break; case ACT_BUILDING: for (count = 0; count < 1 + ATTACK_BONUS(ch) && GET_ACTION(ch) == ACT_BUILDING; count++) process_build(ch, ch->in_room); break; case ACT_DISMANTLING: for (count = 0; count < 1 + ATTACK_BONUS(ch) && GET_ACTION(ch) == ACT_DISMANTLING; count++) process_dismantling(ch, ch->in_room); break; case ACT_HARVESTING: if (!GET_EQ(ch, WEAR_WIELD) || (GET_OBJ_VAL(GET_EQ(ch, WEAR_WIELD), 2) != TYPE_SLICE && GET_OBJ_VAL(GET_EQ(ch, WEAR_WIELD), 2) != TYPE_SLASH)) { send_to_char("You're not using the proper tool for harvesting.\r\n", ch); GET_ACTION(ch) = ACT_NONE; break; } switch(number(0, 2)) { case 0: msg_to_char(ch, "You walk through the field, harvesting the %s.\r\n", crops[(int) world[ch->in_room].type]); sprintf(buf, "$n walks through the field, harvesting the %s.", crops[(int) world[ch->in_room].type]); act(buf, FALSE, ch, 0, 0, TO_ROOM); break; case 1: msg_to_char(ch, "You carefully harvest the %s.\r\n", crops[(int) world[ch->in_room].type]); sprintf(buf, "$n carefully harvests the %s.", crops[(int) world[ch->in_room].type]); act(buf, FALSE, ch, 0, 0, TO_ROOM); break; } GET_BUILD_VALUE(ch->in_room) -= ww_dice(GET_DEXTERITY(ch) + GET_MELEE(ch), 6); if (GET_BUILD_VALUE(ch->in_room) > 0) break; GET_BUILD_VALUE(ch->in_room) = 0; for (c = world[ch->in_room].people; c; c = c->next_in_room) if (!IS_NPC(c) && GET_ACTION(c) == ACT_HARVESTING) GET_ACTION(c) = ACT_NONE; act("You finish harvesting the crop!", FALSE, ch, 0, 0, TO_CHAR); act("$n finished harvesting the crop!", FALSE, ch, 0, 0, TO_ROOM); switch (world[ch->in_room].type) { case CROP_FRUIT: vnum = o_APPLES; break; case CROP_WHEAT: vnum = o_WHEAT; break; case CROP_CORN: vnum = o_CORN; break; default: vnum = o_APPLES; break; } j = number(1, 5); /* Give three trees for harvesting an orchard */ if(world[ch->in_room].type == CROP_FRUIT){ for(i =0; i<=3; i++){ obj_to_room(read_object(o_TREE, VIRTUAL), ch->in_room); } } for (i = 0; i <= j; i++) obj_to_room(read_object(vnum, VIRTUAL), ch->in_room); SECT(ch->in_room) = SECT_FIELD; world[ch->in_room].type = 0; break; case ACT_PLANTING: GET_ACTION_TIMER(ch)--; if (GET_ACTION_TIMER(ch)) GET_BUILD_VALUE(ch->in_room) /= 2; else { msg_to_char(ch, "You finish planting!\r\n"); act("$n finishes planting!", FALSE, ch, 0, 0, TO_ROOM); GET_ACTION(ch) = ACT_NONE; } break; case ACT_MINING: for (count = 0; count < 1 + ATTACK_BONUS(ch) && GET_ACTION(ch) == ACT_MINING; count++) { if (!GET_EQ(ch, WEAR_WIELD) || ((GET_OBJ_VAL(GET_EQ(ch, WEAR_WIELD), 2) != TYPE_PICK) && GET_OBJ_VNUM(GET_EQ(ch, WEAR_WIELD)) != o_HANDAXE)) { send_to_char("You're not using the proper tool for mining!\r\n", ch); GET_ACTION(ch) = ACT_NONE; break; } GET_ACTION_TIMER(ch) -= ww_dice(GET_STRENGTH(ch) + GET_ATHLETICS(ch), 6) + GET_POTENCE(ch); act("You pick at the walls with $p, looking for ore.", FALSE, ch, GET_EQ(ch, WEAR_WIELD), 0, TO_CHAR); act("$n picks at the walls with $p, looking for ore.", FALSE, ch, GET_EQ(ch, WEAR_WIELD), 0, TO_ROOM); if (GET_ACTION_TIMER(ch) > 0) continue; switch(world[ch->in_room].type2) { case ITEM_MAT_SILVER: vnum = o_SILVER; break; case ITEM_MAT_IRON: vnum = o_IRON; break; default: vnum = o_IRON; break; } /* Gold is now found at random *only* */ if (!number(0, 100)) vnum = o_GOLD; obj = read_object(vnum, VIRTUAL); world[ch->in_room].spare -= 1; if (IS_CARRYING_N(ch) >= CAN_CARRY_N(ch) || GET_OBJ_WEIGHT(obj) + IS_CARRYING_W(ch) > CAN_CARRY_W(ch)) obj_to_room(obj, ch->in_room); else obj_to_char(obj, ch); act("With that last stroke, $p falls from the wall!", FALSE, ch, obj, 0, TO_CHAR); act("With $s last stroke, $p falls from the wall where $n was picking!", FALSE, ch, obj, 0, TO_ROOM); GET_ACTION(ch) = ACT_NONE; } break; case ACT_MILLING: GET_ACTION_TIMER(ch) -= ww_dice(GET_INTELLIGENCE(ch) + GET_CRAFTS(ch), 5); if (GET_ACTION_TIMER(ch) > 0) { if (!number(0, 4)) { msg_to_char(ch, "You grind the millstone hard against the grain.\r\n"); act("$n grinds the millstone hard against the grain.", FALSE, ch, 0, 0, TO_ROOM); } break; } GET_ACTION(ch) = 0; msg_to_char(ch, "You finish grinding the wheat.\r\n"); act("$n finishes grinding the wheat.", FALSE, ch, 0, 0, TO_ROOM); obj_to_char(read_object(o_FLOUR, VIRTUAL), ch); break; case ACT_BAKING: GET_ACTION_TIMER(ch) -= ww_dice(GET_INTELLIGENCE(ch) + GET_CRAFTS(ch), 5); if (GET_ACTION_TIMER(ch) > 0) { if (!number(0, 4)) msg_to_char(ch, "Your bread is baking...\r\n"); break; } GET_ACTION(ch) = 0; msg_to_char(ch, "You pull the bread from the oven!\r\n"); act("$n pulls a loaf of bread from the oven!", FALSE, ch, 0, 0, TO_ROOM); obj_to_char(read_object(o_BREAD, VIRTUAL), ch); break; case ACT_FORGING: if (!GET_EQ(ch, WEAR_WIELD) || GET_OBJ_VAL(GET_EQ(ch, WEAR_WIELD), 2) != TYPE_HAMMER) { send_to_char("You need to be using a hammer to forge.\r\n", ch); cancel_forging(ch); break; } GET_ACTION_TIMER(ch) -= ww_dice(GET_DEXTERITY(ch) + GET_CRAFTS(ch), 6); if (GET_ACTION_TIMER(ch) <= 0) finish_forging(ch); else { act("You hit the anvil hard with $p!", FALSE, ch, GET_EQ(ch, WEAR_WIELD), 0, TO_CHAR); act("$n hits the anvil hard with $p!", FALSE, ch, GET_EQ(ch, WEAR_WIELD), 0, TO_ROOM); } break; case ACT_FISHING: if (!GET_EQ(ch, WEAR_WIELD) || GET_OBJ_TYPE(GET_EQ(ch, WEAR_WIELD)) != ITEM_WEAPON || GET_OBJ_VAL(GET_EQ(ch, WEAR_WIELD), 2) != TYPE_STING) { msg_to_char(ch, "You'll need a spear to fish.\r\n"); GET_ACTION(ch) = ACT_NONE; break; } GET_ACTION_TIMER(ch) -= ww_dice(GET_DEXTERITY(ch) + GET_ATHLETICS(ch), 6); if (GET_ACTION_TIMER(ch) > 0) { switch(number(0, 5)) { case 0: msg_to_char(ch, "A fish darts past you, but you narrowly miss it!\r\n"); break; case 1: msg_to_char(ch, "The water waves peacefully, but you don't see any fish..\r\n"); break; case 2: msg_to_char(ch, "The fish are jumping off in the distance, but you can't seem to catch one!\r\n"); break; } } else { GET_ACTION(ch) = ACT_NONE; char_to_room((c = read_mobile(GET_ACTION_VNUM(ch, 0) == 1 ? OCEAN_FISH : RIVER_FISH, VIRTUAL)), ch->in_room); obj_to_char((obj = make_corpse(c)), ch); SET_BIT(GET_OBJ_VAL(obj, 2), CORPSE_SKINNED); extract_char(c); msg_to_char(ch, "A fish darts past you..\r\n"); act("You jab your spear into the water and when you extract it you find $p on the end!", FALSE, ch, obj, 0, TO_CHAR); act("$n jabs $s spear into the water and when $e draws it out, it has $p on the end!", TRUE, ch, obj, 0, TO_ROOM); } break; case ACT_MELTING: GET_ACTION_TIMER(ch) -= 1; if (GET_ACTION_TIMER(ch) > 0) { if (!number(0, 2)) msg_to_char(ch, "You watch as it melts in the fire.\r\n"); break; } finish_melting(ch); break; case ACT_GLASS: GET_ACTION_TIMER(ch) -= 1; strcpy(buf1, GET_OBJ_NAME_BY_PROTO(real_object(GET_ACTION_VNUM(ch, 0)))); switch (GET_ACTION_TIMER(ch)) { case 0: obj_to_char((obj = read_object(GET_ACTION_VNUM(ch, 0), VIRTUAL)), ch); act("You complete $p.", FALSE, ch, obj, 0, TO_CHAR); act("$n has made $p.", TRUE, ch, obj, 0, TO_ROOM); GET_ACTION(ch) = ACT_NONE; break; case 1: msg_to_char(ch, "You set the glass on the table to cool.\r\n"); act("$n sets the glass on the table to cool.", TRUE, ch, 0, 0, TO_ROOM); break; case 2: msg_to_char(ch, "You roll the glass into the shape of %s.\r\n", buf1); sprintf(buf, "$n rolls the glass into the shape of %s.", buf1); act(buf, TRUE, ch, 0, 0, TO_ROOM); break; case 3: msg_to_char(ch, "You blow into the tube and inflate the glass.\r\n"); act("$n blows into the tube and inflates the glass.", TRUE, ch, 0, 0, TO_ROOM); break; case 4: msg_to_char(ch, "You roll the glass into the shape of a ball.\r\n"); act("$n rolls the glass into the shape of a ball.", TRUE, ch, 0, 0, TO_ROOM); break; case 5: msg_to_char(ch, "You blow into the tube and inflate the glass.\r\n"); act("$n blows into the tube and inflates the glass.", TRUE, ch, 0, 0, TO_ROOM); break; case 6: msg_to_char(ch, "You pull a wad of molten glass from the oven.\r\n"); act("$n pulls a wad of molten glass from the oven.", TRUE, ch, 0, 0, TO_ROOM); break; case 8: msg_to_char(ch, "You place a pile of sand in the oven.\r\n"); act("$n places a pile of sand in the oven.", TRUE, ch, 0, 0, TO_ROOM); break; } break; case ACT_MANUFACTURING: process_manufacturing(ch); break; case ACT_PANNING: if (!GET_EQ(ch, WEAR_HOLD) || GET_OBJ_VNUM(GET_EQ(ch, WEAR_HOLD)) != f_PAN) { msg_to_char(ch, "You need to be holding a pan to do that.\r\n"); GET_ACTION(ch) = ACT_NONE; break; } GET_ACTION_TIMER(ch) -= 1; msg_to_char(ch, "You sift through the sand and pebbles, looking for gold...\r\n"); act("$n sifts through the river bed, looking for gold...", TRUE, ch, 0, 0, TO_ROOM); if (GET_ACTION_TIMER(ch) <= 0) { GET_ACTION(ch) = 0; if (!number(0, 19)) { obj_to_char((obj = read_object(o_GOLD_SMALL, VIRTUAL)), ch); act("You find $p!", FALSE, ch, obj, 0, TO_CHAR); break; } msg_to_char(ch, "You find nothing of value.\r\n"); } break; case ACT_MUSIC: if (!(obj = GET_EQ(ch, WEAR_HOLD)) || GET_OBJ_TYPE(obj) != ITEM_INSTRUMENT) { msg_to_char(ch, "You need to hold an instrument to play music!\r\n"); GET_ACTION(ch) = ACT_NONE; break; } switch (GET_MUSIC(ch)) { case 1: strcpy(buf, " very poorly."); break; case 2: strcpy(buf, "."); break; case 3: strcpy(buf, " with flair."); break; case 4: strcpy(buf, " exceptionally well."); break; case 5: strcpy(buf, " majestically."); break; default: strcpy(buf, " angelically!"); break; } switch (GET_OBJ_VAL(obj, 0)) { case INSTR_LYRE: act("You strum at $p and hum to the tune.", FALSE, ch, obj, 0, TO_CHAR); if (number(0, 1)) sprintf(buf1, "$n hums a tune and strums at $p%s", buf); else sprintf(buf1, "$n plucks at $p%s", buf); act(buf1, FALSE, ch, obj, 0, TO_ROOM); break; case INSTR_FLUTE: if (number(0, 1)) act("You whistle a tune through $p.", FALSE, ch, obj, 0, TO_CHAR); else act("You play $p.", FALSE, ch, obj, 0, TO_CHAR); if (number(0, 1)) sprintf(buf1, "$n plays $p%s", buf); else { sprintf(buf1, "$n whistles a tune on $p."); if (GET_MUSIC(ch) != 2) sprintf(buf1 + strlen(buf1), "\r\nYou think $e plays it%s", buf); } act(buf1, FALSE, ch, obj, 0, TO_ROOM); break; default: msg_to_char(ch, "This instrument type is uncoded.\r\n"); GET_ACTION(ch) = ACT_NONE; break; } break; case ACT_EXCAVATING: for (count = 0; count < 1 + ATTACK_BONUS(ch) && GET_ACTION(ch) == ACT_EXCAVATING; count++) { if ((!GET_EQ(ch, WEAR_HOLD) || GET_OBJ_VNUM(GET_EQ(ch, WEAR_HOLD)) != f_SHOVEL) && (!GET_EQ(ch, WEAR_WIELD) || GET_OBJ_VNUM(GET_EQ(ch, WEAR_WIELD)) != f_SHOVEL)) { msg_to_char(ch, "You need a shovel to excavate.\r\n"); GET_ACTION(ch) = ACT_NONE; break; } if (!number(0, 1)) { msg_to_char(ch, "You jab your shovel into the dirt..\r\n"); act("$n jabs $s shovel into the dirt..", FALSE, ch, 0, 0, TO_ROOM); } else { msg_to_char(ch, "You toss a shovel-full of dirt out of the trench.\r\n"); act("$n tosses a shovel-full of dirt out of the trench.", FALSE, ch, 0, 0, TO_ROOM); } GET_BUILD_VALUE(ch->in_room) += 1; if (GET_BUILD_VALUE(ch->in_room) >= 0) { msg_to_char(ch, "You finish excavating the trench!\r\n"); act("$n finishes excavating the trench!", FALSE, ch, 0, 0, TO_ROOM); for (c = world[ch->in_room].people; c; c = c->next_in_room) if (!IS_NPC(c) && GET_ACTION(c) == ACT_EXCAVATING) GET_ACTION(c) = ACT_NONE; } } break; } } } /* strips \r's from line */ char *stripcr(char *dest, const char *src) { int i, length; char *temp; if (!dest || !src) return NULL; temp = &dest[0]; length = strlen(src); for (i = 0; *src && (i < length); i++, src++) if (*src != '\r') *(temp++) = *src; *temp = '\0'; return dest; } void update_reboot(void) { extern const char *reboot_type[]; ACMD(do_reboot); ACMD(do_confirm); extern int wizlock_level; extern char *wizlock_message; if (reboot.time < 0) return; reboot.time -= 1; if (reboot.time <= 0) { do_reboot(NULL, "", 0, reboot.type); return; } if (reboot.time <= 5) { wizlock_level = 1; sprintf(buf, "This mud is preparing to %s. The %s will happen in about %d minutes.\r\n", reboot_type[(int) reboot.type], reboot_type[(int) reboot.type], reboot.time); wizlock_message = str_dup(buf); } if (reboot.time <= 5 || (reboot.time <= 15 && (reboot.time % 2))) { syslog(0, FALSE, "The mud will %s in %d minute%s", reboot_type[(int) reboot.type], reboot.time, reboot.time != 1 ? "s" : ""); syslog(0, FALSE, "This may be accelerated if all players type 'confirm'"); mortlog(0, "The mud will %s in %d minute%s", reboot_type[(int) reboot.type], reboot.time, reboot.time != 1 ? "s" : ""); mortlog(0, "This may be accelerated if all players type 'confirm'"); } do_confirm(NULL, "", 0, 0); } struct new_eq_set_data new_eq[] = { { "\r", -1, -1, -1, -1, -1, -1, -1, -1 }, { "Archer", o_HAT, o_SHIRT, NOTHING, o_PANTS, o_SHOES, f_SHORTSWORD, o_SHORTBOW, o_QUIVER}, { "Bandit", o_HOOD, o_SHIRT, NOTHING, o_PANTS, o_SHOES, f_DAGGER, f_DIRK, NOTHING }, { "Civilian", o_HAT, o_SHIRT, NOTHING, o_PANTS, o_SHOES, f_PICK, f_DIRK, NOTHING }, { "Knight", o_HAT, o_SHIRT, o_TUNIC, o_PANTS, o_SHOES, f_SWORD, f_SWORD, NOTHING }, { "Maiden", o_HOOD, o_DRESS, NOTHING, NOTHING, o_SHOES, o_TORCH, NOTHING, NOTHING }, { "Woodsman", o_HAT, o_SHIRT, NOTHING, o_PANTS, o_SHOES, f_AXE, o_TORCH, NOTHING }, { "\n", -1, -1, -1, -1, -1, -1, -1, -1 } }; /* Some initializations for characters, including initial skills */ void do_start(Creature ch) { void set_title(Creature ch, char *title); extern int siteok_everyone; int i; Object obj; set_title(ch, NULL); /* Default Flags */ SET_BIT(PRF_FLAGS(ch), PRF_MORTLOG); if (siteok_everyone) SET_BIT(PLR_FLAGS(ch), PLR_SITEOK); GET_DAMAGE(ch) = 0; GET_MOVE(ch) = GET_MAX_MOVE(ch); /* Standard conditions */ GET_COND(ch, THIRST) = 0; GET_COND(ch, FULL) = 0; GET_COND(ch, DRUNK) = 0; GET_COND(ch, TIRED) = 0; /* Start playtime */ ch->player.time.played = 0; ch->player.time.logon = time(0); /* Set up initial lore */ if (IS_VAMPIRE(ch)) add_lore(ch, LORE_START_VAMPIRE, -1); /* Give EQ, if applicable */ if (GET_NEW_EQ_SET(ch) != 0) { if (new_eq[(int) GET_NEW_EQ_SET(ch)].head != NOTHING) equip_char(ch, read_object(new_eq[(int) GET_NEW_EQ_SET(ch)].head, VIRTUAL), WEAR_HEAD); if (new_eq[(int) GET_NEW_EQ_SET(ch)].body != NOTHING) equip_char(ch, read_object(new_eq[(int) GET_NEW_EQ_SET(ch)].body, VIRTUAL), WEAR_BODY); if (new_eq[(int) GET_NEW_EQ_SET(ch)].armor != NOTHING) equip_char(ch, read_object(new_eq[(int) GET_NEW_EQ_SET(ch)].armor, VIRTUAL), WEAR_ARMOR); if (new_eq[(int) GET_NEW_EQ_SET(ch)].legs != NOTHING) equip_char(ch, read_object(new_eq[(int) GET_NEW_EQ_SET(ch)].legs, VIRTUAL), WEAR_LEGS); if (new_eq[(int) GET_NEW_EQ_SET(ch)].feet != NOTHING) equip_char(ch, read_object(new_eq[(int) GET_NEW_EQ_SET(ch)].feet, VIRTUAL), WEAR_FEET); if (new_eq[(int) GET_NEW_EQ_SET(ch)].wield != NOTHING) equip_char(ch, read_object(new_eq[(int) GET_NEW_EQ_SET(ch)].wield, VIRTUAL), WEAR_WIELD); if (new_eq[(int) GET_NEW_EQ_SET(ch)].hold != NOTHING) equip_char(ch, read_object(new_eq[(int) GET_NEW_EQ_SET(ch)].hold, VIRTUAL), WEAR_HOLD); if (new_eq[(int) GET_NEW_EQ_SET(ch)].quiver != NOTHING) { equip_char(ch, read_object(new_eq[(int) GET_NEW_EQ_SET(ch)].quiver, VIRTUAL), WEAR_QUIVER); for (i = 0; i < GET_OBJ_VAL(GET_EQ(ch, WEAR_QUIVER), 0); i++) obj_to_obj(read_object(o_ARROW, VIRTUAL), GET_EQ(ch, WEAR_QUIVER)); } /* Food/Water */ obj_to_char(read_object(o_BREAD, VIRTUAL), ch); obj_to_char(read_object(o_BREAD, VIRTUAL), ch); obj = read_object(c_BOWL, VIRTUAL); GET_OBJ_VAL(obj, 1) = GET_OBJ_VAL(obj, 0); GET_OBJ_VAL(obj, 2) = LIQ_WATER; obj_to_char(obj, ch); } } void update_rooms(void) { extern int last_zone_rotation; int i, j, update; room_rnum room; update = last_zone_rotation + 1; if (update > NUM_ZONE_UPDATES) update = 0; for (i = 0; i <= NUM_MAP_ZONES; i++) { if (zone_table[i].rotation != update) continue; for (room = i * SIZE_MAP_ZONES; room < (i+1) * SIZE_MAP_ZONES; room++) { if (room > top_of_world) break; /* Growing Seeds */ if (SECT(room) == SECT_SEEDED) { GET_BUILD_VALUE(room)--; if (GET_BUILD_VALUE(room) <= 0) { GET_BUILD_VALUE(room) = 0; SECT(room) = SECT_CROP; } } /* Regrowing forests */ if (SECT(room) == SECT_FOREST_3 || SECT(room) == SECT_FOREST_2 || SECT(room) == SECT_FOREST_1) if (!number(0, 99) && !world[room].type2 && !ROOM_AFF_FLAGGED(room, ROOM_AFF_NO_GROW)) SECT(room)++; /* Growing new forests */ if (SECT(room) == SECT_FOREST_4) for (j = 0; j < NUM_2D_DIRS; j++) if (SECT(real_shift(room, shift_dir[j][0], shift_dir[j][1])) == SECT_FIELD) if (!number(0, 249) && !ROOM_AFF_FLAGGED(room, ROOM_AFF_NO_GROW)) { SECT(real_shift(room, shift_dir[j][0], shift_dir[j][1])) = SECT_FOREST_1; GET_BUILD_VALUE(real_shift(room, shift_dir[j][0], shift_dir[j][1])) = 0; } } } } void display_statistics_to_char(Creature ch) { extern int calculate_wealth(int e); extern int top_of_p_table; extern time_t boot_time; Creature vict; Object obj; int e, i, j; int best_empire = -1, wealthiest_empire = -1, famous_empire = -1; bool found = 0; char *tmstr; time_t mytime; int d, h, m; if (!ch) return; msg_to_char(ch, "\r\nEmpireMUD Statistics:\r\n"); mytime = boot_time; tmstr = (char *) asctime(localtime(&mytime)); *(tmstr + strlen(tmstr) - 1) = '\0'; mytime = time(0) - boot_time; d = mytime / 86400; h = (mytime / 3600) % 24; m = (mytime / 60) % 60; msg_to_char(ch, "Current uptime: Up since %s: %d day%s, %d:%02d\r\n", tmstr, d, ((d == 1) ? "" : "s"), h, m); /* Find best scores.. */ for (e = 0; e <= top_of_empiret; e++) { if (empire[e].imm_only) continue; if (empire[e].members > best_empire) best_empire = empire[e].members; if (calculate_wealth(e) > wealthiest_empire) wealthiest_empire = calculate_wealth(e); if (empire[e].fame > famous_empire) famous_empire = empire[e].fame; } if (best_empire > 1) { for (found = 0, e = 0; e <= top_of_empiret; e++) if (empire[e].members >= best_empire && !empire[e].imm_only) { msg_to_char(ch, "%s %s%s&0", found ? "," : "Most powerful empire:", empire[e].banner, empire[e].name); found = 1; } msg_to_char(ch, "\r\n"); } if (wealthiest_empire > 0) { for (found = 0, e = 0; e <= top_of_empiret; e++) if (calculate_wealth(e) >= wealthiest_empire && !empire[e].imm_only) { msg_to_char(ch, "%s %s%s&0", found ? "," : "Most wealthy empire:", empire[e].banner, empire[e].name); found = 1; } msg_to_char(ch, "\r\n"); } if (famous_empire > 0) { for (found = 0, e = 0; e <= top_of_empiret; e++) if (empire[e].fame >= famous_empire && !empire[e].imm_only) { msg_to_char(ch, "%s %s%s&0", found ? "," : "Most famous empire:", empire[e].banner, empire[e].name); found = 1; } msg_to_char(ch, "\r\n"); } for (e = 0, i = 0, j = 0; e <= top_of_empiret; e++) { i += empire[e].territory; j += empire[e].members; } msg_to_char(ch, "Total Empires: %3d Claimed Area: %d\r\n", top_of_empiret + 1, i); msg_to_char(ch, "Total Players: %5d Players in Empires: %d\r\n", top_of_p_table + 1, j); for (vict = character_list, i = 0; vict; vict = vict->next) if (IS_NPC(vict)) i++; msg_to_char(ch, "Unique Creatures: %3d Total Mobs: %d\r\n", top_of_mobt + 1, i); for (obj = object_list, i = 0; obj; obj = obj->next) i++; msg_to_char(ch, "Unique Objects: %3d Total Objects: %d\r\n", top_of_objt + 1, i); } /* Count total bits in a bitvector_t */ int count_bits(bitvector_t bits) { bitvector_t b = bits, count = 0; for (; b; b >>= 1) if (IS_SET(b, 1)) count++; return count; } /* Finds total number of mobs in the game */ int total_mobs(void) { int count, i; for (i = 0, count = 0; i <= top_of_mobt; i++) count += mob_index[i].number; return count; } /* find out if a person has resources available */ bool has_resources(Creature ch, Resource list[], bool ground) { Object obj; int i, total = 0; bool skin = FALSE; for (i = 0; list[i].vnum != -1; i++, skin = FALSE, total = 0) { if (list[i].vnum == o_SKIN) skin = TRUE; for (obj = ch->carrying; obj; obj = obj->next_content) if (GET_OBJ_VNUM(obj) == list[i].vnum) { if (skin) total += GET_OBJ_VAL(obj, 0); else total++; } if (ground) for (obj = world[ch->in_room].contents; obj; obj = obj->next_content) if (GET_OBJ_VNUM(obj) == list[i].vnum) { if (skin) total += GET_OBJ_VAL(obj, 0); else total++; } if (total < list[i].amount) { msg_to_char(ch, "You need %d more of: %s\r\n", list[i].amount - total, GET_OBJ_NAME_BY_PROTO(real_object(list[i].vnum))); return 0; } } return 1; } /* extract resources from the list, hopefully having checked has_resources */ void extract_resources(Creature ch, Resource list[], bool ground) { Object obj, next_obj; int i, remaining; bool skin = FALSE; for (i = 0; list[i].vnum != -1; i++, skin = FALSE) { if (list[i].vnum == o_SKIN) skin = TRUE; remaining = list[i].amount; for (obj = ch->carrying; obj && remaining > 0; obj = next_obj) { next_obj = obj->next_content; if (GET_OBJ_VNUM(obj) == list[i].vnum) { if (skin) remaining -= GET_OBJ_VAL(obj, 0); else remaining--; extract_obj(obj); } } if (ground) for (obj = world[ch->in_room].contents; obj && remaining > 0; obj = next_obj) { next_obj = obj->next_content; if (GET_OBJ_VNUM(obj) == list[i].vnum) { if (skin) remaining -= GET_OBJ_VAL(obj, 0); else remaining--; extract_obj(obj); } } } } /* give resources from a resource list */ void give_resources(Creature ch, Resource list[], bool split) { Object obj; int i, j, remaining; for (i = 0; list[i].vnum != -1; i++) { remaining = list[i].amount; if (list[i].vnum == o_SKIN) { obj_to_char((obj = read_object(o_SKIN, VIRTUAL)), ch); GET_OBJ_VAL(obj, 0) = remaining; continue; } if (split) remaining /= 2; for (j = 0; j < remaining; j++) { obj = read_object(list[i].vnum, VIRTUAL); if (IS_CARRYING_N(ch) >= CAN_CARRY_N(ch) || GET_OBJ_WEIGHT(obj) + IS_CARRYING_W(ch) > CAN_CARRY_W(ch)) obj_to_room(obj, ch->in_room); else obj_to_char(obj, ch); } } } /* finds the amount of a certain resource in a list */ int get_amount_of_resource(Resource list[], obj_vnum vnum) { int i; for (i = 0; list[i].vnum != -1; i++) if (list[i].vnum == vnum) return list[i].amount; return 0; } /* gets the total amount of resources (used for timers */ int get_total_resources(Resource list[]) { int i, total = 0; for (i = 0; list[i].vnum != -1; i++) total += list[i].amount; return total; }