[REQUEST]Hide Radar

A place for requesting new Source.Python plugins to be made for your server.

Please request only one plugin per thread.
NosferatuJoe
Junior Member
Posts: 17
Joined: Thu Jan 28, 2021 3:54 pm

[REQUEST]Hide Radar

Postby NosferatuJoe » Thu Jan 28, 2021 4:02 pm

Hey everyone,

So the idea is if it's possible to hide the radar while being in a popup menu.
I came upon this idea when using popup menu's and I noticed that on some servers the radar is clipping over the popup menu making the top of it unreadable. If it were possible to hide the radar while in a popup menu it would make it easier to read the top hehe..

An alternative would be to move the popup menu location a bit lower on the y-axis but I'm pretty sure that's not possible in CSGO, + some players have their hud enlarged or modified so it might still cause an issue.

I just noticed that there is a similar plugin in sourcemod but haven't tried it out yet:
https://forums.alliedmods.net/showthread.php?t=240500

Thanks in advance!

PS: I'm willing to pay for this plugin to be created, price can be discussed in PM. This plugin will be donated to the SP WCS mod, and to the community since it'd be a very useful feature in my opinion.
Last edited by NosferatuJoe on Sun Jan 31, 2021 12:01 pm, edited 3 times in total.
User avatar
satoon101
Project Leader
Posts: 2697
Joined: Sat Jul 07, 2012 1:59 am

Re: Hide Radar (toggleable)

Postby satoon101 » Thu Jan 28, 2021 5:11 pm

For future reference, if you are wanting help creating your own plugin and not having someone create it for you, feel free to use the Plugin Development Support forum.

As for your question, hiding the radar is different in CS:S compared to CS:GO. Here is how it is done in GunGame for each:

https://github.com/GunGame-Dev-Team/Gun ... es/csgo.py

https://github.com/GunGame-Dev-Team/Gun ... cstrike.py

There should be a way to know when a player has a menu open, but I am not sure off the top of my head how best to do that.
Image
User avatar
Ayuto
Project Leader
Posts: 2193
Joined: Sat Jul 07, 2012 8:17 am
Location: Germany

Re: Hide Radar (toggleable)

Postby Ayuto » Sat Jan 30, 2021 10:04 am

Alternativley, you could also add pages to your popup to make it a little bit smaller.
NosferatuJoe
Junior Member
Posts: 17
Joined: Thu Jan 28, 2021 3:54 pm

Re: [REQUEST]Hide Radar

Postby NosferatuJoe » Sun Jan 31, 2021 12:00 pm

Thank you so much for the feedback!
Since I'm not capable of coding stuff like this, I'm willing to pay for this to be created.

If anyone is willing to take on the job, we can discuss pricing in PM.

Thanks in advance!
User avatar
VinciT
Senior Member
Posts: 331
Joined: Thu Dec 18, 2014 2:41 am

Re: [REQUEST]Hide Radar

Postby VinciT » Sun Jan 31, 2021 9:49 pm

Hi Joe, give this a try (should work in both CSS and CSGO):

Syntax: Select all

# ../adaptive_radar/adaptive_radar.py

# Python
from time import time

# Source.Python
from core import GAME_NAME
from cvars import ConVar
from events import Event
from menus import SimpleMenu
from players.constants import HideHudFlags
from players.entity import Player


# How often should we check if the player has a menu open? (in seconds)
TICK_RATE = 0.2


# Because of the way we are hiding the radar in CS:S, we need to keep track
# when the player gets flashed/blinded so they remain flashed for the correct
# duration.
if GAME_NAME == 'cstrike':
@Event('player_blind')
def player_blind(event):
"""Called when a player gets flashed/blinded."""
player = PlayerAR.from_userid(event['userid'])
player.got_flashed(player.flash_duration * 0.95)


@Event('player_spawn')
def player_spawn(event):
"""Called when a player spawns."""
player = PlayerAR.from_userid(event['userid'])
# Start looping the '_hide_radar_think()' function.
player.hide_radar_think.start(interval=TICK_RATE)


class PlayerAR(Player):
"""Extended Player class.

Args:
index (int): A valid player index.
caching (bool): Check for a cached instance?

Attributes:
flashed_delay (Delay): Instance of Delay() used to keep track of how
long the player is flashed for.
is_flashed (bool): Is the player currently flashed/blind?
hidden_radar (bool): Is the radar hidden for this player?
hide_radar_think (Repeat): Instance of Repeat() used to loop the
`_hide_radar_think()` function.
"""
# Convars responsible for giving money to the player.
cash_cvars = (ConVar('mp_playercashawards'), ConVar('mp_teamcashawards'))

def __init__(self, index, caching=True):
"""Initializes the object."""
super().__init__(index, caching)

self.flashed_delay = None
self.is_flashed = False
self.hidden_radar = False
self.hide_radar_think = self.repeat(self._hide_radar_think)

def got_flashed(self, duration):
"""Keeps track of how long the player has been flashed for."""
try:
already_running = self.flashed_delay.running
except AttributeError:
# Missing Delay instance, default to False.
already_running = False

# Check if there's already a Delay instance that hasn't been called.
# (in case the player got flashed multiple times in a short timespan)
if already_running:
# Push the delay to be called a bit later.
self.flashed_delay.exec_time = time() + duration
else:
self.is_flashed = True
self.flashed_delay = self.delay(
duration, self.reset_flashed_status)

def reset_flashed_status(self):
"""Sets 'is_flashed' and 'hidden_radar' to False."""
# The player can see again.
self.is_flashed = False
# The radar will show itself after the actual flash/blind wears off,
# reset the 'hidden_radar' attribute so the loop hides the player's
# radar if needed.
self.hidden_radar = False

def _hide_radar_css(self):
if not self.is_flashed:
self.flash_alpha = 0
self.flash_duration = time()

def _hide_radar_csgo(self):
self.hidden_huds |= HideHudFlags.RADAR

# Trick the player into thinking money is disabled on the server, as a
# result, the money/cash HUD element will disappear.
for convar in PlayerAR.cash_cvars:
self.send_convar_value(convar.name, 0)

# Use the correct function to hide the radar based on the game.
hide_radar = _hide_radar_csgo if GAME_NAME == 'csgo' else _hide_radar_css

def _show_radar_css(self):
if not self.is_flashed:
self.flash_duration = 0.001

def _show_radar_csgo(self):
self.hidden_huds &= ~HideHudFlags.RADAR

# Restore the cash convars back to normal.
for convar in PlayerAR.cash_cvars:
self.send_convar_value(convar.name, convar.get_int())

# Use the correct function to show the radar based on the game.
show_radar = _show_radar_csgo if GAME_NAME == 'csgo' else _show_radar_css

def _hide_radar_think(self):
# Let's see if there is an active menu for this player.
active_menu = SimpleMenu.get_user_queue(self.index).active_menu

# Does the player have a menu open and is their radar visible?
if active_menu and not self.hidden_radar:
self.hide_radar()
self.hidden_radar = True
# Or does the player not have any menus open and is their radar hidden?
elif not active_menu and self.hidden_radar:
self.show_radar()
self.hidden_radar = False
Gotta give thanks to satoon for the radar hiding code.
I feel iffy about using _radio_queues to check if the player has any menus open, is there a better/cleaner way to get this info?
Last edited by VinciT on Mon Feb 01, 2021 5:20 am, edited 1 time in total.
ImageImageImageImageImage
User avatar
Kami
Global Moderator
Posts: 263
Joined: Wed Aug 15, 2012 1:24 am
Location: Germany

Re: [REQUEST]Hide Radar

Postby Kami » Sun Jan 31, 2021 10:06 pm

You could use

Syntax: Select all

SimpleMenu.get_user_queue(player.index).active_menu


This will give you any active menu, no matter if SimpleMenu, PagedMenu or ListMenu.
NosferatuJoe
Junior Member
Posts: 17
Joined: Thu Jan 28, 2021 3:54 pm

Re: [REQUEST]Hide Radar

Postby NosferatuJoe » Sun Jan 31, 2021 10:36 pm

Wow I didn't expect it to work right away, thank you so much!

The only feedback I could give is that it sadly doesn't hide the bomb & $$ info, as seen on the screenshot below:

Image
https://imgur.com/a/QIaXKri

But nevertheless I'm quite thrilled about this feature and will hold my word. Can I PM you?
User avatar
VinciT
Senior Member
Posts: 331
Joined: Thu Dec 18, 2014 2:41 am

