12 if(this.
realowner.(weaponentity).lastrocket ==
this)
31 vector force_xyzscale =
'1 1 1';
32 force_xyzscale.x =
WEP_CVAR(WEP_DEVASTATOR, force_xyscale);
33 force_xyzscale.y =
WEP_CVAR(WEP_DEVASTATOR, force_xyscale);
41 WEP_CVAR(WEP_DEVASTATOR, edgedamage),
53 Weapon thiswep = WEP_DEVASTATOR;
55 if(this.
realowner.(weaponentity).m_weapon == thiswep)
80 bool handled_as_rocketjump =
false;
82 bool allow_rocketjump =
WEP_CVAR(WEP_DEVASTATOR, remote_jump);
84 allow_rocketjump =
M_ARGV(0,
bool);
86 if(allow_rocketjump &&
WEP_CVAR(WEP_DEVASTATOR, remote_jump_radius))
90 WEP_CVAR(WEP_DEVASTATOR, remote_jump_radius),
96 if(head.takedamage && (head ==
this.realowner))
98 if(
vdist(this.
origin - head.WarpZone_findradius_nearest, <=,
WEP_CVAR(WEP_DEVASTATOR, remote_jump_radius)))
101 handled_as_rocketjump =
true;
104 if(
WEP_CVAR(WEP_DEVASTATOR, remote_jump_velocity_z_add))
106 head.velocity_x *= 0.9;
107 head.velocity_y *= 0.9;
108 head.velocity_z =
bound(
109 WEP_CVAR(WEP_DEVASTATOR, remote_jump_velocity_z_min),
110 head.velocity.z +
WEP_CVAR(WEP_DEVASTATOR, remote_jump_velocity_z_add),
111 WEP_CVAR(WEP_DEVASTATOR, remote_jump_velocity_z_max)
119 WEP_CVAR(WEP_DEVASTATOR, remote_jump_damage),
120 WEP_CVAR(WEP_DEVASTATOR, remote_jump_damage),
121 WEP_CVAR(WEP_DEVASTATOR, remote_jump_radius),
124 (
WEP_CVAR(WEP_DEVASTATOR, remote_jump_force) ?
WEP_CVAR(WEP_DEVASTATOR, remote_jump_force) : 0),
139 WEP_CVAR(WEP_DEVASTATOR, remote_damage),
140 WEP_CVAR(WEP_DEVASTATOR, remote_edgedamage),
141 WEP_CVAR(WEP_DEVASTATOR, remote_radius),
142 (handled_as_rocketjump ? head :
NULL),
144 WEP_CVAR(WEP_DEVASTATOR, remote_force),
150 Weapon thiswep = WEP_DEVASTATOR;
151 if(this.
realowner.(weaponentity).m_weapon == thiswep)
167 if(this.
realowner.(weaponentity).lastrocket)
181 if(thisdir * goaldir > maxturn_cos)
183 if(thisdir * goaldir < -0.9998)
195 f = thisdir * goaldir;
198 m2 = maxturn_cos * maxturn_cos;
200 return normalize(thisdir + goaldir * v.y);
214 vector desireddir, olddir, newdir, desiredorigin, goal;
232 if(this.
realowner.(weaponentity).m_weapon == WEP_DEVASTATOR)
234 if(
this == this.
realowner.(weaponentity).lastrocket)
235 if(!this.
realowner.(weaponentity).rl_release)
237 if(
WEP_CVAR(WEP_DEVASTATOR, guiderate))
241 f =
WEP_CVAR(WEP_DEVASTATOR, guideratedelay);
262 goal = desiredorigin + ((this.
origin - desiredorigin) * desireddir +
WEP_CVAR(WEP_DEVASTATOR, guidegoal)) * desireddir;
316 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);
320 missile.weaponentity_fld = weaponentity;
321 missile.owner = missile.realowner = actor;
323 if(
WEP_CVAR(WEP_DEVASTATOR, detonatedelay) >= 0)
324 missile.spawnshieldtime =
time +
WEP_CVAR(WEP_DEVASTATOR, detonatedelay);
326 missile.spawnshieldtime = -1;
327 missile.pushltime =
time +
WEP_CVAR(WEP_DEVASTATOR, guidedelay);
328 missile.classname =
"rocket";
329 missile.bot_dodge =
true;
330 missile.bot_dodgerating =
WEP_CVAR(WEP_DEVASTATOR, damage) * 2;
336 missile.damagedbycontents =
true;
341 missile.projectiledeathtype = thiswep.
m_id;
342 setsize(missile,
'-3 -3 -3',
'3 3 3');
350 missile.nextthink =
time;
352 missile.rl_detonate_later = (fire & 2);
363 if (
time >= missile.nextthink)
371 if (!
WEP_CVAR(WEP_DEVASTATOR, guidestop) && !actor.(weaponentity).rl_release)
373 int fired_rockets = 0;
387 if (
WEP_CVAR(WEP_DEVASTATOR, guiderate) > 0)
388 spd *=
sqrt(
WEP_CVAR(WEP_DEVASTATOR, guiderate)) * (20 / 9.489);
390 bool shot_accurate = (
WEP_CVAR(WEP_DEVASTATOR, guiderate) < 50);
392 float pred_time =
bound(0.02, 0.02 + (8 -
skill) * 0.01, 0.1);
396 float selfdamage = 0, teamdamage = 0, enemydamage = 0;
397 float pred_selfdamage = 0, pred_teamdamage = 0, pred_enemydamage = 0;
398 float edgedamage =
WEP_CVAR(WEP_DEVASTATOR, edgedamage);
399 float coredamage =
WEP_CVAR(WEP_DEVASTATOR, damage);
404 IL_EACH(g_bot_targets, it.bot_attack,
407 vector target_pos = it.origin + (it.maxs - it.mins) * 0.5;
409 float dist = vlen(target_pos - rocket.origin);
411 if (dist <= edgeradius)
413 float f = (edgeradius > 0) ? max(0, 1 - (dist / edgeradius)) : 1;
414 dmg = coredamage * f + edgedamage * (1 - f);
417 float pred_dist = vlen(target_pos + it.velocity * pred_time - (rocket.origin + rocket.velocity * pred_time));
419 if (pred_dist <= edgeradius)
421 float f = (edgeradius > 0) ? max(0, 1 - (pred_dist / edgeradius)) : 1;
422 pred_dmg = coredamage * f + edgedamage * (1 - f);
428 if(StatusEffects_active(STATUSEFFECT_Strength, it))
429 dmg *= autocvar_g_balance_powerup_strength_damage;
430 if(StatusEffects_active(STATUSEFFECT_Shield, it))
431 dmg *= autocvar_g_balance_powerup_invincible_takedamage;
434 pred_selfdamage += pred_dmg;
436 else if(SAME_TEAM(it, actor))
438 if(StatusEffects_active(STATUSEFFECT_Shield, it))
439 dmg *= autocvar_g_balance_powerup_invincible_takedamage;
442 pred_teamdamage += pred_dmg;
444 else if(bot_shouldattack(actor, it))
446 if(StatusEffects_active(STATUSEFFECT_Shield, it))
447 dmg *= autocvar_g_balance_powerup_invincible_takedamage;
450 pred_enemydamage += pred_dmg;
466 float good_damage = enemydamage;
467 float pred_good_damage = pred_enemydamage;
468 float bad_damage = selfdamage + teamdamage;
469 float pred_bad_damage = pred_selfdamage + pred_teamdamage;
473 if(good_damage > coredamage * 0.1 && good_damage > bad_damage * 1.5
474 && (pred_good_damage < good_damage + 2 || pred_good_damage < pred_bad_damage * 1.5))
488 if(
WEP_CVAR(WEP_DEVASTATOR, reload_ammo) && actor.(weaponentity).clip_load <
WEP_CVAR(WEP_DEVASTATOR,
ammo)) {
489 thiswep.wr_reload(thiswep, actor, weaponentity);
493 if(actor.(weaponentity).rl_release ||
WEP_CVAR(WEP_DEVASTATOR, guidestop))
505 if(actor.(weaponentity).m_switchweapon == thiswep)
507 bool rockfound =
false;
510 if(!it.rl_detonate_later)
512 it.rl_detonate_later = true;
534 if(
WEP_CVAR(WEP_DEVASTATOR, reload_ammo))
545 if(actor.rl_release == 0)
554 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"));
586 return WEAPON_DEVASTATOR_SUICIDE;
592 return WEAPON_DEVASTATOR_MURDER_SPLASH;
594 return WEAPON_DEVASTATOR_MURDER_DIRECT;
618 PAR(_(
"The %s launches a remote controlled rocket, dealing significant damage when it explodes on impact. "
619 "If the primary fire is held, the rocket can be guided by the user's aim, allowing steering it towards enemies."),
COLORED_NAME(
this));
620 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."));
621 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));
622 PAR(_(
"Due to its high damage output, the %s is one of the most commonly used weapons. "
623 "It can be used in almost any scenario, working best in medium range combat. "
624 "In close range combat, the large splash radius often results in rockets damaging both you and your enemy."),
COLORED_NAME(
this));
625 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, "
626 "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(id,...)
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.
bool SetResourceExplicit(entity e, Resource res_type, float amount)
Sets the resource amount of an entity without calling any hooks.
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 csqcprojectile_clientanimate
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, float inflictorselfdamage, float forceintensity, vector forcexyzscale, int deathtype,.entity weaponentity, entity directhitentity)
IntrusiveList g_damagedbycontents
float autocvar_g_balance_selfdamagepercent
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)
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)
vector W_Devastator_SteerTo(vector thisdir, vector goaldir, float maxturn_cos)
void W_Devastator_Think(entity this)
#define pointparticles(effect, org, vel, howmany)
void Send_Effect(entity eff, vector eff_loc, vector eff_vel, int eff_cnt)
ERASEABLE entity IL_PUSH(IntrusiveList this, entity it)
Push to tail.
#define IL_EACH(this, cond, body)
vector WarpZone_RefSys_TransformVelocity(entity from, entity to, vector vel)
entity WarpZone_FindRadius(vector org, float rad, bool needlineofsight)
entity WarpZone_RefSys_SpawnSameRefSys(entity me)
vector WarpZone_RefSys_TransformOrigin(entity from, entity to, vector org)
ERASEABLE vector solve_quadratic(float a, float b, float c)
ax^2 + bx + c = 0
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_PrepareExplosionByDamage(entity this, entity attacker, void(entity this) explode)
bool W_DualWielding(entity player)
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)]