Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rework stunning effect #50

Merged
merged 8 commits into from
Sep 5, 2024
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
2 changes: 1 addition & 1 deletion src/generated/resources/assets/oreganized/lang/en_us.json
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@
"block.oreganized.white_crystal_glass_pane": "White Crystal Glass Pane",
"block.oreganized.yellow_crystal_glass": "Yellow Crystal Glass",
"block.oreganized.yellow_crystal_glass_pane": "Yellow Crystal Glass Pane",
"effect.oreganized.stunning": "Stunning",
"effect.oreganized.stunning": "Brain Damage",
"effect.oreganized.stunning.description": "Paralyzes the victim periodically with random intervals",
"entity.oreganized.lead_bolt": "Lead Bolt",
"entity.oreganized.shrapnel_bomb": "Shrapnel Bomb",
Expand Down
24 changes: 19 additions & 5 deletions src/main/java/galena/oreganized/client/render/gui/OGui.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,30 @@

import com.mojang.blaze3d.systems.RenderSystem;
import galena.oreganized.Oreganized;
import galena.oreganized.content.effect.StunningEffect;
import galena.oreganized.index.OEffects;
import galena.oreganized.index.OFluids;
import io.netty.util.collection.IntObjectHashMap;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.client.gui.overlay.ForgeGui;

import java.util.HashMap;
import java.util.stream.IntStream;

