1
0
Fork 0
mirror of https://codeberg.org/demostf/parser.git synced 2026-06-03 18:24:05 +02:00

medigun type, spy class data

This commit is contained in:
Robin Appelman 2025-06-28 18:26:29 +02:00
commit 15046e8744
11 changed files with 1093 additions and 54 deletions

2
Cargo.lock generated
View file

@ -1149,7 +1149,7 @@ dependencies = [
[[package]]
name = "tf-demo-parser"
version = "0.6.4"
version = "0.7.0"
dependencies = [
"Inflector",
"better-panic",

View file

@ -1,7 +1,7 @@
[package]
name = "tf-demo-parser"
description = "parser for tf2 demo files"
version = "0.6.4"
version = "0.7.0"
authors = ["Robin Appelman <robin@icewind.nl>"]
edition = "2021"
license = "MIT OR Apache-2.0"

View file

@ -26,6 +26,6 @@ fn main() -> Result<(), MainError> {
let demo = Demo::new(&file);
let parser = DemoParser::new_with_analyser(demo.get_stream(), GameStateAnalyser::new());
let (_, state) = parser.parse()?;
println!("{}", serde_json::to_string_pretty(&state.buildings)?);
println!("{}", serde_json::to_string_pretty(&state.players)?);
Ok(())
}

904
src/demo/data/attributes.rs Normal file
View file

@ -0,0 +1,904 @@
use crate::demo::sendprop::{SendProp, SendPropIdentifier, SendPropValue};
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
#[repr(i64)]
pub enum Attribute {
DamagePenalty = 1,
DamageBonus = 2,
ClipSizePenalty = 3,
ClipSizeBonus = 4,
FireRatePenalty = 5,
FireRateBonus = 6,
HealRatePenalty = 7,
HealRateBonus = 8,
UberChargeRatePenalty = 9,
UberChargeRateBonus = 10,
OverHealBonus = 11,
OverHealDecayPenalty = 12,
OverHealDecayBonus = 13,
OverHealDecayDisabled = 14,
CritModDisabled = 15,
HealOnHitForRapidFire = 16,
AddUberChargeOnHit = 17,
MedigunChargeIsCritBoost = 18,
TmpDmgBuffOnHit = 19,
CritVsBurningPlayers = 20,
DmgPenaltyVsNonburning = 21,
NoCritVsNonburning = 22,
ModFlamethrowerPush = 23,
ModFlamethrowerBackCrit = 24,
HiddenSecondaryMaxAmmoPenalty = 25,
MaxHealthAdditiveBonus = 26,
AltFireDisabled = 27,
CritModDisabledHidden = 28,
FistsHaveRadialBuff = 30,
CritBoostOnKill = 31,
SlowEnemyOnHit = 32,
SetCloakIsFeignDeath = 33,
MultiplyCloakMeterConsumeRate = 34,
MultiplyCloakMeterRegenRate = 35,
SpreadPenalty = 36,
HiddenPrimaryMaxAmmoBonus = 37,
ModBatLaunchesBalls = 38,
DmgPenaltyVsNonStunned = 39,
ZoomSpeedModDisabled = 40,
SniperChargePerSec = 41,
SniperNoHeadshots = 42,
ScattergunNoReloadSingle = 43,
ScattergunHasKnockback = 44,
BulletsPerShotBonus = 45,
SniperZoomPenalty = 46,
SniperNoCharge = 47,
SetCloakIsMovementBased = 48,
NoDoubleJump = 49,
AbsorbDamageWhileCloaked = 50,
RevolverUseHitLocations = 51,
BackstabShield = 52,
FireRetardant = 53,
MoveSpeedPenalty = 54,
ObsoleteAmmoPenalty = 55,
JarateDescription = 56,
HealthRegen = 57,
SelfDmgPushForceIncreased = 58,
SelfDmgPushForceDecreased = 59,
DmgTakenFromFireReduced = 60,
DmgTakenFromFireIncreased = 61,
DmgTakenFromCritReduced = 62,
DmgTakenFromCritIncreased = 63,
DmgTakenFromBlastReduced = 64,
DmgTakenFromBlastIncreased = 65,
DmgTakenFromBulletsReduced = 66,
DmgTakenFromBulletsIncreased = 67,
IncreasePlayerCaptureValue = 68,
HealthFromHealersReduced = 69,
HealthFromHealersIncreased = 70,
WeaponBurnDmgIncreased = 71,
WeaponBurnDmgReduced = 72,
WeaponBurnTimeIncreased = 73,
WeaponBurnTimeReduced = 74,
AimingMoveSpeedIncreased = 75,
MaxAmmoPrimaryIncreased = 76,
MaxAmmoPrimaryReduced = 77,
MaxAmmoSecondaryIncreased = 78,
MaxAmmoSecondaryReduced = 79,
MaxAmmoMetalIncreased = 80,
MaxAmmoMetalReduced = 81,
CloakConsumeRateIncreased = 82,
CloakConsumeRateDecreased = 83,
CloakRegenRateIncreased = 84,
CloakRegenRateDecreased = 85,
MinigunSpinupTimeIncreased = 86,
MinigunSpinupTimeDecreased = 87,
MaxPipeBombsIncreased = 88,
MaxPipeBombsDecreased = 89,
SniperRifleChargeRateIncreased = 90,
SniperRifleChargeRateDecreased = 91,
ConstructionRateIncreased = 92,
ConstructionRateDecreased = 93,
RepairRateIncreased = 94,
RepairRateDecreased = 95,
ReloadTimeIncreased = 96,
ReloadTimeDecreased = 97,
SelfDamageOnHitForRapidFire = 98,
BlastRadiusIncreased = 99,
BlastRadiusDecreased = 100,
ProjectileRangeIncreased = 101,
ProjectileRangeDecreased = 102,
ProjectileSpeedIncreased = 103,
ProjectileSpeedDecreased = 104,
OverHealPenalty = 105,
WeaponSpreadBonus = 106,
MoveSpeedBonus = 107,
HealthFromPacksIncreased = 108,
HealthFromPacksDecreased = 109,
HealOnHitForSlowFire = 110,
SelfDamageOnHitForSlowFire = 111,
AmmoRegen = 112,
MetalRegen = 113,
ModMiniCritAirborne = 114,
ModShovelDamageBoost = 115,
ModSoldierBuffType = 116,
DmgFalloffIncreased = 117,
DmgFalloffDecreased = 118,
StickyDetonateMode = 119,
StickyArmTimePenalty = 120,
StickiesDetonateStickies = 121,
ModDemoBuffType = 122,
SpeedBoostWhenActive = 123,
ModWrenchBuildsMiniSentry = 124,
MaxHealthAdditivePenalty = 125,
StickyArmTimeBonus = 126,
StickyAirBurstMode = 127,
ProvideOnActive = 128,
HealthDrain = 129,
MedicRegenBonus = 130,
MedicRegenPenalty = 131,
CommunityDescription = 132,
SoldierModelIndex = 133,
AttachParticleEffect = 134,
RocketJumpDamageReduction = 135,
ModSentryKilledRevenge = 136,
DmgBonusVsBuildings = 137,
DmgPenaltyVsPlayers = 138,
LunchboxAddsMaxHealthBonus = 139,
HiddenMaxHealthNonBuffed = 140,
SelfmadeDescription = 141,
SetItemTintRgb = 142,
CustomEmployeeNumber = 143,
LunchboxAddsMiniCrits = 144,
TauntIsHighFive = 145,
DamageAppliesToSappers = 146,
WrenchIndex = 147,
BuildingCostReduction = 148,
BleedingDuration = 149,
TurnToGold = 150,
DeprecatedSocketedItemDefinitionIdDeprecated = 151,
CustomTextureLo = 152,
CannotTrade = 153,
DisguiseOnBackstab = 154,
CannotDisguise = 155,
SilentKiller = 156,
DisguiseSpeedPenalty = 157,
AddCloakOnKill = 158,
SetBonusCloakBlinkTimePenalty = 159,
SetBonusQuietUnStealth = 160,
FlameSizePenalty = 161,
FlameSizeBonus = 162,
FlameLifePenalty = 163,
FlameLifeBonus = 164,
ChargedAirblast = 165,
AddCloakOnHit = 166,
DisguiseDamageReduction = 167,
DisguiseNoBurn = 168,
SetBonusDmgFromSentryReduced = 169,
AirblastCostIncreased = 170,
AirblastCostDecreased = 171,
Purchased = 172,
FlameAmmoPerSecondIncreased = 173,
FlameAmmoPerSecondDecreased = 174,
JarateDuration = 175,
SetBonusNoDeathFromHeadshots = 176,
DeployTimeIncreased = 177,
DeployTimeDecreased = 178,
MiniCritsBecomeCrits = 179,
HealOnKill = 180,
NoSelfBlastDmg = 181,
SlowEnemyOnHitMajor = 182,
AimingMoveSpeedDecreased = 183,
DuelLoserAccountId = 184,
EventDate = 185,
GifterAccountId = 186,
SetSupplyCrateSeries = 187,
PreserveUberCharge = 188,
ElevateQuality = 189,
ActiveHealthRegen = 190,
ActiveHealthDegen = 191,
ReferencedItemIdLow = 192,
ReferencedItemIdHigh = 193,
ReferencedItemDefUpdated = 194,
AlwaysTradable = 195,
NoiseMaker = 196,
HalloweenItem = 197,
CollectionBitsDeprecated = 198,
SwitchFromWepDeployTimeDecreased = 199,
EnablesAoeHeal = 200,
GestureSpeedIncrease = 201,
ChargeTimeIncreased = 202,
DropHealthPackOnKill = 203,
HitSelfOnMiss = 204,
DmgFromRangedReduced = 205,
DmgFromMeleeIncreased = 206,
BlastDmgToSelfIncreased = 207,
SetDamageTypeIgnite = 208,
MiniCritVsBurningPlayer = 209,
TradableAfterDate = 211,
ForceLevelDisplay = 212,
KillEater = 214,
ApplyZVelocityOnDamage = 215,
ApplyLookVelocityOnDamage = 216,
Sanguisuge = 217,
MarkForDeath = 218,
DecapitateType = 219,
RestoreHealthOnKill = 220,
MultiplyDecloakRate = 221,
MultiplySniperChargeAfterBodyShot = 222,
MultiplySniperChargeAfterMiss = 223,
DmgBonusWhileHalfDead = 224,
DmgPenaltyWhileHalfAlive = 225,
HonorBound = 226,
CustomTextureHi = 227,
MakersMarkId = 228,
UniqueCraftIndex = 229,
ModMedicKilledRevenge = 230,
MedigunChargeIsMegaHeal = 231,
ModMedicKilledMiniCritBoost = 232,
ModMedicHealedDamageBonus = 233,
ModMedicHealedDeployTimePenalty = 234,
ModShovelSpeedBoost = 235,
ModWeaponBlocksHealing = 236,
MultiplySniperChargeAfterHeadshot = 237,
MinigunNoSpinSounds = 238,
UberChargeRateBonusForHealer = 239,
ReloadTimeDecreasedWhileHealed = 240,
ReloadTimeIncreasedHidden = 241,
ModMedicKilledMarkedForDeath = 242,
ModRageOnHitPenalty = 243,
ModRageOnHitBonus = 244,
ModRageDamageBoost = 245,
MultiplyChargeTurnControl = 246,
NoChargeImpactRange = 247,
ChargeImpactDamageIncreased = 248,
ChargeRechargeRateIncreased = 249,
AirDashCount = 250,
SpeedBuffAlly = 251,
DamageForceReduction = 252,
MultiplyCloakRate = 253,
AirblastPushbackScale = 255,
MultiplyAirblastRefireTime = 256,
AirblastVerticalPushbackScale = 257,
AmmoBecomesHealth = 258,
BootsFallingStomp = 259,
DeflectionSizeMultiplier = 260,
SetItemTintRgb2 = 261,
SaxxyAwardCategory = 262,
MeleeBoundsMultiplier = 263,
MeleeRangeMultiplier = 264,
ModMiniCritAirborneDeploy = 265,
ProjectilePenetration = 266,
ModCritWhileAirborne = 267,
MultiplySniperChargePenaltyDisplayOnly = 268,
ModSeeEnemyHealth = 269,
PowerUpMaxCharges = 270,
PowerUpCharges = 271,
PowerUpDuration = 272,
CritBoost = 273,
UberCharge = 274,
CancelFallingDamage = 275,
BidirectionalTeleport = 276,
MultipleSentries = 277,
EffectBarRechargeRateIncreased = 278,
MaxAmmoGrenades1increased = 279,
OverrideProjectileType = 280,
EnergyWeaponNoAmmo = 281,
EnergyWeaponChargedShot = 282,
EnergyWeaponPenetration = 283,
EnergyWeaponNoHurtBuilding = 284,
EnergyWeaponNoDeflect = 285,
EngineerBuildingHealthBonus = 286,
EngineerSentryDamageBonus = 287,
NoCritBoost = 288,
CenterfireProjectile = 289,
KillEaterScoreType = 292,
KillEaterScoreType2 = 293,
KillEater2 = 294,
HasPipboyBuildInterface = 295,
SapperKillsCollectCrits = 296,
SniperOnlyFireZoomed = 297,
ModAmmoPerShot = 298,
AddOnHitAddAmmo = 299,
ElectricalAirblastDisplayOnly = 300,
ModUseMetalAmmoType = 301,
ExpirationDate = 302,
ModMaxPrimaryClipOverride = 303,
SniperFullChargeDamageBonus = 304,
SniperFiresTracer = 305,
SniperNoHeadshotWithoutFullCharge = 306,
ModNoReloadDisplayOnly = 307,
SniperPenetratePlayersWhenCharged = 308,
CritKillWillGib = 309,
Recall = 310,
UnlimitedQuantity = 311,
DisableWeaponHidingForAnimations = 312,
AppliesSnareEffect = 313,
UberDurationBonus = 314,
RefillAmmo = 315,
StoreSortOverrideDeprecated = 317,
FasterReloadRate = 318,
IncreaseBuffDuration = 319,
RoboSapper = 320,
BuildRateBonus = 321,
TauntIsPressAndHold = 322,
AttackProjectiles = 323,
AccuracyScalesDamage = 324,
CurrencyBonus = 325,
IncreasedJumpHeight = 326,
BuildingInstantUpgrade = 327,
DisableFancyClassSelectAnim = 328,
AirblastVulnerabilityMultiplier = 329,
OverrideFootstepSoundSet = 330,
SpawnWithPhysicsToy = 331,
FishDamageOverride = 332,
SetBonusSpecialDsp = 333,
BombinomiconEffectOnDeath = 334,
ClipSizeBonusUpgrade = 335,
HideEnemyHealth = 336,
SubtractVictimMedigunChargeOnHit = 337,
SubtractVictimCloakOnHit = 338,
RevealCloakedVictimOnHit = 339,
RevealDisguisedVictimOnHit = 340,
JarateBackstabber = 341,
EngineerSentryFireRateIncreased = 343,
EngineerSentryRadiusIncreased = 344,
EngineerDispenserRadiusIncreased = 345,
ModBatLaunchesOrnaments = 346,
FreezeBackstabVictim = 347,
FireRatePenaltyHidden = 348,
EnergyWeaponNoDrain = 349,
RagdollsBecomeAsh = 350,
EngineerDisposableSentries = 351,
AltFireTeleportToSpawn = 352,
CannotPickUpBuildings = 353,
StunEnemiesWieldingSameWeapon = 354,
ModAmmoPerShotMissedDisplayOnly = 355,
AirblastDisabled = 356,
IncreaseBuffDurationHidden = 357,
CritForcesVictimToLaugh = 358,
MeltsInFire = 359,
DamageAllConnected = 360,
BecomeFireproofOnHitByFire = 361,
CritFromBehind = 362,
CritDoesNoDamage = 363,
AddJingleToFootsteps = 364,
SetIcicleKnifeMode = 365,
ModStunWaistHighAirborne = 366,
ExtinguishEarnsRevengeCrits = 367,
BurnDamageEarnsRage = 368,
TickleEnemiesWieldingSameWeapon = 369,
AttachParticleEffectStatic = 370,
CosmeticTauntSound = 371,
AcceptedWeddingRingAccountId1 = 372,
AcceptedWeddingRingAccountId2 = 373,
ToolEscrowUntilDate = 374,
GenerateRageOnDamage = 375,
AimingNoFlinch = 376,
AimingKnockbackResistance = 377,
SniperAimingMoveSpeedDecreased = 378,
KillEaterUser1 = 379,
KillEaterUserScoreType1 = 380,
KillEaterUser2 = 381,
KillEaterUserScoreType2 = 382,
KillEaterUser3 = 383,
KillEaterUserScoreType3 = 384,
StrangePartNewCounterId = 385,
MvmCompletedChallengesBitmask = 386,
RageOnKill = 387,
KillEaterKillType = 388,
ShotPenetrateAllPlayers = 389,
HeadshotDamageIncrease = 390,
SetBonusMysterySolvingTimeDecrease = 391,
DamagePenaltyOnBodyShot = 392,
SniperRageDisplayOnly = 393,
FireRateBonusHidden = 394,
ExplosiveSniperShot = 395,
MeleeAttackRateBonus = 396,
ProjectilePenetrationHeavy = 397,
RageOnAssists = 398,
ArmorPiercing = 399,
CannotPickUpIntelligence = 400,
SetBonusChanceOfHungerDecrease = 401,
CannotBeBackstabbed = 402,
SquadSurplusClaimerIdDeprecated = 403,
ShareConsumableWithPatient = 404,
AirblastVerticalVulnerabilityMultiplier = 405,
VisionOptInFlags = 406,
CritVsDisguisedPlayers = 407,
CritVsNonBurningPlayers = 408,
KillForcesAttackerToLaugh = 409,
DamageBonusWhileDisguised = 410,
ProjectileSpreadAnglePenalty = 411,
DmgTakenIncreased = 412,
AutoFiresFullClip = 413,
SelfMarkForDeath = 414,
CountsAsAssisterIsSomeKindOfPetThisUpdateIsGoingToBeAwesome = 415,
ModFlaregunFiresPelletsWithKnockback = 416,
CanOverload = 417,
BoostOnDamage = 418,
HypeResetsOnJump = 419,
PyroYearNumber = 420,
NoPrimaryAmmoFromDispensersWhileActive = 421,
PyrovisionOnlyDisplayOnly = 422,
ClipSizePenaltyHidden = 424,
SapperDamageBonus = 425,
SapperDamagePenalty = 426,
SapperDamageLeachesHealth = 427,
SapperHealthBonus = 428,
SapperHealthPenalty = 429,
RingOfFireWhileAiming = 430,
UsesAmmoWhileAiming = 431,
SapperDegeneratesBuildings = 433,
SapperDamagePenaltyHidden = 434,
CleaverDescription = 435,
RagdollsPlasmaEffect = 436,
CritVsStunnedPlayers = 437,
CritVsWetPlayers = 438,
OverrideItemLevelDescString = 439,
ClipSizeUpgradeAtomic = 440,
AutoFiresFullClipAllAtOnce = 441,
MajorMoveSpeedBonus = 442,
MajorIncreasedJumpHeight = 443,
HeadScale = 444,
PyrovisionOptInDisplayOnly = 445,
HalloweenVisionOptInDisplayOnly = 446,
HalloweenVisionFilterDisplayOnly = 447,
PlayerSkinOverride = 448,
NeverCraftable = 449,
ZombieZombieZombieZombie = 450,
SapperVoicePak = 451,
SapperVoicePakIdleWait = 452,
MerasmusHatLevelDisplayOnly = 453,
StrangeRestrictionType1 = 454,
StrangeRestrictionValue1 = 455,
StrangeRestrictionType2 = 456,
StrangeRestrictionValue2 = 457,
StrangeRestrictionUserType1 = 458,
StrangeRestrictionUserValue1 = 459,
StrangeRestrictionUserType2 = 460,
StrangeRestrictionUserValue2 = 461,
StrangeRestrictionUserType3 = 462,
StrangeRestrictionUserValue3 = 463,
EngineerSentryBuildRateMultiplier = 464,
EngineerTeleporterBuildRateMultiplier = 465,
GrenadeLauncherMortarMode = 466,
GrenadeNotExplodeOnImpact = 467,
StrangeScoreSelector = 468,
EngineerBuildingTeleportingPickup = 469,
GrenadeDamageReductionOnWorldContact = 470,
EngineerRageOnDmg = 471,
MarkForDeathOnBuildingPickup = 472,
MedigunChargeIsResists = 473,
ArrowHealsBuildings = 474,
ProjectileSpeedIncreasedHidden = 475,
DamageBonusHidden = 476,
CannonballPushBack = 477,
RageGivingScale = 478,
OverHealFillRateReduced = 479,
CanteenSpecialist = 481,
OverHealExpert = 482,
MadMilkSyringes = 484,
RocketSpecialist = 488,
SetBonusMoveSpeedSetBonus = 489,
SetBonusHealthRegenSetBonus = 490,
SetBonusDmgTakenFromCritReducedSetBonus = 491,
SetBonusDmgTakenFromFireReducedSetBonus = 492,
HealingMastery = 493,
KillEater3 = 494,
KillEaterScoreType3 = 495,
StrangeRestrictionType3 = 496,
StrangeRestrictionValue3 = 497,
BotCustomJumpParticle = 498,
GenerateRageOnHeal = 499,
CustomNameAttr = 500,
CustomDescAttr = 501,
MedigunBulletResistPassive = 503,
MedigunBlastResistPassive = 504,
MedigunFireResistPassive = 505,
MedigunBulletResistDeployed = 506,
MedigunBlastResistDeployed = 507,
MedigunFireResistDeployed = 508,
MedigunCritBulletPercentBarDeplete = 509,
MedigunCritBlastPercentBarDeplete = 510,
MedigunCritFirePercentBarDeplete = 511,
ThrowableFireSpeed = 512,
ThrowableDamage = 513,
ThrowableHealing = 514,
ThrowableParticleTrailOnly = 515,
SetBonusDmgTakenFromBulletsIncreased = 516,
SetBonusMaxHealthAdditiveBonus = 517,
ScattergunKnockbackMultiplier = 518,
ParticleEffectVerticalOffset = 519,
ParticleEffectUseHeadOrigin = 520,
UseLargeSmokeExplosion = 521,
DamageCausesAirblast = 522,
IncreasedJumpHeightFromWeapon = 524,
DamageForceIncrease = 525,
HealingReceivedBonus = 526,
AfterburnImmunity = 527,
DecodedByItemDefIndex = 528,
HypeDecaysOverTime = 532,
SetBonusCustomTauntParticleAttr = 533,
AirblastVulnerabilityMultiplierHidden = 534,
DamageForceIncreaseHidden = 535,
DamageForceIncreaseText = 536,
SetBonusCallingCardOnKill = 537,
SetThrowableType = 539,
AddHeadOnHit = 540,
ItemStyleOverride = 542,
PaintDecalEnum = 543,
ShowPaintDescription = 544,
BotMedicUberHealthThreshold = 545,
BotMedicUberDeployDelayDuration = 546,
SingleWepDeployTimeDecreased = 547,
HalloweenReloadTimeDecreased = 548,
HalloweenFireRateBonus = 549,
HalloweenIncreasedJumpHeight = 550,
SpecialTaunt = 551,
Revive = 554,
TauntAttackName = 556,
TauntAttackTime = 557,
TauntForceMoveForward = 600,
TauntMimic = 602,
TauntSuccessSound = 606,
TauntSuccessSoundOffset = 607,
TauntSuccessSoundLoop = 608,
TauntSuccessSoundLoopOffset = 609,
IncreasedAirControl = 610,
RocketLaunchImpulse = 612,
MiniCritBoostOnKill = 613,
NoMetalFromDispensersWhileActive = 614,
ProjectileEntityName = 615,
IsThrowablePrimable = 616,
ThrowableDetonationTime = 617,
ThrowableRechargeTime = 618,
CloseRangeBackAttackMiniCrits = 619,
TorsoScale = 620,
RocketJumpAttackRateBonus = 621,
IsThrowableChargeable = 622,
BackHeadshot = 630,
RjAirBombardment = 632,
ProjectileParticleName = 633,
AirJumpOnAttack = 634,
SniperCritNoScope = 636,
SniperIndependentZoomDisplayOnly = 637,
AxtinguisherProperties = 638,
FullChargeTurnControl = 639,
ParachuteAttribute = 640,
TauntForceWeaponSlot = 641,
MiniRockets = 642,
RocketJumpDamageReductionHidden = 643,
ClipSizeIncreaseOnKill = 644,
BreadGlovesProperties = 645,
TauntTurnSpeed = 646,
SniperFiresTracerHidden = 647,
FireRateBonusWithReducedHealth = 651,
TagSummer2014 = 661,
CrateGenerationCode = 662,
StickyBombFizzleTime = 669,
StickyBombChargeRate = 670,
GrenadeNoBounce = 671,
ClassSelectOverrideVcd = 674,
CustomProjectileModel = 675,
LoseDemoChargeOnDamageWhenCharging = 676,
GrenadeNoSpin = 681,
GrenadeDetonationDamagePenalty = 684,
TauntTurnAccelerationTime = 687,
TauntMoveAccelerationTime = 688,
TauntMoveSpeed = 689,
ShuffleCrateItemDefMin = 690,
ShuffleCrateItemDefMax = 691,
LimitedQuantityItem = 692,
SetBonusAlienIsolationXenoBonusPos = 693,
SetBonusAlienIsolationXenoBonusNeg = 694,
SetBonusAlienIsolationMercBonusPos = 695,
SetBonusAlienIsolationMercBonusNeg = 696,
DisableWeaponSwitch = 698,
HandScale = 699,
DisplayDuckLeaderboard = 700,
DuckRating = 701,
DuckBadgeLevel = 702,
TagEotlEarlySupport = 703,
UnlimitedQuantityHidden = 704,
DuckStreaksActive = 705,
PanicAttack = 708,
PanicAttackNegative = 709,
AutoFiresFullClipPenalty = 710,
AutoFiresWhenFull = 711,
ForceWeaponSwitch = 712,
WeaponUsesStattrakModule = 719,
IsOperationPass = 723,
WeaponStattrakModuleScale = 724,
SetItemTextureWear = 725,
CloakConsumeOnFeignDeathActivate = 726,
StickyBombChargeDamageIncrease = 727,
NoCloakWhenCloaked = 728,
ReducedCloakFromAmmo = 729,
ElevateToUnusualIfApplicable = 730,
WeaponAllowInspect = 731,
MetalPickupDecreased = 732,
LoseHypeOnTakeDamage = 733,
HealingReceivedPenalty = 734,
CritVsBurningFlaresDisplayOnly = 735,
SpeedBoostOnKill = 736,
SpeedBoostOnHit = 737,
SpunUpDamageResistance = 738,
UberChargeOverHealRatePenalty = 739,
ReducedHealingFromMedics = 740,
HealthOnRadiusDamage = 741,
StyleChangesOnStrangeLevel = 742,
CannotRestore = 743,
HideCrateSeriesNumber = 744,
HasTeamColorPaintKit = 745,
CosmeticAllowInspect = 746,
HatOnlyUnusualEffect = 747,
ItemsTradedInFor = 748,
TextureWearDefault = 749,
TauntOnlyUnusualEffect = 750,
DeActiveDate = 751,
IsGigerCounter = 752,
HideStrangePrefix = 753,
AlwaysTransmitSo = 754,
AllowHalloweenOffering = 760,
CannotTransmute = 762,
SingleWepHolsterTimeIncreased = 772,
SingleWepDeployTimeIncreased = 773,
ChargeTimeDecreased = 774,
DmgPenaltyVsBuildings = 775,
ChargeImpactDamageDecreased = 776,
NonEconomy = 777,
ChargeMeterOnHit = 778,
MiniCritBoostWhenCharged = 779,
MiniCritBoostChargeRate = 780,
IsASword = 781,
AmmoGivesCharge = 782,
ExtinguishRestoresHealth = 783,
ExtinguishReducesCooldown = 784,
CannotGiftWrap = 785,
ToolNeedsGiftWrap = 786,
FuseBonus = 787,
MoveSpeedBonusShieldRequired = 788,
DamageBonusBulletVsSentryTarget = 789,
ModTeleporterCost = 790,
DamageBlastPush = 791,
MoveSpeedBonusResourceLevel = 792,
HypeOnDamage = 793,
DmgTakenFromFireReducedOnActive = 794,
DamageBonusVsBurning = 795,
MinViewmodelOffset = 796,
DmgPiercesResistsAbsorbs = 797,
EnergyBuffDmgTakenMultiplier = 798,
LoseRevengeCritsOnDeathDisplayOnly = 799,
PatientOverHealPenalty = 800,
ItemMeterChargeRate = 801,
MultiplySpreadScaleFirstShot = 804,
UnusualifierAttributeTemplateName = 805,
ToolTargetItemIconOffset = 806,
AddHeadOnKill = 807,
MultiplySpreadScalesConsecutive = 808,
FixedShotPattern = 809,
ModCloakNoRegenFromItems = 810,
UberChargePreservedOnSpawnMax = 811,
ModAirControlBlastJump = 812,
SpunUpPushForceImmunity = 813,
ModMarkAttackerForDeath = 814,
UseModelCacheIcon = 815,
ModDisguiseConsumesCloak = 816,
InspectViewmodelOffset = 817,
IsPassiveWeapon = 818,
NoJump = 819,
NoDuck = 820,
NoAttack = 821,
AirblastDestroyProjectile = 822,
AirblastPushbackDisabled = 823,
AirblastPushbackNoStun = 824,
AirblastPushbackNoViewPunch = 825,
AirblastDeflectProjectilesDisabled = 826,
AirblastPutOutTeammateDisabled = 827,
AfterburnDurationPenalty = 828,
AfterburnDurationBonus = 829,
AoeDeflection = 830,
MultiplyEndFlameSize = 831,
AirblastGiveTeammateSpeedBoost = 832,
AirblastTurnProjectileToAmmo = 833,
PaintKitProtoDefIndex = 834,
TauntAttrPlayerInvisibilityPercent = 835,
RedirectedFlameSizeMultiplier = 837,
FlameReflectOnCollision = 838,
FlameSpreadDegree = 839,
HolsterAnimTime = 840,
FlameGravity = 841,
FlameIgnorePlayerVelocity = 842,
FlameDrag = 843,
FlameSpeed = 844,
Grenades1resupplyDenied = 845,
Grenades2resupplyDenied = 846,
Grenades3resupplyDenied = 847,
ItemMeterResupplyDenied = 848,
MultiplyPlayerMoveSpeedActive = 851,
MultiplyDamageTakenActive = 852,
MultiplyPatientOverHealPenaltyActive = 853,
MultiplyHealthFromHealersPenaltyActive = 854,
ModMaxHealthDrainRate = 855,
ItemMeterChargeType = 856,
MaxFlameReflectionCount = 859,
FlameReflectionAddLifeTime = 860,
ReflectedFlameDmgReduction = 861,
FlameLifetime = 862,
FlameRandomLifeTimeOffset = 863,
FlameUpSpeed = 865,
CustomPaintKitSeedLo = 866,
CustomPaintKitSeedHi = 867,
CritDmgFalloff = 868,
CritsBecomeMiniCrits = 869,
FallingImpactRadiusPushback = 870,
FallingImpactRadiusStun = 871,
ThermalThrusterAirLaunch = 872,
ThermalThruster = 873,
MultiplyItemMeterChargeRate = 874,
ExplodeOnIgnite = 875,
LunchboxHealingDecreased = 876,
SpeedBoostOnHitEnemy = 877,
ItemMeterStartsEmptyDisplayOnly = 878,
ItemMeterChargeType3displayOnly = 879,
RepairHealthToMetalRatioDisplayOnly = 880,
HealthDrainMedic = 881,
CardDamageBonus = 1000,
CardDmgTakenFromBulletsReduced = 1001,
CardMoveSpeedBonus = 1002,
CardHealthRegen = 1003,
SpellSetItemTintRgb = 1004,
SpellSetHalloweenFootstepType = 1005,
SpellHalloweenVoiceModulation = 1006,
SpellHalloweenPumpkinExplosions = 1007,
SpellHalloweenGreenFlames = 1008,
SpellHalloweenDeathGhosts = 1009,
AttackNotCancelCharge = 1030,
RecipeComponentDefinedItem1 = 2000,
RecipeComponentDefinedItem2 = 2001,
RecipeComponentDefinedItem3 = 2002,
RecipeComponentDefinedItem4 = 2003,
RecipeComponentDefinedItem5 = 2004,
RecipeComponentDefinedItem6 = 2005,
RecipeComponentDefinedItem7 = 2006,
RecipeComponentDefinedItem8 = 2007,
RecipeComponentDefinedItem9 = 2008,
RecipeComponentDefinedItem10 = 2009,
StartDropDate = 2010,
EndDropDate = 2011,
ToolTargetItem = 2012,
KillstreakEffect = 2013,
KillstreakIdleEffect = 2014,
SpellbookPageAttrId = 2015,
HalloweenSpellbookPageTumidum = 2016,
HalloweenSpellbookPageGratanter = 2017,
HalloweenSpellbookPageAudere = 2018,
HalloweenSpellbookPageCongeriae = 2019,
HalloweenSpellbookPageVeteris = 2020,
AdditionalHalloweenResponseCriteriaName = 2021,
LootRarity = 2022,
QualityTextOverride = 2023,
ItemNameTextOverride = 2024,
KillstreakTier = 2025,
WideItemLevel = 2026,
IsAustraliumItem = 2027,
IsMarketable = 2028,
AllowedInMedievalMode = 2029,
CritOnHardHit = 2030,
SeriesNumber = 2031,
RecipeNoPartialComplete = 2032,
KillRefillsMeter = 2034,
RandomDropLineItemUnusualChance = 2035,
RandomDropLineItemUnusualList = 2036,
RandomDropLineItem0 = 2037,
RandomDropLineItem1 = 2038,
RandomDropLineItem2 = 2039,
RandomDropLineItem3 = 2040,
TauntAttachParticleIndex = 2041,
LootListName = 2042,
UpgradeRateDecrease = 2043,
CanShuffleCrateContents = 2044,
RandomDropLineItemFooterDesc = 2045,
IsCommodity = 2046,
VoicePitchScale = 2048,
GunslingerPunchCombo = 2049,
CannotDelete = 2050,
QuestLoanerIdLow = 2051,
QuestLoanerIdHi = 2052,
IsFestivized = 2053,
FireParticleBlue = 2054,
FireParticleRed = 2055,
FireParticleBlueCrit = 2056,
FireParticleRedCrit = 2057,
MeterLabel = 2058,
ItemMeterDamageForFullCharge = 2059,
AirblastCostScaleHidden = 2062,
DragonsFuryPositiveProperties = 2063,
DragonsFuryNegativeProperties = 2064,
DragonsFuryNeutralProperties = 2065,
ForceCenterWrap = 2066,
AttackMiniCritsAndConsumesBurning = 2067,
IsWinterCase = 2068,
ItemSlotCriteria1 = 3000,
ItemInSlot1 = 3001,
ItemSlotCriteria2 = 3002,
ItemInSlot2 = 3003,
ItemSlotCriteria3 = 3004,
ItemInSlot3 = 3005,
ItemSlotCriteria4 = 3006,
ItemInSlot4 = 3007,
ItemSlotCriteria5 = 3008,
ItemInSlot5 = 3009,
ItemSlotCriteria6 = 3010,
ItemInSlot6 = 3011,
ItemSlotCriteria7 = 3012,
ItemInSlot7 = 3013,
ItemSlotCriteria8 = 3014,
ItemInSlot8 = 3015,
QuestEarnedStandardPoints = 3016,
QuestEarnedBonusPoints = 3017,
ItemDropWave = 3018,
}
pub trait AttributeValueType {
fn from_prop_value(value: &SendPropValue) -> Self;
}
impl AttributeValueType for f32 {
fn from_prop_value(value: &SendPropValue) -> Self {
let bits = i64::try_from(value).unwrap_or_default() as u32;
f32::from_bits(bits)
}
}
impl AttributeValueType for i32 {
fn from_prop_value(value: &SendPropValue) -> Self {
f32::from_prop_value(value) as i32
}
}
impl AttributeValueType for bool {
fn from_prop_value(value: &SendPropValue) -> Self {
i32::from_prop_value(value) == 1
}
}
pub fn has_attribute<'a, I: IntoIterator<Item = &'a SendProp>>(
props: I,
attribute: Attribute,
) -> bool {
const ATTRIBUTE_INDEX: SendPropIdentifier =
SendPropIdentifier::new("DT_ScriptCreatedAttribute", "m_iAttributeDefinitionIndex");
for prop in props {
match prop.identifier {
ATTRIBUTE_INDEX if prop.value == SendPropValue::Integer(attribute as i64) => {
return true;
}
_ => {}
}
}
false
}
pub fn get_attribute_value<'a, T: AttributeValueType, I: IntoIterator<Item = &'a SendProp>>(
props: I,
attribute: Attribute,
) -> Option<T> {
const ATTRIBUTE_INDEX: SendPropIdentifier =
SendPropIdentifier::new("DT_ScriptCreatedAttribute", "m_iAttributeDefinitionIndex");
const ATTRIBUTE_VALUE: SendPropIdentifier =
SendPropIdentifier::new("DT_ScriptCreatedAttribute", "m_iRawValue32");
let mut return_next_value = false;
for prop in props {
match prop.identifier {
ATTRIBUTE_INDEX if prop.value == SendPropValue::Integer(attribute as i64) => {
return_next_value = true;
}
ATTRIBUTE_VALUE if return_next_value => return Some(T::from_prop_value(&prop.value)),
_ => {}
}
}
None
}

View file

@ -5,7 +5,10 @@ use crate::demo::gamevent::GameEvent;
use crate::demo::message::packetentities::EntityId;
use crate::demo::packet::datatable::{ClassId, ServerClass, ServerClassName};
use crate::demo::parser::analyser::{Class, Team, UserId, UserInfo};
use crate::demo::parser::MalformedSendPropDefinitionError;
use crate::demo::sendprop::SendPropValue;
use crate::demo::vector::Vector;
use num_enum::TryFromPrimitive;
use parse_display::Display;
use serde::{Deserialize, Serialize};
use std::collections::{BTreeMap, HashMap};
@ -14,6 +17,13 @@ use std::ops::Rem;
#[derive(Default, Serialize, Deserialize, Debug, Copy, Clone, Eq, PartialEq, Hash, Display)]
pub struct Handle(pub i64);
impl TryFrom<&SendPropValue> for Handle {
type Error = MalformedSendPropDefinitionError;
fn try_from(value: &SendPropValue) -> Result<Self, Self::Error> {
i64::try_from(value).map(Handle)
}
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Default)]
#[non_exhaustive]
pub enum PlayerState {
@ -69,8 +79,8 @@ pub struct Player {
pub pitch_angle: f32,
pub state: PlayerState,
pub info: Option<UserInfo>,
pub charge: u8,
pub simtime: u16,
pub class_data: PlayerClassData,
pub simulation_time: u16,
pub ping: u16,
pub in_pvs: bool,
pub bounds: Box,
@ -78,6 +88,49 @@ pub struct Player {
pub(crate) conditions: [u8; 20],
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Default, TryFromPrimitive)]
#[serde(rename_all = "lowercase")]
#[repr(u8)]
pub enum MedigunType {
#[default]
Uber,
Kritzkrieg,
Quickfix,
Vaccinator,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
pub enum PlayerClassData {
#[default]
None,
Medic {
charge: u8,
medigun: MedigunType,
},
Spy {
disguise_team: Team,
disguise_class: Class,
cloak: f32,
},
}
impl PlayerClassData {
pub fn default_for_class(class: Class) -> PlayerClassData {
match class {
Class::Medic => PlayerClassData::Medic {
charge: 0,
medigun: MedigunType::Uber,
},
Class::Spy => PlayerClassData::Spy {
disguise_team: Team::Other,
disguise_class: Class::Other,
cloak: 0.0,
},
_ => PlayerClassData::None,
}
}
}
pub const PLAYER_BOX_DEFAULT: Box = Box {
min: Vector {
x: -24.0,

View file

@ -1,3 +1,4 @@
pub mod attributes;
mod cond;
pub mod game_state;
pub mod userinfo;

View file

@ -82,7 +82,7 @@ impl PartialOrd<u32> for EntityId {
#[discriminant_bits = 2]
#[repr(u8)]
pub enum UpdateType {
Preserve = 0b00,
Delta = 0b00,
Leave = 0b01,
Enter = 0b10,
Delete = 0b11,
@ -177,6 +177,17 @@ impl PacketEntity {
.find(|prop| prop.identifier == *index)
}
pub fn get_own_prop_value_by_identifier<T: for<'a> TryFrom<&'a SendPropValue>>(
&self,
index: SendPropIdentifier,
) -> Option<T> {
self.props
.iter()
.find(|prop| prop.identifier == index)
.map(|prop| &prop.value)
.and_then(|value| value.try_into().ok())
}
pub fn apply_update(&mut self, props: &[SendProp]) {
for prop in props {
match self.mut_prop_by_identifier(&prop.identifier) {
@ -370,7 +381,7 @@ impl Parse<'_> for PacketEntitiesMessage {
Self::read_update(&mut data, send_table, &mut entity.props, entity_index)?;
entities.push(entity);
} else if update_type == UpdateType::Preserve {
} else if update_type == UpdateType::Delta {
let mut entity = get_entity_for_update(state, entity_index, update_type, delta)?;
let send_table = get_send_table(state, entity.server_class)?;
@ -445,7 +456,7 @@ impl Encode for PacketEntitiesMessage {
Self::write_enter(entity, stream, state)?;
Self::write_update(&entity.props, stream, send_table, entity.entity_index)?;
}
UpdateType::Preserve => {
UpdateType::Delta => {
Self::write_update(&entity.props, stream, send_table, entity.entity_index)?;
}
_ => {}
@ -717,7 +728,7 @@ fn test_packet_entitier_message_roundtrip() {
},
],
in_pvs: true,
update_type: UpdateType::Preserve,
update_type: UpdateType::Delta,
serial_number: 0,
delay: None,
delta: None,

View file

@ -1,7 +1,10 @@
use crate::demo::data::attributes::{has_attribute, Attribute};
pub use crate::demo::data::game_state::{
Building, BuildingClass, Dispenser, GameState, Kill, PlayerState, Sentry, Teleporter, World,
};
use crate::demo::data::game_state::{Cart, Handle, Objective, PipeType, Projectile, ProjectileType};
use crate::demo::data::game_state::{
Cart, Handle, MedigunType, Objective, PipeType, PlayerClassData, Projectile, ProjectileType,
};
use crate::demo::data::DemoTick;
use crate::demo::gameevent_gen::ObjectDestroyedEvent;
use crate::demo::gamevent::GameEvent;
@ -143,10 +146,8 @@ impl GameStateAnalyser {
for prop in &entity.props {
if prop.identifier == OUTER {
let outer = i64::try_from(&prop.value).unwrap_or_default();
self.state
.outer_map
.insert(Handle(outer), entity.entity_index);
let outer = Handle::try_from(&prop.value).unwrap_or_default();
self.state.outer_map.insert(outer, entity.entity_index);
}
}
@ -158,6 +159,7 @@ impl GameStateAnalyser {
"CObjectDispenser" => self.handle_dispenser_entity(entity, parser_state),
"CObjectTeleporter" => self.handle_teleporter_entity(entity, parser_state),
"CFuncTrackTrain" => self.handle_train_entity(entity, parser_state),
"CWeaponMedigun" => self.handle_medigun_entity(entity, parser_state),
_ if class_name.starts_with("CTFProjectile_")
|| class_name.as_str() == "CTFGrenadePipebombProjectile" =>
{
@ -188,11 +190,19 @@ impl GameStateAnalyser {
i64::try_from(&prop.value).unwrap_or_default() as u16
}
"m_iPlayerClass" => {
player.class =
Class::new(i64::try_from(&prop.value).unwrap_or_default())
let class =
Class::new(i64::try_from(&prop.value).unwrap_or_default());
if player.class != class {
player.class = class;
player.class_data = PlayerClassData::default_for_class(class);
}
}
"m_iChargeLevel" => {
player.charge = i64::try_from(&prop.value).unwrap_or_default() as u8
if let PlayerClassData::Medic { charge, .. } =
&mut player.class_data
{
*charge = i64::try_from(&prop.value).unwrap_or_default() as u8
}
}
"m_iPing" => {
player.ping = i64::try_from(&prop.value).unwrap_or_default() as u16
@ -253,6 +263,13 @@ impl GameStateAnalyser {
const WEAPON_1: SendPropIdentifier = SendPropIdentifier::new("m_hMyWeapons", "001");
const WEAPON_2: SendPropIdentifier = SendPropIdentifier::new("m_hMyWeapons", "002");
const DISGUISE_TEAM: SendPropIdentifier =
SendPropIdentifier::new("DT_TFPlayerSharedLocal", "m_nDesiredDisguiseTeam");
const DISGUISE_CLASS: SendPropIdentifier =
SendPropIdentifier::new("DT_TFPlayerSharedLocal", "m_nDesiredDisguiseClass");
const CLOAK_LEVEL: SendPropIdentifier =
SendPropIdentifier::new("DT_TFPlayerShared", "m_flCloakMeter");
player.in_pvs = entity.in_pvs;
for prop in entity.props(parser_state) {
@ -281,22 +298,22 @@ impl GameStateAnalyser {
player.pitch_angle = f32::try_from(&prop.value).unwrap_or_default()
}
SIMTIME_PROP => {
player.simtime = i64::try_from(&prop.value).unwrap_or_default() as u16
player.simulation_time = i64::try_from(&prop.value).unwrap_or_default() as u16
}
PROP_BB_MAX => {
let max = Vector::try_from(&prop.value).unwrap_or_default();
player.bounds.max = max;
}
WEAPON_0 => {
let handle = Handle(i64::try_from(&prop.value).unwrap_or_default());
let handle = Handle::try_from(&prop.value).unwrap_or_default();
player.weapons[0] = handle;
}
WEAPON_1 => {
let handle = Handle(i64::try_from(&prop.value).unwrap_or_default());
let handle = Handle::try_from(&prop.value).unwrap_or_default();
player.weapons[1] = handle;
}
WEAPON_2 => {
let handle = Handle(i64::try_from(&prop.value).unwrap_or_default());
let handle = Handle::try_from(&prop.value).unwrap_or_default();
player.weapons[2] = handle;
}
PLAYER_COND | PLAYER_COND_BITS => {
@ -324,11 +341,58 @@ impl GameStateAnalyser {
&i64::try_from(&prop.value).unwrap_or_default().to_le_bytes()[0..4],
);
}
DISGUISE_TEAM => {
if let PlayerClassData::Spy { disguise_team, .. } = &mut player.class_data {
*disguise_team = Team::new(i64::try_from(&prop.value).unwrap_or_default())
}
}
DISGUISE_CLASS => {
if let PlayerClassData::Spy { disguise_class, .. } = &mut player.class_data {
*disguise_class =
Class::new(i64::try_from(&prop.value).unwrap_or_default());
}
}
CLOAK_LEVEL => {
if let PlayerClassData::Spy { cloak, .. } = &mut player.class_data {
*cloak = f32::try_from(&prop.value).unwrap_or_default();
}
}
_ => {}
}
}
}
pub fn handle_medigun_entity(&mut self, entity: &PacketEntity, _parser_state: &ParserState) {
const OUTER: SendPropIdentifier =
SendPropIdentifier::new("DT_AttributeContainer", "m_hOuter");
if entity.update_type == UpdateType::Enter {
let mut ty = MedigunType::Uber;
if has_attribute(&entity.props, Attribute::MedigunChargeIsCritBoost) {
ty = MedigunType::Kritzkrieg;
}
if has_attribute(&entity.props, Attribute::MedigunChargeIsMegaHeal) {
ty = MedigunType::Quickfix;
}
if has_attribute(&entity.props, Attribute::MedigunChargeIsResists) {
ty = MedigunType::Vaccinator;
}
if let Some(handle) = entity.get_own_prop_value_by_identifier(OUTER) {
if let Some(player) = self
.state
.players
.iter_mut()
.find(|player| player.weapons.contains(&handle))
{
if let PlayerClassData::Medic { medigun, .. } = &mut player.class_data {
*medigun = ty;
}
}
}
}
}
pub fn handle_world_entity(&mut self, entity: &PacketEntity, parser_state: &ParserState) {
if let (
Some(SendProp {
@ -669,9 +733,7 @@ impl GameStateAnalyser {
.state
.objectives
.entry(entity.entity_index)
.or_insert_with(|| {
Objective::Cart(Cart::default())
});
.or_insert_with(|| Objective::Cart(Cart::default()));
#[allow(irrefutable_let_patterns)]
if let Objective::Cart(cart) = objective {
@ -705,9 +767,7 @@ impl GameStateAnalyser {
.state
.objectives
.entry(entity.entity_index)
.or_insert_with(|| {
Objective::Cart(Cart::default())
});
.or_insert_with(|| Objective::Cart(Cart::default()));
todo!()
}

View file

@ -28,7 +28,7 @@ pub enum PVSCompat {
impl From<UpdateType> for PVSCompat {
fn from(pvs: UpdateType) -> Self {
match pvs {
UpdateType::Preserve => PVSCompat::Preserve,
UpdateType::Delta => PVSCompat::Preserve,
UpdateType::Leave => PVSCompat::Leave,
UpdateType::Enter => PVSCompat::Enter,
UpdateType::Delete => PVSCompat::Delete,

View file

@ -25,8 +25,8 @@ expression: state
"steamId": "[U:1:78023051]",
"team": "other"
},
"charge": 0,
"simtime": 89,
"class_data": "None",
"simulation_time": 89,
"ping": 41,
"in_pvs": true,
"bounds": {
@ -90,8 +90,8 @@ expression: state
"steamId": "[U:1:151261665]",
"team": "other"
},
"charge": 0,
"simtime": 85,
"class_data": "None",
"simulation_time": 85,
"ping": 41,
"in_pvs": false,
"bounds": {
@ -155,8 +155,13 @@ expression: state
"steamId": "[U:1:105458702]",
"team": "other"
},
"charge": 0,
"simtime": 80,
"class_data": {
"Medic": {
"charge": 0,
"medigun": "uber"
}
},
"simulation_time": 80,
"ping": 21,
"in_pvs": false,
"bounds": {
@ -220,8 +225,8 @@ expression: state
"steamId": "[U:1:81747492]",
"team": "other"
},
"charge": 0,
"simtime": 92,
"class_data": "None",
"simulation_time": 92,
"ping": 60,
"in_pvs": true,
"bounds": {
@ -285,8 +290,8 @@ expression: state
"steamId": "[U:1:50363269]",
"team": "other"
},
"charge": 0,
"simtime": 85,
"class_data": "None",
"simulation_time": 85,
"ping": 48,
"in_pvs": false,
"bounds": {
@ -350,8 +355,13 @@ expression: state
"steamId": "[U:1:192228451]",
"team": "other"
},
"charge": 0,
"simtime": 87,
"class_data": {
"Medic": {
"charge": 0,
"medigun": "uber"
}
},
"simulation_time": 87,
"ping": 58,
"in_pvs": false,
"bounds": {
@ -415,8 +425,8 @@ expression: state
"steamId": "[U:1:103356736]",
"team": "other"
},
"charge": 0,
"simtime": 83,
"class_data": "None",
"simulation_time": 83,
"ping": 40,
"in_pvs": false,
"bounds": {
@ -480,8 +490,8 @@ expression: state
"steamId": "[U:1:85558037]",
"team": "other"
},
"charge": 0,
"simtime": 84,
"class_data": "None",
"simulation_time": 84,
"ping": 41,
"in_pvs": false,
"bounds": {
@ -545,8 +555,8 @@ expression: state
"steamId": "[U:1:101328438]",
"team": "other"
},
"charge": 0,
"simtime": 86,
"class_data": "None",
"simulation_time": 86,
"ping": 81,
"in_pvs": false,
"bounds": {
@ -610,8 +620,8 @@ expression: state
"steamId": "[U:1:63292929]",
"team": "other"
},
"charge": 0,
"simtime": 88,
"class_data": "None",
"simulation_time": 88,
"ping": 26,
"in_pvs": false,
"bounds": {
@ -675,8 +685,8 @@ expression: state
"steamId": "[U:1:91304212]",
"team": "other"
},
"charge": 0,
"simtime": 81,
"class_data": "None",
"simulation_time": 81,
"ping": 37,
"in_pvs": false,
"bounds": {
@ -740,8 +750,8 @@ expression: state
"steamId": "[U:1:82128674]",
"team": "other"
},
"charge": 0,
"simtime": 83,
"class_data": "None",
"simulation_time": 83,
"ping": 16,
"in_pvs": false,
"bounds": {

View file

@ -25,8 +25,8 @@ expression: state
"steamId": "[U:1:64229260]",
"team": "other"
},
"charge": 0,
"simtime": 78,
"class_data": "None",
"simulation_time": 78,
"ping": 5,
"in_pvs": true,
"bounds": {