Xonotic QuakeC
The free, fast arena FPS with crisp movement and a wide array of weapons
arc.qc File Reference
Include dependency graph for arc.qc:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

float Arc_GetHeat_Percent (entity player,.entity weaponentity)
void Arc_Player_SetHeat (entity player,.entity weaponentity)
void Arc_Smoke (Weapon thiswep, entity actor,.entity weaponentity, int fire)
void Draw_ArcBeam (entity this)
void Draw_ArcBeam_callback (vector start, vector hit, vector end)
 NET_HANDLE (ENT_CLIENT_ARC_BEAM, bool isNew)
void Remove_ArcBeam (entity this)
void Reset_ArcBeam ()
void Reset_ArcBeam (entity player, vector forward)
void W_Arc_Attack (Weapon thiswep, entity actor,.entity weaponentity, int fire)
void W_Arc_Attack_Bolt (Weapon thiswep, entity actor,.entity weaponentity, int fire)
void W_Arc_Beam (bool burst, entity actor,.entity weaponentity)
bool W_Arc_Beam_Send (entity this, entity to, int sf)
void W_Arc_Beam_Think (entity this)
void W_Arc_Bolt_Damage (entity this, entity inflictor, entity attacker, float damage, int deathtype,.entity weaponentity, vector hitloc, vector force)
void W_Arc_Bolt_Explode (entity this, entity directhitentity)
void W_Arc_Bolt_Explode_use (entity this, entity actor, entity trigger)
void W_Arc_Bolt_Touch (entity this, entity toucher)

Variables

bool autocvar_cl_arcbeam_simple = true
int beam_slot

Function Documentation

◆ Arc_GetHeat_Percent()

float Arc_GetHeat_Percent ( entity player,
.entity weaponentity )

Definition at line 55 of file arc.qc.

56{
57 if (WEP_CVAR(WEP_ARC, overheat_max) <= 0 || WEP_CVAR(WEP_ARC, overheat_min) <= 0)
58 {
59 player.arc_overheat = 0;
60 return 0;
61 }
62 if (player.(weaponentity).arc_beam)
63 return player.(weaponentity).arc_beam.beam_heat / WEP_CVAR(WEP_ARC, overheat_max);
64
65 if (player.arc_overheat > time)
66 return (player.arc_overheat - time) / WEP_CVAR(WEP_ARC, overheat_max)
67 * player.arc_cooldown;
68 return 0;
69}
entity arc_beam
Definition arc.qh:132
float time
#define WEP_CVAR(wep, name)
Definition all.qh:337

References arc_beam, entity(), time, and WEP_CVAR.

Referenced by Arc_Player_SetHeat().

◆ Arc_Player_SetHeat()

void Arc_Player_SetHeat ( entity player,
.entity weaponentity )

Definition at line 70 of file arc.qc.

71{
72 player.(weaponentity).arc_heat_percent = Arc_GetHeat_Percent(player, weaponentity);
73 //dprint("Heat: ", ftos(player.arc_heat_percent * 100), "%\n");
74}
float Arc_GetHeat_Percent(entity player,.entity weaponentity)
Definition arc.qc:55
float arc_heat_percent
Definition arc.qh:141

References Arc_GetHeat_Percent(), arc_heat_percent, and entity().

◆ Arc_Smoke()

void Arc_Smoke ( Weapon thiswep,
entity actor,
.entity weaponentity,
int fire )

Definition at line 513 of file arc.qc.

514{
515 // calculate a rough shot origin to show the effect from TODO: move this to the client side!
516 makevectors(actor.v_angle);
518 vector md = actor.(weaponentity).movedir;
519 vector dv = v_forward * md.x + v_right * -md.y + v_up * md.z;
520 w_shotorg = actor.origin + actor.view_ofs + dv;
521 //W_SetupShot_Range(actor, weaponentity, false, 0, SND_Null, 0, 0, 0, thiswep.m_id);
522
523 vector smoke_origin = w_shotorg + actor.velocity*frametime;
524 if (actor.arc_overheat > time)
525 {
526 if (random() < actor.(weaponentity).arc_heat_percent)
527 Send_Effect(EFFECT_ARC_SMOKE, smoke_origin, '0 0 0', 1);
528 if (fire & (1 | 2))
529 {
530 Send_Effect(EFFECT_ARC_OVERHEAT_FIRE, smoke_origin, w_shotdir, 1);
531 if (!actor.arc_smoke_sound)
532 {
533 actor.arc_smoke_sound = true;
534 sound(actor, CH_SHOTS_SINGLE, SND_ARC_LOOP_OVERHEAT, VOL_BASE, ATTN_NORM);
535 }
536 }
537 }
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))
540 {
541 float frac_to_max = (actor.(weaponentity).arc_beam.beam_heat - WEP_CVAR(WEP_ARC, overheat_min)) /
542 (WEP_CVAR(WEP_ARC, overheat_max) - WEP_CVAR(WEP_ARC, overheat_min));
543 if (random() < frac_to_max)
544 Send_Effect(EFFECT_ARC_SMOKE, smoke_origin, '0 0 0', 1);
545 }
546
547 bool attacking = PHYS_INPUT_BUTTON_ATCK(actor) || PHYS_INPUT_BUTTON_ATCK2(actor);
548 bool stop_smoke_sound = actor.arc_overheat <= time || !attacking;
549 if ((actor.arc_smoke_sound && stop_smoke_sound) || actor.(weaponentity).m_switchweapon != thiswep)
550 {
551 actor.arc_smoke_sound = false;
552 sound(actor, CH_SHOTS_SINGLE, SND_Null, VOL_BASE, ATTEN_NORM);
553 }
554}
#define PHYS_INPUT_BUTTON_ATCK(s)
Definition player.qh:152
#define PHYS_INPUT_BUTTON_ATCK2(s)
Definition player.qh:154
vector v_up
float frametime
vector v_right
vector v_forward
const float ATTN_NORM
void Send_Effect(entity eff, vector eff_loc, vector eff_vel, int eff_cnt)
Definition all.qc:120
vector movedir
Definition viewloc.qh:18
float random(void)
#define makevectors
Definition post.qh:21
vector
Definition self.qh:96
const float VOL_BASE
Definition sound.qh:36
const int CH_SHOTS_SINGLE
Definition sound.qh:15
const float ATTEN_NORM
Definition sound.qh:30
#define sound(e, c, s, v, a)
Definition sound.qh:52
vector w_shotdir
Definition tracing.qh:20
vector w_shotorg
Definition tracing.qh:19

References ATTEN_NORM, ATTN_NORM, CH_SHOTS_SINGLE, entity(), frametime, makevectors, movedir, PHYS_INPUT_BUTTON_ATCK, PHYS_INPUT_BUTTON_ATCK2, random(), Send_Effect(), sound, time, v_forward, v_right, v_up, vector, VOL_BASE, w_shotdir, w_shotorg, and WEP_CVAR.

◆ Draw_ArcBeam()

void Draw_ArcBeam ( entity this)

Definition at line 823 of file arc.qc.

