Petshop! (Mounts and Scavenger Mode)


Author: mythanical
Created: 2013-08-07T16:00:46-0400
Edited: 2014-01-12T01:36:57-0500
Denizen Version: 0.9.3
Views: 115
Downloads: 1246
Likes: 4


WGET
Description: Petshop
=======
Citizens 2 (build #1045)
Sentry (v. 1.8.0)
Denizen 0.9.2 (build #1417)

To assign to an NPC, select the NPC and type:
/npc assign --set "petshop"

NOTE: Let me know if there are still issues teleporting pets back.

Description:
---------------
Always wanted a "Pet Shop" in your town where players can come from all over the world to buy common, exotic and rare animals (or monsters)? Well now you can! This script will let YOU decide which pets you want to make available for sale, how much they will cost and also allow you to set a pet limit (so the crazy cat lady can't buy 200 ocelots). Then you can buy a custom leash that will allow you to take your pet for a ride!

NEW: Pets can 'scavenge' for items. You can set the frequency (how often the pet should scavenge) and the percentage chance of success that they will find something. Pets must be on 'follow' and the player must obviously be online. Go through the list of items to make sure you're happy with what the pets will be giving players.

This script includes two NPC scripts (you only assign the "petshop" script):
1) Pet Shop Keeper - Enable the sales process and enforce the limit on number of pets.
2) Pet - Primarily sets up the pet's behaviour, follow/stop, mounting and "bye" feature.

Both scripts have variables you might want to consider changing to suit your server!

Other Features:
-------------------
* If the player hates their pet, they can type "bye (petname)" and it'll disappear. You can enable whether you want to refund a certain percentage of the money the player paid.
* Pets can be set to follow / stay
* Pets responds with appropriate sound effect when player's interact with them.
* Players can talk to the shop keeper and say 'teleport' to have lost pets teleported back.
* Pets can be mounted!
* Admin can control whether a custom "leash" is required that can be purchased from the pet shop owner to mount pets
* Admin can control which npc types can be mounted. e.g. exclude bats
* Pets can scavenge and bring their master random items in a controlled list.

Requirements: For this script to work, you will need:
* Citizens 2 (http://ci.citizensnpcs.com/view/All/job/Citizens2/)
* Sentry (http://wiki.citizensnpcs.com/Sentry)
* Denizen (http://ci.citizensnpcs.com/job/Denizen%20Developmental/)
* An economy to deal with money as a method of payment (like iConomy)

# Pet Shop
# ========
#
# Description: 
# ------------
# Always wanted a "Pet Shop" in your town where players can come from
# all over the world to buy common, exotic and rare animals (or monsters)? Well now
# you can! This script will let YOU decide which pets you want to make available for sale,
# how much they will cost and also allow you to set a pet limit (so the crazy cat lady can't
# buy 200 ocelots).
#
# Pets can 'scavenge' for items..the percentage chance of them finding something and the
# frequency of when they should scavenge is adjustable.
#
# This script includes two NPC scripts (you only assign the "petshop" script):
#       1) Pet Shop Keeper - Enable the sales process and enforce the limit on number of pets.
#       2) Pet - Primarily handles the pet's behaviour, follow/stop, scavenge and "bye" feature.
#
# Other Features:
# ---------------
#   * If the player doesn't want their pet any more, they can type "bye (petname)" and it'll
#     disappear. You can enable whether you want to refund a certain percentage of the money
#     the player paid.
#   * Pets can be set to follow / stay
#   * Pets responds with appropriate sound effect when player's interact with them.
#   * Players can talk to the shop keeper and say 'teleport' to have lost pets teleported back.
#   * Pets can be mounted!
#   * Admin can control whether a special "emerald" is required that can be purchased from the petshop
#     owner to mount pets
#   * Admin can control which npc types can be mounted. e.g. exclude bats
#   * Pets can scavenge and bring their master random items in a controlled list.
#
# @author mythanical
# @script version 0.8.6
# @last-updated 10 January 2014
# @irc EsperNet IRC Network #denizen-dev
# @Minecraft Server - minecraft.geek.nz
# @Donate Bitcoin: 1Fzacc2gZ5NGRMXg5jWP6NcUkWei34xjzt
# @Donate Litecoin: LhsaGa1QzmVLjMYwg4ZPTVnmSgnBDGc75U

"Set Global Flags":
  type: world
  events:
    on reload scripts:
    # 'default constants' are separate for each assignment - so this means we have to put these two values
    # into this section as 'global flags' because they are referenced in both assignments below and save us
    # from replicating them across two scripts and possibly giving them inconsistent values.
    #
    # If you set the refund flag to 'yes' and specify a percentage, it means the player will get back that 
    # portion of their money when they 'let their pet go'.
    - flag global "Allow Pet Refund:Yes"
    - flag global "Refund Percentage:80"
 
    # If you enable scavenger, it means there is a chance that the pet will bring their owner a gift every once in a while if they
    # are FOLLOWING the player. This will encourage players to have their pets follow them more often.
    # Note: Every pet has a chance to return something, so more pets means higher chance of loot.
    #
    # The default frequency is set to run a task once every 10 minutes that will then use the percentage chance further below
    # to determine if the pet successfully scavenged something.
    # Change the value to '0' (without the single quotes) to disable scavenging.
    - flag global Scavenge_Frequency:10m
 
    # Specify the percentage (%) chance of a pet finding something.
    - flag global Scavenge_Find_Chance:30
 
    # Here you can list out all the items that can be scavenged. NOTE: Leave the first flag, it's to clear the list and
    # reset it. If you remove the first flag it'll keep on doubling up items every time you refresh.
    - flag global Scavenge_Loot:!
    - flag global Scavenge_Loot:|:arrow|baked_potato|bone|book|bowl|bread|cake|carrot|chainmail_helmet|coal|cocoa|compass|cookie|egg|emerald|feather|fishing_rod|flower_pot|flint_and_steel|gold_axe|gold_ore|iron_ingot|iron_pickaxe|leather|lever|map|melon|melon_seeds|mushroom_soup|painting|pumpkin_pie|raw_beef|raw_chicken|raw_fish|red_mushroom|rotten_flesh|seeds|shears|slime_ball|spider_eye|step|stick|stone_hoe|stone_spade|stone_sword|string|sugar|sugar_cane|torch|vine|watch|wheat|wood|wood_door|wool

"Petshop":
  type: assignment

  default constants:
  
    # Pet shop's Name
    Petshop Name: "Pick-A-Pet"
 
    # The following NPC types are available as part of Citizens: http://wiki.citizensnpcs.com/Types
    # --------------------------------------------------------------------------------------------------------
    # blaze, bat, cave_spider, chicken, creeper, cow, enderman (goes crazy in rain), 
    # ender_dragon (do not recommend), ghast (do not recommend), giant (massive zombie!), iron_golem, 
    # magma_cube (careful! damages nearby players), mushroom_cow, ocelot, pig, pig_zombie, 
    # player (will use skin of player with same name), sheep, silverfish, squid (can't walk on land...duh),
    # snowman, wolf, skeleton, slime, spider, witch, witherboss (does not move), villager, 
    # zombie (burns in sunlight, but invulnerable)
    # --------------------------------------------------------------------------------------------------------
 
    # These are the pets that's been enabled and can be purchased. Note: Case sensitive, so leave lower case.
    Pets: ocelot|silverfish|wolf|cow|creeper|bat|chicken|cave_spider|iron_golem|sheep|villager
 
    # Make sure to uncomment the pet and adjust the price to suit your server.
    # ------------------------------------------------------------------------
    # Blaze Price: 800
    Bat Price: 400
    Cave_Spider Price: 500
    Chicken Price: 50
    Creeper Price: 1000
    Cow Price: 300
    # Enderman Price: 3000
    # Ender_Dragon Price: 20000
    # Ghast Price: 15000
    # Giant Price: 25000
    Iron_Golem Price: 800
    # Magma_Cube Price: 900
    # Mushroom_Cow Price: 1000
    Ocelot Price: 100
    # Pig Price: 75
    # Pig_Zombie Price: 700
    # Player Price: 500
    Sheep Price: 75
    Silverfish Price: 650
    # Squid Price: 200
    # Snowman Price: 200
    Wolf Price: 150
    # Skeleton Price: 750
    # Slime Price: 475
    # Spider Price: 450
    # Witch Price: 1200
    # Witherboss Price: 2000
    Villager Price: 500
    # Zombie Price: 500
 
    # Number of pets allowed per player
    Pet Limit: 2
 
    # Pets can carry items for players. The setting below controls 
 
    # If you specify a price here, then players will need to buy a special emerald for the specified price below, which they need
    # to hold in their hand before they can mount pets. NOTE: Make sure this corresponds with the "Pets Rideable" and 
    # "Special Emerald Required" constant values in the "Pet Script" further below.
    Emerald Name: Emerald of Animal Empathy
    Emerald Price: 5000
    Emerald Buy Again Price: 1000
    
  interact scripts:
  - 10 Adopt a Pet

  actions:
    on assignment:
    # These triggers enable interaction with an NPC via chatting, clicking, entering proximity and when damaging the NPC.
    - trigger name:chat toggle:true
    - trigger name:click toggle:true
    - trigger name:proximity toggle:true
    
    on click:
    # When the NPC is clicked, run the following commands.
    - run "Petshop Dialog Checker"
    - zap step:1 "[email protected] a Pet"

"Adopt a Pet":
  type: interact
  
  steps:
    1:
      proximity trigger:
        entry:
          script:
          # On entering proximity, run the following IF statement to check if the player currently owns any pets. 
          # The default proximity range is set in Denizen\config.yml
          - if <player.flag[Pets].size> >= 1 {
            - random {
              - chat "<yellow>Welcome back <white><player.name><yellow>! How is it going with <white><player.flag[Pets].aslist.formatted><yellow>?"
              - if <player.flag[PetEmeraldBought]> == null && "<npc.constant[Emerald Price]>" > 0 {
                - chat "<yellow>Want to use your pets as mounts? Type '<light_purple>emerald<yellow>' to buy one for <gold><npc.constant[Emerald Price]><yellow>."
                }
                else chat "<yellow>If you<&sq>ve been a <&sq>Bad, Bad Owner!<&sq> and lost your pet, just come to me and type <&sq><white><italic>teleport<reset><yellow><&sq>."
              }
            }
 
            else if <player.flag[PetEmeraldBought]> != null {
              - chat "<yellow>If you ever lose your emerald for mounting pets, you can buy another one for <white><npc.constant[Emerald Buy Again Price]><yellow>." }
 
            else chat "<yellow>Welcome to <npc.constant[Petshop Name]> <white><player.name><yellow>! Talk to me if you want to buy a pet."

      chat trigger:
        'Buy Pet':
          trigger: "I'm interested in a /regex:^(<npc.constant[Pets]>)$/."
          script:
          - flag <player> "price:<npc.constant[<context.message> price]>"
          - flag <player> item:<context.message>
          - chat "<yellow>Ok. They are <gold><player.flag[price]><yellow> each. Would you like to adopt one?"

        'Buy Emerald':
          trigger: "Can I please buy an /emerald/?"
          script:
          - if <player.flag[PetEmeraldBought]> != null && "<npc.constant[Emerald Buy Again Price]>" > <player.money>
            chat "<yellow>I<&sq>m sorry, but you don<&sq>t have enough money to buy another <light_purple><npc.constant[Emerald Name]><yellow>. Come back later when you do."
 
            else if <player.flag[PetEmeraldBought]> == null && "<npc.constant[Emerald Price]>" > <player.money>
            chat "<yellow>I<&sq>m sorry, but you don<&sq>t have enough money to buy a <light_purple><npc.constant[Emerald Name]><yellow>. Come back later when you do."
 
            else if <player.flag[PetEmeraldBought]> != null {
                - take money "qty:<npc.constant[Emerald Buy Again Price]>"
                - narrate "<white><npc.name><red> sells you another <light_purple><npc.constant[Emerald Name]><red> for <gold><npc.constant[Emerald Buy Again Price]><red> <player.money.currency>."
                - give "[email protected] Emerald" }
 
            else {
              - ^take money "qty:<npc.constant[Emerald Price]>"
              - ^flag PetEmeraldBought
              - ^narrate "<white><npc.name><red> sells you a <light_purple><npc.constant[Emerald Name]><red> for <gold><npc.constant[Emerald Price]><red> <player.money.currency>."
              - give "[email protected] Emerald"
            }

        'Teleport Pets':
          trigger: "Please /teleport/ my pets back to me!"
          script:
          - if <player.flag[Pets]> == null narrate "<red>You don<&sq>t have any pets to teleport."
            else {
              - chat "<yellow>Give me a couple of seconds to summon them..."
              - foreach <player.flag[Pets].aslist> {
                - execute as_server "npc sel <%value%.id>"
                - teleport %value% location:<player.location.simple>
                - execute as_server "sentry guard <player.name>"
                - flag %value% Following
                }
            }

        'Enough Money':
          trigger: "/Yes/"
          script:
          - if <player.flag[price]> > <player.money>
            chat "<yellow>I'm sorry, but you don't have enough money to buy a <white><player.flag[item]><yellow>. Come back later when you do."
 
            else {
              - chat "<yellow>Great! And what will you name your new <white><player.flag[item]><yellow>?"
              - narrate "<red>NOTE - No longer than 15 characters and no spaces."
              - zap step:2 }

        'No Thanks':
          trigger: "/No/"
          script:
          - random {
            - chat "<yellow>Oh well, I'm sure someone else will come and adopt them."
            - chat "<yellow>Awww, they liked you! Nevermind, someone else will come and get them soon enough."
            - chat "<yellow>Dang, I was sure you were going to walk out of here with a pet! Maybe next time?"
            - chat "<yellow>How can you say <&sq>no<&sq> to these cute pets?! Haha, nevermind. Hopefully next time!"
 
            - if <player.chat_history[1]> contains <context.message>
              chat "<yellow>You sure you don<&sq>t want a <white><player.chat_history[2]><yellow>? Ok then, hopefully they<&sq>ll be here when you change your mind!"
              else chat "<yellow>That<&sq>s ok, a pet like that will never needs to wait here for very long!"
 
            - if <player.chat_history[1]> contains <context.message>
              chat "<yellow>Oh well, off to the slaughter house with you <white><player.chat_history[2]><yellow>...just joking!"
              else chat "<yellow>The poor thing.. look at them, just standing there, watching you with hopeful eyes.. so lonely.."
            }
          
        'What Did You Say':
          trigger: /REGEX:\w+/
          # This is a catch-all trigger that will repeat what the player said if what they
          # typed didn't match any of the chat triggers above.
          script:
          - chat "<yellow>Sorry <white><player.name><yellow>, but I don<&sq>t know what '<white><context.message><yellow>' means."

    2:
      chat trigger:
        'Name Your Pet':
          trigger: /REGEX:\w+/
          script:
          - flag <player> PetName:<context.message>
          - run "Buy a Pet" def:<player.flag[item]>|<player.flag[price]>|<player.flag[PetName]>
          - zap step:1
          - flag <player> item:!
          - flag <player> price:!
          - flag <player> PetName:!

      proximity trigger:
        exit:
          script:
          - zap step:1

"Petshop Dialog Checker":
  type: task
  speed: 0

  script:
  # This script handles the basic interaction with the 'petshop owner'. The NPC checks if the player has any pets already or
  # whether they have purchased an 'emerald' and chooses a couple of responses from each of those. This is to give the 
  # player some feedback so they know how they are supposed to interact with the NPC.
 
  - if <player.flag[Pets].size> >= "<npc.constant[Pet Limit]>" {
    - if "<global.flag[Allow Pet Refund]>" == "Yes" {
      - chat "<yellow>I cannot sell you any more pets. However you can get a <white><global.flag[Refund Percentage]>%<yellow> refund if you let a pet go."
      - narrate "<red>To get the refund, interact with your pet and type in <white>bye<red> followed by the pet<&sq>s name. e.g. '<white>bye <npc[<player.flag[pets].aslist.get[1]>].name><red>'."
      - zap "[email protected] a Pet" step:1 }
 
      else {
        - chat "<yellow>I<&sq>m sorry <white><player.name><yellow>, but you cannot buy any more pets."
        - narrate "<red>To let a pet go, interact with your pet and type in <white>bye<red> followed by the <white>pet<&sq>s name<red>. e.g. '<white>bye <npc[<player.flag[pets].aslist.get[1]>].name><red>'."
        - zap "[email protected] a Pet" step:1 }
    }
 
    else {
      - chat "<yellow>Looking for a companion? We have the following types of pets available<&co>"
      - chat "<light_purple><npc.constant[Pets].aslist.formatted>"
      - if "<npc.constant[Emerald Price]>" > 0 {
        - if <player.flag[PetEmeraldBought]> == null
          narrate "<red>Say a pet type to get a price or type '<white>emerald<red>' to buy one for <gold><npc.constant[Emerald Price]><red> <player.money.currency> (mount pets)."
 
          else narrate "<red>Say a pet type to get a price or type '<white>emerald<red>' to buy another for <gold><npc.constant[Emerald Buy Again Price]><red> <player.money.currency>." }
 
        else narrate "<red>Say a pet type to get a price."
      - zap "[email protected] a Pet" step:1
    }

"Buy a Pet":
    type: task

    script:
    - ^take money qty:%2%
    # Store the price paid for the pet in a global flag so we can use it in the Pet Script below to 
    # calculate the refund (if enabled).
    - ^flag global PetPrice_<player>:%2%
    - ^execute as_npc "npc create %3% --at <npc.location.simple> --type %1%"
    - ^execute as_npc "npc owner <player.name>"
 
    # The only way I could get the pets to follow the player properly was to turn them into Sentries. So these
    # few commands will enable sentry, tell it to guard (follow) the player, disable retaliation when the owner
    # is attacked and make the pets invincible.
    - ^execute as_npc "trait sentry"
    - ^execute as_npc "sentry guard <player.name>"
    - ^execute as_npc "sentry retaliate false"
    - ^execute as_npc "sentry invincible true"
    - ^execute as_npc 'npc assign --set "Pet Script"'
 
# The script below is the assignment the pet will get. This controls their follow/stop, mounting, starting the
# scavenger mode if disabled, letting the pet go (bye) and refunding player if enabled.

"Pet Script":
  type: assignment

  default constants:
    # Allow pets to be mounted and controlled by players?
    Pets Rideable: "Yes"
 
    # This allows you to control which pets can be mounted. Types like BATS will allow the players to fly
    # quite high which may not be desirable.
    Mountable Pets: blaze|cave_spider|creeper|cow|giant|iron_golem|mushroom_cow|ocelot|pig|pig_zombie|player|sheep|silverfish|snowman|wolf|skeleton|slime|spider|witch|villager|zombie
 
    # This is to specify the item the Pet owner must hold in their hand when they right click to mount & control the pet.
    # To enable special emerald, set the value just below to "Yes" and make sure the "Lore Emerald Name" matches the lore
    # of the item at the bottom of this script.
    Special Emerald Required: "Yes"
    Lore Emerald Name: Pet Emerald
 
    # Otherwise if you do NOT want to use a special emerald, set the value of "Special Emerald Required" to "No" and specify an alternative
    # item here.
    Alternative Ride Item: bed
 
    # This delay is used to control how long the pet should have its 'chat trigger' active. In other words, when you
    # click the pet, the player will have 15s to 'talk' to the pet. After that, the script zaps back to a click
    # trigger only. The reason for this is that pets were listening all the time and when they are bunched up
    # together it was hard for the player to talk to the right pet cause the wrong one was 'listening' and responding.
    Pet Listen Time: 15s

  actions:
    on assignment:
    - trigger name:click toggle:true
    - trigger name:proximity toggle:true
 
    # The following section deals with some of the different behavioural aspects of NPC types. Some move fast,
    # some move slow. This script checks to see what type of NPC it is and then applies some further customisations
    # to make them seem a bit more consistent.
    - ^execute as_server "npc sel <npc.id>"
    - ^if "<npc.constant[Pets Rideable]>" == "Yes" execute as_server "npc controllable" 
    - ^if <npc.entity_type> contains magma_cube|slime|blaze execute as_server "npc speed 10"
      else if <npc.entity_type> contains horse|giant execute as_server "npc speed 5"
      else if <npc.entity_type> contains witch|skeleton|snowman|sheep|pig|chicken|creeper execute as_server "npc speed 1.3"
      else if <npc.entity_type> contains pig_zombie|mushroom_cow|cow execute as_server "npc speed 1.8"
      else if <npc.entity_type> == villager execute as_server "npc speed 0.7"
      else if <npc.entity_type> == enderman execute as_server "npc speed 3.5"
 
    # These flags are used to manage the pet list for each player and also remember the price for a refund. 
    - ^flag <npc> Price:<global.flag[PetPrice_<npc.owner>]>
    - ^flag global PetPrice_<npc.owner>:!
    - ^flag <npc.owner> Pets:->:<npc>
    - ^flag <npc> Following
    - if <global.flag[Scavenge_Frequency]> != 0 run "Pet Scavenger" id:<npc>_scavenger delay:<global.flag[Scavenge_Frequency]>
    
    # The following proximity action starts the scavenger queue again if the player comes back online
    # or if something went wrong like the server dropped.
    on enter proximity:
    - if <npc.owner> == <player> && <npc.flag[Following]> && <global.flag[Scavenge_Frequency]> != 0 && <queue.exists[<npc>_scavenger]> == false
      run "Pet Scavenger" id:<npc>_scavenger delay:<global.flag[Scavenge_Frequency]>

  interact scripts:
  - 10 Pet Interaction

"Pet Interaction":
  type: interact

  steps:
    1:
      click trigger:
        script:
        - run "Pet Mount or Follow"
        - if <npc.owner> == <player> {
            - zap step:2
            - narrate "<red>If you want to let <white><npc.name><red> go, you<&sq>ve got <white><npc.constant[Pet Listen Time]><red> to type in <&sq><white>bye <npc.name><red><&sq>."
            - wait "<npc.constant[Pet Listen Time]>"
            - zap step:1 }

    2:
      click trigger:
        script:
        - run "Pet Mount or Follow"

      chat trigger:
        'Goodbye Pet':
          trigger: "/bye <npc.name>/"
 
          # When the player triggers this, it will first check to see if the player is the owner. If so it'll then
          # check if the 'Refund Percentage' is larger than 0, if so it'll do a basic calculation depending
          # on how much the pet was purchased for and then give the player a specified percentage of their
          # money back.

          script:
          - if <npc.owner> != <player> narrate "<red>This pet belongs to <white><npc.owner.name><red>, you cannot remove it."
          - ^if <npc.owner> == <player> {
            - if "<global.flag[Refund Percentage]>" > 0 && "<global.flag[Allow Pet Refund]>" == "Yes" 
              {
              - flag "percentage:<m:<global.flag[Refund Percentage]>/100>"
              - flag totalrefund:<m:<npc.flag[Price]>*<player.flag[percentage]>>
              - narrate "<red>Your pet, <white><npc.name><red>, has been removed and you<&sq>ve been refunded <gold><player.flag[totalrefund].asint><red> <player.money.currency>."
              - give money qty:<player.flag[totalrefund].asint>
              - flag percentage:!
              - flag totalrefund:!
              }
            - if <queue.exists[<npc>_scavenger]> queue id:<npc>_scavenger stop
            - flag <npc.owner> Pets:<-:<npc>
            - remove <npc>
            }

"Pet Mount or Follow":
  type: task
  speed: 0

  script:
  # There are a few main components here:
  #
  # 1) First, check to see if the player interacting with the pet is it's owner.. if not, make sure
  #    the pet isn't controllable.
  # 2) If the player is the owner, check to see if the pet is mountable, check to see what the item is that
  #    is needed to mount the pet.
  # 3) If it's not the special item (the 'emerald') then is the player holding the alternative item in
  #    their hand.
  # 4) Else, if it's none of the above, tell the pet to either guard their spot or guard the owner. By guard
  #    I mean follow since that's really what we're getting from using Sentry in this instance.
  #
  # Further down it also either cancels or starts the "scavenging" depending on whether it's been
  # enabled.
 
  - ^if <npc.owner> != <player> {
    - run "Pet Noises" instantly
    - narrate "<white><npc.name><red> belongs to <white><npc.owner.name><red>, you can not give it orders."
    - execute as_server "npc sel <npc.id>"
    - execute as_server "npc controllable -n" }
 
    else if <npc.owner> == <player> && "<npc.constant[Pets Rideable]>" == "Yes" && "<npc.constant[Special Emerald Required]>" == "Yes" && "<player.item_in_Hand.lore.contains[Pet Emerald]>" {
      - if "<npc.constant[Mountable Pets]>" contains <npc.entity_type> {
        - execute as_server "npc sel <npc.id>"
        - execute as_server "sentry guard"
        - execute as_server "npc controllable -y"
        - narrate "<green>You hop onto <white><npc.name><&sq>s<green> back.." }
 
        else narrate "<red>Sorry, mounting <white><npc.entity_type><red> type pets has been disabled by your admin."
    }
 
    else if <npc.owner> == <player> && "<npc.constant[Pets Rideable]>" == "Yes" && "<npc.constant[Special Emerald Required]>" == "No" && "<player.item_in_hand>" == "[email protected]<npc.constant[Alternative Ride Item]>" {
      - if "<npc.constant[Mountable Pets]>" contains <npc.entity_type> {
        - execute as_server "npc sel <npc.id>"
        - execute as_server "sentry guard"
        - execute as_server "npc controllable -y"
        - narrate "<green>You hop onto <white><npc.name><&sq>s<green> back.." }
 
        else narrate "<red>Sorry, mounting <white><npc.entity_type><red> type pets has been disabled by your admin."
    }
 
    else {
      - execute as_server "npc sel <npc.id>"
      - execute as_server "npc controllable -n"
      - run "Pet Noises" instantly
      - execute as_server "npc sel <npc.id>"
      - execute as_server "sentry retaliate false"
      - execute as_server "sentry invincible true"
      - if <npc.flag[Following]> {
          - execute as_server "sentry guard"
          - execute as_server "sentry spawn"
          - flag <npc> Following:!
          - if <queue.exists[<npc>_scavenger]> queue id:<npc>_scavenger stop
          - narrate "<white><npc.name><red> will wait here." }
        else {
          - execute as_server "sentry guard <npc.owner.name>"
          - flag <npc> Following
          - if <global.flag[Scavenge_Frequency]> != 0 && <queue.exists[<npc>_scavenger]> == false {
              - run "Pet Scavenger" id:<npc>_scavenger delay:<global.flag[Scavenge_Frequency]>
            }
          - if <global.flag[Scavenge_Frequency]> != 0 narrate "<white><npc.name><red> will follow you and scavenge for items."
            else narrate "<white><npc.name><red> will follow you."
        }
    }
 
# This is the task that run every time the player interacts with the pet. The
# point of this is to give some aural feedback to the player. It uses a set
# of IF statements to compare the entity type (pet) and the play the appropriate
# sound. You can find a list of available sounds at:
#
# http://jd.bukkit.org/rb/apidocs/org/bukkit/Sound.html

"Pet Noises":
  type: task

  script:
  - ^if <npc.entity_type> == 'blaze' playsound location:<npc.location> sound:blaze_breath
    else if <npc.entity_type> == 'bat' playsound location:<npc.location> sound:bat_idle
    else if <npc.entity_type> == 'cave_spider' playsound location:<npc.location> sound:spider_idle
    else if <npc.entity_type> == 'chicken' playsound location:<npc.location> sound:chicken_idle
    else if <npc.entity_type> == 'creeper' playsound location:<npc.location> sound:creeper_hiss
    else if <npc.entity_type> == 'cow' playsound location:<npc.location> sound:cow_idle
 
    else if <npc.entity_type> == 'enderman' {
      - random {
        - playsound location:<npc.location> sound:enderman_idle
        - playsound location:<npc.location> sound:enderman_scream
        - playsound location:<npc.location> sound:enderman_teleport }
    }
 
    else if <npc.entity_type> == 'ender_dragon' {
      - random {
        - playsound location:<npc.location> sound:enderdragon_growl
        - playsound location:<npc.location> sound:enderdragon_wings }
    }
 
    else if <npc.entity_type> == 'ghast' {
      - random {
        - playsound location:<npc.location> sound:ghast_moan
        - playsound location:<npc.location> sound:ghast_scream
        - playsound location:<npc.location> sound:ghast_scream2 }
    }
 
    else if <npc.entity_type> == 'giant' playsound location:<npc.location> sound:zombie_idle
    else if <npc.entity_type> == 'iron_golem' playsound location:<npc.location> sound:irongolem_walk
    else if <npc.entity_type> == 'magma_cube' playsound location:<npc.location> sound:magmacube_jump
    else if <npc.entity_type> == 'mushroom_cow' playsound location:<npc.location> sound:cow_idle
 
    else if <npc.entity_type> == 'ocelot' {
      - random {
        - playsound location:<npc.location> sound:cat_meow
        - playsound location:<npc.location> sound:cat_purr
        - playsound location:<npc.location> sound:cat_purreow
        - playsound location:<npc.location> sound:cat_hiss }
    }
 
    else if <npc.entity_type> == 'pig' playsound location:<npc.location> sound:pig_idle
    else if <npc.entity_type> == 'pig_zombie' playsound location:<npc.location> sound:zombie_pig_idle
 
    else if <npc.entity_type> == 'player' {
      - random {
        - playsound location:<npc.location> sound:burp
        - playsound location:<npc.location> sound:drink
        - playsound location:<npc.location> sound:eat }
    }
 
    else if <npc.entity_type> == 'sheep' playsound location:<npc.location> sound:sheep_idle
 
    else if <npc.entity_type> == 'silverfish' {
      - random {
        - playsound location:<npc.location> sound:silverfish_idle
        - playsound location:<npc.location> sound:silverfish_hit }
    }
 
    else if <npc.entity_type> == 'squid' playsound location:<npc.location> sound:water
 
    else if <npc.entity_type> == 'snowman' {
      - random {
        - playsound location:<npc.location> sound:step_snow
        - playsound location:<npc.location> sound:dig_snow }
    }
 
    else if <npc.entity_type> == 'wolf' {
      - random {
        - playsound location:<npc.location> sound:wolf_bark
        - playsound location:<npc.location> sound:wolf_pant }
    }
 
    else if <npc.entity_type> == 'skeleton' {
      - random {
        - playsound location:<npc.location> sound:skeleton_idle
        - playsound location:<npc.location> sound:skeleton_hurt }
    }
 
    else if <npc.entity_type> == 'slime' {
      - random {
        - playsound location:<npc.location> sound:slime_walk
        - playsound location:<npc.location> sound:slime_walk2 }
    }
 
    else if <npc.entity_type> == 'spider' {
      - random {
        - playsound location:<npc.location> sound:spider_idle
        - playsound location:<npc.location> sound:spider_walk }
    }
 
    else if <npc.entity_type> == 'wither' {
      - random {
        - playsound location:<npc.location> sound:wither_idle
        - playsound location:<npc.location> sound:wither_spawn }
    }
 
    else if <npc.entity_type> == 'zombie' playsound location:<npc.location> sound:zombie_idle
 
# This is the special item that a player can buy to be able to ride a pet.
# If you change the material, you will need to search this script for all instances of the
# word 'emerald', like in the chat trigger and subsequent dialogues. Otherwise it'll break
# parts of this script.

"Petshop Emerald":
  type: item
  material: emerald
  display name: Emerald of Animal Empathy
  no_id: true
  lore:
  - Pet Emerald
 
# The following task loops based on the frequency set in the '<global.flag[Scavenge_Frequency]>' flag. It doesn't
# just do it however... a few checks need to pass first:
#
#  1) Is there a scavenger frequency, in other words, is it enabled?
#  2) Is the owner online?
#  3) Is the owner within 10 blocks of the pet?
#  4) Did it roll a value equal to or higher than the percentage chance specified (<global.flag[Scavenge_Find_Chance]>)?
#
# If all of the criteria were met, it will find a random item in the '<global.flag[Scavenge_Loot]>' list and 
# drop it next to the player.
#
# It then checks again to see if the player is online and if there is a scavenge frequency before it runs the
# task again with a delay.

"Pet Scavenger":
  type: task

  script:
  - if <global.flag[Scavenge_Frequency]> != 0 && <npc.owner.is_online> {
    - if <npc.location.distance[<npc.owner.location>]> <= 10 {
      - if <util.random.int[1].to[100]> <= <global.flag[Scavenge_Find_Chance]> {
        - define loot <global.flag[Scavenge_Loot].aslist.random>
        - drop [email protected]%loot% <npc.owner.location.simple>
        - run "Pet Noises" instantly
        - random {
          - narrate "<red>Your pet <white><npc.name><red> has found something and dropped it at your feet... <gold>%loot%" target:<npc.owner>
          - narrate "<red>Your pet <white><npc.name><red> went scavenging and found something... <gold>%loot%" target:<npc.owner>
          - narrate "<white><npc.name><red> brings you treasure... <gold>%loot%" target:<npc.owner>
          - narrate "<white><npc.name><red> found something behind a rock... <gold>%loot%" target:<npc.owner>
          - narrate "<red>You found <white><npc.name> <red>sitting ontop of something... <gold>%loot%" target:<npc.owner>
          - narrate "<white><npc.name> <red>drops something its been carrying around... <gold>%loot%" target:<npc.owner>
          - narrate "<white><npc.name> <red>wants to please its master and brought you something... <gold>%loot%" target:<npc.owner>
          - narrate "<white><npc.name> <red>found something on an old rotten corpse... <gold>%loot%" target:<npc.owner>
          }
        }
      }
    }
  - wait <global.flag[Scavenge_Frequency]>
  - if <global.flag[Scavenge_Frequency]> != 0 && <npc.owner.is_online> && <npc.flag[Following]>
    run "Pet Scavenger" id:<npc>_scavenger
 
# The world event below is used to clean up scavenger queues. It uses the 'foreach'
# command to run through every Pet the player has and if they have an active queue, it
# will clear it when the player quits.

"Pet Scavenger Queue Clean-up":
  type: world
  events:

    on player quits:
    - if <player.flag[Pets].size> >= 1 {
      - foreach <player.flag[Pets].aslist> {
        - if <queue.exists[%value%_scavenger]> queue id:%value%_scavenger clear }
        }




Comments
2013-09-10 01:38:04 - mythanical:

Changes to flags and broke the script. I have fixed it up. Let me know if there are still any problems.
2013-09-10 01:38:30 - mythanical:

Flags and "player.chat_history"....
2013-11-10 22:01:53 - uledrith:

This is very nice work! I just wanted to report a bug - it still allows players to ride bats, but gives the error message.
2013-12-25 02:57:09 - Tacoaloto:

Honestly I really like this script, and all of the scripts you've made, mythanical! one thing I noticed is that if you have a server that automatically adds targets when the npc creates, you have to make sure you add a few commands to the script to clear those targets. You don't want your brand new creeper to go commit suicide into a zombie, right? =p
2014-01-12 06:11:03 - mythanical:

Uledrith, sorry, I can't reproduce the issue. I tried riding a bat and it didn't mount it and displayed the message saying I couldn't ride it. Tacoaloto, what would cause a server to automatically add targets? Mine doesn't do that, hence why I didn't add protection into the script for something like that.
2014-02-13 03:31:25 - xombiemike:

When we buy a pet no pet shows up. It takes the money though. When I ask for a teleport it says I don't have any pets.
2014-02-13 16:05:56 - xombiemike:

mythanical, I replaced all "execute as_npc" with "execute as_op" and the scrip runs fine now.
2014-07-10 20:03:42 - Tacoaloto:

Extremely late response, but It was the fact that in my config it was designed to automatically target hostile mobs. I fixed it long ago, but for me, non-op players can't interact with their pets. Example: "dkilla5, that pet belongs to dkilla5 and you cannot give it orders."
2014-07-10 20:21:31 - Tacoaloto:

Extremely late response, but It was the fact that in my config it was designed to automatically target hostile mobs. I fixed it long ago, but for me, non-op players can't interact with their pets. Example: "dkilla5, that pet belongs to dkilla5 and you cannot give it orders."