Re: [REQUEST]Hide Radar

Postby VinciT » Mon Feb 01, 2021 5:38 am

Kami wrote:

Syntax: Select all

SimpleMenu.get_user_queue(player.index).active_menu
Thank you Kami, this is exactly what I was looking for. :grin:

No problem Joe, I'm glad it's working as expected. I've updated the plugin with a method to hide the player's money/buyzone icon, but I haven't figured out how to hide the hostage and bomb icons yet. A dirty way to get rid of the bomb icon would be to make the player drop the bomb whenever they have an active menu, but this has too many drawbacks - so we need to find a way to fake it.

NosferatuJoe wrote:But nevertheless I'm quite thrilled about this feature and will hold my word. Can I PM you?
Sure thing! :smile:
ImageImageImageImageImage
User avatar
L'In20Cible
Project Leader
Posts: 1533
Joined: Sat Jul 14, 2012 9:29 pm
Location: Québec

Re: [REQUEST]Hide Radar

Postby L'In20Cible » Mon Feb 01, 2021 6:52 am

VinciT wrote:I feel iffy about using _radio_queues to check if the player has any menus open, is there a better/cleaner way to get this info?
A hook on the ShowMenu usermessage would definitely be the best option. Not only it seems like an overall better approach to me than a constant lookup through repeats, it also has the merit of also detecting menus sent by SM, etc.
User avatar
VinciT
Senior Member
Posts: 331
Joined: Thu Dec 18, 2014 2:41 am

Re: [REQUEST]Hide Radar

Postby VinciT » Mon Feb 01, 2021 7:22 am

L'In20Cible wrote:A hook on the ShowMenu usermessage would definitely be the best option. Not only it seems like an overall better approach to me than a constant lookup through repeats, it also has the merit of also detecting menus sent by SM, etc.
That was my initial idea, but I was greeted by this:

Syntax: Select all

# ../showmenu_hook/showmenu_hook.py

# Source.Python
from messages.hooks import HookUserMessage


@HookUserMessage('ShowMenu')
def showmenu_pre(recpient, message_data):
print(message_data)

Code: Select all

[SP] Caught an Exception:
Traceback (most recent call last):
  File "..\addons\source-python\packages\source-python\messages\impl.py", line 242, in get_user_message_impl
    return implemented_usermessages[msg_index]
KeyError: 54

During handling of the above exception, another exception occurred:
Traceback (most recent call last):
  File "..\addons\source-python\packages\source-python\plugins\command.py", line 164, in load_plugin
    plugin = self.manager.load(plugin_name)
  File "..\addons\source-python\packages\source-python\plugins\manager.py", line 207, in load
    plugin._load()
  File "..\addons\source-python\packages\source-python\plugins\instance.py", line 74, in _load
    self.module = import_module(self.import_name)
  File "..\addons\source-python\plugins\showmenu_hook\showmenu_hook.py", line 7, in <module>
    @HookUserMessage('ShowMenu')
  File "..\addons\source-python\packages\source-python\messages\hooks.py", line 158, in __init__
    self.impl = get_user_message_impl(self.message_index)
  File "..\addons\source-python\packages\source-python\messages\impl.py", line 245, in get_user_message_impl
    f'User message with index {msg_index} is not implemented.')

NotImplementedError: User message with index 54 is not implemented.

:frown:
ImageImageImageImageImage
User avatar
L'In20Cible
Project Leader
Posts: 1533
Joined: Sat Jul 14, 2012 9:29 pm
Location: Québec

Re: [REQUEST]Hide Radar

Postby L'In20Cible » Mon Feb 01, 2021 7:28 am

VinciT wrote:
L'In20Cible wrote:A hook on the ShowMenu usermessage would definitely be the best option. Not only it seems like an overall better approach to me than a constant lookup through repeats, it also has the merit of also detecting menus sent by SM, etc.
That was my initial idea, but I was greeted by this:

Syntax: Select all

# ../showmenu_hook/showmenu_hook.py

# Source.Python
from messages.hooks import HookUserMessage


@HookUserMessage('ShowMenu')
def showmenu_pre(recpient, message_data):
print(message_data)

Code: Select all

[SP] Caught an Exception:
Traceback (most recent call last):
  File "..\addons\source-python\packages\source-python\messages\impl.py", line 242, in get_user_message_impl
    return implemented_usermessages[msg_index]
