/* ************************************************************************ * File: skills.c EmpireMUD 0.0b * * Usage: code related to non-offensive skills and abilities * * * * 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 "comm.h" #include "interpreter.h" #include "handler.h" #include "db.h" #include "skills.h" #include "vnums.h" #include "empire.h" /* Ability names */ const char *talents[] = { "Acting", "Alertness", "Athletics", "Brawl", "Dodge", "Empathy", "Intimidation", "Larceny", "Leadership", "Primal-Urge", "Subterfuge", "\n" }; const char *skills[] = { "Animal Ken", "Archery", "Crafts", "Etiquette", "Herbalism", "Melee", "Music", "Performance", "Ride", "Stealth", "Survival", "\n" }; const char *knowledges[] = { "Academics", "Enigmas", "Hearth Wisdom", "Investigation", "Law", "Linguistics", "Medicine", "Occult", "Politics", "Science", "Seneschal", "\n" }; /* external variables */ extern int last_action_rotation; extern const int dam_type[]; extern int rev_dir[]; Creature find_closest_char(Creature ch, char *arg, bool pc) { Creature best = NULL, i; int best_dist = MAP_SIZE * 2; int d[2], dist, j = 0, number; char tmpname[MAX_INPUT_LENGTH]; char *tmp = tmpname; if ((i = get_char_room_vis(ch, arg)) != NULL) return (i); strcpy(tmp, arg); if (!(number = get_number(&tmp))) return find_closest_char(ch, tmp, TRUE); for (i = character_list; i && (j <= number); i = i->next) if ((isname(tmp, i->player.name) || (i->player.lastname && isname(tmp, i->player.lastname))) && CAN_SEE(ch, i) && i->in_room != NOWHERE && (!pc || !IS_NPC(i))) { if (number == 1) { d[0] = X_COORD(HOME_ROOM(ch->in_room)) - X_COORD(HOME_ROOM(i->in_room)); d[1] = Y_COORD(HOME_ROOM(ch->in_room)) - Y_COORD(HOME_ROOM(i->in_room)); if (d[0] < (-1 * MAP_WIDTH / 2)) d[0] += MAP_WIDTH; if (d[0] > (MAP_WIDTH / 2)) d[0] -= MAP_WIDTH; if (d[1] < (-1 * MAP_HEIGHT / 2)) d[1] += MAP_HEIGHT; if (d[1] > (MAP_HEIGHT / 2)) d[1] -= MAP_HEIGHT; dist = (d[0]) * (d[0]) + (d[1]) * (d[1]); if (dist < best_dist) { best_dist = dist; best = i; } } else if (++j == number) return (i); } return (best); } ACMD(do_track) { Creature vict; int a[2], b[2], d[2], s[2], in_room, to_room, i; char *x_shifts[] = { "west", "", "east" }; char *y_shifts[] = { "south", "", "north" }; if (SECT(ch->in_room) == SECT_OCEAN || SECT(ch->in_room) == SECT_RIVER) { msg_to_char(ch, "You can't track over the ocean.\r\n"); return; } if (SECT(ch->in_room) == SECT_BUILDING || SECT(ch->in_room) == SECT_MONUMENT_CLOSED || SECT(ch->in_room) == SECT_INSIDE) { msg_to_char(ch, "Why don't you try going outside before you start tracking.\r\n"); return; } #ifdef X #undef X #endif #ifdef Y #undef Y #endif #define X 0 #define Y 1 if (IS_NPC(ch)) { send_to_char("You have no idea how.\r\n", ch); return; } one_argument(argument, arg); if (!*arg) { send_to_char("Who are you trying to track?\r\n", ch); return; } /* The person can't see the victim. */ if (!(vict = find_closest_char(ch, arg, FALSE))) { send_to_char(NOPERSON, ch); return; } if ((i = ww_dice(GET_PERCEPTION(ch) + GET_INVESTIGATION(ch), 6 - SENSES_BONUS(ch))) BOTCHED) { s[X] = number(-1, 1); s[Y] = number(-1, 1); *buf = '\0'; sprintf(buf + strlen(buf), "%s%s", y_shifts[s[Y]+1], x_shifts[s[X]+1]); if (!*buf) { msg_to_char(ch, "You sense no trail.\r\n"); return; } msg_to_char(ch, "You think you sense a trail %s from here!\r\n", buf); return; } else if (i FAILED) { msg_to_char(ch, "You sense no trail.\r\n"); return; } in_room = ch->in_room; to_room = HOME_ROOM(vict->in_room); a[X] = X_COORD(in_room); a[Y] = Y_COORD(in_room); b[X] = X_COORD(to_room); b[Y] = Y_COORD(to_room); d[X] = a[X] - b[X]; d[Y] = a[Y] - b[Y]; if (d[X] < (-1 * MAP_WIDTH / 2)) d[X] += MAP_WIDTH; if (d[X] > (MAP_WIDTH / 2)) d[X] -= MAP_WIDTH; if (d[Y] < (-1 * MAP_HEIGHT / 2)) d[Y] += MAP_HEIGHT; if (d[Y] > (MAP_HEIGHT / 2)) d[Y] -= MAP_HEIGHT; if (d[X] > 0) s[X] = -1; else if (d[X]) s[X] = 1; else s[X] = 0; if (d[Y] > 0) s[Y] = -1; else if (d[Y]) s[Y] = 1; else s[Y] = 0; if (SECT(real_shift(in_room, s[X], s[Y])) == SECT_OCEAN || SECT(real_shift(ch->in_room, s[X], s[Y])) == SECT_RIVER) { if (s[X] && SECT(real_shift(in_room, s[X], 0)) != SECT_OCEAN && SECT(real_shift(in_room, s[X], 0)) != SECT_RIVER) s[Y] = 0; else if (s[Y] && SECT(real_shift(in_room, 0, s[Y])) != SECT_OCEAN && SECT(real_shift(in_room, 0, s[Y])) != SECT_RIVER) s[X] = 0; else { msg_to_char(ch, "Unfortunately, the trail ends at the water's edge.\r\n"); return; } } if (SECT(real_shift(in_room, s[X], s[Y])) == SECT_BUILDING || SECT(real_shift(in_room, s[X], s[Y])) == SECT_MONUMENT_CLOSED || SECT(real_shift(in_room, s[X], s[Y])) == SECT_MULTI) { if (SECT(real_shift(in_room, s[X], 0)) != SECT_BUILDING && SECT(real_shift(in_room, s[X], 0)) != SECT_MONUMENT_CLOSED && SECT(real_shift(in_room, s[X], 0)) != SECT_MULTI && s[X]) s[Y] = 0; else if (SECT(real_shift(in_room, 0, s[Y])) != SECT_BUILDING && SECT(real_shift(in_room, 0, s[Y])) != SECT_MONUMENT_CLOSED && SECT(real_shift(in_room, 0, s[Y])) != SECT_MULTI && s[Y]) s[X] = 0; else { msg_to_char(ch, "The trail ends at the base of the building.\r\n"); return; } } sprintf(buf, "%s%s", y_shifts[s[Y]+1], x_shifts[s[X]+1]); if (!*buf) msg_to_char(ch, "You're already there!\r\n"); else msg_to_char(ch, "You sense a trail %s from here!\r\n", buf); } ACMD(do_steal) { Creature vict; Object obj; char vict_name[MAX_INPUT_LENGTH], obj_name[MAX_INPUT_LENGTH]; int eq_pos, ohoh = 0; if (IS_NPC(ch)) { send_to_char("You have no idea how to do that.\r\n", ch); return; } two_arguments(argument, obj_name, vict_name); if (!(vict = get_char_vis(ch, vict_name, FIND_CHAR_ROOM))) { send_to_char("Steal what from whom?\r\n", ch); return; } else if (vict == ch) { send_to_char("Come on now, that's rather stupid!\r\n", ch); return; } if (IS_GOD(vict) || IS_IMMORTAL(vict)) { msg_to_char(ch, "You can't steal from a God!\r\n"); return; } if (IS_GOD(ch) && !IS_GOD(vict)) { msg_to_char(ch, "That would just be cruel.\r\n"); return; } if (!IS_NPC(vict) && GET_MORPH(vict) != MORPH_NONE) { msg_to_char(ch, "You can't steal from someone with no inventory!\r\n"); return; } if (DSC_FLAGGED(vict, DSC_BITUMENOUS_FLESH)) { act("You can't steal from $M, $E's protected by a solid, bitumenous layer!", FALSE, ch, 0, vict, TO_CHAR); return; } if (!(obj = get_obj_in_list_vis(ch, obj_name, vict->carrying))) { for (eq_pos = 0; eq_pos < NUM_WEARS; eq_pos++) if (GET_EQ(vict, eq_pos) && (isname(obj_name, GET_EQ(vict, eq_pos)->name)) && CAN_SEE_OBJ(ch, GET_EQ(vict, eq_pos))) { obj = GET_EQ(vict, eq_pos); break; } if (!obj) { act("$E hasn't got that item.", FALSE, ch, 0, vict, TO_CHAR); return; } else { /* It is equipment */ if ((GET_POS(vict) > POS_SLEEPING)) { send_to_char("Steal the equipment now? Impossible!\r\n", ch); return; } else if (eq_pos == WEAR_SHEATH_1 && GET_EQ(vict, WEAR_IN_SHEATH_1)) { msg_to_char(ch, "You can't remove that while something's in it!\r\n"); return; } else if (eq_pos == WEAR_SHEATH_2 && GET_EQ(vict, WEAR_IN_SHEATH_2)) { msg_to_char(ch, "You can't remove that while something's in it!\r\n"); return; } else if (eq_pos == WEAR_SHEATH_3 && GET_EQ(vict, WEAR_IN_SHEATH_3)) { msg_to_char(ch, "You can't remove that while something's in it!\r\n"); return; } else if (eq_pos == WEAR_WAIST && (GET_EQ(vict, WEAR_SHEATH_1) || GET_EQ(vict, WEAR_SHEATH_2) || GET_EQ(vict, WEAR_SHEATH_3))) { msg_to_char(ch, "You can't remove that while something's attached to it!\r\n"); return; } else { act("You unequip $p and steal it.", FALSE, ch, obj, 0, TO_CHAR); act("$n steals $p from $N.", FALSE, ch, obj, vict, TO_NOTVICT); obj_to_char(unequip_char(vict, eq_pos), ch); if (GET_LEVEL(vict) >= LVL_GOD) msg_to_char(vict, "You sense that someone has %s fingers in your pocket.\r\n", HSHR(ch)); } } } else { /* obj found in inventory */ if ((ww_dice(GET_DEXTERITY(ch) + GET_LARCENY(ch), 7) <= 0 && AWAKE(vict) && !AFF_FLAGGED(ch, AFF_INVISIBLE)) || IS_IMMORTAL(vict) || IS_GOD(vict)) { ohoh = TRUE; send_to_char("Oops..\r\n", ch); act("$n tried to steal something from you!", FALSE, ch, 0, vict, TO_VICT); act("$n tries to steal something from $N.", TRUE, ch, 0, vict, TO_NOTVICT); } else { /* Steal the item */ if (IS_CARRYING_N(ch) + 1 < CAN_CARRY_N(ch)) { if (IS_CARRYING_W(ch) + GET_OBJ_WEIGHT(obj) < CAN_CARRY_W(ch)) { obj_to_char(obj, ch); send_to_char("Got it!\r\n", ch); if (GET_LEVEL(vict) >= LVL_GOD) msg_to_char(vict, "You sense that %s has %s fingers in your pocket.\r\n", PERS(ch, vict, 0), HSHR(ch)); } else send_to_char("You cannot carry that much weight.\r\n", ch); } else send_to_char("You cannot carry that much.\r\n", ch); } } if (ohoh && IS_NPC(vict) && AWAKE(vict)) hit(vict, ch); } ACMD(do_hide) { Creature c; byte stealth; switch (SECT(ch->in_room)) { case SECT_FIELD: case SECT_WASTELAND: case SECT_DESERT: case SECT_ROAD: case SECT_FOREST_1: case SECT_OCEAN: case SECT_RIVER: case SECT_SEEDED: case SECT_FOUNTAIN: case SECT_WELL: case SECT_TOWER_OF_SOULS: case SECT_OASIS: msg_to_char(ch, "You can't hide here!\r\n"); return; } if (GET_RIDING(ch)) { msg_to_char(ch, "You can't hide while mounted!\r\n"); return; } msg_to_char(ch, "You attempt to hide yourself.\r\n"); if (AFF_FLAGGED(ch, AFF_HIDE)) REMOVE_BIT(AFF_FLAGS(ch), AFF_HIDE); WAIT_STATE(ch, PULSE_VIOLENCE * 2); for (c = world[ch->in_room].people; c; c = c->next_in_room) if (c != ch && CAN_SEE(c, ch) && ww_dice(GET_PERCEPTION(c) + GET_ALERTNESS(c), GET_WITS(ch) + GET_STEALTH(ch) - SENSES_BONUS(c)) > 0) { msg_to_char(ch, "You can't hide with somebody watching!\r\n"); return; } /* Outdoors, stealth may not exceed survival */ if (SECT(ch->in_room) == SECT_BUILDING || SECT(ch->in_room) == SECT_MONUMENT_CLOSED || SECT(ch->in_room) == SECT_MONUMENT_OPEN || SECT(ch->in_room) == SECT_INSIDE || SECT(ch->in_room) == SECT_MULTI) stealth = GET_STEALTH(ch); else stealth = MIN(GET_STEALTH(ch), GET_SURVIVAL(ch)); if (ww_dice(GET_DEXTERITY(ch) + stealth, 6) < 1) return; SET_BIT(AFF_FLAGS(ch), AFF_HIDE); } ACMD(do_mill) { Object obj; /* * This is designed for o_WHEAT only. It would have to be rewritten to allow * the milling of other objects. */ one_argument(argument, arg); if (!*arg) msg_to_char(ch, "Mill what?\r\n"); else if (!(obj = get_obj_in_list_vis(ch, arg, ch->carrying))) msg_to_char(ch, "You don't seem to have that.\r\n"); else if (BUILDING_TYPE(ch->in_room) != BUILDING_MILL) msg_to_char(ch, "You need to be in a mill to do this.\r\n"); else if (GET_OBJ_VNUM(obj) != o_WHEAT) msg_to_char(ch, "You can't mill that!\r\n"); else if (!CAN_USE_ROOM(ch, ch->in_room, 0)) msg_to_char(ch, "You don't have permission to use the mill.\r\n"); else if (GET_ACTION(ch) != ACT_NONE) msg_to_char(ch, "You're already quite busy.\r\n"); else { GET_ACTION(ch) = ACT_MILLING; GET_ACTION_TIMER(ch) = 60; GET_ACTION_ROOM(ch) = ch->in_room; GET_ACTION_ROTATION(ch) = last_action_rotation; act("You start milling $p.", FALSE, ch, obj, 0, TO_CHAR); act("$n starts milling $p.", FALSE, ch, obj, 0, TO_ROOM); extract_obj(obj); } } ACMD(do_bake) { Object obj; /* * This is designed to bake o_FLOUR only. To bake other things, * it would have to be rewritten. */ one_argument(argument, arg); if (!*arg) msg_to_char(ch, "What would you like to bake?\r\n"); else if (!(obj = get_obj_in_list_vis(ch, arg, ch->carrying))) msg_to_char(ch, "You don't seem to have that.\r\n"); else if (BUILDING_TYPE(ch->in_room) != BUILDING_BAKER && ROOM_TYPE(ch->in_room) != RTYPE_KITCHEN) msg_to_char(ch, "You can't bake here.\r\n"); else if (GET_OBJ_VNUM(obj) != o_FLOUR) msg_to_char(ch, "You can't bake that.\r\n"); else if (!CAN_USE_ROOM(ch, ch->in_room, 0)) msg_to_char(ch, "You don't have permission to bake anything here.\r\n"); else if (GET_ACTION(ch) != ACT_NONE) msg_to_char(ch, "You're already busy doing something else.\r\n"); else { GET_ACTION(ch) = ACT_BAKING; GET_ACTION_TIMER(ch) = 60; GET_ACTION_ROOM(ch) = ch->in_room; GET_ACTION_ROTATION(ch) = last_action_rotation; act("You begin to bake with $p.", FALSE, ch, obj, 0, TO_CHAR); act("$n begins to bake with $p.", FALSE, ch, obj, 0, TO_ROOM); extract_obj(obj); } } ACMD(do_skin) { Object obj, obj2; one_argument(argument, arg); if (!*arg) msg_to_char(ch, "What would you like to skin.\r\n"); else if (!(obj = get_obj_in_list_vis(ch, arg, ch->carrying))) msg_to_char(ch, "You don't seem to have anything like that.\r\n"); else if (!IS_CORPSE(obj)) msg_to_char(ch, "You can only skin corpses.\r\n"); else if (IS_SET(GET_OBJ_VAL(obj, 2), CORPSE_EATEN)) msg_to_char(ch, "It's too badly mangled to get any amount of usable skin.\r\n"); else if (IS_SET(GET_OBJ_VAL(obj, 2), CORPSE_SKINNED)) msg_to_char(ch, "It's already been skinned.\r\n"); else if (!GET_EQ(ch, WEAR_WIELD) || GET_OBJ_TYPE(GET_EQ(ch, WEAR_WIELD)) != ITEM_WEAPON || dam_type[GET_OBJ_VAL(GET_EQ(ch, WEAR_WIELD), 2)] < DAM_LETHAL) msg_to_char(ch, "You need to be wielding a sharp tool to skin a corpse.\r\n"); else { act("You carefully skin $p.", FALSE, ch, obj, 0, TO_CHAR); act("$n carefully skins $p.", TRUE, ch, obj, 0, TO_ROOM); obj2 = read_object(o_SKIN, VIRTUAL); GET_OBJ_VAL(obj2, 0) = GET_OBJ_VAL(obj, 1); /* Amount of skin */ obj_to_char(obj2, ch); SET_BIT(GET_OBJ_VAL(obj, 2), CORPSE_SKINNED); WAIT_STATE(ch, 2 RL_SEC); } } int total_skins(Creature ch) { int total = 0; Object obj; for (obj = ch->carrying; obj; obj = obj->next_content) if (GET_OBJ_TYPE(obj) == ITEM_SKIN) total += GET_OBJ_VAL(obj, 0); for (obj = world[ch->in_room].contents; obj; obj = obj->next_content) if (GET_OBJ_TYPE(obj) == ITEM_SKIN) total += GET_OBJ_VAL(obj, 0); return total; } void extract_skins_from_char(Creature ch, int skins) { Object o, o2; int remaining = skins; for (o = ch->carrying; o && remaining > 0; o = o2) { o2 = o->next_content; if (GET_OBJ_TYPE(o) == ITEM_SKIN) { remaining -= GET_OBJ_VAL(o, 0); extract_obj(o); } } for (o = world[ch->in_room].contents; o && remaining > 0; o = o2) { o2 = o->next_content; if (GET_OBJ_TYPE(o) == ITEM_SKIN) { remaining -= GET_OBJ_VAL(o, 0); extract_obj(o); } } } ACMD(do_sew) { int i = 0; Object obj; struct sew_data { char *name; int vnum; int skins; int skill; /* Crafts rating required */ } sews[] = { { "shawl", o_SHAWL, 200, 1 }, { "hood", o_HOOD, 25, 1 }, { "cloak", o_CLOAK, 220, 1 }, { "gloves", o_GLOVES, 25, 1 }, { "loop", o_BELTLOOP, 10, 1 }, { "shirt", o_SHIRT, 130, 2 }, { "blouse", o_BLOUSE, 130, 2 }, { "toga", o_TOGA, 150, 2 }, { "sash", o_SASH, 25, 2 }, { "belt", o_BELT, 25, 2 }, { "shield", o_SHIELD, 90, 2 }, { "shoes", o_SHOES, 50, 2 }, { "quiver", o_QUIVER, 100, 2 }, { "canteen", o_CANTEEN, 100, 2 }, { "scabbard", o_SCABBARD, 40, 2 }, { "cape", o_CAPE, 170, 3 }, { "sheath", o_SHEATH, 40, 3 }, { "rope", o_ROPE, 1, 3 }, { "pants", o_PANTS, 180, 3 }, { "tunic", o_TUNIC, 150, 3 }, { "sack", o_SACK, 80, 3 }, { "gauntlets", o_GAUNTLETS,75, 4 }, { "wineskin", o_WINESKIN, 120, 4 }, { "whip", o_WHIP, 120, 4 }, { "boots", o_BOOTS, 80, 4 }, { "hat", o_HAT, 30, 4 }, { "jacket", o_JACKET, 150, 5 }, { "ridingboots",o_RIDINGBOOTS,80, 5 }, { "dress", o_DRESS, 220, 5 }, { "bracers", o_BRACERS, 60, 5 }, { "pack", o_PACK, 120, 5 }, { "\n", 0, 0, 0 } }; skip_spaces(&argument); if (*argument) while ((!is_abbrev(argument, sews[i].name) || GET_CRAFTS(ch) < sews[i].skill) && str_cmp(sews[i].name, "\n")) i++; if (!*argument || !str_cmp(sews[i].name, "\n")) { msg_to_char(ch, "What would you like to sew?\r\nYour choices are:"); for (i = 0; str_cmp(sews[i].name, "\n"); i++) if (sews[i].skill <= GET_CRAFTS(ch)) msg_to_char(ch, " %s", sews[i].name); msg_to_char(ch, "\r\n"); } else if (total_skins(ch) < sews[i].skins) msg_to_char(ch, "You don't have enough material to make that.\r\n"); else { extract_skins_from_char(ch, sews[i].skins); obj_to_char((obj = read_object(sews[i].vnum, VIRTUAL)), ch); act("You sew some skin together into $p!", FALSE, ch, obj, 0, TO_CHAR); act("$n sews some skin together into $p!", TRUE, ch, obj, 0, TO_ROOM); WAIT_STATE(ch, 2 RL_SEC); } } struct forge_data { char *name; int vnum; int crafts; /* Min requirement */ int dexterity; /* Min requirement */ int iron, handles, silver, gold; } forge[] = { /* Weapons */ { "dirk", f_DIRK, 1, 1, 2, 0, 0, 0 }, { "axe", f_AXE, 1, 1, 2, 1, 0, 0 }, { "hammer", f_HAMMER, 1, 1, 2, 1, 0, 0 }, { "pick", f_PICK, 1, 1, 2, 1, 0, 0 }, { "shortsword", f_SHORTSWORD, 1, 1, 2, 0, 0, 0 }, { "dagger", f_DAGGER, 2, 1, 2, 0, 0, 0 }, { "shovel", f_SHOVEL, 2, 2, 2, 1, 0, 0 }, { "rapier", f_RAPIER, 2, 2, 2, 0, 0, 0 }, { "mace", f_MACE, 3, 2, 3, 1, 0, 0 }, { "sword", f_SWORD, 3, 2, 3, 0, 0, 0 }, { "scimitar", f_SCIMITAR, 3, 2, 3, 0, 0, 0 }, { "pike", f_PIKE, 3, 3, 2, 1, 0, 0 }, { "scythe", f_SCYTHE, 3, 3, 3, 1, 0, 0 }, { "halbert", f_HALBERT, 4, 3, 2, 1, 0, 0 }, { "maul", f_MAUL, 4, 4, 2, 1, 0, 0 }, { "poleaxe", f_POLEAXE, 4, 4, 2, 1, 0, 0 }, { "broadsword", f_BROADSWORD, 5, 4, 4, 0, 0, 0 }, { "claymore", f_CLAYMORE, 5, 5, 3, 1, 0, 0 }, { "flamberge", f_FLAMBERGE, 5, 5, 4, 1, 0, 0 }, /* Shields */ { "shield", f_SHIELD, 2, 2, 4, 0, 0, 0 }, { "kiteshield", f_KITE, 3, 3, 6, 0, 0, 0 }, { "towershield",f_TOWER, 4, 4, 8, 0, 0, 0 }, /* Belts */ { "clip", f_BELTCLIP, 1, 1, 1, 0, 0, 0 }, { "platedbelt", f_BELT, 2, 2, 2, 0, 0, 0 }, /* Armor */ { "breastplate",f_BREASTPLATE, 2, 1, 6, 0, 0, 0 }, { "chainmail", f_CHAIN, 2, 2, 7, 0, 0, 0 }, { "ringmail", f_RING, 3, 2, 8, 0, 0, 0 }, { "platemail", f_PLATE, 4, 3, 12, 0, 0, 0 }, { "fullplate", f_FULL_PLATE, 5, 4, 16, 0, 0, 0 }, /* Headgear */ { "helm", f_HELM, 2, 2, 3, 0, 0, 0 }, { "greathelm", f_GREAT_HELM, 3, 2, 3, 0, 0, 0 }, { "crown", f_CROWN, 3, 3, 0, 0, 0, 4 }, /* Jewelry */ { "silver ring", f_RING_SILVER, 3, 2, 0, 0, 1, 0 }, { "silver earring", f_EARRING_SILVER, 3, 2, 0, 0, 2, 0 }, { "gold ring", f_RING_GOLD, 4, 3, 0, 0, 0, 1 }, { "gold earring", f_EARRING_GOLD, 4, 3, 0, 0, 0, 2 }, { "engagement ring", f_RING_ENGAGEMENT, 4, 3, 0, 0, 0, 1 }, { "wedding band", f_RING_WEDDING, 4, 3, 0, 0, 0, 1 }, /* Misc */ { "pan", f_PAN, 3, 4, 2, 0, 0, 0 }, { "\n", 0, 0, 0, 0, 0, 0, 0 } }; void cancel_forging(Creature ch) { int i; for (i = 0; i < forge[GET_ACTION_VNUM(ch, 0)].iron / 2; i++) obj_to_char(read_object(o_IRON, VIRTUAL), ch); for (i = 0; i < forge[GET_ACTION_VNUM(ch, 0)].handles; i++) obj_to_char(read_object(o_HANDLE, VIRTUAL), ch); for (i = 0; i < forge[GET_ACTION_VNUM(ch, 0)].silver; i++) obj_to_char(read_object(o_SILVER, VIRTUAL), ch); for (i = 0; i < forge[GET_ACTION_VNUM(ch, 0)].gold; i++) obj_to_char(read_object(o_GOLD, VIRTUAL), ch); GET_ACTION(ch) = 0; } void finish_forging(Creature ch) { int f = GET_ACTION_VNUM(ch, 0); Object obj; GET_ACTION(ch) = ACT_NONE; obj_to_char((obj = read_object(forge[f].vnum, VIRTUAL)), ch); act("You finish forging $p!", FALSE, ch, obj, 0, TO_CHAR); act("$n finishes forging $p!", FALSE, ch, obj, 0, TO_ROOM); if (GET_CRAFTS(ch) >= 5 && GET_INTELLIGENCE(ch) >= 4 && GET_OBJ_MATERIAL(obj) == ITEM_MAT_IRON) SET_BIT(GET_OBJ_EXTRA(obj), ITEM_SUPERIOR); } bool has_forge_resources(Creature ch, int f) { Object obj; int iron = forge[f].iron, handles = forge[f].handles, silver = forge[f].silver, gold = forge[f].gold; for (obj = ch->carrying; obj; obj = obj->next_content) if (GET_OBJ_VNUM(obj) == o_IRON && iron > 0) iron--; else if (GET_OBJ_VNUM(obj) == o_HANDLE && handles > 0) handles--; else if (GET_OBJ_VNUM(obj) == o_SILVER && silver > 0) silver--; else if (GET_OBJ_VNUM(obj) == o_GOLD && gold > 0) gold--; if (handles > 0 || iron > 0 || gold > 0 || silver > 0) return FALSE; return TRUE; } void extract_forge_resources(Creature ch, int f) { Object obj, next_obj; int iron = forge[f].iron, handles = forge[f].handles, silver = forge[f].silver, gold = forge[f].gold; for (obj = ch->carrying; obj; obj = next_obj) { next_obj = obj->next_content; if (GET_OBJ_VNUM(obj) == o_IRON && iron > 0) { iron--; extract_obj(obj); } else if (GET_OBJ_VNUM(obj) == o_HANDLE && handles > 0) { handles--; extract_obj(obj); } else if (GET_OBJ_VNUM(obj) == o_SILVER && silver > 0) { silver--; extract_obj(obj); } else if (GET_OBJ_VNUM(obj) == o_GOLD && gold > 0) { gold--; extract_obj(obj); } } } ACMD(do_forge) { int i = -1; if (IS_NPC(ch)) return; skip_spaces(&argument); if (*argument) while (1 == 1) { i++; if (!str_cmp(forge[i].name, "\n")) break; if (GET_DEXTERITY(ch) < forge[i].dexterity || GET_CRAFTS(ch) < forge[i].crafts) continue; if (is_abbrev(argument, forge[i].name)) break; } if (!*argument || !str_cmp(forge[i].name, "\n")) { msg_to_char(ch, "What do you want to forge?\r\n"); msg_to_char(ch, "You know how to make:"); for (i = 0; str_cmp(forge[i].name, "\n"); i++) if (GET_DEXTERITY(ch) >= forge[i].dexterity && GET_CRAFTS(ch) >= forge[i].crafts) msg_to_char(ch, " %s", forge[i].name); msg_to_char(ch, "\r\n"); } else if (BUILDING_TYPE(ch->in_room) != BUILDING_FORGE && ROOM_TYPE(ch->in_room) != RTYPE_FORGE) msg_to_char(ch, "You need to be in a forge to do this.\r\n"); else if (!CAN_USE_ROOM(ch, ch->in_room, 0)) msg_to_char(ch, "You don't have permission to use the forge.\r\n"); else if (GET_ACTION(ch) == ACT_FORGING) { cancel_forging(ch); msg_to_char(ch, "You stop forging.\r\n"); } else 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_HAMMER) msg_to_char(ch, "You don't have the proper tool to forge.\r\n"); else if (GET_ACTION(ch) != ACT_NONE) msg_to_char(ch, "You're already quite busy.\r\n"); else if (!has_forge_resources(ch, i)) msg_to_char(ch, "You don't have the resources to forge that.\r\n"); else { GET_ACTION(ch) = ACT_FORGING; GET_ACTION_TIMER(ch) = (forge[i].iron + forge[i].handles + forge[i].silver + forge[i].gold) * 10; GET_ACTION_ROOM(ch) = ch->in_room; GET_ACTION_ROTATION(ch) = last_action_rotation; GET_ACTION_VNUM(ch, 0) = i; extract_forge_resources(ch, i); act("You start forging.", FALSE, ch, 0, 0, TO_CHAR); act("$n starts forging.", FALSE, ch, 0, 0, TO_ROOM); } } ACMD(do_fire) { Object obj; int i; int fire_changes[][2] = { { uc_BOWL, c_BOWL }, { uc_POT, c_POT }, { uc_SHIELD, c_SHIELD }, { uc_LARGESHIELD, c_LARGESHIELD }, { uc_VESSEL, c_VESSEL }, { uc_GREATSHIELD, c_GREATSHIELD }, { -1, -1 }}; one_argument(argument, arg); if (!*arg) msg_to_char(ch, "What do you wish to fire?\r\n"); else if (!(obj = get_obj_in_list_vis(ch, arg, ch->carrying))) msg_to_char(ch, "You don't have anything like that.\r\n"); else if (BUILDING_TYPE(ch->in_room) != BUILDING_POTTER) msg_to_char(ch, "You don't have the resources to fire clay here.\r\n"); else { for (i = 0; fire_changes[i][0] != -1 && fire_changes[i][0] != GET_OBJ_VNUM(obj); i++); if (fire_changes[i][0] == -1) { msg_to_char(ch, "You can't fire that!\r\n"); return; } extract_obj(obj); obj = read_object(fire_changes[i][1], VIRTUAL); obj_to_char(obj, ch); act("You put $p in the fire until it hardens.", FALSE, ch, obj, 0, TO_CHAR); act("$n puts $p in the fire until it hardens.", FALSE, ch, obj, 0, TO_ROOM); WAIT_STATE(ch, 2 RL_SEC); } } ACMD(do_mine) { if (IS_NPC(ch)) return; if (GET_ACTION(ch) == ACT_MINING) { msg_to_char(ch, "You stop mining.\r\n"); act("$n stops mining.", FALSE, ch, 0, 0, TO_ROOM); GET_ACTION(ch) = ACT_NONE; } else if (GET_ACTION(ch) != ACT_NONE) msg_to_char(ch, "You're busy doing something else right now.\r\n"); else if (BUILDING_TYPE(ch->in_room) != BUILDING_MINE) msg_to_char(ch, "This isn't a mine..\r\n"); else if (!CAN_USE_ROOM(ch, ch->in_room, 0)) msg_to_char(ch, "You don't have permission to mine here.\r\n"); else if (!IS_COMPLETE(ch->in_room)) msg_to_char(ch, "The mine shafts aren't finished yet.\r\n"); else if (world[ch->in_room].spare <= 0) msg_to_char(ch, "The mine is depleted, you find nothing of use.\r\n"); else if (BUILDING_TYPE(ch->in_room) != BUILDING_MINE) msg_to_char(ch, "You can't mine here.\r\n"); else 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_PICK) && GET_OBJ_VNUM(GET_EQ(ch, WEAR_WIELD)) != o_HANDAXE)) msg_to_char(ch, "You don't have a tool suitable for mining.\r\n"); else { msg_to_char(ch, "You look for a suitable place and begin to mine.\r\n"); act("$n finds a suitable place and begins to mine.", FALSE, ch, 0, 0, TO_ROOM); GET_ACTION(ch) = ACT_MINING; GET_ACTION_ROOM(ch) = ch->in_room; GET_ACTION_ROTATION(ch) = last_action_rotation; GET_ACTION_TIMER(ch) = 45; } } ACMD(do_mold) { Object obj, obj2; int i; struct molding_data { char *name; int skill; /* Crafts required */ int vnum; } molds[] = { { "bowl", 1, uc_BOWL }, { "pot", 2, uc_POT }, { "shield", 3, uc_SHIELD }, { "largeshield",4, uc_LARGESHIELD }, { "vessel", 5, uc_VESSEL }, { "greatshield",5, uc_GREATSHIELD }, { "\n", 0, 0 }}; two_arguments(argument, arg, buf); if (!*arg || !*buf) { msg_to_char(ch, "What do you want to mold into what?\r\n"); msg_to_char(ch, "You can mold:"); for (i = 0; str_cmp(molds[i].name, "\n"); i++) if (GET_CRAFTS(ch) >= molds[i].skill) msg_to_char(ch, " %s", molds[i].name); msg_to_char(ch, ".\r\n"); return; } if (!(obj = get_obj_in_list_vis(ch, arg, ch->carrying))) { msg_to_char(ch, "Nothing by that name here.\r\n"); return; } i = 0; while (str_cmp(molds[i].name, "\n") && !is_abbrev(buf, molds[i].name)) i++; if (!str_cmp(molds[i].name, "\n") || GET_CRAFTS(ch) < molds[i].skill) { msg_to_char(ch, "You don't know how to mold that.\r\n"); msg_to_char(ch, "You can mold:"); for (i = 0; str_cmp(molds[i].name, "\n"); i++) if (GET_CRAFTS(ch) >= molds[i].skill) msg_to_char(ch, " %s", molds[i].name); msg_to_char(ch, ".\r\n"); return; } if (GET_OBJ_TYPE(obj) != ITEM_CLAY) { msg_to_char(ch, "You can only mold clay.\r\n"); return; } if (!(obj2 = read_object(molds[i].vnum, VIRTUAL))) { msg_to_char(ch, "Molding is currently off-line.\r\n"); return; } act("You mold $p into $P!", FALSE, ch, obj, obj2, TO_CHAR); act("$n molds $p into $P!", TRUE, ch, obj, obj2, TO_ROOM); extract_obj(obj); obj_to_char(obj2, ch); WAIT_STATE(ch, 2 RL_SEC); } ACMD(do_harvest) { extern const char *crops[]; if (IS_NPC(ch)) return; if (GET_ACTION(ch) == ACT_HARVESTING) { msg_to_char(ch, "You stop harvesting the %s.\r\n", crops[(int) world[ch->in_room].type]); act("$n stops harvesting.\r\n", FALSE, ch, 0, 0, TO_ROOM); GET_ACTION(ch) = ACT_NONE; } else if (GET_ACTION(ch) != ACT_NONE) msg_to_char(ch, "You already busy doing something else.\r\n"); else if (SECT(ch->in_room) != SECT_CROP) msg_to_char(ch, "You can't harvest anything here!\r\n"); else if (!CAN_USE_ROOM(ch, ch->in_room, 0)) msg_to_char(ch, "You don't have permission to harvest this crop.\r\n"); else if (real_empire(world[ch->in_room].owner) != -1 && GET_RANK(ch) < empire[real_empire(world[ch->in_room].owner)].priv[PRIV_HARVEST]) msg_to_char(ch, "You don't have permission to harvest crops.\r\n"); else 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_SLICE && GET_OBJ_VAL(GET_EQ(ch, WEAR_WIELD), 2) != TYPE_SLASH)) msg_to_char(ch, "You aren't using the proper tool for that.\r\n"); else { GET_ACTION(ch) = ACT_HARVESTING; GET_ACTION_ROOM(ch) = ch->in_room; GET_ACTION_ROTATION(ch) = last_action_rotation; if (GET_BUILD_VALUE(ch->in_room) == 0) GET_BUILD_VALUE(ch->in_room) = 40; msg_to_char(ch, "You begin harvesting the %s.\r\n", crops[(int) world[ch->in_room].type]); act("$n begins to harvest the crop.", FALSE, ch, 0, 0, TO_ROOM); } } ACMD(do_dig) { if (GET_ACTION(ch) == ACT_DIGGING) { send_to_char("You stop digging.\r\n", ch); act("$n stops digging.", FALSE, ch, 0, 0, TO_ROOM); GET_ACTION(ch) = ACT_NONE; } else if (GET_ACTION(ch) != ACT_NONE) send_to_char("You're already busy.\r\n", ch); else if ( /* Places you CAN'T dig */ (SECT(ch->in_room) == SECT_RIVER || SECT(ch->in_room) == SECT_OCEAN || SECT(ch->in_room) == SECT_ROAD || SECT(ch->in_room) == SECT_MONUMENT_CLOSED || SECT(ch->in_room) == SECT_BUILDING || SECT(ch->in_room) == SECT_INSIDE || SECT(ch->in_room) == SECT_MULTI || SECT(ch->in_room) == SECT_TOWER_OF_SOULS || SECT(ch->in_room) == SECT_WASTELAND || SECT(ch->in_room) == SECT_MONUMENT_OPEN) /* Places you CAN */ && (BUILDING_TYPE(ch->in_room) != BUILDING_MINE) ) send_to_char("You can't dig here.\r\n", ch); else if (!CAN_USE_ROOM(ch, ch->in_room, 0)) msg_to_char(ch, "You don't have permission to dig here.\r\n"); else { GET_ACTION(ch) = ACT_DIGGING; GET_ACTION_TIMER(ch) = 8; GET_ACTION_ROOM(ch) = ch->in_room; GET_ACTION_ROTATION(ch) = last_action_rotation; send_to_char("You begin to dig into the ground.\r\n", ch); act("$n kneels down and begins to dig.", TRUE, ch, 0, 0, TO_ROOM); } } ACMD(do_gather) { if (GET_ACTION(ch) == ACT_GATHERING) { send_to_char("You stop searching for sticks.\r\n", ch); act("$n stops looking around.", TRUE, ch, 0, 0, TO_ROOM); GET_ACTION(ch) = ACT_NONE; } else if (GET_ACTION(ch) != ACT_NONE) send_to_char("You're already busy.\r\n", ch); else if (SECT(ch->in_room) != SECT_FOREST_4 && SECT(ch->in_room) != SECT_FOREST_3 && SECT(ch->in_room) != SECT_FOREST_2 && SECT(ch->in_room) != SECT_FOREST_1&& (SECT(ch->in_room) != SECT_CROP || world[ch->in_room].type != CROP_FRUIT)) send_to_char("You can't really gather outside of the forest or orchard!\r\n", ch); else if (!CAN_USE_ROOM(ch, ch->in_room, 0)) msg_to_char(ch, "You don't have permission to gather here.\r\n"); else { GET_ACTION(ch) = ACT_GATHERING; GET_ACTION_TIMER(ch) = number(5, 9); GET_ACTION_ROOM(ch) = ch->in_room; GET_ACTION_ROTATION(ch) = last_action_rotation; send_to_char("You begin looking around for sticks.\r\n", ch); } } ACMD(do_pick) { if (GET_ACTION(ch) == ACT_PICKING) { send_to_char("You stop searching.\r\n", ch); act("$n stops looking around.", TRUE, ch, 0, 0, TO_ROOM); GET_ACTION(ch) = ACT_NONE; } else if (GET_ACTION(ch) != ACT_NONE) send_to_char("You're already busy.\r\n", ch); else if (SECT(ch->in_room) != SECT_FIELD && (SECT(ch->in_room) != SECT_CROP || world[ch->in_room].type != CROP_FRUIT)) send_to_char("You can only pick flowers in a field, or apples in an orchard!\r\n", ch); else if (!CAN_USE_ROOM(ch, ch->in_room, 0)) msg_to_char(ch, "You don't have permission to pick anything here.\r\n"); else { GET_ACTION(ch) = ACT_PICKING; GET_ACTION_TIMER(ch) = number(5, 9); GET_ACTION_ROOM(ch) = ch->in_room; GET_ACTION_ROTATION(ch) = last_action_rotation; send_to_char("You begin looking around.\r\n", ch); } } ACMD(do_chop) { if (GET_ACTION(ch) == ACT_CHOPPING) { send_to_char("You stop chopping the tree.\r\n", ch); act("$n stops chopping at the tree.", FALSE, ch, 0, 0, TO_ROOM); GET_ACTION(ch) = ACT_NONE; } else if(GET_ACTION(ch) != ACT_NONE) send_to_char("You're already busy.\r\n", ch); else if (SECT(ch->in_room) != SECT_FOREST_4 && SECT(ch->in_room) != SECT_FOREST_3 && SECT(ch->in_room) != SECT_FOREST_2 && SECT(ch->in_room) != SECT_FOREST_1) send_to_char("You can't really chop down trees unless you're in the forest.\r\n", ch); else if (!CAN_USE_ROOM(ch, ch->in_room, 0)) msg_to_char(ch, "You don't have permission to chop down trees here.\r\n"); else if (real_empire(world[ch->in_room].owner) != -1 && GET_RANK(ch) < empire[real_empire(world[ch->in_room].owner)].priv[PRIV_CHOP]) msg_to_char(ch, "You don't have permission to chop down trees.\r\n"); else if (!GET_EQ(ch, WEAR_WIELD)) send_to_char("You need to be wielding some kind of axe to chop.\r\n", ch); else if (GET_OBJ_VAL(GET_EQ(ch, WEAR_WIELD), 2) != TYPE_SLICE) send_to_char("You need to be wielding some kind of axe to chop.\r\n", ch); else { GET_ACTION(ch) = ACT_CHOPPING; GET_ACTION_ROOM(ch) = ch->in_room; GET_ACTION_ROTATION(ch) = last_action_rotation; if (GET_BUILD_VALUE(ch->in_room) == 0) GET_BUILD_VALUE(ch->in_room) = 30; send_to_char("You swing back your axe and prepare to chop...\r\n", ch); act("$n swings $s axe over $s shoulder.", TRUE, ch, 0, 0, TO_ROOM); } } ACMD(do_herd) { extern int perform_move(Creature ch, int dir, int need_specials_check, byte mode); Creature victim; int dir, to_room; two_arguments(argument, arg, buf); if (IS_NPC(ch)) return; else if (!*arg || !*buf) msg_to_char(ch, "Who do you want to herd, and which direction?\r\n"); else if (!(victim = get_char_vis(ch, arg, FIND_CHAR_ROOM))) msg_to_char(ch, NOPERSON); else if (victim == ch) msg_to_char(ch, "Type HELP -- SERIOUS HELP.\r\n"); else if (!IS_NPC(victim) || victim->desc) msg_to_char(ch, "You can only herd animals.\r\n"); else if ((dir = parse_direction(buf)) < 0 || (to_room = real_shift(ch->in_room, shift_dir[dir][0], shift_dir[dir][1])) == NOWHERE) msg_to_char(ch, "That's not a direction!\r\n"); else if (!CAN_USE_ROOM(ch, ch->in_room, 0)) msg_to_char(ch, "You don't have permission to herd here.\r\n"); else if ((SECT(ch->in_room) == SECT_MULTI || SECT(ch->in_room) == SECT_INSIDE || SECT(ch->in_room) == SECT_BUILDING || SECT(ch->in_room) == SECT_MONUMENT_CLOSED) && !CAN_GO(ch, dir)) msg_to_char(ch, "You can't herd anyone in a direction that's blocked!\r\n"); else if (SECT(ch->in_room) == SECT_MOUNTAIN || SECT(ch->in_room) == SECT_OCEAN || SECT(ch->in_room) == SECT_RIVER) msg_to_char(ch, "You find it difficult to do that here.\r\n"); else if (SECT(to_room) == SECT_MOUNTAIN || SECT(to_room) == SECT_OCEAN || SECT(to_room) == SECT_RIVER) msg_to_char(ch, "You find that difficult to do.\r\n"); else if (GET_RIDDEN_BY(victim)) msg_to_char(ch, "You can't herd someone who is being ridden.\r\n"); else if (GET_LED_BY(victim) && GET_LED_BY(victim)->in_room == victim->in_room) msg_to_char(ch, "You can't herd someone who is being led by someone else.\r\n"); else if (ww_dice(GET_MANIPULATION(ch) + GET_ANIMAL_KEN(ch), 6) <= 0) { act("You try to herd $N, but $E refuses to move!", FALSE, ch, 0, victim, TO_CHAR); act("$n tries to herd $N away, but $E refuses to move!", FALSE, ch, 0, victim, TO_ROOM); } else if (SECT(to_room) == SECT_BUILDING && world[real_shift(ch->in_room, shift_dir[dir][0], shift_dir[dir][1])].type != BUILDING_STABLE) msg_to_char(ch, "You can't herd an animal into a building.\r\n"); else if (SECT(to_room) == SECT_MULTI) msg_to_char(ch, "You can't herd an animal in there.\r\n"); else if (SECT(real_shift(ch->in_room, shift_dir[dir][0], shift_dir[dir][1])) == SECT_INSIDE) msg_to_char(ch, "You can't herd an animal in here.\r\n"); else { if (perform_move(victim, dir, TRUE, 0)) { act("You skillfully herd $N.", FALSE, ch, 0, victim, TO_CHAR); act("$n skillfully herds $N.", FALSE, ch, 0, victim, TO_ROOM); if (!perform_move(ch, dir, FALSE, 0)) char_to_room(victim, ch->in_room); } else { act("You try to herd $N, but $E refuses to move!", FALSE, ch, 0, victim, TO_CHAR); act("$n tries to herd $N away, but $E refuses to move!", FALSE, ch, 0, victim, TO_ROOM); } } } ACMD(do_fish) { int dir; byte type = 0; for (dir = 0; dir < NUM_2D_DIRS; dir++) if (SECT(real_shift(ch->in_room, shift_dir[dir][0], shift_dir[dir][1])) == SECT_OCEAN) type = 1; else if (SECT(real_shift(ch->in_room, shift_dir[dir][0], shift_dir[dir][1])) == SECT_RIVER) type = 2; if (!type && SECT(ch->in_room) == SECT_OCEAN) type = 1; if (!type && SECT(ch->in_room) == SECT_RIVER) type = 2; if (IS_NPC(ch)) return; else if (GET_ACTION(ch) == ACT_FISHING) { msg_to_char(ch, "You stop fishing.\r\n"); act("$n stops fishing.", TRUE, ch, 0, 0, TO_ROOM); GET_ACTION(ch) = ACT_NONE; } else if (GET_ACTION(ch)) msg_to_char(ch, "You're really too busy to do that.\r\n"); else if (!IS_OUTDOORS(ch)) msg_to_char(ch, "You can't fish in here!\r\n"); else if (SECT(ch->in_room) == SECT_MOUNTAIN) msg_to_char(ch, "You're a little high up to be fishing.\r\n"); else if (!type) msg_to_char(ch, "Unless you're fishing for worms in puddles, there's really nothing to catch here.\r\n"); else 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"); else { GET_ACTION(ch) = ACT_FISHING; GET_ACTION_ROTATION(ch) = last_action_rotation; GET_ACTION_TIMER(ch) = 40; GET_ACTION_ROOM(ch) = ch->in_room; GET_ACTION_VNUM(ch, 0) = type; msg_to_char(ch, "You begin looking for fish..\r\n"); act("$n begins looking for fish.", TRUE, ch, 0, 0, TO_ROOM); } } /* Melt Data */ int melt_data[][4] = { /* from, to, needs (max 8), gives */ { o_GOLD_SMALL, o_GOLD_DISC, 8, 1 }, { o_SILVER, o_SILVER_DISC, 2, 1 }, { o_GOLD, o_GOLD_DISC, 2, 1 }, { o_SILVER_DISC, o_SILVER_BAR, 2, 1 }, { o_GOLD_DISC, o_GOLD_BAR, 2, 1 }, /* Melted down */ { o_SILVER_BAR, o_SILVER, 1, 4 }, { o_GOLD_BAR, o_GOLD, 1, 4 }, { NOTHING, NOTHING } }; void finish_melting(Creature ch) { Object obj = NULL; int i, j; /* Find the entry in the table */ for (i = 0; melt_data[i][0] != NOTHING && melt_data[i][0] != GET_ACTION_VNUM(ch, 0); i++); if (melt_data[i][0] == NOTHING) { GET_ACTION(ch) = ACT_NONE; return; } for (j = 0; j < melt_data[i][3]; j++) obj_to_char((obj = read_object(melt_data[i][1], VIRTUAL)), ch); sprintf(buf2, " (%dx)", j); sprintf(buf, "You have successfully created $p%s!", j > 1 ? buf2 : ""); sprintf(buf1, "$n has successfully created $p%s!", j > 1 ? buf2 : ""); act(buf, FALSE, ch, obj, 0, TO_CHAR); act(buf1, TRUE, ch, obj, 0, TO_ROOM); GET_ACTION(ch) = ACT_NONE; } void cancel_melting(Creature ch) { Object obj = NULL; int i, j; /* Find the entry in the table */ for (i = 0; melt_data[i][0] != NOTHING && melt_data[i][0] != GET_ACTION_VNUM(ch, 0); i++); for (j = 0; j < melt_data[i][2]; j++) obj_to_char((obj = read_object(melt_data[i][0], VIRTUAL)), ch); GET_ACTION(ch) = ACT_NONE; } ACMD(do_melt) { Object obj[8]; int i, k; if (IS_NPC(ch)) return; one_argument(argument, arg); if (!*arg) msg_to_char(ch, "What would you like to melt?\r\n"); else if (GET_ACTION(ch) != ACT_NONE) msg_to_char(ch, "You're busy right now.\r\n"); else if (!(obj[0] = get_obj_in_list_vis(ch, arg, ch->carrying))) msg_to_char(ch, "You don't seem to have anything like that.\r\n"); else if (BUILDING_TYPE(ch->in_room) != BUILDING_FORGE && ROOM_TYPE(ch->in_room) != RTYPE_FORGE) msg_to_char(ch, "You need to be in a forge to do this.\r\n"); else if (!CAN_USE_ROOM(ch, ch->in_room, 0)) msg_to_char(ch, "You don't have permission to use the forge.\r\n"); else { /* Make sure it's in the list */ for (i = 0; melt_data[i][0] != NOTHING && melt_data[i][0] != GET_OBJ_VNUM(obj[0]); i++); if (melt_data[i][0] == NOTHING) { msg_to_char(ch, "You can't melt that here.\r\n"); return; } /* Find another few of identical vnum */ for (k = 1; k < melt_data[i][2] && obj[k-1]; k++) for (obj[k] = obj[k-1]->next_content; obj[k]; obj[k] = obj[k]->next_content) if (GET_OBJ_VNUM(obj[k]) == GET_OBJ_VNUM(obj[0])) break; /* oops, couldn't find one */ if (!obj[k-1]) { msg_to_char(ch, "You'll need %d of them to melt.\r\n", melt_data[i][2]); return; } GET_ACTION(ch) = ACT_MELTING; GET_ACTION_TIMER(ch) = 10; GET_ACTION_ROOM(ch) = ch->in_room; GET_ACTION_ROTATION(ch) = last_action_rotation; GET_ACTION_VNUM(ch, 0) = melt_data[i][0]; act("You begin to melt $p.", FALSE, ch, obj[0], 0, TO_CHAR); act("$n begins to melt $p.", FALSE, ch, obj[0], 0, TO_ROOM); for (k = 0; k < melt_data[i][2]; k++) if (obj[k]) extract_obj(obj[k]); } } ACMD(do_blow) { int i = 0; struct blow_data_structure { char *name; obj_vnum vnum; } blow_data[] = { { "flask", o_FLASK }, { "jar", o_JAR }, { "\n", NOTHING } }; one_argument(argument, arg); if (*arg) for (i = 0; str_cmp(blow_data[i].name, "\n") && !is_abbrev(arg, blow_data[i].name); i++); if (BUILDING_TYPE(ch->in_room) != BUILDING_GLASS) msg_to_char(ch, "You can't blow glass here.\r\n"); else if (!IS_COMPLETE(ch->in_room)) msg_to_char(ch, "You'll need to finish the building first.\r\n"); else if (!CAN_USE_ROOM(ch, ch->in_room, 0)) msg_to_char(ch, "You don't have permission to use this facility.\r\n"); else if (GET_ACTION(ch) == ACT_GLASS) { msg_to_char(ch, "You scrap the material you were using and stop working on the glass.\r\n"); act("$n stops blowing glass.", TRUE, ch, 0, 0, TO_ROOM); GET_ACTION(ch) = ACT_NONE; } else if (GET_ACTION(ch) != ACT_NONE) msg_to_char(ch, "You're already a little busy right now.\r\n"); else if (!*arg || !str_cmp(blow_data[i].name, "\n")) { msg_to_char(ch, "Blow what: "); for (i = 0; str_cmp(blow_data[i].name, "\n"); i++) msg_to_char(ch, " %s", blow_data[i].name); msg_to_char(ch, "\r\n"); } else { strcpy(buf1, GET_OBJ_NAME_BY_PROTO(real_object(blow_data[i].vnum))); msg_to_char(ch, "You prepare to blow %s.\r\n", buf1); sprintf(buf, "$n prepares to blow %s.", buf1); act(buf, TRUE, ch, 0, 0, TO_ROOM); GET_ACTION(ch) = ACT_GLASS; GET_ACTION_TIMER(ch) = 9; GET_ACTION_VNUM(ch, 0) = blow_data[i].vnum; GET_ACTION_ROOM(ch) = ch->in_room; GET_ACTION_ROTATION(ch) = last_action_rotation; } } ACMD(do_milk) { void weight_change_object(Object obj, int weight); Creature mob; Object cont; int amount; two_arguments(argument, arg, buf); if (BUILDING_TYPE(ch->in_room) != BUILDING_STABLE) msg_to_char(ch, "You can't milk animals here!\r\n"); else if (!CAN_USE_ROOM(ch, ch->in_room, 0)) msg_to_char(ch, "You don't have permission to milk these animals.\r\n"); else if (!*arg || !*buf) msg_to_char(ch, "What would you like to milk, and into what?\r\n"); else if (!(mob = get_char_vis(ch, arg, FIND_CHAR_ROOM))) msg_to_char(ch, NOPERSON); else if (!IS_NPC(mob) || !MOB_FLAGGED(mob, MOB_MILKABLE)) act("You can't milk $N!", FALSE, ch, 0, mob, TO_CHAR); else if (MOB_MILK_TIMER(mob)) act("$E can't be milked again for a while.", FALSE, ch, 0, mob, TO_CHAR); else if (!(cont = get_obj_in_list_vis(ch, buf, ch->carrying))) msg_to_char(ch, "You don't seem to have a %s.\r\n", buf); else if (GET_OBJ_TYPE(cont) != ITEM_DRINKCON) act("You can't milk $N into $p!", FALSE, ch, cont, mob, TO_CHAR); else if (GET_OBJ_VAL(cont, 1) && GET_OBJ_VAL(cont, 2) != LIQ_MILK) msg_to_char(ch, "It's already full of something else.\r\n"); else if (GET_OBJ_VAL(cont, 1) >= GET_OBJ_VAL(cont, 0)) msg_to_char(ch, "It's already full.\r\n"); else { act("You milk $N into $p.", FALSE, ch, cont, mob, TO_CHAR); act("$n milks $N into $p.", FALSE, ch, cont, mob, TO_ROOM); MOB_MILK_TIMER(mob) = number(10, 14); amount = GET_OBJ_VAL(cont, 0) - GET_OBJ_VAL(cont, 1); GET_OBJ_VAL(cont, 1) += amount; GET_OBJ_VAL(cont, 2) = LIQ_MILK; weight_change_object(cont, amount); /* Add weight */ } } ACMD(do_sap) { SPECIAL(spec_bee_hive); void weight_change_object(Object obj, int weight); Object hive, cont; int amount; two_arguments(argument, arg, buf); if (BUILDING_TYPE(ch->in_room) != BUILDING_APIARY) msg_to_char(ch, "You can't sap honey here!\r\n"); else if (!CAN_USE_ROOM(ch, ch->in_room, 0)) msg_to_char(ch, "You don't have permission to sap honey here.\r\n"); else if (!*arg || !*buf) msg_to_char(ch, "What would you like to sap honey from, and into what?\r\n"); else if (!(hive = get_obj_in_list_vis(ch, arg, world[ch->in_room].contents))) msg_to_char(ch, "There's no %s here!", arg); else if (GET_OBJ_RNUM(hive) < 0 || obj_index[GET_OBJ_RNUM(hive)].spec_proc != spec_bee_hive) act("You can't get honey from $p!", FALSE, ch, hive, 0, TO_CHAR); else if (GET_OBJ_VAL(hive, 1) <= 0) act("$p has no honey in it!", FALSE, ch, hive, 0, TO_CHAR); else if (!(cont = get_obj_in_list_vis(ch, buf, ch->carrying))) msg_to_char(ch, "You don't seem to have a %s.\r\n", buf); else if (GET_OBJ_TYPE(cont) != ITEM_DRINKCON) act("You can't sap honey into $p!", FALSE, ch, cont, 0, TO_CHAR); else if (GET_OBJ_VAL(cont, 1) && GET_OBJ_VAL(cont, 2) != LIQ_HONEY) msg_to_char(ch, "It's already full of something else.\r\n"); else if (GET_OBJ_VAL(cont, 1) >= GET_OBJ_VAL(cont, 0)) msg_to_char(ch, "It's already full.\r\n"); else { act("You sap some honey from $p into $P.", FALSE, ch, hive, cont, TO_CHAR); act("$n saps some honey from $p into $P.", FALSE, ch, hive, cont, TO_ROOM); amount = MIN(GET_OBJ_VAL(cont, 0) - GET_OBJ_VAL(cont, 1), GET_OBJ_VAL(hive, 1)); GET_OBJ_VAL(hive, 1) -= amount; GET_OBJ_VAL(cont, 1) += amount; GET_OBJ_VAL(cont, 2) = LIQ_HONEY; weight_change_object(cont, amount); /* Add weight */ } } ACMD(do_extract) { SPECIAL(spec_bee_hive); Object hive, wax; one_argument(argument, arg); if (BUILDING_TYPE(ch->in_room) != BUILDING_APIARY) msg_to_char(ch, "You can't extract wax here!\r\n"); else if (!CAN_USE_ROOM(ch, ch->in_room, 0)) msg_to_char(ch, "You don't have permission to extract wax here.\r\n"); else if (!*arg) msg_to_char(ch, "What would you like to extract wax from?\r\n"); else if (!(hive = get_obj_in_list_vis(ch, arg, world[ch->in_room].contents))) msg_to_char(ch, "There's no %s here!", arg); else if (GET_OBJ_RNUM(hive) < 0 || obj_index[GET_OBJ_RNUM(hive)].spec_proc != spec_bee_hive) act("You can't get wax from $p!", FALSE, ch, hive, 0, TO_CHAR); else if (GET_OBJ_VAL(hive, 2) < 10) act("There isn't enough wax in $p to extract.", FALSE, ch, hive, 0, TO_CHAR); else { wax = read_object(o_WAX, VIRTUAL); if (IS_CARRYING_N(ch) >= CAN_CARRY_N(ch) || GET_OBJ_WEIGHT(wax) + IS_CARRYING_W(ch) > CAN_CARRY_W(ch)) obj_to_room(wax, ch->in_room); else obj_to_char(wax, ch); act("You extract $p from $P.", FALSE, ch, wax, hive, TO_CHAR); act("$n extracts $p from $P.", FALSE, ch, wax, hive, TO_ROOM); GET_OBJ_VAL(hive, 2) -= 10; } } ACMD(do_infiltrate) { int to_room, dir; skip_spaces(&argument); if (IS_NPC(ch)) return; else if (!*argument) msg_to_char(ch, "You must choose a direction to infiltrate.\r\n"); else if ((dir = parse_direction(argument)) < 0) msg_to_char(ch, "Which direction would you like to infiltrate?\r\n"); else if (dir == UP || dir == DOWN) msg_to_char(ch, "You can't infiltrate that direction!\r\n"); else if (SECT((to_room = real_shift(ch->in_room, shift_dir[dir][0], shift_dir[dir][1]))) != SECT_BUILDING && SECT(to_room) != SECT_MULTI) msg_to_char(ch, "You can only infiltrate buildings.\r\n"); else if (SECT(ch->in_room) == SECT_INSIDE) msg_to_char(ch, "You're already inside.\r\n"); else if (GET_RIDING(ch)) msg_to_char(ch, "You can't infiltrate while riding.\r\n"); else if ((!IS_COMPLETE(to_room) && !ALWAYS_CLOSED(to_room)) || CAN_USE_ROOM(ch, to_room, 0)) msg_to_char(ch, "You can just walk in.\r\n"); else if (world[to_room].building_entrance != dir && ((BUILDING_TYPE(to_room) != BUILDING_DOCKS && BUILDING_TYPE(to_room) != BUILDING_SHIPYARD && BUILDING_TYPE(to_room) != BUILDING_TUNNEL && BUILDING_TYPE(to_room) != BUILDING_TUNNEL2 && BUILDING_TYPE(to_room) != BUILDING_GATEHOUSE && BUILDING_TYPE(to_room) != BUILDING_SHIPYARD2) || world[to_room].building_entrance != rev_dir[dir])) msg_to_char(ch, "You can only infiltrate at the entrance.\r\n"); else if (BUILDING_TYPE(to_room) == BUILDING_HAVEN_BURROW || BUILDING_TYPE(to_room) == BUILDING_HAVEN_PUEBLO || BUILDING_TYPE(to_room) == BUILDING_HAVEN_CAVE || BUILDING_TYPE(to_room) == BUILDING_HAVEN_HOUSE) msg_to_char(ch, "You can't infiltrate a haven!\r\n"); else if (ww_dice(GET_DEXTERITY(ch) + GET_LARCENY(ch), 7) <= 0 && !AFF_FLAGGED(ch, AFF_INVISIBLE)) { msg_to_char(ch, "You fail.\r\n"); if (real_empire(world[to_room].owner) != -1) log_to_empire(real_empire(world[to_room].owner), "Someone has attempted to infiltrate at (%d, %d)!", X_COORD(to_room), Y_COORD(to_room)); } else { char_from_room(ch); char_to_room(ch, to_room); look_at_room(ch); msg_to_char(ch, "\r\nInfiltration successful.\r\n"); } } /* tie/untie an npc */ void perform_npc_tie(Creature ch, Creature victim, int subcmd) { extern bool is_entrance(int rnum); Object rope; if (!subcmd && MOB_FLAGGED(victim, MOB_TIED)) act("$E's already tied up!", FALSE, ch, 0, victim, TO_CHAR); else if (subcmd && !MOB_FLAGGED(victim, MOB_TIED)) act("$E isn't even tied up!", FALSE, ch, 0, victim, TO_CHAR); else if (MOB_FLAGGED(victim, MOB_TIED)) { act("You untie $N.", FALSE, ch, 0, victim, TO_CHAR); act("$n unties you!", FALSE, ch, 0, victim, TO_VICT | TO_SLEEP); act("$n unties $N.", FALSE, ch, 0, victim, TO_NOTVICT); REMOVE_BIT(MOB_FLAGS(victim), MOB_TIED); obj_to_char(read_object(o_ROPE, VIRTUAL), ch); } else if (!(rope = get_obj_in_list_num(real_object(o_ROPE), ch->carrying))) msg_to_char(ch, "You don't have any rope.\r\n"); else if (!is_entrance(ch->in_room)) msg_to_char(ch, "You can't tie it here.\r\n"); else { act("You tie $N up.", FALSE, ch, 0, victim, TO_CHAR); act("$n ties you up.", FALSE, ch, 0, victim, TO_VICT | TO_SLEEP); act("$n ties $N up.", FALSE, ch, 0, victim, TO_NOTVICT); SET_BIT(MOB_FLAGS(victim), MOB_TIED); extract_obj(rope); } } ACMD(do_tie) { Creature victim; Object rope; /* subcmd 0 = tie, 1 = untie */ one_argument(argument, arg); if (!*arg) msg_to_char(ch, "%sie whom?\r\n", subcmd ? "Unt" : "T"); else if (!(victim = get_char_vis(ch, arg, FIND_CHAR_ROOM))) msg_to_char(ch, NOPERSON); else if (IS_NPC(victim)) perform_npc_tie(ch, victim, subcmd); else if (IS_GOD(victim) || IS_IMMORTAL(victim)) msg_to_char(ch, "You can't tie up a god!\r\n"); else if (!subcmd && IS_INJURED(victim, INJ_TIED)) act("$E is already tied!", FALSE, ch, 0, victim, TO_CHAR); else if (subcmd && !IS_INJURED(victim, INJ_TIED)) act("$E isn't even tied up!", FALSE, ch, 0, victim, TO_CHAR); else if (IS_INJURED(victim, INJ_TIED)) { act("You unbind $N.", FALSE, ch, 0, victim, TO_CHAR); act("$n unbinds you!", FALSE, ch, 0, victim, TO_VICT | TO_SLEEP); act("$n unbinds $N.", FALSE, ch, 0, victim, TO_NOTVICT); GET_DAMAGE(victim) = MIN(6, GET_DAMAGE(victim)); GET_AGG_DAMAGE(victim) = MIN(GET_DAMAGE(victim), GET_AGG_DAMAGE(victim)); GET_POS(victim) = POS_RESTING; REMOVE_BIT(INJURY_FLAGS(victim), INJ_TIED); obj_to_char(read_object(o_ROPE, VIRTUAL), ch); } else if (GET_POS(victim) >= POS_SLEEPING) act("You need to knock $M out first.", FALSE, ch, 0, victim, TO_CHAR); else if (!(rope = get_obj_in_list_num(real_object(o_ROPE), ch->carrying))) msg_to_char(ch, "You don't have any rope.\r\n"); else { act("You bind and gag $N!", FALSE, ch, 0, victim, TO_CHAR); act("$n binds and gags you!", FALSE, ch, 0, victim, TO_VICT | TO_SLEEP); act("$n binds and gags $N!", FALSE, ch, 0, victim, TO_NOTVICT); SET_BIT(INJURY_FLAGS(victim), INJ_TIED); if (GET_DAMAGE(victim) >= 7) { GET_DAMAGE(victim) = 6; update_pos(victim); } extract_obj(rope); } } ACMD(do_harness) { Creature victim; Object rope = NULL, cart = NULL; /* subcmd 0 = harness, 1 = unharness */ two_arguments(argument, arg, buf); if (!*arg || (!subcmd && !*buf)) { if (subcmd) msg_to_char(ch, "Remove whose harness?\r\n"); else msg_to_char(ch, "Harness whom to what?\r\n"); } else if (!(victim = get_char_vis(ch, arg, FIND_CHAR_ROOM))) msg_to_char(ch, NOPERSON); else if (subcmd && !GET_PULLING(victim)) act("$E isn't harnessed.", FALSE, ch, 0, victim, TO_CHAR); else if (subcmd) { obj_to_char(read_object(o_ROPE, VIRTUAL), ch); cart = GET_PULLING(victim); if (GET_PULLED_BY(cart, 0) == victim) GET_PULLED_BY(cart, 0) = NULL; if (GET_PULLED_BY(cart, 1) == victim) GET_PULLED_BY(cart, 1) = NULL; GET_PULLING(victim) = NULL; act("You unlatch $N from $p.", FALSE, ch, cart, victim, TO_CHAR); act("$n unlatches you from $p.", FALSE, ch, cart, victim, TO_VICT); act("$n unlatches $N from $p.", FALSE, ch, cart, victim, TO_NOTVICT); } else if (GET_PULLING(victim)) act("$E is already harnessed!", FALSE, ch, 0, victim, TO_CHAR); else if (GET_RIDDEN_BY(victim)) msg_to_char(ch, "You can't harness someone who is being ridden.\r\n"); else if (!IS_NPC(victim)) msg_to_char(ch, "You can only harness animals.\r\n"); else if (!(cart = get_obj_in_list_vis(ch, buf, world[ch->in_room].contents))) msg_to_char(ch, "You don't see a %s here.\r\n", buf); else if (GET_OBJ_TYPE(cart) != ITEM_CART) msg_to_char(ch, "You can't harness anyone to that!\r\n"); else if (GET_PULLED_BY(cart, 0) && (GET_OBJ_VAL(cart, 1) <= 1 || GET_PULLED_BY(cart, 1))) msg_to_char(ch, "You can't harness any more animals to it.\r\n"); else if (!(rope = get_obj_in_list_num(real_object(o_ROPE), ch->carrying))) msg_to_char(ch, "You need some rope to do that.\r\n"); else if (!MOB_FLAGGED(victim, MOB_MOUNTABLE)) act("You can't harness $N to that!", FALSE, ch, 0, victim, TO_CHAR); else { extract_obj(rope); if (GET_PULLED_BY(cart, 0)) GET_PULLED_BY(cart, 1) = victim; else GET_PULLED_BY(cart, 0) = victim; GET_PULLING(victim) = cart; act("You harness $N to $p.", FALSE, ch, cart, victim, TO_CHAR); act("$n harnesses you to $p.", FALSE, ch, cart, victim, TO_VICT); act("$n harnesses $N to $p.", FALSE, ch, cart, victim, TO_NOTVICT); } } int total_resource(Creature ch, obj_vnum vnum) { int total = 0; Object obj; for (obj = ch->carrying; obj; obj = obj->next_content) if (GET_OBJ_VNUM(obj) == vnum) total++; for (obj = world[ch->in_room].contents; obj; obj = obj->next_content) if (GET_OBJ_VNUM(obj) == vnum) total++; return total; } void extract_resource(Creature ch, obj_vnum vnum, int amt) { Object o, o2; int remaining = amt; if (remaining) for (o = ch->carrying; o && remaining > 0; o = o2) { o2 = o->next_content; if (GET_OBJ_VNUM(o) == vnum) { remaining--; extract_obj(o); } } if (remaining) for (o = world[ch->in_room].contents; o && remaining > 0; o = o2) { o2 = o->next_content; if (GET_OBJ_VNUM(o) == vnum) { remaining--; extract_obj(o); } } } ACMD(do_assemble) { int i = 0; Object obj; struct assemble_data { char *name; obj_vnum vnum; int science; int intelligence; int sticks, logs, iron, skins; } assembles[] = { { "stool", o_STOOL, 1, 1, 12, 0, 1, 0 }, { "chair", o_CHAIR, 1, 1, 12, 1, 1, 0 }, { "longbow", o_LONGBOW, 2, 2, 3, 0, 0, 20 }, { "table", o_TABLE, 2, 2, 12, 3, 3, 0 }, { "bench", o_BENCH, 2, 2, 12, 3, 3, 0 }, { "shortbow", o_SHORTBOW, 3, 2, 2, 0, 0, 20 }, { "cart", o_CART, 3, 3, 48, 20, 15, 0 }, { "carriage", o_CARRIAGE, 3, 3, 48, 40, 25, 0 }, { "wagon", o_WAGON, 4, 4, 48, 50, 35, 300 }, { "beehive", o_BEEHIVE, 4, 4, 35, 8, 0, 0 }, { "catapult", o_CATAPULT, 5, 4, 48, 60, 45, 0 }, { "\n", 0, 0, 0, 0, 0 } }; skip_spaces(&argument); if (*argument) while ((!is_abbrev(argument, assembles[i].name) || GET_INTELLIGENCE(ch) < assembles[i].intelligence || GET_SCIENCE(ch) < assembles[i].science) && str_cmp(assembles[i].name, "\n")) i++; if (!*argument || !str_cmp(assembles[i].name, "\n")) { msg_to_char(ch, "What would you like to assemble?\r\nYour choices are:"); for (i = 0; str_cmp(assembles[i].name, "\n"); i++) if (assembles[i].intelligence <= GET_INTELLIGENCE(ch) && assembles[i].science <= GET_SCIENCE(ch)) msg_to_char(ch, " %s", assembles[i].name); msg_to_char(ch, "\r\n"); } else if (BUILDING_TYPE(ch->in_room) != BUILDING_CARPENTER) msg_to_char(ch, "You can't assemble here!\r\n"); else if (!CAN_USE_ROOM(ch, ch->in_room, 0)) msg_to_char(ch, "You don't have permission to do that here.\r\n"); else if (total_skins(ch) < assembles[i].skins) msg_to_char(ch, "You don't have enough skin to make that.\r\n"); else if (total_resource(ch, o_LOG) < assembles[i].logs) msg_to_char(ch, "You don't have enough logs to make that.\r\n"); else if (total_resource(ch, o_STICK) < assembles[i].sticks) msg_to_char(ch, "You don't have enough sticks to make that.\r\n"); else if (total_resource(ch, o_IRON) < assembles[i].iron) msg_to_char(ch, "You don't have enough iron ore to make that.\r\n"); else { if (assembles[i].skins) extract_skins_from_char(ch, assembles[i].skins); extract_resource(ch, o_LOG, assembles[i].logs); extract_resource(ch, o_STICK, assembles[i].sticks); extract_resource(ch, o_IRON, assembles[i].iron); obj = read_object(assembles[i].vnum, VIRTUAL); if (CAN_WEAR(obj, ITEM_WEAR_TAKE)) obj_to_char(obj, ch); else obj_to_room(obj, ch->in_room); act("You assemble $p!", FALSE, ch, obj, 0, TO_CHAR); act("$n assembles $p!", TRUE, ch, obj, 0, TO_ROOM); WAIT_STATE(ch, 2 RL_SEC); } } ACMD(do_struggle) { if (!IS_INJURED(ch, INJ_TIED)) msg_to_char(ch, "You aren't even bound!\r\n"); else if (ww_dice(GET_STRENGTH(ch), 8) + GET_POTENCE(ch) < 2) { msg_to_char(ch, "You struggle a bit, but fail to break free.\r\n"); act("$n struggles a little with $s bindings!", TRUE, ch, 0, 0, TO_ROOM); WAIT_STATE(ch, 30 RL_SEC); } else { msg_to_char(ch, "You break free!\r\n"); act("$n struggles with $s bindings and breaks free!", TRUE, ch, 0, 0, TO_ROOM); REMOVE_BIT(INJURY_FLAGS(ch), INJ_TIED); } } ACMD(do_craft) { Object obj, weapon; int i = 0; struct craft_data_structure { char *name; obj_vnum from, to; int timer; } craft_data[] = { { "arrow", o_STICK, o_ARROW, 16 }, { "canoe", o_TREE, o_CANOE, 48 }, { "flute", o_STICK, o_FLUTE, 48 }, { "handle", o_STICK, o_HANDLE, 16 }, { "lyre", o_TREE, o_LYRE, 48 }, { "walkingstick", o_STICK, o_WALKING_STICK, 48 }, { "stake", o_STICK, o_STAKE, 48 }, { "\n", NOTHING, NOTHING } }; one_argument(argument, arg); /* Find what they picked */ if (*arg) for (i = 0; str_cmp(craft_data[i].name, "\n") && !is_abbrev(arg, craft_data[i].name); i++); if (GET_ACTION(ch) == ACT_CRAFTING) { obj_to_char((obj = read_object(GET_ACTION_VNUM(ch, 0), VIRTUAL)), ch); act("You stop scraping at $p.", FALSE, ch, obj, 0, TO_CHAR); GET_ACTION(ch) = ACT_NONE; } else if (GET_ACTION(ch) != ACT_NONE) msg_to_char(ch, "You're already busy doing something else.\r\n"); else if (!*arg || !str_cmp(craft_data[i].name, "\n")) { msg_to_char(ch, "You can craft:\r\n"); for (i = 0; str_cmp(craft_data[i].name, "\n") && !is_abbrev(arg, craft_data[i].name); i++) msg_to_char(ch, "%s\r\n", craft_data[i].name); } else if ((!(weapon = GET_EQ(ch, WEAR_WIELD)) || dam_type[GET_OBJ_VAL(weapon, 2)] < DAM_LETHAL) && (weapon || !(weapon = GET_EQ(ch, WEAR_HOLD)) || dam_type[GET_OBJ_VAL(weapon, 2)] < DAM_LETHAL)) msg_to_char(ch, "You need to be using a sharp tool to craft anything.\r\n"); else if (!(obj = get_obj_in_list_num(real_object(craft_data[i].from), ch->carrying)) && !(obj = get_obj_in_list_num(real_object(craft_data[i].from), world[ch->in_room].contents))) msg_to_char(ch, "You need %s to craft that.\r\n", GET_OBJ_NAME_BY_PROTO(real_object(craft_data[i].from))); else { GET_ACTION(ch) = ACT_CRAFTING; GET_ACTION_ROOM(ch) = NOWHERE; GET_ACTION_TIMER(ch) = craft_data[i].timer; GET_ACTION_ROTATION(ch) = last_action_rotation; GET_ACTION_VNUM(ch, 0) = craft_data[i].from; GET_ACTION_VNUM(ch, 1) = craft_data[i].to; sprintf(buf, "You begin crafting %s.", GET_OBJ_NAME_BY_PROTO(real_object(craft_data[i].to))); sprintf(buf1, "$n begins crafting %s.", GET_OBJ_NAME_BY_PROTO(real_object(craft_data[i].to))); act(buf, FALSE, ch, obj, 0, TO_CHAR); act(buf1, TRUE, ch, obj, 0, TO_ROOM); extract_obj(obj); } } ACMD(do_chip) { Object target, weapon; one_argument(argument, arg); if (GET_ACTION(ch) == ACT_CHIPPING) { obj_to_char((target = read_object(GET_ACTION_VNUM(ch, 0), VIRTUAL)), ch); msg_to_char(ch, "You stop chipping it.\r\n"); act("$n stops chipping $p.", TRUE, ch, target, 0, TO_ROOM); GET_ACTION(ch) = ACT_NONE; } else if (GET_ACTION(ch) != ACT_NONE) msg_to_char(ch, "You're already busy doing something else.\r\n"); else if (!*arg) msg_to_char(ch, "Chip what?\r\n"); else if (!(target = get_obj_in_list_vis(ch, arg, ch->carrying))) msg_to_char(ch, "You don't seem to have a %s.\r\n", arg); else if (GET_OBJ_VNUM(target) != o_ROCK && GET_OBJ_VNUM(target) != o_CHIPPED && GET_OBJ_VNUM(target) != o_HANDAXE) msg_to_char(ch, "You can't chip that!\r\n"); else if ((!(weapon = GET_EQ(ch, WEAR_WIELD)) || GET_OBJ_VAL(weapon, 2) != TYPE_HAMMER) && (weapon || !(weapon = GET_EQ(ch, WEAR_HOLD)) || GET_OBJ_VAL(weapon, 2) != TYPE_HAMMER)) msg_to_char(ch, "You need to be using some kind of hammer to chip it.\r\n"); else { GET_ACTION(ch) = ACT_CHIPPING; GET_ACTION_ROOM(ch) = NOWHERE; GET_ACTION_TIMER(ch) = 16; GET_ACTION_ROTATION(ch) = last_action_rotation; GET_ACTION_VNUM(ch, 0) = GET_OBJ_VNUM(target); act("You begin to chip at $p.", FALSE, ch, target, 0, TO_CHAR); act("$n begins to chip at $p.", TRUE, ch, target, 0, TO_ROOM); extract_obj(target); } } ACMD(do_pan) { int i; 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) break; if (GET_ACTION(ch) == ACT_PANNING) { msg_to_char(ch, "You stop panning for gold.\r\n"); GET_ACTION(ch) = ACT_NONE; } else if (GET_ACTION(ch) != ACT_NONE) msg_to_char(ch, "You're a bit busy right now.\r\n"); else if (!IS_OUTDOORS(ch) || i == NUM_2D_DIRS) msg_to_char(ch, "You need to be next to a river to pan for gold.\r\n"); else 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"); else { msg_to_char(ch, "You kneel down and begin panning at the river bed.\r\n"); act("$n kneels down and begins panning at the river bed.", TRUE, ch, 0, 0, TO_ROOM); GET_ACTION(ch) = ACT_PANNING; GET_ACTION_TIMER(ch) = 10; GET_ACTION_ROOM(ch) = ch->in_room; GET_ACTION_ROTATION(ch) = last_action_rotation; } } ACMD(do_play) { Object obj; if (GET_ACTION(ch) == ACT_MUSIC) { msg_to_char(ch, "You stop playing music.\r\n"); act("$n stops playing music.", FALSE, ch, 0, 0, TO_ROOM); GET_ACTION(ch) = ACT_NONE; } else if (GET_ACTION(ch) != ACT_NONE) msg_to_char(ch, "You're busy right now.\r\n"); else 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"); else if (GET_MUSIC(ch) == 0) msg_to_char(ch, "You have no musical skill whatsoever.\r\n"); else { act("You begin to play $p.", FALSE, ch, obj, 0, TO_CHAR); act("$n begins to play $p.", FALSE, ch, obj, 0, TO_ROOM); GET_ACTION(ch) = ACT_MUSIC; GET_ACTION_TIMER(ch) = -1; GET_ACTION_ROOM(ch) = NOWHERE; GET_ACTION_ROTATION(ch) = last_action_rotation; } } ACMD(do_excavate) { extern bool is_entrance(int rnum); if (GET_ACTION(ch) == ACT_EXCAVATING) { msg_to_char(ch, "You stop the excavation.\r\n"); act("$n stops excavating the trench.", FALSE, ch, 0, 0, TO_ROOM); GET_ACTION(ch) = ACT_NONE; } else if (GET_ACTION(ch) != ACT_NONE) msg_to_char(ch, "You're already quite busy.\r\n"); else if (!CAN_USE_ROOM(ch, ch->in_room, 1)) msg_to_char(ch, "You don't have permission to excavate here!\r\n"); else 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"); else if (SECT(ch->in_room) == SECT_TRENCH && GET_BUILD_VALUE(ch->in_room) < 0) { msg_to_char(ch, "You begin to dig.\r\n"); GET_ACTION(ch) = ACT_EXCAVATING; GET_ACTION_TIMER(ch) = -1; GET_ACTION_ROOM(ch) = ch->in_room; GET_ACTION_ROTATION(ch) = last_action_rotation; } else if (SECT(ch->in_room) == SECT_TRENCH) msg_to_char(ch, "The trench is already complete!\r\n"); else if (SECT(ch->in_room) != SECT_FIELD && SECT(ch->in_room) != SECT_DESERT) msg_to_char(ch, "You can only dig a trench in an open field.\r\n"); else if (is_entrance(ch->in_room)) msg_to_char(ch, "You can't dig a trench in front of an entrance.\r\n"); else { msg_to_char(ch, "You begin to excavate a trench.\r\n"); act("$n begins excavating a trench.", FALSE, ch, 0, 0, TO_ROOM); GET_ACTION(ch) = ACT_EXCAVATING; GET_ACTION_TIMER(ch) = -1; GET_ACTION_ROOM(ch) = ch->in_room; GET_ACTION_ROTATION(ch) = last_action_rotation; /* Set up the trench */ GET_BUILD_VALUE(ch->in_room) = -500; SECT(ch->in_room) = SECT_TRENCH; } } ACMD(do_search) { Creature targ; bool found = FALSE; if (IS_NPC(ch)) return; else if (AFF_FLAGGED(ch, AFF_BLIND)) msg_to_char(ch, "How can you do that, you're blind!\r\n"); else if (!CAN_SEE_IN_DARK_ROOM(ch, ch->in_room)) msg_to_char(ch, "You can't see well enough here to search for anyone!\r\n"); else if (AFF_FLAGGED(ch, AFF_SENSE_HIDE)) msg_to_char(ch, "You search, but find nobody.\r\n"); else { act("$n begins searching around!", TRUE, ch, 0, 0, TO_ROOM); for (targ = world[ch->in_room].people; targ; targ = targ->next_in_room) { if (ch == targ) continue; if (!AFF_FLAGGED(targ, AFF_HIDE) || CAN_SEE(ch, targ)) continue; SET_BIT(AFF_FLAGS(ch), AFF_SENSE_HIDE); if (CAN_SEE(ch, targ) && ww_dice(GET_PERCEPTION(ch) + GET_INVESTIGATION(ch), 7 - SENSES_BONUS(ch)) > ww_dice(GET_DEXTERITY(targ) + GET_STEALTH(targ), 6)) { act("You find $N!", FALSE, ch, 0, targ, TO_CHAR); msg_to_char(targ, "You are discovered!\r\n"); REMOVE_BIT(AFF_FLAGS(targ), AFF_HIDE); found = TRUE; } REMOVE_BIT(AFF_FLAGS(ch), AFF_SENSE_HIDE); } if (!found) msg_to_char(ch, "You search, but find nobody.\r\n"); WAIT_STATE(ch, PULSE_VIOLENCE); } } ACMD(do_scrape) { Object obj, weapon; one_argument(argument, arg); if (GET_ACTION(ch) == ACT_SCRAPING) { obj_to_char((obj = read_object(o_TREE, VIRTUAL)), ch); act("You stop scraping $p.", FALSE, ch, obj, 0, TO_CHAR); GET_ACTION(ch) = ACT_NONE; } else if (GET_ACTION(ch) != ACT_NONE) msg_to_char(ch, "You're already busy doing something else.\r\n"); else if (!*arg) msg_to_char(ch, "Scrape what?\r\n"); else if (!(obj = get_obj_in_list_vis(ch, arg, ch->carrying))) msg_to_char(ch, "You don't seem to have anything like that.\r\n"); else if (GET_OBJ_VNUM(obj) != o_TREE) msg_to_char(ch, "You can't scrape that!\r\n"); else if ((!(weapon = GET_EQ(ch, WEAR_WIELD)) || dam_type[GET_OBJ_VAL(weapon, 2)] < DAM_LETHAL) && (weapon || !(weapon = GET_EQ(ch, WEAR_HOLD)) || dam_type[GET_OBJ_VAL(weapon, 2)] < DAM_LETHAL)) msg_to_char(ch, "You need to be using a sharp tool to scrape anything.\r\n"); else { GET_ACTION(ch) = ACT_SCRAPING; GET_ACTION_ROOM(ch) = NOWHERE; GET_ACTION_TIMER(ch) = number(3, 8); GET_ACTION_ROTATION(ch) = last_action_rotation; act("You begin scraping $p.", FALSE, ch, obj, 0, TO_CHAR); act("$n begins scraping $p.", TRUE, ch, obj, 0, TO_ROOM); extract_obj(obj); } } /* Temporary Werewolf Stuff */ struct tribe_data tribe[] = { { "Black Furies" }, { "Bone Gnawers" }, { "Children of Gaia" }, { "Fenrir" }, { "Fianna" }, { "Red Talons" }, { "Shadow Lords" }, { "Silent Striders" }, { "Silver Fangs" }, { "Warders" }, { "\n" } }; const char *auspice[] = { "Ragabash", "Theurge", "Philodox", "Galliard", "Ahroun", "\n" }; const char *breed[] = { "Homid", "Metis", "Lupus", "\n" }; const char *forms[] = { "homid", "glabro", "crinos", "hispo", "lupus", "\n" }; int form_morphs[] = { MORPH_NONE, MORPH_GLABRO, MORPH_CRINOS, MORPH_HISPO, MORPH_LUPUS }; /* use: shift <form> */ ACMD(do_shift) { int to_form = MORPH_NONE; two_arguments(argument, arg, buf); /* buf WILL be used to use rage to morph */ /* also, this SHOULD be based upon successes */ if (!*arg) msg_to_char(ch, "What form would you like to shift to?\r\n"); else if ((to_form = search_block(arg, forms, FALSE)) < 0) msg_to_char(ch, "The only valid forms are Homid, Glabro, Crinos, Hispo, and Lupus!\r\n"); else if ((to_form = form_morphs[to_form]) == GET_MORPH(ch)) msg_to_char(ch, "You're already in that form!\r\n"); else if (to_form == GET_BREED_FORM(ch)) { sprintf(buf, "%s becomes $n!", PERS(ch, ch, 0)); perform_morph(ch, to_form); act(buf, TRUE, ch, 0, 0, TO_ROOM); act("You shift into $n!", FALSE, ch, 0, 0, TO_CHAR); } else if (GET_ACTION(ch) != ACT_NONE) msg_to_char(ch, "You're busy right now.\r\n"); else if (ww_dice(GET_STAMINA(ch) + GET_PRIMAL_URGE(ch), 6) < 2) { msg_to_char(ch, "You try to shift, but lack the link to your primal side!\r\n"); WAIT_STATE(ch, PULSE_VIOLENCE * 2); } else { GET_ACTION(ch) = ACT_MORPHING; GET_ACTION_ROOM(ch) = NOWHERE; GET_ACTION_VNUM(ch, 0) = to_form; GET_ACTION_TIMER(ch) = 3; GET_ACTION_ROTATION(ch) = last_action_rotation; msg_to_char(ch, "You begin to shift..\r\n"); } }