forked from VoxeLibre/VoxeLibre
Compare commits
294 Commits
Author | SHA1 | Date |
---|---|---|
epCode | ce49cd02ac | |
kay27 | 40c733c913 | |
kay27 | a76fe2b487 | |
kay27 | b14ca5a843 | |
epCode | 3ff214ec2d | |
epCode | f6db31eae3 | |
Lizzy Fleckenstein | 9ba1917209 | |
kay27 | ea41c82834 | |
Lizzy Fleckenstein | 2116b2b9d0 | |
epCode | 08b7340ff5 | |
kay27 | 7a8079bb64 | |
NO11 | cdd12a0c71 | |
NO11 | 652f8d48ed | |
NO11 | 988f298375 | |
NO11 | c73cd8b810 | |
NO11 | ebd4380c98 | |
NO11 | 3d732c2412 | |
NO11 | 03e112ef9b | |
NO11 | 9b81a4d83e | |
NO11 | cbcaef19c6 | |
NO11 | 9e5fb7f533 | |
epCode | 849823af1f | |
kay27 | d50fd06c82 | |
kay27 | 3375e903ce | |
AFCMS | f5f6e232cc | |
Lizzy Fleckenstein | c6ffccfef5 | |
Lizzy Fleckenstein | cbd2731e06 | |
kay27 | a733eb8e0c | |
Nils Dagsson Moskopp | 7c8cf6f79f | |
kay27 | f0c2eb86a2 | |
kay27 | 26ce10d25c | |
kay27 | 6b31e85385 | |
jordan4ibanez | 6279f5eb41 | |
jordan4ibanez | 9789cf5dcd | |
jordan4ibanez | 26847bbb54 | |
jordan4ibanez | 4fca50dead | |
jordan4ibanez | 310dcf9660 | |
jordan4ibanez | ba9866db49 | |
jordan4ibanez | 282ba2614a | |
jordan4ibanez | 26ef8c2674 | |
jordan4ibanez | f5cc2bab09 | |
jordan4ibanez | 71c50042e6 | |
jordan4ibanez | ae0c235c1f | |
jordan4ibanez | 668b67158c | |
jordan4ibanez | c259fc2a28 | |
jordan4ibanez | 249a3c8891 | |
jordan4ibanez | 34b66acc9d | |
jordan4ibanez | 89f35c06af | |
jordan4ibanez | cb093b774c | |
jordan4ibanez | abc68f4dc6 | |
jordan4ibanez | 38dcbcb3d4 | |
jordan4ibanez | d65a5e3be0 | |
kay27 | de41a4c26b | |
kay27 | 5e0bd2281c | |
jordan4ibanez | 346efee399 | |
jordan4ibanez | 18f73ba31f | |
jordan4ibanez | 213d24cc86 | |
jordan4ibanez | b9d175e6a5 | |
jordan4ibanez | fa95545252 | |
jordan4ibanez | 0842a36aa6 | |
iliekprogrammar | 18ee1d476a | |
iliekprogrammar | d50665d2d5 | |
AFCMS | e228c1d70b | |
iliekprogrammar | 5ccb12586d | |
iliekprogrammar | 2db0e176b3 | |
kay27 | 8e30bc8dbd | |
AFCMS | f7ddfe2891 | |
AFCMS | 11114c6847 | |
Lizzy Fleckenstein | d77affca91 | |
Lizzy Fleckenstein | 6a1a634cba | |
Lizzy Fleckenstein | 6c35ff1fc5 | |
Lizzy Fleckenstein | 567f157541 | |
Lizzy Fleckenstein | f282cd0c4d | |
Lizzy Fleckenstein | 3449b3eb7c | |
iliekprogrammar | 986ae950ec | |
iliekprogrammar | 61cef21cd1 | |
TechDudie | db9e8d23d9 | |
TechDudie | f664a87dac | |
Lizzy Fleckenstein | 6e2a7c8a7e | |
Lizzy Fleckenstein | c451866a36 | |
Lizzy Fleckenstein | 3c1a38904a | |
Lizzy Fleckenstein | b2c09c8ba0 | |
jordan4ibanez | 4f2a6b2db0 | |
jordan4ibanez | ec6eb51726 | |
jordan4ibanez | 6cdf7c98c2 | |
jordan4ibanez | 0970981252 | |
jordan4ibanez | 6c4c22e3b9 | |
jordan4ibanez | 9b1cc19718 | |
jordan4ibanez | 7cecc71b91 | |
jordan4ibanez | da057ee9e8 | |
jordan4ibanez | 6aaf25bbc9 | |
jordan4ibanez | 7826311175 | |
jordan4ibanez | 4a1faa44de | |
jordan4ibanez | 8ab9de74dc | |
jordan4ibanez | acd2b8e691 | |
jordan4ibanez | 21334bc49d | |
jordan4ibanez | 56f94af6ce | |
jordan4ibanez | 9f7899c01a | |
jordan4ibanez | 4ec3fd0ba6 | |
jordan4ibanez | 00db03320b | |
kay27 | 069e089ae4 | |
Lizzy Fleckenstein | 430f958fae | |
Lizzy Fleckenstein | f65c40f805 | |
jordan4ibanez | 9e1b662c03 | |
jordan4ibanez | 8e2493dd9a | |
Elias Fleckenstein | 89a9b16465 | |
Lizzy Fleckenstein | ea08fee9ba | |
Lizzy Fleckenstein | 3c73ad3b98 | |
Lizzy Fleckenstein | 91e2372df0 | |
Elias Fleckenstein | 058c6ef9f4 | |
Lizzy Fleckenstein | 38a12e59da | |
Lizzy Fleckenstein | 1d587b8895 | |
Lizzy Fleckenstein | 83b9cf3ad2 | |
Doloment | 31a7a4fbb6 | |
Lizzy Fleckenstein | 962a13847e | |
Lizzy Fleckenstein | f350fa6272 | |
Doloment | 055c406d7a | |
Lizzy Fleckenstein | a348909ba3 | |
Lizzy Fleckenstein | 5bdb3bc274 | |
Lizzy Fleckenstein | ba15f01ca9 | |
Lizzy Fleckenstein | c93a865098 | |
Lizzy Fleckenstein | d07e415b37 | |
Lizzy Fleckenstein | 175cb44fb1 | |
AFCMS | 91da727184 | |
AFCMS | 339e3e2792 | |
kay27 | beb2484224 | |
AFCMS | 28402ca663 | |
Lizzy Fleckenstein | e407ad2254 | |
Elias Fleckenstein | b1c4476a04 | |
kay27 | b1f27dba6a | |
kay27 | 4bc93040d5 | |
kay27 | 5fc3bb11ef | |
ztianyang | 1e1d31b57b | |
epCode | a6f0ad13a0 | |
epCode | 93684baa86 | |
Tianyang Zhang | 8bb8a0e3b2 | |
Saku Laesvuori | c5e1734c1c | |
Lizzy Fleckenstein | 90f312f772 | |
Lizzy Fleckenstein | 1144006cdd | |
kay27 | f54f4ebcf9 | |
Lizzy Fleckenstein | 598692cf8c | |
Lizzy Fleckenstein | ff538d51bd | |
Lizzy Fleckenstein | 49446bbb7b | |
Saku Laesvuori | 4a085c9526 | |
epCode | ac87e0604e | |
jordan4ibanez | f8229def5e | |
jordan4ibanez | 90fd65ac66 | |
epCode | 40b07e466b | |
jordan4ibanez | 0b0a180343 | |
jordan4ibanez | 1b511936f5 | |
jordan4ibanez | 441ce5522a | |
jordan4ibanez | a807ee6372 | |
jordan4ibanez | f1863baedc | |
jordan4ibanez | 0641f09915 | |
jordan4ibanez | bb6cce06e5 | |
jordan4ibanez | c572db92aa | |
jordan4ibanez | b14bc21829 | |
jordan4ibanez | 269ed6b3eb | |
jordan4ibanez | da3d5025a8 | |
jordan4ibanez | 43c47bbe0f | |
jordan4ibanez | 844db8aa7b | |
jordan4ibanez | 22cbfa32de | |
jordan4ibanez | 0840ad98a2 | |
jordan4ibanez | ea54936d28 | |
jordan4ibanez | 1cbd3a998d | |
jordan4ibanez | 61e812e40a | |
jordan4ibanez | b83b4c55fa | |
jordan4ibanez | 18d7be4a4f | |
AFCMS | b68c4b07c1 | |
AFCMS | ca01b3641b | |
AFCMS | 0db47dbf02 | |
AFCMS | 59d687c579 | |
AFCMS | c457c4ce3c | |
AFCMS | ead33e3520 | |
AFCMS | e20e0fab71 | |
AFCMS | 695ad9120b | |
AFCMS | 0da8339352 | |
NO11 | 39aaf0f21f | |
AFCMS | c0fcbffd70 | |
AFCMS | cbc1052f6b | |
jordan4ibanez | 5f361cde29 | |
jordan4ibanez | 1e3676c391 | |
kay27 | fd51910b89 | |
jordan4ibanez | 2f272b3dff | |
epCode | 0dbe66f3b4 | |
AFCMS | 15803fddc2 | |
epCode | 5356e97b77 | |
AFCMS | 626990adeb | |
iliekprogrammar | c44054b51c | |
iliekprogrammar | 9885f36c62 | |
iliekprogrammar | bfff643ff4 | |
iliekprogrammar | ccea673dcc | |
iliekprogrammar | 08e280d9b4 | |
iliekprogrammar | 52c788f197 | |
iliekprogrammar | 089d6aa5c8 | |
iliekprogrammar | 9518086b6b | |
AFCMS | 0740854b5d | |
epCode | 86b63c8bc4 | |
epCode | 38e4e7293a | |
epCode | 97424f7d0a | |
epCode | a14959ac70 | |
AFCMS | 3b8916ef65 | |
AFCMS | a040355dce | |
AFCMS | d4e0d4d1c1 | |
AFCMS | c35dab1d08 | |
AFCMS | 613779a851 | |
AFCMS | 59c13b6df8 | |
AFCMS | 857a0c5565 | |
AFCMS | 41a8cd0e15 | |
AFCMS | 7a5c2d617b | |
AFCMS | 369c8b9b8a | |
AFCMS | 7ec7012572 | |
AFCMS | c70ea7c843 | |
AFCMS | f60941003d | |
AFCMS | 3a514ecdad | |
AFCMS | 600e8bede2 | |
AFCMS | 84819bf9f5 | |
AFCMS | f8a627915e | |
AFCMS | a2fcd28a3d | |
AFCMS | f51deb0737 | |
epCode | 5a7d128861 | |
Elias Fleckenstein | 68d49a43b2 | |
ArTee3 | 1b9737b431 | |
iliekprogrammar | ecdbc30b63 | |
kay27 | d1a0299b92 | |
kay27 | 80d845adb6 | |
kay27 | 2e3a5efaf9 | |
kay27 | b587b1f2a5 | |
kay27 | 1818fcf592 | |
kay27 | bbd52043f1 | |
kay27 | 05260d03d5 | |
kay27 | cb2aae5a55 | |
AFCMS | d07cf64d11 | |
AFCMS | 5a4355b859 | |
kay27 | 628ca226a6 | |
iliekprogrammar | 24da94ec3b | |
iliekprogrammar | e76a0ba6e8 | |
AFCMS | c7389dc0a4 | |
AFCMS | 890a569b13 | |
kay27 | 54e7529754 | |
AFCMS | cdb67d96a6 | |
AFCMS | 6f9c1856b8 | |
AFCMS | e56d9d2ab8 | |
AFCMS | 52939ff6a4 | |
AFCMS | 39ac3f208d | |
AFCMS | 2a5dcd1634 | |
AFCMS | 19db2a479f | |
AFCMS | fb50b256ed | |
AFCMS | ce123d4676 | |
AFCMS | 57ce5143b9 | |
AFCMS | 3ba7a40251 | |
AFCMS | 6a6b5970b3 | |
AFCMS | 30e50a64ef | |
AFCMS | cb294a5cad | |
AFCMS | 9bb5e748b9 | |
AFCMS | 61c9d065fb | |
AFCMS | e2fd0823b9 | |
AFCMS | 826d60e16e | |
AFCMS | e2adead700 | |
AFCMS | e11941c107 | |
AFCMS | e3c99c5be2 | |
AFCMS | 202e30a782 | |
AFCMS | 50bdf03189 | |
AFCMS | 8c002671c0 | |
Lizzy Fleckenstein | 0372057fe3 | |
Lizzy Fleckenstein | 6f8d0d4de0 | |
AFCMS | 9c8ec7d4ec | |
AFCMS | 041300cde4 | |
AFCMS | 88fc515cff | |
AFCMS | 01eba30058 | |
AFCMS | 35b2bd72f8 | |
AFCMS | 41768e95a1 | |
AFCMS | c0308c7c08 | |
AFCMS | 50c35ff5e8 | |
AFCMS | 53d7134437 | |
AFCMS | 78bad87a72 | |
AFCMS | 0e5bbd6d3d | |
kay27 | 25f6a9ee23 | |
AFCMS | 8258dae1b8 | |
AFCMS | e4a6244fdd | |
AFCMS | b9301f12ce | |
AFCMS | 86a18802dc | |
Lizzy Fleckenstein | 97991d138c | |
Code-Sploit | 630e7e8acb | |
Lizzy Fleckenstein | d555fce8bc | |
Code-Sploit | 322578df6a | |
epCode | dbc6dd8cb3 | |
Lizzy Fleckenstein | 46c6328432 | |
Lizzy Fleckenstein | 43a60e0c57 | |
Lizzy Fleckenstein | a47eda44e9 | |
Lizzy Fleckenstein | fe937665f9 | |
iliekprogrammar | ca635b69be | |
iliekprogrammar | ebf9f8c918 | |
iliekprogrammar | 23f69dfd1e |
|
@ -1,5 +1,8 @@
|
|||
# This is a game specific minetest.conf file, do not edit
|
||||
|
||||
# If any of these settings are set in your minetest.conf file in ~/.minetest (Linux) or in the root directory of the game (Run in place/Windows)
|
||||
# They will override these settings
|
||||
|
||||
# Basic game rules
|
||||
time_speed = 72
|
||||
|
||||
|
@ -33,7 +36,7 @@ mgvalleys_spflags = noaltitude_chill,noaltitude_dry,nohumid_rivers,vary_river_de
|
|||
keepInventory = false
|
||||
|
||||
# Performance settings
|
||||
# dedicated_server_step = 0.001
|
||||
dedicated_server_step = 0.05 #tick rate
|
||||
# abm_interval = 0.25
|
||||
# max_objects_per_block = 4096
|
||||
# max_packets_per_iteration = 10096
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
# controls
|
||||
|
||||
## controls.players
|
||||
Table containing player controls at runtime.
|
||||
WARNING: Never use this table in writing
|
||||
|
||||
## controls.register_on_press(func)
|
||||
Register a function that will be executed with (player, keyname) every time a player press a key.
|
||||
|
||||
## controls.registered_on_press
|
||||
Table containing functions registered with controls.register_on_press().
|
||||
|
||||
## controls.register_on_release(func)
|
||||
Register a function that will be executed with (player, keyname, clock_from_last_press) every time a player release a key.
|
||||
|
||||
## controls.registered_on_release
|
||||
Table containing functions registered with controls.register_on_release().
|
||||
|
||||
## controls.register_on_hold(func)
|
||||
Register a function that will be executed with (player, keyname, clock_from_start_hold) every time a player hold a key.
|
||||
|
||||
## controls.registered_on_hold
|
||||
Table containing functions registered with controls.register_on_hold().
|
|
@ -0,0 +1,45 @@
|
|||
# flowlib
|
||||
Simple flow functions.
|
||||
|
||||
## flowlib.is_touching(realpos, nodepos, radius)
|
||||
Return true if a sphere of <radius> at <realpos> collide with node at <nodepos>.
|
||||
* realpos: position
|
||||
* nodepos: position
|
||||
* radius: number
|
||||
|
||||
## flowlib.is_water(pos)
|
||||
Return true if node at <pos> is water, false overwise.
|
||||
* pos: position
|
||||
|
||||
## flowlib.node_is_water(node)
|
||||
Return true if <node> is water, false overwise.
|
||||
* node: node
|
||||
|
||||
## flowlib.is_lava(pos)
|
||||
Return true if node at <pos> is lava, false overwise.
|
||||
* pos: position
|
||||
|
||||
## flowlib.node_is_lava(node)
|
||||
Return true if <node> is lava, false overwise.
|
||||
* node: node
|
||||
|
||||
## flowlib.is_liquid(pos)
|
||||
Return true if node at <pos> is liquid, false overwise.
|
||||
* pos: position
|
||||
|
||||
## flowlib.node_is_liquid(node)
|
||||
Return true if <node> is liquid, false overwise.
|
||||
* node: node
|
||||
|
||||
## flowlib.quick_flow(pos, node)
|
||||
Return direction where the water is flowing (to be use to push mobs, items...).
|
||||
* pos: position
|
||||
* node: node
|
||||
|
||||
## flowlib.move_centre(pos, realpos, node, radius)
|
||||
Return the pos of the nearest not water block near from <pos> in a sphere of <radius> at <realpos>.
|
||||
WARNING: This function is never used in mcl2, use at your own risk. The informations described here may be wrong.
|
||||
* pos: position
|
||||
* realpos: position, position of the entity
|
||||
* node: node
|
||||
* radius: number
|
|
@ -0,0 +1,27 @@
|
|||
# mcl_autogroup
|
||||
This mod emulate digging times from mc.
|
||||
|
||||
## mcl_autogroup.can_harvest(nodename, toolname)
|
||||
Return true if <nodename> can be dig with <toolname>.
|
||||
* nodename: string, valid nodename
|
||||
* toolname: (optional) string, valid toolname
|
||||
|
||||
## mcl_autogroup.get_groupcaps(toolname, efficiency)
|
||||
This function is used to calculate diggroups for tools.
|
||||
WARNING: This function can only be called after mod initialization.
|
||||
* toolname: string, name of the tool being enchanted (like "mcl_tools:diamond_pickaxe")
|
||||
* efficiency: (optional) integer, the efficiency level the tool is enchanted with (default 0)
|
||||
|
||||
## mcl_autogroup.get_wear(toolname, diggroup)
|
||||
Return the max wear of <toolname> with <diggroup>
|
||||
WARNING: This function can only be called after mod initialization.
|
||||
* toolname: string, name of the tool used
|
||||
* diggroup: string, the name of the diggroup the tool is used on
|
||||
|
||||
## mcl_autogroup.register_diggroup(group, def)
|
||||
* group: string, name of the group to register as a digging group
|
||||
* def: (optional) table, table with information about the diggroup (defaults to {} if unspecified)
|
||||
* level: (optional) string, if specified it is an array containing the names of the different digging levels the digging group supports
|
||||
|
||||
## mcl_autogroup.registered_diggroups
|
||||
List of registered diggroups, indexed by name.
|
|
@ -0,0 +1,8 @@
|
|||
# mcl_colors
|
||||
Mod providing global table containing legacity minecraft colors to be used in mods.
|
||||
|
||||
## mcl_colors.*
|
||||
Colors by upper name, in hex value.
|
||||
|
||||
## mcl_colors.background.*
|
||||
Background colors by upper name, in hex value.
|
|
@ -0,0 +1,15 @@
|
|||
# mcl_explosions
|
||||
This mod provide helper functions to create explosions.
|
||||
|
||||
## mcl_explosions.explode(pos, strength, info, puncher)
|
||||
* pos: position, initial position of the explosion
|
||||
* strenght: number, radius of the explosion
|
||||
* info: table, explosion informations:
|
||||
* drop_chance: number, if specified becomes the drop chance of all nodes in the explosion (default: 1.0 / strength)
|
||||
* max_blast_resistance: int, if specified the explosion will treat all non-indestructible nodes as having a blast resistance of no more than this value
|
||||
* sound: bool, if true, the explosion will play a sound (default: true)
|
||||
* particles: bool, if true, the explosion will create particles (default: true)
|
||||
* fire: bool, if true, 1/3 nodes become fire (default: false)
|
||||
* griefing: bool, if true, the explosion will destroy nodes (default: true)
|
||||
* grief_protected: bool, if true, the explosion will also destroy nodes which have been protected (default: false)
|
||||
* puncher: (optional) entity, will be used as source for damage done by the explosion
|
|
@ -21,6 +21,9 @@ mcl_vars.gui_bg_img = "background9[1,1;1,1;mcl_base_textures_background9.png;tru
|
|||
-- Legacy
|
||||
mcl_vars.inventory_header = ""
|
||||
|
||||
-- Tool wield size
|
||||
mcl_vars.tool_wield_scale = { x = 1.8, y = 1.8, z = 1 }
|
||||
|
||||
-- Mapgen variables
|
||||
local mg_name = minetest.get_mapgen_setting("mg_name")
|
||||
local minecraft_height_limit = 256
|
||||
|
@ -175,3 +178,86 @@ minetest.craftitemdef_default.stack_max = 64
|
|||
-- Set random seed for all other mods (Remember to make sure no other mod calls this function)
|
||||
math.randomseed(os.time())
|
||||
|
||||
local chunks = {} -- intervals of chunks generated
|
||||
function mcl_vars.add_chunk(pos)
|
||||
local n = mcl_vars.get_chunk_number(pos) -- unsigned int
|
||||
local prev
|
||||
for i, d in pairs(chunks) do
|
||||
if n <= d[2] then -- we've found it
|
||||
if (n == d[2]) or (n >= d[1]) then return end -- already here
|
||||
if n == d[1]-1 then -- right before:
|
||||
if prev and (prev[2] == n-1) then
|
||||
prev[2] = d[2]
|
||||
table.remove(chunks, i)
|
||||
return
|
||||
end
|
||||
d[1] = n
|
||||
return
|
||||
end
|
||||
if prev and (prev[2] == n-1) then --join to previous
|
||||
prev[2] = n
|
||||
return
|
||||
end
|
||||
table.insert(chunks, i, {n, n}) -- insert new interval before i
|
||||
return
|
||||
end
|
||||
prev = d
|
||||
end
|
||||
chunks[#chunks+1] = {n, n}
|
||||
end
|
||||
function mcl_vars.is_generated(pos)
|
||||
local n = mcl_vars.get_chunk_number(pos) -- unsigned int
|
||||
for i, d in pairs(chunks) do
|
||||
if n <= d[2] then
|
||||
return (n >= d[1])
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-- "Trivial" (actually NOT) function to just read the node and some stuff to not just return "ignore", like mt 5.4 does.
|
||||
-- p: Position, if it's wrong, {name="error"} node will return.
|
||||
-- force: optional (default: false) - Do the maximum to still read the node within us_timeout.
|
||||
-- us_timeout: optional (default: 244 = 0.000244 s = 1/80/80/80), set it at least to 3000000 to let mapgen to finish its job.
|
||||
--
|
||||
-- returns node definition, eg. {name="air"}. Unfortunately still can return {name="ignore"}.
|
||||
function mcl_vars.get_node(p, force, us_timeout)
|
||||
-- check initial circumstances
|
||||
if not p or not p.x or not p.y or not p.z then return {name="error"} end
|
||||
|
||||
-- try common way
|
||||
local node = minetest.get_node(p)
|
||||
if node.name ~= "ignore" then
|
||||
return node
|
||||
end
|
||||
|
||||
-- copy table to get sure it won't changed by other threads
|
||||
local pos = {x=p.x,y=p.y,z=p.z}
|
||||
|
||||
-- try LVM
|
||||
minetest.get_voxel_manip():read_from_map(pos, pos)
|
||||
node = minetest.get_node(pos)
|
||||
if node.name ~= "ignore" or not force then
|
||||
return node
|
||||
end
|
||||
|
||||
-- all ways failed - need to emerge (or forceload if generated)
|
||||
local us_timeout = us_timeout or 244
|
||||
if mcl_vars.is_generated(pos) then
|
||||
minetest.chat_send_all("IMPOSSIBLE! Please report this to MCL2 issue tracker!")
|
||||
minetest.forceload_block(pos)
|
||||
else
|
||||
minetest.emerge_area(pos, pos)
|
||||
end
|
||||
|
||||
local t = minetest.get_us_time()
|
||||
|
||||
node = minetest.get_node(pos)
|
||||
|
||||
while (not node or node.name == "ignore") and (minetest.get_us_time() - t < us_timeout) do
|
||||
node = minetest.get_node(pos)
|
||||
end
|
||||
|
||||
return node
|
||||
-- it still can return "ignore", LOL, even if force = true, but only after time out
|
||||
end
|
||||
|
|
|
@ -410,7 +410,7 @@ function mcl_util.get_color(colorstr)
|
|||
local mc_color = mcl_colors[colorstr:upper()]
|
||||
if mc_color then
|
||||
colorstr = mc_color
|
||||
elseif #colorstr ~= 7 or colorstr:sub(1, 1) ~= "#"then
|
||||
elseif #colorstr ~= 7 or colorstr:sub(1, 1) ~= "#" then
|
||||
return
|
||||
end
|
||||
local hex = tonumber(colorstr:sub(2, 7), 16)
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
# mcl_worlds
|
||||
This mod provides utility functions about positions and dimensions.
|
||||
|
||||
## mcl_worlds.is_in_void(pos)
|
||||
This function returns:
|
||||
|
||||
* true, true: if pos is in deep void (deadly)
|
||||
* true, false: if the pos is in void (non deadly)
|
||||
* false, false: owerwise
|
||||
|
||||
Params:
|
||||
|
||||
* pos: position
|
||||
|
||||
## mcl_worlds.y_to_layer(y)
|
||||
This function is used to calculate the minetest y layer and dimension of the given <y> minecraft layer.
|
||||
Mainly used for ore generation.
|
||||
Takes an Y coordinate as input and returns:
|
||||
|
||||
* The corresponding Minecraft layer (can be nil if void)
|
||||
* The corresponding Minecraft dimension ("overworld", "nether" or "end") or "void" if <y> is in the void
|
||||
If the Y coordinate is not located in any dimension, it will return: nil, "void"
|
||||
|
||||
Params:
|
||||
|
||||
* y: int
|
||||
|
||||
## mcl_worlds.pos_to_dimension(pos)
|
||||
This function return the Minecraft dimension of <pos> ("overworld", "nether" or "end") or "void" if <y> is in the void.
|
||||
|
||||
* pos: position
|
||||
|
||||
## mcl_worlds.layer_to_y(layer, mc_dimension)
|
||||
Takes a Minecraft layer and a “dimension” name and returns the corresponding Y coordinate for MineClone 2.
|
||||
mc_dimension can be "overworld", "nether", "end" (default: "overworld").
|
||||
|
||||
* layer: int
|
||||
* mc_dimension: string
|
||||
|
||||
## mcl_worlds.has_weather(pos)
|
||||
Returns true if <pos> can have weather, false owerwise.
|
||||
Weather can be only in the overworld.
|
||||
|
||||
* pos: position
|
||||
|
||||
## mcl_worlds.has_dust(pos)
|
||||
Returns true if <pos> can have nether dust, false owerwise.
|
||||
Nether dust can be only in the nether.
|
||||
|
||||
* pos: position
|
||||
|
||||
## mcl_worlds.compass_works(pos)
|
||||
Returns true if compasses are working at <pos>, false owerwise.
|
||||
In mc, you cant use compass in the nether and the end.
|
||||
|
||||
* pos: position
|
||||
|
||||
## mcl_worlds.compass_works(pos)
|
||||
Returns true if clock are working at <pos>, false owerwise.
|
||||
In mc, you cant use clock in the nether and the end.
|
||||
|
||||
* pos: position
|
||||
|
||||
## mcl_worlds.register_on_dimension_change(function(player, dimension))
|
||||
Register a callback function func(player, dimension).
|
||||
It will be called whenever a player changes between dimensions.
|
||||
The void counts as dimension.
|
||||
|
||||
* player: player, the player who changed the dimension
|
||||
* dimension: position, The new dimension of the player ("overworld", "nether", "end", "void").
|
||||
|
||||
|
||||
## mcl_worlds.registered_on_dimension_change
|
||||
Table containing all function registered with mcl_worlds.register_on_dimension_change()
|
||||
|
||||
## mcl_worlds.dimension_change(player, dimension)
|
||||
Notify this mod of a dimmension change of <player> to <dimension>
|
||||
|
||||
* player: player, player who changed the dimension
|
||||
* dimension: string, new dimension ("overworld", "nether", "end", "void")
|
|
@ -1,6 +1,6 @@
|
|||
local S = minetest.get_translator("mcl_boats")
|
||||
|
||||
local boat_visual_size = {x = 3, y = 3, z = 3}
|
||||
local boat_visual_size = {x = 1, y = 1, z = 1}
|
||||
local paddling_speed = 22
|
||||
local boat_y_offset = 0.35
|
||||
local boat_y_offset_ground = boat_y_offset + 0.6
|
||||
|
@ -12,9 +12,7 @@ local function is_group(pos, group)
|
|||
return minetest.get_item_group(nn, group) ~= 0
|
||||
end
|
||||
|
||||
local function is_water(pos)
|
||||
return is_group(pos, "water")
|
||||
end
|
||||
local is_water = flowlib.is_water
|
||||
|
||||
local function is_ice(pos)
|
||||
return is_group(pos, "ice")
|
||||
|
@ -247,7 +245,7 @@ function boat.on_step(self, dtime, moveresult)
|
|||
else
|
||||
local ctrl = self._passenger:get_player_control()
|
||||
if ctrl and ctrl.sneak then
|
||||
detach_player(self._passenger, true)
|
||||
detach_object(self._passenger, true)
|
||||
self._passenger = nil
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
name = mcl_boats
|
||||
author = PilzAdam
|
||||
description = Adds drivable boats.
|
||||
depends = mcl_player
|
||||
depends = mcl_player, flowlib
|
||||
optional_depends = mcl_core, doc_identifier
|
||||
|
||||
|
||||
|
|
Binary file not shown.
|
@ -167,7 +167,7 @@ function mcl_burning.set_on_fire(obj, burn_time, reason)
|
|||
hud_elem_type = "image",
|
||||
position = {x = 0.5, y = 0.5},
|
||||
scale = {x = -100, y = -100},
|
||||
text = "mcl_burning_hud_flame_animated.png",
|
||||
text = "mcl_burning_entity_flame_animated.png^[opacity:180^[verticalframe:" .. mcl_burning.animation_frames .. ":" .. 1,
|
||||
z_index = 1000,
|
||||
}) + 1
|
||||
end
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
local S = minetest.get_translator("mcl_falling_nodes")
|
||||
local dmes = minetest.get_modpath("mcl_death_messages") ~= nil
|
||||
local has_mcl_armor = minetest.get_modpath("mcl_armor")
|
||||
|
||||
local is_creative_enabled = minetest.is_creative_enabled
|
||||
|
||||
local get_falling_depth = function(self)
|
||||
if not self._startpos then
|
||||
|
@ -13,9 +16,8 @@ local deal_falling_damage = function(self, dtime)
|
|||
if minetest.get_item_group(self.node.name, "falling_node_damage") == 0 then
|
||||
return
|
||||
end
|
||||
-- Cause damage to any player it hits.
|
||||
-- Cause damage to any entity it hits.
|
||||
-- Algorithm based on MC anvils.
|
||||
-- TODO: Support smashing other objects, too.
|
||||
local pos = self.object:get_pos()
|
||||
if not self._startpos then
|
||||
-- Fallback
|
||||
|
@ -23,30 +25,39 @@ local deal_falling_damage = function(self, dtime)
|
|||
end
|
||||
local objs = minetest.get_objects_inside_radius(pos, 1)
|
||||
for _,v in ipairs(objs) do
|
||||
local hp = v:get_hp()
|
||||
if v:is_player() and hp ~= 0 then
|
||||
if not self._hit_players then
|
||||
self._hit_players = {}
|
||||
end
|
||||
if v:is_player() then
|
||||
local hp = v:get_hp()
|
||||
local name = v:get_player_name()
|
||||
local hit = false
|
||||
for _,v in ipairs(self._hit_players) do
|
||||
if name == v then
|
||||
hit = true
|
||||
if hp ~= 0 then
|
||||
if not self._hit_players then
|
||||
self._hit_players = {}
|
||||
end
|
||||
end
|
||||
if not hit then
|
||||
table.insert(self._hit_players, name)
|
||||
local way = self._startpos.y - pos.y
|
||||
local damage = (way - 1) * 2
|
||||
damage = math.min(40, math.max(0, damage))
|
||||
if damage >= 1 then
|
||||
hp = hp - damage
|
||||
if hp < 0 then
|
||||
hp = 0
|
||||
local hit = false
|
||||
for _,v in ipairs(self._hit_players) do
|
||||
if name == v then
|
||||
hit = true
|
||||
end
|
||||
if v:is_player() then
|
||||
-- TODO: Reduce damage if wearing a helmet
|
||||
end
|
||||
if not hit then
|
||||
table.insert(self._hit_players, name)
|
||||
local way = self._startpos.y - pos.y
|
||||
local damage = (way - 1) * 2
|
||||
damage = math.min(40, math.max(0, damage))
|
||||
if damage >= 1 then
|
||||
hp = hp - damage
|
||||
if hp < 0 then
|
||||
hp = 0
|
||||
end
|
||||
-- Reduce damage if wearing a helmet
|
||||
local inv = v:get_inventory()
|
||||
local helmet = inv:get_stack("armor", 2)
|
||||
if has_mcl_armor and not helmet:is_empty() then
|
||||
hp = hp/4*3
|
||||
if not is_creative_enabled(name) then
|
||||
helmet:add_wear(65535/helmet:get_definition().groups.mcl_armor_uses) --TODO: be sure damage is exactly like mc (informations are missing in the mc wiki)
|
||||
inv:set_stack("armor", 2, helmet)
|
||||
end
|
||||
end
|
||||
local msg
|
||||
if minetest.get_item_group(self.node.name, "anvil") ~= 0 then
|
||||
msg = S("@1 was smashed by a falling anvil.", v:get_player_name())
|
||||
|
@ -56,8 +67,35 @@ local deal_falling_damage = function(self, dtime)
|
|||
if dmes then
|
||||
mcl_death_messages.player_damage(v, msg)
|
||||
end
|
||||
v:set_hp(hp, { type = "punch", from = "mod" })
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
local hp = v:get_luaentity().health
|
||||
if hp and hp ~= 0 then
|
||||
if not self._hit_mobs then
|
||||
self._hit_mobs = {}
|
||||
end
|
||||
local hit = false
|
||||
for _,mob in ipairs(self._hit_mobs) do
|
||||
if v == mob then
|
||||
hit = true
|
||||
end
|
||||
end
|
||||
--TODO: reduce damage for mobs then they will be able to wear armor
|
||||
if not hit then
|
||||
table.insert(self._hit_mobs, v)
|
||||
local way = self._startpos.y - pos.y
|
||||
local damage = (way - 1) * 2
|
||||
damage = math.min(40, math.max(0, damage))
|
||||
if damage >= 1 then
|
||||
hp = hp - damage
|
||||
if hp < 0 then
|
||||
hp = 0
|
||||
end
|
||||
v:get_luaentity().health = hp
|
||||
end
|
||||
v:set_hp(hp, { type = "punch", from = "mod" })
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,10 +1,36 @@
|
|||
--these are lua locals, used for higher performance
|
||||
local minetest,math,vector,ipairs = minetest,math,vector,ipairs
|
||||
|
||||
--this is used for the player pool in the sound buffer
|
||||
local pool = {}
|
||||
|
||||
local tick = false
|
||||
|
||||
minetest.register_on_joinplayer(function(player)
|
||||
local name
|
||||
name = player:get_player_name()
|
||||
pool[name] = 0
|
||||
end)
|
||||
|
||||
minetest.register_on_leaveplayer(function(player)
|
||||
local name
|
||||
name = player:get_player_name()
|
||||
pool[name] = nil
|
||||
end)
|
||||
|
||||
|
||||
local has_awards = minetest.get_modpath("awards")
|
||||
|
||||
local mcl_item_entity = {}
|
||||
|
||||
--basic settings
|
||||
local item_drop_settings = {} --settings table
|
||||
item_drop_settings.dug_buffer = 0.65 -- the warm up period before a dug item can be collected
|
||||
item_drop_settings.age = 1.0 --how old a dropped item (_insta_collect==false) has to be before collecting
|
||||
item_drop_settings.radius_magnet = 2.0 --radius of item magnet. MUST BE LARGER THAN radius_collect!
|
||||
item_drop_settings.xp_radius_magnet = 7.25 --radius of xp magnet. MUST BE LARGER THAN radius_collect!
|
||||
item_drop_settings.radius_collect = 0.2 --radius of collection
|
||||
item_drop_settings.player_collect_height = 1.0 --added to their pos y value
|
||||
item_drop_settings.player_collect_height = 0.8 --added to their pos y value
|
||||
item_drop_settings.collection_safety = false --do this to prevent items from flying away on laggy servers
|
||||
item_drop_settings.random_item_velocity = true --this sets random item velocity if velocity is 0
|
||||
item_drop_settings.drop_single_item = false --if true, the drop control drops 1 item instead of the entire stack, and sneak+drop drops the stack
|
||||
|
@ -16,16 +42,33 @@ local get_gravity = function()
|
|||
return tonumber(minetest.settings:get("movement_gravity")) or 9.81
|
||||
end
|
||||
|
||||
local registered_pickup_achievement = {}
|
||||
|
||||
--TODO: remove limitation of 1 award per itemname
|
||||
function mcl_item_entity.register_pickup_achievement(itemname, award)
|
||||
if not has_awards then
|
||||
minetest.log("warning", "[mcl_item_entity] Trying to register pickup achievement ["..award.."] for ["..itemname.."] while awards missing")
|
||||
elseif registered_pickup_achievement[itemname] then
|
||||
minetest.log("error", "[mcl_item_entity] Trying to register already existing pickup achievement ["..award.."] for ["..itemname.."]")
|
||||
else
|
||||
registered_pickup_achievement[itemname] = award
|
||||
end
|
||||
end
|
||||
|
||||
mcl_item_entity.register_pickup_achievement("tree", "mcl:mineWood")
|
||||
mcl_item_entity.register_pickup_achievement("mcl_mobitems:blaze_rod", "mcl:blazeRod")
|
||||
mcl_item_entity.register_pickup_achievement("mcl_mobitems:leather", "mcl:killCow")
|
||||
mcl_item_entity.register_pickup_achievement("mcl_core:diamond", "mcl:diamonds")
|
||||
|
||||
local check_pickup_achievements = function(object, player)
|
||||
local itemname = ItemStack(object:get_luaentity().itemstring):get_name()
|
||||
if minetest.get_item_group(itemname, "tree") ~= 0 then
|
||||
awards.unlock(player:get_player_name(), "mcl:mineWood")
|
||||
elseif itemname == "mcl_mobitems:blaze_rod" then
|
||||
awards.unlock(player:get_player_name(), "mcl:blazeRod")
|
||||
elseif itemname == "mcl_mobitems:leather" then
|
||||
awards.unlock(player:get_player_name(), "mcl:killCow")
|
||||
elseif itemname == "mcl_core:diamond" then
|
||||
awards.unlock(player:get_player_name(), "mcl:diamonds")
|
||||
if has_awards then
|
||||
local itemname = ItemStack(object:get_luaentity().itemstring):get_name()
|
||||
local playername = player:get_player_name()
|
||||
for name,award in pairs(registered_pickup_achievement) do
|
||||
if itemname == name or minetest.get_item_group(itemname, name) ~= 0 then
|
||||
awards.unlock(playername, award)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -53,103 +96,71 @@ local disable_physics = function(object, luaentity, ignore_check, reset_movement
|
|||
end
|
||||
end
|
||||
|
||||
|
||||
minetest.register_globalstep(function(dtime)
|
||||
|
||||
tick = not tick
|
||||
|
||||
for _,player in pairs(minetest.get_connected_players()) do
|
||||
if player:get_hp() > 0 or not minetest.settings:get_bool("enable_damage") then
|
||||
|
||||
|
||||
local name = player:get_player_name()
|
||||
|
||||
local pos = player:get_pos()
|
||||
|
||||
if tick == true and pool[name] > 0 then
|
||||
minetest.sound_play("item_drop_pickup", {
|
||||
pos = pos,
|
||||
gain = 0.7,
|
||||
max_hear_distance = 16,
|
||||
pitch = math.random(70,110)/100
|
||||
})
|
||||
if pool[name] > 6 then
|
||||
pool[name] = 6
|
||||
else
|
||||
pool[name] = pool[name] - 1
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
local inv = player:get_inventory()
|
||||
local checkpos = {x=pos.x,y=pos.y + item_drop_settings.player_collect_height,z=pos.z}
|
||||
|
||||
--magnet and collection
|
||||
for _,object in pairs(minetest.get_objects_inside_radius(checkpos, item_drop_settings.xp_radius_magnet)) do
|
||||
if not object:is_player() and vector.distance(checkpos, object:get_pos()) < item_drop_settings.radius_magnet and object:get_luaentity() and object:get_luaentity().name == "__builtin:item" and object:get_luaentity()._magnet_timer and (object:get_luaentity()._insta_collect or (object:get_luaentity().age > item_drop_settings.age)) then
|
||||
object:get_luaentity()._magnet_timer = object:get_luaentity()._magnet_timer + dtime
|
||||
local collected = false
|
||||
|
||||
if object:get_luaentity()._magnet_timer >= 0 and object:get_luaentity()._magnet_timer < item_drop_settings.magnet_time and inv and inv:room_for_item("main", ItemStack(object:get_luaentity().itemstring)) then
|
||||
|
||||
-- Collection
|
||||
if vector.distance(checkpos, object:get_pos()) <= item_drop_settings.radius_collect and not object:get_luaentity()._removed then
|
||||
if not object:get_luaentity()._removed then
|
||||
-- Ignore if itemstring is not set yet
|
||||
if object:get_luaentity().itemstring ~= "" then
|
||||
inv:add_item("main", ItemStack(object:get_luaentity().itemstring))
|
||||
minetest.sound_play("item_drop_pickup", {
|
||||
pos = pos,
|
||||
max_hear_distance = 16,
|
||||
gain = 1.0,
|
||||
}, true)
|
||||
check_pickup_achievements(object, player)
|
||||
|
||||
check_pickup_achievements(object, player)
|
||||
|
||||
-- Destroy entity
|
||||
-- This just prevents this section to be run again because object:remove() doesn't remove the item immediately.
|
||||
object:get_luaentity().target = checkpos
|
||||
object:get_luaentity()._removed = true
|
||||
object:remove()
|
||||
collected = true
|
||||
|
||||
object:set_velocity({x=0,y=0,z=0})
|
||||
object:set_acceleration({x=0,y=0,z=0})
|
||||
|
||||
object:move_to(checkpos)
|
||||
|
||||
pool[name] = pool[name] + 1
|
||||
|
||||
minetest.after(0.25, function()
|
||||
--safety check
|
||||
if object and object:get_luaentity() then
|
||||
object:remove()
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
-- Magnet
|
||||
else
|
||||
|
||||
object:get_luaentity()._magnet_active = true
|
||||
object:get_luaentity()._collector_timer = 0
|
||||
|
||||
-- Move object to player
|
||||
disable_physics(object, object:get_luaentity())
|
||||
|
||||
local opos = object:get_pos()
|
||||
local vec = vector.subtract(checkpos, opos)
|
||||
vec = vector.add(opos, vector.divide(vec, 2))
|
||||
object:move_to(vec)
|
||||
|
||||
|
||||
--fix eternally falling items
|
||||
minetest.after(0, function(object)
|
||||
local lua = object:get_luaentity()
|
||||
if lua then
|
||||
object:set_acceleration({x=0, y=0, z=0})
|
||||
end
|
||||
end, object)
|
||||
|
||||
|
||||
--this is a safety to prevent items flying away on laggy servers
|
||||
if item_drop_settings.collection_safety == true then
|
||||
if object:get_luaentity().init ~= true then
|
||||
object:get_luaentity().init = true
|
||||
minetest.after(1, function(args)
|
||||
local playername = args[1]
|
||||
local player = minetest.get_player_by_name(playername)
|
||||
local object = args[2]
|
||||
local lua = object:get_luaentity()
|
||||
if player == nil or not player:is_player() or object == nil or lua == nil or lua.itemstring == nil then
|
||||
return
|
||||
end
|
||||
if inv:room_for_item("main", ItemStack(object:get_luaentity().itemstring)) then
|
||||
inv:add_item("main", ItemStack(object:get_luaentity().itemstring))
|
||||
if not object:get_luaentity()._removed then
|
||||
minetest.sound_play("item_drop_pickup", {
|
||||
pos = pos,
|
||||
max_hear_distance = 16,
|
||||
gain = 1.0,
|
||||
}, true)
|
||||
end
|
||||
check_pickup_achievements(object, player)
|
||||
object:get_luaentity()._removed = true
|
||||
object:remove()
|
||||
else
|
||||
enable_physics(object, object:get_luaentity())
|
||||
end
|
||||
end, {player:get_player_name(), object})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if not collected then
|
||||
if object:get_luaentity()._magnet_timer > 1 then
|
||||
object:get_luaentity()._magnet_timer = -item_drop_settings.magnet_time
|
||||
object:get_luaentity()._magnet_active = false
|
||||
elseif object:get_luaentity()._magnet_timer < 0 then
|
||||
object:get_luaentity()._magnet_timer = object:get_luaentity()._magnet_timer + dtime
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -209,12 +220,13 @@ local function get_fortune_drops(fortune_drops, fortune_level)
|
|||
return drop or {}
|
||||
end
|
||||
|
||||
local doTileDrops = minetest.settings:get_bool("mcl_doTileDrops", true)
|
||||
|
||||
function minetest.handle_node_drops(pos, drops, digger)
|
||||
-- NOTE: This function override allows digger to be nil.
|
||||
-- This means there is no digger. This is a special case which allows this function to be called
|
||||
-- by hand. Creative Mode is intentionally ignored in this case.
|
||||
|
||||
local doTileDrops = minetest.settings:get_bool("mcl_doTileDrops", true)
|
||||
if (digger and digger:is_player() and minetest.is_creative_enabled(digger:get_player_name())) or doTileDrops == false then
|
||||
return
|
||||
end
|
||||
|
@ -314,6 +326,10 @@ function minetest.handle_node_drops(pos, drops, digger)
|
|||
z = -z
|
||||
end
|
||||
obj:set_velocity({x=1/x, y=obj:get_velocity().y, z=1/z})
|
||||
|
||||
obj:get_luaentity().age = item_drop_settings.dug_buffer
|
||||
|
||||
obj:get_luaentity()._insta_collect = false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -380,6 +396,9 @@ minetest.register_entity(":__builtin:item", {
|
|||
-- Number of seconds this item entity has existed so far
|
||||
age = 0,
|
||||
|
||||
-- How old it has become in the collection animation
|
||||
collection_age = 0,
|
||||
|
||||
set_item = function(self, itemstring)
|
||||
self.itemstring = itemstring
|
||||
if self.itemstring == "" then
|
||||
|
@ -545,6 +564,11 @@ minetest.register_entity(":__builtin:item", {
|
|||
|
||||
on_step = function(self, dtime)
|
||||
if self._removed then
|
||||
self.object:set_properties({
|
||||
physical = false
|
||||
})
|
||||
self.object:set_velocity({x=0,y=0,z=0})
|
||||
self.object:set_acceleration({x=0,y=0,z=0})
|
||||
return
|
||||
end
|
||||
self.age = self.age + dtime
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Item_Drop_Pickup - https://freesound.org/people/benniknop/sounds/317848/ (License: CC0)
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1,5 +1,7 @@
|
|||
local S = minetest.get_translator("mcl_minecarts")
|
||||
|
||||
local has_mcl_wip = minetest.get_modpath("mcl_wip")
|
||||
|
||||
mcl_minecarts = {}
|
||||
mcl_minecarts.modpath = minetest.get_modpath("mcl_minecarts")
|
||||
mcl_minecarts.speed_max = 10
|
||||
|
@ -662,8 +664,6 @@ register_minecart(
|
|||
"mcl_minecarts_minecart_chest.png",
|
||||
{"mcl_minecarts:minecart", "mcl_chests:chest"},
|
||||
nil, nil, false)
|
||||
|
||||
mcl_wip.register_wip_item("mcl_minecarts:chest_minecart")
|
||||
|
||||
-- Minecart with Furnace
|
||||
register_minecart(
|
||||
|
@ -719,8 +719,6 @@ register_minecart(
|
|||
end, nil, false
|
||||
)
|
||||
|
||||
mcl_wip.register_wip_item("mcl_minecarts:furnace_minecart")
|
||||
|
||||
-- Minecart with Command Block
|
||||
register_minecart(
|
||||
"mcl_minecarts:command_block_minecart",
|
||||
|
@ -742,8 +740,6 @@ register_minecart(
|
|||
nil, nil, false
|
||||
)
|
||||
|
||||
mcl_wip.register_wip_item("mcl_minecarts:command_block_minecart")
|
||||
|
||||
-- Minecart with Hopper
|
||||
register_minecart(
|
||||
"mcl_minecarts:hopper_minecart",
|
||||
|
@ -762,8 +758,6 @@ register_minecart(
|
|||
nil, nil, false
|
||||
)
|
||||
|
||||
mcl_wip.register_wip_item("mcl_minecarts:hopper_minecart")
|
||||
|
||||
-- Minecart with TNT
|
||||
register_minecart(
|
||||
"mcl_minecarts:tnt_minecart",
|
||||
|
@ -824,29 +818,34 @@ minetest.register_craft({
|
|||
|
||||
-- TODO: Re-enable crafting of special minecarts when they have been implemented
|
||||
if false then
|
||||
minetest.register_craft({
|
||||
output = "mcl_minecarts:furnace_minecart",
|
||||
recipe = {
|
||||
{"mcl_furnaces:furnace"},
|
||||
{"mcl_minecarts:minecart"},
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "mcl_minecarts:furnace_minecart",
|
||||
recipe = {
|
||||
{"mcl_furnaces:furnace"},
|
||||
{"mcl_minecarts:minecart"},
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "mcl_minecarts:hopper_minecart",
|
||||
recipe = {
|
||||
{"mcl_hoppers:hopper"},
|
||||
{"mcl_minecarts:minecart"},
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "mcl_minecarts:chest_minecart",
|
||||
recipe = {
|
||||
{"mcl_chests:chest"},
|
||||
{"mcl_minecarts:minecart"},
|
||||
},
|
||||
})
|
||||
minetest.register_craft({
|
||||
output = "mcl_minecarts:hopper_minecart",
|
||||
recipe = {
|
||||
{"mcl_hoppers:hopper"},
|
||||
{"mcl_minecarts:minecart"},
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "mcl_minecarts:chest_minecart",
|
||||
recipe = {
|
||||
{"mcl_chests:chest"},
|
||||
{"mcl_minecarts:minecart"},
|
||||
},
|
||||
})
|
||||
end
|
||||
|
||||
if has_mcl_wip then
|
||||
mcl_wip.register_wip_item("mcl_minecarts:chest_minecart")
|
||||
mcl_wip.register_wip_item("mcl_minecarts:furnace_minecart")
|
||||
mcl_wip.register_wip_item("mcl_minecarts:command_block_minecart")
|
||||
mcl_wip.register_wip_item("mcl_minecarts:hopper_minecart")
|
||||
end
|
|
@ -1,6 +1,6 @@
|
|||
name = mcl_minecarts
|
||||
author = Krock
|
||||
description = Minecarts are vehicles to move players quickly on rails.
|
||||
depends = mcl_explosions, mcl_core, mcl_sounds, mcl_player, mcl_achievements, mcl_chests, mcl_furnaces, mesecons_commandblock, mcl_hoppers, mcl_tnt, mesecons, mcl_wip
|
||||
optional_depends = doc_identifier
|
||||
depends = mcl_explosions, mcl_core, mcl_sounds, mcl_player, mcl_achievements, mcl_chests, mcl_furnaces, mesecons_commandblock, mcl_hoppers, mcl_tnt, mesecons
|
||||
optional_depends = doc_identifier, mcl_wip
|
||||
|
||||
|
|
|
@ -61,8 +61,6 @@ end
|
|||
|
||||
-- Load settings
|
||||
local damage_enabled = minetest.settings:get_bool("enable_damage")
|
||||
local mobs_spawn = minetest.settings:get_bool("mobs_spawn", true) ~= false
|
||||
|
||||
local disable_blood = minetest.settings:get_bool("mobs_disable_blood")
|
||||
local mobs_drop_items = minetest.settings:get_bool("mobs_drop_items") ~= false
|
||||
local mobs_griefing = minetest.settings:get_bool("mobs_griefing") ~= false
|
||||
|
@ -84,11 +82,6 @@ if minetest.settings:get_bool("only_peaceful_mobs", false) then
|
|||
end)
|
||||
end
|
||||
|
||||
-- calculate aoc range for mob count
|
||||
local aosrb = tonumber(minetest.settings:get("active_object_send_range_blocks"))
|
||||
local abr = tonumber(minetest.settings:get("active_block_range"))
|
||||
local aoc_range = max(aosrb, abr) * 16
|
||||
|
||||
-- pathfinding settings
|
||||
local enable_pathfinding = true
|
||||
local stuck_timeout = 3 -- how long before mob gets stuck in place and starts searching
|
||||
|
@ -283,6 +276,33 @@ local get_velocity = function(self)
|
|||
return 0
|
||||
end
|
||||
|
||||
local function update_roll(self)
|
||||
local is_Fleckenstein = self.nametag == "Fleckenstein"
|
||||
local was_Fleckenstein = false
|
||||
|
||||
local rot = self.object:get_rotation()
|
||||
rot.z = is_Fleckenstein and pi or 0
|
||||
self.object:set_rotation(rot)
|
||||
|
||||
local cbox = table.copy(self.collisionbox)
|
||||
local acbox = self.object:get_properties().collisionbox
|
||||
|
||||
if math.abs(cbox[2] - acbox[2]) > 0.1 then
|
||||
was_Fleckenstein = true
|
||||
end
|
||||
|
||||
if is_Fleckenstein ~= was_Fleckenstein then
|
||||
local pos = self.object:get_pos()
|
||||
pos.y = pos.y + (acbox[2] + acbox[5])
|
||||
self.object:set_pos(pos)
|
||||
end
|
||||
|
||||
if is_Fleckenstein then
|
||||
cbox[2], cbox[5] = -cbox[5], -cbox[2]
|
||||
end
|
||||
|
||||
self.object:set_properties({collisionbox = cbox})
|
||||
end
|
||||
|
||||
-- set and return valid yaw
|
||||
local set_yaw = function(self, yaw, delay, dtime)
|
||||
|
@ -298,6 +318,7 @@ local set_yaw = function(self, yaw, delay, dtime)
|
|||
yaw = yaw + (math.random() * 2 - 1) * 5 * dtime
|
||||
end
|
||||
self.object:set_yaw(yaw)
|
||||
update_roll(self)
|
||||
return yaw
|
||||
end
|
||||
|
||||
|
@ -645,9 +666,9 @@ local update_tag = function(self)
|
|||
nametag = tag,
|
||||
})
|
||||
|
||||
update_roll(self)
|
||||
end
|
||||
|
||||
|
||||
-- drop items
|
||||
local item_drop = function(self, cooked, looting_level)
|
||||
|
||||
|
@ -707,7 +728,9 @@ local item_drop = function(self, cooked, looting_level)
|
|||
end
|
||||
|
||||
-- add item if it exists
|
||||
obj = minetest.add_item(pos, ItemStack(item .. " " .. num))
|
||||
for x = 1, num do
|
||||
obj = minetest.add_item(pos, ItemStack(item .. " " .. 1))
|
||||
end
|
||||
|
||||
if obj and obj:get_luaentity() then
|
||||
|
||||
|
@ -836,10 +859,12 @@ local check_for_death = function(self, cause, cmi_cause)
|
|||
remove_texture_mod(self, "^[colorize:#FF000040")
|
||||
remove_texture_mod(self, "^[brighten")
|
||||
self.passive = true
|
||||
|
||||
self.object:set_properties({
|
||||
pointable = false,
|
||||
collide_with_objects = false,
|
||||
})
|
||||
|
||||
set_velocity(self, 0)
|
||||
local acc = self.object:get_acceleration()
|
||||
acc.x, acc.y, acc.z = 0, DEFAULT_FALL_SPEED, 0
|
||||
|
@ -2789,6 +2814,10 @@ local do_states = function(self, dtime)
|
|||
local arrow, ent
|
||||
local v = 1
|
||||
if not self.shoot_arrow then
|
||||
self.firing = true
|
||||
minetest.after(1, function()
|
||||
self.firing = false
|
||||
end)
|
||||
arrow = minetest.add_entity(p, self.arrow)
|
||||
ent = arrow:get_luaentity()
|
||||
if ent.velocity then
|
||||
|
@ -3487,18 +3516,11 @@ local mob_step = function(self, dtime)
|
|||
yaw = yaw + (math.random() * 2 - 1) * 5 * dtime
|
||||
end
|
||||
self.object:set_yaw(yaw)
|
||||
update_roll(self)
|
||||
end
|
||||
|
||||
-- end rotation
|
||||
|
||||
-- knockback timer
|
||||
if self.pause_timer > 0 then
|
||||
|
||||
self.pause_timer = self.pause_timer - dtime
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
-- run custom function (defined in mob lua file)
|
||||
if self.do_custom then
|
||||
|
||||
|
@ -3508,6 +3530,14 @@ local mob_step = function(self, dtime)
|
|||
end
|
||||
end
|
||||
|
||||
-- knockback timer
|
||||
if self.pause_timer > 0 then
|
||||
|
||||
self.pause_timer = self.pause_timer - dtime
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
-- attack timer
|
||||
self.timer = self.timer + dtime
|
||||
|
||||
|
@ -3526,7 +3556,7 @@ local mob_step = function(self, dtime)
|
|||
end
|
||||
|
||||
-- mob plays random sound at times
|
||||
if random(1, 100) == 1 then
|
||||
if random(1, 70) == 1 then
|
||||
mob_sound(self, "random", true)
|
||||
end
|
||||
|
||||
|
@ -3706,6 +3736,8 @@ function mobs:register_mob(name, def)
|
|||
local can_despawn
|
||||
if def.can_despawn ~= nil then
|
||||
can_despawn = def.can_despawn
|
||||
elseif def.spawn_class == "passive" then
|
||||
can_despawn = false
|
||||
else
|
||||
can_despawn = true
|
||||
end
|
||||
|
@ -3869,6 +3901,12 @@ minetest.register_entity(name, {
|
|||
on_detach_child = mob_detach_child,
|
||||
|
||||
on_activate = function(self, staticdata, dtime)
|
||||
--this is a temporary hack so mobs stop
|
||||
--glitching and acting really weird with the
|
||||
--default built in engine collision detection
|
||||
self.object:set_properties({
|
||||
collide_with_objects = false,
|
||||
})
|
||||
return mob_activate(self, staticdata, def, dtime)
|
||||
end,
|
||||
|
||||
|
@ -3887,289 +3925,6 @@ end
|
|||
end -- END mobs:register_mob function
|
||||
|
||||
|
||||
-- count how many mobs of one type are inside an area
|
||||
local count_mobs = function(pos, mobtype)
|
||||
|
||||
local num = 0
|
||||
local objs = minetest.get_objects_inside_radius(pos, aoc_range)
|
||||
|
||||
for n = 1, #objs do
|
||||
|
||||
local obj = objs[n]:get_luaentity()
|
||||
|
||||
if obj and obj.name and obj._cmi_is_mob then
|
||||
|
||||
-- count passive mobs only
|
||||
if mobtype == "!passive" then
|
||||
if obj.spawn_class == "passive" then
|
||||
num = num + 1
|
||||
end
|
||||
-- count hostile mobs only
|
||||
elseif mobtype == "!hostile" then
|
||||
if obj.spawn_class == "hostile" then
|
||||
num = num + 1
|
||||
end
|
||||
-- count ambient mobs only
|
||||
elseif mobtype == "!ambient" then
|
||||
if obj.spawn_class == "ambient" then
|
||||
num = num + 1
|
||||
end
|
||||
-- count water mobs only
|
||||
elseif mobtype == "!water" then
|
||||
if obj.spawn_class == "water" then
|
||||
num = num + 1
|
||||
end
|
||||
-- count mob type
|
||||
elseif mobtype and obj.name == mobtype then
|
||||
num = num + 1
|
||||
-- count total mobs
|
||||
elseif not mobtype then
|
||||
num = num + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return num
|
||||
end
|
||||
|
||||
|
||||
-- global functions
|
||||
|
||||
function mobs:spawn_abm_check(pos, node, name)
|
||||
-- global function to add additional spawn checks
|
||||
-- return true to stop spawning mob
|
||||
end
|
||||
|
||||
|
||||
function mobs:spawn_specific(name, nodes, neighbors, min_light, max_light,
|
||||
interval, chance, aoc, min_height, max_height, day_toggle, on_spawn)
|
||||
|
||||
-- Do mobs spawn at all?
|
||||
if not mobs_spawn then
|
||||
return
|
||||
end
|
||||
|
||||
-- chance/spawn number override in minetest.conf for registered mob
|
||||
local numbers = minetest.settings:get(name)
|
||||
|
||||
if numbers then
|
||||
numbers = numbers:split(",")
|
||||
chance = tonumber(numbers[1]) or chance
|
||||
aoc = tonumber(numbers[2]) or aoc
|
||||
|
||||
if chance == 0 then
|
||||
minetest.log("warning", string.format("[mobs] %s has spawning disabled", name))
|
||||
return
|
||||
end
|
||||
|
||||
minetest.log("action",
|
||||
string.format("[mobs] Chance setting for %s changed to %s (total: %s)", name, chance, aoc))
|
||||
|
||||
end
|
||||
|
||||
local spawn_action
|
||||
spawn_action = function(pos, node, active_object_count, active_object_count_wider, name)
|
||||
|
||||
local orig_pos = table.copy(pos)
|
||||
-- is mob actually registered?
|
||||
if not mobs.spawning_mobs[name]
|
||||
or not minetest.registered_entities[name] then
|
||||
minetest.log("warning", "Mob spawn of "..name.." failed, unknown entity or mob is not registered for spawning!")
|
||||
return
|
||||
end
|
||||
|
||||
-- additional custom checks for spawning mob
|
||||
if mobs:spawn_abm_check(pos, node, name) == true then
|
||||
minetest.log("info", "Mob spawn of "..name.." at "..minetest.pos_to_string(pos).." failed, ABM check rejected!")
|
||||
return
|
||||
end
|
||||
|
||||
-- count nearby mobs in same spawn class
|
||||
local entdef = minetest.registered_entities[name]
|
||||
local spawn_class = entdef and entdef.spawn_class
|
||||
if not spawn_class then
|
||||
if entdef.type == "monster" then
|
||||
spawn_class = "hostile"
|
||||
else
|
||||
spawn_class = "passive"
|
||||
end
|
||||
end
|
||||
local in_class_cap = count_mobs(pos, "!"..spawn_class) < MOB_CAP[spawn_class]
|
||||
-- do not spawn if too many of same mob in area
|
||||
if active_object_count_wider >= max_per_block -- large-range mob cap
|
||||
or (not in_class_cap) -- spawn class mob cap
|
||||
or count_mobs(pos, name) >= aoc then -- per-mob mob cap
|
||||
-- too many entities
|
||||
minetest.log("info", "Mob spawn of "..name.." at "..minetest.pos_to_string(pos).." failed, too crowded!")
|
||||
return
|
||||
end
|
||||
|
||||
-- if toggle set to nil then ignore day/night check
|
||||
if day_toggle ~= nil then
|
||||
|
||||
local tod = (minetest.get_timeofday() or 0) * 24000
|
||||
|
||||
if tod > 4500 and tod < 19500 then
|
||||
-- daylight, but mob wants night
|
||||
if day_toggle == false then
|
||||
-- mob needs night
|
||||
minetest.log("info", "Mob spawn of "..name.." at "..minetest.pos_to_string(pos).." failed, mob needs light!")
|
||||
return
|
||||
end
|
||||
else
|
||||
-- night time but mob wants day
|
||||
if day_toggle == true then
|
||||
-- mob needs day
|
||||
minetest.log("info", "Mob spawn of "..name.." at "..minetest.pos_to_string(pos).." failed, mob needs daylight!")
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- spawn above node
|
||||
pos.y = pos.y + 1
|
||||
|
||||
-- only spawn away from player
|
||||
local objs = minetest.get_objects_inside_radius(pos, 24)
|
||||
|
||||
for n = 1, #objs do
|
||||
|
||||
if objs[n]:is_player() then
|
||||
-- player too close
|
||||
minetest.log("info", "Mob spawn of "..name.." at "..minetest.pos_to_string(pos).." failed, player too close!")
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
-- mobs cannot spawn in protected areas when enabled
|
||||
if not spawn_protected
|
||||
and minetest.is_protected(pos, "") then
|
||||
minetest.log("info", "Mob spawn of "..name.." at "..minetest.pos_to_string(pos).." failed, position is protected!")
|
||||
return
|
||||
end
|
||||
|
||||
-- are we spawning within height limits?
|
||||
if pos.y > max_height
|
||||
or pos.y < min_height then
|
||||
minetest.log("info", "Mob spawn of "..name.." at "..minetest.pos_to_string(pos).." failed, out of height limit!")
|
||||
return
|
||||
end
|
||||
|
||||
-- are light levels ok?
|
||||
local light = minetest.get_node_light(pos)
|
||||
if not light
|
||||
or light > max_light
|
||||
or light < min_light then
|
||||
minetest.log("info", "Mob spawn of "..name.." at "..minetest.pos_to_string(pos).." failed, bad light!")
|
||||
return
|
||||
end
|
||||
|
||||
-- do we have enough space to spawn mob?
|
||||
local ent = minetest.registered_entities[name]
|
||||
local width_x = max(1, math.ceil(ent.collisionbox[4] - ent.collisionbox[1]))
|
||||
local min_x, max_x
|
||||
if width_x % 2 == 0 then
|
||||
max_x = math.floor(width_x/2)
|
||||
min_x = -(max_x-1)
|
||||
else
|
||||
max_x = math.floor(width_x/2)
|
||||
min_x = -max_x
|
||||
end
|
||||
|
||||
local width_z = max(1, math.ceil(ent.collisionbox[6] - ent.collisionbox[3]))
|
||||
local min_z, max_z
|
||||
if width_z % 2 == 0 then
|
||||
max_z = math.floor(width_z/2)
|
||||
min_z = -(max_z-1)
|
||||
else
|
||||
max_z = math.floor(width_z/2)
|
||||
min_z = -max_z
|
||||
end
|
||||
|
||||
local max_y = max(0, math.ceil(ent.collisionbox[5] - ent.collisionbox[2]) - 1)
|
||||
|
||||
for y = 0, max_y do
|
||||
for x = min_x, max_x do
|
||||
for z = min_z, max_z do
|
||||
local pos2 = {x = pos.x+x, y = pos.y+y, z = pos.z+z}
|
||||
if minetest.registered_nodes[node_ok(pos2).name].walkable == true then
|
||||
-- inside block
|
||||
minetest.log("info", "Mob spawn of "..name.." at "..minetest.pos_to_string(pos).." failed, too little space!")
|
||||
if ent.spawn_small_alternative ~= nil and (not minetest.registered_nodes[node_ok(pos).name].walkable) then
|
||||
minetest.log("info", "Trying to spawn smaller alternative mob: "..ent.spawn_small_alternative)
|
||||
spawn_action(orig_pos, node, active_object_count, active_object_count_wider, ent.spawn_small_alternative)
|
||||
end
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- tweak X/Y/Z spawn pos
|
||||
if width_x % 2 == 0 then
|
||||
pos.x = pos.x + 0.5
|
||||
end
|
||||
if width_z % 2 == 0 then
|
||||
pos.z = pos.z + 0.5
|
||||
end
|
||||
pos.y = pos.y - 0.5
|
||||
|
||||
local mob = minetest.add_entity(pos, name)
|
||||
minetest.log("action", "Mob spawned: "..name.." at "..minetest.pos_to_string(pos))
|
||||
|
||||
if on_spawn then
|
||||
|
||||
local ent = mob:get_luaentity()
|
||||
|
||||
on_spawn(ent, pos)
|
||||
end
|
||||
end
|
||||
|
||||
local function spawn_abm_action(pos, node, active_object_count, active_object_count_wider)
|
||||
spawn_action(pos, node, active_object_count, active_object_count_wider, name)
|
||||
end
|
||||
|
||||
minetest.register_abm({
|
||||
label = name .. " spawning",
|
||||
nodenames = nodes,
|
||||
neighbors = neighbors,
|
||||
interval = interval,
|
||||
chance = floor(max(1, chance * mobs_spawn_chance)),
|
||||
catch_up = false,
|
||||
action = spawn_abm_action,
|
||||
})
|
||||
end
|
||||
|
||||
|
||||
-- compatibility with older mob registration
|
||||
function mobs:register_spawn(name, nodes, max_light, min_light, chance, active_object_count, max_height, day_toggle)
|
||||
|
||||
mobs:spawn_specific(name, nodes, {"air"}, min_light, max_light, 30,
|
||||
chance, active_object_count, -31000, max_height, day_toggle)
|
||||
end
|
||||
|
||||
|
||||
-- MarkBu's spawn function
|
||||
function mobs:spawn(def)
|
||||
|
||||
local name = def.name
|
||||
local nodes = def.nodes or {"group:soil", "group:stone"}
|
||||
local neighbors = def.neighbors or {"air"}
|
||||
local min_light = def.min_light or 0
|
||||
local max_light = def.max_light or 15
|
||||
local interval = def.interval or 30
|
||||
local chance = def.chance or 5000
|
||||
local active_object_count = def.active_object_count or 1
|
||||
local min_height = def.min_height or -31000
|
||||
local max_height = def.max_height or 31000
|
||||
local day_toggle = def.day_toggle
|
||||
local on_spawn = def.on_spawn
|
||||
|
||||
mobs:spawn_specific(name, nodes, neighbors, min_light, max_light, interval,
|
||||
chance, active_object_count, min_height, max_height, day_toggle, on_spawn)
|
||||
end
|
||||
|
||||
|
||||
-- register arrow for shoot attack
|
||||
function mobs:register_arrow(name, def)
|
||||
|
||||
|
@ -4192,6 +3947,11 @@ function mobs:register_arrow(name, def)
|
|||
switch = 0,
|
||||
owner_id = def.owner_id,
|
||||
rotate = def.rotate,
|
||||
on_punch = function(self)
|
||||
local vel = self.object:get_velocity()
|
||||
self.object:set_velocity({x=vel.x * -1, y=vel.y * -1, z=vel.z * -1})
|
||||
end,
|
||||
collisionbox = def.collisionbox or {0, 0, 0, 0, 0, 0},
|
||||
automatic_face_movement_dir = def.rotate
|
||||
and (def.rotate - (pi / 180)) or false,
|
||||
|
||||
|
@ -4254,7 +4014,7 @@ function mobs:register_arrow(name, def)
|
|||
|
||||
if self.hit_player or self.hit_mob or self.hit_object then
|
||||
|
||||
for _,player in pairs(minetest.get_objects_inside_radius(pos, 1.0)) do
|
||||
for _,player in pairs(minetest.get_objects_inside_radius(pos, 1.5)) do
|
||||
|
||||
if self.hit_player
|
||||
and player:is_player() then
|
||||
|
@ -4309,7 +4069,7 @@ end
|
|||
|
||||
-- make explosion with protection and tnt mod check
|
||||
function mobs:boom(self, pos, strength, fire)
|
||||
|
||||
self.object:remove()
|
||||
if mod_explosions then
|
||||
if mobs_griefing and not minetest.is_protected(pos, "") then
|
||||
mcl_explosions.explode(pos, strength, { drop_chance = 1.0, fire = fire }, self.object)
|
||||
|
@ -4590,6 +4350,7 @@ function mobs:alias_mob(old_name, new_name)
|
|||
|
||||
end
|
||||
|
||||
--[[
|
||||
local timer = 0
|
||||
minetest.register_globalstep(function(dtime)
|
||||
timer = timer + dtime
|
||||
|
@ -4606,3 +4367,4 @@ minetest.register_globalstep(function(dtime)
|
|||
end
|
||||
timer = 0
|
||||
end)
|
||||
]]--
|
|
@ -4,8 +4,11 @@ local path = minetest.get_modpath(minetest.get_current_modname())
|
|||
-- Mob API
|
||||
dofile(path .. "/api.lua")
|
||||
|
||||
-- Spawning Algorithm
|
||||
dofile(path .. "/spawning.lua")
|
||||
|
||||
-- Rideable Mobs
|
||||
dofile(path .. "/mount.lua")
|
||||
|
||||
-- Mob Items
|
||||
dofile(path .. "/crafts.lua")
|
||||
dofile(path .. "/crafts.lua")
|
|
@ -168,16 +168,20 @@ function mobs.detach(player, offset)
|
|||
|
||||
mcl_player.player_set_animation(player, "stand" , 30)
|
||||
|
||||
local pos = player:get_pos()
|
||||
--local pos = player:get_pos()
|
||||
|
||||
pos = {x = pos.x + offset.x, y = pos.y + 0.2 + offset.y, z = pos.z + offset.z}
|
||||
--pos = {x = pos.x + offset.x, y = pos.y + 0.2 + offset.y, z = pos.z + offset.z}
|
||||
|
||||
player:add_velocity(vector.new(math.random(-6,6),math.random(5,8),math.random(-6,6))) --throw the rider off
|
||||
|
||||
--[[
|
||||
minetest.after(0.1, function(name, pos)
|
||||
local player = minetest.get_player_by_name(name)
|
||||
if player then
|
||||
player:set_pos(pos)
|
||||
end
|
||||
end, player:get_player_name(), pos)
|
||||
]]--
|
||||
end
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,648 @@
|
|||
--lua locals
|
||||
local get_node = minetest.get_node
|
||||
local get_item_group = minetest.get_item_group
|
||||
local get_node_light = minetest.get_node_light
|
||||
local find_nodes_in_area_under_air = minetest.find_nodes_in_area_under_air
|
||||
local new_vector = vector.new
|
||||
local math_random = math.random
|
||||
local get_biome_name = minetest.get_biome_name
|
||||
local max = math.max
|
||||
local get_objects_inside_radius = minetest.get_objects_inside_radius
|
||||
local vector_distance = vector.distance
|
||||
|
||||
-- range for mob count
|
||||
local aoc_range = 32
|
||||
--[[
|
||||
|
||||
THIS IS THE BIG LIST OF ALL BIOMES - used for programming/updating mobs
|
||||
|
||||
underground:
|
||||
"FlowerForest_underground",
|
||||
"JungleEdge_underground",local spawning_position = spawning_position_list[math.random(1,#spawning_position_list)]
|
||||
"ColdTaiga_underground",
|
||||
"IcePlains_underground",
|
||||
"IcePlainsSpikes_underground",
|
||||
"MegaTaiga_underground",
|
||||
"Taiga_underground",
|
||||
"ExtremeHills+_underground",
|
||||
"JungleM_underground",
|
||||
"ExtremeHillsM_underground",
|
||||
"JungleEdgeM_underground",
|
||||
|
||||
ocean:
|
||||
"RoofedForest_ocean",
|
||||
"JungleEdgeM_ocean",
|
||||
"BirchForestM_ocean",
|
||||
"BirchForest_ocean",
|
||||
"IcePlains_deep_ocean",
|
||||
"Jungle_deep_ocean",
|
||||
"Savanna_ocean",
|
||||
"MesaPlateauF_ocean",
|
||||
"ExtremeHillsM_deep_ocean",
|
||||
"Savanna_deep_ocean",
|
||||
"SunflowerPlains_ocean",
|
||||
"Swampland_deep_ocean",
|
||||
"Swampland_ocean",
|
||||
"MegaSpruceTaiga_deep_ocean",
|
||||
"ExtremeHillsM_ocean",
|
||||
"JungleEdgeM_deep_ocean",
|
||||
"SunflowerPlains_deep_ocean",
|
||||
"BirchForest_deep_ocean",
|
||||
"IcePlainsSpikes_ocean",
|
||||
"Mesa_ocean",
|
||||
"StoneBeach_ocean",
|
||||
"Plains_deep_ocean",
|
||||
"JungleEdge_deep_ocean",
|
||||
"SavannaM_deep_ocean",
|
||||
"Desert_deep_ocean",
|
||||
"Mesa_deep_ocean",
|
||||
"ColdTaiga_deep_ocean",
|
||||
"Plains_ocean",
|
||||
"MesaPlateauFM_ocean",
|
||||
"Forest_deep_ocean",
|
||||
"JungleM_deep_ocean",
|
||||
"FlowerForest_deep_ocean",
|
||||
"MushroomIsland_ocean",
|
||||
"MegaTaiga_ocean",
|
||||
"StoneBeach_deep_ocean",
|
||||
"IcePlainsSpikes_deep_ocean",
|
||||
"ColdTaiga_ocean",
|
||||
"SavannaM_ocean",
|
||||
"MesaPlateauF_deep_ocean",
|
||||
"MesaBryce_deep_ocean",
|
||||
"ExtremeHills+_deep_ocean",
|
||||
"ExtremeHills_ocean",
|
||||
"MushroomIsland_deep_ocean",
|
||||
"Forest_ocean",
|
||||
"MegaTaiga_deep_ocean",
|
||||
"JungleEdge_ocean",
|
||||
"MesaBryce_ocean",
|
||||
"MegaSpruceTaiga_ocean",
|
||||
"ExtremeHills+_ocean",
|
||||
"Jungle_ocean",
|
||||
"RoofedForest_deep_ocean",
|
||||
"IcePlains_ocean",
|
||||
"FlowerForest_ocean",
|
||||
"ExtremeHills_deep_ocean",
|
||||
"MesaPlateauFM_deep_ocean",
|
||||
"Desert_ocean",
|
||||
"Taiga_ocean",
|
||||
"BirchForestM_deep_ocean",
|
||||
"Taiga_deep_ocean",
|
||||
"JungleM_ocean",
|
||||
|
||||
water or beach?
|
||||
"MesaPlateauFM_sandlevel",
|
||||
"MesaPlateauF_sandlevel",
|
||||
"MesaBryce_sandlevel",
|
||||
"Mesa_sandlevel",
|
||||
|
||||
beach:
|
||||
"FlowerForest_beach",
|
||||
"Forest_beach",
|
||||
"StoneBeach",
|
||||
"ColdTaiga_beach_water",
|
||||
"Taiga_beach",
|
||||
"Savanna_beach",
|
||||
"Plains_beach",
|
||||
"ExtremeHills_beach",
|
||||
"ColdTaiga_beach",
|
||||
"Swampland_shore",
|
||||
"MushroomIslandShore",
|
||||
"JungleM_shore",
|
||||
"Jungle_shore",
|
||||
|
||||
dimension biome:
|
||||
"Nether",
|
||||
"End",
|
||||
|
||||
Overworld regular:
|
||||
"Mesa",
|
||||
"FlowerForest",
|
||||
"Swampland",
|
||||
"Taiga",
|
||||
"ExtremeHills",
|
||||
"Jungle",
|
||||
"Savanna",
|
||||
"BirchForest",
|
||||
"MegaSpruceTaiga",
|
||||
"MegaTaiga",
|
||||
"ExtremeHills+",
|
||||
"Forest",
|
||||
"Plains",
|
||||
"Desert",
|
||||
"ColdTaiga",
|
||||
"MushroomIsland",
|
||||
"IcePlainsSpikes",
|
||||
"SunflowerPlains",
|
||||
"IcePlains",
|
||||
"RoofedForest",
|
||||
"ExtremeHills+_snowtop",
|
||||
"MesaPlateauFM_grasstop",
|
||||
"JungleEdgeM",
|
||||
"ExtremeHillsM",
|
||||
"JungleM",
|
||||
"BirchForestM",
|
||||
"MesaPlateauF",
|
||||
"MesaPlateauFM",
|
||||
"MesaPlateauF_grasstop",
|
||||
"MesaBryce",
|
||||
"JungleEdge",
|
||||
"SavannaM",
|
||||
]]--
|
||||
|
||||
|
||||
|
||||
|
||||
local mobs_spawn = minetest.settings:get_bool("mobs_spawn", true) ~= false
|
||||
-- count how many mobs of one type are inside an area
|
||||
|
||||
local count_mobs = function(pos,mobtype)
|
||||
print(mobtype)
|
||||
local num = 0
|
||||
local objs = get_objects_inside_radius(pos, aoc_range)
|
||||
for n = 1, #objs do
|
||||
local obj = objs[n]:get_luaentity()
|
||||
if obj and obj.name and obj._cmi_is_mob then
|
||||
-- count hostile mobs only
|
||||
if mobtype == "hostile" then
|
||||
if obj.spawn_class == "hostile" then
|
||||
num = num + 1
|
||||
end
|
||||
-- count passive mobs only
|
||||
else
|
||||
num = num + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return num
|
||||
end
|
||||
|
||||
|
||||
-- global functions
|
||||
|
||||
function mobs:spawn_abm_check(pos, node, name)
|
||||
-- global function to add additional spawn checks
|
||||
-- return true to stop spawning mob
|
||||
end
|
||||
|
||||
|
||||
--[[
|
||||
Custom elements changed:
|
||||
|
||||
name:
|
||||
the mobs name
|
||||
|
||||
dimension:
|
||||
"overworld"
|
||||
"nether"
|
||||
"end"
|
||||
|
||||
types of spawning:
|
||||
"water"
|
||||
"ground"
|
||||
"lava"
|
||||
|
||||
biomes: tells the spawner to allow certain mobs to spawn in certain biomes
|
||||
{"this", "that", "grasslands", "whatever"}
|
||||
|
||||
|
||||
what is aoc??? objects in area
|
||||
|
||||
WARNING: BIOME INTEGRATION NEEDED -> How to get biome through lua??
|
||||
]]--
|
||||
|
||||
|
||||
--this is where all of the spawning information is kept
|
||||
local spawn_dictionary = {}
|
||||
|
||||
function mobs:spawn_specific(name, dimension, type_of_spawning, biomes, min_light, max_light, interval, chance, aoc, min_height, max_height, day_toggle, on_spawn)
|
||||
|
||||
--print(dump(biomes))
|
||||
|
||||
-- Do mobs spawn at all?
|
||||
if not mobs_spawn then
|
||||
return
|
||||
end
|
||||
|
||||
-- chance/spawn number override in minetest.conf for registered mob
|
||||
local numbers = minetest.settings:get(name)
|
||||
|
||||
if numbers then
|
||||
numbers = numbers:split(",")
|
||||
chance = tonumber(numbers[1]) or chance
|
||||
aoc = tonumber(numbers[2]) or aoc
|
||||
|
||||
if chance == 0 then
|
||||
minetest.log("warning", string.format("[mobs] %s has spawning disabled", name))
|
||||
return
|
||||
end
|
||||
|
||||
minetest.log("action",
|
||||
string.format("[mobs] Chance setting for %s changed to %s (total: %s)", name, chance, aoc))
|
||||
end
|
||||
|
||||
--[[
|
||||
local spawn_action
|
||||
spawn_action = function(pos, node, active_object_count, active_object_count_wider, name)
|
||||
|
||||
local orig_pos = table.copy(pos)
|
||||
-- is mob actually registered?
|
||||
if not mobs.spawning_mobs[name]
|
||||
or not minetest.registered_entities[name] then
|
||||
minetest.log("warning", "Mob spawn of "..name.." failed, unknown entity or mob is not registered for spawning!")
|
||||
return
|
||||
end
|
||||
|
||||
-- additional custom checks for spawning mob
|
||||
if mobs:spawn_abm_check(pos, node, name) == true then
|
||||
minetest.log("info", "Mob spawn of "..name.." at "..minetest.pos_to_string(pos).." failed, ABM check rejected!")
|
||||
return
|
||||
end
|
||||
|
||||
-- count nearby mobs in same spawn class
|
||||
local entdef = minetest.registered_entities[name]
|
||||
local spawn_class = entdef and entdef.spawn_class
|
||||
if not spawn_class then
|
||||
if entdef.type == "monster" then
|
||||
spawn_class = "hostile"
|
||||
else
|
||||
spawn_class = "passive"
|
||||
end
|
||||
end
|
||||
local in_class_cap = count_mobs(pos, "!"..spawn_class) < MOB_CAP[spawn_class]
|
||||
-- do not spawn if too many of same mob in area
|
||||
if active_object_count_wider >= max_per_block -- large-range mob cap
|
||||
or (not in_class_cap) -- spawn class mob cap
|
||||
or count_mobs(pos, name) >= aoc then -- per-mob mob cap
|
||||
-- too many entities
|
||||
minetest.log("info", "Mob spawn of "..name.." at "..minetest.pos_to_string(pos).." failed, too crowded!")
|
||||
return
|
||||
end
|
||||
|
||||
-- if toggle set to nil then ignore day/night check
|
||||
if day_toggle ~= nil then
|
||||
|
||||
local tod = (minetest.get_timeofday() or 0) * 24000
|
||||
|
||||
if tod > 4500 and tod < 19500 then
|
||||
-- daylight, but mob wants night
|
||||
if day_toggle == false then
|
||||
-- mob needs night
|
||||
minetest.log("info", "Mob spawn of "..name.." at "..minetest.pos_to_string(pos).." failed, mob needs light!")
|
||||
return
|
||||
end
|
||||
else
|
||||
-- night time but mob wants day
|
||||
if day_toggle == true then
|
||||
-- mob needs day
|
||||
minetest.log("info", "Mob spawn of "..name.." at "..minetest.pos_to_string(pos).." failed, mob needs daylight!")
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- spawn above node
|
||||
pos.y = pos.y + 1
|
||||
|
||||
-- only spawn away from player
|
||||
local objs = minetest.get_objects_inside_radius(pos, 24)
|
||||
|
||||
for n = 1, #objs do
|
||||
|
||||
if objs[n]:is_player() then
|
||||
-- player too close
|
||||
minetest.log("info", "Mob spawn of "..name.." at "..minetest.pos_to_string(pos).." failed, player too close!")
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
-- mobs cannot spawn in protected areas when enabled
|
||||
if not spawn_protected
|
||||
and minetest.is_protected(pos, "") then
|
||||
minetest.log("info", "Mob spawn of "..name.." at "..minetest.pos_to_string(pos).." failed, position is protected!")
|
||||
return
|
||||
end
|
||||
|
||||
-- are we spawning within height limits?
|
||||
if pos.y > max_height
|
||||
or pos.y < min_height then
|
||||
minetest.log("info", "Mob spawn of "..name.." at "..minetest.pos_to_string(pos).." failed, out of height limit!")
|
||||
return
|
||||
end
|
||||
|
||||
-- are light levels ok?
|
||||
local light = minetest.get_node_light(pos)
|
||||
if not light
|
||||
or light > max_light
|
||||
or light < min_light then
|
||||
minetest.log("info", "Mob spawn of "..name.." at "..minetest.pos_to_string(pos).." failed, bad light!")
|
||||
return
|
||||
end
|
||||
|
||||
-- do we have enough space to spawn mob?
|
||||
local ent = minetest.registered_entities[name]
|
||||
local width_x = max(1, math.ceil(ent.collisionbox[4] - ent.collisionbox[1]))
|
||||
local min_x, max_x
|
||||
if width_x % 2 == 0 then
|
||||
max_x = math.floor(width_x/2)
|
||||
min_x = -(max_x-1)
|
||||
else
|
||||
max_x = math.floor(width_x/2)
|
||||
min_x = -max_x
|
||||
end
|
||||
|
||||
local width_z = max(1, math.ceil(ent.collisionbox[6] - ent.collisionbox[3]))
|
||||
local min_z, max_z
|
||||
if width_z % 2 == 0 then
|
||||
max_z = math.floor(width_z/2)
|
||||
min_z = -(max_z-1)
|
||||
else
|
||||
max_z = math.floor(width_z/2)
|
||||
min_z = -max_z
|
||||
end
|
||||
|
||||
local max_y = max(0, math.ceil(ent.collisionbox[5] - ent.collisionbox[2]) - 1)
|
||||
|
||||
for y = 0, max_y do
|
||||
for x = min_x, max_x do
|
||||
for z = min_z, max_z do
|
||||
local pos2 = {x = pos.x+x, y = pos.y+y, z = pos.z+z}
|
||||
if minetest.registered_nodes[node_ok(pos2).name].walkable == true then
|
||||
-- inside block
|
||||
minetest.log("info", "Mob spawn of "..name.." at "..minetest.pos_to_string(pos).." failed, too little space!")
|
||||
if ent.spawn_small_alternative ~= nil and (not minetest.registered_nodes[node_ok(pos).name].walkable) then
|
||||
minetest.log("info", "Trying to spawn smaller alternative mob: "..ent.spawn_small_alternative)
|
||||
spawn_action(orig_pos, node, active_object_count, active_object_count_wider, ent.spawn_small_alternative)
|
||||
end
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- tweak X/Y/Z spawn pos
|
||||
if width_x % 2 == 0 then
|
||||
pos.x = pos.x + 0.5
|
||||
end
|
||||
if width_z % 2 == 0 then
|
||||
pos.z = pos.z + 0.5
|
||||
end
|
||||
pos.y = pos.y - 0.5
|
||||
|
||||
local mob = minetest.add_entity(pos, name)
|
||||
minetest.log("action", "Mob spawned: "..name.." at "..minetest.pos_to_string(pos))
|
||||
|
||||
if on_spawn then
|
||||
|
||||
local ent = mob:get_luaentity()
|
||||
|
||||
on_spawn(ent, pos)
|
||||
end
|
||||
end
|
||||
|
||||
local function spawn_abm_action(pos, node, active_object_count, active_object_count_wider)
|
||||
spawn_action(pos, node, active_object_count, active_object_count_wider, name)
|
||||
end
|
||||
]]--
|
||||
|
||||
local entdef = minetest.registered_entities[name]
|
||||
local spawn_class
|
||||
if entdef.type == "monster" then
|
||||
spawn_class = "hostile"
|
||||
else
|
||||
spawn_class = "passive"
|
||||
end
|
||||
|
||||
--load information into the spawn dictionary
|
||||
local key = #spawn_dictionary + 1
|
||||
spawn_dictionary[key] = {}
|
||||
spawn_dictionary[key]["name"] = name
|
||||
spawn_dictionary[key]["dimension"] = dimension
|
||||
spawn_dictionary[key]["type_of_spawning"] = type_of_spawning
|
||||
spawn_dictionary[key]["biomes"] = biomes
|
||||
spawn_dictionary[key]["min_light"] = min_light
|
||||
spawn_dictionary[key]["max_light"] = max_light
|
||||
spawn_dictionary[key]["interval"] = interval
|
||||
spawn_dictionary[key]["chance"] = chance
|
||||
spawn_dictionary[key]["aoc"] = aoc
|
||||
spawn_dictionary[key]["min_height"] = min_height
|
||||
spawn_dictionary[key]["max_height"] = max_height
|
||||
spawn_dictionary[key]["day_toggle"] = day_toggle
|
||||
--spawn_dictionary[key]["on_spawn"] = spawn_abm_action
|
||||
spawn_dictionary[key]["spawn_class"] = spawn_class
|
||||
|
||||
--[[
|
||||
minetest.register_abm({
|
||||
label = name .. " spawning",
|
||||
nodenames = nodes,
|
||||
neighbors = neighbors,
|
||||
interval = interval,
|
||||
chance = floor(max(1, chance * mobs_spawn_chance)),
|
||||
catch_up = false,
|
||||
action = spawn_abm_action,
|
||||
})
|
||||
]]--
|
||||
end
|
||||
|
||||
-- compatibility with older mob registration
|
||||
-- we're going to forget about this for now -j4i
|
||||
--[[
|
||||
function mobs:register_spawn(name, nodes, max_light, min_light, chance, active_object_count, max_height, day_toggle)
|
||||
|
||||
mobs:spawn_specific(name, nodes, {"air"}, min_light, max_light, 30,
|
||||
chance, active_object_count, -31000, max_height, day_toggle)
|
||||
end
|
||||
]]--
|
||||
|
||||
|
||||
--Don't disable this yet-j4i
|
||||
-- MarkBu's spawn function
|
||||
|
||||
function mobs:spawn(def)
|
||||
--does nothing for now
|
||||
--[[
|
||||
local name = def.name
|
||||
local nodes = def.nodes or {"group:soil", "group:stone"}
|
||||
local neighbors = def.neighbors or {"air"}
|
||||
local min_light = def.min_light or 0
|
||||
local max_light = def.max_light or 15
|
||||
local interval = def.interval or 30
|
||||
local chance = def.chance or 5000
|
||||
local active_object_count = def.active_object_count or 1
|
||||
local min_height = def.min_height or -31000
|
||||
local max_height = def.max_height or 31000
|
||||
local day_toggle = def.day_toggle
|
||||
local on_spawn = def.on_spawn
|
||||
|
||||
mobs:spawn_specific(name, nodes, neighbors, min_light, max_light, interval,
|
||||
chance, active_object_count, min_height, max_height, day_toggle, on_spawn)
|
||||
]]--
|
||||
end
|
||||
|
||||
|
||||
|
||||
local axis
|
||||
--inner and outer part of square donut radius
|
||||
local inner = 1
|
||||
local outer = 65
|
||||
local int = {-1,1}
|
||||
local position_calculation = function(pos)
|
||||
|
||||
pos = vector.floor(pos)
|
||||
|
||||
--this is used to determine the axis buffer from the player
|
||||
axis = math.random(0,1)
|
||||
|
||||
--cast towards the direction
|
||||
if axis == 0 then --x
|
||||
pos.x = pos.x + math.random(inner,outer)*int[math.random(1,2)]
|
||||
pos.z = pos.z + math.random(-outer,outer)
|
||||
else --z
|
||||
pos.z = pos.z + math.random(inner,outer)*int[math.random(1,2)]
|
||||
pos.x = pos.x + math.random(-outer,outer)
|
||||
end
|
||||
return(pos)
|
||||
end
|
||||
|
||||
--[[
|
||||
local decypher_limits_dictionary = {
|
||||
["overworld"] = {mcl_vars.mg_overworld_min,mcl_vars.mg_overworld_max},
|
||||
["nether"] = {mcl_vars.mg_nether_min, mcl_vars.mg_nether_max},
|
||||
["end"] = {mcl_vars.mg_end_min, mcl_vars.mg_end_max}
|
||||
}
|
||||
]]--
|
||||
|
||||
local function decypher_limits(posy)
|
||||
--local min_max_table = decypher_limits_dictionary[dimension]
|
||||
--return min_max_table[1],min_max_table[2]
|
||||
posy = math.floor(posy)
|
||||
return posy - 32, posy + 32
|
||||
end
|
||||
|
||||
--a simple helper function for mob_spawn
|
||||
local function biome_check(biome_list, biome_goal)
|
||||
for _,data in ipairs(biome_list) do
|
||||
if data == biome_goal then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
--todo mob limiting
|
||||
--MAIN LOOP
|
||||
|
||||
if mobs_spawn then
|
||||
local timer = 0
|
||||
minetest.register_globalstep(function(dtime)
|
||||
timer = timer + dtime
|
||||
if timer >= 8 then
|
||||
timer = 0
|
||||
for _,player in pairs(minetest.get_connected_players()) do
|
||||
for i = 1,math_random(3,8) do
|
||||
repeat -- after this line each "break" means "continue"
|
||||
local player_pos = player:get_pos()
|
||||
|
||||
local _,dimension = mcl_worlds.y_to_layer(player_pos.y)
|
||||
|
||||
if dimension == "void" or dimension == "default" then
|
||||
break -- ignore void and unloaded area
|
||||
end
|
||||
|
||||
local min,max = decypher_limits(player_pos.y)
|
||||
|
||||
local goal_pos = position_calculation(player_pos)
|
||||
|
||||
local spawning_position_list = find_nodes_in_area_under_air(new_vector(goal_pos.x,min,goal_pos.z), vector.new(goal_pos.x,max,goal_pos.z), {"group:solid", "group:water", "group:lava"})
|
||||
|
||||
--couldn't find node
|
||||
if #spawning_position_list <= 0 then
|
||||
break
|
||||
end
|
||||
|
||||
local spawning_position = spawning_position_list[math_random(1,#spawning_position_list)]
|
||||
|
||||
--Prevent strange behavior/too close to player
|
||||
if not spawning_position or vector_distance(player_pos, spawning_position) < 15 then
|
||||
break
|
||||
end
|
||||
|
||||
local gotten_node = get_node(spawning_position).name
|
||||
|
||||
if not gotten_node or gotten_node == "air" then --skip air nodes
|
||||
break
|
||||
end
|
||||
|
||||
local gotten_biome = minetest.get_biome_data(spawning_position)
|
||||
|
||||
if not gotten_biome then
|
||||
break --skip if in unloaded area
|
||||
end
|
||||
|
||||
gotten_biome = get_biome_name(gotten_biome.biome) --makes it easier to work with
|
||||
|
||||
--grab random mob
|
||||
local mob_def = spawn_dictionary[math.random(1,#spawn_dictionary)]
|
||||
|
||||
if not mob_def then
|
||||
break --skip if something ridiculous happens (nil mob def)
|
||||
end
|
||||
|
||||
--skip if not correct dimension
|
||||
if mob_def.dimension ~= dimension then
|
||||
break
|
||||
end
|
||||
|
||||
--skip if not in correct biome
|
||||
if not biome_check(mob_def.biomes, gotten_biome) then
|
||||
break
|
||||
end
|
||||
|
||||
--add this so mobs don't spawn inside nodes
|
||||
spawning_position.y = spawning_position.y + 1
|
||||
|
||||
if spawning_position.y < mob_def.min_height or spawning_position.y > mob_def.max_height then
|
||||
break
|
||||
end
|
||||
|
||||
--only need to poll for node light if everything else worked
|
||||
local gotten_light = get_node_light(spawning_position)
|
||||
|
||||
--don't spawn if not in light limits
|
||||
if gotten_light < mob_def.min_light or gotten_light > mob_def.max_light then
|
||||
break
|
||||
end
|
||||
|
||||
local is_water = get_item_group(gotten_node, "water") ~= 0
|
||||
local is_lava = get_item_group(gotten_node, "lava") ~= 0
|
||||
|
||||
if mob_def.type_of_spawning == "ground" and is_water then
|
||||
break
|
||||
end
|
||||
|
||||
if mob_def.type_of_spawning == "ground" and is_lava then
|
||||
break
|
||||
end
|
||||
|
||||
--finally do the heavy check (for now) of mobs in area
|
||||
if count_mobs(spawning_position, mob_def.spawn_class) >= mob_def.aoc then
|
||||
break
|
||||
end
|
||||
|
||||
--adjust the position for water and lava mobs
|
||||
if mob_def.type_of_spawning == "water" or mob_def.type_of_spawning == "lava" then
|
||||
spawning_position.y = spawning_position.y - 1
|
||||
end
|
||||
|
||||
--everything is correct, spawn mob
|
||||
minetest.add_entity(spawning_position, mob_def.name)
|
||||
until true --this is a safety catch
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
|
@ -290,13 +290,13 @@ mobs_mc.spawn = {
|
|||
mobs_mc.spawn_height = {
|
||||
water = tonumber(minetest.settings:get("water_level")) or 0, -- Water level in the Overworld
|
||||
|
||||
-- Overworld boundaries (inclusive)
|
||||
overworld_min = -2999,
|
||||
-- Overworld boundaries (inclusive) --I adjusted this to be more reasonable
|
||||
overworld_min = -64,-- -2999,
|
||||
overworld_max = 31000,
|
||||
|
||||
-- Nether boundaries (inclusive)
|
||||
nether_min = -3369,
|
||||
nether_max = -3000,
|
||||
nether_min = -29067,-- -3369,
|
||||
nether_max = -28939,-- -3000,
|
||||
|
||||
-- End boundaries (inclusive)
|
||||
end_min = -6200,
|
||||
|
|
|
@ -521,7 +521,7 @@ if c("totem") then
|
|||
-- Totem of Undying
|
||||
minetest.register_craftitem("mobs_mc:totem", {
|
||||
description = S("Totem of Undying"),
|
||||
_tt_help = minetest.colorize("#00FF00", S("Protects you from death while wielding it")),
|
||||
_tt_help = minetest.colorize(mcl_colors.GREEN, S("Protects you from death while wielding it")),
|
||||
_doc_items_longdesc = S("A totem of undying is a rare artifact which may safe you from certain death."),
|
||||
_doc_items_usagehelp = S("The totem only works while you hold it in your hand. If you receive fatal damage, you are saved from death and you get a second chance with 1 HP. The totem is destroyed in the process, however."),
|
||||
inventory_image = "mcl_totems_totem.png",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
--###################
|
||||
--################### AGENT
|
||||
--################### AGENT - seemingly unused
|
||||
--###################
|
||||
|
||||
local S = minetest.get_translator("mobs_mc")
|
||||
|
|
|
@ -64,7 +64,81 @@ else
|
|||
end
|
||||
|
||||
-- Spawn on solid blocks at or below Sea level and the selected light level
|
||||
mobs:spawn_specific("mobs_mc:bat", mobs_mc.spawn.solid, {"air"}, 0, maxlight, 20, 5000, 2, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.water-1)
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:bat",
|
||||
"overworld",
|
||||
"ground",
|
||||
{
|
||||
"FlowerForest_underground",
|
||||
"JungleEdge_underground",
|
||||
"StoneBeach_underground",
|
||||
"MesaBryce_underground",
|
||||
"Mesa_underground",
|
||||
"RoofedForest_underground",
|
||||
"Jungle_underground",
|
||||
"Swampland_underground",
|
||||
"MushroomIsland_underground",
|
||||
"BirchForest_underground",
|
||||
"Plains_underground",
|
||||
"MesaPlateauF_underground",
|
||||
"ExtremeHills_underground",
|
||||
"MegaSpruceTaiga_underground",
|
||||
"BirchForestM_underground",
|
||||
"SavannaM_underground",
|
||||
"MesaPlateauFM_underground",
|
||||
"Desert_underground",
|
||||
"Savanna_underground",
|
||||
"Forest_underground",
|
||||
"SunflowerPlains_underground",
|
||||
"ColdTaiga_underground",
|
||||
"IcePlains_underground",
|
||||
"IcePlainsSpikes_underground",
|
||||
"MegaTaiga_underground",
|
||||
"Taiga_underground",
|
||||
"ExtremeHills+_underground",
|
||||
"JungleM_underground",
|
||||
"ExtremeHillsM_underground",
|
||||
"JungleEdgeM_underground",
|
||||
"Mesa",
|
||||
"FlowerForest",
|
||||
"Swampland",
|
||||
"Taiga",
|
||||
"ExtremeHills",
|
||||
"Jungle",
|
||||
"Savanna",
|
||||
"BirchForest",
|
||||
"MegaSpruceTaiga",
|
||||
"MegaTaiga",
|
||||
"ExtremeHills+",
|
||||
"Forest",
|
||||
"Plains",
|
||||
"Desert",
|
||||
"ColdTaiga",
|
||||
"MushroomIsland",
|
||||
"IcePlainsSpikes",
|
||||
"SunflowerPlains",
|
||||
"IcePlains",
|
||||
"RoofedForest",
|
||||
"ExtremeHills+_snowtop",
|
||||
"MesaPlateauFM_grasstop",
|
||||
"JungleEdgeM",
|
||||
"ExtremeHillsM",
|
||||
"JungleM",
|
||||
"BirchForestM",
|
||||
"MesaPlateauF",
|
||||
"MesaPlateauFM",
|
||||
"MesaPlateauF_grasstop",
|
||||
"MesaBryce",
|
||||
"JungleEdge",
|
||||
"SavannaM",
|
||||
},
|
||||
0,
|
||||
maxlight,
|
||||
20,
|
||||
5000,
|
||||
2,
|
||||
mobs_mc.spawn_height.overworld_min,
|
||||
mobs_mc.spawn_height.water-1)
|
||||
|
||||
|
||||
-- spawn eggs
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
-- daufinsyd
|
||||
-- My work is under the LGPL terms
|
||||
-- Model and mobs_blaze.png see https://github.com/22i/minecraft-voxel-blender-models
|
||||
-- Model and mobs_blaze.png see https://github.com/22i/minecraft-voxel-blender-models -hi 22i ~jordan4ibanez
|
||||
-- blaze.lua partial copy of mobs_mc/ghast.lua
|
||||
|
||||
local S = minetest.get_translator("mobs_mc")
|
||||
|
@ -75,9 +75,71 @@ mobs:register_mob("mobs_mc:blaze", {
|
|||
fear_height = 0,
|
||||
glow = 14,
|
||||
fire_resistant = true,
|
||||
do_custom = function(self)
|
||||
if self.state == "attack" and vector.distance(self.object:get_pos(), self.attack:get_pos()) < 1.2 then
|
||||
mcl_burning.set_on_fire(self.attack, 5)
|
||||
end
|
||||
local pos = self.object:get_pos()
|
||||
minetest.add_particle({
|
||||
pos = {x=pos.x+math.random(-0.7,0.7)*math.random()/2,y=pos.y+math.random(0.7,1.2),z=pos.z+math.random(-0.7,0.7)*math.random()/2},
|
||||
velocity = {x=0, y=math.random(1,1), z=0},
|
||||
expirationtime = math.random(),
|
||||
size = math.random(1, 4),
|
||||
collisiondetection = true,
|
||||
vertical = false,
|
||||
texture = "mcl_particles_smoke_anim.png^[colorize:#2c2c2c:255",
|
||||
animation = {
|
||||
type = "vertical_frames",
|
||||
aspect_w = 8,
|
||||
aspect_h = 8,
|
||||
length = 2.05,
|
||||
},
|
||||
})
|
||||
minetest.add_particle({
|
||||
pos = {x=pos.x+math.random(-0.7,0.7)*math.random()/2,y=pos.y+math.random(0.7,1.2),z=pos.z+math.random(-0.7,0.7)*math.random()/2},
|
||||
velocity = {x=0, y=math.random(1,1), z=0},
|
||||
expirationtime = math.random(),
|
||||
size = math.random(1, 4),
|
||||
collisiondetection = true,
|
||||
vertical = false,
|
||||
texture = "mcl_particles_smoke_anim.png^[colorize:#424242:255",
|
||||
animation = {
|
||||
type = "vertical_frames",
|
||||
aspect_w = 8,
|
||||
aspect_h = 8,
|
||||
length = 2.05,
|
||||
},
|
||||
})
|
||||
minetest.add_particle({
|
||||
pos = {x=pos.x+math.random(-0.7,0.7)*math.random()/2,y=pos.y+math.random(0.7,1.2),z=pos.z+math.random(-0.7,0.7)*math.random()/2},
|
||||
velocity = {x=0, y=math.random(1,1), z=0},
|
||||
expirationtime = math.random(),
|
||||
size = math.random(1, 4),
|
||||
collisiondetection = true,
|
||||
vertical = false,
|
||||
texture = "mcl_particles_smoke_anim.png^[colorize:#0f0f0f:255",
|
||||
animation = {
|
||||
type = "vertical_frames",
|
||||
aspect_w = 8,
|
||||
aspect_h = 8,
|
||||
length = 2.05,
|
||||
},
|
||||
})
|
||||
end,
|
||||
})
|
||||
|
||||
mobs:spawn_specific("mobs_mc:blaze", mobs_mc.spawn.nether_fortress, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 5000, 3, mobs_mc.spawn_height.nether_min, mobs_mc.spawn_height.nether_max)
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:blaze",
|
||||
"nether",
|
||||
"ground",
|
||||
{"Nether"},
|
||||
0,
|
||||
minetest.LIGHT_MAX+1,
|
||||
30,
|
||||
5000,
|
||||
3,
|
||||
mobs_mc.spawn_height.nether_min,
|
||||
mobs_mc.spawn_height.nether_max)
|
||||
|
||||
-- Blaze fireball
|
||||
mobs:register_arrow("mobs_mc:blaze_fireball", {
|
||||
|
|
|
@ -100,7 +100,34 @@ mobs:register_mob("mobs_mc:chicken", {
|
|||
})
|
||||
|
||||
--spawn
|
||||
mobs:spawn_specific("mobs_mc:chicken", mobs_mc.spawn.grassland, {"air"}, 9, minetest.LIGHT_MAX+1, 30, 17000, 3, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max)
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:chicken",
|
||||
"overworld",
|
||||
"ground",
|
||||
{
|
||||
"FlowerForest",
|
||||
"Swampland",
|
||||
"Taiga",
|
||||
"ExtremeHills",
|
||||
"BirchForest",
|
||||
"MegaSpruceTaiga",
|
||||
"MegaTaiga",
|
||||
"ExtremeHills+",
|
||||
"Forest",
|
||||
"Plains",
|
||||
"ColdTaiga",
|
||||
"SunflowerPlains",
|
||||
"RoofedForest",
|
||||
"MesaPlateauFM_grasstop",
|
||||
"ExtremeHillsM",
|
||||
"BirchForestM",
|
||||
},
|
||||
9,
|
||||
minetest.LIGHT_MAX+1,
|
||||
30, 17000,
|
||||
3,
|
||||
mobs_mc.spawn_height.water,
|
||||
mobs_mc.spawn_height.overworld_max)
|
||||
|
||||
-- spawn eggs
|
||||
mobs:register_egg("mobs_mc:chicken", S("Chicken"), "mobs_mc_spawn_icon_chicken.png", 0)
|
||||
|
|
|
@ -145,8 +145,53 @@ mobs:register_mob("mobs_mc:mooshroom", mooshroom_def)
|
|||
|
||||
|
||||
-- Spawning
|
||||
mobs:spawn_specific("mobs_mc:cow", mobs_mc.spawn.grassland, {"air"}, 9, minetest.LIGHT_MAX+1, 30, 17000, 10, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max)
|
||||
mobs:spawn_specific("mobs_mc:mooshroom", mobs_mc.spawn.mushroom_island, {"air"}, 9, minetest.LIGHT_MAX+1, 30, 17000, 5, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max)
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:cow",
|
||||
"overworld",
|
||||
"ground",
|
||||
{
|
||||
"FlowerForest",
|
||||
"Swampland",
|
||||
"Taiga",
|
||||
"ExtremeHills",
|
||||
"BirchForest",
|
||||
"MegaSpruceTaiga",
|
||||
"MegaTaiga",
|
||||
"ExtremeHills+",
|
||||
"Forest",
|
||||
"Plains",
|
||||
"ColdTaiga",
|
||||
"SunflowerPlains",
|
||||
"RoofedForest",
|
||||
"MesaPlateauFM_grasstop",
|
||||
"ExtremeHillsM",
|
||||
"BirchForestM",
|
||||
},
|
||||
9,
|
||||
minetest.LIGHT_MAX+1,
|
||||
30,
|
||||
17000,
|
||||
10,
|
||||
mobs_mc.spawn_height.water,
|
||||
mobs_mc.spawn_height.overworld_max)
|
||||
|
||||
|
||||
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:mooshroom",
|
||||
"overworld",
|
||||
"ground",
|
||||
{
|
||||
"MushroomIslandShore",
|
||||
"MushroomIsland"
|
||||
},
|
||||
9,
|
||||
minetest.LIGHT_MAX+1,
|
||||
30,
|
||||
17000,
|
||||
5,
|
||||
mobs_mc.spawn_height.overworld_min,
|
||||
mobs_mc.spawn_height.overworld_max)
|
||||
|
||||
-- spawn egg
|
||||
mobs:register_egg("mobs_mc:cow", S("Cow"), "mobs_mc_spawn_icon_cow.png", 0)
|
||||
|
|
|
@ -39,6 +39,8 @@ mobs:register_mob("mobs_mc:creeper", {
|
|||
runaway_from = { "mobs_mc:ocelot", "mobs_mc:cat" },
|
||||
attack_type = "explode",
|
||||
|
||||
--hssssssssssss
|
||||
|
||||
explosion_strength = 3,
|
||||
explosion_radius = 3.5,
|
||||
explosion_damage_radius = 3.5,
|
||||
|
@ -76,7 +78,6 @@ mobs:register_mob("mobs_mc:creeper", {
|
|||
self._forced_explosion_countdown_timer = self._forced_explosion_countdown_timer - dtime
|
||||
if self._forced_explosion_countdown_timer <= 0 then
|
||||
mobs:boom(self, mcl_util.get_object_center(self.object), self.explosion_strength)
|
||||
self.object:remove()
|
||||
end
|
||||
end
|
||||
end,
|
||||
|
@ -139,6 +140,9 @@ mobs:register_mob("mobs_mc:creeper_charged", {
|
|||
pathfinding = 1,
|
||||
visual = "mesh",
|
||||
mesh = "mobs_mc_creeper.b3d",
|
||||
|
||||
--BOOM
|
||||
|
||||
textures = {
|
||||
{"mobs_mc_creeper.png",
|
||||
"mobs_mc_creeper_charge.png"},
|
||||
|
@ -195,7 +199,6 @@ mobs:register_mob("mobs_mc:creeper_charged", {
|
|||
self._forced_explosion_countdown_timer = self._forced_explosion_countdown_timer - dtime
|
||||
if self._forced_explosion_countdown_timer <= 0 then
|
||||
mobs:boom(self, mcl_util.get_object_center(self.object), self.explosion_strength)
|
||||
self.object:remove()
|
||||
end
|
||||
end
|
||||
end,
|
||||
|
@ -250,7 +253,158 @@ mobs:register_mob("mobs_mc:creeper_charged", {
|
|||
glow = 3,
|
||||
})
|
||||
|
||||
mobs:spawn_specific("mobs_mc:creeper", mobs_mc.spawn.solid, {"air"}, 0, 7, 20, 16500, 2, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max)
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:creeper",
|
||||
"overworld",
|
||||
"ground",
|
||||
{
|
||||
"Mesa",
|
||||
"FlowerForest",
|
||||
"Swampland",
|
||||
"Taiga",
|
||||
"ExtremeHills",
|
||||
"Jungle",
|
||||
"Savanna",
|
||||
"BirchForest",
|
||||
"MegaSpruceTaiga",
|
||||
"MegaTaiga",
|
||||
"ExtremeHills+",
|
||||
"Forest",
|
||||
"Plains",
|
||||
"Desert",
|
||||
"ColdTaiga",
|
||||
"MushroomIsland",
|
||||
"IcePlainsSpikes",
|
||||
"SunflowerPlains",
|
||||
"IcePlains",
|
||||
"RoofedForest",
|
||||
"ExtremeHills+_snowtop",
|
||||
"MesaPlateauFM_grasstop",
|
||||
"JungleEdgeM",
|
||||
"ExtremeHillsM",
|
||||
"JungleM",
|
||||
"BirchForestM",
|
||||
"MesaPlateauF",
|
||||
"MesaPlateauFM",
|
||||
"MesaPlateauF_grasstop",
|
||||
"MesaBryce",
|
||||
"JungleEdge",
|
||||
"SavannaM",
|
||||
"FlowerForest_beach",
|
||||
"Forest_beach",
|
||||
"StoneBeach",
|
||||
"ColdTaiga_beach_water",
|
||||
"Taiga_beach",
|
||||
"Savanna_beach",
|
||||
"Plains_beach",
|
||||
"ExtremeHills_beach",
|
||||
"ColdTaiga_beach",
|
||||
"Swampland_shore",
|
||||
"MushroomIslandShore",
|
||||
"JungleM_shore",
|
||||
"Jungle_shore",
|
||||
"MesaPlateauFM_sandlevel",
|
||||
"MesaPlateauF_sandlevel",
|
||||
"MesaBryce_sandlevel",
|
||||
"Mesa_sandlevel",
|
||||
"RoofedForest_ocean",
|
||||
"JungleEdgeM_ocean",
|
||||
"BirchForestM_ocean",
|
||||
"BirchForest_ocean",
|
||||
"IcePlains_deep_ocean",
|
||||
"Jungle_deep_ocean",
|
||||
"Savanna_ocean",
|
||||
"MesaPlateauF_ocean",
|
||||
"ExtremeHillsM_deep_ocean",
|
||||
"Savanna_deep_ocean",
|
||||
"SunflowerPlains_ocean",
|
||||
"Swampland_deep_ocean",
|
||||
"Swampland_ocean",
|
||||
"MegaSpruceTaiga_deep_ocean",
|
||||
"ExtremeHillsM_ocean",
|
||||
"JungleEdgeM_deep_ocean",
|
||||
"SunflowerPlains_deep_ocean",
|
||||
"BirchForest_deep_ocean",
|
||||
"IcePlainsSpikes_ocean",
|
||||
"Mesa_ocean",
|
||||
"StoneBeach_ocean",
|
||||
"Plains_deep_ocean",
|
||||
"JungleEdge_deep_ocean",
|
||||
"SavannaM_deep_ocean",
|
||||
"Desert_deep_ocean",
|
||||
"Mesa_deep_ocean",
|
||||
"ColdTaiga_deep_ocean",
|
||||
"Plains_ocean",
|
||||
"MesaPlateauFM_ocean",
|
||||
"Forest_deep_ocean",
|
||||
"JungleM_deep_ocean",
|
||||
"FlowerForest_deep_ocean",
|
||||
"MushroomIsland_ocean",
|
||||
"MegaTaiga_ocean",
|
||||
"StoneBeach_deep_ocean",
|
||||
"IcePlainsSpikes_deep_ocean",
|
||||
"ColdTaiga_ocean",
|
||||
"SavannaM_ocean",
|
||||
"MesaPlateauF_deep_ocean",
|
||||
"MesaBryce_deep_ocean",
|
||||
"ExtremeHills+_deep_ocean",
|
||||
"ExtremeHills_ocean",
|
||||
"MushroomIsland_deep_ocean",
|
||||
"Forest_ocean",
|
||||
"MegaTaiga_deep_ocean",
|
||||
"JungleEdge_ocean",
|
||||
"MesaBryce_ocean",
|
||||
"MegaSpruceTaiga_ocean",
|
||||
"ExtremeHills+_ocean",
|
||||
"Jungle_ocean",
|
||||
"RoofedForest_deep_ocean",
|
||||
"IcePlains_ocean",
|
||||
"FlowerForest_ocean",
|
||||
"ExtremeHills_deep_ocean",
|
||||
"MesaPlateauFM_deep_ocean",
|
||||
"Desert_ocean",
|
||||
"Taiga_ocean",
|
||||
"BirchForestM_deep_ocean",
|
||||
"Taiga_deep_ocean",
|
||||
"JungleM_ocean",
|
||||
"FlowerForest_underground",
|
||||
"JungleEdge_underground",
|
||||
"StoneBeach_underground",
|
||||
"MesaBryce_underground",
|
||||
"Mesa_underground",
|
||||
"RoofedForest_underground",
|
||||
"Jungle_underground",
|
||||
"Swampland_underground",
|
||||
"MushroomIsland_underground",
|
||||
"BirchForest_underground",
|
||||
"Plains_underground",
|
||||
"MesaPlateauF_underground",
|
||||
"ExtremeHills_underground",
|
||||
"MegaSpruceTaiga_underground",
|
||||
"BirchForestM_underground",
|
||||
"SavannaM_underground",
|
||||
"MesaPlateauFM_underground",
|
||||
"Desert_underground",
|
||||
"Savanna_underground",
|
||||
"Forest_underground",
|
||||
"SunflowerPlains_underground",
|
||||
"ColdTaiga_underground",
|
||||
"IcePlains_underground",
|
||||
"IcePlainsSpikes_underground",
|
||||
"MegaTaiga_underground",
|
||||
"Taiga_underground",
|
||||
"ExtremeHills+_underground",
|
||||
"JungleM_underground",
|
||||
"ExtremeHillsM_underground",
|
||||
"JungleEdgeM_underground",
|
||||
},
|
||||
0,
|
||||
7,
|
||||
20,
|
||||
16500,
|
||||
2,
|
||||
mobs_mc.spawn_height.overworld_min,
|
||||
mobs_mc.spawn_height.overworld_max)
|
||||
|
||||
-- spawn eggs
|
||||
mobs:register_egg("mobs_mc:creeper", S("Creeper"), "mobs_mc_spawn_icon_creeper.png", 0)
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
mcl_mobs
|
|
@ -50,8 +50,8 @@ mobs:register_mob("mobs_mc:enderdragon", {
|
|||
arrow = "mobs_mc:dragon_fireball",
|
||||
shoot_interval = 0.5,
|
||||
shoot_offset = -1.0,
|
||||
xp_min = 12000,
|
||||
xp_max = 12000,
|
||||
xp_min = 500,
|
||||
xp_max = 500,
|
||||
animation = {
|
||||
fly_speed = 8, stand_speed = 8,
|
||||
stand_start = 0, stand_end = 20,
|
||||
|
@ -59,15 +59,47 @@ mobs:register_mob("mobs_mc:enderdragon", {
|
|||
run_start = 0, run_end = 20,
|
||||
},
|
||||
ignores_nametag = true,
|
||||
on_die = function(self, own_pos)
|
||||
if self._egg_spawn_pos then
|
||||
local pos = minetest.string_to_pos(self._egg_spawn_pos)
|
||||
--if minetest.get_node(pos).buildable_to then
|
||||
minetest.set_node(pos, {name = mobs_mc.items.dragon_egg})
|
||||
return
|
||||
--end
|
||||
do_custom = function(self)
|
||||
mcl_bossbars.update_boss(self, "Ender Dragon", "light_purple")
|
||||
for _, obj in ipairs(minetest.get_objects_inside_radius(self.object:get_pos(), 80)) do
|
||||
local luaentity = obj:get_luaentity()
|
||||
if luaentity and luaentity.name == "mcl_end:crystal" then
|
||||
if luaentity.beam then
|
||||
if luaentity.beam == self.beam then
|
||||
break
|
||||
end
|
||||
else
|
||||
if self.beam then
|
||||
self.beam:remove()
|
||||
end
|
||||
minetest.add_entity(self.object:get_pos(), "mcl_end:crystal_beam"):get_luaentity():init(self.object, obj)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
if self._portal_pos then
|
||||
-- migrate old format
|
||||
if type(self._portal_pos) == "string" then
|
||||
self._portal_pos = minetest.string_to_pos(self._portal_pos)
|
||||
end
|
||||
local portal_center = vector.add(self._portal_pos, vector.new(3, 11, 3))
|
||||
local pos = self.object:get_pos()
|
||||
if vector.distance(pos, portal_center) > 50 then
|
||||
self.object:set_pos(self._last_good_pos or portal_center)
|
||||
else
|
||||
self._last_good_pos = pos
|
||||
end
|
||||
end
|
||||
end,
|
||||
on_die = function(self, pos)
|
||||
if self._portal_pos then
|
||||
mcl_portals.spawn_gateway_portal()
|
||||
mcl_structures.call_struct(self._portal_pos, "end_exit_portal_open")
|
||||
if self._initial then
|
||||
mcl_experience.throw_experience(pos, 11500) -- 500 + 11500 = 12000
|
||||
minetest.set_node(vector.add(self._portal_pos, vector.new(3, 5, 3)), {name = mobs_mc.items.dragon_egg})
|
||||
end
|
||||
end
|
||||
minetest.add_item(own_pos, mobs_mc.items.dragon_egg)
|
||||
end,
|
||||
fire_resistant = true,
|
||||
})
|
||||
|
|
|
@ -295,7 +295,8 @@ mobs:register_mob("mobs_mc:enderman", {
|
|||
-- ARROW / DAYTIME PEOPLE AVOIDANCE BEHAVIOUR HERE.
|
||||
-- Check for arrows and people nearby.
|
||||
local enderpos = self.object:get_pos()
|
||||
local objs = minetest.get_objects_inside_radius(enderpos, 4)
|
||||
enderpos.y = enderpos.y + 1.5
|
||||
local objs = minetest.get_objects_inside_radius(enderpos, 2)
|
||||
for n = 1, #objs do
|
||||
local obj = objs[n]
|
||||
if obj then
|
||||
|
@ -307,7 +308,7 @@ mobs:register_mob("mobs_mc:enderman", {
|
|||
else
|
||||
local lua = obj:get_luaentity()
|
||||
if lua then
|
||||
if lua.name == "mcl_bows:arrow_entity" then
|
||||
if lua.name == "mcl_bows:arrow_entity" or lua.name == "mcl_throwing:snowball_entity" then
|
||||
self:teleport(nil)
|
||||
end
|
||||
end
|
||||
|
@ -328,35 +329,44 @@ mobs:register_mob("mobs_mc:enderman", {
|
|||
--end
|
||||
end
|
||||
-- Check to see if people are near by enough to look at us.
|
||||
local objs = minetest.get_objects_inside_radius(enderpos, 64)
|
||||
local obj
|
||||
for n = 1, #objs do
|
||||
obj = objs[n]
|
||||
if obj then
|
||||
if minetest.is_player(obj) then
|
||||
for _,obj in pairs(minetest.get_connected_players()) do
|
||||
|
||||
--check if they are within radius
|
||||
local player_pos = obj:get_pos()
|
||||
if player_pos then -- prevent crashing in 1 in a million scenario
|
||||
|
||||
local ender_distance = vector.distance(enderpos, player_pos)
|
||||
if ender_distance <= 64 then
|
||||
|
||||
-- Check if they are looking at us.
|
||||
local player_pos = obj:get_pos()
|
||||
local look_dir_not_normalized = obj:get_look_dir()
|
||||
local look_dir = vector.normalize(look_dir_not_normalized)
|
||||
local look_pos = vector.new({x = look_dir.x+player_pos.x, y = look_dir.y+player_pos.y + 1.5, z = look_dir.z+player_pos.z}) -- Arbitrary value (1.5) is head level according to player info mod.
|
||||
-- Cast up to 64 to see if player is looking at enderman.
|
||||
for n = 1,64,.25 do
|
||||
local node = minetest.get_node(look_pos)
|
||||
if node.name ~= "air" then
|
||||
break
|
||||
end
|
||||
if look_pos.x-1<enderpos.x and look_pos.x+1>enderpos.x and look_pos.y-2.89<enderpos.y and look_pos.y-2>enderpos.y and look_pos.z-1<enderpos.z and look_pos.z+1>enderpos.z then
|
||||
local player_eye_height = obj:get_properties().eye_height
|
||||
|
||||
--skip player if they have no data - log it
|
||||
if not player_eye_height then
|
||||
minetest.log("error", "Enderman at location: ".. dump(enderpos).." has indexed a null player!")
|
||||
else
|
||||
|
||||
--calculate very quickly the exact location the player is looking
|
||||
--within the distance between the two "heads" (player and enderman)
|
||||
local look_pos = vector.new(player_pos.x, player_pos.y + player_eye_height, player_pos.z)
|
||||
local look_pos_base = look_pos
|
||||
local ender_eye_pos = vector.new(enderpos.x, enderpos.y + 2.75, enderpos.z)
|
||||
local eye_distance_from_player = vector.distance(ender_eye_pos, look_pos)
|
||||
look_pos = vector.add(look_pos, vector.multiply(look_dir, eye_distance_from_player))
|
||||
|
||||
--if looking in general head position, turn hostile
|
||||
if minetest.line_of_sight(ender_eye_pos, look_pos_base) and vector.distance(look_pos, ender_eye_pos) <= 0.4 then
|
||||
self.provoked = "staring"
|
||||
self.attack = minetest.get_player_by_name(obj:get_player_name())
|
||||
break
|
||||
else
|
||||
else -- I'm not sure what this part does, but I don't want to break anything - jordan4ibanez
|
||||
if self.provoked == "staring" then
|
||||
self.provoked = "broke_contact"
|
||||
end
|
||||
end
|
||||
end
|
||||
look_pos.x = look_pos.x + (.25 * look_dir.x)
|
||||
look_pos.y = look_pos.y + (.25 * look_dir.y)
|
||||
look_pos.z = look_pos.z + (.25 * look_dir.z)
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -534,9 +544,11 @@ mobs:register_mob("mobs_mc:enderman", {
|
|||
--if (minetest.get_timeofday() * 24000) > 5001 and (minetest.get_timeofday() * 24000) < 19000 then
|
||||
-- self:teleport(nil)
|
||||
--else
|
||||
if pr:next(1, 8) == 8 then --FIXME: real mc rate
|
||||
self:teleport(hitter)
|
||||
self.attack=hitter
|
||||
self.state="attack"
|
||||
end
|
||||
self.attack=hitter
|
||||
self.state="attack"
|
||||
--end
|
||||
end
|
||||
end,
|
||||
|
@ -549,11 +561,189 @@ mobs:register_mob("mobs_mc:enderman", {
|
|||
|
||||
|
||||
-- End spawn
|
||||
mobs:spawn_specific("mobs_mc:enderman", mobs_mc.spawn.solid, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 3000, 12, mobs_mc.spawn_height.end_min, mobs_mc.spawn_height.end_max)
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:enderman",
|
||||
"end",
|
||||
"ground",
|
||||
{
|
||||
"End"
|
||||
},
|
||||
0,
|
||||
minetest.LIGHT_MAX+1,
|
||||
30,
|
||||
3000,
|
||||
12,
|
||||
mobs_mc.spawn_height.end_min,
|
||||
mobs_mc.spawn_height.end_max)
|
||||
-- Overworld spawn
|
||||
mobs:spawn_specific("mobs_mc:enderman", mobs_mc.spawn.solid, {"air"}, 0, 7, 30, 19000, 2, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max)
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:enderman",
|
||||
"overworld",
|
||||
"ground",
|
||||
{
|
||||
"Mesa",
|
||||
"FlowerForest",
|
||||
"Swampland",
|
||||
"Taiga",
|
||||
"ExtremeHills",
|
||||
"Jungle",
|
||||
"Savanna",
|
||||
"BirchForest",
|
||||
"MegaSpruceTaiga",
|
||||
"MegaTaiga",
|
||||
"ExtremeHills+",
|
||||
"Forest",
|
||||
"Plains",
|
||||
"Desert",
|
||||
"ColdTaiga",
|
||||
"MushroomIsland",
|
||||
"IcePlainsSpikes",
|
||||
"SunflowerPlains",
|
||||
"IcePlains",
|
||||
"RoofedForest",
|
||||
"ExtremeHills+_snowtop",
|
||||
"MesaPlateauFM_grasstop",
|
||||
"JungleEdgeM",
|
||||
"ExtremeHillsM",
|
||||
"JungleM",
|
||||
"BirchForestM",
|
||||
"MesaPlateauF",
|
||||
"MesaPlateauFM",
|
||||
"MesaPlateauF_grasstop",
|
||||
"MesaBryce",
|
||||
"JungleEdge",
|
||||
"SavannaM",
|
||||
"FlowerForest_beach",
|
||||
"Forest_beach",
|
||||
"StoneBeach",
|
||||
"ColdTaiga_beach_water",
|
||||
"Taiga_beach",
|
||||
"Savanna_beach",
|
||||
"Plains_beach",
|
||||
"ExtremeHills_beach",
|
||||
"ColdTaiga_beach",
|
||||
"Swampland_shore",
|
||||
"MushroomIslandShore",
|
||||
"JungleM_shore",
|
||||
"Jungle_shore",
|
||||
"MesaPlateauFM_sandlevel",
|
||||
"MesaPlateauF_sandlevel",
|
||||
"MesaBryce_sandlevel",
|
||||
"Mesa_sandlevel",
|
||||
"RoofedForest_ocean",
|
||||
"JungleEdgeM_ocean",
|
||||
"BirchForestM_ocean",
|
||||
"BirchForest_ocean",
|
||||
"IcePlains_deep_ocean",
|
||||
"Jungle_deep_ocean",
|
||||
"Savanna_ocean",
|
||||
"MesaPlateauF_ocean",
|
||||
"ExtremeHillsM_deep_ocean",
|
||||
"Savanna_deep_ocean",
|
||||
"SunflowerPlains_ocean",
|
||||
"Swampland_deep_ocean",
|
||||
"Swampland_ocean",
|
||||
"MegaSpruceTaiga_deep_ocean",
|
||||
"ExtremeHillsM_ocean",
|
||||
"JungleEdgeM_deep_ocean",
|
||||
"SunflowerPlains_deep_ocean",
|
||||
"BirchForest_deep_ocean",
|
||||
"IcePlainsSpikes_ocean",
|
||||
"Mesa_ocean",
|
||||
"StoneBeach_ocean",
|
||||
"Plains_deep_ocean",
|
||||
"JungleEdge_deep_ocean",
|
||||
"SavannaM_deep_ocean",
|
||||
"Desert_deep_ocean",
|
||||
"Mesa_deep_ocean",
|
||||
"ColdTaiga_deep_ocean",
|
||||
"Plains_ocean",
|
||||
"MesaPlateauFM_ocean",
|
||||
"Forest_deep_ocean",
|
||||
"JungleM_deep_ocean",
|
||||
"FlowerForest_deep_ocean",
|
||||
"MushroomIsland_ocean",
|
||||
"MegaTaiga_ocean",
|
||||
"StoneBeach_deep_ocean",
|
||||
"IcePlainsSpikes_deep_ocean",
|
||||
"ColdTaiga_ocean",
|
||||
"SavannaM_ocean",
|
||||
"MesaPlateauF_deep_ocean",
|
||||
"MesaBryce_deep_ocean",
|
||||
"ExtremeHills+_deep_ocean",
|
||||
"ExtremeHills_ocean",
|
||||
"MushroomIsland_deep_ocean",
|
||||
"Forest_ocean",
|
||||
"MegaTaiga_deep_ocean",
|
||||
"JungleEdge_ocean",
|
||||
"MesaBryce_ocean",
|
||||
"MegaSpruceTaiga_ocean",
|
||||
"ExtremeHills+_ocean",
|
||||
"Jungle_ocean",
|
||||
"RoofedForest_deep_ocean",
|
||||
"IcePlains_ocean",
|
||||
"FlowerForest_ocean",
|
||||
"ExtremeHills_deep_ocean",
|
||||
"MesaPlateauFM_deep_ocean",
|
||||
"Desert_ocean",
|
||||
"Taiga_ocean",
|
||||
"BirchForestM_deep_ocean",
|
||||
"Taiga_deep_ocean",
|
||||
"JungleM_ocean",
|
||||
"FlowerForest_underground",
|
||||
"JungleEdge_underground",
|
||||
"StoneBeach_underground",
|
||||
"MesaBryce_underground",
|
||||
"Mesa_underground",
|
||||
"RoofedForest_underground",
|
||||
"Jungle_underground",
|
||||
"Swampland_underground",
|
||||
"MushroomIsland_underground",
|
||||
"BirchForest_underground",
|
||||
"Plains_underground",
|
||||
"MesaPlateauF_underground",
|
||||
"ExtremeHills_underground",
|
||||
"MegaSpruceTaiga_underground",
|
||||
"BirchForestM_underground",
|
||||
"SavannaM_underground",
|
||||
"MesaPlateauFM_underground",
|
||||
"Desert_underground",
|
||||
"Savanna_underground",
|
||||
"Forest_underground",
|
||||
"SunflowerPlains_underground",
|
||||
"ColdTaiga_underground",
|
||||
"IcePlains_underground",
|
||||
"IcePlainsSpikes_underground",
|
||||
"MegaTaiga_underground",
|
||||
"Taiga_underground",
|
||||
"ExtremeHills+_underground",
|
||||
"JungleM_underground",
|
||||
"ExtremeHillsM_underground",
|
||||
"JungleEdgeM_underground",
|
||||
},
|
||||
0,
|
||||
7,
|
||||
30,
|
||||
19000,
|
||||
2,
|
||||
mobs_mc.spawn_height.overworld_min,
|
||||
mobs_mc.spawn_height.overworld_max)
|
||||
|
||||
-- Nether spawn (rare)
|
||||
mobs:spawn_specific("mobs_mc:enderman", mobs_mc.spawn.solid, {"air"}, 0, 7, 30, 27500, 4, mobs_mc.spawn_height.nether_min, mobs_mc.spawn_height.nether_max)
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:enderman",
|
||||
"nether",
|
||||
"ground",
|
||||
{
|
||||
"Nether"
|
||||
},
|
||||
0,
|
||||
7,
|
||||
30,
|
||||
27500,
|
||||
4,
|
||||
mobs_mc.spawn_height.nether_min,
|
||||
mobs_mc.spawn_height.nether_max)
|
||||
|
||||
-- spawn eggs
|
||||
mobs:register_egg("mobs_mc:enderman", S("Enderman"), "mobs_mc_spawn_icon_enderman.png", 0)
|
||||
|
|
|
@ -63,10 +63,32 @@ mobs:register_mob("mobs_mc:ghast", {
|
|||
makes_footstep_sound = false,
|
||||
instant_death = true,
|
||||
fire_resistant = true,
|
||||
do_custom = function(self)
|
||||
if self.firing == true then
|
||||
self.base_texture = {"mobs_mc_ghast_firing.png"}
|
||||
self.object:set_properties({textures=self.base_texture})
|
||||
else
|
||||
self.base_texture = {"mobs_mc_ghast.png"}
|
||||
self.object:set_properties({textures=self.base_texture})
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
|
||||
mobs:spawn_specific("mobs_mc:ghast", mobs_mc.spawn.nether, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 18000, 2, mobs_mc.spawn_height.nether_min, mobs_mc.spawn_height.nether_max)
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:ghast",
|
||||
"nether",
|
||||
"ground",
|
||||
{
|
||||
"Nether"
|
||||
},
|
||||
0,
|
||||
minetest.LIGHT_MAX+1,
|
||||
30,
|
||||
18000,
|
||||
2,
|
||||
mobs_mc.spawn_height.nether_min,
|
||||
mobs_mc.spawn_height.nether_max)
|
||||
|
||||
-- fireball (projectile)
|
||||
mobs:register_arrow("mobs_mc:fireball", {
|
||||
|
@ -74,6 +96,7 @@ mobs:register_arrow("mobs_mc:fireball", {
|
|||
visual_size = {x = 1, y = 1},
|
||||
textures = {"mcl_fire_fire_charge.png"},
|
||||
velocity = 15,
|
||||
collisionbox = {-.5, -.5, -.5, .5, .5, .5},
|
||||
|
||||
hit_player = function(self, player)
|
||||
if rawget(_G, "armor") and armor.last_damage_types then
|
||||
|
|
|
@ -106,7 +106,7 @@ mobs:register_mob("mobs_mc:guardian_elder", {
|
|||
view_range = 16,
|
||||
})
|
||||
|
||||
-- Spawning disabled due to size issues
|
||||
-- Spawning disabled due to size issues <- what do you mean? -j4i
|
||||
-- TODO: Re-enable spawning
|
||||
-- mobs:spawn_specific("mobs_mc:guardian_elder", mobs_mc.spawn.water, mobs_mc.spawn_water, 0, minetest.LIGHT_MAX+1, 30, 40000, 2, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.water-18)
|
||||
|
||||
|
|
|
@ -157,8 +157,29 @@ local horse = {
|
|||
self._regentimer = 0
|
||||
end
|
||||
|
||||
-- if driver present allow control of horse
|
||||
if self.driver then
|
||||
-- Some weird human is riding. Buck them off?
|
||||
if self.driver and not self.tamed and self.buck_off_time <= 0 then
|
||||
if math.random() < 0.2 then
|
||||
mobs.detach(self.driver, {x = 1, y = 0, z = 1})
|
||||
-- TODO bucking animation
|
||||
else
|
||||
-- Nah, can't be bothered. Think about it again in one second
|
||||
self.buck_off_time = 20
|
||||
end
|
||||
end
|
||||
|
||||
-- Tick the timer for trying to buck the player off
|
||||
if self.buck_off_time then
|
||||
if self.driver then
|
||||
self.buck_off_time = self.buck_off_time - 1
|
||||
else
|
||||
-- Player isn't riding anymore so no need to count
|
||||
self.buck_off_time = nil
|
||||
end
|
||||
end
|
||||
|
||||
-- if driver present and horse has a saddle allow control of horse
|
||||
if self.driver and self._saddle then
|
||||
|
||||
mobs.drive(self, "walk", "stand", false, dtime)
|
||||
|
||||
|
@ -191,6 +212,49 @@ local horse = {
|
|||
local item = clicker:get_wielded_item()
|
||||
local iname = item:get_name()
|
||||
local heal = 0
|
||||
|
||||
-- Taming
|
||||
self.temper = self.temper or (math.random(1,100))
|
||||
|
||||
if not self.tamed then
|
||||
local temper_increase = 0
|
||||
|
||||
-- Feeding, intentionally not using mobs:feed_tame because horse taming is
|
||||
-- different and more complicated
|
||||
if (iname == mobs_mc.items.sugar) then
|
||||
temper_increase = 3
|
||||
elseif (iname == mobs_mc.items.wheat) then
|
||||
temper_increase = 3
|
||||
elseif (iname == mobs_mc.items.apple) then
|
||||
temper_increase = 3
|
||||
elseif (iname == mobs_mc.items.golden_carrot) then
|
||||
temper_increase = 5
|
||||
elseif (iname == mobs_mc.items.golden_apple) then
|
||||
temper_increase = 10
|
||||
-- Trying to ride
|
||||
elseif not self.driver then
|
||||
self.object:set_properties({stepheight = 1.1})
|
||||
mobs.attach(self, clicker)
|
||||
self.buck_off_time = 40 -- TODO how long does it take in minecraft?
|
||||
if self.temper > 100 then
|
||||
self.tamed = true -- NOTE taming can only be finished by riding the horse
|
||||
if not self.owner or self.owner == "" then
|
||||
self.owner = clicker:get_player_name()
|
||||
end
|
||||
end
|
||||
temper_increase = 5
|
||||
|
||||
-- Clicking on the horse while riding ==> unmount
|
||||
elseif self.driver and self.driver == clicker then
|
||||
mobs.detach(clicker, {x = 1, y = 0, z = 1})
|
||||
end
|
||||
|
||||
-- If nothing happened temper_increase = 0 and addition does nothing
|
||||
self.temper = self.temper + temper_increase
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
if can_breed(self.name) then
|
||||
-- Breed horse with golden apple or golden carrot
|
||||
if (iname == mobs_mc.items.golden_apple) then
|
||||
|
@ -202,7 +266,8 @@ local horse = {
|
|||
return
|
||||
end
|
||||
end
|
||||
-- Feed/tame with anything else
|
||||
-- Feed with anything else
|
||||
-- TODO heal amounts don't work
|
||||
if (iname == mobs_mc.items.sugar) then
|
||||
heal = 1
|
||||
elseif (iname == mobs_mc.items.wheat) then
|
||||
|
@ -212,7 +277,7 @@ local horse = {
|
|||
elseif (iname == mobs_mc.items.hay_bale) then
|
||||
heal = 20
|
||||
end
|
||||
if heal > 0 and mobs:feed_tame(self, clicker, heal, false, true) then
|
||||
if heal > 0 and mobs:feed_tame(self, clicker, heal, false, false) then
|
||||
return
|
||||
end
|
||||
|
||||
|
@ -445,8 +510,56 @@ mobs:register_mob("mobs_mc:mule", mule)
|
|||
|
||||
--===========================
|
||||
--Spawn Function
|
||||
mobs:spawn_specific("mobs_mc:horse", mobs_mc.spawn.grassland_savanna, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 15000, 4, mobs_mc.spawn_height.water+3, mobs_mc.spawn_height.overworld_max)
|
||||
mobs:spawn_specific("mobs_mc:donkey", mobs_mc.spawn.grassland_savanna, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 15000, 4, mobs_mc.spawn_height.water+3, mobs_mc.spawn_height.overworld_max)
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:horse",
|
||||
"overworld",
|
||||
"ground",
|
||||
{
|
||||
"FlowerForest",
|
||||
"Swampland",
|
||||
"Taiga",
|
||||
"ExtremeHills",
|
||||
"BirchForest",
|
||||
"MegaSpruceTaiga",
|
||||
"MegaTaiga",
|
||||
"ExtremeHills+",
|
||||
"Forest",
|
||||
"Plains",
|
||||
"ColdTaiga",
|
||||
"SunflowerPlains",
|
||||
"RoofedForest",
|
||||
"MesaPlateauFM_grasstop",
|
||||
"ExtremeHillsM",
|
||||
"BirchForestM",
|
||||
},
|
||||
0,
|
||||
minetest.LIGHT_MAX+1,
|
||||
30,
|
||||
15000,
|
||||
4,
|
||||
mobs_mc.spawn_height.water+3,
|
||||
mobs_mc.spawn_height.overworld_max)
|
||||
|
||||
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:donkey",
|
||||
"overworld",
|
||||
"ground",
|
||||
{
|
||||
"Mesa",
|
||||
"MesaPlateauFM_grasstop",
|
||||
"MesaPlateauF",
|
||||
"MesaPlateauFM",
|
||||
"MesaPlateauF_grasstop",
|
||||
"MesaBryce",
|
||||
},
|
||||
0,
|
||||
minetest.LIGHT_MAX+1,
|
||||
30,
|
||||
15000,
|
||||
4,
|
||||
mobs_mc.spawn_height.water+3,
|
||||
mobs_mc.spawn_height.overworld_max)
|
||||
|
||||
-- spawn eggs
|
||||
mobs:register_egg("mobs_mc:horse", S("Horse"), "mobs_mc_spawn_icon_horse.png", 0)
|
||||
|
|
|
@ -217,7 +217,25 @@ mobs:register_mob("mobs_mc:llama", {
|
|||
})
|
||||
|
||||
--spawn
|
||||
mobs:spawn_specific("mobs_mc:llama", mobs_mc.spawn.savanna, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 15000, 5, mobs_mc.spawn_height.water+15, mobs_mc.spawn_height.overworld_max)
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:llama",
|
||||
"overworld",
|
||||
"ground",
|
||||
{
|
||||
"Mesa",
|
||||
"MesaPlateauFM_grasstop",
|
||||
"MesaPlateauF",
|
||||
"MesaPlateauFM",
|
||||
"MesaPlateauF_grasstop",
|
||||
"MesaBryce",
|
||||
},
|
||||
0,
|
||||
minetest.LIGHT_MAX+1,
|
||||
30,
|
||||
15000,
|
||||
5,
|
||||
mobs_mc.spawn_height.water+15,
|
||||
mobs_mc.spawn_height.overworld_max)
|
||||
|
||||
-- spawn eggs
|
||||
mobs:register_egg("mobs_mc:llama", S("Llama"), "mobs_mc_spawn_icon_llama.png", 0)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
name = mobs_mc
|
||||
author = maikerumine
|
||||
description = Adds Minecraft-like monsters and animals.
|
||||
depends = mcl_init, mcl_particles, mcl_mobs, mcl_wip
|
||||
depends = mcl_init, mcl_particles, mcl_mobs, mcl_wip, mcl_colors
|
||||
optional_depends = default, mcl_tnt, mcl_bows, mcl_throwing, mcl_fishing, bones, mesecons_materials, mobs_mc_gameconfig, doc_items
|
||||
|
||||
|
|
|
@ -152,6 +152,25 @@ mobs:register_mob("mobs_mc:cat", cat)
|
|||
local base_spawn_chance = 5000
|
||||
|
||||
-- Spawn ocelot
|
||||
--they get the same as the llama because I'm trying to rework so much of this code right now -j4i
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:ocelot",
|
||||
"overworld",
|
||||
"ground",
|
||||
{
|
||||
"Jungle",
|
||||
"JungleEdgeM",
|
||||
"JungleM",
|
||||
"JungleEdge",
|
||||
},
|
||||
0,
|
||||
minetest.LIGHT_MAX+1,
|
||||
30,
|
||||
15000,
|
||||
5,
|
||||
mobs_mc.spawn_height.water+15,
|
||||
mobs_mc.spawn_height.overworld_max)
|
||||
--[[
|
||||
mobs:spawn({
|
||||
name = "mobs_mc:ocelot",
|
||||
nodes = mobs_mc.spawn.jungle,
|
||||
|
@ -163,8 +182,8 @@ mobs:spawn({
|
|||
min_height = mobs_mc.spawn_height.water+1, -- Right above ocean level
|
||||
max_height = mobs_mc.spawn_height.overworld_max,
|
||||
on_spawn = function(self, pos)
|
||||
--[[ Note: Minecraft has a 1/3 spawn failure rate.
|
||||
In this mod it is emulated by reducing the spawn rate accordingly (see above). ]]
|
||||
Note: Minecraft has a 1/3 spawn failure rate.
|
||||
In this mod it is emulated by reducing the spawn rate accordingly (see above).
|
||||
|
||||
-- 1/7 chance to spawn 2 ocelot kittens
|
||||
if pr:next(1,7) == 1 then
|
||||
|
@ -207,6 +226,7 @@ mobs:spawn({
|
|||
end
|
||||
end,
|
||||
})
|
||||
]]--
|
||||
|
||||
-- spawn eggs
|
||||
-- FIXME: The spawn icon shows a cat texture, not an ocelot texture
|
||||
|
|
|
@ -90,8 +90,24 @@ mobs:register_mob("mobs_mc:parrot", {
|
|||
|
||||
})
|
||||
|
||||
-- Parrots spawn rarely in jungles. TODO: Also check for jungle *biome*
|
||||
mobs:spawn_specific("mobs_mc:parrot", {"mcl_core:jungletree", "mcl_core:jungleleaves"}, {"air"}, 0, minetest.LIGHT_MAX+1, 7, 30000, 1, mobs_mc.spawn_height.water+7, mobs_mc.spawn_height.overworld_max)
|
||||
-- Parrots spawn rarely in jungles. TODO: Also check for jungle *biome* <- I'll get to this eventually -j4i
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:parrot",
|
||||
"overworld",
|
||||
"ground",
|
||||
{
|
||||
"Jungle",
|
||||
"JungleEdgeM",
|
||||
"JungleM",
|
||||
"JungleEdge",
|
||||
},
|
||||
0,
|
||||
minetest.LIGHT_MAX+1,
|
||||
7,
|
||||
30000,
|
||||
1,
|
||||
mobs_mc.spawn_height.water+7,
|
||||
mobs_mc.spawn_height.overworld_max)
|
||||
|
||||
-- spawn eggs
|
||||
mobs:register_egg("mobs_mc:parrot", S("Parrot"), "mobs_mc_spawn_icon_parrot.png", 0)
|
||||
|
|
|
@ -182,7 +182,35 @@ mobs:register_mob("mobs_mc:pig", {
|
|||
end,
|
||||
})
|
||||
|
||||
mobs:spawn_specific("mobs_mc:pig", mobs_mc.spawn.grassland, {"air"}, 9, minetest.LIGHT_MAX+1, 30, 15000, 8, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max)
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:pig",
|
||||
"overworld",
|
||||
"ground",
|
||||
{
|
||||
"FlowerForest",
|
||||
"Swampland",
|
||||
"Taiga",
|
||||
"ExtremeHills",
|
||||
"BirchForest",
|
||||
"MegaSpruceTaiga",
|
||||
"MegaTaiga",
|
||||
"ExtremeHills+",
|
||||
"Forest",
|
||||
"Plains",
|
||||
"ColdTaiga",
|
||||
"SunflowerPlains",
|
||||
"RoofedForest",
|
||||
"MesaPlateauFM_grasstop",
|
||||
"ExtremeHillsM",
|
||||
"BirchForestM",
|
||||
},
|
||||
9,
|
||||
minetest.LIGHT_MAX+1,
|
||||
30,
|
||||
15000,
|
||||
8,
|
||||
mobs_mc.spawn_height.overworld_min,
|
||||
mobs_mc.spawn_height.overworld_max)
|
||||
|
||||
-- spawn eggs
|
||||
mobs:register_egg("mobs_mc:pig", S("Pig"), "mobs_mc_spawn_icon_pig.png", 0)
|
||||
|
|
|
@ -67,7 +67,23 @@ mobs:register_mob("mobs_mc:polar_bear", {
|
|||
})
|
||||
|
||||
|
||||
mobs:spawn_specific("mobs_mc:polar_bear", mobs_mc.spawn.snow, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 7000, 3, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max)
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:polar_bear",
|
||||
"overworld",
|
||||
"ground",
|
||||
{
|
||||
"ColdTaiga",
|
||||
"IcePlainsSpikes",
|
||||
"IcePlains",
|
||||
"ExtremeHills+_snowtop",
|
||||
},
|
||||
0,
|
||||
minetest.LIGHT_MAX+1,
|
||||
30,
|
||||
7000,
|
||||
3,
|
||||
mobs_mc.spawn_height.overworld_min,
|
||||
mobs_mc.spawn_height.overworld_max)
|
||||
|
||||
-- spawn egg
|
||||
mobs:register_egg("mobs_mc:polar_bear", S("Polar Bear"), "mobs_mc_spawn_icon_polarbear.png", 0)
|
||||
|
|
|
@ -107,8 +107,39 @@ end
|
|||
mobs:register_mob("mobs_mc:killer_bunny", killer_bunny)
|
||||
|
||||
-- Mob spawning rules.
|
||||
-- Different skins depending on spawn location
|
||||
-- Different skins depending on spawn location <- we'll get to this when the spawning algorithm is fleshed out
|
||||
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:rabbit",
|
||||
"overworld",
|
||||
"ground",
|
||||
{
|
||||
"FlowerForest",
|
||||
"Swampland",
|
||||
"Taiga",
|
||||
"ExtremeHills",
|
||||
"BirchForest",
|
||||
"MegaSpruceTaiga",
|
||||
"MegaTaiga",
|
||||
"ExtremeHills+",
|
||||
"Forest",
|
||||
"Plains",
|
||||
"ColdTaiga",
|
||||
"SunflowerPlains",
|
||||
"RoofedForest",
|
||||
"MesaPlateauFM_grasstop",
|
||||
"ExtremeHillsM",
|
||||
"BirchForestM",
|
||||
},
|
||||
9,
|
||||
minetest.LIGHT_MAX+1,
|
||||
30,
|
||||
15000,
|
||||
8,
|
||||
mobs_mc.spawn_height.overworld_min,
|
||||
mobs_mc.spawn_height.overworld_max)
|
||||
|
||||
--[[
|
||||
local spawn = {
|
||||
name = "mobs_mc:rabbit",
|
||||
neighbors = {"air"},
|
||||
|
@ -165,6 +196,7 @@ spawn_grass.on_spawn = function(self, pos)
|
|||
self.object:set_properties({textures = self.base_texture})
|
||||
end
|
||||
mobs:spawn(spawn_grass)
|
||||
]]--
|
||||
|
||||
-- Spawn egg
|
||||
mobs:register_egg("mobs_mc:rabbit", S("Rabbit"), "mobs_mc_spawn_icon_rabbit.png", 0)
|
||||
|
|
|
@ -25,6 +25,19 @@ local colors = {
|
|||
unicolor_black = { mobs_mc.items.wool_black, "#000000D0" },
|
||||
}
|
||||
|
||||
local rainbow_colors = {
|
||||
"unicolor_light_red",
|
||||
"unicolor_red",
|
||||
"unicolor_orange",
|
||||
"unicolor_yellow",
|
||||
"unicolor_green",
|
||||
"unicolor_dark_green",
|
||||
"unicolor_light_blue",
|
||||
"unicolor_blue",
|
||||
"unicolor_violet",
|
||||
"unicolor_red_violet"
|
||||
}
|
||||
|
||||
if minetest.get_modpath("mcl_wool") ~= nil then
|
||||
colors["unicolor_light_blue"] = { mobs_mc.items.wool_light_blue, "#5050FFD0" }
|
||||
end
|
||||
|
@ -112,7 +125,7 @@ mobs:register_mob("mobs_mc:sheep", {
|
|||
end,
|
||||
|
||||
-- Set random color on spawn
|
||||
do_custom = function(self)
|
||||
do_custom = function(self, dtime)
|
||||
if not self.initial_color_set then
|
||||
local r = math.random(0,100000)
|
||||
local textures
|
||||
|
@ -149,8 +162,35 @@ mobs:register_mob("mobs_mc:sheep", {
|
|||
}
|
||||
self.initial_color_set = true
|
||||
end
|
||||
|
||||
local is_kay27 = self.nametag == "kay27"
|
||||
|
||||
if self.color_change_timer then
|
||||
local old_color = self.color
|
||||
if is_kay27 then
|
||||
self.color_change_timer = self.color_change_timer - dtime
|
||||
if self.color_change_timer < 0 then
|
||||
self.color_change_timer = 0.5
|
||||
self.color_index = (self.color_index + 1) % #rainbow_colors
|
||||
self.color = rainbow_colors[self.color_index + 1]
|
||||
end
|
||||
else
|
||||
self.color_change_timer = nil
|
||||
self.color_index = nil
|
||||
self.color = self.initial_color
|
||||
end
|
||||
|
||||
if old_color ~= self.color then
|
||||
self.base_texture = sheep_texture(self.color)
|
||||
self.object:set_properties({textures = self.base_texture})
|
||||
end
|
||||
elseif is_kay27 then
|
||||
self.initial_color = self.color
|
||||
self.color_change_timer = 0
|
||||
self.color_index = -1
|
||||
end
|
||||
end,
|
||||
|
||||
|
||||
on_rightclick = function(self, clicker)
|
||||
local item = clicker:get_wielded_item()
|
||||
|
||||
|
@ -263,7 +303,35 @@ mobs:register_mob("mobs_mc:sheep", {
|
|||
end
|
||||
end,
|
||||
})
|
||||
mobs:spawn_specific("mobs_mc:sheep", mobs_mc.spawn.grassland, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 15000, 3, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max)
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:sheep",
|
||||
"overworld",
|
||||
"ground",
|
||||
{
|
||||
"FlowerForest",
|
||||
"Swampland",
|
||||
"Taiga",
|
||||
"ExtremeHills",
|
||||
"BirchForest",
|
||||
"MegaSpruceTaiga",
|
||||
"MegaTaiga",
|
||||
"ExtremeHills+",
|
||||
"Forest",
|
||||
"Plains",
|
||||
"ColdTaiga",
|
||||
"SunflowerPlains",
|
||||
"RoofedForest",
|
||||
"MesaPlateauFM_grasstop",
|
||||
"ExtremeHillsM",
|
||||
"BirchForestM",
|
||||
},
|
||||
0,
|
||||
minetest.LIGHT_MAX+1,
|
||||
30,
|
||||
15000,
|
||||
3,
|
||||
mobs_mc.spawn_height.overworld_min,
|
||||
mobs_mc.spawn_height.overworld_max)
|
||||
|
||||
-- spawn eggs
|
||||
mobs:register_egg("mobs_mc:sheep", S("Sheep"), "mobs_mc_spawn_icon_sheep.png", 0)
|
||||
|
|
|
@ -81,4 +81,17 @@ mobs:register_arrow("mobs_mc:shulkerbullet", {
|
|||
|
||||
mobs:register_egg("mobs_mc:shulker", S("Shulker"), "mobs_mc_spawn_icon_shulker.png", 0)
|
||||
|
||||
mobs:spawn_specific("mobs_mc:shulker", mobs_mc.spawn.end_city, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 5000, 2, mobs_mc.spawn_height.end_min, mobs_mc.spawn_height.end_max)
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:shulker",
|
||||
"end",
|
||||
"ground",
|
||||
{
|
||||
"End"
|
||||
},
|
||||
0,
|
||||
minetest.LIGHT_MAX+1,
|
||||
30,
|
||||
5000,
|
||||
2,
|
||||
mobs_mc.spawn_height.end_min,
|
||||
mobs_mc.spawn_height.end_max)
|
||||
|
|
|
@ -139,13 +139,195 @@ table.insert(stray.drops, {
|
|||
mobs:register_mob("mobs_mc:stray", stray)
|
||||
|
||||
-- Overworld spawn
|
||||
mobs:spawn_specific("mobs_mc:skeleton", mobs_mc.spawn.solid, {"air"}, 0, 7, 20, 17000, 2, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max)
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:skeleton",
|
||||
"overworld",
|
||||
"ground",
|
||||
{
|
||||
"Mesa",
|
||||
"FlowerForest",
|
||||
"Swampland",
|
||||
"Taiga",
|
||||
"ExtremeHills",
|
||||
"Jungle",
|
||||
"Savanna",
|
||||
"BirchForest",
|
||||
"MegaSpruceTaiga",
|
||||
"MegaTaiga",
|
||||
"ExtremeHills+",
|
||||
"Forest",
|
||||
"Plains",
|
||||
"Desert",
|
||||
"ColdTaiga",
|
||||
"MushroomIsland",
|
||||
"IcePlainsSpikes",
|
||||
"SunflowerPlains",
|
||||
"IcePlains",
|
||||
"RoofedForest",
|
||||
"ExtremeHills+_snowtop",
|
||||
"MesaPlateauFM_grasstop",
|
||||
"JungleEdgeM",
|
||||
"ExtremeHillsM",
|
||||
"JungleM",
|
||||
"BirchForestM",
|
||||
"MesaPlateauF",
|
||||
"MesaPlateauFM",
|
||||
"MesaPlateauF_grasstop",
|
||||
"MesaBryce",
|
||||
"JungleEdge",
|
||||
"SavannaM",
|
||||
"FlowerForest_beach",
|
||||
"Forest_beach",
|
||||
"StoneBeach",
|
||||
"ColdTaiga_beach_water",
|
||||
"Taiga_beach",
|
||||
"Savanna_beach",
|
||||
"Plains_beach",
|
||||
"ExtremeHills_beach",
|
||||
"ColdTaiga_beach",
|
||||
"Swampland_shore",
|
||||
"MushroomIslandShore",
|
||||
"JungleM_shore",
|
||||
"Jungle_shore",
|
||||
"MesaPlateauFM_sandlevel",
|
||||
"MesaPlateauF_sandlevel",
|
||||
"MesaBryce_sandlevel",
|
||||
"Mesa_sandlevel",
|
||||
"RoofedForest_ocean",
|
||||
"JungleEdgeM_ocean",
|
||||
"BirchForestM_ocean",
|
||||
"BirchForest_ocean",
|
||||
"IcePlains_deep_ocean",
|
||||
"Jungle_deep_ocean",
|
||||
"Savanna_ocean",
|
||||
"MesaPlateauF_ocean",
|
||||
"ExtremeHillsM_deep_ocean",
|
||||
"Savanna_deep_ocean",
|
||||
"SunflowerPlains_ocean",
|
||||
"Swampland_deep_ocean",
|
||||
"Swampland_ocean",
|
||||
"MegaSpruceTaiga_deep_ocean",
|
||||
"ExtremeHillsM_ocean",
|
||||
"JungleEdgeM_deep_ocean",
|
||||
"SunflowerPlains_deep_ocean",
|
||||
"BirchForest_deep_ocean",
|
||||
"IcePlainsSpikes_ocean",
|
||||
"Mesa_ocean",
|
||||
"StoneBeach_ocean",
|
||||
"Plains_deep_ocean",
|
||||
"JungleEdge_deep_ocean",
|
||||
"SavannaM_deep_ocean",
|
||||
"Desert_deep_ocean",
|
||||
"Mesa_deep_ocean",
|
||||
"ColdTaiga_deep_ocean",
|
||||
"Plains_ocean",
|
||||
"MesaPlateauFM_ocean",
|
||||
"Forest_deep_ocean",
|
||||
"JungleM_deep_ocean",
|
||||
"FlowerForest_deep_ocean",
|
||||
"MushroomIsland_ocean",
|
||||
"MegaTaiga_ocean",
|
||||
"StoneBeach_deep_ocean",
|
||||
"IcePlainsSpikes_deep_ocean",
|
||||
"ColdTaiga_ocean",
|
||||
"SavannaM_ocean",
|
||||
"MesaPlateauF_deep_ocean",
|
||||
"MesaBryce_deep_ocean",
|
||||
"ExtremeHills+_deep_ocean",
|
||||
"ExtremeHills_ocean",
|
||||
"MushroomIsland_deep_ocean",
|
||||
"Forest_ocean",
|
||||
"MegaTaiga_deep_ocean",
|
||||
"JungleEdge_ocean",
|
||||
"MesaBryce_ocean",
|
||||
"MegaSpruceTaiga_ocean",
|
||||
"ExtremeHills+_ocean",
|
||||
"Jungle_ocean",
|
||||
"RoofedForest_deep_ocean",
|
||||
"IcePlains_ocean",
|
||||
"FlowerForest_ocean",
|
||||
"ExtremeHills_deep_ocean",
|
||||
"MesaPlateauFM_deep_ocean",
|
||||
"Desert_ocean",
|
||||
"Taiga_ocean",
|
||||
"BirchForestM_deep_ocean",
|
||||
"Taiga_deep_ocean",
|
||||
"JungleM_ocean",
|
||||
"FlowerForest_underground",
|
||||
"JungleEdge_underground",
|
||||
"StoneBeach_underground",
|
||||
"MesaBryce_underground",
|
||||
"Mesa_underground",
|
||||
"RoofedForest_underground",
|
||||
"Jungle_underground",
|
||||
"Swampland_underground",
|
||||
"MushroomIsland_underground",
|
||||
"BirchForest_underground",
|
||||
"Plains_underground",
|
||||
"MesaPlateauF_underground",
|
||||
"ExtremeHills_underground",
|
||||
"MegaSpruceTaiga_underground",
|
||||
"BirchForestM_underground",
|
||||
"SavannaM_underground",
|
||||
"MesaPlateauFM_underground",
|
||||
"Desert_underground",
|
||||
"Savanna_underground",
|
||||
"Forest_underground",
|
||||
"SunflowerPlains_underground",
|
||||
"ColdTaiga_underground",
|
||||
"IcePlains_underground",
|
||||
"IcePlainsSpikes_underground",
|
||||
"MegaTaiga_underground",
|
||||
"Taiga_underground",
|
||||
"ExtremeHills+_underground",
|
||||
"JungleM_underground",
|
||||
"ExtremeHillsM_underground",
|
||||
"JungleEdgeM_underground",
|
||||
},
|
||||
0,
|
||||
7,
|
||||
20,
|
||||
17000,
|
||||
2,
|
||||
mobs_mc.spawn_height.overworld_min,
|
||||
mobs_mc.spawn_height.overworld_max)
|
||||
|
||||
|
||||
-- Nether spawn
|
||||
mobs:spawn_specific("mobs_mc:skeleton", mobs_mc.spawn.nether_fortress, {"air"}, 0, 7, 30, 10000, 3, mobs_mc.spawn_height.nether_min, mobs_mc.spawn_height.nether_max)
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:skeleton",
|
||||
"nether",
|
||||
"ground",
|
||||
{
|
||||
"Nether"
|
||||
},
|
||||
0,
|
||||
7,
|
||||
30,
|
||||
10000,
|
||||
3,
|
||||
mobs_mc.spawn_height.nether_min,
|
||||
mobs_mc.spawn_height.nether_max)
|
||||
|
||||
-- Stray spawn
|
||||
-- TODO: Spawn directly under the sky
|
||||
mobs:spawn_specific("mobs_mc:stray", mobs_mc.spawn.snow, {"air"}, 0, 7, 20, 19000, 2, mobs_mc.spawn_height.water, mobs_mc.spawn_height.overworld_max)
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:stray",
|
||||
"overworld",
|
||||
"ground",
|
||||
{
|
||||
"ColdTaiga",
|
||||
"IcePlainsSpikes",
|
||||
"IcePlains",
|
||||
"ExtremeHills+_snowtop",
|
||||
},
|
||||
0,
|
||||
7,
|
||||
20,
|
||||
19000,
|
||||
2,
|
||||
mobs_mc.spawn_height.water,
|
||||
mobs_mc.spawn_height.overworld_max)
|
||||
|
||||
|
||||
-- spawn eggs
|
||||
|
|
|
@ -94,7 +94,20 @@ mobs:register_mob("mobs_mc:witherskeleton", {
|
|||
})
|
||||
|
||||
--spawn
|
||||
mobs:spawn_specific("mobs_mc:witherskeleton", mobs_mc.spawn.nether_fortress, {"air"}, 0, 7, 30, 5000, 5, mobs_mc.spawn_height.nether_min, mobs_mc.spawn_height.nether_max)
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:witherskeleton",
|
||||
"nether",
|
||||
"ground",
|
||||
{
|
||||
"Nether"
|
||||
},
|
||||
0,
|
||||
7,
|
||||
30,
|
||||
5000,
|
||||
5,
|
||||
mobs_mc.spawn_height.nether_min,
|
||||
mobs_mc.spawn_height.nether_max)
|
||||
|
||||
-- spawn eggs
|
||||
mobs:register_egg("mobs_mc:witherskeleton", S("Wither Skeleton"), "mobs_mc_spawn_icon_witherskeleton.png", 0)
|
||||
mobs:register_egg("mobs_mc:witherskeleton", S("Wither Skeleton"), "mobs_mc_spawn_icon_witherskeleton.png", 0)
|
|
@ -51,7 +51,6 @@ local spawn_children_on_die = function(child_mob, children_count, spawn_distance
|
|||
end
|
||||
end, children, self.attack)
|
||||
end
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -109,7 +108,6 @@ local slime_big = {
|
|||
fear_height = 0,
|
||||
spawn_small_alternative = "mobs_mc:slime_small",
|
||||
on_die = spawn_children_on_die("mobs_mc:slime_small", 4, 1.0, 1.5),
|
||||
fire_resistant = true,
|
||||
use_texture_alpha = true,
|
||||
}
|
||||
mobs:register_mob("mobs_mc:slime_big", slime_big)
|
||||
|
@ -159,9 +157,137 @@ mobs:register_mob("mobs_mc:slime_tiny", slime_tiny)
|
|||
local smin = mobs_mc.spawn_height.overworld_min
|
||||
local smax = mobs_mc.spawn_height.water - 23
|
||||
|
||||
mobs:spawn_specific("mobs_mc:slime_tiny", mobs_mc.spawn.solid, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 12000, 4, smin, smax)
|
||||
mobs:spawn_specific("mobs_mc:slime_small", mobs_mc.spawn.solid, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 8500, 4, smin, smax)
|
||||
mobs:spawn_specific("mobs_mc:slime_big", mobs_mc.spawn.solid, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 10000, 4, smin, smax)
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:slime_tiny",
|
||||
"overworld",
|
||||
"ground",
|
||||
{
|
||||
"FlowerForest_underground",
|
||||
"JungleEdge_underground",
|
||||
"StoneBeach_underground",
|
||||
"MesaBryce_underground",
|
||||
"Mesa_underground",
|
||||
"RoofedForest_underground",
|
||||
"Jungle_underground",
|
||||
"Swampland_underground",
|
||||
"MushroomIsland_underground",
|
||||
"BirchForest_underground",
|
||||
"Plains_underground",
|
||||
"MesaPlateauF_underground",
|
||||
"ExtremeHills_underground",
|
||||
"MegaSpruceTaiga_underground",
|
||||
"BirchForestM_underground",
|
||||
"SavannaM_underground",
|
||||
"MesaPlateauFM_underground",
|
||||
"Desert_underground",
|
||||
"Savanna_underground",
|
||||
"Forest_underground",
|
||||
"SunflowerPlains_underground",
|
||||
"ColdTaiga_underground",
|
||||
"IcePlains_underground",
|
||||
"IcePlainsSpikes_underground",
|
||||
"MegaTaiga_underground",
|
||||
"Taiga_underground",
|
||||
"ExtremeHills+_underground",
|
||||
"JungleM_underground",
|
||||
"ExtremeHillsM_underground",
|
||||
"JungleEdgeM_underground",
|
||||
},
|
||||
0,
|
||||
minetest.LIGHT_MAX+1,
|
||||
30,
|
||||
12000,
|
||||
4,
|
||||
smin,
|
||||
smax)
|
||||
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:slime_small",
|
||||
"overworld",
|
||||
"ground",
|
||||
{
|
||||
"FlowerForest_underground",
|
||||
"JungleEdge_underground",
|
||||
"StoneBeach_underground",
|
||||
"MesaBryce_underground",
|
||||
"Mesa_underground",
|
||||
"RoofedForest_underground",
|
||||
"Jungle_underground",
|
||||
"Swampland_underground",
|
||||
"MushroomIsland_underground",
|
||||
"BirchForest_underground",
|
||||
"Plains_underground",
|
||||
"MesaPlateauF_underground",
|
||||
"ExtremeHills_underground",
|
||||
"MegaSpruceTaiga_underground",
|
||||
"BirchForestM_underground",
|
||||
"SavannaM_underground",
|
||||
"MesaPlateauFM_underground",
|
||||
"Desert_underground",
|
||||
"Savanna_underground",
|
||||
"Forest_underground",
|
||||
"SunflowerPlains_underground",
|
||||
"ColdTaiga_underground",
|
||||
"IcePlains_underground",
|
||||
"IcePlainsSpikes_underground",
|
||||
"MegaTaiga_underground",
|
||||
"Taiga_underground",
|
||||
"ExtremeHills+_underground",
|
||||
"JungleM_underground",
|
||||
"ExtremeHillsM_underground",
|
||||
"JungleEdgeM_underground",
|
||||
},
|
||||
0,
|
||||
minetest.LIGHT_MAX+1,
|
||||
30,
|
||||
8500,
|
||||
4,
|
||||
smin,
|
||||
smax)
|
||||
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:slime_big",
|
||||
"overworld",
|
||||
"ground",
|
||||
{
|
||||
"FlowerForest_underground",
|
||||
"JungleEdge_underground",
|
||||
"StoneBeach_underground",
|
||||
"MesaBryce_underground",
|
||||
"Mesa_underground",
|
||||
"RoofedForest_underground",
|
||||
"Jungle_underground",
|
||||
"Swampland_underground",
|
||||
"MushroomIsland_underground",
|
||||
"BirchForest_underground",
|
||||
"Plains_underground",
|
||||
"MesaPlateauF_underground",
|
||||
"ExtremeHills_underground",
|
||||
"MegaSpruceTaiga_underground",
|
||||
"BirchForestM_underground",
|
||||
"SavannaM_underground",
|
||||
"MesaPlateauFM_underground",
|
||||
"Desert_underground",
|
||||
"Savanna_underground",
|
||||
"Forest_underground",
|
||||
"SunflowerPlains_underground",
|
||||
"ColdTaiga_underground",
|
||||
"IcePlains_underground",
|
||||
"IcePlainsSpikes_underground",
|
||||
"MegaTaiga_underground",
|
||||
"Taiga_underground",
|
||||
"ExtremeHills+_underground",
|
||||
"JungleM_underground",
|
||||
"ExtremeHillsM_underground",
|
||||
"JungleEdgeM_underground",
|
||||
},
|
||||
0,
|
||||
minetest.LIGHT_MAX+1,
|
||||
30,
|
||||
10000,
|
||||
4,
|
||||
smin,
|
||||
smax)
|
||||
|
||||
-- Magma cube
|
||||
local magma_cube_big = {
|
||||
|
@ -274,13 +400,55 @@ mobs:register_mob("mobs_mc:magma_cube_tiny", magma_cube_tiny)
|
|||
local mmin = mobs_mc.spawn_height.nether_min
|
||||
local mmax = mobs_mc.spawn_height.nether_max
|
||||
|
||||
mobs:spawn_specific("mobs_mc:magma_cube_tiny", mobs_mc.spawn.nether, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 15000, 4, mmin, mmax)
|
||||
mobs:spawn_specific("mobs_mc:magma_cube_small", mobs_mc.spawn.nether, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 15500, 4, mmin, mmax)
|
||||
mobs:spawn_specific("mobs_mc:magma_cube_big", mobs_mc.spawn.nether, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 16000, 4, mmin, mmax)
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:magma_cube_tiny",
|
||||
"nether",
|
||||
"ground",
|
||||
{
|
||||
"Nether"
|
||||
},
|
||||
0,
|
||||
minetest.LIGHT_MAX+1,
|
||||
30,
|
||||
15000,
|
||||
4,
|
||||
mmin,
|
||||
mmax)
|
||||
|
||||
mobs:spawn_specific("mobs_mc:magma_cube_tiny", mobs_mc.spawn.nether_fortress, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 11000, 4, mmin, mmax)
|
||||
mobs:spawn_specific("mobs_mc:magma_cube_small", mobs_mc.spawn.nether_fortress, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 11100, 4, mmin, mmax)
|
||||
mobs:spawn_specific("mobs_mc:magma_cube_big", mobs_mc.spawn.nether_fortress, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 11200, 4, mmin, mmax)
|
||||
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:magma_cube_small",
|
||||
"nether",
|
||||
"ground",
|
||||
{
|
||||
"Nether"
|
||||
},
|
||||
0,
|
||||
minetest.LIGHT_MAX+1,
|
||||
30,
|
||||
15500,
|
||||
4,
|
||||
mmin,
|
||||
mmax)
|
||||
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:magma_cube_big",
|
||||
"nether",
|
||||
"ground",
|
||||
{
|
||||
"Nether"
|
||||
},
|
||||
0,
|
||||
minetest.LIGHT_MAX+1,
|
||||
30,
|
||||
16000,
|
||||
4,
|
||||
mmin,
|
||||
mmax)
|
||||
|
||||
--mobs:spawn_specific("mobs_mc:magma_cube_tiny", mobs_mc.spawn.nether_fortress, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 11000, 4, mmin, mmax)
|
||||
--mobs:spawn_specific("mobs_mc:magma_cube_small", mobs_mc.spawn.nether_fortress, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 11100, 4, mmin, mmax)
|
||||
--mobs:spawn_specific("mobs_mc:magma_cube_big", mobs_mc.spawn.nether_fortress, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 11200, 4, mmin, mmax)
|
||||
|
||||
|
||||
-- spawn eggs
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -87,7 +87,158 @@ cave_spider.sounds.base_pitch = 1.25
|
|||
mobs:register_mob("mobs_mc:cave_spider", cave_spider)
|
||||
|
||||
|
||||
mobs:spawn_specific("mobs_mc:spider", mobs_mc.spawn.solid, {"air"}, 0, 7, 30, 17000, 2, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max)
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:spider",
|
||||
"overworld",
|
||||
"ground",
|
||||
{
|
||||
"Mesa",
|
||||
"FlowerForest",
|
||||
"Swampland",
|
||||
"Taiga",
|
||||
"ExtremeHills",
|
||||
"Jungle",
|
||||
"Savanna",
|
||||
"BirchForest",
|
||||
"MegaSpruceTaiga",
|
||||
"MegaTaiga",
|
||||
"ExtremeHills+",
|
||||
"Forest",
|
||||
"Plains",
|
||||
"Desert",
|
||||
"ColdTaiga",
|
||||
"MushroomIsland",
|
||||
"IcePlainsSpikes",
|
||||
"SunflowerPlains",
|
||||
"IcePlains",
|
||||
"RoofedForest",
|
||||
"ExtremeHills+_snowtop",
|
||||
"MesaPlateauFM_grasstop",
|
||||
"JungleEdgeM",
|
||||
"ExtremeHillsM",
|
||||
"JungleM",
|
||||
"BirchForestM",
|
||||
"MesaPlateauF",
|
||||
"MesaPlateauFM",
|
||||
"MesaPlateauF_grasstop",
|
||||
"MesaBryce",
|
||||
"JungleEdge",
|
||||
"SavannaM",
|
||||
"FlowerForest_beach",
|
||||
"Forest_beach",
|
||||
"StoneBeach",
|
||||
"ColdTaiga_beach_water",
|
||||
"Taiga_beach",
|
||||
"Savanna_beach",
|
||||
"Plains_beach",
|
||||
"ExtremeHills_beach",
|
||||
"ColdTaiga_beach",
|
||||
"Swampland_shore",
|
||||
"MushroomIslandShore",
|
||||
"JungleM_shore",
|
||||
"Jungle_shore",
|
||||
"MesaPlateauFM_sandlevel",
|
||||
"MesaPlateauF_sandlevel",
|
||||
"MesaBryce_sandlevel",
|
||||
"Mesa_sandlevel",
|
||||
"RoofedForest_ocean",
|
||||
"JungleEdgeM_ocean",
|
||||
"BirchForestM_ocean",
|
||||
"BirchForest_ocean",
|
||||
"IcePlains_deep_ocean",
|
||||
"Jungle_deep_ocean",
|
||||
"Savanna_ocean",
|
||||
"MesaPlateauF_ocean",
|
||||
"ExtremeHillsM_deep_ocean",
|
||||
"Savanna_deep_ocean",
|
||||
"SunflowerPlains_ocean",
|
||||
"Swampland_deep_ocean",
|
||||
"Swampland_ocean",
|
||||
"MegaSpruceTaiga_deep_ocean",
|
||||
"ExtremeHillsM_ocean",
|
||||
"JungleEdgeM_deep_ocean",
|
||||
"SunflowerPlains_deep_ocean",
|
||||
"BirchForest_deep_ocean",
|
||||
"IcePlainsSpikes_ocean",
|
||||
"Mesa_ocean",
|
||||
"StoneBeach_ocean",
|
||||
"Plains_deep_ocean",
|
||||
"JungleEdge_deep_ocean",
|
||||
"SavannaM_deep_ocean",
|
||||
"Desert_deep_ocean",
|
||||
"Mesa_deep_ocean",
|
||||
"ColdTaiga_deep_ocean",
|
||||
"Plains_ocean",
|
||||
"MesaPlateauFM_ocean",
|
||||
"Forest_deep_ocean",
|
||||
"JungleM_deep_ocean",
|
||||
"FlowerForest_deep_ocean",
|
||||
"MushroomIsland_ocean",
|
||||
"MegaTaiga_ocean",
|
||||
"StoneBeach_deep_ocean",
|
||||
"IcePlainsSpikes_deep_ocean",
|
||||
"ColdTaiga_ocean",
|
||||
"SavannaM_ocean",
|
||||
"MesaPlateauF_deep_ocean",
|
||||
"MesaBryce_deep_ocean",
|
||||
"ExtremeHills+_deep_ocean",
|
||||
"ExtremeHills_ocean",
|
||||
"MushroomIsland_deep_ocean",
|
||||
"Forest_ocean",
|
||||
"MegaTaiga_deep_ocean",
|
||||
"JungleEdge_ocean",
|
||||
"MesaBryce_ocean",
|
||||
"MegaSpruceTaiga_ocean",
|
||||
"ExtremeHills+_ocean",
|
||||
"Jungle_ocean",
|
||||
"RoofedForest_deep_ocean",
|
||||
"IcePlains_ocean",
|
||||
"FlowerForest_ocean",
|
||||
"ExtremeHills_deep_ocean",
|
||||
"MesaPlateauFM_deep_ocean",
|
||||
"Desert_ocean",
|
||||
"Taiga_ocean",
|
||||
"BirchForestM_deep_ocean",
|
||||
"Taiga_deep_ocean",
|
||||
"JungleM_ocean",
|
||||
"FlowerForest_underground",
|
||||
"JungleEdge_underground",
|
||||
"StoneBeach_underground",
|
||||
"MesaBryce_underground",
|
||||
"Mesa_underground",
|
||||
"RoofedForest_underground",
|
||||
"Jungle_underground",
|
||||
"Swampland_underground",
|
||||
"MushroomIsland_underground",
|
||||
"BirchForest_underground",
|
||||
"Plains_underground",
|
||||
"MesaPlateauF_underground",
|
||||
"ExtremeHills_underground",
|
||||
"MegaSpruceTaiga_underground",
|
||||
"BirchForestM_underground",
|
||||
"SavannaM_underground",
|
||||
"MesaPlateauFM_underground",
|
||||
"Desert_underground",
|
||||
"Savanna_underground",
|
||||
"Forest_underground",
|
||||
"SunflowerPlains_underground",
|
||||
"ColdTaiga_underground",
|
||||
"IcePlains_underground",
|
||||
"IcePlainsSpikes_underground",
|
||||
"MegaTaiga_underground",
|
||||
"Taiga_underground",
|
||||
"ExtremeHills+_underground",
|
||||
"JungleM_underground",
|
||||
"ExtremeHillsM_underground",
|
||||
"JungleEdgeM_underground",
|
||||
},
|
||||
0,
|
||||
7,
|
||||
30,
|
||||
17000,
|
||||
2,
|
||||
mobs_mc.spawn_height.overworld_min,
|
||||
mobs_mc.spawn_height.overworld_max)
|
||||
|
||||
-- spawn eggs
|
||||
mobs:register_egg("mobs_mc:spider", S("Spider"), "mobs_mc_spawn_icon_spider.png", 0)
|
||||
|
|
|
@ -62,7 +62,158 @@ mobs:register_mob("mobs_mc:squid", {
|
|||
|
||||
local water = mobs_mc.spawn_height.water
|
||||
--name, nodes, neighbours, minlight, maxlight, interval, chance, active_object_count, min_height, max_height
|
||||
mobs:spawn_specific("mobs_mc:squid", mobs_mc.spawn.water, {mobs_mc.items.water_source}, 0, minetest.LIGHT_MAX+1, 30, 5500, 3, water-16, water)
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:squid",
|
||||
"overworld",
|
||||
"water",
|
||||
{
|
||||
"Mesa",
|
||||
"FlowerForest",
|
||||
"Swampland",
|
||||
"Taiga",
|
||||
"ExtremeHills",
|
||||
"Jungle",
|
||||
"Savanna",
|
||||
"BirchForest",
|
||||
"MegaSpruceTaiga",
|
||||
"MegaTaiga",
|
||||
"ExtremeHills+",
|
||||
"Forest",
|
||||
"Plains",
|
||||
"Desert",
|
||||
"ColdTaiga",
|
||||
"MushroomIsland",
|
||||
"IcePlainsSpikes",
|
||||
"SunflowerPlains",
|
||||
"IcePlains",
|
||||
"RoofedForest",
|
||||
"ExtremeHills+_snowtop",
|
||||
"MesaPlateauFM_grasstop",
|
||||
"JungleEdgeM",
|
||||
"ExtremeHillsM",
|
||||
"JungleM",
|
||||
"BirchForestM",
|
||||
"MesaPlateauF",
|
||||
"MesaPlateauFM",
|
||||
"MesaPlateauF_grasstop",
|
||||
"MesaBryce",
|
||||
"JungleEdge",
|
||||
"SavannaM",
|
||||
"FlowerForest_beach",
|
||||
"Forest_beach",
|
||||
"StoneBeach",
|
||||
"ColdTaiga_beach_water",
|
||||
"Taiga_beach",
|
||||
"Savanna_beach",
|
||||
"Plains_beach",
|
||||
"ExtremeHills_beach",
|
||||
"ColdTaiga_beach",
|
||||
"Swampland_shore",
|
||||
"MushroomIslandShore",
|
||||
"JungleM_shore",
|
||||
"Jungle_shore",
|
||||
"MesaPlateauFM_sandlevel",
|
||||
"MesaPlateauF_sandlevel",
|
||||
"MesaBryce_sandlevel",
|
||||
"Mesa_sandlevel",
|
||||
"RoofedForest_ocean",
|
||||
"JungleEdgeM_ocean",
|
||||
"BirchForestM_ocean",
|
||||
"BirchForest_ocean",
|
||||
"IcePlains_deep_ocean",
|
||||
"Jungle_deep_ocean",
|
||||
"Savanna_ocean",
|
||||
"MesaPlateauF_ocean",
|
||||
"ExtremeHillsM_deep_ocean",
|
||||
"Savanna_deep_ocean",
|
||||
"SunflowerPlains_ocean",
|
||||
"Swampland_deep_ocean",
|
||||
"Swampland_ocean",
|
||||
"MegaSpruceTaiga_deep_ocean",
|
||||
"ExtremeHillsM_ocean",
|
||||
"JungleEdgeM_deep_ocean",
|
||||
"SunflowerPlains_deep_ocean",
|
||||
"BirchForest_deep_ocean",
|
||||
"IcePlainsSpikes_ocean",
|
||||
"Mesa_ocean",
|
||||
"StoneBeach_ocean",
|
||||
"Plains_deep_ocean",
|
||||
"JungleEdge_deep_ocean",
|
||||
"SavannaM_deep_ocean",
|
||||
"Desert_deep_ocean",
|
||||
"Mesa_deep_ocean",
|
||||
"ColdTaiga_deep_ocean",
|
||||
"Plains_ocean",
|
||||
"MesaPlateauFM_ocean",
|
||||
"Forest_deep_ocean",
|
||||
"JungleM_deep_ocean",
|
||||
"FlowerForest_deep_ocean",
|
||||
"MushroomIsland_ocean",
|
||||
"MegaTaiga_ocean",
|
||||
"StoneBeach_deep_ocean",
|
||||
"IcePlainsSpikes_deep_ocean",
|
||||
"ColdTaiga_ocean",
|
||||
"SavannaM_ocean",
|
||||
"MesaPlateauF_deep_ocean",
|
||||
"MesaBryce_deep_ocean",
|
||||
"ExtremeHills+_deep_ocean",
|
||||
"ExtremeHills_ocean",
|
||||
"MushroomIsland_deep_ocean",
|
||||
"Forest_ocean",
|
||||
"MegaTaiga_deep_ocean",
|
||||
"JungleEdge_ocean",
|
||||
"MesaBryce_ocean",
|
||||
"MegaSpruceTaiga_ocean",
|
||||
"ExtremeHills+_ocean",
|
||||
"Jungle_ocean",
|
||||
"RoofedForest_deep_ocean",
|
||||
"IcePlains_ocean",
|
||||
"FlowerForest_ocean",
|
||||
"ExtremeHills_deep_ocean",
|
||||
"MesaPlateauFM_deep_ocean",
|
||||
"Desert_ocean",
|
||||
"Taiga_ocean",
|
||||
"BirchForestM_deep_ocean",
|
||||
"Taiga_deep_ocean",
|
||||
"JungleM_ocean",
|
||||
"FlowerForest_underground",
|
||||
"JungleEdge_underground",
|
||||
"StoneBeach_underground",
|
||||
"MesaBryce_underground",
|
||||
"Mesa_underground",
|
||||
"RoofedForest_underground",
|
||||
"Jungle_underground",
|
||||
"Swampland_underground",
|
||||
"MushroomIsland_underground",
|
||||
"BirchForest_underground",
|
||||
"Plains_underground",
|
||||
"MesaPlateauF_underground",
|
||||
"ExtremeHills_underground",
|
||||
"MegaSpruceTaiga_underground",
|
||||
"BirchForestM_underground",
|
||||
"SavannaM_underground",
|
||||
"MesaPlateauFM_underground",
|
||||
"Desert_underground",
|
||||
"Savanna_underground",
|
||||
"Forest_underground",
|
||||
"SunflowerPlains_underground",
|
||||
"ColdTaiga_underground",
|
||||
"IcePlains_underground",
|
||||
"IcePlainsSpikes_underground",
|
||||
"MegaTaiga_underground",
|
||||
"Taiga_underground",
|
||||
"ExtremeHills+_underground",
|
||||
"JungleM_underground",
|
||||
"ExtremeHillsM_underground",
|
||||
"JungleEdgeM_underground",
|
||||
},
|
||||
0,
|
||||
minetest.LIGHT_MAX+1,
|
||||
30,
|
||||
5500,
|
||||
3,
|
||||
water-16,
|
||||
water+1)
|
||||
|
||||
-- spawn eggs
|
||||
mobs:register_egg("mobs_mc:squid", S("Squid"), "mobs_mc_spawn_icon_squid.png", 0)
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 1.5 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.3 KiB |
|
@ -516,7 +516,7 @@ local function show_trade_formspec(playername, trader, tradenum)
|
|||
"size[9,8.75]"
|
||||
.."background[-0.19,-0.25;9.41,9.49;mobs_mc_trading_formspec_bg.png]"
|
||||
..disabled_img
|
||||
.."label[4,0;"..F(minetest.colorize("#313131", S(profession))).."]"
|
||||
.."label[4,0;"..F(minetest.colorize(mcl_colors.DARK_GRAY, S(profession))).."]"
|
||||
.."list[current_player;main;0,4.5;9,3;9]"
|
||||
.."list[current_player;main;0,7.74;9,1;]"
|
||||
..b_prev..b_next
|
||||
|
@ -967,6 +967,10 @@ mobs:register_mob("mobs_mc:villager", {
|
|||
drops = {},
|
||||
can_despawn = false,
|
||||
-- TODO: sounds
|
||||
sounds = {
|
||||
random = "mobs_mc_villager",
|
||||
distance = 10,
|
||||
},
|
||||
animation = {
|
||||
stand_speed = 25,
|
||||
stand_start = 40,
|
||||
|
@ -1070,7 +1074,35 @@ mobs:register_mob("mobs_mc:villager", {
|
|||
|
||||
|
||||
|
||||
mobs:spawn_specific("mobs_mc:villager", mobs_mc.spawn.village, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 20, 4, mobs_mc.spawn_height.water+1, mobs_mc.spawn_height.overworld_max)
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:villager",
|
||||
"overworld",
|
||||
"ground",
|
||||
{
|
||||
"FlowerForest",
|
||||
"Swampland",
|
||||
"Taiga",
|
||||
"ExtremeHills",
|
||||
"BirchForest",
|
||||
"MegaSpruceTaiga",
|
||||
"MegaTaiga",
|
||||
"ExtremeHills+",
|
||||
"Forest",
|
||||
"Plains",
|
||||
"ColdTaiga",
|
||||
"SunflowerPlains",
|
||||
"RoofedForest",
|
||||
"MesaPlateauFM_grasstop",
|
||||
"ExtremeHillsM",
|
||||
"BirchForestM",
|
||||
},
|
||||
0,
|
||||
minetest.LIGHT_MAX+1,
|
||||
30,
|
||||
20,
|
||||
4,
|
||||
mobs_mc.spawn_height.water+1,
|
||||
mobs_mc.spawn_height.overworld_max)
|
||||
|
||||
-- spawn eggs
|
||||
mobs:register_egg("mobs_mc:villager", S("Villager"), "mobs_mc_spawn_icon_villager.png", 0)
|
||||
|
|
|
@ -146,8 +146,99 @@ mobs:register_mob("mobs_mc:villager_zombie", {
|
|||
harmed_by_heal = true,
|
||||
})
|
||||
|
||||
mobs:spawn_specific("mobs_mc:villager_zombie", mobs_mc.spawn.village, {"air"}, 0, 7, 30, 4090, 4, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max)
|
||||
mobs:spawn_specific("mobs_mc:villager_zombie", mobs_mc.spawn.solid, {"air"}, 0, 7, 30, 60000, 4, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max)
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:villager_zombie",
|
||||
"overworld",
|
||||
"ground",
|
||||
{
|
||||
"FlowerForest_underground",
|
||||
"JungleEdge_underground",
|
||||
"StoneBeach_underground",
|
||||
"MesaBryce_underground",
|
||||
"Mesa_underground",
|
||||
"RoofedForest_underground",
|
||||
"Jungle_underground",
|
||||
"Swampland_underground",
|
||||
"MushroomIsland_underground",
|
||||
"BirchForest_underground",
|
||||
"Plains_underground",
|
||||
"MesaPlateauF_underground",
|
||||
"ExtremeHills_underground",
|
||||
"MegaSpruceTaiga_underground",
|
||||
"BirchForestM_underground",
|
||||
"SavannaM_underground",
|
||||
"MesaPlateauFM_underground",
|
||||
"Desert_underground",
|
||||
"Savanna_underground",
|
||||
"Forest_underground",
|
||||
"SunflowerPlains_underground",
|
||||
"ColdTaiga_underground",
|
||||
"IcePlains_underground",
|
||||
"IcePlainsSpikes_underground",
|
||||
"MegaTaiga_underground",
|
||||
"Taiga_underground",
|
||||
"ExtremeHills+_underground",
|
||||
"JungleM_underground",
|
||||
"ExtremeHillsM_underground",
|
||||
"JungleEdgeM_underground",
|
||||
"Mesa",
|
||||
"FlowerForest",
|
||||
"Swampland",
|
||||
"Taiga",
|
||||
"ExtremeHills",
|
||||
"Jungle",
|
||||
"Savanna",
|
||||
"BirchForest",
|
||||
"MegaSpruceTaiga",
|
||||
"MegaTaiga",
|
||||
"ExtremeHills+",
|
||||
"Forest",
|
||||
"Plains",
|
||||
"Desert",
|
||||
"ColdTaiga",
|
||||
"MushroomIsland",
|
||||
"IcePlainsSpikes",
|
||||
"SunflowerPlains",
|
||||
"IcePlains",
|
||||
"RoofedForest",
|
||||
"ExtremeHills+_snowtop",
|
||||
"MesaPlateauFM_grasstop",
|
||||
"JungleEdgeM",
|
||||
"ExtremeHillsM",
|
||||
"JungleM",
|
||||
"BirchForestM",
|
||||
"MesaPlateauF",
|
||||
"MesaPlateauFM",
|
||||
"MesaPlateauF_grasstop",
|
||||
"MesaBryce",
|
||||
"JungleEdge",
|
||||
"SavannaM",
|
||||
"FlowerForest_beach",
|
||||
"Forest_beach",
|
||||
"StoneBeach",
|
||||
"ColdTaiga_beach_water",
|
||||
"Taiga_beach",
|
||||
"Savanna_beach",
|
||||
"Plains_beach",
|
||||
"ExtremeHills_beach",
|
||||
"ColdTaiga_beach",
|
||||
"Swampland_shore",
|
||||
"MushroomIslandShore",
|
||||
"JungleM_shore",
|
||||
"Jungle_shore",
|
||||
"MesaPlateauFM_sandlevel",
|
||||
"MesaPlateauF_sandlevel",
|
||||
"MesaBryce_sandlevel",
|
||||
"Mesa_sandlevel",
|
||||
},
|
||||
0,
|
||||
7,
|
||||
30,
|
||||
4090,
|
||||
4,
|
||||
mobs_mc.spawn_height.overworld_min,
|
||||
mobs_mc.spawn_height.overworld_max)
|
||||
--mobs:spawn_specific("mobs_mc:villager_zombie", "overworld", "ground", 0, 7, 30, 60000, 4, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max)
|
||||
|
||||
-- spawn eggs
|
||||
mobs:register_egg("mobs_mc:villager_zombie", S("Zombie Villager"), "mobs_mc_spawn_icon_zombie_villager.png", 0)
|
||||
|
|
|
@ -99,7 +99,7 @@ mobs:register_arrow("mobs_mc:potion_arrow", {
|
|||
end
|
||||
})
|
||||
|
||||
-- TODO: Spawn when witch works properly
|
||||
-- TODO: Spawn when witch works properly <- eventually -j4i
|
||||
--mobs:spawn_specific("mobs_mc:witch", mobs_mc.spawn.jungle, {"air"}, 0, minetest.LIGHT_MAX-6, 12, 20000, 2, mobs_mc.spawn_height.water-6, mobs_mc.spawn_height.overworld_max)
|
||||
|
||||
-- spawn eggs
|
||||
|
|
|
@ -16,7 +16,7 @@ mobs:register_mob("mobs_mc:wither", {
|
|||
hp_min = 300,
|
||||
xp_min = 50,
|
||||
xp_max = 50,
|
||||
armor = {undead = 80, fleshy = 80},
|
||||
armor = {undead = 80, fleshy = 100},
|
||||
-- This deviates from MC Wiki's size, which makes no sense
|
||||
collisionbox = {-0.9, 0.4, -0.9, 0.9, 2.45, 0.9},
|
||||
visual = "mesh",
|
||||
|
@ -66,6 +66,15 @@ mobs:register_mob("mobs_mc:wither", {
|
|||
run_start = 0, run_end = 20,
|
||||
},
|
||||
harmed_by_heal = true,
|
||||
do_custom = function(self)
|
||||
if self.health < (self.hp_max / 2) then
|
||||
self.base_texture = "mobs_mc_wither_half_health.png"
|
||||
self.fly = false
|
||||
self.object:set_properties({textures={self.base_texture}})
|
||||
self.armor = {undead = 80, fleshy = 80}
|
||||
end
|
||||
mcl_bossbars.update_boss(self, "Wither", "dark_purple")
|
||||
end,
|
||||
on_spawn = function(self)
|
||||
minetest.sound_play("mobs_mc_wither_spawn", {object=self.object, gain=1.0, max_hear_distance=64})
|
||||
end,
|
||||
|
@ -107,4 +116,4 @@ mobs:register_arrow("mobs_mc:wither_skull", {
|
|||
--Spawn egg
|
||||
mobs:register_egg("mobs_mc:wither", S("Wither"), "mobs_mc_spawn_icon_wither.png", 0, true)
|
||||
|
||||
mcl_wip.register_wip_item("mobs_mc:wither")
|
||||
mcl_wip.register_wip_item("mobs_mc:wither")
|
||||
|
|
|
@ -232,6 +232,34 @@ end
|
|||
mobs:register_mob("mobs_mc:dog", dog)
|
||||
|
||||
-- Spawn
|
||||
mobs:spawn_specific("mobs_mc:wolf", mobs_mc.spawn.wolf, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 9000, 7, mobs_mc.spawn_height.water+3, mobs_mc.spawn_height.overworld_max)
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:wolf",
|
||||
"overworld",
|
||||
"ground",
|
||||
{
|
||||
"FlowerForest",
|
||||
"Swampland",
|
||||
"Taiga",
|
||||
"ExtremeHills",
|
||||
"BirchForest",
|
||||
"MegaSpruceTaiga",
|
||||
"MegaTaiga",
|
||||
"ExtremeHills+",
|
||||
"Forest",
|
||||
"Plains",
|
||||
"ColdTaiga",
|
||||
"SunflowerPlains",
|
||||
"RoofedForest",
|
||||
"MesaPlateauFM_grasstop",
|
||||
"ExtremeHillsM",
|
||||
"BirchForestM",
|
||||
},
|
||||
0,
|
||||
minetest.LIGHT_MAX+1,
|
||||
30,
|
||||
9000,
|
||||
7,
|
||||
mobs_mc.spawn_height.water+3,
|
||||
mobs_mc.spawn_height.overworld_max)
|
||||
|
||||
mobs:register_egg("mobs_mc:wolf", S("Wolf"), "mobs_mc_spawn_icon_wolf.png", 0)
|
||||
|
|
|
@ -135,11 +135,227 @@ mobs:register_mob("mobs_mc:baby_husk", baby_husk)
|
|||
|
||||
-- Spawning
|
||||
|
||||
mobs:spawn_specific("mobs_mc:zombie", mobs_mc.spawn.solid, {"air"}, 0, 7, 30, 6000, 4, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max)
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:zombie",
|
||||
"overworld",
|
||||
"ground",
|
||||
{
|
||||
"FlowerForest_underground",
|
||||
"JungleEdge_underground",
|
||||
"StoneBeach_underground",
|
||||
"MesaBryce_underground",
|
||||
"Mesa_underground",
|
||||
"RoofedForest_underground",
|
||||
"Jungle_underground",
|
||||
"Swampland_underground",
|
||||
"MushroomIsland_underground",
|
||||
"BirchForest_underground",
|
||||
"Plains_underground",
|
||||
"MesaPlateauF_underground",
|
||||
"ExtremeHills_underground",
|
||||
"MegaSpruceTaiga_underground",
|
||||
"BirchForestM_underground",
|
||||
"SavannaM_underground",
|
||||
"MesaPlateauFM_underground",
|
||||
"Desert_underground",
|
||||
"Savanna_underground",
|
||||
"Forest_underground",
|
||||
"SunflowerPlains_underground",
|
||||
"ColdTaiga_underground",
|
||||
"IcePlains_underground",
|
||||
"IcePlainsSpikes_underground",
|
||||
"MegaTaiga_underground",
|
||||
"Taiga_underground",
|
||||
"ExtremeHills+_underground",
|
||||
"JungleM_underground",
|
||||
"ExtremeHillsM_underground",
|
||||
"JungleEdgeM_underground",
|
||||
"Mesa",
|
||||
"FlowerForest",
|
||||
"Swampland",
|
||||
"Taiga",
|
||||
"ExtremeHills",
|
||||
"Jungle",
|
||||
"Savanna",
|
||||
"BirchForest",
|
||||
"MegaSpruceTaiga",
|
||||
"MegaTaiga",
|
||||
"ExtremeHills+",
|
||||
"Forest",
|
||||
"Plains",
|
||||
"Desert",
|
||||
"ColdTaiga",
|
||||
"MushroomIsland",
|
||||
"IcePlainsSpikes",
|
||||
"SunflowerPlains",
|
||||
"IcePlains",
|
||||
"RoofedForest",
|
||||
"ExtremeHills+_snowtop",
|
||||
"MesaPlateauFM_grasstop",
|
||||
"JungleEdgeM",
|
||||
"ExtremeHillsM",
|
||||
"JungleM",
|
||||
"BirchForestM",
|
||||
"MesaPlateauF",
|
||||
"MesaPlateauFM",
|
||||
"MesaPlateauF_grasstop",
|
||||
"MesaBryce",
|
||||
"JungleEdge",
|
||||
"SavannaM",
|
||||
"FlowerForest_beach",
|
||||
"Forest_beach",
|
||||
"StoneBeach",
|
||||
"ColdTaiga_beach_water",
|
||||
"Taiga_beach",
|
||||
"Savanna_beach",
|
||||
"Plains_beach",
|
||||
"ExtremeHills_beach",
|
||||
"ColdTaiga_beach",
|
||||
"Swampland_shore",
|
||||
"MushroomIslandShore",
|
||||
"JungleM_shore",
|
||||
"Jungle_shore",
|
||||
"MesaPlateauFM_sandlevel",
|
||||
"MesaPlateauF_sandlevel",
|
||||
"MesaBryce_sandlevel",
|
||||
"Mesa_sandlevel",
|
||||
},
|
||||
0,
|
||||
7,
|
||||
30,
|
||||
6000,
|
||||
4,
|
||||
mobs_mc.spawn_height.overworld_min,
|
||||
mobs_mc.spawn_height.overworld_max)
|
||||
-- Baby zombie is 20 times less likely than regular zombies
|
||||
mobs:spawn_specific("mobs_mc:baby_zombie", mobs_mc.spawn.solid, {"air"}, 0, 7, 30, 60000, 4, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max)
|
||||
mobs:spawn_specific("mobs_mc:husk", mobs_mc.spawn.desert, {"air"}, 0, 7, 30, 6500, 4, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max)
|
||||
mobs:spawn_specific("mobs_mc:baby_husk", mobs_mc.spawn.desert, {"air"}, 0, 7, 30, 65000, 4, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max)
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:baby_zombie",
|
||||
"overworld",
|
||||
"ground",
|
||||
{
|
||||
"FlowerForest_underground",
|
||||
"JungleEdge_underground",
|
||||
"StoneBeach_underground",
|
||||
"MesaBryce_underground",
|
||||
"Mesa_underground",
|
||||
"RoofedForest_underground",
|
||||
"Jungle_underground",
|
||||
"Swampland_underground",
|
||||
"MushroomIsland_underground",
|
||||
"BirchForest_underground",
|
||||
"Plains_underground",
|
||||
"MesaPlateauF_underground",
|
||||
"ExtremeHills_underground",
|
||||
"MegaSpruceTaiga_underground",
|
||||
"BirchForestM_underground",
|
||||
"SavannaM_underground",
|
||||
"MesaPlateauFM_underground",
|
||||
"Desert_underground",
|
||||
"Savanna_underground",
|
||||
"Forest_underground",
|
||||
"SunflowerPlains_underground",
|
||||
"ColdTaiga_underground",
|
||||
"IcePlains_underground",
|
||||
"IcePlainsSpikes_underground",
|
||||
"MegaTaiga_underground",
|
||||
"Taiga_underground",
|
||||
"ExtremeHills+_underground",
|
||||
"JungleM_underground",
|
||||
"ExtremeHillsM_underground",
|
||||
"JungleEdgeM_underground",
|
||||
"Mesa",
|
||||
"FlowerForest",
|
||||
"Swampland",
|
||||
"Taiga",
|
||||
"ExtremeHills",
|
||||
"Jungle",
|
||||
"Savanna",
|
||||
"BirchForest",
|
||||
"MegaSpruceTaiga",
|
||||
"MegaTaiga",
|
||||
"ExtremeHills+",
|
||||
"Forest",
|
||||
"Plains",
|
||||
"Desert",
|
||||
"ColdTaiga",
|
||||
"MushroomIsland",
|
||||
"IcePlainsSpikes",
|
||||
"SunflowerPlains",
|
||||
"IcePlains",
|
||||
"RoofedForest",
|
||||
"ExtremeHills+_snowtop",
|
||||
"MesaPlateauFM_grasstop",
|
||||
"JungleEdgeM",
|
||||
"ExtremeHillsM",
|
||||
"JungleM",
|
||||
"BirchForestM",
|
||||
"MesaPlateauF",
|
||||
"MesaPlateauFM",
|
||||
"MesaPlateauF_grasstop",
|
||||
"MesaBryce",
|
||||
"JungleEdge",
|
||||
"SavannaM",
|
||||
"FlowerForest_beach",
|
||||
"Forest_beach",
|
||||
"StoneBeach",
|
||||
"ColdTaiga_beach_water",
|
||||
"Taiga_beach",
|
||||
"Savanna_beach",
|
||||
"Plains_beach",
|
||||
"ExtremeHills_beach",
|
||||
"ColdTaiga_beach",
|
||||
"Swampland_shore",
|
||||
"MushroomIslandShore",
|
||||
"JungleM_shore",
|
||||
"Jungle_shore",
|
||||
"MesaPlateauFM_sandlevel",
|
||||
"MesaPlateauF_sandlevel",
|
||||
"MesaBryce_sandlevel",
|
||||
"Mesa_sandlevel",
|
||||
},
|
||||
0,
|
||||
7,
|
||||
30,
|
||||
60000,
|
||||
4,
|
||||
mobs_mc.spawn_height.overworld_min,
|
||||
mobs_mc.spawn_height.overworld_max)
|
||||
|
||||
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:husk",
|
||||
"overworld",
|
||||
"ground",
|
||||
{
|
||||
"Desert",
|
||||
"SavannaM",
|
||||
"Savanna",
|
||||
"Savanna_beach",
|
||||
},
|
||||
0,
|
||||
7,
|
||||
30,
|
||||
6500,
|
||||
4,
|
||||
mobs_mc.spawn_height.overworld_min,
|
||||
mobs_mc.spawn_height.overworld_max)
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:baby_husk",
|
||||
"overworld",
|
||||
"ground",
|
||||
{
|
||||
"Desert",
|
||||
"SavannaM",
|
||||
"Savanna",
|
||||
"Savanna_beach",
|
||||
},
|
||||
0,
|
||||
7,
|
||||
30,
|
||||
65000,
|
||||
4,
|
||||
mobs_mc.spawn_height.overworld_min,
|
||||
mobs_mc.spawn_height.overworld_max)
|
||||
|
||||
-- Spawn eggs
|
||||
mobs:register_egg("mobs_mc:husk", S("Husk"), "mobs_mc_spawn_icon_husk.png", 0)
|
||||
|
|
|
@ -111,12 +111,38 @@ baby_pigman.child = 1
|
|||
mobs:register_mob("mobs_mc:baby_pigman", baby_pigman)
|
||||
|
||||
-- Regular spawning in the Nether
|
||||
mobs:spawn_specific("mobs_mc:pigman", mobs_mc.spawn.solid, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 6000, 3, mobs_mc.spawn_height.nether_min, mobs_mc.spawn_height.nether_max)
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:pigman",
|
||||
"nether",
|
||||
"ground",
|
||||
{
|
||||
"Nether"
|
||||
},
|
||||
0,
|
||||
minetest.LIGHT_MAX+1,
|
||||
30,
|
||||
6000,
|
||||
3,
|
||||
mobs_mc.spawn_height.nether_min,
|
||||
mobs_mc.spawn_height.nether_max)
|
||||
-- Baby zombie is 20 times less likely than regular zombies
|
||||
mobs:spawn_specific("mobs_mc:baby_pigman", mobs_mc.spawn.solid, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 100000, 4, mobs_mc.spawn_height.nether_min, mobs_mc.spawn_height.nether_max)
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:baby_pigman",
|
||||
"nether",
|
||||
"ground",
|
||||
{
|
||||
"Nether"
|
||||
},
|
||||
0,
|
||||
minetest.LIGHT_MAX+1,
|
||||
30,
|
||||
100000,
|
||||
4,
|
||||
mobs_mc.spawn_height.nether_min,
|
||||
mobs_mc.spawn_height.nether_max)
|
||||
|
||||
-- Spawning in Nether portals in the Overworld
|
||||
mobs:spawn_specific("mobs_mc:pigman", mobs_mc.spawn.nether_portal, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 500, 4, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max)
|
||||
--mobs:spawn_specific("mobs_mc:pigman", mobs_mc.spawn.nether_portal, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 500, 4, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max)
|
||||
|
||||
-- spawn eggs
|
||||
mobs:register_egg("mobs_mc:pigman", S("Zombie Pigman"), "mobs_mc_spawn_icon_zombie_pigman.png", 0)
|
||||
|
|
|
@ -1,13 +1,7 @@
|
|||
local S = minetest.get_translator("doc")
|
||||
local F = function(f) return minetest.formspec_escape(S(f)) end
|
||||
|
||||
-- Compability for 0.4.14 or earlier
|
||||
local colorize
|
||||
if minetest.colorize then
|
||||
colorize = minetest.colorize
|
||||
else
|
||||
colorize = function(color, text) return text end
|
||||
end
|
||||
local colorize = minetest.colorize
|
||||
|
||||
doc = {}
|
||||
|
||||
|
@ -41,10 +35,10 @@ doc.FORMSPEC.ENTRY_HEIGHT = doc.FORMSPEC.ENTRY_END_Y - doc.FORMSPEC.ENTRY_START_
|
|||
-- Internal helper variables
|
||||
local DOC_INTRO = S("This is the help.")
|
||||
|
||||
local COLOR_NOT_VIEWED = "#00FFFF" -- cyan
|
||||
local COLOR_VIEWED = "#FFFFFF" -- white
|
||||
local COLOR_HIDDEN = "#999999" -- gray
|
||||
local COLOR_ERROR = "#FF0000" -- red
|
||||
local COLOR_NOT_VIEWED = mcl_colors.AQUA
|
||||
local COLOR_VIEWED = mcl_colors.WHITE
|
||||
local COLOR_HIDDEN = mcl_colors.GRAY
|
||||
local COLOR_ERROR = mcl_colors.RED
|
||||
|
||||
local CATEGORYFIELDSIZE = {
|
||||
WIDTH = math.ceil(doc.FORMSPEC.WIDTH / 4),
|
||||
|
@ -776,7 +770,7 @@ function doc.generate_entry_list(cid, playername)
|
|||
if name == nil or name == "" then
|
||||
name = S("Nameless entry (@1)", eid)
|
||||
if doc.entry_viewed(playername, cid, eid) then
|
||||
viewedprefix = "#FF4444"
|
||||
viewedprefix = mcl_colors.RED
|
||||
else
|
||||
viewedprefix = COLOR_ERROR
|
||||
end
|
||||
|
|
|
@ -2,3 +2,4 @@ name = doc
|
|||
author = Wuzzy
|
||||
description = A simple in-game documentation system which enables mods to add help entries based on templates.
|
||||
optional_depends = unified_inventory, sfinv_buttons, central_message, inventory_plus
|
||||
depends = mcl_colors
|
||||
|
|
|
@ -410,7 +410,7 @@ local function get_tooltip(item, groups, cooktime, burntime)
|
|||
local tooltip
|
||||
|
||||
if groups then
|
||||
local gcol = "#FFAAFF"
|
||||
local gcol = mcl_colors.LIGHT_PURPLE
|
||||
if #groups == 1 then
|
||||
local g = group_names[groups[1]]
|
||||
local groupstr
|
||||
|
@ -446,12 +446,12 @@ local function get_tooltip(item, groups, cooktime, burntime)
|
|||
|
||||
if not groups and cooktime then
|
||||
tooltip = tooltip .. "\n" ..
|
||||
S("Cooking time: @1", colorize("yellow", cooktime))
|
||||
S("Cooking time: @1", colorize(mcl_colors.YELLOW, cooktime))
|
||||
end
|
||||
|
||||
if not groups and burntime then
|
||||
tooltip = tooltip .. "\n" ..
|
||||
S("Burning time: @1", colorize("yellow", burntime))
|
||||
S("Burning time: @1", colorize(mcl_colors.YELLOW, burntime))
|
||||
end
|
||||
|
||||
return fmt(FMT.tooltip, item, ESC(tooltip))
|
||||
|
@ -668,7 +668,7 @@ local function make_formspec(name)
|
|||
fs[#fs + 1] = fmt("label[%f,%f;%s]",
|
||||
sfinv_only and 6.3 or data.iX - 2.2,
|
||||
0.22,
|
||||
ESC(colorize("#383838", fmt("%s / %u", data.pagenum, data.pagemax))))
|
||||
ESC(colorize(mcl_colors.DARK_GRAY, fmt("%s / %u", data.pagenum, data.pagemax))))
|
||||
|
||||
fs[#fs + 1] = fmt([[
|
||||
image_button[%f,0.12;0.8,0.8;craftguide_prev_icon.png;prev;]
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
name = mcl_craftguide
|
||||
author = kilbith
|
||||
description = The most comprehensive Crafting Guide on Minetest.
|
||||
depends = mcl_core, mcl_compass, mcl_clock, doc
|
||||
depends = mcl_core, mcl_compass, mcl_clock, doc, mcl_colors
|
||||
optional_depends = sfinv, sfinv_buttons
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
name = mcl_tt
|
||||
author = Wuzzy
|
||||
description = Add MCL2 tooltips
|
||||
depends = tt, mcl_enchanting
|
||||
depends = tt, mcl_enchanting, mcl_colors
|
||||
|
|
|
@ -77,7 +77,7 @@ end)
|
|||
tt.register_snippet(function(itemstring)
|
||||
local def = minetest.registered_items[itemstring]
|
||||
if minetest.get_item_group(itemstring, "crush_after_fall") == 1 then
|
||||
return S("Deals damage when falling"), "#FFFF00"
|
||||
return S("Deals damage when falling"), mcl_colors.YELLOW
|
||||
end
|
||||
end)
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
tt = {}
|
||||
tt.COLOR_DEFAULT = "#d0ffd0"
|
||||
tt.COLOR_DANGER = "#ffff00"
|
||||
tt.COLOR_GOOD = "#00ff00"
|
||||
tt.NAME_COLOR = "#FFFF4C"
|
||||
tt.COLOR_DEFAULT = mcl_colors.GREEN
|
||||
tt.COLOR_DANGER = mcl_colors.YELLOW
|
||||
tt.COLOR_GOOD = mcl_colors.GREEN
|
||||
tt.NAME_COLOR = mcl_colors.YELLOW
|
||||
|
||||
-- API
|
||||
tt.registered_snippets = {}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
name = tt
|
||||
author = Wuzzy
|
||||
description = Support for custom tooltip extensions for items
|
||||
depends = mcl_colors
|
||||
|
|
|
@ -214,7 +214,7 @@ function awards.unlock(name, award)
|
|||
|
||||
-- Get award
|
||||
minetest.log("action", name.." has gotten award "..award)
|
||||
minetest.chat_send_all(S("@1 has made the achievement @2", name, minetest.colorize("#51EF4E", "[" .. (awdef.title or award) .. "]")))
|
||||
minetest.chat_send_all(S("@1 has made the achievement @2", name, minetest.colorize(mcl_colors.GREEN, "[" .. (awdef.title or award) .. "]")))
|
||||
data.unlocked[award] = award
|
||||
awards.save()
|
||||
|
||||
|
@ -447,7 +447,7 @@ function awards.getFormspec(name, to, sid)
|
|||
first = false
|
||||
|
||||
if def.secret and not award.got then
|
||||
formspec = formspec .. "#707070"..minetest.formspec_escape(S("(Secret Award)"))
|
||||
formspec = formspec .. mcl_colors.DARK_GRAY..minetest.formspec_escape(S("(Secret Award)"))
|
||||
else
|
||||
local title = award.name
|
||||
if def and def.title then
|
||||
|
@ -456,7 +456,7 @@ function awards.getFormspec(name, to, sid)
|
|||
if award.got then
|
||||
formspec = formspec .. minetest.formspec_escape(title)
|
||||
else
|
||||
formspec = formspec .. "#ACACAC".. minetest.formspec_escape(title)
|
||||
formspec = formspec .. mcl_colors.GRAY.. minetest.formspec_escape(title)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -6,3 +6,4 @@ license = LGPL 2.1 or later
|
|||
forum = https://forum.minetest.net/viewtopic.php?t=4870
|
||||
version = 2.3.0
|
||||
optional_depends = sfinv, unified_inventory
|
||||
depends = mcl_colors
|
||||
|
|
|
@ -17,7 +17,7 @@ To give you a *very* brief overview over this API, here is the basic workflow on
|
|||
In order to use this API, you should be aware of a few basic rules in order to understand it:
|
||||
|
||||
* A HUD bar is an approximate graphical representation of the ratio of a current value and a maximum value, i.e. current health of 15 and maximum health of 20. A full HUD bar represents 100%, an empty HUD bar represents 0%.
|
||||
* The current value must always be equal to or smaller then the maximum
|
||||
* The current value must always be equal to or smaller then the maximum
|
||||
* Both current value and maximum must not be smaller than 0
|
||||
* Both current value and maximum must be real numbers. So no NaN, infinity, etc.
|
||||
* The HUD bar will be hidden if the maximum equals 0. This is intentional.
|
||||
|
@ -45,7 +45,7 @@ a vertical gradient.
|
|||
### Icon
|
||||
A 16×16 image shown left of the HUD bar. This is optional.
|
||||
|
||||
### `hb.register_hudbar(identifier, text_color, label, textures, default_start_value, default_start_max, default_start_hidden, format_string, format_string_config)`
|
||||
### `hb.register_hudbar(identifier, text_color, label, textures, direction, default_start_value, default_start_max, default_start_hidden, format_string, format_string_config)`
|
||||
This function registers a new custom HUD bar definition to the HUD bars mod, so it can be later used to be displayed, changed, hidden
|
||||
and unhidden on a per-player basis.
|
||||
Note this does not yet display the HUD bar.
|
||||
|
@ -63,6 +63,7 @@ for more information.
|
|||
* `bar`: The file name of the bar image (as string). This is only used for the `progress_bar` bar type (see `README.txt`, settings section).
|
||||
* `icon`: The file name of the icon, as string. For the `progress_bar` type, it is shown as single image left of the bar, for the two statbar bar types, it is used as the statbar icon and will be repeated. This field can be `nil`, in which case no icon will be used, but this is not recommended, because the HUD bar will be invisible if the one of the statbar bar types is used.
|
||||
* `bgicon`: The file name of the background icon, it is used as the background for the modern statbar mode only. This field can be `nil`, in which case no background icon will be displayed in this mode.
|
||||
* `direction`: Either left to right(0), or right to left(1).
|
||||
* `default_start_value`: If this HUD bar is added to a player, and no initial value is specified, this value will be used as initial current value
|
||||
* `default_max_value`: If this HUD bar is added to a player, and no initial maximum value is specified, this value will be used as initial maximum value
|
||||
* `default_start_hidden`: The HUD bar will be initially start hidden by default when added to a player. Use `hb.unhide_hudbar` to unhide it.
|
||||
|
|
|
@ -20,9 +20,9 @@ if hb.settings.bar_type == "progress_bar" then
|
|||
hb.settings.start_offset_right.x = hb.load_setting("hudbars_start_offset_right_x", "number", 15)
|
||||
hb.settings.start_offset_right.y = hb.load_setting("hudbars_start_offset_right_y", "number", -86)
|
||||
else
|
||||
hb.settings.start_offset_left.x = hb.load_setting("hudbars_start_statbar_offset_left_x", "number", -265)
|
||||
hb.settings.start_offset_left.x = hb.load_setting("hudbars_start_statbar_offset_left_x", "number", -258)
|
||||
hb.settings.start_offset_left.y = hb.load_setting("hudbars_start_statbar_offset_left_y", "number", -90)
|
||||
hb.settings.start_offset_right.x = hb.load_setting("hudbars_start_statbar_offset_right_x", "number", 25)
|
||||
hb.settings.start_offset_right.x = hb.load_setting("hudbars_start_statbar_offset_right_x", "number", 16)
|
||||
hb.settings.start_offset_right.y = hb.load_setting("hudbars_start_statbar_offset_right_y", "number", -90)
|
||||
end
|
||||
-- Modified in MCL2!
|
||||
|
|
|
@ -124,7 +124,7 @@ function hb.get_hudbar_position_index(identifier)
|
|||
end
|
||||
end
|
||||
|
||||
function hb.register_hudbar(identifier, text_color, label, textures, default_start_value, default_start_max, default_start_hidden, format_string, format_string_config)
|
||||
function hb.register_hudbar(identifier, text_color, label, textures, direction, default_start_value, default_start_max, default_start_hidden, format_string, format_string_config)
|
||||
minetest.log("action", "hb.register_hudbar: "..tostring(identifier))
|
||||
local hudtable = {}
|
||||
local pos, offset
|
||||
|
@ -133,30 +133,33 @@ function hb.register_hudbar(identifier, text_color, label, textures, default_sta
|
|||
if hb.settings.alignment_pattern == "stack_up" then
|
||||
pos = hb.settings.pos_left
|
||||
offset = {
|
||||
x = hb.settings.start_offset_left.x,
|
||||
x = direction == 0 and hb.settings.start_offset_left.x or -hb.settings.start_offset_right.x,
|
||||
y = hb.settings.start_offset_left.y - hb.settings.vmargin * index
|
||||
}
|
||||
elseif hb.settings.alignment_pattern == "stack_down" then
|
||||
pos = hb.settings.pos_left
|
||||
offset = {
|
||||
x = hb.settings.start_offset_left.x,
|
||||
x = direction == 0 and hb.settings.start_offset_right.x or -hb.settings.start_offset_left.x,
|
||||
y = hb.settings.start_offset_left.y + hb.settings.vmargin * index
|
||||
}
|
||||
else
|
||||
else -- zigzag
|
||||
if index % 2 == 0 then
|
||||
pos = hb.settings.pos_left
|
||||
offset = {
|
||||
x = hb.settings.start_offset_left.x,
|
||||
-- -(24+18) = -42. using linear eq, -42 = -258m - 24.
|
||||
x = direction == 0 and hb.settings.start_offset_left.x or (-42+24)/(-258.0) * hb.settings.start_offset_left.x - 24,
|
||||
y = hb.settings.start_offset_left.y - hb.settings.vmargin * (index/2)
|
||||
}
|
||||
else
|
||||
pos = hb.settings.pos_right
|
||||
offset = {
|
||||
x = hb.settings.start_offset_right.x,
|
||||
-- 24*10+30 - 24 = 234. using linear eq, 234 = 16m - 24.
|
||||
x = direction == 0 and hb.settings.start_offset_right.x or (234+24)/(16) * hb.settings.start_offset_right.x - 24,
|
||||
y = hb.settings.start_offset_right.y - hb.settings.vmargin * ((index-1)/2)
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
if format_string == nil then
|
||||
format_string = N("@1: @2/@3")
|
||||
end
|
||||
|
@ -181,6 +184,7 @@ function hb.register_hudbar(identifier, text_color, label, textures, default_sta
|
|||
local state = {}
|
||||
local name = player:get_player_name()
|
||||
local bgscale, iconscale, text, barnumber, bgiconnumber
|
||||
|
||||
if start_max == 0 or start_hidden then
|
||||
bgscale = { x=0, y=0 }
|
||||
else
|
||||
|
@ -197,6 +201,7 @@ function hb.register_hudbar(identifier, text_color, label, textures, default_sta
|
|||
bgiconnumber = hb.settings.statbar_length
|
||||
text = make_label(format_string, format_string_config, label, start_value, start_max)
|
||||
end
|
||||
|
||||
if hb.settings.bar_type == "progress_bar" then
|
||||
ids.bg = player:hud_add({
|
||||
hud_elem_type = "image",
|
||||
|
@ -219,6 +224,7 @@ function hb.register_hudbar(identifier, text_color, label, textures, default_sta
|
|||
})
|
||||
end
|
||||
end
|
||||
|
||||
local bar_image, bgicon, bar_size
|
||||
if hb.settings.bar_type == "progress_bar" then
|
||||
bar_image = textures.bar
|
||||
|
@ -234,10 +240,12 @@ function hb.register_hudbar(identifier, text_color, label, textures, default_sta
|
|||
bgicon = textures.bgicon
|
||||
bar_size = {x=24, y=24}
|
||||
end
|
||||
|
||||
local text2
|
||||
if hb.settings.bar_type == "statbar_modern" then
|
||||
text2 = bgicon
|
||||
end
|
||||
|
||||
ids.bar = player:hud_add({
|
||||
hud_elem_type = "statbar",
|
||||
position = pos,
|
||||
|
@ -247,7 +255,7 @@ function hb.register_hudbar(identifier, text_color, label, textures, default_sta
|
|||
item = bgiconnumber,
|
||||
alignment = {x=-1,y=-1},
|
||||
offset = offset,
|
||||
direction = 0,
|
||||
direction = direction,
|
||||
size = bar_size,
|
||||
z_index = 1,
|
||||
})
|
||||
|
@ -258,7 +266,7 @@ function hb.register_hudbar(identifier, text_color, label, textures, default_sta
|
|||
text = text,
|
||||
alignment = {x=1,y=1},
|
||||
number = text_color,
|
||||
direction = 0,
|
||||
direction = direction,
|
||||
offset = { x = offset.x + 2, y = offset.y - 1},
|
||||
z_index = 2,
|
||||
})
|
||||
|
@ -298,7 +306,7 @@ function hb.register_hudbar(identifier, text_color, label, textures, default_sta
|
|||
hudtable.default_start_max = default_start_max
|
||||
|
||||
hb.hudbars_count= hb.hudbars_count + 1
|
||||
|
||||
|
||||
hb.hudtables[identifier] = hudtable
|
||||
end
|
||||
|
||||
|
@ -359,6 +367,7 @@ function hb.change_hudbar(player, identifier, new_value, new_max_value, new_icon
|
|||
if new_text_color ~= nil then
|
||||
player:hud_change(hudtable.hudids[name].text, "number", new_text_color)
|
||||
end
|
||||
|
||||
else
|
||||
if new_icon ~= nil and hudtable.hudids[name].bar ~= nil then
|
||||
player:hud_change(hudtable.hudids[name].bar, "text", new_icon)
|
||||
|
@ -474,8 +483,8 @@ end
|
|||
|
||||
--register built-in HUD bars
|
||||
if minetest.settings:get_bool("enable_damage") or hb.settings.forceload_default_hudbars then
|
||||
hb.register_hudbar("health", 0xFFFFFF, S("Health"), { bar = "hudbars_bar_health.png", icon = "hudbars_icon_health.png", bgicon = "hudbars_bgicon_health.png" }, 20, 20, false)
|
||||
hb.register_hudbar("breath", 0xFFFFFF, S("Breath"), { bar = "hudbars_bar_breath.png", icon = "hudbars_icon_breath.png", bgicon = "hudbars_bgicon_breath.png" }, 10, 10, true)
|
||||
hb.register_hudbar("health", 0xFFFFFF, S("Health"), { bar = "hudbars_bar_health.png", icon = "hudbars_icon_health.png", bgicon = "hudbars_bgicon_health.png" }, 0, 20, 20, false)
|
||||
hb.register_hudbar("breath", 0xFFFFFF, S("Breath"), { bar = "hudbars_bar_breath.png", icon = "hudbars_icon_breath.png", bgicon = "hudbars_bgicon_breath.png" }, 1, 10, 10, true)
|
||||
end
|
||||
|
||||
local function hide_builtin(player)
|
||||
|
@ -520,7 +529,7 @@ local function update_hud(player, has_damage)
|
|||
--air
|
||||
local breath_max = player:get_properties().breath_max
|
||||
local breath = player:get_breath()
|
||||
|
||||
|
||||
if breath >= breath_max and hb.settings.autohide_breath == true then
|
||||
hb.hide_hudbar(player, "breath")
|
||||
else
|
||||
|
|
|
@ -238,3 +238,20 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
|
|||
awards.show_to(name, name, nil, false)
|
||||
end
|
||||
end)
|
||||
|
||||
|
||||
awards.register_achievement("mcl:stoneAge", {
|
||||
title = S("Stone Age"),
|
||||
description = S("Mine a stone with new pickaxe."),
|
||||
icon = "default_cobble.png",
|
||||
})
|
||||
awards.register_achievement("mcl:hotStuff", {
|
||||
title = S("Hot Stuff"),
|
||||
description = S("Put lava in a bucket."),
|
||||
icon = "bucket_lava.png",
|
||||
})
|
||||
awards.register_achievement("mcl:obsidian", {
|
||||
title = S("Ice Bucket Challenge"),
|
||||
description = S("Obtain an obsidian block."),
|
||||
icon = "default_obsidian.png",
|
||||
})
|
||||
|
|
|
@ -0,0 +1,187 @@
|
|||
mcl_bossbars = {
|
||||
bars = {},
|
||||
huds = {},
|
||||
static = {},
|
||||
colors = {"light_purple", "blue", "red", "green", "yellow", "dark_purple", "white"},
|
||||
max_bars = tonumber(minetest.settings:get("max_bossbars")) or 4
|
||||
}
|
||||
|
||||
function mcl_bossbars.recalculate_colors()
|
||||
local sorted = {}
|
||||
local colors = mcl_bossbars.colors
|
||||
local color_count = #colors
|
||||
local frame_count = color_count * 2
|
||||
for i, color in ipairs(colors) do
|
||||
local idx = i * 2 - 1
|
||||
local image = "mcl_bossbars.png"
|
||||
.. "^[transformR270"
|
||||
.. "^[verticalframe:" .. frame_count .. ":" .. (idx - 1)
|
||||
.. "^(mcl_bossbars_empty.png"
|
||||
.. "^[lowpart:%d:mcl_bossbars.png"
|
||||
.. "^[transformR270"
|
||||
.. "^[verticalframe:" .. frame_count .. ":" .. idx .. ")"
|
||||
local _, hex = mcl_util.get_color(color)
|
||||
sorted[color] = {
|
||||
image = image,
|
||||
hex = hex,
|
||||
}
|
||||
end
|
||||
mcl_bossbars.colors_sorted = sorted
|
||||
end
|
||||
|
||||
local function get_color_info(color, percentage)
|
||||
local cdef = mcl_bossbars.colors_sorted[color]
|
||||
return cdef.hex, string.format(cdef.image, percentage)
|
||||
end
|
||||
|
||||
local last_id = 0
|
||||
|
||||
function mcl_bossbars.add_bar(player, def, dynamic, priority)
|
||||
local name = player:get_player_name()
|
||||
local bars = mcl_bossbars.bars[name]
|
||||
local bar = {text = def.text, priority = priority or 0}
|
||||
bar.color, bar.image = get_color_info(def.color, def.percentage)
|
||||
if dynamic then
|
||||
for _, other in pairs(bars) do
|
||||
if not other.id and other.color == bar.color and (other.original_text or other.text) == bar.text and other.image == bar.image then
|
||||
if not other.count then
|
||||
other.count = 1
|
||||
other.original_text = other.text
|
||||
end
|
||||
other.count = other.count + 1
|
||||
other.text = other.original_text .. " x" .. other.count
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
table.insert(bars, bar)
|
||||
if not dynamic then
|
||||
bar.raw_color = def.color
|
||||
bar.id = last_id + 1
|
||||
last_id = bar.id
|
||||
mcl_bossbars.static[bar.id] = bar
|
||||
return id
|
||||
end
|
||||
end
|
||||
|
||||
function mcl_bossbars.remove_bar(id)
|
||||
mcl_bossbars.static[id].bar.static = false
|
||||
mcl_bossbars.static[id] = nil
|
||||
end
|
||||
|
||||
function mcl_bossbars.update_bar(id, def, priority)
|
||||
local old = mcl_bossbars.static[id]
|
||||
old.color = get_color_info(def.color or old.raw_color, def.percentage or old.percentage)
|
||||
old.text = def.text or old.text
|
||||
old.priority = priority or old.priority
|
||||
end
|
||||
|
||||
function mcl_bossbars.update_boss(luaentity, name, color)
|
||||
local object = luaentity.object
|
||||
local bardef = {
|
||||
text = luaentity.nametag,
|
||||
percentage = math.floor(luaentity.health / luaentity.hp_max * 100),
|
||||
color = color,
|
||||
}
|
||||
if not bardef.text or bardef.text == "" then
|
||||
bardef.text = name
|
||||
end
|
||||
local pos = object:get_pos()
|
||||
for _, player in pairs(minetest.get_connected_players()) do
|
||||
local d = vector.distance(pos, player:get_pos())
|
||||
if d <= 80 then
|
||||
mcl_bossbars.add_bar(player, bardef, true, d)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
minetest.register_on_joinplayer(function(player)
|
||||
local name = player:get_player_name()
|
||||
mcl_bossbars.huds[name] = {}
|
||||
mcl_bossbars.bars[name] = {}
|
||||
end)
|
||||
|
||||
minetest.register_on_leaveplayer(function(player)
|
||||
local name = player:get_player_name()
|
||||
mcl_bossbars.huds[name] = nil
|
||||
for _, bar in pairs(mcl_bossbars.bars[name]) do
|
||||
if bar.id then
|
||||
mcl_bossbars.static[bar.id] = nil
|
||||
end
|
||||
end
|
||||
mcl_bossbars.bars[name] = nil
|
||||
end)
|
||||
|
||||
minetest.register_globalstep(function()
|
||||
for _, player in pairs(minetest.get_connected_players()) do
|
||||
local name = player:get_player_name()
|
||||
local bars = mcl_bossbars.bars[name]
|
||||
local huds = mcl_bossbars.huds[name]
|
||||
table.sort(bars, function(a, b) return a.priority < b.priority end)
|
||||
local huds_new = {}
|
||||
local bars_new = {}
|
||||
local i = 0
|
||||
|
||||
while #huds > 0 or #bars > 0 do
|
||||
local bar = table.remove(bars, 1)
|
||||
local hud = table.remove(huds, 1)
|
||||
|
||||
if bar and bar.id then
|
||||
table.insert(bars_new, bar)
|
||||
end
|
||||
|
||||
if bar and not hud then
|
||||
if i < mcl_bossbars.max_bars then
|
||||
hud = {
|
||||
color = bar.color,
|
||||
image = bar.image,
|
||||
text = bar.text,
|
||||
text_id = player:hud_add({
|
||||
hud_elem_type = "text",
|
||||
text = bar.text,
|
||||
number = bar.color,
|
||||
position = {x = 0.5, y = 0},
|
||||
alignment = {x = 0, y = 1},
|
||||
offset = {x = 0, y = i * 40},
|
||||
}),
|
||||
image_id = player:hud_add({
|
||||
hud_elem_type = "image",
|
||||
text = bar.image,
|
||||
position = {x = 0.5, y = 0},
|
||||
alignment = {x = 0, y = 1},
|
||||
offset = {x = 0, y = i * 40 + 25},
|
||||
scale = {x = 3, y = 3},
|
||||
}),
|
||||
}
|
||||
end
|
||||
elseif hud and not bar then
|
||||
player:hud_remove(hud.text_id)
|
||||
player:hud_remove(hud.image_id)
|
||||
hud = nil
|
||||
else
|
||||
if bar.text ~= hud.text then
|
||||
player:hud_change(hud.text_id, "text", bar.text)
|
||||
hud.text = bar.text
|
||||
end
|
||||
|
||||
if bar.color ~= hud.color then
|
||||
player:hud_change(hud.text_id, "number", bar.color)
|
||||
hud.color = bar.color
|
||||
end
|
||||
|
||||
if bar.image ~= hud.image then
|
||||
player:hud_change(hud.image_id, "text", bar.image)
|
||||
hud.image = bar.image
|
||||
end
|
||||
end
|
||||
|
||||
table.insert(huds_new, hud)
|
||||
i = i + 1
|
||||
end
|
||||
|
||||
mcl_bossbars.huds[name] = huds_new
|
||||
mcl_bossbars.bars[name] = bars_new
|
||||
end
|
||||
end)
|
||||
|
||||
mcl_bossbars.recalculate_colors()
|
|
@ -0,0 +1,4 @@
|
|||
name = mcl_bossbars
|
||||
author = Fleckenstein
|
||||
description = Show enderdragon & wither boss bars. Also allows custom bars.
|
||||
depends = mcl_util, mcl_colors
|
Binary file not shown.
After Width: | Height: | Size: 3.6 KiB |
Binary file not shown.
After Width: | Height: | Size: 3.3 KiB |
|
@ -0,0 +1,209 @@
|
|||
mcl_credits = {
|
||||
players = {},
|
||||
}
|
||||
|
||||
mcl_credits.description = "A faithful Open Source clone of Minecraft"
|
||||
|
||||
-- Sub-lists are sorted by number of commits, but the list should not be rearranged (-> new contributors are just added at the end of the list)
|
||||
mcl_credits.people = {
|
||||
{"Creator of MineClone", 0x0A9400, {
|
||||
"davedevils",
|
||||
}},
|
||||
{"Creator of MineClone2", 0xFBF837, {
|
||||
"Wuzzy",
|
||||
}},
|
||||
{"Maintainers", 0xFF51D5, {
|
||||
"Fleckenstein",
|
||||
"kay27",
|
||||
"oilboi",
|
||||
}},
|
||||
{"Developers", 0xF84355, {
|
||||
"bzoss",
|
||||
"AFCMS",
|
||||
"epCode",
|
||||
"ryvnf",
|
||||
"iliekprogrammar",
|
||||
"MysticTempest",
|
||||
"Rootyjr",
|
||||
"Nicu",
|
||||
"aligator",
|
||||
}},
|
||||
{"Contributors", 0x52FF00, {
|
||||
"Code-Sploit",
|
||||
"Laurent Rocher",
|
||||
"HimbeerserverDE",
|
||||
"TechDudie",
|
||||
"Alexander Minges",
|
||||
"ArTee3",
|
||||
"ZeDique la Ruleta",
|
||||
"pitchum",
|
||||
"wuniversales",
|
||||
"Bu-Gee",
|
||||
"David McMackins II",
|
||||
"Nicholas Niro",
|
||||
"Wouters Dorian",
|
||||
"Blue Blancmange",
|
||||
"Jared Moody",
|
||||
"Li0n",
|
||||
"Midgard",
|
||||
"NO11",
|
||||
"Saku Laesvuori",
|
||||
"Yukitty",
|
||||
"ZedekThePD",
|
||||
"aldum",
|
||||
"dBeans",
|
||||
"nickolas360",
|
||||
"yutyo",
|
||||
"ztianyang",
|
||||
}},
|
||||
{"MineClone5", 0xA60014, {
|
||||
"kay27",
|
||||
"Debiankaios",
|
||||
"epCode",
|
||||
"NO11",
|
||||
"j45",
|
||||
}},
|
||||
{"3D Models", 0x0019FF, {
|
||||
"22i",
|
||||
"tobyplowy",
|
||||
"epCode",
|
||||
}},
|
||||
{"Textures", 0xFF9705, {
|
||||
"XSSheep",
|
||||
"Wuzzy",
|
||||
"kingoscargames",
|
||||
"leorockway",
|
||||
"xMrVizzy",
|
||||
"yutyo"
|
||||
}},
|
||||
{"Translations", 0x00FF60, {
|
||||
"Wuzzy",
|
||||
"Rocher Laurent",
|
||||
"wuniversales",
|
||||
"kay27",
|
||||
"pitchum",
|
||||
}},
|
||||
}
|
||||
|
||||
local function add_hud_element(def, huds, y)
|
||||
def.alignment = {x = 0, y = 0}
|
||||
def.position = {x = 0.5, y = 0}
|
||||
def.offset = {x = 0, y = y}
|
||||
def.z_index = 1001
|
||||
local id = huds.player:hud_add(def)
|
||||
table.insert(huds.ids, id)
|
||||
huds.moving[id] = y
|
||||
return id
|
||||
end
|
||||
|
||||
function mcl_credits.show(player)
|
||||
local name = player:get_player_name()
|
||||
if mcl_credits.players[name] then
|
||||
return
|
||||
end
|
||||
local huds = {
|
||||
new = true, -- workaround for MT < 5.5 (sending hud_add and hud_remove in the same tick)
|
||||
player = player,
|
||||
moving = {},
|
||||
ids = {
|
||||
player:hud_add({
|
||||
hud_elem_type = "image",
|
||||
text = "menu_bg.png",
|
||||
position = {x = 0, y = 0},
|
||||
alignment = {x = 1, y = 1},
|
||||
scale = {x = -100, y = -100},
|
||||
z_index = 1000,
|
||||
}),
|
||||
player:hud_add({
|
||||
hud_elem_type = "text",
|
||||
text = "Sneak to skip",
|
||||
position = {x = 1, y = 1},
|
||||
alignment = {x = -1, y = -1},
|
||||
offset = {x = -5, y = -5},
|
||||
z_index = 1001,
|
||||
number = 0xFFFFFF,
|
||||
})
|
||||
},
|
||||
}
|
||||
add_hud_element({
|
||||
hud_elem_type = "image",
|
||||
text = "mineclone2_logo.png",
|
||||
scale = {x = 1, y = 1},
|
||||
}, huds, 300, 0)
|
||||
add_hud_element({
|
||||
hud_elem_type = "text",
|
||||
text = mcl_credits.description,
|
||||
number = 0x757575,
|
||||
scale = {x = 5, y = 5},
|
||||
}, huds, 350, 0)
|
||||
local y = 450
|
||||
for _, group in ipairs(mcl_credits.people) do
|
||||
add_hud_element({
|
||||
hud_elem_type = "text",
|
||||
text = group[1],
|
||||
number = group[2],
|
||||
scale = {x = 3, y = 3},
|
||||
}, huds, y, 0)
|
||||
y = y + 25
|
||||
for _, name in ipairs(group[3]) do
|
||||
y = y + 25
|
||||
add_hud_element({
|
||||
hud_elem_type = "text",
|
||||
text = name,
|
||||
number = 0xFFFFFF,
|
||||
scale = {x = 1, y = 1},
|
||||
}, huds, y, 0)
|
||||
end
|
||||
y = y + 200
|
||||
end
|
||||
huds.icon = add_hud_element({
|
||||
hud_elem_type = "image",
|
||||
text = "mineclone2_icon.png",
|
||||
scale = {x = 1, y = 1},
|
||||
}, huds, y)
|
||||
mcl_credits.players[name] = huds
|
||||
end
|
||||
|
||||
function mcl_credits.hide(player)
|
||||
local name = player:get_player_name()
|
||||
local huds = mcl_credits.players[name]
|
||||
if huds then
|
||||
for _, id in pairs(huds.ids) do
|
||||
player:hud_remove(id)
|
||||
end
|
||||
end
|
||||
mcl_credits.players[name] = nil
|
||||
end
|
||||
|
||||
minetest.register_on_leaveplayer(function(player)
|
||||
mcl_credits.players[player:get_player_name()] = nil
|
||||
end)
|
||||
|
||||
minetest.register_globalstep(function(dtime)
|
||||
for _, huds in pairs(mcl_credits.players) do
|
||||
local player = huds.player
|
||||
if not huds.new and player:get_player_control().sneak then
|
||||
mcl_credits.hide(player)
|
||||
else
|
||||
local moving = {}
|
||||
local any
|
||||
for id, y in pairs(huds.moving) do
|
||||
y = y - 1
|
||||
if y > -100 then
|
||||
if id == huds.icon then
|
||||
y = math.max(400, y)
|
||||
else
|
||||
any = true
|
||||
end
|
||||
player:hud_change(id, "offset", {x = 0, y = y})
|
||||
moving[id] = y
|
||||
end
|
||||
end
|
||||
if not any then
|
||||
mcl_credits.hide(player)
|
||||
end
|
||||
huds.moving = moving
|
||||
end
|
||||
huds.new = false
|
||||
end
|
||||
end)
|
|
@ -0,0 +1,3 @@
|
|||
name = mcl_credits
|
||||
author = Fleckenstein
|
||||
description = Show a HUD containing the credits
|
Binary file not shown.
After Width: | Height: | Size: 3.9 KiB |
Binary file not shown.
After Width: | Height: | Size: 76 KiB |
|
@ -1,5 +1,8 @@
|
|||
local S = minetest.get_translator("mcl_death_messages")
|
||||
local N = function(s) return s end
|
||||
local C = minetest.colorize
|
||||
|
||||
local color_skyblue = mcl_colors.AQUA
|
||||
|
||||
local function get_tool_name(item)
|
||||
local name = item:get_meta():get_string("name")
|
||||
|
@ -41,6 +44,9 @@ local msgs = {
|
|||
["murder"] = {
|
||||
N("@1 was slain by @2 using [@3]"),
|
||||
},
|
||||
["murder_hand"] = {
|
||||
N("@1 was slain by @2"),
|
||||
},
|
||||
["murder_any"] = {
|
||||
N("@1 was killed."),
|
||||
},
|
||||
|
@ -131,7 +137,7 @@ local last_damages = { }
|
|||
|
||||
minetest.register_on_dieplayer(function(player, reason)
|
||||
-- Death message
|
||||
local message = minetest.settings:get_bool("mcl_showDeathMessages")
|
||||
local message = minetest.settings:get_bool("mcl_showDeathMessages") --Maybe cache the setting?
|
||||
if message == nil then
|
||||
message = true
|
||||
end
|
||||
|
@ -201,7 +207,11 @@ minetest.register_on_dieplayer(function(player, reason)
|
|||
elseif hitter:is_player() then
|
||||
hittername = hitter:get_player_name()
|
||||
if hittername ~= nil then
|
||||
msg = dmsg("murder", name, hittername, minetest.colorize("#00FFFF", hitter_toolname))
|
||||
if hitter_toolname == "" then
|
||||
msg = dmsg("murder_hand", name, hittername)
|
||||
else
|
||||
msg = dmsg("murder", name, hittername, C(color_skyblue, hitter_toolname))
|
||||
end
|
||||
else
|
||||
msg = dmsg("murder_any", name)
|
||||
end
|
||||
|
@ -229,7 +239,7 @@ minetest.register_on_dieplayer(function(player, reason)
|
|||
if shooter == nil then
|
||||
msg = dmsg("arrow", name)
|
||||
elseif shooter:is_player() then
|
||||
msg = dmsg("arrow_name", name, shooter:get_player_name(), minetest.colorize("#00FFFF", get_tool_name(shooter:get_wielded_item())))
|
||||
msg = dmsg("arrow_name", name, shooter:get_player_name(), C(color_skyblue, get_tool_name(shooter:get_wielded_item())))
|
||||
elseif s_ent and s_ent._cmi_is_mob then
|
||||
if s_ent.nametag ~= "" then
|
||||
msg = dmsg("arrow_name", name, shooter:get_player_name(), get_tool_name(shooter:get_wielded_item()))
|
||||
|
|
|
@ -56,3 +56,4 @@ A ghast scared @1 to death.=Ein Ghast hat @1 zu Tode erschrocken.
|
|||
@1 was killed by a baby husk.=@1 wurde von einem Wüstenzombiebaby getötet.
|
||||
@1 was killed by a zombie pigman.=@1 wurde von einem Schweinezombie getötet.
|
||||
@1 was killed by a baby zombie pigman.=@1 wurde von einem Schweinezombiebaby getötet.
|
||||
@1 was slain by @2.=
|
||||
|
|
|
@ -55,3 +55,4 @@ A ghast scared @1 to death.=Se ha asustado @1 hasta morir.
|
|||
@1 was killed by a baby husk.=@1 fue asesinado por un bebé husk.
|
||||
@1 was killed by a zombie pigman.=@1 fue asesinado por un cerdo zombie.
|
||||
@1 was killed by a baby zombie pigman.=@1 fue asesinado por un bebé cerdo zombie.
|
||||
@1 was slain by @2.=
|
||||
|
|
|
@ -56,3 +56,4 @@ A ghast scared @1 to death.=Un ghast a éffrayé @1 à mort.
|
|||
@1 was killed by a baby husk.=@1 a été tué par un bébé zombie momie.
|
||||
@1 was killed by a zombie pigman.=@1 a été tué par un zombie-couchon.
|
||||
@1 was killed by a baby zombie pigman.=@1 a été tué par un bébé zombie-couchon
|
||||
@1 was slain by @2.=
|
||||
|
|
|
@ -56,3 +56,4 @@ A ghast scared @1 to death.=Гаст напугал @1 до смерти.
|
|||
@1 was killed by a baby husk.=@1 был(а) убит(а) машылом-кадавром.
|
||||
@1 was killed by a zombie pigman.=@1 был(а) убит(а) зомби-свиночеловеком.
|
||||
@1 was killed by a baby zombie pigman.=@1 был(а) убит(а) малышом-зомби-свиночеловеком.
|
||||
@1 was slain by @2.=
|
||||
|
|
|
@ -56,3 +56,4 @@ A ghast scared @1 to death.=
|
|||
@1 was killed by a baby husk.=
|
||||
@1 was killed by a zombie pigman.=
|
||||
@1 was killed by a baby zombie pigman.=
|
||||
@1 was slain by @2.=
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
name = mcl_death_messages
|
||||
author = 4Evergreen4
|
||||
description = Shows messages in chat when a player dies.
|
||||
depends = mcl_colors
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue