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

59{
60 if ( WEP_CVAR(WEP_ARC, overheat_max) <= 0 || WEP_CVAR(WEP_ARC, overheat_max) <= 0 )
61 {
62 player.arc_overheat = 0;
63 return 0;
64 }
65
66 if ( player.(weaponentity).arc_beam )
67 return player.(weaponentity).arc_beam.beam_heat/WEP_CVAR(WEP_ARC, overheat_max);
68
69 if ( player.arc_overheat > time )
70 {
71 return (player.arc_overheat-time) / WEP_CVAR(WEP_ARC, overheat_max)
72 * player.arc_cooldown;
73 }
74
75 return 0;
76}
entity arc_beam
Definition arc.qh:128
float time
#define WEP_CVAR(wep, name)
Definition all.qh:321

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

78{
79 player.(weaponentity).arc_heat_percent = Arc_GetHeat_Percent(player, weaponentity);
80 //dprint("Heat: ",ftos(player.arc_heat_percent*100),"%\n");
81}
float Arc_GetHeat_Percent(entity player,.entity weaponentity)
Definition arc.qc:58
float arc_heat_percent
Definition arc.qh:137

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

524{
525 // calculate a rough shot origin to show the effect from TODO: move this to the client side!
526 makevectors(actor.v_angle);
528 vector md = actor.(weaponentity).movedir;
529 vector dv = v_forward * md.x + v_right * -md.y + v_up * md.z;
530 w_shotorg = actor.origin + actor.view_ofs + dv;
531 //W_SetupShot_Range(actor,weaponentity,false,0,SND_Null,0,0,0,thiswep.m_id);
532
533 vector smoke_origin = w_shotorg + actor.velocity*frametime;
534 if ( actor.arc_overheat > time )
535 {
536 if ( random() < actor.(weaponentity).arc_heat_percent )
537 Send_Effect(EFFECT_ARC_SMOKE, smoke_origin, '0 0 0', 1 );
538 if ( fire & (1 | 2) )
539 {
540 Send_Effect(EFFECT_ARC_OVERHEAT_FIRE, smoke_origin, w_shotdir, 1 );
541 if ( !actor.arc_smoke_sound )
542 {
543 actor.arc_smoke_sound = true;
544 sound(actor, CH_SHOTS_SINGLE, SND_ARC_LOOP_OVERHEAT, VOL_BASE, ATTN_NORM);
545 }
546 }
547 }
548 else if ( actor.(weaponentity).arc_beam && WEP_CVAR(WEP_ARC, overheat_max) > 0 &&
549 actor.(weaponentity).arc_beam.beam_heat > WEP_CVAR(WEP_ARC, overheat_min) )
550 {
551 if ( random() < (actor.(weaponentity).arc_beam.beam_heat-WEP_CVAR(WEP_ARC, overheat_min)) /
552 ( WEP_CVAR(WEP_ARC, overheat_max)-WEP_CVAR(WEP_ARC, overheat_min) ) )
553 Send_Effect(EFFECT_ARC_SMOKE, smoke_origin, '0 0 0', 1 );
554 }
555
556 bool attacking = PHYS_INPUT_BUTTON_ATCK(actor) || PHYS_INPUT_BUTTON_ATCK2(actor);
557 bool stop_smoke_sound = actor.arc_overheat <= time || !attacking;
558 if ((actor.arc_smoke_sound && stop_smoke_sound) || actor.(weaponentity).m_switchweapon != thiswep)
559 {
560 actor.arc_smoke_sound = false;
561 sound(actor, CH_SHOTS_SINGLE, SND_Null, VOL_BASE, ATTEN_NORM);
562 }
563}
#define PHYS_INPUT_BUTTON_ATCK(s)
Definition player.qh:150
#define PHYS_INPUT_BUTTON_ATCK2(s)
Definition player.qh:152
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:124
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 863 of file arc.qc.

