1
0
mirror of https://repo.or.cz/minetest_playereffects.git synced 2025-07-03 08:40:40 +02:00

1 Commits

Author SHA1 Message Date
0f92ce7b10 Réduit les messages de la console. 2018-09-02 18:43:08 +02:00
3 changed files with 83 additions and 111 deletions

View File

@ -1,6 +1,6 @@
# Player Effects # Player Effects
## Summary ## Summary
This is an framework for assigning temporary status effects to players. This mod is aimed to modders and maybe interested people. 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.
## Profile ## Profile
* Name: Player Effects * Name: Player Effects
@ -65,19 +65,11 @@ Normally you dont need to read or edit fields of this table. Use `playereffec
#### Effect group #### 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`. 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. 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. Dont 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.
The concept of groups may be changed or extended in the future. The concept of groups may be changed or extended in the future.
The following effect group names have standardized meanings and should solely be used for their intended purpose: 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.
* `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`) #### 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. 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.

View File

@ -115,11 +115,11 @@ playereffects.register_effect_type("slowregen", "Slow Regeneration", "heart.png"
function(player) function(player)
player:set_hp(player:get_hp()+1) player:set_hp(player:get_hp()+1)
end, end,
nil, nil, nil, 3 nil, nil, nil, 15
) )
-- Dummy effect for the stress test -- Dummy effect for the stree test
playereffects.register_effect_type("stress", "Stress Test Effect", nil, {}, playereffects.register_effect_type("stress", "Stress Test Effect", nil, {},
function(player) function(player)
end, end,

176
init.lua
View File

@ -98,30 +98,32 @@ function playereffects.register_effect_type(effect_type_id, description, icon, g
minetest.log("action", "[playereffects] Effect type "..effect_type_id.." registered!") minetest.log("action", "[playereffects] Effect type "..effect_type_id.." registered!")
end end
function playereffects.apply_effect_type(effect_type_id, duration, entity, repeat_interval_time_left) function playereffects.apply_effect_type(effect_type_id, duration, player, repeat_interval_time_left)
local start_time = os.time() local start_time = os.time()
local is_player = false local is_player = false
if(type(entity)=="userdata") then if(type(player)=="userdata") then
if(entity.is_player ~= nil) then if(player.is_player ~= nil) then
if(entity:is_player() == true) then if(player:is_player() == true) then
is_player = true is_player = true
end end
end 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 = entity:get_player_name() local playername = player:get_player_name()
local groups = playereffects.effect_types[effect_type_id].groups local groups = playereffects.effect_types[effect_type_id].groups
for k,v in pairs(groups) do for k,v in pairs(groups) do
playereffects.cancel_effect_group(v, entity) playereffects.cancel_effect_group(v, playername)
end end
local metadata local metadata
if(playereffects.effect_types[effect_type_id].repeat_interval == nil) then if(playereffects.effect_types[effect_type_id].repeat_interval == nil) then
local status = playereffects.effect_types[effect_type_id].apply(entity) local status = playereffects.effect_types[effect_type_id].apply(player)
if(status == false) then if(status == false) then
if is_player then minetest.log("action", "[playereffects] Attempt to apply effect type "..effect_type_id.." to player "..playername.." failed!")
minetest.log("action", "[playereffects] Attempt to apply effect type "..effect_type_id.." to player "..playername.." failed!")
end
return false return false
else else
metadata = status metadata = status
@ -130,8 +132,32 @@ function playereffects.apply_effect_type(effect_type_id, duration, entity, repea
local effect_id = playereffects.next_effect_id() 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 local repeat_interval = playereffects.effect_types[effect_type_id].repeat_interval
if(repeat_interval ~= nil) then if(repeat_interval ~= nil) then
if(repeat_interval_time_left == nil) then if(repeat_interval_time_left == nil) then
@ -139,47 +165,18 @@ function playereffects.apply_effect_type(effect_type_id, duration, entity, repea
end end
end end
-- Handle HUD --[[ show no more than 20 effects on the screen, so that hud_update does not need to be called so often ]]
if is_player then local text_id, icon_id
local smallest_hudpos if(free_hudpos <= 20) then
local biggest_hudpos = -1 text_id, icon_id = playereffects.hud_effect(effect_type_id, player, free_hudpos, duration, repeat_interval_time_left)
local free_hudpos local hudinfo = {
if(playereffects.hudinfos[playername] == nil) then text_id = text_id,
playereffects.hudinfos[playername] = {} icon_id = icon_id,
end pos = free_hudpos,
local hudinfos = playereffects.hudinfos[playername] }
for effect_id, hudinfo in pairs(hudinfos) do playereffects.hudinfos[playername][effect_id] = hudinfo
local hudpos = hudinfo.pos else
if(hudpos > biggest_hudpos) then text_id, icon_id = nil, nil
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 end
local effect = { local effect = {
@ -196,7 +193,7 @@ function playereffects.apply_effect_type(effect_type_id, duration, entity, repea
playereffects.effects[effect_id] = effect playereffects.effects[effect_id] = effect
if(repeat_interval ~= nil) then if(repeat_interval ~= nil) then
minetest.after(repeat_interval_time_left, playereffects.repeater, effect_id, duration, entity, playereffects.effect_types[effect_type_id].apply) minetest.after(repeat_interval_time_left, playereffects.repeater, effect_id, duration, player, playereffects.effect_types[effect_type_id].apply)
else else
minetest.after(duration, function(effect_id) playereffects.cancel_effect(effect_id) end, effect_id) minetest.after(duration, function(effect_id) playereffects.cancel_effect(effect_id) end, effect_id)
end end
@ -204,11 +201,11 @@ function playereffects.apply_effect_type(effect_type_id, duration, entity, repea
return effect_id return effect_id
end end
function playereffects.repeater(effect_id, repetitions, entity, apply) function playereffects.repeater(effect_id, repetitions, player, apply)
local effect = playereffects.effects[effect_id] local effect = playereffects.effects[effect_id]
if(effect ~= nil and entity ~= nil and entity:get_luaentity() ~= nil) then if(effect ~= nil) then
local repetitions = effect.time_left local repetitions = effect.time_left
apply(entity) apply(player)
repetitions = repetitions - 1 repetitions = repetitions - 1
effect.time_left = repetitions effect.time_left = repetitions
if(repetitions <= 0) then if(repetitions <= 0) then
@ -222,15 +219,15 @@ function playereffects.repeater(effect_id, repetitions, entity, apply)
playereffects.repeater, playereffects.repeater,
effect_id, effect_id,
repetitions, repetitions,
entity, player,
apply apply
) )
end end
end end
end end
function playereffects.cancel_effect_type(effect_type_id, cancel_all, entity_or_playername) function playereffects.cancel_effect_type(effect_type_id, cancel_all, playername)
local effects = playereffects.get_player_effects(entity_or_playername) local effects = playereffects.get_player_effects(playername)
if(cancel_all==nil) then cancel_all = false end if(cancel_all==nil) then cancel_all = false end
for e=1, #effects do for e=1, #effects do
if(effects[e].effect_type_id == effect_type_id) then if(effects[e].effect_type_id == effect_type_id) then
@ -242,8 +239,8 @@ function playereffects.cancel_effect_type(effect_type_id, cancel_all, entity_or_
end end
end end
function playereffects.cancel_effect_group(groupname, entity_or_playername) function playereffects.cancel_effect_group(groupname, playername)
local effects = playereffects.get_player_effects(entity_or_playername) local effects = playereffects.get_player_effects(playername)
for e=1,#effects do for e=1,#effects do
local effect = effects[e] local effect = effects[e]
local thesegroups = playereffects.effect_types[effect.effect_type_id].groups local thesegroups = playereffects.effect_types[effect.effect_type_id].groups
@ -271,35 +268,22 @@ function playereffects.cancel_effect(effect_id)
local effect = playereffects.effects[effect_id] local effect = playereffects.effects[effect_id]
if(effect ~= nil) then if(effect ~= nil) then
local player = minetest.get_player_by_name(effect.playername) local player = minetest.get_player_by_name(effect.playername)
if player then local hudinfo = playereffects.hudinfos[effect.playername][effect_id]
local hudinfo = playereffects.hudinfos[effect.playername][effect_id] if(hudinfo ~= nil) then
if(hudinfo ~= nil) then if(hudinfo.text_id~=nil) then
if(hudinfo.text_id~=nil) then player:hud_remove(hudinfo.text_id)
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 end
if(hudinfo.icon_id~=nil) then
-- TODO: Implement cancellation for non-players player:hud_remove(hudinfo.icon_id)
playereffects.effect_types[effect.effect_type_id].cancel(effect, player) end
playereffects.hudinfos[effect.playername][effect_id] = nil
end end
playereffects.effect_types[effect.effect_type_id].cancel(effect, player)
playereffects.effects[effect_id] = nil playereffects.effects[effect_id] = nil
end end
end end
function playereffects.get_player_effects(entity_or_playername) function playereffects.get_player_effects(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 if(minetest.get_player_by_name(playername) ~= nil) then
local effects = {} local effects = {}
for k,v in pairs(playereffects.effects) do for k,v in pairs(playereffects.effects) do
@ -313,8 +297,8 @@ function playereffects.get_player_effects(entity_or_playername)
end end
end end
function playereffects.has_effect_type(entity_or_playername, effect_type_id) function playereffects.has_effect_type(playername, effect_type_id)
local pe = playereffects.get_player_effects(entity_or_playername) local pe = playereffects.get_player_effects(playername)
for i=1,#pe do for i=1,#pe do
if pe[i].effect_type_id == effect_type_id then if pe[i].effect_type_id == effect_type_id then
return true return true
@ -330,13 +314,11 @@ function playereffects.save_to_file()
local inactive_effects = {} local inactive_effects = {}
for id,effecttable in pairs(playereffects.inactive_effects) do for id,effecttable in pairs(playereffects.inactive_effects) do
local playername = id local playername = id
if playername ~= "" then if(inactive_effects[playername] == nil) then
if(inactive_effects[playername] == nil) then inactive_effects[playername] = {}
inactive_effects[playername] = {} end
end for i=1,#effecttable do
for i=1,#effecttable do table.insert(inactive_effects[playername], effecttable[i])
table.insert(inactive_effects[playername], effecttable[i])
end
end end
end end
for id,effect in pairs(playereffects.effects) do for id,effect in pairs(playereffects.effects) do
@ -360,9 +342,7 @@ function playereffects.save_to_file()
if(inactive_effects[effect.playername] == nil) then if(inactive_effects[effect.playername] == nil) then
inactive_effects[effect.playername] = {} inactive_effects[effect.playername] = {}
end end
if effect.playername ~= "" then table.insert(inactive_effects[effect.playername], new_effect)
table.insert(inactive_effects[effect.playername], new_effect)
end
end end
savetable.inactive_effects = inactive_effects savetable.inactive_effects = inactive_effects
@ -375,7 +355,7 @@ function playereffects.save_to_file()
if file then if file then
file:write(savestring) file:write(savestring)
io.close(file) io.close(file)
minetest.log("action", "[playereffects] Wrote playereffects data into "..filepath..".") minetest.log("verbose", "[playereffects] Wrote playereffects data into "..filepath..".")
else else
minetest.log("error", "[playereffects] Failed to write playereffects data into "..filepath..".") minetest.log("error", "[playereffects] Failed to write playereffects data into "..filepath..".")
end end
@ -447,7 +427,7 @@ minetest.register_globalstep(function(dtime)
-- Autosave into file -- Autosave into file
if(playereffects.use_autosave == true and playereffects.autosave_timer >= playereffects.autosave_time) then if(playereffects.use_autosave == true and playereffects.autosave_timer >= playereffects.autosave_time) then
playereffects.autosave_timer = 0 playereffects.autosave_timer = 0
minetest.log("action", "[playereffects] Autosaving mod data to playereffects.mt ...") minetest.log("verbose", "[playereffects] Autosaving mod data to playereffects.mt ...")
playereffects.save_to_file() playereffects.save_to_file()
end end
end) end)