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;
}