/************************************************************************ Realms of Aurealis James Rhone aka Vall of RoA handler.c Vital code related to char and object moving. Other miscellaneous mud handler functions. ******** Heavily modified and expanded ******** *** BE AWARE OF ALL RIGHTS AND RESERVATIONS *** ******** Heavily modified and expanded ******** All rights reserved henceforth. Please note that no guarantees are associated with any code from Realms of Aurealis. All code which has been released to the general public has been done so with an 'as is' pretense. RoA is based on both Diku and CircleMUD and ALL licenses from both *MUST* be adhered to as well as the RoA license. *** Read, Learn, Understand, Improve *** *************************************************************************/ #include "conf.h" #include "sysdep.h" #include "structures.h" #include "utils.h" #include "comm.h" #include "db.h" #include "handler.h" #include "interpreter.h" #include "acmd.h" #include "mudlimits.h" #include "magic.h" #include "affect.h" #include "lists.h" #include "fight.h" #include "global.h" #include "plshop.h" #include "objsave.h" #include "clicomm.h" #include "darkenelf.h" #include "descmenu.h" /* external vars */ extern chdata *combat_list; extern char *wv_bits[]; /* external functions */ void free_char(chdata *ch); void stop_fighting(chdata *ch); void remove_follower(chdata *ch); void clearMemory(chdata *ch); void float_sink_char(chdata *ch); void float_sink_object(obdata *ob, int room); void reload_zone(int zone); int unidle_reset_zone(int zone); void null_char_room_affects(chdata *ch); void remove_song_from_world(chdata *ch, sh_int song); void send_aff1_mesg(chdata *ch, int j, BOOL flag); void send_aff2_mesg(chdata *ch, int j, BOOL flag); int apply_ac(chdata *ch, int pos); int can_see(chdata *ch, chdata *i); int num_remorts(chdata *ch); void update_client_eq(dsdata *d); void update_client_inv(dsdata *d); void die_follower(chdata *ch); char *fname(char *namelist) { static char holder[30]; register char *point; for (point = holder; isalpha(*namelist); namelist++, point++) *point = *namelist; *point = '\0'; return(holder); } int isname(char *str, char *namelist) { register char *curname, *curstr; if (!namelist || !*namelist) return FALSE; curname = namelist; for (; ; ) { for (curstr = str; ; curstr++, curname++) { if (!*curstr && !isalpha(*curname)) return TRUE; if (!*curname) return FALSE; if (!*curstr || *curname == ' ') break; if (LOWER(*curstr) != LOWER(*curname)) break; } // skip to next name for (; isalpha(*curname); curname++) ; if (!*curname) return FALSE; curname++; /* first char of new name */ } } /* move a player out of a room */ void char_from_room(chdata *ch) { chdata *temp; int room = ch->in_room; if (IN_NOWHERE(ch)) { sprintf(buf, "SYSERR: NOWHERE chfromroom (%s)",GET_NAME(ch)); log(buf); exit(1); } if (EQ(ch, W_HOLD) && OBJ_LIGHT(EQ(ch, W_HOLD)) && LIT(EQ(ch, W_HOLD))) world[room].light--; if (IS_AFFECTED2(ch, AFF2_LIGHT)) world[room].light--; world[room].light = MAX(0, world[room].light); REMOVE_FROM_LIST(ch, world[room].people, next_in_room); if (IS_NPC(ch)) world[room].num_present--; /* -1 to the room for MOBS for now*/ else if (!IS_IMMORTAL(ch)) { if (GET_RACE(ch) == RACE_DRAGON) world[room].num_present -= 4; /* dragon size 4 */ if (GET_RACE(ch) == RACE_OGRE || GET_RACE(ch) == RACE_ORC) world[room].num_present -= 3; /* these guys are 3 */ if (GET_RACE(ch) == RACE_PIXIE || GET_RACE(ch) == RACE_NIXIE) world[room].num_present -= 1; /* small size 1 */ else world[room].num_present -= 2; /* normal size 2 */ } ch->in_room = NOWHERE; ch->next_in_room = NULL; } // give newbie eq to ch if <= level 1 and they enter newbie eq room void give_newbie_eq(chdata *ch) { obdata *ob = NULL; int i; // torch ob = read_object(172, VIRTUAL); obj_to_char(ob, ch); // bag ob = read_object(173, VIRTUAL); obj_to_char(ob, ch); // waterskin i think ob = read_object(175, VIRTUAL); obj_to_char(ob, ch); // 4 breads for (i = 0; i < 4; i++) { ob = read_object(174, VIRTUAL); obj_to_char(ob, ch); } switch (GET_CLASS(ch)) { case CLASS_WARRIOR: ob = read_object(153, VIRTUAL); obj_to_char(ob, ch); ob = read_object(162, VIRTUAL); obj_to_char(ob, ch); ob = read_object(171, VIRTUAL); obj_to_char(ob, ch); break; case CLASS_MAGE: case CLASS_MADEPT: ob = read_object(151, VIRTUAL); obj_to_char(ob, ch); ob = read_object(160, VIRTUAL); obj_to_char(ob, ch); ob = read_object(169, VIRTUAL); obj_to_char(ob, ch); break; case CLASS_CLERIC: case CLASS_DRUID: ob = read_object(152, VIRTUAL); obj_to_char(ob, ch); ob = read_object(161, VIRTUAL); obj_to_char(ob, ch); ob = read_object(171, VIRTUAL); obj_to_char(ob, ch); break; case CLASS_THIEF: ob = read_object(154, VIRTUAL); obj_to_char(ob, ch); ob = read_object(163, VIRTUAL); obj_to_char(ob, ch); ob = read_object(171, VIRTUAL); obj_to_char(ob, ch); break; case CLASS_RANGER: ob = read_object(156, VIRTUAL); obj_to_char(ob, ch); ob = read_object(165, VIRTUAL); obj_to_char(ob, ch); ob = read_object(171, VIRTUAL); obj_to_char(ob, ch); break; case CLASS_BARD: ob = read_object(157, VIRTUAL); obj_to_char(ob, ch); ob = read_object(166, VIRTUAL); obj_to_char(ob, ch); ob = read_object(170, VIRTUAL); obj_to_char(ob, ch); break; case CLASS_SHAMAN: ob = read_object(155, VIRTUAL); obj_to_char(ob, ch); ob = read_object(164, VIRTUAL); obj_to_char(ob, ch); ob = read_object(171, VIRTUAL); obj_to_char(ob, ch); break; case CLASS_MONK: ob = read_object(159, VIRTUAL); obj_to_char(ob, ch); ob = read_object(168, VIRTUAL); obj_to_char(ob, ch); ob = read_object(169, VIRTUAL); obj_to_char(ob, ch); break; case CLASS_WARLOCK: ob = read_object(158, VIRTUAL); obj_to_char(ob, ch); ob = read_object(167, VIRTUAL); obj_to_char(ob, ch); ob = read_object(170, VIRTUAL); obj_to_char(ob, ch); break; }; GET_GOLD(ch) = 500; send_to_char("%B%6You've been given some equipment and currency!%0\n\r",ch); } // if this room has a sound file... if ch has client connection... send it.. // also, after that, if mob in room has a sound.. send that void check_room_soundsend(chdata *ch) { void send_soundfile_to_client(dsdata *d, char *sound_file); chdata *m; if (INVALID_ROOM(ch->in_room)) return; if (!ch->desc || !HAS_CLIENT(ch->desc)) return; // first, check the room they're in... if (world[ch->in_room].sound_file) { send_soundfile_to_client(ch->desc, world[ch->in_room].sound_file); ch->desc->room_stimer = world[ch->in_room].music_timer; ch->desc->music_room = world[ch->in_room].number; } // ALSO have to check if a mob in the room with them is makin noise... for (m=world[ch->in_room].people; m; m=m->next_in_room) if (IS_NPC(m) && m->npc_specials.sound_file) { send_soundfile_to_client(ch->desc, m->npc_specials.sound_file); ch->desc->mob_stimer = m->npc_specials.music_timer; ch->desc->music_room = GET_MOB_VNUM(m); break; } } /* place a character in a room */ void char_to_room(chdata *ch, int room) { int zone; void reset_roazone(int zone); int purge_zone(int zone); ch->next_in_room = world[room].people; world[room].people = ch; zone = world[room].zone; /* CHECK FOR FREENESS, IF SO LOAD ROOMS AND ZONE COMLIST!!! */ /* even an immortal will trigger this one */ if (REAL_ZONE(zone) && ZONE_FREED(zone)) reload_zone(zone); if (IS_NPC(ch)) world[room].num_present++; /* add one to the room for MOBS for now*/ else if (IS_PC(ch) && !IS_IMMORTAL(ch)) { if (GET_RACE(ch) == RACE_DRAGON) world[room].num_present += 4; /* dragon size 4 */ if (GET_RACE(ch) == RACE_OGRE || GET_RACE(ch) == RACE_ORC) world[room].num_present += 3; /* these guys are 3 */ if (GET_RACE(ch) == RACE_PIXIE || GET_RACE(ch) == RACE_NIXIE) world[room].num_present += 1; /* small size 1 */ else world[room].num_present += 2; /* normal size 2 */ /* CHECK FOR IDLENESS, IF SO RESET THE ZONE!!! */ if (REAL_ZONE(zone) && ZONE_IDLE(zone)) unidle_reset_zone(zone); } ch->in_room = room; if ((room == real_room(1904)) && (GET_LEVEL(ch) <= 1)) give_newbie_eq(ch); if (EQ(ch, W_HOLD) && OBJ_LIGHT(EQ(ch, W_HOLD)) && LIT(EQ(ch, W_HOLD)) ) world[room].light++; if (IS_AFFECTED2(ch, AFF2_LIGHT)) world[room].light++; // if light isnt waterproof, extinguish it -roa if (ROOM_FLAGGED(room, UWATER) && EQ(ch, W_HOLD) && LIT(EQ(ch, W_HOLD)) && !OBJ_FLAGGED(EQ(ch, W_HOLD), ITEM_WATERPROOF)) do_extinguish(ch, "", 0, 0); // if they were eavesdroppin, pull them from it now... 4/17/98 -jtrhone if (CHAR_FLAGGED(ch, CH_EAVESDROPPING) && ch->desc && !INVALID_ROOM(ch->desc->room_snooping)) { remove_room_snooper(&world[ch->desc->room_snooping], ch->desc); REMOVE_BIT(CHAR_FLAGS(ch), CH_EAVESDROPPING); } check_room_soundsend(ch); } /* give an object to a char */ void obj_to_char(obdata *object, chdata *ch) { object->next_content = ch->carrying; ch->carrying = object; object->carried_by = ch; object->in_room = NOWHERE; IS_CARRYING_W(ch) += GET_OBJ_WEIGHT(object); IS_CARRYING_N(ch)++; if ((IS_PC(ch) && !IS_IMMORTAL(ch)) || (SPC_FLAGGED(ch, SPC_SHOPKEEP) || SPC_FLAGGED(ch, SPC_FIXER))) object->touched = TRUE; /* set flag for crash-save system */ if (IS_PC(ch)) SET_BIT(PLR_FLAGS(ch), PLR_CRASH); // update client inv list... 6/17/98 -jtrhone if (ch->desc && D_CHECK(ch->desc) && HAS_CLIENT(ch->desc) && PLR2_FLAGGED(ch, PLR2_CLIENTINV)) update_client_inv(ch->desc); } /* take an object from a char */ void obj_from_char(obdata *object) { obdata *temp = NULL; chdata *ch = object->carried_by; REMOVE_FROM_LIST(object, ch->carrying, next_content); /* this object has been touched by mortals */ if (IS_PC(ch) && !IS_IMMORTAL(ch)) object->touched = TRUE; /* player gets flagged crash for next autosave */ if (IS_PC(ch)) SET_BIT(PLR_FLAGS(ch), PLR_CRASH); IS_CARRYING_W(object->carried_by) -= GET_OBJ_WEIGHT(object); IS_CARRYING_N(object->carried_by)--; object->carried_by = NULL; object->next_content = NULL; // update client inv list... 6/17/98 -jtrhone if (ch->desc && D_CHECK(ch->desc) && HAS_CLIENT(ch->desc) && PLR2_FLAGGED(ch, PLR2_CLIENTINV)) update_client_inv(ch->desc); } // object - character restrictions, return true if any // remort only eq update 5/29/98 -jtrhone BOOL object_restricts(chdata *ch, obdata *obj) { if ((OBJ_FLAGGED(obj, ITEM_ANTI_EVIL) && IS_EVIL(ch)) ) { if (!IN_NOWHERE(ch)) { act("You, being evil, are unable to use $p.", FALSE, ch, obj, 0, TO_CHAR); act("$n is unable to use $p.", FALSE, ch, obj, 0, TO_ROOM); } else log("SYSERR: ch->in_room = NOWHERE when equipping char."); return TRUE; } if (OBJ_FLAGGED(obj, ITEM_ANTI_GOOD) && IS_GOOD(ch)) { if (!IN_NOWHERE(ch)) { act("You, being good, are unable to use $p.", FALSE, ch, obj, 0, TO_CHAR); act("$n is unable to use $p.", FALSE, ch, obj, 0, TO_ROOM); } else log("SYSERR: ch->in_room = NOWHERE when equipping char."); return TRUE; } if (OBJ_FLAGGED(obj, ITEM_ANTI_NEUTRAL) && IS_NEUTRAL(ch)) { if (!IN_NOWHERE(ch)) { act("You, being neutral, are unable to use $p.", FALSE, ch, obj, 0, TO_CHAR); act("$n is unable to use $p.", FALSE, ch, obj, 0, TO_ROOM); } else log("SYSERR: ch->in_room = NOWHERE when equipping char."); return TRUE; } if (OBJ_FLAGGED(obj, ITEM_ANTI_MAGE) && IS_NAT_MAGE(ch)) { if (!IN_NOWHERE(ch)) { act("Mages are unable to use $p.", FALSE, ch, obj, 0, TO_CHAR); act("$n is unable to use $p.", FALSE, ch, obj, 0, TO_ROOM); } else log("SYSERR: ch->in_room = NOWHERE when equipping char."); return TRUE; } if (OBJ_FLAGGED(obj, ITEM_ANTI_CLERIC) && IS_NAT_CLERIC(ch)) { if (!IN_NOWHERE(ch)) { act("Clerics are unable to use $p.", FALSE, ch, obj, 0, TO_CHAR); act("$n is unable to use $p.", FALSE, ch, obj, 0, TO_ROOM); } else log("SYSERR: ch->in_room = NOWHERE when equipping char."); return TRUE; } if (OBJ_FLAGGED(obj, ITEM_ANTI_WARRIOR) && IS_NAT_WARRIOR(ch)) { if (!IN_NOWHERE(ch)) { act("Warriors are unable to use $p.", FALSE, ch, obj, 0, TO_CHAR); act("$n is unable to use $p.", FALSE, ch, obj, 0, TO_ROOM); } else log("SYSERR: ch->in_room = NOWHERE when equipping char."); return TRUE; } if (OBJ_FLAGGED(obj, ITEM_ANTI_THIEF) && IS_NAT_THIEF(ch)) { if (!IN_NOWHERE(ch)) { act("Thieves are unable to use $p.", FALSE, ch, obj, 0, TO_CHAR); act("$n is unable to use $p.", FALSE, ch, obj, 0, TO_ROOM); } else log("SYSERR: ch->in_room = NOWHERE when equipping char."); return TRUE; } if (OBJ_FLAGGED(obj, ITEM_ANTI_SHAMAN) && IS_NAT_SHAMAN(ch)) { if (!IN_NOWHERE(ch)) { act("Shaman are unable to use $p.", FALSE, ch, obj, 0, TO_CHAR); act("$n is unable to use $p.", FALSE, ch, obj, 0, TO_ROOM); } else log("SYSERR: ch->in_room = NOWHERE when equipping char."); return TRUE; } if (OBJ_FLAGGED(obj, ITEM_ANTI_BARD) && IS_NAT_BARD(ch)) { if (!IN_NOWHERE(ch)) { act("Bards are unable to use $p.", FALSE, ch, obj, 0, TO_CHAR); act("$n is unable to use $p.", FALSE, ch, obj, 0, TO_ROOM); } else log("SYSERR: ch->in_room = NOWHERE when equipping char."); return TRUE; } if (OBJ_FLAGGED(obj, ITEM_ANTI_RANGER) && IS_NAT_RANGER(ch)) { if (!IN_NOWHERE(ch)) { act("Rangers are unable to use $p.", FALSE, ch, obj, 0, TO_CHAR); act("$n is unable to use $p.", FALSE, ch, obj, 0, TO_ROOM); } else log("SYSERR: ch->in_room = NOWHERE when equipping char."); return TRUE; } if (OBJ_FLAGGED(obj, ITEM_ANTI_WARLOCK) && IS_NAT_WARLOCK(ch)) { if (!IN_NOWHERE(ch)) { act("Warlocks are unable to use $p.", FALSE, ch, obj, 0, TO_CHAR); act("$n is unable to use $p.", FALSE, ch, obj, 0, TO_ROOM); } else log("SYSERR: ch->in_room = NOWHERE when equipping char."); return TRUE; } if (OBJ_FLAGGED(obj, ITEM_ANTI_MONK) && IS_NAT_MONK(ch)) { if (!IN_NOWHERE(ch)) { act("Monshai are unable to use $p.", FALSE, ch, obj, 0, TO_CHAR); act("$n is unable to use $p.", FALSE, ch, obj, 0, TO_ROOM); } else log("SYSERR: ch->in_room = NOWHERE when equipping char."); return TRUE; } if (OBJ_FLAGGED2(obj, ITEM_ANTI_HUMAN) && IS_HUMAN(ch)) { if (!IN_NOWHERE(ch)) { act("Humans are unable to use $p.", FALSE, ch, obj, 0, TO_CHAR); act("$n is unable to use $p.", FALSE, ch, obj, 0, TO_ROOM); } else log("SYSERR: ch->in_room = NOWHERE when equipping char."); return TRUE; } if (OBJ_FLAGGED2(obj, ITEM_ANTI_ELF) && IS_ELF(ch)) { if (!IN_NOWHERE(ch)) { act("Elves are unable to use $p.", FALSE, ch, obj, 0, TO_CHAR); act("$n is unable to use $p.", FALSE, ch, obj, 0, TO_ROOM); } else log("SYSERR: ch->in_room = NOWHERE when equipping char."); return TRUE; } if (OBJ_FLAGGED2(obj, ITEM_ANTI_HALF_ELF) && IS_HALF_ELF(ch)) { if (!IN_NOWHERE(ch)) { act("Half-elves are unable to use $p.", FALSE, ch, obj, 0, TO_CHAR); act("$n is unable to use $p.", FALSE, ch, obj, 0, TO_ROOM); } else log("SYSERR: ch->in_room = NOWHERE when equipping char."); return TRUE; } if (OBJ_FLAGGED2(obj, ITEM_ANTI_ORC) && IS_ORC(ch)) { if (!IN_NOWHERE(ch)) { act("Orcs are unable to use $p.", FALSE, ch, obj, 0, TO_CHAR); act("$n is unable to use $p.", FALSE, ch, obj, 0, TO_ROOM); } else log("SYSERR: ch->in_room = NOWHERE when equipping char."); return TRUE; } if (OBJ_FLAGGED2(obj, ITEM_ANTI_OGRE) && IS_OGRE(ch)) { if (!IN_NOWHERE(ch)) { act("Ogres are unable to use $p.", FALSE, ch, obj, 0, TO_CHAR); act("$n is unable to use $p.", FALSE, ch, obj, 0, TO_ROOM); } else log("SYSERR: ch->in_room = NOWHERE when equipping char."); return TRUE; } if (OBJ_FLAGGED2(obj, ITEM_ANTI_DROW) && IS_DROW(ch)) { if (!IN_NOWHERE(ch)) { act("Drow are unable to use $p.", FALSE, ch, obj, 0, TO_CHAR); act("$n is unable to use $p.", FALSE, ch, obj, 0, TO_ROOM); } else log("SYSERR: ch->in_room = NOWHERE when equipping char."); return TRUE; } if (OBJ_FLAGGED2(obj, ITEM_ANTI_DWARF) && IS_DWARF(ch)) { if (!IN_NOWHERE(ch)) { act("Dwarves are unable to use $p.", FALSE, ch, obj, 0, TO_CHAR); act("$n is unable to use $p.", FALSE, ch, obj, 0, TO_ROOM); } else log("SYSERR: ch->in_room = NOWHERE when equipping char."); return TRUE; } if (OBJ_FLAGGED2(obj, ITEM_ANTI_PIXIE) && IS_PIXIE(ch)) { if (!IN_NOWHERE(ch)) { act("Pixies are unable to use $p.", FALSE, ch, obj, 0, TO_CHAR); act("$n is unable to use $p.", FALSE, ch, obj, 0, TO_ROOM); } else log("SYSERR: ch->in_room = NOWHERE when equipping char."); return TRUE; } if (OBJ_FLAGGED2(obj, ITEM_ANTI_NIXIE) && IS_NIXIE(ch)) { if (!IN_NOWHERE(ch)) { act("Nixies are unable to use $p.", FALSE, ch, obj, 0, TO_CHAR); act("$n is unable to use $p.", FALSE, ch, obj, 0, TO_ROOM); } else log("SYSERR: ch->in_room = NOWHERE when equipping char."); return TRUE; } if (OBJ_FLAGGED2(obj, ITEM_ANTI_MADEPT) && IS_NAT_MADEPT(ch)) { if (!IN_NOWHERE(ch)) { act("Madept are unable to use $p.", FALSE, ch, obj, 0, TO_CHAR); act("$n is unable to use $p.", FALSE, ch, obj, 0, TO_ROOM); } else log("SYSERR: ch->in_room = NOWHERE when equipping char."); return TRUE; } if (OBJ_FLAGGED2(obj, ITEM_ANTI_DRUID) && IS_NAT_DRUID(ch)) { if (!IN_NOWHERE(ch)) { act("Druids are unable to use $p.", FALSE, ch, obj, 0, TO_CHAR); act("$n is unable to use $p.", FALSE, ch, obj, 0, TO_ROOM); } else log("SYSERR: ch->in_room = NOWHERE when equipping char."); return TRUE; } if (OBJ_FLAGGED2(obj, ITEM_ANTI_DRAGON) && IS_DRAGON(ch)) { if (!IN_NOWHERE(ch)) { act("Drakyn are unable to use $p.", FALSE, ch, obj, 0, TO_CHAR); act("$n is unable to use $p.", FALSE, ch, obj, 0, TO_ROOM); } else log("SYSERR: ch->in_room = NOWHERE when equipping char."); return TRUE; } if (OBJ_FLAGGED2(obj, ITEM_ANTI_ASSASSIN) && IS_ASSASSIN(ch)) { if (!IN_NOWHERE(ch)) { act("Assassins are unable to use $p.", FALSE, ch, obj, 0, TO_CHAR); act("$n is unable to use $p.", FALSE, ch, obj, 0, TO_ROOM); } else log("SYSERR: ch->in_room = NOWHERE when equipping char."); return TRUE; } if (OBJ_FLAGGED2(obj, ITEM_ANTI_ASSASSIN) && MOB2_FLAGGED(ch, MOB2_ASSASSIN)) { if (!IN_NOWHERE(ch)) { act("Assassins are unable to use $p.", FALSE, ch, obj, 0, TO_CHAR); act("$n is unable to use $p.", FALSE, ch, obj, 0, TO_ROOM); } else log("SYSERR: ch->in_room = NOWHERE when equipping char."); return TRUE; } if (OBJ_FLAGGED2(obj, ITEM_ASSASSIN_ONLY) && (!MOB2_FLAGGED(ch, MOB2_ASSASSIN) && !IS_ASSASSIN(ch))) { if (!IN_NOWHERE(ch)) { act("Only assassins are able to use $p.", FALSE, ch, obj, 0, TO_CHAR); act("$n is unable to use $p.", FALSE, ch, obj, 0, TO_ROOM); } else log("SYSERR: ch->in_room = NOWHERE when equipping char."); return TRUE; } // let NPCs/Immortals get remort waver 6/24/98 -jtrhone if (OBJ_FLAGGED2(obj, ITEM_REMORT_ONLY) && IS_PC(ch) && !IS_IMMORTAL(ch) && !num_remorts(ch)) { if (!IN_NOWHERE(ch)) { act("Only remorts are able to use $p.", FALSE, ch, obj, 0, TO_CHAR); act("$n is unable to use $p.", FALSE, ch, obj, 0, TO_ROOM); } else log("SYSERR: ch->in_room = NOWHERE when equipping char."); return TRUE; } // else, all is good, return ok... return FALSE; } /* RoA ... we MUST know if equip was successful! */ // updated to support wvectors 5/28/98 -jtrhone // if anything fails, give obj to char, do not make it disappear 6/4/98 -jtrhone BOOL equip_char(chdata *ch, obdata *obj, int pos, BOOL mode) { int i, j; long oldbitv1, newbitv1; long oldbitv2, newbitv2; assert(pos >= 0 && pos < MAX_WEAR); if (EQ(ch, pos) || WV_FLAGGED(ch, ((1 << pos)) )) { sprintf(buf, "SYSERR: Char already equipped: %s, %s (%d), pos: %d", GET_NAME(ch), obj->shdesc, GET_OBJ_VNUM(obj), pos); mudlog(buf, BRF, LEV_IMM, TRUE); obj_to_char(obj, ch); return FALSE; } if (obj->carried_by) { sprintf(buf, "SYSERR: EQUIP: Obj(%d: %s) carried_by %s", GET_OBJ_VNUM(obj), obj->shdesc, GET_NAME(obj->carried_by)); mudlog(buf, BRF, LEV_IMM, TRUE); obj_to_char(obj, ch); return FALSE; } if (obj->in_room != NOWHERE) { log("SYSERR: EQUIP: Obj is in_room when equip."); obj_to_char(obj, ch); return FALSE; } if (IS_AFFECTED2(ch, AFF2_CLAWS) && (pos == W_WIELD || pos == W_HOLD)) { if (!IN_NOWHERE(ch)) act("Your claws prevent you from wielding or holding anything.", FALSE, ch, 0, 0, TO_CHAR); obj_to_char(obj, ch); return FALSE; } // object_restricts now sends tailored failure messages if (!IS_IMMORTAL(ch) && object_restricts(ch, obj)) { obj_to_char(obj, ch); return FALSE; } obj->in_room = NOWHERE; EQ(ch, pos) = obj; if (ITEM_TYPE(obj) == ITEM_ARMOR) GET_AC(ch) -= apply_ac(ch, pos); oldbitv1 = AFF_FLAGS(ch); oldbitv2 = AFF2_FLAGS(ch); for (j = 0; j < MAX_OBJ_AFFECT; j++) affect_modify(ch, obj->affected[j].location, obj->affected[j].modifier, obj->eqaffbit, obj->eqaff2bit, TRUE); newbitv1 = AFF_FLAGS(ch); newbitv2 = AFF2_FLAGS(ch); for(j = 1, i = 0; i < MAX_AFFECT; i++, j *= 2) if(IS_SET(newbitv1, j) && !IS_SET(oldbitv1, j) && mode) send_aff1_mesg(ch, j, TRUE); for(j = 1, i = 0; i < MAX_AFFECT; i++, j *= 2) if(IS_SET(newbitv2, j) && !IS_SET(oldbitv2, j) && mode) send_aff2_mesg(ch, j, TRUE); affect_total(ch); // now, set wvector flags from object's wvflags and send messages 5/28/98 -jtrhone if (WV_FLAGS(obj)) { SET_BIT(WV_FLAGS(ch), WV_FLAGS(obj)); if (mode) { act("$p also occupies the following positions:", FALSE, ch, obj, 0, TO_CHAR); sprintbit(WV_FLAGS(obj), wv_bits, buf2); sprintf(buf, "%%B%%6%s%%0\n", buf2); S2C(); } } // update client eq list... 6/17/98 -jtrhone if (mode && ch->desc && D_CHECK(ch->desc) && HAS_CLIENT(ch->desc) && PLR2_FLAGGED(ch, PLR2_CLIENTEQ)) update_client_eq(ch->desc); return TRUE; } // updated to support slot revamp, 5/26/98 -jtrhone // updated to support wvectors 5/28/98 -jtrhone obdata *unequip_char(chdata *ch, int pos, BOOL mode) { int i, j; obdata *obj; long oldbitv1, newbitv1; long oldbitv2, newbitv2; assert(pos >= 0 && pos < MAX_WEAR); assert(EQ(ch, pos)); obj = EQ(ch, pos); if (ITEM_TYPE(obj) == ITEM_ARMOR) GET_AC(ch) += apply_ac(ch, pos); // this supports new slot revamp 5/26/98 -jtrhone if (OBJ_LIGHT(obj) && LIT(obj) && mode) do_extinguish(ch, "", 0, 0); EQ(ch, pos) = NULL; oldbitv1 = AFF_FLAGS(ch); oldbitv2 = AFF2_FLAGS(ch); for (j = 0; j < MAX_OBJ_AFFECT; j++) affect_modify(ch, obj->affected[j].location, obj->affected[j].modifier, obj->eqaffbit, obj->eqaff2bit, FALSE); affect_total(ch); newbitv1 = AFF_FLAGS(ch); newbitv2 = AFF2_FLAGS(ch); for(j = 1, i = 0; i < MAX_AFFECT;i++, j *= 2) if(!IS_SET(newbitv1, j) && IS_SET(oldbitv1, j) && mode) send_aff1_mesg(ch, j, FALSE); for(j = 1, i = 0; i < MAX_AFFECT;i++, j *= 2) if(!IS_SET(newbitv2, j) && IS_SET(oldbitv2, j) && mode) send_aff2_mesg(ch, j, FALSE); EQ(ch, pos) = NULL; // now, remove wvector flags from object's wvflags and send messages 5/28/98 -jtrhone if (WV_FLAGS(obj)) { REMOVE_BIT(WV_FLAGS(ch), WV_FLAGS(obj)); if (mode) { act("Removing $p has freed up the following positions:", FALSE, ch, obj, 0, TO_CHAR); sprintbit(WV_FLAGS(obj), wv_bits, buf2); sprintf(buf, "%%B%%6%s%%0\n", buf2); S2C(); } } // update client eq list... 6/17/98 -jtrhone if (mode && ch->desc && D_CHECK(ch->desc) && HAS_CLIENT(ch->desc) && PLR2_FLAGGED(ch, PLR2_CLIENTEQ)) update_client_eq(ch->desc); return(obj); } // yank a piece of eq out of equip list, place it into inventory -roa BOOL eq_to_inv(chdata *ch, int pos, BOOL tellem) { obdata *ob; assert(pos >= 0 && pos < MAX_WEAR); ob = unequip_char(ch, pos, tellem); obj_to_char(ob, ch); return TRUE; } // yank a piece of inv out of inv list, wield/wear it -roa BOOL inv_to_eq(chdata *ch, obdata *ob, int pos, BOOL tellem) { assert(pos >= 0 && pos < MAX_WEAR); obj_from_char(ob); return equip_char(ch, ob, pos, tellem); } int get_number(char **name) { int i; char *ppos; char number[MAX_INPUT_LENGTH]; *number = '\0'; if ((ppos = strchr(*name, '.'))) { *ppos++ = '\0'; strcpy(number, *name); strcpy(*name, ppos); for (i = 0; *(number + i); i++) if (!isdigit(*(number + i))) return 0; return(atoi(number)); } return 1; } /* Search a given list for an object, and return a pointer to that object */ obdata *get_obj_in_list(char *name, obdata *list) { obdata *i; int j, number; char tmpname[MAX_INPUT_LENGTH]; char *tmp; str_cpy(tmpname, name, MAX_INPUT_LENGTH, "get_obj_in_list"); tmp = tmpname; if (!(number = get_number(&tmp))) return NULL; for (i = list, j = 1; i && (j <= number); i = i->next_content) if (isname(tmp, i->name)) { if (j == number) return(i); j++; } return NULL; } /* Search a given list for an object number, and return a ptr to that obj */ obdata *get_obj_in_list_num(int num, obdata *list) { obdata *i; for (i = list; i; i = i->next_content) if (i->item_number == num) return(i); return NULL; } /*search the entire world for an object, and return a pointer */ obdata *get_obj(char *name) { obdata *i; int j, number; char tmpname[MAX_INPUT_LENGTH]; char *tmp; str_cpy(tmpname, name, MAX_INPUT_LENGTH, "get_obj"); tmp = tmpname; if (!(number = get_number(&tmp))) return NULL; for (i = object_list, j = 1; i && (j <= number); i = i->next) if (isname(tmp, i->name)) { if (j == number) return(i); j++; } return NULL; } /*search the entire world for an object number, and return a pointer */ obdata *get_obj_num(int nr) { obdata *i; for (i = object_list; i; i = i->next) if (i->item_number == nr) return(i); return NULL; } /* search a room for a char, and return a pointer if found.. */ chdata *get_char_room(char *name, int room) { chdata *i; int j, number; char tmpname[MAX_INPUT_LENGTH]; char *tmp; str_cpy(tmpname, name, MAX_INPUT_LENGTH, "get_char_room"); tmp = tmpname; if (!(number = get_number(&tmp))) return NULL; for (i = world[room].people, j = 1; i && (j <= number); i = i->next_in_room) if (isname(tmp, i->player.name)) { if (j == number) return(i); j++; } return NULL; } /* search all over the world for a char, and return a pointer if found */ chdata *get_char(char *name) { chdata *i; int j, number; char tmpname[MAX_INPUT_LENGTH]; char *tmp; if (!name || !*name) return NULL; str_cpy(tmpname, name, MAX_INPUT_LENGTH, "get_char"); tmp = tmpname; if (!(number = get_number(&tmp))) return NULL; for (i = character_list, j = 1; i && (j <= number); i = i->next) if (isname(tmp, i->player.name)) { if (j == number) return(i); j++; } return NULL; } /* search all over the world for a char num, and return a pointer if found */ chdata *get_char_num(int nr) { chdata *i; for (i = character_list; i; i = i->next) if (i->nr == nr) return(i); return NULL; } /* put an object in a room */ void obj_to_room(obdata *object, int room) { object->next_content = world[room].contents; world[room].contents = object; object->in_room = room; object->carried_by = NULL; if (ROOM_FLAGGED2(room, HOUSE)) SET_BIT(ROOM_FLAGS2(room), HOUSE_CRASH); else if (ROOM_FLAGGED2(room, SAVE_ROOM)) SET_BIT(ROOM_FLAGS2(room), ROOM_CRASH); } /* Take an object from a room */ void obj_from_room(obdata *object) { obdata *temp; if (object->in_room == NOWHERE) { sprintf(buf, "SYSERR: Obj in NOWHERE, placed in void.(%d)", GET_OBJ_VNUM(object)); mudlog(buf, BRF, LEV_IMM, TRUE); obj_to_room(object, 0); return; } REMOVE_FROM_LIST(object, world[object->in_room].contents, next_content); if (ROOM_FLAGGED2(object->in_room, HOUSE)) SET_BIT(ROOM_FLAGS2(object->in_room), HOUSE_CRASH); else if (ROOM_FLAGGED2(object->in_room, SAVE_ROOM)) SET_BIT(ROOM_FLAGS2(object->in_room), ROOM_CRASH); object->in_room = NOWHERE; object->next_content = NULL; } // place an object inside another object void obj_to_obj(obdata *obj, obdata *obj_to) { obdata *tmp_obj; if (!obj || !obj_to) return; obj->next_content = obj_to->contains; obj_to->contains = obj; obj->in_obj = obj_to; for (tmp_obj = obj->in_obj; tmp_obj->in_obj; tmp_obj = tmp_obj->in_obj) GET_OBJ_WEIGHT(tmp_obj) += GET_OBJ_WEIGHT(obj); /* top level object. Subtract weight from inventory if necessary. */ GET_OBJ_WEIGHT(tmp_obj) += GET_OBJ_WEIGHT(obj); if (tmp_obj->carried_by) IS_CARRYING_W(tmp_obj->carried_by) += GET_OBJ_WEIGHT(obj); } /* remove an object from an object */ void obj_from_obj(obdata *obj) { obdata *temp, *obj_from; if (obj->in_obj == NULL) { log("SYSERR: (handler.c): trying to illegally extract obj from obj"); return; } obj_from = obj->in_obj; REMOVE_FROM_LIST(obj, obj_from->contains, next_content); /* Subtract weight from containers container */ for (temp = obj->in_obj; temp->in_obj; temp = temp->in_obj) GET_OBJ_WEIGHT(temp) -= GET_OBJ_WEIGHT(obj); /* Subtract weight from char that carries the object */ GET_OBJ_WEIGHT(temp) -= GET_OBJ_WEIGHT(obj); if (temp->carried_by) IS_CARRYING_W(temp->carried_by) -= GET_OBJ_WEIGHT(obj); obj->in_obj = NULL; obj->next_content = NULL; } /* Set all carried_by to point to new owner */ void object_list_new_owner(obdata *list, chdata *ch) { if (list) { object_list_new_owner(list->contains, ch); object_list_new_owner(list->next_content, ch); list->carried_by = ch; } } /* Extract an object from the world */ void extract_obj(obdata *obj) { obdata *temp; if (!INVALID_ROOM(obj->in_room)) obj_from_room(obj); else if (obj->carried_by) obj_from_char(obj); else if (obj->in_obj) obj_from_obj(obj); /* leave nothing behind */ while(obj->contains) extract_obj(obj->contains); obj->contains = NULL; REMOVE_FROM_LIST(obj, object_list, next); if (GET_OBJ_RNUM(obj) >= 0) obj_index[GET_OBJ_RNUM(obj)].number--; free_obj(obj); } // update object just decrements the timers on this obj and all within it/after it in list void update_object(obdata *obj, int use) { if (!obj) { mudlog("SYSERR: NO OBJECT in update_object, handler.c", BRF, LEV_IMM, TRUE); return; } if (obj->timer > 0) obj->timer -= use; if (obj->contains) update_object(obj->contains, use); if (obj->next_content) update_object(obj->next_content, use); } // updated to support pure poisons and brewing and the like... 4/17/98 -jtrhone // updated to check hold slot for light objs rather than light slot // i.e. to support slot revamp 5/26/98 -jtrhone // todo: should move light updates to update_obj and add inv scanning void update_char_objects( chdata *ch ) { int i; BOOL waslit = FALSE; if (EQ(ch, W_HOLD) && OBJ_LIGHT(EQ(ch, W_HOLD)) && LIGHT_TIME(EQ(ch, W_HOLD)) > 0) { LIGHT_TIME(EQ(ch, W_HOLD))--; waslit = TRUE; } if (EQ(ch, W_HOLD) && OBJ_LIGHT(EQ(ch, W_HOLD)) && !LIGHT_TIME(EQ(ch, W_HOLD)) && waslit && !IN_NOWHERE(ch)) { EQ(ch, W_HOLD)->lit = FALSE; act("Your light source has burnt out!",FALSE,ch,0,0,TO_CHAR); if (world[ch->in_room].light > 0) { if ((world[ch->in_room].light--) > 0) { act("The area surrounding you gets slightly darker.",FALSE,ch,0,0,TO_CHAR); act("The area surrounding you gets slightly darker.",FALSE,ch,0,0,TO_ROOM); } else { act("The area surrounding you suddenly gets dark!",FALSE,ch,0,0,TO_CHAR); act("The area surrounding you suddenly gets dark!",FALSE,ch,0,0,TO_ROOM); } } } /* update all but light objects */ // apparently, objs in EQ list time out faster for (i = 0; i < MAX_WEAR; i++) if (EQ(ch, i) && !OBJ_LIGHT(EQ(ch, i))) update_object(EQ(ch, i), 2); // than objs in inventory (why... i dunno.. ) 4/17/98 -jtrhone if (ch->carrying) update_object(ch->carrying, 1); // now, update the poison if ch is brewing and is holding the right stuff // 4/17/98 -jtrhone if (affected_by_spell(ch, SKILL_BREW)) { obdata *o; if (!(o = EQ(ch, W_HOLD)) || (!IS_LIQCONT(o)) || (DRINKS_LEFT(o) && DRINK_TYPE(o) != LIQ_POISON)) affect_from_char(ch, SKILL_BREW); else if (!DRINKS_LEFT(o) || IS_PUREPOISON(o)) { act("You continue to brew your poison.", FALSE,ch,0,0,TO_CHAR); DRINK_TYPE(o) = LIQ_POISON; DRINKS_LEFT(o)++; POISON_LEVEL(o)++; } } } // for NPC - extract mob from real world and free_char as well... // for PCs - extract character from real world, leave char at menu... void extract_char(chdata *ch) { obdata *obj; chdata *k, *temp; dsdata *d; int l; BOOL zap = FALSE; void update_client_who(void); if (CHAR_FLAGGED(ch, CH_RECORD)) fclose(ch->fp); if (IS_PC(ch)) { global_forget(ch); if (SINGING(ch)) remove_song_from_world(ch, SINGING(ch)); if (PLAYING(ch)) remove_song_from_world(ch, PLAYING(ch)); remove_char_plshops(ch); // if they have any clpids, we wanna not point to this char anymore // 3/1/98 -jtrhone null_char_clpids(ch); } if (IS_PC(ch) && !ch->desc) for (d = descriptor_list; d; d = d->next) if (d->original == ch) do_return(d->character, "", 0, 0); if (IN_NOWHERE(ch)) { log("SYSERR: NOWHERE extracting char. (handler.c, extract_char)"); log(GET_NAME(ch)); /* just to see if mob or player next time */ exit(1); } /* if player in void or nowehere, wipe the objects RoA */ if (!ch->in_room) zap = TRUE; if (ch->followers || ch->master) die_follower(ch); if (ch->desc) { if (ch->desc->snooping) ch->desc->snooping->snoop_by = 0; if (ch->desc->snoop_by) { if (ch->desc->snoop_by->character) send_to_char("Your victim is no longer among us.\n\r", ch->desc->snoop_by->character); ch->desc->snoop_by->snooping = 0; } ch->desc->snooping = ch->desc->snoop_by = 0; // now for room snooping if (ch->desc->room_snooping) remove_room_snooper(&world[ch->desc->room_snooping], ch->desc); } if (MOB_FLAGGED(ch, MOB_PLSHOPKEEP)) { save_plshopkeep_objs(ch); extract_objects(ch->carrying); } else while (ch->carrying) { obj = ch->carrying; obj_from_char(obj); if (zap) { obj_to_room(obj, ch->in_room); extract_obj(obj); } else float_sink_object(obj, ch->in_room); } /* clear equipment_list */ for (l = 0; l < MAX_WEAR; l++) if (EQ(ch, l)) { obj = unequip_char(ch, l, FALSE); if (zap) { obj_to_room(obj, ch->in_room); extract_obj(obj); } else float_sink_object(obj, ch->in_room); } if (FIGHTING(ch)) stop_fighting(ch); for (k = combat_list; k ; k = temp) { temp = k->next_fighting; if (FIGHTING(k) == ch) stop_fighting(k); } null_char_room_affects(ch); /* in case they's a shaman and they be in a rite */ DELAY_TYPE(ch) = 0; char_from_room(ch); /* pull the char from the list */ REMOVE_FROM_LIST(ch, character_list, next); if (ch->desc && ch->desc->original) do_return(ch, "", 0, 0); if (IS_NPC(ch)) { if (GET_MOB_RNUM(ch) > -1) mob_index[GET_MOB_RNUM(ch)].number--; clearMemory(ch); free_char(ch); /* note, ch is invalid after this call */ } else if (ch->desc) { /* if they hit a dt, have them press return to go to menu */ if (CHAR_FLAGGED(ch, CH_HIT_DT)) { CHAR_FLAGS(ch) = 0; save_char(ch, NOWHERE); STATE(ch->desc) = CON_DESCMENU; descmenu_next(ch->desc, mainmenu); descmenu_push_jump(ch->desc, genericreturn); } else { CHAR_FLAGS(ch) = 0; save_char(ch, NOWHERE); STATE(ch->desc) = CON_DESCMENU; if (VT100(ch)) { resetscr(ch); send_to_q(VTMENU, ch->desc); } else send_to_q(MENU, ch->desc); descmenu_next(ch->desc, mainmenu); } // now, update the client who lists 6/15/98 -jtrhone update_client_who(); } } // unlike the previous function, this one does not leave a PC at main menu, but rather // flings him/her from the game, also does not rely on there being a descriptor // also, it's assumed all equipment has already been removed before this point... // usually called on PCs that have been force-saved -roa int eject_char(chdata *ch) { chdata *k, *temp; dsdata *d; int l; // if char is switched, return em now if (IS_PC(ch)) for (d = descriptor_list; d; d = d->next) if (d->original == ch) do_return(d->character, "", 0, 0); if (ch->followers || ch->master) die_follower(ch); // shouldn't have eq or inventory here, but hey... for (l = 0; l < MAX_WEAR; l++) if (EQ(ch, l) || ch->carrying) { sprintf(buf, "SYSERR: Ejected char had equipment/inventory (%s).", GET_NAME(ch)); mudlog(buf, BRF, LEV_IMM, TRUE); break; } // shouldn't be fighting, but just in case... if (FIGHTING(ch)) stop_fighting(ch); for (k = combat_list; k ; k = temp) { temp = k->next_fighting; if (FIGHTING(k) == ch) stop_fighting(k); } // remove any song affects and set room affects by this char to NULL if (IS_PC(ch)) { if (SINGING(ch)) remove_song_from_world(ch, SINGING(ch)); if (PLAYING(ch)) remove_song_from_world(ch, PLAYING(ch)); } null_char_room_affects(ch); /* in case they's a shaman and they be in a rite */ DELAY_TYPE(ch) = CHAR_FLAGS(ch) = 0; char_from_room(ch); // yank character from list now REMOVE_FROM_LIST(ch, character_list, next); if (IS_PC(ch)) save_char(ch, NOWHERE); else if (IS_NPC(ch)) { if (GET_MOB_RNUM(ch) > -1) mob_index[GET_MOB_RNUM(ch)].number--; clearMemory(ch); } free_char(ch); /* note, ch is invalid after this call */ return CHAR_DIED; } /* *********************************************************************** Here follows high-level versions of some earlier routines, ie functions which incorporate the actual player-data. *********************************************************************** */ // Changed this to allow 0.<name> for PCs and add "me" and "self" support // ala Circle 3.0... 03/22/98 -callahan CharData *get_char_room_vis(CharData *ch, char *name) { CharData *i; int j = 0, number; char tmpname[MAX_INPUT_LENGTH]; char *tmp = tmpname; if (IN_NOWHERE(ch)) return (NULL); if (!str_cmp(name, "self") || !str_cmp(name, "me")) return ch; // 0.<name> means PC with name str_cpy(tmp, name, MAX_INPUT_LENGTH, "get_char_room_vis"); if (!(number = get_number(&tmp))) return get_player_vis(ch, tmp, TRUE); for (i = Adjacents(ch); i && j <= number; i = i->next_in_room) if (isname(tmp, PName(i))) if (can_see(ch, i)) if (++j == number) return i; return NULL; } // Added int inroom check so 0.playername only works within a room. // 03/22/98 -callahan chdata *get_player_vis(chdata *ch, char *name, int inroom) { chdata *i; for (i = character_list; i; i = i->next) if (IS_PC(i) && !str_cmp(i->player.name, name) && can_see(ch, i) && (!inroom || (InRoom(ch) == InRoom(i)))) return i; return 0; } chdata *get_char_zone_vis(chdata *ch, char *name) { chdata *i; int j, number; char tmpname[MAX_INPUT_LENGTH]; char *tmp; /* check location */ if ((i = get_char_room_vis(ch, name))) return(i); str_cpy(tmpname, name, MAX_INPUT_LENGTH, "get_char_zone_vis"); tmp = tmpname; if (!(number = get_number(&tmp))) return(0); for (i = character_list, j = 1; i && (j <= number); i = i->next) if (isname(tmp, i->player.name) && can_see(ch, i) && !INVALID_ROOM(i->in_room) && world[i->in_room].zone == world[ch->in_room].zone) { if (j == number) return(i); j++; } return(0); } chdata *get_char_zone(int zone, char *name) { chdata *i; int j, number; char tmpname[MAX_INPUT_LENGTH]; char *tmp; str_cpy(tmpname, name, MAX_INPUT_LENGTH, "get_char_zone"); tmp = tmpname; if (!(number = get_number(&tmp))) return(0); for (i = character_list, j = 1; i && (j <= number); i = i->next) if (isname(tmp, i->player.name) && !INVALID_ROOM(i->in_room) && world[i->in_room].zone == zone) { if (j == number) return(i); j++; } return(0); } chdata *get_char_vis(chdata *ch, char *name) { chdata *i; int j, number; char tmpname[MAX_INPUT_LENGTH]; char *tmp; /* check location */ if ((i = get_char_room_vis(ch, name))) return(i); str_cpy(tmpname, name, MAX_INPUT_LENGTH, "get_char_vis"); tmp = tmpname; if (!(number = get_number(&tmp))) return(0); for (i = character_list, j = 1; i && (j <= number); i = i->next) if (isname(tmp, i->player.name) && can_see(ch, i)) { if (j == number) return(i); j++; } return(0); } obdata *get_obj_in_list_vis(chdata *ch, char *name, obdata *list) { obdata *i; int j, number; char tmpname[MAX_INPUT_LENGTH]; char *tmp; str_cpy(tmpname, name, MAX_INPUT_LENGTH, "get_obj_in_list_vis"); tmp = tmpname; if (!(number = get_number(&tmp))) return(0); for (i = list, j = 1; i && (j <= number); i = i->next_content) if (isname(tmp, i->name)) if (CAN_SEE_OBJ(ch, i)) { if (j == number) return(i); j++; } return(0); } // same as get_obj_vis, but with a zone check obdata *get_obj_zone_vis(chdata *ch, char *name) { obdata *i; int j, number; char tmpname[MAX_INPUT_LENGTH]; char *tmp; /* scan room */ if ((i = get_obj_in_list_vis(ch, name, world[ch->in_room].contents))) return(i); str_cpy(tmpname, name, MAX_INPUT_LENGTH, "get_obj_zone_vis"); tmp = tmpname; if (!(number = get_number(&tmp))) return(0); /* ok.. no luck yet. scan the entire obj list */ for (i = object_list, j = 1; i && (j <= number); i = i->next) if (isname(tmp, i->name)) if (CAN_SEE_OBJ(ch, i) && !INVALID_ROOM(i->in_room) && world[i->in_room].zone == world[ch->in_room].zone) { if (j == number) return(i); j++; } return(0); } obdata *get_object_zone(int zone, char *name) { obdata *i; int j, number; char tmpname[MAX_INPUT_LENGTH]; char *tmp; str_cpy(tmpname, name, MAX_INPUT_LENGTH, "get_obj_zone"); tmp = tmpname; if (!(number = get_number(&tmp))) return(0); for (i = object_list, j = 1; i && (j <= number); i = i->next) if (isname(tmp, i->name)) if (!INVALID_ROOM(i->in_room) && world[i->in_room].zone == zone) { if (j == number) return(i); j++; } return NULL; } /*search the entire world for an object, and return a pointer */ obdata *get_obj_vis(chdata *ch, char *name) { obdata *i; int j, number; char tmpname[MAX_INPUT_LENGTH]; char *tmp; /* scan items carried */ if ((i = get_obj_in_list_vis(ch, name, ch->carrying))) return(i); /* scan room */ if ((i = get_obj_in_list_vis(ch, name, world[ch->in_room].contents))) return(i); str_cpy(tmpname, name, MAX_INPUT_LENGTH, "get_obj_vis"); tmp = tmpname; if (!(number = get_number(&tmp))) return(0); /* ok.. no luck yet. scan the entire obj list */ for (i = object_list, j = 1; i && (j <= number); i = i->next) if (isname(tmp, i->name)) if (CAN_SEE_OBJ(ch, i)) { if (j == number) return(i); j++; } return(0); } obdata *get_object_in_equip_vis(chdata *ch, char *arg, obdata *equipment[], int *j) { for ((*j) = 0; (*j) < MAX_WEAR ; (*j)++) if (equipment[(*j)]) if (CAN_SEE_OBJ(ch, equipment[(*j)])) if (isname(arg, equipment[(*j)]->name)) return(equipment[(*j)]); return (0); } // no longer create an exdesc on money objs, now use obj ldesc 11/28/97 -jtrhone obdata *create_money(int amount) { char buf[200]; obdata *obj; if (amount <= 0) { log("SYSERR: Try to create negative or 0 currency."); exit(1); } CREATE(obj, obdata, 1); clear_object(obj); if (amount == 1) { sprintf(buf, "%s %s", currency_name, currency_name_plural); obj->name = str_dup(buf); sprintf(buf, "a %s", currency_name); obj->shdesc = str_dup(buf); sprintf(buf, "One miserable %s is lying here.", currency_name); obj->description = str_dup(buf); sprintf(buf, "One miserable %s.", currency_name); obj->actdesc = str_dup(buf); } else { sprintf(buf, "%s %s", currency_name_plural, currency_name); obj->name = str_dup(buf); if (amount <= 100) { sprintf(buf, "a small pile of %s", currency_name_plural); obj->shdesc = str_dup(buf); sprintf(buf, "A small pile of %s is lying here.", currency_name_plural); obj->description = str_dup(buf); } else if (amount <= 1000) { sprintf(buf, "a pile of %s", currency_name_plural); obj->shdesc = str_dup(buf); sprintf(buf, "A pile of %s is lying here.", currency_name_plural); obj->description = str_dup(buf); } else if (amount <= 25000) { sprintf(buf, "a large heap of %s", currency_name_plural); obj->shdesc = str_dup(buf); sprintf(buf, "A large heap of %s is lying here.", currency_name_plural); obj->description = str_dup(buf); } else if (amount <= 500000) { sprintf(buf, "a huge mound of %s", currency_name_plural); obj->shdesc = str_dup(buf); sprintf(buf, "A huge mound of %s is lying here.", currency_name_plural); obj->description = str_dup(buf); } else { sprintf(buf, "an enormous mountain of %s", currency_name_plural); obj->shdesc = str_dup(buf); sprintf(buf, "An enormous mountain of %s is lying here.", currency_name_plural); obj->description = str_dup(buf); } if (amount < 10) { sprintf(buf, "There are %d %s.", amount, currency_name_plural); obj->actdesc = str_dup(buf); } else if (amount < 100) { sprintf(buf, "There are about %d %s.", 10 * (amount / 10), currency_name_plural); obj->actdesc = str_dup(buf); } else if (amount < 1000) { sprintf(buf, "There looks to be about %d %s.", 100 * (amount / 100), currency_name_plural); obj->actdesc = str_dup(buf); } else if (amount < 100000) { sprintf(buf, "You guess there are, maybe, %d %s.", 1000 * ((amount / 1000) + number(0, (amount / 1000))), currency_name_plural); obj->actdesc = str_dup(buf); } else { sprintf(buf, "There are a LOT of %s.", currency_name_plural); obj->actdesc = str_dup(buf); } } obj->type_flag = ITEM_MONEY; OBJ_WEARS(obj) = ITEM_TAKE; obj->value[0] = amount; obj->cost = amount; obj->item_number = -1; obj->next = object_list; object_list = obj; return(obj); } /* Generic Find, designed to find any object/character */ /* Calling : */ /* *arg is the sting containing the string to be searched for. */ /* This string doesn't have to be a single word, the routine */ /* extracts the next word itself. */ /* bitv.. All those bits that you want to "search through". */ /* Bit found will be result of the function */ /* *ch This is the person that is trying to "find" */ /* **tar_ch Will be NULL if no character was found, otherwise points */ /* **tar_obj Will be NULL if no object was found, otherwise points */ /* */ /* The routine returns a pointer to the next word in *arg (just like the */ /* one_argument routine). */ int generic_find(char *arg, int bitvector, chdata *ch, chdata **tar_ch, obdata **tar_obj) { static char *ignore[] = { "the", "in", "on", "at", "\n" }; int i; char name[256]; BOOL found = FALSE; /* Eliminate spaces and "ignore" words */ while (*arg && !found) { for (; *arg == ' '; arg++) ; for (i = 0; (name[i] = *(arg + i)) && (name[i] != ' '); i++) ; name[i] = 0; arg += i; if (search_block(name, ignore, TRUE) > -1) found = TRUE; } if (!name[0]) return(0); *tar_ch = 0; *tar_obj = 0; if (IS_SET(bitvector, FIND_CHAR_ROOM)) { /* Find person in room */ if ((*tar_ch = get_char_room_vis(ch, name))) { return(FIND_CHAR_ROOM); } } if (IS_SET(bitvector, FIND_CHAR_WORLD)) { if ((*tar_ch = get_char_vis(ch, name))) { return(FIND_CHAR_WORLD); } } if (IS_SET(bitvector, FIND_OBJ_EQUIP)) { for (found = FALSE, i = 0; i < MAX_WEAR && !found; i++) if (EQ(ch, i) && isname(name, EQ(ch, i)->name)) { *tar_obj = EQ(ch, i); found = TRUE; } if (found) return(FIND_OBJ_EQUIP); } if (IS_SET(bitvector, FIND_OBJ_INV)) { if ((*tar_obj = get_obj_in_list_vis(ch, name, ch->carrying))) { return(FIND_OBJ_INV); } } if (IS_SET(bitvector, FIND_OBJ_ROOM)) { if ((*tar_obj = get_obj_in_list_vis(ch, name, world[ch->in_room].contents))) { return(FIND_OBJ_ROOM); } } if (IS_SET(bitvector, FIND_OBJ_WORLD)) { if ((*tar_obj = get_obj_vis(ch, name))) { return(FIND_OBJ_WORLD); } } return(0); } /* a function to scan for "all" or "all.x" */ int find_all_dots(char *arg) { if (!str_cmp(arg, "all")) return FIND_ALL; else if (!strncmp(arg, "all.", 4)) { strcpy(arg, arg+4); return FIND_ALLDOT; } else return FIND_INDIV; } // Function to manipulate multiple objects. 08/10/98 -callahan int ManyObjs(char *arg, char *ptr) { int amount = 0; char buff[MAX_INPUT_LENGTH]; buff[0] = 0; sscanf(arg, "%d*%s", &amount, buff); if (buff[0] == '\0') return 0; if (amount < 1) return 0; if (amount > 20) amount = 20; while (*arg != '*') arg++; arg++; for (; (*ptr = *arg); arg++, ptr++); return amount; }