[ANY] Weapon Zoom

Release your plugins here!
User avatar
Kami
Global Moderator
Posts: 264
Joined: Wed Aug 15, 2012 1:24 am
Location: Germany

[ANY] Weapon Zoom

Postby Kami » Mon Dec 21, 2020 9:51 pm

Hey guys, this is a plugin that enables you to use zoom on weapons that normaly would not have zoom.

https://github.com/kamikazekuh/zoom

You can configure weapons should be able to zoom by adding them to:

Syntax: Select all

zoom_weapons = ['weapon_357',"weapon_pistol']


You can also change the button to use for zooming, default is ATTACK2 (Right click) You can find available Buttons here: http://wiki.sourcepython.com/developing ... yerButtons

Syntax: Select all

zoom_button = PlayerButtons.ATTACK2


You can change the zoom level by changing the zoom_level

Syntax: Select all

zoom_level = 30


If you have any problems with this plugin let me know.
User avatar
daren adler
Senior Member
Posts: 348
Joined: Sat May 18, 2019 7:42 pm

Re: [ANY] Weapon Zoom

Postby daren adler » Wed Jan 20, 2021 2:59 am

I like your script :grin: . i am only using it for 1 weapon ( :tongue: ). I am using it for the smg, and the right mouse button shots the nads,,i went to the site you said to go to change it, but did not figer out what one to use for it, was thinking of mouse 4, but i guess not everyone uses mouse 4 or even have mouse 4. Could you show me what one would be best to use? :rolleyes: I also get a error. Thank you :cool:

Code: Select all

2021-01-19 21:07:43 - sp   -   EXCEPTION   
[SP] Caught an Exception:
Traceback (most recent call last):
  File "..\addons\source-python\plugins\zoom\zoom.py", line 56, in on_player_run_command
    if player.active_weapon.classname not in zoom_weapons and player.active_weapon.classname not in zoom_exclude:

AttributeError: 'NoneType' object has no attribute 'classname'
User avatar
Painkiller
Senior Member
Posts: 726
Joined: Sun Mar 01, 2015 8:09 am
Location: Germany
Contact:

Re: [ANY] Weapon Zoom

Postby Painkiller » Thu Jan 21, 2021 10:07 am

The zoom should not be taken for weapons that has a secondary ability.
User avatar
daren adler
Senior Member
Posts: 348
Joined: Sat May 18, 2019 7:42 pm

Re: [ANY] Weapon Zoom

Postby daren adler » Thu Jan 21, 2021 7:55 pm

You can also change the button to use for zooming, default is ATTACK2 (Right click) You can find available Buttons here: http://wiki.sourcepython.com/developing ... yerButtons

Syntax: Select all

zoom_button = PlayerButtons.ATTACK2

Thought thats what this is for, sorry if i am wrong.
User avatar
Kami
Global Moderator
Posts: 264
Joined: Wed Aug 15, 2012 1:24 am
Location: Germany

Re: [ANY] Weapon Zoom

Postby Kami » Thu Jan 21, 2021 8:48 pm

No you are right you can use zoom for any weapon you want, that's why I linked to the buttons. I need to look into this on the weekend. Not sure if you can set buttons via name directly (like real life name of the button) or if you have to use the PlayerButtons.
User avatar
daren adler
Senior Member
Posts: 348
Joined: Sat May 18, 2019 7:42 pm

Re: [ANY] Weapon Zoom

Postby daren adler » Thu Jan 21, 2021 9:07 pm

Ok. Thank you for reply :grin: :cool:
User avatar
Ayuto
Project Leader
Posts: 2195
Joined: Sat Jul 07, 2012 8:17 am
Location: Germany

Re: [ANY] Weapon Zoom

Postby Ayuto » Fri Jan 22, 2021 6:53 am

Kami wrote:No you are right you can use zoom for any weapon you want, that's why I linked to the buttons. I need to look into this on the weekend. Not sure if you can set buttons via name directly (like real life name of the button) or if you have to use the PlayerButtons.

No, that's not possible. The client doesn't send any keyboard information to the server. It did in the past in CS 1.6, but not anymore with the source engine. Thus, you cannot know whether the client pressed mouse2 or something like that.
User avatar
daren adler
Senior Member
Posts: 348
Joined: Sat May 18, 2019 7:42 pm

Re: [ANY] Weapon Zoom

Postby daren adler » Fri Jan 22, 2021 6:38 pm

Darn :frown: Ok thank you for info :grin: :grin:
User avatar
VinciT
Senior Member
Posts: 331
Joined: Thu Dec 18, 2014 2:41 am

Re: [ANY] Weapon Zoom

Postby VinciT » Fri Jan 22, 2021 7:28 pm

Ayuto wrote:
Kami wrote:No you are right you can use zoom for any weapon you want, that's why I linked to the buttons. I need to look into this on the weekend. Not sure if you can set buttons via name directly (like real life name of the button) or if you have to use the PlayerButtons.

No, that's not possible. The client doesn't send any keyboard information to the server. It did in the past in CS 1.6, but not anymore with the source engine. Thus, you cannot know whether the client pressed mouse2 or something like that.
One way around this would be to create a ClientCommand that the user can bind to any key they want (mouse4 in this case). Although it wouldn't be as intuitive, since it adds another step to the process (binding a command to a key), it would achieve what daren is trying to accomplish.
ImageImageImageImageImage
User avatar
Kami
Global Moderator
Posts: 264
Joined: Wed Aug 15, 2012 1:24 am
Location: Germany

Re: [ANY] Weapon Zoom

Postby Kami » Fri Jan 22, 2021 8:14 pm

That is a great idea, thank you!

I updated the plugin and it now has a clientcommand "do_zoom" which will execute the zoom. You can now do:

Syntax: Select all

zoom_button = None


to disable the use of buttons to rely on the clientcommand alone.

To use the clientcommand you can do:

Code: Select all

bind "mouse4" "do_zoom"


You can ofc use the PlayerButtons and the clientcommand at the same time if you want.
User avatar
L'In20Cible
Project Leader
Posts: 1534
Joined: Sat Jul 14, 2012 9:29 pm
Location: Québec

Re: [ANY] Weapon Zoom

Postby L'In20Cible » Fri Jan 22, 2021 9:39 pm


Without going into details, because I don't currently have time to do so, here are some stuff to consider:

  • You should avoid repeated attribute retrievals. Remember, Python is dynamic and won't do any kind of optimization for you. For example, there is no reason to repeat the following:

    if player.active_weapon != None:
    if player.active_weapon.classname not in zoom_weapons and player.active_weapon.classname not in zoom_exclude:


    Resolve it once, assign it to your current frame and re-use it! For example:

    Syntax: Select all

    weapon = player.active_weapon
    if weapon is None:
    return
    classname = weapon.classname
    if classname not in zoom_weapons and classname not in zoom_exclude:
    return


    Just like that this code is much faster to compute (you could be surprised to time the difference). Same goes for repeated Player, player.userid, etc.

  • Your pressed and in_zoom dictionaries are leaking. They will just grow for every player that connect. Regardless, PlayerDictionary is much more preferable than dictionaries of userid's (they were cool in 2007 :grin: ). Here's a quick example:

    Syntax: Select all

    class MyPlayer(Player):
    def __init__(self, index, caching=True):
    self.pressed = False
    self.in_zoom = False

    players = PlayerDictionary(MyPlayer)

    player = players[index]
    player.pressed = True
    player.active_weapon
    player.whatever
    ...


    Instances are lazy and instantiated only when needed and are automatically cleaned up when they are disconnecting meaning that you don't have any validation to make and can just go straight to the point of retrieving and manipulating players.

  • Rather than the following:

    Syntax: Select all

    @OnPlayerRunCommand
    def on_player_run_command(player, user_cmd):
    if zoom_button != None:


    You should just not register your callback at all:

    Syntax: Select all

    if zoom_button is not None:
    @OnPlayerRunCommand
    def on_player_run_command(player, user_cmd):


    No reason to be called every frame for every player just to exit the call.

  • The zoom_exclude list is redundant. If you wish to exclude a weapon then... well... don't add it to zoom_weapons? :tongue:

Anyways, with all that said, you don't necessarily need to track the pressed/zoom status yourself. The whole thing could be simplified to something like this (untested):

Syntax: Select all

from commands.client import ClientCommand
from listeners import get_button_combination_status
from listeners import ButtonStatus
from listeners import OnButtonStateChanged
from players.constants import PlayerButtons
from players.entity import Player

zoom_button = PlayerButtons.ATTACK2
zoom_level = 30
zoom_weapons = ['weapon_357']

def toggle_zoom(player):
weapon = player.active_weapon
if weapon is None or weapon.classname not in zoom_weapons:
return

player.fov = player.default_fov if player.fov == zoom_level else zoom_level

if zoom_button is not None:
@OnButtonStateChanged
def on_buttons_state_changed(player, old, new):
if get_button_combination_status(old, new, zoom_button) != ButtonStatus.PRESSED:
return

toggle_zoom(player)

@ClientCommand('do_zoom')
def do_zoom(command, index, team_only=False):
toggle_zoom(Player(index))
Last edited by L'In20Cible on Fri Jan 22, 2021 10:34 pm, edited 1 time in total.
rautamiekka
Junior Member
Posts: 11
Joined: Mon Feb 15, 2016 6:53 pm
Location: Ulvila, Finland
Contact:

Re: [ANY] Weapon Zoom

Postby rautamiekka » Fri Jan 22, 2021 10:12 pm

L'In20Cible wrote:

Syntax: Select all

def toggle_zoom(player):
weapon = player.active_weapon
if weapon is None or weapon.classname not in zoom_weapons:
return

player.fov = player.default_fov if player.fov == zoom_level else zoom_level
Hmm, couldn't that be shortened/simplified to

Syntax: Select all

def toggle_zoom(player):
if player.active_weapon.classname not in zoom_weapons:
return

player.fov = player.default_fov if player.fov == zoom_level else zoom_level
since weapon ain't reffed after the if and there won't be None in zoom_weapons ?
User avatar
L'In20Cible
Project Leader
Posts: 1534
Joined: Sat Jul 14, 2012 9:29 pm
Location: Québec

Re: [ANY] Weapon Zoom

Postby L'In20Cible » Fri Jan 22, 2021 10:17 pm

rautamiekka wrote:
L'In20Cible wrote:

Syntax: Select all

def toggle_zoom(player):
weapon = player.active_weapon
if weapon is None or weapon.classname not in zoom_weapons:
return

player.fov = player.default_fov if player.fov == zoom_level else zoom_level
Hmm, couldn't that be shortened/simplified to

Syntax: Select all

def toggle_zoom(player):
if player.active_weapon.classname not in zoom_weapons:
return

player.fov = player.default_fov if player.fov == zoom_level else zoom_level
since weapon ain't reffed after the if and there won't be None in zoom_weapons ?

If the player isn't holding any weapon, this will evaluates as if None.classname not in zoom_weapons: and produces an AttributeError.
rautamiekka
Junior Member
Posts: 11
Joined: Mon Feb 15, 2016 6:53 pm
Location: Ulvila, Finland
Contact:

Re: [ANY] Weapon Zoom

Postby rautamiekka » Fri Jan 22, 2021 10:39 pm

L'In20Cible wrote:If the player isn't holding any weapon, this will evaluates as if None.classname not in zoom_weapons: and produces an AttributeError.

Good point. I didn't even have a clue such behaviour could happen.
User avatar
Kami
Global Moderator
Posts: 264
Joined: Wed Aug 15, 2012 1:24 am
Location: Germany

Re: [ANY] Weapon Zoom

Postby Kami » Sat Jan 23, 2021 12:49 am

Thank you for your feedback! I tried to include some of your tips. My current code is:

Syntax: Select all

# =============================================================================
# >> IMPORTS
# =============================================================================
from commands.client import ClientCommand
from listeners import OnPlayerRunCommand
from players.constants import PlayerButtons
from players.entity import Player

# =============================================================================
# >> CONFIG
# =============================================================================
zoom_button = PlayerButtons.ATTACK2
zoom_level = 30
zoom_weapons = ['weapon_357']
zoom_exclude = ['weapon_crossbow']

# =============================================================================
# >> CLASSES
# =============================================================================
class ZoomPlayer(Player):
def __init__(self, index, caching=True):
super().__init__(index, caching)
self.pressed = False
self.in_zoom = False

def toggle_zoom(self):
weapon = self.active_weapon
if weapon is None or weapon.classname not in zoom_weapons:
return

self.fov = self.default_fov if self.fov == zoom_level else zoom_level

# =============================================================================
# >> COMMANDS
# =============================================================================
@ClientCommand('do_zoom')
def _zoom_client_command(command,index,team_only=False):
player = ZoomPlayer(index)
weapon = player.active_weapon
if weapon is None: return
if weapon.classname in zoom_weapons:
player.toggle_zoom()

# =============================================================================
# >> LISTENERS
# =============================================================================
if zoom_button != None:
@OnPlayerRunCommand
def on_player_run_command(ply, user_cmd):
player = ZoomPlayer(ply.index)
weapon = player.active_weapon
default_pov = player.default_fov
if weapon is None: return
if user_cmd.buttons & zoom_button:
if weapon.classname in zoom_weapons:
if not player.pressed:
if not player.in_zoom:
player.pressed = True
player.fov = zoom_level
player.in_zoom = True
else:
player.fov = default_pov
player.in_zoom = False
player.pressed = True
else:
if player.pressed == True:
player.pressed = False
if weapon.classname not in zoom_weapons and weapon.classname not in zoom_exclude:
player.fov = default_pov
player.in_zoom = False
player.pressed = False


The last part of the code is ment to remove the zoom if you change to a non zoom weapon. That's what zoom_exlude is for. It keeps the weapons that already have a zoom by default (e.g. weapon_crossbow) from beeing reset.
rautamiekka
Junior Member
Posts: 11
Joined: Mon Feb 15, 2016 6:53 pm
Location: Ulvila, Finland
Contact:

Re: [ANY] Weapon Zoom

Postby rautamiekka » Sat Jan 23, 2021 1:04 am

Syntax: Select all

# =============================================================================
# >> LISTENERS
# =============================================================================
if zoom_button != None:
@OnPlayerRunCommand
def on_player_run_command(ply, user_cmd):
player = ZoomPlayer(ply.index)
weapon = player.active_weapon
default_pov = player.default_fov
if weapon == None: return
Always use is when checking for None, False, or True (there's a == True later). I don't remember why though, I think it was something about their internals.
User avatar
L'In20Cible
Project Leader
Posts: 1534
Joined: Sat Jul 14, 2012 9:29 pm
Location: Québec

Re: [ANY] Weapon Zoom

Postby L'In20Cible » Sat Jan 23, 2021 2:57 am

Kami wrote:Thank you for your feedback! I tried to include some of your tips. My current code is:

Syntax: Select all

# =============================================================================
# >> IMPORTS
# =============================================================================
from commands.client import ClientCommand
from listeners import OnPlayerRunCommand
from players.constants import PlayerButtons
from players.entity import Player

# =============================================================================
# >> CONFIG
# =============================================================================
zoom_button = PlayerButtons.ATTACK2
zoom_level = 30
zoom_weapons = ['weapon_357']
zoom_exclude = ['weapon_crossbow']

# =============================================================================
# >> CLASSES
# =============================================================================
class ZoomPlayer(Player):
def __init__(self, index, caching=True):
super().__init__(index, caching)
self.pressed = False
self.in_zoom = False

def toggle_zoom(self):
weapon = self.active_weapon
if weapon is None or weapon.classname not in zoom_weapons:
return

self.fov = self.default_fov if self.fov == zoom_level else zoom_level

# =============================================================================
# >> COMMANDS
# =============================================================================
@ClientCommand('do_zoom')
def _zoom_client_command(command,index,team_only=False):
player = ZoomPlayer(index)
weapon = player.active_weapon
if weapon is None: return
if weapon.classname in zoom_weapons:
player.toggle_zoom()

# =============================================================================
# >> LISTENERS
# =============================================================================
if zoom_button != None:
@OnPlayerRunCommand
def on_player_run_command(ply, user_cmd):
player = ZoomPlayer(ply.index)
weapon = player.active_weapon
default_pov = player.default_fov
if weapon is None: return
if user_cmd.buttons & zoom_button:
if weapon.classname in zoom_weapons:
if not player.pressed:
if not player.in_zoom:
player.pressed = True
player.fov = zoom_level
player.in_zoom = True
else:
player.fov = default_pov
player.in_zoom = False
player.pressed = True
else:
if player.pressed == True:
player.pressed = False
if weapon.classname not in zoom_weapons and weapon.classname not in zoom_exclude:
player.fov = default_pov
player.in_zoom = False
player.pressed = False


The last part of the code is ment to remove the zoom if you change to a non zoom weapon. That's what zoom_exlude is for. It keeps the weapons that already have a zoom by default (e.g. weapon_crossbow) from beeing reset.


Syntax: Select all

from commands.client import ClientCommand
from entities.hooks import EntityCondition
from entities.hooks import EntityPreHook
from listeners import get_button_combination_status
from listeners import ButtonStatus
from listeners import OnButtonStateChanged
from memory import make_object
from players.constants import PlayerButtons
from players.entity import Player
from weapons.entity import Weapon

zoom_button = PlayerButtons.ATTACK2
zoom_level = 30
zoom_weapons = ['weapon_357']

def toggle_zoom(player):
weapon = player.active_weapon
if weapon is None or weapon.classname not in zoom_weapons:
return

player.fov = player.default_fov if player.fov == zoom_level else zoom_level

if zoom_button is not None:
@OnButtonStateChanged
def on_buttons_state_changed(player, old, new):
if get_button_combination_status(old, new, zoom_button) != ButtonStatus.PRESSED:
return

toggle_zoom(player)

@ClientCommand('do_zoom')
def do_zoom(command, index, team_only=False):
toggle_zoom(Player(index))

@EntityPreHook(EntityCondition.is_player, 'weapon_switch')
def pre_weapon_switch(stack_data):
player = make_object(Player, stack_data[0])
player.fov = player.default_fov
User avatar
daren adler
Senior Member
Posts: 348
Joined: Sat May 18, 2019 7:42 pm

Re: [ANY] Weapon Zoom

Postby daren adler » Sat Jan 23, 2021 4:00 pm

Is there one of these i can use? and if so what one do i use?
User avatar
Kami
Global Moderator
Posts: 264
Joined: Wed Aug 15, 2012 1:24 am
Location: Germany

Re: [ANY] Weapon Zoom

Postby Kami » Mon Jan 25, 2021 1:23 pm

Hey daren, I just tested L'In20Cible's version and it works perfectly, so you can use that.

@L'In20Cible: I gotta be honest, I'm not sure what the etiquette is in this kind of situation. Am I supposed to add your code to my github, even though you wrote it? I don't want to be rude but I'm really not sure what to do :D
User avatar
L'In20Cible
Project Leader
Posts: 1534
Joined: Sat Jul 14, 2012 9:29 pm
Location: Québec

Re: [ANY] Weapon Zoom

Postby L'In20Cible » Mon Jan 25, 2021 3:46 pm

Kami wrote:Hey daren, I just tested L'In20Cible's version and it works perfectly, so you can use that.

@L'In20Cible: I gotta be honest, I'm not sure what the etiquette is in this kind of situation. Am I supposed to add your code to my github, even though you wrote it? I don't want to be rude but I'm really not sure what to do :D

If you want to use this code, go for it. I just wanted to share a simplified alternative in an effort to perhaps teach something. You can also make posters of it if you want! It would certainly look good on a wall. :tongue:

Return to “Plugin Releases”

Who is online

Users browsing this forum: No registered users and 6 guests