changeset 192:191f89a22303

Further work on the scripting system.
author KarstenBock@gmx.net
date Sun, 13 Nov 2011 17:19:14 +0100
parents c97e48257f51
children 728eabc921f2
files src/parpg/components/fifeagent.py src/parpg/dialogueactions.py src/parpg/gamescenecontroller.py src/parpg/gamestate.py src/parpg/systems/scriptingsystem.py src/parpg/world.py
diffstat 6 files changed, 100 insertions(+), 25 deletions(-) [+]
line wrap: on
line diff
--- a/src/parpg/components/fifeagent.py	Sun Nov 13 13:37:24 2011 +0100
+++ b/src/parpg/components/fifeagent.py	Sun Nov 13 17:19:14 2011 +0100
@@ -34,4 +34,10 @@
 def setup_behaviour(agent):
     """Attach the behaviour to the layer"""
     if agent.behaviour:   
-        agent.behaviour.attachToLayer(agent.entity.getID(), agent.layer)
\ No newline at end of file
+        agent.behaviour.attachToLayer(agent.entity.getID(), agent.layer)
+        
+def approach(agent, target_or_location, action):
+    if agent.behaviour: 
+        agent.behaviour.approach(target_or_location, action)
+        
+commands = {"approach":approach}
\ No newline at end of file
--- a/src/parpg/dialogueactions.py	Sun Nov 13 13:37:24 2011 +0100
+++ b/src/parpg/dialogueactions.py	Sun Nov 13 17:19:14 2011 +0100
@@ -94,7 +94,6 @@
         @type kwargs: dict of objects
         """
         DialogueAction.__init__(self, *args, **kwargs)
-        self.npc_id = args[0]
     
     def __call__(self, game_state):
         """
@@ -104,7 +103,7 @@
             game state.
         @type game_state: dict of objects
         """
-        npc_id = self.npc_id
+        npc_id = game_state["npc"].general.identifier
         # NOTE Technomage 2010-11-13: This print statement seems overly
         #     verbose, so I'm logging it as an INFO message instead.
 #        print("You've met {0}!".format(npc_id))
--- a/src/parpg/gamescenecontroller.py	Sun Nov 13 13:37:24 2011 +0100
+++ b/src/parpg/gamescenecontroller.py	Sun Nov 13 17:19:14 2011 +0100
@@ -73,6 +73,8 @@
                                 model,
                                 application)
         World.__init__(self)
+        self.systems.scripting.game_state = self.model.game_state
+        
         #this can be helpful for IDEs code analysis
         if False:
             assert(isinstance(self.engine, fife.Engine))
@@ -563,6 +565,7 @@
         if self.paused: 
             return
         ControllerBase.pump(self, dt)
+        World.pump(self, dt)
         self.updateMouse()
         if self.model.active_map:
             self.view.highlightFrontObject(self.last_mousecoords)
--- a/src/parpg/gamestate.py	Sun Nov 13 13:37:24 2011 +0100
+++ b/src/parpg/gamestate.py	Sun Nov 13 17:19:14 2011 +0100
@@ -26,6 +26,10 @@
         self.current_map_name = None
         self.maps = {}
         self.npcs_met = set()
+        self.funcs = {
+            "meet":self.meet,
+            "met":self.met
+        }
         
         
     def addObject(self, object_id, map_id, game_object):
@@ -68,10 +72,13 @@
            @type map: String
            @param map: The map name.
            @returns: The list of objects on this map. Or an empty list"""
+        return [i for i in self.getObjectDictOfMap(map_id).values()
+                                    if map_id in self.objects]
+    
+    
+    def getObjectDictOfMap(self, map_id):
         if map_id in self.objects:
-            return [i for i in self.objects[map_id].values() \
-                                        if map_id in self.objects]
-        
+            return self.objects[map_id]
         return {}
     
     def deleteObjectsFromMap(self, map_id):
