Index: ps/trunk/binaries/data/mods/public/simulation/components/StatusBars.js =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/components/StatusBars.js (revision 19450) +++ ps/trunk/binaries/data/mods/public/simulation/components/StatusBars.js (revision 19451) @@ -1,273 +1,275 @@ const NATURAL_COLOR = "255 255 255 255"; // pure white function StatusBars() {} StatusBars.prototype.Schema = "" + "" + "" + "" + "" + "" + "" + "" + ""; /** * For every sprite, the code will call their "Add" method when regenerating * the sprites. Every sprite adder should return the height it needs. * * Modders who need extra sprites can just modify this array, and * provide the right methods. */ StatusBars.prototype.Sprites = [ "PackBar", "ResourceSupplyBar", "CaptureBar", "HealthBar", "AuraIcons", ]; StatusBars.prototype.Init = function() { this.enabled = false; this.auraSources = new Map(); }; /** * Don't serialise this.enabled since it's modified by the GUI */ StatusBars.prototype.Serialize = function() { return {"auraSources": this.auraSources}; }; StatusBars.prototype.Deserialize = function(data) { this.Init(); this.auraSources = data.auraSources; }; StatusBars.prototype.SetEnabled = function(enabled) { // Quick return if no change if (enabled == this.enabled) return; this.enabled = enabled; // Update the displayed sprites this.RegenerateSprites(); }; StatusBars.prototype.AddAuraSource = function(source, auraName) { if (this.auraSources.has(source)) this.auraSources.get(source).push(auraName); else this.auraSources.set(source, [auraName]); this.RegenerateSprites(); }; StatusBars.prototype.RemoveAuraSource = function(source, auraName) { let names = this.auraSources.get(source); names.splice(names.indexOf(auraName), 1); this.RegenerateSprites(); }; StatusBars.prototype.OnHealthChanged = function(msg) { if (this.enabled) this.RegenerateSprites(); }; StatusBars.prototype.OnCapturePointsChanged = function(msg) { if (this.enabled) this.RegenerateSprites(); }; StatusBars.prototype.OnResourceSupplyChanged = function(msg) { if (this.enabled) this.RegenerateSprites(); }; StatusBars.prototype.OnPackProgressUpdate = function(msg) { if (this.enabled) this.RegenerateSprites(); }; StatusBars.prototype.RegenerateSprites = function() { let cmpOverlayRenderer = Engine.QueryInterface(this.entity, IID_OverlayRenderer); cmpOverlayRenderer.Reset(); let yoffset = 0; for (let sprite of this.Sprites) yoffset += this["Add"+sprite](cmpOverlayRenderer, yoffset); }; // Internal helper functions /** * Generic piece of code to add a bar */ StatusBars.prototype.AddBar = function(cmpOverlayRenderer, yoffset, type, amount) { // Size of health bar (in world-space units) let width = +this.template.BarWidth; let height = +this.template.BarHeight; // World-space offset from the unit's position let offset = { "x": 0, "y": +this.template.HeightOffset, "z": 0 }; // background cmpOverlayRenderer.AddSprite( "art/textures/ui/session/icons/"+type+"_bg.png", { "x": -width/2, "y": yoffset }, { "x": width/2, "y": height + yoffset}, offset, NATURAL_COLOR ); // foreground cmpOverlayRenderer.AddSprite( "art/textures/ui/session/icons/"+type+"_fg.png", { "x": -width/2, "y": yoffset}, { "x": width*(amount - 0.5), "y": height + yoffset}, offset, NATURAL_COLOR ); return height * 1.2; }; StatusBars.prototype.AddPackBar = function(cmpOverlayRenderer, yoffset) { if (!this.enabled) return 0; let cmpPack = Engine.QueryInterface(this.entity, IID_Pack); if (!cmpPack || !cmpPack.IsPacking()) return 0; return this.AddBar(cmpOverlayRenderer, yoffset, "pack", cmpPack.GetProgress()); }; StatusBars.prototype.AddHealthBar = function(cmpOverlayRenderer, yoffset) { if (!this.enabled) return 0; let cmpHealth = QueryMiragedInterface(this.entity, IID_Health); if (!cmpHealth || !cmpHealth.GetHitpoints() > 0) return 0; return this.AddBar(cmpOverlayRenderer, yoffset, "health", cmpHealth.GetHitpoints() / cmpHealth.GetMaxHitpoints()); }; StatusBars.prototype.AddResourceSupplyBar = function(cmpOverlayRenderer, yoffset) { if (!this.enabled) return 0; let cmpResourceSupply = QueryMiragedInterface(this.entity, IID_ResourceSupply); if (!cmpResourceSupply) return 0; let value = cmpResourceSupply.IsInfinite() ? 1 : cmpResourceSupply.GetCurrentAmount() / cmpResourceSupply.GetMaxAmount(); return this.AddBar(cmpOverlayRenderer, yoffset, "supply", value); }; StatusBars.prototype.AddCaptureBar = function(cmpOverlayRenderer, yoffset) { if (!this.enabled) return 0; let cmpCapturable = QueryMiragedInterface(this.entity, IID_Capturable); if (!cmpCapturable) return 0; let cmpOwnership = QueryMiragedInterface(this.entity, IID_Ownership); if (!cmpOwnership) return 0; let owner = cmpOwnership.GetOwner(); + if (owner == -1) + return 0; let cp = cmpCapturable.GetCapturePoints(); // Size of health bar (in world-space units) let width = +this.template.BarWidth; let height = +this.template.BarHeight; // World-space offset from the unit's position let offset = { "x": 0, "y": +this.template.HeightOffset, "z": 0 }; let setCaptureBarPart = function(playerID, startSize) { let c = QueryPlayerIDInterface(playerID).GetColor(); let strColor = (c.r * 255) + " " + (c.g * 255) + " " + (c.b * 255) + " 255"; let size = width * cp[playerID] / cmpCapturable.GetMaxCapturePoints(); cmpOverlayRenderer.AddSprite( "art/textures/ui/session/icons/capture_bar.png", { "x": startSize, "y": yoffset }, { "x": startSize + size, "y": height + yoffset}, offset, strColor ); return size + startSize; }; // first handle the owner's points, to keep those points on the left for clarity let size = setCaptureBarPart(owner, -width / 2); for (let i in cp) if (i != owner && cp[i] > 0) size = setCaptureBarPart(i, size); return height * 1.2; }; StatusBars.prototype.AddAuraIcons = function(cmpOverlayRenderer, yoffset) { let cmpGuiInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface); let sources = cmpGuiInterface.GetEntitiesWithStatusBars().filter(e => this.auraSources.has(e) && this.auraSources.get(e).length); if (!sources.length) return 0; let iconSet = new Set(); for (let ent of sources) { let cmpAuras = Engine.QueryInterface(ent, IID_Auras); if (!cmpAuras) // probably the ent just died continue; for (let name of this.auraSources.get(ent)) iconSet.add(cmpAuras.GetOverlayIcon(name)); } // World-space offset from the unit's position let offset = { "x": 0, "y": +this.template.HeightOffset + yoffset, "z": 0 }; let iconSize = +this.template.BarWidth / 2; let xoffset = -iconSize * (iconSet.size - 1) * 0.6; for (let icon of iconSet) { cmpOverlayRenderer.AddSprite( icon, { "x": xoffset - iconSize/2, "y": yoffset }, { "x": xoffset + iconSize/2, "y": iconSize + yoffset }, offset, NATURAL_COLOR ); xoffset += iconSize * 1.2; } return iconSize + this.template.BarHeight / 2; }; Engine.RegisterComponentType(IID_StatusBars, "StatusBars", StatusBars);