]> icculus.org git repositories - divverent/nexuiz.git/blob - data/qcsrc/warpzonelib/common.qc
ignore refsys in findradius
[divverent/nexuiz.git] / data / qcsrc / warpzonelib / common.qc
1 void WarpZone_SetUp(entity e, vector my_org, vector my_ang, vector other_org, vector other_ang)
2 {
3         e.warpzone_transform = AnglesTransform_Divide(other_ang, AnglesTransform_TurnDirectionFR(my_ang));
4         e.warpzone_shift = AnglesTransform_PrePostShift_GetPostShift(my_org, e.warpzone_transform, other_org);
5         e.warpzone_origin = my_org;
6         e.warpzone_targetorigin = other_org;
7         e.warpzone_angles = my_ang;
8         e.warpzone_targetangles = other_ang;
9         fixedmakevectors(my_ang); e.warpzone_forward = v_forward;
10         fixedmakevectors(other_ang); e.warpzone_targetforward = v_forward;
11 }
12
13 .entity enemy;
14
15 vector WarpZoneLib_BoxTouchesBrush_mins;
16 vector WarpZoneLib_BoxTouchesBrush_maxs;
17 entity WarpZoneLib_BoxTouchesBrush_ent;
18 entity WarpZoneLib_BoxTouchesBrush_ignore;
19 float WarpZoneLib_BoxTouchesBrush_Recurse()
20 {
21         float s;
22         entity se;
23         float f;
24
25         tracebox('0 0 0', WarpZoneLib_BoxTouchesBrush_mins, WarpZoneLib_BoxTouchesBrush_maxs, '0 0 0', MOVE_NOMONSTERS, WarpZoneLib_BoxTouchesBrush_ignore);
26 #ifdef CSQC
27         if (trace_networkentity)
28         {
29                 dprint("hit a network ent, cannot continue WarpZoneLib_BoxTouchesBrush\n");
30                 // we cannot continue, as a player blocks us...
31                 // so, abort
32                 return 0;
33         }
34 #endif
35         if not(trace_ent)
36                 return 0;
37         if (trace_ent == WarpZoneLib_BoxTouchesBrush_ent)
38                 return 1;
39
40         se = trace_ent;
41         s = se.solid;
42         se.solid = SOLID_NOT;
43         f = WarpZoneLib_BoxTouchesBrush_Recurse();
44         se.solid = s;
45
46         return f;
47 }
48
49 float WarpZoneLib_BoxTouchesBrush(vector mi, vector ma, entity e, entity ig)
50 {
51     float f, s;
52
53     if not(e.modelindex)
54         return 1;
55
56     s = e.solid;
57     e.solid = SOLID_BSP;
58     WarpZoneLib_BoxTouchesBrush_mins = mi;
59     WarpZoneLib_BoxTouchesBrush_maxs = ma;
60     WarpZoneLib_BoxTouchesBrush_ent = e;
61     WarpZoneLib_BoxTouchesBrush_ignore = ig;
62     f = WarpZoneLib_BoxTouchesBrush_Recurse();
63     e.solid = s;
64
65     return f;
66 }
67
68 entity WarpZone_Find(vector mi, vector ma)
69 {
70         // if we are near any warpzone planes - MOVE AWAY (work around nearclip)
71         entity e;
72         for(e = world; (e = find(e, classname, "trigger_warpzone")); )
73                 if(WarpZoneLib_BoxTouchesBrush(mi, ma, e, world))
74                         return e;
75         return world;
76 }
77
78 void WarpZone_MakeAllSolid()
79 {
80         entity e;
81         for(e = world; (e = find(e, classname, "trigger_warpzone")); )
82                 e.solid = SOLID_BSP;
83 }
84
85 void WarpZone_MakeAllOther()
86 {
87         entity e;
88         for(e = world; (e = find(e, classname, "trigger_warpzone")); )
89                 e.solid = SOLID_TRIGGER;
90 }
91
92 void WarpZone_TraceBox(vector org, vector mi, vector ma, vector end, float nomonsters, entity forent)
93 {
94         float frac, sol;
95         vector o0, e0;
96         entity wz;
97         vector vf, vr, vu;
98         vf = v_forward;
99         vr = v_right;
100         vu = v_up;
101         o0 = org;
102         e0 = end;
103         // if starting in warpzone, first transform
104         wz = WarpZone_Find(org + mi, org + ma);
105         if(wz)
106         {
107                 org = WarpZone_TransformOrigin(wz, trace_endpos);
108                 end = WarpZone_TransformOrigin(wz, end);
109                 WarpZone_trace_velocity = WarpZone_TransformVelocity(wz, WarpZone_trace_velocity);
110                 WarpZone_trace_angles = WarpZone_TransformAngles(wz, WarpZone_trace_angles);
111                 WarpZone_trace_v_angle = WarpZone_TransformVAngles(wz, WarpZone_trace_v_angle);
112         }
113         WarpZone_MakeAllSolid();
114         sol = -1;
115         frac = 0;
116         for(;;)
117         {
118                 tracebox(org, mi, ma, end, nomonsters, forent);
119                 if(WarpZone_trace_callback)
120                         WarpZone_trace_callback(org, trace_endpos, end);
121                 if(sol < 0)
122                         sol = trace_startsolid;
123                 if(trace_fraction >= 1)
124                         break;
125                 frac = trace_fraction = frac + (1 - frac) * trace_fraction;
126                 if(trace_ent.classname != "trigger_warpzone")
127                         break;
128                 if(trace_ent == wz)
129                 {
130                         dprint("I transformed into the same zone again, wtf, aborting the trace\n");
131                         break;
132                 }
133                 wz = trace_ent;
134                 // we hit a warpzone... so, let's perform the trace after the warp again
135                 org = WarpZone_TransformOrigin(wz, trace_endpos);
136                 end = WarpZone_TransformOrigin(wz, end);
137                 WarpZone_trace_velocity = WarpZone_TransformVelocity(wz, WarpZone_trace_velocity);
138                 WarpZone_trace_angles = WarpZone_TransformAngles(wz, WarpZone_trace_angles);
139                 WarpZone_trace_v_angle = WarpZone_TransformVAngles(wz, WarpZone_trace_v_angle);
140         }
141         WarpZone_MakeAllOther();
142         trace_startsolid = sol;
143         WarpZone_trace_endpos = o0 + (e0 - o0) * trace_fraction;
144         v_forward = vf;
145         v_right = vr;
146         v_up = vu;
147 }
148
149 void WarpZone_TraceBox_ThroughZone(vector org, vector mi, vector ma, vector end, float nomonsters, entity forent, entity zone)
150 {
151         float frac, sol;
152         vector o0, e0;
153         entity wz;
154         vector vf, vr, vu;
155         vf = v_forward;
156         vr = v_right;
157         vu = v_up;
158         o0 = org;
159         e0 = end;
160         // if starting in warpzone, first transform
161         wz = WarpZone_Find(org + mi, org + ma);
162         if(wz)
163         {
164                 if(wz != zone)
165                 {
166                         // we are in ANOTHER warpzone. This is bad. Make a zero length trace and return.
167                         sol = 1;
168                         trace_fraction = 0;
169                         trace_endpos = org;
170                         goto fail;
171                 }
172                 org = WarpZone_TransformOrigin(wz, trace_endpos);
173                 end = WarpZone_TransformOrigin(wz, end);
174                 WarpZone_trace_velocity = WarpZone_TransformVelocity(wz, WarpZone_trace_velocity);
175                 WarpZone_trace_angles = WarpZone_TransformAngles(wz, WarpZone_trace_angles);
176                 WarpZone_trace_v_angle = WarpZone_TransformVAngles(wz, WarpZone_trace_v_angle);
177         }
178         WarpZone_MakeAllSolid();
179         sol = -1;
180         frac = 0;
181         for(;;)
182         {
183                 tracebox(org, mi, ma, end, nomonsters, forent);
184                 if(WarpZone_trace_callback)
185                         WarpZone_trace_callback(org, trace_endpos, end);
186                 if(sol < 0)
187                         sol = trace_startsolid;
188                 if(trace_fraction >= 1)
189                         break;
190                 frac = trace_fraction = frac + (1 - frac) * trace_fraction;
191                 if(trace_ent.classname != "trigger_warpzone")
192                         break;
193                 if(trace_ent != zone)
194                         break;
195                 if(trace_ent == wz)
196                 {
197                         dprint("I transformed into the same zone again, wtf, aborting the trace\n");
198                         break;
199                 }
200                 wz = trace_ent;
201                 // we hit a warpzone... so, let's perform the trace after the warp again
202                 org = WarpZone_TransformOrigin(wz, trace_endpos);
203                 end = WarpZone_TransformOrigin(wz, end);
204                 WarpZone_trace_velocity = WarpZone_TransformVelocity(wz, WarpZone_trace_velocity);
205                 WarpZone_trace_angles = WarpZone_TransformAngles(wz, WarpZone_trace_angles);
206                 WarpZone_trace_v_angle = WarpZone_TransformVAngles(wz, WarpZone_trace_v_angle);
207         }
208         WarpZone_MakeAllOther();
209 :fail
210         trace_startsolid = sol;
211         WarpZone_trace_endpos = o0 + (e0 - o0) * trace_fraction;
212         v_forward = vf;
213         v_right = vr;
214         v_up = vu;
215 }
216
217 void WarpZone_TraceLine(vector org, vector end, float nomonsters, entity forent)
218 {
219         WarpZone_TraceBox(org, '0 0 0', '0 0 0', end, nomonsters, forent);
220 }
221
222 void WarpZone_TraceToss(entity e, entity forent)
223 {
224         float g, dt;
225         vector vf, vr, vu, v0, o0;
226         entity wz;
227         vf = v_forward;
228         vr = v_right;
229         vu = v_up;
230         v0 = e.velocity;
231         o0 = e.origin;
232         // if starting in warpzone, first transform
233         wz = WarpZone_Find(e.origin + e.mins, e.origin + e.maxs);
234         if(wz)
235         {
236                 setorigin(e, WarpZone_TransformOrigin(wz, e.origin));
237                 e.velocity = WarpZone_TransformVelocity(wz, e.velocity);
238         }
239         WarpZone_MakeAllSolid();
240         g = cvar("sv_gravity") * e.gravity;
241         WarpZone_tracetoss_time = 0;
242         for(;;)
243         {
244                 tracetoss(e, forent);
245                 if(WarpZone_trace_callback)
246                         WarpZone_trace_callback(e.origin, trace_endpos, trace_endpos);
247                 e.origin = trace_endpos;
248                 dt = vlen(e.origin - o0) / vlen(e.velocity);
249                 WarpZone_tracetoss_time += dt;
250                 e.velocity_z -= WarpZone_tracetoss_time * g;
251                 if(trace_fraction >= 1)
252                         break;
253                 if(trace_ent.classname != "trigger_warpzone")
254                         break;
255                 if(trace_ent == wz)
256                 {
257                         dprint("I transformed into the same zone again, wtf, aborting the trace\n");
258                         break;
259                 }
260                 wz = trace_ent;
261                 // we hit a warpzone... so, let's perform the trace after the warp again
262                 e.origin = WarpZone_TransformOrigin(wz, e.origin);
263                 e.velocity = WarpZone_TransformVelocity(wz, e.velocity);
264         }
265         WarpZone_MakeAllOther();
266         v_forward = vf;
267         v_right = vr;
268         v_up = vu;
269         WarpZone_tracetoss_velocity = e.velocity;
270         e.velocity = v0;
271         e.origin = o0;
272         WarpZone_trace_endpos = e.origin + e.velocity * WarpZone_tracetoss_time;
273         WarpZone_trace_endpos_z -= 0.5 * g * WarpZone_tracetoss_time * WarpZone_tracetoss_time;
274 }
275
276 void WarpZone_TrailParticles(entity own, float eff, vector org, vector end)
277 {
278         vector vf, vr, vu;
279         entity e;
280         vf = v_forward;
281         vr = v_right;
282         vu = v_up;
283         WarpZone_MakeAllSolid();
284         e = world;
285         for(;;)
286         {
287                 traceline(org, end, MOVE_NOMONSTERS, world);
288                 //print(vtos(org), " to ", vtos(trace_endpos), "\n");
289                 trailparticles(own, eff, org, trace_endpos);
290                 if(trace_fraction >= 1)
291                         break;
292                 if(trace_ent.classname != "trigger_warpzone")
293                         break;
294                 // we hit a warpzone... so, let's perform the trace after the warp again
295                 org = WarpZone_TransformOrigin(trace_ent, trace_endpos);
296                 end = WarpZone_TransformOrigin(trace_ent, end);
297                 if(trace_ent == e)
298                 {
299                         dprint("I transformed into the same zone again, wtf, aborting the trace\n");
300                         break;
301                 }
302                 e = trace_ent;
303         }
304         WarpZone_MakeAllOther();
305         v_forward = vf;
306         v_right = vr;
307         v_up = vu;
308 }
309
310 float WarpZone_PlaneDist(entity wz, vector v)
311 {
312         return (v - wz.warpzone_origin) * wz.warpzone_forward;
313 }
314
315 float WarpZone_TargetPlaneDist(entity wz, vector v)
316 {
317         return (v - wz.warpzone_targetorigin) * wz.warpzone_targetforward;
318 }
319
320 vector WarpZone_TransformOrigin(entity wz, vector v)
321 {
322         return wz.warpzone_shift + AnglesTransform_Apply(wz.warpzone_transform, v);
323 }
324
325 vector WarpZone_TransformVelocity(entity wz, vector v)
326 {
327         return AnglesTransform_Apply(wz.warpzone_transform, v);
328 }
329
330 vector WarpZone_TransformAngles(entity wz, vector v)
331 {
332         return AnglesTransform_ApplyToAngles(wz.warpzone_transform, v);
333 }
334
335 vector WarpZone_TransformVAngles(entity wz, vector ang)
336 {
337         float roll;
338
339         roll = ang_z;
340         ang_z = 0;
341
342         ang = AnglesTransform_ApplyToVAngles(wz.warpzone_transform, ang);
343         ang = AnglesTransform_Normalize(ang, TRUE);
344         ang = AnglesTransform_CancelRoll(ang);
345
346         ang_z = roll;
347         return ang;
348 }
349
350 vector WarpZone_UnTransformOrigin(entity wz, vector v)
351 {
352         return AnglesTransform_Apply(AnglesTransform_Invert(wz.warpzone_transform), v - wz.warpzone_shift);
353 }
354
355 vector WarpZone_UnTransformVelocity(entity wz, vector v)
356 {
357         return AnglesTransform_Apply(AnglesTransform_Invert(wz.warpzone_transform), v);
358 }
359
360 vector WarpZone_UnTransformAngles(entity wz, vector v)
361 {
362         return AnglesTransform_ApplyToAngles(AnglesTransform_Invert(wz.warpzone_transform), v);
363 }
364
365 vector WarpZone_UnTransformVAngles(entity wz, vector ang)
366 {
367         float roll;
368
369         roll = ang_z;
370         ang_z = 0;
371
372         ang = AnglesTransform_ApplyToVAngles(AnglesTransform_Invert(wz.warpzone_transform), ang);
373         ang = AnglesTransform_Normalize(ang, TRUE);
374         ang = AnglesTransform_CancelRoll(ang);
375
376         ang_z = roll;
377         return ang;
378 }
379
380 vector WarpZoneLib_NearestPointOnBox(vector mi, vector ma, vector org)
381 {
382         vector nearest;
383         nearest_x = bound(mi_x, org_x, ma_x);
384         nearest_y = bound(mi_y, org_y, ma_y);
385         nearest_z = bound(mi_z, org_z, ma_z);
386         return nearest;
387 }
388
389 .float WarpZone_findradius_hit;
390 .entity WarpZone_findradius_next;
391 void WarpZone_FindRadius_Recurse(vector org, float rad,        vector org0,               vector transform, vector shift, float needlineofsight)
392 //                               blast origin of current search   original blast origin   how to untransform (victim to blast system)
393 {
394         vector org_new;
395         vector org0_new;
396         vector shift_new, transform_new;
397         vector shift_second, transform_second;
398         vector p;
399         entity e, e0;
400         entity wz;
401         if(rad <= 0)
402                 return;
403         e0 = findradius(org, rad);
404         wz = world;
405
406         for(e = e0; e; e = e.chain)
407         {
408                 p = WarpZoneLib_NearestPointOnBox(e.origin + e.mins, e.origin + e.maxs, org0);
409                 if(needlineofsight)
410                 {
411                         traceline(org, p, MOVE_NOMONSTERS, e);
412                         if(trace_fraction < 1)
413                                 continue;
414                 }
415                 if(!e.WarpZone_findradius_hit || vlen(e.WarpZone_findradius_dist) > vlen(org0 - p))
416                 {
417                         e.WarpZone_findradius_nearest = p;
418                         e.WarpZone_findradius_dist = org0 - p;
419                         e.WarpZone_findradius_findorigin = org;
420                         e.WarpZone_findradius_findradius = rad;
421                         if(e.classname == "warpzone_refsys")
422                         {
423                                 // ignore, especially: do not overwrite the refsys parameters
424                         }
425                         else if(e.classname == "trigger_warpzone")
426                         {
427                                 e.WarpZone_findradius_next = wz;
428                                 wz = e;
429                                 e.WarpZone_findradius_hit = 1;
430                                 e.enemy.WarpZone_findradius_dist = '0 0 0'; // we don't want to go through this zone ever again
431                                 e.enemy.WarpZone_findradius_hit = 1;
432                         }
433                         else
434                         {
435                                 e.warpzone_transform = transform;
436                                 e.warpzone_shift = shift;
437                                 e.WarpZone_findradius_hit = 1;
438                         }
439                 }
440         }
441         for(e = wz; e; e = e.WarpZone_findradius_next)
442         {
443                 org0_new = WarpZone_TransformOrigin(e, org);
444                 traceline(e.warpzone_targetorigin, org0_new, MOVE_NOMONSTERS, e);
445                 org_new = trace_endpos;
446
447                 transform_second = AnglesTransform_Invert(e.warpzone_transform);
448                 shift_second = AnglesTransform_PrePostShift_GetPostShift(e.warpzone_shift, transform_second, '0 0 0'); // invert the shift
449                 transform_new = AnglesTransform_Multiply(transform, transform_second);
450                 shift_new = AnglesTransform_Multiply_GetPostShift(transform, shift, transform_second, shift_second);
451                 WarpZone_FindRadius_Recurse(
452                         org_new,
453                         bound(0, rad - vlen(org_new - org0_new), rad - 8),
454                         org0_new,
455                         transform_new, shift_new,
456                         needlineofsight);
457                 e.WarpZone_findradius_hit = 0;
458                 e.enemy.WarpZone_findradius_hit = 0;
459         }
460 }
461 entity WarpZone_FindRadius(vector org, float rad, float needlineofsight)
462 {
463         entity e0, e;
464         WarpZone_FindRadius_Recurse(org, rad, org, '0 0 0', '0 0 0', needlineofsight);
465         e0 = findchainfloat(WarpZone_findradius_hit, 1);
466         for(e = e0; e; e = e.chain)
467                 e.WarpZone_findradius_hit = 0;
468         return e0;
469 }
470
471 void WarpZone_Accumulator_Clear(entity acc)
472 {
473         acc.warpzone_transform = '0 0 0';
474         acc.warpzone_shift = '0 0 0';
475 }
476 void WarpZone_Accumulator_AddTransform(entity acc, vector t, vector s)
477 {
478         vector tr, st;
479         tr = AnglesTransform_Multiply(t, acc.warpzone_transform);
480         st = AnglesTransform_Multiply_GetPostShift(t, s, acc.warpzone_transform, acc.warpzone_shift);
481         acc.warpzone_transform = tr;
482         acc.warpzone_shift = st;
483 }
484 void WarpZone_Accumulator_Add(entity acc, entity wz)
485 {
486         vector t, st;
487         t = AnglesTransform_Multiply(wz.warpzone_transform, acc.warpzone_transform);
488         st = AnglesTransform_Multiply_GetPostShift(wz.warpzone_transform, wz.warpzone_shift, acc.warpzone_transform, acc.warpzone_shift);
489         acc.warpzone_transform = t;
490         acc.warpzone_shift = st;
491 }
492
493 .entity WarpZone_refsys;
494 void WarpZone_RefSys_GC()
495 {
496         // garbage collect unused reference systems
497         self.nextthink = time + 1;
498         if(self.owner.WarpZone_refsys != self)
499                 remove(self);
500 }
501 void WarpZone_RefSys_Add(entity me, entity wz)
502 {
503         if(me.WarpZone_refsys.owner != me)
504         {
505                 me.WarpZone_refsys = spawn();
506                 me.WarpZone_refsys.classname = "warpzone_refsys";
507                 me.WarpZone_refsys.owner = me;
508                 me.WarpZone_refsys.think = WarpZone_RefSys_GC;
509                 me.WarpZone_refsys.nextthink = time + 1;
510                 WarpZone_Accumulator_Clear(me.WarpZone_refsys);
511         }
512         if(wz)
513                 WarpZone_Accumulator_Add(me.WarpZone_refsys, wz);
514 }
515 .vector WarpZone_refsys_incremental_shift;
516 .vector WarpZone_refsys_incremental_transform;
517 void WarpZone_RefSys_AddIncrementally(entity me, entity ref)
518 {
519         vector t, s;
520         if(me.WarpZone_refsys_incremental_transform == ref.WarpZone_refsys.warpzone_transform)
521         if(me.WarpZone_refsys_incremental_shift == ref.WarpZone_refsys.warpzone_shift)
522                 return;
523         if(me.WarpZone_refsys.owner != me)
524         {
525                 me.WarpZone_refsys = spawn();
526                 me.WarpZone_refsys.classname = "warpzone_refsys";
527                 me.WarpZone_refsys.owner = me;
528                 me.WarpZone_refsys.think = WarpZone_RefSys_GC;
529                 me.WarpZone_refsys.nextthink = time + 1;
530                 WarpZone_Accumulator_Clear(me.WarpZone_refsys);
531         }
532         t = AnglesTransform_Invert(me.WarpZone_refsys_incremental_transform);
533         s = AnglesTransform_PrePostShift_GetPostShift(me.WarpZone_refsys_incremental_shift, t, '0 0 0');
534         WarpZone_Accumulator_AddTransform(me.WarpZone_refsys, t, s);
535         WarpZone_Accumulator_Add(me.WarpZone_refsys, ref);
536         me.WarpZone_refsys_incremental_shift = ref.WarpZone_refsys.warpzone_shift;
537         me.WarpZone_refsys_incremental_transform = ref.WarpZone_refsys.warpzone_transform;
538 }
539 void WarpZone_RefSys_BeginAddingIncrementally(entity me, entity ref)
540 {
541         me.WarpZone_refsys_incremental_shift = ref.WarpZone_refsys.warpzone_shift;
542         me.WarpZone_refsys_incremental_transform = ref.WarpZone_refsys.warpzone_transform;
543 }
544 vector WarpZone_RefSys_TransformOrigin(entity from, entity to, vector org)
545 {
546         if(from.WarpZone_refsys)
547                 org = WarpZone_UnTransformOrigin(from.WarpZone_refsys, org);
548         if(to.WarpZone_refsys)
549                 org = WarpZone_TransformOrigin(to.WarpZone_refsys, org);
550         return org;
551 }
552 vector WarpZone_RefSys_TransformVelocity(entity from, entity to, vector vel)
553 {
554         if(from.WarpZone_refsys)
555                 vel = WarpZone_UnTransformVelocity(from.WarpZone_refsys, vel);
556         if(to.WarpZone_refsys)
557                 vel = WarpZone_TransformVelocity(to.WarpZone_refsys, vel);
558         return vel;
559 }
560 vector WarpZone_RefSys_TransformAngles(entity from, entity to, vector ang)
561 {
562         if(from.WarpZone_refsys)
563                 ang = WarpZone_UnTransformAngles(from.WarpZone_refsys, ang);
564         if(to.WarpZone_refsys)
565                 ang = WarpZone_TransformAngles(to.WarpZone_refsys, ang);
566         return ang;
567 }
568 vector WarpZone_RefSys_TransformVAngles(entity from, entity to, vector ang)
569 {
570         if(from.WarpZone_refsys)
571                 ang = WarpZone_UnTransformVAngles(from.WarpZone_refsys, ang);
572         if(to.WarpZone_refsys)
573                 ang = WarpZone_TransformVAngles(to.WarpZone_refsys, ang);
574         return ang;
575 }
576 entity WarpZone_RefSys_SpawnSameRefSys(entity me)
577 {
578         entity e;
579         e = spawn();
580         if(me.WarpZone_refsys)
581         {
582                 e.WarpZone_refsys = spawn();
583                 e.WarpZone_refsys.classname = "warpzone_refsys";
584                 e.WarpZone_refsys.owner = e;
585                 e.WarpZone_refsys.think = WarpZone_RefSys_GC;
586                 e.WarpZone_refsys.nextthink = time + 1;
587                 e.WarpZone_refsys.warpzone_shift = me.WarpZone_refsys.warpzone_shift;
588                 e.WarpZone_refsys.warpzone_transform = me.WarpZone_refsys.warpzone_transform;
589         }
590         return e;
591 }