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:92
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 829 of file arc.qc.

830{
831 float dt = time - this.move_time;
832 this.move_time = time;
833 if (dt <= 0)
834 return;
835
836 // origin = beam starting origin
837 // v_angle = wanted/aim direction
838 // angles = current direction of beam
839
840 vector start_pos;
841 vector wantdir; //= view_forward;
842 vector beamdir; //= this.beam_dir;
843
844 float segments;
845 if (this.beam_usevieworigin)
846 {
847 // WEAPONTODO:
848 // Currently we have to replicate nearly the same method of figuring
849 // out the shotdir that the server does... Ideally in the future we
850 // should be able to acquire this from a generalized function built
851 // into a weapon system for client code.
852
853 // Dr. Jaska: Reply to ^: Do we? If the server would decide where a
854 // client draws a beam it would mean that what the client sees will
855 // always be lagged and not where they are actually hitting in "real
856 // time" after being antilagged. Thus I don't understand the above.
857
858 // find where we are aiming
859 vector myviewangle = view_angles;
861 {
863 myviewangle = eX * csqcplayer.v_angle.x + eY * csqcplayer.angles.y;
864 else
865 myviewangle = warpzone_save_view_angles;
866 }
867 vector forward, right, up;
868 MAKE_VECTORS(myviewangle, forward, right, up);
869 entity wepent = viewmodels[this.beam_slot];
870
872
873 // decide upon start position
874 if (this.beam_usevieworigin == 2)
875 start_pos = warpzone_save_view_origin;
876 else if (csqcplayer)
877 start_pos = csqcplayer.origin + csqcplayer.view_ofs;
878 else
879 start_pos = this.origin;
880
881 vector start_pos_saved = start_pos;
882 int v_shot_idx;
883 (v_shot_idx = gettagindex(wepent, "shot")) || (v_shot_idx = gettagindex(wepent, "tag_shot"));
884 if (v_shot_idx && this.beam_usevieworigin == 2)
885 {
886 start_pos = gettaginfo(wepent, v_shot_idx) - '0 0 2';
887 // ignore our own player model in this traceline otherwise it may be hit with trace_fraction < 1
888 // while crouching / standing up due to view height smoothing (cl_smoothviewheight)
889 traceline(start_pos_saved, start_pos, MOVE_NORMAL, csqcplayer);
890 if (trace_fraction < 1)
891 {
892 // found an obstacle between view origin and shot tag
893 v_shot_idx = 0;
894 start_pos = trace_endpos;
895 start_pos_saved = start_pos;
896 }
897 }
898
899 // trace forward with an estimation
901 start_pos_saved,
902 start_pos_saved + forward * WEP_CVAR(WEP_ARC, beam_range),
904 this
905 );
906
907 // untransform in case our trace went through a warpzone
909
910 // un-adjust trueaim if shotend is too close
911 if (vdist(end_pos - start_pos, <, g_trueaim_minrange))
912 end_pos = start_pos + (forward * g_trueaim_minrange);
913
914 // move shot origin to the actual gun muzzle origin
915 vector origin_offset = '0 0 0';
916 if (!v_shot_idx || this.beam_usevieworigin != 2)
917 {
918 this.beam_shotorigin = wepent.movedir;
919 origin_offset = right * -this.beam_shotorigin.y + up * this.beam_shotorigin.z;
920 }
921 else
922 this.beam_shotorigin = '0 0 0';
923
924 start_pos += origin_offset;
925
926 // Move it also forward, but only as far as possible without hitting anything. Don't poke into walls!
927 traceline(start_pos, start_pos + forward * this.beam_shotorigin.x, MOVE_NORMAL, this);
928 start_pos = trace_endpos;
929
930 // calculate the aim direction now
931 if (vdist(end_pos - start_pos, >, 0.001))
932 wantdir = normalize(end_pos - start_pos);
933 else
934 wantdir = view_forward;
935
936 if (!this.beam_initialized)
937 {
938 this.beam_dir = wantdir;
939 this.beam_initialized = true;
940
941 this.beam_muzzleentity.drawmask = MASK_NORMAL; // NOTE: this works around the muzzle entity flashing on the middle of the screen for a frame
942 }
943
944 segments = 1;
945 if (this.beam_dir != wantdir)
946 {
947 // calculate how much we're going to move the end of the beam to the want position
948 float angle = vlen(wantdir - this.beam_dir) * RAD2DEG;
949 if (angle < 0.01) // snap only when very close so it's impossible to notice
950 this.beam_dir = wantdir; // snap otherwise vectors will never actually be the same
951 else
952 {
953 float max_blendfactor = 1;
954 if (angle && angle > WEP_CVAR(WEP_ARC, beam_maxangle))
955 max_blendfactor = WEP_CVAR(WEP_ARC, beam_maxangle) / angle;
956 float blendfactor = bound(0, (1 - (WEP_CVAR(WEP_ARC, beam_returnspeed) * dt)), max_blendfactor);
957 this.beam_dir = normalize((wantdir * (1 - blendfactor)) + (this.beam_dir * blendfactor));
958
959 // calculate how many segments are needed
960 float max_allowed_segments = ARC_MAX_SEGMENTS;
961 if (WEP_CVAR(WEP_ARC, beam_distancepersegment))
962 {
963 max_allowed_segments = 1 + (vlen(wantdir / WEP_CVAR(WEP_ARC, beam_distancepersegment)));
964 max_allowed_segments = bound(1, max_allowed_segments, ARC_MAX_SEGMENTS);
965 }
966 if (WEP_CVAR(WEP_ARC, beam_degreespersegment))
967 {
968 segments = min(angle, WEP_CVAR(WEP_ARC, beam_maxangle)) / WEP_CVAR(WEP_ARC, beam_degreespersegment);
969 segments = bound(1, segments, max_allowed_segments);
970 }
971 }
972 }
973
974 // set the beam direction which the rest of the code will refer to
975 beamdir = this.beam_dir;
976
977 // finally, set this.angles to the proper direction so that muzzle attachment points in proper direction
978 this.angles = fixedvectoangles2(forward, up); // TODO(Samual): is this == warpzone_save_view_angles?
979 }
980 else // if (!this.beam_usevieworigin)
981 {
983
984 // set the values from the provided info from the networked entity
985 start_pos = this.origin;
986 wantdir = this.v_angle;
987 beamdir = this.angles;
988
989 segments = 1;
990 if (beamdir != wantdir)
991 {
992 float angle = vlen(wantdir - beamdir) * RAD2DEG;
993
994 // calculate how many segments are needed
995 float max_allowed_segments = ARC_MAX_SEGMENTS;
996 if (WEP_CVAR(WEP_ARC, beam_distancepersegment))
997 {
998 max_allowed_segments = 1 + (vlen(wantdir / WEP_CVAR(WEP_ARC, beam_distancepersegment)));
999 max_allowed_segments = bound(1, max_allowed_segments, ARC_MAX_SEGMENTS);
1000 }
1001
1002 if (WEP_CVAR(WEP_ARC, beam_degreespersegment))
1003 {
1004 segments = min(angle, WEP_CVAR(WEP_ARC, beam_maxangle)) / WEP_CVAR(WEP_ARC, beam_degreespersegment);
1005 segments = bound(1, segments, max_allowed_segments);
1006 }
1007 }
1008 }
1009
1010 setorigin(this, start_pos);
1011 this.beam_muzzleentity.angles.z = random() * 360; // WEAPONTODO: use avelocity instead?
1012
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;
1016
1019 {
1023 }
1024
1025 vector last_origin = start_pos;
1026 vector original_start_pos = start_pos;
1027
1028 for (int i = 1; i <= segments; ++i)
1029 {
1030 // WEAPONTODO (client):
1031 // In order to do nice fading and pointing on the starting segment, we must always
1032 // have that drawn as a separate triangle... However, that is difficult to do when
1033 // keeping in mind the above problems and also optimizing the amount of segments
1034 // drawn on screen at any given time. (Automatic beam quality scaling, essentially)
1035
1036 vector new_origin = bezier_quadratic_getpoint(
1037 start_pos,
1038 beam_controlpoint,
1039 beam_endpos,
1040 i / segments
1041 );
1042
1044 last_origin,
1045 '0 0 0',
1046 '0 0 0',
1047 new_origin,
1049 NULL,
1050 NULL,
1052 );
1053
1054 last_origin = trace_endpos;
1055
1056 if (trace_fraction < 1)
1057 break; // hit something
1058
1059 // Do all the transforms for warpzones right now, as we already "are" in the post-trace
1060 // system (if we hit a player, that's always BEHIND the last passed wz).
1061 start_pos = WarpZone_TransformOrigin(WarpZone_trace_transform, start_pos);
1062 beam_controlpoint = WarpZone_TransformOrigin(WarpZone_trace_transform, beam_controlpoint);
1063 beam_endpos = WarpZone_TransformOrigin(WarpZone_trace_transform, beam_endpos);
1066 {
1069 }
1070 }
1071
1072 // visual effects for startpoint and endpoint
1075 this.beam_hiteffect,
1076 last_origin,
1078 dt * 2
1079 );
1080
1081 if (this.beam_hitlight[0])
1083 last_origin,
1084 this.beam_hitlight[0],
1085 vec3(
1086 this.beam_hitlight[1],
1087 this.beam_hitlight[2],
1088 this.beam_hitlight[3]
1089 )
1090 );
1091
1094 this.beam_muzzleeffect,
1095 original_start_pos + wantdir * 20,
1096 wantdir * 1000,
1097 dt * 0.1
1098 );
1099
1100 if (this.beam_muzzlelight[0])
1102 original_start_pos + wantdir * 20,
1103 this.beam_muzzlelight[0],
1104 vec3(
1105 this.beam_muzzlelight[1],
1106 this.beam_muzzlelight[2],
1107 this.beam_muzzlelight[3]
1108 )
1109 );
1110
1111 // cleanup
1114 {
1118 }
1119}
#define fixedvectoangles2
bool autocvar_cl_arcbeam_simple
Definition arc.qc:727
void Draw_ArcBeam_callback(vector start, vector hit, vector end)
Definition arc.qc:742
int beam_slot
Definition arc.qc:729
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:121
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:212
void WarpZone_TraceLine(vector org, vector end, float nomonsters, entity forent)
Definition common.qc:348
vector WarpZone_TransformVelocity(entity wz, vector v)
Definition common.qc:514
vector WarpZone_UnTransformOrigin(entity wz, vector v)
Definition common.qc:544
vector WarpZone_TransformOrigin(entity wz, vector v)
Definition common.qc:509
entity WarpZone_trace_transform
Definition common.qh:37
float angle
Definition viewloc.qc:114
ERASEABLE vector bezier_quadratic_getpoint(vector a, vector b, vector c, float t)
Definition math.qh:111
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:77
#define NULL
Definition post.qh:14
#define gettaginfo
Definition post.qh:32
#define adddynamiclight
Definition post.qh:29
const vector eY
Definition vector.qh:45
#define vdist(v, cmp, f)
Vector distance comparison, avoids sqrt()
Definition vector.qh:8
const vector eX
Definition vector.qh:44
#define vec3(_x, _y, _z)
Definition vector.qh:95
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 742 of file arc.qc.

