Platform Tutorial Defining Mobs

From Multiverse

Jump to: navigation, search
Contributed by: Multiverse Last Tested: 23 Apr 08 Tested By: SteveJ Tested With: 1.5

This section describes how to add mobs to the world and how to give them behaviors. The second half of this article goes on to explain how to use spawn generators to create multiple mobs and respawn them when they are killed. You must have a Multiverse server suite set up with the sample world files. You must also configure a client to log into your world with the sample world assets.


Contents

Create a single mob

To create a new mob, you must:

  1. Define a display context to describe how the mob will be displayed in the world.
  2. Define a template describing the mob,.
  3. Use the template to create an instance of that mob.
  4. Add behaviors to the mob.

Define a display context

A display context describes the look of a object in the world. It contains information about the mesh file the client loads and which submeshes and materials the client will display for this object. Display contexts for mobs are created in the templates.py script for your world. By default, this script is located in the mv-home/config/worldname directory. So, for Sampleworld, this file is mv-home/config/sampleworld/templates.py.

The following code creates the display context for the brax mob. The necessary asset files are already included in the complete SampleAssets (see Downloading asset repositories for more info):

brax_base_DC = DisplayContext("brax.mesh", True)
brax_base_DC.addSubmesh(DisplayContext.Submesh("braxBodyShape-lib.0", "brax.phong1"))
brax_base_DC.addSubmesh(DisplayContext.Submesh("braxHeadShape-lib.0", "brax.phong1"))
brax_base_DC.addSubmesh(DisplayContext.Submesh("braxTailShellTopShape-lib.0", "brax.phong1"))
brax_base_DC.addSubmesh(DisplayContext.Submesh("braxTailShellShape-lib.0", "brax.phong1"))
brax_base_DC.addSubmesh(DisplayContext.Submesh("braxTailShape-lib.0", "brax.phong1"))
brax_base_DC.addSubmesh(DisplayContext.Submesh("braxLadenBoxesShape-lib.0", "brax.brax_box_006_lambert5"))

In this example, "braxBodyShape-lib.0" is the submesh for the brax body and "brax.phong1" is the corresponding material; "braxHeadShape-lib.0" is the submesh for the brax's head, which also used "brax.phong1" as the material; and so on for the additional 4 submeshes.

You can see the submeshes and corresponding materials in any model by loading the mesh into the Multiverse Model Viewer. To see the material name, just click on the submesh in the Model Viewer's list of submeshes.

A display context is defined by the multiverse.server.objects.DisplayContext class.

Define a mob template

The object manager creates objects from templates that describe them. A template specifies the display context for the object and whatever attributes that object will have. By convention, mob templates are defined in the mv-home/config/world-name/templates.py script.

tmpl = Template("Brax")
tmpl.put(WorldManagerClient.NAMESPACE, WorldManagerClient.TEMPL_DISPLAY_CONTEXT, brax_base_DC)
tmpl.put(WorldManagerClient.NAMESPACE, WorldManagerClient.TEMPL_OBJECT_TYPE, ObjectTypes.mob)

A mob template is defined by the multiverse.server.objects.Template class.

Although the brax doesn't have any inventory, to see how to provide inventory to a mob, inspect the line for the "Quest Giver" ("Human Female Leather") mob:

tmpl.put(InventoryClient.NAMESPACE, InventoryClient.TEMPL_ITEMS, "Leather Tunic; Leather Pants; Leather Boots")

This specifies that the mob has a Leather Tunic, Leather Pants, and Leather Boots in its inventory. The templates for each of the items are defined later in the templates.py file.

To make the brax attackable and give it attributes necessary for combat such as health, you can use the following lines:

