X-Git-Url: https://de.git.xonotic.org/?a=blobdiff_plain;f=qcsrc%2Fserver%2Fg_subs.qc;h=6444ffdb3cec98fcf7f97114736f340c493964ef;hb=2c20e3699828b698074c825401dfe21ee0d9fe27;hp=e119e5aba40040a359eca73d26d6a909f6f5d128;hpb=d9708336de4c01e81ea08bb205093b676b7cb882;p=xonotic%2Fxonotic-data.pk3dir.git diff --git a/qcsrc/server/g_subs.qc b/qcsrc/server/g_subs.qc index e119e5aba..6444ffdb3 100644 --- a/qcsrc/server/g_subs.qc +++ b/qcsrc/server/g_subs.qc @@ -1,6 +1,4 @@ -void SUB_Null() {} -float SUB_True() { return 1; } -float SUB_False() { return 0; } +void SUB_NullThink(void) { } void(vector destangle, float tspeed, void() func) SUB_CalcAngleMove; void() SUB_CalcMoveDone; @@ -58,19 +56,6 @@ void updateanim(entity e) //print(ftos(time), " -> ", ftos(e.frame), "\n"); } -vector animfixfps(entity e, vector a) -{ - // multi-frame anim: keep as-is - if(a_y == 1) - { - float dur; - dur = frameduration(e.modelindex, a_x); - if(dur > 0) - a_z = 1.0 / dur; - } - return a; -} - /* ================== SUB_Remove @@ -107,7 +92,7 @@ Makes client invisible or removes non-client */ void SUB_VanishOrRemove (entity ent) { - if (ent.flags & FL_CLIENT) + if (IS_CLIENT(ent)) { // vanish ent.alpha = -1; @@ -144,9 +129,6 @@ Fade 'ent' out when time >= 'when' */ void SUB_SetFade (entity ent, float when, float fadetime) { - //if (ent.flags & FL_CLIENT) // && ent.deadflag != DEAD_NO) - // return; - //ent.alpha = 1; ent.fade_rate = 1/fadetime; ent.think = SUB_SetFade_Think; ent.nextthink = when; @@ -178,24 +160,29 @@ 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 @@ -203,6 +190,7 @@ void SUB_CalcMove_controller_think (void) self.owner.velocity = veloc; 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 +199,35 @@ 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 +} + +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,23 +238,61 @@ void SUB_CalcMove (vector tdest, float tspeed, void() func) self.finaldest = tdest; self.think = SUB_CalcMoveDone; - if (tdest == self.origin) + if(tspeed > 0) // positive: start speed + traveltime = 2 * vlen(tcontrol - self.origin) / tspeed; + else // negative: end speed + traveltime = 2 * vlen(tcontrol - tdest) / -tspeed; + + if (traveltime < 0.1) // useless anim { self.velocity = '0 0 0'; self.nextthink = self.ltime + 0.1; return; } - delta = tdest - self.origin; - traveltime = vlen (delta) / tspeed; + controller = spawn(); + controller.classname = "SUB_CalcMove_controller"; + controller.owner = self; + 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.animstate_starttime = time; + controller.animstate_endtime = time + traveltime; + controller.think = SUB_CalcMove_controller_think; + controller.think1 = self.think; - if (traveltime < 0.1) + // the thinking is now done by the controller + self.think = SUB_NullThink; // for PushMove + self.nextthink = self.ltime + traveltime; + + // invoke controller + self = controller; + self.think(); + 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. @@ -252,25 +304,8 @@ void SUB_CalcMove (vector tdest, float tspeed, void() func) return; } - controller = spawn(); - controller.classname = "SUB_CalcMove_controller"; - controller.owner = self; - controller.origin = self.origin; // starting point - 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; - controller.think1 = self.think; - - // the thinking is now done by the controller - self.think = SUB_Null; - self.nextthink = self.ltime + traveltime; - - // invoke controller - self = controller; - self.think(); - self = self.owner; + // 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) @@ -378,15 +413,13 @@ void tracebox_antilag_force_wz (entity source, vector v1, vector mi, vector ma, // check whether antilagged traces are enabled if (lag < 0.001) lag = 0; - if (clienttype(forent) != CLIENTTYPE_REAL) + if not(IS_REAL_CLIENT(forent)) 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 +480,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 +517,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 +531,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 +558,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); } /* @@ -786,7 +781,15 @@ void SetBrushEntityModel() if(self.model != "") { precache_model(self.model); - setmodel(self, self.model); // no precision needed + if(self.mins != '0 0 0' || self.maxs != '0 0 0') + { + vector mi = self.mins; + vector ma = self.maxs; + setmodel(self, self.model); // no precision needed + setsize(self, mi, ma); + } + else + setmodel(self, self.model); // no precision needed InitializeEntity(self, LODmodel_attach, INITPRIO_FINDTARGET); } setorigin(self, self.origin); @@ -798,7 +801,15 @@ void SetBrushEntityModelNoLOD() if(self.model != "") { precache_model(self.model); - setmodel(self, self.model); // no precision needed + if(self.mins != '0 0 0' || self.maxs != '0 0 0') + { + vector mi = self.mins; + vector ma = self.maxs; + setmodel(self, self.model); // no precision needed + setsize(self, mi, ma); + } + else + setmodel(self, self.model); // no precision needed } setorigin(self, self.origin); ApplyMinMaxScaleAngles(self);