Advertisement
Agent_Ash

SmoothMoveTurn mixin

Jan 11th, 2025
66
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 5.95 KB | None | 0 0
  1. Mixin class SmoothMoveTurnMixin
  2. {
  3.     //ChaseSmooth works by  storing the state ChaseSmooth was called from, and using that information along with
  4.     //the actor's tics value to determine if the ChaseSmoth call each tic should have the chance to result in an attack, or just moving & turning.
  5.     //The smooth turning functions work in a similar way.
  6.     Actor smtActor;//the actor instance this mixin belongs to
  7.     State smtChaseState;
  8.     bool smtChasing;//controls wether to call A_Chase or A_Wander in ChaseSmooth
  9.     int smtChaseFlags;//stores any A_Chase flags for use during Tick()
  10.    
  11.     State smtTurnState;
  12.     double smtAngleTarget;
  13.     double smtAngleTurnSpeed;//the difference between starting angle and smtAngleTarget divided by smtTurnState.tics
  14.     double smtAngleTurnSpeedMax;//if > 0, if smtLimitAngleTurnSpeed is true and when chasing or wandering, limit smtAngleTurnSpeed to to this
  15.     bool smtLimitAngleTurnSpeed;//set to true when chasing or wandering
  16.  
  17.     bool affectPitch;
  18.     double smtPitchTarget;
  19.     double smtPitchTurnSpeed;//the difference between starting Pitch and smtPitchTarget divided by smtTurnState.tics
  20.     double smtPitchTurnSpeedMax;//if > 0, if smtLimitPitchTurnSpeed is true and when chasing or wandering, limit smtPitchTurnSpeed to to this
  21.     bool smtLimitPitchTurnSpeed;//set to true when chasing or wandering
  22.  
  23.     property ChaseAffectsPitch : affectPitch;
  24.    
  25.     void InitSmoothMoveTurnMixin(Actor other, double AngleTurnSpeedMax = 0, double PitchTurnSpeedMax = 0)
  26.     {
  27.         smtActor = other;
  28.         smtAngleTurnSpeedMax = AngleTurnSpeedMax;
  29.         smtPitchTurnSpeedMax = PitchTurnSpeedMax;
  30.     }
  31.    
  32.     //To be called from the smtActor's Tick()
  33.     void UpdateSmoothMoveTurn()
  34.     {
  35.         if(smtActor == null)
  36.         {
  37.             return;
  38.         }
  39.         //this chase behavior is called when the monster is in a state that called A_ChaseSmooth,
  40.         //but is not the first tic in that state
  41.         if(smtChaseState && smtActor.curState && smtActor.tics != smtActor.curState.tics)
  42.         {
  43.             if (smtActor.curState == smtChaseState)
  44.             {
  45.                 ChaseSmooth(melee : null, missile : null, chaseFlags : smtChaseFlags, chase : smtChasing);
  46.             }
  47.             else
  48.             {
  49.                 smtChaseState = null;
  50.                 smtChasing = false;
  51.                 smtChaseFlags = 0;
  52.             }
  53.         }
  54.         //this is used for turning smoothly.
  55.         if (smtTurnState && smtActor.curState && smtActor.tics != smtActor.curState.tics)
  56.         {
  57.             if(smtActor.curState == smtTurnState)
  58.             {
  59.                 TurnTowards();
  60.             }
  61.             else
  62.             {
  63.                 smtTurnState = null;
  64.                 smtLimitAngleTurnSpeed = false;
  65.                 smtLimitPitchTurnSpeed = false;
  66.             }
  67.         }
  68.     }
  69.    
  70.     //Smooth chasing code by Boondorl
  71.     //Smooth turning code by phantombeta
  72.     void ChaseSmooth(StateLabel melee = '_a_chase_default', StateLabel missile = '_a_chase_default', int chaseFlags = 0, bool chase = true)
  73.     {
  74.         smtChasing = chase;
  75.         smtChaseState = smtActor.curState;
  76.         smtChaseFlags = chaseFlags;
  77.  
  78.         Vector3 tempPos = smtActor.pos;
  79.         double angleTemp = smtActor.angle;
  80.         smtLimitAngleTurnSpeed = true;
  81.         double pitchTemp = smtActor.pitch;
  82.         if (affectPitch)
  83.             smtLimitpitchTurnSpeed = true;
  84.        
  85.         if(chase)
  86.         {
  87.             if(smtActor.target == null)
  88.             {
  89.                 return;
  90.             }
  91.             A_Chase(melee,missile,chaseFlags);
  92.         }
  93.         else
  94.         {
  95.             A_Wander(chaseFlags);
  96.         }
  97.  
  98.         Vector3 diff = (smtActor.pos - tempPos);
  99.         Vector3 dir = !(diff ~== (0, 0, 0)) ? diff.Unit() : (0, 0, 0);
  100.         smtActor.SetOrigin(tempPos + dir * smtActor.speed,true);
  101.        
  102.         smtActor.A_SetAngle(angleTemp);
  103.         if (affectPitch)
  104.         {
  105.             smtActor.A_SetPitch(pitchTemp);
  106.         }
  107.         //only rotate for the initial ChaseSmooth call, and not the automatic ones from Tick()
  108.         if(smtActor.tics == smtActor.curState.tics)
  109.         {
  110.             FaceAngleSmooth(smtActor.moveDir * 45, smtActor.moveDir * 45);
  111.         }
  112.     }
  113.  
  114.     //Shortcut for smooth wandering.  
  115.     void WanderSmooth(int flags = 0)
  116.     {
  117.         ChaseSmooth(null, null, flags, false);
  118.     }
  119.    
  120.     //Smooth variant of A_Face(). Pass target as a parameter to replicate A_FaceTarget.
  121.     void FaceSmooth(Actor other = null,int flags = 0)
  122.     {
  123.         if(other == null)
  124.         {
  125.             return;
  126.         }
  127.         double angleTemp = smtActor.angle;
  128.         smtActor.A_Face(other,0,0,0,0,flags);//for pitch setting
  129.         smtActor.A_SetAngle(angleTemp);
  130.         FacePosSmooth(other.pos + (0,0,flags == FAF_MIDDLE ? double(other.height) / 2 : 0));
  131.     }
  132.     //for facing a position
  133.     void FacePosSmooth(Vector3 targetPos)
  134.     {
  135.         Vector3 sCoords = LevelLocals.SphericalCoords(smtActor.pos,targetPos,(smtActor.angle,smtActor.pitch));
  136.         FaceAngleSmooth(smtActor.angle - sCoords.x, smtActor.pitch - sCoords.y);
  137.     }
  138.    
  139.     void FaceAngleSmooth(double a, double p = 0)
  140.     {
  141.         smtTurnState = smtActor.curState;
  142.         smtAngleTarget = a;
  143.         double angDiff = DeltaAngle(smtActor.angle,smtAngleTarget);
  144.         smtAngleTurnSpeed = abs(angDiff / (smtTurnState.tics > 0 ? smtTurnState.tics : 1));
  145.         smtPitchTarget = p;
  146.         double pitchDiff = DeltaAngle(smtActor.Pitch,smtPitchTarget);
  147.         smtPitchTurnSpeed = abs(pitchDiff / (smtTurnState.tics > 0 ? smtTurnState.tics : 1));
  148.         if(smtLimitAngleTurnSpeed && smtAngleTurnSpeedMax > 0)
  149.         {
  150.             smtAngleTurnSpeed = Clamp(smtAngleTurnSpeed,0,smtAngleTurnSpeedMax);
  151.             smtPitchTurnSpeed = Clamp(smtPitchTurnSpeed,0,smtPitchTurnSpeedMax);
  152.         }
  153.         TurnTowards();
  154.     }
  155.     //the base smooth turning function, turns smoothly towards any angle.
  156.     //This is only  to be called from Tick(), ChaseSmooth, or the other smooth rotating functions.
  157.     protected void TurnTowards()
  158.     {
  159.         double angDiff = DeltaAngle(smtActor.angle,smtAngleTarget);
  160.         double angleChange = angDiff < 0 ? max(-smtAngleTurnSpeed, angDiff) : min(smtAngleTurnSpeed, angDiff);
  161.         smtActor.A_SetAngle(smtActor.angle + angleChange);
  162.  
  163.         if (affectPitch)
  164.         {
  165.             double pitDiff = DeltaAngle(smtActor.pitch,smtpitchTarget);
  166.             double pitchChange = pitDiff < 0 ? max(-smtpitchTurnSpeed, pitDiff) : min(smtpitchTurnSpeed, pitDiff);
  167.             smtActor.A_Setpitch(smtActor.pitch + pitchChange);
  168.         }
  169.         //console.printf("[SmoothMoveTurnMixin/TurnTowards] smtAngleTarget = %f, angDiff = %f, smtAngleTurnSpeed = %f, angleChange = %f, angle = %f",smtAngleTarget,angDiff,smtAngleTurnSpeed,angleChange,smtActor.angle);
  170.     }
  171. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement