Ticket #2577: 2577 Atlas Todo.patch
File 2577 Atlas Todo.patch, 24.8 KB (added by , 9 years ago) |
---|
-
binaries/data/mods/public/art/actors/units/celts/boudicca_chariot.xml
12 12 <props> 13 13 <prop actor="units/celts/boudicca_chariot_h1.xml" attachpoint="horseright"/> 14 14 <prop actor="units/celts/boudicca_chariot_h2.xml" attachpoint="horseleft"/> 15 <prop actor="units/celts/boudicca_r2.xml" attachpoint="rider"/>16 15 <prop actor="units/celts/champion_unit_4_d.xml" attachpoint="driver"/> 17 16 </props> 18 17 <textures><texture file="structural/celt_chariot_b.dds" name="baseTex"/></textures> -
binaries/data/mods/public/art/actors/units/persians/cavalry_archer_a.xml
14 14 <prop actor="units/persians/pers_chariot_archer_a_h2.xml" attachpoint="horse2"/> 15 15 <prop actor="units/persians/pers_chariot_archer_a_h3.xml" attachpoint="horse3"/> 16 16 <prop actor="units/persians/pers_chariot_archer_a_h4.xml" attachpoint="horse4"/> 17 <prop actor="units/persians/cavalry_archer_a_r.xml" attachpoint="rider1"/>18 17 <prop actor="units/persians/cavalry_archer_a_d.xml" attachpoint="rider2"/> 19 18 </props> 20 19 <textures><texture file="structural/pers_chariot_a.png" name="baseTex"/></textures> -
binaries/data/mods/public/art/actors/units/persians/cavalry_archer_e.xml
15 15 <prop actor="units/persians/pers_chariot_archer_e_h2.xml" attachpoint="horse2"/> 16 16 <prop actor="units/persians/pers_chariot_archer_e_h3.xml" attachpoint="horse3"/> 17 17 <prop actor="units/persians/pers_chariot_archer_e_h4.xml" attachpoint="horse4"/> 18 <prop actor="units/persians/cavalry_archer_e_r.xml" attachpoint="rider1"/>19 18 <prop actor="units/persians/cavalry_archer_e_d.xml" attachpoint="rider2"/> 20 19 </props> 21 20 <textures><texture file="structural/pers_chariot_e.png" name="baseTex"/></textures> -
binaries/data/mods/public/simulation/components/Attack.js
155 155 "</interleave>" + 156 156 "</element>" + 157 157 "</optional>" + 158 "<optional>"+ 159 "<element name='TurretsOnly' a:help='When set to \"true\", will only accept attacks coming from turrets.'><text/></element>" + 160 "</optional>" + 158 161 "</interleave>" + 159 162 "</element>" + 160 163 "</optional>" + … … 202 205 203 206 Attack.prototype.Init = function() 204 207 { 208 this.latestTarget = INVALID_ENTITY; 205 209 }; 206 210 207 Attack.prototype.Serialize = null; // we have no dynamic state to save 211 Attack.prototype.Serialize = null; // we have no dynamic state to save 208 212 209 213 Attack.prototype.GetAttackTypes = function() 210 214 { … … 502 506 * and should only be called after GetTimers().repeat msec has passed since the last 503 507 * call to PerformAttack. 504 508 */ 505 Attack.prototype.PerformAttack = function(type, target )509 Attack.prototype.PerformAttack = function(type, target, turretId) 506 510 { 511 if(this.template[type].TurretsOnly) 512 if (!turretId && this.template[type].TurretsOnly == "true") 513 return; 514 507 515 // If this is a ranged attack, then launch a projectile 508 516 if (type == "Ranged") 509 517 { … … 571 579 var graphicalPosition = Vector3D.mult(missileDirection, 2).add(realTargetPosition); 572 580 // Launch the graphical projectile 573 581 var cmpProjectileManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_ProjectileManager); 574 var id = cmpProjectileManager.LaunchProjectileAtPoint(t his.entity, realTargetPosition, horizSpeed, gravity);582 var id = cmpProjectileManager.LaunchProjectileAtPoint(turretId || this.entity, realTargetPosition, horizSpeed, gravity); 575 583 576 584 var playerId = Engine.QueryInterface(this.entity, IID_Ownership).GetOwner(); 577 585 var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer); -
binaries/data/mods/public/simulation/components/interfaces/TurretAI.js
1 Engine.RegisterInterface("TurretAI"); -
binaries/data/mods/public/simulation/components/interfaces/TurretHolder.js
1 Engine.RegisterInterface("TurretHolder"); 2 -
binaries/data/mods/public/simulation/components/TurretAI.js
1 function TurretAI() {} 2 TurretAI.prototype.Schema = 3 "<empty/>"; 4 5 TurretAI.prototype.g_MaxPreferenceBonus = 2; 6 TurretAI.prototype.g_LatestTarget = 0 ; 7 8 /** 9 * Initialize TurretAI Component. 10 */ 11 TurretAI.prototype.Init = function() 12 { 13 }; 14 15 /** 16 * Get the turrent parent. 17 */ 18 TurretAI.prototype.GetTurretParent = function() 19 { 20 var cmpPosition = Engine.QueryInterface(this.entity, IID_Position); 21 if (!cmpPosition) 22 return INVALID_ENTITY; 23 return cmpPosition.GetTurretParent(); 24 }; 25 26 /** 27 * Get the attack component 28 */ 29 TurretAI.prototype.GetCmpAttack = function() 30 { 31 // use own attack, or turretHolder's attack 32 var cmpAttack = Engine.QueryInterface(this.entity, IID_Attack); 33 if (cmpAttack) 34 return cmpAttack; 35 return Engine.QueryInterface(this.GetTurretParent(), IID_Attack); 36 }; 37 38 /** 39 * Sends the message to change ownership 40 */ 41 TurretAI.prototype.OnOwnershipChanged = function(msg) 42 { 43 var cmpAttack = this.GetCmpAttack(); 44 if (!cmpAttack) 45 return; 46 //Return the first possible Attack Type, Capturing being the last. 47 this.bestAttack = cmpAttack.GetAttackTypes()[0]; 48 49 // Remove current targets, to prevent them from being added twice 50 this.targetUnits = []; 51 52 if (msg.to != -1) 53 this.SetupRangeQuery(msg.to); 54 55 // Non-Gaia buildings should attack certain Gaia units. 56 if (msg.to != 0 || this.gaiaUnitsQuery) 57 this.SetupGaiaRangeQuery(msg.to); 58 }; 59 60 /** 61 * Change Diplomacy State 62 */ 63 TurretAI.prototype.OnDiplomacyChanged = function(msg) 64 { 65 var cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership); 66 if (cmpOwnership && cmpOwnership.GetOwner() == msg.player) 67 { 68 // Remove now allied/neutral units 69 this.targetUnits = []; 70 this.SetupRangeQuery(msg.player); 71 } 72 }; 73 74 /** 75 * Cleanup on destroy 76 */ 77 TurretAI.prototype.OnDestroy = function() 78 { 79 if (this.timer) 80 { 81 let cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer); 82 cmpTimer.CancelTimer(this.timer); 83 this.timer = undefined; 84 } 85 86 // Clean up range queries 87 var cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager); 88 if (this.enemyUnitsQuery) 89 cmpRangeManager.DestroyActiveQuery(this.enemyUnitsQuery); 90 if (this.gaiaUnitsQuery) 91 cmpRangeManager.DestroyActiveQuery(this.gaiaUnitsQuery); 92 }; 93 94 /** 95 * Setup the Range Query to detect units coming in & out of range 96 */ 97 TurretAI.prototype.SetupRangeQuery = function(owner) 98 { 99 var cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager); 100 var cmpPlayerManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager); 101 var cmpAttack = this.GetCmpAttack(); 102 if (!cmpAttack) 103 return; 104 105 if (this.enemyUnitsQuery) 106 { 107 cmpRangeManager.DestroyActiveQuery(this.enemyUnitsQuery); 108 this.enemyUnitsQuery = undefined; 109 } 110 111 var players = []; 112 var cmpPlayer = Engine.QueryInterface(cmpPlayerManager.GetPlayerByID(owner), IID_Player); 113 var numPlayers = cmpPlayerManager.GetNumPlayers(); 114 115 for (let i = 1; i < numPlayers; ++i) 116 { 117 // TODO: How to handle neutral players - Special query to attack military only? 118 if (cmpPlayer.IsEnemy(i)) 119 players.push(i); 120 } 121 122 var range = cmpAttack.GetRange(this.bestAttack); 123 this.enemyUnitsQuery = cmpRangeManager.CreateActiveParabolicQuery(this.entity, range.min, range.max, range.elevationBonus, players, IID_DamageReceiver, cmpRangeManager.GetEntityFlagMask("normal")); 124 cmpRangeManager.EnableActiveQuery(this.enemyUnitsQuery); 125 }; 126 127 /** 128 *Set up a range query for Gaia units within LOS range which can be attacked. 129 * This should be called whenever our ownership changes. 130 */ 131 TurretAI.prototype.SetupGaiaRangeQuery = function() 132 { 133 var cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership); 134 var owner = cmpOwnership.GetOwner(); 135 136 var cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager); 137 var playerMan = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager); 138 var cmpAttack = this.GetCmpAttack(); 139 if (!cmpAttack) 140 return; 141 142 if (this.gaiaUnitsQuery) 143 { 144 cmpRangeManager.DestroyActiveQuery(this.gaiaUnitsQuery); 145 this.gaiaUnitsQuery = undefined; 146 } 147 148 if (owner == -1) 149 return; 150 151 var cmpPlayer = Engine.QueryInterface(playerMan.GetPlayerByID(owner), IID_Player); 152 if (!cmpPlayer.IsEnemy(0)) 153 return; 154 155 var range = cmpAttack.GetRange(this.bestAttack); 156 157 // This query is only interested in Gaia entities that can attack. 158 this.gaiaUnitsQuery = cmpRangeManager.CreateActiveParabolicQuery(this.entity, range.min, range.max, range.elevationBonus, [0], IID_Attack, cmpRangeManager.GetEntityFlagMask("normal")); 159 cmpRangeManager.EnableActiveQuery(this.gaiaUnitsQuery); 160 }; 161 162 /** 163 * Called when units enter or leave range 164 */ 165 TurretAI.prototype.OnRangeUpdate = function(msg) 166 { 167 var cmpAttack = this.GetCmpAttack(); 168 if (!cmpAttack) 169 return; 170 171 if (msg.tag == this.gaiaUnitsQuery) 172 { 173 const filter = function(e) { 174 let cmpUnitAI = Engine.QueryInterface(e, IID_UnitAI); 175 return (cmpUnitAI && (!cmpUnitAI.IsAnimal() || cmpUnitAI.IsDangerousAnimal())); 176 }; 177 178 if (msg.added.length) 179 msg.added = msg.added.filter(filter); 180 181 // Removed entities may not have cmpUnitAI. 182 for (let i = 0; i < msg.removed.length; ++i) 183 if (this.targetUnits.indexOf(msg.removed[i]) == -1) 184 msg.removed.splice(i--, 1); 185 } 186 else if (msg.tag != this.enemyUnitsQuery) 187 return; 188 189 if (msg.added.length > 0) 190 for (let entity of msg.added) 191 if (cmpAttack.CanAttack(entity)) 192 this.targetUnits.push(entity); 193 194 if (msg.removed.length > 0) 195 for (let entity of msg.removed) 196 { 197 let index = this.targetUnits.indexOf(entity); 198 if (index > -1) 199 this.targetUnits.splice(index, 1); 200 } 201 202 if (!this.targetUnits.length || this.timer) 203 return; 204 205 var attackTimers = cmpAttack.GetTimers(this.bestAttack); 206 this.SelectAnimation("attack_" + this.bestAttack.toLowerCase(), false, 1.0, "attack"); 207 this.SetAnimationSync(attackTimers.prepare, attackTimers.repeat); 208 // units entered the range, prepare to shoot 209 var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer); 210 this.timer = cmpTimer.SetInterval(this.entity, IID_TurretAI, "Attack", attackTimers.prepare, attackTimers.repeat, null); 211 }; 212 213 /** 214 * Get Previous Target 215 */ 216 TurretAI.prototype.GetPreviousTarget = function() 217 { 218 var cmpAttack = this.GetCmpAttack(); 219 if (!cmpAttack) 220 return INVALID_ENTITY; 221 var previousTarget = this.g_LatestTarget; 222 var cmpUnitAI = Engine.QueryInterface(this.GetTurretParent(), IID_UnitAI); 223 // if a unit ai, use that to overcome the difference between rangeManager range and unitMotion range 224 if (cmpUnitAI) 225 { 226 if (cmpUnitAI.CheckTargetAttackRange(previousTarget, this.bestAttack)) 227 return previousTarget; 228 return INVALID_ENTITY; 229 } 230 // else just use the range manager (which gives us the list of possible targets); 231 if (this.targetUnits.indexOf(previousTarget) != -1) 232 return previousTarget; 233 return INVALID_ENTITY; 234 }; 235 236 /** 237 * Attack other entities 238 */ 239 TurretAI.prototype.Attack = function() 240 { 241 if (!this.targetUnits.length) 242 { 243 if (this.timer) 244 { 245 // stop the timer 246 let cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer); 247 cmpTimer.CancelTimer(this.timer); 248 this.timer = undefined; 249 } 250 this.SelectAnimation("idle"); 251 return; 252 } 253 254 var cmpAttack = this.GetCmpAttack(); 255 if (!cmpAttack) 256 return; 257 var target = this.GetPreviousTarget(); 258 // if no target, select a random one 259 if (target == INVALID_ENTITY) 260 { 261 var selectedIndex = -1; 262 var targets = new WeightedList(); 263 for (let i = 0; i < this.targetUnits.length; i++) 264 { 265 let target = this.targetUnits[i]; 266 let preference = cmpAttack.GetPreference(target); 267 let weight = 1; 268 if (preference !== null && preference !== undefined) 269 { 270 // Lower preference scores indicate a higher preference so they should result in a higher weight. 271 weight = 1 + this.g_MaxPreferenceBonus / (1 + preference); 272 } 273 targets.push(target, weight); 274 } 275 selectedIndex = targets.randomIndex() 276 target = targets.itemAt(selectedIndex); 277 } 278 // now we hope there's a target 279 if (target != INVALID_ENTITY) 280 { 281 // TODO : It should only turn if the parent has more than one turret. 282 this.TurnTowardsTarget(target); 283 cmpAttack.PerformAttack(this.bestAttack, target, this.entity); 284 this.g_LatestTarget = target; 285 } 286 }; 287 288 /** 289 * Selection the animations for the turret 290 */ 291 TurretAI.prototype.SelectAnimation = function(name, once = false, speed = 1.0, sound) 292 { 293 var cmpVisual = Engine.QueryInterface(this.entity, IID_Visual); 294 if (!cmpVisual) 295 return; 296 297 var soundgroup; 298 if (sound) 299 { 300 let cmpSound = Engine.QueryInterface(this.entity, IID_Sound); 301 if (cmpSound) 302 soundgroup = cmpSound.GetSoundGroup(sound); 303 } 304 cmpVisual.SelectAnimation(name, once, speed, soundgroup || ""); 305 }; 306 307 /** 308 * Synchronise Animations 309 */ 310 TurretAI.prototype.SetAnimationSync = function(actiontime, repeattime) 311 { 312 var cmpVisual = Engine.QueryInterface(this.entity, IID_Visual); 313 if (!cmpVisual) 314 return; 315 316 cmpVisual.SetAnimationSyncRepeat(repeattime); 317 cmpVisual.SetAnimationSyncOffset(actiontime); 318 }; 319 320 /** 321 * Orient the turret toward his foe. 322 */ 323 TurretAI.prototype.TurnTowardsTarget = function(target) 324 { 325 var cmpThisPosition = Engine.QueryInterface(this.entity, IID_Position); 326 var cmpTargetPosition = Engine.QueryInterface(target, IID_Position); 327 if (!cmpThisPosition || !cmpTargetPosition || !cmpThisPosition.IsInWorld() || !cmpTargetPosition.IsInWorld()) 328 return; 329 330 var pos = cmpTargetPosition.GetPosition2D().sub(cmpThisPosition.GetPosition2D()); 331 cmpThisPosition.TurnTo(Math.atan2(pos.x, pos.y)); 332 }; 333 334 Engine.RegisterComponentType(IID_TurretAI, "TurretAI", TurretAI); -
binaries/data/mods/public/simulation/components/TurretHolder.js
1 function TurretHolder() {} 2 3 TurretHolder.prototype.Schema = 4 "<element name='TurretPoints'>" + 5 "<zeroOrMore>" + 6 "<element a:help='Element containing the offset coordinates and the template'>" + 7 "<anyName/>" + 8 "<interleave>" + 9 "<element name='Template'>" + 10 "<text/>" + 11 "</element>" + 12 "<element name='X'>" + 13 "<data type='decimal'/>" + 14 "</element>" + 15 "<element name='Y'>" + 16 "<data type='decimal'/>" + 17 "</element>" + 18 "<element name='Z'>" + 19 "<data type='decimal'/>" + 20 "</element>" + 21 "</interleave>" + 22 "</element>" + 23 "</zeroOrMore>" + 24 "</element>"; 25 26 /** 27 * Initialize TurretHolder Component. 28 */ 29 TurretHolder.prototype.Init = function() 30 { 31 this.turrets = []; 32 var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer); 33 // hack for atlas, don't create the turrets in Atlas, as the references get lost 34 // TODO implement some sort of tag for the turrets so they never get saved by Atlas 35 /* if (cmpTimer.GetTime() == 0) 36 cmpTimer.SetTimeout(this.entity, IID_TurretHolder, "CreateTurrets", 100, null); 37 else*/ 38 this.CreateTurrets(); 39 }; 40 41 /** 42 * Create the Turrets. 43 */ 44 TurretHolder.prototype.CreateTurrets = function() 45 { 46 for each (let turretPoint in this.template.TurretPoints) 47 { 48 var ent = Engine.AddEntity(turretPoint.Template); 49 var offset = new Vector3D(+turretPoint.X, +turretPoint.Y, +turretPoint.Z); 50 var cmpPosition = Engine.QueryInterface(ent, IID_Position); 51 if (cmpPosition) 52 cmpPosition.SetTurretParent(this.entity, offset); 53 this.turrets.push(ent); 54 } 55 var cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership); 56 if (cmpOwnership && cmpOwnership.GetOwner() != -1) 57 this.ChangeTurretOwnership(cmpOwnership.GetOwner()); 58 }; 59 60 /** 61 * Return the list of entities garrisoned inside. 62 */ 63 TurretHolder.prototype.GetTurrets = function() 64 { 65 return this.turrets; 66 }; 67 68 /** 69 * Destroys the entities. 70 */ 71 TurretHolder.prototype.OnDestroy = function() 72 { 73 for (let ent of this.turrets) 74 Engine.DestroyEntity(ent); 75 }; 76 77 /** 78 * Change the ownership of the turret. 79 */ 80 TurretHolder.prototype.OnOwnershipChanged = function(msg) 81 { 82 this.ChangeTurretOwnership(msg.to); 83 }; 84 85 /** 86 * Set the ownership of all present turrets to the same owner. 87 */ 88 TurretHolder.prototype.ChangeTurretOwnership = function(owner) 89 { 90 for (let ent of this.turrets) 91 { 92 var cmpOwnership = Engine.QueryInterface(ent, IID_Ownership); 93 if (cmpOwnership) 94 cmpOwnership.SetOwner(owner); 95 } 96 }; 97 98 Engine.RegisterComponentType(IID_TurretHolder, "TurretHolder", TurretHolder); 99 -
binaries/data/mods/public/simulation/templates/template_turret.xml
1 <?xml version="1.0" encoding="utf-8"?> 2 <Entity parent="template_entity_full"> 3 <Decay> 4 <Active>false</Active> 5 <SinkingAnim>false</SinkingAnim> 6 <DelayTime>80.0</DelayTime> 7 <SinkRate>0.01</SinkRate> 8 <SinkAccel>0.0</SinkAccel> 9 </Decay> 10 <Minimap> 11 <Type>unit</Type> 12 </Minimap> 13 <OverlayRenderer/> 14 <Selectable disable=""/> 15 <Sound> 16 <SoundGroups> 17 <attacked>interface/alarm/alarm_attackplayer.xml</attacked> 18 </SoundGroups> 19 </Sound> 20 <TurretAI/> 21 <Visibility> 22 <RetainInFog>false</RetainInFog> 23 <AlwaysVisible>false</AlwaysVisible> 24 <Preview>false</Preview> 25 <Corpse>false</Corpse> 26 </Visibility> 27 <Vision> 28 <Range>92</Range> 29 </Vision> 30 <VisualActor> 31 <SilhouetteDisplay>true</SilhouetteDisplay> 32 <SilhouetteOccluder>false</SilhouetteOccluder> 33 <VisibleInAtlasOnly>false</VisibleInAtlasOnly> 34 </VisualActor> 35 </Entity> -
binaries/data/mods/public/simulation/templates/units/brit_hero_bouddica_r.xml
Property changes on: binaries/data/mods/public/simulation/templates/template_turret.xml ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +text/xml \ No newline at end of property
1 <?xml version="1.0" encoding="utf-8"?> 2 <Entity parent="template_turret"> 3 <VisualActor> 4 <Actor>units/celts/boudicca_r2.xml</Actor> 5 </VisualActor> 6 </Entity> -
binaries/data/mods/public/simulation/templates/units/brit_hero_boudicca.xml
1 1 <?xml version="1.0" encoding="utf-8"?> 2 2 <Entity parent="template_unit_hero_cavalry_javelinist"> 3 <Attack> 4 <Ranged> 5 <TurretsOnly>true</TurretsOnly> 6 </Ranged> 7 </Attack> 3 8 <Auras> 4 9 <Aura1> 5 10 <Type>global</Type> … … 26 31 <History>Ammianus Marcellinus described how difficult it would be for a band of foreigners to deal with a Celt if he called in the help of his wife. For she was stronger than he was and could rain blows and kicks upon the assailants equal in force to the shots of a catapult. Boudicca, queen of the Iceni, was said to be 'very tall and terrifying in appearance; her voice was very harsh and a great mass of red hair fell over her shoulders. She wore a tunic of many colors over which a thick cloak was fastened by a brooch.</History> 27 32 <Icon>units/celt_hero_boudicca.png</Icon> 28 33 </Identity> 34 <TurretHolder> 35 <TurretPoints> 36 <Archer> 37 <Template>units/brit_hero_bouddica_r</Template> 38 <X>0</X> 39 <Y>1.4</Y> 40 <Z>-2.5</Z> 41 </Archer> 42 </TurretPoints> 43 </TurretHolder> 29 44 <VisualActor> 30 45 <Actor>units/celts/boudicca_chariot.xml</Actor> 31 46 </VisualActor> -
binaries/data/mods/public/simulation/templates/units/pers_cavalry_archer_a.xml
1 1 <?xml version="1.0" encoding="utf-8"?> 2 2 <Entity parent="units/pers_cavalry_archer_b"> 3 <Attack> 4 <Ranged> 5 <TurretsOnly>true</TurretsOnly> 6 </Ranged> 7 </Attack> 3 8 <Identity> 4 9 <Rank>Advanced</Rank> 5 10 </Identity> … … 6 11 <Promotion> 7 12 <Entity>units/pers_cavalry_archer_e</Entity> 8 13 </Promotion> 14 <TurretHolder> 15 <TurretPoints> 16 <Archer> 17 <Template>units/pers_cavalry_archer_rider_a</Template> 18 <X>1</X> 19 <Y>2.2</Y> 20 <Z>-4.0</Z> 21 </Archer> 22 </TurretPoints> 23 </TurretHolder> 9 24 <VisualActor> 10 25 <Actor>units/persians/cavalry_archer_a.xml</Actor> 11 26 </VisualActor> -
binaries/data/mods/public/simulation/templates/units/pers_cavalry_archer_e.xml
4 4 <Rank>Elite</Rank> 5 5 </Identity> 6 6 <Promotion disable=""/> 7 <TurretHolder> 8 <TurretPoints> 9 <Archer> 10 <Template>units/pers_cavalry_archer_rider_e</Template> 11 <X>1</X> 12 <Y>2.2</Y> 13 <Z>-4.0</Z> 14 </Archer> 15 </TurretPoints> 16 </TurretHolder> 7 17 <VisualActor> 8 18 <Actor>units/persians/cavalry_archer_e.xml</Actor> 9 19 </VisualActor> -
binaries/data/mods/public/simulation/templates/units/pers_cavalry_archer_rider_a.xml
1 <?xml version="1.0" encoding="utf-8"?> 2 <Entity parent="template_turret"> 3 <VisualActor> 4 <Actor>units/persians/cavalry_archer_a_r.xml</Actor> 5 </VisualActor> 6 </Entity> -
binaries/data/mods/public/simulation/templates/units/pers_cavalry_archer_rider_e.xml
Property changes on: binaries/data/mods/public/simulation/templates/units/pers_cavalry_archer_rider_a.xml ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +text/xml \ No newline at end of property
1 <?xml version="1.0" encoding="utf-8"?> 2 <Entity parent="template_turret"> 3 <VisualActor> 4 <Actor>units/persians/cavalry_archer_e_r.xml</Actor> 5 </VisualActor> 6 </Entity>