-
Notifications
You must be signed in to change notification settings - Fork 49
Expand file tree
/
Copy pathasw_weapon_ricochet_shared.cpp
More file actions
288 lines (239 loc) · 9.11 KB
/
asw_weapon_ricochet_shared.cpp
File metadata and controls
288 lines (239 loc) · 9.11 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
#include "cbase.h"
#include "asw_weapon_ricochet_shared.h"
#include "in_buttons.h"
#ifdef CLIENT_DLL
#define CASW_Weapon C_ASW_Weapon
#define CASW_Marine C_ASW_Marine
#define CBasePlayer C_BasePlayer
#include "c_asw_player.h"
#include "c_asw_weapon.h"
#include "c_asw_marine.h"
#include "c_asw_marine_resource.h"
#include "precache_register.h"
#include "c_te_effect_dispatch.h"
#include "iviewrender_beams.h" // laser beam
#else
#include "asw_lag_compensation.h"
#include "asw_marine.h"
#include "asw_player.h"
#include "asw_weapon.h"
#include "npcevent.h"
#include "te_effect_dispatch.h"
#include "asw_marine_resource.h"
#include "asw_marine_speech.h"
#include "decals.h"
#include "ammodef.h"
#include "asw_weapon_ammo_bag_shared.h"
#include "asw_rocket.h"
#endif
#include "asw_bouncing_pellet_shared.h"
#include "shot_manipulator.h"
#include "asw_marine_skills.h"
#include "fmtstr.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
IMPLEMENT_NETWORKCLASS_ALIASED( ASW_Weapon_Ricochet, DT_ASW_Weapon_Ricochet )
BEGIN_NETWORK_TABLE( CASW_Weapon_Ricochet, DT_ASW_Weapon_Ricochet )
#ifdef CLIENT_DLL
// recvprops
#else
// sendprops
#endif
END_NETWORK_TABLE()
#ifdef CLIENT_DLL
BEGIN_PREDICTION_DATA( CASW_Weapon_Ricochet )
END_PREDICTION_DATA()
#endif
LINK_ENTITY_TO_CLASS( asw_weapon_ricochet, CASW_Weapon_Ricochet );
PRECACHE_WEAPON_REGISTER( asw_weapon_ricochet );
extern ConVar asw_weapon_max_shooting_distance;
extern ConVar asw_controls;
#ifndef CLIENT_DLL
extern ConVar asw_debug_marine_damage;
#else
extern ConVar asw_laser_sight_min_distance;
#endif
ConVar rd_ricochet_bounces( "rd_ricochet_bounces", "3", FCVAR_REPLICATED | FCVAR_CHEAT );
ConVar rd_ricochet_bounce_world_only( "rd_ricochet_bounce_world_only", "0", FCVAR_REPLICATED | FCVAR_CHEAT );
ConVar rd_ricochet_bounce_horiz( "rd_ricochet_bounce_horiz", "0", FCVAR_REPLICATED | FCVAR_CHEAT );
ConVar rd_ricochet_shotgun_bounces( "rd_ricochet_shotgun_bounces", "1", FCVAR_REPLICATED | FCVAR_CHEAT );
ConVar rd_ricochet_shotgun_pellets( "rd_ricochet_shotgun_pellets", "7", FCVAR_REPLICATED | FCVAR_CHEAT );
ConVar rd_ricochet_shotgun_damage_scale( "rd_ricochet_shotgun_damage_scale", "0.3", FCVAR_REPLICATED | FCVAR_CHEAT );
ConVar rd_ricochet_shotgun_spread( "rd_ricochet_shotgun_spread", "20", FCVAR_REPLICATED | FCVAR_CHEAT );
ConVar rd_ricochet_shotgun_fire_rate( "rd_ricochet_shotgun_fire_rate", "10.0", FCVAR_REPLICATED | FCVAR_CHEAT );
ConVar rd_ricochet_max_distance( "rd_ricochet_max_distance", "3.0", FCVAR_REPLICATED | FCVAR_CHEAT );
CASW_Weapon_Ricochet::CASW_Weapon_Ricochet()
{
m_flNextEmptySoundTime = FLT_MAX;
}
CASW_Weapon_Ricochet::~CASW_Weapon_Ricochet()
{
}
void CASW_Weapon_Ricochet::Precache()
{
BaseClass::Precache();
PrecacheParticleSystem( "weapon_laser_sight_ricochet" );
}
void CASW_Weapon_Ricochet::PrimaryAttack()
{
// If my clip is empty (and I use clips) start reload
if ( UsesClipsForAmmo1() && !m_iClip1 )
{
Reload();
return;
}
CASW_Player *pPlayer = GetCommander();
CASW_Marine *pMarine = GetMarine();
bool bAttack1, bAttack2, bReload, bOldReload, bOldAttack1;
GetButtons( bAttack1, bAttack2, bReload, bOldReload, bOldAttack1 );
if ( pMarine ) // firing from a marine
{
m_bIsFiring = true;
// MUST call sound before removing a round from the clip of a CMachineGun
WeaponSound( SINGLE );
if ( m_iClip1 <= AmmoClickPoint() )
{
LowAmmoSound();
}
// sets the animation on the weapon model iteself
SendWeaponAnim( GetPrimaryAttackActivity() );
pMarine->DoAnimationEvent( bAttack2 ? PLAYERANIMEVENT_FIRE_GUN_SECONDARY : PLAYERANIMEVENT_FIRE_GUN_PRIMARY );
#ifdef GAME_DLL // check for turning on lag compensation
if ( pPlayer && pMarine->IsInhabited() )
{
CASW_Lag_Compensation::RequestLagCompensation( pPlayer, pPlayer->GetCurrentUserCommand() );
}
#endif
FireBulletsInfo_t info;
info.m_vecSrc = pMarine->Weapon_ShootPosition();
if ( pPlayer && pMarine->IsInhabited() )
{
info.m_vecDirShooting = pPlayer->GetAutoaimVectorForMarine( pMarine, GetAutoAimAmount(), GetVerticalAdjustOnlyAutoAimAmount() ); // 45 degrees = 0.707106781187
}
else
{
#ifdef CLIENT_DLL
Msg( "Error, clientside firing of a weapon that's being controlled by an AI marine\n" );
#else
info.m_vecDirShooting = pMarine->GetActualShootTrajectory( info.m_vecSrc );
#endif
}
info.m_flDistance = asw_weapon_max_shooting_distance.GetFloat() * rd_ricochet_max_distance.GetFloat();
info.m_iTracerFreq = 1; // asw tracer test everytime
// To make the firing framerate independent, we may have to fire more than one bullet here on low-framerate systems,
// especially if the weapon we're firing has a really fast rate of fire.
info.m_iShots = 0;
float fireRate = GetFireRate();
if ( bAttack2 )
fireRate *= rd_ricochet_shotgun_fire_rate.GetFloat();
while ( m_flNextPrimaryAttack <= gpGlobals->curtime )
{
m_flNextPrimaryAttack = m_flNextPrimaryAttack + fireRate;
info.m_iShots++;
if ( !fireRate )
break;
}
// Make sure we don't fire more than the amount in the clip
if ( UsesClipsForAmmo1() )
{
info.m_iShots = MIN( info.m_iShots, m_iClip1 );
m_iClip1 -= info.m_iShots;
NotifyIfNoneClip1Ammo( pMarine );
}
else
{
info.m_iShots = MIN( info.m_iShots, pMarine->GetAmmoCount( m_iPrimaryAmmoType ) );
pMarine->RemoveAmmo( info.m_iShots, m_iPrimaryAmmoType );
}
int nBounces;
if ( bAttack2 )
{
info.m_vecSpread.x = info.m_vecSpread.y = info.m_vecSpread.z = rd_ricochet_shotgun_spread.GetFloat();
info.m_nFlags = FIRE_BULLETS_NO_PIERCING_SPARK | FIRE_BULLETS_HULL | FIRE_BULLETS_ANGULAR_SPREAD;
info.m_iAmmoType = m_iSecondaryAmmoType;
info.m_iShots *= rd_ricochet_shotgun_pellets.GetInt();
info.m_flDamage = MAX( GetWeaponDamage() * rd_ricochet_shotgun_damage_scale.GetFloat(), 1.0f );
nBounces = rd_ricochet_shotgun_bounces.GetInt();
}
else
{
info.m_vecSpread = GetBulletSpread();
info.m_flDamage = GetWeaponDamage();
info.m_iAmmoType = m_iPrimaryAmmoType;
nBounces = rd_ricochet_bounces.GetInt();
}
#ifndef CLIENT_DLL
if ( asw_debug_marine_damage.GetBool() )
Msg( "Weapon dmg = %f\n", info.m_flDamage );
pMarine->GetMarineResource()->OnFired_ScaleDamage( info );
#endif
pMarine->FireBouncingBullets( info, nBounces, 0, false, rd_ricochet_bounce_world_only.GetBool(), rd_ricochet_bounce_horiz.GetInt() == 2 ? ( pPlayer && pMarine->IsInhabited() ? pPlayer->GetASWControls() == ASWC_TOPDOWN : asw_controls.GetInt() == 1 ) : rd_ricochet_bounce_horiz.GetBool() );
// increment shooting stats
#ifndef CLIENT_DLL
if ( pMarine->GetMarineResource() )
{
pMarine->GetMarineResource()->UsedWeapon( this, info.m_iShots );
pMarine->OnWeaponFired( this, info.m_iShots, bAttack2 );
}
#endif
}
}
void CASW_Weapon_Ricochet::SecondaryAttack()
{
// prevent secondary fire from interrupting the gun
m_flNextSecondaryAttack = FLT_MAX;
}
#ifdef CLIENT_DLL
void CASW_Weapon_Ricochet::UpdateBounceLaser()
{
if ( !m_pLaserPointerEffect )
return;
CASW_Player *pPlayer = GetCommander();
CASW_Marine *pMarine = GetMarine();
if ( !pPlayer || !pMarine || !pMarine->IsInhabited() || !m_bUsingViewMarineLaserPointer )
return;
Vector vecSrc = pMarine->Weapon_ShootPosition();
Vector vecDir = pPlayer->GetAutoaimVectorForMarine( pMarine, GetAutoAimAmount(), GetVerticalAdjustOnlyAutoAimAmount() );
if ( pMarine->m_flLaserSightLength > asw_laser_sight_min_distance.GetFloat() )
{
vecDir = pMarine->m_vLaserSightCorrection;
}
float flRemainingDist = asw_weapon_max_shooting_distance.GetFloat() * rd_ricochet_max_distance.GetFloat();
trace_t tr;
UTIL_TraceLine( vecSrc, vecSrc + vecDir * flRemainingDist, MASK_SHOT, pMarine, COLLISION_GROUP_NONE, &tr );
bool bAttack1, bAttack2, bReload, bOldReload, bOldAttack1;
GetButtons( bAttack1, bAttack2, bReload, bOldReload, bOldAttack1 );
bool bNoReflectZ = rd_ricochet_bounce_horiz.GetInt() == 2 ? ( pPlayer && pMarine->IsInhabited() ? pPlayer->GetASWControls() == ASWC_TOPDOWN : asw_controls.GetInt() == 1 ) : rd_ricochet_bounce_horiz.GetBool();
int nBounces = bAttack2 ? rd_ricochet_shotgun_bounces.GetInt() : rd_ricochet_bounces.GetInt();
for ( int i = 0; i < 5; i++ )
{
flRemainingDist -= vecSrc.DistTo( tr.endpos );
vecSrc = tr.endpos;
if ( tr.DidHit() && i < nBounces && flRemainingDist > 0 )
{
Vector vecNewDir = vecDir;
// reflect the X+Y off the surface (leave Z intact so the shot is more likely to stay flat and hit enemies)
float proj = ( vecNewDir ).Dot( tr.plane.normal );
VectorMA( vecNewDir, -proj * 2, tr.plane.normal, vecNewDir );
vecDir.x = vecNewDir.x;
vecDir.y = vecNewDir.y;
if ( !bNoReflectZ )
vecDir.z = vecNewDir.z;
UTIL_TraceLine( vecSrc, vecSrc + vecDir * flRemainingDist, MASK_SHOT, NULL, COLLISION_GROUP_NONE, &tr );
// If we're going to hit a marine after a bounce, make sure the base laser pointer code knows that.
if ( IsFriendlyFireTarget( tr.m_pEnt ) )
{
SetLaserTargetEntity( tr.m_pEnt );
}
}
m_pLaserPointerEffect->SetControlPoint( i + 10, vecSrc );
m_pLaserPointerEffect->SetControlPointForwardVector( i + 10, vecDir );
}
}
bool CASW_Weapon_Ricochet::Simulate()
{
bool bContinue = BaseClass::Simulate();
UpdateBounceLaser();
return bContinue;
}
#endif