# 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:" # 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@|" # The following commands sets up the Boss using the values specified in the # constants above. - execute as_server "npc sel " - execute as_server "npc type " - if "" == baby age baby - execute as_server "npc speed " - execute as_server "npc lookclose" - execute as_server "trait sentry" - execute as_server "sentry health " - execute as_server "sentry respawn " - execute as_server "sentry speed " - execute as_server "sentry strength " - execute as_server "sentry armor " - execute as_server "sentry range " - if "" != none execute as_server "sentry equip " # 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:" # This is used in world events further down to prevent self/minion harm. - flag global ListOfBosses: # 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:" on spawn: # Teleport boss back to starting point. - teleport "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 { - flag npc BossDied:! - foreach { - if != true && != null { - flag global AllMinions:<-:%value% - remove %value% } } - execute as_server "npc sel " - execute as_server "sentry target clear" - if "].block.sign_contents>" contains modifyblock air - if != none && == null { - flag Scoreboard: - if == "bosshealth" { - execute as_server "scoreboard objectives add .Damage dummy" - execute as_server "scoreboard objectives setDisplay sidebar .Damage" } else if == "minionkills" { - execute as_server "scoreboard objectives add .MinionKills dummy" - execute as_server "scoreboard objectives setDisplay sidebar .MinionKills" } else { - execute as_server "scoreboard objectives add .MinionDmg dummy" - execute as_server "scoreboard objectives setDisplay sidebar .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 "" { - foreach "" { - if != %value% remove } } # It then clears the minion list for each battle stage. - foreach "" { - flag "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: - sign "|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 != null { - announce "BOSS EVENT<&co> has been killed by ." - announce "------------------------------------------" - announce "Battle Stats<&co>" - announce "" - announce " Total Health<&co> " - foreach { - define bosspercentage /*100>].asint> - announce "<%value%.name>|" - announce "Boss Damage (<%bosspercentage%><&pc>) - Hits| " - if != null { - announce "Combined Minion Damage - Hits| - Minions Killed| " } - flag player:%value% BossPlayerTotalDamage:! - flag player:%value% BossPlayerHitCount:! - flag player:%value% MinionsKilledCount:! - flag player:%value% MinionHitCount:! - flag player:%value% MinionTotalDamage:! } - announce "------------------------------------------" - foreach { - if contains %value% flag npc BossSpectatorList:<-:%value% } - if >= 1 announce "Spectators| " - if "" == "Yes" run "BossName Drop the Loot" instantly } # Remove any visual effects applied at fight stages and clear sentry targets. - execute as_server "npc sel " - 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 != null { - if == "bosshealth" execute as_server "scoreboard objectives remove .Damage" else if == "minionkills" execute as_server "scoreboard objectives remove .MinionKills" else if == "minionhealth" execute as_server "scoreboard objectives remove .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 !contains && != flag npc BossPlayerList:->: # Add players to the spectator list, which shows up in the battle stats after the boss fight. - if !contains && != flag npc BossSpectatorList:->: # 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 "" == "proximity" && == null { - flag npc BossStage:One - run "BossName Fight" } else if != 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 == && "].size>" >= 1 attack "target:].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 "].size>" < 1 && != null && "" == "Yes" { - run "BossName Self Heal" id:_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 "].size>" < 1 && != null && "" >= 1 && == null { - flag BossResetTimer - run "BossName Reset" id:_ResetTimer "delay:" } 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 define phealth # 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 !contains && != flag BossPlayerList:->: # 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 !contains && != flag BossHitList:->: # 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 "" contains One && == null && <= "" { - flag npc BossStage:One - run "BossName Fight" } else if "" contains Two && == One && <= "" { - flag npc BossStage:Two - run "BossName Fight" } else if "" contains Three && == Two && <= "" { - flag npc BossStage:Three - run "BossName Fight" } else if "" contains Four && == Three && <= "" { - 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 define finaldamage >].asint> else define finaldamage %phealth% - ^flag player BossPlayerTotalDamage:+:%finaldamage% # Add the damage amount into the Minecraft scoreboard. (Right hand side of players screen). - if == bosshealth && %finaldamage% != 0 execute as_server "scoreboard players add .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 "Boss Stage - Health %" targets: - ^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: 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 " Boss Aura>" { - execute as_server "npc sel " - execute as_server "npc effect --play none" - execute as_server "npc effect --play Boss Aura>" } else { - execute as_server "npc sel " - 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 " Spawn Minions>" == "Yes" && != { - flag MinionSpawnedStage: - repeat " Minion Quantity>" { - flag global TempBossId: - if " Minion Spawn Location>" == "player" { - define selplayer "" - flag SpawnLocation:|.get_spawnable_blocks.random> - run "BossName Spawn Minion" instantly } else if " Minion Spawn Location>" == cuboid { - flag SpawnLocation:.get_spawnable_blocks.random> - run "BossName Spawn Minion" instantly } else if " Minion Spawn Location>" == "boss" { - flag SpawnLocation:|.get_spawnable_blocks.random> - run "BossName Spawn Minion" instantly } } - if Minions].size> >= 1 { - foreach Minions].aslist> { - execute as_server "npc sel <%value%.id>" - if " Minion Weapon>" != none equip %value% "hand: Minion Weapon>" - if " Minion Age>" == baby age %value% baby - execute as_server "sentry respawn -1" - execute as_server "sentry health Minion Health>" - execute as_server "sentry strength Minion Strength>" - execute as_server "sentry armor Minion Armor>" - execute as_server "sentry target add entity<&co>player" - attack %value% target: } } } # The server then select the boss ID again and also adds "player" type as it's target. - ^execute as_server "npc sel " - ^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 " Boss Special Attack>" { - flag ActiveSpecialAttackStage:Arrows - run "BossName Special Attack - Arrows" } else if " Boss Special Attack>" == "Rain Arrows" { - flag "ActiveSpecialAttackStage:Rain Arrows" - run "BossName Special Attack - Rain Arrows" } else if " Boss Special Attack>" == "Lightning Bolt" { - flag "ActiveSpecialAttackStage:Lightning Bolt" - run "BossName Special Attack - Lightning Bolt" } else if " Boss Special Attack>" == "Lightning Storm" { - flag "ActiveSpecialAttackStage:Lightning Storm" - run "BossName Special Attack - Lightning Storm" } else if " Boss Special Attack>" == "TNT" { - flag "ActiveSpecialAttackStage:TNT" - run "BossName Special Attack - TNT" } else if " Boss Special Attack>" == "TNT Drop" { - flag "ActiveSpecialAttackStage:TNT Drop" - run "BossName Special Attack - TNT Drop" } else if " Boss Special Attack>" == "Throw" { - flag "ActiveSpecialAttackStage:Throw" - run "BossName Special Attack - Throw" } else if " Boss Special Attack>" == "Firestarter" { - flag "ActiveSpecialAttackStage:Firestarter" - run "BossName Special Attack - Firestarter" } else if " Boss Special Attack>" == none flag 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 == null attack "target:].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 - if "" == lightning strike no_damage location: else if "" == explode explode power:1 location: # 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 --at --type --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 " # 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:->: # 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 MinionCreator: # Minion adds itself into the boss's minion list flags. - ^flag ]> Stage].flag[BossStage]>Minions:->: - ^flag ]> AllMyMinions:->: # If player exits this proximity range the minion will stop attacking. (Temporary until Sentry is fixed) - ^flag npc "Minion Awareness Range:].flag[Minion Awareness Range]>" - ^trigger name:proximity toggle:true "radius:" 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:<-: # Remove the minion from the boss's minion list. - flag ]> AllMyMinions:<-: # If the scoreboard is set to record minions killed count, add one to the player score. - if ].flag[Scoreboard]> == minionkills execute as_server "scoreboard players add ].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 define phealth - ^define mincreator - wait 1t - ^if !contains && != flag BossPlayerList:->: - ^if !contains && != flag BossHitList:->: - ^if define finaldamage >].asint> else define finaldamage - ^flag player MinionTotalDamage:+:%finaldamage% - ^flag player MinionHitCount:++ - ^if == minionhealth && %finaldamage% != 0 execute as_server "scoreboard players add .MinionDmg %finaldamage%" click trigger: script: - run "BossName Health Status" proximity trigger: exit: script: - if == && "].size>" >= 1 attack "target:].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 == && contains determine cancelled else if == && contains determine cancelled else if == determine cancelled else if contains 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 < && "].size>" < 1 && == null { - flag HealActive - heal 1 - wait 5 - flag 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 and the remaining 28 bars will be # . # # 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 == 100 narrate " Health<&co> [||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||]" else { - ^define GreenTenCount /10)>].asint> - ^define GreenTenTotal ].asint> - ^define GreenOneCount -%GreenTenTotal%>].asint> - ^define RedTenCount >/10)>].asint> - ^define RedTenTotal ].asint> - ^define RedOneCount >-%RedTenTotal%>].asint> - ^repeat %GreenTenCount% { - flag "GreenBars:||||||||||" } - ^repeat %GreenOneCount% { - flag "GreenBars:|" } - ^repeat %RedTenCount% { - flag "RedBars:||||||||||" } - ^repeat %RedOneCount% { - flag "RedBars:|" } - ^if == null narrate " Health<&co> []" else narrate " Health<&co> []" - ^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 != null { - foreach "" { - foreach { - if != %value% remove } } - foreach "" { - flag Stage%value%Minions:! } - announce "BOSS EVENT<&co> has been reset." - foreach { - flag player:%value% BossPlayerTotalDamage:! - flag player:%value% BossPlayerHitCount:! - flag player:%value% MinionsKilledCount:! - flag player:%value% MinionHitCount:! - flag player:%value% MinionTotalDamage:! } - foreach { - if contains %value% flag BossSpectatorList:<-:%value% } - execute as_server "npc sel " - execute as_server "npc effect --play none" - execute as_server "sentry target clear" - if != null { - if == bosshealth execute as_server "scoreboard objectives remove .Damage" else if == minionkills execute as_server "scoreboard objectives remove .MinionKills" else if == minionhealth execute as_server "scoreboard objectives remove .MinionDmg" } - teleport "" "location:" - heal - flag BossHitList:! - flag BossSpectatorList:! - flag BossStage:! - flag BossPlayerList:! - flag BadLoopProtect:! - flag ActiveSpecialAttackStage:! - flag MinionSpawnedStage:! - flag Scoreboard:! - flag AllMyMinions:! - flag BossResetTimer:! - flag 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 != null && "].size>" >= 1 && != null && == "Arrows" { - wait 5s - if "].size>" >= 1 && != null && == "Arrows" run "BossName Special Attack - Arrows" id:BossSpecialAttack } else if == null || == "Arrows" { - if "]>" != null { - flag ActiveSpecialAttackStage:Arrows - flag PreventDoubleAttack "duration: Boss Special Attack Delay>" - define arrowplayer "].random>" - narrate " shoots a towards <%arrowplayer%.name>..." targets: - shoot i@arrow origin: destination: Height:0.1 save:shot - ^foreach { - flag global ArrowList:->:%value% } - wait " Boss Special Attack Delay>" - if "].size>" >= 1 && != null && == "Arrows" run "BossName Special Attack - Arrows" id:BossSpecialAttack } } #-------------------------------------------------------------------------------# # 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 <.get_outline> duration:10s #-------------------------------------------------------------------------------# "BossName Special Attack - Rain Arrows": type: task script: - ^if != null && "].size>" >= 1 && != null && == "Rain Arrows" { - wait 5s - if "].size>" >= 1 && != null && == "Rain Arrows" run "BossName Special Attack - Rain Arrows" id:BossSpecialAttack } else if == null || == "Rain Arrows" { - if "]>" != null { - flag "ActiveSpecialAttackStage:Rain Arrows" - flag PreventDoubleAttack "duration: Boss Special Attack Delay>" - narrate " causes it to ..." targets: - repeat 50 { - define roof .max.y.add[-1]> - define Xrange .min.x.add[+1].as_int>].to[.max.x.add[-1].as_int>]> - define Zrange .min.z.add[+1].as_int>].to[.max.z.add[-1].as_int>]> - spawn i@arrow origin:%Xrange%,%roof%,%Zrange%,world } - wait " Boss Special Attack Delay>" - if "].size>" >= 1 && != null && == "Rain Arrows" run "BossName Special Attack - Rain Arrows" id:BossSpecialAttack } } "BossName Special Attack - Lightning Bolt": type: task script: - ^if != null && "].size>" >= 1 && != null && == "Lightning Bolt" { - wait 5s - if "].size>" >= 1 && != null && == "Lightning Bolt" run "BossName Special Attack - Lightning Bolt" id:BossSpecialAttack } else if == null || == "Lightning Bolt" { - if "]>" != null { - flag "ActiveSpecialAttackStage:Lightning Bolt" - flag PreventDoubleAttack "duration: Boss Special Attack Delay>" - define lightningplayer "].random>" - narrate " calls a to hit <%lightningplayer%.name>..." targets: - strike destination: - wait " Boss Special Attack Delay>" - if "].size>" >= 1 && != null && == "Lightning Bolt" run "BossName Special Attack - Lightning Bolt" } } "BossName Special Attack - Lightning Storm": type: task script: - ^if != null && "].size>" >= 1 && != null && == "Lightning Storm" { - wait 5s - if "].size>" >= 1 && != null && == "Lightning Storm" run "BossName Special Attack - Lightning Storm" id:BossSpecialAttack } else if == null || == "Lightning Storm" { - if "]>" != null { - flag "ActiveSpecialAttackStage:Lightning Storm" - flag PreventDoubleAttack "duration: Boss Special Attack Delay>" - narrate " calls a ..." targets: - repeat 10 { - define floor .min.y> - define Xrange .min.x.add[+1].as_int>].to[.max.x.add[-1].as_int>]> - define Zrange .min.z.add[+1].as_int>].to[.max.z.add[-1].as_int>]> - strike "destination:%Xrange%,%floor%,%Zrange%,world" } - wait " Boss Special Attack Delay>" - if "].size>" >= 1 && != null && == "Lightning Storm" run "BossName Special Attack - Lightning Storm" } } "BossName Special Attack - TNT": type: task script: - ^if != null && "].size>" >= 1 && != null && == "TNT" { - wait 5s - if "].size>" >= 1 && != null && == "TNT" run "BossName Special Attack - TNT" id:BossSpecialAttack } else if == null || == "TNT" { - if "]>" != null { - flag ActiveSpecialAttackStage:TNT - flag PreventDoubleAttack "duration: Boss Special Attack Delay>" - define targetplayer "].random>" - narrate " lobs at <%targetplayer%.name>..." targets: - playsound location: sound:fuse - shoot e@primed_tnt origin: destination: Height:0.5 - wait " Boss Special Attack Delay>" - if "].size>" >= 1 && != null && == "TNT" run "BossName Special Attack - TNT" id:BossSpecialAttack } } "BossName Special Attack - TNT Drop": type: task script: - ^if != null && "].size>" >= 1 && != null && == "TNT Drop" { - wait 5s - if "].size>" >= 1 && != null && == "TNT Drop" run "BossName Special Attack - TNT Drop" id:BossSpecialAttack } else if == null || == "TNT Drop" { - if "]>" != null { - flag "ActiveSpecialAttackStage:TNT Drop" - flag PreventDoubleAttack "duration: Boss Special Attack Delay>" - narrate " drops primed TNT.. TAKE COVER!" targets: - repeat 5 { - define roof .max.y.add[-1]> - define Xrange .min.x.add[+1].as_int>].to[.max.x.add[-1].as_int>]> - define Zrange .min.z.add[+1].as_int>].to[.max.z.add[-1].as_int>]> - spawn e@primed_tnt origin:%Xrange%,%roof%,%Zrange%,world } - wait " Boss Special Attack Delay>" - if "].size>" >= 1 && != null && == "TNT Drop" run "BossName Special Attack - TNT Drop" id:BossSpecialAttack } } # The section below is disabled until https://github.com/aufdemrand/Denizen/issues/408 is fixed. # #"BossName Special Attack - Invisible": # type: task # # script: # - ^if == null || == "Invisible" flag npc ActiveSpecialAttackStage:Invisible # - ^if "]>" != null { # - narrate " goes ..." "targets:" # - execute as_server "npc sel " # - execute as_server "npc effect --play none" # - invisible npc state:true # - flag npc NoBlood # - define teleportplayer "].random>" # - teleport "" "location:%teleportplayer%" # - wait 10 # - invisible npc state:false # - flag npc NoBlood:! # - narrate " reappears from thin air..." "targets:" # - execute as_server "npc effect --play Boss Aura> # - wait " Boss Special Attack Delay>" # - if "].size>" >= 1 && != null && == "TNT" run "BossName Special Attack - TNT" id:BossSpecialAttack # } "BossName Special Attack - Throw": type: task script: - ^if != null && "].size>" >= 1 && != null && == "Throw" { - wait 5s - if "].size>" >= 1 && != null && == "Throw" run "BossName Special Attack - Throw" id:BossSpecialAttack } else if "].size>" >= 1 && != null && == "Throw" { - flag PreventDoubleAttack "duration: Boss Special Attack Delay>" - if == null || == "Throw" flag ActiveSpecialAttackStage:Throw - if "]>" != null { - flag "ThrowList:|:].random[3]>" - narrate " throws ..." targets: - foreach { - flag ThrowList:<-:%value% - define roof .max.y.add[-1]> - define Xrange .min.x.as_int>].to[.max.x.as_int>]> - define Zrange .min.z.as_int>].to[.max.z.as_int>]> - shoot %value% origin: destination:%Xrange%,%roof%,%Zrange%,world height:1.8 gravity:0.32 } - flag ThrowList:! - wait " Boss Special Attack Delay>" - if "].size>" >= 1 && != null && == "Throw" run "BossName Special Attack - Throw" id:BossSpecialAttack } } "BossName Special Attack - Firestarter": type: task script: - ^if != null && "].size>" >= 1 && != null && == "Firestarter" { - wait 5s - if "].size>" >= 1 && != null && == Firestarter run "BossName Special Attack - Firestarter" id:BossSpecialAttack } else if "].size>" >= 1 && != null && == Firestarter { - flag PreventDoubleAttack "duration: Boss Special Attack Delay>" - if == null || == Firestarter flag ActiveSpecialAttackStage:Firestarter - if "]>" != null { - narrate " sets the place on fire..." targets: - repeat 10 { - modifyblock location:.get_spawnable_blocks.random> fire } - wait " Boss Special Attack Delay>" - if "].size>" >= 1 && != null && == "Firestarter" run "BossName Special Attack - Firestarter" id:BossSpecialAttack } } #-------------------------------------------------------------------------------# # 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 contains && ].flag[NoBlood]> == null { - playeffect location: effect:DRIP_LAVA radius:10 qty:300 offset:0.15 } on player damaged by arrow: - ^if contains { - flag global ArrowList:<-: - if ].flag[CurrentSpecialAttack]> == "Poison Arrow" { - cast poison duration:3 power:1 - random { - narrate "...and hits , causing them to bleed from the ears." targets:].flag[BossPlayerList].aslist> - narrate "...and hits , causing agonising pain and loss of health." targets:].flag[BossPlayerList].aslist> - narrate "...and hits , causing itchy and burning skin blisters." targets:].flag[BossPlayerList].aslist> } } else if ].flag[CurrentSpecialAttack]> == "Wither Arrow" { - cast wither duration:3 power:1 - random { - narrate "...and hits , causing their skin to peel off." targets:].flag[BossPlayerList].aslist> - narrate "...and hits , causing their limbs to decay." targets:].flag[BossPlayerList].aslist> - narrate "...and hits , causing their skin to ooze." targets:].flag[BossPlayerList].aslist> } } else if ].flag[CurrentSpecialAttack]> == "Weakness Arrow" { - cast weakness duration:3 power:1 - random { - narrate "...and hits , causing them to become weak and tired." targets:].flag[BossPlayerList].aslist> - narrate "...and hits , causing them to deal less damage." targets:].flag[BossPlayerList].aslist> - narrate "...and hits , causing them to hit like a little girl." targets:].flag[BossPlayerList].aslist> } } else if ].flag[CurrentSpecialAttack]> == "Slowness Arrow" { - cast slow duration:10 power:3 - random { - narrate "...and hits , causing them to become slow and lazy." targets:].flag[BossPlayerList].aslist> - narrate "...and hits , causing them to walk at a snails pace." targets:].flag[BossPlayerList].aslist> - narrate "...and hits , causing them to be slower than a speeding microorganism." targets:].flag[BossPlayerList].aslist> - narrate "...and hits , causing them to be slower than a 1 legged dog on tranquilizers." targets:].flag[BossPlayerList].aslist> - narrate "...and hits , causing them to be slower than a geriatric slug on a salted snowed-in street." targets:].flag[BossPlayerList].aslist> - narrate "...and hits , causing them to be slower than a snail traveling through peanut butter." targets:].flag[BossPlayerList].aslist> - narrate "...and hits , causing them to be slower than Java." targets:].flag[BossPlayerList].aslist> - narrate "...and hits , causing them to be slower than quadriplegic in a sack race." targets:].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 "" == "player" { - foreach { - flag Looter:%value% - repeat "" { - give to:].inventory> "i@" } } } else if "" == boss { - foreach { - repeat "" { - drop "i@" location: } } } else if "" == chest { - define chestlocation |.get_spawnable_blocks.random> - modifyblock location:%chestlocation% chest - foreach { - repeat "" { - give "i@" to: } } } else if "" == playerchest { - foreach { - define chestlocation |<%value%.location.add[2,1,2].simple>.get_spawnable_blocks.random.as_location.block> - flag %value% LootChestLocation:%chestlocation% - flag LootChestLocationList:->:%chestlocation% - flag global GlobalLootChestLocationList:->:%chestlocation% - modifyblock location:%chestlocation% chest - repeat "" { - give "i@" to: } } - flag PlayersGettingChest: } - if >= 1 && "" >= 1 run "BossName Loot Chest Expiry" "delay:" #-------------------------------------------------------------------------------# # 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 { - if == m@chest { - flag global GlobalLootChestLocationList:<-:%value% - modifyblock %value% air } } - ^foreach { - flag %value% LootChestLocation:! } - ^flag PlayersGettingChest:! - ^flag 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 - 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:" # #--------------------------------- 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 "<<%1%>.entity_type> is going to explode in..." targets: - if <%1%.is_spawned> { - narrate "3...." targets: - 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 "2...." targets: - playeffect location:<%1%.location> effect:fireworks_spark qty:10 } else { - queue clear - flag player "Mobcorn Cooldown:!" } - wait 1 - if <%1%.is_spawned> { - narrate "1...." targets: - 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 " - execute as_server 'npc assign --set "Bloodsucker Bat"' "Bloodsucker Bat": type: assignment actions: on assignment: - flag "BloodsuckerBatList:->:" - trigger name:proximity toggle:true radius:15 - trigger name:damage toggle:true - execute as_server "npc sel " - execute as_server "npc lookclose" - execute as_server "npc vulnerable" - execute as_server "npc health --set 1" - flag Exists - run "Bloodsucker Despawn Timer" delay:60s on death: - flag "BloodsuckerBatList:<-:" - flag Exists:! - remove interact scripts: - 5 Bloodsucker Interaction "Bloodsucker Interaction": type: interact steps: 1: damage trigger: script: - playsound location: sound:bat_idle proximity trigger: exit: script: - ^if "].flag[Bloodsucker Target]>" == || == { - flag "BloodsuckerBatList:<-:" - remove } "Bloodsucker Despawn Timer": type: task script: - if remove #-------------------------------------------------------------------------------# # 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 () in the world is damaged # by an arrow, it checks to see if the person () 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 "].item_in_Hand.lore.contains[A legion of tormented souls imprisoned in this bow fills]>" == true { - cast wither duration:10 power:1 - playsound location: sound:wither_death volume:2 pitch:0.01 - if && "].flag[Hit by Bow of Decay]>" == null { - flag "Hit by Bow of Decay" duration:120s - narrate "You feel your flesh peeling away...strange voices in your head..so much hate.." targets: } } else if "].item_in_Hand.lore.contains[A twisted circus owner forged this to]>" == true { - if && "].flag[Hit by MerryGoRound]>" == null { - flag "Hit by MerryGoRound" duration:5s - narrate "The eery twisted music of a deserted, foggy circus makes you turn...round and round..." targets: } - rotate 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 rather than . 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 "" { - if && "" == null { - flag "Hit by Hammer of the Gods" duration:120s - narrate "The gods curse you... your end is near..." targets: } - strike destination: } else if "" { - playsound location: sound:enderdragon_growl volume:0.2 pitch:0.01 - heal 1 - hurt 1 } else if "" { - if "" == null && "" == 0 && !contains { - flag "Bloodsucker Cooldown" duration:10s - flag "Bloodsucker Target:" - foreach |.get_spawnable_blocks.random[3]> { - run instantly "Spawn Bloodsucker Bat" context:%value% } - foreach { - attack %value% target: } } else if >= 1 && contains { - flag "Bloodsucker Target:" - foreach { - playeffect location:|.get_spawnable_blocks.random> effect:large_smoke - teleport %value% location:|.get_spawnable_blocks.random> } - foreach { - attack %value% target: } } } else if "" determine cancelled on player right clicks with i@PTD: - if "" != null { - playsound location: sound:enderman_teleport - playeffect location: effect:large_smoke - narrate "Teleporting to Saved Location []<&co> ]>" - teleport "location:]>" - flag "PTD Locations[]:<-" - playsound location: sound:enderman_teleport - playeffect location: effect:large_smoke } else narrate "You have no coordinates loaded in your PTD..." on player left clicks block with i@PTD: - if "" == null { - flag "PTD Locations:" - narrate "Saved Location [/3]<&co> ]>" } else if "" = 1 { - flag "PTD Locations:->:" - narrate "Saved Location [/3]<&co> ]>" } else if "" = 2 { - flag "PTD Locations:->:" - narrate "Saved Location [/3]<&co> ]>" } else narrate "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 >= 3 narrate "The Herder is full and cannot capture any more souls..." else if { - flag HerderList:->: - playeffect location: effect:witch_magic - remove - if == 1 narrate "You have trapped the soul of a ..." else if >= 2 narrate "You have trapped the souls of .." } # 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 != null { - narrate "Releasing ..." - foreach { - spawn %value% location:|.get_spawnable_blocks.random> } - flag "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 "" == null { - flag player "Fools Gold Cooldown" duration:120s - showfake diamond_block location:|.get_spawnable_blocks.random> duration:120s - showfake gold_block location:|.get_spawnable_blocks.random> duration:120s - showfake chest location:|.get_spawnable_blocks.random> duration:120s } else narrate " before you can use Fool's Gold 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 "" == null && { - flag "Mobcorn Cooldown" duration:10s - run "Mobcorn Time" def: } else if "" != null narrate "Please wait for Mobcorn to cooldown..." on player right clicks entity with i@Doppelganger: - if == narrate "Entity is already your Doppelganger." else if || { - if "" == null { - if "" != null && { - give to: } - flag "Doppelganger Cooldown" duration:30s - head skin: } } else if "" != null narrate " before you can use Doppelganger 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 "" == null { - flag "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 "" == null { - flag "PhaseShifter Cooldown" duration:3s - if "" == null { - random { - narrate " shimmer and disappears..." targets: - narrate " teleports to a nearby location..." targets: - narrate "With a puff of smoke, teleports not too far away.." targets: } } - flag "PhaseShifter Narrate Cooldown" duration:30s - playsound location: sound:enderman_teleport - playeffect location: effect:large_smoke - teleport location:|.get_spawnable_blocks.random> - playsound location: sound:enderman_teleport - playeffect 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 contains { - if != { - narrate "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 == && contains && != null { - narrate "Chest has been despawned..." - flag LootChestLocation:! - flag global GlobalLootChestLocationList:<-: - modifyblock 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 >= 1 { - foreach { - flag BloodsuckerBatList:<-:%value% - remove %value% } - flag BloodsuckerBatList:! } on player dies: - if >= 1 { - foreach { - flag BloodsuckerBatList:<-:%value% - remove %value% } - flag BloodsuckerBatList:! }