Xonotic
okrpc.qc
Go to the documentation of this file.
1 #include "okrpc.qh"
2 
3 #ifdef SVQC
4 
5 .float m_chainsaw_damage; // accumulated damage of the missile as it passes trough enemies
6 
7 void W_OverkillRocketPropelledChainsaw_Explode(entity this, entity directhitentity)
8 {
9  this.event_damage = func_null;
10  this.takedamage = DAMAGE_NO;
11 
12  float explosion_damage = RadiusDamage(this, this.realowner, WEP_CVAR_PRI(okrpc, damage), WEP_CVAR_PRI(okrpc, edgedamage), WEP_CVAR_PRI(okrpc, radius), NULL, NULL, WEP_CVAR_PRI(okrpc, force), this.projectiledeathtype, this.weaponentity_fld, directhitentity);
13  if (explosion_damage > 0 && this.m_chainsaw_damage > 0)
14  {
15  // if chainsaw hit something, it removed fired damage (so that direct hit is 100%)
16  // now that we also damaged something by explosion we'd go over 100% so let's add the fired damage back
17  accuracy_add(this.realowner, DEATH_WEAPONOF(this.projectiledeathtype), WEP_CVAR(okrpc, damage), 0);
18  }
19 
20  delete(this);
21 }
22 
23 void W_OverkillRocketPropelledChainsaw_Explode_think(entity this)
24 {
25  W_OverkillRocketPropelledChainsaw_Explode(this, NULL);
26 }
27 
28 void W_OverkillRocketPropelledChainsaw_Touch (entity this, entity toucher)
29 {
30  if(WarpZone_Projectile_Touch(this, toucher))
31  if(wasfreed(this))
32  return;
33 
34  W_OverkillRocketPropelledChainsaw_Explode(this, toucher);
35 }
36 
37 void W_OverkillRocketPropelledChainsaw_Damage(entity this, entity inflictor, entity attacker, float damage, int deathtype, .entity weaponentity, vector hitloc, vector force)
38 {
39  if (GetResource(this, RES_HEALTH) <= 0)
40  return;
41 
42  if (!W_CheckProjectileDamage(inflictor.realowner, this.realowner, deathtype, -1)) // no exceptions
43  return; // g_projectiles_damage says to halt
44 
45  TakeResource(this, RES_HEALTH, damage);
46 
47  if (GetResource(this, RES_HEALTH) <= 0)
48  W_PrepareExplosionByDamage(this, attacker, W_OverkillRocketPropelledChainsaw_Explode_think);
49 }
50 
51 void W_OverkillRocketPropelledChainsaw_Think(entity this)
52 {
53  if(this.cnt <= time)
54  {
55  delete(this);
56  return;
57  }
58 
59  float myspeed = vlen(this.velocity);
60  float myspeed_accel = myspeed * sys_frametime;
61  vector mydir = normalize(this.velocity);
62 
63  tracebox(this.origin, this.mins, this.maxs, this.origin + mydir * (2 * myspeed_accel), MOVE_NORMAL, this);
64  if (IS_PLAYER(trace_ent))
65  {
67  {
68  if (this.m_chainsaw_damage == 0) // first hit
69  {
70  // The fired damage of the explosion is already counted in the statistics (when launching the chainsaw).
71  // We remove it here so that a direct hit that passes through and doesn't damage anything by the explosion later is still 100%.
72  float fired_damage = WEP_CVAR_PRI(okrpc, damage2) - WEP_CVAR_PRI(okrpc, damage);
73  float hit_damage = WEP_CVAR_PRI(okrpc, damage2);
74  accuracy_add(this.realowner, DEATH_WEAPONOF(this.projectiledeathtype), fired_damage, hit_damage);
75  }
76  this.m_chainsaw_damage += WEP_CVAR_PRI(okrpc, damage2);
77  }
78  Damage(trace_ent, this, this.realowner, WEP_CVAR_PRI(okrpc, damage2), this.projectiledeathtype, this.weaponentity_fld, this.origin, normalize(this.origin - trace_ent.origin) * WEP_CVAR_PRI(okrpc, force));
79  }
80 
81  this.velocity = mydir * (myspeed + (WEP_CVAR_PRI(okrpc, speedaccel) * sys_frametime));
82 
84  this.nextthink = time;
85 }
86 
87 void W_OverkillRocketPropelledChainsaw_Attack(Weapon thiswep, entity actor, .entity weaponentity)
88 {
89  entity missile = spawn(); //WarpZone_RefSys_SpawnSameRefSys(actor);
90 
91  W_DecreaseAmmo(thiswep, actor, WEP_CVAR_PRI(okrpc, ammo), weaponentity);
92  W_SetupShot_ProjectileSize(actor, weaponentity, '-3 -3 -3', '3 3 3', false, 5, SND_ROCKET_FIRE, CH_WEAPON_A, WEP_CVAR_PRI(okrpc, damage), thiswep.m_id);
93  W_MuzzleFlash(thiswep, actor, weaponentity, w_shotorg, w_shotdir);
94  PROJECTILE_MAKETRIGGER(missile);
95 
96  missile.owner = missile.realowner = actor;
97  missile.bot_dodge = true;
98  missile.bot_dodgerating = WEP_CVAR_PRI(okrpc, damage) * 2;
99 
100  missile.takedamage = DAMAGE_YES;
101  missile.damageforcescale = WEP_CVAR_PRI(okrpc, damageforcescale);
103  missile.event_damage = W_OverkillRocketPropelledChainsaw_Damage;
104  missile.damagedbycontents = true;
105  IL_PUSH(g_damagedbycontents, missile);
106  set_movetype(missile, MOVETYPE_FLY);
107 
108  missile.projectiledeathtype = thiswep.m_id;
109  missile.weaponentity_fld = weaponentity;
110  setsize (missile, '-3 -3 -3', '3 3 3'); // give it some size so it can be shot
111 
112  setorigin(missile, w_shotorg - v_forward * 3); // move it back so it hits the wall at the right point
113  W_SetupProjVelocity_Basic(missile, WEP_CVAR_PRI(okrpc, speed), 0);
114 
115  settouch(missile, W_OverkillRocketPropelledChainsaw_Touch);
116 
117  setthink(missile, W_OverkillRocketPropelledChainsaw_Think);
118  missile.cnt = time + WEP_CVAR_PRI(okrpc, lifetime);
119  missile.nextthink = time;
120  missile.flags = FL_PROJECTILE;
121  IL_PUSH(g_projectiles, missile);
122  IL_PUSH(g_bot_dodge, missile);
123 
124  CSQCProjectile(missile, true, PROJECTILE_RPC, false);
125 
126  missile.m_chainsaw_damage = 0;
127 
128  MUTATOR_CALLHOOK(EditProjectile, actor, missile);
129 }
130 
131 METHOD(OverkillRocketPropelledChainsaw, wr_aim, void(entity thiswep, entity actor, .entity weaponentity))
132 {
133  PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, weaponentity, WEP_CVAR_PRI(okrpc, speed), 0, WEP_CVAR_PRI(okrpc, lifetime), false);
134 }
135 
136 METHOD(OverkillRocketPropelledChainsaw, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
137 {
138  if ((WEP_CVAR_SEC(okrpc, refire_type) == 1) && (fire & 2) && (time >= actor.jump_interval))
139  {
140  // Secondary uses it's own refire timer if refire_type is 1.
141  actor.jump_interval = time + WEP_CVAR_SEC(okrpc, refire) * W_WeaponRateFactor(actor);
142  BLASTER_SECONDARY_ATTACK(okrpc, actor, weaponentity);
143  if ((actor.(weaponentity).wframe == WFRAME_IDLE) ||
144  (actor.(weaponentity).wframe == WFRAME_FIRE2))
145  {
146  // Set secondary fire animation.
147  actor.(weaponentity).wframe = WFRAME_FIRE2;
148  FOREACH_CLIENT(true, LAMBDA(
149  if (it == actor || (IS_SPEC(it) && it.enemy == actor))
150  {
151  wframe_send(it, actor.(weaponentity), WFRAME_FIRE2, autocvar_g_weaponratefactor, true);
152  }
153  ));
155  }
156  }
157  if (WEP_CVAR(okrpc, reload_ammo) && actor.(weaponentity).clip_load < WEP_CVAR_PRI(okrpc, ammo))
158  {
159  // Forced reload
160  thiswep.wr_reload(thiswep, actor, weaponentity);
161  return;
162  }
163  if (fire & 1) // Primary attack
164  {
165  if (!weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR_PRI(okrpc, refire)))
166  {
167  return;
168  }
169  W_OverkillRocketPropelledChainsaw_Attack(thiswep, actor, weaponentity);
170  weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_PRI(okrpc, animtime), w_ready);
171  return;
172  }
173  if ((fire & 2) && (WEP_CVAR_SEC(okrpc, refire_type) == 0)) // Secondary attack
174  {
175  if (!weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR_SEC(okrpc, refire)))
176  {
177  return;
178  }
179  BLASTER_SECONDARY_ATTACK(okrpc, actor, weaponentity);
180  weapon_thinkf(actor, weaponentity, WFRAME_FIRE2, WEP_CVAR_SEC(okrpc, animtime), w_ready);
181  }
182 }
183 
184 METHOD(OverkillRocketPropelledChainsaw, wr_checkammo1, bool(entity thiswep, entity actor, .entity weaponentity))
185 {
186  float ammo_amount = GetResource(actor, thiswep.ammo_type) >= WEP_CVAR_PRI(okrpc, ammo);
187  ammo_amount += actor.(weaponentity).(weapon_load[thiswep.m_id]) >= WEP_CVAR_PRI(okrpc, ammo);
188  return ammo_amount;
189 }
190 
191 METHOD(OverkillRocketPropelledChainsaw, wr_checkammo2, bool(entity thiswep, entity actor, .entity weaponentity))
192 {
193  float ammo_amount = GetResource(actor, thiswep.ammo_type) >= WEP_CVAR_SEC(okrpc, ammo);
194  ammo_amount += actor.(weaponentity).(weapon_load[thiswep.m_id]) >= WEP_CVAR_SEC(okrpc, ammo);
195  return ammo_amount;
196 }
197 
198 METHOD(OverkillRocketPropelledChainsaw, wr_reload, void(entity thiswep, entity actor, .entity weaponentity))
199 {
200  W_Reload(actor, weaponentity, WEP_CVAR_PRI(okrpc, ammo), SND_RELOAD);
201 }
202 
203 METHOD(OverkillRocketPropelledChainsaw, wr_suicidemessage, Notification(entity thiswep))
204 {
206  return WEAPON_OVERKILL_RPC_SUICIDE_SPLASH;
207  else
208  return WEAPON_OVERKILL_RPC_SUICIDE_DIRECT;
209 }
210 
212 {
214  return WEAPON_BLASTER_MURDER;
215  else if((w_deathtype & HITTYPE_BOUNCE) || (w_deathtype & HITTYPE_SPLASH))
216  return WEAPON_OVERKILL_RPC_MURDER_SPLASH;
217  else
218  return WEAPON_OVERKILL_RPC_MURDER_DIRECT;
219 }
220 
221 #endif
222 
223 #ifdef CSQC
224 
225 METHOD(OverkillRocketPropelledChainsaw, wr_impacteffect, void(entity thiswep, entity actor))
226 {
227  vector org2;
228  org2 = w_org + w_backoff * 12;
229  pointparticles(EFFECT_ROCKET_EXPLODE, org2, '0 0 0', 1);
230  if(!w_issilent)
231  sound(actor, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
232 }
233 
234 #endif
const int HITTYPE_SPLASH
automatically set by RadiusDamage
Definition: all.qh:27
#define WEP_CVAR_PRI(wepname, name)
Definition: all.qh:300
#define W_SetupProjVelocity_Basic(ent, pspeed, pspread)
Definition: tracing.qh:48
bool bot_aim(entity this,.entity weaponentity, float shotspeed, float shotspeedupward, float maxshottime, float applygravity)
#define WEP_CVAR_SEC(wepname, name)
Definition: all.qh:301
float weapon_load[REGISTRY_MAX(Weapons)]
Definition: weaponsystem.qh:29
const int HITTYPE_BOUNCE
Definition: all.qh:28
float speed
Definition: subs.qh:41
vector w_shotorg
Definition: tracing.qh:18
#define PROJECTILE_MAKETRIGGER(e)
Definition: common.qh:29
bool SetResourceExplicit(entity e, Resource res_type, float amount)
Sets the resource amount of an entity without calling any hooks.
Definition: cl_resources.qc:15
#define W_SetupShot_ProjectileSize(ent, wepent, mi, ma, antilag, recoil, snd, chan, maxdamage, deathtype)
Definition: tracing.qh:29
float W_CheckProjectileDamage(entity inflictor, entity projowner, int deathtype, float exception)
Definition: common.qc:49
float damageforcescale
Definition: damage.qh:137
IntrusiveList g_damagedbycontents
Definition: damage.qh:155
entity() spawn
const float MOVE_NORMAL
Definition: csprogsdefs.qc:252
#define FOREACH_CLIENT(cond, body)
Definition: utils.qh:49
void w_ready(Weapon thiswep, entity actor,.entity weaponentity, int fire)
float radius
Definition: impulse.qh:11
vector maxs
Definition: csprogsdefs.qc:113
#define WEP_CVAR(wepname, name)
Definition: all.qh:299
#define LAMBDA(...)
Definition: misc.qh:37
vector w_shotdir
Definition: tracing.qh:19
entity weaponentity_fld
Definition: weaponsystem.qh:27
origin
Definition: ent_cs.qc:114
#define METHOD(cname, name, prototype)
Definition: oo.qh:257
void CSQCProjectile(entity e, float clientanimate, int type, float docull)
#define DEATH_WEAPONOF(t)
Definition: all.qh:41
IntrusiveList g_bot_dodge
Definition: api.qh:150
entity trace_ent
Definition: csprogsdefs.qc:40
void TakeResource(entity receiver, Resource res_type, float amount)
Takes an entity some resource.
Definition: cl_resources.qc:31
RES_HEALTH
Definition: ent_cs.qc:126
float ammo
Definition: sv_turrets.qh:44
#define IS_SPEC(v)
Definition: utils.qh:10
float sys_frametime
Definition: common.qh:57
float lifetime
Definition: powerups.qc:23
vector mins
Definition: csprogsdefs.qc:113
float cnt
Definition: powerups.qc:24
ERASEABLE entity IL_PUSH(IntrusiveList this, entity it)
Push to tail.
void UpdateCSQCProjectile(entity e)
const int CH_WEAPON_A
Definition: sound.qh:7
bool weapon_prepareattack(Weapon thiswep, entity actor,.entity weaponentity, bool secondary, float attacktime)
void animdecide_setaction(entity e, float action, float restart)
Definition: animdecide.qc:338
void W_PrepareExplosionByDamage(entity this, entity attacker, void(entity this) explode)
Definition: common.qc:91
#define pointparticles
Definition: csprogsdefs.qh:13
#define NULL
Definition: post.qh:17
const float VOL_BASE
Definition: sound.qh:36
#define PHYS_INPUT_BUTTON_ATCK(s)
Definition: player.qh:146
float takedamage
Definition: progsdefs.qc:147
const int ANIMACTION_SHOOT
Definition: animdecide.qh:145
void Damage(entity targ, entity inflictor, entity attacker, float damage, int deathtype,.entity weaponentity, vector hitloc, vector force)
Definition: damage.qc:583
const int HITTYPE_SECONDARY
Definition: all.qh:25
const float ATTEN_NORM
Definition: sound.qh:30
float nextthink
Definition: csprogsdefs.qc:121
const int CH_SHOTS
Definition: sound.qh:14
float w_deathtype
Definition: damage.qh:97
vector(float skel, float bonenum) _skel_get_boneabs_hidden
IntrusiveList g_projectiles
Definition: common.qh:46
float GetResource(entity e, Resource res_type)
Returns the current amount of resource the given entity has.
Definition: cl_resources.qc:10
void accuracy_add(entity this, Weapon w, float fired, float hit)
Definition: accuracy.qc:83
entity Notification
always last
Definition: all.qh:82
float health
Definition: progsdefs.qc:137
void weapon_thinkf(entity actor,.entity weaponentity, WFRAME fr, float t, void(Weapon thiswep, entity actor,.entity weaponentity, int fire) func)
float RadiusDamage(entity inflictor, entity attacker, float coredamage, float edgedamage, float rad, entity cantbe, entity mustbe, float forceintensity, int deathtype,.entity weaponentity, entity directhitentity)
Definition: damage.qc:1057
bool accuracy_isgooddamage(entity attacker, entity targ)
Definition: accuracy.qc:112
entity realowner
Definition: common.qh:25
#define MUTATOR_CALLHOOK(id,...)
Definition: base.qh:140
setorigin(ent, v)
#define setthink(e, f)
const int PROJECTILE_RPC
Definition: projectiles.qh:43
float WarpZone_Projectile_Touch(entity this, entity toucher)
Definition: server.qc:382
void W_DecreaseAmmo(Weapon wep, entity actor, float ammo_use,.entity weaponentity)
#define sound(e, c, s, v, a)
Definition: sound.qh:52
fields which are explicitly/manually set are marked with "M", fields set automatically are marked wit...
Definition: weapon.qh:41
float time
Definition: csprogsdefs.qc:16
vector velocity
Definition: csprogsdefs.qc:103
int m_id
Definition: weapon.qh:42
float W_WeaponRateFactor(entity this)
Definition: weaponsystem.qc:33
float DAMAGE_NO
Definition: progsdefs.qc:282
void set_movetype(entity this, int mt)
float MOVETYPE_FLY
Definition: progsdefs.qc:251
#define IS_PLAYER(v)
Definition: utils.qh:9
var void func_null()
vector v_forward
Definition: csprogsdefs.qc:31
float DAMAGE_YES
Definition: progsdefs.qc:283
void W_Reload(entity actor,.entity weaponentity, float sent_ammo_min, Sound sent_sound)
int projectiledeathtype
Definition: common.qh:20