7 void W_Devastator_Unregister(
entity this)
12 if(this.
realowner.(weaponentity).lastrocket ==
this)
17 void W_Devastator_Explode(
entity this,
entity directhitentity)
19 W_Devastator_Unregister(
this);
26 Send_Notification(NOTIF_ONE, this.
realowner, MSG_ANNCE, ANNCE_ACHIEVEMENT_AIRSHOT);
45 Weapon thiswep = WEP_DEVASTATOR;
47 if(this.
realowner.(weaponentity).m_weapon == thiswep)
50 if(!(this.
realowner.items & IT_UNLIMITED_AMMO))
60 void W_Devastator_Explode_think(
entity this)
62 W_Devastator_Explode(
this,
NULL);
65 void W_Devastator_DoRemoteExplode(
entity this, .
entity weaponentity)
67 W_Devastator_Unregister(
this);
72 bool handled_as_rocketjump =
false;
74 bool allow_rocketjump =
WEP_CVAR(devastator, remote_jump);
76 allow_rocketjump =
M_ARGV(0,
bool);
78 if(allow_rocketjump &&
WEP_CVAR(devastator, remote_jump_radius))
82 WEP_CVAR(devastator, remote_jump_radius),
88 if(head.takedamage && (head ==
this.realowner))
90 if(
vdist(this.
origin - head.WarpZone_findradius_nearest, <=,
WEP_CVAR(devastator, remote_jump_radius)))
93 handled_as_rocketjump =
true;
96 if(
WEP_CVAR(devastator, remote_jump_velocity_z_add))
98 head.velocity_x *= 0.9;
99 head.velocity_y *= 0.9;
100 head.velocity_z =
bound(
101 WEP_CVAR(devastator, remote_jump_velocity_z_min),
102 head.velocity.z +
WEP_CVAR(devastator, remote_jump_velocity_z_add),
103 WEP_CVAR(devastator, remote_jump_velocity_z_max)
111 WEP_CVAR(devastator, remote_jump_damage),
112 WEP_CVAR(devastator, remote_jump_damage),
113 WEP_CVAR(devastator, remote_jump_radius),
116 (
WEP_CVAR(devastator, remote_jump_force) ?
WEP_CVAR(devastator, remote_jump_force) : 0),
131 WEP_CVAR(devastator, remote_damage),
132 WEP_CVAR(devastator, remote_edgedamage),
133 WEP_CVAR(devastator, remote_radius),
134 (handled_as_rocketjump ? head :
NULL),
142 Weapon thiswep = WEP_DEVASTATOR;
143 if(this.
realowner.(weaponentity).m_weapon == thiswep)
146 if(!(this.
realowner.items & IT_UNLIMITED_AMMO))
156 void W_Devastator_RemoteExplode(
entity this, .
entity weaponentity)
159 if(this.
realowner.(weaponentity).lastrocket)
166 W_Devastator_DoRemoteExplode(
this, weaponentity);
173 if(thisdir * goaldir > maxturn_cos)
175 if(thisdir * goaldir < -0.9998)
187 f = thisdir * goaldir;
190 m2 = maxturn_cos * maxturn_cos;
192 return normalize(thisdir + goaldir * v.y);
204 void W_Devastator_Think(
entity this)
206 vector desireddir, olddir, newdir, desiredorigin, goal;
212 W_Devastator_Explode(
this, NULL);
224 if(this.
realowner.(weaponentity).m_weapon == WEP_DEVASTATOR)
226 if(
this == this.
realowner.(weaponentity).lastrocket)
227 if(!this.
realowner.(weaponentity).rl_release)
233 f =
WEP_CVAR(devastator, guideratedelay);
240 vector vecs = ((md.x > 0) ? md :
'0 0 0');
256 goal = desiredorigin + ((this.
origin - desiredorigin) * desireddir +
WEP_CVAR(devastator, guidegoal)) * desireddir;
271 if(this.rl_detonate_later)
272 W_Devastator_RemoteExplode(
this, weaponentity);
284 W_Devastator_Unregister(
this);
287 W_Devastator_Unregister(
this);
288 W_Devastator_Explode(
this, toucher);
306 void W_Devastator_Attack(
Weapon thiswep,
entity actor, .
entity weaponentity,
int fire)
310 W_SetupShot_ProjectileSize(actor, weaponentity,
'-3 -3 -3',
'3 3 3',
false, 5, SND_ROCKET_FIRE,
CH_WEAPON_A,
WEP_CVAR(devastator, damage), thiswep.
m_id);
314 missile.weaponentity_fld = weaponentity;
315 missile.owner = missile.realowner = actor;
316 actor.(weaponentity).lastrocket = missile;
317 if(
WEP_CVAR(devastator, detonatedelay) >= 0)
318 missile.spawnshieldtime =
time +
WEP_CVAR(devastator, detonatedelay);
320 missile.spawnshieldtime = -1;
321 missile.pushltime =
time +
WEP_CVAR(devastator, guidedelay);
322 missile.classname =
"rocket";
323 missile.bot_dodge =
true;
324 missile.bot_dodgerating =
WEP_CVAR(devastator, damage) * 2;
329 missile.event_damage = W_Devastator_Damage;
330 missile.damagedbycontents =
true;
335 missile.projectiledeathtype = thiswep.
m_id;
336 setsize(missile,
'-3 -3 -3',
'3 3 3');
342 settouch(missile, W_Devastator_Touch);
343 setthink(missile, W_Devastator_Think);
344 missile.nextthink =
time;
346 missile.rl_detonate_later = (fire & 2);
347 missile.flags = FL_PROJECTILE;
357 if (
time >= missile.nextthink)
370 float edgedamage, coredamage, edgeradius, recipricoledgeradius;
371 float selfdamage, teamdamage, enemydamage;
372 edgedamage =
WEP_CVAR(devastator, edgedamage);
373 coredamage =
WEP_CVAR(devastator, damage);
375 recipricoledgeradius = 1 / edgeradius;
382 IL_EACH(g_bot_targets, it.bot_attack,
384 float d = vlen(it.origin + (it.mins + it.maxs) * 0.5 - rocket.origin);
385 d = bound(0, edgedamage + (coredamage - edgedamage) * sqrt(1 - d * recipricoledgeradius), 10000);
388 selfdamage = selfdamage + d;
389 else if(SAME_TEAM(it, actor))
390 teamdamage = teamdamage + d;
391 else if(bot_shouldattack(actor, it))
392 enemydamage = enemydamage + d;
395 float desirabledamage;
396 desirabledamage = enemydamage;
397 if(StatusEffects_active(STATUSEFFECT_Shield, actor) && !StatusEffects_active(STATUSEFFECT_SpawnShield, actor))
400 desirabledamage = desirabledamage - teamdamage;
408 IL_EACH(g_bot_targets, it.bot_attack,
410 if((v_forward * normalize(rocket.origin - it.origin) < 0.1)
411 && desirabledamage > 0.1 * coredamage
412 ) PHYS_INPUT_BUTTON_ATCK2(actor) = true;
419 if((v_forward * normalize(it.origin - actor.enemy.origin) < 0.1)
420 && IS_PLAYER(actor.enemy)
421 && (desirabledamage >= 0.1 * coredamage)
424 float distance = bound(300, vlen(actor.origin - actor.enemy.origin), 30000);
425 if(random() / distance * 300 > frametime * bound(0, (10 - skill) * 0.2, 1))
426 PHYS_INPUT_BUTTON_ATCK2(actor) = true;
432 if(desirabledamage >= 0.75 * coredamage)
444 if(
WEP_CVAR(devastator, reload_ammo) && actor.(weaponentity).clip_load <
WEP_CVAR(devastator,
ammo)) {
445 thiswep.wr_reload(thiswep, actor, weaponentity);
449 if(actor.(weaponentity).rl_release ||
WEP_CVAR(devastator, guidestop))
452 W_Devastator_Attack(thiswep, actor, weaponentity, fire);
454 actor.(weaponentity).rl_release = 0;
458 actor.(weaponentity).rl_release = 1;
461 if(actor.(weaponentity).m_switchweapon == thiswep)
463 bool rockfound =
false;
466 if(!it.rl_detonate_later)
468 it.rl_detonate_later = true;
479 actor.(weaponentity).rl_release = 1;
488 if(
WEP_CVAR(devastator, reload_ammo))
499 if(actor.rl_release == 0)
508 LOG_INFOF(
"W_Devastator(WR_CHECKAMMO1): %d, %.2f, %d: %s", actor.rl_release,
GetResource(actor, thiswep.ammo_type),
WEP_CVAR(devastator,
ammo), (ammo_amount ?
"TRUE" :
"FALSE"));
526 actor.(weaponentity).lastrocket = NULL;
527 actor.(weaponentity).rl_release = 0;
536 return WEAPON_DEVASTATOR_SUICIDE;
541 return WEAPON_DEVASTATOR_MURDER_SPLASH;
543 return WEAPON_DEVASTATOR_MURDER_DIRECT;
552 org2 = w_org + w_backoff * 12;
const int HITTYPE_SPLASH
automatically set by RadiusDamage
#define PHYS_INPUT_BUTTON_ATCK2(s)
#define W_SetupProjVelocity_Basic(ent, pspeed, pspread)
#define IL_EACH(this, cond, body)
bool bot_aim(entity this,.entity weaponentity, float shotspeed, float shotspeedupward, float maxshottime, float applygravity)
float weapon_load[REGISTRY_MAX(Weapons)]
ERASEABLE vector solve_quadratic(float a, float b, float c)
ax^2 + bx + c = 0
#define PROJECTILE_MAKETRIGGER(e)
bool SetResourceExplicit(entity e, Resource res_type, float amount)
Sets the resource amount of an entity without calling any hooks.
#define w_getbestweapon(ent, wepent)
#define W_SetupShot_ProjectileSize(ent, wepent, mi, ma, antilag, recoil, snd, chan, maxdamage, deathtype)
float W_CheckProjectileDamage(entity inflictor, entity projowner, int deathtype, float exception)
IntrusiveList g_damagedbycontents
void w_ready(Weapon thiswep, entity actor,.entity weaponentity, int fire)
#define WEP_CVAR(wepname, name)
#define METHOD(cname, name, prototype)
void CSQCProjectile(entity e, float clientanimate, int type, float docull)
vector WarpZone_RefSys_TransformVelocity(entity from, entity to, vector vel)
IntrusiveList g_bot_dodge
void TakeResource(entity receiver, Resource res_type, float amount)
Takes an entity some resource.
vector WarpZone_RefSys_TransformOrigin(entity from, entity to, vector org)
float autocvar_g_balance_selfdamagepercent
ERASEABLE entity IL_PUSH(IntrusiveList this, entity it)
Push to tail.
void UpdateCSQCProjectile(entity e)
bool W_DualWielding(entity player)
const int MAX_WEAPONSLOTS
Resource ammo_type
M: ammotype : main ammo type.
const int PROJECTILE_ROCKET
bool weapon_prepareattack(Weapon thiswep, entity actor,.entity weaponentity, bool secondary, float attacktime)
void W_PrepareExplosionByDamage(entity this, entity attacker, void(entity this) explode)
entity WarpZone_RefSys_SpawnSameRefSys(entity me)
#define PHYS_INPUT_BUTTON_ATCK(s)
entity WarpZone_FindRadius(vector org, float rad, bool needlineofsight)
bool IsFlying(entity this)
vector(float skel, float bonenum) _skel_get_boneabs_hidden
IntrusiveList g_projectiles
float GetResource(entity e, Resource res_type)
Returns the current amount of resource the given entity has.
#define vdist(v, cmp, f)
Vector distance comparison, avoids sqrt()
float W_WeaponSpeedFactor(entity this)
entity Notification
always last
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)
#define MUTATOR_CALLHOOK(id,...)
entity weaponentities[MAX_WEAPONSLOTS]
float WarpZone_Projectile_Touch(entity this, entity toucher)
#define ATTACK_FINISHED(ent, w)
void W_DecreaseAmmo(Weapon wep, entity actor, float ammo_use,.entity weaponentity)
#define sound(e, c, s, v, a)
float csqcprojectile_clientanimate
fields which are explicitly/manually set are marked with "M", fields set automatically are marked wit...
void set_movetype(entity this, int mt)
void W_Reload(entity actor,.entity weaponentity, float sent_ammo_min, Sound sent_sound)