824{
825 float dt = time - this.move_time;
826 this.move_time = time;
827 if (dt <= 0)
828 return;
829
830 // origin = beam starting origin
831 // v_angle = wanted/aim direction
832 // angles = current direction of beam
833
834 vector start_pos;
835 vector wantdir; //= view_forward;
836 vector beamdir; //= this.beam_dir;
837
838 float segments;
839 if (this.beam_usevieworigin)
840 {
841 // WEAPONTODO:
842 // Currently we have to replicate nearly the same method of figuring
843 // out the shotdir that the server does... Ideally in the future we
844 // should be able to acquire this from a generalized function built
845 // into a weapon system for client code.
846
847 // Dr. Jaska: Reply to ^: Do we? If the server would decide where a
848 // client draws a beam it would mean that what the client sees will
849 // always be lagged and not where they are actually hitting in "real
850 // time" after being antilagged. Thus I don't understand the above.
851
852 // find where we are aiming
853 vector myviewangle = view_angles;
855 {
857 myviewangle = eX * csqcplayer.v_angle.x + eY * csqcplayer.angles.y;
858 else
859 myviewangle = warpzone_save_view_angles;
860 }
861 vector forward, right, up;
862 MAKE_VECTORS(myviewangle, forward, right, up);
863 entity wepent = viewmodels[this.beam_slot];
864
866
867 // decide upon start position
868 if (this.beam_usevieworigin == 2)
869 start_pos = warpzone_save_view_origin;
870 else if (csqcplayer)
871 start_pos = csqcplayer.origin + csqcplayer.view_ofs;
872 else
873 start_pos = this.origin;
874
875 vector start_pos_saved = start_pos;
876 int v_shot_idx;
877 (v_shot_idx = gettagindex(wepent, "shot")) || (v_shot_idx = gettagindex(wepent, "tag_shot"));
878 if (v_shot_idx && this.beam_usevieworigin == 2)
879 {
880 start_pos = gettaginfo(wepent, v_shot_idx) - '0 0 2';
881 // ignore our own player model in this traceline otherwise it may be hit with trace_fraction < 1
882 // while crouching / standing up due to view height smoothing (cl_smoothviewheight)
883 traceline(start_pos_saved, start_pos, MOVE_NORMAL, csqcplayer);
884 if (trace_fraction < 1)
885 {
886 // found an obstacle between view origin and shot tag
887 v_shot_idx = 0;
888 start_pos = trace_endpos;
889 start_pos_saved = start_pos;
890 }
891 }
892
893 // trace forward with an estimation
895 start_pos_saved,
896 start_pos_saved + forward * WEP_CVAR(WEP_ARC, beam_range),
898 this
899 );
900
901 // untransform in case our trace went through a warpzone
903
904 // un-adjust trueaim if shotend is too close
905 if (vdist(end_pos - start_pos, <, g_trueaim_minrange))
906 end_pos = start_pos + (forward * g_trueaim_minrange);
907
908 // move shot origin to the actual gun muzzle origin
909 vector origin_offset = '0 0 0';
910 if (!v_shot_idx || this.beam_usevieworigin != 2)
911 {
912 this.beam_shotorigin = wepent.movedir;
913 origin_offset = right * -this.beam_shotorigin.y + up * this.beam_shotorigin.z;
914 }
915 else
916 this.beam_shotorigin = '0 0 0';
917
918 start_pos += origin_offset;
919
920 // Move it also forward, but only as far as possible without hitting anything. Don't poke into walls!
921 traceline(start_pos, start_pos + forward * this.beam_shotorigin.x, MOVE_NORMAL, this);
922 start_pos = trace_endpos;
923
924 // calculate the aim direction now
925 if (vdist(end_pos - start_pos, >, 0.001))
926 wantdir = normalize(end_pos - start_pos);
927 else
928 wantdir = view_forward;
929
930 if (!this.beam_initialized)
931 {
932 this.beam_dir = wantdir;
933 this.beam_initialized = true;
934
935 this.beam_muzzleentity.drawmask = MASK_NORMAL; // NOTE: this works around the muzzle entity flashing on the middle of the screen for a frame
936 }
937
938 segments = 1;
939 if (this.beam_dir != wantdir)
940 {
941 // calculate how much we're going to move the end of the beam to the want position
942 float angle = vlen(wantdir - this.beam_dir) * RAD2DEG;
943 if (angle < 0.01) // snap only when very close so it's impossible to notice
944 this.beam_dir = wantdir; // snap otherwise vectors will never actually be the same
945 else
946 {
947 float max_blendfactor = 1;
948 if (angle && angle > WEP_CVAR(WEP_ARC, beam_maxangle))
949 max_blendfactor = WEP_CVAR(WEP_ARC, beam_maxangle) / angle;
950 float blendfactor = bound(0, (1 - (WEP_CVAR(WEP_ARC, beam_returnspeed) * dt)), max_blendfactor);
951 this.beam_dir = normalize((wantdir * (1 - blendfactor)) + (this.beam_dir * blendfactor));
952
953 // calculate how many segments are needed
954 float max_allowed_segments = ARC_MAX_SEGMENTS;
955 if (WEP_CVAR(WEP_ARC, beam_distancepersegment))
956 {
957 max_allowed_segments = 1 + (vlen(wantdir / WEP_CVAR(WEP_ARC, beam_distancepersegment)));
958 max_allowed_segments = bound(1, max_allowed_segments, ARC_MAX_SEGMENTS);
959 }
960 if (WEP_CVAR(WEP_ARC, beam_degreespersegment))
961 {
962 segments = min(angle, WEP_CVAR(WEP_ARC, beam_maxangle)) / WEP_CVAR(WEP_ARC, beam_degreespersegment);
963 segments = bound(1, segments, max_allowed_segments);
964 }
965 }
966 }
967
968 // set the beam direction which the rest of the code will refer to
969 beamdir = this.beam_dir;
970
971 // finally, set this.angles to the proper direction so that muzzle attachment points in proper direction
972 this.angles = fixedvectoangles2(forward, up); // TODO(Samual): is this == warpzone_save_view_angles?
973 }
974 else // if (!this.beam_usevieworigin)
975 {
977
978 // set the values from the provided info from the networked entity
979 start_pos = this.origin;
980 wantdir = this.v_angle;
981 beamdir = this.angles;
982
983 segments = 1;
984 if (beamdir != wantdir)
985 {
986 float angle = vlen(wantdir - beamdir) * RAD2DEG;
987
988 // calculate how many segments are needed
989 float max_allowed_segments = ARC_MAX_SEGMENTS;
990 if (WEP_CVAR(WEP_ARC, beam_distancepersegment))
991 {
992 max_allowed_segments = 1 + (vlen(wantdir / WEP_CVAR(WEP_ARC, beam_distancepersegment)));
993 max_allowed_segments = bound(1, max_allowed_segments, ARC_MAX_SEGMENTS);
994 }
995
996 if (WEP_CVAR(WEP_ARC, beam_degreespersegment))
997 {
998 segments = min(angle, WEP_CVAR(WEP_ARC, beam_maxangle)) / WEP_CVAR(WEP_ARC, beam_degreespersegment);
999 segments = bound(1, segments, max_allowed_segments);
1000 }
1001 }
1002 }
1003
1004 setorigin(this, start_pos);
1005 this.beam_muzzleentity.angles.z = random() * 360; // WEAPONTODO: use avelocity instead?
1006
1007 vector beam_endpos = start_pos + (beamdir * WEP_CVAR(WEP_ARC, beam_range));
1008 float beam_controlpoint_dist = WEP_CVAR(WEP_ARC, beam_range) * bound(0.001, 1 - WEP_CVAR(WEP_ARC, beam_tightness), 1);
1009 vector beam_controlpoint = start_pos + wantdir * beam_controlpoint_dist;
1010
1013 {
1017 }
1018
1019 vector last_origin = start_pos;
1020 vector original_start_pos = start_pos;
1021
1022 for (int i = 1; i <= segments; ++i)
1023 {
1024 // WEAPONTODO (client):
1025 // In order to do nice fading and pointing on the starting segment, we must always
1026 // have that drawn as a separate triangle... However, that is difficult to do when
1027 // keeping in mind the above problems and also optimizing the amount of segments
1028 // drawn on screen at any given time. (Automatic beam quality scaling, essentially)
1029
1030 vector new_origin = bezier_quadratic_getpoint(
1031 start_pos,
1032 beam_controlpoint,
1033 beam_endpos,
1034 i / segments
1035 );
1036
1038 last_origin,
1039 '0 0 0',
1040 '0 0 0',
1041 new_origin,
1043 NULL,
1044 NULL,
1046 );
1047
1048 last_origin = trace_endpos;
1049
1050 if (trace_fraction < 1)
1051 break; // hit something
1052
1053 // Do all the transforms for warpzones right now, as we already "are" in the post-trace
1054 // system (if we hit a player, that's always BEHIND the last passed wz).
1055 start_pos = WarpZone_TransformOrigin(WarpZone_trace_transform, start_pos);
1056 beam_controlpoint = WarpZone_TransformOrigin(WarpZone_trace_transform, beam_controlpoint);
1057 beam_endpos = WarpZone_TransformOrigin(WarpZone_trace_transform, beam_endpos);
1060 {
1063 }
1064 }
1065
1066 // visual effects for startpoint and endpoint
1069 this.beam_hiteffect,
1070 last_origin,
1072 dt * 2
1073 );
1074
1075 if (this.beam_hitlight[0])
1077 last_origin,
1078 this.beam_hitlight[0],
1079 vec3(
1080 this.beam_hitlight[1],
1081 this.beam_hitlight[2],
1082 this.beam_hitlight[3]
1083 )
1084 );
1085
1088 this.beam_muzzleeffect,
1089 original_start_pos + wantdir * 20,
1090 wantdir * 1000,
1091 dt * 0.1
1092 );
1093
1094 if (this.beam_muzzlelight[0])
1096 original_start_pos + wantdir * 20,
1097 this.beam_muzzlelight[0],
1098 vec3(
1099 this.beam_muzzlelight[1],
1100 this.beam_muzzlelight[2],
1101 this.beam_muzzlelight[3]
1102 )
1103 );
1104
1105 // cleanup
1108 {
1112 }
1113}
#define fixedvectoangles2
bool autocvar_cl_arcbeam_simple
Definition arc.qc:721
void Draw_ArcBeam_callback(vector start, vector hit, vector end)
Definition arc.qc:736
int beam_slot
Definition arc.qc:723
vector Draw_ArcBeam_callback_last_top
Definition arc.qh:164
vector beam_dir
Definition arc.qh:110
float beam_hitlight[4]
Definition arc.qh:151
const float ARC_MAX_SEGMENTS
Definition arc.qh:107
bool beam_initialized
Definition arc.qh:135
entity beam_hiteffect
Definition arc.qh:150
vector Draw_ArcBeam_callback_last_bottom
Definition arc.qh:165
entity Draw_ArcBeam_callback_entity
Definition arc.qh:162
float beam_usevieworigin
Definition arc.qh:158
entity beam_muzzleeffect
Definition arc.qh:152
float beam_muzzlelight[4]
Definition arc.qh:153
vector beam_shotorigin
Definition arc.qh:160
float Draw_ArcBeam_callback_last_thickness
Definition arc.qh:163
entity beam_muzzleentity
Definition arc.qh:156
var entity(vector mins, vector maxs,.entity tofield) findbox_tofield_OrFallback
entity csqcplayer
Definition cl_player.qh:26
float g_trueaim_minrange
Definition main.qh:171
vector view_forward
Definition main.qh:109
vector v_angle
Definition player.qh:236
const float MOVE_NOMONSTERS
float RAD2DEG
const float MASK_NORMAL
const float MOVE_NORMAL
vector view_angles
vector trace_endpos
float trace_dphitq3surfaceflags
vector origin
float trace_fraction
float Q3SURFACEFLAG_NOIMPACT
#define MAKE_VECTORS(angles, forward, right, up)
Same as the makevectors builtin but uses the provided locals instead of the v_* globals.
#define gettagindex
#define pointparticles(effect, org, vel, howmany)
Definition effect.qh:7
ent angles
Definition ent_cs.qc:146
void InterpolateOrigin_Do(entity this)
set origin based on iorigin1 (old pos), iorigin2 (desired pos), and time
vector warpzone_save_view_origin
Definition client.qh:8
vector warpzone_save_view_angles
Definition client.qh:9
void WarpZone_TraceBox_ThroughZone(vector org, vector mi, vector ma, vector end, float nomonsters, entity forent, entity zone, WarpZone_trace_callback_t cb)
Definition common.qc:192
void WarpZone_TraceLine(vector org, vector end, float nomonsters, entity forent)
Definition common.qc:328
vector WarpZone_TransformVelocity(entity wz, vector v)
Definition common.qc:491
vector WarpZone_UnTransformOrigin(entity wz, vector v)
Definition common.qc:519
vector WarpZone_TransformOrigin(entity wz, vector v)
Definition common.qc:486
entity WarpZone_trace_transform
Definition common.qh:40
float angle
Definition viewloc.qc:114
ERASEABLE vector bezier_quadratic_getpoint(vector a, vector b, vector c, float t)
Definition math.qh:114
float bound(float min, float value, float max)
float vlen(vector v)
float min(float f,...)
vector normalize(vector v)
float move_time
Definition movetypes.qh:81
#define NULL
Definition post.qh:14
#define gettaginfo
Definition post.qh:32
#define adddynamiclight
Definition post.qh:29
const vector eY
Definition vector.qh:44
#define vdist(v, cmp, f)
Vector distance comparison, avoids sqrt().
Definition vector.qh:8
const vector eX
Definition vector.qh:43
#define vec3(_x, _y, _z)
Definition vector.qh:100
int autocvar_chase_active
Definition view.qh:17
bool autocvar_r_drawviewmodel
Definition view.qh:97
bool autocvar_cl_lockview
Definition view.qh:20
entity viewmodels[MAX_WEAPONSLOTS]
Definition view.qh:108

