12 if (this.
realowner.(weaponentity).lastrocket ==
this)
29 vector force_xyzscale =
'1 1 1';
30 force_xyzscale.x =
WEP_CVAR(WEP_DEVASTATOR, force_xyscale);
31 force_xyzscale.y =
WEP_CVAR(WEP_DEVASTATOR, force_xyscale);
35 WEP_CVAR(WEP_DEVASTATOR, edgedamage),
47 Weapon thiswep = WEP_DEVASTATOR;
49 if (this.
realowner.(weaponentity).m_weapon == thiswep
76 bool handled_as_rocketjump =
false;
78 bool allow_rocketjump =
WEP_CVAR(WEP_DEVASTATOR, remote_jump);
80 allow_rocketjump =
M_ARGV(0,
bool);
82 if (allow_rocketjump &&
WEP_CVAR(WEP_DEVASTATOR, remote_jump_radius))
89 handled_as_rocketjump =
true;
92 if (
WEP_CVAR(WEP_DEVASTATOR, remote_jump_velocity_z_add))
94 head.velocity.x *= 0.9;
95 head.velocity.y *= 0.9;
96 head.velocity.z =
bound(
97 WEP_CVAR(WEP_DEVASTATOR, remote_jump_velocity_z_min),
98 head.velocity.z +
WEP_CVAR(WEP_DEVASTATOR, remote_jump_velocity_z_add),
99 WEP_CVAR(WEP_DEVASTATOR, remote_jump_velocity_z_max)
105 WEP_CVAR(WEP_DEVASTATOR, remote_jump_damage),
106 WEP_CVAR(WEP_DEVASTATOR, remote_jump_damage),
107 WEP_CVAR(WEP_DEVASTATOR, remote_jump_radius),
110 (
WEP_CVAR(WEP_DEVASTATOR, remote_jump_force) ?
WEP_CVAR(WEP_DEVASTATOR, remote_jump_force) : 0),
119 WEP_CVAR(WEP_DEVASTATOR, remote_damage),
120 WEP_CVAR(WEP_DEVASTATOR, remote_edgedamage),
121 WEP_CVAR(WEP_DEVASTATOR, remote_radius),
122 (handled_as_rocketjump ? head :
NULL),
124 WEP_CVAR(WEP_DEVASTATOR, remote_force),
130 Weapon thiswep = WEP_DEVASTATOR;
131 if (this.
realowner.(weaponentity).m_weapon == thiswep
145 || !this.
realowner.(weaponentity).lastrocket)
178 if (this.
realowner.(weaponentity).m_weapon == WEP_DEVASTATOR)
180 if (
this == this.
realowner.(weaponentity).lastrocket
181 && !
this.realowner.(weaponentity).rl_release
183 &&
WEP_CVAR(WEP_DEVASTATOR, guiderate)
187 WEP_CVAR(WEP_DEVASTATOR, guiderate),
188 WEP_CVAR(WEP_DEVASTATOR, guideratedelay),
189 WEP_CVAR(WEP_DEVASTATOR, guidegoal),
190 WEP_CVAR(WEP_DEVASTATOR, guidedelay),
191 EFFECT_ROCKET_GUIDE, SND_DEVASTATOR_MODE,
VOL_BASE);
197 if (
WEP_CVAR(WEP_DEVASTATOR, speedaccel) ||
WEP_CVAR(WEP_DEVASTATOR, guiderate))
231 W_SetupShot_ProjectileSize(actor, weaponentity,
'-3 -3 -3',
'3 3 3',
false, 5, SND_DEVASTATOR_FIRE,
CH_WEAPON_A,
WEP_CVAR(WEP_DEVASTATOR, damage), thiswep.
m_id);
234 entity missile =
new(rocket);
236 missile.weaponentity_fld = weaponentity;
237 missile.owner = missile.realowner = actor;
239 if (
WEP_CVAR(WEP_DEVASTATOR, detonatedelay) >= 0)
240 missile.spawnshieldtime =
time +
WEP_CVAR(WEP_DEVASTATOR, detonatedelay);
242 missile.spawnshieldtime = -1;
243 missile.pushltime =
time +
WEP_CVAR(WEP_DEVASTATOR, guidedelay);
244 missile.bot_dodge =
true;
245 missile.bot_dodgerating =
WEP_CVAR(WEP_DEVASTATOR, damage) * 2;
251 missile.damagedbycontents =
true;
256 missile.projectiledeathtype = thiswep.
m_id;
257 setsize(missile,
'-3 -3 -3',
'3 3 3');
265 missile.nextthink =
time;
267 missile.rl_detonate_later =
boolean(fire & 2);
280 if (
time >= missile.nextthink)
286 if (!
WEP_CVAR(WEP_DEVASTATOR, guidestop) && !actor.(weaponentity).rl_release)
288 int fired_rockets = 0;
299 if (
WEP_CVAR(WEP_DEVASTATOR, guiderate) > 0)
300 spd *=
sqrt(
WEP_CVAR(WEP_DEVASTATOR, guiderate)) * (20 / 9.489);
302 bool shot_accurate = (
WEP_CVAR(WEP_DEVASTATOR, guiderate) < 50);
304 float pred_time =
bound(0.02, 0.02 + (8 -
skill) * 0.01, 0.1);
308 float selfdamage = 0, teamdamage = 0, enemydamage = 0;
309 float pred_selfdamage = 0, pred_teamdamage = 0, pred_enemydamage = 0;
310 float edgedamage =
WEP_CVAR(WEP_DEVASTATOR, edgedamage);
311 float coredamage =
WEP_CVAR(WEP_DEVASTATOR, damage);
316 IL_EACH(g_bot_targets, it.bot_attack,
319 vector target_pos = it.origin + (it.maxs - it.mins) * 0.5;
322 float dist = vlen(target_pos - rocket.origin);
324 if (dist <= edgeradius)
326 f = (edgeradius > 0) ? max(0, 1 - (dist / edgeradius)) : 1;
327 dmg = coredamage * f + edgedamage * (1 - f);
330 float pred_dist = vlen(target_pos + it.velocity * pred_time - (rocket.origin + rocket.velocity * pred_time));
332 if (pred_dist <= edgeradius)
334 f = (edgeradius > 0) ? max(0, 1 - (pred_dist / edgeradius)) : 1;
335 pred_dmg = coredamage * f + edgedamage * (1 - f);
341 if (StatusEffects_active(STATUSEFFECT_Strength, it))
342 dmg *= autocvar_g_balance_powerup_strength_damage;
343 if (StatusEffects_active(STATUSEFFECT_Shield, it))
344 dmg *= autocvar_g_balance_powerup_invincible_takedamage;
347 pred_selfdamage += pred_dmg;
349 else if (SAME_TEAM(it, actor))
351 if (StatusEffects_active(STATUSEFFECT_Shield, it))
352 dmg *= autocvar_g_balance_powerup_invincible_takedamage;
355 pred_teamdamage += pred_dmg;
357 else if (bot_shouldattack(actor, it))
359 if (StatusEffects_active(STATUSEFFECT_Shield, it))
360 dmg *= autocvar_g_balance_powerup_invincible_takedamage;
363 pred_enemydamage += pred_dmg;
379 float good_damage = enemydamage;
380 float pred_good_damage = pred_enemydamage;
381 float bad_damage = selfdamage + teamdamage;
382 float pred_bad_damage = pred_selfdamage + pred_teamdamage;
386 if (good_damage > coredamage * 0.1 && good_damage > bad_damage * 1.5
387 && (pred_good_damage < good_damage + 2 || pred_good_damage < pred_bad_damage * 1.5))
400 if (
WEP_CVAR(WEP_DEVASTATOR, reload_ammo) && actor.(weaponentity).clip_load <
WEP_CVAR(WEP_DEVASTATOR,
ammo))
402 thiswep.wr_reload(thiswep, actor, weaponentity);
408 if ((actor.(weaponentity).rl_release ||
WEP_CVAR(WEP_DEVASTATOR, guidestop))
420 && actor.(weaponentity).m_switchweapon == thiswep)
422 bool rockfound =
false;
425 if (!it.rl_detonate_later)
427 it.rl_detonate_later = true;
448 if (
WEP_CVAR(WEP_DEVASTATOR, reload_ammo))
459 if (!actor.rl_release)
468 LOG_INFOF(
"W_Devastator(WR_CHECKAMMO1): %d, %.2f, %d: %s", actor.rl_release,
GetResource(actor, thiswep.ammo_type),
WEP_CVAR(WEP_DEVASTATOR,
ammo), (ammo_amount ?
"TRUE" :
"FALSE"));
500 return WEAPON_DEVASTATOR_SUICIDE;
506 return WEAPON_DEVASTATOR_MURDER_SPLASH;
508 return WEAPON_DEVASTATOR_MURDER_DIRECT;
532 PAR(_(
"The %s launches a remote controlled rocket, dealing significant damage when it explodes on impact. "
533 "If the primary fire is held, the rocket can be guided by the user's aim, allowing steering it towards enemies."),
COLORED_NAME(
this));
534 PAR(_(
"The secondary fire can be used to immediately detonate rockets, allowing dealing damage to enemies even if the rocket barely missed colliding with them."));
535 PAR(_(
"It consumes a bunch of %s ammo for each rocket, which can end up being depleted quickly, so often players alternate with another weapon like %s."),
COLORED_NAME(ITEM_Rockets),
COLORED_NAME(WEP_VORTEX));
536 PAR(_(
"Due to its high damage output, the %s is one of the most commonly used weapons. "
537 "It can be used in almost any scenario, working best in medium range combat. "
538 "In close range combat, the large splash radius often results in rockets damaging both you and your enemy."),
COLORED_NAME(
this));
539 PAR(_(
"Due to the ability to remotely detonate rockets, a common usage is \"rocket flying,\" where you fire a rocket and immediately detonate it to boost yourself while mid-air, "
540 "much more effective with the %s mutator enabled."),
COLORED_NAME(MUTATOR_rocketflying));
bool bot_aim(entity this,.entity weaponentity, float shotspeed, float shotspeedupward, float maxshottime, float applygravity, bool shot_accurate)
IntrusiveList g_bot_dodge
#define MUTATOR_CALLHOOK(name,...)
#define M_ARGV(idx, type)
var entity(vector mins, vector maxs,.entity tofield) findbox_tofield_OrFallback
float GetResource(entity e, Resource res_type)
Returns the current amount of resource the given entity has.
void TakeResource(entity receiver, Resource res_type, float amount)
Takes an entity some resource.
fields which are explicitly/manually set are marked with "M", fields set automatically are marked wit...
Resource ammo_type
M: ammotype : main ammo type.
#define COLORED_NAME(this)
const int IT_UNLIMITED_AMMO
bool IsFlying(entity this)
#define PHYS_INPUT_BUTTON_ATCK(s)
#define PHYS_INPUT_BUTTON_ATCK2(s)
void UpdateCSQCProjectile(entity e)
void CSQCProjectile(entity e, float clientanimate, int type, float docull)
float RadiusDamage(entity inflictor, entity attacker, float coredamage, float edgedamage, float rad, entity cantbe, entity mustbe, float forceintensity, int deathtype,.entity weaponentity, entity directhitentity)
float RadiusDamageForSource(entity inflictor, vector inflictororigin, vector inflictorvelocity, entity attacker, float coredamage, float edgedamage, float rad, entity cantbe, entity mustbe, bool inflictorselfdamage, float forceintensity, vector forcexyzscale, int deathtype,.entity weaponentity, entity directhitentity)
Returns total damage applied to creatures.
IntrusiveList g_damagedbycontents
float autocvar_g_balance_selfdamagepercent
const int HITTYPE_BOUNCE
set manually after projectile has bounced
const int HITTYPE_SPLASH
automatically set by RadiusDamage
void W_Devastator_Explode(entity this, entity directhitentity)
void W_Devastator_Explode_think(entity this)
void W_Devastator_Damage(entity this, entity inflictor, entity attacker, float damage, int deathtype,.entity weaponentity, vector hitloc, vector force)
void W_Devastator_DoRemoteExplode(entity this,.entity weaponentity)
bool W_Devastator_DoRemoteExplode_cond(entity e)
void W_Devastator_Attack(Weapon thiswep, entity actor,.entity weaponentity, int fire)
void W_Devastator_Touch(entity this, entity toucher)
void W_Devastator_RemoteExplode(entity this,.entity weaponentity)
void W_Devastator_Unregister(entity this)
void W_Devastator_Think(entity this)
#define pointparticles(effect, org, vel, howmany)
SetResourceExplicit(ent, RES_ARMOR, ReadByte() *DEC_FACTOR)) ENTCS_PROP(NAME
ERASEABLE entity IL_PUSH(IntrusiveList this, entity it)
Push to tail.
#define IL_EACH(this, cond, body)
entity WarpZone_SearchInRadius(vector org, float rad, float nomonsters, WarpZone_FindRadius_cond_callback_t cb)
Modified findradius aware of warpzones, that only includes entities that meet the "cb" criteria.
vector WarpZone_RefSys_TransformOrigin(entity from, entity to, vector org)
Transform origin org in from's reference into to's reference.
void WarpZone_RefSys_Copy(entity me, entity from)
Copies the warpzone reference of from onto me.
noref entity WarpZone_SearchInRadius_otherent
Free to use in the callback.
void set_movetype(entity this, int mt)
void Send_Notification(NOTIF broadcast, entity client, MSG net_type, Notification net_name,...count)
entity Notification
always last
#define METHOD(cname, name, prototype)
const int PROJECTILE_ROCKET
float health
Legacy fields for the resources. To be removed.
#define w_getbestweapon(ent, wepent)
float W_CheckProjectileDamage(entity inflictor, entity projowner, int deathtype, float exception)
void W_GuideProjectile(entity this,.entity weaponentity, float guide_start_time, float guide_rate, float guide_rate_delay, float guide_goal, float guide_delay, entity eff, entity snd, float vol)
Guides a projectile towards the crosshair (v_forward).
void W_PrepareExplosionByDamage(entity this, entity attacker, void(entity this) explode)
IntrusiveList g_projectiles
#define PROJECTILE_MAKETRIGGER(e)
float WarpZone_Projectile_Touch(entity this, entity toucher)
#define sound(e, c, s, v, a)
bool StatusEffects_active(StatusEffect this, entity actor)
float autocvar_g_balance_powerup_strength_damage
#define PAR(...)
Adds an individually translatable paragraph to PAGE_TEXT without having to deal with strcat and sprin...
#define W_SetupShot_ProjectileSize(ent, wepent, mi, ma, antilag, recoil, snd, chan, maxdamage, deathtype)
#define W_SetupProjVelocity_Basic(ent, pspeed, pspread)
#define vdist(v, cmp, f)
Vector distance comparison, avoids sqrt().
ERASEABLE vector NearestPointOnBox(entity box, vector org)
string W_Guide_Keybinds(Weapon wep)
void W_MuzzleFlash(Weapon thiswep, entity actor,.entity weaponentity, vector shotorg, vector shotdir)
string W_Guide_DPS_onlyOne_unnamed(string name)
#define WEP_CVAR(wep, name)
const int MAX_WEAPONSLOTS
entity weaponentities[MAX_WEAPONSLOTS]
void W_DecreaseAmmo(Weapon wep, entity actor, float ammo_use,.entity weaponentity)
float W_WeaponSpeedFactor(entity this)
void W_Reload(entity actor,.entity weaponentity, float sent_ammo_min, Sound sent_sound)
void weapon_thinkf(entity actor,.entity weaponentity, WFRAME fr, float t, void(Weapon thiswep, entity actor,.entity weaponentity, int fire) func)
bool weapon_prepareattack(Weapon thiswep, entity actor,.entity weaponentity, bool secondary, float attacktime)
void w_ready(Weapon thiswep, entity actor,.entity weaponentity, int fire)
#define ATTACK_FINISHED(ent, w)
float weapon_load[REGISTRY_MAX(Weapons)]