KeyError: 54

During handling of the above exception, another exception occurred:
Traceback (most recent call last):
  File "..\addons\source-python\packages\source-python\plugins\command.py", line 164, in load_plugin
    plugin = self.manager.load(plugin_name)
  File "..\addons\source-python\packages\source-python\plugins\manager.py", line 207, in load
    plugin._load()
  File "..\addons\source-python\packages\source-python\plugins\instance.py", line 74, in _load
    self.module = import_module(self.import_name)
  File "..\addons\source-python\plugins\showmenu_hook\showmenu_hook.py", line 7, in <module>
    @HookUserMessage('ShowMenu')
  File "..\addons\source-python\packages\source-python\messages\hooks.py", line 158, in __init__
    self.impl = get_user_message_impl(self.message_index)
  File "..\addons\source-python\packages\source-python\messages\impl.py", line 245, in get_user_message_impl
    f'User message with index {msg_index} is not implemented.')

NotImplementedError: User message with index 54 is not implemented.

:frown:


You can't use HookUserMessage because there is no implementation class for that message (feel free to PR one!) but you can hook it up directly with something like that (untested):

Syntax: Select all

from messages.hooks import HookProtobufUserMessage

@HookProtobufUserMessage('ShowMenu')
def pre_show_menu(recipients, buffer):
display_time = buffer.get_int32('display_time')
Not sure if that affects CS:GO as well, but I remember vaguely CS:S having a client-side limit of 4 seconds (the time a default radio menu automatically closes) I believe it was so you may have to clamp it if it goes higher.
User avatar
VinciT
Senior Member
Posts: 331
Joined: Thu Dec 18, 2014 2:41 am

Re: [REQUEST]Hide Radar

Postby VinciT » Mon Feb 01, 2021 7:40 am

Awesome, it works! I'll redo the plugin tomorrow when I wake up to use the hook instead of the repeater. I'll attempt to implement the ShowMenuImpl class as well. Thank you so much L'In20Cible.
ImageImageImageImageImage
User avatar
VinciT
Senior Member
Posts: 331
Joined: Thu Dec 18, 2014 2:41 am

Re: [REQUEST]Hide Radar

Postby VinciT » Wed Feb 03, 2021 9:03 am

Alright, I've reworked the plugin to use the UserMessage hooks:

Syntax: Select all

# ../adaptive_radar/adaptive_radar.py

# Python
from time import time

# Source.Python
from commands.client import ClientCommand
from core import GAME_NAME
from cvars import ConVar
from entities.hooks import EntityCondition, EntityPreHook
from listeners.tick import RepeatStatus
from menus import SimpleMenu
from messages.hooks import HookBitBufferUserMessage, HookProtobufUserMessage
from players.constants import HideHudFlags
from players.entity import Player


# Seconds until the radar reappears after the player closes their menu.
SHOW_DELAY = 0.25

# Seconds until the menu times out and closes on the client-side.
MENU_TIMEOUT_DELAY = 4

# Duration of the invisible flash/blind that we'll be using to hide the radar
# in Counter-Strike: Source.
FLASH_DURATION = 6000


class _PlayerCSS(Player):
"""Extended Player class for Counter-Strike: Source.

Args:
index (int): A valid player index.
caching (bool): Check for a cached instance?

Attributes:
flashed_delay (Delay): Instance of Delay() used to keep track of how
long the player is flashed for.
is_flashed (bool): Is the player currently flashed/blind?
hide_radar_think (Repeat): Instance of Repeat() used to loop the
`_hide_radar_think()` function.
"""

def __init__(self, index, caching=True):
"""Initializes the object."""
super().__init__(index, caching)

self.is_flashed = False
self.flashed_delay = None
self.hide_radar_think = self.repeat(self._hide_radar_think)

def on_flashed(self, duration):
"""Keeps track of how long the player has been flashed for.

Args:
duration (float): Time until the player can see clearly again.
"""
flashed_delay = self.flashed_delay

try:
already_running = flashed_delay.running
except AttributeError:
# Missing Delay instance, default to False.
already_running = False

