Topic category: User side tutorials
Want to create a regeneration-like effect, but the potion keeps healing you too quickly? In this tutorial I'll explain how to make potions that trigger a procedure every x ticks, rather than every tick.
First of all, create your potion
This doesn't really need any explaination: create the procedure you want to call, create the potion and call the procedure in "On potion active tick".
Now, if you open the code of the potion, you'll find something like this:
public boolean isReady(int duration, int amplifier) {
return true;
}
This function is called every tick: if it returns true, then the code inside performEffect will be executed (in this case, it'll trigger the procedure). Here, the function will always return the value true, so the effect is executed on every tick. If your potion has a duration of 40, the procedure will be called 40 times, and so on.
Let's say we want the potion to heal your hunger every 100 ticks (5 seconds): to pull this off, we'll have to define an integer inside isReady. Vanilla Minecraft names it k, so that's what I'll use in this tutorial
1. Fixed period
The effect is triggered every 100 ticks, no matter the level of your potion. In this case we'll just set k to 100.
int k = 100;
2. Variable period
The effect is triggered more often the higher the level. In this case you have to write an expression with the variable amplifier - which is the level of your potion minus 1. It's also one of the parameters of isReady, so you don't have to worry about defining it or anything. Here's a few examples:
int k = 100 / (amplifier + 1);
If you use a division, increase amplifier by one, or you'll get a division-by-zero error when the level of the potion is 1. Just to be safe, you can check if amplifier is -1 and give k a different value in such situation. Here's a small table with the duration of the period in relation to the amplifier.
amplifier | k |
0 | 100 |
1 | 50 |
2 | 33 |
int k = 100 >> amplifier;
This expression is pretty much the same as writing 100 / 2amplifier. The period is cut in half with each level, which is what happens with Regeneration, Poison and Wither. k rolls back to 100 when amplifier is a multiplier of 32, but this shouldn't concern you, since you probably don't need your potion to reach lvl 33+
amplifier | k |
0 | 100 |
1 | 50 |
2 |
25 |
Now that we've set the period, the code should look something like this:
public boolean isReady(int duration, int amplifier) {
int k = 100 >> amplifier;
return true;
}
However, the function still returns true every tick. Here's where we use the other parameter of the function, duration, which is how long the potion will be active for. By using the operator %, we can trigger the procedure every time duration is a multiplier of k.
return duration % k == 0;
If amplifier = 0, then k = 100. The effect will be triggered if duration is 100, 200, 300 and so on. It's worth nothing that, with variable periods, k can reach the value 0. To prevent division-by-zero errors, you need to add an if statement and check whether k is 0. The resulting code should be something like this:
public boolean isReady(int duration, int amplifier) {
int k = 100 >> amplifier;
if (k > 0)
return duration % k == 0;
else
return true;
}
Now, if k is 0, the procedure is called every tick instead of crashing the game.
That's pretty much it. I'll publish an example mod with the workspace if that can be helpful.
Wow, this is a very nice explanation :) If you ever consider becoming a wiki contributor and post such tutorials on the wiki, this is the page to apply: https://mcreator.net/page/wiki-contributors ;)
I don't understand:(
Which parts do you need help with?
I made an image which should help understand the % part:
% is called the "modulo" operator. Think of it as "cutting" the duration into pieces that measure k ticks. For example, if k is 4, it's like counting 0 1 2 3 over and over. return duration % k == 0; triggers the procedure every time you hit 0.
oh but return true it ends the effect?
If you leave return true the effect will happen every tick (1/20th of a second). With return duration % k == 0; the effect happens every k ticks. If the statement after return is true, the game triggers the procedure, otherwise it doesn't.
To clarify, think of isReady as a question: "Is the procedure ready to be executed?". return is what answers the question. With duration % k == 0; you're asking the game if duration is a multiplier of k. For example, if k is 4, the answer to that question is true when duration is 4, 8, 12 and so on. The answer to "Is duration a multiplier of k?" is also the answer to "Is the procedure ready to be executed?", because of the return
Alternatively, player nbt can probably provide the same effect, if you are not very experienced with code.
Nice tutorial :) Keep up the good work!
Btw, never seen it was C#, lol
And guess what? It didn't work of course!
Man, that doesn't work at all... I've got just an effect which does litteraly anything :/
Ah it worked now
Nice. It's very useful thing