X-Git-Url: http://git.xonotic.org/?a=blobdiff_plain;f=qcsrc%2Fserver%2Fg_subs.qc;h=6a62d61b5d423e43debf69ab9461e031c427142c;hb=30cd3220d0370aa10dfb62eeb2ee3145d56b1c68;hp=47f3a5a699b8daa78b7d9a896304a5ae681a6a0c;hpb=57c5dfd12fc3f7ce7b2bc844325a2c85929f10de;p=xonotic%2Fxonotic-data.pk3dir.git diff --git a/qcsrc/server/g_subs.qc b/qcsrc/server/g_subs.qc index 47f3a5a69..6a62d61b5 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; +} /* ================== @@ -177,10 +169,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 +239,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 +370,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 +389,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 +403,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 +752,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 +788,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 +799,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 +819,7 @@ void SetMovedir() } self.angles = '0 0 0'; -}; +} void InitTrigger() { @@ -756,7 +831,7 @@ void InitTrigger() self.movetype = MOVETYPE_NONE; self.modelindex = 0; self.model = ""; -}; +} void InitSolidBSPTrigger() { @@ -768,7 +843,7 @@ void InitSolidBSPTrigger() self.movetype = MOVETYPE_NONE; // why was this PUSH? -div0 // self.modelindex = 0; self.model = ""; -}; +} float InitMovingBrushTrigger() { @@ -783,4 +858,4 @@ float InitMovingBrushTrigger() return 0; } return 1; -}; +}