References adddynamiclight, angle, angles, ARC_MAX_SEGMENTS, autocvar_chase_active, autocvar_cl_arcbeam_simple, autocvar_cl_lockview, autocvar_r_drawviewmodel, beam_dir, beam_hiteffect, beam_hitlight, beam_initialized, beam_muzzleeffect, beam_muzzleentity, beam_muzzlelight, beam_shotorigin, beam_slot, beam_usevieworigin, bezier_quadratic_getpoint(), bound(), csqcplayer, Draw_ArcBeam_callback(), Draw_ArcBeam_callback_entity, Draw_ArcBeam_callback_last_bottom, Draw_ArcBeam_callback_last_thickness, Draw_ArcBeam_callback_last_top, entity(), eX, eY, fixedvectoangles2, g_trueaim_minrange, gettagindex, gettaginfo, InterpolateOrigin_Do(), MAKE_VECTORS, MASK_NORMAL, min(), MOVE_NOMONSTERS, MOVE_NORMAL, move_time, normalize(), NULL, origin, pointparticles, Q3SURFACEFLAG_NOIMPACT, RAD2DEG, random(), time, trace_dphitq3surfaceflags, trace_endpos, trace_fraction, v_angle, vdist, vec3, vector, view_angles, view_forward, viewmodels, vlen(), warpzone_save_view_angles, warpzone_save_view_origin, WarpZone_trace_transform, WarpZone_TraceBox_ThroughZone(), WarpZone_TraceLine(), WarpZone_TransformOrigin(), WarpZone_TransformVelocity(), WarpZone_UnTransformOrigin(), and WEP_CVAR.

Referenced by NET_HANDLE().

◆ Draw_ArcBeam_callback()

void Draw_ArcBeam_callback ( vector start,
vector hit,
vector end )

Definition at line 736 of file arc.qc.

737{
740
741 vector hitorigin;
742 #if 0
743 if (trace_fraction != 1)
744 {
745 // calculate our own hit origin as trace_endpos tends to jump around annoyingly (to player origin?)
746 hitorigin = start + (Draw_ArcBeam_callback_new_dir * Draw_ArcBeam_callback_segmentdist * trace_fraction);
748 }
749 else
750 hitorigin = hit;
751 #else
752 hitorigin = hit;
753 #endif
754
755 float thickness = beam.beam_thickness;
756
758 Draw_CylindricLine(start, hit, thickness, beam.beam_image, 0.25, time * -3, beam.beam_color, beam.beam_alpha, DRAWFLAG_NORMAL, transformed_view_org);
759 else
760 {
761 // Thickdir shall be perpendicular to the beam and to the view-to-beam direction (WEAPONTODO: WHY)
762 // WEAPONTODO: Wouldn't it be better to be perpendicular to the beam and to the view FORWARD direction?
763 vector thickdir = normalize(cross(normalize(start - hit), transformed_view_org - start));
764
765 // draw primary beam render
766 vector top = hitorigin + (thickdir * thickness);
767 vector bottom = hitorigin - (thickdir * thickness);
768
771
772 // draw segment
773 R_BeginPolygon(beam.beam_image, DRAWFLAG_NORMAL, false); // DRAWFLAG_ADDITIVE
774 R_PolygonVertex(
775 top,
776 '0 0.5 0' + ('0 0.5 0' * (thickness / beam.beam_thickness)),
777 beam.beam_color,
778 beam.beam_alpha
779 );
780 R_PolygonVertex(
781 last_top,
782 '0 0.5 0' + ('0 0.5 0' * (Draw_ArcBeam_callback_last_thickness / beam.beam_thickness)),
783 beam.beam_color,
784 beam.beam_alpha
785 );
786 R_PolygonVertex(
787 last_bottom,
788 '0 0.5 0' * (1 - (Draw_ArcBeam_callback_last_thickness / beam.beam_thickness)),
789 beam.beam_color,
790 beam.beam_alpha
791 );
792 R_PolygonVertex(
793 bottom,
794 '0 0.5 0' * (1 - (thickness / beam.beam_thickness)),
795 beam.beam_color,
796 beam.beam_alpha
797 );
798 R_EndPolygon();
799
800 // set up for the next
804 }
805
806 // draw trailing particles
807 // NOTES:
808 // - Don't use spammy particle counts here, use a FEW small particles around the beam
809 // - We're not using WarpZone_TrailParticles here because we will handle warpzones ourselves.
810 if (beam.beam_traileffect)
811 trailparticles(beam, beam.beam_traileffect, start, hitorigin);
812}
vector view_origin
Definition main.qh:109
void Draw_CylindricLine(vector from, vector to, float thickness, string texture, float aspect, float shift, vector rgb, float theAlpha, float drawflag, vector vieworg)
Definition draw.qh:10
const float DRAWFLAG_NORMAL
#define trailparticles(e, effect, org, vel)
Definition effect.qh:9
#define cross(a, b)
Definition vector.qh:25

References autocvar_cl_arcbeam_simple, cross, Draw_ArcBeam_callback_entity, Draw_ArcBeam_callback_last_bottom, Draw_ArcBeam_callback_last_thickness, Draw_ArcBeam_callback_last_top, Draw_CylindricLine(), DRAWFLAG_NORMAL, entity(), normalize(), time, trace_fraction, trailparticles, vector, view_origin, WarpZone_trace_transform, WarpZone_TransformOrigin(), and WarpZone_UnTransformOrigin().

Referenced by Draw_ArcBeam().

◆ NET_HANDLE()

NET_HANDLE ( ENT_CLIENT_ARC_BEAM ,
bool isNew )

Definition at line 1121 of file arc.qc.

