Xonotic
racer_weapon.qc
Go to the documentation of this file.
1 #include "racer_weapon.qh"
2 
3 #ifdef SVQC
4 
5 void racer_fire_rocket(entity this, entity player, vector org, vector dir, entity trg);
6 METHOD(RacerAttack, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
7 {
8  bool isPlayer = IS_PLAYER(actor);
9  entity player = isPlayer ? actor : actor.owner;
10  entity veh = player.vehicle;
11  if (fire & 1)
12  if (weapon_prepareattack(thiswep, player, weaponentity, false, autocvar_g_vehicle_racer_cannon_refire)) {
13  if (veh) {
14  veh.vehicle_energy -= autocvar_g_vehicle_racer_cannon_cost;
15  veh.wait = time;
16  }
17  if(!isPlayer)
18  {
19  string tagname = (veh.cnt)
20  ? (veh.cnt = 0, "tag_fire1")
21  : (veh.cnt = 1, "tag_fire2");
22  vector vshotorg = gettaginfo(veh, gettagindex(veh, tagname));
23  w_shotorg = vshotorg;
25 
26  // Fix z-aim (for chase mode)
27  crosshair_trace(player);
28  w_shotdir.z = normalize(trace_endpos - vshotorg).z * 0.5;
29  }
30  if (isPlayer) W_SetupShot_Dir(player, weaponentity, v_forward, false, 0, SND_Null, CH_WEAPON_B, 0, DEATH_VH_WAKI_GUN.m_id);
31  vector org = w_shotorg;
33  entity bolt = vehicles_projectile(((veh) ? veh : player), EFFECT_RACER_MUZZLEFLASH, SND_LASERGUN_FIRE,
34  org, normalize(v_forward + randomvec() * autocvar_g_vehicle_racer_cannon_spread) * autocvar_g_vehicle_racer_cannon_speed,
35  autocvar_g_vehicle_racer_cannon_damage, autocvar_g_vehicle_racer_cannon_radius, autocvar_g_vehicle_racer_cannon_force, 0,
36  DEATH_VH_WAKI_GUN.m_id, PROJECTILE_WAKICANNON, 0, true, true, player);
37  bolt.velocity = normalize(dir) * autocvar_g_vehicle_racer_cannon_speed;
38  weapon_thinkf(player, weaponentity, WFRAME_FIRE1, 0, w_ready);
39  }
40  if (fire & 2)
41  if (!isPlayer || weapon_prepareattack(thiswep, actor, weaponentity, false, 0.2)) {
42  if (isPlayer) W_SetupShot_Dir(actor, weaponentity, v_forward, false, 0, SND_Null, CH_WEAPON_B, 0, DEATH_VH_WAKI_ROCKET.m_id);
43  racer_fire_rocket(((veh) ? veh : player), player, w_shotorg, w_shotdir, NULL);
44  weapon_thinkf(actor, weaponentity, WFRAME_FIRE2, 0, w_ready);
45  }
46 }
47 
48 METHOD(RacerAttack, wr_checkammo1, bool(RacerAttack thiswep, entity actor, .entity weaponentity))
49 {
50  bool isPlayer = IS_PLAYER(actor);
51  entity player = isPlayer ? actor : actor.owner;
52  entity veh = player.vehicle;
53  return isPlayer || veh.vehicle_energy >= autocvar_g_vehicle_racer_cannon_cost;
54 }
55 
56 void racer_rocket_tracker(entity this);
57 void racer_rocket_groundhugger(entity this);
58 
59 void racer_fire_rocket(entity this, entity player, vector org, vector dir, entity trg)
60 {
61  entity rocket = vehicles_projectile(this, EFFECT_RACER_ROCKETLAUNCH, SND_ROCKET_FIRE,
62  org, dir * autocvar_g_vehicle_racer_rocket_speed,
63  autocvar_g_vehicle_racer_rocket_damage, autocvar_g_vehicle_racer_rocket_radius, autocvar_g_vehicle_racer_rocket_force, 3,
64  DEATH_VH_WAKI_ROCKET.m_id, PROJECTILE_WAKIROCKET, 20, false, false, player);
65 
66  rocket.lip = autocvar_g_vehicle_racer_rocket_accel * sys_frametime;
67  rocket.wait = autocvar_g_vehicle_racer_rocket_turnrate;
68  rocket.nextthink = time;
69  rocket.enemy = trg;
70  rocket.cnt = time + 15;
71 
72  if(trg)
73  setthink(rocket, racer_rocket_tracker);
74  else
75  setthink(rocket, racer_rocket_groundhugger);
76 }
77 
78 void racer_rocket_tracker(entity this)
79 {
80  vector olddir, newdir;
81  float oldvel, newvel;
82 
83  this.nextthink = time;
84 
85  if (IS_DEAD(this.owner) || this.cnt < time)
86  {
87  this.use(this, NULL, NULL);
88  return;
89  }
90 
91  if(!this.realowner.vehicle)
92  {
94  return;
95  }
96 
97  olddir = normalize(this.velocity);
98  oldvel = vlen(this.velocity);
99  newvel = oldvel + this.lip;
100  makevectors(vectoangles(olddir));
101 
102  float time_to_impact = min(vlen(this.enemy.origin - this.origin) / vlen(this.velocity), 1);
103  vector predicted_origin = this.enemy.origin + this.enemy.velocity * time_to_impact;
104 
105  traceline(this.origin, this.origin + v_forward * 64 - '0 0 32', MOVE_NORMAL, this);
106  newdir = normalize(predicted_origin - this.origin);
107 
108  //vector
109  float height_diff = predicted_origin_z - this.origin_z;
110 
111  if(vdist(newdir - v_forward, >, autocvar_g_vehicle_racer_rocket_locked_maxangle))
112  {
113  //bprint("Target lost!\n");
114  //dprint("OF:", ftos(vlen(newdir - v_forward)), "\n");
115  setthink(this, racer_rocket_groundhugger);
116  return;
117  }
118 
119  if(trace_fraction != 1.0 && trace_ent != this.enemy)
120  newdir_z += 16 * sys_frametime;
121 
122  this.velocity = normalize(olddir + newdir * autocvar_g_vehicle_racer_rocket_turnrate) * newvel;
123  this.velocity_z -= 800 * sys_frametime;
124  this.velocity_z += max(height_diff, autocvar_g_vehicle_racer_rocket_climbspeed) * sys_frametime ;
125 
126  UpdateCSQCProjectile(this);
127  return;
128 }
129 
130 void racer_rocket_groundhugger(entity this)
131 {
132  vector olddir, newdir;
133  float oldvel, newvel;
134 
135  this.nextthink = time;
136 
137  if(IS_DEAD(this.owner) || this.cnt < time)
138  {
139  this.use(this, NULL, NULL);
140  return;
141  }
142 
143  if(!this.realowner.vehicle)
144  {
145  UpdateCSQCProjectile(this);
146  return;
147  }
148 
149  olddir = normalize(this.velocity);
150  oldvel = vlen(this.velocity);
151  newvel = oldvel + this.lip;
152 
153  tracebox(this.origin, this.mins, this.maxs, this.origin + olddir * 64, MOVE_WORLDONLY,this);
154  if(trace_fraction <= 0.5)
155  {
156  // Hitting somethign soon, just speed ahead
157  this.velocity = olddir * newvel;
158  UpdateCSQCProjectile(this);
159  return;
160  }
161 
162  traceline(trace_endpos, trace_endpos - '0 0 64', MOVE_NORMAL, this);
163  if(trace_fraction != 1.0)
164  {
165  newdir = normalize(trace_endpos + '0 0 64' - this.origin) * autocvar_g_vehicle_racer_rocket_turnrate;
166  this.velocity = normalize(olddir + newdir) * newvel;
167  }
168  else
169  {
170  this.velocity = olddir * newvel;
171  this.velocity_z -= 1600 * sys_frametime; // 2x grav looks better for this one
172  }
173 
174  int cont = pointcontents(this.origin - '0 0 32');
175  if(cont == CONTENT_WATER || cont == CONTENT_LAVA || cont == CONTENT_SLIME)
176  this.velocity_z += 200;
177 
178  UpdateCSQCProjectile(this);
179  return;
180 }
181 
182 #endif
const float CONTENT_LAVA
Definition: csprogsdefs.qc:240
vector w_shotorg
Definition: tracing.qh:18
entity() spawn
const float MOVE_NORMAL
Definition: csprogsdefs.qc:252
void w_ready(Weapon thiswep, entity actor,.entity weaponentity, int fire)
vector maxs
Definition: csprogsdefs.qc:113
vector w_shotdir
Definition: tracing.qh:19
origin
Definition: ent_cs.qc:114
#define gettaginfo
Definition: post.qh:32
#define METHOD(cname, name, prototype)
Definition: oo.qh:257
entity owner
Definition: main.qh:73
#define gettagindex
Definition: dpextensions.qh:16
void crosshair_trace(entity pl)
Definition: tracing.qc:508
entity trace_ent
Definition: csprogsdefs.qc:40
float sys_frametime
Definition: common.qh:57
entity enemy
Definition: sv_ctf.qh:143
vector mins
Definition: csprogsdefs.qc:113
float cnt
Definition: powerups.qc:24
const float CONTENT_SLIME
Definition: csprogsdefs.qc:239
void UpdateCSQCProjectile(entity e)
bool weapon_prepareattack(Weapon thiswep, entity actor,.entity weaponentity, bool secondary, float attacktime)
const float CONTENT_WATER
Definition: csprogsdefs.qc:238
#define NULL
Definition: post.qh:17
const int PROJECTILE_WAKIROCKET
Definition: projectiles.qh:28
vector trace_endpos
Definition: csprogsdefs.qc:37
#define IS_DEAD(s)
Definition: utils.qh:26
const int PROJECTILE_WAKICANNON
Definition: projectiles.qh:29
float nextthink
Definition: csprogsdefs.qc:121
#define W_SetupShot_Dir(ent, wepent, s_forward, antilag, recoil, snd, chan, maxdamage, deathtype)
Definition: tracing.qh:31
vector(float skel, float bonenum) _skel_get_boneabs_hidden
#define vdist(v, cmp, f)
Vector distance comparison, avoids sqrt()
Definition: vector.qh:8
float lip
Definition: subs.qh:40
void weapon_thinkf(entity actor,.entity weaponentity, WFRAME fr, float t, void(Weapon thiswep, entity actor,.entity weaponentity, int fire) func)
entity realowner
Definition: common.qh:25
#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
const int CH_WEAPON_B
Definition: sound.qh:8
int dir
Definition: impulse.qc:89
#define makevectors
Definition: post.qh:21
float trace_fraction
Definition: csprogsdefs.qc:36
#define IS_PLAYER(v)
Definition: utils.qh:9
vector v_forward
Definition: csprogsdefs.qc:31