48 if (!player.(weaponentity).arc_beam)
50 player.(weaponentity).
arc_beam.beam_dir = forward;
57 if (
WEP_CVAR(WEP_ARC, overheat_max) <= 0 ||
WEP_CVAR(WEP_ARC, overheat_min) <= 0)
59 player.arc_overheat = 0;
62 if (player.(weaponentity).arc_beam)
63 return player.(weaponentity).
arc_beam.beam_heat /
WEP_CVAR(WEP_ARC, overheat_max);
65 if (player.arc_overheat >
time)
66 return (player.arc_overheat -
time) /
WEP_CVAR(WEP_ARC, overheat_max)
67 * player.arc_cooldown;
125 if (
WEP_CVAR(WEP_ARC, bolt_bounce_explode))
137 if (this.
cnt == 1 &&
WEP_CVAR(WEP_ARC, bolt_bounce_lifetime))
148 entity missile =
new(missile);
149 missile.owner = missile.realowner = actor;
150 missile.bot_dodge =
true;
152 missile.bot_dodgerating =
WEP_CVAR(WEP_ARC, bolt_damage);
156 missile.damageforcescale =
WEP_CVAR(WEP_ARC, bolt_damageforcescale);
158 missile.damagedbycontents =
true;
165 missile.nextthink =
time +
WEP_CVAR(WEP_ARC, bolt_lifetime);
168 missile.weaponentity_fld = weaponentity;
170 setsize(missile,
'0 0 0',
'0 0 0');
185 if (actor.(weaponentity).misc_bulletcounter == 0)
198 if (
this != own.(weaponentity).arc_beam)
219 || own.(weaponentity).m_switchweapon != WEP_ARC
223 if (
WEP_CVAR(WEP_ARC, cooldown) > 0)
225 float cooldown_speed;
227 cooldown_speed =
WEP_CVAR(WEP_ARC, cooldown);
242 if (
WEP_CVAR(WEP_ARC, cooldown_release) || overheat)
244 own.arc_cooldown = cooldown_speed;
248 if (
this == own.(weaponentity).arc_beam)
264 float rootammo = (burst ?
WEP_CVAR(WEP_ARC, burst_ammo) :
WEP_CVAR(WEP_ARC, beam_ammo));
283 WEP_CVAR(WEP_ARC, beam_damage) * coefficient,
325 float max_blendfactor = 1;
337 if (
WEP_CVAR(WEP_ARC, beam_distancepersegment))
343 if (
WEP_CVAR(WEP_ARC, beam_degreespersegment))
346 segments =
bound(1, segments, max_allowed_segments);
351 float beam_controlpoint_dist =
WEP_CVAR(WEP_ARC, beam_range) *
bound(0.001, 1 -
WEP_CVAR(WEP_ARC, beam_tightness), 1);
354 int new_beam_type = 0;
356 vector last_origin_prev =
'0 0 0';
357 for (
int i = 1; i <= segments; ++i)
381 last_origin_prev = last_origin;
406 float roothealth = (burst ?
WEP_CVAR(WEP_ARC, burst_healing_hps) :
WEP_CVAR(WEP_ARC, beam_healing_hps));
407 float rootarmor = (burst ?
WEP_CVAR(WEP_ARC, burst_healing_aps) :
WEP_CVAR(WEP_ARC, beam_healing_aps));
416 if (roothealth || rootarmor)
419 else if (
trace_ent.takedamage && (is_player ||
WEP_CVAR(WEP_ARC, beam_nonplayerdamage)))
427 WEP_CVAR(WEP_ARC, beam_falloff_mindist),
428 WEP_CVAR(WEP_ARC, beam_falloff_maxdist),
429 WEP_CVAR(WEP_ARC, beam_falloff_halflifedist),
437 rootdamage =
WEP_CVAR(WEP_ARC, burst_damage);
439 rootdamage =
WEP_CVAR(WEP_ARC, beam_damage);
442 rootdamage =
WEP_CVAR(WEP_ARC, beam_nonplayerdamage);
450 rootdamage * coefficient *
falloff,
465 new_beam_type |= burst;
481 if (
time - actor.(weaponentity).beam_prev > 1)
485 beam.weaponentity_fld = weaponentity;
490 beam.bot_dodge =
true;
492 beam.bot_dodgerating =
WEP_CVAR(WEP_ARC, beam_damage);
493 beam.beam_bursting =
boolean(burst);
500 if (!actor.(weaponentity).arc_beam || wasfreed(actor.(weaponentity).arc_beam))
502 w_ready(thiswep, actor, weaponentity, fire);
510 actor.(weaponentity).
wframe = WFRAME_FIRE1;
520 w_shotorg = actor.origin + actor.view_ofs + dv;
524 if (actor.arc_overheat >
time)
526 if (
random() < actor.(weaponentity).arc_heat_percent)
527 Send_Effect(EFFECT_ARC_SMOKE, smoke_origin,
'0 0 0', 1);
531 if (!actor.arc_smoke_sound)
533 actor.arc_smoke_sound =
true;
538 else if (actor.(weaponentity).arc_beam &&
WEP_CVAR(WEP_ARC, overheat_max) > 0
539 && actor.(weaponentity).arc_beam.beam_heat >
WEP_CVAR(WEP_ARC, overheat_min))
541 float frac_to_max = (actor.(weaponentity).arc_beam.beam_heat -
WEP_CVAR(WEP_ARC, overheat_min)) /
543 if (
random() < frac_to_max)
544 Send_Effect(EFFECT_ARC_SMOKE, smoke_origin,
'0 0 0', 1);
548 bool stop_smoke_sound = actor.arc_overheat <=
time || !attacking;
549 if ((actor.arc_smoke_sound && stop_smoke_sound) || actor.(weaponentity).m_switchweapon != thiswep)
551 actor.arc_smoke_sound =
false;
558 if (
WEP_CVAR(WEP_ARC, beam_botaimspeed))
566 Arc_Smoke(thiswep, actor, weaponentity, fire);
568 bool beam_fire2 = ((fire & 2) && !
WEP_CVAR(WEP_ARC, bolt));
570 if (
time >= actor.arc_overheat
571 && ((fire & 1) || beam_fire2 || actor.(weaponentity).arc_beam.beam_bursting))
574 if (actor.(weaponentity).arc_BUTTON_ATCK_prev)
577 if (actor.animstate_startframe == actor.anim_shoot.x && actor.animstate_numframes == actor.anim_shoot.y)
578 weapon_thinkf(actor, weaponentity, WFRAME_DONTCHANGE, autocvar_g_balance_arc_primary_animtime,
w_ready);
585 if ((!actor.(weaponentity).arc_beam || wasfreed(actor.(weaponentity).arc_beam))
588 W_Arc_Beam(
boolean(beam_fire2), actor, weaponentity);
590 if (!actor.(weaponentity).arc_BUTTON_ATCK_prev)
592 actor.(weaponentity).
wframe = WFRAME_FIRE1;
603 if (!thiswep.wr_checkammo2(thiswep, actor, weaponentity)
607 w_ready(thiswep, actor, weaponentity, fire);
610 int to_shoot =
WEP_CVAR(WEP_ARC, bolt_count);
613 float ammo_available =
GetResource(actor, thiswep.ammo_type);
616 float burst_fraction =
min(1, ammo_available /
WEP_CVAR(WEP_ARC, bolt_ammo));
617 to_shoot =
floor(to_shoot * burst_fraction);
620 int to_use =
min(
WEP_CVAR(WEP_ARC, bolt_ammo), ammo_available);
630 if (actor.(weaponentity).arc_BUTTON_ATCK_prev)
640 if (
weapon_prepareattack(thiswep, actor, weaponentity,
true, autocvar_g_balance_arc_secondary_refire))
643 actor.arc_count = autocvar_g_balance_arc_secondary_count;
644 weapon_thinkf(actor, weaponentity, WFRAME_FIRE2, autocvar_g_balance_arc_secondary_animtime, w_arc_checkattack);
652 return WEAPON_ARC_SUICIDE_BOLT;
654 return WEAPON_THINKING_WITH_PORTALS;
676 ammo_amount += actor.(weaponentity).(
weapon_load[WEP_ARC.m_id]) >=
WEP_CVAR(WEP_ARC, bolt_ammo);
680 return WEP_CVAR(WEP_ARC, overheat_max) > 0 &&
686 return WEAPON_ARC_MURDER_SPRAY;
688 return WEAPON_ARC_MURDER;
694 actor.arc_overheat = 0;
695 actor.arc_cooldown = 0;
709 actor.arc_overheat = 0;
710 actor.arc_cooldown = 0;
719 actor.arc_overheat = 0;
720 actor.arc_cooldown = 0;
752 hitorigin = start + (Draw_ArcBeam_callback_new_dir * Draw_ArcBeam_callback_segmentdist *
trace_fraction);
761 float thickness = beam.beam_thickness;
772 vector top = hitorigin + (thickdir * thickness);
773 vector bottom = hitorigin - (thickdir * thickness);
782 '0 0.5 0' + (
'0 0.5 0' * (thickness / beam.beam_thickness)),
800 '0 0.5 0' * (1 - (thickness / beam.beam_thickness)),
816 if (beam.beam_traileffect)
824 e.beam_initialized =
false;
826 e.beam_initialized =
false;
832 this.move_time =
time;
867 vector forward, right, up;
881 vector start_pos_saved = start_pos;
886 start_pos =
gettaginfo(wepent, v_shot_idx) -
'0 0 2';
895 start_pos_saved = start_pos;
902 start_pos_saved + forward *
WEP_CVAR(WEP_ARC, beam_range),
915 vector origin_offset =
'0 0 0';
924 start_pos += origin_offset;
931 if (
vdist(end_pos - start_pos, >, 0.001))
932 wantdir =
normalize(end_pos - start_pos);
953 float max_blendfactor = 1;
956 float blendfactor =
bound(0, (1 - (
WEP_CVAR(WEP_ARC, beam_returnspeed) * dt)), max_blendfactor);
961 if (
WEP_CVAR(WEP_ARC, beam_distancepersegment))
963 max_allowed_segments = 1 + (
vlen(wantdir /
WEP_CVAR(WEP_ARC, beam_distancepersegment)));
966 if (
WEP_CVAR(WEP_ARC, beam_degreespersegment))
969 segments =
bound(1, segments, max_allowed_segments);
990 if (beamdir != wantdir)
996 if (
WEP_CVAR(WEP_ARC, beam_distancepersegment))
998 max_allowed_segments = 1 + (
vlen(wantdir /
WEP_CVAR(WEP_ARC, beam_distancepersegment)));
1002 if (
WEP_CVAR(WEP_ARC, beam_degreespersegment))
1005 segments =
bound(1, segments, max_allowed_segments);
1010 setorigin(
this, start_pos);
1013 vector beam_endpos = start_pos + (beamdir *
WEP_CVAR(WEP_ARC, beam_range));
1014 float beam_controlpoint_dist =
WEP_CVAR(WEP_ARC, beam_range) *
bound(0.001, 1 -
WEP_CVAR(WEP_ARC, beam_tightness), 1);
1015 vector beam_controlpoint = start_pos + wantdir * beam_controlpoint_dist;
1025 vector last_origin = start_pos;
1026 vector original_start_pos = start_pos;
1028 for (
int i = 1; i <= segments; ++i)
1095 original_start_pos + wantdir * 20,
1102 original_start_pos + wantdir * 20,
1148 flash =
new(arc_flash);
1153 flash.avelocity.z = 5000;
1154 setattachment(flash,
this,
"");
1155 setorigin(flash,
'0 0 0');
1195 setorigin(
this, this.
origin);
1207 vector beamcolor =
'1 1 1';
1231 setmodel(flash, MDL_ARC_MUZZLEFLASH);
1255 setmodel(flash, MDL_ARC_MUZZLEFLASH);
1279 setmodel(flash, MDL_ARC_MUZZLEFLASH);
1303 setmodel(flash, MDL_ARC_MUZZLEFLASH);
1327 setmodel(flash, MDL_ARC_MUZZLEFLASH);
1351 setmodel(flash, MDL_ARC_MUZZLEFLASH);
1375 setmodel(flash, MDL_ARC_MUZZLEFLASH);
1399 setmodel(flash, MDL_ARC_MUZZLEFLASH);
1425 setmodel(flash, MDL_ARC_MUZZLEFLASH);
1448 PAR(_(
"The %s fires a continuous beam of electricity, steadily dealing damage to any enemies that cross its path."),
COLORED_NAME(
this));
1449 PAR(_(
"The secondary fire rapidly shoots electric bolts forward, exploding on impact and dealing some splash damage."));
1450 PAR(_(
"It consumes %s ammo, steadily churning through your supply to maintain the stream."),
COLORED_NAME(ITEM_Cells));
1451 PAR(_(
"The %s is quite a versatile weapon, however it is more effective at close to medium ranges, since the stream is not instantaneous."),
COLORED_NAME(
this));
void accuracy_add(entity this, Weapon w, float fired, float hit, float real)
update accuracy stats
bool accuracy_isgooddamage(entity attacker, entity targ)
does this damage count towards accuracy stats?
void WarpZone_traceline_antilag(entity source, vector v1, vector v2, float nomonst, entity forent, float lag)
#define ANTILAG_LATENCY(e)
bool bot_aim(entity this,.entity weaponentity, float shotspeed, float shotspeedupward, float maxshottime, float applygravity, bool shot_accurate)
IntrusiveList g_bot_dodge
void W_Arc_Beam(bool burst, entity actor,.entity weaponentity)
bool autocvar_cl_arcbeam_simple
void Arc_Smoke(Weapon thiswep, entity actor,.entity weaponentity, int fire)
void Remove_ArcBeam(entity this)
bool W_Arc_Beam_Send(entity this, entity to, int sf)
void Draw_ArcBeam_callback(vector start, vector hit, vector end)
void W_Arc_Bolt_Damage(entity this, entity inflictor, entity attacker, float damage, int deathtype,.entity weaponentity, vector hitloc, vector force)
void W_Arc_Attack_Bolt(Weapon thiswep, entity actor,.entity weaponentity, int fire)
void W_Arc_Bolt_Explode_use(entity this, entity actor, entity trigger)
void W_Arc_Beam_Think(entity this)
void W_Arc_Attack(Weapon thiswep, entity actor,.entity weaponentity, int fire)
float Arc_GetHeat_Percent(entity player,.entity weaponentity)
void Draw_ArcBeam(entity this)
void W_Arc_Bolt_Touch(entity this, entity toucher)
void W_Arc_Bolt_Explode(entity this, entity directhitentity)
void Arc_Player_SetHeat(entity player,.entity weaponentity)
vector Draw_ArcBeam_callback_last_top
const int ARC_SF_LOCALMASK
const float ARC_MAX_SEGMENTS
const int ARC_SF_BEAMTYPE
bool arc_BUTTON_ATCK_prev
const int ARC_BT_BURST_HEAL
vector Draw_ArcBeam_callback_last_bottom
entity Draw_ArcBeam_callback_entity
const int ARC_BT_BURST_MISS
const int ARC_BT_BURST_WALL
float beam_muzzlelight[4]
const int ARC_BT_BURST_HIT
float Draw_ArcBeam_callback_last_thickness
const int ARC_BT_BURSTMASK
#define MUTATOR_CALLHOOK(id,...)
int W_GunAlign(entity this, int preferred_align)
var entity(vector mins, vector maxs,.entity tofield) findbox_tofield_OrFallback
void SetResource(entity e, Resource res_type, float amount)
Sets the current amount of resource the given entity will have.
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.
virtual void wr_checkammo1()
(SERVER) checks ammo for weapon primary
IntrusiveList g_drawables
#define colormapPaletteColor(c, isPants)
#define COLORED_NAME(this)
const int IT_UNLIMITED_AMMO
#define setmodel(this, m)
#define PHYS_INPUT_BUTTON_ATCK(s)
#define PHYS_INPUT_BUTTON_ATCK2(s)
float W_WeaponRateFactor(entity this)
void Draw_CylindricLine(vector from, vector to, float thickness, string texture, float aspect, float shift, vector rgb, float theAlpha, float drawflag, vector vieworg)
const float DRAWFLAG_NORMAL
const float MOVE_NOMONSTERS
const float EF_FULLBRIGHT
float trace_dphitq3surfaceflags
float Q3SURFACEFLAG_NOIMPACT
void CSQCProjectile(entity e, float clientanimate, int type, float docull)
void Damage(entity targ, entity inflictor, entity attacker, float damage, int deathtype,.entity weaponentity, vector hitloc, vector force)
bool Heal(entity targ, entity inflictor, float amount, float limit)
float RadiusDamage(entity inflictor, entity attacker, float coredamage, float edgedamage, float rad, entity cantbe, entity mustbe, float forceintensity, int deathtype,.entity weaponentity, entity directhitentity)
IntrusiveList g_damagedbycontents
void W_SwitchWeapon_Force(Player this, Weapon w,.entity weaponentity)
const int HITTYPE_SECONDARY
#define MAKE_VECTORS(angles, forward, right, up)
Same as the makevectors builtin but uses the provided locals instead of the v_* globals.
#define pointparticles(effect, org, vel, howmany)
#define trailparticles(e, effect, org, vel)
void Send_Effect(entity eff, vector eff_loc, vector eff_vel, int eff_cnt)
#define entcs_receiver(...)
int entcs_GetClientColors(int i)
void InterpolateOrigin_Undo(entity this)
snap origin to iorigin2 (actual origin)
void InterpolateOrigin_Note(entity this)
void InterpolateOrigin_Do(entity this)
set origin based on iorigin1 (old pos), iorigin2 (desired pos), and time
ERASEABLE entity IL_PUSH(IntrusiveList this, entity it)
Push to tail.
#define NET_HANDLE(id, param)
#define ReadAngleVector()
#define WriteHeader(to, id)
void Net_LinkEntity(entity e, bool docull, float dt, bool(entity this, entity to, int sendflags) sendfunc)
vector warpzone_save_view_origin
vector warpzone_save_view_angles
void WarpZone_TraceBox_ThroughZone(vector org, vector mi, vector ma, vector end, float nomonsters, entity forent, entity zone, WarpZone_trace_callback_t cb)
void WarpZone_TraceLine(vector org, vector end, float nomonsters, entity forent)
vector WarpZone_TransformVelocity(entity wz, vector v)
vector WarpZone_UnTransformOrigin(entity wz, vector v)
vector WarpZone_TransformOrigin(entity wz, vector v)
entity WarpZone_trace_transform
ERASEABLE float ExponentialFalloff(float mindist, float maxdist, float halflifedist, float d)
ERASEABLE vector bezier_quadratic_getpoint(vector a, vector b, vector c, float t)
void set_movetype(entity this, int mt)
const int MOVETYPE_BOUNCEMISSILE
entity Notification
always last
#define METHOD(cname, name, prototype)
void loopsound(entity e, int ch, Sound samp, float vol, float attn)
const int PROJECTILE_ARC_BOLT
bool client_hasweapon(entity this, Weapon wpn,.entity weaponentity, float andammo, bool complain)
void W_SwitchToOtherWeapon(entity this,.entity weaponentity)
Perform weapon to attack (weaponstate and attack_finished check is here)
#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)
void adaptor_think2use_hittype_splash(entity this)
#define PROJECTILE_TOUCH(e, t)
IntrusiveList g_projectiles
#define PROJECTILE_MAKETRIGGER(e)
const int CH_SHOTS_SINGLE
#define sound(e, c, s, v, a)
#define PAR(...)
Adds an individually translatable paragraph to PAGE_TEXT without having to deal with strcat and sprin...
void GiveResourceWithLimit(entity receiver, Resource res_type, float amount, float limit)
Gives an entity some resource but not more than a limit.
float autocvar_g_balance_pause_armor_rot
#define W_SetupProjVelocity_PRE(ent, wep, prefix)
#define W_SetupShot_Range(ent, wepent, antilag, recoil, snd, chan, maxdamage, range, deathtype)
#define W_SetupShot(ent, wepent, antilag, recoil, snd, chan, maxdamage, deathtype)
#define vdist(v, cmp, f)
Vector distance comparison, avoids sqrt()
int autocvar_chase_active
bool autocvar_r_drawviewmodel
bool autocvar_cl_lockview
entity viewmodels[MAX_WEAPONSLOTS]
string W_Guide_Keybinds(Weapon wep)
void W_MuzzleFlash(Weapon thiswep, entity actor,.entity weaponentity, vector shotorg, vector shotdir)
string W_Guide_DPS_primaryDPS(string name, string pri, string sec)
vector shotorg_adjust(vector vecs, bool y_is_right, bool visual, int algn)
#define WEP_CVAR(wep, name)
const int MAX_WEAPONSLOTS
entity weaponentities[MAX_WEAPONSLOTS]
int autocvar_cl_tracers_teamcolor
int weaponslot(.entity weaponentity)
void W_DecreaseAmmo(Weapon wep, entity actor, float ammo_use,.entity weaponentity)
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)
vector CL_Weapon_GetShotOrg(int wpn)
void w_ready(Weapon thiswep, entity actor,.entity weaponentity, int fire)
bool weapon_prepareattack_check(Weapon thiswep, entity actor,.entity weaponentity, bool secondary, float attacktime)
entity weapon_dropevent_item
#define ATTACK_FINISHED(ent, w)
float weapon_load[REGISTRY_MAX(Weapons)]