1 #include "spiderbot_weapons.qh"
5 void spiderbot_rocket_artillery(entity this)
8 UpdateCSQCProjectile(this);
11 void spiderbot_rocket_unguided(entity this)
13 vector newdir, olddir;
15 this.nextthink = time;
17 olddir = normalize(this.velocity);
18 newdir = normalize(this.pos1 - this.origin) + randomvec() * autocvar_g_vehicle_spiderbot_rocket_noise;
19 this.velocity = normalize(olddir + newdir * autocvar_g_vehicle_spiderbot_rocket_turnrate) * autocvar_g_vehicle_spiderbot_rocket_speed;
21 UpdateCSQCProjectile(this);
23 if (IS_DEAD(this.owner) || this.cnt < time || vdist(this.pos1 - this.origin, <, 16))
24 this.use(this, NULL, NULL);
27 void spiderbot_rocket_guided(entity this)
29 vector newdir, olddir;
31 this.nextthink = time;
33 if(!this.realowner.vehicle)
34 setthink(this, spiderbot_rocket_unguided);
36 crosshair_trace(this.realowner);
37 olddir = normalize(this.velocity);
38 newdir = normalize(trace_endpos - this.origin) + randomvec() * autocvar_g_vehicle_spiderbot_rocket_noise;
39 this.velocity = normalize(olddir + newdir * autocvar_g_vehicle_spiderbot_rocket_turnrate) * autocvar_g_vehicle_spiderbot_rocket_speed;
41 UpdateCSQCProjectile(this);
43 if (IS_DEAD(this.owner) || this.cnt < time)
44 this.use(this, NULL, NULL);
47 void spiderbot_guide_release(entity this)
49 bool donetrace = false;
50 IL_EACH(g_projectiles, it.realowner == this.owner && getthink(it) == spiderbot_rocket_guided,
52 if(!donetrace) // something exists, let's trace!
55 crosshair_trace(this.owner);
58 it.pos1 = trace_endpos;
59 setthink(it, spiderbot_rocket_unguided);
63 float spiberbot_calcartillery_flighttime;
64 vector spiberbot_calcartillery(vector org, vector tgt, float ht)
66 float grav, sdist, zdist, vs, vz, jumpheight;
69 grav = autocvar_sv_gravity;
70 zdist = tgt_z - org_z;
71 sdist = vlen(tgt - org - zdist * '0 0 1');
72 sdir = normalize(tgt - org - zdist * '0 0 1');
74 // how high do we need to go?
75 jumpheight = fabs(ht);
77 jumpheight = jumpheight + zdist;
80 vz = sqrt(2 * grav * jumpheight); // NOTE: sqrt(positive)!
82 // we start with downwards velocity only if it's a downjump and the jump apex should be outside the jump!
88 solution = solve_quadratic(0.5 * grav, -vz, zdist); // equation "z(ti) = zdist"
89 // ALWAYS solvable because jumpheight >= zdist
91 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)
93 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)
100 // almost straight line type
101 // jump apex is before the jump
102 // we must take the larger one
103 spiberbot_calcartillery_flighttime = solution_y;
108 // jump apex is during the jump
109 // we must take the larger one too
110 spiberbot_calcartillery_flighttime = solution_y;
118 // almost straight line type
119 // jump apex is after the jump
120 // we must take the smaller one
121 spiberbot_calcartillery_flighttime = solution_x;
126 // jump apex is during the jump
127 // we must take the larger one
128 spiberbot_calcartillery_flighttime = solution_y;
131 vs = sdist / spiberbot_calcartillery_flighttime;
133 // finally calculate the velocity
134 return sdir * vs + '0 0 1' * vz;
137 void spiderbot_rocket_do(entity this)
140 entity rocket = NULL;
142 if (this.wait != -10)
144 if (PHYS_INPUT_BUTTON_ATCK2(this.owner) && STAT(VEHICLESTAT_W2MODE, this) == SBRM_GUIDE)
147 if (this.tur_head.frame == 9 || this.tur_head.frame == 1)
149 if(this.gun2.cnt < time && this.tur_head.frame == 9)
150 this.tur_head.frame = 1;
159 spiderbot_guide_release(this);
165 if(this.gun2.cnt > time)
168 if (this.tur_head.frame >= 9)
170 this.tur_head.frame = 1;
175 if(!PHYS_INPUT_BUTTON_ATCK2(this.owner))
178 if(!weaponLocked(this.owner) && !weaponUseForbidden(this.owner))
181 v = gettaginfo(this.tur_head,gettagindex(this.tur_head,"tag_fire"));
183 switch(STAT(VEHICLESTAT_W2MODE, this))
186 rocket = vehicles_projectile(this, EFFECT_SPIDERBOT_ROCKETLAUNCH.eent_eff_name, SND_ROCKET_FIRE,
187 v, normalize(randomvec() * autocvar_g_vehicle_spiderbot_rocket_spread + v_forward) * autocvar_g_vehicle_spiderbot_rocket_speed,
188 autocvar_g_vehicle_spiderbot_rocket_damage, autocvar_g_vehicle_spiderbot_rocket_radius, autocvar_g_vehicle_spiderbot_rocket_force, 1,
189 DEATH_VH_SPID_ROCKET.m_id, PROJECTILE_SPIDERROCKET, autocvar_g_vehicle_spiderbot_rocket_health, false, true, this.owner);
190 crosshair_trace(this.owner);
191 float _dist = (random() * autocvar_g_vehicle_spiderbot_rocket_radius) + vlen(v - trace_endpos);
192 _dist -= (random() * autocvar_g_vehicle_spiderbot_rocket_radius) ;
193 rocket.nextthink = time + (_dist / autocvar_g_vehicle_spiderbot_rocket_speed);
194 setthink(rocket, vehicles_projectile_explode_think);
196 if(PHYS_INPUT_BUTTON_ATCK2(this.owner) && this.tur_head.frame == 1)
200 rocket = vehicles_projectile(this, EFFECT_SPIDERBOT_ROCKETLAUNCH.eent_eff_name, SND_ROCKET_FIRE,
201 v, normalize(v_forward) * autocvar_g_vehicle_spiderbot_rocket_speed,
202 autocvar_g_vehicle_spiderbot_rocket_damage, autocvar_g_vehicle_spiderbot_rocket_radius, autocvar_g_vehicle_spiderbot_rocket_force, 1,
203 DEATH_VH_SPID_ROCKET.m_id, PROJECTILE_SPIDERROCKET, autocvar_g_vehicle_spiderbot_rocket_health, false, false, this.owner);
204 crosshair_trace(this.owner);
205 rocket.pos1 = trace_endpos;
206 rocket.nextthink = time;
207 setthink(rocket, spiderbot_rocket_guided);
212 rocket = vehicles_projectile(this, EFFECT_SPIDERBOT_ROCKETLAUNCH.eent_eff_name, SND_ROCKET_FIRE,
213 v, normalize(v_forward) * autocvar_g_vehicle_spiderbot_rocket_speed,
214 autocvar_g_vehicle_spiderbot_rocket_damage, autocvar_g_vehicle_spiderbot_rocket_radius, autocvar_g_vehicle_spiderbot_rocket_force, 1,
215 DEATH_VH_SPID_ROCKET.m_id, PROJECTILE_SPIDERROCKET, autocvar_g_vehicle_spiderbot_rocket_health, false, true, this.owner);
217 crosshair_trace(this.owner);
219 rocket.pos1 = trace_endpos + randomvec() * (0.75 * autocvar_g_vehicle_spiderbot_rocket_radius);
220 rocket.pos1_z = trace_endpos_z;
222 traceline(v, v + '0 0 1' * max_shot_distance, MOVE_WORLDONLY, this);
223 float h1 = 0.75 * vlen(v - trace_endpos);
226 traceline(v , rocket.pos1 + '0 0 1' * max_shot_distance, MOVE_WORLDONLY, this);
227 float h2 = 0.75 * vlen(rocket.pos1 - v);
229 rocket.velocity = spiberbot_calcartillery(v, rocket.pos1, ((h1 < h2) ? h1 : h2));
230 set_movetype(rocket, MOVETYPE_TOSS);
232 //setthink(rocket, spiderbot_rocket_artillery);
235 rocket.classname = "spiderbot_rocket";
237 rocket.cnt = time + autocvar_g_vehicle_spiderbot_rocket_lifetime;
239 this.tur_head.frame += 1;
240 if (this.tur_head.frame == 9)
241 this.attack_finished_single[0] = autocvar_g_vehicle_spiderbot_rocket_reload;
243 this.attack_finished_single[0] = ((STAT(VEHICLESTAT_W2MODE, this) == SBRM_VOLLY) ? autocvar_g_vehicle_spiderbot_rocket_refire2 : autocvar_g_vehicle_spiderbot_rocket_refire);
245 this.gun2.cnt = time + this.attack_finished_single[0];