How to use PlayerAnimation.RELOAD?

Please post any questions about developing your plugin here. Please use the search function before posting!
User avatar
BackRaw
Senior Member
Posts: 537
Joined: Sun Jul 15, 2012 1:46 am
Location: Germany
Contact:

How to use PlayerAnimation.RELOAD?

Postby BackRaw » Fri Dec 01, 2017 12:29 am

Hi,

can I somehow utilize PlayerAnimation.RELOAD to detect whether a player wants to reload their weapon? Or is that constant just indicating that the player is currently reloading their weapon?

Thanks!
Last edited by BackRaw on Fri Dec 01, 2017 3:43 am, edited 1 time in total.
User avatar
iPlayer
Developer
Posts: 590
Joined: Sat Nov 14, 2015 8:37 am
Location: Moscow
Contact:

Re: How to use PlayerAnimation.RELOAD?

Postby iPlayer » Fri Dec 01, 2017 1:07 am

It's just one of the possible player animations. You can't really detect anything with it other than that reloading has begun. "Player intention detection" will more likely be described with PlayerButtons.RELOAD, but it will boil down to just checking R (or other key) state, even if a player only possesses a knife.

Offtopic
If you're concerned about that DM ammo re-filling, I'd just set a Repeatable routine that'd go through all player entities (or weapon entities, if CS:GO) and maximize their ammo every 5 seconds. You'll never run out of ammo that way. Heck, I think 5 seconds is rapid enough to prevent your clip (not reserve ammo) from ever running out, because I doubt there're weapons that could fire all of their clip that quickly.

That routine can be optimized though. Apart from that time constant (which I suggested to be 5 seconds), you can think about the routine itself. It might just go through all players and maximize their ammo for each type. But in CS:GO, I think, they changed it so that the ammo is not a player property, but a property of the weapon itself. So iterating on weapon entities instead of players will reduce the costs. I also believe that setting ammo attributes of 100 entities in one tick won't freeze the server as much as creating 100 Repeat routines for each player/entity, so I'd go with a single global ammo-resetting loop.
Image /id/its_iPlayer
My plugins: Map Cycle • Killstreaker • DeadChat • Infinite Jumping • TripMines • AdPurge • Bot Damage • PLRBots • Entity AntiSpam

Hail, Companion. [...] Hands to yourself, sneak thief. Image
User avatar
BackRaw
Senior Member
Posts: 537
Joined: Sun Jul 15, 2012 1:46 am
Location: Germany
Contact:

Re: How to use PlayerAnimation.RELOAD?

Postby BackRaw » Fri Dec 01, 2017 1:13 am

iPlayer wrote:It's just one of the possible player animations. You can't really detect anything with it other than that reloading has begun. "Player intention detection" will more likely be described with PlayerButtons.RELOAD, but it will boil down to just checking R (or other key) state, even if a player only possesses a knife.

Thanks for the info!

iPlayer wrote:Offtopic
If you're concerned about that DM ammo re-filling, I'd just set a Repeatable routine that'd go through all player entities (or weapon entities, if CS:GO) and maximize their ammo every 5 seconds. You'll never run out of ammo that way. Heck, I think 5 seconds is rapid enough to prevent your clip (not reserve ammo) from ever running out, because I doubt there're weapons that could fire all of their clip that quickly.

That routine can be optimized though. Apart from that time constant (which I suggested to be 5 seconds), you can think about the routine itself. It might just go through all players and maximize their ammo for each type. But in CS:GO, I think, they changed it so that the ammo is not a player property, but a property of the weapon itself. So iterating on weapon entities instead of players will reduce the costs. I also believe that setting ammo attributes of 100 entities in one tick won't freeze the server as much as creating 100 Repeat routines for each player/entity, so I'd go with a single global ammo-resetting loop.

Yeah well, do you think that would be a better/smoother approach than my current implementation?
User avatar
iPlayer
Developer
Posts: 590
Joined: Sat Nov 14, 2015 8:37 am
Location: Moscow
Contact:

Re: How to use PlayerAnimation.RELOAD?

Postby iPlayer » Fri Dec 01, 2017 1:45 am

Well, can't really answer your question, but I'd point out the issue with your implementation.

