You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Distinction between bought and picked up weapon #146
In my application I'm trying to track all player's purchases. For this purpose I use ItemPickup event, its WeaponTraceable() method and my own internal structure that maps every weapon's ID to its owner:
This works perfectly for any weapon except flashbang. When a player buys a second flashbang, they already have this weapon and therefore weaponOwner[weaponTraceable.UniqueID()] stores a value for it. Currently I use a separate rule for second flashbang which looks like this:
ifplayer.IsInBuyZone() && (app.freezetime||app.parser.CurrentTime() -app.roundBeginTime<app.buyTime) {
// bought a flashbang
} else {
// picked it up
}
where app.freezetime is binded to "cs_gamerules_data.m_bFreezePeriod" property of "CCSGameRulesProxy" server class on entity creation, app.roundBeginTime gets updated every time a freezetime ends and app.buyTime is accuired from app.parser.GameState().ConVars()["mp_buytime"].
This seems to be working but still could possibly be the cause of some bugs later on. So my question is -- what is a proper way to determine if a player actually bought a second flashbang?
Hmm, interesting problem. Unfortunately I don't have a quick answer.
It would probably be worth it to integrate this directly into the library.
Something like ItemPickup.IsBought
But I think your implementation is probably correct and I would imagine it would look similar if done inside the parser.
I will do some more testing, depending on the findings a PR would be very welcome 😄
I personally think that IsBought is too strong a name for the shown implementation 🙂 Theoretically, a player can accuire a new weapon through a console command, be given a new weapon for free from some plugin, from round restoring etc. In my application I have quite a complicated logic for eliminating all these reasons which is not general enough to be included directly into the library.
However ItemPickup.IsNew which wraps this code in my opition would be really handy. The only thing which stops me from submitting a PR right now is this second flashbang case.
Side note: your current code will think knifes and starter pistols are bought.
This may or may not be what you want.
Thank you for your care 😃
Currently I'm handling it via
I personally think that IsBought is too strong a name for the shown implementation 🙂
Good point, yeah. I guess for the flashbang having the custom rule until #145 is solved would be acceptable. But if you'd rather wait for that to be resolved that's fine as well, I think it shouldn't be too long away.
Technically, a Glock or USP can be bought if dropped first
That's true, I'm just hoping that in a real game (and I was recently working hard on eliminating all the unimportant rounds from the competitive game) when the player actually wants to win they wouldn't do such a nonsense 😃
But if you'd rather wait for that to be resolved that's fine as well
TBH I think that your library, being in a sense a fundamental one, shoudn't rely on such rules as mine for a second flashbang 🙂 There always might be a case when e.g. a player A bought a flashbang playing as a terrorist on de_dust2, was almost immediately killed by a sniper from double doors and then a player B, which already had a flashbang, has picked up the second flashbang from player A's dead body.
this situation would actually be covered by the buytime check
Not really, in this particular case player A may be dead until the end of the buy time.
This actually is the real problem I've encountered when parsing some MM demos. DD2 seems to be the only map where such situations (player's death in the buy zone in the first seconds of the round) can occur but still it is affecting my economy calculations 😞
I probably should implement some other checks like "have the player spent money equivalent of the item in the same tick as they have picked it up" but I don't know how to perform it aside from storing all players' money which they had in the previous availiable frame which is not reliable since there are some demos where there can be up to 13 in-game ticks between two demo frames and theoretically a player can obtain several new items in between.
Well #147 doesn't really solve this issue: while we are now able to tell how many flashbangs a player has, there is still no way to tell if the second flashbang was bought or picked up since WeaponTraceable() returns UniqueID of the weapon the player already had. At least the method proposed above cannot tell the difference because app.weaponOwner[weaponTraceable.UniqueID()] would always be equal to the current player.
I suspect that there is some fix that can help us but I don't know how to implement it. Let me describe why do I think so:
Case 1: a player has no flashbangs and they pick up (and I mean actually pick up) one. Now the flashbang they have has the same UniqueID as the picked up one and we can track its previous owner (see lines 80, 83, 150, 154, 155 etc. from output3.log) and actually whatever we want to track.
Case 2: a player has one flashbang and they pick up or buy another one. Now UniqueID of the flashbang is lost somewhere and it serves only as ammo for the weapon player already has. In this case we cannot tell the origin of this second flashbang. However, it may be the same flashbang from the first case which otherwise we would be able to track be the player's "flashbang ammo" empty. So there is somewhere the UniqueID of this second flashbang, but we just don't have it anymore when ItemPickup is fired.
So I think there should be a method to catch this moment when UniqueUD of the second flashbang is lost and store it somewhere. Moreover, a believe there should be a way to attach this information directly to ItemPickup event so WeaponTracable() would return the actual picked up item and not try to find it in the player's inventory. It would be more robust and able to track any item despite of its ability to serve as ammo (e. g. when you play Danger Zone you can have several medkits and explosives; and I do not find it impossible that at some point your library may be used for parsing Danger Zone demos 😄)
Well #147 doesn't really solve this issue: while we are now able to tell how many flashbangs a player has, there is still no way to tell if the second flashbang was bought or picked up
Hmm you're right.
So there is somewhere the UniqueID of this second flashbang, but we just don't have it anymore when ItemPickup is fired.
Not quite, UniqueID is an internally generated thing, currently there is no Equipment instance being created in this case, so we don't have a UniqueID. But of course we could create one.
So I think there should be a method to catch this moment when UniqueUD of the second flashbang is lost and store it somewhere. Moreover, a believe there should be a way to attach this information directly to ItemPickup event so WeaponTracable() would return the actual picked up item and not try to find it in the player's inventory. It would be more robust and able to track any item despite of its ability to serve as ammo (e. g. when you play Danger Zone you can have several medkits and explosives; and I do not find it impossible that at some point your library may be used for parsing Danger Zone demos 😄)
I think you're right with that, thanks for your inputs!
It appears like this isn't possible for flashbangs, sorry.
We can't create a new UniqueID because we don't actually have a separate entity for the second flashbang from what I can tell.
WeaponTracable() would return the actual picked up item and not try to find it in the player's inventory.
The item_pickup event has no information about the actual item, only about the type of the item, so there would be no way to tell which of the two flashbangs was the new one even if we could create the second entity.
So all we know is that a player somehow accquired the second flashbang? That's a pity.
How do you think, is there a way to add something like "MoneySpentThisTick" to a player property list? Should be a decent hack to make an almost certain guess that a player has bought something if we know that he has got it in the same tick he lost amount of money equivalent to item's price.
You could try to use CCSPlayerResource.m_iTotalCashSpent.NNN where NNN is Player.Entity.ID() with left padding (e.g. CCSPlayerResource.m_iTotalCashSpent.001)
But I woudln't want to integrate this into the library, seems a bit too hacky to support officially.
Yeah I agree. And also I forgot that we don't have information about each and every tick and there, as I have already mentioned above, might be a gap up to 13 ticks so the player can buy several items in between.
From what i understand the problem here is just for flash bangs in case a player already has one. Would it be possible to implement it for everything else?
Either with a "yes, no, dont know" logic or as ItemPickup.IsDefinitleyNew which is false for duplicate flashbangs?
Activity
markus-wa commentedon Sep 10, 2019
Hmm, interesting problem. Unfortunately I don't have a quick answer.
It would probably be worth it to integrate this directly into the library.
Something like
ItemPickup.IsBoughtBut I think your implementation is probably correct and I would imagine it would look similar if done inside the parser.
I will do some more testing, depending on the findings a PR would be very welcome 😄
markus-wa commentedon Sep 10, 2019
Side note: your current code will think knifes and starter pistols are bought.
This may or may not be what you want.
BestAwperEver commentedon Sep 10, 2019
I personally think that
IsBoughtis too strong a name for the shown implementation 🙂 Theoretically, a player can accuire a new weapon through a console command, be given a new weapon for free from some plugin, from round restoring etc. In my application I have quite a complicated logic for eliminating all these reasons which is not general enough to be included directly into the library.However
ItemPickup.IsNewwhich wraps this code in my opition would be really handy. The only thing which stops me from submitting a PR right now is this second flashbang case.Thank you for your care 😃
Currently I'm handling it via
markus-wa commentedon Sep 10, 2019
Good point, yeah. I guess for the flashbang having the custom rule until #145 is solved would be acceptable. But if you'd rather wait for that to be resolved that's fine as well, I think it shouldn't be too long away.
Technically, a Glock or USP can be bought if dropped first. But I assume that edge case is not super important 😄
BestAwperEver commentedon Sep 10, 2019
That's true, I'm just hoping that in a real game (and I was recently working hard on eliminating all the unimportant rounds from the competitive game) when the player actually wants to win they wouldn't do such a nonsense 😃
BestAwperEver commentedon Sep 10, 2019
TBH I think that your library, being in a sense a fundamental one, shoudn't rely on such rules as mine for a second flashbang 🙂 There always might be a case when e.g. a
player Abought a flashbang playing as a terrorist on de_dust2, was almost immediately killed by a sniper from double doors and then aplayer B, which already had a flashbang, has picked up the second flashbang fromplayer A's dead body.markus-wa commentedon Sep 10, 2019
I agree, but from what I understand this situation would actually be covered by the buytime check.
But anyway, it's certainly safer to wait since we don't know all the edge cases.
BestAwperEver commentedon Sep 10, 2019
Not really, in this particular case
player Amay be dead until the end of the buy time.This actually is the real problem I've encountered when parsing some MM demos. DD2 seems to be the only map where such situations (player's death in the buy zone in the first seconds of the round) can occur but still it is affecting my economy calculations 😞
I probably should implement some other checks like "have the player spent money equivalent of the item in the same tick as they have picked it up" but I don't know how to perform it aside from storing all players' money which they had in the previous availiable frame which is not reliable since there are some demos where there can be up to 13 in-game ticks between two demo frames and theoretically a player can obtain several new items in between.
markus-wa commentedon Sep 10, 2019
Ahhh, bollocks!
Yeah we definitely better wait then.
markus-wa commentedon Sep 13, 2019
So with #147 being merged, do you think your fix would be possible now?
If so please feel free to file a PR 🙂.
BestAwperEver commentedon Sep 13, 2019
Well #147 doesn't really solve this issue: while we are now able to tell how many flashbangs a player has, there is still no way to tell if the second flashbang was bought or picked up since
WeaponTraceable()returnsUniqueIDof the weapon the player already had. At least the method proposed above cannot tell the difference becauseapp.weaponOwner[weaponTraceable.UniqueID()]would always be equal to the current player.I suspect that there is some fix that can help us but I don't know how to implement it. Let me describe why do I think so:
Case 1: a player has no flashbangs and they pick up (and I mean actually pick up) one. Now the flashbang they have has the same
UniqueIDas the picked up one and we can track its previous owner (see lines 80, 83, 150, 154, 155 etc. from output3.log) and actually whatever we want to track.Case 2: a player has one flashbang and they pick up or buy another one. Now
UniqueIDof the flashbang is lost somewhere and it serves only as ammo for the weapon player already has. In this case we cannot tell the origin of this second flashbang. However, it may be the same flashbang from the first case which otherwise we would be able to track be the player's "flashbang ammo" empty. So there is somewhere theUniqueIDof this second flashbang, but we just don't have it anymore whenItemPickupis fired.So I think there should be a method to catch this moment when
UniqueUDof the second flashbang is lost and store it somewhere. Moreover, a believe there should be a way to attach this information directly toItemPickupevent soWeaponTracable()would return the actual picked up item and not try to find it in the player's inventory. It would be more robust and able to track any item despite of its ability to serve as ammo (e. g. when you play Danger Zone you can have several medkits and explosives; and I do not find it impossible that at some point your library may be used for parsing Danger Zone demos 😄)markus-wa commentedon Sep 13, 2019
Hmm you're right.
Not quite,
UniqueIDis an internally generated thing, currently there is noEquipmentinstance being created in this case, so we don't have aUniqueID. But of course we could create one.I think you're right with that, thanks for your inputs!
Let's see if we can make this work somehow 😅.
markus-wa commentedon Nov 6, 2019
It appears like this isn't possible for flashbangs, sorry.
We can't create a new
UniqueIDbecause we don't actually have a separate entity for the second flashbang from what I can tell.The
item_pickupevent has no information about the actual item, only about the type of the item, so there would be no way to tell which of the two flashbangs was the new one even if we could create the second entity.So I think for now there is no way to do this 🙁 .
BestAwperEver commentedon Nov 6, 2019
So all we know is that a player somehow accquired the second flashbang? That's a pity.
How do you think, is there a way to add something like "MoneySpentThisTick" to a player property list? Should be a decent hack to make an almost certain guess that a player has bought something if we know that he has got it in the same tick he lost amount of money equivalent to item's price.
markus-wa commentedon Nov 6, 2019
You could try to use
CCSPlayerResource.m_iTotalCashSpent.NNNwhere NNN isPlayer.Entity.ID()with left padding (e.g.CCSPlayerResource.m_iTotalCashSpent.001)But I woudln't want to integrate this into the library, seems a bit too hacky to support officially.
BestAwperEver commentedon Nov 6, 2019
Yeah I agree. And also I forgot that we don't have information about each and every tick and there, as I have already mentioned above, might be a gap up to 13 ticks so the player can buy several items in between.
markus-wa commentedon Nov 6, 2019
right, good point as well. quite unfortunate.
JanEricNitschke commentedon Apr 26, 2023
From what i understand the problem here is just for flash bangs in case a player already has one. Would it be possible to implement it for everything else?
Either with a "yes, no, dont know" logic or as
ItemPickup.IsDefinitleyNewwhich is false for duplicate flashbangs?MarcusKNielsen commentedon Jan 13, 2024
I agree with @JanEricNitschke if it works for everything except the flashbangs, then this is still a very useful tool.