864{
865 float dt = time - this.move_time;
866 this.move_time = time;
867 if(dt <= 0) { return; }
868
869 // origin = beam starting origin
870 // v_angle = wanted/aim direction
871 // angles = current direction of beam
872
873 vector start_pos;
874 vector wantdir; //= view_forward;
875 vector beamdir; //= this.beam_dir;
876
877 float segments;
878 if(this.beam_usevieworigin)
879 {
880 // WEAPONTODO:
881 // Currently we have to replicate nearly the same method of figuring
882 // out the shotdir that the server does... Ideally in the future we
883 // should be able to acquire this from a generalized function built
884 // into a weapon system for client code.
885
886 // Dr. Jaska: Reply to ^: Do we? If the server would decide where a
887 // client draws a beam it would mean that what the client sees will
888 // always be lagged and not where they are actually hitting in "real
889 // time" after being antilagged. Thus I don't understand the above.
890
891 // find where we are aiming
892 vector myviewangle = view_angles;
894 {
896 myviewangle = eX * csqcplayer.v_angle.x + eY * csqcplayer.angles.y;
897 else
898 myviewangle = warpzone_save_view_angles;
899 }
900 vector forward, right, up;
901 MAKE_VECTORS(myviewangle, forward, right, up);
902 entity wepent = viewmodels[this.beam_slot];
903
905
906 // decide upon start position
907 if(this.beam_usevieworigin == 2)
908 { start_pos = warpzone_save_view_origin; }
909 else if(csqcplayer)
910 { start_pos = csqcplayer.origin + csqcplayer.view_ofs; }
911 else
912 { start_pos = this.origin; }
913
914 vector start_pos_saved = start_pos;
915 int v_shot_idx; // used later
916 (v_shot_idx = gettagindex(wepent, "shot")) || (v_shot_idx = gettagindex(wepent, "tag_shot"));
917 if(v_shot_idx && this.beam_usevieworigin == 2)
918 {
919 start_pos = gettaginfo(wepent, v_shot_idx) - '0 0 2';
920 // ignore our own player model in this traceline otherwise it may be hit with trace_fraction < 1
921 // while crouching / standing up due to view height smoothing (cl_smoothviewheight)
922 traceline(start_pos_saved, start_pos, MOVE_NORMAL, csqcplayer);
923 if (trace_fraction < 1)
924 {
925 // found an obstacle between view origin and shot tag
926 v_shot_idx = 0;
927 start_pos = trace_endpos;
928 start_pos_saved = start_pos;
929 }
930 }
931
932 // trace forward with an estimation
934 start_pos_saved,
935 start_pos_saved + forward * WEP_CVAR(WEP_ARC, beam_range),
937 this
938 );
939
940 // untransform in case our trace went through a warpzone
942
943 // un-adjust trueaim if shotend is too close
944 if(vdist(end_pos - start_pos, <, g_trueaim_minrange))
945 end_pos = start_pos + (forward * g_trueaim_minrange);
946
947 // move shot origin to the actual gun muzzle origin
948 vector origin_offset = '0 0 0';
949 if(!v_shot_idx || this.beam_usevieworigin != 2)
950 {
951 this.beam_shotorigin = wepent.movedir;
952 origin_offset = right * -this.beam_shotorigin.y + up * this.beam_shotorigin.z;
953 }
954 else
955 this.beam_shotorigin = '0 0 0';
956
957 start_pos = start_pos + origin_offset;
958
959 // Move it also forward, but only as far as possible without hitting anything. Don't poke into walls!
960 traceline(start_pos, start_pos + forward * this.beam_shotorigin.x, MOVE_NORMAL, this);
961 start_pos = trace_endpos;
962
963 // calculate the aim direction now
964 if (vdist(end_pos - start_pos, >, 0.001))
965 wantdir = normalize(end_pos - start_pos);
966 else
967 wantdir = view_forward;
968
969 if(!this.beam_initialized)
970 {
971 this.beam_dir = wantdir;
972 this.beam_initialized = true;
973
974 this.beam_muzzleentity.drawmask = MASK_NORMAL; // NOTE: this works around the muzzle entity flashing on the middle of the screen for a frame
975 }
976
977 segments = 1;
978 if(this.beam_dir != wantdir)
979 {
980 // calculate how much we're going to move the end of the beam to the want position
981 float angle = vlen(wantdir - this.beam_dir) * RAD2DEG;
982 if (angle < 0.01) // snap only when very close so it's impossible to notice
983 this.beam_dir = wantdir; // snap otherwise vectors will never actually be the same
984 else
985 {
986 float max_blendfactor = 1;
987 if(angle && (angle > WEP_CVAR(WEP_ARC, beam_maxangle)))
988 max_blendfactor = WEP_CVAR(WEP_ARC, beam_maxangle) / angle;
989 float blendfactor = bound(0, (1 - (WEP_CVAR(WEP_ARC, beam_returnspeed) * dt)), max_blendfactor);
990 this.beam_dir = normalize((wantdir * (1 - blendfactor)) + (this.beam_dir * blendfactor));
991
992 // calculate how many segments are needed
993 float max_allowed_segments = ARC_MAX_SEGMENTS;
994 if(WEP_CVAR(WEP_ARC, beam_distancepersegment))
995 {
996 max_allowed_segments = 1 + (vlen(wantdir / WEP_CVAR(WEP_ARC, beam_distancepersegment)));
997 max_allowed_segments = bound(1, max_allowed_segments, ARC_MAX_SEGMENTS);
998 }
999
1000 if(WEP_CVAR(WEP_ARC, beam_degreespersegment))
1001 {
1002 segments = min(angle, WEP_CVAR(WEP_ARC, beam_maxangle)) / WEP_CVAR(WEP_ARC, beam_degreespersegment);
1003 segments = bound(1, segments, max_allowed_segments);
1004 }
1005 }
1006 }
1007
1008 // set the beam direction which the rest of the code will refer to
1009 beamdir = this.beam_dir;
1010
1011 // finally, set this.angles to the proper direction so that muzzle attachment points in proper direction
1012 this.angles = fixedvectoangles2(forward, up); // TODO(Samual): is this == warpzone_save_view_angles?
1013 }
1014 else // if(!this.beam_usevieworigin)
1015 {
1017
1018 // set the values from the provided info from the networked entity
1019 start_pos = this.origin;
1020 wantdir = this.v_angle;
1021 beamdir = this.angles;
1022
1023 segments = 1;
1024 if(beamdir != wantdir)
1025 {
1026 float angle = vlen(wantdir - beamdir) * RAD2DEG;
1027
1028 // calculate how many segments are needed
1029 float max_allowed_segments = ARC_MAX_SEGMENTS;
1030 if(WEP_CVAR(WEP_ARC, beam_distancepersegment))
1031 {
1032 max_allowed_segments = 1 + (vlen(wantdir / WEP_CVAR(WEP_ARC, beam_distancepersegment)));
1033 max_allowed_segments = bound(1, max_allowed_segments, ARC_MAX_SEGMENTS);
1034 }
1035
1036 if(WEP_CVAR(WEP_ARC, beam_degreespersegment))
1037 {
1038 segments = min(angle, WEP_CVAR(WEP_ARC, beam_maxangle)) / WEP_CVAR(WEP_ARC, beam_degreespersegment);
1039 segments = bound(1, segments, max_allowed_segments);
1040 }
1041 }
1042 }
1043
1044 setorigin(this, start_pos);
1045 this.beam_muzzleentity.angles_z = random() * 360; // WEAPONTODO: use avelocity instead?
1046
1047 vector beam_endpos = (start_pos + (beamdir * WEP_CVAR(WEP_ARC, beam_range)));
1048 float beam_controlpoint_dist = WEP_CVAR(WEP_ARC, beam_range) * bound(0.001, 1 - WEP_CVAR(WEP_ARC, beam_tightness), 1);
1049 vector beam_controlpoint = start_pos + wantdir * beam_controlpoint_dist;
1050
1053 {
1057 }
1058
1059 vector last_origin = start_pos;
1060 vector original_start_pos = start_pos;
1061
1062 for(int i = 1; i <= segments; ++i)
1063 {
1064 // WEAPONTODO (client):
1065 // In order to do nice fading and pointing on the starting segment, we must always
1066 // have that drawn as a separate triangle... However, that is difficult to do when
1067 // keeping in mind the above problems and also optimizing the amount of segments
1068 // drawn on screen at any given time. (Automatic beam quality scaling, essentially)
1069
1070 vector new_origin = bezier_quadratic_getpoint(
1071 start_pos,
1072 beam_controlpoint,
1073 beam_endpos,
1074 i / segments);
1075
1077 last_origin,
1078 '0 0 0',
1079 '0 0 0',
1080 new_origin,
1082 NULL,
1083 NULL,
1085 );
1086
1087 last_origin = trace_endpos;
1088
1089 if(trace_fraction < 1)
1090 break; // hit something
1091
1092 // Do all the transforms for warpzones right now, as we already "are" in the post-trace
1093 // system (if we hit a player, that's always BEHIND the last passed wz).
1094 start_pos = WarpZone_TransformOrigin(WarpZone_trace_transform, start_pos);
1095 beam_controlpoint = WarpZone_TransformOrigin(WarpZone_trace_transform, beam_controlpoint);
1096 beam_endpos = WarpZone_TransformOrigin(WarpZone_trace_transform, beam_endpos);
1099 {
1102 }
1103 }
1104
1105 // visual effects for startpoint and endpoint
1107 {
1109 this.beam_hiteffect,
1110 last_origin,
1112 dt * 2
1113 );
1114 }
1115 if(this.beam_hitlight[0])
1116 {
1118 last_origin,
1119 this.beam_hitlight[0],
1120 vec3(
1121 this.beam_hitlight[1],
1122 this.beam_hitlight[2],
1123 this.beam_hitlight[3]
1124 )
1125 );
1126 }
1128 {
1130 this.beam_muzzleeffect,
1131 original_start_pos + wantdir * 20,
1132 wantdir * 1000,
1133 dt * 0.1
1134 );
1135 }
1136 if(this.beam_muzzlelight[0])
1137 {
1139 original_start_pos + wantdir * 20,
1140 this.beam_muzzlelight[0],
1141 vec3(
1142 this.beam_muzzlelight[1],
1143 this.beam_muzzlelight[2],
1144 this.beam_muzzlelight[3]
1145 )
1146 );
1147 }
1148
1149 // cleanup
1152 {
1156 }
1157}
#define fixedvectoangles2
bool autocvar_cl_arcbeam_simple
Definition arc.qc:755
void Draw_ArcBeam_callback(vector start, vector hit, vector end)
Definition arc.qc:769
int beam_slot
Definition arc.qc:757
vector Draw_ArcBeam_callback_last_top
Definition arc.qh:160
vector beam_dir
Definition arc.qh:106
float beam_hitlight[4]
Definition arc.qh:147
const float ARC_MAX_SEGMENTS
Definition arc.qh:103
bool beam_initialized
Definition arc.qh:131
entity beam_hiteffect
Definition arc.qh:146
vector Draw_ArcBeam_callback_last_bottom
Definition arc.qh:161
entity Draw_ArcBeam_callback_entity
Definition arc.qh:158
float beam_usevieworigin
Definition arc.qh:154
entity beam_muzzleeffect
Definition arc.qh:148
float beam_muzzlelight[4]
Definition arc.qh:149
vector beam_shotorigin
Definition arc.qh:156
float Draw_ArcBeam_callback_last_thickness
Definition arc.qh:159
entity beam_muzzleentity
Definition arc.qh:152
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:237
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:545
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 769 of file arc.qc.

