Changeset View
Standalone View
binaries/data/mods/public/simulation/components/VisionSharing.js
function VisionSharing() {} | function VisionSharing() {} | ||||
VisionSharing.prototype.Schema = | VisionSharing.prototype.Schema = | ||||
"<empty/>"; | "<element name='Bribable'>" + | ||||
"<data type='boolean'/>" + | |||||
"</element>" + | |||||
"<optional>" + | |||||
"<element name='Duration' a:help='Duration (in second) of the vision sharing for spies'>" + | |||||
elexis: Should state something when it's a permanent spy | |||||
Not Done Inline Actionsok mimo: ok | |||||
"<ref name='positiveDecimal'/>" + | |||||
Not Done Inline Actions(Usually milliseconds in the templates, but I'm fine with seconds as likely noone (not even modders on a mars mission) will use something with higher precision) elexis: (Usually milliseconds in the templates, but I'm fine with seconds as likely noone (not even… | |||||
Not Done Inline ActionsUsually? all BuildTime or tech ResearchTime are in second. But i agree that we always have this ambiguity when reading templates which is not nice. Maybe we should decide on one time convention at least for future additions. I've no strong opinion about second or millisecond. mimo: Usually? all BuildTime or tech ResearchTime are in second. But i agree that we always have this… | |||||
"</element>" + | |||||
"</optional>"; | |||||
VisionSharing.prototype.Init = function() | VisionSharing.prototype.Init = function() | ||||
{ | { | ||||
this.activated = false; | this.activated = false; | ||||
this.shared = new Set(); | this.shared = undefined; | ||||
this.spyId = 0; | |||||
this.spies = undefined; | |||||
}; | }; | ||||
/** | /** | ||||
* As entities have not necessarily the VisionSharing component, it has to be activated | * As entities have not necessarily the VisionSharing component, it has to be activated | ||||
* before use so that the rangeManager can register it | * before use so that the rangeManager can register it | ||||
*/ | */ | ||||
VisionSharing.prototype.Activate = function() | VisionSharing.prototype.Activate = function() | ||||
{ | { | ||||
if (this.activated) | if (this.activated) | ||||
return; | return; | ||||
let cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership); | let cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership); | ||||
if (!cmpOwnership || cmpOwnership.GetOwner() <= 0) | if (!cmpOwnership || cmpOwnership.GetOwner() <= 0) | ||||
return; | return; | ||||
this.shared.add(cmpOwnership.GetOwner()); | this.shared = new Set([cmpOwnership.GetOwner()]); | ||||
Engine.PostMessage(this.entity, MT_VisionSharingChanged, | Engine.PostMessage(this.entity, MT_VisionSharingChanged, | ||||
{ "entity": this.entity, "player": cmpOwnership.GetOwner(), "add": true }); | { "entity": this.entity, "player": cmpOwnership.GetOwner(), "add": true }); | ||||
this.activated = true; | this.activated = true; | ||||
}; | }; | ||||
VisionSharing.prototype.CheckVisionSharings = function() | VisionSharing.prototype.CheckVisionSharings = function() | ||||
{ | { | ||||
let shared = new Set(); | let shared = new Set(); | ||||
Show All 19 Lines | if (cmpGarrisonHolder) | ||||
if (entOwner > 0 && entOwner != owner) | if (entOwner > 0 && entOwner != owner) | ||||
{ | { | ||||
shared.add(entOwner); | shared.add(entOwner); | ||||
// if shared by another player than the owner and not yet activated, do it | // if shared by another player than the owner and not yet activated, do it | ||||
this.Activate(); | this.Activate(); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
// vision sharing due to spies | |||||
if (this.spies) | |||||
for (let spy of this.spies.values()) | |||||
if (spy > 0 && spy != owner) | |||||
shared.add(spy); | |||||
} | } | ||||
if (!this.activated) | if (!this.activated) | ||||
return; | return; | ||||
// compare with previous vision sharing, and update if needed | // compare with previous vision sharing, and update if needed | ||||
for (let player of shared) | for (let player of shared) | ||||
if (!this.shared.has(player)) | if (!this.shared.has(player)) | ||||
Engine.PostMessage(this.entity, MT_VisionSharingChanged, | Engine.PostMessage(this.entity, MT_VisionSharingChanged, | ||||
{ "entity": this.entity, "player": player, "add": true }); | { "entity": this.entity, "player": player, "add": true }); | ||||
for (let player of this.shared) | for (let player of this.shared) | ||||
if (!shared.has(player)) | if (!shared.has(player)) | ||||
Engine.PostMessage(this.entity, MT_VisionSharingChanged, | Engine.PostMessage(this.entity, MT_VisionSharingChanged, | ||||
{ "entity": this.entity, "player": player, "add": false }); | { "entity": this.entity, "player": player, "add": false }); | ||||
this.shared = shared; | this.shared = shared; | ||||
}; | }; | ||||
VisionSharing.prototype.IsBribable = function() | |||||
{ | |||||
return this.template.Bribable == "true"; | |||||
}; | |||||
VisionSharing.prototype.OnDiplomacyChanged = function(msg) | VisionSharing.prototype.OnDiplomacyChanged = function(msg) | ||||
{ | { | ||||
this.CheckVisionSharings(); | this.CheckVisionSharings(); | ||||
}; | }; | ||||
VisionSharing.prototype.OnGarrisonedUnitsChanged = function(msg) | VisionSharing.prototype.OnGarrisonedUnitsChanged = function(msg) | ||||
{ | { | ||||
this.CheckVisionSharings(); | this.CheckVisionSharings(); | ||||
}; | }; | ||||
VisionSharing.prototype.OnOwnershipChanged = function(msg) | VisionSharing.prototype.OnOwnershipChanged = function(msg) | ||||
{ | { | ||||
if (this.activated) | if (this.activated) | ||||
this.CheckVisionSharings(); | this.CheckVisionSharings(); | ||||
}; | }; | ||||
fatherbushidoUnsubmitted Not Done Inline ActionsJust note for myself: fatherbushido: Just note for myself:
(When msg.to == -1,
The CheckVisionSharings() calls will just set this. | |||||
VisionSharing.prototype.AddSpy = function(player, timeLength) | |||||
{ | |||||
if (!this.IsBribable()) | |||||
return; | |||||
let cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership); | |||||
if (!cmpOwnership || cmpOwnership.GetOwner() == player || player <= 0) | |||||
return; | |||||
let cmpTechnologyManager = QueryPlayerIDInterface(player, IID_TechnologyManager); | |||||
if (!cmpTechnologyManager || !cmpTechnologyManager.CanProduce("special/spy")) | |||||
return; | |||||
let template = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager).GetTemplate("special/spy"); | |||||
let costs = {}; | |||||
for (let res in template.Cost.Resources) | |||||
costs[res] = Math.floor(ApplyValueModificationsToTemplate("Cost/Resources/"+res, +template.Cost.Resources[res], player, template)); | |||||
let cmpPlayer = QueryPlayerIDInterface(player); | |||||
if (!cmpPlayer || !cmpPlayer.TrySubtractResources(costs)) | |||||
return; | |||||
// If no duration given, take it from the spy template and scale it with the ent vision | |||||
// When no duration argument nor in spy template, it is a permanent spy | |||||
let duration = timeLength; | |||||
if (!duration && template.VisionSharing && template.VisionSharing.Duration) | |||||
{ | |||||
duration = ApplyValueModificationsToTemplate("VisionSharing/Duration", +template.VisionSharing.Duration, player, template); | |||||
let cmpVision = Engine.QueryInterface(this.entity, IID_Vision); | |||||
if (cmpVision) | |||||
duration *= 60 / Math.max(30, cmpVision.GetRange()); | |||||
Not Done Inline ActionsNot convinced by scaling with the vision range in comparison to just using the default. Permanent spies are impossible without changing special/spy.xml? Sounds bad for modders and future extension if so. (Would that actually work if attempted to be used or bug with undefined?) elexis: Not convinced by scaling with the vision range in comparison to just using the default. | |||||
Not Done Inline Actionswhile scaling is not really needed with bribable traders (land and naval traders have nearly the same vision), it would be unfair to pay the same price for a female (vision=32) and a cav (vision=90) if we add more bribable units. We could replace this scaling by a price depending on vision of the unit which will be selected, but i'm not sure it is worth the complication. mimo: while scaling is not really needed with bribable traders (land and naval traders have nearly… | |||||
Not Done Inline ActionsShouldn't the template specify the duration, thus the use/cost ratio? elexis: Shouldn't the template specify the duration, thus the use/cost ratio?
Permanent spies, well… | |||||
} | |||||
if (!this.spies) | |||||
this.spies = new Map(); | |||||
this.spies.set(++this.spyId, player); | |||||
if (duration) | |||||
{ | |||||
let cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer); | |||||
cmpTimer.SetTimeout(this.entity, IID_VisionSharing, "RemoveSpy", duration * 1000, { "id": this.spyId }); | |||||
Not Done Inline Actions(perhaps add spaces) fatherbushido: (perhaps add spaces) | |||||
Not Done Inline Actionsyou mean for "duration*1000"? ok mimo: you mean for "duration*1000"? ok | |||||
Not Done Inline Actionsyes fatherbushido: yes | |||||
Not Done Inline Actions(indeed according to Coding_Conventions) elexis: (indeed according to Coding_Conventions) | |||||
Not Done Inline Actionstrailing whitespace elexis: trailing whitespace | |||||
} | |||||
this.Activate(); | |||||
this.CheckVisionSharings(); | |||||
return this.spyId; | |||||
}; | |||||
VisionSharing.prototype.RemoveSpy = function(data) | |||||
{ | |||||
this.spies.delete(data.id); | |||||
this.CheckVisionSharings(); | |||||
}; | |||||
/** | |||||
Not Done Inline Actions/** * */ elexis: ```
/**
*
*/
``` | |||||
* Returns true if this entity share its vision with player | |||||
*/ | |||||
VisionSharing.prototype.ShareVisionWith = function(player) | |||||
{ | |||||
if (this.activated) | |||||
return this.shared.has(player); | |||||
let cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership); | |||||
return cmpOwnership && cmpOwnership.GetOwner() == player; | |||||
}; | |||||
Not Done Inline Actions(Apparently the usual cases (defeat, ownership change, diplomacy change) that have often caused trouble with various components are covered, good) elexis: (Apparently the usual cases (defeat, ownership change, diplomacy change) that have often caused… | |||||
Engine.RegisterComponentType(IID_VisionSharing, "VisionSharing", VisionSharing); | Engine.RegisterComponentType(IID_VisionSharing, "VisionSharing", VisionSharing); |
Should state something when it's a permanent spy