/*
 *  Arcanum Editor - ROM area editor
 *  Copyright (C) 1999  Lucas Wall <kthulhu@usa.net>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  any later version.
 *
 *  This program 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 General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 *
 *  If you make changes to the source and want to make the public you can
 *  mail the diferences to me <kthulhu@usa.net> and I'll add them to the
 *  main distribution. Of course your name will be added to the program with
 *  information about the changes you made.
 *
 *
 *  Packed on Thu Aug 19 03:02:27 1999
 *
 */


/*
 * File: Tables.cpp
 *
 * Changes:
 *
 * 19/08/99 Lucas Wall <kthulhu@usa.net>
 *          First source release. Its quite messy and has no
 *          comments. I never planed to release the source code... :-)
 *
 */


// Tables.cpp: implementation of the CTables class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "arcaed.h"
#include "Tables.h"
#include "fread.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// CNumStrData Class
//////////////////////////////////////////////////////////////////////

template <> void AFXAPI DestructElements <CNumStrData*> ( CNumStrData** pElements, int nCount )
{
    for ( int i = 0; i < nCount; i++, pElements++ )
    {
		delete *pElements;
    }
}

template <> void AFXAPI DestructElements <CObjTypeData*> ( CObjTypeData** pElements, int nCount )
{
    for ( int i = 0; i < nCount; i++, pElements++ )
    {
		delete *pElements;
    }
}

template <> void AFXAPI DestructElements <CColorData*> ( CColorData** pElements, int nCount )
{
    for ( int i = 0; i < nCount; i++, pElements++ )
    {
		delete *pElements;
    }
}

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CNumStrData::CNumStrData()
{
	m_num = 0;
	m_text = "";
	m_show = "";
}

CNumStrData::~CNumStrData()
{

}

const CNumStrData& CNumStrData::operator=( const CNumStrData &data )
{
	m_num = data.m_num;
	m_text = data.m_text;
	m_show = data.m_show;
	return *this;
}

//////////////////////////////////////////////////////////////////////
// CObjTypeData Class
//////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CObjTypeData::CObjTypeData()
{
	m_num = 0;
	m_text = "";
}

CObjTypeData::~CObjTypeData()
{

}

//////////////////////////////////////////////////////////////////////
// CObjVData Class
//////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CObjVData::CObjVData()
{
	m_fixedtable = TABLE_NEW;
	m_text = "";
	m_type = 'N';
}

CObjVData::~CObjVData()
{

}

//////////////////////////////////////////////////////////////////////
// CColorData Class
//////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CColorData::CColorData()
{
	m_num = m_r = m_g = m_b = 0;
}

CColorData::~CColorData()
{

}

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CTables::CTables()
{
	m_isdoor = 0;
	m_locked = 0;
	m_mudtype = MUD_ARCANUM;
	m_mobprog = TRUE;
}

CTables::~CTables()
{

}

int CTables::load_data( char *fname, int *line )
{
	CFile f;
	if( !f.Open( fname, CFile::modeRead ) )
		return TRUE;
	CArchive ar( &f, CArchive::load );

	*line = 0;

	while( true )
	{
		char letter;
		CString word;
		int res;

		while( ( letter = fread_letter( ar ) ) != '#' 
			&& letter != 0 );

		if ( letter == 0 ) break;

		word = fread_word( ar );
		word.MakeUpper();

		res = TRUE;
		if ( word == "END" ) break;
		else if ( word == "GENERAL" ) res = load_general( ar );
		else if ( word == "SECTORTYPE" ) res = load_sectortypes( ar );
		else if ( word == "ROOMFLAGS" ) res = load_flags( ar, m_roomflags );
		else if ( word == "EXITFLAGS" ) res = load_flags( ar, m_exitflags );
		else if ( word == "OBJTYPES" ) res = load_objtypes( ar );
		else if ( word == "OBJTABLES" ) res = load_objtables( ar );
		else if ( word == "EXTRAFLAGS" ) res = load_flags( ar, m_extra_flags );
		else if ( word == "WEARFLAGS" ) res = load_flags( ar, m_wear_flags );
		else if ( word == "SPELLS" ) res = load_flags( ar, m_spells );
		else if ( word == "WEAPONCLASES" ) res = load_flags( ar, m_weapon_clases );
		else if ( word == "LIQUIDS" ) res = load_flags( ar, m_liquids );
		else if ( word == "ATTACKTYPES" ) res = load_strlist( ar, m_attack_types );
		else if ( word == "PORTALFLAGS" ) res = load_flags( ar, m_portal_flags );
		else if ( word == "AFFECTFLAGS" ) res = load_flags( ar, m_affect_flags );
		else if ( word == "AFFECTLOCATION" ) res = load_numlist( ar, m_affect_location );
		else if ( word == "IMMFLAGS" ) res = load_flags( ar, m_imm_flags );
		else if ( word == "MERCMSG" ) res = load_numlist( ar, m_mercmsg );
		else if ( word == "MOBFLAGS" ) res = load_mobflags( ar );
		else if ( word == "ACTFLAGS" ) res = load_flags( ar, m_act_flags );
		else if ( word == "OFFFLAGS" ) res = load_flags( ar, m_off_flags );
		else if ( word == "PARTS" ) res = load_flags( ar, m_parts_flags );
		else if ( word == "FORM" ) res = load_flags( ar, m_form_flags );
		else if ( word == "SEX" ) res = load_flags( ar, m_sex );
		else if ( word == "SIZE" ) res = load_flags( ar, m_size );
		else if ( word == "POS" ) res = load_strlist( ar, m_pos );
		else if ( word == "MOBPROGTRIG" ) res = load_flags( ar, m_mobprog_trigs );
		else if ( word == "SKILLS" ) res = load_flags( ar, m_skills );
		else if ( word == "TRAINFLAGS" ) res = load_flags( ar, m_train_flags );
		else if ( word == "WEARPOS" ) res = load_numlist( ar, m_wearpos );
		else if ( word == "DIRNAME" ) res = load_numlist( ar, m_dirname );
		else if ( word == "RECUNAME" ) res = load_numlist( ar, m_recuname );
		else if ( word == "SECTORCOLORS" ) res = load_colorlist( ar, m_sector_colors );
		else if ( word == "AFFTO" ) res = load_numlist( ar, m_aff_to );
		else if ( word == "CLASSES" ) res = load_numlist( ar, m_classes );

		if ( res )
		{
			ar.Close();
			f.Close();
			return TRUE;
		}

	}
	
	ar.Close();
	f.Close();

	return FALSE;
}

