1 #ifndef VEHICLE_SPIDERBOT_WEAPONS_H
2 #define VEHICLE_SPIDERBOT_WEAPONS_H
4 #include <common/weapons/all.qh>
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;
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;
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;
37 void spiderbot_rocket_artillery()
39 self.nextthink = time;
40 UpdateCSQCProjectile(self);
43 void spiderbot_rocket_unguided()
45 vector newdir, olddir;
47 self.nextthink = time;
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;
53 UpdateCSQCProjectile(self);
55 if (IS_DEAD(self.owner) || self.cnt < time || vdist(self.pos1 - self.origin, <, 16))
59 void spiderbot_rocket_guided()
61 vector newdir, olddir;
63 self.nextthink = time;
65 if(!self.realowner.vehicle)
66 self.think = spiderbot_rocket_unguided;
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;
73 UpdateCSQCProjectile(self);
75 if (IS_DEAD(self.owner) || self.cnt < time)
79 void spiderbot_guide_release()
82 rkt = findchainentity(realowner, self.owner);
86 crosshair_trace(self.owner);
89 if(rkt.think == spiderbot_rocket_guided)
91 rkt.pos1 = trace_endpos;
92 rkt.think = spiderbot_rocket_unguided;
98 float spiberbot_calcartillery_flighttime;
99 vector spiberbot_calcartillery(vector org, vector tgt, float ht)
101 float grav, sdist, zdist, vs, vz, jumpheight;
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');
109 // how high do we need to go?
110 jumpheight = fabs(ht);
112 jumpheight = jumpheight + zdist;
115 vz = sqrt(2 * grav * jumpheight); // NOTE: sqrt(positive)!
117 // we start with downwards velocity only if it's a downjump and the jump apex should be outside the jump!
123 solution = solve_quadratic(0.5 * grav, -vz, zdist); // equation "z(ti) = zdist"
124 // ALWAYS solvable because jumpheight >= zdist
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)
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)
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;
143 // jump apex is during the jump
144 // we must take the larger one too
145 spiberbot_calcartillery_flighttime = solution_y;
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;
161 // jump apex is during the jump
162 // we must take the larger one
163 spiberbot_calcartillery_flighttime = solution_y;
166 vs = sdist / spiberbot_calcartillery_flighttime;
168 // finally calculate the velocity
169 return sdir * vs + '0 0 1' * vz;
172 void spiderbot_rocket_do()
175 entity rocket = world;
177 if (self.wait != -10)
179 if (PHYS_INPUT_BUTTON_ATCK2(self.owner) && self.vehicle_weapon2mode == SBRM_GUIDE)
182 if (self.tur_head.frame == 9 || self.tur_head.frame == 1)
184 if(self.gun2.cnt < time && self.tur_head.frame == 9)
185 self.tur_head.frame = 1;
194 spiderbot_guide_release();
200 if(self.gun2.cnt > time)
203 if (self.tur_head.frame >= 9)
205 self.tur_head.frame = 1;
210 if(!PHYS_INPUT_BUTTON_ATCK2(self.owner))
213 if(forbidWeaponUse(self.owner))
216 v = gettaginfo(self.tur_head,gettagindex(self.tur_head,"tag_fire"));
218 switch(self.vehicle_weapon2mode)
221 rocket = vehicles_projectile(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;
231 if(PHYS_INPUT_BUTTON_ATCK2(self.owner) && self.tur_head.frame == 1)
235 rocket = vehicles_projectile(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;
247 rocket = vehicles_projectile(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);
252 crosshair_trace(self.owner);
254 rocket.pos1 = trace_endpos + randomvec() * (0.75 * autocvar_g_vehicle_spiderbot_rocket_radius);
255 rocket.pos1_z = trace_endpos_z;
257 traceline(v, v + '0 0 1' * MAX_SHOT_DISTANCE, MOVE_WORLDONLY, self);
258 float h1 = 0.75 * vlen(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);
264 rocket.velocity = spiberbot_calcartillery(v, rocket.pos1, ((h1 < h2) ? h1 : h2));
265 rocket.movetype = MOVETYPE_TOSS;
267 //rocket.think = spiderbot_rocket_artillery;
270 rocket.classname = "spiderbot_rocket";
272 rocket.cnt = time + autocvar_g_vehicle_spiderbot_rocket_lifetime;
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;
278 self.attack_finished_single[0] = ((self.vehicle_weapon2mode == SBRM_VOLLY) ? autocvar_g_vehicle_spiderbot_rocket_refire2 : autocvar_g_vehicle_spiderbot_rocket_refire);
280 self.gun2.cnt = time + self.attack_finished_single[0];