comparison pytouhou/vm/msgrunner.py @ 286:4838e9bab0f9

Implement dialogs (MSG files).
author Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
date Sun, 12 Feb 2012 16:06:03 +0100
parents
children 61adb5453e46
comparison
equal deleted inserted replaced
285:2100276c289d 286:4838e9bab0f9
1 # -*- encoding: utf-8 -*-
2 ##
3 ## Copyright (C) 2012 Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
4 ##
5 ## This program is free software; you can redistribute it and/or modify
6 ## it under the terms of the GNU General Public License as published
7 ## by the Free Software Foundation; version 3 only.
8 ##
9 ## This program is distributed in the hope that it will be useful,
10 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
11 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 ## GNU General Public License for more details.
13 ##
14
15
16 from pytouhou.utils.helpers import get_logger
17
18 from pytouhou.vm.common import MetaRegistry, instruction
19 from pytouhou.game.face import Face
20
21 logger = get_logger(__name__)
22
23
24 class MSGRunner(object):
25 __metaclass__ = MetaRegistry
26 __slots__ = ('_msg', '_game', 'frame', 'sleep_time', 'allow_skip',
27 'frozen', 'faces', 'ended', 'instruction_pointer')
28
29 def __init__(self, msg, script, game):
30 self._msg = msg.msgs[script + 10 * (game.players[0].state.character // 2)]
31 self._game = game
32 self.frame = 0
33 self.sleep_time = 0
34 self.allow_skip = True
35 self.frozen = False
36
37 self.faces = [None, None]
38 game.msg_sprites = self.objects
39 self.ended = False
40
41 self.instruction_pointer = 0
42
43
44 def objects(self):
45 return [face for face in self.faces if face] if not self.ended else []
46
47
48 def run_iteration(self):
49 while True:
50 if self.ended:
51 return False
52
53 try:
54 frame, instr_type, args = self._msg[self.instruction_pointer]
55 except IndexError:
56 self.end()
57 return False
58
59 if frame > self.frame:
60 break
61 else:
62 self.instruction_pointer += 1
63
64 if frame == self.frame:
65 try:
66 callback = self._handlers[instr_type]
67 except KeyError:
68 logger.warn('unhandled msg opcode %d (args: %r)', instr_type, args)
69 else:
70 callback(self, *args)
71
72 if not self.frozen:
73 if self.sleep_time > 0:
74 self.sleep_time -= 1
75 else:
76 self.frame += 1
77
78 for face in self.faces:
79 if face:
80 face.update()
81
82 return True
83
84
85 def skip(self):
86 self.sleep_time = 0
87
88
89 def end(self):
90 self._game.msg_runner = None
91 self._game.msg_wait = False
92 self.ended = True
93
94
95 @instruction(0)
96 def unknown0(self):
97 if self.allow_skip:
98 raise Exception #TODO: seems to crash the game, but why?
99 self.end()
100
101
102 @instruction(1)
103 def enter(self, side, effect):
104 self.faces[side] = Face(self._game.msg_anm_wrapper, effect, side)
105
106
107 @instruction(2)
108 def change_face(self, side, index):
109 face = self.faces[side]
110 if face:
111 face.load(index)
112
113
114 @instruction(4)
115 def pause(self, duration):
116 self.sleep_time = duration
117
118
119 @instruction(5)
120 def animate(self, side, effect):
121 face = self.faces[side]
122 if face:
123 face.animate(effect)
124
125
126 @instruction(6)
127 def spawn_enemy_sprite(self):
128 self._game.msg_wait = False
129
130
131 @instruction(10)
132 def freeze(self):
133 self.frozen = True
134
135
136 @instruction(13)
137 def set_allow_skip(self, boolean):
138 self.allow_skip = bool(boolean)