[Mod] Player Effects [1.2.1] [playereffects]

User avatar
Wuzzy
Member
Posts: 4786
Joined: Mon Sep 24, 2012 15:01
GitHub: Wuzzy2
IRC: Wuzzy
In-game: Wuzzy
Contact:

[Mod] Player Effects [1.2.1] [playereffects]

by Wuzzy » Post

Player Effects is a modding framework for assigning temporary status effects to players.

Version: 1.2.1 (This is a SemVer.)
For: Minetest 0.4.10 or later
License of everything: MIT License
Download: https://codeberg.org/Wuzzy/minetest_pla ... /1.2.1.zip
Project page with README file: https://codeberg.org/Wuzzy/minetest_playereffects

List of known mods which use Player Effects: This is a framework for other mods to depend on. It provides means to define, apply and remove temporary status effects to players in a (hopefully) unobstrusive way.
A status effect is an effect for a player which changes some property of the player. This property can be practically everything. Currently, the framework supports one kind of effect, which I call “exclusive effects”. For each property (speed, gravity, whatver), there can be only one effect in place at the same time.
  • high walking speed (speed property)
  • high jump height (jump property)
  • low player gravity (gravity property)
  • high player gravity (gravity property)
  • having the X privilege granted (binary “do I have the property?” property) (yes, this is weird, but it works!)
The framework aims to provide means to define effect types and to apply and cancel effects to players. The framework aims to be a stable foundation stone. This means it needs a lot of testing.

This is what the mod had achieved for now:
  • Showing all active effects in the HUD (with timer)
  • Letting you define your own status effect types
  • Letting you define effect groups to automatically eliminate effect conflicts (fast vs slow, low vs high gravity, etc.)
  • Letting you apply effects to player
  • Letting you remove effects to player
  • Doing a lot of important “plumbing” and “behind-the-stages” work:
    • Remembering effects when a player leaves and freeze the timer
    • Restoring them when the player is back
    • Remembering all effects when the server shuts down
    • Restoring them as frozen effects when the server is back
    • Cancelling all active player’s effects when he/she/it dies
The HUD shows a list of active effects and looks like this:
Image

Many things have been achiveved, but I do not guarantee a stable API yet. Until version 1.0, I intend this thread to be a discussion thread for comments, ideas, test reports, and whatever.


List of important goals for later versions:
  • Additive effects: A whole new class of effects which is different from the exclusive effects. They too use effect groups, but they do not cancel each other out. Instead, they add to each other. Let’s say you take 2 potion of speed, maybe both are not of the same strength. Under exclusive effects, the old effect is simply gone. But under additive effects, the speed of both potions would add up. It is also planned to add optional limits, so a player could not jack up a property towards absurdly high values.
The mod comes with several example effect types for testing; they are enabled by default and I hope they should be helpful for modders as well. As soon as I think this mod is stable, I disable the examples by default, simply to avoid cluttering the modspace. ;-)
The examples are simply chatcommands available to everyone (effect groups are in brackets)
* /fast: You become faster (speed)
* /slow: You become slower (speed)
* /highjump: You can jump a bit higher (jump)
* /fly: You get the fly privilege temporarily (fly)

Try /fast and /slow quickly after each other. There should be no overlap at all. Using status effects to handle privileges sounds weird and it IS weird. But it is also funny somehow. If you really want to manipulate privileges with this mods, just make sure nobody messes around with the affected privileges manually.

The relevant stuff for modders:

To use this framework, do this:
  • create a mod
  • make it depend on playereffects
  • register effect types
  • decide when to apply said effect types and apply them
The important functions:
Register a new effect type:

Code: Select all

playereffects.register_effect_type(internal_name, description, groups, apply, cancel)
Where:
internal_name is the name which is internally used by the mod. Please use only alphanumeric ASCII characters.
description is the text which is exposed to the GUI and visible to the player.
groups is a table of strings to which the effect type is assigned to. I explain the concept of effect groups later.
apply is a function which takes a player object. It is the player object to which the effect is applied to. This function isused by the framework to start the effect; it should only contain the gameplay-relevant stuff, the framework does the rest for you.
cancel is a function which takes an effect table. It is the effect which is to be cancelled. This function is called by the framework when the effect expires or is explicitly cancelled by other means.

Apply an existing effect type to a player:

Code: Select all

playereffects.apply_effect_type(internal_name, duration, player)
This applies the effect type with the internal name internal_name for duration seconds to player.
Last edited by Wuzzy on Tue Jun 20, 2023 07:59, edited 20 times in total.

prestidigitator
Member
Posts: 647
Joined: Thu Feb 21, 2013 23:54

Re: [Mod] Player effects [0.1] [playereffects]

by prestidigitator » Post

Interesting. It would conceivably be possible to layer multiple effects that each affect the same property, by using a Decorator pattern. Something like:

Code: Select all

--- Parent class for effects that can decorate each other.
 --
 -- Fields:
 --    parent
 --       - Parent effect, for removal.
 --    child
 --       - Child effect from which to derive this one.
 --    done
 --       True if effect has been removed.
 --    cleanup(self, root)
 --       Callback method to call (once) when effect is removed.  Passed the
 --       "parent-most" effect left in the list after removing self (possibly
 --       nil).
 --
Effect =
{
   new = function(class, child)
      local self = setmetatable({ child = child }, { __index = class });
      if child then child.parent = self; end
      return self;
   end,

   --- Calculates this effect's value.
   getValue = function(self)
      return nil;
   end,

   --- Removes this effect from the list, calling self:cleanup(root) and also
    -- returning root, where root is the "parent-most" effect left after the
    -- removal (possibly nil).
   remove = function(self)
      if self.done then return nil; end

      local p, c = self.parent, self.child;
      if c then c.parent = p; end
      if p then
         p.child = c;
         while p.parent do
            p = p.parent;
         end
      end

      local root = p or c;

      if self.cleanup then
         self:cleanup(root);
         self.cleanup = nil;
      end

      return root;
   end
};
setmetatable(Effect, { __call = Effect.new });

--- Always returns a constant value.
 --
 -- Example:
 --
 --    local eff = ConstEffect(3.14);
 --    eff:getValue() -- 3.14
 --
ConstEffect =
{
   new = function(class, constValue, child)
      local self = Effect.new(class, child);
      self.constValue = constValue;
      return self;
   end,

   getValue = function(self)
      return self.constValue;
   end
};
setmetatable(ConstEffect, { __index = Effect, __call = ConstEffect.new });

--- Multiplies the value of its child by a factor.
 --
 -- Example:
 --
 --    local eff = MultiplierEffect(3, ConstEffect(7));
 --    eff:getValue() -- 3 * 7
 --
MultiplierEffect =
{
   new = function(class, factor, child)
      local self = Effect.new(class, child);
      self.factor = factor;
      return self;
   end,

   getValue = function(self)
      if self.child then
         return self.factor * self.child:getValue();
      else
         return nil;
      end
   end
};
setmetatable(MultiplierEffect,
             { __index = Effect, __call = MultiplierEffect.new  });

--- Adds a constant to the value of its child.
 --
 -- Example:
 --
 --    local eff = AdderEffect(3, ConstEffect(7));
 --    eff:getValue() -- 3 + 7
 --
AdderEffect =
{
   new = function(class, addend, child)
      local self = Effect.new(class, child);
      self.addend = addend;
      return self;
   end,

   getValue = function(self)
      if self.child then
         return self.addend + self.child:getValue();
      else
         return nil;
      end
   end
};
setmetatable(AdderEffect, { __index = Effect, __call = AdderEffect.new  });
Here is an example of use of these classes:

Code: Select all

local originalValue = ConstEffect(3.14);
print(originalValue:getValue()); -- 3.14
local me = MultiplierEffect(2, originalValue); -- me -> originalValue
print(me:getValue()); -- 6.28 = 2 * 3.14
local ae = AdderEffect(4, me); -- ae -> me -> originalValue
print(ae:getValue()); -- 10.28 = 4 + 2 * 3.14
me:remove(); -- ae -> originalValue
print(ae:getValue()); -- 7.14 = 4 + 3.14
And here is an example of how you could use it in a mod for, say, gravity:

Code: Select all

local gravityEffects = {};

local function setGravity(player, g)
   player:set_physics_override({ gravity = g });
end

function addGravityEffect(player, effect, duration)
   local oldCallback = effect.cleanup;
   effect.cleanup =
      function(self, root)
         gravityEffects[player] = root;
         setGravity(player, (root and root:getValue()) or 1.0);

         if oldCallback then oldCallback(self, root); end
      end;

   effect.child = gravityEffects[player] or ConstEffect(1.0);
   gravityEffects[player] = effect;
   setGravity(player, effect:getValue());

   minetest.after(duration, effect.remove, effect);
end

minetest.register_on_leaveplayer(
   function(player)
      local effect = gravityEffects[player];
      while effect do
         effect = effect:remove();
      end
   end);
You could also call remove() on an effect before its time runs out (or after; it wouldn't hurt anything), and re-use the Effect classes for other types of effect (speed, jump, etc.).

(All code in this post is WTFPL.)

User avatar
Wuzzy
Member
Posts: 4786
Joined: Mon Sep 24, 2012 15:01
GitHub: Wuzzy2
IRC: Wuzzy
In-game: Wuzzy
Contact:

Re: [Mod] Player effects [0.1] [playereffects]

by Wuzzy » Post

Whoa! You put a lot of thought work into it. Thanks for taking your time here. I appreciate that. This looks like you have written almost a completely new mod just to make a point.

But I’m afraid I won’t use much or even anything at all of that. This is way too complicated for a relatively simple task.
I don’t like that a part of the complexity seems to leak out to the API, which is not what I want. I want the framework to do the plumbing. I don’t want to bother the modder with “cleanup” functions and children and parents and stuff like that. I am not even sure if I understood the term “‘parent-most’” correctly.

I think this could be done much much simpler. For “layering”, I might as well add all effect values together (with a start value maybe) each time an effect is applied or cancelled to get the value I have to set. ;-)
Same is true is I work with multipliers. Then I just multiply all values (again with a start value for when no effect is in place).
As long as I stick to one operation (addition, multiplication) per effect type, I see no reason to ditch the simpler approach. It seems weird to me to use so much fancyness just to do basic arithmetics. xD

What seems to be uniquely possible with that decorator pattern are multiple effect types where some effects add and some other effects multiply. But I just can’t think of any real use case for that.
I can see an use case for using only addition: Increasing something lineary, for examle the damage dealt (+2 damage points here, +4 damage points there, and so on. Or something like that).
And I can see an use case for using only multiplication: set_physics_override. Other operations wouln’t make sense here. (if you get 2 times double speed, the overall effect would be 2*2 = 4, a quadruple speed.)
But using addition and multiplication (and maybe even more operators?) for the same property? I have no idea for what that would be good for.
It’d probably even confusing for players and I also wonder how to expose this effect mess to the HUD without loss of information. Because it makes a difference if you get an “add 10” effect first, and an “multiply by 2” effect secondly or if you get these effects vice-versa. This is too much weirdness for me already and I fear when using effects with mixed operations, the results can be pretty unpredictable. So it would be hard to balance well. This feature would then end up in being not used.

So yeah, I think I rather do it my way. :P

Oh, the framework is already able to cancel effects, even before the timer runs out. :-)

prestidigitator
Member
Posts: 647
Joined: Thu Feb 21, 2013 23:54

Re: [Mod] Player effects [0.1] [playereffects]

by prestidigitator » Post

No worries. Writing class libraries is fun. The point was actually to make the external API really simple. Maybe I should've started with an example of how it could be used. Like:

Code: Select all

-- Multiply the player's gravity by 0.5 for 10 seconds (even if there are other gravity effects already)
local myEffect = MultiplierEffect(0.5);
addGravityEffect(player, myEffect, 10);

-- Now either forget about it and let it expire after 10 seconds...
-- ...or if you want to allow the effect to be cancelled by something...
myEffect:remove();
That's it. :-) But, anyway, I won't be offended if you don't use it or anything. It was just an idea for getting around that issue of allowing only one effect. Something to keep the fires burning.

prestidigitator
Member
Posts: 647
Joined: Thu Feb 21, 2013 23:54

Re: [Mod] Player effects [0.1] [playereffects]

by prestidigitator » Post

Wuzzy wrote:What seems to be uniquely possible with that decorator pattern are multiple effect types where some effects add and some other effects multiply. But I just can’t think of any real use case for that.
I can see an use case for using only addition: Increasing something lineary, for examle the damage dealt (+2 damage points here, +4 damage points there, and so on. Or something like that).
And I can see an use case for using only multiplication: set_physics_override. Other operations wouln’t make sense here. (if you get 2 times double speed, the overall effect would be 2*2 = 4, a quadruple speed.)
But using addition and multiplication (and maybe even more operators?) for the same property? I have no idea for what that would be good for.
You pretty much got it. The idea was that it allows things to be stacked and then parts removed again while keeping the rest intact. Classes could be generic enough to be reused between different properties (even though you may not necessarily want to use all possible combinations). But it certainly might be overkill! Your idea got me thinking of fantasy roleplaying systems and stuff, where one kind of item might say it, "adds ... to running speed," and some spell might say it, "doubles all movement." Such things DO often get a little ridiculous in terms of how every different case affects another. Maybe it's a bad idea to open that kind of door. LOL.

User avatar
Wuzzy
Member
Posts: 4786
Joined: Mon Sep 24, 2012 15:01
GitHub: Wuzzy2
IRC: Wuzzy
In-game: Wuzzy
Contact:

Version 0.2 released!

by Wuzzy » Post

Version 0.2 released!