1122{
1123 int sf = ReadByte();
1124 int slot = ReadByte();
1125 entity flash;
1126
1127 this.beam_slot = slot;
1128
1129 if (isNew)
1130 {
1131 int gunalign = W_GunAlign(viewmodels[slot], STAT(GUNALIGN)) - 1;
1132
1133 this.beam_shotorigin = arc_shotorigin[gunalign]; // get a starting point
1134
1135 // set other main attributes of the beam
1136 this.draw = Draw_ArcBeam;
1137 IL_PUSH(g_drawables, this);
1138 this.entremove = Remove_ArcBeam;
1139 this.move_time = time;
1140 loopsound(this, CH_SHOTS_SINGLE, SND_ARC_LOOP, VOL_BASE, ATTEN_NORM);
1141
1142 flash = new(arc_flash);
1143 flash.owner = this;
1144 flash.effects = EF_ADDITIVE | EF_FULLBRIGHT;
1145 //flash.drawmask = MASK_NORMAL;
1146 flash.solid = SOLID_NOT;
1147 flash.avelocity.z = 5000;
1148 setattachment(flash, this, "");
1149 setorigin(flash, '0 0 0');
1150
1151 this.beam_muzzleentity = flash;
1152 }
1153 else
1154 flash = this.beam_muzzleentity;
1155
1156 if (sf & ARC_SF_UPDATE)
1157 {
1158 this.beam_usevieworigin = (ReadByte()) // drawlocal?
1159 ? (autocvar_chase_active ? 1 : 2)
1160 : 0;
1161
1162 this.sv_entnum = ReadByte();
1163 }
1164
1165 if (!this.beam_usevieworigin)
1166 {
1167 // this.iflags = IFLAG_ORIGIN | IFLAG_ANGLES | IFLAG_V_ANGLE; // why doesn't this work?
1168 this.iflags = IFLAG_ORIGIN;
1169
1171 }
1172
1173 if (sf & ARC_SF_START) // starting location
1174 this.origin = ReadVector();
1175 else if (this.beam_usevieworigin) // infer the location from player location
1176 {
1177 if (this.beam_usevieworigin == 2)
1178 {
1179 // use view origin
1180 this.origin = view_origin;
1181 }
1182 else
1183 {
1184 // use player origin so that third person display still works
1185 this.origin = entcs_receiver(player_localnum).origin + ('0 0 1' * STAT(VIEWHEIGHT));
1186 }
1187 }
1188
1189 setorigin(this, this.origin);
1190
1191 if (sf & ARC_SF_WANTDIR) // want/aim direction
1192 this.v_angle = ReadVector();
1193
1194 if (sf & ARC_SF_BEAMDIR) // beam direction
1195 this.angles = ReadAngleVector();
1196
1197 if (sf & ARC_SF_BEAMTYPE) // beam type
1198 {
1199 this.beam_type = ReadByte();
1200
1201 vector beamcolor = '1 1 1';
1203 beamcolor = colormapPaletteColor(entcs_GetClientColors(this.sv_entnum - 1) & 0x0F, true);
1204
1205 switch (this.beam_type)
1206 {
1207 case ARC_BT_MISS:
1208 this.beam_color = beamcolor;
1209 this.beam_alpha = 0.5;
1210 this.beam_thickness = 8;
1211 this.beam_traileffect = (EFFECT_ARC_BEAM);
1212 this.beam_hiteffect = (EFFECT_ARC_LIGHTNING);
1213 this.beam_hitlight[0] = 0;
1214 this.beam_hitlight[1] = 1;
1215 this.beam_hitlight[2] = 1;
1216 this.beam_hitlight[3] = 1;
1217 this.beam_muzzleeffect = EFFECT_Null;
1218 this.beam_muzzlelight[0] = 0;
1219 this.beam_muzzlelight[1] = 1;
1220 this.beam_muzzlelight[2] = 1;
1221 this.beam_muzzlelight[3] = 1;
1222 this.beam_image = "particles/lgbeam";
1224 {
1225 setmodel(flash, MDL_ARC_MUZZLEFLASH);
1226 flash.alpha = this.beam_alpha;
1227 flash.colormod = this.beam_color;
1228 flash.scale = 0.35;
1229 }
1230 break;
1231 case ARC_BT_WALL: // grenadelauncher_muzzleflash healray_muzzleflash
1232 this.beam_color = beamcolor;
1233 this.beam_alpha = 0.5;
1234 this.beam_thickness = 8;
1235 this.beam_traileffect = (EFFECT_ARC_BEAM);
1236 this.beam_hiteffect = (EFFECT_ARC_LIGHTNING);
1237 this.beam_hitlight[0] = 0;
1238 this.beam_hitlight[1] = 1;
1239 this.beam_hitlight[2] = 1;
1240 this.beam_hitlight[3] = 1;
1241 this.beam_muzzleeffect = EFFECT_Null; // (EFFECT_GRENADE_MUZZLEFLASH);
1242 this.beam_muzzlelight[0] = 0;
1243 this.beam_muzzlelight[1] = 1;
1244 this.beam_muzzlelight[2] = 1;
1245 this.beam_muzzlelight[3] = 1;
1246 this.beam_image = "particles/lgbeam";
1248 {
1249 setmodel(flash, MDL_ARC_MUZZLEFLASH);
1250 flash.alpha = this.beam_alpha;
1251 flash.colormod = this.beam_color;
1252 flash.scale = 0.35;
1253 }
1254 break;
1255 case ARC_BT_HEAL:
1256 this.beam_color = beamcolor;
1257 this.beam_alpha = 0.5;
1258 this.beam_thickness = 8;
1259 this.beam_traileffect = (EFFECT_ARC_BEAM_HEAL);
1260 this.beam_hiteffect = (EFFECT_ARC_BEAM_HEAL_IMPACT);
1261 this.beam_hitlight[0] = 0;
1262 this.beam_hitlight[1] = 1;
1263 this.beam_hitlight[2] = 1;
1264 this.beam_hitlight[3] = 1;
1265 this.beam_muzzleeffect = EFFECT_Null;
1266 this.beam_muzzlelight[0] = 0;
1267 this.beam_muzzlelight[1] = 1;
1268 this.beam_muzzlelight[2] = 1;
1269 this.beam_muzzlelight[3] = 1;
1270 this.beam_image = "particles/lgbeam";
1272 {
1273 setmodel(flash, MDL_ARC_MUZZLEFLASH);
1274 flash.alpha = this.beam_alpha;
1275 flash.colormod = this.beam_color;
1276 flash.scale = 0.35;
1277 }
1278 break;
1279 case ARC_BT_HIT:
1280 this.beam_color = beamcolor;
1281 this.beam_alpha = 0.5;
1282 this.beam_thickness = 8;
1283 this.beam_traileffect = (EFFECT_ARC_BEAM);
1284 this.beam_hiteffect = (EFFECT_ARC_LIGHTNING);
1285 this.beam_hitlight[0] = 20;
1286 this.beam_hitlight[1] = 1;
1287 this.beam_hitlight[2] = 0;
1288 this.beam_hitlight[3] = 0;
1289 this.beam_muzzleeffect = EFFECT_Null;
1290 this.beam_muzzlelight[0] = 50;
1291 this.beam_muzzlelight[1] = 1;
1292 this.beam_muzzlelight[2] = 0;
1293 this.beam_muzzlelight[3] = 0;
1294 this.beam_image = "particles/lgbeam";
1296 {
1297 setmodel(flash, MDL_ARC_MUZZLEFLASH);
1298 flash.alpha = this.beam_alpha;
1299 flash.colormod = this.beam_color;
1300 flash.scale = 0.35;
1301 }
1302 break;
1303 case ARC_BT_BURST_MISS:
1304 this.beam_color = beamcolor;
1305 this.beam_alpha = 0.5;
1306 this.beam_thickness = 14;
1307 this.beam_traileffect = (EFFECT_ARC_BEAM);
1308 this.beam_hiteffect = (EFFECT_ARC_LIGHTNING);
1309 this.beam_hitlight[0] = 0;
1310 this.beam_hitlight[1] = 1;
1311 this.beam_hitlight[2] = 1;
1312 this.beam_hitlight[3] = 1;
1313 this.beam_muzzleeffect = EFFECT_Null;
1314 this.beam_muzzlelight[0] = 0;
1315 this.beam_muzzlelight[1] = 1;
1316 this.beam_muzzlelight[2] = 1;
1317 this.beam_muzzlelight[3] = 1;
1318 this.beam_image = "particles/lgbeam";
1320 {
1321 setmodel(flash, MDL_ARC_MUZZLEFLASH);
1322 flash.alpha = this.beam_alpha;
1323 flash.colormod = this.beam_color;
1324 flash.scale = 0.35;
1325 }
1326 break;
1327 case ARC_BT_BURST_WALL:
1328 this.beam_color = beamcolor;
1329 this.beam_alpha = 0.5;
1330 this.beam_thickness = 14;
1331 this.beam_traileffect = (EFFECT_ARC_BEAM);
1332 this.beam_hiteffect = (EFFECT_ARC_LIGHTNING);
1333 this.beam_hitlight[0] = 0;
1334 this.beam_hitlight[1] = 1;
1335 this.beam_hitlight[2] = 1;
1336 this.beam_hitlight[3] = 1;
1337 this.beam_muzzleeffect = EFFECT_Null;
1338 this.beam_muzzlelight[0] = 0;
1339 this.beam_muzzlelight[1] = 1;
1340 this.beam_muzzlelight[2] = 1;
1341 this.beam_muzzlelight[3] = 1;
1342 this.beam_image = "particles/lgbeam";
1344 {
1345 setmodel(flash, MDL_ARC_MUZZLEFLASH);
1346 flash.alpha = this.beam_alpha;
1347 flash.colormod = this.beam_color;
1348 flash.scale = 0.35;
1349 }
1350 break;
1351 case ARC_BT_BURST_HEAL:
1352 this.beam_color = beamcolor;
1353 this.beam_alpha = 0.5;
1354 this.beam_thickness = 14;
1355 this.beam_traileffect = (EFFECT_ARC_BEAM_HEAL);
1356 this.beam_hiteffect = (EFFECT_ARC_BEAM_HEAL_IMPACT2);
1357 this.beam_hitlight[0] = 0;
1358 this.beam_hitlight[1] = 1;
1359 this.beam_hitlight[2] = 1;
1360 this.beam_hitlight[3] = 1;
1361 this.beam_muzzleeffect = EFFECT_Null;
1362 this.beam_muzzlelight[0] = 0;
1363 this.beam_muzzlelight[1] = 1;
1364 this.beam_muzzlelight[2] = 1;
1365 this.beam_muzzlelight[3] = 1;
1366 this.beam_image = "particles/lgbeam";
1368 {
1369 setmodel(flash, MDL_ARC_MUZZLEFLASH);
1370 flash.alpha = this.beam_alpha;
1371 flash.colormod = this.beam_color;
1372 flash.scale = 0.35;
1373 }
1374 break;
1375 case ARC_BT_BURST_HIT:
1376 this.beam_color = beamcolor;
1377 this.beam_alpha = 0.5;
1378 this.beam_thickness = 14;
1379 this.beam_traileffect = (EFFECT_ARC_BEAM);
1380 this.beam_hiteffect = (EFFECT_ARC_LIGHTNING);
1381 this.beam_hitlight[0] = 0;
1382 this.beam_hitlight[1] = 1;
1383 this.beam_hitlight[2] = 1;
1384 this.beam_hitlight[3] = 1;
1385 this.beam_muzzleeffect = EFFECT_Null;
1386 this.beam_muzzlelight[0] = 0;
1387 this.beam_muzzlelight[1] = 1;
1388 this.beam_muzzlelight[2] = 1;
1389 this.beam_muzzlelight[3] = 1;
1390 this.beam_image = "particles/lgbeam";
1392 {
1393 setmodel(flash, MDL_ARC_MUZZLEFLASH);
1394 flash.alpha = this.beam_alpha;
1395 flash.colormod = this.beam_color;
1396 flash.scale = 0.35;
1397 }
1398 break;
1399
1400 // shouldn't be possible, but lets make it colorful if it does :D
1401 default:
1402 this.beam_color = randomvec();
1403 this.beam_alpha = 1;
1404 this.beam_thickness = 8;
1405 this.beam_traileffect = NULL;
1406 this.beam_hiteffect = NULL;
1407 this.beam_hitlight[0] = 0;
1408 this.beam_hitlight[1] = 1;
1409 this.beam_hitlight[2] = 1;
1410 this.beam_hitlight[3] = 1;
1411 this.beam_muzzleeffect = EFFECT_Null;
1412 this.beam_muzzlelight[0] = 0;
1413 this.beam_muzzlelight[1] = 1;
1414 this.beam_muzzlelight[2] = 1;
1415 this.beam_muzzlelight[3] = 1;
1416 this.beam_image = "particles/lgbeam";
1418 {
1419 setmodel(flash, MDL_ARC_MUZZLEFLASH);
1420 flash.alpha = this.beam_alpha;
1421 flash.colormod = this.beam_color;
1422 flash.scale = 0.35;
1423 }
1424 break;
1425 }
1426 }
1427
1428 if (!this.beam_usevieworigin)
1430
1431 return true;
1432}
void Remove_ArcBeam(entity this)
Definition arc.qc:1115
void Draw_ArcBeam(entity this)
Definition arc.qc:823
const int ARC_BT_HEAL
Definition arc.qh:116
const int ARC_SF_UPDATE
Definition arc.qh:124
const int ARC_BT_HIT
Definition arc.qh:117
const int ARC_SF_WANTDIR
Definition arc.qh:126
const int ARC_SF_BEAMDIR
Definition arc.qh:127
int beam_type
Definition arc.qh:112
vector arc_shotorigin[4]
Definition arc.qh:108
const int ARC_BT_WALL
Definition arc.qh:115
const int ARC_SF_BEAMTYPE
Definition arc.qh:128
entity beam_traileffect
Definition arc.qh:149
const int ARC_BT_BURST_HEAL
Definition arc.qh:120
float beam_thickness
Definition arc.qh:148
const int ARC_BT_MISS
Definition arc.qh:114
const int ARC_BT_BURST_MISS
Definition arc.qh:118
string beam_image
Definition arc.qh:154
const int ARC_BT_BURST_WALL
Definition arc.qh:119
const int ARC_BT_BURST_HIT
Definition arc.qh:121
const int ARC_SF_START
Definition arc.qh:125
float beam_alpha
Definition arc.qh:147
int W_GunAlign(entity this, int preferred_align)
IntrusiveList g_drawables
Definition main.qh:91
int sv_entnum
Definition main.qh:186
#define colormapPaletteColor(c, isPants)
Definition color.qh:5
#define setmodel(this, m)
Definition model.qh:26
float player_localnum
const float EF_ADDITIVE
const float EF_FULLBRIGHT
const float SOLID_NOT
#define entcs_receiver(...)
Definition ent_cs.qh:61
int entcs_GetClientColors(int i)
Definition ent_cs.qh:111
void InterpolateOrigin_Undo(entity this)
snap origin to iorigin2 (actual origin)
void InterpolateOrigin_Note(entity this)
const int IFLAG_ORIGIN
int iflags
ERASEABLE entity IL_PUSH(IntrusiveList this, entity it)
Push to tail.
vector beam_color
Definition laser.qh:30
#define ReadVector()
Definition net.qh:349
#define ReadAngleVector()
Definition net.qh:351
int ReadByte()
#define STAT(...)
Definition stats.qh:94
vector randomvec(void)
void loopsound(entity e, int ch, Sound samp, float vol, float attn)
bool teamplay
Definition teams.qh:59
int autocvar_cl_tracers_teamcolor
Definition weapon.qh:249

