# HG changeset patch # User Emmanuel Gil Peyrot # Date 1318948502 25200 # Node ID c8c60291c56fdf7d1751cdfe574c987d799fa555 # Parent 5271789c067d048502e657a34201f83e16d0e588 Implement item dropping by enemies. diff --git a/pytouhou/formats/ecl.py b/pytouhou/formats/ecl.py --- a/pytouhou/formats/ecl.py +++ b/pytouhou/formats/ecl.py @@ -132,10 +132,10 @@ class ECL(object): 134: ('', None), 135: ('i', None)} #TODO - _main_instructions = {0: ('fffhHHH', 'spawn_enemy'), - 2: ('fffhHHH', 'spawn_enemy_mirrored'), - 4: ('fffhHHH', 'spawn_enemy_random'), - 6: ('fffhHHH', 'spawn_enemy_mirrored_random'), + _main_instructions = {0: ('fffhhHH', 'spawn_enemy'), + 2: ('fffhhHH', 'spawn_enemy_mirrored'), + 4: ('fffhhHH', 'spawn_enemy_random'), + 6: ('fffhhHH', 'spawn_enemy_mirrored_random'), 8: ('', None), 9: ('', None), 10: ('II', None), diff --git a/pytouhou/game/game.py b/pytouhou/game/game.py --- a/pytouhou/game/game.py +++ b/pytouhou/game/game.py @@ -55,6 +55,8 @@ class Game(object): def drop_bonus(self, x, y, _type): player = self.players[0] #TODO + if _type > 6: + return item_type = self.item_types[_type] item = Item((x, y), item_type, self) self.items.append(item) @@ -190,6 +192,9 @@ class Game(object): self.cancelled_bullets = [bullet for bullet in self.cancelled_bullets if bullet.is_visible(384, 448)] self.players_bullets = [bullet for bullet in self.players_bullets if bullet.is_visible(384, 448)] + # Filter out-of-scren items + self.items = [item for item in self.items if item.y < 448] + # Disable boss mode if it is dead/it has timeout if self.boss and self.boss._removed: self.boss = None diff --git a/pytouhou/vm/eclrunner.py b/pytouhou/vm/eclrunner.py --- a/pytouhou/vm/eclrunner.py +++ b/pytouhou/vm/eclrunner.py @@ -118,12 +118,25 @@ class ECLRunner(object): self.sub = enm.boss_callback self.instruction_pointer = 0 enm.boss_callback = None - if enm.life == 0 and enm.death_callback is not None: + if enm.life <= 0: + death_flags = enm.death_flags & 7 + + if death_flags < 4: + if enm._bonus_dropped >= 0: + self._game.drop_bonus(enm.x, enm.y, enm._bonus_dropped) + elif enm._bonus_dropped == -1: + self._game.drop_bonus(enm.x, enm.y, self._game.prng.rand_uint16() % 2) #TODO: find the formula in the binary. Can be big power sometimes. + + if enm.death_callback is not None: + self.frame = 0 + self.sub = enm.death_callback + self.instruction_pointer = 0 + enm.death_callback = None + elif enm.life <= enm.low_life_trigger and enm.low_life_callback is not None: self.frame = 0 - self.sub = enm.death_callback + self.sub = enm.low_life_callback self.instruction_pointer = 0 - #TODO: various things, like deleting the character - enm.death_callback = None #XXX + enm.low_life_callback = None elif enm.timeout and enm.frame == enm.timeout: enm.frame = 0 if enm.timeout_callback is not None: @@ -798,10 +811,12 @@ class ECLRunner(object): @instruction(119) def drop_some_bonus(self, number): + bonus = 0 if self._enemy.select_player().state.power < 128 else 1 for i in range(number): #TODO: find the formula in the binary. self._game.drop_bonus(self._enemy.x - 64 + self._game.prng.rand_uint16() % 128, - self._enemy.y - 64 + self._game.prng.rand_uint16() % 128, 0) + self._enemy.y - 64 + self._game.prng.rand_uint16() % 128, + bonus) @instruction(120) @@ -835,6 +850,7 @@ class ECLRunner(object): @instruction(124) def drop_specific_bonus(self, _type): + #TODO: if _type < 0, “drop” an bullet animation instead of a bonus (never used). self._game.drop_bonus(self._enemy.x, self._enemy.y, _type)