]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/server/g_subs.qc
Merge branch 'master' into mirceakitsune/func_train_beizer_curve
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / g_subs.qc
index df63a70bb85d4f01578823b1b4ea3ceaba48f8ce..464312b8da89e44be372c02b3b5de9286c091508 100644 (file)
@@ -2,7 +2,6 @@ void SUB_Null() {}
 float SUB_True() { return 1; }
 float SUB_False() { return 0; }
 
-void(vector destangle, float tspeed, void() func) SUB_CalcAngleMove;
 void()  SUB_CalcMoveDone;
 void() SUB_CalcAngleMoveDone;
 //void() SUB_UseTargets;
@@ -171,6 +170,7 @@ void SUB_CalcMoveDone (void)
                self.think1 ();
 }
 
+.float bezier_turn;
 void SUB_CalcMove_controller_think (void)
 {
        entity oldself;
@@ -188,12 +188,31 @@ void SUB_CalcMove_controller_think (void)
 
                traveltime = self.animstate_endtime - self.animstate_starttime;
                phasepos = (nexttick - self.animstate_starttime) / traveltime; // range: [0, 1]
-               if(self.platmovetype != 1)
+               if(!self.platmovetype)
+                       self.platmovetype = 2; // default
+               switch(self.platmovetype)
                {
-                       phasepos = 3.14159265 + (phasepos * 3.14159265); // range: [pi, 2pi]
-                       phasepos = cos(phasepos); // cos [pi, 2pi] is in [-1, 1]
-                       phasepos = phasepos + 1; // correct range to [0, 2]
-                       phasepos = phasepos / 2; // correct range to [0, 1]
+                       case 1: // linear
+                               break;
+                       case 2: // cosine
+                               /* old version, good for mathematical reference
+                               phasepos = 3.14159265 + (phasepos * 3.14159265); // range: [pi, 2pi]
+                               phasepos = cos(phasepos); // cos [pi, 2pi] is in [-1, 1]
+                               phasepos = phasepos + 1; // correct range to [0, 2]
+                               phasepos = phasepos / 2; // correct range to [0, 1]
+                               */
+
+                               phasepos = (1 - cos(phasepos * 3.14159265)) / 2;
+                               break;
+                       case 3: // inverted cosine
+                               phasepos = acos(1 - phasepos * 2) / 3.14159265;
+                               break;
+                       case 4: // half cosine
+                               phasepos = (1 - cos(phasepos * (3.14159265 / 2)));
+                               break;
+                       case 5: // inverted half cosine
+                               phasepos = sin(phasepos * (3.14159265 / 2));
+                               break;
                }
                nextpos = self.origin + (delta * phasepos) + (delta2 * phasepos * phasepos);
                // derivative: delta + 2 * delta2 * phasepos (e.g. for angle positioning)
@@ -206,6 +225,14 @@ void SUB_CalcMove_controller_think (void)
                        veloc = veloc * (1 / sys_frametime); // so it arrives for the next frame
                }
                self.owner.velocity = veloc;