# Check if there's already a Delay instance that hasn't been called.
# (in case the player got flashed multiple times in a short timespan)
if already_running:
# Push the delay to be called a bit later.
flashed_delay.exec_time = time() + duration
else:
self.is_flashed = True
self.flashed_delay = self.delay(
duration, self.reset_flashed_status)

def reset_flashed_status(self):
"""Called when the player can see clearly again."""
# The player can see again.
self.is_flashed = False

# Should the radar still be hidden?
if self.hide_radar_think.status == RepeatStatus.RUNNING:
self._hide_radar_think()

def hide_radar(self):
"""Hides the player's radar."""
self.hide_radar_think.start(interval=0.5, execute_on_start=True)

def _hide_radar_think(self):
if not self.is_flashed:
self.flash_alpha = 0
self.flash_duration = FLASH_DURATION

def show_radar(self):
"""Shows the player's radar."""
# Stop the loop.
self.hide_radar_think.stop()

# Can the player see clearly?
if not self.is_flashed:
# Show the radar after the specified delay.
self.flash_duration = SHOW_DELAY


class _PlayerCSGO(Player):
"""Extended Player class for Counter-Strike: Global Offensive.

Args:
index (int): A valid player index.
caching (bool): Check for a cached instance?

Attributes:
timeout_delay (Delay): Instance of Delay() used show the radar in case
the menu closed automatically on the client-side.
show_delay (Delay): Instance of Delay() used to show the radar after
the player closes their menu.
"""
# Convars responsible for giving money to the player.
cash_cvars = (ConVar('mp_playercashawards'), ConVar('mp_teamcashawards'))

def __init__(self, index, caching=True):
"""Initializes the object."""
super().__init__(index, caching)

self.timeout_delay = None
self.show_delay = None

def hide_radar(self):
"""Hides the player's radar."""
timeout_delay = self.timeout_delay

try:
already_running = timeout_delay.running
except AttributeError:
already_running = False

if already_running:
timeout_delay.exec_time = time() + MENU_TIMEOUT_DELAY
else:
try:
# If the player recently closed their last menu, make sure to
# prevent the radar from showing up.
self.show_delay.cancel()
except (AttributeError, ValueError):
pass

self.hidden_huds |= HideHudFlags.RADAR
# Trick the player into thinking money is disabled on the server,
# as a result, the money/cash HUD element will disappear.
for convar in PlayerAR.cash_cvars:
self.send_convar_value(convar.name, 0)

self.timeout_delay = self.delay(
MENU_TIMEOUT_DELAY, self.show_radar)

def show_radar(self):
"""Shows the player's radar, money, and buyzone icon."""
try:
# Stop the timeout delay, if there is one.
self.timeout_delay.cancel()
except (ValueError, AttributeError):
pass

self.show_delay = self.delay(SHOW_DELAY, self._show_radar)

def _show_radar(self):
self.hidden_huds &= ~HideHudFlags.RADAR

# Restore the cash convars back to normal.
for convar in PlayerAR.cash_cvars:
self.send_convar_value(convar.name, convar.get_int())


# Is the plugin running on a Counter-Strike: Source server?
if GAME_NAME == 'cstrike':
PlayerAR = _PlayerCSS

@EntityPreHook(EntityCondition.is_human_player, 'blind')
def blind_pre(stack_data):
"""Called when the player gets flashed/blinded."""
player = PlayerAR._obj(stack_data[0])
# Calculate the duration of the flash.
duration = stack_data[2] / 1.4

# Did the duration of the flash get overridden somehow?
if player.flash_duration >= FLASH_DURATION:
# Use the correct duration.
player.flash_duration = duration

# Use 99% of the actual duration to prevent the radar from flickering.
player.on_flashed(duration * 0.99)

@HookBitBufferUserMessage('ShowMenu')
def show_menu_pre(recipients, buffer_read, buffer_write):
"""Called when a ShowMenu user message gets sent."""
_valid_slots = buffer_read.read_word()
_display_time = buffer_read.read_char()
chunked = buffer_read.read_byte()

# Is this the last piece/chunk of this ShowMenu user message?
if not chunked:
for index in recipients:
player = PlayerAR(index)

if player.is_bot():
continue

player.hide_radar()

# Or is it on a Counter-Strike: Global Offensive server?
elif GAME_NAME == 'csgo':
PlayerAR = _PlayerCSGO

