|
2 | 2 | package common |
3 | 3 |
|
4 | 4 | import ( |
5 | | - "strings" |
| 5 | + "math/rand" |
| 6 | + "time" |
| 7 | + |
| 8 | + r3 "github.com/golang/geo/r3" |
| 9 | +) |
| 10 | + |
| 11 | +// Team is the type for the various TeamXYZ constants. |
| 12 | +type Team byte |
| 13 | + |
| 14 | +// Team constants give information about which team a player is on. |
| 15 | +const ( |
| 16 | + TeamUnassigned Team = iota |
| 17 | + TeamSpectators |
| 18 | + TeamTerrorists |
| 19 | + TeamCounterTerrorists |
6 | 20 | ) |
7 | 21 |
|
8 | | -var eqNameToWeapon map[string]EquipmentElement |
| 22 | +// DemoHeader contains information from a demo's header. |
| 23 | +type DemoHeader struct { |
| 24 | + Filestamp string // aka. File-type, must be HL2DEMO |
| 25 | + Protocol int // Should be 4 |
| 26 | + NetworkProtocol int // Not sure what this is for |
| 27 | + ServerName string // Server's 'hostname' config value |
| 28 | + ClientName string // Usually 'GOTV Demo' |
| 29 | + MapName string // E.g. de_cache, de_nuke, cs_office, etc. |
| 30 | + GameDirectory string // Usually 'csgo' |
| 31 | + PlaybackTime time.Duration // Demo duration in seconds (= PlaybackTicks / Server's tickrate) |
| 32 | + PlaybackTicks int // Game duration in ticks (= PlaybackTime * Server's tickrate) |
| 33 | + PlaybackFrames int // Amount of 'frames' aka demo-ticks recorded (= PlaybackTime * Demo's recording rate) |
| 34 | + SignonLength int // Length of the Signon package in bytes |
| 35 | +} |
| 36 | + |
| 37 | +// FrameRate returns the frame rate of the demo (frames / demo-ticks per second). |
| 38 | +// Not necessarily the tick-rate the server ran on during the game. |
| 39 | +func (h DemoHeader) FrameRate() float64 { |
| 40 | + return float64(h.PlaybackFrames) / h.PlaybackTime.Seconds() |
| 41 | +} |
9 | 42 |
|
10 | | -var eqElementToName map[EquipmentElement]string |
| 43 | +// FrameTime returns the time a frame / demo-tick takes in seconds. |
| 44 | +func (h DemoHeader) FrameTime() time.Duration { |
| 45 | + return time.Duration(h.PlaybackTime.Nanoseconds() / int64(h.PlaybackFrames)) |
| 46 | +} |
| 47 | + |
| 48 | +// TickRate returns the tick-rate the server ran on during the game. |
| 49 | +// VolvoPlx128TixKTnxBye |
| 50 | +func (h DemoHeader) TickRate() float64 { |
| 51 | + return float64(h.PlaybackTicks) / h.PlaybackTime.Seconds() |
| 52 | +} |
| 53 | + |
| 54 | +// TickTime returns the time a single tick takes in seconds. |
| 55 | +func (h DemoHeader) TickTime() time.Duration { |
| 56 | + return time.Duration(h.PlaybackTime.Nanoseconds() / int64(h.PlaybackTicks)) |
| 57 | +} |
| 58 | + |
| 59 | +// GrenadeProjectile is a grenade thrown intentionally by a player. It is used to track grenade projectile |
| 60 | +// positions between the time at which they are thrown and until they detonate. |
| 61 | +type GrenadeProjectile struct { |
| 62 | + EntityID int |
| 63 | + Weapon EquipmentElement |
| 64 | + Thrower *Player // Always seems to be the same as Owner, even if the grenade was picked up |
| 65 | + Owner *Player // Always seems to be the same as Thrower, even if the grenade was picked up |
| 66 | + Position r3.Vector |
| 67 | + Trajectory []r3.Vector // List of all known locations of the grenade up to the current point |
| 68 | + |
| 69 | + // uniqueID is used to distinguish different grenades (which potentially have the same, reused entityID) from each other. |
| 70 | + uniqueID int64 |
| 71 | +} |
11 | 72 |
|
12 | | -func init() { |
13 | | - initEqNameToWeapon() |
14 | | - initEqElementToName() |
| 73 | +// UniqueID returns the unique id of the grenade. |
| 74 | +// The unique id is a random int generated internally by this library and can be used to differentiate |
| 75 | +// grenades from each other. This is needed because demo-files reuse entity ids. |
| 76 | +func (g GrenadeProjectile) UniqueID() int64 { |
| 77 | + return g.uniqueID |
15 | 78 | } |
16 | 79 |
|
17 | | -func initEqNameToWeapon() { |
18 | | - eqNameToWeapon = make(map[string]EquipmentElement) |
19 | | - |
20 | | - eqNameToWeapon["ak47"] = EqAK47 |
21 | | - eqNameToWeapon["aug"] = EqAUG |
22 | | - eqNameToWeapon["awp"] = EqAWP |
23 | | - eqNameToWeapon["bizon"] = EqBizon |
24 | | - eqNameToWeapon["c4"] = EqBomb |
25 | | - eqNameToWeapon["deagle"] = EqDeagle |
26 | | - eqNameToWeapon["decoy"] = EqDecoy |
27 | | - eqNameToWeapon["decoygrenade"] = EqDecoy |
28 | | - eqNameToWeapon["decoyprojectile"] = EqDecoy |
29 | | - eqNameToWeapon["elite"] = EqDualBarettas |
30 | | - eqNameToWeapon["famas"] = EqFamas |
31 | | - eqNameToWeapon["fiveseven"] = EqFiveSeven |
32 | | - eqNameToWeapon["flashbang"] = EqFlash |
33 | | - eqNameToWeapon["g3sg1"] = EqG3SG1 |
34 | | - eqNameToWeapon["galil"] = EqGalil |
35 | | - eqNameToWeapon["galilar"] = EqGalil |
36 | | - eqNameToWeapon["glock"] = EqGlock |
37 | | - eqNameToWeapon["hegrenade"] = EqHE |
38 | | - eqNameToWeapon["hkp2000"] = EqP2000 |
39 | | - eqNameToWeapon["incgrenade"] = EqIncendiary |
40 | | - eqNameToWeapon["incendiarygrenade"] = EqIncendiary |
41 | | - eqNameToWeapon["m249"] = EqM249 |
42 | | - eqNameToWeapon["m4a1"] = EqM4A4 |
43 | | - eqNameToWeapon["mac10"] = EqMac10 |
44 | | - eqNameToWeapon["mag7"] = EqSwag7 |
45 | | - eqNameToWeapon["molotov"] = EqMolotov |
46 | | - eqNameToWeapon["molotovgrenade"] = EqMolotov |
47 | | - eqNameToWeapon["molotovprojectile"] = EqMolotov |
48 | | - eqNameToWeapon["mp7"] = EqMP7 |
49 | | - eqNameToWeapon["mp9"] = EqMP9 |
50 | | - eqNameToWeapon["negev"] = EqNegev |
51 | | - eqNameToWeapon["nova"] = EqNova |
52 | | - eqNameToWeapon["p250"] = EqP250 |
53 | | - eqNameToWeapon["p90"] = EqP90 |
54 | | - eqNameToWeapon["sawedoff"] = EqSawedOff |
55 | | - eqNameToWeapon["scar20"] = EqScar20 |
56 | | - eqNameToWeapon["sg556"] = EqSG556 |
57 | | - eqNameToWeapon["smokegrenade"] = EqSmoke |
58 | | - eqNameToWeapon["smokegrenadeprojectile"] = EqSmoke |
59 | | - eqNameToWeapon["taser"] = EqZeus |
60 | | - eqNameToWeapon["tec9"] = EqTec9 |
61 | | - eqNameToWeapon["ump45"] = EqUMP |
62 | | - eqNameToWeapon["xm1014"] = EqXM1014 |
63 | | - eqNameToWeapon["m4a1_silencer"] = EqM4A1 |
64 | | - eqNameToWeapon["m4a1_silencer_off"] = EqM4A1 |
65 | | - eqNameToWeapon["cz75a"] = EqCZ |
66 | | - eqNameToWeapon["usp"] = EqUSP |
67 | | - eqNameToWeapon["usp_silencer"] = EqUSP |
68 | | - eqNameToWeapon["usp_silencer_off"] = EqUSP |
69 | | - eqNameToWeapon["world"] = EqWorld |
70 | | - eqNameToWeapon["inferno"] = EqIncendiary |
71 | | - eqNameToWeapon["revolver"] = EqRevolver |
72 | | - eqNameToWeapon["vest"] = EqKevlar |
73 | | - eqNameToWeapon["vesthelm"] = EqHelmet |
74 | | - eqNameToWeapon["defuser"] = EqDefuseKit |
75 | | - |
76 | | - // These don't exist and / or used to crash the game with the give command |
77 | | - eqNameToWeapon["scar17"] = EqUnknown |
78 | | - eqNameToWeapon["sensorgrenade"] = EqUnknown |
79 | | - eqNameToWeapon["mp5navy"] = EqUnknown |
80 | | - eqNameToWeapon["p228"] = EqUnknown |
81 | | - eqNameToWeapon["scout"] = EqUnknown |
82 | | - eqNameToWeapon["sg550"] = EqUnknown |
83 | | - eqNameToWeapon["sg552"] = EqUnknown // This one still crashes the game :) |
84 | | - eqNameToWeapon["tmp"] = EqUnknown |
85 | | - eqNameToWeapon["worldspawn"] = EqUnknown |
| 80 | +// NewGrenadeProjectile creates a grenade projectile and sets the Unique-ID. |
| 81 | +// |
| 82 | +// Intended for internal use only. |
| 83 | +func NewGrenadeProjectile() *GrenadeProjectile { |
| 84 | + return &GrenadeProjectile{uniqueID: rand.Int63()} |
86 | 85 | } |
87 | 86 |
|
88 | | -func initEqElementToName() { |
89 | | - eqElementToName = make(map[EquipmentElement]string) |
90 | | - eqElementToName[EqAK47] = "AK-47" |
91 | | - eqElementToName[EqAUG] = "AUG" |
92 | | - eqElementToName[EqAWP] = "AWP" |
93 | | - eqElementToName[EqBizon] = "PP-Bizon" |
94 | | - eqElementToName[EqBomb] = "C4" |
95 | | - eqElementToName[EqDeagle] = "Desert Eagle" |
96 | | - eqElementToName[EqDecoy] = "Decoy Grenade" |
97 | | - eqElementToName[EqDualBarettas] = "Dual Barettas" |
98 | | - eqElementToName[EqFamas] = "FAMAS" |
99 | | - eqElementToName[EqFiveSeven] = "Five-SeveN" |
100 | | - eqElementToName[EqFlash] = "Flashbang" |
101 | | - eqElementToName[EqG3SG1] = "G3SG1" |
102 | | - eqElementToName[EqGalil] = "Galil AR" |
103 | | - eqElementToName[EqGlock] = "Glock-18" |
104 | | - eqElementToName[EqHE] = "HE Grenade" |
105 | | - eqElementToName[EqP2000] = "P2000" |
106 | | - eqElementToName[EqIncendiary] = "Incendiary Grenade" |
107 | | - eqElementToName[EqM249] = "M249" |
108 | | - eqElementToName[EqM4A4] = "M4A1" |
109 | | - eqElementToName[EqMac10] = "MAC-10" |
110 | | - eqElementToName[EqSwag7] = "MAG-7" |
111 | | - eqElementToName[EqMolotov] = "Molotov" |
112 | | - eqElementToName[EqMP7] = "MP7" |
113 | | - eqElementToName[EqMP9] = "MP9" |
114 | | - eqElementToName[EqNegev] = "Negev" |
115 | | - eqElementToName[EqNova] = "Nova" |
116 | | - eqElementToName[EqP250] = "p250" |
117 | | - eqElementToName[EqP90] = "P90" |
118 | | - eqElementToName[EqSawedOff] = "Sawed-Off" |
119 | | - eqElementToName[EqScar20] = "SCAR-20" |
120 | | - eqElementToName[EqSG553] = "SG 553" |
121 | | - eqElementToName[EqSmoke] = "Smoke Grenade" |
122 | | - eqElementToName[EqScout] = "SSG 08" |
123 | | - eqElementToName[EqZeus] = "Zeus x27" |
124 | | - eqElementToName[EqTec9] = "Tec-9" |
125 | | - eqElementToName[EqUMP] = "UMP-45" |
126 | | - eqElementToName[EqXM1014] = "XM1014" |
127 | | - eqElementToName[EqM4A1] = "M4A1" |
128 | | - eqElementToName[EqCZ] = "CZ75 Auto" |
129 | | - eqElementToName[EqUSP] = "USP-S" |
130 | | - eqElementToName[EqWorld] = "World" |
131 | | - eqElementToName[EqRevolver] = "R8 Revolver" |
132 | | - eqElementToName[EqKevlar] = "Kevlar Vest" |
133 | | - eqElementToName[EqHelmet] = "Kevlar + Helmet" |
134 | | - eqElementToName[EqDefuseKit] = "Defuse Kit" |
135 | | - eqElementToName[EqKnife] = "Knife" |
136 | | - eqElementToName[EqUnknown] = "UNKNOWN" |
| 87 | +// Bomb tracks the bomb's position, and the player carrying it, if any. |
| 88 | +type Bomb struct { |
| 89 | + // Intended for internal use only. Use Position() instead. |
| 90 | + // Contains the last location of the dropped or planted bomb. |
| 91 | + LastOnGroundPosition r3.Vector |
| 92 | + Carrier *Player |
137 | 93 | } |
138 | 94 |
|
139 | | -// MapEquipment creates an EquipmentElement from the name of the weapon / equipment. |
140 | | -func MapEquipment(eqName string) EquipmentElement { |
141 | | - eqName = strings.TrimPrefix(eqName, weaponPrefix) |
142 | | - |
143 | | - var wep EquipmentElement |
144 | | - if strings.Contains(eqName, "knife") || strings.Contains(eqName, "bayonet") { |
145 | | - wep = EqKnife |
146 | | - } else { |
147 | | - // If the eqName isn't known it will be EqUnknown as that is the default value for EquipmentElement |
148 | | - var ok bool |
149 | | - if wep, ok = eqNameToWeapon[eqName]; !ok { |
150 | | - // TODO: Return error / warning for unmapped weapons |
151 | | - } |
| 95 | +// Position returns the current position of the bomb. |
| 96 | +// This is either the position of the player holding it |
| 97 | +// or LastOnGroundPosition if it's dropped or planted. |
| 98 | +func (b Bomb) Position() r3.Vector { |
| 99 | + if b.Carrier != nil { |
| 100 | + return b.Carrier.Position |
152 | 101 | } |
153 | 102 |
|
154 | | - return wep |
| 103 | + return b.LastOnGroundPosition |
155 | 104 | } |
0 commit comments