/*****************************************************************************
* DikuMUD (C) 1990, 1991 by: *
* Sebastian Hammer, Michael Seifert, Hans Henrik Staefeldt, Tom Madsen, *
* and Katja Nyboe. *
*---------------------------------------------------------------------------*
* MERC 2.1 (C) 1992, 1993 by: *
* Michael Chastain, Michael Quan, and Mitchell Tse. *
*---------------------------------------------------------------------------*
* SMAUG 1.4 (C) 1994, 1995, 1996, 1998 by: Derek Snider. *
* Team: Thoric, Altrag, Blodkai, Narn, Haus, Scryn, Rennard, Swordbearer, *
* gorog, Grishnakh, Nivek, Tricops, and Fireblade. *
*---------------------------------------------------------------------------*
* SMAUG 1.7 FUSS by: Samson and others of the SMAUG community. *
* Their contributions are greatly appreciated. *
*---------------------------------------------------------------------------*
* LoP (C) 2006 - 2012 by: the LoP team. *
*---------------------------------------------------------------------------*
* Wilderness Code *
*****************************************************************************/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "h/mud.h"
bool loc_in_wilderness; /* Used to know if they should enter the wilderness */
int loc_cords[2]; /* Used to get the cords for goto etc... */
extern int desccount;
extern int desccheck;
extern char showdescription[MSL];
bool should_follow_wilderness( CHAR_DATA *ch, CHAR_DATA *rch );
void put_in_wilderness( CHAR_DATA *ch, short x, short y )
{
if( !ch )
return;
if( is_npc( ch ) )
xSET_BIT( ch->act, ACT_WILDERNESS );
else
xSET_BIT( ch->act, PLR_WILDERNESS );
ch->cords[0] = x;
ch->cords[1] = y;
}
/* Allow them to move around the wilderness */
void move_around_wilderness( CHAR_DATA *ch, short dir, char *str )
{
CHAR_DATA *fch, *nextinroom, *master;
int x = 0, y = 0, chx = 0, chy = 0, moveloss = 0, sector = 0, oldchx, oldchy;
if( !ch || !str || str[0] == '\0' )
return;
desccount = 0;
desccheck = 0;
chx = ch->cords[0];
oldchx = ch->cords[0];
chy = ch->cords[1];
oldchy = ch->cords[1];
if( dir == 0 ) /* North */
chy--; /* Line before */
else if( dir == 1 ) /* South */
chy++; /* Line below */
else if( dir == 2 ) /* East */
chx++; /* Next character */
else if( dir == 3 ) /* West */
chx--; /* Previous character */
else if( dir == 4 ) /* NE */
{
chy--; /* Line before */
chx++; /* Next character */
}
else if( dir == 5 ) /* NW */
{
chy--; /* Line before */
chx--; /* Previous character */
}
else if( dir == 6 ) /* SE */
{
chy++; /* Line below */
chx++; /* Next character */
}
else if( dir == 7 ) /* SW */
{
chy++; /* Line below */
chx--; /* Previous character */
}
if( chy < 0 || chx < 0 )
{
send_to_char( "You can't go that way.\r\n", ch );
return;
}
/* Parse the description and add in color etc... for where they are */
for( ; *str != '\0'; )
{
if( *str != '\r' && *str != '\n' && x == chx && y == chy ) /* Ok so it is there and valid */
{
/* These you can't go to */
if( *str == ' ' )
{
send_to_char( "You can't go that way.\r\n", ch );
return;
}
/* Since we have the character now lets set up the movement loss */
/* Only loose movement if not on a mount */
if( *str == '^' ) /* Mountain */
sector = SECT_MOUNTAIN;
else if( *str == '*' ) /* Field */
sector = SECT_FIELD;
else if( *str == '~' )
sector = SECT_WATER_SWIM;
else /* Default of the Inside */
sector = SECT_INSIDE;
moveloss = 1;
if( ( ch->mount && ( !should_follow_wilderness( ch, ch->mount ) || !is_floating( ch->mount ) ) ) || !is_floating( ch ) )
moveloss = movement_loss[ URANGE( 0, sector, SECT_MAX - 1 ) ];;
if( ch->mount && should_follow_wilderness( ch, ch->mount ) )
{
if( ch->mount->move < moveloss )
{
send_to_char( "Your mount is to exhausted.\r\n", ch );
return;
}
move_around_wilderness( ch->mount, dir, ch->in_room->description );
}
else /* Only take movement if no mount since mount will loose when it is done */
{
if( ch->move < moveloss )
{
send_to_char( "Your to exhausted.\r\n", ch );
return;
}
ch->move -= moveloss;
}
ch->cords[0] = chx;
ch->cords[1] = chy;
do_look( ch, (char *)"auto" );
ch->cords[0] = oldchx;
ch->cords[1] = oldchy;
for( fch = ch->in_room->first_person; fch; fch = nextinroom )
{
nextinroom = fch->next_in_room;
if( fch == ch || !fch->master )
continue;
master = fch->master;
while( master->master )
master = master->master;
if( master != ch || xIS_SET( ch->act, PLR_SOLO ) || xIS_SET( fch->act, PLR_SOLO ) )
continue;
if( fch->position != POS_STANDING && fch->position != POS_MOUNTED )
continue;
if( !should_follow_wilderness( ch, fch ) )
continue;
act( AT_ACTION, "You follow $N.", fch, NULL, master, TO_CHAR );
move_around_wilderness( fch, dir, fch->in_room->description );
}
ch->cords[0] = chx;
ch->cords[1] = chy;
return;
}
/* Should do this after the other checks */
if( *str != '\r' && *str != '\n' )
x++;
if( *str == '\n' )
{
x = 0;
y++;
}
str++;
}
send_to_char( "You can't go that way.\r\n", ch );
}
void parse_wilderness_description( CHAR_DATA *ch, char *str )
{
int x = 0, y = 0;
if( !ch || !str || str[0] == '\0' )
return;
desccount = 0;
desccheck = 0;
/* Parse the description and add in color etc... for where they are */
for( ; *str != '\0'; )
{
if( x == ch->cords[0] && y == ch->cords[1] && is_in_wilderness( ch ) )
{
showdescription[desccount++] = '&';
showdescription[desccount++] = 'r';
if( *str == '&' || *str == '^' || *str == '}' )
showdescription[desccount++] = *str;
showdescription[desccount++] = *str;
showdescription[desccount++] = '&';
showdescription[desccount++] = 'D';
}
else
{
if( *str == '&' || *str == '^' || *str == '}' )
showdescription[desccount++] = *str;
showdescription[desccount++] = *str;
}
if( *str != '\n' && *str != '\r' )
x++;
if( *str == '\n' )
{
x = 0;
y++;
}
str++;
}
showdescription[desccount] = '\0';
send_to_char( showdescription, ch );
}
bool is_same_cords( OBJ_DATA *obj, CHAR_DATA *ch )
{
if( !obj || !ch )
return false;
if( !xIS_SET( obj->extra_flags, ITEM_WILDERNESS ) && !is_in_wilderness( ch ) )
return true;
if( xIS_SET( obj->extra_flags, ITEM_WILDERNESS ) && is_in_wilderness( ch )
&& obj->cords[0] == ch->cords[0] && obj->cords[1] == ch->cords[1] )
return true;
return false;
}
bool should_follow_wilderness( CHAR_DATA *ch, CHAR_DATA *rch )
{
if( !ch || !rch )
return false;
if( is_in_wilderness( ch ) )
{
if( is_in_wilderness( rch ) && ch->cords[0] == rch->cords[0] && ch->cords[1] == rch->cords[1] )
return true;
}
if( !is_in_wilderness( ch ) )
{
if( !is_in_wilderness( rch ) )
return true;
}
return false;
}
CMDF( do_wilderness )
{
CHAR_DATA *fch, *nextinroom, *master;
if( !ch || !ch->in_room )
return;
if( !xIS_SET( ch->in_room->room_flags, ROOM_WILDERNESS ) )
{
/* Just incase for some reason not in the room any more */
if( is_npc( ch ) )
xREMOVE_BIT( ch->act, ACT_WILDERNESS );
else
xREMOVE_BIT( ch->act, PLR_WILDERNESS );
ch->cords[0] = 0;
ch->cords[1] = 0;
send_to_char( "You aren't currently in a wilderness room.\r\n", ch );
return;
}
if( ch->mount && should_follow_wilderness( ch, ch->mount ) )
do_wilderness( ch->mount, (char *)"" );
for( fch = ch->in_room->first_person; fch; fch = nextinroom )
{
nextinroom = fch->next_in_room;
if( fch == ch || !fch->master )
continue;
master = fch->master;
while( master->master )
master = master->master;
if( master != ch || xIS_SET( ch->act, PLR_SOLO ) || xIS_SET( fch->act, PLR_SOLO ) )
continue;
if( fch->position != POS_STANDING && fch->position != POS_MOUNTED )
continue;
if( !should_follow_wilderness( ch, fch ) )
continue;
do_wilderness( fch, (char *)"" );
}
ch->cords[0] = 0;
ch->cords[1] = 0;
if( is_npc( ch ) )
{
xTOGGLE_BIT( ch->act, ACT_WILDERNESS );
if( xIS_SET( ch->act, ACT_WILDERNESS ) )
send_to_char( "You enter the wilderness.\r\n", ch );
else
send_to_char( "You emerge from the wilderness.\r\n", ch );
}
else
{
xTOGGLE_BIT( ch->act, PLR_WILDERNESS );
if( xIS_SET( ch->act, PLR_WILDERNESS ) )
send_to_char( "You enter the wilderness.\r\n", ch );
else
send_to_char( "You emerge from the wilderness.\r\n", ch );
}
}
void obj_to_char_cords( OBJ_DATA *obj, CHAR_DATA *ch )
{
if( !obj || !ch || !ch->in_room )
return;
if( !xIS_SET( ch->in_room->room_flags, ROOM_WILDERNESS ) )
return;
if( !is_in_wilderness( ch ) )
return;
/* Should be good to set it now */
xSET_BIT( obj->extra_flags, ITEM_WILDERNESS );
obj->cords[0] = ch->cords[0];
obj->cords[1] = ch->cords[1];
}
bool can_see_character( CHAR_DATA *ch, CHAR_DATA *rch )
{
if( !ch || !rch || !ch->in_room || !rch->in_room )
return false;
if( !xIS_SET( ch->in_room->room_flags, ROOM_WILDERNESS ) )
return true;
/* If not set to wilderness */
if( !is_in_wilderness( ch ) )
{
/* This one is so just skip them */
if( is_in_wilderness( rch ) )
return false;
}
/* Is set to wilderness */
if( is_in_wilderness( ch ) )
{
/* This one isn't so just skip them */
if( !is_in_wilderness( rch ) )
return false;
/* If not in the same spot continue */
if( ch->cords[0] != rch->cords[0] || ch->cords[1] != rch->cords[1] )
return false;
}
return true;
}
bool is_in_wilderness( CHAR_DATA *ch )
{
if( !ch )
{
bug( "%s: NULL ch", __FUNCTION__ );
return false;
}
if( !ch->in_room || !xIS_SET( ch->in_room->room_flags, ROOM_WILDERNESS ) )
return false;
if( is_npc( ch ) && xIS_SET( ch->act, ACT_WILDERNESS ) )
return true;
if( !is_npc( ch ) && xIS_SET( ch->act, PLR_WILDERNESS ) )
return true;
return false;
}
/* Lets set them to the cords if we need to */
void set_loc_cords( CHAR_DATA *ch )
{
if( !loc_in_wilderness || !ch )
return;
if( is_npc( ch ) )
xSET_BIT( ch->act, ACT_WILDERNESS );
else
xSET_BIT( ch->act, PLR_WILDERNESS );
ch->cords[0] = loc_cords[0];
ch->cords[1] = loc_cords[1];
}
void char_to_char_cords( CHAR_DATA *ch, CHAR_DATA *victim )
{
if( !ch || !victim )
return;
if( !is_in_wilderness( ch ) )
return;
if( is_npc( ch ) )
xSET_BIT( victim->act, ACT_WILDERNESS );
else
xSET_BIT( victim->act, PLR_WILDERNESS );
victim->cords[0] = ch->cords[0];
victim->cords[1] = ch->cords[1];
}