diff --git a/binaries/data/mods/official/entities/template_entity.xml b/binaries/data/mods/official/entities/template_entity.xml
index dd2ac14500..cf72780c72 100755
--- a/binaries/data/mods/official/entities/template_entity.xml
+++ b/binaries/data/mods/official/entities/template_entity.xml
@@ -52,10 +52,17 @@
-1.0
+
6
.2
+
+
+ 1.0
+ 0.0
+
+
7
.1
diff --git a/binaries/data/mods/official/entities/template_entity_script.js b/binaries/data/mods/official/entities/template_entity_script.js
index ec7399321d..8b44525ace 100644
--- a/binaries/data/mods/official/entities/template_entity_script.js
+++ b/binaries/data/mods/official/entities/template_entity_script.js
@@ -377,7 +377,7 @@ function performAttack( evt )
dmg.pierce = parseInt(a.damage * a.pierce);
}
- // Add flank bonus
+ // Add flank penalty
if(evt.target.traits.flank_penalty)
{
var flank = (evt.target.getAttackDirections()-1)*evt.target.traits.flank_penalty.value;
@@ -403,7 +403,13 @@ function performAttackRanged( evt )
dmg.hack = parseInt(a.damage * a.hack);
dmg.pierce = parseInt(a.damage * a.pierce);
- // Add flank bonus
+ // Add flank penalty and elevation bonus
+ var elevationBonus = (this.getHeight() - evt.target.getHeight())/this.traits.elevation.rate * this.traits.elevation.value;
+
+ dmg.crush += dmg.crush * elevationBonus;
+ dmg.hack += dmg.hack * elevationBonus;
+ dmg.pierce += dmg.pierce * elevationBonus;
+ console.write( dmg.crush + "|" + dmg.hack );
if(evt.target.traits.flank_penalty)
{
var flank = (evt.target.getAttackDirections()-1)*evt.target.traits.flank_penalty.value;
diff --git a/source/graphics/Sprite.cpp b/source/graphics/Sprite.cpp
index cac085a59b..c32d1fb815 100644
--- a/source/graphics/Sprite.cpp
+++ b/source/graphics/Sprite.cpp
@@ -54,14 +54,14 @@ CSprite::~CSprite()
void CSprite::Render()
{
- BeginBillboard();
-
- glDisable(GL_CULL_FACE);
-
+ glPushMatrix();
glTranslatef(m_translation.X, m_translation.Y, m_translation.Z);
glScalef(m_scale.X, m_scale.Y, m_scale.Z);
+ BeginBillboard();
+ glDisable(GL_CULL_FACE);
- ogl_tex_bind(m_texture->GetHandle());
+ if ( m_texture->GetHandle() != 0 )
+ ogl_tex_bind(m_texture->GetHandle());
glColor4fv(m_colour);
@@ -187,7 +187,7 @@ void CSprite::SetColour(float * colour)
m_colour[3] = colour[3];
}
-// should be called before any other gl calls
+//Must call glPushMatrix() before this. Should be called before any other gl calls
void CSprite::BeginBillboard()
{
float newMatrix[16] = { 1.0f, 0.0f, 0.0f, 0.0f,
@@ -207,7 +207,6 @@ void CSprite::BeginBillboard()
newMatrix[9] = currentMatrix[6];
newMatrix[10] = currentMatrix[10];
- glPushMatrix();
glMultMatrixf(newMatrix);
}
diff --git a/source/ps/Game.cpp b/source/ps/Game.cpp
index dc1bf215c8..8b58e35361 100644
--- a/source/ps/Game.cpp
+++ b/source/ps/Game.cpp
@@ -38,7 +38,8 @@ CGame::CGame():
m_pLocalPlayer(NULL),
m_GameStarted(false),
m_Paused(false),
- m_Time(0)
+ m_Time(0),
+ m_SimRate(1.0f)
{
debug_printf("CGame::CGame(): Game object CREATED; initializing..\n");
}
@@ -139,9 +140,9 @@ void CGame::Update(double deltaTime)
{
return;
}
-
+ deltaTime *= m_SimRate;
m_Time += deltaTime;
-
+
m_Simulation->Update(deltaTime);
// TODO Detect game over and bring up the summary screen or something
diff --git a/source/ps/Game.h b/source/ps/Game.h
index ad397fc758..44aa5ec901 100644
--- a/source/ps/Game.h
+++ b/source/ps/Game.h
@@ -2,7 +2,7 @@
#define _ps_Game_H
#include "ps/Errors.h"
-
+#include "maths/MathUtil.h"
#include
class CWorld;
@@ -29,6 +29,7 @@ class CGame
bool m_GameStarted;
float m_Time;
+ float m_SimRate;
enum EOG
{
@@ -92,6 +93,11 @@ public:
inline float GetTime()
{ return m_Time; }
+ inline void SetSimRate(float simRate)
+ { m_SimRate=clamp(simRate, 0.0f, simRate); }
+ inline float GetSimRate()
+ { return m_SimRate; }
+
private:
PSRETURN RegisterInit(CGameAttributes* pAttribs);
diff --git a/source/ps/GameSetup/GameSetup.cpp b/source/ps/GameSetup/GameSetup.cpp
index fd7621d508..d2dab80a68 100644
--- a/source/ps/GameSetup/GameSetup.cpp
+++ b/source/ps/GameSetup/GameSetup.cpp
@@ -345,8 +345,9 @@ void Render()
PROFILE_START( "render health bars" );
pglActiveTextureARB(GL_TEXTURE1_ARB);
glDisable(GL_TEXTURE_2D);
- pglActiveTextureARB(GL_TEXTURE2_ARB);
- glDisable(GL_TEXTURE_2D);
+ //Not all hardware supports 3 texture units!
+ //pglActiveTextureARB(GL_TEXTURE2_ARB);
+ //glDisable(GL_TEXTURE_2D);
pglActiveTextureARB(GL_TEXTURE0_ARB);
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
diff --git a/source/ps/Hotkey.cpp b/source/ps/Hotkey.cpp
index 0e7de0c362..3159462828 100644
--- a/source/ps/Hotkey.cpp
+++ b/source/ps/Hotkey.cpp
@@ -140,7 +140,9 @@ static SHotkeyInfo hotkeyInfo[] =
{ HOTKEY_WATER_TOGGLE, "water.toggle", SDLK_q, 0 },
{ HOTKEY_WATER_RAISE, "water.toggle", SDLK_a, 0 },
{ HOTKEY_WATER_LOWER, "water.toggle", SDLK_z, 0 },
- { HOTKEY_PAUSE, "pause", SDLK_PAUSE, 0 }
+ { HOTKEY_PAUSE, "pause", SDLK_PAUSE, 0 },
+ { HOTKEY_SPEED_INCREASE, "speed.increase", 0, 0 },
+ { HOTKEY_SPEED_DECREASE, "speed.decrease", 0, 0 }
};
/* SDL-type ends */
diff --git a/source/ps/Hotkey.h b/source/ps/Hotkey.h
index 935e63f4ab..b73078eb5f 100644
--- a/source/ps/Hotkey.h
+++ b/source/ps/Hotkey.h
@@ -104,6 +104,8 @@ enum
HOTKEY_WATER_RAISE,
HOTKEY_WATER_LOWER,
HOTKEY_PAUSE,
+ HOTKEY_SPEED_INCREASE,
+ HOTKEY_SPEED_DECREASE,
HOTKEY_LAST,
diff --git a/source/scripting/ScriptGlue.cpp b/source/scripting/ScriptGlue.cpp
index 5076e3a30a..a7336196c4 100644
--- a/source/scripting/ScriptGlue.cpp
+++ b/source/scripting/ScriptGlue.cpp
@@ -9,7 +9,6 @@
#include "ScriptGlue.h"
#include "JSConversions.h"
#include "GameEvents.h"
-
#include "graphics/GameView.h"
#include "graphics/LightEnv.h"
#include "graphics/MapWriter.h"
@@ -35,6 +34,7 @@
#include "renderer/SkyManager.h"
#include "renderer/WaterManager.h"
#include "simulation/BaseEntityCollection.h"
+#include "simulation/BaseTechCollection.h"
#include "simulation/Entity.h"
#include "simulation/EntityFormation.h"
#include "simulation/EntityHandles.h"
@@ -267,9 +267,13 @@ JSBool issueCommand( JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* rv
CreateFormationMessage(messages, msg, entities[i]);
formation->SetDuplication(true);
entities.erase( entities.begin()+i ); //we don't want to be in two orders
+ --i;
}
else if ( duplicate )
+ {
entities.erase( entities.begin()+i );
+ --i;
+ }
}
}
@@ -324,6 +328,37 @@ JSBool isFormationLocked( JSContext* cx, JSObject* UNUSED(obj), uint argc, jsval
*rval = entity->GetFormation()->IsLocked() ? JS_TRUE : JS_FALSE;
return JS_TRUE;
}
+//-----------------------------------------------------------------------------
+// Techs
+//-----------------------------------------------------------------------------
+
+JSBool getTechTemplate( JSContext* cx, JSObject* UNUSED(obj), uint argc, jsval* argv, jsval* rval )
+{
+ REQUIRE_MIN_PARAMS(2, getTechTemplate);
+
+ CStrW name = ToPrimitive( argv[0] );
+ PS_uint playerID = (PS_uint)ToPrimitive( argv[1] );
+ rval = JSVAL_NULL;
+
+ if ( g_Game->GetPlayer(playerID) )
+ {
+ //The tech will now temporarily belong to this player. This will change on the next call.
+ CBaseTech* tech = g_BaseTechCollection.getTemplate(name);
+ if ( tech )
+ {
+ tech->setPlayer( g_Game->GetPlayer(playerID) );
+ *rval = OBJECT_TO_JSVAL(tech->GetScript());
+ }
+ else
+ JS_ReportError(cx, "Invalid tech template name \"%s\" passed for getTechTemplate()", name.c_str() );
+ }
+ else
+ JS_ReportError(cx, "Invalid playerID \"%d\"passed for getTechTemplate()", playerID);
+
+ if ( rval )
+ return JS_TRUE;
+ return JS_FALSE;
+}
//-----------------------------------------------------------------------------
// Events
@@ -523,6 +558,16 @@ JSBool cancelTimer( JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* UNU
return( JS_TRUE );
}
+//Set the simulation rate scalar-time becomes time * SimRate.
+//Params: rate [float] : sets SimRate
+JSBool setSimRate(JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* UNUSED(rval))
+{
+ REQUIRE_MIN_PARAMS(1, setSimRate);
+ REQUIRE_MAX_PARAMS(1, setSimRate);
+
+ g_Game->SetSimRate( ToPrimitive(argv[0]) );
+ return JS_TRUE;
+}
//-----------------------------------------------------------------------------
@@ -1154,7 +1199,9 @@ JSFunctionSpec ScriptFunctionTable[] =
JS_FUNC(removeFromFormation, removeFromFormation, 1)
JS_FUNC(lockEntityFormation, lockEntityFormation, 1)
JS_FUNC(isFormationLocked, isFormationLocked, 1)
-
+
+ //Tech
+ JS_FUNC(getTechTemplate, getTechTemplate, 2)
// Camera
JS_FUNC(setCameraTarget, setCameraTarget, 1)
@@ -1186,6 +1233,7 @@ JSFunctionSpec ScriptFunctionTable[] =
JS_FUNC(setInterval, setInterval, 2)
JS_FUNC(cancelInterval, cancelInterval, 0)
JS_FUNC(cancelTimer, cancelTimer, 0)
+ JS_FUNC(setSimRate, setSimRate, 1)
// Game Setup
JS_FUNC(startGame, startGame, 0)
diff --git a/source/simulation/BaseEntityCollection.cpp b/source/simulation/BaseEntityCollection.cpp
index 5f044954ec..2ea048bfff 100644
--- a/source/simulation/BaseEntityCollection.cpp
+++ b/source/simulation/BaseEntityCollection.cpp
@@ -57,6 +57,7 @@ CBaseEntity* CBaseEntityCollection::getTemplate( CStrW name, CPlayer* player )
if( !newTemplate->loadXML( path ) )
{
LOG(ERROR, LOG_CATEGORY, "CBaseEntityCollection::loadTemplates(): Couldn't load template \"%s\"", path.c_str());
+ delete newTemplate;
return( NULL );
}
diff --git a/source/simulation/BaseFormationCollection.cpp b/source/simulation/BaseFormationCollection.cpp
index 53d17818de..49880e7e74 100644
--- a/source/simulation/BaseFormationCollection.cpp
+++ b/source/simulation/BaseFormationCollection.cpp
@@ -54,6 +54,7 @@ CBaseFormation* CBaseFormationCollection::getTemplate( CStrW name )
if( !newTemplate->loadXML( path ) )
{
LOG(ERROR, LOG_CATEGORY, "CBaseFormationCollection::loadTemplates(): Couldn't load template \"%s\"", path.c_str());
+ delete newTemplate;
return( NULL );
}
diff --git a/source/simulation/BaseTech.cpp b/source/simulation/BaseTech.cpp
new file mode 100644
index 0000000000..3ed71ed215
--- /dev/null
+++ b/source/simulation/BaseTech.cpp
@@ -0,0 +1,493 @@
+#include "precompiled.h"
+#include "BaseTech.h"
+#include "BaseTechCollection.h"
+#include "EntityManager.h"
+#include "ps/CStr.h"
+#include "ps/CLogger.h"
+#include "scripting/ScriptingHost.h"
+#include "ps/XML/Xeromyces.h"
+#include "ps/XML/XeroXMB.h"
+
+#define LOG_CATEGORY "Techs"
+
+STL_HASH_SET CBaseTech::m_scriptsLoaded;
+
+CBaseTech::CBaseTech()
+{
+ m_researched = m_excluded=false;
+ AddProperty(L"generic", &CBaseTech::m_Generic, true);
+ AddProperty(L"specific", &CBaseTech::m_Specific, true);
+ AddProperty(L"icon", &CBaseTech::m_Icon); //GUI might want to change this...?
+ AddProperty(L"icon_cell", &CBaseTech::m_IconCell);
+ AddProperty(L"classes", &CBaseTech::m_Classes, true);
+ AddProperty(L"history", &CBaseTech::m_History, true);
+
+ AddProperty(L"time", &CBaseTech::m_ReqTime); //Techs may upgrade research time and cost of other techs
+ AddProperty(L"food", &CBaseTech::m_ReqFood);
+ AddProperty(L"wood", &CBaseTech::m_ReqWood);
+ AddProperty(L"stone", &CBaseTech::m_ReqStone);
+ AddProperty(L"ore", &CBaseTech::m_ReqOre);
+
+ m_effectFunction = NULL;
+ m_JSFirst = false;
+
+ ONCE( ScriptingInit() );
+}
+bool CBaseTech::loadXML( CStr filename )
+{
+ CXeromyces XeroFile;
+
+ if (XeroFile.Load(filename) != PSRETURN_OK)
+ return false;
+
+ #define EL(x) int el_##x = XeroFile.getElementID(#x)
+
+ EL(tech);
+ EL(id);
+ EL(req);
+ EL(effect);
+
+ #undef EL
+
+ XMBElement Root = XeroFile.getRoot();
+ if ( Root.getNodeName() != el_tech )
+ {
+ LOG( ERROR, LOG_CATEGORY, "CBaseTech: XML root was not \"Tech\" in file %s. Load failed.", filename.c_str() );
+ return false;
+ }
+ XMBElementList RootChildren = Root.getChildNodes();
+ bool ret;
+ for ( int i=0; iSetFunction( fn );
+ }
+ else if ( Inline != CStr() )
+ m_effectFunction->Compile( CStrW( filename ) + L"::" + (CStrW)funcName + L" (" + CStrW( element.getLineNumber() ) + L")", Inline );
+ //(No error needed; scripts are optional)
+ }
+ else
+ {
+ const char* tagName = XeroFile.getElementString(name).c_str();
+ LOG( ERROR, LOG_CATEGORY, "CBaseTech: invalid tag %s for XML file", tagName );
+ return false;
+ }
+ }
+ return true;
+}
+bool CBaseTech::isTechValid()
+{
+ if ( m_excluded )
+ return false;
+ if ( hasReqEntities() && hasReqTechs() )
+ return true;
+ return false;
+}
+bool CBaseTech::hasReqEntities()
+{
+ bool ret=true;
+ std::vector* entities = m_player->GetControlledEntities();
+ for ( std::vector::iterator it=m_ReqEntities.begin(); it != m_ReqEntities.end(); it++ )
+ {
+ for( CEntityList::iterator it2=entities->begin(); it2 != entities->end(); it2++ )
+ {
+ if ( (*it2)->m_classes.IsMember(*it) )
+ {
+ ret=true;
+ break;
+ }
+ }
+ }
+ delete entities;
+ return ret;
+}
+bool CBaseTech::hasReqTechs()
+{
+ bool ret=false;
+ for ( std::vector::iterator it=m_ReqTechs.begin(); it != m_ReqTechs.end(); it++ )
+ {
+ if ( g_BaseTechCollection.getTemplate( (CStrW)*it )->isResearched() )
+ {
+ ret=true;
+ break;
+ }
+ }
+ return ret;
+}
+//JS stuff
+
+void CBaseTech::ScriptingInit()
+{
+ AddMethod( "applyEffects", 1 );
+ AddMethod( "isExcluded", 0 );
+ AddMethod( "isValid", 0 );
+ AddMethod( "isResearched", 0 );
+ AddMethod( "getPlayerID", 0 );
+ AddMethod( "isJSFirst", 0 );
+
+ CJSObject::ScriptingInit("TechTemplate");
+}
+
+jsval CBaseTech::ApplyEffects( JSContext* cx, uintN argc, jsval* argv )
+{
+ if ( !isTechValid() )
+ return JS_FALSE;
+ else if ( argc < 2 )
+ {
+ JS_ReportError(cx, "too few parameters for CBaseTech::ApplyEffects.");
+ return JS_FALSE;
+ }
+
+ //Order overriding for some special case
+ bool first = ToPrimitive( argv[0] );
+ bool invert = ToPrimitive( argv[1] );
+
+ //Optional type overriding if some in some special case the script wants to modify non-floats
+ CStr varType("float");
+ if ( argc == 3 )
+ varType = ToPrimitive( argv[2] );
+
+ if ( first )
+ m_effectFunction->Run( this->GetScript() );
+
+ //Disable other templates
+ for ( std::vector::iterator it=m_Pairs.begin(); it != m_Pairs.end(); it++ )
+ g_BaseTechCollection.getTemplate(*it)->setExclusion(true);
+
+ std::vector* entities = m_player->GetControlledEntities();
+ if ( entities->empty() )
+ {
+ delete entities;
+ return JS_FALSE;
+ }
+
+ //Find which entities should be affected
+ for ( std::vector::iterator it = m_Targets.begin(); it != m_Targets.end(); it++ )
+ {
+ for ( size_t i=0; isize(); ++i )
+ {
+ if ( !(*entities)[i]->m_classes.IsMember( *it ) )
+ entities->erase(entities->begin() + i);
+ }
+ }
+ CEntityList::iterator HEit = entities->begin();
+ for ( ; HEit != entities->end(); HEit++ )
+ {
+ for ( std::vector::iterator mod=m_Modifiers.begin(); mod!=m_Modifiers.end(); mod++ )
+ {
+ //Get the member corresponding to the javascript attribute string
+ void* attribute = (char*)&**HEit + (*HEit)->m_AttributeTable[mod->attribute];
+ float modValue = (invert ? -mod->value : mod->value);
+
+ if ( varType == "int" )
+ *(int*)attribute += (int)modValue;
+ if ( varType == "double" )
+ *(double*)attribute += (double)modValue;
+ else
+ *(float*)attribute += (float)modValue;
+ }
+ }
+ for ( HEit = entities->begin(); HEit != entities->end(); HEit++ )
+ {
+ for ( std::vector::iterator set=m_Sets.begin(); set!=m_Sets.end(); set++ )
+ {
+ //Get the member corresponding to the javascript attribute string
+ void* attribute = (char*)&**HEit + (*HEit)->m_AttributeTable[set->attribute];
+ float setValue = invert ? -set->value : set->value;
+
+ if ( varType == "int" )
+ *(int*)attribute += (int)setValue;
+ if ( varType == "double" )
+ *(double*)attribute += (double)setValue;
+ else
+ *(float*)attribute += (float)setValue;
+ }
+ }
+ if ( !first )
+ m_effectFunction->Run( this->GetScript() );
+ delete entities;
+ return JS_TRUE;
+}
+
+jsval CBaseTech::IsValid( JSContext* UNUSED(cx), uintN UNUSED(argc), jsval* UNUSED(argv) )
+{
+ if ( isTechValid() )
+ return JS_TRUE;
+ return JS_FALSE;
+}
+jsval CBaseTech::IsExcluded( JSContext* UNUSED(cx), uintN UNUSED(argc), jsval* UNUSED(argv) )
+{
+ if ( m_excluded )
+ return JS_TRUE;
+ return JS_FALSE;
+}
+jsval CBaseTech::IsResearched( JSContext* UNUSED(cx), uintN UNUSED(argc), jsval* UNUSED(argv) )
+{
+ if ( isResearched() )
+ return JS_TRUE;
+ return JS_FALSE;
+}
+inline jsval CBaseTech::GetPlayerID( JSContext* UNUSED(cx), uintN UNUSED(argc), jsval* UNUSED(argv) )
+{
+ return ToJSVal( m_player->GetPlayerID() );
+}
+jsval CBaseTech::IsJSFirst( JSContext* UNUSED(cx), uintN UNUSED(argc), jsval* UNUSED(argv) )
+{
+ if ( m_JSFirst )
+ return JS_TRUE;
+ return JS_FALSE;
+}
+
+
+
+
diff --git a/source/simulation/BaseTech.h b/source/simulation/BaseTech.h
new file mode 100644
index 0000000000..b863a66b90
--- /dev/null
+++ b/source/simulation/BaseTech.h
@@ -0,0 +1,85 @@
+//Andrew aka pyrolink
+//ajdecker1022@msn.com
+//Holds template information for technologies and research
+
+#ifndef BASETECH_INCLUDED
+#define BASETECH_INCLUDED
+
+#include
+#include "scripting/ScriptableComplex.h"
+
+class CStr;
+class XMBElement;
+class CXeromyces;
+
+class CBaseTech : public CJSObject
+{
+ friend class CBaseTechCollection;
+
+ typedef struct Modifier
+ {
+ CStr attribute;
+ float value;
+ Modifier() { value = 0; }
+ };
+ static STL_HASH_SET m_scriptsLoaded;
+
+public:
+ CBaseTech();
+ ~CBaseTech() {}
+
+ //JS functions
+ static void ScriptingInit();
+ jsval ApplyEffects( JSContext* cx, uintN argc, jsval* argv );
+ jsval IsValid( JSContext* cx, uintN argc, jsval* argv );
+ jsval IsResearched( JSContext* cx, uintN argc, jsval* argv );
+ jsval IsJSFirst( JSContext* cx, uintN argc, jsval* argv );
+ jsval IsExcluded( JSContext* cx, uintN argc, jsval* argv );
+ inline jsval GetPlayerID( JSContext* cx, uintN argc, jsval* argv );
+
+
+ bool isTechValid();
+ inline bool isResearched() { return m_researched; }
+
+ void setPlayer( CPlayer* player ) { m_player=player; }
+ void setExclusion( bool exclude ) { m_excluded=exclude; }
+
+ bool loadXML( CStr filename );
+ bool loadELID( XMBElement ID, CXeromyces& XeroFile );
+ bool loadELReq( XMBElement Req, CXeromyces& XeroFile );
+ bool loadELEffect( XMBElement Effect, CXeromyces& XeroFile, CStr& filename );
+
+private:
+ CStr m_Generic;
+ CStr m_Specific;
+
+ CStr m_Icon;
+ int m_IconCell;
+ CStr m_Classes;
+ CStr m_History;
+
+ float m_ReqTime;
+ float m_ReqWood;
+ float m_ReqFood;
+ float m_ReqStone;
+ float m_ReqOre;
+
+ std::vector m_ReqEntities;
+ std::vector m_ReqTechs;
+ std::vector m_Pairs;
+ std::vector m_Targets;
+ std::vector m_Modifiers;
+ std::vector m_Sets;
+
+ CPlayer* m_player; //Which player this tech belongs to
+ CScriptObject* m_effectFunction;
+
+ bool m_JSFirst; //Should JS effect function run before C++
+ bool m_excluded;
+ bool m_researched;
+
+ bool hasReqEntities();
+ bool hasReqTechs();
+};
+
+#endif
\ No newline at end of file
diff --git a/source/simulation/BaseTechCollection.cpp b/source/simulation/BaseTechCollection.cpp
new file mode 100644
index 0000000000..49b1291067
--- /dev/null
+++ b/source/simulation/BaseTechCollection.cpp
@@ -0,0 +1,71 @@
+#include "precompiled.h"
+
+#include "BaseTechCollection.h"
+#include "ps/CLogger.h"
+#include "ps/VFSUtil.h"
+
+#define LOG_CATEGORY "tech"
+
+void CBaseTechCollection::LoadFile( const char* path )
+{
+ //Make tech file reading
+ CStrW tag = CStr(path).AfterLast("/").BeforeLast(".xml");
+ m_templateFilenames[tag] = path;
+}
+
+static void LoadTechThunk( const char* path, const DirEnt* UNUSED(ent), void* context )
+{
+ CBaseTechCollection* this_ = (CBaseTechCollection*)context;
+ this_->LoadFile(path);
+}
+
+int CBaseTechCollection::loadTemplates()
+{
+ // Load all files in techs/ and subdirectories.
+ THROW_ERR( vfs_dir_enum( "techs/", VFS_DIR_RECURSIVE, "*.xml",
+ LoadTechThunk, this ) );
+ return 0;
+}
+
+CBaseTech* CBaseTechCollection::getTemplate( CStrW name )
+{
+ // Check whether this template has already been loaded.
+ //If previously loaded, all slots will be found, so any entry works.
+ templateMap::iterator it = m_templates.find( name );
+ if( it != m_templates.end() )
+ return( it->second );
+
+ // Find the filename corresponding to this template
+ templateFilenameMap::iterator filename_it = m_templateFilenames.find( name );
+ if( filename_it == m_templateFilenames.end() )
+ return( NULL );
+
+ CStr path( filename_it->second );
+
+ //Try to load to the tech
+ CBaseTech* newTemplate = new CBaseTech();
+ if( !newTemplate->loadXML( path ) )
+ {
+ LOG(ERROR, LOG_CATEGORY, "CBaseTechCollection::loadTemplates(): Couldn't load template \"%s\"", path.c_str());
+ delete newTemplate;
+ return( NULL );
+
+ }
+ m_templates[name] = newTemplate;
+
+ LOG(NORMAL, LOG_CATEGORY, "CBaseTechCollection::loadTemplates(): Loaded template \"%s\"", path.c_str());
+ return newTemplate;
+}
+
+void CBaseTechCollection::getBaseTechNames( std::vector& names )
+{
+ for( templateFilenameMap::iterator it = m_templateFilenames.begin(); it != m_templateFilenames.end(); ++it )
+ if( ! (it->first.Length() > 8 && it->first.Left(8) == L"template"))
+ names.push_back( it->first );
+}
+
+CBaseTechCollection::~CBaseTechCollection()
+{
+ for( templateMap::iterator it = m_templates.begin(); it != m_templates.end(); ++it )
+ delete( it->second );
+}
diff --git a/source/simulation/BaseTechCollection.h b/source/simulation/BaseTechCollection.h
new file mode 100644
index 0000000000..a0e2f0fc31
--- /dev/null
+++ b/source/simulation/BaseTechCollection.h
@@ -0,0 +1,34 @@
+//Andrew aka pyrolink - ajdecker1022@msn.com
+//Manages the tech templates. More detail: see CBaseFormation and CBaseEntity (collections)
+
+
+#ifndef BASETECH_COLLECTION_INCLUDED
+#define BASETECH_COLLECTION_INCLUDED
+
+#include
+#include "ps/CStr.h"
+#include "ps/Singleton.h"
+#include "BaseTech.h"
+#include "ps/Game.h"
+
+#define g_BaseTechCollection CBaseTechCollection::GetSingleton()
+
+class CBaseTechCollection : public Singleton
+{
+
+ typedef std::map templateMap;
+ typedef std::map templateFilenameMap;
+ templateMap m_templates;
+ templateFilenameMap m_templateFilenames;
+public:
+ ~CBaseTechCollection();
+ CBaseTech* getTemplate( CStrW techType );
+ int loadTemplates();
+ void LoadFile( const char* path );
+
+ // Create a list of the names of all base techs, excluding template_*,
+ // for display in ScEd's entity-selection box.
+ void getBaseTechNames( std::vector& names );
+};
+
+#endif
diff --git a/source/simulation/Entity.cpp b/source/simulation/Entity.cpp
index 84bd35c384..6be5401697 100644
--- a/source/simulation/Entity.cpp
+++ b/source/simulation/Entity.cpp
@@ -32,6 +32,7 @@ extern int g_xres, g_yres;
#include
using namespace std;
+std::map CEntity::m_AttributeTable;
CEntity::CEntity( CBaseEntity* base, CVector3D position, float orientation, const std::set& actorSelections, CStrW building )
{
@@ -233,6 +234,61 @@ void CEntity::loadBase()
}
}
+void CEntity::initAttributes(const CEntity* _this)
+{
+#define getoffset(member) \
+ (size_t) ((unsigned char*)&_this->member - (unsigned char*)_this)
+
+#define getoffset_action(member, mem2) \
+ (size_t) ((unsigned char*)&_this->member.mem2 - (unsigned char*)_this)
+
+ //Add the attribute name and the variable that holds it
+ CEntity::m_AttributeTable["actions.move.speed_curr"] = getoffset(m_speed);
+ CEntity::m_AttributeTable["actions.move.run.speed"] = getoffset(m_runSpeed);
+ CEntity::m_AttributeTable["actions.move.run.rangemin"] = getoffset_action(m_run, m_MinRange);
+ CEntity::m_AttributeTable["actions.move.run.range"] = getoffset_action(m_run, m_MaxRange);
+ CEntity::m_AttributeTable["actions.move.run.regen_rate"] = getoffset(m_runRegenRate);
+ CEntity::m_AttributeTable["actions.move.run.decay_rate"] = getoffset(m_runDecayRate);
+ CEntity::m_AttributeTable["actions.move.pass_through_allies"] = getoffset(m_passThroughAllies);
+ CEntity::m_AttributeTable["traits.extant"] = getoffset(m_extant);
+ CEntity::m_AttributeTable["traits.corpse"] = getoffset(m_corpse);
+ CEntity::m_AttributeTable["actions.move.turningradius"] = getoffset(m_turningRadius);
+
+ CEntity::m_AttributeTable["traits.health.curr"] = getoffset(m_healthCurr);
+ CEntity::m_AttributeTable["traits.health.max"] = getoffset(m_healthMax);
+ CEntity::m_AttributeTable["traits.health.regen_rate"] = getoffset(m_healthRegenRate);
+ CEntity::m_AttributeTable["traits.health.regen_start"] = getoffset(m_healthRegenStart);
+ CEntity::m_AttributeTable["traits.health.decay_rate"] = getoffset(m_healthDecayRate);
+ //This are not changable from techs until the updated bars are finished
+
+ /* CEntity::m_AttributeTable["traits.stamina.curr"] = getoffset(m_staminaCurr);
+ CEntity::m_AttributeTable["traits.stamina.max"] = getoffset(m_staminaMax);
+ CEntity::m_AttributeTable["traits.bars.height"] = getoffset(m_barHeight);
+ CEntity::m_AttributeTable["traits.bars"] = getoffset(m_barOffset);
+ CEntity::m_AttributeTable["traits.bars.width"] = getoffset(m_barWidth);
+ CEntity::m_AttributeTable["traits.bars.border_height"] = getoffset(m_barBorderHeight);
+ CEntity::m_AttributeTable["traits.bars.border_width"] = getoffset(m_barBorderWidth);
+ CEntity::m_AttributeTable["traits.bars.border_name"] = getoffset(m_barBorderName);*/
+ CEntity::m_AttributeTable["traits.flank_penalty.sectors"] = getoffset(m_sectorDivs);
+ CEntity::m_AttributeTable["traits.pitch.sectors"] = getoffset(m_pitchDivs);
+ CEntity::m_AttributeTable["traits.rank.width"] = getoffset(m_rankWidth);
+// CEntity::m_AttributeTable["traits.rank"] = getoffset(m_rankOffset);
+ CEntity::m_AttributeTable["traits.rank.height"] = getoffset(m_rankHeight);
+ CEntity::m_AttributeTable["traits.rank.name"] = getoffset(m_rankName);
+ CEntity::m_AttributeTable["traits.minimap.type"] = getoffset(m_minimapType);
+ CEntity::m_AttributeTable["traits.minimap.red"] = getoffset(m_minimapR);
+ CEntity::m_AttributeTable["traits.minimap.green"] = getoffset(m_minimapG);
+ CEntity::m_AttributeTable["traits.minimap.blue"] = getoffset(m_minimapB);
+ CEntity::m_AttributeTable["traits.anchor.type"] = getoffset(m_anchorType);
+ CEntity::m_AttributeTable["traits.anchor.conformx"] = getoffset(m_anchorConformX);
+ CEntity::m_AttributeTable["traits.anchor.conformz"] = getoffset(m_anchorConformZ);
+ CEntity::m_AttributeTable["traits.vision.los"] = getoffset(m_los);
+ CEntity::m_AttributeTable["traits.vision.permanent"] = getoffset(m_permanent);
+ CEntity::m_AttributeTable["last_combat_time"] = getoffset(m_lastCombatTime);
+ CEntity::m_AttributeTable["last_run_time"] = getoffset(m_lastRunTime);
+ CEntity::m_AttributeTable["building"] = getoffset(m_building);
+#undef getoffset
+}
void CEntity::kill()
{
g_Selection.removeAll( me );
@@ -1386,6 +1442,7 @@ void CEntity::ScriptingInit()
AddMethod( "registerOrderChange", 0 );
AddMethod( "getAttackDirections", 0 );
AddMethod("findSector", 4);
+ AddMethod("getHeight", 0 );
AddClassProperty( L"template", (CBaseEntity* CEntity::*)&CEntity::m_base, false, (NotifyFn)&CEntity::loadBase );
AddClassProperty( L"traits.id.classes", (GetFn)&CEntity::getClassSet, (SetFn)&CEntity::setClassSet );
diff --git a/source/simulation/Entity.h b/source/simulation/Entity.h
index 39f6a4a739..4e126c0f0a 100644
--- a/source/simulation/Entity.h
+++ b/source/simulation/Entity.h
@@ -65,6 +65,9 @@ public:
// Intrinsic properties
CBaseEntity* m_base;
+ //Attributes table: key=attribute, value=variable name
+ static std::map m_AttributeTable;
+
// The entity to switch to when this dies.
CStrW m_corpse;
@@ -90,7 +93,7 @@ public:
float m_healthDecayRate;
SEntityAction m_run;
-
+
ActionTable m_actions;
bool m_selected;
@@ -306,6 +309,7 @@ public:
// Reset properties after the entity-template we use changes.
void loadBase();
+ static void initAttributes(const CEntity* _this);
void playerChanged(); // Fixes player colour if player is changed by script
void reorient(); // Orientation
@@ -404,7 +408,10 @@ public:
m_orderQueue.pop_front();
return JSVAL_VOID;
}
-
+ jsval GetHeight( JSContext* UNUSED(cx), uintN UNUSED(argc), jsval* UNUSED(argv) )
+ {
+ return ToJSVal(m_position.Y);
+ }
static void ScriptingInit();
private: