X-Git-Url: https://de.git.xonotic.org/?p=xonotic%2Fxonotic-data.pk3dir.git;a=blobdiff_plain;f=qcsrc%2Fserver%2Fg_subs.qc;h=e119e5aba40040a359eca73d26d6a909f6f5d128;hp=47f3a5a699b8daa78b7d9a896304a5ae681a6a0c;hb=e52c92b8ba22924be19d8458fb1dd0cb7cfe11c7;hpb=c4052acb21de917a6010586315bf102e262eb986 diff --git a/qcsrc/server/g_subs.qc b/qcsrc/server/g_subs.qc index 47f3a5a69..e119e5aba 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; } @@ -16,6 +16,9 @@ void spawnfunc_info_null (void) void setanim(entity e, vector anim, float looping, float override, float restart) { + if (!anim) + return; // no animation was given to us! We can't use this. + if (anim_x == e.animstate_startframe) if (anim_y == e.animstate_numframes) if (anim_z == e.animstate_framerate) @@ -38,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) { @@ -53,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; +} /* ================== @@ -118,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; @@ -132,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; } /* @@ -153,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; } @@ -177,10 +171,51 @@ void SUB_CalcMoveDone (void) self.think1 (); } +void SUB_CalcMove_controller_think (void) +{ + entity oldself; + float traveltime; + float phasepos; + float nexttick; + vector delta; + vector veloc; + vector nextpos; + 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); + + 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; + self.nextthink = nexttick; + } else { + oldself = self; + self.owner.think = self.think1; + self = self.owner; + remove(oldself); + self.think(); + } +} + void SUB_CalcMove (vector tdest, float tspeed, void() func) { vector delta; float traveltime; + entity controller; if (!tspeed) objerror ("No speed is defined!"); @@ -206,9 +241,36 @@ void SUB_CalcMove (vector tdest, float tspeed, void() func) return; } - self.velocity = delta * (1/traveltime); // QuakeC doesn't allow vector/float division + // 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.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; } void SUB_CalcMoveEnt (entity ent, vector tdest, float tspeed, void() func) @@ -310,8 +372,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) @@ -329,12 +391,9 @@ void tracebox_antilag_force_wz (entity source, vector v1, vector mi, vector ma, 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 @@ -346,12 +405,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 @@ -698,6 +754,33 @@ void LODmodel_attach() SetCustomizer(self, LOD_customize, LOD_uncustomize); } +void ApplyMinMaxScaleAngles(entity e) +{ + if(e.angles_x != 0 || e.angles_z != 0 || self.avelocity_x != 0 || self.avelocity_z != 0) // "weird" rotation + { + e.maxs = '1 1 1' * vlen( + '1 0 0' * max(-e.mins_x, e.maxs_x) + + '0 1 0' * max(-e.mins_y, e.maxs_y) + + '0 0 1' * max(-e.mins_z, e.maxs_z) + ); + e.mins = -e.maxs; + } + else if(e.angles_y != 0 || self.avelocity_y != 0) // yaw only is a bit better + { + e.maxs_x = vlen( + '1 0 0' * max(-e.mins_x, e.maxs_x) + + '0 1 0' * max(-e.mins_y, e.maxs_y) + ); + e.maxs_y = e.maxs_x; + e.mins_x = -e.maxs_x; + e.mins_y = -e.maxs_x; + } + if(e.scale) + setsize(e, e.mins * e.scale, e.maxs * e.scale); + else + setsize(e, e.mins, e.maxs); +} + void SetBrushEntityModel() { if(self.model != "") @@ -707,10 +790,7 @@ void SetBrushEntityModel() InitializeEntity(self, LODmodel_attach, INITPRIO_FINDTARGET); } setorigin(self, self.origin); - if(self.scale) - setsize(self, self.mins * self.scale, self.maxs * self.scale); - else - setsize(self, self.mins, self.maxs); + ApplyMinMaxScaleAngles(self); } void SetBrushEntityModelNoLOD() @@ -721,10 +801,7 @@ void SetBrushEntityModelNoLOD() setmodel(self, self.model); // no precision needed } setorigin(self, self.origin); - if(self.scale) - setsize(self, self.mins * self.scale, self.maxs * self.scale); - else - setsize(self, self.mins, self.maxs); + ApplyMinMaxScaleAngles(self); } /* @@ -744,7 +821,7 @@ void SetMovedir() } self.angles = '0 0 0'; -}; +} void InitTrigger() { @@ -756,7 +833,7 @@ void InitTrigger() self.movetype = MOVETYPE_NONE; self.modelindex = 0; self.model = ""; -}; +} void InitSolidBSPTrigger() { @@ -768,7 +845,7 @@ void InitSolidBSPTrigger() self.movetype = MOVETYPE_NONE; // why was this PUSH? -div0 // self.modelindex = 0; self.model = ""; -}; +} float InitMovingBrushTrigger() { @@ -783,4 +860,4 @@ float InitMovingBrushTrigger() return 0; } return 1; -}; +}