743{
746
747 vector hitorigin;
748 #if 0
749 if (trace_fraction != 1)
750 {
751 // calculate our own hit origin as trace_endpos tends to jump around annoyingly (to player origin?)
752 hitorigin = start + (Draw_ArcBeam_callback_new_dir * Draw_ArcBeam_callback_segmentdist * trace_fraction);
754 }
755 else
756 hitorigin = hit;
757 #else
758 hitorigin = hit;
759 #endif
760
761 float thickness = beam.beam_thickness;
762
764 Draw_CylindricLine(start, hit, thickness, beam.beam_image, 0.25, time * -3, beam.beam_color, beam.beam_alpha, DRAWFLAG_NORMAL, transformed_view_org);
765 else
766 {
767 // Thickdir shall be perpendicular to the beam and to the view-to-beam direction (WEAPONTODO: WHY)
768 // WEAPONTODO: Wouldn't it be better to be perpendicular to the beam and to the view FORWARD direction?
769 vector thickdir = normalize(cross(normalize(start - hit), transformed_view_org - start));
770
771 // draw primary beam render
772 vector top = hitorigin + (thickdir * thickness);
773 vector bottom = hitorigin - (thickdir * thickness);
774
777
778 // draw segment
779 R_BeginPolygon(beam.beam_image, DRAWFLAG_NORMAL, false); // DRAWFLAG_ADDITIVE
780 R_PolygonVertex(
781 top,
782 '0 0.5 0' + ('0 0.5 0' * (thickness / beam.beam_thickness)),
783 beam.beam_color,
784 beam.beam_alpha
785 );
786 R_PolygonVertex(
787 last_top,
788 '0 0.5 0' + ('0 0.5 0' * (Draw_ArcBeam_callback_last_thickness / beam.beam_thickness)),
789 beam.beam_color,
790 beam.beam_alpha
791 );
792 R_PolygonVertex(
793 last_bottom,
794 '0 0.5 0' * (1 - (Draw_ArcBeam_callback_last_thickness / beam.beam_thickness)),
795 beam.beam_color,
796 beam.beam_alpha
797 );
798 R_PolygonVertex(
799 bottom,
800 '0 0.5 0' * (1 - (thickness / beam.beam_thickness)),
801 beam.beam_color,
802 beam.beam_alpha
803 );
804 R_EndPolygon();
805
806 // set up for the next
810 }
811
812 // draw trailing particles
813 // NOTES:
814 // - Don't use spammy particle counts here, use a FEW small particles around the beam
815 // - We're not using WarpZone_TrailParticles here because we will handle warpzones ourselves.
816 if (beam.beam_traileffect)
817 trailparticles(beam, beam.beam_traileffect, start, hitorigin);
818}
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:11
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 1127 of file arc.qc.

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