@@ -157,4 +164,4 @@
            @type npc: str
            @param npc: The NPC's name or id
            @return: None"""
-        return npc in self.npcs_met
+        return npc in self.npcs_met
\ No newline at end of file
--- a/src/parpg/systems/scriptingsystem.py	Sun Nov 13 13:37:24 2011 +0100
+++ b/src/parpg/systems/scriptingsystem.py	Sun Nov 13 17:19:14 2011 +0100
@@ -11,24 +11,31 @@
 #   You should have received a copy of the GNU General Public License
 #   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
+from collections import deque
+from copy import deepcopy
+
 from parpg.bGrease import System
-from collections import deque
 
 class Script(object):
     """Script object"""
 
-    def __init__(self, condition, actions, system):
+    def __init__(self, actions, system):
         """Constructor"""
         assert(isinstance(actions, deque))
-        self.condition = condition
         self.actions = actions
+        assert(isinstance(system, ScriptingSystem))
         self.system = system
+        self.reset()
+
+    def reset(self):
+        """Resets the state of the script"""
+        self.running_actions = deepcopy(self.actions)
         self.running = False
         self.finished = False
         self.time = 0
         self.wait = 0
         self.cur_action = None
-
+    
     def update(self, time):
         """Advance the script"""
         if not self.running:
@@ -39,12 +46,21 @@
         if self.wait <= self.time:
             self.time = 0		    
             try:
-                action = self.actions.popleft()
-                self.cur_action = action[0]
-                self.wait = action[1]
-                if len(action) >= 3:
-                    vals = action[3:] if len(action) > 3 else ()
-                    command = action[2]
+                action_data = self.running_actions.popleft()
+                action = self.system.actions[action_data[0]]
+                action_params = eval(action_data[1], 
+                                          self.system.funcs, 
+                                          self.system.vals
+                                          ) 
+                self.cur_action = action(self.system.world, action_params)
+                self.wait = action_data[2]
+                if len(action_data) >= 4:
+                    vals = (
+                        eval(action_data[4], self.system.funcs, self.system.vals) 
+                        if len(action_data) > 4
+                        else ()
+                    )
+                    command = action_data[3]
                     self.system.commands[command](
                         *vals, 
                         action=self.cur_action
@@ -62,12 +78,15 @@
     their behavior.
     """
 
-    def __init__(self, funcs, commands):
+    def __init__(self, commands, actions):
         """Constructor"""
-        self.funcs = funcs
+        self.funcs = {}
         self.vals = {}
-        self.scripts = []
+        self.scripts = {}
         self.commands = commands
+        self.conditions = []
+        self.actions = actions
+        self.game_state = None
 
     def step(self, dt):
         """Execute a time step for the system. Must be defined
@@ -76,11 +95,50 @@
         :param dt: Time since last step invocation
         :type dt: float
         """
-        for script in self.scripts:
+        self.vals.clear()        
+        self.vals.update(
+            self.game_state.getObjectDictOfMap(
+                self.game_state.current_map_name)
+        )
+        self.funcs.clear()
+        self.funcs.update(self.game_state.funcs)
+        for condition_data in self.conditions:
+            condition = condition_data[0]
+            script_name = condition_data[1]
+            if not self.scripts.has_key(script_name):
+                return
+            script = self.scripts[script_name]
+            if eval(condition, self.funcs, self.vals) and not script.running:
+                script.running = True
+        for script in self.scripts.itervalues():
             assert(isinstance(script, Script))
             if script.finished:
-                self.scripts.remove(script)
+                script.reset()
             elif script.running:
                 script.update(dt)
-            elif eval(script.condition, self.funcs, self.vals):
-                script.running = True
\ No newline at end of file
+                
+    def setScript(self, name, actions):
+        """Sets a script.
+        @param name: The name of the script
+        @param actions: What the script does
+        """
+        self.scripts[name] = Script(actions, 
+                                    self
+                                    )
+        
+    def addCondition(self, condition, script_name):
+        """Adds a condition.
+        @param condition: Condition which will be evaluated
+        @param script_name: Name of the script that will be executed if the
+        condition evaluates to True.
+        """
+        self.conditions.append((condition, script_name))
+    
+    
+    def runScript(self, name):
+        """Runs a script with the given name
+        @param name: The name of the script"""
+        if self.scripts.has_key(name):
+            self.scripts[name].running = True
+        
+    
\ No newline at end of file
--- a/src/parpg/world.py	Sun Nov 13 13:37:24 2011 +0100
+++ b/src/parpg/world.py	Sun Nov 13 17:19:14 2011 +0100
@@ -3,7 +3,9 @@
 
 from parpg.mode import FifeMode
 from parpg import components
+from parpg.components.fifeagent import commands
 from parpg.systems import ScriptingSystem
+from parpg.entities.action import ACTIONS
 
 class World(FifeMode, BaseWorld):
 
@@ -15,7 +17,7 @@
         """Configure the game world's components, systems and renderers"""
         for name, component in components.components.iteritems():
             setattr(self.components, name, component)
-        self.systems.scripting = ScriptingSystem({})
+        self.systems.scripting = ScriptingSystem(commands, ACTIONS)
     
     def pump(self, dt):
         for component in self.components: