Jump to content

[1.7.10][Solved] How to conditionally disable player hp regeneration


Recommended Posts

Posted

Hi everyone,

 

I was wondering if anyone would happen to know how to disable hp regeneration for the player. I want it disabled when a condition is true for my player. Since peaceful mode makes it so that your hp regens over time i want this disabled for my player when he is morphed into one of his party members. Any ideas?

 

[EDIT]

This has been Solved see the solution in http://www.minecraftforge.net/forum/index.php/topic,34056.0.html

Posted

LivingHealEvent?

 

Note: As far as I remember it is impossible to know how healing was applied. Only thing you can do is to deal damage whenever you know that entity might have been healed (mening: when food is above healing requirement).

1.7.10 is no longer supported by forge, you are on your own.

Posted

You could register the current health at the point where the regen should be disabled. From there on, override that value whenever it goes down, and override the health with that value whenever it goes up.

 

Not a perfect solution, but it should cover most cases.

If anyone has a comprehensive, visual guide to GUIs - don't hesitate to message me. They make my head spin.

Posted

Hey I cant find the LivingHealEvent. Im in forge version 1.7.10-10.13.2.1230.jar Is this event a new one?

 

Looking at the changelog, it was added in 1.7.10-10.13.2.1256 and 1.8-11.14.0.1257.

Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.

Posted

Yes ernio is right. There is no way to detect the source of healing.

What you could do is store some data in IEEP, e.g. the last healing. Everytime the player wants to heal check the amount (normal regen is half a heart) and the time. If you know how much time between healing ticks is u can exactly find out if the source COULD be regen.

Posted

Sometimes I wonder where do you get those ideas from.

 

I mean - you find something challenging so you just sit there until you find a way to do it your way, or you just know even more than I thought.

 

Anyway - that's some good shit. Useful AF, now I don't have to do "regen=vanilla(+1)+myStats(+x)" but directly "regen=myStats(+x)".

1.7.10 is no longer supported by forge, you are on your own.

Posted

Also, wrapping existing FoodStats object is preferable, since there are some mods using same method.

I. Stellarium for Minecraft: Configurable Universe for Minecraft! (WIP)

II. Stellar Sky, Better Star Rendering&Sky Utility mod, had separated from Stellarium.

Posted

Would it be preferable to create my own custom class that extends the foodstats class and override its onUpdate method to conditionally disable the hp regen or would just updating forge be a better solution so that I can use the LivingHealEvent?

Posted

Also, Im not really sure how to Override the food stats object for the player. I know how to override methods but Ive never overridden an object before. In Entityplayer the food stats variable is protected. I made my custom Food Stats Class extend the vanilla Food Stats class and in the onUpdate method I call super.onUpdate() and I put a @Override annotation above it as per usual. Not sure what else I am missing

Posted

1. You would have to completely change the onUpdate method.

2. This is what I mean by 'overlap': store the existing FoodStats object,

    and call its method which you would not want to change.

I. Stellarium for Minecraft: Configurable Universe for Minecraft! (WIP)

II. Stellar Sky, Better Star Rendering&Sky Utility mod, had separated from Stellarium.

Posted

Ok, Im not sure exactly how to do this. So far I have the following in my custom class (its all based on vanilla except the onUpdate method which is different (I changed it completely to just outprint to consol (the outprint doesnt currently show up btw)))

 

The CustomFoodStats  class

public class CustomFoodStats extends FoodStats
{
    /** The player's food level. */
    private int foodLevel = 20;
    /** The player's food saturation. */
    private float foodSaturationLevel = 5.0F;
    /** The player's food exhaustion. */
    private float foodExhaustionLevel;
    /** The player's food timer value. */
    private int foodTimer;
    private int prevFoodLevel = 20;
   
    /**
     * Args: int foodLevel, float foodSaturationModifier
     */
    @Override
    public void addStats(int min, float max)
    {	super.addStats(min, max);
        this.foodLevel = Math.min(min + this.foodLevel, 20);
        this.foodSaturationLevel = Math.min(this.foodSaturationLevel + (float)min * max * 2.0F, (float)this.foodLevel);
    }
    @Override
    public void func_151686_a(ItemFood food, ItemStack itemStack)
    { 	super.func_151686_a(food, itemStack);
        this.addStats(food.func_150905_g(itemStack), food.func_150906_h(itemStack));
    }

    /**
     * Handles the food game logic.
     */
    @Override
    public void onUpdate(EntityPlayer player)
    {  	super.onUpdate(player);
    	System.out.println("OVERRIDDEN");
    }

    /**
     * Reads food stats from an NBT object.
     */
    @Override
    public void readNBT(NBTTagCompound nbt)
    {	super.readNBT(nbt);
        if (nbt.hasKey("foodLevel", 99))
        {
            this.foodLevel = nbt.getInteger("foodLevel");
            this.foodTimer = nbt.getInteger("foodTickTimer");
            this.foodSaturationLevel = nbt.getFloat("foodSaturationLevel");
            this.foodExhaustionLevel = nbt.getFloat("foodExhaustionLevel");
        }
    }

    /**
     * Writes food stats to an NBT object.
     */
    @Override
    public void writeNBT(NBTTagCompound nbt)
    {	super.writeNBT(nbt);
        nbt.setInteger("foodLevel", this.foodLevel);
        nbt.setInteger("foodTickTimer", this.foodTimer);
        nbt.setFloat("foodSaturationLevel", this.foodSaturationLevel);
        nbt.setFloat("foodExhaustionLevel", this.foodExhaustionLevel);
    }

    /**
     * Get the player's food level.
     */
    @Override
    public int getFoodLevel()
    {	super.getFoodLevel();
        return this.foodLevel;
    }

    @Override
    @SideOnly(Side.CLIENT)
    public int getPrevFoodLevel()
    {	super.getPrevFoodLevel();
        return this.prevFoodLevel;
    }

    /**
     * If foodLevel is not max.
     */
    @Override
    public boolean needFood()
    {	super.needFood();
        return this.foodLevel < 20;
    }

    /**
     * adds input to foodExhaustionLevel to a max of 40
     */
    @Override
    public void addExhaustion(float amount)
    {	super.addExhaustion(amount);
        this.foodExhaustionLevel = Math.min(this.foodExhaustionLevel + amount, 40.0F);
    }

    /**
     * Get the player's food saturation level.
     */
    @Override
    public float getSaturationLevel()
    {	super.getSaturationLevel();
        return this.foodSaturationLevel;
    }

    @Override
    @SideOnly(Side.CLIENT)
    public void setFoodLevel(int amount)
    {	super.setFoodLevel(amount);
        this.foodLevel = amount;
    }

    @Override
    @SideOnly(Side.CLIENT)
    public void setFoodSaturationLevel(float amount)
    {	super.setFoodSaturationLevel(amount);
        this.foodSaturationLevel = amount;
    }
}

Posted

in my IEEP I do the following.

public CustomFoodStats foodStats = new CustomFoodStats(); to initialize it,

Then inside the onLivingUpdate Event I get the IEEP instance from the player and then do

ieep.foodStats.onUpdate((EntityPlayer) event.entity);

but this doesnt override anything it just calls my onUpdate method

Posted

You should set the foodstats field of the player.

Also don't just copy-paste the code..

I. Stellarium for Minecraft: Configurable Universe for Minecraft! (WIP)

II. Stellar Sky, Better Star Rendering&Sky Utility mod, had separated from Stellarium.

Posted

That is what happens when you don't understand how Java (or programming) works. (I wasn't expecting this from you really :P)

 

Just making class won't do anything.

You need to actually replace FoodStats object in EntityPlayer field.

 

In EntityPlayer there is a field:

protected FoodStats foodStats = new FoodStats();

Basically - you need to replace it whenever it is not set yours.

Init in Java goes like this: (refresh my memory if not)

Static initalization.
Instance initialization.
Constructor executed.

So You can probably use EntityConstructing event to access player#foodStats with reflection and set value to your own.

ObfuscationReflectionHelper.getPrivateValue(EntityPlayer.class, event.player, "foodStats", "findSrgInFiles");

 

Mentioned before object wrapping is passing previous FoodStats (no matter the extension) into your new one.

So e.g you can have FoodStatsOfModOne inside FoodStatsOfYourMod.

1.7.10 is no longer supported by forge, you are on your own.

Posted

I understand that copying the class wont do anything, I am bad at reflection so I guess I wasnt being clear I wasnt sure how to actually override the actual object so that I can use my class instead.

Posted

Ok, so in my EntityConstructing event I get the access player#foodStats. But this outprints as Null when I do this. Im not sure what else to do

 

@SubscribeEvent
public void onEntityConstructing(EntityConstructing event) {

	if (event.entity instanceof EntityPlayer) {
		if (BattlePlayerProperties.get((EntityPlayer) event.entity) == null) {
			BattlePlayerProperties.register((EntityPlayer) event.entity);
			}

	FoodStats foodStats = ObfuscationReflectionHelper.getPrivateValue(EntityPlayer.class, (EntityPlayer)event.entity, "foodStats", "findSrgInFiles");
                System.out.println(foodStats); //PRINTS A VALUE OF NULL
	}
}

Posted

Im not really sure what I have to do here to replace the FoodStats object that the player is using with my own.

 

I know that I have to get the object but when I do that using Entity Constructing event I get a value of null for it and I know that I have to replace the object after it has been initialized with my own (the class is above) But i am not sure what the steps are

Posted

I tried the following to get the field and it doesnt seem to fail, it outprints the following on EntityConstructing:  TRYING custommod.player.properties.CustomFoodStats@16c8fa04

 

try{
			Field field = ReflectionHelper.findField(EntityPlayer.class,"field_71100_bB","foodStats");
			field.setAccessible(true);
			field.set((EntityPlayer)event.entity, new CustomFoodStats());
			System.out.println("TRYING " + field.get(event.entity));

		}catch (Throwable e){
			System.out.println("Reflection on foodStats variable for Player has FAILED!!");
			e.printStackTrace();
		}

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.