1122{
1123 delete(this.beam_muzzleentity);
1124 sound(this, CH_SHOTS_SINGLE, SND_Null, VOL_BASE, ATTEN_NORM);
1125}

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 820 of file arc.qc.

821{
822 entity e;
823 for (e = NULL; (e = findfloat(e, beam_usevieworigin, 1)); )
824 e.beam_initialized = false;
825 for (e = NULL; (e = findfloat(e, beam_usevieworigin, 2)); )
826 e.beam_initialized = false;
827}
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
bool SetResourceExplicit(entity e, Resource res_type, float amount)
Sets the resource amount of an entity without calling any hooks.
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:29
vector vectoangles(vector v)
void set_movetype(entity this, int mt)
Definition movetypes.qc:4
const int MOVETYPE_BOUNCEMISSILE
Definition movetypes.qh:140
const int PROJECTILE_ARC_BOLT
#define setthink(e, f)
#define settouch(e, f)
Definition self.qh:73
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:129
#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
const int MSG_ENTITY
Definition net.qh:156
#define WriteHeader(to, id)
Definition net.qh:265
void WriteByte(float data, float dest, float desto)
#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 coefficient = min(coefficient, GetResource(own, thiswep.ammo_type) / rootammo);
268 SetResource(own, thiswep.ammo_type, max(0, GetResource(own, thiswep.ammo_type) - (rootammo * frametime)));
269 }
270 }
271 float heat_speed = (burst ? WEP_CVAR(WEP_ARC, burst_heat) : WEP_CVAR(WEP_ARC, beam_heat));
272 this.beam_heat = min(WEP_CVAR(WEP_ARC, overheat_max), this.beam_heat + heat_speed * frametime);
273
274 makevectors(own.v_angle);
275
277 own,
278 weaponentity,
279 true,
280 0,
281 SND_Null,
282 0,
283 WEP_CVAR(WEP_ARC, beam_damage) * coefficient,
284 WEP_CVAR(WEP_ARC, beam_range),
285 thiswep.m_id
286 );
287
288 // After teleport, "lock" the beam until the teleport is confirmed.
289 if (time < this.beam_teleporttime + ANTILAG_LATENCY(own))
290 w_shotdir = this.beam_dir;
291
292 // network information: shot origin and want/aim direction
293 if (this.beam_start != w_shotorg)
294 {
295 this.SendFlags |= ARC_SF_START;
296 this.beam_start = w_shotorg;
297 }
298 if (this.beam_wantdir != w_shotdir)
299 {
301 this.beam_wantdir = w_shotdir;
302 }
303
304 if (!this.beam_initialized)
305 {
306 this.beam_dir = w_shotdir;
307 this.beam_initialized = true;
308 }
309
310 // WEAPONTODO: Detect player velocity so that the beam curves when moving too
311 // idea: blend together this.beam_dir with the inverted direction the player is moving in
312 // might have to make some special accomodation so that it only uses view_right and view_up
313
314 // note that if we do this, it'll always be corrected to a maximum angle by beam_maxangle handling
315
316 float segments = 1;
317 if (this.beam_dir != w_shotdir)
318 {
319 // calculate how much we're going to move the end of the beam to the want position
320 float angle = vlen(w_shotdir - this.beam_dir) * RAD2DEG;
321 if (angle < 0.01) // snap only when very close so it's impossible to notice
322 this.beam_dir = w_shotdir; // snap otherwise vectors will never actually be the same
323 else
324 {
325 float max_blendfactor = 1;
326 if (angle && angle > WEP_CVAR(WEP_ARC, beam_maxangle))
327 max_blendfactor = WEP_CVAR(WEP_ARC, beam_maxangle) / angle;
328 float blendfactor = bound(0, (1 - (WEP_CVAR(WEP_ARC, beam_returnspeed) * frametime)), max_blendfactor);
329 this.beam_dir = normalize((w_shotdir * (1 - blendfactor)) + (this.beam_dir * blendfactor));
330 }
331
332 // network information: beam direction
334
335 // calculate how many segments are needed
336 float max_allowed_segments = ARC_MAX_SEGMENTS;
337 if (WEP_CVAR(WEP_ARC, beam_distancepersegment))
338 {
339 max_allowed_segments = 1 + vlen(w_shotdir) / WEP_CVAR(WEP_ARC, beam_distancepersegment);
340 max_allowed_segments = bound(1, max_allowed_segments, ARC_MAX_SEGMENTS);
341 }
342
343 if (WEP_CVAR(WEP_ARC, beam_degreespersegment))
344 {
345 segments = min(angle, WEP_CVAR(WEP_ARC, beam_maxangle)) / WEP_CVAR(WEP_ARC, beam_degreespersegment);
346 segments = bound(1, segments, max_allowed_segments);
347 }
348 }
349
350 vector beam_endpos = w_shotorg + (this.beam_dir * WEP_CVAR(WEP_ARC, beam_range));
351 float beam_controlpoint_dist = WEP_CVAR(WEP_ARC, beam_range) * bound(0.001, 1 - WEP_CVAR(WEP_ARC, beam_tightness), 1);
352 vector beam_controlpoint = w_shotorg + w_shotdir * beam_controlpoint_dist;
353
354 int new_beam_type = 0;
355 vector last_origin = w_shotorg;
356 vector last_origin_prev = '0 0 0';
357 for (int i = 1; i <= segments; ++i)
358 {
359 // WEAPONTODO (client):
360 // In order to do nice fading and pointing on the starting segment, we must always
361 // have that drawn as a separate triangle... However, that is difficult to do when
362 // keeping in mind the above problems and also optimizing the amount of segments
363 // drawn on screen at any given time. (Automatic beam quality scaling, essentially)
364
366 w_shotorg,
367 beam_controlpoint,
368 beam_endpos,
369 i / segments
370 );
371
373 own,
374 last_origin,
375 new_origin,
377 NULL,
378 ANTILAG_LATENCY(own)
379 );
380
381 last_origin_prev = last_origin; // used later to calculate damage force direction
382 last_origin = trace_endpos;
383
384 // Do all the transforms for warpzones right now, as we already "are" in the post-trace
385 // system (if we hit a player, that's always BEHIND the last passed wz).
387
388 if (trace_fraction == 1)
389 {
390 beam_controlpoint = WarpZone_TransformOrigin(WarpZone_trace_transform, beam_controlpoint);
391 beam_endpos = WarpZone_TransformOrigin(WarpZone_trace_transform, beam_endpos);
392 continue;
393 }
394
395 if (!trace_ent)
396 {
397 // we collided with geometry
398 new_beam_type = ARC_BT_WALL;
399 break;
400 }
401
402 // we collided with an entity
403 bool is_player = (IS_PLAYER(trace_ent) || trace_ent.classname == "body" || IS_MONSTER(trace_ent));
404 if (trace_ent != own && SAME_TEAM(own, trace_ent))
405 {
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));
408 float hplimit = (IS_PLAYER(trace_ent) ? WEP_CVAR(WEP_ARC, beam_healing_hmax) : RES_LIMIT_NONE);
409 Heal(trace_ent, own, (roothealth * coefficient), hplimit);
410 if (IS_PLAYER(trace_ent) && rootarmor
411 && GetResource(trace_ent, RES_ARMOR) <= WEP_CVAR(WEP_ARC, beam_healing_amax))
412 {
413 GiveResourceWithLimit(trace_ent, RES_ARMOR, (rootarmor * coefficient), WEP_CVAR(WEP_ARC, beam_healing_amax));
414 trace_ent.pauserotarmor_finished = max(trace_ent.pauserotarmor_finished, time + autocvar_g_balance_pause_armor_rot);
415 }
416 if (roothealth || rootarmor)
417 new_beam_type = ARC_BT_HEAL;
418 }
419 else if (trace_ent.takedamage && (is_player || WEP_CVAR(WEP_ARC, beam_nonplayerdamage)))
420 {
421 // calculate our own hit origin as trace_endpos tends to jump around annoyingly (to player origin?)
422 // NO. trace_endpos should be just fine. If not,
423 // that's an engine bug that needs proper debugging.
424 vector hitorigin = trace_endpos;
425
427 WEP_CVAR(WEP_ARC, beam_falloff_mindist),
428 WEP_CVAR(WEP_ARC, beam_falloff_maxdist),
429 WEP_CVAR(WEP_ARC, beam_falloff_halflifedist),
431 );
432
433 float rootdamage;
434 if (is_player)
435 {
436 if (burst)
437 rootdamage = WEP_CVAR(WEP_ARC, burst_damage);
438 else
439 rootdamage = WEP_CVAR(WEP_ARC, beam_damage);
440 }
441 else
442 rootdamage = WEP_CVAR(WEP_ARC, beam_nonplayerdamage);
443
445 accuracy_add(own, WEP_ARC, 0, rootdamage * coefficient * falloff, 0); // add to hit
446
447 vector new_dir = normalize(new_origin - last_origin_prev);
449 Damage(trace_ent, own, own,
450 rootdamage * coefficient * falloff,
451 WEP_ARC.m_id,
452 weaponentity,
453 hitorigin,
454 WEP_CVAR(WEP_ARC, beam_force) * coefficient * falloff * new_dir
455 );
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:130
int SendFlags
Definition net.qh:159
ERASEABLE float ExponentialFalloff(float mindist, float maxdist, float halflifedist, float d)
Definition math.qh:241
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
Definition all.qh:31
entity entity toucher
Definition self.qh:72
#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 727 of file arc.qc.

Referenced by Draw_ArcBeam(), and Draw_ArcBeam_callback().

◆ beam_slot

int beam_slot

Definition at line 729 of file arc.qc.

Referenced by Draw_ArcBeam(), and NET_HANDLE().