161bdcbcc941ca69773ff6ebf589746fc6384a92
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / tturrets / system / system_misc.qc
1 //--// Some support routines //--//
2
3 #define anglemodss(a) (a - floor(a / 360) * 360)
4
5 float(float v) anglemods =
6 {
7         v = v - 360 * floor(v / 360);
8         return v;
9 }
10
11 float safeangle(float a)
12 {
13     if((a >= -360) && (a <= 360))
14         return a;
15
16
17     a -= (360 * floor(a / 360));
18
19     return a;
20 }
21
22 float shortangle_f(float ang1,float ang2)
23 {
24     if(ang1 > ang2)
25     {
26         if(ang1 > 180)
27             return ang1 - 360;
28     }
29     else
30     {
31         if(ang1 < -180)
32             return ang1 + 360;
33     }
34
35     return ang1;
36 }
37
38 vector shortangle_v(vector ang1,vector ang2)
39 {
40     vector vtmp;
41
42     vtmp_x = shortangle_f(ang1_x,ang2_x);
43     vtmp_y = shortangle_f(ang1_y,ang2_y);
44     vtmp_z = shortangle_f(ang1_z,ang2_z);
45
46     return vtmp;
47 }
48
49 vector shortangle_vxy(vector ang1,vector ang2)
50 {
51     vector vtmp;
52
53     vtmp_x = shortangle_f(ang1_x,ang2_x);
54     vtmp_y = shortangle_f(ang1_y,ang2_y);
55
56     return vtmp;
57 }
58
59 // Get real origin
60 vector real_origin(entity ent)
61 {
62     entity e;
63     vector v;
64
65     e = ent.tag_entity;
66     while(e)
67     {
68         // v = v + e.origin;
69         v = v + ((e.absmin + e.absmax) * 0.5);
70         e = e.tag_entity;
71     }
72     //v = v + ent.origin;
73     v = v + ((ent.absmin + ent.absmax) * 0.5);
74     return v;
75 }
76
77 // Plug this into wherever precache is done.
78 void g_turrets_common_precash()
79 {
80     precache_model ("models/turrets/c512.md3");
81     precache_model ("models/marker.md3");
82 }
83
84 void SUB_Remove();
85 void marker_think()
86 {
87     if(self.cnt)
88     if(self.cnt < time)
89     {
90         self.think = SUB_Remove;
91         self.nextthink = time;
92         return;
93     }
94
95     self.frame += 1;
96     if(self.frame > 29)
97         self.frame = 0;
98
99     self.nextthink = time;
100 }
101
102 void mark_error(vector where,float lifetime)
103 {
104     entity err;
105
106     err = spawn();
107     err.classname = "error_marker";
108     setmodel(err,"models/marker.md3");
109     setorigin(err,where);
110     err.movetype = MOVETYPE_NONE;
111     err.think = marker_think;
112     err.nextthink = time;
113     err.skin = 0;
114     if(lifetime)
115         err.cnt = lifetime + time;
116 }
117
118 void mark_info(vector where,float lifetime)
119 {
120     entity err;
121
122     err = spawn();
123     err.classname = "info_marker";
124     setmodel(err,"models/marker.md3");
125     setorigin(err,where);
126     err.movetype = MOVETYPE_NONE;
127     err.think = marker_think;
128     err.nextthink = time;
129     err.skin = 1;
130     if(lifetime)
131         err.cnt = lifetime + time;
132 }
133
134 entity mark_misc(vector where,float lifetime)
135 {
136     entity err;
137
138     err = spawn();
139     err.classname = "mark_misc";
140     setmodel(err,"models/marker.md3");
141     setorigin(err,where);
142     err.movetype = MOVETYPE_NONE;
143     err.think = marker_think;
144     err.nextthink = time;
145     err.skin = 3;
146     if(lifetime)
147         err.cnt = lifetime + time;
148     return err;
149 }
150
151 /*
152 * Paint a v_color colord circle on target onwho
153 * that fades away over f_time
154 */
155 void paint_target(entity onwho, float f_size, vector v_color, float f_time)
156 {
157     entity e;
158
159     e = spawn();
160     setmodel(e, "models/turrets/c512.md3"); // precision set above
161     e.scale = (f_size/512);
162     //setsize(e, '0 0 0', '0 0 0');
163     //setattachment(e,onwho,"");
164     setorigin(e,onwho.origin + '0 0 1');
165     e.alpha = 0.15;
166     e.movetype = MOVETYPE_FLY;
167
168     e.velocity = (v_color * 32); // + '0 0 1' * 64;
169
170     e.colormod = v_color;
171     SUB_SetFade(e,time,f_time);
172 }
173
174 void paint_target2(entity onwho, float f_size, vector v_color, float f_time)
175 {
176     entity e;
177
178     e = spawn();
179     setmodel(e, "models/turrets/c512.md3"); // precision set above
180     e.scale = (f_size/512);
181     setsize(e, '0 0 0', '0 0 0');
182
183     setorigin(e,onwho.origin + '0 0 1');
184     e.alpha = 0.15;
185     e.movetype = MOVETYPE_FLY;
186
187     e.velocity = (v_color * 32); // + '0 0 1' * 64;
188     e.avelocity_x = -128;
189
190     e.colormod = v_color;
191     SUB_SetFade(e,time,f_time);
192 }
193
194 void paint_target3(vector where, float f_size, vector v_color, float f_time)
195 {
196     entity e;
197     e = spawn();
198     setmodel(e, "models/turrets/c512.md3"); // precision set above
199     e.scale = (f_size/512);
200     setsize(e, '0 0 0', '0 0 0');
201     setorigin(e,where+ '0 0 1');
202     e.movetype = MOVETYPE_NONE;
203     e.velocity = '0 0 0';
204     e.colormod = v_color;
205     SUB_SetFade(e,time,f_time);
206 }
207
208 /*
209 * Return the angle between two enteties
210 */
211 vector angleofs(entity from, entity to)
212 {
213     vector v_res;
214
215     // makevectors(from.angles);
216     v_res = normalize(to.origin - from.origin);
217     v_res = vectoangles(v_res);
218     v_res = v_res - from.angles;
219
220     if (v_res_x < 0) v_res_x += 360;
221     if (v_res_x > 180) v_res_x -= 360;
222
223     if (v_res_y < 0) v_res_y += 360;
224     if (v_res_y > 180) v_res_y -= 360;
225
226     return v_res;
227 }
228
229 vector angleofs2(entity from, vector to)
230 {
231     vector v_res;
232
233     // makevectors(from.angles);
234     v_res = normalize(to - from.origin);
235     v_res = vectoangles(v_res);
236     v_res = v_res - from.angles;
237
238     if (v_res_x < 0) v_res_x += 360;
239     if (v_res_x > 180) v_res_x -= 360;
240
241     if (v_res_y < 0) v_res_y += 360;
242     if (v_res_y > 180) v_res_y -= 360;
243
244     return v_res;
245 }
246
247 vector angleofs3(vector from,vector from_a, entity to)
248 {
249     vector v_res;
250
251     // makevectors(from.angles);
252     v_res = normalize(to.origin - from);
253     v_res = vectoangles(v_res);
254     v_res = v_res - from_a;
255
256     if (v_res_x < 0) v_res_x += 360;
257     if (v_res_x > 180) v_res_x -= 360;
258
259     if (v_res_y < 0) v_res_y += 360;
260     if (v_res_y > 180) v_res_y -= 360;
261
262     return v_res;
263 }
264
265 float turret_tag_setup()
266 {
267     if(!self.tur_head)
268     {
269         dprint("Call to turret_tag_setup with self.tur_head missing!\n");
270         self.tur_shotorg = '0 0 0';
271         return 0;
272     }
273
274     //if not(self.turrcaps_flags & TFL_TURRCAPS_HEADATTACHED)
275     //    setorigin(self.tur_head,gettaginfo(self,gettagindex(self,"tag_head")));
276
277     self.tur_shotorg = gettaginfo(self.tur_head,gettagindex(self.tur_head,"tag_fire"));
278
279     v_forward = normalize(v_forward);
280
281     return 1;
282 }
283
284 float turret_tag_fire_update()
285 {
286     if(!self.tur_head)
287     {
288         dprint("Call to turret_tag_fire_update with self.tur_head missing!\n");
289         self.tur_shotorg = '0 0 0';
290         return 0;
291     }
292
293     self.tur_shotorg = gettaginfo(self.tur_head,gettagindex(self.tur_head,"tag_fire"));
294     v_forward = normalize(v_forward);
295
296     //dprint("update: tur_shotorg: ",vtos(self.tur_shotorg)," origin:", vtos(self.tur_head.origin), " angels: ", vtos(self.tur_head.angles),"\n");
297
298     return 1;
299 }
300
301 void FireImoBeam (vector start,vector end,vector smin,vector smax,
302                   float bforce,float f_dmg,float f_velfactor, float deathtype)
303
304 {
305     local vector hitloc, force, endpoint, dir;
306     local entity ent;
307
308     dir = normalize(end - start);
309     force = dir * bforce;
310
311     // go a little bit into the wall because we need to hit this wall later
312     end = end + dir;
313
314     // trace multiple times until we hit a wall, each obstacle will be made unsolid.
315     // note down which entities were hit so we can damage them later
316     while (1)
317     {
318         tracebox(start, smin, smax, end, FALSE, self);
319
320         // if it is world we can't hurt it so stop now
321         if (trace_ent == world || trace_fraction == 1)
322             break;
323
324         if (trace_ent.solid == SOLID_BSP)
325             break;
326
327         // make the entity non-solid so we can hit the next one
328         trace_ent.railgunhit = TRUE;
329         trace_ent.railgunhitloc = end;
330         trace_ent.railgunhitsolidbackup = trace_ent.solid;
331
332         // stop if this is a wall
333
334         // make the entity non-solid
335         trace_ent.solid = SOLID_NOT;
336     }
337
338     endpoint = trace_endpos;
339
340     // find all the entities the railgun hit and restore their solid state
341     ent = findfloat(world, railgunhit, TRUE);
342     while (ent)
343     {
344         // restore their solid type
345         ent.solid = ent.railgunhitsolidbackup;
346         ent = findfloat(ent, railgunhit, TRUE);
347     }
348
349     // find all the entities the railgun hit and hurt them
350     ent = findfloat(world, railgunhit, TRUE);
351     while (ent)
352     {
353         // get the details we need to call the damage function
354         hitloc = ent.railgunhitloc;
355         ent.railgunhitloc = '0 0 0';
356         ent.railgunhitsolidbackup = SOLID_NOT;
357         ent.railgunhit = FALSE;
358
359         // apply the damage
360         if (ent.takedamage)
361         {
362             Damage (ent, self, self, f_dmg, deathtype, hitloc, force);
363             ent.velocity = ent.velocity * f_velfactor;
364             //ent.alpha = 0.25 + random() * 0.75;
365         }
366
367         // advance to the next entity
368         ent = findfloat(ent, railgunhit, TRUE);
369     }
370     trace_endpos = endpoint;
371 }
372
373 void turrets_precache_debug_models()
374 {
375     precache_model ("models/turrets/c512.md3");
376     precache_model ("models/pathlib/goodsquare.md3");
377     precache_model ("models/pathlib/badsquare.md3");
378     precache_model ("models/pathlib/square.md3");
379     precache_model ("models/pathlib/edge.md3");
380 }
381
382 void turrets_precash()
383 {
384     precache_model ("models/turrets/base-gib1.md3");
385     precache_model ("models/turrets/base-gib2.md3");
386     precache_model ("models/turrets/base-gib3.md3");
387     precache_model ("models/turrets/base-gib4.md3");
388
389     precache_model ("models/turrets/head-gib1.md3");
390     precache_model ("models/turrets/head-gib2.md3");
391     precache_model ("models/turrets/head-gib3.md3");
392     precache_model ("models/turrets/head-gib4.md3");
393     precache_model ("models/turrets/terrainbase.md3");
394
395     //precache_model ("models/turrets/base.md3");
396     //precache_model ("models/turrets/flac.md3");
397     //precache_model ("models/turrets/pd_proj.md3");
398     //precache_model ("models/turrets/reactor.md3");
399     //precache_model ("models/turrets/mlrs_rocket.md3");
400     //precache_model ("models/turrets/hellion.md3");
401     //precache_model ("models/turrets/hunter2.md3");
402     //precache_model ("models/turrets/hk.md3");
403     //precache_model ("models/turrets/machinegun.md3");
404     //precache_model ("models/turrets/rocket.md3");
405     //precache_model ("models/turrets/mlrs.md3");
406     //precache_model ("models/turrets/phaser.md3");
407     //precache_model ("models/turrets/phaser_beam.md3");
408     //precache_model ("models/turrets/plasmad.md3");
409     //precache_model ("models/turrets/plasma.md3");
410     //precache_model ("models/turrets/tesla_head.md3");
411     //precache_model ("models/turrets/tesla_base.md3");
412         //turrets_precache_debug_models();
413 }