# More work on technologies.

Techs will now apply to units created after they are researched.

This was SVN commit r4143.
This commit is contained in:
Matei 2006-07-18 23:59:48 +00:00
parent b70e16cf2a
commit 8eae620b11
7 changed files with 86 additions and 69 deletions

View File

@ -8,6 +8,7 @@
class CNetMessage;
class HEntity;
class CTechnology;
typedef SColour SPlayerColour;
@ -26,6 +27,8 @@ private:
UpdateCallback *m_UpdateCB;
void *m_UpdateCBData;
std::vector<CTechnology*> m_ActiveTechs;
virtual void Update(CStrW name, ISynchedJSProperty *prop);
public:
@ -59,6 +62,16 @@ public:
}
void SetValue(CStrW name, CStrW value);
inline void AddActiveTech(CTechnology* tech)
{
m_ActiveTechs.push_back(tech);
}
inline const std::vector<CTechnology*>& GetActiveTechs()
{
return m_ActiveTechs;
}
// Caller frees...
std::vector<HEntity>* GetControlledEntities();

View File

@ -25,6 +25,7 @@
#include "FormationManager.h"
#include "TerritoryManager.h"
#include "Formation.h"
#include "TechnologyCollection.h"
#include "graphics/GameView.h"
#include "graphics/Sprite.h"
#include "graphics/UnitManager.h"
@ -671,6 +672,14 @@ void UpdateAuras_Normal( SAura& aura, CEntity* e )
bool CEntity::Initialize()
{
// Apply our player's active techs to ourselves (we do this here since m_player isn't yet set in the constructor)
const std::vector<CTechnology*>& techs = m_player->GetActiveTechs();
for( int i=0; i<techs.size(); i++ )
{
techs[i]->apply( this );
}
// Dispatch the initialize script event
CEventInitialize evt;
if( !DispatchEvent( &evt ) )
{

View File

@ -37,8 +37,7 @@ CEntityTemplate::CEntityTemplate( CPlayer* player )
m_sectorDivs = 4;
// Sentinel values for stamina and health (so scripts can check if an entity has no stamina or no HP).
m_speed=0;
m_staminaCurr = 0;
m_speed = 0;
m_staminaMax = 0;
m_healthMax = 0;
@ -430,7 +429,6 @@ void CEntityTemplate::ScriptingInit()
AddClassProperty( L"traits.health.regen_rate", &CEntityTemplate::m_healthRegenRate );
AddClassProperty( L"traits.health.regen_start", &CEntityTemplate::m_healthRegenStart );
AddClassProperty( L"traits.health.decay_rate", &CEntityTemplate::m_healthDecayRate );
AddClassProperty( L"traits.stamina.curr", &CEntityTemplate::m_staminaCurr );
AddClassProperty( L"traits.stamina.max", &CEntityTemplate::m_staminaMax );
AddClassProperty( L"traits.stamina.bar_height", &CEntityTemplate::m_staminaBarHeight );
AddClassProperty( L"traits.stamina.bar_size", &CEntityTemplate::m_staminaBarSize );

View File

@ -63,7 +63,6 @@ public:
CBoundingObject::EBoundingType m_bound_type;
//SP properties
float m_staminaCurr;
float m_staminaMax;
// HP properties

View File

@ -300,17 +300,16 @@ bool CTechnology::loadELEffect( XMBElement effect, CXeromyces& XeroFile, CStr& f
}
bool CTechnology::isTechValid()
{
if ( !m_player )
return false;
if ( m_excluded )
return false;
if ( hasReqEntities() && hasReqTechs() )
return true;
return false;
}
bool CTechnology::hasReqEntities()
{
bool ret=true;
bool ret = false;
std::vector<HEntity>* entities = m_player->GetControlledEntities();
for ( std::vector<CStr>::iterator it=m_ReqEntities.begin(); it != m_ReqEntities.end(); it++ )
{
@ -318,7 +317,7 @@ bool CTechnology::hasReqEntities()
{
if ( (*it2)->m_classes.IsMember(*it) )
{
ret=true;
ret = true;
break;
}
}
@ -326,19 +325,55 @@ bool CTechnology::hasReqEntities()
delete entities;
return ret;
}
bool CTechnology::hasReqTechs()
{
bool ret=true;
bool ret = true;
for ( std::vector<CStr>::iterator it=m_ReqTechs.begin(); it != m_ReqTechs.end(); it++ )
{
if ( !g_TechnologyCollection.getTechnology( (CStrW)*it, m_player )->isResearched() )
{
ret=false;
ret = false;
break;
}
}
return ret;
}
void CTechnology::apply( CEntity* entity )
{
// Find out if the unit has one of our target classes
bool ok = false;
for ( std::vector<CStr>::iterator it = m_Targets.begin(); it != m_Targets.end(); it++ )
{
if ( entity->m_classes.IsMember( *it ) )
{
ok = true;
break;
}
}
if( !ok ) return;
// Apply modifiers
for ( std::vector<Modifier>::iterator mod=m_Modifiers.begin(); mod!=m_Modifiers.end(); mod++ )
{
jsval oldVal;
if( entity->GetProperty( g_ScriptingHost.getContext(), mod->attribute, &oldVal ) )
{
jsval newVal = ToJSVal( ToPrimitive<float>(oldVal) + mod->value );
entity->SetProperty( g_ScriptingHost.GetContext(), mod->attribute, &newVal );
}
}
// Apply sets
for ( std::vector<Modifier>::iterator mod=m_Sets.begin(); mod!=m_Sets.end(); mod++ )
{
jsval newVal = ToJSVal( mod->value );
entity->SetProperty( g_ScriptingHost.GetContext(), mod->attribute, &newVal );
}
}
//JS stuff
void CTechnology::ScriptingInit()
@ -368,81 +403,38 @@ void CTechnology::ScriptingInit()
debug_printf("CTechnology::ScriptingInit complete");
}
jsval CTechnology::ApplyEffects( JSContext* cx, uintN argc, jsval* argv )
jsval CTechnology::ApplyEffects( JSContext* UNUSED(cx), uintN UNUSED(argc), jsval* UNUSED(argv) )
{
if ( argc < 2 )
{
JS_ReportError(cx, "too few parameters for CTechnology::ApplyEffects.");
return JS_FALSE;
}
if ( !isTechValid() )
return JS_FALSE;
bool first = ToPrimitive<bool>( argv[0] );
bool invert = ToPrimitive<bool>( argv[1] );
if ( first )
{
m_effectFunction.Run( this->GetScript() );
return JSVAL_FALSE;
}
// Disable any paired techs
for ( std::vector<CStr>::iterator it=m_Pairs.begin(); it != m_Pairs.end(); it++ )
g_TechnologyCollection.getTechnology(*it, m_player)->setExclusion(true);
// Disable ourselves so we can't be researched twice
setExclusion(true);
// Get the entities that should be affected
// Apply effects to all entities
std::vector<HEntity>* entities = m_player->GetControlledEntities();
std::vector<HEntity> entitiesAffected;
for ( size_t i=0; i<entities->size(); ++i )
{
for ( std::vector<CStr>::iterator it = m_Targets.begin(); it != m_Targets.end(); it++ )
{
if ( (*entities)[i]->m_classes.IsMember( *it ) )
{
entitiesAffected.push_back( (*entities)[i] );
break;
}
}
apply( (*entities)[i] );
}
delete entities;
std::vector<HEntity>::iterator entIt;
for ( std::vector<Modifier>::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<float>(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<Modifier>::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 )
// Run one-time tech script
if( m_effectFunction )
{
m_effectFunction.Run( this->GetScript() );
}
return JS_TRUE;
// Add ourselves to player's researched techs
m_player->AddActiveTech( this );
return JSVAL_TRUE;
}
jsval CTechnology::IsValid( JSContext* UNUSED(cx), uintN UNUSED(argc), jsval* UNUSED(argv) )

View File

@ -12,6 +12,7 @@
class XMBElement;
class CXeromyces;
class CEntity;
class CTechnology : public CJSObject<CTechnology>
{
@ -38,6 +39,8 @@ public:
jsval IsExcluded( JSContext* cx, uintN argc, jsval* argv );
inline jsval GetPlayerID( JSContext* cx, uintN argc, jsval* argv );
void apply( CEntity* entity );
bool isTechValid();
inline bool isResearched() { return m_researched; }

View File

@ -5,7 +5,6 @@
#ifndef TECHNOLOGY_COLLECTION_INCLUDED
#define TECHNOLOGY_COLLECTION_INCLUDED
#include <vector>
#include "ps/CStr.h"
#include "ps/Singleton.h"
#include "Technology.h"
@ -20,9 +19,13 @@ class CTechnologyCollection : public Singleton<CTechnologyCollection>
TechMap m_techs[PS_MAX_PLAYERS+1];
TechFilenameMap m_techFilenames;
public:
~CTechnologyCollection();
std::vector<CTechnology*> activeTechs[PS_MAX_PLAYERS+1];
CTechnology* getTechnology( CStrW techType, CPlayer* player );
~CTechnologyCollection();
int loadTechnologies();
void LoadFile( const char* path );
};