/****************************************************************************
* [S]imulated [M]edieval [A]dventure multi[U]ser [G]ame | *
* -----------------------------------------------------------| \\._.// *
* SmaugWiz (C) 1998 by Russ Pillsbury (Windows NT version) | (0...0) *
* -----------------------------------------------------------| ).:.( *
* SMAUG (C) 1994, 1995, 1996 by Derek Snider | {o o} *
* -----------------------------------------------------------| / ' ' \ *
* SMAUG code team: Thoric, Altrag, Blodkai, Narn, Haus, |~'~.VxvxV.~'~*
* Scryn, Swordbearer, Rennard, Tricops, and Gorog. | *
* ------------------------------------------------------------------------ *
* 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 Staerfeldt, Tom Madsen, and Katja Nyboe. *
****************************************************************************/
#include "stdafx.h"
#include "smaug.h"
#include "bitvector.h"
#include "SysData.h"
#include "skill.h"
#include "objects.h"
#include "rooms.h"
#include "deity.h"
#include "Exits.h"
#include "SmaugFiles.h"
#include "descriptor.h"
#include "character.h"
// double sqrt (double x);
// External functions
void show_list_to_char (CObjData *list, CCharacter *ch,
BOOL fShort, BOOL fShowNothing);
// Local functions.
void get_obj (CCharacter *ch, CObjData *obj, CObjData *container);
BOOL remove_obj (CCharacter *ch, int iWear, BOOL fReplace);
void wear_obj (CCharacter *ch, CObjData *obj, BOOL fReplace,
short wear_bit);
// how resistant an object is to damage -Thoric
short get_obj_resistance (CObjData *obj)
{
short resist;
resist = number_fuzzy (MAX_ITEM_IMPACT);
/* magical items are more resistant */
if (obj->IsMagic ())
resist += number_fuzzy (12);
/* metal objects are definately stronger */
if (obj->IsMetal ())
resist += number_fuzzy (5);
/* organic objects are most likely weaker */
if (obj->IsOrganic ())
resist -= number_fuzzy (5);
/* blessed objects should have a little bonus */
if (obj->IsBlessed ())
resist += number_fuzzy (5);
/* lets make store inventory pretty tough */
if (obj->IsInventory ())
resist += 20;
/* okay... let's add some bonus/penalty for item level... */
resist += (obj->level / 10) - 2;
/* and lasty... take armor or weapon's condition into consideration */
if (obj->item_type == ITEM_ARMOR || obj->item_type == ITEM_WEAPON)
resist += (obj->value[0] / 2) - 2;
return URANGE (10, resist, 99);
}
void get_obj (CCharacter *ch, CObjData *obj, CObjData *container)
{
int weight;
if (! obj->CanWear (ITEM_TAKE)
&& (ch->GetLevel () < SysData.GetObjNoTakeLevel)) {
ch->SendText ("You can't take that.\n\r");
return;
}
if (obj->IsPrototype () && ! can_take_proto (ch)) {
ch->SendText ("A godly force prevents you from getting close to it.\n\r");
return;
}
if (ch->carry_number + get_obj_number (obj) > ch->GetMaxItems ()) {
act (AT_PLAIN, "$d: you can't carry that many items.",
ch, NULL, obj->GetName (), TO_CHAR);
return;
}
if (obj->IsCovering ())
weight = obj->weight;
else
weight = get_obj_weight (obj);
if (ch->GetCarryWeight () + weight > can_carry_w (ch)) {
act (AT_PLAIN, "$d: you can't carry that much weight.",
ch, NULL, obj->GetName (), TO_CHAR);
return;
}
if (container) {
act (AT_ACTION, container->IsCovering () ?
"You get $p from beneath $P." : "You get $p from $P",
ch, obj, container, TO_CHAR);
act (AT_ACTION, container->IsCovering () ?
"$n gets $p from beneath $P." : "$n gets $p from $P",
ch, obj, container, TO_ROOM);
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);
}
// Clan storeroom checks
if (ch->GetInRoom ()->IsClanStoreRoom ()
&& (!container || container->carried_by == NULL)) {
POSITION pos = ClanList.GetHeadPosition ();
while (pos) {
CClanData *clan = ClanList.GetNext (pos);
if (clan->storeroom == ch->GetInRoom ()->vnum)
clan->SaveStoreroom (ch);
}
}
if (obj->item_type != ITEM_CONTAINER)
check_for_trap (ch, obj, TRAP_GET);
if (char_died (ch))
return;
if (obj->item_type == ITEM_MONEY) {
ch->AddGold (obj->value[0]);
extract_obj (obj);
}
else obj = obj_to_char (obj, ch);
if (char_died (ch) || obj_extracted (obj))
return;
oprog_get_trigger (ch, obj);
}
void do_get (CCharacter *ch, char *argument)
{
char arg1 [MAX_INPUT_LENGTH];
char arg2 [MAX_INPUT_LENGTH];
CObjData *obj;
CObjData *container;
short number;
BOOL found;
argument = one_argument (argument, arg1);
if (is_number (arg1))
{
number = atoi (arg1);
if (number < 1)
{
ch->SendText ("That was easy...\n\r");
return;
}
if ((ch->carry_number + number) > ch->GetMaxItems ())
{
ch->SendText ("You can't carry that many.\n\r");
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')
{
ch->SendText ("Get what?\n\r");
return;
}
if (ms_find_obj (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->GetInRoom ()->GetContentList ());
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 (SysData.IsSaveOnGet ())
save_char_obj (ch);
} else {
short cnt = 0;
BOOL fAll;
char *chk;
if (ch->GetInRoom ()->IsDonationRoom ())
{
ch->SendText ("The gods frown upon such a display of greed!\n\r");
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;
POSITION Rpos = ch->GetInRoom ()->GetHeadContentPos ();
while (obj = ch->GetInRoom ()->GetNextContent (Rpos)) {
if ((fAll || nifty_is_name (chk, obj->GetName ()))
&& 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, NULL);
if (char_died (ch)
|| ch->carry_number >= ch->GetMaxItems ()
|| ch->GetCarryWeight () >= can_carry_w (ch)
|| (number && cnt >= number)) {
if (SysData.IsSaveOnGet () && !char_died (ch))
save_char_obj (ch);
return;
}
}
}
if (!found)
{
if (fAll)
ch->SendText ("I see nothing here.\n\r");
else
act (AT_PLAIN, "I see no $T here.", ch, NULL, chk, TO_CHAR);
}
else if (SysData.IsSaveOnGet ())
save_char_obj (ch);
}
}
else
{
/* 'get ... container' */
if (!str_cmp (arg2, "all") || !str_prefix ("all.", arg2))
{
ch->SendText ("You can't do that.\n\r");
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 (! container->IsCovering ())
{
ch->SendText ("That's not a container.\n\r");
return;
}
if (ch->GetCarryWeight () + container->weight > can_carry_w (ch))
{
ch->SendText ("It's too heavy for you to lift.\n\r");
return;
}
break;
case ITEM_CONTAINER:
case ITEM_CORPSE_NPC:
break;
case ITEM_CORPSE_PC:
{
char name[MAX_INPUT_LENGTH];
CCharacter *gch;
const char *pd;
if (ch->IsNpc ())
{
ch->SendText ("You can't do that.\n\r");
return;
}
pd = container->GetShortDescr ();
pd = one_argument (pd, name);
pd = one_argument (pd, name);
pd = one_argument (pd, name);
pd = one_argument (pd, name);
if (container->IsClanCorpse ()
&& !ch->IsNpc () && (get_timer (ch, TIMER_PKILLED) > 0)
&& str_cmp (name, ch->GetName ()))
{
ch->SendText ("You cannot loot from that corpse...yet.\n\r");
return;
}
if (container->IsClanCorpse ()
&& !ch->IsNpc () && ch->IsPkiller ())
break;
if (str_cmp (name, ch->GetName ()) && !ch->IsImmortal ())
{
BOOL fGroup;
fGroup = FALSE;
for (gch = first_char; gch; gch = gch->GetNext ())
{
if (!gch->IsNpc ()
&& is_same_group (ch, gch)
&& !str_cmp (name, gch->GetName ()))
{
fGroup = TRUE;
break;
}
}
if (!fGroup)
{
ch->SendText ("That's someone else's corpse.\n\r");
return;
}
}
}
}
if (! container->IsCovering ()
&& IS_SET (container->value[1], CONT_CLOSED))
{
act (AT_PLAIN, "The $d is closed.", ch, NULL, container->GetName (), TO_CHAR);
return;
}
if (number <= 1 && str_cmp (arg1, "all") && str_prefix ("all.", arg1))
{
/* 'get obj container' */
obj = get_obj_list (ch, arg1, container->GetContentList ());
if (!obj)
{
act (AT_PLAIN, container->IsCovering () ?
"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);
get_obj (ch, obj, container);
check_for_trap (ch, container, TRAP_GET);
if (char_died (ch))
return;
if (SysData.IsSaveOnGet ())
save_char_obj (ch);
}
else
{
int cnt = 0;
BOOL fAll;
char *chk;
/* 'get all container' or 'get all.obj container' */
if (container->IsDonation ())
{
ch->SendText ("The gods frown upon such an act of greed!\n\r");
return;
}
if (!str_cmp (arg1, "all"))
fAll = TRUE;
else
fAll = FALSE;
if (number > 1)
chk = arg1;
else
chk = &arg1[4];
found = FALSE;
POSITION Cpos = container->GetHeadContentPos ();
while (obj = container->GetNextContent (Cpos)) {
if ((fAll || nifty_is_name (chk, obj->GetName ()))
&& 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)
|| ch->carry_number >= ch->GetMaxItems ()
|| ch->GetCarryWeight () >= can_carry_w (ch)
|| (number && cnt >= number))
return;
}
}
if (!found)
{
if (fAll)
act (AT_PLAIN, container->IsCovering () ?
"I see nothing beneath the $T." :
"I see nothing in the $T.",
ch, NULL, arg2, TO_CHAR);
else
act (AT_PLAIN, container->IsCovering () ?
"I see nothing like that beneath the $T." :
"I see nothing like that in the $T.",
ch, NULL, arg2, TO_CHAR);
}
else
check_for_trap (ch, container, TRAP_GET);
if (char_died (ch))
return;
if (found && (SysData.IsSaveOnGet ()))
save_char_obj (ch);
}
}
return;
}
void do_put (CCharacter *ch, char *argument)
{
char arg1 [MAX_INPUT_LENGTH];
char arg2 [MAX_INPUT_LENGTH];
CObjData *container;
CObjData *obj;
short count;
int number;
BOOL save_char = FALSE;
argument = one_argument (argument, arg1);
if (is_number (arg1)) {
number = atoi (arg1);
if (number < 1) {
ch->SendText ("That was easy...\n\r");
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")) && argument [0] != '\0')
argument = one_argument (argument, arg2);
if (arg1 [0] == '\0' || arg2 [0] == '\0') {
ch->SendText ("Put what in what?\n\r");
return;
}
if (ms_find_obj (ch))
return;
if (! str_cmp (arg2, "all") || ! str_prefix ("all.", arg2)) {
ch->SendText ("You can't do that.\n\r");
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 && (SysData.IsSaveOnPut ()))
save_char = TRUE;
if (container->IsCovering ()) {
if (ch->GetCarryWeight () + container->weight > can_carry_w (ch)) {
ch->SendText ("It's too heavy for you to lift.\n\r");
return;
}
} else {
if (container->item_type != ITEM_CONTAINER) {
ch->SendText ("That's not a container.\n\r");
return;
}
if (IS_SET (container->value[1], CONT_CLOSED)) {
act (AT_PLAIN, "The $d is closed.", ch, NULL,
container->GetName (), 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) {
ch->SendText ("You do not have that item.\n\r");
return;
}
if (obj == container) {
ch->SendText ("You can't fold it into itself.\n\r");
return;
}
if (!can_drop_obj (ch, obj)) {
ch->SendText ("You can't let go of it.\n\r");
return;
}
if ((container->IsCovering ()
&& (get_obj_weight (obj) / obj->count)
> ((get_obj_weight (container) / container->count)
- container->weight))) {
ch->SendText ("It won't fit under there.\n\r");
return;
}
if ((get_obj_weight (obj) / obj->count)
+ (get_obj_weight (container) / container->count)
> container->value [0]) {
ch->SendText ("It won't fit.\n\r");
return;
}
separate_obj (obj);
separate_obj (container);
obj_from_char (obj);
obj = obj_to_obj (obj, container);
check_for_trap (ch, container, TRAP_PUT);
if (char_died (ch))
return;
count = obj->count;
obj->count = 1;
act (AT_ACTION, container->IsCovering ()
? "$n hides $p beneath $P." : "$n puts $p in $P.",
ch, obj, container, TO_ROOM);
act (AT_ACTION, container->IsCovering ()
? "You hide $p beneath $P." : "You put $p in $P.",
ch, obj, container, TO_CHAR);
obj->count = count;
if (save_char)
save_char_obj (ch);
// Clan storeroom check
if (ch->GetInRoom ()->IsClanStoreRoom ()
&& container->carried_by == NULL) {
POSITION pos = ClanList.GetHeadPosition ();
while (pos) {
CClanData *clan = ClanList.GetNext (pos);
if (clan->storeroom == ch->GetInRoom ()->vnum)
ch, clan->SaveStoreroom (ch);
}
}
} else {
BOOL found = FALSE;
int cnt = 0;
BOOL fAll;
char *chk;
if (! str_cmp (arg1, "all"))
fAll = TRUE;
else
fAll = FALSE;
if (number > 1)
chk = arg1;
else
chk = &arg1 [4];
separate_obj (container);
// 'put all container' or 'put all.obj container'
POSITION pos = ch->GetHeadCarryPos ();
while (obj = ch->GetNextCarrying (pos)) {
if ((fAll || nifty_is_name (chk, obj->GetName ()))
&& can_see_obj (ch, *obj)
&& obj->wear_loc == WEAR_NONE
&& obj != container
&& can_drop_obj (ch, obj)
&& get_obj_weight (obj) + get_obj_weight (container)
<= container->value [0]) {
if (number && (cnt + obj->count) > number)
split_obj (obj, number - cnt);
cnt += obj->count;
obj_from_char (obj);
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);
found = TRUE;
check_for_trap (ch, container, TRAP_PUT);
if (char_died (ch))
return;
if (number && cnt >= number)
break;
}
}
// 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;
}
if (save_char)
save_char_obj (ch);
// Clan storeroom check
if (ch->GetInRoom ()->IsClanStoreRoom ()
&& container->carried_by == NULL) {
POSITION pos = ClanList.GetHeadPosition ();
while (pos) {
CClanData *clan = ClanList.GetNext (pos);
if (clan->storeroom == ch->GetInRoom ()->vnum)
clan->SaveStoreroom (ch);
}
}
}
}
void do_drop (CCharacter *ch, char *argument)
{
char arg [MAX_INPUT_LENGTH];
CObjData *obj;
BOOL found;
int number;
argument = one_argument (argument, arg);
if (is_number (arg)) {
number = atoi (arg);
if (number < 1) {
ch->SendText ("That was easy...\n\r");
return;
}
argument = one_argument (argument, arg);
}
else number = 0;
if (arg [0] == '\0') {
ch->SendText ("Drop what?\n\r");
return;
}
if (ms_find_obj (ch))
return;
if (ch->GetInRoom ()->IsNoDrop ()
|| (! ch->IsNpc () && ch->IsLitterBug ())) {
set_char_color (AT_MAGIC, ch);
ch->SendText ("A magical force stops you!\n\r");
set_char_color (AT_TELL, ch);
ch->SendText ("Someone tells you, 'No littering here!'\n\r");
return;
}
if (number > 0) {
// 'drop NNNN coins'
if (! str_cmp (arg, "coins") || !str_cmp (arg, "coin")) {
if (ch->GetGold () < number) {
ch->SendText ("You haven't got that many coins.\n\r");
return;
}
ch->AddGold (-number);
POSITION Rpos = ch->GetInRoom ()->GetHeadContentPos ();
while (obj = ch->GetInRoom ()->GetNextContent (Rpos)) {
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->GetInRoom ());
ch->SendText ("OK.\n\r");
if (SysData.IsSaveOnDrop ())
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) {
ch->SendText ("You do not have that item.\n\r");
return;
}
if (! can_drop_obj (ch, obj)) {
ch->SendText ("You can't let go of it.\n\r");
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->GetInRoom ());
oprog_drop_trigger (ch, obj); // mudprogs
if (char_died (ch) || obj_extracted (obj))
return;
// Clan storeroom saving
if (ch->GetInRoom ()->IsClanStoreRoom ()) {
POSITION pos = ClanList.GetHeadPosition ();
while (pos) {
CClanData *clan = ClanList.GetNext (pos);
if (clan->storeroom == ch->GetInRoom ()->vnum)
clan->SaveStoreroom (ch);
}
}
} 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 (ch->GetInRoom ()->IsNoDropAll ()
|| ch->GetInRoom ()->IsClanStoreRoom ()) {
ch->SendText ("You can't seem to do that here...\n\r");
return;
}
found = FALSE;
POSITION pos = ch->GetHeadCarryPos ();
while (obj = ch->GetNextCarrying (pos)) {
if ((fAll || nifty_is_name (chk, obj->GetName ()))
&& can_see_obj (ch, *obj)
&& obj->wear_loc == WEAR_NONE
&& can_drop_obj (ch, obj)) {
found = TRUE;
if (obj->pIndexData->HasDropProg () && obj->count > 1) {
++cnt;
separate_obj (obj);
obj_from_char (obj);
if (! pos)
pos = ch->GetHeadCarryPos ();
} 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->GetInRoom ());
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 (SysData.IsSaveOnDrop ())
save_char_obj (ch); // duping protector
}
void do_give (CCharacter *ch, char *argument)
{
char arg1 [MAX_INPUT_LENGTH];
char arg2 [MAX_INPUT_LENGTH];
char buf [MAX_INPUT_LENGTH];
CCharacter *victim;
CObjData *obj;
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')
{
ch->SendText ("Give what to whom?\n\r");
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")))
{
ch->SendText ("Sorry, you can't do that.\n\r");
return;
}
argument = one_argument (argument, arg2);
if (!str_cmp (arg2, "to") && argument[0] != '\0')
argument = one_argument (argument, arg2);
if (arg2[0] == '\0')
{
ch->SendText ("Give what to whom?\n\r");
return;
}
if ((victim = get_char_room (ch, arg2)) == NULL)
{
ch->SendText ("They aren't here.\n\r");
return;
}
if (ch->GetGold () < amount)
{
ch->SendText ("Very generous of you, but you haven't got that much gold.\n\r");
return;
}
ch->AddGold (-amount);
victim->AddGold (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 );
ch->SendText ("OK.\n\r");
mprog_bribe_trigger (victim, ch, amount);
if (SysData.IsSaveOnGive () && !char_died (ch))
save_char_obj (ch);
if (SysData.IsSaveOnReceive () && !char_died (victim))
save_char_obj (victim);
return;
}
if ((obj = get_obj_carry (ch, arg1)) == NULL)
{
ch->SendText ("You do not have that item.\n\r");
return;
}
if (obj->wear_loc != WEAR_NONE)
{
ch->SendText ("You must remove it first.\n\r");
return;
}
if ((victim = get_char_room (ch, arg2)) == NULL)
{
ch->SendText ("They aren't here.\n\r");
return;
}
if (!can_drop_obj (ch, obj))
{
ch->SendText ("You can't let go of it.\n\r");
return;
}
if (victim->carry_number + (get_obj_number (obj)/obj->count) > victim->GetMaxItems ())
{
act (AT_PLAIN, "$N has $S hands full.", ch, NULL, victim, TO_CHAR);
return;
}
if (victim->GetCarryWeight () + (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 (obj->IsPrototype () && !can_take_proto (victim))
{
act (AT_PLAIN, "You cannot give that to $N!", ch, NULL, victim, TO_CHAR);
return;
}
separate_obj (obj);
obj_from_char (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 = obj_to_char (obj, victim);
mprog_give_trigger (victim, ch, obj);
if (SysData.IsSaveOnGive () && !char_died (ch))
save_char_obj (ch);
if (SysData.IsSaveOnReceive () && !char_died (victim))
save_char_obj (victim);
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 (CObjData *obj)
{
CCharacter *ch;
obj_ret objcode;
ch = obj->carried_by;
objcode = rNONE;
separate_obj (obj);
if (ch)
act (AT_OBJECT, "($p gets damaged)", ch, obj, NULL, TO_CHAR);
else
if (obj->in_room && (ch = obj->in_room->first_person) != NULL)
{
act (AT_OBJECT, "($p gets damaged)", ch, obj, NULL, TO_ROOM);
act (AT_OBJECT, "($p gets damaged)", ch, obj, NULL, TO_CHAR);
ch = NULL;
}
oprog_damage_trigger (ch, obj);
if (obj_extracted (obj))
return global_objcode;
switch (obj->item_type)
{
default:
make_scraps (obj);
objcode = rOBJ_SCRAPPED;
break;
case ITEM_CONTAINER:
if (--obj->value[3] <= 0)
{
make_scraps (obj);
objcode = rOBJ_SCRAPPED;
}
break;
case ITEM_ARMOR:
if (ch && obj->value[0] >= 1)
ch->AddArmor (apply_ac (obj, obj->wear_loc));
if (--obj->value[0] <= 0)
{
if (! ch->IsPkiller () && !in_arena (ch))
{
make_scraps (obj);
objcode = rOBJ_SCRAPPED;
}
else
obj->value[0] = 1;
}
else
if (ch && obj->value[0] >= 1)
ch->AddArmor (-apply_ac (obj, obj->wear_loc));
break;
case ITEM_WEAPON:
if (--obj->value[0] <= 0)
{
if (! ch->IsPkiller () && !in_arena (ch))
{
make_scraps (obj);
objcode = rOBJ_SCRAPPED;
}
else
obj->value[0] = 1;
}
break;
}
return objcode;
}
/*
* Remove an object.
*/
BOOL remove_obj (CCharacter *ch, int iWear, BOOL fReplace)
{
CObjData *obj, *tmpobj;
if ((obj = get_eq_char (ch, iWear)) == NULL)
return TRUE;
if (!fReplace
&& ch->carry_number + get_obj_number (obj) > ch->GetMaxItems ())
{
act (AT_PLAIN, "$d: you can't carry that many items.",
ch, NULL, obj->GetName (), TO_CHAR);
return FALSE;
}
if (!fReplace)
return FALSE;
if (obj->IsNoRemove ())
{
act (AT_PLAIN, "You can't remove $p.", ch, obj, NULL, TO_CHAR);
return FALSE;
}
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 (CCharacter *ch)
{
if (ch->IsNpc ())
return TRUE;
if (ch->GetPcData ()->learned [gsn_dual_wield])
return TRUE;
return FALSE;
}
/*
* See if char can dual wield at this time -Thoric
*/
BOOL can_dual (CCharacter *ch)
{
if (!could_dual (ch))
return FALSE;
if (get_eq_char (ch, WEAR_DUAL_WIELD))
{
ch->SendText ("You are already wielding two weapons!\n\r");
return FALSE;
}
if (get_eq_char (ch, WEAR_SHIELD))
{
ch->SendText ("You cannot dual wield while holding a shield!\n\r");
return FALSE;
}
if (get_eq_char (ch, WEAR_HOLD))
{
ch->SendText ("You cannot dual wield while holding something!\n\r");
return FALSE;
}
return TRUE;
}
// Check to see if there is room to wear another object on this location
// (Layered clothing support)
BOOL can_layer (CCharacter *ch, CObjData *obj, short wear_loc)
{
CObjData *otmp;
short bitlayers = 0;
short objlayers = obj->pIndexData->layers;
POSITION pos = ch->GetHeadCarryPos ();
while (otmp = ch->GetNextCarrying (pos))
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
void wear_obj (CCharacter *ch, CObjData *obj, BOOL fReplace, short wear_bit)
{
char buf [MAX_STRING_LENGTH];
CObjData *tmpobj;
short bit, tmp;
separate_obj (obj);
if (ch->GetTrustLevel () < obj->level) {
sprintf (buf, "You must be level %d to use this object.\n\r",
obj->level);
ch->SendText (buf);
act (AT_ACTION, "$n tries to use $p, but is too inexperienced.",
ch, obj, NULL, TO_ROOM);
return;
}
// int Class = ch->GetClass ();
if (! ch->IsImmortal () && obj->IsAntiClass (ch->GetClass ())) {
act (AT_MAGIC, "You are forbidden to use that item.", ch, NULL, NULL, TO_CHAR);
act (AT_ACTION, "$n tries to use $p, but is forbidden to do so.",
ch, obj, NULL, TO_ROOM);
return;
}
if (wear_bit > -1) {
bit = wear_bit;
if (! obj->CanWear (1 << bit)) {
if (fReplace) {
switch (1 << bit) {
case ITEM_HOLD:
ch->SendText ("You cannot hold that.\n\r");
break;
case ITEM_WIELD:
case ITEM_MISSILE_WIELD:
ch->SendText ("You cannot wield that.\n\r");
break;
default:
ch->SendTextf ("You cannot wear that on your %s.\n\r",
w_flags [bit]);
}
}
return;
}
} else {
for (bit = -1, tmp = 1; tmp < 31; tmp++) {
if (obj->CanWear (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)
ch->SendText ("You can't wear, wield, or hold that.\n\r");
return;
}
switch (1 << bit) {
default:
bug ("wear_obj: uknown/unused item_wear bit %d", bit);
if (fReplace)
ch->SendText ("You can't wear, wield, or hold that.\n\r");
return;
case ITEM_WEAR_FINGER:
if (get_eq_char (ch, WEAR_FINGER_L)
&& get_eq_char (ch, WEAR_FINGER_R)
&& !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 slips $s left finger into $p.",
ch, obj, NULL, TO_ROOM);
act (AT_ACTION, "You slip your left finger into $p.",
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 slips $s right finger into $p.",
ch, obj, NULL, TO_ROOM);
act (AT_ACTION, "You slip your right finger into $p.",
ch, obj, NULL, TO_CHAR);
}
equip_char (ch, obj, WEAR_FINGER_R);
oprog_wear_trigger (ch, obj);
return;
}
bug ("Wear_obj: no free finger.");
ch->SendText ("You already wear something on both fingers.\n\r");
return;
case ITEM_WEAR_NECK:
if (get_eq_char (ch, WEAR_NECK_1) != NULL
&& get_eq_char (ch, WEAR_NECK_2) != NULL
&& !remove_obj (ch, WEAR_NECK_1, fReplace)
&& !remove_obj (ch, WEAR_NECK_2, fReplace))
return;
if (! get_eq_char (ch, WEAR_NECK_1)) {
if (! oprog_use_trigger (ch, obj, NULL, NULL, NULL)) {
act (AT_ACTION, "$n wears $p around $s neck.",
ch, obj, NULL, TO_ROOM);
act (AT_ACTION, "You wear $p around your neck.",
ch, obj, NULL, TO_CHAR);
}
equip_char (ch, obj, WEAR_NECK_1);
oprog_wear_trigger (ch, obj);
return;
}
if (! get_eq_char (ch, WEAR_NECK_2)) {
if (! oprog_use_trigger (ch, obj, NULL, NULL, NULL)) {
act (AT_ACTION, "$n wears $p around $s neck.",
ch, obj, NULL, TO_ROOM);
act (AT_ACTION, "You wear $p around your neck.",
ch, obj, NULL, TO_CHAR);
}
equip_char (ch, obj, WEAR_NECK_2);
oprog_wear_trigger (ch, obj);
return;
}
bug ("Wear_obj: no free neck.");
ch->SendText ("You already wear two neck items.\n\r");
return;
case ITEM_WEAR_BODY:
// if (! remove_obj (ch, WEAR_BODY, fReplace))
// return;
if (! can_layer (ch, obj, WEAR_BODY)) {
ch->SendText ("It won't fit overtop of what you're already wearing.\n\r");
return;
}
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_WEAR_EYES:
if (! remove_obj (ch, WEAR_EYES, fReplace))
return;
if (! oprog_use_trigger (ch, obj, NULL, NULL, NULL)) {
act (AT_ACTION, "$n places $p on $s eyes.", ch, obj, NULL, TO_ROOM);
act (AT_ACTION, "You place $p on your eyes.", ch, obj, NULL, TO_CHAR);
}
equip_char (ch, obj, WEAR_EYES);
oprog_wear_trigger (ch, obj);
return;
case ITEM_WEAR_FACE:
if (! remove_obj (ch, WEAR_FACE, fReplace))
return;
if (! oprog_use_trigger (ch, obj, NULL, NULL, NULL)) {
act (AT_ACTION, "$n places $p on $s face.", ch, obj, NULL, TO_ROOM);
act (AT_ACTION, "You place $p on your face.", ch, obj, NULL, TO_CHAR);
}
equip_char (ch, obj, WEAR_FACE);
oprog_wear_trigger (ch, obj);
return;
case ITEM_WEAR_EARS:
if (! remove_obj (ch, WEAR_EARS, fReplace))
return;
if (! oprog_use_trigger (ch, obj, NULL, NULL, NULL)) {
act (AT_ACTION, "$n wears $p on $s ears.", ch, obj, NULL, TO_ROOM);
act (AT_ACTION, "You wear $p on your ears.", ch, obj, NULL, TO_CHAR);
}
equip_char (ch, obj, WEAR_EARS);
oprog_wear_trigger (ch, obj);
return;
case ITEM_WEAR_LEGS:
// if (!remove_obj (ch, WEAR_LEGS, fReplace))
// return;
if (! can_layer (ch, obj, WEAR_LEGS)) {
ch->SendText ("It won't fit overtop of what you're already wearing.\n\r");
return;
}
if (! oprog_use_trigger (ch, obj, NULL, NULL, NULL)) {
act (AT_ACTION, "$n slips into $p.", ch, obj, NULL, TO_ROOM);
act (AT_ACTION, "You slip into $p.", ch, obj, NULL, TO_CHAR);
}
equip_char (ch, obj, WEAR_LEGS);
oprog_wear_trigger (ch, obj);
return;
case ITEM_WEAR_FEET:
// if (!remove_obj (ch, WEAR_FEET, fReplace))
// return;
if (! can_layer (ch, obj, WEAR_FEET)) {
ch->SendText ("It won't fit overtop of what you're already wearing.\n\r");
return;
}
if (! oprog_use_trigger (ch, obj, NULL, NULL, NULL)) {
act (AT_ACTION, "$n wears $p on $s feet.", ch, obj, NULL, TO_ROOM);
act (AT_ACTION, "You wear $p on your feet.", ch, obj, NULL, TO_CHAR);
}
equip_char (ch, obj, WEAR_FEET);
oprog_wear_trigger (ch, obj);
return;
case ITEM_WEAR_HANDS:
// if (!remove_obj (ch, WEAR_HANDS, fReplace))
// return;
if (! can_layer (ch, obj, WEAR_HANDS)) {
ch->SendText ("It won't fit overtop of what you're already wearing.\n\r");
return;
}
if (! oprog_use_trigger (ch, obj, NULL, NULL, NULL)) {
act (AT_ACTION, "$n wears $p on $s hands.", ch, obj, NULL, TO_ROOM);
act (AT_ACTION, "You wear $p on your hands.", ch, obj, NULL, TO_CHAR);
}
equip_char (ch, obj, WEAR_HANDS);
oprog_wear_trigger (ch, obj);
return;
case ITEM_WEAR_ARMS:
// if (!remove_obj (ch, WEAR_ARMS, fReplace))
// return;
if (! can_layer (ch, obj, WEAR_ARMS)) {
ch->SendText ("It won't fit overtop of what you're already wearing.\n\r");
return;
}
if (! oprog_use_trigger (ch, obj, NULL, NULL, NULL)) {
act (AT_ACTION, "$n wears $p on $s arms.", ch, obj, NULL, TO_ROOM);
act (AT_ACTION, "You wear $p on your arms.", ch, obj, NULL, TO_CHAR);
}
equip_char (ch, obj, WEAR_ARMS);
oprog_wear_trigger (ch, obj);
return;
case ITEM_WEAR_ABOUT:
// if (!remove_obj (ch, WEAR_ABOUT, fReplace))
// return;
if (! can_layer (ch, obj, WEAR_ABOUT)) {
ch->SendText ("It won't fit overtop of what you're already wearing.\n\r");
return;
}
if (! oprog_use_trigger (ch, obj, NULL, NULL, NULL)) {
act (AT_ACTION, "$n wears $p about $s body.", ch, obj, NULL, TO_ROOM);
act (AT_ACTION, "You wear $p about your body.", ch, obj, NULL, TO_CHAR);
}
equip_char (ch, obj, WEAR_ABOUT);
oprog_wear_trigger (ch, obj);
return;
case ITEM_WEAR_BACK:
if (! remove_obj (ch, WEAR_BACK, fReplace))
return;
if (! oprog_use_trigger (ch, obj, NULL, NULL, NULL)) {
act (AT_ACTION, "$n slings $p on $s back.", ch, obj, NULL, TO_ROOM);
act (AT_ACTION, "You sling $p on your back.", ch, obj, NULL, TO_CHAR);
}
equip_char (ch, obj, WEAR_BACK);
oprog_wear_trigger (ch, obj);
return;
case ITEM_WEAR_WAIST:
// if (!remove_obj (ch, WEAR_WAIST, fReplace))
// return;
if (! can_layer (ch, obj, WEAR_WAIST)) {
ch->SendText ("It won't fit overtop of what you're already wearing.\n\r");
return;
}
if (! oprog_use_trigger (ch, obj, NULL, NULL, NULL)) {
act (AT_ACTION, "$n wears $p about $s waist.", ch, obj, NULL, TO_ROOM);
act (AT_ACTION, "You wear $p about your waist.", ch, obj, NULL, TO_CHAR);
}
equip_char (ch, obj, WEAR_WAIST);
oprog_wear_trigger (ch, obj);
return;
case ITEM_WEAR_WRIST:
if (get_eq_char (ch, WEAR_WRIST_L)
&& get_eq_char (ch, WEAR_WRIST_R)
&& !remove_obj (ch, WEAR_WRIST_L, fReplace)
&& !remove_obj (ch, WEAR_WRIST_R, fReplace))
return;
if (! get_eq_char (ch, WEAR_WRIST_L)) {
if (! oprog_use_trigger (ch, obj, NULL, NULL, NULL)) {
act (AT_ACTION, "$n fits $p around $s left wrist.",
ch, obj, NULL, TO_ROOM);
act (AT_ACTION, "You fit $p around your left wrist.",
ch, obj, NULL, TO_CHAR);
}
equip_char (ch, obj, WEAR_WRIST_L);
oprog_wear_trigger (ch, obj);
return;
}
if (! get_eq_char (ch, WEAR_WRIST_R)) {
if (! oprog_use_trigger (ch, obj, NULL, NULL, NULL)) {
act (AT_ACTION, "$n fits $p around $s right wrist.",
ch, obj, NULL, TO_ROOM);
act (AT_ACTION, "You fit $p around your right wrist.",
ch, obj, NULL, TO_CHAR);
}
equip_char (ch, obj, WEAR_WRIST_R);
oprog_wear_trigger (ch, obj);
return;
}
bug ("Wear_obj: no free wrist.");
ch->SendText ("You already wear two wrist items.\n\r");
return;
case ITEM_WEAR_ANKLE:
if (get_eq_char (ch, WEAR_ANKLE_L)
&& get_eq_char (ch, WEAR_ANKLE_R)
&& ! remove_obj (ch, WEAR_ANKLE_L, fReplace)
&& ! remove_obj (ch, WEAR_ANKLE_R, fReplace))
return;
if (! get_eq_char (ch, WEAR_ANKLE_L)) {
if (! oprog_use_trigger (ch, obj, NULL, NULL, NULL)) {
act (AT_ACTION, "$n fits $p around $s left ankle.",
ch, obj, NULL, TO_ROOM);
act (AT_ACTION, "You fit $p around your left ankle.",
ch, obj, NULL, TO_CHAR);
}
equip_char (ch, obj, WEAR_ANKLE_L);
oprog_wear_trigger (ch, obj);
return;
}
if (! get_eq_char (ch, WEAR_ANKLE_R)) {
if (! oprog_use_trigger (ch, obj, NULL, NULL, NULL)) {
act (AT_ACTION, "$n fits $p around $s right ankle.",
ch, obj, NULL, TO_ROOM);
act (AT_ACTION, "You fit $p around your right ankle.",
ch, obj, NULL, TO_CHAR);
}
equip_char (ch, obj, WEAR_ANKLE_R);
oprog_wear_trigger (ch, obj);
return;
}
bug ("Wear_obj: no free ankle.");
ch->SendText ("You already wear two ankle items.\n\r");
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))) {
ch->SendText ("You can't use a shield AND two weapons!\n\r");
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;
tmpobj = NULL;
} else {
if ((tmpobj = get_eq_char (ch, WEAR_WIELD)) != NULL
&& (get_eq_char (ch, WEAR_MISSILE_WIELD) ||
get_eq_char (ch, WEAR_DUAL_WIELD))){
ch->SendText ("You're already wielding two weapons.\n\r");
return;
}
}
if (tmpobj) {
if (can_dual (ch)) {
if (get_obj_weight (obj) + get_obj_weight (tmpobj)
> str_app [ch->GetCurrentStrength ()].wield) {
ch->SendText ("It is too heavy for you to wield.\n\r");
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 [ch->GetCurrentStrength ()].wield){
ch->SendText ("It is too heavy for you to wield.\n\r");
return;
}
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);
return;
case ITEM_HOLD:
if (get_eq_char (ch, WEAR_DUAL_WIELD)
|| (get_eq_char (ch, WEAR_WIELD)
&& get_eq_char (ch, WEAR_MISSILE_WIELD))) {
ch->SendText ("You cannot hold something AND two weapons!\n\r");
return;
}
if (! remove_obj (ch, WEAR_HOLD, fReplace))
return;
if (obj->item_type == ITEM_WAND
|| obj->item_type == ITEM_STAFF
|| obj->item_type == ITEM_FOOD
|| obj->item_type == ITEM_COOK
|| obj->item_type == ITEM_PILL
|| obj->item_type == ITEM_POTION
|| obj->item_type == ITEM_SCROLL
|| obj->item_type == ITEM_DRINK_CON
|| obj->item_type == ITEM_BLOOD
|| obj->item_type == ITEM_PIPE
|| obj->item_type == ITEM_HERB
|| obj->item_type == ITEM_KEY
|| !oprog_use_trigger (ch, obj, NULL, NULL, NULL)) {
act (AT_ACTION, "$n holds $p in $s hands.", ch, obj, NULL, TO_ROOM);
act (AT_ACTION, "You hold $p in your hands.", ch, obj, NULL, TO_CHAR);
}
equip_char (ch, obj, WEAR_HOLD);
oprog_wear_trigger (ch, obj);
}
}
void do_wear (CCharacter *ch, char *argument)
{
char arg1 [MAX_INPUT_LENGTH];
char arg2 [MAX_INPUT_LENGTH];
CObjData *obj;
short 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') {
ch->SendText ("Wear, wield, or hold what?\n\r");
return;
}
if (ms_find_obj (ch))
return;
if (! str_cmp (arg1, "all")) {
POSITION pos = ch->GetHeadCarryPos ();
while (obj = ch->GetNextCarrying (pos))
if (obj->wear_loc == WEAR_NONE && can_see_obj (ch, *obj))
wear_obj (ch, obj, FALSE, -1);
} else {
if ((obj = get_obj_carry (ch, arg1)) == NULL) {
ch->SendText ("You do not have that item.\n\r");
return;
}
if (arg2 [0] != '\0')
wear_bit = get_wflag (arg2);
else
wear_bit = -1;
wear_obj (ch, obj, TRUE, wear_bit);
}
}
void do_remove (CCharacter *ch, char *argument)
{
char arg [MAX_INPUT_LENGTH];
CObjData *obj, *obj_next;
one_argument (argument, arg);
if (arg [0] == '\0') {
ch->SendText ("Remove what?\n\r");
return;
}
if (ms_find_obj (ch))
return;
if (! str_cmp (arg, "all")) { // SB Remove all
POSITION pos = ch->GetHeadCarryPos ();
while (obj = ch->GetNextCarrying (pos)) {
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) {
ch->SendText ("You are not using that item.\n\r");
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;
}
remove_obj (ch, obj->wear_loc, TRUE);
}
void do_bury (CCharacter *ch, char *argument)
{
char arg [MAX_INPUT_LENGTH];
CObjData *obj;
BOOL shovel;
short move;
one_argument (argument, arg);
if (arg [0] == '\0') {
ch->SendText ("What do you wish to bury?\n\r");
return;
}
if (ms_find_obj (ch))
return;
shovel = FALSE;
POSITION pos = ch->GetHeadCarryPos ();
while (obj = ch->GetNextCarrying (pos))
if (obj->item_type == ITEM_SHOVEL) {
shovel = TRUE;
break;
}
obj = get_obj_list_rev (ch, arg, ch->GetInRoom ()->GetContentList ());
if (! obj) {
ch->SendText ("You can't find it.\n\r");
return;
}
separate_obj (obj);
if (! obj->CanWear (ITEM_TAKE)) {
if (! obj->IsClanCorpse ()
|| ch->IsNpc () || ! ch->IsPkiller ()) {
act (AT_PLAIN, "You cannot bury $p.", ch, obj, 0, TO_CHAR);
return;
}
}
switch (ch->GetInRoom ()->sector_type) {
case SECT_CITY:
case SECT_INSIDE:
ch->SendText ("The floor is too hard to dig through.\n\r");
return;
case SECT_WATER_SWIM:
case SECT_WATER_NOSWIM:
case SECT_UNDERWATER:
ch->SendText ("You cannot bury something here.\n\r");
return;
case SECT_AIR:
ch->SendText ("What? In the air?!\n\r");
return;
}
if (obj->weight > (UMAX (5, (can_carry_w (ch) / 10))) && !shovel) {
ch->SendText ("You'd need a shovel to bury something that big.\n\r");
return;
}
move = (obj->weight * 50 * (shovel ? 1 : 5)) / UMAX (1, can_carry_w (ch));
move = URANGE (2, move, 1000);
if (move > ch->GetMove ()) {
ch->SendText (
"You don't have the energy to bury something of that size.\n\r");
return;
}
ch->AddMove (-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);
obj->SetBuried ();
WAIT_STATE (ch, URANGE (10, move / 2, 100));
}
void do_sacrifice (CCharacter *ch, char *argument)
{
char arg [MAX_INPUT_LENGTH];
char buf [MAX_STRING_LENGTH];
CString Name;
CObjData *obj;
one_argument (argument, arg);
if (arg [0] == '\0' || !str_cmp (arg, ch->GetName ())) {
act (AT_ACTION, "$n offers $mself to $s deity, who graciously declines.",
ch, NULL, NULL, TO_ROOM);
ch->SendText ("Your deity appreciates your offer and may accept it later.");
return;
}
if (ms_find_obj (ch))
return;
obj = get_obj_list_rev (ch, arg, ch->GetInRoom ()->GetContentList ());
if (! obj) {
ch->SendText ("You can't find it.\n\r");
return;
}
separate_obj (obj);
if (! obj->CanWear (ITEM_TAKE)) {
act (AT_PLAIN, "$p is not an acceptable sacrifice.", ch, obj, 0, TO_CHAR);
return;
}
if (! ch->IsNpc () && ch->GetPcData ()->deity
&& ch->GetPcData ()->deity->IsValidName ())
Name = ch->GetPcData ()->deity->GetName ();
else if (! ch->IsNpc () && ch->IsGuilded () && SysData.pGuildOverseer[0] != '\0')
Name = SysData.pGuildOverseer;
else if (! ch->IsNpc () && ch->GetPcData ()->GetClan ()
&& ch->GetPcData ()->GetClan ()->deity[0] != '\0')
Name = ch->GetPcData ()->GetClan ()->deity;
else Name = SysData.GetSupremeEntity ();
ch->AddGold (1);
if (obj->item_type == ITEM_CORPSE_NPC
|| obj->item_type == ITEM_CORPSE_PC)
adjust_favor (ch, 5, 1);
ch->SendTextf ("%s gives you one gold coin for your sacrifice.\n\r", Name);
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)) {
if (cur_obj == obj->serial)
global_objcode = rOBJ_SACCED;
extract_obj (obj);
}
}
void do_brandish (CCharacter *ch, char *argument)
{
CCharacter *vch;
CCharacter *vch_next;
CObjData *staff;
ch_ret retcode;
int sn;
if ((staff = get_eq_char (ch, WEAR_HOLD)) == NULL) {
ch->SendText ("You hold nothing in your hand.\n\r");
return;
}
if (staff->item_type != ITEM_STAFF) {
ch->SendText ("You can brandish only with a staff.\n\r");
return;
}
if ((sn = staff->value[3]) < 0 || sn >= SkillTable.GetCount ()
|| SkillTable.GetSpellFunction (sn) == NULL) {
bug ("Do_brandish: bad sn %d.", sn);
return;
}
WAIT_STATE (ch, 2 * PULSE_VIOLENCE);
if (staff->value [2] > 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);
}
for (vch = ch->GetInRoom ()->first_person; vch; vch = vch_next) {
vch_next = vch->GetNextInRoom ();
if (! vch->IsNpc () && vch->IsWizInvis ()
&& vch->GetPcData ()->wizinvis >= LEVEL_IMMORTAL)
continue;
else
switch (SkillTable.GetTarget (sn)) {
default:
bug ("Do_brandish: bad target for sn %d.", sn);
return;
case TAR_IGNORE:
if (vch != ch)
continue;
break;
case TAR_CHAR_OFFENSIVE:
if (ch->IsNpc () ? vch->IsNpc () : !vch->IsNpc ())
continue;
break;
case TAR_CHAR_DEFENSIVE:
if (ch->IsNpc () ? !vch->IsNpc () : vch->IsNpc ())
continue;
break;
case TAR_CHAR_SELF:
if (vch != ch)
continue;
break;
}
retcode = obj_cast_spell (staff->value[3], staff->value[0], ch, vch, NULL);
if (retcode == rCHAR_DIED || retcode == rBOTH_DIED) {
bug ("do_brandish: char died", 0);
return;
}
}
}
if (--staff->value [2] <= 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);
}
}
void do_zap (CCharacter *ch, char *argument)
{
char arg [MAX_INPUT_LENGTH];
CCharacter *victim;
CObjData *wand;
CObjData *obj;
ch_ret retcode;
one_argument (argument, arg);
if (arg [0] == '\0' && ! ch->GetFightData ()) {
ch->SendText ("Zap whom or what?\n\r");
return;
}
if ((wand = get_eq_char (ch, WEAR_HOLD)) == NULL) {
ch->SendText ("You hold nothing in your hand.\n\r");
return;
}
if (wand->item_type != ITEM_WAND) {
ch->SendText ("You can zap only with a wand.\n\r");
return;
}
obj = NULL;
if (arg [0] == '\0') {
if (ch->GetFightData ())
victim = ch->GetFightWho ();
else {
ch->SendText ("Zap whom or what?\n\r");
return;
}
} else {
if ((victim = get_char_room (ch, arg)) == NULL
&& (obj = get_obj_here (ch, arg)) == NULL) {
ch->SendText ("You can't find it.\n\r");
return;
}
}
WAIT_STATE (ch, 1 * PULSE_VIOLENCE);
if (wand->value [2] > 0) {
if (victim) {
if (! oprog_use_trigger (ch, wand, victim, NULL, NULL)) {
act (AT_MAGIC, "$n aims $p at $N.", ch, wand, victim, TO_ROOM);
act (AT_MAGIC, "You aim $p at $N.", ch, wand, victim, TO_CHAR);
}
} else {
if (! oprog_use_trigger (ch, wand, NULL, obj, NULL)) {
act (AT_MAGIC, "$n aims $p at $P.", ch, wand, obj, TO_ROOM);
act (AT_MAGIC, "You aim $p at $P.", ch, wand, obj, TO_CHAR);
}
}
retcode = obj_cast_spell (wand->value [3], wand->value [0],
ch, victim, obj);
if (retcode == rCHAR_DIED || retcode == rBOTH_DIED) {
bug ("do_zap: char died");
return;
}
}
if (--wand->value [2] <= 0) {
act (AT_MAGIC, "$p explodes into fragments.", ch, wand, NULL, TO_ROOM);
act (AT_MAGIC, "$p explodes into fragments.", ch, wand, NULL, TO_CHAR);
if (wand->serial == cur_obj)
global_objcode = rOBJ_USED;
extract_obj (wand);
}
}
// Make objects in rooms that are nofloor fall - Scryn 1/23/96
void obj_fall (CObjData *obj, BOOL through)
{
CExitData *pexit;
CRoomIndexData *to_room;
static int fall_count;
char buf[MAX_STRING_LENGTH];
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 (obj->in_room->HasNoFloor ()
&& obj->CanGo (DIR_DOWN)
&& ! obj->IsMagic ())
{
pexit = get_exit (obj->in_room, DIR_DOWN);
to_room = pexit->GetToRoom ();
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);
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 (! obj->in_room->HasNoFloor () && 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)
{
CCharacter *rch;
CCharacter *vch = NULL;
int chcnt = 0;
for (rch = obj->in_room->first_person; rch;
rch = rch->GetNextInRoom (), 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*vch->GetLevel (), TYPE_UNDEFINED);
}
/* Damage objects */
switch (obj->item_type)
{
case ITEM_WEAPON:
case ITEM_ARMOR:
if ((obj->value[0] - dam) <= 0)
{
if (obj->in_room->first_person)
{
act (AT_PLAIN, "$p is destroyed by the fall!",
obj->in_room->first_person, obj, NULL, TO_ROOM);
act (AT_PLAIN, "$p is destroyed by the fall!",
obj->in_room->first_person, obj, NULL, TO_CHAR);
}
make_scraps (obj);
}
else
obj->value[0] -= dam;
break;
default:
if ((dam*15) > get_obj_resistance (obj))
{
if (obj->in_room->first_person)
{
act (AT_PLAIN, "$p is destroyed by the fall!",
obj->in_room->first_person, obj, NULL, TO_ROOM);
act (AT_PLAIN, "$p is destroyed by the fall!",
obj->in_room->first_person, obj, NULL, TO_CHAR);
}
make_scraps (obj);
}
break;
}
}
obj_fall (obj, TRUE);
}
return;
}