Changeset View
Standalone View
binaries/data/mods/public/simulation/components/Foundation.js
function Foundation() {} | function Foundation() {} | ||||
Foundation.prototype.Schema = | Foundation.prototype.Schema = | ||||
"<empty/>"; | "<empty/>"; | ||||
Freagarach: Mind to revert? | |||||
Done Inline ActionsNo I don't mind. It's actually when I moved it :) Stan: No I don't mind. It's actually when I moved it :) | |||||
Foundation.prototype.Init = function() | Foundation.prototype.Init = function() | ||||
{ | { | ||||
// Foundations are initially 'uncommitted' and do not block unit movement at all | // Foundations are initially 'uncommitted' and do not block unit movement at all | ||||
// (to prevent players exploiting free foundations to confuse enemy units). | // (to prevent players exploiting free foundations to confuse enemy units). | ||||
// The first builder to reach the uncommitted foundation will tell friendly units | // The first builder to reach the uncommitted foundation will tell friendly units | ||||
// and animals to move out of the way, then will commit the foundation and enable | // and animals to move out of the way, then will commit the foundation and enable | ||||
// its obstruction once there's nothing in the way. | // its obstruction once there's nothing in the way. | ||||
this.committed = false; | this.committed = false; | ||||
this.builders = new Map(); // Map of builder entities to their work per second | this.builders = new Map(); // Map of builder entities to their work per second | ||||
this.totalBuilderRate = 0; // Total amount of work the builders do each second | this.totalBuilderRate = 0; // Total amount of work the builders do each second | ||||
this.buildMultiplier = 1; // Multiplier for the amount of work builders do | this.buildMultiplier = 1; // Multiplier for the amount of work builders do | ||||
this.buildTimePenalty = 0.7; // Penalty for having multiple builders | this.buildTimePenalty = 0.7; // Penalty for having multiple builders | ||||
this.previewEntity = INVALID_ENTITY; | this.previewEntity = INVALID_ENTITY; | ||||
Done Inline ActionsObselete. Freagarach: Obselete. | |||||
let cmpAutoBuildable = Engine.QueryInterface(this.entity, IID_AutoBuildable); | |||||
if (cmpAutoBuildable) | |||||
Done Inline Actionswhy did you not switch from isautobuildable to getrate != 0 check ? if nothing here, message system you added has no reason to be added :) Silier: why did you not switch from isautobuildable to getrate != 0 check ? if nothing here, message… | |||||
this.StartTimer(); | |||||
}; | }; | ||||
Foundation.prototype.InitialiseConstruction = function(owner, template) | Foundation.prototype.InitialiseConstruction = function(owner, template) | ||||
{ | { | ||||
this.finalTemplateName = template; | this.finalTemplateName = template; | ||||
// We need to know the owner in OnDestroy, but at that point the entity has already been | // We need to know the owner in OnDestroy, but at that point the entity has already been | ||||
// decoupled from its owner, so we need to remember it in here (and assume it won't change) | // decoupled from its owner, so we need to remember it in here (and assume it won't change) | ||||
▲ Show 20 Lines • Show All 118 Lines • ▼ Show 20 Lines | |||||
* @param {number} builderEnt - The entity to add. | * @param {number} builderEnt - The entity to add. | ||||
* @return {boolean} - Whether the addition was successful. | * @return {boolean} - Whether the addition was successful. | ||||
*/ | */ | ||||
Foundation.prototype.AddBuilderHelper = function(builderEnt) | Foundation.prototype.AddBuilderHelper = function(builderEnt) | ||||
{ | { | ||||
if (this.builders.has(builderEnt)) | if (this.builders.has(builderEnt)) | ||||
return false; | return false; | ||||
let buildRate = Engine.QueryInterface(builderEnt, IID_Builder).GetRate(); | let cmpBuilder = Engine.QueryInterface(builderEnt, IID_Builder) || | ||||
Done Inline ActionsI would put this in an if for readability, perhaps? And should we check for the existence of AutoBuild first? Freagarach: I would put this in an `if` for readability, perhaps? And should we check for the existence of… | |||||
Done Inline ActionsSo: let rate = 0; if (cmpBuilder) rate = cmpBuilder.GetRate() else if(this.template.AutoBuild) rate = ApplyValueModificationsToEntity("Foundation/AutoBuild/Rate", +this.template.AutoBuild.Rate, this.entity); I assume there is no case where we want both? Stan: So:
```lang=js
let rate = 0;
if (cmpBuilder)
rate = cmpBuilder.GetRate()
else if(this. | |||||
Done Inline ActionsIf it has neither shouldn't we return, not add a builder with rate 0? Freagarach: If it has neither shouldn't we return, not add a builder with rate `0`? | |||||
Done Inline ActionsReturn or warning? Stan: Return or warning? | |||||
Engine.QueryInterface(this.entity, IID_AutoBuildable); | |||||
if (!cmpBuilder) | |||||
Done Inline Actionsstill my question: if autobuildable do you want to allow another builders ? Silier: still my question: if autobuildable do you want to allow another builders ? | |||||
Done Inline ActionsYes. Stan: Yes. | |||||
Done Inline ActionsI would say that a modder should have at least the option: either let a building autobuild itself slowly or speed up construction using villies. Freagarach: I would say that a modder should have at least the option: either let a building autobuild… | |||||
return false; | |||||
Done Inline Actionsif ( Freagarach: `if (` | |||||
Done Inline Actionsyou can get rid of if else branch negating condition Silier: you can get rid of if else branch negating condition | |||||
let buildRate = cmpBuilder.GetRate(); | |||||
this.builders.set(builderEnt, buildRate); | this.builders.set(builderEnt, buildRate); | ||||
this.totalBuilderRate += buildRate; | this.totalBuilderRate += buildRate; | ||||
return true; | return true; | ||||
Done Inline Actionsif (rate == 0)? Freagarach: `if (rate == 0)`? | |||||
Done Inline ActionsWhat if the applied modification is 0? Stan: What if the applied modification is 0? | |||||
Done Inline ActionsWould we want to add a builder with rate == 0 is then the question ;) But I guess that is outside the scope for this patch, as it would need further investigation (could introduce infinite loops perhaps, don't know). Freagarach: Would we want to add a builder with `rate == 0` is then the question ;) But I guess that is… | |||||
Done Inline Actionselse if ((cmpBuilder = Engine.QueryInterface(this.entity, IID_AutoBuildable))) buildRate = cmpBuilder.GetAutoBuildRate(); ? Freagarach: ```
else if ((cmpBuilder = Engine.QueryInterface(this.entity, IID_AutoBuildable)))
buildRate… | |||||
Done Inline ActionsMeh. Stan: Meh. | |||||
Done Inline Actionslet cmpBuilder = Engine.QueryInterface(builderEnt, IID_Builder) || Engine.QueryInterface(this.entity, IID_AutoBuildable); if (cmpBuilder) buildRate = cmpBuilder.GetRate(); else return false; ? Freagarach: ```
let cmpBuilder = Engine.QueryInterface(builderEnt, IID_Builder) ||
Engine.QueryInterface… | |||||
Done Inline ActionsNeeds to rename the function else it won't work Stan: Needs to rename the function else it won't work | |||||
} | } | ||||
/** | /** | ||||
* Adds a builder to the counter. | * Adds a builder to the counter. | ||||
* | * | ||||
* @param {number} builderEnt - The entity to add. | * @param {number} builderEnt - The entity to add. | ||||
*/ | */ | ||||
Foundation.prototype.AddBuilder = function(builderEnt) | Foundation.prototype.AddBuilder = function(builderEnt) | ||||
▲ Show 20 Lines • Show All 131 Lines • ▼ Show 20 Lines | if (cmpFoundationVisual && cmpFoundationVisual.HasConstructionPreview()) | ||||
var cmpPreviewVisual = Engine.QueryInterface(this.previewEntity, IID_Visual); | var cmpPreviewVisual = Engine.QueryInterface(this.previewEntity, IID_Visual); | ||||
if (cmpPreviewVisual) | if (cmpPreviewVisual) | ||||
{ | { | ||||
cmpPreviewVisual.SetActorSeed(cmpFoundationVisual.GetActorSeed()); | cmpPreviewVisual.SetActorSeed(cmpFoundationVisual.GetActorSeed()); | ||||
cmpPreviewVisual.SelectAnimation("scaffold", false, 1.0, ""); | cmpPreviewVisual.SelectAnimation("scaffold", false, 1.0, ""); | ||||
} | } | ||||
var cmpFoundationPosition = Engine.QueryInterface(this.entity, IID_Position); | var cmpFoundationPosition = Engine.QueryInterface(this.entity, IID_Position); | ||||
var pos = cmpFoundationPosition.GetPosition2D(); | let pos = cmpFoundationPosition.GetPosition2D(); | ||||
var rot = cmpFoundationPosition.GetRotation(); | let rot = cmpFoundationPosition.GetRotation(); | ||||
cmpPreviewPosition.SetYRotation(rot.y); | cmpPreviewPosition.SetYRotation(rot.y); | ||||
cmpPreviewPosition.SetXZRotation(rot.x, rot.z); | cmpPreviewPosition.SetXZRotation(rot.x, rot.z); | ||||
cmpPreviewPosition.JumpTo(pos.x, pos.y); | cmpPreviewPosition.JumpTo(pos.x, pos.y); | ||||
} | } | ||||
this.committed = true; | this.committed = true; | ||||
} | } | ||||
Show All 40 Lines | if (progress >= 1.0) | ||||
} | } | ||||
var cmpBuildingPosition = Engine.QueryInterface(building, IID_Position); | var cmpBuildingPosition = Engine.QueryInterface(building, IID_Position); | ||||
if (!cmpBuildingPosition) | if (!cmpBuildingPosition) | ||||
{ | { | ||||
error("New building " + building + " has no position component."); | error("New building " + building + " has no position component."); | ||||
Engine.DestroyEntity(building); | Engine.DestroyEntity(building); | ||||
return; | return; | ||||
} | } | ||||
var pos = cmpPosition.GetPosition2D(); | let pos = cmpPosition.GetPosition2D(); | ||||
cmpBuildingPosition.JumpTo(pos.x, pos.y); | cmpBuildingPosition.JumpTo(pos.x, pos.y); | ||||
var rot = cmpPosition.GetRotation(); | let rot = cmpPosition.GetRotation(); | ||||
cmpBuildingPosition.SetYRotation(rot.y); | cmpBuildingPosition.SetYRotation(rot.y); | ||||
cmpBuildingPosition.SetXZRotation(rot.x, rot.z); | cmpBuildingPosition.SetXZRotation(rot.x, rot.z); | ||||
// TODO: should add a ICmpPosition::CopyFrom() instead of all this | // TODO: should add a ICmpPosition::CopyFrom() instead of all this | ||||
var cmpRallyPoint = Engine.QueryInterface(this.entity, IID_RallyPoint); | var cmpRallyPoint = Engine.QueryInterface(this.entity, IID_RallyPoint); | ||||
var cmpBuildingRallyPoint = Engine.QueryInterface(building, IID_RallyPoint); | var cmpBuildingRallyPoint = Engine.QueryInterface(building, IID_RallyPoint); | ||||
if(cmpRallyPoint && cmpBuildingRallyPoint) | if(cmpRallyPoint && cmpBuildingRallyPoint) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 83 Lines • ▼ Show 20 Lines | |||||
Foundation.prototype.GetBuildRate = function() | Foundation.prototype.GetBuildRate = function() | ||||
{ | { | ||||
let cmpHealth = Engine.QueryInterface(this.entity, IID_Health); | let cmpHealth = Engine.QueryInterface(this.entity, IID_Health); | ||||
let cmpCost = Engine.QueryInterface(this.entity, IID_Cost); | let cmpCost = Engine.QueryInterface(this.entity, IID_Cost); | ||||
// Return infinity for instant structure conversion | // Return infinity for instant structure conversion | ||||
return cmpHealth.GetMaxHitpoints() / cmpCost.GetBuildTime(); | return cmpHealth.GetMaxHitpoints() / cmpCost.GetBuildTime(); | ||||
}; | }; | ||||
Foundation.prototype.StartTimer = function() | |||||
{ | |||||
if (this.timer) | |||||
return; | |||||
this.AddBuilder(this.entity); | |||||
Done Inline ActionsCan StartTimer() be called after construction has started? Freagarach: Can `StartTimer()` be called after construction has started? | |||||
Done Inline ActionsNot currently, any reason for that? Stan: Not currently, any reason for that? | |||||
Done Inline ActionsWell, you call this function in init, so it will be called only once, but making sure this is not finished yet is okay I guess. Freagarach: Well, you call this function in init, so it will be called only once, but making sure this is… | |||||
Done Inline ActionsI see right! Stan: I see right! | |||||
let cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer); | |||||
this.timer = cmpTimer.SetInterval(this.entity, IID_Foundation, "AutoBuild", 0, 1000, undefined); | |||||
}; | |||||
Foundation.prototype.CancelTimer = function() | |||||
{ | |||||
if (!this.timer) | |||||
return; | |||||
this.RemoveBuilder(this.entity); | |||||
let cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer); | |||||
cmpTimer.CancelTimer(this.timer); | |||||
delete this.timer; | |||||
}; | |||||
Foundation.prototype.AutoBuild = function() | |||||
{ | |||||
let cmpAutoBuildable = Engine.QueryInterface(this.entity, IID_AutoBuildable); | |||||
if (!cmpAutoBuildable) | |||||
Done Inline Actionsif this, better to cancel timer Silier: if this, better to cancel timer | |||||
{ | |||||
Done Inline ActionsCheck for cmp? Freagarach: Check for cmp? | |||||
this.CancelTimer(); | |||||
return; | |||||
} | |||||
let rate = cmpAutoBuildable.GetRate(); | |||||
if (rate != 0) | |||||
this.Build(this.entity, rate); | |||||
Done Inline ActionsSince this is good idea, its not the right one. It is not guaranteed Foundation will get on value modification message after Autobuildable and not before. What I meant on irc, is that you send message from autobuildable when value is modified and catch it in foundation. Even if current message system would send messages in alphabetic order in respect to components, that message would be also required if one would want special icon over foundation if is currently autobuildable or in gui to get the icon hide or show correctly. Silier: Since this is good idea, its not the right one. It is not guaranteed Foundation will get on… | |||||
Done Inline Actionsmaybe !rate Silier: maybe !rate | |||||
Done Inline ActionsI'd rather not, as it would cover rate being negative. Stan: I'd rather not, as it would cover rate being negative. | |||||
Done Inline Actions!-5 == false Silier: !-5 == false | |||||
Done Inline Actions@Angen should I change it then? Stan: @Angen should I change it then? | |||||
Done Inline Actionsits not terrible or bad as it is so i leave that on you to decide and rate will always be defined Silier: its not terrible or bad as it is so i leave that on you to decide and rate will always be… | |||||
}; | |||||
Done Inline ActionsThis is not used anymore? Freagarach: This is not used anymore? | |||||
Done Inline ActionsRight Stan: Right | |||||
Foundation.prototype.OnAutoBuildRateChanged = function() | |||||
{ | |||||
if (this.timer) | |||||
return; | |||||
let cmpAutoBuildable = Engine.QueryInterface(this.entity, IID_AutoBuildable); | |||||
if (cmpAutoBuildable && cmpAutoBuildable.GetRate() != 0) | |||||
this.StartTimer(); | |||||
}; | |||||
Engine.RegisterComponentType(IID_Foundation, "Foundation", Foundation); | Engine.RegisterComponentType(IID_Foundation, "Foundation", Foundation); | ||||
Done Inline Actionsthis.CancelTimer means timer is running and we want to cancel it, right ? But if timer is running L518 executes early return so never gets here, also AutoBuild will cancel timer if rate reaches 0 Silier: this.CancelTimer means timer is running and we want to cancel it, right ? But if timer is… | |||||
Done Inline Actionseven if you cancel timer above when rate reaches 0, this line starts it again Silier: even if you cancel timer above when rate reaches 0, this line starts it again |
Mind to revert?