public class OGui extends ForgeGui {

protected static final ResourceLocation STUNNING_LOCATION = Oreganized.modLoc("textures/misc/stunning_outline.png");
protected static final ResourceLocation STUNNING_VIGNETTE_LOCATION = Oreganized.modLoc( "textures/misc/stunning_overlay.png");

private static final IntObjectHashMap<ResourceLocation> STUNNING_OVERLAY_LOCATIONS = new IntObjectHashMap<>();

protected static ResourceLocation getStunningOutline(int amplifier) {
return STUNNING_OVERLAY_LOCATIONS.computeIfAbsent(amplifier, i -> {
return Oreganized.modLoc("textures/misc/brain_damage_outline_" + (i + 1) + ".png");
});
}

public OGui(Minecraft mc) {
super(mc);
}
Expand All @@ -24,12 +36,14 @@ public void render(GuiGraphics guiGraphics, float partialTick) {
this.screenHeight = this.minecraft.getWindow().getGuiScaledHeight();
RenderSystem.enableBlend();

if (this.minecraft.player.hasEffect(OEffects.STUNNING.get())) {
this.renderTextureOverlay(guiGraphics, STUNNING_VIGNETTE_LOCATION, 1);
this.renderTextureOverlay(guiGraphics, STUNNING_LOCATION, 0.8F);
var stunning = this.minecraft.player.getEffect(OEffects.STUNNING.get());
if (stunning != null) {
var opacity = stunning.getAmplifier() * 1F / StunningEffect.MAX_AMPLIFIER;
this.renderTextureOverlay(guiGraphics, STUNNING_VIGNETTE_LOCATION, opacity);
this.renderTextureOverlay(guiGraphics, getStunningOutline(stunning.getAmplifier()), 1F);
}

if (this.minecraft.player.isEyeInFluidType(OFluids.MOLTEN_LEAD_TYPE.get()))
this.renderTextureOverlay(guiGraphics, STUNNING_VIGNETTE_LOCATION, 1);
this.renderTextureOverlay(guiGraphics, STUNNING_VIGNETTE_LOCATION, 1F);
}
}
72 changes: 32 additions & 40 deletions src/main/java/galena/oreganized/content/effect/StunningEffect.java
Original file line number Diff line number Diff line change
@@ -1,68 +1,60 @@
package galena.oreganized.content.effect;

import galena.oreganized.Oreganized;
import galena.oreganized.index.OEffects;
import net.minecraft.client.player.Input;
import net.minecraft.world.effect.MobEffect;
import net.minecraft.world.effect.MobEffectCategory;
import net.minecraft.world.effect.MobEffectInstance;
import net.minecraft.world.effect.MobEffects;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.entity.ai.attributes.AttributeModifier;
import net.minecraft.world.entity.ai.attributes.Attributes;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.client.event.MovementInputUpdateEvent;
import net.minecraftforge.event.entity.living.LivingEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import galena.oreganized.Oreganized;
import java.util.UUID;

@Mod.EventBusSubscriber(modid = Oreganized.MOD_ID, value = Dist.CLIENT)
public class StunningEffect extends MobEffect {

public static boolean flag = false; // Flag to check if entity should be paralysed
public static int coolDown = 0;
private static final String SLOWNESS_UUID = "019150f6-e85e-777f-a566-1eafd7c7e1a5";
public static final int MAX_AMPLIFIER = 9;

public StunningEffect() {
super(MobEffectCategory.HARMFUL, 0x3B3B63);
addAttributeModifier(Attributes.MOVEMENT_SPEED, SLOWNESS_UUID, -0.075, AttributeModifier.Operation.MULTIPLY_TOTAL);
}

public static double getTurnModifier(LivingEntity entity) {
var effect = entity.getEffect(OEffects.STUNNING.get());
if (effect == null) return 1.0;

return 0.95 - effect.getAmplifier() * 0.05;
}

@Override
public void applyEffectTick(@NotNull LivingEntity entity, int amplifier) {
if (coolDown <= 0) {
// amplifier multiplies only the time frozen, making the relative gap larger the higher the level
coolDown = entity.level().getRandom().nextInt(120 * (flag ? amplifier + 1 : 1)) + 20;
flag = !flag; // Toggle flag, if should be paralysed flag = true, else flag = false
}
coolDown--; // cool down is decremented every in game tick
}
if (entity.level().getGameTime() % 5 != 0L) return;

@SubscribeEvent // applyStunned for Mobs
public static void applyStunned(LivingEvent.LivingTickEvent event) {
LivingEntity entity = event.getEntity();
if ((!(entity instanceof Player)) && entity.hasEffect(OEffects.STUNNING.get()) && flag) {
// Copied from LivingEntity.aiStep() when isImmobile() is true
entity.setJumping(false);
entity.xxa = 0.0F;
entity.zza = 0.0F;
}
}
var health = entity.getHealth() / entity.getMaxHealth();
var targetAmplifier = (int) Math.ceil((1.0 - health) * MAX_AMPLIFIER);

if (targetAmplifier == amplifier) return;
var instance = entity.getEffect(this);
if (instance == null) return;

var step = targetAmplifier > amplifier ? 1 : -1;

@SubscribeEvent // applyStunned for Players
public static void applyStunned(MovementInputUpdateEvent event) {
Input input = event.getInput(); // Gets player movement input
if (event.getEntity().hasEffect(OEffects.STUNNING.get()) && flag) {
// Disable all movement related input by setting it to false or 0
input.up = false;
input.down = false;
input.left = false;
input.right = false;
input.forwardImpulse = 0;
input.leftImpulse = 0;
input.jumping = false;
input.shiftKeyDown = false;
if (instance.update(new MobEffectInstance(this, instance.getDuration() + 1, amplifier + step, instance.isAmbient(), instance.isVisible(), instance.showIcon()))) {
addAttributeModifiers(entity, entity.getAttributes(), instance.getAmplifier());
}
}

@Override
public boolean isDurationEffectTick(int pDuration, int pAmplifier) {
return this == OEffects.STUNNING.get();
public boolean isDurationEffectTick(int duration, int amplifier) {
return true;
}
}
22 changes: 22 additions & 0 deletions src/main/java/galena/oreganized/mixin/FoodDataMixin.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package galena.oreganized.mixin;

import galena.oreganized.index.OEffects;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.food.FoodData;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;

@Mixin(FoodData.class)
public class FoodDataMixin {

@Redirect(
method = "tick(Lnet/minecraft/world/entity/player/Player;)V",
at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;heal(F)V")
)
private void modifyHealthAmount(Player player, float value) {
if (player.hasEffect(OEffects.STUNNING.get())) player.heal(value / 2);
else player.heal(value);
}

}
28 changes: 28 additions & 0 deletions src/main/java/galena/oreganized/mixin/MobEffectInstanceMixin.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package galena.oreganized.mixin;

import galena.oreganized.content.effect.StunningEffect;
import galena.oreganized.index.OEffects;
import net.minecraft.world.effect.MobEffectInstance;
import org.objectweb.asm.Opcodes;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;

@Mixin(MobEffectInstance.class)
public class MobEffectInstanceMixin {

@Redirect(
method = "update(Lnet/minecraft/world/effect/MobEffectInstance;)Z",
at = @At(
value = "FIELD",
target = "Lnet/minecraft/world/effect/MobEffectInstance;amplifier:I",
ordinal = 0,
opcode = Opcodes.GETFIELD
)
)
private int replaceStunning(MobEffectInstance instance) {
if (instance.getEffect() == OEffects.STUNNING.get()) return StunningEffect.MAX_AMPLIFIER + 1;
return instance.getAmplifier();
}

}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
6 changes: 3 additions & 3 deletions src/main/resources/oreganized.mixins.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@
"package": "galena.oreganized.mixin",
"compatibilityLevel": "JAVA_17",
"mixins": [
"AbstractArrowMixin", "BlockMixin", "CrossbowMixin", "DispenserBlockMixin", "IceBlockMixin", "PlayerMixin"
"AbstractArrowMixin", "CrossbowMixin", "DispenserBlockMixin", "FoodDataMixin", "MobEffectInstanceMixin",
"PlayerMixin", "BlockMixin", "IceBlockMixin"
],
"client": [
"client.HumanoidArmorLayerAccessor", "client.HumanoidArmorLayerMixin"
],
"server": [
],
"server": [],
"injectors": {
"defaultRequire": 1
},
Expand Down
Loading