Cleaning up ba.Stats class

This commit is contained in:
Eric Froemling 2020-04-06 18:17:36 -07:00
parent 039b6df851
commit 0de2335fcf
9 changed files with 124 additions and 143 deletions

View File

@ -172,16 +172,16 @@ class CoopGameActivity(GameActivity):
shadow=1.0 if vrmode else 0.5, shadow=1.0 if vrmode else 0.5,
transition_delay=0.0, transition_delay=0.0,
transition_out_delay=1.3 transition_out_delay=1.3
if self.slow_motion else 4000).autoretain() if self.slow_motion else 4.0).autoretain()
hval = 70 hval = 70
vval = -50 vval = -50
tdelay = 0 tdelay = 0.0
for ach in achievements: for ach in achievements:
tdelay += 50 tdelay += 0.05
ach.create_display(hval + 40, ach.create_display(hval + 40,
vval + v_offs, vval + v_offs,
0 + tdelay, 0 + tdelay,
outdelay=1300 if self.slow_motion else 4000, outdelay=1.3 if self.slow_motion else 4.0,
style='in_game') style='in_game')
vval -= 55 vval -= 55

View File

@ -680,9 +680,9 @@ class GameActivity(Activity):
killer = msg.killerplayer killer = msg.killerplayer
# Inform our score-set of the demise. # Inform our score-set of the demise.
self.stats.player_lost_spaz(player, self.stats.player_was_killed(player,
killed=msg.killed, killed=msg.killed,
killer=killer) killer=killer)
# Award the killer points if he's on a different team. # Award the killer points if he's on a different team.
if killer and killer.team is not player.team: if killer and killer.team is not player.team:
@ -1071,7 +1071,6 @@ class GameActivity(Activity):
spaz.node.name = name spaz.node.name = name
spaz.node.name_color = display_color spaz.node.name_color = display_color
spaz.connect_controls_to_player() spaz.connect_controls_to_player()
self.stats.player_got_new_spaz(player, spaz)
# Move to the stand position and add a flash of light. # Move to the stand position and add a flash of light.
spaz.handlemessage( spaz.handlemessage(

View File

@ -72,12 +72,11 @@ class PlayerRecord:
self.killed_count = 0 self.killed_count = 0
self.accum_killed_count = 0 self.accum_killed_count = 0
self._multi_kill_timer: Optional[ba.Timer] = None self._multi_kill_timer: Optional[ba.Timer] = None
self._multikillcount = 0 self._multi_kill_count = 0
self._stats = weakref.ref(stats) self._stats = weakref.ref(stats)
self._last_player: Optional[ba.Player] = None self._last_player: Optional[ba.Player] = None
self._player: Optional[ba.Player] = None self._player: Optional[ba.Player] = None
self.associate_with_player(player) self.associate_with_player(player)
self._spaz: Optional[ReferenceType[ba.Actor]] = None
self._team: Optional[ReferenceType[ba.Team]] = None self._team: Optional[ReferenceType[ba.Team]] = None
self.streak = 0 self.streak = 0
@ -115,16 +114,6 @@ class PlayerRecord:
assert player is not None assert player is not None
return player.get_icon() return player.get_icon()
def get_spaz(self) -> Optional[ba.Actor]:
"""Return the player entry's spaz."""
if self._spaz is None:
return None
return self._spaz()
def set_spaz(self, spaz: Optional[ba.Actor]) -> None:
"""(internal)"""
self._spaz = weakref.ref(spaz) if spaz is not None else None
def cancel_multi_kill_timer(self) -> None: def cancel_multi_kill_timer(self) -> None:
"""Cancel any multi-kill timer for this player entry.""" """Cancel any multi-kill timer for this player entry."""
self._multi_kill_timer = None self._multi_kill_timer = None
@ -144,12 +133,11 @@ class PlayerRecord:
self.character = player.character self.character = player.character
self._last_player = player self._last_player = player
self._player = player self._player = player
self._spaz = None
self.streak = 0 self.streak = 0
def _end_multi_kill(self) -> None: def _end_multi_kill(self) -> None:
self._multi_kill_timer = None self._multi_kill_timer = None
self._multikillcount = 0 self._multi_kill_count = 0
def get_last_player(self) -> ba.Player: def get_last_player(self) -> ba.Player:
"""Return the last ba.Player we were associated with.""" """Return the last ba.Player we were associated with."""
@ -162,52 +150,51 @@ class PlayerRecord:
# pylint: disable=too-many-statements # pylint: disable=too-many-statements
from ba._lang import Lstr from ba._lang import Lstr
from ba._general import Call from ba._general import Call
from ba._enums import TimeFormat self._multi_kill_count += 1
self._multikillcount += 1
stats = self._stats() stats = self._stats()
assert stats assert stats
if self._multikillcount == 1: if self._multi_kill_count == 1:
score = 0 score = 0
name = None name = None
delay = 0 delay = 0.0
color = (0.0, 0.0, 0.0, 1.0) color = (0.0, 0.0, 0.0, 1.0)
scale = 1.0 scale = 1.0
sound = None sound = None
elif self._multikillcount == 2: elif self._multi_kill_count == 2:
score = 20 score = 20
name = Lstr(resource='twoKillText') name = Lstr(resource='twoKillText')
color = (0.1, 1.0, 0.0, 1) color = (0.1, 1.0, 0.0, 1)
scale = 1.0 scale = 1.0
delay = 0 delay = 0.0
sound = stats.orchestrahitsound1 sound = stats.orchestrahitsound1
elif self._multikillcount == 3: elif self._multi_kill_count == 3:
score = 40 score = 40
name = Lstr(resource='threeKillText') name = Lstr(resource='threeKillText')
color = (1.0, 0.7, 0.0, 1) color = (1.0, 0.7, 0.0, 1)
scale = 1.1 scale = 1.1
delay = 300 delay = 0.3
sound = stats.orchestrahitsound2 sound = stats.orchestrahitsound2
elif self._multikillcount == 4: elif self._multi_kill_count == 4:
score = 60 score = 60
name = Lstr(resource='fourKillText') name = Lstr(resource='fourKillText')
color = (1.0, 1.0, 0.0, 1) color = (1.0, 1.0, 0.0, 1)
scale = 1.2 scale = 1.2
delay = 600 delay = 0.6
sound = stats.orchestrahitsound3 sound = stats.orchestrahitsound3
elif self._multikillcount == 5: elif self._multi_kill_count == 5:
score = 80 score = 80
name = Lstr(resource='fiveKillText') name = Lstr(resource='fiveKillText')
color = (1.0, 0.5, 0.0, 1) color = (1.0, 0.5, 0.0, 1)
scale = 1.3 scale = 1.3
delay = 900 delay = 0.9
sound = stats.orchestrahitsound4 sound = stats.orchestrahitsound4
else: else:
score = 100 score = 100
name = Lstr(resource='multiKillText', name = Lstr(resource='multiKillText',
subs=[('${COUNT}', str(self._multikillcount))]) subs=[('${COUNT}', str(self._multi_kill_count))])
color = (1.0, 0.5, 0.0, 1) color = (1.0, 0.5, 0.0, 1)
scale = 1.3 scale = 1.3
delay = 1000 delay = 1.0
sound = stats.orchestrahitsound4 sound = stats.orchestrahitsound4
def _apply(name2: Lstr, score2: int, showpoints2: bool, def _apply(name2: Lstr, score2: int, showpoints2: bool,
@ -217,12 +204,9 @@ class PlayerRecord:
# Only award this if they're still alive and we can get # Only award this if they're still alive and we can get
# their pos. # their pos.
try: if self._player is not None and self._player.node:
actor = self.get_spaz() our_pos = self._player.node.position
assert actor is not None else:
assert actor.node
our_pos = actor.node.position
except Exception:
return return
# Jitter position a bit since these often come in clusters. # Jitter position a bit since these often come in clusters.
@ -249,10 +233,9 @@ class PlayerRecord:
activity.handlemessage(PlayerScoredMessage(score=score2)) activity.handlemessage(PlayerScoredMessage(score=score2))
if name is not None: if name is not None:
_ba.timer(300 + delay, _ba.timer(
Call(_apply, name, score, showpoints, color, scale, 0.3 + delay,
sound), Call(_apply, name, score, showpoints, color, scale, sound))
timeformat=TimeFormat.MILLISECONDS)
# Keep the tally rollin'... # Keep the tally rollin'...
# set a timer for a bit in the future. # set a timer for a bit in the future.
@ -304,6 +287,7 @@ class Stats:
def reset(self) -> None: def reset(self) -> None:
"""Reset the stats instance completely.""" """Reset the stats instance completely."""
# Just to be safe, lets make sure no multi-kill timers are gonna go off # Just to be safe, lets make sure no multi-kill timers are gonna go off
# for no-longer-on-the-list players. # for no-longer-on-the-list players.
for p_entry in list(self._player_records.values()): for p_entry in list(self._player_records.values()):
@ -345,17 +329,6 @@ class Stats:
records[record_id] = record records[record_id] = record
return records return records
def _get_spaz(self, player: ba.Player) -> Optional[ba.Actor]:
return self._player_records[player.get_name()].get_spaz()
def player_got_new_spaz(self, player: ba.Player, spaz: ba.Actor) -> None:
"""Call this when a player gets a new Spaz."""
record = self._player_records[player.get_name()]
if record.get_spaz() is not None:
raise Exception("got 2 player_got_new_spaz() messages in a row"
" without a lost-spaz message")
record.set_spaz(spaz)
def player_got_hit(self, player: ba.Player) -> None: def player_got_hit(self, player: ba.Player) -> None:
"""Call this when a player got hit.""" """Call this when a player got hit."""
s_player = self._player_records[player.get_name()] s_player = self._player_records[player.get_name()]
@ -388,7 +361,7 @@ class Stats:
from ba import _math from ba import _math
from ba._gameactivity import GameActivity from ba._gameactivity import GameActivity
from ba._lang import Lstr from ba._lang import Lstr
del victim_player # currently unused del victim_player # Currently unused.
name = player.get_name() name = player.get_name()
s_player = self._player_records[name] s_player = self._player_records[name]
@ -418,16 +391,9 @@ class Stats:
from ba import _error from ba import _error
_error.print_exception('error showing big_message') _error.print_exception('error showing big_message')
# If we currently have a spaz, pop up a score over it. # If we currently have a actor, pop up a score over it.
if display and showpoints: if display and showpoints:
our_pos: Optional[Sequence[float]] our_pos = player.node.position if player.node else None
try:
spaz = s_player.get_spaz()
assert spaz is not None
assert spaz.node
our_pos = spaz.node.position
except Exception:
our_pos = None
if our_pos is not None: if our_pos is not None:
if target is None: if target is None:
target = our_pos target = our_pos
@ -478,15 +444,14 @@ class Stats:
return points return points
def player_lost_spaz(self, def player_was_killed(self,
player: ba.Player, player: ba.Player,
killed: bool = False, killed: bool = False,
killer: ba.Player = None) -> None: killer: ba.Player = None) -> None:
"""Should be called when a player loses a spaz.""" """Should be called when a player is killed."""
from ba._lang import Lstr from ba._lang import Lstr
name = player.get_name() name = player.get_name()
prec = self._player_records[name] prec = self._player_records[name]
prec.set_spaz(None)
prec.streak = 0 prec.streak = 0
if killed: if killed:
prec.accum_killed_count += 1 prec.accum_killed_count += 1

View File

@ -776,8 +776,8 @@ class Bomb(ba.Actor):
self.arm_timer = ba.Timer( self.arm_timer = ba.Timer(
0.2, ba.WeakCall(self.handlemessage, ArmMessage())) 0.2, ba.WeakCall(self.handlemessage, ArmMessage()))
self.warn_timer = ba.Timer( self.warn_timer = ba.Timer(
0.001 * (fuse_time - 1700), fuse_time - 1.7, ba.WeakCall(self.handlemessage,
ba.WeakCall(self.handlemessage, WarnMessage())) WarnMessage()))
else: else:
fuse_time = 3.0 fuse_time = 3.0

View File

@ -111,9 +111,9 @@ class SpazBot(basespaz.Spaz):
static = False static = False
bouncy = False bouncy = False
run = False run = False
charge_dist_min = 0.0 # when we can start a new charge charge_dist_min = 0.0 # When we can start a new charge.
charge_dist_max = 2.0 # when we can start a new charge charge_dist_max = 2.0 # When we can start a new charge.
run_dist_min = 0.0 # how close we can be to continue running run_dist_min = 0.0 # How close we can be to continue running.
charge_speed_min = 0.4 charge_speed_min = 0.4
charge_speed_max = 1.0 charge_speed_max = 1.0
throw_dist_min = 5.0 throw_dist_min = 5.0
@ -193,6 +193,7 @@ class SpazBot(basespaz.Spaz):
assert self._player_pts assert self._player_pts
for plpt, plvel in self._player_pts: for plpt, plvel in self._player_pts:
dist = (plpt - botpt).length() dist = (plpt - botpt).length()
# Ignore player-points that are significantly below the bot # Ignore player-points that are significantly below the bot
# (keeps bots from following players off cliffs). # (keeps bots from following players off cliffs).
if (closest_dist is None if (closest_dist is None
@ -218,9 +219,12 @@ class SpazBot(basespaz.Spaz):
# pylint: disable=too-many-locals # pylint: disable=too-many-locals
if self.update_callback is not None: if self.update_callback is not None:
if self.update_callback(self): if self.update_callback(self):
return # true means bot has been handled # Bot has been handled.
return
if not self.node:
return
assert self.node
pos = self.node.position pos = self.node.position
our_pos = ba.Vec3(pos[0], 0, pos[2]) our_pos = ba.Vec3(pos[0], 0, pos[2])
can_attack = True can_attack = True
@ -239,11 +243,13 @@ class SpazBot(basespaz.Spaz):
holding_flag = False holding_flag = False
else: else:
holding_flag = False holding_flag = False
# If we're holding the flag, just walk left. # If we're holding the flag, just walk left.
if holding_flag: if holding_flag:
# just walk left # Just walk left.
self.node.move_left_right = -1.0 self.node.move_left_right = -1.0
self.node.move_up_down = 0.0 self.node.move_up_down = 0.0
# Otherwise try to go pick it up. # Otherwise try to go pick it up.
else: else:
assert self.target_flag.node assert self.target_flag.node
@ -273,6 +279,7 @@ class SpazBot(basespaz.Spaz):
self.node.pickup_pressed = True self.node.pickup_pressed = True
self.node.pickup_pressed = False self.node.pickup_pressed = False
return return
# Not a flag-bearer. If we're holding anything but a bomb, drop it. # Not a flag-bearer. If we're holding anything but a bomb, drop it.
if self.node.hold_node: if self.node.hold_node:
try: try:
@ -289,12 +296,13 @@ class SpazBot(basespaz.Spaz):
target_pt_raw, target_vel = self._get_target_player_pt() target_pt_raw, target_vel = self._get_target_player_pt()
if target_pt_raw is None: if target_pt_raw is None:
# use default target if we've got one # Use default target if we've got one.
if self.target_point_default is not None: if self.target_point_default is not None:
target_pt_raw = self.target_point_default target_pt_raw = self.target_point_default
target_vel = ba.Vec3(0, 0, 0) target_vel = ba.Vec3(0, 0, 0)
can_attack = False can_attack = False
# with no target, we stop moving and drop whatever we're holding
# With no target, we stop moving and drop whatever we're holding.
else: else:
self.node.move_left_right = 0 self.node.move_left_right = 0
self.node.move_up_down = 0 self.node.move_up_down = 0
@ -303,13 +311,14 @@ class SpazBot(basespaz.Spaz):
self.node.pickup_pressed = False self.node.pickup_pressed = False
return return
# we don't want height to come into play # We don't want height to come into play.
target_pt_raw[1] = 0.0 target_pt_raw[1] = 0.0
assert target_vel is not None assert target_vel is not None
target_vel[1] = 0.0 target_vel[1] = 0.0
dist_raw = (target_pt_raw - our_pos).length() dist_raw = (target_pt_raw - our_pos).length()
# use a point out in front of them as real target
# Use a point out in front of them as real target.
# (more out in front the farther from us they are) # (more out in front the farther from us they are)
target_pt = (target_pt_raw + target_pt = (target_pt_raw +
target_vel * dist_raw * 0.3 * self._lead_amount) target_vel * dist_raw * 0.3 * self._lead_amount)
@ -319,25 +328,26 @@ class SpazBot(basespaz.Spaz):
to_target = diff.normalized() to_target = diff.normalized()
if self._mode == 'throw': if self._mode == 'throw':
# we can only throw if alive and well.. # We can only throw if alive and well.
if not self._dead and not self.node.knockout: if not self._dead and not self.node.knockout:
assert self._throw_release_time is not None assert self._throw_release_time is not None
time_till_throw = self._throw_release_time - ba.time() time_till_throw = self._throw_release_time - ba.time()
if not self.node.hold_node: if not self.node.hold_node:
# if we haven't thrown yet, whip out the bomb # If we haven't thrown yet, whip out the bomb.
if not self._have_dropped_throw_bomb: if not self._have_dropped_throw_bomb:
self.drop_bomb() self.drop_bomb()
self._have_dropped_throw_bomb = True self._have_dropped_throw_bomb = True
# otherwise our lack of held node means we successfully
# released our bomb.. lets retreat now # Otherwise our lack of held node means we successfully
# released our bomb; lets retreat now.
else: else:
self._mode = 'flee' self._mode = 'flee'
# oh crap we're holding a bomb.. better throw it. # Oh crap, we're holding a bomb; better throw it.
elif time_till_throw <= 0.0: elif time_till_throw <= 0.0:
# jump and throw.. # Jump and throw.
def _safe_pickup(node: ba.Node) -> None: def _safe_pickup(node: ba.Node) -> None:
if node and self.node: if node and self.node:
self.node.pickup_pressed = True self.node.pickup_pressed = True
@ -346,25 +356,26 @@ class SpazBot(basespaz.Spaz):
if dist > 5.0: if dist > 5.0:
self.node.jump_pressed = True self.node.jump_pressed = True
self.node.jump_pressed = False self.node.jump_pressed = False
# throws:
# Throws:
ba.timer(0.1, ba.Call(_safe_pickup, self.node)) ba.timer(0.1, ba.Call(_safe_pickup, self.node))
else: else:
# throws: # Throws:
ba.timer(0.1, ba.Call(_safe_pickup, self.node)) ba.timer(0.1, ba.Call(_safe_pickup, self.node))
if self.static: if self.static:
if time_till_throw < 0.3: if time_till_throw < 0.3:
speed = 1.0 speed = 1.0
elif time_till_throw < 0.7 and dist > 3.0: elif time_till_throw < 0.7 and dist > 3.0:
speed = -1.0 # whiplash for long throws speed = -1.0 # Whiplash for long throws.
else: else:
speed = 0.02 speed = 0.02
else: else:
if time_till_throw < 0.7: if time_till_throw < 0.7:
# right before throw charge full speed towards target # Right before throw charge full speed towards target.
speed = 1.0 speed = 1.0
else: else:
# earlier we can hold or move backward for a whiplash # Earlier we can hold or move backward for a whiplash.
speed = 0.0125 speed = 0.0125
self.node.move_left_right = to_target.x * speed self.node.move_left_right = to_target.x * speed
self.node.move_up_down = to_target.z * -1.0 * speed self.node.move_up_down = to_target.z * -1.0 * speed
@ -373,8 +384,9 @@ class SpazBot(basespaz.Spaz):
if random.random() < 0.3: if random.random() < 0.3:
self._charge_speed = random.uniform(self.charge_speed_min, self._charge_speed = random.uniform(self.charge_speed_min,
self.charge_speed_max) self.charge_speed_max)
# if we're a runner we run during charges *except when near
# an edge (otherwise we tend to fly off easily) # If we're a runner we run during charges *except when near
# an edge (otherwise we tend to fly off easily).
if self.run and dist_raw > self.run_dist_min: if self.run and dist_raw > self.run_dist_min:
self._lead_amount = 0.3 self._lead_amount = 0.3
self._running = True self._running = True
@ -388,8 +400,8 @@ class SpazBot(basespaz.Spaz):
self.node.move_up_down = to_target.z * -1.0 * self._charge_speed self.node.move_up_down = to_target.z * -1.0 * self._charge_speed
elif self._mode == 'wait': elif self._mode == 'wait':
# every now and then, aim towards our target.. # Every now and then, aim towards our target.
# other than that, just stand there # Other than that, just stand there.
if ba.time(timeformat=ba.TimeFormat.MILLISECONDS) % 1234 < 100: if ba.time(timeformat=ba.TimeFormat.MILLISECONDS) % 1234 < 100:
self.node.move_left_right = to_target.x * (400.0 / 33000) self.node.move_left_right = to_target.x * (400.0 / 33000)
self.node.move_up_down = to_target.z * (-400.0 / 33000) self.node.move_up_down = to_target.z * (-400.0 / 33000)
@ -398,8 +410,8 @@ class SpazBot(basespaz.Spaz):
self.node.move_up_down = 0 self.node.move_up_down = 0
elif self._mode == 'flee': elif self._mode == 'flee':
# even if we're a runner, only run till we get away from our # Even if we're a runner, only run till we get away from our
# target (if we keep running we tend to run off edges) # target (if we keep running we tend to run off edges).
if self.run and dist < 3.0: if self.run and dist < 3.0:
self._running = True self._running = True
self.node.run = 1.0 self.node.run = 1.0
@ -409,20 +421,20 @@ class SpazBot(basespaz.Spaz):
self.node.move_left_right = to_target.x * -1.0 self.node.move_left_right = to_target.x * -1.0
self.node.move_up_down = to_target.z self.node.move_up_down = to_target.z
# we might wanna switch states unless we're doing a throw # We might wanna switch states unless we're doing a throw
# (in which case that's our sole concern) # (in which case that's our sole concern).
if self._mode != 'throw': if self._mode != 'throw':
# if we're currently charging, keep track of how far we are # If we're currently charging, keep track of how far we are
# from our target.. when this value increases it means our charge # from our target. When this value increases it means our charge
# is over (ran by them or something) # is over (ran by them or something).
if self._mode == 'charge': if self._mode == 'charge':
if (self._charge_closing_in if (self._charge_closing_in
and self._last_charge_dist < dist < 3.0): and self._last_charge_dist < dist < 3.0):
self._charge_closing_in = False self._charge_closing_in = False
self._last_charge_dist = dist self._last_charge_dist = dist
# if we have a clean shot, throw! # If we have a clean shot, throw!
if (self.throw_dist_min <= dist < self.throw_dist_max if (self.throw_dist_min <= dist < self.throw_dist_max
and random.random() < self.throwiness and can_attack): and random.random() < self.throwiness and can_attack):
self._mode = 'throw' self._mode = 'throw'
@ -434,15 +446,15 @@ class SpazBot(basespaz.Spaz):
(1.0 / self.throw_rate) * (1.0 / self.throw_rate) *
(0.8 + 1.3 * random.random())) (0.8 + 1.3 * random.random()))
# if we're static, always charge (which for us means barely move) # If we're static, always charge (which for us means barely move).
elif self.static: elif self.static:
self._mode = 'wait' self._mode = 'wait'
# if we're too close to charge (and aren't in the middle of an # If we're too close to charge (and aren't in the middle of an
# existing charge) run away # existing charge) run away.
elif dist < self.charge_dist_min and not self._charge_closing_in: elif dist < self.charge_dist_min and not self._charge_closing_in:
# ..unless we're near an edge, in which case we got no choice # ..unless we're near an edge, in which case we've got no
# but to charge.. # choice but to charge.
if self.map.is_point_near_edge(our_pos, self._running): if self.map.is_point_near_edge(our_pos, self._running):
if self._mode != 'charge': if self._mode != 'charge':
self._mode = 'charge' self._mode = 'charge'
@ -452,7 +464,7 @@ class SpazBot(basespaz.Spaz):
else: else:
self._mode = 'flee' self._mode = 'flee'
# we're within charging distance, backed against an edge, # We're within charging distance, backed against an edge,
# or farther than our max throw distance.. chaaarge! # or farther than our max throw distance.. chaaarge!
elif (dist < self.charge_dist_max or dist > self.throw_dist_max elif (dist < self.charge_dist_max or dist > self.throw_dist_max
or self.map.is_point_near_edge(our_pos, self._running)): or self.map.is_point_near_edge(our_pos, self._running)):
@ -462,11 +474,11 @@ class SpazBot(basespaz.Spaz):
self._charge_closing_in = True self._charge_closing_in = True
self._last_charge_dist = dist self._last_charge_dist = dist
# we're too close to throw but too far to charge - either run # We're too close to throw but too far to charge - either run
# away or just chill if we're near an edge # away or just chill if we're near an edge.
elif dist < self.throw_dist_min: elif dist < self.throw_dist_min:
# charge if either we're within charge range or # Charge if either we're within charge range or
# cant retreat to throw # cant retreat to throw.
self._mode = 'flee' self._mode = 'flee'
# Do some awesome jumps if we're running. # Do some awesome jumps if we're running.
@ -494,29 +506,30 @@ class SpazBot(basespaz.Spaz):
def on_expire(self) -> None: def on_expire(self) -> None:
basespaz.Spaz.on_expire(self) basespaz.Spaz.on_expire(self)
# we're being torn down; release
# our callback(s) so there's no chance of them # We're being torn down; release our callback(s) so there's
# keeping activities or other things alive.. # no chance of them keeping activities or other things alive.
self.update_callback = None self.update_callback = None
def handlemessage(self, msg: Any) -> Any: def handlemessage(self, msg: Any) -> Any:
# pylint: disable=too-many-branches # pylint: disable=too-many-branches
self._handlemessage_sanity_check() self._handlemessage_sanity_check()
# keep track of if we're being held and by who most recently # Keep track of if we're being held and by who most recently.
if isinstance(msg, ba.PickedUpMessage): if isinstance(msg, ba.PickedUpMessage):
super().handlemessage(msg) # augment standard behavior super().handlemessage(msg) # Augment standard behavior.
self.held_count += 1 self.held_count += 1
picked_up_by = msg.node.source_player picked_up_by = msg.node.source_player
if picked_up_by: if picked_up_by:
self.last_player_held_by = picked_up_by self.last_player_held_by = picked_up_by
elif isinstance(msg, ba.DroppedMessage): elif isinstance(msg, ba.DroppedMessage):
super().handlemessage(msg) # augment standard behavior super().handlemessage(msg) # Augment standard behavior.
self.held_count -= 1 self.held_count -= 1
if self.held_count < 0: if self.held_count < 0:
print("ERROR: spaz held_count < 0") print("ERROR: spaz held_count < 0")
# let's count someone dropping us as an attack..
# Let's count someone dropping us as an attack.
try: try:
if msg.node: if msg.node:
picked_up_by = msg.node.source_player picked_up_by = msg.node.source_player
@ -533,18 +546,19 @@ class SpazBot(basespaz.Spaz):
elif isinstance(msg, ba.DieMessage): elif isinstance(msg, ba.DieMessage):
# report normal deaths for scoring purposes # Report normal deaths for scoring purposes.
if not self._dead and not msg.immediate: if not self._dead and not msg.immediate:
killerplayer: Optional[ba.Player] killerplayer: Optional[ba.Player]
# if this guy was being held at the time of death, the
# holder is the killer # If this guy was being held at the time of death, the
# holder is the killer.
if self.held_count > 0 and self.last_player_held_by: if self.held_count > 0 and self.last_player_held_by:
killerplayer = self.last_player_held_by killerplayer = self.last_player_held_by
else: else:
# otherwise if they were attacked by someone in the # If they were attacked by someone in the last few
# last few seconds that person's the killer.. # seconds that person's the killer.
# otherwise it was a suicide # Otherwise it was a suicide.
if (self.last_player_attacked_by if (self.last_player_attacked_by
and ba.time() - self.last_attacked_time < 4.0): and ba.time() - self.last_attacked_time < 4.0):
killerplayer = self.last_player_attacked_by killerplayer = self.last_player_attacked_by
@ -552,15 +566,15 @@ class SpazBot(basespaz.Spaz):
killerplayer = None killerplayer = None
activity = self._activity() activity = self._activity()
# (convert dead refs to None) # (convert dead player refs to None)
if not killerplayer: if not killerplayer:
killerplayer = None killerplayer = None
if activity is not None: if activity is not None:
activity.handlemessage( activity.handlemessage(
SpazBotDeathMessage(self, killerplayer, msg.how)) SpazBotDeathMessage(self, killerplayer, msg.how))
super().handlemessage(msg) # augment standard behavior super().handlemessage(msg) # Augment standard behavior.
# keep track of the player who last hit us for point rewarding # Keep track of the player who last hit us for point rewarding.
elif isinstance(msg, ba.HitMessage): elif isinstance(msg, ba.HitMessage):
if msg.source_player: if msg.source_player:
self.last_player_attacked_by = msg.source_player self.last_player_attacked_by = msg.source_player
@ -889,8 +903,9 @@ class BotSet:
def __init__(self) -> None: def __init__(self) -> None:
"""Create a bot-set.""" """Create a bot-set."""
# we spread our bots out over a few lists so we can update
# them in a staggered fashion # We spread our bots out over a few lists so we can update
# them in a staggered fashion.
self._bot_list_count = 5 self._bot_list_count = 5
self._bot_add_list = 0 self._bot_add_list = 0
self._bot_update_list = 0 self._bot_update_list = 0
@ -963,7 +978,7 @@ class BotSet:
self._bot_update_list = (self._bot_update_list + self._bot_update_list = (self._bot_update_list +
1) % self._bot_list_count 1) % self._bot_list_count
# update our list of player points for the bots to use # Update our list of player points for the bots to use.
player_pts = [] player_pts = []
for player in ba.getactivity().players: for player in ba.getactivity().players:
try: try:
@ -980,7 +995,8 @@ class BotSet:
def clear(self) -> None: def clear(self) -> None:
"""Immediately clear out any bots in the set.""" """Immediately clear out any bots in the set."""
# don't do this if the activity is shutting down or dead
# Don't do this if the activity is shutting down or dead.
activity = ba.getactivity(doraise=False) activity = ba.getactivity(doraise=False)
if activity is None or activity.is_expired(): if activity is None or activity.is_expired():
return return
@ -1025,7 +1041,8 @@ class BotSet:
Use this when the bots have won a game. Use this when the bots have won a game.
""" """
self._bot_update_timer = None self._bot_update_timer = None
# at this point stop doing anything but jumping and celebrating
# At this point stop doing anything but jumping and celebrating.
for botlist in self._bot_lists: for botlist in self._bot_lists:
for bot in botlist: for bot in botlist:
if bot.node: if bot.node:

View File

@ -213,7 +213,7 @@ class EasterEggHuntGame(ba.TeamGameActivity):
player = msg.spaz.getplayer() player = msg.spaz.getplayer()
if not player: if not player:
return return
self.stats.player_lost_spaz(player) self.stats.player_was_killed(player)
# Respawn them shortly. # Respawn them shortly.
assert self.initial_player_info is not None assert self.initial_player_info is not None

View File

@ -814,7 +814,7 @@ class FootballCoopGame(ba.CoopGameActivity):
# Respawn dead players. # Respawn dead players.
player = msg.spaz.player player = msg.spaz.player
self.stats.player_lost_spaz(player) self.stats.player_was_killed(player)
assert self.initial_player_info is not None assert self.initial_player_info is not None
respawn_time = 2.0 + len(self.initial_player_info) * 1.0 respawn_time = 2.0 + len(self.initial_player_info) * 1.0

View File

@ -1131,7 +1131,7 @@ class RunaroundGame(ba.CoopGameActivity):
return return
if not player: if not player:
return return
self.stats.player_lost_spaz(player) self.stats.player_was_killed(player)
# Respawn them shortly. # Respawn them shortly.
assert self.initial_player_info is not None assert self.initial_player_info is not None

View File

@ -263,7 +263,7 @@ class TheLastStandGame(ba.CoopGameActivity):
return return
if not player: if not player:
return return
self.stats.player_lost_spaz(player) self.stats.player_was_killed(player)
ba.timer(0.1, self._checkroundover) ba.timer(0.1, self._checkroundover)
elif isinstance(msg, ba.PlayerScoredMessage): elif isinstance(msg, ba.PlayerScoredMessage):