Boss - Multistage with Minions, Loot and More!


Author: mythanical
Created: 2013-10-12T02:52:09-0400
Edited: 2013-10-22T04:59:23-0400
Denizen Version: 0.9.3
Views: 57
Downloads: 1643
Likes: 3


WGET
Description: Boss Fight - Multistage and Highly Configurable
=====================================
Citizens 2 (build #991)
Denizen 0.9.3 (build #1341)
Sentry 1.5.3

KNOWN ISSUES:
==============
* There is a more than 40 second delay with Sentry when you assign PLAYER as the target. I've logged it, waiting for it to be fixed. (https://github.com/jrbudda/Sentry/issues/161).
* Because of that issue, we have to use the "attack" command which sometimes causes the boss or the minions to teleport themselves to runaway players.

To assign to an NPC, literally type:
/npc assign --set "bossname"

DISCLAIMER:
===========
This is an advanced script. You should test this script before you use it on your LIVE server. Some of the item drops ignore ZONE PROTECTION. So if you play on a strict server you will want to disable those items by removing them from the "BossName Determine Loot" script.

DESCRIPTION:
============
This is a four stage boss fight with a bunch of simple configuration options that will allow you to create a unique boss fight. You can decide how many stages you want to enable, how difficult the boss should be (health, armor, strength), whether it should spawn minions and if so, how many, how difficult etc. The boss has several different 'special attacks' that can be used directly on players or inside a "cuboid", which you have to specify in the constant values at the top of the script.

The boss can heal or reset itself if no one is in range.

When the boss is killed, it can drop random loot (from a series of item scripts that's located towards the bottom of this script) directly into players inventory, on the floor around the boss or into secure chests for each of the boss fighters.

At the end of the fight, it will show a text scoreboard that shows total damage, hit count, minion kills etc for each player.

FEATURES:
==========
* Boss and/or Minions (quantity, health, armor, strength)
* Special Attacks (arrow spells, lightning storm, arrows dropping from ceiling)
* Boss heal/reset itself if inactive
* Unique item drops, using item scripts and world events
* Text scoreboard showing battle summary stats

# Boss Fight - Multistage and Highly Configurable
# Citizens 2 (build #991)
# Denizen 0.9.3 (build #1341)
# Sentry 1.5.3
#
# To assign to an NPC, literally type:
# /npc assign --set "bossname"
#
# DISCLAIMER:
# ===========
# This is an advanced script. You should test this script
# before you use it on your LIVE server. Some of the item drops
# ignore ZONE PROTECTION. So if you play on a strict
# server you will want to disable those items by
# removing them from the "BossName Determine Loot" script.
#
# DESCRIPTION:
# ============
#
# This is a four stage boss fight with a bunch of simple configuration
# options that will allow you to create a unique boss fight.
# You can decide how many stages you want to enable, how difficult the
# boss should be (health, armor, strength), whether it should spawn
# minions and if so, how many, how difficult etc. The boss has several
# different 'special attacks' that can be used directly on players or
# inside a "cuboid", which you have to specify in the constant values
# at the top of the script.
#
# The boss can heal or reset itself if no one is in range.
#
# When the boss is killed, it can drop random loot (from a series of
# item scripts that's located towards the bottom of this script) directly
# into players inventory, on the floor around the boss or into secure chests
# for each of the boss fighters.
#
# At the end of the fight, it will show a text scoreboard that shows total
# damage, hit count, minion kills etc for each player.
#
# FEATURES:
# =========
#  * Boss and/or Minions (quantity, health, armor, strength)
#  * Special Attacks (arrow spells, lightning storm, arrows dropping from ceiling)
#  * Boss heal/reset itself if inactive
#  * Unique item drops, using item scripts and world events
#  * Text scoreboard showing battle summary stats
#  * Shows health bar when you right click boss or minion.
#
# NOTE: 
# ====
# If you want to use this on more than one NPC you simply need to do
# a FIND on the word 'BossName' and REPLACE it with your NPC name. Then
# make another copy of the script and do another FIND/REPLACE for every
# boss NPC that will use this.
#
# CREDITS:
# ========
# Thanks to aufdemrand, davidcernat and mcmonkey for fixing/adding things in
# Denizen. Thanks to Matterom and blankiito for example scripts on the work 
# they've done on custom items and effects.
#
#
# @author mythanical
# @script version 0.2
# @last-updated October 22 2013
# @irc EsperNet IRC Network #denizen-dev
# @Minecraft Server - minecraft.geek.nz
# @Donate Bitcoin: 1Fzacc2gZ5NGRMXg5jWP6NcUkWei34xjzt
# @Donate Litecoin: LhsaGa1QzmVLjMYwg4ZPTVnmSgnBDGc75U
 

"BossName":
  type: assignment

  default constants:

    # --------------------------------------------------------------------------------------------------------
    # NOTE: 'Player' entity type NPC's are fully supported by Sentry, but other types may give you some
    #       interesting, unexpected or undesired results. Especially when you try and equip them with a
    #       weapon.
    #
    # 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)
    # --------------------------------------------------------------------------------------------------------

    Boss Entity Type: player
 
    # adult                 (Normal NPC type)
    # baby                  (Cause the Boss to be a baby. Note: Not all entity types have a baby version)
    Boss Age: adult
 
    # The following Sentry weapons are fully supported by 'player' type entity (http://wiki.citizensnpcs.com/Sentry):
    # bow                   (Archer - Range is 50 meters on flat ground.)
    # redstone_torch_on     (Pyromancer I - Shoot small, non-incendiary fireballs)
    # torch                 (Pyromancer II -  Shoot fireballs that set the land on fire)
    # blaze_rod             (Pyromancer III - Shoot large, explosive fireballs that set the land on fire)
    # snow_ball             (Ice Magi - Throw snowballs which slow enemies on contact. Snowballs have a range of about 25 blocks on flat ground)
    # egg                   (Bombardiers - explode?  Eggs have a range of about 25 blocks on flat ground)
    # potion                (Witch Doctor - Will throw a splash version of whatever potion type it is equipped with)
    # paper                 (Stormcaller I - Strike single targets with bolts of electricity)
    # book                  (Stormcaller II - Smite multiple foes. This lightning's damage is atmospheric and therefore is not affected by the Sentry's strength)
    # book_and_quill        (Stormcaller III - Bolts instantly kill any living thing they touch regardless of health, armor, or play mode)
    # ender_pearl           (Warlock I - Fling targets high into the air)
    # skull_item            (Warlock II - Mid-range warlock shoots black explosive wither skulls at the enemy)
    # none                  (Brawler - Swords, axes, picks, shovels, rocks, bricks, or even fish, the brawlers take the fight to the enemy, hand to hand)
    Boss Weapon: none
 
    # The sentry values for the boss, you can check out what these mean at:
    # http://wiki.citizensnpcs.co/Sentry
    Boss Health: 500
    Boss Strength: 1
    Boss Armor: 1
    Boss Agro Range: 15
 
    # Awareness range will still trigger special attacks.
    Boss Awareness Range: 30
    Boss Movement Speed: 1
 
    # If all players have left the boss proximity, this enables the boss to heal itself slowly.
    Boss Exit Proximity Self Healing: "Yes"
 
    # Set the location where your boss will respawn
    Boss Spawn Location: "-151,65,80,world"
 
    # Set to -1 if you never want the boss to respawn and be permanently destroyed on death.
    Boss Respawn Delay: 600
 
    # On default, boss fight will reset after 120s of inactivity. Set to 0 if you don't ever want it to reset
    # and allow players to come back later to finish it.
    Boss Reset Timer: 120
 
    # The item scripts for the loot is located at the bottom. It will give each player, that hit the boss or a minion
    # at least once, a random item.
    Drop Loot on Death: "Yes"
 
    # The specifies how much loot per player
    Loot Quantity: 1
 
    # This specifies how the loot should be distributed.
    # player                (Put the item into the players inventory)
    # boss                  (Drop the loot on the ground around the boss)
    # chest                 (Spawn a chest with all the loot inside it where the boss died)
    # playerchest           (Create a chest next to each player that only they can access)
    Loot Distribution: playerchest
 
    # To prevent any loot chests from staying forever, give them any value other than 0
    # and they will expire..dropping all the loot on the floor.
    Loot Chest Expiry: 600
 
    # Enable scoreboard (on right side of screen) to show either Minion Kills or Boss Health Damage by each player
    # during the fight. This gets removed when the boss is killed.
    # bosshealth            (Show running damage dealt to boss by each player)
    # minionkills           (Show a count for number of minions killed by players)
    # minionhealth          (Show the running damage dealt to minions by each player)
    # none                  (No running battle scoreboard)
    Scoreboard: bosshealth
 
    # The cuboid is the square area (a room) where most of the fighting will take place. This area can be used in the options below
    # to allow mobs to be spawned in it or to have some of the boss special fighting skills to take place in. 
    Cuboid Spawn Area Poss 1: "-162,68,77,world"
    Cuboid Spawn Area Poss 2: "-141,63,105,world"
 
    # What will trigger the start of the boss fight? 
    # proximity             (Activate if a player walks into the proximity specified in the "Boss Awareness Range" constant value above)
    # damage                (Activate boss fight when damaged by a player)
    Bossfight Activator: damage
 
    # Currently the script supports 4 battle stages. A stage is reached/unlocked when the boss is down to a specified health percentage.
    # You decide the boss health percentage, minion names, the quantity to spawn, NPC types and how/where they spawn.
    # If you want less stages, simply remove them from the list. If you don't want any, type in "none". Make sure to type it as "One|Two|Three|Four".
    # If you only want the first two stages, type it as: One|Two

    Enabled Boss Stages: One|Two|Three|Four
 
    # The sections below detail the values for each of the 4 stages of the boss fight. You should modify these to make each boss fight unique.
    Stage One Boss Health Percentage: 95
 
    # none                  (No effect around NPC)
    # flame                 (Create a fiery effect around the boss)
    # heart                 (Surrounds the boss with love hearts - kill you with love??)
    # smoke                 (Create a smokey 'pop' effect around the boss)
    # ender                 (Create the Enderman particles around NPC)
    # potbreak              (Not very good, also makes the pot break sound)
    # explosion             (Creeper explosion effect, causes no damage)
    Stage One Boss Aura: smoke
 
    # "Poison Arrow"        (Shoot a poisonous arrow towards a randomly chosen player. Only casts when the player is hit)
    # "Wither Arrow"        (Cast wither...)
    # "Weakness Arrow"      (Cast weakness...)
    # "Slowness Arrow"      (Cast slowness...)
    # "Rain Arrows"         (Rain arrows from the sky - note: you need provide values for the "Cuboid Spawn Area Poss x" above for this to work)
    # "Lightning Bolt"      (Hit a single random player with a lightning bolt - this never misses)
    # "Lightning Storm"     (Several damaging lightning bolts - note: you to need provide values for the "Cuboid Spawn Area Poss x" above for this to work)
    # "TNT"                 (Boss tosses a block of primed tnt at a random player)
    # "TNT Drop"            (Drop 5 blocks of TNT in random locations in the cuboid - Minecraft/Bukkit bug prevents this from working)
    # "Throw"               (This will cause 3 players to be thrown from their current position to a random location inside the cuboid)
    # "Firestarter"         (Ignite 10 random blocks in the cuboid)
    # none                  (No special attack)
    Stage One Boss Special Attack: "Poison Arrow"
 
    # Run the special attack on a loop, once every 20 seconds.
    Stage One Boss Special Attack Delay: 20s

    Stage One Spawn Minions: "Yes"
    Stage One Minion Type: zombie
    Stage One Minion Age: baby
    Stage One Minion Name: RotWalker
    Stage One Minion Weapon: wood_sword
    Stage One Minion Health: 30
    Stage One Minion Quantity: 5
    Stage One Minion Strength: 2
    Stage One Minion Armor: 3
    Stage One Minion Speed: 0.5
 
    # lightning             (lightning bolt with sound)
    # explode               (harmless explosion effect with sound)
    # none                  (no effect)
    Stage One Minion Spawn Effect: none
 
    # player: spawn around random player
    # boss: spawn around boss
    # cuboid: spawn anywhere inside the cuboid values you specified above
    Stage One Minion Spawn Location: player
 
    # Boss - Stage Two
    Stage Two Boss Health Percentage: 75
    Stage Two Boss Aura: ender
    Stage Two Boss Special Attack: "Wither Arrow"
    Stage Two Boss Special Attack Delay: 30s
    Stage Two Spawn Minions: "Yes"
    Stage Two Minion Type: cave_spider
    Stage Two Minion Age: adult
    Stage Two Minion Name: Crawler
    Stage Two Minion Weapon: none
    Stage Two Minion Health: 5
    Stage Two Minion Quantity: 15
    Stage Two Minion Strength: 1
    Stage Two Minion Armor: 1
    Stage Two Minion Speed: 1.5
    Stage Two Minion Spawn Effect: lightning
    Stage Two Minion Spawn Location: cuboid
 
    # Boss - Stage Three
    Stage Three Boss Health Percentage: 50
    Stage Three Boss Aura: flame
    Stage Three Boss Special Attack: Firestarter
    Stage Three Boss Special Attack Delay: 20s
    Stage Three Spawn Minions: "Yes"
    Stage Three Minion Type: blaze
    Stage Three Minion Age: adult
    Stage Three Minion Name: FireElement
    Stage Three Minion Weapon: none
    Stage Three Minion Health: 30
    Stage Three Minion Quantity: 5
    Stage Three Minion Strength: 2
    Stage Three Minion Armor: 8
    Stage Three Minion Speed: 1
    Stage Three Minion Spawn Effect: explode
    Stage Three Minion Spawn Location: boss
 
    # Boss - Stage Four
    Stage Four Boss Health Percentage: 25
    Stage Four Boss Aura: heart
    Stage Four Boss Special Attack: "TNT Drop"
    Stage Four Boss Special Attack Delay: 20s
    Stage Four Spawn Minions: "Yes"
    Stage Four Minion Type: iron_golem
    Stage Four Minion Age: adult
    Stage Four Minion Name: Terminator
    Stage Four Minion Weapon: none
    Stage Four Minion Health: 50
    Stage Four Minion Quantity: 5
    Stage Four Minion Strength: 3
    Stage Four Minion Armor: 8
    Stage Four Minion Speed: 1.2
    Stage Four Minion Spawn Effect: lightning
    Stage Four Minion Spawn Location: cuboid
 
#WARNING# Only continue past this point if you know what you're doing!! #WARNING#

  interact scripts:
  - 10 BossName Script

  actions:
    on assignment:
    # For this script, the click trigger is only used to return the boss's health.
    - trigger name:click toggle:true
    # Proximity set to a radius of 30, you should increase this in the 
    # "Boss Awareness Range" constant above if you're fighting in a large arena.
    - trigger name:proximity toggle:true "radius:<cons:Boss Awareness Range>"
    # Damage trigger does a whole bunch of stuff which I'll explain in that section.
    - trigger name:damage toggle:true
 
    # Create a NPC flag called "cuboid" that stores the cuboid values in a simple
    # shorter name which makes it easy for reuse.
    - flag npc "cuboid:cu@<cons:Cuboid Spawn Area Poss 1>|<cons:Cuboid Spawn Area Poss 2>"
 
    # The following commands sets up the Boss using the values specified in the 
    # constants above.
    - execute as_server "npc sel <npc.id>"
    - execute as_server "npc type <cons:Boss Entity Type>"
    - if "<cons:Boss Age>" == baby age <npc> baby
    - execute as_server "npc speed <cons:Boss Movement Speed>"
    - execute as_server "npc lookclose"
    - execute as_server "trait sentry"
    - execute as_server "sentry health <cons:Boss Health>"
    - execute as_server "sentry respawn <cons:Boss Respawn Delay>"
    - execute as_server "sentry speed <cons:Boss Movement Speed>"
    - execute as_server "sentry strength <cons:Boss Strength>"
    - execute as_server "sentry armor <cons:Boss Armor>"
    - execute as_server "sentry range <cons:Boss Agro Range>"
    - if "<cons:Boss Weapon>" != none execute as_server "sentry equip <cons:Boss Weapon>"
 
    # Put the boss stages into a flag - this will be used throughout to check which boss
    # stages should be activated.
    - flag npc "Enabled Boss Stages:<cons:Enabled Boss Stages>"
 
    # This is used in world events further down to prevent self/minion harm.
    - flag global ListOfBosses:<npc>
    
    # This is used by the minions to prevent teleporting to players when the player exits
    # their awareness range. (Temporary until Sentry is fixed)
    - flag npc "Minion Awareness Range:<cons:Boss Awareness Range>"

    on spawn:
    # Teleport boss back to starting point.
    - teleport <npc> "location:<cons:Boss Spawn Location>"
 
    # Every time the boss spawns after it's been killed, it'll run through the following process
    # to do some 'clean-up' from the previous battle.
    #
    # First it runs through a global "minion" list and check to see whether they are despanwed and
    # if they have a "creator". It then removes them from the global list and executes the "remove"
    # command to permanently get rid of them.
    #
    # Clear the Sentry target list, so it doesn't attack players unprovoked.
    #
    # Remove the "R.I.P" sign it placed when and where it died.
    #
    # Set up the Minecraft scoreboard.
    # First it checks to see if its meant to create a Scoreboard, if so, it'll flag the
    # NPC with what the scoreboard should show:
    #   * bosshealth
    #   * minionkills
    #   * miniondamage
    #
    # It uses the "substring" to put a limit in place for the length of the boss's name because
    # if the name is too long, the scoreboard will fail to create.
 
    - if <npc.flag[BossDied]> {
      - flag npc BossDied:!
 
      - foreach <global.flag[AllMinions].aslist> {
        - if <npc[%value%].is_spawned> != true && <npc[%value%].flag[MinionCreator]> != null {
          - flag global AllMinions:<-:%value%
          - remove %value% }
        }
 
      - execute as_server "npc sel <npc.id>"
      - execute as_server "sentry target clear"
 
      - if "<location[<npc.flag[DeathLocation]>].block.sign_contents>" contains <npc.name> modifyblock <npc.flag[DeathLocation]> air
 
      - if <cons:Scoreboard> != none && <npc.flag[Scoreboard]> == null {
        - flag <npc> Scoreboard:<cons:Scoreboard>
        - if <npc.flag[Scoreboard]> == "bosshealth" {
          - execute as_server "scoreboard objectives add <npc.name.substring[1,9]>.Damage dummy"
          - execute as_server "scoreboard objectives setDisplay sidebar <npc.name.substring[1,9]>.Damage" }
          else if <npc.flag[Scoreboard]> == "minionkills" {
            - execute as_server "scoreboard objectives add <npc.name.substring[1,5]>.MinionKills dummy"
            - execute as_server "scoreboard objectives setDisplay sidebar <npc.name.substring[1,5]>.MinionKills" }
          else { 
            - execute as_server "scoreboard objectives add <npc.name.substring[1,6]>.MinionDmg dummy"
            - execute as_server "scoreboard objectives setDisplay sidebar <npc.name.substring[1,6]>.MinionDmg" }
        }
      }

    on death:
    # When the boss dies, there is a bunch of clean-up that needs to happen.
    #
    # It goes through a couple of 'foreach' loops to remove all the minions that were created
    # during the various stages. Each minion was added to the boss flag list and now it simply
    # iterates through removing each minion by substituting %value% with their NPC ID, e.g.  n@123
    - foreach "<npc.flag[Enabled Boss Stages].aslist>" {
              - foreach "<npc.flag[Stage%value%Minions].aslist>" {
                  - if <npc> != %value% remove <npc[%value%]>
              }
      }
 
    # It then clears the minion list for each battle stage.
    - foreach "<npc.flag[Enabled Boss Stages].aslist>" {
              - flag <npc> "Stage%value%Minions:!"
      }
 
    # Remove the next 2 lines if you don't like it. What it does is flag where the boss died and put a
    # sign into the ground with the boss's name, followed by "was defeated here". The "|" means go onto
    # the next line on the sign.
    - flag npc DeathLocation:<npc.location.simple>
    - sign <npc.flag[DeathLocation]> "<npc.name>|was defeated|here."
 
    # The following section builds the text scoreboard that is displayed in the Minecraft chat when
    # the boss has been killed.
    #
    # The IF checks to see if anybody hit the boss at any point (using the "BossHitList" flag).
    # You'll see further down that this list is populated by the damage trigger when the boss is hit
    # by a player.
    #
    # It then announces to the server the result of the battle. It uses a foreach loop to cycle through
    # all players that hit the boss (even those that didn't penetrate its amor) and shows for each player
    # how much damage, their overall damage percentage and the number of times they hit the boss.
    #
    # If the player also damaged and killed minions, it will show another line with minion total damage,
    # hit count and number of minions killed.
    #
    # This is all recorded into flags during the damage trigger and on death action for the boss and minions.
    #
    # At the bottom it shows a list of all players that got into the "Boss Awareness Range" but never
    # damaged/hit the boss or minions, e.g SPECTATORS.
    #
    # During the foreach loop, it also clears all the player flags to ready them for the next battle.
    #
    # Lastly, it checks to see if the "Drop Loot on Death" is set to "Yes", and if so it runs the task
    # called "BossName Drop the Loot" instantly.
 
    - if <npc.flag[BossHitList]> != null {
      - announce "<red>BOSS EVENT<&co> <white><npc.name><red> has been killed by <yellow><npc.flag[BossHitList].formatted><red>."
      - announce "<green>------------------------------------------"
      - announce "<green><underline>Battle Stats<&co>"
      - announce ""
      - announce "<red><npc.name> Total Health<&co> <npc.health.max.as_int>"
      - foreach <npc.flag[BossHitList].aslist> {
        - define bosspercentage <util.as_element[<m:<player[%value%].flag[BossPlayerTotalDamage]>/<npc.health.max>*100>].asint>
        - announce "<yellow><%value%.name>|"
        - announce "<aqua>Boss Damage <gold><player[%value%].flag[BossPlayerTotalDamage].as_int> (<%bosspercentage%><&pc>) <aqua>- Hits| <gold><player[%value%].flag[BossPlayerHitCount].as_int>"
        - if <player[%value%].flag[MinionTotalDamage]> != null {
          - announce "<aqua>Combined Minion Damage <gold><player[%value%].flag[MinionTotalDamage].as_int || 0> <aqua>- Hits| <gold><player[%value%].flag[MinionHitCount].as_int || 0> <aqua>- Minions Killed| <gold><player[%value%].flag[MinionsKilledCount].as_int || 0>" }
        - flag player:%value% BossPlayerTotalDamage:!
        - flag player:%value% BossPlayerHitCount:!
        - flag player:%value% MinionsKilledCount:!
        - flag player:%value% MinionHitCount:!
        - flag player:%value% MinionTotalDamage:! }
      - announce "<green>------------------------------------------"
      - foreach <npc.flag[BossSpectatorList].aslist> {
        - if <npc.flag[BossHitList].aslist> contains %value% flag npc BossSpectatorList:<-:%value% }
      - if <npc.flag[BossSpectatorList].size> >= 1 announce "Spectators| <npc.flag[BossSpectatorList].formatted>"
      - if "<cons:Drop Loot on Death>" == "Yes" run "BossName Drop the Loot" instantly
      }
 
    # Remove any visual effects applied at fight stages and clear sentry targets.
    - execute as_server "npc sel <npc.id>"
    - execute as_server "npc effect --play none"
    - execute as_server "sentry target clear"
 
    # If the scoreboard was enabled, this will remove it so it doesn't stay behind on player's screens.
    - if <npc.flag[Scoreboard]> != null {
      - if <npc.flag[Scoreboard]> == "bosshealth" execute as_server "scoreboard objectives remove <npc.name.substring[1,9]>.Damage"
        else if <npc.flag[Scoreboard]> == "minionkills" execute as_server "scoreboard objectives remove <npc.name.substring[1,5]>.MinionKills"
        else if <npc.flag[Scoreboard]> == "minionhealth" execute as_server "scoreboard objectives remove <npc.name.substring[1,6]>.MinionDmg"
        }
 
    # Clear all the flags used during the fight to set boss up for the next fight.
    - flag npc BossHitList:!
    - flag npc BossSpectatorList:!
    - flag npc BossStage:!
    - flag npc BossPlayerList:!
    - flag npc BadLoopProtect:!
    - flag npc ActiveSpecialAttackStage:!
    - flag npc MinionSpawnedStage:!
    - flag npc Scoreboard:!
    - flag npc AllMyMinions:!
    - flag npc BossResetTimer:!
    - flag npc HealActive:!
 
    # This flag is used to prevent certain "on spawn" commands from running unless the boss actually died. 
    - flag npc BossDied

"BossName Script":
  type: interact

  steps:
    1:
      click trigger:
        script:
        # Right clicking the boss will run the "BossName Health Status" task that'll construct a
        # text based health bar that will show in the Minecraft chat window.
        - run "BossName Health Status"

      proximity trigger:
        entry:
          script:
          # When a player enters the proximity set in the "Boss Awareness Range" constant value, it'll check to see
          # if they are already on the list and if not it will add them to the "BossPlayerList" flag. This is used for
          # targetted narrate messages throughout the fight.
          - if <npc.flag[BossPlayerList].aslist> !contains <player> && <player.name> != <npc.name> flag npc BossPlayerList:->:<player>
          
          # Add players to the spectator list, which shows up in the battle stats after the boss fight.
          - if <npc.flag[BossSpectatorList].aslist> !contains <player> && <player.name> != <npc.name> flag npc BossSpectatorList:->:<player>
          
          # If proximity was set as the "BossName Fight Activator" in the constant values at the top, this will
          # start the fight if there isn't already an active fight stage.
          - if "<cons:Bossfight Activator>" == "proximity" && <npc.flag[BossStage]> == null {
            - flag npc BossStage:One
            - run "BossName Fight" }
            else if <npc.flag[BossStage]> != null run "BossName Fight"
 
          # This resets the timer when a player enters proximity so the boss does NOT get reset after the period
          # of inactivity specified in the "BossName Reset Timer" constant value up top.
          - flag npc BossResetTimer:!

        exit:
          script:
          - if <npc.navigator.target_entity> == <player>
            && "<npc.location.find.players.within[<cons:Boss Awareness Range>].size>" >= 1
            attack <npc> "target:<npc.location.find.players.within[<cons:Boss Awareness Range>].get[1]>"
            else attack stop
 
          # The wait 10 allows for a buffer where players are on the edge of the proximity moving in an out.
          - wait 10
 
          # If the fight has been activated (it hasn't got a null boss stage), and there are no players in proximity
          # and self healing has been enabled, run the "BossName Self Heal" task.
          - if "<npc.location.find.players.within[<cons:Boss Awareness Range>].size>" < 1
            && <npc.flag[BossStage]> != null
            && "<cons:Boss Exit Proximity Self Healing>" == "Yes" {
            - run "BossName Self Heal" id:<npc.name>_BossHeal }
 
          # Same as above, except this kicks off the overall "BossName Reset" task with a delay timer (set in 
          # "BossName Reset Timer" constant above).
          - if "<npc.location.find.players.within[<cons:Boss Awareness Range>].size>" < 1 && <npc.flag[BossStage]> != null && "<cons:Boss Reset Timer>" >= 1 && <npc.flag[BossResetTimer]> == null {
            - flag <npc> BossResetTimer
            - run "BossName Reset" id:<npc.name>_ResetTimer "delay:<cons:Boss Reset Timer>" }

      damage trigger:
        script:
        # Every time the boss is hit (whether they are actually damaged or not), it will the commands below.
        #
        # The first IF is so save save the current boss health into a defined value called "phealth".
        - ^if <npc.is_spawned> define phealth <npc.health.as_int>

        # This tick is necessary to allow time for the damage value to be applied to the NPC.
        - wait 1t
 
        # If the player managed to get through the "entry proximity" without being added to the "BossPlayerList"
        # it will do it now.
        - ^if <npc.flag[BossPlayerList].aslist> !contains <player> && <player.name> != <npc.name> flag <npc> BossPlayerList:->:<player>

        # Start counting the number of times the player has hit the boss. Add "+1" every time they trigger this.
        - ^flag player BossPlayerHitCount:++
 
        # Add the player into the "BossHitList" if they aren't already.
        - ^if <npc.flag[BossHitList].aslist> !contains <player> && <player.name> != <npc.name> flag <npc> BossHitList:->:<player>

        # The following IF is used to check the boss's current health. If their health is lower than the specified
        # percentage in the "Stage One/Two/Three/Four Boss Health Percentage" constant values, it will activate the
        # next fighting stage.
        # It flags (flag npc BossStage:One etc) the stage it's at because this is used to control the flow of
        # stages and also used during the "Special Attack" loop tasks further down.
        - ^if "<npc.flag[Enabled Boss Stages].aslist>" contains One && <npc.flag[BossStage]> == null && <npc.health.percentage.as_int> <= "<cons:Stage One Boss Health Percentage>" {
            - flag npc BossStage:One
            - run "BossName Fight" }
          else if "<npc.flag[Enabled Boss Stages].aslist>" contains Two && <npc.flag[BossStage]> == One && <npc.health.percentage.as_int> <= "<cons:Stage Two Boss Health Percentage>" {
            - flag npc BossStage:Two
            - run "BossName Fight" }
          else if "<npc.flag[Enabled Boss Stages].aslist>" contains Three && <npc.flag[BossStage]> == Two && <npc.health.percentage.as_int> <= "<cons:Stage Three Boss Health Percentage>" {
            - flag npc BossStage:Three
            - run "BossName Fight" }
          else if "<npc.flag[Enabled Boss Stages].aslist>" contains Four && <npc.flag[BossStage]> == Three && <npc.health.percentage.as_int> <= "<cons:Stage Four Boss Health Percentage>" {
            - flag npc BossStage:Four
            - run "BossName Fight" }
 
        # The new NPC remaining value is then subtracted off the previous damage value. This is then
        # added into a player flag as the total damage value they inflicted. 
        - ^if <npc.is_spawned> define finaldamage <el@val[<m:%phealth%-<npc.health>>].asint>
          else define finaldamage %phealth%
        - ^flag player BossPlayerTotalDamage:+:%finaldamage%
 
        # Add the damage amount into the Minecraft scoreboard. (Right hand side of players screen).
        - if <npc.flag[Scoreboard]> == bosshealth && %finaldamage% != 0 execute as_server "scoreboard players add <player.name> <npc.name.substring[1,9]>.Damage %finaldamage%"

"BossName Fight":
  type: task

  script:
  # Every time a stage kicks off, this is the part of the script it runs.
  # Initially it announces the boss health percentage to the "BossPlayerList" (so not everyone on the server
  # gets the message, only the participants. It also runs the "BossName Health Status" script which displays
  # a dynamic text based health bar.
  - ^narrate "<red>Boss Stage <npc.flag[BossStage]> - Health <npc.health.percentage.as_int>%" targets:<npc.flag[BossPlayerList].aslist>
  - ^run "BossName Health Status"
 
  # Flags the boss with the current stage special attack, used by the special attack tasks to run (or not
  # if it's not relevant for that stage anymore).
  - ^flag npc "CurrentSpecialAttack:<cons:Stage <npc.flag[BossStage]> Boss Special Attack>"
 
  # Each stage can also have a different effect play around/near the boss, this is checked here and
  # applied with the "execute as_server" command.
  # If there is no effect for this stage, it removes it with the "--play none" parameter below.
  - ^if flame|heart|smoke|ender|potbreak|explosion contains "<cons:Stage <npc.flag[BossStage]> Boss Aura>" {
      - execute as_server "npc sel <npc.id>"
      - execute as_server "npc effect --play none"
      - execute as_server "npc effect --play <cons:Stage <npc.flag[BossStage]> Boss Aura>"
    }
    else {
      - execute as_server "npc sel <npc.id>"
      - execute as_server "npc effect --play none" }
 
  # The next section is where the minions are spawned, if enabled, for the relevant boss stage.
  # For the "repeat" command, it runs the number of times based on the number of minions you've set
  # to spawn in the "... Minion Qunatity" constant values at the top for each stage.
  #
  # It uses a global flag (TempBossId) to store the boss's NPC ID which is then put into a for each of
  # the minions - so it creates a relationship of sorts between the boss & minions so they can be
  # despawned when the boss dies for example.
  #
  # It checks to see where the minions should spawn based on your set spawn location, 'player', 
  # 'cuboid' or 'boss'. Then it uses a great tag combination "get_spawnable_blocks.random" to pick
  # a random "safe" location for the minion to spawn. This prevents *most* NPC's from spawning inside
  # walls.
  #
  # Then, once its got the location it runs the "BossName Spawn Minion" task instantly. This is explained further
  # down when you get to the task.
  #
  # Once the minion has been created, it'll make it a baby if a) you enabled it  b) if the NPC type
  # supports it. It then applies all the sentry values you've set at each stage in the constants
  # at the top of the script. Lastly, it adds "player" type to it's Sentry target list, picks a random 
  # player from the BossPlayerList and..well.. attacks it.
 
  - if "<cons:Stage <npc.flag[BossStage]> Spawn Minions>" == "Yes" && <npc.flag[MinionSpawnedStage]> != <npc.flag[BossStage]> {
    - flag <npc> MinionSpawnedStage:<npc.flag[BossStage]>
    - repeat "<cons:Stage <npc.flag[BossStage]> Minion Quantity>" {
      - flag global TempBossId:<npc>
      - if "<cons:Stage <npc.flag[BossStage]> Minion Spawn Location>" == "player" {
        - define selplayer "<npc.flag[BossPlayerList].aslist.random>"  
        - flag <npc> SpawnLocation:<cu@<player[%selplayer%].location.add[-4,0,-4].simple>|<player[%selplayer%].location.add[4,1,4].simple>.get_spawnable_blocks.random>
        - run "BossName Spawn Minion" instantly
        }
        else if "<cons:Stage <npc.flag[BossStage]> Minion Spawn Location>" == cuboid {
          - flag <npc> SpawnLocation:<cu@<npc.flag[cuboid]>.get_spawnable_blocks.random>
          - run "BossName Spawn Minion" instantly
        }
        else if "<cons:Stage <npc.flag[BossStage]> Minion Spawn Location>" == "boss" {  
          - flag <npc> SpawnLocation:<cu@<npc.location.add[-4,0,-4].simple>|<npc.location.add[4,1,4].simple>.get_spawnable_blocks.random>
          - run "BossName Spawn Minion" instantly
        }
      }
    - if <npc.flag[Stage<npc.flag[BossStage]>Minions].size> >= 1 {
      - foreach <npc.flag[Stage<npc.flag[BossStage]>Minions].aslist> {
        - execute as_server "npc sel <%value%.id>"
        - if "<cons:Stage <npc.flag[BossStage]> Minion Weapon>" != none equip %value% "hand:<cons:Stage <npc.flag[BossStage]> Minion Weapon>"
        - if "<cons:Stage <npc.flag[BossStage]> Minion Age>" == baby age %value% baby
        - execute as_server "sentry respawn -1"
        - execute as_server "sentry health <cons:Stage <npc.flag[BossStage]> Minion Health>"
        - execute as_server "sentry strength <cons:Stage <npc.flag[BossStage]> Minion Strength>"
        - execute as_server "sentry armor <cons:Stage <npc.flag[BossStage]> Minion Armor>"
        - execute as_server "sentry target add entity<&co>player"
        - attack %value% target:<npc.flag[BossPlayerList].aslist.random>
        }
      }
    }
 
  # The server then select the boss ID again and also adds "player" type as it's target.
  - ^execute as_server "npc sel <npc.id>"
  - ^execute as_server "sentry target add entity<&co>player"
 
  # Each stage can have a different special attack. This is where that process kicks off. First it checks
  # what the attack is for the particular stage the boss is on, then flags the NPC with the
  # "ActiveSpecialAttackStage" which is used by the special attack tasks to run or cancel further down.
  - ^if "Poison Arrow|Wither Arrow|Weakness Arrow|Slowness Arrow" contains "<cons:Stage <npc.flag[BossStage]> Boss Special Attack>" {
    - flag <npc> ActiveSpecialAttackStage:Arrows
    - run "BossName Special Attack - Arrows" }
    else if "<cons:Stage <npc.flag[BossStage]> Boss Special Attack>" == "Rain Arrows" {
      - flag <npc> "ActiveSpecialAttackStage:Rain Arrows"
      - run "BossName Special Attack - Rain Arrows" }
    else if "<cons:Stage <npc.flag[BossStage]> Boss Special Attack>" == "Lightning Bolt" {
      - flag <npc> "ActiveSpecialAttackStage:Lightning Bolt"
      - run "BossName Special Attack - Lightning Bolt" }
    else if "<cons:Stage <npc.flag[BossStage]> Boss Special Attack>" == "Lightning Storm" {
      - flag <npc> "ActiveSpecialAttackStage:Lightning Storm"
      - run "BossName Special Attack - Lightning Storm" }
    else if "<cons:Stage <npc.flag[BossStage]> Boss Special Attack>" == "TNT" {
      - flag <npc> "ActiveSpecialAttackStage:TNT"
      - run "BossName Special Attack - TNT" }
    else if "<cons:Stage <npc.flag[BossStage]> Boss Special Attack>" == "TNT Drop" {
      - flag <npc> "ActiveSpecialAttackStage:TNT Drop"
      - run "BossName Special Attack - TNT Drop" }
    else if "<cons:Stage <npc.flag[BossStage]> Boss Special Attack>" == "Throw" {
      - flag <npc> "ActiveSpecialAttackStage:Throw"
      - run "BossName Special Attack - Throw" }
    else if "<cons:Stage <npc.flag[BossStage]> Boss Special Attack>" == "Firestarter" {
      - flag <npc> "ActiveSpecialAttackStage:Firestarter"
      - run "BossName Special Attack - Firestarter" }
    else if "<cons:Stage <npc.flag[BossStage]> Boss Special Attack>" == none flag <npc> ActiveSpecialAttackStage:!
 
  # If for some reason Sentry is delayed (known issue which I've logged here: https://github.com/jrbudda/Sentry/issues/161) this will
  # make sure if it's got no target to pick the closest player and attack them.
  - ^if <npc.navigator.target_entity> == null attack <npc> "target:<npc.location.find.players.within[<cons:Boss Awareness Range>].get[1]>"

"BossName Spawn Minion":
    type: task

    script:
    # Here it initially defines the boss stage and then use that to pick:
    # 1) Which effect is used to spawn the minion
    # 2) Give it a name, a type, speed and make it a Sentry.
 
    - define bosstage <npc.flag[BossStage]>
    - if "<cons:Stage %bosstage% Minion Spawn Effect>" == lightning strike no_damage location:<npc.flag[SpawnLocation]>
      else if "<cons:Stage %bosstage% Minion Spawn Effect>" == explode explode power:1 location:<npc.flag[SpawnLocation]>

    # The most effective way to create an NPC is to fit as MANY of the possible parameters into the "npc create" command
    # as possible. This avoids a scenario where the players can witness the NPC's changing or being teleported to where
    # you intended etc.
    - execute as_server "npc create <cons:Stage %bosstage% Minion Name> --at <npc.flag[SpawnLocation]> --type <cons:Stage %bosstage% Minion Type> --speed <cons:Stage %bosstage% Minion Speed> --trait sentry"
 
    # This sets the minions owner to be the boss. It's not really used in this scrpt but I do it anyway.
    - execute as_server "npc owner <npc.name>"
 
    # Assign the "BossName Minion Basics" script below to each minion.
    - execute as_server 'npc assign --set "BossName Minion Basics"'

"BossName Minion Basics":
  type: assignment

  actions:
    on assignment:
    - trigger name:click toggle:true
    - trigger name:damage toggle:true
 
    # Add this NPC id to a global "AllMinions" list.. this is checked by the boss on spawn
    # to clean up any left behind NPC's if something went wrong or server shutdown midway
    # through a fight.
    - ^flag global AllMinions:->:<npc>

    # Flag the minion with the boss ID. This allows the minion to updates flags on the boss,
    # e.g. the "BossPlayerList" or to add itself to the "AllMyMinions" list which is checked
    # during the "BossName Prevent Self Harm" script.
    - ^flag <npc> MinionCreator:<global.flag[TempBossId]>

    # Minion adds itself into the boss's minion list flags.
    - ^flag <npc[<npc.flag[MinionCreator]>]> Stage<npc[<npc.flag[MinionCreator]>].flag[BossStage]>Minions:->:<npc>
    - ^flag <npc[<npc.flag[MinionCreator]>]> AllMyMinions:->:<npc>
    
    # If player exits this proximity range the minion will stop attacking. (Temporary until Sentry is fixed)
    - ^flag npc "Minion Awareness Range:<npc[<npc.flag[MinionCreator]>].flag[Minion Awareness Range]>"
    - ^trigger name:proximity toggle:true "radius:<npc.flag[Minion Awareness Range]>"

    on death by player:
    # When the minion is killed by a player (rather than by other mobs or the environment) it
    # will add 1 to player flag keeping a count of minions killed.
    - flag player MinionsKilledCount:++
 
    # Remove the minion from the "AllMinions" global flag (used to clean up if minions left
    # behind for whatever reason).
    - flag global AllMinions:<-:<npc>

    # Remove the minion from the boss's minion list.
    - flag <npc[<npc.flag[MinionCreator]>]> AllMyMinions:<-:<npc>

    # If the scoreboard is set to record minions killed count, add one to the player score.
    - if <npc[<npc.flag[MinionCreator]>].flag[Scoreboard]> == minionkills execute as_server "scoreboard players add <player.name> <npc[<npc.flag[MinionCreator]>].name.substring[1,5]>.MinionKills 1"

  interact scripts:
  - 5 BossName Minion Damage

"BossName Minion Damage":
  type: interact

  steps:
    1:
      damage trigger:
        script:
        # This damage trigger is very similar to the boss's, so won't explain what happens here.
        - ^if <npc.is_spawned> define phealth <npc.health>
        - ^define mincreator <npc.flag[MinionCreator]>
        - wait 1t
        - ^if <npc[%mincreator%].flag[BossPlayerList].aslist> !contains <player> && <player.name> != <npc[%mincreator%].name> flag <npc[%mincreator%]> BossPlayerList:->:<player>
        - ^if <npc[%mincreator%].flag[BossHitList].aslist> !contains <player> && <player.name> != <npc[%mincreator%].name> flag <npc[%mincreator%]> BossHitList:->:<player>
        - ^if <npc.is_spawned> define finaldamage <el@val[<m:%phealth%-<npc.health>>].asint>
          else define finaldamage <el@val[%phealth%].asint>
        - ^flag player MinionTotalDamage:+:%finaldamage%
        - ^flag player MinionHitCount:++
        - ^if <npc[%mincreator%].flag[Scoreboard]> == minionhealth && %finaldamage% != 0 execute as_server "scoreboard players add <player.name> <npc[%mincreator%].name.substring[1,6]>.MinionDmg %finaldamage%"

      click trigger:
        script:
        - run "BossName Health Status"

      proximity trigger:
        exit:
          script:
          - if <npc.navigator.target_entity> == <player>
            && "<npc.location.find.players.within[<npc.flag[Minion Awareness Range]>].size>" >= 1
            attack <npc> "target:<npc.location.find.players.within[<npc.flag[Minion Awareness Range]>].get[1]>"
            else attack stop
 
#-------------------------------------------------------------------------------#
# There is a chance the NPC (boss or minions) can hurt themselves, so even
# though it's not the most effective world script, it will at least check to
# see if the "damager" is the boss or a minion and if so, cancel the damage
#
# I'm specifically checking the NPC flags so it doesn't cancel damage on other
# NPC's on the server.
#
#-------------------------------------------------------------------------------#

"BossName Prevent Self Harm":
  type: world
  events:
    on npc damaged:
    - if <context.entity> == <context.damager> && <global.flag[ListOfBosses].aslist> contains <context.entity> determine cancelled
      else if <context.entity> == <context.damager> && <global.flag[AllMinions].aslist> contains <context.entity> determine cancelled
      else if <context.damager> == <npc.flag[MinionCreator]> determine cancelled
      else if <npc.flag[AllMyMinions].aslist> contains <context.damager> determine cancelled
 
#-------------------------------------------------------------------------------#
# If you typed "Yes" in the  "Boss Exit Proximity Self Healing" constant value,
# a exit proximity trigger will check to see if there are any players left in
# proximity.. if not, it will run this task below which will heal the NPC 1
# health every 5 seconds.
#
# If players enter proximity, this task is cancelled and the boss will stop
# healing.
#
#-------------------------------------------------------------------------------#

"BossName Self Heal":
    type: task

    script:
    - if <npc.health> < <npc.health.max> && "<npc.location.find.players.within[<cons:Boss Awareness Range>].size>" < 1 && <npc.flag[HealActive]> == null {
      - flag <npc> HealActive
      - heal <npc> 1
      - wait 5
      - flag <npc> HealActive:!
      - run "BossName Self Heal" }
 
#-------------------------------------------------------------------------------#
# The following script builds up a health bar for the NPC. It does
# this by dividing their current health by 10, the result of that, say 7.2 is
# then rounded down to 7. It then repeats a loop 7 times, each time adding
# 10 "|" characters into a flag. So 7 x ||||||||||.. the remaining 2 (7.2)
# then just gets added onto that, e.g. ||
#
# The reason I did it this way was so that it didn't repeat the loop 70 times to
# build up the number of health bars.
#
# In the example, 72 bars will be <GREEN> and the remaining 28 bars will be
# <RED>.
#
# This can be used with any NPC regardless of how much health they have 
# because it uses their "percentage" of health rather than max value health.
#-------------------------------------------------------------------------------#

"BossName Health Status":
  type: task
  script:
  - ^if <npc.health.percentage> == 100
    narrate "<red><npc.name.substring[1,12]> Health<&co><white> [<green>||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||<white>]"
 
    else {
      - ^define GreenTenCount <el@val[<m:floor(<npc.health.percentage>/10)>].asint>
      - ^define GreenTenTotal <el@val[<m:%GreenTenCount%*10>].asint>
      - ^define GreenOneCount <el@val[<m:<npc.health.percentage>-%GreenTenTotal%>].asint>
 
      - ^define RedTenCount <el@val[<m:floor(<m:100-<npc.health.percentage>>/10)>].asint>
      - ^define RedTenTotal <el@val[<m:%RedTenCount%*10>].asint>
      - ^define RedOneCount <el@val[<m:<m:100-<npc.health.percentage>>-%RedTenTotal%>].asint>
 
      - ^repeat %GreenTenCount% {
        - flag <npc> "GreenBars:<npc.flag[GreenBars].replace[null]>||||||||||" }
 
      - ^repeat %GreenOneCount% {
        - flag <npc> "GreenBars:<npc.flag[GreenBars].replace[null]>|" }
 
      - ^repeat %RedTenCount% {
        - flag <npc> "RedBars:<npc.flag[RedBars].replace[null]>||||||||||" }
 
      - ^repeat %RedOneCount% {
        - flag <npc> "RedBars:<npc.flag[RedBars].replace[null]>|" }
 
      - ^if <npc.flag[RedBars]> == null narrate "<red><npc.name.substring[1,12]> Health<&co><white> [<green><npc.flag[GreenBars]><white>]"
        else narrate "<red><npc.name.substring[1,12]> Health<&co><white> [<green><npc.flag[GreenBars]><red><npc.flag[RedBars].replace[null]><white>]"
      - ^flag npc GreenBars:!
      - ^flag npc RedBars:!
    }
 
#-------------------------------------------------------------------------------#
# The next script is used to RESET the boss back to start (health back to 100%,
# all spawned minions removed, all player damage/counter flags reset, all boss
# targets, effects and flags cleared and Minecraft scoreboard removed.
#
# This task will only run if the "Boss Reset Timer" constant value is set to
# 1 or higher and when the last player leaves the boss proximity. When a
# player enters proximity, the "BossResetTimer" flag timer is NULL'ed, so when
# the task runs it fails on the first IF and boss is not reset.
#-------------------------------------------------------------------------------#

"BossName Reset":
    type: task

    script:
    - ^if <npc.flag[BossResetTimer]> != null {
      - foreach "<npc.flag[Enabled Boss Stages].aslist>" {
        - foreach <npc.flag[Stage%value%Minions].aslist> {
          - if <npc> != %value% remove <npc[%value%]>
          }
        }
 
      - foreach "<npc.flag[Enabled Boss Stages].aslist>" {
        - flag <npc> Stage%value%Minions:! }
 
      - announce "<red>BOSS EVENT<&co> <white><npc.name><red> has been reset."
      - foreach <npc.flag[BossHitList].aslist> {
        - flag player:%value% BossPlayerTotalDamage:!
        - flag player:%value% BossPlayerHitCount:!
        - flag player:%value% MinionsKilledCount:!
        - flag player:%value% MinionHitCount:!
        - flag player:%value% MinionTotalDamage:! }
      - foreach <npc.flag[BossSpectatorList].aslist> {
        - if <npc.flag[BossHitList].aslist> contains %value% flag <npc> BossSpectatorList:<-:%value% }
      - execute as_server "npc sel <npc.id>"
      - execute as_server "npc effect --play none"
      - execute as_server "sentry target clear"
      - if <npc.flag[Scoreboard]> != null {
        - if <npc.flag[Scoreboard]> == bosshealth execute as_server "scoreboard objectives remove <npc.name.substring[1,9]>.Damage"
          else if <npc.flag[Scoreboard]> == minionkills execute as_server "scoreboard objectives remove <npc.name.substring[1,5]>.MinionKills"
          else if <npc.flag[Scoreboard]> == minionhealth execute as_server "scoreboard objectives remove <npc.name.substring[1,6]>.MinionDmg"
        }
      - teleport "<npc>" "location:<cons:Boss Spawn Location>"
      - heal <npc>
      - flag <npc> BossHitList:!
      - flag <npc> BossSpectatorList:!
      - flag <npc> BossStage:!
      - flag <npc> BossPlayerList:!
      - flag <npc> BadLoopProtect:!
      - flag <npc> ActiveSpecialAttackStage:!
      - flag <npc> MinionSpawnedStage:!
      - flag <npc> Scoreboard:!
      - flag <npc> AllMyMinions:!
      - flag <npc> BossResetTimer:!
      - flag <npc> HealActive:!
     }
 
#-------------------------------------------------------------------------------#
# The following section contains several scripts that are all used by the 
# "special attack" that is enabled in the constant values "Stage One/Two/Three
# /Four Boss Special Attack" at the top of the script.
#
# When the task is executed, it checks the following criteria:
# * PreventDoubleAttack: This flag is to prevent the task from running
#   when it's already active. If the flag wasn't there it would've happened when
#   another player entered the boss's proximity.
#
# * Find players within a radius specified in constant "Boss Awareness Range"
#   from the NPC: This prevents the task from running if no one is there.
#
# * Boss Stage: This is used to check if the boss is in an attack stage, e.g.
#   the fight isn't over.
#
# * Active Special Attack Stage: Checks if the "Arrows" attack is still
#   relevant for the particular boss stage we're in.
#
# If all of those are met, it waits 5 seconds and then runs the task again. If
# the criteria isn't met, it moves onto the "else if" section where it 
# checks whether the ActiveSpecialAttackStage is null (first time a special
# attack script is executed) OR whether it's looping for a second time and 
# "Arrows" is still the relevant special attack. It then does another check to
# see if there are players within a "Boss Awareness Range" block radius.
#
# After that, it flags the NPC with its current active special attack and puts
# the "PreventDoubleAttack" protection flag in place, with an expiry (just in
# time for the next intended delayed attack). It then finds a random player
# within a "Boss Awareness Range" block radius and uses the "shoot" command to
# shoot the arrow towards their location. Each arrow (entity) that gets fired is
# recorded into a global flag called "ArrowList". This list is used later in the
# world script to check who the arrow came from and what "special attack" to
# apply. e.g. poison, blindness etc.
#
# It then waits for the period of time specified in the "Stage One/Two/Three/Four
# Boss Special Attack Delay", does a quick check to see if there are at least
# one player in proximity and also if this attack is still relevant, e.g. the
# boss isn't into the next stage which may be using another special attack.
#-------------------------------------------------------------------------------#

"BossName Special Attack - Arrows":
    type: task

    script:
    - ^if <npc.flag[PreventDoubleAttack]> != null && "<npc.location.find.players.within[<cons:Boss Awareness Range>].size>" >= 1 && <npc.flag[BossStage]> != null && <npc.flag[ActiveSpecialAttackStage]> == "Arrows" {
      - wait 5s
      - if "<npc.location.find.players.within[<cons:Boss Awareness Range>].size>" >= 1 && <npc.flag[BossStage]> != null && <npc.flag[ActiveSpecialAttackStage]> == "Arrows" run "BossName Special Attack - Arrows" id:Boss<npc.id>SpecialAttack
      }
 
      else if <npc.flag[ActiveSpecialAttackStage]> == null || <npc.flag[ActiveSpecialAttackStage]> == "Arrows" {
        - if "<npc.location.find.players.within[<cons:Boss Awareness Range>]>" != null {
          - flag <npc> ActiveSpecialAttackStage:Arrows
          - flag <npc> PreventDoubleAttack "duration:<cons:Stage <npc.flag[BossStage]> Boss Special Attack Delay>"
          - define arrowplayer "<npc.location.find.players.within[<cons:Boss Awareness Range>].random>"
          - narrate "<red><npc.name> shoots a <npc.flag[CurrentSpecialAttack]> towards <yellow><%arrowplayer%.name><red>..." targets:<npc.flag[BossPlayerList].aslist>
          - shoot i@arrow origin:<npc> destination:<player[%arrowplayer%].location> Height:0.1 save:shot
          - ^foreach <entry[shot].shot_entities> {
            - flag global ArrowList:->:%value% }
          - wait "<cons:Stage <npc.flag[BossStage]> Boss Special Attack Delay>"
          - if "<npc.location.find.players.within[<cons:Boss Awareness Range>].size>" >= 1 && <npc.flag[BossStage]> != null && <npc.flag[ActiveSpecialAttackStage]> == "Arrows" run "BossName Special Attack - Arrows" id:Boss<npc.id>SpecialAttack
          }
      }
 
#-------------------------------------------------------------------------------#
# This script uses a "Cuboid" which are the two values you specified in the
# constant values "Cuboid Spawn Area Poss 1" and "Cuboid Spawn Area Poss 2" at
# the top of the script.
#
# The cuboid should be a square INSIDE your fighting room. If the cuboid is
# larger than your room, you'll have arrows spawning outside of the room.
# 
# If you want to see where your cuboid outline is, type the following command in
# Minecraft, with the NPC selected, and it'll create fake glass blocks that will 
# disappear in 10 seconds:
#
#     /ex showfake glass <<npc.flag[cuboid]>.get_outline> duration:10s
#-------------------------------------------------------------------------------#

"BossName Special Attack - Rain Arrows":
    type: task

    script:
    - ^if <npc.flag[PreventDoubleAttack]> != null && "<npc.location.find.players.within[<cons:Boss Awareness Range>].size>" >= 1 && <npc.flag[BossStage]> != null && <npc.flag[ActiveSpecialAttackStage]> == "Rain Arrows" {
      - wait 5s
      - if "<npc.location.find.players.within[<cons:Boss Awareness Range>].size>" >= 1 && <npc.flag[BossStage]> != null && <npc.flag[ActiveSpecialAttackStage]> == "Rain Arrows" run "BossName Special Attack - Rain Arrows" id:Boss<npc.id>SpecialAttack
      }
 
      else if <npc.flag[ActiveSpecialAttackStage]> == null || <npc.flag[ActiveSpecialAttackStage]> == "Rain Arrows" {
        - if "<npc.location.find.players.within[<cons:Boss Awareness Range>]>" != null {
          - flag <npc> "ActiveSpecialAttackStage:Rain Arrows"
          - flag <npc> PreventDoubleAttack "duration:<cons:Stage <npc.flag[BossStage]> Boss Special Attack Delay>"
          - narrate "<red><npc.name> causes it to <npc.flag[CurrentSpecialAttack]>..." targets:<npc.flag[BossPlayerList].aslist>
          - repeat 50 {
            - define roof <cu@<npc.flag[cuboid]>.max.y.add[-1]>
            - define Xrange <util.random.int[<cu@<npc.flag[cuboid]>.min.x.add[+1].as_int>].to[<cu@<npc.flag[cuboid]>.max.x.add[-1].as_int>]>
            - define Zrange <util.random.int[<cu@<npc.flag[cuboid]>.min.z.add[+1].as_int>].to[<cu@<npc.flag[cuboid]>.max.z.add[-1].as_int>]>
            - spawn i@arrow origin:%Xrange%,%roof%,%Zrange%,world
            }
          - wait "<cons:Stage <npc.flag[BossStage]> Boss Special Attack Delay>"
          - if "<npc.location.find.players.within[<cons:Boss Awareness Range>].size>" >= 1 && <npc.flag[BossStage]> != null && <npc.flag[ActiveSpecialAttackStage]> == "Rain Arrows" run "BossName Special Attack - Rain Arrows" id:Boss<npc.id>SpecialAttack
          }
      }

"BossName Special Attack - Lightning Bolt":
    type: task

    script:
    - ^if <npc.flag[PreventDoubleAttack]> != null && "<npc.location.find.players.within[<cons:Boss Awareness Range>].size>" >= 1 && <npc.flag[BossStage]> != null && <npc.flag[ActiveSpecialAttackStage]> == "Lightning Bolt" {
      - wait 5s
      - if "<npc.location.find.players.within[<cons:Boss Awareness Range>].size>" >= 1 && <npc.flag[BossStage]> != null && <npc.flag[ActiveSpecialAttackStage]> == "Lightning Bolt" run "BossName Special Attack - Lightning Bolt" id:Boss<npc.id>SpecialAttack
      }
 
      else if <npc.flag[ActiveSpecialAttackStage]> == null || <npc.flag[ActiveSpecialAttackStage]> == "Lightning Bolt" {
        - if "<npc.location.find.players.within[<cons:Boss Awareness Range>]>" != null {
          - flag <npc> "ActiveSpecialAttackStage:Lightning Bolt"
          - flag <npc> PreventDoubleAttack "duration:<cons:Stage <npc.flag[BossStage]> Boss Special Attack Delay>"
          - define lightningplayer "<npc.location.find.players.within[<cons:Boss Awareness Range>].random>"
          - narrate "<red><npc.name> calls a <npc.flag[CurrentSpecialAttack]> to hit <yellow><%lightningplayer%.name><red>..." targets:<npc.flag[BossPlayerList].aslist>
          - strike destination:<player[%lightningplayer%].location>
          - wait "<cons:Stage <npc.flag[BossStage]> Boss Special Attack Delay>"
          - if "<npc.location.find.players.within[<cons:Boss Awareness Range>].size>" >= 1 && <npc.flag[BossStage]> != null && <npc.flag[ActiveSpecialAttackStage]> == "Lightning Bolt" run "BossName Special Attack - Lightning Bolt"
          }
      }

"BossName Special Attack - Lightning Storm":
    type: task

    script:
    - ^if <npc.flag[PreventDoubleAttack]> != null && "<npc.location.find.players.within[<cons:Boss Awareness Range>].size>" >= 1 && <npc.flag[BossStage]> != null && <npc.flag[ActiveSpecialAttackStage]> == "Lightning Storm" {
      - wait 5s
      - if "<npc.location.find.players.within[<cons:Boss Awareness Range>].size>" >= 1 && <npc.flag[BossStage]> != null && <npc.flag[ActiveSpecialAttackStage]> == "Lightning Storm" run "BossName Special Attack - Lightning Storm" id:Boss<npc.id>SpecialAttack
      }
 
      else if <npc.flag[ActiveSpecialAttackStage]> == null || <npc.flag[ActiveSpecialAttackStage]> == "Lightning Storm" {
        - if "<npc.location.find.players.within[<cons:Boss Awareness Range>]>" != null {
          - flag <npc> "ActiveSpecialAttackStage:Lightning Storm"
          - flag <npc> PreventDoubleAttack "duration:<cons:Stage <npc.flag[BossStage]> Boss Special Attack Delay>"
          - narrate "<red><npc.name> calls a <npc.flag[CurrentSpecialAttack]> ..." targets:<npc.flag[BossPlayerList].aslist>
          - repeat 10 {
            - define floor <cu@<npc.flag[cuboid]>.min.y>
            - define Xrange <util.random.int[<cu@<npc.flag[cuboid]>.min.x.add[+1].as_int>].to[<cu@<npc.flag[cuboid]>.max.x.add[-1].as_int>]>
            - define Zrange <util.random.int[<cu@<npc.flag[cuboid]>.min.z.add[+1].as_int>].to[<cu@<npc.flag[cuboid]>.max.z.add[-1].as_int>]>
            - strike "destination:%Xrange%,%floor%,%Zrange%,world"
          }
          - wait "<cons:Stage <npc.flag[BossStage]> Boss Special Attack Delay>"
          - if "<npc.location.find.players.within[<cons:Boss Awareness Range>].size>" >= 1 && <npc.flag[BossStage]> != null && <npc.flag[ActiveSpecialAttackStage]> == "Lightning Storm" run "BossName Special Attack - Lightning Storm"
          }
      }

"BossName Special Attack - TNT":
    type: task

    script:
    - ^if <npc.flag[PreventDoubleAttack]> != null && "<npc.location.find.players.within[<cons:Boss Awareness Range>].size>" >= 1 && <npc.flag[BossStage]> != null && <npc.flag[ActiveSpecialAttackStage]> == "TNT" {
      - wait 5s
      - if "<npc.location.find.players.within[<cons:Boss Awareness Range>].size>" >= 1 && <npc.flag[BossStage]> != null && <npc.flag[ActiveSpecialAttackStage]> == "TNT" run "BossName Special Attack - TNT" id:Boss<npc.id>SpecialAttack
      }
 
      else if <npc.flag[ActiveSpecialAttackStage]> == null || <npc.flag[ActiveSpecialAttackStage]> == "TNT" {
        - if  "<npc.location.find.players.within[<cons:Boss Awareness Range>]>" != null {
          - flag <npc> ActiveSpecialAttackStage:TNT
          - flag <npc> PreventDoubleAttack "duration:<cons:Stage <npc.flag[BossStage]> Boss Special Attack Delay>"
          - define targetplayer "<npc.location.find.players.within[<cons:Boss Awareness Range>].random>"
          - narrate "<red><npc.name> lobs <npc.flag[CurrentSpecialAttack]> at <yellow><%targetplayer%.name><red>..." targets:<npc.flag[BossPlayerList].aslist>
          - playsound location:<player[%targetplayer%].location> sound:fuse
          - shoot e@primed_tnt origin:<npc> destination:<player[%targetplayer%].location.simple> Height:0.5
          - wait "<cons:Stage <npc.flag[BossStage]> Boss Special Attack Delay>"
          - if "<npc.location.find.players.within[<cons:Boss Awareness Range>].size>" >= 1 && <npc.flag[BossStage]> != null && <npc.flag[ActiveSpecialAttackStage]> == "TNT" run "BossName Special Attack - TNT" id:Boss<npc.id>SpecialAttack
          }
      }

"BossName Special Attack - TNT Drop":
    type: task

    script:
    - ^if <npc.flag[PreventDoubleAttack]> != null && "<npc.location.find.players.within[<cons:Boss Awareness Range>].size>" >= 1 && <npc.flag[BossStage]> != null && <npc.flag[ActiveSpecialAttackStage]> == "TNT Drop" {
      - wait 5s
      - if "<npc.location.find.players.within[<cons:Boss Awareness Range>].size>" >= 1 && <npc.flag[BossStage]> != null && <npc.flag[ActiveSpecialAttackStage]> == "TNT Drop" run "BossName Special Attack - TNT Drop" id:Boss<npc.id>SpecialAttack
      }
 
      else if <npc.flag[ActiveSpecialAttackStage]> == null || <npc.flag[ActiveSpecialAttackStage]> == "TNT Drop" {
        - if "<npc.location.find.players.within[<cons:Boss Awareness Range>]>" != null {
          - flag <npc> "ActiveSpecialAttackStage:TNT Drop"
          - flag <npc> PreventDoubleAttack "duration:<cons:Stage <npc.flag[BossStage]> Boss Special Attack Delay>"
          - narrate "<red><npc.name> drops primed TNT.. TAKE COVER!" targets:<npc.flag[BossPlayerList].aslist>
          - repeat 5 {
            - define roof <cu@<npc.flag[cuboid]>.max.y.add[-1]>
            - define Xrange <util.random.int[<cu@<npc.flag[cuboid]>.min.x.add[+1].as_int>].to[<cu@<npc.flag[cuboid]>.max.x.add[-1].as_int>]>
            - define Zrange <util.random.int[<cu@<npc.flag[cuboid]>.min.z.add[+1].as_int>].to[<cu@<npc.flag[cuboid]>.max.z.add[-1].as_int>]>
            - spawn e@primed_tnt origin:%Xrange%,%roof%,%Zrange%,world }
        - wait "<cons:Stage <npc.flag[BossStage]> Boss Special Attack Delay>"
        - if "<npc.location.find.players.within[<cons:Boss Awareness Range>].size>" >= 1 && <npc.flag[BossStage]> != null && <npc.flag[ActiveSpecialAttackStage]> == "TNT Drop" run "BossName Special Attack - TNT Drop" id:Boss<npc.id>SpecialAttack
        }
      }
 
 
# The section below is disabled until https://github.com/aufdemrand/Denizen/issues/408 is fixed.
#
#"BossName Special Attack - Invisible":
#    type: task
#
#    script:
#    - ^if <npc.flag[ActiveSpecialAttackStage]> == null || <npc.flag[ActiveSpecialAttackStage]> == "Invisible" flag npc ActiveSpecialAttackStage:Invisible
#    - ^if "<npc.location.find.players.within[<cons:Boss Awareness Range>]>" != null {
#      - narrate "<red><npc.name> goes <npc.flag[CurrentSpecialAttack]>..." "targets:<npc.flag[BossPlayerList].aslist>"
#      - execute as_server "npc sel <npc.id>"
#      - execute as_server "npc effect --play none"
#      - invisible npc state:true
#      - flag npc NoBlood
#      - define teleportplayer "<npc.location.find.players.within[<cons:Boss Awareness Range>].random>"
#      - teleport "<npc>" "location:%teleportplayer%"
#      - wait 10
#      - invisible npc state:false
#      - flag npc NoBlood:!
#      - narrate "<red><npc.name> reappears from thin air..." "targets:<npc.flag[BossPlayerList].aslist>"
#      - execute as_server "npc effect --play <cons:Stage <npc.flag[BossStage]> Boss Aura>
#      - wait "<cons:Stage <npc.flag[BossStage]> Boss Special Attack Delay>"
#      - if "<npc.location.find.players.within[<cons:Boss Awareness Range>].size>" >= 1 && <npc.flag[BossStage]> != null && <npc.flag[ActiveSpecialAttackStage]> == "TNT" run "BossName Special Attack - TNT" id:Boss<npc.id>SpecialAttack
#      }

"BossName Special Attack - Throw":
    type: task

    script:
    - ^if <npc.flag[PreventDoubleAttack]> != null && "<npc.location.find.players.within[<cons:Boss Awareness Range>].size>" >= 1 && <npc.flag[BossStage]> != null && <npc.flag[ActiveSpecialAttackStage]> == "Throw" {
      - wait 5s
      - if "<npc.location.find.players.within[<cons:Boss Awareness Range>].size>" >= 1 && <npc.flag[BossStage]> != null && <npc.flag[ActiveSpecialAttackStage]> == "Throw" run "BossName Special Attack - Throw" id:Boss<npc.id>SpecialAttack }
      else if "<npc.location.find.players.within[<cons:Boss Awareness Range>].size>" >= 1 && <npc.flag[BossStage]> != null && <npc.flag[ActiveSpecialAttackStage]> == "Throw" {
      - flag <npc> PreventDoubleAttack "duration:<cons:Stage <npc.flag[BossStage]> Boss Special Attack Delay>"
      - if <npc.flag[ActiveSpecialAttackStage]> == null || <npc.flag[ActiveSpecialAttackStage]> == "Throw" flag <npc> ActiveSpecialAttackStage:Throw
      - if "<npc.location.find.players.within[<cons:Boss Awareness Range>]>" != null {
        - flag <npc> "ThrowList:|:<npc.location.find.players.within[<cons:Boss Awareness Range>].random[3]>"
        - narrate "<red><npc.name> throws <npc.flag[Throwlist].formatted>..." targets:<npc.flag[BossPlayerList].aslist>
        - foreach <npc.flag[Throwlist].aslist> {
          - flag <npc> ThrowList:<-:%value%
          - define roof <cu@<npc.flag[cuboid]>.max.y.add[-1]>
          - define Xrange <util.random.int[<cu@<npc.flag[cuboid]>.min.x.as_int>].to[<cu@<npc.flag[cuboid]>.max.x.as_int>]>
          - define Zrange <util.random.int[<cu@<npc.flag[cuboid]>.min.z.as_int>].to[<cu@<npc.flag[cuboid]>.max.z.as_int>]>
          - shoot %value% origin:<player[%value%].location.simple> destination:%Xrange%,%roof%,%Zrange%,world height:1.8 gravity:0.32
          }
        - flag <npc> ThrowList:!
        - wait "<cons:Stage <npc.flag[BossStage]> Boss Special Attack Delay>"
        - if "<npc.location.find.players.within[<cons:Boss Awareness Range>].size>" >= 1 && <npc.flag[BossStage]> != null && <npc.flag[ActiveSpecialAttackStage]> == "Throw" run "BossName Special Attack - Throw" id:Boss<npc.id>SpecialAttack
        }
      }

"BossName Special Attack - Firestarter":
    type: task

    script:
    - ^if <npc.flag[PreventDoubleAttack]> != null && "<npc.location.find.players.within[<cons:Boss Awareness Range>].size>" >= 1 && <npc.flag[BossStage]> != null && <npc.flag[ActiveSpecialAttackStage]> == "Firestarter" {
      - wait 5s
      - if "<npc.location.find.players.within[<cons:Boss Awareness Range>].size>" >= 1 && <npc.flag[BossStage]> != null && <npc.flag[ActiveSpecialAttackStage]> == Firestarter run "BossName Special Attack - Firestarter" id:Boss<npc.id>SpecialAttack }
 
      else if "<npc.location.find.players.within[<cons:Boss Awareness Range>].size>" >= 1 && <npc.flag[BossStage]> != null && <npc.flag[ActiveSpecialAttackStage]> == Firestarter {
      - flag <npc> PreventDoubleAttack "duration:<cons:Stage <npc.flag[BossStage]> Boss Special Attack Delay>"
      - if <npc.flag[ActiveSpecialAttackStage]> == null || <npc.flag[ActiveSpecialAttackStage]> == Firestarter flag <npc> ActiveSpecialAttackStage:Firestarter
      - if "<npc.location.find.players.within[<cons:Boss Awareness Range>]>" != null {
        - narrate "<red><npc.name> sets the place on fire..." targets:<npc.flag[BossPlayerList].aslist>
        - repeat 10 {
          - modifyblock location:<cu@<npc.flag[cuboid]>.get_spawnable_blocks.random> fire
          }
        - wait "<cons:Stage <npc.flag[BossStage]> Boss Special Attack Delay>"
        - if "<npc.location.find.players.within[<cons:Boss Awareness Range>].size>" >= 1 && <npc.flag[BossStage]> != null && <npc.flag[ActiveSpecialAttackStage]> == "Firestarter" run "BossName Special Attack - Firestarter" id:Boss<npc.id>SpecialAttack
        }
      }
 
#-------------------------------------------------------------------------------#
# This section is primarily to handle the different types of arrows the boss
# can shoot as part of it's special attacks. It determines which spell to "cast"
# based on what the current active special attack is.
#
# It'll also narrate a random message to the boss player list about who got hit
# and what the effect is.
#
# The other purpose here is to show the "blood" effect when you hit the NPC. It
# uses the the "drip_lava" effect but draws 300 of them to make it look like a
# bloody mist. Thanks to blankiito for this effect!
#-------------------------------------------------------------------------------#

"BossName Special Attack Handler":
  type: world
  events:
  
    on npc damaged by player:
    - if <context.entity> contains <global.flag[ListOfBosses]> && <npc[<context.entity>].flag[NoBlood]> == null {
      - playeffect location:<context.entity.location> effect:DRIP_LAVA radius:10 qty:300 offset:0.15 }

    on player damaged by arrow:
    - ^if <context.projectile> contains <global.flag[ArrowList]> {
      - flag global ArrowList:<-:<context.projectile>
      - if <npc[<context.damager>].flag[CurrentSpecialAttack]> == "Poison Arrow" {
        - cast poison duration:3 power:1 <context.entity>
        - random {
          - narrate "<red>...and hits <yellow><context.entity.name><red>, causing them to bleed from the ears." targets:<npc[<context.damager>].flag[BossPlayerList].aslist>
          - narrate "<red>...and hits <yellow><context.entity.name><red>, causing agonising pain and loss of health." targets:<npc[<context.damager>].flag[BossPlayerList].aslist>
          - narrate "<red>...and hits <yellow><context.entity.name><red>, causing itchy and burning skin blisters." targets:<npc[<context.damager>].flag[BossPlayerList].aslist> }
        }
        else if <npc[<context.damager>].flag[CurrentSpecialAttack]> == "Wither Arrow" {
        - cast wither duration:3 power:1 <context.entity>
        - random {
          - narrate "<red>...and hits <yellow><context.entity.name><red>, causing their skin to peel off." targets:<npc[<context.damager>].flag[BossPlayerList].aslist>
          - narrate "<red>...and hits <yellow><context.entity.name><red>, causing their limbs to decay." targets:<npc[<context.damager>].flag[BossPlayerList].aslist>
          - narrate "<red>...and hits <yellow><context.entity.name><red>, causing their skin to ooze." targets:<npc[<context.damager>].flag[BossPlayerList].aslist> }
        }
        else if <npc[<context.damager>].flag[CurrentSpecialAttack]> == "Weakness Arrow" {
        - cast weakness duration:3 power:1 <context.entity>
        - random {
          - narrate "<red>...and hits <yellow><context.entity.name><red>, causing them to become weak and tired." targets:<npc[<context.damager>].flag[BossPlayerList].aslist>
          - narrate "<red>...and hits <yellow><context.entity.name><red>, causing them to deal less damage." targets:<npc[<context.damager>].flag[BossPlayerList].aslist>
          - narrate "<red>...and hits <yellow<context.entity.name><red>, causing them to hit like a little girl." targets:<npc[<context.damager>].flag[BossPlayerList].aslist> }
        }
        else if <npc[<context.damager>].flag[CurrentSpecialAttack]> == "Slowness Arrow" {
        - cast slow duration:10 power:3 <context.entity>
        - random {
          - narrate "<red>...and hits <yellow><context.entity.name><red>, causing them to become slow and lazy." targets:<npc[<context.damager>].flag[BossPlayerList].aslist>
          - narrate "<red>...and hits <yellow><context.entity.name><red>, causing them to walk at a snails pace." targets:<npc[<context.damager>].flag[BossPlayerList].aslist>
          - narrate "<red>...and hits <yellow><context.entity.name><red>, causing them to be slower than a speeding microorganism." targets:<npc[<context.damager>].flag[BossPlayerList].aslist>
          - narrate "<red>...and hits <yellow><context.entity.name><red>, causing them to be slower than a 1 legged dog on tranquilizers." targets:<npc[<context.damager>].flag[BossPlayerList].aslist>
          - narrate "<red>...and hits <yellow><context.entity.name><red>, causing them to be slower than a geriatric slug on a salted snowed-in street." targets:<npc[<context.damager>].flag[BossPlayerList].aslist>
          - narrate "<red>...and hits <yellow><context.entity.name><red>, causing them to be slower than a snail traveling through peanut butter." targets:<npc[<context.damager>].flag[BossPlayerList].aslist>
          - narrate "<red>...and hits <yellow><context.entity.name><red>, causing them to be slower than Java." targets:<npc[<context.damager>].flag[BossPlayerList].aslist>
          - narrate "<red>...and hits <yellow><context.entity.name><red>, causing them to be slower than quadriplegic in a sack race." targets:<npc[<context.damager>].flag[BossPlayerList].aslist> }
        }
      }
 
#-------------------------------------------------------------------------------#
# Loot can be delivered in 3 different ways. 
# 1) In the player inventory, using the "give" command.
# 2) Drop around where the boss died.
# 3) Inside a chest that spawns in close proximity to where the boss died.
#
# How does it decide the loot? By using a procedure script of course! This
# type of script returns us a single value. Further explained in the next
# section.
#-------------------------------------------------------------------------------#

"BossName Drop the Loot":
    type: task

    script:
    - if "<cons:Loot Distribution>" == "player" {
      - foreach <npc.flag[BossHitList].aslist> {
        - flag <npc> Looter:%value%
        - repeat "<cons:Loot Quantity>" {
          - give to:<player[<npc.flag[looter]>].inventory> "i@<proc:BossName Determine Loot>"
          }
        }
      }
 
      else if "<cons:Loot Distribution>" == boss {
        - foreach <npc.flag[BossHitList].aslist> {
          - repeat "<cons:Loot Quantity>" {
            - drop "i@<proc:BossName Determine Loot>" location:<npc.flag[DeathLocation]>
          }
        }
      }
 
      else if "<cons:Loot Distribution>" == chest {
      - define chestlocation <cu@<npc.location.add[-2,0,-2].simple>|<npc.location.add[2,1,2].simple>.get_spawnable_blocks.random>
      - modifyblock location:%chestlocation% chest
      - foreach <npc.flag[BossHitList].aslist> {
        - repeat "<cons:Loot Quantity>" {
          - give "i@<proc:BossName Determine Loot>" to:<in@location[%chestlocation%]> }
        }
      }
 
      else if "<cons:Loot Distribution>" == playerchest {
      - foreach <npc.flag[BossHitList].aslist> {
        - define chestlocation <cu@<%value%.location.add[-2,0,-2].simple>|<%value%.location.add[2,1,2].simple>.get_spawnable_blocks.random.as_location.block>
        - flag %value% LootChestLocation:%chestlocation%
        - flag <npc> LootChestLocationList:->:%chestlocation%
        - flag global GlobalLootChestLocationList:->:%chestlocation%
        - modifyblock location:%chestlocation% chest
        - repeat "<cons:Loot Quantity>" {
          - give "i@<proc:BossName Determine Loot>" to:<in@location[%chestlocation%]> }
        }
      - flag <npc> PlayersGettingChest:<npc.flag[BossHitList]>        
      }
    - if <npc.flag[LootChestLocationList].size> >= 1 && "<cons:Loot Chest Expiry>" >= 1 run "BossName Loot Chest Expiry" "delay:<cons:Loot Chest Expiry>"
 
#-------------------------------------------------------------------------------#
# This task will run with a delay specified in the "Loot Chest Expiry" constant
# value at the top of the script.
#
# It simply removes the chests and drop the items on the floor.
#-------------------------------------------------------------------------------#

"BossName Loot Chest Expiry":
    type: task

    script:
    - ^foreach <npc.flag[LootChestLocationList].aslist> {
      - if <location[%value%].block.material> == m@chest {
        - flag global GlobalLootChestLocationList:<-:%value%
        - modifyblock %value% air }
      }
    - ^foreach <npc.flag[PlayersGettingChest].aslist> {
      - flag %value% LootChestLocation:! }
    - ^flag <npc> PlayersGettingChest:!
    - ^flag <npc> LootChestLocationList:!
 
#-------------------------------------------------------------------------------#
# The next section is a PROCEDURE script used to return a SINGLE value back to
# our main script. In this case, we just want an ITEM SCRIPT name to be returned.
#
# The script "rolls" a value between 0 to a 100 for each player. If
# it rolls between 0 to 40, set the quality to "Common". If its anywhere between
# 40 to 70, set it to "Uncommon" etc etc.
#
# Then, after the quality has been defined, check which section we'll be getting
# the item from. So, if the %quality% is "Common", it'll go into the
# corresponding braces and run the first command "random 8", which will then
# jump to any one of the following 8 lines.
#
# If it then lands on "Durable Diamond Helmet", that's the value the procedure
# script will return to the main boss script and that's the item that will
# dropped/given to the player.
#-------------------------------------------------------------------------------#

"BossName Determine Loot":
    type: procedure

    script:
    - define roll <util.random.int[1].to[100]>
    - if %roll% >= 0 && %roll% < 40 define quality "Common"
      else if %roll% >= 40 && %roll% < 70 define quality "Uncommon"
      else if %roll% >= 70 && %roll% < 85 define quality "Rare"
      else if %roll% >= 85 && %roll% < 95 define quality "Epic"
      else if %roll% >= 95 define quality "Legendary"
 
    - if %quality% == Common random {
      - determine "Trusty Diamond Axe"
      - determine "Trusty Diamond Sword"
      - determine "Trusty Diamond Hoe"
      - determine "Trusty Diamond Spade"
      - determine "Durable Diamond Helmet"
      - determine "Thorny Diamond Chestplate"
      - determine "Diamond Sword of Looting"
      - determine "Efficient Diamond Pickaxe" }
 
      else if %quality% == Uncommon random {
        - determine "Herder"
        - determine "MerryGoRound"
        - determine "FoolsGold"
        - determine "Doppelganger"
        - determine "PTD" }
 
      else if %quality% == Rare random {
        - determine "Aquamarine"
        - determine "Karthlan Warrior Axe"
        - determine "Flamebane"
        - determine "PhaseShifter" }
 
      else if %quality% == Epic random {
        - determine "Meteorite"
        - determine "Sunflare"
        - determine "Heartburn" }
 
      else if %quality% == Legendary random {
        - determine "Bow of Decay"
        - determine "Hammer of the Gods"
        - determine "Lifestealer"
        - determine "Bloodsucker"
        - determine "Mobcorn" }
 
#-------------------------------------------------------------------------------#
# This section of the script defines the items, their lore and Minecraft
# enchantments. To replace/add enchantments check out the following link:
#
#   http://jd.bukkit.org/rb/apidocs/org/bukkit/enchantments/Enchantment.html
# 
# To get one of these items without fighting the boss, as op, simply substitute
# the name of the item and type the following into your Minecraft chat:
#
#   /ex drop "item:Hammer of the Gods" "location:<player.location>"
#
#--------------------------------- Common Items --------------------------------#

"Trusty Diamond Axe":
   type: item
   material: diamond_axe
   display name: "Trusty Diamond Axe"
   lore:
   - A trusty diamond axe.
   - Common Item
   enchantments:
   - durability:1
   - damage_all:1

"Trusty Diamond Sword":
   type: item
   material: diamond_sword
   display name: "Trusty Diamond Sword"
   lore:
   - A trusty diamond sword.
   - Common Item
   enchantments:
   - durability:1
   - damage_all:1

"Trusty Diamond Hoe":
   type: item
   material: diamond_hoe
   display name: "Trusty Diamond Hoe"
   lore:
   - A trusty diamond hoe.
   - Common Item
   enchantments:
   - durability:1

"Trusty Diamond Spade":
   type: item
   material: diamond_spade
   display name: "Trusty Diamond Spade"
   lore:
   - A trusty diamond spade.
   - Common Item
   enchantments:
   - durability:1

"Durable Diamond Helmet":
   type: item
   material: diamond_helmet
   display name: "Durable Diamond Helmet"
   lore:
   - A durable diamond helmet.
   - Common Item
   enchantments:
   - durability:1

"Thorny Diamond Chestplate":
   type: item
   material: diamond_chestplate
   display name: "Thorny Diamond Chestplate"
   lore:
   - A thorny diamond chestplate.
   - Common Item
   enchantments:
   - durability:2
   - thorns:1

"Diamond Sword of Looting":
   type: item
   material: diamond_sword
   display name: "Diamond Sword of Looting"
   lore:
   - Increased loot drops with this diamond
   - sword.
   - Common Item
   enchantments:
   - loot_bonus_mobs:1
   - durability:2

"Efficient Diamond Pickaxe":
   type: item
   material: diamond_pickaxe
   display name: "Efficient Diamond Pickaxe"
   lore:
   - A fast and durable pickaxe.
   enchantments:
   - durability:2
   - dig_speed:5
 
#-------------------------------- Uncommon Items -------------------------------#

"MerryGoRound":
   type: item
   material: bow
   display name: "MerryGoRound"
   lore:
   - A twisted circus owner forged this to
   - use on his 'less willing' performers.
   - Uncommon Item
   enchantments:
   - durability:3

"PhaseShifter":
   type: item
   material: diamond_sword
   display name: "PhaseShifter"
   lore:
   - Now you see me.. now you don't.
   - Uncommon Item
   enchantments:
   - durability:3

"Herder":
   type: item
   material: diamond_hoe
   display name: "Herder"
   lore:
   - Capture up to 3 friendly mobs inside
   - this magical hoe.
   - Uncommon Item
   enchantments:
   - durability:3

"FoolsGold":
   type: item
   material: gold_nugget
   display name: "Fool's Gold"
   lore:
   - Lure your victims with Fool's Gold
   - and strike them from behind!
   - Uncommon Item

"Doppelganger":
   type: item
   material: feather
   display name: "Doppelganger"
   lore:
   - Doppelganger is a paranormal double
   - of a living enity.
   - Uncommon Item

"PTD":
   type: item
   material: diamond_sword
   display name: "PTD"
   lore:
   - Personal Teleportation Device v0.3
   - Uncommon Item
 
#--------------------------------- Rare Items --------------------------------#

"Flamebane":
   type: item
   material: diamond_chestplate
   display name: "Flamebane"
   lore:
   - Forged in the fires of Mount Regaros
   - for workers to survive extreme mining
   - conditions.
   - Rare Item
   enchantments:
   - protection_explosions:4
   - protection_fire:4
   - protection_environmental:4

"Aquamarine":
   type: item
   material: diamond_helmet
   display name: "Aquamarine"
   lore:
   - Created by the Great Engineers of Karthlan
   - to allow working and mining underwater.
   - Rare Item
   enchantments:
   - water_worker:1
   - oxygen:3
   - durability:3

"Karthlan Warrior Axe":
   type: item
   material: diamond_axe
   display name: "Karthlan Warrior Axe"
   lore:
   - A super durable 2000 year old axe from the
   - destroyed Karthlan dynasty.
   - Rare Item
   enchantments:
   - knockback:2
   - damage_all:5
   - durability:3
 
#--------------------------------- Epic Items --------------------------------#

"Meteorite":
   type: item
   material: stick
   display name: "Meteorite"
   lore:
   - Same as dodgeball, but with flaming
   - hot, explosive magma.
   - Epic Item
   enchantments:
   - durability:3

"Sunflare":
   type: item
   material: diamond_sword
   display name: "Sunflare"
   lore:
   - A forgotten elementalist imbued this sword with
   - the power of the sun to set its victims on fire.
   - Epic Item
   enchantments:
   - fire_espect:2
   - damage_all:5
   - durability:3

"Heartburn":
   type: item
   material: bow
   display name: "Heartburn"
   lore:
   - Coated arrow tips set alight even
   - with the slightest wind friction.
   - Epic Item
   enchantments:
   - arrow_fire:2
   - damage_all:5
   - durability:3
 
#----------------------------- Legendary Items -----------------------------#

"Bow of Decay":
   type: item
   material: bow
   display name: "Bow of Decay"
   lore:
   - A legion of tormented souls imprisoned in this bow fills 
   - each arrow with a millenia of despair and insanity.
   - Legendary Item
   enchantments:
   - durability:3

"Hammer of the Gods":
   type: item
   material: diamond_axe
   display name: "Hammer of the Gods"
   lore:
   - Long lost where even the gods couldn't find it, yet this
   - hammer mysteriously ended up in your hands.
   - Legendary Item
   enchantments:
   - durability:3
   - damage_all:5

"Lifestealer":
   type: item
   material: diamond_sword
   display name: "Lifestealer"
   lore:
   - A sacrifice gone wrong, the sword was removed from 
   - the hands of a baby, dressed in necromancer robes.
   - Legendary Item
   enchantments:
   - durability:3
   - damage_all:5

"Mobcorn":
   type: item
   material: stick
   display name: "Mobcorn"
   lore:
   - What happens when you put a magnetron inside
   - a cow? Only one way to find out.
   - Legendary Item

"Mobcorn Time":
    type: task

    script:
    - narrate "<white><<%1%>.entity_type><red> is going to explode in..." targets:<player.location.find.players.within[10]>
    - if <%1%.is_spawned> { 
      - narrate "<red>3...." targets:<player.location.find.players.within[10]>
      - playsound location:<%1%.location> sound:fuse
      - playeffect location:<%1%.location> effect:fireworks_spark qty:10 }
      else {
        - queue clear 
        - flag player "Mobcorn Cooldown:!" }
    - wait 1
    - if <%1%.is_spawned> { 
      - narrate "<red>2...." targets:<player.location.find.players.within[10]>
      - playeffect location:<%1%.location> effect:fireworks_spark qty:10 }
      else {
        - queue clear 
        - flag player "Mobcorn Cooldown:!" }
    - wait 1 
    - if <%1%.is_spawned> { 
      - narrate "<red>1...." targets:<player.location.find.players.within[10]>
      - playeffect location:<%1%.location> effect:fireworks_spark qty:10 }
      else {
        - queue clear 
        - flag player "Mobcorn Cooldown:!" }
    - wait 1
    - if <%1%.is_spawned> {
      - explode power:2 location:<%1%.location> fire breakblocks
      - if <%1%.is_spawned> remove %1% }
      else {
        - queue clear
        - flag player "Mobcorn Cooldown:!" }
 
 
#------------------- Bloodsucker Legendary Item Section -------------------#
# This item requires its own section because it does a little more than
# the other items. Below is a script similar to the minion script above
# but a lot simpler.
#
# The primary points here are:
# 1) Create the bats
# 2) Add bats to player flag and remove them permanently on death
# 3) Remove bats if their owner or their target exits their proximity.
# 4) Remove the bat after 60 seconds regardless of what it's doing.
#
# Further down there are a couple of world events to remove the bats when
# the player dies or quits the server.
#------------------- Bloodsucker Legendary Item Section -------------------#
 

"Bloodsucker":
   type: item
   material: diamond_sword
   display name: "Bloodsucker"
   lore:
   - Those squeaky noises, glowing red eyes..
   - .... I hope my end is quick.
   - Legendary Item
   enchantments:
   - durability:3

"Spawn Bloodsucker Bat":
    type: task

    script:
    - playeffect location:%1% effect:LARGE_SMOKE
    - execute as_server "npc create Bloodsucker --at %1% --type bat --speed 1.3"
    - execute as_server "npc owner <player.name>"
    - execute as_server 'npc assign --set "Bloodsucker Bat"'

"Bloodsucker Bat":
  type: assignment

  actions:
    on assignment:
    - flag <npc.owner> "BloodsuckerBatList:->:<npc>"
    - trigger name:proximity toggle:true radius:15
    - trigger name:damage toggle:true
    - execute as_server "npc sel <npc.id>"
    - execute as_server "npc lookclose"
    - execute as_server "npc vulnerable"
    - execute as_server "npc health --set 1"
    - flag <npc> Exists
    - run "Bloodsucker Despawn Timer" delay:60s
    
    on death:
    - flag <npc.owner> "BloodsuckerBatList:<-:<npc>"
    - flag <npc> Exists:!
    - remove <npc>

  interact scripts:
  - 5 Bloodsucker Interaction

"Bloodsucker Interaction":
  type: interact

  steps:
    1:
      damage trigger:
        script:
        - playsound location:<npc.location> sound:bat_idle

      proximity trigger:
        exit:
          script:
          - ^if "<player[<npc.owner>].flag[Bloodsucker Target]>" == <player> || <player.name> == <npc.owner> {
            - flag <npc.owner> "BloodsuckerBatList:<-:<npc>"
            - remove <npc> }

"Bloodsucker Despawn Timer":
    type: task

    script:
    - if <npc.flag[Exists]> remove <npc>

#-------------------------------------------------------------------------------#
# The section below handles the world events to make all the "cool stuff"
# possible. It means that every time one of these events occur in the world, it
# will be evaluated against some criteria to see if the "cool stuff" should
# happen.
#
# For example, every time any entity (<context.entity>) in the world is damaged
# by an arrow, it checks to see if the person (<context.damager>) that fired the
# arrow is holding an item with the following two lore descriptions:
#
#   * A legion of tormented souls imprisoned in this bow fills
#   * A twisted circus owner forged this to
#
# If they are and there are no cooldowns in effect, it'll run the relevant
# (cast or rotate) commands on the entity that got hit.
#-------------------------------------------------------------------------------#

"Legendary and Epic Item Effects":
  type: world
  events:

    on entity damaged by arrow:
    - if "<player[<context.damager>].item_in_Hand.lore.contains[A legion of tormented souls imprisoned in this bow fills]>" == true {
      - cast wither duration:10 power:1 <context.entity>
      - playsound location:<context.entity.location> sound:wither_death volume:2 pitch:0.01
      - if <context.entity.is_player> && "<player[<context.entity>].flag[Hit by Bow of Decay]>" == null {
        - flag <context.entity> "Hit by Bow of Decay" duration:120s
        - narrate "<red>You feel your flesh peeling away...strange voices in your head..so much hate.." targets:<context.entity>
        }
      }
 
      else if "<player[<context.damager>].item_in_Hand.lore.contains[A twisted circus owner forged this to]>" == true {
      - if <context.entity.is_player> && "<player[<context.entity>].flag[Hit by MerryGoRound]>" == null {
        - flag <context.entity> "Hit by MerryGoRound" duration:5s
        - narrate "<red>The eery twisted music of a deserted, foggy circus makes you turn...round and round..." targets:<context.entity> }
      - rotate <context.entity> duration:5s
      }
 
    # This handles the effect on an entity getting hit directly by a player. Since it knows
    # who the player is, you can just use <player...> rather than <context.damager>. Which
    # makes it a bit easier to flag the player etc.
    #
    # It compares 3 different weapons, using the "lore" as the method, in this case, to
    # identify which weapon was used.
    on entity damaged by player:
    - if "<player.item_in_Hand.lore.contains[Long lost where even the gods couldn't find it, yet this]>" {
      - if <context.entity.is_player> && "<player.flag[Hit by Hammer of the Gods]>" == null {
        - flag <player> "Hit by Hammer of the Gods" duration:120s
        - narrate "<red>The gods curse you... your end is near..." targets:<context.entity> }
      - strike destination:<context.entity.location> }
 
      else if "<player.item_in_Hand.lore.contains[A sacrifice gone wrong, the sword was removed from]>" {
        - playsound location:<context.entity.location> sound:enderdragon_growl volume:0.2 pitch:0.01
        - heal <context.damager> 1
        - hurt <context.entity> 1
      }
 
      else if "<player.item_in_Hand.lore.contains[Those squeaky noises, glowing red eyes..]>" {
        - if "<player.flag[Bloodsucker Cooldown]>" == null && "<player.flag[BloodsuckerBatList].size>" == 0 && <context.entity> !contains <player.flag[BloodsuckerBatList].aslist> {
          - flag <player> "Bloodsucker Cooldown" duration:10s
          - flag <player> "Bloodsucker Target:<context.entity>"
          - foreach <cu@<context.entity.location.add[-2,0,-2].simple>|<context.entity.location.add[2,1,2].simple>.get_spawnable_blocks.random[3]> {
            - run instantly "Spawn Bloodsucker Bat" context:%value% }
          - foreach <player.flag[BloodsuckerBatList].aslist> {
            - attack %value% target:<context.entity> }
          }
 
          else if <player.flag[BloodsuckerBatList].size> >= 1 && <context.entity> contains <player.flag[BloodsuckerBatList].aslist> {
            - flag <player> "Bloodsucker Target:<context.entity>"
            - foreach <player.flag[BloodsuckerBatList].aslist> {
              - playeffect location:<cu@<context.entity.location.add[-2,0,-2].simple>|<context.entity.location.add[2,2,2].simple>.get_spawnable_blocks.random> effect:large_smoke
              - teleport %value% location:<cu@<context.entity.location.add[-2,-1,-2].simple>|<context.entity.location.add[2,1,2].simple>.get_spawnable_blocks.random> }
            - foreach <player.flag[BloodsuckerBatList].aslist> {
              - attack %value% target:<context.entity> }
          }
      }
 
      else if "<player.item_in_Hand.lore.contains[Personal Teleportation Device v0.3]>" determine cancelled

    on player right clicks with i@PTD:
    - if "<player.flag[PTD Locations]>" != null {
      - playsound location:<player.location> sound:enderman_teleport
      - playeffect location:<player.location> effect:large_smoke
      - narrate "<red>Teleporting to Saved Location [<yellow><player.flag[PTD Locations].size><red>]<&co><white> <player.flag[PTD Locations].get[<player.flag[PTD Locations].size>]>"
      - teleport <player> "location:<player.flag[PTD Locations].get[<player.flag[PTD Locations].size>]>"
      - flag <player> "PTD Locations[<player.flag[PTD Locations].size>]:<-"
      - playsound location:<player.location> sound:enderman_teleport
      - playeffect location:<player.location> effect:large_smoke }
 
      else narrate "<red>You have no coordinates loaded in your PTD..."

    on player left clicks block with i@PTD:
    - if "<player.flag[PTD Locations]>" == null {
      - flag <player> "PTD Locations:<player.location.cursor_on.add[0,1,0].simple>"
      - narrate "<red>Saved Location [<yellow><player.flag[PTD Locations].size>/3<red>]<&co><white> <player.flag[PTD Locations].get[<player.flag[PTD Locations].size>]>" }
 
      else if "<player.flag[PTD locations].size>" = 1 {
        - flag <player> "PTD Locations:->:<player.location.cursor_on.add[0,1,0].simple>"
        - narrate "<red>Saved Location [<yellow><player.flag[PTD Locations].size>/3<red>]<&co><white> <player.flag[PTD Locations].get[<player.flag[PTD Locations].size>]>" }
 
      else if "<player.flag[PTD locations].size>" = 2 {
        - flag <player> "PTD Locations:->:<player.location.cursor_on.add[0,1,0].simple>"
        - narrate "<red>Saved Location [<yellow><player.flag[PTD Locations].size>/3<red>]<&co><white> <player.flag[PTD Locations].get[<player.flag[PTD Locations].size>]>" }
 
      else narrate "<red>Your PTD v0.3 is out of memory. You cannot store any more coordinates."
 
    # Here we specifically only fire this event if the player right clicks, an entity (mobs only), using the item "Herder".
    # It checks the entity type and store the value inside a player flag. It then "removes" the entity but
    # makes it seem like their soul was captured inside the Herder.
    on player right clicks entity with i@Herder:
    - if <player.flag[HerderList].size> >= 3 narrate "<red>The <white>Herder<red> is full and cannot capture any more souls..."
      else if <context.entity.is_mob> {
        - flag <player> HerderList:->:<context.entity.entity_type>
        - playeffect location:<context.entity.location> effect:witch_magic
        - remove <context.entity>
        - if <player.flag[HerderList].size> == 1 narrate "<red>You have trapped the soul of a <player.flag[HerderList].formatted>..."
          else if <player.flag[HerderList].size> >= 2 narrate "<red>You have trapped the souls of <player.flag[HerderList].formatted>.."
      }
 
    # In this event, it checks to see if there are any entity types in the "HerderList" player flag, if so it
    # spawns the mobs at the cursor location, using the "safe spawn" tag "get_spawnable_blocks".
    on player right clicks block with i@Herder:
    - if <player.flag[HerderList]> != null {
      - narrate "<red>Releasing <player.flag[HerderList].formatted>..."
      - foreach <player.flag[HerderList].aslist> {
        - spawn %value% location:<cu@<player.location.cursor_on.add[-1,0,-1].simple>|<player.location.cursor_on.add[1,2,1].simple>.get_spawnable_blocks.random> }
      - flag <player> "HerderList:!"
      }
 
    # This section also uses the "get_spawnable_blocks" tag to find an appropriate location to "showfake"
    # a few valuable blocks. They automatically despawn after 120s unless they are destroyed earlier.
    # WARNING: Will allow spawning fake blocks in protected areas.
    on player right clicks block with i@FoolsGold:
    - if "<player.flag[Fools Gold Cooldown]>" == null {
      - flag player "Fools Gold Cooldown" duration:120s
      - showfake diamond_block location:<cu@<player.location.cursor_on.add[-1,0,-1].simple>|<player.location.cursor_on.add[1,2,1].simple>.get_spawnable_blocks.random> duration:120s
      - showfake gold_block location:<cu@<player.location.cursor_on.add[-1,0,-1].simple>|<player.location.cursor_on.add[1,2,1].simple>.get_spawnable_blocks.random> duration:120s
      - showfake chest location:<cu@<player.location.cursor_on.add[-1,0,-1].simple>|<player.location.cursor_on.add[1,2,1].simple>.get_spawnable_blocks.random> duration:120s
      }
      else narrate "<white><player.flag[Fools Gold Cooldown].expiration.formatted><red> before you can use <white>Fool's Gold<red> again."
 
    # This item script checks to see if the entity clicked is a mob and if the cooldown expired,
    # then runs a script called "Mobcorn Time", which provides a count down timer before
    # the mob explodes!
    # WARNING: Can probably damage and set protected zones on fire!!
    on player right clicks entity with i@Mobcorn:
    - if "<player.flag[Mobcorn Cooldown]>" == null && <context.entity.is_mob> {
      - flag <player> "Mobcorn Cooldown" duration:10s
      - run "Mobcorn Time" def:<context.entity>
      }
       else if "<player.flag[Mobcorn Cooldown]>" != null narrate "<red>Please wait for Mobcorn to cooldown..."
 

    on player right clicks entity with i@Doppelganger:
    - if <context.entity.equipment.helmet.skin> == <player.name> narrate "<red>Entity is already your Doppelganger."
      else if <context.entity.is_mob> || <context.entity.is_player> {
        - if "<player.flag[Doppelganger Cooldown]>" == null {
          - if "<context.entity.equipment.helmet>" != null && <context.entity.is_player> {
            - give to:<context.entity.inventory> <context.entity.equipment.helmet> }
          - flag <player> "Doppelganger Cooldown" duration:30s
          - head <context.entity> skin:<player> }
      }
 
      else if "<player.flag[Doppelganger Cooldown]>" != null narrate "<white><player.flag[Doppelganger Cooldown].expiration.formatted><red> before you can use <white>Doppelganger<red> again."
 
    # Shoot fireballs in the direction of where the cursor is, they have "weight" so it gives
    # a "bullet drop" effect.
    # WARNING: Can probably damage and set protected zones on fire!!
    on player right clicks with i@Meteorite:
    - if "<player.flag[Meteorite Cooldown]>" == null {
      - flag <player> "Meteorite Cooldown" duration:3s
      - shoot e@fireball height:0.05 gravity:0.01 }
 
    # This script will teleport any player, where no cooldown is in effect, to a "safe" location within
    # a 20 block radius. Above or below ground.
    # WARNING: This will allow players to get into protected buildings!!
    on player right clicks with i@PhaseShifter:
    - if "<player.flag[PhaseShifter Cooldown]>" == null {
      - flag <player> "PhaseShifter Cooldown" duration:3s
      - if "<player.flag[PhaseShifter Narrate Cooldown]>" == null {
        - random {
          - narrate "<white><player.name><red> shimmer and disappears..." targets:<player.location.find.players.within[10]>
          - narrate "<white><player.name><red> teleports to a nearby location..." targets:<player.location.find.players.within[10]>
          - narrate "<white>With a puff of smoke, <white><player.name><red> teleports not too far away.." targets:<player.location.find.players.within[10]> }
        }
      - flag <player> "PhaseShifter Narrate Cooldown" duration:30s
      - playsound location:<player.location> sound:enderman_teleport
      - playeffect location:<player.location> effect:large_smoke
      - teleport <player> location:<cu@<player.location.add[-20,-10,-20].simple>|<player.location.add[20,20,20].simple>.get_spawnable_blocks.random>
      - playsound location:<player.location> sound:enderman_teleport
      - playeffect location:<player.location> effect:large_smoke }
 
    # This section is relevant if the boss drop uses the "playerchest" method. It controls who can
    # access the contents of the chest. If the player flag "LootChestLocation" does not match
    # the location of the chest it uses "determine cancelled" to prevent the inventory window from
    # showing up.
    on player opens chest:
    - if <global.flag[GlobalLootChestLocationList].aslist> contains <context.inventory.location> {
      - if <player.flag[LootChestLocation]> != <context.inventory.location> {
        - narrate "<red>You cannot access the contents of this chest."
        - determine cancelled }
      }
 
    # If the chest location is on the player flag and the global "GlobalLootChestLocation" list
    # it will despawn when it's closed.
    on player closes chest:
     - if <player.flag[LootChestLocation]> == <context.inventory.location> && <global.flag[GlobalLootChestLocationList].aslist> contains <context.inventory.location> && <context.inventory.location> != null {
       - narrate "<red>Chest has been despawned..."
       - flag <player> LootChestLocation:!
       - flag global GlobalLootChestLocationList:<-:<context.inventory.location>
       - modifyblock <context.inventory.location> air }
 
    # The following two events run when a player quits or dies. This is to clean up/remove
    # any bats that were spawned with the Bloodsucker item.
    on player quits:
    - if <player.flag[BloodsuckerBatList].size> >= 1 {
      - foreach <player.flag[BloodsuckerBatList].aslist> {
        - flag <player> BloodsuckerBatList:<-:%value%
        - remove %value% }
      - flag <player> BloodsuckerBatList:!
      }
    
    on player dies:
    - if <player.flag[BloodsuckerBatList].size> >= 1 {
      - foreach <player.flag[BloodsuckerBatList].aslist> {
        - flag <player> BloodsuckerBatList:<-:%value%
        - remove %value% }
      - flag <player> BloodsuckerBatList:!
      }




Comments
2013-12-26 23:14:18 - Tacoaloto:

I have no idea how to make the boss do damage. like his minions do damage to me, but I can't hurt neither the boss or minions, and the boss doesn't do anything but run up to me
2014-01-07 01:51:11 - Tacoaloto:

Found a solution! pvp was disabled on the world I spawned him on for some reason
2014-03-14 16:00:04 - DarthRiddle:

This script may be out of date? The boss battle randomly works and generally never re-spawns right off the default script. Is this still a supported script?
2014-11-17 10:39:56 - mcmonkey:

Jabeltoo updated this script, available here: https://github.com/Jabelpeeps/My-Denizen-scripts