Implement strength and agility scaling
This commit is contained in:
@@ -16,6 +16,8 @@ import net.minecraftforge.event.entity.player.PlayerInteractEvent;
|
|||||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||||
import net.minecraftforge.fml.common.Mod;
|
import net.minecraftforge.fml.common.Mod;
|
||||||
import net.minecraftforge.event.level.BlockEvent;
|
import net.minecraftforge.event.level.BlockEvent;
|
||||||
|
import net.minecraftforge.event.entity.living.LivingDamageEvent;
|
||||||
|
import net.minecraft.world.entity.LivingEntity;
|
||||||
|
|
||||||
@Mod.EventBusSubscriber(modid = AscendMod.MODID)
|
@Mod.EventBusSubscriber(modid = AscendMod.MODID)
|
||||||
public class ActivityEvents {
|
public class ActivityEvents {
|
||||||
@@ -54,7 +56,7 @@ public class ActivityEvents {
|
|||||||
public static void onPlayerDamaged(LivingHurtEvent event) {
|
public static void onPlayerDamaged(LivingHurtEvent event) {
|
||||||
if (event.getEntity() instanceof Player player && !player.level().isClientSide) {
|
if (event.getEntity() instanceof Player player && !player.level().isClientSide) {
|
||||||
player.getCapability(PlayerStatsProvider.PLAYER_STATS).ifPresent(stats -> {
|
player.getCapability(PlayerStatsProvider.PLAYER_STATS).ifPresent(stats -> {
|
||||||
int gain = Math.min((int) event.getAmount() * 2, 10);
|
int gain = Math.min((int) event.getAmount() / 2, 10);
|
||||||
stats.addAscendXP(gain);
|
stats.addAscendXP(gain);
|
||||||
PlayerStatsProvider.sync(player);
|
PlayerStatsProvider.sync(player);
|
||||||
});
|
});
|
||||||
@@ -203,4 +205,22 @@ public class ActivityEvents {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public static void onPlayerDealsDamage(LivingDamageEvent event) {
|
||||||
|
if (!(event.getSource().getEntity() instanceof Player player)) return;
|
||||||
|
if (player.level().isClientSide) return;
|
||||||
|
LivingEntity target = event.getEntity();
|
||||||
|
player.getCapability(PlayerStatsProvider.PLAYER_STATS).ifPresent(stats -> {
|
||||||
|
int strength = stats.getAttributeLevel("strength");
|
||||||
|
if (strength <= 0) return;
|
||||||
|
float bypassFraction = Math.min(strength * 0.001f, 0.30f);
|
||||||
|
int armor = target.getArmorValue();
|
||||||
|
if (armor <= 0 || bypassFraction <= 0f) return;
|
||||||
|
float baseDamage = event.getAmount();
|
||||||
|
float armorFactor = (float) armor / (armor + 100.0f);
|
||||||
|
float bonus = baseDamage * armorFactor * bypassFraction;
|
||||||
|
event.setAmount(baseDamage + bonus);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -2,6 +2,7 @@ package net.fretux.ascend.event;
|
|||||||
|
|
||||||
import net.fretux.ascend.AscendMod;
|
import net.fretux.ascend.AscendMod;
|
||||||
import net.fretux.ascend.player.PlayerStatsProvider;
|
import net.fretux.ascend.player.PlayerStatsProvider;
|
||||||
|
import net.fretux.ascend.player.StatEffects;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.world.entity.Entity;
|
import net.minecraft.world.entity.Entity;
|
||||||
import net.minecraft.world.entity.player.Player;
|
import net.minecraft.world.entity.player.Player;
|
||||||
@@ -27,15 +28,19 @@ public class PlayerEvents {
|
|||||||
public static void onPlayerClone(PlayerEvent.Clone event) {
|
public static void onPlayerClone(PlayerEvent.Clone event) {
|
||||||
event.getOriginal().reviveCaps();
|
event.getOriginal().reviveCaps();
|
||||||
event.getOriginal().getCapability(PlayerStatsProvider.PLAYER_STATS).ifPresent(oldStats ->
|
event.getOriginal().getCapability(PlayerStatsProvider.PLAYER_STATS).ifPresent(oldStats ->
|
||||||
event.getEntity().getCapability(PlayerStatsProvider.PLAYER_STATS).ifPresent(newStats ->
|
event.getEntity().getCapability(PlayerStatsProvider.PLAYER_STATS).ifPresent(newStats -> {
|
||||||
newStats.deserializeNBT(oldStats.serializeNBT())));
|
newStats.deserializeNBT(oldStats.serializeNBT());
|
||||||
|
StatEffects.applyAll(event.getEntity());
|
||||||
|
})
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Optional but very helpful: sync on login so client sees initial 15 points
|
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
public static void onPlayerLogin(PlayerEvent.PlayerLoggedInEvent event) {
|
public static void onPlayerLogin(PlayerEvent.PlayerLoggedInEvent event) {
|
||||||
if (!event.getEntity().level().isClientSide) {
|
if (!event.getEntity().level().isClientSide) {
|
||||||
PlayerStatsProvider.sync(event.getEntity());
|
PlayerStatsProvider.sync(event.getEntity());
|
||||||
|
StatEffects.applyAll(event.getEntity());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package net.fretux.ascend.network;
|
package net.fretux.ascend.network;
|
||||||
|
|
||||||
|
import net.fretux.ascend.player.StatEffects;
|
||||||
import net.minecraft.network.FriendlyByteBuf;
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
import net.minecraft.network.chat.Component;
|
import net.minecraft.network.chat.Component;
|
||||||
import net.minecraft.server.level.ServerPlayer;
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
@@ -50,8 +51,29 @@ public class ServerboundSpendPointPacket {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
player.getCapability(PlayerStatsProvider.PLAYER_STATS).ifPresent(stats -> {
|
||||||
|
boolean success = stats.spendPoints(attribute);
|
||||||
|
if (success) {
|
||||||
|
if ("strength".equals(attribute)) {
|
||||||
|
StatEffects.applyStrength(player, stats.getAttributeLevel("strength"));
|
||||||
|
}
|
||||||
|
|
||||||
|
player.sendSystemMessage(Component.literal("You increased " + attribute + "!"));
|
||||||
|
CompoundTag data = stats.serializeNBT();
|
||||||
|
PacketHandler.INSTANCE.send(
|
||||||
|
PacketDistributor.PLAYER.with(() -> player),
|
||||||
|
new ClientboundSyncStatsPacket(data)
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
int level = stats.getAttributeLevel(attribute);
|
||||||
|
int cost = stats.getCostToUpgrade(attribute);
|
||||||
|
int have = stats.getUnspentPoints();
|
||||||
|
player.sendSystemMessage(Component.literal(
|
||||||
|
"Not enough points (" + have + "/" + cost + ") to increase " + attribute + " (lvl " + level + ")."
|
||||||
|
));
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
ctx.get().setPacketHandled(true);
|
ctx.get().setPacketHandled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -12,6 +12,7 @@ public class PlayerStats {
|
|||||||
private int ascendLevel = 1;
|
private int ascendLevel = 1;
|
||||||
private int ascendXP = 0;
|
private int ascendXP = 0;
|
||||||
private int unspentPoints = POINTS_PER_LEVEL;
|
private int unspentPoints = POINTS_PER_LEVEL;
|
||||||
|
public static final int MAX_ATTRIBUTE_POINTS = 100;
|
||||||
public PlayerStats() {
|
public PlayerStats() {
|
||||||
for (String attr : new String[]{
|
for (String attr : new String[]{
|
||||||
"strength", "agility", "fortitude", "intelligence",
|
"strength", "agility", "fortitude", "intelligence",
|
||||||
@@ -61,10 +62,16 @@ public class PlayerStats {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean spendPoints(String attribute) {
|
public boolean spendPoints(String attribute) {
|
||||||
if (unspentPoints <= 0) return false;
|
|
||||||
if (!attributes.containsKey(attribute)) return false;
|
if (!attributes.containsKey(attribute)) return false;
|
||||||
attributes.put(attribute, attributes.get(attribute) + 1);
|
int level = attributes.get(attribute);
|
||||||
unspentPoints--;
|
if (level >= MAX_ATTRIBUTE_POINTS) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (unspentPoints <= 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
unspentPoints -= 1;
|
||||||
|
attributes.put(attribute, level + 1);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,7 +84,9 @@ public class PlayerStats {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setAttributeLevel(String attribute, int level) {
|
public void setAttributeLevel(String attribute, int level) {
|
||||||
attributes.put(attribute, level);
|
if (!attributes.containsKey(attribute)) return;
|
||||||
|
int clamped = Math.max(0, Math.min(level, MAX_ATTRIBUTE_POINTS));
|
||||||
|
attributes.put(attribute, clamped);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CompoundTag serializeNBT() {
|
public CompoundTag serializeNBT() {
|
||||||
@@ -104,9 +113,8 @@ public class PlayerStats {
|
|||||||
if (tag.contains("Attributes")) {
|
if (tag.contains("Attributes")) {
|
||||||
CompoundTag attrTag = tag.getCompound("Attributes");
|
CompoundTag attrTag = tag.getCompound("Attributes");
|
||||||
for (String key : attributes.keySet()) {
|
for (String key : attributes.keySet()) {
|
||||||
if (attrTag.contains(key)) {
|
int loaded = attrTag.getInt(key);
|
||||||
attributes.put(key, attrTag.getInt(key));
|
attributes.put(key, Math.max(0, Math.min(loaded, MAX_ATTRIBUTE_POINTS)));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,96 @@
|
|||||||
|
package net.fretux.ascend.player;
|
||||||
|
|
||||||
|
import net.minecraft.world.entity.player.Player;
|
||||||
|
import net.minecraft.world.entity.ai.attributes.AttributeInstance;
|
||||||
|
import net.minecraft.world.entity.ai.attributes.AttributeModifier;
|
||||||
|
import net.minecraft.world.entity.ai.attributes.Attributes;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public final class StatEffects {
|
||||||
|
|
||||||
|
// ===== Strength UUIDs =====
|
||||||
|
private static final UUID STRENGTH_DAMAGE_UUID =
|
||||||
|
UUID.fromString("a7b8b2c3-9b0d-4e1a-8ee3-21f6a7b2c3d4");
|
||||||
|
private static final UUID STRENGTH_KNOCKBACK_UUID =
|
||||||
|
UUID.fromString("b17f0d74-9cd9-4f90-9ec8-6a1046e2f912");
|
||||||
|
private static final UUID AGILITY_SPEED_UUID =
|
||||||
|
UUID.fromString("c12e9b6f-1d79-4a49-b57f-7f563c10aa11");
|
||||||
|
private static final UUID AGILITY_STEALTH_UUID =
|
||||||
|
UUID.fromString("d4e8a9f2-3b5c-4d0a-9f11-8acb3f0b77e2");
|
||||||
|
|
||||||
|
private StatEffects() {}
|
||||||
|
|
||||||
|
public static void applyAll(Player player) {
|
||||||
|
player.getCapability(PlayerStatsProvider.PLAYER_STATS).ifPresent(stats -> {
|
||||||
|
applyStrength(player, stats.getAttributeLevel("strength"));
|
||||||
|
applyAgility(player, stats.getAttributeLevel("agility"));
|
||||||
|
// later: fortitude, etc.
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void applyStrength(Player player, int strengthLevel) {
|
||||||
|
AttributeInstance atk = player.getAttribute(Attributes.ATTACK_DAMAGE);
|
||||||
|
if (atk != null) {
|
||||||
|
atk.removeModifier(STRENGTH_DAMAGE_UUID);
|
||||||
|
if (strengthLevel > 0) {
|
||||||
|
double dmgBonus = strengthLevel * 0.1d;
|
||||||
|
atk.addTransientModifier(new AttributeModifier(
|
||||||
|
STRENGTH_DAMAGE_UUID,
|
||||||
|
"Ascend Strength damage bonus",
|
||||||
|
dmgBonus,
|
||||||
|
AttributeModifier.Operation.ADDITION
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AttributeInstance kb = player.getAttribute(Attributes.ATTACK_KNOCKBACK);
|
||||||
|
if (kb != null) {
|
||||||
|
kb.removeModifier(STRENGTH_KNOCKBACK_UUID);
|
||||||
|
if (strengthLevel > 0) {
|
||||||
|
double kbBonus = strengthLevel * 0.03d;
|
||||||
|
kb.addTransientModifier(new AttributeModifier(
|
||||||
|
STRENGTH_KNOCKBACK_UUID,
|
||||||
|
"Ascend Strength knockback bonus",
|
||||||
|
kbBonus,
|
||||||
|
AttributeModifier.Operation.ADDITION
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void applyAgility(Player player, int agilityLevel) {
|
||||||
|
AttributeInstance move = player.getAttribute(Attributes.MOVEMENT_SPEED);
|
||||||
|
if (move != null) {
|
||||||
|
move.removeModifier(AGILITY_SPEED_UUID);
|
||||||
|
if (agilityLevel > 0) {
|
||||||
|
double speedBonus = agilityLevel * 0.0005d;
|
||||||
|
move.addTransientModifier(new AttributeModifier(
|
||||||
|
AGILITY_SPEED_UUID,
|
||||||
|
"Ascend Agility speed bonus",
|
||||||
|
speedBonus,
|
||||||
|
AttributeModifier.Operation.ADDITION
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AttributeInstance follow = player.getAttribute(Attributes.FOLLOW_RANGE);
|
||||||
|
if (follow != null) {
|
||||||
|
follow.removeModifier(AGILITY_STEALTH_UUID);
|
||||||
|
if (agilityLevel > 0) {
|
||||||
|
double perPoint = 0.003d;
|
||||||
|
double maxReduction = 0.5d;
|
||||||
|
double reduction = Math.min(agilityLevel * perPoint, maxReduction);
|
||||||
|
|
||||||
|
if (reduction > 0.0d) {
|
||||||
|
double multiplier = 1.0d - reduction;
|
||||||
|
follow.addTransientModifier(new AttributeModifier(
|
||||||
|
AGILITY_STEALTH_UUID,
|
||||||
|
"Ascend Agility stealth bonus",
|
||||||
|
multiplier - 1.0d,
|
||||||
|
AttributeModifier.Operation.MULTIPLY_TOTAL
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user