1#include "util.qh"
2/*
3* Update this.tur_shotorg by getting up2date bone info
4* NOTICE this func overwrites the global v_forward, v_right and v_up vectors.
5*/
6float turret_tag_fire_update(entity this)
7{
8	if(!this.tur_head)
9	{
10		LOG_DEBUG("Call to turret_tag_fire_update with this.tur_head missing!");
11		this.tur_shotorg = '0 0 0';
12		return false;
13	}
14
15	this.tur_shotorg = gettaginfo(this.tur_head, gettagindex(this.tur_head, "tag_fire"));
16	v_forward = normalize(v_forward);
17
18	return true;
19}
20
21/*
22* Railgun-like beam, but has thickness and suppots slowing of target
23*/
24void FireImoBeam(entity this, vector start, vector end, vector smin, vector smax,
25				  float bforce, float f_dmg, float f_velfactor, int deathtype)
26
27{
28	vector hitloc, force, endpoint, dir;
29	entity ent;
30
31	dir = normalize(end - start);
32	force = dir * bforce;
33
34	// go a little bit into the wall because we need to hit this wall later
35	end = end + dir;
36
37	// trace multiple times until we hit a wall, each obstacle will be made unsolid.
38	// note down which entities were hit so we can damage them later
39	while (1)
40	{
41		tracebox(start, smin, smax, end, false, this);
42
43		// if it is NULL we can't hurt it so stop now
44		if (trace_ent == NULL || trace_fraction == 1)
45			break;
46
47		if (trace_ent.solid == SOLID_BSP)
48			break;
49
50		// make the entity non-solid so we can hit the next one
51		trace_ent.railgunhit = true;
52		trace_ent.railgunhitloc = end;
53		trace_ent.railgunhitsolidbackup = trace_ent.solid;
54
55		// stop if this is a wall
56
57		// make the entity non-solid
58		trace_ent.solid = SOLID_NOT;
59	}
60
61	endpoint = trace_endpos;
62
63	// find all the entities the railgun hit and restore their solid state
64	ent = findfloat(NULL, railgunhit, true);
65	while (ent)
66	{
67		// restore their solid type
68		ent.solid = ent.railgunhitsolidbackup;
69		ent = findfloat(ent, railgunhit, true);
70	}
71
72	// find all the entities the railgun hit and hurt them
73	ent = findfloat(NULL, railgunhit, true);
74	while (ent)
75	{
76		// get the details we need to call the damage function
77		hitloc = ent.railgunhitloc;
78		ent.railgunhitloc = '0 0 0';
79		ent.railgunhitsolidbackup = SOLID_NOT;
80		ent.railgunhit = false;
81
82		// apply the damage
83		if (ent.takedamage)
84		{
85			Damage (ent, this, this, f_dmg, deathtype, hitloc, force);
86			ent.velocity = ent.velocity * f_velfactor;
87			//ent.alpha = 0.25 + random() * 0.75;
88		}
89
90		// advance to the next entity
91		ent = findfloat(ent, railgunhit, true);
92	}
93	trace_endpos = endpoint;
94}
95
96#ifdef TURRET_DEBUG
97void marker_think(entity this, )
98{
99	if(this.cnt)
100	if(this.cnt < time)
101	{
102		setthink(this, SUB_Remove);
103		this.nextthink = time;
104		return;
105	}
106
107	this.frame += 1;
108	if(this.frame > 29)
109		this.frame = 0;
110
111	this.nextthink = time;
112}
113
114void mark_error(vector where,float lifetime)
115{
116	entity err = new(error_marker);
117	setmodel(err, MDL_MARKER);
118	setorigin(err, where);
119	set_movetype(err, MOVETYPE_NONE);
120	setthink(err, marker_think);
121	err.nextthink = time;
122	err.skin = 0;
123	if(lifetime)
124		err.cnt = lifetime + time;
125}
126
127void mark_info(vector where,float lifetime)
128{
129	entity err = spawn(info_marker);
130	setmodel(err, MDL_MARKER);
131	setorigin(err, where);
132	set_movetype(err, MOVETYPE_NONE);
133	setthink(err, marker_think);
134	err.nextthink = time;
135	err.skin = 1;
136	if(lifetime)
137		err.cnt = lifetime + time;
138}
139
140entity mark_misc(vector where,float lifetime)
141{
142	entity err = spawn(mark_misc);
143	setmodel(err, MDL_MARKER);
144	setorigin(err, where);
145	set_movetype(err, MOVETYPE_NONE);
146	setthink(err, marker_think);
147	err.nextthink = time;
148	err.skin = 3;
149	if(lifetime)
150		err.cnt = lifetime + time;
151	return err;
152}
153
154MODEL(TUR_C512, "models/turrets/c512.md3");
155
156/*
157* Paint a v_color colord circle on target onwho
158* that fades away over f_time
159*/
160void paint_target(entity onwho, float f_size, vector v_color, float f_time)
161{
162	entity e;
163
164	e = spawn();
165	setmodel(e, MDL_TUR_C512); // precision set above
166	e.scale = (f_size/512);
167	//setsize(e, '0 0 0', '0 0 0');
168	//setattachment(e,onwho,"");
169	setorigin(e, onwho.origin + '0 0 1');
170	e.alpha = 0.15;
171	set_movetype(e, MOVETYPE_FLY);
172
173	e.velocity = (v_color * 32); // + '0 0 1' * 64;
174
175	e.colormod = v_color;
176	SUB_SetFade(e,time,f_time);
177}
178
179void paint_target2(entity onwho, float f_size, vector v_color, float f_time)
180{
181	entity e;
182
183	e = spawn();
184	setmodel(e, MDL_TUR_C512); // precision set above
185	e.scale = (f_size/512);
186	setsize(e, '0 0 0', '0 0 0');
187
188	setorigin(e, onwho.origin + '0 0 1');
189	e.alpha = 0.15;
190	set_movetype(e, MOVETYPE_FLY);
191
192	e.velocity = (v_color * 32); // + '0 0 1' * 64;
193	e.avelocity_x = -128;
194
195	e.colormod = v_color;
196	SUB_SetFade(e,time,f_time);
197}
198
199void paint_target3(vector where, float f_size, vector v_color, float f_time)
200{
201	entity e;
202	e = spawn();
203	setmodel(e, MDL_TUR_C512); // precision set above
204	e.scale = (f_size/512);
205	setsize(e, '0 0 0', '0 0 0');
206	setorigin(e, where + '0 0 1');
207	set_movetype(e, MOVETYPE_NONE);
208	e.velocity = '0 0 0';
209	e.colormod = v_color;
210	SUB_SetFade(e,time,f_time);
211}
212#endif
213