Ticket #999: #999-2012-02-24.patch
File #999-2012-02-24.patch, 53.6 KB (added by , 12 years ago) |
---|
-
0ad/binaries/data/mods/public/simulation/helpers/Commands.js
66 66 }); 67 67 break; 68 68 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 69 83 case "repair": 70 84 // This covers both repairing damaged buildings, and constructing unfinished foundations 71 85 if (g_DebugCommands && !IsOwnedByAllyOfPlayer(player, cmd.target)) -
0ad/binaries/data/mods/public/simulation/components/GuiInterface.js
264 264 ret.barterMarket = { "prices": cmpBarter.GetPrices() }; 265 265 } 266 266 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 267 285 var cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager); 268 286 ret.visibility = cmpRangeManager.GetLosVisibility(ent, player, false); 269 287 -
0ad/binaries/data/mods/public/simulation/components/interfaces/Heal.js
1 Engine.RegisterInterface("Heal"); 2 3 //TODO register message type healed? -
0ad/binaries/data/mods/public/simulation/components/Health.js
131 131 { 132 132 // If we're already dead, don't allow resurrection 133 133 if (this.hitpoints == 0) 134 return ;134 return false; 135 135 136 136 var old = this.hitpoints; 137 137 this.hitpoints = Math.min(this.hitpoints + amount, this.GetMaxHitpoints()); 138 138 139 139 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}; 140 142 }; 141 143 142 144 //// Private functions //// -
0ad/binaries/data/mods/public/simulation/components/Loot.js
21 21 22 22 Loot.prototype.GetXp = function() 23 23 { 24 return this.template.xp;24 return +(this.template.xp || 0); 25 25 }; 26 26 27 27 Loot.prototype.GetResources = function() -
0ad/binaries/data/mods/public/simulation/components/tests/test_GuiInterface.js
5 5 Engine.LoadComponentScript("interfaces/DamageReceiver.js"); 6 6 Engine.LoadComponentScript("interfaces/Foundation.js"); 7 7 Engine.LoadComponentScript("interfaces/GarrisonHolder.js"); 8 Engine.LoadComponentScript("interfaces/Heal.js"); 8 9 Engine.LoadComponentScript("interfaces/Health.js"); 9 10 Engine.LoadComponentScript("interfaces/Promotion.js"); 10 11 Engine.LoadComponentScript("interfaces/RallyPoint.js"); -
0ad/binaries/data/mods/public/simulation/components/UnitAI.js
(this hunk was shorter than expected) 282 282 // so abandon this attack order 283 283 this.FinishOrder(); 284 284 }, 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 285 323 "Order.Gather": function(msg) { 286 324 287 325 // If the target is still alive, we need to kill it first … … 402 439 cmpFormation.Disband(); 403 440 }, 404 441 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 405 449 "Order.Repair": function(msg) { 406 450 // TODO: see notes in Order.Attack 407 451 var cmpFormation = Engine.QueryInterface(this.entity, IID_Formation); … … 995 1039 }, 996 1040 }, 997 1041 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 998 1172 // Returning to dropsite 999 1173 "RETURNRESOURCE": { 1000 1174 "APPROACHING": { … … 1746 1920 }; 1747 1921 1748 1922 /** 1923 * Returns true if the target exists and the current hitpoints are at maximum. 1924 */ 1925 UnitAI.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 /** 1749 1935 * Returns true if the target exists and needs to be killed before 1750 1936 * beginning to gather resources from it. 1751 1937 */ … … 2236 2422 case "Flee": 2237 2423 case "LeaveFoundation": 2238 2424 case "Attack": 2425 case "Heal": 2239 2426 case "Gather": 2240 2427 case "ReturnResource": 2241 2428 case "Repair": … … 2359 2546 this.AddOrder("GatherNearPosition", { "type": type, "x": position[0], "z": position[1] }, queued); 2360 2547 } 2361 2548 2549 UnitAI.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 2362 2560 UnitAI.prototype.ReturnResource = function(target, queued) 2363 2561 { 2364 2562 if (!this.CanReturnResource(target, true)) … … 2555 2753 return true; 2556 2754 }; 2557 2755 2756 UnitAI.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 2558 2801 UnitAI.prototype.CanReturnResource = function(target, checkCarriedResource) 2559 2802 { 2560 2803 // Formation controllers should always respond to commands -
0ad/binaries/data/mods/public/simulation/components/Heal.js
1 function Heal() {} 2 3 Heal.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 27 Heal.prototype.Init = function() 28 { 29 }; 30 31 Heal.prototype.Serialize = null; // we have no dynamic state to save 32 33 Heal.prototype.GetTimers = function() 34 { 35 var prepare = 1000; 36 var repeat = +(this.template.Rate || 1000); 37 return { "prepare": prepare, "repeat": repeat }; 38 } 39 40 Heal.prototype.GetRange = function() 41 { 42 var max = +this.template.Range; 43 var min = 0; 44 return { "max": max, "min": min }; 45 }; 46 47 Heal.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 */ 58 Heal.prototype.PerformHeal = function(target) 59 { 60 this.CauseHeal({"target": target}); 61 }; 62 63 /** 64 * Heal target 65 */ 66 Heal.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 86 Engine.RegisterComponentType(IID_Heal, "Heal", Heal); -
0ad/binaries/data/mods/public/simulation/templates/template_unit_support_healer.xml
5 5 <Pierce>2.0</Pierce> 6 6 <Crush>2.0</Crush> 7 7 </Armour> 8 <Auras>8 <!-- <Auras> 9 9 <Heal> 10 10 <Radius>20</Radius> 11 11 <Speed>2000</Speed> 12 12 </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> 14 20 <Cost> 15 21 <Resources> 16 22 <metal>120</metal> … … 23 29 <Identity> 24 30 <Classes datatype="tokens">Healer</Classes> 25 31 <GenericName>Healer</GenericName> 26 <Tooltip>Heal units within his Aura. (Not implemented yet)</Tooltip> 32 <Tooltip>Heal units.</Tooltip> 33 <Rank>Basic</Rank> 27 34 </Identity> 35 <Promotion> 36 <RequiredXp>100</RequiredXp> 37 </Promotion> 28 38 <Sound> 29 39 <SoundGroups> 30 40 <select>voice/hellenes/civ/civ_male_select.xml</select> -
0ad/binaries/data/mods/public/simulation/templates/template_structure_civic_temple.xml
57 57 </TerritoryInfluence> 58 58 <TrainingQueue> 59 59 <Entities datatype="tokens"> 60 units/{civ}_support_healer 60 units/{civ}_support_healer_b 61 61 </Entities> 62 62 </TrainingQueue> 63 63 <Vision> -
0ad/binaries/data/mods/public/simulation/templates/units/hele_support_healer_a.xml
1 1 <?xml version="1.0" encoding="utf-8"?> 2 <Entity parent=" template_unit_support_healer">2 <Entity parent="units/hele_support_healer_b"> 3 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> 4 <Rank>Advanced</Rank> 8 5 </Identity> 6 <Promotion> 7 <Entity>units/hele_support_healer_e</Entity> 8 </Promotion> 9 9 <VisualActor> 10 10 <Actor>units/hellenes/healer.xml</Actor> 11 11 </VisualActor> -
0ad/binaries/data/mods/public/simulation/templates/units/hele_support_healer_e.xml
1 1 <?xml version="1.0" encoding="utf-8"?> 2 <Entity parent=" template_unit_support_healer">2 <Entity parent="units/hele_support_healer_a"> 3 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> 4 <Rank>Elite</Rank> 8 5 </Identity> 6 <Promotion disable=""/> 9 7 <VisualActor> 10 8 <Actor>units/hellenes/healer.xml</Actor> 11 9 </VisualActor> -
0ad/binaries/data/mods/public/simulation/templates/units/celt_support_healer_a.xml
1 1 <?xml version="1.0" encoding="utf-8"?> 2 <Entity parent=" template_unit_support_healer">2 <Entity parent="units/celt_support_healer_b"> 3 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> 4 <Rank>Advanced</Rank> 8 5 </Identity> 6 <Promotion> 7 <Entity>units/celt_support_healer_e</Entity> 8 </Promotion> 9 9 <VisualActor> 10 10 <Actor>units/celts/healer.xml</Actor> 11 11 </VisualActor> -
0ad/binaries/data/mods/public/simulation/templates/units/celt_support_healer_e.xml
1 1 <?xml version="1.0" encoding="utf-8"?> 2 <Entity parent=" template_unit_support_healer">2 <Entity parent="units/celt_support_healer_a"> 3 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> 4 <Rank>Elite</Rank> 8 5 </Identity> 6 <Promotion disable=""/> 9 7 <VisualActor> 10 8 <Actor>units/celts/healer.xml</Actor> 11 9 </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
1 1 <?xml version="1.0" encoding="utf-8"?> 2 <Entity parent=" template_unit_support_healer">2 <Entity parent="units/iber_support_healer_b"> 3 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> 4 <Rank>Advanced</Rank> 8 5 </Identity> 6 <Promotion> 7 <Entity>units/iber_support_healer_e</Entity> 8 </Promotion> 9 9 <VisualActor> 10 10 <Actor>units/iberians/healer.xml</Actor> 11 11 </VisualActor> -
0ad/binaries/data/mods/public/simulation/templates/units/iber_support_healer_e.xml
1 1 <?xml version="1.0" encoding="utf-8"?> 2 <Entity parent=" template_unit_support_healer">2 <Entity parent="units/iber_support_healer_a"> 3 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> 4 <Rank>Elite</Rank> 8 5 </Identity> 6 <Promotion disable=""/> 9 7 <VisualActor> 10 8 <Actor>units/iberians/healer.xml</Actor> 11 9 </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
1 1 <?xml version="1.0" encoding="utf-8"?> 2 <Entity parent=" template_unit_support_healer">2 <Entity parent="units/pers_support_healer_b"> 3 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> 4 <Rank>Advanced</Rank> 9 5 </Identity> 6 <Promotion> 7 <Entity>units/pers_support_healer_e</Entity> 8 </Promotion> 10 9 <VisualActor> 11 10 <Actor>units/persians/healer.xml</Actor> 12 11 </VisualActor> -
0ad/binaries/data/mods/public/simulation/templates/units/pers_support_healer_e.xml
1 1 <?xml version="1.0" encoding="utf-8"?> 2 <Entity parent=" template_unit_support_healer">2 <Entity parent="units/pers_support_healer_a"> 3 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> 4 <Rank>Elite</Rank> 9 5 </Identity> 6 <Promotion disable=""/> 10 7 <VisualActor> 11 8 <Actor>units/persians/healer.xml</Actor> 12 9 </VisualActor> -
0ad/binaries/data/mods/public/simulation/templates/units/cart_support_healer_a.xml
1 1 <?xml version="1.0" encoding="utf-8"?> 2 <Entity parent=" template_unit_support_healer">2 <Entity parent="units/cart_support_healer_b"> 3 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> 4 <Rank>Advanced</Rank> 9 5 </Identity> 6 <Promotion> 7 <Entity>units/cart_support_healer_e</Entity> 8 </Promotion> 10 9 <VisualActor> 11 10 <Actor>units/carthaginians/healer.xml</Actor> 12 11 </VisualActor> -
0ad/binaries/data/mods/public/simulation/templates/units/cart_support_healer_e.xml
1 1 <?xml version="1.0" encoding="utf-8"?> 2 <Entity parent=" template_unit_support_healer">2 <Entity parent="units/cart_support_healer_a"> 3 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> 4 <Rank>Elite</Rank> 9 5 </Identity> 6 <Promotion disable=""/> 10 7 <VisualActor> 11 8 <Actor>units/carthaginians/healer.xml</Actor> 12 9 </VisualActor> -
0ad/binaries/data/mods/public/simulation/templates/units/rome_support_healer_a.xml
1 1 <?xml version="1.0" encoding="utf-8"?> 2 <Entity parent=" template_unit_support_healer">2 <Entity parent="units/rome_support_healer_b"> 3 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> 4 <Rank>Advanced</Rank> 9 5 </Identity> 6 <Promotion> 7 <Entity>units/rome_support_healer_e</Entity> 8 </Promotion> 10 9 <VisualActor> 11 10 <Actor>units/romans/healer.xml</Actor> 12 11 </VisualActor> -
0ad/binaries/data/mods/public/simulation/templates/units/rome_support_healer_e.xml
1 1 <?xml version="1.0" encoding="utf-8"?> 2 <Entity parent=" template_unit_support_healer">2 <Entity parent="units/rome_support_healer_a"> 3 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> 4 <Rank>Elite</Rank> 9 5 </Identity> 6 <Promotion disable=""/> 10 7 <VisualActor> 11 8 <Actor>units/romans/healer.xml</Actor> 12 9 </VisualActor> -
0ad/binaries/data/mods/public/gui/session/session.xml
725 725 </object> 726 726 </object> 727 727 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 728 740 <object name="unitResearchPanel" 729 741 style="TranslucentPanelThinBorder" 730 742 size="0 100%-56 100% 100%" -
0ad/binaries/data/mods/public/gui/session/input.js
15 15 const ACTION_NONE = 0; 16 16 const ACTION_GARRISON = 1; 17 17 const ACTION_REPAIR = 2; 18 const ACTION_HEAL = 3; 18 19 var preSelectedAction = ACTION_NONE; 19 20 20 21 var INPUT_NORMAL = 0; … … 255 256 } 256 257 } 257 258 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; 258 272 case "gather": 259 273 if (targetState.resourceSupply && (playerOwned || gaiaOwned)) 260 274 { … … 350 364 else 351 365 return {"type": "none", "cursor": "action-repair-disabled", "target": undefined}; 352 366 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; 353 373 } 354 374 } 355 375 else if (Engine.HotkeyIsPressed("session.garrison")) … … 992 1012 Engine.GuiInterfaceCall("PlaySound", { "name": "order_attack", "entity": selection[0] }); 993 1013 return true; 994 1014 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 995 1026 case "build": // (same command as repair) 996 1027 case "repair": 997 1028 Engine.PostNetworkCommand({"type": "repair", "entities": selection, "target": action.target, "autocontinue": true, "queued": queued}); … … 1204 1235 inputState = INPUT_PRESELECTEDACTION; 1205 1236 preSelectedAction = ACTION_REPAIR; 1206 1237 break; 1238 case "heal": 1239 inputState = INPUT_PRESELECTEDACTION; 1240 preSelectedAction = ACTION_HEAL; 1241 break; 1242 case "promote": 1243 doAction({ "type": "promote"}) 1244 break; 1207 1245 case "unload-all": 1208 1246 unloadAll(entity); 1209 1247 break; -
0ad/binaries/data/mods/public/gui/session/unit_commands.js
5 5 const FORMATION = "Formation"; 6 6 const TRAINING = "Training"; 7 7 const CONSTRUCTION = "Construction"; 8 const ABILITY = "Ability"; 8 9 const COMMAND = "Command"; 9 10 const STANCE = "Stance"; 10 11 … … 20 21 const BARTER_ACTIONS = ["Sell", "Buy"]; 21 22 22 23 // 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};24 var g_unitPanelButtons = {"Selection": 0, "Queue": 0, "Formation": 0, "Garrison": 0, "Barter": 0, "Training": 0, "Construction": 0, "Ability": 0, "Command": 0, "Stance": 0}; 24 25 25 26 // Unit panels are panels with row(s) of buttons 26 var g_unitPanels = ["Selection", "Queue", "Formation", "Garrison", "Barter", "Training", "Construction", " Research", "Stance", "Command"];27 var g_unitPanels = ["Selection", "Queue", "Formation", "Garrison", "Barter", "Training", "Construction", "Ability", "Research", "Stance", "Command"]; 27 28 28 29 // Indexes of resources to sell and buy on barter panel 29 30 var g_barterSell = 0; … … 174 175 numberOfItems = 24; 175 176 break; 176 177 178 case ABILITY: 179 if (numberOfItems > 24) 180 numberOfItems = 24; 181 break; 182 177 183 case COMMAND: 178 184 if (numberOfItems > 6) 179 185 numberOfItems = 6; … … 190 196 var item = items[i]; 191 197 var entType = ((guiName == "Queue")? item.template : item); 192 198 var template; 193 if (guiName != "Formation" && guiName != "Command" && guiName != "Stance" )199 if (guiName != "Formation" && guiName != "Command" && guiName != "Stance" && guiName != "Ability") 194 200 { 195 201 template = GetTemplateData(entType); 196 202 if (!template) … … 269 275 270 276 break; 271 277 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 272 295 case COMMAND: 273 296 // here, "item" is an object with properties .name (command name), .tooltip and .icon (relative to session/icons/single) 274 297 if (item.name == "unload-all") … … 338 361 icon.sprite = "stretched:session/icons/single/" + item.icon; 339 362 340 363 } 364 else if (guiName == "Ability") 365 { 366 icon.sprite = "stretched:session/icons/single/"+item+".png"; 367 } 341 368 else if (template.icon) 342 369 { 343 370 icon.sprite = "stretched:session/portraits/" + template.icon; … … 511 538 setupUnitBarterPanel(entState); 512 539 } 513 540 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 514 551 if (entState.buildEntities && entState.buildEntities.length) 515 552 { 516 553 setupUnitPanel("Construction", usedPanels, entState, entState.buildEntities, startBuildingPlacement); -
0ad/binaries/data/mods/public/art/textures/cursors/action-heal.txt
1 1 1 -
0ad/binaries/data/mods/public/maps/scenarios/Territory
Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream
423 423 <Orientation y="2.35621"/> 424 424 </Entity> 425 425 <Entity uid="70"> 426 <Template>units/cart_support_healer </Template>426 <Template>units/cart_support_healer_b</Template> 427 427 <Player>1</Player> 428 428 <Position x="466.09253" z="360.52533"/> 429 429 <Orientation y="2.35621"/> -
0ad/binaries/data/mods/public/maps/scenarios/Carthaginian
393 393 <Orientation y="2.35621"/> 394 394 </Entity> 395 395 <Entity uid="155"> 396 <Template>units/cart_support_healer </Template>396 <Template>units/cart_support_healer_b</Template> 397 397 <Player>2</Player> 398 398 <Position x="317.48292" z="426.92215"/> 399 399 <Orientation y="2.35621"/> -
0ad/binaries/data/mods/public/maps/scenarios/Carthaginians
698 698 <Orientation y="2.35621"/> 699 699 </Entity> 700 700 <Entity uid="144"> 701 <Template>units/cart_support_healer </Template>701 <Template>units/cart_support_healer_b</Template> 702 702 <Player>1</Player> 703 703 <Position x="357.91175" z="352.26969"/> 704 704 <Orientation y="2.35621"/> -
0ad/binaries/data/mods/public/maps/scenarios/Iberians_Sandbox.xml
625 625 <Orientation y="2.35621"/> 626 626 </Entity> 627 627 <Entity uid="102"> 628 <Template>units/iber_support_healer </Template>628 <Template>units/iber_support_healer_b</Template> 629 629 <Player>1</Player> 630 630 <Position x="461.1692" z="253.42179"/> 631 631 <Orientation y="2.35621"/> 632 632 </Entity> 633 633 <Entity uid="103"> 634 <Template>units/iber_support_healer </Template>634 <Template>units/iber_support_healer_b</Template> 635 635 <Player>1</Player> 636 636 <Position x="463.86204" z="255.47721"/> 637 637 <Orientation y="2.35621"/> 638 638 </Entity> 639 639 <Entity uid="104"> 640 <Template>units/iber_support_healer </Template>640 <Template>units/iber_support_healer_b</Template> 641 641 <Player>1</Player> 642 642 <Position x="467.43818" z="259.12848"/> 643 643 <Orientation y="2.35621"/> -
0ad/binaries/data/mods/public/maps/scenarios/Hellenic
1048 1048 <Orientation y="-2.7069"/> 1049 1049 </Entity> 1050 1050 <Entity uid="186"> 1051 <Template>units/hele_support_healer </Template>1051 <Template>units/hele_support_healer_b</Template> 1052 1052 <Player>1</Player> 1053 1053 <Position x="575.92756" z="588.6966"/> 1054 1054 <Orientation y="2.35621"/> 1055 1055 </Entity> 1056 1056 <Entity uid="187"> 1057 <Template>units/hele_support_healer </Template>1057 <Template>units/hele_support_healer_b</Template> 1058 1058 <Player>1</Player> 1059 1059 <Position x="578.18409" z="590.42273"/> 1060 1060 <Orientation y="2.35621"/> 1061 1061 </Entity> 1062 1062 <Entity uid="188"> 1063 <Template>units/hele_support_healer </Template>1063 <Template>units/hele_support_healer_b</Template> 1064 1064 <Player>1</Player> 1065 1065 <Position x="580.17115" z="593.37488"/> 1066 1066 <Orientation y="2.35621"/> -
0ad/binaries/data/mods/public/maps/scenarios/Celtic_Buildings.xml
462 462 <Orientation y="-0.01775"/> 463 463 </Entity> 464 464 <Entity uid="222"> 465 <Template>units/celt_support_healer </Template>465 <Template>units/celt_support_healer_b</Template> 466 466 <Player>1</Player> 467 467 <Position x="168.80031" z="46.27845"/> 468 468 <Orientation y="2.35621"/>