master
raymoo 7 years ago
commit 2c208403ff
  1. 13
      COPYING
  2. 33
      README.md
  3. 2
      depends.txt
  4. 1
      description.txt
  5. 219
      init.lua
  6. 1
      mod.conf

@ -0,0 +1,13 @@
Copyright 2015-2016 raymoo
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

@ -0,0 +1,33 @@
#The Armor Monoid
This mod provides a monoidal_effects monoid for handling armor groups. It
provides the ```"armor"``` monoid, and a way to register new damage types
for players.
Using the monoid
================
The values in the monoid are tables mapping armor group names to damage
multipliers. For example, if I wanted to register an effect granting arcane
damage resistance but fleshy damage vulnerability, I could do <br/>
```
monoidal_effects.register_effect_type("magic_barrier", {
disp_name = "Magic Barrier",
tags = { magical = 1 },
monoids = { armor = true },
cancel_on_death = true,
values = { armor = { fleshy = 1.5, arcane = 0.3 } },
icon = "magic_barrier.png",
})
```
Registering damage types
========================
To add a new damage type to players, use armor_monoid.register_armor_group. For
example: <br/>
```
armor_monoid.register_armor_group("arcane", 100)
```
<br/>
As you can see, the argument is not a multiplier, but the base armor group
rating. Calling this would mean players start off with an armor rating in
"arcane" of 100 (no protection).

@ -0,0 +1,2 @@
monoidal_effects
3d_armor?

@ -0,0 +1 @@
A monoidal_effects monoid for armor

@ -0,0 +1,219 @@
armor_monoid = {}
local armor_groups = { fleshy = 100 }
armor_monoid.registered_groups = armor_groups
local join_handled = {}
local function copy_tab(tab)
local copy = {}
for k, v in pairs(tab) do
copy[k] = v
end
return copy
end
-- The values in this monoid are not armor group values, but damage multipliers.
-- For example { fleshy = 0.5, fire = 1.2 } would mean that a player takes
-- half fleshy damage and 120% fire damage. Nil values are the same as putting
-- 1. The final multipliers are multiplied to the base damage for the group.
monoidal_effects.register_monoid("armor", {
combine = function(tab1, tab2)
local res = {}
for k, v in pairs(armor_groups) do
local v1 = tab1[k]
local v2 = tab2[k]
if not v1 then
res[k] = v2
elseif not v2 then
res[k] = v1
else
res[k] = v1 * v2
end
end
return res
end,
fold = function(elems)
local res = {}
for k, tab in pairs(elems) do
for k, v in pairs(armor_groups) do
local vres = res[k]
local v_other = tab[k]
if not vres then
res[k] = v_other
elseif v_other then
res[k] = vres * v_other
end
-- If not v_other, res[k] remains the same.
end
end
return res
end,
identity = {},
apply = function(multipliers, player)
local final = copy_tab(armor_groups)
for k, v in pairs(multipliers) do
if final[k] then -- Make sure it is a registered armor group
final[k] = final[k] * v
end
end
join_handled[player:get_player_name()] = true
player:set_armor_groups(final)
end,
})
-- If the monoid has not fired yet (or won't fire)
minetest.register_on_joinplayer(function(player)
if not join_handled[player:get_player_name()] then
player:set_armor_groups(armor_groups)
end
end)
minetest.register_on_leaveplayer(function(player)
join_handled[player:get_player_name()] = nil
end)
-- armor_monoid.register_armor_group("name", x) creates an armor group called name
-- with a default armor value of x.
function armor_monoid.register_armor_group(name, def)
armor_groups[name] = def
end
if not minetest.global_exists("armor") then return end
monoidal_effects.register_type("armor_monoid:compat_armor", {
disp_name = "3D Armor Compatibility",
dynamic = true,
monoids = { armor = true },
hidden = true,
cancel_on_death = false,
values = { armor = {} },
})
monoidal_effects.register_type("armor_monoid:compat_phys", {
disp_name = "3D Armor Physics Compatibility",
dynamic = true,
monoids = { speed = true, jump = true, gravity = true },
hidden = true,
cancel_on_death = false,
values = { speed = 1, jump = 1, gravity = 1 },
})
-- Armor override
armor.set_player_armor = function(self, player)
local name, player_inv = armor:get_valid_player(player, "[set_player_armor]")
if not name then
return
end
local armor_texture = "3d_armor_trans.png"
local armor_level = 0
local armor_heal = 0
local armor_fire = 0
local armor_water = 0
local state = 0
local items = 0
local elements = {}
local textures = {}
local physics_o = {speed=1,gravity=1,jump=1}
local material = {type=nil, count=1}
local preview = armor:get_preview(name) or "character_preview.png"
for _,v in ipairs(self.elements) do
elements[v] = false
end
for i=1, 6 do
local stack = player_inv:get_stack("armor", i)
local item = stack:get_name()
if stack:get_count() == 1 then
local def = stack:get_definition()
for k, v in pairs(elements) do
if v == false then
local level = def.groups["armor_"..k]
if level then
local texture = def.texture or item:gsub("%:", "_")
table.insert(textures, texture..".png")
preview = preview.."^"..texture.."_preview.png"
armor_level = armor_level + level
state = state + stack:get_wear()
items = items + 1
armor_heal = armor_heal + (def.groups["armor_heal"] or 0)
armor_fire = armor_fire + (def.groups["armor_fire"] or 0)
armor_water = armor_water + (def.groups["armor_water"] or 0)
for kk,vv in ipairs(self.physics) do
local o_value = def.groups["physics_"..vv]
if o_value then
physics_o[vv] = physics_o[vv] + o_value
end
end
local mat = string.match(item, "%:.+_(.+)$")
if material.type then
if material.type == mat then
material.count = material.count + 1
end
else
material.type = mat
end
elements[k] = true
end
end
end
end
end
if minetest.get_modpath("shields") then
armor_level = armor_level * 0.9
end
if material.type and material.count == #self.elements then
armor_level = armor_level * 1.1
end
armor_level = armor_level * ARMOR_LEVEL_MULTIPLIER
armor_heal = armor_heal * ARMOR_HEAL_MULTIPLIER
if #textures > 0 then
armor_texture = table.concat(textures, "^")
end
local armor_groups = {fleshy=100}
if armor_level > 0 then
armor_groups.level = math.floor(armor_level / 20)
armor_groups.fleshy = 100 - armor_level
end
monoidal_effects.cancel_effect_type("armor_monoid:compat_armor", name)
monoidal_effects.cancel_effect_type("armor_monoid:compat_phys", name)
monoidal_effects.apply_effect("armor_monoid:compat_armor", "perm", name, {
armor = { fleshy = armor_groups.fleshy / 100 },
})
monoidal_effects.apply_effect("armor_monoid:compat_phys", "perm", name, physics_o)
self.textures[name].armor = armor_texture
self.textures[name].preview = preview
self.def[name].state = state
self.def[name].count = items
self.def[name].level = armor_level
self.def[name].heal = armor_heal
self.def[name].jump = physics_o.jump
self.def[name].speed = physics_o.speed
self.def[name].gravity = physics_o.gravity
self.def[name].fire = armor_fire
self.def[name].water = armor_water
self:update_player_visuals(player)
end

@ -0,0 +1 @@
name=armor_monoid
Loading…
Cancel
Save