Added PASAP entity systems

This was SVN commit r246.
This commit is contained in:
MarkT 2004-05-21 23:46:16 +00:00
parent 6f2aba631b
commit 6d5afc10ff
90 changed files with 8823 additions and 8423 deletions

View File

@ -19,6 +19,10 @@
#include "Renderer.h" #include "Renderer.h"
#include "Model.h" #include "Model.h"
#include "UnitManager.h" #include "UnitManager.h"
#include "BaseEntityCollection.h"
#include "Entity.h"
#include "EntityHandles.h"
#include "EntityManager.h"
#ifndef NO_GUI #ifndef NO_GUI
#include "gui/GUI.h" #include "gui/GUI.h"
@ -240,7 +244,7 @@ static void Render()
g_Renderer.SetCamera(g_Camera); g_Renderer.SetCamera(g_Camera);
// switch on wireframe for terrain if we want it // switch on wireframe for terrain if we want it
g_Renderer.SetTerrainRenderMode(SOLID); g_Renderer.SetTerrainRenderMode( SOLID );
RenderTerrain(); RenderTerrain();
RenderModels(); RenderModels();
@ -310,6 +314,8 @@ void UpdateWorld(float time)
for (uint i=0;i<units.size();++i) { for (uint i=0;i<units.size();++i) {
units[i]->m_Model->Update(time); units[i]->m_Model->Update(time);
} }
g_EntityManager.updateAll( time );
} }
@ -441,6 +447,12 @@ if(argc < 2)
// the terrain // the terrain
terr_init(); terr_init();
// This needs to be done after the renderer has loaded all its actors...
new CBaseEntityCollection;
new CEntityManager;
g_EntityTemplateCollection.loadTemplates();
// load a map if we were given one // load a map if we were given one
if (g_MapFile) { if (g_MapFile) {
CStr mapfilename("mods/official/maps/scenarios/"); CStr mapfilename("mods/official/maps/scenarios/");
@ -455,6 +467,12 @@ if(argc < 2)
} }
} }
// Initialize entities
g_EntityManager.dispatchAll( &CMessage( CMessage::EMSG_INIT ) );
PASAPScenario();
#ifndef NO_GUI #ifndef NO_GUI
in_add_handler(gui_handler); in_add_handler(gui_handler);
#endif #endif
@ -472,7 +490,7 @@ in_add_handler(terr_handler);
g_Config.Update(); g_Config.Update();
while(!quit) while(!quit)
{ {
g_Config.Update(); //g_Config.Update();
allow_reload(); allow_reload();
@ -515,6 +533,8 @@ in_add_handler(terr_handler);
#endif #endif
delete &g_Config; delete &g_Config;
delete &g_EntityManager;
delete &g_EntityTemplateCollection;
return 0; return 0;
} }

View File

@ -2,8 +2,8 @@ dofile("functions.lua")
-- Set up the Project -- Set up the Project
project.name = "prometheus" project.name = "prometheus"
project.bindir = "../../../binaries/system" project.bindir = "../../binaries/system"
project.libdir = "../../../binaries/system" project.libdir = "../../binaries/system"
-- Start the package part -- Start the package part
package = newpackage() package = newpackage()
@ -20,22 +20,24 @@ package.config["Release"].target = "ps"
-- Files -- Files
package.files = { package.files = {
-- ps/ -- ps/
{ sourcesfromdirs("../../ps") }, { sourcesfromdirs("../ps") },
-- simulation/
{ sourcesfromdirs("../simulation") },
-- lib/ -- lib/
{ sourcesfromdirs( { sourcesfromdirs(
"../../lib", "../lib",
"../../lib/sysdep", "../lib/sysdep",
"../../lib/res") }, "../lib/res") },
-- terrain/ -- terrain/
{ sourcesfromdirs( { sourcesfromdirs(
"../../terrain") }, "../terrain") },
-- gui/ -- gui/
{ sourcesfromdirs( { sourcesfromdirs(
"../../gui") }, "../gui") },
-- main -- main
{ "../../main.cpp" } { "../main.cpp" }
} }
package.includepaths = { "../../ps", "../../lib", "../../terrain", "../.." } package.includepaths = { "../ps", "../simulation", "../lib", "../terrain", ".." }
-- Platform Specifics -- Platform Specifics
if (OS == "windows") then if (OS == "windows") then
@ -44,7 +46,7 @@ if (OS == "windows") then
"opengl32", "opengl32",
"glu32" "glu32"
} }
tinsert(package.files, sourcesfromdirs("../../lib/sysdep/win")) tinsert(package.files, sourcesfromdirs("../lib/sysdep/win"))
package.linkoptions = { "/ENTRY:entry" } package.linkoptions = { "/ENTRY:entry" }
package.linkflags = { "static-runtime" } package.linkflags = { "static-runtime" }
package.buildflags = { "no-main" } package.buildflags = { "no-main" }

View File

