1 #include "spiderbot_weapons.qh"
7 void spiderbot_rocket_artillery(entity this)
10 UpdateCSQCProjectile(this);
13 void spiderbot_rocket_unguided(entity this)
15 vector newdir, olddir;
17 this.nextthink = time;
19 olddir = normalize(this.velocity);
20 newdir = normalize(this.pos1 - this.origin) + randomvec() * autocvar_g_vehicle_spiderbot_rocket_noise;
21 this.velocity = normalize(olddir + newdir * autocvar_g_vehicle_spiderbot_rocket_turnrate) * autocvar_g_vehicle_spiderbot_rocket_speed;
23 UpdateCSQCProjectile(this);
25 if (IS_DEAD(this.owner) || this.cnt < time || vdist(this.pos1 - this.origin, <, 16))
26 this.use(this, NULL, NULL);
29 void spiderbot_rocket_guided(entity this)
31 vector newdir, olddir;
33 this.nextthink = time;
35 if(!this.realowner.vehicle)
36 setthink(this, spiderbot_rocket_unguided);
38 crosshair_trace(this.realowner);
39 olddir = normalize(this.velocity);
40 newdir = normalize(trace_endpos - this.origin) + randomvec() * autocvar_g_vehicle_spiderbot_rocket_noise;
41 this.velocity = normalize(olddir + newdir * autocvar_g_vehicle_spiderbot_rocket_turnrate) * autocvar_g_vehicle_spiderbot_rocket_speed;
43 UpdateCSQCProjectile(this);
45 if (IS_DEAD(this.owner) || this.cnt < time)
46 this.use(this, NULL, NULL);
49 void spiderbot_guide_release(entity this)
52 rkt = findchainentity(realowner, this.owner);
56 crosshair_trace(this.owner);
59 if(getthink(rkt) == spiderbot_rocket_guided)
61 rkt.pos1 = trace_endpos;
62 setthink(rkt, spiderbot_rocket_unguided);
68 float spiberbot_calcartillery_flighttime;
69 vector spiberbot_calcartillery(vector org, vector tgt, float ht)
71 float grav, sdist, zdist, vs, vz, jumpheight;
74 grav = autocvar_sv_gravity;
75 zdist = tgt_z - org_z;
76 sdist = vlen(tgt - org - zdist * '0 0 1');
77 sdir = normalize(tgt - org - zdist * '0 0 1');
79 // how high do we need to go?
80 jumpheight = fabs(ht);
82 jumpheight = jumpheight + zdist;
85 vz = sqrt(2 * grav * jumpheight); // NOTE: sqrt(positive)!
87 // we start with downwards velocity only if it's a downjump and the jump apex should be outside the jump!
93 solution = solve_quadratic(0.5 * grav, -vz, zdist); // equation "z(ti) = zdist"
94 // ALWAYS solvable because jumpheight >= zdist
96 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)
98 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)
105 // almost straight line type
106 // jump apex is before the jump
107 // we must take the larger one
108 spiberbot_calcartillery_flighttime = solution_y;
113 // jump apex is during the jump
114 // we must take the larger one too
115 spiberbot_calcartillery_flighttime = solution_y;
123 // almost straight line type
124 // jump apex is after the jump
125 // we must take the smaller one
126 spiberbot_calcartillery_flighttime = solution_x;
131 // jump apex is during the jump
132 // we must take the larger one
133 spiberbot_calcartillery_flighttime = solution_y;
136 vs = sdist / spiberbot_calcartillery_flighttime;
138 // finally calculate the velocity
139 return sdir * vs + '0 0 1' * vz;
142 void spiderbot_rocket_do(entity this)
145 entity rocket = NULL;
147 if (this.wait != -10)
149 if (PHYS_INPUT_BUTTON_ATCK2(this.owner) && this.vehicle_weapon2mode == SBRM_GUIDE)
152 if (this.tur_head.frame == 9 || this.tur_head.frame == 1)
154 if(this.gun2.cnt < time && this.tur_head.frame == 9)
155 this.tur_head.frame = 1;
164 spiderbot_guide_release(this);
170 if(this.gun2.cnt > time)
173 if (this.tur_head.frame >= 9)
175 this.tur_head.frame = 1;
180 if(!PHYS_INPUT_BUTTON_ATCK2(this.owner))
183 if(forbidWeaponUse(this.owner))
186 v = gettaginfo(this.tur_head,gettagindex(this.tur_head,"tag_fire"));
188 switch(this.vehicle_weapon2mode)
191 rocket = vehicles_projectile(this, EFFECT_SPIDERBOT_ROCKETLAUNCH.eent_eff_name, SND_ROCKET_FIRE,
192 v, normalize(randomvec() * autocvar_g_vehicle_spiderbot_rocket_spread + v_forward) * autocvar_g_vehicle_spiderbot_rocket_speed,
193 autocvar_g_vehicle_spiderbot_rocket_damage, autocvar_g_vehicle_spiderbot_rocket_radius, autocvar_g_vehicle_spiderbot_rocket_force, 1,
194 DEATH_VH_SPID_ROCKET.m_id, PROJECTILE_SPIDERROCKET, autocvar_g_vehicle_spiderbot_rocket_health, false, true, this.owner);
195 crosshair_trace(this.owner);
196 float _dist = (random() * autocvar_g_vehicle_spiderbot_rocket_radius) + vlen(v - trace_endpos);
197 _dist -= (random() * autocvar_g_vehicle_spiderbot_rocket_radius) ;
198 rocket.nextthink = time + (_dist / autocvar_g_vehicle_spiderbot_rocket_speed);
199 setthink(rocket, vehicles_projectile_explode);
201 if(PHYS_INPUT_BUTTON_ATCK2(this.owner) && this.tur_head.frame == 1)
205 rocket = vehicles_projectile(this, EFFECT_SPIDERBOT_ROCKETLAUNCH.eent_eff_name, SND_ROCKET_FIRE,
206 v, normalize(v_forward) * autocvar_g_vehicle_spiderbot_rocket_speed,
207 autocvar_g_vehicle_spiderbot_rocket_damage, autocvar_g_vehicle_spiderbot_rocket_radius, autocvar_g_vehicle_spiderbot_rocket_force, 1,
208 DEATH_VH_SPID_ROCKET.m_id, PROJECTILE_SPIDERROCKET, autocvar_g_vehicle_spiderbot_rocket_health, false, false, this.owner);
209 crosshair_trace(this.owner);
210 rocket.pos1 = trace_endpos;
211 rocket.nextthink = time;
212 setthink(rocket, spiderbot_rocket_guided);
217 rocket = vehicles_projectile(this, EFFECT_SPIDERBOT_ROCKETLAUNCH.eent_eff_name, SND_ROCKET_FIRE,
218 v, normalize(v_forward) * autocvar_g_vehicle_spiderbot_rocket_speed,
219 autocvar_g_vehicle_spiderbot_rocket_damage, autocvar_g_vehicle_spiderbot_rocket_radius, autocvar_g_vehicle_spiderbot_rocket_force, 1,
220 DEATH_VH_SPID_ROCKET.m_id, PROJECTILE_SPIDERROCKET, autocvar_g_vehicle_spiderbot_rocket_health, false, true, this.owner);
222 crosshair_trace(this.owner);
224 rocket.pos1 = trace_endpos + randomvec() * (0.75 * autocvar_g_vehicle_spiderbot_rocket_radius);
225 rocket.pos1_z = trace_endpos_z;
227 traceline(v, v + '0 0 1' * MAX_SHOT_DISTANCE, MOVE_WORLDONLY, this);
228 float h1 = 0.75 * vlen(v - trace_endpos);
231 traceline(v , rocket.pos1 + '0 0 1' * MAX_SHOT_DISTANCE, MOVE_WORLDONLY, this);
232 float h2 = 0.75 * vlen(rocket.pos1 - v);
234 rocket.velocity = spiberbot_calcartillery(v, rocket.pos1, ((h1 < h2) ? h1 : h2));
235 rocket.movetype = MOVETYPE_TOSS;
237 //setthink(rocket, spiderbot_rocket_artillery);
240 rocket.classname = "spiderbot_rocket";
242 rocket.cnt = time + autocvar_g_vehicle_spiderbot_rocket_lifetime;
244 this.tur_head.frame += 1;
245 if (this.tur_head.frame == 9)
246 this.attack_finished_single[0] = autocvar_g_vehicle_spiderbot_rocket_reload;
248 this.attack_finished_single[0] = ((this.vehicle_weapon2mode == SBRM_VOLLY) ? autocvar_g_vehicle_spiderbot_rocket_refire2 : autocvar_g_vehicle_spiderbot_rocket_refire);
250 this.gun2.cnt = time + this.attack_finished_single[0];