diff --git a/source/ps/Game.h b/source/ps/Game.h index 44aa5ec901..08adfe3066 100644 --- a/source/ps/Game.h +++ b/source/ps/Game.h @@ -14,7 +14,7 @@ class CGameAttributes; // Default player limit (not counting the Gaia player) // This may be overridden by system.cfg ("max_players") -#define PS_MAX_PLAYERS 6 +#define PS_MAX_PLAYERS 8 class CGame { diff --git a/source/ps/World.cpp b/source/ps/World.cpp index 88bf13d02e..738825396c 100644 --- a/source/ps/World.cpp +++ b/source/ps/World.cpp @@ -44,7 +44,7 @@ CWorld::CWorld(CGame *pGame): void CWorld::Initialize(CGameAttributes *pAttribs) { // TODO: Find a better way of handling these global things - ONCE(RegMemFun(CEntityTemplateCollection::GetSingletonPtr(), &CEntityTemplateCollection::loadTemplates, L"LoadTemplates", 15)); + ONCE(RegMemFun(CEntityTemplateCollection::GetSingletonPtr(), &CEntityTemplateCollection::loadTemplates, L"loadTemplates", 15)); // Load the map, if one was specified if (pAttribs->m_MapFile.Length()) diff --git a/source/scripting/ScriptGlue.cpp b/source/scripting/ScriptGlue.cpp index ccb305b4f7..7fe3560f8b 100644 --- a/source/scripting/ScriptGlue.cpp +++ b/source/scripting/ScriptGlue.cpp @@ -345,12 +345,25 @@ JSBool isFormationLocked( JSContext* cx, JSObject* UNUSED(obj), uint argc, jsval JSBool getTechnology( JSContext* cx, JSObject* UNUSED(obj), uint argc, jsval* argv, jsval* rval ) { - REQUIRE_MIN_PARAMS(1, getTechnology); + REQUIRE_MIN_PARAMS(2, getTechnology); - CStrW name = ToPrimitive( argv[0] ); + CStrW name; + CPlayer* player; + + try + { + name = g_ScriptingHost.ValueToUCString( argv[0] ); + player = ToNative( argv[1] ); + } + catch( PSERROR_Scripting_ConversionFailed ) + { + JS_ReportError( cx, "Invalid parameters for getTechnology (expected name and player)" ); + return( JS_TRUE ); + } + *rval = JSVAL_NULL; - CTechnology* tech = g_TechnologyCollection.getTechnology( name ); + CTechnology* tech = g_TechnologyCollection.getTechnology( name, player ); if ( tech ) *rval = ToJSVal( tech ); else diff --git a/source/scripting/ScriptableComplex.h b/source/scripting/ScriptableComplex.h index eccc8482e8..5f294078db 100644 --- a/source/scripting/ScriptableComplex.h +++ b/source/scripting/ScriptableComplex.h @@ -521,7 +521,8 @@ public: WatchNotify( cx, PropertyName, vp ); prop->Set( cx, this, *vp ); - prop->m_Inherited = false; + if(!prop->m_Intrinsic) + prop->m_Inherited = false; // If it's a C++ property, reflect this change in objects that inherit this. if( prop->m_AllowsInheritance && prop->m_Intrinsic ) diff --git a/source/simulation/Entity.cpp b/source/simulation/Entity.cpp index e0be201937..6852743939 100644 --- a/source/simulation/Entity.cpp +++ b/source/simulation/Entity.cpp @@ -40,9 +40,13 @@ CEntity::CEntity( CEntityTemplate* base, CVector3D position, float orientation, ent_flags = 0; m_position = position; + m_orientation.X = 0; m_orientation.Y = orientation; + m_orientation.Z = 0; m_ahead.x = sin( m_orientation.Y ); m_ahead.y = cos( m_orientation.Y ); + m_position_previous = m_position; + m_orientation_previous = m_orientation; m_player = 0; m_productionQueue = new CProductionQueue( this ); @@ -71,9 +75,6 @@ CEntity::CEntity( CEntityTemplate* base, CVector3D position, float orientation, if( m_bounds ) m_bounds->setPosition( m_position.X, m_position.Z ); - m_position_previous = m_position; - m_orientation_previous = m_orientation; - m_graphics_position = m_position; m_graphics_orientation = m_orientation; m_actor_transform_valid = false; @@ -107,6 +108,8 @@ CEntity::CEntity( CEntityTemplate* base, CVector3D position, float orientation, m_associatedTerritory = 0; m_player = g_Game->GetPlayer( 0 ); + + debug_printf("traits.health.max = %f\n", m_healthMax); } CEntity::~CEntity() diff --git a/source/simulation/EntityTemplate.cpp b/source/simulation/EntityTemplate.cpp index 88f5454638..11317b784e 100644 --- a/source/simulation/EntityTemplate.cpp +++ b/source/simulation/EntityTemplate.cpp @@ -46,6 +46,11 @@ CEntityTemplate::CEntityTemplate( CPlayer* player ) m_bound_type = CBoundingObject::BOUND_NONE; m_bound_circle = NULL; m_bound_box = NULL; + + // If these aren't set, we can get an infinite loop in CEntity::interpolate, which is nasty; they + // should be set in template_entity, but do this in case some entity forgets to inherit from that + m_anchorConformX = 0; + m_anchorConformZ = 0; } CEntityTemplate::~CEntityTemplate() diff --git a/source/simulation/EntityTemplateCollection.cpp b/source/simulation/EntityTemplateCollection.cpp index 20df488a8f..bfd62f5db1 100644 --- a/source/simulation/EntityTemplateCollection.cpp +++ b/source/simulation/EntityTemplateCollection.cpp @@ -6,6 +6,7 @@ #include "ps/CLogger.h" #include "ps/VFSUtil.h" #include "ps/Player.h" +#include "ps/Game.h" #define LOG_CATEGORY "entity" @@ -29,9 +30,24 @@ static void LoadFileThunk( const char* path, const DirEnt* UNUSED(ent), void* co int CEntityTemplateCollection::loadTemplates() { - // Load all files in entities/ and its subdirectories. + // List all files in entities/ and its subdirectories. THROW_ERR( vfs_dir_enum( "entities/", VFS_DIR_RECURSIVE, "*.xml", LoadFileThunk, this ) ); + + /*// Load all the templates; this is necessary so that we can apply techs to them + // (otherwise a tech can't affect the template of a unit that doesn't yet exist) + for( TemplateFilenameMap::iterator it = m_templateFilenames.begin(); it != m_templateFilenames.end(); ++it ) + { + // Load the no-player version of this template (used by techs for base values) + getTemplate( it->first, 0 ); + + for( uint i=0; i<=g_Game->GetNumPlayers(); i++ ) + { + // TODO: Load the template just once and clone it to get these player templates + getTemplate( it->first, g_Game->GetPlayer(i) ); + } + }*/ + return 0; } @@ -41,12 +57,12 @@ CEntityTemplate* CEntityTemplateCollection::getTemplate( CStrW name, CPlayer* pl int id = ( player == 0 ? NULL_PLAYER : player->GetPlayerID() ); // Check whether this template has already been loaded - templateMap::iterator it = m_templates[id].find( name ); + TemplateMap::iterator it = m_templates[id].find( name ); if( it != m_templates[id].end() ) return( it->second ); // Find the filename corresponding to this template - templateFilenameMap::iterator filename_it = m_templateFilenames.find( name ); + TemplateFilenameMap::iterator filename_it = m_templateFilenames.find( name ); if( filename_it == m_templateFilenames.end() ) return( NULL ); @@ -69,14 +85,24 @@ CEntityTemplate* CEntityTemplateCollection::getTemplate( CStrW name, CPlayer* pl void CEntityTemplateCollection::getEntityTemplateNames( std::vector& names ) { - for( templateFilenameMap::iterator it = m_templateFilenames.begin(); it != m_templateFilenames.end(); ++it ) + 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 ); } +void CEntityTemplateCollection::getPlayerTemplates( CPlayer* player, std::vector& dest ) +{ + int id = ( player == 0 ? NULL_PLAYER : player->GetPlayerID() ); + + for( TemplateMap::iterator it = m_templates[id].begin(); it != m_templates[id].end(); ++it ) + { + dest.push_back( it->second ); + } +} + CEntityTemplateCollection::~CEntityTemplateCollection() { for( int id = 0; id < PS_MAX_PLAYERS + 2; id++ ) - for( templateMap::iterator it = m_templates[id].begin(); it != m_templates[id].end(); ++it ) + for( TemplateMap::iterator it = m_templates[id].begin(); it != m_templates[id].end(); ++it ) delete( it->second ); } diff --git a/source/simulation/EntityTemplateCollection.h b/source/simulation/EntityTemplateCollection.h index f20bfbc02e..75a7ecd123 100644 --- a/source/simulation/EntityTemplateCollection.h +++ b/source/simulation/EntityTemplateCollection.h @@ -25,26 +25,32 @@ #include "ps/Game.h" #define g_EntityTemplateCollection CEntityTemplateCollection::GetSingleton() -#define NULL_PLAYER (PS_MAX_PLAYERS+1) class CPlayer; class CEntityTemplateCollection : public Singleton { - typedef STL_HASH_MAP templateMap; - typedef STL_HASH_MAP templateFilenameMap; + static const uint NULL_PLAYER = (PS_MAX_PLAYERS+1); + + typedef STL_HASH_MAP TemplateMap; + typedef STL_HASH_MAP TemplateFilenameMap; - templateMap m_templates[PS_MAX_PLAYERS + 2]; - templateFilenameMap m_templateFilenames; + TemplateMap m_templates[PS_MAX_PLAYERS + 2]; + TemplateFilenameMap m_templateFilenames; public: ~CEntityTemplateCollection(); CEntityTemplate* getTemplate( CStrW entityType, CPlayer* player = 0 ); + + // Load list of template filenames int loadTemplates(); void LoadFile( const char* path ); // Create a list of the names of all base entities, excluding template_*, // for display in ScEd's entity-selection box. void getEntityTemplateNames( std::vector& names ); + + // Get all the templates owned by a specific player, which is useful for techs + void getPlayerTemplates( CPlayer* player, std::vector& dest ); }; #endif diff --git a/source/simulation/Simulation.cpp b/source/simulation/Simulation.cpp index 06c29d2aaa..751d1a55b1 100644 --- a/source/simulation/Simulation.cpp +++ b/source/simulation/Simulation.cpp @@ -27,6 +27,7 @@ #include "simulation/Entity.h" #include "simulation/LOSManager.h" #include "simulation/TerritoryManager.h" +#include "simulation/EntityTemplateCollection.h" #include "gui/CGUI.h" diff --git a/source/simulation/Technology.cpp b/source/simulation/Technology.cpp index 5f9f577130..7c11a0be5b 100644 --- a/source/simulation/Technology.cpp +++ b/source/simulation/Technology.cpp @@ -7,22 +7,21 @@ #include "scripting/ScriptingHost.h" #include "ps/XML/Xeromyces.h" #include "ps/XML/XeroXMB.h" -#include "EntityTemplate.h" #include "Entity.h" +#include "EntityTemplate.h" +#include "EntityTemplateCollection.h" #include "ps/Player.h" #define LOG_CATEGORY "Techs" STL_HASH_SET CTechnology::m_scriptsLoaded; -bool CTechnology::m_excluded[PS_MAX_PLAYERS+1]; -CTechnology::CTechnology() +CTechnology::CTechnology( CPlayer* player ) : m_player(player) { ONCE( ScriptingInit(); ); m_researched=false; - for ( PS_uint i=0; iGetPlayerID()]) + if ( m_excluded ) return false; if ( hasReqEntities() && hasReqTechs() ) return true; @@ -332,7 +331,7 @@ bool CTechnology::hasReqTechs() bool ret=true; for ( std::vector::iterator it=m_ReqTechs.begin(); it != m_ReqTechs.end(); it++ ) { - if ( !g_TechnologyCollection.getTechnology( (CStrW)*it )->isResearched() ) + if ( !g_TechnologyCollection.getTechnology( (CStrW)*it, m_player )->isResearched() ) { ret=false; break; @@ -357,7 +356,7 @@ void CTechnology::ScriptingInit() AddProperty(L"stone", &CTechnology::m_ReqStone); AddProperty(L"ore", &CTechnology::m_ReqOre); - AddMethod( "applyEffects", 1 ); + AddMethod( "applyEffects", 2 ); AddMethod( "isExcluded", 0 ); AddMethod( "isValid", 0 ); AddMethod( "isResearched", 0 ); @@ -371,47 +370,30 @@ void CTechnology::ScriptingInit() jsval CTechnology::ApplyEffects( JSContext* cx, uintN argc, jsval* argv ) { - if ( argc < 3 ) + if ( argc < 2 ) { JS_ReportError(cx, "too few parameters for CTechnology::ApplyEffects."); return JS_FALSE; } - m_player = g_Game->GetPlayer( ToPrimitive( argv[0] ) ); - if( !m_player ) - { - JS_ReportError(cx, "invalid player number for CTechnology::ApplyEffects."); - return JS_FALSE; - } if ( !isTechValid() ) return JS_FALSE; - bool first = ToPrimitive( argv[1] ); - bool invert = ToPrimitive( argv[2] ); - - //Optional type overriding if some in some special case the script wants to modify non-floats - CStr varType("float"); - if ( argc == 4 ) - varType = ToPrimitive( argv[3] ); + bool first = ToPrimitive( argv[0] ); + bool invert = ToPrimitive( argv[1] ); if ( first ) { m_effectFunction.Run( this->GetScript() ); } - //Disable other templates + // Disable any paired techs for ( std::vector::iterator it=m_Pairs.begin(); it != m_Pairs.end(); it++ ) - g_TechnologyCollection.getTechnology(*it)->setExclusion(m_player->GetPlayerID(), true); - setExclusion(m_player->GetPlayerID(), true); + g_TechnologyCollection.getTechnology(*it, m_player)->setExclusion(true); + setExclusion(true); + // Get the entities that should be affected std::vector* entities = m_player->GetControlledEntities(); - if ( entities->empty() ) - { - delete entities; - return JS_FALSE; - } - std::vector entitiesAffected; - //Find which entities should be affected for ( size_t i=0; isize(); ++i ) { for ( std::vector::iterator it = m_Targets.begin(); it != m_Targets.end(); it++ ) @@ -423,15 +405,17 @@ jsval CTechnology::ApplyEffects( JSContext* cx, uintN argc, jsval* argv ) } } } + delete entities; - std::vector::iterator HEit = entitiesAffected.begin(); - for ( ; HEit != entitiesAffected.end(); HEit++ ) + std::vector::iterator entIt; + + for ( std::vector::iterator mod=m_Modifiers.begin(); mod!=m_Modifiers.end(); mod++ ) { - for ( std::vector::iterator mod=m_Modifiers.begin(); mod!=m_Modifiers.end(); mod++ ) - { - CEntity* ent = *HEit; - float modValue = (invert ? -mod->value : mod->value); + float modValue = (invert ? -mod->value : mod->value); + for ( entIt = entitiesAffected.begin(); entIt != entitiesAffected.end(); entIt++ ) + { + CEntity* ent = *entIt; jsval oldVal; if( ent->GetProperty( g_ScriptingHost.getContext(), mod->attribute, &oldVal ) ) { @@ -443,11 +427,11 @@ jsval CTechnology::ApplyEffects( JSContext* cx, uintN argc, jsval* argv ) if( !invert ) // can't invert Set effects, so just ignore them if invert is true { - for ( HEit = entitiesAffected.begin(); HEit != entitiesAffected.end(); HEit++ ) + for ( std::vector::iterator mod=m_Sets.begin(); mod!=m_Sets.end(); mod++ ) { - for ( std::vector::iterator mod=m_Sets.begin(); mod!=m_Sets.end(); mod++ ) + for ( entIt = entitiesAffected.begin(); entIt != entitiesAffected.end(); entIt++ ) { - CEntity* ent = *HEit; + CEntity* ent = *entIt; jsval newVal = ToJSVal( mod->value ); ent->SetProperty( g_ScriptingHost.GetContext(), mod->attribute, &newVal ); } @@ -458,7 +442,6 @@ jsval CTechnology::ApplyEffects( JSContext* cx, uintN argc, jsval* argv ) { m_effectFunction.Run( this->GetScript() ); } - delete entities; return JS_TRUE; } @@ -471,7 +454,7 @@ jsval CTechnology::IsValid( JSContext* UNUSED(cx), uintN UNUSED(argc), jsval* UN jsval CTechnology::IsExcluded( JSContext* UNUSED(cx), uintN UNUSED(argc), jsval* UNUSED(argv) ) { - if ( m_excluded[m_player->GetPlayerID()] ) + if ( m_excluded ) return JS_TRUE; return JS_FALSE; } diff --git a/source/simulation/Technology.h b/source/simulation/Technology.h index 6599c3335d..1a6f86037f 100644 --- a/source/simulation/Technology.h +++ b/source/simulation/Technology.h @@ -26,7 +26,7 @@ class CTechnology : public CJSObject static STL_HASH_SET m_scriptsLoaded; public: - CTechnology(); + CTechnology(CPlayer* player); ~CTechnology() {} //JS functions @@ -41,8 +41,7 @@ public: bool isTechValid(); inline bool isResearched() { return m_researched; } - void setPlayer( CPlayer* player ) { m_player=player; } - void setExclusion( PS_uint player, bool exclude ) { m_excluded[player]=exclude; } + void setExclusion( bool exclude ) { m_excluded=exclude; } bool loadXML( CStr filename ); bool loadELID( XMBElement ID, CXeromyces& XeroFile ); @@ -76,7 +75,7 @@ private: bool m_JSFirst; //Should JS effect function run before C++ - static bool m_excluded[PS_MAX_PLAYERS+1]; //Gaia is not counted in max_players + bool m_excluded; bool m_researched; bool hasReqEntities(); diff --git a/source/simulation/TechnologyCollection.cpp b/source/simulation/TechnologyCollection.cpp index 54b2b5435c..93df62f908 100644 --- a/source/simulation/TechnologyCollection.cpp +++ b/source/simulation/TechnologyCollection.cpp @@ -3,6 +3,7 @@ #include "TechnologyCollection.h" #include "ps/CLogger.h" #include "ps/VFSUtil.h" +#include "ps/Player.h" #define LOG_CATEGORY "tech" @@ -10,7 +11,7 @@ void CTechnologyCollection::LoadFile( const char* path ) { //Make tech file reading CStrW tag = CStr(path).AfterLast("/").BeforeLast(".xml"); - m_templateFilenames[tag] = path; + m_techFilenames[tag] = path; } static void LoadTechThunk( const char* path, const DirEnt* UNUSED(ent), void* context ) @@ -27,45 +28,43 @@ int CTechnologyCollection::loadTechnologies() return 0; } -CTechnology* CTechnologyCollection::getTechnology( CStrW name ) +CTechnology* CTechnologyCollection::getTechnology( CStrW name, CPlayer* player ) { + // Find player ID + debug_assert( player != 0 ); + int id = player->GetPlayerID(); + // 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() ) + TechMap::iterator it = m_techs[id].find( name ); + if( it != m_techs[id].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() ) + TechFilenameMap::iterator filename_it = m_techFilenames.find( name ); + if( filename_it == m_techFilenames.end() ) return( NULL ); CStr path( filename_it->second ); //Try to load to the tech - CTechnology* newTemplate = new CTechnology(); + CTechnology* newTemplate = new CTechnology( player ); if( !newTemplate->loadXML( path ) ) { - LOG(ERROR, LOG_CATEGORY, "CTechnologyCollection::getTechnology(): Couldn't load template \"%s\"", path.c_str()); + LOG(ERROR, LOG_CATEGORY, "CTechnologyCollection::getTechnology(): Couldn't load tech \"%s\"", path.c_str()); delete newTemplate; return( NULL ); } - m_templates[name] = newTemplate; + m_techs[id][name] = newTemplate; - LOG(NORMAL, LOG_CATEGORY, "CTechnologyCollection::getTechnology(): Loaded template \"%s\"", path.c_str()); + LOG(NORMAL, LOG_CATEGORY, "CTechnologyCollection::getTechnology(): Loaded tech \"%s\"", path.c_str()); return newTemplate; } -void CTechnologyCollection::getTechnologyNames( 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 ); -} - CTechnologyCollection::~CTechnologyCollection() { - for( templateMap::iterator it = m_templates.begin(); it != m_templates.end(); ++it ) - delete( it->second ); + for( uint id=0; idsecond ); } diff --git a/source/simulation/TechnologyCollection.h b/source/simulation/TechnologyCollection.h index 80db6ab908..2ad4e66ffe 100644 --- a/source/simulation/TechnologyCollection.h +++ b/source/simulation/TechnologyCollection.h @@ -15,20 +15,16 @@ class CTechnologyCollection : public Singleton { - - typedef std::map templateMap; - typedef std::map templateFilenameMap; - templateMap m_templates; - templateFilenameMap m_templateFilenames; + typedef std::map TechMap; + typedef std::map TechFilenameMap; + + TechMap m_techs[PS_MAX_PLAYERS+1]; + TechFilenameMap m_techFilenames; public: ~CTechnologyCollection(); - CTechnology* getTechnology( CStrW techType ); + CTechnology* getTechnology( CStrW techType, CPlayer* player ); int loadTechnologies(); 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 getTechnologyNames( std::vector& names ); }; #endif