770{
773
774 vector hitorigin;
775
776 #if 0
777 if(trace_fraction != 1)
778 {
779 // calculate our own hit origin as trace_endpos tends to jump around annoyingly (to player origin?)
780 hitorigin = start + (Draw_ArcBeam_callback_new_dir * Draw_ArcBeam_callback_segmentdist * trace_fraction);
782 }
783 else
784 {
785 hitorigin = hit;
786 }
787 #else
788 hitorigin = hit;
789 #endif
790
791 float thickness = beam.beam_thickness;
792
794 Draw_CylindricLine(start, hit, thickness, beam.beam_image, 0.25, -time * 3, beam.beam_color, beam.beam_alpha, DRAWFLAG_NORMAL, transformed_view_org);
795 else
796 {
797 // Thickdir shall be perpendicular to the beam and to the view-to-beam direction (WEAPONTODO: WHY)
798 // WEAPONTODO: Wouldn't it be better to be perpendicular to the beam and to the view FORWARD direction?
799 vector thickdir = normalize(cross(normalize(start - hit), transformed_view_org - start));
800
801 // draw primary beam render
802 vector top = hitorigin + (thickdir * thickness);
803 vector bottom = hitorigin - (thickdir * thickness);
804
807
808 // draw segment
809 R_BeginPolygon(beam.beam_image, DRAWFLAG_NORMAL, false); // DRAWFLAG_ADDITIVE
810 R_PolygonVertex(
811 top,
812 '0 0.5 0' + ('0 0.5 0' * (thickness / beam.beam_thickness)),
813 beam.beam_color,
814 beam.beam_alpha
815 );
816 R_PolygonVertex(
817 last_top,
818 '0 0.5 0' + ('0 0.5 0' * (Draw_ArcBeam_callback_last_thickness / beam.beam_thickness)),
819 beam.beam_color,
820 beam.beam_alpha
821 );
822 R_PolygonVertex(
823 last_bottom,
824 '0 0.5 0' * (1 - (Draw_ArcBeam_callback_last_thickness / beam.beam_thickness)),
825 beam.beam_color,
826 beam.beam_alpha
827 );
828 R_PolygonVertex(
829 bottom,
830 '0 0.5 0' * (1 - (thickness / beam.beam_thickness)),
831 beam.beam_color,
832 beam.beam_alpha
833 );
834 R_EndPolygon();
835
836 // set up for the next
840 }
841
842 // draw trailing particles
843 // NOTES:
844 // - Don't use spammy particle counts here, use a FEW small particles around the beam
845 // - We're not using WarpZone_TrailParticles here because we will handle warpzones ourselves.
846 if(beam.beam_traileffect)
847 {
848 trailparticles(beam, beam.beam_traileffect, start, hitorigin);
849 }
850}
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 1165 of file arc.qc.