You delay the refilling procedure with Source.Python delay mechanism on a value based on m_flNextPrimaryAttack value. But the latter is expressed with time that can be affected by host_timescale, while Source.Python uses system time to delay user routines. So yeah, 1 second that you add "to somewhat counter the effects of lags, etc" is reasonable because engine internal time is different from OS time and the lags really can mess the whole thing up. But host_timescale makes that 1 second pointless, as depending on the cvar this 1 second can play different roles in fighting effects of lags.

Also if a server freezes for more than 1 second, any player that was reloading a weapon won't get his ammo refilled.

Now, what if you remove all that next-attack/delaying stuff at all? Refill the ammo right when weapon_reload fires. You lose exactly 1 clip of ammo (because at the end of animation a player will have the ammo reduced), but will it make any difference? If you want players to see the max ammo value most of the time, you can instead reset their ammo to max_ammo + clip_size to counter the effect of ammo reduction. It's just the player will see impossible (in classic gameplay terms) amount of ammo, but only while the reloading animation plays.
Image /id/its_iPlayer
My plugins: Map Cycle • Killstreaker • DeadChat • Infinite Jumping • TripMines • AdPurge • Bot Damage • PLRBots • Entity AntiSpam

Hail, Companion. [...] Hands to yourself, sneak thief. Image
User avatar
BackRaw
Senior Member
Posts: 537
Joined: Sun Jul 15, 2012 1:46 am
Location: Germany
Contact:

Re: How to use PlayerAnimation.RELOAD?

Postby BackRaw » Fri Dec 01, 2017 2:07 am

iPlayer wrote:Well, can't really answer your question, but I'd point out the issue with your implementation.

You delay the refilling procedure with Source.Python delay mechanism on a value based on m_flNextPrimaryAttack value. But the latter is expressed with time that can be affected by host_timescale, while Source.Python uses system time to delay user routines. So yeah, 1 second that you add "to somewhat counter the effects of lags, etc" is reasonable because engine internal time is different from OS time and the lags really can mess the whole thing up. But host_timescale makes that 1 second pointless, as depending on the cvar this 1 second can play different roles in fighting effects of lags.

Also if a server freezes for more than 1 second, any player that was reloading a weapon won't get his ammo refilled.

Wow, I didn't know that this was the case! Can the tickrate affect the issue here as well?

iPlayer wrote:Now, what if you remove all that next-attack/delaying stuff at all? Refill the ammo right when weapon_reload fires. You lose exactly 1 clip of ammo (because at the end of animation a player will have the ammo reduced), but will it make any difference? If you want players to see the max ammo value most of the time, you can instead reset their ammo to max_ammo + clip_size to counter the effect of ammo reduction. It's just the player will see impossible (in classic gameplay terms) amount of ammo, but only while the reloading animation plays.

Good point, never thought about doing it that way lol. I'll try it out, thanks.
User avatar
iPlayer
Developer
Posts: 590
Joined: Sat Nov 14, 2015 8:37 am
Location: Moscow
Contact:

Re: How to use PlayerAnimation.RELOAD?

Postby iPlayer » Fri Dec 01, 2017 2:25 am

No, tickrate doesn't affect internal timer, because tick interval (ideal time spent per tick) is constant once you launch the server. The game is smart enough to do the math, given it knows the total tick count and the tick interval :)

Also. I didn't see that you also launch your refilling routine (the one with delays and all that math) in OnPlayerRunCommand. That's sensible since weapon_reload is reported to fire only on manual reload. Two issue here, though:

1. You acquire player's active weapon and its class (weapon data) and a instantiate your own classes inside of that listener. That listener is called every tick, so move as much heavy stuff as possible out of it. Since you simply check for weapon's clip being 0, just create an EntityDictionary and add all weapons that you give to players there. And iterate over that list every tick if you want, but you will have access to the entities right away, without fiddling with player entities etc.

2. Weapon reloading is not started as long as a player holds their ATTACK button. With your plugin, proceeding to hold the ATTACK button with an empted clip will result not only to PlayerEntity instantiating every tick, but also doing all that math/delaying stuff which will add 64 new delay routines per second to Source.Python delaying mechanism.
Image /id/its_iPlayer
My plugins: Map Cycle • Killstreaker • DeadChat • Infinite Jumping • TripMines • AdPurge • Bot Damage • PLRBots • Entity AntiSpam

