Xonotic
spiderbot_weapons.qc
Go to the documentation of this file.
1 #include "spiderbot_weapons.qh"
2 
3 #ifdef SVQC
4 
5 void spiderbot_rocket_artillery(entity this)
6 {
7  this.nextthink = time;
9 }
10 
11 void spiderbot_rocket_unguided(entity this)
12 {
13  vector newdir, olddir;
14 
15  this.nextthink = time;
16 
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;
20 
22 
23  if (IS_DEAD(this.owner) || this.cnt < time || vdist(this.pos1 - this.origin, <, 16))
24  this.use(this, NULL, NULL);
25 }
26 
27 void spiderbot_rocket_guided(entity this)
28 {
29  vector newdir, olddir;
30 
31  this.nextthink = time;
32 
33  if(!this.realowner.vehicle)
34  setthink(this, spiderbot_rocket_unguided);
35 
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;
40 
42 
43  if (IS_DEAD(this.owner) || this.cnt < time)
44  this.use(this, NULL, NULL);
45 }
46 
47 void spiderbot_guide_release(entity this)
48 {
49  bool donetrace = false;
50  IL_EACH(g_projectiles, it.realowner == this.owner && getthink(it) == spiderbot_rocket_guided,
51  {
52  if(!donetrace) // something exists, let's trace!
53  {
54  donetrace = true;
55  crosshair_trace(this.owner);
56  }
57 
58  it.pos1 = trace_endpos;
59  setthink(it, spiderbot_rocket_unguided);
60  });
61 }
62 
63 float spiberbot_calcartillery_flighttime;
64 vector spiberbot_calcartillery(vector org, vector tgt, float ht)
65 {
66  float grav, sdist, zdist, vs, vz, jumpheight;
67  vector sdir;
68 
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');
73 
74  // how high do we need to go?
75  jumpheight = fabs(ht);
76  if(zdist > 0)
77  jumpheight = jumpheight + zdist;
78 
79  // push so high...
80  vz = sqrt(2 * grav * jumpheight); // NOTE: sqrt(positive)!
81 
82  // we start with downwards velocity only if it's a downjump and the jump apex should be outside the jump!
83  if(ht < 0)
84  if(zdist < 0)
85  vz = -vz;
86 
87  vector solution;
88  solution = solve_quadratic(0.5 * grav, -vz, zdist); // equation "z(ti) = zdist"
89  // ALWAYS solvable because jumpheight >= zdist
90  if(!solution_z)
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)
92  if(zdist == 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)
94 
95  if(zdist < 0)
96  {
97  // down-jump
98  if(ht < 0)
99  {
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;
104  }
105  else
106  {
107  // regular jump
108  // jump apex is during the jump
109  // we must take the larger one too
110  spiberbot_calcartillery_flighttime = solution_y;
111  }
112  }
113  else
114  {
115  // up-jump
116  if(ht < 0)
117  {
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;
122  }
123  else
124  {
125  // regular jump
126  // jump apex is during the jump
127  // we must take the larger one
128  spiberbot_calcartillery_flighttime = solution_y;
129  }
130  }
131  vs = sdist / spiberbot_calcartillery_flighttime;
132 
133  // finally calculate the velocity
134  return sdir * vs + '0 0 1' * vz;
135 }
136 
137 void spiderbot_rocket_do(entity this)
138 {
139  vector v;
140  entity rocket = NULL;
141 
142  if (this.wait != -10)
143  {
144  if (PHYS_INPUT_BUTTON_ATCK2(this.owner) && STAT(VEHICLESTAT_W2MODE, this) == SBRM_GUIDE)
145  {
146  if (this.wait == 1)
147  if (this.tur_head.frame == 9 || this.tur_head.frame == 1)
148  {
149  if(this.gun2.cnt < time && this.tur_head.frame == 9)
150  this.tur_head.frame = 1;
151 
152  return;
153  }
154  this.wait = 1;
155  }
156  else
157  {
158  if(this.wait)
159  spiderbot_guide_release(this);
160 
161  this.wait = 0;
162  }
163  }
164 
165  if(this.gun2.cnt > time)
166  return;
167 
168  if (this.tur_head.frame >= 9)
169  {
170  this.tur_head.frame = 1;
171  this.wait = 0;
172  }
173 
174  if(this.wait != -10)
175  if(!PHYS_INPUT_BUTTON_ATCK2(this.owner))
176  return;
177 
178  if(weaponLocked(this.owner) || weaponUseForbidden(this.owner))
179  return;
180 
181  v = gettaginfo(this.tur_head,gettagindex(this.tur_head,"tag_fire"));
182 
183  switch(STAT(VEHICLESTAT_W2MODE, this))
184  {
185  case SBRM_VOLLY:
186  rocket = vehicles_projectile(this, EFFECT_SPIDERBOT_ROCKETLAUNCH, 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);
195 
196  if(PHYS_INPUT_BUTTON_ATCK2(this.owner) && this.tur_head.frame == 1)
197  this.wait = -10;
198  break;
199  case SBRM_GUIDE:
200  rocket = vehicles_projectile(this, EFFECT_SPIDERBOT_ROCKETLAUNCH, 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);
208 
209 
210  break;
211  case SBRM_ARTILLERY:
212  rocket = vehicles_projectile(this, EFFECT_SPIDERBOT_ROCKETLAUNCH, 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);
216 
217  crosshair_trace(this.owner);
218 
219  rocket.pos1 = trace_endpos + randomvec() * (0.75 * autocvar_g_vehicle_spiderbot_rocket_radius);
220  rocket.pos1_z = trace_endpos_z;
221 
222  traceline(v, v + '0 0 1' * max_shot_distance, MOVE_WORLDONLY, this);
223  float h1 = 0.75 * vlen(v - trace_endpos);
224 
225  //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);
228 
229  rocket.velocity = spiberbot_calcartillery(v, rocket.pos1, ((h1 < h2) ? h1 : h2));
230  set_movetype(rocket, MOVETYPE_TOSS);
231  rocket.gravity = 1;
232  //setthink(rocket, spiderbot_rocket_artillery);
233  break;
234  }
235  rocket.classname = "spiderbot_rocket";
236 
237  rocket.cnt = time + autocvar_g_vehicle_spiderbot_rocket_lifetime;
238 
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;
242  else
243  this.attack_finished_single[0] = ((STAT(VEHICLESTAT_W2MODE, this) == SBRM_VOLLY) ? autocvar_g_vehicle_spiderbot_rocket_refire2 : autocvar_g_vehicle_spiderbot_rocket_refire);
244 
245  this.gun2.cnt = time + this.attack_finished_single[0];
246 }
247 
248 #endif
#define PHYS_INPUT_BUTTON_ATCK2(s)
Definition: player.qh:148
#define IL_EACH(this, cond, body)
ERASEABLE vector solve_quadratic(float a, float b, float c)
ax^2 + bx + c = 0
Definition: math.qh:307
const int PROJECTILE_SPIDERROCKET
Definition: projectiles.qh:27
#define getthink(e)
bool weaponUseForbidden(entity player)
float MOVETYPE_TOSS
Definition: progsdefs.qc:252
entity tur_head
Definition: sv_turrets.qh:29
entity() spawn
origin
Definition: ent_cs.qc:114
#define gettaginfo
Definition: post.qh:32
entity owner
Definition: main.qh:73
#define gettagindex
Definition: dpextensions.qh:16
void crosshair_trace(entity pl)
Definition: tracing.qc:508
void vehicles_projectile_explode_think(entity this)
Definition: sv_vehicles.qc:213
bool weaponLocked(entity player)
float cnt
Definition: powerups.qc:24
void UpdateCSQCProjectile(entity e)
float wait
Definition: subs.qh:39
#define NULL
Definition: post.qh:17
vector trace_endpos
Definition: csprogsdefs.qc:37
#define IS_DEAD(s)
Definition: utils.qh:26
float nextthink
Definition: csprogsdefs.qc:121
vector(float skel, float bonenum) _skel_get_boneabs_hidden
IntrusiveList g_projectiles
Definition: common.qh:46
vector v
Definition: ent_cs.qc:116
#define vdist(v, cmp, f)
Vector distance comparison, avoids sqrt()
Definition: vector.qh:8
entity realowner
Definition: common.qh:25
vector pos1
Definition: subs.qh:50
#define setthink(e, f)
entity vehicles_projectile(entity this, entity _mzlfx, Sound _mzlsound, vector _org, vector _vel, float _dmg, float _radi, float _force, float _size, int _deahtype, float _projtype, float _health, bool _cull, bool _clianim, entity _owner)
Definition: sv_vehicles.qc:223
#define use
Definition: csprogsdefs.qh:50
float MOVE_WORLDONLY
float time
Definition: csprogsdefs.qc:16
vector velocity
Definition: csprogsdefs.qc:103
void set_movetype(entity this, int mt)
float attack_finished_single[MAX_WEAPONSLOTS]
Definition: weaponsystem.qh:36
vector v_forward
Definition: csprogsdefs.qc:31