Skip to content

Commit

Permalink
Adds secret horses and their config.
Browse files Browse the repository at this point in the history
- Adds secret horses, which can be acquired... secretly.
  • Loading branch information
BuildTools committed Feb 16, 2020
1 parent aa9df12 commit b2012f8
Show file tree
Hide file tree
Showing 3 changed files with 179 additions and 27 deletions.
13 changes: 12 additions & 1 deletion src/com/nevakanezah/horseenhancer/CommandHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import org.bukkit.entity.Player;

import com.nevakanezah.horseenhancer.util.ArgumentParser;
import com.nevakanezah.horseenhancer.util.SpecialHorses;
import com.nevakanezah.horseenhancer.util.StorableHashMap;

import net.md_5.bungee.api.ChatColor;
Expand Down Expand Up @@ -426,13 +427,23 @@ private boolean horseSummon(CommandSender sender, String[] args) {
type = EntityType.LLAMA;
break;
case "skeleton":
case "skeleton_horse":
type = EntityType.SKELETON_HORSE;
gender = "UNDEAD";
break;
case "zombie":
case "zombie_horse":
type = EntityType.ZOMBIE_HORSE;
gender = "UNDEAD";
break;
case "maximule":
HorseData maximuleData = new HorseData();
SpecialHorses.spawnMaximule(((Entity)sender).getLocation(), maximuleData);
return true;
case "invincible":
HorseData invincibleData = new HorseData();
SpecialHorses.spawnInvincible(((Entity)sender).getLocation(), invincibleData);
return true;
case "help":
showSummonUsage(sender);
return true;
Expand Down Expand Up @@ -648,7 +659,7 @@ private boolean horseUpdate(CommandSender sender, String[] args) {
ArrayList<UUID> matches = new ArrayList<>();
for(HorseData horseData : horseList.values()) {
AbstractHorse candidate = (AbstractHorse)Bukkit.getEntity(horseData.getUniqueID());
String name = candidate.getCustomName();
String name = candidate.getCustomName() == null ? "" : candidate.getCustomName();

if(horseData.getHorseID().equalsIgnoreCase(searchParam)
|| (name != null && name.equalsIgnoreCase(searchParam))
Expand Down
108 changes: 82 additions & 26 deletions src/com/nevakanezah/horseenhancer/HorseSpawnEventHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@

import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.attribute.Attribute;
import org.bukkit.entity.AbstractHorse;
import org.bukkit.entity.Donkey;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Horse;
import org.bukkit.entity.Player;
Expand All @@ -18,8 +20,10 @@
import org.bukkit.event.Listener;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.event.entity.EntityBreedEvent;

import com.nevakanezah.horseenhancer.util.SpecialHorses;
import com.nevakanezah.horseenhancer.util.StorableHashMap;

import net.md_5.bungee.api.ChatColor;
Expand All @@ -30,7 +34,7 @@ public class HorseSpawnEventHandler implements Listener {

static final String MOVE_SPEED = "GENERIC_MOVEMENT_SPEED";
static final String MAX_HEALTH = "GENERIC_MAX_HEALTH";
static final String JUMP_STRENGTH = "JUMP_STRENGTH";
static final String JUMP_STRENGTH = "HORSE_JUMP_STRENGTH";

public HorseSpawnEventHandler(HorseEnhancerPlugin plugin) {
this.plugin = plugin;
Expand Down Expand Up @@ -101,7 +105,8 @@ public void onHorseSpawn(CreatureSpawnEvent event) {
* @param childData The data for the child that we will operate on
* @return The modified childData
*/
private HorseData handleBreedingEvent(CreatureSpawnEvent event, HorseData childData) {
private HorseData handleBreedingEvent(CreatureSpawnEvent event, HorseData childData) {
final boolean secretHorsesEnabled = plugin.getConfig().getBoolean("enable-secret-horses");
// Declare the horses & data containers involved
AbstractHorse child = (AbstractHorse) event.getEntity();
AbstractHorse father = (AbstractHorse) Bukkit.getEntity(childData.getFatherID());
Expand Down Expand Up @@ -141,29 +146,22 @@ private HorseData handleBreedingEvent(CreatureSpawnEvent event, HorseData childD
Location loc = mother.getLocation();
child.remove();

AbstractHorse newChild = (AbstractHorse)loc.getWorld().spawnEntity(loc, EntityType.ZOMBIE_HORSE);
childData.setUniqueID(newChild.getUniqueId());
childData.setType(EntityType.ZOMBIE_HORSE);
AbstractHorse newChild = SpecialHorses.spawnInbred(loc, childData);

newChild.getAttribute(Attribute.GENERIC_MOVEMENT_SPEED).setBaseValue(0.1);
newChild.getAttribute(Attribute.GENERIC_MAX_HEALTH).setBaseValue(10);
newChild.setTamed(true);
newChild.setAge(-9999999);
newChild.setJumpStrength(0.3);
newChild.setAgeLock(true);
newChild.setBreed(false);

childData.setGender("INBRED");
registerHorse(newChild.getUniqueId(), childData);
return null;
}

if(secretHorsesEnabled && handleSecretHorses(child, father, mother, childData, fatherData, motherData))
return childData;

//Apply modified stats to the child
child.getAttribute(Attribute.GENERIC_MOVEMENT_SPEED).setBaseValue(
Math.max( 0.1125, Math.min( 0.3375, getAttributeFromParents(father, mother, MOVE_SPEED ))));
child.getAttribute(Attribute.GENERIC_MAX_HEALTH).setBaseValue(
Math.max( 15, Math.min( 30, getAttributeFromParents(father, mother, MAX_HEALTH ))));
child.setJumpStrength( Math.max( 0.4, Math.min( 1.0, getAttributeFromParents(father, mother, JUMP_STRENGTH ) )));
child.getAttribute(Attribute.HORSE_JUMP_STRENGTH).setBaseValue(
Math.max( 0.4, Math.min( 1.0, getAttributeFromParents(father, mother, JUMP_STRENGTH ) )));

// Coat colouration handling
if(child.getType().equals(EntityType.HORSE)) {
Expand All @@ -173,7 +171,7 @@ private HorseData handleBreedingEvent(CreatureSpawnEvent event, HorseData childD

return childData;
}

/**
* Determine the colour of the child based loosely on the colours of the parents,
* instead of randomly.
Expand Down Expand Up @@ -220,16 +218,9 @@ protected double getAttributeFromParents(AbstractHorse father, AbstractHorse mot
double bias = Math.random();
double result = 0;

if(attr.contentEquals(MOVE_SPEED)
|| attr.contentEquals(MAX_HEALTH)) {
result = (father.getAttribute(Attribute.valueOf(attr)).getBaseValue() * bias)
+ (mother.getAttribute(Attribute.valueOf(attr)).getBaseValue() * (1-bias));
}
else if(attr.contentEquals(JUMP_STRENGTH)) {
result = (father.getJumpStrength() * bias)
+ (mother.getJumpStrength() * (1-bias));
}

result = (father.getAttribute(Attribute.valueOf(attr)).getBaseValue() * bias)
+ (mother.getAttribute(Attribute.valueOf(attr)).getBaseValue() * (1-bias));

// Convert skew to its value as a % of result, then apply that value to the result
skew *= result;
result += skew;
Expand All @@ -252,4 +243,69 @@ private String registerHorse(UUID uuid, HorseData horseData) {
return output;
}

/**
* Evaluates whether to spawn one of the easter egg horse varieties, and handles
* spawning and attribute assignment. Secret horses are acquired through breeding
* parents with particular circumstances, and only one secret horse may exist
* at a time on the server.
* @param child The new horse entity to update or replace
* @param father The horse's father
* @param mother The horse's mother
* @param childData The horse's data container to be updated
* @param fatherData The father's data container, for evaluating conditions
* @param motherData The mother's data container, for evaluating conditions
* @return true if a secret horse was born, false otherwise.
*/
private boolean handleSecretHorses(AbstractHorse child, AbstractHorse father, AbstractHorse mother,
HorseData childData, HorseData fatherData, HorseData motherData) {
Location loc = child.getLocation();
double fSpeed = father.getAttribute(Attribute.valueOf(MOVE_SPEED)).getBaseValue();
double fHealth = father.getAttribute(Attribute.valueOf(MAX_HEALTH)).getBaseValue();
double fJump = father.getAttribute(Attribute.valueOf(JUMP_STRENGTH)).getBaseValue();
double mSpeed = mother.getAttribute(Attribute.valueOf(MOVE_SPEED)).getBaseValue();
double mHealth = mother.getAttribute(Attribute.valueOf(MAX_HEALTH)).getBaseValue();
double mJump = mother.getAttribute(Attribute.valueOf(JUMP_STRENGTH)).getBaseValue();

// A better-than-vanilla horse born to an unlikely couple
boolean maximule = false;

// Why is it called invincible if I can still see it? Well not anymore!
boolean invincible = false;

for(HorseData horseData : horseList.values()) {
if(horseData.getGenderName().equalsIgnoreCase("UNIQUE"))
return false;
}

if(((father instanceof Horse && mother instanceof Donkey)
&& (0.1125 <= fSpeed && fSpeed <= 0.135)
&& (0.4 <= fJump && fJump <= 0.46)
&& (15 <= fHealth && fHealth < 17)
&& (28.5 <= mHealth && mHealth <= 30))
|| ((father instanceof Donkey && mother instanceof Horse)
&& (0.1125 <= mSpeed && mSpeed <= 0.135)
&& (0.4 <= mJump && mJump <= 0.46)
&& (15 <= mHealth && mHealth < 17)
&& (28.5 <= fHealth && fHealth <= 30))) {
maximule = true;
}
else if(father.hasPotionEffect(PotionEffectType.INVISIBILITY)
&& ((Horse)father).getInventory().getArmor().getType().equals(Material.GOLD_BARDING)
&& mother.hasPotionEffect(PotionEffectType.INVISIBILITY)
&& ((Horse)mother).getInventory().getArmor().getType().equals(Material.GOLD_BARDING)) {
invincible = true;
}

if(maximule || invincible)
child.remove();

if(maximule)
SpecialHorses.spawnMaximule(loc, childData);

if(invincible)
SpecialHorses.spawnInvincible(loc, childData);

return true;
}

}
85 changes: 85 additions & 0 deletions src/com/nevakanezah/horseenhancer/util/SpecialHorses.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package com.nevakanezah.horseenhancer.util;

import org.bukkit.EntityEffect;
import org.bukkit.Location;
import org.bukkit.attribute.Attribute;
import org.bukkit.entity.AbstractHorse;
import org.bukkit.entity.EntityType;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;

import com.nevakanezah.horseenhancer.HorseData;

import net.md_5.bungee.api.ChatColor;

public class SpecialHorses {

private SpecialHorses() {
super();
}

/**
* Spawn a horse whose parents were maybe a little too close.
* @param loc Location to spawn the new entity
* @param horseData Data container to be attached to the new entity
* @return the newly-spawned horse
*/
public static AbstractHorse spawnInbred(Location loc, HorseData horseData) {
AbstractHorse horse = (AbstractHorse)loc.getWorld().spawnEntity(loc, EntityType.ZOMBIE_HORSE);
horseData.setUniqueID(horse.getUniqueId());
horseData.setType(EntityType.ZOMBIE_HORSE);

horse.getAttribute(Attribute.GENERIC_MOVEMENT_SPEED).setBaseValue(0.1);
horse.getAttribute(Attribute.GENERIC_MAX_HEALTH).setBaseValue(10);
horse.getAttribute(Attribute.HORSE_JUMP_STRENGTH).setBaseValue(0.3);
horse.setTamed(true);
horse.setAge(-9999999);
horse.setAgeLock(true);
horse.setBreed(false);

horseData.setGender("INBRED");

return horse;
}

public static AbstractHorse spawnMaximule(Location loc, HorseData horseData) {
AbstractHorse horse = (AbstractHorse)loc.getWorld().spawnEntity(loc, EntityType.MULE);
horseData.setUniqueID(horse.getUniqueId());
horseData.setType(EntityType.MULE);

horse.getAttribute(Attribute.GENERIC_MOVEMENT_SPEED).setBaseValue(0.35);
horse.getAttribute(Attribute.GENERIC_MAX_HEALTH).setBaseValue(35);
horse.getAttribute(Attribute.HORSE_JUMP_STRENGTH).setBaseValue(1.18);
horse.setCustomName(ChatColor.DARK_RED + "MA"+ ChatColor.GOLD + "XI" + ChatColor.DARK_BLUE + "MU" + ChatColor.DARK_GREEN + "LE");
horse.setBreed(false);
horse.setAge(0);
horse.setAgeLock(true);
horse.playEffect(EntityEffect.FIREWORK_EXPLODE);

horseData.setGender("UNIQUE");

return horse;
}

public static AbstractHorse spawnInvincible(Location loc, HorseData horseData) {
AbstractHorse horse = (AbstractHorse)loc.getWorld().spawnEntity(loc, EntityType.HORSE);
horseData.setUniqueID(horse.getUniqueId());
horseData.setType(EntityType.HORSE);

horse.getAttribute(Attribute.GENERIC_MOVEMENT_SPEED).setBaseValue(0.38);
horse.getAttribute(Attribute.GENERIC_MAX_HEALTH).setBaseValue(15);
horse.getAttribute(Attribute.HORSE_JUMP_STRENGTH).setBaseValue(0.565);
horse.setCustomName(ChatColor.DARK_BLUE + "Invincible");
horse.setAge(0);
horse.setAgeLock(true);
horse.setTamed(true);
horse.setBreed(false);
horse.playEffect(EntityEffect.FIREWORK_EXPLODE);
PotionEffect invis = new PotionEffect(PotionEffectType.INVISIBILITY, 2147483000, 1, false, false);
horse.addPotionEffect(invis, true);
horseData.setGender("UNIQUE");

return horse;
}

}

0 comments on commit b2012f8

Please sign in to comment.