
    Iik                     x    S r SSKr\R                  " 5       rSSKJr  \(       a  SSKJr  SSKJ	r	   " S S5      r
g)	zKMixin providing sound scheduling, event scheduling, and playback for games.    N)TYPE_CHECKING   )Player)Userc                      \ rS rSrSrSrSrSrS\S.S\S\	S	\4S
 jjr
SSS\S.S\	S\	S\	S\S\	S	\	4S jjr    S/S\S\	S\	S\	S\	S	S4S jjr S0S\\\\	4      S\	S	S4S jjrS1S jrS1S jrS0S\S \S\	S	S4S! jjrS1S" jrS\S \S	S4S# jrS2S$\S\	S\	S\	S	S4
S% jjrS2S$\S\	S\	S\	S	S4
S& jjrS3S$\S'\S	S4S( jjrS4S)\S*\S+\S	S4S, jjrS1S- jrS.rg)5GameSoundMixin   aj  Schedule and play sounds and game events for games.

Expected Game attributes:
    scheduled_sounds: list of [tick, sound, vol, pan, pitch].
    sound_scheduler_tick: int.
    event_queue: list of (tick, event_type, data).
    is_animating: bool.
    current_music: str.
    current_ambience: str.
    players: list[Player].
    get_user(player) -> User | None.
      z"game_squares/diceroll{variant}.ogg)sound_templatevariant_countr   r   returnc                    [         R                  S[        SU5      5      nUR                  US9nU R	                  U5        U$ )zGPlay one standard board-game dice roll sound and return its asset path.   variant)_SOUND_RANDOMrandintmaxformat
play_sound)selfr   r   r   sounds        Ac:\Users\dbart\PlayPalace11\server\game_utils\game_sound_mixin.pyplay_standard_dice_roll_sound,GameSoundMixin.play_standard_dice_roll_sound%   sA      ''3q-+@A%%g%6          zgame_squares/step{variant}.ogg)start_delay_ticksstep_interval_ticksr   r   spacesr    r!   c                    [        SU5      n[        [        SU5      5       HP  n[        R                  S[        SU5      5      nUR	                  US9n	U R                  XS9  U[        SU5      -  nMR     U$ )zSchedule one standard token-movement sound sequence.

Returns the first tick after the final movement sound, which is useful
for scheduling the arrival/landing event in the same pacing style.
r   r   r   delay_ticks)r   ranger   r   r   schedule_sound)
r   r"   r    r!   r   r   
next_delay_r   r   s
             r   'schedule_standard_token_movement_sounds6GameSoundMixin.schedule_standard_token_movement_sounds1   s}     -.
s1f~&A#++As1m/DEG"))'):E>#a!455J	 '
 r   r   r%   volumepanpitchNc                 ^    U R                   U-   nU R                  R                  XaX4U/5        g)a  Schedule a sound to play after a delay.

Args:
    sound: Sound file name to play.
    delay_ticks: Number of ticks to wait before playing (0 = next tick).
    volume: Volume (0-100).
    pan: Pan (-100 to 100, 0 = center).
    pitch: Pitch (100 = normal).
N)sound_scheduler_tickscheduled_soundsappend)r   r   r%   r,   r-   r.   target_ticks          r   r'   GameSoundMixin.schedule_soundG   s/    " //+=$$k&u%MNr   soundsstart_delayc                 D    UnU H  u  pEU R                  XCS9  X5-  nM     g)zSchedule a sequence of sounds with delays between them.

Args:
    sounds: List of (sound_name, delay_after) tuples.
    start_delay: Initial delay before first sound.
r$   N)r'   )r   r5   r6   current_tickr   delay_afters         r   schedule_sound_sequence&GameSoundMixin.schedule_sound_sequence[   s/     #"(E@'L #)r   c                 8    U R                   R                  5         g)zClear all scheduled sounds.N)r1   clear)r   s    r   clear_scheduled_sounds%GameSoundMixin.clear_scheduled_soundsk   s    ##%r   c                     U R                   n/ nU R                   H3  nUu  pEpgnXA::  a  U R                  XVXx5        M"  UR                  U5        M5     X l        U =R                   S-  sl         g)z<Process scheduled sounds. Called automatically in on_tick().r   N)r0   r1   r   r2   )	r   r8   	remaining	scheduledtickr   r,   r-   r.   s	            r   process_scheduled_sounds'GameSoundMixin.process_scheduled_soundso   sk    00 	..I.7+De#s:  + / !*!!Q&!r   
event_typedatac                 \    U R                   U-   nU R                  R                  XAU45        g)zSchedule a game event to fire after a delay.

