2012-11-07 18:56:14 +01:00
function EntityLimits ( ) { }
2010-12-12 00:19:17 +01:00
2012-11-07 18:56:14 +01:00
EntityLimits . prototype . Schema =
2013-10-06 05:13:46 +02:00
"<a:help>Specifies per category limits on number of entities (buildings or units) that can be created for each player</a:help>" +
2011-08-06 10:11:05 +02:00
"<a:example>" +
"<Limits>" +
2013-12-27 11:58:48 +01:00
"<DefenseTower>25</DefenseTower>" +
"<Fortress>10</Fortress>" +
"<Wonder>1</Wonder>" +
"<Hero>1</Hero>" +
"<Apadana>1</Apadana>" +
"<Monument>5</Monument>" +
2011-08-06 10:11:05 +02:00
"</Limits>" +
2013-12-27 11:58:48 +01:00
"<LimitChangers>" +
"<Monument>" +
2015-01-01 19:28:21 +01:00
"<CivilCentre>2</CivilCentre>" +
2013-12-27 11:58:48 +01:00
"</Monument>" +
"</LimitChangers>" +
2015-01-01 19:28:21 +01:00
"<LimitRemovers>" +
"<CivilCentre>" +
"<RequiredTechs datatype=\"tokens\">town_phase</RequiredTechs>" +
"</CivilCentre>" +
"</LimitRemovers>" +
2011-08-06 10:11:05 +02:00
"</a:example>" +
2010-12-12 00:19:17 +01:00
"<element name='Limits'>" +
"<zeroOrMore>" +
2013-10-06 05:13:46 +02:00
"<element a:help='Specifies a category of building/unit on which to apply this limit. See BuildRestrictions/TrainingRestrictions for possible categories'>" +
2010-12-12 00:19:17 +01:00
"<anyName />" +
2013-09-15 10:19:50 +02:00
"<data type='integer'/>" +
2010-12-12 00:19:17 +01:00
"</element>" +
"</zeroOrMore>" +
2013-12-27 11:58:48 +01:00
"</element>" +
"<element name='LimitChangers'>" +
"<zeroOrMore>" +
"<element a:help='Specifies a category of building/unit on which to apply this limit. See BuildRestrictions/TrainingRestrictions for possible categories'>" +
"<anyName />" +
"<zeroOrMore>" +
"<element a:help='Specifies the class that changes the entity limit'>" +
"<anyName />" +
"<data type='integer'/>" +
"</element>" +
"</zeroOrMore>" +
"</element>" +
"</zeroOrMore>" +
2015-01-01 19:28:21 +01:00
"</element>" +
"<element name='LimitRemovers'>" +
"<zeroOrMore>" +
"<element a:help='Specifies a category of building/unit on which to remove this limit. The limit will be removed if all the followings requirements are satisfied'>" +
"<anyName />" +
"<oneOrMore>" +
"<element a:help='Possible requirements are: RequiredTechs and RequiredClasses'>" +
"<anyName />" +
"<attribute name='datatype'>" +
"<value>tokens</value>" +
"</attribute>" +
"<text/>" +
"</element>" +
"</oneOrMore>" +
"</element>" +
"</zeroOrMore>" +
2010-12-12 00:19:17 +01:00
"</element>" ;
2013-12-27 11:58:48 +01:00
2012-11-07 18:56:14 +01:00
const TRAINING = "training" ;
const BUILD = "build" ;
EntityLimits . prototype . Init = function ( )
2010-12-12 00:19:17 +01:00
{
2011-11-14 01:02:54 +01:00
this . limit = { } ;
2015-01-01 19:28:21 +01:00
this . count = { } ; // counts entities which change the limit of the given category
2013-12-27 11:58:48 +01:00
this . changers = { } ;
2015-01-01 19:28:21 +01:00
this . removers = { } ;
this . classCount = { } ; // counts entities with the given class, used in the limit removal
this . removedLimit = { } ;
2010-12-12 00:19:17 +01:00
for ( var category in this . template . Limits )
{
2013-09-15 10:19:50 +02:00
this . limit [ category ] = + this . template . Limits [ category ] ;
2011-08-06 10:11:05 +02:00
this . count [ category ] = 0 ;
2015-01-01 19:28:21 +01:00
if ( category in this . template . LimitChangers )
{
this . changers [ category ] = { } ;
for ( var c in this . template . LimitChangers [ category ] )
this . changers [ category ] [ c ] = + this . template . LimitChangers [ category ] [ c ] ;
}
if ( category in this . template . LimitRemovers )
{
this . removedLimit [ category ] = this . limit [ category ] ; // keep a copy of removeable limits for possible restoration
this . removers [ category ] = { } ;
for ( var c in this . template . LimitRemovers [ category ] )
{
this . removers [ category ] [ c ] = this . template . LimitRemovers [ category ] [ c ] . _string . split ( /\s+/ ) ;
if ( c === "RequiredClasses" )
for ( var cls of this . removers [ category ] [ c ] )
this . classCount [ cls ] = 0 ;
}
}
2010-12-12 00:19:17 +01:00
}
} ;
2013-12-27 11:58:48 +01:00
EntityLimits . prototype . ChangeCount = function ( category , value )
2010-12-12 00:19:17 +01:00
{
2011-08-06 10:11:05 +02:00
if ( this . count [ category ] !== undefined )
2012-11-07 18:56:14 +01:00
this . count [ category ] += value ;
2010-12-12 00:19:17 +01:00
} ;
2012-11-07 18:56:14 +01:00
EntityLimits . prototype . GetLimits = function ( )
2011-10-21 01:35:52 +02:00
{
2011-11-14 01:02:54 +01:00
return this . limit ;
2011-10-21 01:35:52 +02:00
} ;
2012-11-07 18:56:14 +01:00
EntityLimits . prototype . GetCounts = function ( )
2011-10-21 01:35:52 +02:00
{
2011-11-14 01:02:54 +01:00
return this . count ;
2011-10-21 01:35:52 +02:00
} ;
2013-12-27 11:58:48 +01:00
EntityLimits . prototype . GetLimitChangers = function ( )
2010-12-12 00:19:17 +01:00
{
2013-12-27 11:58:48 +01:00
return this . changers ;
} ;
2011-08-06 10:11:05 +02:00
2015-01-01 19:28:21 +01:00
EntityLimits . prototype . UpdateLimitsFromTech = function ( tech )
{
for ( var category in this . removers )
if ( "RequiredTechs" in this . removers [ category ] && this . removers [ category ] [ "RequiredTechs" ] . indexOf ( tech ) !== - 1 )
this . removers [ category ] [ "RequiredTechs" ] . splice ( this . removers [ category ] [ "RequiredTechs" ] . indexOf ( tech ) , 1 ) ;
this . UpdateLimitRemoval ( ) ;
} ;
EntityLimits . prototype . UpdateLimitRemoval = function ( )
{
for ( var category in this . removers )
{
var nolimit = true ;
if ( "RequiredTechs" in this . removers [ category ] )
nolimit = ! this . removers [ category ] [ "RequiredTechs" ] . length ;
if ( nolimit && "RequiredClasses" in this . removers [ category ] )
for ( var cls of this . removers [ category ] [ "RequiredClasses" ] )
nolimit = nolimit && this . classCount [ cls ] > 0 ;
if ( nolimit && this . limit [ category ] !== undefined )
this . limit [ category ] = undefined ;
else if ( ! nolimit && this . limit [ category ] === undefined )
this . limit [ category ] = this . removedLimit [ category ] ;
}
} ;
2013-12-27 11:58:48 +01:00
EntityLimits . prototype . AllowedToCreate = function ( limitType , category , count )
{
2011-08-06 10:11:05 +02:00
// Allow unspecified categories and those with no limit
if ( this . count [ category ] === undefined || this . limit [ category ] === undefined )
return true ;
2013-09-15 10:19:50 +02:00
if ( this . count [ category ] + count > this . limit [ category ] )
2010-12-12 00:19:17 +01:00
{
2011-08-16 06:44:15 +02:00
var cmpPlayer = Engine . QueryInterface ( this . entity , IID _Player ) ;
2012-11-07 18:56:14 +01:00
var notification = {
2014-06-19 16:37:08 +02:00
"players" : [ cmpPlayer . GetPlayerID ( ) ] ,
2014-05-19 09:35:05 +02:00
"translateMessage" : true ,
"translateParameters" : [ "category" ] ,
"parameters" : { "category" : category , "limit" : this . limit [ category ] } ,
} ;
if ( limitType == BUILD )
notification . message = markForTranslation ( "%(category)s build limit of %(limit)s reached" ) ;
else if ( limitType == TRAINING )
notification . message = markForTranslation ( "%(category)s training limit of %(limit)s reached" ) ;
else
{
warn ( "EntityLimits.js: Unknown LimitType " + limitType )
notification . message = markForTranslation ( "%(category)s limit of %(limit)s reached" ) ;
}
2011-08-06 10:11:05 +02:00
var cmpGUIInterface = Engine . QueryInterface ( SYSTEM _ENTITY , IID _GuiInterface ) ;
cmpGUIInterface . PushNotification ( notification ) ;
return false ;
2010-12-12 00:19:17 +01:00
}
2011-08-06 10:11:05 +02:00
return true ;
2012-11-07 18:56:14 +01:00
}
EntityLimits . prototype . AllowedToBuild = function ( category )
{
2013-04-29 02:36:21 +02:00
// We pass count 0 as the creation of the building has already taken place and
// the ownership has been set (triggering OnGlobalOwnershipChanged)
return this . AllowedToCreate ( BUILD , category , 0 ) ;
2012-11-07 18:56:14 +01:00
} ;
EntityLimits . prototype . AllowedToTrain = function ( category , count )
{
return this . AllowedToCreate ( TRAINING , category , count ) ;
2010-12-12 00:19:17 +01:00
} ;
2012-11-07 18:56:14 +01:00
EntityLimits . prototype . OnGlobalOwnershipChanged = function ( msg )
2015-01-01 19:28:21 +01:00
{
2013-12-27 11:58:48 +01:00
// check if we are adding or removing an entity from this player
var cmpPlayer = Engine . QueryInterface ( this . entity , IID _Player ) ;
if ( ! cmpPlayer )
{
error ( "EntityLimits component is defined on a non-player entity" ) ;
return ;
}
if ( msg . from == cmpPlayer . GetPlayerID ( ) )
var modifier = - 1 ;
else if ( msg . to == cmpPlayer . GetPlayerID ( ) )
var modifier = 1 ;
else
return ;
// Update entity counts
2012-11-07 18:56:14 +01:00
var category = null ;
2011-08-16 06:44:15 +02:00
var cmpBuildRestrictions = Engine . QueryInterface ( msg . entity , IID _BuildRestrictions ) ;
if ( cmpBuildRestrictions )
2012-11-07 18:56:14 +01:00
category = cmpBuildRestrictions . GetCategory ( ) ;
var cmpTrainingRestrictions = Engine . QueryInterface ( msg . entity , IID _TrainingRestrictions ) ;
if ( cmpTrainingRestrictions )
category = cmpTrainingRestrictions . GetCategory ( ) ;
if ( category )
2015-01-01 19:28:21 +01:00
this . ChangeCount ( category , modifier ) ;
2013-12-27 11:58:48 +01:00
// Update entity limits
var cmpIdentity = Engine . QueryInterface ( msg . entity , IID _Identity ) ;
if ( ! cmpIdentity )
return ;
2015-01-01 19:28:21 +01:00
2014-05-07 10:24:31 +02:00
// foundations shouldn't change the entity limits until they're completed
var cmpFoundation = Engine . QueryInterface ( msg . entity , IID _Foundation ) ;
if ( cmpFoundation )
return ;
2013-12-27 11:58:48 +01:00
var classes = cmpIdentity . GetClassesList ( ) ;
for ( var category in this . changers )
for ( var c in this . changers [ category ] )
if ( classes . indexOf ( c ) >= 0 )
2015-01-01 19:28:21 +01:00
{
2015-01-24 13:03:31 +01:00
if ( this . limit [ category ] != undefined )
2015-01-01 19:28:21 +01:00
this . limit [ category ] += modifier * this . changers [ category ] [ c ] ;
2015-01-24 13:03:31 +01:00
if ( this . removedLimit [ category ] != undefined ) // update removed limits in case we want to restore it
2015-01-01 19:28:21 +01:00
this . removedLimit [ category ] += modifier * this . changers [ category ] [ c ] ;
}
for ( var category in this . removers )
if ( "RequiredClasses" in this . removers [ category ] )
for ( var cls of this . removers [ category ] [ "RequiredClasses" ] )
if ( classes . indexOf ( cls ) !== - 1 )
this . classCount [ cls ] += modifier ;
this . UpdateLimitRemoval ( ) ;
2011-08-16 06:44:15 +02:00
} ;
2012-11-07 18:56:14 +01:00
Engine . RegisterComponentType ( IID _EntityLimits , "EntityLimits" , EntityLimits ) ;