]> icculus.org git repositories - divverent/nexuiz.git/blob - data/qcsrc/warpzonelib/common.qc
now bullets support warpzones too
[divverent/nexuiz.git] / data / qcsrc / warpzonelib / common.qc
1 .vector warpzone_origin;
2 .vector warpzone_transform;
3 .entity enemy;
4
5 vector WarpZoneLib_BoxTouchesBrush_mins;
6 vector WarpZoneLib_BoxTouchesBrush_maxs;
7 entity WarpZoneLib_BoxTouchesBrush_ent;
8 entity WarpZoneLib_BoxTouchesBrush_ignore;
9 float WarpZoneLib_BoxTouchesBrush_Recurse()
10 {
11         float s;
12         entity se;
13         float f;
14
15         tracebox('0 0 0', WarpZoneLib_BoxTouchesBrush_mins, WarpZoneLib_BoxTouchesBrush_maxs, '0 0 0', MOVE_NOMONSTERS, WarpZoneLib_BoxTouchesBrush_ignore);
16 #ifdef CSQC
17         if (trace_networkentity)
18         {
19                 dprint("hit a network ent, cannot continue WarpZoneLib_BoxTouchesBrush\n");
20                 // we cannot continue, as a player blocks us...
21                 // so, abort
22                 return 0;
23         }
24 #endif
25         if not(trace_ent)
26                 return 0;
27         if (trace_ent == WarpZoneLib_BoxTouchesBrush_ent)
28                 return 1;
29
30         
31
32         se = trace_ent;
33         s = se.solid;
34         se.solid = SOLID_NOT;
35         f = WarpZoneLib_BoxTouchesBrush_Recurse();
36         se.solid = s;
37
38         return f;
39 }
40
41 float WarpZoneLib_BoxTouchesBrush(vector mi, vector ma, entity e, entity ig)
42 {
43     float f, s;
44
45     if not(e.modelindex)
46         return 1;
47
48     s = e.solid;
49     e.solid = SOLID_BSP;
50     WarpZoneLib_BoxTouchesBrush_mins = mi;
51     WarpZoneLib_BoxTouchesBrush_maxs = ma;
52     WarpZoneLib_BoxTouchesBrush_ent = e;
53     WarpZoneLib_BoxTouchesBrush_ignore = ig;
54     f = WarpZoneLib_BoxTouchesBrush_Recurse();
55     e.solid = s;
56
57     return f;
58 }
59
60 entity WarpZone_Find(vector mi, vector ma)
61 {
62         // if we are near any warpzone planes - MOVE AWAY (work around nearclip)
63         entity e;
64         for(e = world; (e = find(e, classname, "trigger_warpzone")); )
65                 if(WarpZoneLib_BoxTouchesBrush(mi, ma, e, world))
66                         return e;
67         return world;
68 }
69
70 void WarpZone_MakeAllSolid()
71 {
72         entity e;
73         for(e = world; (e = find(e, classname, "trigger_warpzone")); )
74                 e.solid = SOLID_BSP;
75 }
76
77 void WarpZone_MakeAllOther()
78 {
79         entity e;
80         for(e = world; (e = find(e, classname, "trigger_warpzone")); )
81                 e.solid = SOLID_TRIGGER;
82 }
83
84 void WarpZone_TraceBox(vector org, vector mi, vector ma, vector end, float nomonsters, entity forent)
85 {
86         float frac, sol;
87         vector o0, e0;
88         vector vf, vr, vu;
89         vf = v_forward;
90         vr = v_right;
91         vu = v_up;
92         WarpZone_MakeAllSolid();
93         o0 = org;
94         e0 = end;
95         sol = -1;
96         frac = 0;
97         for(;;)
98         {
99                 tracebox(org, mi, ma, end, nomonsters, forent);
100                 if(WarpZone_trace_callback)
101                         WarpZone_trace_callback();
102                 if(sol < 0)
103                         sol = trace_startsolid;
104                 if(trace_fraction >= 1)
105                         break;
106                 frac = trace_fraction = frac + (1 - frac) * trace_fraction;
107                 if(trace_ent.classname != "trigger_warpzone")
108                         break;
109                 // we hit a warpzone... so, let's perform the trace after the warp again
110                 org = WarpZone_TransformOrigin(trace_ent, trace_endpos);
111                 end = WarpZone_TransformOrigin(trace_ent, end);
112         }
113         WarpZone_MakeAllOther();
114         trace_startsolid = sol;
115         WarpZone_trace_endpos = o0 + (e0 - o0) * trace_fraction;
116         v_forward = vf;
117         v_right = vr;
118         v_up = vu;
119 }
120
121 void WarpZone_TraceLine(vector org, vector end, float nomonsters, entity forent)
122 {
123         WarpZone_TraceBox(org, '0 0 0', '0 0 0', end, nomonsters, forent);
124 }
125
126 void WarpZone_TraceToss(entity e, entity forent)
127 {
128         float g, dt;
129         vector vf, vr, vu, v0, o0;
130         vf = v_forward;
131         vr = v_right;
132         vu = v_up;
133         WarpZone_MakeAllSolid();
134         g = cvar("sv_gravity") * e.gravity;
135         WarpZone_tracetoss_time = 0;
136         v0 = e.velocity;
137         o0 = e.origin;
138         for(;;)
139         {
140                 tracetoss(e, forent);
141                 if(WarpZone_trace_callback)
142                         WarpZone_trace_callback();
143                 e.origin = trace_endpos;
144                 dt = vlen(e.origin - o0) / vlen(e.velocity);
145                 WarpZone_tracetoss_time += dt;
146                 e.velocity_z -= WarpZone_tracetoss_time * g;
147                 if(trace_fraction >= 1)
148                         break;
149                 if(trace_ent.classname != "trigger_warpzone")
150                         break;
151                 // we hit a warpzone... so, let's perform the trace after the warp again
152                 e.origin = WarpZone_TransformOrigin(trace_ent, e.origin);
153                 e.velocity = WarpZone_TransformVelocity(trace_ent, e.velocity);
154         }
155         WarpZone_MakeAllOther();
156         v_forward = vf;
157         v_right = vr;
158         v_up = vu;
159         WarpZone_tracetoss_velocity = e.velocity;
160         e.velocity = v0;
161         e.origin = o0;
162         WarpZone_trace_endpos = e.origin + e.velocity * WarpZone_tracetoss_time;
163         WarpZone_trace_endpos_z -= 0.5 * g * WarpZone_tracetoss_time * WarpZone_tracetoss_time;
164 }
165
166 void WarpZone_TrailParticles(entity own, float eff, vector org, vector end)
167 {
168         float frac;
169         vector vf, vr, vu;
170         vf = v_forward;
171         vr = v_right;
172         vu = v_up;
173         WarpZone_MakeAllSolid();
174         frac = 0;
175         for(;;)
176         {
177                 traceline(org, end, MOVE_NOMONSTERS, world);
178                 //print(vtos(org), " to ", vtos(trace_endpos), "\n");
179                 trailparticles(own, eff, org, trace_endpos);
180                 if(trace_fraction >= 1)
181                         break;
182                 if(trace_ent.classname != "trigger_warpzone")
183                         break;
184                 // we hit a warpzone... so, let's perform the trace after the warp again
185                 org = WarpZone_TransformOrigin(trace_ent, trace_endpos);
186                 end = WarpZone_TransformOrigin(trace_ent, end);
187         }
188         WarpZone_MakeAllOther();
189         v_forward = vf;
190         v_right = vr;
191         v_up = vu;
192 }
193
194 vector WarpZone_TransformOrigin(entity wz, vector v)
195 {
196         return wz.enemy.warpzone_origin + AnglesTransform_Apply(wz.warpzone_transform, v - wz.warpzone_origin);
197 }
198
199 vector WarpZone_TransformVelocity(entity wz, vector v)
200 {
201         return AnglesTransform_Apply(wz.warpzone_transform, v);
202 }
203
204 vector WarpZone_TransformAngles(entity wz, vector v)
205 {
206         return AnglesTransform_ApplyToAngles(wz.warpzone_transform, v);
207 }
208
209 vector WarpZone_TransformVAngles(entity wz, vector ang)
210 {
211         float roll;
212
213         roll = ang_z;
214         ang_z = 0;
215
216         ang = AnglesTransform_ApplyToVAngles(wz.warpzone_transform, ang);
217         ang = AnglesTransform_Normalize(ang, TRUE);
218         ang = AnglesTransform_CancelRoll(ang);
219
220         ang_z = roll;
221         return ang;
222 }