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 for(entity check = findradius((this.absmin + this.absmax) * 0.5, vlen(this.absmax - this.absmin) * 0.5 + 1); check; check = check.chain)
76 switch(check.move_movetype)
82 case MOVETYPE_FLY_WORLDONLY:
88 if(check.owner == this || this.owner == check)
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(check) || check.groundentity != this)
96 tracebox(check.origin, check.mins, check.maxs, check.origin, MOVE_NOMONSTERS, check);
100 vector pivot = check.mins + 0.5 * (check.maxs - check.mins);
105 vector org = check.origin - this.origin;
109 org2.x = (org * forward);
110 org2.y = (org * left);
118 check.moved_from = check.origin;
119 check.moved_fromangles = check.angles;
120 IL_PUSH(g_pushmove_moved, check);
122 // physics objects need better collisions than this code can do
123 if(check.move_movetype == MOVETYPE_PHYSICS)
125 check.origin = check.origin + move;
126 _Movetype_LinkEdict(check, true);
130 // try moving the contacted entity
131 int savesolid = this.solid;
132 this.solid = SOLID_NOT;
133 if(!_Movetype_PushEntity(check, move, true, true))
135 // entity "check" got teleported
136 check.angles_y += trace_fraction * moveangle.y;
137 this.solid = savesolid;
138 continue; // pushed enough
140 // FIXME: turn players specially
141 check.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(check.move_movetype != MOVETYPE_WALK && (trace_fraction < 1 || check.groundentity != this))
148 UNSET_ONGROUND(check);
150 // if it is still inside the pusher, block
151 tracebox(check.origin, check.mins, check.maxs, check.origin, MOVE_NOMONSTERS, check);
154 if(_Movetype_NudgeOutOfSolid_PivotIsKnownGood(check, pivot))
156 // hack to invoke all necessary movement triggers
157 _Movetype_PushEntity(check, '0 0 0', true, true);
158 // we could fix it or entity "check" was telported
162 // still inside pusher, so it's really blocked
165 if(check.mins_x == check.maxs_x)
167 if(check.solid == SOLID_NOT || check.solid == SOLID_TRIGGER)
170 check.mins_x = check.mins_y = 0;
171 check.maxs = check.mins;
175 this.origin = pushorig;
176 this.angles = pushang;
177 this.ltime = pushltime;
178 _Movetype_LinkEdict(this, false);
180 // move back any entities we already moved
181 IL_EACH(g_pushmove_moved, true,
183 check.origin = check.moved_from;
184 check.angles = check.moved_fromangles;
185 _Movetype_LinkEdict(check, false);
188 // if the pusher has a "blocked" function, call it, otherwise just stay in place until the obstacle is gone
190 getblocked(this)(this, check);
194 this.angles_x -= 360.0 * floor(this.angles_x * (1.0 / 360.0));
195 this.angles_y -= 360.0 * floor(this.angles_y * (1.0 / 360.0));
196 this.angles_z -= 360.0 * floor(this.angles_z * (1.0 / 360.0));
197 IL_CLEAR(g_pushmove_moved); // clean up
200 void _Movetype_Physics_Push(entity this, float dt) // SV_Physics_Pusher
202 float oldltime = this.ltime;
204 if(this.nextthink < this.ltime + dt)
206 movetime = this.nextthink - this.ltime;
213 // advances this.ltime if not blocked
214 _Movetype_PushMove(this, movetime);
217 if(this.nextthink > oldltime && this.nextthink <= this.ltime)
220 getthink(this)(this);