diff --git a/mods/mana/API.md b/mods/mana/API.md new file mode 100644 index 00000000..c82eda1d --- /dev/null +++ b/mods/mana/API.md @@ -0,0 +1,120 @@ +API documentation for Mana 1.0.1 +================================ + +## Introduction +The API of the Mana mod allows you to set and receive +the current and maxiumum mana reserves of a player, +and to subtract and add mana. + +## The basic rules +For integrity reasons, this mod will ensure that the following assumptions +are true at all times for all players: + +* Current and maximum mana can never be smaller than 0 +* The current value must not be greater than the maximum value +* Only integer numbers are permitted for mana values + +It should be not possible to break these rules using this API alone. +If you somehow manage to break one ofthe rules, please report a bug. + +If a real number is used as input for a value, it will be rounded +(“round up half” rule). + +## Functions +Of not specified otherwise, all functions return `nil`. +`playername` always refers to the name of a player, as string. +`value` always refers to a number and for most functions it must always be equal to or greater than 0. + + +### `mana.set(playername, value)` +Sets the mana reserve of the specified player to `value`. +If `value` is smaller than 0, the mana will be set to 0. +If `value` is greater than the maximum, the mana will be set to the maximum. + + +### `mana.setmax(playername, value)` +Sets the maximum of the player to `value`. + +If the new maximum would become smaller than the current value, +the current value will automatically be set to +the new maximum. + +### `mana.setregen(playername, value)` +Sets the mana regeneration per mana tick of the player to `value`. +Negative values are not permitted. +The length of one “mana tick” is specified as the server-wide setting +`mana_default_regen` in seconds. + + +### `mana.get(playername)` +Returns the current mana of the specified player as number. + + +### `mana.getmax(playername)` +Returns the current maximum mana of the specified player as number. + + +### `mana.getregen(playername)` +Returns the current mana regneration per mana tick of the specified +player as number. +The length of one “mana tick” is specified as the server-wide setting +`mana_default_regen` in seconds. + + +### `mana.add(playername, value)` +Adds the specified non-negative amount of mana to the player, but only +if the sum would not be greater than the maximum, + +#### Return value +* `true` on success, all mana has been added +* `false` on failure, no mana has been added + + +### `mana.subtract(playername, value)` +Subtracts the specified non-negative amount of mana from the player, +but only if the player has sufficient mana reservers. + +#### Return value +* `true` on success, all mana has been subtracted +* `false` on failure, no mana has been subtraceed + + +### `mana.add_up_to(playername, value)` +Adds the specified non-negative amount of mana to the player, but it will +be capped at the maximum. + +#### Return value +* `true, excess` on success, where `excess` is the amount of Mana which could not be added because it would have exceeded the maximum. `excess` equals `0` if all mana has been added +* `false` on failure (mana could not be added) + + +### `mana.subtract_up_to(playername, value)` +Subtracts the specified non-negative amount of mana from the player, +but if the difference is smaller than 0, the mana will be set to 0. + +#### Return value +* `true, missing` on success, where `missing` is the amount of Mana which could not be subtracted because it would have exceeded 0. `missing` equals `0` if all mana has been subtracted +* `false` on failure (mana could not be subtracted) + + +## Appendix +### General recommendations +If you want your mod to be portable, it is recommended that you balance your mod in such a way that it assumes +that every player starts with the following default mana values: + +* Max. mana: 200 +* Mana regeneration: 1 mana every 0.2 seconds + +Also assume that the max. mana never changes. +This should (hopefully) ensure that multiple independent mana-using mods are more or less balanced when using +the default settings. + +Also, to make life easier for subgame makers, define custom minetest.conf settings for your mod in order to +overwrite the mana costs (and other relevant values) used by your mod. That way, subgame makers only have to edit +minetest.conf, and not your mod. + +You do not have to bother about default values if you want to directly integrate your mod in a subgame and do +not plan to release the mod independently. + +The best way to reliable balance the mana values used by several mods is to create a standalone subgame. It is +highly recommended that you tweak the mana values of the mods to fit the subgame's needs. diff --git a/mods/mana/README.txt b/mods/mana/README.txt new file mode 100644 index 00000000..8f9ba0ce --- /dev/null +++ b/mods/mana/README.txt @@ -0,0 +1,51 @@ +Mana mod [mana] +=============== +Version: 1.0.1 +Note: This mod uses semantic versioning, as defined by version 2.0.0 of the SemVer standard. +See: + +Description +=========== +This mod adds basic support for mana to Minetest. + +Each player will have an additional attribute: Mana. To be precise: + +- Current mana reserves: How much mana the player currently has +- Maximum possible mana: How much mana the player can have at maximum +- Mana regeneration amont: How much mana will be generated each “mana tick” (default 0.2 seconds) + +By default, each player spawns with 0/200 mana, and regenerates 1 mana per fifth of a second. All +these values can be configured with the server settings (`minetest.conf`) and it is highly advised to do +so if you plan to integrate this mod into a subgame. + +The mana regeneration rate (the “mana tick”) is a global setting and is *not* configured on a +per-player basis. + +The mod provides a simple API to set, get, add and subtract the mana (and maximum) mana of any player, and +for setting the regeneration amount. Note that this mod itself does *not* change the gameplay in a meaningful +way. You should install other mods which use the Mana mod as a dependency. + +The API documentation is in the file API.md. + +If the mod “HUD bars” [hudbars] is installed, a blue bar will be added to the HUD showing the player's mana reserves. +It currently only works with version 0.3.0 of this mod. + +Otherwise, the mana is just shown as text. + +Configuration +============= + +This mod can be configured with minetest.conf! The following settings are accepted: + +* `mana_default_max`: Initial max. mana given to new players. Default: `200`. This value must be non-negative. +* `mana_default_regen`: Initial regenerated mana per “mana tick”. Default: `1`. This value must be non-negative. +* `mana_regen_timer`: The length of a “mana tick” in seconds. Each player will get his/her mana increased by the current + regen value per mana tick. Default: `0.2`. This value must be positive, also try to avoid very small values + as those could probably stress your machine a lot. + + +License information +=================== +* textures/mana_icon.png: CC-BY by Buch . +* textures/mana_bar.png: WTFPL by Wuzzy. +* Everything else: WTFPL. diff --git a/mods/mana/depends.txt b/mods/mana/depends.txt new file mode 100644 index 00000000..3e1d5c20 --- /dev/null +++ b/mods/mana/depends.txt @@ -0,0 +1 @@ +hudbars? diff --git a/mods/mana/description.txt b/mods/mana/description.txt new file mode 100644 index 00000000..e9efb088 --- /dev/null +++ b/mods/mana/description.txt @@ -0,0 +1 @@ +Adds a mana attribute to players, can be used as energy source for magical items, etc. diff --git a/mods/mana/init.lua b/mods/mana/init.lua new file mode 100644 index 00000000..dbadb4cc --- /dev/null +++ b/mods/mana/init.lua @@ -0,0 +1,308 @@ +--[[ +Mana 1.0.1 +This mod adds mana to players, a special attribute + +License: WTFPL +]] + +--[===[ + Initialization +]===] + +mana = {} +mana.playerlist = {} + +mana.settings = {} +mana.settings.default_max = 200 +mana.settings.default_regen = 1 +mana.settings.regen_timer = 0.2 + +do + local default_max = tonumber(minetest.setting_get("mana_default_max")) + if default_max ~= nil then + mana.settings.default_max = default_max + end + + local default_regen = tonumber(minetest.setting_get("mana_default_regen")) + if default_regen ~= nil then + mana.settings.default_regen = default_regen + end + + local regen_timer = tonumber(minetest.setting_get("mana_regen_timer")) + if regen_timer ~= nil then + mana.settings.regen_timer = regen_timer + end +end + + +--[===[ + API functions +]===] + +function mana.set(playername, value) + if value < 0 then + minetest.log("info", "[mana] Warning: mana.set was called with negative value!") + value = 0 + end + value = mana.round(value) + if value > mana.playerlist[playername].maxmana then + value = mana.playerlist[playername].maxmana + end + if mana.playerlist[playername].mana ~= value then + mana.playerlist[playername].mana = value + mana.hud_update(playername) + end +end + +function mana.setmax(playername, value) + if value < 0 then + value = 0 + minetest.log("info", "[mana] Warning: mana.setmax was called with negative value!") + end + value = mana.round(value) + if mana.playerlist[playername].maxmana ~= value then + mana.playerlist[playername].maxmana = value + if(mana.playerlist[playername].mana > value) then + mana.playerlist[playername].mana = value + end + mana.hud_update(playername) + end +end + +function mana.setregen(playername, value) + if value < 0 then + value = 0 + minetest.log("info", "[mana] Warning: mana.setregen was called with negative value!") + end + value = mana.round(value) + mana.playerlist[playername].regen = value +end + +function mana.get(playername) + return mana.playerlist[playername].mana +end + +function mana.getmax(playername) + return mana.playerlist[playername].maxmana +end + +function mana.getregen(playername) + return mana.playerlist[playername].regen +end + +function mana.add_up_to(playername, value) + local t = mana.playerlist[playername] + value = mana.round(value) + if(t ~= nil and value >= 0) then + local excess + if((t.mana + value) > t.maxmana) then + excess = (t.mana + value) - t.maxmana + t.mana = t.maxmana + else + excess = 0 + t.mana = t.mana + value + end + mana.hud_update(playername) + return true, excess + else + return false + end +end + +function mana.add(playername, value) + local t = mana.playerlist[playername] + value = mana.round(value) + if(t ~= nil and ((t.mana + value) <= t.maxmana) and value >= 0) then + t.mana = t.mana + value + mana.hud_update(playername) + return true + else + return false + end +end + +function mana.subtract(playername, value) + local t = mana.playerlist[playername] + value = mana.round(value) + if(t ~= nil and t.mana >= value and value >= 0) then + t.mana = t.mana -value + mana.hud_update(playername) + return true + else + return false + end +end + +function mana.subtract_up_to(playername, value) + local t = mana.playerlist[playername] + value = mana.round(value) + if(t ~= nil and value >= 0) then + local missing + if((t.mana - value) < 0) then + missing = math.abs(t.mana - value) + t.mana = 0 + else + missing = 0 + t.mana = t.mana - value + end + mana.hud_update(playername) + return true, missing + else + return false + end +end + + + + + +--[===[ + File handling, loading data, saving data, setting up stuff for players. +]===] + + +-- Load the playerlist from a previous session, if available. +do + local filepath = minetest.get_worldpath().."/mana.mt" + local file = io.open(filepath, "r") + if file then + minetest.log("action", "[mana] mana.mt opened.") + local string = file:read() + io.close(file) + if(string ~= nil) then + local savetable = minetest.deserialize(string) + mana.playerlist = savetable.playerlist + minetest.debug("[mana] mana.mt successfully read.") + end + end +end + +function mana.save_to_file() + local savetable = {} + savetable.playerlist = mana.playerlist + + local savestring = minetest.serialize(savetable) + + local filepath = minetest.get_worldpath().."/mana.mt" + local file = io.open(filepath, "w") + if file then + file:write(savestring) + io.close(file) + minetest.log("action", "[mana] Wrote mana data into "..filepath..".") + else + minetest.log("error", "[mana] Failed to write mana data into "..filepath..".") + end +end + + +minetest.register_on_respawnplayer(function(player) + local playername = player:get_player_name() + mana.set(playername, 0) + mana.hud_update(playername) +end) + + +minetest.register_on_leaveplayer(function(player) + local playername = player:get_player_name() + mana.hud_remove(playername) + mana.playerlist[playername] = nil +end) + +minetest.register_on_shutdown(function() + minetest.log("action", "[mana] Server shuts down. Rescuing data into mana.mt") + mana.save_to_file() +end) + +minetest.register_on_joinplayer(function(player) + local playername = player:get_player_name() + + if mana.playerlist[playername] == nil then + mana.playerlist[playername] = {} + mana.playerlist[playername].mana = 0 + mana.playerlist[playername].maxmana = mana.settings.default_max + mana.playerlist[playername].regen = mana.settings.default_regen + end + + if minetest.get_modpath("hudbars") ~= nil then + hb.init_hudbar(player, "mana", mana.get(playername), mana.getmax(playername)) + else + mana.hud_add(playername) + end +end) + + +--[===[ + Mana regeneration +]===] + +mana.regen_timer = 0 + +minetest.register_globalstep(function(dtime) + mana.regen_timer = mana.regen_timer + dtime + if mana.regen_timer >= mana.settings.regen_timer then + local factor = math.floor(mana.regen_timer / mana.settings.regen_timer) + local players = minetest.get_connected_players() + for i=1, #players do + local name = players[i]:get_player_name() + if mana.playerlist[name] ~= nil then + if players[i]:get_hp() > 0 then + mana.add_up_to(name, mana.playerlist[name].regen * factor) + end + end + end + mana.regen_timer = mana.regen_timer % mana.settings.regen_timer + end +end) + +--[===[ + HUD functions +]===] + +if minetest.get_modpath("hudbars") ~= nil then + hb.register_hudbar("mana", 0xFFFFFF, "Mana", { bar = "mana_bar.png", icon = "mana_icon.png" }, 0, mana.settings.default_max, false) + + function mana.hud_update(playername) + local player = minetest.get_player_by_name(playername) + if player ~= nil then + hb.change_hudbar(player, "mana", mana.get(playername), mana.getmax(playername)) + end + end + +else + function mana.manastring(playername) + return string.format("Mana: %d/%d", mana.get(playername), mana.getmax(playername)) + end + + function mana.hud_add(playername) + local player = minetest.get_player_by_name(playername) + local id = player:hud_add({ + hud_elem_type = "text", + position = { x = 0.5, y=0.9 }, + text = mana.manastring(playername), + scale = { x = 0, y = 0 }, + alignment = { x = 6.96, y = -14}, + direction = 1, + number = 0xFFFFFF, + offset = { x = -200, y = 15} + }) + mana.playerlist[playername].hudid = id + return id + end + + function mana.hud_update(playername) + local player = minetest.get_player_by_name(playername) + player:hud_change(mana.playerlist[playername].hudid, "number", mana.get(playername)) + end + + function mana.hud_remove(playername) + local player = minetest.get_player_by_name(playername) + player:hud_remove(mana.playerlist[playername].hudid) + end +end + +--[===[ + Helper functions +]===] +mana.round = function(x) + return math.ceil(math.floor(x+0.5)) +end diff --git a/mods/mana/textures/mana_bar.png b/mods/mana/textures/mana_bar.png new file mode 100644 index 00000000..bb4faa33 Binary files /dev/null and b/mods/mana/textures/mana_bar.png differ diff --git a/mods/mana/textures/mana_icon.png b/mods/mana/textures/mana_icon.png new file mode 100644 index 00000000..d25ddff0 Binary files /dev/null and b/mods/mana/textures/mana_icon.png differ diff --git a/worlds/minetestforfun/world.mt b/worlds/minetestforfun/world.mt index 5cba5bad..1f453daf 100644 --- a/worlds/minetestforfun/world.mt +++ b/worlds/minetestforfun/world.mt @@ -57,7 +57,6 @@ load_mod_mesecons = true load_mod_mesecons_alias = true load_mod_mesecons_button = true load_mod_mesecons_commandblock = true -load_mod_mesecons_compatibility = true load_mod_mesecons_delayer = true load_mod_mesecons_extrawires = true load_mod_mesecons_hydroturbine = true