vh-bombsquad-modded-server-.../dist/ba_data/python/bastd/actor/respawnicon.py
2024-02-20 23:04:51 +05:30

168 lines
5.6 KiB
Python

# Released under the MIT License. See LICENSE for details.
#
"""Implements respawn icon actor."""
from __future__ import annotations
import weakref
from typing import TYPE_CHECKING
import ba
if TYPE_CHECKING:
pass
class RespawnIcon:
"""An icon with a countdown that appears alongside the screen.
category: Gameplay Classes
This is used to indicate that a ba.Player is waiting to respawn.
"""
_MASKTEXSTORENAME = ba.storagename('masktex')
_ICONSSTORENAME = ba.storagename('icons')
def __init__(self, player: ba.Player, respawn_time: float):
"""Instantiate with a ba.Player and respawn_time (in seconds)."""
self._visible = True
on_right, offs_extra, respawn_icons = self._get_context(player)
# Cache our mask tex on the team for easy access.
mask_tex = player.team.customdata.get(self._MASKTEXSTORENAME)
if mask_tex is None:
mask_tex = ba.gettexture('characterIconMask')
player.team.customdata[self._MASKTEXSTORENAME] = mask_tex
assert isinstance(mask_tex, ba.Texture)
# Now find the first unused slot and use that.
index = 0
while (
index in respawn_icons
and respawn_icons[index]() is not None
and respawn_icons[index]().visible
):
index += 1
respawn_icons[index] = weakref.ref(self)
offs = offs_extra + index * -53
icon = player.get_icon()
texture = icon['texture']
h_offs = -10
ipos = (-40 - h_offs if on_right else 40 + h_offs, -180 + offs)
self._image: ba.NodeActor | None = ba.NodeActor(
ba.newnode(
'image',
attrs={
'texture': texture,
'tint_texture': icon['tint_texture'],
'tint_color': icon['tint_color'],
'tint2_color': icon['tint2_color'],
'mask_texture': mask_tex,
'position': ipos,
'scale': (32, 32),
'opacity': 1.0,
'absolute_scale': True,
'attach': 'topRight' if on_right else 'topLeft',
},
)
)
assert self._image.node
ba.animate(self._image.node, 'opacity', {0.0: 0, 0.2: 0.7})
npos = (-40 - h_offs if on_right else 40 + h_offs, -205 + 49 + offs)
self._name: ba.NodeActor | None = ba.NodeActor(
ba.newnode(
'text',
attrs={
'v_attach': 'top',
'h_attach': 'right' if on_right else 'left',
'text': ba.Lstr(value=player.getname()),
'maxwidth': 100,
'h_align': 'center',
'v_align': 'center',
'shadow': 1.0,
'flatness': 1.0,
'color': ba.safecolor(icon['tint_color']),
'scale': 0.5,
'position': npos,
},
)
)
assert self._name.node
ba.animate(self._name.node, 'scale', {0: 0, 0.1: 0.5})
tpos = (-60 - h_offs if on_right else 60 + h_offs, -192 + offs)
self._text: ba.NodeActor | None = ba.NodeActor(
ba.newnode(
'text',
attrs={
'position': tpos,
'h_attach': 'right' if on_right else 'left',
'h_align': 'right' if on_right else 'left',
'scale': 0.9,
'shadow': 0.5,
'flatness': 0.5,
'v_attach': 'top',
'color': ba.safecolor(icon['tint_color']),
'text': '',
},
)
)
assert self._text.node
ba.animate(self._text.node, 'scale', {0: 0, 0.1: 0.9})
self._respawn_time = ba.time() + respawn_time
self._update()
self._timer: ba.Timer | None = ba.Timer(
1.0, ba.WeakCall(self._update), repeat=True
)
@property
def visible(self) -> bool:
"""Is this icon still visible?"""
return self._visible
def _get_context(self, player: ba.Player) -> tuple[bool, float, dict]:
"""Return info on where we should be shown and stored."""
activity = ba.getactivity()
if isinstance(ba.getsession(), ba.DualTeamSession):
on_right = player.team.id % 2 == 1
# Store a list of icons in the team.
icons = player.team.customdata.get(self._ICONSSTORENAME)
if icons is None:
player.team.customdata[self._ICONSSTORENAME] = icons = {}
assert isinstance(icons, dict)
offs_extra = -20
else:
on_right = False
# Store a list of icons in the activity.
icons = activity.customdata.get(self._ICONSSTORENAME)
if icons is None:
activity.customdata[self._ICONSSTORENAME] = icons = {}
assert isinstance(icons, dict)
if isinstance(activity.session, ba.FreeForAllSession):
offs_extra = -150
else:
offs_extra = -20
return on_right, offs_extra, icons
def _update(self) -> None:
remaining = int(round(self._respawn_time - ba.time()))
if remaining > 0:
assert self._text is not None
if self._text.node:
self._text.node.text = str(remaining)
else:
self._visible = False
self._image = self._text = self._timer = self._name = None