Ticket #2062: watersink.patch

File watersink.patch, 6.2 KB (added by scythetwirler, 11 years ago)
  • binaries/data/mods/public/simulation/components/UnitMotionFlying.js

     
    11// (A serious implementation of this might want to use C++ instead of JS
    22// for performance; this is just for fun.)
    3 const shortFinal = 2.5;
     3const SHORT_FINAL = 2.5;
     4const SINK_LEVEL = 2;
    45function UnitMotionFlying() {}
    56
    67UnitMotionFlying.prototype.Schema =
     
    5859    var cmpPosition = Engine.QueryInterface(this.entity, IID_Position);
    5960    var pos = cmpPosition.GetPosition();
    6061    var angle = cmpPosition.GetRotation().y;
    61 
     62    var cmpTerrain = Engine.QueryInterface(SYSTEM_ENTITY, IID_Terrain);
     63    var ground = cmpTerrain.GetGroundLevel(pos.x, pos.z);
     64    var cmpWaterManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_WaterManager);
     65    var ground = Math.max(cmpTerrain.GetGroundLevel(pos.x, pos.z), cmpWaterManager.GetWaterLevel(pos.x, pos.z) - SINK_LEVEL);
    6266    var canTurn = true;
    6367
    64     if (!this.landing)
     68    if (this.landing)
    6569    {
    66         // If we haven't reached max speed yet then we're still on the ground;
    67         // otherwise we're taking off or flying
    68         // this.onGround in case of a go-around after landing (but not fully stopped)
    69         var cmpTerrain = Engine.QueryInterface(SYSTEM_ENTITY, IID_Terrain);
    70         var ground = cmpTerrain.GetGroundLevel(pos.x, pos.z);
    71         if (this.speed < this.template.TakeoffSpeed && this.onGround)
    72         {
    73             // Accelerate forwards
    74             this.speed = Math.min(this.template.MaxSpeed, this.speed + turnLength * this.template.AccelRate);
    75             canTurn = false;
    76             // Clamp to ground if below it, or descend if above
    77             if (pos.y < ground)
    78                 pos.y = ground;
    79             else if (pos.y > ground)
    80                 pos.y = Math.max(ground, pos.y - turnLength * this.template.ClimbRate);
    81         }
    82         else
    83         {
    84             this.onGround = false;
    85             // Climb/sink to max height above ground
    86             this.speed = Math.min(this.template.MaxSpeed, this.speed + turnLength * this.template.AccelRate);
    87             var targetHeight = ground + (+this.template.FlyingHeight);
    88             if (pos.y < targetHeight)
    89                 pos.y = Math.min(targetHeight, pos.y + turnLength * this.template.ClimbRate);
    90             else if (pos.y > targetHeight)
    91                 pos.y = Math.max(targetHeight, pos.y - turnLength * this.template.ClimbRate);           
    92         }
    93         cmpPosition.SetHeightFixed(pos.y);
    94     }
    95     else
    96     {
    9770        if (this.speed > 0 && this.onGround)
    9871        {
    9972            // Deaccelerate forwards...at a very reduced pace.
    10073            this.speed = Math.max(0, this.speed - turnLength * this.template.BrakingRate);
    10174            canTurn = false;
    102             // Clamp to ground if below it, or descend if above
    103             var cmpTerrain = Engine.QueryInterface(SYSTEM_ENTITY, IID_Terrain);
    104             var ground = cmpTerrain.GetGroundLevel(pos.x, pos.z);
     75            // Clamp to ground if below it, or descend if above                     
    10576            if (pos.y < ground)
    10677                pos.y = ground;
    10778            else if (pos.y > ground)
    108                 pos.y = Math.max(ground, pos.y - turnLength * this.template.ClimbRate);
    109             cmpPosition.SetHeightFixed(pos.y);         
     79                pos.y = Math.max(ground, pos.y - turnLength * this.template.ClimbRate);         
    11080        }
    11181        else if (this.speed == 0)
    11282        {
     
    12191            // We need to slow down to land!
    12292            this.speed = Math.max(this.template.LandingSpeed, this.speed - turnLength * this.template.SlowingRate);
    12393            canTurn = false;
    124             var cmpTerrain = Engine.QueryInterface(SYSTEM_ENTITY, IID_Terrain);
    125             var ground = cmpTerrain.GetGroundLevel(pos.x, pos.z);
    12694            var targetHeight = ground;
    12795            // Steep, then gradual descent.
    128             var descentRate = ((pos.y - targetHeight) / this.template.FlyingHeight * this.template.ClimbRate + shortFinal) * shortFinal;
     96            var descentRate = ((pos.y - targetHeight) / this.template.FlyingHeight * this.template.ClimbRate + SHORT_FINAL) * SHORT_FINAL;
    12997            if (pos.y < targetHeight)
    13098                pos.y = Math.max(targetHeight, pos.y + turnLength * descentRate);
    13199            else if (pos.y > targetHeight)
    132100                pos.y = Math.max(targetHeight, pos.y - turnLength * descentRate);
    133101            if (targetHeight == pos.y)
    134102                this.onGround = true;
    135             cmpPosition.SetHeightFixed(pos.y);
    136103        }       
    137104    }
     105    else
     106    {
     107        // If we haven't reached max speed yet then we're still on the ground;
     108        // otherwise we're taking off or flying
     109        // this.onGround in case of a go-around after landing (but not fully stopped)
     110        if (this.speed < this.template.TakeoffSpeed && this.onGround)
     111        {
     112            // Accelerate forwards
     113            this.speed = Math.min(this.template.MaxSpeed, this.speed + turnLength * this.template.AccelRate);
     114            canTurn = false;
     115            // Clamp to ground if below it, or descend if above
     116            if (pos.y < ground)
     117                pos.y = ground;
     118            else if (pos.y > ground)
     119                pos.y = Math.max(ground, pos.y - turnLength * this.template.ClimbRate);
     120        }
     121        else
     122        {
     123            this.onGround = false;
     124            // Climb/sink to max height above ground
     125            this.speed = Math.min(this.template.MaxSpeed, this.speed + turnLength * this.template.AccelRate);
     126            var targetHeight = ground + (+this.template.FlyingHeight);
     127            if (pos.y < targetHeight)
     128                pos.y = Math.min(targetHeight, pos.y + turnLength * this.template.ClimbRate);
     129            else if (pos.y > targetHeight)
     130                pos.y = Math.max(targetHeight, pos.y - turnLength * this.template.ClimbRate);           
     131        }
     132    }   
    138133
    139134    // If we're in range of the target then tell people that we've reached it
    140135    // (TODO: quantisation breaks this)
     
    144139        this.reachedTarget = true;
    145140        Engine.PostMessage(this.entity, MT_MotionChanged, { "starting": false, "error": false });
    146141    }
    147 
    148142    // If we're facing away from the target, and are still fairly close to it,
    149143    // then carry on going straight so we overshoot in a straight line
    150144    var isBehindTarget = ((this.targetX - pos.x) * Math.sin(angle) + (this.targetZ - pos.z) * Math.cos(angle) < 0);
    151145    // Overshoot the target: carry on straight
    152146    if (isBehindTarget && distFromTarget < this.template.MaxSpeed * this.template.OvershootTime)
    153147        canTurn = false;
    154 
    155148    if (canTurn)
    156149    {
    157150        // Turn towards the target
     
    170163
    171164    pos.x += this.speed * turnLength * Math.sin(angle);
    172165    pos.z += this.speed * turnLength * Math.cos(angle);
    173 
     166    cmpPosition.SetHeightFixed(pos.y);
    174167    cmpPosition.TurnTo(angle);
    175168    cmpPosition.MoveTo(pos.x, pos.z);
    176169};