#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 "BaseEntity.h" #include "Entity.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() { ONCE( ScriptingInit(); ); m_researched=false; for ( PS_uint i=0; iGetPlayerID()]) return false; if ( hasReqEntities() && hasReqTechs() ) return true; return false; } bool CTechnology::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 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() ) { 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", 1 ); 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 < 3 ) { 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] ); if ( first ) { m_effectFunction.Run( this->GetScript() ); } //Disable other templates 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); 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++ ) { if ( (*entities)[i]->m_classes.IsMember( *it ) ) { entitiesAffected.push_back( (*entities)[i] ); break; } } } std::vector::iterator HEit = entitiesAffected.begin(); for ( ; HEit != entitiesAffected.end(); HEit++ ) { for ( std::vector::iterator mod=m_Modifiers.begin(); mod!=m_Modifiers.end(); mod++ ) { //CEntity* ent = *HEit; //debug_printf("Modifying on %ls\n", ent->m_base->m_Tag.c_str() ); //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; else if ( varType == "double" ) *(double*)attribute += (double)modValue; else *(float*)attribute += (float)modValue; } } for ( HEit = entitiesAffected.begin(); HEit != entitiesAffected.end(); HEit++ ) { for ( std::vector::iterator set=m_Sets.begin(); set!=m_Sets.end(); set++ ) { //CEntity* ent = *HEit; //debug_printf("Setting on %ls\n", ent->m_base->m_Tag.c_str() ); //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; else 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 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[m_player->GetPlayerID()] ) 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; }