2 * Return a angle within +/- 360.
4 float anglemods(float v)
6 v = v - 360 * floor(v / 360);
17 * Return the short angle
19 float shortangle_f(float ang1, float ang2)
35 vector shortangle_v(vector ang1, vector ang2)
39 vtmp_x = shortangle_f(ang1_x,ang2_x);
40 vtmp_y = shortangle_f(ang1_y,ang2_y);
41 vtmp_z = shortangle_f(ang1_z,ang2_z);
46 vector shortangle_vxy(vector ang1, vector ang2)
50 vtmp_x = shortangle_f(ang1_x,ang2_x);
51 vtmp_y = shortangle_f(ang1_y,ang2_y);
58 * Get "real" origin, in worldspace, even if ent is attached to something else.
60 vector real_origin(entity ent)
68 v = v + ((e.absmin + e.absmax) * 0.5);
71 v = v + ((ent.absmin + ent.absmax) * 0.5);
76 * Return the angle between two enteties
78 vector angleofs(entity from, entity to)
82 v_res = normalize(to.origin - from.origin);
83 v_res = vectoangles(v_res);
84 v_res = v_res - from.angles;
86 if (v_res_x < 0) v_res_x += 360;
87 if (v_res_x > 180) v_res_x -= 360;
89 if (v_res_y < 0) v_res_y += 360;
90 if (v_res_y > 180) v_res_y -= 360;
95 vector angleofs3(vector from, vector from_a, entity to)
99 v_res = normalize(to.origin - from);
100 v_res = vectoangles(v_res);
101 v_res = v_res - from_a;
103 if (v_res_x < 0) v_res_x += 360;
104 if (v_res_x > 180) v_res_x -= 360;
106 if (v_res_y < 0) v_res_y += 360;
107 if (v_res_y > 180) v_res_y -= 360;
113 * Update self.tur_shotorg by getting up2date bone info
114 * NOTICE this func overwrites the global v_forward, v_right and v_up vectors.
116 float turret_tag_fire_update()
120 error("Call to turret_tag_fire_update with self.tur_head missing!\n");
121 self.tur_shotorg = '0 0 0';
125 self.tur_shotorg = gettaginfo(self.tur_head, gettagindex(self.tur_head, "tag_fire"));
126 v_forward = normalize(v_forward);
132 * Railgun-like beam, but has thickness and suppots slowing of target
134 void FireImoBeam (vector start, vector end, vector smin, vector smax,
135 float bforce, float f_dmg, float f_velfactor, float deathtype)
138 local vector hitloc, force, endpoint, dir;
141 dir = normalize(end - start);
142 force = dir * bforce;
144 // go a little bit into the wall because we need to hit this wall later
147 // trace multiple times until we hit a wall, each obstacle will be made unsolid.
148 // note down which entities were hit so we can damage them later
151 tracebox(start, smin, smax, end, FALSE, self);
153 // if it is world we can't hurt it so stop now
154 if (trace_ent == world || trace_fraction == 1)
157 if (trace_ent.solid == SOLID_BSP)
160 // make the entity non-solid so we can hit the next one
161 trace_ent.railgunhit = TRUE;
162 trace_ent.railgunhitloc = end;
163 trace_ent.railgunhitsolidbackup = trace_ent.solid;
165 // stop if this is a wall
167 // make the entity non-solid
168 trace_ent.solid = SOLID_NOT;
171 endpoint = trace_endpos;
173 // find all the entities the railgun hit and restore their solid state
174 ent = findfloat(world, railgunhit, TRUE);
177 // restore their solid type
178 ent.solid = ent.railgunhitsolidbackup;
179 ent = findfloat(ent, railgunhit, TRUE);
182 // find all the entities the railgun hit and hurt them
183 ent = findfloat(world, railgunhit, TRUE);
186 // get the details we need to call the damage function
187 hitloc = ent.railgunhitloc;
188 ent.railgunhitloc = '0 0 0';
189 ent.railgunhitsolidbackup = SOLID_NOT;
190 ent.railgunhit = FALSE;
195 Damage (ent, self, self, f_dmg, deathtype, hitloc, force);
196 ent.velocity = ent.velocity * f_velfactor;
197 //ent.alpha = 0.25 + random() * 0.75;
200 // advance to the next entity
201 ent = findfloat(ent, railgunhit, TRUE);
203 trace_endpos = endpoint;
206 // Plug this into wherever precache is done.
207 void g_turrets_common_precash()
209 precache_model ("models/turrets/c512.md3");
210 precache_model ("models/marker.md3");
213 void turrets_precache_debug_models()
215 precache_model ("models/turrets/c512.md3");
216 precache_model ("models/pathlib/goodsquare.md3");
217 precache_model ("models/pathlib/badsquare.md3");
218 precache_model ("models/pathlib/square.md3");
219 precache_model ("models/pathlib/edge.md3");
222 void turrets_precash()
224 precache_model ("models/turrets/base-gib1.md3");
225 precache_model ("models/turrets/base-gib2.md3");
226 precache_model ("models/turrets/base-gib3.md3");
227 precache_model ("models/turrets/base-gib4.md3");
229 precache_model ("models/turrets/head-gib1.md3");
230 precache_model ("models/turrets/head-gib2.md3");
231 precache_model ("models/turrets/head-gib3.md3");
232 precache_model ("models/turrets/head-gib4.md3");
233 precache_model ("models/turrets/terrainbase.md3");
235 //precache_model ("models/turrets/base.md3");
236 //precache_model ("models/turrets/flac.md3");
237 //precache_model ("models/turrets/pd_proj.md3");
238 //precache_model ("models/turrets/reactor.md3");
239 //precache_model ("models/turrets/mlrs_rocket.md3");
240 //precache_model ("models/turrets/hellion.md3");
241 //precache_model ("models/turrets/hunter2.md3");
242 //precache_model ("models/turrets/hk.md3");
243 //precache_model ("models/turrets/machinegun.md3");
244 //precache_model ("models/turrets/rocket.md3");
245 //precache_model ("models/turrets/mlrs.md3");
246 //precache_model ("models/turrets/phaser.md3");
247 //precache_model ("models/turrets/phaser_beam.md3");
248 //precache_model ("models/turrets/plasmad.md3");
249 //precache_model ("models/turrets/plasma.md3");
250 //precache_model ("models/turrets/tesla_head.md3");
251 //precache_model ("models/turrets/tesla_base.md3");
253 turrets_precache_debug_models();
265 self.think = SUB_Remove;
266 self.nextthink = time;
274 self.nextthink = time;
277 void mark_error(vector where,float lifetime)
282 err.classname = "error_marker";
283 setmodel(err,"models/marker.md3");
284 setorigin(err,where);
285 err.movetype = MOVETYPE_NONE;
286 err.think = marker_think;
287 err.nextthink = time;
290 err.cnt = lifetime + time;
293 void mark_info(vector where,float lifetime)
298 err.classname = "info_marker";
299 setmodel(err,"models/marker.md3");
300 setorigin(err,where);
301 err.movetype = MOVETYPE_NONE;
302 err.think = marker_think;
303 err.nextthink = time;
306 err.cnt = lifetime + time;
309 entity mark_misc(vector where,float lifetime)
314 err.classname = "mark_misc";
315 setmodel(err,"models/marker.md3");
316 setorigin(err,where);
317 err.movetype = MOVETYPE_NONE;
318 err.think = marker_think;
319 err.nextthink = time;
322 err.cnt = lifetime + time;
327 * Paint a v_color colord circle on target onwho
328 * that fades away over f_time
330 void paint_target(entity onwho, float f_size, vector v_color, float f_time)
335 setmodel(e, "models/turrets/c512.md3"); // precision set above
336 e.scale = (f_size/512);
337 //setsize(e, '0 0 0', '0 0 0');
338 //setattachment(e,onwho,"");
339 setorigin(e,onwho.origin + '0 0 1');
341 e.movetype = MOVETYPE_FLY;
343 e.velocity = (v_color * 32); // + '0 0 1' * 64;
345 e.colormod = v_color;
346 SUB_SetFade(e,time,f_time);
349 void paint_target2(entity onwho, float f_size, vector v_color, float f_time)
354 setmodel(e, "models/turrets/c512.md3"); // precision set above
355 e.scale = (f_size/512);
356 setsize(e, '0 0 0', '0 0 0');
358 setorigin(e,onwho.origin + '0 0 1');
360 e.movetype = MOVETYPE_FLY;
362 e.velocity = (v_color * 32); // + '0 0 1' * 64;
363 e.avelocity_x = -128;
365 e.colormod = v_color;
366 SUB_SetFade(e,time,f_time);
369 void paint_target3(vector where, float f_size, vector v_color, float f_time)
373 setmodel(e, "models/turrets/c512.md3"); // precision set above
374 e.scale = (f_size/512);
375 setsize(e, '0 0 0', '0 0 0');
376 setorigin(e,where+ '0 0 1');
377 e.movetype = MOVETYPE_NONE;
378 e.velocity = '0 0 0';
379 e.colormod = v_color;
380 SUB_SetFade(e,time,f_time);