Make planes about 20% cooler. Fixes #2067.

This was SVN commit r13694.
This commit is contained in:
alpha123 2013-08-17 22:55:16 +00:00
parent abce308281
commit a18262e7b1
3 changed files with 159 additions and 63 deletions

View File

@ -32,6 +32,7 @@ GarrisonHolder.prototype.Init = function()
this.entities = [];
this.spaceOccupied = 0;
this.timer = undefined;
this.allowGarrisoning = [];
};
/**
@ -82,7 +83,31 @@ GarrisonHolder.prototype.EjectEntitiesOnDestroy = function()
if (this.template.EjectEntitiesOnDestroy == "true")
return true;
return false;
}
};
/**
* Set this entity to allow or disallow garrisoning in
* Every component calling this function should do it with its own ID, and as long as one
* component doesn't allow this entity to garrison, it can't be garrisoned
* When this entity already contains garrisoned soldiers,
* these will not be able to ungarrison until the flag is set to true again.
*
* This more useful for modern-day features. For example you can't garrison or ungarrison
* a driving vehicle or plane.
*/
GarrisonHolder.prototype.AllowGarrisoning = function(allow, callerID)
{
this.allowGarrisoning[callerID] = allow;
};
/**
* Check if no component of this entity blocks garrisoning
* (f.e. because the vehicle is moving too fast)
*/
GarrisonHolder.prototype.IsGarrisoningAllowed = function()
{
return this.allowGarrisoning.every(function (x) x);
};
/**
* Get number of garrisoned units capable of shooting arrows
@ -107,6 +132,9 @@ GarrisonHolder.prototype.GetGarrisonedArcherCount = function(garrisonArrowClasse
*/
GarrisonHolder.prototype.AllowedToGarrison = function(entity)
{
if (!this.IsGarrisoningAllowed())
return false;
var allowedClasses = this.GetAllowedClassesList();
var entityClasses = (Engine.QueryInterface(entity, IID_Identity)).GetClassesList();
// Check if the unit is allowed to be garrisoned inside the building
@ -167,11 +195,11 @@ GarrisonHolder.prototype.Garrison = function(entity)
*/
GarrisonHolder.prototype.Eject = function(entity, forced)
{
var entityIndex = this.entities.indexOf(entity);
// Error: invalid entity ID, usually it's already been ejected
if (entityIndex == -1)
{ // Error: invalid entity ID, usually it's already been ejected
return false; // Fail
}
// Find spawning location
var cmpFootprint = Engine.QueryInterface(this.entity, IID_Footprint);
@ -237,6 +265,8 @@ GarrisonHolder.prototype.OrderWalkToRallyPoint = function(entities)
*/
GarrisonHolder.prototype.PerformEject = function(entities, forced)
{
if (!this.IsGarrisoningAllowed() && !forced)
return false
var ejectedEntities = [];
var success = true;
for each (var entity in entities)

View File

@ -1,6 +1,6 @@
// (A serious implementation of this might want to use C++ instead of JS
// for performance; this is just for fun.)
const shortFinal = 2.5;
const SHORT_FINAL = 2.5;
function UnitMotionFlying() {}
UnitMotionFlying.prototype.Schema =
@ -33,6 +33,9 @@ UnitMotionFlying.prototype.Schema =
"</element>" +
"<element name='ClimbRate'>" +
"<ref name='nonNegativeDecimal'/>" +
"</element>" +
"<element name='DiesInWater'>" +
"<data type='boolean'/>" +
"</element>";
UnitMotionFlying.prototype.Init = function()
@ -46,30 +49,89 @@ UnitMotionFlying.prototype.Init = function()
this.speed = 0;
this.landing = false;
this.onGround = true;
this.pitch = 0;
this.roll = 0;
this.waterDeath = false;
};
UnitMotionFlying.prototype.OnUpdate = function(msg)
{
var turnLength = msg.turnLength;
if (!this.hasTarget)
return;
var cmpGarrisonHolder = Engine.QueryInterface(this.entity, IID_GarrisonHolder);
var cmpHealth = Engine.QueryInterface(this.entity, IID_Health);
var cmpPosition = Engine.QueryInterface(this.entity, IID_Position);
var pos = cmpPosition.GetPosition();
var angle = cmpPosition.GetRotation().y;
var cmpTerrain = Engine.QueryInterface(SYSTEM_ENTITY, IID_Terrain);
var cmpWaterManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_WaterManager);
var ground = Math.max(cmpTerrain.GetGroundLevel(pos.x, pos.z), cmpWaterManager.GetWaterLevel(pos.x, pos.z));
var newangle = angle;
var canTurn = true;
if (!this.landing)
if (this.landing)
{
if (this.speed > 0 && this.onGround)
{
this.pitch = 0;
// Deaccelerate forwards...at a very reduced pace.
if (this.waterDeath)
this.speed = Math.max(0, this.speed - turnLength * this.template.BrakingRate * 10);
else
this.speed = Math.max(0, this.speed - turnLength * this.template.BrakingRate);
canTurn = false;
// Clamp to ground if below it, or descend if above
if (pos.y < ground)
pos.y = ground;
else if (pos.y > ground)
pos.y = Math.max(ground, pos.y - turnLength * this.template.ClimbRate);
}
else if (this.speed == 0 && this.onGround)
{
if (this.waterDeath)
cmpHealth.Kill();
this.pitch = 0;
// We've stopped.
cmpGarrisonHolder.AllowGarrisoning(true,"UnitMotionFlying")
canTurn = false;
this.hasTarget = false;
this.landing = false;
}
else
{
// Final Approach
// We need to slow down to land!
this.speed = Math.max(this.template.LandingSpeed, this.speed - turnLength * this.template.SlowingRate);
canTurn = false;
var targetHeight = ground;
// Steep, then gradual descent.
if ((pos.y - targetHeight) / this.template.FlyingHeight > 1 / SHORT_FINAL)
this.pitch = - Math.PI / 18;
else
this.pitch = Math.PI / 18;
var descentRate = ((pos.y - targetHeight) / this.template.FlyingHeight * this.template.ClimbRate + SHORT_FINAL) * SHORT_FINAL;
if (pos.y < targetHeight)
pos.y = Math.max(targetHeight, pos.y + turnLength * descentRate);
else if (pos.y > targetHeight)
pos.y = Math.max(targetHeight, pos.y - turnLength * descentRate);
if (targetHeight == pos.y)
{
this.onGround = true;
if (targetHeight == cmpWaterManager.GetWaterLevel(pos.x, pos.z) && this.template.DiesInWater)
this.waterDeath = true;
}
}
}
else
{
// If we haven't reached max speed yet then we're still on the ground;
// otherwise we're taking off or flying
// this.onGround in case of a go-around after landing (but not fully stopped)
var cmpTerrain = Engine.QueryInterface(SYSTEM_ENTITY, IID_Terrain);
var ground = cmpTerrain.GetGroundLevel(pos.x, pos.z);
if (this.speed < this.template.TakeoffSpeed && this.onGround)
{
cmpGarrisonHolder.AllowGarrisoning(false,"UnitMotionFlying")
this.pitch = 0;
// Accelerate forwards
this.speed = Math.min(this.template.MaxSpeed, this.speed + turnLength * this.template.AccelRate);
canTurn = false;
@ -85,54 +147,20 @@ UnitMotionFlying.prototype.OnUpdate = function(msg)
// Climb/sink to max height above ground
this.speed = Math.min(this.template.MaxSpeed, this.speed + turnLength * this.template.AccelRate);
var targetHeight = ground + (+this.template.FlyingHeight);
if (Math.abs(pos.y-targetHeight) > this.template.FlyingHeight/5)
{
this.pitch = Math.PI / 9;
canTurn = false;
}
else
this.pitch = 0;
if (pos.y < targetHeight)
pos.y = Math.min(targetHeight, pos.y + turnLength * this.template.ClimbRate);
else if (pos.y > targetHeight)
{
pos.y = Math.max(targetHeight, pos.y - turnLength * this.template.ClimbRate);
}
cmpPosition.SetHeightFixed(pos.y);
}
else
{
if (this.speed > 0 && this.onGround)
{
// Deaccelerate forwards...at a very reduced pace.
this.speed = Math.max(0, this.speed - turnLength * this.template.BrakingRate);
canTurn = false;
// Clamp to ground if below it, or descend if above
var cmpTerrain = Engine.QueryInterface(SYSTEM_ENTITY, IID_Terrain);
var ground = cmpTerrain.GetGroundLevel(pos.x, pos.z);
if (pos.y < ground)
pos.y = ground;
else if (pos.y > ground)
pos.y = Math.max(ground, pos.y - turnLength * this.template.ClimbRate);
cmpPosition.SetHeightFixed(pos.y);
}
else if (this.speed == 0)
{
// We've stopped.
canTurn = false;
this.hasTarget = false;
this.landing = false;
}
else
{
// Final Approach
// We need to slow down to land!
this.speed = Math.max(this.template.LandingSpeed, this.speed - turnLength * this.template.SlowingRate);
canTurn = false;
var cmpTerrain = Engine.QueryInterface(SYSTEM_ENTITY, IID_Terrain);
var ground = cmpTerrain.GetGroundLevel(pos.x, pos.z);
var targetHeight = ground;
// Steep, then gradual descent.
var descentRate = ((pos.y - targetHeight) / this.template.FlyingHeight * this.template.ClimbRate + shortFinal) * shortFinal;
if (pos.y < targetHeight)
pos.y = Math.max(targetHeight, pos.y + turnLength * descentRate);
else if (pos.y > targetHeight)
pos.y = Math.max(targetHeight, pos.y - turnLength * descentRate);
if (targetHeight == pos.y)
this.onGround = true;
cmpPosition.SetHeightFixed(pos.y);
this.pitch = -1 * this.pitch;
}
}
}
@ -165,13 +193,22 @@ UnitMotionFlying.prototype.OnUpdate = function(msg)
var deltaClamped = Math.min(Math.max(delta, -this.template.TurnRate * turnLength), this.template.TurnRate * turnLength);
// Calculate new orientation, in a peculiar way in order to make sure the
// result gets close to targetAngle (rather than being n*2*pi out)
angle = targetAngle + deltaClamped - delta;
newangle = targetAngle + deltaClamped - delta;
if (newangle - angle > Math.PI / 18)
this.roll = Math.PI / 9;
else if (newangle - angle < -Math.PI / 18)
this.roll = - Math.PI / 9;
else
this.roll = newangle - angle;
}
else
this.roll = 0;
pos.x += this.speed * turnLength * Math.sin(angle);
pos.z += this.speed * turnLength * Math.cos(angle);
cmpPosition.TurnTo(angle);
cmpPosition.SetHeightFixed(pos.y);
cmpPosition.TurnTo(newangle);
cmpPosition.SetXZRotation(this.pitch, this.roll);
cmpPosition.MoveTo(pos.x, pos.z);
};
@ -251,7 +288,9 @@ UnitMotionFlying.prototype.FaceTowardsPoint = function(x, z)
UnitMotionFlying.prototype.StopMoving = function()
{
//Invert
this.landing = !this.landing;
if (!this.waterDeath)
this.landing = !this.landing;
};
UnitMotionFlying.prototype.SetDebugOverlay = function(enabled)

