source: trunk/game/scripts/objects/actors.py @ 323

Revision 323, 10.1 KB checked in by eliedebrauwer, 10 years ago (diff)

Ticket #73: Patch by eliedebrauwer, removed obj_hashes from world, and from the maps, added logic to restore PC and NPC behaviour based on the layer ID, added logic to trigger the map load using within the pump(). Load still not functional. comment[s:trac, t:73]

  • Property svn:eol-style set to native
Line 
1#!/usr/bin/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/>.
17import fife
18from scripts import world
19from base import *
20
21"""All actors go here. Concrete classes only."""
22
23__all__ = ["PlayerCharacter", "NonPlayerCharacter",]
24
25TDS = Setting()
26_AGENT_STATE_NONE, _AGENT_STATE_IDLE, _AGENT_STATE_APPROACH, _AGENT_STATE_RUN, _AGENT_STATE_WANDER, _AGENT_STATE_TALK = xrange(6)
27
28class ActorBehaviour (fife.InstanceActionListener):
29    """Fife agent listener
30    """
31    def __init__(self, layer):
32        fife.InstanceActionListener.__init__(self)
33        self.layer = layer
34   
35    def attachToLayer(self, agent_ID):
36        """ Attaches to a certain layer
37            @type agent_ID: String
38            @param agent_ID: ID of the layer to attach to.
39            @return: None
40        """
41        self.agent = self.layer.getInstance(agent_ID)
42        self.agent.addActionListener(self)
43        self.state = _AGENT_STATE_NONE
44        self.speed = float(TDS.readSetting("PCSpeed"))-1 # TODO: rework/improve
45       
46    def getX(self):
47        """Get the NPC's x position on the map.
48           @rtype: integer"
49           @return: the x coordinate of the NPC's location"""
50        return self.agent.getLocation().getLayerCoordinates().x
51
52    def getY(self):
53        """Get the NPC's y position on the map.
54           @rtype: integer
55           @return: the y coordinate of the NPC's location"""
56        return self.agent.getLocation().getLayerCoordinates().y
57       
58    def onInstanceActionFinished(self, instance, action):
59        pass
60
61   
62class PCBehaviour (ActorBehaviour):
63    def __init__(self, parent = None, layer = None):
64        super(PCBehaviour, self).__init__(layer)
65       
66        self.parent = parent
67        self.idle_counter = 1
68        self.speed = float(TDS.readSetting("PCSpeed")) # TODO: rework/improve
69        self.nextAction = None
70       
71    def onInstanceActionFinished(self, instance, action):
72        """@type instance: ???
73           @param instance: ???
74           @type action: ???
75           @param action: ???
76           @return: None"""
77        if self.nextAction:
78            self.nextAction.execute()
79            self.nextAction = None
80            self.idle()
81        else:
82            self.idle()
83           
84        if(action.getId() != 'stand'):
85            self.idle_counter = 1
86        else:
87            self.idle_counter += 1
88           
89    def onNewMap(self, layer):
90        """Sets the agent onto the new layer.
91        """
92        self.agent = layer.getInstance(self.parent.name)
93        self.agent.addActionListener(self)
94        self.state = _AGENT_STATE_NONE
95        self.idle_counter = 1
96   
97    def idle(self):
98        """@return: None"""
99        self.state = _AGENT_STATE_IDLE
100        self.agent.act('stand', self.agent.getFacingLocation())
101
102class PlayerCharacter (GameObject, Living, CharStats):
103    """
104    PC class
105    """
106    def __init__ (self, ID, agent_layer = None, **kwargs):
107        GameObject.__init__( self, ID, **kwargs )
108        Living.__init__( self, **kwargs )
109        CharStats.__init__( self, **kwargs )
110
111        self.is_PC = True
112       
113        # PC _has_ an inventory, he _is not_ one
114        self.inventory = None
115       
116        self.state = _AGENT_STATE_NONE
117        self.layer_id = agent_layer.getId()
118        self.createBehaviour(agent_layer)
119   
120    def createBehaviour(self, layer):
121        """ Creates the behaviour for this actor.
122            @return None """
123        self.behaviour = PCBehaviour(self, layer)
124   
125    def setup(self):
126        """@return: None"""
127        self.behaviour.attachToLayer(self.ID)
128
129    def start(self):
130        """@return: None"""
131        self.behaviour.idle()
132   
133    def run(self, location):
134        """Makes the PC run to a certain location
135           @type location: fife.ScreenPoint
136           @param location: Screen position to run to.
137           @return: None"""
138        self.state = _AGENT_STATE_RUN
139        self.behaviour.agent.move('run', location, self.behaviour.speed+1)
140
141    def walk(self, location):
142        """Makes the PC walk to a certain location.
143           @type location: fife.ScreenPoint
144           @param location: Screen position to walk to.
145           @return: None"""
146        self.state = _AGENT_STATE_RUN
147        self.behaviour.agent.move('walk', location, self.behaviour.speed-1)
148
149    def teleport(self, location):
150        """Teleports a PC instantly to the given location.
151           @type location: fife.Location
152           @param location: Target coordinates for PC.
153           @return: None"""
154        self.state = _AGENT_STATE_IDLE
155        self.behaviour.agent.setLocation(location)
156
157    def approach(self, location, action = None):
158        """Approaches an npc and then ???.
159           @type loc: fife.Location
160           @param loc: the location to approach
161           @type action: Action
162           @param action: The action to schedule for execution after the approach.
163           @return: None"""
164        self.state = _AGENT_STATE_APPROACH
165        self.behaviour.nextAction = action
166        boxLocation = tuple([int(float(i)) for i in location])
167        l = fife.Location(self.behaviour.agent.getLocation())
168        l.setLayerCoordinates(fife.ModelCoordinate(*boxLocation))
169        self.behaviour.agent.move('run', l, self.behaviour.speed)
170
171class NPCBehaviour(ActorBehaviour):
172    def __init__(self, Parent = None, Layer = None):
173        super(NPCBehaviour, self).__init__(Layer)
174       
175        self.parent = Parent
176        self.state = _AGENT_STATE_NONE
177       
178        # hard code this for now
179        self.distRange = (2, 4)
180       
181    def getTargetLocation(self):
182        """@rtype: fife.Location
183           @return: NPC's position"""
184        x = self.getX()
185        y = self.getY()
186        if self.state == _AGENT_STATE_WANDER:
187            """ Random Target Location """
188            l = [0, 0]
189            for i in range(len(l)):
190                sign = randrange(0, 2)
191                dist = randrange(self.distRange[0], self.distRange[1])
192                if sign == 0:
193                    dist *= -1
194                l[i] = dist
195            x += l[0]
196            y += l[1]
197            # Random walk is
198            # rl = randint(-1, 1);ud = randint(-1, 1);x += rl;y += ud
199        l = fife.Location(self.agent.getLocation())
200        l.setLayerCoordinates(fife.ModelCoordinate(*tuple([x, y])))
201        return l
202
203    def onInstanceActionFinished(self, instance, action):
204        """What the NPC does when it has finished an action.
205           Called by the engine and required for InstanceActionListeners.
206           @type instance: fife.Instance
207           @param instance: self.agent (the NPC listener is listening for this
208            instance)
209           @type action: ???
210           @param action: ???
211           @return: None"""
212        if self.state == _AGENT_STATE_WANDER:
213            self.target_loc = self.getTargetLocation()
214        self.idle()
215       
216   
217    def idle(self):
218        """Controls the NPC when it is idling. Different actions
219           based on the NPC's state.
220           @return: None"""
221        if self.state == _AGENT_STATE_NONE:
222            self.state = _AGENT_STATE_IDLE
223            self.agent.act('stand', self.agent.getFacingLocation())
224        elif self.state == _AGENT_STATE_IDLE:
225            self.target_loc = self.getTargetLocation()
226            self.state = _AGENT_STATE_WANDER
227            self.agent.act('stand', self.agent.getFacingLocation())
228        elif self.state == _AGENT_STATE_WANDER:
229            self.parent.wander(self.target_loc)
230            self.state = _AGENT_STATE_NONE
231        elif self.state == _AGENT_STATE_TALK:
232            self.agent.act('stand', self.pc.getLocation())
233
234class NonPlayerCharacter(GameObject, Living, Scriptable, CharStats):
235    """
236    NPC class
237    """
238    def __init__(self, ID, agent_layer = None, name = 'NPC', \
239                 text = 'A nonplayer character', **kwargs):
240        # init game object
241        GameObject.__init__( self, ID, **kwargs )
242        Living.__init__( self, **kwargs )
243        Scriptable.__init__( self, **kwargs )
244        CharStats.__init__( self, **kwargs )
245
246        self.is_NPC = True
247        self.inventory = None
248        self.layer_id = agent_layer.getId()
249        self.createBehaviour(agent_layer)       
250        self.dialogue = kwargs.get('dialogue')
251
252    def createBehaviour(self, layer):
253        """ Creates the behaviour for this actor.
254            @return None """
255        self.behaviour = NPCBehaviour(self, layer)
256
257    def getLocation(self):
258        """ Get the NPC's position as a fife.Location object. Basically a
259            wrapper.
260            @rtype: fife.Location
261            @return: the location of the NPC"""
262        return self.behaviour.agent.getLocation()
263   
264    def wander(self, location):
265        """Nice slow movement for random walking.
266           @type location: fife.Location
267           @param location: Where the NPC will walk to.
268           @return: None"""
269        self.behaviour.agent.move('walk', location, self.behaviour.speed-1)
270
271    def run(self, location):
272        """Faster movement than walk.
273           @type location: fife.Location
274           @param location: Where the NPC will run to."""
275        self.behaviour.agent.move('run', location, self.behaviour.speed+1)
276
277    def talk(self, pc):
278        """ Makes the NPC ready to talk to the PC
279            @return: None"""
280        self.behaviour.state = _AGENT_STATE_TALK
281        self.behaviour.pc = pc.behaviour.agent
282        self.behaviour.idle()
283   
284    def setup(self):
285        """@return: None"""
286        self.behaviour.attachToLayer(self.ID)
287
288    def start(self):
289        """@return: None"""
290        self.behaviour.idle()
Note: See TracBrowser for help on using the repository browser.