11#if ( CLIENT_DLL || GAME_DLL ) && GMOD_DLL
2+ #if GAME_DLL
3+ using Game . Server ;
4+ #endif
5+ using Source ;
26using Source . Common ;
7+ using Source . Common . Mathematics ;
8+
9+ using System . Numerics ;
310namespace Game . Shared . GarrysMod ;
411using FIELD = Source . FIELD < WeaponStunStick > ;
512
613[ LinkEntityToClass ( "weapon_stunstick" ) ]
714[ PrecacheWeaponRegister ( "weapon_stunstick" ) ]
815[ NetworkName ( "CWeaponStunStick" ) ]
9- public class WeaponStunStick : BaseHL2MPBludgeonWeapon
16+ public partial class WeaponStunStick : BaseHL2MPBludgeonWeapon
1017{
1118 public static readonly
1219#if CLIENT_DLL
@@ -28,7 +35,210 @@ public static readonly
2835 public static readonly new ServerClass ServerClass = new ServerClass ( DT_WeaponStunStick ) ;
2936#endif
3037 [ NetworkName ( "m_bActive" ) ]
38+ #if CLIENT_DLL
3139 public bool Active ;
32- public override float GetFireRate ( ) => 0.2f ;
40+ #else
41+ [ NetworkVar ] public partial bool Active { get ; set ; }
42+ #endif
43+
44+ public const float STUNSTICK_RANGE = 75.0f ;
45+ public const float STUNSTICK_REFIRE = 0.8f ;
46+ public const string STUNSTICK_BEAM_MATERIAL = "sprites/lgtning.vmt" ;
47+
48+ #if ! CLIENT_DLL
49+ static readonly ActTable [ ] acttable = [
50+ new ( ) { BaseAct = Activity . ACT_RANGE_ATTACK1 , WeaponAct = Activity . ACT_RANGE_ATTACK_SLAM , Required = true } ,
51+ new ( ) { BaseAct = Activity . ACT_HL2MP_IDLE , WeaponAct = Activity . ACT_HL2MP_IDLE_MELEE , Required = false } ,
52+ new ( ) { BaseAct = Activity . ACT_HL2MP_RUN , WeaponAct = Activity . ACT_HL2MP_RUN_MELEE , Required = false } ,
53+ new ( ) { BaseAct = Activity . ACT_HL2MP_IDLE_CROUCH , WeaponAct = Activity . ACT_HL2MP_IDLE_CROUCH_MELEE , Required = false } ,
54+ new ( ) { BaseAct = Activity . ACT_HL2MP_WALK_CROUCH , WeaponAct = Activity . ACT_HL2MP_WALK_CROUCH_MELEE , Required = false } ,
55+ new ( ) { BaseAct = Activity . ACT_HL2MP_GESTURE_RANGE_ATTACK , WeaponAct = Activity . ACT_HL2MP_GESTURE_RANGE_ATTACK_MELEE , Required = false } ,
56+ new ( ) { BaseAct = Activity . ACT_HL2MP_GESTURE_RELOAD , WeaponAct = Activity . ACT_HL2MP_GESTURE_RELOAD_MELEE , Required = false } ,
57+ new ( ) { BaseAct = Activity . ACT_HL2MP_JUMP , WeaponAct = Activity . ACT_HL2MP_JUMP_MELEE , Required = false } ,
58+ ] ;
59+
60+ public override ReadOnlySpan < ActTable > ActivityList ( ) => acttable ;
61+ #endif
62+
63+ public WeaponStunStick ( ) {
64+ Active = false ;
65+ }
66+
67+ public override void Spawn ( ) {
68+ Precache ( ) ;
69+
70+ base . Spawn ( ) ;
71+ AddSolidFlags ( SolidFlags . NotStandable ) ;
72+ }
73+
74+ public override void Precache ( ) {
75+ base . Precache ( ) ;
76+
77+ PrecacheScriptSound ( "Weapon_StunStick.Activate" ) ;
78+ PrecacheScriptSound ( "Weapon_StunStick.Deactivate" ) ;
79+
80+ PrecacheModel ( STUNSTICK_BEAM_MATERIAL ) ;
81+ PrecacheModel ( "sprites/light_glow02_add.vmt" ) ;
82+ PrecacheModel ( "effects/blueflare1.vmt" ) ;
83+ PrecacheModel ( "sprites/light_glow02_add_noz.vmt" ) ;
84+ }
85+
86+ public override float GetRange ( ) => STUNSTICK_RANGE ;
87+ public override float GetFireRate ( ) => STUNSTICK_REFIRE ;
88+
89+ public override float GetDamageForActivity ( Activity hitActivity ) => 40.0f ;
90+
91+ public override bool PlayFleshyHittySoundOnHit ( ) => true ;
92+
93+ public override void SecondaryAttack ( ) { }
94+
95+ #if ! CLIENT_DLL
96+ public override SCOND_t WeaponMeleeAttack1Condition ( float dot , float dist ) {
97+ AI_BaseNPC npc = GetOwner ( ) ! . MyNPCPointer ( ) ! ;
98+ BaseEntity ? enemy = npc . GetEnemy ( ) ;
99+ if ( enemy == null )
100+ return SCOND_t . COND_NONE ;
101+
102+ enemy . GetVelocity ( out Vector3 velocity , out _ ) ;
103+
104+ float dt = WeaponCrowbar . sk_crowbar_lead_time . GetFloat ( ) ;
105+ dt += random . RandomFloat ( - 0.3f , 0.2f ) ;
106+ if ( dt < 0.0f )
107+ dt = 0.0f ;
108+
109+ MathLib . VectorMA ( enemy . WorldSpaceCenter ( ) , dt , velocity , out Vector3 extrapolatedPos ) ;
110+
111+ Vector3 delta = extrapolatedPos - npc . WorldSpaceCenter ( ) ;
112+
113+ if ( MathF . Abs ( delta . Z ) > 70 )
114+ return SCOND_t . COND_TOO_FAR_TO_ATTACK ;
115+
116+ Vector3 forward = npc . BodyDirection2D ( ) ;
117+ delta . Z = 0.0f ;
118+ float extrapolatedDot = MathLib . DotProduct2D ( delta . AsVector2D ( ) , forward . AsVector2D ( ) ) ;
119+ if ( ( dot < 0.7 ) && ( extrapolatedDot < 0.7 ) )
120+ return SCOND_t . COND_NOT_FACING_ATTACK ;
121+
122+ float extrapolatedDist = MathLib . Vector2DLength ( delta . AsVector2D ( ) ) ;
123+
124+ if ( enemy . IsPlayer ( ) ) {
125+ Vector3 projectEnemy = enemy . GetAbsOrigin ( ) + ( enemy . GetAbsVelocity ( ) * 0.35f ) ;
126+ Vector3 projectMe = GetAbsOrigin ( ) ;
127+
128+ if ( MathLib . Vector2DLength ( ( projectMe - projectEnemy ) . AsVector2D ( ) ) <= 48.0f )
129+ return SCOND_t . COND_CAN_MELEE_ATTACK1 ;
130+ }
131+
132+ float targetDist = 48.0f ;
133+ if ( ( dist > targetDist ) && ( extrapolatedDist > targetDist ) )
134+ return SCOND_t . COND_TOO_FAR_TO_ATTACK ;
135+
136+ return SCOND_t . COND_CAN_MELEE_ATTACK1 ;
137+ }
138+
139+ public override void Operator_HandleAnimEvent ( ref AnimEvent animEvent , BaseCombatCharacter op ) {
140+ switch ( animEvent . Event ) {
141+ case EVENT_WEAPON_MELEE_HIT : {
142+ MathLib . AngleVectors ( GetAbsAngles ( ) , out Vector3 direction ) ;
143+
144+ BaseEntity ? enemy = op . MyNPCPointer ( ) ? . GetEnemy ( ) ;
145+ if ( enemy != null ) {
146+ Vector3 delta = enemy . WorldSpaceCenter ( ) - op . Weapon_ShootPosition ( ) ;
147+ MathLib . VectorNormalize ( ref delta ) ;
148+
149+ Vector2 delta2D = delta . AsVector2D ( ) ;
150+ float length2D = delta2D . Length ( ) ;
151+ if ( length2D != 0 )
152+ delta2D /= length2D ;
153+ if ( MathLib . DotProduct2D ( delta2D , direction . AsVector2D ( ) ) > 0.8f )
154+ direction = delta ;
155+ }
156+
157+ MathLib . VectorMA ( op . Weapon_ShootPosition ( ) , 32 , direction , out Vector3 end ) ;
158+ BaseEntity ? hurt = op . CheckTraceHullAttack ( op . Weapon_ShootPosition ( ) , end ,
159+ new ( - 16 , - 16 , - 40 ) , new ( 16 , 16 , 16 ) , GetDamageForActivity ( GetActivity ( ) ) , DamageType . Club , 0.5f , false ) ;
160+
161+ if ( hurt != null ) {
162+ WeaponSound ( Shared . WeaponSound . MeleeHit ) ;
163+
164+ BasePlayer ? player = ToBasePlayer ( hurt ) ;
165+
166+ if ( player != null && ( player . GetFlags ( ) & EntityFlags . GodMode ) == 0 ) {
167+ float yawKick = random . RandomFloat ( - 48 , - 24 ) ;
168+
169+ player . ViewPunch ( new QAngle ( - 16 , yawKick , 2 ) ) ;
170+
171+ Vector3 dir = hurt . GetAbsOrigin ( ) - GetAbsOrigin ( ) ;
172+
173+ if ( player . GetGroundEntity ( ) == op ) {
174+ dir = direction ;
175+ dir . Z = 0 ;
176+ }
177+
178+ MathLib . VectorNormalize ( ref dir ) ;
179+
180+ dir *= 500.0f ;
181+
182+ if ( ( player . GetFlags ( ) & EntityFlags . OnGround ) == 0 )
183+ dir . Z = 0.0f ;
184+
185+ hurt . ApplyAbsVelocityImpulse ( dir ) ;
186+
187+ Util . ScreenFade ( player , new ( 128 , 0 , 0 , 128 ) , 0.5f , 0.1f , FadeFlags . In ) ;
188+
189+ player . ForceDropOfCarriedPhysObjects ( null ) ;
190+ }
191+ }
192+ else
193+ WeaponSound ( Shared . WeaponSound . MeleeMiss ) ;
194+ }
195+ break ;
196+ default :
197+ base . Operator_HandleAnimEvent ( ref animEvent , op ) ;
198+ break ;
199+ }
200+ }
201+ #endif
202+
203+ public void SetStunState ( bool state ) {
204+ Active = state ;
205+
206+ if ( Active ) {
207+ #if ! CLIENT_DLL
208+ GetAttachment ( 1 , out Vector3 attachment , out QAngle _ ) ;
209+ g_pEffects . Sparks ( attachment ) ;
210+ #endif
211+
212+ EmitSound ( "Weapon_StunStick.Activate" ) ;
213+ }
214+ else
215+ EmitSound ( "Weapon_StunStick.Deactivate" ) ;
216+ }
217+
218+ public bool GetStunState ( ) => Active ;
219+
220+ public override bool Deploy ( ) {
221+ SetStunState ( true ) ;
222+
223+ return base . Deploy ( ) ;
224+ }
225+
226+ public override bool Holster ( BaseCombatWeapon ? switchingTo = null ) {
227+ if ( base . Holster ( switchingTo ) == false )
228+ return false ;
229+
230+ SetStunState ( false ) ;
231+ SetWeaponVisible ( false ) ;
232+
233+ return true ;
234+ }
235+
236+ public override void Drop ( in Vector3 velocity ) {
237+ SetStunState ( false ) ;
238+
239+ #if ! CLIENT_DLL
240+ Util . Remove ( this ) ;
241+ #endif
242+ }
33243}
34244#endif
0 commit comments