Line data Source code
1 : function RallyPoint() {} 2 : 3 1 : RallyPoint.prototype.Schema = 4 : "<a:component/><empty/>"; 5 : 6 1 : RallyPoint.prototype.Init = function() 7 : { 8 7 : this.pos = []; 9 7 : this.data = []; 10 : }; 11 : 12 1 : RallyPoint.prototype.AddPosition = function(x, z) 13 : { 14 14 : this.pos.push({ 15 : "x": x, 16 : "z": z 17 : }); 18 : }; 19 : 20 1 : RallyPoint.prototype.HasPositions = function() 21 : { 22 0 : return this.pos.length > 0; 23 : }; 24 : 25 1 : RallyPoint.prototype.GetFirstPosition = function() 26 : { 27 0 : return this.pos.length ? Vector2D.from3D(this.pos[0]) : new Vector2D(-1, -1); 28 : }; 29 : 30 1 : RallyPoint.prototype.GetPositions = function() 31 : { 32 : // Update positions for moving target entities 33 : 34 35 : var cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager); 35 35 : var cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership); 36 : 37 : // We must not affect the simulation state here (modifications of the 38 : // RallyPointRenderer are allowed though), so copy the state 39 35 : var ret = []; 40 35 : for (var i = 0; i < this.pos.length; i++) 41 : { 42 41 : ret.push(this.pos[i]); 43 : 44 : // Update the rallypoint coordinates if the target is alive 45 41 : if (!this.data[i] || !this.data[i].target || !this.TargetIsAlive(this.data[i].target)) 46 41 : continue; 47 : 48 : // and visible 49 0 : if (cmpRangeManager && cmpOwnership && 50 : cmpRangeManager.GetLosVisibility(this.data[i].target, cmpOwnership.GetOwner()) != "visible") 51 0 : continue; 52 : 53 : // Get the actual position of the target entity 54 0 : var cmpPosition = Engine.QueryInterface(this.data[i].target, IID_Position); 55 0 : if (!cmpPosition || !cmpPosition.IsInWorld()) 56 0 : continue; 57 : 58 0 : var targetPosition = cmpPosition.GetPosition2D(); 59 0 : if (!targetPosition) 60 0 : continue; 61 : 62 0 : if (this.pos[i].x == targetPosition.x && this.pos[i].z == targetPosition.y) 63 0 : continue; 64 : 65 0 : ret[i] = { "x": targetPosition.x, "z": targetPosition.y }; 66 0 : var cmpRallyPointRenderer = Engine.QueryInterface(this.entity, IID_RallyPointRenderer); 67 0 : if (cmpRallyPointRenderer) 68 0 : cmpRallyPointRenderer.UpdatePosition(i, targetPosition); 69 : } 70 : 71 35 : return ret; 72 : }; 73 : 74 : // Extra data for the rally point, should have a command property and then helpful data for that command 75 : // See getActionInfo in gui/input.js 76 1 : RallyPoint.prototype.AddData = function(data) 77 : { 78 14 : this.data.push(data); 79 : }; 80 : 81 : // Returns an array with the data associated with this rally point. Each element has the structure: 82 : // {"type": "walk/gather/garrison/...", "target": targetEntityId, "resourceType": "tree/fruit/ore/..."} where target 83 : // and resourceType (specific resource type) are optional, also target may be an invalid entity, check for existence. 84 1 : RallyPoint.prototype.GetData = function() 85 : { 86 28 : return this.data; 87 : }; 88 : 89 1 : RallyPoint.prototype.Unset = function() 90 : { 91 4 : this.pos = []; 92 4 : this.data = []; 93 : }; 94 : 95 1 : RallyPoint.prototype.Reset = function() 96 : { 97 3 : this.Unset(); 98 3 : var cmpRallyPointRenderer = Engine.QueryInterface(this.entity, IID_RallyPointRenderer); 99 3 : if (cmpRallyPointRenderer) 100 0 : cmpRallyPointRenderer.Reset(); 101 : }; 102 : 103 : /** 104 : * @param {number} entity - The entity ID of the entity to order to the rally point. 105 : * @param {string[]} ignore - The commands to ignore when performed on this.entity. 106 : * E.g. "garrison" when unloading. 107 : */ 108 1 : RallyPoint.prototype.OrderToRallyPoint = function(entity, ignore = []) 109 : { 110 0 : let cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership); 111 0 : if (!cmpOwnership) 112 0 : return; 113 0 : let owner = cmpOwnership.GetOwner(); 114 : 115 0 : let cmpEntOwnership = Engine.QueryInterface(entity, IID_Ownership); 116 0 : if (!cmpEntOwnership || cmpEntOwnership.GetOwner() != owner) 117 0 : return; 118 : 119 0 : let commands = GetRallyPointCommands(this, [entity]); 120 0 : if (!commands.length || 121 : commands[0].target == this.entity && ignore.includes(commands[0].type)) 122 0 : return; 123 : 124 0 : for (let command of commands) 125 0 : ProcessCommand(owner, command); 126 : }; 127 : 128 1 : RallyPoint.prototype.OnGlobalEntityRenamed = function(msg) 129 : { 130 0 : for (let data of this.data) 131 : { 132 0 : if (!data) 133 0 : continue; 134 0 : if (data.target && data.target == msg.entity) 135 0 : data.target = msg.newentity; 136 0 : if (data.source && data.source == msg.entity) 137 0 : data.source = msg.newentity; 138 : } 139 : 140 0 : if (msg.entity != this.entity) 141 0 : return; 142 : 143 0 : let cmpRallyPointNew = Engine.QueryInterface(msg.newentity, IID_RallyPoint); 144 0 : if (cmpRallyPointNew) 145 : { 146 0 : let rallyCoords = this.GetPositions(); 147 0 : let rallyData = this.GetData(); 148 0 : for (let i = 0; i < rallyCoords.length; ++i) 149 : { 150 0 : cmpRallyPointNew.AddPosition(rallyCoords[i].x, rallyCoords[i].z); 151 0 : cmpRallyPointNew.AddData(rallyData[i]); 152 : } 153 : } 154 : }; 155 : 156 1 : RallyPoint.prototype.OnOwnershipChanged = function(msg) 157 : { 158 : // No need to reset when constructing or destructing the entity 159 4 : if (msg.from == INVALID_PLAYER || msg.to == INVALID_PLAYER) 160 2 : return; 161 : 162 2 : this.Reset(); 163 : }; 164 : 165 : /** 166 : * Returns true if the target exists and has non-zero hitpoints. 167 : */ 168 1 : RallyPoint.prototype.TargetIsAlive = function(ent) 169 : { 170 13 : var cmpFormation = Engine.QueryInterface(ent, IID_Formation); 171 13 : if (cmpFormation) 172 0 : return true; 173 : 174 13 : var cmpHealth = QueryMiragedInterface(ent, IID_Health); 175 13 : return cmpHealth && cmpHealth.GetHitpoints() != 0; 176 : }; 177 : 178 1 : Engine.RegisterComponentType(IID_RallyPoint, "RallyPoint", RallyPoint);