Prototype Pet System

From Multiverse

Jump to: navigation, search
The code in this article or section has not been verified with Multiverse platform version 1.5. You can help by testing it, and rewriting as necessary.

Contents

Overview

Multiverse developer Draive created a prototype pet system that enables PCs to "tame" mobs and make them into pets.

Setting up the pet system

To set up the pet system, follow these steps:

  1. Edit your world settings file and change your ID number.
  2. Rebuild MARS with the new combat behavior.
  3. Edit the Python scripts
    • Add commands and register each command in proxy.py.
    • Modify CombatBehavior class
    • Modify mob database script
    • Set up stats
  4. Restart servers

Caveats

The code in this prototype example is:

  • Not complete. Specifically, the aggressive mode combat behavior is missing (to make the pet attack anything withing the specified range).
  • Not optimized for speed and has only been tested with one person on the server.
  • Designed and tested with Draive's customized version of MARS. In particular, it uses the character creation system described in the Platform Tutorial.

Using the pet system

Once you have set up the pet system, target a mob and type the command "/pettame" to make the mob your pet.

Then you can give the following commands to your pet:

  • /follow - pet follows you around
  • /stop - pet stops moving
  • /pet attack - pet attacks the mob or PC you target
  • /pet stop attack - pet stops attacking
  • /come - pet comes to you
  • /pet defend - pet will be defensive
  • /pet aggro - pet will attack anyone within the specified radius
  • /petspam - toggle "your pet is being attacked" messages

Code

The code for the pet systems consists of:

  • Python code to add to proxy.py
  • Java code to modify CombatBehavior
  • Python code for mobs_db.py and character_factory

Add command code

In addition to the methods for the slash commands, the following code includes GetTargetPropertyCommand and SetTargetPropertyCommand methods to set properties on a targeted mob.

Add the following code to proxy.py:

class GetTargetPropertyCommand (ProxyPlugin.CommandParser):
    def parse(self, cmdEvent):
        cmd = cmdEvent.getCommand()
        playerOid = cmdEvent.getObjectOid()
        targetOid = cmdEvent.getTarget()
        property = cmd[cmd.index(' ')+1:]
        Log.debug("GetpropertyCommand:" + property )
        property = WorldManagerClient.getObjectProperty(targetOid, property);
        WorldManagerClient.sendObjChatMsg(playerOid, 
                                          1, 
                                          str(property))
        return None
       
class SetTargetPropertyCommand (ProxyPlugin.CommandParser):
    def parse(self, cmdEvent):
        cmd = cmdEvent.getCommand()
        playerOid = cmdEvent.getObjectOid()
        targetOid = cmdEvent.getTarget()     
        splitCmd = cmd.split(" ")
        property = str(splitCmd[1])
        amount = int(splitCmd[2])
        Log.debug("SetpropertyCommand: property")
        WorldManagerClient.setObjectProperty(targetOid, 
                                             property,
                                             amount);
        WorldManagerClient.sendObjChatMsg(playerOid, 
                                          1, 
                                          "set property: for " + property + " " +  str(amount))
        return None       
              
class PetFollowCommand (ProxyPlugin.CommandParser):
   def parse(self, cmdEvent):
       cmd = cmdEvent.getCommand()
       playerOid = cmdEvent.getObjectOid()
       targetOid = cmdEvent.getTarget()
       petOid = WorldManagerClient.getObjectProperty(playerOid, "pet.mypet");       
       targetObj = ObjectStub(petOid, None, "")
       playerHandle = EntityHandle(playerOid)
       if (petOid == 0):
            WorldManagerClient.sendObjChatMsg(playerOid, 
                                              1, 
                                              "You have no pet")     
       else:
  # TODO - make pet speed = player speed
            followCmd = BaseBehavior.FollowCommandMessage(targetObj, playerHandle, 3000)
            Engine.getAgent().sendBroadcast(followCmd)
            WorldManagerClient.sendObjChatMsg(playerOid, 
                                              1, 
                                              "Your pet is now following you.")
       return None

