mirror of
https://github.com/RYDE-WORK/ballistica.git
synced 2026-01-27 01:13:13 +08:00
Cleaning up factory classes
This commit is contained in:
parent
c5b0d977e3
commit
bc22359dcd
@ -34,10 +34,6 @@ from bastd.gameutils import SharedObjects
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, Sequence, Optional, Callable, List, Tuple, Type
|
||||
|
||||
# Attr we store these objects as on the current activity.
|
||||
# (based on our module so hopefully avoids conflicts)
|
||||
STORAGE_ATTR_NAME = '_' + __name__.replace('.', '_') + '_bombfactory'
|
||||
|
||||
PlayerType = TypeVar('PlayerType', bound='ba.Player')
|
||||
|
||||
|
||||
@ -150,14 +146,16 @@ class BombFactory:
|
||||
ba.Sound for a rolling bomb.
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def get() -> BombFactory:
|
||||
_STORENAME = ba.storagename()
|
||||
|
||||
@classmethod
|
||||
def get(cls) -> BombFactory:
|
||||
"""Get/create a shared bastd.actor.bomb.BombFactory object."""
|
||||
activity = ba.getactivity()
|
||||
factory = getattr(activity, STORAGE_ATTR_NAME, None)
|
||||
factory = activity.customdata.get(cls._STORENAME)
|
||||
if factory is None:
|
||||
factory = BombFactory()
|
||||
setattr(activity, STORAGE_ATTR_NAME, factory)
|
||||
activity.customdata[cls._STORENAME] = factory
|
||||
assert isinstance(factory, BombFactory)
|
||||
return factory
|
||||
|
||||
|
||||
@ -59,6 +59,8 @@ class FlagFactory:
|
||||
The ba.Texture for flags.
|
||||
"""
|
||||
|
||||
_STORENAME = ba.storagename()
|
||||
|
||||
def __init__(self) -> None:
|
||||
"""Instantiate a FlagFactory.
|
||||
|
||||
@ -123,14 +125,14 @@ class FlagFactory:
|
||||
|
||||
self.flag_texture = ba.gettexture('flagColor')
|
||||
|
||||
@staticmethod
|
||||
def get() -> FlagFactory:
|
||||
@classmethod
|
||||
def get(cls) -> FlagFactory:
|
||||
"""Get/create a shared FlagFactory instance."""
|
||||
activity = ba.getactivity()
|
||||
factory = getattr(activity, 'shared_flag_factory', None)
|
||||
factory = activity.customdata.get(cls._STORENAME)
|
||||
if factory is None:
|
||||
factory = FlagFactory()
|
||||
setattr(activity, 'shared_flag_factory', factory)
|
||||
activity.customdata[cls._STORENAME] = factory
|
||||
assert isinstance(factory, FlagFactory)
|
||||
return factory
|
||||
|
||||
|
||||
@ -29,6 +29,7 @@ from typing import TYPE_CHECKING
|
||||
import ba
|
||||
from bastd.actor import bomb as stdbomb
|
||||
from bastd.actor.powerupbox import PowerupBoxFactory
|
||||
from bastd.actor.spazfactory import SpazFactory
|
||||
from bastd.gameutils import SharedObjects
|
||||
|
||||
if TYPE_CHECKING:
|
||||
@ -56,18 +57,6 @@ class BombDiedMessage:
|
||||
"""A bomb has died and thus can be recycled."""
|
||||
|
||||
|
||||
def get_factory() -> SpazFactory:
|
||||
"""Return the shared ba.SpazFactory object, creating it if necessary."""
|
||||
# pylint: disable=cyclic-import
|
||||
from bastd.actor.spazfactory import SpazFactory
|
||||
activity = ba.getactivity()
|
||||
factory = getattr(activity, 'shared_spaz_factory', None)
|
||||
if factory is None:
|
||||
factory = activity.shared_spaz_factory = SpazFactory() # type: ignore
|
||||
assert isinstance(factory, SpazFactory)
|
||||
return factory
|
||||
|
||||
|
||||
class Spaz(ba.Actor):
|
||||
"""
|
||||
Base class for various Spazzes.
|
||||
@ -112,7 +101,7 @@ class Spaz(ba.Actor):
|
||||
shared = SharedObjects.get()
|
||||
activity = self.activity
|
||||
|
||||
factory = get_factory()
|
||||
factory = SpazFactory.get()
|
||||
|
||||
# we need to behave slightly different in the tutorial
|
||||
self._demo_mode = demo_mode
|
||||
@ -466,7 +455,7 @@ class Spaz(ba.Actor):
|
||||
ba.timer(
|
||||
0.1,
|
||||
ba.WeakCall(self._safe_play_sound,
|
||||
get_factory().swish_sound, 0.8))
|
||||
SpazFactory.get().swish_sound, 0.8))
|
||||
self._turbo_filter_add_press('punch')
|
||||
|
||||
def _safe_play_sound(self, sound: ba.Sound, volume: float) -> None:
|
||||
@ -605,7 +594,7 @@ class Spaz(ba.Actor):
|
||||
he will explode in 5 seconds.
|
||||
"""
|
||||
if not self._cursed:
|
||||
factory = get_factory()
|
||||
factory = SpazFactory.get()
|
||||
self._cursed = True
|
||||
|
||||
# Add the curse material.
|
||||
@ -637,7 +626,7 @@ class Spaz(ba.Actor):
|
||||
self._punch_power_scale = 1.7
|
||||
self._punch_cooldown = 300
|
||||
else:
|
||||
factory = get_factory()
|
||||
factory = SpazFactory.get()
|
||||
self._punch_power_scale = factory.punch_power_scale_gloves
|
||||
self._punch_cooldown = factory.punch_cooldown_gloves
|
||||
|
||||
@ -650,7 +639,7 @@ class Spaz(ba.Actor):
|
||||
ba.print_error('Can\'t equip shields; no node.')
|
||||
return
|
||||
|
||||
factory = get_factory()
|
||||
factory = SpazFactory.get()
|
||||
if self.shield is None:
|
||||
self.shield = ba.newnode('shield',
|
||||
owner=self.node,
|
||||
@ -685,7 +674,7 @@ class Spaz(ba.Actor):
|
||||
self.shield = None
|
||||
self.shield_decay_timer = None
|
||||
assert self.node
|
||||
ba.playsound(get_factory().shield_down_sound,
|
||||
ba.playsound(SpazFactory.get().shield_down_sound,
|
||||
1.0,
|
||||
position=self.node.position)
|
||||
else:
|
||||
@ -802,7 +791,7 @@ class Spaz(ba.Actor):
|
||||
ba.WeakCall(self._gloves_wear_off),
|
||||
timeformat=ba.TimeFormat.MILLISECONDS))
|
||||
elif msg.poweruptype == 'shield':
|
||||
factory = get_factory()
|
||||
factory = SpazFactory.get()
|
||||
|
||||
# Let's allow powerup-equipped shields to lose hp over time.
|
||||
self.equip_shields(decay=factory.shield_decay_rate > 0)
|
||||
@ -832,7 +821,7 @@ class Spaz(ba.Actor):
|
||||
self._cursed = False
|
||||
|
||||
# Remove cursed material.
|
||||
factory = get_factory()
|
||||
factory = SpazFactory.get()
|
||||
for attr in ['materials', 'roller_materials']:
|
||||
materials = getattr(self.node, attr)
|
||||
if factory.curse_material in materials:
|
||||
@ -856,7 +845,7 @@ class Spaz(ba.Actor):
|
||||
if not self.node:
|
||||
return None
|
||||
if self.node.invincible:
|
||||
ba.playsound(get_factory().block_sound,
|
||||
ba.playsound(SpazFactory.get().block_sound,
|
||||
1.0,
|
||||
position=self.node.position)
|
||||
return None
|
||||
@ -881,7 +870,7 @@ class Spaz(ba.Actor):
|
||||
if not self.node:
|
||||
return None
|
||||
if self.node.invincible:
|
||||
ba.playsound(get_factory().block_sound,
|
||||
ba.playsound(SpazFactory.get().block_sound,
|
||||
1.0,
|
||||
position=self.node.position)
|
||||
return True
|
||||
@ -924,13 +913,13 @@ class Spaz(ba.Actor):
|
||||
# without damaging the player.
|
||||
# However, massive damage events should still be able to
|
||||
# damage the player. This hopefully gives us a happy medium.
|
||||
max_spillover = get_factory().max_shield_spillover_damage
|
||||
max_spillover = SpazFactory.get().max_shield_spillover_damage
|
||||
if self.shield_hitpoints <= 0:
|
||||
|
||||
# FIXME: Transition out perhaps?
|
||||
self.shield.delete()
|
||||
self.shield = None
|
||||
ba.playsound(get_factory().shield_down_sound,
|
||||
ba.playsound(SpazFactory.get().shield_down_sound,
|
||||
1.0,
|
||||
position=self.node.position)
|
||||
|
||||
@ -944,7 +933,7 @@ class Spaz(ba.Actor):
|
||||
chunk_type='spark')
|
||||
|
||||
else:
|
||||
ba.playsound(get_factory().shield_hit_sound,
|
||||
ba.playsound(SpazFactory.get().shield_hit_sound,
|
||||
0.5,
|
||||
position=self.node.position)
|
||||
|
||||
@ -1001,14 +990,14 @@ class Spaz(ba.Actor):
|
||||
# Let's always add in a super-punch sound with boxing
|
||||
# gloves just to differentiate them.
|
||||
if msg.hit_subtype == 'super_punch':
|
||||
ba.playsound(get_factory().punch_sound_stronger,
|
||||
ba.playsound(SpazFactory.get().punch_sound_stronger,
|
||||
1.0,
|
||||
position=self.node.position)
|
||||
if damage > 500:
|
||||
sounds = get_factory().punch_sound_strong
|
||||
sounds = SpazFactory.get().punch_sound_strong
|
||||
sound = sounds[random.randrange(len(sounds))]
|
||||
else:
|
||||
sound = get_factory().punch_sound
|
||||
sound = SpazFactory.get().punch_sound
|
||||
ba.playsound(sound, 1.0, position=self.node.position)
|
||||
|
||||
# Throw up some chunks.
|
||||
@ -1118,7 +1107,7 @@ class Spaz(ba.Actor):
|
||||
elif self.node:
|
||||
self.node.hurt = 1.0
|
||||
if self.play_big_death_sound and not wasdead:
|
||||
ba.playsound(get_factory().single_player_death_sound)
|
||||
ba.playsound(SpazFactory.get().single_player_death_sound)
|
||||
self.node.dead = True
|
||||
ba.timer(2.0, self.node.delete)
|
||||
|
||||
@ -1160,7 +1149,7 @@ class Spaz(ba.Actor):
|
||||
# If its something besides another spaz, just do a muffled
|
||||
# punch sound.
|
||||
if node.getnodetype() != 'spaz':
|
||||
sounds = get_factory().impact_sounds_medium
|
||||
sounds = SpazFactory.get().impact_sounds_medium
|
||||
sound = sounds[random.randrange(len(sounds))]
|
||||
ba.playsound(sound, 1.0, position=self.node.position)
|
||||
|
||||
@ -1347,11 +1336,11 @@ class Spaz(ba.Actor):
|
||||
scale=0.3,
|
||||
spread=0.2,
|
||||
chunk_type='ice')
|
||||
ba.playsound(get_factory().shatter_sound,
|
||||
ba.playsound(SpazFactory.get().shatter_sound,
|
||||
1.0,
|
||||
position=self.node.position)
|
||||
else:
|
||||
ba.playsound(get_factory().splatter_sound,
|
||||
ba.playsound(SpazFactory.get().splatter_sound,
|
||||
1.0,
|
||||
position=self.node.position)
|
||||
self.handlemessage(ba.DieMessage())
|
||||
@ -1369,11 +1358,11 @@ class Spaz(ba.Actor):
|
||||
self.node.handlemessage('knockout', max(0.0, 50.0 * intensity))
|
||||
sounds: Sequence[ba.Sound]
|
||||
if intensity > 5.0:
|
||||
sounds = get_factory().impact_sounds_harder
|
||||
sounds = SpazFactory.get().impact_sounds_harder
|
||||
elif intensity > 3.0:
|
||||
sounds = get_factory().impact_sounds_hard
|
||||
sounds = SpazFactory.get().impact_sounds_hard
|
||||
else:
|
||||
sounds = get_factory().impact_sounds_medium
|
||||
sounds = SpazFactory.get().impact_sounds_medium
|
||||
sound = sounds[random.randrange(len(sounds))]
|
||||
ba.playsound(sound, position=pos, volume=5.0)
|
||||
|
||||
@ -1418,7 +1407,7 @@ class Spaz(ba.Actor):
|
||||
self._punch_power_scale = 1.2
|
||||
self._punch_cooldown = BASE_PUNCH_COOLDOWN
|
||||
else:
|
||||
factory = get_factory()
|
||||
factory = SpazFactory.get()
|
||||
self._punch_power_scale = factory.punch_power_scale
|
||||
self._punch_cooldown = factory.punch_cooldown
|
||||
self._has_boxing_gloves = False
|
||||
|
||||
@ -26,8 +26,6 @@ from typing import TYPE_CHECKING
|
||||
|
||||
import ba
|
||||
from bastd.gameutils import SharedObjects
|
||||
from bastd.actor.spaz import (PickupMessage, PunchHitMessage,
|
||||
CurseExplodeMessage)
|
||||
import _ba
|
||||
|
||||
if TYPE_CHECKING:
|
||||
@ -97,12 +95,20 @@ class SpazFactory:
|
||||
A ba.Material applied to a cursed ba.Spaz that triggers an explosion.
|
||||
"""
|
||||
|
||||
_STORENAME = ba.storagename()
|
||||
|
||||
def _preload(self, character: str) -> None:
|
||||
"""Preload media needed for a given character."""
|
||||
self.get_media(character)
|
||||
|
||||
def __init__(self) -> None:
|
||||
"""Instantiate a factory object."""
|
||||
# pylint: disable=cyclic-import
|
||||
# FIXME: should probably put these somewhere common so we don't
|
||||
# have to import them from a module that imports us.
|
||||
from bastd.actor.spaz import (PickupMessage, PunchHitMessage,
|
||||
CurseExplodeMessage)
|
||||
|
||||
shared = SharedObjects.get()
|
||||
self.impact_sounds_medium = (ba.getsound('impactMedium'),
|
||||
ba.getsound('impactMedium2'))
|
||||
@ -265,3 +271,14 @@ class SpazFactory:
|
||||
else:
|
||||
media = self.spaz_media[character]
|
||||
return media
|
||||
|
||||
@classmethod
|
||||
def get(cls) -> SpazFactory:
|
||||
"""Return the shared ba.SpazFactory, creating it if necessary."""
|
||||
# pylint: disable=cyclic-import
|
||||
activity = ba.getactivity()
|
||||
factory = activity.customdata.get(cls._STORENAME)
|
||||
if factory is None:
|
||||
factory = activity.customdata[cls._STORENAME] = SpazFactory()
|
||||
assert isinstance(factory, SpazFactory)
|
||||
return factory
|
||||
|
||||
@ -28,7 +28,7 @@ from __future__ import annotations
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import ba
|
||||
from bastd.actor.spaz import get_factory
|
||||
from bastd.actor.spazfactory import SpazFactory
|
||||
from bastd.actor.scoreboard import Scoreboard
|
||||
|
||||
if TYPE_CHECKING:
|
||||
@ -525,7 +525,7 @@ class EliminationGame(ba.TeamGameActivity[Player, Team]):
|
||||
# Play big death sound on our last death
|
||||
# or for every one in solo mode.
|
||||
if self._solo_mode or player.lives == 0:
|
||||
ba.playsound(get_factory().single_player_death_sound)
|
||||
ba.playsound(SpazFactory.get().single_player_death_sound)
|
||||
|
||||
# If we hit zero lives, we're dead (and our team might be too).
|
||||
if player.lives == 0:
|
||||
|
||||
@ -29,10 +29,6 @@ import ba
|
||||
if TYPE_CHECKING:
|
||||
from typing import Sequence, Optional
|
||||
|
||||
# Attr we store these objects as on the current activity.
|
||||
# (based on our module so hopefully avoids conflicts)
|
||||
STORAGE_ATTR_NAME = '_' + __name__.replace('.', '_') + '_sharedobjs'
|
||||
|
||||
|
||||
class SharedObjects:
|
||||
"""Various common components for use in games.
|
||||
@ -44,9 +40,11 @@ class SharedObjects:
|
||||
standard materials.
|
||||
"""
|
||||
|
||||
_STORENAME = ba.storagename()
|
||||
|
||||
def __init__(self) -> None:
|
||||
activity = ba.getactivity()
|
||||
if hasattr(activity, STORAGE_ATTR_NAME):
|
||||
if hasattr(activity, self._STORENAME):
|
||||
raise RuntimeError('Use SharedObjects.get() to fetch the'
|
||||
' shared instance for this activity.')
|
||||
self._object_material: Optional[ba.Material] = None
|
||||
@ -58,14 +56,14 @@ class SharedObjects:
|
||||
self._region_material: Optional[ba.Material] = None
|
||||
self._railing_material: Optional[ba.Material] = None
|
||||
|
||||
@staticmethod
|
||||
def get() -> SharedObjects:
|
||||
@classmethod
|
||||
def get(cls) -> SharedObjects:
|
||||
"""Fetch/create the instance of this class for the current activity."""
|
||||
activity = ba.getactivity()
|
||||
shobs = getattr(activity, STORAGE_ATTR_NAME, None)
|
||||
shobs = activity.customdata.get(cls._STORENAME)
|
||||
if shobs is None:
|
||||
shobs = SharedObjects()
|
||||
setattr(activity, STORAGE_ATTR_NAME, shobs)
|
||||
activity.customdata[cls._STORENAME] = shobs
|
||||
assert isinstance(shobs, SharedObjects)
|
||||
return shobs
|
||||
|
||||
|
||||
@ -28,7 +28,6 @@ import weakref
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import ba
|
||||
from bastd.actor import spaz
|
||||
import _ba
|
||||
|
||||
if TYPE_CHECKING:
|
||||
@ -886,6 +885,7 @@ def _preload2() -> None:
|
||||
|
||||
|
||||
def _preload3() -> None:
|
||||
from bastd.actor.spazfactory import SpazFactory
|
||||
for mname in ['bomb', 'bombSticky', 'impactBomb']:
|
||||
ba.getmodel(mname)
|
||||
for tname in [
|
||||
@ -895,7 +895,7 @@ def _preload3() -> None:
|
||||
ba.gettexture(tname)
|
||||
for sname in ['freeze', 'fuse01', 'activateBeep', 'warnBeep']:
|
||||
ba.getsound(sname)
|
||||
spaz.get_factory()
|
||||
SpazFactory.get()
|
||||
ba.timer(0.2, _preload4)
|
||||
|
||||
|
||||
|
||||
@ -120,7 +120,7 @@ def get_target(path: str) -> None:
|
||||
# Just expand it and it get placed wherever it belongs.
|
||||
|
||||
# Strangely, decompressing lots of these simultaneously leads to occasional
|
||||
# "File does not exist" errors when running on Windows Subystem for Linux.
|
||||
# "File does not exist" errors when running on Windows Subsystem for Linux.
|
||||
# There should be no overlap in files getting written, but perhaps
|
||||
# something about how tar rebuilds the directory structure causes clashes.
|
||||
# It seems that just explicitly creating necessary directories first
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user