the effect full suite
This commit is contained in:
@@ -53,3 +53,12 @@ Dedicated-server runtime verification remains a later test step; this iteration
|
|||||||
- After a successful build, the script can commit and push the repository.
|
- After a successful build, the script can commit and push the repository.
|
||||||
- Git push retries automatically up to three times per round; after three failures the user can choose another three-attempt round or stop.
|
- Git push retries automatically up to three times per round; after three failures the user can choose another three-attempt round or stop.
|
||||||
- Added `.gitignore` for Gradle caches, build output, Loom runtime files, IDE metadata, and logs so Git integration does not stage generated files.
|
- Added `.gitignore` for Gradle caches, build output, Loom runtime files, IDE metadata, and logs so Git integration does not stage generated files.
|
||||||
|
|
||||||
|
## 0.9.0-alpha - Full-set armor effects
|
||||||
|
|
||||||
|
- Attacker full set: `Better Armor` effect icon, +15 armor toughness, +0.25 knockback resistance.
|
||||||
|
- Scout full set: `Lightweight` effect icon, +0.025 movement speed.
|
||||||
|
- Defender full set: `Heavy Armor` effect icon, -0.02 movement speed, and final health damage reduced to 85%.
|
||||||
|
- Medical full set: `Self-Healing Device` ready effect; below 30% health triggers Regeneration IV for 5 seconds and a 30-second self-healing cooldown.
|
||||||
|
- Reused the original mod's mob-effect icons (`tough`, `heavy_armor`, `light_leg`, `rescue`, `rescue_cooldown`).
|
||||||
|
- Full-set logic runs server-side so it can later be tested on a dedicated Fabric server as well as integrated singleplayer.
|
||||||
|
|||||||
+1
-1
@@ -8,6 +8,6 @@ loom_version=1.17-SNAPSHOT
|
|||||||
fabric_api_version=0.158.0+26.2
|
fabric_api_version=0.158.0+26.2
|
||||||
geckolib_version=5.5.4
|
geckolib_version=5.5.4
|
||||||
|
|
||||||
mod_version=0.8.0-alpha
|
mod_version=0.9.0-alpha
|
||||||
maven_group=me.xjqsh
|
maven_group=me.xjqsh
|
||||||
archives_base_name=lrarmor
|
archives_base_name=lrarmor
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package me.xjqsh.lesraisinsarmor;
|
package me.xjqsh.lesraisinsarmor;
|
||||||
|
|
||||||
import me.xjqsh.lesraisinsarmor.init.ModItems;
|
import me.xjqsh.lesraisinsarmor.init.ModItems;
|
||||||
|
import me.xjqsh.lesraisinsarmor.effect.ModEffects;
|
||||||
|
import me.xjqsh.lesraisinsarmor.gameplay.ArmorSetEffects;
|
||||||
import net.fabricmc.api.ModInitializer;
|
import net.fabricmc.api.ModInitializer;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -11,7 +13,9 @@ public final class LesRaisinsArmor implements ModInitializer {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onInitialize() {
|
public void onInitialize() {
|
||||||
|
ModEffects.initialize();
|
||||||
ModItems.initialize();
|
ModItems.initialize();
|
||||||
|
ArmorSetEffects.initialize();
|
||||||
LOGGER.info("LesRaisinsArmor Fabric 26.2 port initialized ({} armor pieces).", ModItems.ARMOR_ITEMS.size());
|
LOGGER.info("LesRaisinsArmor Fabric 26.2 port initialized ({} armor pieces).", ModItems.ARMOR_ITEMS.size());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,53 @@
|
|||||||
|
package me.xjqsh.lesraisinsarmor.effect;
|
||||||
|
|
||||||
|
import me.xjqsh.lesraisinsarmor.LesRaisinsArmor;
|
||||||
|
import net.minecraft.core.Holder;
|
||||||
|
import net.minecraft.core.Registry;
|
||||||
|
import net.minecraft.core.registries.BuiltInRegistries;
|
||||||
|
import net.minecraft.resources.Identifier;
|
||||||
|
import net.minecraft.world.effect.MobEffect;
|
||||||
|
import net.minecraft.world.effect.MobEffectCategory;
|
||||||
|
import net.minecraft.world.entity.ai.attributes.AttributeModifier;
|
||||||
|
import net.minecraft.world.entity.ai.attributes.Attributes;
|
||||||
|
|
||||||
|
public final class ModEffects {
|
||||||
|
private ModEffects() {}
|
||||||
|
|
||||||
|
public static final Holder<MobEffect> TOUGH = Registry.registerForHolder(
|
||||||
|
BuiltInRegistries.MOB_EFFECT, id("tough"),
|
||||||
|
new ArmorSetEffect(MobEffectCategory.BENEFICIAL, 0x59646f)
|
||||||
|
.addAttributeModifier(Attributes.ARMOR_TOUGHNESS, id("toughness"), 15.0, AttributeModifier.Operation.ADD_VALUE)
|
||||||
|
.addAttributeModifier(Attributes.KNOCKBACK_RESISTANCE, id("knockback_resistance"), 0.25, AttributeModifier.Operation.ADD_VALUE));
|
||||||
|
|
||||||
|
public static final Holder<MobEffect> LIGHT_LEG = Registry.registerForHolder(
|
||||||
|
BuiltInRegistries.MOB_EFFECT, id("light_leg"),
|
||||||
|
new ArmorSetEffect(MobEffectCategory.BENEFICIAL, 0x76c7a2)
|
||||||
|
.addAttributeModifier(Attributes.MOVEMENT_SPEED, id("scout_speed"), 0.025, AttributeModifier.Operation.ADD_VALUE));
|
||||||
|
|
||||||
|
public static final Holder<MobEffect> HEAVY_ARMOR = Registry.registerForHolder(
|
||||||
|
BuiltInRegistries.MOB_EFFECT, id("heavy_armor"),
|
||||||
|
new ArmorSetEffect(MobEffectCategory.BENEFICIAL, 0x55585e)
|
||||||
|
.addAttributeModifier(Attributes.MOVEMENT_SPEED, id("defender_speed"), -0.02, AttributeModifier.Operation.ADD_VALUE));
|
||||||
|
|
||||||
|
public static final Holder<MobEffect> RESCUE = Registry.registerForHolder(
|
||||||
|
BuiltInRegistries.MOB_EFFECT, id("rescue"),
|
||||||
|
new ArmorSetEffect(MobEffectCategory.BENEFICIAL, 0xb84c4c));
|
||||||
|
|
||||||
|
public static final Holder<MobEffect> RESCUE_COOLDOWN = Registry.registerForHolder(
|
||||||
|
BuiltInRegistries.MOB_EFFECT, id("rescue_cooldown"),
|
||||||
|
new ArmorSetEffect(MobEffectCategory.NEUTRAL, 0x6f6f6f));
|
||||||
|
|
||||||
|
private static Identifier id(String path) {
|
||||||
|
return Identifier.fromNamespaceAndPath(LesRaisinsArmor.MOD_ID, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void initialize() {
|
||||||
|
// Class loading performs registry registration.
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class ArmorSetEffect extends MobEffect {
|
||||||
|
private ArmorSetEffect(MobEffectCategory category, int color) {
|
||||||
|
super(category, color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
package me.xjqsh.lesraisinsarmor.gameplay;
|
||||||
|
|
||||||
|
import me.xjqsh.lesraisinsarmor.effect.ModEffects;
|
||||||
|
import me.xjqsh.lesraisinsarmor.item.LrArmorItem;
|
||||||
|
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents;
|
||||||
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
|
import net.minecraft.world.effect.MobEffect;
|
||||||
|
import net.minecraft.world.effect.MobEffectInstance;
|
||||||
|
import net.minecraft.world.effect.MobEffects;
|
||||||
|
import net.minecraft.world.entity.EquipmentSlot;
|
||||||
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
|
||||||
|
public final class ArmorSetEffects {
|
||||||
|
private static final int SET_EFFECT_DURATION = 40;
|
||||||
|
private static final int REFRESH_THRESHOLD = 25;
|
||||||
|
private static final int RESCUE_COOLDOWN_TICKS = 30 * 20;
|
||||||
|
private static final int RESCUE_REGEN_TICKS = 5 * 20;
|
||||||
|
|
||||||
|
private ArmorSetEffects() {}
|
||||||
|
|
||||||
|
public static void initialize() {
|
||||||
|
ServerTickEvents.END_SERVER_TICK.register(server -> {
|
||||||
|
for (ServerPlayer player : server.getPlayerList().getPlayers()) {
|
||||||
|
tickPlayer(player);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void tickPlayer(ServerPlayer player) {
|
||||||
|
syncSetEffect(player, "attacker", ModEffects.TOUGH);
|
||||||
|
syncSetEffect(player, "scout", ModEffects.LIGHT_LEG);
|
||||||
|
syncSetEffect(player, "defender", ModEffects.HEAVY_ARMOR);
|
||||||
|
|
||||||
|
if (hasFullSet(player, "medical")) {
|
||||||
|
tickMedical(player);
|
||||||
|
} else {
|
||||||
|
player.removeEffect(ModEffects.RESCUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void tickMedical(ServerPlayer player) {
|
||||||
|
if (player.hasEffect(ModEffects.RESCUE_COOLDOWN)) {
|
||||||
|
player.removeEffect(ModEffects.RESCUE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
refreshEffect(player, ModEffects.RESCUE);
|
||||||
|
|
||||||
|
if (player.getHealth() < player.getMaxHealth() * 0.30f) {
|
||||||
|
player.removeEffect(ModEffects.RESCUE);
|
||||||
|
player.addEffect(new MobEffectInstance(MobEffects.REGENERATION, RESCUE_REGEN_TICKS, 3, false, true, true));
|
||||||
|
player.addEffect(new MobEffectInstance(ModEffects.RESCUE_COOLDOWN, RESCUE_COOLDOWN_TICKS, 0, false, false, true));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void syncSetEffect(ServerPlayer player, String suit, net.minecraft.core.Holder<MobEffect> effect) {
|
||||||
|
if (hasFullSet(player, suit)) {
|
||||||
|
refreshEffect(player, effect);
|
||||||
|
} else {
|
||||||
|
player.removeEffect(effect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void refreshEffect(ServerPlayer player, net.minecraft.core.Holder<MobEffect> effect) {
|
||||||
|
MobEffectInstance current = player.getEffect(effect);
|
||||||
|
if (current == null || current.getDuration() < REFRESH_THRESHOLD) {
|
||||||
|
player.addEffect(new MobEffectInstance(effect, SET_EFFECT_DURATION, 0, false, false, true));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean hasFullSet(net.minecraft.world.entity.LivingEntity entity, String suit) {
|
||||||
|
return isSuitPiece(entity.getItemBySlot(EquipmentSlot.HEAD), suit)
|
||||||
|
&& isSuitPiece(entity.getItemBySlot(EquipmentSlot.CHEST), suit)
|
||||||
|
&& isSuitPiece(entity.getItemBySlot(EquipmentSlot.LEGS), suit)
|
||||||
|
&& isSuitPiece(entity.getItemBySlot(EquipmentSlot.FEET), suit);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isSuitPiece(ItemStack stack, String suit) {
|
||||||
|
return stack.getItem() instanceof LrArmorItem armor && armor.suitId().equals(suit);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package me.xjqsh.lesraisinsarmor.mixin;
|
||||||
|
|
||||||
|
import me.xjqsh.lesraisinsarmor.gameplay.ArmorSetEffects;
|
||||||
|
import net.minecraft.world.entity.LivingEntity;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.ModifyArg;
|
||||||
|
|
||||||
|
@Mixin(LivingEntity.class)
|
||||||
|
public abstract class LivingEntityDamageMixin {
|
||||||
|
@ModifyArg(
|
||||||
|
method = "actuallyHurt",
|
||||||
|
at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;setHealth(F)V"),
|
||||||
|
index = 0
|
||||||
|
)
|
||||||
|
private float lrarmor$applyDefenderDamageReduction(float newHealth) {
|
||||||
|
LivingEntity self = (LivingEntity) (Object) this;
|
||||||
|
if (!ArmorSetEffects.hasFullSet(self, "defender")) {
|
||||||
|
return newHealth;
|
||||||
|
}
|
||||||
|
|
||||||
|
float currentHealth = self.getHealth();
|
||||||
|
float healthDamage = Math.max(0.0f, currentHealth - newHealth);
|
||||||
|
return currentHealth - healthDamage * 0.85f;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -28,7 +28,6 @@
|
|||||||
"item.lrarmor.medical_chestplate": "MEDICAL-CHEST",
|
"item.lrarmor.medical_chestplate": "MEDICAL-CHEST",
|
||||||
"item.lrarmor.medical_leggings": "MEDICAL-LEGS",
|
"item.lrarmor.medical_leggings": "MEDICAL-LEGS",
|
||||||
"item.lrarmor.medical_boots": "MEDICAL-BOOTS",
|
"item.lrarmor.medical_boots": "MEDICAL-BOOTS",
|
||||||
|
|
||||||
"item.lrarmor.dea_armed_helmet": "Black Tactical Helmet",
|
"item.lrarmor.dea_armed_helmet": "Black Tactical Helmet",
|
||||||
"item.lrarmor.dea_armed_chestplate": "DEA Chest",
|
"item.lrarmor.dea_armed_chestplate": "DEA Chest",
|
||||||
"item.lrarmor.dea_armed_leggings": "Denim Jeans",
|
"item.lrarmor.dea_armed_leggings": "Denim Jeans",
|
||||||
@@ -65,7 +64,6 @@
|
|||||||
"item.lrarmor.joker_chestplate": "\"Joker\" Jacket",
|
"item.lrarmor.joker_chestplate": "\"Joker\" Jacket",
|
||||||
"item.lrarmor.joker_leggings": "\"Joker\" Pants",
|
"item.lrarmor.joker_leggings": "\"Joker\" Pants",
|
||||||
"item.lrarmor.joker_boots": "\"Joker\" Boots",
|
"item.lrarmor.joker_boots": "\"Joker\" Boots",
|
||||||
|
|
||||||
"suit.lrarmor.armored_chemical": "ARMORED CHEMICAL SUIT",
|
"suit.lrarmor.armored_chemical": "ARMORED CHEMICAL SUIT",
|
||||||
"suit.lrarmor.attacker": "ATTACKER SUIT",
|
"suit.lrarmor.attacker": "ATTACKER SUIT",
|
||||||
"suit.lrarmor.chemical_protective": "CHEMICAL PROTECTIVE SUIT",
|
"suit.lrarmor.chemical_protective": "CHEMICAL PROTECTIVE SUIT",
|
||||||
@@ -82,10 +80,10 @@
|
|||||||
"suit.lrarmor.fbi_armed": "FBI Special Suit",
|
"suit.lrarmor.fbi_armed": "FBI Special Suit",
|
||||||
"suit.lrarmor.joker": "\"Joker\" Organization Suit",
|
"suit.lrarmor.joker": "\"Joker\" Organization Suit",
|
||||||
"suit.lrarmor.joker_armed": "\"Joker\" Organization Combat Suit",
|
"suit.lrarmor.joker_armed": "\"Joker\" Organization Combat Suit",
|
||||||
|
|
||||||
"effect.lrarmor.tough": "Better Armor",
|
"effect.lrarmor.tough": "Better Armor",
|
||||||
"effect.lrarmor.heavy_armor": "Heavy Armor",
|
"effect.lrarmor.heavy_armor": "Heavy Armor",
|
||||||
"effect.lrarmor.light_leg": "Lightweight",
|
"effect.lrarmor.light_leg": "Lightweight",
|
||||||
"effect.lrarmor.rescue": "Self-Healing Device",
|
"effect.lrarmor.rescue": "Self-Healing Device",
|
||||||
"tooltip.lramrmor.suit": "%s: %s"
|
"tooltip.lramrmor.suit": "%s: %s",
|
||||||
|
"effect.lrarmor.rescue_cooldown": "Self-Healing Cooldown"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
{
|
{
|
||||||
"itemGroup.tab.lrarmor": "绿葡萄护甲",
|
"itemGroup.tab.lrarmor": "绿葡萄护甲",
|
||||||
"item.lrarmor.armored_chemical_helmet": "装甲防化服-头盔",
|
"item.lrarmor.armored_chemical_helmet": "装甲防化服-头盔",
|
||||||
"item.lrarmor.armored_chemical_chestplate": "装甲防化服-胸甲",
|
"item.lrarmor.armored_chemical_chestplate": "装甲防化服-胸甲",
|
||||||
@@ -28,7 +28,6 @@
|
|||||||
"item.lrarmor.medical_chestplate": "创伤小组-胸甲",
|
"item.lrarmor.medical_chestplate": "创伤小组-胸甲",
|
||||||
"item.lrarmor.medical_leggings": "创伤小组-护腿",
|
"item.lrarmor.medical_leggings": "创伤小组-护腿",
|
||||||
"item.lrarmor.medical_boots": "创伤小组-靴子",
|
"item.lrarmor.medical_boots": "创伤小组-靴子",
|
||||||
|
|
||||||
"item.lrarmor.dea_armed_helmet": "黑色战术头盔",
|
"item.lrarmor.dea_armed_helmet": "黑色战术头盔",
|
||||||
"item.lrarmor.dea_armed_chestplate": "DEA 防弹衣",
|
"item.lrarmor.dea_armed_chestplate": "DEA 防弹衣",
|
||||||
"item.lrarmor.dea_armed_leggings": "休闲牛仔裤",
|
"item.lrarmor.dea_armed_leggings": "休闲牛仔裤",
|
||||||
@@ -65,7 +64,6 @@
|
|||||||
"item.lrarmor.joker_chestplate": "“愚者”礼服上衣",
|
"item.lrarmor.joker_chestplate": "“愚者”礼服上衣",
|
||||||
"item.lrarmor.joker_leggings": "“愚者”礼服长裤",
|
"item.lrarmor.joker_leggings": "“愚者”礼服长裤",
|
||||||
"item.lrarmor.joker_boots": "“愚者”礼服靴子",
|
"item.lrarmor.joker_boots": "“愚者”礼服靴子",
|
||||||
|
|
||||||
"suit.lrarmor.armored_chemical": "装甲防化服套装",
|
"suit.lrarmor.armored_chemical": "装甲防化服套装",
|
||||||
"suit.lrarmor.attacker": "突击者套装",
|
"suit.lrarmor.attacker": "突击者套装",
|
||||||
"suit.lrarmor.chemical_protective": "防化服套装",
|
"suit.lrarmor.chemical_protective": "防化服套装",
|
||||||
@@ -82,10 +80,10 @@
|
|||||||
"suit.lrarmor.fbi_armed": "FBI特别组装甲套装",
|
"suit.lrarmor.fbi_armed": "FBI特别组装甲套装",
|
||||||
"suit.lrarmor.joker": "“愚者”组织套装",
|
"suit.lrarmor.joker": "“愚者”组织套装",
|
||||||
"suit.lrarmor.joker_armed": "“愚者”组织作战套装",
|
"suit.lrarmor.joker_armed": "“愚者”组织作战套装",
|
||||||
|
|
||||||
"effect.lrarmor.tough": "特制减震夹层",
|
"effect.lrarmor.tough": "特制减震夹层",
|
||||||
"effect.lrarmor.heavy_armor": "超重型全身装甲",
|
"effect.lrarmor.heavy_armor": "超重型全身装甲",
|
||||||
"effect.lrarmor.light_leg": "轻量化腿部支撑",
|
"effect.lrarmor.light_leg": "轻量化腿部支撑",
|
||||||
"effect.lrarmor.rescue": "便携自愈设备",
|
"effect.lrarmor.rescue": "便携自愈设备",
|
||||||
"tooltip.lramrmor.suit": "%s: %s"
|
"tooltip.lramrmor.suit": "%s: %s",
|
||||||
|
"effect.lrarmor.rescue_cooldown": "自愈装置冷却"
|
||||||
}
|
}
|
||||||
@@ -25,6 +25,7 @@
|
|||||||
"geckolib": ">=5.5.4"
|
"geckolib": ">=5.5.4"
|
||||||
},
|
},
|
||||||
"mixins": [
|
"mixins": [
|
||||||
|
"lrarmor.mixins.json",
|
||||||
{
|
{
|
||||||
"config": "lrarmor.client.mixins.json",
|
"config": "lrarmor.client.mixins.json",
|
||||||
"environment": "client"
|
"environment": "client"
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"required": true,
|
||||||
|
"package": "me.xjqsh.lesraisinsarmor.mixin",
|
||||||
|
"mixins": [
|
||||||
|
"LivingEntityDamageMixin"
|
||||||
|
],
|
||||||
|
"injectors": {
|
||||||
|
"defaultRequire": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user