Hail, Companion. [...] Hands to yourself, sneak thief. Image
User avatar
L'In20Cible
Project Leader
Posts: 1533
Joined: Sat Jul 14, 2012 9:29 pm
Location: Québec

Re: How to use PlayerAnimation.RELOAD?

Postby L'In20Cible » Fri Dec 01, 2017 2:38 am

Why not simply hook CBaseCombatCharacter::RemoveAmmo and always block its execution?
User avatar
BackRaw
Senior Member
Posts: 537
Joined: Sun Jul 15, 2012 1:46 am
Location: Germany
Contact:

Re: How to use PlayerAnimation.RELOAD?

Postby BackRaw » Fri Dec 01, 2017 2:49 am

L'In20Cible wrote:Why not simply hook CBaseCombatCharacter::RemoveAmmo and always block its execution?

I didn't know about that. Is it exposed so I can use it in a EntityPreHook?
User avatar
BackRaw
Senior Member
Posts: 537
Joined: Sun Jul 15, 2012 1:46 am
Location: Germany
Contact:

Re: How to use PlayerAnimation.RELOAD?

Postby BackRaw » Fri Dec 01, 2017 2:51 am

iPlayer wrote:No, tickrate doesn't affect internal timer, because tick interval (ideal time spent per tick) is constant once you launch the server. The game is smart enough to do the math, given it knows the total tick count and the tick interval :)

Also. I didn't see that you also launch your refilling routine (the one with delays and all that math) in OnPlayerRunCommand. That's sensible since weapon_reload is reported to fire only on manual reload. Two issue here, though:

1. You acquire player's active weapon and its class (weapon data) and a instantiate your own classes inside of that listener. That listener is called every tick, so move as much heavy stuff as possible out of it. Since you simply check for weapon's clip being 0, just create an EntityDictionary and add all weapons that you give to players there. And iterate over that list every tick if you want, but you will have access to the entities right away, without fiddling with player entities etc.

2. Weapon reloading is not started as long as a player holds their ATTACK button. With your plugin, proceeding to hold the ATTACK button with an empted clip will result not only to PlayerEntity instantiating every tick, but also doing all that math/delaying stuff which will add 64 new delay routines per second to Source.Python delaying mechanism.

Good point! Well, I'm cancelling each delay in delay_manager.__call__() so it won't start 64 new delays. However, it's a bit of a hack and not the best solution, I admit that.
User avatar
iPlayer
Developer
Posts: 590
Joined: Sat Nov 14, 2015 8:37 am
Location: Moscow
Contact:

Re: How to use PlayerAnimation.RELOAD?

Postby iPlayer » Fri Dec 01, 2017 2:55 am

Why not simply hook CBaseCombatCharacter::RemoveAmmo and always block its execution?

I was actually going to propose that in my next reply to BackRaw :) Along with refilling the ammo in a post-hook on CBaseCombatWeapon::FinishReload. But I'm kinda taught by you not to hook stuff without the need, and the above solutions will work well. And as for making sure that the player can only see the max amount of ammo on their HUD - isn't ammo subtraction also predicted on clientside? If I remember correctly, clip subtraction (per shot) is predicted, so the player will still see the reduced value for a moment.

P.S. There's an interesting line:

Syntax: Select all

if ( GetAmmoDef()->MaxCarry( iAmmoIndex ) == INFINITE_AMMO )


If we can make sure this MaxCarry returns INFINITE_AMMO for every ammo type, then we achieve what we initally try to do - infinite ammo. I think it must also hide ammo counter on client.
Image /id/its_iPlayer
My plugins: Map Cycle • Killstreaker • DeadChat • Infinite Jumping • TripMines • AdPurge • Bot Damage • PLRBots • Entity AntiSpam

Hail, Companion. [...] Hands to yourself, sneak thief. Image
User avatar
BackRaw
Senior Member
Posts: 537
Joined: Sun Jul 15, 2012 1:46 am
Location: Germany
Contact:

Re: How to use PlayerAnimation.RELOAD?

Postby BackRaw » Fri Dec 01, 2017 3:37 am

iPlayer wrote:
Why not simply hook CBaseCombatCharacter::RemoveAmmo and always block its execution?