References angles, ARC_BT_BURST_HEAL, ARC_BT_BURST_HIT, ARC_BT_BURST_MISS, ARC_BT_BURST_WALL, ARC_BT_HEAL, ARC_BT_HIT, ARC_BT_MISS, ARC_BT_WALL, ARC_SF_BEAMDIR, ARC_SF_BEAMTYPE, ARC_SF_START, ARC_SF_UPDATE, ARC_SF_WANTDIR, arc_shotorigin, ATTEN_NORM, autocvar_chase_active, autocvar_cl_tracers_teamcolor, autocvar_r_drawviewmodel, beam_alpha, beam_color, beam_hiteffect, beam_hitlight, beam_image, beam_muzzleeffect, beam_muzzleentity, beam_muzzlelight, beam_shotorigin, beam_slot, beam_thickness, beam_traileffect, beam_type, beam_usevieworigin, CH_SHOTS_SINGLE, colormapPaletteColor, Draw_ArcBeam(), EF_ADDITIVE, EF_FULLBRIGHT, entcs_GetClientColors(), entcs_receiver, entity(), g_drawables, IFLAG_ORIGIN, iflags, IL_PUSH(), InterpolateOrigin_Note(), InterpolateOrigin_Undo(), loopsound(), move_time, NULL, origin, player_localnum, randomvec(), ReadAngleVector, ReadByte(), ReadVector, Remove_ArcBeam(), setmodel, SOLID_NOT, STAT, sv_entnum, teamplay, time, v_angle, vector, view_origin, viewmodels, VOL_BASE, and W_GunAlign().

◆ Remove_ArcBeam()

void Remove_ArcBeam ( entity this)

Definition at line 1115 of file arc.qc.

1116{
1117 delete(this.beam_muzzleentity);
1118 sound(this, CH_SHOTS_SINGLE, SND_Null, VOL_BASE, ATTEN_NORM);
1119}

References ATTEN_NORM, beam_muzzleentity, CH_SHOTS_SINGLE, entity(), sound, and VOL_BASE.

Referenced by NET_HANDLE().

◆ Reset_ArcBeam() [1/2]

void Reset_ArcBeam ( )

Definition at line 814 of file arc.qc.

815{
816 entity e;
817 for (e = NULL; (e = findfloat(e, beam_usevieworigin, 1)); )
818 e.beam_initialized = false;
819 for (e = NULL; (e = findfloat(e, beam_usevieworigin, 2)); )
820 e.beam_initialized = false;
821}
entity findfloat(entity start,.float field, float match)

References beam_usevieworigin, entity(), findfloat(), and NULL.

Referenced by CSQCModel_Effects_PostUpdate(), TeleportPlayer(), and WarpZone_PostTeleportPlayer_Callback().

◆ Reset_ArcBeam() [2/2]

void Reset_ArcBeam ( entity player,
vector forward )

Definition at line 43 of file arc.qc.

