X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=qcsrc%2Fserver%2Fg_subs.qc;h=b07cae2714e19770ca08d721d26fd0cec4885575;hb=64b6c7420b3e1c307f408a9f17d9c765a268621a;hp=c311f3774f45f59c7ad934e6b5992e673c1b4f54;hpb=5b902bfabe6575373dac2ffe636074c0308c6abf;p=xonotic%2Fxonotic-data.pk3dir.git diff --git a/qcsrc/server/g_subs.qc b/qcsrc/server/g_subs.qc index c311f3774..b07cae271 100644 --- a/qcsrc/server/g_subs.qc +++ b/qcsrc/server/g_subs.qc @@ -1,4 +1,4 @@ -void SUB_Null() {}; +void SUB_Null() {} float SUB_True() { return 1; } float SUB_False() { return 0; } @@ -41,7 +41,7 @@ void setanim(entity e, vector anim, float looping, float override, float restart e.animstate_override = override; e.frame = e.animstate_startframe; e.frame1time = servertime; -}; +} void updateanim(entity e) { @@ -56,31 +56,20 @@ void updateanim(entity e) } e.frame = e.animstate_startframe + bound(0, (time - e.animstate_starttime) * e.animstate_framerate, e.animstate_numframes - 1); //print(ftos(time), " -> ", ftos(e.frame), "\n"); -}; - -float animparseerror; -vector animparseline(float animfile) -{ - local string line; - local float c; - local vector anim; - if (animfile < 0) - return '0 1 2'; - line = fgets(animfile); - c = tokenize_console(line); - if (c < 3) +} + +vector animfixfps(entity e, vector a) +{ + // multi-frame anim: keep as-is + if(a_y == 1) { - animparseerror = TRUE; - return '0 1 2'; + float dur; + dur = frameduration(e.modelindex, a_x); + if(dur > 0) + a_z = 1.0 / dur; } - anim_x = stof(argv(0)); - anim_y = stof(argv(1)); - anim_z = stof(argv(2)); - // don't allow completely bogus values - if (anim_x < 0 || anim_y < 1 || anim_z < 0.001) - anim = '0 1 2'; - return anim; -}; + return a; +} /* ================== @@ -121,7 +110,7 @@ void SUB_VanishOrRemove (entity ent) if (ent.flags & FL_CLIENT) { // vanish - ent.model = ""; + ent.alpha = -1; ent.effects = 0; ent.glow_size = 0; ent.pflags = 0; @@ -135,12 +124,15 @@ void SUB_VanishOrRemove (entity ent) void SUB_SetFade_Think (void) { + if(self.alpha == 0) + self.alpha = 1; self.think = SUB_SetFade_Think; - self.nextthink = self.fade_time; - self.alpha = 1 - (time - self.fade_time) * self.fade_rate; + self.nextthink = time; + self.alpha -= frametime * self.fade_rate; if (self.alpha < 0.01) SUB_VanishOrRemove(self); - self.alpha = bound(0.01, self.alpha, 1); + else + self.nextthink = time; } /* @@ -156,7 +148,6 @@ void SUB_SetFade (entity ent, float when, float fadetime) // return; //ent.alpha = 1; ent.fade_rate = 1/fadetime; - ent.fade_time = when; ent.think = SUB_SetFade_Think; ent.nextthink = when; } @@ -187,24 +178,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 @@ -212,6 +208,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; @@ -220,9 +217,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; @@ -233,40 +256,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; - } - - delta = tdest - self.origin; - traveltime = vlen (delta) / tspeed; + 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) + 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; @@ -282,6 +289,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; @@ -381,8 +425,8 @@ Additionally it moves players back into the past before the trace and restores t */ void tracebox_antilag_force_wz (entity source, vector v1, vector mi, vector ma, vector v2, float nomonst, entity forent, float lag, float wz) { - local entity player; - local float oldsolid; + entity player; + float oldsolid; // check whether antilagged traces are enabled if (lag < 0.001) @@ -391,21 +435,16 @@ 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) { // take players back into the past - player = player_list; - while (player) - { - antilag_takeback(player, time - lag); - player = player.nextplayer; - } + FOR_EACH_PLAYER(player) + if(player != forent) + antilag_takeback(player, time - lag); } // do the trace @@ -417,12 +456,9 @@ void tracebox_antilag_force_wz (entity source, vector v1, vector mi, vector ma, // restore players to current positions if (lag) { - player = player_list; - while (player) - { - antilag_restore(player); - player = player.nextplayer; - } + FOR_EACH_PLAYER(player) + if(player != forent) + antilag_restore(player); } // restore shooter solid type @@ -462,10 +498,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; @@ -498,6 +535,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. @@ -510,6 +549,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 { @@ -528,59 +576,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); } /* @@ -801,7 +799,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); @@ -813,7 +819,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); @@ -836,7 +850,7 @@ void SetMovedir() } self.angles = '0 0 0'; -}; +} void InitTrigger() { @@ -848,7 +862,7 @@ void InitTrigger() self.movetype = MOVETYPE_NONE; self.modelindex = 0; self.model = ""; -}; +} void InitSolidBSPTrigger() { @@ -860,7 +874,7 @@ void InitSolidBSPTrigger() self.movetype = MOVETYPE_NONE; // why was this PUSH? -div0 // self.modelindex = 0; self.model = ""; -}; +} float InitMovingBrushTrigger() { @@ -875,4 +889,4 @@ float InitMovingBrushTrigger() return 0; } return 1; -}; +}