I was actually going to propose that in my next reply to BackRaw :) Along with refilling the ammo in a post-hook on CBaseCombatWeapon::FinishReload. But I'm kinda taught by you not to hook stuff without the need, and the above solutions will work well. And as for making sure that the player can only see the max amount of ammo on their HUD - isn't ammo subtraction also predicted on clientside? If I remember correctly, clip subtraction (per shot) is predicted, so the player will still see the reduced value for a moment.

P.S. There's an interesting line:

Syntax: Select all

if ( GetAmmoDef()->MaxCarry( iAmmoIndex ) == INFINITE_AMMO )


If we can make sure this MaxCarry returns INFINITE_AMMO for every ammo type, then we achieve what we initally try to do - infinite ammo. I think it must also hide ammo counter on client.

I like the INFINITE_AMMO approach the most, tbh. That would make things a whole lot easier. :D
User avatar
iPlayer
Developer
Posts: 590
Joined: Sat Nov 14, 2015 8:37 am
Location: Moscow
Contact:

Re: How to use PlayerAnimation.RELOAD?

Postby iPlayer » Fri Dec 01, 2017 3:44 am

Here's the source code of CAmmoDef::MaxCarry:

Syntax: Select all

int	CAmmoDef::MaxCarry(int nAmmoIndex)
{
if ( nAmmoIndex < 1 || nAmmoIndex >= m_nAmmoIndex )
return 0;

if ( m_AmmoType[nAmmoIndex].pMaxCarry == USE_CVAR )
{
if ( m_AmmoType[nAmmoIndex].pMaxCarryCVar )
return m_AmmoType[nAmmoIndex].pMaxCarryCVar->GetFloat();

return 0;
}
else
{
return m_AmmoType[nAmmoIndex].pMaxCarry;
}
}


The easiest solution is probably to make sure that the ammo cvars are set to something that would be treated as INFINITE_AMMO constant.

Now:

Syntax: Select all

#define	INFINITE_AMMO	-2


Just set all ammo cvars to -2, and let the engine do everything else. Every ammo type that is defined by a cvar will be infinite. I've just tested on CS:S, and it just displays the ammo value as 999. Without ever reducing it.

The cvars themselves can be found in wiki (say, here - they all start with ammo_ prefix), but ideally your plugin will find them by itself.
Image /id/its_iPlayer
My plugins: Map Cycle • Killstreaker • DeadChat • Infinite Jumping • TripMines • AdPurge • Bot Damage • PLRBots • Entity AntiSpam

Hail, Companion. [...] Hands to yourself, sneak thief. Image
User avatar
BackRaw
Senior Member
Posts: 537
Joined: Sun Jul 15, 2012 1:46 am
Location: Germany
Contact:

Re: How to use PlayerAnimation.RELOAD?

Postby BackRaw » Fri Dec 01, 2017 3:56 am

iPlayer wrote:Here's the source code of CAmmoDef::MaxCarry:

Syntax: Select all

int	CAmmoDef::MaxCarry(int nAmmoIndex)
{
if ( nAmmoIndex < 1 || nAmmoIndex >= m_nAmmoIndex )
return 0;

if ( m_AmmoType[nAmmoIndex].pMaxCarry == USE_CVAR )
{
if ( m_AmmoType[nAmmoIndex].pMaxCarryCVar )
return m_AmmoType[nAmmoIndex].pMaxCarryCVar->GetFloat();

return 0;
}
else
{
return m_AmmoType[nAmmoIndex].pMaxCarry;
}
}


The easiest solution is probably to make sure that the ammo cvars are set to something that would be treated as INFINITE_AMMO constant.

Now:

Syntax: Select all

#define	INFINITE_AMMO	-2


Just set all ammo cvars to -2, and let the engine do everything else. Every ammo type that is defined by a cvar will be infinite. I've just tested on CS:S, and it just displays the ammo value as 999. Without ever reducing it.

The cvars themselves can be found in wiki (say, here - they all start with ammo_ prefix), but ideally your plugin will find them by itself.

Cool, thought it was harder than that. I can't change the 999 ammo being displayed, can I? Because I kinda don't want to 'touch' that. It would be better, imo, to display the standard max ammo values instead of 999. But for that I would need the CBaseCombatCharacter::RemoveAmmo hook right?

