Compare commits
460 Commits
version-0.
...
master
Author | SHA1 | Date | |
---|---|---|---|
3ae2529c9f | |||
a6779e7911 | |||
a586aeee0c | |||
082e866274 | |||
c224a73df7 | |||
280165fada | |||
357cc3aada | |||
ab1bec3be8 | |||
22955b413a | |||
1fcbf64d53 | |||
fb86c02e43 | |||
20917da061 | |||
7bd77a7b80 | |||
25369e5165 | |||
7fc313f911 | |||
4bac73fc9e | |||
f430395b64 | |||
467709c935 | |||
e0b6112320 | |||
6b2f83e8e3 | |||
f3e66701aa | |||
babb15262d | |||
7a0c456638 | |||
9a687fbb51 | |||
1e2760a6cf | |||
1da9d94e7c | |||
3660e50312 | |||
c894ba4b0c | |||
aef125a0ca | |||
7d251784e7 | |||
6eb492b09c | |||
dfa19cce98 | |||
19b8ea4028 | |||
1d8509e75b | |||
053c30b8b1 | |||
dc7fbce09a | |||
72970b3da1 | |||
52f0e6a0ed | |||
400745dd0c | |||
68d724176e | |||
2ef66d3132 | |||
e75c0bedcc | |||
92d036c5a7 | |||
7f20e5dcb7 | |||
04b45deec8 | |||
bfa3a2b6d1 | |||
41301a4663 | |||
eebee34fa0 | |||
c7ee559a4c | |||
9444afd722 | |||
1869d4b0c3 | |||
e1a262ba20 | |||
ac445a6cd0 | |||
c95eb77a4e | |||
a9b8bc4ddd | |||
6757013da2 | |||
b6651fd396 | |||
16e2648416 | |||
44778d7861 | |||
5845d3682d | |||
8dcbc42525 | |||
c0f303abc1 | |||
46c599333e | |||
da78601a77 | |||
c790b20169 | |||
a897f7e72f | |||
e8f938bd2c | |||
ac7615212b | |||
3bc7ed06e2 | |||
38fc2cff2b | |||
2d280a5a1e | |||
1dec1f2153 | |||
9417629f51 | |||
0dffd62fb0 | |||
a0cf12bbd0 | |||
371285a903 | |||
8eaf8edb4c | |||
f07f0507e2 | |||
bcdd82980b | |||
e75af55f7e | |||
3ca25f7ec4 | |||
583dfe7b21 | |||
44111db4d7 | |||
52f4c52271 | |||
2ebefb332f | |||
bda0db7c04 | |||
31aa979215 | |||
42f7dac4d0 | |||
e7abacc94e | |||
a3cba570c4 | |||
3ddcbae968 | |||
5642819ba5 | |||
724a3df50f | |||
33e9ac8e23 | |||
06aaaf4bca | |||
d515480370 | |||
6242cebb20 | |||
291f0eb23a | |||
3b97763fdc | |||
713b0c81d4 | |||
cbd1a1246b | |||
5958b312ac | |||
7436fcdffe | |||
3f1a952afb | |||
7f63df230c | |||
294338d3b0 | |||
9459400474 | |||
2d9b0066bf | |||
502eb142da | |||
7fc9966945 | |||
4dc9a81ec2 | |||
979516c13d | |||
ec5de28dc2 | |||
0af7280e64 | |||
2b535ee887 | |||
073206701a | |||
b4eebf604e | |||
0da0088889 | |||
dbc6ccf089 | |||
acd8b2647d | |||
a6b89e7929 | |||
c3a755518e | |||
4c99049600 | |||
f81cb10f20 | |||
f3ad7ec6f1 | |||
fccd4d8b15 | |||
e5b2cf3a34 | |||
d2608351f6 | |||
afee335dc2 | |||
a05eae3782 | |||
2ac90f8d19 | |||
4adc602704 | |||
e248752ee4 | |||
47ecef46f7 | |||
1d22612664 | |||
3fe7dd2249 | |||
be9579a365 | |||
18320e96b9 | |||
99471d3aa0 | |||
b6283f3f0f | |||
5da2f3060a | |||
7e2d9426d1 | |||
813a88f3a1 | |||
1ff3bb0041 | |||
41b8c3e343 | |||
941bfc27f9 | |||
f991b676f4 | |||
4c032e8c7e | |||
945e816b55 | |||
10ded06705 | |||
43a69ad853 | |||
13a8f0d019 | |||
70325158e6 | |||
c96ba7ef34 | |||
838867a6bc | |||
9ce0ed9f55 | |||
c0d45ceaa1 | |||
656bcf30bc | |||
579e64a5e7 | |||
6f99803d2d | |||
f960fc1a41 | |||
af4a381433 | |||
1f11a28ad4 | |||
a5ddc3e60a | |||
83f3e01efa | |||
7d30bc25a3 | |||
e4b12558d4 | |||
21b5c68505 | |||
21716ffd31 | |||
cc6fff2b04 | |||
4210cafff3 | |||
579d245a00 | |||
c812e0ac56 | |||
4baed2ca22 | |||
b9c8681e14 | |||
2fc92880fd | |||
b4cfdac6f5 | |||
59b26b37f9 | |||
7226dd6174 | |||
4fc51971d1 | |||
291b34bfc6 | |||
da7df11ce4 | |||
4ff61da39a | |||
688e21f285 | |||
ea70066d7a | |||
d5896a04e2 | |||
d979815a49 | |||
cca523f193 | |||
ae448c150c | |||
925b39f577 | |||
0454d72c72 | |||
9fa95b2e2c | |||
43c9984d57 | |||
cc26d04345 | |||
38d79b91a1 | |||
db8fb5ebd4 | |||
2150fcea8d | |||
9577fb773e | |||
ea29ec6f6f | |||
793c74856f | |||
47734969e2 | |||
1af0bb60f8 | |||
a11b3302e1 | |||
664d9fbfef | |||
4dd7e41749 | |||
df429ee487 | |||
7566ecccee | |||
99bc8cf2d3 | |||
a2ec13e28d | |||
065815eec1 | |||
16b0ee2d9e | |||
64f8b3cd58 | |||
74ef6c5759 | |||
b741b7426b | |||
db312b3245 | |||
de2c47f334 | |||
b4283f6e60 | |||
888fbacb49 | |||
50453aa5a6 | |||
b45fbd0f2a | |||
9ffcc19fd7 | |||
6359b0a0ed | |||
4dbe76312b | |||
20edce6c55 | |||
6e58d1280b | |||
20d4728829 | |||
7cfd744ff3 | |||
a76a35f177 | |||
e5e926a02e | |||
3951c833da | |||
e9a2c57826 | |||
5508a26dbf | |||
0ec7858937 | |||
1e059f2557 | |||
5dab1ca887 | |||
1fdff7adaa | |||
23e4d5114f | |||
7fde7c050d | |||
45099ae25a | |||
edebf13c1f | |||
4083782246 | |||
5911447048 | |||
3aac5c98f4 | |||
fe9664589a | |||
11ce84873b | |||
86fd6b0d7d | |||
27a3823eed | |||
348dad3d4d | |||
ea86aa35f5 | |||
f0edb9a710 | |||
75191490c2 | |||
f91af02c45 | |||
3843578a33 | |||
1570efb7ac | |||
5517be8ff2 | |||
709535dff0 | |||
a1d904c517 | |||
3c2cb16351 | |||
6bf28dc2c5 | |||
75a7181e0f | |||
2b840fbe38 | |||
701215c22f | |||
e46ff3488b | |||
f74a52df62 | |||
3c4500a9bf | |||
e69b59e2af | |||
d43d96bb28 | |||
7a980a6717 | |||
fc3fcea4b7 | |||
b59464de88 | |||
80024fc154 | |||
d826b53877 | |||
01a3425ec8 | |||
616d9398f2 | |||
6661ec0b40 | |||
ca1cf6bfeb | |||
8f5ffeb384 | |||
ca79d39688 | |||
8b8a554ff7 | |||
3df7802439 | |||
19e297a2e8 | |||
190614d47b | |||
37b10d1cee | |||
4b45f85687 | |||
a5b650285b | |||
26212fb3e4 | |||
4829445d12 | |||
4d3b219e7d | |||
81ffdaa6a7 | |||
ba62febdee | |||
8939a0dd43 | |||
c691f3e219 | |||
bf9ba59c0f | |||
75f808131c | |||
b88f946929 | |||
c63376b523 | |||
c070dfb19f | |||
4b70580ce4 | |||
65b6d58580 | |||
98786fd8f7 | |||
9105e8403e | |||
6b2e3adc00 | |||
c9001f9e53 | |||
cc25d6be13 | |||
f557c4d69e | |||
456c84e93e | |||
0157ebd683 | |||
c39f838893 | |||
862deff373 | |||
ac414d3df3 | |||
3cf6887abd | |||
b14db3c43c | |||
8f8c6c6bfa | |||
54ec4b3cef | |||
32e87ee543 | |||
d322a0f110 | |||
9cc2f3db02 | |||
ddd7f3786c | |||
5c5359de4f | |||
1aa2b769d7 | |||
5421ce46da | |||
72cffbae17 | |||
170ee39aed | |||
59bbc55b73 | |||
1dd904f5be | |||
9de8cc12bb | |||
4e8cf05436 | |||
b6a44057a6 | |||
ae33659168 | |||
fb29ce9150 | |||
7408ebcd81 | |||
36737441d4 | |||
5a112547e6 | |||
0d5cf6d58a | |||
f17a104ab1 | |||
f83e7e9984 | |||
be1d353ec0 | |||
241aa663f1 | |||
921e1ace24 | |||
0ec2dbfb36 | |||
7fc991765c | |||
991d2955e0 | |||
64ec3dcf93 | |||
e1caf0ab0c | |||
a44d1a2530 | |||
16bc6232ca | |||
6efe3bf116 | |||
67867e78ec | |||
64f6be4d61 | |||
741faf3520 | |||
1c56ee4bd6 | |||
40a3c1e0c4 | |||
ae7ad422a5 | |||
bad1452e87 | |||
7cefc1a7ba | |||
8f2badeec3 | |||
734e01e847 | |||
4eabd8512a | |||
14a0eb8cca | |||
e1ffdd6a0d | |||
306f193db6 | |||
6704431499 | |||
bc0ea6b5bf | |||
0fc71201b4 | |||
d107708bec | |||
bd2ebac24e | |||
ebe159ac2c | |||
1d1534b416 | |||
91602ed6f2 | |||
2b0ce6f63e | |||
3badcea0d9 | |||
d2f32beebb | |||
b3f755f7d7 | |||
dec92749f9 | |||
9da2395586 | |||
6942aa37d2 | |||
7da9d81963 | |||
905fc9fcb0 | |||
b8e5d0adde | |||
58337c0404 | |||
87af6e0c68 | |||
70d353bb6c | |||
6e0fbc8bb2 | |||
9c2b9c9b5a | |||
b8be801b94 | |||
679888398f | |||
c03cefbc87 | |||
d95f494a94 | |||
195d138da5 | |||
dd9c63e4ca | |||
358e4a2467 | |||
3dd43c7c6f | |||
b17d8ea55a | |||
e6979e9409 | |||
466c5e6957 | |||
a9fcbf29fe | |||
499d5af310 | |||
e3c2616328 | |||
b5db0f1aa6 | |||
ad6c464573 | |||
5ab2f73695 | |||
e14af35b95 | |||
c3d37e83c2 | |||
046880a534 | |||
258b1cbf48 | |||
c10a606632 | |||
2415d66057 | |||
abf445014e | |||
4415e2b33b | |||
36688c74a8 | |||
672dbe1f54 | |||
3c98acb9c9 | |||
5075cc48a4 | |||
7eebc378a6 | |||
6f7a0ea7fc | |||
7ee4126d15 | |||
b67de94223 | |||
3604420d9e | |||
0936d6f173 | |||
e4ab8c02ac | |||
db157c080d | |||
aaf90c2b24 | |||
4420afb8d1 | |||
3e9ce303e6 | |||
11887fc73b | |||
85f56f7ba0 | |||
eedf913638 | |||
ecfd397d77 | |||
b76508397f | |||
9aaba7569c | |||
1886fe6b1a | |||
19d45efd12 | |||
72b612f081 | |||
8a881022e9 | |||
8457220413 | |||
cf2786a818 | |||
5345c50c7e | |||
2b8e0c5fd9 | |||
55e2b69a08 | |||
a07a00c117 | |||
681bf25505 | |||
0b3deea513 | |||
9dbf76d013 | |||
f71204db09 | |||
025c0136b7 | |||
cf87528a03 | |||
9481e548cf | |||
02ba28f11b | |||
5e52758216 | |||
59048743ab | |||
cfc6984a36 | |||
619a52688f | |||
8f2852c6b3 | |||
956193b49a | |||
d7a87a515b | |||
eeb69e1280 | |||
cf0331a043 | |||
61e6052019 | |||
0edd6ac9e0 | |||
efea71a63e |
5
.gitattributes
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
.* export-ignore
|
||||
gendoc.sh export-ignore
|
||||
integration-test.sh export-ignore
|
||||
preview_gen.py export-ignore
|
||||
screenshot.xcf export-ignore
|
14
.github/workflows/integration-test.yml
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
name: integration-test
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
|
||||
- name: integration-test
|
||||
run: ./integration-test.sh
|
17
.github/workflows/luacheck.yml
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
name: luacheck
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: apt
|
||||
run: sudo apt-get install -y luarocks
|
||||
- name: luacheck install
|
||||
run: luarocks install --local luacheck
|
||||
- name: luacheck run
|
||||
run: $HOME/.luarocks/bin/luacheck ./
|
31
.github/workflows/reference.yml
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
name: Build Reference
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
- name: Setup Lua
|
||||
uses: leafo/gh-actions-lua@v10.0.0
|
||||
with:
|
||||
luaVersion: 5.4
|
||||
- name: Setup Lua Rocks
|
||||
uses: leafo/gh-actions-luarocks@v4
|
||||
- name: Setup LDoc dependencies
|
||||
run: luarocks install --only-deps https://raw.githubusercontent.com/lunarmodules/ldoc/master/rockspecs/ldoc-1.5.0-1.rockspec
|
||||
- name: Setup LDoc
|
||||
run: git clone --single-branch --branch=custom https://github.com/AntumDeluge/ldoc.git .ldoc/ldoc && chmod +x .ldoc/ldoc/ldoc.lua
|
||||
- name: Generate docs
|
||||
run: chmod +x .ldoc/gendoc.sh && ./.ldoc/gendoc.sh
|
||||
- name: Deploy
|
||||
uses: peaceiris/actions-gh-pages@v3
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
publish_dir: ./3d_armor/docs
|
3
.gitignore
vendored
@ -5,3 +5,6 @@
|
||||
tags
|
||||
*.vim
|
||||
|
||||
## Eclipse project files & directories
|
||||
.project
|
||||
.settings
|
||||
|
335
.ldoc/config.ld
Normal file
@ -0,0 +1,335 @@
|
||||
|
||||
-- place this file in mod ".ldoc" directory
|
||||
|
||||
local print, type, string, table, tostring, tonumber, error, pairs, ipairs
|
||||
if import then
|
||||
print = import("print")
|
||||
type = import("type")
|
||||
string = import("string")
|
||||
table = import("table")
|
||||
tostring = import("tostring")
|
||||
tonumber = import("tonumber")
|
||||
error = import("error")
|
||||
pairs = import("pairs")
|
||||
ipairs = import("ipairs")
|
||||
end
|
||||
|
||||
project = "3d_armor"
|
||||
title = "3D Armor"
|
||||
format = "markdown"
|
||||
not_luadoc = true
|
||||
boilerplate = false
|
||||
wrap = false
|
||||
style = true
|
||||
favicon = "https://www.minetest.net/media/icon.svg"
|
||||
|
||||
file = {
|
||||
"3d_armor/api.lua",
|
||||
".ldoc/settings.luadoc",
|
||||
--".ldoc/armors.luadoc",
|
||||
".ldoc/helmets.luadoc",
|
||||
".ldoc/chestplates.luadoc",
|
||||
".ldoc/leggings.luadoc",
|
||||
".ldoc/boots.luadoc",
|
||||
--".ldoc/shields.luadoc",
|
||||
"shields/init.lua",
|
||||
".ldoc/crafting.luadoc",
|
||||
}
|
||||
|
||||
|
||||
new_type("setting", "Settings")
|
||||
new_type("armor", "Armors")
|
||||
new_type("craft", "Craft Recipes")
|
||||
|
||||
alias("helmet", "armor")
|
||||
alias("chestplate", "armor")
|
||||
alias("leggings", "armor")
|
||||
alias("boots", "armor")
|
||||
alias("shield", "armor")
|
||||
alias("grp", "group")
|
||||
|
||||
-- function declarations
|
||||
local format_text
|
||||
local format_group
|
||||
|
||||
custom_tags = {
|
||||
-- settings
|
||||
{
|
||||
"settype",
|
||||
title = "Type",
|
||||
hidden = true,
|
||||
},
|
||||
{
|
||||
"min",
|
||||
title = "Minimum Value",
|
||||
hidden = true,
|
||||
},
|
||||
{
|
||||
"max",
|
||||
title = "Maximum Value",
|
||||
hidden = true,
|
||||
},
|
||||
{
|
||||
"default",
|
||||
title = "Default Value",
|
||||
hidden = true,
|
||||
},
|
||||
-- craft items/tools
|
||||
{
|
||||
-- specify image basename only
|
||||
"img",
|
||||
title = "Inventory Image",
|
||||
format = function(value)
|
||||
return "<img src=\"../data/" .. value .. "\" style=\"width:32px; height:32px;\" />"
|
||||
end,
|
||||
},
|
||||
{
|
||||
-- specify full (relative or absolute) image path
|
||||
"image",
|
||||
title = "Image",
|
||||
format = function(value)
|
||||
return "<img src=\"" .. value .. "\" style=\"width:32px; height:32px;\" />"
|
||||
end,
|
||||
},
|
||||
{
|
||||
"group",
|
||||
title = "Groups",
|
||||
format = function(value)
|
||||
return format_group(value)
|
||||
end,
|
||||
},
|
||||
{
|
||||
"armorgrp",
|
||||
title = "Armor Groups",
|
||||
format = function(value)
|
||||
return format_group(value)
|
||||
end,
|
||||
},
|
||||
{
|
||||
"damagegrp",
|
||||
title = "Damage Groups",
|
||||
format = function(value)
|
||||
return format_group(value)
|
||||
end,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
if string then
|
||||
string.trim = function(st, delim)
|
||||
if not delim then
|
||||
delim = " "
|
||||
end
|
||||
|
||||
while string.find(st, delim) == 1 do
|
||||
st = st:sub(2)
|
||||
end
|
||||
|
||||
while string.sub(st, string.len(st)) == delim do
|
||||
st = st:sub(1, string.len(st)-1)
|
||||
end
|
||||
|
||||
return st
|
||||
end
|
||||
|
||||
string.split = function(st, delim)
|
||||
local list = {}
|
||||
|
||||
local idx = string.find(st, delim)
|
||||
while idx do
|
||||
table.insert(list, st:sub(1, idx-1))
|
||||
st = st:sub(idx+1)
|
||||
idx = string.find(st, delim)
|
||||
end
|
||||
-- add remaining item
|
||||
table.insert(list, st)
|
||||
|
||||
return list
|
||||
end
|
||||
end
|
||||
|
||||
if table then
|
||||
if not table.copy then
|
||||
table.copy = function(orig_table)
|
||||
local new_table = {}
|
||||
for k, v in pairs(orig_table) do
|
||||
new_table[k] = v
|
||||
end
|
||||
|
||||
return new_table
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
format_text = function(text, flags)
|
||||
local ret = "<"
|
||||
local ttype = "span"
|
||||
if flags.code then
|
||||
ttype = "code"
|
||||
end
|
||||
|
||||
ret = ret .. ttype .. " style=\""
|
||||
|
||||
if flags.size then
|
||||
ret = ret .. "font-size:" .. flags.size .. ";"
|
||||
end
|
||||
if flags.mono then
|
||||
ret = ret .. "font-family:monospace;"
|
||||
end
|
||||
if flags.italic then
|
||||
ret = ret .. "font-style:italic;"
|
||||
end
|
||||
if flags.bold then
|
||||
ret = ret .. "font-weight:bold;"
|
||||
end
|
||||
if flags.color then
|
||||
ret = ret .. "color:" .. flags.color .. ";"
|
||||
end
|
||||
if flags.bgcolor then
|
||||
ret = ret .. "background-color:" .. flags.bgcolor .. ";"
|
||||
end
|
||||
|
||||
ret = ret .. "\">" .. text .. "</" .. ttype .. ">"
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
format_group = function(text)
|
||||
if string then
|
||||
local idx, k, v = string.find(text, " ")
|
||||
if idx then
|
||||
text = format_text(string.sub(text, 1, idx-1) .. ": ", {mono=true, color="darkgreen"})
|
||||
.. string.sub(text, idx)
|
||||
end
|
||||
end
|
||||
|
||||
return text
|
||||
end
|
||||
|
||||
|
||||
local function format_setting_tag(desc, value)
|
||||
return "\n- <span style=\"font-size:80%;\">`" .. desc .. ":`</span> `" .. value .. "`"
|
||||
end
|
||||
|
||||
|
||||
local registered = {
|
||||
settings = {},
|
||||
}
|
||||
|
||||
local function setting_handler(item)
|
||||
-- avoid parsing again
|
||||
if registered.settings[item.name] then
|
||||
return item
|
||||
end
|
||||
|
||||
if not ipairs or not type then
|
||||
return item
|
||||
end
|
||||
|
||||
local tags = {
|
||||
{"settype", "type"},
|
||||
{"default"},
|
||||
{"min", "minimum value"},
|
||||
{"max", "maximum value"},
|
||||
}
|
||||
|
||||
local def = {
|
||||
["settype"] = format_setting_tag("type", "string"),
|
||||
}
|
||||
|
||||
for _, t in ipairs(tags) do
|
||||
local name = t[1]
|
||||
local desc = t[2]
|
||||
if not desc then desc = name end
|
||||
|
||||
local value = item.tags[name]
|
||||
if type(value) == "table" then
|
||||
if #value > 1 then
|
||||
local msg = item.file.filename .. " (line " .. item.lineno
|
||||
.. "): multiple instances of tag \"" .. name .. "\" found"
|
||||
if error then
|
||||
error(msg)
|
||||
elseif print then
|
||||
print("WARNING: " .. msg)
|
||||
end
|
||||
end
|
||||
|
||||
if value[1] then
|
||||
def[name] = format_setting_tag(desc, value[1])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
item.description = item.description .. "\n\n**Definition:**\n" .. def.settype
|
||||
for _, t in ipairs({def.default, def.min, def.max}) do
|
||||
if t then
|
||||
item.description = item.description .. t
|
||||
end
|
||||
end
|
||||
|
||||
registered.settings[item.name] = true
|
||||
|
||||
return item
|
||||
end
|
||||
|
||||
function custom_display_name_handler(item, default_handler)
|
||||
if item.type == "setting" then
|
||||
item = setting_handler(item)
|
||||
end
|
||||
|
||||
if item then
|
||||
return default_handler(item)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local custom_see_links = {
|
||||
["ObjectRef"] = "https://minetest.gitlab.io/minetest/class-reference/#objectref",
|
||||
["PlayerMetaRef"] = "https://minetest.gitlab.io/minetest/class-reference/#playermetaref",
|
||||
["ItemDef"] = "https://minetest.gitlab.io/minetest/definition-tables/#item-definition",
|
||||
["ItemStack"] = "https://minetest.gitlab.io/minetest/class-reference/#itemstack",
|
||||
["groups"] = "https://minetest.gitlab.io/minetest/groups/",
|
||||
["entity_damage_mechanism"] = "https://minetest.gitlab.io/minetest/entity-damage-mechanism/",
|
||||
["vector"] = "https://minetest.gitlab.io/minetest/representations-of-simple-things/#positionvector",
|
||||
}
|
||||
|
||||
local function format_custom_see(name, section)
|
||||
local url = custom_see_links[name]
|
||||
if not url then
|
||||
url = ""
|
||||
end
|
||||
|
||||
if not name then
|
||||
name = ""
|
||||
end
|
||||
|
||||
return name, url
|
||||
end
|
||||
|
||||
custom_see_handler("^(ObjectRef)$", function(name, section)
|
||||
return format_custom_see(name, section)
|
||||
end)
|
||||
|
||||
custom_see_handler("^(PlayerMetaRef)$", function(name, section)
|
||||
return format_custom_see(name, section)
|
||||
end)
|
||||
|
||||
custom_see_handler("^(ItemDef)$", function(name, section)
|
||||
return format_custom_see(name, section)
|
||||
end)
|
||||
|
||||
custom_see_handler("^(groups)$", function(name, section)
|
||||
return format_custom_see(name, section)
|
||||
end)
|
||||
|
||||
custom_see_handler("^(entity_damage_mechanism)$", function(name, section)
|
||||
return format_custom_see(name, section)
|
||||
end)
|
||||
|
||||
custom_see_handler("^(ItemStack)$", function(name, section)
|
||||
return format_custom_see(name, section)
|
||||
end)
|
||||
|
||||
custom_see_handler("^(vector)$", function(name, section)
|
||||
return name, "https://minetest.gitlab.io/minetest/representations-of-simple-things/#positionvector"
|
||||
end)
|
39
.ldoc/crafting.luadoc
Normal file
@ -0,0 +1,39 @@
|
||||
|
||||
--- 3D Armor Crafting
|
||||
--
|
||||
-- @topic crafting
|
||||
|
||||
|
||||
--- Craft recipes for helmets, chestplates, leggings, boots, & shields.
|
||||
--
|
||||
-- @craft armor
|
||||
-- @usage
|
||||
-- Key:
|
||||
-- - m: material
|
||||
-- - wood: group:wood
|
||||
-- - cactus: default:cactus
|
||||
-- - steel: default:steel_ingot
|
||||
-- - bronze: default:bronze_ingot
|
||||
-- - diamond: default:diamond
|
||||
-- - gold: default:gold_ingot
|
||||
-- - mithril: moreores:mithril_ingot
|
||||
-- - crystal: ethereal:crystal_ingot
|
||||
-- - nether: nether:nether_ingot
|
||||
--
|
||||
-- helmet: chestplate: leggings:
|
||||
-- ┌───┬───┬───┐ ┌───┬───┬───┐ ┌───┬───┬───┐
|
||||
-- │ m │ m │ m │ │ m │ │ m │ │ m │ m │ m │
|
||||
-- ├───┼───┼───┤ ├───┼───┼───┤ ├───┼───┼───┤
|
||||
-- │ m │ │ m │ │ m │ m │ m │ │ m │ │ m │
|
||||
-- ├───┼───┼───┤ ├───┼───┼───┤ ├───┼───┼───┤
|
||||
-- │ │ │ │ │ m │ m │ m │ │ m │ │ m │
|
||||
-- └───┴───┴───┘ └───┴───┴───┘ └───┴───┴───┘
|
||||
--
|
||||
-- boots: shield:
|
||||
-- ┌───┬───┬───┐ ┌───┬───┬───┐
|
||||
-- │ │ │ │ │ m │ m │ m │
|
||||
-- ├───┼───┼───┤ ├───┼───┼───┤
|
||||
-- │ m │ │ m │ │ m │ m │ m │
|
||||
-- ├───┼───┼───┤ ├───┼───┼───┤
|
||||
-- │ m │ │ m │ │ │ m │ │
|
||||
-- └───┴───┴───┘ └───┴───┴───┘
|
88
.ldoc/gendoc.sh
Executable file
@ -0,0 +1,88 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Place this file in mod ".ldoc" directory.
|
||||
#
|
||||
# To change output directory set the `d_export` environment variable.
|
||||
# Example:
|
||||
# $ d_export=/custom/path ./gendoc.sh
|
||||
|
||||
|
||||
d_ldoc="$(dirname $(readlink -f $0))"
|
||||
f_config="${d_ldoc}/config.ld"
|
||||
|
||||
cd "${d_ldoc}/.."
|
||||
|
||||
d_root="$(pwd)"
|
||||
d_export="${d_export:-${d_root}/3d_armor/docs/reference}"
|
||||
d_data="${d_export}/data"
|
||||
|
||||
cmd_ldoc="${d_ldoc}/ldoc/ldoc.lua"
|
||||
if test -f "${cmd_ldoc}"; then
|
||||
if test ! -x "${cmd_ldoc}"; then
|
||||
chmod +x "${cmd_ldoc}"
|
||||
fi
|
||||
else
|
||||
cmd_ldoc="ldoc"
|
||||
fi
|
||||
|
||||
|
||||
# clean old files
|
||||
rm -rf "${d_export}"
|
||||
|
||||
# generate items, settings, & crafts topics temp files
|
||||
echo -e "\ngenerating temp files ..."
|
||||
for script in src settings; do
|
||||
script="${d_ldoc}/parse_${script}.py"
|
||||
if test ! -f "${script}"; then
|
||||
echo "ERROR: script doesn't exist: ${script}"
|
||||
else
|
||||
# check script's executable bit
|
||||
if test ! -x "${script}"; then
|
||||
chmod +x "${script}"
|
||||
fi
|
||||
# execute script
|
||||
"${script}"
|
||||
fi
|
||||
done
|
||||
|
||||
echo
|
||||
|
||||
# generate new doc files
|
||||
"${cmd_ldoc}" --unsafe_no_sandbox -c "${f_config}" -d "${d_export}" "${d_root}"; retval=$?
|
||||
|
||||
# check exit status
|
||||
if test ${retval} -ne 0; then
|
||||
echo -e "\nan error occurred (ldoc return code: ${retval})"
|
||||
exit ${retval}
|
||||
fi
|
||||
|
||||
echo -e "\ncleaning temp files ..."
|
||||
find "${d_ldoc}" -type f -name "*.luadoc" ! -name "crafting.luadoc" -exec rm -vf {} +
|
||||
|
||||
# HACK: ldoc does not seem to like the "shields:" prefix
|
||||
echo -e "\ncompensating for LDoc's issue with \"shields:\" prefix ..."
|
||||
sed -i \
|
||||
-e 's/<strong>shield_/<strong>shields:shield_/' \
|
||||
-e 's/<td class="name\(.*\)>shield_/<td class="name\1>shields:shield_/' \
|
||||
-e 's/<a href="#shield_/<a href="#shields:shield_/' \
|
||||
-e 's/<a name.*"shield_/<a name="shields:shield_/' \
|
||||
"${d_export}/topics/shields.html"
|
||||
|
||||
# copy textures to data directory
|
||||
printf "\ncopying textures ..."
|
||||
mkdir -p "${d_data}"
|
||||
texture_count=0
|
||||
for d_mod in armor_* shields; do
|
||||
printf "\rcopying textures from ${d_mod} ...\n"
|
||||
for png in $(find "${d_root}/${d_mod}/textures" -maxdepth 1 -type f -name "*.png"); do
|
||||
if test -f "${d_data}/$(basename ${png})"; then
|
||||
echo "WARNING: not overwriting existing file: ${png}"
|
||||
else
|
||||
cp "${png}" "${d_data}"
|
||||
texture_count=$((texture_count + 1))
|
||||
printf "\rcopied ${texture_count} textures"
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
echo -e "\n\nDone!"
|
305
.ldoc/ldoc.css
Normal file
@ -0,0 +1,305 @@
|
||||
/* BEGIN RESET
|
||||
|
||||
Copyright (c) 2010, Yahoo! Inc. All rights reserved.
|
||||
Code licensed under the BSD License:
|
||||
http://developer.yahoo.com/yui/license.html
|
||||
version: 2.8.2r1
|
||||
*/
|
||||
html {
|
||||
color: #000;
|
||||
background: #FFF;
|
||||
}
|
||||
body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,button,textarea,p,blockquote,th,td {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
}
|
||||
fieldset,img {
|
||||
border: 0;
|
||||
}
|
||||
address,caption,cite,code,dfn,em,strong,th,var,optgroup {
|
||||
font-style: inherit;
|
||||
font-weight: inherit;
|
||||
}
|
||||
del,ins {
|
||||
text-decoration: none;
|
||||
}
|
||||
li {
|
||||
margin-left: 20px;
|
||||
}
|
||||
caption,th {
|
||||
text-align: left;
|
||||
}
|
||||
h1,h2,h3,h4,h5,h6 {
|
||||
font-size: 100%;
|
||||
font-weight: bold;
|
||||
}
|
||||
q:before,q:after {
|
||||
content: '';
|
||||
}
|
||||
abbr,acronym {
|
||||
border: 0;
|
||||
font-variant: normal;
|
||||
}
|
||||
sup {
|
||||
vertical-align: baseline;
|
||||
}
|
||||
sub {
|
||||
vertical-align: baseline;
|
||||
}
|
||||
legend {
|
||||
color: #000;
|
||||
}
|
||||
input,button,textarea,select,optgroup,option {
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
font-style: inherit;
|
||||
font-weight: inherit;
|
||||
}
|
||||
input,button,textarea,select {*font-size:100%;
|
||||
}
|
||||
/* END RESET */
|
||||
|
||||
body {
|
||||
margin-left: 1em;
|
||||
margin-right: 1em;
|
||||
font-family: arial, helvetica, geneva, sans-serif;
|
||||
background-color: #ffffff; margin: 0px;
|
||||
}
|
||||
|
||||
code, tt { font-family: monospace; font-size: 1.1em; }
|
||||
span.parameter { font-family:monospace; }
|
||||
span.parameter:after { content:":"; }
|
||||
span.types:before { content:"("; }
|
||||
span.types:after { content:")"; }
|
||||
.type { font-weight: bold; font-style:italic }
|
||||
|
||||
body, p, td, th { font-size: .95em; line-height: 1.2em;}
|
||||
|
||||
p, ul { margin: 10px 0 0 0px;}
|
||||
|
||||
strong { font-weight: bold;}
|
||||
|
||||
em { font-style: italic;}
|
||||
|
||||
h1 {
|
||||
font-size: 1.5em;
|
||||
margin: 20px 0 20px 0;
|
||||
}
|
||||
h2, h3, h4 { margin: 15px 0 10px 0; }
|
||||
h2 { font-size: 1.25em; }
|
||||
h3 { font-size: 1.15em; }
|
||||
h4 { font-size: 1.06em; }
|
||||
|
||||
a:link { font-weight: bold; color: #004080; text-decoration: none; }
|
||||
a:visited { font-weight: bold; color: #006699; text-decoration: none; }
|
||||
a:link:hover { text-decoration: underline; }
|
||||
|
||||
hr {
|
||||
color:#cccccc;
|
||||
background: #00007f;
|
||||
height: 1px;
|
||||
}
|
||||
|
||||
blockquote { margin-left: 3em; }
|
||||
|
||||
ul { list-style-type: disc; }
|
||||
|
||||
p.name {
|
||||
font-family: "Andale Mono", monospace;
|
||||
padding-top: 1em;
|
||||
}
|
||||
|
||||
pre {
|
||||
background-color: rgb(245, 245, 245);
|
||||
border: 1px solid #C0C0C0; /* silver */
|
||||
padding: 10px;
|
||||
margin: 10px 0 10px 0;
|
||||
overflow: auto;
|
||||
font-family: "Andale Mono", monospace;
|
||||
}
|
||||
|
||||
pre.example {
|
||||
font-size: .85em;
|
||||
}
|
||||
|
||||
table.index { border: 1px #00007f; }
|
||||
table.index td { text-align: left; vertical-align: top; }
|
||||
|
||||
#container {
|
||||
margin-left: 1em;
|
||||
margin-right: 1em;
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
#product {
|
||||
text-align: center;
|
||||
border-bottom: 1px solid #cccccc;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
#product big {
|
||||
font-size: 2em;
|
||||
}
|
||||
|
||||
#main {
|
||||
background-color: #f0f0f0;
|
||||
border-left: 2px solid #cccccc;
|
||||
}
|
||||
|
||||
#navigation {
|
||||
float: left;
|
||||
width: 14em;
|
||||
vertical-align: top;
|
||||
background-color: #f0f0f0;
|
||||
overflow: visible;
|
||||
position: fixed;
|
||||
}
|
||||
|
||||
#navigation h2 {
|
||||
background-color:#e7e7e7;
|
||||
font-size:1.1em;
|
||||
color:#000000;
|
||||
text-align: left;
|
||||
padding:0.2em;
|
||||
border-top:1px solid #dddddd;
|
||||
border-bottom:1px solid #dddddd;
|
||||
}
|
||||
|
||||
#navigation ul
|
||||
{
|
||||
font-size:1em;
|
||||
list-style-type: none;
|
||||
margin: 1px 1px 10px 1px;
|
||||
}
|
||||
|
||||
#navigation li {
|
||||
text-indent: -1em;
|
||||
display: block;
|
||||
margin: 3px 0px 0px 22px;
|
||||
}
|
||||
|
||||
#navigation li li a {
|
||||
margin: 0px 3px 0px -1em;
|
||||
}
|
||||
|
||||
#content {
|
||||
margin-left: 14em;
|
||||
padding: 1em;
|
||||
width: 700px;
|
||||
border-left: 2px solid #cccccc;
|
||||
border-right: 2px solid #cccccc;
|
||||
background-color: #ffffff;
|
||||
min-height: 425px;
|
||||
}
|
||||
|
||||
#about {
|
||||
clear: both;
|
||||
padding: 5px;
|
||||
border-top: 2px solid #cccccc;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
@media print {
|
||||
body {
|
||||
font: 12pt "Times New Roman", "TimeNR", Times, serif;
|
||||
}
|
||||
a { font-weight: bold; color: #004080; text-decoration: underline; }
|
||||
|
||||
#main {
|
||||
background-color: #ffffff;
|
||||
border-left: 0px;
|
||||
}
|
||||
|
||||
#container {
|
||||
margin-left: 2%;
|
||||
margin-right: 2%;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
#content {
|
||||
padding: 1em;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
#navigation {
|
||||
display: none;
|
||||
}
|
||||
pre.example {
|
||||
font-family: "Andale Mono", monospace;
|
||||
font-size: 10pt;
|
||||
page-break-inside: avoid;
|
||||
}
|
||||
}
|
||||
|
||||
table.module_list {
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
border-color: #cccccc;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
table.module_list td {
|
||||
border-width: 1px;
|
||||
padding: 3px;
|
||||
border-style: solid;
|
||||
border-color: #cccccc;
|
||||
}
|
||||
table.module_list td.name { background-color: #f0f0f0; min-width: 200px; }
|
||||
table.module_list td.summary { width: 100%; }
|
||||
|
||||
|
||||
table.function_list {
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
border-color: #cccccc;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
table.function_list td {
|
||||
border-width: 1px;
|
||||
padding: 3px;
|
||||
border-style: solid;
|
||||
border-color: #cccccc;
|
||||
}
|
||||
table.function_list td.name { background-color: #f0f0f0; min-width: 200px; }
|
||||
table.function_list td.summary { width: 100%; }
|
||||
|
||||
ul.nowrap {
|
||||
overflow:auto;
|
||||
white-space:nowrap;
|
||||
}
|
||||
|
||||
dl.table dt, dl.function dt {border-top: 1px solid #ccc; padding-top: 1em;}
|
||||
dl.table dd, dl.function dd {padding-bottom: 1em; margin: 10px 0 0 20px;}
|
||||
dl.table h3, dl.function h3 {font-size: .95em;}
|
||||
|
||||
/* stop sublists from having initial vertical space */
|
||||
ul ul { margin-top: 0px; }
|
||||
ol ul { margin-top: 0px; }
|
||||
ol ol { margin-top: 0px; }
|
||||
ul ol { margin-top: 0px; }
|
||||
|
||||
/* make the target distinct; helps when we're navigating to a function */
|
||||
a:target + * {
|
||||
background-color: #FF9;
|
||||
}
|
||||
|
||||
|
||||
/* styles for prettification of source */
|
||||
pre .comment { color: #558817; }
|
||||
pre .constant { color: #a8660d; }
|
||||
pre .escape { color: #844631; }
|
||||
pre .keyword { color: #aa5050; font-weight: bold; }
|
||||
pre .library { color: #0e7c6b; }
|
||||
pre .marker { color: #512b1e; background: #fedc56; font-weight: bold; }
|
||||
pre .string { color: #8080ff; }
|
||||
pre .number { color: #f8660d; }
|
||||
pre .operator { color: #2239a8; font-weight: bold; }
|
||||
pre .preprocessor, pre .prepro { color: #a33243; }
|
||||
pre .global { color: #800080; }
|
||||
pre .user-keyword { color: #800080; }
|
||||
pre .prompt { color: #558817; }
|
||||
pre .url { color: #272fc2; text-decoration: underline; }
|
||||
|
118
.ldoc/parse_settings.py
Executable file
@ -0,0 +1,118 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# This script will format "settingtypes.txt" file found at the root
|
||||
# of 3d_armor modpack into a format readable by LDoc.
|
||||
|
||||
import sys, os, errno, codecs
|
||||
|
||||
|
||||
path = os.path.realpath(__file__)
|
||||
script = os.path.basename(path)
|
||||
d_root = os.path.dirname(os.path.dirname(path))
|
||||
d_ldoc = os.path.join(d_root, ".ldoc")
|
||||
f_settings = os.path.join(d_root, "settingtypes.txt")
|
||||
|
||||
if not os.path.isfile(f_settings):
|
||||
print("settingtypes.txt does not exist")
|
||||
sys.exit(errno.ENOENT)
|
||||
|
||||
i_stream = codecs.open(f_settings, "r", "utf-8")
|
||||
data_in = i_stream.read()
|
||||
i_stream.close()
|
||||
|
||||
data_in = data_in.replace("\r", "")
|
||||
|
||||
sets = data_in.split("\n\n")
|
||||
|
||||
for idx in reversed(range(len(sets))):
|
||||
set = sets[idx]
|
||||
lines = set.split("\n")
|
||||
for idx2 in reversed(range(len(lines))):
|
||||
li = lines[idx2].strip(" \t")
|
||||
if li == "" or li[0] == "[":
|
||||
lines.pop(idx2)
|
||||
|
||||
if len(lines) == 0:
|
||||
sets.pop(idx)
|
||||
else:
|
||||
sets[idx] = "\n".join(lines)
|
||||
|
||||
filtered = []
|
||||
|
||||
for set in sets:
|
||||
comment = False
|
||||
lines = set.split("\n")
|
||||
new_lines = []
|
||||
for li in lines:
|
||||
if li[0] == "#":
|
||||
new_lines.append(li)
|
||||
else:
|
||||
new_lines.append(li)
|
||||
filtered.append("\n".join(new_lines))
|
||||
new_lines = []
|
||||
|
||||
settings = []
|
||||
|
||||
def parse_setting(set):
|
||||
desc = []
|
||||
setting = summary = stype = sdefault = soptions = None
|
||||
|
||||
for li in set.split("\n"):
|
||||
if li[0] == "#":
|
||||
desc.append("-- {}".format(li.lstrip(" #")))
|
||||
else:
|
||||
setting = li.split(" ")[0]
|
||||
summary = li.split(")")[0].split("(")[-1]
|
||||
li = li.split(")")[-1].strip()
|
||||
rem = li.split(" ")
|
||||
stype = rem[0]
|
||||
rem.pop(0)
|
||||
|
||||
if len(rem) > 0:
|
||||
sdefault = rem[0]
|
||||
rem.pop(0)
|
||||
|
||||
if len(rem) > 0:
|
||||
soptions = " ".join(rem)
|
||||
|
||||
if not setting:
|
||||
return
|
||||
|
||||
st = "---"
|
||||
if summary:
|
||||
if summary[-1] != ".":
|
||||
summary = "{}.".format(summary)
|
||||
st = "{} {}".format(st, summary)
|
||||
|
||||
st = "{}\n--".format(st)
|
||||
|
||||
if len(desc) > 0:
|
||||
st = "{}\n{}\n--".format(st, "\n".join(desc))
|
||||
|
||||
st = "{}\n-- @setting {}".format(st, setting)
|
||||
|
||||
if stype:
|
||||
st = "{}\n-- @settype {}".format(st, stype)
|
||||
|
||||
if sdefault:
|
||||
st = "{}\n-- @default {}".format(st, sdefault)
|
||||
|
||||
# TODO: add options
|
||||
|
||||
settings.append(st)
|
||||
|
||||
for f in filtered:
|
||||
parse_setting(f)
|
||||
|
||||
outfile = os.path.join(d_ldoc, "settings.luadoc")
|
||||
data_out = "\n--- 3D Armor Settings\n--\n-- @topic settings\n\n\n{}\n".format("\n\n".join(settings))
|
||||
|
||||
o_stream = codecs.open(outfile, "w", "utf-8")
|
||||
if not o_stream:
|
||||
print("ERROR: could not open file for writing: {}".format(outfile))
|
||||
sys.exit(errno.EIO)
|
||||
|
||||
o_stream.write(data_out)
|
||||
o_stream.close()
|
||||
|
||||
print("settings exported to\t{}".format(outfile))
|
90
.ldoc/parse_src.py
Executable file
@ -0,0 +1,90 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# This script will parse source files for docstring.
|
||||
|
||||
import os, codecs
|
||||
|
||||
|
||||
path = os.path.realpath(__file__)
|
||||
script = os.path.basename(path)
|
||||
d_root = os.path.dirname(os.path.dirname(path))
|
||||
d_ldoc = os.path.join(d_root, ".ldoc")
|
||||
|
||||
|
||||
armor_types = {
|
||||
"armor": {"topic": "Armors", "values": []},
|
||||
"helmet": {"topic": "Helmets", "values": []},
|
||||
"chestplate": {"topic": "Chestplates", "values": []},
|
||||
"leggings": {"topic": "Leggings", "values": []},
|
||||
"boots": {"topic": "Boots", "values": []},
|
||||
#"shield": {"topic": "Shields", "values": []},
|
||||
}
|
||||
|
||||
def parse_file(f):
|
||||
buffer = codecs.open(f, "r", "utf-8")
|
||||
if not buffer:
|
||||
print("ERROR: could not open file for reading: {}".format(f))
|
||||
return
|
||||
|
||||
data_in = buffer.read()
|
||||
buffer.close()
|
||||
|
||||
# format to LF (Unix)
|
||||
data_in = data_in.replace("\r\n", "\n").replace("\r", "\n")
|
||||
|
||||
current_item = []
|
||||
item_type = None
|
||||
new_item = False
|
||||
for li in data_in.split("\n"):
|
||||
li = li.strip()
|
||||
if li.startswith("---"):
|
||||
new_item = True
|
||||
elif not li.startswith("--"):
|
||||
new_item = False
|
||||
|
||||
if new_item:
|
||||
current_item.append(li)
|
||||
if not item_type:
|
||||
for a_type in armor_types:
|
||||
if "@{} ".format(a_type) in li:
|
||||
item_type = a_type
|
||||
break
|
||||
elif item_type and len(current_item):
|
||||
armor_types[item_type]["values"].append("\n".join(current_item))
|
||||
item_type = None
|
||||
current_item = []
|
||||
else:
|
||||
current_item = []
|
||||
|
||||
to_parse = []
|
||||
|
||||
for obj in os.listdir(d_root):
|
||||
fullpath = os.path.join(d_root, obj)
|
||||
if not obj.startswith(".") and os.path.isdir(fullpath):
|
||||
for root, dirs, files in os.walk(fullpath):
|
||||
for f in files:
|
||||
if f.endswith(".lua"):
|
||||
to_parse.append(os.path.join(root, f))
|
||||
|
||||
for p in to_parse:
|
||||
if not os.path.isfile(p):
|
||||
print("ERROR: {} is not a file".format(p))
|
||||
else:
|
||||
parse_file(p)
|
||||
|
||||
for t in armor_types:
|
||||
topic = armor_types[t]["topic"]
|
||||
items = armor_types[t]["values"]
|
||||
|
||||
if len(items):
|
||||
outfile = os.path.join(d_ldoc, "{}.luadoc".format(topic.lower()))
|
||||
|
||||
buffer = codecs.open(outfile, "w", "utf-8")
|
||||
if not buffer:
|
||||
print("ERROR: could not open file for writing: {}".format(outfile))
|
||||
continue
|
||||
|
||||
buffer.write("\n--- 3D Armor {}\n--\n-- @topic {}\n\n\n{}\n".format(topic, topic.lower(), "\n\n".join(items)))
|
||||
buffer.close()
|
||||
|
||||
print("{} exported to\t{}".format(topic.lower(), outfile))
|
33
.luacheckrc
Normal file
@ -0,0 +1,33 @@
|
||||
|
||||
unused_args = false
|
||||
|
||||
globals = {
|
||||
"wieldview",
|
||||
"armor",
|
||||
"inventory_plus"
|
||||
}
|
||||
|
||||
read_globals = {
|
||||
-- Stdlib
|
||||
string = {fields = {"split"}},
|
||||
table = {fields = {"copy", "getn"}},
|
||||
|
||||
-- Minetest
|
||||
"vector", "ItemStack",
|
||||
"dump", "VoxelArea",
|
||||
|
||||
-- deps
|
||||
"default",
|
||||
"player_api",
|
||||
"minetest",
|
||||
"unified_inventory",
|
||||
"wardrobe",
|
||||
"player_monoids",
|
||||
"armor_monoid",
|
||||
"sfinv",
|
||||
"ARMOR_MATERIALS",
|
||||
"ARMOR_FIRE_NODES",
|
||||
"pova",
|
||||
"skins",
|
||||
"u_skins"
|
||||
}
|
525
3d_armor/README.md
Normal file
@ -0,0 +1,525 @@
|
||||
# [mod] Visible Player Armor [3d_armor]
|
||||
|
||||
| | | | |
|
||||
|--|--|--|--|
|
||||
|-[Overview](#overview) |||-[API](#api)
|
||||
|-[Armor Configuration](#armor-configuration) |||- - [3d_Armor Item Storage](#3d_armor-item-storage)
|
||||
|- - [disable_specific_materials](#to-disable-individual-armor-materials) |||- - [Armor Registration](#armor-registration)
|
||||
|- - [armor_init_delay](#initialization-glitches-when-a-player-first-joins) |||- - [Registering Armor Groups](#registering-armor-groups)
|
||||
|- - [wieldview_update_time](#how-often-player-wield-items-are-updated) |||- - [Groups used by 3d_Armor](#groups-used-by-3d_armor)
|
||||
|- - [armor_bones_delay](#armor-not-in-bones-due-to-server-lag) |||- - - [Elements](#elements)
|
||||
|- - [armor_update_time](#how-often-player-armor-items-are-updated) |||- - - [Attributes](#attributes)
|
||||
|- - [armor_drop](#drop-armor-when-a-player-dies) |||- - - [Physics](#physics)
|
||||
|- - [armor_destroy](#destroy-armor-when-a-player-dies) |||- - - [Durability](#durability)
|
||||
|- - [armor_level_multiplier](#armor-level-multiplyer) |||- - - [Armor Material](#armor-material)
|
||||
|- - [armor_heal_multiplier](#armor-healing-multiplyer) |||- - [Armour Functions](#armor-functions)
|
||||
|- - [armor_set_elements](#allows-the-customisation-of-armor-set) |||- - - [armor:set_player_armor](#armor-set_player_armor)
|
||||
|- - [armor_set_bonus](#armor-set-bonus-multiplier) |||- - - [armor:punch](#armor-punch)
|
||||
|- - [armor_water_protect](#enable-water-protection) |||- - - [armor:damage](#armor-damage)
|
||||
|- - [armor_fire_protect](#enable-fire-protection) |||- - - [armor:remove_all](#armor-remove_all)
|
||||
|- - [armor_punch_damage](#enable-punch-damage-effects) |||- - - [armor:equip](#armor-equip)
|
||||
|- - [armor_migrate_old_inventory](#migration-of-old-armor-inventories) |||- - - [armor:unequip](#armor-unequip)
|
||||
| |||- - - [armor:update_skin](#armor-update_skin)
|
||||
|-[Credits](#credits) |||- - [Callbacks](#Callbacks)
|
||||
| |||- - - [Item callbacks](#item-callbacks)
|
||||
| |||- - - [Global callbacks](#global-callbacks)
|
||||
|
||||
# Overview
|
||||
|
||||
**Depends:** default
|
||||
|
||||
**Recommends:** sfinv, unified_inventory or smart_inventory (use only one to avoid conflicts)
|
||||
|
||||
**Supports:** player_monoids, armor_monoid and POVA
|
||||
|
||||
Adds craftable armor that is visible to other players. Each armor item worn contributes to
|
||||
a player's armor group level making them less vulnerable to weapons.
|
||||
|
||||
Armor takes damage when a player is hurt but also offers a percentage chance of healing.
|
||||
Overall level is boosted by 10% when wearing a full matching set.
|
||||
|
||||
# Armor Configuration
|
||||
|
||||
Change the following default settings by going to Main Menu>>Settings(Tab)>>All Settings(Button)>>Mods>>minetest-3d_Armor>>3d_Armor
|
||||
|
||||
### To disable individual armor materials
|
||||
**set the below to false**
|
||||
|
||||
armor_material_wood = true
|
||||
armor_material_cactus = true
|
||||
armor_material_steel = true
|
||||
armor_material_bronze = true
|
||||
armor_material_diamond = true
|
||||
armor_material_gold = true
|
||||
armor_material_mithril = true
|
||||
armor_material_crystal = true
|
||||
armor_material_nether = true
|
||||
|
||||
### Initialization glitches when a player first joins
|
||||
**Increase to prevent glitches**
|
||||
|
||||
armor_init_delay = 2
|
||||
|
||||
### Armor not in bones due to server lag
|
||||
**Increase to help resolve**
|
||||
|
||||
armor_bones_delay = 1
|
||||
|
||||
### How often player armor items are updated
|
||||
**Number represents how often per second update is performed, higher value means less performance hit for servers but armor items maybe delayed in updating when switching.Fractional seconds also supported eg 0.1**
|
||||
|
||||
armor_update_time = 1
|
||||
|
||||
### Drop armor when a player dies
|
||||
**Uses bones mod if present, otherwise items are dropped around the player when false.**
|
||||
|
||||
armor_drop = true
|
||||
|
||||
### Destroy armor when a player dies
|
||||
**overrides armor_drop.**
|
||||
|
||||
armor_destroy = false
|
||||
|
||||
### Armor level multiplyer
|
||||
**Increase to make armor more effective and decrease to make armor less effective**
|
||||
**eg: level_multiplier = 0.5 will reduce armor level by half.**
|
||||
|
||||
armor_level_multiplier = 1
|
||||
|
||||
### Armor healing multiplyer
|
||||
**Increase to make armor healing more effective and decrease to make healing less effective**
|
||||
**eg: armor_heal_multiplier = 0 will disable healing altogether.**
|
||||
|
||||
armor_heal_multiplier = 1
|
||||
|
||||
### Allows the customisation of armor set
|
||||
**Shields already configured as need to be worn to complete an armor set**
|
||||
**These names come from [Element names](#groups-used-by-3d_armor), the second half of the element name only is used eg armor_head is head**
|
||||
|
||||
armor_set_elements = head torso legs feet shield
|
||||
|
||||
### Armor set bonus multiplier
|
||||
**Set to 1 to disable set bonus**
|
||||
|
||||
armor_set_multiplier = 1.1
|
||||
|
||||
### Enable water protection
|
||||
**periodically restores breath when activated**
|
||||
|
||||
armor_water_protect = true
|
||||
|
||||
### Enable fire protection
|
||||
**defaults to true if using ethereal mod**
|
||||
|
||||
armor_fire_protect = false
|
||||
|
||||
### Fire protection enabled, disable torch fire damage
|
||||
**when fire protection is enabled allows you to disable fire damage from torches**
|
||||
**defaults to true if using ethereal mod**
|
||||
|
||||
armor_fire_protect_torch = false
|
||||
|
||||
### Enable punch damage effects
|
||||
|
||||
armor_punch_damage = true
|
||||
|
||||
### Migration of old armor inventories
|
||||
|
||||
armor_migrate_old_inventory = true
|
||||
|
||||
### How often player wield items are updated
|
||||
**Number represents how often per second update is performed, higher value means less performance hit for servers but wield items maybe delayed in updating when switching. Fractional seconds also supported eg 0.1**
|
||||
***Note this is MT engine functionality but included for completness***
|
||||
|
||||
wieldview_update_time = 1
|
||||
|
||||
# API
|
||||
|
||||
## 3d_Armor item storage
|
||||
3d_Armor stores each armor piece a player currently has equiped in a ***detached*** inventory. The easiest way to access this inventory if needed is using this line of code
|
||||
|
||||
local _, armor_inv = armor:get_valid_player(player, "3d_armor")
|
||||
|
||||
**Example**
|
||||
|
||||
armor:register_on_equip(function(player, index, stack)
|
||||
local _, armor_inv = armor:get_valid_player(player, "3d_armor")
|
||||
for i = 1, 6 do
|
||||
local stack = armor_inv:get_stack("armor", i)
|
||||
if stack:get_name() == "3d_armor:chestplate_gold" then
|
||||
minetest.chat_send_player(player:get_player_name(),"Got to love the Bling!!!")
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
## Armor Registration
|
||||
|
||||
armor:register_armor(name, def)
|
||||
|
||||
Wrapper function for `minetest.register_tool`, which enables the easy registration of new armor items. While registering armor as a tool item is still supported, this may be deprecated in future so all armor items should be registered using *armor:register_armor(name,def)*.
|
||||
|
||||
### Additional fields supported by 3d_armor
|
||||
|
||||
texture = <filename>
|
||||
preview = <filename>
|
||||
armor_groups = <table>
|
||||
damage_groups = <table>
|
||||
reciprocate_damage = <bool>
|
||||
on_equip = <function>
|
||||
on_unequip = <function>
|
||||
on_destroy = <function>
|
||||
on_damage = <function>
|
||||
on_punched = <function>
|
||||
|
||||
***Reciprocal tool*** damage will apply damage back onto the attacking tool/weapon, however this will only be done by the first armor inventory item with `reciprocate_damage = true`, damage does not stack.
|
||||
|
||||
**Example Simple:**
|
||||
|
||||
armor:register_armor("mod_name:chestplate_leather", {
|
||||
description = "Leather Chestplate",
|
||||
inventory_image = "mod_name_inv_chestplate_leather.png",
|
||||
texture = "mod_name_leather_chestplate.png",
|
||||
preview = "mod_name_leather_chestplate_preview.png",
|
||||
groups = {armor_torso=1, armor_heal=0, armor_use=2000, flammable=1},
|
||||
armor_groups = {fleshy=10},
|
||||
damage_groups = {cracky=3, snappy=2, choppy=3, crumbly=2, level=1}
|
||||
})
|
||||
*See ***armor.lua*** under **3d_armor>>3d_armor** for further examples*
|
||||
|
||||
**Extended functionality**
|
||||
The values for ***texture*** and ***preview*** do not need to be included when registering armor if they follow the naming convention in the textures mod folder of:
|
||||
***texture:*** *mod_name_leather_chestplate.png*
|
||||
***preview:*** *mod_name_leather_chestplate_preview.png*
|
||||
|
||||
## Registering Armor Groups
|
||||
3d armor has a built in armor group which is ***fleshy*** all players base vulnerability to being fleshy is ***100***.
|
||||
3d armour allows for the easy registration/addition of new armor groups::
|
||||
|
||||
armor:register_armor_group(group, base)
|
||||
|
||||
***group:*** Is the name of the new armor group
|
||||
***base*** Is the starting vulnerability that all players have to that new group. This dosent need to be 100.
|
||||
|
||||
**Example**
|
||||
|
||||
armor:register_armor_group("radiation", 100)
|
||||
|
||||
New armor group is registered called *radiation* and all players start off with a base vulnerability of *100* to radiation.
|
||||
|
||||
**Example** *Showing armor reg, new group usage and custom function*
|
||||
|
||||
armor:register_armor("mod_name:speed_boots", {
|
||||
description = "Speed Boots",
|
||||
inventory_image = "mod_name_speed_boots_inv.png",
|
||||
texture = "mod_name_speed_boots.png",
|
||||
preview = "mod_name_speed_boots_preview.png",
|
||||
groups = {armor_feet=1, armor_use=500, physics_speed=1.2, flammable=1},
|
||||
armor_groups = {fleshy=10, radiation=10},
|
||||
damage_groups = {cracky=3, snappy=3, choppy=3, crumbly=3, level=1},
|
||||
reciprocate_damage = true,
|
||||
on_destroy = function(player, index, stack)
|
||||
local pos = player:get_pos()
|
||||
if pos then
|
||||
minetest.sound_play({
|
||||
name = "mod_name_break_sound",
|
||||
pos = pos,
|
||||
gain = 0.5,
|
||||
})
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
### Tools/weapons and new armor groups
|
||||
The above allows armor to block/prevent new damage types but you also need to assign the new damage group to a tool/weapon or even a node (see technic mod) to make wearing the armor item meaningful. Simply add the ***armor_groups*** name to the tool items ***damage_groups***.
|
||||
|
||||
**Example**
|
||||
|
||||
minetest.register_tool("mod_name:glowing_sword", {
|
||||
description = "Glowing Sword",
|
||||
inventory_image = "mod_name_tool_glowingsword.png",
|
||||
tool_capabilities = {full_punch_interval = 1.2,max_drop_level=0,
|
||||
groupcaps={
|
||||
cracky = {times={[3]=1.60}, uses=10, maxlevel=1},},
|
||||
damage_groups = {fleshy=10,radiation=20},
|
||||
},
|
||||
sound = {breaks = "default_tool_breaks"},
|
||||
groups = {pickaxe = 1, flammable = 2}
|
||||
})
|
||||
|
||||
## Groups used by 3d_Armor
|
||||
3d_armor has many default groups already registered, these are categorized under 4 main headings
|
||||
- **Elements:** armor_head, armor_torso, armor_legs, armor_feet
|
||||
- **Attributes:** armor_heal, armor_fire, armor_water, armor_feather
|
||||
- **Physics:** physics_jump, physics_speed, physics_gravity
|
||||
- **Durability:** armor_use, flammable
|
||||
|
||||
***Note: for calculation purposes "Attributes" and "Physics" values stack***
|
||||
|
||||
### Elements
|
||||
Additional armor elements can be added by dependant mods, for example shields adds the group armor_shield which has by default a limit that only 1 shield can be worn at a time.
|
||||
|
||||
Adding Elements is more complex but the below code can be used to add new elements;
|
||||
|
||||
if minetest.global_exists("armor") and armor.elements then
|
||||
table.insert(armor.elements, "hands")
|
||||
end
|
||||
**1st line** not strictly needed but checks that the global table "armor" and subtable "elements" exists
|
||||
**2nd line** adds a new value to the armor.elements table called "hands"
|
||||
|
||||
See ***init.lua*** under **3d_armor>>shields** for a further example
|
||||
|
||||
The new armor item can now be registered using the new element
|
||||
**Example**
|
||||
|
||||
armor:register_armor("mod_name:gloves_wood", {
|
||||
description = "Wood Gauntlets",
|
||||
inventory_image = "mod_name_inv_gloves_wood.png",
|
||||
texture = "mod_name_gloves_wood.png",
|
||||
preview = "mod_name_gloves_wood_preview.png",
|
||||
groups = {armor_hands=1, armor_heal=0, armor_use=2000, flammable=1},
|
||||
armor_groups = {fleshy=5},
|
||||
damage_groups = {cracky=3, snappy=2, choppy=3, crumbly=2, level=1},
|
||||
})
|
||||
|
||||
### Attributes
|
||||
Three attributes are avaliable in 3d_armor these are armor_heal, armor_fire and armor_water. Although possible to add additional attributes they would do nothing as code needs to be provide to specifiy the behaviour this could be done in a dependant mod
|
||||
|
||||
#### Armor_heal
|
||||
This isn't how much the armor will heal but relates to the chance the armor will completely block the damage. For each point of ***armor_heal*** there is a 1% chance that damage will be completely blocked, this value will stack between all armor pieces
|
||||
|
||||
**Example**
|
||||
The below Diamond chestplate has a 12% chance to completely block all damage (armor_heal=12), however so do boots, helmet and trousers so if the player was wearing all 4 pieces they would have a 48% chance of blocking all damage each attack.
|
||||
|
||||
armor:register_armor("3d_armor:chestplate_diamond", {
|
||||
description = S("Diamond Chestplate"),
|
||||
inventory_image = "3d_armor_inv_chestplate_diamond.png",
|
||||
groups = {armor_torso=1, armor_heal=12, armor_use=200},
|
||||
armor_groups = {fleshy=20},
|
||||
damage_groups = {cracky=2, snappy=1, choppy=1, level=3},
|
||||
})
|
||||
|
||||
#### Armor_fire
|
||||
***"Armor_fire"*** provides 5 levels of fire protection
|
||||
- level 1 protects against torches
|
||||
- level 2 protects against crystal spike (Ethereal mod)
|
||||
- level 3 protects against fire
|
||||
- level 4 unused
|
||||
- level 5 protects against lava
|
||||
|
||||
**Example**
|
||||
|
||||
armor:register_armor("mod_name:fire_proof_jacket", {
|
||||
description = "Fire Proof Jacket",
|
||||
inventory_image = "mod_name_inv_fire_proof_jacket.png",
|
||||
groups = {armor_torso=1, armor_fire=3, armor_use=1000},
|
||||
armor_groups = {fleshy=10},
|
||||
damage_groups = {cracky=2, snappy=1, choppy=1, level=3},
|
||||
})
|
||||
|
||||
#### Armor_water
|
||||
***"Armor_water"*** will periodically restore a players breath when underwater. This only has one level or state, which is armor_water=1
|
||||
|
||||
**Example**
|
||||
|
||||
armor:register_armor("mod_name:helmet_underwater_breath", {
|
||||
description = "Helmet of Underwater Breathing",
|
||||
inventory_image = "mod_name_inv_helmet_underwater_breath.png",
|
||||
groups = {armor_head=1, armor_water=1, armor_use=1000},
|
||||
armor_groups = {fleshy=5},
|
||||
damage_groups = {cracky=2, snappy=1, choppy=1, level=3},
|
||||
})
|
||||
|
||||
#### Armor_feather
|
||||
***"Armor_feather"*** will slow a player when falling. This only has one level or state, which is armor_feather=1
|
||||
|
||||
### Physics
|
||||
The physics attributes supported by 3d_armor are ***physics_jump, physics_speed and physics_gravity***. Although 3d_armor supports the use of this with no other mods it is recommended that the mod [player_monoids](https://forum.minetest.net/viewtopic.php?t=14895) is used to help with intermod compatability.
|
||||
|
||||
***physics_jump*** - Will increase/decrease the jump strength of the player so they can jump more/less. The base number is "1" and any value is added or subtracted, supports fractional so "physics_jump=1" will increase jump strength by 100%. "physics_jump= -0.5" will decrease jump by 50%.
|
||||
|
||||
***physics_speed*** - Will increase/decrease the walk speed of the player so they walk faster/slower. The base number is "1" and any value is added or subtracted, supports fractional so "physics_speed=1.5" will increase speed by 150%, "physics_speed= -0.5" will decrease speed by 50%.
|
||||
|
||||
***physics_gravity*** - Will increase/decrease gravity the player experiences so it's higher/lower. The base number is "1" and any value is added or subtracted, supports fractional so "physics_gravity=2" will increase gravity by 200%, "physics_gravity= -1" will decrease gravity by 100%.
|
||||
|
||||
*Note: The player physics modifications won't be applied via `set_physics_override` if `player_physics_locked` is set to 1 in the respective player's meta.*
|
||||
|
||||
### Durability
|
||||
Durability is determined by the value assigned to the group ***armor_use***. The higher the ***armor_use*** value the faster/more quickly it is damaged/degrades. This is calculated using the formula:
|
||||
|
||||
Total uses = approx(65535/armor_use)
|
||||
|
||||
**Example**
|
||||
All wood armor items have an ***armor_use=2000***;
|
||||
|
||||
65535/2000 = 32.76 (32)
|
||||
After 32 uses(hits) the armor item will break.
|
||||
|
||||
All diamond armor items have an ***armor_use=200***;
|
||||
|
||||
65535/2000 = 327.6 (327)
|
||||
After 327 uses(hits) the armor item will break.
|
||||
|
||||
### Armor Material
|
||||
The material the armor is made from is defined by adding the material to the end of registered armor item name. It is very important the material is the last item in the registered item name and it is preceeded by an "_" eg "_materialname".
|
||||
The material name is what 3d_armor uses to determine if a player is wearing a set of armor. To recieve the set bonus all items worn must be made of the same material.
|
||||
So to get a set bonus under the default set settings the players armor items listed below must be made of the same material:
|
||||
* head - Helmet
|
||||
* torso - Chestplate
|
||||
* legs - Leggings
|
||||
* feet - Boots
|
||||
* shield - Shields
|
||||
|
||||
If all of the above were made of material "wood" the player would recieve an ***armor_set_bonus*** of armor_level * 1.1, essentially +10%
|
||||
|
||||
**Example One**
|
||||
|
||||
armor:register_armor("3d_armor:helmet_bronze", {
|
||||
description = S("Bronze Helmet"),
|
||||
inventory_image = "3d_armor_inv_helmet_bronze.png",
|
||||
groups = {armor_head=1, armor_heal=6, armor_use=400, physics_speed=-0.01, physics_gravity=0.01},
|
||||
armor_groups = {fleshy=10},
|
||||
damage_groups = {cracky=3, snappy=2, choppy=2, crumbly=1, level=2},
|
||||
})
|
||||
|
||||
**Example Two**
|
||||
|
||||
armor:register_armor("new_mod:helmet_spartan_bronze", {
|
||||
description = S("Spartan Helmet"),
|
||||
inventory_image = "new_mod_inv_helmet_spartan_bronze.png",
|
||||
groups = {armor_head=1, armor_heal=6, armor_use=350, physics_speed=-0.01, physics_gravity=0.01},
|
||||
armor_groups = {fleshy=12},
|
||||
damage_groups = {cracky=3, snappy=2, choppy=2, crumbly=1, level=2},
|
||||
})
|
||||
|
||||
***Note: At the moment an armor item can only be made of one material***
|
||||
|
||||
## Armor Functions
|
||||
|
||||
See also: [API Reference](https://minetest-mods.github.io/3d_armor/reference/)
|
||||
|
||||
### armor set_player_armor
|
||||
|
||||
armor:set_player_armor(player)
|
||||
|
||||
Primarily an internal function but can be called externally to apply any
|
||||
changes that might not otherwise get handled.
|
||||
|
||||
### armor punch
|
||||
|
||||
armor:punch(player, hitter, time_from_last_punch, tool_capabilities)
|
||||
|
||||
Used to apply damage to all equipped armor based on the damage groups of
|
||||
each individual item.`hitter`, `time_from_last_punch` and `tool_capabilities`
|
||||
are optional but should be valid if included.
|
||||
|
||||
### armor damage
|
||||
|
||||
armor:damage(player, index, stack, use)
|
||||
|
||||
Adds wear to a single armor itemstack, triggers `on_damage` callbacks and
|
||||
updates the necessary inventories. Also handles item destruction callbacks
|
||||
and so should NOT be called from `on_unequip` to avoid an infinite loop.
|
||||
|
||||
### armor remove_all
|
||||
|
||||
armor:remove_all(player)
|
||||
|
||||
Removes all armors from the player's inventory without triggering any callback.
|
||||
|
||||
### armor equip
|
||||
|
||||
armor:equip(player, armor_name)
|
||||
|
||||
Equip the armor, removing the itemstack from the main inventory if there's one.
|
||||
|
||||
### armor unequip
|
||||
|
||||
armor:unequip(player, armor_name)
|
||||
|
||||
Unequip the armor, adding the itemstack to the main inventory.
|
||||
|
||||
### armor update_skin
|
||||
|
||||
armor:update_skin(player_name)
|
||||
|
||||
Triggers a skin update with the same action as if a field with `skins_set` was submitted.
|
||||
|
||||
## Callbacks
|
||||
|
||||
### Item Callbacks
|
||||
|
||||
In all of the below when armor is destroyed `stack` will contain a copy of the previous stack.
|
||||
|
||||
*unsure what this note means may apply to all item callbacks or just on_punched*
|
||||
Return `false` to override armor damage effects.
|
||||
|
||||
#### on_equip
|
||||
|
||||
on_equip = func(player, index, stack)
|
||||
|
||||
#### on_unequip
|
||||
|
||||
on_unequip = func(player, index, stack)
|
||||
|
||||
#### on_destroy
|
||||
|
||||
on_destroy = func(player, index, stack)
|
||||
|
||||
#### on_damage
|
||||
|
||||
on_damage = func(player, index, stack)
|
||||
|
||||
#### on_punched
|
||||
|
||||
on_punched = func(player, hitter, time_from_last_punch, tool_capabilities)
|
||||
|
||||
`on_punched` is called every time a player is punched or takes damage, `hitter`, `time_from_last_punch` and `tool_capabilities` can be `nil` and will be in the case of fall damage.
|
||||
When fire protection is enabled, hitter == "fire" in the event of fire damage.
|
||||
|
||||
|
||||
### Global Callbacks
|
||||
|
||||
#### armor register_on_update
|
||||
|
||||
armor:register_on_update(function(player))
|
||||
|
||||
#### armor register_on_equip
|
||||
|
||||
armor:register_on_equip(function(player, index, stack))
|
||||
|
||||
#### armor register_on_unequip
|
||||
|
||||
armor:register_on_unequip(function(player, index, stack))
|
||||
|
||||
#### armor register_on_destroy
|
||||
armor:register_on_destroy(function(player, index, stack))
|
||||
|
||||
**Example**
|
||||
|
||||
armor:register_on_update(function(player)
|
||||
print(player:get_player_name().." armor updated!")
|
||||
end)
|
||||
|
||||
|
||||
# Credits
|
||||
|
||||
### The below have added too, tested or in other ways contributed to the development and ongoing support of 3d_Armor
|
||||
|
||||
|Stu |Stujones11 |Stu |Github Ghosts |
|
||||
|:---------------:|:---------------:|:---------------:|:---------------:|
|
||||
|Pavel_S |BlockMen |Tenplus1 |donat-b |
|
||||
|JPRuehmann |BrandonReese |Megaf |Zeg9 |
|
||||
|poet.nohit |Echoes91 |Adimgar |Khonkhortisan |
|
||||
|VanessaE |CraigyDavi |proller |Thomasrudin |
|
||||
|Byakuren |kilbith (jp) |afflatus |G1ov4 |
|
||||
|Thomas-S |Dragonop |Napiophelios |Emojigit |
|
||||
|rubenwardy |daviddoesminetest|bell07 |OgelGames |
|
||||
|tobyplowy |crazyginger72 |fireglow |bhree |
|
||||
|Lone_Wolf(HT) |Wuzzy(2) |numberZero |Monte48 |
|
||||
|AntumDeluge |Terumoc |runsy |Dacmot |
|
||||
|codexp |davidthecreator |SmallJoker |orbea |
|
||||
|BuckarooBanzay |daret |Exeterdad |Calinou |
|
||||
|Pilcrow182 |indriApollo |HybridDog |CraigyDavi |
|
||||
|Paly-2 |Diogogomes | | |
|
||||
|
||||
*Note: Names gathered from 3d_armor forum thread and github, I may have missed some people, apologises if I have - S01*
|
@ -1,15 +0,0 @@
|
||||
[mod] Visible Player Armor [3d_armor]
|
||||
=====================================
|
||||
|
||||
depends: default, inventory_plus, unified_skins
|
||||
|
||||
Adds craftable armor that is visible to other players. Each armor item worn contibutes to
|
||||
a player's armor group level making them less vulnerable to weapons.
|
||||
|
||||
Armor takes damage when a player is hurt but also offers a percentage chance of healing.
|
||||
|
||||
default settings: [minetest.conf]
|
||||
|
||||
# Set number of seconds between armor updates.
|
||||
3d_armor_update_time = 1
|
||||
|
982
3d_armor/api.lua
Normal file
@ -0,0 +1,982 @@
|
||||
|
||||
--- 3D Armor API
|
||||
--
|
||||
-- @topic api
|
||||
|
||||
|
||||
local transparent_armor = minetest.settings:get_bool("armor_transparent", false)
|
||||
|
||||
|
||||
--- Tables
|
||||
--
|
||||
-- @section tables
|
||||
|
||||
--- Armor definition table used for registering armor.
|
||||
--
|
||||
-- @table ArmorDef
|
||||
-- @tfield string description Human-readable name/description.
|
||||
-- @tfield string inventory_image Image filename used for icon.
|
||||
-- @tfield table groups See: `ArmorDef.groups`
|
||||
-- @tfield table armor_groups See: `ArmorDef.armor_groups`
|
||||
-- @tfield table damage_groups See: `ArmorDef.damage_groups`
|
||||
-- @see ItemDef
|
||||
-- @usage local def = {
|
||||
-- description = "Wood Helmet",
|
||||
-- inventory_image = "3d_armor_inv_helmet_wood.png",
|
||||
-- groups = {armor_head=1, armor_heal=0, armor_use=2000, flammable=1},
|
||||
-- armor_groups = {fleshy=5},
|
||||
-- damage_groups = {cracky=3, snappy=2, choppy=3, crumbly=2, level=1},
|
||||
-- }
|
||||
|
||||
--- Groups table.
|
||||
--
|
||||
-- General groups defining item behavior.
|
||||
--
|
||||
-- Some commonly used groups: ***armor\_<type>***, ***armor\_heal***, ***armor\_use***
|
||||
--
|
||||
-- @table ArmorDef.groups
|
||||
-- @tfield int armor_type The armor type. "head", "torso", "hands", "shield", etc.
|
||||
-- (**Note:** replace "type" with actual type).
|
||||
-- @tfield int armor_heal Healing value of armor when equipped.
|
||||
-- @tfield int armor_use Amount of uses/damage before armor "breaks".
|
||||
-- @see groups
|
||||
-- @usage groups = {
|
||||
-- armor_head = 1,
|
||||
-- armor_heal = 5,
|
||||
-- armor_use = 2000,
|
||||
-- flammable = 1,
|
||||
-- }
|
||||
|
||||
--- Armor groups table.
|
||||
--
|
||||
-- Groups that this item is effective against when taking damage.
|
||||
--
|
||||
-- Some commonly used groups: ***fleshy***
|
||||
--
|
||||
-- @table ArmorDef.armor_groups
|
||||
-- @usage armor_groups = {
|
||||
-- fleshy = 5,
|
||||
-- }
|
||||
|
||||
--- Damage groups table.
|
||||
--
|
||||
-- Groups that this item is effective on when used as a weapon/tool.
|
||||
--
|
||||
-- Some commonly used groups: ***cracky***, ***snappy***, ***choppy***, ***crumbly***, ***level***
|
||||
--
|
||||
-- @table ArmorDef.damage_groups
|
||||
-- @see entity_damage_mechanism
|
||||
-- @usage damage_groups = {
|
||||
-- cracky = 3,
|
||||
-- snappy = 2,
|
||||
-- choppy = 3,
|
||||
-- crumbly = 2,
|
||||
-- level = 1,
|
||||
-- }
|
||||
|
||||
--- @section end
|
||||
|
||||
|
||||
-- support for i18n
|
||||
local S = minetest.get_translator(minetest.get_current_modname())
|
||||
|
||||
local skin_previews = {}
|
||||
local use_player_monoids = minetest.global_exists("player_monoids")
|
||||
local use_armor_monoid = minetest.global_exists("armor_monoid")
|
||||
local use_pova_mod = minetest.get_modpath("pova")
|
||||
local armor_def = setmetatable({}, {
|
||||
__index = function()
|
||||
return setmetatable({
|
||||
groups = setmetatable({}, {
|
||||
__index = function()
|
||||
return 0
|
||||
end})
|
||||
}, {
|
||||
__index = function()
|
||||
return 0
|
||||
end
|
||||
})
|
||||
end,
|
||||
})
|
||||
local armor_textures = setmetatable({}, {
|
||||
__index = function()
|
||||
return setmetatable({}, {
|
||||
__index = function()
|
||||
return "blank.png"
|
||||
end
|
||||
})
|
||||
end
|
||||
})
|
||||
|
||||
armor = {
|
||||
timer = 0,
|
||||
elements = {"head", "torso", "legs", "feet"},
|
||||
physics = {"jump", "speed", "gravity"},
|
||||
attributes = {"heal", "fire", "water", "feather"},
|
||||
formspec = "image[2.5,0;2,4;armor_preview]"..
|
||||
default.gui_bg..
|
||||
default.gui_bg_img..
|
||||
default.gui_slots..
|
||||
default.get_hotbar_bg(0, 4.7)..
|
||||
"list[current_player;main;0,4.7;8,1;]"..
|
||||
"list[current_player;main;0,5.85;8,3;8]",
|
||||
def = armor_def,
|
||||
textures = armor_textures,
|
||||
default_skin = "character",
|
||||
materials = {
|
||||
wood = "group:wood",
|
||||
cactus = "default:cactus",
|
||||
steel = "default:steel_ingot",
|
||||
bronze = "default:bronze_ingot",
|
||||
diamond = "default:diamond",
|
||||
gold = "default:gold_ingot",
|
||||
mithril = "moreores:mithril_ingot",
|
||||
crystal = "ethereal:crystal_ingot",
|
||||
nether = "nether:nether_ingot",
|
||||
},
|
||||
fire_nodes = {
|
||||
{"nether:lava_source", 5, 8},
|
||||
{"default:lava_source", 5, 8},
|
||||
{"default:lava_flowing", 5, 8},
|
||||
{"fire:basic_flame", 3, 4},
|
||||
{"fire:permanent_flame", 3, 4},
|
||||
{"ethereal:crystal_spike", 2, 1},
|
||||
{"ethereal:fire_flower", 2, 1},
|
||||
{"nether:lava_crust", 2, 1},
|
||||
{"default:torch", 1, 1},
|
||||
{"default:torch_ceiling", 1, 1},
|
||||
{"default:torch_wall", 1, 1},
|
||||
},
|
||||
registered_groups = {["fleshy"]=100},
|
||||
registered_callbacks = {
|
||||
on_update = {},
|
||||
on_equip = {},
|
||||
on_unequip = {},
|
||||
on_damage = {},
|
||||
on_destroy = {},
|
||||
},
|
||||
migrate_old_inventory = true,
|
||||
version = "0.4.13",
|
||||
get_translator = S
|
||||
}
|
||||
|
||||
armor.config = {
|
||||
init_delay = 2,
|
||||
bones_delay = 1,
|
||||
update_time = 1,
|
||||
drop = minetest.get_modpath("bones") ~= nil,
|
||||
destroy = false,
|
||||
level_multiplier = 1,
|
||||
heal_multiplier = 1,
|
||||
material_wood = true,
|
||||
material_cactus = true,
|
||||
material_steel = true,
|
||||
material_bronze = true,
|
||||
material_diamond = true,
|
||||
material_gold = true,
|
||||
material_mithril = true,
|
||||
material_crystal = true,
|
||||
material_nether = true,
|
||||
set_elements = "head torso legs feet shield",
|
||||
set_multiplier = 1.1,
|
||||
water_protect = true,
|
||||
fire_protect = minetest.get_modpath("ethereal") ~= nil,
|
||||
fire_protect_torch = minetest.get_modpath("ethereal") ~= nil,
|
||||
feather_fall = true,
|
||||
punch_damage = true,
|
||||
}
|
||||
|
||||
|
||||
--- Methods
|
||||
--
|
||||
-- @section methods
|
||||
|
||||
--- Registers a new armor item.
|
||||
--
|
||||
-- @function armor:register_armor
|
||||
-- @tparam string name Armor item technical name (ex: "3d\_armor:helmet\_gold").
|
||||
-- @tparam ArmorDef def Armor definition table.
|
||||
-- @usage armor:register_armor("3d_armor:helmet_wood", {
|
||||
-- description = "Wood Helmet",
|
||||
-- inventory_image = "3d_armor_inv_helmet_wood.png",
|
||||
-- groups = {armor_head=1, armor_heal=0, armor_use=2000, flammable=1},
|
||||
-- armor_groups = {fleshy=5},
|
||||
-- damage_groups = {cracky=3, snappy=2, choppy=3, crumbly=2, level=1},
|
||||
-- })
|
||||
armor.register_armor = function(self, name, def)
|
||||
def.on_secondary_use = function(itemstack, player)
|
||||
return armor:equip(player, itemstack)
|
||||
end
|
||||
def.on_place = function(itemstack, player, pointed_thing)
|
||||
if pointed_thing.type == "node" and player and not player:get_player_control().sneak then
|
||||
local node = minetest.get_node(pointed_thing.under)
|
||||
local ndef = minetest.registered_nodes[node.name]
|
||||
if ndef and ndef.on_rightclick then
|
||||
return ndef.on_rightclick(pointed_thing.under, node, player, itemstack, pointed_thing)
|
||||
end
|
||||
end
|
||||
return armor:equip(player, itemstack)
|
||||
end
|
||||
-- The below is a very basic check to try and see if a material name exists as part
|
||||
-- of the item name. However this check is very simple and just checks theres "_something"
|
||||
-- at the end of the item name and logging an error to debug if not.
|
||||
local check_mat_exists = string.match(name, "%:.+_(.+)$")
|
||||
if check_mat_exists == nil then
|
||||
minetest.log("warning:[3d_armor] Registered armor "..name..
|
||||
" does not have \"_material\" specified at the end of the item registration name")
|
||||
end
|
||||
minetest.register_tool(name, def)
|
||||
end
|
||||
|
||||
--- Registers a new armor group.
|
||||
--
|
||||
-- @function armor:register_armor_group
|
||||
-- @tparam string group Group ID.
|
||||
-- @tparam int base Base armor value.
|
||||
armor.register_armor_group = function(self, group, base)
|
||||
base = base or 100
|
||||
self.registered_groups[group] = base
|
||||
if use_armor_monoid then
|
||||
armor_monoid.register_armor_group(group, base)
|
||||
end
|
||||
end
|
||||
|
||||
--- Armor Callbacks Registration
|
||||
--
|
||||
-- @section callbacks
|
||||
|
||||
--- Registers a callback for when player visuals are update.
|
||||
--
|
||||
-- @function armor:register_on_update
|
||||
-- @tparam function func Function to be executed.
|
||||
-- @see armor:update_player_visuals
|
||||
-- @usage armor:register_on_update(function(player, index, stack)
|
||||
-- -- code to execute
|
||||
-- end)
|
||||
armor.register_on_update = function(self, func)
|
||||
if type(func) == "function" then
|
||||
table.insert(self.registered_callbacks.on_update, func)
|
||||
end
|
||||
end
|
||||
|
||||
--- Registers a callback for when armor is equipped.
|
||||
--
|
||||
-- @function armor:register_on_equip
|
||||
-- @tparam function func Function to be executed.
|
||||
-- @usage armor:register_on_equip(function(player, index, stack)
|
||||
-- -- code to execute
|
||||
-- end)
|
||||
armor.register_on_equip = function(self, func)
|
||||
if type(func) == "function" then
|
||||
table.insert(self.registered_callbacks.on_equip, func)
|
||||
end
|
||||
end
|
||||
|
||||
--- Registers a callback for when armor is unequipped.
|
||||
--
|
||||
-- @function armor:register_on_unequip
|
||||
-- @tparam function func Function to be executed.
|
||||
-- @usage armor:register_on_unequip(function(player, index, stack)
|
||||
-- -- code to execute
|
||||
-- end)
|
||||
armor.register_on_unequip = function(self, func)
|
||||
if type(func) == "function" then
|
||||
table.insert(self.registered_callbacks.on_unequip, func)
|
||||
end
|
||||
end
|
||||
|
||||
--- Registers a callback for when armor is damaged.
|
||||
--
|
||||
-- @function armor:register_on_damage
|
||||
-- @tparam function func Function to be executed.
|
||||
-- @see armor:damage
|
||||
-- @usage armor:register_on_damage(function(player, index, stack)
|
||||
-- -- code to execute
|
||||
-- end)
|
||||
armor.register_on_damage = function(self, func)
|
||||
if type(func) == "function" then
|
||||
table.insert(self.registered_callbacks.on_damage, func)
|
||||
end
|
||||
end
|
||||
|
||||
--- Registers a callback for when armor is destroyed.
|
||||
--
|
||||
-- @function armor:register_on_destroy
|
||||
-- @tparam function func Function to be executed.
|
||||
-- @see armor:damage
|
||||
-- @usage armor:register_on_destroy(function(player, index, stack)
|
||||
-- -- code to execute
|
||||
-- end)
|
||||
armor.register_on_destroy = function(self, func)
|
||||
if type(func) == "function" then
|
||||
table.insert(self.registered_callbacks.on_destroy, func)
|
||||
end
|
||||
end
|
||||
|
||||
--- @section end
|
||||
|
||||
|
||||
--- Methods
|
||||
--
|
||||
-- @section methods
|
||||
|
||||
--- Runs callbacks.
|
||||
--
|
||||
-- @function armor:run_callbacks
|
||||
-- @tparam function callback Function to execute.
|
||||
-- @tparam ObjectRef player First parameter passed to callback.
|
||||
-- @tparam int index Second parameter passed to callback.
|
||||
-- @tparam ItemStack stack Callback owner.
|
||||
armor.run_callbacks = function(self, callback, player, index, stack)
|
||||
if stack then
|
||||
local def = stack:get_definition() or {}
|
||||
if type(def[callback]) == "function" then
|
||||
def[callback](player, index, stack)
|
||||
end
|
||||
end
|
||||
local callbacks = self.registered_callbacks[callback]
|
||||
if callbacks then
|
||||
for _, func in pairs(callbacks) do
|
||||
func(player, index, stack)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Updates visuals.
|
||||
--
|
||||
-- @function armor:update_player_visuals
|
||||
-- @tparam ObjectRef player
|
||||
armor.update_player_visuals = function(self, player)
|
||||
if not player then
|
||||
return
|
||||
end
|
||||
local name = player:get_player_name()
|
||||
if self.textures[name] then
|
||||
player_api.set_textures(player, {
|
||||
self.textures[name].skin,
|
||||
self.textures[name].armor,
|
||||
self.textures[name].wielditem,
|
||||
})
|
||||
end
|
||||
self:run_callbacks("on_update", player)
|
||||
end
|
||||
|
||||
--- Sets player's armor attributes.
|
||||
--
|
||||
-- @function armor:set_player_armor
|
||||
-- @tparam ObjectRef player
|
||||
armor.set_player_armor = function(self, player)
|
||||
local name, armor_inv = self:get_valid_player(player, "[set_player_armor]")
|
||||
if not name then
|
||||
return
|
||||
end
|
||||
local state = 0
|
||||
local count = 0
|
||||
local preview = armor:get_preview(name)
|
||||
local texture = "blank.png"
|
||||
local physics = {}
|
||||
local attributes = {}
|
||||
local levels = {}
|
||||
local groups = {}
|
||||
local change = {}
|
||||
local set_worn = {}
|
||||
local armor_multi = 0
|
||||
local worn_armor = armor:get_weared_armor_elements(player)
|
||||
for _, phys in pairs(self.physics) do
|
||||
physics[phys] = 1
|
||||
end
|
||||
for _, attr in pairs(self.attributes) do
|
||||
attributes[attr] = 0
|
||||
end
|
||||
for group, _ in pairs(self.registered_groups) do
|
||||
change[group] = 1
|
||||
levels[group] = 0
|
||||
end
|
||||
local list = armor_inv:get_list("armor")
|
||||
if type(list) ~= "table" then
|
||||
return
|
||||
end
|
||||
for i, stack in pairs(list) do
|
||||
if stack:get_count() == 1 then
|
||||
local def = stack:get_definition()
|
||||
for _, element in pairs(self.elements) do
|
||||
if def.groups["armor_"..element] then
|
||||
if def.armor_groups then
|
||||
for group, level in pairs(def.armor_groups) do
|
||||
if levels[group] then
|
||||
levels[group] = levels[group] + level
|
||||
end
|
||||
end
|
||||
else
|
||||
local level = def.groups["armor_"..element]
|
||||
levels["fleshy"] = levels["fleshy"] + level
|
||||
end
|
||||
break
|
||||
end
|
||||
-- DEPRECATED, use armor_groups instead
|
||||
if def.groups["armor_radiation"] and levels["radiation"] then
|
||||
levels["radiation"] = levels["radiation"] + def.groups["armor_radiation"]
|
||||
end
|
||||
end
|
||||
local item = stack:get_name()
|
||||
local tex = def.texture or item:gsub("%:", "_")
|
||||
tex = tex:gsub(".png$", "")
|
||||
local prev = def.preview or tex.."_preview"
|
||||
prev = prev:gsub(".png$", "")
|
||||
if not transparent_armor then
|
||||
texture = texture.."^"..tex..".png"
|
||||
end
|
||||
preview = preview.."^"..prev..".png"
|
||||
state = state + stack:get_wear()
|
||||
count = count + 1
|
||||
for _, phys in pairs(self.physics) do
|
||||
local value = def.groups["physics_"..phys] or 0
|
||||
physics[phys] = physics[phys] + value
|
||||
end
|
||||
for _, attr in pairs(self.attributes) do
|
||||
local value = def.groups["armor_"..attr] or 0
|
||||
attributes[attr] = attributes[attr] + value
|
||||
end
|
||||
end
|
||||
end
|
||||
-- The following code compares player worn armor items against requirements
|
||||
-- of which armor pieces are needed to be worn to meet set bonus requirements
|
||||
for loc,item in pairs(worn_armor) do
|
||||
local item_mat = string.match(item, "%:.+_(.+)$")
|
||||
local worn_key = item_mat or "unknown"
|
||||
|
||||
-- Perform location checks to ensure the armor is worn correctly
|
||||
for k,set_loc in pairs(armor.config.set_elements)do
|
||||
if set_loc == loc then
|
||||
if set_worn[worn_key] == nil then
|
||||
set_worn[worn_key] = 0
|
||||
set_worn[worn_key] = set_worn[worn_key] + 1
|
||||
else
|
||||
set_worn[worn_key] = set_worn[worn_key] + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Apply the armor multiplier only if the player is wearing a full set of armor
|
||||
for mat_name,arm_piece_num in pairs(set_worn) do
|
||||
if arm_piece_num == #armor.config.set_elements then
|
||||
armor_multi = armor.config.set_multiplier
|
||||
end
|
||||
end
|
||||
for group, level in pairs(levels) do
|
||||
if level > 0 then
|
||||
level = level * armor.config.level_multiplier
|
||||
if armor_multi ~= 0 then
|
||||
level = level * armor.config.set_multiplier
|
||||
end
|
||||
end
|
||||
local base = self.registered_groups[group]
|
||||
self.def[name].groups[group] = level
|
||||
if level > base then
|
||||
level = base
|
||||
end
|
||||
groups[group] = base - level
|
||||
change[group] = groups[group] / base
|
||||
end
|
||||
for _, attr in pairs(self.attributes) do
|
||||
local mult = attr == "heal" and self.config.heal_multiplier or 1
|
||||
self.def[name][attr] = attributes[attr] * mult
|
||||
end
|
||||
for _, phys in pairs(self.physics) do
|
||||
self.def[name][phys] = physics[phys]
|
||||
end
|
||||
if use_armor_monoid then
|
||||
armor_monoid.monoid:add_change(player, change, "3d_armor:armor")
|
||||
else
|
||||
-- Preserve immortal group (damage disabled for player)
|
||||
local player_groups = player:get_armor_groups()
|
||||
local immortal = player_groups.immortal
|
||||
if immortal and immortal ~= 0 then
|
||||
groups.immortal = 1
|
||||
end
|
||||
-- Preserve fall_damage_add_percent group (fall damage modifier)
|
||||
groups.fall_damage_add_percent = player_groups.fall_damage_add_percent
|
||||
player:set_armor_groups(groups)
|
||||
end
|
||||
if use_player_monoids then
|
||||
player_monoids.speed:add_change(player, physics.speed,
|
||||
"3d_armor:physics")
|
||||
player_monoids.jump:add_change(player, physics.jump,
|
||||
"3d_armor:physics")
|
||||
player_monoids.gravity:add_change(player, physics.gravity,
|
||||
"3d_armor:physics")
|
||||
elseif use_pova_mod then
|
||||
-- only add the changes, not the default 1.0 for each physics setting
|
||||
pova.add_override(name, "3d_armor", {
|
||||
speed = physics.speed - 1,
|
||||
jump = physics.jump - 1,
|
||||
gravity = physics.gravity - 1,
|
||||
})
|
||||
pova.do_override(player)
|
||||
else
|
||||
local player_physics_locked = player:get_meta():get_int("player_physics_locked")
|
||||
if player_physics_locked == nil or player_physics_locked == 0 then
|
||||
player:set_physics_override(physics)
|
||||
end
|
||||
end
|
||||
self.textures[name].armor = texture
|
||||
self.textures[name].preview = preview
|
||||
self.def[name].level = self.def[name].groups.fleshy or 0
|
||||
self.def[name].state = state
|
||||
self.def[name].count = count
|
||||
self:update_player_visuals(player)
|
||||
end
|
||||
|
||||
--- Action when armor is punched.
|
||||
--
|
||||
-- @function armor:punch
|
||||
-- @tparam ObjectRef player Player wearing the armor.
|
||||
-- @tparam ObjectRef hitter Entity attacking player.
|
||||
-- @tparam[opt] int time_from_last_punch Time in seconds since last punch action.
|
||||
-- @tparam[opt] table tool_capabilities See `entity_damage_mechanism`.
|
||||
armor.punch = function(self, player, hitter, time_from_last_punch, tool_capabilities)
|
||||
local name, armor_inv = self:get_valid_player(player, "[punch]")
|
||||
if not name then
|
||||
return
|
||||
end
|
||||
local set_state
|
||||
local set_count
|
||||
local state = 0
|
||||
local count = 0
|
||||
local recip = true
|
||||
local default_groups = {cracky=3, snappy=3, choppy=3, crumbly=3, level=1}
|
||||
local list = armor_inv:get_list("armor")
|
||||
for i, stack in pairs(list) do
|
||||
if stack:get_count() == 1 then
|
||||
local itemname = stack:get_name()
|
||||
local use = minetest.get_item_group(itemname, "armor_use") or 0
|
||||
local damage = use > 0
|
||||
local def = stack:get_definition() or {}
|
||||
if type(def.on_punched) == "function" then
|
||||
damage = def.on_punched(player, hitter, time_from_last_punch,
|
||||
tool_capabilities) ~= false and damage == true
|
||||
end
|
||||
if damage == true and tool_capabilities then
|
||||
local damage_groups = def.damage_groups or default_groups
|
||||
local level = damage_groups.level or 0
|
||||
local groupcaps = tool_capabilities.groupcaps or {}
|
||||
local uses = 0
|
||||
damage = false
|
||||
if next(groupcaps) == nil then
|
||||
damage = true
|
||||
end
|
||||
for group, caps in pairs(groupcaps) do
|
||||
local maxlevel = caps.maxlevel or 0
|
||||
local diff = maxlevel - level
|
||||
if diff == 0 then
|
||||
diff = 1
|
||||
end
|
||||
if diff > 0 and caps.times then
|
||||
local group_level = damage_groups[group]
|
||||
if group_level then
|
||||
local time = caps.times[group_level]
|
||||
if time then
|
||||
local dt = time_from_last_punch or 0
|
||||
if dt > time / diff then
|
||||
if caps.uses then
|
||||
uses = caps.uses * math.pow(3, diff)
|
||||
end
|
||||
damage = true
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if damage == true and recip == true and hitter and
|
||||
def.reciprocate_damage == true and uses > 0 then
|
||||
local item = hitter:get_wielded_item()
|
||||
if item and item:get_name() ~= "" then
|
||||
item:add_wear(65535 / uses)
|
||||
hitter:set_wielded_item(item)
|
||||
end
|
||||
-- reciprocate tool damage only once
|
||||
recip = false
|
||||
end
|
||||
end
|
||||
if damage == true and hitter == "fire" then
|
||||
damage = minetest.get_item_group(itemname, "flammable") > 0
|
||||
end
|
||||
if damage == true then
|
||||
self:damage(player, i, stack, use)
|
||||
set_state = self.def[name].state
|
||||
set_count = self.def[name].count
|
||||
end
|
||||
state = state + stack:get_wear()
|
||||
count = count + 1
|
||||
end
|
||||
end
|
||||
if set_count and set_count ~= count then
|
||||
state = set_state or state
|
||||
count = set_count or count
|
||||
end
|
||||
self.def[name].state = state
|
||||
self.def[name].count = count
|
||||
end
|
||||
|
||||
--- Action when armor is damaged.
|
||||
--
|
||||
-- @function armor:damage
|
||||
-- @tparam ObjectRef player
|
||||
-- @tparam int index Inventory index where armor is equipped.
|
||||
-- @tparam ItemStack stack Armor item receiving damaged.
|
||||
-- @tparam int use Amount of wear to add to armor item.
|
||||
armor.damage = function(self, player, index, stack, use)
|
||||
local old_stack = ItemStack(stack)
|
||||
local worn_armor = armor:get_weared_armor_elements(player)
|
||||
if not worn_armor then
|
||||
return
|
||||
end
|
||||
local armor_worn_cnt = 0
|
||||
for k,v in pairs(worn_armor) do
|
||||
armor_worn_cnt = armor_worn_cnt + 1
|
||||
end
|
||||
use = math.ceil(use/armor_worn_cnt)
|
||||
stack:add_wear(use)
|
||||
self:run_callbacks("on_damage", player, index, stack)
|
||||
self:set_inventory_stack(player, index, stack)
|
||||
if stack:get_count() == 0 then
|
||||
self:run_callbacks("on_unequip", player, index, old_stack)
|
||||
self:run_callbacks("on_destroy", player, index, old_stack)
|
||||
self:set_player_armor(player)
|
||||
end
|
||||
end
|
||||
|
||||
--- Get elements of equipped armor.
|
||||
--
|
||||
-- @function armor:get_weared_armor_elements
|
||||
-- @tparam ObjectRef player
|
||||
-- @treturn table List of equipped armors.
|
||||
armor.get_weared_armor_elements = function(self, player)
|
||||
local name, inv = self:get_valid_player(player, "[get_weared_armor]")
|
||||
local weared_armor = {}
|
||||
if not name then
|
||||
return
|
||||
end
|
||||
for i=1, inv:get_size("armor") do
|
||||
local item_name = inv:get_stack("armor", i):get_name()
|
||||
local element = self:get_element(item_name)
|
||||
if element ~= nil then
|
||||
weared_armor[element] = item_name
|
||||
end
|
||||
end
|
||||
return weared_armor
|
||||
end
|
||||
|
||||
--- Equips a piece of armor to a player.
|
||||
--
|
||||
-- @function armor:equip
|
||||
-- @tparam ObjectRef player Player to whom item is equipped.
|
||||
-- @tparam ItemStack itemstack Armor item to be equipped.
|
||||
-- @treturn ItemStack Leftover item stack.
|
||||
armor.equip = function(self, player, itemstack)
|
||||
local name, armor_inv = self:get_valid_player(player, "[equip]")
|
||||
local armor_element = self:get_element(itemstack:get_name())
|
||||
if name and armor_element then
|
||||
local index
|
||||
for i=1, armor_inv:get_size("armor") do
|
||||
local stack = armor_inv:get_stack("armor", i)
|
||||
if self:get_element(stack:get_name()) == armor_element then
|
||||
--prevents equiping an armor that would unequip a cursed armor.
|
||||
if minetest.get_item_group(stack:get_name(), "cursed") ~= 0 then
|
||||
return itemstack
|
||||
end
|
||||
index = i
|
||||
self:unequip(player, armor_element)
|
||||
break
|
||||
elseif not index and stack:is_empty() then
|
||||
index = i
|
||||
end
|
||||
end
|
||||
local stack = itemstack:take_item()
|
||||
armor_inv:set_stack("armor", index, stack)
|
||||
self:run_callbacks("on_equip", player, index, stack)
|
||||
self:set_player_armor(player)
|
||||
self:save_armor_inventory(player)
|
||||
end
|
||||
return itemstack
|
||||
end
|
||||
|
||||
--- Unequips a piece of armor from a player.
|
||||
--
|
||||
-- @function armor:unequip
|
||||
-- @tparam ObjectRef player Player from whom item is removed.
|
||||
-- @tparam string armor_element Armor type identifier associated with the item
|
||||
-- to be removed ("head", "torso", "hands", "shield", "legs", "feet", etc.).
|
||||
armor.unequip = function(self, player, armor_element)
|
||||
local name, armor_inv = self:get_valid_player(player, "[unequip]")
|
||||
if not name then
|
||||
return
|
||||
end
|
||||
for i=1, armor_inv:get_size("armor") do
|
||||
local stack = armor_inv:get_stack("armor", i)
|
||||
if self:get_element(stack:get_name()) == armor_element then
|
||||
armor_inv:set_stack("armor", i, "")
|
||||
minetest.after(0, function()
|
||||
local pplayer = minetest.get_player_by_name(name)
|
||||
if pplayer then -- player is still online
|
||||
local inv = pplayer:get_inventory()
|
||||
if inv:room_for_item("main", stack) then
|
||||
inv:add_item("main", stack)
|
||||
else
|
||||
minetest.add_item(pplayer:get_pos(), stack)
|
||||
end
|
||||
end
|
||||
end)
|
||||
self:run_callbacks("on_unequip", player, i, stack)
|
||||
self:set_player_armor(player)
|
||||
self:save_armor_inventory(player)
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Removes all armor worn by player.
|
||||
--
|
||||
-- @function armor:remove_all
|
||||
-- @tparam ObjectRef player
|
||||
armor.remove_all = function(self, player)
|
||||
local name, inv = self:get_valid_player(player, "[remove_all]")
|
||||
if not name then
|
||||
return
|
||||
end
|
||||
inv:set_list("armor", {})
|
||||
self:set_player_armor(player)
|
||||
self:save_armor_inventory(player)
|
||||
end
|
||||
|
||||
local skin_mod
|
||||
|
||||
--- Retrieves player's current skin.
|
||||
--
|
||||
-- @function armor:get_player_skin
|
||||
-- @tparam string name Player name.
|
||||
-- @treturn string Skin filename.
|
||||
armor.get_player_skin = function(self, name)
|
||||
if (skin_mod == "skins" or skin_mod == "simple_skins") and skins.skins[name] then
|
||||
return skins.skins[name]..".png"
|
||||
elseif skin_mod == "u_skins" and u_skins.u_skins[name] then
|
||||
return u_skins.u_skins[name]..".png"
|
||||
elseif skin_mod == "wardrobe" and wardrobe.playerSkins and wardrobe.playerSkins[name] then
|
||||
return wardrobe.playerSkins[name]
|
||||
end
|
||||
return armor.default_skin..".png"
|
||||
end
|
||||
|
||||
--- Updates skin.
|
||||
--
|
||||
-- @function armor:update_skin
|
||||
-- @tparam string name Player name.
|
||||
armor.update_skin = function(self, name)
|
||||
minetest.after(0, function()
|
||||
local pplayer = minetest.get_player_by_name(name)
|
||||
if pplayer then
|
||||
self.textures[name].skin = self:get_player_skin(name)
|
||||
self:set_player_armor(pplayer)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
--- Adds preview for armor inventory.
|
||||
--
|
||||
-- @function armor:add_preview
|
||||
-- @tparam string preview Preview image filename.
|
||||
armor.add_preview = function(self, preview)
|
||||
skin_previews[preview] = true
|
||||
end
|
||||
|
||||
--- Retrieves preview for armor inventory.
|
||||
--
|
||||
-- @function armor:get_preview
|
||||
-- @tparam string name Player name.
|
||||
-- @treturn string Preview image filename.
|
||||
armor.get_preview = function(self, name)
|
||||
local preview = string.gsub(armor:get_player_skin(name), ".png", "_preview.png")
|
||||
if skin_previews[preview] then
|
||||
return preview
|
||||
end
|
||||
return "character_preview.png"
|
||||
end
|
||||
|
||||
--- Retrieves armor formspec.
|
||||
--
|
||||
-- @function armor:get_armor_formspec
|
||||
-- @tparam string name Player name.
|
||||
-- @tparam[opt] bool listring Use `listring` formspec element (default: `false`).
|
||||
-- @treturn string Formspec formatted string.
|
||||
armor.get_armor_formspec = function(self, name, listring)
|
||||
local formspec = armor.formspec..
|
||||
"list[detached:"..name.."_armor;armor;0,0.5;2,3;]"
|
||||
if listring == true then
|
||||
formspec = formspec.."listring[current_player;main]"..
|
||||
"listring[detached:"..name.."_armor;armor]"
|
||||
end
|
||||
formspec = formspec:gsub("armor_preview", armor.textures[name].preview)
|
||||
formspec = formspec:gsub("armor_level", armor.def[name].level)
|
||||
for _, attr in pairs(self.attributes) do
|
||||
formspec = formspec:gsub("armor_attr_"..attr, armor.def[name][attr])
|
||||
end
|
||||
for group, _ in pairs(self.registered_groups) do
|
||||
formspec = formspec:gsub("armor_group_"..group,
|
||||
armor.def[name].groups[group])
|
||||
end
|
||||
return formspec
|
||||
end
|
||||
|
||||
--- Retrieves element.
|
||||
--
|
||||
-- @function armor:get_element
|
||||
-- @tparam string item_name
|
||||
-- @return Armor element.
|
||||
armor.get_element = function(self, item_name)
|
||||
for _, element in pairs(armor.elements) do
|
||||
if minetest.get_item_group(item_name, "armor_"..element) > 0 then
|
||||
return element
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Serializes armor inventory.
|
||||
--
|
||||
-- @function armor:serialize_inventory_list
|
||||
-- @tparam table list Inventory contents.
|
||||
-- @treturn string
|
||||
armor.serialize_inventory_list = function(self, list)
|
||||
local list_table = {}
|
||||
for _, stack in ipairs(list) do
|
||||
table.insert(list_table, stack:to_string())
|
||||
end
|
||||
return minetest.serialize(list_table)
|
||||
end
|
||||
|
||||
--- Deserializes armor inventory.
|
||||
--
|
||||
-- @function armor:deserialize_inventory_list
|
||||
-- @tparam string list_string Serialized inventory contents.
|
||||
-- @treturn table
|
||||
armor.deserialize_inventory_list = function(self, list_string)
|
||||
local list_table = minetest.deserialize(list_string)
|
||||
local list = {}
|
||||
for _, stack in ipairs(list_table or {}) do
|
||||
table.insert(list, ItemStack(stack))
|
||||
end
|
||||
return list
|
||||
end
|
||||
|
||||
--- Loads armor inventory.
|
||||
--
|
||||
-- @function armor:load_armor_inventory
|
||||
-- @tparam ObjectRef player
|
||||
-- @treturn bool
|
||||
armor.load_armor_inventory = function(self, player)
|
||||
local _, inv = self:get_valid_player(player, "[load_armor_inventory]")
|
||||
if inv then
|
||||
local meta = player:get_meta()
|
||||
local armor_list_string = meta:get_string("3d_armor_inventory")
|
||||
if armor_list_string then
|
||||
inv:set_list("armor",
|
||||
self:deserialize_inventory_list(armor_list_string))
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Saves armor inventory.
|
||||
--
|
||||
-- Inventory is stored in `PlayerMetaRef` string "3d\_armor\_inventory".
|
||||
--
|
||||
-- @function armor:save_armor_inventory
|
||||
-- @tparam ObjectRef player
|
||||
armor.save_armor_inventory = function(self, player)
|
||||
local _, inv = self:get_valid_player(player, "[save_armor_inventory]")
|
||||
if inv then
|
||||
local meta = player:get_meta()
|
||||
meta:set_string("3d_armor_inventory",
|
||||
self:serialize_inventory_list(inv:get_list("armor")))
|
||||
end
|
||||
end
|
||||
|
||||
--- Updates inventory.
|
||||
--
|
||||
-- DEPRECATED: Legacy inventory support.
|
||||
--
|
||||
-- @function armor:update_inventory
|
||||
-- @param player
|
||||
armor.update_inventory = function(self, player)
|
||||
-- DEPRECATED: Legacy inventory support
|
||||
end
|
||||
|
||||
--- Sets inventory stack.
|
||||
--
|
||||
-- @function armor:set_inventory_stack
|
||||
-- @tparam ObjectRef player
|
||||
-- @tparam int i Armor inventory index.
|
||||
-- @tparam ItemStack stack Armor item.
|
||||
armor.set_inventory_stack = function(self, player, i, stack)
|
||||
local _, inv = self:get_valid_player(player, "[set_inventory_stack]")
|
||||
if inv then
|
||||
inv:set_stack("armor", i, stack)
|
||||
self:save_armor_inventory(player)
|
||||
end
|
||||
end
|
||||
|
||||
--- Checks for a player that can use armor.
|
||||
--
|
||||
-- @function armor:get_valid_player
|
||||
-- @tparam ObjectRef player
|
||||
-- @tparam string msg Additional info for log messages.
|
||||
-- @treturn list Player name & armor inventory.
|
||||
-- @usage local name, inv = armor:get_valid_player(player, "[equip]")
|
||||
armor.get_valid_player = function(self, player, msg)
|
||||
msg = msg or ""
|
||||
if not player then
|
||||
minetest.log("warning", ("3d_armor%s: Player reference is nil"):format(msg))
|
||||
return
|
||||
end
|
||||
if type(player) ~= "userdata" then
|
||||
-- Fake player, fail silently
|
||||
return
|
||||
end
|
||||
local name = player:get_player_name()
|
||||
if not name then
|
||||
minetest.log("warning", ("3d_armor%s: Player name is nil"):format(msg))
|
||||
return
|
||||
end
|
||||
local inv = minetest.get_inventory({type="detached", name=name.."_armor"})
|
||||
if not inv then
|
||||
-- This check may fail when called inside `on_joinplayer`
|
||||
-- in that case, the armor will be initialized/updated later on
|
||||
minetest.log("warning", ("3d_armor%s: Detached armor inventory is nil"):format(msg))
|
||||
return
|
||||
end
|
||||
return name, inv
|
||||
end
|
||||
|
||||
--- Drops armor item at given position.
|
||||
--
|
||||
-- @tparam vector pos
|
||||
-- @tparam ItemStack stack Armor item to be dropped.
|
||||
armor.drop_armor = function(pos, stack)
|
||||
local node = minetest.get_node_or_nil(pos)
|
||||
if node then
|
||||
local obj = minetest.add_item(pos, stack)
|
||||
if obj then
|
||||
obj:set_velocity({x=math.random(-1, 1), y=5, z=math.random(-1, 1)})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Allows skin mod to be set manually.
|
||||
--
|
||||
-- Useful for skin mod forks that do not use the same name.
|
||||
--
|
||||
-- @tparam string mod Name of skin mod. Recognized names are "simple\_skins", "u\_skins", & "wardrobe".
|
||||
armor.set_skin_mod = function(mod)
|
||||
skin_mod = mod
|
||||
end
|
37
3d_armor/armor.conf
Executable file
@ -0,0 +1,37 @@
|
||||
-- Armor Configuration (defaults)
|
||||
|
||||
-- Increase this if you get initialization glitches when a player first joins.
|
||||
ARMOR_INIT_DELAY = 3
|
||||
|
||||
-- Number of initialization attempts.
|
||||
-- Use in conjunction with ARMOR_INIT_DELAY if initialization problems persist.
|
||||
ARMOR_INIT_TIMES = 3
|
||||
|
||||
-- Increase this if armor is not getting into bones due to server lag.
|
||||
ARMOR_BONES_DELAY = 3
|
||||
|
||||
-- How often player armor/wield items are updated.
|
||||
ARMOR_UPDATE_TIME = 1
|
||||
|
||||
-- Drop armor when a player dies.
|
||||
-- Uses bones mod if present, otherwise items are dropped around the player.
|
||||
ARMOR_DROP = true
|
||||
|
||||
-- Pulverise armor when a player dies, overrides ARMOR_DROP.
|
||||
ARMOR_DESTROY = false
|
||||
|
||||
-- You can use this to increase or decrease overall armor effectiveness,
|
||||
-- eg: ARMOR_LEVEL_MULTIPLIER = 0.5 will reduce armor level by half.
|
||||
ARMOR_LEVEL_MULTIPLIER = 1
|
||||
|
||||
-- You can use this to increase or decrease overall armor healing,
|
||||
-- eg: ARMOR_HEAL_MULTIPLIER = 0 will disable healing altogether.
|
||||
ARMOR_HEAL_MULTIPLIER = 1
|
||||
|
||||
-- You can also use this file to execute arbitary lua code
|
||||
-- eg: Dumb the armor down if using Simple Mobs
|
||||
--if minetest.get_modpath("mobs") then
|
||||
-- ARMOR_LEVEL_MULTIPLIER = 1
|
||||
-- ARMOR_HEAL_MULTIPLIER = 0
|
||||
--end
|
||||
|
62
3d_armor/armor.conf.example
Normal file
@ -0,0 +1,62 @@
|
||||
-- DEPRECATED, will not be supported in future versions
|
||||
|
||||
-- See README.txt for new configuration options.
|
||||
|
||||
-- Armor Configuration (defaults)
|
||||
|
||||
-- You can remove any unwanted armor materials from this table.
|
||||
-- Note that existing armor that is removed will show up as an unknown item.
|
||||
ARMOR_MATERIALS = {
|
||||
wood = "group:wood",
|
||||
cactus = "default:cactus",
|
||||
steel = "default:steel_ingot",
|
||||
bronze = "default:bronze_ingot",
|
||||
diamond = "default:diamond",
|
||||
gold = "default:gold_ingot",
|
||||
mithril = "moreores:mithril_ingot",
|
||||
crystal = "ethereal:crystal_ingot",
|
||||
nether = "nether:nether_ingot",
|
||||
}
|
||||
|
||||
-- Enable fire protection (defaults true if using ethereal mod)
|
||||
ARMOR_FIRE_PROTECT = false
|
||||
|
||||
-- Fire protection nodes, (name, protection level, damage)
|
||||
ARMOR_FIRE_NODES = {
|
||||
{"default:lava_source", 5, 4},
|
||||
{"default:lava_flowing", 5, 4},
|
||||
{"fire:basic_flame", 3, 4},
|
||||
{"fire:permanent_flame", 3, 4},
|
||||
{"ethereal:crystal_spike", 2, 1},
|
||||
{"ethereal:fire_flower", 2, 1},
|
||||
{"default:torch", 1, 1},
|
||||
}
|
||||
|
||||
-- Increase this if you get initialization glitches when a player first joins.
|
||||
ARMOR_INIT_DELAY = 1
|
||||
|
||||
-- Increase this if armor is not getting into bones due to server lag.
|
||||
ARMOR_BONES_DELAY = 1
|
||||
|
||||
-- How often player armor/wield items are updated.
|
||||
ARMOR_UPDATE_TIME = 1
|
||||
|
||||
-- Drop armor when a player dies.
|
||||
-- Uses bones mod if present, otherwise items are dropped around the player.
|
||||
ARMOR_DROP = true
|
||||
|
||||
-- Pulverise armor when a player dies, overrides ARMOR_DROP.
|
||||
ARMOR_DESTROY = false
|
||||
|
||||
-- You can use this to increase or decrease overall armor effectiveness,
|
||||
-- eg: ARMOR_LEVEL_MULTIPLIER = 0.5 will reduce armor level by half.
|
||||
ARMOR_LEVEL_MULTIPLIER = 1
|
||||
|
||||
-- You can use this to increase or decrease overall armor healing,
|
||||
-- eg: ARMOR_HEAL_MULTIPLIER = 0 will disable healing altogether.
|
||||
ARMOR_HEAL_MULTIPLIER = 1
|
||||
|
||||
-- You can use this to increase or decrease overall armor radiation protection,
|
||||
-- eg: ARMOR_RADIATION_MULTIPLIER = 0 will completely disable radiation protection.
|
||||
-- Note: patched technic mod is required
|
||||
ARMOR_RADIATION_MULTIPLIER = 1
|
@ -1,91 +0,0 @@
|
||||
|
||||
armor_api = {
|
||||
player_hp = {},
|
||||
}
|
||||
|
||||
armor_api.get_armor_textures = function(self, player)
|
||||
if not player then
|
||||
return
|
||||
end
|
||||
local name = player:get_player_name()
|
||||
local textures = {}
|
||||
local player_inv = player:get_inventory()
|
||||
for _,v in ipairs({"head", "torso", "legs"}) do
|
||||
local stack = player_inv:get_stack("armor_"..v, 1)
|
||||
if stack:get_definition().groups["armor_"..v] then
|
||||
local item = stack:get_name()
|
||||
textures[v] = item:gsub("%:", "_")..".png"
|
||||
end
|
||||
end
|
||||
local stack = player_inv:get_stack("armor_shield", 1)
|
||||
if stack:get_definition().groups["armor_shield"] then
|
||||
local item = stack:get_name()
|
||||
textures["shield"] = minetest.registered_items[item].inventory_image
|
||||
end
|
||||
return textures
|
||||
end
|
||||
|
||||
armor_api.set_player_armor = function(self, player)
|
||||
if not player then
|
||||
return
|
||||
end
|
||||
local name = player:get_player_name()
|
||||
local player_inv = player:get_inventory()
|
||||
local armor_level = 0
|
||||
for _,v in ipairs({"head", "torso", "legs", "shield"}) do
|
||||
local stack = player_inv:get_stack("armor_"..v, 1)
|
||||
local armor = stack:get_definition().groups["armor_"..v] or 0
|
||||
armor_level = armor_level + armor
|
||||
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
|
||||
player:set_armor_groups(armor_groups)
|
||||
uniskins:update_player_visuals(player)
|
||||
end
|
||||
|
||||
armor_api.update_armor = function(self, player)
|
||||
if not player then
|
||||
return
|
||||
end
|
||||
local name = player:get_player_name()
|
||||
local hp = player:get_hp()
|
||||
if hp == nil or hp == 0 or hp == self.player_hp[name] then
|
||||
return
|
||||
end
|
||||
if self.player_hp[name] > hp then
|
||||
local player_inv = player:get_inventory()
|
||||
local armor_inv = minetest.get_inventory({type="detached", name=name.."_outfit"})
|
||||
if armor_inv == nil then
|
||||
return
|
||||
end
|
||||
local heal_max = 0
|
||||
for _,v in ipairs({"head", "torso", "legs", "shield"}) do
|
||||
local stack = armor_inv:get_stack("armor_"..v, 1)
|
||||
if stack:get_count() > 0 then
|
||||
local use = stack:get_definition().groups["armor_use"] or 0
|
||||
local heal = stack:get_definition().groups["armor_heal"] or 0
|
||||
local item = stack:get_name()
|
||||
stack:add_wear(use)
|
||||
armor_inv:set_stack("armor_"..v, 1, stack)
|
||||
player_inv:set_stack("armor_"..v, 1, stack)
|
||||
if stack:get_count() == 0 then
|
||||
local desc = minetest.registered_items[item].description
|
||||
if desc then
|
||||
minetest.chat_send_player(name, "Your "..desc.." got destroyed!")
|
||||
end
|
||||
self:set_player_armor(player)
|
||||
end
|
||||
heal_max = heal_max + heal
|
||||
end
|
||||
end
|
||||
if heal_max > math.random(100) then
|
||||
player:set_hp(self.player_hp[name])
|
||||
return
|
||||
end
|
||||
end
|
||||
self.player_hp[name] = hp
|
||||
end
|
||||
|
@ -12,8 +12,14 @@ Helmets:
|
||||
+---+---+---+
|
||||
|
||||
[3d_armor:helmet_wood] X = [default:wood]
|
||||
[3d_armor:helmet_cactus] X = [default:cactus]
|
||||
[3d_armor:helmet_steel] X = [default:steel_ingot]
|
||||
[3d_armor:helmet_bronze] X = [default:bronze_ingot]
|
||||
[3d_armor:helmet_diamond] X = [default:diamond]
|
||||
[3d_armor:helmet_gold] X = [default:gold_ingot]
|
||||
[3d_armor:helmet_mithril] X = [moreores:mithril_ingot] *
|
||||
[3d_armor:helmet_crystal] X = [ethereal:crystal_ingot] **
|
||||
[3d_armor:helmet_nether] X = [ethereal:nether_ingot] **
|
||||
|
||||
Chestplates:
|
||||
|
||||
@ -26,8 +32,14 @@ Chestplates:
|
||||
+---+---+---+
|
||||
|
||||
[3d_armor:chestplate_wood] X = [default:wood]
|
||||
[3d_armor:chestplate_cactus] X = [default:cactus]
|
||||
[3d_armor:chestplate_steel] X = [default:steel_ingot]
|
||||
[3d_armor:chestplate_bronze] X = [default:bronze_ingot]
|
||||
[3d_armor:chestplate_diamond] X = [default:diamond]
|
||||
[3d_armor:chestplate_gold] X = [default:gold_ingot]
|
||||
[3d_armor:chestplate_mithril] X = [moreores:mithril_ingot] *
|
||||
[3d_armor:chestplate_crystal] X = [ethereal:crystal_ingot] **
|
||||
[3d_armor:chestplate_nether] X = [ethereal:nether_ingot] **
|
||||
|
||||
Leggings:
|
||||
|
||||
@ -40,35 +52,33 @@ Leggings:
|
||||
+---+---+---+
|
||||
|
||||
[3d_armor:leggings_wood] X = [default:wood]
|
||||
[3d_armor:leggings_cactus] X = [default:cactus]
|
||||
[3d_armor:leggings_steel] X = [default:steel_ingot]
|
||||
[3d_armor:leggings_bronze] X = [default:bronze_ingot]
|
||||
[3d_armor:leggings_diamond] X = [default:diamond]
|
||||
[3d_armor:leggings_gold] X = [default:gold_ingot]
|
||||
[3d_armor:leggings_mithril] X = [moreores:mithril_ingot] *
|
||||
[3d_armor:leggings_crystal] X = [ethereal:crystal_ingot] **
|
||||
[3d_armor:leggings_nether] X = [ethereal:nether_ingot] **
|
||||
|
||||
Shields:
|
||||
Boots:
|
||||
|
||||
+---+---+---+
|
||||
| X | X | X |
|
||||
| X | | X |
|
||||
+---+---+---+
|
||||
| X | X | X |
|
||||
+---+---+---+
|
||||
| | X | |
|
||||
| X | | X |
|
||||
+---+---+---+
|
||||
|
||||
[3d_armor:shield_wood] X = [default:wood]
|
||||
[3d_armor:shield_steel] X = [default:steel_ingot]
|
||||
[3d_armor:shield_bronze] X = [default:bronze_ingot
|
||||
|
||||
Enhanced Wooden Shield:
|
||||
|
||||
SI = [default:steel_ingot]
|
||||
WS = [3d_armor:shield_wood]
|
||||
|
||||
+----+
|
||||
| SI |
|
||||
+----+
|
||||
| WS |
|
||||
+----+
|
||||
| SI |
|
||||
+----+
|
||||
|
||||
[3d_armor:shield_enhanced_wood]
|
||||
[3d_armor:boots_wood] X = [default:wood]
|
||||
[3d_armor:boots_cactus] X = [default:cactus]
|
||||
[3d_armor:boots_steel] X = [default:steel_ingot]
|
||||
[3d_armor:boots_bronze] X = [default:bronze_ingot
|
||||
[3d_armor:boots_diamond] X = [default:diamond]
|
||||
[3d_armor:boots_gold] X = [default:gold_ingot]
|
||||
[3d_armor:boots_mithril] X = [moreores:mithril_ingot] *
|
||||
[3d_armor:boots_crystal] X = [ethereal:crystal_ingot] **
|
||||
[3d_armor:boots_nether] X = [ethereal:nether_ingot] **
|
||||
|
||||
* Requires moreores mod by Calinou - https://forum.minetest.net/viewtopic.php?id=549
|
||||
** Requires ethereal mod by Chinchow & TenPlus1 - https://github.com/tenplus1/ethereal
|
||||
** Requires nether mod - https://github.com/minetest-mods/nether.git
|
||||
|
@ -1,3 +0,0 @@
|
||||
default
|
||||
inventory_plus
|
||||
unified_skins
|
@ -1,231 +1,504 @@
|
||||
dofile(minetest.get_modpath(minetest.get_current_modname()).."/armor_api.lua")
|
||||
local modname = minetest.get_current_modname()
|
||||
local modpath = minetest.get_modpath(modname)
|
||||
local worldpath = minetest.get_worldpath()
|
||||
local last_punch_time = {}
|
||||
local timer = 0
|
||||
|
||||
local time = 0
|
||||
local update_time = tonumber(minetest.setting_get("3d_armor_update_time"))
|
||||
if not update_time then
|
||||
update_time = 1
|
||||
minetest.setting_set("3d_armor_update_time", tostring(update_time))
|
||||
dofile(modpath.."/api.lua")
|
||||
|
||||
-- local functions
|
||||
local F = minetest.formspec_escape
|
||||
local S = armor.get_translator
|
||||
|
||||
-- integration test
|
||||
if minetest.settings:get_bool("enable_3d_armor_integration_test") then
|
||||
dofile(modpath.."/integration_test.lua")
|
||||
end
|
||||
|
||||
-- Regisiter Head Armor
|
||||
|
||||
minetest.register_tool("3d_armor:helmet_wood", {
|
||||
description = "Wood Helmet",
|
||||
inventory_image = "3d_armor_inv_helmet_wood.png",
|
||||
groups = {armor_head=5, armor_heal=0, armor_use=1000},
|
||||
wear = 0,
|
||||
})
|
||||
-- Legacy Config Support
|
||||
|
||||
minetest.register_tool("3d_armor:helmet_steel", {
|
||||
description = "Steel Helmet",
|
||||
inventory_image = "3d_armor_inv_helmet_steel.png",
|
||||
groups = {armor_head=10, armor_heal=5, armor_use=250},
|
||||
wear = 0,
|
||||
})
|
||||
|
||||
minetest.register_tool("3d_armor:helmet_bronze", {
|
||||
description = "Bronze Helmet",
|
||||
inventory_image = "3d_armor_inv_helmet_bronze.png",
|
||||
groups = {armor_head=15, armor_heal=10, armor_use=100},
|
||||
wear = 0,
|
||||
})
|
||||
|
||||
-- Regisiter Torso Armor
|
||||
|
||||
minetest.register_tool("3d_armor:chestplate_wood", {
|
||||
description = "Wood Chestplate",
|
||||
inventory_image = "3d_armor_inv_chestplate_wood.png",
|
||||
groups = {armor_torso=10, armor_heal=0, armor_use=1000},
|
||||
wear = 0,
|
||||
})
|
||||
|
||||
minetest.register_tool("3d_armor:chestplate_steel", {
|
||||
description = "Steel Chestplate",
|
||||
inventory_image = "3d_armor_inv_chestplate_steel.png",
|
||||
groups = {armor_torso=15, armor_heal=5, armor_use=250},
|
||||
wear = 0,
|
||||
})
|
||||
|
||||
minetest.register_tool("3d_armor:chestplate_bronze", {
|
||||
description = "Bronze Chestplate",
|
||||
inventory_image = "3d_armor_inv_chestplate_bronze.png",
|
||||
groups = {armor_torso=25, armor_heal=10, armor_use=100},
|
||||
wear = 0,
|
||||
})
|
||||
|
||||
-- Regisiter Leg Armor
|
||||
|
||||
minetest.register_tool("3d_armor:leggings_wood", {
|
||||
description = "Wood Leggings",
|
||||
inventory_image = "3d_armor_inv_leggings_wood.png",
|
||||
groups = {armor_legs=5, armor_heal=0, armor_use=1000},
|
||||
wear = 0,
|
||||
})
|
||||
|
||||
minetest.register_tool("3d_armor:leggings_steel", {
|
||||
description = "Steel Leggings",
|
||||
inventory_image = "3d_armor_inv_leggings_steel.png",
|
||||
groups = {armor_legs=10, armor_heal=5, armor_use=250},
|
||||
wear = 0,
|
||||
})
|
||||
|
||||
minetest.register_tool("3d_armor:leggings_bronze", {
|
||||
description = "Bronze Leggings",
|
||||
inventory_image = "3d_armor_inv_leggings_bronze.png",
|
||||
groups = {armor_legs=15, armor_heal=10, armor_use=100},
|
||||
wear = 0,
|
||||
})
|
||||
|
||||
-- Regisiter Shields
|
||||
|
||||
minetest.register_tool("3d_armor:shield_wood", {
|
||||
description = "Wooden Shield",
|
||||
inventory_image = "3d_armor_inv_shield_wood.png",
|
||||
groups = {armor_shield=10, armor_heal=0, armor_use=1000},
|
||||
wear = 0,
|
||||
})
|
||||
|
||||
minetest.register_tool("3d_armor:shield_enhanced_wood", {
|
||||
description = "Enhanced Wooden Shield",
|
||||
inventory_image = "3d_armor_inv_shield_enhanced_wood.png",
|
||||
groups = {armor_shield=15, armor_heal=5, armor_use=500},
|
||||
wear = 0,
|
||||
})
|
||||
|
||||
minetest.register_tool("3d_armor:shield_steel", {
|
||||
description = "Steel Shield",
|
||||
inventory_image = "3d_armor_inv_shield_steel.png",
|
||||
groups = {armor_shield=20, armor_heal=5, armor_use=250},
|
||||
wear = 0,
|
||||
})
|
||||
|
||||
minetest.register_tool("3d_armor:shield_bronze", {
|
||||
description = "Bronze Shield",
|
||||
inventory_image = "3d_armor_inv_shield_bronze.png",
|
||||
groups = {armor_shield=25, armor_heal=10, armor_use=100},
|
||||
wear = 0,
|
||||
})
|
||||
|
||||
-- Register Craft Recipies
|
||||
|
||||
local craft_ingreds = {
|
||||
wood = "default:wood",
|
||||
steel = "default:steel_ingot",
|
||||
bronze = "default:bronze_ingot",
|
||||
}
|
||||
|
||||
for k, v in pairs(craft_ingreds) do
|
||||
minetest.register_craft({
|
||||
output = "3d_armor:helmet_"..k,
|
||||
recipe = {
|
||||
{v, v, v},
|
||||
{v, "", v},
|
||||
{"", "", ""},
|
||||
},
|
||||
})
|
||||
minetest.register_craft({
|
||||
output = "3d_armor:chestplate_"..k,
|
||||
recipe = {
|
||||
{v, "", v},
|
||||
{v, v, v},
|
||||
{v, v, v},
|
||||
},
|
||||
})
|
||||
minetest.register_craft({
|
||||
output = "3d_armor:leggings_"..k,
|
||||
recipe = {
|
||||
{v, v, v},
|
||||
{v, "", v},
|
||||
{v, "", v},
|
||||
},
|
||||
})
|
||||
minetest.register_craft({
|
||||
output = "3d_armor:shield_"..k,
|
||||
recipe = {
|
||||
{v, v, v},
|
||||
{v, v, v},
|
||||
{"", v, ""},
|
||||
},
|
||||
})
|
||||
local input = io.open(modpath.."/armor.conf", "r")
|
||||
if input then
|
||||
dofile(modpath.."/armor.conf")
|
||||
input:close()
|
||||
end
|
||||
input = io.open(worldpath.."/armor.conf", "r")
|
||||
if input then
|
||||
dofile(worldpath.."/armor.conf")
|
||||
input:close()
|
||||
end
|
||||
for name, _ in pairs(armor.config) do
|
||||
local global = "ARMOR_"..name:upper()
|
||||
if minetest.global_exists(global) then
|
||||
armor.config[name] = _G[global]
|
||||
end
|
||||
end
|
||||
if minetest.global_exists("ARMOR_MATERIALS") then
|
||||
armor.materials = table.copy(ARMOR_MATERIALS)
|
||||
end
|
||||
if minetest.global_exists("ARMOR_FIRE_NODES") then
|
||||
armor.fire_nodes = table.copy(ARMOR_FIRE_NODES)
|
||||
end
|
||||
|
||||
minetest.register_craft({
|
||||
output = "3d_armor:shield_enhanced_wood",
|
||||
recipe = {
|
||||
{"default:steel_ingot"},
|
||||
{"3d_armor:shield_wood"},
|
||||
{"default:steel_ingot"},
|
||||
},
|
||||
})
|
||||
-- Load Configuration
|
||||
|
||||
-- Register Callbacks
|
||||
for name, config in pairs(armor.config) do
|
||||
local setting = minetest.settings:get("armor_"..name)
|
||||
if type(config) == "number" then
|
||||
setting = tonumber(setting)
|
||||
elseif type(config) == "string" then
|
||||
setting = tostring(setting)
|
||||
elseif type(config) == "boolean" then
|
||||
setting = minetest.settings:get_bool("armor_"..name)
|
||||
end
|
||||
if setting ~= nil then
|
||||
armor.config[name] = setting
|
||||
end
|
||||
end
|
||||
for material, _ in pairs(armor.materials) do
|
||||
local key = "material_"..material
|
||||
if armor.config[key] == false then
|
||||
armor.materials[material] = nil
|
||||
end
|
||||
end
|
||||
|
||||
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
||||
-- Convert set_elements to a Lua table splitting on blank spaces
|
||||
local t_set_elements = armor.config.set_elements
|
||||
armor.config.set_elements = string.split(t_set_elements, " ")
|
||||
|
||||
-- Remove torch damage if fire_protect_torch == false
|
||||
if armor.config.fire_protect_torch == false and armor.config.fire_protect == true then
|
||||
for k,v in pairs(armor.fire_nodes) do
|
||||
for k2,v2 in pairs(v) do
|
||||
if string.find (v2,"torch") then
|
||||
armor.fire_nodes[k] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Mod Compatibility
|
||||
|
||||
if minetest.get_modpath("technic") then
|
||||
armor.formspec = armor.formspec..
|
||||
"label[5,2.5;"..F(S("Radiation"))..": armor_group_radiation]"
|
||||
armor:register_armor_group("radiation")
|
||||
end
|
||||
local skin_mods = {"skins", "u_skins", "simple_skins", "wardrobe"}
|
||||
for _, mod in pairs(skin_mods) do
|
||||
local path = minetest.get_modpath(mod)
|
||||
if path then
|
||||
local dir_list = minetest.get_dir_list(path.."/textures")
|
||||
for _, fn in pairs(dir_list) do
|
||||
if fn:find("_preview.png$") then
|
||||
armor:add_preview(fn)
|
||||
end
|
||||
end
|
||||
armor.set_skin_mod(mod)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- Armor Initialization
|
||||
|
||||
armor.formspec = armor.formspec..
|
||||
"label[5,1;"..F(S("Level"))..": armor_level]"..
|
||||
"label[5,1.5;"..F(S("Heal"))..": armor_attr_heal]"
|
||||
if armor.config.fire_protect then
|
||||
armor.formspec = armor.formspec.."label[5,2;"..F(S("Fire"))..": armor_attr_fire]"
|
||||
end
|
||||
armor:register_on_damage(function(player, index, stack)
|
||||
local name = player:get_player_name()
|
||||
if fields.outfit then
|
||||
inventory_plus.set_inventory_formspec(player, "size[8,7.5]"
|
||||
.."button[0,0;2,0.5;main;Back]"
|
||||
.."list[current_player;main;0,3.5;8,4;]"
|
||||
.."list[detached:"..name.."_outfit;armor_head;3,0;1,1;]"
|
||||
.."list[detached:"..name.."_outfit;armor_torso;3,1;1,1;]"
|
||||
.."list[detached:"..name.."_outfit;armor_legs;3,2;1,1;]"
|
||||
.."list[detached:"..name.."_outfit;armor_shield;4,1;1,1;]")
|
||||
local def = stack:get_definition()
|
||||
if name and def and def.description and stack:get_wear() > 60100 then
|
||||
minetest.chat_send_player(name, S("Your @1 is almost broken!", def.description))
|
||||
minetest.sound_play("default_tool_breaks", {to_player = name, gain = 2.0})
|
||||
end
|
||||
end)
|
||||
armor:register_on_destroy(function(player, index, stack)
|
||||
local name = player:get_player_name()
|
||||
local def = stack:get_definition()
|
||||
if name and def and def.description then
|
||||
minetest.chat_send_player(name, S("Your @1 got destroyed!", def.description))
|
||||
minetest.sound_play("default_tool_breaks", {to_player = name, gain = 2.0})
|
||||
end
|
||||
end)
|
||||
|
||||
local function validate_armor_inventory(player)
|
||||
-- Workaround for detached inventory swap exploit
|
||||
local _, inv = armor:get_valid_player(player, "[validate_armor_inventory]")
|
||||
local pos = player:get_pos()
|
||||
if not inv then
|
||||
return
|
||||
end
|
||||
local armor_prev = {}
|
||||
local attribute_meta = player:get_meta() -- I know, the function's name is weird but let it be like that. ;)
|
||||
local armor_list_string = attribute_meta:get_string("3d_armor_inventory")
|
||||
if armor_list_string then
|
||||
local armor_list = armor:deserialize_inventory_list(armor_list_string)
|
||||
for i, stack in ipairs(armor_list) do
|
||||
if stack:get_count() > 0 then
|
||||
armor_prev[stack:get_name()] = i
|
||||
end
|
||||
end
|
||||
end
|
||||
local elements = {}
|
||||
local player_inv = player:get_inventory()
|
||||
for i = 1, 6 do
|
||||
local stack = inv:get_stack("armor", i)
|
||||
if stack:get_count() > 0 then
|
||||
local item = stack:get_name()
|
||||
local element = armor:get_element(item)
|
||||
if element and not elements[element] then
|
||||
if armor_prev[item] then
|
||||
armor_prev[item] = nil
|
||||
else
|
||||
-- Item was not in previous inventory
|
||||
armor:run_callbacks("on_equip", player, i, stack)
|
||||
end
|
||||
elements[element] = true;
|
||||
else
|
||||
inv:remove_item("armor", stack)
|
||||
minetest.item_drop(stack, player, pos)
|
||||
-- The following code returns invalid items to the player's main
|
||||
-- inventory but could open up the possibity for a hacked client
|
||||
-- to receive items back they never really had. I am not certain
|
||||
-- so remove the is_singleplayer check at your own risk :]
|
||||
if minetest.is_singleplayer() and player_inv and
|
||||
player_inv:room_for_item("main", stack) then
|
||||
player_inv:add_item("main", stack)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
for item, i in pairs(armor_prev) do
|
||||
local stack = ItemStack(item)
|
||||
-- Previous item is not in current inventory
|
||||
armor:run_callbacks("on_unequip", player, i, stack)
|
||||
end
|
||||
end
|
||||
|
||||
local function init_player_armor(initplayer)
|
||||
local name = assert(initplayer:get_player_name())
|
||||
local armor_inv = minetest.create_detached_inventory(name.."_armor", {
|
||||
on_put = function(inv, listname, index, stack, player)
|
||||
validate_armor_inventory(player)
|
||||
armor:save_armor_inventory(player)
|
||||
armor:set_player_armor(player)
|
||||
end,
|
||||
on_take = function(inv, listname, index, stack, player)
|
||||
validate_armor_inventory(player)
|
||||
armor:save_armor_inventory(player)
|
||||
armor:set_player_armor(player)
|
||||
end,
|
||||
on_move = function(inv, from_list, from_index, to_list, to_index, count, player)
|
||||
validate_armor_inventory(player)
|
||||
armor:save_armor_inventory(player)
|
||||
armor:set_player_armor(player)
|
||||
end,
|
||||
allow_put = function(inv, listname, index, put_stack, player)
|
||||
if player:get_player_name() ~= name then
|
||||
return 0
|
||||
end
|
||||
local element = armor:get_element(put_stack:get_name())
|
||||
if not element then
|
||||
return 0
|
||||
end
|
||||
for i = 1, 6 do
|
||||
local stack = inv:get_stack("armor", i)
|
||||
local def = stack:get_definition() or {}
|
||||
if def.groups and def.groups["armor_"..element]
|
||||
and i ~= index then
|
||||
return 0
|
||||
end
|
||||
end
|
||||
return 1
|
||||
end,
|
||||
allow_take = function(inv, listname, index, stack, player)
|
||||
if player:get_player_name() ~= name then
|
||||
return 0
|
||||
end
|
||||
--cursed items cannot be unequiped by the player
|
||||
local is_cursed = minetest.get_item_group(stack:get_name(), "cursed") ~= 0
|
||||
if not minetest.is_creative_enabled(player) and is_cursed then
|
||||
return 0
|
||||
end
|
||||
return stack:get_count()
|
||||
end,
|
||||
allow_move = function(inv, from_list, from_index, to_list, to_index, count, player)
|
||||
if player:get_player_name() ~= name then
|
||||
return 0
|
||||
end
|
||||
return count
|
||||
end,
|
||||
}, name)
|
||||
armor_inv:set_size("armor", 6)
|
||||
if not armor:load_armor_inventory(initplayer) and armor.migrate_old_inventory then
|
||||
local player_inv = initplayer:get_inventory()
|
||||
player_inv:set_size("armor", 6)
|
||||
for i=1, 6 do
|
||||
local stack = player_inv:get_stack("armor", i)
|
||||
armor_inv:set_stack("armor", i, stack)
|
||||
end
|
||||
armor:save_armor_inventory(initplayer)
|
||||
player_inv:set_size("armor", 0)
|
||||
end
|
||||
for i=1, 6 do
|
||||
local stack = armor_inv:get_stack("armor", i)
|
||||
if stack:get_count() > 0 then
|
||||
armor:run_callbacks("on_equip", initplayer, i, stack)
|
||||
end
|
||||
end
|
||||
armor.def[name] = {
|
||||
level = 0,
|
||||
state = 0,
|
||||
count = 0,
|
||||
groups = {},
|
||||
}
|
||||
for _, phys in pairs(armor.physics) do
|
||||
armor.def[name][phys] = 1
|
||||
end
|
||||
for _, attr in pairs(armor.attributes) do
|
||||
armor.def[name][attr] = 0
|
||||
end
|
||||
for group, _ in pairs(armor.registered_groups) do
|
||||
armor.def[name].groups[group] = 0
|
||||
end
|
||||
local skin = armor:get_player_skin(name)
|
||||
armor.textures[name] = {
|
||||
skin = skin,
|
||||
armor = "blank.png",
|
||||
wielditem = "blank.png",
|
||||
preview = armor.default_skin.."_preview.png",
|
||||
}
|
||||
local texture_path = minetest.get_modpath("player_textures")
|
||||
if texture_path then
|
||||
local dir_list = minetest.get_dir_list(texture_path.."/textures")
|
||||
for _, fn in pairs(dir_list) do
|
||||
if fn == "player_"..name..".png" then
|
||||
armor.textures[name].skin = fn
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
armor:set_player_armor(initplayer)
|
||||
end
|
||||
|
||||
-- Armor Player Model
|
||||
|
||||
player_api.register_model("3d_armor_character.b3d", {
|
||||
animation_speed = 30,
|
||||
textures = {
|
||||
armor.default_skin..".png",
|
||||
"blank.png",
|
||||
"blank.png",
|
||||
},
|
||||
animations = {
|
||||
stand = {x=0, y=79},
|
||||
lay = {x=162, y=166, eye_height = 0.3, override_local = true,
|
||||
collisionbox = {-0.6, 0.0, -0.6, 0.6, 0.3, 0.6}},
|
||||
walk = {x=168, y=187},
|
||||
mine = {x=189, y=198},
|
||||
walk_mine = {x=200, y=219},
|
||||
sit = {x=81, y=160, eye_height = 0.8, override_local = true,
|
||||
collisionbox = {-0.3, 0.0, -0.3, 0.3, 1.0, 0.3}},
|
||||
-- compatibility w/ the emote mod
|
||||
wave = {x = 192, y = 196, override_local = true},
|
||||
point = {x = 196, y = 196, override_local = true},
|
||||
freeze = {x = 205, y = 205, override_local = true},
|
||||
},
|
||||
collisionbox = {-0.3, 0.0, -0.3, 0.3, 1.7, 0.3},
|
||||
-- stepheight: use default
|
||||
eye_height = 1.47,
|
||||
})
|
||||
|
||||
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
||||
local name = armor:get_valid_player(player, "[on_player_receive_fields]")
|
||||
if not name then
|
||||
return
|
||||
end
|
||||
local player_name = player:get_player_name()
|
||||
for field, _ in pairs(fields) do
|
||||
if string.sub(field,0,string.len("skins_set_")) == "skins_set_" then
|
||||
minetest.after(0, function(player)
|
||||
armor_api:set_player_armor(player)
|
||||
end, player)
|
||||
if string.find(field, "skins_set") then
|
||||
armor:update_skin(player_name)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
minetest.register_on_joinplayer(function(player)
|
||||
inventory_plus.register_button(player,"outfit", "Outfit")
|
||||
local player_inv = player:get_inventory()
|
||||
local name = player:get_player_name()
|
||||
local armor_inv = minetest.create_detached_inventory(name.."_outfit",{
|
||||
on_put = function(inv, listname, index, stack, player)
|
||||
player:get_inventory():set_stack(listname, index, stack)
|
||||
armor_api:set_player_armor(player)
|
||||
end,
|
||||
on_take = function(inv, listname, index, stack, player)
|
||||
player:get_inventory():set_stack(listname, index, nil)
|
||||
armor_api:set_player_armor(player)
|
||||
end,
|
||||
allow_put = function(inv, listname, index, stack, player)
|
||||
if inv:is_empty(listname) then
|
||||
return 1
|
||||
end
|
||||
return 0
|
||||
end,
|
||||
allow_take = function(inv, listname, index, stack, player)
|
||||
return stack:get_count()
|
||||
end,
|
||||
allow_move = function(inv, from_list, from_index, to_list, to_index, count, player)
|
||||
return 0
|
||||
end,
|
||||
})
|
||||
for _,v in ipairs({"head", "torso", "legs", "shield"}) do
|
||||
local armor = "armor_"..v
|
||||
player_inv:set_size(armor, 1)
|
||||
armor_inv:set_size(armor, 1)
|
||||
armor_inv:set_stack(armor, 1, player_inv:get_stack(armor, 1))
|
||||
end
|
||||
armor_api.player_hp[name] = 0
|
||||
minetest.after(0, function(player)
|
||||
armor_api:set_player_armor(player)
|
||||
end, player)
|
||||
player_api.set_model(player, "3d_armor_character.b3d")
|
||||
init_player_armor(player)
|
||||
end)
|
||||
|
||||
minetest.register_on_leaveplayer(function(player)
|
||||
local name = player:get_player_name()
|
||||
if name then
|
||||
armor.def[name] = nil
|
||||
armor.textures[name] = nil
|
||||
end
|
||||
end)
|
||||
|
||||
if armor.config.drop == true or armor.config.destroy == true then
|
||||
minetest.register_on_dieplayer(function(player)
|
||||
local name, armor_inv = armor:get_valid_player(player, "[on_dieplayer]")
|
||||
if not name then
|
||||
return
|
||||
end
|
||||
local drop = {}
|
||||
for i=1, armor_inv:get_size("armor") do
|
||||
local stack = armor_inv:get_stack("armor", i)
|
||||
if stack:get_count() > 0 then
|
||||
--soulbound armors remain equipped after death
|
||||
if minetest.get_item_group(stack:get_name(), "soulbound") == 0 then
|
||||
table.insert(drop, stack)
|
||||
armor:run_callbacks("on_unequip", player, i, stack)
|
||||
armor_inv:set_stack("armor", i, nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
armor:save_armor_inventory(player)
|
||||
armor:set_player_armor(player)
|
||||
local pos = player:get_pos()
|
||||
if pos and armor.config.destroy == false then
|
||||
minetest.after(armor.config.bones_delay, function()
|
||||
local meta = nil
|
||||
local maxp = vector.add(pos, 16)
|
||||
local minp = vector.subtract(pos, 16)
|
||||
local bones = minetest.find_nodes_in_area(minp, maxp, {"bones:bones"})
|
||||
for _, p in pairs(bones) do
|
||||
local m = minetest.get_meta(p)
|
||||
if m:get_string("owner") == name then
|
||||
meta = m
|
||||
break
|
||||
end
|
||||
end
|
||||
if meta then
|
||||
local inv = meta:get_inventory()
|
||||
for _,stack in ipairs(drop) do
|
||||
if inv:room_for_item("main", stack) then
|
||||
inv:add_item("main", stack)
|
||||
else
|
||||
armor.drop_armor(pos, stack)
|
||||
end
|
||||
end
|
||||
else
|
||||
for _,stack in ipairs(drop) do
|
||||
armor.drop_armor(pos, stack)
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
end)
|
||||
minetest.register_on_respawnplayer(function(player)
|
||||
-- reset un-dropped armor and it's effects
|
||||
armor:set_player_armor(player)
|
||||
end)
|
||||
end
|
||||
|
||||
if armor.config.punch_damage == true then
|
||||
minetest.register_on_punchplayer(function(player, hitter,
|
||||
time_from_last_punch, tool_capabilities)
|
||||
local name = player:get_player_name()
|
||||
if hitter then
|
||||
local hit_ip = hitter:is_player()
|
||||
if name and hit_ip and minetest.is_protected(player:get_pos(), "") then
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
if name then
|
||||
armor:punch(player, hitter, time_from_last_punch, tool_capabilities)
|
||||
last_punch_time[name] = minetest.get_gametime()
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
minetest.register_on_player_hpchange(function(player, hp_change, reason)
|
||||
if not minetest.is_player(player) then
|
||||
return hp_change
|
||||
end
|
||||
|
||||
if reason.type == "drown" or reason.hunger or hp_change >= 0 then
|
||||
return hp_change
|
||||
end
|
||||
|
||||
local name = player:get_player_name()
|
||||
local properties = player:get_properties()
|
||||
local hp = player:get_hp()
|
||||
if hp + hp_change < properties.hp_max then
|
||||
local heal = armor.def[name].heal
|
||||
if heal >= math.random(100) then
|
||||
hp_change = 0
|
||||
end
|
||||
-- check if armor damage was handled by fire or on_punchplayer
|
||||
local time = last_punch_time[name] or 0
|
||||
if time == 0 or time + 1 < minetest.get_gametime() then
|
||||
armor:punch(player)
|
||||
end
|
||||
end
|
||||
|
||||
return hp_change
|
||||
end, true)
|
||||
|
||||
minetest.register_globalstep(function(dtime)
|
||||
time = time + dtime
|
||||
if time > update_time then
|
||||
for _,player in ipairs(minetest.get_connected_players()) do
|
||||
armor_api:update_armor(player)
|
||||
timer = timer + dtime
|
||||
|
||||
if armor.config.feather_fall == true then
|
||||
for _,player in pairs(minetest.get_connected_players()) do
|
||||
local name = player:get_player_name()
|
||||
if armor.def[name].feather > 0 then
|
||||
local vel_y = player:get_velocity().y
|
||||
if vel_y < -0.5 then
|
||||
vel_y = -(vel_y * 0.05)
|
||||
player:add_velocity({x = 0, y = vel_y, z = 0})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if timer <= armor.config.init_delay then
|
||||
return
|
||||
end
|
||||
timer = 0
|
||||
|
||||
-- water breathing protection, added by TenPlus1
|
||||
if armor.config.water_protect == true then
|
||||
for _,player in pairs(minetest.get_connected_players()) do
|
||||
local name = player:get_player_name()
|
||||
if armor.def[name].water > 0 and
|
||||
player:get_breath() < 10 then
|
||||
player:set_breath(10)
|
||||
end
|
||||
end
|
||||
time = 0
|
||||
end
|
||||
end)
|
||||
|
||||
if armor.config.fire_protect == true then
|
||||
|
||||
-- make torches hurt
|
||||
minetest.override_item("default:torch", {damage_per_second = 1})
|
||||
minetest.override_item("default:torch_wall", {damage_per_second = 1})
|
||||
minetest.override_item("default:torch_ceiling", {damage_per_second = 1})
|
||||
|
||||
-- check player damage for any hot nodes we may be protected against
|
||||
minetest.register_on_player_hpchange(function(player, hp_change, reason)
|
||||
|
||||
if reason.type == "node_damage" and reason.node then
|
||||
-- fire protection
|
||||
if armor.config.fire_protect == true and hp_change < 0 then
|
||||
local name = player:get_player_name()
|
||||
for _,igniter in pairs(armor.fire_nodes) do
|
||||
if reason.node == igniter[1] then
|
||||
if armor.def[name].fire >= igniter[2] then
|
||||
hp_change = 0
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return hp_change
|
||||
end, true)
|
||||
end
|
||||
|
||||
minetest.log("action", "[3d_armor] loaded.")
|
||||
|
25
3d_armor/integration_test.lua
Normal file
@ -0,0 +1,25 @@
|
||||
|
||||
minetest.log("warning", "[TEST] integration-test enabled!")
|
||||
|
||||
minetest.register_on_mods_loaded(function()
|
||||
minetest.after(1, function()
|
||||
|
||||
local data = minetest.write_json({ success = true }, true);
|
||||
local file = io.open(minetest.get_worldpath().."/integration_test.json", "w" );
|
||||
if file then
|
||||
file:write(data)
|
||||
file:close()
|
||||
end
|
||||
|
||||
file = io.open(minetest.get_worldpath().."/registered_nodes.txt", "w" );
|
||||
if file then
|
||||
for name in pairs(minetest.registered_nodes) do
|
||||
file:write(name .. '\n')
|
||||
end
|
||||
file:close()
|
||||
end
|
||||
|
||||
minetest.log("warning", "[TEST] integration tests done!")
|
||||
minetest.request_shutdown("success")
|
||||
end)
|
||||
end)
|
7
3d_armor/locale/3d_armor.de.tr
Normal file
@ -0,0 +1,7 @@
|
||||
# textdomain: 3d_armor
|
||||
Radiation=Strahlung
|
||||
Level=Stufe
|
||||
Heal=Heilung
|
||||
Fire=Feuer
|
||||
Your @1 is almost broken!=@1 ist fast kaputt!
|
||||
Your @1 got destroyed!=@1 wurde zerstört!
|
7
3d_armor/locale/3d_armor.eo.tr
Normal file
@ -0,0 +1,7 @@
|
||||
# textdomain: 3d_armor
|
||||
Radiation=Radiado
|
||||
Level=Nivelo
|
||||
Heal=Blokŝanco
|
||||
Fire=Fajro
|
||||
Your @1 is almost broken!=Via @1 estas preskaŭ rompita!
|
||||
Your @1 got destroyed!=Via @1 detruiĝis!
|
7
3d_armor/locale/3d_armor.es.tr
Normal file
@ -0,0 +1,7 @@
|
||||
# textdomain: 3d_armor
|
||||
Radiation=Radiación
|
||||
Level=Nivel
|
||||
Heal=Salud
|
||||
Fire=Fuego
|
||||
Your @1 is almost broken!=¡Tu @1 esta a punto de romperse!
|
||||
Your @1 got destroyed!=¡Tu @1 fue destruído!
|
7
3d_armor/locale/3d_armor.fr.tr
Normal file
@ -0,0 +1,7 @@
|
||||
# textdomain: 3d_armor
|
||||
Radiation=Radiation
|
||||
Level=Niveau
|
||||
Heal=Soins
|
||||
Fire=Fire
|
||||
Your @1 is almost broken!=Une partie de votre armure est presque détruite : @1 !
|
||||
Your @1 got destroyed!=Une partie de votre armure a été détruite : @1 !
|
7
3d_armor/locale/3d_armor.it.tr
Normal file
@ -0,0 +1,7 @@
|
||||
# textdomain: 3d_armor
|
||||
Radiation=Radiazione
|
||||
Level=Livello
|
||||
Heal=Guarigione
|
||||
Fire=Fuoco
|
||||
Your @1 is almost broken!=@1 quasi in frantumi!
|
||||
Your @1 got destroyed!=@1 in frantumi!
|
7
3d_armor/locale/3d_armor.ms.tr
Normal file
@ -0,0 +1,7 @@
|
||||
# textdomain: 3d_armor
|
||||
Radiation=Radiasi
|
||||
Level=Tahap
|
||||
Heal=Pulih
|
||||
Fire=Api
|
||||
Your @1 is almost broken!=
|
||||
Your @1 got destroyed!=@1 anda telah musnah!
|
7
3d_armor/locale/3d_armor.pl.tr
Normal file
@ -0,0 +1,7 @@
|
||||
# textdomain: 3d_armor
|
||||
Radiation=Promieniowanie
|
||||
Level=Poziom
|
||||
Heal=Uzdrawianie
|
||||
Fire=Ogień
|
||||
Your @1 is almost broken!=Twój @1 jest prawie zepsuty!
|
||||
Your @1 got destroyed!=Twój @1 został zniszczony!
|
7
3d_armor/locale/3d_armor.pt.tr
Normal file
@ -0,0 +1,7 @@
|
||||
# textdomain: 3d_armor
|
||||
Radiation=Radiação
|
||||
Level=Nível
|
||||
Heal=Saúde
|
||||
Fire=Fogo
|
||||
Your @1 is almost broken!=
|
||||
Your @1 got destroyed!=@1 foi destruído(a)!
|
7
3d_armor/locale/3d_armor.pt_BR.tr
Normal file
@ -0,0 +1,7 @@
|
||||
# textdomain: 3d_armor
|
||||
Radiation=Radiação
|
||||
Level=Nível
|
||||
Heal=Saúde
|
||||
Fire=Fogo
|
||||
Your @1 is almost broken!=
|
||||
Your @1 got destroyed!=@1 foi destruído(a)!
|
7
3d_armor/locale/3d_armor.ru.tr
Normal file
@ -0,0 +1,7 @@
|
||||
# textdomain: 3d_armor
|
||||
Radiation=излучение
|
||||
Level=уровень
|
||||
Heal=исцеление
|
||||
Fire=огонь
|
||||
Your @1 is almost broken!=
|
||||
Your @1 got destroyed!=твой(и) @1 был(и) разрушен(ы)!
|
7
3d_armor/locale/3d_armor.sv.tr
Normal file
@ -0,0 +1,7 @@
|
||||
# textdomain: 3d_armor
|
||||
Radiation=Strålning
|
||||
Level=Nivå
|
||||
Heal=Läkning
|
||||
Fire=Eld
|
||||
Your @1 is almost broken!=Din @1 är nästan förstörd!
|
||||
Your @1 got destroyed!=Din @1 blev förstörd!
|
7
3d_armor/locale/template.txt
Normal file
@ -0,0 +1,7 @@
|
||||
# textdomain: 3d_armor
|
||||
Radiation=
|
||||
Level=
|
||||
Heal=
|
||||
Fire=
|
||||
Your @1 is almost broken!=
|
||||
Your @1 got destroyed!=
|
5
3d_armor/mod.conf
Normal file
@ -0,0 +1,5 @@
|
||||
name = 3d_armor
|
||||
depends = default, player_api
|
||||
optional_depends = player_monoids, armor_monoid, pova, moreores
|
||||
description = Adds craftable armor that is visible to other players.
|
||||
min_minetest_version = 5.0
|
BIN
3d_armor/models/3d_armor_character.b3d
Normal file
BIN
3d_armor/models/3d_armor_character.blend
Normal file
Before Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 246 B |
Before Width: | Height: | Size: 258 B |
Before Width: | Height: | Size: 244 B |
Before Width: | Height: | Size: 232 B |
Before Width: | Height: | Size: 255 B |
Before Width: | Height: | Size: 232 B |
Before Width: | Height: | Size: 240 B |
Before Width: | Height: | Size: 251 B |
Before Width: | Height: | Size: 241 B |
Before Width: | Height: | Size: 723 B |
Before Width: | Height: | Size: 747 B |
Before Width: | Height: | Size: 697 B |
Before Width: | Height: | Size: 667 B |
Before Width: | Height: | Size: 885 B |
Before Width: | Height: | Size: 774 B |
Before Width: | Height: | Size: 737 B |
BIN
3d_armor/textures/character_preview.png
Normal file
After Width: | Height: | Size: 339 B |
BIN
3d_armor/textures/inventory_plus_armor.png
Normal file
After Width: | Height: | Size: 544 B |
Before Width: | Height: | Size: 723 B |
7
3d_armor/tools/README.md
Normal file
@ -0,0 +1,7 @@
|
||||
# Intllib tool
|
||||
|
||||
please consider using the intllib tool to update locale files:
|
||||
|
||||
```../../intllib/tools/xgettext.sh ../**/*.lua```
|
||||
|
||||
make sure you are in `3d_armor` derectory before running this command
|
24
3d_armor/tools/updatepo.sh
Executable file
@ -0,0 +1,24 @@
|
||||
#! /bin/bash
|
||||
|
||||
# To create a new translation:
|
||||
# msginit --locale=ll_CC -o locale/ll_CC.po -i locale/template.pot
|
||||
|
||||
cd "$(dirname "${BASH_SOURCE[0]}")/..";
|
||||
|
||||
# Extract translatable strings.
|
||||
xgettext --from-code=UTF-8 \
|
||||
--language=Lua \
|
||||
--sort-by-file \
|
||||
--keyword=S \
|
||||
--keyword=NS:1,2 \
|
||||
--keyword=N_ \
|
||||
--add-comments='Translators:' \
|
||||
--add-location=file \
|
||||
-o locale/template.pot \
|
||||
$(find .. -name '*.lua')
|
||||
|
||||
# Update translations.
|
||||
find locale -name '*.po' | while read -r file; do
|
||||
echo $file
|
||||
msgmerge --update $file locale/template.pot;
|
||||
done
|
38
3d_armor_ip/init.lua
Normal file
@ -0,0 +1,38 @@
|
||||
-- support for i18n
|
||||
local S = minetest.get_translator(minetest.get_current_modname())
|
||||
local F = minetest.formspec_escape
|
||||
|
||||
if not minetest.global_exists("inventory_plus") then
|
||||
minetest.log("warning", "3d_armor_ip: Mod loaded but unused.")
|
||||
return
|
||||
end
|
||||
|
||||
armor.formspec = "size[8,8.5]button[6,0;2,0.5;main;"..F(S("Back")).."]"..armor.formspec
|
||||
armor:register_on_update(function(player)
|
||||
local name = player:get_player_name()
|
||||
local formspec = armor:get_armor_formspec(name, true)
|
||||
local page = player:get_inventory_formspec()
|
||||
if page:find("detached:"..name.."_armor") then
|
||||
inventory_plus.set_inventory_formspec(player, formspec)
|
||||
end
|
||||
end)
|
||||
|
||||
if minetest.get_modpath("crafting") then
|
||||
inventory_plus.get_formspec = function(player, page)
|
||||
end
|
||||
end
|
||||
|
||||
minetest.register_on_joinplayer(function(player)
|
||||
inventory_plus.register_button(player,"armor", S("Armor"))
|
||||
end)
|
||||
|
||||
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
||||
if fields.armor then
|
||||
local name = armor:get_valid_player(player, "[on_player_receive_fields]")
|
||||
if not name then
|
||||
return
|
||||
end
|
||||
local formspec = armor:get_armor_formspec(name, true)
|
||||
inventory_plus.set_inventory_formspec(player, formspec)
|
||||
end
|
||||
end)
|
3
3d_armor_ip/locale/3d_armor_ip.de.tr
Normal file
@ -0,0 +1,3 @@
|
||||
# textdomain: 3d_armor_ip
|
||||
Back=Zurück
|
||||
Armor=Rüstung
|
3
3d_armor_ip/locale/3d_armor_ip.eo.tr
Normal file
@ -0,0 +1,3 @@
|
||||
# textdomain: 3d_armor_ip
|
||||
Back=Dorso
|
||||
Armor=Armaĵo
|
3
3d_armor_ip/locale/3d_armor_ip.fr.tr
Normal file
@ -0,0 +1,3 @@
|
||||
# textdomain: 3d_armor_ip
|
||||
Back=Retour
|
||||
Armor=Armure
|
3
3d_armor_ip/locale/3d_armor_ip.pt_BR.tr
Normal file
@ -0,0 +1,3 @@
|
||||
# textdomain: 3d_armor_ip
|
||||
Back=Voltar
|
||||
Armor=Armadura
|
3
3d_armor_ip/locale/3d_armor_ip.sv.tr
Normal file
@ -0,0 +1,3 @@
|
||||
# textdomain: 3d_armor_ip
|
||||
Back=Tillbaka
|
||||
Armor=Rustning
|
3
3d_armor_ip/locale/template.txt
Normal file
@ -0,0 +1,3 @@
|
||||
# textdomain: 3d_armor_ip
|
||||
Back=
|
||||
Armor=
|
4
3d_armor_ip/mod.conf
Normal file
@ -0,0 +1,4 @@
|
||||
name = 3d_armor_ip
|
||||
depends = 3d_armor
|
||||
optional_depends = inventory_plus
|
||||
description = Adds 3d_armor page to the inventory plus.
|
21
3d_armor_sfinv/init.lua
Normal file
@ -0,0 +1,21 @@
|
||||
-- support for i18n
|
||||
local S = minetest.get_translator(minetest.get_current_modname())
|
||||
|
||||
if not minetest.global_exists("sfinv") then
|
||||
minetest.log("warning", "3d_armor_sfinv: Mod loaded but unused.")
|
||||
return
|
||||
end
|
||||
|
||||
sfinv.register_page("3d_armor:armor", {
|
||||
title = S("Armor"),
|
||||
get = function(self, player, context)
|
||||
local name = player:get_player_name()
|
||||
local formspec = armor:get_armor_formspec(name, true)
|
||||
return sfinv.make_formspec(player, context, formspec, false)
|
||||
end
|
||||
})
|
||||
armor:register_on_update(function(player)
|
||||
if sfinv.enabled then
|
||||
sfinv.set_player_inventory_formspec(player)
|
||||
end
|
||||
end)
|
2
3d_armor_sfinv/locale/3d_armor_sfinv.de.tr
Normal file
@ -0,0 +1,2 @@
|
||||
# textdomain: 3d_armor_sfinv
|
||||
Armor=Rüstung
|
2
3d_armor_sfinv/locale/3d_armor_sfinv.eo.tr
Normal file
@ -0,0 +1,2 @@
|
||||
# textdomain: 3d_armor_sfinv
|
||||
Armor=Armaĵoj
|
2
3d_armor_sfinv/locale/3d_armor_sfinv.es.tr
Normal file
@ -0,0 +1,2 @@
|
||||
# textdomain: 3d_armor_sfinv
|
||||
Armor=Armadura
|
2
3d_armor_sfinv/locale/3d_armor_sfinv.fr.tr
Normal file
@ -0,0 +1,2 @@
|
||||
# textdomain: 3d_armor_sfinv
|
||||
Armor=Armure
|
2
3d_armor_sfinv/locale/3d_armor_sfinv.pt_BR.tr
Normal file
@ -0,0 +1,2 @@
|
||||
# textdomain: 3d_armor_sfinv
|
||||
Armor=Armadura
|
2
3d_armor_sfinv/locale/3d_armor_sfinv.sv.tr
Normal file
@ -0,0 +1,2 @@
|
||||
# textdomain: 3d_armor_sfinv
|
||||
Armor=Rustning
|
2
3d_armor_sfinv/locale/template.txt
Normal file
@ -0,0 +1,2 @@
|
||||
# textdomain: 3d_armor_sfinv
|
||||
Armor=
|
4
3d_armor_sfinv/mod.conf
Normal file
@ -0,0 +1,4 @@
|
||||
name = 3d_armor_sfinv
|
||||
depends = 3d_armor
|
||||
optional_depends = sfinv
|
||||
description = Adds 3d_armor page to the sfinv inventory.
|
21
3d_armor_stand/README.txt
Normal file
@ -0,0 +1,21 @@
|
||||
[mod] 3d Armor Stand [3d_armor_stand]
|
||||
=====================================
|
||||
|
||||
Depends: 3d_armor
|
||||
|
||||
Adds a chest-like armor stand for armor storage and display.
|
||||
|
||||
Crafting
|
||||
--------
|
||||
|
||||
F = Wooden Fence [default:fence_wood]
|
||||
S = Steel Ingot [default:steel_ingot]
|
||||
|
||||
+---+---+---+
|
||||
| | F | |
|
||||
+---+---+---+
|
||||
| | F | |
|
||||
+---+---+---+
|
||||
| S | S | S |
|
||||
+---+---+---+
|
||||
|
447
3d_armor_stand/init.lua
Normal file
@ -0,0 +1,447 @@
|
||||
-- support for i18n
|
||||
local S = minetest.get_translator(minetest.get_current_modname())
|
||||
|
||||
local armor_stand_formspec = "size[8,7]" ..
|
||||
default.gui_bg ..
|
||||
default.gui_bg_img ..
|
||||
default.gui_slots ..
|
||||
default.get_hotbar_bg(0,3) ..
|
||||
"list[current_name;armor_head;3,0.5;1,1;]" ..
|
||||
"list[current_name;armor_torso;4,0.5;1,1;]" ..
|
||||
"list[current_name;armor_legs;3,1.5;1,1;]" ..
|
||||
"list[current_name;armor_feet;4,1.5;1,1;]" ..
|
||||
"image[3,0.5;1,1;3d_armor_stand_head.png]" ..
|
||||
"image[4,0.5;1,1;3d_armor_stand_torso.png]" ..
|
||||
"image[3,1.5;1,1;3d_armor_stand_legs.png]" ..
|
||||
"image[4,1.5;1,1;3d_armor_stand_feet.png]" ..
|
||||
"list[current_player;main;0,3;8,1;]" ..
|
||||
"list[current_player;main;0,4.25;8,3;8]"
|
||||
|
||||
local elements = {"head", "torso", "legs", "feet"}
|
||||
|
||||
local function drop_armor(pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
for _, element in pairs(elements) do
|
||||
local stack = inv:get_stack("armor_"..element, 1)
|
||||
if stack and stack:get_count() > 0 then
|
||||
armor.drop_armor(pos, stack)
|
||||
inv:set_stack("armor_"..element, 1, nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function get_stand_object(pos)
|
||||
local object = nil
|
||||
local objects = minetest.get_objects_inside_radius(pos, 0.5) or {}
|
||||
for _, obj in pairs(objects) do
|
||||
local ent = obj:get_luaentity()
|
||||
if ent then
|
||||
if ent.name == "3d_armor_stand:armor_entity" then
|
||||
-- Remove duplicates
|
||||
if object then
|
||||
obj:remove()
|
||||
else
|
||||
object = obj
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return object
|
||||
end
|
||||
|
||||
local function update_entity(pos)
|
||||
local node = minetest.get_node(pos)
|
||||
local object = get_stand_object(pos)
|
||||
if object then
|
||||
if not string.find(node.name, "3d_armor_stand:") then
|
||||
object:remove()
|
||||
return
|
||||
end
|
||||
else
|
||||
object = minetest.add_entity(pos, "3d_armor_stand:armor_entity")
|
||||
end
|
||||
if object then
|
||||
local texture = "blank.png"
|
||||
local textures = {}
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
local yaw = 0
|
||||
if inv then
|
||||
for _, element in pairs(elements) do
|
||||
local stack = inv:get_stack("armor_"..element, 1)
|
||||
if stack:get_count() == 1 then
|
||||
local item = stack:get_name() or ""
|
||||
local def = stack:get_definition() or {}
|
||||
local groups = def.groups or {}
|
||||
if groups["armor_"..element] then
|
||||
if def.texture then
|
||||
table.insert(textures, def.texture)
|
||||
else
|
||||
table.insert(textures, item:gsub("%:", "_")..".png")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if #textures > 0 then
|
||||
texture = table.concat(textures, "^")
|
||||
end
|
||||
if node.param2 then
|
||||
local rot = node.param2 % 4
|
||||
if rot == 1 then
|
||||
yaw = 3 * math.pi / 2
|
||||
elseif rot == 2 then
|
||||
yaw = math.pi
|
||||
elseif rot == 3 then
|
||||
yaw = math.pi / 2
|
||||
end
|
||||
end
|
||||
object:set_yaw(yaw)
|
||||
object:set_properties({textures={texture}})
|
||||
end
|
||||
end
|
||||
|
||||
local function has_locked_armor_stand_privilege(meta, player)
|
||||
local name = ""
|
||||
if player then
|
||||
if minetest.check_player_privs(player, "protection_bypass") then
|
||||
return true
|
||||
end
|
||||
name = player:get_player_name()
|
||||
end
|
||||
if name ~= meta:get_string("owner") then
|
||||
return false
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
local function add_hidden_node(pos, player)
|
||||
local p = {x=pos.x, y=pos.y + 1, z=pos.z}
|
||||
local name = player:get_player_name()
|
||||
local node = minetest.get_node(p)
|
||||
if node.name == "air" and not minetest.is_protected(pos, name) then
|
||||
minetest.set_node(p, {name="3d_armor_stand:top"})
|
||||
end
|
||||
end
|
||||
|
||||
local function remove_hidden_node(pos)
|
||||
local p = {x=pos.x, y=pos.y + 1, z=pos.z}
|
||||
local node = minetest.get_node(p)
|
||||
if node.name == "3d_armor_stand:top" then
|
||||
minetest.remove_node(p)
|
||||
end
|
||||
end
|
||||
|
||||
minetest.register_node("3d_armor_stand:top", {
|
||||
description = S("Armor Stand Top"),
|
||||
paramtype = "light",
|
||||
drawtype = "plantlike",
|
||||
sunlight_propagates = true,
|
||||
walkable = true,
|
||||
pointable = false,
|
||||
diggable = false,
|
||||
buildable_to = false,
|
||||
drop = "",
|
||||
groups = {not_in_creative_inventory = 1},
|
||||
is_ground_content = false,
|
||||
on_blast = function() end,
|
||||
tiles = {"blank.png"},
|
||||
})
|
||||
|
||||
minetest.register_node("3d_armor_stand:armor_stand", {
|
||||
description = S("Armor Stand"),
|
||||
drawtype = "mesh",
|
||||
mesh = "3d_armor_stand.obj",
|
||||
tiles = {"3d_armor_stand.png"},
|
||||
use_texture_alpha = "clip",
|
||||
paramtype = "light",
|
||||
paramtype2 = "facedir",
|
||||
walkable = false,
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{-0.25, -0.4375, -0.25, 0.25, 1.4, 0.25},
|
||||
{-0.5, -0.5, -0.5, 0.5, -0.4375, 0.5},
|
||||
},
|
||||
},
|
||||
groups = {choppy=2, oddly_breakable_by_hand=2},
|
||||
is_ground_content = false,
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
on_construct = function(pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("formspec", armor_stand_formspec)
|
||||
meta:set_string("infotext", S("Armor Stand"))
|
||||
local inv = meta:get_inventory()
|
||||
for _, element in pairs(elements) do
|
||||
inv:set_size("armor_"..element, 1)
|
||||
end
|
||||
end,
|
||||
can_dig = function(pos, player)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
for _, element in pairs(elements) do
|
||||
if not inv:is_empty("armor_"..element) then
|
||||
return false
|
||||
end
|
||||
end
|
||||
return true
|
||||
end,
|
||||
after_place_node = function(pos, placer)
|
||||
minetest.add_entity(pos, "3d_armor_stand:armor_entity")
|
||||
add_hidden_node(pos, placer)
|
||||
end,
|
||||
allow_metadata_inventory_put = function(pos, listname, index, stack)
|
||||
local def = stack:get_definition() or {}
|
||||
local groups = def.groups or {}
|
||||
if groups[listname] then
|
||||
return 1
|
||||
end
|
||||
return 0
|
||||
end,
|
||||
allow_metadata_inventory_move = function(pos)
|
||||
return 0
|
||||
end,
|
||||
on_metadata_inventory_put = function(pos)
|
||||
update_entity(pos)
|
||||
end,
|
||||
on_metadata_inventory_take = function(pos)
|
||||
update_entity(pos)
|
||||
end,
|
||||
after_destruct = function(pos)
|
||||
update_entity(pos)
|
||||
remove_hidden_node(pos)
|
||||
end,
|
||||
on_blast = function(pos)
|
||||
drop_armor(pos)
|
||||
armor.drop_armor(pos, "3d_armor_stand:armor_stand")
|
||||
minetest.remove_node(pos)
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_node("3d_armor_stand:locked_armor_stand", {
|
||||
description = S("Locked Armor Stand"),
|
||||
drawtype = "mesh",
|
||||
mesh = "3d_armor_stand.obj",
|
||||
tiles = {"3d_armor_stand_locked.png"},
|
||||
use_texture_alpha = "clip",
|
||||
paramtype = "light",
|
||||
paramtype2 = "facedir",
|
||||
walkable = false,
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{-0.25, -0.4375, -0.25, 0.25, 1.4, 0.25},
|
||||
{-0.5, -0.5, -0.5, 0.5, -0.4375, 0.5},
|
||||
},
|
||||
},
|
||||
groups = {choppy=2, oddly_breakable_by_hand=2},
|
||||
is_ground_content = false,
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
on_construct = function(pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("formspec", armor_stand_formspec)
|
||||
meta:set_string("infotext", S("Armor Stand"))
|
||||
meta:set_string("owner", "")
|
||||
local inv = meta:get_inventory()
|
||||
for _, element in pairs(elements) do
|
||||
inv:set_size("armor_"..element, 1)
|
||||
end
|
||||
end,
|
||||
can_dig = function(pos, player)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
for _, element in pairs(elements) do
|
||||
if not inv:is_empty("armor_"..element) then
|
||||
return false
|
||||
end
|
||||
end
|
||||
return true
|
||||
end,
|
||||
after_place_node = function(pos, placer)
|
||||
minetest.add_entity(pos, "3d_armor_stand:armor_entity")
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("owner", placer:get_player_name() or "")
|
||||
meta:set_string("infotext", S("Armor Stand (owned by @1)", meta:get_string("owner")))
|
||||
add_hidden_node(pos, placer)
|
||||
end,
|
||||
allow_metadata_inventory_put = function(pos, listname, index, stack, player)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if not has_locked_armor_stand_privilege(meta, player) then
|
||||
return 0
|
||||
end
|
||||
local def = stack:get_definition() or {}
|
||||
local groups = def.groups or {}
|
||||
if groups[listname] then
|
||||
return 1
|
||||
end
|
||||
return 0
|
||||
end,
|
||||
allow_metadata_inventory_take = function(pos, listname, index, stack, player)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if not has_locked_armor_stand_privilege(meta, player) then
|
||||
return 0
|
||||
end
|
||||
return stack:get_count()
|
||||
end,
|
||||
allow_metadata_inventory_move = function(pos)
|
||||
return 0
|
||||
end,
|
||||
on_metadata_inventory_put = function(pos)
|
||||
update_entity(pos)
|
||||
end,
|
||||
on_metadata_inventory_take = function(pos)
|
||||
update_entity(pos)
|
||||
end,
|
||||
after_destruct = function(pos)
|
||||
update_entity(pos)
|
||||
remove_hidden_node(pos)
|
||||
end,
|
||||
on_blast = function(pos)
|
||||
-- Not affected by TNT
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_node("3d_armor_stand:shared_armor_stand", {
|
||||
description = S("Shared Armor Stand"),
|
||||
drawtype = "mesh",
|
||||
mesh = "3d_armor_stand.obj",
|
||||
tiles = {"3d_armor_stand_shared.png"},
|
||||
use_texture_alpha = "clip",
|
||||
paramtype = "light",
|
||||
paramtype2 = "facedir",
|
||||
walkable = false,
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{-0.25, -0.4375, -0.25, 0.25, 1.4, 0.25},
|
||||
{-0.5, -0.5, -0.5, 0.5, -0.4375, 0.5},
|
||||
},
|
||||
},
|
||||
groups = {choppy=2, oddly_breakable_by_hand=2},
|
||||
is_ground_content = false,
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
on_construct = function(pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("formspec", armor_stand_formspec)
|
||||
meta:set_string("infotext", S("Shared Armor Stand"))
|
||||
local inv = meta:get_inventory()
|
||||
for _, element in pairs(elements) do
|
||||
inv:set_size("armor_"..element, 1)
|
||||
end
|
||||
end,
|
||||
can_dig = function(pos, player)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
for _, element in pairs(elements) do
|
||||
if not inv:is_empty("armor_"..element) then
|
||||
return false
|
||||
end
|
||||
end
|
||||
return true
|
||||
end,
|
||||
after_place_node = function(pos, placer)
|
||||
minetest.add_entity(pos, "3d_armor_stand:armor_entity")
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("infotext", S("Shared Armor Stand"))
|
||||
add_hidden_node(pos, placer)
|
||||
end,
|
||||
allow_metadata_inventory_put = function(pos, listname, index, stack, player)
|
||||
if not minetest.is_player(player) or minetest.is_protected(pos, player:get_player_name()) then
|
||||
return 0
|
||||
end
|
||||
local def = stack:get_definition() or {}
|
||||
local groups = def.groups or {}
|
||||
if groups[listname] then
|
||||
return 1
|
||||
end
|
||||
return 0
|
||||
end,
|
||||
allow_metadata_inventory_take = function(pos, listname, index, stack, player)
|
||||
if not minetest.is_player(player) or minetest.is_protected(pos, player:get_player_name()) then
|
||||
return 0
|
||||
end
|
||||
return stack:get_count()
|
||||
end,
|
||||
allow_metadata_inventory_move = function(pos)
|
||||
return 0
|
||||
end,
|
||||
on_metadata_inventory_put = function(pos)
|
||||
update_entity(pos)
|
||||
end,
|
||||
on_metadata_inventory_take = function(pos)
|
||||
update_entity(pos)
|
||||
end,
|
||||
after_destruct = function(pos)
|
||||
update_entity(pos)
|
||||
remove_hidden_node(pos)
|
||||
end,
|
||||
on_blast = function(pos)
|
||||
-- Not affected by TNT
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_entity("3d_armor_stand:armor_entity", {
|
||||
initial_properties = {
|
||||
physical = true,
|
||||
visual = "mesh",
|
||||
mesh = "3d_armor_entity.obj",
|
||||
visual_size = {x=1, y=1},
|
||||
collisionbox = {0,0,0,0,0,0},
|
||||
textures = {"blank.png"},
|
||||
},
|
||||
_pos = nil,
|
||||
on_activate = function(self)
|
||||
local pos = self.object:get_pos()
|
||||
if pos then
|
||||
self._pos = vector.round(pos)
|
||||
update_entity(pos)
|
||||
end
|
||||
end,
|
||||
on_blast = function(self, damage)
|
||||
local drops = {}
|
||||
local node = minetest.get_node(self._pos)
|
||||
if node.name == "3d_armor_stand:armor_stand" then
|
||||
drop_armor(self._pos)
|
||||
self.object:remove()
|
||||
end
|
||||
return false, false, drops
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_abm({
|
||||
nodenames = {"3d_armor_stand:locked_armor_stand", "3d_armor_stand:shared_armor_stand", "3d_armor_stand:armor_stand"},
|
||||
interval = 15,
|
||||
chance = 1,
|
||||
action = function(pos, node, active_object_count, active_object_count_wider)
|
||||
local num
|
||||
num = #minetest.get_objects_inside_radius(pos, 0.5)
|
||||
if num > 0 then return end
|
||||
update_entity(pos)
|
||||
end
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "3d_armor_stand:armor_stand",
|
||||
recipe = {
|
||||
{"", "group:fence", ""},
|
||||
{"", "group:fence", ""},
|
||||
{"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"},
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "3d_armor_stand:locked_armor_stand",
|
||||
recipe = {
|
||||
{"3d_armor_stand:armor_stand", "default:steel_ingot"},
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "3d_armor_stand:shared_armor_stand",
|
||||
recipe = {
|
||||
{"3d_armor_stand:armor_stand", "default:copper_ingot"},
|
||||
}
|
||||
})
|
||||
|
||||
minetest.log("action", "[3d_armor_stand] loaded.")
|
5
3d_armor_stand/locale/3d_armor_stand.de.tr
Normal file
@ -0,0 +1,5 @@
|
||||
# textdomain: 3d_armor_stand
|
||||
Armor Stand Top=Rüstungsständeroberseite
|
||||
Armor Stand=Rüstungsständer
|
||||
Locked Armor Stand=Abgeschlossener Rüstungsständer
|
||||
Armor Stand (owned by @1)=Rüstungsständer (Eigentum von @1)
|
5
3d_armor_stand/locale/3d_armor_stand.eo.tr
Normal file
@ -0,0 +1,5 @@
|
||||
# textdomain: 3d_armor_stand
|
||||
Armor Stand Top=Armaĵtenila Supro
|
||||
Armor Stand=Armaĵtenilo
|
||||
Locked Armor Stand=Ŝlosita Armaĵtenilo
|
||||
Armor Stand (owned by @1)=Ŝlosita Armaĵtenilo (posedata de @1)
|
6
3d_armor_stand/locale/3d_armor_stand.es.tr
Normal file
@ -0,0 +1,6 @@
|
||||
# textdomain: 3d_armor_stand
|
||||
Armor Stand Top=
|
||||
Armor Stand=Soporte de armadura
|
||||
Locked Armor Stand=Soporte de armadura privado
|
||||
Shared Armor Stand=Soporte de armadura compartido
|
||||
Armor Stand (owned by @1)=Soporte de armadura (de @1)
|
5
3d_armor_stand/locale/3d_armor_stand.fr.tr
Normal file
@ -0,0 +1,5 @@
|
||||
# textdomain: 3d_armor_stand
|
||||
Armor Stand Top=Haut de support d'armure
|
||||
Armor Stand=Support d'armure
|
||||
Locked Armor Stand=Support d'armure verrouillé
|
||||
Armor Stand (owned by @1)=Support d'armure (propriété de @1)
|
5
3d_armor_stand/locale/3d_armor_stand.pt_BR.tr
Normal file
@ -0,0 +1,5 @@
|
||||
# textdomain: 3d_armor_stand
|
||||
Armor Stand Top=Topo do suporte de armadura
|
||||
Armor Stand=Suporte de Armadura
|
||||
Locked Armor Stand=Suporte de armadura trancado
|
||||
Armor Stand (owned by @1)=Suporte de Armadura (dono: @1)
|
5
3d_armor_stand/locale/3d_armor_stand.ru.tr
Executable file
@ -0,0 +1,5 @@
|
||||
# textdomain: 3d_armor_stand
|
||||
Armor Stand Top=верх стойки для брони
|
||||
Armor Stand=стойка для брони
|
||||
Locked Armor Stand=стойка для брони с замком
|
||||
Armor Stand (owned by @1)=стойка для бони (владелец @1)
|
5
3d_armor_stand/locale/3d_armor_stand.sv.tr
Normal file
@ -0,0 +1,5 @@
|
||||
# textdomain: 3d_armor_stand
|
||||
Armor Stand Top=Rustningställstopp
|
||||
Armor Stand=Rustningställ
|
||||
Locked Armor Stand=Låst rustningställ
|
||||
Armor Stand (owned by @1)=Rustningställ (ägd av @1)
|
6
3d_armor_stand/locale/template.txt
Normal file
@ -0,0 +1,6 @@
|
||||
# textdomain: 3d_armor_stand
|
||||
Armor Stand Top=
|
||||
Armor Stand=
|
||||
Locked Armor Stand=
|
||||
Shared Armor Stand=
|
||||
Armor Stand (owned by @1)=
|
2
3d_armor_stand/mod.conf
Normal file
@ -0,0 +1,2 @@
|
||||
name = 3d_armor_stand
|
||||
depends = 3d_armor
|
193
3d_armor_stand/models/3d_armor_entity.obj
Normal file
@ -0,0 +1,193 @@
|
||||
# Blender v2.73 (sub 0) OBJ File: '3d_armor_entity_3.blend'
|
||||
# www.blender.org
|
||||
mtllib 3d_armor_entity.mtl
|
||||
o Player_Cube
|
||||
v 2.200000 9.763893 1.200000
|
||||
v 2.200000 9.763893 -1.200000
|
||||
v 2.200000 2.663871 1.200000
|
||||
v 2.200000 2.663871 -1.200000
|
||||
v -2.200000 9.763893 -1.200000
|
||||
v -2.200000 9.763893 1.200000
|
||||
v -2.200000 2.663871 -1.200000
|
||||
v -2.200000 2.663871 1.200000
|
||||
v 2.300000 13.863962 2.300000
|
||||
v 2.300000 13.863962 -2.300000
|
||||
v 2.300000 9.263885 2.300000
|
||||
v 2.300000 9.263885 -2.300000
|
||||
v -2.300000 13.863962 -2.300000
|
||||
v -2.300000 13.863962 2.300000
|
||||
v -2.300000 9.263885 -2.300000
|
||||
v -2.300000 9.263885 2.300000
|
||||
v -2.322686 2.473175 -1.300000
|
||||
v -2.322686 2.473175 1.300000
|
||||
v -4.713554 2.682348 1.300000
|
||||
v -4.713554 2.682348 -1.300000
|
||||
v -1.686446 9.745432 -1.300000
|
||||
v -1.686446 9.745432 1.300000
|
||||
v -4.077313 9.954605 1.300000
|
||||
v -4.077313 9.954605 -1.300000
|
||||
v 4.077313 9.954605 -1.300000
|
||||
v 4.077313 9.954605 1.300000
|
||||
v 1.686446 9.745432 1.300000
|
||||
v 1.686446 9.745432 -1.300000
|
||||
v 4.713554 2.682348 -1.300000
|
||||
v 4.713554 2.682348 1.300000
|
||||
v 2.322686 2.473175 1.300000
|
||||
v 2.322686 2.473175 -1.300000
|
||||
v 0.139099 2.938947 -1.200000
|
||||
v 0.139099 2.938947 1.200000
|
||||
v 0.261266 -4.059988 1.200000
|
||||
v 0.261266 -4.059988 -1.200000
|
||||
v 2.660901 -4.018101 1.190000
|
||||
v 2.660901 -4.018101 -1.210000
|
||||
v 2.538733 2.980834 1.190000
|
||||
v 2.538733 2.980834 -1.210000
|
||||
v -0.139099 2.938947 -1.200000
|
||||
v -0.139099 2.938947 1.200000
|
||||
v -0.261266 -4.059988 1.200000
|
||||
v -0.261266 -4.059988 -1.200000
|
||||
v -2.538734 2.980834 -1.210000
|
||||
v -2.538734 2.980834 1.190000
|
||||
v -2.660901 -4.018101 -1.210000
|
||||
v -2.660901 -4.018101 1.190000
|
||||
v -2.799999 -4.387500 1.390000
|
||||
v -2.799999 -4.387500 -1.410000
|
||||
v -2.800000 -0.812499 1.390000
|
||||
v -2.800000 -0.812499 -1.410000
|
||||
v -0.000000 -4.387500 -1.400000
|
||||
v -0.000000 -4.387500 1.400000
|
||||
v -0.000000 -0.812499 1.400000
|
||||
v -0.000000 -0.812499 -1.400000
|
||||
v 2.800000 -0.812499 -1.410000
|
||||
v 2.800000 -0.812499 1.390000
|
||||
v 2.799999 -4.387500 -1.410000
|
||||
v 2.799999 -4.387500 1.390000
|
||||
v 0.000000 -4.387500 -1.400000
|
||||
v 0.000000 -4.387500 1.400000
|
||||
v 0.000000 -0.812499 1.400000
|
||||
v 0.000000 -0.812499 -1.400000
|
||||
v 2.267006 13.830965 2.267006
|
||||
v 2.267006 13.830965 -2.267006
|
||||
v 2.267006 9.296881 2.267006
|
||||
v 2.267006 9.296881 -2.267006
|
||||
v -2.267006 13.830965 -2.267006
|
||||
v -2.267006 13.830965 2.267006
|
||||
v -2.267006 9.296881 -2.267006
|
||||
v -2.267006 9.296881 2.267006
|
||||
vt 0.250000 0.375000
|
||||
vt 0.250000 0.000000
|
||||
vt 0.312500 0.000000
|
||||
vt 0.312500 0.375000
|
||||
vt 0.437500 0.375000
|
||||
vt 0.437500 0.500000
|
||||
vt 0.312500 0.500000
|
||||
vt 0.562500 0.375000
|
||||
vt 0.562500 0.500000
|
||||
vt 0.437500 0.000000
|
||||
vt 0.500000 0.000000
|
||||
vt 0.500000 0.375000
|
||||
vt 0.625000 0.000000
|
||||
vt 0.625000 0.375000
|
||||
vt 0.500000 0.750000
|
||||
vt 0.500000 0.500000
|
||||
vt 0.625000 0.500000
|
||||
vt 0.625000 0.750000
|
||||
vt 0.750000 0.750000
|
||||
vt 0.750000 1.000000
|
||||
vt 0.625000 1.000000
|
||||
vt 0.875000 0.750000
|
||||
vt 0.875000 1.000000
|
||||
vt 0.750000 0.500000
|
||||
vt 0.875000 0.500000
|
||||
vt 1.000000 0.750000
|
||||
vt 1.000000 0.500000
|
||||
vt 0.750000 0.375000
|
||||
vt 0.812500 0.500000
|
||||
vt 0.812500 0.375000
|
||||
vt 0.687500 0.375000
|
||||
vt 0.687500 0.500000
|
||||
vt 0.687500 0.000000
|
||||
vt 0.750000 0.000000
|
||||
vt 0.812500 0.000000
|
||||
vt 0.875000 0.375000
|
||||
vt 0.875000 0.000000
|
||||
vt 0.125000 0.375000
|
||||
vt 0.062500 0.375000
|
||||
vt 0.062500 0.500000
|
||||
vt 0.125000 0.500000
|
||||
vt 0.187500 0.375000
|
||||
vt 0.187500 0.500000
|
||||
vt 0.000000 0.375000
|
||||
vt 0.000000 0.000000
|
||||
vt 0.062500 0.000000
|
||||
vt 0.187500 0.000000
|
||||
vt 0.125000 0.000000
|
||||
vt 0.437500 0.875000
|
||||
vt 0.437500 1.000000
|
||||
vt 0.375000 1.000000
|
||||
vt 0.375000 0.875000
|
||||
vt 0.250000 0.875000
|
||||
vt 0.312500 0.875000
|
||||
vt 0.312500 0.656250
|
||||
vt 0.250000 0.656250
|
||||
vt 0.500000 0.875000
|
||||
vt 0.437500 0.656250
|
||||
vt 0.500000 0.656250
|
||||
vt 0.375000 0.656250
|
||||
vt 0.312500 1.000000
|
||||
usemtl Armor
|
||||
s off
|
||||
f 1/1 3/2 4/3 2/4
|
||||
f 5/5 6/6 1/7 2/4
|
||||
f 8/6 7/5 4/8 3/9
|
||||
f 5/5 2/4 4/3 7/10
|
||||
f 7/10 8/11 6/12 5/5
|
||||
f 8/11 3/13 1/14 6/12
|
||||
f 9/15 11/16 12/17 10/18
|
||||
f 13/19 14/20 9/21 10/18
|
||||
f 12/22 11/23 16/20 15/19
|
||||
f 13/19 10/18 12/17 15/24
|
||||
f 14/22 13/19 15/24 16/25
|
||||
f 9/26 14/22 16/25 11/27
|
||||
f 17/28 18/24 19/29 20/30
|
||||
f 24/31 23/32 22/24 21/28
|
||||
f 23/31 24/14 20/13 19/33
|
||||
f 24/31 21/28 17/34 20/33
|
||||
f 21/28 22/30 18/35 17/34
|
||||
f 22/30 23/36 19/37 18/35
|
||||
f 27/30 31/35 30/37 26/36
|
||||
f 28/28 32/34 31/35 27/30
|
||||
f 25/31 29/33 32/34 28/28
|
||||
f 26/31 30/33 29/13 25/14
|
||||
f 25/31 28/28 27/24 26/32
|
||||
f 32/28 29/30 30/29 31/24
|
||||
f 40/38 33/39 34/40 39/41
|
||||
f 36/42 38/38 37/41 35/43
|
||||
f 39/44 37/45 38/46 40/39
|
||||
f 34/1 35/2 37/47 39/42
|
||||
f 40/38 38/48 36/46 33/39
|
||||
f 33/42 36/47 35/48 34/38
|
||||
f 45/38 46/41 42/40 41/39
|
||||
f 41/42 42/38 43/48 44/47
|
||||
f 45/38 41/39 44/46 47/48
|
||||
f 42/1 46/42 48/47 43/2
|
||||
f 46/44 45/39 47/46 48/45
|
||||
f 44/42 43/43 48/41 47/38
|
||||
f 53/49 54/50 49/51 50/52
|
||||
f 51/53 52/54 50/55 49/56
|
||||
f 55/57 51/49 49/58 54/59
|
||||
f 52/52 56/54 53/55 50/60
|
||||
f 56/49 55/52 54/60 53/58
|
||||
f 52/52 51/51 55/61 56/54
|
||||
f 64/49 61/58 62/60 63/52
|
||||
f 57/52 59/60 61/55 64/54
|
||||
f 63/57 62/59 60/58 58/49
|
||||
f 58/53 60/56 59/55 57/54
|
||||
f 61/49 59/52 60/51 62/50
|
||||
f 57/52 64/54 63/61 58/51
|
||||
f 65/15 66/18 68/17 67/16
|
||||
f 69/19 66/18 65/21 70/20
|
||||
f 68/22 71/19 72/20 67/23
|
||||
f 69/19 71/24 68/17 66/18
|
||||
f 70/22 72/25 71/24 69/19
|
||||
f 65/26 67/27 72/25 70/22
|
280
3d_armor_stand/models/3d_armor_stand.obj
Normal file
@ -0,0 +1,280 @@
|
||||
# Blender v2.72 (sub 0) OBJ File: ''
|
||||
# www.blender.org
|
||||
mtllib 3d_armor_stand.mtl
|
||||
o Armor_Stand_Player_Cube_Stand
|
||||
v 0.062500 0.125002 -0.062500
|
||||
v 0.062500 -0.437500 -0.062500
|
||||
v 0.062500 -0.437500 0.062500
|
||||
v 0.062500 0.125002 0.062500
|
||||
v -0.187500 0.250004 0.062500
|
||||
v -0.187500 0.250004 -0.062500
|
||||
v -0.250000 0.250004 -0.062500
|
||||
v -0.250000 0.250004 0.062500
|
||||
v -0.062500 -0.437500 -0.062500
|
||||
v -0.062500 -0.437500 0.062500
|
||||
v -0.187500 -0.437500 0.062500
|
||||
v -0.187500 -0.437500 -0.062500
|
||||
v -0.187500 0.125002 0.062500
|
||||
v -0.187500 0.125002 -0.062500
|
||||
v -0.187500 0.937504 0.062500
|
||||
v -0.187500 0.937504 -0.062500
|
||||
v -0.375000 0.937504 -0.062500
|
||||
v -0.375000 0.937504 0.062500
|
||||
v -0.062500 0.125002 0.062500
|
||||
v 0.187500 0.125002 -0.062500
|
||||
v 0.187500 -0.437500 -0.062500
|
||||
v -0.062500 0.125002 -0.062500
|
||||
v -0.250000 0.125007 -0.062500
|
||||
v -0.250000 0.125007 0.062500
|
||||
v 0.187500 -0.437500 0.062500
|
||||
v 0.187500 0.125002 0.062500
|
||||
v -0.062500 0.937504 0.062500
|
||||
v -0.187500 0.812504 0.062500
|
||||
v -0.062500 0.812504 0.062500
|
||||
v -0.062500 0.937504 -0.062500
|
||||
v 0.187500 0.250004 -0.062500
|
||||
v 0.187500 0.250004 0.062500
|
||||
v 0.250000 0.250004 0.062500
|
||||
v 0.250000 0.250004 -0.062500
|
||||
v 0.250000 0.125007 0.062500
|
||||
v 0.250000 0.125007 -0.062500
|
||||
v 0.187500 0.812504 0.062500
|
||||
v 0.187500 0.812504 -0.062500
|
||||
v 0.375000 0.812504 -0.062500
|
||||
v 0.375000 0.812504 0.062500
|
||||
v 0.187500 0.937504 -0.062500
|
||||
v 0.187500 0.937504 0.062500
|
||||
v 0.375000 0.937504 0.062500
|
||||
v 0.375000 0.937504 -0.062500
|
||||
v 0.062500 0.937504 -0.062500
|
||||
v 0.062500 0.937504 0.062500
|
||||
v -0.062500 0.812504 -0.062500
|
||||
v -0.187500 0.812504 -0.062500
|
||||
v 0.062500 0.812504 -0.062500
|
||||
v 0.062500 0.812504 0.062500
|
||||
v -0.375000 0.812504 -0.062500
|
||||
v -0.375000 0.812504 0.062500
|
||||
v -0.062500 0.250004 0.062500
|
||||
v 0.062500 0.250004 0.062500
|
||||
v 0.062500 0.250004 -0.062500
|
||||
v -0.062500 0.250004 -0.062500
|
||||
v -0.062500 1.312504 -0.062500
|
||||
v 0.062500 1.312504 -0.062500
|
||||
v -0.062500 1.312504 0.062500
|
||||
v 0.062500 1.312504 0.062500
|
||||
v -0.500000 -0.437500 -0.500000
|
||||
v -0.500000 -0.437500 0.500000
|
||||
v 0.500000 -0.437500 0.500000
|
||||
v 0.500000 -0.437500 -0.500000
|
||||
v -0.500000 -0.500000 -0.500000
|
||||
v 0.500000 -0.500000 -0.500000
|
||||
v 0.500000 -0.500000 0.500000
|
||||
v -0.500000 -0.500000 0.500000
|
||||
vt 0.062500 0.140625
|
||||
vt 0.062500 0.000000
|
||||
vt 0.093750 0.000000
|
||||
vt 0.093750 0.140625
|
||||
vt 0.140625 0.234375
|
||||
vt 0.140625 0.203125
|
||||
vt 0.156250 0.203125
|
||||
vt 0.156250 0.234375
|
||||
vt 0.093750 0.171875
|
||||
vt 0.062500 0.171875
|
||||
vt 0.218750 0.140625
|
||||
vt 0.187500 0.140625
|
||||
vt 0.187500 0.000000
|
||||
vt 0.218750 0.000000
|
||||
vt 0.078125 0.437500
|
||||
vt 0.078125 0.468750
|
||||
vt 0.031250 0.468750
|
||||
vt 0.031250 0.437500
|
||||
vt 0.250000 0.140625
|
||||
vt 0.250000 0.000000
|
||||
vt 0.031250 0.140625
|
||||
vt 0.031250 0.000000
|
||||
vt 0.156250 0.140625
|
||||
vt 0.156250 0.000000
|
||||
vt 0.187500 0.203125
|
||||
vt 0.156250 0.171875
|
||||
vt 0.187500 0.171875
|
||||
vt 0.125000 0.000000
|
||||
vt 0.125000 0.140625
|
||||
vt 0.000000 0.140625
|
||||
vt 0.000000 0.000000
|
||||
vt 0.328125 0.437500
|
||||
vt 0.296875 0.437500
|
||||
vt 0.296875 0.406250
|
||||
vt 0.328125 0.406250
|
||||
vt 0.109375 0.437500
|
||||
vt 0.109375 0.468750
|
||||
vt 0.046875 0.203125
|
||||
vt 0.046875 0.234375
|
||||
vt 0.031250 0.234375
|
||||
vt 0.031250 0.203125
|
||||
vt 0.000000 0.203125
|
||||
vt 0.000000 0.171875
|
||||
vt 0.031250 0.171875
|
||||
vt 0.265625 0.468750
|
||||
vt 0.265625 0.437500
|
||||
vt 0.218750 0.437500
|
||||
vt 0.218750 0.468750
|
||||
vt 0.218750 0.171875
|
||||
vt 0.171875 0.468750
|
||||
vt 0.171875 0.437500
|
||||
vt 0.078125 0.406250
|
||||
vt 0.031250 0.406250
|
||||
vt 0.140625 0.468750
|
||||
vt 0.140625 0.437500
|
||||
vt 0.140625 0.406250
|
||||
vt 0.171875 0.406250
|
||||
vt 0.109375 0.406250
|
||||
vt 0.359375 0.437500
|
||||
vt 0.359375 0.406250
|
||||
vt 0.390625 0.406250
|
||||
vt 0.390625 0.437500
|
||||
vt 0.437500 0.406250
|
||||
vt 0.437500 0.437500
|
||||
vt 0.000000 0.437500
|
||||
vt 0.000000 0.406250
|
||||
vt 0.250000 0.437500
|
||||
vt 0.218750 0.406250
|
||||
vt 0.250000 0.406250
|
||||
vt 0.359375 0.468750
|
||||
vt 0.406250 0.468750
|
||||
vt 0.406250 0.437500
|
||||
vt 0.109375 0.234375
|
||||
vt 0.078125 0.234375
|
||||
vt 0.078125 0.203125
|
||||
vt 0.109375 0.203125
|
||||
vt 0.062500 0.468750
|
||||
vt 0.062500 0.562500
|
||||
vt 0.031250 0.562500
|
||||
vt 0.328125 0.468750
|
||||
vt 0.296875 0.468750
|
||||
vt 0.062500 0.593750
|
||||
vt 0.031250 0.593750
|
||||
vt 0.093750 0.468750
|
||||
vt 0.093750 0.562500
|
||||
vt 0.125000 0.468750
|
||||
vt 0.125000 0.562500
|
||||
vt 0.000000 0.562500
|
||||
vt 0.000000 0.468750
|
||||
vt 0.078125 0.171875
|
||||
vt 0.046875 0.171875
|
||||
vt 0.265625 0.203125
|
||||
vt 0.265625 0.171875
|
||||
vt 0.296875 0.171875
|
||||
vt 0.296875 0.203125
|
||||
vt 0.265625 0.234375
|
||||
vt 0.281250 0.234375
|
||||
vt 0.281250 0.203125
|
||||
vt 0.312500 0.171875
|
||||
vt 0.312500 0.203125
|
||||
vt 0.140625 0.171875
|
||||
vt 0.171875 0.234375
|
||||
vt 0.171875 0.203125
|
||||
vt 0.109375 0.171875
|
||||
vt 0.234375 0.203125
|
||||
vt 0.203125 0.203125
|
||||
vt 0.203125 0.171875
|
||||
vt 0.234375 0.171875
|
||||
vt 0.234375 0.234375
|
||||
vt 0.203125 0.234375
|
||||
vt 0.062500 0.375000
|
||||
vt 0.062500 0.234375
|
||||
vt 0.093750 0.234375
|
||||
vt 0.093750 0.375000
|
||||
vt 0.031250 0.375000
|
||||
vt 0.125000 0.234375
|
||||
vt 0.125000 0.375000
|
||||
vt 0.000000 0.375000
|
||||
vt 0.000000 0.234375
|
||||
vt 0.218750 0.375000
|
||||
vt 0.187500 0.375000
|
||||
vt 0.187500 0.234375
|
||||
vt 0.218750 0.234375
|
||||
vt 0.250000 0.375000
|
||||
vt 0.250000 0.234375
|
||||
vt 0.156250 0.375000
|
||||
vt 0.250000 1.000000
|
||||
vt 0.250000 0.750000
|
||||
vt 0.500000 0.750000
|
||||
vt 0.500000 1.000000
|
||||
vt 0.750000 0.750000
|
||||
vt 0.750000 1.000000
|
||||
vt 0.750000 0.734375
|
||||
vt 1.000000 0.734375
|
||||
vt 1.000000 0.750000
|
||||
vt 0.000000 0.750000
|
||||
vt 0.000000 0.734375
|
||||
vt 0.250000 0.734375
|
||||
vt 0.500000 0.734375
|
||||
usemtl Stand
|
||||
s off
|
||||
f 1/1 2/2 3/3 4/4
|
||||
f 5/5 6/6 7/7 8/8
|
||||
f 9/1 10/4 11/9 12/10
|
||||
f 13/11 14/12 12/13 11/14
|
||||
f 15/15 16/16 17/17 18/18
|
||||
f 19/19 13/11 11/14 10/20
|
||||
f 2/2 1/1 20/21 21/22
|
||||
f 14/12 22/23 9/24 12/13
|
||||
f 8/25 7/7 23/26 24/27
|
||||
f 4/4 3/3 25/28 26/29
|
||||
f 22/23 19/29 10/28 9/24
|
||||
f 26/30 25/31 21/22 20/21
|
||||
f 27/32 15/33 28/34 29/35
|
||||
f 16/16 15/15 27/36 30/37
|
||||
f 31/38 32/39 33/40 34/41
|
||||
f 33/42 35/43 36/44 34/41
|
||||
f 37/45 38/46 39/47 40/48
|
||||
f 2/49 21/27 25/12 3/11
|
||||
f 41/50 42/51 43/47 44/48
|
||||
f 38/52 41/15 44/18 39/53
|
||||
f 41/50 45/54 46/55 42/51
|
||||
f 16/51 30/55 47/56 48/57
|
||||
f 41/15 38/52 49/58 45/36
|
||||
f 46/59 50/60 37/61 42/62
|
||||
f 42/62 37/61 40/63 43/64
|
||||
f 43/65 40/66 39/53 44/18
|
||||
f 18/67 17/47 51/68 52/69
|
||||
f 28/34 15/33 18/67 52/69
|
||||
f 16/51 48/57 51/68 17/47
|
||||
f 48/59 28/70 52/71 51/72
|
||||
f 53/73 54/74 55/75 56/76
|
||||
f 30/77 57/78 58/79 45/17
|
||||
f 50/60 46/59 27/32 29/35
|
||||
f 29/80 47/32 49/33 50/81
|
||||
f 47/56 30/55 45/36 49/58
|
||||
f 57/78 59/82 60/83 58/79
|
||||
f 27/84 59/85 57/78 30/77
|
||||
f 46/86 60/87 59/85 27/84
|
||||
f 45/17 58/79 60/88 46/89
|
||||
f 1/90 55/75 31/38 20/91
|
||||
f 54/92 4/93 26/94 32/95
|
||||
f 26/92 20/96 36/97 35/98
|
||||
f 20/91 31/38 34/41 36/44
|
||||
f 32/95 26/94 35/99 33/100
|
||||
f 6/6 14/101 23/26 7/7
|
||||
f 14/102 13/103 24/7 23/8
|
||||
f 6/6 56/76 22/104 14/101
|
||||
f 53/105 5/106 13/107 19/108
|
||||
f 13/107 5/106 8/25 24/27
|
||||
f 1/90 22/104 56/76 55/75
|
||||
f 53/105 19/108 4/93 54/92
|
||||
f 1/109 4/105 19/106 22/110
|
||||
f 49/111 55/112 54/113 50/114
|
||||
f 38/115 31/40 55/112 49/111
|
||||
f 50/114 54/113 32/116 37/117
|
||||
f 37/118 32/119 31/40 38/115
|
||||
f 28/120 48/121 6/122 5/123
|
||||
f 29/124 28/120 5/123 53/125
|
||||
f 48/121 47/126 56/8 6/122
|
||||
f 47/126 29/117 53/116 56/8
|
||||
usemtl Base
|
||||
f 61/127 62/128 63/129 64/130
|
||||
f 65/129 66/131 67/132 68/130
|
||||
f 62/131 68/133 67/134 63/135
|
||||
f 63/136 67/137 66/138 64/128
|
||||
f 61/129 64/128 66/138 65/139
|
||||
f 62/131 61/129 65/139 68/133
|
BIN
3d_armor_stand/models/3d_armor_stand.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
3d_armor_stand/models/3d_armor_stand_locked.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
3d_armor_stand/models/3d_armor_stand_shared.png
Normal file
After Width: | Height: | Size: 1011 B |
BIN
3d_armor_stand/textures/3d_armor_stand_feet.png
Normal file
After Width: | Height: | Size: 160 B |
BIN
3d_armor_stand/textures/3d_armor_stand_head.png
Normal file
After Width: | Height: | Size: 164 B |
BIN
3d_armor_stand/textures/3d_armor_stand_legs.png
Normal file
After Width: | Height: | Size: 159 B |