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