@ -1,211 +0,0 @@
// base entity for all the Units and Buildings in the game 0AD
// written by Jacob Ricketts
#if !defined( __0AD_BASE_ENTITY_H_ )
#define __0AD_BASE_ENTITY_H_
#include "ai_common.h"
#include <vector>
#include <iostream>
class DLLExport CBaseEntity
{
public:
CBaseEntity( void ) { Clear(); };
virtual ~CBaseEntity( void ) { };
virtual void Clear( void ) { ClearBaseEntity(); };
//virtual bool Update( void ) = 0;
//virtual bool HandleMessage( const Message &msg ) = 0;
// === ID FUNCTIONS ===
inline
USHORT GetID( void ) { return( m_nID ); };
inline
USHORT GetTeamID( void ) { return( m_byteTeamID ); };
inline
BYTE AddAllies( BYTE bitflagTeams ) { return( m_bitflagAllies |= bitflagTeams ); };
inline
BYTE RemoveAllies( BYTE bitflagTeams ) { return( m_bitflagAllies &= ~bitflagTeams ); };
// === HIT POINT FUNCTIONS ===
inline
virtual USHORT GetHitPoints( void ) { std::cout << "CBaseEntity.GetHitPoints() called..." << endl; return( m_nHitPoints ); };
inline
virtual USHORT GetBaseHitPoints( void ) { return( m_nBaseHitPoints ); };
inline
virtual USHORT GetMaxHitPoints( void ) { return( m_nMaxHitPoints ); };
inline
virtual short GetRegenRate( void ) { return( m_nBaseRegenRate ); };
// === ATTACK STAT FUNCTIONS ===
inline
virtual USHORT GetAttackStrength( void ) { return( m_nBaseAttackStrength ); };
inline
virtual USHORT GetAttackRate( void ) { return( m_nBaseAttackRate ); };
inline
virtual USHORT GetAreaOfEffect( void ) { return( m_nBaseAreaOfEffect ); };
inline
virtual USHORT GetMaxRange( void ) { return( m_nBaseMaxRange ); };
inline
virtual USHORT GetMinRange( void ) { return( m_nBaseMinRange ); };
inline
virtual USHORT GetMeleeArmor( void ) { return( m_nBaseMeleeArmor ); } ;
inline
virtual USHORT GetPierceArmor( void ) { return( m_nBasePierceArmor ); };
// === MISC ATTRIBUTES ===
inline
virtual const std::vector<USHORT>& AvailableToCivs( void ) { return( m_vAvailableToCivs ); };
inline
virtual const Vector3D& GetPosition( void ) { return( m_vPos ); };
inline
virtual bool BoostsMorale( void ) { return( m_bBoostsMorale ); };
inline
virtual bool DemoralizesEnemies( void ) { return( m_bDemoralizesEnemies ); };
inline
virtual USHORT GetActionRate( void ) { return( m_nBaseActionRate ); };
inline
virtual USHORT GetAreaOfInfluence( void ) { return( m_nBaseAreaOfInfluence ); };
inline
virtual USHORT GetLOS( void ) { return( m_nBaseLOS ); };
// === BUILD STATS ===
inline
virtual USHORT GetBuildTime( void ) { return( m_nBuildTime ); };
inline
virtual USHORT GetReqFoodToBuild( void ) { return( m_nFoodReqToBuild ); };
inline
virtual USHORT GetReqGoldToBuild( void ) { return( m_nGoldReqToBuild ); };
inline
virtual USHORT GetReqMetalToBuild( void ) { return( m_nMetalReqToBuild ); };
inline
virtual USHORT GetReqStoneToBuild( void ) { return( m_nStoneReqToBuild ); };
inline
virtual USHORT GetReqWoodToBuild( void ) { return( m_nWoodReqToBuild ); };
inline
virtual const std::vector<USHORT>& GetBuildingsReqToBuild( void ) { return( m_vBuildingsReqToBuild ); };
inline
virtual const std::vector<USHORT>& GetTechsReqToBuild( void ) { return( m_vTechsReqToBuild ); };
// === UPGRADE STATS ===
inline
virtual USHORT UpgradesTo( void ) { return( m_nUpgradesTo ); };
inline
virtual USHORT GetUpgradeTime( void ) { return( m_nUpgradeTime ); };
inline
virtual USHORT GetReqFoodToUpgrade( void ) { return( m_nFoodReqToUpgrade ); };
inline
virtual USHORT GetReqGoldToUpgrade( void ) { return( m_nGoldReqToUpgrade ); };
inline
virtual USHORT GetReqMetalToUpgrade( void ) { return( m_nMetalReqToUpgrade ); };
inline
virtual USHORT GetReqStoneToUpgrade( void ) { return( m_nStoneReqToUpgrade ); };
inline
virtual USHORT GetReqWoodToUpgrade( void ) { return( m_nWoodReqToUpgrade ); };
inline
virtual const std::vector<USHORT>& GetBuildingsReqToUpgrade( void ) { return( m_vBuildingsReqToUpgrade ); };
inline
virtual const std::vector<USHORT>& GetTechsReqToUpgrade( void ) { return( m_vTechsReqToUpgrade ); };
BYTE m_nCurrentFrame;
protected:
void ClearBaseEntity( void );
USHORT m_nID; // ID for this entity
BYTE m_byteTeamID; // ID of the team this entity is on
BYTE m_bitflagAllies; // bitflag to contain the list of allies
std::vector<USHORT> m_vAvailableToCivs; // a list of Civs that can create this entity
// === ATTRIBUTES ===
USHORT m_nHitPoints; // current amount of hit points
USHORT m_nBaseHitPoints; // initial hit points
USHORT m_nMaxHitPoints; // maximum hit points
short m_nBaseRegenRate; // rate of health regeneation
USHORT m_nBaseAttackStrength; // base strength
USHORT m_nBaseAttackRate; // rate of attack
USHORT m_nBaseMinRange; // minimum range of attack
USHORT m_nBaseMaxRange; // maximum range of attack
USHORT m_nBaseActionRate; // rate of actions
USHORT m_nBaseAreaOfEffect; // area of effect
USHORT m_nBaseAreaOfInfluence; // area of influence
USHORT m_nBaseMeleeArmor; // armor rating against melee attacks
USHORT m_nBasePierceArmor; // armor rating against projectile attacks
USHORT m_nBaseLOS; // line of sight distance
USHORT m_nBuildTime; // time required to build
USHORT m_nUpgradeTime; // time required to upgrade
USHORT m_nFoodReqToBuild; // amount of food required to build
USHORT m_nGoldReqToBuild; // amount of gold required to build
USHORT m_nMetalReqToBuild; // amount of metal required to build
USHORT m_nStoneReqToBuild; // amount of stone required to build
USHORT m_nWoodReqToBuild; // amount of wood required to build
std::vector<USHORT> m_vBuildingsReqToBuild; // buildings required to build this entity
std::vector<USHORT> m_vTechsReqToBuild; // techs required to build this entity
USHORT m_nFoodReqToUpgrade; // cost to upgrade (food)
USHORT m_nGoldReqToUpgrade; // cost to upgrade (gold)
USHORT m_nMetalReqToUpgrade; // cost to upgrade (metal)
USHORT m_nStoneReqToUpgrade; // cost to upgrade (stone)
USHORT m_nWoodReqToUpgrade; // cost to upgrade (wood)
std::vector<USHORT> m_vBuildingsReqToUpgrade; // buildings required to upgrade this entity
std::vector<USHORT> m_vTechsReqToUpgrade; // techs required to upgrade this entity
USHORT m_nUpgradesTo; // ID of entity this unit will upgrade to if possible
bool m_bBoostsMorale; // does this entity boost Morale?
bool m_bDemoralizesEnemies; // does this entity demoralize enemy units?
Vector3D m_vPos; // position on the map
private:
};
#endif

View File

@ -398,6 +398,20 @@ ostream &operator<<(ostream &os, CStr &Str)
return os; return os;
} }
size_t CStr::GetHashCode() const
{
// FNV-1 hash for 64 bit integers.
size_t hash = 14695981039346656037;
const char* data = m_String.data();
for( int t = 0; t < m_String.length(); t++ )
{
hash *= 1099511628211;
hash ^= *(data++);
}
return( hash );
}
uint CStr::GetSerializedLength() const uint CStr::GetSerializedLength() const
{ {
return uint(m_String.length()+1); return uint(m_String.length()+1);

View File

@ -30,6 +30,8 @@ More Info:
*/ */
// Last modified: 19 May 04, Mark Thompson (mot20@cam.ac.uk / mark@wildfiregames.com)
#ifndef CSTR_H #ifndef CSTR_H
#define CSTR_H #define CSTR_H
@ -178,6 +180,8 @@ public:
inline const char *c_str() inline const char *c_str()
{ return m_String.c_str(); } { return m_String.c_str(); }
size_t GetHashCode() const;
// Serialization functions // Serialization functions
virtual uint GetSerializedLength() const; virtual uint GetSerializedLength() const;
virtual u8 *Serialize(u8 *buffer) const; virtual u8 *Serialize(u8 *buffer) const;
@ -188,6 +192,21 @@ private:
TCHAR m_ConversionBuffer[CONVERSION_BUFFER_SIZE]; TCHAR m_ConversionBuffer[CONVERSION_BUFFER_SIZE];
}; };
class CStr_hash_compare
{
public:
static const size_t bucket_size = 1;
static const size_t min_buckets = 16;
size_t operator()( const CStr& Key ) const
{
return( Key.GetHashCode() );
}
bool operator()( const CStr& _Key1, const CStr& _Key2 ) const
{
return( _Key1 < _Key2 );
}
};
// overloaded operator for ostreams // overloaded operator for ostreams
ostream &operator<<(ostream &os, CStr &Str); ostream &operator<<(ostream &os, CStr &Str);

View File

