diff --git a/pom.xml b/pom.xml index 112be0c7..4528e129 100644 --- a/pom.xml +++ b/pom.xml @@ -32,7 +32,7 @@ strife - 3.4.2 + 3.4.4 jar strife diff --git a/src/main/java/land/face/strife/StrifePlugin.java b/src/main/java/land/face/strife/StrifePlugin.java index dd5197b5..abc9c132 100644 --- a/src/main/java/land/face/strife/StrifePlugin.java +++ b/src/main/java/land/face/strife/StrifePlugin.java @@ -54,7 +54,6 @@ The MIT License Copyright (c) 2015 Teal Cube Games import land.face.strife.data.effects.ShootBlock; import land.face.strife.data.effects.TriggerLoreAbility; import land.face.strife.hooks.SnazzyPartiesHook; -import land.face.strife.listeners.BullionListener; import land.face.strife.listeners.ChatListener; import land.face.strife.listeners.CombatListener; import land.face.strife.listeners.CreeperExplodeListener; @@ -472,7 +471,6 @@ public void enable() { Bukkit.getPluginManager().registerEvents(new StatUpdateListener(this), this); Bukkit.getPluginManager().registerEvents(new EntityMagicListener(this), this); Bukkit.getPluginManager().registerEvents(new SpawnListener(this), this); - Bukkit.getPluginManager().registerEvents(new MoneyDropListener(this), this); Bukkit.getPluginManager().registerEvents(new ShearsEquipListener(), this); Bukkit.getPluginManager().registerEvents(new MinionListener(this), this); Bukkit.getPluginManager().registerEvents(new TargetingListener(this), this); @@ -486,7 +484,7 @@ public void enable() { entityHider = new EntityHider(this, Policy.BLACKLIST); if (Bukkit.getPluginManager().getPlugin("Bullion") != null) { - Bukkit.getPluginManager().registerEvents(new BullionListener(this), this); + Bukkit.getPluginManager().registerEvents(new MoneyDropListener(this), this); } if (Bukkit.getPluginManager().getPlugin("HeadDatabase") != null) { Bukkit.getPluginManager().registerEvents(new HeadLoadListener(this), this); diff --git a/src/main/java/land/face/strife/data/BlockData.java b/src/main/java/land/face/strife/data/BlockData.java index ac589cca..240b638f 100644 --- a/src/main/java/land/face/strife/data/BlockData.java +++ b/src/main/java/land/face/strife/data/BlockData.java @@ -6,42 +6,30 @@ public class BlockData { - private long lastHit; - private double storedBlock; + private long runeFalloff; private int runes; private final Set runeHolograms = new HashSet<>(); - public BlockData(long lastHit, double storedBlock) { - this.lastHit = lastHit; - this.storedBlock = storedBlock; + public BlockData() { this.runes = 0; } - public long getLastHit() { - return lastHit; - } - - public void setLastHit(long lastHit) { - this.lastHit = lastHit; - } - - public double getStoredBlock() { - return storedBlock; - } - - public void setStoredBlock(double storedBlock) { - this.storedBlock = storedBlock; - } - public int getRunes() { return runes; } public void setRunes(int runes) { + if (runes >= this.runes) { + runeFalloff = System.currentTimeMillis() + 300000L; + } this.runes = runes; } public Set getRuneHolograms() { return runeHolograms; } + + public long getRuneFalloff() { + return runeFalloff; + } } diff --git a/src/main/java/land/face/strife/data/ChaserEntity.java b/src/main/java/land/face/strife/data/ChaserEntity.java index 20074add..c904d252 100644 --- a/src/main/java/land/face/strife/data/ChaserEntity.java +++ b/src/main/java/land/face/strife/data/ChaserEntity.java @@ -10,6 +10,7 @@ public class ChaserEntity { private final String chaserId; private final int lifespan; private final float speed; + private final float maxSpeed; private Vector velocity; private Location location; @@ -17,10 +18,11 @@ public class ChaserEntity { private int currentTick; public ChaserEntity(final StrifeMob caster, String chaserId, Location location, - LivingEntity target, float speed, Vector velocity, int lifespan) { + LivingEntity target, float speed, float maxSpeed, Vector velocity, int lifespan) { this.caster = caster; this.chaserId = chaserId; this.speed = speed; + this.maxSpeed = maxSpeed; this.velocity = velocity; this.lifespan = lifespan; this.location = location; @@ -44,6 +46,10 @@ public float getSpeed() { return speed; } + public float getMaxSpeed() { + return maxSpeed; + } + public Vector getVelocity() { return velocity; } diff --git a/src/main/java/land/face/strife/data/Spawner.java b/src/main/java/land/face/strife/data/Spawner.java index 1f6184a2..8f9f919d 100644 --- a/src/main/java/land/face/strife/data/Spawner.java +++ b/src/main/java/land/face/strife/data/Spawner.java @@ -122,8 +122,9 @@ public static void spawnSpawner(Spawner s) { if (maxMobs - existingMobs < 1) { return; } - StrifeMob mob = StrifePlugin.getInstance().getUniqueEntityManager() - .spawnUnique(s.getUniqueEntity(), s.getLocation()); + StrifeMob mob = StrifePlugin.getInstance().getStrifeMobManager().getStatMob( + (LivingEntity) StrifePlugin.getInstance().getUniqueEntityManager() + .spawnUnique(s.getUniqueEntity(), s.getLocation())); if (mob == null || mob.getEntity() == null || !mob.getEntity().isValid()) { Bukkit.getLogger().warning("Spawner failed to spawn unique! " + s.getId()); diff --git a/src/main/java/land/face/strife/data/StrifeMob.java b/src/main/java/land/face/strife/data/StrifeMob.java index 9ea02641..3e4761a0 100644 --- a/src/main/java/land/face/strife/data/StrifeMob.java +++ b/src/main/java/land/face/strife/data/StrifeMob.java @@ -28,6 +28,8 @@ import land.face.strife.util.SpecialStatusUtil; import land.face.strife.util.StatUtil; import org.bukkit.Bukkit; +import org.bukkit.attribute.Attribute; +import org.bukkit.attribute.AttributeModifier; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; @@ -57,6 +59,7 @@ public class StrifeMob { private float maxEnergy = 0; private float barrier = 0; private float maxBarrier = 0; + private float block = 0; private boolean shielded; private boolean useEquipment; @@ -71,6 +74,7 @@ public class StrifeMob { private final Set minions = new HashSet<>(); private long cacheStamp = 1L; + private long globalCooldownStamp = 1L; public StrifeMob(Champion champion) { this.livingEntity = new WeakReference<>(champion.getPlayer()); @@ -84,6 +88,14 @@ public StrifeMob(LivingEntity livingEntity) { useEquipment = livingEntity instanceof Player; } + public void bumpGlobalCooldown(int millis) { + globalCooldownStamp = System.currentTimeMillis() + millis; + } + + public boolean isGlobalCooldownReady() { + return globalCooldownStamp < System.currentTimeMillis(); + } + public float getBarrier() { return barrier; } @@ -92,6 +104,31 @@ public float getMaxBarrier() { return maxBarrier; } + public float getBlock() { + return block; + } + + public void setBlock(float block) { + this.block = block; + if (getEntity() instanceof Player) { + Player player = (Player) getEntity(); + for (AttributeModifier mod : player.getAttribute(Attribute.GENERIC_ARMOR).getModifiers()) { + player.getAttribute(Attribute.GENERIC_ARMOR).removeModifier(mod); + } + float maxBlock = getMaxBlock(); + float percent = maxBlock > 0 ? block / maxBlock : 1; + if (percent > 0.99) { + player.getAttribute(Attribute.GENERIC_ARMOR).setBaseValue(-20); + } else { + player.getAttribute(Attribute.GENERIC_ARMOR).setBaseValue(Math.max(1, 20 * percent)); + } + } + } + + public float getMaxBlock() { + return statCache.getOrDefault(StrifeStat.BLOCK, 0f); + } + public void setMaxBarrier(float maxBarrier) { this.maxBarrier = maxBarrier; } @@ -103,7 +140,9 @@ public void restoreBarrier(float amount) { } float maxBarrier = StatUtil.getMaximumBarrier(this); barrier = Math.min(barrier + amount, maxBarrier); - barrierTask.updateArmorBar(this, barrier, maxBarrier); + if (barrierTask != null) { + barrierTask.forceAbsorbHearts(); + } } public float damageBarrier(float amount) { @@ -115,7 +154,9 @@ public float damageBarrier(float amount) { float diff = barrier - amount; if (diff > 0) { barrier -= amount; - barrierTask.updateArmorBar(this, barrier, StatUtil.getMaximumBarrier(this)); + if (barrierTask != null) { + barrierTask.forceAbsorbHearts(); + } BarrierTask.spawnBarrierParticles(getEntity(), amount); return 0; } else { @@ -123,11 +164,19 @@ public float damageBarrier(float amount) { BarrierTask.spawnBarrierParticles(getEntity(), barrier); } barrier = 0; - barrierTask.updateArmorBar(this, 0); + if (barrierTask != null) { + barrierTask.forceAbsorbHearts(); + } return -1 * diff; } } + public void updateBarrierScale() { + if (getEntity() instanceof Player && barrierTask != null) { + barrierTask.updateBarrierScale(); + } + } + public float getEnergy() { return energy; } @@ -269,11 +318,18 @@ public Champion getChampion() { return champion == null ? null : champion.get(); } + public void clearBuffs() { + runningBuffs.clear(); + cacheStamp = 1L; + } + public Map getFinalStats() { if (getChampion() != null) { - return StatUpdateManager.combineMaps(getChampion().getCombinedCache(), getBuffStats()); + return StatUpdateManager.combineMaps(getChampion().getCombinedCache(), + getBuffStats(), equipmentCache.getCombinedStats()); } - return StatUpdateManager.combineMaps(baseStats, getBuffStats(), equipmentCache.getCombinedStats()); + return StatUpdateManager.combineMaps(baseStats, getBuffStats(), + equipmentCache.getCombinedStats()); } public Map getBaseStats() { @@ -372,13 +428,13 @@ public Map> getLoreAbilities() { public Set getTraits() { Set traits = new HashSet<>(equipmentCache.getCombinedTraits()); - if (champion.get() == null) { + if (champion.get() != null) { traits.addAll(Objects.requireNonNull(champion.get()).getPathTraits()); } return traits; } - public boolean hasTrait (StrifeTrait trait) { + public boolean hasTrait(StrifeTrait trait) { if (champion.get() == null) { return equipmentCache.getCombinedTraits().contains(trait); } @@ -440,7 +496,7 @@ public void minionDeath() { } public double getMinionRating() { - if (minionTask == null) { + if (minionTask == null || !getEntity().getPassengers().isEmpty()) { // Arbitrary High Number return 10000000; } @@ -466,14 +522,30 @@ public void restartTimers() { } public void bumpCombat() { + bumpCombat(false); + } + + public void bumpCombat(boolean pvp) { if (isInCombat()) { combatCountdownTask.bump(); + if (pvp) { + combatCountdownTask.setPvp(); + } return; } combatCountdownTask = new CombatCountdownTask(this); + if (pvp) { + combatCountdownTask.setPvp(); + } combatCountdownTask.runTaskTimer(StrifePlugin.getInstance(), 0L, 10L); } + public void flagPvp() { + if (livingEntity.get() instanceof Player && isInCombat()) { + combatCountdownTask.setPvp(); + } + } + public void endCombat() { if (!combatCountdownTask.isCancelled()) { combatCountdownTask.cancel(); @@ -485,6 +557,14 @@ public boolean isInCombat() { return combatCountdownTask != null; } + public boolean isInPvp() { + return combatCountdownTask != null && combatCountdownTask.isPvp(); + } + + public boolean diedFromPvp() { + return getEntity() instanceof Player && getEntity().getKiller() != null || isInPvp(); + } + public Map getBuffStats() { Map stats = new HashMap<>(); Iterator iterator = runningBuffs.iterator(); diff --git a/src/main/java/land/face/strife/data/TargetResponse.java b/src/main/java/land/face/strife/data/TargetResponse.java index dc951eba..d8c692a3 100644 --- a/src/main/java/land/face/strife/data/TargetResponse.java +++ b/src/main/java/land/face/strife/data/TargetResponse.java @@ -2,14 +2,17 @@ import java.util.HashSet; import java.util.Set; +import land.face.strife.timers.SoulTimer; import org.bukkit.Location; import org.bukkit.entity.LivingEntity; public class TargetResponse { private final Set entities = new HashSet<>(); + private final Set souls = new HashSet<>(); private Location location = null; private boolean cancelOnCasterDeath = false; + private boolean force = false; public TargetResponse(Set entities, Location location) { this.entities.addAll(entities); @@ -25,6 +28,14 @@ public TargetResponse(Set entities, boolean cancelOnCasterDeath) { this.cancelOnCasterDeath = cancelOnCasterDeath; } + public boolean isForce() { + return force; + } + + public void setForce(boolean force) { + this.force = force; + } + public boolean isCancelOnCasterDeath() { return cancelOnCasterDeath; } diff --git a/src/main/java/land/face/strife/data/UniqueEntity.java b/src/main/java/land/face/strife/data/UniqueEntity.java index 42ebcb07..4a1dac6e 100644 --- a/src/main/java/land/face/strife/data/UniqueEntity.java +++ b/src/main/java/land/face/strife/data/UniqueEntity.java @@ -31,6 +31,7 @@ public class UniqueEntity { private boolean hasAI; private boolean gravity; private Profession profession; + private boolean invisible; private int size; private int followRange = -1; private boolean pushImmune; @@ -38,6 +39,7 @@ public class UniqueEntity { private boolean burnImmune; private boolean fallImmune; private boolean ignoreSneak; + private boolean saddled; private int maxMods; private boolean removeFollowMods; private boolean powered; @@ -180,6 +182,14 @@ public void setProfession(Profession profession) { this.profession = profession; } + public boolean isInvisible() { + return invisible; + } + + public void setInvisible(boolean invisible) { + this.invisible = invisible; + } + public int getSize() { return size; } @@ -204,6 +214,14 @@ public void setIgnoreSneak(boolean ignoreSneak) { this.ignoreSneak = ignoreSneak; } + public boolean isSaddled() { + return saddled; + } + + public void setSaddled(boolean saddled) { + this.saddled = saddled; + } + public int getMaxMods() { return maxMods; } diff --git a/src/main/java/land/face/strife/data/champion/Champion.java b/src/main/java/land/face/strife/data/champion/Champion.java index 4d1eec7b..83512497 100644 --- a/src/main/java/land/face/strife/data/champion/Champion.java +++ b/src/main/java/land/face/strife/data/champion/Champion.java @@ -24,6 +24,7 @@ import java.util.Map; import java.util.Set; import java.util.UUID; +import java.util.stream.IntStream; import land.face.strife.StrifePlugin; import land.face.strife.data.CombatDetailsContainer; import land.face.strife.managers.StatUpdateManager; @@ -42,6 +43,7 @@ public class Champion { private final Set pathTraits; private final Map combinedStatMap; + private String attributeHeatmap = ""; private Player player; @@ -60,6 +62,7 @@ public Champion(Player player, ChampionSaveData saveData) { combinedStatMap = new HashMap<>(); pathStats = new HashMap<>(); pathTraits = new HashSet<>(); + buildAttributeHeatmap(); } public Map getCombinedCache() { @@ -112,6 +115,42 @@ public int getPendingLevel(StrifeAttribute stat) { return saveData.getPendingLevelMap().getOrDefault(stat, 0); } + public void buildAttributeHeatmap() { + float red = 0; + float yellow = 0; + float green = 0; + float blue = 0; + for (StrifeAttribute attribute : getLevelMap().keySet()) { + switch (attribute.getKey()) { + case "str": + red = getLevelMap().get(attribute); + break; + case "con": + yellow = getLevelMap().get(attribute); + break; + case "dex": + green = getLevelMap().get(attribute); + break; + case "int": + blue = getLevelMap().get(attribute); + break; + } + } + float total = red + yellow + green + blue; + red = red / total; + yellow = yellow / total; + green = green / total; + blue = blue / total; + attributeHeatmap = IntStream.range(0, (int) (red * 8)).mapToObj(i -> "⬤").toString() + + IntStream.range(0, (int) (yellow * 8)).mapToObj(i -> "⬤") + + IntStream.range(0, (int) (green * 8)).mapToObj(i -> "⬤") + + IntStream.range(0, (int) (blue * 8)).mapToObj(i -> "⬤"); + } + + public String getAttributeHeatmap() { + return attributeHeatmap; + } + public void setBonusLevels(int bonusLevels) { saveData.setBonusLevels(bonusLevels); } @@ -142,6 +181,7 @@ public int getUnusedStatPoints() { public void setUnusedStatPoints(int unusedStatPoints) { saveData.setUnusedStatPoints(unusedStatPoints); + buildAttributeHeatmap(); } public int getPendingUnusedStatPoints() { diff --git a/src/main/java/land/face/strife/data/champion/ChampionSaveData.java b/src/main/java/land/face/strife/data/champion/ChampionSaveData.java index f321a6f0..9cbdaec5 100644 --- a/src/main/java/land/face/strife/data/champion/ChampionSaveData.java +++ b/src/main/java/land/face/strife/data/champion/ChampionSaveData.java @@ -183,9 +183,10 @@ public void setGlowEnabled(boolean glowEnabled) { } public enum HealthDisplayType { - VANILLA_TWO_LIFE_PER_HEART, - FIVE_LIFE_PER_HEART, + TWENTY_LIFE_PER_HEART, TEN_LIFE_PER_HEART, + FIVE_LIFE_PER_HEART, + VANILLA_TWO_LIFE_PER_HEART, ONE_ROW_OF_LIFE, TWO_ROWS_OF_LIFE, THREE_ROWS_OF_LIFE diff --git a/src/main/java/land/face/strife/data/conditions/EarthRunesCondition.java b/src/main/java/land/face/strife/data/conditions/EarthRunesCondition.java index c042d09a..3ccf042b 100644 --- a/src/main/java/land/face/strife/data/conditions/EarthRunesCondition.java +++ b/src/main/java/land/face/strife/data/conditions/EarthRunesCondition.java @@ -9,9 +9,9 @@ public class EarthRunesCondition extends Condition { public boolean isMet(StrifeMob attacker, StrifeMob target) { int runes; if (getCompareTarget() == CompareTarget.SELF) { - runes = StrifePlugin.getInstance().getBlockManager().getEarthRunes(attacker.getEntity()); + runes = StrifePlugin.getInstance().getBlockManager().getEarthRunes(attacker); } else { - runes = StrifePlugin.getInstance().getBlockManager().getEarthRunes(target.getEntity()); + runes = StrifePlugin.getInstance().getBlockManager().getEarthRunes(target); } return PlayerDataUtil.conditionCompare(getComparison(), runes, Math.round(getValue())); } diff --git a/src/main/java/land/face/strife/data/effects/AddEarthRunes.java b/src/main/java/land/face/strife/data/effects/AddEarthRunes.java index cb0ed741..43516ec1 100644 --- a/src/main/java/land/face/strife/data/effects/AddEarthRunes.java +++ b/src/main/java/land/face/strife/data/effects/AddEarthRunes.java @@ -9,7 +9,7 @@ public class AddEarthRunes extends Effect { @Override public void apply(StrifeMob caster, StrifeMob target) { - int runes = StrifePlugin.getInstance().getBlockManager().getEarthRunes(target.getEntity()); + int runes = StrifePlugin.getInstance().getBlockManager().getEarthRunes(target); StrifePlugin.getInstance().getBlockManager().setEarthRunes(target,runes + amount); } diff --git a/src/main/java/land/face/strife/data/effects/AreaEffect.java b/src/main/java/land/face/strife/data/effects/AreaEffect.java index c9abd522..19858530 100644 --- a/src/main/java/land/face/strife/data/effects/AreaEffect.java +++ b/src/main/java/land/face/strife/data/effects/AreaEffect.java @@ -126,7 +126,7 @@ private Set getAreaEffectTargets(StrifeMob caster, Location locati if (maxTargets > 0) { int numTargets = maxTargets; if (scaleTargetsWithMultishot) { - float mult = caster.getStat(StrifeStat.MULTISHOT) * (float) Math.pow(Math.random(), 1.5); + float mult = caster.getStat(StrifeStat.MULTISHOT) * (float) Math.pow(Math.random(), 1.15); numTargets = ProjectileUtil.getTotalProjectiles(numTargets, mult); } TargetingUtil.filterByTargetPriority(areaTargets, this, caster, Math.min(numTargets, areaTargets.size())); diff --git a/src/main/java/land/face/strife/data/effects/Charm.java b/src/main/java/land/face/strife/data/effects/Charm.java index fbceaa3d..6aa2ccdb 100644 --- a/src/main/java/land/face/strife/data/effects/Charm.java +++ b/src/main/java/land/face/strife/data/effects/Charm.java @@ -1,11 +1,9 @@ package land.face.strife.data.effects; -import java.util.ArrayList; -import java.util.Comparator; -import java.util.List; import java.util.Random; import land.face.strife.data.StrifeMob; import land.face.strife.stats.StrifeStat; +import land.face.strife.tasks.MinionTask; import land.face.strife.util.StatUtil; import org.bukkit.attribute.Attribute; import org.bukkit.entity.Mob; @@ -23,14 +21,11 @@ public class Charm extends Effect { @Override public void apply(StrifeMob caster, StrifeMob target) { - if (target.isCharmImmune() || !(target.getEntity() instanceof Mob) || target.getEntity() instanceof Player) { + if (target.isCharmImmune() || !(target.getEntity() instanceof Mob) + || target.getEntity() instanceof Player) { return; } - if (!overrideMaster && target.getMaster() != null) { - return; - } - - if (!rollCharmChance(caster, target)) { + if (!overrideMaster && target.getMaster() != null || !rollCharmChance(caster, target)) { return; } @@ -41,28 +36,20 @@ public void apply(StrifeMob caster, StrifeMob target) { ((Wolf) target.getEntity()).setAngry(true); } - ((Mob) target.getEntity()).setTarget(null); target.getFactions().clear(); float lifespan = lifespanSeconds * (1 + (caster.getStat(StrifeStat.EFFECT_DURATION) / 100)); caster.addMinion(target, (int) lifespan); + ((Mob) target.getEntity()).setTarget(null); - double maxHealth = target.getEntity().getMaxHealth() * (1 + (caster.getStat(StrifeStat.MINION_LIFE) / 100)); + target.forceSetStat(StrifeStat.MINION_MULT_INTERNAL, caster.getStat(StrifeStat.MINION_DAMAGE) / 1000); + double maxHealth = target.getEntity().getMaxHealth() * (1 + (caster.getStat(StrifeStat.MINION_LIFE) / 1000)); target.getEntity().getAttribute(Attribute.GENERIC_MAX_HEALTH).setBaseValue(maxHealth); target.getEntity().setHealth(maxHealth); getPlugin().getSpawnerManager().addRespawnTime(target.getEntity()); - List minionList = new ArrayList<>(caster.getMinions()); - - int excessMinions = minionList.size() - (int) caster.getStat(StrifeStat.MAX_MINIONS); - if (excessMinions > 0) { - minionList.sort(Comparator.comparingDouble(StrifeMob::getMinionRating)); - while (excessMinions > 0) { - minionList.get(excessMinions - 1).minionDeath(); - excessMinions--; - } - } + MinionTask.expireMinions(caster); } private boolean rollCharmChance(StrifeMob caster, StrifeMob target) { @@ -88,4 +75,5 @@ public void setChance(float chance) { public void setChancePerLevel(float chancePerLevel) { this.chancePerLevel = chancePerLevel; } + } diff --git a/src/main/java/land/face/strife/data/effects/ChaserEffect.java b/src/main/java/land/face/strife/data/effects/ChaserEffect.java index 20dedad9..c4ef2049 100644 --- a/src/main/java/land/face/strife/data/effects/ChaserEffect.java +++ b/src/main/java/land/face/strife/data/effects/ChaserEffect.java @@ -2,6 +2,7 @@ import land.face.strife.data.LoadedChaser; import land.face.strife.data.StrifeMob; +import land.face.strife.stats.StrifeStat; import land.face.strife.util.DamageUtil.OriginLocation; import land.face.strife.util.TargetingUtil; import org.bukkit.Location; @@ -35,10 +36,11 @@ public void apply(StrifeMob caster, StrifeMob target) { overrideLocation = null; } + float speedMult = 1 + caster.getStat(StrifeStat.PROJECTILE_SPEED) / 100; if (chaseCaster) { - getPlugin().getChaserManager().createChaser(caster, getId(), vector, location, caster.getEntity()); + getPlugin().getChaserManager().createChaser(caster, getId(), vector, location, caster.getEntity(), speedMult); } else { - getPlugin().getChaserManager().createChaser(caster, getId(), vector, location, target.getEntity()); + getPlugin().getChaserManager().createChaser(caster, getId(), vector, location, target.getEntity(), speedMult); } } diff --git a/src/main/java/land/face/strife/data/effects/Corrupt.java b/src/main/java/land/face/strife/data/effects/Corrupt.java index c18af6ad..62f92e93 100644 --- a/src/main/java/land/face/strife/data/effects/Corrupt.java +++ b/src/main/java/land/face/strife/data/effects/Corrupt.java @@ -9,7 +9,7 @@ public class Corrupt extends Effect { @Override public void apply(StrifeMob caster, StrifeMob target) { - DamageUtil.applyCorrupt(target.getEntity(), applyMultipliers(caster, amount)); + DamageUtil.applyCorrupt(target.getEntity(), applyMultipliers(caster, amount), true); } public void setAmount(float amount) { diff --git a/src/main/java/land/face/strife/data/effects/Damage.java b/src/main/java/land/face/strife/data/effects/Damage.java index 3d51d8dd..4e3fe9f7 100644 --- a/src/main/java/land/face/strife/data/effects/Damage.java +++ b/src/main/java/land/face/strife/data/effects/Damage.java @@ -113,6 +113,7 @@ public void apply(StrifeMob caster, StrifeMob target) { DamageUtil.attemptBleed(caster, target, damage.get(DamageType.PHYSICAL), mods, false); } + StrifeMob finalTarget = target; Bukkit.getScheduler().runTaskLater(StrifePlugin.getInstance(), () -> DamageUtil.postDamage(caster, finalTarget, mods), 0L); diff --git a/src/main/java/land/face/strife/data/effects/Effect.java b/src/main/java/land/face/strife/data/effects/Effect.java index a5d79d71..3cc15ba2 100644 --- a/src/main/java/land/face/strife/data/effects/Effect.java +++ b/src/main/java/land/face/strife/data/effects/Effect.java @@ -127,6 +127,7 @@ public enum EffectType { BLEED, TELEPORT, TELEPORT_BEHIND, + THRALL, TITLE, CORRUPT, ADD_EARTH_RUNES, @@ -136,6 +137,7 @@ public enum EffectType { SET_FALL, WAIT, SOUND, + FIREWORK, PARTICLE, SPEAK, PUSH, diff --git a/src/main/java/land/face/strife/data/effects/EquipmentSwap.java b/src/main/java/land/face/strife/data/effects/EquipmentSwap.java index 5fd5e789..3e3ab3ad 100644 --- a/src/main/java/land/face/strife/data/effects/EquipmentSwap.java +++ b/src/main/java/land/face/strife/data/effects/EquipmentSwap.java @@ -4,10 +4,12 @@ import java.util.Map; import land.face.strife.StrifePlugin; import land.face.strife.data.StrifeMob; +import land.face.strife.data.UniqueEntity; import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.inventory.EntityEquipment; import org.bukkit.inventory.EquipmentSlot; +import org.bukkit.inventory.ItemStack; public class EquipmentSwap extends Effect { @@ -23,29 +25,11 @@ public void apply(StrifeMob caster, StrifeMob target) { return; } Bukkit.getScheduler().runTaskLater(StrifePlugin.getInstance(), () -> { - if (itemMap.containsKey(EquipmentSlot.HEAD)) { - equipment.setHelmet(StrifePlugin.getInstance().getEquipmentManager() - .getItem(itemMap.get(EquipmentSlot.HEAD))); - } - if (itemMap.containsKey(EquipmentSlot.CHEST)) { - equipment.setChestplate(StrifePlugin.getInstance().getEquipmentManager() - .getItem(itemMap.get(EquipmentSlot.CHEST))); - } - if (itemMap.containsKey(EquipmentSlot.LEGS)) { - equipment.setLeggings(StrifePlugin.getInstance().getEquipmentManager() - .getItem(itemMap.get(EquipmentSlot.LEGS))); - } - if (itemMap.containsKey(EquipmentSlot.FEET)) { - equipment.setBoots(StrifePlugin.getInstance().getEquipmentManager() - .getItem(itemMap.get(EquipmentSlot.FEET))); - } - if (itemMap.containsKey(EquipmentSlot.HAND)) { - equipment.setItemInMainHand(StrifePlugin.getInstance().getEquipmentManager() - .getItem(itemMap.get(EquipmentSlot.HAND))); - } - if (itemMap.containsKey(EquipmentSlot.OFF_HAND)) { - equipment.setItemInOffHand(StrifePlugin.getInstance().getEquipmentManager() - .getItem(itemMap.get(EquipmentSlot.OFF_HAND))); + for (EquipmentSlot slot : itemMap.keySet()) { + ItemStack stack = getItem(target, slot); + if (stack != null) { + equipment.setItem(slot, stack); + } } }, 1L); } @@ -53,4 +37,16 @@ public void apply(StrifeMob caster, StrifeMob target) { public void addItem(EquipmentSlot slot, String itemId) { itemMap.put(slot, itemId); } + + private ItemStack getItem(StrifeMob mob, EquipmentSlot slot) { + String key = itemMap.get(slot); + if (key.equalsIgnoreCase("reset")) { + if (mob.getUniqueEntityId() == null) { + return null; + } + UniqueEntity ue = getPlugin().getUniqueEntityManager().getUnique(mob.getUniqueEntityId()); + return getPlugin().getEquipmentManager().getItem(ue.getEquipment().get(slot)); + } + return getPlugin().getEquipmentManager().getItem(key); + } } diff --git a/src/main/java/land/face/strife/data/effects/FireworkBurst.java b/src/main/java/land/face/strife/data/effects/FireworkBurst.java new file mode 100644 index 00000000..7a341ce2 --- /dev/null +++ b/src/main/java/land/face/strife/data/effects/FireworkBurst.java @@ -0,0 +1,33 @@ +package land.face.strife.data.effects; + +import com.tealcube.minecraft.bukkit.facecore.utilities.FireworkUtil; +import land.face.strife.data.StrifeMob; +import lombok.Setter; +import org.bukkit.Color; +import org.bukkit.FireworkEffect.Type; +import org.bukkit.Location; + +public class FireworkBurst extends LocationEffect { + + @Setter + private Type effectType; + @Setter + private Color colorOne; + @Setter + private Color colorTwo; + @Setter + private boolean trail; + @Setter + private boolean flicker; + + @Override + public void apply(StrifeMob caster, StrifeMob target) { + Location loc = target.getEntity().getLocation().clone(); + applyAtLocation(caster, loc); + } + + @Override + public void applyAtLocation(StrifeMob caster, Location location) { + FireworkUtil.spawnFirework(location, effectType, colorOne, colorTwo, trail, flicker); + } +} diff --git a/src/main/java/land/face/strife/data/effects/Push.java b/src/main/java/land/face/strife/data/effects/Push.java index a02127b2..5e5e8322 100644 --- a/src/main/java/land/face/strife/data/effects/Push.java +++ b/src/main/java/land/face/strife/data/effects/Push.java @@ -18,7 +18,7 @@ public class Push extends Effect { @Override public void apply(StrifeMob caster, StrifeMob target) { - if (target.getEntity().getType() == EntityType.SHULKER) { + if (target.getEntity().getType() == EntityType.SHULKER || !target.getEntity().hasGravity()) { return; } if (!isFriendly() && StringUtils.isNotBlank(target.getUniqueEntityId())) { diff --git a/src/main/java/land/face/strife/data/effects/ShootProjectile.java b/src/main/java/land/face/strife/data/effects/ShootProjectile.java index e7e63845..3cfa0d4e 100644 --- a/src/main/java/land/face/strife/data/effects/ShootProjectile.java +++ b/src/main/java/land/face/strife/data/effects/ShootProjectile.java @@ -104,7 +104,7 @@ public void apply(StrifeMob caster, StrifeMob target) { if (arrowColor != null) { ((Arrow) projectile).setColor(arrowColor); } - ((Arrow) projectile).setCritical(attackMultiplier > 0.95); + //((Arrow) projectile).setCritical(attackMultiplier > 0.95); ((Arrow) projectile).setPickupStatus(PickupStatus.CREATIVE_ONLY); ProjectileUtil.setPierce((Arrow) projectile, caster.getStat(StrifeStat.PIERCE_CHANCE) / 100); } else if (projectileEntity == EntityType.FIREBALL || projectileEntity == EntityType.DRAGON_FIREBALL) { diff --git a/src/main/java/land/face/strife/data/effects/StrifeParticle.java b/src/main/java/land/face/strife/data/effects/StrifeParticle.java index be5f3a5d..84b62680 100644 --- a/src/main/java/land/face/strife/data/effects/StrifeParticle.java +++ b/src/main/java/land/face/strife/data/effects/StrifeParticle.java @@ -53,14 +53,18 @@ public class StrifeParticle extends LocationEffect { @Override public void apply(StrifeMob caster, StrifeMob target) { if (tickDuration > 0) { - double duration = tickDuration; - if (!strictDuration) { - duration *= 1 + caster.getStat(StrifeStat.EFFECT_DURATION) / 100; + if (isFriendly() == TargetingUtil.isFriendly(caster, target)) { + double duration = tickDuration; + if (!strictDuration) { + duration *= 1 + caster.getStat(StrifeStat.EFFECT_DURATION) / 100; + } + StrifePlugin.getInstance().getParticleTask() + .addContinuousParticle(target.getEntity(), this, (int) duration); } - StrifePlugin.getInstance().getParticleTask().addContinuousParticle(target.getEntity(), this, (int) duration); - return; + } else { + playAtLocation(caster, getLoc(target.getEntity()), + target.getEntity().getEyeLocation().getDirection()); } - playAtLocation(caster, getLoc(target.getEntity()), target.getEntity().getEyeLocation().getDirection()); } @Override @@ -324,6 +328,10 @@ private void spawnParticle(Particle particle, Location location) { } } + public int getTickDuration() { + return tickDuration; + } + public enum ParticleStyle { NORMAL, CIRCLE, diff --git a/src/main/java/land/face/strife/data/effects/Summon.java b/src/main/java/land/face/strife/data/effects/Summon.java index 3fbc12fd..0205e23e 100644 --- a/src/main/java/land/face/strife/data/effects/Summon.java +++ b/src/main/java/land/face/strife/data/effects/Summon.java @@ -2,14 +2,13 @@ import static land.face.strife.data.champion.EquipmentCache.ITEM_SLOTS; -import java.util.ArrayList; -import java.util.Comparator; -import java.util.List; import land.face.strife.StrifePlugin; import land.face.strife.data.StrifeMob; import land.face.strife.listeners.SpawnListener; import land.face.strife.stats.StrifeStat; +import land.face.strife.tasks.MinionTask; import land.face.strife.util.ItemUtil; +import land.face.strife.util.TargetingUtil; import me.libraryaddict.disguise.DisguiseAPI; import me.libraryaddict.disguise.disguisetypes.Disguise; import me.libraryaddict.disguise.disguisetypes.DisguiseType; @@ -35,10 +34,9 @@ public class Summon extends LocationEffect { private boolean mount; private boolean clone; - @Override public void apply(StrifeMob caster, StrifeMob target) { - Location loc = target.getEntity().getLocation(); + Location loc = TargetingUtil.getOriginLocation(target.getEntity(), getOrigin()); applyAtLocation(caster, loc); } @@ -108,17 +106,7 @@ public void applyAtLocation(StrifeMob caster, Location location) { summon.setHealth(maxHealth); } - List minionList = new ArrayList<>(caster.getMinions()); - - int excessMinions = minionList.size() - (int) caster.getStat(StrifeStat.MAX_MINIONS); - if (excessMinions > 0) { - minionList.sort(Comparator.comparingDouble(StrifeMob::getMinionRating)); - while (excessMinions > 0) { - minionList.get(excessMinions - 1).minionDeath(); - //Bukkit.getLogger().info("commit die: " + minionList.get(excessMinions - 1).getEntity().getName()); - excessMinions--; - } - } + MinionTask.expireMinions(caster); } public void setUniqueEntity(String uniqueEntity) { diff --git a/src/main/java/land/face/strife/data/effects/Teleport.java b/src/main/java/land/face/strife/data/effects/Teleport.java index d66eed1c..65cdb729 100644 --- a/src/main/java/land/face/strife/data/effects/Teleport.java +++ b/src/main/java/land/face/strife/data/effects/Teleport.java @@ -16,6 +16,7 @@ public class Teleport extends LocationEffect { private boolean relative; private final List destinationEffects = new ArrayList<>(); private final List originEffects = new ArrayList<>(); + private final List worldSwapWhitelist = new ArrayList<>(); @Override public void apply(StrifeMob caster, StrifeMob target) { @@ -25,6 +26,12 @@ public void apply(StrifeMob caster, StrifeMob target) { @Override public void applyAtLocation(StrifeMob caster, Location location) { + if (caster.getEntity().getLocation().getWorld() != location.getWorld()) { + if (!worldSwapWhitelist.contains(location.getWorld().getName())) { + return; + } + } + TargetResponse response = new TargetResponse(TargetingUtil.getOriginLocation(caster.getEntity(), getOrigin())); getPlugin().getEffectManager().executeEffectList(caster, response, originEffects); @@ -67,4 +74,8 @@ public List getOriginEffects() { return originEffects; } + public List getWorldSwapWhitelist() { + return worldSwapWhitelist; + } + } diff --git a/src/main/java/land/face/strife/data/effects/Thrall.java b/src/main/java/land/face/strife/data/effects/Thrall.java new file mode 100644 index 00000000..bdac5679 --- /dev/null +++ b/src/main/java/land/face/strife/data/effects/Thrall.java @@ -0,0 +1,121 @@ +package land.face.strife.data.effects; + +import com.tealcube.minecraft.bukkit.facecore.utilities.MessageUtils; +import io.pixeloutlaw.minecraft.spigot.garbage.StringExtensionsKt; +import land.face.strife.StrifePlugin; +import land.face.strife.data.StrifeMob; +import land.face.strife.listeners.SpawnListener; +import land.face.strife.stats.StrifeStat; +import land.face.strife.tasks.MinionTask; +import land.face.strife.timers.SoulTimer; +import land.face.strife.util.ItemUtil; +import me.libraryaddict.disguise.DisguiseAPI; +import me.libraryaddict.disguise.disguisetypes.PlayerDisguise; +import org.bukkit.Material; +import org.bukkit.attribute.Attribute; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.entity.Skeleton; +import org.bukkit.inventory.ItemStack; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; +import org.bukkit.scheduler.BukkitRunnable; + +public class Thrall extends Effect { + + private int lifeSeconds = 30; + private String name = "&8«&7Thrall&8»"; + + @Override + public void apply(StrifeMob caster, StrifeMob target) { + if (!(target.getEntity() instanceof Player)) { + return; + } + SoulTimer soul = StrifePlugin.getInstance().getSoulManager().getSoul((Player) + target.getEntity()); + if (soul == null) { + return; + } + + LivingEntity entity = soul.getLocation().getWorld().spawn(soul.getLocation(), Skeleton.class); + StrifeMob mob = StrifePlugin.getInstance().getStrifeMobManager().getStatMob(entity); + + if (mob == null || mob.getEntity() == null) { + return; + } + + soul.getOwner().addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, 600, 0)); + MessageUtils.sendMessage(soul.getOwner(), "&5&oPowerful Black Magics has taken control of your body! Your soul is bound to this grave!"); + + mob.setStats(soul.getStatMap()); + mob.getEntity().setCustomName(StringExtensionsKt.chatColorize(name)); + mob.getEntity().setCustomNameVisible(true); + + PlayerDisguise disguise = new PlayerDisguise(soul.getOwner()); + disguise.setName(""); + disguise.setReplaceSounds(true); + disguise.setDynamicName(true); + + DisguiseAPI.disguiseToAll(mob.getEntity(), disguise); + + entity.getEquipment().setHelmet(soul.getHead()); + if (entity.getEquipment().getHelmet() == null) { + entity.getEquipment().setHelmet(new ItemStack(Material.STONE_BUTTON)); + } + entity.getEquipment().setHelmetDropChance(0); + entity.getEquipment().setChestplate(soul.getBody()); + entity.getEquipment().setChestplateDropChance(0); + entity.getEquipment().setLeggings(soul.getLegs()); + entity.getEquipment().setLeggingsDropChance(0); + entity.getEquipment().setBoots(soul.getBoots()); + entity.getEquipment().setBootsDropChance(0); + entity.getEquipment().setItemInMainHand(soul.getMainHand()); + entity.getEquipment().setItemInMainHandDropChance(0); + entity.getEquipment().setItemInOffHand(soul.getOffHand()); + entity.getEquipment().setItemInOffHandDropChance(0); + + if (ItemUtil.isWandOrStaff(entity.getEquipment().getItemInMainHand())) { + entity.getEquipment().setItemInMainHand(SpawnListener.SKELETON_WAND); + } + + getPlugin().getStatUpdateManager().updateVanillaAttributes(mob); + + float durationSeconds = + (float) lifeSeconds * (1 + caster.getStat(StrifeStat.EFFECT_DURATION) / 100); + caster.addMinion(mob, (int) durationSeconds); + + // force override damage and health. Minion stats 10% as effective + // hence divided by 1000 + mob.forceSetStat(StrifeStat.MINION_MULT_INTERNAL, + caster.getStat(StrifeStat.MINION_DAMAGE) / 1000); + double maxHealth = entity.getMaxHealth() * + (1 + (caster.getStat(StrifeStat.MINION_LIFE) / 1000)); + entity.getAttribute(Attribute.GENERIC_MAX_HEALTH).setBaseValue(maxHealth); + entity.setHealth(maxHealth); + + getPlugin().getSoulManager().removeSoul(soul); + + new BukkitRunnable() { + public void run() { + if (entity.isValid()) { + Player p = soul.getOwner(); + if (p.isOnline() && p.isValid()) { + p.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, 25, 4)); + } + } else { + cancel(); + } + } + }.runTaskTimer(getPlugin(), 0, 20); + + MinionTask.expireMinions(caster); + } + + public void setLifeSeconds(int lifeSeconds) { + this.lifeSeconds = lifeSeconds; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/src/main/java/land/face/strife/listeners/BullionListener.java b/src/main/java/land/face/strife/listeners/BullionListener.java deleted file mode 100644 index efbbec71..00000000 --- a/src/main/java/land/face/strife/listeners/BullionListener.java +++ /dev/null @@ -1,52 +0,0 @@ -/** - * The MIT License Copyright (c) 2015 Teal Cube Games - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and - * associated documentation files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, publish, distribute, - * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or - * substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - * NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ -package land.face.strife.listeners; - -import com.tealcube.minecraft.bukkit.bullion.GoldDropEvent; -import land.face.strife.StrifePlugin; -import land.face.strife.data.StrifeMob; -import land.face.strife.stats.StrifeStat; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.Listener; - -public class BullionListener implements Listener { - - private final StrifePlugin plugin; - - public BullionListener(StrifePlugin plugin) { - this.plugin = plugin; - } - - public StrifePlugin getPlugin() { - return plugin; - } - - @EventHandler(priority = EventPriority.NORMAL) - public void onGoldDrop(GoldDropEvent event) { - if (event.getKiller() == null) { - return; - } - StrifeMob killerMob = plugin.getStrifeMobManager().getStatMob(event.getKiller()); - StrifeMob victimMob = plugin.getStrifeMobManager().getStatMob(event.getLivingEntity()); - float bonus = victimMob.getStat(StrifeStat.GOLD_FIND) + killerMob.getStat(StrifeStat.GOLD_FIND); - event.setAmount(event.getAmount() * (1 + bonus / 100)); - } - -} diff --git a/src/main/java/land/face/strife/listeners/CombatListener.java b/src/main/java/land/face/strife/listeners/CombatListener.java index 383de6b8..21024074 100644 --- a/src/main/java/land/face/strife/listeners/CombatListener.java +++ b/src/main/java/land/face/strife/listeners/CombatListener.java @@ -34,6 +34,7 @@ import land.face.strife.events.StrifeDamageEvent; import land.face.strife.stats.StrifeStat; import land.face.strife.util.DamageUtil; +import land.face.strife.util.DamageUtil.AbilityMod; import land.face.strife.util.DamageUtil.AttackType; import land.face.strife.util.DamageUtil.DamageType; import land.face.strife.util.FangUtil; @@ -95,8 +96,9 @@ public void handleTNT(EntityDamageByEntityEvent event) { @EventHandler(priority = EventPriority.LOWEST) public void handleNpcHits(EntityDamageByEntityEvent event) { - if (event.isCancelled() || event.getEntity().isInvulnerable() || event.getEntity().hasMetadata("NPC") || event - .getEntity().hasMetadata("pet")) { + if (event.isCancelled() || event.getEntity().isInvulnerable() || + event.getEntity().hasMetadata("NPC") || + event.getEntity().hasMetadata("MiniaturePet")) { if (event.getDamager() instanceof Projectile) { event.getDamager().remove(); } @@ -109,18 +111,20 @@ public void strifeDamageHandler(EntityDamageByEntityEvent event) { if (event.isCancelled()) { return; } + if (event.getCause() == DamageCause.THORNS) { + event.setCancelled(true); + return; + } if (plugin.getDamageManager().isHandledDamage(event.getDamager())) { DamageUtil.removeDamageModifiers(event); event.setDamage(BASE, plugin.getDamageManager().getHandledDamage(event.getDamager())); return; } - if (event.getCause() == DamageCause.CUSTOM) { - return; - } if (!(event.getEntity() instanceof LivingEntity) || event.getEntity() instanceof ArmorStand) { return; } - if (event.getDamager() instanceof EvokerFangs && FangUtil.isNoDamageFang((EvokerFangs) event.getDamager())) { + if (event.getDamager() instanceof EvokerFangs && FangUtil + .isNoDamageFang((EvokerFangs) event.getDamager())) { event.setCancelled(true); return; } @@ -132,11 +136,6 @@ public void strifeDamageHandler(EntityDamageByEntityEvent event) { return; } - if (!(attackEntity instanceof Player) && !canMonsterHit(attackEntity)) { - event.setCancelled(true); - return; - } - boolean blocked = (event.isApplicable(BLOCKING) && event.getDamage(BLOCKING) != 0) || (defendEntity instanceof Shulker && event.isApplicable(ARMOR) && event.getDamage(ARMOR) != 0); @@ -179,6 +178,7 @@ public void strifeDamageHandler(EntityDamageByEntityEvent event) { float attackMultiplier = 1f; float healMultiplier = 1f; + boolean backAttack = false; AttackType attackType = DamageUtil.getAttackType(event); if (attackType == AttackType.MELEE) { @@ -190,14 +190,26 @@ public void strifeDamageHandler(EntityDamageByEntityEvent event) { } attackMultiplier = plugin.getAttackSpeedManager().getAttackMultiplier(attacker); attackMultiplier = (float) Math.pow(attackMultiplier, 1.1); + //double angle = attackEntity.getEyeLocation().getDirection() + // .angle(defendEntity.getEyeLocation().getDirection()); + //backAttack = angle < 1; } else if (attackType == AttackType.PROJECTILE) { attackMultiplier = ProjectileUtil.getAttackMult(projectile); + assert projectile != null; + //double angle = projectile.getVelocity().angle(defendEntity.getEyeLocation().getDirection()); + //backAttack = angle < 1; } else if (attackType == AttackType.AREA) { double distance = event.getDamager().getLocation().distance(event.getEntity().getLocation()); attackMultiplier *= Math.max(0.3, 4 / (distance + 3)); healMultiplier = 0.3f; } + if (attackType == AttackType.MELEE && !canMonsterHit(attackEntity)) { + event.setCancelled(true); + return; + } + putMonsterHit(attackEntity); + if (isMultishot) { attackMultiplier *= 0.25; } @@ -211,8 +223,6 @@ public void strifeDamageHandler(EntityDamageByEntityEvent event) { boolean isSneakAttack = attackEntity instanceof Player && plugin.getStealthManager() .canSneakAttack((Player) attackEntity); - putMonsterHit(attackEntity); - boolean mobAbility = plugin.getAbilityManager().abilityCast(attacker, defender, TriggerAbilityType.ON_HIT); if (mobAbility) { @@ -231,10 +241,14 @@ public void strifeDamageHandler(EntityDamageByEntityEvent event) { damageModifiers.setDamageReductionRatio(Math.min(attackMultiplier, 1.0f)); damageModifiers.setScaleChancesWithAttack(true); damageModifiers.setConsumeEarthRunes(!isMultishot); - damageModifiers.setApplyOnHitEffects(attackMultiplier > Math.random()); + damageModifiers.setApplyOnHitEffects(!isMultishot && attackMultiplier > Math.random()); damageModifiers.setSneakAttack(isSneakAttack); damageModifiers.setBlocking(blocked); + if (backAttack) { + damageModifiers.getAbilityMods().put(AbilityMod.BACK_ATTACK, 1f); + } + boolean attackSuccess = DamageUtil.preDamage(attacker, defender, damageModifiers); if (!attackSuccess) { @@ -272,11 +286,15 @@ public void strifeDamageHandler(EntityDamageByEntityEvent event) { return; } - float eventDamage = Math.max(0.002f, defender.damageBarrier((float) strifeDamageEvent.getFinalDamage())); - eventDamage = plugin.getDamageManager().doEnergyAbsorb(defender, eventDamage); + float eventDamage = defender.damageBarrier((float) strifeDamageEvent.getFinalDamage()); - if (damage.containsKey(DamageType.PHYSICAL)) { - DamageUtil.attemptBleed(attacker, defender, damage.get(DamageType.PHYSICAL), damageModifiers, false); + if (finalDamage > 0) { + eventDamage = plugin.getDamageManager().doEnergyAbsorb(defender, eventDamage); + + if (damage.containsKey(DamageType.PHYSICAL)) { + DamageUtil.attemptBleed(attacker, defender, damage.get(DamageType.PHYSICAL), + damageModifiers, false); + } } Bukkit.getScheduler().runTaskLater(plugin, @@ -316,7 +334,7 @@ private boolean canMonsterHit(LivingEntity uuid) { public static void putMonsterHit(LivingEntity livingEntity) { if (!(livingEntity instanceof Player)) { - MONSTER_HIT_COOLDOWN.put(livingEntity, System.currentTimeMillis() + 400); + MONSTER_HIT_COOLDOWN.put(livingEntity, System.currentTimeMillis() + 650); } } diff --git a/src/main/java/land/face/strife/listeners/DataListener.java b/src/main/java/land/face/strife/listeners/DataListener.java index afe15201..7ab7f2ce 100644 --- a/src/main/java/land/face/strife/listeners/DataListener.java +++ b/src/main/java/land/face/strife/listeners/DataListener.java @@ -20,6 +20,9 @@ import land.face.strife.StrifePlugin; import land.face.strife.data.StrifeMob; import land.face.strife.data.champion.Champion; +import land.face.strife.data.champion.ChampionSaveData.HealthDisplayType; +import land.face.strife.managers.StatUpdateManager; +import land.face.strife.managers.UniqueEntityManager; import land.face.strife.stats.AbilitySlot; import land.face.strife.util.ChunkUtil; import land.face.strife.util.DamageUtil; @@ -30,6 +33,8 @@ import org.bukkit.Chunk; import org.bukkit.GameMode; import org.bukkit.Material; +import org.bukkit.attribute.Attribute; +import org.bukkit.attribute.AttributeModifier; import org.bukkit.entity.Entity; import org.bukkit.entity.FallingBlock; import org.bukkit.entity.LivingEntity; @@ -45,6 +50,7 @@ import org.bukkit.event.entity.EntityDamageEvent; import org.bukkit.event.entity.EntityDamageEvent.DamageCause; import org.bukkit.event.entity.EntityTameEvent; +import org.bukkit.event.entity.ItemSpawnEvent; import org.bukkit.event.inventory.InventoryCloseEvent; import org.bukkit.event.player.PlayerChangedWorldEvent; import org.bukkit.event.player.PlayerInteractEntityEvent; @@ -122,8 +128,8 @@ public void onEntityAttack(final EntityDamageByEntityEvent event) { @EventHandler(priority = EventPriority.LOWEST) public void onPlayerJoin(final PlayerJoinEvent event) { - event.getPlayer().setHealthScaled(false); - Champion champion = plugin.getChampionManager().getChampion(event.getPlayer()); + StrifeMob playerMob = plugin.getStrifeMobManager().getStatMob(event.getPlayer()); + Champion champion = playerMob.getChampion(); plugin.getAbilityManager().loadPlayerCooldowns(event.getPlayer()); plugin.getBoostManager().updateGlobalBoostStatus(event.getPlayer()); plugin.getChampionManager().verifyStatValues(champion); @@ -140,6 +146,20 @@ public void onPlayerJoin(final PlayerJoinEvent event) { plugin.getChampionManager().update(event.getPlayer()); + event.getPlayer().setHealthScaled(true); + HealthDisplayType displayType = champion.getSaveData().getHealthDisplayType(); + float maxHealth = Math.max(StatUtil.getHealth(playerMob), 1); + event.getPlayer().setInvulnerable(true); + event.getPlayer().setHealthScale(StatUpdateManager.getHealthScale(displayType, maxHealth)); + event.getPlayer().setInvulnerable(false); + + playerMob.updateBarrierScale(); + + for (AttributeModifier mod : event.getPlayer().getAttribute(Attribute.GENERIC_ARMOR).getModifiers()) { + event.getPlayer().getAttribute(Attribute.GENERIC_ARMOR).removeModifier(mod); + } + event.getPlayer().getAttribute(Attribute.GENERIC_ARMOR).setBaseValue(-20); + if (event.getPlayer().getGameMode() != GameMode.CREATIVE) { Bukkit.getScheduler().runTaskLater(plugin, () -> plugin.getAbilityIconManager().setAllAbilityIcons(event.getPlayer()), 2L); @@ -165,6 +185,10 @@ private void doPlayerLeave(Player player) { plugin.getAbilityIconManager().removeIconItem(player, AbilitySlot.SLOT_C); plugin.getCounterManager().clearCounters(player); plugin.getBossBarManager().disableBars(player); + for (AttributeModifier mod : player.getAttribute(Attribute.GENERIC_ARMOR).getModifiers()) { + player.getAttribute(Attribute.GENERIC_ARMOR).removeModifier(mod); + } + player.getAttribute(Attribute.GENERIC_ARMOR).setBaseValue(-20); } @EventHandler(priority = EventPriority.NORMAL) @@ -282,6 +306,20 @@ public void onInvyClose(InventoryCloseEvent event) { public void onRespawn(PlayerRespawnEvent event) { StrifeMob mob = plugin.getStrifeMobManager().getStatMob(event.getPlayer()); mob.restartTimers(); + for (AttributeModifier mod : event.getPlayer().getAttribute(Attribute.GENERIC_ARMOR).getModifiers()) { + event.getPlayer().getAttribute(Attribute.GENERIC_ARMOR).removeModifier(mod); + } + event.getPlayer().getAttribute(Attribute.GENERIC_ARMOR).setBaseValue(-20); + } + + @EventHandler(priority = EventPriority.NORMAL) + public void onSaddleDrop(ItemSpawnEvent event) { + if (event.getEntity().getItemStack().getType() == Material.SADDLE) { + if (event.getEntity().getItemStack().isSimilar(UniqueEntityManager.DEV_SADDLE)) { + event.getEntity().remove(); + event.setCancelled(true); + } + } } private void ensureAbilitiesDontInstantCast(Player player) { diff --git a/src/main/java/land/face/strife/listeners/DeathListener.java b/src/main/java/land/face/strife/listeners/DeathListener.java index 8e3678bc..71c0fd06 100644 --- a/src/main/java/land/face/strife/listeners/DeathListener.java +++ b/src/main/java/land/face/strife/listeners/DeathListener.java @@ -44,7 +44,9 @@ public DeathListener(StrifePlugin plugin) { @EventHandler(priority = EventPriority.LOWEST) public void onEntityDeathEvent(EntityDeathEvent event) { if (event instanceof PlayerDeathEvent) { - plugin.getSoulManager().createSoul((Player) event.getEntity()); + StrifeMob mob = plugin.getStrifeMobManager().getStatMob(event.getEntity()); + mob.clearBuffs(); + plugin.getSoulManager().createSoul(mob); EndlessEffect.cancelEffects(event.getEntity()); return; } @@ -83,6 +85,7 @@ public void onEntityDeathEvent(EntityDeathEvent event) { @EventHandler(priority = EventPriority.LOW) public void onEntityDeathClearIconsAndStrifeMobs(final EntityDeathEvent event) { plugin.getAbilityManager().unToggleAll(event.getEntity()); + plugin.getDamageOverTimeTask().clearAllDoT(event.getEntity()); if (event.getEntity() instanceof Player) { plugin.getAbilityManager().savePlayerCooldowns((Player) event.getEntity()); plugin.getAbilityIconManager().removeIconItem((Player) event.getEntity(), AbilitySlot.SLOT_A); diff --git a/src/main/java/land/face/strife/listeners/EntityMagicListener.java b/src/main/java/land/face/strife/listeners/EntityMagicListener.java index 4241c9d8..bb595eb6 100644 --- a/src/main/java/land/face/strife/listeners/EntityMagicListener.java +++ b/src/main/java/land/face/strife/listeners/EntityMagicListener.java @@ -6,6 +6,7 @@ import land.face.strife.data.effects.Damage; import land.face.strife.data.effects.StrifeParticle; import land.face.strife.data.effects.StrifeParticle.ParticleStyle; +import land.face.strife.stats.StrifeStat; import land.face.strife.util.DamageUtil.AttackType; import land.face.strife.util.DamageUtil.OriginLocation; import land.face.strife.util.TargetingUtil; @@ -69,8 +70,9 @@ public void onWitchPotionThrow(ProjectileLaunchEvent e) { e.setCancelled(true); witch.getWorld().playSound(witch.getLocation(), Sound.ENTITY_BLAZE_HURT, 0.9f, 2f); StrifeMob witchMob = plugin.getStrifeMobManager().getStatMob(witch); + float speedMult = 1 + witchMob.getStat(StrifeStat.PROJECTILE_SPEED) / 100; plugin.getChaserManager().createChaser(witchMob, WITCH_SPELL_ID, new Vector(0,0,0), - TargetingUtil.getOriginLocation(witch, OriginLocation.BELOW_HEAD), witch.getTarget()); + TargetingUtil.getOriginLocation(witch, OriginLocation.BELOW_HEAD), witch.getTarget(), speedMult); } @EventHandler diff --git a/src/main/java/land/face/strife/listeners/ExperienceListener.java b/src/main/java/land/face/strife/listeners/ExperienceListener.java index 1d521f85..7272e2c6 100644 --- a/src/main/java/land/face/strife/listeners/ExperienceListener.java +++ b/src/main/java/land/face/strife/listeners/ExperienceListener.java @@ -115,7 +115,7 @@ public void onPlayerRespawn(PlayerRespawnEvent event) { if (penaltyFreeWorlds.contains(p.getWorld().getName())) { return; } - if (p.getKiller() != null) { + if (plugin.getStrifeMobManager().getStatMob(p).diedFromPvp()) { return; } if (p.getLevel() >= 100) { diff --git a/src/main/java/land/face/strife/listeners/LoreAbilityListener.java b/src/main/java/land/face/strife/listeners/LoreAbilityListener.java index 5c85a61b..7a2959fb 100644 --- a/src/main/java/land/face/strife/listeners/LoreAbilityListener.java +++ b/src/main/java/land/face/strife/listeners/LoreAbilityListener.java @@ -74,10 +74,8 @@ public void onCombatChange(CombatChangeEvent event) { @EventHandler(priority = EventPriority.MONITOR) public void onCriticalHit(CriticalEvent event) { - Champion champion = event.getAttacker().getChampion(); - if (champion != null) { - executeBoundEffects(event.getAttacker(), event.getVictim().getEntity(), event.getAttacker().getLoreAbilities().get(ON_CRIT)); - } + HashSet abilitySet = new HashSet<>(event.getAttacker().getLoreAbilities().get(ON_CRIT)); + executeBoundEffects(event.getAttacker(), event.getVictim().getEntity(), abilitySet); executeFiniteEffects(event.getAttacker(), event.getVictim(), ON_CRIT); } @@ -124,21 +122,22 @@ public void onSneakAttack(SneakAttackEvent event) { @EventHandler(priority = EventPriority.MONITOR) public void onEntityDeath(EntityDeathEvent event) { StrifeMob victim = strifeMobManager.getStatMob(event.getEntity()); - Player killer = event.getEntity().getKiller(); + LivingEntity killer = victim.getTopDamager(); if (killer == null) { - killer = victim.getTopDamager(); - if (killer == null) { - return; - } + killer = event.getEntity().getKiller(); } StrifeMob killerMob = strifeMobManager.getStatMob(killer); - executeBoundEffects(killerMob, event.getEntity(), killerMob.getLoreAbilities().get(ON_KILL)); + if (killerMob == null || killerMob.getLoreAbilities() == null) { + return; + } + HashSet abilitySet = new HashSet<>(killerMob.getLoreAbilities().get(ON_KILL)); + executeBoundEffects(killerMob, event.getEntity(), abilitySet); executeFiniteEffects(killerMob, victim, ON_KILL); } @EventHandler(priority = EventPriority.MONITOR) public void onStrifeDamage(StrifeDamageEvent event) { - if (event.isCancelled()) { + if (event.isCancelled() || !event.getDamageModifiers().isApplyOnHitEffects()) { return; } StrifeMob attacker = event.getAttacker(); diff --git a/src/main/java/land/face/strife/listeners/MoneyDropListener.java b/src/main/java/land/face/strife/listeners/MoneyDropListener.java index 69cc36a5..6992607a 100644 --- a/src/main/java/land/face/strife/listeners/MoneyDropListener.java +++ b/src/main/java/land/face/strife/listeners/MoneyDropListener.java @@ -18,6 +18,7 @@ */ package land.face.strife.listeners; +import com.tealcube.minecraft.bukkit.bullion.GoldDropEvent; import com.tealcube.minecraft.bukkit.bullion.PlayerDeathDropEvent; import land.face.strife.StrifePlugin; import land.face.strife.data.StrifeMob; @@ -36,11 +37,25 @@ public MoneyDropListener(StrifePlugin plugin) { @EventHandler(priority = EventPriority.MONITOR) public void onEntityDeathEvent(PlayerDeathDropEvent event) { + StrifeMob mob = plugin.getStrifeMobManager().getStatMob(event.getVictim()); + if (mob.diedFromPvp()) { + event.setCancelled(true); + } if (event.getAmountProtected() <= 0) { return; } - StrifeMob mob = plugin.getStrifeMobManager().getStatMob(event.getVictim()); double multiplier = 1 + mob.getStat(StrifeStat.MONEY_KEPT) / 100; event.setAmountProtected(event.getAmountProtected() * multiplier); } + + @EventHandler(priority = EventPriority.NORMAL) + public void onGoldDrop(GoldDropEvent event) { + if (event.getKiller() == null) { + return; + } + StrifeMob killerMob = plugin.getStrifeMobManager().getStatMob(event.getKiller()); + StrifeMob victimMob = plugin.getStrifeMobManager().getStatMob(event.getLivingEntity()); + float bonus = victimMob.getStat(StrifeStat.GOLD_FIND) + killerMob.getStat(StrifeStat.GOLD_FIND); + event.setAmount(event.getAmount() * (1 + bonus / 100)); + } } diff --git a/src/main/java/land/face/strife/listeners/ShootListener.java b/src/main/java/land/face/strife/listeners/ShootListener.java index b3a95a3b..71e9f7cf 100644 --- a/src/main/java/land/face/strife/listeners/ShootListener.java +++ b/src/main/java/land/face/strife/listeners/ShootListener.java @@ -43,12 +43,14 @@ import land.face.strife.util.LogUtil; import land.face.strife.util.ProjectileUtil; import land.face.strife.util.StatUtil; +import land.face.strife.util.TargetingUtil; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.Particle; import org.bukkit.Sound; import org.bukkit.entity.Arrow; import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Mob; import org.bukkit.entity.Player; import org.bukkit.entity.Trident; import org.bukkit.event.EventHandler; @@ -135,6 +137,17 @@ public void onEntityShoot(ProjectileLaunchEvent event) { StrifeMob mob = plugin.getStrifeMobManager() .getStatMob((LivingEntity) event.getEntity().getShooter()); + if (event.getEntity().getShooter() instanceof Mob && ((Mob) event.getEntity().getShooter()).getTarget() != null) { + StrifeMob target = plugin.getStrifeMobManager() + .getStatMob(((Mob) event.getEntity().getShooter()).getTarget()); + + if (TargetingUtil.isFriendly(mob, target)) { + event.setCancelled(true); + ((Mob) event.getEntity().getShooter()).setTarget(null); + return; + } + } + if (plugin.getAbilityManager().abilityCast(mob, TriggerAbilityType.SHOOT)) { event.setCancelled(true); return; diff --git a/src/main/java/land/face/strife/listeners/SwingListener.java b/src/main/java/land/face/strife/listeners/SwingListener.java index 2d180cdb..61cac769 100644 --- a/src/main/java/land/face/strife/listeners/SwingListener.java +++ b/src/main/java/land/face/strife/listeners/SwingListener.java @@ -72,6 +72,9 @@ public void onSwingLeft(PlayerInteractEvent event) { } if (event.getAction() == LEFT_CLICK_AIR || event.getAction() == LEFT_CLICK_BLOCK) { StrifeMob mob = plugin.getStrifeMobManager().getStatMob(event.getPlayer()); + if (ItemUtil.isTool(event.getPlayer().getEquipment().getItemInMainHand())) { + return; + } double attackMult = plugin.getAttackSpeedManager().getAttackMultiplier(mob); if (ItemUtil.isWandOrStaff(event.getPlayer().getEquipment().getItemInMainHand())) { if (attackMult > 0.08) { diff --git a/src/main/java/land/face/strife/listeners/TargetingListener.java b/src/main/java/land/face/strife/listeners/TargetingListener.java index c1c5b21e..2d6a9c74 100644 --- a/src/main/java/land/face/strife/listeners/TargetingListener.java +++ b/src/main/java/land/face/strife/listeners/TargetingListener.java @@ -137,11 +137,12 @@ public void onNormalTarget(EntityTargetLivingEntityEvent event) { if (!(event.getEntity() instanceof Mob)) { return; } - if (event.getReason() == TargetReason.TARGET_ATTACKED_NEARBY_ENTITY - || event.getReason() == TargetReason.FOLLOW_LEADER - || event.getReason() == TargetReason.PIG_ZOMBIE_TARGET - || event.getReason() == TargetReason.REINFORCEMENT_TARGET) { - if (SpecialStatusUtil.isWeakAggro(event.getEntity())) { + if (SpecialStatusUtil.isWeakAggro(event.getEntity())) { + if (event.getReason() == TargetReason.TARGET_ATTACKED_NEARBY_ENTITY + || event.getReason() == TargetReason.FOLLOW_LEADER + || event.getReason() == TargetReason.PIG_ZOMBIE_TARGET + || event.getReason() == TargetReason.REINFORCEMENT_TARGET + || event.getReason() == TargetReason.DEFEND_VILLAGE) { event.setCancelled(true); return; } diff --git a/src/main/java/land/face/strife/listeners/UniqueSplashListener.java b/src/main/java/land/face/strife/listeners/UniqueSplashListener.java index 946e7e5b..e56bcc02 100644 --- a/src/main/java/land/face/strife/listeners/UniqueSplashListener.java +++ b/src/main/java/land/face/strife/listeners/UniqueSplashListener.java @@ -54,7 +54,7 @@ public void onAbilityPotionSplash(PotionSplashEvent event) { } if (plugin.getBlockManager().rollBlock(defender, false)) { - plugin.getBlockManager().blockFatigue(defendEntity, 1.0, false); + plugin.getBlockManager().blockFatigue(defender, 1.0, false, false); plugin.getBlockManager().bumpRunes(defender); DamageUtil.doBlock(attacker, defender); event.setCancelled(true); diff --git a/src/main/java/land/face/strife/managers/AbilityManager.java b/src/main/java/land/face/strife/managers/AbilityManager.java index 7019c91b..00478cee 100644 --- a/src/main/java/land/face/strife/managers/AbilityManager.java +++ b/src/main/java/land/face/strife/managers/AbilityManager.java @@ -92,7 +92,7 @@ public boolean execute(final Ability ability, final StrifeMob caster, LivingEnti public boolean execute(final Ability ability, final StrifeMob caster, LivingEntity target, boolean ignoreReqs) { if (!ignoreReqs) { - if (ability.getCooldown() != 0 && !canBeCast(caster.getEntity(), ability)) { + if (ability.getCooldown() != 0 && !canBeCast(caster, ability)) { doOnCooldownPrompt(caster, ability); return false; } @@ -117,7 +117,7 @@ public boolean execute(final Ability ability, final StrifeMob caster, LivingEnti return true; } } else { - coolDownAbility(caster.getEntity(), ability); + coolDownAbility(caster, ability); } if (caster.getChampion() != null && ability.getAbilityIconData() != null) { caster.getChampion().getDetailsContainer().addWeights(ability); @@ -140,9 +140,8 @@ public boolean execute(final Ability ability, final StrifeMob caster, LivingEnti plugin.getStealthManager().unstealthPlayer((Player) caster.getEntity()); } if (ability.isShowMessages()) { - AdvancedActionBarUtil - .addMessage((Player) caster.getEntity(), "ability-status", - CAST.replace("{n}", ability.getId()), 20, 11); + AdvancedActionBarUtil.addMessage((Player) caster.getEntity(), "ability-status", + CAST.replace("{n}", ability.getId()), 20, 11); } } playChatMessages(caster, ability); @@ -193,7 +192,7 @@ private void doToggleOff(AbilityCooldownContainer container, StrifeMob mob) { } container.setToggledOn(false); Ability ability = getAbility(container.getAbilityId()); - coolDownAbility(mob.getEntity(), ability); + coolDownAbility(mob, ability); Set targets = new HashSet<>(); targets.add(mob.getEntity()); @@ -299,15 +298,15 @@ private boolean hasEnergy(StrifeMob caster, Ability ability) { return true; } - private boolean canBeCast(LivingEntity entity, Ability ability) { - if (entity == null || !entity.isValid()) { + private boolean canBeCast(StrifeMob caster, Ability ability) { + if (caster.getEntity() == null || !caster.getEntity().isValid()) { return false; } if (ability == null) { - Bukkit.getLogger().warning("[Strife] " + entity.getName() + " tried to cast null ability"); + Bukkit.getLogger().warning("[Strife] " + caster.getEntity().getName() + " tried to cast null ability"); return false; } - AbilityCooldownContainer container = getCooldownContainer(entity, ability.getId()); + AbilityCooldownContainer container = getCooldownContainer(caster.getEntity(), ability.getId()); if (container == null || container.getSpentCharges() < ability.getMaxCharges()) { return true; } @@ -369,6 +368,10 @@ public boolean abilityCast(StrifeMob caster, StrifeMob target, TriggerAbilityTyp return true; } + if (!caster.isGlobalCooldownReady()) { + return false; + } + LivingEntity targetEntity; if (target == null) { targetEntity = TargetingUtil.getMobTarget(caster); @@ -398,15 +401,18 @@ public void setGlobalCooldown(Player player, int ticks) { Math.max(player.getCooldown(Material.DIAMOND_CHESTPLATE), ticks)); } - private void coolDownAbility(LivingEntity livingEntity, Ability ability) { - if (!coolingDownAbilities.containsKey(livingEntity)) { - coolingDownAbilities.put(livingEntity, new HashSet<>()); + private void coolDownAbility(StrifeMob caster, Ability ability) { + if (!coolingDownAbilities.containsKey(caster.getEntity())) { + coolingDownAbilities.put(caster.getEntity(), new HashSet<>()); + } + if (ability.getGlobalCooldownTicks() > 0) { + caster.bumpGlobalCooldown(ability.getGlobalCooldownTicks() * 500); } - AbilityCooldownContainer container = getCooldownContainer(livingEntity, ability.getId()); + AbilityCooldownContainer container = getCooldownContainer(caster.getEntity(), ability.getId()); if (container == null) { container = new AbilityCooldownContainer(ability.getId(), System.currentTimeMillis() + (int) (ability.getCooldown() * 1000f)); - coolingDownAbilities.get(livingEntity).add(container); + coolingDownAbilities.get(caster.getEntity()).add(container); } if (container.getSpentCharges() == 0) { container.setStartTime(System.currentTimeMillis()); @@ -436,7 +442,7 @@ private boolean toggleAbility(StrifeMob caster, Ability ability) { } if (container.isToggledOn()) { container.setToggledOn(false); - coolDownAbility(caster.getEntity(), ability); + coolDownAbility(caster, ability); Set entities = new HashSet<>(); entities.add(caster.getEntity()); @@ -511,22 +517,20 @@ private TargetResponse getTargets(StrifeMob caster, LivingEntity target, Ability loc2 = TargetingUtil.modifyLocation(loc2, ability.getRange() + 2); return new TargetResponse(loc2); case NEAREST_SOUL: - SoulTimer soul = plugin.getSoulManager() - .getNearestSoul(caster.getEntity(), ability.getRange()); + SoulTimer soul = plugin.getSoulManager().getNearestSoul(caster.getEntity(), + ability.getRange()); if (soul != null) { - Player playerTarget = Bukkit.getPlayer(soul.getOwner()); - boolean friendlyTarget = TargetingUtil.isFriendly(caster, playerTarget); - if (ability.isFriendly() == friendlyTarget) { - targets.add(Bukkit.getPlayer(soul.getOwner())); - } + targets.add(soul.getOwner()); } - return new TargetResponse(targets, true); + TargetResponse response = new TargetResponse(targets, true); + response.setForce(true); + return response; } return new TargetResponse(new HashSet<>()); } private boolean isAbilityCastReady(StrifeMob caster, StrifeMob target, Ability ability) { - return canBeCast(caster.getEntity(), ability) && PlayerDataUtil + return canBeCast(caster, ability) && PlayerDataUtil .areConditionsMet(caster, target, ability.getConditions()); } diff --git a/src/main/java/land/face/strife/managers/BlockManager.java b/src/main/java/land/face/strife/managers/BlockManager.java index 7ea4f1ac..9b4f191d 100644 --- a/src/main/java/land/face/strife/managers/BlockManager.java +++ b/src/main/java/land/face/strife/managers/BlockManager.java @@ -1,18 +1,20 @@ /** * The MIT License Copyright (c) 2015 Teal Cube Games *

- * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated - * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and + * associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: *

- * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the - * Software. + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. *

- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE - * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT + * NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ package land.face.strife.managers; @@ -40,49 +42,58 @@ import org.bukkit.Material; import org.bukkit.Particle; import org.bukkit.Sound; -import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; public class BlockManager { - private final Map blockDataMap = new WeakHashMap<>(); + private final Map blockDataMap = new WeakHashMap<>(); private final Random random = new Random(); private static final ItemStack BLOCK_DATA = new ItemStack(Material.COARSE_DIRT); - private static final double FLAT_BLOCK_S = 10; - private static final double PERCENT_BLOCK_S = 0.05; - private static final long DEFAULT_BLOCK_MILLIS = 10000; - private static final double MAX_BLOCK_CHANCE = 0.6; + private static final float FLAT_BLOCK_S = 8f; + private static final float PERCENT_BLOCK_S = 0.03f; + private static final double MAX_BLOCK_CHANCE = 0.5; - public void tickHolograms() { - - Iterator iterator = blockDataMap.keySet().iterator(); + public void tickBlock() { + for (StrifeMob mob : blockDataMap.keySet()) { + if (mob.getMaxBlock() < 0.5 || mob.getBlock() >= mob.getMaxBlock()) { + mob.setBlock(mob.getMaxBlock()); + continue; + } + float blockGain = FLAT_BLOCK_S + PERCENT_BLOCK_S * mob.getMaxBlock(); + mob.setBlock(Math.min(mob.getMaxBlock(), mob.getBlock() + blockGain / 20)); + } + } + public void tickHolograms() { + Iterator iterator = blockDataMap.keySet().iterator(); while (iterator.hasNext()) { - LivingEntity le = iterator.next(); - - if (le == null) { + StrifeMob mob = iterator.next(); + if (mob == null) { iterator.remove(); continue; } - - BlockData blockData = blockDataMap.get(le); - - if (!le.isValid()) { + BlockData blockData = blockDataMap.get(mob); + if (!mob.getEntity().isValid()) { for (Hologram holo : blockData.getRuneHolograms()) { holo.delete(); } iterator.remove(); continue; } - + if (System.currentTimeMillis() > blockData.getRuneFalloff()) { + blockData.setRunes(0); + } + if (blockData.getRunes() == 0 && blockData.getRuneHolograms().size() == 0) { + continue; + } if (blockData.getRunes() < blockData.getRuneHolograms().size()) { while (blockData.getRunes() < blockData.getRuneHolograms().size()) { Hologram hologram = getRandomFromCollection(blockData.getRuneHolograms()); - le.getWorld().playSound(hologram.getLocation(), Sound.BLOCK_GRASS_BREAK, 1f, 0.8f); - le.getWorld().spawnParticle( + mob.getEntity().getWorld().playSound(hologram.getLocation(), Sound.BLOCK_GRASS_BREAK, 1f, 0.8f); + mob.getEntity().getWorld().spawnParticle( Particle.ITEM_CRACK, hologram.getLocation(), 20, 0, 0, 0, 0.07f, @@ -92,13 +103,15 @@ public void tickHolograms() { hologram.delete(); } } else { - while (blockData.getRunes() > blockData.getRuneHolograms().size() && blockData.getRuneHolograms().size() < 6) { - Hologram hologram = HologramsAPI.createHologram(StrifePlugin.getInstance(), le.getEyeLocation()); + while (blockData.getRunes() > blockData.getRuneHolograms().size() + && blockData.getRuneHolograms().size() < 6) { + Hologram hologram = HologramsAPI + .createHologram(StrifePlugin.getInstance(), mob.getEntity().getEyeLocation()); hologram.appendItemLine(new ItemStack(Material.COARSE_DIRT)); blockData.getRuneHolograms().add(hologram); } } - orbitRunes(le.getLocation().clone().add(0, 1, 0), blockData.getRuneHolograms()); + orbitRunes(mob.getEntity().getLocation().clone().add(0, 1, 0), blockData.getRuneHolograms()); } } @@ -115,10 +128,10 @@ private void orbitRunes(Location center, Set runeHolograms) { } } - public boolean isAttackBlocked(StrifeMob attacker, StrifeMob defender, float attackMult, AttackType attackType, - boolean isBlocking) { + public boolean isAttackBlocked(StrifeMob attacker, StrifeMob defender, float attackMult, + AttackType attackType, boolean isBlocking) { if (rollBlock(defender, isBlocking)) { - blockFatigue(defender.getEntity(), attackMult, isBlocking); + blockFatigue(defender, attackMult, isBlocking, attackType == AttackType.PROJECTILE); bumpRunes(defender); DamageUtil.doReflectedDamage(defender, attacker, attackType); DamageUtil.doBlock(attacker, defender); @@ -128,11 +141,15 @@ public boolean isAttackBlocked(StrifeMob attacker, StrifeMob defender, float att } public boolean rollBlock(StrifeMob strifeMob, boolean isBlocking) { + if (!blockDataMap.containsKey(strifeMob)) { + BlockData data = new BlockData(); + blockDataMap.put(strifeMob, data); + strifeMob.setBlock(strifeMob.getMaxBlock()); + } if (strifeMob.getStat(StrifeStat.BLOCK) < 1) { return false; } - updateStoredBlock(strifeMob); - double blockChance = Math.min(blockDataMap.get(strifeMob.getEntity()).getStoredBlock() / 100, MAX_BLOCK_CHANCE); + double blockChance = Math.min(strifeMob.getBlock() / 100, MAX_BLOCK_CHANCE); if (isBlocking) { blockChance *= 2; } @@ -140,27 +157,20 @@ public boolean rollBlock(StrifeMob strifeMob, boolean isBlocking) { return random.nextDouble() < blockChance; } - public long getMillisSinceBlock(LivingEntity livingEntity) { - return System.currentTimeMillis() - blockDataMap.get(livingEntity).getLastHit(); - } - - public double getSecondsSinceBlock(LivingEntity livingEntity) { - return ((double) getMillisSinceBlock(livingEntity)) / 1000; - } - - public int getEarthRunes(LivingEntity livingEntity) { - if (!blockDataMap.containsKey(livingEntity)) { + public int getEarthRunes(StrifeMob mob) { + if (!blockDataMap.containsKey(mob)) { return 0; } - return blockDataMap.get(livingEntity).getRunes(); + return blockDataMap.get(mob).getRunes(); } public void setEarthRunes(StrifeMob mob, int runes) { - if (!blockDataMap.containsKey(mob.getEntity())) { - BlockData data = new BlockData(0, mob.getStat(StrifeStat.BLOCK)); - blockDataMap.put(mob.getEntity(), data); + if (!blockDataMap.containsKey(mob)) { + BlockData data = new BlockData(); + blockDataMap.put(mob, data); + mob.setBlock(mob.getMaxBlock()); } - BlockData data = blockDataMap.get(mob.getEntity()); + BlockData data = blockDataMap.get(mob); int maxRunes = Math.round(mob.getStat(StrifeStat.MAX_EARTH_RUNES)); if (maxRunes < 0.99 || mob.getStat(StrifeStat.EARTH_DAMAGE) < 1) { data.setRunes(0); @@ -176,46 +186,32 @@ public void bumpRunes(StrifeMob mob) { if (mob.getStat(StrifeStat.EARTH_DAMAGE) < 1) { return; } - int runes = getEarthRunes(mob.getEntity()); + int runes = getEarthRunes(mob); setEarthRunes(mob, runes + 1); } - private void updateStoredBlock(StrifeMob mob) { - if (blockDataMap.get(mob.getEntity()) == null) { - BlockData data = new BlockData(System.currentTimeMillis() - DEFAULT_BLOCK_MILLIS, 0); - blockDataMap.put(mob.getEntity(), data); - } - double maximumBlock = mob.getStat(StrifeStat.BLOCK); - double block = blockDataMap.get(mob.getEntity()).getStoredBlock(); - double restoredBlock = FLAT_BLOCK_S + PERCENT_BLOCK_S * maximumBlock; - if (mob.getStat(StrifeStat.BLOCK_RECOVERY) > 1) { - restoredBlock *= 1 + mob.getStat(StrifeStat.BLOCK_RECOVERY) / 100; + public void blockFatigue(StrifeMob mob, double attackMultipler, boolean physicallyBlocked, + boolean projectile) { + float fatigue = projectile ? 30 : 60; + if (physicallyBlocked) { + fatigue /= 2; } - - block += restoredBlock * getSecondsSinceBlock(mob.getEntity()); - blockDataMap.get(mob.getEntity()).setStoredBlock(Math.min(block, maximumBlock)); - blockDataMap.get(mob.getEntity()).setLastHit(System.currentTimeMillis()); - LogUtil.printDebug("New block before clamp: " + block); - } - - public void blockFatigue(LivingEntity livingEntity, double attackMultipler, boolean isBlocking) { - BlockData data = blockDataMap.get(livingEntity); - LogUtil.printDebug("Pre reduction block: " + data.getStoredBlock()); - double blockFatigue = attackMultipler * (isBlocking ? 50D : 100D); - data.setStoredBlock(Math.max(0, data.getStoredBlock() - blockFatigue)); - LogUtil.printDebug("Post reduction block: " + data.getStoredBlock()); + fatigue *= attackMultipler; + mob.setBlock(Math.max(0, mob.getBlock() - fatigue)); } private static void pushRunesBar(StrifeMob mob, int maxRunes, int runes) { if (!(mob.getEntity() instanceof Player)) { return; } - String message = ChatColor.GREEN + "Runes: " + ChatColor.DARK_GREEN + IntStream.range(0, runes).mapToObj(i -> "₪") + String message = ChatColor.GREEN + "Runes: " + ChatColor.DARK_GREEN + IntStream.range(0, runes) + .mapToObj(i -> "₪") .collect(Collectors.joining("")); message += ChatColor.BLACK + IntStream.range(0, maxRunes - runes).mapToObj(i -> "₪") .collect(Collectors.joining("")); - AdvancedActionBarUtil.addMessage((Player) mob.getEntity(), "rune-bar", message, runes == 0 ? 200 : 12000, 6); + AdvancedActionBarUtil + .addMessage((Player) mob.getEntity(), "rune-bar", message, runes == 0 ? 200 : 12000, 6); } public static T getRandomFromCollection(Collection coll) { diff --git a/src/main/java/land/face/strife/managers/ChampionManager.java b/src/main/java/land/face/strife/managers/ChampionManager.java index 3700d3f2..8f484e95 100644 --- a/src/main/java/land/face/strife/managers/ChampionManager.java +++ b/src/main/java/land/face/strife/managers/ChampionManager.java @@ -118,6 +118,21 @@ public boolean hasPendingChanges(Champion champion) { return !champion.getLevelMap().equals(champion.getPendingLevelMap()); } + public void verifyPendingStats(Champion champion) { + for (StrifeAttribute attr : new HashSet<>(champion.getPendingLevelMap().keySet())) { + int statCap = plugin.getAttributeManager().getPendingStatCap(attr, champion); + int diff = champion.getPendingLevelMap().get(attr) - statCap; + if (diff > 0) { + champion.getPendingLevelMap().put(attr, statCap); + } + } + int pendingTotal = 0; + for (StrifeAttribute stat : champion.getPendingLevelMap().keySet()) { + pendingTotal += champion.getPendingLevelMap().getOrDefault(stat, 0); + } + champion.setPendingUnusedStatPoints(champion.getPlayer().getLevel() - pendingTotal); + } + public void resetPendingStats(Champion champion) { champion.getSaveData().resetPendingStats(); } @@ -126,8 +141,7 @@ public void savePendingStats(Champion champion) { for (StrifeAttribute stat : champion.getPendingLevelMap().keySet()) { if (champion.getPendingLevel(stat) > champion.getAttributeLevel(stat)) { sendMessage(champion.getPlayer(), stat.getName() + " increased to " + champion.getPendingLevel(stat) + "!"); - champion.getPlayer() - .playSound(champion.getPlayer().getLocation(), stat.getLevelSound(), 1f, stat.getLevelPitch()); + champion.getPlayer().playSound(champion.getPlayer().getLocation(), stat.getLevelSound(), 1f, stat.getLevelPitch()); } } champion.getSaveData().savePendingStats(); diff --git a/src/main/java/land/face/strife/managers/ChaserManager.java b/src/main/java/land/face/strife/managers/ChaserManager.java index 61cdf50c..c659b7e0 100644 --- a/src/main/java/land/face/strife/managers/ChaserManager.java +++ b/src/main/java/land/face/strife/managers/ChaserManager.java @@ -2,7 +2,6 @@ import java.util.HashMap; import java.util.HashSet; -import java.util.Iterator; import java.util.List; import java.util.Set; import land.face.strife.StrifePlugin; @@ -22,46 +21,52 @@ public class ChaserManager { - private StrifePlugin plugin; - private HashMap chaserData = new HashMap<>(); - private Set chasers; + private final StrifePlugin plugin; + private final HashMap chaserData = new HashMap<>(); + private final Set chasers; public ChaserManager(StrifePlugin plugin) { this.plugin = plugin; this.chasers = new HashSet<>(); } - public void createChaser(StrifeMob caster, String id, Vector velocity, Location spawnLocation, LivingEntity target) { + public void createChaser(StrifeMob caster, String id, Vector velocity, Location spawnLocation, + LivingEntity target, float speedMult) { LoadedChaser data = chaserData.get(id); - ChaserEntity chaser = new ChaserEntity(caster, id, spawnLocation, target, data.getSpeed(), velocity, - data.getLifespan()); + ChaserEntity chaser = new ChaserEntity( + caster, id, spawnLocation, target, + data.getSpeed() * speedMult, + data.getMaxSpeed() * speedMult, + velocity, + data.getLifespan() + ); chasers.add(chaser); } public void tickChasers() { - Iterator iterator = chasers.iterator(); - while (iterator.hasNext()) { - ChaserEntity chaser = iterator.next(); + HashSet loopChasers = new HashSet<>(chasers); + + for (ChaserEntity chaser : loopChasers) { if (chaser.getCurrentTick() > chaser.getLifespan()) { - iterator.remove(); + chasers.remove(chaser); continue; } chaser.setCurrentTick(chaser.getCurrentTick() + 1); if (chaser.getTarget() == null || !chaser.getTarget().isValid() || !chaser.getLocation().getWorld().equals(chaser.getTarget().getWorld())) { - iterator.remove(); + chasers.remove(chaser); continue; } LoadedChaser data = chaserData.get(chaser.getChaserId()); if (data.isRemoveAtSolids() && chaser.getLocation().getBlock().getType().isSolid()) { - iterator.remove(); + chasers.remove(chaser); continue; } boolean hitTarget = executeChaserMovement(chaser, data); if (hitTarget) { - iterator.remove(); + chasers.remove(chaser); } } } @@ -69,18 +74,18 @@ public void tickChasers() { private boolean executeChaserMovement(ChaserEntity chaser, LoadedChaser data) { Location targetLocation = TargetingUtil.getOriginLocation(chaser.getTarget(), OriginLocation.CENTER); Vector change = targetLocation.toVector().subtract(chaser.getLocation().toVector()).normalize() - .multiply(data.getSpeed()); + .multiply(chaser.getSpeed()); Vector velocity = chaser.getVelocity(); velocity.add(change); - if (velocity.length() > data.getMaxSpeed()) { - velocity.normalize().multiply(data.getMaxSpeed()); + if (velocity.length() > chaser.getMaxSpeed()) { + velocity.normalize().multiply(chaser.getMaxSpeed()); } chaser.getLocation().add(velocity); for (StrifeParticle particle : data.getParticles()) { particle.applyAtLocation(chaser.getCaster(), chaser.getLocation().clone().subtract(chaser.getVelocity().clone().multiply(0.5))); } - if (isChaserCloseEnough(chaser, data, targetLocation)) { + if (isChaserCloseEnough(chaser, targetLocation)) { Set entities = new HashSet<>(); entities.add(chaser.getTarget()); TargetResponse response = new TargetResponse(entities); @@ -91,8 +96,8 @@ private boolean executeChaserMovement(ChaserEntity chaser, LoadedChaser data) { return false; } - private boolean isChaserCloseEnough(ChaserEntity chaser, LoadedChaser data, Location targetLoc) { - float hitRange = data.getMaxSpeed() + (float) chaser.getTarget().getWidth() / 2; + private boolean isChaserCloseEnough(ChaserEntity chaser, Location targetLoc) { + float hitRange = chaser.getMaxSpeed() + (float) chaser.getTarget().getWidth() / 2; return Math.abs(chaser.getLocation().getX() - targetLoc.getX()) < hitRange && Math.abs(chaser.getLocation().getY() - targetLoc.getY()) < hitRange && Math.abs(chaser.getLocation().getZ() - targetLoc.getZ()) < hitRange; diff --git a/src/main/java/land/face/strife/managers/CounterManager.java b/src/main/java/land/face/strife/managers/CounterManager.java index acda113e..50b6ffd7 100644 --- a/src/main/java/land/face/strife/managers/CounterManager.java +++ b/src/main/java/land/face/strife/managers/CounterManager.java @@ -16,7 +16,8 @@ */ package land.face.strife.managers; -import com.tealcube.minecraft.bukkit.facecore.utilities.MessageUtils; +import com.tealcube.minecraft.bukkit.facecore.utilities.AdvancedActionBarUtil; +import io.pixeloutlaw.minecraft.spigot.garbage.StringExtensionsKt; import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; @@ -38,6 +39,7 @@ public class CounterManager { private final Map> counterMap = new WeakHashMap<>(); private StrifePlugin plugin; private Sound counterSound; + private String COUNTER_MESSAGE; private float pitch; public CounterManager(StrifePlugin plugin) { @@ -45,6 +47,8 @@ public CounterManager(StrifePlugin plugin) { counterSound = Sound.valueOf(plugin.getSettings() .getString("config.mechanics.counter.sound", "ENCHANT_THORNS_HIT")); pitch = (float) plugin.getSettings().getDouble("config.mechanics.counter.pitch", 1); + COUNTER_MESSAGE = StringExtensionsKt.chatColorize( + plugin.getSettings().getString("language.status.counter-message", "&3&lCountered!")); } public void clearCounters(LivingEntity livingEntity) { @@ -75,10 +79,10 @@ public boolean executeCounters(LivingEntity attacker, LivingEntity defender) { defender.getWorld().playSound(defender.getLocation(), counterSound, 1.0f, pitch); if (attacker instanceof Player) { StrifePlugin.getInstance().getIndicatorManager().addIndicator(attacker, defender, - IndicatorStyle.BOUNCE, 6, "&3&o&lCounter!"); + IndicatorStyle.BOUNCE, 7, "&3⛨&lCounter"); } if (defender instanceof Player) { - MessageUtils.sendActionBar((Player) defender, "&e&lCountered!"); + AdvancedActionBarUtil.addMessage((Player) defender, "COMBAT-EVENT", COUNTER_MESSAGE, 10, 100); } if (!data.isTriggered()) { StrifeMob defenderMob = plugin.getStrifeMobManager().getStatMob(defender); diff --git a/src/main/java/land/face/strife/managers/EffectManager.java b/src/main/java/land/face/strife/managers/EffectManager.java index 5fec9ac0..cc2abe79 100644 --- a/src/main/java/land/face/strife/managers/EffectManager.java +++ b/src/main/java/land/face/strife/managers/EffectManager.java @@ -85,6 +85,7 @@ import land.face.strife.data.effects.EndlessEffect; import land.face.strife.data.effects.EquipmentSwap; import land.face.strife.data.effects.EvokerFangEffect; +import land.face.strife.data.effects.FireworkBurst; import land.face.strife.data.effects.Food; import land.face.strife.data.effects.ForceStat; import land.face.strife.data.effects.ForceTarget; @@ -114,6 +115,7 @@ import land.face.strife.data.effects.SwingArm; import land.face.strife.data.effects.Teleport; import land.face.strife.data.effects.TeleportBehind; +import land.face.strife.data.effects.Thrall; import land.face.strife.data.effects.Title; import land.face.strife.data.effects.Undisguise; import land.face.strife.data.effects.UntoggleAbility; @@ -133,6 +135,7 @@ import org.apache.commons.lang.StringUtils; import org.bukkit.Bukkit; import org.bukkit.Color; +import org.bukkit.FireworkEffect.Type; import org.bukkit.Material; import org.bukkit.Particle; import org.bukkit.Sound; @@ -226,22 +229,14 @@ public void execute(Effect effect, StrifeMob caster, TargetResponse response) { effect.apply(caster, effect.isForceTargetCaster() ? caster : targetMob); continue; } - if (effect.isFriendly() != TargetingUtil.isFriendly(caster, targetMob)) { - continue; + if (!response.isForce()) { + if (effect.isFriendly() != TargetingUtil.isFriendly(caster, targetMob)) { + continue; + } } - applyEffectIfConditionsMet(effect, caster, effect.isForceTargetCaster() ? caster : targetMob); - } - } - - private void applyEffectIfConditionsMet(Effect effect, StrifeMob caster, StrifeMob targetMob) { - if (targetMob == null) { - targetMob = caster; - } - if (!PlayerDataUtil.areConditionsMet(caster, targetMob, effect.getConditions())) { - return; + LogUtil.printDebug("-- Applying '" + effect.getId() + "' to " + getName(targetMob.getEntity())); + effect.apply(caster, effect.isForceTargetCaster() ? caster : targetMob); } - LogUtil.printDebug("-- Applying '" + effect.getId() + "' to " + getName(targetMob.getEntity())); - effect.apply(caster, effect.isForceTargetCaster() ? caster : targetMob); } public void loadEffect(String key, ConfigurationSection cs) { @@ -573,6 +568,7 @@ public void loadEffect(String key, ConfigurationSection cs) { double z = cs.getDouble("z", 0); ((Teleport) effect).setVector(new Vector(x, y, z)); ((Teleport) effect).setRelative(cs.getBoolean("relative", false)); + ((Teleport) effect).getWorldSwapWhitelist().addAll(cs.getStringList("world-swap-whitelist")); List destEffects = cs.getStringList("destination-effects"); List originEffects = cs.getStringList("origin-effects"); delayedSetEffects(((Teleport) effect).getDestinationEffects(), destEffects, key, true); @@ -581,6 +577,11 @@ public void loadEffect(String key, ConfigurationSection cs) { case TELEPORT_BEHIND: effect = new TeleportBehind(); break; + case THRALL: + effect = new Thrall(); + ((Thrall) effect).setName(cs.getString("name", "&8«&7Thrall&8»")); + ((Thrall) effect).setLifeSeconds(cs.getInt("lifespan-seconds", 20)); + break; case TITLE: effect = new Title(); ((Title) effect).setTopTitle(cs.getString("upper", "")); @@ -653,8 +654,7 @@ public void loadEffect(String key, ConfigurationSection cs) { effect = new Charm(); ((Charm) effect).setChance((float) cs.getDouble("success-chance", 1)); ((Charm) effect).setChancePerLevel((float) cs.getDouble("chance-per-level", 0)); - ((Charm) effect) - .setLifespanSeconds((float) cs.getDouble("lifespan-seconds", 30)); + ((Charm) effect).setLifespanSeconds((float) cs.getDouble("lifespan-seconds", 30)); ((Charm) effect).setOverrideMaster(cs.getBoolean("override", false)); break; case SWING: @@ -719,6 +719,21 @@ public void loadEffect(String key, ConfigurationSection cs) { ((PlaySound) effect).setVolume((float) cs.getDouble("volume", 1)); ((PlaySound) effect).setPitch((float) cs.getDouble("pitch", 1)); break; + case FIREWORK: + effect = new FireworkBurst(); + try { + ((FireworkBurst) effect).setEffectType(Type.valueOf((cs.getString("effect-type")))); + } catch (Exception e) { + LogUtil.printWarning("Invalid firework effect type in effect " + key + ". Skipping."); + return; + } + int colorOne = Integer.parseInt(cs.getString("color-one", "0xFFFFFF")); + ((FireworkBurst) effect).setColorOne(Color.fromRGB(colorOne)); + int colorTwo = Integer.parseInt(cs.getString("color-two", "0xFFFFFF")); + ((FireworkBurst) effect).setColorTwo(Color.fromRGB(colorTwo)); + ((FireworkBurst) effect).setFlicker(cs.getBoolean("flicker", false)); + ((FireworkBurst) effect).setTrail(cs.getBoolean("trail", false)); + break; case PARTICLE: effect = new StrifeParticle(); Particle particle; diff --git a/src/main/java/land/face/strife/managers/SoulManager.java b/src/main/java/land/face/strife/managers/SoulManager.java index 1b25150a..582d2054 100644 --- a/src/main/java/land/face/strife/managers/SoulManager.java +++ b/src/main/java/land/face/strife/managers/SoulManager.java @@ -7,6 +7,7 @@ import java.util.HashSet; import java.util.Set; import land.face.strife.StrifePlugin; +import land.face.strife.data.StrifeMob; import land.face.strife.data.ability.Ability; import land.face.strife.data.ability.Ability.TargetType; import land.face.strife.data.champion.ChampionSaveData; @@ -47,10 +48,11 @@ public boolean canSeeSouls(Player player) { return false; } - public void createSoul(Player player) { + public void createSoul(StrifeMob mob) { SoulTimer oldSoul = null; + Player player = (Player) mob.getEntity(); for (SoulTimer soulTimer : souls) { - if (soulTimer.getOwner() == player.getUniqueId()) { + if (soulTimer.getOwner() == player) { oldSoul = soulTimer; break; } @@ -62,7 +64,7 @@ public void createSoul(Player player) { String text = soulColor + "" + ChatColor.ITALIC + soulName.replace("{n}", player.getName()); Hologram soulHead = SoulUtil.createSoul(player, text, location.clone().add(0, 0.75, 0)); - souls.add(new SoulTimer(player.getUniqueId(), soulHead, location)); + souls.add(new SoulTimer(mob, soulHead, location)); } public void removeSoul(SoulTimer soulTimer) { @@ -89,7 +91,7 @@ public SoulTimer getNearestSoul(LivingEntity le, float maxDistSquared) { public SoulTimer getSoul(Player player) { for (SoulTimer soulTimer : souls) { - if (soulTimer.getOwner().equals(player.getUniqueId())) { + if (soulTimer.getOwner() == player) { return soulTimer; } } diff --git a/src/main/java/land/face/strife/managers/StatUpdateManager.java b/src/main/java/land/face/strife/managers/StatUpdateManager.java index b497ee1e..d6fa4ed0 100644 --- a/src/main/java/land/face/strife/managers/StatUpdateManager.java +++ b/src/main/java/land/face/strife/managers/StatUpdateManager.java @@ -101,15 +101,6 @@ public void updateHealth(StrifeMob mob) { double maxHealth = Math.max(StatUtil.getHealth(mob), 1); mob.getEntity().getAttribute(Attribute.GENERIC_MAX_HEALTH).setBaseValue(maxHealth); mob.getEntity().setHealth(Math.min(maxHealth, health * (maxHealth / oldMaxHealth))); - if (mob.getChampion() != null) { - HealthDisplayType displayType = mob.getChampion().getSaveData().getHealthDisplayType(); - if (displayType == HealthDisplayType.VANILLA_TWO_LIFE_PER_HEART) { - ((Player) mob.getEntity()).setHealthScaled(false); - return; - } - ((Player) mob.getEntity()).setHealthScaled(true); - ((Player) mob.getEntity()).setHealthScale(getHealthScale(displayType, maxHealth)); - } } public void updateWeight(StrifeMob mob) { @@ -154,19 +145,45 @@ public void updateVanillaAttributes(StrifeMob strifeMob) { updateWeight(strifeMob); } - private double getHealthScale(HealthDisplayType healthDisplayType, double maxHealth) { + public static float getHealthScale(HealthDisplayType healthDisplayType, float maxHealth) { + switch (healthDisplayType) { + case TWENTY_LIFE_PER_HEART: + return 2f * (float) Math.ceil(maxHealth / 20f); + case TEN_LIFE_PER_HEART: + return 2f * (float) Math.ceil(maxHealth / 10f); + case FIVE_LIFE_PER_HEART: + return 2f * (float) Math.ceil(maxHealth / 5f); + case VANILLA_TWO_LIFE_PER_HEART: + return 2f * (float) Math.ceil(maxHealth / 2f); + case TWO_ROWS_OF_LIFE: + return 40f; + case THREE_ROWS_OF_LIFE: + return 60f; + case ONE_ROW_OF_LIFE: + default: + return 20f; + } + } + + public static float getBarrierScale(HealthDisplayType healthDisplayType, float maxHealth, + float maxBarrier) { switch (healthDisplayType) { + case VANILLA_TWO_LIFE_PER_HEART: + return 2f * (float) Math.ceil(maxBarrier / 2f); case FIVE_LIFE_PER_HEART: - return 2 * Math.ceil(maxHealth / 5); + return 2f * (float) Math.ceil(maxBarrier / 5f); case TEN_LIFE_PER_HEART: - return 2 * Math.ceil(maxHealth / 10); + return 2f * (float) Math.ceil(maxBarrier / 10f); + case TWENTY_LIFE_PER_HEART: + return 2f * (float) Math.ceil(maxBarrier / 20f); case TWO_ROWS_OF_LIFE: - return 40; + return 20f * (float) Math.max(Math.floor(2 * maxBarrier / maxHealth), 1); case THREE_ROWS_OF_LIFE: - return 60; + return 20f * (float) Math.max(Math.floor(3 * maxBarrier / maxHealth), 1); case ONE_ROW_OF_LIFE: + return 20f * (float) Math.max(Math.floor(maxBarrier / maxHealth), 1); default: - return 20; + return 20f; } } diff --git a/src/main/java/land/face/strife/managers/StrifeMobManager.java b/src/main/java/land/face/strife/managers/StrifeMobManager.java index 3810db0f..f6df38d3 100644 --- a/src/main/java/land/face/strife/managers/StrifeMobManager.java +++ b/src/main/java/land/face/strife/managers/StrifeMobManager.java @@ -40,7 +40,7 @@ public StrifeMobManager(StrifePlugin plugin) { this.plugin = plugin; dualWieldAttackSpeed = (float) plugin.getSettings().getDouble("config.mechanics.dual-wield-attack-speed", 0) / 2; levelReqGeneric = plugin.getSettings().getString("language.level-req.generic", ""); - for (EquipmentSlot slot : EquipmentSlot.values()) { + for (EquipmentSlot slot : EquipmentCache.ITEM_SLOTS) { levelReqMap.put(slot, plugin.getSettings().getString("language.level-req." + slot, "")); } } @@ -245,6 +245,7 @@ public void updateEquipmentStats(StrifeMob mob) { if (mob.getChampion() != null) { mob.getChampion().recombineCache(); } + mob.updateBarrierScale(); } private void applyDualWieldStatChanges(EquipmentCache cache, EquipmentSlot slot) { diff --git a/src/main/java/land/face/strife/managers/UniqueEntityManager.java b/src/main/java/land/face/strife/managers/UniqueEntityManager.java index dabd9355..c212e5c1 100644 --- a/src/main/java/land/face/strife/managers/UniqueEntityManager.java +++ b/src/main/java/land/face/strife/managers/UniqueEntityManager.java @@ -5,7 +5,9 @@ import com.tealcube.minecraft.bukkit.shade.apache.commons.lang3.StringUtils; import io.pixeloutlaw.minecraft.spigot.config.VersionedSmartYamlConfiguration; import io.pixeloutlaw.minecraft.spigot.garbage.StringExtensionsKt; +import io.pixeloutlaw.minecraft.spigot.hilt.ItemStackExtensionsKt; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; import java.util.Objects; import land.face.strife.StrifePlugin; @@ -27,6 +29,7 @@ import me.libraryaddict.disguise.disguisetypes.Disguise; import org.bukkit.Bukkit; import org.bukkit.Location; +import org.bukkit.Material; import org.bukkit.attribute.AttributeInstance; import org.bukkit.attribute.AttributeModifier; import org.bukkit.configuration.ConfigurationSection; @@ -36,6 +39,7 @@ import org.bukkit.entity.Entity; import org.bukkit.entity.EntityType; import org.bukkit.entity.Hoglin; +import org.bukkit.entity.Horse; import org.bukkit.entity.Item; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Phantom; @@ -51,6 +55,8 @@ import org.bukkit.entity.ZombieVillager; import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.ItemStack; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; public class UniqueEntityManager { @@ -58,10 +64,14 @@ public class UniqueEntityManager { private final Map loadedUniquesMap; private final Map cachedDisguises; + public static ItemStack DEV_SADDLE; + public UniqueEntityManager(StrifePlugin plugin) { this.plugin = plugin; this.loadedUniquesMap = new HashMap<>(); this.cachedDisguises = new HashMap<>(); + DEV_SADDLE = new ItemStack(Material.SADDLE); + ItemStackExtensionsKt.setCustomModelData(DEV_SADDLE, 3000); } public UniqueEntity getUnique(String uniqueId) { @@ -86,19 +96,11 @@ public StrifeMob spawnUnique(String unique, Location location) { plugin.getLogger().warning("Attempted to spawn non-existing unique: " + unique); return null; } - return spawnUnique(uniqueEntity, location); - } - - private void lambdaSetup(Entity e, UniqueEntity uniqueEntity) { - SpecialStatusUtil.setUniqueId(e, uniqueEntity.getId()); - if (cachedDisguises.containsKey(uniqueEntity)) { - //System.out.println(DisguiseParser.parseToString(cachedDisguises.get(uniqueEntity))); - DisguiseAPI.disguiseToAll(e, cachedDisguises.get(uniqueEntity)); - //System.out.println(DisguiseParser.parseToString(DisguiseAPI.getDisguise(e))); - } + return plugin.getStrifeMobManager() + .getStatMob((LivingEntity) spawnUnique(uniqueEntity, location)); } - public StrifeMob spawnUnique(UniqueEntity uniqueEntity, Location location) { + public Entity spawnUnique(UniqueEntity uniqueEntity, Location location) { if (uniqueEntity.getType() == null) { LogUtil.printWarning("Null entity type: " + uniqueEntity.getName()); return null; @@ -106,13 +108,16 @@ public StrifeMob spawnUnique(UniqueEntity uniqueEntity, Location location) { LogUtil.printDebug("Spawning unique entity " + uniqueEntity.getId()); assert uniqueEntity.getType().getEntityClass() != null; - Entity entity = Objects.requireNonNull(location.getWorld()).spawn(location, - uniqueEntity.getType().getEntityClass(), e -> lambdaSetup(e, uniqueEntity)); + return Objects.requireNonNull(location.getWorld()).spawn(location, + uniqueEntity.getType().getEntityClass(), e -> lambdaSetup(e, uniqueEntity, location)); + } - if (!entity.isValid()) { - LogUtil.printWarning( - "Attempted to spawn unique " + uniqueEntity.getName() + " but entity is invalid?"); - return null; + private void lambdaSetup(Entity entity, UniqueEntity uniqueEntity, Location location) { + SpecialStatusUtil.setUniqueId(entity, uniqueEntity.getId()); + if (cachedDisguises.containsKey(uniqueEntity)) { + //System.out.println(DisguiseParser.parseToString(cachedDisguises.get(uniqueEntity))); + DisguiseAPI.disguiseToAll(entity, cachedDisguises.get(uniqueEntity)); + //System.out.println(DisguiseParser.parseToString(DisguiseAPI.getDisguise(e))); } LivingEntity le = (LivingEntity) entity; @@ -209,6 +214,10 @@ public StrifeMob spawnUnique(UniqueEntity uniqueEntity, Location location) { } } + if (uniqueEntity.isInvisible()) { + le.addPotionEffect(new PotionEffect(PotionEffectType.INVISIBILITY, 99999999, 10)); + } + le.setCanPickupItems(false); if (le.getEquipment() != null) { Map equipmentMap = plugin.getEquipmentManager() @@ -216,6 +225,12 @@ public StrifeMob spawnUnique(UniqueEntity uniqueEntity, Location location) { ItemUtil.delayedEquip(equipmentMap, le, true); } + if (uniqueEntity.isSaddled() && le.getType() == EntityType.HORSE) { + assert le instanceof Horse; + Horse horse = (Horse) le; + horse.getInventory().setSaddle(DEV_SADDLE); + } + if (uniqueEntity.getItemPassenger() != null) { Item item = Objects.requireNonNull(location.getWorld()).spawn(location, Item.class, i -> modifyPassengerItem(le, i)); @@ -236,7 +251,8 @@ public StrifeMob spawnUnique(UniqueEntity uniqueEntity, Location location) { if (mobLevel == 0) { mob.setStats(uniqueEntity.getAttributeMap()); } else { - mob.setStats(StatUpdateManager.combineMaps(mob.getBaseStats(), uniqueEntity.getAttributeMap())); + mob.setStats( + StatUpdateManager.combineMaps(mob.getBaseStats(), uniqueEntity.getAttributeMap())); } if (uniqueEntity.getMaxMods() > 0) { @@ -244,7 +260,7 @@ public StrifeMob spawnUnique(UniqueEntity uniqueEntity, Location location) { } mob.setUniqueEntityId(uniqueEntity.getId()); - mob.setFactions(uniqueEntity.getFactions()); + mob.setFactions(new HashSet<>(uniqueEntity.getFactions())); mob.setAlliedGuild(null); SpecialStatusUtil.setDespawnOnUnload(mob.getEntity()); mob.setCharmImmune(uniqueEntity.isCharmImmune()); @@ -259,25 +275,27 @@ public StrifeMob spawnUnique(UniqueEntity uniqueEntity, Location location) { SpecialStatusUtil.setSneakImmune(le); } if (StringUtils.isNotBlank(uniqueEntity.getMount())) { - StrifeMob mountMob = spawnUnique(uniqueEntity.getMount(), location); - if (mountMob != null) { - mountMob.getEntity().addPassenger(mob.getEntity()); - mob.addMinion(mountMob, 0); - } + Bukkit.getScheduler().runTaskLater(StrifePlugin.getInstance(), () -> { + StrifeMob mountMob = spawnUnique(uniqueEntity.getMount(), location); + if (mountMob != null) { + mountMob.getEntity().addPassenger(mob.getEntity()); + mob.addMinion(mountMob, 0); + } + }, 2L); } plugin.getStatUpdateManager().updateVanillaAttributes(mob); mob.setAbilitySet(new EntityAbilitySet(uniqueEntity.getAbilitySet())); - plugin.getAbilityManager().abilityCast(mob, TriggerAbilityType.PHASE_SHIFT); - plugin.getParticleTask().addParticle(le, uniqueEntity.getStrifeParticle()); - plugin.getAbilityManager().startAbilityTimerTask(mob); + Bukkit.getScheduler().runTaskLater(StrifePlugin.getInstance(), () -> { + plugin.getAbilityManager().abilityCast(mob, TriggerAbilityType.PHASE_SHIFT); + plugin.getParticleTask().addParticle(le, uniqueEntity.getStrifeParticle()); + plugin.getAbilityManager().startAbilityTimerTask(mob); + }, 0L); UniqueSpawnEvent event = new UniqueSpawnEvent(mob); Bukkit.getPluginManager().callEvent(event); - - return mob; } private void modifyPassengerItem(LivingEntity rider, Item item) { @@ -306,13 +324,15 @@ public void loadUniques(VersionedSmartYamlConfiguration uniqueEnemiesYAML) { try { uniqueEntity.setType(EntityType.valueOf(type)); } catch (Exception e) { - Bukkit.getLogger().severe("Failed to parse entity " + entityNameKey + ". Invalid type: " + type); + Bukkit.getLogger() + .severe("Failed to parse entity " + entityNameKey + ". Invalid type: " + type); continue; } uniqueEntity.setId(entityNameKey); uniqueEntity.setName( - StringExtensionsKt.chatColorize(Objects.requireNonNull(cs.getString("name", "&fSET &cA &9NAME")))); + StringExtensionsKt + .chatColorize(Objects.requireNonNull(cs.getString("name", "&fSET &cA &9NAME")))); uniqueEntity.setBonusExperience(cs.getInt("bonus-experience", 0)); uniqueEntity.setDisplaceMultiplier(cs.getDouble("displace-multiplier", 1.0)); uniqueEntity.setExperienceMultiplier((float) cs.getDouble("experience-multiplier", 1)); @@ -321,6 +341,7 @@ public void loadUniques(VersionedSmartYamlConfiguration uniqueEnemiesYAML) { uniqueEntity.setFallImmune(cs.getBoolean("fall-immune", false)); uniqueEntity.setPushImmune(cs.getBoolean("push-immune", false)); uniqueEntity.setIgnoreSneak(cs.getBoolean("ignore-sneak", false)); + uniqueEntity.setSaddled(cs.getBoolean("saddled", false)); uniqueEntity.setMaxMods(cs.getInt("max-mods", 3)); uniqueEntity.setRemoveFollowMods(cs.getBoolean("remove-range-modifiers", false)); if (uniqueEntity.getType() == EntityType.CREEPER) { @@ -337,7 +358,9 @@ public void loadUniques(VersionedSmartYamlConfiguration uniqueEnemiesYAML) { uniqueEntity.setArmsRaised(cs.getBoolean("arms-raised", true)); uniqueEntity.setGravity(cs.getBoolean("gravity", true)); uniqueEntity.setHasAI(cs.getBoolean("has-ai", true)); - if (uniqueEntity.getType() == EntityType.VILLAGER || uniqueEntity.getType() == EntityType.ZOMBIE_VILLAGER) { + uniqueEntity.setInvisible(cs.getBoolean("invisible", false)); + if (uniqueEntity.getType() == EntityType.VILLAGER + || uniqueEntity.getType() == EntityType.ZOMBIE_VILLAGER) { String prof = cs.getString("profession"); if (prof != null) { uniqueEntity.setProfession(Profession.valueOf(prof.toUpperCase())); @@ -346,7 +369,8 @@ public void loadUniques(VersionedSmartYamlConfiguration uniqueEnemiesYAML) { uniqueEntity.setBaseLevel(cs.getInt("base-level", -1)); Disguise disguise = PlayerDataUtil - .parseDisguise(cs.getConfigurationSection("disguise"), uniqueEntity.getName(), uniqueEntity.getMaxMods() > 0); + .parseDisguise(cs.getConfigurationSection("disguise"), uniqueEntity.getName(), + uniqueEntity.getMaxMods() > 0); if (disguise != null) { cacheDisguise(uniqueEntity, disguise); @@ -357,7 +381,8 @@ public void loadUniques(VersionedSmartYamlConfiguration uniqueEnemiesYAML) { uniqueEntity.setAttributeMap(attributeMap); uniqueEntity.setEquipment( - plugin.getEquipmentManager().buildEquipmentFromConfigSection(cs.getConfigurationSection("equipment"))); + plugin.getEquipmentManager() + .buildEquipmentFromConfigSection(cs.getConfigurationSection("equipment"))); String passengerItem = cs.getString("item-passenger", ""); if (org.apache.commons.lang.StringUtils.isNotBlank(passengerItem)) { diff --git a/src/main/java/land/face/strife/menus/levelup/LevelupMenuItem.java b/src/main/java/land/face/strife/menus/levelup/LevelupMenuItem.java index 3db9fb3e..d56debad 100644 --- a/src/main/java/land/face/strife/menus/levelup/LevelupMenuItem.java +++ b/src/main/java/land/face/strife/menus/levelup/LevelupMenuItem.java @@ -27,9 +27,12 @@ import land.face.strife.data.champion.StrifeAttribute; import ninja.amp.ampmenus.events.ItemClickEvent; import ninja.amp.ampmenus.items.MenuItem; +import org.bukkit.ChatColor; import org.bukkit.Material; +import org.bukkit.Sound; import org.bukkit.enchantments.Enchantment; import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemFlag; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; @@ -50,7 +53,8 @@ public class LevelupMenuItem extends MenuItem { @Override public ItemStack getFinalIcon(Player player) { Champion champion = plugin.getChampionManager().getChampion(player); - int currentPoints = champion.getPendingLevel(attribute); + int pendingPoints = champion.getPendingLevel(attribute); + int actualPoints = champion.getAttributeLevel(attribute); int statCap = plugin.getAttributeManager().getPendingStatCap(attribute, champion); ItemStack icon = getIcon().clone(); @@ -59,15 +63,15 @@ public ItemStack getFinalIcon(Player player) { if (champion.getAttributeLevel(attribute) == attribute.getMaxCap()) { ItemStackExtensionsKt.setCustomModelData(icon, attribute.getCustomData() + 1); icon.setAmount(attribute.getMaxCap()); - } else if (currentPoints == 0) { + } else if (pendingPoints == 0) { ItemStackExtensionsKt.setCustomModelData(icon, 99); } else { ItemStackExtensionsKt.setCustomModelData(icon, attribute.getCustomData()); - icon.setAmount(currentPoints); + icon.setAmount(pendingPoints); } } ItemMeta itemMeta = icon.getItemMeta(); - if (currentPoints != statCap && champion.getPendingUnusedStatPoints() > 0) { + if (pendingPoints != statCap && champion.getPendingUnusedStatPoints() > 0) { itemMeta.addEnchant(Enchantment.DURABILITY, 1, true); itemMeta.addItemFlags(ItemFlag.HIDE_ENCHANTS); } @@ -86,8 +90,13 @@ public ItemStack getFinalIcon(Player player) { } lore.add(breakLine); - ItemStackExtensionsKt - .setDisplayName(icon, getDisplayName() + " [" + currentPoints + "/" + statCap + "]"); + if (pendingPoints > actualPoints) { + String pendingPlus = ChatColor.WHITE + "(+" + (pendingPoints - actualPoints) + " Pending)"; + ItemStackExtensionsKt.setDisplayName(icon, getDisplayName() + " [" + pendingPoints + "/" + statCap + "]" + pendingPlus); + } else { + ItemStackExtensionsKt.setDisplayName(icon, getDisplayName() + " [" + actualPoints + "/" + statCap + "]"); + } + ItemStackExtensionsKt.setLore(icon, lore); return icon; @@ -98,16 +107,28 @@ public void onItemClick(ItemClickEvent event) { super.onItemClick(event); Player p = event.getPlayer(); Champion champion = plugin.getChampionManager().getChampion(p); - if (champion.getPendingUnusedStatPoints() < 1) { - return; - } - int currentLevel = champion.getPendingLevel(attribute); - if (currentLevel + 1 > plugin.getAttributeManager().getPendingStatCap(attribute, champion)) { - return; + event.setWillUpdate(false); + if (event.getClickType() == ClickType.LEFT) { + if (champion.getPendingUnusedStatPoints() < 1) { + return; + } + int currentLevel = champion.getPendingLevel(attribute); + if (currentLevel + 1 > plugin.getAttributeManager().getPendingStatCap(attribute, champion)) { + return; + } + p.playSound(p.getLocation(), attribute.getClickSound(), 1f, attribute.getClickPitch()); + champion.setPendingLevel(attribute, currentLevel + 1); + champion.setPendingUnusedStatPoints(champion.getPendingUnusedStatPoints() - 1); + event.setWillUpdate(true); + } else if (event.getClickType() == ClickType.RIGHT) { + int currentLevel = champion.getPendingLevel(attribute); + if (currentLevel == 0 || currentLevel == champion.getAttributeLevel(attribute)) { + return; + } + p.playSound(p.getLocation(), Sound.UI_LOOM_TAKE_RESULT, 1f, 0.5f); + champion.setPendingLevel(attribute, currentLevel - 1); + plugin.getChampionManager().verifyPendingStats(champion); + event.setWillUpdate(true); } - p.playSound(p.getLocation(), attribute.getClickSound(), 1f, attribute.getClickPitch()); - champion.setPendingLevel(attribute, currentLevel + 1); - champion.setPendingUnusedStatPoints(champion.getPendingUnusedStatPoints() - 1); - event.setWillUpdate(true); } } diff --git a/src/main/java/land/face/strife/menus/levelup/LevelupPointsMenuItem.java b/src/main/java/land/face/strife/menus/levelup/LevelupPointsMenuItem.java index 4f87e73d..23b5b4ab 100644 --- a/src/main/java/land/face/strife/menus/levelup/LevelupPointsMenuItem.java +++ b/src/main/java/land/face/strife/menus/levelup/LevelupPointsMenuItem.java @@ -37,9 +37,11 @@ public class LevelupPointsMenuItem extends MenuItem { private static final String DISPLAY_NAME = "&f&nUnused Levelpoints"; private static final ItemStack DISPLAY_ICON = new ItemStack(Material.NETHER_STAR); private static final String[] DISPLAY_LORE = { - ChatColor.GRAY + "Click an attribute to upgrade!" + ChatColor.GRAY + "Click attributes to upgrade them!", + ChatColor.GRAY + "Once you're done, click this icon", + ChatColor.GRAY + "to confirm changes!" }; - private static final String CLICK_TO_SAVE_TEXT = TextUtils.color("&e&lClick to apply changes!"); + private static final String CLICK_TO_SAVE_TEXT = TextUtils.color("&a&lClick to confirm changes!"); private final StrifePlugin plugin; @@ -57,7 +59,8 @@ public ItemStack getFinalIcon(Player player) { int stacks = champion.getPendingUnusedStatPoints(); String name = TextUtils.color("&f&nUnused Levelpoints (" + stacks + ")"); - if (champion.getPendingLevelMap().size() > 0) { + if (champion.getPendingUnusedStatPoints() != champion.getUnusedStatPoints()) { + lore.add(""); lore.add(CLICK_TO_SAVE_TEXT); } diff --git a/src/main/java/land/face/strife/menus/stats/StatsChangeHealthDisplay.java b/src/main/java/land/face/strife/menus/stats/StatsChangeHealthDisplay.java index 249819db..19835f26 100644 --- a/src/main/java/land/face/strife/menus/stats/StatsChangeHealthDisplay.java +++ b/src/main/java/land/face/strife/menus/stats/StatsChangeHealthDisplay.java @@ -24,9 +24,13 @@ import java.util.Map; import java.util.WeakHashMap; import land.face.strife.StrifePlugin; +import land.face.strife.data.StrifeMob; import land.face.strife.data.champion.Champion; import land.face.strife.data.champion.ChampionSaveData; +import land.face.strife.data.champion.ChampionSaveData.HealthDisplayType; +import land.face.strife.managers.StatUpdateManager; import land.face.strife.menus.BlankIcon; +import land.face.strife.util.StatUtil; import ninja.amp.ampmenus.events.ItemClickEvent; import ninja.amp.ampmenus.items.MenuItem; import org.apache.commons.lang.WordUtils; @@ -77,14 +81,23 @@ public void onItemClick(ItemClickEvent event) { if (!selfInspectMap.getOrDefault(event.getPlayer(), false)) { return; } - Champion champion = plugin.getChampionManager().getChampion(event.getPlayer()); + StrifeMob playerMob = plugin.getStrifeMobManager().getStatMob(event.getPlayer()); + Champion champion = playerMob.getChampion(); int ordinal = champion.getSaveData().getHealthDisplayType().ordinal(); ordinal++; if (ordinal == ChampionSaveData.DISPLAY_OPTIONS.length) { ordinal = 0; } champion.getSaveData().setHealthDisplayType(ChampionSaveData.DISPLAY_OPTIONS[ordinal]); - plugin.getStatUpdateManager().updateHealth(plugin.getStrifeMobManager().getStatMob(event.getPlayer())); + event.getPlayer().setHealthScaled(true); + HealthDisplayType displayType = champion.getSaveData().getHealthDisplayType(); + float maxHealth = Math.max(StatUtil.getHealth(playerMob), 1); + event.getPlayer().setInvulnerable(true); + event.getPlayer().setHealthScale(StatUpdateManager.getHealthScale(displayType, maxHealth)); + event.getPlayer().setInvulnerable(false); + + playerMob.updateBarrierScale(); + event.setWillUpdate(true); event.setWillClose(false); } diff --git a/src/main/java/land/face/strife/menus/stats/StatsOffenseMenuItem.java b/src/main/java/land/face/strife/menus/stats/StatsOffenseMenuItem.java index ae3cd81c..58dda257 100644 --- a/src/main/java/land/face/strife/menus/stats/StatsOffenseMenuItem.java +++ b/src/main/java/land/face/strife/menus/stats/StatsOffenseMenuItem.java @@ -115,21 +115,20 @@ public ItemStack getFinalIcon(Player commandSender) { addIfApplicable(damageDisplay, shadow, ChatColor.DARK_PURPLE, "☠"); addIfApplicable(damageDisplay, trueDmg, ChatColor.GRAY, "Ω"); lore.add(damageDisplay.toString()); - double criticalMult = 1; - if (!mob.getTraits().contains(StrifeTrait.NO_CRIT_MULT)) { + float critMult = mob.getStat(StrifeStat.CRITICAL_DAMAGE) / 100; + if (!mob.hasTrait(StrifeTrait.NO_CRIT_MULT)) { float critDamage; - if (mob.getTraits().contains(StrifeTrait.ELEMENTAL_CRITS)) { - critDamage = physical + magical; - } else { - critDamage = total - trueDmg; + critDamage = physical + magical; + if (mob.hasTrait(StrifeTrait.ELEMENTAL_CRITS)) { + critDamage += fire + ice + lightning + earth + light + shadow; } - float critChance = Math.max(mob.getStat(StrifeStat.CRITICAL_RATE), 0) / 100; - total += critChance * critDamage * StatUtil.getCriticalMultiplier(mob); + float critChance = Math.min(1, Math.max(mob.getStat(StrifeStat.CRITICAL_RATE), 0) / 100); + total += critChance * critDamage * critMult; } if (mob.getStat(StrifeStat.BLEED_CHANCE) > 0) { float bleedBonus = 0.5f * (1 + mob.getStat(StrifeStat.BLEED_DAMAGE) / 100); bleedBonus *= mob.getStat(StrifeStat.BLEED_CHANCE) / 100; - total += (physical + physical * criticalMult) * bleedBonus; + total += (physical + physical * (1 + critMult)) * bleedBonus; } if (mob.getStat(StrifeStat.MULTISHOT) > 0) { total *= 1 + (0.3 * (mob.getStat(StrifeStat.MULTISHOT) / 100)); @@ -149,9 +148,9 @@ public ItemStack getFinalIcon(Player commandSender) { loreSection.add(addStat("Multishot: ", mob.getStat(StrifeStat.MULTISHOT), "%", INT_FORMAT)); } } - if (mob.getStat(StrifeStat.CRITICAL_RATE) > 0) { + if (mob.getStat(StrifeStat.CRITICAL_RATE) > 0 || !mob.hasTrait(StrifeTrait.NO_CRIT_MULT)) { loreSection.add( - addStat("Critical Chance: ", mob.getStat(StrifeStat.CRITICAL_RATE), "%", INT_FORMAT)); + addStat("Critical Chance: ", Math.min(100, mob.getStat(StrifeStat.CRITICAL_RATE)), "%", INT_FORMAT)); loreSection.add( addStat("Critical Multiplier: ", StatUtil.getCriticalMultiplier(mob), "x", TWO_DECIMAL)); } diff --git a/src/main/java/land/face/strife/menus/stats/StatsOpenLevelupMenu.java b/src/main/java/land/face/strife/menus/stats/StatsOpenLevelupMenu.java index 611872e7..3d4ce9b4 100644 --- a/src/main/java/land/face/strife/menus/stats/StatsOpenLevelupMenu.java +++ b/src/main/java/land/face/strife/menus/stats/StatsOpenLevelupMenu.java @@ -81,8 +81,11 @@ public void onItemClick(ItemClickEvent event) { } event.setWillClose(true); event.setWillUpdate(false); - Bukkit.getScheduler().runTaskLater(StrifePlugin.getInstance(), () -> - plugin.getLevelupMenu().open(event.getPlayer()), 2L); + Bukkit.getScheduler().runTaskLater(StrifePlugin.getInstance(), () -> { + plugin.getChampionManager().resetPendingStats( + plugin.getChampionManager().getChampion(event.getPlayer())); + plugin.getLevelupMenu().open(event.getPlayer()); + }, 2L); } } diff --git a/src/main/java/land/face/strife/stats/StrifeStat.java b/src/main/java/land/face/strife/stats/StrifeStat.java index e5b59816..3d94d466 100644 --- a/src/main/java/land/face/strife/stats/StrifeStat.java +++ b/src/main/java/land/face/strife/stats/StrifeStat.java @@ -109,6 +109,7 @@ public enum StrifeStat { MINION_DAMAGE("Minion Damage"), MINION_LIFE("Minion Max Life"), + MINION_SPEED("Minion Move Speed"), MAX_MINIONS("Maximum Minions"), MOVEMENT_SPEED("Movement Speed"), diff --git a/src/main/java/land/face/strife/tasks/BarrierTask.java b/src/main/java/land/face/strife/tasks/BarrierTask.java index 7bb9d533..2a0454db 100644 --- a/src/main/java/land/face/strife/tasks/BarrierTask.java +++ b/src/main/java/land/face/strife/tasks/BarrierTask.java @@ -3,31 +3,36 @@ import java.lang.ref.WeakReference; import land.face.strife.StrifePlugin; import land.face.strife.data.StrifeMob; +import land.face.strife.managers.StatUpdateManager; import land.face.strife.stats.StrifeStat; import land.face.strife.stats.StrifeTrait; import land.face.strife.util.StatUtil; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.Particle; -import org.bukkit.attribute.Attribute; -import org.bukkit.attribute.AttributeModifier; import org.bukkit.block.data.BlockData; import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; import org.bukkit.scheduler.BukkitRunnable; public class BarrierTask extends BukkitRunnable { private static final long TICK_RATE = 3L; private static final int DELAY_TICKS = (int) ((float) 120 / TICK_RATE); - private static final BlockData BLOCK_DATA = Bukkit.getServer().createBlockData(Material.WHITE_STAINED_GLASS); + private static final BlockData BLOCK_DATA = Bukkit.getServer() + .createBlockData(Material.WHITE_STAINED_GLASS); private final WeakReference parentMob; private int delayTicks = 0; + private float barrierScale = 20f; public BarrierTask(StrifeMob parentMob) { this.parentMob = new WeakReference<>(parentMob); this.runTaskTimer(StrifePlugin.getInstance(), 20L, TICK_RATE); + if (parentMob.getChampion() != null) { + updateBarrierScale(); + } } @Override @@ -37,6 +42,7 @@ public void run() { cancel(); return; } + forceAbsorbHearts(); if (delayTicks > 0) { delayTicks--; return; @@ -53,23 +59,13 @@ public void run() { mob.restoreBarrier(barrierGain); } - public void bumpBarrierTime() { - delayTicks = DELAY_TICKS; - } - - public void updateArmorBar(StrifeMob mob, float currentBarrier, float maxBarrier) { - updateArmorBar(mob, currentBarrier / maxBarrier); + public void updateBarrierScale() { + barrierScale = StatUpdateManager.getBarrierScale(parentMob.get().getChampion().getSaveData() + .getHealthDisplayType(), (float) parentMob.get().getEntity().getMaxHealth(), parentMob.get().getMaxBarrier()); } - public void updateArmorBar(StrifeMob mob, float percent) { - if (!(mob.getEntity() instanceof Player)) { - return; - } - Player player = (Player) mob.getEntity(); - for (AttributeModifier mod : player.getAttribute(Attribute.GENERIC_ARMOR).getModifiers()) { - player.getAttribute(Attribute.GENERIC_ARMOR).removeModifier(mod); - } - player.getAttribute(Attribute.GENERIC_ARMOR).setBaseValue(20 * percent); + public void bumpBarrierTime() { + delayTicks = DELAY_TICKS; } public static void spawnBarrierParticles(LivingEntity entity, float amount) { @@ -84,4 +80,20 @@ public static void spawnBarrierParticles(LivingEntity entity, float amount) { ); } + public void forceAbsorbHearts() { + StrifeMob mob = parentMob.get(); + if (mob.getChampion() == null) { + return; + } + if (mob.getBarrier() > 0) { + mob.getEntity().addPotionEffect(new PotionEffect(PotionEffectType.ABSORPTION, + 99999, 50, true, false)); + float percent = Math.min(1, mob.getBarrier() / mob.getMaxBarrier()); + mob.getEntity().setAbsorptionAmount(percent * barrierScale); + } else { + mob.getEntity().setAbsorptionAmount(0); + mob.getEntity().removePotionEffect(PotionEffectType.ABSORPTION); + } + } + } diff --git a/src/main/java/land/face/strife/tasks/CombatCountdownTask.java b/src/main/java/land/face/strife/tasks/CombatCountdownTask.java index 0d528f8d..f38bf279 100644 --- a/src/main/java/land/face/strife/tasks/CombatCountdownTask.java +++ b/src/main/java/land/face/strife/tasks/CombatCountdownTask.java @@ -15,6 +15,7 @@ public class CombatCountdownTask extends BukkitRunnable { private static final int BUMP_TIME_HALF_SECONDS = 20; private final WeakReference parentMob; + private boolean pvp = false; private int halfSecondsRemaining; @@ -46,6 +47,14 @@ public void bump() { halfSecondsRemaining = BUMP_TIME_HALF_SECONDS; } + public void setPvp() { + pvp = true; + } + + public boolean isPvp() { + return pvp; + } + public static void awardSkillExp(StrifeMob mob) { Champion champion = mob.getChampion(); if (champion == null) { diff --git a/src/main/java/land/face/strife/tasks/DamageOverTimeTask.java b/src/main/java/land/face/strife/tasks/DamageOverTimeTask.java index f512306f..255e5797 100644 --- a/src/main/java/land/face/strife/tasks/DamageOverTimeTask.java +++ b/src/main/java/land/face/strife/tasks/DamageOverTimeTask.java @@ -81,6 +81,12 @@ public void trackWither(LivingEntity livingEntity) { witheredMobs.add(livingEntity); } + public void clearAllDoT(LivingEntity livingEntity) { + poisonedMobs.remove(livingEntity); + witheredMobs.remove(livingEntity); + burningMobs.remove(livingEntity); + } + @Override public void run() { dealPoisonDamage(); diff --git a/src/main/java/land/face/strife/tasks/EveryTickTask.java b/src/main/java/land/face/strife/tasks/EveryTickTask.java index dc5c332d..4e30f348 100644 --- a/src/main/java/land/face/strife/tasks/EveryTickTask.java +++ b/src/main/java/land/face/strife/tasks/EveryTickTask.java @@ -30,6 +30,7 @@ public class EveryTickTask extends BukkitRunnable { @Override public void run() { StrifePlugin.getInstance().getBlockManager().tickHolograms(); + StrifePlugin.getInstance().getBlockManager().tickBlock(); for (Player p : Bukkit.getOnlinePlayers()) { double hoverPower = JumpUtil.determineHoverPower(p); if (hoverPower > 0) { diff --git a/src/main/java/land/face/strife/tasks/MinionTask.java b/src/main/java/land/face/strife/tasks/MinionTask.java index 33f39504..baf5dd94 100644 --- a/src/main/java/land/face/strife/tasks/MinionTask.java +++ b/src/main/java/land/face/strife/tasks/MinionTask.java @@ -1,9 +1,14 @@ package land.face.strife.tasks; import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; import java.util.Objects; import land.face.strife.StrifePlugin; import land.face.strife.data.StrifeMob; +import land.face.strife.stats.StrifeStat; +import org.bukkit.entity.Mob; import org.bukkit.scheduler.BukkitRunnable; public class MinionTask extends BukkitRunnable { @@ -32,9 +37,12 @@ public void run() { cancel(); return; } - if (!mob.getEntity().getPassengers().isEmpty()) { + if (!minionMob.getEntity().getPassengers().isEmpty()) { return; } + if (((Mob) minionMob.getEntity()).getTarget() == mob.getEntity()) { + ((Mob) minionMob.getEntity()).setTarget(null); + } lifespan--; if (lifespan > 0) { return; @@ -57,4 +65,18 @@ public int getLifespan() { public void forceStartDeath() { lifespan = Math.min(0, lifespan); } + + public static void expireMinions(StrifeMob master) { + List minionList = new ArrayList<>(master.getMinions()); + + int excessMinions = minionList.size() - (int) master.getStat(StrifeStat.MAX_MINIONS); + if (excessMinions > 0) { + minionList.sort(Comparator.comparingDouble(StrifeMob::getMinionRating)); + while (excessMinions > 0) { + minionList.get(excessMinions - 1).minionDeath(); + //Bukkit.getLogger().info("commit die: " + minionList.get(excessMinions - 1).getEntity().getName()); + excessMinions--; + } + } + } } diff --git a/src/main/java/land/face/strife/timers/SoulTimer.java b/src/main/java/land/face/strife/timers/SoulTimer.java index b6ebae26..3e4aa9d7 100644 --- a/src/main/java/land/face/strife/timers/SoulTimer.java +++ b/src/main/java/land/face/strife/timers/SoulTimer.java @@ -19,16 +19,21 @@ package land.face.strife.timers; import com.gmail.filoghost.holographicdisplays.api.Hologram; +import java.util.HashMap; import java.util.HashSet; +import java.util.Map; import java.util.Set; import java.util.UUID; import land.face.strife.StrifePlugin; +import land.face.strife.data.StrifeMob; +import land.face.strife.stats.StrifeStat; import land.face.strife.util.LogUtil; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.Particle; import org.bukkit.entity.Entity; import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; import org.bukkit.scheduler.BukkitRunnable; public class SoulTimer extends BukkitRunnable { @@ -39,14 +44,30 @@ public class SoulTimer extends BukkitRunnable { private final Hologram soulHead; private final long creationTime = System.currentTimeMillis(); + private final ItemStack head; + private final ItemStack body; + private final ItemStack legs; + private final ItemStack boots; + private final ItemStack mainHand; + private final ItemStack offHand; + + private final Map statMap = new HashMap<>(); + private static int MAX_SOUL_LIFESPAN = 300000; private double lostExp = 0; - public SoulTimer(UUID owner, Hologram soulHead, Location location) { - this.owner = owner; + public SoulTimer(StrifeMob mob, Hologram soulHead, Location location) { + this.owner = mob.getEntity().getUniqueId(); this.location = location; this.soulHead = soulHead; + this.statMap.putAll(mob.getFinalStats()); + this.head = mob.getEntity().getEquipment().getHelmet(); + this.body = mob.getEntity().getEquipment().getChestplate(); + this.legs = mob.getEntity().getEquipment().getLeggings(); + this.boots = mob.getEntity().getEquipment().getBoots(); + this.mainHand = mob.getEntity().getEquipment().getItemInMainHand(); + this.offHand = mob.getEntity().getEquipment().getItemInOffHand(); LogUtil.printDebug("New SoulTimer created for " + owner); runTaskTimer(StrifePlugin.getInstance(), 0L, 20L); } @@ -57,7 +78,7 @@ public void run() { StrifePlugin.getInstance().getSoulManager().removeSoul(this); return; } - Player p = Bukkit.getPlayer(owner); + Player p = getOwner(); if (p != null && !p.isDead()) { if (!StrifePlugin.getInstance().getSoulManager().isDeathWorld(p.getWorld().getName())) { StrifePlugin.getInstance().getSoulManager().removeSoul(this); @@ -92,8 +113,8 @@ public void run() { viewers.addAll(currentViewers); } - public UUID getOwner() { - return owner; + public Player getOwner() { + return Bukkit.getPlayer(owner); } public Location getLocation() { @@ -122,4 +143,32 @@ private boolean canSeeSouls(Entity entity) { } return false; } + + public ItemStack getHead() { + return head; + } + + public ItemStack getBody() { + return body; + } + + public ItemStack getLegs() { + return legs; + } + + public ItemStack getBoots() { + return boots; + } + + public ItemStack getMainHand() { + return mainHand; + } + + public ItemStack getOffHand() { + return offHand; + } + + public Map getStatMap() { + return statMap; + } } diff --git a/src/main/java/land/face/strife/util/DamageUtil.java b/src/main/java/land/face/strife/util/DamageUtil.java index 4efc99c5..b1313e48 100644 --- a/src/main/java/land/face/strife/util/DamageUtil.java +++ b/src/main/java/land/face/strife/util/DamageUtil.java @@ -66,8 +66,8 @@ public class DamageUtil { private static StrifePlugin plugin; private static GuildsAPI guildsAPI; - private static final String ATTACK_BLOCKED = StringExtensionsKt.chatColorize("&e&lBlocked!"); - private static final String ATTACK_DODGED = StringExtensionsKt.chatColorize("&f&l&oDodge!"); + private static String ATTACK_BLOCKED; + private static String ATTACK_DODGED; public static double EVASION_THRESHOLD; private static final DamageModifier[] MODIFIERS = EntityDamageEvent.DamageModifier.values(); @@ -84,6 +84,10 @@ public static void refresh() { guildsAPI = Guilds.getApi(); EVASION_THRESHOLD = plugin.getSettings().getDouble("config.mechanics.evasion-threshold", 0.5); PVP_MULT = (float) plugin.getSettings().getDouble("config.mechanics.pvp-multiplier", 0.5); + ATTACK_BLOCKED = StringExtensionsKt.chatColorize(plugin.getSettings() + .getString("language.status.block-message", "&e&lBlocked!")); + ATTACK_DODGED = StringExtensionsKt.chatColorize(plugin.getSettings() + .getString("language.status.evade-message", "&7&l&oDodge!")); } public static void applyExtraEffects(StrifeMob attacker, StrifeMob defender, List effects) { @@ -232,13 +236,27 @@ public static float calculateFinalDamage(StrifeMob attacker, StrifeMob defender, LifeSkillType.SNEAK, gainedXp, false, false); } - String damageString = String.valueOf((int) Math.ceil(rawDamage)); + if (rawDamage < 1) { + rawDamage = 0; + } + + String damageString; if (mods.isShowPopoffs() && attacker.getEntity() instanceof Player) { - plugin.getIndicatorManager().addIndicator(attacker.getEntity(), - defender.getEntity(), IndicatorStyle.RANDOM_POPOFF, 9, ChatColor.BOLD + damageString); + if (rawDamage == 0) { + plugin.getIndicatorManager().addIndicator(attacker.getEntity(), defender.getEntity(), + IndicatorStyle.RANDOM_POPOFF, 9, ChatColor.AQUA + "0"); + } else { + damageString = String.valueOf(Math.round(rawDamage)); + if (criticalHit) { + damageString = damageString + ChatColor.RED + "✸"; + } + plugin.getIndicatorManager().addIndicator(attacker.getEntity(), defender.getEntity(), + IndicatorStyle.RANDOM_POPOFF, 9, ChatColor.BOLD + damageString); + } } if (mods.isShowPopoffs() && attacker.getMaster() != null && attacker.getMaster().getEntity() instanceof Player) { + damageString = String.valueOf(Math.round(rawDamage)); plugin.getIndicatorManager().addIndicator(attacker.getMaster().getEntity(), defender.getEntity(), IndicatorStyle.RANDOM_POPOFF, 9, "&7" + damageString); } @@ -310,13 +328,12 @@ private static boolean isCriticalHit(StrifeMob attacker, StrifeMob defender, Dam .getOrDefault(AbilityMod.CRITICAL_CHANCE, 0f)); boolean success = critChance >= rollDouble(hasLuck(attacker.getEntity())); if (success) { - DamageUtil.callCritEvent(attacker, attacker); - defender.getEntity().getWorld().playSound(defender.getEntity().getEyeLocation(), - Sound.ENTITY_GENERIC_BIG_FALL, 2f, 0.8f); - if (attacker.getEntity() instanceof Player) { - StrifePlugin.getInstance().getIndicatorManager().addIndicator(attacker.getEntity(), - defender.getEntity(), IndicatorStyle.FLOAT_UP_FAST, 3, "&c&lCRIT!"); - } + DamageUtil.callCritEvent(attacker, defender); + defender.getEntity().getWorld().playSound(defender.getEntity().getEyeLocation(), Sound.ENTITY_GENERIC_BIG_FALL, 2f, 0.75f); + //if (attacker.getEntity() instanceof Player) { + // StrifePlugin.getInstance().getIndicatorManager().addIndicator(attacker.getEntity(), + // defender.getEntity(), IndicatorStyle.FLOAT_UP_FAST, 3, "&c&lCRIT!"); + //} } return success; } @@ -429,8 +446,8 @@ public static Map buildDamageMap(StrifeMob attacker, StrifeMo return damageMap; } - public static void applyDamageReductions(StrifeMob attacker, StrifeMob defender, Map damageMap, - Map abilityMods) { + public static void applyDamageReductions(StrifeMob attacker, StrifeMob defender, + Map damageMap, Map abilityMods) { damageMap.replaceAll((t, v) -> damageMap.get(t) * getDamageReduction(t, attacker, defender, abilityMods)); } @@ -532,11 +549,11 @@ public static void applyElementalEffects(StrifeMob attacker, StrifeMob defender, break; case DARK: mods.getElementalStatuses().add(ElementalStatus.CORRUPT); - applyCorrupt(defender.getEntity(), 5 + darkDamage / 3); + applyCorrupt(defender.getEntity(), 5 + darkDamage / 3, true); break; case EARTH: mods.getElementalStatuses().add(ElementalStatus.CRUNCH); - int runes = plugin.getBlockManager().getEarthRunes(attacker.getEntity()); + int runes = plugin.getBlockManager().getEarthRunes(attacker); float maxLife = (float) attacker.getEntity().getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue(); float newDamage = damageMap.get(DamageType.EARTH) * 1.1f + (runes * 0.02f * maxLife); damageMap.put(DamageType.EARTH, newDamage); @@ -557,11 +574,17 @@ public static float getDamageReduction(DamageType type, StrifeMob attack, Strife float armor = getDefenderArmor(attack, defend); armor *= 1 - modDoubleMap.getOrDefault(AbilityMod.ARMOR_PEN_MULT, 0f); armor -= modDoubleMap.getOrDefault(AbilityMod.ARMOR_PEN, 0f); + if (modDoubleMap.containsKey(AbilityMod.BACK_ATTACK)) { + armor *= 0.8; + } return getArmorMult(armor); case MAGICAL: float warding = getDefenderWarding(attack, defend); warding *= 1 - modDoubleMap.getOrDefault(AbilityMod.WARD_PEN_MULT, 0f); warding -= modDoubleMap.getOrDefault(AbilityMod.WARD_PEN, 0f); + if (modDoubleMap.containsKey(AbilityMod.BACK_ATTACK)) { + warding *= 0.8; + } return getWardingMult(warding); case FIRE: return 1 - getFireResist(defend, attack.hasTrait(StrifeTrait.SOUL_FLAME)) / 100; @@ -678,6 +701,10 @@ public static float getFullEvasionMult(StrifeMob attacker, StrifeMob defender, M totalAccuracy *= 1 + mods.getOrDefault(AbilityMod.ACCURACY_MULT, 0f) / 100; totalAccuracy += mods.getOrDefault(AbilityMod.ACCURACY, 0f); + if (mods.containsKey(AbilityMod.BACK_ATTACK)) { + totalEvasion *= 0.8; + } + float evasionMultiplier = StatUtil.getMinimumEvasionMult(totalEvasion, totalAccuracy); evasionMultiplier = evasionMultiplier + (rollDouble() * (1 - evasionMultiplier)); @@ -694,7 +721,7 @@ public static void doEvasion(StrifeMob attacker, StrifeMob defender) { defender.getEntity().getWorld() .playSound(defender.getEntity().getEyeLocation(), Sound.ENTITY_GHAST_SHOOT, 0.5f, 2f); if (defender.getEntity() instanceof Player) { - AdvancedActionBarUtil.addMessage((Player) defender.getEntity(), "combat-status", ATTACK_DODGED, 30, 100); + AdvancedActionBarUtil.addMessage((Player) defender.getEntity(), "COMBAT-EVENTs", ATTACK_DODGED, 10, 100); } if (attacker.getEntity() instanceof Player) { StrifePlugin.getInstance().getIndicatorManager() @@ -706,11 +733,11 @@ public static void doBlock(StrifeMob attacker, StrifeMob defender) { callBlockEvent(defender, attacker); defender.getEntity().getWorld().playSound(defender.getEntity().getEyeLocation(), Sound.ITEM_SHIELD_BLOCK, 1f, 1f); if (defender.getEntity() instanceof Player) { - AdvancedActionBarUtil.addMessage((Player) defender.getEntity(), "combat-status", ATTACK_BLOCKED, 30, 100); + AdvancedActionBarUtil.addMessage((Player) defender.getEntity(), "COMBAT-EVENT", ATTACK_BLOCKED, 10, 100); } if (attacker.getEntity() instanceof Player) { - StrifePlugin.getInstance().getIndicatorManager().addIndicator(attacker.getEntity(), defender.getEntity(), - IndicatorStyle.BOUNCE, 6, "&e&lBlocked!"); + plugin.getIndicatorManager().addIndicator(attacker.getEntity(), defender.getEntity(), + IndicatorStyle.RANDOM_POPOFF, 7, "&e⛨&lBlock"); } } @@ -800,9 +827,11 @@ public static void applyBleed(StrifeMob defender, float amount, boolean bypassBa .playSound(defender.getEntity().getLocation(), Sound.ENTITY_SHEEP_SHEAR, 1f, 1f); } - public static void applyCorrupt(LivingEntity defender, float amount) { + public static void applyCorrupt(LivingEntity defender, float amount, boolean silent) { StrifePlugin.getInstance().getCorruptionManager().applyCorruption(defender, amount); - defender.getWorld().playSound(defender.getEyeLocation(), Sound.ENTITY_WITHER_SHOOT, 0.7f, 2f); + if (!silent) { + defender.getWorld().playSound(defender.getEyeLocation(), Sound.ENTITY_WITHER_SHOOT, 0.7f, 2f); + } defender.getWorld().spawnParticle(Particle.SMOKE_NORMAL, defender.getEyeLocation(), 10, 0.4, 0.4, 0.5, 0.1); } @@ -812,8 +841,11 @@ public static void doReflectedDamage(StrifeMob defender, StrifeMob attacker, if (defender.getStat(StrifeStat.DAMAGE_REFLECT) < 0.1) { return; } - double reflectDamage = defender.getStat(StrifeStat.DAMAGE_REFLECT); - reflectDamage = damageType == AttackType.MELEE ? reflectDamage : reflectDamage * 0.6D; + if (!attacker.getEntity().isValid()) { + return; + } + float reflectDamage = defender.getStat(StrifeStat.DAMAGE_REFLECT); + reflectDamage = damageType == AttackType.MELEE ? reflectDamage : reflectDamage * 0.6f; defender.getEntity().getWorld().playSound(defender.getEntity().getLocation(), Sound.BLOCK_LANTERN_STEP, SoundCategory.HOSTILE, 1f, 1.5f); if (attacker.getEntity() instanceof Player) { @@ -821,6 +853,9 @@ public static void doReflectedDamage(StrifeMob defender, StrifeMob attacker, TargetingUtil.getOriginLocation(attacker.getEntity(), OriginLocation.CENTER), (int) reflectDamage, 0.3, 0.3, 0.3, 0.1); } + if (defender.getEntity() instanceof Player) { + attacker.flagPvp(); + } attacker.getEntity().setHealth(Math.max(0D, attacker.getEntity().getHealth() - reflectDamage)); } @@ -988,7 +1023,8 @@ public enum AbilityMod { HEALTH_ON_HIT, BLEED_CHANCE, BLEED_DAMAGE, - STATUS_CHANCE + STATUS_CHANCE, + BACK_ATTACK } public enum AttackType { diff --git a/src/main/java/land/face/strife/util/ItemUtil.java b/src/main/java/land/face/strife/util/ItemUtil.java index 7e96f3ce..fad55bd3 100644 --- a/src/main/java/land/face/strife/util/ItemUtil.java +++ b/src/main/java/land/face/strife/util/ItemUtil.java @@ -86,6 +86,17 @@ public static boolean isMeleeWeapon(Material material) { } } + public static boolean isTool(ItemStack stack) { + String material = stack.getType().toString(); + if (stack.getType() == Material.FISHING_ROD || stack.getType() == Material.SHEARS + || material.endsWith("_PICKAXE") || material.endsWith("_HOE") || material.endsWith("_AXE") + || material.endsWith("_SHOVEL")) { + int modelData = getCustomData(stack); + return modelData < 8000; + } + return false; + } + public static boolean isDualWield(EntityEquipment equipment) { return isMeleeWeapon(equipment.getItemInMainHand().getType()) && isMeleeWeapon( equipment.getItemInOffHand().getType()); @@ -97,6 +108,9 @@ public static boolean isValidOffhand(EntityEquipment entityEquipment) { if (mainItem.getType() == Material.AIR || offItem.getType() == Material.AIR) { return true; } + if (isTool(mainItem)) { + return false; + } if (isMeleeWeapon(mainItem.getType())) { if (isMeleeWeapon(offItem.getType())) { return true; diff --git a/src/main/java/land/face/strife/util/ProjectileUtil.java b/src/main/java/land/face/strife/util/ProjectileUtil.java index 4010189e..e363a541 100644 --- a/src/main/java/land/face/strife/util/ProjectileUtil.java +++ b/src/main/java/land/face/strife/util/ProjectileUtil.java @@ -142,12 +142,6 @@ public static void createArrow(LivingEntity shooter, double attackMult, float po setPierce(arrow, pierceChance); setAttackMult(arrow, (float) attackMult); setShotId(arrow); - - if (shooter instanceof Player) { - if (attackMult > 0.95) { - arrow.setCritical(true); - } - } } public static void createMagicMissile(LivingEntity shooter, double attackMult, float power, diff --git a/src/main/java/land/face/strife/util/TargetingUtil.java b/src/main/java/land/face/strife/util/TargetingUtil.java index 16a79dc7..549cd623 100644 --- a/src/main/java/land/face/strife/util/TargetingUtil.java +++ b/src/main/java/land/face/strife/util/TargetingUtil.java @@ -48,7 +48,7 @@ public static void expandMobRange(LivingEntity attacker, LivingEntity victim) { return; } AttributeInstance attr = victim.getAttribute(GENERIC_FOLLOW_RANGE); - double newVal = Math.max(Math.max(attr.getBaseValue(), attr.getDefaultValue()), 32); + double newVal = Math.max(Math.max(attr.getBaseValue(), attr.getDefaultValue()), 80); victim.getAttribute(GENERIC_FOLLOW_RANGE).setBaseValue(newVal); LivingEntity target = ((Mob) victim).getTarget(); @@ -146,14 +146,12 @@ public static boolean isFriendly(StrifeMob attacker, StrifeMob defender) { if (defender.getMaster() != null) { return isFriendly(attacker, defender.getMaster()); } + if (attacker.getMaster() == defender || attacker.getMinions().contains(defender)) { + return true; + } if (attacker.getEntity() instanceof Player && defender.getEntity() instanceof Player) { return !DamageUtil.canAttack((Player) attacker.getEntity(), (Player) defender.getEntity()); } - for (StrifeMob mob : attacker.getMinions()) { - if (defender.getEntity() == mob.getEntity()) { - return true; - } - } return false; }