@HookProtobufUserMessage('ShowMenu')
def show_menu_pre(recipients, buffer):
"""Called when a ShowMenu user message gets sent."""
for index in recipients:
player = PlayerAR(index)

if player.is_bot():
continue

player.hide_radar()


@ClientCommand('menuselect')
def menu_select(command, index):
"""Called when the player selects an option in the menu."""
# Did the player close their menu?
if SimpleMenu.get_user_queue(index).active_menu is None:
PlayerAR(index).show_radar()
Last edited by VinciT on Mon Apr 26, 2021 6:55 pm, edited 1 time in total.
ImageImageImageImageImage
NosferatuJoe
Junior Member
Posts: 17
Joined: Thu Jan 28, 2021 3:54 pm

Re: [REQUEST]Hide Radar

Postby NosferatuJoe » Fri Feb 05, 2021 1:49 pm

Thanks a lot for all the effort, I really appreciate it. I'm gonna test the plugin right away!
NosferatuJoe
Junior Member
Posts: 17
Joined: Thu Jan 28, 2021 3:54 pm

Re: [REQUEST]Hide Radar

Postby NosferatuJoe » Tue Feb 09, 2021 10:44 am

I just tested the plugin and it works flawless. Thank you so much for all the effort!!

It's a great feature for mods that use menus.
User avatar
VinciT
Senior Member
Posts: 331
Joined: Thu Dec 18, 2014 2:41 am

Re: [REQUEST]Hide Radar

Postby VinciT » Sat Feb 13, 2021 3:49 pm

Awesome! I'm glad it's working as expected. :smile:
ImageImageImageImageImage
NosferatuJoe
Junior Member
Posts: 17
Joined: Thu Jan 28, 2021 3:54 pm

Re: [REQUEST]Hide Radar

Postby NosferatuJoe » Tue Feb 16, 2021 1:03 pm

VinciT wrote:Awesome! I'm glad it's working as expected. :smile:

Wish I could give you + reputation or some sorts. Sadly there is no such option :p
NosferatuJoe
Junior Member
Posts: 17
Joined: Thu Jan 28, 2021 3:54 pm

Re: [REQUEST]Hide Radar

Postby NosferatuJoe » Fri Mar 26, 2021 11:01 pm

Hey VinciT, I can proudly say that your plugin has been used on a live server with 20+ players today. Unfortunately we encountered an error with the plugin where's the menu would occassionally just dissapear. I'm not sure if I can replicate it though but it happened to everyone on the server.

I also got an exception that might be related to this but I'm not entirely sure:

Code: Select all

2021-03-26 19:48:01 - sp   -   EXCEPTION   
[SP] Caught an Exception:
Traceback (most recent call last):
  File "../addons/source-python/packages/source-python/commands/auth.py", line 44, in __call__
    return self.callback(*args)
  File "../addons/source-python/packages/source-python/menus/queue.py", line 267, in _menuselect_callback
    _radio_queues[index]._select(choice)
  File "../addons/source-python/packages/source-python/menus/queue.py", line 126, in _select
    next_menu = active_menu._select(self._index, choice)
  File "../addons/source-python/packages/source-python/menus/radio.py", line 113, in _select
    self._player_pages[player_index].options[choice_index])

KeyError: 1


I've also reported this on the SP github: https://github.com/Source-Python-Dev-Te ... issues/390

Besides that, I like the plugin and would still want to use it in the future. Atm it's just difficult to keep it enabled since a lot people had that occassional issue.
User avatar
VinciT
Senior Member
Posts: 331
Joined: Thu Dec 18, 2014 2:41 am

Re: [REQUEST]Hide Radar

Postby VinciT » Mon Mar 29, 2021 3:39 am

I'm not sure what could have caused this. Are you running both SP and SM? And could you PM me with a list of plugins that you're running which utilize menus?
ImageImageImageImageImage
NosferatuJoe
Junior Member
Posts: 17
Joined: Thu Jan 28, 2021 3:54 pm

Re: [REQUEST]Hide Radar

Postby NosferatuJoe » Tue Apr 06, 2021 5:35 pm

Hey VinciT, I do run both SP, SM and Ayuto's eventscripts emulator. I'll try to get all of the plugins that use menu's

Return to “Plugin Requests”

Who is online

Users browsing this forum: No registered users and 20 guests