@ -1,292 +0,0 @@
// Last modified: 19 January 2004 (Mark Thompson)
#include "Entity.h"
//--------------------------------------------------------
// CEntity: Entity class
//--------------------------------------------------------
//--------------------------------------------------------
// CEntity::CEntity()
//--------------------------------------------------------
CEntity::CEntity()
{
}
//--------------------------------------------------------
// CEntity::~CEntity()
//--------------------------------------------------------
CEntity::~CEntity()
{
}
//--------------------------------------------------------
// CEntity::Dispatch( CEvent* ev )
//
// Handles the event ev, sent by the scheduler
//--------------------------------------------------------
void CEntity::Dispatch( CEvent* ev )
{
}
//--------------------------------------------------------
// CHandle: Stores entity refcounts, etc.
//--------------------------------------------------------
//--------------------------------------------------------
// CHandle::CHandle()
//--------------------------------------------------------
CHandle::CHandle()
{
ptr = NULL;
refcount = 0;
}
//--------------------------------------------------------
// CHandle::~CHandle()
//--------------------------------------------------------
CHandle::~CHandle()
{
if( refcount )
{
// WARNING: RELEASING LIVE HANDLE!
// TODO: Link this into the new logfile system.
}
delete ptr;
}
//--------------------------------------------------------
// CHandlePool: Tracks entity handles.
//--------------------------------------------------------
//--------------------------------------------------------
// CHandlePool::CHandlePool()
//--------------------------------------------------------
CHandlePool::CHandlePool()
{
for( unsigned short t = 0; t < MAX_HANDLES; t++ )
{
Pool[t].nextfree = t + 1;
}
FreeHandle = 0;
}
//--------------------------------------------------------
// CHandlePool::~CHandlePool()
//--------------------------------------------------------
CHandlePool::~CHandlePool()
{
//Terminating, clearing remaining handles...
}
//--------------------------------------------------------
// CHandlePool::Assign( CEntity* ptr )
//--------------------------------------------------------
HEntity CHandlePool::Assign( CEntity* ptr )
{
assert( FreeHandle != BAD_HANDLE );
unsigned short i = FreeHandle;
ptr->Handle = HEntityWeak( i );
FreeHandle = Pool[i].nextfree;
Pool[i].ptr = ptr;
return HEntity( i );
}
//--------------------------------------------------------
// CHandlePool::Destroy( unsigned short index )
//--------------------------------------------------------
void CHandlePool::Destroy( unsigned short index )
{
//Garbage collection
delete Pool[index].ptr;
Pool[index].nextfree = FreeHandle;
Pool[index].refcount = 0;
FreeHandle = index;
}
//--------------------------------------------------------
// HEntity: Refcounted handle to entities.
//--------------------------------------------------------
//--------------------------------------------------------
// HEntity::HEntity()
//--------------------------------------------------------
HEntity::HEntity()
{
index = BAD_HANDLE;
}
//--------------------------------------------------------
// HEntity::HEntity( unsigned short index )
//--------------------------------------------------------
HEntity::HEntity( unsigned short _index )
{
index = _index;
AddRef();
}
//--------------------------------------------------------
// HEntity::HEntity( const HEntity& copy )
//--------------------------------------------------------
HEntity::HEntity( const HEntity& copy )
{
index = copy.index;
AddRef();
}
//--------------------------------------------------------
// HEntity::HEntity( const HEntityWeak& copy )
//--------------------------------------------------------
HEntity::HEntity( const HEntityWeak& copy )
{
index = copy.index;
AddRef();
}
//--------------------------------------------------------
// HEntity::AddRef()
//
// Increments reference count
//--------------------------------------------------------
void HEntity::AddRef()
{
if( index == BAD_HANDLE ) return;
g_HandlePool.Pool[index].refcount++;
}
//--------------------------------------------------------
// HEntity::DecRef()
//
// Decrements reference count
//--------------------------------------------------------
void HEntity::DecRef()
{
if( index == BAD_HANDLE ) return;
if( !g_HandlePool.Pool[index].refcount ) return;
if( --g_HandlePool.Pool[index].refcount == 0 )
g_HandlePool.Destroy( index );
}
//--------------------------------------------------------
// HEntity::operator=( const HEntity& copy )
//--------------------------------------------------------
void HEntity::operator=( const HEntity& copy )
{
DecRef();
index = copy.index;
AddRef();
}
//--------------------------------------------------------
// HEntity::operator=( const HEntityWeak& copy )
//--------------------------------------------------------
void HEntity::operator=( const HEntityWeak& copy )
{
DecRef();
index = copy.index;
AddRef();
}
//--------------------------------------------------------
// HEntity::operator*()
//--------------------------------------------------------
CEntity& HEntity::operator*()
{
assert( index != BAD_HANDLE );
assert( g_HandlePool.Pool[index].ptr );
return( *g_HandlePool.Pool[index].ptr );
}
//--------------------------------------------------------
// HEntity: operator->()
//--------------------------------------------------------
CEntity* HEntity::operator->()
{
assert( index != BAD_HANDLE );
assert( g_HandlePool.Pool[index].ptr );
return( g_HandlePool.Pool[index].ptr );
}
//--------------------------------------------------------
// HEntity::~HEntity()
//--------------------------------------------------------
HEntity::~HEntity()
{
DecRef();
}
//--------------------------------------------------------
// HEntityWeak: Like HEntity, but it isn't refcounted.
// used mainly to hold references-to-self.
// It's slightly faster, and automatically
// converts to a safe HEntity when needed.
//--------------------------------------------------------
//--------------------------------------------------------
// HEntityWeak::HEntityWeak()
//--------------------------------------------------------
HEntityWeak::HEntityWeak()
{
index = BAD_HANDLE;
}
//--------------------------------------------------------
// HEntityWeak::HEntityWeak( unsigned short _index )
//--------------------------------------------------------
HEntityWeak::HEntityWeak( unsigned short _index )
{
index = _index;
}
//--------------------------------------------------------
// HEntityWeak::operator*()
//--------------------------------------------------------
CEntity& HEntityWeak::operator*()
{
assert( index != BAD_HANDLE );
assert( g_HandlePool.Pool[index].ptr );
return( *g_HandlePool.Pool[index].ptr );
}
//--------------------------------------------------------
// HEntityWeak::operator->()
//--------------------------------------------------------
CEntity* HEntityWeak::operator->()
{
assert( index != BAD_HANDLE );
assert( g_HandlePool.Pool[index].ptr );
return( g_HandlePool.Pool[index].ptr );
}
//--------------------------------------------------------
// HEntityWeak::operator HEntity()
//--------------------------------------------------------
HEntityWeak::operator HEntity()
{
return HEntity( index );
}

View File

@ -1,138 +0,0 @@
/*
Entity.h
Entities and associated classes
Mark Thompson (markt@0ad.wildfiregames.com)
Last modified: 19 January 2004 (Mark Thompson)
--Overview--
Contains the class definitions for entities, netsafe entity handles, handle manager
--Usage--
TODO
--Examples--
TODO
--More info--
TDD at http://forums.wildfiregames.com/0ad
*/
#ifndef ENTITY_INCLUDED
#define ENTITY_INCLUDED
#include "assert.h"
#include "stdio.h"
#include "Singleton.h"
#include "Event.h"
// Handle defines
#define MAX_HANDLES 8192
#define BAD_HANDLE MAX_HANDLES
#define NULL 0
typedef unsigned long DWORD;
// Forward-declarations
class CHandlePool;
class CEntity;
class HEntity;
class HEntityWeak;
// HEntityWeak: Weak (non-refcounted) smart pointer
class HEntityWeak
{
friend class CHandlePool;
friend class HEntity;
private:
unsigned short index;
HEntityWeak( unsigned short index );
public:
HEntityWeak();
CEntity& operator*();
CEntity* operator->();
operator HEntity();
};
// CEntity: Entity class
class CEntity
{
friend class CHandlePool;
private:
HEntityWeak Handle; // Reference to self, to include in messages, etc.
// Weak handle isn't refcounted, but is as soon
// as it gets passed out of this class.
public:
CEntity();
~CEntity();
void Dispatch( CEvent* ev );
};
// CHandle: Entity handles, used by manager class
class CHandle
{
friend class CHandlePool;
friend class HEntity;
friend class HEntityWeak;
private:
CEntity* ptr;
unsigned short refcount;
unsigned short nextfree; //Linked list for free handles
CHandle();
~CHandle();
};
// HEntity: Entity smart pointer
class HEntity
{
friend class CHandlePool;
friend class HEntityWeak;
private:
unsigned short index;
HEntity( unsigned short index );
void AddRef();
void DecRef();
public:
CEntity& operator*();
CEntity* operator->();
HEntity();
HEntity( const HEntity& copy );
HEntity( const HEntityWeak& copy );
void operator=( const HEntity& copy );
void operator=( const HEntityWeak& copy );
~HEntity();
};
// CHandlePool: Tracks entity handles
#define g_HandlePool CHandlePool::GetSingleton()
class CHandlePool : public Singleton<CHandlePool>
{
friend class HEntity;
friend class HEntityWeak;
private:
unsigned short FreeHandle;
CHandle Pool[MAX_HANDLES];
public:
CHandlePool();
~CHandlePool();
HEntity Assign( CEntity* ptr );
HEntity Create() { return Assign( new CEntity ); };
void Destroy( unsigned short index );
};
#endif // !defined( ENTITY_INCLUDED )

View File

View File

@ -1,46 +0,0 @@
/*
Event.h
Game event (scheduled messages) definitions
Mark Thompson (markt@0ad.wildfiregames.com)
Last modified: 19 January 2004 (Mark Thompson)
--Overview--
Contains the class definitions for serializable event messages.
--Usage--
TODO
--Examples--
TODO
--More info--
TDD at http://forums.wildfiregames.com/0ad
*/
#ifndef EVENT_INCLUDED
#define EVENT_INCLUDED
#include "assert.h"
#include "stdio.h"
#include "Network/Serialization.h"
#include "Entity.h"
#include "Network/NetMessage.h"
class CEvent : public CNetMessage
{
public:
virtual uint GetSerializedLength() = 0;
virtual u8* Serialize( u8* buffer ) = 0;
};
#endif // EVENT_INCLUDED

View File