Edit: I can't test it right now, because I'm not on my computer, but does changing the weapon's maxammo value help? I mean using the INFINITE_AMMO approach and then give a weapon and set weapon_entity.maxammo = weapon_data.maxammo. Or will it stay 999?
User avatar
iPlayer
Developer
Posts: 590
Joined: Sat Nov 14, 2015 8:37 am
Location: Moscow
Contact:

Re: How to use PlayerAnimation.RELOAD?

Postby iPlayer » Fri Dec 01, 2017 4:19 am

I suspect it may be possible to hide the clip and the ammo counters altogether, but that causes more problems than it solves. People need to see how much ammo they've got in their clip.

As for "999" number - I'd say it makes more sense in case of an infinite ammo. Not much. But default max ammo value that never reduces makes absolutely zero sense to me. And it is, as it turns out, the default behavior defined by Valve, so why override it? (I know, I've never seen that number anywhere in their games, too).

Another thought is that you could try to set the ammo to your own value after player spawns (you can still change the ammo, you just can't remove it with RemoveAmmo function), but it seems that the game displays "999" as soon as a cvar is set to -2, even on a living player. I.e. no matter how much finite ammo the player had, setting the cvar will instantly display 999. This hints us that the cvar is indeed taken into account on clientside, so this number will not reduce even for a moment due to possible prediction. EDIT: Although this cvar is definitely not intended to hold this magical constant, so why would it be replicated? Tests with artificial lags (so that the prediction will be noticable) are needed.

If you go with hooks on RemoveAmmo, the clientside will predict reducing the ammo. The player will can see max_ammo - clip_size number for a moment, even if the server never actually decided to subtract the ammo. EDIT: Tests are also needed to confirm this

P.S. CS:GO displays 999 for infinite ammo as well. But ammo_45acp_max cvar (.45 is USP ammo type in CS:S) had no effect on USP-S. I hope they just changed the ammo type for it and I was too lazy to search for a new one. There're more ammo types in CS:GO than CS:S. Nobody suspects Valve of forgetting to implement a cvar for USP-S, right? :)

EDIT: I just saw your edit, but I kinda answered it before ever seeing it :)
Image /id/its_iPlayer
My plugins: Map Cycle • Killstreaker • DeadChat • Infinite Jumping • TripMines • AdPurge • Bot Damage • PLRBots • Entity AntiSpam

Hail, Companion. [...] Hands to yourself, sneak thief. Image
User avatar
iPlayer
Developer
Posts: 590
Joined: Sat Nov 14, 2015 8:37 am
Location: Moscow
Contact:

Re: How to use PlayerAnimation.RELOAD?

Postby iPlayer » Fri Dec 01, 2017 4:58 am

I think it's possible to hide the ammo without hiding the clip. According to this and this, setting primary clip size of a weapon type to WEAPON_NOCLIP (which is -1) will hide the ammo counter on player HUDs.

This is partly achievable via SP weapons.scripts package that gives you access to weapon configs. For example, Source.Python knows about clip_size attribute, you will need it.

P.S. This is where 999 comes from

EDIT: Oh, but if you set weapon clip size to -1, you'll have to set actual clip sizes by yourself literally EVERYWHERE to make the weapon work :) Guess what, that includes setting the clip... after reload animation finishes! So we kinda get back to that unwanted stuff. I'd go with 999 in HUD if I were you.
Image /id/its_iPlayer
My plugins: Map Cycle • Killstreaker • DeadChat • Infinite Jumping • TripMines • AdPurge • Bot Damage • PLRBots • Entity AntiSpam

Hail, Companion. [...] Hands to yourself, sneak thief. Image
User avatar
BackRaw
Senior Member
Posts: 537
Joined: Sun Jul 15, 2012 1:46 am
Location: Germany
Contact:

Re: How to use PlayerAnimation.RELOAD?

Postby BackRaw » Fri Dec 01, 2017 7:33 am

Thank you very much! I'll test things out when I get back home :)
User avatar
iPlayer
Developer
Posts: 590
Joined: Sat Nov 14, 2015 8:37 am
Location: Moscow
Contact:

Re: How to use PlayerAnimation.RELOAD?

Postby iPlayer » Fri Dec 01, 2017 10:01 am

I'd also mention CS:GO-specific cvar sv_infinite_ammo. It is used the stock DM mode.
Setting it to 1 will get you an infinite reserve ammo, while setting it to 2 gets you an infinite clip, i.e. players won't need to reload at all. Default value is 0.

