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