tmpl.put(CombatClient.NAMESPACE, "health-max", MarsStat("health-max", 100))
tmpl.put(CombatClient.NAMESPACE, "health", MarsStat("health", 100))
tmpl.put(CombatClient.NAMESPACE, "mana-max", MarsStat("mana-max", 100))
tmpl.put(CombatClient.NAMESPACE, "mana", MarsStat("mana", 100))
tmpl.put(CombatClient.NAMESPACE, CombatInfo.COMBAT_PROP_AUTOATTACK_ABILITY, "attack ability")
tmpl.put(CombatClient.NAMESPACE, CombatInfo.COMBAT_PROP_REGEN_EFFECT, "regen effect")
tmpl.put(CombatClient.NAMESPACE, "attackable", Boolean(True))
tmpl.put(CombatClient.NAMESPACE, "combat.mobflag", Boolean(True))

Having defined the Brax template, it must be registered. Follow the definition lines with the call to perform registration:

ObjectManagerClient.registerTemplate(tmpl)

Create and spawn a mob

Now that you have defined a template, you can create a mob as an instance of that template. The simplest way to create a mob is to add a single instance. However, in practice this is rarely useful because you usually want to create a spawn generator.

To do this, first create a marker in World Editor. Call it "mybraxmarker." Then, add the following code to multiverse/config/worldname/mobserver.py to create a single instance of the mob. The first line gets the location of a marker defined in the World Editor. You must know the instance into which you want to spawn the mob, identified here by 'instanceOid'. The call to setY() ensures that the mob is created at ground level:

braxloc = InstanceClient.getMarkerPoint(instanceOid, "mybraxmarker")
braxloc.setY(0)

Then, these two lines create the object using the "Brax" template at the location of the "mybraxmarker" marker:

myOid = ObjectManagerClient.generateObject("Brax", instanceOid, braxloc)
WorldManagerClient.spawn(myOid)

See World Instancing and multiverse.server.plugins.InstanceClient for more on instancing.

Create mobs with a spawn generator

While creating single mobs can be useful, the most common way to create mobs is with a spawn generator. Spawn generators create a group of mobs and respawn them if they are killed.

Create an object factory

A spawn generator uses an object factory to create mobs. An object factory is a simple class that has a makeObject method for creating mobs from a template. For example, add this ObjectFactory sub-class to create a brax spawn generator:

class BraxFactory (ObjectFactory):
   def makeObject(self, spawnData, instanceOid, loc):
       obj = ObjectFactory.makeObject(self, spawnData, instanceOid, loc)
       braxloc = InstanceClient.getMarkerPoint(instanceOid, "mybraxmarker")
       behav = PatrolBehavior()
       behav.addWaypoint(braxLoc)
       behav.addWaypoint(loc)
       obj.addBehavior(BaseBehavior())
       obj.addBehavior(behav)
       obj.addBehavior(CombatBehavior())
       return obj

ObjectFactory.register("BraxFactory", BraxFactory("Brax"))

Creating a spawn generator

A spawn generator can create multiple copies of a mob and respawn them when they are killed. A spawn generator is an instance of the multiverse.mars.objects.SpawnGenerator class. It uses an object factory such as the one defined above.

Spawn generators are created when instances are created or loaded. This is typically done in the instance init and load scripts. The following lines associate the object factory with a spawn generator, and then set the spawn settings. In this case, two brax are spawned within 30 meters of the marker, with a respawn time of 60 seconds. Add this code to your instance init script.

instance = Instance.current()
instanceOid = Instance.currentOid()

braxMarker = instance.getMarker("mybraxmarker").clone()
braxMarker.getPoint().setY(0)
spawnData = SpawnData()
spawnData.setFactoryName("BraxFactory")
spawnData.setInstanceOid(Long(instanceOid))
spawnData.setLoc(braxMarker.getPoint())
spawnData.setNumSpawns(2)
spawnData.setSpawnRadius(30000)
spawnData.setRespawnTime(60000)
MobManagerClient.createSpawnGenerator(spawnData)

See World Instancing and multiverse.server.plugins.InstanceClient for more on instancing.

Add behaviors to a mob

