changeset 79:ffe2c2b9912c

Handle a few more ECL instructions. Prepare for bullet handling \o/
author Thibaut Girka <thib@sitedethib.com>
date Sat, 03 Sep 2011 18:17:39 +0200
parents bcf965ede96c
children 211e84207b3b
files pytouhou/formats/ecl.py pytouhou/game/enemymanager.py pytouhou/vm/eclrunner.py
diffstat 3 files changed, 105 insertions(+), 21 deletions(-) [+]
line wrap: on
line diff
--- a/pytouhou/formats/ecl.py
+++ b/pytouhou/formats/ecl.py
@@ -101,7 +101,7 @@ class ECL(object):
                      101: ('i', 'set_boss_mode?'),
                      102: ('iffff', 'create_squares'),
                      103: ('fff', 'set_enemy_hitbox'),
-                     104: ('i', None),
+                     104: ('i', 'set_collidable'),
                      105: ('i', 'set_damageable'),
                      106: ('i', 'play_sound'),
                      107: ('i', 'set_death_flags'),
--- a/pytouhou/game/enemymanager.py
+++ b/pytouhou/game/enemymanager.py
@@ -21,11 +21,12 @@ from pytouhou.utils.interpolator import 
 from pytouhou.vm.eclrunner import ECLRunner
 from pytouhou.vm.anmrunner import ANMRunner
 from pytouhou.game.sprite import Sprite
-from math import cos, sin, atan2
+from math import cos, sin, atan2, pi
 
 
 class Enemy(object):
-    def __init__(self, pos, life, _type, anm_wrapper):
+    def __init__(self, pos, life, _type, anm_wrapper, game_state):
+        self._game_state = game_state
         self._anm_wrapper = anm_wrapper
         self._sprite = None
         self._anmrunner = None
@@ -42,6 +43,7 @@ class Enemy(object):
         self.damageable = True
         self.death_flags = 0
         self.pending_bullets = []
+        self.extended_bullet_attributes = (0, 0, 0, 0, 0., 0., 0., 0.)
         self.bullet_attributes = None
         self.bullet_launch_offset = (0, 0)
         self.death_callback = None
@@ -71,25 +73,34 @@ class Enemy(object):
 
 
     def set_bullet_attributes(self, type_, bullet_anim, launch_anim,
-                              bullets_per_shot, number_of_shots, speed, unknown,
+                              bullets_per_shot, number_of_shots, speed, speed2,
                               launch_angle, angle, flags):
         self.bullet_attributes = (type_, bullet_anim, launch_anim, bullets_per_shot,
-                                  number_of_shots, speed, unknown, launch_angle,
+                                  number_of_shots, speed, speed2, launch_angle,
                                   angle, flags)
         if not self.delay_attack:
             self.fire()
 
 
     def fire(self):
+        (type_, bullet_anim, launch_anim, bullets_per_shot, number_of_shots,
+         speed, speed2, launch_angle, angle, flags) = self.bullet_attributes
+        if type_ in (67, 69, 71):
+            launch_angle += self.get_player_angle()
+        if type_ in (69, 70, 71):
+            angle = 2. * pi / bullets_per_shot
+        if type_ == 71:
+            launch_angle += pi / bullets_per_shot
         #TODO
         pass
 
 
-    def select_player(self, players):
-        return players[0] #TODO
+    def select_player(self, players=None):
+        return (players or self._game_state.players)[0] #TODO
 
 
-    def get_player_angle(self, player):
+    def get_player_angle(self, player=None):
+        player = player or self.select_player()
         return atan2(player.y - self.y, player.x - self.x)
 
 
@@ -255,7 +266,7 @@ class EnemyManager(object):
                             y = self._game_state.prng.rand_double() * 416
                         if z < -990: #102h.exe@0x411881
                             y = self._game_state.prng.rand_double() * 800
-                    enemy = Enemy((x, y), life, instr_type, self.anm_wrapper)
+                    enemy = Enemy((x, y), life, instr_type, self.anm_wrapper, self._game_state)
                     self.enemies.append(enemy)
                     self.processes.append(ECLRunner(self.ecl, sub, enemy, self._game_state))
 
--- a/pytouhou/vm/eclrunner.py
+++ b/pytouhou/vm/eclrunner.py
@@ -99,20 +99,19 @@ class ECLRunner(object):
             elif value == -10017:
                 return self._enemy.z
             elif value == -10018:
-                player = self._enemy.select_player(self._game_state.players)
+                player = self._enemy.select_player()
                 return player.x
             elif value == -10019:
-                player = self._enemy.select_player(self._game_state.players)
+                player = self._enemy.select_player()
                 return player.y
             elif value == -10021:
