3 void _Movetype_PushMove(entity this, float dt) // SV_PushMove
5 if(this.velocity == '0 0 0' && this.avelocity == '0 0 0')
13 // LadyHavoc: valid pusher types
17 case SOLID_CORPSE: // LadyHavoc: this would be weird...
19 // LadyHavoc: no collisions
23 this.origin = this.origin + dt * this.velocity;
24 this.angles = this.angles + dt * this.avelocity;
25 this.angles_x -= 360.0 * floor(this.angles_x * (1.0 / 360.0));
26 this.angles_y -= 360.0 * floor(this.angles_y * (1.0 / 360.0));
27 this.angles_z -= 360.0 * floor(this.angles_z * (1.0 / 360.0));
29 _Movetype_LinkEdict(this, false);
34 LOG_INFOF("_Movetype_Physics_Push: entity #%d, unrecognized solid type %d", etof(this), this.solid);
40 LOG_INFOF("_Movetype_Physics_Push: entity #%d has an invalid modelindex %d", etof(this), this.modelindex);
44 bool rotated = ((vlen2(this.angles) + vlen2(this.avelocity)) > 0);
46 vector move1 = this.velocity * dt;
47 vector moveangle = this.avelocity * dt;
49 vector a = -moveangle;
50 vector forward, left, up;
51 MAKE_VECTORS(a, forward, left, up);
52 left *= -1; // actually make it left!
54 vector pushorig = this.origin;
55 vector pushang = this.angles;
56 float pushltime = this.ltime;
58 // move the pusher to its final position
60 this.origin = this.origin + dt * this.velocity;
61 this.angles = this.angles + dt * this.avelocity;
63 _Movetype_LinkEdict(this, false); // pulls absmin/absmax from the engine
65 if(this.move_movetype == MOVETYPE_FAKEPUSH) // Tenebrae's MOVETYPE_PUSH variant that doesn't push...
67 this.angles_x -= 360.0 * floor(this.angles_x * (1.0 / 360.0));
68 this.angles_y -= 360.0 * floor(this.angles_y * (1.0 / 360.0));
69 this.angles_z -= 360.0 * floor(this.angles_z * (1.0 / 360.0));
73 IL_CLEAR(g_pushmove_moved); // make sure it's not somehow uncleared
75 for(entity check = findradius((this.absmin + this.absmax) * 0.5, vlen(this.absmax - this.absmin) * 0.5 + 1); check; check = check.chain)
77 switch(check.move_movetype)
83 case MOVETYPE_FLY_WORLDONLY:
89 if(check.owner == this || this.owner == check)
92 // if the entity is standing on the pusher, it will definitely be moved
93 // if the entity is not standing on the pusher, but is in the pusher's
94 // final position, move it
95 if (!IS_ONGROUND(check) || check.groundentity != this)
97 tracebox(check.origin, check.mins, check.maxs, check.origin, MOVE_NOMONSTERS, check);
101 vector pivot = check.mins + 0.5 * (check.maxs - check.mins);
106 vector org = check.origin - this.origin;
110 org2.x = (org * forward);
111 org2.y = (org * left);
119 check.moved_from = check.origin;
120 check.moved_fromangles = check.angles;
121 IL_PUSH(g_pushmove_moved, check);
123 // physics objects need better collisions than this code can do
124 if(check.move_movetype == MOVETYPE_PHYSICS)
126 check.origin = check.origin + move;
127 _Movetype_LinkEdict(check, true);
131 // try moving the contacted entity
132 int savesolid = this.solid;
133 this.solid = SOLID_NOT;
134 if(!_Movetype_PushEntity(check, move, true))
136 // entity "check" got teleported
137 check.angles_y += trace_fraction * moveangle.y;
138 this.solid = savesolid;
139 continue; // pushed enough
141 // FIXME: turn players specially
142 check.angles_y += trace_fraction * moveangle.y;
143 this.solid = savesolid;
145 // this trace.fraction < 1 check causes items to fall off of pushers
146 // if they pass under or through a wall
147 // the groundentity check causes items to fall off of ledges
148 if(check.move_movetype != MOVETYPE_WALK && (trace_fraction < 1 || check.groundentity != this))
149 UNSET_ONGROUND(check);
151 // if it is still inside the pusher, block
152 tracebox(check.origin, check.mins, check.maxs, check.origin, MOVE_NOMONSTERS, check);
155 if(_Movetype_NudgeOutOfSolid_PivotIsKnownGood(check, pivot))
157 // hack to invoke all necessary movement triggers
158 _Movetype_PushEntity(check, '0 0 0', true);
159 // we could fix it or entity "check" was telported
163 // still inside pusher, so it's really blocked
166 if(check.mins_x == check.maxs_x)
168 if(check.solid == SOLID_NOT || check.solid == SOLID_TRIGGER)
171 check.mins_x = check.mins_y = 0;
172 check.maxs = check.mins;
176 this.origin = pushorig;
177 this.angles = pushang;
178 this.ltime = pushltime;
179 _Movetype_LinkEdict(this, false);
181 // move back any entities we already moved
182 IL_EACH(g_pushmove_moved, true,
184 check.origin = check.moved_from;
185 check.angles = check.moved_fromangles;
186 _Movetype_LinkEdict(check, false);
189 // if the pusher has a "blocked" function, call it, otherwise just stay in place until the obstacle is gone
191 getblocked(this)(this, check);
195 this.angles_x -= 360.0 * floor(this.angles_x * (1.0 / 360.0));
196 this.angles_y -= 360.0 * floor(this.angles_y * (1.0 / 360.0));
197 this.angles_z -= 360.0 * floor(this.angles_z * (1.0 / 360.0));
198 IL_CLEAR(g_pushmove_moved); // clean up
201 void _Movetype_Physics_Push(entity this, float dt) // SV_Physics_Pusher
203 float oldltime = this.ltime;
205 if(this.nextthink < this.ltime + dt)
207 movetime = this.nextthink - this.ltime;
214 // advances this.ltime if not blocked
215 _Movetype_PushMove(this, movetime);
218 if(this.nextthink > oldltime && this.nextthink <= this.ltime)
221 getthink(this)(this);