int CTables::load_sectortypes( CArchive &ar )
{
	CString text;
	CNumStrData *sector;

	while ( true )
	{
		text = fread_word( ar );
		text.MakeLower();
		if ( text == "end" ) break;
		if ( text == "" ) return TRUE;
		sector = new CNumStrData();
		sector->m_text = text;
		sector->m_num = fread_number( ar );
		m_sectortypes.Add( sector );
	}

	return FALSE;
}

int CTables::load_objtypes( CArchive &ar )
{
	CString text;
	CObjTypeData *objtype;
	int i;

	while ( true )
	{
		text = fread_word( ar );
		text.MakeLower();
		if ( text == "end" ) break;
		if ( text == "" ) return TRUE;
		objtype = new CObjTypeData();
		objtype->m_text = text;
		objtype->m_num = fread_number( ar );
		for ( i = 0; i < 5; i++ )
		{
			objtype->m_value[i].m_text = fread_string( ar );
			objtype->m_value[i].m_type = toupper( fread_letter( ar ) );
		}
		m_objtypes.Add( objtype );
	}

	return FALSE;
}

int CTables::load_flags( CArchive &ar, CArray< CNumStrData*, CNumStrData* > &flaglist )
{
	CString text;
	CNumStrData *flags;

	while ( true )
	{
		text = fread_word( ar );
		text.MakeLower();
		if ( text == "end" ) break;
		if ( text == "" ) return TRUE;
		flags = new CNumStrData();
		flags->m_text = text;
		flags->m_num = convert_flag( fread_word( ar )[0] );
		flaglist.Add( flags );
	}

	return FALSE;
}

int CTables::load_numlist( CArchive &ar, CArray< CNumStrData*, CNumStrData* > &flaglist )
{
	CString text;
	CNumStrData *flags;

	while ( true )
	{
		text = fread_word( ar );
		text.MakeLower();
		if ( text == "end" ) break;
		if ( text == "" ) return TRUE;
		flags = new CNumStrData();
		flags->m_text = text;
		flags->m_num = fread_number( ar );
		flaglist.Add( flags );
	}

	return FALSE;
}

int CTables::load_strlist( CArchive &ar, CArray< CNumStrData*, CNumStrData* > &flaglist )
{
	CString text;
	CNumStrData *flags;

	while ( true )
	{
		text = fread_word( ar );
		text.MakeLower();
		if ( text == "end" ) break;
		if ( text == "" ) return TRUE;
		flags = new CNumStrData();
		flags->m_text = text;
		flags->m_show = fread_word( ar );
		flaglist.Add( flags );
	}

	return FALSE;
}

int CTables::load_colorlist( CArchive &ar, CArray< CColorData*, CColorData* > &colorlist )
{
	CString text;
	CColorData *color;

	while ( true )
	{
		text = fread_word( ar );
		text.MakeLower();
		if ( text == "end" ) break;
		if ( text == "" ) return TRUE;
		color = new CColorData();
		color->m_num = atoi( text );
		color->m_r = fread_number( ar );
		color->m_g = fread_number( ar );
		color->m_b = fread_number( ar );
		colorlist.Add( color );
	}

	return FALSE;
}

int CTables::load_mobflags( CArchive &ar )
{
	CString text;
	CMobFlags *mobflags;

	while ( true )
	{
		text = fread_word( ar );
		text.MakeLower();
		if ( text == "end" ) break;
		if ( text == "" ) return TRUE;
		mobflags = new CMobFlags();
		mobflags->m_race = text;
		mobflags->m_act = fread_flags( ar );
		mobflags->m_aff = fread_flags( ar );
		mobflags->m_off = fread_flags( ar );
		mobflags->m_imm = fread_flags( ar );
		mobflags->m_res = fread_flags( ar );
		mobflags->m_vul = fread_flags( ar );
		mobflags->m_for = fread_flags( ar );
		mobflags->m_par = fread_flags( ar );
		m_mobflags.Add( mobflags );
	}

	return FALSE;
}

int CTables::load_objtables(CArchive & ar)
{
	CString text;
	int objtype, value, num;
	CNumStrData *flags;

	num = fread_number( ar );
	value = fread_number( ar );

	for ( objtype = 0; objtype < m_objtypes.GetSize(); objtype++ )
		if ( m_objtypes[objtype]->m_num == num )
			break;
	if ( objtype >= m_objtypes.GetSize() )
		return TRUE;

	if ( value > 4 || value < 0 )
		return TRUE;

	text = fread_word( ar );
	text.MakeUpper();
	if ( text == "SPELLS" ) 
	{
		m_objtypes[objtype]->m_value[value].m_fixedtable = TABLE_SPELLS;
		return FALSE;
	}
	else if ( text == "WEAPON_CLASES" ) 
	{
		m_objtypes[objtype]->m_value[value].m_fixedtable = TABLE_WEAPON_CLASES;
		return FALSE;
	}
	else if ( text == "LIQUIDS" ) 
	{
		m_objtypes[objtype]->m_value[value].m_fixedtable = TABLE_LIQUIDS;
		return FALSE;
	}
	else if ( text == "ATTACK_TYPES" ) 
	{
		m_objtypes[objtype]->m_value[value].m_fixedtable = TABLE_ATTACK_TYPES;
		return FALSE;
	}
	else if ( text == "EXIT_FLAGS" ) 
	{
		m_objtypes[objtype]->m_value[value].m_fixedtable = TABLE_EXIT_FLAGS;
		return FALSE;
	}
	else if ( text == "PORTAL_FLAGS" ) 
	{
		m_objtypes[objtype]->m_value[value].m_fixedtable = TABLE_PORTAL_FLAGS;
		return FALSE;
	}
	else if ( text == "NEW" )
		m_objtypes[objtype]->m_value[value].m_fixedtable = TABLE_NEW;
	else 
		return TRUE;

	while ( true )
	{
		text = fread_word( ar );
		text.MakeLower();
		if ( text == "end" ) break;
		if ( text == "" ) return TRUE;
		flags = new CNumStrData();
		flags->m_text = text;
		flags->m_num = convert_flag( fread_letter( ar ) );
		m_objtypes[objtype]->m_value[value].m_table.Add( flags );
	}

	return FALSE;
}

CArray< CNumStrData*, CNumStrData* > *CTables::get_table( int objtype, int value )
{
	int index;

	for ( index = 0; index < tables.m_objtypes.GetSize(); index ++ )
		if ( objtype == tables.m_objtypes[index]->m_num )
			break;

	if ( index >= tables.m_objtypes.GetSize()
		|| value < 0 || value > 4 ) return NULL;

	switch ( tables.m_objtypes[index]->m_value[value].m_fixedtable )
	{
	case TABLE_SPELLS:
		return &tables.m_spells;
	case TABLE_WEAPON_CLASES:
		return &tables.m_weapon_clases;
	case TABLE_LIQUIDS:
		return &tables.m_liquids;
	case TABLE_ATTACK_TYPES:
		return &tables.m_attack_types;
	case TABLE_EXIT_FLAGS:
		return &tables.m_exitflags;
	case TABLE_PORTAL_FLAGS:
		return &tables.m_portal_flags;
	}
	
	return &tables.m_objtypes[index]->m_value[value].m_table;
}

int CTables::load_general( CArchive &ar )
{
	CString word;

	while ( TRUE )
	{
		word = fread_word( ar );
		word.MakeUpper();

		if ( word == "END" ) return FALSE;
		else if ( word == "MUDTYPE" )
		{
			word = fread_word( ar );
			word.MakeUpper();
			if ( word == "ARCANUM" ) m_mudtype = MUD_ARCANUM;
			else if ( word == "ROMDEFAULT" ) m_mudtype = MUD_ROMDEFAULT;
			else if ( word == "ROMOLC" ) m_mudtype = MUD_ROMOLC;
			else return TRUE;
		}
		else if ( word == "ISDOOR" ) m_isdoor = fread_flags( ar );
		else if ( word == "LOCKED" ) m_locked = fread_flags( ar );
		else if ( word == "MOBPROG" ) m_mobprog = fread_number( ar );
		else return TRUE;

	}

	return TRUE;
}