Show QuestImporter.cpp syntax highlighted
/**
**************************************************************************************
*Palisma - Secrets of the Illuminati is an open-source 2D RPG *
*Copyright (C) 2006, Tony Sparks *
* *
*This library is free software; you can redistribute it and/or *
*modify it under the terms of the GNU Lesser General Public *
*License as published by the Free Software Foundation; either *
*version 2.1 of the License, or (at your option) any later version. *
* *
*This library is distributed in the hope that it will be useful, *
*but WITHOUT ANY WARRANTY; without even the implied warranty of *
*MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
*Lesser General Public License for more details. *
* *
*You should have received a copy of the GNU Lesser General Public *
*License along with this library; if not, write to the Free Software *
*Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
**************************************************************************************
*/
#include "StdAfx.h"
#include "QuestImporter.h"
#include "../shared/StringUtil.h"
#include "../shared/geom.h"
#include "../shared/vector.h"
#include "../render/ViewManager.h"
#include "../render/EntityView.h"
#include "EntityManager.h"
#include "Tile.h"
#include "StateFactory.h"
#include "../kernel.h"
extern Kernel* g_kernel;
QuestImporter::QuestImporter()
{
}
/** Create the a scene from a .MAP file */
Scene* QuestImporter::CreateScene(const std::string &file)
{
StringUtil util(file, '.');
// get the name of the map
if ( util.HasNext() )
m_name = util.GetNext();
Release();
// parse out the define file
ParseDefine();
// allocate memory for the new scene
Scene* scene = new Scene;
// parse the layers
ParseLayers( 1, scene->GetBackgroundLayer(), scene );
ParseLayers( 2, scene->GetForegroundLayer(), scene );
// TEMP --HACK-- register the current scene with
// the entity manager, has to be a better way
EntityManager::GetInstance()->SetScene( scene );
// now create the entities
ParseEntities();
// Now fill the tiles with events
ParseEvents( scene );
return scene;
}
/** Parse the .DFN file */
void QuestImporter::ParseDefine()
{
std::string sfile = m_name + ".dfn";
MFile file;
// open stream
if ( /*file.Open( sfile ) ) //*/file.OpenZippedFile( sfile ) )
{
g_kernel->GetConsole()->Print( ("ERROR: Could not find: " + sfile).c_str() );
return;
}
// get the version
m_version = file.ReadLine();
// state the version
g_kernel->GetConsole()->Print( ("--Map version: "+ m_version).c_str() );
// read the file
while ( !file.IsEnd() )
{
// Read the Char association
std::string type = file.ReadNext( ":" );
// read the image file name
std::string filename = file.ReadNext( ":" );
// read the frame time
double frameTime = file.ReadDouble();
// read the row in the image file
int row = file.ReadInt();
// read the col in the image file
int col = file.ReadInt();
//std::cout << "Type: " << type << " filename: " << filename << " row: " << row << "\n";
//
// TODO - add animation to tiles
//
// load the image
Image* image = g_kernel->GetResource()->LoadImages( filename, row ,col );
// create the tile
Tile* tile = new Tile( image, row, col );
// insert into the map
m_tiles[ type ] = tile;
}
// close off the stream
file.Close();
}
/** Parse .LY1 and .LY2 files -- The map layer */
void QuestImporter::ParseLayers(int layer, type_Layer &layers, Scene* scene )
{
std::string sfile = m_name + ((layer == 1) ? ".ly1" : ".ly2");
MFile file;
// open stream
if ( /*file.Open( sfile ) ) //*/file.OpenZippedFile( sfile ) )
{
g_kernel->GetConsole()->Print( ("ERROR: Could not find: "+ sfile).c_str() );
return;
}
if ( layer == 1 )
{
std::string sound = file.ReadLine();
g_kernel->GetConsole()->Print( ("--Map loading sound resource: " + sound).c_str() );
g_kernel->GetSound()->PlayMusic( sound );
}
// parse the layer
Parse( layers, file, scene );
file.Close();
}
/** Parse a layer file */
void QuestImporter::Parse( type_Layer &layer, MFile &file, Scene* scene )
{
// get the map dimensions
int size_x = file.ReadInt();
int size_y = file.ReadInt();
scene->SetMaxX( size_x );
scene->SetMaxY( size_y );
// print dimensions
g_kernel->GetConsole()->Print("--Map dimensions %5d by %5d", size_x, size_y);
//file.ReadLine();
for ( int y = 0; y < size_y; y++ ) {
std::vector<Tile*> subArray;
for(int x = 0; x < size_x; x++ )
{
// read the next tile ref
std::string next = file.ReadNext(":");
Tile* tile = NULL;
// check to see if it is valid
if ( m_tiles.find( next ) != m_tiles.end() )
tile = m_tiles[ next ];
else if ( next == "0" )
{
subArray.push_back( NULL );
continue;
}
else {
// if its not valid, spit out an error message
g_kernel->GetConsole()->Print( ("**Layer Parsing Error in: "+ file.FileName()).c_str() );
g_kernel->GetConsole()->Print("**On line: %4d %4d", x, y );
//std::cout << "x: " << x << " y: " << y << " next: " << next << "\n";
//continue;
return;
}
MPoint p(x, y);
// add the point to the tile
tile->AddEvent( p, NULL );
// add it to the layer
subArray.push_back(tile);
}
file.ReadLine();
//file.ReadNext("\n");
layer.push_back( subArray );
subArray.clear();
}
file.Close();
}
/** Parse .EVT file -- The events on each tile */
void QuestImporter::ParseEvents(Scene* scene)
{
std::string sfile = m_name + ".evt";
MFile file;
// open stream
if ( /*file.Open( sfile ) ) //*/file.OpenZippedFile( sfile ) )
{
g_kernel->GetConsole()->Print( ("ERROR: Could not find: "+ sfile).c_str() );
return;
}
while( !file.IsEnd() )
{
// the location of the tile
int tile_x = file.ReadInt();
int tile_y = file.ReadInt();
// read the event type
//int event_type = file.ReadInt();
/*--------------------------------
Build the Event structure
---------------------------------*/
// the location of the effected entity
int location_x = file.ReadInt();
int location_y = file.ReadInt();
// get the destination point
int point_x = file.ReadInt();
int point_y = file.ReadInt();
// get the damage
int damage = file.ReadInt();
g_kernel->GetConsole()->Print( "%4d %4d : %4d %4d : %4d %4d : %4d ", tile_x, tile_y, //event_type,
location_x, location_y, point_x,point_y, damage );
// now find the tile
Tile* tile = scene->GetTile(1, tile_x, tile_y );
// Set the destination
int wx = 0; int wy = 0;
scene->TileToWorld( point_x, point_y, wx, wy );
Vector2f dest(wx, wy);
MPoint tile_location( tile_x, tile_y );
// create the entity
MEvent* e = new MEvent;
e->destination = dest;
e->damage = damage;
e->type = 0; //event_type;
e->effects = NULL; // TODO: Get an entity by point
// add the event to the tile
tile->AddEvent( tile_location, e );
}
file.Close();
}
/** Parse .ENTS file -- The Entities on a map */
void QuestImporter::ParseEntities()
{
std::string sfile = m_name + ".ents";
MFile file;
// open stream
if ( file.OpenZippedFile( sfile ) )
{
g_kernel->GetConsole()->Print( ("ERROR: Could not find: "+ sfile).c_str() );
return;
}
g_kernel->GetConsole()->Print( "---Parsing Entities..." );
// for creating the entity
EntityManager* entMng = EntityManager::GetInstance();
// for creating the view of the entity
ViewManager* vMng = ViewManager::GetInstance();
while( !file.IsEnd() ) {
// read the entities type name
std::string entName = file.ReadNext(":");
IEntity* ent = NULL;
if ( entName == "player" ) {
ent = entMng->CreatePlayer( entName );
} else if ( entName.compare("weapon")==0 ) {
ent = entMng->CreateWeapon( entName );
} else
ent = entMng->CreateEntity( entName );
ent->SetName( entName );
ent->m_attributes.Put( "entity_type", entName );
// read the entities reference
std::string entRef = file.ReadNext(":");
/*--------------------------------------------------
Start reading properties
---------------------------------------------------*/
//
file.ReadNext("{");
file.ReadLine();
bool rightBrace = false;
while( !file.IsEnd() )
{
std::string line = file.ReadLine();
if ( line == "}" )
{
rightBrace = true;
break;
}
StringUtil util( line, ':' );
std::string propName, v1, v2;
// get the name
if ( util.HasNext() )
{
propName = util.GetNext();
}
// get the value
if ( util.HasNext() )
{
v1 = util.GetNext();
}
// get the 2nd value if applicable
if ( util.HasNext() )
{
v2 = util.GetNext();
}
if ( v2 != "" && util.IsNumber( v1) && util.IsNumber( v2 ) )
{
ent->m_attributes.Put( propName, util.ToFloat( v1 ), util.ToFloat( v2 ) ); // vector
} else if ( util.IsNumber( v1 ) ){
ent->m_attributes.Put( propName, util.ToInt( v1 ) ); // integer
} else {
ent->m_attributes.Put( propName, v1 ); // string
}
}
if ( !rightBrace )
{
g_kernel->GetConsole()->Print( ("**Error parsing Entities in: " + sfile + " missing a closing \'}\' ").c_str() );
g_kernel->GetConsole()->Print( "**On byte: %d of %d", file.GetPosition(), file.Size() );
delete ent;
return;
}
// apply common attributes
ent->Apply();
/*--------------------------------------------------------
Now parse out the states of these entity
---------------------------------------------------------*/
// create the view
EntityView* view = vMng->CreateView( ent );
view->SetVisible( true );
file.ReadNext("{");
file.ReadLine();
std::string simage = file.ReadNext(":");
int row = file.ReadInt();
int col = file.ReadInt();
Image* image = g_kernel->GetResource()->LoadImages( simage, row, col );
view->GetModel()->SetImage( image );
bool rightBrace2 = false;
// read states
while( !file.IsEnd() )
{
if ( file.Peek() == '}' )
{
rightBrace2 = true;
break;
}
// create our model directions
ModelDirections* dirs = new ModelDirections;
std::string state = file.ReadNext(":");
std::string sound = file.ReadNext(":");
std::string script = file.ReadNext(":");
// get all four directions
int animTime = 0;
for ( int i = 0; i < 4; i++ )
{
animTime = file.ReadInt();
int imageRow = file.ReadInt();
int imageCol = file.ReadInt();
int amount = file.ReadInt();
dirs->AddDirection( i, animTime, imageRow, imageCol, amount );
}
// add the state to the model
view->GetModel()->AddState( state, dirs );
// create the state
State* entState = StateFactory::GetInstance()->CreateState( state );
if ( sound != "null" && entState )
entState->m_sound = g_kernel->GetResource()->LoadSound( sound );
if ( script != "null" && entState )
entState->m_scriptFile = script;
entState->m_nextUpdate = animTime;
ent->AddState( state, entState );
file.ReadLine();
}
if ( !rightBrace2 )
{
g_kernel->GetConsole()->Print( ("**Error parsing Entity Models in: " + sfile + " missing a closing \'}\' ").c_str() );
g_kernel->GetConsole()->Print( "**On byte: %d of %d", file.GetPosition(), file.Size() );
return;
}
ent->SetState( ENT_STATES[IDLE] );
// now we can add the ent def
m_entities[entRef] = ent;
file.ReadLine();
}
file.Close();
}
/** Release resources */
void QuestImporter::Release()
{
type_Tiles::iterator it = m_tiles.begin();
for(; it != m_tiles.end();it++)
{
if ( it->second )
delete it->second;
}
m_tiles.clear();
m_entities.clear();
}
QuestImporter::~QuestImporter(void)
{
Release();
}
See more files for this project here