#include "precompiled.h" #include "Technology.h" #include "TechnologyCollection.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" #include "Entity.h" #include "EntityTemplate.h" #include "EntityTemplateCollection.h" #include "ps/Player.h" #define LOG_CATEGORY "Techs" STL_HASH_SET CTechnology::m_scriptsLoaded; CTechnology::CTechnology( CPlayer* player ) : m_player(player) { ONCE( ScriptingInit(); ); m_researched=false; m_excluded = false; m_JSFirst = false; } bool CTechnology::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, "CTechnology: 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; i* 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 CTechnology::hasReqTechs() { bool ret=true; for ( std::vector::iterator it=m_ReqTechs.begin(); it != m_ReqTechs.end(); it++ ) { if ( !g_TechnologyCollection.getTechnology( (CStrW)*it, m_player )->isResearched() ) { ret=false; break; } } return ret; } //JS stuff void CTechnology::ScriptingInit() { AddProperty(L"generic", &CTechnology::m_Generic, true); AddProperty(L"specific", &CTechnology::m_Specific, true); AddProperty(L"icon", &CTechnology::m_Icon); //GUI might want to change this...? AddProperty(L"icon_cell", &CTechnology::m_IconCell); AddProperty(L"classes", &CTechnology::m_Classes, true); AddProperty(L"history", &CTechnology::m_History, true); AddProperty(L"time", &CTechnology::m_ReqTime); //Techs may upgrade research time and cost of other techs AddProperty(L"food", &CTechnology::m_ReqFood); AddProperty(L"wood", &CTechnology::m_ReqWood); AddProperty(L"stone", &CTechnology::m_ReqStone); AddProperty(L"ore", &CTechnology::m_ReqOre); AddMethod( "applyEffects", 2 ); AddMethod( "isExcluded", 0 ); AddMethod( "isValid", 0 ); AddMethod( "isResearched", 0 ); AddMethod( "getPlayerID", 0 ); AddMethod( "isJSFirst", 0 ); CJSObject::ScriptingInit("Technology"); debug_printf("CTechnology::ScriptingInit complete"); } jsval CTechnology::ApplyEffects( JSContext* cx, uintN argc, jsval* argv ) { if ( argc < 2 ) { JS_ReportError(cx, "too few parameters for CTechnology::ApplyEffects."); return JS_FALSE; } if ( !isTechValid() ) return JS_FALSE; bool first = ToPrimitive( argv[0] ); bool invert = ToPrimitive( argv[1] ); if ( first ) { m_effectFunction.Run( this->GetScript() ); } // Disable any paired techs for ( std::vector::iterator it=m_Pairs.begin(); it != m_Pairs.end(); it++ ) g_TechnologyCollection.getTechnology(*it, m_player)->setExclusion(true); setExclusion(true); // Get the entities that should be affected std::vector* entities = m_player->GetControlledEntities(); std::vector entitiesAffected; for ( size_t i=0; isize(); ++i ) { for ( std::vector::iterator it = m_Targets.begin(); it != m_Targets.end(); it++ ) { if ( (*entities)[i]->m_classes.IsMember( *it ) ) { entitiesAffected.push_back( (*entities)[i] ); break; } } } delete entities; std::vector::iterator entIt; for ( std::vector::iterator mod=m_Modifiers.begin(); mod!=m_Modifiers.end(); mod++ ) { 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 ) ) { jsval newVal = ToJSVal( ToPrimitive(oldVal) + modValue ); ent->SetProperty( g_ScriptingHost.GetContext(), mod->attribute, &newVal ); } } } if( !invert ) // can't invert Set effects, so just ignore them if invert is true { for ( std::vector::iterator mod=m_Sets.begin(); mod!=m_Sets.end(); mod++ ) { for ( entIt = entitiesAffected.begin(); entIt != entitiesAffected.end(); entIt++ ) { CEntity* ent = *entIt; jsval newVal = ToJSVal( mod->value ); ent->SetProperty( g_ScriptingHost.GetContext(), mod->attribute, &newVal ); } } } if ( !first ) { m_effectFunction.Run( this->GetScript() ); } return JS_TRUE; } jsval CTechnology::IsValid( JSContext* UNUSED(cx), uintN UNUSED(argc), jsval* UNUSED(argv) ) { if ( isTechValid() ) return JS_TRUE; return JS_FALSE; } jsval CTechnology::IsExcluded( JSContext* UNUSED(cx), uintN UNUSED(argc), jsval* UNUSED(argv) ) { if ( m_excluded ) return JS_TRUE; return JS_FALSE; } jsval CTechnology::IsResearched( JSContext* UNUSED(cx), uintN UNUSED(argc), jsval* UNUSED(argv) ) { if ( isResearched() ) return JS_TRUE; return JS_FALSE; } inline jsval CTechnology::GetPlayerID( JSContext* UNUSED(cx), uintN UNUSED(argc), jsval* UNUSED(argv) ) { return ToJSVal( m_player->GetPlayerID() ); } jsval CTechnology::IsJSFirst( JSContext* UNUSED(cx), uintN UNUSED(argc), jsval* UNUSED(argv) ) { if ( m_JSFirst ) return JS_TRUE; return JS_FALSE; }