Update healer tooltips to also show up in the selection details with actual values from the simulation. Based on patch by fatherbushido, fixes #4026.

Also clean up the Health component.
Rename healer to heal (as that is the actual component name).
Remove the structure tree code to replace a proper Templates.js
implementation.

This was SVN commit r18464.
This commit is contained in:
elexis 2016-07-01 13:32:34 +00:00
parent bb69a6fb86
commit 9d20881ef4
9 changed files with 57 additions and 47 deletions

View file

@ -224,6 +224,13 @@ function GetTemplateDataHelper(template, player, auraTemplates)
ret.garrisonHolder.max = getEntityValue("GarrisonHolder/Max");
}
if (template.Heal)
ret.heal = {
"hp": getEntityValue("Heal/HP"),
"range": getEntityValue("Heal/Range"),
"rate": getEntityValue("Heal/Rate")
};
if (template.Obstruction)
{
ret.obstruction = {

View file

@ -460,25 +460,29 @@ function getSpeedTooltip(template)
function getHealerTooltip(template)
{
if (!template.healer)
if (!template.heal)
return "";
let hp = +(template.heal.hp.toFixed(1));
let range = +(template.heal.range.toFixed(0));
let rate = +((template.heal.rate / 1000).toFixed(1));
return [
sprintf(translatePlural("%(label)s %(val)s %(unit)s", "%(label)s %(val)s %(unit)s", template.healer.HP), {
sprintf(translatePlural("%(label)s %(val)s %(unit)s", "%(label)s %(val)s %(unit)s", hp), {
"label": headerFont(translate("Heal:")),
"val": template.healer.HP,
"val": hp,
// Translation: Short for hit points (or health points) that are healed in one healing action
"unit": unitFont(translatePlural("HP", "HP", template.healer.HP))
"unit": unitFont(translatePlural("HP", "HP", hp))
}),
sprintf(translatePlural("%(label)s %(val)s %(unit)s", "%(label)s %(val)s %(unit)s", template.healer.Range), {
sprintf(translatePlural("%(label)s %(val)s %(unit)s", "%(label)s %(val)s %(unit)s", range), {
"label": headerFont(translate("Range:")),
"val": template.healer.Range,
"unit": unitFont(translatePlural("meter", "meters", template.healer.Range))
"val": range,
"unit": unitFont(translatePlural("meter", "meters", range))
}),
sprintf(translatePlural("%(label)s %(val)s %(unit)s", "%(label)s %(val)s %(unit)s", template.healer.Rate/1000), {
sprintf(translatePlural("%(label)s %(val)s %(unit)s", "%(label)s %(val)s %(unit)s", rate), {
"label": headerFont(translate("Rate:")),
"val": template.healer.Rate/1000,
"unit": unitFont(translatePlural("second", "seconds", template.healer.Rate / 1000))
"val": rate,
"unit": unitFont(translatePlural("second", "seconds", rate))
})
].join(translate(", "));
}

View file

@ -284,6 +284,7 @@ function displaySingle(entState)
Engine.GetGUIObjectByName("attackAndArmorStats").tooltip = [
getAttackTooltip,
getHealerTooltip,
getArmorTooltip,
getRepairRateTooltip,
getBuildRateTooltip,

View file

@ -1006,6 +1006,7 @@ g_SelectionPanels.Training = {
tooltips.push(
getHealthTooltip(template),
getAttackTooltip(template),
getHealerTooltip(template),
getArmorTooltip(template),
getGarrisonTooltip(template),
getProjectilesTooltip(template),

View file

@ -228,17 +228,17 @@ var unitActions =
},
"getActionInfo": function(entState, targetState)
{
if (!entState.healer ||
if (!entState.heal ||
!hasClass(targetState, "Unit") || !targetState.needsHeal ||
!playerCheck(entState, targetState, ["Player", "Ally"]) ||
entState.id == targetState.id) // Healers can't heal themselves.
return false;
let unhealableClasses = entState.healer.unhealableClasses;
let unhealableClasses = entState.heal.unhealableClasses;
if (MatchesClassList(targetState.identity.classes, unhealableClasses))
return false;
let healableClasses = entState.healer.healableClasses;
let healableClasses = entState.heal.healableClasses;
if (!MatchesClassList(targetState.identity.classes, healableClasses))
return false;

View file

@ -80,13 +80,6 @@ function loadUnit(templateName)
}
}
if (template.Heal)
unit.healer = {
"Range": +template.Heal.Range || 0,
"HP": +template.Heal.HP || 0,
"Rate": +template.Heal.Rate || 0
};
if (template.Builder && template.Builder.Entities._string)
for (let build of template.Builder.Entities._string.split(" "))
{

View file

@ -545,7 +545,10 @@ GuiInterface.prototype.GetExtendedEntityState = function(player, ent)
let cmpHeal = Engine.QueryInterface(ent, IID_Heal);
if (cmpHeal)
ret.healer = {
ret.heal = {
"hp": cmpHeal.GetHP(),
"range": cmpHeal.GetRange().max,
"rate": cmpHeal.GetRate(),
"unhealableClasses": cmpHeal.GetUnhealableClasses(),
"healableClasses": cmpHeal.GetHealableClasses(),
};

View file

@ -1,6 +1,6 @@
function Heal() {}
Heal.prototype.Schema =
Heal.prototype.Schema =
"<a:help>Controls the healing abilities of the unit.</a:help>" +
"<a:example>" +
"<Range>20</Range>" +
@ -39,22 +39,28 @@ Heal.prototype.Serialize = null; // we have no dynamic state to save
Heal.prototype.GetTimers = function()
{
var prepare = 1000;
var repeat = +this.template.Rate;
return {
"prepare": 1000,
"repeat": GetRate()
};
};
repeat = ApplyValueModificationsToEntity("Heal/Rate", repeat, this.entity);
return { "prepare": prepare, "repeat": repeat };
Heal.prototype.GetHP = function()
{
return ApplyValueModificationsToEntity("Heal/HP", +this.template.HP, this.entity);
};
Heal.prototype.GetRate = function()
{
return ApplyValueModificationsToEntity("Heal/Rate", +this.template.Rate, this.entity);
};
Heal.prototype.GetRange = function()
{
var min = 0;
var max = +this.template.Range;
max = ApplyValueModificationsToEntity("Heal/Range", max, this.entity);
return { "max": max, "min": min };
return {
"min": 0,
"max": ApplyValueModificationsToEntity("Heal/Range", +this.template.Range, this.entity)
};
};
Heal.prototype.GetUnhealableClasses = function()
@ -68,25 +74,25 @@ Heal.prototype.GetHealableClasses = function()
};
/**
* Heal the target entity. This should only be called after a successful range
* check, and should only be called after GetTimers().repeat msec has passed
* Heal the target entity. This should only be called after a successful range
* check, and should only be called after GetTimers().repeat msec has passed
* since the last call to PerformHeal.
*/
Heal.prototype.PerformHeal = function(target)
{
var cmpHealth = Engine.QueryInterface(target, IID_Health);
let cmpHealth = Engine.QueryInterface(target, IID_Health);
if (!cmpHealth)
return;
var targetState = cmpHealth.Increase(ApplyValueModificationsToEntity("Heal/HP", +this.template.HP, this.entity));
let targetState = cmpHealth.Increase(GetHP());
// Add XP
var cmpLoot = Engine.QueryInterface(target, IID_Loot);
var cmpPromotion = Engine.QueryInterface(this.entity, IID_Promotion);
let cmpLoot = Engine.QueryInterface(target, IID_Loot);
let cmpPromotion = Engine.QueryInterface(this.entity, IID_Promotion);
if (targetState !== undefined && cmpLoot && cmpPromotion)
{
// HP healed * XP per HP
cmpPromotion.IncreaseXp((targetState.new-targetState.old)*(cmpLoot.GetXp()/cmpHealth.GetMaxHitpoints()));
cmpPromotion.IncreaseXp((targetState.new - targetState.old) / cmpHealth.GetMaxHitpoints() * cmpLoot.GetXp());
}
//TODO we need a sound file
// PlaySound("heal_impact", this.entity);
@ -94,16 +100,13 @@ Heal.prototype.PerformHeal = function(target)
Heal.prototype.OnValueModification = function(msg)
{
if (msg.component != "Heal")
if (msg.component != "Heal" || msg.valueNames.indexOf("Heal/Range") === -1)
return;
var cmpUnitAI = Engine.QueryInterface(this.entity, IID_UnitAI);
let cmpUnitAI = Engine.QueryInterface(this.entity, IID_UnitAI);
if (!cmpUnitAI)
return;
if (msg.valueNames.indexOf("Heal/Range") === -1)
return;
cmpUnitAI.UpdateRangeQueries();
};

View file

@ -31,8 +31,6 @@
<GenericName>Acharya Chanakya</GenericName>
<SpecificName>Acharya Chāṇakya</SpecificName>
<Icon>units/maur_hero_chanakya.png</Icon>
<Tooltip>Hero Special: "Healer" - Heal units at an accelerated rate.
Hero Special: "Philosopher" - Research 4 special technologies only available to Chanakya.</Tooltip>
<RequiredTechnology>phase_city</RequiredTechnology>
</Identity>
<Minimap>