153 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			Python
		
	
	
			
		
		
	
	
			153 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			Python
		
	
	
| # npc_dialog.py - Dialog helper class
 | |
| #
 | |
| # Copyright (C) 2007 David Delbecq
 | |
| #
 | |
| # This program is free software; you can redistribute it and/or modify
 | |
| # it under the terms of the GNU General Public License as published by
 | |
| # the Free Software Foundation; either version 2 of the License, or
 | |
| # (at your option) any later version.
 | |
| #
 | |
| # This program is distributed in the hope that it will be useful,
 | |
| # but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | |
| # GNU General Public License for more details.
 | |
| #
 | |
| # You should have received a copy of the GNU General Public License
 | |
| # along with this program; if not, write to the Free Software
 | |
| # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 | |
| #
 | |
| #
 | |
| # This is a simple script that makes use of CFDialog.py and that receives
 | |
| # parameters from a JSON inside the event message. Alternatively, the JSON
 | |
| # parameters, if >= 4096 characters, can be stored in a separate file.
 | |
| # Use the classical script parameter to specify relative location of dialog.
 | |
| #
 | |
| # An example of a map file entry is:
 | |
| #
 | |
| # arch guildmaster
 | |
| # name Sigmund
 | |
| # msg
 | |
| #
 | |
| # endmsg
 | |
| # x 11
 | |
| # y 7
 | |
| # resist_physical 100
 | |
| # resist_magic 100
 | |
| # weight 50000000
 | |
| # friendly 1
 | |
| # stand_still 1
 | |
| # arch event_say
 | |
| # name start/sigmund.msg
 | |
| # title Python
 | |
| # slaying /python/misc/npc_dialog.py
 | |
| # end
 | |
| # end
 | |
| #
 | |
| # An example of a JSON dialog similar to the one described in CFDialog.py is:
 | |
| #
 | |
| # {
 | |
| #   "location" : "test_grandpa_01",
 | |
| #   "rules": [
 | |
| #   {
 | |
| #     "match" : ["hello","hi"],
 | |
| #     "pre" : [["hello","0"]],
 | |
| #     "post" : [["hello","1"]],
 | |
| #     "msg" : ["Hello, lad!","Hi, young fellow!","Howdy!"]
 | |
| #   },
 | |
| #   {
 | |
| #     "match": ["hello","hi"],
 | |
| #     "pre" :[["hello","1"]],
 | |
| #     "post" :[["hello", "*"]],
 | |
| #     "msg" : ["I've heard, you know, I'm not deaf *grmbl*"]
 | |
| #   },
 | |
| #   {
 | |
| #     "match" : ["*"],
 | |
| #     "pre" : [["hello","*"]],
 | |
| #     "post" : [["hello", "*"]],
 | |
| #     "msg" : ["What ?", "Huh ?", "What do you want ?"]
 | |
| #   }
 | |
| # ]}
 | |
| #
 | |
| # For detailed descriptions of the match, pre, post, and msg formats, see the
 | |
| # ../CFDialog.py script.
 | |
| #
 | |
| # "match" is a list of keyword strings, and corresponds to what the player says
 | |
| # that the dialog will respond to.
 | |
| #
 | |
| # In the above example, the first rule is applied if the player/character says
 | |
| # "hello" or "hi" and if the "hello" flag is set to "0" (default).  When the
 | |
| # rule is applied, the "hello" flag is then set to "1".
 | |
| #
 | |
| # "pre" is a list of preconditions that identifies flags that must be set to a
 | |
| # particular value in order to trigger a response if a match is detected.
 | |
| #
 | |
| # "post" is a list of postconditions that specify flags that are to be set if a
 | |
| # response is triggered.
 | |
| #
 | |
| # All of the rule values are lists, and must be enclosed by square braces, but
 | |
| # pre and post are lists of lists, so the nested square braces ([[]]) are
 | |
| # required except that using an empty list [] is the best way to indicate when
 | |
| # the rule does not need to check preconditions or set postconditions.
 | |
| #
 | |
| # "msg" defines one or more responses that will be given if the rule triggers.
 | |
| # When more than one "msg" value is set up, the NPC randomly selects which one
 | |
| # to say each time the rule is applied.
 | |
| #
 | |
| # A relatively complex example of an npc_dialog.py dialog is given in the Gork
 | |
| # treasure room quest.  See ../scorn/kar/gork.msg in particular as it
 | |
| # demonstrates how multiple precondition flag values may be exploited to
 | |
| # produce non-linear and variable-path conversations that are less likely to
 | |
| # frustrate a player.  Refer also to ../scorn/kar/mork.msg to see how more
 | |
| # than one dialog can reference the same dialog flags.
 | |
| 
 | |
| import Crossfire
 | |
| import os
 | |
| from CFDialog import DialogRule, Dialog
 | |
| import cjson
 | |
| 
 | |
| def ruleConnected(character, rule):
 | |
|         m = character.Map
 | |
|         m.TriggerConnected(rule.connected, 1)
 | |
| 
 | |
| npc = Crossfire.WhoAmI()
 | |
| event = Crossfire.WhatIsEvent()
 | |
| player = Crossfire.WhoIsActivator()
 | |
| if (Crossfire.ScriptParameters() != None):
 | |
|     filename = os.path.join(Crossfire.DataDirectory(),
 | |
|                             Crossfire.MapDirectory(),
 | |
|                             Crossfire.ScriptParameters())
 | |
|     try:
 | |
|         f = open(filename,'rb')
 | |
|     except:
 | |
|         Crossfire.Log(Crossfire.LogDebug, "Error loading NPC dialog %s" % filename)
 | |
|         raise
 | |
|     else:
 | |
|         Crossfire.Log(Crossfire.LogDebug, "Loading NPC dialog %s" % filename)
 | |
|         parameters = cjson.decode(f.read())
 | |
|         f.close()
 | |
| else:
 | |
|     parameters = cjson.decode(event.Message)
 | |
| location = parameters["location"];
 | |
| speech = Dialog(player, npc, location)
 | |
| index = 0;
 | |
| 
 | |
| for jsonRule in parameters["rules"]:
 | |
|     if ("connected" in jsonRule):
 | |
|         rule = DialogRule(jsonRule["match"],
 | |
|                           jsonRule["pre"],
 | |
|                           jsonRule["msg"],
 | |
|                           jsonRule["post"],
 | |
|                           None,
 | |
|                           ruleConnected);
 | |
|         rule.connected = jsonRule["connected"]
 | |
|     else:
 | |
|         rule = DialogRule(jsonRule["match"],
 | |
|                           jsonRule["pre"],
 | |
|                           jsonRule["msg"],
 | |
|                           jsonRule["post"])
 | |
|     speech.addRule(rule, index)
 | |
|     index = index + 1
 | |
| 
 | |
| if speech.speak(Crossfire.WhatIsMessage()) == 0:
 | |
|     Crossfire.SetReturnValue(1)
 |