Skip to content

Commit

Permalink
Merge branch 'dev' into lights_platform
Browse files Browse the repository at this point in the history
  • Loading branch information
jabdoa2 committed Mar 11, 2017
2 parents 231c70d + 758176f commit 5f66577
Show file tree
Hide file tree
Showing 17 changed files with 394 additions and 44 deletions.
2 changes: 1 addition & 1 deletion mpf/config_players/queue_relay_player.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def play(self, settings, context, priority=0, **kwargs):
"""Block queue event."""
try:
queue = kwargs['queue']
except IndexError:
except KeyError:
raise AssertionError("Can only use queue relay player with queue event.")

instance_dict = self._get_instance_dict(context)
Expand Down
12 changes: 12 additions & 0 deletions mpf/core/config_spec.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@
eject_coil: single|machine(coils)|None
eject_coil_jam_pulse: single|ms|None
eject_coil_retry_pulse: single|ms|None
retries_before_increasing_pulse: single|int|4
hold_coil: single|machine(coils)|None
hold_coil_release_time: single|ms|1s
hold_events: dict|str:ms|None
Expand Down Expand Up @@ -353,6 +354,7 @@
reset_coil: single|machine(coils)|None
reset_coils: list|machine(coils)|None
reset_events: dict|str:ms|machine_reset_phase_3, ball_starting
ignore_switch_ms: single|ms|500ms
event_player:
__valid_in__: machine, mode, show
__allow_others__:
Expand All @@ -366,10 +368,20 @@
args: dict|str:str|None
post: single|str|
wait_for: single|str|
global_extra_ball_settings:
__valid_in__: machine
max_per_game: single|int|None
max_per_ball: single|int|None
max_lit: single|int|None
lit_memory: single|bool|True
enabled: single|bool|True
events_only: single|bool|False
extra_balls:
__valid_in__: mode
award_events: dict|str:ms|None
light_events: dict|str:ms|None
reset_events: dict|str:ms|None
max_per_game: single|int|1
fadecandy:
__valid_in__: machine
gamma: single|float|2.5
Expand Down
10 changes: 8 additions & 2 deletions mpf/core/events.py
Original file line number Diff line number Diff line change
Expand Up @@ -494,8 +494,14 @@ def _run_handlers_sequential(self, event, callback, kwargs):
pass

# call the handler and save the results
queue = QueuedEvent(self.debug_log)
handler.callback(queue=queue, **merged_kwargs)

try:
queue = merged_kwargs['queue']
handler.callback(**merged_kwargs)
except KeyError:
queue = QueuedEvent(self.debug_log)
handler.callback(queue=queue, **merged_kwargs)

if queue.waiter:
queue.event = asyncio.Event(loop=self.machine.clock.loop)
yield from queue.event.wait()
Expand Down
272 changes: 272 additions & 0 deletions mpf/core/extra_balls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,272 @@
"""Class for the ExtraBallController"""
from mpf.core.case_insensitive_dict import CaseInsensitiveDict
from mpf.core.mpf_controller import MpfController


class ExtraBallController(MpfController):
"""Tracks and manages extra balls at the global level."""

config_name = 'extra_balls'

def __init__(self, machine):
"""Initialize ExtraBallManager"""
super().__init__(machine)

self.extra_balls = CaseInsensitiveDict()

self.config = self.machine.config_validator.validate_config(
config_spec='global_extra_ball_settings',
source=self.machine.config['global_extra_ball_settings'])

self.enabled = self.config['enabled']

if not self.enabled:
return

self.events_only = self.config['events_only']