1166{
1167 int sf = ReadByte();
1168 int slot = ReadByte();
1169 entity flash;
1170
1171 this.beam_slot = slot;
1172
1173 if(isnew)
1174 {
1175 int gunalign = W_GunAlign(viewmodels[slot], STAT(GUNALIGN)) - 1;
1176
1177 this.beam_shotorigin = arc_shotorigin[gunalign]; // get a starting point
1178
1179 // set other main attributes of the beam
1180 this.draw = Draw_ArcBeam;
1181 IL_PUSH(g_drawables, this);
1182 this.entremove = Remove_ArcBeam;
1183 this.move_time = time;
1184 loopsound(this, CH_SHOTS_SINGLE, SND_ARC_LOOP, VOL_BASE, ATTEN_NORM);
1185
1186 flash = new(arc_flash);
1187 flash.owner = this;
1188 flash.effects = EF_ADDITIVE | EF_FULLBRIGHT;
1189 //flash.drawmask = MASK_NORMAL;
1190 flash.solid = SOLID_NOT;
1191 flash.avelocity_z = 5000;
1192 setattachment(flash, this, "");
1193 setorigin(flash, '0 0 0');
1194
1195 this.beam_muzzleentity = flash;
1196 }
1197 else
1198 {
1199 flash = this.beam_muzzleentity;
1200 }
1201
1202 if(sf & ARC_SF_UPDATE)
1203 {
1204 if(ReadByte()) // drawlocal?
1205 {
1207 }
1208 else
1209 {
1210 this.beam_usevieworigin = 0;
1211 }
1212
1213 this.sv_entnum = ReadByte();
1214 }
1215
1216 if(!this.beam_usevieworigin)
1217 {
1218 // this.iflags = IFLAG_ORIGIN | IFLAG_ANGLES | IFLAG_V_ANGLE; // why doesn't this work?
1219 this.iflags = IFLAG_ORIGIN;
1220
1222 }
1223
1224 if(sf & ARC_SF_START) // starting location
1225 {
1226 this.origin = ReadVector();
1227 }
1228 else if(this.beam_usevieworigin) // infer the location from player location
1229 {
1230 if(this.beam_usevieworigin == 2)
1231 {
1232 // use view origin
1233 this.origin = view_origin;
1234 }
1235 else
1236 {
1237 // use player origin so that third person display still works
1238 this.origin = entcs_receiver(player_localnum).origin + ('0 0 1' * STAT(VIEWHEIGHT));
1239 }
1240 }
1241
1242 setorigin(this, this.origin);
1243
1244 if(sf & ARC_SF_WANTDIR) // want/aim direction
1245 {
1246 this.v_angle = ReadVector();
1247 }
1248
1249 if(sf & ARC_SF_BEAMDIR) // beam direction
1250 {
1251 this.angles = ReadAngleVector();
1252 }
1253
1254 if(sf & ARC_SF_BEAMTYPE) // beam type
1255 {
1256 this.beam_type = ReadByte();
1257
1258 vector beamcolor = '1 1 1';
1260 beamcolor = colormapPaletteColor(entcs_GetClientColors(this.sv_entnum - 1) & 0x0F, true);
1261
1262 switch(this.beam_type)
1263 {
1264 case ARC_BT_MISS:
1265 {
1266 this.beam_color = beamcolor;
1267 this.beam_alpha = 0.5;
1268 this.beam_thickness = 8;
1269 this.beam_traileffect = (EFFECT_ARC_BEAM);
1270 this.beam_hiteffect = (EFFECT_ARC_LIGHTNING);
1271 this.beam_hitlight[0] = 0;
1272 this.beam_hitlight[1] = 1;
1273 this.beam_hitlight[2] = 1;
1274 this.beam_hitlight[3] = 1;
1275 this.beam_muzzleeffect = EFFECT_Null;
1276 this.beam_muzzlelight[0] = 0;
1277 this.beam_muzzlelight[1] = 1;
1278 this.beam_muzzlelight[2] = 1;
1279 this.beam_muzzlelight[3] = 1;
1280 this.beam_image = "particles/lgbeam";
1282 {
1283 setmodel(flash, MDL_ARC_MUZZLEFLASH);
1284 flash.alpha = this.beam_alpha;
1285 flash.colormod = this.beam_color;
1286 flash.scale = 0.35;
1287 }
1288 break;
1289 }
1290 case ARC_BT_WALL: // grenadelauncher_muzzleflash healray_muzzleflash
1291 {
1292 this.beam_color = beamcolor;
1293 this.beam_alpha = 0.5;
1294 this.beam_thickness = 8;
1295 this.beam_traileffect = (EFFECT_ARC_BEAM);
1296 this.beam_hiteffect = (EFFECT_ARC_LIGHTNING);
1297 this.beam_hitlight[0] = 0;
1298 this.beam_hitlight[1] = 1;
1299 this.beam_hitlight[2] = 1;
1300 this.beam_hitlight[3] = 1;
1301 this.beam_muzzleeffect = EFFECT_Null; // (EFFECT_GRENADE_MUZZLEFLASH);
1302 this.beam_muzzlelight[0] = 0;
1303 this.beam_muzzlelight[1] = 1;
1304 this.beam_muzzlelight[2] = 1;
1305 this.beam_muzzlelight[3] = 1;
1306 this.beam_image = "particles/lgbeam";
1308 {
1309 setmodel(flash, MDL_ARC_MUZZLEFLASH);
1310 flash.alpha = this.beam_alpha;
1311 flash.colormod = this.beam_color;
1312 flash.scale = 0.35;
1313 }
1314 break;
1315 }
1316 case ARC_BT_HEAL:
1317 {
1318 this.beam_color = beamcolor;
1319 this.beam_alpha = 0.5;
1320 this.beam_thickness = 8;
1321 this.beam_traileffect = (EFFECT_ARC_BEAM_HEAL);
1322 this.beam_hiteffect = (EFFECT_ARC_BEAM_HEAL_IMPACT);
1323 this.beam_hitlight[0] = 0;
1324 this.beam_hitlight[1] = 1;
1325 this.beam_hitlight[2] = 1;
1326 this.beam_hitlight[3] = 1;
1327 this.beam_muzzleeffect = EFFECT_Null;
1328 this.beam_muzzlelight[0] = 0;
1329 this.beam_muzzlelight[1] = 1;
1330 this.beam_muzzlelight[2] = 1;
1331 this.beam_muzzlelight[3] = 1;
1332 this.beam_image = "particles/lgbeam";
1334 {
1335 setmodel(flash, MDL_ARC_MUZZLEFLASH);
1336 flash.alpha = this.beam_alpha;
1337 flash.colormod = this.beam_color;
1338 flash.scale = 0.35;
1339 }
1340 break;
1341 }
1342 case ARC_BT_HIT:
1343 {
1344 this.beam_color = beamcolor;
1345 this.beam_alpha = 0.5;
1346 this.beam_thickness = 8;
1347 this.beam_traileffect = (EFFECT_ARC_BEAM);
1348 this.beam_hiteffect = (EFFECT_ARC_LIGHTNING);
1349 this.beam_hitlight[0] = 20;
1350 this.beam_hitlight[1] = 1;
1351 this.beam_hitlight[2] = 0;
1352 this.beam_hitlight[3] = 0;
1353 this.beam_muzzleeffect = EFFECT_Null;
1354 this.beam_muzzlelight[0] = 50;
1355 this.beam_muzzlelight[1] = 1;
1356 this.beam_muzzlelight[2] = 0;
1357 this.beam_muzzlelight[3] = 0;
1358 this.beam_image = "particles/lgbeam";
1360 {
1361 setmodel(flash, MDL_ARC_MUZZLEFLASH);
1362 flash.alpha = this.beam_alpha;
1363 flash.colormod = this.beam_color;
1364 flash.scale = 0.35;
1365 }
1366 break;
1367 }
1368 case ARC_BT_BURST_MISS:
1369 {
1370 this.beam_color = beamcolor;
1371 this.beam_alpha = 0.5;
1372 this.beam_thickness = 14;
1373 this.beam_traileffect = (EFFECT_ARC_BEAM);
1374 this.beam_hiteffect = (EFFECT_ARC_LIGHTNING);
1375 this.beam_hitlight[0] = 0;
1376 this.beam_hitlight[1] = 1;
1377 this.beam_hitlight[2] = 1;
1378 this.beam_hitlight[3] = 1;
1379 this.beam_muzzleeffect = EFFECT_Null;
1380 this.beam_muzzlelight[0] = 0;
1381 this.beam_muzzlelight[1] = 1;
1382 this.beam_muzzlelight[2] = 1;
1383 this.beam_muzzlelight[3] = 1;
1384 this.beam_image = "particles/lgbeam";
1386 {
1387 setmodel(flash, MDL_ARC_MUZZLEFLASH);
1388 flash.alpha = this.beam_alpha;
1389 flash.colormod = this.beam_color;
1390 flash.scale = 0.35;
1391 }
1392 break;
1393 }
1394 case ARC_BT_BURST_WALL:
1395 {
1396 this.beam_color = beamcolor;
1397 this.beam_alpha = 0.5;
1398 this.beam_thickness = 14;
1399 this.beam_traileffect = (EFFECT_ARC_BEAM);
1400 this.beam_hiteffect = (EFFECT_ARC_LIGHTNING);
1401 this.beam_hitlight[0] = 0;
1402 this.beam_hitlight[1] = 1;
1403 this.beam_hitlight[2] = 1;
1404 this.beam_hitlight[3] = 1;
1405 this.beam_muzzleeffect = EFFECT_Null;
1406 this.beam_muzzlelight[0] = 0;
1407 this.beam_muzzlelight[1] = 1;
1408 this.beam_muzzlelight[2] = 1;
1409 this.beam_muzzlelight[3] = 1;
1410 this.beam_image = "particles/lgbeam";
1412 {
1413 setmodel(flash, MDL_ARC_MUZZLEFLASH);
1414 flash.alpha = this.beam_alpha;
1415 flash.colormod = this.beam_color;
1416 flash.scale = 0.35;
1417 }
1418 break;
1419 }
1420 case ARC_BT_BURST_HEAL:
1421 {
1422 this.beam_color = beamcolor;
1423 this.beam_alpha = 0.5;
1424 this.beam_thickness = 14;
1425 this.beam_traileffect = (EFFECT_ARC_BEAM_HEAL);
1426 this.beam_hiteffect = (EFFECT_ARC_BEAM_HEAL_IMPACT2);
1427 this.beam_hitlight[0] = 0;
1428 this.beam_hitlight[1] = 1;
1429 this.beam_hitlight[2] = 1;
1430 this.beam_hitlight[3] = 1;
1431 this.beam_muzzleeffect = EFFECT_Null;
1432 this.beam_muzzlelight[0] = 0;
1433 this.beam_muzzlelight[1] = 1;
1434 this.beam_muzzlelight[2] = 1;
1435 this.beam_muzzlelight[3] = 1;
1436 this.beam_image = "particles/lgbeam";
1438 {
1439 setmodel(flash, MDL_ARC_MUZZLEFLASH);
1440 flash.alpha = this.beam_alpha;
1441 flash.colormod = this.beam_color;
1442 flash.scale = 0.35;
1443 }
1444 break;
1445 }
1446 case ARC_BT_BURST_HIT:
1447 {
1448 this.beam_color = beamcolor;
1449 this.beam_alpha = 0.5;
1450 this.beam_thickness = 14;
1451 this.beam_traileffect = (EFFECT_ARC_BEAM);
1452 this.beam_hiteffect = (EFFECT_ARC_LIGHTNING);
1453 this.beam_hitlight[0] = 0;
1454 this.beam_hitlight[1] = 1;
1455 this.beam_hitlight[2] = 1;
1456 this.beam_hitlight[3] = 1;
1457 this.beam_muzzleeffect = EFFECT_Null;
1458 this.beam_muzzlelight[0] = 0;
1459 this.beam_muzzlelight[1] = 1;
1460 this.beam_muzzlelight[2] = 1;
1461 this.beam_muzzlelight[3] = 1;
1462 this.beam_image = "particles/lgbeam";
1464 {
1465 setmodel(flash, MDL_ARC_MUZZLEFLASH);
1466 flash.alpha = this.beam_alpha;
1467 flash.colormod = this.beam_color;
1468 flash.scale = 0.35;
1469 }
1470 break;
1471 }
1472
1473 // shouldn't be possible, but lets make it colorful if it does :D
1474 default:
1475 {
1476 this.beam_color = randomvec();
1477 this.beam_alpha = 1;
1478 this.beam_thickness = 8;
1479 this.beam_traileffect = NULL;
1480 this.beam_hiteffect = NULL;
1481 this.beam_hitlight[0] = 0;
1482 this.beam_hitlight[1] = 1;
1483 this.beam_hitlight[2] = 1;
1484 this.beam_hitlight[3] = 1;
1485 this.beam_muzzleeffect = EFFECT_Null;
1486 this.beam_muzzlelight[0] = 0;
1487 this.beam_muzzlelight[1] = 1;
1488 this.beam_muzzlelight[2] = 1;
1489 this.beam_muzzlelight[3] = 1;
1490 this.beam_image = "particles/lgbeam";
1492 {
1493 setmodel(flash, MDL_ARC_MUZZLEFLASH);
1494 flash.alpha = this.beam_alpha;
1495 flash.colormod = this.beam_color;
1496 flash.scale = 0.35;
1497 }
1498 break;
1499 }
1500 }
1501 }
1502
1503 if(!this.beam_usevieworigin)
1504 {
1506 }
1507 return true;
1508}
void Remove_ArcBeam(entity this)
Definition arc.qc:1159
void Draw_ArcBeam(entity this)
Definition arc.qc:863
const int ARC_BT_HEAL
Definition arc.qh:112
const int ARC_SF_UPDATE
Definition arc.qh:120
const int ARC_BT_HIT
Definition arc.qh:113
const int ARC_SF_WANTDIR
Definition arc.qh:122
const int ARC_SF_BEAMDIR
Definition arc.qh:123
int beam_type
Definition arc.qh:108
vector arc_shotorigin[4]
Definition arc.qh:104
const int ARC_BT_WALL
Definition arc.qh:111
const int ARC_SF_BEAMTYPE
Definition arc.qh:124
entity beam_traileffect
Definition arc.qh:145
const int ARC_BT_BURST_HEAL
Definition arc.qh:116
float beam_thickness
Definition arc.qh:144
const int ARC_BT_MISS
Definition arc.qh:110
const int ARC_BT_BURST_MISS
Definition arc.qh:114
string beam_image
Definition arc.qh:150
const int ARC_BT_BURST_WALL
Definition arc.qh:115
const int ARC_BT_BURST_HIT
Definition arc.qh:117
const int ARC_SF_START
Definition arc.qh:121
float beam_alpha
Definition arc.qh:143
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:367
#define ReadAngleVector()
Definition net.qh:369
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:207

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

1160{
1161 delete(this.beam_muzzleentity);
1162 sound(this, CH_SHOTS_SINGLE, SND_Null, VOL_BASE, ATTEN_NORM);
1163}

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

853{
854 entity e;
855 for (e = NULL; (e = findfloat(e, beam_usevieworigin, 1)); ) {
856 e.beam_initialized = false;
857 }
858 for (e = NULL; (e = findfloat(e, beam_usevieworigin, 2)); ) {
859 e.beam_initialized = false;
860 }
861}
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 46 of file arc.qc.

47{
48 for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
49 {
50 .entity weaponentity = weaponentities[slot];
51 if(!player.(weaponentity).arc_beam)
52 continue;
53 player.(weaponentity).arc_beam.beam_dir = forward;
54 player.(weaponentity).arc_beam.beam_teleporttime = time;
55 }
56}
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 508 of file arc.qc.

509{
510 if(!actor.(weaponentity).arc_beam || wasfreed(actor.(weaponentity).arc_beam))
511 {
512 w_ready(thiswep, actor, weaponentity, fire);
513 return;
514 }
515
516 // attack handled by the beam itself, this is just a loop to keep the attack happening!
517
518 // NOTE: arc doesn't use a refire
519 //ATTACK_FINISHED(actor, weaponentity) = time + WEP_CVAR_PRI(WEP_ARC, refire) * W_WeaponRateFactor(actor);
520 actor.(weaponentity).wframe = WFRAME_FIRE1;
521 weapon_thinkf(actor, weaponentity, WFRAME_DONTCHANGE, WEP_CVAR(WEP_ARC, beam_animtime), W_Arc_Attack);
522}
void W_Arc_Attack(Weapon thiswep, entity actor,.entity weaponentity, int fire)
Definition arc.qc:508
WFRAME wframe
Definition all.qh:414
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 137 of file arc.qc.

138{
139 W_SetupShot(actor, weaponentity, false, 2, SND_ARC_BOLT_FIRE, CH_WEAPON_A, WEP_CVAR(WEP_ARC, bolt_damage), thiswep.m_id | HITTYPE_SECONDARY);
140
141 W_MuzzleFlash(thiswep, actor, weaponentity, w_shotorg, w_shotdir);
142
143 entity missile = new(missile);
144 missile.owner = missile.realowner = actor;
145 missile.bot_dodge = true;
146 IL_PUSH(g_bot_dodge, missile);
147 missile.bot_dodgerating = WEP_CVAR(WEP_ARC, bolt_damage);
148
149 missile.takedamage = DAMAGE_YES;
150 SetResourceExplicit(missile, RES_HEALTH, WEP_CVAR(WEP_ARC, bolt_health));
151 missile.damageforcescale = WEP_CVAR(WEP_ARC, bolt_damageforcescale);
152 missile.event_damage = W_Arc_Bolt_Damage;
153 missile.damagedbycontents = true;
155
156 settouch(missile, W_Arc_Bolt_Touch);
157 missile.cnt = 0;
158 missile.use = W_Arc_Bolt_Explode_use;
160 missile.nextthink = time + WEP_CVAR(WEP_ARC, bolt_lifetime);
161 PROJECTILE_MAKETRIGGER(missile);
162 missile.projectiledeathtype = thiswep.m_id | HITTYPE_SECONDARY;
163 missile.weaponentity_fld = weaponentity;
164 setorigin(missile, w_shotorg);
165 setsize(missile, '0 0 0', '0 0 0');
166
168 W_SetupProjVelocity_PRE(missile, WEP_ARC, bolt_);
169
170 missile.angles = vectoangles(missile.velocity);
171 missile.flags = FL_PROJECTILE;
172 IL_PUSH(g_projectiles, missile);
173 missile.missile_flags = MIF_SPLASH;
174
175 CSQCProjectile(missile, true, PROJECTILE_ARC_BOLT, true);
176
177 MUTATOR_CALLHOOK(EditProjectile, actor, missile);
178
179 actor.(weaponentity).misc_bulletcounter = actor.(weaponentity).misc_bulletcounter + 1;
180 if(actor.(weaponentity).misc_bulletcounter == 0)
181 {
182 ATTACK_FINISHED(actor, weaponentity) = time + WEP_CVAR(WEP_ARC, bolt_refire2) * W_WeaponRateFactor(actor);
183 weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR(WEP_ARC, bolt_refire), w_ready);
184 }
185 else
186 {
187 weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR(WEP_ARC, bolt_refire), W_Arc_Attack_Bolt);
188 }
189}
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:137
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:114
#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:45
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:135
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:63
#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:728
#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 488 of file arc.qc.

489{
490 // only play fire sound if 1 sec has passed since player let go the fire button
491 if(time - actor.(weaponentity).beam_prev > 1)
492 sound(actor, CH_WEAPON_A, SND_ARC_FIRE, VOL_BASE, ATTN_NORM);
493
494 entity beam = actor.(weaponentity).arc_beam = new(W_Arc_Beam);
495 beam.weaponentity_fld = weaponentity;
496 beam.solid = SOLID_NOT;
498 beam.owner = actor;
500 beam.bot_dodge = true;
501 IL_PUSH(g_bot_dodge, beam);
502 beam.bot_dodgerating = WEP_CVAR(WEP_ARC, beam_damage);
503 beam.beam_bursting = boolean(burst);
504 Net_LinkEntity(beam, false, 0, W_Arc_Beam_Send);
505
506 getthink(beam)(beam);
507}
void W_Arc_Beam(bool burst, entity actor,.entity weaponentity)
Definition arc.qc:488
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:191
#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:123
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 float drawlocal = ((to == this.owner) || ((to.enemy == this.owner) && IS_SPEC(to)));
16 if(drawlocal) { sf &= ~ARC_SF_LOCALMASK; }
17
20
21 if(sf & ARC_SF_UPDATE)
22 {
23 WriteByte(MSG_ENTITY, drawlocal);
25 }
26 if(sf & ARC_SF_START) // starting location
27 {
28 WriteVector(MSG_ENTITY, this.beam_start);
29 }
30 if(sf & ARC_SF_WANTDIR) // want/aim direction
31 {
32 WriteVector(MSG_ENTITY, this.beam_wantdir);
33 }
34 if(sf & ARC_SF_BEAMDIR) // beam direction
35 {
36 WriteAngleVector(MSG_ENTITY, this.beam_dir);
37 }
38 if(sf & ARC_SF_BEAMTYPE) // beam type
39 {
41 }
42
43 return true;
44}
const int ARC_SF_LOCALMASK
Definition arc.qh:125
vector beam_wantdir
Definition arc.qh:107
vector beam_start
Definition arc.qh:105
entity owner
Definition main.qh:87
const int MSG_ENTITY
Definition net.qh:115
#define WriteHeader(to, id)
Definition net.qh:221
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 191 of file arc.qc.

192{
193 .entity weaponentity = this.weaponentity_fld;
194 entity own = this.owner;
195 if(this != own.(weaponentity).arc_beam)
196 {
197 delete(this);
198 return;
199 }
200
201 int burst = 0;
202 if( (PHYS_INPUT_BUTTON_ATCK2(own) && !WEP_CVAR(WEP_ARC, bolt)) || this.beam_bursting)
203 {
204 if(!this.beam_bursting)
205 this.beam_bursting = true;
206 burst = ARC_BT_BURSTMASK;
207 }
208
209 Weapon thiswep = WEP_ARC;
210
211 // TODO: use standard weapon use checks here!
212 if(!IS_PLAYER(own) || IS_DEAD(own) || STAT(FROZEN, own) || game_stopped || own.vehicle
213 || !weapon_prepareattack_check(thiswep, own, weaponentity, this.beam_bursting, -1)
214 || own.(weaponentity).m_switchweapon != WEP_ARC
215 || (!PHYS_INPUT_BUTTON_ATCK(own) && !burst)
216 || (WEP_CVAR(WEP_ARC, overheat_max) > 0 && this.beam_heat >= WEP_CVAR(WEP_ARC, overheat_max)) )
217 {
218 if ( WEP_CVAR(WEP_ARC, cooldown) > 0 )
219 {
220 float cooldown_speed = 0;
221 if ( this.beam_heat > WEP_CVAR(WEP_ARC, overheat_min) && WEP_CVAR(WEP_ARC, cooldown) > 0 )
222 {
223 cooldown_speed = WEP_CVAR(WEP_ARC, cooldown);
224 }
225 else if ( !burst )
226 {
227 cooldown_speed = this.beam_heat / WEP_CVAR(WEP_ARC, beam_refire);
228 }
229
230 bool overheat = (WEP_CVAR(WEP_ARC, overheat_max) > 0 && this.beam_heat >= WEP_CVAR(WEP_ARC, overheat_max));
231 if (overheat)
232 {
233 Send_Effect(EFFECT_ARC_OVERHEAT, this.beam_start, this.beam_wantdir, 1);
234 sound(this, CH_WEAPON_A, SND_ARC_STOP, VOL_BASE, ATTN_NORM);
235 }
236
237 if ( cooldown_speed )
238 {
239 if (WEP_CVAR(WEP_ARC, cooldown_release) || overheat)
240 own.arc_overheat = time + this.beam_heat / cooldown_speed;
241 own.arc_cooldown = cooldown_speed;
242 }
243
244 }
245
246 if(this == own.(weaponentity).arc_beam) { own.(weaponentity).arc_beam = NULL; }
247 if(!thiswep.wr_checkammo1(thiswep, own, weaponentity) && !(own.items & IT_UNLIMITED_AMMO))
248 {
249 // note: this doesn't force the switch
250 W_SwitchToOtherWeapon(own, weaponentity);
251 }
252 own.(weaponentity).arc_BUTTON_ATCK_prev = false; // allow switching weapons
253 delete(this);
254 return;
255 }
256
257 // decrease ammo
258 float coefficient = frametime;
259 if(!(own.items & IT_UNLIMITED_AMMO))
260 {
261 float rootammo;
262 if(burst)
263 { rootammo = WEP_CVAR(WEP_ARC, burst_ammo); }
264 else
265 { rootammo = WEP_CVAR(WEP_ARC, beam_ammo); }
266
267 if(rootammo)
268 {
269 coefficient = min(coefficient, GetResource(own, thiswep.ammo_type) / rootammo);
270 SetResource(own, thiswep.ammo_type, max(0, GetResource(own, thiswep.ammo_type) - (rootammo * frametime)));
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
295 // network information: shot origin and want/aim direction
296 if(this.beam_start != w_shotorg)
297 {
298 this.SendFlags |= ARC_SF_START;
299 this.beam_start = w_shotorg;
300 }
301 if(this.beam_wantdir != w_shotdir)
302 {
304 this.beam_wantdir = w_shotdir;
305 }
306
307 if(!this.beam_initialized)
308 {
309 this.beam_dir = w_shotdir;
310 this.beam_initialized = true;
311 }
312
313 // WEAPONTODO: Detect player velocity so that the beam curves when moving too
314 // idea: blend together this.beam_dir with the inverted direction the player is moving in
315 // might have to make some special accomodation so that it only uses view_right and view_up
316
317 // note that if we do this, it'll always be corrected to a maximum angle by beam_maxangle handling
318
319 float segments = 1;
320 if(this.beam_dir != w_shotdir)
321 {
322 // calculate how much we're going to move the end of the beam to the want position
323 float angle = vlen(w_shotdir - this.beam_dir) * RAD2DEG;
324 if (angle < 0.01) // snap only when very close so it's impossible to notice
325 this.beam_dir = w_shotdir; // snap otherwise vectors will never actually be the same
326 else
327 {
328 float max_blendfactor = 1;
329 if(angle && (angle > WEP_CVAR(WEP_ARC, beam_maxangle)))
330 max_blendfactor = WEP_CVAR(WEP_ARC, beam_maxangle) / angle;
331 float blendfactor = bound(0, (1 - (WEP_CVAR(WEP_ARC, beam_returnspeed) * frametime)), max_blendfactor);
332 this.beam_dir = normalize((w_shotdir * (1 - blendfactor)) + (this.beam_dir * blendfactor));
333 }
334
335 // network information: beam direction
337
338 // calculate how many segments are needed
339 float max_allowed_segments = ARC_MAX_SEGMENTS;
340 if(WEP_CVAR(WEP_ARC, beam_distancepersegment))
341 {
342 max_allowed_segments = 1 + vlen(w_shotdir) / WEP_CVAR(WEP_ARC, beam_distancepersegment);
343 max_allowed_segments = bound(1, max_allowed_segments, ARC_MAX_SEGMENTS);
344 }
345
346 if(WEP_CVAR(WEP_ARC, beam_degreespersegment))
347 {
348 segments = min(angle, WEP_CVAR(WEP_ARC, beam_maxangle)) / WEP_CVAR(WEP_ARC, beam_degreespersegment);
349 segments = bound(1, segments, max_allowed_segments);
350 }
351 }
352
353 vector beam_endpos = (w_shotorg + (this.beam_dir * WEP_CVAR(WEP_ARC, beam_range)));
354 float beam_controlpoint_dist = WEP_CVAR(WEP_ARC, beam_range) * bound(0.001, 1 - WEP_CVAR(WEP_ARC, beam_tightness), 1);
355 vector beam_controlpoint = w_shotorg + w_shotdir * beam_controlpoint_dist;
356
357 int new_beam_type = 0;
358 vector last_origin = 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
375 own,
376 last_origin,
377 new_origin,
379 NULL,
380 ANTILAG_LATENCY(own)
381 );
382
383 last_origin_prev = last_origin; // used later to calculate damage force direction
384 last_origin = trace_endpos;
385
386 // Do all the transforms for warpzones right now, as we already "are" in the post-trace
387 // system (if we hit a player, that's always BEHIND the last passed wz).
389
390 if(trace_fraction == 1)
391 {
392 beam_controlpoint = WarpZone_TransformOrigin(WarpZone_trace_transform, beam_controlpoint);
393 beam_endpos = WarpZone_TransformOrigin(WarpZone_trace_transform, beam_endpos);
394 continue;
395 }
396
397 if(!trace_ent)
398 {
399 // we collided with geometry
400 new_beam_type = ARC_BT_WALL;
401 break;
402 }
403
404 // we collided with an entity
405 bool is_player = (IS_PLAYER(trace_ent) || trace_ent.classname == "body" || IS_MONSTER(trace_ent));
406 if(trace_ent != own && SAME_TEAM(own, trace_ent))
407 {
408 float roothealth = ((burst) ? WEP_CVAR(WEP_ARC, burst_healing_hps) : WEP_CVAR(WEP_ARC, beam_healing_hps));
409 float rootarmor = ((burst) ? WEP_CVAR(WEP_ARC, burst_healing_aps) : WEP_CVAR(WEP_ARC, beam_healing_aps));
410 float hplimit = ((IS_PLAYER(trace_ent)) ? WEP_CVAR(WEP_ARC, beam_healing_hmax) : RES_LIMIT_NONE);
411 Heal(trace_ent, own, (roothealth * coefficient), hplimit);
412 if(IS_PLAYER(trace_ent) && rootarmor
413 && GetResource(trace_ent, RES_ARMOR) <= WEP_CVAR(WEP_ARC, beam_healing_amax))
414 {
415 GiveResourceWithLimit(trace_ent, RES_ARMOR, (rootarmor * coefficient), WEP_CVAR(WEP_ARC, beam_healing_amax));
416 trace_ent.pauserotarmor_finished = max(
417 trace_ent.pauserotarmor_finished,
419 );
420 }
421 if(roothealth || rootarmor)
422 new_beam_type = ARC_BT_HEAL;
423 }
424 else if(trace_ent.takedamage && (is_player || WEP_CVAR(WEP_ARC, beam_nonplayerdamage)))
425 {
426 // calculate our own hit origin as trace_endpos tends to jump around annoyingly (to player origin?)
427 // NO. trace_endpos should be just fine. If not,
428 // that's an engine bug that needs proper debugging.
429 vector hitorigin = trace_endpos;
430
432 WEP_CVAR(WEP_ARC, beam_falloff_mindist),
433 WEP_CVAR(WEP_ARC, beam_falloff_maxdist),
434 WEP_CVAR(WEP_ARC, beam_falloff_halflifedist),
436 );
437
438 float rootdamage;
439 if(is_player)
440 {
441 if(burst)
442 rootdamage = WEP_CVAR(WEP_ARC, burst_damage);
443 else
444 rootdamage = WEP_CVAR(WEP_ARC, beam_damage);
445 }
446 else
447 rootdamage = WEP_CVAR(WEP_ARC, beam_nonplayerdamage);
448
450 {
451 accuracy_add(own, WEP_ARC, 0, rootdamage * coefficient * falloff, 0); // add to hit
452 }
453
454 vector new_dir = normalize(new_origin - last_origin_prev);
456 Damage(
457 trace_ent,
458 own,
459 own,
460 rootdamage * coefficient * falloff,
461 WEP_ARC.m_id,
462 weaponentity,
463 hitorigin,
464 WEP_CVAR(WEP_ARC, beam_force) * coefficient * falloff * new_dir
465 );
466
467 new_beam_type = ARC_BT_HIT;
468 }
469 break;
470 }
471
472 // te_explosion(trace_endpos);
473
474 // if we're bursting, use burst visual effects
475 new_beam_type |= burst;
476
477 // network information: beam type
478 if(new_beam_type != this.beam_type)
479 {
481 this.beam_type = new_beam_type;
482 }
483
484 own.(weaponentity).beam_prev = time;
485 this.nextthink = time;
486}
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:133
float beam_heat
Definition arc.qh:134
bool arc_BUTTON_ATCK_prev
Definition arc.qh:129
bool beam_bursting
Definition arc.qh:132
float beam_prev
Definition arc.qh:130
const int ARC_BT_BURSTMASK
Definition arc.qh:118
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:44
Resource ammo_type
M: ammotype : main ammo type.
Definition weapon.qh:51
virtual void wr_checkammo1()
(SERVER) checks ammo for weapon primary
Definition weapon.qh:92
const int IT_UNLIMITED_AMMO
Definition item.qh:23
int falloff
Definition impulse.qh:12
#define IS_DEAD(s)
Definition player.qh:245
#define IS_PLAYER(s)
Definition player.qh:243
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:503
bool Heal(entity targ, entity inflictor, float amount, float limit)
Definition damage.qc:987
RES_ARMOR
Definition ent_cs.qc:130
int SendFlags
Definition net.qh:118
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)
Definition selection.qc:256
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:21
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
104 if(!W_CheckProjectileDamage(inflictor.realowner, this.realowner, deathtype, -1))
105 return; // g_projectiles_damage says to halt
106
107 TakeResource(this, RES_HEALTH, damage);
108 this.angles = vectoangles(this.velocity);
109
110 if(GetResource(this, RES_HEALTH) <= 0)
111 W_PrepareExplosionByDamage(this, attacker, getthink(this));
112}
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 83 of file arc.qc.