The following changes have been made:
  • You can add little icons (please only 16px×16px) for every effect type.
  • Effect types can now be hidden. Hidden effects will not be exposed to the player HUD.
  • New settings file: settings.lua. Be careful not to mess this file up for now but it should be safe if you follow the instructions and don’t delete the lines.
  • HUD list of effects can be completely disabled for all players via the settings.
  • The HUD list is now aligned to the right.
  • Autosave feature: The mod automatically saves the effect states in <WORLD PATH>/playereffects.mt every 10 seconds. Real usage has yet to show wheather this is a reasonable interval.
  • Autosave can be disabled and the autosave interval can be changed
  • New examples: /hfast (travel faster for 10s, hidden effect), /stresstest (see below)
  • The “fly” and “highjump” examples now have simple icons
  • After some stresstests (/stresstest <number of effects>), I found out that this mod seems to be safe to use with 100000 dummy effects in place without any notable performance drop. I had to tweak a bit to reach this performance. I don’t think real use will ever reach such extreme numbers, but seeing that playereffects copes well with that number is an important milestone.
  • For performance and network traffic reasons, the maximum number of effects shown in the HUD is now 20. Further effects are hidden.

You may have noticed that I forked the Magic Beans mod. Here’s the fork: magicbeans_w
It uses the Player Effects mod and I think this is an excellent demonstration of using this mod in a production environment. Magicbeans_w 1.2 is only compatible with Player Effects 0.1, I will soon update magicbeans_w to work with the Player Effects 0.2. (Edit: done!)

Here’s a screenshot of how the HUD could look now:
Image

The download link for Player Effects 0.2 lies in the attachment of the first post.

Edit: Interested developers who want to know how the Magic Beans mod was converted to use Player Effects can view this relevant commit diff. For the later addition of icons, see here.

User avatar
Wuzzy
Member
Posts: 4786
Joined: Mon Sep 24, 2012 15:01
GitHub: Wuzzy2
IRC: Wuzzy
In-game: Wuzzy
Contact:

Version 0.3.0 released!

by Wuzzy » Post