self.machine.events.add_handler('player_add_success',
self._player_added)
self.machine.events.add_handler('player_turn_start',
self._player_turn_start)
self.machine.events.add_handler('player_turn_stop',
self._player_turn_stop)
self.machine.events.add_handler('award_extra_ball',
self.award)
'''event: award_extra_ball
desc: This is an event you can post which will immediately award the
player an extra ball (assuming they're within the limits of max
extra balls, etc.). This event will in turn post the
extra_ball_awarded event if the extra ball is able to be awarded.
Note that if you want to just light the extra ball, but not award it
right away, then use the :doc:`award_lit_extra_ball` event instead.
Also note that if an extra ball is lit, this event will NOT unlight
or decrement the lit extra ball count. If you want to do that, use the
:doc:`award_lit_extra_ball` instead.
'''
self.machine.events.add_handler('award_lit_extra_ball',
self.award_lit)
'''event: award_lit_extra_ball
desc: This event will award an extra ball if extra ball is lit. If the
player has no lit extra balls, then this event will have no effect.
This is a good event to use in your extra ball mode or shot to post
to collect the lit extra ball. It will in turn post the
:doc:`extra_ball_awarded` event (assuming the player has not
exceeded any configured limits for max extra balls).
If you just want to award an extra ball regardless of whether the
player has one lit, use the :doc:`award_extra_ball` event instead.
'''

self.machine.events.add_handler('light_extra_ball',
self.light)

'''event: light_extra_ball
This event will check to make sure the extra ball lit limits are not
exceeded, and then add an extra ball lit count to the player, and then
post the :doc:`extra_ball_lit` event.
Note that MPF tracks the number of lit extra balls, so if you post
this event twice then the player will be able to collect two extra
balls (one at a time) by you posting the :doc:`award_extra_ball`
event.
'''

def _player_added(self, player, **kwargs):
del kwargs

player.extra_balls_awarded = dict()
player.extra_balls_lit = 0
player.extra_balls = 0
player.extra_balls_current_ball = 0

def _player_turn_start(self, player, **kwargs):
del kwargs

player.extra_balls_current_ball = 0

if player.extra_balls_lit:
self.relight()

def _player_turn_stop(self, player, **kwargs):
del kwargs

if not self.config['lit_memory']:
player.extra_balls_lit = 0

def award_lit(self, **kwargs):
"""Awards a lit extra ball.
If the player does not have any lit extra balls, this method does
nothing."""
del kwargs

try:
player = self.machine.game.player
except AttributeError:
return

if not self.enabled:
self._extra_ball_disabled_award()
return

if not player.extra_balls_lit:
return

player.extra_balls_lit -= 1
self.award()

if not player.extra_balls_lit:
self.machine.events.post('extra_ball_unlit')

'''event: extra_ball_unlit
desc: No more lit extra balls are available. This is a good event to
use as a stop event for your extra ball lit mode or whatever you're
using to indicate to the player that an extra ball is available.
'''

def award(self, **kwargs):
"""Immediately awards an extra ball.
This event first checks to make sure the limits of the max extra
balls have not been exceeded.
"""
del kwargs

try:
player = self.machine.game.player
except AttributeError:
return

if not self.enabled:
self._extra_ball_disabled_award()
return

if (self.config['max_per_ball'] and
player.extra_balls_this_ball >= self.config['max_per_ball']):
self.machine.events.post('extra_ball_max_exceeded')
'''event: extra_ball_max_exceeded
desc: The global configured max extra balls (either for this
ball or total for the game for this player has been exceeded, so
this event is posted instead of the extra_ball_awarded event.
'''

elif (self.config['max_per_game'] and
player.extra_balls_awarded >= self.config['max_per_game']):
self.machine.events.post('extra_ball_max_exceeded')

else:
self.machine.events.post('extra_ball_awarded')
'''event: extra_ball_awarded
desc: An extra ball was just awarded. This is a good event to
use to trigger award shows, sounds, etc.
'''

if not self.events_only:
player.extra_balls += 1


def light(self, **kwargs):
"""Lights the extra ball.
This method also increments the player's extra_balls_lit count.
"""
del kwargs

try:
player = self.machine.game.player
except AttributeError:
return

if not self.enabled:
return

if ((self.config['max_lit'] and
player.extra_balls_lit < self.config['max_lit']) or
not self.config['max_lit']):

