dawn/notes/
dawn/src/
dawn/src/docs/
/**************************************************************************/
// pushdrag.cpp - push and drag functionality - by Meerclar
/***************************************************************************
 * The Dawn of Time v1.69r (c)1997-2004 Michael Garratt                    *
 * >> A number of people have contributed to the Dawn codebase, with the   *
 *    majority of code written by Michael Garratt - www.dawnoftime.org     *
 * >> To use this source code, you must fully comply with the dawn license *
 *    in licenses.txt... In particular, you may not remove this copyright  *
 *    notice.                                                              *
 ***************************************************************************/
#include "include.h"

// This code needs a little more work, the following should be implemented:
// * racial size checks for mobs/players
// * to awake players/mobs if dragged - even an attempt
// * if a player doesn't have passdoor they should never go thru a door
// * if ch has passdoor and dragging, they should go thru door even if the
//   person they arent dragging doesn't.
// * if pushing someone with pass door, there should be a chance you pass
//   thru them... other times if you dont have passdoor they should pushable
//   thru a closed exit but you dont follow.
// * trigger mobprog exit triggers
// * trigger mobprog entry triggers
// * player pushing echoes shohuld be like object echoes.
/**************************************************************************/
void push_drag( char_data *ch, char *argument, char *verb )
{
	char arg1[MSL];
	char arg2[MSL];
	ROOM_INDEX_DATA *in_room;
	ROOM_INDEX_DATA *to_room;
	char_data *victim;
	EXIT_DATA *pexit;
	OBJ_DATA *obj=NULL;
	int door;
	bool moving_object=false;
	
	argument = one_argument( argument, arg1 );
	argument = one_argument( argument, arg2 );
	
	if(IS_NULLSTR(arg1) || IS_NULLSTR(arg2)){
		ch->printlnf("syntax: %s <name> <direction>", lowercase(verb));
		ch->printlnf("This command can be used to %s players/mobs/objects into other rooms.", 
			capitalize(verb));
		return;
	}

	victim = get_char_room(ch,arg1);
	if(!victim){
		obj = get_obj_list( ch, arg1, ch->in_room->contents );
		if(!obj){
			ch->printlnf("There is no '%s' in the room which you can see to %s.",
				arg1, lowercase(verb));
			push_drag(ch, "", verb);
			return;
		}
		moving_object=true;
	}

	// check they have the movement points required
	if(ch->move<10){
		ch->printlnf("You are too tired to %s any%s around!", verb,
			moving_object?"thing":"body");
		return;
	}

	// lookup the direction
	door=dir_lookup(arg2);
	if(door<0){		
		ch->printlnf("'%s' is not a recognised direction.", arg2);
		push_drag(ch, "", verb);
		return;
	}
	
	// check the direction is appropriate	
	in_room=ch->in_room;
	pexit=in_room->exit[door];
	if(!pexit || !pexit->u1.to_room || !can_see_room(ch,pexit->u1.to_room)){
		ch->printlnf("There is no exit to the %s.", dir_name[door]);
		return;
	}
	to_room = pexit->u1.to_room;

	
	if(moving_object){
		if(IS_SET(pexit->exit_info, EX_CLOSED|EX_NOPASS)){
			act( "You cannot $t it through the $d.", ch, verb, pexit->keyword, TO_CHAR );
			act( "$n decides to $t $P around!",  ch, verb, obj, TO_ROOM );
			return;
		}
				
		act( "You attempt to $T $p out of the room.",ch,  obj, verb, TO_CHAR );
		act( "$n is attempting to $T $p out of the room.",ch,   obj, verb, TO_ROOM );
		
		if ( obj->weight >  (2 * can_carry_w(ch)) ){
	           act( "$p is too heavy to $T.",ch,  obj, verb, TO_CHAR);
			   act( "$n attempts to $T $p, but it is too heavy.",ch,  obj, verb, TO_ROOM);
			   return;
		}

		// do some failure checks which relate to morts only
		if(!IS_IMMORTAL(ch)){
			if( IS_SET(in_room->room_flags, ROOM_SAFE|ROOM_PRIVATE|ROOM_SOLITARY)
				|| IS_SET(to_room->room_flags, ROOM_SAFE|ROOM_PRIVATE|ROOM_SOLITARY))
			{
				act( "$p is not moving.",ch,  obj, verb, TO_CHAR );
				act( "$n doesn't appear to have any success.",ch,   obj, verb, TO_ROOM );
				return;
			}			
		}

		// success pushing an object
		ch->move -= 10;
		ch->println( "You succeed!" );
		act( "$n succeeds!", ch, NULL, NULL, TO_ROOM );
		if (!str_cmp( verb, "drag" )){
			act( "$n drags $p $T!", ch, obj, dir_name[door], TO_ROOM );
			char_from_room( ch );
			char_to_room( ch, pexit->u1.to_room );
			obj_from_room( obj );
			obj_to_room( obj, to_room );
			act( "$n drags $p into the room.", ch, obj, dir_name[door], TO_ROOM );
		}else{			
			act( "$p is pushed %T of the room by $n!", ch, obj, dir_name[door], TO_ROOM );
			char_from_room( ch );
			char_to_room( ch, to_room);
			obj_from_room( obj );
			obj_to_room( obj, to_room);
			act( "$p is pushed into the room by $n!", ch, obj, dir_name[door], TO_ROOM );
		}
		return; // end of pushing/draging an object
	}
	
	// pushing a mob/player, first lets do some idiot checks :)
	if ( ch == victim )	{		
		act( "You $t yourself about the room and look very silly.", ch, verb, NULL, TO_CHAR );
		act( "$n decides to be silly and $t $mself about the room.", ch, verb, NULL, TO_ROOM );
		return;
	}

	act( "You attempt to $t $N out of the room.", ch, verb, victim, TO_CHAR );
	act( "$n is attempting to $t you out of the room!", ch, verb, victim, TO_VICT );
	act( "$n is attempting to $t $N out of the room.", ch, verb, victim, TO_NOTVICT );

	if(!IS_IMMORTAL(ch)){
		// cant push around mobs which provide services
		if(IS_NPC(victim)
			&& (IS_SET(victim->act,ACT_TRAIN | ACT_PRACTICE | ACT_IS_HEALER)
			|| IS_SET(victim->imm_flags,IMM_SUMMON)
			|| IS_KEEPER(victim)))
		{
			act( "$N is not moving.",ch, victim, NULL, TO_CHAR );
			act( "$n doesn't appear to have any success.",ch, NULL, NULL, TO_ROOM );
			return;
		}

		if( IS_SET(in_room->room_flags, ROOM_SAFE|ROOM_PRIVATE|ROOM_SOLITARY)
			|| IS_SET(to_room->room_flags, ROOM_SAFE|ROOM_PRIVATE|ROOM_SOLITARY))
		{
			act( "$N is not moving.",ch, victim, NULL, TO_CHAR );
			act( "$n doesn't appear to have any success.",ch, NULL, NULL, TO_ROOM );
			return;
		}			

		if((!str_cmp( verb, "push" ) && victim->position != POS_STANDING)
		||  is_safe(ch,victim)
		||  (number_percent() <90)
		||   (victim->max_hit > (ch->max_hit + (ch->perm_stats[STAT_ST])*20)) )
		{
			act( "$N is not moving.",ch, victim, NULL, TO_CHAR );
			act( "$n doesn't appear to have any success.",ch, NULL, NULL, TO_ROOM );
			return;
		}
	}
	

	ch->move -= 10;
	ch->println( "You succeed!" );
	act( "$n succeeds!", ch, NULL, NULL, TO_ROOM );
	if (!str_cmp( verb, "drag" )){		
		move_char( ch, door, true);
		act( "$n is dragged $T!", victim, NULL, dir_name[door], TO_ROOM );
		act( "You are dragged $T!", victim, NULL, dir_name[door], TO_CHAR );
		char_from_room( victim );
		char_to_room( victim, to_room);
		act( "$N drags $n into the room.", victim, NULL, ch, TO_NOTVICT );
	}else if (!str_cmp( verb, "push" )){		
		act( "$n `Wflies`x $T!", victim, NULL, dir_name[door], TO_ROOM );
		act( "You `Wfly`x $T!", victim, NULL, dir_name[door], TO_CHAR );
		char_from_room( victim );
		char_to_room( victim, pexit->u1.to_room );
		act( "$n `Wflies`x into the room!", victim, NULL, NULL, TO_ROOM );
	}
}
/**************************************************************************/               
void do_push( char_data *ch, char *argument )
{
	push_drag( ch, argument, "push" );
}

/**************************************************************************/
void do_drag( char_data *ch, char *argument )
{
	push_drag( ch, argument, "drag" );
}

/**************************************************************************/
/**************************************************************************/