Changeset View
Changeset View
Standalone View
Standalone View
binaries/data/mods/public/simulation/components/Turretable.js
- This file was copied from binaries/data/mods/public/simulation/components/Garrisonable.js.
function Garrisonable() {} | function Turretable() {} | ||||
Garrisonable.prototype.Schema = | Turretable.prototype.Schema = | ||||
"<a:help>Controls the garrisonability of an entity.</a:help>" + | "<empty/>"; | ||||
"<a:example>" + | |||||
"<Size>10</Size>" + | |||||
"</a:example>" + | |||||
"<element name='Size' a:help='Number of garrison slots the entity occupies.'>" + | |||||
"<data type='nonNegativeInteger'/>" + | |||||
"</element>"; | |||||
Garrisonable.prototype.Init = function() | Turretable.prototype.Init = function() | ||||
{ | { | ||||
}; | }; | ||||
/** | /** | ||||
* @return {number} - The number of slots this unit takes in a garrisonHolder. | * @return {number} - The entity ID of the entity this entity is turreted on. | ||||
*/ | */ | ||||
Garrisonable.prototype.UnitSize = function() | Turretable.prototype.HolderID = function() | ||||
{ | |||||
return ApplyValueModificationsToEntity("Garrisonable/Size", +this.template.Size, this.entity); | |||||
}; | |||||
/** | |||||
* Calculates the number of slots this unit takes in a garrisonHolder by | |||||
* adding the number of garrisoned slots to the equation. | |||||
* | |||||
* @return {number} - The number of slots this unit and its garrison takes in a garrisonHolder. | |||||
*/ | |||||
Garrisonable.prototype.TotalSize = function() | |||||
{ | |||||
let size = this.UnitSize(); | |||||
let cmpGarrisonHolder = Engine.QueryInterface(this.entity, IID_GarrisonHolder); | |||||
if (cmpGarrisonHolder) | |||||
size += cmpGarrisonHolder.OccupiedSlots(); | |||||
return size; | |||||
}; | |||||
/** | |||||
* @return {number} - The entity ID of the entity this entity is garrisoned in. | |||||
*/ | |||||
Garrisonable.prototype.HolderID = function() | |||||
{ | { | ||||
return this.holder || INVALID_ENTITY; | return this.holder || INVALID_ENTITY; | ||||
}; | }; | ||||
/** | /** | ||||
* @return {boolean} - Whether we're garrisoned. | * @return {boolean} - Whether we're turreted. | ||||
*/ | */ | ||||
Garrisonable.prototype.IsGarrisoned = function() | Turretable.prototype.IsTurreted = function() | ||||
{ | { | ||||
return !!this.holder; | return !!this.holder; | ||||
}; | }; | ||||
/** | /** | ||||
* @param {number} target - The entity ID to check. | * @param {number} target - The entity ID to check. | ||||
* @return {boolean} - Whether we can garrison. | * @return {boolean} - Whether we can occupy the turret. | ||||
*/ | */ | ||||
Garrisonable.prototype.CanGarrison = function(target) | Turretable.prototype.CanOccupy = function(target) | ||||
{ | { | ||||
if (this.holder) | if (this.holder) | ||||
return false; | return false; | ||||
let cmpGarrisonHolder = Engine.QueryInterface(target, IID_GarrisonHolder); | let cmpTurretHolder = Engine.QueryInterface(target, IID_TurretHolder); | ||||
return cmpGarrisonHolder && cmpGarrisonHolder.IsAllowedToGarrison(this.entity); | return cmpTurretHolder && cmpTurretHolder.CanOccupy(this.entity); | ||||
}; | }; | ||||
/** | /** | ||||
* @param {number} target - The entity ID of the entity this entity is being garrisoned in. | * @param {number} target - The entity ID of the entity this entity is being turreted on. | ||||
* @return {boolean} - Whether garrisoning succeeded. | * @param {string} turretPointName - Optionally the turret point name to occupy. | ||||
* @return {boolean} - Whether occupying succeeded. | |||||
*/ | */ | ||||
Garrisonable.prototype.Garrison = function(target, renamed = false) | Turretable.prototype.OccupyTurret = function(target, turretPointName = "") | ||||
{ | { | ||||
if (!this.CanGarrison(target)) | if (!this.CanOccupy(target)) | ||||
return false; | return false; | ||||
let cmpGarrisonHolder = Engine.QueryInterface(target, IID_GarrisonHolder); | let cmpTurretHolder = Engine.QueryInterface(target, IID_TurretHolder); | ||||
if (!cmpGarrisonHolder || !cmpGarrisonHolder.Garrison(this.entity)) | if (!cmpTurretHolder || !cmpTurretHolder.OccupyNamedTurret(this.entity, turretPointName)) | ||||
return false; | return false; | ||||
this.holder = target; | this.holder = target; | ||||
let cmpUnitAI = Engine.QueryInterface(this.entity, IID_UnitAI); | let cmpUnitAI = Engine.QueryInterface(this.entity, IID_UnitAI); | ||||
if (cmpUnitAI) | if (cmpUnitAI) | ||||
{ | |||||
cmpUnitAI.SetGarrisoned(); | cmpUnitAI.SetGarrisoned(); | ||||
cmpUnitAI.SetTurretStance(); | |||||
} | |||||
let cmpPosition = Engine.QueryInterface(this.entity, IID_Position); | let cmpUnitMotion = Engine.QueryInterface(this.entity, IID_UnitMotion); | ||||
if (cmpPosition) | if (cmpUnitMotion) | ||||
cmpPosition.MoveOutOfWorld(); | cmpUnitMotion.SetFacePointAfterMove(false); | ||||
// Remove the unit's obstruction to avoid interfering with pathing. | |||||
let cmpObstruction = Engine.QueryInterface(this.entity, IID_Obstruction); | |||||
if (cmpObstruction) | |||||
cmpObstruction.SetActive(false); | |||||
Engine.PostMessage(this.entity, MT_GarrisonedStateChanged, { | Engine.PostMessage(this.entity, MT_TurretedStateChanged, { | ||||
"oldHolder": INVALID_ENTITY, | "oldHolder": INVALID_ENTITY, | ||||
"holderID": target | "holderID": target | ||||
}); | }); | ||||
if (renamed) | |||||
return true; | |||||
let cmpTurretHolder = Engine.QueryInterface(target, IID_TurretHolder); | |||||
if (cmpTurretHolder) | |||||
cmpTurretHolder.OccupyTurret(this.entity); | |||||
return true; | return true; | ||||
}; | }; | ||||
/** | /** | ||||
* @param {boolean} forced - Optionally whether the spawning is forced. | * @param {boolean} forced - Optionally whether the leaving the turret is forced. | ||||
* @param {boolean} renamed - Optionally whether the ungarrisoning is due to renaming. | * @return {boolean} - Whether leaving the turret succeeded. | ||||
* @return {boolean} - Whether the ungarrisoning succeeded. | |||||
*/ | */ | ||||
Garrisonable.prototype.UnGarrison = function(forced = false, renamed = false) | Turretable.prototype.LeaveTurret = function(forced = false) | ||||
{ | { | ||||
if (!this.holder) | if (!this.holder) | ||||
return true; | return true; | ||||
let cmpGarrisonHolder = Engine.QueryInterface(this.holder, IID_GarrisonHolder); | let pos = PositionHelper.GetSpawnPosition(this.holder, this.entity, forced); | ||||
if (!cmpGarrisonHolder) | |||||
return false; | |||||
let pos = cmpGarrisonHolder.GetSpawnPosition(this.entity, forced); | |||||
if (!pos) | if (!pos) | ||||
return false; | return false; | ||||
if (!cmpGarrisonHolder.Eject(this.entity, forced)) | let cmpTurretHolder = Engine.QueryInterface(this.holder, IID_TurretHolder); | ||||
if (!cmpTurretHolder || !cmpTurretHolder.LeaveTurret(this.entity)) | |||||
return false; | return false; | ||||
let cmpUnitMotionEntity = Engine.QueryInterface(this.entity, IID_UnitMotion); | |||||
if (cmpUnitMotionEntity) | |||||
cmpUnitMotionEntity.SetFacePointAfterMove(true); | |||||
let cmpPosition = Engine.QueryInterface(this.entity, IID_Position); | let cmpPosition = Engine.QueryInterface(this.entity, IID_Position); | ||||
if (cmpPosition) | if (cmpPosition) | ||||
{ | { | ||||
cmpPosition.JumpTo(pos.x, pos.z); | cmpPosition.JumpTo(pos.x, pos.z); | ||||
cmpPosition.SetHeightOffset(0); | cmpPosition.SetHeightOffset(0); | ||||
} | } | ||||
let cmpHolderPosition = Engine.QueryInterface(this.holder, IID_Position); | let cmpHolderPosition = Engine.QueryInterface(this.holder, IID_Position); | ||||
if (cmpHolderPosition) | if (cmpHolderPosition) | ||||
cmpPosition.SetYRotation(cmpHolderPosition.GetPosition().horizAngleTo(pos)); | cmpPosition.SetYRotation(cmpHolderPosition.GetPosition().horizAngleTo(pos)); | ||||
let cmpUnitAI = Engine.QueryInterface(this.entity, IID_UnitAI); | let cmpUnitAI = Engine.QueryInterface(this.entity, IID_UnitAI); | ||||
if (cmpUnitAI) | if (cmpUnitAI) | ||||
{ | { | ||||
cmpUnitAI.Ungarrison(); | cmpUnitAI.Ungarrison(); | ||||
cmpUnitAI.UnsetGarrisoned(); | cmpUnitAI.UnsetGarrisoned(); | ||||
cmpUnitAI.ResetTurretStance(); | |||||
} | } | ||||
Engine.PostMessage(this.entity, MT_GarrisonedStateChanged, { | // Reset the obstruction flags to template defaults. | ||||
let cmpObstruction = Engine.QueryInterface(this.entity, IID_Obstruction); | |||||
if (cmpObstruction) | |||||
cmpObstruction.SetActive(true); | |||||
Engine.PostMessage(this.entity, MT_TurretedStateChanged, { | |||||
"oldHolder": this.holder, | "oldHolder": this.holder, | ||||
"holderID": INVALID_ENTITY | "holderID": INVALID_ENTITY | ||||
}); | }); | ||||
if (renamed) | let cmpRallyPoint = Engine.QueryInterface(this.holder, IID_RallyPoint); | ||||
return true; | if (cmpRallyPoint) | ||||
cmpRallyPoint.OrderToRallyPoint(this.entity, ["occupy-turret"]); | |||||
let cmpTurretHolder = Engine.QueryInterface(this.holder, IID_TurretHolder); | |||||
if (cmpTurretHolder) | |||||
cmpTurretHolder.LeaveTurret(this.entity); | |||||
cmpGarrisonHolder.OrderToRallyPoint(this.entity); | |||||
delete this.holder; | delete this.holder; | ||||
return true; | return true; | ||||
}; | }; | ||||
Garrisonable.prototype.OnEntityRenamed = function(msg) | Turretable.prototype.OnEntityRenamed = function(msg) | ||||
{ | { | ||||
if (!this.holder) | if (!this.holder) | ||||
return; | return; | ||||
let cmpGarrisonHolder = Engine.QueryInterface(this.holder, IID_GarrisonHolder); | |||||
if (cmpGarrisonHolder) | |||||
{ | |||||
this.UnGarrison(true, true); | |||||
let cmpGarrisonable = Engine.QueryInterface(msg.newentity, IID_Garrisonable); | |||||
if (cmpGarrisonable) | |||||
cmpGarrisonable.Garrison(this.holder, true); | |||||
} | |||||
// We process EntityRenamed of turrets seperately since we | |||||
// want to occupy the same position after being renamed. | |||||
let cmpTurretHolder = Engine.QueryInterface(this.holder, IID_TurretHolder); | let cmpTurretHolder = Engine.QueryInterface(this.holder, IID_TurretHolder); | ||||
if (cmpTurretHolder) | if (!cmpTurretHolder) | ||||
cmpTurretHolder.SwapEntities(msg.entity, msg.newentity); | return; | ||||
delete this.holder; | let holder = this.holder; | ||||
let currentPoint = cmpTurretHolder.GetOccupiedTurretName(this.entity); | |||||
this.LeaveTurret(true); | |||||
let cmpTurretableNew = Engine.QueryInterface(msg.newentity, IID_Turretable); | |||||
if (cmpTurretableNew) | |||||
cmpTurretableNew.OccupyTurret(holder, currentPoint); | |||||
}; | |||||
Turretable.prototype.OnOwnershipChanged = function(msg) | |||||
{ | |||||
if (!this.holder) | |||||
return; | |||||
if (msg.to == INVALID_PLAYER) | |||||
this.LeaveTurret(true); | |||||
else if (!IsOwnedByMutualAllyOfEntity(this.entity, this.holder)) | |||||
this.LeaveTurret(); | |||||
}; | }; | ||||
Engine.RegisterComponentType(IID_Garrisonable, "Garrisonable", Garrisonable); | Engine.RegisterComponentType(IID_Turretable, "Turretable", Turretable); |
Wildfire Games · Phabricator