@ -1,59 +0,0 @@
/*
Net Message Creator registration
*/
#ifdef CREATING_NMT
//HACKA HACKA HACKA HACKA HACKA HACK...
#ifdef NMT_CREATOR_PASS_CLASSDEF
/*
The Event classes;
Adding an event currently requires four steps.
One, create the event class within the NMT_CREATOR_PASS_CLASSDEF
ifdef. The classEvent macro will help.
Two, assign an message type in NetMessage.h.
Three, provide a deserializer function mapping in the
NMT_CREATOR_PASS_REGISTRATION ifdef, below.
Four, implement the interface ISerializable for the new class in
Event.cpp.
*/
#define classEvent( _ev ) \
struct CEvent##_ev : public CEvent \
{ \
public: \
uint GetSerializedLength(); \
u8* Serialize( u8* buffer ); \
static CNetMessage* Deserialize( const u8* buffer, \
uint length );
/*
classEvent( TestOnly )
int16 TheIntegerIveGot;
};
*/
#endif
#ifdef NMT_CREATOR_PASS_REGISTRATION
/*
{ NMT_Event_IveGotAnInteger, CEventTestOnly::Deserialize },
*/
#endif
#endif

View File

@ -0,0 +1,91 @@
#include "BaseEntity.h"
#include "ObjectManager.h"
#include "CStr.h"
// xerces XML stuff
#include <xercesc/dom/DOM.hpp>
#include <xercesc/parsers/XercesDOMParser.hpp>
#include <xercesc/framework/LocalFileInputSource.hpp>
#include <xercesc/util/XMLString.hpp>
#include <xercesc/util/PlatformUtils.hpp>
// Gee's custom error handler
#include <ps/XercesErrorHandler.h>
// automatically use namespace ..
XERCES_CPP_NAMESPACE_USE
bool CBaseEntity::loadXML( CStr filename )
{
// I can only assume Rich knows what this does ;)
bool parseOK = false;
// Initialize XML library
XMLPlatformUtils::Initialize();
{
// Create parser instance
XercesDOMParser *parser = new XercesDOMParser();
// Setup parser
parser->setValidationScheme(XercesDOMParser::Val_Auto);
parser->setDoNamespaces(false);
parser->setDoSchema(false);
parser->setCreateEntityReferenceNodes(false);
// Set customized error handler
CXercesErrorHandler *errorHandler = new CXercesErrorHandler();
parser->setErrorHandler(errorHandler);
// Get main node
LocalFileInputSource source( XMLString::transcode(filename) );
// Parse file
parser->parse(source);
// Check how many errors
parseOK = parser->getErrorCount() == 0;
if (parseOK) {
// parsed successfully - grab our data
DOMDocument *doc = parser->getDocument();
DOMElement *element = doc->getDocumentElement();
// root_name should be Object
CStr root_name = XMLString::transcode( element->getNodeName() );
// should have at least 3 children - Name, ModelName and TextureName
DOMNodeList *children = element->getChildNodes();
int numChildren=children->getLength();
for (int i=0; i<numChildren; ++i) {
// Get node
DOMNode *child = children->item(i);
// A child element
if (child->getNodeType() == DOMNode::ELEMENT_NODE)
{
// First get element and not node
DOMElement *child_element = (DOMElement*)child;
CStr element_name = XMLString::transcode( child_element->getNodeName() );
DOMNode *value_node= child_element->getChildNodes()->item(0);
CStr element_value=value_node ? XMLString::transcode(value_node->getNodeValue()) : "";
if (element_name==CStr("Name")) {
m_name = element_value;
} else if (element_name==CStr("Actor")) {
m_actorObject = g_ObjMan.FindObject( element_value );
} else if (element_name==CStr("Speed")) {
m_speed = element_value.ToFloat();
}
}
}
}
delete parser;
}
XMLPlatformUtils::Terminate();
return parseOK;
}

27
source/simulation/BaseEntity.h Executable file
View File

@ -0,0 +1,27 @@
#ifndef BASE_ENTITY_INCLUDED
#define BASE_ENTITY_INCLUDED
#include "CStr.h"
#include "ObjectEntry.h"
#include "EntityProperties.h"
class CBaseEntity
{
public:
// Load from XML
bool loadXML( CStr filename );
// Base stats
CObjectEntry* m_actorObject;
CStr m_name;
float m_speed;
// Extended properties table
std::hash_map<CStr,CGenericProperty,CStr_hash_compare> m_properties;
};
#endif

View File

@ -0,0 +1,67 @@
// Last modified: May 15 2004, Mark Thompson (mark@wildfiregames.com)
#include "BaseEntityCollection.h"
#include "ObjectManager.h"
#include "Model.h"
#include "io.h"
void CBaseEntityCollection::loadTemplates()
{
_finddata_t file;
intptr_t handle;
CStr pathname = "mods/official/entities/templates/";
CStr filespec = pathname + "*.xml";
handle = _findfirst( filespec, &file );
if( handle != -1 )
{
do
{
CBaseEntity newTemplate;
if( newTemplate.loadXML( pathname + file.name ) )
addTemplate( newTemplate );
}
while( !_findnext( handle, &file ) );
_findclose(handle);
}
// He's so annoyingly slow...
CBaseEntity* dude = getTemplate( "Prometheus Dude" );
dude->m_actorObject->m_WalkAnim->m_FrameTime /= 10.0f;
dude->m_speed *= 10.0f;
/*
// Nasty evil wicked hardcoding.
CBaseEntity dude;
dude.m_name = CStr( "Prometheus Dude" );
dude.m_actorObject = g_ObjMan.FindObject( "The Dude" );
dude.m_actorObject->m_Model->GetAnimation()->m_FrameTime /= 3.0f;
dude.speed = 0.3f;
addTemplate( dude );
*/
}
void CBaseEntityCollection::addTemplate( CBaseEntity& temp )
{
m_templates.push_back( temp );
}
CBaseEntity* CBaseEntityCollection::getTemplate( CStr name )
{
for( int t = 0; t < m_templates.size(); t++ )
if( m_templates[t].m_name == name ) return( &( m_templates[t] ) );
return( NULL );
}
CBaseEntity* CBaseEntityCollection::getTemplateByActor( CObjectEntry* actor )
{
for( int t = 0; t < m_templates.size(); t++ )
if( m_templates[t].m_actorObject == actor ) return( &( m_templates[t] ) );
return( NULL );
}

View File

@ -0,0 +1,24 @@
// Last modified: May 15 2004, Mark Thompson (mark@wildfiregames.com)
#ifndef BASEENT_COLLECTION_INCLUDED
#define BASEENT_COLLECTION_INCLUDED
#include <vector>
#include "CStr.h"
#include "Singleton.h"
#include "ObjectEntry.h"
#include "BaseEntity.h"
#define g_EntityTemplateCollection CBaseEntityCollection::GetSingleton()
class CBaseEntityCollection : public Singleton<CBaseEntityCollection>
{
std::vector<CBaseEntity> m_templates;
public:
CBaseEntity* getTemplate( CStr entityType );
void loadTemplates();
void addTemplate( CBaseEntity& temp );
CBaseEntity* getTemplateByActor( CObjectEntry* actor );
};
#endif

242
source/simulation/Entity.cpp Executable file
View File

@ -0,0 +1,242 @@
// Last modified: May 15 2004, Mark Thompson (mark@wildfiregames.com)
#include "Entity.h"
#include "Model.h"
#include "Terrain.h"
#include "EntityManager.h"
#include "BaseEntityCollection.h"
CEntity::CEntity( CBaseEntity* base, CVector3D position, float orientation )
{
// Set our parent unit and build us an actor.
m_base = base;
m_actor = new CUnit;
m_actor->m_Object = m_base->m_actorObject;
m_actor->m_Model = ( m_actor->m_Object->m_Model ) ? m_actor->m_Object->m_Model->Clone() : NULL;
// Register the actor with the renderer.
g_UnitMan.AddUnit( m_actor );
// Set up our instance data
m_speed = m_base->m_speed;
m_position = position;
m_orientation = orientation;
snapToGround();
updateActorTransforms();
// Register the addresses of our native properties with the properties table
m_properties["speed"] = &m_speed;
m_properties["orientation"] = &m_orientation;
m_properties["position"] = &m_position;
}
bool isWaypoint( CEntity* e )
{
return( e->m_base->m_name == CStr( "Waypoint" ) );
}
void CEntity::updateActorTransforms()
{
CMatrix3D m;
m.SetYRotation( m_orientation );
m.Translate( m_position );
m_actor->m_Model->SetTransform( m );
}
float CEntity::getExactGroundLevel( float x, float y )
{
// TODO MT: If OK with Rich, move to terrain core. Once this works, that is.
x /= 4.0f;
y /= 4.0f;
int xi = floor( x );
int yi = floor( y );
float xf = x - (float)xi;
float yf = y - (float)yi;
u16* heightmap = g_Terrain.GetHeightMap();
u16 mapsize = g_Terrain.GetVerticesPerSide();
float h00 = heightmap[yi*mapsize + xi];
float h01 = heightmap[yi*mapsize + xi + mapsize];
float h10 = heightmap[yi*mapsize + xi + 1];
float h11 = heightmap[yi*mapsize + xi + mapsize + 1];
/*
if( xf < ( 1.0f - yf ) )
{
return( HEIGHT_SCALE * ( ( 1 - xf - yf ) * h00 + xf * h10 + yf * h01 ) );
}
else
return( HEIGHT_SCALE * ( ( xf + yf - 1 ) * h11 + ( 1 - xf ) * h01 + ( 1 - yf ) * h10 ) );
*/
/*
if( xf > yf )
{
return( HEIGHT_SCALE * ( ( 1 - xf ) * h00 + ( xf - yf ) * h10 + yf * h11 ) );
}
else
return( HEIGHT_SCALE * ( ( 1 - yf ) * h00 + ( yf - xf ) * h01 + xf * h11 ) );
*/
return( HEIGHT_SCALE * ( ( 1 - yf ) * ( ( 1 - xf ) * h00 + xf * h10 ) + yf * ( ( 1 - xf ) * h01 + xf * h11 ) ) );
}
void CEntity::snapToGround()
{
m_position.Y = getExactGroundLevel( m_position.X, m_position.Z );
}
void CEntity::update( float timestep )
{
while( !m_orderQueue.empty() )
{
CEntityOrder* current = &m_orderQueue.front();
switch( current->m_type )
{
case CEntityOrder::ORDER_GOTO_NOPATHING:
{
float deltax = (float)current->m_data[0].location.x - m_position.X;
float deltay = (float)current->m_data[0].location.y - m_position.Z;
m_targetorientation = atan2( -deltax, -deltay );
float deltatheta = m_targetorientation - m_orientation;
if( deltatheta > PI )
deltatheta -= 2 * PI;
if( deltatheta < -PI )
deltatheta += 2 * PI;
/*
if( deltatheta > 1.0f * timestep )
deltatheta = 1.0f * timestep;
if( deltatheta < -1.0f * timestep )
deltatheta = -1.0f * timestep;
*/
m_orientation += deltatheta;
float len = sqrt( deltax * deltax + deltay * deltay );
float scale = timestep * m_speed;
if( scale > len )
scale = len;
deltax = -sinf( m_orientation ) * scale; deltay = -cosf( m_orientation ) * scale;
m_position.X += deltax;
m_position.Z += deltay;
snapToGround();
updateActorTransforms();
if( len < 0.1f )
m_orderQueue.pop_front();
return;
break;
}
case CEntityOrder::ORDER_GOTO:
{
CEntityOrder pathfind_solution;
pathfind_solution.m_type = CEntityOrder::ORDER_GOTO_NOPATHING;
pathfind_solution.m_data[0] = current->m_data[0];
m_orderQueue.pop_front();
m_orderQueue.push_front( pathfind_solution );
if( m_actor->m_Model->GetAnimation() != m_actor->m_Object->m_WalkAnim )
m_actor->m_Model->SetAnimation( m_actor->m_Object->m_WalkAnim );
break;
}
case CEntityOrder::ORDER_PATROL:
{
CEntityOrder this_segment;
CEntityOrder repeat_patrol;
this_segment.m_type = CEntityOrder::ORDER_GOTO;
this_segment.m_data[0] = current->m_data[0];
repeat_patrol.m_type = CEntityOrder::ORDER_PATROL;
repeat_patrol.m_data[0] = current->m_data[0];
m_orderQueue.pop_front();
m_orderQueue.push_front( this_segment );
m_orderQueue.push_back( repeat_patrol );
break;
}
default:
assert( 0 && "Invalid entity order" );
}
}
if( m_actor->m_Model->GetAnimation() != m_actor->m_Object->m_IdleAnim )
m_actor->m_Model->SetAnimation( m_actor->m_Object->m_IdleAnim );
}
void CEntity::dispatch( CMessage* msg )
{
switch( msg->type )
{
case CMessage::EMSG_TICK:
break;
case CMessage::EMSG_INIT:
if( m_base->m_name == CStr( "Prometheus Dude" ) )
{
std::vector<HEntity>* waypoints = g_EntityManager.matches( isWaypoint );
while( !waypoints->empty() )
{
CEntityOrder patrol;
int id = rand() % waypoints->size();
std::vector<HEntity>::iterator it = waypoints->begin();
it += id;
HEntity waypoint = *it;
patrol.m_type = CEntityOrder::ORDER_PATROL;
patrol.m_data[0].location.x = waypoint->m_position.X;
patrol.m_data[0].location.y = waypoint->m_position.Z;
pushOrder( patrol );
waypoints->erase( it );
}
}
break;
}
}
void CEntity::pushOrder( CEntityOrder& order )
{
m_orderQueue.push_back( order );
}
void PASAPScenario()
{
// Entity demo. I don't know where this information is going to come from for pre-PASAP.
// So, it's hardcoded here. *shrug*
/*
float waypoints[4][2] = { { 12.0f, 64.0f },
{ 28.0f, 64.0f },
{ 56.0f, 52.0f },
{ 24.0f, 28.0f } };
*/
/*
for( int i = 0; i < 4; i++ )
{
HEntity bob = g_EntityManager.create( "Prometheus Dude", CVector3D( waypoints[i][0], 0.0f, waypoints[i][1] ), 0.0f );
for( int t = 0; t < 4; t++ )
{
CEntityOrder march_of_bob;
march_of_bob.m_type = CEntityOrder::ORDER_PATROL ;
march_of_bob.m_data[0].location.x = waypoints[(i+t+1)%4][0];
march_of_bob.m_data[0].location.y = waypoints[(i+t+1)%4][1];
bob->pushOrder( march_of_bob );
}
}
*/
}

54
source/simulation/Entity.h Executable file
View File

@ -0,0 +1,54 @@
// Last modified: May 15 2004, Mark Thompson (mark@wildfiregames.com)
#ifndef ENTITY_INCLUDED
#define ENTITY_INCLUDED
#include <deque>
#include "EntityProperties.h"
#include "BaseEntity.h"
#include "Vector3D.h"
#include "Unit.h"
#include "UnitManager.h"
#include "EntityOrders.h"
#include "EntityHandles.h"
#include "EntityMessage.h"
class CEntityManager;
class CEntity
{
friend CEntityManager;
private:
// Intrinsic properties
public:
CStr m_name;
float m_speed;
CVector3D m_position;
float m_targetorientation;
float m_orientation;
CBaseEntity* m_base;
CUnit* m_actor;
std::deque<CEntityOrder> m_orderQueue;
// Extended properties table
std::hash_map<CStr,CGenericProperty,CStr_hash_compare> m_properties;
CEntity( CBaseEntity* base, CVector3D position, float orientation );
public:
// Handle-to-self.
HEntity me;
void dispatch( CMessage* msg );
void update( float timestep );
void updateActorTransforms();
float getExactGroundLevel( float x, float y );
void snapToGround();
void pushOrder( CEntityOrder& order );
};
extern void PASAPScenario();
#endif

View File

@ -0,0 +1,71 @@
#include "EntityHandles.h"
#include "EntityManager.h"
CHandle::CHandle()
{
m_entity = NULL;
m_refcount = 0;
}
HEntity::HEntity( u16 index )
{
m_handle = index;
addRef();
}
HEntity::HEntity( const HEntity& copy )
{
m_handle = copy.m_handle;
addRef();
}
HEntity::HEntity()
{
m_handle = INVALID_HANDLE;
}
HEntity::~HEntity()
{
if( CEntityManager::extant() )
decRef();
}
void HEntity::operator=( const HEntity& copy )
{
decRef();
m_handle = copy.m_handle;
addRef();
}
void HEntity::addRef()
{
if( m_handle != INVALID_HANDLE )
g_EntityManager.m_entities[m_handle].m_refcount++;
}
void HEntity::decRef()
{
if( m_handle != INVALID_HANDLE )
{
assert( g_EntityManager.m_entities[m_handle].m_refcount != 0 );
if( --g_EntityManager.m_entities[m_handle].m_refcount == 0 )
{
delete( g_EntityManager.m_entities[m_handle].m_entity );
}
}
}
CEntity* HEntity::operator->()
{
assert( m_handle != INVALID_HANDLE );
assert( g_EntityManager.m_entities[m_handle].m_refcount != 0 );
return( g_EntityManager.m_entities[m_handle].m_entity );
}
CEntity& HEntity::operator*()
{
assert( m_handle != INVALID_HANDLE );
assert( g_EntityManager.m_entities[m_handle].m_refcount != 0 );
return( *g_EntityManager.m_entities[m_handle].m_entity );
}

View File

@ -0,0 +1,35 @@
#ifndef ENTITY_HANDLE_INCLUDED
#define ENTITY_HANDLE_INCLUDED
#include "types.h"
#define INVALID_HANDLE 65535
class CEntity;
class CEntityManager;
class CHandle
{
public:
CEntity* m_entity;
u16 m_refcount;
CHandle();
};
class HEntity
{
friend CEntityManager;
u16 m_handle;
void addRef();
void decRef();
HEntity( u16 index );
public:
CEntity& operator*();
CEntity* operator->();
HEntity();
HEntity( const HEntity& copy );
void operator=( const HEntity& copy );
~HEntity();
};
#endif

View File

@ -0,0 +1,56 @@
#include "EntityManager.h"
#include "BaseEntityCollection.h"
CEntityManager::CEntityManager()
{
m_nextalloc = 0;
m_extant = true;
}
CEntityManager::~CEntityManager()
{
m_extant = false;
}
HEntity CEntityManager::create( CBaseEntity* base, CVector3D position, float orientation )
{
assert( base );
while( m_entities[m_nextalloc].m_refcount )
m_nextalloc++;
m_entities[m_nextalloc].m_entity = new CEntity( base, position, orientation );
m_entities[m_nextalloc].m_entity->me = HEntity( m_nextalloc );
return( HEntity( m_nextalloc++ ) );
}
HEntity CEntityManager::create( CStr templatename, CVector3D position, float orientation )
{
CBaseEntity* templateobj = g_EntityTemplateCollection.getTemplate( templatename );
return( create( templateobj, position, orientation ) );
}
std::vector<HEntity>* CEntityManager::matches( EntityPredicate predicate )
{
std::vector<HEntity>* matchlist = new std::vector<HEntity>;
for( int i = 0; i < MAX_HANDLES; i++ )
if( m_entities[i].m_refcount )
if( predicate( m_entities[i].m_entity ) )
matchlist->push_back( HEntity( i ) );
return( matchlist );
}
void CEntityManager::dispatchAll( CMessage* msg )
{
for( int i = 0; i < MAX_HANDLES; i++ )
if( m_entities[i].m_refcount )
m_entities[i].m_entity->dispatch( msg );
}
void CEntityManager::updateAll( float timestep )
{
for( int i = 0; i < MAX_HANDLES; i++ )
if( m_entities[i].m_refcount )
m_entities[i].m_entity->update( timestep );
}
bool CEntityManager::m_extant = false;

View File

@ -0,0 +1,35 @@
#ifndef ENTITY_MANAGER_INCLUDED
#define ENTITY_MANAGER_INCLUDED
#include "Singleton.h"
#include "Entity.h"
#include "EntityHandles.h"
#include "EntityMessage.h"
#define MAX_HANDLES 4096
#define g_EntityManager CEntityManager::GetSingleton()
class CEntityManager : public Singleton<CEntityManager>
{
friend HEntity;
friend CHandle;
CHandle m_entities[MAX_HANDLES];
int m_nextalloc;
static bool m_extant;
public:
typedef bool (*EntityPredicate)( CEntity* target );
CEntityManager();
~CEntityManager();
HEntity create( CBaseEntity* base, CVector3D position, float orientation );
HEntity create( CStr templatename, CVector3D position, float orientation );
void updateAll( float timestep );
void dispatchAll( CMessage* msg );
std::vector<HEntity>* matches( EntityPredicate predicate );
static inline bool extant() // True if the singleton is actively maintaining handles. When false, system is shutting down, handles are quietly dumped.
{
return( m_extant );
}
};
#endif

View File

@ -0,0 +1,19 @@
// Message structure
#ifndef MESSAGING_INCLUDED
#define MESSAGING_INCLUDED
struct CMessage
{
enum EMessageType
{
EMSG_TICK,
EMSG_INIT
} type;
CMessage( EMessageType _type )
{
type = _type;
}
};
#endif

View File

@ -0,0 +1,36 @@
// Last modified: May 15 2004, Mark Thompson (mark@wildfiregames.com)
#ifndef ENTITY_ORDER_INCLUDED
#define ENTITY_ORDER_INCLUDED
#define ORDER_MAX_DATA 1
#include "EntityHandles.h"
struct SOrderData
{
union
{
struct
{
float x;
float y;
} location;
u64 data; // miscellaneous
};
HEntity entity;
};
class CEntityOrder
{
public:
enum
{
ORDER_GOTO_NOPATHING,
ORDER_GOTO,
ORDER_PATROL
} m_type;
SOrderData m_data[ORDER_MAX_DATA];
};
#endif

View File

@ -0,0 +1,160 @@
#include "EntityProperties.h"
CGenericProperty::CGenericProperty()
{
m_type = PROP_INTEGER;
m_integer = 0;
}
CGenericProperty::CGenericProperty( i32 value )
{
m_type = PROP_INTEGER;
m_integer = value;
}
CGenericProperty::CGenericProperty( float value )
{
m_type = PROP_FLOAT;
m_float = value;
}
CGenericProperty::CGenericProperty( CStr& value )
{
m_type = PROP_STRING;
m_string = new CStr( value );
}
CGenericProperty::CGenericProperty( CVector3D& value )
{
m_type = PROP_VECTOR;
m_vector = new CVector3D( value );
}
CGenericProperty::CGenericProperty( void* value )
{
m_type = PROP_PTR;
m_ptr = value;
}
CGenericProperty::CGenericProperty( i32* value )
{
m_type = PROP_INTEGER_INTRINSIC;
m_integerptr = value;
}
CGenericProperty::CGenericProperty( float* value )
{
m_type = PROP_FLOAT_INTRINSIC;
m_floatptr = value;
}
CGenericProperty::CGenericProperty( CStr* value )
{
m_type = PROP_STRING_INTRINSIC;
m_string = value;
}
CGenericProperty::CGenericProperty( CVector3D* value )
{
m_type = PROP_VECTOR_INTRINSIC;
m_vector = value;
}
CGenericProperty::~CGenericProperty()
{
switch( m_type )
{
case PROP_STRING:
delete( m_string ); break;
case PROP_VECTOR:
delete( m_vector ); break;
default:
break;
}
}
CGenericProperty::operator CStr()
{
char working[64];
switch( m_type )
{
case PROP_STRING:
case PROP_STRING_INTRINSIC:
return( *m_string );
case PROP_VECTOR:
case PROP_VECTOR_INTRINSIC:
snprintf( working, 63, "{ %f, %f, %f }", m_vector->X, m_vector->Y, m_vector->Z );
working[63] = 0;
return( CStr( working ) );
case PROP_INTEGER:
return( CStr( m_integer ) );
case PROP_INTEGER_INTRINSIC:
return( CStr( *m_integerptr ) );
case PROP_FLOAT:
return( CStr( m_float ) );
case PROP_FLOAT_INTRINSIC:
return( CStr( *m_floatptr ) );
default:
return( CStr() );
}
}
CGenericProperty::operator CVector3D()
{
switch( m_type )
{
case PROP_VECTOR:
return( *m_vector );
default:
return( CVector3D() );
}
}
CGenericProperty::operator i32()
{
switch( m_type )
{
case PROP_INTEGER:
return( m_integer );
case PROP_INTEGER_INTRINSIC:
return( *m_integerptr );
case PROP_FLOAT:
return( (i32)m_float );
case PROP_FLOAT_INTRINSIC:
return( (i32)*m_floatptr );
case PROP_STRING:
return( m_string->ToInt() );
default:
return( 0 );
}
}
CGenericProperty::operator float()
{
switch( m_type )
{
case PROP_INTEGER:
return( (float)m_integer );
case PROP_INTEGER_INTRINSIC:
return( (float)*m_integerptr );
case PROP_FLOAT:
return( m_float );
case PROP_FLOAT_INTRINSIC:
return( *m_floatptr );
case PROP_STRING:
return( m_string->ToFloat() );
default:
return( 0.0f );
}
}
CGenericProperty::operator void*()
{
switch( m_type )
{
case PROP_PTR:
return( m_ptr );
default:
return( NULL );
}
}

View File

@ -0,0 +1,65 @@
// Inefficiency warning.
// Will move frequently accessed properties (position, name, etc.) to native C++ primitives.
// Just playing around with this idea, will probably keep it for at least some of the more exotic and/or user-defined properties.
// TODO: Fix the silent failures of the conversion functions: need to work out what to do in these cases.
// Mark Thompson mot20@cam.ac.uk / mark@wildfiregames.com
#ifndef ENTITY_PROPERTIES_INCLUDED
#define ENTITY_PROPERTIES_INCLUDED
#include "CStr.h"
#include "Vector3D.h"
#include <hash_map>
class CGenericProperty
{
public:
enum EPropTypes
{
PROP_INTRINSIC = 256,
PROP_INTEGER = 0,
PROP_FLOAT,
PROP_STRING,
PROP_VECTOR,
PROP_PTR,
PROP_INTEGER_INTRINSIC = PROP_INTEGER | PROP_INTRINSIC,
PROP_FLOAT_INTRINSIC = PROP_FLOAT | PROP_INTRINSIC,
PROP_STRING_INTRINSIC = PROP_STRING | PROP_INTRINSIC,
PROP_VECTOR_INTRINSIC = PROP_VECTOR | PROP_INTRINSIC
};
private:
EPropTypes m_type;
union
{
i32 m_integer;
i32* m_integerptr;
float m_float;
float* m_floatptr;
CStr* m_string;
CVector3D* m_vector;
void* m_ptr;
};
public:
CGenericProperty(); // Create an integer property containing 0.
CGenericProperty( i32 value ); // Create an integer property with a given value.
CGenericProperty( i32* value ); // Create an integer property that points to the given variable.
CGenericProperty( float value ); // Create a floating-point property with a given value.
CGenericProperty( float* value ); // Create a floating-point property that points to the given variable.
CGenericProperty( CStr& value ); // Create a string object property that's initialized to a copy of the given string.
CGenericProperty( CStr* value ); // Create a string object property that points to the given variable.
CGenericProperty( CVector3D& value ); // Create a vector object property that's initialized to a copy of the given vector.
CGenericProperty( CVector3D* value ); // Create a vector object property that points to the given variable.
CGenericProperty( void* value ); // Create a general property that points to the given value.
~CGenericProperty();
operator i32(); // Convert to an integer if possible (integer, float, some strings), otherwise returns 0.
operator float(); // Convert to a float if possible (integer, float, some strings), otherwise returns 0.0f.
operator CStr(); // Convert to a string if possible (all except generic pointer), otherwise returns CStr().
operator CVector3D(); // If this property is a vector, returns that vector, otherwise returns CVector3D().
operator void*(); // If this property is a generic pointer, returns that pointer, otherwise returns NULL.
};
#endif

View File

@ -5,6 +5,10 @@
#include "MapReader.h" #include "MapReader.h"
#include "UnitManager.h" #include "UnitManager.h"
#include "ObjectManager.h" #include "ObjectManager.h"
#include "BaseEntity.h"
#include "BaseEntityCollection.h"
#include "EntityManager.h"
#include "terrain/Model.h" #include "terrain/Model.h"
#include "terrain/Terrain.h" #include "terrain/Terrain.h"
#include "terrain/TextureManager.h" #include "terrain/TextureManager.h"
@ -150,17 +154,30 @@ void CMapReader::ApplyData(CFileUnpacker& unpacker)
for (u32 i=0;i<m_Objects.size();i++) { for (u32 i=0;i<m_Objects.size();i++) {
CObjectEntry* objentry=m_ObjectTypes[m_Objects[i].m_ObjectIndex]; CObjectEntry* objentry=m_ObjectTypes[m_Objects[i].m_ObjectIndex];
if (objentry && objentry->m_Model) { if (objentry && objentry->m_Model) {
// create new unit // Hijack the standard actor instantiation for actors that correspond to entities.
CUnit* unit=new CUnit; // Not an ideal solution; we'll have to figure out a map format that can define entities seperately or somesuch.
unit->m_Object=objentry;
unit->m_Model=objentry->m_Model ? objentry->m_Model->Clone() : 0;
CMatrix3D transform; CBaseEntity* templateObject = g_EntityTemplateCollection.getTemplateByActor( objentry );
memcpy(&transform._11,m_Objects[i].m_Transform,sizeof(float)*16); if( templateObject )
unit->m_Model->SetTransform(transform); {
CVector3D orient = ((CMatrix3D*)m_Objects[i].m_Transform)->GetIn();
CVector3D position = ((CMatrix3D*)m_Objects[i].m_Transform)->GetTranslation();
// add this unit to list of units stored in unit manager g_EntityManager.create( templateObject, position, atan2( orient.X, orient.Z ) );
g_UnitMan.AddUnit(unit); }
else
{
CUnit* unit=new CUnit;
unit->m_Object=objentry;
unit->m_Model=objentry->m_Model ? objentry->m_Model->Clone() : 0;
CMatrix3D transform;
memcpy(&transform._11,m_Objects[i].m_Transform,sizeof(float)*16);
unit->m_Model->SetTransform(transform);
// add this unit to list of units stored in unit manager
g_UnitMan.AddUnit(unit);
}
} }
} }

View File

@ -61,32 +61,21 @@ bool CObjectEntry::BuildModel()
CStr texturefilename(m_TextureName); CStr texturefilename(m_TextureName);
m_Model->SetTexture(CTexture((const char*) texturefilename)); m_Model->SetTexture(CTexture((const char*) texturefilename));
for( int t = 0; t < m_Animations.size(); t++ ) { if( m_Animations[t].m_FileName.Length() > 0 ) { CStr animfilename( "mods\\official\\" ); animfilename += m_Animations[t].m_FileName; try { m_Animations[t].m_AnimData = CSkeletonAnim::Load( animfilename ); } catch( ... ) { m_Animations[t].m_AnimData = NULL; } if( m_Animations[t].m_AnimName.LowerCase() == CStr( "idle" ) ) m_IdleAnim = m_Animations[t].m_AnimData; if( m_Animations[t].m_AnimName.LowerCase() == CStr( "walk" ) ) m_WalkAnim = m_Animations[t].m_AnimData; } } m_Model->SetAnimation( m_IdleAnim ); /*
// animations?
if (m_Animations.size()) { if (m_Animations.size()) {
// yes; iterate through and load each one if (m_Animations[0].m_FileName.Length()>0) {
for (uint i=0;i<m_Animations.size();i++) { CStr animfilename("mods\\official\\");
if (m_Animations[i].m_FileName.Length()>0) { animfilename+=m_Animations[0].m_FileName;
CStr animfilename("mods\\official\\");
animfilename+=m_Animations[i].m_FileName;
try { try {
m_Animations[i].m_AnimData=CSkeletonAnim::Load((const char*) animfilename); CSkeletonAnim* anim=CSkeletonAnim::Load((const char*) animfilename);
} catch (...) { m_Model->SetAnimation(anim);
m_Animations[i].m_AnimData=0; } catch (...) {
} m_Model->SetAnimation(0);
}
}
// set the first valid animation found as current
for (uint i=0;i<m_Animations.size();i++) {
if (m_Animations[i].m_AnimData) {
m_Model->SetAnimation(m_Animations[i].m_AnimData);
break;
} }
} }
} }
*/
// rebuild model bounds // rebuild model bounds
m_Model->CalcBounds(); m_Model->CalcBounds();
@ -95,11 +84,12 @@ bool CObjectEntry::BuildModel()
for (uint i=0;i<units.size();++i) { for (uint i=0;i<units.size();++i) {
if (units[i]->m_Model->GetModelDef()==oldmodel) { if (units[i]->m_Model->GetModelDef()==oldmodel) {
units[i]->m_Model->InitModel(m_Model->GetModelDef()); units[i]->m_Model->InitModel(m_Model->GetModelDef());
/*
CSkeletonAnim* anim=m_Model->GetAnimation(); CSkeletonAnim* anim=m_Model->GetAnimation();
if (anim) { if (anim) {
units[i]->m_Model->SetAnimation(anim); units[i]->m_Model->SetAnimation(anim);
} } */
} }
} }
@ -108,7 +98,7 @@ bool CObjectEntry::BuildModel()
return true; return true;
} }
CSkeletonAnim* CObjectEntry::GetNamedAnimation( CStr animationName ) { for( int t = 0; t < m_Animations.size(); t++ ) { if( m_Animations[t].m_AnimName == animationName ) return( m_Animations[t].m_AnimData ); } return( NULL ); }
bool CObjectEntry::Load(const char* filename) bool CObjectEntry::Load(const char* filename)
{ {
bool parseOK = false; bool parseOK = false;

View File

@ -2,20 +2,18 @@
#define _OBJECTENTRY_H #define _OBJECTENTRY_H
class CModel; class CModel;
class CSkeletonAnim;
#include <vector> #include <vector>
#include "CStr.h" #include "CStr.h"
#include "terrain/Bound.h" #include "terrain/Bound.h"
#include "terrain/ModelDef.h"
class CObjectEntry class CObjectEntry
{ {
public: public:
struct Anim { struct Anim {
CStr m_AnimName; CStr m_AnimName;
CStr m_FileName; CStr m_FileName; CSkeletonAnim* m_AnimData; //Pending
CSkeletonAnim* m_AnimData;
}; };
public: public:
@ -33,8 +31,8 @@ public:
CStr m_TextureName; CStr m_TextureName;
// model name // model name
CStr m_ModelName; CStr m_ModelName;
// list of valid animations for this object // animations
std::vector<Anim> m_Animations; std::vector<Anim> m_Animations; CSkeletonAnim* m_IdleAnim; CSkeletonAnim* m_WalkAnim; CSkeletonAnim* m_DeathAnim; CSkeletonAnim* m_MeleeAnim; CSkeletonAnim* m_RangedAnim; CSkeletonAnim* GetNamedAnimation( CStr animationName );
// object space bounds of model // object space bounds of model
// CBound m_Bound; // CBound m_Bound;
// corresponding model // corresponding model
@ -45,3 +43,4 @@ public:
#endif #endif

View File

@ -36,10 +36,8 @@ void CObjectManager::AddObjectType(const char* name)
void CObjectManager::AddObject(CObjectEntry* object,int type) void CObjectManager::AddObject(CObjectEntry* object,int type)
{ {
assert((uint)type<m_ObjectTypes.size()); assert((uint)type<m_ObjectTypes.size());
// build the model now to load the required model/animations from it if( object->BuildModel() )
if (object->BuildModel()) {
m_ObjectTypes[type].m_Objects.push_back(object); m_ObjectTypes[type].m_Objects.push_back(object);
}
} }
void CObjectManager::DeleteObject(CObjectEntry* entry) void CObjectManager::DeleteObject(CObjectEntry* entry)
@ -128,5 +126,3 @@ void CObjectManager::LoadObjects(int type)
_findclose(handle); _findclose(handle);
} }
} }