If you want a mob to do something, you must add behaviors to it before you spawn it. multiverse.server.engine.BaseBehavior provides low level movement handling for mobs, to allow them to handle "goto" and "follow" commands from other behaviors. multiverse.server.engine.PatrolBehavior is a simple behavior that generates a "goto" command to make a mob follow a patrol route. You must add behaviors before spawning an object.

So, replace the behaviors from the BraxFactory with the following:

behav = BaseBehavior()
obj.addBehavior(behav)
behav = PatrolBehavior()
behav.addWaypoint(Point(95926, 88657, 3846780))
behav.addWaypoint(Point(100956, 88657, 3846780))
behav.addWaypoint(Point(100956, 88657, 3859780))
obj.addBehavior(behav)

Additional behavior settings

For information about behavior settings, see these classes in the API:

For example, you can set additional PatrolBehavior settings:

behav = BaseBehavior()
obj.addBehavior(behav)
behav = PatrolBehavior()
behav.setLingerTime(10000)
behav.setMovementSpeed(10000)
behav.addWaypoint(Point(95926, 88657, 3846780))
behav.addWaypoint(Point(100956, 88657, 3846780))
behav.addWaypoint(Point(100956, 88657, 3859780))
obj.addBehavior(behav)

Putting it all together

To add brax to your game world:

  1. Copy templates.py, mobserver.py, and instance_load.py from mv-home/config/sampleworld to mv-home/config/world-name, where world-name is the name of the directory containing your terrain and game world files.
  2. Edit templates.py. Add the following lines of code before the last line:
     braxDC = DisplayContext()
     braxDC.setMeshFile("brax.mesh")
     tmpl = Template("Brax")
     tmpl.put(WorldManagerClient.NAMESPACE, WorldManagerClient.TEMPL_DISPLAY_CONTEXT, braxDC)
     tmpl.put(WorldManagerClient.NAMESPACE, WorldManagerClient.TEMPL_OBJECT_TYPE, ObjectTypes.mob)
     ObjectManagerClient.registerTemplate(tmpl)
    
  3. In the World Editor, add a marker named "mybraxmarker" (or whatever you want to call it).
  4. You will also need to add markers for the Brax patrol route. The code assumes they're named "braxpatrol1", "braxpatrol2", and "braxpatrol3".
  5. Edit mobserver.py. Add the following lines of code before the last line:
     class BraxFactory (ObjectFactory):
        def makeObject(self, spawnData, instanceOid, loc):
            obj = ObjectFactory.makeObject(self, spawnData, instanceOid, loc)
            braxPatrol1 = InstanceClient.getMarkerPoint(instanceOid, "braxpatrol1")
            braxPatrol2 = InstanceClient.getMarkerPoint(instanceOid, "braxpatrol2")
            braxPatrol3 = InstanceClient.getMarkerPoint(instanceOid, "braxpatrol3")
            behav = BaseBehavior()
            obj.addBehavior(behav)
            behav = PatrolBehavior()
            behav.setLingerTime(10000)
            behav.setMovementSpeed(10000)
            behav.addWaypoint(braxPatrol1)  //## broken, var not defined
            behav.addWaypoint(braxPatrol2)
            behav.addWaypoint(braxPatrol3)
            obj.addBehavior(behav)
            return obj
    

    Add the following to the end of instance_load.py

     braxMarker = instance.getMarker("mybraxmarker").clone()
     braxMarker.getPoint().setY(0)
     spawnData = SpawnData()
     spawnData.setFactoryName("BraxFactory")
     spawnData.setInstanceOid(Long(instanceOid))
     spawnData.setLoc(braxMarker.getPoint())
     spawnData.setNumSpawns(2)
     spawnData.setSpawnRadius(30000)
     spawnData.setRespawnTime(60000)
     MobManagerClient.createSpawnGenerator(spawnData)
    
  6. Start the server and log into your world. Use the "/setloc x y z" command if necessary to travel to the coordinates of the spawn generator. You should see two brax running around.



</class1.2>
Personal tools