/* ************************************************************************
* 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");
}
}