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