Remove health component from relics.
Since relics ought to be undestroyable, a health component makes no sense. This makes that the Invulnerability-flag can be removed and relics can be captured again (after 0f91c5ac61#inline-5236). Differential Revision: D1268 Original patch by: @temple Reviewed by: @wraitii Comments by: @bb, @elexis Fixes #5007, #5847, 0f91c5ac61#inline-5236 This was SVN commit r24327.
This commit is contained in:
parent
40f3a967d9
commit
2e79c0a177
@ -159,6 +159,18 @@ function getCurrentHealthTooltip(entState, label)
|
||||
});
|
||||
}
|
||||
|
||||
function getCurrentCaptureTooltip(entState, label)
|
||||
{
|
||||
if (!entState.maxCapturePoints)
|
||||
return "";
|
||||
|
||||
return sprintf(translate("%(captureLabel)s %(current)s / %(max)s"), {
|
||||
"captureLabel": headerFont(label || translate("Capture points:")),
|
||||
"current": Math.round(entState.capturePoints[entState.player]),
|
||||
"max": Math.round(entState.maxCapturePoints)
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts an resistance level into the actual reduction percentage.
|
||||
*/
|
||||
@ -184,10 +196,10 @@ function getResistanceTooltip(template)
|
||||
if (template.resistance.ApplyStatus)
|
||||
details.push(getStatusEffectsResistanceTooltip(template.resistance.ApplyStatus));
|
||||
|
||||
return sprintf(translate("%(label)s\n%(details)s"), {
|
||||
return details.length ? sprintf(translate("%(label)s\n%(details)s"), {
|
||||
"label": headerFont(translate("Resistance:")),
|
||||
"details": g_Indent + details.join("\n" + g_Indent)
|
||||
});
|
||||
}) : "";
|
||||
}
|
||||
|
||||
function getDamageResistanceTooltip(resistanceTypeTemplate)
|
||||
|
@ -1,14 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<object name="panelEntityButtons" size="0 36 50 93">
|
||||
<object name="panelEntityButtons" size="2 38 50 93">
|
||||
<!-- Displays buttons for the most important units like heroes and relics -->
|
||||
<repeat count="19" var="n">
|
||||
<object name="panelEntityButton[n]" size="0 0 50 50" type="button" hidden="true" style="iconButton" tooltip_style="sessionToolTip">
|
||||
|
||||
<!-- Placeholders storing the position for the bars -->
|
||||
<object size="3 100%-5 100%-3 100%-2" name="panelEntitySectionPosTop[n]" hidden="true"/>
|
||||
<object size="3 100% 100%-3 100%+5" name="panelEntitySectionPosBottom[n]" hidden="true"/>
|
||||
|
||||
<object name="panelEntityBackground[n]" type="image" ghost="true" size="1 1 100%-1 100%-1"/>
|
||||
<object name="panelEntityImage[n]" size="5 5 100%-5 100%-5" type="image" ghost="true"/>
|
||||
<object name="panelEntityHitOverlay[n]" hidden="true" type="image" ghost="true" size="5 5 100%-5 100%-5"/>
|
||||
|
||||
<!-- Health bar -->
|
||||
<object size="3 100%-7 100%-3 100%-2" name="panelEntityHealthSection[n]" ghost="true">
|
||||
<object size="3 100%-5 100%-3 100%-2" name="panelEntityHealthSection[n]" ghost="true">
|
||||
<object size="0 0 100% 5" name="panelEntityHealth[n]" type="image" ghost="true">
|
||||
<object type="image" sprite="barBorder" ghost="true" size="-1 -1 100%+1 100%+1"/>
|
||||
<object type="image" sprite="healthBackground" ghost="true"/>
|
||||
@ -17,6 +22,17 @@
|
||||
</object>
|
||||
</object>
|
||||
|
||||
<!-- Capture bar -->
|
||||
<object size="3 100% 100%-3 100%+5" name="panelEntityCaptureSection[n]" ghost="true">
|
||||
<object size="0 0 100% 5" name="panelEntityCapture[n]" type="image" ghost="true">
|
||||
<object type="image" sprite="barBorder" ghost="true" size="-1 -1 100%+1 100%+1"/>
|
||||
<repeat count="9" var="m">
|
||||
<object type="image" ghost="true" name="panelEntityCaptureBar[n][m]" hidden="true"/>
|
||||
</repeat>
|
||||
<object type="image" sprite="statsBarShaderHorizontal" ghost="true"/>
|
||||
</object>
|
||||
</object>
|
||||
|
||||
</object>
|
||||
</repeat>
|
||||
</object>
|
||||
|
@ -1,6 +1,6 @@
|
||||
/**
|
||||
* This class sets up a shortcut to a specific entity in the GUI panel.
|
||||
* The button shows the portrait a tooltip with state information and a health bar.
|
||||
* The button shows the portrait a tooltip with state information and a health and/or capture bar.
|
||||
* Clicking the button selects and jumps to to the entity.
|
||||
*/
|
||||
class PanelEntity
|
||||
@ -9,6 +9,7 @@ class PanelEntity
|
||||
{
|
||||
this.selection = selection;
|
||||
this.hitpoints = undefined;
|
||||
this.capturePoints = undefined;
|
||||
|
||||
/**
|
||||
* Public property
|
||||
@ -22,6 +23,7 @@ class PanelEntity
|
||||
|
||||
this.overlayName = "panelEntityHitOverlay[" + buttonID + "]";
|
||||
this.panelEntityHealthBar = Engine.GetGUIObjectByName("panelEntityHealthBar[" + buttonID + "]");
|
||||
this.panelEntityCaptureBar = Engine.GetGUIObjectByName("panelEntityCapture[" + buttonID + "]");
|
||||
this.panelEntButton = Engine.GetGUIObjectByName("panelEntityButton[" + buttonID + "]");
|
||||
this.panelEntButton.onPress = this.onPress.bind(this);
|
||||
this.panelEntButton.onDoublePress = this.onDoublePress.bind(this);
|
||||
@ -31,6 +33,17 @@ class PanelEntity
|
||||
let template = GetTemplateData(entityState.template);
|
||||
this.nameTooltip = setStringTags(template.name.specific, this.NameTags) + "\n";
|
||||
|
||||
Engine.GetGUIObjectByName("panelEntityHealthSection[" + buttonID + "]").hidden = !entityState.hitpoints;
|
||||
|
||||
let captureSection = Engine.GetGUIObjectByName("panelEntityCaptureSection[" + buttonID + "]");
|
||||
captureSection.hidden = !entityState.capturePoints;
|
||||
if (entityState.capturePoints)
|
||||
{
|
||||
this.capturePoints = entityState.capturePoints;
|
||||
if (!entityState.hitpoints)
|
||||
captureSection.size = Engine.GetGUIObjectByName("panelEntitySectionPosTop[" + buttonID + "]").size;
|
||||
}
|
||||
|
||||
Engine.GetGUIObjectByName("panelEntityImage[" + buttonID + "]").sprite =
|
||||
"stretched:" + this.PortraitDirectory + template.icon;
|
||||
}
|
||||
@ -48,6 +61,18 @@ class PanelEntity
|
||||
setPanelObjectPosition(this.panelEntButton, i, Infinity);
|
||||
|
||||
let entityState = GetEntityState(this.entityID);
|
||||
this.updateHitpointsBar(entityState);
|
||||
this.updateCapturePointsBar(entityState);
|
||||
|
||||
this.panelEntButton.tooltip =
|
||||
this.nameTooltip +
|
||||
this.Tooltips.map(tooltip => tooltip(entityState)).filter(tip => tip).join("\n");
|
||||
}
|
||||
|
||||
updateHitpointsBar(entityState)
|
||||
{
|
||||
if (!entityState.hitpoints)
|
||||
return;
|
||||
|
||||
if (this.hitpoints != entityState.hitpoints)
|
||||
{
|
||||
@ -55,16 +80,44 @@ class PanelEntity
|
||||
size.rright = 100 * entityState.hitpoints / entityState.maxHitpoints;
|
||||
this.panelEntityHealthBar.size = size;
|
||||
}
|
||||
|
||||
this.panelEntButton.tooltip =
|
||||
this.nameTooltip +
|
||||
this.Tooltips.map(tooltip => tooltip(entityState)).filter(tip => tip).join("\n");
|
||||
|
||||
if (this.hitpoints > entityState.hitpoints)
|
||||
startColorFade(this.overlayName, 100, 0, colorFade_attackUnit, true, smoothColorFadeRestart_attackUnit);
|
||||
if (entityState.hitpoints < this.hitpoints)
|
||||
this.onAttacked();
|
||||
this.hitpoints = entityState.hitpoints;
|
||||
}
|
||||
|
||||
updateCapturePointsBar(entityState)
|
||||
{
|
||||
if (!entityState.capturePoints)
|
||||
return;
|
||||
|
||||
let playerParts = this.panelEntityCaptureBar.children;
|
||||
let setCaptureBarPart = function(player, startSize) {
|
||||
let captureBar = playerParts[player];
|
||||
let size = captureBar.size;
|
||||
size.rleft = startSize;
|
||||
size.rright = startSize + 100 * Math.max(0, Math.min(1, entityState.capturePoints[player] / entityState.maxCapturePoints));
|
||||
captureBar.size = size;
|
||||
captureBar.sprite = "color:" + g_DiplomacyColors.getPlayerColor(player, 128);
|
||||
captureBar.hidden = false;
|
||||
return size.rright;
|
||||
};
|
||||
|
||||
let size = setCaptureBarPart(entityState.player, 0);
|
||||
for (let i in entityState.capturePoints)
|
||||
if (i != entityState.player)
|
||||
size = setCaptureBarPart(i, size);
|
||||
|
||||
if (entityState.capturePoints[entityState.player] < this.capturePoints[entityState.player])
|
||||
this.onAttacked();
|
||||
|
||||
this.capturePoints = entityState.capturePoints;
|
||||
}
|
||||
|
||||
onAttacked()
|
||||
{
|
||||
startColorFade(this.overlayName, 100, 0, colorFade_attackUnit, true, smoothColorFadeRestart_attackUnit);
|
||||
}
|
||||
|
||||
onPress()
|
||||
{
|
||||
if (!Engine.HotkeyIsPressed("selection.add"))
|
||||
@ -85,6 +138,7 @@ PanelEntity.prototype.PortraitDirectory = "session/portraits/";
|
||||
|
||||
PanelEntity.prototype.Tooltips = [
|
||||
getCurrentHealthTooltip,
|
||||
getCurrentCaptureTooltip,
|
||||
getAttackTooltip,
|
||||
getResistanceTooltip,
|
||||
getEntityTooltip,
|
||||
|
@ -120,6 +120,7 @@ function displaySingle(entState)
|
||||
|
||||
let showHealth = entState.hitpoints;
|
||||
let showResource = entState.resourceSupply;
|
||||
let showCapture = entState.capturePoints;
|
||||
|
||||
let healthSection = Engine.GetGUIObjectByName("healthSection");
|
||||
let captureSection = Engine.GetGUIObjectByName("captureSection");
|
||||
@ -145,11 +146,13 @@ function displaySingle(entState)
|
||||
captureSection.size = showResource ? sectionPosMiddle.size : sectionPosBottom.size;
|
||||
resourceSection.size = showResource ? sectionPosBottom.size : sectionPosMiddle.size;
|
||||
}
|
||||
else
|
||||
else if (showResource)
|
||||
{
|
||||
captureSection.size = sectionPosBottom.size;
|
||||
resourceSection.size = sectionPosTop.size;
|
||||
}
|
||||
else if (showCapture)
|
||||
captureSection.size = sectionPosTop.size;
|
||||
|
||||
// CapturePoints
|
||||
captureSection.hidden = !entState.capturePoints;
|
||||
|
@ -155,7 +155,7 @@ var g_UnitActions =
|
||||
},
|
||||
"getActionInfo": function(entState, targetState)
|
||||
{
|
||||
if (!entState.attack || !targetState.hitpoints)
|
||||
if (!entState.attack || !targetState.capturePoints)
|
||||
return false;
|
||||
|
||||
return {
|
||||
|
@ -20,9 +20,6 @@ Trigger.prototype.InitCaptureTheRelic = function()
|
||||
{
|
||||
this.relics[i] = TriggerHelper.SpawnUnits(pickRandom(potentialSpawnPoints), catafalqueTemplates[i], 1, 0)[0];
|
||||
|
||||
let cmpResistance = Engine.QueryInterface(this.relics[i], IID_Resistance);
|
||||
cmpResistance.SetInvulnerability(true);
|
||||
|
||||
let cmpPositionRelic = Engine.QueryInterface(this.relics[i], IID_Position);
|
||||
cmpPositionRelic.SetYRotation(randomAngle());
|
||||
}
|
||||
|
@ -124,7 +124,7 @@ Resistance.prototype.GetFullResistance = function()
|
||||
Resistance.prototype.GetResistanceOfForm = function(entityForm)
|
||||
{
|
||||
let ret = {};
|
||||
let template = this.template[entityForm];
|
||||
let template = this.template && this.template[entityForm];
|
||||
if (!template)
|
||||
return ret;
|
||||
|
||||
|
@ -384,13 +384,7 @@ UnitAI.prototype.UnitFsmSpec = {
|
||||
},
|
||||
|
||||
"Order.Attack": function(msg) {
|
||||
if (!this.TargetIsAlive(this.order.data.target))
|
||||
{
|
||||
this.FinishOrder();
|
||||
return;
|
||||
}
|
||||
|
||||
var type = this.GetBestAttackAgainst(this.order.data.target, this.order.data.allowCapture);
|
||||
let type = this.GetBestAttackAgainst(this.order.data.target, this.order.data.allowCapture);
|
||||
if (!type)
|
||||
{
|
||||
// Oops, we can't attack at all
|
||||
@ -743,7 +737,7 @@ UnitAI.prototype.UnitFsmSpec = {
|
||||
|
||||
if (!this.CheckFormationTargetAttackRange(target))
|
||||
{
|
||||
if (this.TargetIsAlive(target) && this.CheckTargetVisible(target))
|
||||
if (this.CanAttack(target) && this.CheckTargetVisible(target))
|
||||
{
|
||||
this.SetNextState("COMBAT.APPROACHING");
|
||||
return;
|
||||
@ -882,7 +876,7 @@ UnitAI.prototype.UnitFsmSpec = {
|
||||
// TODO: on what should we base this range?
|
||||
if (!this.CheckTargetRangeExplicit(msg.data.target, 0, 10))
|
||||
{
|
||||
if (!this.TargetIsAlive(msg.data.target) || !this.CheckTargetVisible(msg.data.target))
|
||||
if (!this.CheckTargetVisible(msg.data.target))
|
||||
this.FinishOrder();
|
||||
else
|
||||
// Out of range; move there in formation
|
||||
@ -1135,7 +1129,7 @@ UnitAI.prototype.UnitFsmSpec = {
|
||||
let allowCapture = this.order.data.allowCapture;
|
||||
if (!this.CheckFormationTargetAttackRange(target))
|
||||
{
|
||||
if (this.TargetIsAlive(target) && this.CheckTargetVisible(target))
|
||||
if (this.CanAttack(target) && this.CheckTargetVisible(target))
|
||||
{
|
||||
this.SetNextState("COMBAT.APPROACHING");
|
||||
return true;
|
||||
@ -1157,7 +1151,7 @@ UnitAI.prototype.UnitFsmSpec = {
|
||||
let allowCapture = this.order.data.allowCapture;
|
||||
if (!this.CheckFormationTargetAttackRange(target))
|
||||
{
|
||||
if (this.TargetIsAlive(target) && this.CheckTargetVisible(target))
|
||||
if (this.CanAttack(target) && this.CheckTargetVisible(target))
|
||||
{
|
||||
this.SetNextState("COMBAT.APPROACHING");
|
||||
return;
|
||||
@ -1396,7 +1390,7 @@ UnitAI.prototype.UnitFsmSpec = {
|
||||
}
|
||||
// if we already are targeting another unit still alive, finish with it first
|
||||
if (this.order && (this.order.type == "WalkAndFight" || this.order.type == "Attack"))
|
||||
if (this.order.data.target != msg.data.attacker && this.TargetIsAlive(msg.data.attacker))
|
||||
if (this.order.data.target != msg.data.attacker && this.CanAttack(msg.data.attacker))
|
||||
return;
|
||||
|
||||
var cmpIdentity = Engine.QueryInterface(this.entity, IID_Identity);
|
||||
@ -1665,7 +1659,7 @@ UnitAI.prototype.UnitFsmSpec = {
|
||||
},
|
||||
|
||||
"Timer": function(msg) {
|
||||
if (!this.TargetIsAlive(this.isGuardOf))
|
||||
if (!this.ShouldGuard(this.isGuardOf))
|
||||
{
|
||||
this.FinishOrder();
|
||||
return;
|
||||
@ -1707,7 +1701,7 @@ UnitAI.prototype.UnitFsmSpec = {
|
||||
},
|
||||
|
||||
"Timer": function(msg) {
|
||||
if (!this.TargetIsAlive(this.isGuardOf))
|
||||
if (!this.ShouldGuard(this.isGuardOf))
|
||||
{
|
||||
this.FinishOrder();
|
||||
return;
|
||||
@ -5187,6 +5181,16 @@ UnitAI.prototype.Guard = function(target, queued)
|
||||
this.AddOrder("Guard", { "target": target, "force": false }, queued);
|
||||
};
|
||||
|
||||
/**
|
||||
* @return {boolean} - Whether it makes sense to guard the given entity.
|
||||
*/
|
||||
UnitAI.prototype.ShouldGuard = function(target)
|
||||
{
|
||||
return this.TargetIsAlive(target) ||
|
||||
Engine.QueryInterface(target, IID_Capturable) ||
|
||||
Engine.QueryInterface(target, IID_StatusEffectsReceiver);
|
||||
};
|
||||
|
||||
UnitAI.prototype.AddGuard = function(target)
|
||||
{
|
||||
if (!this.CanGuard())
|
||||
|
@ -10,6 +10,7 @@
|
||||
<Height>2.0</Height>
|
||||
<Square width="5.0" depth="12.0"/>
|
||||
</Footprint>
|
||||
<Health disable=""/>
|
||||
<Identity>
|
||||
<Classes datatype="tokens">-Organic -ConquestCritical</Classes>
|
||||
<VisibleClasses datatype="tokens">Relic</VisibleClasses>
|
||||
@ -26,6 +27,7 @@
|
||||
<Position>
|
||||
<Anchor>pitch-roll</Anchor>
|
||||
</Position>
|
||||
<Resistance replace=""/>
|
||||
<ResourceGatherer disable=""/>
|
||||
<Selectable>
|
||||
<Overlay>
|
||||
|
Loading…
Reference in New Issue
Block a user