Ticket #999: #999-2012-02-24.patch

File #999-2012-02-24.patch, 53.6 KB (added by leper, 12 years ago)

Work in progress.

  • 0ad/binaries/data/mods/public/simulation/helpers/Commands.js

     
    6666        });
    6767        break;
    6868
     69    case "heal":
     70        if (g_DebugCommands && !(IsOwnedByPlayer(player, cmd.target) || IsOwnedByAllyOfPlayer(player, cmd.target)))
     71        {
     72            // This check is for debugging only!
     73            warn("Invalid command: heal target is not owned by an ally of or player "+player+" itself: "+uneval(cmd));
     74        }
     75
     76        // See UnitAI.CanHeal for target checks
     77        var entities = FilterEntityList(cmd.entities, player, controlAllUnits);
     78        GetFormationUnitAIs(entities).forEach(function(cmpUnitAI) {
     79            cmpUnitAI.Heal(cmd.target, cmd.queued);
     80        });
     81        break;
     82
    6983    case "repair":
    7084        // This covers both repairing damaged buildings, and constructing unfinished foundations
    7185        if (g_DebugCommands && !IsOwnedByAllyOfPlayer(player, cmd.target))
  • 0ad/binaries/data/mods/public/simulation/components/GuiInterface.js

     
    264264        ret.barterMarket = { "prices": cmpBarter.GetPrices() };
    265265    }
    266266
     267    // Abilities
     268    var cmpHeal = Engine.QueryInterface(ent, IID_Heal);
     269    // Check if we have abilities
     270    if (cmpHeal || (cmpHeal && cmpPromotion))
     271        ret.Ability = [];
     272    if (cmpHeal)
     273    {
     274        ret.Ability.Healer = { "healableClasses": cmpHeal.GetHealableClasses() };
     275    }
     276
     277    // TODO remove this; This is just used to test/demonstrate the extensibility
     278    // of the Ability system
     279    // promoteAbility (just for healers)
     280    if (cmpPromotion && cmpHeal)
     281    {
     282        ret.Ability.Promote = true ;
     283    }
     284
    267285    var cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager);
    268286    ret.visibility = cmpRangeManager.GetLosVisibility(ent, player, false);
    269287
  • 0ad/binaries/data/mods/public/simulation/components/interfaces/Heal.js

     
     1Engine.RegisterInterface("Heal");
     2
     3//TODO register message type healed?
  • 0ad/binaries/data/mods/public/simulation/components/Health.js

     
    131131{
    132132    // If we're already dead, don't allow resurrection
    133133    if (this.hitpoints == 0)
    134         return;
     134        return false;
    135135
    136136    var old = this.hitpoints;
    137137    this.hitpoints = Math.min(this.hitpoints + amount, this.GetMaxHitpoints());
    138138
    139139    Engine.PostMessage(this.entity, MT_HealthChanged, { "from": old, "to": this.hitpoints });
     140    // We return the old and the actual hp
     141    return { "old": old, "new": this.hitpoints};
    140142};
    141143
    142144//// Private functions ////
  • 0ad/binaries/data/mods/public/simulation/components/Loot.js

     
    2121
    2222Loot.prototype.GetXp = function()
    2323{
    24     return this.template.xp;
     24    return +(this.template.xp || 0);
    2525};
    2626
    2727Loot.prototype.GetResources = function()
  • 0ad/binaries/data/mods/public/simulation/components/tests/test_GuiInterface.js

     
    55Engine.LoadComponentScript("interfaces/DamageReceiver.js");
    66Engine.LoadComponentScript("interfaces/Foundation.js");
    77Engine.LoadComponentScript("interfaces/GarrisonHolder.js");
     8Engine.LoadComponentScript("interfaces/Heal.js");
    89Engine.LoadComponentScript("interfaces/Health.js");
    910Engine.LoadComponentScript("interfaces/Promotion.js");
    1011Engine.LoadComponentScript("interfaces/RallyPoint.js");
  • 0ad/binaries/data/mods/public/simulation/components/UnitAI.js

    (this hunk was shorter than expected)  
    282282        // so abandon this attack order
    283283        this.FinishOrder();
    284284    },
     285
     286    "Order.Heal": function(msg) {
     287        // Check the target is alive
     288        if (!this.TargetIsAlive(this.order.data.target))
     289        {
     290            this.FinishOrder();
     291            return;
     292        }
     293
     294        // Check if the target is in range
     295        if (this.CheckTargetRange(this.order.data.target, IID_Heal))
     296        {
     297            this.StopMoving();
     298            this.SetNextState("INDIVIDUAL.HEAL.HEALING");
     299            return;
     300        }
     301
     302        // If we can't reach the target, but are standing ground,
     303        // then abandon this heal order
     304        if (this.GetStance().respondStandGround && !this.order.data.force)
     305        {
     306            this.FinishOrder();
     307            return;
     308        }
     309
     310        // Try to move within heal range
     311        if (this.MoveToTargetRange(this.order.data.target, IID_Heal))
     312        {
     313            // We've started walking to the given point
     314            this.SetNextState("INDIVIDUAL.HEAL.APPROACHING");
     315            return;
     316        }
     317
     318        // We can't reach the target, and can't move towards it,
     319        // so abandon this heal order
     320        this.FinishOrder();
     321    },
     322
    285323    "Order.Gather": function(msg) {
    286324       
    287325        // If the target is still alive, we need to kill it first
     
    402439            cmpFormation.Disband();
    403440        },
    404441
     442        "Order.Heal": function(msg) {
     443            // TODO: see notes in Order.Attack
     444            var cmpFormation = Engine.QueryInterface(this.entity, IID_Formation);
     445            cmpFormation.CallMemberFunction("Heal", [msg.data.target, false]);
     446            cmpFormation.Disband();
     447        },
     448
    405449        "Order.Repair": function(msg) {
    406450            // TODO: see notes in Order.Attack
    407451            var cmpFormation = Engine.QueryInterface(this.entity, IID_Formation);
     
    9951039            },
    9961040        },
    9971041
     1042        "HEAL": {
     1043            "EntityRenamed": function(msg) {
     1044                if (this.order.data.target == msg.entity)
     1045                    this.order.data.target = msg.newentity;
     1046            },
     1047
     1048            "Attacked": function(msg) {
     1049                // If we stand ground we will rather die than flee
     1050                if (!this.GetStance().respondStandGround)
     1051                    this.Flee(msg.data.attacker, false);
     1052            },
     1053
     1054            "APPROACHING": {
     1055                "enter": function () {
     1056                    this.SelectAnimation("move");
     1057                    this.StartTimer(1000, 1000);
     1058                },
     1059
     1060                "leave": function() {
     1061                    this.StopTimer();
     1062                },
     1063
     1064                "Timer": function(msg) {
     1065                    if (this.ShouldAbandonChase(this.order.data.target, this.order.data.force))
     1066                    {
     1067                        this.StopMoving();
     1068                        this.FinishOrder();
     1069
     1070                        // Return to our original position
     1071                        if (this.GetStance().respondHoldGround)
     1072                            this.WalkToHeldPosition();
     1073                    }
     1074                },
     1075
     1076                "MoveCompleted": function() {
     1077                    this.SetNextState("HEALING");
     1078                },
     1079
     1080                "Attacked": function(msg) {
     1081                    // If we stand ground we will rather die than flee
     1082                    if (!this.GetStance().respondStandGround)
     1083                        this.Flee(msg.data.attacker, false);
     1084                },
     1085            },
     1086
     1087            "HEALING": {
     1088                "enter": function() {
     1089                    var cmpHeal = Engine.QueryInterface(this.entity, IID_Heal);
     1090                    this.healTimers = cmpHeal.GetTimers();
     1091//                  this.SelectAnimation("heal", false, 1.0, "heal"); // TODO needs animation
     1092//                  this.SetAnimationSync(this.healTimers.prepare, this.healTimers.repeat);
     1093                    this.StartTimer(this.healTimers.prepare, this.healTimers.repeat);
     1094                    // TODO if .prepare is short, players can cheat by cycling heal/stop/heal
     1095                    // to beat the .repeat time; should enforce a minimum time
     1096                    // see comment in ATTACKING.enter
     1097                    this.FaceTowardsTarget(this.order.data.target);
     1098                },
     1099
     1100                "leave": function() {
     1101                    this.StopTimer();
     1102                },
     1103
     1104                "Timer": function(msg) {
     1105                    var target = this.order.data.target;
     1106                    // Check the target is still alive and healable
     1107                    if (this.TargetIsAlive(target) && this.CanHeal(target))
     1108                    {
     1109                        // Check if we can still reach the target
     1110                        if (this.CheckTargetRange(target, IID_Heal))
     1111                        {
     1112                            this.FaceTowardsTarget(target);
     1113                            var cmpHeal = Engine.QueryInterface(this.entity, IID_Heal);
     1114                            cmpHeal.PerformHeal(target);
     1115                            return;
     1116                        }
     1117                        // Can't reach it - try to chase after it
     1118                        if (this.ShouldChaseTargetedEntity(target, this.order.data.force))
     1119                        {
     1120                                if (this.MoveToTargetRange(target, IID_Heal))
     1121                            {
     1122                                this.SetNextState("HEAL.CHASING");
     1123                                return;
     1124                            }
     1125                        }
     1126                    }
     1127                    // Can't reach it, healed to max hp or doesn't exist any more - give up
     1128                    if (this.FinishOrder())
     1129                        return;
     1130
     1131                    // TODO implement autoheal next (like in ATTACK FindNewTargets())
     1132                    // needs FindNewHealTargets() and maybe a something like RespondToTargetedEntities() ; figure out how SortEntitiesByPriority is working
     1133//                  if (this.FindNewHealTargets())
     1134//                  return;
     1135
     1136                    // Return to our original position
     1137                    if (this.GetStance().respondHoldGround)
     1138                        this.WalkToHeldPosition();
     1139                },
     1140                "Attacked": function(msg) {
     1141                    // If we stand ground we will rather die than flee
     1142                    if (!this.GetStance().respondStandGround)
     1143                        this.Flee(msg.data.attacker, false);
     1144                },
     1145            },
     1146            "CHASING": {
     1147                "enter": function () {
     1148                    this.SelectAnimation("move");
     1149                    this.StartTimer(1000, 1000);
     1150                },
     1151
     1152                "leave": function () {
     1153                    this.StopTimer();
     1154                },
     1155                "Timer": function(msg) {
     1156                    if (this.ShouldAbandonChase(this.order.data.target, this.order.data.force))
     1157                    {
     1158                        this.StopMoving();
     1159                        this.FinishOrder();
     1160
     1161                        // Return to our original position
     1162                        if (this.GetStance().respondHoldGround)
     1163                            this.WalkToHeldPosition();
     1164                    }
     1165                },
     1166                "MoveCompleted": function () {
     1167                    this.SetNextState("HEALING");
     1168                },
     1169            }, 
     1170        },
     1171
    9981172        // Returning to dropsite
    9991173        "RETURNRESOURCE": {
    10001174            "APPROACHING": {
     
    17461920};
    17471921
    17481922/**
     1923 * Returns true if the target exists and the current hitpoints are at maximum.
     1924 */
     1925UnitAI.prototype.TargetIsAtMaxHitpoints = function(ent)
     1926{
     1927    var cmpHealth = Engine.QueryInterface(ent, IID_Health);
     1928    if(!cmpHealth)
     1929        return false;
     1930
     1931    return (cmpHealth.GetHitpoints() == cmpHealth.GetMaxHitpoints());
     1932};
     1933
     1934/**
    17491935 * Returns true if the target exists and needs to be killed before
    17501936 * beginning to gather resources from it.
    17511937 */
     
    22362422        case "Flee":
    22372423        case "LeaveFoundation":
    22382424        case "Attack":
     2425        case "Heal":
    22392426        case "Gather":
    22402427        case "ReturnResource":
    22412428        case "Repair":
     
    23592546    this.AddOrder("GatherNearPosition", { "type": type, "x": position[0], "z": position[1] }, queued);
    23602547}
    23612548
     2549UnitAI.prototype.Heal = function(target, queued)
     2550{
     2551    if (!this.CanHeal(target))
     2552    {
     2553        this.WalkToTarget(target, queued);
     2554        return;
     2555    }
     2556    // We don't want to chase units that leave our visibility -> force = false
     2557    this.AddOrder("Heal", { "target": target, "force": false }, queued);
     2558};
     2559
    23622560UnitAI.prototype.ReturnResource = function(target, queued)
    23632561{
    23642562    if (!this.CanReturnResource(target, true))
     
    25552753    return true;
    25562754};
    25572755
     2756UnitAI.prototype.CanHeal = function(target)
     2757{
     2758    // Formation controllers should always respond to commands
     2759    // (then the individual units can make up their own minds)
     2760    if (this.IsFormationController())
     2761        return true;
     2762
     2763    // Verify that we're able to respond to Heal commands
     2764    var cmpHeal = Engine.QueryInterface(this.entity, IID_Heal);
     2765    if (!cmpHeal)
     2766        return false;
     2767
     2768    // Verify that the target is alive
     2769    if (!this.TargetIsAlive(target))
     2770        return false;
     2771
     2772    // Verify that the target is owned by the same player as the entity
     2773    // or of an ally
     2774    var cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership);
     2775    if (!cmpOwnership || !(IsOwnedByPlayer(cmpOwnership.GetOwner(), target) || IsOwnedByAllyOfPlayer(cmpOwnership.GetOwner(), target)))
     2776        return false;
     2777
     2778    // Verify that the target is a healable class
     2779    // We could also use cmpIdentity.GetClassesList but this way is cleaner
     2780    var cmpIdentity = Engine.QueryInterface(target, IID_Identity);
     2781    if (!cmpIdentity)
     2782        return false;
     2783    var healable = false;
     2784    for each (var healableClass in cmpHeal.GetHealableClasses())
     2785    {
     2786        if (cmpIdentity.HasClass(healableClass) != -1)
     2787        {
     2788            healable = true;
     2789        }
     2790    }
     2791    if (!healable)
     2792        return false;
     2793
     2794    // Check that the target is not at MaxHealth
     2795    if (this.TargetIsAtMaxHitpoints(target))
     2796        return false;
     2797
     2798    return true;
     2799};
     2800
    25582801UnitAI.prototype.CanReturnResource = function(target, checkCarriedResource)
    25592802{
    25602803    // Formation controllers should always respond to commands
  • 0ad/binaries/data/mods/public/simulation/components/Heal.js

     
     1function Heal() {}
     2
     3Heal.prototype.Schema =
     4    "<a:help>Controls the healing abilities of the unit.</a:help>" +
     5    "<a:example>" +
     6        "<Range>20</Range>" +
     7        "<HP>5</HP>" +
     8        "<Rate>2000</Rate>" +
     9        "<HealableClasses datatype=\"tokens\">Support Infantry</HealableClasses>" +
     10    "</a:example>" +
     11    "<element name='Range' a:help='Range (in metres) where healing is possible'>" +
     12        "<ref name='nonNegativeDecimal'/>" +
     13    "</element>" +
     14    "<element name='HP' a:help='Hitpoints healed per Rate'>" +
     15        "<ref name='nonNegativeDecimal'/>" +
     16    "</element>" +
     17    "<element name='Rate' a:help='A heal is performed every Rate ms'>" +
     18        "<ref name='nonNegativeDecimal'/>" +
     19    "</element>" +
     20    "<element name='HealableClasses'>" +
     21        "<attribute name='datatype'>" +
     22            "<value>tokens</value>" +
     23        "</attribute>" +
     24        "<text/>" +
     25    "</element>";
     26
     27Heal.prototype.Init = function()
     28{
     29};
     30
     31Heal.prototype.Serialize = null; // we have no dynamic state to save
     32
     33Heal.prototype.GetTimers = function()
     34{
     35    var prepare = 1000;
     36    var repeat = +(this.template.Rate || 1000);
     37    return { "prepare": prepare, "repeat": repeat };
     38}
     39
     40Heal.prototype.GetRange = function()
     41{
     42    var max = +this.template.Range;
     43    var min = 0;
     44    return { "max": max, "min": min };
     45};
     46
     47Heal.prototype.GetHealableClasses = function()
     48{
     49    var classes = this.template.HealableClasses._string;
     50    return classes.split(/\s+/);
     51};
     52
     53/**
     54 * Heal the target entity. This should only be called after a successful range
     55 * check, and should only be called after GetTimers().repeat msec has passed
     56 * since the last call to PerformHeal.
     57 */
     58Heal.prototype.PerformHeal = function(target)
     59{
     60    this.CauseHeal({"target": target});
     61};
     62
     63/**
     64 * Heal target
     65 */
     66Heal.prototype.CauseHeal = function(data)
     67{
     68    var cmpHealth = Engine.QueryInterface(data.target, IID_Health);
     69    if (!cmpHealth)
     70        return;
     71    var targetState = cmpHealth.Increase(Math.max(0,this.template.HP));
     72
     73    // Add XP
     74    var cmpLoot = Engine.QueryInterface(data.target, IID_Loot);
     75    var cmpPromotion = Engine.QueryInterface(this.entity, IID_Promotion);
     76    if (targetState.old && targetState.new && cmpLoot && cmpPromotion)
     77    {
     78        // HP healed * XP per HP
     79        cmpPromotion.IncreaseXp((targetState.new-targetState.old)*(cmpLoot.GetXp()/cmpHealth.GetMaxHitpoints()));
     80    }
     81    //TODO add some Engine.PostMessage? - shouldn't be needed as Increase already posts a message
     82    //TODO we need a sound file
     83//  PlaySound("heal_impact", this.entity);
     84};
     85
     86Engine.RegisterComponentType(IID_Heal, "Heal", Heal);
  • 0ad/binaries/data/mods/public/simulation/templates/template_unit_support_healer.xml

     
    55    <Pierce>2.0</Pierce>
    66    <Crush>2.0</Crush>
    77  </Armour>
    8   <Auras>
     8<!--  <Auras>
    99    <Heal>
    1010      <Radius>20</Radius>
    1111      <Speed>2000</Speed>
    1212    </Heal>
    13   </Auras>
     13 </Auras>-->
     14  <Heal>
     15    <Range>30</Range>
     16    <HP>5</HP>
     17    <Rate>2000</Rate>
     18    <HealableClasses datatype="tokens">Support Infantry Cavalry</HealableClasses>
     19  </Heal>
    1420  <Cost>
    1521    <Resources>
    1622      <metal>120</metal>
     
    2329  <Identity>
    2430    <Classes datatype="tokens">Healer</Classes>
    2531    <GenericName>Healer</GenericName>
    26     <Tooltip>Heal units within his Aura. (Not implemented yet)</Tooltip>
     32    <Tooltip>Heal units.</Tooltip>
     33    <Rank>Basic</Rank>
    2734  </Identity>
     35  <Promotion>
     36    <RequiredXp>100</RequiredXp>
     37  </Promotion>
    2838  <Sound>
    2939    <SoundGroups>
    3040      <select>voice/hellenes/civ/civ_male_select.xml</select>
  • 0ad/binaries/data/mods/public/simulation/templates/template_structure_civic_temple.xml

     
    5757  </TerritoryInfluence>
    5858  <TrainingQueue>
    5959    <Entities datatype="tokens">
    60       units/{civ}_support_healer
     60      units/{civ}_support_healer_b
    6161    </Entities>
    6262  </TrainingQueue>
    6363  <Vision>
  • 0ad/binaries/data/mods/public/simulation/templates/units/hele_support_healer_a.xml

     
    11<?xml version="1.0" encoding="utf-8"?>
    2 <Entity parent="template_unit_support_healer">
     2<Entity parent="units/hele_support_healer_b">
    33  <Identity>
    4     <Civ>hele</Civ>
    5     <SpecificName>Hiereús</SpecificName>
    6     <History>The art of medicine was widely practised in Classical Greece. Hippocrates was the first physician to separate religion and superstition from actual medicine, and many others followed his lead.</History>
    7     <Icon>units/hele_support_healer.png</Icon>
     4    <Rank>Advanced</Rank>
    85  </Identity>
     6  <Promotion>
     7    <Entity>units/hele_support_healer_e</Entity>
     8  </Promotion>
    99  <VisualActor>
    1010    <Actor>units/hellenes/healer.xml</Actor>
    1111  </VisualActor>
  • 0ad/binaries/data/mods/public/simulation/templates/units/hele_support_healer_e.xml

     
    11<?xml version="1.0" encoding="utf-8"?>
    2 <Entity parent="template_unit_support_healer">
     2<Entity parent="units/hele_support_healer_a">
    33  <Identity>
    4     <Civ>hele</Civ>
    5     <SpecificName>Hiereús</SpecificName>
    6     <History>The art of medicine was widely practised in Classical Greece. Hippocrates was the first physician to separate religion and superstition from actual medicine, and many others followed his lead.</History>
    7     <Icon>units/hele_support_healer.png</Icon>
     4    <Rank>Elite</Rank>
    85  </Identity>
     6  <Promotion disable=""/>
    97  <VisualActor>
    108    <Actor>units/hellenes/healer.xml</Actor>
    119  </VisualActor>
  • 0ad/binaries/data/mods/public/simulation/templates/units/celt_support_healer_a.xml

     
    11<?xml version="1.0" encoding="utf-8"?>
    2 <Entity parent="template_unit_support_healer">
     2<Entity parent="units/celt_support_healer_b">
    33  <Identity>
    4     <Civ>celt</Civ>
    5     <SpecificName>Druides </SpecificName>
    6     <History>A druid may be one of many different professions; priest, historian, lawyer, judges, teachers, philosophers, poets, composers, musicians, astronomers, prophets, councillors, high craftsmen like a blacksmith, the classes of the 'men of art', and sometimes kings, chieftains, or other politicians. Druids were very hierarchal, with classes and ranks based on the length of their education and what fields they practiced. They learned their trades through mnemonics by way of poetry and songs, as writing was rarely used by Celts outside of prayers on votive objects, or lists of names for migratory records.</History>
    7     <Icon>units/celt_support_healer.png</Icon>
     4    <Rank>Advanced</Rank>
    85  </Identity>
     6  <Promotion>
     7    <Entity>units/celt_support_healer_e</Entity>
     8  </Promotion>
    99  <VisualActor>
    1010    <Actor>units/celts/healer.xml</Actor>
    1111  </VisualActor>
  • 0ad/binaries/data/mods/public/simulation/templates/units/celt_support_healer_e.xml

     
    11<?xml version="1.0" encoding="utf-8"?>
    2 <Entity parent="template_unit_support_healer">
     2<Entity parent="units/celt_support_healer_a">
    33  <Identity>
    4     <Civ>celt</Civ>
    5     <SpecificName>Druides </SpecificName>
    6     <History>A druid may be one of many different professions; priest, historian, lawyer, judges, teachers, philosophers, poets, composers, musicians, astronomers, prophets, councillors, high craftsmen like a blacksmith, the classes of the 'men of art', and sometimes kings, chieftains, or other politicians. Druids were very hierarchal, with classes and ranks based on the length of their education and what fields they practiced. They learned their trades through mnemonics by way of poetry and songs, as writing was rarely used by Celts outside of prayers on votive objects, or lists of names for migratory records.</History>
    7     <Icon>units/celt_support_healer.png</Icon>
     4    <Rank>Elite</Rank>
    85  </Identity>
     6  <Promotion disable=""/>
    97  <VisualActor>
    108    <Actor>units/celts/healer.xml</Actor>
    119  </VisualActor>
  • 0ad/binaries/data/mods/public/simulation/templates/units/celt_support_healer.xml

     
    1 <?xml version="1.0" encoding="utf-8"?>
    2 <Entity parent="template_unit_support_healer">
    3   <Identity>
    4     <Civ>celt</Civ>
    5     <SpecificName>Druides </SpecificName>
    6     <History>A druid may be one of many different professions; priest, historian, lawyer, judges, teachers, philosophers, poets, composers, musicians, astronomers, prophets, councillors, high craftsmen like a blacksmith, the classes of the 'men of art', and sometimes kings, chieftains, or other politicians. Druids were very hierarchal, with classes and ranks based on the length of their education and what fields they practiced. They learned their trades through mnemonics by way of poetry and songs, as writing was rarely used by Celts outside of prayers on votive objects, or lists of names for migratory records.</History>
    7     <Icon>units/celt_support_healer.png</Icon>
    8   </Identity>
    9   <VisualActor>
    10     <Actor>units/celts/healer.xml</Actor>
    11   </VisualActor>
    12 </Entity>
  • 0ad/binaries/data/mods/public/simulation/templates/units/hele_support_healer.xml

     
    1 <?xml version="1.0" encoding="utf-8"?>
    2 <Entity parent="template_unit_support_healer">
    3   <Identity>
    4     <Civ>hele</Civ>
    5     <SpecificName>Hiereús</SpecificName>
    6     <History>The art of medicine was widely practised in Classical Greece. Hippocrates was the first physician to separate religion and superstition from actual medicine, and many others followed his lead.</History>
    7     <Icon>units/hele_support_healer.png</Icon>
    8   </Identity>
    9   <VisualActor>
    10     <Actor>units/hellenes/healer.xml</Actor>
    11   </VisualActor>
    12 </Entity>
  • 0ad/binaries/data/mods/public/simulation/templates/units/iber_support_healer.xml

     
    1 <?xml version="1.0" encoding="utf-8"?>
    2 <Entity parent="template_unit_support_healer">
    3   <Identity>
    4     <Civ>iber</Civ>
    5     <SpecificName>Sacerdotisa de Ataekina</SpecificName>
    6     <History> To the best of our knowledge, only one 'temple'-like structure has been found on the Iberian Peninsula dating from the times and the Iberians worshiped their pantheon of gods at small home altars; however, a very special sculptured head and torso was found in a farmer's field around the turn of the 20th century of a personage who was obviously someone of great substance. As the two principal gods, of the many worshiped, were male Endovellikos and female Ataekina, we thought it would be nice to adopt The Lady of Elche as our priestess-healer representing Ataekina. We know from archelogy and the Romans that Ataekina was associated with spring, the changing of seasons, and nature in general. Ataekina also seems to have been associated with the cycle of birth-death-rebirth.</History>
    7     <Icon>units/iber_support_healer.png</Icon>
    8   </Identity>
    9   <VisualActor>
    10     <Actor>units/iberians/healer.xml</Actor>
    11   </VisualActor>
    12 </Entity>
  • 0ad/binaries/data/mods/public/simulation/templates/units/rome_support_healer.xml

     
    1 <?xml version="1.0" encoding="utf-8"?>
    2 <Entity parent="template_unit_support_healer">
    3   <Identity>
    4     <Civ>rome</Civ>
    5     <GenericName>State Priest</GenericName>
    6     <SpecificName>Pontifex Minoris</SpecificName>
    7     <History>During the Republic, the position of priest was elevated and required a lot of responsibilities, which is why priests were by no means chosen randomly. The position of Pontifex Maximus, the high priest of the Roman religion, was occupied by such prominent figures as Julius Caesar, Marcus Aemilius Lepidus and Augustus.</History>
    8     <Icon>units/rome_support_healer.png</Icon>
    9   </Identity>
    10   <VisualActor>
    11     <Actor>units/romans/healer.xml</Actor>
    12   </VisualActor>
    13 </Entity>
  • 0ad/binaries/data/mods/public/simulation/templates/units/pers_support_healer.xml

     
    1 <?xml version="1.0" encoding="utf-8"?>
    2 <Entity parent="template_unit_support_healer">
    3   <Identity>
    4     <Civ>hele</Civ>
    5     <GenericName>Median Magus</GenericName>
    6     <SpecificName>Maguš Mada</SpecificName>
    7     <History>Under both the Medes and later the Persian the tribe of the Magi or the Magians were the masters of religious and oral tradition, comparable to the Levites of the Bible. They were connected to Zoroastrianism, but likely tended to other Iranian cults as well. Aside from religious duties the Magians also functioned as the Great King's bureaucrats and kept his administration running.</History>
    8     <Icon>units/pers_support_healer.png</Icon>
    9   </Identity>
    10   <VisualActor>
    11     <Actor>units/persians/healer.xml</Actor>
    12   </VisualActor>
    13 </Entity>
  • 0ad/binaries/data/mods/public/simulation/templates/units/iber_support_healer_a.xml

     
    11<?xml version="1.0" encoding="utf-8"?>
    2 <Entity parent="template_unit_support_healer">
     2<Entity parent="units/iber_support_healer_b">
    33  <Identity>
    4     <Civ>iber</Civ>
    5     <SpecificName>Sacerdotisa de Ataekina</SpecificName>
    6     <History> To the best of our knowledge, only one 'temple'-like structure has been found on the Iberian Peninsula dating from the times and the Iberians worshiped their pantheon of gods at small home altars; however, a very special sculptured head and torso was found in a farmer's field around the turn of the 20th century of a personage who was obviously someone of great substance. As the two principal gods, of the many worshiped, were male Endovellikos and female Ataekina, we thought it would be nice to adopt The Lady of Elche as our priestess-healer representing Ataekina. We know from archelogy and the Romans that Ataekina was associated with spring, the changing of seasons, and nature in general. Ataekina also seems to have been associated with the cycle of birth-death-rebirth.</History>
    7     <Icon>units/iber_support_healer.png</Icon>
     4    <Rank>Advanced</Rank>
    85  </Identity>
     6  <Promotion>
     7    <Entity>units/iber_support_healer_e</Entity>
     8  </Promotion>
    99  <VisualActor>
    1010    <Actor>units/iberians/healer.xml</Actor>
    1111  </VisualActor>
  • 0ad/binaries/data/mods/public/simulation/templates/units/iber_support_healer_e.xml

     
    11<?xml version="1.0" encoding="utf-8"?>
    2 <Entity parent="template_unit_support_healer">
     2<Entity parent="units/iber_support_healer_a">
    33  <Identity>
    4     <Civ>iber</Civ>
    5     <SpecificName>Sacerdotisa de Ataekina</SpecificName>
    6     <History> To the best of our knowledge, only one 'temple'-like structure has been found on the Iberian Peninsula dating from the times and the Iberians worshiped their pantheon of gods at small home altars; however, a very special sculptured head and torso was found in a farmer's field around the turn of the 20th century of a personage who was obviously someone of great substance. As the two principal gods, of the many worshiped, were male Endovellikos and female Ataekina, we thought it would be nice to adopt The Lady of Elche as our priestess-healer representing Ataekina. We know from archelogy and the Romans that Ataekina was associated with spring, the changing of seasons, and nature in general. Ataekina also seems to have been associated with the cycle of birth-death-rebirth.</History>
    7     <Icon>units/iber_support_healer.png</Icon>
     4    <Rank>Elite</Rank>
    85  </Identity>
     6  <Promotion disable=""/>
    97  <VisualActor>
    108    <Actor>units/iberians/healer.xml</Actor>
    119  </VisualActor>
  • 0ad/binaries/data/mods/public/simulation/templates/units/cart_support_healer.xml

     
    1 <?xml version="1.0" encoding="utf-8"?>
    2 <Entity parent="template_unit_support_healer">
    3   <Identity>
    4     <Civ>cart</Civ>
    5     <SpecificName>Kehinit</SpecificName>
    6     <History>Tanit (also spelled TINITH, TINNIT, or TINT), chief goddess of Carthage, equivalent of Astarte. Although she seems to have had some connection with the heavens, she was also a mother goddess, and fertility symbols often accompany representations of her. She was probably the consort of Baal Hammon (or Amon), the chief god of Carthage, and was often given the attribute "face of Baal." Although Tanit did not appear at Carthage before the 5th century BC, she soon eclipsed the more established cult of Baal Hammon and, in the Carthaginian area at least, was frequently listed before him on the monuments. In the worship of Tanit and Baal Hammon, children, probably firstborn, were sacrificed. Ample evidence of the practice has been found west of Carthage in the precinct of Tanit, where a tofet (a sanctuary for the sacrifice of children) was discovered. Tanit was also worshipped on Malta, Sardinia, and in Spain. There is no other reason for giving the Carthaginians a priestess instead of a priest in 0 A.D., although Tanit was the most popular of their two main gods with the people. </History>
    7     <Tooltip>Heal units within her aura. (Not implemented yet)</Tooltip>
    8     <Icon>units/cart_support_healer.png</Icon>
    9   </Identity>
    10   <VisualActor>
    11     <Actor>units/carthaginians/healer.xml</Actor>
    12   </VisualActor>
    13 </Entity>
  • 0ad/binaries/data/mods/public/simulation/templates/units/pers_support_healer_a.xml

     
    11<?xml version="1.0" encoding="utf-8"?>
    2 <Entity parent="template_unit_support_healer">
     2<Entity parent="units/pers_support_healer_b">
    33  <Identity>
    4     <Civ>hele</Civ>
    5     <GenericName>Median Magus</GenericName>
    6     <SpecificName>Maguš Mada</SpecificName>
    7     <History>Under both the Medes and later the Persian the tribe of the Magi or the Magians were the masters of religious and oral tradition, comparable to the Levites of the Bible. They were connected to Zoroastrianism, but likely tended to other Iranian cults as well. Aside from religious duties the Magians also functioned as the Great King's bureaucrats and kept his administration running.</History>
    8     <Icon>units/pers_support_healer.png</Icon>
     4    <Rank>Advanced</Rank>
    95  </Identity>
     6  <Promotion>
     7    <Entity>units/pers_support_healer_e</Entity>
     8  </Promotion>
    109  <VisualActor>
    1110    <Actor>units/persians/healer.xml</Actor>
    1211  </VisualActor>
  • 0ad/binaries/data/mods/public/simulation/templates/units/pers_support_healer_e.xml

     
    11<?xml version="1.0" encoding="utf-8"?>
    2 <Entity parent="template_unit_support_healer">
     2<Entity parent="units/pers_support_healer_a">
    33  <Identity>
    4     <Civ>hele</Civ>
    5     <GenericName>Median Magus</GenericName>
    6     <SpecificName>Maguš Mada</SpecificName>
    7     <History>Under both the Medes and later the Persian the tribe of the Magi or the Magians were the masters of religious and oral tradition, comparable to the Levites of the Bible. They were connected to Zoroastrianism, but likely tended to other Iranian cults as well. Aside from religious duties the Magians also functioned as the Great King's bureaucrats and kept his administration running.</History>
    8     <Icon>units/pers_support_healer.png</Icon>
     4    <Rank>Elite</Rank>
    95  </Identity>
     6  <Promotion disable=""/>
    107  <VisualActor>
    118    <Actor>units/persians/healer.xml</Actor>
    129  </VisualActor>
  • 0ad/binaries/data/mods/public/simulation/templates/units/cart_support_healer_a.xml

     
    11<?xml version="1.0" encoding="utf-8"?>
    2 <Entity parent="template_unit_support_healer">
     2<Entity parent="units/cart_support_healer_b">
    33  <Identity>
    4     <Civ>cart</Civ>
    5     <SpecificName>Kehinit</SpecificName>
    6     <History>Tanit (also spelled TINITH, TINNIT, or TINT), chief goddess of Carthage, equivalent of Astarte. Although she seems to have had some connection with the heavens, she was also a mother goddess, and fertility symbols often accompany representations of her. She was probably the consort of Baal Hammon (or Amon), the chief god of Carthage, and was often given the attribute "face of Baal." Although Tanit did not appear at Carthage before the 5th century BC, she soon eclipsed the more established cult of Baal Hammon and, in the Carthaginian area at least, was frequently listed before him on the monuments. In the worship of Tanit and Baal Hammon, children, probably firstborn, were sacrificed. Ample evidence of the practice has been found west of Carthage in the precinct of Tanit, where a tofet (a sanctuary for the sacrifice of children) was discovered. Tanit was also worshipped on Malta, Sardinia, and in Spain. There is no other reason for giving the Carthaginians a priestess instead of a priest in 0 A.D., although Tanit was the most popular of their two main gods with the people. </History>
    7     <Tooltip>Heal units within her aura. (Not implemented yet)</Tooltip>
    8     <Icon>units/cart_support_healer.png</Icon>
     4    <Rank>Advanced</Rank>
    95  </Identity>
     6  <Promotion>
     7    <Entity>units/cart_support_healer_e</Entity>
     8  </Promotion>
    109  <VisualActor>
    1110    <Actor>units/carthaginians/healer.xml</Actor>
    1211  </VisualActor>
  • 0ad/binaries/data/mods/public/simulation/templates/units/cart_support_healer_e.xml

     
    11<?xml version="1.0" encoding="utf-8"?>
    2 <Entity parent="template_unit_support_healer">
     2<Entity parent="units/cart_support_healer_a">
    33  <Identity>
    4     <Civ>cart</Civ>
    5     <SpecificName>Kehinit</SpecificName>
    6     <History>Tanit (also spelled TINITH, TINNIT, or TINT), chief goddess of Carthage, equivalent of Astarte. Although she seems to have had some connection with the heavens, she was also a mother goddess, and fertility symbols often accompany representations of her. She was probably the consort of Baal Hammon (or Amon), the chief god of Carthage, and was often given the attribute "face of Baal." Although Tanit did not appear at Carthage before the 5th century BC, she soon eclipsed the more established cult of Baal Hammon and, in the Carthaginian area at least, was frequently listed before him on the monuments. In the worship of Tanit and Baal Hammon, children, probably firstborn, were sacrificed. Ample evidence of the practice has been found west of Carthage in the precinct of Tanit, where a tofet (a sanctuary for the sacrifice of children) was discovered. Tanit was also worshipped on Malta, Sardinia, and in Spain. There is no other reason for giving the Carthaginians a priestess instead of a priest in 0 A.D., although Tanit was the most popular of their two main gods with the people. </History>
    7     <Tooltip>Heal units within her aura. (Not implemented yet)</Tooltip>
    8     <Icon>units/cart_support_healer.png</Icon>
     4    <Rank>Elite</Rank>
    95  </Identity>
     6  <Promotion disable=""/>
    107  <VisualActor>
    118    <Actor>units/carthaginians/healer.xml</Actor>
    129  </VisualActor>
  • 0ad/binaries/data/mods/public/simulation/templates/units/rome_support_healer_a.xml

     
    11<?xml version="1.0" encoding="utf-8"?>
    2 <Entity parent="template_unit_support_healer">
     2<Entity parent="units/rome_support_healer_b">
    33  <Identity>
    4     <Civ>rome</Civ>
    5     <GenericName>State Priest</GenericName>
    6     <SpecificName>Pontifex Minoris</SpecificName>
    7     <History>During the Republic, the position of priest was elevated and required a lot of responsibilities, which is why priests were by no means chosen randomly. The position of Pontifex Maximus, the high priest of the Roman religion, was occupied by such prominent figures as Julius Caesar, Marcus Aemilius Lepidus and Augustus.</History>
    8     <Icon>units/rome_support_healer.png</Icon>
     4    <Rank>Advanced</Rank>
    95  </Identity>
     6  <Promotion>
     7    <Entity>units/rome_support_healer_e</Entity>
     8  </Promotion>
    109  <VisualActor>
    1110    <Actor>units/romans/healer.xml</Actor>
    1211  </VisualActor>
  • 0ad/binaries/data/mods/public/simulation/templates/units/rome_support_healer_e.xml

     
    11<?xml version="1.0" encoding="utf-8"?>
    2 <Entity parent="template_unit_support_healer">
     2<Entity parent="units/rome_support_healer_a">
    33  <Identity>
    4     <Civ>rome</Civ>
    5     <GenericName>State Priest</GenericName>
    6     <SpecificName>Pontifex Minoris</SpecificName>
    7     <History>During the Republic, the position of priest was elevated and required a lot of responsibilities, which is why priests were by no means chosen randomly. The position of Pontifex Maximus, the high priest of the Roman religion, was occupied by such prominent figures as Julius Caesar, Marcus Aemilius Lepidus and Augustus.</History>
    8     <Icon>units/rome_support_healer.png</Icon>
     4    <Rank>Elite</Rank>
    95  </Identity>
     6  <Promotion disable=""/>
    107  <VisualActor>
    118    <Actor>units/romans/healer.xml</Actor>
    129  </VisualActor>
  • 0ad/binaries/data/mods/public/gui/session/session.xml

     
    725725                    </object>
    726726                </object>
    727727
     728                <object name="unitAbilityPanel"
     729                    size="14 12 100% 100%"
     730                >
     731                    <object size="0 0 100% 100%">
     732                        <repeat count="24">
     733                            <object name="unitAbilityButton[n]" hidden="true" style="iconButton" type="button" size="0 0 46 46" tooltip_style="sessionToolTipBottom">
     734                                <object name="unitAbilityIcon[n]" type="image" ghost="true" size="3 3 43 43"/>
     735                            </object>
     736                        </repeat>
     737                    </object>
     738                </object>
     739
    728740                <object name="unitResearchPanel"
    729741                    style="TranslucentPanelThinBorder"
    730742                    size="0 100%-56 100% 100%"
  • 0ad/binaries/data/mods/public/gui/session/input.js

     
    1515const ACTION_NONE = 0;
    1616const ACTION_GARRISON = 1;
    1717const ACTION_REPAIR = 2;
     18const ACTION_HEAL = 3;
    1819var preSelectedAction = ACTION_NONE;
    1920
    2021var INPUT_NORMAL = 0;
     
    255256                }
    256257            }
    257258            break;
     259        case "heal": //TODO add something like && targetState.needsheal ?
     260            if (isUnit(targetState) && (playerOwned || allyOwned))
     261            {
     262                var healableClasses = entState.Ability.Healer.healableClasses;
     263                for each (var unitClass in targetState.identity.classes)
     264                {
     265                    if (healableClasses.indexOf(unitClass) != -1)
     266                    {
     267                        return {"possible": true};
     268                    }
     269                }
     270            }
     271            break;
    258272        case "gather":
    259273            if (targetState.resourceSupply && (playerOwned || gaiaOwned))
    260274            {
     
    350364            else
    351365                return {"type": "none", "cursor": "action-repair-disabled", "target": undefined};
    352366            break;
     367        case ACTION_HEAL:
     368            if (getActionInfo("heal", target).possible)
     369                return {"type": "heal", "cursor": "action-heal", "target": target};
     370            else
     371                return {"type": "none", "cursor": "action-heal-disabled", "target": undefined};
     372            break;
    353373        }
    354374    }
    355375    else if (Engine.HotkeyIsPressed("session.garrison"))
     
    9921012        Engine.GuiInterfaceCall("PlaySound", { "name": "order_attack", "entity": selection[0] });
    9931013        return true;
    9941014
     1015    case "promote":
     1016        Engine.PostNetworkCommand({"type": "promote", "entities": selection, "target": action.target, "queued": queued});
     1017        //TODO play sound???
     1018        return true;
     1019
     1020    case "heal":
     1021        Engine.PostNetworkCommand({"type": "heal", "entities": selection, "target": action.target, "queued": queued});
     1022        //TODO play sound
     1023//      Engine.GuiInterfaceCall("PlaySound", { "name": "order_heal", "entity": selection[0] });
     1024        return true;
     1025
    9951026    case "build": // (same command as repair)
    9961027    case "repair":
    9971028        Engine.PostNetworkCommand({"type": "repair", "entities": selection, "target": action.target, "autocontinue": true, "queued": queued});
     
    12041235                inputState = INPUT_PRESELECTEDACTION;
    12051236                preSelectedAction = ACTION_REPAIR;
    12061237                break;
     1238            case "heal":
     1239                inputState = INPUT_PRESELECTEDACTION;
     1240                preSelectedAction = ACTION_HEAL;
     1241                break;
     1242            case "promote":
     1243                doAction({ "type": "promote"})
     1244                break;
    12071245            case "unload-all":
    12081246                unloadAll(entity);
    12091247                break;
  • 0ad/binaries/data/mods/public/gui/session/unit_commands.js

     
    55const FORMATION = "Formation";
    66const TRAINING = "Training";
    77const CONSTRUCTION = "Construction";
     8const ABILITY = "Ability";
    89const COMMAND = "Command";
    910const STANCE = "Stance";
    1011
     
    2021const BARTER_ACTIONS = ["Sell", "Buy"];
    2122
    2223// The number of currently visible buttons (used to optimise showing/hiding)
    23 var g_unitPanelButtons = {"Selection": 0, "Queue": 0, "Formation": 0, "Garrison": 0, "Barter": 0, "Training": 0, "Construction": 0, "Command": 0, "Stance": 0};
     24var g_unitPanelButtons = {"Selection": 0, "Queue": 0, "Formation": 0, "Garrison": 0, "Barter": 0, "Training": 0, "Construction": 0, "Ability": 0, "Command": 0, "Stance": 0};
    2425
    2526// Unit panels are panels with row(s) of buttons
    26 var g_unitPanels = ["Selection", "Queue", "Formation", "Garrison", "Barter", "Training", "Construction", "Research", "Stance", "Command"];
     27var g_unitPanels = ["Selection", "Queue", "Formation", "Garrison", "Barter", "Training", "Construction", "Ability", "Research", "Stance", "Command"];
    2728
    2829// Indexes of resources to sell and buy on barter panel
    2930var g_barterSell = 0;
     
    174175                numberOfItems =  24;
    175176            break;
    176177
     178        case ABILITY:
     179            if (numberOfItems > 24)
     180                numberOfItems = 24;
     181            break;
     182
    177183        case COMMAND:
    178184            if (numberOfItems > 6)
    179185                numberOfItems = 6;
     
    190196        var item = items[i];
    191197        var entType = ((guiName == "Queue")? item.template : item);
    192198        var template;
    193         if (guiName != "Formation" && guiName != "Command" && guiName != "Stance")
     199        if (guiName != "Formation" && guiName != "Command" && guiName != "Stance" && guiName != "Ability")
    194200        {
    195201            template = GetTemplateData(entType);
    196202            if (!template)
     
    269275
    270276                break;
    271277
     278            case ABILITY:
     279                // TODO read tooltips from some file or template based on 'item'
     280                var tooltip;
     281                switch(item)
     282                {
     283                    case "heal":
     284                        tooltip = "Heal units";
     285                        break;
     286                    case "promote":
     287                        tooltip = "Promote this unit";
     288                        break;
     289                    default:
     290                        tooltip = "No tooltip defined";
     291                        break;
     292                }
     293                break;
     294
    272295            case COMMAND:
    273296                // here, "item" is an object with properties .name (command name), .tooltip and .icon (relative to session/icons/single)
    274297                if (item.name == "unload-all")
     
    338361            icon.sprite = "stretched:session/icons/single/" + item.icon;
    339362
    340363        }
     364        else if (guiName == "Ability")
     365        {
     366            icon.sprite = "stretched:session/icons/single/"+item+".png";
     367        }
    341368        else if (template.icon)
    342369        {
    343370            icon.sprite = "stretched:session/portraits/" + template.icon;
     
    511538            setupUnitBarterPanel(entState);
    512539        }
    513540
     541        if (entState.Ability)
     542        {
     543            var abilities = [];
     544            if (entState.Ability.Healer)
     545                abilities.push("heal");
     546            if (entState.Ability.Promote)
     547                abilities.push("promote");
     548            setupUnitPanel("Ability", usedPanels, entState, abilities, function (item) { performCommand(entState.id, item); });
     549        }
     550
    514551        if (entState.buildEntities && entState.buildEntities.length)
    515552        {
    516553            setupUnitPanel("Construction", usedPanels, entState, entState.buildEntities, startBuildingPlacement);
  • 0ad/binaries/data/mods/public/art/textures/cursors/action-heal.txt

     
     11 1
  • 0ad/binaries/data/mods/public/maps/scenarios/Territory

    Cannot display: file marked as a binary type.
    svn:mime-type = application/octet-stream
     
    423423            <Orientation y="2.35621"/>
    424424        </Entity>
    425425        <Entity uid="70">
    426             <Template>units/cart_support_healer</Template>
     426            <Template>units/cart_support_healer_b</Template>
    427427            <Player>1</Player>
    428428            <Position x="466.09253" z="360.52533"/>
    429429            <Orientation y="2.35621"/>
  • 0ad/binaries/data/mods/public/maps/scenarios/Carthaginian

     
    393393            <Orientation y="2.35621"/>
    394394        </Entity>
    395395        <Entity uid="155">
    396             <Template>units/cart_support_healer</Template>
     396            <Template>units/cart_support_healer_b</Template>
    397397            <Player>2</Player>
    398398            <Position x="317.48292" z="426.92215"/>
    399399            <Orientation y="2.35621"/>
  • 0ad/binaries/data/mods/public/maps/scenarios/Carthaginians

     
    698698            <Orientation y="2.35621"/>
    699699        </Entity>
    700700        <Entity uid="144">
    701             <Template>units/cart_support_healer</Template>
     701            <Template>units/cart_support_healer_b</Template>
    702702            <Player>1</Player>
    703703            <Position x="357.91175" z="352.26969"/>
    704704            <Orientation y="2.35621"/>
  • 0ad/binaries/data/mods/public/maps/scenarios/Iberians_Sandbox.xml

     
    625625            <Orientation y="2.35621"/>
    626626        </Entity>
    627627        <Entity uid="102">
    628             <Template>units/iber_support_healer</Template>
     628            <Template>units/iber_support_healer_b</Template>
    629629            <Player>1</Player>
    630630            <Position x="461.1692" z="253.42179"/>
    631631            <Orientation y="2.35621"/>
    632632        </Entity>
    633633        <Entity uid="103">
    634             <Template>units/iber_support_healer</Template>
     634            <Template>units/iber_support_healer_b</Template>
    635635            <Player>1</Player>
    636636            <Position x="463.86204" z="255.47721"/>
    637637            <Orientation y="2.35621"/>
    638638        </Entity>
    639639        <Entity uid="104">
    640             <Template>units/iber_support_healer</Template>
     640            <Template>units/iber_support_healer_b</Template>
    641641            <Player>1</Player>
    642642            <Position x="467.43818" z="259.12848"/>
    643643            <Orientation y="2.35621"/>
  • 0ad/binaries/data/mods/public/maps/scenarios/Hellenic

     
    10481048            <Orientation y="-2.7069"/>
    10491049        </Entity>
    10501050        <Entity uid="186">
    1051             <Template>units/hele_support_healer</Template>
     1051            <Template>units/hele_support_healer_b</Template>
    10521052            <Player>1</Player>
    10531053            <Position x="575.92756" z="588.6966"/>
    10541054            <Orientation y="2.35621"/>
    10551055        </Entity>
    10561056        <Entity uid="187">
    1057             <Template>units/hele_support_healer</Template>
     1057            <Template>units/hele_support_healer_b</Template>
    10581058            <Player>1</Player>
    10591059            <Position x="578.18409" z="590.42273"/>
    10601060            <Orientation y="2.35621"/>
    10611061        </Entity>
    10621062        <Entity uid="188">
    1063             <Template>units/hele_support_healer</Template>
     1063            <Template>units/hele_support_healer_b</Template>
    10641064            <Player>1</Player>
    10651065            <Position x="580.17115" z="593.37488"/>
    10661066            <Orientation y="2.35621"/>
  • 0ad/binaries/data/mods/public/maps/scenarios/Celtic_Buildings.xml

     
    462462            <Orientation y="-0.01775"/>
    463463        </Entity>
    464464        <Entity uid="222">
    465             <Template>units/celt_support_healer</Template>
     465            <Template>units/celt_support_healer_b</Template>
    466466            <Player>1</Player>
    467467            <Position x="168.80031" z="46.27845"/>
    468468            <Orientation y="2.35621"/>