+               if(self.owner.bezier_turn)
+               {
+                       vector vel;
+                       vel = delta + 2 * delta2 * phasepos;
+                       vel_z = -vel_z; // invert z velocity
+                       vel = vectoangles(vel);
+                       self.owner.angles = vel;
+               }
                self.nextthink = nexttick;
        } else {
                // derivative: delta + 2 * delta2 (e.g. for angle positioning)
@@ -229,6 +256,7 @@ void SUB_CalcMove_controller_setbezier (entity controller, vector org, vector co
 
        controller.destvec = 2 * control; // control point
        controller.destvec2 = dest - 2 * control; // quadratic part required to reach end point
+       // also: initial d/dphasepos origin = 2 * control, final speed = 2 * (dest - control)
 }
 
 void SUB_CalcMove_controller_setlinear (entity controller, vector org, vector dest)
@@ -244,7 +272,13 @@ void SUB_CalcMove_controller_setlinear (entity controller, vector org, vector de
        controller.destvec2 = '0 0 0';
 }
 
-void SUB_CalcMove_Bezier (vector tcontrol, vector tdest, float tspeed, void() func)
+float TSPEED_TIME = -1;
+float TSPEED_LINEAR = 0;
+float TSPEED_START = 1;
+float TSPEED_END = 2;
+// TODO average too?
+
+void SUB_CalcMove_Bezier (vector tcontrol, vector tdest, float tspeedtype, float tspeed, void() func)
 {
        float   traveltime;
        entity controller;
@@ -256,10 +290,22 @@ void SUB_CalcMove_Bezier (vector tcontrol, vector tdest, float tspeed, void() fu
        self.finaldest = tdest;
        self.think = SUB_CalcMoveDone;
 
-       if(tspeed > 0) // positive: start speed
-               traveltime = 2 * vlen(tcontrol - self.origin) /  tspeed;
-       else // negative: end speed
-               traveltime = 2 * vlen(tcontrol - tdest)       / -tspeed;
+       switch(tspeedtype)
+       {
+               default:
+               case TSPEED_START:
+                       traveltime = 2 * vlen(tcontrol - self.origin) / tspeed;
+                       break;
+               case TSPEED_END:
+                       traveltime = 2 * vlen(tcontrol - tdest)       / tspeed;
+                       break;
+               case TSPEED_LINEAR:
+                       traveltime = vlen(tdest - self.origin)        / tspeed;
+                       break;
+               case TSPEED_TIME:
+                       traveltime = tspeed;
+                       break;
+       }
 
        if (traveltime < 0.1) // useless anim
        {
@@ -289,7 +335,7 @@ void SUB_CalcMove_Bezier (vector tcontrol, vector tdest, float tspeed, void() fu
        self = self.owner;
 }
 
-void SUB_CalcMove (vector tdest, float tspeed, void() func)
+void SUB_CalcMove (vector tdest, float tspeedtype, float tspeed, void() func)
 {
        vector  delta;
        float   traveltime;
@@ -309,13 +355,25 @@ void SUB_CalcMove (vector tdest, float tspeed, void() func)
        }
 
        delta = tdest - self.origin;
-       traveltime = vlen (delta) / tspeed;
+
+       switch(tspeedtype)
+       {
+               default:
+               case TSPEED_START:
+               case TSPEED_END:
+               case TSPEED_LINEAR:
+                       traveltime = vlen (delta) / tspeed;
+                       break;
+               case TSPEED_TIME:
+                       traveltime = tspeed;
+                       break;
+       }
 
        // Very short animations don't really show off the effect
        // of controlled animation, so let's just use linear movement.
        // Alternatively entities can choose to specify non-controlled movement.
         // The only currently implemented alternative movement is linear (value 1)
-       if (traveltime < 0.15 || self.platmovetype == 1)
+       if (traveltime < 0.15 || self.platmovetype < 2)
        {
                self.velocity = delta * (1/traveltime); // QuakeC doesn't allow vector/float division
                self.nextthink = self.ltime + traveltime;
@@ -323,17 +381,17 @@ void SUB_CalcMove (vector tdest, float tspeed, void() func)
        }
 
        // now just run like a bezier curve...
-       SUB_CalcMove_Bezier((self.origin + tdest) * 0.5, tdest, tspeed, func);
+       SUB_CalcMove_Bezier((self.origin + tdest) * 0.5, tdest, tspeedtype, tspeed, func);
 }
 
-void SUB_CalcMoveEnt (entity ent, vector tdest, float tspeed, void() func)
+void SUB_CalcMoveEnt (entity ent, vector tdest, float tspeedtype, float tspeed, void() func)
 {
        entity  oldself;
 
        oldself = self;
        self = ent;
 
-       SUB_CalcMove (tdest, tspeed, func);
+       SUB_CalcMove (tdest, tspeedtype, tspeed, func);
 
        self = oldself;
 }
@@ -359,7 +417,7 @@ void SUB_CalcAngleMoveDone (void)
 }
 
 // FIXME: I fixed this function only for rotation around the main axes
-void SUB_CalcAngleMove (vector destangle, float tspeed, void() func)
+void SUB_CalcAngleMove (vector destangle, float tspeedtype, float tspeed, void() func)
 {
        vector  delta;
        float   traveltime;
@@ -372,7 +430,19 @@ void SUB_CalcAngleMove (vector destangle, float tspeed, void() func)
        self.angles_y -= 360 * floor((self.angles_y - destangle_y) / 360 + 0.5);
        self.angles_z -= 360 * floor((self.angles_z - destangle_z) / 360 + 0.5);
        delta = destangle - self.angles;
-       traveltime = vlen (delta) / tspeed;
+
+       switch(tspeedtype)
+       {
+               default:
+               case TSPEED_START:
+               case TSPEED_END:
+               case TSPEED_LINEAR:
+                       traveltime = vlen (delta) / tspeed;
+                       break;
+               case TSPEED_TIME:
+                       traveltime = tspeed;
+                       break;
+       }
 
        self.think1 = func;
        self.finalangle = destangle;
@@ -389,14 +459,14 @@ void SUB_CalcAngleMove (vector destangle, float tspeed, void() func)
        self.nextthink = self.ltime + traveltime;
 }
 
-void SUB_CalcAngleMoveEnt (entity ent, vector destangle, float tspeed, void() func)
+void SUB_CalcAngleMoveEnt (entity ent, vector destangle, float tspeedtype, float tspeed, void() func)
 {
        entity  oldself;
 
        oldself = self;
        self = ent;
 
-       SUB_CalcAngleMove (destangle, tspeed, func);
+       SUB_CalcAngleMove (destangle, tspeedtype, tspeed, func);
 
        self = oldself;
 }