forked from mtcontrib/minetest_playereffects
Compare commits
7 Commits
Author | SHA1 | Date | |
---|---|---|---|
9b3b4d1c32 | |||
e24c55d0bd | |||
08b2c5fd22 | |||
f8d70283d1 | |||
51547f2e70 | |||
a043aadeff | |||
c87592a9cf |
14
README.md
14
README.md
@ -1,6 +1,6 @@
|
||||
# Player Effects
|
||||
## Summary
|
||||
This is an framework for assigning temporary status effects to players. This mod is aimed to modders and maybe interested people. This framework is a work in progress and not finished.
|
||||
This is an framework for assigning temporary status effects to players. This mod is aimed to modders and maybe interested people.
|
||||
|
||||
## Profile
|
||||
* Name: Player Effects
|
||||
@ -65,11 +65,19 @@ Normally you don’t need to read or edit fields of this table. Use `playereffec
|
||||
#### Effect group
|
||||
An effect group is basically a concept. Any effect type can be member of any number of effect groups. The main point of effect groups is to find effects which affect the same property. For example, an effect which makes you faster and another effect which makes you slower both affect the same property: speed. The group for that then would be the string `"speed"`. See also `examples.lua`, which includes the effects `high_speed` and `low_speed`.
|
||||
|
||||
Currently, the main rule of Player Effects requires that there can only be one effect in place. Don’t worry, Player Effects already does that job for you. Back to the example: it is possible to be fast and it is possible to be slow. But it is not possible to be fast `and` slow at the same time. Player Effects ensures that by cancelling all conflicting concepts before applying a new one.
|
||||
Currently, the main rule of Player Effects requires that there can only be one effect in place. Player Effects already does that job for you. Back to the example: it is possible to be fast and it is possible to be slow. But it is not possible to be fast *and* slow at the same time. Player Effects ensures that by cancelling all conflicting concepts before applying a new one.
|
||||
|
||||
The concept of groups may be changed or extended in the future.
|
||||
|
||||
You can invent effect groups (like the groups in Minetest) on the fly. A group is just a string. Practically, you should use groups which other people use.
|
||||
The following effect group names have standardized meanings and should solely be used for their intended purpose:
|
||||
|
||||
* `speed`: Affects the player speed set by the `speed` value of `set_physics_override`
|
||||
* `gravity`: Affects the player gravity set by the `gravity` value of `set_physics_override`
|
||||
* `jump`: Affects the player jump strength set by the `jump` value of `set_physics_override`
|
||||
* `health`: Affects the player health
|
||||
* `breath`: Affects the player breath
|
||||
|
||||
You can also invent effect groups (like the groups in Minetest) on the fly. A group is just a string. Practically, you should use groups which other people use.
|
||||
|
||||
#### Effect (`effect`)
|
||||
An effect is an current change of a player property (like speed, jump height, and so on). It is the realization of an effect type. All effects are temporary. There are currently two types of effects: Repeating and non-repeating. Non-repeating effects call their `apply` callback once when they are created. Repeating effects call their apply callback multiple times with a specified interval. By default, effects are non-repeating.
|
||||
|
@ -115,11 +115,11 @@ playereffects.register_effect_type("slowregen", "Slow Regeneration", "heart.png"
|
||||
function(player)
|
||||
player:set_hp(player:get_hp()+1)
|
||||
end,
|
||||
nil, nil, nil, 15
|
||||
nil, nil, nil, 3
|
||||
)
|
||||
|
||||
|
||||
-- Dummy effect for the stree test
|
||||
-- Dummy effect for the stress test
|
||||
playereffects.register_effect_type("stress", "Stress Test Effect", nil, {},
|
||||
function(player)
|
||||
end,
|
||||
|
172
init.lua
172
init.lua
@ -98,32 +98,30 @@ function playereffects.register_effect_type(effect_type_id, description, icon, g
|
||||
minetest.log("action", "[playereffects] Effect type "..effect_type_id.." registered!")
|
||||
end
|
||||
|
||||
function playereffects.apply_effect_type(effect_type_id, duration, player, repeat_interval_time_left)
|
||||
function playereffects.apply_effect_type(effect_type_id, duration, entity, repeat_interval_time_left)
|
||||
local start_time = os.time()
|
||||
local is_player = false
|
||||
if(type(player)=="userdata") then
|
||||
if(player.is_player ~= nil) then
|
||||
if(player:is_player() == true) then
|
||||
if(type(entity)=="userdata") then
|
||||
if(entity.is_player ~= nil) then
|
||||
if(entity:is_player() == true) then
|
||||
is_player = true
|
||||
end
|
||||
end
|
||||
end
|
||||
if(is_player == false) then
|
||||
minetest.log("error", "[playereffects] Attempted to apply effect type "..effect_type_id.." to a non-player!")
|
||||
return false
|
||||
end
|
||||
|
||||
local playername = player:get_player_name()
|
||||
local playername = entity:get_player_name()
|
||||
local groups = playereffects.effect_types[effect_type_id].groups
|
||||
for k,v in pairs(groups) do
|
||||
playereffects.cancel_effect_group(v, playername)
|
||||
playereffects.cancel_effect_group(v, entity)
|
||||
end
|
||||
|
||||
local metadata
|
||||
if(playereffects.effect_types[effect_type_id].repeat_interval == nil) then
|
||||
local status = playereffects.effect_types[effect_type_id].apply(player)
|
||||
local status = playereffects.effect_types[effect_type_id].apply(entity)
|
||||
if(status == false) then
|
||||
minetest.log("action", "[playereffects] Attempt to apply effect type "..effect_type_id.." to player "..playername.." failed!")
|
||||
if is_player then
|
||||
minetest.log("action", "[playereffects] Attempt to apply effect type "..effect_type_id.." to player "..playername.." failed!")
|
||||
end
|
||||
return false
|
||||
else
|
||||
metadata = status
|
||||
@ -132,32 +130,8 @@ function playereffects.apply_effect_type(effect_type_id, duration, player, repea
|
||||
|
||||
|
||||
local effect_id = playereffects.next_effect_id()
|
||||
local smallest_hudpos
|
||||
local biggest_hudpos = -1
|
||||
local free_hudpos
|
||||
if(playereffects.hudinfos[playername] == nil) then
|
||||
playereffects.hudinfos[playername] = {}
|
||||
end
|
||||
local hudinfos = playereffects.hudinfos[playername]
|
||||
for effect_id, hudinfo in pairs(hudinfos) do
|
||||
local hudpos = hudinfo.pos
|
||||
if(hudpos > biggest_hudpos) then
|
||||
biggest_hudpos = hudpos
|
||||
end
|
||||
if(smallest_hudpos == nil) then
|
||||
smallest_hudpos = hudpos
|
||||
elseif(hudpos < smallest_hudpos) then
|
||||
smallest_hudpos = hudpos
|
||||
end
|
||||
end
|
||||
if(smallest_hudpos == nil) then
|
||||
free_hudpos = 0
|
||||
elseif(smallest_hudpos >= 0) then
|
||||
free_hudpos = smallest_hudpos - 1
|
||||
else
|
||||
free_hudpos = biggest_hudpos + 1
|
||||
end
|
||||
|
||||
-- repeat stuff
|
||||
local repeat_interval = playereffects.effect_types[effect_type_id].repeat_interval
|
||||
if(repeat_interval ~= nil) then
|
||||
if(repeat_interval_time_left == nil) then
|
||||
@ -165,18 +139,47 @@ function playereffects.apply_effect_type(effect_type_id, duration, player, repea
|
||||
end
|
||||
end
|
||||
|
||||
--[[ show no more than 20 effects on the screen, so that hud_update does not need to be called so often ]]
|
||||
local text_id, icon_id
|
||||
if(free_hudpos <= 20) then
|
||||
text_id, icon_id = playereffects.hud_effect(effect_type_id, player, free_hudpos, duration, repeat_interval_time_left)
|
||||
local hudinfo = {
|
||||
text_id = text_id,
|
||||
icon_id = icon_id,
|
||||
pos = free_hudpos,
|
||||
}
|
||||
playereffects.hudinfos[playername][effect_id] = hudinfo
|
||||
else
|
||||
text_id, icon_id = nil, nil
|
||||
-- Handle HUD
|
||||
if is_player then
|
||||
local smallest_hudpos
|
||||
local biggest_hudpos = -1
|
||||
local free_hudpos
|
||||
if(playereffects.hudinfos[playername] == nil) then
|
||||
playereffects.hudinfos[playername] = {}
|
||||
end
|
||||
local hudinfos = playereffects.hudinfos[playername]
|
||||
for effect_id, hudinfo in pairs(hudinfos) do
|
||||
local hudpos = hudinfo.pos
|
||||
if(hudpos > biggest_hudpos) then
|
||||
biggest_hudpos = hudpos
|
||||
end
|
||||
if(smallest_hudpos == nil) then
|
||||
smallest_hudpos = hudpos
|
||||
elseif(hudpos < smallest_hudpos) then
|
||||
smallest_hudpos = hudpos
|
||||
end
|
||||
end
|
||||
if(smallest_hudpos == nil) then
|
||||
free_hudpos = 0
|
||||
elseif(smallest_hudpos >= 0) then
|
||||
free_hudpos = smallest_hudpos - 1
|
||||
else
|
||||
free_hudpos = biggest_hudpos + 1
|
||||
end
|
||||
|
||||
--[[ show no more than 20 effects on the screen, so that hud_update does not need to be called so often ]]
|
||||
local text_id, icon_id
|
||||
if(free_hudpos <= 20) then
|
||||
text_id, icon_id = playereffects.hud_effect(effect_type_id, entity, free_hudpos, duration, repeat_interval_time_left)
|
||||
local hudinfo = {
|
||||
text_id = text_id,
|
||||
icon_id = icon_id,
|
||||
pos = free_hudpos,
|
||||
}
|
||||
playereffects.hudinfos[playername][effect_id] = hudinfo
|
||||
else
|
||||
text_id, icon_id = nil, nil
|
||||
end
|
||||
end
|
||||
|
||||
local effect = {
|
||||
@ -193,7 +196,7 @@ function playereffects.apply_effect_type(effect_type_id, duration, player, repea
|
||||
playereffects.effects[effect_id] = effect
|
||||
|
||||
if(repeat_interval ~= nil) then
|
||||
minetest.after(repeat_interval_time_left, playereffects.repeater, effect_id, duration, player, playereffects.effect_types[effect_type_id].apply)
|
||||
minetest.after(repeat_interval_time_left, playereffects.repeater, effect_id, duration, entity, playereffects.effect_types[effect_type_id].apply)
|
||||
else
|
||||
minetest.after(duration, function(effect_id) playereffects.cancel_effect(effect_id) end, effect_id)
|
||||
end
|
||||
@ -201,11 +204,11 @@ function playereffects.apply_effect_type(effect_type_id, duration, player, repea
|
||||
return effect_id
|
||||
end
|
||||
|
||||
function playereffects.repeater(effect_id, repetitions, player, apply)
|
||||
function playereffects.repeater(effect_id, repetitions, entity, apply)
|
||||
local effect = playereffects.effects[effect_id]
|
||||
if(effect ~= nil) then
|
||||
if(effect ~= nil and entity ~= nil and entity:get_luaentity() ~= nil) then
|
||||
local repetitions = effect.time_left
|
||||
apply(player)
|
||||
apply(entity)
|
||||
repetitions = repetitions - 1
|
||||
effect.time_left = repetitions
|
||||
if(repetitions <= 0) then
|
||||
@ -219,15 +222,15 @@ function playereffects.repeater(effect_id, repetitions, player, apply)
|
||||
playereffects.repeater,
|
||||
effect_id,
|
||||
repetitions,
|
||||
player,
|
||||
entity,
|
||||
apply
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function playereffects.cancel_effect_type(effect_type_id, cancel_all, playername)
|
||||
local effects = playereffects.get_player_effects(playername)
|
||||
function playereffects.cancel_effect_type(effect_type_id, cancel_all, entity_or_playername)
|
||||
local effects = playereffects.get_player_effects(entity_or_playername)
|
||||
if(cancel_all==nil) then cancel_all = false end
|
||||
for e=1, #effects do
|
||||
if(effects[e].effect_type_id == effect_type_id) then
|
||||
@ -239,8 +242,8 @@ function playereffects.cancel_effect_type(effect_type_id, cancel_all, playername
|
||||
end
|
||||
end
|
||||
|
||||
function playereffects.cancel_effect_group(groupname, playername)
|
||||
local effects = playereffects.get_player_effects(playername)
|
||||
function playereffects.cancel_effect_group(groupname, entity_or_playername)
|
||||
local effects = playereffects.get_player_effects(entity_or_playername)
|
||||
for e=1,#effects do
|
||||
local effect = effects[e]
|
||||
local thesegroups = playereffects.effect_types[effect.effect_type_id].groups
|
||||
@ -268,22 +271,35 @@ function playereffects.cancel_effect(effect_id)
|
||||
local effect = playereffects.effects[effect_id]
|
||||
if(effect ~= nil) then
|
||||
local player = minetest.get_player_by_name(effect.playername)
|
||||
local hudinfo = playereffects.hudinfos[effect.playername][effect_id]
|
||||
if(hudinfo ~= nil) then
|
||||
if(hudinfo.text_id~=nil) then
|
||||
player:hud_remove(hudinfo.text_id)
|
||||
if player then
|
||||
local hudinfo = playereffects.hudinfos[effect.playername][effect_id]
|
||||
if(hudinfo ~= nil) then
|
||||
if(hudinfo.text_id~=nil) then
|
||||
player:hud_remove(hudinfo.text_id)
|
||||
end
|
||||
if(hudinfo.icon_id~=nil) then
|
||||
player:hud_remove(hudinfo.icon_id)
|
||||
end
|
||||
playereffects.hudinfos[effect.playername][effect_id] = nil
|
||||
end
|
||||
if(hudinfo.icon_id~=nil) then
|
||||
player:hud_remove(hudinfo.icon_id)
|
||||
end
|
||||
playereffects.hudinfos[effect.playername][effect_id] = nil
|
||||
|
||||
-- TODO: Implement cancellation for non-players
|
||||
playereffects.effect_types[effect.effect_type_id].cancel(effect, player)
|
||||
end
|
||||
playereffects.effect_types[effect.effect_type_id].cancel(effect, player)
|
||||
playereffects.effects[effect_id] = nil
|
||||
end
|
||||
end
|
||||
|
||||
function playereffects.get_player_effects(playername)
|
||||
function playereffects.get_player_effects(entity_or_playername)
|
||||
-- TODO: support entity
|
||||
local playername = ""
|
||||
if type(entity_or_playername) == "string" then
|
||||
playername = entity_or_playername
|
||||
elseif type(entity_or_playername) == "userdata" and entity_or_playername:is_player() then
|
||||
playername = entity_or_playername:get_player_name()
|
||||
else
|
||||
return {}
|
||||
end
|
||||
if(minetest.get_player_by_name(playername) ~= nil) then
|
||||
local effects = {}
|
||||
for k,v in pairs(playereffects.effects) do
|
||||
@ -297,8 +313,8 @@ function playereffects.get_player_effects(playername)
|
||||
end
|
||||
end
|
||||
|
||||
function playereffects.has_effect_type(playername, effect_type_id)
|
||||
local pe = playereffects.get_player_effects(playername)
|
||||
function playereffects.has_effect_type(entity_or_playername, effect_type_id)
|
||||
local pe = playereffects.get_player_effects(entity_or_playername)
|
||||
for i=1,#pe do
|
||||
if pe[i].effect_type_id == effect_type_id then
|
||||
return true
|
||||
@ -314,11 +330,13 @@ function playereffects.save_to_file()
|
||||
local inactive_effects = {}
|
||||
for id,effecttable in pairs(playereffects.inactive_effects) do
|
||||
local playername = id
|
||||
if(inactive_effects[playername] == nil) then
|
||||
inactive_effects[playername] = {}
|
||||
end
|
||||
for i=1,#effecttable do
|
||||
table.insert(inactive_effects[playername], effecttable[i])
|
||||
if playername ~= "" then
|
||||
if(inactive_effects[playername] == nil) then
|
||||
inactive_effects[playername] = {}
|
||||
end
|
||||
for i=1,#effecttable do
|
||||
table.insert(inactive_effects[playername], effecttable[i])
|
||||
end
|
||||
end
|
||||
end
|
||||
for id,effect in pairs(playereffects.effects) do
|
||||
@ -342,7 +360,9 @@ function playereffects.save_to_file()
|
||||
if(inactive_effects[effect.playername] == nil) then
|
||||
inactive_effects[effect.playername] = {}
|
||||
end
|
||||
table.insert(inactive_effects[effect.playername], new_effect)
|
||||
if effect.playername ~= "" then
|
||||
table.insert(inactive_effects[effect.playername], new_effect)
|
||||
end
|
||||
end
|
||||
|
||||
savetable.inactive_effects = inactive_effects
|
||||
|
Reference in New Issue
Block a user