84{
85 this.event_damage = func_null;
86 RadiusDamage(this, this.realowner,
87 WEP_CVAR(WEP_ARC, bolt_damage), WEP_CVAR(WEP_ARC, bolt_edgedamage), WEP_CVAR(WEP_ARC, bolt_radius),
88 NULL, NULL, WEP_CVAR(WEP_ARC, bolt_force),
89 this.projectiledeathtype, this.weaponentity_fld, directhitentity);
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:981
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:83

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

115{
117 if(this.cnt >= WEP_CVAR(WEP_ARC, bolt_bounce_count) || !WEP_CVAR(WEP_ARC, bolt_bounce_count) || toucher.takedamage == DAMAGE_AIM) {
118 this.use(this, NULL, toucher);
119 } else {
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 {
127 RadiusDamage(this, this.realowner,
128 WEP_CVAR(WEP_ARC, bolt_damage), WEP_CVAR(WEP_ARC, bolt_edgedamage), WEP_CVAR(WEP_ARC, bolt_radius),
129 NULL, NULL, WEP_CVAR(WEP_ARC, bolt_force),
131 }
132 if(this.cnt == 1 && WEP_CVAR(WEP_ARC, bolt_bounce_lifetime))
133 this.nextthink = time + WEP_CVAR(WEP_ARC, bolt_bounce_lifetime);
134 }
135}
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 755 of file arc.qc.

Referenced by Draw_ArcBeam(), and Draw_ArcBeam_callback().

◆ beam_slot

int beam_slot

Definition at line 757 of file arc.qc.

Referenced by Draw_ArcBeam(), and NET_HANDLE().