class PetStopCommand (ProxyPlugin.CommandParser):
   def parse(self, cmdEvent):
       cmd = cmdEvent.getCommand()
       playerOid = cmdEvent.getObjectOid()
       targetOid = cmdEvent.getTarget()
       petOid = WorldManagerClient.getObjectProperty(playerOid, 
                                                     "pet.mypet");
       targetObj = ObjectStub(petOid, None, "")
       if (petOid == 0):
            WorldManagerClient.sendObjChatMsg(playerOid, 
                                              1, 
                                              "You have no pet.")     
       else:
            stopCmd = BaseBehavior.StopCommandMessage(targetObj)
            Engine.getAgent().sendBroadcast(stopCmd)
            WorldManagerClient.sendObjChatMsg(playerOid, 
                                              1, 
                                              "Your pet will no longer follow you.")
       return None
       
class PetAttackCommand (ProxyPlugin.CommandParser):
   def parse(self, cmdEvent):
       cmd = cmdEvent.getCommand()
       playerOid = cmdEvent.getObjectOid()
       targetOid = cmdEvent.getTarget()
       petowner = "pet.owner1"
       property = WorldManagerClient.getObjectProperty(targetOid, petowner);
       attack = "attack ability"
       petOid = WorldManagerClient.getObjectProperty(playerOid, "pet.mypet");
###    WorldManagerClient.sendObjChatMsg(playerOid, 
                                         1, 
                                         "Debug pet attack message: petOid =" +
                                         str(petOid) + "target Oid = " +
                                         str(targetOid) + "pet owner =" +
                                         str(property) + "playerOid =" +
                                         str(playerOid))
       if (petOid == targetOid) or (playerOid == targetOid):
            WorldManagerClient.sendObjChatMsg(playerOid, 
                                              1, 
            "Your pet loves you too much to be self-destructive.")       
            return None   
       if (petOid == 0):
            WorldManagerClient.sendObjChatMsg(playerOid, 
                                              1, 
                                              "You have no pet")           
       else:
            amount = 0
            property = "pet.aggression"
            WorldManagerClient.setObjectProperty(petOid, property, amount);       
            CombatClient.autoAttack(petOid, targetOid, True)
            WorldManagerClient.sendObjChatMsg(playerOid, 
                                              1, 
            "You command your pet to pwn your target.")
       return None
     
class PetStopAttackCommand (ProxyPlugin.CommandParser):
   def parse(self, cmdEvent):
       cmd = cmdEvent.getCommand()
       playerOid = cmdEvent.getObjectOid()
       targetOid = cmdEvent.getTarget()
       petOid = WorldManagerClient.getObjectProperty(playerOid, 
                                                     "pet.mypet");
       targetObj = ObjectStub(petOid, None, "")
       if (petOid == 0):
            WorldManagerClient.sendObjChatMsg(playerOid, 
                                              1, 
                                              "You have no pet")     
       else:
            amount = 1
            property = "pet.aggression"
            WorldManagerClient.setObjectProperty(petOid, property, amount);
            CombatClient.autoAttack(petOid, targetOid, False)
            WorldManagerClient.sendObjChatMsg(playerOid, 
                                              1, 
             "You command your pet to stop attacking. Hopefully it will live.")
       return None
  
class PetSummonCommand (ProxyPlugin.CommandParser):
   def parse(self, cmdEvent):
       cmd = cmdEvent.getCommand()
       playerOid = cmdEvent.getObjectOid()
       targetOid = cmdEvent.getTarget()
       petOid = WorldManagerClient.getObjectProperty(playerOid, "pet.mypet");
       if (petOid == 0):
            WorldManagerClient.sendObjChatMsg(playerOid, 
                                              1, 
                                              "You have no pet")     
       else:
        WorldManagerClient.reparentWorldNode(petOid, playerOid)
       return None
       
