Adding Mobs to Your World

From Multiverse

(Redirected from Setting Mob Orientation)
Jump to: navigation, search
Contributed by: Multiverse Last Tested: 23 Apr 08 Tested By: SteveJ Tested With: 1.5

This tutorial will cover adding a character to the database then placing it in the world with multiple different behaviors.

Contents

Setup

This tutorial uses the human female model that comes with Multiverse's sample world. You can find all these files in the Complete Asset Repository on the asset repository page.

On the server side, the tutorial uses three Python script files in MV_HOME/config/sampleworld: templates.py, mobserver.py, and instance_load.py

Once you have found these files it is time to move on ...

Examining the Mob Script File

Open the file templates.py. This file contains all of the Python scripting for the mobs in your world, including entering them into the mob database.

Scroll down to this line:

human_female_base_DC = DisplayContext("human_female.mesh", True)

This statement creates a display context called "human_female_base_DC" that uses the human_female mesh. The file given as the argument to the DisplayContext() method will be the mesh file for the mob.

After this line come a few lines that look like this:

human_female_base_DC.addSubmesh(DisplayContext.Submesh("bodyShape-lib.0",
                                                       "human_female.skin_material"))
human_female_base_DC.addSubmesh(DisplayContext.Submesh("head_aShape-lib.0",
                                                       "human_female.head_a_material"))

These statements specify the submeshes to use, and the associated material files. This determines the mob's armour, hair style, and other details. You can list as many as you want here, but usually you wouldn't use more than five to ten submeshes per mob.

Scroll down to the "mob templates" section and find "Human Female Leather Template".

tmpl = Template("Human Female Leather")

This creates a multiverse.server.objects.Template object and specifies that the database use the name "Human Female Leather" to refer to it. "Human Female Leather" is the name that the client will display above the mob's head.

tmpl.put(WorldManagerClient.NAMESPACE, WorldManagerClient.TEMPL_DISPLAY_CONTEXT, human_female_base_DC)

This statement specifies to use the display context "human_female_base_DC" defined previously.

The remaining lines define the template as a mob and give it clothes:

tmpl.put(WorldManagerClient.NAMESPACE, WorldManagerClient.TEMPL_OBJECT_TYPE, ObjectTypes.mob)
tmpl.put(InventoryClient.NAMESPACE, InventoryClient.TEMPL_ITEMS, "*Leather Tunic; *Leather Pants; *Leather Boots")

The last line is:

ObjectManagerClient.registerTemplate(tmpl)

This statement tells the engine about of this mob's template. The second parameter (tmpl in this case) must match the name of the mob created previously.

For attackable mobs, attributes like health need to be defined. Look at the "Orc Warrior Template" above:

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, "attackable", Boolean(True))
tmpl.put(CombatClient.NAMESPACE, "combat.mobflag", Boolean(True))

Now it's time to make some changes (oh joy!).

Modifying the Code for Your Mob

You are going to create your own mob based on the human female leather described above. This is done in two steps:

  • Create a display context
  • Create a template

Creating a display context

Creating a display context is one of two ways to customize how the mob will look. Either you create a new display context with the appropriate meshes, or you can use human_female_base_DC and create items that you can have the mob equip. Since it is only necessary for our mob to look like she is wearing plate armor, and you probably don't want the mob to drop a full set of plate armor each time one is killed, you should make a new display context for her. First go to the top of the file and copy and paste the following code to create human_female_plate_DC.

human_female_plate_DC = DisplayContext("human_female.mesh", True)
human_female_plate_DC.addSubmesh(DisplayContext.Submesh("bodyShape-lib.0", "human_female.skin_material"))
human_female_plate_DC.addSubmesh(DisplayContext.Submesh("head_aShape-lib.0", "human_female.head_a_material"))
human_female_plate_DC.addSubmesh(DisplayContext.Submesh("plate_b_tunicShape-lib.0", "human_female.plate_b_material"))
human_female_plate_DC.addSubmesh(DisplayContext.Submesh("plate_b_helmetShape-lib.0", "human_female.plate_b_material"))
human_female_plate_DC.addSubmesh(DisplayContext.Submesh("plate_b_pantsShape-lib.0", "human_female.plate_b_material"))
human_female_plate_DC.addSubmesh(DisplayContext.Submesh("plate_b_bootsShape-lib.0", "human_female.plate_b_material"))
human_female_plate_DC.addSubmesh(DisplayContext.Submesh("plate_b_glovesShape-lib.0", "human_female.plate_b_material"))

As you can see, this will create a human_female with a full set of plate armor.

Creating the template

Next you need to create the actual template for you mob. Copy all of the code that you've been looking at for the human female leather mob:

tmpl = Template("Human Female Leather")
tmpl.put(WorldManagerClient.NAMESPACE, WorldManagerClient.TEMPL_DISPLAY_CONTEXT, human_female_base_DC)
tmpl.put(WorldManagerClient.NAMESPACE, WorldManagerClient.TEMPL_OBJECT_TYPE, ObjectTypes.mob)
tmpl.put(InventoryClient.NAMESPACE, InventoryClient.TEMPL_ITEMS,
         "*Leather Tunic; *Leather Pants; *Leather Boots")
ObjectManagerClient.registerTemplate(tmpl)

Create a "human female fighter" section below and paste your text. You're going to modify this code to create your mob.

In the first two lines, you just need to change the template name and display context.

tmpl = Template("Human Female Fighter")
tmpl.put(WorldManagerClient.NAMESPACE, WorldManagerClient.TEMPL_DISPLAY_CONTEXT, human_female_plate_DC)