Args:
    event_type: Event identifier (game-specific).
    data: Event payload dict.
    delay_ticks: Ticks to wait before firing (0 = next tick).
N)r0   event_queuer2   )r   rF   rG   r%   r3   s        r   schedule_eventGameSoundMixin.schedule_event   s-     //+=$ ?@r   c                     U R                   (       d  gU R                   n/ U l         / nU R                  nU H1  u  pEnXC::  a  U R                  XV5        M  UR                  XEU45        M3     X R                   -   U l         g)zProcess scheduled events. Call in on_tick() after process_scheduled_sounds().

Events whose tick has arrived are dispatched to on_game_event().
Uses queue-swap so events added during handling are preserved.
N)rI   r0   on_game_eventr2   )r   
to_processrA   r8   rC   rF   rG   s          r   process_scheduled_events'GameSoundMixin.process_scheduled_events   s|     %%
	00&0"Dd#"":4  $D!9:	 '1 %'7'77r   c                     g)zHandle a scheduled game event. Override in subclasses.

Args:
    event_type: The event identifier.
    data: The event payload dict.
N )r   rF   rG   s      r   rM   GameSoundMixin.on_game_event   s     	r   namec                     U R                    H/  nU R                  U5      nU(       d  M  UR                  XX45        M1     g)zPlay a sound for all players.N)playersget_userr   )r   rT   r,   r-   r.   playerusers          r   broadcast_soundGameSoundMixin.broadcast_sound   s1    llF==(Dtc9 #r   c                 (    U R                  XX45        g)zAlias for broadcast_sound.N)rZ   )r   rT   r,   r-   r.   s        r   r   GameSoundMixin.play_sound   s    T36r   loopingc                     Xl         U R                   H.  nU R                  U5      nU(       d  M  UR                  X5        M0     g)z0Play music for all players and store as current.N)current_musicrV   rW   
play_music)r   rT   r^   rX   rY   s        r   ra   GameSoundMixin.play_music   s5    !llF==(Dt. #r   loopintrooutroc                     Xl         U R                   H/  nU R                  U5      nU(       d  M  UR                  XU5        M1     g)z#Play ambient sound for all players.N)current_ambiencerV   rW   play_ambience)r   rc   rd   re   rX   rY   s         r   rh   GameSoundMixin.play_ambience   s9     $llF==(Dt""46 #r   c                     SU l         U R                   H-  nU R                  U5      nU(       d  M  UR                  5         M/     g)z#Stop ambient sound for all players. N)rg   rV   rW   stop_ambience)r   rX   rY   s      r   rl   GameSoundMixin.stop_ambience   s7     "llF==(Dt""$ #r   )rg   r`   rI   r1   )r   d   r   rn   )r   )r   N)rn   r   rn   )T)rk   rk   )__name__
__module____qualname____firstlineno____doc__TICKS_PER_SECOND DEFAULT_DICE_ROLL_SOUND_VARIANTS!DEFAULT_TOKEN_STEP_SOUND_VARIANTSstrintr   r*   r'   listtupler:   r>   rD   dictrJ   rO   rM   rZ   r   boolra   rh   rl   __static_attributes__rR   r   r   r   r      s   " '($()%
 C=	
 
 	

 

  "##$>> 	
 !   
2 OO O 	O
 O O 
O. (U38_%( ( 
	( &'(	A 	AD 	As 	ASW 	A8, 4 D :C : : :QT :_c :7s 7C 7C 7C 7Z^ 7/s /T /T /7# 7c 7s 7D 7%r   r   )rs   randomRandomr   typingr   
games.baser   server.core.users.baser   r   rR   r   r   <module>r      s0    Q    #+C% C%r   