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: