Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public enum ItemStatistic {
BONUS_ATTACK_SPEED("Bonus Attack Speed", NamedTextColor.RED, NamedTextColor.YELLOW, true, PackSprite.STAT_ATTACK_SPEED, 100D),
ABILITY_DAMAGE("Ability Damage", NamedTextColor.RED, NamedTextColor.RED, true, PackSprite.STAT_ABILITY_DAMAGE, 0D, 1D, null, false),
TRUE_DEFENSE("True Defense", NamedTextColor.GREEN, NamedTextColor.WHITE, false, PackSprite.STAT_TRUE_DEFENSE),
FEROCITY("Ferocity", NamedTextColor.GREEN, NamedTextColor.RED, false, PackSprite.STAT_FEROCITY),
FEROCITY("Ferocity", NamedTextColor.GREEN, NamedTextColor.RED, false, PackSprite.STAT_FEROCITY, 500D),
HEALTH_REGENERATION("Health Regen", NamedTextColor.GREEN, NamedTextColor.RED,
false, PackSprite.STAT_HEALTH_REGEN, 100D, 1D),
VITALITY("Vitality", NamedTextColor.GREEN, NamedTextColor.DARK_RED,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package net.swofty.type.skyblockgeneric.event.actions.player.mobdamage;

import net.minestom.server.entity.damage.Damage;
import net.minestom.server.entity.damage.DamageType;
import net.minestom.server.event.entity.projectile.ProjectileCollideWithEntityEvent;
import net.swofty.commons.skyblock.statistics.ItemStatistic;
import net.swofty.commons.skyblock.statistics.ItemStatistics;
Expand All @@ -15,7 +13,7 @@
import net.swofty.type.skyblockgeneric.item.SkyBlockItem;
import net.swofty.type.skyblockgeneric.user.SkyBlockPlayer;
import net.swofty.type.skyblockgeneric.user.statistics.PlayerStatistics;
import net.swofty.type.skyblockgeneric.utility.DamageIndicator;
import net.swofty.type.skyblockgeneric.utility.AttackService;

import java.util.Map;

Expand Down Expand Up @@ -43,33 +41,16 @@ public void run(ProjectileCollideWithEntityEvent event) {
ItemStatistics playerStats = shooter.getStatistics().allStatistics();

// Add the arrow's statistics to the player's statistics
ItemStatistics.add(playerStats, arrowItem.getAttributeHandler().getStatistics());
playerStats = ItemStatistics.add(playerStats, arrowItem.getAttributeHandler().getStatistics());

Map.Entry<Double, Boolean> hit = PlayerStatistics.runPrimaryDamageFormula(playerStats, entityStats);
double damage = hit.getKey() * AttributeEffectService.outgoingDamageMultiplier(shooter.getHuntingData(), collidedWith, true);
boolean critical = hit.getValue();

new DamageIndicator()
.damage((float) damage)
.pos(collidedWith.getPosition())
.critical(critical)
.display(collidedWith.getInstance());
float damageAmount = (float) damage;
if (!AttackService.applyHit(shooter, collidedWith, damageAmount, critical)) return;

collidedWith.damage(new Damage(DamageType.PLAYER_ATTACK, player, player, player.getPosition(), (float) damage));

double ferocity = shooter.getStatistics().allStatistics().getOverall(ItemStatistic.FEROCITY);

int extraAttacks = (int) (ferocity / 100);
double extraAttackChance = (ferocity % 100) / 100.0;

// Extra attacks that are guaranteed because ferocity overflowed 100
for (int i = 0; i < extraAttacks; i++) {
collidedWith.damage(new Damage(DamageType.PLAYER_ATTACK, player, player, player.getPosition(), (float) damage));
}

// Extra attacks that have a chance to occur based on the remaining ferocity
if (Math.random() < extraAttackChance) {
collidedWith.damage(new Damage(DamageType.PLAYER_ATTACK, player, player, player.getPosition(), (float) damage));
}
double ferocity = playerStats.getOverall(ItemStatistic.FEROCITY);
AttackService.scheduleExtraHits(shooter, collidedWith, damageAmount, critical, ferocity);
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
package net.swofty.type.skyblockgeneric.event.actions.player.mobdamage;

import net.kyori.adventure.key.Key;
import net.kyori.adventure.sound.Sound;
import net.minestom.server.entity.Entity;
import net.minestom.server.entity.EntityType;
import net.minestom.server.entity.LivingEntity;
import net.minestom.server.entity.damage.Damage;
import net.minestom.server.entity.damage.DamageType;
import net.minestom.server.event.entity.EntityAttackEvent;
import net.swofty.commons.skyblock.statistics.ItemStatistic;
import net.swofty.commons.skyblock.statistics.ItemStatistics;
Expand All @@ -25,15 +21,13 @@
import net.swofty.type.skyblockgeneric.item.components.ItemRequirementsComponent;
import net.swofty.type.skyblockgeneric.item.updater.PlayerItemOrigin;
import net.swofty.type.skyblockgeneric.user.SkyBlockPlayer;
import net.swofty.type.skyblockgeneric.utility.DamageIndicator;
import net.swofty.type.skyblockgeneric.utility.AttackService;

import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.UUID;

public class PlayerActionDamageMob implements HypixelEventClass {
private static final Random random = new Random();
private static final Map<UUID, Long> COOLDOWN = new HashMap<>();

@PhasedEvent(node = EventNodes.ALL, requireDataLoaded = false, phase = EventPhase.GAMEPLAY)
Expand All @@ -52,8 +46,6 @@ public void run(EntityAttackEvent event) {
else return;
LivingEntity targetLivingEntity = (LivingEntity) targetEntity;

player.playSound(Sound.sound(Key.key("entity." + mob.getEntityType().name().toLowerCase().replace("minecraft:", "") + ".hurt"), Sound.Source.PLAYER, 1f, 1f), Sound.Emitter.self());

ItemStatistics entityStats = mob.getStatistics();
Map.Entry<Double, Boolean> hit = player.getStatistics().runPrimaryDamageFormula(entityStats, player, targetLivingEntity);

Expand All @@ -69,31 +61,16 @@ public void run(EntityAttackEvent event) {
COOLDOWN.put(player.getUuid(), System.currentTimeMillis() +
MathUtility.ticksToMilliseconds(player.getStatistics().getInvulnerabilityTime()));

new DamageIndicator()
.damage((float) valueEvent.getValue())
.pos(targetEntity.getPosition())
.critical(critical)
.display(targetEntity.getInstance());

targetLivingEntity.damage(new Damage(DamageType.PLAYER_ATTACK, player, player, player.getPosition(), (float) valueEvent.getValue()));
float damageAmount = ((Number) valueEvent.getValue()).floatValue();
if (!AttackService.applyHit(player, mob, damageAmount, critical)) return;

double ferocity = player.getStatistics().allStatistics().getOverall(ItemStatistic.FEROCITY);
int extraAttacks = (int) (ferocity / 100);
double extraAttackChance = (ferocity % 100) / 100.0;

// Extra attacks that are guaranteed because ferocity overflowed 100
for (int i = 0; i < extraAttacks; i++) {
targetLivingEntity.damage(new Damage(DamageType.PLAYER_ATTACK, player, player, player.getPosition(), (float) valueEvent.getValue()));
}

// Extra attacks that have a chance to occur based on the remaining ferocity
if (random.nextDouble() < extraAttackChance) {
targetLivingEntity.damage(new Damage(DamageType.PLAYER_ATTACK, player, player, player.getPosition(), (float) valueEvent.getValue()));
}
if (player.getPosition().distance(mob.getPosition()) <= AttackService.MAX_MELEE_FEROCITY_DISTANCE)
AttackService.scheduleExtraHits(player, mob, damageAmount, critical, ferocity);

// Handle damage event enchantments
SkyBlockItem mainHandItem = PlayerItemOrigin.getFromCache(player.getUuid()).get(PlayerItemOrigin.MAIN_HAND);
double damageValue = ((Number) valueEvent.getValue()).doubleValue();
double damageValue = damageAmount;

for (SkyBlockEnchantment enchantment : mainHandItem.getAttributeHandler().getEnchantments().toList()) {
if (enchantment.type().getEnch() instanceof DamageEventEnchant damageEventEnchant) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package net.swofty.type.skyblockgeneric.utility;

import net.kyori.adventure.key.Key;
import net.kyori.adventure.sound.Sound;
import net.minestom.server.MinecraftServer;
import net.minestom.server.coordinate.Pos;
import net.minestom.server.entity.damage.Damage;
import net.minestom.server.entity.damage.DamageType;
import net.minestom.server.instance.Instance;
import net.minestom.server.timer.TaskSchedule;
import net.swofty.type.skyblockgeneric.entity.mob.SkyBlockMob;
import net.swofty.type.skyblockgeneric.user.SkyBlockPlayer;

import java.util.Locale;
import java.util.concurrent.ThreadLocalRandom;

public final class AttackService {
public static final int EXTRA_HIT_DELAY_TICKS = 5;
public static final double MAX_MELEE_FEROCITY_DISTANCE = 6D;
public static final double MAX_FEROCITY = 500D;

private AttackService() {
}

public static boolean applyHit(SkyBlockPlayer attacker, SkyBlockMob target, float damage, boolean critical) {
if (target.isRemoved() || target.isDead()) return false;

Instance instance = target.getInstance();
Pos position = target.getPosition();
boolean applied = target.damage(new Damage(
DamageType.PLAYER_ATTACK,
attacker,
attacker,
attacker.getPosition(),
damage
));
if (!applied) return false;

String entityName = target.getEntityType().name().toLowerCase(Locale.ROOT).replace("minecraft:", "");
attacker.playSound(
Sound.sound(Key.key("entity." + entityName + ".hurt"), Sound.Source.PLAYER, 1f, 1f),
Sound.Emitter.self()
);
if (instance != null) {
new DamageIndicator()
.damage(damage)
.pos(position)
.critical(critical)
.display(instance);
}
return true;
}

public static void scheduleExtraHits(SkyBlockPlayer attacker, SkyBlockMob target,
float damage, boolean critical, double ferocity) {
double effectiveFerocity = Math.max(0D, Math.min(MAX_FEROCITY, ferocity));
int extraHits = calculateExtraHits(effectiveFerocity, ThreadLocalRandom.current().nextDouble(100D));

for (int hit = 0; hit < extraHits; hit++) {
int delay = EXTRA_HIT_DELAY_TICKS * (hit + 1);
MinecraftServer.getSchedulerManager().scheduleTask(
() -> applyHit(attacker, target, damage, critical),
TaskSchedule.tick(delay),
TaskSchedule.stop()
);
}
}

static int calculateExtraHits(double ferocity, double chanceRoll) {
double effectiveFerocity = Math.max(0D, Math.min(MAX_FEROCITY, ferocity));
int extraHits = (int) (effectiveFerocity / 100D);
double remainingChance = effectiveFerocity % 100D;
if (remainingChance > 0D && chanceRoll < remainingChance) {
extraHits++;
}
return extraHits;
}
}
Loading