-void SUB_NullThink() { }
+#include "subs.qh"
+void SUB_NullThink(entity this) { }
-void() SUB_CalcMoveDone;
-void() SUB_CalcAngleMoveDone;
-//void() SUB_UseTargets;
+void SUB_CalcMoveDone(entity this);
+void SUB_CalcAngleMoveDone(entity this);
/*
==================
SUB_Friction
-Applies some friction to self
+Applies some friction to this
==================
*/
.float friction;
-void SUB_Friction ()
-{SELFPARAM();
- self.SUB_NEXTTHINK = time;
- if(self.SUB_FLAGS & FL_ONGROUND)
- self.SUB_VELOCITY = self.SUB_VELOCITY * (1 - frametime * self.friction);
+void SUB_Friction (entity this)
+{
+ this.nextthink = time;
+ if(IS_ONGROUND(this))
+ this.velocity = this.velocity * (1 - frametime * this.friction);
}
/*
else
{
// remove
- remove (ent);
+ delete(ent);
}
}
-void SUB_SetFade_Think ()
-{SELFPARAM();
+void SUB_SetFade_Think (entity this)
+{
if(this.alpha == 0)
this.alpha = 1;
- this.SUB_THINK = SUB_SetFade_Think;
- this.SUB_NEXTTHINK = time;
+ setthink(this, SUB_SetFade_Think);
+ this.nextthink = time;
this.alpha -= frametime * this.fade_rate;
if (this.alpha < 0.01)
SUB_VanishOrRemove(this);
else
- this.SUB_NEXTTHINK = time;
+ this.nextthink = time;
}
/*
void SUB_SetFade (entity ent, float when, float fading_time)
{
ent.fade_rate = 1/fading_time;
- ent.SUB_THINK = SUB_SetFade_Think;
- ent.SUB_NEXTTHINK = when;
+ setthink(ent, SUB_SetFade_Think);
+ ent.nextthink = when;
}
/*
=============
SUB_CalcMove
-calculate self.SUB_VELOCITY and self.SUB_NEXTTHINK to reach dest from
-self.SUB_ORIGIN traveling at speed
+calculate this.velocity and this.nextthink to reach dest from
+this.origin traveling at speed
===============
*/
-void SUB_CalcMoveDone ()
-{SELFPARAM();
+void SUB_CalcMoveDone(entity this)
+{
// After moving, set origin to exact final destination
- SUB_SETORIGIN (self, self.finaldest);
- self.SUB_VELOCITY = '0 0 0';
- self.SUB_NEXTTHINK = -1;
- if (self.think1)
- self.think1 ();
+ setorigin (this, this.finaldest);
+ this.velocity = '0 0 0';
+ this.nextthink = -1;
+ if (this.think1 && this.think1 != SUB_CalcMoveDone)
+ this.think1 (this);
}
.float platmovetype_turn;
-void SUB_CalcMove_controller_think ()
-{SELFPARAM();
- entity oldself;
+void SUB_CalcMove_controller_think (entity this)
+{
float traveltime;
float phasepos;
float nexttick;
vector veloc;
vector angloc;
vector nextpos;
- delta = self.destvec;
- delta2 = self.destvec2;
- if(time < self.animstate_endtime)
+ delta = this.destvec;
+ delta2 = this.destvec2;
+ if(time < this.animstate_endtime)
{
nexttick = time + PHYS_INPUT_FRAMETIME;
- 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);
- nextpos = self.origin + (delta * phasepos) + (delta2 * phasepos * phasepos);
+ traveltime = this.animstate_endtime - this.animstate_starttime;
+ phasepos = (nexttick - this.animstate_starttime) / traveltime; // range: [0, 1]
+ phasepos = cubic_speedfunc(this.platmovetype_start, this.platmovetype_end, phasepos);
+ nextpos = this.origin + (delta * phasepos) + (delta2 * phasepos * phasepos);
// derivative: delta + 2 * delta2 * phasepos (e.g. for angle positioning)
- if(self.owner.platmovetype_turn)
+ if(this.owner.platmovetype_turn)
{
vector destangle;
destangle = delta + 2 * delta2 * phasepos;
destangle_x = -destangle_x; // flip up / down orientation
// take the shortest distance for the angles
- vector v = SUB_ANGLES(self.owner);
+ vector v = this.owner.angles;
v.x -= 360 * floor((v.x - destangle_x) / 360 + 0.5);
v.y -= 360 * floor((v.y - destangle_y) / 360 + 0.5);
v.z -= 360 * floor((v.z - destangle_z) / 360 + 0.5);
- SUB_ANGLES(self.owner) = v;
- angloc = destangle - SUB_ANGLES(self.owner);
+ this.owner.angles = v;
+ angloc = destangle - this.owner.angles;
angloc = angloc * (1 / PHYS_INPUT_FRAMETIME); // so it arrives for the next frame
- self.owner.SUB_AVELOCITY = angloc;
+ this.owner.avelocity = angloc;
}
- if(nexttick < self.animstate_endtime)
- veloc = nextpos - self.owner.SUB_ORIGIN;
+ if(nexttick < this.animstate_endtime)
+ veloc = nextpos - this.owner.origin;
else
- veloc = self.finaldest - self.owner.SUB_ORIGIN;
+ veloc = this.finaldest - this.owner.origin;
veloc = veloc * (1 / PHYS_INPUT_FRAMETIME); // so it arrives for the next frame
- self.owner.SUB_VELOCITY = veloc;
- self.nextthink = nexttick;
+ this.owner.velocity = veloc;
+ this.nextthink = nexttick;
}
else
{
// derivative: delta + 2 * delta2 (e.g. for angle positioning)
- oldself = self;
- self.owner.SUB_THINK = self.think1;
- setself(self.owner);
- remove(oldself);
- self.SUB_THINK();
+ entity own = this.owner;
+ setthink(own, this.think1);
+ // set the owner's reference to this entity to NULL
+ own.move_controller = NULL;
+ delete(this);
+ getthink(own)(own);
}
}
float TSPEED_END = 2;
// TODO average too?
-void SUB_CalcMove_Bezier (vector tcontrol, vector tdest, float tspeedtype, float tspeed, void() func)
-{SELFPARAM();
+void SUB_CalcMove_Bezier (entity this, vector tcontrol, vector tdest, float tspeedtype, float tspeed, void(entity this) func)
+{
float traveltime;
entity controller;
if (!tspeed)
- objerror ("No speed is defined!");
+ objerror (this, "No speed is defined!");
- self.think1 = func;
- self.finaldest = tdest;
- self.SUB_THINK = SUB_CalcMoveDone;
+ this.think1 = func;
+ this.finaldest = tdest;
+ setthink(this, SUB_CalcMoveDone);
switch(tspeedtype)
{
default:
case TSPEED_START:
- traveltime = 2 * vlen(tcontrol - self.SUB_ORIGIN) / tspeed;
+ traveltime = 2 * vlen(tcontrol - this.origin) / tspeed;
break;
case TSPEED_END:
traveltime = 2 * vlen(tcontrol - tdest) / tspeed;
break;
case TSPEED_LINEAR:
- traveltime = vlen(tdest - self.SUB_ORIGIN) / tspeed;
+ traveltime = vlen(tdest - this.origin) / tspeed;
break;
case TSPEED_TIME:
traveltime = tspeed;
if (traveltime < 0.1) // useless anim
{
- self.SUB_VELOCITY = '0 0 0';
- self.SUB_NEXTTHINK = self.SUB_LTIME + 0.1;
+ this.velocity = '0 0 0';
+ this.nextthink = this.ltime + 0.1;
return;
}
+ // delete the previous controller, otherwise changing movement midway is glitchy
+ if (this.move_controller != NULL)
+ {
+ delete(this.move_controller);
+ }
controller = new(SUB_CalcMove_controller);
- controller.owner = self;
- controller.platmovetype = self.platmovetype;
- controller.platmovetype_start = self.platmovetype_start;
- controller.platmovetype_end = self.platmovetype_end;
- SUB_CalcMove_controller_setbezier(controller, self.SUB_ORIGIN, tcontrol, tdest);
+ controller.owner = this;
+ this.move_controller = controller;
+ controller.platmovetype = this.platmovetype;
+ controller.platmovetype_start = this.platmovetype_start;
+ controller.platmovetype_end = this.platmovetype_end;
+ SUB_CalcMove_controller_setbezier(controller, this.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.SUB_THINK;
+ setthink(controller, SUB_CalcMove_controller_think);
+ controller.think1 = getthink(this);
// the thinking is now done by the controller
- self.SUB_THINK = SUB_NullThink; // for PushMove
- self.SUB_NEXTTHINK = self.SUB_LTIME + traveltime;
+ setthink(this, SUB_NullThink); // for PushMove
+ this.nextthink = this.ltime + traveltime;
// invoke controller
- setself(controller);
- self.think();
- setself(self.owner);
+ getthink(controller)(controller);
}
-void SUB_CalcMove (vector tdest, float tspeedtype, float tspeed, void() func)
-{SELFPARAM();
+void SUB_CalcMove (entity this, vector tdest, float tspeedtype, float tspeed, void(entity this) func)
+{
vector delta;
float traveltime;
if (!tspeed)
- objerror ("No speed is defined!");
+ objerror (this, "No speed is defined!");
- self.think1 = func;
- self.finaldest = tdest;
- self.SUB_THINK = SUB_CalcMoveDone;
+ this.think1 = func;
+ this.finaldest = tdest;
+ setthink(this, SUB_CalcMoveDone);
- if (tdest == self.SUB_ORIGIN)
+ if (tdest == this.origin)
{
- self.SUB_VELOCITY = '0 0 0';
- self.SUB_NEXTTHINK = self.SUB_LTIME + 0.1;
+ this.velocity = '0 0 0';
+ this.nextthink = this.ltime + 0.1;
return;
}
- delta = tdest - self.SUB_ORIGIN;
+ delta = tdest - this.origin;
switch(tspeedtype)
{
// 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?
+ if (traveltime < 0.15 || (this.platmovetype_start == 1 && this.platmovetype_end == 1)) // is this correct?
{
- self.SUB_VELOCITY = delta * (1/traveltime); // QuakeC doesn't allow vector/float division
- self.SUB_NEXTTHINK = self.SUB_LTIME + traveltime;
+ this.velocity = delta * (1/traveltime); // QuakeC doesn't allow vector/float division
+ this.nextthink = this.ltime + traveltime;
return;
}
// now just run like a bezier curve...
- SUB_CalcMove_Bezier((self.SUB_ORIGIN + tdest) * 0.5, tdest, tspeedtype, tspeed, func);
+ SUB_CalcMove_Bezier(this, (this.origin + tdest) * 0.5, tdest, tspeedtype, tspeed, func);
}
-void SUB_CalcMoveEnt (entity ent, vector tdest, float tspeedtype, float tspeed, void() func)
-{SELFPARAM();
- WITHSELF(ent, SUB_CalcMove(tdest, tspeedtype, tspeed, func));
+void SUB_CalcMoveEnt (entity ent, vector tdest, float tspeedtype, float tspeed, void(entity this) func)
+{
+ SUB_CalcMove(ent, tdest, tspeedtype, tspeed, func);
}
/*
=============
SUB_CalcAngleMove
-calculate self.SUB_AVELOCITY and self.SUB_NEXTTHINK to reach destangle from
-self.angles rotating
+calculate this.avelocity and this.nextthink to reach destangle from
+this.angles rotating
-The calling function should make sure self.SUB_THINK is valid
+The calling function should make sure this.setthink is valid
===============
*/
-void SUB_CalcAngleMoveDone ()
-{SELFPARAM();
+void SUB_CalcAngleMoveDone(entity this)
+{
// After rotating, set angle to exact final angle
- self.angles = self.finalangle;
- self.SUB_AVELOCITY = '0 0 0';
- self.SUB_NEXTTHINK = -1;
- if (self.think1)
- self.think1 ();
+ this.angles = this.finalangle;
+ this.avelocity = '0 0 0';
+ this.nextthink = -1;
+ if (this.think1 && this.think1 != SUB_CalcAngleMoveDone) // avoid endless loops
+ this.think1 (this);
}
// FIXME: I fixed this function only for rotation around the main axes
-void SUB_CalcAngleMove (vector destangle, float tspeedtype, float tspeed, void() func)
-{SELFPARAM();
- vector delta;
- float traveltime;
-
+void SUB_CalcAngleMove (entity this, vector destangle, float tspeedtype, float tspeed, void(entity this) func)
+{
if (!tspeed)
- objerror ("No speed is defined!");
+ objerror (this, "No speed is defined!");
// take the shortest distance for the angles
- self.angles_x -= 360 * floor((self.angles_x - destangle_x) / 360 + 0.5);
- 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;
+ this.angles_x -= 360 * floor((this.angles_x - destangle_x) / 360 + 0.5);
+ this.angles_y -= 360 * floor((this.angles_y - destangle_y) / 360 + 0.5);
+ this.angles_z -= 360 * floor((this.angles_z - destangle_z) / 360 + 0.5);
+ vector delta = destangle - this.angles;
+ float traveltime;
switch(tspeedtype)
{
break;
}
- self.think1 = func;
- self.finalangle = destangle;
- self.SUB_THINK = SUB_CalcAngleMoveDone;
+ this.think1 = func;
+ this.finalangle = destangle;
+ setthink(this, SUB_CalcAngleMoveDone);
if (traveltime < 0.1)
{
- self.SUB_AVELOCITY = '0 0 0';
- self.SUB_NEXTTHINK = self.SUB_LTIME + 0.1;
+ this.avelocity = '0 0 0';
+ this.nextthink = this.ltime + 0.1;
return;
}
- self.SUB_AVELOCITY = delta * (1 / traveltime);
- self.SUB_NEXTTHINK = self.SUB_LTIME + traveltime;
+ this.avelocity = delta * (1 / traveltime);
+ this.nextthink = this.ltime + traveltime;
}
-void SUB_CalcAngleMoveEnt (entity ent, vector destangle, float tspeedtype, float tspeed, void() func)
-{SELFPARAM();
- WITHSELF(ent, SUB_CalcAngleMove (destangle, tspeedtype, tspeed, func));
+void SUB_CalcAngleMoveEnt (entity ent, vector destangle, float tspeedtype, float tspeed, void(entity this) func)
+{
+ SUB_CalcAngleMove (ent, destangle, tspeedtype, tspeed, func);
}