/**************************************************************************** * [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. * * ------------------------------------------------------------------------ * * Misc module for general commands: not skills or spells * **************************************************************************** * Note: Most of the stuff in here would go in act_obj.c, but act_obj was * * getting big. * ****************************************************************************/ #include "stdafx.h" #include "smaug.h" #include "SysData.h" #include "skill.h" #include "objects.h" #include "rooms.h" #include "Exits.h" #include "descriptor.h" #include "character.h" extern int top_exit; /* * Fill a container * Many enhancements added by Thoric (ie: filling non-drink containers) */ void do_fill (CCharacter *ch, char *argument) { char arg1 [MAX_INPUT_LENGTH]; char arg2 [MAX_INPUT_LENGTH]; CObjData *obj; CObjData *source; short dest_item, src_item1, src_item2, src_item3; int diff; BOOL all = FALSE; argument = one_argument (argument, arg1); argument = one_argument (argument, arg2); /* munch optional words */ if ((!str_cmp (arg2, "from") || !str_cmp (arg2, "with")) && argument[0] != '\0') argument = one_argument (argument, arg2); if (arg1[0] == '\0') { ch->SendText ("Fill what?\n\r"); return; } if (ms_find_obj (ch)) return; if ((obj = get_obj_carry (ch, arg1)) == NULL) { ch->SendText ("You do not have that item.\n\r"); return; } else dest_item = obj->item_type; src_item1 = src_item2 = src_item3 = -1; switch (dest_item) { default: act (AT_ACTION, "$n tries to fill $p... (Don't ask me how)", ch, obj, NULL, TO_ROOM); ch->SendText ("You cannot fill that.\n\r"); return; /* place all fillable item types here */ case ITEM_DRINK_CON: src_item1 = ITEM_FOUNTAIN; src_item2 = ITEM_BLOOD; break; case ITEM_HERB_CON: src_item1 = ITEM_HERB; src_item2 = ITEM_HERB_CON; break; case ITEM_PIPE: src_item1 = ITEM_HERB; src_item2 = ITEM_HERB_CON; break; case ITEM_CONTAINER: src_item1 = ITEM_CONTAINER; src_item2 = ITEM_CORPSE_NPC; src_item3 = ITEM_CORPSE_PC; break; } if (dest_item == ITEM_CONTAINER) { if (IS_SET (obj->value[1], CONT_CLOSED)) { act (AT_PLAIN, "The $d is closed.", ch, NULL, obj->GetName (), TO_CHAR); return; } if (get_obj_weight (obj) / obj->count >= obj->value[0]) { ch->SendText ("It's already full as it can be.\n\r"); return; } } else { diff = obj->value[0] - obj->value[1]; if (diff < 1 || obj->value[1] >= obj->value[0]) { ch->SendText ("It's already full as it can be.\n\r"); return; } } if (dest_item == ITEM_PIPE && IS_SET (obj->value[3], PIPE_FULLOFASH)) { ch->SendText ("It's full of ashes, and needs to be emptied first.\n\r"); return; } if (arg2[0] != '\0') { if (dest_item == ITEM_CONTAINER && (!str_cmp (arg2, "all") || !str_prefix ("all.", arg2))) { all = TRUE; source = NULL; } else /* This used to let you fill a pipe from an object on the ground. Seems to me you should be holding whatever you want to fill a pipe with. It's nitpicking, but I needed to change it to get a mobprog to work right. Check out Lord Fitzgibbon if you're curious. -Narn */ if (dest_item == ITEM_PIPE) { if ((source = get_obj_carry (ch, arg2)) == NULL) { ch->SendText ("You don't have that item.\n\r"); return; } if (source->item_type != src_item1 && source->item_type != src_item2 && source->item_type != src_item3) { act (AT_PLAIN, "You cannot fill $p with $P!", ch, obj, source, TO_CHAR); return; } } else { if ((source = get_obj_here (ch, arg2)) == NULL) { ch->SendText ("You cannot find that item.\n\r"); return; } } } else source = NULL; if (!source && dest_item == ITEM_PIPE) { ch->SendText ("Fill it with what?\n\r"); return; } if (! source) { BOOL found = FALSE; found = FALSE; separate_obj (obj); CObjectList &List = ch->GetInRoom ()->GetContentList (); POSITION pos = List.GetHeadPosition (); while (source = List.GetNext (pos)) { if (dest_item == ITEM_CONTAINER) { if (! source->CanWear (ITEM_TAKE) || (source->IsPrototype () && !can_take_proto (ch)) || ch->GetCarryWeight () + get_obj_weight (source) > can_carry_w (ch) || (get_obj_weight (source) + get_obj_weight (obj)/obj->count) > obj->value [0]) continue; if (all && arg2 [3] == '.' && !nifty_is_name (&arg2 [4], source->GetName ())) continue; obj_from_room (source); if (source->item_type == ITEM_MONEY) { ch->AddGold (source->value [0]); extract_obj (source); } else obj_to_obj (source, obj); found = TRUE; } else if (source->item_type == src_item1 || source->item_type == src_item2 || source->item_type == src_item3) { found = TRUE; break; } } if (! found) { switch (src_item1) { default: ch->SendText ("There is nothing appropriate here!\n\r"); return; case ITEM_FOUNTAIN: ch->SendText ("There is no fountain or pool here!\n\r"); return; case ITEM_BLOOD: ch->SendText ("There is no blood pool here!\n\r"); return; case ITEM_HERB_CON: ch->SendText ("There are no herbs here!\n\r"); return; case ITEM_HERB: ch->SendText ("You cannot find any smoking herbs.\n\r"); return; } } if (dest_item == ITEM_CONTAINER) { act (AT_ACTION, "You fill $p.", ch, obj, NULL, TO_CHAR); act (AT_ACTION, "$n fills $p.", ch, obj, NULL, TO_ROOM); return; } } if (dest_item == ITEM_CONTAINER) { CObjData *otmp; char name[MAX_INPUT_LENGTH]; CCharacter *gch; char *pd; BOOL found = FALSE; if (source == obj) { ch->SendText ("You can't fill something with itself!\n\r"); return; } switch (source->item_type) { default: /* put something in container */ if (!source->in_room /* disallow inventory items */ || ! source->CanWear (ITEM_TAKE) || (source->IsPrototype () && !can_take_proto (ch)) || ch->GetCarryWeight () + get_obj_weight (source) > can_carry_w (ch) || (get_obj_weight (source) + get_obj_weight (obj)/obj->count) > obj->value[0]) { ch->SendText ("You can't do that.\n\r"); return; } separate_obj (obj); act (AT_ACTION, "You take $P and put it inside $p.", ch, obj, source, TO_CHAR); act (AT_ACTION, "$n takes $P and puts it inside $p.", ch, obj, source, TO_ROOM); obj_from_room (source); obj_to_obj (source, obj); break; case ITEM_MONEY: ch->SendText ("You can't do that... yet.\n\r"); break; case ITEM_CORPSE_PC: if (ch->IsNpc ()) { ch->SendText ("You can't do that.\n\r"); return; } if (! source->IsClanCorpse () || ! ch->IsPkiller ()) { pd = NCCP source->GetShortDescr (); pd = one_argument (pd, name); pd = one_argument (pd, name); pd = one_argument (pd, name); pd = one_argument (pd, name); if (str_cmp (name, ch->GetName ()) && ch->IsMortal ()) { 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; } } } case ITEM_CONTAINER: if (source->item_type == ITEM_CONTAINER /* don't remove */ && IS_SET (source->value[1], CONT_CLOSED)) { act (AT_PLAIN, "The $d is closed.", ch, NULL, source->GetName (), TO_CHAR); return; } case ITEM_CORPSE_NPC: if (source->GetContentList ().IsEmpty ()) { ch->SendText ("It's empty.\n\r"); return; } separate_obj (obj); CObjectList &List = source->GetContentList (); POSITION pos = List.GetHeadPosition (); while (otmp = List.GetNext (pos)) { if (! otmp->CanWear (ITEM_TAKE) || (otmp->IsPrototype () && !can_take_proto (ch)) || ch->carry_number + otmp->count > ch->GetMaxItems () || ch->GetCarryWeight () + get_obj_weight (otmp) > can_carry_w (ch) || (get_obj_weight (source) + get_obj_weight (obj)/obj->count) > obj->value[0]) continue; obj_from_obj (otmp); obj_to_obj (otmp, obj); found = TRUE; } if (found) { act (AT_ACTION, "You fill $p from $P.", ch, obj, source, TO_CHAR); act (AT_ACTION, "$n fills $p from $P.", ch, obj, source, TO_ROOM); } else ch->SendText ("There is nothing appropriate in there.\n\r"); break; } return; } if (source->value[1] < 1) { ch->SendText ("There's none left!\n\r"); return; } if (source->count > 1 && source->item_type != ITEM_FOUNTAIN) separate_obj (source); separate_obj (obj); switch (source->item_type) { default: bug ("do_fill: got bad item type: %d", source->item_type); ch->SendText ("Something went wrong...\n\r"); return; case ITEM_FOUNTAIN: if (obj->value[1] != 0 && obj->value[2] != 0) { ch->SendText ("There is already another liquid in it.\n\r"); return; } obj->value[2] = 0; obj->value[1] = obj->value[0]; act (AT_ACTION, "You fill $p from $P.", ch, obj, source, TO_CHAR); act (AT_ACTION, "$n fills $p from $P.", ch, obj, source, TO_ROOM); return; case ITEM_BLOOD: if (obj->value[1] != 0 && obj->value[2] != 13) { ch->SendText ("There is already another liquid in it.\n\r"); return; } obj->value[2] = 13; if (source->value[1] < diff) diff = source->value[1]; obj->value[1] += diff; act (AT_ACTION, "You fill $p from $P.", ch, obj, source, TO_CHAR); act (AT_ACTION, "$n fills $p from $P.", ch, obj, source, TO_ROOM); if ((source->value[1] -= diff) < 1) { extract_obj (source); make_bloodstain (ch); } return; case ITEM_HERB: if (obj->value[1] != 0 && obj->value[2] != source->value[2]) { ch->SendText ("There is already another type of herb in it.\n\r"); return; } obj->value[2] = source->value[2]; if (source->value[1] < diff) diff = source->value[1]; obj->value[1] += diff; act (AT_ACTION, "You fill $p with $P.", ch, obj, source, TO_CHAR); act (AT_ACTION, "$n fills $p with $P.", ch, obj, source, TO_ROOM); if ((source->value[1] -= diff) < 1) extract_obj (source); return; case ITEM_HERB_CON: if (obj->value[1] != 0 && obj->value[2] != source->value[2]) { ch->SendText ("There is already another type of herb in it.\n\r"); return; } obj->value[2] = source->value[2]; if (source->value[1] < diff) diff = source->value[1]; obj->value[1] += diff; source->value[1] -= diff; act (AT_ACTION, "You fill $p from $P.", ch, obj, source, TO_CHAR); act (AT_ACTION, "$n fills $p from $P.", ch, obj, source, TO_ROOM); return; case ITEM_DRINK_CON: if (obj->value[1] != 0 && obj->value[2] != source->value[2]) { ch->SendText ("There is already another liquid in it.\n\r"); return; } obj->value[2] = source->value[2]; if (source->value[1] < diff) diff = source->value[1]; obj->value[1] += diff; source->value[1] -= diff; act (AT_ACTION, "You fill $p from $P.", ch, obj, source, TO_CHAR); act (AT_ACTION, "$n fills $p from $P.", ch, obj, source, TO_ROOM); return; } } void do_drink (CCharacter *ch, char *argument) { char arg[MAX_INPUT_LENGTH]; CObjData *obj; int amount; int liquid; argument = one_argument (argument, arg); /* munch optional words */ if (! str_cmp (arg, "from") && argument [0] != '\0') argument = one_argument (argument, arg); if (arg [0] == '\0') { POSITION pos = ch->GetInRoom ()->GetHeadContentPos (); while (obj = ch->GetInRoom ()->GetNextContent (pos)) if ((obj->item_type == ITEM_FOUNTAIN) || (obj->item_type == ITEM_BLOOD)) break; if (! obj) { ch->SendText ("Drink what?\n\r"); return; } } else { if ((obj = get_obj_here (ch, arg)) == NULL) { ch->SendText ("You can't find it.\n\r"); return; } } if (obj->count > 1 && obj->item_type != ITEM_FOUNTAIN) separate_obj (obj); if (!ch->IsNpc () && ch->GetPcData ()->condition[COND_DRUNK] > 40) { ch->SendText ("You fail to reach your mouth. *Hic*\n\r"); return; } switch (obj->item_type) { default: if (obj->carried_by == ch) { act (AT_ACTION, "$n lifts $p up to $s mouth and tries to drink from it...", ch, obj, NULL, TO_ROOM); act (AT_ACTION, "You bring $p up to your mouth and try to drink from it...", ch, obj, NULL, TO_CHAR); } else { act (AT_ACTION, "$n gets down and tries to drink from $p... (Is $e feeling ok?)", ch, obj, NULL, TO_ROOM); act (AT_ACTION, "You get down on the ground and try to drink from $p...", ch, obj, NULL, TO_CHAR); } break; case ITEM_POTION: if (obj->carried_by == ch) do_quaff (ch, NCCP obj->GetName ()); else ch->SendText ("You're not carrying that.\n\r"); break; case ITEM_BLOOD: if (ch->IsVampire () && !ch->IsNpc ()) { if (obj->timer > 0 /* if timer, must be spilled blood */ && ch->GetLevel () > 5 && ch->GetPcData ()->condition[COND_BLOODTHIRST] > (5+ch->GetLevel ()/10)) { ch->SendText ("It is above you to stoop to drinking blood from the ground!\n\r"); ch->SendText ("Unless in dire need, you'd much rather have blood from a victim's neck!\n\r"); return; } if (ch->GetPcData ()->condition[COND_BLOODTHIRST] < (10 + ch->GetLevel ())) { if (ch->GetPcData ()->condition[COND_FULL] >= 48 || ch->GetPcData ()->condition[COND_THIRST] >= 48) { ch->SendText ("You are too full to drink any blood.\n\r"); return; } if (!oprog_use_trigger (ch, obj, NULL, NULL, NULL)) { act (AT_BLOOD, "$n drinks from the spilled blood.", ch, NULL, NULL, TO_ROOM); set_char_color (AT_BLOOD, ch); ch->SendText ("You relish in the replenishment of this vital fluid...\n\r"); if (obj->value[1] <=1) { set_char_color (AT_BLOOD, ch); ch->SendText ("You drink the last drop of blood from the spill.\n\r"); act (AT_BLOOD, "$n drinks the last drop of blood from the spill.", ch, NULL, NULL, TO_ROOM); } } gain_condition (ch, COND_BLOODTHIRST, 1); gain_condition (ch, COND_FULL, 1); gain_condition (ch, COND_THIRST, 1); if (--obj->value[1] <=0) { if (obj->serial == cur_obj) global_objcode = rOBJ_DRUNK; extract_obj (obj); make_bloodstain (ch); } } else ch->SendText ("Alas... you cannot consume any more blood.\n\r"); } else ch->SendText ("It is not in your nature to do such things.\n\r"); break; case ITEM_FOUNTAIN: if (!oprog_use_trigger (ch, obj, NULL, NULL, NULL)) { act (AT_ACTION, "$n drinks from the fountain.", ch, NULL, NULL, TO_ROOM); ch->SendText ("You take a long thirst quenching drink.\n\r"); } if (!ch->IsNpc ()) ch->GetPcData ()->condition[COND_THIRST] = 40; break; case ITEM_DRINK_CON: if (obj->value[1] <= 0) { ch->SendText ("It is already empty.\n\r"); return; } if ((liquid = obj->value[2]) >= LIQ_MAX) { bug ("Do_drink: bad liquid number %d.", liquid); liquid = obj->value[2] = 0; } if (!oprog_use_trigger (ch, obj, NULL, NULL, NULL)) { act (AT_ACTION, "$n drinks $T from $p.", ch, obj, liq_table[liquid].liq_name, TO_ROOM); act (AT_ACTION, "You drink $T from $p.", ch, obj, liq_table[liquid].liq_name, TO_CHAR); } amount = 1; /* UMIN (amount, obj->value[1]); */ /* what was this? concentrated drinks? concentrated water too I suppose... sheesh! */ gain_condition (ch, COND_DRUNK, amount * liq_table[liquid].liq_affect[COND_DRUNK ]); gain_condition (ch, COND_FULL, amount * liq_table[liquid].liq_affect[COND_FULL ]); gain_condition (ch, COND_THIRST, amount * liq_table[liquid].liq_affect[COND_THIRST ]); if (!ch->IsNpc ()) { if (ch->GetPcData ()->condition[COND_DRUNK] > 24) ch->SendText ("You feel quite sloshed.\n\r"); else if (ch->GetPcData ()->condition[COND_DRUNK] > 18) ch->SendText ("You feel very drunk.\n\r"); else if (ch->GetPcData ()->condition[COND_DRUNK] > 12) ch->SendText ("You feel drunk.\n\r"); else if (ch->GetPcData ()->condition[COND_DRUNK] > 8) ch->SendText ("You feel a little drunk.\n\r"); else if (ch->GetPcData ()->condition[COND_DRUNK] > 5) ch->SendText ("You feel light headed.\n\r"); if (ch->GetPcData ()->condition[COND_FULL] > 40) ch->SendText ("You are full.\n\r"); if (ch->GetPcData ()->condition[COND_THIRST] > 40) ch->SendText ("You feel bloated.\n\r"); else if (ch->GetPcData ()->condition[COND_THIRST] > 36) ch->SendText ("Your stomach is sloshing around.\n\r"); else if (ch->GetPcData ()->condition[COND_THIRST] > 30) ch->SendText ("You do not feel thirsty.\n\r"); } if (obj->value[3]) { /* The drink was poisoned! */ CAffectData af; act (AT_POISON, "$n sputters and gags.", ch, NULL, NULL, TO_ROOM); act (AT_POISON, "You sputter and gag.", ch, NULL, NULL, TO_CHAR); ch->SetMentalState (URANGE (20, ch->GetMentalState () + 5, 100)); af.type = gsn_poison; af.duration = 3 * obj->value[3]; af.location = APPLY_NONE; af.modifier = 0; af.bitvector = AFF_POISON; affect_join (ch, &af); } obj->value[1] -= amount; if (obj->value[1] <= 0) { ch->SendText ("The empty container vanishes.\n\r"); if (cur_obj == obj->serial) global_objcode = rOBJ_DRUNK; extract_obj (obj); } break; } WAIT_STATE (ch, PULSE_PER_SECOND); return; } void do_eat (CCharacter *ch, char *argument) { CObjData *obj; ch_ret retcode; int foodcond; if (argument[0] == '\0') { ch->SendText ("Eat what?\n\r"); return; } if (ch->IsNpc () || ch->GetPcData ()->condition[COND_FULL] > 5) if (ms_find_obj (ch)) return; if ((obj = find_obj (ch, argument, TRUE)) == NULL) return; if (ch->IsMortal ()) { if (obj->item_type != ITEM_FOOD && obj->item_type != ITEM_PILL) { act (AT_ACTION, "$n starts to nibble on $p... ($e must really be hungry)", ch, obj, NULL, TO_ROOM); act (AT_ACTION, "You try to nibble on $p...", ch, obj, NULL, TO_CHAR); return; } if (!ch->IsNpc () && ch->GetPcData ()->condition[COND_FULL] > 40) { ch->SendText ("You are too full to eat more.\n\r"); return; } } /* required due to object grouping */ separate_obj (obj); if (ch->IsPkiller ()) WAIT_STATE (ch, PULSE_PER_SECOND/4); else WAIT_STATE (ch, PULSE_PER_SECOND/2); if (obj->in_obj) { act (AT_PLAIN, "You take $p from $P.", ch, obj, obj->in_obj, TO_CHAR); act (AT_PLAIN, "$n takes $p from $P.", ch, obj, obj->in_obj, TO_ROOM); } if (!oprog_use_trigger (ch, obj, NULL, NULL, NULL)) { if (! obj->HasValidActionDescr ()) { act (AT_ACTION, "$n eats $p.", ch, obj, NULL, TO_ROOM); act (AT_ACTION, "You eat $p.", ch, obj, NULL, TO_CHAR); } else actiondesc (ch, obj, NULL); } switch (obj->item_type) { case ITEM_FOOD: if (obj->timer > 0 && obj->value[1] > 0) foodcond = (obj->timer * 10) / obj->value[1]; else foodcond = 10; if (!ch->IsNpc ()) { int condition; condition = ch->GetPcData ()->condition[COND_FULL]; gain_condition (ch, COND_FULL, (obj->value[0] * foodcond) / 10); if (condition <= 1 && ch->GetPcData ()->condition[COND_FULL] > 1) ch->SendText ("You are no longer hungry.\n\r"); else if (ch->GetPcData ()->condition[COND_FULL] > 40) ch->SendText ("You are full.\n\r"); } if ( obj->value[3] != 0 || (foodcond < 4 && number_range (0, foodcond + 1) == 0)) { /* The food was poisoned! */ CAffectData af; if (obj->value[3] != 0) { act (AT_POISON, "$n chokes and gags.", ch, NULL, NULL, TO_ROOM); act (AT_POISON, "You choke and gag.", ch, NULL, NULL, TO_CHAR); ch->SetMentalState (URANGE (20, ch->GetMentalState () + 5, 100)); } else { act (AT_POISON, "$n gags on $p.", ch, obj, NULL, TO_ROOM); act (AT_POISON, "You gag on $p.", ch, obj, NULL, TO_CHAR); ch->SetMentalState (URANGE (15, ch->GetMentalState () + 5, 100)); } af.type = gsn_poison; af.duration = 2 * obj->value[0] * (obj->value[3] > 0 ? obj->value[3] : 1); af.location = APPLY_NONE; af.modifier = 0; af.bitvector = AFF_POISON; affect_join (ch, &af); } break; case ITEM_PILL: /* allow pills to fill you, if so desired */ if (!ch->IsNpc () && obj->value[4]) { int condition; condition = ch->GetPcData ()->condition[COND_FULL]; gain_condition (ch, COND_FULL, obj->value[4]); if (condition <= 1 && ch->GetPcData ()->condition[COND_FULL] > 1) ch->SendText ("You are no longer hungry.\n\r"); else if (ch->GetPcData ()->condition[COND_FULL] > 40) ch->SendText ("You are full.\n\r"); } retcode = obj_cast_spell (obj->value[1], obj->value[0], ch, ch, NULL); if (retcode == rNONE) retcode = obj_cast_spell (obj->value[2], obj->value[0], ch, ch, NULL); if (retcode == rNONE) retcode = obj_cast_spell (obj->value[3], obj->value[0], ch, ch, NULL); break; } if (obj->serial == cur_obj) global_objcode = rOBJ_EATEN; extract_obj (obj); return; } void do_quaff (CCharacter *ch, char *argument) { CObjData *obj; ch_ret retcode; if (argument[0] == '\0' || !str_cmp (argument, "")) { ch->SendText ("Quaff what?\n\r"); return; } if ((obj = find_obj (ch, argument, TRUE)) == NULL) return; if (obj->item_type != ITEM_POTION) { if (obj->item_type == ITEM_DRINK_CON) do_drink (ch, NCCP obj->GetName ()); else { act (AT_ACTION, "$n lifts $p up to $s mouth and tries to drink from it...", ch, obj, NULL, TO_ROOM); act (AT_ACTION, "You bring $p up to your mouth and try to drink from it...", ch, obj, NULL, TO_CHAR); } return; } /* * Fullness checking -Thoric */ if (!ch->IsNpc () && (ch->GetPcData ()->condition[COND_FULL] >= 48 || ch->GetPcData ()->condition[COND_THIRST] >= 48)) { ch->SendText ("Your stomach cannot contain any more.\n\r"); return; } separate_obj (obj); if (obj->in_obj) { act (AT_PLAIN, "You take $p from $P.", ch, obj, obj->in_obj, TO_CHAR); act (AT_PLAIN, "$n takes $p from $P.", ch, obj, obj->in_obj, TO_ROOM); } /* * If fighting, chance of dropping potion -Thoric */ if (ch->GetFightData () && number_percent () > (ch->GetDexterity () * 2 + 48)) { act (AT_MAGIC, "$n accidentally drops $p and it smashes into a thousand fragments.", ch, obj, NULL, TO_ROOM); act (AT_MAGIC, "Oops... $p gets knocked from your hands and smashes into pieces!", ch, obj, NULL ,TO_CHAR); } else { if (!oprog_use_trigger (ch, obj, NULL, NULL, NULL)) { act (AT_ACTION, "$n quaffs $p.", ch, obj, NULL, TO_ROOM); act (AT_ACTION, "You quaff $p.", ch, obj, NULL, TO_CHAR); } if (ch->IsPkiller ()) WAIT_STATE (ch, PULSE_PER_SECOND/4); else WAIT_STATE (ch, PULSE_PER_SECOND/2); gain_condition (ch, COND_THIRST, 1); retcode = obj_cast_spell (obj->value[1], obj->value[0], ch, ch, NULL); if (retcode == rNONE) retcode = obj_cast_spell (obj->value[2], obj->value[0], ch, ch, NULL); if (retcode == rNONE) retcode = obj_cast_spell (obj->value[3], obj->value[0], ch, ch, NULL); } if (cur_obj == obj->serial) global_objcode = rOBJ_QUAFFED; extract_obj (obj); return; } void do_recite (CCharacter *ch, char *argument) { char arg1[MAX_INPUT_LENGTH]; char arg2[MAX_INPUT_LENGTH]; CCharacter *victim; CObjData *scroll; CObjData *obj; ch_ret retcode; argument = one_argument (argument, arg1); argument = one_argument (argument, arg2); if (arg1[0] == '\0') { ch->SendText ("Recite what?\n\r"); return; } if (ms_find_obj (ch)) return; if ((scroll = get_obj_carry (ch, arg1)) == NULL) { ch->SendText ("You do not have that scroll.\n\r"); return; } if (scroll->item_type != ITEM_SCROLL) { act (AT_ACTION, "$n holds up $p as if to recite something from it...", ch, scroll, NULL, TO_ROOM); act (AT_ACTION, "You hold up $p and stand there with your mouth open. (Now what?)", ch, scroll, NULL, TO_CHAR); return; } if (ch->IsNpc () && (scroll->pIndexData->vnum == OBJ_VNUM_SCROLL_SCRIBING)) { ch->SendText ("As a mob, this dialect is foreign to you.\n\r"); return; } if ((scroll->pIndexData->vnum == OBJ_VNUM_SCROLL_SCRIBING) && (ch->GetLevel () + 10 < scroll->value[0])) { ch->SendText ("This scroll is too complex for you to understand.\n\r"); return; } obj = NULL; if (arg2[0] == '\0') victim = ch; else { if ((victim = get_char_room (ch, arg2)) == NULL && (obj = get_obj_here (ch, arg2)) == NULL) { ch->SendText ("You can't find it.\n\r"); return; } } separate_obj (scroll); act (AT_MAGIC, "$n recites $p.", ch, scroll, NULL, TO_ROOM); act (AT_MAGIC, "You recite $p.", ch, scroll, NULL, TO_CHAR); if (victim != ch) WAIT_STATE (ch, 2 * PULSE_VIOLENCE); else if (ch->IsPkiller ()) WAIT_STATE (ch, PULSE_PER_SECOND/4); else WAIT_STATE (ch, PULSE_PER_SECOND/2); retcode = obj_cast_spell (scroll->value[1], scroll->value[0], ch, victim, obj); if (retcode == rNONE) retcode = obj_cast_spell (scroll->value[2], scroll->value[0], ch, victim, obj); if (retcode == rNONE) retcode = obj_cast_spell (scroll->value[3], scroll->value[0], ch, victim, obj); if (scroll->serial == cur_obj) global_objcode = rOBJ_USED; extract_obj (scroll); return; } // Function to handle the state changing of a triggerobject (lever) -Thoric void pullorpush (CCharacter *ch, CObjData *obj, BOOL pull) { char buf[MAX_STRING_LENGTH]; CCharacter *rch; BOOL isup; CRoomIndexData *room, *to_room; CExitData *pexit, *pexit_rev; int edir; char *txt; if (IS_SET (obj->value[0], TRIG_UP)) isup = TRUE; else isup = FALSE; switch (obj->item_type) { default: sprintf (buf, "You can't %s that!\n\r", pull ? "pull" : "push"); ch->SendText (buf); return; break; case ITEM_SWITCH: case ITEM_LEVER: case ITEM_PULLCHAIN: if ((!pull && isup) || (pull && !isup)) { sprintf (buf, "It is already %s.\n\r", isup ? "up" : "down"); ch->SendText (buf); return; } case ITEM_BUTTON: if ((!pull && isup) || (pull & !isup)) { sprintf (buf, "It is already %s.\n\r", isup ? "in" : "out"); ch->SendText (buf); return; } break; } if (pull && obj->GetIndex ()->HasPullProg ()) { if (!IS_SET (obj->value[0], TRIG_AUTORETURN)) REMOVE_BIT (obj->value[0], TRIG_UP); oprog_pull_trigger (ch, obj); return; } if (! pull && obj->GetIndex ()->HasPushProg ()) { if (!IS_SET (obj->value[0], TRIG_AUTORETURN)) SET_BIT (obj->value[0], TRIG_UP); oprog_push_trigger (ch, obj); return; } if (!oprog_use_trigger (ch, obj, NULL, NULL, NULL)) { sprintf (buf, "$n %s $p.", pull ? "pulls" : "pushes"); act (AT_ACTION, buf, ch, obj, NULL, TO_ROOM); sprintf (buf, "You %s $p.", pull ? "pull" : "push"); act (AT_ACTION, buf, ch, obj, NULL, TO_CHAR); } if (!IS_SET (obj->value[0], TRIG_AUTORETURN)) { if (pull) REMOVE_BIT (obj->value[0], TRIG_UP); else SET_BIT (obj->value[0], TRIG_UP); } if (IS_SET (obj->value[0], TRIG_TELEPORT) || IS_SET (obj->value[0], TRIG_TELEPORTALL) || IS_SET (obj->value[0], TRIG_TELEPORTPLUS)) { int flags; if ((room = RoomTable.GetRoom (obj->value[1])) == NULL) { bug ("PullOrPush: obj points to invalid room %d", obj->value[1]); return; } flags = 0; if (IS_SET (obj->value[0], TRIG_SHOWROOMDESC)) SET_BIT (flags, TELE_SHOWDESC); if (IS_SET (obj->value[0], TRIG_TELEPORTALL)) SET_BIT (flags, TELE_TRANSALL); if (IS_SET (obj->value[0], TRIG_TELEPORTPLUS)) SET_BIT (flags, TELE_TRANSALLPLUS); teleport (ch, obj->value[1], flags); return; } if (IS_SET (obj->value[0], TRIG_RAND4) || IS_SET (obj->value[0], TRIG_RAND6)) { int maxd; if ((room = RoomTable.GetRoom (obj->value[1])) == NULL) { bug ("PullOrPush: obj points to invalid room %d", obj->value[1]); return; } if (IS_SET (obj->value[0], TRIG_RAND4)) maxd = 3; else maxd = 5; randomize_exits (room, maxd); for (rch = room->first_person; rch; rch = rch->GetNextInRoom ()) { rch->SendText ("You hear a loud rumbling sound.\n\r"); rch->SendText ("Something seems different...\n\r"); } } if (IS_SET (obj->value[0], TRIG_DOOR)) { room = RoomTable.GetRoom (obj->value[1]); if (!room) room = obj->in_room; if (!room) { bug ("PullOrPush: obj points to invalid room %d", obj->value[1]); return; } if (IS_SET (obj->value[0], TRIG_D_NORTH)) { edir = DIR_NORTH; txt = "to the north"; } else if (IS_SET (obj->value[0], TRIG_D_SOUTH)) { edir = DIR_SOUTH; txt = "to the south"; } else if (IS_SET (obj->value[0], TRIG_D_EAST)) { edir = DIR_EAST; txt = "to the east"; } else if (IS_SET (obj->value[0], TRIG_D_WEST)) { edir = DIR_WEST; txt = "to the west"; } else if (IS_SET (obj->value[0], TRIG_D_UP)) { edir = DIR_UP; txt = "from above"; } else if (IS_SET (obj->value[0], TRIG_D_DOWN)) { edir = DIR_DOWN; txt = "from below"; } else { bug ("PullOrPush: door: no direction flag set.", 0); return; } pexit = get_exit (room, edir); if (! pexit) { if (!IS_SET (obj->value[0], TRIG_PASSAGE)) { bug ("PullOrPush: obj points to non-exit %d", obj->value [1]); return; } to_room = RoomTable.GetRoom (obj->value [2]); if (! to_room) { bug ("PullOrPush: dest points to invalid room %d", obj->value[2]); return; } pexit = make_exit (room, to_room, edir); pexit->keyword = STRALLOC (""); pexit->description = STRALLOC (""); pexit->key = -1; pexit->SetFlags (0); top_exit++; act (AT_PLAIN, "A passage opens!", ch, NULL, NULL, TO_CHAR); act (AT_PLAIN, "A passage opens!", ch, NULL, NULL, TO_ROOM); return; } if (IS_SET (obj->value [0], TRIG_UNLOCK) && pexit->IsLocked ()) { pexit->ClrLocked (); act (AT_PLAIN, "You hear a faint click $T.", ch, NULL, txt, TO_CHAR); act (AT_PLAIN, "You hear a faint click $T.", ch, NULL, txt, TO_ROOM); if ((pexit_rev = pexit->rexit) != NULL && pexit_rev->GetToRoom () == ch->GetInRoom ()) pexit_rev->ClrLocked (); return; } if (IS_SET (obj->value[0], TRIG_LOCK) && ! pexit->IsLocked ()) { pexit->SetLocked (); act (AT_PLAIN, "You hear a faint click $T.", ch, NULL, txt, TO_CHAR); act (AT_PLAIN, "You hear a faint click $T.", ch, NULL, txt, TO_ROOM); if ((pexit_rev = pexit->rexit) != NULL && pexit_rev->GetToRoom () == ch->GetInRoom ()) pexit_rev->SetLocked (); return; } if (IS_SET (obj->value [0], TRIG_OPEN) && pexit->IsClosed ()) { pexit->ClrClosed (); for (rch = room->first_person; rch; rch = rch->GetNextInRoom ()) act (AT_ACTION, "The $d opens.", rch, NULL, pexit->keyword, TO_CHAR); if ((pexit_rev = pexit->rexit) != NULL && pexit_rev->GetToRoom () == ch->GetInRoom ()) { pexit_rev->ClrClosed (); for (rch = pexit->GetToRoom ()->first_person; rch; rch = rch->GetNextInRoom ()) act (AT_ACTION, "The $d opens.", rch, NULL, pexit_rev->keyword, TO_CHAR); } check_room_for_traps (ch, trap_door[edir]); return; } if (IS_SET (obj->value[0], TRIG_CLOSE) && ! pexit->IsClosed ()) { pexit->SetClosed (); for (rch = room->first_person; rch; rch = rch->GetNextInRoom ()) act (AT_ACTION, "The $d closes.", rch, NULL, pexit->keyword, TO_CHAR); if ((pexit_rev = pexit->rexit) != NULL && pexit_rev->GetToRoom () == ch->GetInRoom ()) { pexit_rev->SetClosed (); for (rch = pexit->GetToRoom ()->first_person; rch; rch = rch->GetNextInRoom ()) act (AT_ACTION, "The $d closes.", rch, NULL, pexit_rev->keyword, TO_CHAR); } check_room_for_traps (ch, trap_door[edir]); return; } } } void do_pull (CCharacter *ch, char *argument) { char arg[MAX_INPUT_LENGTH]; CObjData *obj; one_argument (argument, arg); if (arg[0] == '\0') { ch->SendText ("Pull what?\n\r"); return; } if (ms_find_obj (ch)) return; if ((obj = get_obj_here (ch, arg)) == NULL) { act (AT_PLAIN, "I see no $T here.", ch, NULL, arg, TO_CHAR); return; } pullorpush (ch, obj, TRUE); } void do_push (CCharacter *ch, char *argument) { char arg[MAX_INPUT_LENGTH]; CObjData *obj; one_argument (argument, arg); if (arg[0] == '\0') { ch->SendText ("Push what?\n\r"); return; } if (ms_find_obj (ch)) return; if ((obj = get_obj_here (ch, arg)) == NULL) { act (AT_PLAIN, "I see no $T here.", ch, NULL, arg, TO_CHAR); return; } pullorpush (ch, obj, FALSE); } void do_rap (CCharacter* ch, char* argument) { CExitData *pExit; char arg [MAX_INPUT_LENGTH]; one_argument (argument, arg); if (arg [0] == '\0') { ch->SendText ("Rap on what?\n\r"); return; } if (ch->GetFightWho ()) { ch->SendText ( "You have better things to do with your hands right now.\n\r"); return; } if (pExit = find_door (ch, arg, FALSE)) { CRoomIndexData *to_room; CExitData *pRev; char *keyword; if (! pExit->IsClosed ()) { ch->SendText ("Why knock? It's open.\n\r"); return; } if (pExit->IsSecret ()) keyword = "wall"; else keyword = pExit->keyword; act (AT_ACTION, "You rap loudly on the $d.", ch, NULL, keyword, TO_CHAR); act (AT_ACTION, "$n raps loudly on the $d.", ch, NULL, keyword, TO_ROOM); if ((to_room = pExit->GetToRoom ()) && (pRev = pExit->rexit) && pRev->GetToRoom () == ch->GetInRoom ()) { CCharacter *rch = to_room->first_person; for ( ; rch; rch = rch->GetNextInRoom ()) { act (AT_ACTION, "Someone raps loudly from the other side of the $d.", rch, NULL, pRev->keyword, TO_CHAR); } } } else { act (AT_ACTION, "You make knocking motions through the air.", ch, NULL, NULL, TO_CHAR); act (AT_ACTION, "$n makes knocking motions through the air.", ch, NULL, NULL, TO_ROOM); } } /* pipe commands (light, tamp, smoke) by Thoric */ void do_tamp (CCharacter *ch, char *argument) { CObjData *pipe; char arg[MAX_INPUT_LENGTH]; one_argument (argument, arg); if (arg[0] == '\0') { ch->SendText ("Tamp what?\n\r"); return; } if (ms_find_obj (ch)) return; if ((pipe = get_obj_carry (ch, arg)) == NULL) { ch->SendText ("You aren't carrying that.\n\r"); return; } if (pipe->item_type != ITEM_PIPE) { ch->SendText ("You can't tamp that.\n\r"); return; } if (!IS_SET (pipe->value[3], PIPE_TAMPED)) { act (AT_ACTION, "You gently tamp $p.", ch, pipe, NULL, TO_CHAR); act (AT_ACTION, "$n gently tamps $p.", ch, pipe, NULL, TO_ROOM); SET_BIT (pipe->value[3], PIPE_TAMPED); return; } ch->SendText ("It doesn't need tamping.\n\r"); } void do_smoke (CCharacter *ch, char *argument) { CObjData *pipe; char arg[MAX_INPUT_LENGTH]; one_argument (argument, arg); if (arg[0] == '\0') { ch->SendText ("Smoke what?\n\r"); return; } if (ms_find_obj (ch)) return; if ((pipe = get_obj_carry (ch, arg)) == NULL) { ch->SendText ("You aren't carrying that.\n\r"); return; } if (pipe->item_type != ITEM_PIPE) { act (AT_ACTION, "You try to smoke $p... but it doesn't seem to work.", ch, pipe, NULL, TO_CHAR); act (AT_ACTION, "$n tries to smoke $p... (I wonder what $e's been putting his $s pipe?)", ch, pipe, NULL, TO_ROOM); return; } if (!IS_SET (pipe->value[3], PIPE_LIT)) { act (AT_ACTION, "You try to smoke $p, but it's not lit.", ch, pipe, NULL, TO_CHAR); act (AT_ACTION, "$n tries to smoke $p, but it's not lit.", ch, pipe, NULL, TO_ROOM); return; } if (pipe->value[1] > 0) { if (!oprog_use_trigger (ch, pipe, NULL, NULL, NULL)) { act (AT_ACTION, "You draw thoughtfully from $p.", ch, pipe, NULL, TO_CHAR); act (AT_ACTION, "$n draws thoughtfully from $p.", ch, pipe, NULL, TO_ROOM); } if (HerbTable.IsValid (pipe->value[2]) && pipe->value[2] < HerbTable.GetCount ()) { int sn = pipe->value[2] + TYPE_HERB; CSkill *skill = SkillTable.GetValidSkill (sn); WAIT_STATE (ch, skill->GetBeats ()); if (skill->GetSpellFunction ()) obj_cast_spell (sn, UMIN (skill->GetMinLevel (), ch->GetLevel ()), ch, ch, NULL); if (obj_extracted (pipe)) return; } else bug ("do_smoke: bad herb type %d", pipe->value[2]); SET_BIT (pipe->value[3], PIPE_HOT); if (--pipe->value[1] < 1) { REMOVE_BIT (pipe->value[3], PIPE_LIT); SET_BIT (pipe->value[3], PIPE_DIRTY); SET_BIT (pipe->value[3], PIPE_FULLOFASH); } } } void do_light (CCharacter *ch, char *argument) { CObjData *pipe; char arg[MAX_INPUT_LENGTH]; one_argument (argument, arg); if (arg[0] == '\0') { ch->SendText ("Light what?\n\r"); return; } if (ms_find_obj (ch)) return; if ((pipe = get_obj_carry (ch, arg)) == NULL) { ch->SendText ("You aren't carrying that.\n\r"); return; } if (pipe->item_type != ITEM_PIPE) { ch->SendText ("You can't light that.\n\r"); return; } if (!IS_SET (pipe->value[3], PIPE_LIT)) { if (pipe->value[1] < 1) { act (AT_ACTION, "You try to light $p, but it's empty.", ch, pipe, NULL, TO_CHAR); act (AT_ACTION, "$n tries to light $p, but it's empty.", ch, pipe, NULL, TO_ROOM); return; } act (AT_ACTION, "You carefully light $p.", ch, pipe, NULL, TO_CHAR); act (AT_ACTION, "$n carefully lights $p.", ch, pipe, NULL, TO_ROOM); SET_BIT (pipe->value[3], PIPE_LIT); return; } ch->SendText ("It's already lit.\n\r"); } void do_empty (CCharacter *ch, char *argument) { CObjData *obj; char arg1[MAX_INPUT_LENGTH]; char arg2[MAX_INPUT_LENGTH]; argument = one_argument (argument, arg1); argument = one_argument (argument, arg2); if (!str_cmp (arg2, "into") && argument[0] != '\0') argument = one_argument (argument, arg2); if (arg1[0] == '\0') { ch->SendText ("Empty what?\n\r"); return; } if (ms_find_obj (ch)) return; if ((obj = get_obj_carry (ch, arg1)) == NULL) { ch->SendText ("You aren't carrying that.\n\r"); return; } if (obj->count > 1) separate_obj (obj); switch (obj->item_type) { default: act (AT_ACTION, "You shake $p in an attempt to empty it...", ch, obj, NULL, TO_CHAR); act (AT_ACTION, "$n begins to shake $p in an attempt to empty it...", ch, obj, NULL, TO_ROOM); return; case ITEM_PIPE: act (AT_ACTION, "You gently tap $p and empty it out.", ch, obj, NULL, TO_CHAR); act (AT_ACTION, "$n gently taps $p and empties it out.", ch, obj, NULL, TO_ROOM); REMOVE_BIT (obj->value[3], PIPE_FULLOFASH); REMOVE_BIT (obj->value[3], PIPE_LIT); obj->value[1] = 0; return; case ITEM_DRINK_CON: if (obj->value[1] < 1) { ch->SendText ("It's already empty.\n\r"); return; } act (AT_ACTION, "You empty $p.", ch, obj, NULL, TO_CHAR); act (AT_ACTION, "$n empties $p.", ch, obj, NULL, TO_ROOM); obj->value[1] = 0; return; case ITEM_CONTAINER: if (IS_SET (obj->value [1], CONT_CLOSED)) { act (AT_PLAIN, "The $d is closed.", ch, NULL, obj->GetName (), TO_CHAR); return; } if (obj->GetContentList ().IsEmpty ()) { ch->SendText ("It's already empty.\n\r"); return; } if (arg2 [0] == '\0') { 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 (ch->GetInRoom ()->IsNoDropAll () || ch->GetInRoom ()->IsClanStoreRoom ()) { ch->SendText ("You can't seem to do that here...\n\r"); return; } if (empty_obj (obj, NULL, ch->GetInRoom ())) { act (AT_ACTION, "You empty $p.", ch, obj, NULL, TO_CHAR); act (AT_ACTION, "$n empties $p.", ch, obj, NULL, TO_ROOM); if (SysData.IsSaveOnDrop ()) save_char_obj (ch); } else ch->SendText ("Hmmm... didn't work.\n\r"); } else { CObjData *dest = get_obj_here (ch, arg2); if (!dest) { ch->SendText ("You can't find it.\n\r"); return; } if (dest == obj) { ch->SendText ("You can't empty something into itself!\n\r"); return; } if (dest->item_type != ITEM_CONTAINER) { ch->SendText ("That's not a container!\n\r"); return; } if (IS_SET (dest->value[1], CONT_CLOSED)) { act (AT_PLAIN, "The $d is closed.", ch, NULL, dest->GetName (), TO_CHAR); return; } separate_obj (dest); if (empty_obj (obj, dest, NULL)) { act (AT_ACTION, "You empty $p into $P.", ch, obj, dest, TO_CHAR); act (AT_ACTION, "$n empties $p into $P.", ch, obj, dest, TO_ROOM); if (!dest->carried_by && SysData.IsSaveOnPut ()) save_char_obj (ch); } else act (AT_ACTION, "$P is too full.", ch, obj, dest, TO_CHAR); } return; } } /* * Apply a salve/ointment -Thoric */ void do_apply (CCharacter *ch, char *argument) { CObjData *obj; ch_ret retcode; if (argument[0] == '\0') { ch->SendText ("Apply what?\n\r"); return; } if (ms_find_obj (ch)) return; if ((obj = get_obj_carry (ch, argument)) == NULL) { ch->SendText ("You do not have that.\n\r"); return; } if (obj->item_type != ITEM_SALVE) { act (AT_ACTION, "$n starts to rub $p on $mself...", ch, obj, NULL, TO_ROOM); act (AT_ACTION, "You try to rub $p on yourself...", ch, obj, NULL, TO_CHAR); return; } separate_obj (obj); --obj->value[1]; if (!oprog_use_trigger (ch, obj, NULL, NULL, NULL)) { if (! obj->HasValidActionDescr ()) { act (AT_ACTION, "$n rubs $p onto $s body.", ch, obj, NULL, TO_ROOM); if (obj->value[1] <= 0) act (AT_ACTION, "You apply the last of $p onto your body.", ch, obj, NULL, TO_CHAR); else act (AT_ACTION, "You apply $p onto your body.", ch, obj, NULL, TO_CHAR); } else actiondesc (ch, obj, NULL); } WAIT_STATE (ch, obj->value[2]); retcode = obj_cast_spell (obj->value[4], obj->value[0], ch, ch, NULL); if (retcode == rNONE) retcode = obj_cast_spell (obj->value[5], obj->value[0], ch, ch, NULL); if (!obj_extracted (obj) && obj->value[1] <= 0) extract_obj (obj); return; } void actiondesc (CCharacter *ch, CObjData *obj, void *vo) { char charbuf[MAX_STRING_LENGTH]; char roombuf[MAX_STRING_LENGTH]; const char *srcptr = obj->GetActionDescr (); char *charptr = charbuf; char *roomptr = roombuf; const char *ichar; const char *iroom; while (*srcptr != '\0') { if (*srcptr == '$') { srcptr++; switch (*srcptr) { case 'e': ichar = "you"; iroom = "$e"; break; case 'm': ichar = "you"; iroom = "$m"; break; case 'n': ichar = "you"; iroom = "$n"; break; case 's': ichar = "your"; iroom = "$s"; break; /*case 'q': iroom = "s"; break;*/ default: srcptr--; *charptr++ = *srcptr; *roomptr++ = *srcptr; break; } } else if (*srcptr == '%' && *++srcptr == 's') { ichar = "You"; iroom = ch->IsNpc () ? ch->GetShortDescr () : ch->GetName (); } else { *charptr++ = *srcptr; *roomptr++ = *srcptr; srcptr++; continue; } while ((*charptr = *ichar) != '\0') { charptr++; ichar++; } while ((*roomptr = *iroom) != '\0') { roomptr++; iroom++; } srcptr++; } *charptr = '\0'; *roomptr = '\0'; /* sprintf (buf, "Charbuf: %s", charbuf); gpDoc->LogString (buf, LOG_HIGH, LEVEL_LESSER); sprintf (buf, "Roombuf: %s", roombuf); gpDoc->LogString (buf, LOG_HIGH, LEVEL_LESSER); */ switch (obj->item_type) { case ITEM_BLOOD: case ITEM_FOUNTAIN: act (AT_ACTION, charbuf, ch, obj, ch, TO_CHAR); act (AT_ACTION, roombuf, ch, obj, ch, TO_ROOM); return; case ITEM_DRINK_CON: act (AT_ACTION, charbuf, ch, obj, liq_table[obj->value[2]].liq_name, TO_CHAR); act (AT_ACTION, roombuf, ch, obj, liq_table[obj->value[2]].liq_name, TO_ROOM); return; case ITEM_PIPE: return; case ITEM_ARMOR: case ITEM_WEAPON: case ITEM_LIGHT: return; case ITEM_FOOD: case ITEM_PILL: act (AT_ACTION, charbuf, ch, obj, ch, TO_CHAR); act (AT_ACTION, roombuf, ch, obj, ch, TO_ROOM); return; default: return; } return; }