class SetOwnerCommand (ProxyPlugin.CommandParser):
    def parse(self, cmdEvent):
        cmd = cmdEvent.getCommand()
        playerOid = cmdEvent.getObjectOid()
        targetOid = cmdEvent.getTarget()
        playerOid2 = int(cmdEvent.getObjectOid())
        targetOid2 = int(cmdEvent.getTarget())
        petowner = "pet.owner1"
        pet = "pet.mypet"
        Log.debug("SetpropertyCommand: property")
        property = "combat.level"
        ownerlv = WorldManagerClient.getObjectProperty(playerOid, property);
        petlv = WorldManagerClient.getObjectProperty(targetOid, property);
        playerHandle = EntityHandle(playerOid)
        if (ownerlv >= petlv):
          WorldManagerClient.setObjectProperty(targetOid, petowner, playerOid2);
          WorldManagerClient.setObjectProperty(playerOid, pet, targetOid2);
          targetObj = ObjectStub(targetOid, None, "")
          followCmd = BaseBehavior.FollowCommandMessage(targetObj, playerHandle, 3000)
          Engine.getAgent().sendBroadcast(followCmd)
          WorldManagerClient.sendObjChatMsg(playerOid, 
                                            1, 
                                            "Setting you as owner of this pet.")
        else:
          WorldManagerClient.sendObjChatMsg(playerOid, 
                                            1, 
                                            "Gain a few more levels, chief.")   
        return None
       
class PetSetDefensiveCommand (ProxyPlugin.CommandParser):
    def parse(self, cmdEvent):
        cmd = cmdEvent.getCommand()
        playerOid = cmdEvent.getObjectOid()
        petOid = WorldManagerClient.getObjectProperty(playerOid, "pet.mypet");
        property = "pet.aggression"
        amount = 0
        if (petOid != 0):
          WorldManagerClient.setObjectProperty(petOid, property, amount);
          WorldManagerClient.sendObjChatMsg(playerOid, 
                                            1, 
                                            "Your pet will now defend itself.")
        else:
            WorldManagerClient.sendObjChatMsg(playerOid, 
                                              1, 
                                              "You have no pet.")   
        return None
       
class PetSetPassiveCommand (ProxyPlugin.CommandParser):
    def parse(self, cmdEvent):
        cmd = cmdEvent.getCommand()
        playerOid = cmdEvent.getObjectOid()
        petOid = WorldManagerClient.getObjectProperty(playerOid, "pet.mypet");
        property = "pet.aggression"
        amount = 1
        if (petOid != 0):
          WorldManagerClient.setObjectProperty(petOid, property, amount);
          WorldManagerClient.sendObjChatMsg(playerOid, 
                                            1, 
                                            "Your pet is now a hippy.")
        else:
            WorldManagerClient.sendObjChatMsg(playerOid, 
                                              1, 
                                              "You have no pet")   
        return None
       
class PetSetAggressiveCommand (ProxyPlugin.CommandParser):
    def parse(self, cmdEvent):
        cmd = cmdEvent.getCommand()
        playerOid = cmdEvent.getObjectOid()
        petOid = WorldManagerClient.getObjectProperty(playerOid, "pet.mypet");
        property = "pet.aggression"
        amount = 2
        if (petOid != 0):       
          WorldManagerClient.setObjectProperty(petOid, property, amount);
          WorldManagerClient.sendObjChatMsg(playerOid, 
                                            1, 
                                            "Your pet is now mean as hell.")
        else:
            WorldManagerClient.sendObjChatMsg(playerOid, 
                                              1, 
                                              "You have no pet.")         
        return None
       
class PetSpamCommand (ProxyPlugin.CommandParser):
    def parse(self, cmdEvent):
        cmd = cmdEvent.getCommand()
        playerOid = cmdEvent.getObjectOid()     
        property = "pet.spam"
        amount = WorldManagerClient.getObjectProperty(playerOid, property);
        petOid = WorldManagerClient.getObjectProperty(playerOid, "pet.mypet");
        if (petOid != 0): 
          if (amount == 1):
            WorldManagerClient.setObjectProperty(playerOid, property, 0);
            WorldManagerClient.sendObjChatMsg(playerOid, 1, "spam off")
          else:
            WorldManagerClient.setObjectProperty(playerOid, property, 1);   
            WorldManagerClient.sendObjChatMsg(playerOid, 1, "spam on")   
       
        else:
            WorldManagerClient.sendObjChatMsg(playerOid, 
                                              1, 
                                              "You have no pet and you are lame.")         
        return None

Register commands