player.extra_balls_lit += 1
self.machine.events.post('extra_ball_lit')
'''event: extra_ball_lit
desc: An extra ball was just lit. This is a good event to use to
start your extra ball lit mode, or to turn on an extra ball light,
etc.
Note that this event is posted if an extra ball is lit during play
and also when a player's turn starts if they have a lit extra ball.
See also the :doc:`extra_ball_lit_awarded` for a similar event that
is only posted when an extra ball is lit during play, and not
if the player starts their turn with the extra ball lit.
'''

self.machine.events.post('extra_ball_lit_awarded')
'''event: extra_ball_lit_awarded
desc: This even is posted when an extra ball is lit during play.
It is NOT posted when a player's turn starts if they have a lit
extra ball from their previous turn. Therefore this event is a
good event to use for your award slides and shows when a player
lights the extra ball, because you don't want to use
:doc:`extra_ball_lit` because that is also posted when the
player's turn starts and you don't want the award show to play
again when they're starting their turn.
'''

else:
self.machine.events.post('extra_ball_lit_max_exceeded')
'''event: extra_ball_lit_max_exceeded
desc: Posted when an extra ball would be lit, except there's a
global configured max lit setting and the number of lit extra
balls is higher than that.
'''

def relight(self, **kwargs):
"""Relights the extra ball when a player's turn starts.
This event does not post the "extra_ball_lit_awarded" event so you
can use it to not show the extra ball awards when a player starts
their turn with an extra ball lit.
"""
del kwargs

try:
player = self.machine.game.player
except AttributeError:
return

if not self.enabled or not player.extra_balls_lit:
return

self.machine.events.post('extra_ball_lit')

def _extra_ball_disabled_award(self):
self.machine.events.post('extra_ball_disabled_award')
'''event: extra_ball_disabled_award
desc: Posted when you have the global extra ball settings set to not
enable extra balls but where an extra ball would have been awarded.
This is a good alternative event to use to score points or whatever
else you want to give the player when extra balls are disabled.
'''
2 changes: 1 addition & 1 deletion mpf/core/mode_device.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,4 @@ def device_removed_from_mode(self, mode):
"""
del mode
raise NotImplementedError(
'{} does not have a device_removed_from_mode() method'.format(self.name))
'{} does not have a device_removed_from_mode() method'.format(self))
12 changes: 12 additions & 0 deletions mpf/core/mode_timer.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,11 @@ def start(self, **kwargs):
ticks=self.mode.player[self.tick_var],
ticks_remaining=self.ticks_remaining)

self._post_tick_events()
# since lots of slides and stuff are tied to the timer tick, we want
# to post an initial tick event also that represents the starting
# timer value.

def restart(self, **kwargs):
"""Restart the timer by resetting it and then starting it.
Expand Down Expand Up @@ -244,6 +249,9 @@ def pause(self, timer_value=0, **kwargs):
"""
del kwargs

if not timer_value:
timer_value = 0 # make sure it's not None, etc.

self.info_log("Pausing Timer for %s secs", timer_value)

self.running = False
Expand Down Expand Up @@ -330,6 +338,10 @@ def _timer_tick(self, dt):
else:
self.mode.player[self.tick_var] += 1

self._post_tick_events()

def _post_tick_events(self):

if not self._check_for_done():
self.machine.events.post('timer_' + self.name + '_tick',
ticks=self.mode.player[self.tick_var],
Expand Down
4 changes: 3 additions & 1 deletion mpf/core/player.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
import copy
import logging

from mpf.core.case_insensitive_dict import CaseInsensitiveDict

from mpf.core.utility_functions import Util


Expand Down Expand Up @@ -64,7 +66,7 @@ def __init__(self, machine, index):
# use self.__dict__ below since __setattr__ would make these player vars
self.__dict__['log'] = logging.getLogger("Player")
self.__dict__['machine'] = machine
self.__dict__['vars'] = dict()
self.__dict__['vars'] = CaseInsensitiveDict()

number = index + 1

Expand Down
Loading

0 comments on commit 5f66577

Please sign in to comment.