View File

@ -13,6 +13,26 @@
<Spread>1.5</Spread>
</Ranged>
</Attack>
<BuildingAI>
<DefaultArrowCount>3</DefaultArrowCount>
<GarrisonArrowMultiplier>1</GarrisonArrowMultiplier>
<GarrisonArrowClasses>Infantry</GarrisonArrowClasses>
</BuildingAI>
<GarrisonHolder>
<Max>1</Max>
<EjectHealth>0</EjectHealth>
<List datatype="tokens">Support Infantry</List>
<BuffHeal>1</BuffHeal>
<LoadingRange>5</LoadingRange>
<EjectEntitiesOnDestroy>false</EjectEntitiesOnDestroy>
</GarrisonHolder>
<Decay>
<Inactive/>
<SinkingAnim/>
<DelayTime>0.0</DelayTime>
<SinkRate>3.0</SinkRate>
<SinkAccel>7.0</SinkAccel>
</Decay>
<Identity>
<Civ>hele</Civ>
<SpecificName>P-51 Mustang</SpecificName>
@ -21,9 +41,15 @@
<Icon>units/global_mustang.png</Icon>
<Formations datatype="tokens" replace=""/>
</Identity>
<Health>
<Max>100</Max>
<Unhealable>true</Unhealable>
<Repairable>true</Repairable>
</Health>
<Obstruction disable=""/>
<Position>
<TurnRate>1.0</TurnRate>
<Floating>true</Floating>
</Position>
<UnitMotion disable=""/>
<UnitMotionFlying>
@ -36,7 +62,8 @@
<TurnRate>1.0</TurnRate>
<OvershootTime>2.0</OvershootTime>
<FlyingHeight>50.0</FlyingHeight>
<ClimbRate>5.0</ClimbRate>
<ClimbRate>15.0</ClimbRate>
<DiesInWater>true</DiesInWater>
</UnitMotionFlying>
<Vision>
<Range>100</Range>