]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/common/vehicles/vehicle/spiderbot_weapons.qc
Clean up vehicle physics plugin a bit
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / vehicles / vehicle / spiderbot_weapons.qc
1 #ifndef VEHICLE_SPIDERBOT_WEAPONS_H
2 #define VEHICLE_SPIDERBOT_WEAPONS_H
3
4 #include <common/weapons/all.qh>
5
6 #endif
7
8 #ifdef IMPLEMENTATION
9
10 #ifdef SVQC
11
12 // 400 (x2) DPS
13 float autocvar_g_vehicle_spiderbot_minigun_damage = 24;
14 float autocvar_g_vehicle_spiderbot_minigun_refire = 0.06;
15 float autocvar_g_vehicle_spiderbot_minigun_spread = 0.015;
16 int autocvar_g_vehicle_spiderbot_minigun_ammo_cost = 1;
17 int autocvar_g_vehicle_spiderbot_minigun_ammo_max = 100;
18 int autocvar_g_vehicle_spiderbot_minigun_ammo_regen = 40;
19 float autocvar_g_vehicle_spiderbot_minigun_ammo_regen_pause = 1;
20 float autocvar_g_vehicle_spiderbot_minigun_force = 9;
21 float autocvar_g_vehicle_spiderbot_minigun_solidpenetration = 32;
22
23 float autocvar_g_vehicle_spiderbot_rocket_damage = 50;
24 float autocvar_g_vehicle_spiderbot_rocket_force = 150;
25 float autocvar_g_vehicle_spiderbot_rocket_radius = 250;
26 float autocvar_g_vehicle_spiderbot_rocket_speed = 3500;
27 float autocvar_g_vehicle_spiderbot_rocket_spread = 0.05;
28 float autocvar_g_vehicle_spiderbot_rocket_refire = 0.1;
29 // volley
30 float autocvar_g_vehicle_spiderbot_rocket_refire2 = 0.025;
31 float autocvar_g_vehicle_spiderbot_rocket_reload = 4;
32 float autocvar_g_vehicle_spiderbot_rocket_health = 100;
33 float autocvar_g_vehicle_spiderbot_rocket_noise = 0.2;
34 float autocvar_g_vehicle_spiderbot_rocket_turnrate = 0.25;
35 float autocvar_g_vehicle_spiderbot_rocket_lifetime = 20;
36
37 void spiderbot_rocket_artillery()
38 {SELFPARAM();
39     self.nextthink = time;
40     UpdateCSQCProjectile(self);
41 }
42
43 void spiderbot_rocket_unguided()
44 {SELFPARAM();
45     vector newdir, olddir;
46
47     self.nextthink  = time;
48
49     olddir = normalize(self.velocity);
50     newdir = normalize(self.pos1 - self.origin) + randomvec() * autocvar_g_vehicle_spiderbot_rocket_noise;
51     self.velocity = normalize(olddir + newdir * autocvar_g_vehicle_spiderbot_rocket_turnrate) * autocvar_g_vehicle_spiderbot_rocket_speed;
52
53     UpdateCSQCProjectile(self);
54
55     if (IS_DEAD(self.owner) || self.cnt < time || vdist(self.pos1 - self.origin, <, 16))
56         self.use();
57 }
58
59 void spiderbot_rocket_guided()
60 {SELFPARAM();
61     vector newdir, olddir;
62
63     self.nextthink  = time;
64
65     if(!self.realowner.vehicle)
66         self.think = spiderbot_rocket_unguided;
67
68     crosshair_trace(self.realowner);
69     olddir = normalize(self.velocity);
70     newdir = normalize(trace_endpos - self.origin) + randomvec() * autocvar_g_vehicle_spiderbot_rocket_noise;
71     self.velocity = normalize(olddir + newdir * autocvar_g_vehicle_spiderbot_rocket_turnrate) * autocvar_g_vehicle_spiderbot_rocket_speed;
72
73     UpdateCSQCProjectile(self);
74
75     if (IS_DEAD(self.owner) || self.cnt < time)
76         self.use();
77 }
78
79 void spiderbot_guide_release()
80 {SELFPARAM();
81     entity rkt;
82     rkt = findchainentity(realowner, self.owner);
83     if(!rkt)
84         return;
85
86     crosshair_trace(self.owner);
87     while(rkt)
88     {
89         if(rkt.think == spiderbot_rocket_guided)
90         {
91             rkt.pos1 = trace_endpos;
92             rkt.think = spiderbot_rocket_unguided;
93         }
94         rkt = rkt.chain;
95     }
96 }
97
98 float spiberbot_calcartillery_flighttime;
99 vector spiberbot_calcartillery(vector org, vector tgt, float ht)
100 {
101     float grav, sdist, zdist, vs, vz, jumpheight;
102     vector sdir;
103
104     grav  = autocvar_sv_gravity;
105     zdist = tgt_z - org_z;
106     sdist = vlen(tgt - org - zdist * '0 0 1');
107     sdir  = normalize(tgt - org - zdist * '0 0 1');
108
109     // how high do we need to go?
110     jumpheight = fabs(ht);
111     if(zdist > 0)
112         jumpheight = jumpheight + zdist;
113
114     // push so high...
115     vz = sqrt(2 * grav * jumpheight); // NOTE: sqrt(positive)!
116
117     // we start with downwards velocity only if it's a downjump and the jump apex should be outside the jump!
118     if(ht < 0)
119         if(zdist < 0)
120             vz = -vz;
121
122     vector solution;
123     solution = solve_quadratic(0.5 * grav, -vz, zdist); // equation "z(ti) = zdist"
124     // ALWAYS solvable because jumpheight >= zdist
125     if(!solution_z)
126         solution_y = solution_x; // just in case it is not solvable due to roundoff errors, assume two equal solutions at their center (this is mainly for the usual case with ht == 0)
127     if(zdist == 0)
128         solution_x = solution_y; // solution_x is 0 in this case, so don't use it, but rather use solution_y (which will be sqrt(0.5 * jumpheight / grav), actually)
129
130     if(zdist < 0)
131     {
132         // down-jump
133         if(ht < 0)
134         {
135             // almost straight line type
136             // jump apex is before the jump
137             // we must take the larger one
138             spiberbot_calcartillery_flighttime = solution_y;
139         }
140         else
141         {
142             // regular jump
143             // jump apex is during the jump
144             // we must take the larger one too
145             spiberbot_calcartillery_flighttime = solution_y;
146         }
147     }
148     else
149     {
150         // up-jump
151         if(ht < 0)
152         {
153             // almost straight line type
154             // jump apex is after the jump
155             // we must take the smaller one
156             spiberbot_calcartillery_flighttime = solution_x;
157         }
158         else
159         {
160             // regular jump
161             // jump apex is during the jump
162             // we must take the larger one
163             spiberbot_calcartillery_flighttime = solution_y;
164         }
165     }
166     vs = sdist / spiberbot_calcartillery_flighttime;
167
168     // finally calculate the velocity
169     return sdir * vs + '0 0 1' * vz;
170 }
171
172 void spiderbot_rocket_do()
173 {SELFPARAM();
174     vector v;
175     entity rocket = world;
176
177     if (self.wait != -10)
178     {
179         if (PHYS_INPUT_BUTTON_ATCK2(self.owner) && self.vehicle_weapon2mode == SBRM_GUIDE)
180         {
181             if (self.wait == 1)
182             if (self.tur_head.frame == 9 || self.tur_head.frame == 1)
183             {
184                 if(self.gun2.cnt < time && self.tur_head.frame == 9)
185                     self.tur_head.frame = 1;
186
187                 return;
188             }
189             self.wait = 1;
190         }
191         else
192         {
193             if(self.wait)
194                 spiderbot_guide_release();
195
196             self.wait = 0;
197         }
198     }
199
200     if(self.gun2.cnt > time)
201         return;
202
203     if (self.tur_head.frame >= 9)
204     {
205         self.tur_head.frame = 1;
206         self.wait = 0;
207     }
208
209     if(self.wait != -10)
210     if(!PHYS_INPUT_BUTTON_ATCK2(self.owner))
211         return;
212
213     if(forbidWeaponUse(self.owner))
214         return;
215
216     v = gettaginfo(self.tur_head,gettagindex(self.tur_head,"tag_fire"));
217
218     switch(self.vehicle_weapon2mode)
219     {
220         case SBRM_VOLLY:
221             rocket = vehicles_projectile(self, EFFECT_SPIDERBOT_ROCKETLAUNCH.eent_eff_name, SND_ROCKET_FIRE,
222                                    v, normalize(randomvec() * autocvar_g_vehicle_spiderbot_rocket_spread + v_forward) * autocvar_g_vehicle_spiderbot_rocket_speed,
223                                    autocvar_g_vehicle_spiderbot_rocket_damage, autocvar_g_vehicle_spiderbot_rocket_radius, autocvar_g_vehicle_spiderbot_rocket_force, 1,
224                                    DEATH_VH_SPID_ROCKET.m_id, PROJECTILE_SPIDERROCKET, autocvar_g_vehicle_spiderbot_rocket_health, false, true, self.owner);
225             crosshair_trace(self.owner);
226             float _dist = (random() * autocvar_g_vehicle_spiderbot_rocket_radius) + vlen(v - trace_endpos);
227             _dist -= (random() * autocvar_g_vehicle_spiderbot_rocket_radius) ;
228             rocket.nextthink  = time + (_dist / autocvar_g_vehicle_spiderbot_rocket_speed);
229             rocket.think         = vehicles_projectile_explode;
230
231             if(PHYS_INPUT_BUTTON_ATCK2(self.owner) && self.tur_head.frame == 1)
232                 self.wait = -10;
233             break;
234         case SBRM_GUIDE:
235             rocket = vehicles_projectile(self, EFFECT_SPIDERBOT_ROCKETLAUNCH.eent_eff_name, SND_ROCKET_FIRE,
236                                    v, normalize(v_forward) * autocvar_g_vehicle_spiderbot_rocket_speed,
237                                    autocvar_g_vehicle_spiderbot_rocket_damage, autocvar_g_vehicle_spiderbot_rocket_radius, autocvar_g_vehicle_spiderbot_rocket_force, 1,
238                                    DEATH_VH_SPID_ROCKET.m_id, PROJECTILE_SPIDERROCKET, autocvar_g_vehicle_spiderbot_rocket_health, false, false, self.owner);
239             crosshair_trace(self.owner);
240             rocket.pos1    = trace_endpos;
241             rocket.nextthink  = time;
242             rocket.think          = spiderbot_rocket_guided;
243
244
245         break;
246         case SBRM_ARTILLERY:
247             rocket = vehicles_projectile(self, EFFECT_SPIDERBOT_ROCKETLAUNCH.eent_eff_name, SND_ROCKET_FIRE,
248                                    v, normalize(v_forward) * autocvar_g_vehicle_spiderbot_rocket_speed,
249                                    autocvar_g_vehicle_spiderbot_rocket_damage, autocvar_g_vehicle_spiderbot_rocket_radius, autocvar_g_vehicle_spiderbot_rocket_force, 1,
250                                    DEATH_VH_SPID_ROCKET.m_id, PROJECTILE_SPIDERROCKET, autocvar_g_vehicle_spiderbot_rocket_health, false, true, self.owner);
251
252             crosshair_trace(self.owner);
253
254             rocket.pos1    = trace_endpos + randomvec() * (0.75 * autocvar_g_vehicle_spiderbot_rocket_radius);
255             rocket.pos1_z          = trace_endpos_z;
256
257             traceline(v, v + '0 0 1' * MAX_SHOT_DISTANCE, MOVE_WORLDONLY, self);
258             float h1 = 0.75 * vlen(v - trace_endpos);
259
260             //v = trace_endpos;
261             traceline(v , rocket.pos1 + '0 0 1' * MAX_SHOT_DISTANCE, MOVE_WORLDONLY, self);
262             float h2 = 0.75 * vlen(rocket.pos1 - v);
263
264             rocket.velocity  = spiberbot_calcartillery(v, rocket.pos1, ((h1 < h2) ? h1 : h2));
265             rocket.movetype  = MOVETYPE_TOSS;
266             rocket.gravity   = 1;
267             //rocket.think       = spiderbot_rocket_artillery;
268         break;
269     }
270     rocket.classname  = "spiderbot_rocket";
271
272     rocket.cnt = time + autocvar_g_vehicle_spiderbot_rocket_lifetime;
273
274     self.tur_head.frame += 1;
275     if (self.tur_head.frame == 9)
276         self.attack_finished_single[0] = autocvar_g_vehicle_spiderbot_rocket_reload;
277     else
278         self.attack_finished_single[0] = ((self.vehicle_weapon2mode ==  SBRM_VOLLY) ? autocvar_g_vehicle_spiderbot_rocket_refire2 : autocvar_g_vehicle_spiderbot_rocket_refire);
279
280     self.gun2.cnt = time + self.attack_finished_single[0];
281 }
282
283 #endif
284
285 #endif