44{
45 for (int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
46 {
47 .entity weaponentity = weaponentities[slot];
48 if (!player.(weaponentity).arc_beam)
49 continue;
50 player.(weaponentity).arc_beam.beam_dir = forward;
51 player.(weaponentity).arc_beam.beam_teleporttime = time;
52 }
53}
const int MAX_WEAPONSLOTS
Definition weapon.qh:16
entity weaponentities[MAX_WEAPONSLOTS]
Definition weapon.qh:17

References arc_beam, entity(), MAX_WEAPONSLOTS, time, vector, and weaponentities.

◆ W_Arc_Attack()

void W_Arc_Attack ( Weapon thiswep,
entity actor,
.entity weaponentity,
int fire )

Definition at line 498 of file arc.qc.

499{
500 if (!actor.(weaponentity).arc_beam || wasfreed(actor.(weaponentity).arc_beam))
501 {
502 w_ready(thiswep, actor, weaponentity, fire);
503 return;
504 }
505
506 // attack handled by the beam itself, this is just a loop to keep the attack happening!
507
508 // NOTE: arc doesn't use a refire
509 //ATTACK_FINISHED(actor, weaponentity) = time + WEP_CVAR_PRI(WEP_ARC, refire) * W_WeaponRateFactor(actor);
510 actor.(weaponentity).wframe = WFRAME_FIRE1;
511 weapon_thinkf(actor, weaponentity, WFRAME_DONTCHANGE, WEP_CVAR(WEP_ARC, beam_animtime), W_Arc_Attack);
512}
void W_Arc_Attack(Weapon thiswep, entity actor,.entity weaponentity, int fire)
Definition arc.qc:498
WFRAME wframe
Definition all.qh:439
void weapon_thinkf(entity actor,.entity weaponentity, WFRAME fr, float t, void(Weapon thiswep, entity actor,.entity weaponentity, int fire) func)
void w_ready(Weapon thiswep, entity actor,.entity weaponentity, int fire)

References entity(), W_Arc_Attack(), w_ready(), weapon_thinkf(), WEP_CVAR, and wframe.

Referenced by W_Arc_Attack().

◆ W_Arc_Attack_Bolt()

void W_Arc_Attack_Bolt ( Weapon thiswep,
entity actor,
.entity weaponentity,
int fire )

Definition at line 142 of file arc.qc.

143{
144 W_SetupShot(actor, weaponentity, false, 2, SND_ARC_BOLT_FIRE, CH_WEAPON_A, WEP_CVAR(WEP_ARC, bolt_damage), thiswep.m_id | HITTYPE_SECONDARY);
145
146 W_MuzzleFlash(thiswep, actor, weaponentity, w_shotorg, w_shotdir);
147
148 entity missile = new(missile);
149 missile.owner = missile.realowner = actor;
150 missile.bot_dodge = true;
151 IL_PUSH(g_bot_dodge, missile);
152 missile.bot_dodgerating = WEP_CVAR(WEP_ARC, bolt_damage);
153
154 missile.takedamage = DAMAGE_YES;
155 SetResourceExplicit(missile, RES_HEALTH, WEP_CVAR(WEP_ARC, bolt_health));
156 missile.damageforcescale = WEP_CVAR(WEP_ARC, bolt_damageforcescale);
157 missile.event_damage = W_Arc_Bolt_Damage;
158 missile.damagedbycontents = true;
160
161 settouch(missile, W_Arc_Bolt_Touch);
162 missile.cnt = 0;
163 missile.use = W_Arc_Bolt_Explode_use;
165 missile.nextthink = time + WEP_CVAR(WEP_ARC, bolt_lifetime);
166 PROJECTILE_MAKETRIGGER(missile);
167 missile.projectiledeathtype = thiswep.m_id | HITTYPE_SECONDARY;
168 missile.weaponentity_fld = weaponentity;
169 setorigin(missile, w_shotorg);
170 setsize(missile, '0 0 0', '0 0 0');
171
173 W_SetupProjVelocity_PRE(missile, WEP_ARC, bolt_);
174
175 missile.angles = vectoangles(missile.velocity);
176 missile.flags = FL_PROJECTILE;
177 IL_PUSH(g_projectiles, missile);
178 missile.missile_flags = MIF_SPLASH;
179
180 CSQCProjectile(missile, true, PROJECTILE_ARC_BOLT, true);
181
182 MUTATOR_CALLHOOK(EditProjectile, actor, missile);
183
184 ++actor.(weaponentity).misc_bulletcounter;
185 if (actor.(weaponentity).misc_bulletcounter == 0)
186 {
187 ATTACK_FINISHED(actor, weaponentity) = time + WEP_CVAR(WEP_ARC, bolt_refire2) * W_WeaponRateFactor(actor);
188 weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR(WEP_ARC, bolt_refire), w_ready);
189 }
190 else
191 weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR(WEP_ARC, bolt_refire), W_Arc_Attack_Bolt);
192}
IntrusiveList g_bot_dodge
Definition api.qh:150
void W_Arc_Bolt_Damage(entity this, entity inflictor, entity attacker, float damage, int deathtype,.entity weaponentity, vector hitloc, vector force)
Definition arc.qc:99
void W_Arc_Attack_Bolt(Weapon thiswep, entity actor,.entity weaponentity, int fire)
Definition arc.qc:142
void W_Arc_Bolt_Explode_use(entity this, entity actor, entity trigger)
Definition arc.qc:94
void W_Arc_Bolt_Touch(entity this, entity toucher)
Definition arc.qc:113
#define MUTATOR_CALLHOOK(id,...)
Definition base.qh:143
int m_id
Definition weapon.qh:43
float W_WeaponRateFactor(entity this)
const int FL_PROJECTILE
Definition constants.qh:85
void CSQCProjectile(entity e, float clientanimate, int type, float docull)
IntrusiveList g_damagedbycontents
Definition damage.qh:143
const int HITTYPE_SECONDARY
Definition all.qh:31
SetResourceExplicit(ent, RES_ARMOR, ReadByte() *DEC_FACTOR)) ENTCS_PROP(NAME
vector vectoangles(vector v)
void set_movetype(entity this, int mt)
Definition movetypes.qc:4
const int MOVETYPE_BOUNCEMISSILE
Definition movetypes.qh:144
const int PROJECTILE_ARC_BOLT
#define setthink(e, f)
#define settouch(e, f)
Definition self.qh:77
void adaptor_think2use_hittype_splash(entity this)
Definition common.qc:106
const int MIF_SPLASH
Definition common.qh:46
IntrusiveList g_projectiles
Definition common.qh:58
#define PROJECTILE_MAKETRIGGER(e)
Definition common.qh:34
float misc_bulletcounter
Definition common.qh:19
const int CH_WEAPON_A
Definition sound.qh:7
const int DAMAGE_YES
Definition subs.qh:80
#define W_SetupProjVelocity_PRE(ent, wep, prefix)
Definition tracing.qh:65
#define W_SetupShot(ent, wepent, antilag, recoil, snd, chan, maxdamage, deathtype)
Definition tracing.qh:34
void W_MuzzleFlash(Weapon thiswep, entity actor,.entity weaponentity, vector shotorg, vector shotdir)
Definition all.qc:715
#define ATTACK_FINISHED(ent, w)

References adaptor_think2use_hittype_splash(), ATTACK_FINISHED, CH_WEAPON_A, CSQCProjectile(), DAMAGE_YES, entity(), FL_PROJECTILE, g_bot_dodge, g_damagedbycontents, g_projectiles, HITTYPE_SECONDARY, IL_PUSH(), Weapon::m_id, MIF_SPLASH, misc_bulletcounter, MOVETYPE_BOUNCEMISSILE, MUTATOR_CALLHOOK, PROJECTILE_ARC_BOLT, PROJECTILE_MAKETRIGGER, set_movetype(), SetResourceExplicit(), setthink, settouch, time, vectoangles(), W_Arc_Attack_Bolt(), W_Arc_Bolt_Damage(), W_Arc_Bolt_Explode_use(), W_Arc_Bolt_Touch(), W_MuzzleFlash(), w_ready(), W_SetupProjVelocity_PRE, W_SetupShot, w_shotdir, w_shotorg, W_WeaponRateFactor(), weapon_thinkf(), and WEP_CVAR.

Referenced by W_Arc_Attack_Bolt().

◆ W_Arc_Beam()

void W_Arc_Beam ( bool burst,
entity actor,
.entity weaponentity )

Definition at line 478 of file arc.qc.

479{
480 // only play fire sound if 1 sec has passed since player let go the fire button
481 if (time - actor.(weaponentity).beam_prev > 1)
482 sound(actor, CH_WEAPON_A, SND_ARC_FIRE, VOL_BASE, ATTN_NORM);
483
484 entity beam = actor.(weaponentity).arc_beam = new(W_Arc_Beam);
485 beam.weaponentity_fld = weaponentity;
486 beam.solid = SOLID_NOT;
488 beam.owner = actor;
490 beam.bot_dodge = true;
491 IL_PUSH(g_bot_dodge, beam);
492 beam.bot_dodgerating = WEP_CVAR(WEP_ARC, beam_damage);
493 beam.beam_bursting = boolean(burst);
494 Net_LinkEntity(beam, false, 0, W_Arc_Beam_Send);
495
496 getthink(beam)(beam);
497}
void W_Arc_Beam(bool burst, entity actor,.entity weaponentity)
Definition arc.qc:478
bool W_Arc_Beam_Send(entity this, entity to, int sf)
Definition arc.qc:7
void W_Arc_Beam_Think(entity this)
Definition arc.qc:194
#define boolean(value)
Definition bool.qh:9
void Net_LinkEntity(entity e, bool docull, float dt, bool(entity this, entity to, int sendflags) sendfunc)
Definition net.qh:167
const int MOVETYPE_NONE
Definition movetypes.qh:133
#define getthink(e)

References arc_beam, ATTN_NORM, boolean, CH_WEAPON_A, entity(), g_bot_dodge, getthink, IL_PUSH(), MOVETYPE_NONE, Net_LinkEntity(), set_movetype(), setthink, SOLID_NOT, sound, time, VOL_BASE, W_Arc_Beam(), W_Arc_Beam_Send(), W_Arc_Beam_Think(), and WEP_CVAR.

Referenced by W_Arc_Beam().

◆ W_Arc_Beam_Send()

bool W_Arc_Beam_Send ( entity this,
entity to,
int sf )

Definition at line 7 of file arc.qc.

8{
9 WriteHeader(MSG_ENTITY, ENT_CLIENT_ARC_BEAM);
10
11 // Truncate information when this beam is displayed to the owner client
12 // - The owner client has no use for beam start position or directions,
13 // it always figures this information out for itself with csqc code.
14 // - Spectating the owner also truncates this information.
15 bool drawlocal = (to == this.owner || (to.enemy == this.owner && IS_SPEC(to)));
16 if (drawlocal)
18
21
22 if (sf & ARC_SF_UPDATE)
23 {
24 WriteByte(MSG_ENTITY, drawlocal);
26 }
27
28 if (sf & ARC_SF_START) // starting location
29 WriteVector(MSG_ENTITY, this.beam_start);
30
31 if (sf & ARC_SF_WANTDIR) // want/aim direction
32 WriteVector(MSG_ENTITY, this.beam_wantdir);
33
34 if (sf & ARC_SF_BEAMDIR) // beam direction
35 WriteAngleVector(MSG_ENTITY, this.beam_dir);
36
37 if (sf & ARC_SF_BEAMTYPE) // beam type
39
40 return true;
41}
const int ARC_SF_LOCALMASK
Definition arc.qh:129
vector beam_wantdir
Definition arc.qh:111
vector beam_start
Definition arc.qh:109
entity owner
Definition main.qh:87
WriteByte(chan, ent.angles.y/DEC_FACTOR)
const int MSG_ENTITY
Definition net.qh:156
#define WriteHeader(to, id)
Definition net.qh:265
#define etof(e)
Definition misc.qh:25
#define IS_SPEC(v)
Definition utils.qh:10
int weaponslot(.entity weaponentity)
Definition weapon.qh:19
entity weaponentity_fld

References ARC_SF_BEAMDIR, ARC_SF_BEAMTYPE, ARC_SF_LOCALMASK, ARC_SF_START, ARC_SF_UPDATE, ARC_SF_WANTDIR, beam_dir, beam_start, beam_type, beam_wantdir, entity(), etof, IS_SPEC, MSG_ENTITY, owner, weaponentity_fld, weaponslot(), WriteByte(), and WriteHeader.

Referenced by W_Arc_Beam().

◆ W_Arc_Beam_Think()

void W_Arc_Beam_Think ( entity this)

Definition at line 194 of file arc.qc.

195{
196 .entity weaponentity = this.weaponentity_fld;
197 entity own = this.owner;
198 if (this != own.(weaponentity).arc_beam)
199 {
200 delete(this);
201 return;
202 }
203
204 int burst;
205 if ((PHYS_INPUT_BUTTON_ATCK2(own) && !WEP_CVAR(WEP_ARC, bolt)) || this.beam_bursting)
206 {
207 if (!this.beam_bursting)
208 this.beam_bursting = true;
209 burst = ARC_BT_BURSTMASK;
210 }
211 else
212 burst = 0;
213
214 Weapon thiswep = WEP_ARC;
215
216 // TODO: use standard weapon use checks here!
217 if (!IS_PLAYER(own) || IS_DEAD(own) || STAT(FROZEN, own) || game_stopped || own.vehicle
218 || !weapon_prepareattack_check(thiswep, own, weaponentity, this.beam_bursting, -1)
219 || own.(weaponentity).m_switchweapon != WEP_ARC
220 || (!PHYS_INPUT_BUTTON_ATCK(own) && !burst)
221 || (WEP_CVAR(WEP_ARC, overheat_max) > 0 && this.beam_heat >= WEP_CVAR(WEP_ARC, overheat_max)))
222 {
223 if (WEP_CVAR(WEP_ARC, cooldown) > 0)
224 {
225 float cooldown_speed;
226 if (this.beam_heat > WEP_CVAR(WEP_ARC, overheat_min) && WEP_CVAR(WEP_ARC, cooldown) > 0)
227 cooldown_speed = WEP_CVAR(WEP_ARC, cooldown);
228 else if (!burst)
229 cooldown_speed = this.beam_heat / WEP_CVAR(WEP_ARC, beam_refire);
230 else
231 cooldown_speed = 0;
232
233 bool overheat = (WEP_CVAR(WEP_ARC, overheat_max) > 0 && this.beam_heat >= WEP_CVAR(WEP_ARC, overheat_max));
234 if (overheat)
235 {
236 Send_Effect(EFFECT_ARC_OVERHEAT, this.beam_start, this.beam_wantdir, 1);
237 sound(this, CH_WEAPON_A, SND_ARC_STOP, VOL_BASE, ATTN_NORM);
238 }
239
240 if (cooldown_speed)
241 {
242 if (WEP_CVAR(WEP_ARC, cooldown_release) || overheat)
243 own.arc_overheat = time + this.beam_heat / cooldown_speed;
244 own.arc_cooldown = cooldown_speed;
245 }
246 }
247
248 if (this == own.(weaponentity).arc_beam)
249 own.(weaponentity).arc_beam = NULL;
250 if (!thiswep.wr_checkammo1(thiswep, own, weaponentity) && !(own.items & IT_UNLIMITED_AMMO))
251 {
252 // NOTE: this doesn't force the switch
253 W_SwitchToOtherWeapon(own, weaponentity);
254 }
255 own.(weaponentity).arc_BUTTON_ATCK_prev = false; // allow switching weapons
256 delete(this);
257 return;
258 }
259
260 // decrease ammo
261 float coefficient = frametime;
262 if (!(own.items & IT_UNLIMITED_AMMO))
263 {
264 float rootammo = (burst ? WEP_CVAR(WEP_ARC, burst_ammo) : WEP_CVAR(WEP_ARC, beam_ammo));
265 if (rootammo)
266 {
267 float curr_ammo = GetResource(own, thiswep.ammo_type);
268 coefficient = min(coefficient, curr_ammo / rootammo);
269 SetResource(own, thiswep.ammo_type, max(0, curr_ammo - rootammo * frametime));
270 }
271 }
272
273 float heat_speed = (burst ? WEP_CVAR(WEP_ARC, burst_heat) : WEP_CVAR(WEP_ARC, beam_heat));
274 this.beam_heat = min(WEP_CVAR(WEP_ARC, overheat_max), this.beam_heat + heat_speed * frametime);
275
276 makevectors(own.v_angle);
277
279 own,
280 weaponentity,
281 true,
282 0,
283 SND_Null,
284 0,
285 WEP_CVAR(WEP_ARC, beam_damage) * coefficient,
286 WEP_CVAR(WEP_ARC, beam_range),
287 thiswep.m_id
288 );
289
290 // After teleport, "lock" the beam until the teleport is confirmed.
291 if (time < this.beam_teleporttime + ANTILAG_LATENCY(own))
292 w_shotdir = this.beam_dir;
293
294 // network information: shot origin and want/aim direction
295 if (this.beam_start != w_shotorg)
296 {
297 this.SendFlags |= ARC_SF_START;
298 this.beam_start = w_shotorg;
299 }
300 if (this.beam_wantdir != w_shotdir)
301 {
303 this.beam_wantdir = w_shotdir;
304 }
305
306 if (!this.beam_initialized)
307 {
308 this.beam_dir = w_shotdir;
309 this.beam_initialized = true;
310 }
311
312 // WEAPONTODO: Detect player velocity so that the beam curves when moving too
313 // idea: blend together this.beam_dir with the inverted direction the player is moving in
314 // might have to make some special accomodation so that it only uses view_right and view_up
315
316 // note that if we do this, it'll always be corrected to a maximum angle by beam_maxangle handling
317
318 float segments = 1;
319 if (this.beam_dir != w_shotdir)
320 {
321 // calculate how much we're going to move the end of the beam to the want position
322 float angle = vlen(w_shotdir - this.beam_dir) * RAD2DEG;
323 if (angle < 0.01) // snap only when very close so it's impossible to notice
324 this.beam_dir = w_shotdir; // snap otherwise vectors will never actually be the same
325 else
326 {
327 float max_blendfactor = 1;
328 if (angle && angle > WEP_CVAR(WEP_ARC, beam_maxangle))
329 max_blendfactor = WEP_CVAR(WEP_ARC, beam_maxangle) / angle;
330 float blendfactor = bound(0, (1 - (WEP_CVAR(WEP_ARC, beam_returnspeed) * frametime)), max_blendfactor);
331 this.beam_dir = normalize((w_shotdir * (1 - blendfactor)) + (this.beam_dir * blendfactor));
332 }
333
334 // network information: beam direction
336
337 // calculate how many segments are needed
338 float max_allowed_segments = ARC_MAX_SEGMENTS;
339 if (WEP_CVAR(WEP_ARC, beam_distancepersegment))
340 {
341 max_allowed_segments = 1 + vlen(w_shotdir) / WEP_CVAR(WEP_ARC, beam_distancepersegment);
342 max_allowed_segments = bound(1, max_allowed_segments, ARC_MAX_SEGMENTS);
343 }
344
345 if (WEP_CVAR(WEP_ARC, beam_degreespersegment))
346 {
347 segments = min(angle, WEP_CVAR(WEP_ARC, beam_maxangle)) / WEP_CVAR(WEP_ARC, beam_degreespersegment);
348 segments = bound(1, segments, max_allowed_segments);
349 }
350 }
351
352 vector beam_endpos = w_shotorg + (this.beam_dir * WEP_CVAR(WEP_ARC, beam_range));
353 float beam_controlpoint_dist = WEP_CVAR(WEP_ARC, beam_range) * bound(0.001, 1 - WEP_CVAR(WEP_ARC, beam_tightness), 1);
354 vector beam_controlpoint = w_shotorg + w_shotdir * beam_controlpoint_dist;
355
356 int new_beam_type = 0;
357 vector last_origin = w_shotorg;
358 vector original_start_pos = w_shotorg;
359 vector last_origin_prev = '0 0 0';
360 for (int i = 1; i <= segments; ++i)
361 {
362 // WEAPONTODO (client):
363 // In order to do nice fading and pointing on the starting segment, we must always
364 // have that drawn as a separate triangle... However, that is difficult to do when
365 // keeping in mind the above problems and also optimizing the amount of segments
366 // drawn on screen at any given time. (Automatic beam quality scaling, essentially)
367
369 w_shotorg,
370 beam_controlpoint,
371 beam_endpos,
372 i / segments
373 );
374
376 own,
377 last_origin,
378 new_origin,
380 NULL,
381 ANTILAG_LATENCY(own)
382 );
383
384 last_origin_prev = last_origin; // used later to calculate damage force direction
385 last_origin = trace_endpos;
386
387 // Do all the transforms for warpzones right now, as we already "are" in the post-trace
388 // system (if we hit a player, that's always BEHIND the last passed wz).
390
391 if (trace_fraction == 1)
392 {
393 beam_controlpoint = WarpZone_TransformOrigin(WarpZone_trace_transform, beam_controlpoint);
394 beam_endpos = WarpZone_TransformOrigin(WarpZone_trace_transform, beam_endpos);
395 continue;
396 }
397
398 if (!trace_ent)
399 {
400 // we collided with geometry
401 new_beam_type = ARC_BT_WALL;
402 break;
403 }
404
405 // we collided with an entity
406 bool is_player = (IS_PLAYER(trace_ent) || trace_ent.classname == "body" || IS_MONSTER(trace_ent));
407 if (trace_ent != own && SAME_TEAM(own, trace_ent))
408 {
409 float roothealth = (burst ? WEP_CVAR(WEP_ARC, burst_healing_hps) : WEP_CVAR(WEP_ARC, beam_healing_hps));
410 float rootarmor = (burst ? WEP_CVAR(WEP_ARC, burst_healing_aps) : WEP_CVAR(WEP_ARC, beam_healing_aps));
411 float hplimit = (IS_PLAYER(trace_ent) ? WEP_CVAR(WEP_ARC, beam_healing_hmax) : RES_LIMIT_NONE);
412 Heal(trace_ent, own, (roothealth * coefficient), hplimit);
413 if (IS_PLAYER(trace_ent) && rootarmor
414 && GetResource(trace_ent, RES_ARMOR) <= WEP_CVAR(WEP_ARC, beam_healing_amax))
415 {
416 GiveResourceWithLimit(trace_ent, RES_ARMOR, (rootarmor * coefficient), WEP_CVAR(WEP_ARC, beam_healing_amax));
417 trace_ent.pauserotarmor_finished = max(trace_ent.pauserotarmor_finished, time + autocvar_g_balance_pause_armor_rot);
418 }
419 if (roothealth || rootarmor)
420 new_beam_type = ARC_BT_HEAL;
421 }
422 else if (trace_ent.takedamage && (is_player || WEP_CVAR(WEP_ARC, beam_nonplayerdamage)))
423 {
424 // calculate our own hit origin as trace_endpos tends to jump around annoyingly (to player origin?)
425 // NO. trace_endpos should be just fine. If not,
426 // that's an engine bug that needs proper debugging.
427 vector hitorigin = trace_endpos;
428 float falloff = 1;
429 if (WEP_CVAR(WEP_ARC, beam_falloff_halflifedist))
431 WEP_CVAR(WEP_ARC, beam_falloff_mindist),
432 WEP_CVAR(WEP_ARC, beam_falloff_maxdist),
433 WEP_CVAR(WEP_ARC, beam_falloff_halflifedist),
434 vlen(WarpZone_UnTransformOrigin(WarpZone_trace_transform, hitorigin) - original_start_pos)
435 );
436
437 float damage;
438 if (is_player)
439 {
440 if (burst)
441 damage = WEP_CVAR(WEP_ARC, burst_damage);
442 else
443 damage = WEP_CVAR(WEP_ARC, beam_damage);
444 }
445 else
446 damage = WEP_CVAR(WEP_ARC, beam_nonplayerdamage);
447 damage *= coefficient * falloff;
448
450 accuracy_add(own, WEP_ARC, 0, damage, 0); // add to hit
451
452 vector new_dir = normalize(new_origin - last_origin_prev);
454 float force = WEP_CVAR(WEP_ARC, beam_force) * coefficient * falloff;
455 Damage(trace_ent, own, own, damage, WEP_ARC.m_id, weaponentity, hitorigin, force * new_dir);
456
457 new_beam_type = ARC_BT_HIT;
458 }
459 break;
460 }
461
462 // te_explosion(trace_endpos);
463
464 // if we're bursting, use burst visual effects
465 new_beam_type |= burst;
466
467 // network information: beam type
468 if (new_beam_type != this.beam_type)
469 {
471 this.beam_type = new_beam_type;
472 }
473
474 own.(weaponentity).beam_prev = time;
475 this.nextthink = time;
476}
void accuracy_add(entity this, Weapon w, float fired, float hit, float real)
update accuracy stats
Definition accuracy.qc:102
bool accuracy_isgooddamage(entity attacker, entity targ)
does this damage count towards accuracy stats?
Definition accuracy.qc:133
void WarpZone_traceline_antilag(entity source, vector v1, vector v2, float nomonst, entity forent, float lag)
Definition antilag.qc:221
#define ANTILAG_LATENCY(e)
Definition antilag.qh:19
float beam_teleporttime
Definition arc.qh:137
float beam_heat
Definition arc.qh:138
bool arc_BUTTON_ATCK_prev
Definition arc.qh:133
bool beam_bursting
Definition arc.qh:136
float beam_prev
Definition arc.qh:134
const int ARC_BT_BURSTMASK
Definition arc.qh:122
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.
fields which are explicitly/manually set are marked with "M", fields set automatically are marked wit...
Definition weapon.qh:42
Resource ammo_type
M: ammotype : main ammo type.
Definition weapon.qh:56
virtual void wr_checkammo1()
(SERVER) checks ammo for weapon primary
Definition weapon.qh:100
const int IT_UNLIMITED_AMMO
Definition item.qh:23
int falloff
Definition impulse.qh:12
#define IS_DEAD(s)
Definition player.qh:244
#define IS_PLAYER(s)
Definition player.qh:242
float game_stopped
Definition stats.qh:81
entity trace_ent
float nextthink
void Damage(entity targ, entity inflictor, entity attacker, float damage, int deathtype,.entity weaponentity, vector hitloc, vector force)
Definition damage.qc:493
bool Heal(entity targ, entity inflictor, float amount, float limit)
Definition damage.qc:957
RES_ARMOR
Definition ent_cs.qc:155
int SendFlags
Definition net.qh:159
ERASEABLE float ExponentialFalloff(float mindist, float maxdist, float halflifedist, float d)
Definition math.qh:247
float max(float f,...)
const int RES_LIMIT_NONE
Definition resources.qh:60
void W_SwitchToOtherWeapon(entity this,.entity weaponentity)
Perform weapon to attack (weaponstate and attack_finished check is here).
Definition selection.qc:247
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 SAME_TEAM(a, b)
Definition teams.qh:241
#define W_SetupShot_Range(ent, wepent, antilag, recoil, snd, chan, maxdamage, range, deathtype)
Definition tracing.qh:36
#define IS_MONSTER(v)
Definition utils.qh:23
bool weapon_prepareattack_check(Weapon thiswep, entity actor,.entity weaponentity, bool secondary, float attacktime)