Register the commands by adding the following lines to proxy.py:

proxyPlugin.registerCommand("/pettame", SetOwnerCommand())
proxyPlugin.registerCommand("/follow", PetFollowCommand())
proxyPlugin.registerCommand("/stop", PetStopCommand())
proxyPlugin.registerCommand("/pet attack", PetAttackCommand())
proxyPlugin.registerCommand("/pet stop attack", PetStopAttackCommand())
proxyPlugin.registerCommand("/come", PetSummonCommand())
proxyPlugin.registerCommand("/pet defend", PetSetDefensiveCommand())
proxyPlugin.registerCommand("/pet aggro", PetSetAggressiveCommand())
proxyPlugin.registerCommand("/petspam", PetSpamCommand())

Modify CombatBehavior class

Replace the onMessage method in multiverse.mars.behaviors.CombatBehavior with the following code:

    public boolean onMessage(Message msg, int flags) {

      long owner = (Integer) WorldManagerClient.getObjectProperty(obj.getOid(), 
                                                                  "pet.owner1");
      int aggression = (Integer) WorldManagerClient.getObjectProperty(obj.getOid(), 
                                                                      "pet.aggression");
      if (owner != 0){
         int spam = (Integer) WorldManagerClient.getObjectProperty(owner, "pet.spam");   
      }
        int spam = 0;
      
       if (msg instanceof CombatClient.DamageMessage) {
         CombatClient.DamageMessage dmgMsg = (CombatClient.DamageMessage)msg;
         
         switch (aggression){
         // case 0 = defensive , case 1 = passive , case 2 = aggressive
         case 0: 
               Engine.getAgent().sendBroadcast(new BaseBehavior.FollowCommandMessage(obj, 
                                    new EntityHandle(dmgMsg.getAttackerOid()), 
                                    6000));
               CombatClient.autoAttack(session, obj.getOid(), dmgMsg.getAttackerOid(), true);
//            int spam = 0;
               if (spam == 1){
               WorldManagerClient.sendObjChatMsg(owner, 1, "Your pet is under attack!" + aggression);
            }
            break;
			case 1:           
			  CombatClient.autoAttack(obj.getOid(), dmgMsg.getAttackerOid(), false);
			  if (spam == 1) {
				  WorldManagerClient.sendObjChatMsg(owner, 1, "Your pet is under attack!" + aggression);
			  }
			  break;

//         case 2:            
//               //TODO - put in stuff to make him attack ppl who come in range
//               CombatClient.autoAttack(obj.getOid(), dmgMsg.getAttackerOid(), true);
//                        if (spam){   
//            WorldManagerClient.sendObjChatMsg(owner, 1, "Your pet is attacking someone..");
//         
         default:
		   Engine.getAgent().sendBroadcast(new BaseBehavior.FollowCommandMessage(obj, 
								new EntityHandle(dmgMsg.getAttackerOid()), 
								6000));

		   CombatClient.autoAttack(obj.getOid(), dmgMsg.getAttackerOid(), true);
		   if (spam == 1) {
			   WorldManagerClient.sendObjChatMsg(owner, 1, "Your pet is under attack!" + aggression);
		   }
            break;
         }
      }
      

   return true;
    }

Modify mob database script

To make sure it doesn't pull nulls, put these inside your mobs in mobs_db.py:

yourmob.setProperty("pet.owner1", Integer(0))
yourmob.setProperty("pet.aggression", Integer(0))
yourmob.setProperty("combat.level", Integer(60))

Set up stats

Now to set up yourself with the stats. Please remember to edit world_settings.xml to make a new ID so that the new character gets loaded. Put this inside your toon in character_factory:

obj.setProperty("pet.mypet", Integer(0))
obj.setProperty("combat.level", Integer(61))

The player has to have a pet.mypet ID to identify his pet. When the system is installed, if you don't put that in character_factory.py, then it will pull nulls when you went to test the system and possibly crash it.

Basically, the player character has to start with a pet ID zero (or any integer), so that when the system calls getProperty(pet.mypet) there is something there.

The system will not see this information unless you change your player ID in the world settings file, and the system creates a new character.

Personal tools