bastd.actor.respawnicon
Implements respawn icon actor.
1# Released under the MIT License. See LICENSE for details. 2# 3"""Implements respawn icon actor.""" 4 5from __future__ import annotations 6 7import weakref 8from typing import TYPE_CHECKING 9 10import ba 11 12if TYPE_CHECKING: 13 pass 14 15 16class RespawnIcon: 17 """An icon with a countdown that appears alongside the screen. 18 19 category: Gameplay Classes 20 21 This is used to indicate that a ba.Player is waiting to respawn. 22 """ 23 24 _MASKTEXSTORENAME = ba.storagename('masktex') 25 _ICONSSTORENAME = ba.storagename('icons') 26 27 def __init__(self, player: ba.Player, respawn_time: float): 28 """Instantiate with a ba.Player and respawn_time (in seconds).""" 29 self._visible = True 30 31 on_right, offs_extra, respawn_icons = self._get_context(player) 32 33 # Cache our mask tex on the team for easy access. 34 mask_tex = player.team.customdata.get(self._MASKTEXSTORENAME) 35 if mask_tex is None: 36 mask_tex = ba.gettexture('characterIconMask') 37 player.team.customdata[self._MASKTEXSTORENAME] = mask_tex 38 assert isinstance(mask_tex, ba.Texture) 39 40 # Now find the first unused slot and use that. 41 index = 0 42 while (index in respawn_icons and respawn_icons[index]() is not None 43 and respawn_icons[index]().visible): 44 index += 1 45 respawn_icons[index] = weakref.ref(self) 46 47 offs = offs_extra + index * -53 48 icon = player.get_icon() 49 texture = icon['texture'] 50 h_offs = -10 51 ipos = (-40 - h_offs if on_right else 40 + h_offs, -180 + offs) 52 self._image: ba.NodeActor | None = ba.NodeActor( 53 ba.newnode('image', 54 attrs={ 55 'texture': texture, 56 'tint_texture': icon['tint_texture'], 57 'tint_color': icon['tint_color'], 58 'tint2_color': icon['tint2_color'], 59 'mask_texture': mask_tex, 60 'position': ipos, 61 'scale': (32, 32), 62 'opacity': 1.0, 63 'absolute_scale': True, 64 'attach': 'topRight' if on_right else 'topLeft' 65 })) 66 67 assert self._image.node 68 ba.animate(self._image.node, 'opacity', {0.0: 0, 0.2: 0.7}) 69 70 npos = (-40 - h_offs if on_right else 40 + h_offs, -205 + 49 + offs) 71 self._name: ba.NodeActor | None = ba.NodeActor( 72 ba.newnode('text', 73 attrs={ 74 'v_attach': 'top', 75 'h_attach': 'right' if on_right else 'left', 76 'text': ba.Lstr(value=player.getname()), 77 'maxwidth': 100, 78 'h_align': 'center', 79 'v_align': 'center', 80 'shadow': 1.0, 81 'flatness': 1.0, 82 'color': ba.safecolor(icon['tint_color']), 83 'scale': 0.5, 84 'position': npos 85 })) 86 87 assert self._name.node 88 ba.animate(self._name.node, 'scale', {0: 0, 0.1: 0.5}) 89 90 tpos = (-60 - h_offs if on_right else 60 + h_offs, -192 + offs) 91 self._text: ba.NodeActor | None = ba.NodeActor( 92 ba.newnode('text', 93 attrs={ 94 'position': tpos, 95 'h_attach': 'right' if on_right else 'left', 96 'h_align': 'right' if on_right else 'left', 97 'scale': 0.9, 98 'shadow': 0.5, 99 'flatness': 0.5, 100 'v_attach': 'top', 101 'color': ba.safecolor(icon['tint_color']), 102 'text': '' 103 })) 104 105 assert self._text.node 106 ba.animate(self._text.node, 'scale', {0: 0, 0.1: 0.9}) 107 108 self._respawn_time = ba.time() + respawn_time 109 self._update() 110 self._timer: ba.Timer | None = ba.Timer(1.0, 111 ba.WeakCall(self._update), 112 repeat=True) 113 114 @property 115 def visible(self) -> bool: 116 """Is this icon still visible?""" 117 return self._visible 118 119 def _get_context(self, player: ba.Player) -> tuple[bool, float, dict]: 120 """Return info on where we should be shown and stored.""" 121 activity = ba.getactivity() 122 123 if isinstance(ba.getsession(), ba.DualTeamSession): 124 on_right = player.team.id % 2 == 1 125 126 # Store a list of icons in the team. 127 icons = player.team.customdata.get(self._ICONSSTORENAME) 128 if icons is None: 129 player.team.customdata[self._ICONSSTORENAME] = icons = {} 130 assert isinstance(icons, dict) 131 132 offs_extra = -20 133 else: 134 on_right = False 135 136 # Store a list of icons in the activity. 137 icons = activity.customdata.get(self._ICONSSTORENAME) 138 if icons is None: 139 activity.customdata[self._ICONSSTORENAME] = icons = {} 140 assert isinstance(icons, dict) 141 142 if isinstance(activity.session, ba.FreeForAllSession): 143 offs_extra = -150 144 else: 145 offs_extra = -20 146 return on_right, offs_extra, icons 147 148 def _update(self) -> None: 149 remaining = int(round(self._respawn_time - ba.time())) 150 if remaining > 0: 151 assert self._text is not None 152 if self._text.node: 153 self._text.node.text = str(remaining) 154 else: 155 self._visible = False 156 self._image = self._text = self._timer = self._name = None
class
RespawnIcon:
17class RespawnIcon: 18 """An icon with a countdown that appears alongside the screen. 19 20 category: Gameplay Classes 21 22 This is used to indicate that a ba.Player is waiting to respawn. 23 """ 24 25 _MASKTEXSTORENAME = ba.storagename('masktex') 26 _ICONSSTORENAME = ba.storagename('icons') 27 28 def __init__(self, player: ba.Player, respawn_time: float): 29 """Instantiate with a ba.Player and respawn_time (in seconds).""" 30 self._visible = True 31 32 on_right, offs_extra, respawn_icons = self._get_context(player) 33 34 # Cache our mask tex on the team for easy access. 35 mask_tex = player.team.customdata.get(self._MASKTEXSTORENAME) 36 if mask_tex is None: 37 mask_tex = ba.gettexture('characterIconMask') 38 player.team.customdata[self._MASKTEXSTORENAME] = mask_tex 39 assert isinstance(mask_tex, ba.Texture) 40 41 # Now find the first unused slot and use that. 42 index = 0 43 while (index in respawn_icons and respawn_icons[index]() is not None 44 and respawn_icons[index]().visible): 45 index += 1 46 respawn_icons[index] = weakref.ref(self) 47 48 offs = offs_extra + index * -53 49 icon = player.get_icon() 50 texture = icon['texture'] 51 h_offs = -10 52 ipos = (-40 - h_offs if on_right else 40 + h_offs, -180 + offs) 53 self._image: ba.NodeActor | None = ba.NodeActor( 54 ba.newnode('image', 55 attrs={ 56 'texture': texture, 57 'tint_texture': icon['tint_texture'], 58 'tint_color': icon['tint_color'], 59 'tint2_color': icon['tint2_color'], 60 'mask_texture': mask_tex, 61 'position': ipos, 62 'scale': (32, 32), 63 'opacity': 1.0, 64 'absolute_scale': True, 65 'attach': 'topRight' if on_right else 'topLeft' 66 })) 67 68 assert self._image.node 69 ba.animate(self._image.node, 'opacity', {0.0: 0, 0.2: 0.7}) 70 71 npos = (-40 - h_offs if on_right else 40 + h_offs, -205 + 49 + offs) 72 self._name: ba.NodeActor | None = ba.NodeActor( 73 ba.newnode('text', 74 attrs={ 75 'v_attach': 'top', 76 'h_attach': 'right' if on_right else 'left', 77 'text': ba.Lstr(value=player.getname()), 78 'maxwidth': 100, 79 'h_align': 'center', 80 'v_align': 'center', 81 'shadow': 1.0, 82 'flatness': 1.0, 83 'color': ba.safecolor(icon['tint_color']), 84 'scale': 0.5, 85 'position': npos 86 })) 87 88 assert self._name.node 89 ba.animate(self._name.node, 'scale', {0: 0, 0.1: 0.5}) 90 91 tpos = (-60 - h_offs if on_right else 60 + h_offs, -192 + offs) 92 self._text: ba.NodeActor | None = ba.NodeActor( 93 ba.newnode('text', 94 attrs={ 95 'position': tpos, 96 'h_attach': 'right' if on_right else 'left', 97 'h_align': 'right' if on_right else 'left', 98 'scale': 0.9, 99 'shadow': 0.5, 100 'flatness': 0.5, 101 'v_attach': 'top', 102 'color': ba.safecolor(icon['tint_color']), 103 'text': '' 104 })) 105 106 assert self._text.node 107 ba.animate(self._text.node, 'scale', {0: 0, 0.1: 0.9}) 108 109 self._respawn_time = ba.time() + respawn_time 110 self._update() 111 self._timer: ba.Timer | None = ba.Timer(1.0, 112 ba.WeakCall(self._update), 113 repeat=True) 114 115 @property 116 def visible(self) -> bool: 117 """Is this icon still visible?""" 118 return self._visible 119 120 def _get_context(self, player: ba.Player) -> tuple[bool, float, dict]: 121 """Return info on where we should be shown and stored.""" 122 activity = ba.getactivity() 123 124 if isinstance(ba.getsession(), ba.DualTeamSession): 125 on_right = player.team.id % 2 == 1 126 127 # Store a list of icons in the team. 128 icons = player.team.customdata.get(self._ICONSSTORENAME) 129 if icons is None: 130 player.team.customdata[self._ICONSSTORENAME] = icons = {} 131 assert isinstance(icons, dict) 132 133 offs_extra = -20 134 else: 135 on_right = False 136 137 # Store a list of icons in the activity. 138 icons = activity.customdata.get(self._ICONSSTORENAME) 139 if icons is None: 140 activity.customdata[self._ICONSSTORENAME] = icons = {} 141 assert isinstance(icons, dict) 142 143 if isinstance(activity.session, ba.FreeForAllSession): 144 offs_extra = -150 145 else: 146 offs_extra = -20 147 return on_right, offs_extra, icons 148 149 def _update(self) -> None: 150 remaining = int(round(self._respawn_time - ba.time())) 151 if remaining > 0: 152 assert self._text is not None 153 if self._text.node: 154 self._text.node.text = str(remaining) 155 else: 156 self._visible = False 157 self._image = self._text = self._timer = self._name = None
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.
RespawnIcon(player: ba._player.Player, respawn_time: float)
28 def __init__(self, player: ba.Player, respawn_time: float): 29 """Instantiate with a ba.Player and respawn_time (in seconds).""" 30 self._visible = True 31 32 on_right, offs_extra, respawn_icons = self._get_context(player) 33 34 # Cache our mask tex on the team for easy access. 35 mask_tex = player.team.customdata.get(self._MASKTEXSTORENAME) 36 if mask_tex is None: 37 mask_tex = ba.gettexture('characterIconMask') 38 player.team.customdata[self._MASKTEXSTORENAME] = mask_tex 39 assert isinstance(mask_tex, ba.Texture) 40 41 # Now find the first unused slot and use that. 42 index = 0 43 while (index in respawn_icons and respawn_icons[index]() is not None 44 and respawn_icons[index]().visible): 45 index += 1 46 respawn_icons[index] = weakref.ref(self) 47 48 offs = offs_extra + index * -53 49 icon = player.get_icon() 50 texture = icon['texture'] 51 h_offs = -10 52 ipos = (-40 - h_offs if on_right else 40 + h_offs, -180 + offs) 53 self._image: ba.NodeActor | None = ba.NodeActor( 54 ba.newnode('image', 55 attrs={ 56 'texture': texture, 57 'tint_texture': icon['tint_texture'], 58 'tint_color': icon['tint_color'], 59 'tint2_color': icon['tint2_color'], 60 'mask_texture': mask_tex, 61 'position': ipos, 62 'scale': (32, 32), 63 'opacity': 1.0, 64 'absolute_scale': True, 65 'attach': 'topRight' if on_right else 'topLeft' 66 })) 67 68 assert self._image.node 69 ba.animate(self._image.node, 'opacity', {0.0: 0, 0.2: 0.7}) 70 71 npos = (-40 - h_offs if on_right else 40 + h_offs, -205 + 49 + offs) 72 self._name: ba.NodeActor | None = ba.NodeActor( 73 ba.newnode('text', 74 attrs={ 75 'v_attach': 'top', 76 'h_attach': 'right' if on_right else 'left', 77 'text': ba.Lstr(value=player.getname()), 78 'maxwidth': 100, 79 'h_align': 'center', 80 'v_align': 'center', 81 'shadow': 1.0, 82 'flatness': 1.0, 83 'color': ba.safecolor(icon['tint_color']), 84 'scale': 0.5, 85 'position': npos 86 })) 87 88 assert self._name.node 89 ba.animate(self._name.node, 'scale', {0: 0, 0.1: 0.5}) 90 91 tpos = (-60 - h_offs if on_right else 60 + h_offs, -192 + offs) 92 self._text: ba.NodeActor | None = ba.NodeActor( 93 ba.newnode('text', 94 attrs={ 95 'position': tpos, 96 'h_attach': 'right' if on_right else 'left', 97 'h_align': 'right' if on_right else 'left', 98 'scale': 0.9, 99 'shadow': 0.5, 100 'flatness': 0.5, 101 'v_attach': 'top', 102 'color': ba.safecolor(icon['tint_color']), 103 'text': '' 104 })) 105 106 assert self._text.node 107 ba.animate(self._text.node, 'scale', {0: 0, 0.1: 0.9}) 108 109 self._respawn_time = ba.time() + respawn_time 110 self._update() 111 self._timer: ba.Timer | None = ba.Timer(1.0, 112 ba.WeakCall(self._update), 113 repeat=True)
Instantiate with a ba.Player and respawn_time (in seconds).