I know your plugin is cross-game, but you may want to enable this cvar if it runs on CS:GO. If I remember correctly, the reserve ammo counter will behave the way you like - just default max value.

The most significant difference from exploiting ammo_ cvars is that they can be set separately for different ammo types. For example, you can make unlimited HE grenades without touching any other ammo. But in your case, I don't think this plays the key role as you want ALL weapons to have infinite ammo anyways. The only question is if it's really worth the effort dedicating a separate functionality for CS:GO when the default one can be seen as sufficient.
Image /id/its_iPlayer
My plugins: Map Cycle • Killstreaker • DeadChat • Infinite Jumping • TripMines • AdPurge • Bot Damage • PLRBots • Entity AntiSpam

Hail, Companion. [...] Hands to yourself, sneak thief. Image
User avatar
BackRaw
Senior Member
Posts: 537
Joined: Sun Jul 15, 2012 1:46 am
Location: Germany
Contact:

Re: How to use PlayerAnimation.RELOAD?

Postby BackRaw » Fri Dec 01, 2017 12:03 pm

iPlayer wrote:I'd also mention CS:GO-specific cvar sv_infinite_ammo. It is used the stock DM mode.
Setting it to 1 will get you an infinite reserve ammo, while setting it to 2 gets you an infinite clip, i.e. players won't need to reload at all. Default value is 0.

I know your plugin is cross-game, but you may want to enable this cvar if it runs on CS:GO. If I remember correctly, the reserve ammo counter will behave the way you like - just default max value.

Awesome! Didn't know that cvar existed.

iPlayer wrote:The most significant difference from exploiting ammo_ cvars is that they can be set separately for different ammo types. For example, you can make unlimited HE grenades without touching any other ammo. But in your case, I don't think this plays the key role as you want ALL weapons to have infinite ammo anyways. The only question is if it's really worth the effort dedicating a separate functionality for CS:GO when the default one can be seen as sufficient.

Yeah, if I have to implement it that way (ammo_ cvars) for CS:S then I'm no sure if it would be good to do it another way for CS:GO. I'll need to test each possibility and see what is best.

I guess the thread can be marked as solved now.

Edit: Does sv_infinite_ammo apply to grenades and so on as well?
User avatar
iPlayer
Developer
Posts: 590
Joined: Sat Nov 14, 2015 8:37 am
Location: Moscow
Contact:

Re: How to use PlayerAnimation.RELOAD?

Postby iPlayer » Fri Dec 01, 2017 12:17 pm

BackRaw wrote:Edit: Does sv_infinite_ammo apply to grenades and so on as well?

According to several grenade training tutorials like this one, yes.

I guess the thread can be marked as solved now.

Not sure if we can mark topics as "solved" on these forums besides stating that in the title directly. Which is not a common practice here anyways. The only reason I'd change the current title (and I can't edit your posts) is to make it reflect the true goal and the whole discussion more precisely. Current one is very loose now :)
Image /id/its_iPlayer
My plugins: Map Cycle • Killstreaker • DeadChat • Infinite Jumping • TripMines • AdPurge • Bot Damage • PLRBots • Entity AntiSpam

Hail, Companion. [...] Hands to yourself, sneak thief. Image
User avatar
BackRaw
Senior Member
Posts: 537
Joined: Sun Jul 15, 2012 1:46 am
Location: Germany
Contact:

Re: How to use PlayerAnimation.RELOAD?

Postby BackRaw » Fri Dec 01, 2017 1:53 pm

iPlayer wrote:
BackRaw wrote:Edit: Does sv_infinite_ammo apply to grenades and so on as well?

According to several grenade training tutorials like this one, yes.
Would've been too good to be true otherwise :D

iPlayer wrote:
I guess the thread can be marked as solved now.

Not sure if we can mark topics as "solved" on these forums besides stating that in the title directly. Which is not a common practice here anyways. The only reason I'd change the current title (and I can't edit your posts) is to make it reflect the true goal and the whole discussion more precisely. Current one is very loose now :)

Yeah, idk why I wrote that lol. Anyways I'll get testing soon and hopefully come up with a more efficient implementation than my current one.

Return to “Plugin Development Support”

Who is online

Users browsing this forum: No registered users and 18 guests