# Released under the MIT License. See LICENSE for details.#"""Defines some standard message objects for use with handlemessage() calls."""from__future__importannotationsfromdataclassesimportdataclassfromtypingimportTYPE_CHECKING,TypeVarfromenumimportEnumimportbabaseifTYPE_CHECKING:fromtypingimportSequence,Anyimportbascenev1class_UnhandledType:pass# A special value that should be returned from handlemessage()# functions for unhandled message types. This may result# in fallback message types being attempted/etc.UNHANDLED=_UnhandledType()@dataclassclassOutOfBoundsMessage:"""A message telling an object that it is out of bounds. Category: Message Classes """classDeathType(Enum):"""A reason for a death. Category: Enums """GENERIC='generic'OUT_OF_BOUNDS='out_of_bounds'IMPACT='impact'FALL='fall'REACHED_GOAL='reached_goal'LEFT_GAME='left_game'@dataclassclassDieMessage:"""A message telling an object to die. Category: **Message Classes** Most bascenev1.Actor-s respond to this. """immediate:bool=False"""If this is set to True, the actor should disappear immediately. This is for 'removing' stuff from the game more so than 'killing' it. If False, the actor should die a 'normal' death and can take its time with lingering corpses, sound effects, etc."""how:DeathType=DeathType.GENERIC"""The particular reason for death."""PlayerT=TypeVar('PlayerT',bound='bascenev1.Player')classPlayerDiedMessage:"""A message saying a bascenev1.Player has died. Category: **Message Classes** """killed:bool"""If True, the player was killed; If False, they left the game or the round ended."""how:DeathType"""The particular type of death."""def__init__(self,player:bascenev1.Player,was_killed:bool,killerplayer:bascenev1.Player|None,how:DeathType,):"""Instantiate a message with the given values."""# Invalid refs should never be passed as args.assertplayer.exists()self._player=player# Invalid refs should never be passed as args.assertkillerplayerisNoneorkillerplayer.exists()self._killerplayer=killerplayerself.killed=was_killedself.how=how
[docs]defgetkillerplayer(self,playertype:type[PlayerT])->PlayerT|None:"""Return the bascenev1.Player responsible for the killing, if any. Pass the Player type being used by the current game. """assertisinstance(self._killerplayer,(playertype,type(None)))returnself._killerplayer
[docs]defgetplayer(self,playertype:type[PlayerT])->PlayerT:"""Return the bascenev1.Player that died. The type of player for the current activity should be passed so that the type-checker properly identifies the returned value as one. """player:Any=self._playerassertisinstance(player,playertype)# We should never be delivering invalid refs.# (could theoretically happen if someone holds on to us)assertplayer.exists()returnplayer
@dataclassclassStandMessage:"""A message telling an object to move to a position in space. Category: **Message Classes** Used when teleporting players to home base, etc. """position:Sequence[float]=(0.0,0.0,0.0)"""Where to move to."""angle:float=0.0"""The angle to face (in degrees)"""@dataclassclassPickUpMessage:"""Tells an object that it has picked something up. Category: **Message Classes** """node:bascenev1.Node"""The bascenev1.Node that is getting picked up."""@dataclassclassDropMessage:"""Tells an object that it has dropped what it was holding. Category: **Message Classes** """@dataclassclassPickedUpMessage:"""Tells an object that it has been picked up by something. Category: **Message Classes** """node:bascenev1.Node"""The bascenev1.Node doing the picking up."""@dataclassclassDroppedMessage:"""Tells an object that it has been dropped. Category: **Message Classes** """node:bascenev1.Node"""The bascenev1.Node doing the dropping."""@dataclassclassShouldShatterMessage:"""Tells an object that it should shatter. Category: **Message Classes** """@dataclassclassImpactDamageMessage:"""Tells an object that it has been jarred violently. Category: **Message Classes** """intensity:float"""The intensity of the impact."""@dataclassclassFreezeMessage:"""Tells an object to become frozen. Category: **Message Classes** As seen in the effects of an ice bascenev1.Bomb. """@dataclassclassThawMessage:"""Tells an object to stop being frozen. Category: **Message Classes** """@dataclassclassCelebrateMessage:"""Tells an object to celebrate. Category: **Message Classes** """duration:float=10.0"""Amount of time to celebrate in seconds."""classHitMessage:"""Tells an object it has been hit in some way. Category: **Message Classes** This is used by punches, explosions, etc to convey their effect to a target. """def__init__(self,*,srcnode:bascenev1.Node|None=None,pos:Sequence[float]|None=None,velocity:Sequence[float]|None=None,magnitude:float=1.0,velocity_magnitude:float=0.0,radius:float=1.0,source_player:bascenev1.Player|None=None,kick_back:float=1.0,flat_damage:float|None=None,hit_type:str='generic',force_direction:Sequence[float]|None=None,hit_subtype:str='default',):"""Instantiate a message with given values."""self.srcnode=srcnodeself.pos=posifposisnotNoneelsebabase.Vec3()self.velocity=velocityifvelocityisnotNoneelsebabase.Vec3()self.magnitude=magnitudeself.velocity_magnitude=velocity_magnitudeself.radius=radius# We should not be getting passed an invalid ref.assertsource_playerisNoneorsource_player.exists()self._source_player=source_playerself.kick_back=kick_backself.flat_damage=flat_damageself.hit_type=hit_typeself.hit_subtype=hit_subtypeself.force_direction=(force_directionifforce_directionisnotNoneelsevelocity)
[docs]defget_source_player(self,playertype:type[PlayerT])->PlayerT|None:"""Return the source-player if one exists and is the provided type."""player:Any=self._source_player# We should not be delivering invalid refs.# (we could translate to None here but technically we are changing# the message delivered which seems wrong)assertplayerisNoneorplayer.exists()# Return the player *only* if they're the type given.returnplayerifisinstance(player,playertype)elseNone
@dataclassclassPlayerProfilesChangedMessage:"""Signals player profiles may have changed and should be reloaded."""