/*************************************************************************** * Mud20 1.0 by Todd H. Johnson (Kregor) a derivative of the Open Gaming * * License by Wizards of the Coast. All comments referring to D20, OGL, * * and SRD refer to the System Reference Document for the Open Gaming * * system. Any inclusion of these derivatives must include credit to the * * Mud20 system, the full and complete Open Gaming LIcense, and credit to * * the respective authors. See ../doc/srd.txt for more information. * * * * Emud 2.2 by Igor van den Hoven, Michiel Lange, and Martin Bethlehem. * * * * MrMud 1.4 by David Bills, Dug Michael and Martin Gallwey * * * * Merc 2.1 Diku Mud improvments copyright (C) 1992, 1993 by Michael * * Chastain, Michael Quan, and Mitchell Tse. * * * * Original Diku Mud copyright (C) 1990 1991 by Sebastian Hammer, * * Michael Seifert, Hans Henrik St{rfeld, Tom Madsen, and Katje Nyboe. * ***************************************************************************/ /*************************************************************************** * act_move.c: player-initiated movement functions. * ***************************************************************************/ #include "mud.h" const int trap_dir[] = { TRAP_TRIG_MOVE_NORTH, TRAP_TRIG_MOVE_EAST, TRAP_TRIG_MOVE_SOUTH, TRAP_TRIG_MOVE_WEST, TRAP_TRIG_MOVE_UP, TRAP_TRIG_MOVE_DOWN }; const int trap_door[] = { TRAP_TRIG_OPEN_NORTH, TRAP_TRIG_OPEN_EAST, TRAP_TRIG_OPEN_SOUTH, TRAP_TRIG_OPEN_WEST, TRAP_TRIG_OPEN_UP, TRAP_TRIG_OPEN_DOWN }; /* Local functions. */ int scan_door args( ( CHAR_DATA *ch, char *arg ) ); OBJ_DATA *find_key args( ( CHAR_DATA *ch, int key ) ); bool move_char( CHAR_DATA *ch, int door, bool forreal, char *argument ) { CHAR_DATA *fch, *fch_next, *fch_last, *sch, *mount; ROOM_INDEX_DATA *in_room, *to_room; ROOM_TIMER_DATA *rtd; int in_room_vnum, to_room_vnum; EXIT_DATA *pExit; char buf[MAX_STRING_LENGTH]; int sdoor, move; bool drunk, found, track, CanSee; OBJ_DATA *boat, *cart; push_call("move_char(%p,%p)",ch,door); if (door < 0 || door > 5) { bug( "do_move: bad door %d.", door ); pop_call(); return FALSE; } move = 1; drunk = !IS_NPC(ch) && drunk_level(ch) >= DRUNK_DRUNK; found = FALSE; in_room_vnum = ch->in_room->vnum; in_room = ch->in_room; mount = is_mounting(ch) ? ch->mounting : ch; cart = ch->hitched; CanSee = can_see_in_room(ch, in_room) || learned(ch, gsn_blind_fight); if (!IS_NPC(ch) && forreal && is_string(ch->pcdata->pose)) { STRFREE (ch->pcdata->pose); ch->pcdata->pose = STRALLOC(""); send_to_char( "Your pose has been removed.\n\r", ch ); } /* added buildwalk function - Kregor */ if (argument) { if (!IS_NPC(ch) && IS_PLR(ch, PLR_BUILDWALK) && can_olc_modify(ch, ch->in_room->vnum)) { if ((pExit = get_exit(in_room->vnum, door)) == NULL) { if (*argument == '\0') { bool fMatch = FALSE; for (to_room_vnum = in_room->area->olc_range_lo ; to_room_vnum <= in_room->area->olc_range_hi ; to_room_vnum++) { if (get_room_index(to_room_vnum) == NULL && can_olc_modify(ch, to_room_vnum)) { fMatch = TRUE; break; } } if (!fMatch) { ch_printf_color(ch, "Next room index not found.\n\r"); pop_call(); return FALSE; } } else if (!is_number(argument) || (to_room_vnum = atoi(argument)) <= 0) { send_to_char( "Invalid vnum argument.\n\r",ch); pop_call(); return FALSE; } if (!can_olc_modify(ch, to_room_vnum)) { ch_printf_color(ch, "That vnum is not in your allocated range.\n\r"); pop_call(); return FALSE; } do_link( ch, format("%s %d both", dir_name[door], to_room_vnum) ); do_goto( ch, format("%d", to_room_vnum) ); pop_call(); return TRUE; } } } if (IS_SET(in_room->room_flags, ROOM_BLOCK)) { if ((rtd = get_room_affect(in_room, ROOM_BLOCK)) == NULL || rtd->modifier == -1 || rtd->modifier == door) { if (forreal) { if (rtd && is_string(skill_table[rtd->type].vis_affect)) act( skill_table[rtd->type].vis_affect, ch, dir_name[door], NULL, TO_CHAR); else act("You can't seem to move in that direction!", ch, NULL, NULL, TO_CHAR); } pop_call(); return FALSE; } } if (forreal) { if (IS_SET(in_room->room_flags, ROOM_ICE) && !IS_FLYING(mount) && !IS_AFFECTED(mount, AFF_WATER_WALK)) { if (!tumble_check(ch, NULL, tumble_roll(ch), 10)) { if (!refl_save(ch, NULL, 10, -1)) { switch (number_bits(1)) { case 0: act( "You slip and fall flat.", ch, NULL, NULL, TO_CHAR); act( "$n slips and falls flat.", ch, NULL, NULL, TO_ROOM); break; case 1: act( "You lose your footing and fall.", ch, NULL, NULL, TO_CHAR); act( "$n loses $s footing and falls.", ch, NULL, NULL, TO_ROOM); break; } TAKE_ACTION(ch, ACTION_MOVE); mount->position = POS_RESTING; } else { act( "You lose your balance, and manage to right yourself.", ch, NULL, NULL, TO_CHAR); TAKE_ACTION(ch, ACTION_MOVE); } pop_call(); return FALSE; } } else if (drunk) { if (mount == ch && drunk_level(ch) * drunk_level(ch) > number_percent() && !tumble_check(ch, NULL, tumble_roll(ch), 10)) { act( "You stumble over in your drunken state.", ch, NULL, NULL, TO_CHAR); act( "$n stumbles over in $s drunken state.", ch, NULL, NULL, TO_ROOM); ch->position = POS_RESTING; TAKE_ACTION(ch, ACTION_MOVE); pop_call(); return FALSE; } else { if (drunk_level(ch) * drunk_level(ch) > number_percent()) { door = number_range(0, 5); } } } else if (!CanSee) { if (mount == ch && number_percent() < 15 && !tumble_check(ch, NULL, tumble_roll(ch), 10)) { act( "You blindly stumble over yourself.", ch, NULL, NULL, TO_CHAR); act( "$n blindly stumbles over $mself.", ch, NULL, NULL, TO_ROOM); ch->position = POS_RESTING; TAKE_ACTION(ch, ACTION_MOVE); pop_call(); return FALSE; } else { if (number_percent() < 15 && !perception_check(ch, NULL, perception_roll(ch, SENSE_SIGHT), 20)) { door = number_range(0, 5); } } } } pExit = get_exit(in_room->vnum, door); if (pExit == NULL || !can_use_exit(ch, pExit)) { if (forreal) { if (drunk && !IS_OUTSIDE(ch)) { send_to_char( "You slam into somthing in your drunken state!\n\r", ch ); act( "$n slams $mself into something in $s drunken state!", ch, NULL, NULL, TO_ROOM); } else if (!CanSee && !IS_OUTSIDE(ch)) { send_to_char( "You blindly slam into something!\n\r", ch ); act( "$n slams blindly into something!", ch, NULL, NULL, TO_ROOM); } else { send_to_char( "Alas, you cannot go that way.\n\r", ch ); } } pop_call(); return FALSE; } to_room_vnum = pExit->to_room; to_room = room_index[to_room_vnum]; if (IS_SET(to_room->room_flags, ROOM_BLOCK)) { if ((rtd = get_room_affect(to_room, ROOM_BLOCK)) == NULL || rtd->modifier == -1 || rtd->modifier == rev_dir[door]) { if (forreal) { if (rtd && is_string(skill_table[rtd->type].vis_affect)) act( skill_table[rtd->type].vis_affect, ch, dir_name[door], NULL, TO_CHAR); else act("You can't seem to move in that direction!", ch, NULL, NULL, TO_CHAR); } pop_call(); return FALSE; } } if (to_room->area->low_r_vnum != ROOM_VNUM_SCHOOL) { if(!IS_NPC(ch)) { if (NOT_AUTHED(ch)) { if (forreal) { send_to_char( "You have not been authorized to enter the realms.\n\r", ch); } pop_call(); return FALSE; } if (IS_SET(pvnum_index[ch->pcdata->pvnum]->flags, PVNUM_CHNG_DESC)) { if (forreal) { send_to_char( "You have been asked to change your desc by the GMs. See HELP DESCRIPTION.\n\r", ch); } pop_call(); return FALSE; } if (ch->description[0] == '\0') { if (forreal) { send_to_char( "You need to set your description first. See HELP DESCRIPTION.\n\r", ch); } pop_call(); return FALSE; } if (ch->pcdata->adjective[0] == '\0') { if (forreal) { send_to_char( "You need to set your adjective. See HELP ADJ.\n\r", ch); } pop_call(); return FALSE; } } } if (!IS_PLR(ch, PLR_HOLYLIGHT) && !IS_NPC(ch) && ch->in_room->area != to_room->area ) { if (ch->level < to_room->area->low_hard_range) { if (forreal) { switch( to_room->area->low_hard_range - ch->level ) { case 1: send_to_char( "A voice in your mind says, 'You are nearly ready to go that way...'\n\r", ch ); break; case 2: case 3: case 4: send_to_char( "A voice in your mind says, 'Soon you shall be ready to travel down this path... soon.'\n\r", ch ); break; case 5: send_to_char( "A voice in your mind says, 'You are not ready to go down that path... yet.'.\n\r", ch); break; default: send_to_char( "A voice in your mind says, 'You are not ready to go down that path.'.\n\r", ch); } } pop_call(); return FALSE; } else if ( ch->level > to_room->area->hi_hard_range ) { if (forreal) { send_to_char( "A voice in your head says, 'There is nothing more for you down that path.'\n\r", ch ); } pop_call(); return FALSE; } } if (IS_SET(pExit->exit_info, EX_CLOSED) && !IS_AFFECTED(ch, AFF_GASEOUS) && !IS_INCORPOREAL(ch)) { if (IS_NPC(ch) || !IS_PLR(ch, PLR_HOLYLIGHT)) { if (IS_SET(pExit->exit_info, EX_HIDDEN)) { if (forreal) { if (drunk && !IS_OUTSIDE(ch)) { send_to_char( "You hit a wall in your drunken state.\n\r", ch ); act( "$n slams $mself into a wall in $s drunken state!", ch, NULL, NULL, TO_ROOM); } else { send_to_char( "Alas, you cannot go that way.\n\r", ch ); } } } else { if (forreal) { act( "The $d is closed.", ch, NULL, pExit->keyword, TO_CHAR ); } } pop_call(); return FALSE; } } if (IS_SET(pExit->exit_info, EX_CLOSED) && IS_SET(pExit->exit_info, EX_PASSPROOF)) { if (forreal) { act( "The $d remains firm.", ch, NULL, pExit->keyword, TO_CHAR ); } pop_call(); return FALSE; } if (IS_SET(pExit->exit_info, EX_JUMP) && !IS_FLYING(ch)) { if (forreal) { send_to_char("You would have to JUMP that way.\n\r", ch); pop_call(); return FALSE; } } if (IS_AFFECTED(ch, AFF_DOMINATE) && !IS_NPC(ch) && ch->master != NULL && in_room == ch->master->in_room ) { if (forreal) { send_to_char( "What? And leave your beloved master?\n\r", ch ); } pop_call(); return FALSE; } if (!IS_NPC(ch) && ch->level < LEVEL_IMMORTAL && room_is_private(to_room)) { if (forreal) { send_to_char( "That room is private right now.\n\r", ch ); } pop_call(); return FALSE; } if (in_room->sector_type == SECT_AIR || to_room->sector_type == SECT_AIR || (door == DIR_UP && IS_SET(to_room->room_flags, ROOM_NOFLOOR) && !IS_SET(pExit->exit_info, EX_CLIMB) && !is_affected(ch, gsn_spider_climb))) { if (!is_mounting(ch) && !IS_FLYING(ch)) { if (forreal) { send_to_char( "You would have to fly.\n\r", ch ); } pop_call(); return FALSE; } else if (is_mounting(ch) && !IS_FLYING(ch->mounting)) { if (forreal) { send_to_char("Your mount would need to fly.\n\r", ch); } pop_call(); return FALSE; } } if (to_room->sector_type == SECT_UNDER_WATER && in_room->sector_type != SECT_UNDER_WATER && IS_AFFECTED(ch, AFF_WATER_WALK)) { if (forreal) { send_to_char("You cannot submerge while affected by Water Walking.\n\r", ch); } pop_call(); return FALSE; } if (in_room->sector_type == SECT_OCEAN || to_room->sector_type == SECT_OCEAN || in_room->sector_type == SECT_LAKE || to_room->sector_type == SECT_LAKE) { if (!is_mounting(ch) && !IS_FLYING(ch) && !CAN_SWIM(ch)) { if (in_room->sector_type != SECT_UNDER_WATER) { for (boat = ch->first_carrying ; boat ; boat = boat->next_content) { if (IS_OBJ_TYPE(boat, ITEM_BOAT)) { found = TRUE; break; } } if (!boat && forreal && !swim_check(ch, 0)) { pop_call(); return FALSE; } } } if (is_mounting(ch) && !IS_FLYING(ch->mounting) && !CAN_SWIM(ch->mounting)) { if (in_room->sector_type != SECT_UNDER_WATER) { if (forreal) { send_to_char("Your mount can't swim.\n\r", ch); } pop_call(); return FALSE; } } } if (!IS_NPC(ch)) { if (to_room->sector_type == SECT_ASTRAL) { if (!CAN_ASTRAL_WALK(ch)) { if (forreal) { send_to_char( "You cannot traverse the astral plane.\n\r", ch ); } pop_call(); return FALSE; } } if (in_room->sector_type == SECT_ETHEREAL || to_room->sector_type == SECT_ETHEREAL) { if (!CAN_ETHEREAL_WALK(ch)) { if (forreal) { send_to_char( "You cannot traverse the ether.\n\r", ch ); } pop_call(); return FALSE; } } if (IS_SET(to_room->room_flags, ROOM_RIP) && ch->level < LEVEL_IMMORTAL) { if (ch->pcdata->pvnum != to_room->creator_pvnum) { if (forreal) { send_to_char( "Mystical wards prevent you from entering.\n\r", ch ); } pop_call(); return FALSE; } } } if (mount != ch) { switch (mount->position) { case POS_DEAD: if (forreal) { send_to_char("Your mount is dead!\n\r", ch); } pop_call(); return FALSE; case POS_MORTAL: case POS_INCAP: if (forreal) { send_to_char("Your mount is hurt far too badly to move.\n\r", ch); } pop_call(); return FALSE; case POS_STUNNED: if (forreal) { send_to_char("Your mount is too stunned to move.\n\r", ch); } pop_call(); return FALSE; case POS_SLEEPING: if (forreal) { send_to_char("Your mount is sleeping.\n\r", ch); } pop_call(); return FALSE; case POS_RESTING: case POS_CROUCHING: case POS_KNEELING: case POS_SITTING: if (forreal) { send_to_char("Your mount is not standing.\n\r", ch); } pop_call(); return FALSE; } } if (IS_ENTANGLED(mount)) { if (forreal) act("You are too tangled up to move!", ch, NULL, NULL, TO_CHAR); pop_call(); return FALSE; } if (ch->grappling) { if (forreal) { if (!in_same_room(ch, ch->grappling)) { stop_grapple(ch); } else { act("You will have to RELEASE your grapple, or DRAG $N with you!", ch, NULL, ch->grappling, TO_CHAR); pop_call(); return FALSE; } } else { pop_call(); return FALSE; } } if (ch->grappled_by) { if (forreal) { if (!in_same_room(ch, ch->grappled_by)) { stop_grapple(ch); } else { act("You failed to break $N's hold this turn.", ch, NULL, ch->grappled_by, TO_CHAR); act("$n struggles against your hold.", ch, NULL, ch->grappled_by, TO_VICT); pop_call(); return FALSE; } } else { pop_call(); return FALSE; } } if (!IS_AFFECTED(ch, AFF_FREEDOM) && (is_affected(ch, gsn_crushing_hand) || is_affected(ch, gsn_grasping_hand))) { if (forreal) { act("The giant hand holds you fast!!", ch, NULL, NULL, TO_CHAR); } pop_call(); return FALSE; } if (!IS_FLYING(mount)) { move = sector_table[in_room->sector_type].movement; if (IS_SET(pExit->exit_info, EX_CLIMB) && !is_affected(ch, gsn_spider_climb) && !race_table[get_race(ch)].climb_speed) { move *= 4; } switch (ch->in_room->sector_type) { case SECT_FIELD: case SECT_FOREST: case SECT_HILLS: case SECT_DESERT: case SECT_BEACH: case SECT_MOUNTAIN: case SECT_TUNDRA: if (learned(ch, gsn_woodland_stride)) { move = UMAX(1, move / 2); } break; case SECT_SWAMP: if (IS_AFFECTED(mount, AFF_WATER_WALK) || IS_AFFECTED(mount, AFF_FREEDOM)) { move = 1; } else if (learned(ch, gsn_woodland_stride)) { move = UMAX(1, move / 2); } else if (CAN_SWIM(mount)) { move = UMAX(1, move / 2); } break; case SECT_LAKE: case SECT_OCEAN: case SECT_RIVER: if (IS_AFFECTED(mount, AFF_WATER_WALK) || IS_AFFECTED(mount, AFF_FREEDOM)) { move = 1; } else if (CAN_SWIM(mount)) { move = UMAX(1, move / 2); } break; default: break; } } else { move = 1; } move = UMAX(1, move * mount->speed * mount->speed); /* * Make movement based on carry weight */ switch (encumberance(mount)) { case OVERLOADED: move *= 3; break; case VERY_ENCUMBERED: move *= 2; break; case ENCUMBERED: move = move * 3 / 2; break; } if (ch->in_room->sector_type == SECT_FOREST && to_room->sector_type == SECT_FOREST && is_affected(mount, gsn_tree_stride)) { move = 0; // Tree Stride = no move loss } if (IS_INCORPOREAL(ch) || CAN_ETHEREAL_WALK(ch) || IS_AFFECTED(ch, AFF_GASEOUS)) { move = 0; // Incorporeal = no move loss } /* * SRD rule: pushing a mount beyond their endurance is a DC25 handle animal check - Kregor */ if (is_mounting(ch) && ch->mounting->move < move) { if (forreal && !handle_animal_check(ch, ch->mounting, handle_animal_roll(ch), 25)) { send_to_char( "Your mount refuses to be pushed farther.\n\r", ch); pop_call(); return FALSE; } } if (forreal == FALSE) { pop_call(); return TRUE; } // reduce speed for difficult terrain check_speed(mount, ch->in_room); if (!IS_NPC(ch) || ch->desc) { if (ch->in_room->sector_type != SECT_FOREST || to_room->sector_type != SECT_FOREST || !is_affected(mount, gsn_tree_stride)) // Tree Stride = no wait state { if (IS_INCORPOREAL(ch) || CAN_ETHEREAL_WALK(ch) || IS_AFFECTED(ch, AFF_GASEOUS)) { wait_state(ch, 11 - mount->speed * 2); } else if (ch->in_room->sector_type == SECT_UNDER_WATER) { if (!CAN_SWIM(mount) && !IS_AFFECTED(mount, AFF_FREEDOM)) { wait_state(ch, (16 - mount->speed * 2) * 2); } else { wait_state(ch, (16 - mount->speed * 2) * 1); } } else if (ch->in_room->sector_type == SECT_LAKE && !IS_FLYING(mount)) { if (!CAN_SWIM(mount) && !IS_AFFECTED(mount, AFF_FREEDOM)) { wait_state(ch, (14 - mount->speed * 2) * 2); } else { wait_state(ch, (14 - mount->speed * 2) * 1); } } else if (ch->in_room->sector_type == SECT_OCEAN && !IS_FLYING(mount)) { if (!CAN_SWIM(mount) && !IS_AFFECTED(mount, AFF_FREEDOM)) { wait_state(ch, (16 - mount->speed * 2) * 2); } else { wait_state(ch, (16 - mount->speed * 2) * 1); } } else { wait_state(ch, 11 - mount->speed * 2); } } } // if (move > mount->move) // mount->nonlethal += (move - mount->move); // mount->move = UMAX(0, mount->move - move); if (!move_loss(ch, mount, move)) { pop_call(); return FALSE; } if (IS_SET(pExit->exit_info, EX_CLIMB) && !IS_FLYING(mount) && !is_affected(mount, gsn_spider_climb)) { if (forreal) { if (mount != ch) { send_to_char("You will have to dismount to climb there.\n\r", ch); pop_call(); return FALSE; } if (ch->hitched) { act("You will have to unhitch $p to climb.", ch, ch->hitched, NULL, TO_CHAR); pop_call(); return FALSE; } int check = climb_check(ch, NULL, climb_roll(ch), pExit->climb_dc); if (check == -2) { SET_AFFECT(ch, AFF2_FALLING); switch(door) { case DIR_UP: act( "You slip and fall back down.", ch, NULL, NULL, TO_CHAR); char_from_room(ch); char_to_room(ch, to_room_vnum, TRUE); pop_call(); return FALSE; case DIR_DOWN: act( "You slip and fall downwards.", ch, NULL, NULL, TO_CHAR); char_from_room(ch); char_to_room(ch, in_room_vnum, TRUE); pop_call(); return FALSE; default: break; } } else if (!check) { act( "You attempt to climb $t, but fail to make any progress.", ch, dir_name[door], NULL, TO_CHAR); act( "$n attempts to climb, and doesn't make any progress.", ch, NULL, NULL, TO_ROOM); pop_call(); return FALSE; } } } if (trig_room_trap(ch, trap_dir[door])) { if (!IS_AWAKE(ch)) { pop_call(); return FALSE; } } if (IS_SET(pExit->exit_info, EX_CLIMB) && !IS_FLYING(mount)) { sprintf(buf, " climbs %s", dir_name[door]); } else if (!IS_FLYING(mount) && ch->in_room->sector_type != SECT_UNDER_WATER && ch->in_room->sector_type != SECT_LAKE && ch->in_room->sector_type != SECT_RIVER && ch->in_room->sector_type != SECT_OCEAN) { if (is_mounting(ch)) { sprintf(buf, " rides %s", dir_name[door]); } else if (!drunk && get_race(ch) == RACE_NONE) { sprintf(buf, " leaves %s", dir_name[door]); } else if (drunk) { sprintf(buf, " stumbles satiated %swards", dir_name[door]); } else { switch (ch->speed) { case 0: sprintf(buf, " leaves slowly %sward", dir_name[door]); break; case 1: sprintf(buf, " leaves %sward", dir_name[door]); break; case 2: sprintf(buf, " hustles %sward", dir_name[door]); break; case 3: sprintf(buf, " rushes %sward", dir_name[door]); break; case 4: sprintf(buf, " leaves hastily %sward", dir_name[door]); break; case 5: sprintf(buf, " blazes %sward", dir_name[door]); break; } } } else if (IS_FLYING(mount) && ch->in_room->sector_type != SECT_UNDER_WATER) { if (drunk) { sprintf(buf, " flies zigzagging %swards", dir_name[door]); } else { sprintf(buf, " flies %s", dir_name[door]); } } else { if (found && ch->in_room->sector_type != SECT_UNDER_WATER) { if (drunk) { sprintf(buf, " sails zigzagging %swards", dir_name[door]); } else { sprintf(buf," sails %s", dir_name[door]); } } if (IS_AFFECTED(mount, AFF_WATER_WALK)) { if (is_mounting(ch)) { sprintf(buf," rides %s", dir_name[door]); } else if (drunk) { sprintf(buf," stumbles %swards", dir_name[door]); } else { sprintf(buf," walks %s", dir_name[door]); } } else { if (drunk) { sprintf(buf," swims zigzagging %swards", dir_name[door]); } else { sprintf(buf," swims %s", dir_name[door]); } } } if (is_mounting(ch)) { cat_sprintf(buf, " upon %s.", get_name(ch->mounting)); } else { cat_sprintf(buf, "."); } act( "$n$t", ch, buf, NULL, TO_SEEHEAR); /* * Chaos - code for last_left - track skill 11/14/93 * Revamped by Kregor - 3/9/07 */ switch (in_room->sector_type) { case SECT_LAKE: case SECT_OCEAN: case SECT_LAVA: case SECT_AIR: case SECT_ASTRAL: case SECT_ETHEREAL: track = FALSE; break; default: track = TRUE; break; } if ((!IS_NPC(ch) && IS_IMMORTAL(ch)) || IS_ACT(ch, ACT_MOBINVIS) || IS_INCORPOREAL(ch) || CAN_ETHEREAL_WALK(ch) || IS_AFFECTED(ch, AFF_GASEOUS) || (IS_AFFECTED(ch, AFF_SNEAK) && learned(ch, gsn_trackless_step)) || is_affected(ch, gsn_pass_without_trace)) track = FALSE; if (track) { int cnt; STRFREE(in_room->last_left[0]); for (cnt = 0 ; cnt < MAX_LAST_LEFT-1 ; cnt++) { in_room->last_left[cnt] = in_room->last_left[cnt+1]; in_room->last_left_bits[cnt] = in_room->last_left_bits[cnt+1]; in_room->last_left_pvnum[cnt] = in_room->last_left_pvnum[cnt+1]; } in_room->last_left[MAX_LAST_LEFT-1] = STRDUPE( ch->name ); if (!IS_NPC(ch)) { in_room->last_left_pvnum[MAX_LAST_LEFT-1] = ch->pcdata->pvnum; } else { in_room->last_left_pvnum[MAX_LAST_LEFT-1] = 0; } in_room->last_left_bits[MAX_LAST_LEFT-1] = 1 << door; if (100 * ch->hit / get_max_hit(ch) < 20 && !IS_UNDEAD(ch)) { SET_BIT(in_room->last_left_bits[MAX_LAST_LEFT-1], TRACK_BLOOD); } else if (IS_FLYING(ch)) { SET_BIT(in_room->last_left_bits[MAX_LAST_LEFT-1], TRACK_FLY); } } if (!IS_NPC(ch)) { mprog_exit_trigger(ch, door); rprog_exit_trigger(ch, door); if (ch->in_room != in_room) { pop_call(); return FALSE; } } char_from_room( ch ); char_to_room(ch, to_room_vnum, TRUE); in_room = room_index[in_room_vnum]; to_room = room_index[to_room_vnum]; if (to_room != ch->in_room) { pop_call(); return TRUE; } if (IS_SET(pExit->exit_info, EX_CLIMB) && !IS_FLYING(mount)) { if (door == DIR_DOWN) sprintf(buf, " climbs down from %s", rev_dir_name[door]); else if (door == DIR_UP) sprintf(buf, " climbs up from %s", rev_dir_name[door]); else sprintf(buf, " climbs in from %s", rev_dir_name[door]); } else if (!IS_FLYING(mount) && ch->in_room->sector_type != SECT_UNDER_WATER && ch->in_room->sector_type != SECT_LAKE && ch->in_room->sector_type != SECT_RIVER && ch->in_room->sector_type != SECT_OCEAN) { if (is_mounting(ch)) { sprintf(buf, " rides in from %s", rev_dir_name[door]); } else if (drunk) { sprintf(buf, " stumbles in satiated from %s", rev_dir_name[door]); } else { switch (ch->speed) { case 0: sprintf(buf," arrives slowly from %s", rev_dir_name[door]); break; case 1: sprintf(buf," arrives from %s", rev_dir_name[door]); break; case 2: sprintf(buf," hustles in from %s", rev_dir_name[door]); break; case 3: sprintf(buf," rushes in from %s", rev_dir_name[door]); break; case 4: sprintf(buf," arrives hastily from %s", rev_dir_name[door]); break; case 5: sprintf(buf," arrives in a blaze from %s", rev_dir_name[door]); break; } } } else if (IS_FLYING(mount) && ch->in_room->sector_type != SECT_UNDER_WATER) { if (drunk) { sprintf(buf, " flies in zigzagging from %s", rev_dir_name[door]); } else { sprintf(buf, " flies in from %s", rev_dir_name[door]); } } else { if (found && ch->in_room->sector_type != SECT_UNDER_WATER) { if (drunk) { sprintf(buf, " sails in zigzagging from the %s", rev_dir_name[door]); } else { sprintf(buf," sails in from %s", rev_dir_name[door]); } } else if (IS_AFFECTED(mount, AFF_WATER_WALK)) { if (is_mounting(ch)) { sprintf(buf," rides in from %s", rev_dir_name[door]); } else if (drunk) { sprintf(buf," stumbles in from %s", rev_dir_name[door]); } else { sprintf(buf," walks in from %s", rev_dir_name[door]); } } else { if (drunk) { sprintf(buf," swims zigzagging in from %s", rev_dir_name[door]); } else { sprintf(buf," swims in from %s", rev_dir_name[door]); } } } if (is_mounting(ch)) { cat_sprintf(buf, " on %s.", get_name(ch->mounting)); } else if (found && ch->in_room->sector_type != SECT_UNDER_WATER) { cat_sprintf(buf, " on %s.", boat->short_descr); } else if (cart) { cat_sprintf(buf, " pulling %s.", cart->short_descr); } else { cat_sprintf(buf, "."); } act( "$n$t", ch, buf, NULL, TO_SEEHEAR); do_look( ch, "" ); if (ch->in_room->sector_type != SECT_ASTRAL && !IS_NPC(ch) && ch->in_room->vnum > 5) { ch->pcdata->last_real_room = ch->in_room->vnum; } if (IS_AFFECTED(ch, AFF_DETECT_TRAPS) || learned(ch, gsn_trap_spotter)) { OBJ_DATA *obj; for (obj = ch->in_room->first_content ; obj ; obj = obj->next_content) { if (IS_OBJ_TYPE(obj, ITEM_TRAP) && is_trap_armed(obj)) { if (IS_AFFECTED(ch, AFF_DETECT_TRAPS)) { send_to_char_color( "{118}You detect a trap here!", ch ); break; } else if (perception_check(ch, NULL, perception_roll(ch, SENSE_SIGHT), trap_dc(obj))) { send_to_char_color( "{118}You spot a trap here!", ch ); break; } } } } // if (!IS_IMMORTAL(ch) && !IS_NPC(ch) && in_room->area != to_room->area) // { // if (ch->level < to_room->area->low_soft_range) // { // send_to_char("You feel uncomfortable being in this strange land...\n\r", ch); // } // else if (ch->level > to_room->area->hi_soft_range) // { // send_to_char("You feel there is not much to gain visiting this place...\n\r", ch); // } // } // if (!IS_FLYING(mount)) { if (IS_SET(ch->in_room->room_flags, ROOM_ICE) && !IS_AFFECTED(mount, AFF_WATER_WALK)) { if (!tumble_check(mount, NULL, tumble_roll(ch), 10)) { if (!refl_save(mount, NULL, 10, -1)) { switch (number_bits(1)) { case 0: act( "You slip and fall flat on your back.", mount, NULL, NULL, TO_CHAR); act( "$n slips and falls flat on $s back.", mount, NULL, NULL, TO_ROOM); break; case 1: act( "You lose your footing and fall.", mount, NULL, NULL, TO_CHAR); act( "$n loses $s footing and falls.", mount, NULL, NULL, TO_ROOM); break; } TAKE_ACTION(ch, ACTION_FULL); mount->position = POS_RESTING; } else { act( "You lose your balance, and manage to right yourself.", mount, NULL, NULL, TO_CHAR); act( "$n loses $s balance, but manages to right $mrself.", mount, NULL, NULL, TO_CHAR); TAKE_ACTION(ch, ACTION_MOVE); } pop_call(); return FALSE; } } if ((rtd = get_room_affect(ch->in_room, ROOM_ENTANGLE)) != NULL) { CHAR_DATA *caster; if ((caster = get_caster_room(rtd)) == NULL || caster != ch || !is_same_group(caster, ch)) { if (rtd->type == gsn_entangle) act( "{128}Plants and vines whip around and snag at you.", ch, NULL, NULL, TO_CHAR); if (!IS_AFFECTED(ch, AFF_FREEDOM)) { if (!IS_AFFECTED(ch, AFF2_ENTANGLED) && !refl_save(ch, NULL, rtd->level, gsn_entangle)) { AFFECT_DATA af; act( "{128}Plants and vines whip around and snag $n.", ch, NULL, NULL, TO_ROOM); af.type = rtd->type; af.duration = rtd->duration; af.modifier = 0; af.location = APPLY_NONE; af.bittype = AFFECT_TO_CHAR; af.bitvector = AFF2_ENTANGLED; af.level = rtd->level; af.caster = STRALLOC(rtd->caster); affect_join( caster, ch, &af ); } } } } if (is_room_affected(ch->in_room, gsn_faithful_hound)) { CHAR_DATA *caster; if ((caster = get_caster_room(rtd)) != NULL && caster != ch) { act( "{138}The voice of a dog unseen by you barks furiously.", ch, NULL, NULL, TO_CHAR); act( "{138}Your spectral hound barks at $n furiously.", ch, NULL, caster, TO_VICT); act( "{138}The voice of an unseen dog barks at $n furiously.", ch, NULL, caster, TO_NOTVICT); } } } /* * For swift tracker ability - Kregor 3/9/07 */ if (!IS_NPC(ch) && ch->pcdata->tracking) { CHAR_DATA * rch; for (rch = ch->in_room->first_person ; rch ; rch = rch->next_in_room) { if (rch == ch->pcdata->tracking) { send_to_char_color("{138}You've found your prey!\n\r", ch); stop_tracking(ch); break; } } if (rch == NULL) { track_char(ch, ch->pcdata->tracking); } } if (mount != ch) { ch->mounting = mount; } if (cart) { ch->hitched = cart; } if (ch->in_room == in_room) { pop_call(); return FALSE; } else if (mount != ch) { char_from_room(mount); char_to_room(mount, ch->in_room->vnum, TRUE); } if (cart) { send_to_room(format("%s trundles %sward.\n\r", cart->short_descr, dir_name[door]), cart->in_room); obj_from_room(cart); obj_to_room(cart, ch->in_room->vnum); } /* Take followers along */ fch_last = in_room->last_person; for (fch = in_room->first_person ; fch ; fch = fch_next) { fch_next = fch->next_in_room; if (fch->in_room != in_room) { fch_next = in_room->first_person; continue; } if (fch->master == ch && fch->position == POS_STANDING && fch->in_room != ch->in_room) { fch->speed = mount->speed; // first, match leader's speed. check_speed(fch, fch->in_room); // then, see if he can keep up. if (fch->speed < mount->speed) { if (fch->leader != ch) { act( "You move too fast for $N to follow.", ch, NULL, fch, TO_CHAR); act( "$n moves too fast for you to follow.", ch, NULL, fch, TO_VICT); continue; } act( "$N can't move that fast, so you slow down.", ch, NULL, fch, TO_CHAR); mount->speed = fch->speed; for (sch = ch->master ; sch ; sch = sch->master) { if (sch->speed != mount->speed && sch->in_room == ch->in_room) { sch->speed = mount->speed; } else { break; } } } act( "You follow $N\n\r.", fch, NULL, ch, TO_CHAR ); move_char( fch, door, TRUE, NULL ); } if (fch == fch_last) { break; } } if (!IS_NPC(ch)) { mprog_greet_trigger(ch); oprog_greet_trigger(ch); rprog_greet_trigger(ch); } /* make shadowers shadow player -Dug */ if (!IS_NPC(ch)) { if ((fch = ch->pcdata->shadowed_by) != NULL) { if (fch->position == POS_STANDING && (fch->in_room != ch->in_room)) { for (sdoor = 0 ; sdoor < 6 ; sdoor++) { if ((pExit = get_exit(fch->in_room->vnum, sdoor)) != NULL && room_index[pExit->to_room] == in_room) { CHAR_DATA *tch; ch_printf_color(fch, "%s leaves %s.\n\r", dir_name[door], get_name(ch)); fch->speed = mount->speed; check_speed(fch, fch->in_room); if (mount->speed <= fch->speed) { fch->speed = ch->speed; ch_printf_color(fch, "You follow at a discrete distance.\n\r"); tch = fch->pcdata->shadowing; fch->pcdata->shadowing = NULL; move_char( fch, sdoor, TRUE, NULL ); fch->pcdata->shadowing = tch; if (can_see(ch, fch) && !bluff_check(fch, ch, bluff_roll(fch), 0)) { act( "{138}You sense you are being followed by $n.", fch, NULL, ch, TO_VICT); } } else { act( "$N is moving too fast for you to follow.", fch, NULL, ch, TO_CHAR); } break; } } if (sdoor == 6) { stop_shadow(fch); } } else { stop_shadow(fch); } } if (ch->pcdata->shadowing) { stop_shadow(ch); } if (IS_SET(ch->act, PLR_WIZTIME)) { ch_printf_color(ch, "{058}DEBUG: %d move point used\n\r", move); } } mprog_entry_trigger(ch); rprog_entry_trigger(ch); pop_call(); return FALSE; } bool can_move_char( CHAR_DATA *ch, int door ) { return move_char(ch, door, FALSE, NULL); } /* * Subtract move points from character - return FALSE when unconscious * SRD adaptation: pushing yourself while exhausted is a forced march * Take 2 pts nonlethal damage per move pt below 0 - Kregor */ bool move_loss( CHAR_DATA *ch, CHAR_DATA *mount, int move ) { CHAR_DATA *victim; push_call("move_loss(%p,%p)",ch,move); if (mount == NULL) victim = ch; else victim = mount; if (victim->move < move) { if (mount == NULL || mount == ch) act( "You are pushing yourself beyond your endurance!", victim, NULL, NULL, TO_CHAR ); else act( "$N is being pushed beyond $S endurance!", ch, NULL, victim, TO_CHAR ); victim->nonlethal += (move - victim->move) * 2; victim->move = UMAX(0, victim->move - move); update_pos(victim,-1); } else { victim->move -= move; } if (!IS_AWAKE(victim)) { send_to_char_color("{138}You fall unconscious from exhaustion.\n\r", victim); act( "$n falls unconscious from exhaustion.", victim, NULL, NULL, TO_ROOM); pop_call(); return FALSE; } pop_call(); return TRUE; } /* * Shove and Drag * Original code from Ferris@FootPrints.net * adapted to Mud20 by Kregor */ char * const shove_drag_verb [] = { "shove", "drag", "*" }; void shove_drag( CHAR_DATA *ch, char *argument, bool fDrag ) { char arg1[MAX_INPUT_LENGTH]; char arg2[MAX_INPUT_LENGTH]; char buf[MAX_STRING_LENGTH]; ROOM_INDEX_DATA *in_room; ROOM_INDEX_DATA *to_room; CHAR_DATA *victim; EXIT_DATA *pExit; OBJ_DATA *obj; int door; push_call("shove_drag(%p,%s,%s)",ch,argument,fDrag); argument = one_argument(argument, arg1); argument = one_argument(argument, arg2); if (arg1[0] == '\0' || arg2[0] == '\0') { act("$t whom or what where?", ch, shove_drag_verb[fDrag], NULL, TO_CHAR); pop_call(); return; } if ((obj = get_obj_list(ch, arg1, ch->in_room->first_content)) == NULL) { if ((victim = get_char_room(ch, arg1)) == NULL) { act("$t whom or what where?", ch, shove_drag_verb[fDrag], NULL, TO_CHAR); pop_call(); return; } } if ((door = direction_door(arg2)) == -1) { act("Alas, you cannot $t anything in that direction.", ch, shove_drag_verb[fDrag], NULL, TO_CHAR); pop_call(); return; } if ((pExit = get_exit(ch->in_room->vnum, door)) == NULL || (to_room = room_index[pExit->to_room]) == NULL) { bug("shove_drag: NULL room",0); pop_call(); return; } if (!can_move_char(ch, door)) { act( "You are unable to $t anything $Tward.", ch, shove_drag_verb[fDrag], dir_name[door], TO_CHAR); pop_call(); return; } if (obj) { if (!IS_PLR(ch, PLR_HOLYLIGHT) && !IS_SET(obj->wear_flags, CAN_WEAR_TAKE)) { act("$p won't budge.", ch, obj, NULL, TO_CHAR); pop_call(); return; } if (IS_SET(pExit->exit_info, EX_CLOSED)) { act( "You cannot $t it through $d.", ch, shove_drag_verb[fDrag], pExit->keyword, TO_CHAR); act( "$n decides to $t $P around!", ch, shove_drag_verb[fDrag], obj, TO_ROOM); pop_call(); return; } if (get_obj_weight(obj) > (5 * can_carry_w(ch)) - ch->carry_weight) { act( "$p is too heavy to $T.", ch, obj, shove_drag_verb[fDrag], TO_CHAR); sprintf(buf, "$n attempts to %s $p $Tward, but it's too heavy.", shove_drag_verb[fDrag]); act( buf, ch, obj, dir_name[door], TO_ROOM); pop_call(); return; } if (!move_loss(ch, NULL, UMAX(1,get_obj_weight(obj) / 100))) { pop_call(); return; } obj_from_room(obj); obj_to_room(obj, to_room->vnum); if (fDrag) { act( "$n drags $p $Tward.", ch, obj, dir_name[door], TO_ROOM); move_char( ch, door, TRUE, NULL ); act( "You drag $p in from the $T.", ch, obj, rev_dir_name[door], TO_CHAR); act( "$n drags $p in from $T", ch, obj, rev_dir_name[door], TO_ROOM); } else { act( "You shove $p $Tward.", ch, obj, dir_name[door], TO_CHAR); act( "$n shoves $p $Tward.", ch, obj, dir_name[door], TO_ROOM); sprintf(buf, "%s is shoved in from %s.\n\r", obj->short_descr, rev_dir_name[door]); send_to_room(buf, to_room); } TAKE_ACTION(ch, ACTION_MOVE); pop_call(); return; } if (ch == victim) { act( "You cannot $t yourself.", ch, shove_drag_verb[fDrag], NULL, TO_CHAR); pop_call(); return; } in_room = victim->in_room; if (!IS_PLR(ch, PLR_HOLYLIGHT)) { if (IS_AWAKE(victim) && is_safe(ch,victim)) { pop_call(); return; } if (IS_NPC(victim) && (IS_SET(victim->act,ACT_TRAIN|ACT_IS_HEALER) || victim->pIndexData->pShop || victim->pIndexData->pStable || victim->pIndexData->pInn)) { act("$N won't budge.", ch, NULL, victim, TO_CHAR); pop_call(); return; } } if (IS_AWAKE(victim) && !can_move_char(victim, door)) { act( "You are unable to $t them $Tward.", ch, shove_drag_verb[fDrag], dir_name[door], TO_CHAR); act( "$n tries to $t you around!", ch, shove_drag_verb[fDrag], victim, TO_VICT); act( "$n tries to $t $N around!", ch, shove_drag_verb[fDrag], victim, TO_NOTVICT); pop_call(); return; } // for now simply intercepts, until grappling is coded. if (fDrag && IS_AWAKE(victim) && (!victim->grappled_by || victim->grappled_by != ch)) { act( "If you want to drag $N around, you need to grapple $M first.", ch, NULL, victim, TO_CHAR); pop_call(); return; } bool shoved = FALSE; /* * Bull Rushing rules in play here. * Shoving is hostile, so check murder and AoO are called - Kregor */ if (!fDrag) { if (!IS_AWAKE(victim)) { act( "$N is not conscious, you would need to drag $M.", ch, NULL, victim, TO_CHAR); pop_call(); return; } if (get_size(ch) + 1 < get_size(victim)) { act( "$N is too big for you to shove around.", ch, NULL, victim, TO_CHAR); pop_call(); return; } if (is_mounting(victim)) { send_to_char( "You can't shove a mounted target... MAYBE you could shove the mount.\n\r", ch ); pop_call(); return; } int check; CHECK_TURN(ch, victim); if (in_combat(ch) && !is_active(ch) && !has_opportunity(ch, victim)) { send_to_char("Just wait your turn.\n\r", ch); pop_call(); return; } if (!check_murder(ch, victim)) { pop_call(); return; } if (in_combat(ch) && !is_active(ch)) take_opportunity(ch, victim); TAKE_ACTION(ch, ACTION_STANDARD); if (!learned(ch, gsn_imp_bullrush) || (learned(victim, gsn_combat_reflexes) && victim->level > ch->level - 4)) { if (attack_of_opportunity(victim, ch)) { if (!IS_AWAKE(ch)) { pop_call(); return; } } } if ((check = combat_maneuver_check(ch, victim, gsn_bullrush)) >= 10) shoved = TRUE; else if (check >= 0) { act( "You shove $N back away from you.", ch, NULL, victim, TO_CHAR); act( "$n shoves you back away from $m.", ch, NULL, victim, TO_VICT); act( "$n shoves $N back away from $m.", ch, NULL, victim, TO_NOTVICT); victim->distracted = 2; if (IS_NPC(victim) && !in_combat(victim)) fight(victim, ch); pop_call(); return; } } if (!IS_AWAKE(victim) && victim->weight + victim->carry_weight > can_carry_w(ch) * 5) { sprintf(buf, "You attempt to %s $N $tward, but $E is too heavy.", shove_drag_verb[fDrag]); act( buf, ch, dir_name[door], victim, TO_CHAR); sprintf(buf, "$n attempts to %s $N $tward, but $E is too heavy.", shove_drag_verb[fDrag]); act( buf, ch, dir_name[door], victim, TO_NOTVICT); sprintf(buf, "$n attempts to %s you $tward, but $E is too heavy.", shove_drag_verb[fDrag]); act( buf, ch, dir_name[door], victim, TO_VICT); pop_call(); return; } if (IS_AWAKE(victim) && !shoved) { sprintf(buf, "You attempt to %s $N $tward, and fail.", shove_drag_verb[fDrag]); act( buf, ch, dir_name[door], victim, TO_CHAR); sprintf(buf, "$n attempts to %s $N $tward, and fails.", shove_drag_verb[fDrag]); act( buf, ch, dir_name[door], victim, TO_NOTVICT); sprintf(buf, "$n attempts to %s you $tward, and fails.", shove_drag_verb[fDrag]); act( buf, ch, dir_name[door], victim, TO_VICT); if (IS_NPC(victim) && !in_combat(victim)) fight(victim, ch); pop_call(); return; } if (!move_loss(ch, NULL, UMAX(1, get_weight(victim) / 10))) { pop_call(); return; } char_from_room(victim); char_to_room(victim, to_room->vnum, TRUE); if (IS_AWAKE(victim)) do_look(victim, "auto"); else TAKE_ACTION(ch, ACTION_MOVE); if (fDrag) { move_char( ch, door, TRUE, NULL ); act( "$N is dragged in by $n from $t.", ch, rev_dir_name[door], victim, TO_NOTVICT); act( "You are dragged in by $n from $t.", ch, rev_dir_name[door], victim, TO_VICT); act( "You drag $N in from $t.", ch, rev_dir_name[door], victim, TO_CHAR); } else { act( "$n is shoved in from $t.", victim, rev_dir_name[door], NULL, TO_NOTVICT); act( "$N is shoved $tward.", ch, dir_name[door], victim, TO_CHAR); act( "$N is shoved $tward by $n.", ch, dir_name[door], victim, TO_ROOM); if (IS_NPC(victim) && !IS_NPC(ch) && ch != victim) { if (victim->npcdata->hate_fear != ch->pcdata->pvnum) { victim->npcdata->hate_fear = ch->pcdata->pvnum; } } } pop_call(); return; } void do_shove(CHAR_DATA *ch, char *argument) { shove_drag(ch, argument, FALSE); return; } void do_drag(CHAR_DATA *ch, char *argument) { shove_drag(ch, argument, TRUE); return; } void do_shadow (CHAR_DATA * ch, char *argument) { char arg1[MAX_INPUT_LENGTH], arg2[MAX_INPUT_LENGTH]; CHAR_DATA *victim; int door; ROOM_INDEX_DATA *old_room; push_call("do_shadow(%p,%p)",ch,argument); if (IS_NPC(ch)) { send_to_char("You failed.\n\r", ch); pop_call(); return; } argument = one_argument(argument, arg1); argument = one_argument(argument, arg2); if ((door = direction_door(arg1)) == -1) { if ((door = direction_door(arg2)) == -1) { send_to_char ("What direction?\n\r", ch); pop_call(); return; } else { strcpy(arg2, arg1); } } if (arg2[0] == '\0') { send_to_char ("Shadow whom?\n\r", ch); pop_call(); return; } if (!is_valid_exit(ch, ch->in_room, door)) { send_to_char ("There is no exit there.\n\r", ch); pop_call(); return; } old_room = ch->in_room; ch->in_room = room_index[get_exit(ch->in_room->vnum, door)->to_room]; victim = get_char_room(ch, arg2); ch->in_room = old_room; if (victim == NULL || victim->in_room == ch->in_room) { send_to_char ("They aren't there.\n\r", ch); pop_call(); return; } if (streetwise_check(ch, victim, streetwise_roll(ch), bluff_roll(victim))) { act ("You fail to shadow $m.", ch, NULL, victim, TO_CHAR); pop_call(); return; } if (IS_NPC(victim) || victim->pcdata->shadowed_by || victim->pcdata->shadowing) { act ("You can't seem to shadow $m.", ch, NULL, victim, TO_CHAR); pop_call(); return; } if (ch->master) { stop_follower(ch); } if (ch->pcdata->shadowing) { stop_shadow(ch); } add_shadow(ch, victim); pop_call(); return; } void add_shadow (CHAR_DATA * ch, CHAR_DATA * master) { push_call("add_shadow(%p,%p)",ch,master); if (ch->pcdata->shadowing) { bug("add_shadow : already shadowing.", 0); pop_call(); return; } ch->pcdata->shadowing = master; master->pcdata->shadowed_by = ch; act ("You are now shadowing $N.", ch, NULL, master, TO_CHAR); pop_call(); return; } void stop_shadow (CHAR_DATA * ch) { push_call("stop_shadow(%p)",ch); if (IS_NPC(ch) || ch->pcdata->shadowing == NULL) { pop_call(); return; } act ("You stop shadowing $N.", ch, NULL, ch->pcdata->shadowing, TO_CHAR); ch->pcdata->shadowing->pcdata->shadowed_by = NULL; ch->pcdata->shadowing = NULL; pop_call(); return; } void do_land( CHAR_DATA *ch, char *argument ) { push_call("do_land(%p,%p)",ch,argument); if (IS_AFFECTED(ch, AFF_FLYING)) { act( "{168}$n descends and lands.{300}", ch, NULL, NULL, TO_ROOM ); act( "{168}You descend and land.{300}", ch, NULL, NULL, TO_CHAR ); REMOVE_BIT( ch->affected_by, AFF_FLYING ); } else { send_to_char( "You are not currently airborne.\n\r", ch ); } pop_call(); return; } void do_fly( CHAR_DATA *ch, char *argument ) { push_call("do_land(%p,%p)",ch,argument); if (!CAN_FLY(ch)) { send_to_char_color("Nice try, but you can't fly.\n\r", ch); pop_call(); return; } else { if (!IS_AFFECTED(ch, AFF_FLYING)) { act( "{168}$n launches $mself into the air!{300}", ch, NULL, NULL, TO_ROOM ); act( "{168}You launch yourself into the air!{300}", ch, NULL, NULL, TO_CHAR ); SET_BIT( ch->affected_by, AFF_FLYING ); } else { send_to_char_color("{168}You are already airborne.{300}\n\r", ch); } } pop_call(); return; } /* * Automatically adjust speed at move_char * based on room conditions - Kregor 5/4/12 */ void check_speed( CHAR_DATA *ch, ROOM_INDEX_DATA *room ) { CHAR_DATA *mount = NULL; int current; push_call("check_speed(%p,%p)",ch,room); // NPCs move at normal speed by default if (IS_NPC(ch) && !is_mounted(ch)) { if (ch->npcdata->hate_fear) // unless chasing or fleeing someone ch->speed = UMAX(SPEED_RUN, ch->speed); else if (IS_AFFECTED(ch, AFF_HASTE)) ch->speed = URANGE(SPEED_NORMAL, ch->speed, SPEED_HASTE); else ch->speed = URANGE(SPEED_NORMAL, ch->speed, SPEED_RUN); } else if (IS_PLR(ch, PLR_HOLYLIGHT)) { pop_call(); return; } else if (IS_AFFECTED(ch, AFF_HASTE)) { ch->speed = UMIN(ch->speed, SPEED_HASTE); } else { ch->speed = UMIN(ch->speed, SPEED_RUN); } current = ch->speed; if (is_mounting(ch)) { mount = ch->mounting; } else { mount = ch; } //can always move at half speed if (current == SPEED_HALF) { pop_call(); return; } if (IS_FATIGUED(mount) && current > SPEED_NORMAL) { if (mount != ch) send_to_char("Your mount is too fatigued to run.", ch); else send_to_char("You are too fatigued to run.", ch); current = SPEED_NORMAL; } switch (encumberance(mount)) { case ENCUMBERED: case VERY_ENCUMBERED: if (current > SPEED_NORMAL) { if (mount != ch) send_to_char("Your mount is encumbered and can only walk.", ch); else send_to_char("You are encumbered and can only walk.", ch); current = SPEED_NORMAL; } break; case OVERLOADED: if (current > SPEED_HALF) { if (mount != ch) send_to_char("Your mount is overloaded and can only move at half speed.\n\r", ch); else send_to_char("You are overloaded and can only move at half speed.\n\r", ch); current = SPEED_HALF; } break; } if (is_affected(mount, gsn_cripple) && current > SPEED_HALF) { if (mount != ch) send_to_char("Your mount is crippled and can only move at half speed.\n\r", ch); else send_to_char("You are crippled and can only move at half speed.\n\r", ch); current = SPEED_HALF; } if (IS_BLIND(ch) && current > SPEED_HALF && !learned(mount, gsn_blindsight) && !domain_apotheosis(ch, DOMAIN_CAVERN)) { if (learned(ch, gsn_blind_fight) && current > SPEED_NORMAL) { act("You cannot run while you are blinded.", ch, NULL, NULL, TO_CHAR); current = SPEED_NORMAL; } else { act("You can only move at half speed while you are blinded.", ch, NULL, NULL, TO_CHAR); current = SPEED_HALF; } } if (!IS_NPC(ch) && ch->pcdata->tracking) { if (current > SPEED_NORMAL && !learned(ch, gsn_master_hunter)) { send_to_char("You cannot move that quickly while tracking.\n\r", ch); current = SPEED_NORMAL; } if (current > SPEED_HUSTLE) { send_to_char("You cannot move that quickly while tracking.\n\r", ch); current = SPEED_HUSTLE; } } if (IS_AFFECTED(ch, AFF_HIDE) && current) { if (learned(ch, gsn_camouflage) && IS_OUTSIDE(ch) && current > SPEED_NORMAL) { send_to_char( "You can only move at normal or slower speed while hiding.\n\r" ,ch); current = SPEED_NORMAL; } else if (learned(ch, gsn_swift_stealth) && current > SPEED_NORMAL) { send_to_char( "You can only move at normal or slower speed while hiding.\n\r" ,ch); current = SPEED_NORMAL; } else { send_to_char( "You can only move at half speed while hiding.\n\r" ,ch); current = SPEED_HALF; } } if (IS_AFFECTED(ch, AFF_SNEAK) && current > SPEED_HUSTLE) { send_to_char( "You cannot sneak while running.\n\r", ch); AFFECT_STRIP(ch, AFF_SNEAK); } if (IS_SET(room->room_flags, ROOM_ICE)) { if (!IS_SHIFT(race_table[get_race(mount)].sectors, SECT_TUNDRA) && !IS_AFFECTED(mount, AFF_WATER_WALK)) { act("{168}You cannot move that fast on the ice.", ch, NULL, NULL, TO_CHAR); current = SPEED_HALF; } } if (!can_see_in_room(ch, room)) { act("{108}You cannot see to move that fast!", ch, NULL, NULL, TO_CHAR); current = SPEED_HALF; } // Freedom trumps environmental conditions if (!IS_AFFECTED(mount, AFF_FREEDOM)) { if (IS_SET(room->room_flags, ROOM_ENTANGLE)) { act("You cannot move that fast in your surroundings.", ch, NULL, NULL, TO_CHAR); current = SPEED_HALF; } // creatures native to a terrain have no restriction for terrain if (!IS_SHIFT(race_table[get_race(ch)].sectors, room->sector_type)) { if (!IS_FLYING(ch)) // terrain that only affects if on the ground { switch (room->sector_type) { case SECT_OCEAN: case SECT_RIVER: case SECT_LAKE: if (!rspec_req(mount, RSPEC_AQUATIC) && !CAN_SWIM(mount)) { act("You cannot move that fast in your surroundings.", ch, NULL, NULL, TO_CHAR); current = SPEED_HALF; } break; case SECT_SWAMP: if (!rspec_req(mount, RSPEC_AQUATIC) && !CAN_SWIM(mount) && !learned(mount, gsn_woodland_stride)) { act("You cannot move that fast in your surroundings.", ch, NULL, NULL, TO_CHAR); current = SPEED_HALF; } break; case SECT_DESERT: case SECT_BEACH: if (!learned(mount, gsn_woodland_stride)) { if (current > SPEED_NORMAL) { act("You cannot move that fast in your surroundings.", ch, NULL, NULL, TO_CHAR); current = SPEED_NORMAL; } } break; case SECT_UNDER_WATER: if (!rspec_req(mount, RSPEC_AQUATIC) && !CAN_SWIM(mount)) { act("You cannot move that fast in your surroundings.", ch, NULL, NULL, TO_CHAR); current = SPEED_HALF; } break; case SECT_LAVA: if (!IS_AFFECTED(mount, AFF_WATER_WALK)) { act("You cannot move that fast in your surroundings.", ch, NULL, NULL, TO_CHAR); current = SPEED_HALF; } break; case SECT_TUNDRA: if (!learned(mount, gsn_woodland_stride) && !IS_AFFECTED(mount, AFF_WATER_WALK)) { if (current > SPEED_NORMAL) { act("You cannot move that fast in your surroundings.", ch, NULL, NULL, TO_CHAR); current = SPEED_NORMAL; } } break; } } } } ch->speed = current; if (mount != ch) mount->speed = current; pop_call(); return; } void do_speed( CHAR_DATA *ch, char *argument ) { int value; push_call("do_speed(%p,%p)",ch,argument); if (argument[0]=='\0') { ch_printf_color(ch, "Usage: speed <%s>\n\r", give_flags(move_speeds)); send_to_char( "This allows changing of rate of movement. Rates effect the amount of MV lost.\n\r", ch); ch_printf_color( ch, " {200}Current move speed: {178}%s{300}\n\r", capitalize(move_speeds[ch->speed])); pop_call(); return; } if ((value = get_flag(argument, move_speeds)) == -1) { send_to_char( "That is not a valid speed.\n\r" ,ch); pop_call(); return; } ch->speed = value; check_speed(ch, ch->in_room); ch_printf_color( ch, "{200}Speed set to: {178}%s{300}.\n\r", capitalize(move_speeds[ch->speed])); if (IS_AFFECTED(ch, AFF_SNEAK) && ch->speed > 0) { switch (ch->speed) { default: break; case 1: if ((!IS_OUTSIDE(ch) || !learned(ch, gsn_camouflage)) && !learned(ch, gsn_swift_stealth)) ch_printf_color( ch, "You suffer a penalty of -5 to your stealth roll at this speed.\n\r" ); break; case 2: ch_printf_color( ch, "You suffer a penalty of -20 to your stealth roll at this speed.\n\r" ); break; } } pop_call(); return; } void do_north( CHAR_DATA *ch, char *argument ) { push_call("do_north(%p,%p)",ch,argument); move_char( ch, DIR_NORTH, TRUE, argument ); pop_call(); return; } void do_east( CHAR_DATA *ch, char *argument ) { push_call("do_east(%p,%p)",ch,argument); move_char( ch, DIR_EAST, TRUE, argument ); pop_call(); return; } void do_south( CHAR_DATA *ch, char *argument ) { push_call("do_south(%p,%p)",ch,argument); move_char( ch, DIR_SOUTH, TRUE, argument ); pop_call(); return; } void do_west( CHAR_DATA *ch, char *argument ) { push_call("do_west(%p,%p)",ch,argument); move_char( ch, DIR_WEST, TRUE, argument ); pop_call(); return; } void do_up( CHAR_DATA *ch, char *argument ) { push_call("do_up(%p,%p)",ch,argument); move_char( ch, DIR_UP, TRUE, argument ); pop_call(); return; } void do_down( CHAR_DATA *ch, char *argument ) { push_call("do_down(%p,%p)",ch,argument); move_char( ch, DIR_DOWN, TRUE, argument ); pop_call(); return; } /* * The JUMP command, used to leap up, down or across * exits with the EX_JUMP flag - Kregor * * USING THE FLAG: * Ideally, a jump across should be to get over a pit, accomplished * by setting a downward exit with a fall_dist, can be flagged * EX_JUMP and/or EX_CLIMB. It is assumed you are jumping over this * exit to get the direction you wish to go. Failure makes you fall * into this pit room. The room across from the EX_JUMP exit should * also be flagged EX_JUMP in the opposing direction, with a like * downward pit room below it that adjoins with the pit room * beneath the other room. */ void do_jump( CHAR_DATA *ch, char *argument ) { int dir, diceroll, dc, reach, check; EXIT_DATA *pExit; ROOM_INDEX_DATA *to_room; char direction[6]; push_call("do_jump(%p,%p)",ch,argument); if (argument[0] == '\0') { act( "Jump in what direction?", ch, NULL, NULL, TO_CHAR); pop_call(); return; } if ((dir = direction_door(argument)) == -1) { send_to_char("There is nowhere to jump in that direction.\n\r",ch); pop_call(); return; } if ((pExit = get_exit(ch->in_room->vnum, dir)) == NULL) { send_to_char("There is nowhere to jump in that direction.\n\r",ch); pop_call(); return; } if ((to_room = room_index[pExit->to_room]) == NULL) { log_build_printf(ch->in_room->vnum, "do_jump: NULL room"); pop_call(); return; } if (!IS_SET(pExit->exit_info, EX_JUMP)) { send_to_char("You cannot jump to get there.\n\r",ch); pop_call(); return; } if (!can_use_exit(ch, pExit)) { if(IS_SET(ch->in_room->room_flags, ROOM_INDOORS)) { act( "You slam yourself into the wall!", ch, NULL, NULL, TO_CHAR ); act( "$n slams $mself into the wall!", ch, NULL, NULL, TO_ROOM ); } else { send_to_char( "Alas, you cannot go that way.\n\r", ch ); } } if (!can_move_char(ch, dir)) { send_to_char("You cannot jump there.\n\r",ch); pop_call(); return; } diceroll = jump_roll(ch); reach = (get_height(ch) + 12) / 12; switch (dir) { case DIR_UP: if (pExit->fall_dist < reach) dc = 0; else dc = (pExit->fall_dist - reach) * 4; break; case DIR_NORTH: case DIR_SOUTH: case DIR_EAST: case DIR_WEST: dc = pExit->fall_dist; break; case DIR_DOWN: if (pExit->fall_dist < reach) dc = 0; else dc = 15; break; } if ((check = jump_check(ch, NULL, diceroll, dc)) >= 0) { if (check <= -5 || !refl_save(ch, NULL, 20, -1)) { /* use falling code in char_to_room to damage char if fails downward jump */ if (dir == DIR_DOWN) { act( "You try to jump $T, but fall.", ch, NULL, dir_name[dir], TO_CHAR); act( "$n tries to jump $T, but falls.", ch, NULL, dir_name[dir], TO_ROOM); set_falling(ch, pExit->fall_dist); char_from_room(ch); char_to_room(ch, pExit->to_room, TRUE); do_look(ch, ""); if (!IS_NPC(ch)) { mprog_greet_trigger(ch); oprog_greet_trigger(ch); rprog_greet_trigger(ch); } pop_call(); return; } else if (dir == DIR_UP) { act( "You try to jump $T, but do not succeed.", ch, NULL, dir_name[dir], TO_CHAR); act( "$n tries to jump $T, but does not succeed.", ch, NULL, dir_name[dir], TO_ROOM); pop_call(); return; } else { act( "You try to jump across to the $T, but falls short.", ch, NULL, dir_name[dir], TO_CHAR); act( "$n tries to jump across to the $T, but falls short.", ch, NULL, dir_name[dir], TO_ROOM); /* If there's a pit, fall into it! */ if ((pExit = get_exit(ch->in_room->vnum, DIR_DOWN)) != NULL && pExit->fall_dist && !can_move_char(ch, DIR_DOWN)) { set_falling(ch, pExit->fall_dist); act( "$n falls downward!", ch, NULL, NULL, TO_ROOM); char_from_room(ch); char_to_room(ch, pExit->to_room, TRUE); do_look(ch, ""); if (!IS_NPC(ch)) { mprog_greet_trigger(ch); oprog_greet_trigger(ch); rprog_greet_trigger(ch); } } pop_call(); return; } } } if (dir >= 4) sprintf(direction, "high"); else { sprintf(direction, "long"); if ((pExit = to_room->exit[dir]) == NULL) { log_build_printf(to_room->vnum, "do_jump: no valid exit to jump to"); pop_call(); return; } } act( "You make an athletic $t jump $Tward.", ch, direction, dir_name[dir], TO_CHAR); act( "$n makes an athletic $t jump $Tward.", ch, direction, dir_name[dir], TO_ROOM); char_from_room(ch); char_to_room(ch, pExit->to_room, TRUE); do_look(ch, ""); /* if not trained in Jump, char lands prone unless check made by 5 or more */ if (check < 0 || (check < 5 && !learned(ch, gsn_jump))) { act( "$n leaps in from $T, landing flat on $s face.", ch, NULL, rev_dir_name[dir], TO_ROOM); act( "{178}You land flat on your face on the other side.", ch, NULL, NULL, TO_CHAR); ch->position = POS_RESTING; } else { act( "$n leaps in from $T.", ch, NULL, rev_dir_name[dir], TO_ROOM); } if (!IS_NPC(ch)) { mprog_greet_trigger(ch); oprog_greet_trigger(ch); rprog_greet_trigger(ch); } pop_call(); return; } int scan_door( CHAR_DATA *ch, char *arg ) { char door_name[MAX_INPUT_LENGTH]; int count, number, door; EXIT_DATA *pExit; push_call("scan_door(%p,%p)",ch,arg); number = number_argument(arg, door_name); count = 0; for (door = 0 ; door <= 5 ; door++) { if ((pExit = get_exit(ch->in_room->vnum, door)) == NULL) { continue; } if (!IS_SET(pExit->exit_info, EX_ISDOOR)) { continue; } if (!pExit->keyword || !is_name(door_name, pExit->keyword)) { continue; } if (!can_use_exit(ch, pExit)) { continue; } if (IS_SET(pExit->exit_info, EX_HIDDEN) && !can_see_hidden(ch,door)) { continue; } if (++count != number) { continue; } pop_call(); return door; } pop_call(); return( -1 ); } int find_door( CHAR_DATA *ch, char *arg ) { EXIT_DATA *pExit; int door = -1; push_call("find_door(%p,%p)",ch,arg); if ((door = scan_door(ch, arg)) >= 0) { pop_call(); return door; } if ((door = direction_door(arg)) == -1) { pop_call(); return -1; } if ((pExit = get_exit(ch->in_room->vnum, door)) == NULL) { pop_call(); return -1; } if (!IS_SET(pExit->exit_info, EX_ISDOOR)) { pop_call(); return -1; } if (!can_use_exit(ch, pExit)) { pop_call(); return -1; } if (IS_SET(pExit->exit_info, EX_HIDDEN) && !can_see_hidden(ch,door)) { pop_call(); return -1; } pop_call(); return door; } void do_open( CHAR_DATA *ch, char *argument ) { char arg[MAX_INPUT_LENGTH]; OBJ_DATA *obj; int door; push_call("do_open(%p,%p)",ch,argument); one_argument( argument, arg ); if (!check_blind(ch)) { pop_call(); return; } if (arg[0] == '\0') { send_to_char( "Open what?\n\r", ch ); pop_call(); return; } if (IS_INCORPOREAL(ch) || !is_handy(ch)) { act("You are unable to open anything.", ch, NULL, NULL, TO_CHAR); pop_call(); return; } if ((door = find_door(ch, arg)) >= 0) { ROOM_INDEX_DATA *to_room; EXIT_DATA *pExit; EXIT_DATA *pExit_rev; pExit = ch->in_room->exit[door]; if (!IS_SET(pExit->exit_info, EX_CLOSED)) { send_to_char( "It's already open.\n\r", ch); pop_call(); return; } /* * Auto unlock - Scandum 02-07-2002 */ if (IS_SET(pExit->exit_info, EX_LOCKED) && !IS_SET(pExit->exit_info, EX_KNOCKED)) { OBJ_DATA *key = NULL; switch (pExit->key) { case -2: break; case -1: case 0: send_to_char("It's locked.\n\r", ch); pop_call(); return; default: if ((key = find_key(ch, pExit->key)) == NULL) { send_to_char( "It's locked.\n\r", ch); pop_call(); return; } break; } REMOVE_BIT(pExit->exit_info, EX_LOCKED); if (key) { act( "You unlock the $d with $p.", ch, key, pExit->keyword, TO_CHAR); act( "$n unlocks the $d with $p.", ch, key, pExit->keyword, TO_ROOM); } else { act( "You unlock the $d.", ch, NULL, pExit->keyword, TO_CHAR); act( "$n unlocks the $d.", ch, NULL, pExit->keyword, TO_ROOM); } if ((to_room = room_index[pExit->to_room]) != NULL && (pExit_rev = to_room->exit[rev_dir[door]]) != NULL && room_index[pExit_rev->to_room] == ch->in_room) { REMOVE_BIT(pExit_rev->exit_info, EX_LOCKED); } } REMOVE_BIT(pExit->exit_info, EX_CLOSED); act( "$n opens the $d.", ch, NULL, pExit->keyword, TO_ROOM ); act( "You open the $d.", ch, NULL, pExit->keyword, TO_CHAR ); if ((to_room = room_index[pExit->to_room]) != NULL && (pExit_rev = to_room->exit[rev_dir[door]]) != NULL && room_index[pExit_rev->to_room] == ch->in_room ) { REMOVE_BIT(pExit_rev->exit_info, EX_CLOSED); ch->in_room = to_room; act( "The $d opens.", ch, NULL, pExit_rev->keyword, TO_ROOM); ch->in_room = room_index[pExit_rev->to_room]; } trig_room_trap(ch, trap_door[door]); } else if ((obj = get_obj_here(ch, arg)) != NULL) { if (obj->item_type != ITEM_SPELLPOUCH && obj->item_type != ITEM_CONTAINER && obj->item_type != ITEM_SHEATH && obj->item_type != ITEM_CART && obj->item_type != ITEM_QUIVER) { send_to_char( "That's not a container.\n\r", ch ); pop_call(); return; } if (!IS_SET(obj->value[1], CONT_CLOSED)) { send_to_char( "It's already open.\n\r", ch ); pop_call(); return; } if (!IS_SET(obj->value[1], CONT_CLOSEABLE)) { send_to_char( "It's not closeable.\n\r", ch ); pop_call(); return; } if (IS_SET(obj->value[1], CONT_LOCKED)) { if (obj->value[2] < 1) { send_to_char( "It's locked.\n\r", ch ); pop_call(); return; } if (find_key(ch, obj->value[2]) == NULL) { send_to_char( "It's locked.\n\r", ch ); pop_call(); return; } REMOVE_BIT(obj->value[1], CONT_LOCKED); act( "You unlock $p.", ch, obj, NULL, TO_CHAR ); if (obj->carried_by == ch) act( "$n unlocks $p.", ch, obj, NULL, TO_CAN_SEE ); else act( "$n unlocks $p.", ch, obj, NULL, TO_ROOM ); trig_obj_trap(ch, obj, TRAP_TRIG_OPEN_OBJ); } REMOVE_BIT(obj->value[1], CONT_CLOSED); act( "You open $p.", ch, obj, NULL, TO_CHAR ); if (obj->carried_by == ch) act( "$n opens $p.", ch, obj, NULL, TO_CAN_SEE ); else act( "$n opens $p.", ch, obj, NULL, TO_ROOM ); trig_obj_trap(ch, obj, TRAP_TRIG_OPEN_OBJ); } else { act( "You see no $T here.", ch, NULL, arg, TO_CHAR ); } pop_call(); return; } void do_close( CHAR_DATA *ch, char *argument ) { char arg[MAX_INPUT_LENGTH]; OBJ_DATA *obj; int door; push_call("do_close(%p,%p)",ch,argument); one_argument( argument, arg ); if (!check_blind(ch)) { pop_call(); return; } if (arg[0] == '\0') { send_to_char( "Close what?\n\r", ch ); pop_call(); return; } if ((door = find_door(ch, arg)) >= 0) { ROOM_INDEX_DATA *to_room; EXIT_DATA *pExit; EXIT_DATA *pExit_rev; pExit = ch->in_room->exit[door]; if (IS_SET(pExit->exit_info, EX_CLOSED)) { send_to_char( "It's already closed.\n\r", ch ); pop_call(); return; } if (IS_SET(pExit->exit_info, EX_BASHED)) { send_to_char( "It's been bashed off its hinges!\n\r", ch ); pop_call(); return; } SET_BIT(pExit->exit_info, EX_CLOSED); act( "$n closes the $d.", ch, NULL, pExit->keyword, TO_ROOM ); act( "You close the $d.", ch, NULL, pExit->keyword, TO_CHAR ); if ((to_room = room_index[pExit->to_room]) != NULL && (pExit_rev = to_room->exit[rev_dir[door]]) != 0 && room_index[pExit_rev->to_room] == ch->in_room) { CHAR_DATA *rch; SET_BIT( pExit_rev->exit_info, EX_CLOSED ); for (rch = to_room->first_person ; rch ; rch = rch->next_in_room) { act( "The $d closes.", rch, NULL, pExit_rev->keyword, TO_CHAR ); } } } else if ((obj = get_obj_here(ch, arg)) != NULL) { if (obj->item_type != ITEM_SPELLPOUCH && obj->item_type != ITEM_CONTAINER && obj->item_type != ITEM_SHEATH && obj->item_type != ITEM_CART && obj->item_type != ITEM_QUIVER) { send_to_char( "That's not a container.\n\r", ch ); pop_call(); return; } if (IS_SET(obj->value[1], CONT_CLOSED)) { send_to_char( "It's already closed.\n\r", ch ); pop_call(); return; } if (!IS_SET(obj->value[1], CONT_CLOSEABLE)) { send_to_char( "It's not closeable.\n\r", ch ); pop_call(); return; } SET_BIT(obj->value[1], CONT_CLOSED); act( "You close $p.", ch, obj, NULL, TO_CHAR ); if (obj->carried_by == ch) act( "$n closes $p.", ch, obj, NULL, TO_CAN_SEE ); else act( "$n closes $p.", ch, obj, NULL, TO_ROOM ); } else { act( "You see no $T here.", ch, NULL, arg, TO_CHAR ); } pop_call(); return; } OBJ_DATA *find_key( CHAR_DATA *ch, int key ) { OBJ_DATA *obj; push_call("find_key(%p,%p)",ch,key); for (obj = ch->first_carrying ; obj ; obj = obj->next_content) { if ((obj->pIndexData->vnum == key) || ((obj->item_type == ITEM_KEY) && (key == obj->value[0]))) { pop_call(); return obj; } } pop_call(); return NULL; } void do_knock (CHAR_DATA *ch, char *argument) { int door; char arg[MAX_INPUT_LENGTH]; ROOM_INDEX_DATA *to_room; EXIT_DATA *pExit; EXIT_DATA *pExit_rev; push_call("do_knock(%p,%p)",ch,argument); argument = one_argument (argument, arg); if ((door = find_door(ch, arg)) == -1) { send_to_char ("That's not a door.\n\r", ch); pop_call(); return; } pExit = ch->in_room->exit[door]; if (!IS_SET(pExit->exit_info, EX_ISDOOR) ) { send_to_char ("There's no door on it.\n\r", ch); pop_call(); return; } else if (!IS_SET(pExit->exit_info, EX_CLOSED)) { send_to_char ("It's already open!\n\r", ch); pop_call(); return; } act( "$n knocks on the $d.", ch, NULL, pExit->keyword, TO_ROOM ); act( "You knock on the $d.", ch, NULL, pExit->keyword, TO_CHAR ); if ((to_room = room_index[pExit->to_room]) != NULL && (pExit_rev = to_room->exit[rev_dir[door]]) != 0 && room_index[pExit_rev->to_room] == ch->in_room) { CHAR_DATA *rch; for (rch = to_room->first_person ; rch ; rch = rch->next_in_room) { act( "Someone knocks on the $d.", rch, NULL, pExit_rev->keyword, TO_CHAR ); } } pop_call(); return; } void do_lock( CHAR_DATA *ch, char *argument ) { char arg[MAX_INPUT_LENGTH]; OBJ_DATA *obj; int door, dc; push_call("do_lock(%p,%p)",ch,argument); if (!check_blind(ch)) { pop_call(); return; } one_argument( argument, arg ); if (arg[0] == '\0') { send_to_char( "Lock what?\n\r", ch ); pop_call(); return; } if ((door = find_door(ch, arg)) >= 0) { ROOM_INDEX_DATA *to_room; EXIT_DATA *pExit; EXIT_DATA *pExit_rev; pExit = ch->in_room->exit[door]; if (!IS_SET(pExit->exit_info, EX_CLOSED)) { if (IS_SET(pExit->exit_info, EX_BASHED)) { send_to_char("It's been bashed off its hinges!\n\r", ch); pop_call(); return; } send_to_char("The door is wide open.\n\r", ch); pop_call(); return; } if (IS_SET(pExit->exit_info, EX_LOCKED)) { send_to_char( "It's already locked.\n\r", ch); pop_call(); return; } if (pExit->key == -1) { send_to_char( "It can't be locked.\n\r", ch ); pop_call(); return; } if (IS_SET(pExit->exit_info, EX_KNOCKED)) { send_to_char( "Magical energies prevent it from being locked.\n\r", ch); pop_call(); return; } if (!IS_SET(pExit->exit_info, EX_CLOSED)) { act( "You need to close the $d to lock it.", ch, NULL, pExit->keyword, TO_CHAR ); pop_call(); return; } if (pExit->key != -2 && find_key(ch, pExit->key) == NULL) { if (!learned(ch, gsn_pick_lock)) { send_to_char( "You lack the key.\n\r", ch); pop_call(); return; } dc = lock_dc(pExit, NULL); if (!pick_lock_check(ch, NULL, pick_lock_roll(ch), dc)) { send_to_char( "You failed to rig the lock.\n\r", ch); pop_call(); return; } } SET_BIT(pExit->exit_info, EX_LOCKED); act( "You lock the $d.", ch, NULL, pExit->keyword, TO_CHAR); act( "$n locks the $d.", ch, NULL, pExit->keyword, TO_ROOM); if ((to_room = room_index[pExit->to_room]) != NULL && (pExit_rev = to_room->exit[rev_dir[door]]) != 0 && room_index[pExit_rev->to_room] == ch->in_room) { SET_BIT( pExit_rev->exit_info, EX_LOCKED ); } pop_call(); return; } if ((obj = get_obj_here(ch, arg)) == NULL) { act( "You see no $T here.", ch, NULL, arg, TO_CHAR ); pop_call(); return; } else { if (obj->item_type == ITEM_CONTAINER) { if (IS_SET(obj->value[1], CONT_LOCKED)) { send_to_char( "It's already locked.\n\r", ch ); pop_call(); return; } if (obj->value[2] < 1) { send_to_char( "It can't be locked.\n\r", ch); pop_call(); return; } if (IS_SET(obj->value[1], CONT_KNOCKED)) { send_to_char( "Magical energies prevent it from being locked.\n\r", ch ); pop_call(); return; } if (!IS_SET(obj->value[1], CONT_CLOSED)) { act( "You need to close $p to lock it.", ch, obj, NULL, TO_CHAR ); pop_call(); return; } if (find_key(ch, obj->value[2]) == NULL) { if (!learned(ch, gsn_pick_lock)) { send_to_char( "You lack the key.\n\r", ch); pop_call(); return; } dc = lock_dc(NULL, obj); if (!pick_lock_check(ch, NULL, pick_lock_roll(ch), dc)) { send_to_char( "You failed to rig the lock.\n\r", ch ); pop_call(); return; } } SET_BIT(obj->value[1], CONT_LOCKED); act( "You lock $p.", ch, obj, NULL, TO_CHAR ); act( "$n locks $p.", ch, obj, NULL, TO_ROOM ); } else if (obj->item_type == ITEM_PORTAL) { if (IS_SET(obj->value[2], PORTAL_LOCKED)) { send_to_char( "It's already locked.\n\r", ch ); pop_call(); return; } if (obj->value[1] == -1) { send_to_char( "It can't be locked.\n\r", ch); pop_call(); return; } if (IS_SET(obj->value[2], PORTAL_KNOCKED)) { send_to_char( "Magical energies prevent it from being locked.\n\r", ch ); pop_call(); return; } if (!IS_SET(obj->value[2], PORTAL_CLOSED)) { act( "You need to close $p to lock it.", ch, obj, NULL, TO_CHAR ); pop_call(); return; } if (find_key(ch, obj->value[2]) == NULL) { if (!learned(ch, gsn_pick_lock)) { send_to_char( "You lack the key.\n\r", ch); pop_call(); return; } dc = lock_dc(NULL, obj); if (!pick_lock_check(ch, NULL, pick_lock_roll(ch), dc)) { send_to_char( "You failed to rig the lock.\n\r", ch ); pop_call(); return; } } SET_BIT(obj->value[2], PORTAL_LOCKED); act( "You lock $p.", ch, obj, NULL, TO_CHAR ); act( "$n locks $p.", ch, obj, NULL, TO_ROOM ); } else { send_to_char( "That's not a container or portal.\n\r", ch ); pop_call(); return; } } pop_call(); return; } void do_unlock( CHAR_DATA *ch, char *argument ) { char arg[MAX_INPUT_LENGTH]; OBJ_DATA *obj, *key; int door; push_call("do_unlock(%p,%p)",ch,argument); obj=NULL; key=NULL; one_argument( argument, arg ); if ( arg[0] == '\0' ) { send_to_char( "Unlock what?\n\r", ch ); pop_call(); return; } if ((door = find_door(ch, arg)) >= 0) { ROOM_INDEX_DATA *to_room; EXIT_DATA *pExit; EXIT_DATA *pExit_rev; pExit = ch->in_room->exit[door]; if (!IS_SET(pExit->exit_info, EX_CLOSED)) { send_to_char( "It's not closed.\n\r", ch); pop_call(); return; } if (!IS_SET(pExit->exit_info, EX_LOCKED) || IS_SET(pExit->exit_info, EX_KNOCKED)) { send_to_char( "It's already unlocked.\n\r", ch ); pop_call(); return; } if (pExit->key == -1) { send_to_char( "It can't be unlocked.\n\r", ch); pop_call(); return; } if (pExit->key != -2 && (key = find_key(ch, pExit->key)) == NULL) { if (learned(ch, gsn_pick_lock)) { do_pick(ch, arg); pop_call(); return; } send_to_char( "You lack the key.\n\r", ch); pop_call(); return; } REMOVE_BIT(pExit->exit_info, EX_LOCKED); if (!key) { act( "You unlatch the $d.", ch, NULL, pExit->keyword, TO_CHAR); act( "$n latches the $d.", ch, NULL, pExit->keyword, TO_ROOM); } else { act( "You unlock the $d with $p.", ch, key, pExit->keyword, TO_CHAR); act( "$n unlocks the $d with $p.", ch, key, pExit->keyword, TO_ROOM); } if ((to_room = room_index[pExit->to_room]) != NULL && (pExit_rev = to_room->exit[rev_dir[door]]) != NULL && room_index[pExit_rev->to_room] == ch->in_room ) { REMOVE_BIT(pExit_rev->exit_info, EX_LOCKED); } } else if ((obj = get_obj_here(ch, arg)) != NULL) { if (obj->item_type == ITEM_CONTAINER) { if (!IS_SET(obj->value[1], CONT_CLOSED)) { send_to_char( "It's not closed.\n\r", ch ); pop_call(); return; } if (obj->value[2] == -1) { send_to_char( "It can't be unlocked.\n\r", ch ); pop_call(); return; } if ((key = find_key(ch, obj->value[2])) == NULL) { if (learned(ch, gsn_pick_lock)) { do_pick(ch, arg); pop_call(); return; } send_to_char( "You lack the key.\n\r", ch ); pop_call(); return; } if (!IS_SET(obj->value[1], CONT_LOCKED) || IS_SET(obj->value[1], CONT_KNOCKED)) { send_to_char( "It's already unlocked.\n\r", ch ); pop_call(); return; } REMOVE_BIT(obj->value[1], CONT_LOCKED); act( "You unlock $p with $P.", ch, obj, key, TO_CHAR ); act( "$n unlocks $p with $P.", ch, obj, key, TO_ROOM ); } if (obj->item_type == ITEM_PORTAL) { if (!IS_SET(obj->value[2], PORTAL_CLOSED)) { send_to_char( "It's not closed.\n\r", ch ); pop_call(); return; } if (obj->value[2] == -1) { send_to_char( "It can't be unlocked.\n\r", ch ); pop_call(); return; } if ((key = find_key(ch, obj->value[1])) == NULL) { if (learned(ch, gsn_pick_lock)) { do_pick(ch, arg); pop_call(); return; } send_to_char( "You lack the key.\n\r", ch ); pop_call(); return; } if (!IS_SET(obj->value[2], PORTAL_LOCKED) || IS_SET(obj->value[2], PORTAL_KNOCKED)) { send_to_char( "It's already unlocked.\n\r", ch ); pop_call(); return; } REMOVE_BIT(obj->value[2], PORTAL_LOCKED); act( "You unlock $p with $P.", ch, obj, key, TO_CHAR ); act( "$n unlocks $p with $P.", ch, obj, key, TO_ROOM ); } else { send_to_char( "That's not a container or portal.\n\r", ch ); pop_call(); return; } } else { act( "You see no $T here.", ch, NULL, arg, TO_CHAR ); } pop_call(); return; } bool can_use_furniture( CHAR_DATA *ch, OBJ_DATA *obj, int position ) { int nocover; push_call("can_use_furniture(%p,%p,%p)",ch,obj,position); if (!obj || !ch) { pop_call(); return FALSE; } if (ch->hitched) { act("You cannot use $p while you are hitched to $P.", ch, obj, ch->hitched, TO_CHAR); pop_call(); return FALSE; } if (obj->item_type != ITEM_FURNITURE) { switch (position) { default: send_to_char("You can't do that on that.\n\r", ch); pop_call(); return FALSE; case POS_CROUCHING: break; case POS_SITTING: send_to_char("You can't sit on or at that.\n\r", ch); pop_call(); return FALSE; case POS_STANDING: send_to_char("You can't stand on that.\n\r", ch); pop_call(); return FALSE; case POS_RESTING: send_to_char("You can't rest on that.\n\r", ch); pop_call(); return FALSE; case POS_SLEEPING: send_to_char("You can't sleep on that.\n\r", ch); pop_call(); return FALSE; case POS_KNEELING: send_to_char("You can't kneel at that.\n\r", ch); pop_call(); return FALSE; } switch (obj->item_type) { default: send_to_char("That would not grant you any cover.\n\r", ch); pop_call(); return FALSE; case ITEM_FURNITURE: case ITEM_CONTAINER: case ITEM_FOUNTAIN: case ITEM_BOAT: case ITEM_TOTEM: break; } if (get_size(ch) > obj->size + 1) { send_to_char("That is too small to grant you any cover!\n\r", ch); pop_call(); return FALSE; } } switch (position) { default: send_to_char("You can't do that to that.\n\r", ch); pop_call(); return FALSE; case POS_CROUCHING: break; case POS_SITTING: if (!IS_SET(obj->value[2], FURN_SIT_AT) && !IS_SET(obj->value[2], FURN_SIT_ON) && !IS_SET(obj->value[2], FURN_SIT_IN)) { send_to_char("You can't sit on that.\n\r", ch); pop_call(); return FALSE; } break; case POS_STANDING: if (!IS_SET(obj->value[2], FURN_STAND_ON) && !IS_SET(obj->value[2], FURN_STAND_IN)) { send_to_char("You can't stand on that.\n\r", ch); pop_call(); return FALSE; } break; case POS_RESTING: if (!IS_SET(obj->value[2], FURN_REST_ON) && !IS_SET(obj->value[2], FURN_REST_IN)) { send_to_char("You can't rest on that.\n\r", ch); pop_call(); return FALSE; } break; case POS_SLEEPING: if (!IS_SET(obj->value[2], FURN_SLEEP_ON) && !IS_SET(obj->value[2], FURN_SLEEP_IN)) { send_to_char("You can't sleep on that.\n\r", ch); pop_call(); return FALSE; } break; case POS_KNEELING: if (!IS_SET(obj->value[2], FURN_KNEEL_AT)) { send_to_char("You can't kneel at that.\n\r", ch); pop_call(); return FALSE; } break; } if ((nocover = obj->size - get_size(ch)) <= 0) nocover = 1; else nocover *= 2; if (ch->furniture != obj) { if (position == POS_CROUCHING && count_users(obj) >= nocover) { act( "There's no more room to hide behind $p.", ch, obj, NULL, TO_CHAR); pop_call(); return FALSE; } else if (obj->value[0] && count_users(obj) >= obj->value[0]) { if (position == POS_KNEELING || (position == POS_SITTING && IS_SET(obj->value[2], FURN_SIT_AT))) act( "There's no more room at $p.", ch, obj, NULL, TO_CHAR); else act( "There's no more room on $p.", ch, obj, NULL, TO_CHAR); pop_call(); return FALSE; } } pop_call(); return TRUE; } void do_stand( CHAR_DATA *ch, char *argument ) { OBJ_DATA *obj = NULL; CHAR_DATA *rch; push_call("do_stand(%p,%p)",ch,argument); if (in_combat(ch) && ch->position > POS_CROUCHING) { send_to_char("You are already standing... in combat!\n\r", ch); pop_call(); return; } if (IS_AFFECTED(ch, AFF_SLEEP)) { send_to_char( "You can't wake up!\n\r", ch ); pop_call(); return; } if (argument[0] != '\0') { if ((obj = get_obj_list(ch, argument, ch->in_room->first_content)) == NULL) { send_to_char("You do not see that here.\n\r", ch); pop_call(); return; } } if (!IS_NPC(ch) && is_string(ch->pcdata->pose)) { STRFREE (ch->pcdata->pose); ch->pcdata->pose = STRALLOC(""); send_to_char( "Your pose has been removed.\n\r", ch ); } if (obj) { if (!can_use_furniture(ch, obj, POS_STANDING)) { pop_call(); return; } } if (ch->position <= POS_SITTING) { TAKE_ACTION(ch, ACTION_MOVE); } if (in_combat(ch) && ch->position <= POS_SITTING && !learned(ch, gsn_spring_attack)) { for (rch = ch->in_room->first_person ; rch ; rch = rch->next_in_room) { if (who_fighting(rch) == ch) attack_of_opportunity(rch, ch); } } switch (ch->position) { case POS_SLEEPING: update_pos(ch, POS_STANDING); if (obj == NULL) { act( "You wake and stand up.", ch, NULL, NULL, TO_CHAR); act( "$n wakes and stands up.", ch, NULL, NULL, TO_ROOM); } else if (IS_SET(obj->value[2], FURN_STAND_ON)) { act( "You wake and jump onto $p.", ch, obj, NULL, TO_CHAR); act( "$n wakes and jumps onto $p.", ch, obj, NULL, TO_ROOM); } else { act( "You wake and step into $p.", ch, obj, NULL, TO_CHAR); act( "$n wakes and steps into $p.", ch, obj, NULL, TO_ROOM); } break; case POS_STANDING: case POS_KNEELING: case POS_CROUCHING: case POS_SITTING: case POS_RESTING: if (ch->position == POS_STANDING && ((obj == NULL && ch->furniture == NULL) || obj == ch->furniture)) { send_to_char("You are already standing.\n\r", ch); break; } if (ch->position == POS_CROUCHING && ch->furniture && IS_AFFECTED(ch, AFF_HIDE)) { do_visible(ch, ""); update_pos(ch, POS_STANDING); break; } if (obj == NULL) { if (ch->position == POS_KNEELING) { act( "You rise up from your knee.", ch, NULL, NULL, TO_CHAR); act( "$n rises from $s knee.", ch, NULL, NULL, TO_ROOM); } else { act( "You stand up.", ch, NULL, NULL, TO_CHAR); act( "$n stands up.", ch, NULL, NULL, TO_ROOM); } } else if (IS_SET(obj->value[2], FURN_STAND_ON)) { act( "You jump onto $p.", ch, obj, NULL, TO_CHAR); act( "$n jumps onto $p.", ch, obj, NULL, TO_ROOM); } else { act( "You step into $p.", ch, obj, NULL, TO_CHAR); act( "$n steps into $p.", ch, obj, NULL, TO_ROOM); } if (in_combat(ch)) { update_pos(ch, POS_FIGHTING); } else { update_pos(ch, POS_STANDING); } break; } if (ch->furniture) { user_from_furniture(ch); } user_to_furniture(ch, obj); pop_call(); return; } void do_sit (CHAR_DATA *ch, char *argument) { OBJ_DATA *obj = NULL; push_call("do_sit(%p,%p)",ch,argument); if (in_combat(ch)) { send_to_char_color("{118}Your adrenaline is pumping too hard to rest!\n\r", ch); pop_call(); return; } if (ch->fear_level) { ch_printf_color(ch, "{018}Mind is racing too fast with fear to rest!\n\r"); pop_call(); return; } if (IS_AFFECTED(ch, AFF_SLEEP)) { send_to_char( "You can't wake up!\n\r", ch ); pop_call(); return; } if (is_mounting(ch)) { send_to_char("You are already sitting, on your mount.\n\r", ch); pop_call(); return; } if (argument[0] != '\0') { if ((obj = get_obj_list(ch, argument, ch->in_room->first_content)) == NULL) { send_to_char("You do not see that here.\n\r", ch); pop_call(); return; } if (!can_use_furniture(ch, obj, POS_SITTING)) { pop_call(); return; } } if (!IS_NPC(ch) && is_string(ch->pcdata->pose) && ch->position > POS_SITTING) { STRFREE (ch->pcdata->pose); ch->pcdata->pose = STRALLOC(""); send_to_char( "Your pose has been removed.\n\r", ch ); } switch (ch->position) { case POS_SLEEPING: update_pos(ch, POS_SITTING); if (obj == NULL) { act( "You wake and sit up.", ch, NULL, NULL, TO_CHAR); act( "$n wakes and sits up.", ch, NULL, NULL, TO_ROOM); } else if (IS_SET(obj->value[2], FURN_SIT_ON)) { act( "You wake and sit on $p.", ch, obj, NULL, TO_CHAR); act( "$n wakes and sits on $p.", ch, obj, NULL, TO_ROOM); } else if (IS_SET(obj->value[2], FURN_SIT_AT)) { act( "You wake and sit at $p.", ch, obj, NULL, TO_CHAR); act( "$n wakes and sits at $p.", ch, obj, NULL, TO_ROOM); } else { act( "You wake and sit in $p.", ch, obj, NULL, TO_CHAR); act( "$n wakes and sits in $p.", ch, obj, NULL, TO_ROOM); } break; case POS_RESTING: if (obj == NULL) { act( "You sit up.", ch, NULL, NULL, TO_CHAR); act( "$n sits up.", ch, NULL, NULL, TO_ROOM); } else if (IS_SET(obj->value[2], FURN_SIT_ON)) { act( "You sit up on $p.", ch, obj, NULL, TO_CHAR); act( "$n sits up on $p.", ch, obj, NULL, TO_ROOM); } else if (IS_SET(obj->value[2], FURN_SIT_AT)) { act( "You sit up at $p.", ch, obj, NULL, TO_CHAR); act( "$n sits up at $p.", ch, obj, NULL, TO_ROOM); } else { act( "You sit up in $p.", ch, obj, NULL, TO_CHAR); act( "$n sits up in $p.", ch, obj, NULL, TO_ROOM); } break; case POS_KNEELING: case POS_CROUCHING: case POS_SITTING: case POS_STANDING: if (ch->position == POS_SITTING && ((obj == NULL && ch->furniture == NULL) || obj == ch->furniture)) { send_to_char("You are already sitting down.\n\r", ch); break; } update_pos(ch, POS_SITTING); if (obj == NULL) { act( "You sit down on the ground.", ch, NULL, NULL, TO_CHAR); act( "$n sits down on the ground.", ch, NULL, NULL, TO_ROOM); } else if (IS_SET(obj->value[2], FURN_SIT_ON)) { act( "You sit on $p.", ch, obj, NULL, TO_CHAR); act( "$n sits on $p.", ch, obj, NULL, TO_ROOM); } else if (IS_SET(obj->value[2], FURN_SIT_AT)) { act( "You sit at $p.", ch, obj, NULL, TO_CHAR); act( "$n sits at $p.", ch, obj, NULL, TO_ROOM); } else { act( "You sit down in $p.", ch, obj, NULL, TO_CHAR); act( "$n sits down in $p.", ch, obj, NULL, TO_ROOM); } break; } if (ch->furniture) user_from_furniture(ch); user_to_furniture(ch, obj); pop_call(); return; } void do_kneel (CHAR_DATA *ch, char *argument) { OBJ_DATA *obj = NULL; CHAR_DATA *victim = NULL; push_call("do_kneel(%p,%p)",ch,argument); if (in_combat(ch)) { send_to_char_color("{118}Your adrenaline is pumping too hard to rest!\n\r", ch); pop_call(); return; } if (ch->fear_level) { ch_printf_color(ch, "{018}Mind is racing too fast with fear to rest!\n\r"); pop_call(); return; } if (IS_AFFECTED(ch, AFF_SLEEP)) { send_to_char( "You can't wake up!\n\r", ch ); pop_call(); return; } if (is_mounting(ch)) { send_to_char("You should dismount first.\n\r", ch); pop_call(); return; } if (argument[0] != '\0') { if ((obj = get_obj_list(ch, argument, ch->in_room->first_content)) == NULL) { if ((victim = get_char_room(ch, argument)) == NULL) { send_to_char("You do not see that here.\n\r", ch); pop_call(); return; } } if (obj && !can_use_furniture(ch, obj, POS_KNEELING)) { pop_call(); return; } } if (!IS_NPC(ch) && is_string(ch->pcdata->pose) && ch->position != POS_KNEELING) { STRFREE (ch->pcdata->pose); ch->pcdata->pose = STRALLOC(""); send_to_char( "Your pose has been removed.\n\r", ch ); } switch (ch->position) { case POS_KNEELING: case POS_CROUCHING: case POS_SITTING: case POS_STANDING: case POS_RESTING: if (ch->position == POS_KNEELING && ((obj == NULL && ch->furniture == NULL) || obj == ch->furniture)) { send_to_char("You are already kneeling.\n\r", ch); break; } update_pos(ch, POS_KNEELING); if (obj != NULL) { act( "You kneel at $p.", ch, obj, NULL, TO_CHAR); act( "$n kneel at $p.", ch, obj, NULL, TO_ROOM); } else if (victim != NULL) { act( "You kneel before $N.", ch, NULL, victim, TO_CHAR); act( "$n kneels before $N.", ch, NULL, victim, TO_ROOM); } else { act( "You kneel down.", ch, NULL, NULL, TO_CHAR); act( "$n kneels down.", ch, NULL, NULL, TO_ROOM); } break; } if (ch->furniture) user_from_furniture(ch); user_to_furniture(ch, obj); pop_call(); return; } void do_rest (CHAR_DATA *ch, char *argument) { OBJ_DATA *obj = NULL; push_call("do_rest(%p,%p)",ch,argument); if (in_combat(ch)) { send_to_char_color("{118}Your adrenaline is pumping too hard to rest!\n\r", ch); pop_call(); return; } if (ch->fear_level) { ch_printf_color(ch, "{018}Mind is racing too fast with fear to rest!\n\r"); pop_call(); return; } if (IS_AFFECTED(ch, AFF_SLEEP)) { send_to_char( "You can't wake up!\n\r", ch ); pop_call(); return; } if (is_mounting(ch)) { send_to_char("You should dismount first.\n\r", ch); pop_call(); return; } if (argument[0] != '\0') { if ((obj = get_obj_list(ch, argument, ch->in_room->first_content)) == NULL) { send_to_char("You do not see that here.\n\r", ch); pop_call(); return; } if (!can_use_furniture(ch, obj, POS_RESTING)) { pop_call(); return; } } if (!IS_NPC(ch) && is_string(ch->pcdata->pose) && ch->position > POS_SITTING) { STRFREE (ch->pcdata->pose); ch->pcdata->pose = STRALLOC(""); send_to_char( "Your pose has been removed.\n\r", ch ); } switch (ch->position) { case POS_SLEEPING: update_pos(ch, POS_RESTING); if (obj == NULL) { act( "You wake and rest easily.", ch, NULL, NULL, TO_CHAR); act( "$n wakes and rests easily.", ch, NULL, NULL, TO_ROOM); } else if (IS_SET(obj->value[2], FURN_REST_ON)) { act( "You wake and rest on $p.", ch, obj, NULL, TO_CHAR); act( "$n wakes and rests on $p.", ch, obj, NULL, TO_ROOM); } else { act( "You wake and rest in $p.", ch, obj, NULL, TO_CHAR); act( "$n wakes and rests in $p.", ch, obj, NULL, TO_ROOM); } if (in_camp(ch)) { send_to_char("You camp and begin recuperating.\n\r", ch); act( "$n joins the camp.\n\r",ch,NULL,NULL,TO_ROOM); SET_AFFECT(ch, AFF2_CAMPING); } break; case POS_KNEELING: case POS_CROUCHING: case POS_SITTING: case POS_STANDING: case POS_RESTING: if (ch->position == POS_RESTING && ((obj == NULL && ch->furniture == NULL) || obj == ch->furniture)) { send_to_char("You are already resting.\n\r", ch); break; } update_pos(ch, POS_RESTING); if (obj == NULL) { act( "You rest easily.", ch, NULL, NULL, TO_CHAR); act( "$n rests easily.", ch, NULL, NULL, TO_ROOM); } else if (IS_SET(obj->value[2], FURN_REST_ON)) { act( "You rest on $p.", ch, obj, NULL, TO_CHAR); act( "$n rests on $p.", ch, obj, NULL, TO_ROOM); } else { act( "You rest in $p.", ch, obj, NULL, TO_CHAR); act( "$n rests in $p.", ch, obj, NULL, TO_ROOM); } if (in_camp(ch)) { send_to_char("You camp and begin recuperating.\n\r", ch); act( "$n joins the camp.\n\r",ch,NULL,NULL,TO_ROOM); SET_AFFECT(ch, AFF2_CAMPING); } break; } if (ch->furniture) user_from_furniture(ch); user_to_furniture(ch, obj); pop_call(); return; } void do_crouch (CHAR_DATA *ch, char *argument) { OBJ_DATA *obj = NULL; push_call("do_crouch(%p,%p)",ch,argument); if (ch->position <= POS_SLEEPING) { send_to_char( "In your dreams, or what?\n\r", ch ); pop_call(); return; } if (IS_AFFECTED(ch, AFF_SLEEP)) { send_to_char( "You can't wake up!\n\r", ch ); pop_call(); return; } if (is_mounting(ch)) { send_to_char("You should dismount first.\n\r", ch); pop_call(); return; } if (argument[0] != '\0') { if ((obj = get_obj_list(ch, argument, ch->in_room->first_content)) == NULL) { send_to_char("You do not see that here.\n\r", ch); pop_call(); return; } if (!can_use_furniture(ch, obj, POS_CROUCHING)) { pop_call(); return; } } if (!IS_NPC(ch) && is_string(ch->pcdata->pose) && ch->position != POS_CROUCHING) { STRFREE (ch->pcdata->pose); ch->pcdata->pose = STRALLOC(""); send_to_char( "Your pose has been removed.\n\r", ch ); } switch (ch->position) { case POS_SLEEPING: send_to_char("In your dreams, or what?", ch); pop_call(); return; case POS_KNEELING: case POS_CROUCHING: case POS_SITTING: case POS_STANDING: case POS_RESTING: if (ch->position == POS_CROUCHING && ((obj == NULL && ch->furniture == NULL) || obj == ch->furniture)) { send_to_char("You are already crouching down.\n\r", ch); break; } update_pos(ch, POS_CROUCHING); if (obj == NULL) { act( "You crouch down.", ch, NULL, NULL, TO_CHAR); act( "$n crouches down.", ch, NULL, NULL, TO_CAN_SEE); } else { act( "You crouch behind $p for cover.", ch, obj, NULL, TO_CHAR); act( "$n crouches behind $p for cover.", ch, obj, NULL, TO_CAN_SEE); } break; } if (ch->furniture) user_from_furniture(ch); user_to_furniture(ch, obj); pop_call(); return; } void do_sleep( CHAR_DATA *ch, char *argument ) { OBJ_DATA *obj = NULL; push_call("do_sleep(%p,%p)",ch,argument); if (in_combat(ch)) { send_to_char("No way! You are in combat!\n\r", ch); pop_call(); return; } if (argument && ch->pcdata->last_combat + 60 > mud->current_time) { ch_printf_color(ch, "{018}Your adrenaline is pumping too hard to sleep now!\n\r"); pop_call(); return; } if (ch->fear_level) { ch_printf_color(ch, "{018}Mind is racing too fast with fear to sleep now!\n\r"); pop_call(); return; } if (is_mounting(ch)) { send_to_char("You should dismount first.\n\r", ch); pop_call(); return; } if (argument[0] != '\0') { if ((obj = get_obj_list(ch, argument, ch->in_room->first_content)) == NULL) { send_to_char("You do not see that here.\n\r", ch); pop_call(); return; } if (!can_use_furniture(ch, obj, POS_SLEEPING)) { pop_call(); return; } } if (!IS_NPC(ch) && is_string(ch->pcdata->pose)) { STRFREE (ch->pcdata->pose); ch->pcdata->pose = STRALLOC(""); send_to_char( "Your pose has been removed.\n\r", ch ); } switch (ch->position) { case POS_SLEEPING: if (obj == NULL || obj == ch->furniture) { send_to_char("You are already sleeping.\n\r", ch); break; } update_pos(ch, POS_RESTING); if (IS_SET(obj->value[2], FURN_SLEEP_ON)) { act( "You wake up and go to sleep on $p.", ch, obj, NULL, TO_CHAR); act( "$n wakes up and goes to sleep on $p.", ch, obj, NULL, TO_ROOM); } else { act( "You wake up and go to sleep in $p.", ch, obj, NULL, TO_CHAR); act( "$n wakes up and goes to sleep in $p.", ch, obj, NULL, TO_ROOM); } update_pos(ch, POS_SLEEPING); break; case POS_KNEELING: case POS_CROUCHING: case POS_SITTING: case POS_STANDING: case POS_RESTING: if (obj == NULL) { act( "You go to sleep.", ch, NULL, NULL, TO_CHAR); act( "$n goes to sleep.", ch, NULL, NULL, TO_ROOM); } else if (IS_SET(obj->value[2], FURN_SLEEP_ON)) { act( "You go to sleep on $p.", ch, obj, NULL, TO_CHAR); act( "$n goes to sleep on $p.", ch, obj, NULL, TO_ROOM); } else { act( "You go to sleep in $p.", ch, obj, NULL, TO_CHAR); act( "$n goes to sleep in $p.", ch, obj, NULL, TO_ROOM); } if (ch->position != POS_RESTING && in_camp(ch)) { send_to_char("You camp and begin recuperating.\n\r", ch); act( "$n joins the camp.\n\r", ch, NULL, NULL, TO_ROOM); SET_AFFECT(ch, AFF2_CAMPING); } update_pos(ch, POS_SLEEPING); break; } if (ch->furniture) user_from_furniture(ch); user_to_furniture(ch, obj); pop_call(); return; } /* * Revamped this a good bit because it made more * sense to awaken in a resting position, and to * not break camp or remove furniture simply * because you woke up - Kregor */ void do_wake( CHAR_DATA *ch, char *argument ) { char arg[MAX_INPUT_LENGTH]; CHAR_DATA *victim; push_call("do_wake(%p,%p)",ch,argument); one_argument( argument, arg ); if (arg[0] == '\0') victim = ch; else if (!IS_AWAKE(ch)) { send_to_char( "You are asleep yourself!\n\r", ch); pop_call(); return; } else if ((victim = get_char_room(ch, arg)) == NULL) { send_to_char( "They aren't here.\n\r", ch); pop_call(); return; } if (victim != ch) { if (IS_AFFECTED(victim, AFF2_FASCINATED)) { act("You shake $N to $S senses.", ch, NULL, victim, TO_CHAR); act("$n shakes you to your senses!", ch, NULL, victim, TO_VICT); act("$n shakes $N to $S senses!", ch, NULL, victim, TO_NOTVICT); AFFECT_STRIP(victim, AFF2_FASCINATED); } } if (IS_AWAKE(victim)) { if (victim == ch) { act( "You shake your head trying to stay awake.", ch, NULL, NULL, TO_CHAR ); act( "$n shakes $s head trying to stay awake.", ch, NULL, NULL, TO_ROOM ); } else act( "$N is already awake.", ch, NULL, victim, TO_CHAR ); pop_call(); return; } if (IS_AFFECTED(victim, AFF_SLEEP) || ch->position < POS_SLEEPING) { act( "You can't wake $N!", ch, NULL, victim, TO_CHAR ); pop_call(); return; } update_pos(victim, POS_RESTING); if (ch != victim) { act( "You wake $N.", ch, NULL, victim, TO_CHAR ); act( "$n wakes $N.", ch, NULL, victim, TO_NOTVICT ); act( "$n wakes you.", ch, NULL, victim, TO_VICT ); } else { act( "You wake up.", ch, NULL, NULL, TO_CHAR ); act( "$n wakes up.", ch, NULL, NULL, TO_ROOM ); } pop_call(); return; } void do_pray (CHAR_DATA *ch, char *argument) { OBJ_DATA *obj = NULL; push_call("do_pray(%p,%p)",ch,argument); if (in_combat(ch)) { send_to_char_color("{118}Your adrenaline is pumping too hard to pray!\n\r", ch); pop_call(); return; } if (IS_AFFECTED(ch, AFF_SLEEP)) { send_to_char( "You can't wake up!\n\r", ch ); pop_call(); return; } if (is_mounting(ch)) { send_to_char("You should dismount first.\n\r", ch); pop_call(); return; } if (argument[0] != '\0') { if ((obj = get_obj_list(ch, argument, ch->in_room->first_content)) == NULL) { send_to_char("You do not see that here.\n\r", ch); pop_call(); return; } if (obj && !can_use_furniture(ch, obj, POS_KNEELING)) { pop_call(); return; } } else { for (obj = ch->in_room->first_content ; obj ; obj = obj->next_content) { if (can_use_furniture(ch, obj, POS_KNEELING)) break; } if (!obj) { send_to_char("There is no altar here to pray at.\n\r", ch); pop_call(); return; } } if (!IS_NPC(ch) && is_string(ch->pcdata->pose) && ch->position != POS_KNEELING) { STRFREE (ch->pcdata->pose); ch->pcdata->pose = STRALLOC(""); send_to_char( "Your pose has been removed.\n\r", ch ); } switch (ch->position) { case POS_KNEELING: case POS_CROUCHING: case POS_SITTING: case POS_STANDING: case POS_RESTING: if (ch->position == POS_KNEELING && ((obj == NULL && ch->furniture == NULL) || obj == ch->furniture)) { send_to_char("You are already kneeling.\n\r", ch); break; } update_pos(ch, POS_KNEELING); if (obj != NULL) { act( "You kneel at $p.", ch, obj, NULL, TO_CHAR); act( "$n kneels at $p.", ch, obj, NULL, TO_ROOM); } else { act( "You kneel down.", ch, NULL, NULL, TO_CHAR); act( "$n kneels down.", ch, NULL, NULL, TO_ROOM); } break; } if (ch->furniture) user_from_furniture(ch); user_to_furniture(ch, obj); pop_call(); return; } void do_recall( CHAR_DATA *ch, char *argument ) { char arg[MAX_STRING_LENGTH]; push_call("do_recall(%p,%p)",ch,argument); if (IS_NPC(ch)) { pop_call(); return; } argument = one_argument(argument, arg); if (arg[0] == '\0') { send_to_char_color("{068}Current Recall Room:\n\r", ch); ch_printf_color(ch, " {178}%s\n\r", room_index[ch->pcdata->recall]->name); send_to_char_color("{078}Syntax: recall <set|reset>\n\r", ch); pop_call(); return; } if (!strcasecmp(arg, "set")) { if (ch->in_room->vnum == ch->pcdata->recall) { send_to_char("You are already in your recall room.\n\r", ch); pop_call(); return; } if (IS_SET(ch->in_room->room_flags, ROOM_NO_RECALL)) { send_to_char( "You cannot do that in this room.\n\r", ch); pop_call(); return; } if (IS_SET(ch->in_room->area->flags, AFLAG_NORECALL)) { send_to_char( "You cannot do that in this area.\n\r", ch); pop_call(); return; } ch->pcdata->recall = ch->in_room->vnum; send_to_char( "Your recall room has been set.\n\r", ch); pop_call(); return; } if (!strcasecmp(arg, "reset")) { ch->pcdata->recall = ch->pcdata->death_room; send_to_char( "Your recall room has been reset.\n\r", ch); pop_call(); return; } pop_call(); return; } void do_waypoint( CHAR_DATA *ch, char *argument ) { char arg[MAX_STRING_LENGTH]; char buf[MAX_STRING_LENGTH]; char colw[10], colW[10], colc[10], colC[10]; int cnt, value; push_call("do_recall(%p,%p)",ch,argument); if (IS_NPC(ch)) { pop_call(); return; } if (!learned(ch, gsn_teleport) && !learned(ch, gsn_greater_teleport) && !learned(ch, gsn_shadow_walk) && !learned(ch, gsn_pass_plant) && !learned(ch, gsn_dimension_door) && !learned(ch, gsn_teleportation_circle)) { send_to_char("You do not know how to teleport.", ch); pop_call(); return; } sprintf(colw, "{078}"); sprintf(colW, "{178}"); sprintf(colc, "{068}"); sprintf(colC, "{168}"); if (ch->in_room->sector_type == SECT_ETHEREAL) { send_to_char( "You don't know the path back to the real universe.\n\r", ch); pop_call(); return; } if (ch->in_room->sector_type == SECT_ASTRAL) { send_to_char( "You are too far out of your mind to recall anything.\n\r", ch); pop_call(); return; } if (argument[0] == '\0') { sprintf(buf, "%sCurrent Teleport Waypoints:\n\r", colc); for (cnt = 1 ; cnt <= UMIN(ch->level, MAX_WAYPOINT) ; cnt++) { if (ch->pcdata->waypoint[cnt] <= 0 || room_index[ch->pcdata->waypoint[cnt]] == NULL) { cat_sprintf(buf, " %s%2d%s] %sNone\n\r", colW, cnt, colc, colw); continue; } cat_sprintf(buf, " %s%2d%s] %s%s\n\r", colW, cnt, colc, colw, room_index[ch->pcdata->waypoint[cnt]]->name); } cat_sprintf(buf, "%sSyntax: waypoint <set|clear> <number>\n\r", colw); send_to_char_color(buf, ch); pop_call(); return; } argument = one_argument(argument, arg); if (!strcasecmp(arg, "set")) { if (IS_SET(ch->in_room->room_flags, ROOM_NO_ASTRAL) || IS_SET(ch->in_room->room_flags, ROOM_PRIVATE)) { send_to_char( "You are unable to do that in this room.\n\r", ch); pop_call(); return; } if (IS_SET(ch->in_room->area->flags, AFLAG_NOTELEPORT)) { send_to_char( "You cannot do that in this area.\n\r", ch); pop_call(); return; } if (!is_number(argument) || argument[0] == '\0') { send_to_char( "Set what waypoint number?\n\r", ch); pop_call(); return; } if ((value = atol(argument)) > UMIN(ch->level, MAX_WAYPOINT)) { send_to_char( "You cannot set that many waypoints. Clear one if you want another.\n\r", ch); pop_call(); return; } if (ch->pcdata->waypoint[value] > 0) { send_to_char( "That waypoint is already set. Clear it if you wish to reset it.\n\r", ch); pop_call(); return; } ch->pcdata->waypoint[value] = ch->in_room->vnum; act( "You study the room intently and keep it in your memory.", ch, NULL, NULL, TO_CHAR); act( "$n studies the room intently.", ch, NULL, NULL, TO_ROOM); pop_call(); return; } if (!strcasecmp(arg, "clear")) { if (!is_number(argument) || argument[0] == '\0') { send_to_char( "Clear what waypoint number?\n\r", ch); pop_call(); return; } if ((value = atol(argument)) > ch->level / 2) { send_to_char( "You cannot set that many waypoints. Clear one if you want another\n\r", ch); pop_call(); return; } if (ch->pcdata->waypoint[value] <= 0) { send_to_char( "That waypoint is already clear.\n\r", ch); pop_call(); return; } ch_printf_color(ch, "Your dismiss the image of %s from your memory.\n\r", room_index[ch->pcdata->waypoint[value]]->name); ch->pcdata->waypoint[value] = 0; pop_call(); return; } pop_call(); return; } /* * Commmand to enter a portal */ void do_enter( CHAR_DATA *ch, char *argument) { OBJ_DATA *portal; int destination, old_room; CHAR_DATA *fch, *fch_next; push_call("do_enter(%p,%p)",ch,argument); if (argument[0] == '\0') { send_to_char("Enter what?\n\r", ch); pop_call(); return; } old_room = ch->in_room->vnum; portal = get_obj_list(ch, argument, ch->in_room->first_content); if (portal == NULL) { send_to_char("You cannot find that to enter.\n\r", ch); pop_call(); return; } if (portal->item_type != ITEM_PORTAL) { send_to_char("You cannot seem to find a way in.\n\r", ch); pop_call(); return; } if (!class_allowed(portal, ch, FALSE) || is_affected(ch, gsn_dimensional_anchor) || IS_SET(ch->in_room->room_flags, ROOM_NO_ASTRAL)) { act("Mystic wards prevent you from entering $p.", ch, portal, NULL, TO_CHAR); pop_call(); return; } if (IS_SET(portal->value[2], PORTAL_CLOSED)) { act("$p is closed.", ch, portal, NULL, TO_CHAR); pop_call(); return; } if (IS_SET(portal->value[2], PORTAL_NO_ENTER)) { act("You cannot find a way to enter $p.", ch, portal, NULL, TO_CHAR); pop_call(); return; } if (IS_SET(portal->value[2], PORTAL_RANDOM)) { destination = get_random_room_index(ch, 1, MAX_VNUM-1)->vnum; } else if (IS_SET(portal->value[2], PORTAL_RANDOM_AREA)) { destination = get_random_room_index(ch, portal->pIndexData->area->low_r_vnum, portal->pIndexData->area->hi_r_vnum)->vnum; } else { destination = portal->value[3]; } if (get_room_index(destination) == NULL || destination == ch->in_room->vnum) { act( "$p doesn't seem to go anywhere.", ch, portal, NULL, TO_CHAR); pop_call(); return; } if (!move_loss(ch, NULL, 1)) { pop_call(); return; } if (IS_SET(portal->value[2], PORTAL_STEP_THROUGH)) { act( "You step through $p.", ch, portal, NULL, TO_CHAR); act( "$n steps through $p.", ch, portal, NULL, TO_SEEHEAR); } else if (IS_SET(portal->value[2], PORTAL_STEP_INTO)) { act( "You step into $p.", ch, portal, NULL, TO_CHAR); act( "$n steps into $p.", ch, portal, NULL, TO_SEEHEAR); } else { act( "You enter $p.", ch, portal, NULL, TO_CHAR); act( "$n enters $p.", ch, portal, NULL, TO_SEEHEAR); } char_to_room(ch, destination, TRUE); act( "$n emerges out of a rift in space.", ch, NULL, NULL, TO_SEEHEAR); do_look(ch, "auto"); for (fch = room_index[old_room]->first_person ; fch ; fch = fch_next) { fch_next = fch->next_in_room; if (fch->master == ch && IS_PET(fch, ch) && fch->position == POS_STANDING) { act( "You follow $N.", fch, NULL, ch, TO_CHAR); act( "$n follows $N.", fch, NULL, ch, TO_SEEHEAR); char_to_room(fch, destination, TRUE); act( "$n emerges out of a rift in space.", fch, NULL, NULL, TO_SEEHEAR); do_look(fch, "auto"); TAKE_ACTION(fch, ACTION_MOVE); } } mprog_greet_trigger(ch); oprog_greet_trigger(ch); rprog_greet_trigger(ch); TAKE_ACTION(ch, ACTION_MOVE); if (portal->value[0] > 0) { portal->value[0]--; if (portal->value[0] == 0) { act( "$p fades out of existence.", fch, portal, NULL, TO_CHAR); act( "$p fades out of existence.", fch, portal, NULL, TO_ROOM); junk_obj(portal); pop_call(); return; } } if (IS_SET(portal->value[2], PORTAL_GOWITH)) { send_to_room(format("%s fades from existence.\n\r", portal->short_descr), room_index[old_room]); obj_from_room(portal); obj_to_room(portal, ch->in_room->vnum); act( "$p fades into reality.", ch, portal, NULL, TO_ROOM); pop_call(); return; } pop_call(); return; } void do_follow (CHAR_DATA * ch, char *argument) { char arg[MAX_INPUT_LENGTH]; CHAR_DATA *victim; push_call("do_follow(%p,%p)",ch,argument); one_argument (argument, arg); if (arg[0] == '\0') { send_to_char ("Follow whom?\n\r", ch); pop_call(); return; } if (in_combat(ch)) { send_to_char("No way! You are still fighting!\n",ch); pop_call(); return; } if ((victim = get_char_room (ch, arg)) == NULL) { send_to_char ("They aren't here.\n\r", ch); pop_call(); return; } if (victim == ch) { if (ch->master == NULL) { send_to_char ("You already follow yourself.\n\r", ch); pop_call(); return; } stop_follower(ch); pop_call(); return; } if (!IS_NPC(ch)) { if (is_master(victim, ch) && IS_NPC (victim)) { send_to_char ("You may not follow a slave or pet.\n\r", ch); pop_call(); return; } } if (IS_AFFECTED(ch, AFF_DOMINATE)) { send_to_char ("You only feel like following your master.\n\r", ch); pop_call(); return; } /* poll the block list of the victim */ if (blocking(victim, ch)) { act ("$E eludes you at every step.", ch, 0, victim, TO_CHAR); pop_call(); return; } if (ch->master != NULL) { stop_follower (ch); } add_follower (ch, victim); pop_call(); return; } void add_follower (CHAR_DATA * ch, CHAR_DATA * master) { PET_DATA *pet; push_call("add_follower(%p,%p)",ch,master); if (ch->master != NULL) { bug ("Add_follower: non-null master.", 0); pop_call(); return; } ch->master = master; ch->leader = NULL; if (can_see(master, ch)) { act ("$n now follows you.", ch, NULL, master, TO_VICT); } act ("You now follow $N.", ch, NULL, master, TO_CHAR); ALLOCMEM(pet, PET_DATA, 1); pet->ch = ch; LINK(pet, mud->f_pet, mud->l_pet, next, prev); if (IS_ACT(ch, ACT_FAMILIAR) && !IS_NPC(master)) { master->pcdata->familiar = ch->race; } pop_call(); return; } void stop_follower (CHAR_DATA * ch) { PET_DATA *pet; push_call("stop_follower(%p)",ch); if (ch == NULL) { bug( "stop_follower : ch == NULL.",0); pop_call(); return; } if (ch->master == NULL) { bug( "Stop_follower: null master.", 0 ); pop_call(); return; } if (can_see(ch->master, ch)) { act ("$n stops following you.", ch, NULL, ch->master, TO_VICT); } act ("You stop following $N.", ch, NULL, ch->master, TO_CHAR); if (ch->master->mounting == ch) { ch->master->mounting = NULL; } if (IS_ACT(ch, ACT_FAMILIAR) && !IS_NPC(ch->master)) { ch->master->pcdata->familiar = RACE_NONE; } ch->master = NULL; ch->leader = NULL; for (pet = mud->f_pet ; pet ; pet = pet->next) { if (pet->ch == ch) { UNLINK(pet, mud->f_pet, mud->l_pet, next, prev); FREEMEM(pet); break; } } if (IS_ACT(ch, ACT_PET)) { if (ch->in_room) act( "$n has left the game.", ch, NULL, NULL, TO_ROOM); junk_mob(ch); } pop_call(); return; } void die_follower (CHAR_DATA * ch) { PET_DATA *pch, *pch_next; push_call("die_follower(%p)",ch); ch->position = POS_DEAD; if (ch->master != NULL) { stop_follower(ch); } ch->leader = NULL; for (pch = mud->f_pet ; pch ; pch = pch_next) { pch_next = pch->next; if (pch->ch->master == ch) { stop_follower(pch->ch); } } pop_call(); return; } /* * Is cart hitched to someone - Kregor */ CHAR_DATA *is_hitched( OBJ_DATA * obj ) { CHAR_DATA *fch; push_call("is_hitched(%p)",obj); if (obj->in_room == NULL) { log_printf("is_hitched: obj->in_room == NULL"); pop_call(); return FALSE; } for (fch = obj->in_room->first_person ; fch ; fch = fch->next_in_room) { if (fch->hitched == obj) { pop_call(); return fch; } } pop_call(); return NULL; } /* * remove cart from char. */ void user_from_cart( CHAR_DATA *ch ) { push_call("user_from_cart(%p)",ch); if (ch->hitched == NULL) { pop_call(); return; } ch->hitched = NULL; pop_call(); return; } /* * Hitch a cart to yourself, or a target pet - Kregor */ void do_hitch( CHAR_DATA *ch, char *argument ) { CHAR_DATA *victim; OBJ_DATA *obj; char arg[MAX_INPUT_LENGTH]; push_call("do_hitch()"); if (*argument == '\0') { send_to_char("Hitch what to whom?\n\r", ch); pop_call(); return; } argument = one_argument(argument, arg); if ((obj = get_obj_room(ch, arg)) == NULL) { send_to_char("There's no cart by that name here.\n\r", ch); pop_call(); return; } if (!IS_OBJ_TYPE(obj, ITEM_CART)) { act("$p is not a cart.", ch, obj, NULL, TO_CHAR); pop_call(); return; } if (*argument == '\0') { victim = ch; } else if ((victim = get_char_room(ch, argument)) == NULL) { send_to_char("There's no one by that name here.\n\r", ch); pop_call(); return; } else if (ch != victim && !is_master(victim, ch)) { act("$N is not yours to hitch $p onto.", ch, obj, victim, TO_CHAR); pop_call(); return; } if (is_hitched(obj)) { act("$p is already hitched to someone.", ch, obj, NULL, TO_CHAR); pop_call(); return; } if (victim->hitched) { if (victim == ch) act("You are already hitched to $p.", ch, victim->hitched, NULL, TO_CHAR); else act("$N is already hitched to $p.", ch, victim->hitched, victim, TO_CHAR); pop_call(); return; } victim->hitched = obj; act("$p is hitched to $N.", ch, obj, victim, TO_NOTVICT); act("$p is hitched to you.", ch, obj, victim, TO_VICT); if (ch == victim) act("$p is hitched to you.", ch, obj, victim, TO_CHAR); else act("$p is hitched to $N.", ch, obj, victim, TO_CHAR); pop_call(); return; } /* * Unhitch a cart - Kregor */ void do_unhitch( CHAR_DATA *ch, char *argument ) { CHAR_DATA *victim; OBJ_DATA *obj; char arg[MAX_INPUT_LENGTH]; push_call("do_unhitch()"); if (*argument == '\0') { send_to_char("Unhitch what?\n\r", ch); pop_call(); return; } argument = one_argument(argument, arg); if ((obj = get_obj_room(ch, arg)) == NULL) { send_to_char("There's no cart by that name here.\n\r", ch); pop_call(); return; } if (!IS_OBJ_TYPE(obj, ITEM_CART)) { act("$p is not a cart.", ch, obj, NULL, TO_CHAR); pop_call(); return; } if ((victim = is_hitched(obj)) == NULL) { act("$p is not hitched to anyone.", ch, obj, NULL, TO_CHAR); pop_call(); return; } if (ch != victim && !is_master(victim, ch)) { act("$N is not yours to unhitch.", ch, NULL, victim, TO_CHAR); pop_call(); return; } user_from_cart(victim); act("$p is unhitched from $N.", ch, obj, victim, TO_NOTVICT); act("$p is unhitched from you.", ch, obj, victim, TO_VICT); if (ch == victim) act("$p is hitched from you.", ch, obj, victim, TO_CHAR); else act("$p is hitched from $N.", ch, obj, victim, TO_CHAR); pop_call(); return; }