References accuracy_add(), accuracy_isgooddamage(), Weapon::ammo_type, angle, ANTILAG_LATENCY, arc_beam, ARC_BT_BURSTMASK, ARC_BT_HEAL, ARC_BT_HIT, ARC_BT_WALL, arc_BUTTON_ATCK_prev, ARC_MAX_SEGMENTS, ARC_SF_BEAMDIR, ARC_SF_BEAMTYPE, ARC_SF_START, ARC_SF_WANTDIR, ATTN_NORM, autocvar_g_balance_pause_armor_rot, beam_bursting, beam_dir, beam_heat, beam_initialized, beam_prev, beam_start, beam_teleporttime, beam_type, beam_wantdir, bezier_quadratic_getpoint(), bound(), CH_WEAPON_A, Damage(), entity(), ExponentialFalloff(), falloff, frametime, game_stopped, GetResource(), GiveResourceWithLimit(), Heal(), IS_DEAD, IS_MONSTER, IS_PLAYER, IT_UNLIMITED_AMMO, Weapon::m_id, makevectors, max(), min(), MOVE_NORMAL, nextthink, normalize(), NULL, owner, PHYS_INPUT_BUTTON_ATCK, PHYS_INPUT_BUTTON_ATCK2, RAD2DEG, RES_ARMOR, RES_LIMIT_NONE, SAME_TEAM, Send_Effect(), SendFlags, SetResource(), sound, STAT, time, trace_endpos, trace_ent, trace_fraction, vector, vlen(), VOL_BASE, W_SetupShot_Range, w_shotdir, w_shotorg, W_SwitchToOtherWeapon(), WarpZone_trace_transform, WarpZone_traceline_antilag(), WarpZone_TransformOrigin(), WarpZone_TransformVelocity(), WarpZone_UnTransformOrigin(), weapon_prepareattack_check(), weaponentity_fld, WEP_CVAR, and Weapon::wr_checkammo1().

