X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=qcsrc%2Fserver%2Fg_subs.qc;h=9454f14f49263ab45cd10acabb49a41e3103ba1c;hb=a83efc591039d68bc106b09001c3f46a14eb52a4;hp=e119e5aba40040a359eca73d26d6a909f6f5d128;hpb=9f31b2438f27e46e900e4a9afe47fec5fcace088;p=xonotic%2Fxonotic-data.pk3dir.git diff --git a/qcsrc/server/g_subs.qc b/qcsrc/server/g_subs.qc index e119e5aba..9454f14f4 100644 --- a/qcsrc/server/g_subs.qc +++ b/qcsrc/server/g_subs.qc @@ -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; @@ -178,31 +178,62 @@ 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] - 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); + traveltime = self.animstate_endtime - self.animstate_starttime; + phasepos = (nexttick - self.animstate_starttime) / traveltime; // range: [0, 1] + phasepos = cubic_speedfunc(self.platmovetype_start, self.platmovetype_end, phasepos); + + /* switch(self.platmovetype) + { + case 1: // linear + break; + // phasepos = cubic_speedfunc(1, 1, phasepos); // identity + case 2: // cosine + // phasepos = (1 - cos(phasepos * 3.14159265)) / 2; + phasepos = cubic_speedfunc(0, 0, phasepos); + break; + case 3: // inverted cosine + // phasepos = acos(1 - phasepos * 2) / 3.14159265; + phasepos = cubic_speedfunc(2, 2, phasepos); + break; + case 4: // half cosine + // phasepos = (1 - cos(phasepos * (3.14159265 / 2))); + phasepos = cubic_speedfunc(0, 1.5, phasepos); + break; + case 5: // inverted half cosine + // phasepos = sin(phasepos * (3.14159265 / 2)); + phasepos = cubic_speedfunc(1.5, 0, phasepos); + break; + } */ + 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 +242,42 @@ 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'; +} + +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) { - vector delta; float traveltime; entity controller; @@ -224,40 +288,38 @@ void SUB_CalcMove (vector tdest, float tspeed, void() func) self.finaldest = tdest; self.think = SUB_CalcMoveDone; - if (tdest == self.origin) + switch(tspeedtype) { - self.velocity = '0 0 0'; - self.nextthink = self.ltime + 0.1; - return; + 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; } - 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; + controller.platmovetype_start = self.platmovetype_start; + controller.platmovetype_end = self.platmovetype_end; + 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,14 +335,63 @@ void SUB_CalcMove (vector tdest, float tspeed, void() func) self = self.owner; } -void SUB_CalcMoveEnt (entity ent, vector tdest, float tspeed, void() func) +void SUB_CalcMove (vector tdest, float tspeedtype, 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; + + 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_start == 1 && self.platmovetype_end == 1)) // is this correct? + { + 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, tspeedtype, tspeed, 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; } @@ -306,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; @@ -319,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; @@ -336,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; } @@ -382,11 +505,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) { @@ -447,10 +568,11 @@ void WarpZone_tracebox_antilag (entity source, vector v1, vector mi, vector ma, tracebox_antilag_force_wz(source, v1, mi, ma, v2, nomonst, forent, lag, TRUE); } -float tracebox_inverted (vector v1, vector mi, vector ma, vector v2, float nomonsters, entity forent) // returns the number of traces done, for benchmarking +float tracebox_inverted (vector v1, vector mi, vector ma, vector v2, float nomonsters, entity forent, float stopatentity) // returns the number of traces done, for benchmarking { vector pos, dir, t; float nudge; + entity stopentity; //nudge = 2 * cvar("collision_impactnudge"); // why not? nudge = 0.5; @@ -483,6 +605,8 @@ float tracebox_inverted (vector v1, vector mi, vector ma, vector v2, float nomon dprint(" trace distance is ", ftos(vlen(pos - trace_endpos)), "\n"); } + stopentity = trace_ent; + if(trace_startsolid) { // we started inside solid. @@ -495,6 +619,15 @@ float tracebox_inverted (vector v1, vector mi, vector ma, vector v2, float nomon // t is still inside solid? bad // force advance, then, and retry pos = t + dir * nudge; + + // but if we hit an entity, stop RIGHT before it + if(stopatentity && stopentity) + { + trace_ent = stopentity; + trace_endpos = t; + trace_fraction = ((trace_endpos - v1) * dir) / ((v2 - v1) * dir); + return c; + } } else { @@ -513,59 +646,9 @@ float tracebox_inverted (vector v1, vector mi, vector ma, vector v2, float nomon } } -void traceline_inverted (vector v1, vector v2, float nomonsters, entity forent) +void traceline_inverted (vector v1, vector v2, float nomonsters, entity forent, float stopatentity) { -#if 0 - vector pos, dir, t; - float nudge; - - //nudge = 2 * cvar("collision_impactnudge"); // why not? - nudge = 0.5; - - dir = normalize(v2 - v1); - - pos = v1 + dir * nudge; - - for(;;) - { - if((pos - v1) * dir >= (v2 - v1) * dir) - { - // went too far - trace_fraction = 1; - return; - } - - traceline(pos, v2, nomonsters, forent); - - if(trace_startsolid) - { - // we started inside solid. - // then trace from endpos to pos - t = trace_endpos; - traceline(t, pos, nomonsters, forent); - if(trace_startsolid) - { - // t is inside solid? bad - // force advance, then - pos = pos + dir * nudge; - } - else - { - // we actually LEFT solid! - trace_fraction = ((trace_endpos - v1) * dir) / ((v2 - v1) * dir); - return; - } - } - else - { - // pos is outside solid?!? but why?!? never mind, just return it. - trace_endpos = pos; - trace_fraction = ((trace_endpos - v1) * dir) / ((v2 - v1) * dir); - return; - } - } -#else - tracebox_inverted(v1, '0 0 0', '0 0 0', v2, nomonsters, forent); + tracebox_inverted(v1, '0 0 0', '0 0 0', v2, nomonsters, forent, stopatentity); } /*