X-Git-Url: http://git.xonotic.org/?a=blobdiff_plain;ds=sidebyside;f=qcsrc%2Fserver%2Fg_subs.qc;h=049ba797ed24d450f2ec568ba78bcb410c30e3ce;hb=3b1499eee0331a2b357f46cc669f772559fabb3c;hp=e119e5aba40040a359eca73d26d6a909f6f5d128;hpb=2d2a167c9d4f4ffd8f4234309c936d99e842869b;p=xonotic%2Fxonotic-data.pk3dir.git diff --git a/qcsrc/server/g_subs.qc b/qcsrc/server/g_subs.qc index e119e5aba..049ba797e 100644 --- a/qcsrc/server/g_subs.qc +++ b/qcsrc/server/g_subs.qc @@ -171,6 +171,7 @@ void SUB_CalcMoveDone (void) self.think1 (); } +.float bezier_turn; void SUB_CalcMove_controller_think (void) { entity oldself; @@ -178,31 +179,45 @@ void SUB_CalcMove_controller_think (void) float phasepos; float nexttick; vector delta; + vector delta2; vector veloc; vector nextpos; + delta = self.destvec; + delta2 = self.destvec2; if(time < self.animstate_endtime) { - delta = self.destvec; nexttick = time + sys_frametime; - if(nexttick < self.animstate_endtime) { - traveltime = self.animstate_endtime - self.animstate_starttime; - phasepos = (nexttick - self.animstate_starttime) / traveltime; // range: [0, 1] + traveltime = self.animstate_endtime - self.animstate_starttime; + phasepos = (nexttick - self.animstate_starttime) / traveltime; // range: [0, 1] + if(self.platmovetype != 1) + { 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] - nextpos = self.origin + (delta * phasepos); + } + nextpos = self.origin + (delta * phasepos) + (delta2 * phasepos * phasepos); + // derivative: delta + 2 * delta2 * phasepos (e.g. for angle positioning) + if(nexttick < self.animstate_endtime) { veloc = nextpos - self.owner.origin; veloc = veloc * (1 / sys_frametime); // so it arrives for the next frame - } else { veloc = self.finaldest - self.owner.origin; 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) oldself = self; self.owner.think = self.think1; self = self.owner; @@ -211,9 +226,36 @@ void SUB_CalcMove_controller_think (void) } } -void SUB_CalcMove (vector tdest, float tspeed, void() func) +void SUB_CalcMove_controller_setbezier (entity controller, vector org, vector control, vector dest) +{ + // 0 * (1-t) * (1-t) + 2 * control * t * (1-t) + dest * t * t + // 2 * control * t - 2 * control * t * t + dest * t * t + // 2 * control * t + (dest - 2 * control) * t * t + + controller.origin = org; // starting point + control -= org; + dest -= org; + + 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) +{ + // 0 * (1-t) * (1-t) + 2 * control * t * (1-t) + dest * t * t + // 2 * control * t - 2 * control * t * t + dest * t * t + // 2 * control * t + (dest - 2 * control) * t * t + + controller.origin = org; // starting point + dest -= org; + + controller.destvec = dest; // end point + controller.destvec2 = '0 0 0'; +} + +void SUB_CalcMove_Bezier (vector tcontrol, vector tdest, float tspeed, void() func) { - vector delta; float traveltime; entity controller; @@ -224,40 +266,24 @@ void SUB_CalcMove (vector tdest, float tspeed, void() func) self.finaldest = tdest; self.think = SUB_CalcMoveDone; - if (tdest == self.origin) - { - self.velocity = '0 0 0'; - self.nextthink = self.ltime + 0.1; - return; - } + if(tspeed > 0) // positive: start speed + traveltime = 2 * vlen(tcontrol - self.origin) / tspeed; + else // negative: end speed + traveltime = 2 * vlen(tcontrol - tdest) / -tspeed; - delta = tdest - self.origin; - traveltime = vlen (delta) / tspeed; - - if (traveltime < 0.1) + if (traveltime < 0.1) // useless anim { self.velocity = '0 0 0'; self.nextthink = self.ltime + 0.1; return; } - // 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) - { - self.velocity = delta * (1/traveltime); // QuakeC doesn't allow vector/float division - self.nextthink = self.ltime + traveltime; - return; - } - controller = spawn(); controller.classname = "SUB_CalcMove_controller"; controller.owner = self; - controller.origin = self.origin; // starting point + controller.platmovetype = self.platmovetype; + SUB_CalcMove_controller_setbezier(controller, self.origin, tcontrol, tdest); controller.finaldest = (tdest + '0 0 0.125'); // where do we want to end? Offset to overshoot a bit. - controller.destvec = delta; controller.animstate_starttime = time; controller.animstate_endtime = time + traveltime; controller.think = SUB_CalcMove_controller_think; @@ -273,6 +299,43 @@ void SUB_CalcMove (vector tdest, float tspeed, void() func) self = self.owner; } +void SUB_CalcMove (vector tdest, float tspeed, void() func) +{ + vector delta; + float traveltime; + + if (!tspeed) + objerror ("No speed is defined!"); + + self.think1 = func; + self.finaldest = tdest; + self.think = SUB_CalcMoveDone; + + if (tdest == self.origin) + { + self.velocity = '0 0 0'; + self.nextthink = self.ltime + 0.1; + return; + } + + delta = tdest - self.origin; + traveltime = vlen (delta) / tspeed; + + // 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) + { + self.velocity = delta * (1/traveltime); // QuakeC doesn't allow vector/float division + self.nextthink = self.ltime + traveltime; + return; + } + + // now just run like a bezier curve... + SUB_CalcMove_Bezier((self.origin + tdest) * 0.5, tdest, tspeed, func); +} + void SUB_CalcMoveEnt (entity ent, vector tdest, float tspeed, void() func) { entity oldself; @@ -382,11 +445,9 @@ void tracebox_antilag_force_wz (entity source, vector v1, vector mi, vector ma, lag = 0; // only antilag for clients // change shooter to SOLID_BBOX so the shot can hit corpses + oldsolid = source.dphitcontentsmask; if(source) - { - oldsolid = source.dphitcontentsmask; source.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_CORPSE; - } if (lag) {