source: trunk/game/scripts/dialoguegui.py @ 366

Revision 361, 6.7 KB checked in by orlandov, 10 years ago (diff)

Ticket #104 - Patch by Vaporice and or1andov. Integrate quests into game dialogue and make it possible to persist quest state. fixes[s:trac, t:134]

  • Integrate Vaporice's quest engine implementation
  • Discontinue or1andov's sample dialogue and use Zenbitz's Drunkard
  • Reuse Zenbitz's dialogue functions and callbacks in the game PlayerCharacter? class
  • Whitespace and style tweaks
  • Property svn:eol-style set to native
Line 
1#!python
2
3#   This file is part of PARPG.
4
5#   PARPG is free software: you can redistribute it and/or modify
6#   it under the terms of the GNU General Public License as published by
7#   the Free Software Foundation, either version 3 of the License, or
8#   (at your option) any later version.
9
10#   PARPG is distributed in the hope that it will be useful,
11#   but WITHOUT ANY WARRANTY; without even the implied warranty of
12#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13#   GNU General Public License for more details.
14
15#   You should have received a copy of the GNU General Public License
16#   along with PARPG.  If not, see <http://www.gnu.org/licenses/>.
17
18import pychan
19import fife
20import pychan.widgets as widgets
21from scripts.dialogue import DialogueEngine
22
23class DialogueGUI(object):
24    def __init__(self, npc, quest_engine, pc):
25        self.pc = pc
26
27        # define dialogue engine callbacks
28        def start_quest(state, quest):
29            print "You've picked up the '%s' quest!" % quest
30            state['quest'].addQuest(quest)
31
32        def complete_quest(state, quest_id):
33            print "You've finished the quest %s" % quest_id
34            state['quest'].finishQuest(quest_id)
35
36        def delete_quest(state, quest_id):
37            print "You've deleted quest %s" % quest_id
38            state['quest'].deleteQuest(quest_id)
39
40        def increase_value(state, quest_id, variable, value):
41            print "Increased %s by %i"%(variable,value)
42            state['quest'][quest_id].increaseValue(variable,value)
43
44        def decrease_value(state, quest_id, variable, value):
45            print "Decreased %s by %i"%(variable,value)
46            state['quest'][quest_id].decreaseValue(variable,value)
47
48        def set_value(state,quest_id, variable, value):
49            print "Set %s to %i"%(variable,value)
50            state['quest'][quest_id].setValue(variable,value)
51
52        def meet(state, npc):
53            print "You've met %s!" % npc
54            state['pc'].meet(npc)
55
56        def get_stuff(state, thing):
57            if thing not in state['pc'].inventory:
58                state['pc'].inventory.add(thing)
59                print "You've now have the %s" % thing
60
61        def take_stuff(state,thing):
62            if thing in state['pc'].inventory:
63                state['pc'].inventory.remove(thing)
64                print "You no longer have the %s" % thing
65
66        dialogue_callbacks = {
67            "complete_quest": complete_quest,
68            "decrease_value": decrease_value,
69            "delete_quest": delete_quest,
70            'end': self.handleEnd,
71            "get_stuff" : get_stuff,
72            "increase_value": increase_value,
73            "meet": meet,
74            'npc_avatar': self.handleAvatarImage,
75            'responses': self.handleResponses,
76            'say': self.handleSay,
77            "set_value": set_value,
78            "start_quest": start_quest,
79            "take_stuff" : take_stuff
80        }
81
82        self.npc = npc
83        state = {
84            'pc': self.pc,
85            'quest': quest_engine
86        }
87        self.dialogue_engine = DialogueEngine(npc.dialogue,
88                                              dialogue_callbacks, state)
89        self.dialogue_gui = pychan.loadXML("gui/dialogue.xml")
90
91    def initiateDialogue(self):
92        """Callback for starting a quest"""
93        stats_label = self.dialogue_gui.findChild(name='stats_label')
94        stats_label.text = u'Name: Ronwell\nA grizzled villager'
95
96        events = {
97            'end_button': self.handleEnd
98        }
99        self.dialogue_gui.mapEvents(events)
100        self.dialogue_gui.show()
101        responses_list = self.dialogue_gui.findChild(name='choices_list')
102        responses = self.dialogue_engine.run()
103        self.setResponses(responses)
104
105    def handleSay(self, state, say):
106        """Callback for NPC speech"""
107        speech = self.dialogue_gui.findChild(name='speech')
108        # to append text to npc speech box, uncomment the following line
109        #speech.text = speech.text + "\n-----\n" + unicode(say)
110        speech.text = unicode(say)
111
112    def handleEntered(self, *args):
113        """Callback for when user hovers over response label"""
114        pass
115
116    def handleExited(self, *args):
117        """Callback for when user hovers out of response label"""
118        pass
119
120    def handleClicked(self, *args):
121        """Handle a response being clicked"""
122        response = int(args[0].name.replace('response', ''))
123        if not self.dialogue_engine.reply(response):
124            self.handleEnd()
125
126    def handleEnd(self):
127        """Handle the end of the conversation being reached. Either from the
128           GUI or from within the conversation itself."""
129        self.dialogue_engine = None
130        self.dialogue_gui.hide()
131        self.npc.behaviour.state = 1
132        self.npc.behaviour.idle()
133
134    def handleAvatarImage(self, state, image):
135        """Callback to handle when the dialogue engine wants to set the NPC image
136           @type image: str
137           @param image: filename of avatar image"""
138        avatar_image = self.dialogue_gui.findChild(name='npc_avatar')
139        avatar_image.image = image
140
141    def handleResponses(self, *args):
142        """Callback to handle when the dialogue engine wants to display a new
143           list of options"""
144        self.setResponses(args[1])
145
146    def setResponses(self, responses):
147        """Creates the list of clickable response labels and sets their
148           respective on-click callbacks
149           @type responses: [ [ "response text", section, condition ], ...]
150           @param responses: the list of response objects from the dialogue
151                             engine"""
152        choices_list = self.dialogue_gui.findChild(name='choices_list')
153        choices_list.removeAllChildren()
154        for i,r in enumerate(responses):
155            button = widgets.Label(
156                name="response%s"%(i,),
157                text=unicode(r[0]),
158                hexpand="1",
159                min_size=(100,16),
160                max_size=(490,48),
161                position_technique='center:center'
162            )
163            button.margins = (5,5)
164            button.background_color = fife.Color(0,0,0)
165            button.color = fife.Color(0,255,0)
166            button.border_size = 0
167            button.wrap_text = 1
168            button.capture(lambda button=button: self.handleEntered(button), \
169                           event_name='mouseEntered')
170            button.capture(lambda button=button: self.handleExited(button), \
171                           event_name='mouseExited')
172            button.capture(lambda button=button: self.handleClicked(button), \
173                           event_name='mouseClicked')
174            choices_list.addChild(button)
175            self.dialogue_gui.adaptLayout(True)
176
177
Note: See TracBrowser for help on using the repository browser.