I have changed the version numbering scheme. From now on, Semantic Versioning (http://semver.org/) is used.

Version 0.3.0 is released!
This time I have made the documentation, an API cleanup and added some features.

List of changes:
  • Documentation. Yeah, finally! README.md is the file which contains a hopefully complete API and data type specification along with many explanations on how to use this mod as player, server operator and modder. If you have any problems with this file, please tell me.
  • Effect metadata. This is a measure to store additional, user-defined data when applying an effect. This effect metadata can be reused in the cancel callback again. For example, this can be used to store a HUD ID which you need again if you want to remove the HUD element again.
  • cancel_on_death = false: You now can define effect types which are not cancelled when the player dies.
  • Effects which are kept on death are shown in a light purple font in the HUD.
  • apply_effect_type now checks if the player argument is valid.
  • apply_effect_type returns the effect ID of the created effect on success. Use case: You can use this later if you want to cancel the effect manually with cancel_effect.
  • Experimental feature: The apply callback of an effect type can now “fail”. This can be used if for some reason you cannot apply the effect in this situation. This feature is experimental, buggy and may be removed again.
  • New example chat commands:
    • cancelall: Cancels all your active effects
    • blind: Makes the screen black for 5 seconds. Very experimental and messes around with the HUD, but demonstrates the usage of effect metadata.
    • null: A simply dummy effect which always fails when you try to apply it. This is there to demonstrate “failing” effects.
    • The “fly” example effect now is kept when you die.
    • The “effect apply” examples now write in your console the effect ID on success or that the effect failed.
Player Effects comes closer to version 1.0.0. The TODO list for it becomes smaller and smaller:
  • Ensuring the API functions actually help the modder and don’t get in the way
  • A lot of testing!
  • Disable examples by default
This version is still compatible to magicbeans_w 1.3.

The actual programming for this milestone is done. What is needed now are reviews and testing. I want to be sure that everything is stable before I declare version 1.0.0. I also want to stabilize the API to prevent breaking it all the time.

User avatar
Wuzzy
Member
Posts: 4786
Joined: Mon Sep 24, 2012 15:01
GitHub: Wuzzy2
IRC: Wuzzy
In-game: Wuzzy
Contact:

1.0.0 released

by Wuzzy » Post

I think all the goals of 1.0.0 are achieved now and I don’t see what I could add more for this branch.
So I release 1.0.0. See opening post for the download link.

Changes:
  • New API function to receive the remaining time of an effect: playereffects.get_remaining_effect_time
  • Performance optimizations, especially concerning the HUD
  • “cancel” callback now takes a player argument as well (for convenience)
  • disable examples by default. Use settings.lua to enable them
Read README.md to know how this all works.

Version 1.0.0 is fully backwards-compatible to 0.3.0.

My earlier stresstests were bogus; accidently I did not actually had 100000 effects, just 1000.
So I retried the stresstests. On my slow laptop, I can have a server with 10000 simutanous effects without problems; it starts to get laggy at 35000 effects. On 100000 effects, the server almost stops responding. However, I think already 10000 is a number which is large enough for real-life usage. I highly doubt that a single player ever needs more than 20 effects at once, but Player Effects could cope with that.
The performance optimizations were really needed, I think. The apply effect function was of complexity O(n), where n is the number of active effects. I managed to reduce it to O(1).

I also want you to inform you of a known bug in playereffects:
In singleplayer mode, the effect timers completely ignore any pause. So if you have effect X and there are 30 seconds left and you pause the game for 5 seconds, you have 25 seconds left when you unpause the game and not, what would be better, 30 seconds.
Sadly, this bug is currently unfixable with the current Lua API, so I released version 1.0.0 anyways.

The initial post for Player Effects is currently not accurate anymore. I hope I can update it later. The “official” documentation is in README.md now, take the initial post just as an overview.


From version 1.0.0 on, I plan to add two more major features which I already explained in the initial post: Additive effects and repeater functions. I can’t guarantee yet that this would be a backwards-compatible change. My guess would be that it would likely not backwards-compatible, sorry.
After that, I don’t plan any further features yet.

User avatar
Wuzzy
Member
Posts: 4786
Joined: Mon Sep 24, 2012 15:01
GitHub: Wuzzy2
IRC: Wuzzy
In-game: Wuzzy
Contact:

1.1.0 released

by Wuzzy » Post

Okay, here is version 1.1.0 (Zip archive in first post).

The new release has one new feature: Repeating effects! A repeating effect is an effect which is applied n times with a interval of t. A possible use case of this would be to create a “healing” effect which heals you 1 HP per second.
As always, this is documented in README.md and an example is included.

I also finally uploaded the Git repository. Here’s the project page: http://repo.or.cz/w/minetest_playereffects.git

User avatar
balthazariv
Member
Posts: 214
Joined: Mon Apr 07, 2014 15:48
Contact:

Re: [Mod] Player Effects [1.1.0] [playereffects]

by balthazariv » Post

Hello,

I don't know what that backup "Autosaving mod data to playereffects.mt"

Code: Select all

20:10:42: ACTION[ServerThread]: [playereffects] Autosaving mod data to playereffects.mt ...
20:10:42: ACTION[ServerThread]: [playereffects] Wrote playereffects data into L:\Minetest\minetest-0.4.10\bin\..\worlds\TEST2/playereffects.mt.
20:10:47: ACTION[ServerThread]: [playereffects] Autosaving mod data to playereffects.mt ...
20:10:47: ACTION[ServerThread]: [playereffects] Wrote playereffects data into L:\Minetest\minetest-0.4.10\bin\..\worlds\TEST2/playereffects.mt.
20:10:57: ACTION[ServerThread]: [playereffects] Autosaving mod data to playereffects.mt ...
20:10:57: ACTION[ServerThread]: [playereffects] Wrote playereffects data into L:\Minetest\minetest-0.4.10\bin\..\worlds\TEST2/playereffects.mt.
20:11:07: ACTION[ServerThread]: [playereffects] Autosaving mod data to playereffects.mt ...
20:11:07: ACTION[ServerThread]: [playereffects] Wrote playereffects data into L:\Minetest\minetest-0.4.10\bin\..\worlds\TEST2/playereffects.mt.
20:11:17: ACTION[ServerThread]: [playereffects] Autosaving mod data to playereffects.mt ...
20:11:17: ACTION[ServerThread]: [playereffects] Wrote playereffects data into L:\Minetest\minetest-0.4.10\bin\..\worlds\TEST2/playereffects.mt.
20:11:27: ACTION[ServerThread]: [playereffects] Autosaving mod data to playereffects.mt ...
20:11:27: ACTION[ServerThread]: [playereffects] Wrote playereffects data into L:\Minetest\minetest-0.4.10\bin\..\worlds\TEST2/playereffects.mt.
20:11:37: ACTION[ServerThread]: [playereffects] Autosaving mod data to playereffects.mt ...
20:11:37: ACTION[ServerThread]: [playereffects] Wrote playereffects data into L:\Minetest\minetest-0.4.10\bin\..\worlds\TEST2/playereffects.mt.
20:11:47: ACTION[ServerThread]: [playereffects] Autosaving mod data to playereffects.mt ...
20:11:47: ACTION[ServerThread]: [playereffects] Wrote playereffects data into L:\Minetest\minetest-0.4.10\bin\..\worlds\TEST2/playereffects.mt.
20:11:57: ACTION[ServerThread]: [playereffects] Autosaving mod data to playereffects.mt ...
20:11:57: ACTION[ServerThread]: [playereffects] Wrote playereffects data into L:\Minetest\minetest-0.4.10\bin\..\worlds\TEST2/playereffects.mt.
20:12:07: ACTION[ServerThread]: [playereffects] Autosaving mod data to playereffects.mt ...
20:12:07: ACTION[ServerThread]: [playereffects] Wrote playereffects data into L:\Minetest\minetest-0.4.10\bin\..\worlds\TEST2/playereffects.mt.
20:12:17: ACTION[ServerThread]: [playereffects] Autosaving mod data to playereffects.mt ...
20:12:17: ACTION[ServerThread]: [playereffects] Wrote playereffects data into L:\Minetest\minetest-0.4.10\bin\..\worlds\TEST2/playereffects.mt.
20:12:27: ACTION[ServerThread]: [playereffects] Autosaving mod data to playereffects.mt ...
20:12:27: ACTION[ServerThread]: [playereffects] Wrote playereffects data into L:\Minetest\minetest-0.4.10\bin\..\worlds\TEST2/playereffects.mt.
20:12:37: ACTION[ServerThread]: [playereffects] Autosaving mod data to playereffects.mt ...
20:12:37: ACTION[ServerThread]: [playereffects] Wrote playereffects data into L:\Minetest\minetest-0.4.10\bin\..\worlds\TEST2/playereffects.mt.
20:12:47: ACTION[ServerThread]: [playereffects] Autosaving mod data to playereffects.mt ...
20:12:47: ACTION[ServerThread]: [playereffects] Wrote playereffects data into L:\Minetest\minetest-0.4.10\bin\..\worlds\TEST2/playereffects.mt.
20:12:57: ACTION[ServerThread]: [playereffects] Autosaving mod data to playereffects.mt ...
20:12:57: ACTION[ServerThread]: [playereffects] Wrote playereffects data into L:\Minetest\minetest-0.4.10\bin\..\worlds\TEST2/playereffects.mt.
20:13:07: ACTION[ServerThread]: [playereffects] Autosaving mod data to playereffects.mt ...
20:13:07: ACTION[ServerThread]: [playereffects] Wrote playereffects data into L:\Minetest\minetest-0.4.10\bin\..\worlds\TEST2/playereffects.mt.
20:13:17: ACTION[ServerThread]: [playereffects] Autosaving mod data to playereffects.mt ...
20:13:17: ACTION[ServerThread]: [playereffects] Wrote playereffects data into L:\Minetest\minetest-0.4.10\bin\..\worlds\TEST2/playereffects.mt.
20:13:27: ACTION[ServerThread]: [playereffects] Autosaving mod data to playereffects.mt ...
20:13:27: ACTION[ServerThread]: [playereffects] Wrote playereffects data into L:\Minetest\minetest-0.4.10\bin\..\worlds\TEST2/playereffects.mt.
In the file playereffects.mt i have just

Code: Select all

return { ["inactive_effects"] = {  }, ["last_effect_id"] = 0 }
As against that prevents the loading of my mods

Thanks

User avatar
Wuzzy
Member
Posts: 4786
Joined: Mon Sep 24, 2012 15:01
GitHub: Wuzzy2
IRC: Wuzzy
In-game: Wuzzy
Contact:

Re: [Mod] Player Effects [1.1.0] [playereffects]

by Wuzzy » Post

This is not an error. And the particular file you have means you haven’t experienced any effects so far.
The mod uses the file to store all the active effects. It is saved regularly so all the effects can be restored with a precision of 10 seconds even if the server crashes.

But maybe I should try to reduce the number of times this mod autosaves the effect data. Especially if nothing actually changes. Do you want such a change or isn’t it important enough for you?

Or is the only thing you care about just that the log file is flooded with these messages?
As against that prevents the loading of my mods
I do not understand this.

User avatar
LanceJZ
New member
Posts: 5
Joined: Thu Sep 11, 2014 08:54
GitHub: Lancejz
In-game: Purple
Location: Seattle
Contact:

Re: [Mod] Player Effects [1.1.0] [playereffects]

by LanceJZ » Post

Hey, I could use something like this for my RPG mod I've started working on. Are you still working on this mod, because I hope you are.

User avatar
Wuzzy
Member
Posts: 4786
Joined: Mon Sep 24, 2012 15:01
GitHub: Wuzzy2
IRC: Wuzzy
In-game: Wuzzy
Contact:

Re: [Mod] Player Effects [1.1.0] [playereffects]

by Wuzzy » Post

I will continue working on this whenever I feel like it. :P
Currently, I do not feel like it.

User avatar
Wuzzy
Member
Posts: 4786
Joined: Mon Sep 24, 2012 15:01
GitHub: Wuzzy2
IRC: Wuzzy
In-game: Wuzzy
Contact:

Patch Release: 1.1.1

by Wuzzy » Post

Hi! I just made a patch release, the new version is now 1.1.1.

This fixes a bug leaking a variable into global space which caused an error message in the chatlog in the recent Minetest version. That's all, bye!

TeTpaAka
Member
Posts: 141
Joined: Sat Dec 28, 2013 21:54

Re: [Mod] Player Effects [1.1.1] [playereffects]

by TeTpaAka » Post

Hi Wuzzy,

Is there a way to give priorities to effects?
What I means is, right now, when an effect is applied, every other effect of the same group is disabled. Would it be possible to give the effects a priority, so that the effect with the higher priority continues? Or is there another way to achieve this?
That would make some effects of my Magic mod more powerful.

User avatar
davidthecreator
Member
Posts: 452
Joined: Mon Aug 18, 2014 19:48
GitHub: daviddoesminetest
In-game: DavidDoesMinetest
Location: Lithuania

Re: [Mod] Player Effects [1.1.1] [playereffects]

by davidthecreator » Post

Can i make nodes or entities give player effects when touched?

User avatar
Wuzzy
Member
Posts: 4786
Joined: Mon Sep 24, 2012 15:01
GitHub: Wuzzy2
IRC: Wuzzy
In-game: Wuzzy
Contact:

Re: [Mod] Player Effects [1.1.1] [playereffects]

by Wuzzy » Post

@davidthecreator: No, the player effects stricly apply to players only.

@TeTpaAka: No. Unless I update this mod, of course (sorry for late answer). But I am not sure what exactly you want here.

TeTpaAka
Member
Posts: 141
Joined: Sat Dec 28, 2013 21:54

Re: [Mod] Player Effects [1.1.1] [playereffects]

by TeTpaAka » Post

Wuzzy wrote:@TeTpaAka: No. Unless I update this mod, of course (sorry for late answer). But I am not sure what exactly you want here.
For example:
  1. A player gets hit by a spell that makes him blind for 20 seconds.
  2. After 5 seconds, he gets hit again, this time with a spell that blinds him for 5 seconds. This spell overrides the previous one although it is less powerful. This way, you can heal yourself by hurting yourself with a weaker attack.
Another example:
  1. A player gains temporarily the ability to fly.
  2. He gets hit with a spell that temporarily disables flight.
  3. When he gets hit by another spell that grants flight, the seconds point gets invalid, since it gets overridden by this.

User avatar
Wuzzy
Member
Posts: 4786
Joined: Mon Sep 24, 2012 15:01
GitHub: Wuzzy2
IRC: Wuzzy
In-game: Wuzzy
Contact:

Re: [Mod] Player Effects [1.1.1] [playereffects]

by Wuzzy » Post

TeTpaAka, thanks for your remarks. Yes, these are all correct and in the current version, stuff like this can not be prevented. :-(
It turns out this mod really needs these additive effects or some sort of “effect stacks” to properly handle this stuff. I also need to put some thought into how the effect timers are treated.

I am just too lazy to do this work right now, sorry. xD

User avatar
davidthecreator
Member
Posts: 452
Joined: Mon Aug 18, 2014 19:48
GitHub: daviddoesminetest
In-game: DavidDoesMinetest
Location: Lithuania

Re: [Mod] Player Effects [1.1.1] [playereffects]

by davidthecreator » Post

I ment are nodes or entities able to give the efects to players not players to entities or nodes for lets say: some one makes "poisoned" debuff that can be given to player using a command or drinking a potion from your potions mod but the maker of this debuff makes a poisoned spyke node and he wants it to give the debuff to a player as soon as it touches it is that possible

User avatar
Wuzzy
Member
Posts: 4786
Joined: Mon Sep 24, 2012 15:01
GitHub: Wuzzy2
IRC: Wuzzy
In-game: Wuzzy
Contact:

Re: [Mod] Player Effects [1.1.1] [playereffects]

by Wuzzy » Post

Yes, this is certainly possible. Nodes and entities can use their own code to cause a player effect. In fact, I have already demonstrated this possibility in my (still very WIP) subgame Weird. If you get into the frost biome, there is one ice/stone monster which throws ice balls, if it hits you, you get frozen for 5 seconds. Being frozen is a player effect and the ice ball is an entity. :-)
Basically everything which has code and is able to call the Player Effects functions should be able to apply player effects to any player. Node callbacks, entitiy functions, your own mod, whatever. It does not matter.

However, detecting when a player *touches* a certain node is quite tricky right now, but this has nothing to do with this mod. One could theoretically detect when a player is near a certain node. Maybe you want to look into the code of the pressure code of Mesecons, here the node just regularily checks if a player stands above the node.

User avatar
davidthecreator
Member
Posts: 452
Joined: Mon Aug 18, 2014 19:48
GitHub: daviddoesminetest
In-game: DavidDoesMinetest
Location: Lithuania

Re: [Mod] Player Effects [1.1.1] [playereffects]

by davidthecreator » Post

If you say its possible i say: aaaaaaaaaawwwwwwwwwwyyyyyyyyyeeeeeeeeeeaaaaaaaa!!!!
And also: i guess after a little play arround with mobs that mihght poison player or so i should also dont forget to make an antidote couse armor wont help in this case

User avatar
MineYoshi
Member
Posts: 5373
Joined: Wed Jul 08, 2015 13:20
Contact:

Re: [Mod] Player Effects [1.1.1] [playereffects]

by MineYoshi » Post

wuzzy add a new mod in the list of mod that uses your mod is my Retroblocks mod please here is the link:
viewtopic.php?f=9&t=13118&p=188502#p188502
Have a nice day! :D

Byakuren
Member
Posts: 818
Joined: Tue Apr 14, 2015 01:59
GitHub: raymoo
IRC: Hijiri
In-game: Raymoo + Clownpiece

Re: [Mod] Player Effects [1.1.1] [playereffects]

by Byakuren » Post

A simpler way to implement additive effect groups could be to have the effects be monoidal. What this means is that when you define additive effects, you don't define an "apply" function. Instead, you define for each effect type in the additive group a data value associated with the effect. This can be any value. Then for the entire effect group, you want to define:
  • A combination function: A function that will combine two data values. For example, if your effects give gravity multipliers, this function would just multiply them together.
  • An identity: A "default" value, to be used when no effect in the effect group is active. For gravity multipliers, this would be 1.
  • An application function: It takes a data value and applies the effects.
What you would do is keep track of all of the active effects for each effect group. Whenever this list of active effects changes, you calculate the current data value by using the combination function to combine the whole list, and then you apply it to the player using the application function. If there are no more effects, just apply the application function to the identity, which will give default behavior. If the identity value is truly an identity for the combination function, you can handle both empty and nonempty lists in the same case: you combine the identity with the contents of the list of active data. If it's empty, you get just the identity, and if it's not empty, the identity doesn't affect the result of combining the list. But for this to work, users of the library are obligated to make sure the identity is really an identity, so it might be better to handle them in separate cases anyway.

I think this is an elegant solution, and some common effect uses would be covered:
  • Anything involving numerical addition or multiplication - Combination function is addition or multiplication, and the identity is 0 or 1, respectively.
  • Stronger effects overriding only during their duration - Suppose you want a longer-lasting weak effect to remain even after a strong similar effect wears off. Then your combination function could just choose the maximum-strength effect. The identity isn't so obvious though. What you can do is make the identity nil, and when the application function is applied to nil, it just cancels the effects. To be a proper identity, the combination function should always pick a non-nil value as the maximum if it can. This method of using "nil" as the identity in fact works for any combination function, so you can do this when there is no natural-feeling identity.
  • Effects with explicit priorities - Similar to the above, but comparing their priorities rather than potency. The above one could be considered a special case of this.
One limitation I see already is that you wouldn't have a proper monoid if you mixed additions and multiplications. To cover these, you can weaken the requirements on the users of the library, so that the combination function doesn't have to be associative (which monoids require), but still require the identity be an identity. You as the library-writer would have to guarantee a certain application order though, like earliest-applied to latest-applied, so that users of the library know what to expect.

Another issue is that if you want an effect to affect multiple monoidal effect groups that have a different kind of effect data, there wouldn't be a way to handle it in this system. One way to work around that would be to instead have a table of effect data indexed by effect groups, similar to how tool capabilities have numbers associated with them. Then for each effect group, you would just use the provided value in the table.

An effect could affect both exclusive and monoidal effect groups, since the original apply function would not be used in the monoidal effect group, and the extra data for the monoidal effect groups would not affect the exclusive effect groups.

Another thing this method would be unable to do is cancel effects permanently, since the effects cannot remove other effects, and when they wear off, the other effects will remain. The most you could do is temporarily mask the effects. Arguably you would want to remove effects from outside the framework of monoidal effects, though.

EDIT:: Another possibly useful feature would be to have effect groups that are just tags, and don't cancel or add together or anything. Then, for example, you could cancel all effects in the group "magical", if you are dispelling magical effects.

EDIT2:: If additive effects are included, then it would make sense to allow infinite-duration effects as well, because then you can have permanent effects that stack with temporary ones nicely.
Last edited by Byakuren on Sun Jan 03, 2016 21:02, edited 1 time in total.
Every time a mod API is left undocumented, a koala dies.

Byakuren
Member
Posts: 818
Joined: Tue Apr 14, 2015 01:59
GitHub: raymoo
IRC: Hijiri
In-game: Raymoo + Clownpiece

Re: [Mod] Player Effects [1.1.1] [playereffects]

by Byakuren » Post

I've started using playereffect in magical_realm.

Is there any reason you put effect cancellation into a minetest.after instead of doing it in the step function along with the HUD? You are already calculating the time left, so it would only be an extra comparison, except when you have to cancel effects (or apply repeating effects). I'm getting long delays in the cancellation of some effects, so that the HUD sometimes goes even to -60 seconds. minetest.after already uses globalstep, so I don't think it would be much less efficient.

Here is the effect in question: https://github.com/raymoo/magical_realm ... t.lua#L262
Every time a mod API is left undocumented, a koala dies.

Post Reply

Who is online

Users browsing this forum: No registered users and 21 guests