Referenced by W_Arc_Beam().

◆ W_Arc_Bolt_Damage()

void W_Arc_Bolt_Damage ( entity this,
entity inflictor,
entity attacker,
float damage,
int deathtype,
.entity weaponentity,
vector hitloc,
vector force )

Definition at line 99 of file arc.qc.

100{
101 if (GetResource(this, RES_HEALTH) <= 0)
102 return;
103 if (!W_CheckProjectileDamage(inflictor.realowner, this.realowner, deathtype, -1))
104 return; // g_projectiles_damage says to halt
105
106 TakeResource(this, RES_HEALTH, damage);
107 this.angles = vectoangles(this.velocity);
108
109 if (GetResource(this, RES_HEALTH) <= 0)
110 W_PrepareExplosionByDamage(this, attacker, getthink(this));
111}
void TakeResource(entity receiver, Resource res_type, float amount)
Takes an entity some resource.
vector velocity
float W_CheckProjectileDamage(entity inflictor, entity projowner, int deathtype, float exception)
Definition common.qc:45
void W_PrepareExplosionByDamage(entity this, entity attacker, void(entity this) explode)
Definition common.qc:87

References angles, entity(), GetResource(), getthink, TakeResource(), vectoangles(), vector, velocity, W_CheckProjectileDamage(), and W_PrepareExplosionByDamage().

Referenced by W_Arc_Attack_Bolt().

◆ W_Arc_Bolt_Explode()

void W_Arc_Bolt_Explode ( entity this,
entity directhitentity )

Definition at line 76 of file arc.qc.

77{
78 this.event_damage = func_null;
79 RadiusDamage(this, this.realowner,
80 WEP_CVAR(WEP_ARC, bolt_damage),
81 WEP_CVAR(WEP_ARC, bolt_edgedamage),
82 WEP_CVAR(WEP_ARC, bolt_radius),
83 NULL,
84 NULL,
85 WEP_CVAR(WEP_ARC, bolt_force),
88 directhitentity
89 );
90
91 delete(this);
92}
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:943
var void func_null()
int projectiledeathtype
Definition common.qh:21
entity realowner

References entity(), func_null(), NULL, projectiledeathtype, RadiusDamage(), realowner, weaponentity_fld, and WEP_CVAR.

Referenced by W_Arc_Bolt_Explode_use().

◆ W_Arc_Bolt_Explode_use()

void W_Arc_Bolt_Explode_use ( entity this,
entity actor,
entity trigger )

Definition at line 94 of file arc.qc.

95{
96 W_Arc_Bolt_Explode(this, trigger);
97}
void W_Arc_Bolt_Explode(entity this, entity directhitentity)
Definition arc.qc:76

References entity(), and W_Arc_Bolt_Explode().

Referenced by W_Arc_Attack_Bolt().

◆ W_Arc_Bolt_Touch()

void W_Arc_Bolt_Touch ( entity this,
entity toucher )

Definition at line 113 of file arc.qc.

114{
116 if (this.cnt >= WEP_CVAR(WEP_ARC, bolt_bounce_count) || !WEP_CVAR(WEP_ARC, bolt_bounce_count) || toucher.takedamage == DAMAGE_AIM)
117 this.use(this, NULL, toucher);
118 else
119 {
120 ++this.cnt;
121 Send_Effect(EFFECT_BALL_SPARKS, this.origin, this.velocity, 1);
122 this.angles = vectoangles(this.velocity);
123 this.owner = NULL;
125 if (WEP_CVAR(WEP_ARC, bolt_bounce_explode))
126 RadiusDamage(this, this.realowner,
127 WEP_CVAR(WEP_ARC, bolt_damage),
128 WEP_CVAR(WEP_ARC, bolt_edgedamage),
129 WEP_CVAR(WEP_ARC, bolt_radius),
130 NULL,
131 NULL,
132 WEP_CVAR(WEP_ARC, bolt_force),
134 this.weaponentity_fld,
135 toucher
136 );
137 if (this.cnt == 1 && WEP_CVAR(WEP_ARC, bolt_bounce_lifetime))
138 this.nextthink = time + WEP_CVAR(WEP_ARC, bolt_bounce_lifetime);
139 }
140}
float cnt
Definition powerups.qc:24
#define use
const int HITTYPE_BOUNCE
set manually after projectile has bounced
Definition all.qh:33
entity entity toucher
Definition self.qh:76
#define PROJECTILE_TOUCH(e, t)
Definition common.qh:28
const int DAMAGE_AIM
Definition subs.qh:81

References angles, cnt, DAMAGE_AIM, entity(), HITTYPE_BOUNCE, nextthink, NULL, origin, owner, PROJECTILE_TOUCH, projectiledeathtype, RadiusDamage(), realowner, Send_Effect(), time, toucher, use, vectoangles(), velocity, weaponentity_fld, and WEP_CVAR.

Referenced by W_Arc_Attack_Bolt().

Variable Documentation

◆ autocvar_cl_arcbeam_simple

bool autocvar_cl_arcbeam_simple = true

Definition at line 721 of file arc.qc.

Referenced by Draw_ArcBeam(), and Draw_ArcBeam_callback().

◆ beam_slot

int beam_slot

Definition at line 723 of file arc.qc.

Referenced by Draw_ArcBeam(), and NET_HANDLE().