-                player = self._enemy.select_player(self._game_state.players)
-                return self._enemy.get_player_angle(player)
+                return self._enemy.get_player_angle()
             elif value == -10022:
                 return self._enemy.frame
             elif value == -10024:
                 return self._enemy.life
             elif value == -10025:
-                return self._enemy.select_player(self._game_state.players).character
+                return self._enemy.select_player().character
             raise NotImplementedError(value) #TODO
         else:
             return value
@@ -383,7 +382,7 @@ class ECLRunner(object):
     def target_player(self, unknown, speed):
         #TODO: unknown
         self._enemy.speed = speed
-        self._enemy.angle = self._enemy.get_player_angle(self._enemy.select_player(self._game_state.players))
+        self._enemy.angle = self._enemy.get_player_angle()
 
 
     @instruction(56)
@@ -423,12 +422,73 @@ class ECLRunner(object):
 
     @instruction(67)
     def set_bullet_attributes1(self, bullet_anim, launch_anim, bullets_per_shot,
-                              number_of_shots, speed, unknown, launch_angle,
-                              angle, flags):
-        self._enemy.set_bullet_attributes(1, bullet_anim, launch_anim,
-                                           bullets_per_shot, number_of_shots,
-                                           speed, unknown, launch_angle, angle,
-                                           flags)
+                               number_of_shots, speed, speed2, launch_angle,
+                               angle, flags):
+        self._enemy.set_bullet_attributes(67, bullet_anim, launch_anim,
+                                          self._getval(bullets_per_shot),
+                                          self._getval(number_of_shots),
+                                          self._getval(speed),
+                                          self._getval(speed2),
+                                          self._getval(launch_angle),
+                                          self._getval(angle),
+                                          flags)
+
+
+    @instruction(68)
+    def set_bullet_attributes2(self, bullet_anim, launch_anim, bullets_per_shot,
+                               number_of_shots, speed, speed2, launch_angle,
+                               angle, flags):
+        self._enemy.set_bullet_attributes(68, bullet_anim, launch_anim,
+                                          self._getval(bullets_per_shot),
+                                          self._getval(number_of_shots),
+                                          self._getval(speed),
+                                          self._getval(speed2),
+                                          self._getval(launch_angle),
+                                          self._getval(angle),
+                                          flags)
+
+
+    @instruction(69)
+    def set_bullet_attributes3(self, bullet_anim, launch_anim, bullets_per_shot,
+                               number_of_shots, speed, speed2, launch_angle,
+                               angle, flags):
+        self._enemy.set_bullet_attributes(69, bullet_anim, launch_anim,
+                                          self._getval(bullets_per_shot),
+                                          self._getval(number_of_shots),
+                                          self._getval(speed),
+                                          self._getval(speed2),
+                                          self._getval(launch_angle),
+                                          self._getval(angle),
+                                          flags)
+
+
+    @instruction(70)
+    def set_bullet_attributes4(self, bullet_anim, launch_anim, bullets_per_shot,
+                               number_of_shots, speed, speed2, launch_angle,
+                               angle, flags):
+        self._enemy.set_bullet_attributes(67, bullet_anim, launch_anim,
+                                          self._getval(bullets_per_shot),
+                                          self._getval(number_of_shots),
+                                          self._getval(speed),
+                                          self._getval(speed2),
+                                          self._getval(launch_angle),
+                                          self._getval(angle),
+                                          flags)
+
+
+    @instruction(71)
+    def set_bullet_attributes5(self, bullet_anim, launch_anim, bullets_per_shot,
+                               number_of_shots, speed, speed2, launch_angle,
+                               angle, flags):
+        self._enemy.set_bullet_attributes(71, bullet_anim, launch_anim,
+                                          self._getval(bullets_per_shot),
+                                          self._getval(number_of_shots),
+                                          self._getval(speed),
+                                          self._getval(speed2),
+                                          self._getval(launch_angle),
+                                          self._getval(angle),
+                                          flags)
+
 
 
     @instruction(76)
@@ -457,6 +517,11 @@ class ECLRunner(object):
         self._enemy.bullet_launch_offset = (x, y)
 
 
+    @instruction(82)
+    def set_extended_bullet_attributes(self, *attributes):
+        self._enemy.extended_bullet_attributes = attributes
+
+
     @instruction(97)
     def set_anim(self, sprite_index):
         self._enemy.set_anim(sprite_index)
@@ -484,6 +549,14 @@ class ECLRunner(object):
         self._enemy.hitbox = (width, height)
 
 
+    @instruction(104)
+    def set_collidable(self, collidable):
+        """Defines whether the enemy is “collidable”.
+        A collision between a collidable enemy and the player will kill the player.
+        """
+        self._enemy.collidable = bool(collidable & 1)
+
+
     @instruction(105)
     def set_damageable(self, damageable):
         self._enemy.damageable = bool(damageable & 1)