1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 from random import randrange
19
20
21 from fife import fife
22
23 from base import GameObject, Living, Scriptable, CharStats
24 from composed import CarryableItem
25 from scripts.inventory import Inventory
26 from scripts.common.utils import loadSettings
27
28 """All actors go here. Concrete classes only."""
29
30 __all__ = ["PlayerCharacter", "NonPlayerCharacter",]
31
32 Settings = loadSettings()
33
34 _AGENT_STATE_NONE, _AGENT_STATE_IDLE, _AGENT_STATE_APPROACH, _AGENT_STATE_RUN, _AGENT_STATE_WANDER, _AGENT_STATE_TALK = xrange(6)
35
37 """Fife agent listener"""
39 fife.InstanceActionListener.__init__(self)
40 self.layer = layer
41 self.agent = None
42 self.state = None
43 self.speed = 0
44 self.idle_counter = 1
45
47 """Attaches to a certain layer
48 @type agent_ID: String
49 @param agent_ID: ID of the layer to attach to.
50 @return: None"""
51 self.agent = self.layer.getInstance(agent_ID)
52 self.agent.addActionListener(self)
53 self.state = _AGENT_STATE_NONE
54
55 self.speed = Settings.get("PARPG", "PCSpeed")-1
56
58 """Get the NPC's x position on the map.
59 @rtype: integer"
60 @return: the x coordinate of the NPC's location"""
61 return self.agent.getLocation().getLayerCoordinates().x
62
64 """Get the NPC's y position on the map.
65 @rtype: integer
66 @return: the y coordinate of the NPC's location"""
67 return self.agent.getLocation().getLayerCoordinates().y
68
70 """Sets the agent onto the new layer."""
71 if self.agent is not None:
72 self.agent.removeActionListener(self)
73
74 self.agent = layer.getInstance(self.parent.ID)
75 self.agent.addActionListener(self)
76 self.state = _AGENT_STATE_NONE
77 self.idle_counter = 1
78
80 """@return: None"""
81 self.state = _AGENT_STATE_IDLE
82 self.agent.act('stand', self.agent.getFacingLocation())
83
86
88 - def __init__(self, parent = None, layer = None):
89 super(PCBehaviour, self).__init__(layer)
90 self.parent = parent
91 self.idle_counter = 1
92
93 self.speed = Settings.get("PARPG", "PCSpeed")
94 self.nextAction = None
95 self.agent = None
96
98 """@type instance: ???
99 @param instance: ???
100 @type action: ???
101 @param action: ???
102 @return: None"""
103
104 act = self.nextAction
105 self.nextAction = None
106 self.idle()
107
108 if act:
109 act.execute()
110
111 if(action.getId() != 'stand'):
112 self.idle_counter = 1
113 else:
114 self.idle_counter += 1
115
116
118 - def __init__(self, Parent = None, Layer = None):
119 super(NPCBehaviour, self).__init__(Layer)
120
121 self.parent = Parent
122 self.state = _AGENT_STATE_NONE
123 self.pc = None
124 self.target_loc = None
125 self.nextAction = None
126
127
128 self.distRange = (2, 4)
129
130
131
132
133 self.wanderCounter = 0
134 self.wanderRate = 9
135
137 """@rtype: fife.Location
138 @return: NPC's position"""
139 x = self.getX()
140 y = self.getY()
141 if self.state == _AGENT_STATE_WANDER:
142 """ Random Target Location """
143 l = [0, 0]
144 for i in range(len(l)):
145 sign = randrange(0, 2)
146 dist = randrange(self.distRange[0], self.distRange[1])
147 if sign == 0:
148 dist *= -1
149 l[i] = dist
150 x += l[0]
151 y += l[1]
152
153
154 l = fife.Location(self.agent.getLocation())
155 l.setLayerCoordinates(fife.ModelCoordinate(x, y))
156 return l
157
159 """What the NPC does when it has finished an action.
160 Called by the engine and required for InstanceActionListeners.
161 @type instance: fife.Instance
162 @param instance: self.agent (the NPC listener is listening for this
163 instance)
164 @type action: ???
165 @param action: ???
166 @return: None"""
167 if self.state == _AGENT_STATE_WANDER:
168 self.target_loc = self.getTargetLocation()
169 self.idle()
170
171
173 """Controls the NPC when it is idling. Different actions
174 based on the NPC's state.
175 @return: None"""
176 if self.state == _AGENT_STATE_NONE:
177 self.state = _AGENT_STATE_IDLE
178 self.agent.act('stand', self.agent.getFacingLocation())
179 elif self.state == _AGENT_STATE_IDLE:
180 if self.wanderCounter > self.wanderRate:
181 self.wanderCounter = 0
182 self.state = _AGENT_STATE_WANDER
183 else:
184 self.wanderCounter += 1
185 self.state = _AGENT_STATE_NONE
186
187 self.target_loc = self.getTargetLocation()
188 self.agent.act('stand', self.agent.getFacingLocation())
189 elif self.state == _AGENT_STATE_WANDER:
190 self.parent.wander(self.target_loc)
191 self.state = _AGENT_STATE_NONE
192 elif self.state == _AGENT_STATE_TALK:
193 self.agent.act('stand', self.pc.getLocation())
194
196 """Base class for Characters"""
197 - def __init__(self, ID, agent_layer = None, inventory = None,
198 text = "", **kwargs):
213
215 """Creates the behaviour for this actor.
216 @return: None"""
217 pass
218
220 """@return: None"""
221 self.behaviour.attachToLayer(self.ID)
222
224 """@return: None"""
225 self.behaviour.idle()
226
228 """Teleports a Character instantly to the given location.
229 @type location: fife.Location
230 @param location: Target coordinates for Character.
231 @return: None"""
232 self.state = _AGENT_STATE_IDLE
233 self.behaviour.nextAction = None
234 self.behaviour.agent.setLocation(location)
235
236 - def give (self, item, actor):
237 """Gives the specified item to the different actor. Raises an exception if the item was invalid or not found
238 @type item: Carryable
239 @param item: The item object to give
240 @param actor: Person to give item to"""
241 if item == None:
242 raise ValueError("I don't have %s" % item.name)
243 self.inventory.takeItem(item)
244 actor.inventory.placeItem(item)
245
247 """Returns wether an item is present in the players inventory or not
248 @param item_type: ID of the item
249 @type item_type: str
250 @return: True when the item is present, False when not"""
251 return self.inventory.findItem(item_type = item_type)
252
254 """Returns number of all items or items specified by item_type
255 the player has.
256 @param item_type: ID of the item, can be empty
257 @type item_type: str
258 @return: Number of items"""
259 return self.inventory.count(item_type)
260
262 """Get the NPC's position as a fife.Location object. Basically a
263 wrapper.
264 @rtype: fife.Location
265 @return: the location of the NPC"""
266 return self.behaviour.agent.getLocation()
267
268 - def run(self, location):
269 """Makes the PC run to a certain location
270 @type location: fife.ScreenPoint
271 @param location: Screen position to run to.
272 @return: None"""
273 self.state = _AGENT_STATE_RUN
274 self.behaviour.nextAction = None
275 self.behaviour.agent.move('run', location, self.behaviour.speed+1)
276
277 - def walk(self, location):
278 """Makes the PC walk to a certain location.
279 @type location: fife.ScreenPoint
280 @param location: Screen position to walk to.
281 @return: None"""
282 self.state = _AGENT_STATE_RUN
283 self.behaviour.nextAction = None
284 self.behaviour.agent.move('walk', location, self.behaviour.speed-1)
285
292
294 """Get-er property function"""
295 return (self.getLocation().getMapCoordinates().x,
296 self.getLocation().getMapCoordinates().y)
297
299 """Set-er property function"""
300 map_coords = self.getLocation().getMapCoordinates()
301 map_coords.X, map_coords.Y = float(coords[0]), float (coords[1])
302 self.teleport(map_coords)
303
304 coords = property (_getCoords, _setCoords,
305 doc = "Property allowing you to get and set the object's \
306 coordinates via tuples")
307
309 """PC class"""
310 - def __init__ (self, ID, agent_layer = None, inventory = None,
311 text = "Its you. Who would've thought that?", **kwargs):
322
324 """Returns state for saving
325 """
326 ret_dict = super(PlayerCharacter, self).getStateForSaving()
327 ret_dict["PeopleKnown"] = self.people_i_know
328 return ret_dict
329
330 - def meet(self, npc):
331 """Record that the PC has met a certain NPC
332 @type npc: str
333 @param npc: The NPC's name or id"""
334 if npc in self.people_i_know:
335
336
337 return
338 self.people_i_know.add(npc)
339
340 - def met(self, npc):
341 """Indicate whether the PC has met this npc before
342 @type npc: str
343 @param npc: The NPC's name or id
344 @return: None"""
345 return npc in self.people_i_know
346
348 """Creates the behaviour for this actor.
349 @return: None"""
350 self.behaviour = PCBehaviour(self, layer)
351
352 - def approach(self, location, action = None):
353 """Approaches a location and then perform an action (if set).
354 @type loc: fife.Location
355 @param loc: the location to approach
356 @type action: Action
357 @param action: The action to schedule for execution after the approach.
358 @return: None"""
359 self.state = _AGENT_STATE_APPROACH
360 self.behaviour.nextAction = action
361 boxLocation = tuple([int(float(i)) for i in location])
362 l = fife.Location(self.behaviour.agent.getLocation())
363 l.setLayerCoordinates(fife.ModelCoordinate(*boxLocation))
364 self.behaviour.agent.move('run', l, self.behaviour.speed+1)
365
367 """NPC class"""
368 - def __init__(self, ID, agent_layer=None, name='NPC', \
369 text = 'A nonplayer character', inventory = None,
370 real_name = 'NPC', dialogue = None, **kwargs):
379
381 """Prepares state for saving
382 @type state: dictionary
383 @param state: State of the object
384 """
385 CharacterBase.prepareStateForSaving(self, state)
386 del state["behaviour"]
387
389 """Returns state for saving
390 """
391 ret_dict = CharacterBase.getStateForSaving(self)
392 ret_dict["Lives"] = self.lives
393 ret_dict["State"] = self.behaviour.state
394 return ret_dict
395
397 """Creates the behaviour for this actor.
398 @return None """
399 self.behaviour = NPCBehaviour(self, layer)
400
402 """Nice slow movement for random walking.
403 @type location: fife.Location
404 @param location: Where the NPC will walk to.
405 @return: None"""
406 self.behaviour.agent.move('walk', location, self.behaviour.speed-1)
407
408 - def talk(self, pc):
409 """Makes the NPC ready to talk to the PC
410 @return: None"""
411 self.behaviour.state = _AGENT_STATE_TALK
412 self.behaviour.pc = pc.behaviour.agent
413 self.behaviour.idle()
414