How to make a potion trigger its effect every x ticks [TUTORIAL]

Started by SomeoneElse on Sun, 07/28/2019 - 16:03

Topic category: User side tutorials

Last seen on 12:44, 2. Jul 2020
Joined Nov 2017
User points:

User statistics:

  • Modifications:
  • Forum topics:
  • Wiki pages:
  • Tracker tickets:
  • Comments:
How to make a potion trigger its effect every x ticks [TUTORIAL]
Sun, 07/28/2019 - 18:43 (edited)

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.

Edited by SomeoneElse on Sun, 07/28/2019 - 18:43
Wow, this is a very nice…
Sun, 07/28/2019 - 18:42

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 ;)

Last seen on 12:48, 2. Jul 2020
Joined Jun 2019
User points:

User statistics:

  • Modifications:
  • Forum topics:
  • Wiki pages:
  • Tracker tickets:
  • Comments:
I don't understand:(
Sun, 07/28/2019 - 23:24

I don't understand:(

Last seen on 12:44, 2. Jul 2020
Joined Nov 2017
User points:

User statistics:

  • Modifications:
  • Forum topics:
  • Wiki pages:
  • Tracker tickets:
  • Comments:
Which parts do you need help…
Sun, 07/28/2019 - 23:34

Which parts do you need help with?
I made an image which should help understand the % part:
Modulo operator

% 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.

Last seen on 12:48, 2. Jul 2020
Joined Jun 2019
User points:

User statistics:

  • Modifications:
  • Forum topics:
  • Wiki pages:
  • Tracker tickets:
  • Comments:
oh but return true it ends…
Sun, 07/28/2019 - 23:55

oh but return true it ends the effect?

Last seen on 12:44, 2. Jul 2020
Joined Nov 2017
User points:

User statistics:

  • Modifications:
  • Forum topics:
  • Wiki pages:
  • Tracker tickets:
  • Comments:
If you leave return true the…
Mon, 07/29/2019 - 00:04

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.

Last seen on 12:44, 2. Jul 2020
Joined Nov 2017
User points:

User statistics:

  • Modifications:
  • Forum topics:
  • Wiki pages:
  • Tracker tickets:
  • Comments:
To clarify, think of isReady…
Mon, 07/29/2019 - 00:09

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

Last seen on 09:58, 2. Jul 2020
Joined Jun 2016
User points:

User statistics:

  • Modifications:
  • Forum topics:
  • Wiki pages:
  • Tracker tickets:
  • Comments:
Alternatively, player nbt…
Mon, 07/29/2019 - 19:08

Alternatively, player nbt can probably provide the same effect, if you are not very experienced with code.

Last seen on 14:00, 6. Apr 2020
Joined Aug 2019
User points:

User statistics:

  • Modifications:
  • Forum topics:
  • Wiki pages:
  • Tracker tickets:
  • Comments:
Nice tutorial :) Keep up the…
Sat, 08/03/2019 - 09:59

Nice tutorial :) Keep up the good work!

Last seen on 14:00, 6. Apr 2020
Joined Aug 2019
User points:

User statistics:

  • Modifications:
  • Forum topics:
  • Wiki pages:
  • Tracker tickets:
  • Comments:
Btw, never seen it was C#,…
Sat, 08/03/2019 - 09:59

Btw, never seen it was C#, lol

Last seen on 12:21, 2. Jul 2020
Joined Jun 2017
User points:

User statistics:

  • Modifications:
  • Forum topics:
  • Wiki pages:
  • Tracker tickets:
  • Comments:
And guess what? It didn't…
Wed, 08/14/2019 - 11:49

And guess what? It didn't work of course!

Last seen on 12:21, 2. Jul 2020
Joined Jun 2017
User points:

User statistics:

  • Modifications:
  • Forum topics:
  • Wiki pages:
  • Tracker tickets:
  • Comments:
Man, that doesn't work at…
Wed, 08/14/2019 - 11:51

Man, that doesn't work at all... I've got just an effect which does litteraly anything :/

Last seen on 12:21, 2. Jul 2020
Joined Jun 2017
User points:

User statistics:

  • Modifications:
  • Forum topics:
  • Wiki pages:
  • Tracker tickets:
  • Comments:
Ah it worked now
Wed, 08/14/2019 - 12:58

Ah it worked now