2 void _Movetype_PushMove(entity this, float dt) // SV_PushMove
4 if(this.velocity == '0 0 0' && this.avelocity == '0 0 0')
12 // LadyHavoc: valid pusher types
16 case SOLID_CORPSE: // LadyHavoc: this would be weird...
18 // LadyHavoc: no collisions
22 this.origin = this.origin + dt * this.velocity;
23 this.angles = this.angles + dt * this.avelocity;
24 this.angles_x -= 360.0 * floor(this.angles_x * (1.0 / 360.0));
25 this.angles_y -= 360.0 * floor(this.angles_y * (1.0 / 360.0));
26 this.angles_z -= 360.0 * floor(this.angles_z * (1.0 / 360.0));
28 _Movetype_LinkEdict(this, false);
33 LOG_INFOF("_Movetype_Physics_Push: entity #%d, unrecognized solid type %d", etof(this), this.solid);
39 LOG_INFOF("_Movetype_Physics_Push: entity #%d has an invalid modelindex %d", etof(this), this.modelindex);
43 bool rotated = ((vlen2(this.angles) + vlen2(this.avelocity)) > 0);
45 vector move1 = this.velocity * dt;
46 vector moveangle = this.avelocity * dt;
48 vector a = -moveangle;
49 vector forward, left, up;
50 MAKE_VECTORS(a, forward, left, up);
51 left *= -1; // actually make it left!
53 vector pushorig = this.origin;
54 vector pushang = this.angles;
55 float pushltime = this.ltime;
57 // move the pusher to its final position
59 this.origin = this.origin + dt * this.velocity;
60 this.angles = this.angles + dt * this.avelocity;
62 _Movetype_LinkEdict(this, false); // pulls absmin/absmax from the engine
64 if(this.move_movetype == MOVETYPE_FAKEPUSH) // Tenebrae's MOVETYPE_PUSH variant that doesn't push...
66 this.angles_x -= 360.0 * floor(this.angles_x * (1.0 / 360.0));
67 this.angles_y -= 360.0 * floor(this.angles_y * (1.0 / 360.0));
68 this.angles_z -= 360.0 * floor(this.angles_z * (1.0 / 360.0));
72 IL_CLEAR(g_pushmove_moved); // make sure it's not somehow uncleared
74 FOREACH_ENTITY_RADIUS(0.5 * (this.absmin + this.absmax), 0.5 * vlen(this.absmax - this.absmin), true,
76 switch(it.move_movetype)
82 case MOVETYPE_FLY_WORLDONLY:
88 if(it.owner == this || this.owner == it)
91 // if the entity is standing on the pusher, it will definitely be moved
92 // if the entity is not standing on the pusher, but is in the pusher's
93 // final position, move it
94 if (!IS_ONGROUND(it) || it.groundentity != this)
96 tracebox(it.origin, it.mins, it.maxs, it.origin, MOVE_NORMAL, it);
100 vector pivot = it.mins + 0.5 * it.maxs;
105 vector org = it.origin - this.origin;
109 org2.x = (org * forward);
110 org2.y = (org * left);
118 it.moved_from = it.origin;
119 it.moved_fromangles = it.angles;
120 IL_PUSH(g_pushmove_moved, it);
122 // physics objects need better collisions than this code can do
123 if(it.move_movetype == MOVETYPE_PHYSICS)
125 it.origin = it.origin + move;
126 _Movetype_LinkEdict(it, true);
130 // try moving the contacted entity
131 int savesolid = this.solid;
132 this.solid = SOLID_NOT;
133 if(!_Movetype_PushEntity(it, move, true, false))
135 // entity "check" got teleported
136 it.angles_y += trace_fraction * moveangle.y;
137 this.solid = savesolid;
138 continue; // pushed enough
140 // FIXME: turn players specially
141 it.angles_y += trace_fraction * moveangle.y;
142 this.solid = savesolid;
144 // this trace.fraction < 1 check causes items to fall off of pushers
145 // if they pass under or through a wall
146 // the groundentity check causes items to fall off of ledges
147 if(it.move_movetype != MOVETYPE_WALK && (trace_fraction < 1 || it.groundentity != this))
150 // if it is still inside the pusher, block
151 tracebox(it.origin, it.mins, it.maxs, it.origin, MOVE_NORMAL, it);
154 if(_Movetype_NudgeOutOfSolid_PivotIsKnownGood(it, pivot))
156 // hack to invoke all necessary movement triggers
157 vector move2 = '0 0 0';
158 if(!_Movetype_PushEntity(it, move2, true, false))
160 // entity "check" got teleported
167 // still inside pusher, so it's really blocked
170 if(it.mins_x == it.maxs_x)
172 if(it.solid == SOLID_NOT || it.solid == SOLID_TRIGGER)
175 it.mins_x = it.mins_y = 0;
180 this.origin = pushorig;
181 this.angles = pushang;
182 this.ltime = pushltime;
183 _Movetype_LinkEdict(this, false);
185 // move back any entities we already moved
186 IL_EACH(g_pushmove_moved, true,
188 it.origin = it.moved_from;
189 it.angles = it.moved_fromangles;
190 _Movetype_LinkEdict(it, false);
193 // if the pusher has a "blocked" function, call it, otherwise just stay in place until the obstacle is gone
195 getblocked(this)(this, it);
199 this.angles_x -= 360.0 * floor(this.angles_x * (1.0 / 360.0));
200 this.angles_y -= 360.0 * floor(this.angles_y * (1.0 / 360.0));
201 this.angles_z -= 360.0 * floor(this.angles_z * (1.0 / 360.0));
202 IL_CLEAR(g_pushmove_moved); // clean up
205 void _Movetype_Physics_Push(entity this, float dt) // SV_Physics_Pusher
207 float oldltime = this.ltime;
209 if(this.nextthink < this.ltime + dt)
211 movetime = this.nextthink - this.ltime;
218 // advances this.ltime if not blocked
219 _Movetype_PushMove(this, movetime);
222 if(this.nextthink > oldltime && this.nextthink <= this.ltime)
225 getthink(this)(this);