Reference:Rio:Quick and dirty guide to NPCs in demo

From Post-Apocalyptic RPG wiki

Jump to: navigation, search

Code reference.png This article covers outdated code reference information!

Code reference articles are stored at the wiki for legacy reasons. They are often outdated and duplicate Epydoc code documentation and department-specific tutorials. Code reference articles need to be reviewed by the programming department to see if they provide any useful information that is not available elsewhere at the wiki. After they have been reviewed and their unique information has been moved to more appropriate articles, the code reference articles should be deleted.


Firstly, get the current PARPG demo up and running.

This document is going to look at building a character and putting him into the game, and by following this process we can start to see how Fife works 'under the hood' so to speak.

Start by running the demo (on linux, run run.py from the /fife/clients/parpg folder). Walk north and you should bump into this character:

Chemist example1.jpg

If you right click, you'll get three options, 'Move here', 'Kick' and 'Inspect'. Selecting 'kick' gets you the response "Hey", and inspect gets "Engine told me that this instance has ID 6644 and object name chemist". He'll also occasionally spout some text, such as "Bring it on baby, I'm ready for action!"

So let's look at how this fellow is represented in game data. His graphic data can be found at /parpg/objects/agents/chemist. In here is the are a whole bunch of other folders (experiment/read/repair/stand/talk/walk) which hold all the animation frames, and an object.xml file which holds some more info. Most importantly, it holds the name for the object: the second line says object id="chemist".

Casually looking around you'll see that there aren't any data files for the chemist himself (his position, for example, must be somewhere....), so I did a quick grep -R "chemist" * and found that the interesting file we need to look at is /maps/shrine.xml. Here on line 56 we have

<import file="../objects/agents/chemist/object.xml"></import>

So this is where the engine gets the graphic imformation from... And a bit further down we see

<i x="30.0" o="chemist" z="0.0" y="-30.0" r="90"></i>

There is nothing more special for the chemist. If after all you start up the demo again if you click any object in the game you will get exactly the same options as you do for the chemist. So he's not even an NPC as such yet! Whereas the girl that follows you is at least a little more interesting - she has more options! So let's check her out by inspecting her: name NPC:girl,ID 6672 and object name girl.

Now without going into all the gory detail of how I found everything out, here is how you add an extra option for this NPC. Firstly, in gui/instancemenu.xml, add a line:

<Button name="HelloButton" text="Hello" />

under the kissButton. In scripts/agents/girl.py, at the end of the file add the code handle for this:

def HelloButtonHandler(self, myself, speaker):
	# 5000 is time in milliseconds to show text
	myself.say('Hello, World!',5000)

In scripts/world.py add another handler routine (mmm, thats right, we get to add 2 functions with the same name):

def HelloButtonHandler(self):
	self.hide_instancemenu()
	self.instance_to_agent[self.instancemenu.instance.getFifeId()].HelloButtonHandler(self.instancemenu.instance,self.hero)

Now run the demo again and right click the girl to get the Hello option, and to check it works. Finally, let's add the chemist as an NPC and give him some other options. Firstly we adjust his entry in shrine.xml - change line 6081 to:

<i x="5.0" o="chemist" z="0.0" y="8.0" id="NPC:chemist" r="90"></i>

This will also move him much closer to us. Next we need to add a chemist script into /scripts/agents, so we'll take a copy of the girl script and modify it to this:

from agent import Agent
import fife
from settings import Setting

TDS = Setting()

_STATE_NONE, _STATE_IDLE, _STATE_RUN, _STATE_FOLLOW = 0, 1, 2, 3

class Chemist(Agent):
	def __init__(self, model, agentName, layer, uniqInMap=True):
		super(Chemist, self).__init__(model, agentName, layer, uniqInMap)
		self.state = _STATE_NONE
		#self.waypoints = ((67, 80), (75, 44))
		#self.waypoint_counter = 0
		self.hero = self.layer.getInstance('PC')

	def onInstanceActionFinished(self, instance, action):
		pass

	def getNextWaypoint(self):
		return l

	def start(self):
		pass

	def idle(self):
		self.state = _STATE_IDLE
		self.agent.act('stand', self.agent.getFacingLocation(), False)

	def run(self, location):
		pass

	def GiveOxygenButtonHandler(self, myself, speaker):
		myself.say('Thanks buddy!',2000)

Notice I've added a different handler right at the bottom - the 'GiveOxygen'. We need to add this to the /gui/instancemenu.xml file:

<Button name="GiveOxygenButton" text="GiveOxygen" />

The last set of alterations have to made to the world.py file. Add another handler underneath HelloButtonHandler:

def GiveOxygenButtonHandler(self):
    	self.hide_instancemenu()'''
	self.instance_to_agent[self.instancemenu.instance.getFifeId()].GiveOxygenButtonHandler(self.instancemenu.instance,self.hero)

After line 10, at the top, add:

from agents.chemist import Chemist

Change line 114 to reference the chemist:

self.hero, self.girl, self.chemist, self.clouds, self.beekeepers = None, None, None, [], []

At line 133 insert some new code to set him up:

self.chemist = Chemist(self.model, 'NPC:chemist', self.agentlayer)
self.instance_to_agent[self.chemist.agent.getFifeId()] = self.chemist
self.chemist.start()

Save all these files, exit and run the demo again. Walk up and right click, select 'Give Oxygen' and you should get:

Chemist example2.jpg


Phew! Now you can play around with the chemist script and try to see what some of this does. Hope this is of some use to you!

Personal tools