View File

@ -13,7 +13,6 @@
#include "Vector3D.h" #include "Vector3D.h"
#include "Quaternion.h" #include "Quaternion.h"
// TODO, RC: ugh - remove; use CStr
#ifndef MAX_NAME_LENGTH #ifndef MAX_NAME_LENGTH
#define MAX_NAME_LENGTH 128 #define MAX_NAME_LENGTH 128
#endif #endif

View File

@ -1,3 +1,4 @@
#include "TextureManager.h" #include "TextureManager.h"
#include "lib.h" #include "lib.h"
#include "ogl.h" #include "ogl.h"
@ -23,7 +24,7 @@ void CTextureManager::AddTextureType(const char* name)
m_TerrainTextures.resize(m_TerrainTextures.size()+1); m_TerrainTextures.resize(m_TerrainTextures.size()+1);
STextureType& ttype=m_TerrainTextures.back(); STextureType& ttype=m_TerrainTextures.back();
ttype.m_Name=name; ttype.m_Name=name;
ttype.m_Index=(int)m_TerrainTextures.size()-1; ttype.m_Index=m_TerrainTextures.size()-1;
} }
CTextureEntry* CTextureManager::FindTexture(const char* filename) CTextureEntry* CTextureManager::FindTexture(const char* filename)
@ -198,4 +199,3 @@ void CTextureManager::LoadTerrainTextures()
} }
} }
} }

View File

@ -1,3 +1,4 @@
#include "Matrix3D.h" #include "Matrix3D.h"
#include "Renderer.h" #include "Renderer.h"
#include "Terrain.h" #include "Terrain.h"
@ -23,21 +24,27 @@ void RenderScene ();
extern bool keys[512]; // SDL also defines non-ascii keys; 512 should be enough extern bool keys[512]; // SDL also defines non-ascii keys; 512 should be enough
//CMatrix3D g_WorldMat; CMatrix3D g_WorldMat;
CRenderer g_Renderer; CRenderer g_Renderer;
CTerrain g_Terrain; CTerrain g_Terrain;
CCamera g_Camera; CCamera g_Camera;
CLightEnv g_LightEnv; CLightEnv g_LightEnv;
int SelPX, SelPY, SelTX, SelTY;
int g_BaseTexCounter = 0;
int g_SecTexCounter = 1;
int g_TransTexCounter = 0;
int g_TickCounter = 0;
double g_LastTime;
const int NUM_ALPHA_MAPS = 13;
const float ViewScrollSpeed = 60;
float ViewFOV;
int mouse_x=50, mouse_y=50; int mouse_x=50, mouse_y=50;
float ViewScrollSpeed = 60.0f;
float ViewZoomFactor = 1.0f;
float ViewFOV = 0.0f;
void terr_init() void terr_init()
{ {
int xres,yres; int xres,yres;
@ -55,7 +62,6 @@ void terr_init()
InitScene (); InitScene ();
} }
void terr_update(const float DeltaTime) void terr_update(const float DeltaTime)
{ {
const float dx = ViewScrollSpeed * DeltaTime; const float dx = ViewScrollSpeed * DeltaTime;
@ -73,6 +79,7 @@ void terr_update(const float DeltaTime)
g_Camera.m_Orientation.Translate(Up*-1); g_Camera.m_Orientation.Translate(Up*-1);
const float s30 = sin(DEGTORAD(30.0f)); const float s30 = sin(DEGTORAD(30.0f));
const float c30 = cos(DEGTORAD(30.0f)); const float c30 = cos(DEGTORAD(30.0f));
const float s45 = sin(DEGTORAD(45.0f)); const float s45 = sin(DEGTORAD(45.0f));
@ -102,6 +109,8 @@ void terr_update(const float DeltaTime)
bool terr_handler(const SDL_Event& ev) bool terr_handler(const SDL_Event& ev)
{ {
switch(ev.type) switch(ev.type)
@ -129,7 +138,105 @@ bool terr_handler(const SDL_Event& ev)
g_Camera.m_Orientation.RotateY(DEGTORAD(-45)); g_Camera.m_Orientation.RotateY(DEGTORAD(-45));
g_Camera.m_Orientation.Translate (100, 150, -100); g_Camera.m_Orientation.Translate (100, 150, -100);
break; break;
}
/* case 'L':
g_HillShading = !g_HillShading;
break;
// tile selection
case SDLK_DOWN:
if(++SelTX > 15)
if(SelPX == g_Terrain.GetPatchesPerSide()-1)
SelTX = 15;
else
SelTX = 0, SelPX++;
break;
case SDLK_UP:
if(--SelTX < 0)
if(SelPX == 0)
SelTX = 0;
else
SelTX = 15, SelPX--;
break;
case SDLK_RIGHT:
if(++SelTY > 15)
if(SelPY == g_Terrain.GetPatchesPerSide()-1)
SelTY = 15;
else
SelTY = 0, SelPY++;
break;
case SDLK_LEFT:
if(--SelTY < 0)
if(SelPY == 0)
SelTY = 0;
else
SelTY = 15, SelPY--;
break;
case SDLK_KP0:
{
CMiniPatch *MPatch = &g_Terrain.GetPatch(SelPY, SelPX)->m_MiniPatches[SelTY][SelTX];
/*if (!MPatch->Tex2)
{
MPatch->m_AlphaMap = AlphaMaps[g_TransTexCounter];
MPatch->Tex2 = BaseTexs[g_SecTexCounter];
}
else
{
MPatch->Tex2 = 0;
MPatch->m_AlphaMap = 0;
}*/
break;
}
/*case SDLK_KP1:
{
CMiniPatch *MPatch = &g_Terrain.GetPatch(SelPY, SelPX)->m_MiniPatches[SelTY][SelTX];
g_BaseTexCounter++;
if (g_BaseTexCounter > 4)
g_BaseTexCounter = 0;
MPatch->Tex1 = BaseTexs[g_BaseTexCounter];
break;
}
case SDLK_KP2:
{
CMiniPatch *MPatch = &g_Terrain.m_Patches[SelPY][SelPX].m_MiniPatches[SelTY][SelTX];
if (MPatch->Tex2)
{
g_SecTexCounter++;
if (g_SecTexCounter > 4)
g_SecTexCounter = 0;
MPatch->Tex2 = BaseTexs[g_SecTexCounter];
}
break;
}
case SDLK_KP3:
{
CMiniPatch *MPatch = &g_Terrain.m_Patches[SelPY][SelPX].m_MiniPatches[SelTY][SelTX];
if (MPatch->m_AlphaMap)
{
g_TransTexCounter++;
if (g_TransTexCounter >= NUM_ALPHA_MAPS)
g_TransTexCounter = 0;
MPatch->m_AlphaMap = AlphaMaps[g_TransTexCounter];
}
break;
}*/
//}
} }
return false; return false;
@ -156,7 +263,7 @@ void InitScene ()
int w; int w;
int h; int h;
tex_info(ht, &w, &h, NULL, NULL, (void**)&p); tex_info(ht, &w, &h, NULL, NULL, (void **)&p);
printf("terrain.raw: %dx%d\n", w, h); printf("terrain.raw: %dx%d\n", w, h);
@ -203,6 +310,7 @@ for (uint ii=0;ii<g_TexMan.m_TerrainTextures.size();ii++) {
g_Camera.m_Orientation.RotateY(DEGTORAD(-45)); g_Camera.m_Orientation.RotateY(DEGTORAD(-45));
g_Camera.m_Orientation.Translate (100, 150, -100); g_Camera.m_Orientation.Translate (100, 150, -100);
} }
void InitResources() void InitResources()