changeset 165:c8c60291c56f

Implement item dropping by enemies.
author Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
date Tue, 18 Oct 2011 07:35:02 -0700
parents 5271789c067d
children dcf32488a2c9
files pytouhou/formats/ecl.py pytouhou/game/game.py pytouhou/vm/eclrunner.py
diffstat 3 files changed, 30 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- 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),
--- 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
--- 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)