/
equipment.go
396 lines (341 loc) · 12 KB
/
equipment.go
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
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
package common
import (
"math/rand"
"strings"
st "github.com/markus-wa/demoinfocs-golang/v2/pkg/demoinfocs/sendtables"
)
// EquipmentClass is the type for the various EqClassXYZ constants.
type EquipmentClass int
// EquipmentClass constants give information about the type of an equipment (SMG, Rifle, Grenade etc.).
//
// Note: (EquipmentType+99) / 100 = EquipmentClass
const (
EqClassUnknown EquipmentClass = 0
EqClassPistols EquipmentClass = 1
EqClassSMG EquipmentClass = 2
EqClassHeavy EquipmentClass = 3
EqClassRifle EquipmentClass = 4
EqClassEquipment EquipmentClass = 5
EqClassGrenade EquipmentClass = 6
)
// EquipmentType is the type for the various EqXYZ constants.
type EquipmentType int
// Class returns the class of the equipment.
// E.g. pistol, smg, heavy etc.
func (e EquipmentType) Class() EquipmentClass {
const classDenominator = 100
return EquipmentClass((int(e) + classDenominator - 1) / classDenominator)
}
// String returns a human readable name for the equipment.
// E.g. 'AK-47', 'UMP-45', 'Smoke Grenade' etc.
func (e EquipmentType) String() string {
return eqElementToName[e]
}
// EquipmentType constants give information about what weapon a player has equipped.
const (
EqUnknown EquipmentType = 0
// Pistols
EqP2000 EquipmentType = 1
EqGlock EquipmentType = 2
EqP250 EquipmentType = 3
EqDeagle EquipmentType = 4
EqFiveSeven EquipmentType = 5
EqDualBerettas EquipmentType = 6
EqTec9 EquipmentType = 7
EqCZ EquipmentType = 8
EqUSP EquipmentType = 9
EqRevolver EquipmentType = 10
// SMGs
EqMP7 EquipmentType = 101
EqMP9 EquipmentType = 102
EqBizon EquipmentType = 103
EqMac10 EquipmentType = 104
EqUMP EquipmentType = 105
EqP90 EquipmentType = 106
EqMP5 EquipmentType = 107
// Heavy
EqSawedOff EquipmentType = 201
EqNova EquipmentType = 202
EqMag7 EquipmentType = 203 // You should consider using EqSwag7 instead
EqSwag7 EquipmentType = 203
EqXM1014 EquipmentType = 204
EqM249 EquipmentType = 205
EqNegev EquipmentType = 206
// Rifles
EqGalil EquipmentType = 301
EqFamas EquipmentType = 302
EqAK47 EquipmentType = 303
EqM4A4 EquipmentType = 304
EqM4A1 EquipmentType = 305
EqScout EquipmentType = 306
EqSSG08 EquipmentType = 306
EqSG556 EquipmentType = 307
EqSG553 EquipmentType = 307
EqAUG EquipmentType = 308
EqAWP EquipmentType = 309
EqScar20 EquipmentType = 310
EqG3SG1 EquipmentType = 311
// Equipment
EqZeus EquipmentType = 401
EqKevlar EquipmentType = 402
EqHelmet EquipmentType = 403
EqBomb EquipmentType = 404
EqKnife EquipmentType = 405
EqDefuseKit EquipmentType = 406
EqWorld EquipmentType = 407
// Grenades
EqDecoy EquipmentType = 501
EqMolotov EquipmentType = 502
EqIncendiary EquipmentType = 503
EqFlash EquipmentType = 504
EqSmoke EquipmentType = 505
EqHE EquipmentType = 506
)
var eqNameToWeapon map[string]EquipmentType
var eqElementToName map[EquipmentType]string
func init() {
initEqNameToWeapon()
initEqElementToName()
}
//nolint:funlen
func initEqNameToWeapon() {
eqNameToWeapon = make(map[string]EquipmentType)
eqNameToWeapon["ak47"] = EqAK47
eqNameToWeapon["aug"] = EqAUG
eqNameToWeapon["awp"] = EqAWP
eqNameToWeapon["bizon"] = EqBizon
eqNameToWeapon["c4"] = EqBomb
eqNameToWeapon["deagle"] = EqDeagle
eqNameToWeapon["decoy"] = EqDecoy
eqNameToWeapon["decoygrenade"] = EqDecoy
eqNameToWeapon["decoyprojectile"] = EqDecoy
eqNameToWeapon["decoy_projectile"] = EqDecoy
eqNameToWeapon["elite"] = EqDualBerettas
eqNameToWeapon["famas"] = EqFamas
eqNameToWeapon["fiveseven"] = EqFiveSeven
eqNameToWeapon["flashbang"] = EqFlash
eqNameToWeapon["g3sg1"] = EqG3SG1
eqNameToWeapon["galil"] = EqGalil
eqNameToWeapon["galilar"] = EqGalil
eqNameToWeapon["glock"] = EqGlock
eqNameToWeapon["hegrenade"] = EqHE
eqNameToWeapon["hkp2000"] = EqP2000
eqNameToWeapon["incgrenade"] = EqIncendiary
eqNameToWeapon["incendiarygrenade"] = EqIncendiary
eqNameToWeapon["m249"] = EqM249
eqNameToWeapon["m4a1"] = EqM4A4
eqNameToWeapon["mac10"] = EqMac10
eqNameToWeapon["mag7"] = EqSwag7
eqNameToWeapon["molotov"] = EqMolotov
eqNameToWeapon["molotovgrenade"] = EqMolotov
eqNameToWeapon["molotovprojectile"] = EqMolotov
eqNameToWeapon["molotov_projectile"] = EqMolotov
eqNameToWeapon["mp7"] = EqMP7
eqNameToWeapon["mp5sd"] = EqMP5
eqNameToWeapon["mp9"] = EqMP9
eqNameToWeapon["negev"] = EqNegev
eqNameToWeapon["nova"] = EqNova
eqNameToWeapon["p250"] = EqP250
eqNameToWeapon["p90"] = EqP90
eqNameToWeapon["sawedoff"] = EqSawedOff
eqNameToWeapon["scar20"] = EqScar20
eqNameToWeapon["sg556"] = EqSG556
eqNameToWeapon["smokegrenade"] = EqSmoke
eqNameToWeapon["smokegrenadeprojectile"] = EqSmoke
eqNameToWeapon["smokegrenade_projectile"] = EqSmoke
eqNameToWeapon["ssg08"] = EqScout
eqNameToWeapon["taser"] = EqZeus
eqNameToWeapon["tec9"] = EqTec9
eqNameToWeapon["ump45"] = EqUMP
eqNameToWeapon["xm1014"] = EqXM1014
eqNameToWeapon["m4a1_silencer"] = EqM4A1
eqNameToWeapon["m4a1_silencer_off"] = EqM4A1
eqNameToWeapon["cz75a"] = EqCZ
eqNameToWeapon["usp"] = EqUSP
eqNameToWeapon["usp_silencer"] = EqUSP
eqNameToWeapon["usp_silencer_off"] = EqUSP
eqNameToWeapon["world"] = EqWorld
eqNameToWeapon["inferno"] = EqIncendiary
eqNameToWeapon["revolver"] = EqRevolver
eqNameToWeapon["vest"] = EqKevlar
eqNameToWeapon["vesthelm"] = EqHelmet
eqNameToWeapon["defuser"] = EqDefuseKit
// These don't exist and / or used to crash the game with the give command
eqNameToWeapon["scar17"] = EqUnknown
eqNameToWeapon["sensorgrenade"] = EqUnknown
eqNameToWeapon["mp5navy"] = EqUnknown
eqNameToWeapon["p228"] = EqUnknown
eqNameToWeapon["scout"] = EqUnknown
eqNameToWeapon["sg550"] = EqUnknown
eqNameToWeapon["sg552"] = EqUnknown // This one still crashes the game :)
eqNameToWeapon["tmp"] = EqUnknown
eqNameToWeapon["worldspawn"] = EqWorld
}
//nolint:funlen
func initEqElementToName() {
eqElementToName = make(map[EquipmentType]string)
eqElementToName[EqAK47] = "AK-47"
eqElementToName[EqAUG] = "AUG"
eqElementToName[EqAWP] = "AWP"
eqElementToName[EqBizon] = "PP-Bizon"
eqElementToName[EqBomb] = "C4"
eqElementToName[EqDeagle] = "Desert Eagle"
eqElementToName[EqDecoy] = "Decoy Grenade"
eqElementToName[EqDualBerettas] = "Dual Berettas"
eqElementToName[EqFamas] = "FAMAS"
eqElementToName[EqFiveSeven] = "Five-SeveN"
eqElementToName[EqFlash] = "Flashbang"
eqElementToName[EqG3SG1] = "G3SG1"
eqElementToName[EqGalil] = "Galil AR"
eqElementToName[EqGlock] = "Glock-18"
eqElementToName[EqHE] = "HE Grenade"
eqElementToName[EqP2000] = "P2000"
eqElementToName[EqIncendiary] = "Incendiary Grenade"
eqElementToName[EqM249] = "M249"
eqElementToName[EqM4A4] = "M4A4"
eqElementToName[EqMac10] = "MAC-10"
eqElementToName[EqSwag7] = "MAG-7"
eqElementToName[EqMolotov] = "Molotov"
eqElementToName[EqMP7] = "MP7"
eqElementToName[EqMP5] = "MP5-SD"
eqElementToName[EqMP9] = "MP9"
eqElementToName[EqNegev] = "Negev"
eqElementToName[EqNova] = "Nova"
eqElementToName[EqP250] = "P250"
eqElementToName[EqP90] = "P90"
eqElementToName[EqSawedOff] = "Sawed-Off"
eqElementToName[EqScar20] = "SCAR-20"
eqElementToName[EqSG553] = "SG 553"
eqElementToName[EqSmoke] = "Smoke Grenade"
eqElementToName[EqScout] = "SSG 08"
eqElementToName[EqZeus] = "Zeus x27"
eqElementToName[EqTec9] = "Tec-9"
eqElementToName[EqUMP] = "UMP-45"
eqElementToName[EqXM1014] = "XM1014"
eqElementToName[EqM4A1] = "M4A1"
eqElementToName[EqCZ] = "CZ75 Auto"
eqElementToName[EqUSP] = "USP-S"
eqElementToName[EqWorld] = "World"
eqElementToName[EqRevolver] = "R8 Revolver"
eqElementToName[EqKevlar] = "Kevlar Vest"
eqElementToName[EqHelmet] = "Kevlar + Helmet"
eqElementToName[EqDefuseKit] = "Defuse Kit"
eqElementToName[EqKnife] = "Knife"
eqElementToName[EqUnknown] = "UNKNOWN"
}
const weaponPrefix = "weapon_"
// MapEquipment creates an EquipmentType from the name of the weapon / equipment.
// Returns EqUnknown if no mapping can be found.
func MapEquipment(eqName string) EquipmentType {
eqName = strings.TrimPrefix(eqName, weaponPrefix)
var wep EquipmentType
if strings.Contains(eqName, "knife") || strings.Contains(eqName, "bayonet") {
wep = EqKnife
} else {
// If the eqName isn't known it will be EqUnknown as that is the default value for EquipmentType
wep = eqNameToWeapon[eqName]
}
return wep
}
// ZoomLevel contains how far a player is zoomed in.
type ZoomLevel int
// All currently known zoom levels.
const (
ZoomNone ZoomLevel = 0
ZoomHalf ZoomLevel = 1
ZoomFull ZoomLevel = 2
)
// Equipment is a weapon / piece of equipment belonging to a player.
// This also includes the skin and some additional data.
type Equipment struct {
Type EquipmentType // The type of weapon which the equipment instantiates.
Entity st.Entity // The game entity instance
Owner *Player // The player carrying the equipment, not necessarily the buyer.
OriginalString string // E.g. 'models/weapons/w_rif_m4a1_s.mdl'. Used internally to differentiate alternative weapons (M4A4 / M4A1-S etc.).
uniqueID int64
}
// String returns a human readable name for the equipment.
// E.g. 'AK-47', 'UMP-45', 'Smoke Grenade' etc.
func (e *Equipment) String() string {
return e.Type.String()
}
// Class returns the class of the equipment.
// E.g. pistol, smg, heavy etc.
func (e *Equipment) Class() EquipmentClass {
return e.Type.Class()
}
// UniqueID returns the unique id of the equipment element.
// The unique id is a random int generated internally by this library and can be used to differentiate
// equipment from each other. This is needed because demo-files reuse entity ids.
func (e *Equipment) UniqueID() int64 {
return e.uniqueID
}
// AmmoInMagazine returns the ammo left in the magazine.
// Returns CWeaponCSBase.m_iClip1 for most weapons and 1 for grenades.
func (e *Equipment) AmmoInMagazine() int {
if e.Class() == EqClassGrenade {
return 1
}
if e.Entity == nil {
return 0
}
val, ok := e.Entity.PropertyValue("m_iClip1")
if !ok {
return -1
}
// need to subtract 1 as m_iClip1 is nrOfBullets + 1
return val.IntVal - 1
}
// AmmoType returns the weapon's ammo type, mostly (only?) relevant for grenades.
func (e *Equipment) AmmoType() int {
return getInt(e.Entity, "LocalWeaponData.m_iPrimaryAmmoType")
}
// ZoomLevel returns how far the player has zoomed in on the weapon.
// Only weapons with scopes have a valid zoom level.
func (e *Equipment) ZoomLevel() ZoomLevel {
if e.Entity == nil {
return 0
}
// if the property doesn't exist we return 0 by default
val, _ := e.Entity.PropertyValue("m_zoomLevel")
return ZoomLevel(val.IntVal)
}
// AmmoReserve returns the ammo left available for reloading.
// Returns CWeaponCSBase.m_iPrimaryReserveAmmoCount for most weapons and 'Owner.AmmoLeft[AmmoType] - 1' for grenades.
// Use AmmoInMagazine() + AmmoReserve() to quickly get the amount of grenades a player owns.
func (e *Equipment) AmmoReserve() int {
if e.Class() == EqClassGrenade {
if e.Owner != nil {
// minus one for 'InMagazine'
return e.Owner.AmmoLeft[e.AmmoType()] - 1
}
return 0
}
if e.Entity == nil {
return 0
}
// if the property doesn't exist we return 0 by default
val, _ := e.Entity.PropertyValue("m_iPrimaryReserveAmmoCount")
return val.IntVal
}
// NewEquipment creates a new Equipment and sets the UniqueID.
//
// Intended for internal use only.
func NewEquipment(wep EquipmentType) *Equipment {
return &Equipment{Type: wep, uniqueID: rand.Int63()}
}
var equipmentToAlternative = map[EquipmentType]EquipmentType{
EqP2000: EqUSP,
EqP250: EqCZ, // for old demos where the CZ was the alternative for the P250
EqFiveSeven: EqCZ,
EqTec9: EqCZ,
EqDeagle: EqRevolver,
EqMP7: EqMP5,
EqM4A4: EqM4A1,
}
// EquipmentAlternative returns the EquipmentType of the alternatively equippable weapon.
// E.g. returns EquipmentAlternative(EqP2000) returns EqUSP.
// Only works one way (default-to-alternative) as the Five-Seven and Tec-9 both map to the CZ-75.
func EquipmentAlternative(eq EquipmentType) EquipmentType {
return equipmentToAlternative[eq]
}