5a0426edce7ffba41c69eb48b8c293a1b5c07b46
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / physics / movetypes / push.qc
1 void _Movetype_PushMove(entity this, float dt)  // SV_PushMove
2 {
3         if (this.move_velocity == '0 0 0' && this.move_avelocity == '0 0 0')
4         {
5                 this.move_ltime += dt;
6                 return;
7         }
8
9         switch (this.solid)
10         {
11                 // LordHavoc: valid pusher types
12                 case SOLID_BSP:
13                 case SOLID_BBOX:
14                 case SOLID_SLIDEBOX:
15                 case SOLID_CORPSE:  // LordHavoc: this would be weird...
16                         break;
17                 // LordHavoc: no collisions
18                 case SOLID_NOT:
19                 case SOLID_TRIGGER:
20                         this.move_origin = this.move_origin + dt * this.move_velocity;
21                         this.move_angles = this.move_angles + dt * this.move_avelocity;
22                         this.move_angles_x -= 360.0 * floor(this.move_angles.x * (1.0 / 360.0));
23                         this.move_angles_y -= 360.0 * floor(this.move_angles.y * (1.0 / 360.0));
24                         this.move_angles_z -= 360.0 * floor(this.move_angles.z * (1.0 / 360.0));
25                         this.move_ltime += dt;
26                         _Movetype_LinkEdict(this, true);
27                         return;
28                 default:
29                         LOG_TRACEF("_Movetype_PushMove: entity %e, unrecognized solid type %d\n", this, this.solid);
30                         return;
31         }
32
33         bool rotated = (this.move_angles * this.move_angles) + (this.move_avelocity * this.move_avelocity) > 0;
34
35         vector move1 = this.move_velocity * dt;
36         vector moveangle = this.move_avelocity * dt;
37
38         makevectors_matrix(-moveangle);
39
40 //      vector pushorig = this.move_origin;
41 //      vector pushang = this.move_angles;
42 //      float pushltime = this.move_ltime;
43
44 // move the pusher to its final position
45
46         this.move_origin = this.move_origin + dt * this.move_velocity;
47         this.move_angles = this.move_angles + dt * this.move_avelocity;
48
49         this.move_ltime += dt;
50         _Movetype_LinkEdict(this, true);
51
52         int savesolid = this.solid;
53
54         if (this.move_movetype != MOVETYPE_FAKEPUSH)
55         {
56             FOREACH_ENTITY_RADIUS(0.5 * (this.absmin + this.absmax), 0.5 * vlen(this.absmax - this.absmin), true, {
57                         switch (it.move_movetype)
58                         {
59                                 case MOVETYPE_NONE:
60                                 case MOVETYPE_PUSH:
61                                 case MOVETYPE_FOLLOW:
62                                 case MOVETYPE_NOCLIP:
63                                 case MOVETYPE_FLY_WORLDONLY:
64                                         continue;
65                                 default:
66                                         break;
67                         }
68
69                         if (it.owner == this)
70                                 continue;
71
72                         if (this.owner == it)
73                                 continue;
74
75                         vector pivot = it.mins + 0.5 * (it.maxs - it.mins);
76                         vector move;
77                         if (rotated)
78                         {
79                                 vector org = (it.move_origin - this.move_origin) + pivot;
80                                 vector org2;
81                                 org2.x = org * v_forward;
82                                 org2.y = org * v_right;
83                                 org2.z = org * v_up;
84                                 move = (org2 - org) + move1;
85                         }
86                         else
87                         {
88                                 move = move1;
89                         }
90
91                         // physics objects need better collisions than this code can do
92                         if (it.move_movetype == 32)  // MOVETYPE_PHYSICS
93                         {
94                                 it.move_origin = it.move_origin + move;
95                                 _Movetype_LinkEdict(it, true);
96                                 continue;
97                         }
98
99                         // try moving the contacted entity
100                         this.solid = SOLID_NOT;
101                         bool flag = false;
102                         flag = _Movetype_PushEntity(it, move, true);
103                         if (!flag)
104                         {
105                                 // entity "it" got teleported
106                                 it.move_angles_y += trace_fraction * moveangle.y;
107                                 this.solid = savesolid;
108                                 continue;  // pushed enough
109                         }
110                         // FIXME: turn players specially
111                         it.move_angles_y += trace_fraction * moveangle.y;
112                         this.solid = savesolid;
113
114                         // this trace.fraction < 1 check causes items to fall off of pushers
115                         // if they pass under or through a wall
116                         // the groundentity check causes items to fall off of ledges
117                         if (it.move_movetype != MOVETYPE_WALK && (trace_fraction < 1 || it.move_groundentity != this))
118                                 it.move_flags &= ~FL_ONGROUND;
119         });
120         }
121
122         this.move_angles_x -= 360.0 * floor(this.move_angles.x * (1.0 / 360.0));
123         this.move_angles_y -= 360.0 * floor(this.move_angles.y * (1.0 / 360.0));
124         this.move_angles_z -= 360.0 * floor(this.move_angles.z * (1.0 / 360.0));
125 }
126
127 void _Movetype_Physics_Pusher(entity this, float dt)  // SV_Physics_Pusher
128 {
129         float oldltime = this.move_ltime;
130         float thinktime = this.move_nextthink;
131         float movetime;
132         if (thinktime < this.move_ltime + dt)
133         {
134                 movetime = thinktime - this.move_ltime;
135                 if (movetime < 0)
136                         movetime = 0;
137         }
138         else
139         {
140                 movetime = dt;
141         }
142
143         if (movetime)
144                 // advances this.move_ltime if not blocked
145                 _Movetype_PushMove(this, movetime);
146
147         if (thinktime > oldltime && thinktime <= this.move_ltime)
148         {
149                 this.move_nextthink = 0;
150                 this.move_time = time;
151                 this.move_think(this);
152         }
153 }