This gives your mob the name "Human Female Fighter", so the server can differentiate it from other Templates being used. The name you use for the Template must be unique. This also gives your mob the display context that you've created. When players see this mob in the world they will see the "Human Female Fighter" above her head and know to run in fear.

Next you will want to give your mob a weapon. Since you've already added armor onto your display context, you do not need to add any armor. Scroll down to the swords section and pick what sword you want your mob to have. You can look at them in the model viewer of course. sword7 is a nice saber.

tmpl.put(InventoryClient.NAMESPACE, InventoryClient.TEMPL_ITEMS, "*sword7")

Next copy and paste the following lines from one of the other mob templates:

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, "attackable", Boolean(True))
tmpl.put(CombatClient.NAMESPACE, "combat.mobflag", Boolean(True))
tmpl.put(WorldManagerClient.NAMESPACE, "clickCommand", "/click")

These lines give your mob health and mana as well as making it attackable. This is also where the mob is given abilities. If you want to have a stronger attack ability, you can create one in MV_HOME/config/ability_db.py.

Once you have done that, this part is complete, your mob is now in the database and ready for use in the world.

Placing the Mob in the World

Open mobserver.py and add code to the end of the file.

This time I will give you code to input and then explain what it means (I like to try add a little variety in these long boring tutorials). Add the following (you can cut and paste this code):

class Hf_fighterFactory (ObjectFactory):
    def makeObject(self, spawnData, instanceOid, loc):
        obj = ObjectFactory.makeObject(self, spawnData, instanceOid, loc)
        return obj

ObjectFactory.register("Hf_fighterFactory", Hf_fighterFactory("Human Female Leather"))

Open instance_load.py and add this code to the end of the file.

hf_fighterLoc = Point(426980, 0, 1030650)
spawnData = SpawnData()
spawnData.setFactoryName("Hf_fighterFactory")
spawnData.setInstanceOid(Long(instanceOid))
spawnData.setLoc(hf_fighterLoc)
spawnData.setNumSpawns(1)
spawnData.setSpawnRadius(1)
spawnData.setRespawnTime(60000)
MobManagerClient.createSpawnGenerator(spawnData)

Before you try this code, you must do something important. Look at this line:

hf_fighterLoc = Point(426860, 0, 1031650)

That line defines where the spawn generator will be located. If you have changed your world you will need to change the Point values. Here is how you do it:

  1. Log into your world.
  2. Stand where you want the spawn generator to be.
  3. Type "/info".
  4. Record the location displayed in the line:
    Target Position: (<some number>, <some number>, <some number>)
  5. Quit the client (exit your world) and enter these values as the arguments to the Point function. Leave y as 0 so the mob will stay on the ground.

If you would rather set the spawn generator's location in the World Editor, you can add a marker where you want it, in this case called "hfmarker", and replace the above line with:

hf_fighterLoc = instance.getMarker("hfmarker").getPoint().clone()
hf_fighterLoc.setY(0)

Now look at these lines of code in mobserver.py:

class Hf_fighterFactory (ObjectFactory):
    def makeObject(self, spawnData, instanceOid, loc):
        obj = ObjectFactory.makeObject(self, spawnData, instanceOid, loc)
        return obj

This code can set the behavior for mobs created by this spawn generator. In this example, there are no behaviors defined, so there is nothing extra listed there. For some other examples with behaviors, look through mobserver.py. You could copy the wolves' behavior to make the fighter patrol around a radius and fight back when you attack (make sure you change wolfLoc to hf_fighterLoc).

ObjectFactory.register("Hf_fighterFactory", Hf_fighterFactory("Human Female Leather"))

This line registers the Hf_fighterFactory ObjectFactory so it can be referenced later when the spawn generator is created. The "Human Female Leather" is a template name and must match the name specified previously in templates.py.

Let's look at instance_load.py in detail:

spawnData = SpawnData()
spawnData.setFactoryName("Hf_fighterFactory")

These lines create a SpawnData and set the factory to be used by the spawn generator. This factory was registered in mobserver.py. Now look at these lines of code:

spawnData.setInstanceOid(Long(instanceOid))
spawnData.setLoc(hf_fighterLoc)

These lines set the spawn generator location: the instance and location within the instance.

spawnData.setNumSpawns(1)
spawnData.setSpawnRadius(1)
spawnData.setRespawnTime(60000)

These lines set some of the details about the spawn generator. Specifically, how many mobs are spawned, the maximum distance from the generator they are spawned, and how long after death until respawn. You can set these to whatever suits your situation. For this example, leave them as is, but feel free to change the values to see what the results are like.

MobManagerClient.createSpawnGenerator(spawnData)

Finally, the spawn generator is created. The instance_load.py script is running in the instance plugin, so the mob plugin API (MobManagerClient) is used to create the spawn generator.

Setting mob orientation

By default, mobs will all be facing the same direction. To set the orientation (facing direction) of a mob, use the setOrientation() method of the mob's world node (multiverse.server.engine.BasicWorldNode). To get the world node, call getWorldNode() on the multiverse.server.objects.ObjectStub.

class myMob (ObjectFactory):
def makeObject(self, loc):
  obj = ObjectFactory.makeObject(self, loc)
  mobOrient = Quaternion.fromAngleAxisDegrees(90, MVVector(0,1,0))
  obj.getWorldNode().setOrientation(mobOrient)
  obj.updateWorldNode()
  .
  .
  .
  return obj

Seeing Your Mob

When you log into your world you should see a Human Female Fighter mob somewhere around where you spawn (unless you changed the spawn location). If you used the sample world and the location I used here, the fighter will be near the quest giver.

Well that pretty much wraps up this tutorial. If you cannot find the mob, or the server is crashing, please contact with me via the forums, PM, or email me at andrew@doomsberg.com

Personal tools