/*
....[@@@..[@@@..............[@.................. MUD++ is a written from
....[@..[@..[@..[@..[@..[@@@@@....[@......[@.... scratch multi-user swords and
....[@..[@..[@..[@..[@..[@..[@..[@@@@@..[@@@@@.. sorcery game written in C++.
....[@......[@..[@..[@..[@..[@....[@......[@.... This server is an ongoing
....[@......[@..[@@@@@..[@@@@@.................. development project. All
................................................ contributions are welcome.
....Copyright(C).1995.Melvin.Smith.............. Enjoy.
------------------------------------------------------------------------------
Melvin Smith (aka Fusion) msmith@falcon.mercer.peachnet.edu
MUD++ development mailing list mudpp-list@spice.com
------------------------------------------------------------------------------
area.cc
*/
#include "io.h"
#include "string.h"
#include "llist.h"
#include "indexable.h"
#include "room.h"
#include "area.h"
#include "pc.h"
#include "shop.h"
extern LList<PC> pcs;
extern LList<NPC> npcs;
extern LList<Area> areas;
extern IndexList<Object> objIndex;
extern IndexList<NPC> npcIndex;
extern IndexList<Room> roomIndex;
void Area::setFile( const String & x )
{
file = x;
}
const String & Area::getFile()
{
return file;
}
int Area::reload()
{
// This leaves invalid pointers in other areas so it is imperative
// that a global relink be done immediately following an area reload
roomIndex.clr();
npcIndex.clr();
objIndex.clr();
rmDirtyBit();
return readFrom();
}
// will change to readProtoFrom
/*
int Area::readFrom( const char * str )
{
InFile in( str );
if( !in )
return -1;
return readFrom( in );
}
*/
// will change to readProtoFrom
int Area::readFrom( InFile &in )
{
char buf[BUF];
Index index;
// Read area header
for( ; ; )
{
in.getword( buf );
switch( *buf )
{
default : continue;
case '{': // nest++; unused for now
continue;
case '}': // nest--;
break;
case 'B': if( !str_cmp( buf, "Builder" ) )
builder = in.getstring( buf );
continue;
case 'N': if( !str_cmp( buf, "Name" ) )
setName( in.getstring( buf ) );
continue;
case 'R': if( !str_cmp( buf, "RepopMes" ) )
setRepopMessg( in.getstring( buf ) );
else if( !str_cmp( buf, "RepopTime" ) )
repop_time = in.getnum();
continue;
case 'S':
if( !str_cmp( buf, "Security" ) )
{
security = in.getnum();
continue;
}
continue;
case 'V': //if( !str_cmp( buf, "Version" ) )
//version = in.getnum();
continue;
}
break;
}
while(in)
{
in.getword( buf );
if( !in )
break;
if( *buf == 'R' ) // Room
{
index = in.getword( buf );
Room *newRoom = new Room( this, index.getKey() ); // This = Area *
// will change to readProtoFrom
newRoom->readFrom( in );
roomIndex.addIndex( index, newRoom );
}
else if( *buf == 'N' ) // NPC
{
NPC *newNPC = new NPC;
index = in.getword( buf );
// will change to readProtoFrom
newNPC->readFrom( in );
npcIndex.addIndex( index, newNPC );
}
else if( *buf == 'S' ) // ShopKeeper
{
NPC *newSK = new ShopKeeper;
index =in.getword( buf );
// will change to readProtoFrom
newSK->readFrom( in );
npcIndex.addIndex( index, newSK );
}
else if( *buf == 'O' ) // Object
{
Object *newObj = new Object;
index = in.getword( buf );
newObj->readProtoFrom( in );
objIndex.addIndex( index, newObj );
}
else if( *buf == '#' )
return 0;
else
return -1;
}
return 0;
}
// will change to writeProtoTo
/*
int Area::writeTo( const char * str )
{
OutFile out( str );
if( !out )
return -1;
return writeTo( out );
}
*/
// will change to writeProtoTo
int Area::writeTo( OutFile & out ) const
{
out << "{\n"
<< "Name " << name << "~\n"
<< "Security " << security << "\n"
<< "RepopMes " << repop_messg << "~\n"
<< "RepopTime " << repop_time << "\n"
<< "Builder " << builder << "~\n"
<< "}\n\n";
NPC *npc;
out << "NPCS\n";
npcIndex.reset();
while( ( npc = npcIndex.peek() ) )
{
npcIndex.next();
// Will change to writeProtoTo
if( !npc->isShopKeeper() )
npc->writeTo( out );
}
out << "#\n\n";
out << "SHOPKEEPERS\n";
npcIndex.reset();
while( ( npc = npcIndex.peek() ) )
{
npcIndex.next();
if( !npc->isShopKeeper() )
continue;
// Will change to writeProtoTo
npc->writeTo( out );
}
out << "#\n\n";
out << "ITEMS\n";
objIndex.reset();
Object *obj;
while( ( obj = (Object *)objIndex.peek() ) )
{
objIndex.next();
obj->writeProtoTo( out );
}
out << "#\n\n";
out << "ROOMS\n";
roomIndex.reset();
Room *room;
while( ( room = (Room *)roomIndex.peek() ) )
{
roomIndex.next();
// Will change to writeProtoTo
room->writeTo( out );
}
out << "#\n";
return 1;
}
int Area::addRoom( Room * room )
{
// Add checks later
Index x;
x.setKey( room->getKey() );
roomIndex.addIndex( x, room );
return 0;
}
const String & Area::getRepopMessg()
{
return repop_messg;
}
void Area::setRepopMessg( const String & x )
{
repop_messg = x;
}
void Area::setRepopTime( int t )
{
if( t > 0 )
repop_time = t;
}
int Area::getRepopTime()
{
return repop_time;
}
void Area::repop()
{
Room * room;
roomIndex.reset();
while( ( room = roomIndex.peek() ) )
{
roomIndex.next();
room->repop();
}
outAllChar( repop_messg );
timer = 0;
}
int Area::getSecurity() const
{
return security;
}
const String & Area::getBuilder()
{
return builder;
}
void Area::Builder( const String & strBuilder )
{
if( builder == strBuilder )
;
//else builder = strBuilder;
}
Room *Area::getRoom( const Index & )
{
return 0;
}
Object *Area::lookupObj( const Index & x )
{
return objIndex.lookup( x );
}
Object *Area::createObj( const Index & x )
{
Object *obj;
obj = objIndex.lookup( x );
if( !obj )
return 0;
// call the Object copy constructor to correctly clone the Object
return new Object( *obj );
}
NPC *Area::lookupNPC( const Index & x )
{
return npcIndex.lookup( x );
}
NPC *Area::createNPC( const Index & x )
{
NPC *npc = npcIndex.lookup( x );
if( npc )
// call the NPC copy constructor to correctly clone the Object
return new NPC( *npc );
return 0;
}
// Inline these later
Room *Area::lookupRoom( const String & x )
{
return roomIndex.lookup( x );
}
Room *Area::lookupRoom( const char * x )
{
return roomIndex.lookup( x );
}
Room *Area::lookupRoom( const Index & x )
{
return roomIndex.lookup( x.getKey() );
}
void Area::hardLink()
{
Room *room;
roomIndex.reset();
while( ( room = roomIndex.peek() ) )
{
roomIndex.next();
room->hardLink();
}
}
void Area::outAllChar( const char * str )
{
PC *pc;
LList<PC> tList = pcs;
tList.reset();
while( ( pc = tList.peek() ) )
{
tList.next();
// Add check for awake after position implemented
if( !pc->isPlaying() )
continue;
else if( pc->inRoom()->getArea() != this )
continue;
else
{
pc->out( str );
}
}
}
void Area::outAllCharExcept( const char * str, PC * skip )
{
PC *pc;
LList<PC> tList = pcs;
tList.reset();
while( ( pc = tList.peek() ) )
{
tList.next();
// Add check for awake after position implemented
if( !pc->isPlaying() )
continue;
else if( pc->inRoom()->getArea() != this )
continue;
else if( pc == skip )
continue;
else
{
pc->out( str );
}
}
}
Area * lookupArea( const String & x )
{
Area *area;
LList<Area> tlist = areas;
tlist.reset();
while( ( area = tlist.peek() ) )
{
tlist.next();
if( area->getKey() == x )
return area;
}
return 0;
}
Area * lookupArea( const char * x )
{
return lookupArea( String( x ) );
}