/****************************************************************************
* [S]imulated [M]edieval [A]dventure multi[U]ser [G]ame | \\._.// *
* -----------------------------------------------------------| (0...0) *
* SMAUG 1.4 (C) 1994, 1995, 1996, 1998 by Derek Snider | ).:.( *
* -----------------------------------------------------------| {o o} *
* SMAUG code team: Thoric, Altrag, Blodkai, Narn, Haus, | / ' ' \ *
* Scryn, Rennard, Swordbearer, Gorog, Grishnakh, Nivek, |~'~.VxvxV.~'~*
* Tricops and Fireblade | *
* ------------------------------------------------------------------------ *
* Merc 2.1 Diku Mud improvments copyright (C) 1992, 1993 by Michael *
* Chastain, Michael Quan, and Mitchell Tse. *
* Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, *
* Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. *
* ------------------------------------------------------------------------ *
* Object manipulation module *
****************************************************************************/
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "mud.h"
#include "bet.h"
extern int start_marketpid;
/*double sqrt( double x );*/
int sacall = 0;
/*
* External functions
*/
void show_list_to_char args((OBJ_DATA * list, CHAR_DATA * ch, bool fShort, bool fShowNothing, const int iDefaultAction));
void write_corpses args((CHAR_DATA * ch, char *name, OBJ_DATA * objrem));
/*
* Local functions.
*/
void get_obj args((CHAR_DATA * ch, OBJ_DATA * obj, OBJ_DATA * container));
OBJ_DATA *recursive_note_find args((OBJ_DATA * obj, char *argument));
/*
* how resistant an object is to damage -Thoric
*/
sh_int get_obj_resistance(OBJ_DATA * obj, CHAR_DATA *ch)
{
int resist;
if (obj->item_type == ITEM_WEAPON)
resist = obj->value[10];
else
resist = obj->value[4];
/* magical items are more resistant */
if (IS_OBJ_STAT(obj, ITEM_MAGIC))
resist += number_range(1, 2);
/* glowing objects should have a little bonus */
if (IS_OBJ_STAT(obj, ITEM_GLOW))
resist += 1;
/* lets make store inventory pretty tough */
if (IS_OBJ_STAT(obj, ITEM_INVENTORY))
resist += 3;
resist += ch->apply_armor;
/* and lasty... take armor or weapon's condition into consideration */
if (obj->item_type == ITEM_ARMOR)
resist = resist * obj->value[3] / 1000;
if (obj->item_type == ITEM_WEAPON)
resist = resist * obj->value[0] / 1000;
return URANGE(1, resist, 20);
}
bool is_kingdom_chest(OBJ_DATA * obj)
{
KCHEST_DATA *kchest;
for (kchest = first_kchest; kchest; kchest = kchest->next)
{
if (kchest->obj == obj)
return TRUE;
}
return FALSE;
}
void get_obj(CHAR_DATA * ch, OBJ_DATA * obj, OBJ_DATA * container)
{
CLAN_DATA *clan;
int weight;
int amt; /* gold per-race multipliers */
char *pd;
char name[MIL];
CHAR_DATA *fch;
if (!CAN_WEAR(obj, ITEM_TAKE) && (ch->level < sysdata.level_getobjnotake))
{
send_to_char("You can't take that.\n\r", ch);
return;
}
if (obj->in_room)
{
for(fch = obj->in_room->first_person; fch != NULL; fch = fch->next_in_room)
{
if (fch->on == obj)
{
send_to_char("You cannot pick up a piece of furniture with someone on it.\n\r", ch);
return;
}
}
}
if (IS_SET(obj->magic_flags, ITEM_PKDISARMED))
{
REMOVE_BIT(obj->magic_flags, ITEM_PKDISARMED);
obj->value[5] = 0;
}
if (container && container->item_type == ITEM_CORPSE_PC && IS_OBJ_STAT(obj, ITEM_NOGIVE) && !sysdata.resetgame)
{
pd = container->short_descr;
pd = one_argument(pd, name);
pd = one_argument(pd, name);
pd = one_argument(pd, name);
pd = one_argument(pd, name);
if (IS_NPC(ch) || str_cmp(name, ch->name))
{
send_to_char("A nogive item cannot be looted from a corpse.\n\r", ch);
return;
}
}
if (IS_UNIQUE(ch, obj) && container && container->carried_by && container->carried_by == ch)
{
;
}
else if (IS_UNIQUE(ch, obj))
{
send_to_char("That item is unique and you already have one on you.\n\r", ch);
return;
}
if (IS_OBJ_STAT(obj, ITEM_PROTOTYPE) && !can_take_proto(ch))
{
send_to_char("A godly force prevents you from getting close to it.\n\r", ch);
return;
}
if (get_ch_carry_number(ch) + get_obj_number(obj) > can_carry_n(ch))
{
act(AT_PLAIN, "$d: you can't carry that many items.", ch, NULL, obj->name, TO_CHAR);
return;
}
if (IS_OBJ_STAT(obj, ITEM_COVERING))
weight = obj->weight;
else
weight = get_obj_weight(obj);
if (get_ch_carry_weight(ch) + weight > can_carry_w(ch))
{
act(AT_PLAIN, "$d: you can't carry that much weight.", ch, NULL, obj->name, TO_CHAR);
return;
}
if (container)
{
if (container->item_type == ITEM_KEYRING && !IS_OBJ_STAT(container, ITEM_COVERING))
{
act(AT_ACTION, "You remove $p from $P", ch, obj, container, TO_CHAR);
act(AT_ACTION, "$n removes $p from $P", ch, obj, container, TO_ROOM);
}
else
{
act(AT_ACTION, IS_OBJ_STAT(container, ITEM_COVERING) ? "You get $p from beneath $P." : "You get $p from $P", ch, obj, container, TO_CHAR);
act(AT_ACTION, IS_OBJ_STAT(container, ITEM_COVERING) ? "$n gets $p from beneath $P." : "$n gets $p from $P", ch, obj, container, TO_ROOM);
}
if (IS_OBJ_STAT(container, ITEM_CLANCORPSE) && !IS_NPC(ch) && str_cmp(container->name + 7, ch->name))
container->value[5]++;
obj_from_obj(obj);
}
else
{
act(AT_ACTION, "You get $p.", ch, obj, container, TO_CHAR);
act(AT_ACTION, "$n gets $p.", ch, obj, container, TO_ROOM);
obj_from_room(obj);
}
check_for_trap(ch, obj, -1, NEW_TRAP_GETOBJ);
if (char_died(ch))
return;
if (global_retcode == rOBJ_SCRAPPED)
return;
// Check to see if it is a kingdom chest
if (container && is_kingdom_chest(container))
save_kingdom_chests(ch);
/* Clan storeroom checks */
if (xIS_SET(ch->in_room->room_flags, ROOM_CLANSTOREROOM) && (!container || container->carried_by == NULL))
{
/* if (!char_died) save_char_obj(ch); */
for (clan = first_clan; clan; clan = clan->next)
if (clan->storeroom == ch->in_room->vnum)
save_clan_storeroom(ch, clan);
}
if (obj->item_type == ITEM_MONEY)
{
amt = obj->value[0];
/*
* The idea was to make some races more adroit at money handling,
* however, this resulted in elves dropping 1M gps and picking
* up 1.1M, repeating, and getting rich. The only solution would
* be to fuzzify the "drop coins" code, but that seems like it'd
* lead to more confusion than it warrants. -h
*
* When you work on this again, make it so that amt is NEVER multiplied
* by more than 1.0. Use less than 1.0 for ogre, orc, troll, etc.
* (Ie: a penalty rather than a bonus)
*/
#ifdef GOLD_MULT
switch (ch->race)
{
case (1):
amt *= 1.1;
break; /* elf */
case (2):
amt *= 0.97;
break; /* dwarf */
case (3):
amt *= 1.02;
break; /* halfling */
case (4):
amt *= 1.08;
break; /* pixie */
case (6):
amt *= 0.92;
break; /* half-ogre */
case (7):
amt *= 0.94;
break; /* half-orc */
case (8):
amt *= 0.90;
break; /* half-troll */
case (9):
amt *= 1.04;
break; /* half-elf */
case (10):
amt *= 1.06;
break; /* gith */
}
#endif
ch->gold += amt;
if (xIS_SET(ch->act, PLR_AUTOSPLIT))
{
char buf1[20];
sprintf(buf1, "%d", amt);
do_split(ch, buf1);
}
extract_obj(obj);
}
else
{
obj = obj_to_char(obj, ch);
}
if (char_died(ch) || obj_extracted(obj))
return;
oprog_get_trigger(ch, obj);
return;
}
void do_get(CHAR_DATA * ch, char *argument)
{
char arg1[MIL];
char arg2[MIL];
OBJ_DATA *obj;
OBJ_DATA *obj_next;
OBJ_DATA *container;
sh_int number;
bool found;
argument = one_argument(argument, arg1);
if (is_number(arg1))
{
number = atoi(arg1);
if (number < 1)
{
send_to_char("That was easy...\n\r", ch);
return;
}
if ((get_ch_carry_number(ch) + number) > can_carry_n(ch))
{
send_to_char("You can't carry that many.\n\r", ch);
return;
}
argument = one_argument(argument, arg1);
}
else
number = 0;
argument = one_argument(argument, arg2);
/* munch optional words */
if (!str_cmp(arg2, "from") && argument[0] != '\0')
argument = one_argument(argument, arg2);
/* Get type. */
if (arg1[0] == '\0')
{
send_to_char("Get what?\n\r", ch);
return;
}
if (ms_find_obj(ch))
return;
if (IS_NPC(ch) && xIS_SET(ch->act, ACT_MILITARY))
{
send_to_char("You cannot do that.\n\r", ch);
return;
}
if (arg2[0] == '\0')
{
if (number <= 1 && str_cmp(arg1, "all") && str_prefix("all.", arg1))
{
/* 'get obj' */
obj = get_obj_list(ch, arg1, ch->in_room->first_content);
if (!obj)
{
act(AT_PLAIN, "I see no $T here.", ch, NULL, arg1, TO_CHAR);
return;
}
separate_obj(obj);
get_obj(ch, obj, NULL);
if (char_died(ch))
return;
if (IS_SET(sysdata.save_flags, SV_GET))
save_char_obj(ch);
}
else
{
sh_int cnt = 0;
bool fAll;
char *chk;
if (xIS_SET(ch->in_room->room_flags, ROOM_DONATION))
{
send_to_char("The gods frown upon such a display of greed!\n\r", ch);
return;
}
if (!str_cmp(arg1, "all"))
fAll = TRUE;
else
fAll = FALSE;
if (number > 1)
chk = arg1;
else
chk = &arg1[4];
/* 'get all' or 'get all.obj' */
found = FALSE;
for (obj = ch->in_room->last_content; obj; obj = obj_next)
{
obj_next = obj->prev_content;
if ((fAll || nifty_is_name(chk, obj->name)) && can_see_obj(ch, obj))
{
if (IS_OBJ_STAT(obj, ITEM_ONMAP))
{
if (ch->map != obj->map
|| ch->coord->x != obj->coord->x
|| ch->coord->y != obj->coord->y)
{
found = FALSE;
continue;
}
}
found = TRUE;
if (number && (cnt + obj->count) > number)
split_obj(obj, number - cnt);
cnt += obj->count;
get_obj(ch, obj, NULL);
if (char_died(ch) || get_ch_carry_number(ch) >= can_carry_n(ch) || get_ch_carry_weight(ch) >= can_carry_w(ch) || (number && cnt >= number))
{
if (IS_SET(sysdata.save_flags, SV_GET) && !char_died(ch))
save_char_obj(ch);
return;
}
}
}
if (!found)
{
if (fAll)
send_to_char("I see nothing here.\n\r", ch);
else
act(AT_PLAIN, "I see no $T here.", ch, NULL, chk, TO_CHAR);
}
else if (IS_SET(sysdata.save_flags, SV_GET))
save_char_obj(ch);
}
}
else
{
/* 'get ... container' */
if (!str_cmp(arg2, "all") || !str_prefix("all.", arg2))
{
send_to_char("You can't do that.\n\r", ch);
return;
}
if ((container = get_obj_here(ch, arg2)) == NULL)
{
act(AT_PLAIN, "I see no $T here.", ch, NULL, arg2, TO_CHAR);
return;
}
switch (container->item_type)
{
default:
if (!IS_OBJ_STAT(container, ITEM_COVERING))
{
send_to_char("That's not a container.\n\r", ch);
return;
}
if (get_ch_carry_weight(ch) + container->weight > can_carry_w(ch))
{
send_to_char("It's too heavy for you to lift.\n\r", ch);
return;
}
break;
case ITEM_CONTAINER:
case ITEM_CORPSE_NPC:
case ITEM_KEYRING:
case ITEM_QUIVER:
case ITEM_SHEATH:
break;
case ITEM_CORPSE_PC:
{
bool fGroup;
char name[MIL];
CHAR_DATA *gch;
char *pd;
fGroup = FALSE;
if (IS_NPC(ch))
{
send_to_char("You can't do that.\n\r", ch);
return;
}
pd = container->short_descr;
pd = one_argument(pd, name);
pd = one_argument(pd, name);
pd = one_argument(pd, name);
pd = one_argument(pd, name);
/* Killer/owner loot only if die to pkill blow --Blod */
if (IS_OBJ_STAT(container, ITEM_CLANCORPSE)
&& !IS_NPC(ch)
&& container->action_desc[0] != '\0'
&& str_cmp(name, ch->name) && str_cmp(container->action_desc, ch->name) && container->timer > 2878)
{
send_to_char("The corpse is too fresh to loot at this moment..\n\r", ch);
return;
}
if (IS_OBJ_STAT(container, ITEM_CLANCORPSE)
&& !IS_NPC(ch) && container->action_desc[0] != '\0' && !str_cmp(container->action_desc, ch->name))
{
if (check_room_pk(ch) == 4)
fGroup = TRUE;
}
if (IS_OBJ_STAT(container, ITEM_CLANCORPSE) && container->timer < 2879)
{
if (check_room_pk(ch) == 4)
fGroup = TRUE;
}
if (str_cmp(name, ch->name) && !IS_IMMORTAL(ch))
{
for (gch = first_char; gch; gch = gch->next)
{
if (!IS_NPC(gch) && is_same_group(ch, gch) && !str_cmp(name, gch->name))
{
fGroup = TRUE;
break;
}
}
if (!fGroup)
{
send_to_char("That's someone else's corpse.\n\r", ch);
return;
}
}
}
}
if (container->item_type == ITEM_CONTAINER || container->item_type == ITEM_QUIVER)
{
if (!IS_OBJ_STAT(container, ITEM_COVERING) && IS_SET(container->value[1], CONT_CLOSED))
{
act(AT_PLAIN, "The $d is closed.", ch, NULL, container->name, TO_CHAR);
return;
}
}
if (number <= 1 && str_cmp(arg1, "all") && str_prefix("all.", arg1))
{
/* 'get obj container' */
obj = get_obj_list(ch, arg1, container->first_content);
if (!obj)
{
act(AT_PLAIN, IS_OBJ_STAT(container, ITEM_COVERING) ?
"I see nothing like that beneath the $T." : "I see nothing like that in the $T.", ch, NULL, arg2, TO_CHAR);
return;
}
separate_obj(obj);
check_for_trap(ch, container, TRAP_GET, NEW_TRAP_GET);
if (char_died(ch))
return;
if (global_retcode == rOBJ_SCRAPPED)
return;
get_obj(ch, obj, container);
/* Oops no wonder corpses were duping oopsie did I do that
* --Shaddai
*/
if (container->item_type == ITEM_CORPSE_PC)
write_corpses(NULL, container->short_descr + 14, NULL);
if (IS_SET(sysdata.save_flags, SV_GET))
save_char_obj(ch);
}
else
{
int cnt = 0;
bool fAll;
char *chk;
/* 'get all container' or 'get all.obj container' */
if (IS_OBJ_STAT(container, ITEM_DONATION))
{
send_to_char("The gods frown upon such an act of greed!\n\r", ch);
return;
}
if (!str_cmp(arg1, "all"))
fAll = TRUE;
else
fAll = FALSE;
if (number > 1)
chk = arg1;
else
chk = &arg1[4];
found = FALSE;
check_for_trap(ch, container, TRAP_GET, NEW_TRAP_GET);
if (char_died(ch))
return;
if (global_retcode == rOBJ_SCRAPPED)
return;
for (obj = container->first_content; obj; obj = obj_next)
{
obj_next = obj->next_content;
if ((fAll || nifty_is_name(chk, obj->name)) && can_see_obj(ch, obj))
{
found = TRUE;
if (number && (cnt + obj->count) > number)
split_obj(obj, number - cnt);
cnt += obj->count;
get_obj(ch, obj, container);
if (char_died(ch) || get_ch_carry_number(ch) >= can_carry_n(ch) || get_ch_carry_weight(ch) >= can_carry_w(ch) || (number && cnt >= number))
return;
}
}
if (!found)
{
if (fAll)
{
if (container->item_type == ITEM_KEYRING && !IS_OBJ_STAT(container, ITEM_COVERING))
act(AT_PLAIN, "The $T holds no keys.", ch, NULL, arg2, TO_CHAR);
else
act(AT_PLAIN, IS_OBJ_STAT(container, ITEM_COVERING) ?
"I see nothing beneath the $T." : "I see nothing in the $T.", ch, NULL, arg2, TO_CHAR);
}
else
{
if (container->item_type == ITEM_KEYRING && !IS_OBJ_STAT(container, ITEM_COVERING))
act(AT_PLAIN, "The $T does not hold that key.", ch, NULL, arg2, TO_CHAR);
else
act(AT_PLAIN, IS_OBJ_STAT(container, ITEM_COVERING) ?
"I see nothing like that beneath the $T." : "I see nothing like that in the $T.", ch, NULL, arg2, TO_CHAR);
}
}
/* Oops no wonder corpses were duping oopsie did I do that
* --Shaddai
*/
if (container && container->item_type == ITEM_CORPSE_PC)
write_corpses(NULL, container->short_descr + 14, NULL);
if (found && IS_SET(sysdata.save_flags, SV_GET))
save_char_obj(ch);
}
}
return;
}
void do_put(CHAR_DATA * ch, char *argument)
{
char arg1[MIL];
char arg2[MIL];
OBJ_DATA *container;
OBJ_DATA *obj;
OBJ_DATA *sheath;
OBJ_DATA *obj_next;
CLAN_DATA *clan;
sh_int count;
int number;
bool save_char = FALSE;
argument = one_argument(argument, arg1);
if (is_number(arg1))
{
number = atoi(arg1);
if (number < 1)
{
send_to_char("That was easy...\n\r", ch);
return;
}
argument = one_argument(argument, arg1);
}
else
number = 0;
argument = one_argument(argument, arg2);
/* munch optional words */
if ((!str_cmp(arg2, "into") || !str_cmp(arg2, "inside")
|| !str_cmp(arg2, "in") || !str_cmp(arg2, "under") || !str_cmp(arg2, "onto") || !str_cmp(arg2, "on")) && argument[0] != '\0')
argument = one_argument(argument, arg2);
if (arg1[0] == '\0' || arg2[0] == '\0')
{
send_to_char("Put what in what?\n\r", ch);
return;
}
if (ms_find_obj(ch))
return;
if (!str_cmp(arg2, "all") || !str_prefix("all.", arg2))
{
send_to_char("You can't do that.\n\r", ch);
return;
}
if ((container = get_obj_here(ch, arg2)) == NULL)
{
act(AT_PLAIN, "I see no $T here.", ch, NULL, arg2, TO_CHAR);
return;
}
if (!container->carried_by && IS_SET(sysdata.save_flags, SV_PUT))
save_char = TRUE;
if (IS_OBJ_STAT(container, ITEM_COVERING))
{
if (get_ch_carry_weight(ch) + container->weight > can_carry_w(ch))
{
send_to_char("It's too heavy for you to lift.\n\r", ch);
return;
}
}
else
{
if (container->item_type != ITEM_CONTAINER
&& container->item_type != ITEM_KEYRING && container->item_type != ITEM_QUIVER && container->item_type != ITEM_SHEATH)
{
send_to_char("That's not a container.\n\r", ch);
return;
}
if (container->item_type == ITEM_CONTAINER || container->item_type == ITEM_QUIVER)
{
if (IS_SET(container->value[1], CONT_CLOSED))
{
act(AT_PLAIN, "The $d is closed.", ch, NULL, container->name, TO_CHAR);
return;
}
}
}
if (number <= 1 && str_cmp(arg1, "all") && str_prefix("all.", arg1))
{
/* 'put obj container' */
if ((obj = get_obj_carry(ch, arg1)) == NULL)
{
send_to_char("You do not have that item.\n\r", ch);
return;
}
if (obj == container)
{
send_to_char("You can't fold it into itself.\n\r", ch);
return;
}
if (!can_drop_obj(ch, obj))
{
send_to_char("You can't let go of it.\n\r", ch);
return;
}
/* Check to see if they are trying to cheat by putting the item in a container --Xerves 3/24/99 */
if ((IS_OBJ_STAT(obj, ITEM_NOGIVE) && !IS_OBJ_STAT(container, ITEM_NOGIVE))
|| (IS_OBJ_STAT(container, ITEM_NOGIVE) && !IS_OBJ_STAT(obj, ITEM_NOGIVE)))
{
send_to_char("You failed again my friend!\n\r", ch);
return;
}
if (container && (IS_UNIQUE(ch, container) || IS_UNIQUE(ch, obj)) && obj->item_type == ITEM_CONTAINER)
{
send_to_char("You cannot put a unique container in any kind of container.\n\r", ch);
return;
}
if (container->item_type == ITEM_KEYRING && obj->item_type != ITEM_KEY)
{
send_to_char("That's not a key.\n\r", ch);
return;
}
if (container->item_type == ITEM_QUIVER && obj->item_type != ITEM_PROJECTILE)
{
send_to_char("That's not a projectile.\n\r", ch);
return;
}
if (container->item_type == ITEM_SHEATH && (container->value[1] != obj->value[3]))
{
send_to_char("You can only put a weapon made for the sheath in the sheath.\n\r", ch);
return;
}
if (container->item_type == ITEM_SHEATH && ((container->value[2] != obj->pIndexData->vnum) && container->value[2] != 0))
{
send_to_char("Your sheath was made for only one weapon and the weapon you have it not it.\n\r", ch);
return;
}
if ((IS_OBJ_STAT(container, ITEM_COVERING)
&& (get_obj_weight(obj) / obj->count) > ((get_obj_weight(container) / container->count) - container->weight)))
{
send_to_char("It won't fit under there.\n\r", ch);
return;
}
/* note use of get_real_obj_weight */
if ((get_real_obj_weight(obj) / obj->count) + (get_real_obj_weight(container) / container->count) > container->value[0])
{
send_to_char("It won't fit.\n\r", ch);
return;
}
/* Don't need all of this, but will probably use it later on containers --Xerves */
if (container->item_type == ITEM_SHEATH)
{
count = 0;
if (container->first_content)
{
for (sheath = container->first_content; sheath; sheath = sheath->next_content)
count++;
}
if (count == 1)
{
send_to_char("Sheath's only fit one weapon, remove the one in it first.\n\r", ch);
return;
}
}
separate_obj(obj);
separate_obj(container);
obj_from_char(obj);
obj = obj_to_obj(obj, container);
count = obj->count;
obj->count = 1;
if (container->item_type == ITEM_KEYRING && !IS_OBJ_STAT(container, ITEM_COVERING))
{
act(AT_ACTION, "$n slips $p onto $P.", ch, obj, container, TO_ROOM);
act(AT_ACTION, "You slip $p onto $P.", ch, obj, container, TO_CHAR);
}
else
{
act(AT_ACTION, IS_OBJ_STAT(container, ITEM_COVERING) ? "$n hides $p beneath $P." : "$n puts $p in $P.", ch, obj, container, TO_ROOM);
act(AT_ACTION, IS_OBJ_STAT(container, ITEM_COVERING) ? "You hide $p beneath $P." : "You put $p in $P.", ch, obj, container, TO_CHAR);
}
obj->count = count;
check_for_trap(ch, container, TRAP_PUT, NEW_TRAP_PUT);
if (char_died(ch))
return;
if (global_retcode == rOBJ_SCRAPPED)
return;
check_for_trap(ch, obj, -1, NEW_TRAP_PUTOBJ);
if (char_died(ch))
return;
if (global_retcode == rOBJ_SCRAPPED)
return;
/* Oops no wonder corpses were duping oopsie did I do that
* --Shaddai
*/
if (container->item_type == ITEM_CORPSE_PC)
write_corpses(NULL, container->short_descr + 14, NULL);
if (save_char)
save_char_obj(ch);
// Check to see if it is a kingdom chest
if (container && is_kingdom_chest(container))
save_kingdom_chests(ch);
/* Clan storeroom check */
if (xIS_SET(ch->in_room->room_flags, ROOM_CLANSTOREROOM) && container->carried_by == NULL)
{
/* if (!char_died && !save_char ) save_char_obj(ch); */
for (clan = first_clan; clan; clan = clan->next)
if (clan->storeroom == ch->in_room->vnum)
save_clan_storeroom(ch, clan);
}
}
else
{
bool found = FALSE;
int cnt = 0;
bool fAll;
char *chk;
if (container->item_type == ITEM_SHEATH)
{
send_to_char("You cannot put all your items in a sheath, only one weapon.\n\r", ch);
return;
}
if (!str_cmp(arg1, "all"))
fAll = TRUE;
else
fAll = FALSE;
if (number > 1)
chk = arg1;
else
chk = &arg1[4];
separate_obj(container);
check_for_trap(ch, container, TRAP_PUT, NEW_TRAP_PUT);
if (char_died(ch))
return;
if (global_retcode == rOBJ_SCRAPPED)
return;
/* 'put all container' or 'put all.obj container' */
for (obj = ch->first_carrying; obj; obj = obj_next)
{
obj_next = obj->next_content;
if ((fAll || nifty_is_name(chk, obj->name))
&& can_see_obj(ch, obj)
&& obj->wear_loc == WEAR_NONE
&& obj != container
&& can_drop_obj(ch, obj)
&& (container->item_type != ITEM_KEYRING || obj->item_type == ITEM_KEY)
&& (container->item_type != ITEM_QUIVER || obj->item_type == ITEM_PROJECTILE)
&& get_obj_weight(obj) + get_obj_weight(container) <= container->value[0])
{
found = TRUE;
if ((IS_OBJ_STAT(obj, ITEM_NOGIVE) && !IS_OBJ_STAT(container, ITEM_NOGIVE))
|| (IS_OBJ_STAT(container, ITEM_NOGIVE) && !IS_OBJ_STAT(obj, ITEM_NOGIVE)))
continue;
if (container && (IS_UNIQUE(ch, container) || IS_UNIQUE(ch, obj)) && obj->item_type == ITEM_CONTAINER)
continue;
if (number && (cnt + obj->count) > number)
split_obj(obj, number - cnt);
cnt += obj->count;
obj_from_char(obj);
if (container->item_type == ITEM_KEYRING)
{
act(AT_ACTION, "$n slips $p onto $P.", ch, obj, container, TO_ROOM);
act(AT_ACTION, "You slip $p onto $P.", ch, obj, container, TO_CHAR);
}
else
{
act(AT_ACTION, "$n puts $p in $P.", ch, obj, container, TO_ROOM);
act(AT_ACTION, "You put $p in $P.", ch, obj, container, TO_CHAR);
}
obj = obj_to_obj(obj, container);
check_for_trap(ch, obj, -1, NEW_TRAP_PUTOBJ);
if (char_died(ch))
return;
if (global_retcode == rOBJ_SCRAPPED)
return;
if (number && cnt >= number)
break;
}
}
check_for_trap(ch, container, TRAP_PUT, NEW_TRAP_PUT);
if (char_died(ch))
return;
if (global_retcode == rOBJ_SCRAPPED)
return;
/*
* Don't bother to save anything if nothing was dropped -Thoric
*/
if (!found)
{
if (fAll)
act(AT_PLAIN, "You are not carrying anything.", ch, NULL, NULL, TO_CHAR);
else
act(AT_PLAIN, "You are not carrying any $T.", ch, NULL, chk, TO_CHAR);
return;
}
else
{
send_to_char("Done.\n\r", ch);
}
if (save_char)
save_char_obj(ch);
/* Oops no wonder corpses were duping oopsie did I do that
* --Shaddai
*/
if (container->item_type == ITEM_CORPSE_PC)
write_corpses(NULL, container->short_descr + 14, NULL);
// Check to see if it is a kingdom chest
if (container && is_kingdom_chest(container))
save_kingdom_chests(ch);
/* Clan storeroom check */
if (xIS_SET(ch->in_room->room_flags, ROOM_CLANSTOREROOM) && container->carried_by == NULL)
{
/* if (!char_died && !save_char) save_char_obj(ch); */
for (clan = first_clan; clan; clan = clan->next)
if (clan->storeroom == ch->in_room->vnum)
save_clan_storeroom(ch, clan);
}
}
return;
}
void do_drop(CHAR_DATA * ch, char *argument)
{
char arg[MIL];
OBJ_DATA *obj;
OBJ_DATA *obj_next;
bool found;
CLAN_DATA *clan;
int number;
argument = one_argument(argument, arg);
if (is_number(arg))
{
number = atoi(arg);
if (number < 1)
{
send_to_char("That was easy...\n\r", ch);
return;
}
argument = one_argument(argument, arg);
}
else
number = 0;
if (arg[0] == '\0')
{
send_to_char("Drop what?\n\r", ch);
return;
}
if (ms_find_obj(ch))
return;
if (xIS_SET(ch->act, PLR_LITTERBUG))
{
set_char_color(AT_YELLOW, ch);
send_to_char("A godly force prevents you from dropping anything...\n\r", ch);
return;
}
if (IS_NPC(ch) && xIS_SET(ch->act, ACT_MILITARY))
{
send_to_char("You cannot do that.\n\r", ch);
return;
}
if ((wIS_SET(ch, ROOM_NODROP) || xIS_SET(ch->in_room->room_flags, ROOM_NODROP)) && ch != supermob)
{
set_char_color(AT_MAGIC, ch);
send_to_char("A magical force stops you!\n\r", ch);
set_char_color(AT_TELL, ch);
send_to_char("Someone tells you, 'No littering here!'\n\r", ch);
return;
}
if (number > 0)
{
/* 'drop NNNN coins' */
if (!str_cmp(arg, "coins") || !str_cmp(arg, "coin"))
{
if (ch->gold < number)
{
send_to_char("You haven't got that many coins.\n\r", ch);
return;
}
ch->gold -= number;
for (obj = ch->in_room->first_content; obj; obj = obj_next)
{
obj_next = obj->next_content;
if (ch->coord->x != obj->coord->x || ch->coord->y != obj->coord->y || ch->map != obj->map)
continue;
switch (obj->pIndexData->vnum)
{
case OBJ_VNUM_MONEY_ONE:
number += 1;
extract_obj(obj);
break;
case OBJ_VNUM_MONEY_SOME:
number += obj->value[0];
extract_obj(obj);
break;
}
}
act(AT_ACTION, "$n drops some gold.", ch, NULL, NULL, TO_ROOM);
obj_to_room(create_money(number), ch->in_room, ch);
send_to_char("OK.\n\r", ch);
if (IS_SET(sysdata.save_flags, SV_DROP))
save_char_obj(ch);
return;
}
}
if (number <= 1 && str_cmp(arg, "all") && str_prefix("all.", arg))
{
/* 'drop obj' */
if ((obj = get_obj_carry(ch, arg)) == NULL)
{
send_to_char("You do not have that item.\n\r", ch);
return;
}
if (!can_drop_obj(ch, obj))
{
send_to_char("You can't let go of it.\n\r", ch);
return;
}
separate_obj(obj);
act(AT_ACTION, "$n drops $p.", ch, obj, NULL, TO_ROOM);
act(AT_ACTION, "You drop $p.", ch, obj, NULL, TO_CHAR);
obj_from_char(obj);
obj = obj_to_room(obj, ch->in_room, ch);
check_for_trap(ch, obj, -1, NEW_TRAP_DROPOBJ);
if (char_died(ch))
return;
if (global_retcode == rOBJ_SCRAPPED)
return;
oprog_drop_trigger(ch, obj); /* mudprogs */
if (char_died(ch) || obj_extracted(obj))
return;
/* Clan storeroom saving */
if (xIS_SET(ch->in_room->room_flags, ROOM_CLANSTOREROOM))
{
/* if (!char_died) save_char_obj(ch); */
for (clan = first_clan; clan; clan = clan->next)
if (clan->storeroom == ch->in_room->vnum)
save_clan_storeroom(ch, clan);
}
}
else
{
int cnt = 0;
char *chk;
bool fAll;
if (!str_cmp(arg, "all"))
fAll = TRUE;
else
fAll = FALSE;
if (number > 1)
chk = arg;
else
chk = &arg[4];
/* 'drop all' or 'drop all.obj' */
if (wIS_SET(ch, ROOM_NODROPALL) || xIS_SET(ch->in_room->room_flags, ROOM_NODROPALL)
|| xIS_SET(ch->in_room->room_flags, ROOM_CLANSTOREROOM))
{
send_to_char("You can't seem to do that here...\n\r", ch);
return;
}
found = FALSE;
for (obj = ch->first_carrying; obj; obj = obj_next)
{
obj_next = obj->next_content;
if ((fAll || nifty_is_name(chk, obj->name)) && can_see_obj(ch, obj) && obj->wear_loc == WEAR_NONE && can_drop_obj(ch, obj))
{
found = TRUE;
if (HAS_PROG(obj->pIndexData, DROP_PROG) && obj->count > 1)
{
++cnt;
separate_obj(obj);
obj_from_char(obj);
if (!obj_next)
obj_next = ch->first_carrying;
}
else
{
if (number && (cnt + obj->count) > number)
split_obj(obj, number - cnt);
cnt += obj->count;
obj_from_char(obj);
}
act(AT_ACTION, "$n drops $p.", ch, obj, NULL, TO_ROOM);
act(AT_ACTION, "You drop $p.", ch, obj, NULL, TO_CHAR);
obj = obj_to_room(obj, ch->in_room, ch);
check_for_trap(ch, obj, -1, NEW_TRAP_DROPOBJ);
if (char_died(ch))
return;
if (global_retcode == rOBJ_SCRAPPED)
return;
oprog_drop_trigger(ch, obj); /* mudprogs */
if (char_died(ch))
return;
if (number && cnt >= number)
break;
}
}
if (!found)
{
if (fAll)
act(AT_PLAIN, "You are not carrying anything.", ch, NULL, NULL, TO_CHAR);
else
act(AT_PLAIN, "You are not carrying any $T.", ch, NULL, chk, TO_CHAR);
}
}
if (IS_SET(sysdata.save_flags, SV_DROP))
save_char_obj(ch); /* duping protector */
return;
}
void do_give(CHAR_DATA * ch, char *argument)
{
char arg1[MIL];
char arg2[MIL];
char buf[MIL];
CHAR_DATA *victim;
OBJ_DATA *obj;
SLAB_DATA *slab;
int cnt;
argument = one_argument(argument, arg1);
argument = one_argument(argument, arg2);
if (!str_cmp(arg2, "to") && argument[0] != '\0')
argument = one_argument(argument, arg2);
if (arg1[0] == '\0' || arg2[0] == '\0')
{
send_to_char("Give what to whom?\n\r", ch);
return;
}
if (ms_find_obj(ch))
return;
if (is_number(arg1))
{
/* 'give NNNN coins victim' */
int amount;
amount = atoi(arg1);
if (amount <= 0 || (str_cmp(arg2, "coins") && str_cmp(arg2, "coin")))
{
send_to_char("Sorry, you can't do that.\n\r", ch);
return;
}
argument = one_argument(argument, arg2);
if (!str_cmp(arg2, "to") && argument[0] != '\0')
argument = one_argument(argument, arg2);
if (arg2[0] == '\0')
{
send_to_char("Give what to whom?\n\r", ch);
return;
}
if ((victim = get_char_room_new(ch, arg2, 1)) == NULL)
{
send_to_char("They aren't here.\n\r", ch);
return;
}
if (ch->gold < amount)
{
send_to_char("Very generous of you, but you haven't got that much gold.\n\r", ch);
return;
}
ch->gold -= amount;
victim->gold += amount;
strcpy(buf, "$n gives you ");
strcat(buf, arg1);
strcat(buf, (amount > 1) ? " coins." : " coin.");
act(AT_ACTION, buf, ch, NULL, victim, TO_VICT);
act(AT_ACTION, "$n gives $N some gold.", ch, NULL, victim, TO_NOTVICT);
act(AT_ACTION, "You give $N some gold.", ch, NULL, victim, TO_CHAR);
send_to_char("OK.\n\r", ch);
mprog_bribe_trigger(victim, ch, amount);
if (IS_SET(sysdata.save_flags, SV_GIVE) && !char_died(ch))
save_char_obj(ch);
if (IS_SET(sysdata.save_flags, SV_RECEIVE) && !char_died(victim))
save_char_obj(victim);
return;
}
if ((obj = get_obj_carry(ch, arg1)) == NULL)
{
send_to_char("You do not have that item.\n\r", ch);
return;
}
if (obj->wear_loc != WEAR_NONE)
{
send_to_char("You must remove it first.\n\r", ch);
return;
}
if ((victim = get_char_room_new(ch, arg2, 1)) == NULL)
{
send_to_char("They aren't here.\n\r", ch);
return;
}
if (!can_drop_obj(ch, obj))
{
send_to_char("You can't let go of it.\n\r", ch);
return;
}
/* Prevents giving of special items (rare items) -- Xerves 3/24/99 */
if (IS_OBJ_STAT(obj, ITEM_NOGIVE) && !IS_IMMORTAL(ch) && !IS_IMMORTAL(victim))
{
send_to_char("You cannot give this item to another, it is special.\n\r", ch);
return;
}
if (IS_UNIQUE(victim, obj))
{
send_to_char("That item is unique and your target already has one.\n\r", ch);
return;
}
if (IS_NPC(victim))
{
if (xIS_SET(victim->act, ACT_CASTEMOB))
{
send_to_char("Sorry, I do not accept donations.\n\r", ch);
return;
}
if (xIS_SET(victim->act, ACT_MILITARY))
{
send_to_char("You cannot give objects to a military mobile.\n\r", ch);
return;
}
}
if (get_ch_carry_number(victim) + (get_obj_number(obj) / obj->count) > can_carry_n(victim))
{
act(AT_PLAIN, "$N has $S hands full.", ch, NULL, victim, TO_CHAR);
return;
}
if (get_ch_carry_weight(victim) + (get_obj_weight(obj) / obj->count) > can_carry_w(victim))
{
act(AT_PLAIN, "$N can't carry that much weight.", ch, NULL, victim, TO_CHAR);
return;
}
if (!can_see_obj(victim, obj))
{
act(AT_PLAIN, "$N can't see it.", ch, NULL, victim, TO_CHAR);
return;
}
if (IS_OBJ_STAT(obj, ITEM_PROTOTYPE) && !can_take_proto(victim))
{
act(AT_PLAIN, "You cannot give that to $N!", ch, NULL, victim, TO_CHAR);
return;
}
cnt = 1;
if (isdigit(argument[0]) && IS_IMMORTAL(ch) && xIS_SET(obj->extra_flags, ITEM_FORGEABLE))
{
for (slab = first_slab; slab ; slab = slab->next)
{
if (atoi(argument) == cnt)
break;
cnt++;
}
if (!slab)
{
send_to_char("There is no such ore (type forge ores)\n\r", ch);
return;
}
obj->value[6] = slab->vnum;
ch_printf(ch, "That item will now load as %s.\n\r", slab->adj);
}
separate_obj(obj);
act(AT_ACTION, "$n gives $p to $N.", ch, obj, victim, TO_NOTVICT);
act(AT_ACTION, "$n gives you $p.", ch, obj, victim, TO_VICT);
act(AT_ACTION, "You give $p to $N.", ch, obj, victim, TO_CHAR);
obj_from_char(obj);
obj = obj_to_char(obj, victim);
mprog_give_trigger(victim, ch, obj);
if (IS_SET(sysdata.save_flags, SV_GIVE) && !char_died(ch))
save_char_obj(ch);
if (IS_SET(sysdata.save_flags, SV_RECEIVE) && !char_died(victim))
save_char_obj(victim);
check_for_trap(ch, obj, -1, NEW_TRAP_GIVEOBJ);
if (char_died(ch))
return;
if (global_retcode == rOBJ_SCRAPPED)
return;
return;
}
/*
* Damage an object. -Thoric
* Affect player's AC if necessary.
* Make object into scraps if necessary.
* Send message about damaged object.
*/
obj_ret damage_obj(OBJ_DATA * obj, CHAR_DATA * attacker, int proj, int dam)
{
CHAR_DATA *ch;
OBJ_DATA *wpn;
obj_ret objcode;
int durability;
ch = obj->carried_by;
objcode = rNONE;
// Promote that carnage!!! -- Xerves
if (in_arena(ch))
{
act(AT_OBJECT, "(Xerves magically prevents $p from being damaged)", ch, obj, NULL, TO_CHAR);
return objcode;
}
if (IS_OBJ_STAT(obj, ITEM_NOBREAK))
{
if (obj->item_type != ITEM_LIGHT)
oprog_damage_trigger(ch, obj);
else if (!in_arena(ch))
oprog_damage_trigger(ch, obj);
return objcode;
}
separate_obj(obj);
if (obj->item_type != ITEM_LIGHT)
oprog_damage_trigger(ch, obj);
else if (!in_arena(ch))
oprog_damage_trigger(ch, obj);
if (obj_extracted(obj))
return global_objcode;
switch (obj->item_type)
{
default:
make_scraps(obj, attacker);
objcode = rOBJ_SCRAPPED;
break;
case ITEM_CONTAINER:
case ITEM_KEYRING:
case ITEM_QUIVER:
case ITEM_SHEATH:
if (--obj->value[3] <= 0)
{
if (!in_arena(ch))
{
make_scraps(obj, attacker);
objcode = rOBJ_SCRAPPED;
}
else
obj->value[3] = 1;
}
break;
case ITEM_LIGHT:
if (--obj->value[0] <= 0)
{
if (!in_arena(ch))
{
make_scraps(obj, attacker);
objcode = rOBJ_SCRAPPED;
}
else
obj->value[0] = 1;
}
break;
case ITEM_WEAPON:
if (attacker && !in_arena(ch))
{
durability = UMAX(1, obj->value[10]);
dam = dam * 2 / durability;
if (proj == 1) //Less wear on the actual bows
dam /= 3;
if (dam < 1)
dam = 1;
obj->value[0] -= dam;
if (obj->value[0] <= 0)
{
make_scraps(obj, attacker);
objcode = rOBJ_SCRAPPED;
}
else if (obj->value[0] < 200)
{
act(AT_RED, "$p is almost broken, you need to fix it immediately!", ch, obj, NULL, TO_CHAR);
}
else if (obj->value[0] < 400)
{
act(AT_WHITE, "$p is damaged, you need to fix it immediately!", ch, obj, NULL, TO_CHAR);
}
break;
}
case ITEM_ARMOR:
durability = UMAX(1, obj->value[4]);
if (attacker && !in_arena(ch))
{
if (IS_SET(obj->wear_flags, ITEM_WEAR_SHIELD))
{
dam = number_range(dam*5/10, dam*7/10);
if (proj == 1)
dam /= 3;
if (dam < 1)
dam = 1;
obj->value[0] -= dam;
if (obj->value[0] <= 0)
{
make_scraps(obj, attacker);
objcode = rOBJ_SCRAPPED;
}
break;
}
if (proj == 0)
wpn = get_eq_char(attacker, WEAR_WIELD);
else
wpn = get_eq_char(attacker, WEAR_MISSILE_WIELD);
if (proj == 1) //Stab
{
dam = dam * 6 / durability/ 10;
obj->value[3] -= URANGE(1, dam, 40);
}
else
{
if (attacker->grip == GRIP_BASH)
{
dam = dam * 6 / durability;
obj->value[3] -= URANGE(2, dam, 60);
}
if (attacker->grip == GRIP_STAB)
{
dam = dam * 2 / durability;
obj->value[3] -= URANGE(1, dam, 30);
}
if (attacker->grip == GRIP_SLASH)
{
dam = dam * 4 / durability;
obj->value[3] -= URANGE(1, dam, 40);
}
}
}
else
{
dam = dam / (1+(durability/5));
obj->value[3] -= UMAX(1, dam);
}
if (obj->value[3] <= 0)
{
make_scraps(obj, attacker);
objcode = rOBJ_SCRAPPED;
}
else if (obj->value[3] < 200 && !IS_SET(obj->wear_flags, ITEM_WEAR_SHIELD))
{
act(AT_RED, "$p is almost broken, you need to fix it immediately!", ch, obj, NULL, TO_CHAR);
}
else if (obj->value[3] < 400 && !IS_SET(obj->wear_flags, ITEM_WEAR_SHIELD))
{
act(AT_WHITE, "$p is damaged, you need to fix it immediately!", ch, obj, NULL, TO_CHAR);
}
else if (obj->value[1] && obj->value[0] * 1000 / obj->value[1] < 200 && IS_SET(obj->wear_flags, ITEM_WEAR_SHIELD))
{
act(AT_RED, "$p is almost broken, you need to fix it immediately!", ch, obj, NULL, TO_CHAR);
}
else if (obj->value[1] && obj->value[0] * 1000 / obj->value[1] < 400 && IS_SET(obj->wear_flags, ITEM_WEAR_SHIELD))
{
act(AT_WHITE, "$p is damaged, you need to fix it immediately!", ch, obj, NULL, TO_CHAR);
}
break;
}
return objcode;
}
/*
* Remove an object.
* Added support to check only and not remove, it is fReplace 2, 0 and 1 are FALSE/TRUE
*/
bool remove_obj(CHAR_DATA * ch, int iWear, sh_int fReplace)
{
OBJ_DATA *obj, *tmpobj;
obj = get_eq_char(ch, iWear);
if (!obj)
{
return TRUE;
}
if (!fReplace && get_ch_carry_number(ch) + get_obj_number(obj) > can_carry_n(ch))
{
act(AT_PLAIN, "$d: you can't carry that many items.", ch, NULL, obj->name, TO_CHAR);
return FALSE;
}
if (!fReplace)
return FALSE;
if (IS_OBJ_STAT(obj, ITEM_NOREMOVE))
{
act(AT_PLAIN, "You can't remove $p.", ch, obj, NULL, TO_CHAR);
return FALSE;
}
if (ch->fighting)
{
if (IS_SET(obj->wear_flags, ITEM_LODGE_RIB) || IS_SET(obj->wear_flags, ITEM_LODGE_ARM) || IS_SET(obj->wear_flags, ITEM_LODGE_LEG))
{
if (!IS_NPC(ch))
ch->fight_timer = 1;
}
if (IS_SET(obj->wear_flags, ITEM_WIELD) || IS_SET(obj->wear_flags, ITEM_DUAL_WIELD) || IS_SET(obj->wear_flags, ITEM_MISSILE_WIELD)
|| IS_SET(obj->wear_flags, ITEM_WEAR_SHIELD))
{
if (!IS_NPC(ch))
ch->fight_timer = 2;
}
if (IS_SET(obj->wear_flags, ITEM_WEAR_FINGER) || IS_SET(obj->wear_flags, ITEM_WEAR_ABOUT_NECK) || IS_SET(obj->wear_flags, ITEM_WEAR_BACK)
|| IS_SET(obj->wear_flags, ITEM_WEAR_WAIST))
{
if (!IS_NPC(ch))
ch->fight_timer = 2;
}
if (IS_SET(obj->wear_flags, ITEM_WEAR_HEAD) || IS_SET(obj->wear_flags, ITEM_WEAR_NECK) || IS_SET(obj->wear_flags, ITEM_WEAR_ARMS))
{
if (!IS_NPC(ch))
ch->fight_timer = 3;
}
if (IS_SET(obj->wear_flags, ITEM_WEAR_LEGS))
{
if (!IS_NPC(ch))
ch->fight_timer = 4;
}
if (IS_SET(obj->wear_flags, ITEM_WEAR_BODY))
{
if (!IS_NPC(ch))
ch->fight_timer = 6;
}
}
if (fReplace == 2)
return TRUE;
else
{
if (obj == get_eq_char(ch, WEAR_WIELD) && (tmpobj = get_eq_char(ch, WEAR_DUAL_WIELD)) != NULL)
tmpobj->wear_loc = WEAR_WIELD;
unequip_char(ch, obj);
act(AT_ACTION, "$n stops using $p.", ch, obj, NULL, TO_ROOM);
act(AT_ACTION, "You stop using $p.", ch, obj, NULL, TO_CHAR);
oprog_remove_trigger(ch, obj);
return TRUE;
}
}
/*
* See if char could be capable of dual-wielding -Thoric
*/
bool could_dual(CHAR_DATA * ch)
{
if (IS_NPC(ch) || (ch->pcdata->learned[gsn_dual_wield] && ch->pcdata->ranking[gsn_dual_wield]))
return TRUE;
return FALSE;
}
/*
* See if char can dual wield at this time -Thoric
*/
bool can_dual(CHAR_DATA * ch)
{
if (!could_dual(ch))
return FALSE;
if (get_eq_char(ch, WEAR_DUAL_WIELD))
{
send_to_char("You are already wielding two weapons!\n\r", ch);
return FALSE;
}
if (get_eq_char(ch, WEAR_SHIELD))
{
send_to_char("You cannot dual wield while holding a shield!\n\r", ch);
return FALSE;
}
if (ch->con_rarm == -1 || ch->con_larm == -1)
{
send_to_char("You cannot dual wield without the use of an arm\n\r", ch);
return FALSE;
}
return TRUE;
}
/*
* Check to see if there is room to wear another object on this location
* (Layered clothing support)
*/
bool can_layer(CHAR_DATA * ch, OBJ_DATA * obj, sh_int wear_loc)
{
OBJ_DATA *otmp;
sh_int bitlayers = 0;
sh_int objlayers = obj->pIndexData->layers;
for (otmp = ch->first_carrying; otmp; otmp = otmp->next_content)
{
if (otmp->wear_loc == wear_loc)
{
if (!otmp->pIndexData->layers)
return FALSE;
else
bitlayers |= otmp->pIndexData->layers;
}
}
if ((bitlayers && !objlayers) || bitlayers > objlayers)
return FALSE;
if (!bitlayers || ((bitlayers & ~objlayers) == bitlayers))
return TRUE;
return FALSE;
}
/*
* Wear one object.
* Optional replacement of existing objects.
* Big repetitive code, ick.
*
* Restructured a bit to allow for specifying body location -Thoric
* & Added support for layering on certain body locations
*/
void wear_obj(CHAR_DATA * ch, OBJ_DATA * obj, bool fReplace, sh_int wear_bit)
{
char buf[MSL];
char *wbuf;
char name[MSL];
OBJ_DATA *tmpobj = NULL;
sh_int bit, tmp;
int race = -1;
separate_obj(obj);
if (get_trust(ch) < obj->level && !IS_OBJ_STAT(obj, ITEM_LODGED))
{
sprintf(buf, "You must be level %d to use this object.\n\r", obj->level);
send_to_char(buf, ch);
act(AT_ACTION, "$n tries to use $p, but is too inexperienced.", ch, obj, NULL, TO_ROOM);
return;
}
if (IS_OBJ_STAT(obj, ITEM_KINGDOMEQ) && !IS_OBJ_STAT(obj, ITEM_LODGED))
{
if (!IS_NPC(ch) || (IS_NPC(ch) && !xIS_SET(ch->act, ACT_MILITARY)))
{
send_to_char("Cannot equip this item, it is kingdom eq\n\r", ch);
return;
}
}
wbuf = obj->name;
wbuf = one_argument(wbuf, name);
wbuf = one_argument(wbuf, name);
name[0] = UPPER(name[0]);
if (!str_cmp(name, "Fairy"))
race = 5;
else if (!str_cmp(name, "Hobbit"))
race = 4;
else if (!str_cmp(name, "Ogre"))
race = 3;
else if (!str_cmp(name, "Dwarven"))
race = 2;
else if (!str_cmp(name, "Elven"))
race = 1;
else if (!str_cmp(name, "Human"))
race = 0;
else
{
if (xIS_SET(obj->extra_flags, ITEM_FORGEABLE))
{
bug("wear_obj: Invalid Race Name %s, on player %s", name, ch->name);
send_to_char("Error: Invalid Race Name, tell an immortal.\n\r", ch);
return;
}
}
if (xIS_SET(obj->extra_flags, ITEM_FORGEABLE) && ch->race != race && obj->item_type == ITEM_ARMOR)
{
ch_printf(ch, "That item is %s in nature and you are not that race.\n\r", name);
return;
}
if (race > -1 && ch->race != race && obj->item_type == ITEM_ARMOR)
{
ch_printf(ch, "That item is %s in nature and you are not that race.\n\r", name);
return;
}
if (obj->item_type == ITEM_ARMOR && obj->value[5] >= ASIZE_HEAVY && ch->race == RACE_HOBBIT)
{
ch_printf(ch, "Hobbits cannot wear heavy armor.\n\r");
return;
}
if (obj->sworthrestrict > player_stat_worth(ch))
{
send_to_char("You are not powerful enough to use this.\n\r", ch);
return;
}
if (ch->fighting)
{
if (IS_SET(obj->wear_flags, ITEM_LODGE_RIB) || IS_SET(obj->wear_flags, ITEM_LODGE_ARM) || IS_SET(obj->wear_flags, ITEM_LODGE_LEG))
{
if (!IS_NPC(ch))
ch->fight_timer = 1;
}
if (IS_SET(obj->wear_flags, ITEM_WIELD) || IS_SET(obj->wear_flags, ITEM_DUAL_WIELD) || IS_SET(obj->wear_flags, ITEM_MISSILE_WIELD)
|| IS_SET(obj->wear_flags, ITEM_WEAR_SHIELD))
{
if (!IS_NPC(ch))
ch->fight_timer = 2;
}
if (IS_SET(obj->wear_flags, ITEM_WEAR_FINGER) || IS_SET(obj->wear_flags, ITEM_WEAR_ABOUT_NECK) || IS_SET(obj->wear_flags, ITEM_WEAR_BACK)
|| IS_SET(obj->wear_flags, ITEM_WEAR_WAIST))
{
if (!IS_NPC(ch))
ch->fight_timer = 2;
}
if (IS_SET(obj->wear_flags, ITEM_WEAR_HEAD) || IS_SET(obj->wear_flags, ITEM_WEAR_NECK) || IS_SET(obj->wear_flags, ITEM_WEAR_ARMS))
{
if (!IS_NPC(ch))
ch->fight_timer = 3;
}
if (IS_SET(obj->wear_flags, ITEM_WEAR_LEGS))
{
if (!IS_NPC(ch))
ch->fight_timer = 4;
}
if (IS_SET(obj->wear_flags, ITEM_WEAR_BODY))
{
if (!IS_NPC(ch))
ch->fight_timer = 6;
}
}
if (wear_bit > -1)
{
bit = wear_bit;
if (!CAN_WEAR(obj, 1 << bit))
{
if (fReplace)
{
switch (1 << bit)
{
case ITEM_WIELD:
case ITEM_MISSILE_WIELD:
send_to_char("You cannot wield that.\n\r", ch);
break;
case ITEM_WEAR_NOCKED:
send_to_char("You cannot nock that.\n\r", ch);
break;
default:
sprintf(buf, "You cannot wear that on your %s.\n\r", w_flags[bit]);
send_to_char(buf, ch);
}
}
return;
}
}
else
{
for (bit = -1, tmp = 1; tmp < 31; tmp++)
{
if (CAN_WEAR(obj, 1 << tmp))
{
bit = tmp;
break;
}
}
}
/* currently cannot have a light in non-light position */
if (obj->item_type == ITEM_LIGHT)
{
if (!remove_obj(ch, WEAR_LIGHT, fReplace))
return;
if (!oprog_use_trigger(ch, obj, NULL, NULL, NULL))
{
act(AT_ACTION, "$n holds $p as a light.", ch, obj, NULL, TO_ROOM);
act(AT_ACTION, "You hold $p as your light.", ch, obj, NULL, TO_CHAR);
}
equip_char(ch, obj, WEAR_LIGHT);
oprog_wear_trigger(ch, obj);
return;
}
if (bit == -1)
{
if (fReplace)
send_to_char("You can't wear, wield, or hold that.\n\r", ch);
return;
}
switch (1 << bit)
{
default:
bug("wear_obj: uknown/unused item_wear bit %d", bit);
if (fReplace)
send_to_char("You can't wear, wield, or hold that.\n\r", ch);
return;
case ITEM_WEAR_NOCKED:
if (!remove_obj(ch, WEAR_NOCKED, fReplace))
return;
if (!oprog_use_trigger(ch, obj, NULL, NULL, NULL))
{
act(AT_ACTION, "$n nocks $p upon $s weapon.", ch, obj, NULL, TO_ROOM);
act(AT_ACTION, "You nock $p upon your weapon.", ch, obj, NULL, TO_CHAR);
}
equip_char(ch, obj, WEAR_NOCKED);
oprog_wear_trigger(ch, obj);
return;
case ITEM_WEAR_FINGER:
if (get_eq_char(ch, WEAR_FINGER_L) != NULL
&& get_eq_char(ch, WEAR_FINGER_R) != NULL && !remove_obj(ch, WEAR_FINGER_L, fReplace) && !remove_obj(ch, WEAR_FINGER_R, fReplace))
return;
if (!get_eq_char(ch, WEAR_FINGER_L))
{
if (!oprog_use_trigger(ch, obj, NULL, NULL, NULL))
{
act(AT_ACTION, "$n slides $p on $s left ring finger.", ch, obj, NULL, TO_ROOM);
act(AT_ACTION, "You slide $p on your left ring finger.", ch, obj, NULL, TO_CHAR);
}
equip_char(ch, obj, WEAR_FINGER_L);
oprog_wear_trigger(ch, obj);
return;
}
if (!get_eq_char(ch, WEAR_FINGER_R))
{
if (!oprog_use_trigger(ch, obj, NULL, NULL, NULL))
{
act(AT_ACTION, "$n slides $p on $s right ring finger.", ch, obj, NULL, TO_ROOM);
act(AT_ACTION, "You slide $p on your right ring finger.", ch, obj, NULL, TO_CHAR);
}
equip_char(ch, obj, WEAR_FINGER_R);
oprog_wear_trigger(ch, obj);
return;
}
bug("Wear_obj: no free finger.", 0);
send_to_char("You already wear two finger items.\n\r", ch);
return;
case ITEM_WEAR_ABOUT_NECK:
if (!remove_obj(ch, WEAR_ABOUT_NECK, fReplace))
return;
if (!oprog_use_trigger(ch, obj, NULL, NULL, NULL))
{
act(AT_ACTION, "$n clamps $p around $s neck.", ch, obj, NULL, TO_ROOM);
act(AT_ACTION, "You clamp $p around your neck.", ch, obj, NULL, TO_CHAR);
}
equip_char(ch, obj, WEAR_ABOUT_NECK);
oprog_wear_trigger(ch, obj);
return;
case ITEM_WEAR_NECK:
if (!remove_obj(ch, WEAR_NECK, fReplace))
return;
if (!oprog_use_trigger(ch, obj, NULL, NULL, NULL))
{
act(AT_ACTION, "$n fastens $p around $s neck.", ch, obj, NULL, TO_ROOM);
act(AT_ACTION, "You fasten $p around your neck.", ch, obj, NULL, TO_CHAR);
}
equip_char(ch, obj, WEAR_NECK);
oprog_wear_trigger(ch, obj);
return;
case ITEM_WEAR_BACK:
if (!can_layer(ch, obj, WEAR_BACK))
{
send_to_char("It won't fit overtop of what you're already wearing.\n\r", ch);
return;
}
if (!oprog_use_trigger(ch, obj, NULL, NULL, NULL))
{
act(AT_ACTION, "$n slings $p upon $s back.", ch, obj, NULL, TO_ROOM);
act(AT_ACTION, "You sling $p upon your back.", ch, obj, NULL, TO_CHAR);
}
equip_char(ch, obj, WEAR_BACK);
oprog_wear_trigger(ch, obj);
return;
case ITEM_WEAR_ARMS:
if (get_eq_char(ch, WEAR_ARM_L) != NULL
&& get_eq_char(ch, WEAR_ARM_R) != NULL && !remove_obj(ch, WEAR_ARM_L, fReplace) && !remove_obj(ch, WEAR_ARM_R, fReplace))
return;
if (!get_eq_char(ch, WEAR_ARM_L) && ch->con_larm != -1)
{
if (!oprog_use_trigger(ch, obj, NULL, NULL, NULL))
{
act(AT_ACTION, "$n slides $p around $s left arm.", ch, obj, NULL, TO_ROOM);
act(AT_ACTION, "You slide $p around your left arm.", ch, obj, NULL, TO_CHAR);
}
equip_char(ch, obj, WEAR_ARM_L);
oprog_wear_trigger(ch, obj);
return;
}
if (!get_eq_char(ch, WEAR_ARM_R) && ch->con_rarm != -1)
{
if (!oprog_use_trigger(ch, obj, NULL, NULL, NULL))
{
act(AT_ACTION, "$n slides $p around $s right arm.", ch, obj, NULL, TO_ROOM);
act(AT_ACTION, "You slide $p around your right arm.", ch, obj, NULL, TO_CHAR);
}
equip_char(ch, obj, WEAR_ARM_R);
oprog_wear_trigger(ch, obj);
return;
}
if ((ch->con_rarm == -1 || ch->con_larm == -1) && (!get_eq_char(ch, WEAR_ARM_R) || !get_eq_char(ch, WEAR_ARM_L)))
{
send_to_char("You cannot wear that around your arm because you arm is broken off.\n\r", ch);
return;
}
bug("Wear_obj: no free arm.", 0);
send_to_char("You already wear two arm items.\n\r", ch);
return;
case ITEM_WEAR_LEGS:
if (get_eq_char(ch, WEAR_LEG_L) != NULL
&& get_eq_char(ch, WEAR_LEG_R) != NULL && !remove_obj(ch, WEAR_LEG_L, fReplace) && !remove_obj(ch, WEAR_LEG_R, fReplace))
return;
if (!get_eq_char(ch, WEAR_LEG_L) && ch->con_lleg != -1)
{
if (ch->con_lleg == -1)
{
send_to_char("You cannot wear that around your leg because you leg is broken off.\n\r", ch);
return;
}
if (!oprog_use_trigger(ch, obj, NULL, NULL, NULL))
{
act(AT_ACTION, "$n slides $p around $s left leg.", ch, obj, NULL, TO_ROOM);
act(AT_ACTION, "You slide $p around your left leg.", ch, obj, NULL, TO_CHAR);
}
equip_char(ch, obj, WEAR_LEG_L);
oprog_wear_trigger(ch, obj);
return;
}
if (!get_eq_char(ch, WEAR_LEG_R) && ch->con_rleg != -1)
{
if (ch->con_rleg == -1)
{
send_to_char("You cannot wear that around your leg because you leg is broken off.\n\r", ch);
return;
}
if (!oprog_use_trigger(ch, obj, NULL, NULL, NULL))
{
act(AT_ACTION, "$n slides $p around $s right leg.", ch, obj, NULL, TO_ROOM);
act(AT_ACTION, "You slide $p around your right leg.", ch, obj, NULL, TO_CHAR);
}
equip_char(ch, obj, WEAR_LEG_R);
oprog_wear_trigger(ch, obj);
return;
}
if ((ch->con_rleg == -1 || ch->con_lleg == -1) && (!get_eq_char(ch, WEAR_LEG_R) || !get_eq_char(ch, WEAR_LEG_L)))
{
send_to_char("You cannot wear that around your arm because you arm is broken off.\n\r", ch);
return;
}
bug("Wear_obj: no free leg.", 0);
send_to_char("You already wear two leg items.\n\r", ch);
return;
case ITEM_WEAR_BODY:
if (!remove_obj(ch, WEAR_BODY, fReplace))
return;
//I hate layering, bye -- Xerves
if (!oprog_use_trigger(ch, obj, NULL, NULL, NULL))
{
act(AT_ACTION, "$n fits $p on $s body.", ch, obj, NULL, TO_ROOM);
act(AT_ACTION, "You fit $p on your body.", ch, obj, NULL, TO_CHAR);
}
equip_char(ch, obj, WEAR_BODY);
oprog_wear_trigger(ch, obj);
return;
case ITEM_WEAR_HEAD:
if (!remove_obj(ch, WEAR_HEAD, fReplace))
return;
if (!oprog_use_trigger(ch, obj, NULL, NULL, NULL))
{
act(AT_ACTION, "$n dons $p upon $s head.", ch, obj, NULL, TO_ROOM);
act(AT_ACTION, "You don $p upon your head.", ch, obj, NULL, TO_CHAR);
}
equip_char(ch, obj, WEAR_HEAD);
oprog_wear_trigger(ch, obj);
return;
case ITEM_LODGE_RIB:
if (!remove_obj(ch, WEAR_LODGE_RIB, fReplace))
return;
if (!oprog_use_trigger(ch, obj, NULL, NULL, NULL))
{
act(AT_ACTION, "$p lodges itself in $n's ribs.", ch, obj, NULL, TO_ROOM);
sprintf(buf, "$p &G&W[&RLODGES&G&W]%s itself in your ribs.", char_color_str(AT_ACTION, ch));
act(AT_ACTION, buf, ch, obj, NULL, TO_CHAR);
}
equip_char(ch, obj, WEAR_LODGE_RIB);
oprog_wear_trigger(ch, obj);
return;
case ITEM_LODGE_ARM:
if (!remove_obj(ch, WEAR_LODGE_ARM, fReplace))
return;
if (!oprog_use_trigger(ch, obj, NULL, NULL, NULL))
{
act(AT_ACTION, "$p lodges itself in $n's ribs.", ch, obj, NULL, TO_ROOM);
sprintf(buf, "$p &G&W[&RLODGES&G&W]%s itself in your arm.", char_color_str(AT_ACTION, ch));
act(AT_ACTION, buf, ch, obj, NULL, TO_CHAR);
}
equip_char(ch, obj, WEAR_LODGE_ARM);
oprog_wear_trigger(ch, obj);
return;
case ITEM_LODGE_LEG:
if (!remove_obj(ch, WEAR_LODGE_LEG, fReplace))
return;
if (!oprog_use_trigger(ch, obj, NULL, NULL, NULL))
{
act(AT_ACTION, "$p lodges itself in $n's ribs.", ch, obj, NULL, TO_ROOM);
sprintf(buf, "$p &G&W[&RLODGES&G&W]%s itself in your leg.", char_color_str(AT_ACTION, ch));
act(AT_ACTION, buf, ch, obj, NULL, TO_CHAR);
}
equip_char(ch, obj, WEAR_LODGE_LEG);
oprog_wear_trigger(ch, obj);
return;
//Only layerable slot for now because of sheaths
case ITEM_WEAR_WAIST:
/*
if ( !remove_obj( ch, WEAR_WAIST, fReplace ) )
return;
*/
if (!can_layer(ch, obj, WEAR_WAIST))
{
send_to_char("It won't fit overtop of what you're already wearing.\n\r", ch);
return;
}
if (!oprog_use_trigger(ch, obj, NULL, NULL, NULL))
{
act(AT_ACTION, "$n buckles $p about $s waist.", ch, obj, NULL, TO_ROOM);
act(AT_ACTION, "You buckle $p about your waist.", ch, obj, NULL, TO_CHAR);
}
equip_char(ch, obj, WEAR_WAIST);
oprog_wear_trigger(ch, obj);
return;
case ITEM_WEAR_SHIELD:
if (get_eq_char(ch, WEAR_DUAL_WIELD) || (get_eq_char(ch, WEAR_WIELD) && get_eq_char(ch, WEAR_MISSILE_WIELD)))
{
send_to_char("You can't use a shield AND two weapons!\n\r", ch);
return;
}
if (get_eq_char(ch, WEAR_WIELD) && (ch->con_rarm == -1 || ch->con_larm == -1))
{
send_to_char("You don't have an available hand seeing how it is broken off.\n\r", ch);
return;
}
if ((tmpobj = (get_eq_char(ch, WEAR_MISSILE_WIELD))) != NULL)
{
if (IS_OBJ_STAT(tmpobj, ITEM_TWOHANDED))
{
if (IS_NPC(ch) || ch->pcdata->learned[gsn_inhuman_strength] <= 0)
{
send_to_char("The weapon you are wielding now is two-handed.\n\r", ch);
return;
}
}
}
if ((tmpobj = (get_eq_char(ch, WEAR_WIELD))) != NULL)
{
if (IS_OBJ_STAT(tmpobj, ITEM_TWOHANDED))
{
if (IS_NPC(ch) || ch->pcdata->learned[gsn_inhuman_strength] <= 0)
{
send_to_char("The weapon you are wielding now is two-handed.\n\r", ch);
return;
}
}
}
if (IS_OBJ_STAT(obj, ITEM_TWOHANDED))
{
if (get_eq_char(ch, WEAR_WIELD) || get_eq_char(ch, WEAR_DUAL_WIELD) || get_eq_char(ch, WEAR_MISSILE_WIELD))
{
send_to_char("That shield is two-handed. You cannot wield a weapon with it.\n\r", ch);
return;
}
}
if (ch->con_rarm == -1 && ch->con_larm == -1)
{
send_to_char("You have no available hands to hold a shield because you have no hands.\n\r", ch);
return;
}
if (!remove_obj(ch, WEAR_SHIELD, fReplace))
return;
if (!oprog_use_trigger(ch, obj, NULL, NULL, NULL))
{
act(AT_ACTION, "$n uses $p as a shield.", ch, obj, NULL, TO_ROOM);
act(AT_ACTION, "You use $p as a shield.", ch, obj, NULL, TO_CHAR);
}
equip_char(ch, obj, WEAR_SHIELD);
oprog_wear_trigger(ch, obj);
return;
case ITEM_MISSILE_WIELD:
case ITEM_WIELD:
if (!could_dual(ch))
{
if (!remove_obj(ch, WEAR_MISSILE_WIELD, fReplace))
return;
if (!remove_obj(ch, WEAR_WIELD, fReplace))
return;
if ((tmpobj = get_eq_char(ch, WEAR_SHIELD)) != NULL && IS_OBJ_STAT(tmpobj, ITEM_TWOHANDED))
{
send_to_char("The Shield you are holding requires two hands.\n\r", ch);
return;
}
if (IS_OBJ_STAT(obj, ITEM_TWOHANDED) && tmpobj)
{
if (IS_NPC(ch) || ch->pcdata->learned[gsn_inhuman_strength] <= 0)
{
send_to_char("If you want to use that two-handed weapon, remove your shield first.\n\r", ch);
return;
}
}
tmpobj = NULL;
if ((tmpobj = get_eq_char(ch, WEAR_SHIELD)) != NULL && IS_OBJ_STAT(tmpobj, ITEM_TWOHANDED))
{
send_to_char("The Shield you are holding requires two hands.\n\r", ch);
return;
}
if (get_eq_char(ch, WEAR_SHIELD) && (ch->con_rarm == -1 || ch->con_larm == -1))
{
send_to_char("Hard to wield something when one hand is chopped off.\n\r", ch);
return;
}
if (ch->con_rarm == -1 && ch->con_larm == -1)
{
send_to_char("Hard to wield something when you have NO hands to wield it with.\n\r", ch);
return;
}
tmpobj = NULL;
}
else
{
if ((tmpobj = get_eq_char(ch, WEAR_SHIELD)) != NULL && IS_OBJ_STAT(tmpobj, ITEM_TWOHANDED))
{
send_to_char("The Shield you are holding requires two hands.\n\r", ch);
return;
}
if (IS_OBJ_STAT(obj, ITEM_TWOHANDED) && tmpobj)
{
if (IS_NPC(ch) || ch->pcdata->learned[gsn_inhuman_strength] <= 0)
{
send_to_char("If you want to use that two-handed weapon, remove your shield first.\n\r", ch);
return;
}
}
tmpobj = NULL;
if ((tmpobj = get_eq_char(ch, WEAR_WIELD)) != NULL && (get_eq_char(ch, WEAR_MISSILE_WIELD) || get_eq_char(ch, WEAR_DUAL_WIELD)))
{
send_to_char("You're already wielding two weapons.\n\r", ch);
return;
}
if (IS_OBJ_STAT(obj, ITEM_TWOHANDED) && get_eq_char(ch, WEAR_MISSILE_WIELD))
{
send_to_char("That weapon is two-handed and you are weilding a missile weapon.\n\r", ch);
return;
}
if (get_eq_char(ch, WEAR_MISSILE_WIELD))
{
if ((tmpobj = get_eq_char(ch, WEAR_MISSILE_WIELD)) != NULL && IS_OBJ_STAT(tmpobj, ITEM_TWOHANDED))
{
send_to_char("You are wielding a two-handed missile weapon!\n\r", ch);
return;
}
}
if (get_eq_char(ch, WEAR_WIELD))
{
if ((tmpobj = get_eq_char(ch, WEAR_WIELD)) != NULL && get_eq_char(ch, WEAR_SHIELD))
{
send_to_char("You must first remove that shield you are holding.\n\r", ch);
return;
}
}
if (get_eq_char(ch, WEAR_WIELD) && (ch->con_rarm == -1 || ch->con_larm == -1))
{
send_to_char("You do not have availability of one hand because it is chopped off.\n\r", ch);
return;
}
if (!tmpobj && ch->con_rarm == -1 && ch->con_larm == -1)
{
send_to_char("Hard to wield something when you have no hands.\n\r", ch);
return;
}
}
if (tmpobj)
{
if (can_dual(ch))
{
if (get_obj_weight(obj) + get_obj_weight(tmpobj) > str_app[get_curr_str(ch)].wield)
{
send_to_char("&RWielding such heavy weapons is going to slow you down!!&w.\n\r", ch);
}
/* New Weapon Handling code -- Xerves 6/1/99 */
if (!IS_NPC(ch))
{
if (obj->value[3] < race_table[ch->race]->weaponmin)
{
act(AT_ACTION, "You try to wield $p, but you cannot grasp it with your hands.", ch, obj, NULL, TO_CHAR);
return;
}
if (obj->value[3] > race_table[ch->race]->weaponmax)
{
act(AT_ACTION, "You try to wield $p, but you cannot even lift it off the ground.", ch, obj, NULL, TO_CHAR);
return;
}
}
if (IS_OBJ_STAT(obj, ITEM_TWOHANDED))
{
send_to_char("That weapon requires two hands to wield.\n\r", ch);
return;
}
if (IS_OBJ_STAT(tmpobj, ITEM_TWOHANDED))
{
send_to_char("The weapon you are wielding now is two-handed.\n\r", ch);
return;
}
if (!oprog_use_trigger(ch, obj, NULL, NULL, NULL))
{
act(AT_ACTION, "$n dual-wields $p.", ch, obj, NULL, TO_ROOM);
act(AT_ACTION, "You dual-wield $p.", ch, obj, NULL, TO_CHAR);
}
if (1 << bit == ITEM_MISSILE_WIELD)
equip_char(ch, obj, WEAR_MISSILE_WIELD);
else
equip_char(ch, obj, WEAR_DUAL_WIELD);
oprog_wear_trigger(ch, obj);
}
return;
}
if (get_obj_weight(obj) > str_app[get_curr_str(ch)].wield)
{
send_to_char("&RWielding such a heavy weapon is going to slow you down!!&w.\n\r", ch);
}
/* New weapon handling code -- Xerves 6/1/90 */
if (!IS_NPC(ch))
{
if (obj->value[3] < race_table[ch->race]->weaponmin)
{
act(AT_ACTION, "You try to wield $p, but you cannot grasp it with your hands.", ch, obj, NULL, TO_CHAR);
return;
}
if (obj->value[3] > race_table[ch->race]->weaponmax)
{
act(AT_ACTION, "You try to wield $p, but you cannot even lift it off the ground.", ch, obj, NULL, TO_CHAR);
return;
}
}
if (!IS_NPC(ch))
{
if ((ch->pcdata->righthanded == 0 && ch->con_larm == -1) || (ch->pcdata->righthanded == 1 && ch->con_rarm == -1))
{
if (!oprog_use_trigger(ch, obj, NULL, NULL, NULL))
{
act(AT_ACTION, "$n wields $p with $s off-hand.", ch, obj, NULL, TO_ROOM);
act(AT_ACTION, "You wield $p with your off-hand.", ch, obj, NULL, TO_CHAR);
}
}
else
{
if (!oprog_use_trigger(ch, obj, NULL, NULL, NULL))
{
act(AT_ACTION, "$n wields $p.", ch, obj, NULL, TO_ROOM);
act(AT_ACTION, "You wield $p.", ch, obj, NULL, TO_CHAR);
}
}
}
else
{
if (ch->con_rarm == -1)
{
if (!oprog_use_trigger(ch, obj, NULL, NULL, NULL))
{
act(AT_ACTION, "$n wields $p with $s off-hand.", ch, obj, NULL, TO_ROOM);
act(AT_ACTION, "You wield $p with your off-hand.", ch, obj, NULL, TO_CHAR);
}
}
else
{
if (!oprog_use_trigger(ch, obj, NULL, NULL, NULL))
{
act(AT_ACTION, "$n wields $p.", ch, obj, NULL, TO_ROOM);
act(AT_ACTION, "You wield $p.", ch, obj, NULL, TO_CHAR);
}
}
}
if (1 << bit == ITEM_MISSILE_WIELD)
equip_char(ch, obj, WEAR_MISSILE_WIELD);
else
equip_char(ch, obj, WEAR_WIELD);
oprog_wear_trigger(ch, obj);
if (ch->fighting)
{
SET_BIT(ch->fight_state, FSTATE_WIELD);
if (ch->fight_timer <= 2)
ch->fight_timer = 2;
}
return;
}
}
// Used to unequip a weapon and put it back in a sheath.
// You sheath going from DUAL to Primary
void do_sheath(CHAR_DATA * ch, char *argument)
{
OBJ_DATA *sheath;
OBJ_DATA *weapon = NULL;
char buf[MSL];
int found = 0;
int rev = 0;
int count = 0;
if (!str_cmp(argument, "go reverse"))
rev = 1;
if (!str_cmp(argument, "go reverse again"))
rev = 2;
if (ms_find_obj(ch))
return;
if (get_eq_char(ch, WEAR_DUAL_WIELD))
{
weapon = get_eq_char(ch, WEAR_DUAL_WIELD);
}
else
{
if (get_eq_char(ch, WEAR_WIELD))
{
weapon = get_eq_char(ch, WEAR_WIELD);
}
}
if (!weapon)
{
send_to_char("You need to be wielding a weapon to sheath it.\n\r", ch);
return;
}
if (IS_OBJ_STAT(weapon, ITEM_NOREMOVE))
{
act(AT_PLAIN, "You can't remove $p.", ch, weapon, NULL, TO_CHAR);
return;
}
/* Total of 3 possible sheath locations, will loop through three times to find
a good one if it has to */
for (sheath = ch->first_carrying; sheath; sheath = sheath->next_content)
{
if (sheath->item_type == ITEM_SHEATH && sheath->wear_loc == WEAR_WAIST)
{
found = 1;
if (rev != count)
{
count++;
continue;
}
if (sheath->value[1] == weapon->value[3] && get_obj_weight(weapon) <= sheath->value[0] && !sheath->first_content)
{
if (sheath->value[2] != 0 && sheath->value[2] == weapon->pIndexData->vnum)
break;
else
{
if (sheath->value[2] == 0)
break;
else
continue;
}
break;
}
}
}
if (found == 0)
{
send_to_char("You need to be wearing a sheath before you can sheath a weapon.\n\r", ch);
return;
}
if (!sheath)
{
send_to_char("You have an improper sheath or it is full, help sheath for more info.\n\r", ch);
return;
}
if (IS_OBJ_STAT(weapon, ITEM_NOGIVE) && !IS_OBJ_STAT(sheath, ITEM_NOGIVE))
{
if (rev == 0)
{
do_sheath(ch, "go reverse");
return;
}
else if (rev == 1)
{
do_sheath(ch, "go reverse again");
return;
}
else
{
send_to_char("Your container needs to be nogive if your weapon is nogive.\n\r", ch);
return;
}
}
if (IS_OBJ_STAT(sheath, ITEM_NOGIVE) && !IS_OBJ_STAT(weapon, ITEM_NOGIVE))
{
if (rev == 0)
{
do_sheath(ch, "go reverse");
return;
}
else if (rev == 1)
{
do_sheath(ch, "go reverse again");
return;
}
else
{
send_to_char("Your weapon needs to be nogive if your container is nogive.\n\r", ch);
return;
}
}
if ((weapon->pIndexData->vnum != sheath->value[2]) && sheath->value[2] != 0)
{
if (rev == 0)
{
do_sheath(ch, "go reverse");
return;
}
else if (rev == 1)
{
do_sheath(ch, "go reverse again");
return;
}
else
{
send_to_char("Your sheath was made for a certain weapon and this one is not it.\n\r", ch);
return;
}
}
if (HAS_WAIT(ch))
{
send_to_char("You are too busy in battle to do that.\n\r", ch);
return;
}
sprintf(buf, "'%s'", weapon->name);
do_remove(ch, buf);
sprintf(buf, "'%s' '%s'", weapon->name, sheath->name);
do_put(ch, buf);
if (!sheath->first_content)
{
sprintf(buf, "'%s'", weapon->name);
do_wear(ch, buf);
}
return;
}
// Used to draw a weapon from a sheath for combat.
void do_draw(CHAR_DATA * ch, char *argument)
{
OBJ_DATA *sheath;
OBJ_DATA *weapon = NULL;
OBJ_DATA *tmpobj;
char buf[MSL];
char arg[MIL];
int found = 0;
int sn;
int limb;
if (ms_find_obj(ch))
return;
for (sheath = ch->first_carrying; sheath; sheath = sheath->next_content)
{
if (sheath->item_type == ITEM_SHEATH && sheath->wear_loc == WEAR_WAIST)
{
found = 1;
if (sheath->first_content)
{
weapon = sheath->first_content;
break;
}
}
}
if (found == 0)
{
send_to_char("You need to be wearing a sheath on your waist in order to draw.\n\r", ch);
return;
}
if (!weapon)
{
send_to_char("You don't have anything in your sheath to wield you fool.\n\r", ch);
return;
}
/* Quick checks to see if it is wieldable before removing, will safe some text spam on the
player plus problems */
if (!could_dual(ch))
{
if (!remove_obj(ch, WEAR_MISSILE_WIELD, 2))
return;
if (!remove_obj(ch, WEAR_WIELD, 2))
return;
if ((tmpobj = get_eq_char(ch, WEAR_SHIELD)) != NULL && IS_OBJ_STAT(tmpobj, ITEM_TWOHANDED))
{
if (IS_NPC(ch) || ch->pcdata->learned[gsn_inhuman_strength] <= 0)
return;
}
if (get_eq_char(ch, WEAR_SHIELD) && (ch->con_rarm == -1 || ch->con_larm == -1))
{
return;
}
if (ch->con_rarm == -1 && ch->con_larm == -1)
{
return;
}
tmpobj = NULL;
if (get_obj_weight(weapon) > str_app[get_curr_str(ch)].wield)
{
send_to_char("&RWielding such a heavy weapon is going to slow you down!!&w.\n\r", ch);
}
}
else
{
if ((tmpobj = get_eq_char(ch, WEAR_SHIELD)) != NULL && IS_OBJ_STAT(tmpobj, ITEM_TWOHANDED))
{
return;
}
if (IS_OBJ_STAT(weapon, ITEM_TWOHANDED) && tmpobj)
{
if (IS_NPC(ch) || ch->pcdata->learned[gsn_inhuman_strength] <= 0)
return;
}
tmpobj = NULL;
if ((tmpobj = get_eq_char(ch, WEAR_WIELD)) != NULL && (get_eq_char(ch, WEAR_MISSILE_WIELD) || get_eq_char(ch, WEAR_DUAL_WIELD)))
return;
if (IS_OBJ_STAT(weapon, ITEM_TWOHANDED) && get_eq_char(ch, WEAR_MISSILE_WIELD))
{
return;
}
if (get_eq_char(ch, WEAR_MISSILE_WIELD))
{
if ((tmpobj = get_eq_char(ch, WEAR_MISSILE_WIELD)) != NULL && IS_OBJ_STAT(tmpobj, ITEM_TWOHANDED))
{
return;
}
}
if (get_eq_char(ch, WEAR_WIELD))
{
if ((tmpobj = get_eq_char(ch, WEAR_WIELD)) != NULL && get_eq_char(ch, WEAR_SHIELD))
{
return;
}
}
if (get_eq_char(ch, WEAR_WIELD) && (ch->con_rarm == -1 || ch->con_larm == -1))
{
return;
}
if (!tmpobj && ch->con_rarm == -1 && ch->con_larm == -1)
{
return;
}
if (tmpobj)
{
if (get_obj_weight(weapon) + get_obj_weight(tmpobj) > str_app[get_curr_str(ch)].wield)
{
send_to_char("&RWielding such heavy weapons is going to slow you down!!&w.\n\r", ch);
}
}
else
{
if (get_obj_weight(weapon) > str_app[get_curr_str(ch)].wield)
{
send_to_char("&RWielding such a heavy weapon is going to slow you down!!&w.\n\r", ch);
}
}
}
/* New Weapon Handling code -- Xerves 6/1/99 */
if (!IS_NPC(ch))
{
if (weapon->value[3] < race_table[ch->race]->weaponmin)
{
act(AT_ACTION, "You try to wield $p, but you cannot grasp it with your hands.", ch, weapon, NULL, TO_CHAR);
return;
}
if (weapon->value[3] > race_table[ch->race]->weaponmax)
{
act(AT_ACTION, "You try to wield $p, but you cannot even lift it off the ground.", ch, weapon, NULL, TO_CHAR);
return;
}
}
if ((IS_OBJ_STAT(weapon, ITEM_NOGIVE) && !IS_OBJ_STAT(sheath, ITEM_NOGIVE))
|| (IS_OBJ_STAT(sheath, ITEM_NOGIVE) && !IS_OBJ_STAT(weapon, ITEM_NOGIVE)))
{
send_to_char("Either the weapon or sheath has a nogive flag, bug reported\n\r", ch);
bug("%s has a nogive flag weapon or container, trying to draw", ch->name);
return;
}
if (HAS_WAIT(ch))
{
send_to_char("You are too busy in battle to do that.\n\r", ch);
return;
}
sprintf(buf, "'%s' '%s'", weapon->name, sheath->name);
do_get(ch, buf);
sprintf(buf, "'%s'", weapon->name);
do_wear(ch, buf);
if (weapon->wear_loc != WEAR_WIELD && weapon->wear_loc != WEAR_MISSILE_WIELD && weapon->wear_loc != WEAR_DUAL_WIELD)
{
sprintf(buf, "'%s' '%s'", weapon->name, sheath->name);
do_put(ch, buf);
}
if (argument[0] != '\0')
{
CHAR_DATA *victim;
argument = one_argument(argument, arg);
if ((victim = get_char_room_new(ch, arg, 1)) == NULL)
{
send_to_char("They aren't here.\n\r", ch);
return;
}
if (IS_NPC(victim) && victim->morph)
{
send_to_char("This creature appears strange to you. Look upon it more closely before attempting to kill it.", ch);
return;
}
if (victim == ch)
{
send_to_char("You hit yourself. Ouch!\n\r", ch);
return;
}
if (is_safe(ch, victim))
return;
if (IS_AFFECTED(ch, AFF_CHARM) && ch->master == victim)
{
act(AT_PLAIN, "$N is your beloved master.", ch, NULL, victim, TO_CHAR);
return;
}
if (ch->position == POS_FIGHTING
|| ch->position == POS_EVASIVE || ch->position == POS_DEFENSIVE || ch->position == POS_AGGRESSIVE || ch->position == POS_BERSERK)
{
send_to_char("You do the best you can!\n\r", ch);
return;
}
if (argument[0] == '\0')
{
send_to_char("Need to choose a limb: rarm, larm, rleg, lleg, body, head, neck.\n\r", ch);
return;
}
if (!str_cmp(argument, "rarm"))
limb = LM_RARM;
else if (!str_cmp(argument, "larm"))
limb = LM_LARM;
else if (!str_cmp(argument, "rleg"))
limb = LM_RLEG;
else if (!str_cmp(argument, "lleg"))
limb = LM_LLEG;
else if (!str_cmp(argument, "body"))
limb = LM_BODY;
else if (!str_cmp(argument, "head"))
limb = LM_HEAD;
else if (!str_cmp(argument, "neck"))
limb = LM_NECK;
else
{
send_to_char("Need to choose a limb: rarm, larm, rleg, lleg, body, head, neck.\n\r", ch);
return;
}
check_attacker(ch, victim);
one_hit(ch, victim, gsn_unsheath, limb);
sn = sheath->value[4];
if (sn > 0)
{
if (IS_VALID_SN(sn) && skill_table[sn]->spell_fun)
{
if (sheath->value[5] > 0)
{
if (number_range(1, 100) > sheath->value[5])
return;
}
else
{
if (number_range(1, 100) > 25)
return;
}
(*skill_table[sn]->spell_fun) (sn, 1, ch, victim);
if (char_died(ch) || char_died(victim))
return;
}
}
return;
}
if (ch->fighting && ch->fighting->who != ch)
{
check_attacker(ch, ch->fighting->who);
if (argument[0] == '\0')
{
send_to_char("Need to choose a limb: rarm, larm, rleg, lleg, body, head, neck\n\r", ch);
return;
}
if (!str_cmp(argument, "rarm"))
limb = LM_RARM;
else if (!str_cmp(argument, "larm"))
limb = LM_LARM;
else if (!str_cmp(argument, "rleg"))
limb = LM_RLEG;
else if (!str_cmp(argument, "lleg"))
limb = LM_LLEG;
else if (!str_cmp(argument, "body"))
limb = LM_BODY;
else if (!str_cmp(argument, "head"))
limb = LM_HEAD;
else if (!str_cmp(argument, "neck"))
limb = LM_NECK;
else
{
send_to_char("Need to choose a limb: rarm, larm, rleg, lleg, body, head, neck", ch);
return;
}
one_hit(ch, ch->fighting->who, gsn_unsheath, limb);
}
sn = sheath->value[4];
if (sn > 0)
{
if (IS_VALID_SN(sn) && skill_table[sn]->spell_fun && ch->fighting && ch->fighting->who != ch)
{
if (sheath->value[5] > 0)
{
if (number_range(1, 100) > sheath->value[5])
return;
}
else
{
if (number_range(1, 100) > 25)
return;
}
(*skill_table[sn]->spell_fun) (sn, 1, ch, ch->fighting->who);
if (char_died(ch) || char_died(ch->fighting->who))
return;
}
}
return;
}
void do_wear(CHAR_DATA * ch, char *argument)
{
char arg1[MIL];
char arg2[MIL];
OBJ_DATA *obj;
sh_int wear_bit;
argument = one_argument(argument, arg1);
argument = one_argument(argument, arg2);
if ((!str_cmp(arg2, "on") || !str_cmp(arg2, "upon") || !str_cmp(arg2, "around")) && argument[0] != '\0')
argument = one_argument(argument, arg2);
if (arg1[0] == '\0')
{
send_to_char("Wear, wield, or hold what?\n\r", ch);
return;
}
if (ms_find_obj(ch))
return;
if (!str_cmp(arg1, "all"))
{
OBJ_DATA *obj_next;
for (obj = ch->first_carrying; obj; obj = obj_next)
{
obj_next = obj->next_content;
if (IS_SET(obj->wear_flags, ITEM_LODGE_RIB) || IS_SET(obj->wear_flags, ITEM_LODGE_ARM) || IS_SET(obj->wear_flags, ITEM_LODGE_LEG))
continue;
if (obj->wear_loc == WEAR_NONE && can_see_obj(ch, obj))
{
wear_obj(ch, obj, FALSE, -1);
if (char_died(ch))
return;
}
}
return;
}
else
{
if ((obj = get_obj_carry(ch, arg1)) == NULL)
{
send_to_char("You do not have that item.\n\r", ch);
return;
}
if (IS_SET(obj->wear_flags, ITEM_LODGE_RIB) || IS_SET(obj->wear_flags, ITEM_LODGE_ARM) || IS_SET(obj->wear_flags, ITEM_LODGE_LEG))
{
send_to_char("I do not think you want to wear that.\n\r", ch);
return;
}
if (arg2[0] != '\0')
wear_bit = get_wflag(arg2);
else
wear_bit = -1;
wear_obj(ch, obj, TRUE, wear_bit);
}
return;
}
void do_remove(CHAR_DATA * ch, char *argument)
{
char arg[MIL];
OBJ_DATA *obj, *obj_next;
one_argument(argument, arg);
if (arg[0] == '\0')
{
send_to_char("Remove what?\n\r", ch);
return;
}
if (ms_find_obj(ch))
return;
if (!str_cmp(arg, "all")) /* SB Remove all */
{
act(AT_PLAIN, "$n starts to remove it all.", ch, NULL, NULL, TO_ROOM);
for (obj = ch->first_carrying; obj != NULL; obj = obj_next)
{
obj_next = obj->next_content;
if (IS_SET(obj->wear_flags, ITEM_LODGE_RIB) || IS_SET(obj->wear_flags, ITEM_LODGE_ARM) || IS_SET(obj->wear_flags, ITEM_LODGE_LEG))
continue;
if (obj->wear_loc != WEAR_NONE && can_see_obj(ch, obj))
remove_obj(ch, obj->wear_loc, TRUE);
}
return;
}
if ((obj = get_obj_wear(ch, arg)) == NULL)
{
send_to_char("You are not using that item.\n\r", ch);
return;
}
if ((obj_next = get_eq_char(ch, obj->wear_loc)) != obj)
{
act(AT_PLAIN, "You must remove $p first.", ch, obj_next, NULL, TO_CHAR);
return;
}
if (IS_SET(obj->wear_flags, ITEM_LODGE_RIB) || IS_SET(obj->wear_flags, ITEM_LODGE_ARM) || IS_SET(obj->wear_flags, ITEM_LODGE_LEG))
{
send_to_char("You cannot remove those kind items, use dislodge.\n\r", ch);
return;
}
remove_obj(ch, obj->wear_loc, TRUE);
return;
}
void do_bury(CHAR_DATA * ch, char *argument)
{
char arg[MIL];
OBJ_DATA *obj;
bool shovel;
sh_int move;
one_argument(argument, arg);
if (arg[0] == '\0')
{
send_to_char("What do you wish to bury?\n\r", ch);
return;
}
if (ms_find_obj(ch))
return;
shovel = FALSE;
for (obj = ch->first_carrying; obj; obj = obj->next_content)
if (obj->item_type == ITEM_SHOVEL)
{
shovel = TRUE;
break;
}
obj = get_obj_list_rev(ch, arg, ch->in_room->last_content);
if (!obj)
{
send_to_char("You can't find it.\n\r", ch);
return;
}
separate_obj(obj);
if (!CAN_WEAR(obj, ITEM_TAKE))
{
if (!IS_OBJ_STAT(obj, ITEM_CLANCORPSE) || IS_NPC(ch))
{
act(AT_PLAIN, "You cannot bury $p.", ch, obj, 0, TO_CHAR);
return;
}
}
switch (ch->in_room->sector_type)
{
case SECT_CITY:
case SECT_INSIDE:
send_to_char("The floor is too hard to dig through.\n\r", ch);
return;
case SECT_WATER_SWIM:
case SECT_WATER_NOSWIM:
case SECT_UNDERWATER:
send_to_char("You cannot bury something here.\n\r", ch);
return;
case SECT_AIR:
send_to_char("What? In the air?!\n\r", ch);
return;
}
if (obj->weight > (UMAX(5, (can_carry_w(ch) / 10))) && !shovel)
{
send_to_char("You'd need a shovel to bury something that big.\n\r", ch);
return;
}
move = (obj->weight * 50 * (shovel ? 1 : 5)) / UMAX(1, can_carry_w(ch));
move = URANGE(2, move, 1000);
if (move > ch->move)
{
send_to_char("You don't have the energy to bury something of that size.\n\r", ch);
return;
}
ch->move -= move;
if (obj->item_type == ITEM_CORPSE_NPC || obj->item_type == ITEM_CORPSE_PC)
adjust_favor(ch, 6, 1);
act(AT_ACTION, "You solemnly bury $p...", ch, obj, NULL, TO_CHAR);
act(AT_ACTION, "$n solemnly buries $p...", ch, obj, NULL, TO_ROOM);
xSET_BIT(obj->extra_flags, ITEM_BURIED);
WAIT_STATE(ch, URANGE(10, move / 2, 100));
return;
}
void do_sacrifice(CHAR_DATA * ch, char *argument)
{
char arg[MIL];
char buf[MSL];
char name[50];
OBJ_DATA *obj;
OBJ_DATA *obj_prev;
int x;
one_argument(argument, arg);
if (argument[0] == '\0')
{
send_to_char("Syntax: sacrifice <name of object>\n\r", ch);
send_to_char("Syntax: sacrifice all\n\r", ch);
return;
}
if (!str_cmp(arg, "all"))
{
sacall = 1;
for (x = 1; x <= 15; x++) //Due to separate obj this needs to be run a few times to clean up the mess
{
for (obj = ch->in_room->last_content; obj; obj = obj_prev)
{
obj_prev = obj->prev_content;
if (IN_SAME_ROOM_OBJ(ch, obj))
{
sprintf(buf, "%s", obj->name);
do_sacrifice(ch, buf);
}
}
}
sacall = 0;
return;
}
if (!str_cmp(arg, ch->name))
{
act(AT_ACTION, "$n offers $mself to $s deity, who graciously declines.", ch, NULL, NULL, TO_ROOM);
send_to_char("Your deity appreciates your offer and may accept it later.\n\r", ch);
return;
}
if (ms_find_obj(ch))
return;
obj = get_obj_list_rev(ch, arg, ch->in_room->last_content);
if (!obj)
{
send_to_char("You can't find it.\n\r", ch);
return;
}
separate_obj(obj);
if (!CAN_WEAR(obj, ITEM_TAKE))
{
if (sacall == 0)
act(AT_PLAIN, "$p is not an acceptable sacrifice.", ch, obj, 0, TO_CHAR);
return;
}
if (!IS_NPC(ch) && ch->pcdata->deity && ch->pcdata->deity->name[0] != '\0')
{
strcpy(name, ch->pcdata->deity->name);
}
else if (!IS_NPC(ch) && IS_GUILDED(ch) && sysdata.guild_overseer[0] != '\0')
{
strcpy(name, sysdata.guild_overseer);
}
else if (!IS_NPC(ch) && ch->pcdata->clan && ch->pcdata->clan->deity[0] != '\0')
{
strcpy(name, ch->pcdata->clan->deity);
}
else
{
strcpy(name, "Xerves");
}
ch->gold += 1;
if (obj->item_type == ITEM_CORPSE_NPC || obj->item_type == ITEM_CORPSE_PC)
adjust_favor(ch, 5, 1);
sprintf(buf, "%s gives you one gold coin for your sacrifice.\n\r", name);
send_to_char(buf, ch);
sprintf(buf, "$n sacrifices $p to %s.", name);
act(AT_ACTION, buf, ch, obj, NULL, TO_ROOM);
oprog_sac_trigger(ch, obj);
if (obj_extracted(obj))
return;
if (cur_obj == obj->serial)
global_objcode = rOBJ_SACCED;
check_for_trap(ch, obj, -1, NEW_TRAP_SACOBJ);
if (global_retcode == rOBJ_SCRAPPED)
return;
if (obj)
extract_obj(obj);
return;
}
//Used on runes, for now, just for moving to a portal
void do_rub(CHAR_DATA * ch, char *argument)
{
OBJ_DATA *rune;
char arg1[MIL];
int p, x, y, map;
int count = 0;
int found = 0;
int targetRoomVnum;
ROOM_INDEX_DATA *targetRoom;
p = 0;
if (IS_NPC(ch))
{
send_to_char("This command is for PCs only, sorry.\n\r", ch);
return;
}
if (argument[0] == '\0')
{
send_to_char("rub <rune> <portal>\n\r", ch);
return;
}
argument = one_argument(argument, arg1);
if ((rune = get_obj_carry(ch, arg1)) == NULL)
{
send_to_char("You do not have that item in your inventory.\n\r", ch);
return;
}
if (rune->item_type != ITEM_RUNE)
{
send_to_char("You can only rub runes.\n\r", ch);
return;
}
if (rune->value[0] != 1)
{
send_to_char("You try to rub the rune, but it appears to not be enchanted.\n\r", ch);
return;
}
if (can_use_portal(ch, 3) == FALSE)
return;
WAIT_STATE(ch, 3 * PULSE_VIOLENCE);
if (isdigit(argument[0]))
{
for (p = 0; p < sysdata.last_portal; p++)
{
if (xIS_SET(ch->pcdata->portalfnd, p))
{
count++;
}
if (count == atoi(argument))
{
found = 1;
break;
}
}
}
if (!str_cmp(argument, "home"))
{
if (ch->in_room->vnum == ROOM_VNUM_PORTAL)
{
send_to_char("You cannot use the rune to portal to a portal you are at.\n\r", ch);
return;
}
else
count = 10000; //Should be enough, god forbid 10000 portal spots -- Xerves
}
if (found == 0 && count < 10000)
{
send_to_char("Your rune will only work with portals on your list, or 'home' or 'newbie'.\n\r", ch);
return;
}
if (count == 0)
{
send_to_char("You have no portals to goto.\n\r", ch);
return;
}
if (count == 10000)
targetRoomVnum = ROOM_VNUM_PORTAL;
else
targetRoomVnum = OVERLAND_SOLAN;
if (count != 10000 && count != 10001)
{
x = portal_show[p]->x;
y = portal_show[p]->y;
map = portal_show[p]->map;
if (ch->coord->x == x && ch->coord->y == y && ch->map == map)
{
send_to_char("You cannot use the rune to portal to a portal you are at.\n\r", ch);
return;
}
}
else
{
x = -1;
y = -1;
map = -1;
if (ch->in_room->vnum == targetRoomVnum)
{
send_to_char("You cannot use the rune to portal to a portal you are at.\n\r", ch);
return;
}
}
targetRoom = get_room_index(targetRoomVnum);
if (x > -1 || y > -1 || map > -1)
{
SET_ONMAP_FLAG(ch);
ch->coord->x = x;
ch->coord->y = y;
ch->map = map;
char_from_room(ch);
char_to_room(ch, targetRoom);
update_objects(ch, x, y, ch->map);
if (ch->rider)
{
SET_ONMAP_FLAG(ch->rider);
ch->rider->coord->x = x;
ch->rider->coord->y = y;
ch->rider->map = map;
char_from_room(ch->rider);
char_to_room(ch->rider, targetRoom);
update_objects(ch->rider, x, y, ch->map);
}
}
else
{
REMOVE_ONMAP_FLAG(ch);
ch->coord->x = -1;
ch->coord->y = -1;
ch->map = -1;
char_from_room(ch);
char_to_room(ch, targetRoom);
update_objects(ch, x, y, ch->map);
if (ch->rider)
{
REMOVE_ONMAP_FLAG(ch->rider);
ch->rider->coord->x = -1;
ch->rider->coord->y = -1;
ch->rider->map = -1;
char_from_room(ch->rider);
char_to_room(ch->rider, targetRoom);
update_objects(ch->rider, x, y, ch->map);
}
}
if (ch->on)
{
ch->on = NULL;
ch->position = POS_STANDING;
}
if (ch->position != POS_STANDING)
{
ch->position = POS_STANDING;
}
act(AT_MAGIC, "$n appears in a flash of light!", ch, NULL, NULL, TO_ROOM);
do_look(ch, "auto");
if (--rune->value[1] <= 0)
{
act(AT_MAGIC, "$p lights up and suddenly and vanishes from $n", ch, rune, NULL, TO_ROOM);
act(AT_MAGIC, "$p lights up and suddenly and vanishes from your inventory.", ch, rune, NULL, TO_CHAR);
if (rune->serial == cur_obj)
global_objcode = rOBJ_USED;
separate_obj(rune);
extract_obj(rune);
}
return;
}
void do_brandish(CHAR_DATA * ch, char *argument)
{
CHAR_DATA *victim = NULL;
OBJ_DATA *staff;
int value = 0;
ch_ret retcode;
static char extra[MSL];
int passarg = 0;
int sn;
if ((staff = get_eq_char(ch, WEAR_WIELD)) == NULL)
{
send_to_char("You not wielding anything to brandish.\n\r", ch);
return;
}
if ((sn = staff->value[4]) < 0 || sn >= top_sn || skill_table[sn]->spell_fun == NULL)
{
bug("Do_brandish: bad sn %d.", sn);
return;
}
if (HAS_WAIT(ch))
{
send_to_char("You are too busy in battle to do that.\n\r", ch);
return;
}
if (ch->fighting)
ch->fight_timer = staff->value[5] - SPOWER_MIN + 2;
else
WAIT_STATE(ch, staff->value[5] - SPOWER_MIN + 2);
if (staff->value[5] > 0)
{
if (!oprog_use_trigger(ch, staff, NULL, NULL, NULL))
{
act(AT_MAGIC, "$n brandishes $p.", ch, staff, NULL, TO_ROOM);
act(AT_MAGIC, "You brandish $p.", ch, staff, NULL, TO_CHAR);
}
if (skill_table[sn]->target == TAR_CHAR_OFFENSIVE && ch->fighting)
victim = ch->fighting->who;
if (skill_table[sn]->target == TAR_CHAR_DEFENSIVE)
victim = ch;
if (staff->value[4] != skill_lookup("word of recall"))
{
if (argument[0] != '\0')
{
if ((victim=get_char_room(ch, argument)) == NULL)
{
send_to_char("Your target is not in this room.\n\r", ch);
return;
}
}
}
else
{
victim = ch;
sprintf(extra, argument);
target_name = extra;
passarg = 1;
}
if (skill_table[sn]->target == TAR_CHAR_SELF)
victim = ch;
if (skill_table[sn]->target != TAR_IGNORE)
{
if (!victim)
{
send_to_char("You need a target to brandish your weapon on.\n\r", ch);
return;
}
}
if (victim && !IS_NPC(victim) && xIS_SET(victim->act, PLR_WIZINVIS) && victim->pcdata->wizinvis >= LEVEL_IMMORTAL)
{
send_to_char("Your target is not in this room.\n\r", ch);
return;
}
switch (skill_table[sn]->target)
{
case TAR_CHAR_SELF:
if (victim != ch)
{
send_to_char("Can only target yourself with this weapon.\n\r", ch);
return;
}
}
if (staff->value[5] < SPOWER_MIN || staff->value[5] > SPOWER_GREATEST)
{
staff->value[5] = SPOWER_MIN;
bug("Spower on object %s on %s is bad.", staff->name, ch->name);
}
if (!passarg)
retcode = obj_cast_spell(staff->value[4], staff->value[5], ch, victim, staff);
else
retcode = obj_cast_spell(staff->value[4]+10000, staff->value[5], ch, victim, staff);
if (retcode == rCHAR_DIED || retcode == rBOTH_DIED)
{
bug("do_brandish: char died", 0);
return;
}
if (staff->value[5] == SPOWER_MIN)
value = 15;
if (staff->value[5] == SPOWER_LOW)
value = 25;
if (staff->value[5] == SPOWER_MED)
value = 40;
if (staff->value[5] == SPOWER_HI)
value = 60;
if (staff->value[5] == SPOWER_GREAT)
value = 90;
if (staff->value[5] == SPOWER_GREATER)
value = 130;
if (staff->value[5] == SPOWER_GREATEST)
value = 180;
value = value * (100-(staff->value[10]*4)) / 100;
staff->value[0] -= number_range(value*80/100, value*120/100);
if (staff->value[0] <= 0)
{
act(AT_MAGIC, "$p blazes bright and vanishes from $n's hands!", ch, staff, NULL, TO_ROOM);
act(AT_MAGIC, "$p blazes bright and is gone!", ch, staff, NULL, TO_CHAR);
if (staff->serial == cur_obj)
global_objcode = rOBJ_USED;
extract_obj(staff);
}
}
return;
}
//No reason, just use brandish
void do_zap(CHAR_DATA * ch, char *argument)
{
do_brandish(ch, argument);
return;
}
/*
* Save items in a clan storage room -Scryn & Thoric
*/
void save_clan_storeroom(CHAR_DATA * ch, CLAN_DATA * clan)
{
FILE *fp;
char filename[256];
OBJ_DATA *contents;
if (!clan)
{
bug("save_clan_storeroom: Null clan pointer!", 0);
return;
}
if (!ch)
{
bug("save_clan_storeroom: Null ch pointer!", 0);
return;
}
sprintf(filename, "%s%s.vault", CLAN_DIR, clan->filename);
if ((fp = fopen(filename, "w")) == NULL)
{
bug("save_clan_storeroom: fopen", 0);
perror(filename);
}
else
{
fprintf(fp, "#VERSION\n");
fprintf(fp, "Version %d\n", SAVEVERSION);
fprintf(fp, "End\n\n");
contents = ch->in_room->last_content;
if (contents)
{
fwrite_obj(ch, contents, fp, 0, OS_CARRY);
}
fprintf(fp, "#END\n");
fclose(fp);
return;
}
return;
}
/* put an item on , or see the stats on the current item or bet */
void do_auction(CHAR_DATA * ch, char *argument)
{
OBJ_DATA *obj;
char arg1[MIL];
char arg2[MIL];
char arg3[MIL];
char buf[MSL];
int i;
argument = one_argument(argument, arg1);
argument = one_argument(argument, arg2);
argument = one_argument(argument, arg3);
set_char_color(AT_LBLUE, ch);
if (IS_NPC(ch)) /* NPC can be extracted at any time and thus can't auction! */
return;
/* I pity the foo that doesn't work nights....
if ((gethour() > 18 || gethour() < 9) && auction->item == NULL && !IS_IMMORTAL(ch))
{
send_to_char("\n\rThe auctioneer works between the hours of 9 AM and 6 PM\n\r", ch);
return;
} */
if (arg1[0] == '\0')
{
if (auction->item != NULL)
{
obj = auction->item;
/* show item data here */
if (auction->bet > 0)
sprintf(buf, "\n\rCurrent bid on this item is %d gold.\n\r", auction->bet);
else
sprintf(buf, "\n\rNo bids on this item have been received.\n\r");
set_char_color(AT_BLUE, ch);
send_to_char(buf, ch);
code_identify(ch, obj, NULL, 1, NULL);
if ((obj->item_type == ITEM_CONTAINER || obj->item_type == ITEM_KEYRING || obj->item_type == ITEM_QUIVER) && obj->first_content)
{
set_char_color(AT_OBJECT, ch);
send_to_char("Contents:\n\r", ch);
show_list_to_char( obj->first_content, ch, TRUE, FALSE, eItemBid );
}
if (IS_IMMORTAL(ch))
{
sprintf(buf, "Seller: %s. Bidder: %s. Round: %d.\n\r", auction->seller->name, auction->buyer->name, (auction->going + 1));
send_to_char(buf, ch);
sprintf(buf, "Time left in round: %d.\n\r", auction->pulse);
send_to_char(buf, ch);
}
return;
}
else
{
set_char_color(AT_LBLUE, ch);
send_to_char("\n\rThere is nothing being auctioned right now. What would you like to auction?\n\r", ch);
return;
}
}
if (IS_IMMORTAL(ch) && !str_cmp(arg1, "stop"))
{
if (auction->item == NULL)
{
send_to_char("There is no auction to stop.\n\r", ch);
return;
}
else /* stop the auction */
{
set_char_color(AT_LBLUE, ch);
sprintf(buf, "Sale of %s has been stopped by an Immortal.", auction->item->short_descr);
talk_auction(buf);
obj_to_char(auction->item, auction->seller);
if (IS_SET(sysdata.save_flags, SV_AUCTION))
save_char_obj(auction->seller);
auction->item = NULL;
if (auction->buyer != NULL && auction->buyer != auction->seller) /* return money to the buyer */
{
auction->buyer->gold += auction->bet;
send_to_char("Your money has been returned.\n\r", auction->buyer);
}
return;
}
}
if (!str_cmp(arg1, "bid"))
{
if (auction->item != NULL)
{
int newbet;
if (ch->level < auction->item->level)
{
send_to_char("This object's level is too high for your use.\n\r", ch);
return;
}
if (ch == auction->seller)
{
send_to_char("You can't bid on your own item!\n\r", ch);
return;
}
if (IS_UNIQUE(ch, auction->item))
{
send_to_char("That item is unique and you already have one.\n\r", ch);
return;
}
/* make - perhaps - a bet now */
if (arg2[0] == '\0')
{
send_to_char("Bid how much?\n\r", ch);
return;
}
newbet = parsebet(auction->bet, arg2);
/* ch_printf( ch, "Bid: %d\n\r",newbet); */
if (newbet < auction->starting)
{
send_to_char("You must place a bid that is higher than the starting bet.\n\r", ch);
return;
}
/* to avoid slow auction, use a bigger amount than 100 if the bet
is higher up - changed to 10000 for our high economy
*/
/* Blah, changed it back -- Xerves 11/99 */
if (newbet < (auction->bet + 100))
{
send_to_char("You must at least bid 100 coins over the current bid.\n\r", ch);
return;
}
if (newbet > ch->gold)
{
send_to_char("You don't have that much money!\n\r", ch);
return;
}
if (newbet > 2000000000)
{
send_to_char("You can't bid over 2 billion coins.\n\r", ch);
return;
}
/* Is it the item they really want to bid on? --Shaddai */
if (arg3[0] != '\0' && !nifty_is_name(arg3, auction->item->name))
{
send_to_char("That item is not being auctioned right now.\n\r", ch);
return;
}
/* the actual bet is OK! */
/* return the gold to the last buyer, if one exists */
if (auction->buyer != NULL && auction->buyer != auction->seller)
auction->buyer->gold += auction->bet;
ch->gold -= newbet; /* substract the gold - important :) */
if (IS_SET(sysdata.save_flags, SV_AUCTION))
save_char_obj(ch);
auction->buyer = ch;
auction->bet = newbet;
auction->going = 0;
auction->pulse = PULSE_AUCTION; /* start the auction over again */
sprintf(buf, "A bid of %d gold has been received on %s.\n\r", newbet, auction->item->short_descr);
talk_auction(buf);
return;
}
else
{
send_to_char("There isn't anything being auctioned right now.\n\r", ch);
return;
}
}
/* finally... */
if (ms_find_obj(ch))
return;
obj = get_obj_carry(ch, arg1); /* does char have the item ? */
if (obj == NULL)
{
send_to_char("You aren't carrying that.\n\r", ch);
return;
}
if (obj->timer > 0)
{
send_to_char("You can't auction objects that are decaying.\n\r", ch);
return;
}
if (get_timer(ch, TIMER_AUCTION) >= 1)
{
send_to_char("There is a 30 second wait after you auction an item, please wait.\n\r", ch);
return;
}
/* prevent repeat auction items */
for (i = 0; i < AUCTION_MEM && auction->history[i]; i++)
{
if (auction->history[i] == obj->pIndexData)
{
send_to_char("Such an item has been auctioned " "recently, try again later.\n\r", ch);
return;
}
}
if (arg2[0] == '\0')
{
auction->starting = obj->cost;
sprintf(arg2, "%d", obj->cost);
}
if (!str_cmp(arg2, "lowest"))
{
auction->starting = UMAX(1, obj->cost/10);
sprintf(arg2, "%d", UMAX(1, obj->cost/10));
}
if (!is_number(arg2))
{
send_to_char("You must input a number at which to start the auction.\n\r", ch);
return;
}
if (atoi(arg2) < UMAX(1,obj->cost/10))
{
send_to_char("You can't auction something for less than 1/10 cost of the object!\n\r", ch);
return;
}
/* Cannot auction a nogive item, another block --Xerves 3/24/99 */
if (IS_OBJ_STAT(obj, ITEM_NOGIVE))
{
send_to_char("Please give up! You cannot auction this item!n\r", ch);
return;
}
if (auction->item == NULL)
switch (obj->item_type)
{
default:
act(AT_TELL, "You cannot auction $Ts.", ch, NULL, item_type_name(obj), TO_CHAR);
return;
/* insert any more item types here... items with a timer MAY NOT BE
AUCTIONED!
*/
case ITEM_LIGHT:
case ITEM_TREASURE:
case ITEM_POTION:
case ITEM_CONTAINER:
case ITEM_KEYRING:
case ITEM_QUIVER:
case ITEM_DRINK_CON:
case ITEM_FOOD:
case ITEM_COOK:
case ITEM_PEN:
case ITEM_BOAT:
case ITEM_PIPE:
case ITEM_INCENSE:
case ITEM_FIRE:
case ITEM_RUNEPOUCH:
case ITEM_MAP:
case ITEM_BOOK:
case ITEM_RUNE:
case ITEM_TGEM:
case ITEM_MATCH:
case ITEM_WEAPON:
case ITEM_ARMOR:
case ITEM_SCROLL:
separate_obj(obj);
obj_from_char(obj);
if (IS_SET(sysdata.save_flags, SV_AUCTION))
save_char_obj(ch);
auction->item = obj;
auction->bet = 0;
auction->buyer = ch;
auction->seller = ch;
auction->pulse = PULSE_AUCTION;
auction->going = 0;
auction->starting = atoi(arg2);
/* add the new item to the history */
if (AUCTION_MEM > 0)
{
memmove((char *) auction->history + sizeof(OBJ_INDEX_DATA *), auction->history, (AUCTION_MEM - 1) * sizeof(OBJ_INDEX_DATA *));
auction->history[0] = obj->pIndexData;
}
/* reset the history timer */
auction->hist_timer = 0;
if (auction->starting > 0)
auction->bet = auction->starting;
sprintf(buf, "A new item is being auctioned: %s at %d gold.", obj->short_descr, auction->starting);
talk_auction(buf);
return;
} /* switch */
else
{
act(AT_TELL, "Try again later - $p is being auctioned right now!", ch, auction->item, NULL, TO_CHAR);
return;
}
}
//EQ like Bazaar. Will allow players to put up equipment to sell. There will
//be a fee though and you don't have to sit around to sell the objects.
void do_market(CHAR_DATA *ch, char *argument)
{
char arg1[MIL];
char arg2[MIL];
char arg3[MIL];
char arg4[MIL];
char buf[MSL];
char buf2[MSL];
int count = 0;
int price = 0;
int sellname = 0;
OBJ_DATA *obj;
OBJ_DATA *rest;
MARKET_DATA *market;
MARKET_DATA *marketnext;
int num = 0;
if (check_npc(ch))
return;
if (!xIS_SET(ch->in_room->room_flags, ROOM_MARKETPLACE))
{
send_to_char("You can only use this command at a marketplace.\n\r", ch);
return;
}
if (argument[0] == '\0')
{
send_to_char("Syntax: market list [search option] [value]\n\r", ch);
send_to_char("Syntax: market sell <name of item> [count|all] [cost|lowest] [list seller name <yes|no>]\n\r", ch);
send_to_char("Syntax: market buy <number> <count|all>\n\r", ch);
send_to_char("Syntax: market edit <number> <list|cost> <new value>\n\r", ch);
send_to_char("Syntax: market view <number>\n\r", ch);
send_to_char("Syntax: market claim\n\r", ch);
send_to_char("Syntax: seach options: all name maxcost mincost rangecost itemtype\n\r", ch);
return;
}
argument = one_argument(argument, arg1);
if (!str_cmp(arg1, "claim"))
{
for (market = first_market; market; market = marketnext)
{
marketnext = market->next;
if (market->count < market->scount && market->pid == ch->pcdata->pid)
{
price = market->cost * (market->scount - market->count);
ch->gold += price - (price * 5 / 100);
num++;
ch_printf(ch, "You sold %d of %d of %s and you earned %d (fee of %d)\n\r",
market->scount - market->count, market->scount, market->obj->short_descr,
price - (price * 5 / 100), price * 5 / 100);
if (market->count == 0)
{
STRFREE(market->name);
extract_obj(market->obj);
UNLINK(market, first_market, last_market, next, prev);
DISPOSE(market);
}
else
{
market->scount = market->count;
}
}
}
if (num == 0)
{
send_to_char("None of your goods have sold yet.\n\r", ch);
return;
}
else
{
save_market_data();
return;
}
}
if (!str_cmp(arg1, "edit"))
{
argument = one_argument(argument, arg2);
argument = one_argument(argument, arg3);
for (market = first_market; market; market = market->next)
{
num++;
if (market->mpid == atoi(arg2))
break;
}
if (!market)
{
send_to_char("That item number does not exist.\n\r", ch);
return;
}
if (market->pid != ch->pcdata->pid)
{
send_to_char("This object does not belong to you.\n\r", ch);
return;
}
if (!str_cmp(arg3, "cost"))
{
if (atoi(argument) < market->obj->cost)
{
send_to_char("Asking price cannot be lower than the cost of the object.\n\r", ch);
return;
}
market->cost = atoi(argument);
ch_printf(ch, "Changed the cost on item %d to %d\n\r", atoi(arg2), atoi(argument));
save_market_data();
return;
}
if (!str_cmp(arg3, "list"))
{
if (!str_cmp(argument, "no"))
{
if (market->name)
STRFREE(market->name);
market->name = STRALLOC("Unlisted");
}
else if (!str_cmp(argument, "yes"))
{
if (market->name)
STRFREE(market->name);
market->name = STRALLOC(ch->name);
}
else
{
do_market(ch, "");
return;
}
send_to_char("Changed your name listing to what you provided.\n\r", ch);
save_market_data();
return;
}
do_market(ch, "");
return;
}
if (!str_cmp(arg1, "view"))
{
for (market = first_market; market; market = market->next)
{
num++;
if (market->mpid == atoi(argument))
break;
}
if (!market)
{
send_to_char("That item number does not exist.\n\r", ch);
return;
}
code_identify(ch, market->obj, NULL, 1, NULL);
return;
}
if (!str_cmp(arg1, "buy"))
{
argument = one_argument(argument, arg2);
if (atoi(arg2) <= 0)
{
send_to_char("You must specify the number of the item you wish to purchase.\n\r", ch);
return;
}
for (market = first_market; market; market = market->next)
{
if (market->mpid == atoi(arg2))
break;
}
if (!market)
{
send_to_char("That item number does not exist.\n\r", ch);
return;
}
if (atoi(argument) > 0)
{
if (market->count < atoi(argument))
{
ch_printf(ch, "There is only %d of those for sale.\n\r", market->count);
return;
}
if (market->count == atoi(argument))
count = -1;
else
count = atoi(argument);
}
else if (!str_cmp(argument, "all"))
{
count = -1;
}
else
{
send_to_char("Invalid option.\n\r", ch);
return;
}
if (count == -1)
price = market->count * market->cost;
else
price = market->cost * count;
if (price > ch->gold)
{
send_to_char("You do not have enough gold to pay for that.\n\r", ch);
return;
}
if (count == -1)
{
if (get_ch_carry_weight(ch) + (get_obj_weight(market->obj) * market->count) > can_carry_w(ch))
{
send_to_char("You cannot carry that much weight.\n\r", ch);
return;
}
if (get_ch_carry_number(ch) + market->count > can_carry_n(ch))
{
send_to_char("You cannot carry that many items.\n\r", ch);
return;
}
obj = clone_object(market->obj);
count = market->count;
obj->count = market->count;
market->count = 0;
obj_to_char(obj, ch);
}
else
{
if (get_ch_carry_weight(ch) + (get_obj_weight(market->obj) * count) > can_carry_w(ch))
{
send_to_char("You cannot carry that much weight.\n\r", ch);
return;
}
if (get_ch_carry_number(ch) + count > can_carry_n(ch))
{
send_to_char("You cannot carry that many items.\n\r", ch);
return;
}
obj = clone_object(market->obj);
obj->count = count;
market->count -= count;
obj_to_char(obj, ch);
}
ch->gold -= price;
save_market_data();
ch_printf(ch, "You have purchased %d of %s\n\r", count, obj->short_descr);
return;
}
if (!str_cmp(arg1, "list"))
{
argument = one_argument(argument, arg2);
if (!str_cmp(arg2, "name"))
{
ch_printf(ch, "&w&RNum Item Name Cnt Cost Asking Itemtype Seller\n\r----------------------------------------------------------------------------------------------\n\r", ch);
for (market = first_market; market; market = market->next)
{
num++;
if (market->count)
{
if (nifty_is_name(argument, market->obj->name))
{
sprintf(buf2, "%d", market->mpid);
sprintf(buf, MXPFTAG("Command 'market view %d' desc='Click here to id this item'", "%d", "/Command") "%s",
market->mpid, market->mpid, add_space(strlen(buf2), 6));
ch_printf(ch, "&c&w%s> " MXPFTAG("PCommand 'market buy %d 1' desc='Click here to buy this item'", "&w&W%s", "/PCommand")
"%s&w&W %-2d &w&c%-10d &w&C%-10d ",
buf, market->mpid, market->obj->short_descr, add_wspace(strlen_color(market->obj->short_descr), 30),
market->count, market->obj->cost, market->cost);
ch_printf(ch, MXPFTAG("Command 'market list itemtype %s' desc='Click here to view other items of this itemtype'", "&w&G%s", "/Command")
"%s &w&O%-15s\n\r", item_type_name(market->obj), item_type_name(market->obj),
add_wspace(strlen(item_type_name(market->obj)), 14), market->name);
}
}
}
return;
}
if (!str_cmp(arg2, "mincost"))
{
ch_printf(ch, "&w&RNum Item Name Cnt Cost Asking Itemtype Seller\n\r----------------------------------------------------------------------------------------------\n\r", ch);
for (market = first_market; market; market = market->next)
{
num++;
if (market->count)
{
if (market->cost >= atoi(argument))
{
sprintf(buf2, "%d", market->mpid);
sprintf(buf, MXPFTAG("Command 'market view %d' desc='Click here to id this item'", "%d", "/Command") "%s",
market->mpid, market->mpid, add_space(strlen(buf2), 6));
ch_printf(ch, "&c&w%s> " MXPFTAG("PCommand 'market buy %d 1' desc='Click here to buy this item'", "&w&W%s", "/PCommand")
"%s&w&W %-2d &w&c%-10d &w&C%-10d ",
buf, market->mpid, market->obj->short_descr, add_wspace(strlen_color(market->obj->short_descr), 30),
market->count, market->obj->cost, market->cost);
ch_printf(ch, MXPFTAG("Command 'market list itemtype %s' desc='Click here to view other items of this itemtype'", "&w&G%s", "/Command")
"%s &w&O%-15s\n\r", item_type_name(market->obj), item_type_name(market->obj),
add_wspace(strlen(item_type_name(market->obj)), 14), market->name);
}
}
}
return;
}
if (!str_cmp(arg2, "rangecost"))
{
argument = one_argument(argument, arg3);
if (atoi(arg3) > atoi(argument))
{
send_to_char("The first value in the range has to be less than the second.\n\r", ch);
return;
}
ch_printf(ch, "&w&RNum Item Name Cnt Cost Asking Itemtype Seller\n\r----------------------------------------------------------------------------------------------\n\r", ch);
for (market = first_market; market; market = market->next)
{
num++;
if (market->count)
{
if (market->cost >= atoi(arg3) && market->cost <= atoi(argument))
{
sprintf(buf2, "%d", market->mpid);
sprintf(buf, MXPFTAG("Command 'market view %d' desc='Click here to id this item'", "%d", "/Command") "%s",
market->mpid, market->mpid, add_space(strlen(buf2), 6));
ch_printf(ch, "&c&w%s> " MXPFTAG("PCommand 'market buy %d 1' desc='Click here to buy this item'", "&w&W%s", "/PCommand")
"%s&w&W %-2d &w&c%-10d &w&C%-10d ",
buf, market->mpid, market->obj->short_descr, add_wspace(strlen_color(market->obj->short_descr), 30),
market->count, market->obj->cost, market->cost);
ch_printf(ch, MXPFTAG("Command 'market list itemtype %s' desc='Click here to view other items of this itemtype'", "&w&G%s", "/Command")
"%s &w&O%-15s\n\r", item_type_name(market->obj), item_type_name(market->obj),
add_wspace(strlen(item_type_name(market->obj)), 14), market->name);
}
}
}
return;
}
if (!str_cmp(arg2, "maxcost"))
{
ch_printf(ch, "&w&RNum Item Name Cnt Cost Asking Itemtype Seller\n\r----------------------------------------------------------------------------------------------\n\r", ch);
for (market = first_market; market; market = market->next)
{
num++;
if (market->count)
{
if (market->cost <= atoi(argument))
{
sprintf(buf2, "%d", market->mpid);
sprintf(buf, MXPFTAG("Command 'market view %d' desc='Click here to id this item'", "%d", "/Command") "%s",
market->mpid, market->mpid, add_space(strlen(buf2), 6));
ch_printf(ch, "&c&w%s> " MXPFTAG("PCommand 'market buy %d 1' desc='Click here to buy this item'", "&w&W%s", "/PCommand")
"%s&w&W %-2d &w&c%-10d &w&C%-10d ",
buf, market->mpid, market->obj->short_descr, add_wspace(strlen_color(market->obj->short_descr), 30),
market->count, market->obj->cost, market->cost);
ch_printf(ch, MXPFTAG("Command 'market list itemtype %s' desc='Click here to view other items of this itemtype'", "&w&G%s", "/Command")
"%s &w&O%-15s\n\r", item_type_name(market->obj), item_type_name(market->obj),
add_wspace(strlen(item_type_name(market->obj)), 14), market->name);
}
}
}
return;
}
if (!str_cmp(arg2, "itemtype"))
{
int ivalue = get_otype(argument);
if (ivalue < 1)
{
ch_printf(ch, "Unknown type: %s\n\r", argument);
return;
}
ch_printf(ch, "&w&RNum Item Name Cnt Cost Asking Itemtype Seller\n\r----------------------------------------------------------------------------------------------\n\r", ch);
for (market = first_market; market; market = market->next)
{
num++;
if (market->count)
{
if (market->obj->item_type == ivalue)
{
sprintf(buf2, "%d", market->mpid);
sprintf(buf, MXPFTAG("Command 'market view %d' desc='Click here to id this item'", "%d", "/Command") "%s",
market->mpid, market->mpid, add_space(strlen(buf2), 6));
ch_printf(ch, "&c&w%s> " MXPFTAG("PCommand 'market buy %d 1' desc='Click here to buy this item'", "&w&W%s", "/PCommand")
"%s&w&W %-2d &w&c%-10d &w&C%-10d ",
buf, market->mpid, market->obj->short_descr, add_wspace(strlen_color(market->obj->short_descr), 30),
market->count, market->obj->cost, market->cost);
ch_printf(ch, MXPFTAG("Command 'market list itemtype %s' desc='Click here to view other items of this itemtype'", "&w&G%s", "/Command")
"%s &w&O%-15s\n\r", item_type_name(market->obj), item_type_name(market->obj),
add_wspace(strlen(item_type_name(market->obj)), 14), market->name);
}
}
}
return;
}
if (!str_cmp(arg2, "all"))
{
ch_printf(ch, "&w&RNum Item Name Cnt Cost Asking Itemtype Seller\n\r---------------------------------------------------------------------------------------------\n\r", ch);
for (market = first_market; market; market = market->next)
{
num++;
if (market->count)
{
sprintf(buf2, "%d", market->mpid);
sprintf(buf, MXPFTAG("Command 'market view %d' desc='Click here to id this item'", "%d", "/Command") "%s",
market->mpid, market->mpid, add_space(strlen(buf2), 6));
ch_printf(ch, "&c&w%s> " MXPFTAG("PCommand 'market buy %d 1' desc='Click here to buy this item'", "&w&W%s", "/PCommand")
"%s&w&W %-2d &w&c%-10d &w&C%-10d ",
buf, market->mpid, market->obj->short_descr, add_wspace(strlen_color(market->obj->short_descr), 30),
market->count, market->obj->cost, market->cost);
ch_printf(ch, MXPFTAG("Command 'market list itemtype %s' desc='Click here to view other items of this itemtype'", "&w&G%s", "/Command")
"%s &w&O%-15s\n\r", item_type_name(market->obj), item_type_name(market->obj),
add_wspace(strlen(item_type_name(market->obj)), 14), market->name);
}
}
return;
}
send_to_char("Your options are: all name maxcost mincost rangecost itemtype\n\r", ch);
return;
}
if (!str_cmp(arg1, "sell"))
{
argument = one_argument(argument, arg2);
argument = one_argument(argument, arg3);
argument = one_argument(argument, arg4);
if ((obj = get_obj_carry(ch, arg2)) == NULL)
{
send_to_char("You don't have that item in your inventory.\n\r", ch);
return;
}
if (IS_OBJ_STAT(obj, ITEM_NOGIVE) || IS_OBJ_STAT(obj, ITEM_NODROP) || IS_OBJ_STAT(obj, ITEM_ARTIFACT))
{
send_to_char("You cannot attempt to sell an item with a nogive/nodrop/artifact flag on it.\n\r", ch);
return;
}
if (obj->first_content)
{
send_to_char("You cannot sell a container with something in it.\n\r", ch);
return;
}
if (atoi(arg3) <= 0 && str_cmp(arg3, "all"))
{
send_to_char("You need to specify a number of the item to sell or type all.\n\r", ch);
return;
}
if (arg3[0] == '\0')
{
count = 1;
}
else
{
if (atoi(arg3) > 0)
{
if (obj->count < atoi(arg3))
{
ch_printf(ch, "You only have %d of those. Turn off combine in config to see how they are matched.\n\r", obj->count);
return;
}
if (obj->count == atoi(arg3))
count = -1;
else
count = atoi(arg3);
}
else if (!str_cmp(arg3, "all"))
{
count = -1;
}
else
{
send_to_char("Invalid option.\n\r", ch);
return;
}
}
if (arg4[0] == '\0')
{
price = obj->cost;
}
else
{
if (!str_cmp(arg4, "lowest"))
{
price = UMAX(1, obj->cost/10);
}
else if (atoi(arg4) < UMAX(1, obj->cost/10))
{
send_to_char("Asking price cannot be lower than 1/10 the cost of the object.\n\r", ch);
return;
}
else
{
price = atoi(arg4);
}
}
if (!str_cmp(argument, "yes"))
sellname = 1;
CREATE(market, MARKET_DATA, 1);
market->mpid = ++start_marketpid;
market->cost = price;
if (count == -1)
market->count = obj->count;
else
market->count = count;
market->pid = ch->pcdata->pid;
if (sellname)
market->name = STRALLOC(ch->name);
else
market->name = STRALLOC("Unlisted");
if (count == -1)
{
obj_from_char(obj);
obj->count = 1;
market->obj = obj;
}
else
{
rest = separate_obj(obj);
obj_from_char(obj);
obj->count = 1;
market->obj = obj;
rest->count = rest->count - market->count + 1;
}
market->scount = market->count;
LINK(market, first_market, last_market, next, prev);
save_market_data();
ch_printf(ch, "You have put up %d of %s for sale.\n\r", market->count, market->obj->short_descr);
return;
}
do_market(ch, "");
return;
}
/* Make objects in rooms that are nofloor fall - Scryn 1/23/96 */
void obj_fall(OBJ_DATA * obj, bool through)
{
EXIT_DATA *pexit;
ROOM_INDEX_DATA *to_room;
static int fall_count;
char buf[MSL];
static bool is_falling; /* Stop loops from the call to obj_to_room() -- Altrag */
if (!obj->in_room || is_falling)
return;
if (fall_count > 30)
{
bug("object falling in loop more than 30 times", 0);
extract_obj(obj);
fall_count = 0;
return;
}
if (xIS_SET(obj->in_room->room_flags, ROOM_NOFLOOR) && CAN_GO(obj, DIR_DOWN) && !IS_OBJ_STAT(obj, ITEM_MAGIC))
{
pexit = get_exit(obj->in_room, DIR_DOWN);
to_room = pexit->to_room;
if (through)
fall_count++;
else
fall_count = 0;
if (obj->in_room == to_room)
{
sprintf(buf, "Object falling into same room, room %d", to_room->vnum);
bug(buf, 0);
extract_obj(obj);
return;
}
if (obj->in_room->first_person)
{
act(AT_PLAIN, "$p falls far below...", obj->in_room->first_person, obj, NULL, TO_ROOM);
act(AT_PLAIN, "$p falls far below...", obj->in_room->first_person, obj, NULL, TO_CHAR);
}
obj_from_room(obj);
is_falling = TRUE;
obj = obj_to_room(obj, to_room, obj->in_room->first_person);
is_falling = FALSE;
if (obj->in_room->first_person)
{
act(AT_PLAIN, "$p falls from above...", obj->in_room->first_person, obj, NULL, TO_ROOM);
act(AT_PLAIN, "$p falls from above...", obj->in_room->first_person, obj, NULL, TO_CHAR);
}
if (!xIS_SET(obj->in_room->room_flags, ROOM_NOFLOOR) && through)
{
/* int dam = (int)9.81*sqrt(fall_count*2/9.81)*obj->weight/2;
*/ int dam = fall_count * obj->weight / 2;
/* Damage players */
if (obj->in_room->first_person && number_percent() > 15)
{
CHAR_DATA *rch;
CHAR_DATA *vch = NULL;
int chcnt = 0;
for (rch = obj->in_room->first_person; rch; rch = rch->next_in_room, chcnt++)
if (number_range(0, chcnt) == 0)
vch = rch;
act(AT_WHITE, "$p falls on $n!", vch, obj, NULL, TO_ROOM);
act(AT_WHITE, "$p falls on you!", vch, obj, NULL, TO_CHAR);
damage(vch, vch, dam, TYPE_UNDEFINED, 0, -1);
}
}
obj_fall(obj, TRUE);
}
return;
}
/* Scryn, by request of Darkur, 12/04/98 */
/* Reworked recursive_note_find to fix crash bug when the note was left
* blank. 7/6/98 -- Shaddai
*/
void do_findnote(CHAR_DATA * ch, char *argument)
{
OBJ_DATA *obj;
if (IS_NPC(ch))
{
send_to_char("Huh?\n\r", ch);
return;
}
if (argument[0] == '\0')
{
send_to_char("You must specify at least one keyword.\n\r", ch);
return;
}
obj = recursive_note_find(ch->first_carrying, argument);
if (obj)
{
if (obj->in_obj)
{
obj_from_obj(obj);
obj = obj_to_char(obj, ch);
}
wear_obj(ch, obj, TRUE, -1);
}
else
send_to_char("Note not found.\n\r", ch);
return;
}
OBJ_DATA *recursive_note_find(OBJ_DATA * obj, char *argument)
{
OBJ_DATA *returned_obj;
bool match = TRUE;
char *argcopy;
char *subject;
char arg[MIL];
char subj[MSL];
if (!obj)
return NULL;
switch (obj->item_type)
{
case ITEM_PAPER:
if ((subject = get_extra_descr("_subject_", obj->first_extradesc)) == NULL)
break;
sprintf(subj, "%s", strlower(subject));
subject = strlower(subj);
argcopy = argument;
while (match)
{
argcopy = one_argument(argcopy, arg);
if (arg[0] == '\0')
break;
if (!strstr(subject, arg))
match = FALSE;
}
if (match)
return obj;
break;
case ITEM_CONTAINER:
case ITEM_CORPSE_NPC:
case ITEM_CORPSE_PC:
if (obj->first_content)
{
returned_obj = recursive_note_find(obj->first_content, argument);
if (returned_obj)
return returned_obj;
}
break;
default:
break;
}
return recursive_note_find(obj->next_content, argument);
}
/* Junk command installed by Shai'tan 7-25-99
Code courtesy of Stu, from the mailing list. Allows player to
destroy item in inventory. */
void do_junk(CHAR_DATA * ch, char *argument)
{
OBJ_DATA *obj, *obj_next;
char arg[MIL];
char *chk;
bool found = FALSE;
argument = one_argument(argument, arg);
if (arg[0] == '\0')
{
send_to_char("Junk what?\n\r", ch);
return;
}
chk = arg;
if (IS_NPC(ch) && xIS_SET(ch->act, ACT_MILITARY))
{
send_to_char("You cannot do that.\n\r", ch);
return;
}
found = FALSE;
for (obj = ch->first_carrying; obj; obj = obj_next)
{
obj_next = obj->next_content;
if ((nifty_is_name(chk, obj->name)) && can_see_obj(ch, obj) && obj->wear_loc == WEAR_NONE)
{
found = TRUE;
break;
}
}
if (found == TRUE)
{
separate_obj(obj);
obj_from_char(obj);
extract_obj(obj);
act(AT_ACTION, "$n junks $p.", ch, obj, NULL, TO_ROOM);
act(AT_ACTION, "You junk $p.", ch, obj, NULL, TO_CHAR);
}
return;
}
int get_used_imbueslots(OBJ_DATA *obj)
{
int cnt = 0;
IMBUE_DATA *imbue;
for (imbue = obj->first_imbue; imbue; imbue = imbue->next)
{
if (imbue->plevel == -1)
continue;
if (imbue->plevel == 0)
cnt++;
else
cnt += imbue->plevel;
}
return cnt;
}
extern int top_affect;
void save_sysdata args((SYSTEM_DATA sys));
//1000 - Damage 1001 - Durability 1002 - TohitBash 1003 - TohitStab 1004 - TohitSlash
//1005 - Weight 1006 - Shieldlag 1007 - Blocking % 1008 - Proj Range 1009 - Parry Chance 1010 - Stop Parry
//1011 - SpellSN 1012 - SpellStr 1013 - Unbeakable 1014 - Nodisarm 1015 - Sanctified 1016 - Change Size
//1017 - Saves
void set_otheraff_gem(int type, int value, OBJ_DATA *obj, int gemnum)
{
AFFECT_DATA *paf;
if (type == 1000)
{
if (obj->item_type == ITEM_WEAPON || obj->item_type == ITEM_PROJECTILE || obj->item_type == ITEM_MISSILE_WEAPON)
{
obj->value[1] += value;
obj->value[2] += value;
}
}
if (type == 1001)
{
if (obj->item_type == ITEM_WEAPON || obj->item_type == ITEM_MISSILE_WEAPON)
{
obj->value[10] = UMIN(25, obj->value[10]+value);
}
if (obj->item_type == ITEM_ARMOR && !IS_SET(obj->wear_flags, ITEM_WEAR_SHIELD))
{
obj->value[4] = UMIN(25, obj->value[4]+value);
}
if (obj->item_type == ITEM_ARMOR && IS_SET(obj->wear_flags, ITEM_WEAR_SHIELD))
{
obj->value[1] += obj->value[1] * value / 50;
}
}
if (type == 1002)
{
if (obj->item_type == ITEM_WEAPON)
{
obj->value[7] += value;
}
if (obj->item_type == ITEM_ARMOR && !IS_SET(obj->wear_flags, ITEM_WEAR_SHIELD))
{
obj->value[0] += value;
}
}
if (type == 1003)
{
if (obj->item_type == ITEM_WEAPON || obj->item_type == ITEM_PROJECTILE || obj->item_type == ITEM_MISSILE_WEAPON)
{
obj->value[9] += value;
}
if (obj->item_type == ITEM_ARMOR && !IS_SET(obj->wear_flags, ITEM_WEAR_SHIELD))
{
obj->value[2] += value;
}
}
if (type == 1004)
{
if (obj->item_type == ITEM_WEAPON)
{
obj->value[8] += value;
}
if (obj->item_type == ITEM_ARMOR && !IS_SET(obj->wear_flags, ITEM_WEAR_SHIELD))
{
obj->value[1] += value;
}
}
if (type == 1005)
obj->weight = UMAX(.01, obj->weight-=abs(value));
if (type == 1006)
{
if (obj->item_type == ITEM_ARMOR && IS_SET(obj->wear_flags, ITEM_WEAR_SHIELD))
obj->value[3] = UMAX(0, obj->value[3]-abs(value));
}
if (type == 1007)
{
if (obj->item_type == ITEM_ARMOR && IS_SET(obj->wear_flags, ITEM_WEAR_SHIELD))
obj->value[2] += value;
}
if (type == 1008)
{
if (obj->item_type == ITEM_MISSILE_WEAPON)
obj->value[4] += value;
}
if (type == 1009)
{
if (obj->item_type == ITEM_WEAPON)
obj->value[12] += value;
}
if (type == 1010)
{
if (obj->item_type == ITEM_WEAPON)
obj->value[13] += value;
}
if (type == 1011)
{
if (obj->item_type == ITEM_WEAPON)
obj->value[4] = value;
}
if (type == 1012)
{
if (obj->item_type == ITEM_WEAPON)
obj->value[5] = value;
}
if (type == 1013)
{
xSET_BIT(obj->extra_flags, ITEM_NOBREAK);
}
if (type == 1014)
{
xSET_BIT(obj->extra_flags, ITEM_NODISARM);
}
if (type == 1015)
{
xSET_BIT(obj->extra_flags, ITEM_SANCTIFIED);
}
if (type == 1016)
{
if (obj->item_type == ITEM_WEAPON)
obj->value[3] = URANGE(1, obj->value[3]+value, 12);
}
if (type == 1017)
{
CREATE(paf, AFFECT_DATA, 1);
paf->type = -1;
paf->duration = -1;
paf->location = 20;
paf->modifier = value;
paf->gemnum = gemnum;
xCLEAR_BITS(paf->bitvector);
paf->next = NULL;
LINK(paf, obj->first_affect, obj->last_affect, next, prev);
++top_affect;
CREATE(paf, AFFECT_DATA, 1);
paf->type = -1;
paf->duration = -1;
paf->location = 21;
paf->modifier = value;
paf->gemnum = gemnum;
xCLEAR_BITS(paf->bitvector);
paf->next = NULL;
LINK(paf, obj->first_affect, obj->last_affect, next, prev);
++top_affect;
CREATE(paf, AFFECT_DATA, 1);
paf->type = -1;
paf->duration = -1;
paf->location = 22;
paf->modifier = value;
paf->gemnum = gemnum;
xCLEAR_BITS(paf->bitvector);
paf->next = NULL;
LINK(paf, obj->first_affect, obj->last_affect, next, prev);
++top_affect;
CREATE(paf, AFFECT_DATA, 1);
paf->type = -1;
paf->duration = -1;
paf->location = 23;
paf->modifier = value;
paf->gemnum = gemnum;
xCLEAR_BITS(paf->bitvector);
paf->next = NULL;
LINK(paf, obj->first_affect, obj->last_affect, next, prev);
++top_affect;
CREATE(paf, AFFECT_DATA, 1);
paf->type = -1;
paf->duration = -1;
paf->location = 24;
paf->modifier = value;
paf->gemnum = gemnum;
xCLEAR_BITS(paf->bitvector);
paf->next = NULL;
LINK(paf, obj->first_affect, obj->last_affect, next, prev);
++top_affect;
}
}
/* Connect pieces of an ITEM -- Originally from ACK! *
* Modified for Smaug by Zarius 5/19/2000 *
* *
* Zarius' connect-item code altered for *
* Rafermand mini-nodes by Skan 1/26/02 *
* *
* do_connect altered... changed to do_setgem */
//Changed altogether for something else -- Xerves
void do_setgem(CHAR_DATA * ch, char *argument)
{
OBJ_DATA *first_obj;
OBJ_DATA *second_obj;
IMBUE_DATA *imbue;
AFFECT_DATA *paf;
int usedslots;
char arg1[MSL], arg2[MAX_STRING_LENGTH];
argument = one_argument(argument, arg1);
argument = one_argument(argument, arg2);
if (arg1[0] == '\0' || arg2[0] == '\0')
{
send_to_char("Syntax: setgem <gem> <item receiving gem>.\n\r", ch);
return;
}
if ((first_obj = get_obj_carry(ch, arg1)) == NULL)
{
send_to_char("You must be holding both parts!!\n\r", ch);
return;
}
separate_obj(first_obj);
if ((second_obj = get_obj_carry(ch, arg2)) == NULL)
{
send_to_char("You mus be holding both parts!!\n\r", ch);
return;
}
separate_obj(second_obj);
if (first_obj->item_type != ITEM_TGEM)
{
send_to_char("The first item is not a gem.\n\r", ch);
return;
}
if (first_obj->value[12] == -1)
usedslots = 0;
else if (first_obj->value[12] == 0)
usedslots = 1;
else
usedslots = first_obj->value[12];
if (get_used_imbueslots(second_obj)+usedslots > second_obj->imbueslots)
{
send_to_char("The item is already full and cannot be imbued anymore.\n\r", ch);
return;
}
CREATE(imbue, IMBUE_DATA, 1);
LINK(imbue, second_obj->first_imbue, second_obj->last_imbue, next, prev);
imbue->type = first_obj->value[0];
imbue->sworth = first_obj->value[1];
imbue->lowvalue = first_obj->value[2];
imbue->highvalue = first_obj->value[3];
imbue->value = number_range(imbue->lowvalue, imbue->highvalue);
imbue->type2 = first_obj->value[4];
imbue->sworth2 = first_obj->value[5];
imbue->lowvalue2 = first_obj->value[6];
imbue->highvalue2 = first_obj->value[7];
imbue->value2 = number_range(imbue->lowvalue2, imbue->highvalue2);
imbue->type3 = first_obj->value[8];
imbue->sworth3 = first_obj->value[9];
imbue->lowvalue3 = first_obj->value[10];
imbue->highvalue3 = first_obj->value[11];
imbue->value3 = number_range(imbue->lowvalue3, imbue->highvalue3);
imbue->plevel = first_obj->value[12];
imbue->gemnum = ++sysdata.top_gem_num;
save_sysdata(sysdata);
second_obj->sworthrestrict += imbue->sworth;
second_obj->sworthrestrict += imbue->sworth2;
second_obj->sworthrestrict += imbue->sworth3;
if (imbue->type > 0 && imbue->type < 1000)
{
CREATE(paf, AFFECT_DATA, 1);
paf->type = -1;
paf->duration = -1;
paf->location = imbue->type;
paf->modifier = imbue->value;
paf->gemnum = imbue->gemnum;
xCLEAR_BITS(paf->bitvector);
paf->next = NULL;
LINK(paf, second_obj->first_affect, second_obj->last_affect, next, prev);
++top_affect;
}
if (imbue->type >= 1000)
{
set_otheraff_gem(imbue->type, imbue->value, second_obj, imbue->gemnum);
}
if (imbue->type2 > 0 && imbue->type2 < 1000)
{
CREATE(paf, AFFECT_DATA, 1);
paf->type = -1;
paf->duration = -1;
paf->location = imbue->type2;
paf->modifier = imbue->value2;
paf->gemnum = imbue->gemnum;
xCLEAR_BITS(paf->bitvector);
paf->next = NULL;
LINK(paf, second_obj->first_affect, second_obj->last_affect, next, prev);
++top_affect;
}
if (imbue->type2 >= 1000)
{
set_otheraff_gem(imbue->type2, imbue->value2, second_obj, imbue->gemnum);
}
if (imbue->type3 > 0 && imbue->type3 < 1000)
{
CREATE(paf, AFFECT_DATA, 1);
paf->type = -1;
paf->duration = -1;
paf->location = imbue->type3;
paf->modifier = imbue->value3;
paf->gemnum = imbue->gemnum;
xCLEAR_BITS(paf->bitvector);
paf->next = NULL;
LINK(paf, second_obj->first_affect, second_obj->last_affect, next, prev);
++top_affect;
}
if (imbue->type3 >= 1000)
{
set_otheraff_gem(imbue->type3, imbue->value3, second_obj, imbue->gemnum);
}
act(AT_ACTION, "$n sets $p in $P.", ch, first_obj, second_obj, TO_ROOM);
act(AT_ACTION, "You set $p in $P.", ch, first_obj, second_obj, TO_CHAR);
extract_obj(first_obj);
return;
}
/*Start Alchemy Section - Corellon - 7/15/02*/
int get_alch_success(CHAR_DATA *ch, OBJ_DATA *obj)
{
return URANGE(30, (30 + 2*get_curr_int(ch) + get_curr_wis(ch) + obj->value[0] + URANGE(-6, get_curr_lck(ch)-14, 6)), 90);
}
void do_mixpotion(CHAR_DATA *ch, char *argument)
{
char arg[MIL];
char arg2[MIL];
char arg3[MIL];
char arg4[MIL];
char buf1[MSL];
char buf2[MSL];
char buf3[MSL];
OBJ_DATA *obj;
OBJ_DATA *obj2;
OBJ_DATA *obj3;
OBJ_DATA *obj4;
int mod;
int perm;
argument = one_argument(argument,arg);
argument = one_argument(argument,arg2);
argument = one_argument(argument,arg3);
argument = one_argument(argument,arg4);
if (IS_NPC(ch))
{
send_to_char("Not for NPCs.\n\r", ch);
return;
}
if(arg[0] == '\0' || arg2[0] == '\0' || arg3[0] == '\0' || arg4[0] == '\0')
{
send_to_char("Usage: mixpotion <power reagant> <affecting reagant> <flask> <mortar>\n\r",ch);
return;
}
if((obj = get_obj_carry(ch,arg)) == NULL)
{
send_to_char("You don't have the specified power reagant.\n\r",ch);
send_to_char("Usage: mixpotion <power reagant> <affecting reagant> <flask> <mortar>\n\r",ch);
return;
}
if((obj2 = get_obj_carry(ch,arg2)) == NULL)
{
send_to_char("You don't have the specified affect reagant.\n\r",ch);
send_to_char("Usage: mixpotion <power reagant> <affecting reagant> <flask> <mortar>\n\r",ch);
return;
}
if((obj3 = get_obj_carry(ch,arg3)) == NULL)
{
send_to_char("You don't have that container.\n\r",ch);
send_to_char("Usage: mixpotion <power reagant> <affecting reagant> <flask> <mortar>\n\r",ch);
return;
}
if((obj4 = get_obj_carry(ch,arg4)) == NULL)
{
send_to_char("You don't have that mortar and pestle\n\r",ch);
send_to_char("Usage: mixpotion <power reagant> <affecting reagant> <flask> <mortar>\n\r",ch);
return;
}
if( obj3->pIndexData->vnum != OBJ_VNUM_FLASK_BREWING || obj3->value[1] != -1)
{
send_to_char( "You must be holding an empty flask to mix a potion.\n\r", ch );
return;
}
if (!xIS_SET(obj->extra_flags,ITEM_POWREAG))
{
send_to_char( "That's not a proper power reagant!\n\r",ch);
return;
}
if (!xIS_SET(obj2->extra_flags,ITEM_AFFREAG))
{
send_to_char( "That's not a proper reagant!\n\r", ch );
return;
}
if(!xIS_SET(obj4->extra_flags,ITEM_MORTAR))
{
send_to_char("Not a mortar\n\r",ch);
return;
}
if(obj->value[5] >= 1008 && xIS_SET(obj2->extra_flags,ITEM_PERMREAG))
{
perm = TRUE;
}
else if((obj->value[5] >= 1008 && !xIS_SET(obj2->extra_flags,ITEM_PERMREAG)) || (obj->value[5] < 1008 && xIS_SET(obj2->extra_flags,ITEM_PERMREAG)))
{
perm = FALSE;
}
else
{
perm = 2;
}
if(get_alch_success(ch,obj4) < number_range(1,100))
{
separate_obj(obj3);
/* create the potion */
mod = obj2->value[1]; // set spell - will be expanded later to account for adding in new skills
obj3->value[1] = mod;
if(perm==TRUE) //is it perm?
{
obj3->item_type = ITEM_TREASURE;
obj3->value[0] = obj2->value[0];
xTOGGLE_BIT(obj3->extra_flags,ITEM_MIXED);
STRFREE(obj3->description);
sprintf(buf2,"A flask labelled 'permanent' contains a strange mixed liquid");
obj3->description = STRALLOC(buf2);
STRFREE(obj3->short_descr);
sprintf(buf1, "permanent potion");
obj3->short_descr = STRALLOC( aoran(buf1));
STRFREE(obj3->name);
sprintf(buf3, "flask permanent");
obj3->name = STRALLOC(buf3);
separate_obj(obj2);
extract_obj(obj2);
separate_obj(obj);
extract_obj(obj);
return;
}
else if(perm==2)
{
obj3->value[5] = obj->value[5];
sprintf(buf1, "%s potion", skill_table[mod]->name);
STRFREE(obj3->short_descr);
obj3->short_descr = STRALLOC( aoran(buf1) );
sprintf(buf2, "A flask labelled '%s' contains a strange, mixed liquid.", skill_table[mod]->name);
STRFREE(obj3->description);
obj3->description = STRALLOC(buf2);
sprintf(buf3, "flask potion %s", skill_table[mod]->name);
STRFREE(obj3->name);
obj3->name = STRALLOC(buf3);
}
else
{
send_to_char("You are trying to mix a non-permanent and a permanent reagant. BAD PLAYER, BAD!!\n\r",ch);
return;
}
}
else
{
if(perm==FALSE)
{
send_to_char("You are trying to mix a non-permanent and a permanent reagant. BAD PLAYER, BAD!!\n\r",ch);
return;
}
send_to_char("You failed.\n\r",ch);
}
/* remove the reagants from inventory */
separate_obj(obj2);
extract_obj(obj2);
separate_obj(obj);
extract_obj(obj);
return;
}
void do_enhance(CHAR_DATA *ch, char *argument)
{
char arg[MIL];
char arg2[MIL];
char arg3[MIL];
OBJ_DATA *obj;
OBJ_DATA *obj2;
OBJ_DATA *obj3;
AFFECT_DATA *paf;
argument = one_argument(argument,arg);
argument = one_argument(argument,arg2);
argument = one_argument(argument,arg3);
if (IS_NPC(ch))
{
send_to_char("Not for NPCs.\n\r", ch);
return;
}
if((obj = get_obj_carry(ch,arg)) == NULL)
{
send_to_char("Usage: modweapon <enhancer> <weapon> <mortar>\n\r",ch);
return;
}
if((obj2 = get_obj_carry(ch,arg2)) == NULL)
{
send_to_char("Usage: modweapon <enhancer> <weapon> <mortar> \n\r",ch);
return;
}
if((obj3 = get_obj_carry(ch,arg3)) == NULL)
{
send_to_char("Usage: modweapon <enhancer> <weapon> <mortar> \n\r",ch);
return;
}
if(!xIS_SET(obj->extra_flags,ITEM_MIXED))
{
send_to_char("That is not potion with weapon enhancing power\n\r",ch);
return;
}
if(xIS_SET(obj2->extra_flags,ITEM_MAGIC))
{
send_to_char("This item is magical and cannot be enhanced.\n\r",ch);
return;
}
if(!xIS_SET(obj3->extra_flags,ITEM_MORTAR))
{
send_to_char("Usage: modweapon <enhancer> <weapon> <mortar> \n\r",ch);
return;
}
/* Add the appropriate affects */
if(get_alch_success(ch,obj3) < number_range(1,100))
{
CREATE(paf, AFFECT_DATA, 1);
paf->type = -1;
paf->duration = -1;
if(obj->value[0] == 0 || obj->value[0] > 18) // If number is out of range, default to wearspell
{
paf->location = APPLY_WEARSPELL;
}
else
{
paf->location = obj->value[0];
}
paf->modifier = obj->value[1];
LINK(paf, obj2->first_affect, obj2->last_affect, next, prev);
send_to_char("You have enhanced your weapon.\n\r", ch);
xTOGGLE_BIT(obj2->extra_flags,ITEM_MAGIC);
}
else
{
send_to_char("You failed.\n\r",ch);
}
separate_obj(obj); //remove items
extract_obj(obj);
return;
}