forked from 0ad/0ad
# 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:
parent
b70e16cf2a
commit
8eae620b11
@ -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();
|
||||
|
||||
|
@ -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 ) )
|
||||
{
|
||||
|
@ -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 );
|
||||
|
@ -63,7 +63,6 @@ public:
|
||||
CBoundingObject::EBoundingType m_bound_type;
|
||||
|
||||
//SP properties
|
||||
float m_staminaCurr;
|
||||
float m_staminaMax;
|
||||
|
||||
// HP properties
|
||||
|
@ -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) )
|
||||
|
@ -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; }
|
||||
|
||||
|
@ -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 );
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user